Coverage Report

Created: 2025-06-24 06:45

/src/binutils-gdb/bfd/mach-o-x86-64.c
Line
Count
Source (jump to first uncovered line)
1
/* Intel x86-64 Mach-O support for BFD.
2
   Copyright (C) 2010-2025 Free Software Foundation, Inc.
3
4
   This file is part of BFD, the Binary File Descriptor library.
5
6
   This program is free software; you can redistribute it and/or modify
7
   it under the terms of the GNU General Public License as published by
8
   the Free Software Foundation; either version 3 of the License, or
9
   (at your option) any later version.
10
11
   This program is distributed in the hope that it will be useful,
12
   but WITHOUT ANY WARRANTY; without even the implied warranty of
13
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
   GNU General Public License for more details.
15
16
   You should have received a copy of the GNU General Public License
17
   along with this program; if not, write to the Free Software
18
   Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
19
   MA 02110-1301, USA.  */
20
21
#include "sysdep.h"
22
#include "bfd.h"
23
#include "libbfd.h"
24
#include "libiberty.h"
25
#include "mach-o.h"
26
#include "mach-o/x86-64.h"
27
28
#define bfd_mach_o_object_p bfd_mach_o_x86_64_object_p
29
#define bfd_mach_o_core_p bfd_mach_o_x86_64_core_p
30
#define bfd_mach_o_mkobject bfd_mach_o_x86_64_mkobject
31
32
static bfd_cleanup
33
bfd_mach_o_x86_64_object_p (bfd *abfd)
34
3.43M
{
35
3.43M
  return bfd_mach_o_header_p (abfd, 0, 0, BFD_MACH_O_CPU_TYPE_X86_64);
36
3.43M
}
37
38
static bfd_cleanup
39
bfd_mach_o_x86_64_core_p (bfd *abfd)
40
16.6k
{
41
16.6k
  return bfd_mach_o_header_p (abfd, 0,
42
16.6k
            BFD_MACH_O_MH_CORE, BFD_MACH_O_CPU_TYPE_X86_64);
43
16.6k
}
44
45
static bool
46
bfd_mach_o_x86_64_mkobject (bfd *abfd)
47
15
{
48
15
  bfd_mach_o_data_struct *mdata;
49
50
15
  if (!bfd_mach_o_mkobject_init (abfd))
51
0
    return false;
52
53
15
  mdata = bfd_mach_o_get_data (abfd);
54
15
  mdata->header.magic = BFD_MACH_O_MH_MAGIC_64;
55
15
  mdata->header.cputype = BFD_MACH_O_CPU_TYPE_X86_64;
56
15
  mdata->header.cpusubtype =
57
15
    BFD_MACH_O_CPU_SUBTYPE_X86_ALL | BFD_MACH_O_CPU_SUBTYPE_LIB64;
58
15
  mdata->header.byteorder = BFD_ENDIAN_LITTLE;
59
15
  mdata->header.version = 2;
60
61
15
  return true;
62
15
}
63
64
/* In case we're on a 32-bit machine, construct a 64-bit "-1" value.  */
65
#define MINUS_ONE (~ (bfd_vma) 0)
66
67
static reloc_howto_type x86_64_howto_table[]=
68
{
69
  /* 0 */
70
  HOWTO(BFD_RELOC_64, 0, 8, 64, false, 0,
71
  complain_overflow_bitfield,
72
  NULL, "64",
73
  false, MINUS_ONE, MINUS_ONE, false),
74
  HOWTO(BFD_RELOC_32, 0, 4, 32, false, 0,
75
  complain_overflow_bitfield,
76
  NULL, "32",
77
  false, 0xffffffff, 0xffffffff, false),
78
  HOWTO(BFD_RELOC_32_PCREL, 0, 4, 32, true, 0,
79
  complain_overflow_bitfield,
80
  NULL, "DISP32",
81
  false, 0xffffffff, 0xffffffff, true),
82
  HOWTO(BFD_RELOC_MACH_O_X86_64_PCREL32_1, 0, 4, 32, true, 0,
83
  complain_overflow_bitfield,
84
  NULL, "DISP32_1",
85
  false, 0xffffffff, 0xffffffff, true),
86
  /* 4 */
87
  HOWTO(BFD_RELOC_MACH_O_X86_64_PCREL32_2, 0, 4, 32, true, 0,
88
  complain_overflow_bitfield,
89
  NULL, "DISP32_2",
90
  false, 0xffffffff, 0xffffffff, true),
91
  HOWTO(BFD_RELOC_MACH_O_X86_64_PCREL32_4, 0, 4, 32, true, 0,
92
  complain_overflow_bitfield,
93
  NULL, "DISP32_4",
94
  false, 0xffffffff, 0xffffffff, true),
95
  HOWTO(BFD_RELOC_MACH_O_X86_64_BRANCH32, 0, 4, 32, true, 0,
96
  complain_overflow_bitfield,
97
  NULL, "BRANCH32",
98
  false, 0xffffffff, 0xffffffff, true),
99
  HOWTO(BFD_RELOC_MACH_O_X86_64_GOT_LOAD, 0, 4, 32, true, 0,
100
  complain_overflow_bitfield,
101
  NULL, "GOT_LOAD",
102
  false, 0xffffffff, 0xffffffff, true),
103
  /* 8 */
104
  HOWTO(BFD_RELOC_MACH_O_SUBTRACTOR32, 0, 4, 32, false, 0,
105
  complain_overflow_bitfield,
106
  NULL, "SUBTRACTOR32",
107
  false, 0xffffffff, 0xffffffff, false),
108
  HOWTO(BFD_RELOC_MACH_O_SUBTRACTOR64, 0, 8, 64, false, 0,
109
  complain_overflow_bitfield,
110
  NULL, "SUBTRACTOR64",
111
  false, MINUS_ONE, MINUS_ONE, false),
112
  HOWTO(BFD_RELOC_MACH_O_X86_64_GOT, 0, 4, 32, true, 0,
113
  complain_overflow_bitfield,
114
  NULL, "GOT",
115
  false, 0xffffffff, 0xffffffff, true),
116
  HOWTO(BFD_RELOC_MACH_O_X86_64_BRANCH8, 0, 1, 8, true, 0,
117
  complain_overflow_bitfield,
118
  NULL, "BRANCH8",
119
  false, 0xff, 0xff, true),
120
  /* 12 */
121
  HOWTO(BFD_RELOC_MACH_O_X86_64_TLV, 0, 4, 32, true, 0,
122
  complain_overflow_bitfield,
123
  NULL, "TLV",
124
  false, 0xffffffff, 0xffffffff, true),
125
};
126
127
static bool
128
bfd_mach_o_x86_64_canonicalize_one_reloc (bfd *       abfd,
129
            struct mach_o_reloc_info_external * raw,
130
            arelent *   res,
131
            asymbol **  syms,
132
            arelent *   res_base ATTRIBUTE_UNUSED)
