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/m68k.h"
28: #include "coff/internal.h"
29: #include "libcoff.h"
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52: #define COFF_DEFAULT_SECTION_ALIGNMENT_POWER (2)
53:
54: #ifndef COFF_PAGE_SIZE
55:
56: #define COFF_PAGE_SIZE 0x2000
57: #endif
58:
59: #ifndef COFF_COMMON_ADDEND
60: #define RELOC_SPECIAL_FN 0
61: #else
62: static bfd_reloc_status_type m68kcoff_common_addend_special_fn
63: PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
64: static reloc_howto_type *m68kcoff_common_addend_rtype_to_howto
65: PARAMS ((bfd *, asection *, struct internal_reloc *,
66: struct coff_link_hash_entry *, struct internal_syment *,
67: bfd_vma *));
68: #define RELOC_SPECIAL_FN m68kcoff_common_addend_special_fn
69: #endif
70:
71: static bfd_boolean m68k_coff_is_local_label_name
72: PARAMS ((bfd *, const char *));
73:
74:
75:
76:
77:
78: static bfd_boolean
79: m68k_coff_is_local_label_name (abfd, name)
80: bfd *abfd;
81: const char *name;
82: {
83: if (name[0] == 'L' && name[1] == '%')
84: return TRUE;
85:
86: return _bfd_coff_is_local_label_name (abfd, name);
87: }
88:
89: #ifndef STATIC_RELOCS
90:
91: #define m68kcoff_howto_table _bfd_m68kcoff_howto_table
92: #define m68k_rtype2howto _bfd_m68kcoff_rtype2howto
93: #define m68k_howto2rtype _bfd_m68kcoff_howto2rtype
94: #define m68k_reloc_type_lookup _bfd_m68kcoff_reloc_type_lookup
95: #define m68k_reloc_name_lookup _bfd_m68kcoff_reloc_name_lookup
96: #endif
97:
98: #ifdef ONLY_DECLARE_RELOCS
99: extern reloc_howto_type m68kcoff_howto_table[];
100: #else
101: #ifdef STATIC_RELOCS
102: static
103: #endif
104: reloc_howto_type m68kcoff_howto_table[] =
105: {
106: HOWTO (R_RELBYTE, 0, 0, 8, FALSE, 0, complain_overflow_bitfield, RELOC_SPECIAL_FN, "8", TRUE, 0x000000ff,0x000000ff, FALSE),
107: HOWTO (R_RELWORD, 0, 1, 16, FALSE, 0, complain_overflow_bitfield, RELOC_SPECIAL_FN, "16", TRUE, 0x0000ffff,0x0000ffff, FALSE),
108: HOWTO (R_RELLONG, 0, 2, 32, FALSE, 0, complain_overflow_bitfield, RELOC_SPECIAL_FN, "32", TRUE, 0xffffffff,0xffffffff, FALSE),
109: HOWTO (R_PCRBYTE, 0, 0, 8, TRUE, 0, complain_overflow_signed, RELOC_SPECIAL_FN, "DISP8", TRUE, 0x000000ff,0x000000ff, FALSE),
110: HOWTO (R_PCRWORD, 0, 1, 16, TRUE, 0, complain_overflow_signed, RELOC_SPECIAL_FN, "DISP16", TRUE, 0x0000ffff,0x0000ffff, FALSE),
111: HOWTO (R_PCRLONG, 0, 2, 32, TRUE, 0, complain_overflow_signed, RELOC_SPECIAL_FN, "DISP32", TRUE, 0xffffffff,0xffffffff, FALSE),
112: HOWTO (R_RELLONG_NEG, 0, -2, 32, FALSE, 0, complain_overflow_bitfield, RELOC_SPECIAL_FN, "-32", TRUE, 0xffffffff,0xffffffff, FALSE),
113: };
114: #endif
115:
116: #ifndef BADMAG
117: #define BADMAG(x) M68KBADMAG(x)
118: #endif
119: #define M68 1
120:
121:
122:
123: #ifdef ONLY_DECLARE_RELOCS
124: extern void m68k_rtype2howto PARAMS ((arelent *internal, int relocentry));
125: extern int m68k_howto2rtype PARAMS ((reloc_howto_type *));
126: extern reloc_howto_type *m68k_reloc_type_lookup
127: PARAMS ((bfd *, bfd_reloc_code_real_type));
128: extern reloc_howto_type *m68k_reloc_name_lookup
129: PARAMS ((bfd *, const char *));
130: #else
131:
132: #ifdef STATIC_RELOCS
133: #define STAT_REL static
134: #else
135: #define STAT_REL
136: #endif
137:
138: STAT_REL reloc_howto_type * m68k_reloc_type_lookup PARAMS ((bfd *, bfd_reloc_code_real_type));
139: STAT_REL reloc_howto_type * m68k_reloc_name_lookup PARAMS ((bfd *, const char *));
140: STAT_REL int m68k_howto2rtype PARAMS ((reloc_howto_type *));
141: STAT_REL void m68k_rtype2howto PARAMS ((arelent *, int));
142:
143:
144: STAT_REL void
145: m68k_rtype2howto(internal, relocentry)
146: arelent *internal;
147: int relocentry;
148: {
149: switch (relocentry)
150: {
151: case R_RELBYTE: internal->howto = m68kcoff_howto_table + 0; break;
152: case R_RELWORD: internal->howto = m68kcoff_howto_table + 1; break;
153: case R_RELLONG: internal->howto = m68kcoff_howto_table + 2; break;
154: case R_PCRBYTE: internal->howto = m68kcoff_howto_table + 3; break;
155: case R_PCRWORD: internal->howto = m68kcoff_howto_table + 4; break;
156: case R_PCRLONG: internal->howto = m68kcoff_howto_table + 5; break;
157: case R_RELLONG_NEG: internal->howto = m68kcoff_howto_table + 6; break;
158: }
159: }
160:
161: STAT_REL int
162: m68k_howto2rtype (internal)
163: reloc_howto_type *internal;
164: {
165: if (internal->pc_relative)
166: {
167: switch (internal->bitsize)
168: {
169: case 32: return R_PCRLONG;
170: case 16: return R_PCRWORD;
171: case 8: return R_PCRBYTE;
172: }
173: }
174: else
175: {
176: switch (internal->bitsize)
177: {
178: case 32: return R_RELLONG;
179: case 16: return R_RELWORD;
180: case 8: return R_RELBYTE;
181: }
182: }
183: return R_RELLONG;
184: }
185:
186: STAT_REL reloc_howto_type *
187: m68k_reloc_type_lookup (abfd, code)
188: bfd *abfd ATTRIBUTE_UNUSED;
189: bfd_reloc_code_real_type code;
190: {
191: switch (code)
192: {
193: default: return NULL;
194: case BFD_RELOC_8: return m68kcoff_howto_table + 0;
195: case BFD_RELOC_16: return m68kcoff_howto_table + 1;
196: case BFD_RELOC_CTOR:
197: case BFD_RELOC_32: return m68kcoff_howto_table + 2;
198: case BFD_RELOC_8_PCREL: return m68kcoff_howto_table + 3;
199: case BFD_RELOC_16_PCREL: return m68kcoff_howto_table + 4;
200: case BFD_RELOC_32_PCREL: return m68kcoff_howto_table + 5;
201:
202: }
203:
204: }
205:
206: STAT_REL reloc_howto_type *
207: m68k_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED,
208: const char *r_name)
209: {
210: unsigned int i;
211:
212: for (i = 0;
213: i < sizeof (m68kcoff_howto_table) / sizeof (m68kcoff_howto_table[0]);
214: i++)
215: if (m68kcoff_howto_table[i].name != NULL
216: && strcasecmp (m68kcoff_howto_table[i].name, r_name) == 0)
217: return &m68kcoff_howto_table[i];
218:
219: return NULL;
220: }
221:
222: #endif
223:
224: #define RTYPE2HOWTO(internal, relocentry) \
225: m68k_rtype2howto(internal, (relocentry)->r_type)
226:
227: #define SELECT_RELOC(external, internal) \
228: external.r_type = m68k_howto2rtype (internal)
229:
230: #define coff_bfd_reloc_type_lookup m68k_reloc_type_lookup
231: #define coff_bfd_reloc_name_lookup m68k_reloc_name_lookup
232:
233: #ifndef COFF_COMMON_ADDEND
234: #ifndef coff_rtype_to_howto
235:
236: #define coff_rtype_to_howto m68kcoff_rtype_to_howto
237:
238: static reloc_howto_type *m68kcoff_rtype_to_howto
239: PARAMS ((bfd *, asection *, struct internal_reloc *,
240: struct coff_link_hash_entry *, struct internal_syment *,
241: bfd_vma *));
242:
243: static reloc_howto_type *
244: m68kcoff_rtype_to_howto (abfd, sec, rel, h, sym, addendp)
245: bfd *abfd ATTRIBUTE_UNUSED;
246: asection *sec;
247: struct internal_reloc *rel;
248: struct coff_link_hash_entry *h ATTRIBUTE_UNUSED;
249: struct internal_syment *sym ATTRIBUTE_UNUSED;
250: bfd_vma *addendp;
251: {
252: arelent relent;
253: reloc_howto_type *howto;
254:
255: relent.howto = NULL;
256: RTYPE2HOWTO (&relent, rel);
257:
258: howto = relent.howto;
259:
260: if (howto != NULL && howto->pc_relative)
261: *addendp += sec->vma;
262:
263: return howto;
264: }
265:
266: #endif
267: #endif
268: ^L
269: #ifdef COFF_COMMON_ADDEND
270:
271:
272:
273:
274:
275:
276:
277:
278:
279:
280:
281: static bfd_reloc_status_type
282: m68kcoff_common_addend_special_fn (abfd, reloc_entry, symbol, data,
283: input_section, output_bfd, error_message)
284: bfd *abfd;
285: arelent *reloc_entry;
286: asymbol *symbol;
287: PTR data;
288: asection *input_section ATTRIBUTE_UNUSED;
289: bfd *output_bfd;
290: char **error_message ATTRIBUTE_UNUSED;
291: {
292: symvalue diff;
293:
294: if (output_bfd == (bfd *) NULL)
295: return bfd_reloc_continue;
296:
297: if (bfd_is_com_section (symbol->section))
298: {
299:
300:
301:
302:
303:
304:
305:
306:
307:
308:
309:
310: diff = symbol->value + reloc_entry->addend;
311: }
312: else
313: {
314:
315:
316:
317:
318: diff = reloc_entry->addend;
319: }
320:
321: #define DOIT(x) \
322: x = ((x & ~howto->dst_mask) | (((x & howto->src_mask) + diff) & howto->dst_mask))
323:
324: if (diff != 0)
325: {
326: reloc_howto_type *howto = reloc_entry->howto;
327: unsigned char *addr = (unsigned char *) data + reloc_entry->address;
328:
329: switch (howto->size)
330: {
331: case 0:
332: {
333: char x = bfd_get_8 (abfd, addr);
334: DOIT (x);
335: bfd_put_8 (abfd, x, addr);
336: }
337: break;
338:
339: case 1:
340: {
341: short x = bfd_get_16 (abfd, addr);
342: DOIT (x);
343: bfd_put_16 (abfd, (bfd_vma) x, addr);
344: }
345: break;
346:
347: case 2:
348: {
349: long x = bfd_get_32 (abfd, addr);
350: DOIT (x);
351: bfd_put_32 (abfd, (bfd_vma) x, addr);
352: }
353: break;
354:
355: default:
356: abort ();
357: }
358: }
359:
360:
361: return bfd_reloc_continue;
362: }
363:
364:
365:
366:
367:
368:
369:
370:
371:
372:
373:
374:
375:
376:
377: #define CALC_ADDEND(abfd, ptr, reloc, cache_ptr) \
378: { \
379: coff_symbol_type *coffsym = (coff_symbol_type *) NULL; \
380: if (ptr && bfd_asymbol_bfd (ptr) != abfd) \
381: coffsym = (obj_symbols (abfd) \
382: + (cache_ptr->sym_ptr_ptr - symbols)); \
383: else if (ptr) \
384: coffsym = coff_symbol_from (abfd, ptr); \
385: if (coffsym != (coff_symbol_type *) NULL \
386: && coffsym->native->u.syment.n_scnum == 0) \
387: cache_ptr->addend = - coffsym->native->u.syment.n_value; \
388: else if (ptr && bfd_asymbol_bfd (ptr) == abfd \
389: && ptr->section != (asection *) NULL) \
390: cache_ptr->addend = - (ptr->section->vma + ptr->value); \
391: else \
392: cache_ptr->addend = 0; \
393: if (ptr && (reloc.r_type == R_PCRBYTE \
394: || reloc.r_type == R_PCRWORD \
395: || reloc.r_type == R_PCRLONG)) \
396: cache_ptr->addend += asect->vma; \
397: }
398:
399: #ifndef coff_rtype_to_howto
400:
401:
402:
403:
404: static reloc_howto_type *
405: m68kcoff_common_addend_rtype_to_howto (abfd, sec, rel, h, sym, addendp)
406: bfd *abfd ATTRIBUTE_UNUSED;
407: asection *sec;
408: struct internal_reloc *rel;
409: struct coff_link_hash_entry *h;
410: struct internal_syment *sym;
411: bfd_vma *addendp;
412: {
413: arelent relent;
414: reloc_howto_type *howto;
415:
416: relent.howto = NULL;
417: RTYPE2HOWTO (&relent, rel);
418:
419: howto = relent.howto;
420:
421: if (howto->pc_relative)
422: *addendp += sec->vma;
423:
424: if (sym != NULL && sym->n_scnum == 0 && sym->n_value != 0)
425: {
426:
427:
428:
429:
430:
431: BFD_ASSERT (h != NULL);
432: *addendp -= sym->n_value;
433: }
434:
435:
436:
437:
438: if (h != NULL && h->root.type == bfd_link_hash_common)
439: *addendp += h->root.u.c.size;
440:
441: return howto;
442: }
443:
444: #define coff_rtype_to_howto m68kcoff_common_addend_rtype_to_howto
445:
446: #endif
447:
448: #endif
449:
450: #if !defined ONLY_DECLARE_RELOCS && ! defined STATIC_RELOCS
451:
452:
453:
454:
455:
456:
457:
458: bfd_boolean
459: bfd_m68k_coff_create_embedded_relocs (abfd, info, datasec, relsec, errmsg)
460: bfd *abfd;
461: struct bfd_link_info *info;
462: asection *datasec;
463: asection *relsec;
464: char **errmsg;
465: {
466: char *extsyms;
467: bfd_size_type symesz;
468: struct internal_reloc *irel, *irelend;
469: bfd_byte *p;
470: bfd_size_type amt;
471:
472: BFD_ASSERT (! info->relocatable);
473:
474: *errmsg = NULL;
475:
476: if (datasec->reloc_count == 0)
477: return TRUE;
478:
479: extsyms = obj_coff_external_syms (abfd);
480: symesz = bfd_coff_symesz (abfd);
481:
482: irel = _bfd_coff_read_internal_relocs (abfd, datasec, TRUE, NULL, FALSE,
483: NULL);
484: irelend = irel + datasec->reloc_count;
485:
486: amt = (bfd_size_type) datasec->reloc_count * 12;
487: relsec->contents = (bfd_byte *) bfd_alloc (abfd, amt);
488: if (relsec->contents == NULL)
489: return FALSE;
490:
491: p = relsec->contents;
492:
493: for (; irel < irelend; irel++, p += 12)
494: {
495: asection *targetsec;
496:
497:
498:
499:
500:
501:
502:
503:
504: if (irel->r_type != R_RELLONG)
505: {
506: *errmsg = _("unsupported reloc type");
507: bfd_set_error (bfd_error_bad_value);
508: return FALSE;
509: }
510:
511: if (irel->r_symndx == -1)
512: targetsec = bfd_abs_section_ptr;
513: else
514: {
515: struct coff_link_hash_entry *h;
516:
517: h = obj_coff_sym_hashes (abfd)[irel->r_symndx];
518: if (h == NULL)
519: {
520: struct internal_syment isym;
521:
522: bfd_coff_swap_sym_in (abfd, extsyms + symesz * irel->r_symndx,
523: &isym);
524: targetsec = coff_section_from_bfd_index (abfd, isym.n_scnum);
525: }
526: else if (h->root.type == bfd_link_hash_defined
527: || h->root.type == bfd_link_hash_defweak)
528: targetsec = h->root.u.def.section;
529: else
530: targetsec = NULL;
531: }
532:
533: bfd_put_32 (abfd,
534: (irel->r_vaddr - datasec->vma + datasec->output_offset), p);
535: memset (p + 4, 0, 8);
536: if (targetsec != NULL)
537: strncpy ((char *) p + 4, targetsec->output_section->name, 8);
538: }
539:
540: return TRUE;
541: }
542: #endif
543: ^L
544: #define coff_bfd_is_local_label_name m68k_coff_is_local_label_name
545:
546: #define coff_relocate_section _bfd_coff_generic_relocate_section
547:
548: #include "coffcode.h"
549: