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 "bfdlink.h"
28: #include "libbfd.h"
29: #include "coff/internal.h"
30: #include "coff/sym.h"
31: #include "coff/symconst.h"
32: #include "coff/ecoff.h"
33: #include "coff/mips.h"
34: #include "libcoff.h"
35: #include "libecoff.h"
36: ^L
37:
38:
39: static bfd_boolean mips_ecoff_bad_format_hook
40: PARAMS ((bfd *abfd, PTR filehdr));
41: static void mips_ecoff_swap_reloc_in
42: PARAMS ((bfd *, PTR, struct internal_reloc *));
43: static void mips_ecoff_swap_reloc_out
44: PARAMS ((bfd *, const struct internal_reloc *, PTR));
45: static void mips_adjust_reloc_in
46: PARAMS ((bfd *, const struct internal_reloc *, arelent *));
47: static void mips_adjust_reloc_out
48: PARAMS ((bfd *, const arelent *, struct internal_reloc *));
49: static bfd_reloc_status_type mips_generic_reloc
50: PARAMS ((bfd *abfd, arelent *reloc, asymbol *symbol, PTR data,
51: asection *section, bfd *output_bfd, char **error));
52: static bfd_reloc_status_type mips_refhi_reloc
53: PARAMS ((bfd *abfd, arelent *reloc, asymbol *symbol, PTR data,
54: asection *section, bfd *output_bfd, char **error));
55: static bfd_reloc_status_type mips_reflo_reloc
56: PARAMS ((bfd *abfd, arelent *reloc, asymbol *symbol, PTR data,
57: asection *section, bfd *output_bfd, char **error));
58: static bfd_reloc_status_type mips_gprel_reloc
59: PARAMS ((bfd *abfd, arelent *reloc, asymbol *symbol, PTR data,
60: asection *section, bfd *output_bfd, char **error));
61: static void mips_relocate_hi
62: PARAMS ((struct internal_reloc *refhi, struct internal_reloc *reflo,
63: bfd *input_bfd, asection *input_section, bfd_byte *contents,
64: bfd_vma relocation));
65: static bfd_boolean mips_relocate_section
66: PARAMS ((bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *, PTR));
67: static reloc_howto_type *mips_bfd_reloc_type_lookup
68: PARAMS ((bfd *, bfd_reloc_code_real_type));
69: ^L
70:
71:
72:
73:
74:
75:
76:
77:
78: #define MIPSECOFF
79: #define NO_COFF_RELOCS
80: #define NO_COFF_SYMBOLS
81: #define NO_COFF_LINENOS
82: #define coff_swap_filehdr_in mips_ecoff_swap_filehdr_in
83: #define coff_swap_filehdr_out mips_ecoff_swap_filehdr_out
84: #define coff_swap_aouthdr_in mips_ecoff_swap_aouthdr_in
85: #define coff_swap_aouthdr_out mips_ecoff_swap_aouthdr_out
86: #define coff_swap_scnhdr_in mips_ecoff_swap_scnhdr_in
87: #define coff_swap_scnhdr_out mips_ecoff_swap_scnhdr_out
88: #include "coffswap.h"
89:
90:
91: #define ECOFF_32
92: #include "ecoffswap.h"
93: ^L
94:
95:
96: static reloc_howto_type mips_howto_table[] =
97: {
98:
99:
100:
101: HOWTO (MIPS_R_IGNORE,
102: 0,
103: 0,
104: 8,
105: FALSE,
106: 0,
107: complain_overflow_dont,
108: 0,
109: "IGNORE",
110: FALSE,
111: 0,
112: 0,
113: FALSE),
114:
115:
116: HOWTO (MIPS_R_REFHALF,
117: 0,
118: 1,
119: 16,
120: FALSE,
121: 0,
122: complain_overflow_bitfield,
123: mips_generic_reloc,
124: "REFHALF",
125: TRUE,
126: 0xffff,
127: 0xffff,
128: FALSE),
129:
130:
131: HOWTO (MIPS_R_REFWORD,
132: 0,
133: 2,
134: 32,
135: FALSE,
136: 0,
137: complain_overflow_bitfield,
138: mips_generic_reloc,
139: "REFWORD",
140: TRUE,
141: 0xffffffff,
142: 0xffffffff,
143: FALSE),
144:
145:
146: HOWTO (MIPS_R_JMPADDR,
147: 2,
148: 2,
149: 26,
150: FALSE,
151: 0,
152: complain_overflow_dont,
153:
154:
155:
156: mips_generic_reloc,
157: "JMPADDR",
158: TRUE,
159: 0x3ffffff,
160: 0x3ffffff,
161: FALSE),
162:
163:
164:
165: HOWTO (MIPS_R_REFHI,
166: 16,
167: 2,
168: 16,
169: FALSE,
170: 0,
171: complain_overflow_bitfield,
172: mips_refhi_reloc,
173: "REFHI",
174: TRUE,
175: 0xffff,
176: 0xffff,
177: FALSE),
178:
179:
180: HOWTO (MIPS_R_REFLO,
181: 0,
182: 2,
183: 16,
184: FALSE,
185: 0,
186: complain_overflow_dont,
187: mips_reflo_reloc,
188: "REFLO",
189: TRUE,
190: 0xffff,
191: 0xffff,
192: FALSE),
193:
194:
195:
196: HOWTO (MIPS_R_GPREL,
197: 0,
198: 2,
199: 16,
200: FALSE,
201: 0,
202: complain_overflow_signed,
203: mips_gprel_reloc,
204: "GPREL",
205: TRUE,
206: 0xffff,
207: 0xffff,
208: FALSE),
209:
210:
211:
212: HOWTO (MIPS_R_LITERAL,
213: 0,
214: 2,
215: 16,
216: FALSE,
217: 0,
218: complain_overflow_signed,
219: mips_gprel_reloc,
220: "LITERAL",
221: TRUE,
222: 0xffff,
223: 0xffff,
224: FALSE),
225:
226: EMPTY_HOWTO (8),
227: EMPTY_HOWTO (9),
228: EMPTY_HOWTO (10),
229: EMPTY_HOWTO (11),
230:
231:
232:
233:
234: HOWTO (MIPS_R_PCREL16,
235: 2,
236: 2,
237: 16,
238: TRUE,
239: 0,
240: complain_overflow_signed,
241: mips_generic_reloc,
242: "PCREL16",
243: TRUE,
244: 0xffff,
245: 0xffff,
246: TRUE),
247: };
248:
249: #define MIPS_HOWTO_COUNT \
250: (sizeof mips_howto_table / sizeof mips_howto_table[0])
251: ^L
252:
253:
254: static bfd_boolean
255: mips_ecoff_bad_format_hook (abfd, filehdr)
256: bfd *abfd;
257: PTR filehdr;
258: {
259: struct internal_filehdr *internal_f = (struct internal_filehdr *) filehdr;
260:
261: switch (internal_f->f_magic)
262: {
263: case MIPS_MAGIC_1:
264:
265: return TRUE;
266:
267: case MIPS_MAGIC_BIG:
268: case MIPS_MAGIC_BIG2:
269: case MIPS_MAGIC_BIG3:
270: return bfd_big_endian (abfd);
271:
272: case MIPS_MAGIC_LITTLE:
273: case MIPS_MAGIC_LITTLE2:
274: case MIPS_MAGIC_LITTLE3:
275: return bfd_little_endian (abfd);
276:
277: default:
278: return FALSE;
279: }
280: }
281: ^L
282:
283:
284:
285:
286:
287:
288: static void
289: mips_ecoff_swap_reloc_in (abfd, ext_ptr, intern)
290: bfd *abfd;
291: PTR ext_ptr;
292: struct internal_reloc *intern;
293: {
294: const RELOC *ext = (RELOC *) ext_ptr;
295:
296: intern->r_vaddr = H_GET_32 (abfd, ext->r_vaddr);
297: if (bfd_header_big_endian (abfd))
298: {
299: intern->r_symndx = (((int) ext->r_bits[0]
300: << RELOC_BITS0_SYMNDX_SH_LEFT_BIG)
301: | ((int) ext->r_bits[1]
302: << RELOC_BITS1_SYMNDX_SH_LEFT_BIG)
303: | ((int) ext->r_bits[2]
304: << RELOC_BITS2_SYMNDX_SH_LEFT_BIG));
305: intern->r_type = ((ext->r_bits[3] & RELOC_BITS3_TYPE_BIG)
306: >> RELOC_BITS3_TYPE_SH_BIG);
307: intern->r_extern = (ext->r_bits[3] & RELOC_BITS3_EXTERN_BIG) != 0;
308: }
309: else
310: {
311: intern->r_symndx = (((int) ext->r_bits[0]
312: << RELOC_BITS0_SYMNDX_SH_LEFT_LITTLE)
313: | ((int) ext->r_bits[1]
314: << RELOC_BITS1_SYMNDX_SH_LEFT_LITTLE)
315: | ((int) ext->r_bits[2]
316: << RELOC_BITS2_SYMNDX_SH_LEFT_LITTLE));
317: intern->r_type = (((ext->r_bits[3] & RELOC_BITS3_TYPE_LITTLE)
318: >> RELOC_BITS3_TYPE_SH_LITTLE)
319: | ((ext->r_bits[3] & RELOC_BITS3_TYPEHI_LITTLE)
320: << RELOC_BITS3_TYPEHI_SH_LITTLE));
321: intern->r_extern = (ext->r_bits[3] & RELOC_BITS3_EXTERN_LITTLE) != 0;
322: }
323: }
324:
325:
326:
327: static void
328: mips_ecoff_swap_reloc_out (abfd, intern, dst)
329: bfd *abfd;
330: const struct internal_reloc *intern;
331: PTR dst;
332: {
333: RELOC *ext = (RELOC *) dst;
334: long r_symndx;
335:
336: BFD_ASSERT (intern->r_extern
337: || (intern->r_symndx >= 0 && intern->r_symndx <= 12));
338:
339: r_symndx = intern->r_symndx;
340:
341: H_PUT_32 (abfd, intern->r_vaddr, ext->r_vaddr);
342: if (bfd_header_big_endian (abfd))
343: {
344: ext->r_bits[0] = r_symndx >> RELOC_BITS0_SYMNDX_SH_LEFT_BIG;
345: ext->r_bits[1] = r_symndx >> RELOC_BITS1_SYMNDX_SH_LEFT_BIG;
346: ext->r_bits[2] = r_symndx >> RELOC_BITS2_SYMNDX_SH_LEFT_BIG;
347: ext->r_bits[3] = (((intern->r_type << RELOC_BITS3_TYPE_SH_BIG)
348: & RELOC_BITS3_TYPE_BIG)
349: | (intern->r_extern ? RELOC_BITS3_EXTERN_BIG : 0));
350: }
351: else
352: {
353: ext->r_bits[0] = r_symndx >> RELOC_BITS0_SYMNDX_SH_LEFT_LITTLE;
354: ext->r_bits[1] = r_symndx >> RELOC_BITS1_SYMNDX_SH_LEFT_LITTLE;
355: ext->r_bits[2] = r_symndx >> RELOC_BITS2_SYMNDX_SH_LEFT_LITTLE;
356: ext->r_bits[3] = (((intern->r_type << RELOC_BITS3_TYPE_SH_LITTLE)
357: & RELOC_BITS3_TYPE_LITTLE)
358: | ((intern->r_type >> RELOC_BITS3_TYPEHI_SH_LITTLE
359: & RELOC_BITS3_TYPEHI_LITTLE))
360: | (intern->r_extern ? RELOC_BITS3_EXTERN_LITTLE : 0));
361: }
362: }
363:
364:
365:
366:
367:
368: static void
369: mips_adjust_reloc_in (abfd, intern, rptr)
370: bfd *abfd;
371: const struct internal_reloc *intern;
372: arelent *rptr;
373: {
374: if (intern->r_type > MIPS_R_PCREL16)
375: abort ();
376:
377: if (! intern->r_extern
378: && (intern->r_type == MIPS_R_GPREL
379: || intern->r_type == MIPS_R_LITERAL))
380: rptr->addend += ecoff_data (abfd)->gp;
381:
382:
383:
384: if (intern->r_type == MIPS_R_IGNORE)
385: rptr->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr;
386:
387: rptr->howto = &mips_howto_table[intern->r_type];
388: }
389:
390:
391:
392:
393: static void
394: mips_adjust_reloc_out (abfd, rel, intern)
395: bfd *abfd ATTRIBUTE_UNUSED;
396: const arelent *rel ATTRIBUTE_UNUSED;
397: struct internal_reloc *intern ATTRIBUTE_UNUSED;
398: {
399: }
400:
401:
402:
403:
404:
405:
406:
407:
408:
409:
410:
411:
412: static bfd_reloc_status_type
413: mips_generic_reloc (abfd,
414: reloc_entry,
415: symbol,
416: data,
417: input_section,
418: output_bfd,
419: error_message)
420: bfd *abfd ATTRIBUTE_UNUSED;
421: arelent *reloc_entry;
422: asymbol *symbol;
423: PTR data ATTRIBUTE_UNUSED;
424: asection *input_section;
425: bfd *output_bfd;
426: char **error_message ATTRIBUTE_UNUSED;
427: {
428: if (output_bfd != (bfd *) NULL
429: && (symbol->flags & BSF_SECTION_SYM) == 0
430: && reloc_entry->addend == 0)
431: {
432: reloc_entry->address += input_section->output_offset;
433: return bfd_reloc_ok;
434: }
435:
436: return bfd_reloc_continue;
437: }
438:
439:
440:
441:
442:
443:
444:
445:
446:
447:
448: struct mips_hi
449: {
450: struct mips_hi *next;
451: bfd_byte *addr;
452: bfd_vma addend;
453: };
454:
455:
456:
457: static struct mips_hi *mips_refhi_list;
458:
459: static bfd_reloc_status_type
460: mips_refhi_reloc (abfd,
461: reloc_entry,
462: symbol,
463: data,
464: input_section,
465: output_bfd,
466: error_message)
467: bfd *abfd ATTRIBUTE_UNUSED;
468: arelent *reloc_entry;
469: asymbol *symbol;
470: PTR data;
471: asection *input_section;
472: bfd *output_bfd;
473: char **error_message ATTRIBUTE_UNUSED;
474: {
475: bfd_reloc_status_type ret;
476: bfd_vma relocation;
477: struct mips_hi *n;
478:
479:
480:
481: if (output_bfd != (bfd *) NULL
482: && (symbol->flags & BSF_SECTION_SYM) == 0
483: && reloc_entry->addend == 0)
484: {
485: reloc_entry->address += input_section->output_offset;
486: return bfd_reloc_ok;
487: }
488:
489: ret = bfd_reloc_ok;
490: if (bfd_is_und_section (symbol->section)
491: && output_bfd == (bfd *) NULL)
492: ret = bfd_reloc_undefined;
493:
494: if (bfd_is_com_section (symbol->section))
495: relocation = 0;
496: else
497: relocation = symbol->value;
498:
499: relocation += symbol->section->output_section->vma;
500: relocation += symbol->section->output_offset;
501: relocation += reloc_entry->addend;
502:
503: if (reloc_entry->address > bfd_get_section_limit (abfd, input_section))
504: return bfd_reloc_outofrange;
505:
506:
507: n = (struct mips_hi *) bfd_malloc ((bfd_size_type) sizeof *n);
508: if (n == NULL)
509: return bfd_reloc_outofrange;
510: n->addr = (bfd_byte *) data + reloc_entry->address;
511: n->addend = relocation;
512: n->next = mips_refhi_list;
513: mips_refhi_list = n;
514:
515: if (output_bfd != (bfd *) NULL)
516: reloc_entry->address += input_section->output_offset;
517:
518: return ret;
519: }
520:
521:
522:
523:
524:
525: static bfd_reloc_status_type
526: mips_reflo_reloc (abfd,
527: reloc_entry,
528: symbol,
529: data,
530: input_section,
531: output_bfd,
532: error_message)
533: bfd *abfd;
534: arelent *reloc_entry;
535: asymbol *symbol;
536: PTR data;
537: asection *input_section;
538: bfd *output_bfd;
539: char **error_message;
540: {
541: if (mips_refhi_list != NULL)
542: {
543: struct mips_hi *l;
544:
545: l = mips_refhi_list;
546: while (l != NULL)
547: {
548: unsigned long insn;
549: unsigned long val;
550: unsigned long vallo;
551: struct mips_hi *next;
552:
553:
554:
555:
556:
557: insn = bfd_get_32 (abfd, l->addr);
558: vallo = (bfd_get_32 (abfd, (bfd_byte *) data + reloc_entry->address)
559: & 0xffff);
560: val = ((in