mach-o-x86-64.c 11 KB

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