Various portability lints.
[platform/upstream/binutils.git] / bfd / coff-mips.c
1 /* MIPS Extended-Coff handler for Binary File Diddling.
2    Written by Per Bothner.  */
3
4 /* Copyright (C) 1990, 1991 Free Software Foundation, Inc.
5
6 This file is part of BFD, the Binary File Diddler.
7
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)
11 any later version.
12
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.
17
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.  */
21
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
24    out by default.  */
25
26 #define MIPS 1
27 #include <stdio.h>
28 #include <string.h>
29
30 #include "bfd.h"
31 #include "libbfd.h"
32 #include "sysdep.h"
33
34 #include "intel-coff.h"
35 #include "libcoff.h"            /* to allow easier abstraction-breaking */
36
37 /* initialize a section structure with information
38  * peculiar to this particular implementation of coff 
39  */
40
41 static boolean
42 ecoff_new_section_hook(ignore_abfd, ignore)
43 bfd *ignore_abfd;
44 asection *ignore;
45 {
46     return true;
47 }
48
49 /* Take a section header read from a coff file (in HOST byte order),
50    and make a BFD "section" out of it.  */
51 static          boolean
52 DEFUN(make_a_section_from_file,(abfd, hdr),
53       bfd            *abfd AND
54       struct scnhdr  *hdr)
55 {
56     asection       *return_section;
57
58     {
59         /* Assorted wastage to null-terminate the name, thanks AT&T! */
60         char *name = bfd_alloc(abfd, sizeof (hdr->s_name)+1);
61         if (name == NULL) {
62             bfd_error = no_memory;
63             return false;
64         }
65         strncpy(name, (char *) &hdr->s_name[0], sizeof (hdr->s_name));
66         name[sizeof (hdr->s_name)] = 0;
67
68         return_section = bfd_make_section(abfd, name);
69     }
70
71     /* s_paddr is presumed to be = to s_vaddr */
72 #define assign(to, from) return_section->to = hdr->from
73     assign(vma, s_vaddr);
74     /* assign (vma, s_vaddr); */
75     assign(size, s_size);
76     assign(filepos, s_scnptr);
77     assign(rel_filepos, s_relptr);
78     assign(reloc_count, s_nreloc);
79     assign(line_filepos, s_lnnoptr);
80     /*
81        return_section->linesize =   hdr->s_nlnno * sizeof (struct lineno);
82     */
83
84 #undef assign
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;
92
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;
97     return true;
98 }
99
100 bfd_target *
101 ecoff_real_object_p (abfd, nscns, opthdr)
102      bfd *abfd;
103      unsigned short nscns, opthdr;
104 {
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 */
110
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;
117     return 0;
118   }
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);
123
124   /* Now copy data as required; construct all asections etc */
125   tdata = (struct icofdata *) bfd_zalloc (abfd, sizeof (struct icofdata) +
126                                                 sizeof (AOUTHDR));
127   if (tdata == NULL) {
128     bfd_release (abfd, file_info);
129     bfd_error = no_memory;
130     return 0;
131   }
132
133   if (nscns != 0) 
134   {
135     unsigned int i;
136     for (i = 0; i < nscns; i++) 
137       {
138         make_a_section_from_file (abfd, sections + i);
139       }
140   }
141
142   abfd->flags |= HAS_RELOC | HAS_LINENO | HAS_LOCALS;
143
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;
152    
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;
158   return abfd->xvec;
159 }
160
161 bfd_target *
162 ecoff_object_p (abfd)
163      bfd *abfd;
164 {
165   unsigned char short_bytes[SHORT_SIZE];
166   unsigned short magic, nscns, opthdr;
167
168   bfd_error = no_error;
169
170   /* figure out how much to read */
171   if (bfd_read ((PTR)short_bytes, 1, SHORT_SIZE, abfd) != SHORT_SIZE)
172     return 0;
173
174   magic = bfd_h_getshort (abfd, short_bytes);
175   if (magic != (abfd->xvec->byteorder_big_p ? 0x160 :  0x162)) {
176     bfd_error = wrong_format;
177     return 0;
178   }
179   if (bfd_read ((PTR)short_bytes, 1, SHORT_SIZE, abfd) != SHORT_SIZE)
180     return 0;
181   nscns = bfd_h_getshort (abfd, short_bytes);
182
183   if (bfd_seek (abfd,(file_ptr) ((sizeof (long)) * 3), true) < 0) 
184     return 0;
185   if (bfd_read ((PTR)short_bytes, 1, SHORT_SIZE, abfd) != SHORT_SIZE)
186     return 0;
187   opthdr = bfd_h_getshort (abfd, short_bytes);
188
189   return ecoff_real_object_p (abfd, nscns, opthdr);
190 }
191
192 static boolean
193 ecoff_mkobject (abfd)
194      bfd *abfd;
195 {
196   char *rawptr;
197
198
199   bfd_error = no_error;
200
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;
205     return false;
206   }
207   set_tdata (abfd, rawptr);
208   return true;
209 }
210 \f
211 void
212 ecoff_write_linenumbers(ignore_abfd)
213 bfd *ignore_abfd;
214 {
215 }
216
217
218 static asymbol *
219 ecoff_make_empty_symbol(abfd)
220     bfd            *abfd;
221 {
222     coff_symbol_type *new = (coff_symbol_type *) bfd_alloc(abfd, sizeof(coff_symbol_type));
223     if (new == NULL) {
224         bfd_error = no_memory;
225         return (NULL);
226     }                           /* on error */
227     new->native = 0;
228     new->lineno = (alent *) NULL;
229     new->symbol.the_bfd = abfd;
230     return &new->symbol;
231 }
232
233 /*SUPPRESS 558*/
234 /*SUPPRESS 529*/
235 boolean
236 ecoff_write_object_contents (ignore_abfd)
237      bfd *ignore_abfd;
238 {
239   return false;
240 }
241 \f
242 /* Calculate the file position for each section. */
243 /* ARGSUSED */
244 boolean
245 ecoff_set_section_contents (abfd, section, location, offset, count)
246      bfd *abfd;
247      sec_ptr section;
248      unsigned char *location;
249      file_ptr offset;
250       int count;
251 {
252     return false;
253 }
254
255 /* ARGSUSED */
256 boolean
257 ecoff_set_section_linenos (abfd, section, location, offset, count)
258      bfd *abfd;
259      sec_ptr section;
260      unsigned char *location;
261      file_ptr offset;
262       int count;
263 {
264    return 0;
265 }
266 \f
267
268 /* ARGSUSED */
269 boolean
270 ecoff_close_and_cleanup (abfd)
271      bfd *abfd;
272 {
273   return false;
274 }
275 \f
276 /* ARGSUSED */
277 static boolean
278 ecoff_slurp_symbol_table(abfd)
279      bfd *abfd;
280 {
281     abort();
282 }
283
284 unsigned int
285 ecoff_get_symtab_upper_bound (abfd)
286      bfd *abfd;
287 {
288   if (!ecoff_slurp_symbol_table (abfd)) return 0;
289
290   return (bfd_get_symcount (abfd)+1) * (sizeof (coff_symbol_type *));
291 }
292
293
294 unsigned int
295 ecoff_get_symtab(abfd, alocation)
296 bfd *abfd;
297 asymbol **alocation;
298 {
299   unsigned int counter = 0;
300   coff_symbol_type *symbase;
301   coff_symbol_type **location = (coff_symbol_type **)(alocation);
302
303   if (!ecoff_slurp_symbol_table (abfd)) return 0;
304
305   for (symbase = obj_symbols (abfd); counter++ < bfd_get_symcount (abfd);)
306     *(location++) = symbase++;
307   *location++ =0;
308   return counter;
309 }
310
311 unsigned int
312 ecoff_get_reloc_upper_bound (abfd, asect)
313      bfd *abfd;
314      sec_ptr asect;
315 {
316   if (bfd_get_format (abfd) != bfd_object) {
317     bfd_error = invalid_operation;
318     return 0;
319   }
320
321   return   (asect->reloc_count + 1) * sizeof(arelent *);
322 }
323
324
325
326 /* ARGSUSED */
327 boolean
328 ecoff_slurp_reloc_table (abfd, asect)
329      bfd *abfd;
330      sec_ptr asect;
331 {
332     abort();
333 }
334
335
336 /* This is stupid.  This function should be a boolean predicate */
337 unsigned int
338 ecoff_canonicalize_reloc (abfd, section, relptr)
339      bfd *abfd;
340      sec_ptr section;
341      arelent **relptr;
342 {
343     return 0;
344 }
345
346 boolean
347 ecoff_get_section_contents (abfd, section, location, offset, count)
348      bfd *abfd;
349      sec_ptr section;
350      PTR location;
351      file_ptr offset;
352      int count;
353 {
354   if (count) {
355     if (offset >= section->size) return false;
356
357     bfd_seek (abfd, section->filepos + offset, SEEK_SET);
358
359     return (bfd_read (location, 1, count, abfd) == count) ? true:false;
360   }
361   else return true;
362 }
363
364 /* ARGSUSED */
365 alent *
366 ecoff_get_lineno(ignore_abfd, ignore_symbol)
367 bfd *ignore_abfd;
368 PTR ignore_symbol;
369 {
370 return (alent *)NULL;
371 }
372
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
386
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 */
392
393        (HAS_RELOC | EXEC_P |    /* object flags */
394         HAS_LINENO | HAS_DEBUG |
395         HAS_SYMS | HAS_LOCALS | DYNAMIC | WP_TEXT),
396
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 */
402
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 */
406           bfd_false},
407        JUMP_TABLE (ecoff)
408 };
409
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 */
415
416        (HAS_RELOC | EXEC_P |    /* object flags */
417         HAS_LINENO | HAS_DEBUG |
418         HAS_SYMS | HAS_LOCALS | DYNAMIC | WP_TEXT),
419
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 */
425
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 */
429           bfd_false},
430        JUMP_TABLE(ecoff)
431 };