1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25: #include "sysdep.h"
26: #include "bfd.h"
27: #include "libiberty.h"
28: #include "libbfd.h"
29: #include "bfdlink.h"
30: #include "coff/sh.h"
31: #include "coff/internal.h"
32:
33: #ifdef COFF_WITH_PE
34: #include "coff/pe.h"
35:
36: #ifndef COFF_IMAGE_WITH_PE
37: static bfd_boolean sh_align_load_span
38: PARAMS ((bfd *, asection *, bfd_byte *,
39: bfd_boolean (*) (bfd *, asection *, PTR, bfd_byte *, bfd_vma),
40: PTR, bfd_vma **, bfd_vma *, bfd_vma, bfd_vma, bfd_boolean *));
41:
42: #define _bfd_sh_align_load_span sh_align_load_span
43: #endif
44: #endif
45:
46: #include "libcoff.h"
47:
48:
49: static bfd_reloc_status_type sh_reloc
50: PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
51: static long get_symbol_value PARAMS ((asymbol *));
52: static bfd_boolean sh_relax_section
53: PARAMS ((bfd *, asection *, struct bfd_link_info *, bfd_boolean *));
54: static bfd_boolean sh_relax_delete_bytes
55: PARAMS ((bfd *, asection *, bfd_vma, int));
56: #ifndef COFF_IMAGE_WITH_PE
57: static const struct sh_opcode *sh_insn_info PARAMS ((unsigned int));
58: #endif
59: static bfd_boolean sh_align_loads
60: PARAMS ((bfd *, asection *, struct internal_reloc *, bfd_byte *,
61: bfd_boolean *));
62: static bfd_boolean sh_swap_insns
63: PARAMS ((bfd *, asection *, PTR, bfd_byte *, bfd_vma));
64: static bfd_boolean sh_relocate_section
65: PARAMS ((bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *,
66: struct internal_reloc *, struct internal_syment *, asection **));
67: static bfd_byte *sh_coff_get_relocated_section_contents
68: PARAMS ((bfd *, struct bfd_link_info *, struct bfd_link_order *,
69: bfd_byte *, bfd_boolean, asymbol **));
70: static reloc_howto_type * sh_coff_reloc_type_lookup PARAMS ((bfd *, bfd_reloc_code_real_type));
71:
72: #ifdef COFF_WITH_PE
73:
74: #define COFF_DEFAULT_SECTION_ALIGNMENT_POWER 2
75: #else
76:
77: #define COFF_DEFAULT_SECTION_ALIGNMENT_POWER 4
78: #endif
79:
80: #ifdef COFF_IMAGE_WITH_PE
81:
82: #define COFF_PAGE_SIZE 0x1000
83: #endif
84:
85:
86: #define COFF_LONG_FILENAMES
87:
88: #ifdef COFF_WITH_PE
89: static bfd_boolean in_reloc_p PARAMS ((bfd *, reloc_howto_type *));
90:
91:
92: static bfd_boolean in_reloc_p (abfd, howto)
93: bfd * abfd ATTRIBUTE_UNUSED;
94: reloc_howto_type * howto;
95: {
96: return ! howto->pc_relative && howto->type != R_SH_IMAGEBASE;
97: }
98: #endif
99:
100:
101:
102: static reloc_howto_type sh_coff_howtos[] =
103: {
104: EMPTY_HOWTO (0),
105: EMPTY_HOWTO (1),
106: #ifdef COFF_WITH_PE
107:
108: HOWTO (R_SH_IMM32CE,
109: 0,
110: 2,
111: 32,
112: FALSE,
113: 0,
114: complain_overflow_bitfield,
115: sh_reloc,
116: "r_imm32ce",
117: TRUE,
118: 0xffffffff,
119: 0xffffffff,
120: FALSE),
121: #else
122: EMPTY_HOWTO (2),
123: #endif
124: EMPTY_HOWTO (3),
125: EMPTY_HOWTO (4),
126: EMPTY_HOWTO (5),
127: EMPTY_HOWTO (6),
128: EMPTY_HOWTO (7),
129: EMPTY_HOWTO (8),
130: EMPTY_HOWTO (9),
131:
132: HOWTO (R_SH_PCDISP8BY2,
133: 1,
134: 1,
135: 8,
136: TRUE,
137: 0,
138: complain_overflow_signed,
139: sh_reloc,
140: "r_pcdisp8by2",
141: TRUE,
142: 0xff,
143: 0xff,
144: TRUE),
145:
146: EMPTY_HOWTO (11),
147:
148: HOWTO (R_SH_PCDISP,
149: 1,
150: 1,
151: 12,
152: TRUE,
153: 0,
154: complain_overflow_signed,
155: sh_reloc,
156: "r_pcdisp12by2",
157: TRUE,
158: 0xfff,
159: 0xfff,
160: TRUE),
161:
162: EMPTY_HOWTO (13),
163:
164: HOWTO (R_SH_IMM32,
165: 0,
166: 2,
167: 32,
168: FALSE,
169: 0,
170: complain_overflow_bitfield,
171: sh_reloc,
172: "r_imm32",
173: TRUE,
174: 0xffffffff,
175: 0xffffffff,
176: FALSE),
177:
178: EMPTY_HOWTO (15),
179: #ifdef COFF_WITH_PE
180: HOWTO (R_SH_IMAGEBASE,
181: 0,
182: 2,
183: 32,
184: FALSE,
185: 0,
186: complain_overflow_bitfield,
187: sh_reloc,
188: "rva32",
189: TRUE,
190: 0xffffffff,
191: 0xffffffff,
192: FALSE),
193: #else
194: EMPTY_HOWTO (16),
195: #endif
196: EMPTY_HOWTO (17),
197: EMPTY_HOWTO (18),
198: EMPTY_HOWTO (19),
199: EMPTY_HOWTO (20),
200: EMPTY_HOWTO (21),
201:
202: HOWTO (R_SH_PCRELIMM8BY2,
203: 1,
204: 1,
205: 8,
206: TRUE,
207: 0,
208: complain_overflow_unsigned,
209: sh_reloc,
210: "r_pcrelimm8by2",
211: TRUE,
212: 0xff,
213: 0xff,
214: TRUE),
215:
216: HOWTO (R_SH_PCRELIMM8BY4,
217: 2,
218: 1,
219: 8,
220: TRUE,
221: 0,
222: complain_overflow_unsigned,
223: sh_reloc,
224: "r_pcrelimm8by4",
225: TRUE,
226: 0xff,
227: 0xff,
228: TRUE),
229:
230: HOWTO (R_SH_IMM16,
231: 0,
232: 1,
233: 16,
234: FALSE,
235: 0,
236: complain_overflow_bitfield,
237: sh_reloc,
238: "r_imm16",
239: TRUE,
240: 0xffff,
241: 0xffff,
242: FALSE),
243:
244: HOWTO (R_SH_SWITCH16,
245: 0,
246: 1,
247: 16,
248: FALSE,
249: 0,
250: complain_overflow_bitfield,
251: sh_reloc,
252: "r_switch16",
253: TRUE,
254: 0xffff,
255: 0xffff,
256: FALSE),
257:
258: HOWTO (R_SH_SWITCH32,
259: 0,
260: 2,
261: 32,
262: FALSE,
263: 0,
264: complain_overflow_bitfield,
265: sh_reloc,
266: "r_switch32",
267: TRUE,
268: 0xffffffff,
269: 0xffffffff,
270: FALSE),
271:
272: HOWTO (R_SH_USES,
273: 0,
274: 1,
275: 16,
276: FALSE,
277: 0,
278: complain_overflow_bitfield,
279: sh_reloc,
280: "r_uses",
281: TRUE,
282: 0xffff,
283: 0xffff,
284: FALSE),
285:
286: HOWTO (R_SH_COUNT,
287: 0,
288: 2,
289: 32,
290: FALSE,
291: 0,
292: complain_overflow_bitfield,
293: sh_reloc,
294: "r_count",
295: TRUE,
296: 0xffffffff,
297: 0xffffffff,
298: FALSE),
299:
300: HOWTO (R_SH_ALIGN,
301: 0,
302: 2,
303: 32,
304: FALSE,
305: 0,
306: complain_overflow_bitfield,
307: sh_reloc,
308: "r_align",
309: TRUE,
310: 0xffffffff,
311: 0xffffffff,
312: FALSE),
313:
314: HOWTO (R_SH_CODE,
315: 0,
316: 2,
317: 32,
318: FALSE,
319: 0,
320: complain_overflow_bitfield,
321: sh_reloc,
322: "r_code",
323: TRUE,
324: 0xffffffff,
325: 0xffffffff,
326: FALSE),
327:
328: HOWTO (R_SH_DATA,
329: 0,
330: 2,
331: 32,
332: FALSE,
333: 0,
334: complain_overflow_bitfield,
335: sh_reloc,
336: "r_data",
337: TRUE,
338: 0xffffffff,
339: 0xffffffff,
340: FALSE),
341:
342: HOWTO (R_SH_LABEL,
343: 0,
344: 2,
345: 32,
346: FALSE,
347: 0,
348: complain_overflow_bitfield,
349: sh_reloc,
350: "r_label",
351: TRUE,
352: 0xffffffff,
353: 0xffffffff,
354: FALSE),
355:
356: HOWTO (R_SH_SWITCH8,
357: 0,
358: 0,
359: 8,
360: FALSE,
361: 0,
362: complain_overflow_bitfield,
363: sh_reloc,
364: "r_switch8",
365: TRUE,
366: 0xff,
367: 0xff,
368: FALSE)
369: };
370:
371: #define SH_COFF_HOWTO_COUNT (sizeof sh_coff_howtos / sizeof sh_coff_howtos[0])
372:
373:
374: #define BADMAG(x) SHBADMAG(x)
375:
376:
377: #define SH 1
378:
379:
380: #define __A_MAGIC_SET__
381:
382: #ifndef COFF_WITH_PE
383:
384: #define SWAP_IN_RELOC_OFFSET H_GET_32
385: #define SWAP_OUT_RELOC_OFFSET H_PUT_32
386:
387:
388: #define SWAP_OUT_RELOC_EXTRA(abfd, src, dst) \
389: do \
390: { \
391: dst->r_stuff[0] = 'S'; \
392: dst->r_stuff[1] = 'C'; \
393: } \
394: while (0)
395: #endif
396:
397:
398:
399: static long
400: get_symbol_value (symbol)
401: asymbol *symbol;
402: {
403: bfd_vma relocation;
404:
405: if (bfd_is_com_section (symbol->section))
406: relocation = 0;
407: else
408: relocation = (symbol->value +
409: symbol->section->output_section->vma +
410: symbol->section->output_offset);
411:
412: return relocation;
413: }
414:
415: #ifdef COFF_WITH_PE
416:
417:
418: #define coff_rtype_to_howto coff_sh_rtype_to_howto
419: static reloc_howto_type * coff_sh_rtype_to_howto PARAMS ((bfd *, asection *, struct internal_reloc *, struct coff_link_hash_entry *, struct internal_syment *, bfd_vma *));
420:
421: static reloc_howto_type *
422: coff_sh_rtype_to_howto (abfd, sec, rel, h, sym, addendp)
423: bfd * abfd ATTRIBUTE_UNUSED;
424: asection * sec;
425: struct internal_reloc * rel;
426: struct coff_link_hash_entry * h;
427: struct internal_syment * sym;
428: bfd_vma * addendp;
429: {
430: reloc_howto_type * howto;
431:
432: howto = sh_coff_howtos + rel->r_type;
433:
434: *addendp = 0;
435:
436: if (howto->pc_relative)
437: *addendp += sec->vma;
438:
439: if (sym != NULL && sym->n_scnum == 0 && sym->n_value != 0)
440: {
441:
442:
443:
444:
445:
446: BFD_ASSERT (h != NULL);
447: }
448:
449: if (howto->pc_relative)
450: {
451: *addendp -= 4;
452:
453:
454:
455:
456:
457:
458:
459: if (sym != NULL && sym->n_scnum != 0)
460: *addendp -= sym->n_value;
461: }
462:
463: if (rel->r_type == R_SH_IMAGEBASE)
464: *addendp -= pe_data (sec->output_section->owner)->pe_opthdr.ImageBase;
465:
466: return howto;
467: }
468:
469: #endif
470:
471:
472: struct shcoff_reloc_map
473: {
474: bfd_reloc_code_real_type bfd_reloc_val;
475: unsigned char shcoff_reloc_val;
476: };
477:
478: #ifdef COFF_WITH_PE
479:
480: static const struct shcoff_reloc_map sh_reloc_map[] =
481: {
482: { BFD_RELOC_32, R_SH_IMM32CE },
483: { BFD_RELOC_RVA, R_SH_IMAGEBASE },
484: { BFD_RELOC_CTOR, R_SH_IMM32CE },
485: };
486: #else
487:
488: static const struct shcoff_reloc_map sh_reloc_map[] =
489: {
490: { BFD_RELOC_32, R_SH_IMM32 },
491: { BFD_RELOC_CTOR, R_SH_IMM32 },
492: };
493: #endif
494:
495:
496:
497: #define coff_bfd_reloc_type_lookup sh_coff_reloc_type_lookup
498: #define coff_bfd_reloc_name_lookup sh_coff_reloc_name_lookup
499:
500: static reloc_howto_type *
501: sh_coff_reloc_type_lookup (abfd, code)
502: bfd * abfd ATTRIBUTE_UNUSED;
503: bfd_reloc_code_real_type code;
504: {
505: unsigned int i;
506:
507: for (i = ARRAY_SIZE (sh_reloc_map); i--;)
508: if (sh_reloc_map[i].bfd_reloc_val == code)
509: return &sh_coff_howtos[(int) sh_reloc_map[i].shcoff_reloc_val];
510:
511: fprintf (stderr, "SH Error: unknown reloc type %d\n", code);
512: return NULL;
513: }
514:
515: static reloc_howto_type *
516: sh_coff_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED,
517: const char *r_name)
518: {
519: unsigned int i;
520:
521: for (i = 0; i < sizeof (sh_coff_howtos) / sizeof (sh_coff_howtos[0]); i++)
522: if (sh_coff_howtos[i].name != NULL
523: && strcasecmp (sh_coff_howtos[i].name, r_name) == 0)
524: return &sh_coff_howtos[i];
525:
526: return NULL;
527: }
528:
529:
530:
531:
532: #define RTYPE2HOWTO(relent, internal) \
533: ((relent)->howto = \
534: ((internal)->r_type < SH_COFF_HOWTO_COUNT \
535: ? &sh_coff_howtos[(internal)->r_type] \
536: : (reloc_howto_type *) NULL))
537:
538:
539:
540: #define CALC_ADDEND(abfd, ptr, reloc, cache_ptr) \
541: { \
542: coff_symbol_type *coffsym = (coff_symbol_type *) NULL; \
543: if (ptr && bfd_asymbol_bfd (ptr) != abfd) \
544: coffsym = (obj_symbols (abfd) \
545: + (cache_ptr->sym_ptr_ptr - symbols)); \
546: else if (ptr) \
547: coffsym = coff_symbol_from (abfd, ptr); \
548: if (coffsym != (coff_symbol_type *) NULL \
549: && coffsym->native->u.syment.n_scnum == 0) \
550: cache_ptr->addend = 0; \
551: else if (ptr && bfd_asymbol_bfd (ptr) == abfd \
552: