aboutsummaryrefslogtreecommitdiff
path: root/bfd/elfxx-aarch64.h
blob: 506f4a93c9d7cd7b99d29f2c4a5fbd6b965af232 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
/* AArch64-specific backend routines.
   Copyright (C) 2009-2025 Free Software Foundation, Inc.
   Contributed by ARM Ltd.

   This file is part of BFD, the Binary File Descriptor library.

   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 3 of the License, or
   (at your option) any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program; see the file COPYING3. If not,
   see <http://www.gnu.org/licenses/>.  */

extern void bfd_elf64_aarch64_init_maps
  (bfd *);

extern void bfd_elf32_aarch64_init_maps
  (bfd *);

/* Types of PLTs based on the level of security.  This would be a
   bit-mask to denote which of the combinations of security features
   are enabled:
   - No security feature PLTs
   - PLTs with BTI instruction
   - PLTs with PAC instruction
*/
typedef enum
{
  PLT_NORMAL	= 0x0,  /* Normal plts.  */
  PLT_BTI	= 0x1,  /* plts with BTI.  */
  PLT_PAC	= 0x2,  /* plts with pointer authentication.  */
  PLT_BTI_PAC	= PLT_BTI | PLT_PAC
} aarch64_plt_type;

/* Indicates whether the linker should generate warnings, errors, or nothing
   when input objects are missing GNU feature property markings and the output
   has the markings.  */
typedef enum
{
  MARKING_NONE	= 0,  /* Does not emit any warning/error messages.  */
  MARKING_WARN	= 1,  /* Emit warning when the input objects are missing GNU
			 feature property markings, and the output has the
			 markings.  */
  MARKING_ERROR	= 2,  /* Emit error when the input objects are missing GNU
			 feature property markings, and the output has the
			 markings.  */
  MARKING_UNSET = 3,  /* The only purpose of this value is to simulate an
			 optional to detect when the value was not initialized
			 from the command line.  */
} aarch64_feature_marking_report;

/* To indicate whether GNU_PROPERTY_AARCH64_FEATURE_1_GCS bit is
   enabled/disabled on the output when -z gcs linker
   command line option is passed.  */
typedef enum
{
  GCS_NEVER	= 0,  /* gcs is disabled on output.  */
  GCS_IMPLICIT  = 1,  /* gcs is deduced from input object.  */
  GCS_ALWAYS	= 2,  /* gsc is enabled on output.  */
} aarch64_gcs_type;

/* A structure to encompass all information about software protections coming
   from BTI, PAC and GCS related command line options.  */
struct aarch64_protection_opts
{
  /* PLT type to use depending on the selected software proctections.  */
  aarch64_plt_type plt_type;

  /* Report level for BTI issues.  */
  aarch64_feature_marking_report bti_report;

  /* Look-up mode for GCS property.  */
  aarch64_gcs_type gcs_type;

  /* Report level for GCS issues.  */
  aarch64_feature_marking_report gcs_report;

  /* Report level for GCS issues with dynamic inputs.  */
  aarch64_feature_marking_report gcs_report_dynamic;
};
typedef struct aarch64_protection_opts aarch64_protection_opts;

struct elf_aarch64_local_symbol;
struct elf_aarch64_obj_tdata
{
  struct elf_obj_tdata root;

  /* local symbol descriptors */
  struct elf_aarch64_local_symbol *locals;

  /* Zero to warn when linking objects with incompatible enum sizes.  */
  int no_enum_size_warning;

  /* Zero to warn when linking objects with incompatible wchar_t sizes.  */
  int no_wchar_size_warning;

  /* All GNU_PROPERTY_AARCH64_FEATURE_1_AND properties.  */
  uint32_t gnu_property_aarch64_feature_1_and;

  /* Software protections options.  */
  struct aarch64_protection_opts sw_protections;

  /* Number of reported BTI issues.  */
  int n_bti_issues;

  /* Number of reported GCS issues for non-dynamic objects.  */
  int n_gcs_issues;

  /* Number of reported GCS issues for dynamic objects.  */
  int n_gcs_dynamic_issues;
};

#define elf_aarch64_tdata(bfd)				\
  ((struct elf_aarch64_obj_tdata *) (bfd)->tdata.any)

/* An enum to define what kind of erratum fixes we should apply.  This gives the
   user a bit more control over the sequences we generate.  */
typedef enum
{
  ERRAT_NONE  = (1 << 0),  /* No erratum workarounds allowed.  */
  ERRAT_ADR   = (1 << 1),  /* Erratum workarounds using ADR allowed.  */
  ERRAT_ADRP  = (1 << 2),  /* Erratum workarounds using ADRP are allowed.  */
} erratum_84319_opts;

