1 /* MIPS Extended-Coff handler for Binary File Diddling.
2 Written by Per Bothner.
4 /* Copyright (C) 1990, 1991 Free Software Foundation, Inc.
6 This file is part of BFD, the Binary File Diddler.
8 BFD 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 1, or (at your option)
13 BFD 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.
18 You should have received a copy of the GNU General Public License
19 along with BFD; see the file COPYING. If not, write to
20 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
22 /* This does not compile on anything but a MIPS yet (and I haven't been
23 able to test it there either since the latest merge!). So it stays
34 #include "intel-coff.h"
35 #include "libcoff.h" /* to allow easier abstraction-breaking */
37 static reloc_howto_type howto_table
[] =
56 { R_RELLONG
, 0, 2, 32, 0, 0, true, true},
64 { R_IPRMED
, 2, 2,22,1,0, true, true},
66 /* FIXME: What do we do with this - ? */
68 { R_OPTCALL
, 0,2,32,0,0, true, true},
70 { R_OPTCALL
, 0,3,32,0,0, true, true},
75 #define ALIGN(this, boundary) \
76 ((( (this) + ((boundary) -1)) & (~((boundary)-1))))
79 /* Support for Motorola 88k bcs coff as well as Intel 960 coff */
83 /* Align an address by rounding it up to a power of two. It leaves the
84 address unchanged if align == 0 (2^0 = alignment of 1 byte) */
85 #define i960_align(addr, align) \
86 ( ((addr) + ((1<<(align))-1)) & (-1 << (align)))
88 #define TAG_SECTION_NAME ".tagbits"
90 /* Libraries shouldn't be doing this stuff anyway! */
95 /* initialize a section structure with information
96 * peculiar to this particular implementation of coff
100 ecoff_new_section_hook(abfd
, section
)
106 /* actually it makes itself and its children from the file headers */
108 make_a_section_from_file (abfd
, hdr
)
112 asection
*return_section
;
114 { char *name
= (char *)xmalloc(9);
116 strncpy(name
, (char *)&hdr
->s_name
[0], 8);
118 return_section
= bfd_make_section(abfd
, name
);
119 (return_section
->name
)[8] = 0;
122 /* s_paddr is presumed to be = to s_vaddr */
123 /* FIXME -- needs to call swapping routines */
124 #define assign(to, from) return_section->to = hdr->from
125 assign (vma
, s_vaddr
);
126 /* assign (vma, s_vaddr);*/
127 assign (size
, s_size
);
128 assign (filepos
, s_scnptr
);
129 assign (rel_filepos
, s_relptr
);
130 assign (reloc_count
, s_nreloc
);
132 assign (alignment
, s_align
);
134 assign (line_filepos
, s_lnnoptr
);
135 /* return_section->linesize = hdr->s_nlnno * sizeof (struct lineno);*/
138 return_section
->lineno_count
= hdr
->s_nlnno
;
139 return_section
->userdata
= (void *)NULL
;
140 return_section
->next
= (asection
*)NULL
;
141 if ((hdr
->s_flags
& STYP_TEXT
) || (hdr
->s_flags
& STYP_DATA
))
142 return_section
->flags
= (SEC_LOAD
| SEC_ALLOC
);
143 else if (hdr
->s_flags
& STYP_BSS
)
144 return_section
->flags
= SEC_ALLOC
;
146 if (hdr
->s_nreloc
!= 0) return_section
->flags
|= SEC_RELOC
;
152 ecoff_real_object_p (abfd
, nscns
, opthdr
)
154 unsigned short nscns
, opthdr
;
156 struct icofdata
*tdata
;
157 char *file_info
; /* buffer for all the headers */
158 long readsize
; /* length of file_info */
159 struct filehdr
* filehdr
; /* points into file_info */
160 struct scnhdr
*sections
; /* points into file_info */
162 /* OK, now we know the format, read in the filehdr, soi-disant
163 "optional header", and all the sections.*/
164 readsize
= sizeof(struct filehdr
) + opthdr
+ (nscns
* sizeof (struct scnhdr
));
165 file_info
= (char*)bfd_alloc (abfd
, readsize
);
166 if (file_info
== NULL
) {
167 bfd_error
= no_memory
;
170 if (bfd_seek (abfd
, 0, false) < 0) return 0;
171 if (bfd_read (file_info
, 1, readsize
, abfd
) != readsize
) return 0;
172 filehdr
= (struct filehdr
*) file_info
;
173 sections
= (struct scnhdr
*) (file_info
+ sizeof (struct filehdr
) + opthdr
);
175 /* Now copy data as required; construct all asections etc */
176 tdata
= (struct icofdata
*) bfd_zalloc (abfd
, sizeof (struct icofdata
) +
179 bfd_release (abfd
, file_info
);
180 bfd_error
= no_memory
;
187 for (i
= 0; i
< nscns
; i
++)
189 make_a_section_from_file (abfd
, sections
+ i
);
193 abfd
->flags
|= HAS_RELOC
| HAS_LINENO
| HAS_LOCALS
;
195 /* FIXME, the guess should be set by OR-ing info from the sections */
196 if ((filehdr
->f_flags
& F_RELFLG
) != F_RELFLG
) abfd
->flags
&= ~HAS_RELOC
;
197 if ((filehdr
->f_flags
& F_EXEC
) == F_EXEC
) abfd
->flags
|= EXEC_P
;
198 if ((filehdr
->f_flags
& F_LNNO
) != F_LNNO
) abfd
->flags
&= ~HAS_LINENO
;
199 if ((filehdr
->f_flags
& F_LSYMS
) != F_LSYMS
) abfd
->flags
&= ~HAS_LOCALS
;
200 set_tdata (abfd
, tdata
);
201 bfd_get_symcount (abfd
) = filehdr
->f_nsyms
;
202 if (filehdr
->f_nsyms
) abfd
->flags
|= HAS_SYMS
;
204 tdata
->sym_filepos
= filehdr
->f_symptr
;
205 /* FIXME, needs byte swapping */
206 tdata
->hdr
= *(struct aouthdr
*)(file_info
+ sizeof (struct filehdr
));
207 tdata
->symbols
= (coff_symbol_type
*)NULL
;
208 bfd_get_start_address (abfd
) = exec_hdr (abfd
).entry
;
213 ecoff_object_p (abfd
)
216 unsigned short magic
, nscns
, opthdr
;
218 bfd_error
= no_error
;
220 /* figure out how much to read */
221 if (bfd_read (&magic
, 1, sizeof (magic
), abfd
) != sizeof (magic
))
224 magic
= bfd_h_getshort (abfd
, (unsigned char *)&magic
);
225 if (magic
!= (abfd
->xvec
->byteorder_big_p
? 0x160 : 0x162)) {
226 bfd_error
= wrong_format
;
229 if (bfd_read (&nscns
, 1, sizeof (nscns
), abfd
) != sizeof (nscns
))
231 nscns
= bfd_h_getshort (abfd
, (unsigned char *)&nscns
);
233 if (bfd_seek (abfd
,(file_ptr
) ((sizeof (long)) * 3), true) < 0)
235 if (bfd_read (&opthdr
, 1, sizeof (opthdr
), abfd
) != sizeof (opthdr
))
237 opthdr
= bfd_h_getshort (abfd
, (unsigned char *)&opthdr
);
239 return ecoff_real_object_p (abfd
, nscns
, opthdr
);
243 ecoff_mkobject (abfd
)
249 bfd_error
= no_error
;
251 /* Use an intermediate variable for clarity */
252 rawptr
= (char*)bfd_zalloc (abfd
, sizeof (struct icofdata
));
253 if (rawptr
== NULL
) {
254 bfd_error
= no_memory
;
257 set_tdata (abfd
, rawptr
);
262 ecoff_count_linenumbers(abfd
)
265 unsigned int limit
= bfd_get_symcount(abfd
);
269 asection
*s
= abfd
->sections
->output_section
;
271 BFD_ASSERT(s
->lineno_count
== 0);
277 for (p
= abfd
->outsymbols
,i
= 0; i
< limit
; i
++, p
++)
279 asymbol
*q_maybe
= *p
;
280 if (q_maybe
->the_bfd
->xvec
->flavour
== bfd_target_coff_flavour_enum
) {
281 coff_symbol_type
*q
= coffsymbol(q_maybe
);
284 /* This symbol has a linenumber, increment the
285 * owning section's linenumber count */
286 alent
*l
= q
->lineno
;
287 q
->symbol
.section
->output_section
->lineno_count
++;
289 while (l
->line_number
) {
290 q
->symbol
.section
->output_section
->lineno_count
++;
299 ecoff_write_symbols(abfd
)
306 ecoff_write_linenumbers(abfd
)
313 ecoff_make_empty_symbol(abfd
, n
)
317 coff_symbol_type
*new = (coff_symbol_type
*)xmalloc(sizeof(coff_symbol_type
));
319 new->lineno
= (alent
*)NULL
;
320 new->symbol
.the_bfd
= abfd
;
327 ecoff_write_object_contents (abfd
)
333 /* Calculate the file position for each section. */
336 ecoff_compute_section_file_positions (abfd
)
343 ecoff_set_section_contents (abfd
, section
, location
, offset
, count
)
346 unsigned char *location
;
354 ecoff_set_section_linenos (abfd
, section
, location
, offset
, count
)
357 unsigned char *location
;
366 ecoff_close_and_cleanup (abfd
)
373 struct sec
*section_from_bfd_index(abfd
, index
)
378 struct sec
*answer
= abfd
->sections
;
381 answer
= answer
->next
;
389 ecoff_get_symcount_upper_bound (abfd
)
392 fatal("call to ecoff_get_symcount_upper_bound");
397 ecoff_get_first_symbol (abfd
)
404 ecoff_get_next_symbol (abfd
, oidx
)
408 if (oidx
== BFD_NO_MORE_SYMBOLS
) return BFD_NO_MORE_SYMBOLS
;
409 return ++oidx
>= bfd_get_symcount (abfd
) ? BFD_NO_MORE_SYMBOLS
: oidx
;
413 ecoff_symbol_name (abfd
, idx
)
417 return (obj_symbols (abfd
) + idx
)->symbol
.name
;
421 ecoff_symbol_value (abfd
, idx
)
425 return (obj_symbols (abfd
) + idx
)->symbol
.value
;
429 ecoff_classify_symbol (abfd
, idx
)
437 ecoff_symbol_hasclass (abfd
, idx
, class)
450 ecoff_slurp_line_table (abfd
, asect
)
458 ecoff_slurp_symbol_table(abfd
)
465 ecoff_get_symtab_upper_bound (abfd
)
468 if (!ecoff_slurp_symbol_table (abfd
)) return 0;
470 return (bfd_get_symcount (abfd
)+1) * (sizeof (coff_symbol_type
*));
475 ecoff_get_symtab(abfd
, alocation
)
479 unsigned int counter
= 0;
480 coff_symbol_type
*symbase
;
481 coff_symbol_type
**location
= (coff_symbol_type
**)(alocation
);
483 if (!ecoff_slurp_symbol_table (abfd
)) return 0;
485 for (symbase
= obj_symbols (abfd
); counter
++ < bfd_get_symcount (abfd
);)
486 *(location
++) = symbase
++;
492 ecoff_get_reloc_upper_bound (abfd
, asect
)
496 if (bfd_get_format (abfd
) != bfd_object
) {
497 bfd_error
= invalid_operation
;
501 return (asect
->reloc_count
+ 1) * sizeof(arelent
*);
508 ecoff_slurp_reloc_table (abfd
, asect
)
516 /* This is stupid. This function should be a boolean predicate */
518 ecoff_canonicalize_reloc (abfd
, section
, relptr
)
527 ecoff_get_section_contents (abfd
, section
, location
, offset
, count
)
535 if (offset
>= section
->size
) return false;
537 bfd_seek (abfd
, section
->filepos
+ offset
, SEEK_SET
);
539 return (bfd_read (location
, 1, count
, abfd
) == count
) ? true:false;
545 ecoff_get_lineno(ignore_abfd
, ignore_symbol
)
549 return (alent
*)NULL
;
552 #define ecoff_core_file_failing_command _bfd_dummy_core_file_failing_command
553 #define ecoff_core_file_failing_signal _bfd_dummy_core_file_failing_signal
554 #define ecoff_core_file_matches_executable_p _bfd_dummy_core_file_matches_executable_p
555 #define ecoff_slurp_armap bfd_false
556 #define ecoff_slurp_extended_name_table bfd_false
557 #define ecoff_truncate_arname bfd_void
558 #define ecoff_write_armap bfd_false
559 #define ecoff_print_symbol bfd_void
560 #define ecoff_set_arch_mach bfd_false
561 #define ecoff_openr_next_archived_file bfd_generic_openr_next_archived_file
562 #define ecoff_find_nearest_line bfd_false
563 #define ecoff_generic_stat_arch_elt bfd_generic_stat_arch_elt
564 #define ecoff_sizeof_headers bfd_0
566 bfd_target ecoff_little_vec
=
567 {"ecoff-littlemips", /* name */
568 bfd_target_coff_flavour_enum
,
569 false, /* data byte order is little */
570 false, /* header byte order is little */
572 (HAS_RELOC
| EXEC_P
| /* object flags */
573 HAS_LINENO
| HAS_DEBUG
|
574 HAS_SYMS
| HAS_LOCALS
| DYNAMIC
| WP_TEXT
),
576 (SEC_HAS_CONTENTS
| SEC_ALLOC
| SEC_LOAD
| SEC_RELOC
), /* section flags */
577 '/', /* ar_pad_char */
578 15, /* ar_max_namelen */
579 _do_getllong
, _do_putllong
, _do_getlshort
, _do_putlshort
, /* data */
580 _do_getllong
, _do_putllong
, _do_getlshort
, _do_putlshort
, /* hdrs */
582 {_bfd_dummy_target
, ecoff_object_p
, /* bfd_check_format */
583 bfd_generic_archive_p
, _bfd_dummy_target
},
584 {bfd_false
, ecoff_mkobject
, bfd_false
, /* bfd_set_format */
589 bfd_target ecoff_big_vec
=
590 {"ecoff-bigmips", /* name */
591 bfd_target_coff_flavour_enum
,
592 true, /* data byte order is big */
593 true, /* header byte order is big */
595 (HAS_RELOC
| EXEC_P
| /* object flags */
596 HAS_LINENO
| HAS_DEBUG
|
597 HAS_SYMS
| HAS_LOCALS
| DYNAMIC
| WP_TEXT
),
599 (SEC_HAS_CONTENTS
| SEC_ALLOC
| SEC_LOAD
| SEC_RELOC
), /* section flags */
600 ' ', /* ar_pad_char */
601 16, /* ar_max_namelen */
602 _do_getblong
, _do_putblong
, _do_getbshort
, _do_putbshort
, /* data */
603 _do_getblong
, _do_putblong
, _do_getbshort
, _do_putbshort
, /* hdrs */
605 {_bfd_dummy_target
, ecoff_object_p
, /* bfd_check_format */
606 bfd_generic_archive_p
, _bfd_dummy_target
},
607 {bfd_false
, ecoff_mkobject
, bfd_false
, /* bfd_set_format */