mach-o-i386.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416
  1. /* Intel i386 Mach-O support for BFD.
  2. Copyright (C) 2009-2022 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 "bfd.h"
  18. #include "libbfd.h"
  19. #include "libiberty.h"
  20. #include "mach-o.h"
  21. #include "mach-o/reloc.h"
  22. #define bfd_mach_o_object_p bfd_mach_o_i386_object_p
  23. #define bfd_mach_o_core_p bfd_mach_o_i386_core_p
  24. #define bfd_mach_o_mkobject bfd_mach_o_i386_mkobject
  25. static bfd_cleanup
  26. bfd_mach_o_i386_object_p (bfd *abfd)
  27. {
  28. return bfd_mach_o_header_p (abfd, 0, 0, BFD_MACH_O_CPU_TYPE_I386);
  29. }
  30. static bfd_cleanup
  31. bfd_mach_o_i386_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_I386);
  35. }
  36. static bool
  37. bfd_mach_o_i386_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;
  44. mdata->header.cputype = BFD_MACH_O_CPU_TYPE_I386;
  45. mdata->header.cpusubtype = BFD_MACH_O_CPU_SUBTYPE_X86_ALL;
  46. mdata->header.byteorder = BFD_ENDIAN_LITTLE;
  47. mdata->header.version = 1;
  48. return true;
  49. }
  50. static reloc_howto_type i386_howto_table[]=
  51. {
  52. /* 0 */
  53. HOWTO(BFD_RELOC_32, 0, 2, 32, false, 0,
  54. complain_overflow_bitfield,
  55. NULL, "32",
  56. false, 0xffffffff, 0xffffffff, false),
  57. HOWTO(BFD_RELOC_16, 0, 1, 16, false, 0,
  58. complain_overflow_bitfield,
  59. NULL, "16",
  60. false, 0xffff, 0xffff, false),
  61. HOWTO(BFD_RELOC_8, 0, 0, 8, false, 0,
  62. complain_overflow_bitfield,
  63. NULL, "8",
  64. false, 0xff, 0xff, false),
  65. HOWTO(BFD_RELOC_32_PCREL, 0, 2, 32, true, 0,
  66. complain_overflow_bitfield,
  67. NULL, "DISP32",
  68. false, 0xffffffff, 0xffffffff, true),
  69. /* 4 */
  70. HOWTO(BFD_RELOC_16_PCREL, 0, 1, 16, true, 0,
  71. complain_overflow_bitfield,
  72. NULL, "DISP16",
  73. false, 0xffff, 0xffff, true),
  74. HOWTO(BFD_RELOC_MACH_O_SECTDIFF, 0, 2, 32, false, 0,
  75. complain_overflow_bitfield,
  76. NULL, "SECTDIFF_32",
  77. false, 0xffffffff, 0xffffffff, false),
  78. HOWTO(BFD_RELOC_MACH_O_LOCAL_SECTDIFF, 0, 2, 32, false, 0,
  79. complain_overflow_bitfield,
  80. NULL, "LSECTDIFF_32",
  81. false, 0xffffffff, 0xffffffff, false),
  82. HOWTO(BFD_RELOC_MACH_O_PAIR, 0, 2, 32, false, 0,
  83. complain_overflow_bitfield,
  84. NULL, "PAIR_32",
  85. false, 0xffffffff, 0xffffffff, false),
  86. /* 8 */
  87. HOWTO(BFD_RELOC_MACH_O_SECTDIFF, 0, 1, 16, false, 0,
  88. complain_overflow_bitfield,
  89. NULL, "SECTDIFF_16",
  90. false, 0xffff, 0xffff, false),
  91. HOWTO(BFD_RELOC_MACH_O_LOCAL_SECTDIFF, 0, 1, 16, false, 0,
  92. complain_overflow_bitfield,
  93. NULL, "LSECTDIFF_16",
  94. false, 0xffff, 0xffff, false),
  95. HOWTO(BFD_RELOC_MACH_O_PAIR, 0, 1, 16, false, 0,
  96. complain_overflow_bitfield,
  97. NULL, "PAIR_16",
  98. false, 0xffff, 0xffff, false),
  99. };
  100. static bool
  101. bfd_mach_o_i386_canonicalize_one_reloc (bfd * abfd,
  102. struct mach_o_reloc_info_external * raw,
  103. arelent * res,
  104. asymbol ** syms,
  105. arelent * res_base)
  106. {
  107. bfd_mach_o_reloc_info reloc;
  108. if (!bfd_mach_o_pre_canonicalize_one_reloc (abfd, raw, &reloc, res, syms))
  109. return false;
  110. if (reloc.r_scattered)
  111. {
  112. switch (reloc.r_type)
  113. {
  114. case BFD_MACH_O_GENERIC_RELOC_PAIR:
  115. /* PR 21813: Check for a corrupt PAIR reloc at the start. */
  116. if (res == res_base)
  117. return false;
  118. if (reloc.r_length == 2)
  119. {
  120. res->howto = &i386_howto_table[7];
  121. res->address = res[-1].address;
  122. return true;
  123. }
  124. else if (reloc.r_length == 1)
  125. {
  126. res->howto = &i386_howto_table[10];
  127. res->address = res[-1].address;
  128. return true;
  129. }
  130. return false;
  131. case BFD_MACH_O_GENERIC_RELOC_SECTDIFF:
  132. if (reloc.r_length == 2)
  133. {
  134. res->howto = &i386_howto_table[5];
  135. return true;
  136. }
  137. else if (reloc.r_length == 1)
  138. {
  139. res->howto = &i386_howto_table[8];
  140. return true;
  141. }
  142. return false;
  143. case BFD_MACH_O_GENERIC_RELOC_LOCAL_SECTDIFF:
  144. if (reloc.r_length == 2)
  145. {
  146. res->howto = &i386_howto_table[6];
  147. return true;
  148. }
  149. else if (reloc.r_length == 1)
  150. {
  151. res->howto = &i386_howto_table[9];
  152. return true;
  153. }
  154. return false;
  155. default:
  156. break;
  157. }
  158. }
  159. else
  160. {
  161. switch (reloc.r_type)
  162. {
  163. case BFD_MACH_O_GENERIC_RELOC_VANILLA:
  164. switch ((reloc.r_length << 1) | reloc.r_pcrel)
  165. {
  166. case 0: /* len = 0, pcrel = 0 */
  167. res->howto = &i386_howto_table[2];
  168. return true;
  169. case 2: /* len = 1, pcrel = 0 */
  170. res->howto = &i386_howto_table[1];
  171. return true;
  172. case 3: /* len = 1, pcrel = 1 */
  173. res->howto = &i386_howto_table[4];
  174. return true;
  175. case 4: /* len = 2, pcrel = 0 */
  176. res->howto = &i386_howto_table[0];
  177. return true;
  178. case 5: /* len = 2, pcrel = 1 */
  179. res->howto = &i386_howto_table[3];
  180. return true;
  181. default:
  182. return false;
  183. }
  184. default:
  185. break;
  186. }
  187. }
  188. return false;
  189. }
  190. static bool
  191. bfd_mach_o_i386_swap_reloc_out (arelent *rel, bfd_mach_o_reloc_info *rinfo)
  192. {
  193. rinfo->r_address = rel->address;
  194. switch (rel->howto->type)
  195. {
  196. case BFD_RELOC_32:
  197. case BFD_RELOC_32_PCREL:
  198. case BFD_RELOC_16:
  199. case BFD_RELOC_16_PCREL:
  200. case BFD_RELOC_8:
  201. rinfo->r_scattered = 0;
  202. rinfo->r_type = BFD_MACH_O_GENERIC_RELOC_VANILLA;
  203. rinfo->r_pcrel = rel->howto->pc_relative;
  204. rinfo->r_length = rel->howto->size; /* Correct in practice. */
  205. if ((*rel->sym_ptr_ptr)->flags & BSF_SECTION_SYM)
  206. {
  207. rinfo->r_extern = 0;
  208. rinfo->r_value =
  209. (*rel->sym_ptr_ptr)->section->output_section->target_index;
  210. }
  211. else
  212. {
  213. rinfo->r_extern = 1;
  214. rinfo->r_value = (*rel->sym_ptr_ptr)->udata.i;
  215. }
  216. break;
  217. case BFD_RELOC_MACH_O_SECTDIFF:
  218. rinfo->r_scattered = 1;
  219. rinfo->r_type = BFD_MACH_O_GENERIC_RELOC_SECTDIFF;
  220. rinfo->r_pcrel = 0;
  221. rinfo->r_length = rel->howto->size;
  222. rinfo->r_extern = 0;
  223. rinfo->r_value = rel->addend;
  224. break;
  225. case BFD_RELOC_MACH_O_LOCAL_SECTDIFF:
  226. rinfo->r_scattered = 1;
  227. rinfo->r_type = BFD_MACH_O_GENERIC_RELOC_LOCAL_SECTDIFF;
  228. rinfo->r_pcrel = 0;
  229. rinfo->r_length = rel->howto->size;
  230. rinfo->r_extern = 0;
  231. rinfo->r_value = rel->addend;
  232. break;
  233. case BFD_RELOC_MACH_O_PAIR:
  234. rinfo->r_address = 0;
  235. rinfo->r_scattered = 1;
  236. rinfo->r_type = BFD_MACH_O_GENERIC_RELOC_PAIR;
  237. rinfo->r_pcrel = 0;
  238. rinfo->r_length = rel->howto->size;
  239. rinfo->r_extern = 0;
  240. rinfo->r_value = rel->addend;
  241. break;
  242. default:
  243. return false;
  244. }
  245. return true;
  246. }
  247. static reloc_howto_type *
  248. bfd_mach_o_i386_bfd_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
  249. bfd_reloc_code_real_type code)
  250. {
  251. unsigned int i;
  252. for (i = 0; i < sizeof (i386_howto_table) / sizeof (*i386_howto_table); i++)
  253. if (code == i386_howto_table[i].type)
  254. return &i386_howto_table[i];
  255. return NULL;
  256. }
  257. static reloc_howto_type *
  258. bfd_mach_o_i386_bfd_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED,
  259. const char *name ATTRIBUTE_UNUSED)
  260. {
  261. return NULL;
  262. }
  263. static bool
  264. bfd_mach_o_i386_print_thread (bfd *abfd, bfd_mach_o_thread_flavour *thread,
  265. void *vfile, char *buf)
  266. {
  267. FILE *file = (FILE *)vfile;
  268. switch (thread->flavour)
  269. {
  270. case BFD_MACH_O_x86_THREAD_STATE:
  271. if (thread->size < (8 + 16 * 4))
  272. return false;
  273. fprintf (file, " x86_THREAD_STATE:\n");
  274. fprintf (file, " flavor: 0x%08lx count: 0x%08lx\n",
  275. (unsigned long)bfd_get_32 (abfd, buf + 0),
  276. (unsigned long)bfd_get_32 (abfd, buf + 4));
  277. fprintf (file, " eax: %08lx ebx: %08lx ecx: %08lx edx: %08lx\n",
  278. (unsigned long)bfd_get_32 (abfd, buf + 8),
  279. (unsigned long)bfd_get_32 (abfd, buf + 12),
  280. (unsigned long)bfd_get_32 (abfd, buf + 16),
  281. (unsigned long)bfd_get_32 (abfd, buf + 20));
  282. fprintf (file, " edi: %08lx esi: %08lx ebp: %08lx esp: %08lx\n",
  283. (unsigned long)bfd_get_32 (abfd, buf + 24),
  284. (unsigned long)bfd_get_32 (abfd, buf + 28),
  285. (unsigned long)bfd_get_32 (abfd, buf + 32),
  286. (unsigned long)bfd_get_32 (abfd, buf + 36));
  287. fprintf (file, " ss: %08lx flg: %08lx eip: %08lx cs: %08lx\n",
  288. (unsigned long)bfd_get_32 (abfd, buf + 40),
  289. (unsigned long)bfd_get_32 (abfd, buf + 44),
  290. (unsigned long)bfd_get_32 (abfd, buf + 48),
  291. (unsigned long)bfd_get_32 (abfd, buf + 52));
  292. fprintf (file, " ds: %08lx es: %08lx fs: %08lx gs: %08lx\n",
  293. (unsigned long)bfd_get_32 (abfd, buf + 56),
  294. (unsigned long)bfd_get_32 (abfd, buf + 60),
  295. (unsigned long)bfd_get_32 (abfd, buf + 64),
  296. (unsigned long)bfd_get_32 (abfd, buf + 68));
  297. return true;
  298. case BFD_MACH_O_x86_FLOAT_STATE:
  299. if (thread->size < 8)
  300. return false;
  301. fprintf (file, " x86_FLOAT_STATE:\n");
  302. fprintf (file, " flavor: 0x%08lx count: 0x%08lx\n",
  303. (unsigned long)bfd_get_32 (abfd, buf + 0),
  304. (unsigned long)bfd_get_32 (abfd, buf + 4));
  305. return true;
  306. case BFD_MACH_O_x86_EXCEPTION_STATE:
  307. if (thread->size < 8 + 3 * 4)
  308. return false;
  309. fprintf (file, " x86_EXCEPTION_STATE:\n");
  310. fprintf (file, " flavor: 0x%08lx count: 0x%08lx\n",
  311. (unsigned long)bfd_get_32 (abfd, buf + 0),
  312. (unsigned long)bfd_get_32 (abfd, buf + 4));
  313. fprintf (file, " trapno: %08lx err: %08lx faultaddr: %08lx\n",
  314. (unsigned long)bfd_get_32 (abfd, buf + 8),
  315. (unsigned long)bfd_get_32 (abfd, buf + 12),
  316. (unsigned long)bfd_get_32 (abfd, buf + 16));
  317. return true;
  318. default:
  319. break;
  320. }
  321. return false;
  322. }
  323. static const mach_o_section_name_xlat text_section_names_xlat[] =
  324. {
  325. { ".symbol_stub", "__symbol_stub",
  326. SEC_CODE | SEC_LOAD, BFD_MACH_O_S_SYMBOL_STUBS,
  327. BFD_MACH_O_S_ATTR_PURE_INSTRUCTIONS,
  328. 0},
  329. { ".picsymbol_stub", "__picsymbol_stub",
  330. SEC_CODE | SEC_LOAD, BFD_MACH_O_S_SYMBOL_STUBS,
  331. BFD_MACH_O_S_ATTR_PURE_INSTRUCTIONS,
  332. 0},
  333. { NULL, NULL, 0, 0, 0, 0}
  334. };
  335. static const mach_o_section_name_xlat data_section_names_xlat[] =
  336. {
  337. /* The first two are recognized by i386, but not emitted for x86 by
  338. modern GCC. */
  339. { ".non_lazy_symbol_pointer", "__nl_symbol_ptr",
  340. SEC_DATA | SEC_LOAD, BFD_MACH_O_S_NON_LAZY_SYMBOL_POINTERS,
  341. BFD_MACH_O_S_ATTR_NONE, 2},
  342. { ".lazy_symbol_pointer", "__la_symbol_ptr",
  343. SEC_DATA | SEC_LOAD, BFD_MACH_O_S_LAZY_SYMBOL_POINTERS,
  344. BFD_MACH_O_S_ATTR_NONE, 2},
  345. { ".lazy_symbol_pointer2", "__la_sym_ptr2",
  346. SEC_DATA | SEC_LOAD, BFD_MACH_O_S_LAZY_SYMBOL_POINTERS,
  347. BFD_MACH_O_S_ATTR_NONE, 2},
  348. { ".lazy_symbol_pointer3", "__la_sym_ptr3",
  349. SEC_DATA | SEC_LOAD, BFD_MACH_O_S_LAZY_SYMBOL_POINTERS,
  350. BFD_MACH_O_S_ATTR_NONE, 2},
  351. { NULL, NULL, 0, 0, 0, 0}
  352. };
  353. static const mach_o_section_name_xlat import_section_names_xlat[] =
  354. {
  355. { ".picsymbol_stub3", "__jump_table",
  356. SEC_CODE | SEC_LOAD, BFD_MACH_O_S_SYMBOL_STUBS,
  357. BFD_MACH_O_S_ATTR_PURE_INSTRUCTIONS
  358. | BFD_MACH_O_S_SELF_MODIFYING_CODE,
  359. 6},
  360. { ".non_lazy_symbol_pointer_x86", "__pointers",
  361. SEC_DATA | SEC_LOAD, BFD_MACH_O_S_NON_LAZY_SYMBOL_POINTERS,
  362. BFD_MACH_O_S_ATTR_NONE, 2},
  363. { NULL, NULL, 0, 0, 0, 0}
  364. };
  365. const mach_o_segment_name_xlat mach_o_i386_segsec_names_xlat[] =
  366. {
  367. { "__TEXT", text_section_names_xlat },
  368. { "__DATA", data_section_names_xlat },
  369. { "__IMPORT", import_section_names_xlat },
  370. { NULL, NULL }
  371. };
  372. #define bfd_mach_o_canonicalize_one_reloc bfd_mach_o_i386_canonicalize_one_reloc
  373. #define bfd_mach_o_swap_reloc_out bfd_mach_o_i386_swap_reloc_out
  374. #define bfd_mach_o_print_thread bfd_mach_o_i386_print_thread
  375. #define bfd_mach_o_tgt_seg_table mach_o_i386_segsec_names_xlat
  376. #define bfd_mach_o_section_type_valid_for_tgt NULL
  377. #define bfd_mach_o_bfd_reloc_type_lookup bfd_mach_o_i386_bfd_reloc_type_lookup
  378. #define bfd_mach_o_bfd_reloc_name_lookup bfd_mach_o_i386_bfd_reloc_name_lookup
  379. #define TARGET_NAME i386_mach_o_vec
  380. #define TARGET_STRING "mach-o-i386"
  381. #define TARGET_ARCHITECTURE bfd_arch_i386
  382. #define TARGET_PAGESIZE 4096
  383. #define TARGET_BIG_ENDIAN 0
  384. #define TARGET_ARCHIVE 0
  385. #define TARGET_PRIORITY 0
  386. #include "mach-o-target.c"