coff-z8k.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382
  1. /* BFD back-end for Zilog Z800n COFF binaries.
  2. Copyright (C) 1992-2022 Free Software Foundation, Inc.
  3. Contributed by Cygnus Support.
  4. Written by Steve Chamberlain, <sac@cygnus.com>.
  5. This file is part of BFD, the Binary File Descriptor library.
  6. This program is free software; you can redistribute it and/or modify
  7. it under the terms of the GNU General Public License as published by
  8. the Free Software Foundation; either version 3 of the License, or
  9. (at your option) any later version.
  10. This program is distributed in the hope that it will be useful,
  11. but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. GNU General Public License for more details.
  14. You should have received a copy of the GNU General Public License
  15. along with this program; if not, write to the Free Software
  16. Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
  17. MA 02110-1301, USA. */
  18. #include "sysdep.h"
  19. #include "bfd.h"
  20. #include "libbfd.h"
  21. #include "bfdlink.h"
  22. #include "coff/z8k.h"
  23. #include "coff/internal.h"
  24. #include "libcoff.h"
  25. #define COFF_DEFAULT_SECTION_ALIGNMENT_POWER (1)
  26. static reloc_howto_type r_imm32 =
  27. HOWTO (R_IMM32, 0, 2, 32, false, 0,
  28. complain_overflow_bitfield, 0, "r_imm32", true, 0xffffffff,
  29. 0xffffffff, false);
  30. static reloc_howto_type r_imm4l =
  31. HOWTO (R_IMM4L, 0, 0, 4, false, 0,
  32. complain_overflow_bitfield, 0, "r_imm4l", true, 0xf, 0xf, false);
  33. static reloc_howto_type r_da =
  34. HOWTO (R_IMM16, 0, 1, 16, false, 0,
  35. complain_overflow_bitfield, 0, "r_da", true, 0x0000ffff, 0x0000ffff,
  36. false);
  37. static reloc_howto_type r_imm8 =
  38. HOWTO (R_IMM8, 0, 0, 8, false, 0,
  39. complain_overflow_bitfield, 0, "r_imm8", true, 0x000000ff, 0x000000ff,
  40. false);
  41. static reloc_howto_type r_rel16 =
  42. HOWTO (R_REL16, 0, 1, 16, false, 0,
  43. complain_overflow_bitfield, 0, "r_rel16", true, 0x0000ffff, 0x0000ffff,
  44. true);
  45. static reloc_howto_type r_jr =
  46. HOWTO (R_JR, 1, 0, 8, true, 0, complain_overflow_signed, 0,
  47. "r_jr", true, 0xff, 0xff, true);
  48. static reloc_howto_type r_disp7 =
  49. HOWTO (R_DISP7, 0, 0, 7, true, 0, complain_overflow_bitfield, 0,
  50. "r_disp7", true, 0x7f, 0x7f, true);
  51. static reloc_howto_type r_callr =
  52. HOWTO (R_CALLR, 1, 1, 12, true, 0, complain_overflow_signed, 0,
  53. "r_callr", true, 0xfff, 0xfff, true);
  54. #define BADMAG(x) Z8KBADMAG(x)
  55. #define Z8K 1 /* Customize coffcode.h. */
  56. #define __A_MAGIC_SET__
  57. /* Code to swap in the reloc. */
  58. #define SWAP_IN_RELOC_OFFSET H_GET_32
  59. #define SWAP_OUT_RELOC_OFFSET H_PUT_32
  60. #define SWAP_OUT_RELOC_EXTRA(abfd, src, dst) \
  61. dst->r_stuff[0] = 'S'; \
  62. dst->r_stuff[1] = 'C';
  63. /* Code to turn a r_type into a howto ptr, uses the above howto table. */
  64. static void
  65. rtype2howto (arelent *internal, struct internal_reloc *dst)
  66. {
  67. switch (dst->r_type)
  68. {
  69. default:
  70. internal->howto = NULL;
  71. break;
  72. case R_IMM8:
  73. internal->howto = &r_imm8;
  74. break;
  75. case R_IMM16:
  76. internal->howto = &r_da;
  77. break;
  78. case R_JR:
  79. internal->howto = &r_jr;
  80. break;
  81. case R_DISP7:
  82. internal->howto = &r_disp7;
  83. break;
  84. case R_CALLR:
  85. internal->howto = &r_callr;
  86. break;
  87. case R_REL16:
  88. internal->howto = &r_rel16;
  89. break;
  90. case R_IMM32:
  91. internal->howto = &r_imm32;
  92. break;
  93. case R_IMM4L:
  94. internal->howto = &r_imm4l;
  95. break;
  96. }
  97. }
  98. #define RTYPE2HOWTO(internal, relocentry) rtype2howto (internal, relocentry)
  99. static reloc_howto_type *
  100. coff_z8k_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
  101. bfd_reloc_code_real_type code)
  102. {
  103. switch (code)
  104. {
  105. case BFD_RELOC_8: return & r_imm8;
  106. case BFD_RELOC_16: return & r_da;
  107. case BFD_RELOC_32: return & r_imm32;
  108. case BFD_RELOC_8_PCREL: return & r_jr;
  109. case BFD_RELOC_16_PCREL: return & r_rel16;
  110. case BFD_RELOC_Z8K_DISP7: return & r_disp7;
  111. case BFD_RELOC_Z8K_CALLR: return & r_callr;
  112. case BFD_RELOC_Z8K_IMM4L: return & r_imm4l;
  113. default: BFD_FAIL ();
  114. return 0;
  115. }
  116. }
  117. static reloc_howto_type *
  118. coff_z8k_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED,
  119. const char *r_name)
  120. {
  121. if (strcasecmp (r_imm8.name, r_name) == 0)
  122. return &r_imm8;
  123. if (strcasecmp (r_da.name, r_name) == 0)
  124. return &r_da;
  125. if (strcasecmp (r_imm32.name, r_name) == 0)
  126. return &r_imm32;
  127. if (strcasecmp (r_jr.name, r_name) == 0)
  128. return &r_jr;
  129. if (strcasecmp (r_rel16.name, r_name) == 0)
  130. return &r_rel16;
  131. if (strcasecmp (r_disp7.name, r_name) == 0)
  132. return &r_disp7;
  133. if (strcasecmp (r_callr.name, r_name) == 0)
  134. return &r_callr;
  135. if (strcasecmp (r_imm4l.name, r_name) == 0)
  136. return &r_imm4l;
  137. return NULL;
  138. }
  139. /* Perform any necessary magic to the addend in a reloc entry. */
  140. #define CALC_ADDEND(abfd, symbol, ext_reloc, cache_ptr) \
  141. cache_ptr->addend = ext_reloc.r_offset;
  142. #define RELOC_PROCESSING(relent,reloc,symbols,abfd,section) \
  143. reloc_processing(relent, reloc, symbols, abfd, section)
  144. static void
  145. reloc_processing (arelent *relent,
  146. struct internal_reloc *reloc,
  147. asymbol **symbols,
  148. bfd *abfd,
  149. asection *section)
  150. {
  151. relent->address = reloc->r_vaddr;
  152. rtype2howto (relent, reloc);
  153. if (reloc->r_symndx == -1)
  154. relent->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr;
  155. else if (reloc->r_symndx >= 0 && reloc->r_symndx < obj_conv_table_size (abfd))
  156. relent->sym_ptr_ptr = symbols + obj_convert (abfd)[reloc->r_symndx];
  157. else
  158. {
  159. _bfd_error_handler
  160. /* xgettext:c-format */
  161. (_("%pB: warning: illegal symbol index %ld in relocs"),
  162. abfd, reloc->r_symndx);
  163. relent->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr;
  164. }
  165. relent->addend = reloc->r_offset;
  166. relent->address -= section->vma;
  167. }
  168. static void
  169. extra_case (bfd *in_abfd,
  170. struct bfd_link_info *link_info,
  171. struct bfd_link_order *link_order,
  172. arelent *reloc,
  173. bfd_byte *data,
  174. unsigned int *src_ptr,
  175. unsigned int *dst_ptr)
  176. {
  177. asection * input_section = link_order->u.indirect.section;
  178. switch (reloc->howto->type)
  179. {
  180. case R_IMM8:
  181. bfd_put_8 (in_abfd,
  182. bfd_coff_reloc16_get_value (reloc, link_info, input_section),
  183. data + *dst_ptr);
  184. (*dst_ptr) += 1;
  185. (*src_ptr) += 1;
  186. break;
  187. case R_IMM32:
  188. /* If no flags are set, assume immediate value. */
  189. if (! (*reloc->sym_ptr_ptr)->section->flags)
  190. {
  191. bfd_put_32 (in_abfd,
  192. bfd_coff_reloc16_get_value (reloc, link_info,
  193. input_section),
  194. data + *dst_ptr);
  195. }
  196. else
  197. {
  198. bfd_vma dst = bfd_coff_reloc16_get_value (reloc, link_info,
  199. input_section);
  200. /* Addresses are 23 bit, and the layout of those in a 32-bit
  201. value is as follows:
  202. 1AAAAAAA xxxxxxxx AAAAAAAA AAAAAAAA
  203. (A - address bits, x - ignore). */
  204. dst = (dst & 0xffff) | ((dst & 0xff0000) << 8) | 0x80000000;
  205. bfd_put_32 (in_abfd, dst, data + *dst_ptr);
  206. }
  207. (*dst_ptr) += 4;
  208. (*src_ptr) += 4;
  209. break;
  210. case R_IMM4L:
  211. bfd_put_8 (in_abfd,
  212. ((bfd_get_8 (in_abfd, data + *dst_ptr) & 0xf0)
  213. | (0x0f
  214. & bfd_coff_reloc16_get_value (reloc, link_info,
  215. input_section))),
  216. data + *dst_ptr);
  217. (*dst_ptr) += 1;
  218. (*src_ptr) += 1;
  219. break;
  220. case R_IMM16:
  221. bfd_put_16 (in_abfd,
  222. bfd_coff_reloc16_get_value (reloc, link_info, input_section),
  223. data + *dst_ptr);
  224. (*dst_ptr) += 2;
  225. (*src_ptr) += 2;
  226. break;
  227. case R_JR:
  228. {
  229. bfd_vma dst = bfd_coff_reloc16_get_value (reloc, link_info,
  230. input_section);
  231. bfd_vma dot = (*dst_ptr
  232. + input_section->output_offset
  233. + input_section->output_section->vma);
  234. int gap = dst - dot - 1; /* -1, since we're in the odd byte of the
  235. word and the pc's been incremented. */
  236. if (gap & 1)
  237. abort ();
  238. gap /= 2;
  239. if (gap > 127 || gap < -128)
  240. (*link_info->callbacks->reloc_overflow)
  241. (link_info, NULL, bfd_asymbol_name (*reloc->sym_ptr_ptr),
  242. reloc->howto->name, reloc->addend, input_section->owner,
  243. input_section, reloc->address);
  244. bfd_put_8 (in_abfd, gap, data + *dst_ptr);
  245. (*dst_ptr)++;
  246. (*src_ptr)++;
  247. break;
  248. }
  249. case R_DISP7:
  250. {
  251. bfd_vma dst = bfd_coff_reloc16_get_value (reloc, link_info,
  252. input_section);
  253. bfd_vma dot = (*dst_ptr
  254. + input_section->output_offset
  255. + input_section->output_section->vma);
  256. int gap = dst - dot - 1; /* -1, since we're in the odd byte of the
  257. word and the pc's been incremented. */
  258. if (gap & 1)
  259. abort ();
  260. gap /= 2;
  261. if (gap > 0 || gap < -127)
  262. (*link_info->callbacks->reloc_overflow)
  263. (link_info, NULL, bfd_asymbol_name (*reloc->sym_ptr_ptr),
  264. reloc->howto->name, reloc->addend, input_section->owner,
  265. input_section, reloc->address);
  266. bfd_put_8 (in_abfd,
  267. (bfd_get_8 ( in_abfd, data + *dst_ptr) & 0x80) + (-gap & 0x7f),
  268. data + *dst_ptr);
  269. (*dst_ptr)++;
  270. (*src_ptr)++;
  271. break;
  272. }
  273. case R_CALLR:
  274. {
  275. bfd_vma dst = bfd_coff_reloc16_get_value (reloc, link_info,
  276. input_section);
  277. bfd_vma dot = (*dst_ptr
  278. + input_section->output_offset
  279. + input_section->output_section->vma);
  280. int gap = dst - dot - 2;
  281. if (gap & 1)
  282. abort ();
  283. if (gap > 4096 || gap < -4095)
  284. (*link_info->callbacks->reloc_overflow)
  285. (link_info, NULL, bfd_asymbol_name (*reloc->sym_ptr_ptr),
  286. reloc->howto->name, reloc->addend, input_section->owner,
  287. input_section, reloc->address);
  288. gap /= 2;
  289. bfd_put_16 (in_abfd,
  290. (bfd_get_16 ( in_abfd, data + *dst_ptr) & 0xf000) | (-gap & 0x0fff),
  291. data + *dst_ptr);
  292. (*dst_ptr) += 2;
  293. (*src_ptr) += 2;
  294. break;
  295. }
  296. case R_REL16:
  297. {
  298. bfd_vma dst = bfd_coff_reloc16_get_value (reloc, link_info,
  299. input_section);
  300. bfd_vma dot = (*dst_ptr
  301. + input_section->output_offset
  302. + input_section->output_section->vma);
  303. int gap = dst - dot - 2;
  304. if (gap > 32767 || gap < -32768)
  305. (*link_info->callbacks->reloc_overflow)
  306. (link_info, NULL, bfd_asymbol_name (*reloc->sym_ptr_ptr),
  307. reloc->howto->name, reloc->addend, input_section->owner,
  308. input_section, reloc->address);
  309. bfd_put_16 (in_abfd, (bfd_vma) gap, data + *dst_ptr);
  310. (*dst_ptr) += 2;
  311. (*src_ptr) += 2;
  312. break;
  313. }
  314. default:
  315. abort ();
  316. }
  317. }
  318. #define coff_reloc16_extra_cases extra_case
  319. #define coff_bfd_reloc_type_lookup coff_z8k_reloc_type_lookup
  320. #define coff_bfd_reloc_name_lookup coff_z8k_reloc_name_lookup
  321. #ifndef bfd_pe_print_pdata
  322. #define bfd_pe_print_pdata NULL
  323. #endif
  324. #include "coffcode.h"
  325. #undef coff_bfd_get_relocated_section_contents
  326. #define coff_bfd_get_relocated_section_contents \
  327. bfd_coff_reloc16_get_relocated_section_contents
  328. #undef coff_bfd_relax_section
  329. #define coff_bfd_relax_section bfd_coff_reloc16_relax_section
  330. CREATE_BIG_COFF_TARGET_VEC (z8k_coff_vec, "coff-z8k", 0, 0, '_', NULL, COFF_SWAP_TABLE)