133
2.19M
{
134
2.19M
  bfd_mach_o_reloc_info reloc;
135
136
2.19M
  if (!bfd_mach_o_pre_canonicalize_one_reloc (abfd, raw, &reloc, res, syms))
137
17.5k
    return false;
138
139
  /* On x86-64, scattered relocs are not used.  */
140
2.17M
  if (reloc.r_scattered)
141
18.9k
    return false;
142
143
2.15M
  switch (reloc.r_type)
144
2.15M
    {
145
21.7k
    case BFD_MACH_O_X86_64_RELOC_UNSIGNED:
146
21.7k
      if (reloc.r_pcrel)
147
575
  return false;
148
21.1k
      switch (reloc.r_length)
149
21.1k
  {
150
736
  case 2:
151
736
    res->howto = &x86_64_howto_table[1];
152
736
    return true;
153
3.94k
  case 3:
154
3.94k
    res->howto = &x86_64_howto_table[0];
155
3.94k
    return true;
156
16.4k
  default:
157
16.4k
    return false;
158
21.1k
  }
159
2.37k
    case BFD_MACH_O_X86_64_RELOC_SIGNED:
160
2.37k
      if (reloc.r_length == 2 && reloc.r_pcrel)
161
264
  {
162
264
    res->howto = &x86_64_howto_table[2];
163
264
    return true;
164
264
  }
165
2.11k
      break;
166
2.11k
    case BFD_MACH_O_X86_64_RELOC_BRANCH:
167
1.49k
      if (!reloc.r_pcrel)
168
824
  return false;
169
673
      switch (reloc.r_length)
170
673
  {
171
241
  case 2:
172
241
    res->howto = &x86_64_howto_table[6];
173
241
    return true;
174
432
  default:
175
432
    return false;
176
673
  }
177
0
      break;
178
2.09M
    case BFD_MACH_O_X86_64_RELOC_GOT_LOAD:
179
2.09M
      if (reloc.r_length == 2 && reloc.r_pcrel && reloc.r_extern)
180
2.09M
  {
181
2.09M
    res->howto = &x86_64_howto_table[7];
182
2.09M
    return true;
183
2.09M
  }
184
464
      break;
185
1.57k
    case BFD_MACH_O_X86_64_RELOC_GOT:
186
1.57k
      if (reloc.r_length == 2 && reloc.r_pcrel && reloc.r_extern)
187
518
  {
188
518
    res->howto = &x86_64_howto_table[10];
189
518
    return true;
190
518
  }
191
1.05k
      break;
192
28.2k
    case BFD_MACH_O_X86_64_RELOC_SUBTRACTOR:
193
28.2k
      if (reloc.r_pcrel)
194
613
  return false;
195
27.6k
      switch (reloc.r_length)
196
27.6k
  {
197
26.2k
  case 2:
198
26.2k
    res->howto = &x86_64_howto_table[8];
199
26.2k
    return true;
200
357
  case 3:
201
357
    res->howto = &x86_64_howto_table[9];
202
357
    return true;
203
983
  default:
204
983
    return false;
205
27.6k
  }
206
0
      break;
207
1.72k
    case BFD_MACH_O_X86_64_RELOC_SIGNED_1:
208
1.72k
      if (reloc.r_length == 2 && reloc.r_pcrel)
209
416
  {
210
416
    res->howto = &x86_64_howto_table[3];
211
416
    return true;
212
416
  }
213
1.31k
      break;
214
2.64k
    case BFD_MACH_O_X86_64_RELOC_SIGNED_2:
215
2.64k
      if (reloc.r_length == 2 && reloc.r_pcrel)
216
1.76k
  {
217
1.76k
    res->howto = &x86_64_howto_table[4];
218
1.76k
    return true;
219
1.76k
  }
220
880
      break;
221
880
    case BFD_MACH_O_X86_64_RELOC_SIGNED_4:
222
508
      if (reloc.r_length == 2 && reloc.r_pcrel)
223
98
  {
224
98
    res->howto = &x86_64_howto_table[5];
225
98
    return true;
226
98
  }
227
410
      break;
228
496
    case BFD_MACH_O_X86_64_RELOC_TLV:
229
496
      if (reloc.r_length == 2 && reloc.r_pcrel && reloc.r_extern)
230
89
  {
231
89
    res->howto = &x86_64_howto_table[12];
232
89
    return true;
233
89
  }
234
407
      break;
235
2.75k
    default:
236
2.75k
      return false;
237
2.15M
    }
238
6.64k
  return false;
239
2.15M
}
240
241
static bool
242
bfd_mach_o_x86_64_swap_reloc_out (arelent *rel, bfd_mach_o_reloc_info *rinfo)
243
0
{
244
0
  rinfo->r_address = rel->address;
245
0
  rinfo->r_scattered = 0;
246
0
  switch (rel->howto->type)
247
0
    {
248
0
    case BFD_RELOC_32:
249
0
      rinfo->r_type = BFD_MACH_O_X86_64_RELOC_UNSIGNED;
250
0
      rinfo->r_pcrel = 0;
251
0
      rinfo->r_length = 2;
252
0
      break;
253
0
    case BFD_RELOC_64:
254
0
      rinfo->r_type = BFD_MACH_O_X86_64_RELOC_UNSIGNED;
255
0
      rinfo->r_pcrel = 0;
256
0
      rinfo->r_length = 3;
257
0
      break;
258
0
    case BFD_RELOC_32_PCREL:
259
0
      rinfo->r_type = BFD_MACH_O_X86_64_RELOC_SIGNED;
260
0
      rinfo->r_pcrel = 1;
261
0
      rinfo->r_length = 2;
262
0
      break;
263
0
    case BFD_RELOC_MACH_O_X86_64_PCREL32_1:
264
0
      rinfo->r_type = BFD_MACH_O_X86_64_RELOC_SIGNED_1;
265
0
      rinfo->r_pcrel = 1;
266
0
      rinfo->r_length = 2;
267
0
      break;
268
0
    case BFD_RELOC_MACH_O_X86_64_PCREL32_2:
269
0
      rinfo->r_type = BFD_MACH_O_X86_64_RELOC_SIGNED_2;
270
0
      rinfo->r_pcrel = 1;
271
0
      rinfo->r_length = 2;
272
0
      break;
273
0
    case BFD_RELOC_MACH_O_X86_64_PCREL32_4:
274
0
      rinfo->r_type = BFD_MACH_O_X86_64_RELOC_SIGNED_4;
275
0
      rinfo->r_pcrel = 1;
276
0
      rinfo->r_length = 2;
277
0
      break;
278
0
    case BFD_RELOC_MACH_O_X86_64_BRANCH32:
279
0
      rinfo->r_type = BFD_MACH_O_X86_64_RELOC_BRANCH;
280
0
      rinfo->r_pcrel = 1;
281
0
      rinfo->r_length = 2;
282
0
      break;
283
0
    case BFD_RELOC_MACH_O_SUBTRACTOR32:
284
0
      rinfo->r_type = BFD_MACH_O_X86_64_RELOC_SUBTRACTOR;
285
0
      rinfo->r_pcrel = 0;
286
0
      rinfo->r_length = 2;
287
0
      break;
288
0
    case BFD_RELOC_MACH_O_SUBTRACTOR64:
289
0
      rinfo->r_type = BFD_MACH_O_X86_64_RELOC_SUBTRACTOR;
290
0
      rinfo->r_pcrel = 0;
291
0
      rinfo->r_length = 3;
292
0
      break;
293
0
    case BFD_RELOC_MACH_O_X86_64_GOT:
294
0
      rinfo->r_type = BFD_MACH_O_X86_64_RELOC_GOT;
295
0
      rinfo->r_pcrel = 1;
296
0
      rinfo->r_length = 2;
297
0
      break;
298
0
    case BFD_RELOC_MACH_O_X86_64_GOT_LOAD:
299
0
      rinfo->r_type = BFD_MACH_O_X86_64_RELOC_GOT_LOAD;
300
0
      rinfo->r_pcrel = 1;
301
0
      rinfo->r_length = 2;
302
0
      break;
303
0
    case BFD_RELOC_MACH_O_X86_64_TLV:
304
0
      rinfo->r_type = BFD_MACH_O_X86_64_RELOC_TLV;
305
0
      rinfo->r_pcrel = 1;
306
0
      rinfo->r_length = 2;
307
0
      break;
308
0
    default:
309
0
      return false;
310
0
    }
311
0
  if ((*rel->sym_ptr_ptr)->flags & BSF_SECTION_SYM)
312
0
    {
313
0
      rinfo->r_extern = 0;
314
0
      rinfo->r_value =
315
0
  (*rel->sym_ptr_ptr)->section->output_section->target_index;
316
0
    }
317
0
  else
318
0
    {
319
0
      rinfo->r_extern = 1;
320
0
      rinfo->r_value = (*rel->sym_ptr_ptr)->udata.i;
321
0
    }
322
0
  return true;
323
0
}
324
325
static reloc_howto_type *
326
bfd_mach_o_x86_64_bfd_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
327
           bfd_reloc_code_real_type code)
