Coverage Report

Created: 2023-08-28 06:23

/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-2023 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
0
{
35
0
  return bfd_mach_o_header_p (abfd, 0, 0, BFD_MACH_O_CPU_TYPE_X86_64);
36
0
}
37
38
static bfd_cleanup
39
bfd_mach_o_x86_64_core_p (bfd *abfd)
40
0
{
41
0
  return bfd_mach_o_header_p (abfd, 0,
42
0
            BFD_MACH_O_MH_CORE, BFD_MACH_O_CPU_TYPE_X86_64);
43
0
}
44
45
static bool
46
bfd_mach_o_x86_64_mkobject (bfd *abfd)
47
0
{
48
0
  bfd_mach_o_data_struct *mdata;
49
50
0
  if (!bfd_mach_o_mkobject_init (abfd))
51
0
    return false;
52
53
0
  mdata = bfd_mach_o_get_data (abfd);
54
0
  mdata->header.magic = BFD_MACH_O_MH_MAGIC_64;
55
0
  mdata->header.cputype = BFD_MACH_O_CPU_TYPE_X86_64;
56
0
  mdata->header.cpusubtype =
57
0
    BFD_MACH_O_CPU_SUBTYPE_X86_ALL | BFD_MACH_O_CPU_SUBTYPE_LIB64;
58
0
  mdata->header.byteorder = BFD_ENDIAN_LITTLE;
59
0
  mdata->header.version = 2;
60
61
0
  return true;
62
0
}
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
0
{
134
0
  bfd_mach_o_reloc_info reloc;
135
136
0
  if (!bfd_mach_o_pre_canonicalize_one_reloc (abfd, raw, &reloc, res, syms))
137
0
    return false;
138
139
  /* On x86-64, scattered relocs are not used.  */
140
0
  if (reloc.r_scattered)
141
0
    return false;
142
143
0
  switch (reloc.r_type)
144
0
    {
145
0
    case BFD_MACH_O_X86_64_RELOC_UNSIGNED:
146
0
      if (reloc.r_pcrel)
147
0
  return false;
148
0
      switch (reloc.r_length)
149
0
  {
150
0
  case 2:
151
0
    res->howto = &x86_64_howto_table[1];
152
0
    return true;
153
0
  case 3:
154
0
    res->howto = &x86_64_howto_table[0];
155
0
    return true;
156
0
  default:
157
0
    return false;
158
0
  }
159
0
    case BFD_MACH_O_X86_64_RELOC_SIGNED:
160
0
      if (reloc.r_length == 2 && reloc.r_pcrel)
161
0
  {
162
0
    res->howto = &x86_64_howto_table[2];
163
0
    return true;
164
0
  }
165
0
      break;
166
0
    case BFD_MACH_O_X86_64_RELOC_BRANCH:
167
0
      if (!reloc.r_pcrel)
168
0
  return false;
169
0
      switch (reloc.r_length)
170
0
  {
171
0
  case 2:
172
0
    res->howto = &x86_64_howto_table[6];
173
0
    return true;
174
0
  default:
175
0
    return false;
176
0
  }
177
0
      break;
178
0
    case BFD_MACH_O_X86_64_RELOC_GOT_LOAD:
179
0
      if (reloc.r_length == 2 && reloc.r_pcrel && reloc.r_extern)
180
0
  {
181
0
    res->howto = &x86_64_howto_table[7];
182
0
    return true;
183
0
  }
184
0
      break;
185
0
    case BFD_MACH_O_X86_64_RELOC_GOT:
186
0
      if (reloc.r_length == 2 && reloc.r_pcrel && reloc.r_extern)
187
0
  {
188
0
    res->howto = &x86_64_howto_table[10];
189
0
    return true;
190
0
  }
191
0
      break;
192
0
    case BFD_MACH_O_X86_64_RELOC_SUBTRACTOR:
193
0
      if (reloc.r_pcrel)
194
0
  return false;
195
0
      switch (reloc.r_length)
196
0
  {
197
0
  case 2:
198
0
    res->howto = &x86_64_howto_table[8];
199
0
    return true;
200
0
  case 3:
201
0
    res->howto = &x86_64_howto_table[9];
202
0
    return true;
203
0
  default:
204
0
    return false;
205
0
  }
206
0
      break;
207
0
    case BFD_MACH_O_X86_64_RELOC_SIGNED_1:
208
0
      if (reloc.r_length == 2 && reloc.r_pcrel)
209
0
  {
210
0
    res->howto = &x86_64_howto_table[3];
211
0
    return true;
212
0
  }
213
0
      break;
214
0
    case BFD_MACH_O_X86_64_RELOC_SIGNED_2:
215
0
      if (reloc.r_length == 2 && reloc.r_pcrel)
216
0
  {
217
0
    res->howto = &x86_64_howto_table[4];
218
0
    return true;
219
0
  }
220
0
      break;
221
0
    case BFD_MACH_O_X86_64_RELOC_SIGNED_4:
222
0
      if (reloc.r_length == 2 && reloc.r_pcrel)
223
0
  {
224
0
    res->howto = &x86_64_howto_table[5];
225
0
    return true;
226
0
  }
227
0
      break;
228
0
    case BFD_MACH_O_X86_64_RELOC_TLV:
229
0
      if (reloc.r_length == 2 && reloc.r_pcrel && reloc.r_extern)
230
0
  {
231
0
    res->howto = &x86_64_howto_table[12];
232
0
    return true;
233
0
  }
234
0
      break;
235
0
    default:
236
0
      return false;
237
0
    }
238
0
  return false;
239
0
}
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"