1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24: #include "sysdep.h"
25: #include "bfd.h"
26: #include "libbfd.h"
27: #include "coff/arm.h"
28: #include "coff/internal.h"
29:
30: #ifdef COFF_WITH_PE
31: #include "coff/pe.h"
32: #endif
33:
34: #include "libcoff.h"
35:
36:
37:
38: #define APCS_26_FLAG(abfd) \
39: (coff_data (abfd)->flags & F_APCS_26)
40:
41: #define APCS_FLOAT_FLAG(abfd) \
42: (coff_data (abfd)->flags & F_APCS_FLOAT)
43:
44: #define PIC_FLAG(abfd) \
45: (coff_data (abfd)->flags & F_PIC)
46:
47: #define APCS_SET(abfd) \
48: (coff_data (abfd)->flags & F_APCS_SET)
49:
50: #define SET_APCS_FLAGS(abfd, flgs) \
51: do \
52: { \
53: coff_data (abfd)->flags &= ~(F_APCS_26 | F_APCS_FLOAT | F_PIC); \
54: coff_data (abfd)->flags |= (flgs) | F_APCS_SET; \
55: } \
56: while (0)
57:
58: #define INTERWORK_FLAG(abfd) \
59: (coff_data (abfd)->flags & F_INTERWORK)
60:
61: #define INTERWORK_SET(abfd) \
62: (coff_data (abfd)->flags & F_INTERWORK_SET)
63:
64: #define SET_INTERWORK_FLAG(abfd, flg) \
65: do \
66: { \
67: coff_data (abfd)->flags &= ~F_INTERWORK; \
68: coff_data (abfd)->flags |= (flg) | F_INTERWORK_SET; \
69: } \
70: while (0)
71:
72: #ifndef NUM_ELEM
73: #define NUM_ELEM(a) ((sizeof (a)) / sizeof ((a)[0]))
74: #endif
75:
76: typedef enum {bunknown, b9, b12, b23} thumb_pcrel_branchtype;
77:
78: typedef unsigned long int insn32;
79: typedef unsigned short int insn16;
80:
81:
82:
83:
84:
85:
86: #define THUMB2ARM_GLUE_SECTION_NAME ".glue_7t"
87: #define THUMB2ARM_GLUE_ENTRY_NAME "__%s_from_thumb"
88:
89: #define ARM2THUMB_GLUE_SECTION_NAME ".glue_7"
90: #define ARM2THUMB_GLUE_ENTRY_NAME "__%s_from_arm"
91:
92:
93:
94: static bfd_reloc_status_type
95: coff_arm_reloc (bfd *abfd,
96: arelent *reloc_entry,
97: asymbol *symbol ATTRIBUTE_UNUSED,
98: void * data,
99: asection *input_section ATTRIBUTE_UNUSED,
100: bfd *output_bfd,
101: char **error_message ATTRIBUTE_UNUSED)
102: {
103: symvalue diff;
104:
105: if (output_bfd == NULL)
106: return bfd_reloc_continue;
107:
108: diff = reloc_entry->addend;
109:
110: #define DOIT(x) \
111: x = ((x & ~howto->dst_mask) \
112: | (((x & howto->src_mask) + diff) & howto->dst_mask))
113:
114: if (diff != 0)
115: {
116: reloc_howto_type *howto = reloc_entry->howto;
117: unsigned char *addr = (unsigned char *) data + reloc_entry->address;
118:
119: switch (howto->size)
120: {
121: case 0:
122: {
123: char x = bfd_get_8 (abfd, addr);
124: DOIT (x);
125: bfd_put_8 (abfd, x, addr);
126: }
127: break;
128:
129: case 1:
130: {
131: short x = bfd_get_16 (abfd, addr);
132: DOIT (x);
133: bfd_put_16 (abfd, (bfd_vma) x, addr);
134: }
135: break;
136:
137: case 2:
138: {
139: long x = bfd_get_32 (abfd, addr);
140: DOIT (x);
141: bfd_put_32 (abfd, (bfd_vma) x, addr);
142: }
143: break;
144:
145: default:
146: abort ();
147: }
148: }
149:
150:
151: return bfd_reloc_continue;
152: }
153:
154:
155:
156:
157: #ifndef TARGET_UNDERSCORE
158: #define TARGET_UNDERSCORE '_'
159: #endif
160:
161: #ifndef PCRELOFFSET
162: #define PCRELOFFSET TRUE
163: #endif
164:
165:
166:
167:
168: #ifdef ARM_WINCE
169:
170: #define ARM_26D 0
171: #define ARM_32 1
172: #define ARM_RVA32 2
173: #define ARM_26 3
174: #define ARM_THUMB12 4
175: #define ARM_SECTION 14
176: #define ARM_SECREL 15
177:
178: #else
179:
180: #define ARM_8 0
181: #define ARM_16 1
182: #define ARM_32 2
183: #define ARM_26 3
184: #define ARM_DISP8 4
185: #define ARM_DISP16 5
186: #define ARM_DISP32 6
187: #define ARM_26D 7
188:
189: #define ARM_NEG16 9
190: #define ARM_NEG32 10
191: #define ARM_RVA32 11
192: #define ARM_THUMB9 12
193: #define ARM_THUMB12 13
194: #define ARM_THUMB23 14
195:
196: #endif
197:
198: static bfd_reloc_status_type aoutarm_fix_pcrel_26_done
199: (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **);
200: static bfd_reloc_status_type aoutarm_fix_pcrel_26
201: (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **);
202: static bfd_reloc_status_type coff_thumb_pcrel_12
203: (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **);
204: #ifndef ARM_WINCE
205: static bfd_reloc_status_type coff_thumb_pcrel_9
206: (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **);
207: static bfd_reloc_status_type coff_thumb_pcrel_23
208: (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **);
209: #endif
210:
211: static reloc_howto_type aoutarm_std_reloc_howto[] =
212: {
213: #ifdef ARM_WINCE
214: HOWTO (ARM_26D,
215: 2,
216: 2,
217: 24,
218: TRUE,
219: 0,
220: complain_overflow_dont,
221: aoutarm_fix_pcrel_26_done,
222: "ARM_26D",
223: TRUE,
224: 0x00ffffff,
225: 0x0,
226: PCRELOFFSET),
227: HOWTO (ARM_32,
228: 0,
229: 2,
230: 32,
231: FALSE,
232: 0,
233: complain_overflow_bitfield,
234: coff_arm_reloc,
235: "ARM_32",
236: TRUE,
237: 0xffffffff,
238: 0xffffffff,
239: PCRELOFFSET),
240: HOWTO (ARM_RVA32,
241: 0,
242: 2,
243: 32,
244: FALSE,
245: 0,
246: complain_overflow_bitfield,
247: coff_arm_reloc,
248: "ARM_RVA32",
249: TRUE,
250: 0xffffffff,
251: 0xffffffff,
252: PCRELOFFSET),
253: HOWTO (ARM_26,
254: 2,
255: 2,
256: 24,
257: TRUE,
258: 0,
259: complain_overflow_signed,
260: aoutarm_fix_pcrel_26 ,
261: "ARM_26",
262: FALSE,
263: 0x00ffffff,
264: 0x00ffffff,
265: PCRELOFFSET),
266: HOWTO (ARM_THUMB12,
267: 1,
268: 1,
269: 11,
270: TRUE,
271: 0,
272: complain_overflow_signed,
273: coff_thumb_pcrel_12 ,
274: "ARM_THUMB12",
275: FALSE,
276: 0x000007ff,
277: 0x000007ff,
278: PCRELOFFSET),
279: EMPTY_HOWTO (-1),
280: EMPTY_HOWTO (-1),
281: EMPTY_HOWTO (-1),
282: EMPTY_HOWTO (-1),
283: EMPTY_HOWTO (-1),
284: EMPTY_HOWTO (-1),
285: EMPTY_HOWTO (-1),
286: EMPTY_HOWTO (-1),
287: EMPTY_HOWTO (-1),
288: HOWTO (ARM_SECTION,
289: 0,
290: 1,
291: 16,
292: FALSE,
293: 0,
294: complain_overflow_bitfield,
295: coff_arm_reloc,
296: "ARM_SECTION",
297: TRUE,
298: 0x0000ffff,
299: 0x0000ffff,
300: PCRELOFFSET),
301: HOWTO (ARM_SECREL,
302: 0,
303: 2,
304: 32,
305: FALSE,
306: 0,
307: complain_overflow_bitfield,
308: coff_arm_reloc,
309: "ARM_SECREL",
310: TRUE,
311: 0xffffffff,
312: 0xffffffff,
313: PCRELOFFSET),
314: #else
315: HOWTO (ARM_8,
316: 0,
317: 0,
318: 8,
319: FALSE,
320: 0,
321: complain_overflow_bitfield,
322: coff_arm_reloc,
323: "ARM_8",
324: TRUE,
325: 0x000000ff,
326: 0x000000ff,
327: PCRELOFFSET),
328: HOWTO (ARM_16,
329: 0,
330: 1,
331: 16,
332: FALSE,
333: 0,
334: complain_overflow_bitfield,
335: coff_arm_reloc,
336: "ARM_16",
337: TRUE,
338: 0x0000ffff,
339: 0x0000ffff,
340: PCRELOFFSET),
341: HOWTO (ARM_32,
342: 0,
343: 2,
344: 32,
345: FALSE,
346: 0,
347: complain_overflow_bitfield,
348: coff_arm_reloc,
349: "ARM_32",
350: TRUE,
351: 0xffffffff,
352: 0xffffffff,
353: PCRELOFFSET),
354: HOWTO (ARM_26,
355: 2,
356: 2,
357: 24,
358: TRUE,
359: 0,
360: complain_overflow_signed,
361: aoutarm_fix_pcrel_26 ,
362: "ARM_26",
363: FALSE,
364: 0x00ffffff,
365: 0x00ffffff,
366: PCRELOFFSET),
367: HOWTO (ARM_DISP8,
368: 0,
369: 0,
370: 8,
371: TRUE,
372: 0,
373: complain_overflow_signed,
374: coff_arm_reloc,
375: "ARM_DISP8",
376: TRUE,
377: 0x000000ff,
378: 0x000000ff,
379: TRUE),
380: HOWTO (ARM_DISP16,
381: 0,
382: 1,
383: 16,
384: TRUE,
385: 0,
386: complain_overflow_signed,
387: coff_arm_reloc,
388: "ARM_DISP16",
389: TRUE,
390: 0x0000ffff,
391: 0x0000ffff,
392: TRUE),
393: HOWTO (ARM_DISP32,
394: 0,
395: 2,
396: 32,
397: TRUE,
398: 0,
399: complain_overflow_signed,
400: coff_arm_reloc,
401: "ARM_DISP32",
402: TRUE,
403: 0xffffffff,
404: 0xffffffff,
405: TRUE),
406: HOWTO (ARM_26D,
407: 2,
408: 2,
409: 24,
410: FALSE,
411: 0,
412: complain_overflow_dont,
413: aoutarm_fix_pcrel_26_done,
414: "ARM_26D",
415: TRUE,
416: 0x00ffffff,
417: 0x0,
418: FALSE),
419:
420: EMPTY_HOWTO (-1),
421: HOWTO (ARM_NEG16,
422: 0,
423: -1,
424: 16,
425: FALSE,
426: 0,
427: complain_overflow_bitfield,
428: coff_arm_reloc,
429: "ARM_NEG16",
430: TRUE,
431: 0x0000ffff,
432: 0x0000ffff,
433: FALSE),
434: HOWTO (ARM_NEG32,
435: 0,
436: -2,
437: 32,
438: FALSE,
439: 0,
440: complain_overflow_bitfield,
441: coff_arm_reloc,
442: "ARM_NEG32",
443: TRUE,
444: 0xffffffff,
445: 0xffffffff,
446: FALSE),
447: HOWTO (ARM_RVA32,
448: 0,
449: 2,
450: 32,
451: FALSE,
452: 0,
453: complain_overflow_bitfield,
454: coff_arm_reloc,
455: "ARM_RVA32",
456: TRUE,
457: 0xffffffff,
458: 0xffffffff,
459: PCRELOFFSET),
460: HOWTO (ARM_THUMB9,
461: 1,
462: 1,
463: 8,
464: TRUE,
465: 0,
466: complain_overflow_signed,
467: coff_thumb_pcrel_9 ,
468: "ARM_THUMB9",
469: FALSE,
470: 0x000000ff,
471: 0x000000ff,
472: PCRELOFFSET),
473: HOWTO (ARM_THUMB12,
474: 1,
475: 1,
476: 11,
477: TRUE,
478: 0,
479: complain_overflow_signed,
480: coff_thumb_pcrel_12 ,
481: "ARM_THUMB12",
482: FALSE,
483: 0x000007ff,
484: 0x000007ff,
485: PCRELOFFSET),
486: HOWTO (ARM_THUMB23,
487: 1,
488: 2,
489: 22,
490: TRUE,
491: 0,
492: complain_overflow_signed,
493: coff_thumb_pcrel_23 ,
494: "ARM_THUMB23",
495: FALSE,
496: 0x07ff07ff,
497: 0x07ff07ff,
498: PCRELOFFSET)
499: #endif
500: };
501:
502: #define NUM_RELOCS NUM_ELEM (aoutarm_std_reloc_howto)
503:
504: #ifdef COFF_WITH_PE
505:
506:
507:
508: static bfd_boolean
509: in_reloc_p (bfd * abfd ATTRIBUTE_UNUSED,
510: reloc_howto_type * howto)
511: {
512: return !howto->pc_relative && howto->type != ARM_RVA32;
513: }
514: #endif
515:
516: #define RTYPE2HOWTO(cache_ptr, dst) \
517: (cache_ptr)->howto = \
518: (dst)->r_type < NUM_RELOCS \
519: ? aoutarm_std_reloc_howto + (dst)->r_type \
520: : NULL
521:
522: #define coff_rtype_to_howto coff_arm_rtype_to_howto
523:
524: static reloc_howto_type *
525: coff_arm_rtype_to_howto (bfd *abfd ATTRIBUTE_UNUSED,
526: asection *sec,
527: struct internal_reloc *rel,
528: struct coff_link_hash_entry *h ATTRIBUTE_UNUSED,
529: struct internal_syment *sym ATTRIBUTE_UNUSED,
530: bfd_vma *addendp)
531: {
532: reloc_howto_type * howto;
533:
534: if (rel->r_type >= NUM_RELOCS)
535: return NULL;
536:
537: howto = aoutarm_std_reloc_howto + rel->r_type;
538:
539: if (rel->r_type == ARM_RVA32)
540: *addendp -= pe_data (sec->output_section->owner)->pe_opthdr.ImageBase;
541:
542: #if defined COFF_WITH_PE && defined ARM_WINCE
543: if (rel->r_type == ARM_SECREL)
544: {
545: bfd_vma osect_vma;
546:
547: if (h && (h->type == bfd_link_hash_defined
548: || h->type == bfd_link_hash_defweak))
549: osect_vma = h->root.u.def.section->output_section->vma;
550: else
551: {
552: asection *sec;
553: int i;
554:
555:
556:
557:
558: for (sec = abfd->sections, i = 1; i < sym->n_scnum; i++)
559: sec = sec->next;
560:
561: osect_vma = sec->output_section->vma;
562: }
563:
564: *addendp -= osect_vma;
565: }
566: #endif
567:
568: return howto;
569: }
570:
571:
572:
573: static bfd_reloc_status_type
574: aoutarm_fix_pcrel_26_done (bfd *abfd ATTRIBUTE_UNUSED,
575: arelent *reloc_entry ATTRIBUTE_UNUSED,
576: asymbol *symbol ATTRIBUTE_UNUSED,
577: void * data ATTRIBUTE_UNUSED,
578: asection *input_section ATTRIBUTE_UNUSED,
579: bfd *output_bfd ATTRIBUTE_UNUSED,
580: char **error_message ATTRIBUTE_UNUSED)
581: {
582:
583: return bfd_reloc_ok;
584: }
585:
586:
587:
588: static bfd_reloc_status_type
589: aoutarm_fix_pcrel_26 (bfd *abfd,
590: arelent *reloc_entry,
591: asymbol *symbol,
592: void * data,
593: asection *input_section,
594: bfd *output_bfd,
595: char **error_message ATTRIBUTE_UNUSED)
596: {
597: bfd_vma relocation;
598: bfd_size_type addr = reloc_entry->address;
599: long target = bfd_get_32 (abfd, (bfd_byte *) data + addr);
600: bfd_reloc_status_type flag = bfd_reloc_ok;
601:
602:
603: if (symbol->section == &bfd_und_section
604: && (symbol->flags & BSF_WEAK) == 0)
605: return output_bfd ? bfd_reloc_continue : bfd_reloc_undefined;
606:
607:
608:
609: if (symbol->section->name != input_section->name
610: && output_bfd != (bfd *)NULL)
611: return bfd_reloc_continue;
612:
613: relocation = (target & 0x00ffffff) << 2;
614: relocation = (<