Annotation of src/external/gpl3/binutils.old/dist/bfd/coff-mips.c, Revision 1.4.8.1
1.1 christos 1: /* BFD back-end for MIPS Extended-Coff files.
1.4.8.1 ! pgoyette 2: Copyright (C) 1990-2016 Free Software Foundation, Inc.
1.1 christos 3: Original version by Per Bothner.
4: Full support added by Ian Lance Taylor, ian@cygnus.com.
5:
6: This file is part of BFD, the Binary File Descriptor library.
7:
8: This program is free software; you can redistribute it and/or modify
9: it under the terms of the GNU General Public License as published by
10: the Free Software Foundation; either version 3 of the License, or
11: (at your option) any later version.
12:
13: This program is distributed in the hope that it will be useful,
14: but WITHOUT ANY WARRANTY; without even the implied warranty of
15: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16: GNU General Public License for more details.
17:
18: You should have received a copy of the GNU General Public License
19: along with this program; if not, write to the Free Software
20: Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
21: MA 02110-1301, USA. */
22:
23: #include "sysdep.h"
24: #include "bfd.h"
25: #include "bfdlink.h"
26: #include "libbfd.h"
27: #include "coff/internal.h"
28: #include "coff/sym.h"
29: #include "coff/symconst.h"
30: #include "coff/ecoff.h"
31: #include "coff/mips.h"
32: #include "libcoff.h"
33: #include "libecoff.h"
34:
35: /* Prototypes for static functions. */
36: static bfd_reloc_status_type
37: mips_generic_reloc
38: (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **);
39: static bfd_reloc_status_type
40: mips_refhi_reloc
41: (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **);
42: static bfd_reloc_status_type
43: mips_reflo_reloc
44: (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **);
45: static bfd_reloc_status_type
1.3 christos 46: mips_gprel_reloc
1.1 christos 47: (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **);
48:
49:
50: /* ECOFF has COFF sections, but the debugging information is stored in
51: a completely different format. ECOFF targets use some of the
52: swapping routines from coffswap.h, and some of the generic COFF
53: routines in coffgen.c, but, unlike the real COFF targets, do not
54: use coffcode.h itself.
55:
56: Get the generic COFF swapping routines, except for the reloc,
57: symbol, and lineno ones. Give them ECOFF names. */
58: #define MIPSECOFF
59: #define NO_COFF_RELOCS
60: #define NO_COFF_SYMBOLS
61: #define NO_COFF_LINENOS
62: #define coff_swap_filehdr_in mips_ecoff_swap_filehdr_in
63: #define coff_swap_filehdr_out mips_ecoff_swap_filehdr_out
64: #define coff_swap_aouthdr_in mips_ecoff_swap_aouthdr_in
65: #define coff_swap_aouthdr_out mips_ecoff_swap_aouthdr_out
66: #define coff_swap_scnhdr_in mips_ecoff_swap_scnhdr_in
67: #define coff_swap_scnhdr_out mips_ecoff_swap_scnhdr_out
68:
69: #include "coffswap.h"
70:
71: /* Get the ECOFF swapping routines. */
72: #define ECOFF_32
73: #include "ecoffswap.h"
74:
75: /* How to process the various relocs types. */
76:
77: static reloc_howto_type mips_howto_table[] =
78: {
79: /* Reloc type 0 is ignored. The reloc reading code ensures that
80: this is a reference to the .abs section, which will cause
81: bfd_perform_relocation to do nothing. */
82: HOWTO (MIPS_R_IGNORE, /* type */
83: 0, /* rightshift */
84: 0, /* size (0 = byte, 1 = short, 2 = long) */
85: 8, /* bitsize */
86: FALSE, /* pc_relative */
87: 0, /* bitpos */
88: complain_overflow_dont, /* complain_on_overflow */
89: 0, /* special_function */
90: "IGNORE", /* name */
91: FALSE, /* partial_inplace */
92: 0, /* src_mask */
93: 0, /* dst_mask */
94: FALSE), /* pcrel_offset */
95:
96: /* A 16 bit reference to a symbol, normally from a data section. */
97: HOWTO (MIPS_R_REFHALF, /* type */
98: 0, /* rightshift */
99: 1, /* size (0 = byte, 1 = short, 2 = long) */
100: 16, /* bitsize */
101: FALSE, /* pc_relative */
102: 0, /* bitpos */
103: complain_overflow_bitfield, /* complain_on_overflow */
104: mips_generic_reloc, /* special_function */
105: "REFHALF", /* name */
106: TRUE, /* partial_inplace */
107: 0xffff, /* src_mask */
108: 0xffff, /* dst_mask */
109: FALSE), /* pcrel_offset */
110:
111: /* A 32 bit reference to a symbol, normally from a data section. */
112: HOWTO (MIPS_R_REFWORD, /* type */
113: 0, /* rightshift */
114: 2, /* size (0 = byte, 1 = short, 2 = long) */
115: 32, /* bitsize */
116: FALSE, /* pc_relative */
117: 0, /* bitpos */
118: complain_overflow_bitfield, /* complain_on_overflow */
119: mips_generic_reloc, /* special_function */
120: "REFWORD", /* name */
121: TRUE, /* partial_inplace */
122: 0xffffffff, /* src_mask */
123: 0xffffffff, /* dst_mask */
124: FALSE), /* pcrel_offset */
125:
126: /* A 26 bit absolute jump address. */
127: HOWTO (MIPS_R_JMPADDR, /* type */
128: 2, /* rightshift */
129: 2, /* size (0 = byte, 1 = short, 2 = long) */
130: 26, /* bitsize */
131: FALSE, /* pc_relative */
132: 0, /* bitpos */
133: complain_overflow_dont, /* complain_on_overflow */
134: /* This needs complex overflow
135: detection, because the upper four
136: bits must match the PC. */
137: mips_generic_reloc, /* special_function */
138: "JMPADDR", /* name */
139: TRUE, /* partial_inplace */
140: 0x3ffffff, /* src_mask */
141: 0x3ffffff, /* dst_mask */
142: FALSE), /* pcrel_offset */
143:
144: /* The high 16 bits of a symbol value. Handled by the function
145: mips_refhi_reloc. */
146: HOWTO (MIPS_R_REFHI, /* type */
147: 16, /* rightshift */
148: 2, /* size (0 = byte, 1 = short, 2 = long) */
149: 16, /* bitsize */
150: FALSE, /* pc_relative */
151: 0, /* bitpos */
152: complain_overflow_bitfield, /* complain_on_overflow */
153: mips_refhi_reloc, /* special_function */
154: "REFHI", /* name */
155: TRUE, /* partial_inplace */
156: 0xffff, /* src_mask */
157: 0xffff, /* dst_mask */
158: FALSE), /* pcrel_offset */
159:
160: /* The low 16 bits of a symbol value. */
161: HOWTO (MIPS_R_REFLO, /* type */
162: 0, /* rightshift */
163: 2, /* size (0 = byte, 1 = short, 2 = long) */
164: 16, /* bitsize */
165: FALSE, /* pc_relative */
166: 0, /* bitpos */
167: complain_overflow_dont, /* complain_on_overflow */
168: mips_reflo_reloc, /* special_function */
169: "REFLO", /* name */
170: TRUE, /* partial_inplace */
171: 0xffff, /* src_mask */
172: 0xffff, /* dst_mask */
173: FALSE), /* pcrel_offset */
174:
175: /* A reference to an offset from the gp register. Handled by the
176: function mips_gprel_reloc. */
177: HOWTO (MIPS_R_GPREL, /* type */
178: 0, /* rightshift */
179: 2, /* size (0 = byte, 1 = short, 2 = long) */
180: 16, /* bitsize */
181: FALSE, /* pc_relative */
182: 0, /* bitpos */
183: complain_overflow_signed, /* complain_on_overflow */
184: mips_gprel_reloc, /* special_function */
185: "GPREL", /* name */
186: TRUE, /* partial_inplace */
187: 0xffff, /* src_mask */
188: 0xffff, /* dst_mask */
189: FALSE), /* pcrel_offset */
190:
191: /* A reference to a literal using an offset from the gp register.
192: Handled by the function mips_gprel_reloc. */
193: HOWTO (MIPS_R_LITERAL, /* type */
194: 0, /* rightshift */
195: 2, /* size (0 = byte, 1 = short, 2 = long) */
196: 16, /* bitsize */
197: FALSE, /* pc_relative */
198: 0, /* bitpos */
199: complain_overflow_signed, /* complain_on_overflow */
200: mips_gprel_reloc, /* special_function */
201: "LITERAL", /* name */
202: TRUE, /* partial_inplace */
203: 0xffff, /* src_mask */
204: 0xffff, /* dst_mask */
205: FALSE), /* pcrel_offset */
206:
207: EMPTY_HOWTO (8),
208: EMPTY_HOWTO (9),
209: EMPTY_HOWTO (10),
210: EMPTY_HOWTO (11),
211:
212: /* FIXME: This relocation is used (internally only) to represent branches
213: when assembling. It should never appear in output files, and
214: be removed. (It used to be used for embedded-PIC support.) */
215: HOWTO (MIPS_R_PCREL16, /* type */
216: 2, /* rightshift */
217: 2, /* size (0 = byte, 1 = short, 2 = long) */
218: 16, /* bitsize */
219: TRUE, /* pc_relative */
220: 0, /* bitpos */
221: complain_overflow_signed, /* complain_on_overflow */
222: mips_generic_reloc, /* special_function */
223: "PCREL16", /* name */
224: TRUE, /* partial_inplace */
225: 0xffff, /* src_mask */
226: 0xffff, /* dst_mask */
227: TRUE), /* pcrel_offset */
228: };
229:
230: #define MIPS_HOWTO_COUNT \
231: (sizeof mips_howto_table / sizeof mips_howto_table[0])
232:
233: /* See whether the magic number matches. */
234:
235: static bfd_boolean
236: mips_ecoff_bad_format_hook (bfd * abfd, void * filehdr)
237: {
238: struct internal_filehdr *internal_f = (struct internal_filehdr *) filehdr;
239:
240: switch (internal_f->f_magic)
241: {
242: case MIPS_MAGIC_1:
243: /* I don't know what endianness this implies. */
244: return TRUE;
245:
246: case MIPS_MAGIC_BIG:
247: case MIPS_MAGIC_BIG2:
248: case MIPS_MAGIC_BIG3:
249: return bfd_big_endian (abfd);
250:
251: case MIPS_MAGIC_LITTLE:
252: case MIPS_MAGIC_LITTLE2:
253: case MIPS_MAGIC_LITTLE3:
254: return bfd_little_endian (abfd);
255:
256: default:
257: return FALSE;
258: }
259: }
260:
261: /* Reloc handling. MIPS ECOFF relocs are packed into 8 bytes in
262: external form. They use a bit which indicates whether the symbol
263: is external. */
264:
265: /* Swap a reloc in. */
266:
267: static void
268: mips_ecoff_swap_reloc_in (bfd * abfd,
269: void * ext_ptr,
270: struct internal_reloc *intern)
271: {
272: const RELOC *ext = (RELOC *) ext_ptr;
273:
274: intern->r_vaddr = H_GET_32 (abfd, ext->r_vaddr);
275: if (bfd_header_big_endian (abfd))
276: {
277: intern->r_symndx = (((int) ext->r_bits[0]
278: << RELOC_BITS0_SYMNDX_SH_LEFT_BIG)
279: | ((int) ext->r_bits[1]
280: << RELOC_BITS1_SYMNDX_SH_LEFT_BIG)
281: | ((int) ext->r_bits[2]
282: << RELOC_BITS2_SYMNDX_SH_LEFT_BIG));
283: intern->r_type = ((ext->r_bits[3] & RELOC_BITS3_TYPE_BIG)
284: >> RELOC_BITS3_TYPE_SH_BIG);
285: intern->r_extern = (ext->r_bits[3] & RELOC_BITS3_EXTERN_BIG) != 0;
286: }
287: else
288: {
289: intern->r_symndx = (((int) ext->r_bits[0]
290: << RELOC_BITS0_SYMNDX_SH_LEFT_LITTLE)
291: | ((int) ext->r_bits[1]
292: << RELOC_BITS1_SYMNDX_SH_LEFT_LITTLE)
293: | ((int) ext->r_bits[2]
294: << RELOC_BITS2_SYMNDX_SH_LEFT_LITTLE));
295: intern->r_type = (((ext->r_bits[3] & RELOC_BITS3_TYPE_LITTLE)
296: >> RELOC_BITS3_TYPE_SH_LITTLE)
297: | ((ext->r_bits[3] & RELOC_BITS3_TYPEHI_LITTLE)
298: << RELOC_BITS3_TYPEHI_SH_LITTLE));
299: intern->r_extern = (ext->r_bits[3] & RELOC_BITS3_EXTERN_LITTLE) != 0;
300: }
301: }
302:
303: /* Swap a reloc out. */
304:
305: static void
306: mips_ecoff_swap_reloc_out (bfd * abfd,
307: const struct internal_reloc * intern,
308: void * dst)
309: {
310: RELOC *ext = (RELOC *) dst;
311: long r_symndx;
312:
313: BFD_ASSERT (intern->r_extern
314: || (intern->r_symndx >= 0 && intern->r_symndx <= 12));
315:
316: r_symndx = intern->r_symndx;
317:
318: H_PUT_32 (abfd, intern->r_vaddr, ext->r_vaddr);
319: if (bfd_header_big_endian (abfd))
320: {
321: ext->r_bits[0] = r_symndx >> RELOC_BITS0_SYMNDX_SH_LEFT_BIG;
322: ext->r_bits[1] = r_symndx >> RELOC_BITS1_SYMNDX_SH_LEFT_BIG;
323: ext->r_bits[2] = r_symndx >> RELOC_BITS2_SYMNDX_SH_LEFT_BIG;
324: ext->r_bits[3] = (((intern->r_type << RELOC_BITS3_TYPE_SH_BIG)
325: & RELOC_BITS3_TYPE_BIG)
326: | (intern->r_extern ? RELOC_BITS3_EXTERN_BIG : 0));
327: }
328: else
329: {
330: ext->r_bits[0] = r_symndx >> RELOC_BITS0_SYMNDX_SH_LEFT_LITTLE;
331: ext->r_bits[1] = r_symndx >> RELOC_BITS1_SYMNDX_SH_LEFT_LITTLE;
332: ext->r_bits[2] = r_symndx >> RELOC_BITS2_SYMNDX_SH_LEFT_LITTLE;
333: ext->r_bits[3] = (((intern->r_type << RELOC_BITS3_TYPE_SH_LITTLE)
334: & RELOC_BITS3_TYPE_LITTLE)
335: | ((intern->r_type >> RELOC_BITS3_TYPEHI_SH_LITTLE
336: & RELOC_BITS3_TYPEHI_LITTLE))
337: | (intern->r_extern ? RELOC_BITS3_EXTERN_LITTLE : 0));
338: }
339: }
340:
341: /* Finish canonicalizing a reloc. Part of this is generic to all
342: ECOFF targets, and that part is in ecoff.c. The rest is done in
343: this backend routine. It must fill in the howto field. */
344:
345: static void
346: mips_adjust_reloc_in (bfd *abfd,
347: const struct internal_reloc *intern,
348: arelent *rptr)
349: {
350: if (intern->r_type > MIPS_R_PCREL16)
351: abort ();
352:
353: if (! intern->r_extern
354: && (intern->r_type == MIPS_R_GPREL
355: || intern->r_type == MIPS_R_LITERAL))
356: rptr->addend += ecoff_data (abfd)->gp;
357:
358: /* If the type is MIPS_R_IGNORE, make sure this is a reference to
359: the absolute section so that the reloc is ignored. */
360: if (intern->r_type == MIPS_R_IGNORE)
361: rptr->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr;
362:
363: rptr->howto = &mips_howto_table[intern->r_type];
364: }
365:
366: /* Make any adjustments needed to a reloc before writing it out. None
367: are needed for MIPS. */
368:
369: static void
370: mips_adjust_reloc_out (bfd *abfd ATTRIBUTE_UNUSED,
371: const arelent *rel ATTRIBUTE_UNUSED,
372: struct internal_reloc *intern ATTRIBUTE_UNUSED)
373: {
374: }
375:
376: /* ECOFF relocs are either against external symbols, or against
377: sections. If we are producing relocatable output, and the reloc
378: is against an external symbol, and nothing has given us any
379: additional addend, the resulting reloc will also be against the
380: same symbol. In such a case, we don't want to change anything
381: about the way the reloc is handled, since it will all be done at
382: final link time. Rather than put special case code into
383: bfd_perform_relocation, all the reloc types use this howto
384: function. It just short circuits the reloc if producing
385: relocatable output against an external symbol. */
386:
387: static bfd_reloc_status_type
388: mips_generic_reloc (bfd *abfd ATTRIBUTE_UNUSED,
389: arelent *reloc_entry,
390: asymbol *symbol,
391: void * data ATTRIBUTE_UNUSED,
392: asection *input_section,
393: bfd *output_bfd,
394: char **error_message ATTRIBUTE_UNUSED)
395: {
396: if (output_bfd != (bfd *) NULL
397: && (symbol->flags & BSF_SECTION_SYM) == 0
398: && reloc_entry->addend == 0)
399: {
400: reloc_entry->address += input_section->output_offset;
401: return bfd_reloc_ok;
402: }
403:
404: return bfd_reloc_continue;
405: }
406:
407: /* Do a REFHI relocation. This has to be done in combination with a
408: REFLO reloc, because there is a carry from the REFLO to the REFHI.
409: Here we just save the information we need; we do the actual
410: relocation when we see the REFLO. MIPS ECOFF requires that the
411: REFLO immediately follow the REFHI. As a GNU extension, we permit
412: an arbitrary number of HI relocs to be associated with a single LO
413: reloc. This extension permits gcc to output the HI and LO relocs
414: itself. */
415:
416: struct mips_hi
417: {
418: struct mips_hi *next;
419: bfd_byte *addr;
420: bfd_vma addend;
421: };
422:
423: /* FIXME: This should not be a static variable. */
424:
425: static struct mips_hi *mips_refhi_list;
426:
427: static bfd_reloc_status_type
428: mips_refhi_reloc (bfd *abfd ATTRIBUTE_UNUSED,
429: arelent *reloc_entry,
430: asymbol *symbol,
431: void * data,
432: asection *input_section,
433: bfd *output_bfd,
434: char **error_message ATTRIBUTE_UNUSED)
435: {
436: bfd_reloc_status_type ret;
437: bfd_vma relocation;
438: struct mips_hi *n;
439:
440: /* If we're relocating, and this an external symbol, we don't want
441: to change anything. */
442: if (output_bfd != (bfd *) NULL
443: && (symbol->flags & BSF_SECTION_SYM) == 0
444: && reloc_entry->addend == 0)
445: {
446: reloc_entry->address += input_section->output_offset;
447: return bfd_reloc_ok;
448: }
449:
450: ret = bfd_reloc_ok;
451: if (bfd_is_und_section (symbol->section)
452: && output_bfd == (bfd *) NULL)
453: ret = bfd_reloc_undefined;
454:
455: if (bfd_is_com_section (symbol->section))
456: relocation = 0;
457: else
458: relocation = symbol->value;
459:
460: relocation += symbol->section->output_section->vma;
461: relocation += symbol->section->output_offset;
462: relocation += reloc_entry->addend;
463:
464: if (reloc_entry->address > bfd_get_section_limit (abfd, input_section))
465: return bfd_reloc_outofrange;
466:
467: /* Save the information, and let REFLO do the actual relocation. */
468: n = (struct mips_hi *) bfd_malloc ((bfd_size_type) sizeof *n);
469: if (n == NULL)
470: return bfd_reloc_outofrange;
471: n->addr = (bfd_byte *) data + reloc_entry->address;
472: n->addend = relocation;
473: n->next = mips_refhi_list;
474: mips_refhi_list = n;
475:
476: if (output_bfd != (bfd *) NULL)
477: reloc_entry->address += input_section->output_offset;
478:
479: return ret;
480: }
481:
482: /* Do a REFLO relocation. This is a straightforward 16 bit inplace
483: relocation; this function exists in order to do the REFHI
484: relocation described above. */
485:
486: static bfd_reloc_status_type
487: mips_reflo_reloc (bfd *abfd ATTRIBUTE_UNUSED,
488: arelent *reloc_entry,
489: asymbol *symbol,
490: void * data,
491: asection *input_section,
492: bfd *output_bfd,
493: char **error_message ATTRIBUTE_UNUSED)
494: {
495: if (mips_refhi_list != NULL)
496: {
497: struct mips_hi *l;
498:
499: l = mips_refhi_list;
500: while (l != NULL)
501: {
502: unsigned long insn;
503: unsigned long val;
504: unsigned long vallo;
505: struct mips_hi *next;
506:
507: /* Do the REFHI relocation. Note that we actually don't
508: need to know anything about the REFLO itself, except
509: where to find the low 16 bits of the addend needed by the
510: REFHI. */
511: insn = bfd_get_32 (abfd, l->addr);
512: vallo = (bfd_get_32 (abfd, (bfd_byte *) data + reloc_entry->address)
513: & 0xffff);
514: val = ((insn & 0xffff) << 16) + vallo;
515: val += l->addend;
516:
517: /* The low order 16 bits are always treated as a signed
518: value. Therefore, a negative value in the low order bits
519: requires an adjustment in the high order bits. We need
520: to make this adjustment in two ways: once for the bits we
521: took from the data, and once for the bits we are putting
522: back in to the data. */
523: if ((vallo & 0x8000) != 0)
524: val -= 0x10000;
525: if ((val & 0x8000) != 0)
526: val += 0x10000;
527:
528: insn = (insn &~ (unsigned) 0xffff) | ((val >> 16) & 0xffff);
529: bfd_put_32 (abfd, (bfd_vma) insn, l->addr);
530:
531: next = l->next;
532: free (l);
533: l = next;
534: }
535:
536: mips_refhi_list = NULL;
537: }
538:
539: /* Now do the REFLO reloc in the usual way. */
540: return mips_generic_reloc (abfd, reloc_entry, symbol, data,
541: input_section, output_bfd, error_message);
542: }
543:
544: /* Do a GPREL relocation. This is a 16 bit value which must become
545: the offset from the gp register. */
546:
547: static bfd_reloc_status_type
548: mips_gprel_reloc (bfd *abfd ATTRIBUTE_UNUSED,
549: arelent *reloc_entry,
550: asymbol *symbol,
551: void * data,
552: asection *input_section,
553: bfd *output_bfd,
554: char **error_message ATTRIBUTE_UNUSED)
555: {
556: bfd_boolean relocatable;
557: bfd_vma gp;
558: bfd_vma relocation;
559: unsigned long val;
560: unsigned long insn;
561:
562: /* If we're relocating, and this is an external symbol with no
563: addend, we don't want to change anything. We will only have an
564: addend if this is a newly created reloc, not read from an ECOFF
565: file. */
566: if (output_bfd != (bfd *) NULL
567: && (symbol->flags & BSF_SECTION_SYM) == 0
568: && reloc_entry->addend == 0)
569: {
570: reloc_entry->address += input_section->output_offset;
571: return bfd_reloc_ok;
572: }
573:
574: if (output_bfd != (bfd *) NULL)
575: relocatable = TRUE;
576: else
577: {
578: relocatable = FALSE;
579: output_bfd = symbol->section->output_section->owner;
580: }
581:
582: if (bfd_is_und_section (symbol->section) && ! relocatable)
583: return bfd_reloc_undefined;
584:
585: /* We have to figure out the gp value, so that we can adjust the
586: symbol value correctly. We look up the symbol _gp in the output
587: BFD. If we can't find it, we're stuck. We cache it in the ECOFF
588: target data. We don't need to adjust the symbol value for an
589: external symbol if we are producing relocatable output. */
590: gp = _bfd_get_gp_value (output_bfd);
591: if (gp == 0
592: && (! relocatable
593: || (symbol->flags & BSF_SECTION_SYM) != 0))
594: {
595: if (relocatable)
596: {
597: /* Make up a value. */
598: gp = symbol->section->output_section->vma + 0x4000;
599: _bfd_set_gp_value (output_bfd, gp);
600: }
601: else
602: {
603: unsigned int count;
604: asymbol **sym;
605: unsigned int i;
606:
607: count = bfd_get_symcount (output_bfd);
608: sym = bfd_get_outsymbols (output_bfd);
609:
610: if (sym == (asymbol **) NULL)
611: i = count;
612: else
613: {
614: for (i = 0; i < count; i++, sym++)
615: {
616: register const char *name;
617:
618: name = bfd_asymbol_name (*sym);
619: if (*name == '_' && strcmp (name, "_gp") == 0)
620: {
621: gp = bfd_asymbol_value (*sym);
622: _bfd_set_gp_value (output_bfd, gp);
623: break;
624: }
625: }
626: }
627:
628: if (i >= count)
629: {
630: /* Only get the error once. */
631: gp = 4;
632: _bfd_set_gp_value (output_bfd, gp);
633: *error_message =
634: (char *) _("GP relative relocation when _gp not defined");
635: return bfd_reloc_dangerous;
636: }
637: }
638: }
639:
640: if (bfd_is_com_section (symbol->section))
641: relocation = 0;
642: else
643: relocation = symbol->value;
644:
645: relocation += symbol->section->output_section->vma;
646: relocation += symbol->section->output_offset;
647:
648: if (reloc_entry->address > bfd_get_section_limit (abfd, input_section))
649: return bfd_reloc_outofrange;
650:
651: insn = bfd_get_32 (abfd, (bfd_byte *) data + reloc_entry->address);
652:
653: /* Set val to the offset into the section or symbol. */
654: val = ((insn & 0xffff) + reloc_entry->addend) & 0xffff;
655: if (val & 0x8000)
656: val -= 0x10000;
657:
658: /* Adjust val for the final section location and GP value. If we
659: are producing relocatable output, we don't want to do this for
660: an external symbol. */
661: if (! relocatable
662: || (symbol->flags & BSF_SECTION_SYM) != 0)
663: val += relocation - gp;
664:
665: insn = (insn &~ (unsigned) 0xffff) | (val & 0xffff);
666: bfd_put_32 (abfd, (bfd_vma) insn, (bfd_byte *) data + reloc_entry->address);
667:
668: if (relocatable)
669: reloc_entry->address += input_section->output_offset;
670:
671: /* Make sure it fit in 16 bits. */
672: if ((long) val >= 0x8000 || (long) val < -0x8000)
673: return bfd_reloc_overflow;
674:
675: return bfd_reloc_ok;
676: }
677:
678: /* Get the howto structure for a generic reloc type. */
679:
680: static reloc_howto_type *
681: mips_bfd_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
682: bfd_reloc_code_real_type code)
683: {
684: int mips_type;
685:
686: switch (code)
687: {
688: case BFD_RELOC_16:
689: mips_type = MIPS_R_REFHALF;
690: break;
691: case BFD_RELOC_32:
692: case BFD_RELOC_CTOR:
693: mips_type = MIPS_R_REFWORD;
694: break;
695: case BFD_RELOC_MIPS_JMP:
696: mips_type = MIPS_R_JMPADDR;
697: break;
698: case BFD_RELOC_HI16_S:
699: mips_type = MIPS_R_REFHI;
700: break;
701: case BFD_RELOC_LO16:
702: mips_type = MIPS_R_REFLO;
703: break;
704: case BFD_RELOC_GPREL16:
705: mips_type = MIPS_R_GPREL;
706: break;
707: case BFD_RELOC_MIPS_LITERAL:
708: mips_type = MIPS_R_LITERAL;
709: break;
710: case BFD_RELOC_16_PCREL_S2:
711: mips_type = MIPS_R_PCREL16;
712: break;
713: default:
714: return (reloc_howto_type *) NULL;
715: }
716:
717: return &mips_howto_table[mips_type];
718: }
719:
720: static reloc_howto_type *
721: mips_bfd_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED,
722: const char *r_name)
723: {
724: unsigned int i;
725:
726: for (i = 0;
727: i < sizeof (mips_howto_table) / sizeof (mips_howto_table[0]);
728: i++)
729: if (mips_howto_table[i].name != NULL
730: && strcasecmp (mips_howto_table[i].name, r_name) == 0)
731: return &mips_howto_table[i];
732:
733: return NULL;
734: }
735:
736: /* A helper routine for mips_relocate_section which handles the REFHI
737: relocations. The REFHI relocation must be followed by a REFLO
738: relocation, and the addend used is formed from the addends of both
739: instructions. */
740:
741: static void
742: mips_relocate_hi (struct internal_reloc *refhi,
743: struct internal_reloc *reflo,
744: bfd *input_bfd,
745: asection *input_section,
746: bfd_byte *contents,
747: bfd_vma relocation)
748: {
749: unsigned long insn;
750: unsigned long val;
751: unsigned long vallo;
752:
753: if (refhi == NULL)
754: return;
755:
756: insn = bfd_get_32 (input_bfd,
757: contents + refhi->r_vaddr - input_section->vma);
758: if (reflo == NULL)
759: vallo = 0;
760: else
761: vallo = (bfd_get_32 (input_bfd,
762: contents + reflo->r_vaddr - input_section->vma)
763: & 0xffff);
764:
765: val = ((insn & 0xffff) << 16) + vallo;
766: val += relocation;
767:
768: /* The low order 16 bits are always treated as a signed value.
769: Therefore, a negative value in the low order bits requires an
770: adjustment in the high order bits. We need to make this
771: adjustment in two ways: once for the bits we took from the data,
772: and once for the bits we are putting back in to the data. */
773: if ((vallo & 0x8000) != 0)
774: val -= 0x10000;
775:
776: if ((val & 0x8000) != 0)
777: val += 0x10000;
778:
779: insn = (insn &~ (unsigned) 0xffff) | ((val >> 16) & 0xffff);
780: bfd_put_32 (input_bfd, (bfd_vma) insn,
781: contents + refhi->r_vaddr - input_section->vma);
782: }
783:
784: /* Relocate a section while linking a MIPS ECOFF file. */
785:
786: static bfd_boolean
787: mips_relocate_section (bfd *output_bfd,
788: struct bfd_link_info *info,
789: bfd *input_bfd,
790: asection *input_section,
791: bfd_byte *contents,
792: void * external_relocs)
793: {
794: asection **symndx_to_section;
795: struct ecoff_link_hash_entry **sym_hashes;
796: bfd_vma gp;
797: bfd_boolean gp_undefined;
798: struct external_reloc *ext_rel;
799: struct external_reloc *ext_rel_end;
800: unsigned int i;
801: bfd_boolean got_lo;
802: struct internal_reloc lo_int_rel;
803: bfd_size_type amt;
804:
805: BFD_ASSERT (input_bfd->xvec->byteorder
806: == output_bfd->xvec->byteorder);
807:
808: /* We keep a table mapping the symndx found in an internal reloc to
809: the appropriate section. This is faster than looking up the
810: section by name each time. */
811: symndx_to_section = ecoff_data (input_bfd)->symndx_to_section;
812: if (symndx_to_section == (asection **) NULL)
813: {
814: amt = NUM_RELOC_SECTIONS * sizeof (asection *);
815: symndx_to_section = (asection **) bfd_alloc (input_bfd, amt);
816: if (!symndx_to_section)
817: return FALSE;
818:
819: symndx_to_section[RELOC_SECTION_NONE] = NULL;
820: symndx_to_section[RELOC_SECTION_TEXT] =
821: bfd_get_section_by_name (input_bfd, ".text");
822: symndx_to_section[RELOC_SECTION_RDATA] =
823: bfd_get_section_by_name (input_bfd, ".rdata");
824: symndx_to_section[RELOC_SECTION_DATA] =
825: bfd_get_section_by_name (input_bfd, ".data");
826: symndx_to_section[RELOC_SECTION_SDATA] =
827: bfd_get_section_by_name (input_bfd, ".sdata");
828: symndx_to_section[RELOC_SECTION_SBSS] =
829: bfd_get_section_by_name (input_bfd, ".sbss");
830: symndx_to_section[RELOC_SECTION_BSS] =
831: bfd_get_section_by_name (input_bfd, ".bss");
832: symndx_to_section[RELOC_SECTION_INIT] =
833: bfd_get_section_by_name (input_bfd, ".init");
834: symndx_to_section[RELOC_SECTION_LIT8] =
835: bfd_get_section_by_name (input_bfd, ".lit8");
836: symndx_to_section[RELOC_SECTION_LIT4] =
837: bfd_get_section_by_name (input_bfd, ".lit4");
838: symndx_to_section[RELOC_SECTION_XDATA] = NULL;
839: symndx_to_section[RELOC_SECTION_PDATA] = NULL;
840: symndx_to_section[RELOC_SECTION_FINI] =
841: bfd_get_section_by_name (input_bfd, ".fini");
842: symndx_to_section[RELOC_SECTION_LITA] = NULL;
843: symndx_to_section[RELOC_SECTION_ABS] = NULL;
844:
845: ecoff_data (input_bfd)->symndx_to_section = symndx_to_section;
846: }
847:
848: sym_hashes = ecoff_data (input_bfd)->sym_hashes;
849:
850: gp = _bfd_get_gp_value (output_bfd);
851: if (gp == 0)
852: gp_undefined = TRUE;
853: else
854: gp_undefined = FALSE;
855:
856: got_lo = FALSE;
857:
858: ext_rel = (struct external_reloc *) external_relocs;
859: ext_rel_end = ext_rel + input_section->reloc_count;
860: for (i = 0; ext_rel < ext_rel_end; ext_rel++, i++)
861: {
862: struct internal_reloc int_rel;
863: bfd_boolean use_lo = FALSE;
864: bfd_vma addend;
865: reloc_howto_type *howto;
866: struct ecoff_link_hash_entry *h = NULL;
867: asection *s = NULL;
868: bfd_vma relocation;
869: bfd_reloc_status_type r;
870:
871: if (! got_lo)
872: mips_ecoff_swap_reloc_in (input_bfd, ext_rel, &int_rel);
873: else
874: {
875: int_rel = lo_int_rel;
876: got_lo = FALSE;
877: }
878:
879: BFD_ASSERT (int_rel.r_type
880: < sizeof mips_howto_table / sizeof mips_howto_table[0]);
881:
882: /* The REFHI reloc requires special handling. It must be followed
883: by a REFLO reloc, and the addend is formed from both relocs. */
884: if (int_rel.r_type == MIPS_R_REFHI)
885: {
886: struct external_reloc *lo_ext_rel;
887:
888: /* As a GNU extension, permit an arbitrary number of REFHI
889: relocs before the REFLO reloc. This permits gcc to emit
890: the HI and LO relocs itself. */
891: for (lo_ext_rel = ext_rel + 1;
892: lo_ext_rel < ext_rel_end;
893: lo_ext_rel++)
894: {
895: mips_ecoff_swap_reloc_in (input_bfd, lo_ext_rel,
896: &lo_int_rel);
897: if (lo_int_rel.r_type != int_rel.r_type)
898: break;
899: }
900:
901: if (lo_ext_rel < ext_rel_end
902: && lo_int_rel.r_type == MIPS_R_REFLO
903: && int_rel.r_extern == lo_int_rel.r_extern
904: && int_rel.r_symndx == lo_int_rel.r_symndx)
905: {
906: use_lo = TRUE;
907: if (lo_ext_rel == ext_rel + 1)
908: got_lo = TRUE;
909: }
910: }
911:
912: howto = &mips_howto_table[int_rel.r_type];
913:
914: if (int_rel.r_extern)
915: {
916: h = sym_hashes[int_rel.r_symndx];
917: /* If h is NULL, that means that there is a reloc against an
918: external symbol which we thought was just a debugging
919: symbol. This should not happen. */
920: if (h == (struct ecoff_link_hash_entry *) NULL)
921: abort ();
922: }
923: else
924: {
925: if (int_rel.r_symndx < 0 || int_rel.r_symndx >= NUM_RELOC_SECTIONS)
926: s = NULL;
927: else
928: s = symndx_to_section[int_rel.r_symndx];
929:
930: if (s == (asection *) NULL)
931: abort ();
932: }
933:
934: /* The GPREL reloc uses an addend: the difference in the GP
935: values. */
936: if (int_rel.r_type != MIPS_R_GPREL
937: && int_rel.r_type != MIPS_R_LITERAL)
938: addend = 0;
939: else
940: {
941: if (gp_undefined)
942: {
1.4.8.1 ! pgoyette 943: (*info->callbacks->reloc_dangerous)
! 944: (info, _("GP relative relocation used when GP not defined"),
! 945: input_bfd, input_section,
! 946: int_rel.r_vaddr - input_section->vma);
1.1 christos 947: /* Only give the error once per link. */
948: gp = 4;
949: _bfd_set_gp_value (output_bfd, gp);
950: gp_undefined = FALSE;
951: }
952: if (! int_rel.r_extern)
953: {
954: /* This is a relocation against a section. The current
955: addend in the instruction is the difference between
956: INPUT_SECTION->vma and the GP value of INPUT_BFD. We
957: must change this to be the difference between the
958: final definition (which will end up in RELOCATION)
959: and the GP value of OUTPUT_BFD (which is in GP). */
960: addend = ecoff_data (input_bfd)->gp - gp;
961: }
1.3 christos 962: else if (! bfd_link_relocatable (info)
1.1 christos 963: || h->root.type == bfd_link_hash_defined
964: || h->root.type == bfd_link_hash_defweak)
965: {
966: /* This is a relocation against a defined symbol. The
967: current addend in the instruction is simply the
968: desired offset into the symbol (normally zero). We
969: are going to change this into a relocation against a
970: defined symbol, so we want the instruction to hold
971: the difference between the final definition of the
972: symbol (which will end up in RELOCATION) and the GP
973: value of OUTPUT_BFD (which is in GP). */
974: addend = - gp;
975: }
976: else
977: {
978: /* This is a relocation against an undefined or common
979: symbol. The current addend in the instruction is
980: simply the desired offset into the symbol (normally
981: zero). We are generating relocatable output, and we
982: aren't going to define this symbol, so we just leave
983: the instruction alone. */
984: addend = 0;
985: }
986: }
987:
1.3 christos 988: if (bfd_link_relocatable (info))
1.1 christos 989: {
990: /* We are generating relocatable output, and must convert
991: the existing reloc. */
992: if (int_rel.r_extern)
993: {
994: if ((h->root.type == bfd_link_hash_defined
995: || h->root.type == bfd_link_hash_defweak)
996: && ! bfd_is_abs_section (h->root.u.def.section))
997: {
998: const char *name;
999:
1000: /* This symbol is defined in the output. Convert
1001: the reloc from being against the symbol to being
1002: against the section. */
1003:
1004: /* Clear the r_extern bit. */
1005: int_rel.r_extern = 0;
1006:
1007: /* Compute a new r_symndx value. */
1008: s = h->root.u.def.section;
1009: name = bfd_get_section_name (output_bfd,
1010: s->output_section);
1011:
1012: int_rel.r_symndx = -1;
1013: switch (name[1])
1014: {
1015: case 'b':
1016: if (strcmp (name, ".bss") == 0)
1017: int_rel.r_symndx = RELOC_SECTION_BSS;
1018: break;
1019: case 'd':
1020: if (strcmp (name, ".data") == 0)
1021: int_rel.r_symndx = RELOC_SECTION_DATA;
1022: break;
1023: case 'f':
1024: if (strcmp (name, ".fini") == 0)
1025: int_rel.r_symndx = RELOC_SECTION_FINI;
1026: break;
1027: case 'i':
1028: if (strcmp (name, ".init") == 0)
1029: int_rel.r_symndx = RELOC_SECTION_INIT;
1030: break;
1031: case 'l':
1032: if (strcmp (name, ".lit8") == 0)
1033: int_rel.r_symndx = RELOC_SECTION_LIT8;
1034: else if (strcmp (name, ".lit4") == 0)
1035: int_rel.r_symndx = RELOC_SECTION_LIT4;
1036: break;
1037: case 'r':
1038: if (strcmp (name, ".rdata") == 0)
1039: int_rel.r_symndx = RELOC_SECTION_RDATA;
1040: break;
1041: case 's':
1042: if (strcmp (name, ".sdata") == 0)
1043: int_rel.r_symndx = RELOC_SECTION_SDATA;
1044: else if (strcmp (name, ".sbss") == 0)
1045: int_rel.r_symndx = RELOC_SECTION_SBSS;
1046: break;
1047: case 't':
1048: if (strcmp (name, ".text") == 0)
1049: int_rel.r_symndx = RELOC_SECTION_TEXT;
1050: break;
1051: }
1052:
1053: if (int_rel.r_symndx == -1)
1054: abort ();
1055:
1056: /* Add the section VMA and the symbol value. */
1057: relocation = (h->root.u.def.value
1058: + s->output_section->vma
1059: + s->output_offset);
1060:
1061: /* For a PC relative relocation, the object file
1062: currently holds just the addend. We must adjust
1063: by the address to get the right value. */
1064: if (howto->pc_relative)
1065: relocation -= int_rel.r_vaddr - input_section->vma;
1066:
1067: h = NULL;
1068: }
1069: else
1070: {
1071: /* Change the symndx value to the right one for the
1072: output BFD. */
1073: int_rel.r_symndx = h->indx;
1074: if (int_rel.r_symndx == -1)
1075: {
1076: /* This symbol is not being written out. */
1.4.8.1 ! pgoyette 1077: (*info->callbacks->unattached_reloc)
! 1078: (info, h->root.root.string, input_bfd, input_section,
! 1079: int_rel.r_vaddr - input_section->vma);
1.1 christos 1080: int_rel.r_symndx = 0;
1081: }
1082: relocation = 0;
1083: }
1084: }
1085: else
1086: {
1087: /* This is a relocation against a section. Adjust the
1088: value by the amount the section moved. */
1089: relocation = (s->output_section->vma
1090: + s->output_offset
1091: - s->vma);
1092: }
1093:
1094: relocation += addend;
1095: addend = 0;
1096:
1097: /* Adjust a PC relative relocation by removing the reference
1098: to the original address in the section and including the
1099: reference to the new address. */
1100: if (howto->pc_relative)
1101: relocation -= (input_section->output_section->vma
1102: + input_section->output_offset
1103: - input_section->vma);
1104:
1105: /* Adjust the contents. */
1106: if (relocation == 0)
1107: r = bfd_reloc_ok;
1108: else
1109: {
1110: if (int_rel.r_type != MIPS_R_REFHI)
1111: r = _bfd_relocate_contents (howto, input_bfd, relocation,
1112: (contents
1113: + int_rel.r_vaddr
1114: - input_section->vma));
1115: else
1116: {
1117: mips_relocate_hi (&int_rel,
1118: use_lo ? &lo_int_rel : NULL,
1119: input_bfd, input_section, contents,
1120: relocation);
1121: r = bfd_reloc_ok;
1122: }
1123: }
1124:
1125: /* Adjust the reloc address. */
1126: int_rel.r_vaddr += (input_section->output_section->vma
1127: + input_section->output_offset
1128: - input_section->vma);
1129:
1130: /* Save the changed reloc information. */
1131: mips_ecoff_swap_reloc_out (input_bfd, &int_rel, ext_rel);
1132: }
1133: else
1134: {
1135: /* We are producing a final executable. */
1136: if (int_rel.r_extern)
1137: {
1138: /* This is a reloc against a symbol. */
1139: if (h->root.type == bfd_link_hash_defined
1140: || h->root.type == bfd_link_hash_defweak)
1141: {
1142: asection *hsec;
1143:
1144: hsec = h->root.u.def.section;
1145: relocation = (h->root.u.def.value
1146: + hsec->output_section->vma
1147: + hsec->output_offset);
1148: }
1149: else
1150: {
1.4.8.1 ! pgoyette 1151: (*info->callbacks->undefined_symbol)
! 1152: (info, h->root.root.string, input_bfd, input_section,
! 1153: int_rel.r_vaddr - input_section->vma, TRUE);
1.1 christos 1154: relocation = 0;
1155: }
1156: }
1157: else
1158: {
1159: /* This is a reloc against a section. */
1160: relocation = (s->output_section->vma
1161: + s->output_offset
1162: - s->vma);
1163:
1164: /* A PC relative reloc is already correct in the object
1165: file. Make it look like a pcrel_offset relocation by
1166: adding in the start address. */
1167: if (howto->pc_relative)
1168: relocation += int_rel.r_vaddr;
1169: }
1170:
1171: if (int_rel.r_type != MIPS_R_REFHI)
1172: r = _bfd_final_link_relocate (howto,
1173: input_bfd,
1174: input_section,
1175: contents,
1176: (int_rel.r_vaddr
1177: - input_section->vma),
1178: relocation,
1179: addend);
1180: else
1181: {
1182: mips_relocate_hi (&int_rel,
1183: use_lo ? &lo_int_rel : NULL,
1184: input_bfd, input_section, contents,
1185: relocation);
1186: r = bfd_reloc_ok;
1187: }
1188: }
1189:
1190: /* MIPS_R_JMPADDR requires peculiar overflow detection. The
1191: instruction provides a 28 bit address (the two lower bits are
1192: implicit zeroes) which is combined with the upper four bits
1193: of the instruction address. */
1194: if (r == bfd_reloc_ok
1195: && int_rel.r_type == MIPS_R_JMPADDR
1196: && (((relocation
1197: + addend
1198: + (int_rel.r_extern ? 0 : s->vma))
1199: & 0xf0000000)
1200: != ((input_section->output_section->vma
1201: + input_section->output_offset
1202: + (int_rel.r_vaddr - input_section->vma))
1203: & 0xf0000000)))
1204: r = bfd_reloc_overflow;
1205:
1206: if (r != bfd_reloc_ok)
1207: {
1208: switch (r)
1209: {
1210: default:
1211: case bfd_reloc_outofrange:
1212: abort ();
1213: case bfd_reloc_overflow:
1214: {
1215: const char *name;
1216:
1217: if (int_rel.r_extern)
1218: name = NULL;
1219: else
1220: name = bfd_section_name (input_bfd, s);
1.4.8.1 ! pgoyette 1221: (*info->callbacks->reloc_overflow)
! 1222: (info, (h ? &h->root : NULL), name, howto->name,
! 1223: (bfd_vma) 0, input_bfd, input_section,
! 1224: int_rel.r_vaddr - input_section->vma);
1.1 christos 1225: }
1226: break;
1227: }
1228: }
1229: }
1230:
1231: return TRUE;
1232: }
1233:
1234: /* This is the ECOFF backend structure. The backend field of the
1235: target vector points to this. */
1236:
1237: static const struct ecoff_backend_data mips_ecoff_backend_data =
1238: {
1239: /* COFF backend structure. */
1240: {
1241: (void (*) (bfd *,void *,int,int,int,int,void *)) bfd_void, /* aux_in */
1242: (void (*) (bfd *,void *,void *)) bfd_void, /* sym_in */
1243: (void (*) (bfd *,void *,void *)) bfd_void, /* lineno_in */
1244: (unsigned (*) (bfd *,void *,int,int,int,int,void *)) bfd_void,/*aux_out*/
1245: (unsigned (*) (bfd *,void *,void *)) bfd_void, /* sym_out */
1246: (unsigned (*) (bfd *,void *,void *)) bfd_void, /* lineno_out */
1247: (unsigned (*) (bfd *,void *,void *)) bfd_void, /* reloc_out */
1248: mips_ecoff_swap_filehdr_out, mips_ecoff_swap_aouthdr_out,
1249: mips_ecoff_swap_scnhdr_out,
1.3 christos 1250: FILHSZ, AOUTSZ, SCNHSZ, 0, 0, 0, 0, FILNMLEN, TRUE,
1251: ECOFF_NO_LONG_SECTION_NAMES, 4, FALSE, 2, 32768,
1.1 christos 1252: mips_ecoff_swap_filehdr_in, mips_ecoff_swap_aouthdr_in,
1253: mips_ecoff_swap_scnhdr_in, NULL,
1254: mips_ecoff_bad_format_hook, _bfd_ecoff_set_arch_mach_hook,
1255: _bfd_ecoff_mkobject_hook, _bfd_ecoff_styp_to_sec_flags,
1256: _bfd_ecoff_set_alignment_hook, _bfd_ecoff_slurp_symbol_table,
1257: NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
1258: NULL, NULL, NULL
1259: },
1260: /* Supported architecture. */
1261: bfd_arch_mips,
1262: /* Initial portion of armap string. */
1263: "__________",
1264: /* The page boundary used to align sections in a demand-paged
1265: executable file. E.g., 0x1000. */
1266: 0x1000,
1267: /* TRUE if the .rdata section is part of the text segment, as on the
1268: Alpha. FALSE if .rdata is part of the data segment, as on the
1269: MIPS. */
1270: FALSE,
1271: /* Bitsize of constructor entries. */
1272: 32,
1273: /* Reloc to use for constructor entries. */
1274: &mips_howto_table[MIPS_R_REFWORD],
1275: {
1276: /* Symbol table magic number. */
1277: magicSym,
1278: /* Alignment of debugging information. E.g., 4. */
1279: 4,
1280: /* Sizes of external symbolic information. */
1281: sizeof (struct hdr_ext),
1282: sizeof (struct dnr_ext),
1283: sizeof (struct pdr_ext),
1284: sizeof (struct sym_ext),
1285: sizeof (struct opt_ext),
1286: sizeof (struct fdr_ext),
1287: sizeof (struct rfd_ext),
1288: sizeof (struct ext_ext),
1289: /* Functions to swap in external symbolic data. */
1290: ecoff_swap_hdr_in,
1291: ecoff_swap_dnr_in,
1292: ecoff_swap_pdr_in,
1293: ecoff_swap_sym_in,
1294: ecoff_swap_opt_in,
1295: ecoff_swap_fdr_in,
1296: ecoff_swap_rfd_in,
1297: ecoff_swap_ext_in,
1298: _bfd_ecoff_swap_tir_in,
1299: _bfd_ecoff_swap_rndx_in,
1300: /* Functions to swap out external symbolic data. */
1301: ecoff_swap_hdr_out,
1302: ecoff_swap_dnr_out,
1303: ecoff_swap_pdr_out,
1304: ecoff_swap_sym_out,
1305: ecoff_swap_opt_out,
1306: ecoff_swap_fdr_out,
1307: ecoff_swap_rfd_out,
1308: ecoff_swap_ext_out,
1309: _bfd_ecoff_swap_tir_out,
1310: _bfd_ecoff_swap_rndx_out,
1311: /* Function to read in symbolic data. */
1312: _bfd_ecoff_slurp_symbolic_info
1313: },
1314: /* External reloc size. */
1315: RELSZ,
1316: /* Reloc swapping functions. */
1317: mips_ecoff_swap_reloc_in,
1318: mips_ecoff_swap_reloc_out,
1319: /* Backend reloc tweaking. */
1320: mips_adjust_reloc_in,
1321: mips_adjust_reloc_out,
1322: /* Relocate section contents while linking. */
1323: mips_relocate_section,
1324: /* Do final adjustments to filehdr and aouthdr. */
1325: NULL,
1326: /* Read an element from an archive at a given file position. */
1327: _bfd_get_elt_at_filepos
1328: };
1329:
1330: /* Looking up a reloc type is MIPS specific. */
1331: #define _bfd_ecoff_bfd_reloc_type_lookup mips_bfd_reloc_type_lookup
1332: #define _bfd_ecoff_bfd_reloc_name_lookup mips_bfd_reloc_name_lookup
1333:
1334: /* Getting relocated section contents is generic. */
1335: #define _bfd_ecoff_bfd_get_relocated_section_contents \
1336: bfd_generic_get_relocated_section_contents
1337:
1338: /* Handling file windows is generic. */
1339: #define _bfd_ecoff_get_section_contents_in_window \
1340: _bfd_generic_get_section_contents_in_window
1341:
1342: /* Relaxing sections is MIPS specific. */
1343: #define _bfd_ecoff_bfd_relax_section bfd_generic_relax_section
1344:
1345: /* GC of sections is not done. */
1346: #define _bfd_ecoff_bfd_gc_sections bfd_generic_gc_sections
1347:
1348: /* Input section flags is not implemented. */
1349: #define _bfd_ecoff_bfd_lookup_section_flags bfd_generic_lookup_section_flags
1350:
1351: /* Merging of sections is not done. */
1352: #define _bfd_ecoff_bfd_merge_sections bfd_generic_merge_sections
1353:
1354: #define _bfd_ecoff_bfd_is_group_section bfd_generic_is_group_section
1355: #define _bfd_ecoff_bfd_discard_group bfd_generic_discard_group
1356: #define _bfd_ecoff_section_already_linked \
1357: _bfd_coff_section_already_linked
1358: #define _bfd_ecoff_bfd_define_common_symbol bfd_generic_define_common_symbol
1359:
1.3 christos 1360: extern const bfd_target mips_ecoff_be_vec;
1.1 christos 1361:
1.3 christos 1362: const bfd_target mips_ecoff_le_vec =
1.1 christos 1363: {
1364: "ecoff-littlemips", /* name */
1365: bfd_target_ecoff_flavour,
1366: BFD_ENDIAN_LITTLE, /* data byte order is little */
1367: BFD_ENDIAN_LITTLE, /* header byte order is little */
1368:
1369: (HAS_RELOC | EXEC_P | /* object flags */
1370: HAS_LINENO | HAS_DEBUG |
1371: HAS_SYMS | HAS_LOCALS | WP_TEXT | D_PAGED),
1372:
1373: (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC | SEC_CODE | SEC_DATA),
1374: 0, /* leading underscore */
1375: ' ', /* ar_pad_char */
1376: 15, /* ar_max_namelen */
1377: 0, /* match priority. */
1378: bfd_getl64, bfd_getl_signed_64, bfd_putl64,
1379: bfd_getl32, bfd_getl_signed_32, bfd_putl32,
1380: bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* data */
1381: bfd_getl64, bfd_getl_signed_64, bfd_putl64,
1382: bfd_getl32, bfd_getl_signed_32, bfd_putl32,
1383: bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* hdrs */
1384:
1385: {_bfd_dummy_target, coff_object_p, /* bfd_check_format */
1386: bfd_generic_archive_p, _bfd_dummy_target},
1387: {bfd_false, _bfd_ecoff_mkobject, /* bfd_set_format */
1388: _bfd_generic_mkarchive, bfd_false},
1389: {bfd_false, _bfd_ecoff_write_object_contents, /* bfd_write_contents */
1390: _bfd_write_archive_contents, bfd_false},
1391:
1392: BFD_JUMP_TABLE_GENERIC (_bfd_ecoff),
1393: BFD_JUMP_TABLE_COPY (_bfd_ecoff),
1394: BFD_JUMP_TABLE_CORE (_bfd_nocore),
1395: BFD_JUMP_TABLE_ARCHIVE (_bfd_ecoff),
1396: BFD_JUMP_TABLE_SYMBOLS (_bfd_ecoff),
1397: BFD_JUMP_TABLE_RELOCS (_bfd_ecoff),
1398: BFD_JUMP_TABLE_WRITE (_bfd_ecoff),
1399: BFD_JUMP_TABLE_LINK (_bfd_ecoff),
1400: BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
1401:
1.3 christos 1402: & mips_ecoff_be_vec,
1.1 christos 1403:
1404: & mips_ecoff_backend_data
1405: };
1406:
1.3 christos 1407: const bfd_target mips_ecoff_be_vec =
1.1 christos 1408: {
1409: "ecoff-bigmips", /* name */
1410: bfd_target_ecoff_flavour,
1411: BFD_ENDIAN_BIG, /* data byte order is big */
1412: BFD_ENDIAN_BIG, /* header byte order is big */
1413:
1414: (HAS_RELOC | EXEC_P | /* object flags */
1415: HAS_LINENO | HAS_DEBUG |
1416: HAS_SYMS | HAS_LOCALS | WP_TEXT | D_PAGED),
1417:
1418: (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC | SEC_CODE | SEC_DATA),
1419: 0, /* leading underscore */
1420: ' ', /* ar_pad_char */
1421: 15, /* ar_max_namelen */
1422: 0, /* match priority. */
1423: bfd_getb64, bfd_getb_signed_64, bfd_putb64,
1424: bfd_getb32, bfd_getb_signed_32, bfd_putb32,
1425: bfd_getb16, bfd_getb_signed_16, bfd_putb16,
1426: bfd_getb64, bfd_getb_signed_64, bfd_putb64,
1427: bfd_getb32, bfd_getb_signed_32, bfd_putb32,
1428: bfd_getb16, bfd_getb_signed_16, bfd_putb16,
1429: {_bfd_dummy_target, coff_object_p, /* bfd_check_format */
1430: bfd_generic_archive_p, _bfd_dummy_target},
1431: {bfd_false, _bfd_ecoff_mkobject, /* bfd_set_format */
1432: _bfd_generic_mkarchive, bfd_false},
1433: {bfd_false, _bfd_ecoff_write_object_contents, /* bfd_write_contents */
1434: _bfd_write_archive_contents, bfd_false},
1435:
1436: BFD_JUMP_TABLE_GENERIC (_bfd_ecoff),
1437: BFD_JUMP_TABLE_COPY (_bfd_ecoff),
1438: BFD_JUMP_TABLE_CORE (_bfd_nocore),
1439: BFD_JUMP_TABLE_ARCHIVE (_bfd_ecoff),
1440: BFD_JUMP_TABLE_SYMBOLS (_bfd_ecoff),
1441: BFD_JUMP_TABLE_RELOCS (_bfd_ecoff),
1442: BFD_JUMP_TABLE_WRITE (_bfd_ecoff),
1443: BFD_JUMP_TABLE_LINK (_bfd_ecoff),
1444: BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
1445:
1.3 christos 1446: & mips_ecoff_le_vec,
1.1 christos 1447:
1448: & mips_ecoff_backend_data
1449: };
1450:
1.3 christos 1451: const bfd_target mips_ecoff_bele_vec =
1.1 christos 1452: {
1453: "ecoff-biglittlemips", /* name */
1454: bfd_target_ecoff_flavour,
1455: BFD_ENDIAN_LITTLE, /* data byte order is little */
1456: BFD_ENDIAN_BIG, /* header byte order is big */
1457:
1458: (HAS_RELOC | EXEC_P | /* object flags */
1459: HAS_LINENO | HAS_DEBUG |
1460: HAS_SYMS | HAS_LOCALS | WP_TEXT | D_PAGED),
1461:
1462: (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC | SEC_CODE | SEC_DATA),
1463: 0, /* leading underscore */
1464: ' ', /* ar_pad_char */
1465: 15, /* ar_max_namelen */
1466: 0, /* match priority. */
1467: bfd_getl64, bfd_getl_signed_64, bfd_putl64,
1468: bfd_getl32, bfd_getl_signed_32, bfd_putl32,
1469: bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* data */
1470: bfd_getb64, bfd_getb_signed_64, bfd_putb64,
1471: bfd_getb32, bfd_getb_signed_32, bfd_putb32,
1472: bfd_getb16, bfd_getb_signed_16, bfd_putb16, /* hdrs */
1473:
1474: {_bfd_dummy_target, coff_object_p, /* bfd_check_format */
1475: bfd_generic_archive_p, _bfd_dummy_target},
1476: {bfd_false, _bfd_ecoff_mkobject, /* bfd_set_format */
1477: _bfd_generic_mkarchive, bfd_false},
1478: {bfd_false, _bfd_ecoff_write_object_contents, /* bfd_write_contents */
1479: _bfd_write_archive_contents, bfd_false},
1480:
1481: BFD_JUMP_TABLE_GENERIC (_bfd_ecoff),
1482: BFD_JUMP_TABLE_COPY (_bfd_ecoff),
1483: BFD_JUMP_TABLE_CORE (_bfd_nocore),
1484: BFD_JUMP_TABLE_ARCHIVE (_bfd_ecoff),
1485: BFD_JUMP_TABLE_SYMBOLS (_bfd_ecoff),
1486: BFD_JUMP_TABLE_RELOCS (_bfd_ecoff),
1487: BFD_JUMP_TABLE_WRITE (_bfd_ecoff),
1488: BFD_JUMP_TABLE_LINK (_bfd_ecoff),
1489: BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
1490:
1491: NULL,
1492:
1493: & mips_ecoff_backend_data
1494: };
CVSweb <webmaster@jp.NetBSD.org>