328
0
{
329
0
  unsigned int i;
330
331
0
  for (i = 0;
332
0
       i < sizeof (x86_64_howto_table) / sizeof (*x86_64_howto_table);
333
0
       i++)
334
0
    if (code == x86_64_howto_table[i].type)
335
0
      return &x86_64_howto_table[i];
336
0
  return NULL;
337
0
}
338
339
static reloc_howto_type *
340
bfd_mach_o_x86_64_bfd_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED,
341
           const char *name ATTRIBUTE_UNUSED)
342
0
{
343
0
  return NULL;
344
0
}
345
346
static bool
347
bfd_mach_o_section_type_valid_for_x86_64 (unsigned long val)
348
0
{
349
0
  if (val == BFD_MACH_O_S_NON_LAZY_SYMBOL_POINTERS
350
0
      || val == BFD_MACH_O_S_LAZY_SYMBOL_POINTERS
351
0
      || val == BFD_MACH_O_S_SYMBOL_STUBS)
352
0
    return false;
353
0
  return true;
354
0
}
355
356
/* We want to bump the alignment of some sections.  */
357
static const mach_o_section_name_xlat text_section_names_xlat[] =
358
  {
359
    { ".eh_frame",        "__eh_frame",
360
  SEC_READONLY | SEC_DATA | SEC_LOAD, BFD_MACH_O_S_COALESCED,
361
  BFD_MACH_O_S_ATTR_LIVE_SUPPORT
362
  | BFD_MACH_O_S_ATTR_STRIP_STATIC_SYMS
363
  | BFD_MACH_O_S_ATTR_NO_TOC,   3},
364
    { NULL, NULL, 0, 0, 0, 0}
365
  };
