elf32-visium.c 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878
  1. /* Visium-specific support for 32-bit ELF.
  2. Copyright (C) 2003-2015 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. static bfd_reloc_status_type visium_elf_howto_parity_reloc
  23. (bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **);
  24. static reloc_howto_type visium_elf_howto_table[] = {
  25. /* This reloc does nothing. */
  26. HOWTO (R_VISIUM_NONE, /* type */
  27. 0, /* rightshift */
  28. 3, /* size (0 = byte, 1 = short, 2 = long) */
  29. 0, /* bitsize */
  30. FALSE, /* pc_relative */
  31. 0, /* bitpos */
  32. complain_overflow_dont, /* complain_on_overflow */
  33. bfd_elf_generic_reloc, /* special_function */
  34. "R_VISIUM_NONE", /* name */
  35. FALSE, /* partial_inplace */
  36. 0, /* src_mask */
  37. 0, /* dst_mask */
  38. FALSE), /* pcrel_offset */
  39. /* A 8 bit absolute relocation. */
  40. HOWTO (R_VISIUM_8, /* type */
  41. 0, /* rightshift */
  42. 0, /* size (0 = byte, 1 = short, 2 = long) */
  43. 8, /* bitsize */
  44. FALSE, /* pc_relative */
  45. 0, /* bitpos */
  46. complain_overflow_bitfield, /* complain_on_overflow */
  47. bfd_elf_generic_reloc, /* special_function */
  48. "R_VISIUM_8", /* name */
  49. FALSE, /* partial_inplace */
  50. 0x00, /* src_mask */
  51. 0xff, /* dst_mask */
  52. FALSE), /* pcrel_offset */
  53. /* A 16 bit absolute relocation. */
  54. HOWTO (R_VISIUM_16, /* type */
  55. 0, /* rightshift */
  56. 1, /* size (0 = byte, 1 = short, 2 = long) */
  57. 16, /* bitsize */
  58. FALSE, /* pc_relative */
  59. 0, /* bitpos */
  60. complain_overflow_bitfield, /* complain_on_overflow */
  61. bfd_elf_generic_reloc, /* special_function */
  62. "R_VISIUM_16", /* name */
  63. FALSE, /* partial_inplace */
  64. 0x0000, /* src_mask */
  65. 0xffff, /* dst_mask */
  66. FALSE), /* pcrel_offset */
  67. /* A 32 bit absolute relocation. */
  68. HOWTO (R_VISIUM_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_VISIUM_32", /* name */
  77. FALSE, /* partial_inplace */
  78. 0x00000000, /* src_mask */
  79. 0xffffffff, /* dst_mask */
  80. FALSE), /* pcrel_offset */
  81. /* A 8 bit PC relative relocation. */
  82. HOWTO (R_VISIUM_8_PCREL, /* type */
  83. 0, /* rightshift */
  84. 0, /* size (0 = byte, 1 = short, 2 = long) */
  85. 8, /* bitsize */
  86. TRUE, /* pc_relative */
  87. 0, /* bitpos */
  88. complain_overflow_bitfield, /* complain_on_overflow */
  89. bfd_elf_generic_reloc, /* special_function */
  90. "R_VISIUM_8_PCREL", /* name */
  91. FALSE, /* partial_inplace */
  92. 0x00, /* src_mask */
  93. 0xff, /* dst_mask */
  94. TRUE), /* pcrel_offset */
  95. /* A 16 bit PC relative relocation. */
  96. HOWTO (R_VISIUM_16_PCREL, /* type */
  97. 0, /* rightshift */
  98. 1, /* size (0 = byte, 1 = short, 2 = long) */
  99. 16, /* bitsize */
  100. TRUE, /* pc_relative */
  101. 0, /* bitpos */
  102. complain_overflow_bitfield, /* complain_on_overflow */
  103. bfd_elf_generic_reloc, /* special_function */
  104. "R_VISIUM_16_PCREL", /* name */
  105. FALSE, /* partial inplace */
  106. 0x0000, /* src_mask */
  107. 0xffff, /* dst_mask */
  108. TRUE), /* pcrel_offset */
  109. /* A 32-bit PC relative relocation. */
  110. HOWTO (R_VISIUM_32_PCREL, /* type */
  111. 0, /* rightshift */
  112. 2, /* size (0 = byte, 1 = short, 2 = long) */
  113. 32, /* bitsize */
  114. TRUE, /* pc_relative */
  115. 0, /* bitpos */
  116. complain_overflow_bitfield, /* complain_on_overflow */
  117. bfd_elf_generic_reloc, /* special_function */
  118. "R_VISIUM_32_PCREL", /* name */
  119. FALSE, /* partial_inplace */
  120. 0, /* src_mask */
  121. 0xffffffff, /* dst_mask */
  122. TRUE), /* pcrel_offset */
  123. /* A 16-bit PC word relative offset, relative to start of instruction
  124. and always in the second half of the instruction. */
  125. HOWTO (R_VISIUM_PC16, /* type */
  126. 2, /* rightshift */
  127. 2, /* size (0 = byte, 1 = short, 2 = long) */
  128. 16, /* bitsize */
  129. TRUE, /* pc_relative */
  130. 0, /* bitpos */
  131. complain_overflow_signed, /* complain_on_overflow */
  132. visium_elf_howto_parity_reloc, /* special_function */
  133. "R_VISIUM_PC16", /* name */
  134. FALSE, /* partial_inplace */
  135. 0x00000000, /* src_mask */
  136. 0x0000ffff, /* dst_mask */
  137. TRUE), /* pcrel_offset */
  138. /* The high 16 bits of symbol value. */
  139. HOWTO (R_VISIUM_HI16, /* type */
  140. 16, /* rightshift */
  141. 2, /* size (0 = byte, 1 = short, 2 = long) */
  142. 16, /* bitsize */
  143. FALSE, /* pc_relative */
  144. 0, /* bitpos */
  145. complain_overflow_dont, /* complain_on_overflow */
  146. visium_elf_howto_parity_reloc, /* special_function */
  147. "R_VISIUM_HI16", /* name */
  148. FALSE, /* partial_inplace */
  149. 0x00000000, /* src_mask */
  150. 0x0000ffff, /* dst_mask */
  151. FALSE), /* pcrel_offset */
  152. /* The low 16 bits of symbol value. */
  153. HOWTO (R_VISIUM_LO16, /* type */
  154. 0, /* rightshift */
  155. 2, /* size (0 = byte, 1 = short, 2 = long) */
  156. 16, /* bitsize */
  157. FALSE, /* pc_relative */
  158. 0, /* bitpos */
  159. complain_overflow_dont, /* complain_on_overflow */
  160. visium_elf_howto_parity_reloc, /* special_function */
  161. "R_VISIUM_LO16", /* name */
  162. FALSE, /* partial_inplace */
  163. 0x00000000, /* src_mask */
  164. 0x0000ffff, /* dst_mask */
  165. FALSE), /* pcrel_offset */
  166. /* A 16 bit immediate value. */
  167. HOWTO (R_VISIUM_IM16, /* type */
  168. 0, /* rightshift */
  169. 2, /* size (0 = byte, 1 = short, 2 = long) */
  170. 16, /* bitsize */
  171. FALSE, /* pc_relative */
  172. 0, /* bitpos */
  173. complain_overflow_unsigned, /* complain_on_overflow */
  174. visium_elf_howto_parity_reloc, /* special_function */
  175. "R_VISIUM_IM16", /* name */
  176. FALSE, /* partial_inplace */
  177. 0x0000000, /* src_mask */
  178. 0x000ffff, /* dst_mask */
  179. FALSE), /* pcrel_offset */
  180. /* The high 16 bits of symbol value, pc relative. */
  181. HOWTO (R_VISIUM_HI16_PCREL, /* type */
  182. 16, /* rightshift */
  183. 2, /* size (0 = byte, 1 = short, 2 = long) */
  184. 16, /* bitsize */
  185. TRUE, /* pc_relative */
  186. 0, /* bitpos */
  187. complain_overflow_dont, /* complain_on_overflow */
  188. visium_elf_howto_parity_reloc, /* special_function */
  189. "R_VISIUM_HI16_PCREL", /* name */
  190. FALSE, /* partial_inplace */
  191. 0x00000000, /* src_mask */
  192. 0x0000ffff, /* dst_mask */
  193. TRUE), /* pcrel_offset */
  194. /* The low 16 bits of symbol value, pc relative. */
  195. HOWTO (R_VISIUM_LO16_PCREL, /* type */
  196. 0, /* rightshift */
  197. 2, /* size (0 = byte, 1 = short, 2 = long) */
  198. 16, /* bitsize */
  199. TRUE, /* pc_relative */
  200. 0, /* bitpos */
  201. complain_overflow_dont, /* complain_on_overflow */
  202. visium_elf_howto_parity_reloc, /* special_function */
  203. "R_VISIUM_LO16_PCREL", /* name */
  204. FALSE, /* partial_inplace */
  205. 0x00000000, /* src_mask */
  206. 0x0000ffff, /* dst_mask */
  207. TRUE), /* pcrel_offset */
  208. /* A 16 bit immediate value, pc relative. */
  209. HOWTO (R_VISIUM_IM16_PCREL, /* type */
  210. 0, /* rightshift */
  211. 2, /* size (0 = byte, 1 = short, 2 = long) */
  212. 16, /* bitsize */
  213. TRUE, /* pc_relative */
  214. 0, /* bitpos */
  215. complain_overflow_unsigned, /* complain_on_overflow */
  216. visium_elf_howto_parity_reloc, /* special_function */
  217. "R_VISIUM_IM16_PCREL", /* name */
  218. FALSE, /* partial_inplace */
  219. 0x0000000, /* src_mask */
  220. 0x000ffff, /* dst_mask */
  221. TRUE), /* pcrel_offset */
  222. };
  223. /* GNU extension to record C++ vtable hierarchy. */
  224. static reloc_howto_type visium_elf_vtinherit_howto =
  225. HOWTO (R_VISIUM_GNU_VTINHERIT, /* type */
  226. 0, /* rightshift */
  227. 2, /* size (0 = byte, 1 = short, 2 = long) */
  228. 0, /* bitsize */
  229. FALSE, /* pc_relative */
  230. 0, /* bitpos */
  231. complain_overflow_dont, /* complain_on_overflow */
  232. NULL, /* special_function */
  233. "R_VISIUM_GNU_VTINHERIT", /* name */
  234. FALSE, /* partial_inplace */
  235. 0, /* src_mask */
  236. 0, /* dst_mask */
  237. FALSE); /* pcrel_offset */
  238. /* GNU extension to record C++ vtable member usage. */
  239. static reloc_howto_type visium_elf_vtentry_howto =
  240. HOWTO (R_VISIUM_GNU_VTENTRY, /* type */
  241. 0, /* rightshift */
  242. 2, /* size (0 = byte, 1 = short, 2 = long) */
  243. 0, /* bitsize */
  244. FALSE, /* pc_relative */
  245. 0, /* bitpos */
  246. complain_overflow_dont, /* complain_on_overflow */
  247. NULL, /* special_function */
  248. "R_VISIUM_GNU_VTENTRY", /* name */
  249. FALSE, /* partial_inplace */
  250. 0, /* src_mask */
  251. 0, /* dst_mask */
  252. FALSE); /* pcrel_offset */
  253. /* Return the parity bit for INSN shifted to its final position. */
  254. static bfd_vma
  255. visium_parity_bit (bfd_vma insn)
  256. {
  257. bfd_vma p = 0;
  258. int i;
  259. for (i = 0; i < 31; i++)
  260. {
  261. p ^= (insn & 1);
  262. insn >>= 1;
  263. }
  264. return p << 31;
  265. }
  266. /* This "special function" will only be used when the input and
  267. output files have different formats ie. when generating S-records
  268. directly using "--oformat srec". Otherwise we use
  269. _bfd_final_link_relocate which uses a howto structure, but does
  270. not use the special_function field.
  271. It sets instruction parity to even. This cannot be done by a howto. */
  272. static bfd_reloc_status_type
  273. visium_elf_howto_parity_reloc (bfd * input_bfd, arelent *reloc_entry,
  274. asymbol *symbol, PTR data,
  275. asection *input_section, bfd *output_bfd,
  276. char **error_message ATTRIBUTE_UNUSED)
  277. {
  278. bfd_reloc_status_type ret;
  279. bfd_vma relocation;
  280. bfd_byte *inplace_address;
  281. bfd_vma insn;
  282. const bfd_vma signmask = 0xffff8000;
  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. + input_section->output_offset;
  315. relocation -= reloc_entry->address;
  316. }
  317. switch (reloc_entry->howto->type)
  318. {
  319. case R_VISIUM_PC16:
  320. relocation >>= 2;
  321. if (ret == bfd_reloc_ok && (relocation & signmask) != 0
  322. && (relocation & signmask) != signmask)
  323. ret = bfd_reloc_overflow;
  324. relocation &= 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 void
  412. visium_info_to_howto_rela (bfd *abfd ATTRIBUTE_UNUSED, 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 >= (unsigned int) R_VISIUM_max)
  426. {
  427. _bfd_error_handler (_("%B: invalid Visium reloc number: %d"), abfd, r_type);
  428. r_type = 0;
  429. }
  430. cache_ptr->howto = &visium_elf_howto_table[r_type];
  431. break;
  432. }
  433. }
  434. /* Look through the relocs for a section during the first phase.
  435. Since we don't do .gots or .plts, we just need to consider the
  436. virtual table relocs for gc. */
  437. static bfd_boolean
  438. visium_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
  439. asection *sec, const Elf_Internal_Rela *relocs)
  440. {
  441. Elf_Internal_Shdr *symtab_hdr;
  442. struct elf_link_hash_entry **sym_hashes;
  443. const Elf_Internal_Rela *rel;
  444. const Elf_Internal_Rela *rel_end;
  445. if (bfd_link_relocatable (info))
  446. return TRUE;
  447. symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
  448. sym_hashes = elf_sym_hashes (abfd);
  449. rel_end = relocs + sec->reloc_count;
  450. for (rel = relocs; rel < rel_end; rel++)
  451. {
  452. struct elf_link_hash_entry *h;
  453. unsigned long r_symndx;
  454. r_symndx = ELF32_R_SYM (rel->r_info);
  455. if (r_symndx < symtab_hdr->sh_info)
  456. h = NULL;
  457. else
  458. {
  459. h = sym_hashes[r_symndx - symtab_hdr->sh_info];
  460. while (h->root.type == bfd_link_hash_indirect
  461. || h->root.type == bfd_link_hash_warning)
  462. h = (struct elf_link_hash_entry *) h->root.u.i.link;
  463. }
  464. switch (ELF32_R_TYPE (rel->r_info))
  465. {
  466. /* This relocation describes the C++ object vtable hierarchy.
  467. Reconstruct it for later use during GC. */
  468. case R_VISIUM_GNU_VTINHERIT:
  469. if (!bfd_elf_gc_record_vtinherit (abfd, sec, h, rel->r_offset))
  470. return FALSE;
  471. break;
  472. /* This relocation describes which C++ vtable entries are actually
  473. used. Record for later use during GC. */
  474. case R_VISIUM_GNU_VTENTRY:
  475. if (!bfd_elf_gc_record_vtentry (abfd, sec, h, rel->r_addend))
  476. return FALSE;
  477. break;
  478. }
  479. }
  480. return TRUE;
  481. }
  482. /* Relocate a VISIUM ELF section. */
  483. static bfd_boolean
  484. visium_elf_relocate_section (bfd *output_bfd,
  485. struct bfd_link_info *info, bfd *input_bfd,
  486. asection *input_section, bfd_byte *contents,
  487. Elf_Internal_Rela *relocs,
  488. Elf_Internal_Sym *local_syms,
  489. asection **local_sections)
  490. {
  491. Elf_Internal_Shdr *symtab_hdr;
  492. struct elf_link_hash_entry **sym_hashes;
  493. Elf_Internal_Rela *rel;
  494. Elf_Internal_Rela *relend;
  495. symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
  496. sym_hashes = elf_sym_hashes (input_bfd);
  497. relend = relocs + input_section->reloc_count;
  498. for (rel = relocs; rel < relend; rel++)
  499. {
  500. reloc_howto_type *howto;
  501. unsigned long r_symndx;
  502. Elf_Internal_Sym *sym;
  503. asection *sec;
  504. struct elf_link_hash_entry *h;
  505. bfd_vma relocation;
  506. bfd_reloc_status_type r;
  507. const char *name = NULL;
  508. int r_type;
  509. bfd_vma insn;
  510. r_type = ELF32_R_TYPE (rel->r_info);
  511. if (r_type == R_VISIUM_GNU_VTINHERIT || r_type == R_VISIUM_GNU_VTENTRY)
  512. continue;
  513. r_symndx = ELF32_R_SYM (rel->r_info);
  514. howto = visium_elf_howto_table + ELF32_R_TYPE (rel->r_info);
  515. h = NULL;
  516. sym = NULL;
  517. sec = NULL;
  518. if (r_symndx < symtab_hdr->sh_info)
  519. {
  520. /* This is a local symbol. */
  521. sym = local_syms + r_symndx;
  522. sec = local_sections[r_symndx];
  523. relocation = _bfd_elf_rela_local_sym (output_bfd, sym, &sec, rel);
  524. name = bfd_elf_string_from_elf_section
  525. (input_bfd, symtab_hdr->sh_link, sym->st_name);
  526. name = (name == NULL) ? bfd_section_name (input_bfd, sec) : name;
  527. }
  528. else
  529. {
  530. bfd_boolean unresolved_reloc;
  531. bfd_boolean warned, ignored;
  532. RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
  533. r_symndx, symtab_hdr, sym_hashes,
  534. h, sec, relocation,
  535. unresolved_reloc, warned, ignored);
  536. name = h->root.root.string;
  537. }
  538. if (sec != NULL && discarded_section (sec))
  539. {
  540. /* For relocs against symbols from removed linkonce sections,
  541. or sections discarded by a linker script, we just want the
  542. section contents zeroed. Avoid any special processing. */
  543. _bfd_clear_contents (howto, input_bfd, input_section,
  544. contents + rel->r_offset);
  545. rel->r_info = 0;
  546. rel->r_addend = 0;
  547. continue;
  548. }
  549. if (bfd_link_relocatable (info))
  550. continue;
  551. switch (r_type)
  552. {
  553. case R_VISIUM_PC16:
  554. case R_VISIUM_HI16:
  555. case R_VISIUM_LO16:
  556. case R_VISIUM_IM16:
  557. case R_VISIUM_HI16_PCREL:
  558. case R_VISIUM_LO16_PCREL:
  559. case R_VISIUM_IM16_PCREL:
  560. r = _bfd_final_link_relocate (howto, input_bfd, input_section,
  561. contents, rel->r_offset,
  562. relocation, rel->r_addend);
  563. /* For instruction relocations, the parity needs correcting. */
  564. if (r == bfd_reloc_ok)
  565. {
  566. insn = bfd_get_32 (input_bfd, contents + rel->r_offset);
  567. insn = (insn & 0x7fffffff) | visium_parity_bit (insn);
  568. bfd_put_32 (input_bfd, insn, contents + rel->r_offset);
  569. }
  570. break;
  571. default:
  572. r = _bfd_final_link_relocate (howto, input_bfd, input_section,
  573. contents, rel->r_offset,
  574. relocation, rel->r_addend);
  575. break;
  576. }
  577. if (r != bfd_reloc_ok)
  578. {
  579. const char *msg = (const char *) NULL;
  580. switch (r)
  581. {
  582. case bfd_reloc_overflow:
  583. r = info->callbacks->reloc_overflow
  584. (info, (h ? &h->root : NULL), name, howto->name, (bfd_vma) 0,
  585. input_bfd, input_section, rel->r_offset);
  586. break;
  587. case bfd_reloc_undefined:
  588. r = info->callbacks->undefined_symbol
  589. (info, name, input_bfd, input_section, rel->r_offset, TRUE);
  590. break;
  591. case bfd_reloc_outofrange:
  592. msg = _("internal error: out of range error");
  593. break;
  594. case bfd_reloc_notsupported:
  595. msg = _("internal error: unsupported relocation error");
  596. break;
  597. case bfd_reloc_dangerous:
  598. msg = _("internal error: dangerous relocation");
  599. break;
  600. default:
  601. msg = _("internal error: unknown error");
  602. break;
  603. }
  604. if (msg)
  605. r = info->callbacks->warning
  606. (info, msg, name, input_bfd, input_section, rel->r_offset);
  607. if (!r)
  608. return FALSE;
  609. }
  610. }
  611. return TRUE;
  612. }
  613. /* This function is called during section gc to discover the section a
  614. to which a particular relocation refers. Return the section that
  615. should be marked against GC for a given relocation. */
  616. static asection *
  617. visium_elf_gc_mark_hook (asection *sec, struct bfd_link_info *info,
  618. Elf_Internal_Rela *rel, struct elf_link_hash_entry *h,
  619. Elf_Internal_Sym *sym)
  620. {
  621. if (h != NULL)
  622. switch (ELF32_R_TYPE (rel->r_info))
  623. {
  624. case R_VISIUM_GNU_VTINHERIT:
  625. case R_VISIUM_GNU_VTENTRY:
  626. return NULL;
  627. }
  628. return _bfd_elf_gc_mark_hook (sec, info, rel, h, sym);
  629. }
  630. static void
  631. visium_elf_post_process_headers (bfd *abfd,
  632. struct bfd_link_info *info ATTRIBUTE_UNUSED)
  633. {
  634. Elf_Internal_Ehdr *i_ehdrp = elf_elfheader (abfd);
  635. i_ehdrp->e_ident[EI_OSABI] = ELFOSABI_STANDALONE;
  636. i_ehdrp->e_ident[EI_ABIVERSION] = 1;
  637. }
  638. /* Function to set the ELF flag bits. */
  639. static bfd_boolean
  640. visium_elf_set_private_flags (bfd *abfd, flagword flags)
  641. {
  642. elf_elfheader (abfd)->e_flags = flags;
  643. elf_flags_init (abfd) = TRUE;
  644. return TRUE;
  645. }
  646. /* Copy backend specific data from one object module to another. */
  647. static bfd_boolean
  648. visium_elf_copy_private_bfd_data (bfd *ibfd, bfd *obfd)
  649. {
  650. if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour
  651. || bfd_get_flavour (obfd) != bfd_target_elf_flavour)
  652. return TRUE;
  653. BFD_ASSERT (!elf_flags_init (obfd)
  654. || elf_elfheader (obfd)->e_flags ==
  655. elf_elfheader (ibfd)->e_flags);
  656. elf_elfheader (obfd)->e_flags = elf_elfheader (ibfd)->e_flags;
  657. elf_flags_init (obfd) = TRUE;
  658. /* Copy object attributes. */
  659. _bfd_elf_copy_obj_attributes (ibfd, obfd);
  660. return TRUE;
  661. }
  662. /* Merge backend specific data from an object
  663. file to the output object file when linking. */
  664. static bfd_boolean
  665. visium_elf_merge_private_bfd_data (bfd *ibfd, bfd *obfd)
  666. {
  667. flagword old_flags;
  668. flagword new_flags;
  669. flagword mismatch;
  670. const char *opt_arch = NULL;
  671. const char *new_opt_with = NULL;
  672. const char *old_opt_with = NULL;
  673. const char *with = "with";
  674. const char *without = "without";
  675. const char *mcm = "mcm";
  676. const char *mcm24 = "mcm24";
  677. const char *gr6 = "gr6";
  678. new_flags = elf_elfheader (ibfd)->e_flags;
  679. old_flags = elf_elfheader (obfd)->e_flags;
  680. if (!elf_flags_init (obfd))
  681. {
  682. /* First call, no flags set. */
  683. elf_flags_init (obfd) = TRUE;
  684. elf_elfheader (obfd)->e_flags = new_flags;
  685. }
  686. else
  687. {
  688. mismatch = (new_flags ^ old_flags)
  689. & (EF_VISIUM_ARCH_MCM | EF_VISIUM_ARCH_MCM24 | EF_VISIUM_ARCH_GR6);
  690. if (mismatch & EF_VISIUM_ARCH_GR6)
  691. {
  692. opt_arch = gr6;
  693. new_opt_with = new_flags & EF_VISIUM_ARCH_GR6 ? with : without;
  694. old_opt_with = old_flags & EF_VISIUM_ARCH_GR6 ? with : without;
  695. }
  696. else if (mismatch & EF_VISIUM_ARCH_MCM)
  697. {
  698. opt_arch = mcm;
  699. new_opt_with = new_flags & EF_VISIUM_ARCH_MCM ? with : without;
  700. old_opt_with = old_flags & EF_VISIUM_ARCH_MCM ? with : without;
  701. }
  702. else if (mismatch & EF_VISIUM_ARCH_MCM24)
  703. {
  704. opt_arch = mcm24;
  705. new_opt_with = new_flags & EF_VISIUM_ARCH_MCM24 ? with : without;
  706. old_opt_with = old_flags & EF_VISIUM_ARCH_MCM24 ? with : without;
  707. }
  708. if (mismatch)
  709. _bfd_error_handler
  710. (_
  711. ("%s: compiled %s -mtune=%s and linked with modules"
  712. " compiled %s -mtune=%s"),
  713. bfd_get_filename (ibfd), new_opt_with, opt_arch, old_opt_with,
  714. opt_arch);
  715. }
  716. return TRUE;
  717. }
  718. static bfd_boolean
  719. visium_elf_print_private_bfd_data (bfd *abfd, void *ptr)
  720. {
  721. FILE *file = (FILE *) ptr;
  722. flagword flags;
  723. BFD_ASSERT (abfd != NULL && ptr != NULL);
  724. /* Print normal ELF private data. */
  725. _bfd_elf_print_private_bfd_data (abfd, ptr);
  726. flags = elf_elfheader (abfd)->e_flags;
  727. fprintf (file, _("private flags = 0x%lx:"), (long) flags);
  728. if (flags & EF_VISIUM_ARCH_GR6)
  729. fprintf (file, " -mtune=gr6");
  730. else if (flags & EF_VISIUM_ARCH_MCM)
  731. fprintf (file, " -mtune=mcm");
  732. else if (flags & EF_VISIUM_ARCH_MCM24)
  733. fprintf (file, " -mtune=mcm24");
  734. fputc ('\n', file);
  735. return TRUE;
  736. }
  737. #define ELF_ARCH bfd_arch_visium
  738. #define ELF_MACHINE_CODE EM_VISIUM
  739. #define ELF_MAXPAGESIZE 1
  740. #define TARGET_BIG_SYM visium_elf32_vec
  741. #define TARGET_BIG_NAME "elf32-visium"
  742. #define elf_info_to_howto_rel NULL
  743. #define elf_info_to_howto visium_info_to_howto_rela
  744. #define elf_backend_relocate_section visium_elf_relocate_section
  745. #define elf_backend_gc_mark_hook visium_elf_gc_mark_hook
  746. #define elf_backend_check_relocs visium_elf_check_relocs
  747. #define elf_backend_rela_normal 1
  748. #define elf_backend_can_gc_sections 1
  749. #define bfd_elf32_bfd_reloc_type_lookup visium_reloc_type_lookup
  750. #define bfd_elf32_bfd_reloc_name_lookup visium_reloc_name_lookup
  751. #define bfd_elf32_bfd_set_private_flags visium_elf_set_private_flags
  752. #define bfd_elf32_bfd_copy_private_bfd_data visium_elf_copy_private_bfd_data
  753. #define bfd_elf32_bfd_merge_private_bfd_data visium_elf_merge_private_bfd_data
  754. #define bfd_elf32_bfd_print_private_bfd_data visium_elf_print_private_bfd_data
  755. #define elf_backend_post_process_headers visium_elf_post_process_headers
  756. #include "elf32-target.h"