extern void bfd_elf64_aarch64_set_options
  (bfd *, struct bfd_link_info *, int, int, int, int, erratum_84319_opts, int,
   const aarch64_protection_opts *);

extern void bfd_elf32_aarch64_set_options
  (bfd *, struct bfd_link_info *, int, int, int, int, erratum_84319_opts, int,
   const aarch64_protection_opts *);

/* AArch64 stub generation support for ELF64.  Called from the linker.  */
extern int elf64_aarch64_setup_section_lists
  (bfd *, struct bfd_link_info *);
extern void elf64_aarch64_next_input_section
  (struct bfd_link_info *, struct bfd_section *);
extern bool elf64_aarch64_size_stubs
  (bfd *, bfd *, struct bfd_link_info *, bfd_signed_vma,
   struct bfd_section * (*) (const char *, struct bfd_section *),
   void (*) (void));
extern bool elf64_aarch64_build_stubs
  (struct bfd_link_info *);
/* AArch64 stub generation support for ELF32.  Called from the linker.  */
extern int elf32_aarch64_setup_section_lists
  (bfd *, struct bfd_link_info *);
extern void elf32_aarch64_next_input_section
  (struct bfd_link_info *, struct bfd_section *);
extern bool elf32_aarch64_size_stubs
  (bfd *, bfd *, struct bfd_link_info *, bfd_signed_vma,
   struct bfd_section * (*) (const char *, struct bfd_section *),
   void (*) (void));
extern bool elf32_aarch64_build_stubs
  (struct bfd_link_info *);

/* AArch64 relative relocation packing support for ELF64.  */
extern bool elf64_aarch64_size_relative_relocs
  (struct bfd_link_info *, bool *);
extern bool elf64_aarch64_finish_relative_relocs
  (struct bfd_link_info *);
/* AArch64 relative relocation packing support for ELF32.  */
extern bool elf32_aarch64_size_relative_relocs
  (struct bfd_link_info *, bool *);
extern bool elf32_aarch64_finish_relative_relocs
  (struct bfd_link_info *);

/* Take the PAGE component of an address or offset.  */
#define PG(x)	     ((x) & ~ (bfd_vma) 0xfff)
#define PG_OFFSET(x) ((x) &   (bfd_vma) 0xfff)

#define AARCH64_ADR_OP		0x10000000
#define AARCH64_ADRP_OP		0x90000000
#define AARCH64_ADRP_OP_MASK	0x9F000000

extern bfd_signed_vma
_bfd_aarch64_sign_extend (bfd_vma, int);

extern uint32_t
_bfd_aarch64_decode_adrp_imm (uint32_t);

extern uint32_t
_bfd_aarch64_reencode_adr_imm (uint32_t, uint32_t);

extern bfd_reloc_status_type
_bfd_aarch64_elf_put_addend (bfd *, bfd_byte *, bfd_reloc_code_real_type,
			     reloc_howto_type *, bfd_signed_vma);

extern bfd_vma
_bfd_aarch64_elf_resolve_relocation (bfd *, bfd_reloc_code_real_type, bfd_vma,
				     bfd_vma, bfd_vma, bool);

extern bool
_bfd_aarch64_elf_grok_prstatus (bfd *, Elf_Internal_Note *);

extern bool
_bfd_aarch64_elf_grok_psinfo (bfd *, Elf_Internal_Note *);

extern char *
_bfd_aarch64_elf_write_core_note (bfd *, char *, int *, int, ...);

#define elf_backend_grok_prstatus	_bfd_aarch64_elf_grok_prstatus
#define elf_backend_grok_psinfo		_bfd_aarch64_elf_grok_psinfo
#define elf_backend_write_core_note	_bfd_aarch64_elf_write_core_note

extern bfd *
_bfd_aarch64_elf_link_setup_gnu_properties (struct bfd_link_info *);

extern enum elf_property_kind
_bfd_aarch64_elf_parse_gnu_properties (bfd *, unsigned int,
				       bfd_byte *, unsigned int);

extern bool
_bfd_aarch64_elf_merge_gnu_properties (struct bfd_link_info *, bfd *,
				       elf_property *, elf_property *,
				       uint32_t);

extern void
_bfd_aarch64_elf_check_bti_report (struct bfd_link_info *, bfd *);

extern void
_bfd_aarch64_elf_check_gcs_report (struct bfd_link_info *, bfd *);

extern void
_bfd_aarch64_elf_link_fixup_gnu_properties (struct bfd_link_info *,
					    elf_property_list **);

#define elf_backend_parse_gnu_properties	\
  _bfd_aarch64_elf_parse_gnu_properties

#define elf_backend_fixup_gnu_properties	\
  _bfd_aarch64_elf_link_fixup_gnu_properties