elf32-ft32.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381
  1. /* ft32-specific support for 32-bit ELF.
  2. Copyright (C) 2013-2015 Free Software Foundation, Inc.
  3. Copied from elf32-moxie.c which is..
  4. Copyright (C) 2009-2015 Free Software Foundation, Inc.
  5. Free Software Foundation, Inc.
  6. This file is part of BFD, the Binary File Descriptor library.
  7. This program is free software; you can redistribute it and/or modify
  8. it under the terms of the GNU General Public License as published by
  9. the Free Software Foundation; either version 3 of the License, or
  10. (at your option) any later version.
  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. You should have received a copy of the GNU General Public License
  16. along with this program; if not, write to the Free Software
  17. Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
  18. MA 02110-1301, USA. */
  19. #include "sysdep.h"
  20. #include "bfd.h"
  21. #include "libbfd.h"
  22. #include "elf-bfd.h"
  23. #include "elf/ft32.h"
  24. /* Forward declarations. */
  25. static reloc_howto_type ft32_elf_howto_table [] =
  26. {
  27. /* This reloc does nothing. */
  28. HOWTO (R_FT32_NONE, /* type */
  29. 0, /* rightshift */
  30. 2, /* size (0 = byte, 1 = short, 2 = long) */
  31. 32, /* bitsize */
  32. FALSE, /* pc_relative */
  33. 0, /* bitpos */
  34. complain_overflow_bitfield, /* complain_on_overflow */
  35. bfd_elf_generic_reloc, /* special_function */
  36. "R_FT32_NONE", /* name */
  37. FALSE, /* partial_inplace */
  38. 0, /* src_mask */
  39. 0, /* dst_mask */
  40. FALSE), /* pcrel_offset */
  41. /* A 32 bit absolute relocation. */
  42. HOWTO (R_FT32_32, /* type */
  43. 0, /* rightshift */
  44. 2, /* size (0 = byte, 1 = short, 2 = long) */
  45. 32, /* bitsize */
  46. FALSE, /* pc_relative */
  47. 0, /* bitpos */
  48. complain_overflow_bitfield, /* complain_on_overflow */
  49. bfd_elf_generic_reloc, /* special_function */
  50. "R_FT32_32", /* name */
  51. FALSE, /* partial_inplace */
  52. 0x00000000, /* src_mask */
  53. 0xffffffff, /* dst_mask */
  54. FALSE), /* pcrel_offset */
  55. HOWTO (R_FT32_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_bitfield, /* complain_on_overflow */
  62. bfd_elf_generic_reloc, /* special_function */
  63. "R_FT32_16", /* name */
  64. FALSE, /* partial_inplace */
  65. 0x00000000, /* src_mask */
  66. 0x0000ffff, /* dst_mask */
  67. FALSE), /* pcrel_offset */
  68. HOWTO (R_FT32_8, /* type */
  69. 0, /* rightshift */
  70. 0, /* size (0 = byte, 1 = short, 2 = long) */
  71. 8, /* bitsize */
  72. FALSE, /* pc_relative */
  73. 0, /* bitpos */
  74. complain_overflow_signed, /* complain_on_overflow */
  75. bfd_elf_generic_reloc, /* special_function */
  76. "R_FT32_8", /* name */
  77. FALSE, /* partial_inplace */
  78. 0x00000000, /* src_mask */
  79. 0x000000ff, /* dst_mask */
  80. FALSE), /* pcrel_offset */
  81. HOWTO (R_FT32_10, /* type */
  82. 0, /* rightshift */
  83. 1, /* size (0 = byte, 1 = short, 2 = long) */
  84. 10, /* bitsize */
  85. FALSE, /* pc_relative */
  86. 4, /* bitpos */
  87. complain_overflow_signed, /* complain_on_overflow */
  88. bfd_elf_generic_reloc, /* special_function */
  89. "R_FT32_10", /* name */
  90. FALSE, /* partial_inplace */
  91. 0x00000000, /* src_mask */
  92. 0x00003ff0, /* dst_mask */
  93. FALSE), /* pcrel_offset */
  94. HOWTO (R_FT32_20, /* type */
  95. 0, /* rightshift */
  96. 2, /* size (0 = byte, 1 = short, 2 = long) */
  97. 20, /* bitsize */
  98. FALSE, /* pc_relative */
  99. 0, /* bitpos */
  100. complain_overflow_dont, /* complain_on_overflow */
  101. bfd_elf_generic_reloc, /* special_function */
  102. "R_FT32_20", /* name */
  103. FALSE, /* partial_inplace */
  104. 0x00000000, /* src_mask */
  105. 0x000fffff, /* dst_mask */
  106. FALSE), /* pcrel_offset */
  107. HOWTO (R_FT32_17, /* type */
  108. 0, /* rightshift */
  109. 2, /* size (0 = byte, 1 = short, 2 = long) */
  110. 17, /* bitsize */
  111. FALSE, /* pc_relative */
  112. 0, /* bitpos */
  113. complain_overflow_dont, /* complain_on_overflow */
  114. bfd_elf_generic_reloc, /* special_function */
  115. "R_FT32_17", /* name */
  116. FALSE, /* partial_inplace */
  117. 0x00000000, /* src_mask */
  118. 0x0001ffff, /* dst_mask */
  119. FALSE), /* pcrel_offset */
  120. HOWTO (R_FT32_18, /* type */
  121. 2, /* rightshift */
  122. 2, /* size (0 = byte, 1 = short, 2 = long) */
  123. 18, /* bitsize */
  124. FALSE, /* pc_relative */
  125. 0, /* bitpos */
  126. complain_overflow_signed, /* complain_on_overflow */
  127. bfd_elf_generic_reloc, /* special_function */
  128. "R_FT32_18", /* name */
  129. FALSE, /* partial_inplace */
  130. 0x00000000, /* src_mask */
  131. 0x0003ffff, /* dst_mask */
  132. FALSE), /* pcrel_offset */
  133. };
  134. /* Map BFD reloc types to FT32 ELF reloc types. */
  135. struct ft32_reloc_map
  136. {
  137. bfd_reloc_code_real_type bfd_reloc_val;
  138. unsigned int ft32_reloc_val;
  139. };
  140. static const struct ft32_reloc_map ft32_reloc_map [] =
  141. {
  142. { BFD_RELOC_NONE, R_FT32_NONE },
  143. { BFD_RELOC_32, R_FT32_20 },
  144. { BFD_RELOC_16, R_FT32_16 },
  145. { BFD_RELOC_8, R_FT32_8 },
  146. { BFD_RELOC_FT32_10, R_FT32_10 },
  147. { BFD_RELOC_FT32_20, R_FT32_20 },
  148. { BFD_RELOC_FT32_17, R_FT32_17 },
  149. { BFD_RELOC_FT32_18, R_FT32_18 },
  150. };
  151. static reloc_howto_type *
  152. ft32_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
  153. bfd_reloc_code_real_type code)
  154. {
  155. unsigned int i;
  156. for (i = sizeof (ft32_reloc_map) / sizeof (ft32_reloc_map[0]);
  157. --i;)
  158. if (ft32_reloc_map [i].bfd_reloc_val == code)
  159. return & ft32_elf_howto_table [ft32_reloc_map[i].ft32_reloc_val];
  160. return NULL;
  161. }
  162. static reloc_howto_type *
  163. ft32_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED, const char *r_name)
  164. {
  165. unsigned int i;
  166. for (i = 0;
  167. i < sizeof (ft32_elf_howto_table) / sizeof (ft32_elf_howto_table[0]);
  168. i++)
  169. if (ft32_elf_howto_table[i].name != NULL
  170. && strcasecmp (ft32_elf_howto_table[i].name, r_name) == 0)
  171. return &ft32_elf_howto_table[i];
  172. return NULL;
  173. }
  174. /* Set the howto pointer for an FT32 ELF reloc. */
  175. static void
  176. ft32_info_to_howto_rela (bfd *abfd ATTRIBUTE_UNUSED,
  177. arelent *cache_ptr,
  178. Elf_Internal_Rela *dst)
  179. {
  180. unsigned int r_type;
  181. r_type = ELF32_R_TYPE (dst->r_info);
  182. BFD_ASSERT (r_type < (unsigned int) R_FT32_max);
  183. cache_ptr->howto = & ft32_elf_howto_table [r_type];
  184. }
  185. /* Relocate an FT32 ELF section.
  186. The RELOCATE_SECTION function is called by the new ELF backend linker
  187. to handle the relocations for a section.
  188. The relocs are always passed as Rela structures; if the section
  189. actually uses Rel structures, the r_addend field will always be
  190. zero.
  191. This function is responsible for adjusting the section contents as
  192. necessary, and (if using Rela relocs and generating a relocatable
  193. output file) adjusting the reloc addend as necessary.
  194. This function does not have to worry about setting the reloc
  195. address or the reloc symbol index.
  196. LOCAL_SYMS is a pointer to the swapped in local symbols.
  197. LOCAL_SECTIONS is an array giving the section in the input file
  198. corresponding to the st_shndx field of each local symbol.
  199. The global hash table entry for the global symbols can be found
  200. via elf_sym_hashes (input_bfd).
  201. When generating relocatable output, this function must handle
  202. STB_LOCAL/STT_SECTION symbols specially. The output symbol is
  203. going to be the section symbol corresponding to the output
  204. section, which means that the addend must be adjusted
  205. accordingly. */
  206. static bfd_boolean
  207. ft32_elf_relocate_section (bfd *output_bfd,
  208. struct bfd_link_info *info,
  209. bfd *input_bfd,
  210. asection *input_section,
  211. bfd_byte *contents,
  212. Elf_Internal_Rela *relocs,
  213. Elf_Internal_Sym *local_syms,
  214. asection **local_sections)
  215. {
  216. Elf_Internal_Shdr *symtab_hdr;
  217. struct elf_link_hash_entry **sym_hashes;
  218. Elf_Internal_Rela *rel;
  219. Elf_Internal_Rela *relend;
  220. symtab_hdr = & elf_tdata (input_bfd)->symtab_hdr;
  221. sym_hashes = elf_sym_hashes (input_bfd);
  222. relend = relocs + input_section->reloc_count;
  223. for (rel = relocs; rel < relend; rel ++)
  224. {
  225. reloc_howto_type *howto;
  226. unsigned long r_symndx;
  227. Elf_Internal_Sym *sym;
  228. asection *sec;
  229. struct elf_link_hash_entry *h;
  230. bfd_vma relocation;
  231. bfd_reloc_status_type r;
  232. const char *name;
  233. int r_type;
  234. r_type = ELF32_R_TYPE (rel->r_info);
  235. r_symndx = ELF32_R_SYM (rel->r_info);
  236. howto = ft32_elf_howto_table + r_type;
  237. h = NULL;
  238. sym = NULL;
  239. sec = NULL;
  240. if (r_symndx < symtab_hdr->sh_info)
  241. {
  242. sym = local_syms + r_symndx;
  243. sec = local_sections [r_symndx];
  244. relocation = _bfd_elf_rela_local_sym (output_bfd, sym, &sec, rel);
  245. name = bfd_elf_string_from_elf_section
  246. (input_bfd, symtab_hdr->sh_link, sym->st_name);
  247. name = (name == NULL) ? bfd_section_name (input_bfd, sec) : name;
  248. }
  249. else
  250. {
  251. bfd_boolean unresolved_reloc, warned, ignored;
  252. RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
  253. r_symndx, symtab_hdr, sym_hashes,
  254. h, sec, relocation,
  255. unresolved_reloc, warned, ignored);
  256. name = h->root.root.string;
  257. }
  258. if (sec != NULL && discarded_section (sec))
  259. RELOC_AGAINST_DISCARDED_SECTION (info, input_bfd, input_section,
  260. rel, 1, relend, howto, 0, contents);
  261. if (bfd_link_relocatable (info))
  262. continue;
  263. r = _bfd_final_link_relocate (howto, input_bfd, input_section,
  264. contents, rel->r_offset,
  265. relocation, rel->r_addend);
  266. if (r != bfd_reloc_ok)
  267. {
  268. const char * msg = NULL;
  269. switch (r)
  270. {
  271. case bfd_reloc_overflow:
  272. r = info->callbacks->reloc_overflow
  273. (info, (h ? &h->root : NULL), name, howto->name,
  274. (bfd_vma) 0, input_bfd, input_section, rel->r_offset);
  275. break;
  276. case bfd_reloc_undefined:
  277. r = info->callbacks->undefined_symbol
  278. (info, name, input_bfd, input_section, rel->r_offset,
  279. TRUE);
  280. break;
  281. case bfd_reloc_outofrange:
  282. msg = _("internal error: out of range error");
  283. break;
  284. case bfd_reloc_notsupported:
  285. msg = _("internal error: unsupported relocation error");
  286. break;
  287. case bfd_reloc_dangerous:
  288. msg = _("internal error: dangerous relocation");
  289. break;
  290. default:
  291. msg = _("internal error: unknown error");
  292. break;
  293. }
  294. if (msg)
  295. r = info->callbacks->warning
  296. (info, msg, name, input_bfd, input_section, rel->r_offset);
  297. if (! r)
  298. return FALSE;
  299. }
  300. }
  301. return TRUE;
  302. }
  303. #define ELF_ARCH bfd_arch_ft32
  304. #define ELF_MACHINE_CODE EM_FT32
  305. #define ELF_MAXPAGESIZE 0x1
  306. #define TARGET_LITTLE_SYM ft32_elf32_vec
  307. #define TARGET_LITTLE_NAME "elf32-ft32"
  308. #define elf_info_to_howto_rel NULL
  309. #define elf_info_to_howto ft32_info_to_howto_rela
  310. #define elf_backend_relocate_section ft32_elf_relocate_section
  311. #define elf_backend_can_gc_sections 1
  312. #define elf_backend_rela_normal 1
  313. #define bfd_elf32_bfd_reloc_type_lookup ft32_reloc_type_lookup
  314. #define bfd_elf32_bfd_reloc_name_lookup ft32_reloc_name_lookup
  315. #include "elf32-target.h"