elf32-xc16x.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487
  1. /* Infineon XC16X-specific support for 16-bit ELF.
  2. Copyright (C) 2006-2022 Free Software Foundation, Inc.
  3. Contributed by KPIT Cummins Infosystems
  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, 51 Franklin Street - Fifth Floor, Boston,
  16. MA 02110-1301, USA. */
  17. #include "sysdep.h"
  18. #include "bfd.h"
  19. #include "libbfd.h"
  20. #include "elf-bfd.h"
  21. #include "elf/xc16x.h"
  22. #include "dwarf2.h"
  23. #include "libiberty.h"
  24. static reloc_howto_type xc16x_elf_howto_table [] =
  25. {
  26. /* This reloc does nothing. */
  27. HOWTO (R_XC16X_NONE, /* type */
  28. 0, /* rightshift */
  29. 3, /* size (0 = byte, 1 = short, 2 = long) */
  30. 0, /* bitsize */
  31. false, /* pc_relative */
  32. 0, /* bitpos */
  33. complain_overflow_dont, /* complain_on_overflow */
  34. bfd_elf_generic_reloc, /* special_function */
  35. "R_XC16X_NONE", /* name */
  36. false, /* partial_inplace */
  37. 0, /* src_mask */
  38. 0, /* dst_mask */
  39. false), /* pcrel_offset */
  40. /* An 8 bit absolute relocation. */
  41. HOWTO (R_XC16X_ABS_8, /* type */
  42. 0, /* rightshift */
  43. 0, /* size (0 = byte, 1 = short, 2 = long) */
  44. 8, /* bitsize */
  45. false, /* pc_relative */
  46. 8, /* bitpos */
  47. complain_overflow_bitfield, /* complain_on_overflow */
  48. bfd_elf_generic_reloc, /* special_function */
  49. "R_XC16X_ABS_8", /* name */
  50. true, /* partial_inplace */
  51. 0x0000, /* src_mask */
  52. 0x00ff, /* dst_mask */
  53. false), /* pcrel_offset */
  54. /* A 16 bit absolute relocation. */
  55. HOWTO (R_XC16X_ABS_16, /* type */
  56. 0, /* rightshift */
  57. 1, /* size (0 = byte, 1 = short, 2 = long) */
  58. 16, /* bitsize */
  59. false, /* pc_relative */
  60. 0, /* bitpos */
  61. complain_overflow_dont, /* complain_on_overflow */
  62. bfd_elf_generic_reloc, /* special_function */
  63. "R_XC16X_ABS_16", /* name */
  64. true, /* partial_inplace */
  65. 0x00000000, /* src_mask */
  66. 0x0000ffff, /* dst_mask */
  67. false), /* pcrel_offset */
  68. HOWTO (R_XC16X_ABS_32, /* type */
  69. 0, /* rightshift */
  70. 2, /* size (0 = byte, 1 = short, 2 = long) */
  71. 32, /* bitsize */
  72. false, /* pc_relative */
  73. 0, /* bitpos */
  74. complain_overflow_bitfield, /* complain_on_overflow */
  75. bfd_elf_generic_reloc, /* special_function */
  76. "R_XC16X_ABS_32", /* name */
  77. true, /* partial_inplace */
  78. 0x00000000, /* src_mask */
  79. 0xffffffff, /* dst_mask */
  80. false), /* pcrel_offset */
  81. /* A PC relative 8 bit relocation. */
  82. HOWTO (R_XC16X_8_PCREL, /* type */
  83. 0, /* rightshift */
  84. 0, /* size (0 = byte, 1 = short, 2 = long) */
  85. 8, /* bitsize */
  86. true, /* pc_relative */
  87. 8, /* bitpos */
  88. complain_overflow_signed, /* complain_on_overflow */
  89. bfd_elf_generic_reloc, /* special_function */
  90. "R_XC16X_8_PCREL", /* name */
  91. false, /* partial_inplace */
  92. 0x0000, /* src_mask */
  93. 0x00ff, /* dst_mask */
  94. true), /* pcrel_offset */
  95. /* Relocation regarding page number. */
  96. HOWTO (R_XC16X_PAG, /* type */
  97. 0, /* rightshift */
  98. 1, /* size (0 = byte, 1 = short, 2 = long) */
  99. 16, /* bitsize */
  100. false, /* pc_relative */
  101. 0, /* bitpos */
  102. complain_overflow_signed, /* complain_on_overflow */
  103. bfd_elf_generic_reloc, /* special_function */
  104. "R_XC16X_PAG", /* name */
  105. true, /* partial_inplace */
  106. 0x00000000, /* src_mask */
  107. 0x0000ffff, /* dst_mask */
  108. false), /* pcrel_offset */
  109. /* Relocation regarding page number. */
  110. HOWTO (R_XC16X_POF, /* type */
  111. 0, /* rightshift */
  112. 1, /* size (0 = byte, 1 = short, 2 = long) */
  113. 16, /* bitsize */
  114. false, /* pc_relative */
  115. 0, /* bitpos */
  116. complain_overflow_signed, /* complain_on_overflow */
  117. bfd_elf_generic_reloc, /* special_function */
  118. "R_XC16X_POF", /* name */
  119. true, /* partial_inplace */
  120. 0x00000000, /* src_mask */
  121. 0x0000ffff, /* dst_mask */
  122. false), /* pcrel_offset */
  123. /* Relocation regarding segment number. */
  124. HOWTO (R_XC16X_SEG, /* type */
  125. 0, /* rightshift */
  126. 1, /* size (0 = byte, 1 = short, 2 = long) */
  127. 16, /* bitsize */
  128. false, /* pc_relative */
  129. 0, /* bitpos */
  130. complain_overflow_signed, /* complain_on_overflow */
  131. bfd_elf_generic_reloc, /* special_function */
  132. "R_XC16X_SEG", /* name */
  133. true, /* partial_inplace */
  134. 0x00000000, /* src_mask */
  135. 0x0000ffff, /* dst_mask */
  136. false), /* pcrel_offset */
  137. /* Relocation regarding segment offset. */
  138. HOWTO (R_XC16X_SOF, /* type */
  139. 0, /* rightshift */
  140. 1, /* size (0 = byte, 1 = short, 2 = long) */
  141. 16, /* bitsize */
  142. false, /* pc_relative */
  143. 0, /* bitpos */
  144. complain_overflow_signed, /* complain_on_overflow */
  145. bfd_elf_generic_reloc, /* special_function */
  146. "R_XC16X_SOF", /* name */
  147. true, /* partial_inplace */
  148. 0x00000000, /* src_mask */
  149. 0x0000ffff, /* dst_mask */
  150. false) /* pcrel_offset */
  151. };
  152. /* Map BFD reloc types to XC16X ELF reloc types. */
  153. struct xc16x_reloc_map
  154. {
  155. bfd_reloc_code_real_type bfd_reloc_val;
  156. unsigned int xc16x_reloc_val;
  157. };
  158. static const struct xc16x_reloc_map xc16x_reloc_map [] =
  159. {
  160. { BFD_RELOC_NONE, R_XC16X_NONE },
  161. { BFD_RELOC_8, R_XC16X_ABS_8 },
  162. { BFD_RELOC_16, R_XC16X_ABS_16 },
  163. { BFD_RELOC_32, R_XC16X_ABS_32 },
  164. { BFD_RELOC_8_PCREL, R_XC16X_8_PCREL },
  165. { BFD_RELOC_XC16X_PAG, R_XC16X_PAG},
  166. { BFD_RELOC_XC16X_POF, R_XC16X_POF},
  167. { BFD_RELOC_XC16X_SEG, R_XC16X_SEG},
  168. { BFD_RELOC_XC16X_SOF, R_XC16X_SOF},
  169. };
  170. /* This function is used to search for correct relocation type from
  171. howto structure. */
  172. static reloc_howto_type *
  173. xc16x_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
  174. bfd_reloc_code_real_type code)
  175. {
  176. unsigned int i;
  177. for (i = ARRAY_SIZE (xc16x_reloc_map); --i;)
  178. if (xc16x_reloc_map [i].bfd_reloc_val == code)
  179. return & xc16x_elf_howto_table [xc16x_reloc_map[i].xc16x_reloc_val];
  180. return NULL;
  181. }
  182. static reloc_howto_type *
  183. xc16x_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED,
  184. const char *r_name)
  185. {
  186. unsigned int i;
  187. for (i = 0; i < ARRAY_SIZE (xc16x_elf_howto_table); i++)
  188. if (xc16x_elf_howto_table[i].name != NULL
  189. && strcasecmp (xc16x_elf_howto_table[i].name, r_name) == 0)
  190. return &xc16x_elf_howto_table[i];
  191. return NULL;
  192. }
  193. static reloc_howto_type *
  194. elf32_xc16x_rtype_to_howto (bfd *abfd ATTRIBUTE_UNUSED, unsigned r_type)
  195. {
  196. if (r_type < ARRAY_SIZE (xc16x_elf_howto_table))
  197. return & xc16x_elf_howto_table[r_type];
  198. return NULL;
  199. }
  200. /* For a particular operand this function is
  201. called to finalise the type of relocation. */
  202. static bool
  203. elf32_xc16x_info_to_howto (bfd *abfd, arelent *bfd_reloc,
  204. Elf_Internal_Rela *elf_reloc)
  205. {
  206. unsigned int r;
  207. unsigned int i;
  208. r = ELF32_R_TYPE (elf_reloc->r_info);
  209. for (i = 0; i < ARRAY_SIZE (xc16x_elf_howto_table); i++)
  210. if (xc16x_elf_howto_table[i].type == r)
  211. {
  212. bfd_reloc->howto = &xc16x_elf_howto_table[i];
  213. return true;
  214. }
  215. /* xgettext:c-format */
  216. _bfd_error_handler (_("%pB: unsupported relocation type %#x"), abfd, r);
  217. bfd_set_error (bfd_error_bad_value);
  218. return false;
  219. }
  220. static bfd_reloc_status_type
  221. elf32_xc16x_final_link_relocate (unsigned long r_type,
  222. bfd *input_bfd,
  223. bfd *output_bfd ATTRIBUTE_UNUSED,
  224. asection *input_section ATTRIBUTE_UNUSED,
  225. bfd_byte *contents,
  226. bfd_vma offset,
  227. bfd_vma value,
  228. bfd_vma addend,
  229. struct bfd_link_info *info ATTRIBUTE_UNUSED,
  230. asection *sym_sec ATTRIBUTE_UNUSED,
  231. int is_local ATTRIBUTE_UNUSED)
  232. {
  233. bfd_byte *hit_data = contents + offset;
  234. bfd_vma val1;
  235. switch (r_type)
  236. {
  237. case R_XC16X_NONE:
  238. return bfd_reloc_ok;
  239. case R_XC16X_ABS_16:
  240. value += addend;
  241. bfd_put_16 (input_bfd, value, hit_data);
  242. return bfd_reloc_ok;
  243. case R_XC16X_8_PCREL:
  244. bfd_put_8 (input_bfd, value, hit_data);
  245. return bfd_reloc_ok;
  246. /* Following case is to find page number from actual
  247. address for this divide value by 16k i.e. page size. */
  248. case R_XC16X_PAG:
  249. value += addend;
  250. value /= 0x4000;
  251. bfd_put_16 (input_bfd, value, hit_data);
  252. return bfd_reloc_ok;
  253. /* Following case is to find page offset from actual address
  254. for this take modulo of value by 16k i.e. page size. */
  255. case R_XC16X_POF:
  256. value += addend;
  257. value %= 0x4000;
  258. bfd_put_16 (input_bfd, value, hit_data);
  259. return bfd_reloc_ok;
  260. /* Following case is to find segment number from actual
  261. address for this divide value by 64k i.e. segment size. */
  262. case R_XC16X_SEG:
  263. value += addend;
  264. value /= 0x10000;
  265. bfd_put_16 (input_bfd, value, hit_data);
  266. return bfd_reloc_ok;
  267. /* Following case is to find segment offset from actual address
  268. for this take modulo of value by 64k i.e. segment size. */
  269. case R_XC16X_SOF:
  270. value += addend;
  271. value %= 0x10000;
  272. bfd_put_16 (input_bfd, value, hit_data);
  273. return bfd_reloc_ok;
  274. case R_XC16X_ABS_32:
  275. if (!strstr (input_section->name,".debug"))
  276. {
  277. value += addend;
  278. val1 = value;
  279. value %= 0x4000;
  280. val1 /= 0x4000;
  281. val1 = val1 << 16;
  282. value += val1;
  283. bfd_put_32 (input_bfd, value, hit_data);
  284. }
  285. else
  286. {
  287. value += addend;
  288. bfd_put_32 (input_bfd, value, hit_data);
  289. }
  290. return bfd_reloc_ok;
  291. default:
  292. return bfd_reloc_notsupported;
  293. }
  294. }
  295. static int
  296. elf32_xc16x_relocate_section (bfd *output_bfd,
  297. struct bfd_link_info *info,
  298. bfd *input_bfd,
  299. asection *input_section,
  300. bfd_byte *contents,
  301. Elf_Internal_Rela *relocs,
  302. Elf_Internal_Sym *local_syms,
  303. asection **local_sections)
  304. {
  305. Elf_Internal_Shdr *symtab_hdr;
  306. struct elf_link_hash_entry **sym_hashes;
  307. Elf_Internal_Rela *rel, *relend;
  308. symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
  309. sym_hashes = elf_sym_hashes (input_bfd);
  310. rel = relocs;
  311. relend = relocs + input_section->reloc_count;
  312. for (; rel < relend; rel++)
  313. {
  314. unsigned int r_type;
  315. unsigned long r_symndx;
  316. Elf_Internal_Sym *sym;
  317. asection *sec;
  318. struct elf_link_hash_entry *h;
  319. bfd_vma relocation;
  320. /* This is a final link. */
  321. r_symndx = ELF32_R_SYM (rel->r_info);
  322. r_type = ELF32_R_TYPE (rel->r_info);
  323. h = NULL;
  324. sym = NULL;
  325. sec = NULL;
  326. if (r_symndx < symtab_hdr->sh_info)
  327. {
  328. sym = local_syms + r_symndx;
  329. sec = local_sections[r_symndx];
  330. relocation = _bfd_elf_rela_local_sym (output_bfd, sym, &sec, rel);
  331. }
  332. else
  333. {
  334. bool unresolved_reloc, warned, ignored;
  335. RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
  336. r_symndx, symtab_hdr, sym_hashes,
  337. h, sec, relocation,
  338. unresolved_reloc, warned, ignored);
  339. }
  340. if (sec != NULL && discarded_section (sec))
  341. {
  342. /* For relocs against symbols from removed linkonce sections,
  343. or sections discarded by a linker script, we just want the
  344. section contents cleared. Avoid any special processing. */
  345. reloc_howto_type *howto;
  346. howto = elf32_xc16x_rtype_to_howto (input_bfd, r_type);
  347. RELOC_AGAINST_DISCARDED_SECTION (info, input_bfd, input_section,
  348. rel, 1, relend, howto, 0, contents);
  349. }
  350. if (bfd_link_relocatable (info))
  351. continue;
  352. elf32_xc16x_final_link_relocate (r_type, input_bfd, output_bfd,
  353. input_section,
  354. contents, rel->r_offset,
  355. relocation, rel->r_addend,
  356. info, sec, h == NULL);
  357. }
  358. return true;
  359. }
  360. static bool
  361. elf32_xc16x_final_write_processing (bfd *abfd)
  362. {
  363. unsigned long val;
  364. switch (bfd_get_mach (abfd))
  365. {
  366. default:
  367. case bfd_mach_xc16x:
  368. val = 0x1000;
  369. break;
  370. case bfd_mach_xc16xl:
  371. val = 0x1001;
  372. break;
  373. case bfd_mach_xc16xs:
  374. val = 0x1002;
  375. break;
  376. }
  377. elf_elfheader (abfd)->e_flags |= val;
  378. return _bfd_elf_final_write_processing (abfd);
  379. }
  380. static unsigned long
  381. elf32_xc16x_mach (flagword flags)
  382. {
  383. switch (flags)
  384. {
  385. case 0x1000:
  386. default:
  387. return bfd_mach_xc16x;
  388. case 0x1001:
  389. return bfd_mach_xc16xl;
  390. case 0x1002:
  391. return bfd_mach_xc16xs;
  392. }
  393. }
  394. static bool
  395. elf32_xc16x_object_p (bfd *abfd)
  396. {
  397. bfd_default_set_arch_mach (abfd, bfd_arch_xc16x,
  398. elf32_xc16x_mach (elf_elfheader (abfd)->e_flags));
  399. return true;
  400. }
  401. #define ELF_ARCH bfd_arch_xc16x
  402. #define ELF_MACHINE_CODE EM_XC16X
  403. #define ELF_MAXPAGESIZE 0x100
  404. #define TARGET_LITTLE_SYM xc16x_elf32_vec
  405. #define TARGET_LITTLE_NAME "elf32-xc16x"
  406. #define elf_backend_final_write_processing elf32_xc16x_final_write_processing
  407. #define elf_backend_object_p elf32_xc16x_object_p
  408. #define elf_backend_can_gc_sections 1
  409. #define bfd_elf32_bfd_reloc_type_lookup xc16x_reloc_type_lookup
  410. #define bfd_elf32_bfd_reloc_name_lookup xc16x_reloc_name_lookup
  411. #define elf_info_to_howto elf32_xc16x_info_to_howto
  412. #define elf_info_to_howto_rel elf32_xc16x_info_to_howto
  413. #define elf_backend_relocate_section elf32_xc16x_relocate_section
  414. #define elf_backend_rela_normal 1
  415. #include "elf32-target.h"