elf32-visium.c 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883
  1. /* Visium-specific support for 32-bit ELF.
  2. Copyright (C) 2003-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,
  15. Boston, MA 02110-1301, USA. */
  16. #include "sysdep.h"
  17. #include "bfd.h"
  18. #include "sysdep.h"
  19. #include "libbfd.h"
  20. #include "elf-bfd.h"
  21. #include "elf/visium.h"
  22. #include "libiberty.h"
  23. static bfd_reloc_status_type visium_elf_howto_parity_reloc
  24. (bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **);
  25. static reloc_howto_type visium_elf_howto_table[] = {
  26. /* This reloc does nothing. */
  27. HOWTO (R_VISIUM_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_VISIUM_NONE", /* name */
  36. false, /* partial_inplace */
  37. 0, /* src_mask */
  38. 0, /* dst_mask */
  39. false), /* pcrel_offset */
  40. /* A 8 bit absolute relocation. */
  41. HOWTO (R_VISIUM_8, /* type */
  42. 0, /* rightshift */
  43. 0, /* size (0 = byte, 1 = short, 2 = long) */
  44. 8, /* bitsize */
  45. false, /* pc_relative */
  46. 0, /* bitpos */
  47. complain_overflow_bitfield, /* complain_on_overflow */
  48. bfd_elf_generic_reloc, /* special_function */
  49. "R_VISIUM_8", /* name */
  50. false, /* partial_inplace */
  51. 0x00, /* src_mask */
  52. 0xff, /* dst_mask */
  53. false), /* pcrel_offset */
  54. /* A 16 bit absolute relocation. */
  55. HOWTO (R_VISIUM_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_VISIUM_16", /* name */
  64. false, /* partial_inplace */
  65. 0x0000, /* src_mask */
  66. 0xffff, /* dst_mask */
  67. false), /* pcrel_offset */
  68. /* A 32 bit absolute relocation. */
  69. HOWTO (R_VISIUM_32, /* type */
  70. 0, /* rightshift */
  71. 2, /* size (0 = byte, 1 = short, 2 = long) */
  72. 32, /* bitsize */
  73. false, /* pc_relative */
  74. 0, /* bitpos */
  75. complain_overflow_bitfield, /* complain_on_overflow */
  76. bfd_elf_generic_reloc, /* special_function */
  77. "R_VISIUM_32", /* name */
  78. false, /* partial_inplace */
  79. 0x00000000, /* src_mask */
  80. 0xffffffff, /* dst_mask */
  81. false), /* pcrel_offset */
  82. /* A 8 bit PC relative relocation. */
  83. HOWTO (R_VISIUM_8_PCREL, /* type */
  84. 0, /* rightshift */
  85. 0, /* size (0 = byte, 1 = short, 2 = long) */
  86. 8, /* bitsize */
  87. true, /* pc_relative */
  88. 0, /* bitpos */
  89. complain_overflow_bitfield, /* complain_on_overflow */
  90. bfd_elf_generic_reloc, /* special_function */
  91. "R_VISIUM_8_PCREL", /* name */
  92. false, /* partial_inplace */
  93. 0x00, /* src_mask */
  94. 0xff, /* dst_mask */
  95. true), /* pcrel_offset */
  96. /* A 16 bit PC relative relocation. */
  97. HOWTO (R_VISIUM_16_PCREL, /* type */
  98. 0, /* rightshift */
  99. 1, /* size (0 = byte, 1 = short, 2 = long) */
  100. 16, /* bitsize */
  101. true, /* pc_relative */
  102. 0, /* bitpos */
  103. complain_overflow_bitfield, /* complain_on_overflow */
  104. bfd_elf_generic_reloc, /* special_function */
  105. "R_VISIUM_16_PCREL", /* name */
  106. false, /* partial inplace */
  107. 0x0000, /* src_mask */
  108. 0xffff, /* dst_mask */
  109. true), /* pcrel_offset */
  110. /* A 32-bit PC relative relocation. */
  111. HOWTO (R_VISIUM_32_PCREL, /* type */
  112. 0, /* rightshift */
  113. 2, /* size (0 = byte, 1 = short, 2 = long) */
  114. 32, /* bitsize */
  115. true, /* pc_relative */
  116. 0, /* bitpos */
  117. complain_overflow_bitfield, /* complain_on_overflow */
  118. bfd_elf_generic_reloc, /* special_function */
  119. "R_VISIUM_32_PCREL", /* name */
  120. false, /* partial_inplace */
  121. 0, /* src_mask */
  122. 0xffffffff, /* dst_mask */
  123. true), /* pcrel_offset */
  124. /* A 16-bit PC word relative offset, relative to start of instruction
  125. and always in the second half of the instruction. */
  126. HOWTO (R_VISIUM_PC16, /* type */
  127. 2, /* rightshift */
  128. 2, /* size (0 = byte, 1 = short, 2 = long) */
  129. 16, /* bitsize */
  130. true, /* pc_relative */
  131. 0, /* bitpos */
  132. complain_overflow_signed, /* complain_on_overflow */
  133. visium_elf_howto_parity_reloc, /* special_function */
  134. "R_VISIUM_PC16", /* name */
  135. false, /* partial_inplace */
  136. 0x00000000, /* src_mask */
  137. 0x0000ffff, /* dst_mask */
  138. true), /* pcrel_offset */
  139. /* The high 16 bits of symbol value. */
  140. HOWTO (R_VISIUM_HI16, /* type */
  141. 16, /* rightshift */
  142. 2, /* size (0 = byte, 1 = short, 2 = long) */
  143. 16, /* bitsize */
  144. false, /* pc_relative */
  145. 0, /* bitpos */
  146. complain_overflow_dont, /* complain_on_overflow */
  147. visium_elf_howto_parity_reloc, /* special_function */
  148. "R_VISIUM_HI16", /* name */
  149. false, /* partial_inplace */
  150. 0x00000000, /* src_mask */
  151. 0x0000ffff, /* dst_mask */
  152. false), /* pcrel_offset */
  153. /* The low 16 bits of symbol value. */
  154. HOWTO (R_VISIUM_LO16, /* type */
  155. 0, /* rightshift */
  156. 2, /* size (0 = byte, 1 = short, 2 = long) */
  157. 16, /* bitsize */
  158. false, /* pc_relative */
  159. 0, /* bitpos */
  160. complain_overflow_dont, /* complain_on_overflow */
  161. visium_elf_howto_parity_reloc, /* special_function */
  162. "R_VISIUM_LO16", /* name */
  163. false, /* partial_inplace */
  164. 0x00000000, /* src_mask */
  165. 0x0000ffff, /* dst_mask */
  166. false), /* pcrel_offset */
  167. /* A 16 bit immediate value. */
  168. HOWTO (R_VISIUM_IM16, /* type */
  169. 0, /* rightshift */
  170. 2, /* size (0 = byte, 1 = short, 2 = long) */
  171. 16, /* bitsize */
  172. false, /* pc_relative */
  173. 0, /* bitpos */
  174. complain_overflow_unsigned, /* complain_on_overflow */
  175. visium_elf_howto_parity_reloc, /* special_function */
  176. "R_VISIUM_IM16", /* name */
  177. false, /* partial_inplace */
  178. 0x0000000, /* src_mask */
  179. 0x000ffff, /* dst_mask */
  180. false), /* pcrel_offset */
  181. /* The high 16 bits of symbol value, pc relative. */
  182. HOWTO (R_VISIUM_HI16_PCREL, /* type */
  183. 16, /* rightshift */
  184. 2, /* size (0 = byte, 1 = short, 2 = long) */
  185. 16, /* bitsize */
  186. true, /* pc_relative */
  187. 0, /* bitpos */
  188. complain_overflow_dont, /* complain_on_overflow */
  189. visium_elf_howto_parity_reloc, /* special_function */
  190. "R_VISIUM_HI16_PCREL", /* name */
  191. false, /* partial_inplace */
  192. 0x00000000, /* src_mask */
  193. 0x0000ffff, /* dst_mask */
  194. true), /* pcrel_offset */
  195. /* The low 16 bits of symbol value, pc relative. */
  196. HOWTO (R_VISIUM_LO16_PCREL, /* type */
  197. 0, /* rightshift */
  198. 2, /* size (0 = byte, 1 = short, 2 = long) */
  199. 16, /* bitsize */
  200. true, /* pc_relative */
  201. 0, /* bitpos */
  202. complain_overflow_dont, /* complain_on_overflow */
  203. visium_elf_howto_parity_reloc, /* special_function */
  204. "R_VISIUM_LO16_PCREL", /* name */
  205. false, /* partial_inplace */
  206. 0x00000000, /* src_mask */
  207. 0x0000ffff, /* dst_mask */
  208. true), /* pcrel_offset */
  209. /* A 16 bit immediate value, pc relative. */
  210. HOWTO (R_VISIUM_IM16_PCREL, /* type */
  211. 0, /* rightshift */
  212. 2, /* size (0 = byte, 1 = short, 2 = long) */
  213. 16, /* bitsize */
  214. true, /* pc_relative */
  215. 0, /* bitpos */
  216. complain_overflow_unsigned, /* complain_on_overflow */
  217. visium_elf_howto_parity_reloc, /* special_function */
  218. "R_VISIUM_IM16_PCREL", /* name */
  219. false, /* partial_inplace */
  220. 0x0000000, /* src_mask */
  221. 0x000ffff, /* dst_mask */
  222. true), /* pcrel_offset */
  223. };
  224. /* GNU extension to record C++ vtable hierarchy. */
  225. static reloc_howto_type visium_elf_vtinherit_howto =
  226. HOWTO (R_VISIUM_GNU_VTINHERIT, /* type */
  227. 0, /* rightshift */
  228. 2, /* size (0 = byte, 1 = short, 2 = long) */
  229. 0, /* bitsize */
  230. false, /* pc_relative */
  231. 0, /* bitpos */
  232. complain_overflow_dont, /* complain_on_overflow */
  233. NULL, /* special_function */
  234. "R_VISIUM_GNU_VTINHERIT", /* name */
  235. false, /* partial_inplace */
  236. 0, /* src_mask */
  237. 0, /* dst_mask */
  238. false); /* pcrel_offset */
  239. /* GNU extension to record C++ vtable member usage. */
  240. static reloc_howto_type visium_elf_vtentry_howto =
  241. HOWTO (R_VISIUM_GNU_VTENTRY, /* type */
  242. 0, /* rightshift */
  243. 2, /* size (0 = byte, 1 = short, 2 = long) */
  244. 0, /* bitsize */
  245. false, /* pc_relative */
  246. 0, /* bitpos */
  247. complain_overflow_dont, /* complain_on_overflow */
  248. NULL, /* special_function */
  249. "R_VISIUM_GNU_VTENTRY", /* name */
  250. false, /* partial_inplace */
  251. 0, /* src_mask */
  252. 0, /* dst_mask */
  253. false); /* pcrel_offset */
  254. /* Return the parity bit for INSN shifted to its final position. */
  255. static bfd_vma
  256. visium_parity_bit (bfd_vma insn)
  257. {
  258. bfd_vma p = 0;
  259. int i;
  260. for (i = 0; i < 31; i++)
  261. {
  262. p ^= (insn & 1);
  263. insn >>= 1;
  264. }
  265. return p << 31;
  266. }
  267. /* This "special function" will only be used when the input and
  268. output files have different formats ie. when generating S-records
  269. directly using "--oformat srec". Otherwise we use
  270. _bfd_final_link_relocate which uses a howto structure, but does
  271. not use the special_function field.
  272. It sets instruction parity to even. This cannot be done by a howto. */
  273. static bfd_reloc_status_type
  274. visium_elf_howto_parity_reloc (bfd * input_bfd, arelent *reloc_entry,
  275. asymbol *symbol, PTR data,
  276. asection *input_section, bfd *output_bfd,
  277. char **error_message ATTRIBUTE_UNUSED)
  278. {
  279. bfd_reloc_status_type ret;
  280. bfd_vma relocation;
  281. bfd_byte *inplace_address;
  282. bfd_vma insn;
  283. /* This part is from bfd_elf_generic_reloc.
  284. If we're relocating, and this an external symbol, we don't want
  285. to change anything. */
  286. if (output_bfd != (bfd *) NULL && (symbol->flags & BSF_SECTION_SYM) == 0)
  287. {
  288. reloc_entry->address += input_section->output_offset;
  289. return bfd_reloc_ok;
  290. }
  291. /* Now do the reloc in the usual way. */
  292. /* Sanity check the address (offset in section). */
  293. if (reloc_entry->address > bfd_get_section_limit (input_bfd, input_section))
  294. return bfd_reloc_outofrange;
  295. ret = bfd_reloc_ok;
  296. if (bfd_is_und_section (symbol->section) && output_bfd == (bfd *) NULL)
  297. ret = bfd_reloc_undefined;
  298. if (bfd_is_com_section (symbol->section) || output_bfd != (bfd *) NULL)
  299. relocation = 0;
  300. else
  301. relocation = symbol->value;
  302. /* Only do this for a final link. */
  303. if (output_bfd == (bfd *) NULL)
  304. {
  305. relocation += symbol->section->output_section->vma;
  306. relocation += symbol->section->output_offset;
  307. }
  308. relocation += reloc_entry->addend;
  309. inplace_address = (bfd_byte *) data + reloc_entry->address;
  310. insn = bfd_get_32 (input_bfd, inplace_address);
  311. if (reloc_entry->howto->pc_relative)
  312. {
  313. relocation -= input_section->output_section->vma;
  314. relocation -= input_section->output_offset;
  315. relocation -= reloc_entry->address;
  316. }
  317. switch (reloc_entry->howto->type)
  318. {
  319. case R_VISIUM_PC16:
  320. if (ret == bfd_reloc_ok
  321. && ((bfd_signed_vma) relocation < -0x20000
  322. || (bfd_signed_vma) relocation > 0x1ffff))
  323. ret = bfd_reloc_overflow;
  324. relocation = (relocation >> 2) & 0xffff;
  325. break;
  326. case R_VISIUM_HI16:
  327. case R_VISIUM_HI16_PCREL:
  328. relocation = (relocation >> 16) & 0xffff;
  329. break;
  330. case R_VISIUM_LO16:
  331. case R_VISIUM_LO16_PCREL:
  332. relocation &= 0xffff;
  333. break;
  334. case R_VISIUM_IM16:
  335. case R_VISIUM_IM16_PCREL:
  336. if (ret == bfd_reloc_ok && (relocation & 0xffff0000) != 0)
  337. ret = bfd_reloc_overflow;
  338. relocation &= 0xffff;
  339. break;
  340. }
  341. insn = (insn & 0x7fff0000) | relocation;
  342. insn |= visium_parity_bit (insn);
  343. bfd_put_32 (input_bfd, insn, inplace_address);
  344. if (output_bfd != (bfd *) NULL)
  345. reloc_entry->address += input_section->output_offset;
  346. return ret;
  347. }
  348. static reloc_howto_type *
  349. visium_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
  350. bfd_reloc_code_real_type code)
  351. {
  352. /* Note that the visium_elf_howto_table is indexed by the R_
  353. constants. Thus, the order that the howto records appear in the
  354. table *must* match the order of the relocation types defined in
  355. include/elf/visium.h. */
  356. switch (code)
  357. {
  358. case BFD_RELOC_NONE:
  359. return &visium_elf_howto_table[(int) R_VISIUM_NONE];
  360. case BFD_RELOC_8:
  361. return &visium_elf_howto_table[(int) R_VISIUM_8];
  362. case BFD_RELOC_16:
  363. return &visium_elf_howto_table[(int) R_VISIUM_16];
  364. case BFD_RELOC_32:
  365. return &visium_elf_howto_table[(int) R_VISIUM_32];
  366. case BFD_RELOC_8_PCREL:
  367. return &visium_elf_howto_table[(int) R_VISIUM_8_PCREL];
  368. case BFD_RELOC_16_PCREL:
  369. return &visium_elf_howto_table[(int) R_VISIUM_16_PCREL];
  370. case BFD_RELOC_32_PCREL:
  371. return &visium_elf_howto_table[(int) R_VISIUM_32_PCREL];
  372. case BFD_RELOC_VISIUM_REL16:
  373. return &visium_elf_howto_table[(int) R_VISIUM_PC16];
  374. case BFD_RELOC_VISIUM_HI16:
  375. return &visium_elf_howto_table[(int) R_VISIUM_HI16];
  376. case BFD_RELOC_VISIUM_LO16:
  377. return &visium_elf_howto_table[(int) R_VISIUM_LO16];
  378. case BFD_RELOC_VISIUM_IM16:
  379. return &visium_elf_howto_table[(int) R_VISIUM_IM16];
  380. case BFD_RELOC_VISIUM_HI16_PCREL:
  381. return &visium_elf_howto_table[(int) R_VISIUM_HI16_PCREL];
  382. case BFD_RELOC_VISIUM_LO16_PCREL:
  383. return &visium_elf_howto_table[(int) R_VISIUM_LO16_PCREL];
  384. case BFD_RELOC_VISIUM_IM16_PCREL:
  385. return &visium_elf_howto_table[(int) R_VISIUM_IM16_PCREL];
  386. case BFD_RELOC_VTABLE_INHERIT:
  387. return &visium_elf_vtinherit_howto;
  388. case BFD_RELOC_VTABLE_ENTRY:
  389. return &visium_elf_vtentry_howto;
  390. default:
  391. return NULL;
  392. }
  393. }
  394. static reloc_howto_type *
  395. visium_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED, const char *r_name)
  396. {
  397. unsigned int i;
  398. for (i = 0;
  399. i < (sizeof (visium_elf_howto_table)
  400. / sizeof (visium_elf_howto_table[0])); i++)
  401. if (visium_elf_howto_table[i].name != NULL
  402. && strcasecmp (visium_elf_howto_table[i].name, r_name) == 0)
  403. return &visium_elf_howto_table[i];
  404. if (strcasecmp (visium_elf_vtinherit_howto.name, r_name) == 0)
  405. return &visium_elf_vtinherit_howto;
  406. if (strcasecmp (visium_elf_vtentry_howto.name, r_name) == 0)
  407. return &visium_elf_vtentry_howto;
  408. return NULL;
  409. }
  410. /* Set the howto pointer for a VISIUM ELF reloc. */
  411. static bool
  412. visium_info_to_howto_rela (bfd *abfd, arelent *cache_ptr,
  413. Elf_Internal_Rela *dst)
  414. {
  415. unsigned int r_type = ELF32_R_TYPE (dst->r_info);
  416. switch (r_type)
  417. {
  418. case R_VISIUM_GNU_VTINHERIT:
  419. cache_ptr->howto = &visium_elf_vtinherit_howto;
  420. break;
  421. case R_VISIUM_GNU_VTENTRY:
  422. cache_ptr->howto = &visium_elf_vtentry_howto;
  423. break;
  424. default:
  425. if (r_type >= ARRAY_SIZE (visium_elf_howto_table))
  426. {
  427. /* xgettext:c-format */
  428. _bfd_error_handler (_("%pB: unsupported relocation type %#x"),
  429. abfd, r_type);
  430. bfd_set_error (bfd_error_bad_value);
  431. return false;
  432. }
  433. cache_ptr->howto = &visium_elf_howto_table[r_type];
  434. break;
  435. }
  436. return true;
  437. }
  438. /* Look through the relocs for a section during the first phase.
  439. Since we don't do .gots or .plts, we just need to consider the
  440. virtual table relocs for gc. */
  441. static bool
  442. visium_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
  443. asection *sec, const Elf_Internal_Rela *relocs)
  444. {
  445. Elf_Internal_Shdr *symtab_hdr;
  446. struct elf_link_hash_entry **sym_hashes;
  447. const Elf_Internal_Rela *rel;
  448. const Elf_Internal_Rela *rel_end;
  449. if (bfd_link_relocatable (info))
  450. return true;
  451. symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
  452. sym_hashes = elf_sym_hashes (abfd);
  453. rel_end = relocs + sec->reloc_count;
  454. for (rel = relocs; rel < rel_end; rel++)
  455. {
  456. struct elf_link_hash_entry *h;
  457. unsigned long r_symndx;
  458. r_symndx = ELF32_R_SYM (rel->r_info);
  459. if (r_symndx < symtab_hdr->sh_info)
  460. h = NULL;
  461. else
  462. {
  463. h = sym_hashes[r_symndx - symtab_hdr->sh_info];
  464. while (h->root.type == bfd_link_hash_indirect
  465. || h->root.type == bfd_link_hash_warning)
  466. h = (struct elf_link_hash_entry *) h->root.u.i.link;
  467. }
  468. switch (ELF32_R_TYPE (rel->r_info))
  469. {
  470. /* This relocation describes the C++ object vtable hierarchy.
  471. Reconstruct it for later use during GC. */
  472. case R_VISIUM_GNU_VTINHERIT:
  473. if (!bfd_elf_gc_record_vtinherit (abfd, sec, h, rel->r_offset))
  474. return false;
  475. break;
  476. /* This relocation describes which C++ vtable entries are actually
  477. used. Record for later use during GC. */
  478. case R_VISIUM_GNU_VTENTRY:
  479. if (!bfd_elf_gc_record_vtentry (abfd, sec, h, rel->r_addend))
  480. return false;
  481. break;
  482. }
  483. }
  484. return true;
  485. }
  486. /* Relocate a VISIUM ELF section. */
  487. static int
  488. visium_elf_relocate_section (bfd *output_bfd,
  489. struct bfd_link_info *info, bfd *input_bfd,
  490. asection *input_section, bfd_byte *contents,
  491. Elf_Internal_Rela *relocs,
  492. Elf_Internal_Sym *local_syms,
  493. asection **local_sections)
  494. {
  495. Elf_Internal_Shdr *symtab_hdr;
  496. struct elf_link_hash_entry **sym_hashes;
  497. Elf_Internal_Rela *rel;
  498. Elf_Internal_Rela *relend;
  499. symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
  500. sym_hashes = elf_sym_hashes (input_bfd);
  501. relend = relocs + input_section->reloc_count;
  502. for (rel = relocs; rel < relend; rel++)
  503. {
  504. reloc_howto_type *howto;
  505. unsigned long r_symndx;
  506. Elf_Internal_Sym *sym;
  507. asection *sec;
  508. struct elf_link_hash_entry *h;
  509. bfd_vma relocation;
  510. bfd_reloc_status_type r;
  511. const char *name = NULL;
  512. int r_type;
  513. bfd_vma insn;
  514. r_type = ELF32_R_TYPE (rel->r_info);
  515. if (r_type == R_VISIUM_GNU_VTINHERIT || r_type == R_VISIUM_GNU_VTENTRY)
  516. continue;
  517. r_symndx = ELF32_R_SYM (rel->r_info);
  518. howto = visium_elf_howto_table + ELF32_R_TYPE (rel->r_info);
  519. h = NULL;
  520. sym = NULL;
  521. sec = NULL;
  522. if (r_symndx < symtab_hdr->sh_info)
  523. {
  524. /* This is a local symbol. */
  525. sym = local_syms + r_symndx;
  526. sec = local_sections[r_symndx];
  527. relocation = _bfd_elf_rela_local_sym (output_bfd, sym, &sec, rel);
  528. name = bfd_elf_string_from_elf_section
  529. (input_bfd, symtab_hdr->sh_link, sym->st_name);
  530. name = name == NULL ? bfd_section_name (sec) : name;
  531. }
  532. else
  533. {
  534. bool unresolved_reloc;
  535. bool warned, ignored;
  536. RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
  537. r_symndx, symtab_hdr, sym_hashes,
  538. h, sec, relocation,
  539. unresolved_reloc, warned, ignored);
  540. name = h->root.root.string;
  541. }
  542. if (sec != NULL && discarded_section (sec))
  543. {
  544. /* For relocs against symbols from removed linkonce sections,
  545. or sections discarded by a linker script, we just want the
  546. section contents zeroed. Avoid any special processing. */
  547. _bfd_clear_contents (howto, input_bfd, input_section,
  548. contents, rel->r_offset);
  549. rel->r_info = 0;
  550. rel->r_addend = 0;
  551. continue;
  552. }
  553. if (bfd_link_relocatable (info))
  554. continue;
  555. switch (r_type)
  556. {
  557. case R_VISIUM_PC16:
  558. case R_VISIUM_HI16:
  559. case R_VISIUM_LO16:
  560. case R_VISIUM_IM16:
  561. case R_VISIUM_HI16_PCREL:
  562. case R_VISIUM_LO16_PCREL:
  563. case R_VISIUM_IM16_PCREL:
  564. r = _bfd_final_link_relocate (howto, input_bfd, input_section,
  565. contents, rel->r_offset,
  566. relocation, rel->r_addend);
  567. /* For instruction relocations, the parity needs correcting. */
  568. if (r == bfd_reloc_ok)
  569. {
  570. insn = bfd_get_32 (input_bfd, contents + rel->r_offset);
  571. insn = (insn & 0x7fffffff) | visium_parity_bit (insn);
  572. bfd_put_32 (input_bfd, insn, contents + rel->r_offset);
  573. }
  574. break;
  575. default:
  576. r = _bfd_final_link_relocate (howto, input_bfd, input_section,
  577. contents, rel->r_offset,
  578. relocation, rel->r_addend);
  579. break;
  580. }
  581. if (r != bfd_reloc_ok)
  582. {
  583. const char *msg = (const char *) NULL;
  584. switch (r)
  585. {
  586. case bfd_reloc_overflow:
  587. (*info->callbacks->reloc_overflow)
  588. (info, (h ? &h->root : NULL), name, howto->name, (bfd_vma) 0,
  589. input_bfd, input_section, rel->r_offset);
  590. break;
  591. case bfd_reloc_undefined:
  592. (*info->callbacks->undefined_symbol)
  593. (info, name, input_bfd, input_section, rel->r_offset, true);
  594. break;
  595. case bfd_reloc_outofrange:
  596. msg = _("internal error: out of range error");
  597. break;
  598. case bfd_reloc_notsupported:
  599. msg = _("internal error: unsupported relocation error");
  600. break;
  601. case bfd_reloc_dangerous:
  602. msg = _("internal error: dangerous relocation");
  603. break;
  604. default:
  605. msg = _("internal error: unknown error");
  606. break;
  607. }
  608. if (msg)
  609. (*info->callbacks->warning) (info, msg, name, input_bfd,
  610. input_section, rel->r_offset);
  611. }
  612. }
  613. return true;
  614. }
  615. /* This function is called during section gc to discover the section a
  616. to which a particular relocation refers. Return the section that
  617. should be marked against GC for a given relocation. */
  618. static asection *
  619. visium_elf_gc_mark_hook (asection *sec, struct bfd_link_info *info,
  620. Elf_Internal_Rela *rel, struct elf_link_hash_entry *h,
  621. Elf_Internal_Sym *sym)
  622. {
  623. if (h != NULL)
  624. switch (ELF32_R_TYPE (rel->r_info))
  625. {
  626. case R_VISIUM_GNU_VTINHERIT:
  627. case R_VISIUM_GNU_VTENTRY:
  628. return NULL;
  629. }
  630. return _bfd_elf_gc_mark_hook (sec, info, rel, h, sym);
  631. }
  632. static bool
  633. visium_elf_init_file_header (bfd *abfd, struct bfd_link_info *info)
  634. {
  635. Elf_Internal_Ehdr *i_ehdrp;
  636. if (!_bfd_elf_init_file_header (abfd, info))
  637. return false;
  638. i_ehdrp = elf_elfheader (abfd);
  639. i_ehdrp->e_ident[EI_ABIVERSION] = 1;
  640. return true;
  641. }
  642. /* Function to set the ELF flag bits. */
  643. static bool
  644. visium_elf_set_private_flags (bfd *abfd, flagword flags)
  645. {
  646. elf_elfheader (abfd)->e_flags = flags;
  647. elf_flags_init (abfd) = true;
  648. return true;
  649. }
  650. /* Copy backend specific data from one object module to another. */
  651. static bool
  652. visium_elf_copy_private_bfd_data (bfd *ibfd, bfd *obfd)
  653. {
  654. if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour
  655. || bfd_get_flavour (obfd) != bfd_target_elf_flavour)
  656. return true;
  657. BFD_ASSERT (!elf_flags_init (obfd)
  658. || elf_elfheader (obfd)->e_flags ==
  659. elf_elfheader (ibfd)->e_flags);
  660. elf_elfheader (obfd)->e_flags = elf_elfheader (ibfd)->e_flags;
  661. elf_flags_init (obfd) = true;
  662. /* Copy object attributes. */
  663. _bfd_elf_copy_obj_attributes (ibfd, obfd);
  664. return true;
  665. }
  666. /* Merge backend specific data from an object
  667. file to the output object file when linking. */
  668. static bool
  669. visium_elf_merge_private_bfd_data (bfd *ibfd, struct bfd_link_info *info)
  670. {
  671. bfd *obfd = info->output_bfd;
  672. flagword old_flags;
  673. flagword new_flags;
  674. flagword mismatch;
  675. const char *opt_arch = NULL;
  676. const char *new_opt_with = NULL;
  677. const char *old_opt_with = NULL;
  678. const char *with = "with";
  679. const char *without = "without";
  680. const char *mcm = "mcm";
  681. const char *mcm24 = "mcm24";
  682. const char *gr6 = "gr6";
  683. new_flags = elf_elfheader (ibfd)->e_flags;
  684. old_flags = elf_elfheader (obfd)->e_flags;
  685. if (!elf_flags_init (obfd))
  686. {
  687. /* First call, no flags set. */
  688. elf_flags_init (obfd) = true;
  689. elf_elfheader (obfd)->e_flags = new_flags;
  690. }
  691. else
  692. {
  693. mismatch = (new_flags ^ old_flags)
  694. & (EF_VISIUM_ARCH_MCM | EF_VISIUM_ARCH_MCM24 | EF_VISIUM_ARCH_GR6);
  695. if (mismatch & EF_VISIUM_ARCH_GR6)
  696. {
  697. opt_arch = gr6;
  698. new_opt_with = new_flags & EF_VISIUM_ARCH_GR6 ? with : without;
  699. old_opt_with = old_flags & EF_VISIUM_ARCH_GR6 ? with : without;
  700. }
  701. else if (mismatch & EF_VISIUM_ARCH_MCM)
  702. {
  703. opt_arch = mcm;
  704. new_opt_with = new_flags & EF_VISIUM_ARCH_MCM ? with : without;
  705. old_opt_with = old_flags & EF_VISIUM_ARCH_MCM ? with : without;
  706. }
  707. else if (mismatch & EF_VISIUM_ARCH_MCM24)
  708. {
  709. opt_arch = mcm24;
  710. new_opt_with = new_flags & EF_VISIUM_ARCH_MCM24 ? with : without;
  711. old_opt_with = old_flags & EF_VISIUM_ARCH_MCM24 ? with : without;
  712. }
  713. if (mismatch)
  714. _bfd_error_handler
  715. /* xgettext:c-format */
  716. (_("%pB: compiled %s -mtune=%s and linked with modules"
  717. " compiled %s -mtune=%s"),
  718. ibfd, new_opt_with, opt_arch, old_opt_with, opt_arch);
  719. }
  720. return true;
  721. }
  722. static bool
  723. visium_elf_print_private_bfd_data (bfd *abfd, void *ptr)
  724. {
  725. FILE *file = (FILE *) ptr;
  726. flagword flags;
  727. BFD_ASSERT (abfd != NULL && ptr != NULL);
  728. /* Print normal ELF private data. */
  729. _bfd_elf_print_private_bfd_data (abfd, ptr);
  730. flags = elf_elfheader (abfd)->e_flags;
  731. fprintf (file, _("private flags = 0x%lx:"), (long) flags);
  732. if (flags & EF_VISIUM_ARCH_GR6)
  733. fprintf (file, " -mtune=gr6");
  734. else if (flags & EF_VISIUM_ARCH_MCM)
  735. fprintf (file, " -mtune=mcm");
  736. else if (flags & EF_VISIUM_ARCH_MCM24)
  737. fprintf (file, " -mtune=mcm24");
  738. fputc ('\n', file);
  739. return true;
  740. }
  741. #define ELF_ARCH bfd_arch_visium
  742. #define ELF_MACHINE_CODE EM_VISIUM
  743. #define ELF_OSABI ELFOSABI_STANDALONE
  744. #define ELF_MAXPAGESIZE 1
  745. #define TARGET_BIG_SYM visium_elf32_vec
  746. #define TARGET_BIG_NAME "elf32-visium"
  747. #define elf_info_to_howto_rel NULL
  748. #define elf_info_to_howto visium_info_to_howto_rela
  749. #define elf_backend_relocate_section visium_elf_relocate_section
  750. #define elf_backend_gc_mark_hook visium_elf_gc_mark_hook
  751. #define elf_backend_check_relocs visium_elf_check_relocs
  752. #define elf_backend_rela_normal 1
  753. #define elf_backend_can_gc_sections 1
  754. #define bfd_elf32_bfd_reloc_type_lookup visium_reloc_type_lookup
  755. #define bfd_elf32_bfd_reloc_name_lookup visium_reloc_name_lookup
  756. #define bfd_elf32_bfd_set_private_flags visium_elf_set_private_flags
  757. #define bfd_elf32_bfd_copy_private_bfd_data visium_elf_copy_private_bfd_data
  758. #define bfd_elf32_bfd_merge_private_bfd_data visium_elf_merge_private_bfd_data
  759. #define bfd_elf32_bfd_print_private_bfd_data visium_elf_print_private_bfd_data
  760. #define elf_backend_init_file_header visium_elf_init_file_header
  761. #include "elf32-target.h"