elf32-xgate.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527
  1. /* Freescale XGATE-specific support for 32-bit ELF
  2. Copyright (C) 2010-2022 Free Software Foundation, Inc.
  3. Contributed by Sean Keys(skeys@ipdatasys.com)
  4. This file is part of BFD, the Binary File Descriptor library.
  5. This program is free software; you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation; either version 3 of the License, or
  8. (at your option) any later version.
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with this program; if not, write to the Free Software
  15. Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
  16. MA 02110-1301, USA. */
  17. #include "sysdep.h"
  18. #include "bfd.h"
  19. #include "bfdlink.h"
  20. #include "libbfd.h"
  21. #include "elf-bfd.h"
  22. #include "elf/xgate.h"
  23. #include "opcode/xgate.h"
  24. #include "libiberty.h"
  25. /* Forward declarations. */
  26. static bfd_reloc_status_type xgate_elf_ignore_reloc
  27. (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **);
  28. static bfd_reloc_status_type xgate_elf_special_reloc
  29. (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **);
  30. /* Use REL instead of RELA to save space */
  31. #define USE_REL 1
  32. static reloc_howto_type elf_xgate_howto_table[] =
  33. {
  34. /* This reloc does nothing. */
  35. HOWTO (R_XGATE_NONE, /* type */
  36. 0, /* rightshift */
  37. 3, /* size (0 = byte, 1 = short, 2 = long) */
  38. 0, /* bitsize */
  39. false, /* pc_relative */
  40. 0, /* bitpos */
  41. complain_overflow_dont,/* complain_on_overflow */
  42. bfd_elf_generic_reloc, /* special_function */
  43. "R_XGATE_NONE", /* name */
  44. false, /* partial_inplace */
  45. 0, /* src_mask */
  46. 0, /* dst_mask */
  47. false), /* pcrel_offset */
  48. /* A 8 bit absolute relocation. */
  49. HOWTO (R_XGATE_8, /* type */
  50. 0, /* rightshift */
  51. 0, /* size (0 = byte, 1 = short, 2 = long) */
  52. 8, /* bitsize */
  53. false, /* pc_relative */
  54. 0, /* bitpos */
  55. complain_overflow_bitfield, /* complain_on_overflow */
  56. bfd_elf_generic_reloc, /* special_function */
  57. "R_XGATE_8", /* name */
  58. false, /* partial_inplace */
  59. 0x00ff, /* src_mask */
  60. 0x00ff, /* dst_mask */
  61. false), /* pcrel_offset */
  62. /* A 8 bit PC-rel relocation. */
  63. HOWTO (R_XGATE_PCREL_8, /* type */
  64. 0, /* rightshift */
  65. 0, /* size (0 = byte, 1 = short, 2 = long) */
  66. 8, /* bitsize */
  67. true, /* pc_relative */
  68. 0, /* bitpos */
  69. complain_overflow_bitfield, /* complain_on_overflow */
  70. bfd_elf_generic_reloc, /* special_function */
  71. "R_XGATE_PCREL_8", /* name */
  72. false, /* partial_inplace */
  73. 0x00ff, /* src_mask */
  74. 0x00ff, /* dst_mask */
  75. true), /* pcrel_offset */
  76. /* A 16 bit absolute relocation. */
  77. HOWTO (R_XGATE_16, /* type */
  78. 0, /* rightshift */
  79. 1, /* size (0 = byte, 1 = short, 2 = long) */
  80. 16, /* bitsize */
  81. false, /* pc_relative */
  82. 0, /* bitpos */
  83. complain_overflow_dont /*bitfield */, /* complain_on_overflow */
  84. bfd_elf_generic_reloc, /* special_function */
  85. "R_XGATE_16", /* name */
  86. false, /* partial_inplace */
  87. 0xffff, /* src_mask */
  88. 0xffff, /* dst_mask */
  89. false), /* pcrel_offset */
  90. /* A 32 bit absolute relocation. This one is never used for the
  91. code relocation. It's used by gas for -gstabs generation. */
  92. HOWTO (R_XGATE_32, /* type */
  93. 0, /* rightshift */
  94. 2, /* size (0 = byte, 1 = short, 2 = long) */
  95. 32, /* bitsize */
  96. false, /* pc_relative */
  97. 0, /* bitpos */
  98. complain_overflow_bitfield, /* complain_on_overflow */
  99. bfd_elf_generic_reloc, /* special_function */
  100. "R_XGATE_32", /* name */
  101. false, /* partial_inplace */
  102. 0xffffffff, /* src_mask */
  103. 0xffffffff, /* dst_mask */
  104. false), /* pcrel_offset */
  105. /* A 16 bit PC-rel relocation. */
  106. HOWTO (R_XGATE_PCREL_16, /* type */
  107. 0, /* rightshift */
  108. 1, /* size (0 = byte, 1 = short, 2 = long) */
  109. 16, /* bitsize */
  110. true, /* pc_relative */
  111. 0, /* bitpos */
  112. complain_overflow_dont, /* complain_on_overflow */
  113. bfd_elf_generic_reloc, /* special_function */
  114. "R_XGATE_PCREL_16", /* name */
  115. false, /* partial_inplace */
  116. 0xffff, /* src_mask */
  117. 0xffff, /* dst_mask */
  118. true), /* pcrel_offset */
  119. /* GNU extension to record C++ vtable hierarchy. */
  120. HOWTO (R_XGATE_GNU_VTINHERIT, /* type */
  121. 0, /* rightshift */
  122. 1, /* size (0 = byte, 1 = short, 2 = long) */
  123. 0, /* bitsize */
  124. false, /* pc_relative */
  125. 0, /* bitpos */
  126. complain_overflow_dont, /* complain_on_overflow */
  127. NULL, /* special_function */
  128. "R_XGATE_GNU_VTINHERIT", /* name */
  129. false, /* partial_inplace */
  130. 0, /* src_mask */
  131. 0, /* dst_mask */
  132. false), /* pcrel_offset */
  133. /* GNU extension to record C++ vtable member usage. */
  134. HOWTO (R_XGATE_GNU_VTENTRY, /* type */
  135. 0, /* rightshift */
  136. 1, /* size (0 = byte, 1 = short, 2 = long) */
  137. 0, /* bitsize */
  138. false, /* pc_relative */
  139. 0, /* bitpos */
  140. complain_overflow_dont, /* complain_on_overflow */
  141. _bfd_elf_rel_vtable_reloc_fn, /* special_function */
  142. "R_XGATE_GNU_VTENTRY", /* name */
  143. false, /* partial_inplace */
  144. 0, /* src_mask */
  145. 0, /* dst_mask */
  146. false), /* pcrel_offset */
  147. /* A 24 bit relocation. */
  148. HOWTO (R_XGATE_24, /* type */
  149. 0, /* rightshift */
  150. 1, /* size (0 = byte, 1 = short, 2 = long) */
  151. 16, /* bitsize */
  152. false, /* pc_relative */
  153. 0, /* bitpos */
  154. complain_overflow_dont, /* complain_on_overflow */
  155. bfd_elf_generic_reloc, /* special_function */
  156. "R_XGATE_IMM8_LO", /* name */
  157. false, /* partial_inplace */
  158. 0x00ff, /* src_mask */
  159. 0x00ff, /* dst_mask */
  160. false), /* pcrel_offset */
  161. /* A 16-bit low relocation. */
  162. HOWTO (R_XGATE_LO16, /* type */
  163. 8, /* rightshift */
  164. 1, /* size (0 = byte, 1 = short, 2 = long) */
  165. 16, /* bitsize */
  166. false, /* pc_relative */
  167. 0, /* bitpos */
  168. complain_overflow_dont, /* complain_on_overflow */
  169. bfd_elf_generic_reloc, /* special_function */
  170. "R_XGATE_IMM8_HI", /* name */
  171. false, /* partial_inplace */
  172. 0x00ff, /* src_mask */
  173. 0x00ff, /* dst_mask */
  174. false), /* pcrel_offset */
  175. /* A page relocation. */
  176. HOWTO (R_XGATE_GPAGE, /* type */
  177. 0, /* rightshift */
  178. 0, /* size (0 = byte, 1 = short, 2 = long) */
  179. 8, /* bitsize */
  180. false, /* pc_relative */
  181. 0, /* bitpos */
  182. complain_overflow_dont, /* complain_on_overflow */
  183. xgate_elf_special_reloc,/* special_function */
  184. "R_XGATE_GPAGE", /* name */
  185. false, /* partial_inplace */
  186. 0x00ff, /* src_mask */
  187. 0x00ff, /* dst_mask */
  188. false), /* pcrel_offset */
  189. /* A 9 bit absolute relocation. */
  190. HOWTO (R_XGATE_PCREL_9, /* type */
  191. 0, /* rightshift */
  192. 1, /* size (0 = byte, 1 = short, 2 = long) */
  193. 9, /* bitsize */
  194. true, /* pc_relative */
  195. 0, /* bitpos */
  196. complain_overflow_bitfield, /* complain_on_overflow */
  197. bfd_elf_generic_reloc, /* special_function */
  198. "R_XGATE_PCREL_9", /* name */
  199. false, /* partial_inplace */
  200. 0xffff, /* src_mask */
  201. 0xffff, /* dst_mask */
  202. true), /* pcrel_offset */
  203. /* A 8 bit absolute relocation (upper address). */
  204. HOWTO (R_XGATE_PCREL_10, /* type */
  205. 8, /* rightshift */
  206. 0, /* size (0 = byte, 1 = short, 2 = long) */
  207. 10, /* bitsize */
  208. true, /* pc_relative */
  209. 0, /* bitpos */
  210. complain_overflow_dont, /* complain_on_overflow */
  211. bfd_elf_generic_reloc, /* special_function */
  212. "R_XGATE_PCREL_10", /* name */
  213. false, /* partial_inplace */
  214. 0x00ff, /* src_mask */
  215. 0x00ff, /* dst_mask */
  216. true), /* pcrel_offset */
  217. /* A 8 bit absolute relocation. */
  218. HOWTO (R_XGATE_IMM8_LO, /* type */
  219. 0, /* rightshift */
  220. 1, /* size (0 = byte, 1 = short, 2 = long) */
  221. 16, /* bitsize */
  222. false, /* pc_relative */
  223. 0, /* bitpos */
  224. complain_overflow_dont, /* complain_on_overflow */
  225. bfd_elf_generic_reloc, /* special_function */
  226. "R_XGATE_IMM8_LO", /* name */
  227. false, /* partial_inplace */
  228. 0xffff, /* src_mask */
  229. 0xffff, /* dst_mask */
  230. false), /* pcrel_offset */
  231. /* A 16 bit absolute relocation (upper address). */
  232. HOWTO (R_XGATE_IMM8_HI, /* type */
  233. 8, /* rightshift */
  234. 1, /* size (0 = byte, 1 = short, 2 = long) */
  235. 16, /* bitsize */
  236. false, /* pc_relative */
  237. 0, /* bitpos */
  238. complain_overflow_dont, /* complain_on_overflow */
  239. bfd_elf_generic_reloc, /* special_function */
  240. "R_XGATE_IMM8_HI", /* name */
  241. false, /* partial_inplace */
  242. 0x00ff, /* src_mask */
  243. 0x00ff, /* dst_mask */
  244. false), /* pcrel_offset */
  245. /* A 3 bit absolute relocation. */
  246. HOWTO (R_XGATE_IMM3, /* type */
  247. 8, /* rightshift */
  248. 1, /* size (0 = byte, 1 = short, 2 = long) */
  249. 16, /* bitsize */
  250. false, /* pc_relative */
  251. 0, /* bitpos */
  252. complain_overflow_dont, /* complain_on_overflow */
  253. bfd_elf_generic_reloc, /* special_function */
  254. "R_XGATE_IMM3", /* name */
  255. false, /* partial_inplace */
  256. 0x00ff, /* src_mask */
  257. 0x00ff, /* dst_mask */
  258. false), /* pcrel_offset */
  259. /* A 4 bit absolute relocation. */
  260. HOWTO (R_XGATE_IMM4, /* type */
  261. 8, /* rightshift */
  262. 1, /* size (0 = byte, 1 = short, 2 = long) */
  263. 16, /* bitsize */
  264. false, /* pc_relative */
  265. 0, /* bitpos */
  266. complain_overflow_dont, /* complain_on_overflow */
  267. bfd_elf_generic_reloc, /* special_function */
  268. "R_XGATE_IMM4", /* name */
  269. false, /* partial_inplace */
  270. 0x00ff, /* src_mask */
  271. 0x00ff, /* dst_mask */
  272. false), /* pcrel_offset */
  273. /* A 5 bit absolute relocation. */
  274. HOWTO (R_XGATE_IMM5, /* type */
  275. 8, /* rightshift */
  276. 1, /* size (0 = byte, 1 = short, 2 = long) */
  277. 16, /* bitsize */
  278. false, /* pc_relative */
  279. 0, /* bitpos */
  280. complain_overflow_dont, /* complain_on_overflow */
  281. bfd_elf_generic_reloc, /* special_function */
  282. "R_XGATE_IMM5", /* name */
  283. false, /* partial_inplace */
  284. 0x00ff, /* src_mask */
  285. 0x00ff, /* dst_mask */
  286. false), /* pcrel_offset */
  287. /* Mark beginning of a jump instruction (any form). */
  288. HOWTO (R_XGATE_RL_JUMP, /* type */
  289. 0, /* rightshift */
  290. 1, /* size (0 = byte, 1 = short, 2 = long) */
  291. 0, /* bitsize */
  292. false, /* pc_relative */
  293. 0, /* bitpos */
  294. complain_overflow_dont, /* complain_on_overflow */
  295. xgate_elf_ignore_reloc, /* special_function */
  296. "R_XGATE_RL_JUMP", /* name */
  297. true, /* partial_inplace */
  298. 0, /* src_mask */
  299. 0, /* dst_mask */
  300. true), /* pcrel_offset */
  301. /* Mark beginning of Gcc relaxation group instruction. */
  302. HOWTO (R_XGATE_RL_GROUP, /* type */
  303. 0, /* rightshift */
  304. 1, /* size (0 = byte, 1 = short, 2 = long) */
  305. 0, /* bitsize */
  306. false, /* pc_relative */
  307. 0, /* bitpos */
  308. complain_overflow_dont, /* complain_on_overflow */
  309. xgate_elf_ignore_reloc, /* special_function */
  310. "R_XGATE_RL_GROUP", /* name */
  311. true, /* partial_inplace */
  312. 0, /* src_mask */
  313. 0, /* dst_mask */
  314. true), /* pcrel_offset */
  315. };
  316. /* Map BFD reloc types to XGATE ELF reloc types. */
  317. struct xgate_reloc_map
  318. {
  319. bfd_reloc_code_real_type bfd_reloc_val;
  320. unsigned char elf_reloc_val;
  321. };
  322. static const struct xgate_reloc_map xgate_reloc_map[] =
  323. {
  324. {BFD_RELOC_NONE, R_XGATE_NONE},
  325. {BFD_RELOC_8, R_XGATE_8},
  326. {BFD_RELOC_8_PCREL, R_XGATE_PCREL_8},
  327. {BFD_RELOC_16_PCREL, R_XGATE_PCREL_16},
  328. {BFD_RELOC_16, R_XGATE_16},
  329. {BFD_RELOC_32, R_XGATE_32},
  330. {BFD_RELOC_VTABLE_INHERIT, R_XGATE_GNU_VTINHERIT},
  331. {BFD_RELOC_VTABLE_ENTRY, R_XGATE_GNU_VTENTRY},
  332. {BFD_RELOC_XGATE_LO16, R_XGATE_LO16},
  333. {BFD_RELOC_XGATE_GPAGE, R_XGATE_GPAGE},
  334. {BFD_RELOC_XGATE_24, R_XGATE_24},
  335. {BFD_RELOC_XGATE_PCREL_9, R_XGATE_PCREL_9},
  336. {BFD_RELOC_XGATE_PCREL_10, R_XGATE_PCREL_10},
  337. {BFD_RELOC_XGATE_IMM8_LO, R_XGATE_IMM8_LO},
  338. {BFD_RELOC_XGATE_IMM8_HI, R_XGATE_IMM8_HI},
  339. {BFD_RELOC_XGATE_IMM3, R_XGATE_IMM3},
  340. {BFD_RELOC_XGATE_IMM4, R_XGATE_IMM4},
  341. {BFD_RELOC_XGATE_IMM5, R_XGATE_IMM5},
  342. {BFD_RELOC_XGATE_RL_JUMP, R_XGATE_RL_JUMP},
  343. {BFD_RELOC_XGATE_RL_GROUP, R_XGATE_RL_GROUP},
  344. };
  345. static reloc_howto_type *
  346. bfd_elf32_bfd_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
  347. bfd_reloc_code_real_type code)
  348. {
  349. unsigned int i;
  350. for (i = 0; i < ARRAY_SIZE (xgate_reloc_map); i++)
  351. if (xgate_reloc_map[i].bfd_reloc_val == code)
  352. return &elf_xgate_howto_table[xgate_reloc_map[i].elf_reloc_val];
  353. return NULL;
  354. }
  355. static reloc_howto_type *
  356. bfd_elf32_bfd_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED, const char *r_name)
  357. {
  358. unsigned int i;
  359. for (i = 0; i < ARRAY_SIZE (elf_xgate_howto_table); i++)
  360. if (elf_xgate_howto_table[i].name != NULL
  361. && strcasecmp (elf_xgate_howto_table[i].name, r_name) == 0)
  362. return &elf_xgate_howto_table[i];
  363. return NULL;
  364. }
  365. /* Set the howto pointer for an XGATE ELF reloc. */
  366. static bool
  367. xgate_info_to_howto_rel (bfd *abfd,
  368. arelent *cache_ptr,
  369. Elf_Internal_Rela *dst)
  370. {
  371. unsigned int r_type;
  372. r_type = ELF32_R_TYPE (dst->r_info);
  373. if (r_type >= (unsigned int) R_XGATE_max)
  374. {
  375. /* xgettext:c-format */
  376. _bfd_error_handler (_("%pB: unsupported relocation type %#x"),
  377. abfd, r_type);
  378. bfd_set_error (bfd_error_bad_value);
  379. return false;
  380. }
  381. cache_ptr->howto = &elf_xgate_howto_table[r_type];
  382. return true;
  383. }
  384. /* Specific sections:
  385. - The .page0 is a data section that is mapped in [0x0000..0x00FF].
  386. Page0 accesses are faster on the M68HC12.
  387. - The .vectors is the section that represents the interrupt
  388. vectors.
  389. - The .xgate section is starts in 0xE08800 or as xgate sees it 0x0800. */
  390. static const struct bfd_elf_special_section elf32_xgate_special_sections[] =
  391. {
  392. { STRING_COMMA_LEN (".eeprom"), 0, SHT_PROGBITS, SHF_ALLOC + SHF_WRITE },
  393. { STRING_COMMA_LEN (".page0"), 0, SHT_PROGBITS, SHF_ALLOC + SHF_WRITE },
  394. { STRING_COMMA_LEN (".softregs"), 0, SHT_NOBITS, SHF_ALLOC + SHF_WRITE },
  395. { STRING_COMMA_LEN (".vectors"), 0, SHT_PROGBITS, SHF_ALLOC },
  396. /*{ STRING_COMMA_LEN (".xgate"), 0, SHT_PROGBITS, SHF_ALLOC + SHF_WRITE },
  397. TODO finish this implementation */
  398. { NULL, 0, 0, 0, 0 }
  399. };
  400. /* Hook called when reading symbols. */
  401. static void
  402. elf32_xgate_backend_symbol_processing (bfd *abfd ATTRIBUTE_UNUSED,
  403. asymbol *sym)
  404. {
  405. /* Mark xgate symbols. */
  406. ((elf_symbol_type *) sym)->internal_elf_sym.st_target_internal = 1;
  407. }
  408. /* This function is used for relocs which are only used for relaxing,
  409. which the linker should otherwise ignore. */
  410. static bfd_reloc_status_type
  411. xgate_elf_ignore_reloc (bfd *abfd ATTRIBUTE_UNUSED,
  412. arelent *reloc_entry,
  413. asymbol *symbol ATTRIBUTE_UNUSED,
  414. void *data ATTRIBUTE_UNUSED,
  415. asection *input_section,
  416. bfd *output_bfd,
  417. char **error_message ATTRIBUTE_UNUSED)
  418. {
  419. if (output_bfd != NULL)
  420. reloc_entry->address += input_section->output_offset;
  421. return bfd_reloc_ok;
  422. }
  423. static bfd_reloc_status_type
  424. xgate_elf_special_reloc (bfd *abfd ATTRIBUTE_UNUSED,
  425. arelent *reloc_entry ATTRIBUTE_UNUSED,
  426. asymbol *symbol ATTRIBUTE_UNUSED,
  427. void *data ATTRIBUTE_UNUSED,
  428. asection *input_section ATTRIBUTE_UNUSED,
  429. bfd *output_bfd ATTRIBUTE_UNUSED,
  430. char **error_message ATTRIBUTE_UNUSED)
  431. {
  432. abort ();
  433. }
  434. static bool
  435. _bfd_xgate_elf_print_private_bfd_data (bfd *abfd, void *ptr)
  436. {
  437. FILE *file = (FILE *) ptr;
  438. BFD_ASSERT (abfd != NULL && ptr != NULL);
  439. /* Print normal ELF private data. */
  440. _bfd_elf_print_private_bfd_data (abfd, ptr);
  441. /* xgettext:c-format */
  442. fprintf (file, _("private flags = %lx:"), elf_elfheader (abfd)->e_flags);
  443. if (elf_elfheader (abfd)->e_flags & E_XGATE_I32)
  444. fprintf (file, _("[abi=32-bit int, "));
  445. else
  446. fprintf (file, _("[abi=16-bit int, "));
  447. if (elf_elfheader (abfd)->e_flags & E_XGATE_F64)
  448. fprintf (file, _("64-bit double, "));
  449. else
  450. fprintf (file, _("32-bit double, "));
  451. if (elf_elfheader (abfd)->e_flags & EF_XGATE_MACH)
  452. fprintf (file, _("cpu=XGATE]"));
  453. else
  454. fprintf (file, _("error reading cpu type from elf private data"));
  455. fputc ('\n', file);
  456. return true;
  457. }
  458. #define ELF_ARCH bfd_arch_xgate
  459. #define ELF_MACHINE_CODE EM_XGATE
  460. #define ELF_MAXPAGESIZE 0x1000
  461. #define TARGET_BIG_SYM xgate_elf32_vec
  462. #define TARGET_BIG_NAME "elf32-xgate"
  463. #define elf_info_to_howto_rel xgate_info_to_howto_rel
  464. #define elf_backend_special_sections elf32_xgate_special_sections
  465. #define elf_backend_symbol_processing elf32_xgate_backend_symbol_processing
  466. #define bfd_elf32_bfd_print_private_bfd_data _bfd_xgate_elf_print_private_bfd_data
  467. #include "elf32-target.h"