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 /* initialize a section structure with information
38 * peculiar to this particular implementation of coff
42 ecoff_new_section_hook(ignore_abfd
, ignore
)
49 /* Take a section header read from a coff file (in HOST byte order),
50 and make a BFD "section" out of it. */
52 DEFUN(make_a_section_from_file
,(abfd
, hdr
),
56 asection
*return_section
;
59 /* Assorted wastage to null-terminate the name, thanks AT&T! */
60 char *name
= bfd_alloc(abfd
, sizeof (hdr
->s_name
)+1);
62 bfd_error
= no_memory
;
65 strncpy(name
, (char *) &hdr
->s_name
[0], sizeof (hdr
->s_name
));
66 name
[sizeof (hdr
->s_name
)] = 0;
68 return_section
= bfd_make_section(abfd
, name
);
71 /* s_paddr is presumed to be = to s_vaddr */
72 #define assign(to, from) return_section->to = hdr->from
74 /* assign (vma, s_vaddr); */
76 assign(filepos
, s_scnptr
);
77 assign(rel_filepos
, s_relptr
);
78 assign(reloc_count
, s_nreloc
);
79 assign(line_filepos
, s_lnnoptr
);
81 return_section->linesize = hdr->s_nlnno * sizeof (struct lineno);
85 return_section
->lineno_count
= hdr
->s_nlnno
;
86 return_section
->userdata
= NULL
;
87 return_section
->next
= (asection
*) NULL
;
88 if ((hdr
->s_flags
& STYP_TEXT
) || (hdr
->s_flags
& STYP_DATA
))
89 return_section
->flags
= (SEC_LOAD
| SEC_ALLOC
);
90 else if (hdr
->s_flags
& STYP_BSS
)
91 return_section
->flags
= SEC_ALLOC
;
93 if (hdr
->s_nreloc
!= 0)
94 return_section
->flags
|= SEC_RELOC
;
95 if (hdr
->s_scnptr
!= 0)
96 return_section
->flags
|= SEC_HAS_CONTENTS
;
101 ecoff_real_object_p (abfd
, nscns
, opthdr
)
103 unsigned short nscns
, opthdr
;
105 struct icofdata
*tdata
;
106 char *file_info
; /* buffer for all the headers */
107 long readsize
; /* length of file_info */
108 struct filehdr
* filehdr
; /* points into file_info */
109 struct scnhdr
*sections
; /* points into file_info */
111 /* OK, now we know the format, read in the filehdr, soi-disant
112 "optional header", and all the sections.*/
113 readsize
= sizeof(struct filehdr
) + opthdr
+ (nscns
* sizeof (struct scnhdr
));
114 file_info
= (char*)bfd_alloc (abfd
, readsize
);
115 if (file_info
== NULL
) {
116 bfd_error
= no_memory
;
119 if (bfd_seek (abfd
, 0, false) < 0) return 0;
120 if (bfd_read (file_info
, 1, readsize
, abfd
) != readsize
) return 0;
121 filehdr
= (struct filehdr
*) file_info
;
122 sections
= (struct scnhdr
*) (file_info
+ sizeof (struct filehdr
) + opthdr
);
124 /* Now copy data as required; construct all asections etc */
125 tdata
= (struct icofdata
*) bfd_zalloc (abfd
, sizeof (struct icofdata
) +
128 bfd_release (abfd
, file_info
);
129 bfd_error
= no_memory
;
136 for (i
= 0; i
< nscns
; i
++)
138 make_a_section_from_file (abfd
, sections
+ i
);
142 abfd
->flags
|= HAS_RELOC
| HAS_LINENO
| HAS_LOCALS
;
144 /* FIXME, the guess should be set by OR-ing info from the sections */
145 if ((filehdr
->f_flags
& F_RELFLG
) != F_RELFLG
) abfd
->flags
&= ~HAS_RELOC
;
146 if ((filehdr
->f_flags
& F_EXEC
) == F_EXEC
) abfd
->flags
|= EXEC_P
;
147 if ((filehdr
->f_flags
& F_LNNO
) != F_LNNO
) abfd
->flags
&= ~HAS_LINENO
;
148 if ((filehdr
->f_flags
& F_LSYMS
) != F_LSYMS
) abfd
->flags
&= ~HAS_LOCALS
;
149 set_tdata (abfd
, tdata
);
150 bfd_get_symcount (abfd
) = filehdr
->f_nsyms
;
151 if (filehdr
->f_nsyms
) abfd
->flags
|= HAS_SYMS
;
153 tdata
->sym_filepos
= filehdr
->f_symptr
;
154 /* FIXME, needs byte swapping */
155 tdata
->hdr
= *(struct aouthdr
*)(file_info
+ sizeof (struct filehdr
));
156 tdata
->symbols
= (coff_symbol_type
*)NULL
;
157 bfd_get_start_address (abfd
) = exec_hdr (abfd
).entry
;
162 ecoff_object_p (abfd
)
165 unsigned char short_bytes
[SHORT_SIZE
];
166 unsigned short magic
, nscns
, opthdr
;
168 bfd_error
= no_error
;
170 /* figure out how much to read */
171 if (bfd_read (short_bytes
, 1, SHORT_SIZE
, abfd
) != SHORT_SIZE
)
174 magic
= bfd_h_getshort (abfd
, short_bytes
);
175 if (magic
!= (abfd
->xvec
->byteorder_big_p
? 0x160 : 0x162)) {
176 bfd_error
= wrong_format
;
179 if (bfd_read (short_bytes
, 1, SHORT_SIZE
, abfd
) != SHORT_SIZE
)
181 nscns
= bfd_h_getshort (abfd
, short_bytes
);
183 if (bfd_seek (abfd
,(file_ptr
) ((sizeof (long)) * 3), true) < 0)
185 if (bfd_read (short_bytes
, 1, SHORT_SIZE
, abfd
) != SHORT_SIZE
)
187 opthdr
= bfd_h_getshort (abfd
, short_bytes
);
189 return ecoff_real_object_p (abfd
, nscns
, opthdr
);
193 ecoff_mkobject (abfd
)
199 bfd_error
= no_error
;
201 /* Use an intermediate variable for clarity */
202 rawptr
= (char*)bfd_zalloc (abfd
, sizeof (struct icofdata
));
203 if (rawptr
== NULL
) {
204 bfd_error
= no_memory
;
207 set_tdata (abfd
, rawptr
);
212 ecoff_write_linenumbers(ignore_abfd
)
219 ecoff_make_empty_symbol(abfd
)
222 coff_symbol_type
*new = (coff_symbol_type
*) bfd_alloc(abfd
, sizeof(coff_symbol_type
));
224 bfd_error
= no_memory
;
228 new->lineno
= (alent
*) NULL
;
229 new->symbol
.the_bfd
= abfd
;
236 ecoff_write_object_contents (ignore_abfd
)
242 /* Calculate the file position for each section. */
245 ecoff_set_section_contents (abfd
, section
, location
, offset
, count
)
248 unsigned char *location
;
257 ecoff_set_section_linenos (abfd
, section
, location
, offset
, count
)
260 unsigned char *location
;
270 ecoff_close_and_cleanup (abfd
)
278 ecoff_slurp_symbol_table(abfd
)
285 ecoff_get_symtab_upper_bound (abfd
)
288 if (!ecoff_slurp_symbol_table (abfd
)) return 0;
290 return (bfd_get_symcount (abfd
)+1) * (sizeof (coff_symbol_type
*));
295 ecoff_get_symtab(abfd
, alocation
)
299 unsigned int counter
= 0;
300 coff_symbol_type
*symbase
;
301 coff_symbol_type
**location
= (coff_symbol_type
**)(alocation
);
303 if (!ecoff_slurp_symbol_table (abfd
)) return 0;
305 for (symbase
= obj_symbols (abfd
); counter
++ < bfd_get_symcount (abfd
);)
306 *(location
++) = symbase
++;
312 ecoff_get_reloc_upper_bound (abfd
, asect
)
316 if (bfd_get_format (abfd
) != bfd_object
) {
317 bfd_error
= invalid_operation
;
321 return (asect
->reloc_count
+ 1) * sizeof(arelent
*);
328 ecoff_slurp_reloc_table (abfd
, asect
)
336 /* This is stupid. This function should be a boolean predicate */
338 ecoff_canonicalize_reloc (abfd
, section
, relptr
)
347 ecoff_get_section_contents (abfd
, section
, location
, offset
, count
)
355 if (offset
>= section
->size
) return false;
357 bfd_seek (abfd
, section
->filepos
+ offset
, SEEK_SET
);
359 return (bfd_read (location
, 1, count
, abfd
) == count
) ? true:false;
366 ecoff_get_lineno(ignore_abfd
, ignore_symbol
)
370 return (alent
*)NULL
;
373 #define ecoff_core_file_failing_command _bfd_dummy_core_file_failing_command
374 #define ecoff_core_file_failing_signal _bfd_dummy_core_file_failing_signal
375 #define ecoff_core_file_matches_executable_p _bfd_dummy_core_file_matches_executable_p
376 #define ecoff_slurp_armap bfd_false
377 #define ecoff_slurp_extended_name_table bfd_false
378 #define ecoff_truncate_arname bfd_void
379 #define ecoff_write_armap bfd_false
380 #define ecoff_print_symbol bfd_void
381 #define ecoff_set_arch_mach bfd_false
382 #define ecoff_openr_next_archived_file bfd_generic_openr_next_archived_file
383 #define ecoff_find_nearest_line bfd_false
384 #define ecoff_generic_stat_arch_elt bfd_generic_stat_arch_elt
385 #define ecoff_sizeof_headers bfd_0
387 bfd_target ecoff_little_vec
=
388 {"ecoff-littlemips", /* name */
389 bfd_target_coff_flavour_enum
,
390 false, /* data byte order is little */
391 false, /* header byte order is little */
393 (HAS_RELOC
| EXEC_P
| /* object flags */
394 HAS_LINENO
| HAS_DEBUG
|
395 HAS_SYMS
| HAS_LOCALS
| DYNAMIC
| WP_TEXT
),
397 (SEC_HAS_CONTENTS
| SEC_ALLOC
| SEC_LOAD
| SEC_RELOC
), /* section flags */
398 '/', /* ar_pad_char */
399 15, /* ar_max_namelen */
400 _do_getllong
, _do_putllong
, _do_getlshort
, _do_putlshort
, /* data */
401 _do_getllong
, _do_putllong
, _do_getlshort
, _do_putlshort
, /* hdrs */
403 {_bfd_dummy_target
, ecoff_object_p
, /* bfd_check_format */
404 bfd_generic_archive_p
, _bfd_dummy_target
},
405 {bfd_false
, ecoff_mkobject
, bfd_false
, /* bfd_set_format */
410 bfd_target ecoff_big_vec
=
411 {"ecoff-bigmips", /* name */
412 bfd_target_coff_flavour_enum
,
413 true, /* data byte order is big */
414 true, /* header byte order is big */
416 (HAS_RELOC
| EXEC_P
| /* object flags */
417 HAS_LINENO
| HAS_DEBUG
|
418 HAS_SYMS
| HAS_LOCALS
| DYNAMIC
| WP_TEXT
),
420 (SEC_HAS_CONTENTS
| SEC_ALLOC
| SEC_LOAD
| SEC_RELOC
), /* section flags */
421 ' ', /* ar_pad_char */
422 16, /* ar_max_namelen */
423 _do_getblong
, _do_putblong
, _do_getbshort
, _do_putbshort
, /* data */
424 _do_getblong
, _do_putblong
, _do_getbshort
, _do_putbshort
, /* hdrs */
426 {_bfd_dummy_target
, ecoff_object_p
, /* bfd_check_format */
427 bfd_generic_archive_p
, _bfd_dummy_target
},
428 {bfd_false
, ecoff_mkobject
, bfd_false
, /* bfd_set_format */