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 ((PTR)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 ((PTR)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 ((PTR)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 */