366
367
const mach_o_segment_name_xlat mach_o_x86_64_segsec_names_xlat[] =
368
  {
369
    { "__TEXT", text_section_names_xlat },
370
    { NULL, NULL }
371
  };
372
373
#define bfd_mach_o_canonicalize_one_reloc bfd_mach_o_x86_64_canonicalize_one_reloc
374
#define bfd_mach_o_swap_reloc_out bfd_mach_o_x86_64_swap_reloc_out
375
376
#define bfd_mach_o_bfd_reloc_type_lookup bfd_mach_o_x86_64_bfd_reloc_type_lookup
377
#define bfd_mach_o_bfd_reloc_name_lookup bfd_mach_o_x86_64_bfd_reloc_name_lookup
378
#define bfd_mach_o_print_thread NULL
379
#define bfd_mach_o_tgt_seg_table mach_o_x86_64_segsec_names_xlat
380
#define bfd_mach_o_section_type_valid_for_tgt bfd_mach_o_section_type_valid_for_x86_64
381
382
#define TARGET_NAME   x86_64_mach_o_vec
383
#define TARGET_STRING   "mach-o-x86-64"
384
#define TARGET_ARCHITECTURE bfd_arch_i386
385
#define TARGET_PAGESIZE   4096
386
#define TARGET_BIG_ENDIAN 0
387
#define TARGET_ARCHIVE    0
388
#define TARGET_PRIORITY   0
389
#include "mach-o-target.c"