0ae7af87e0cdd58a2a56f4bbd844b5c09ac36747
[binutils-gdb.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 static reloc_howto_type howto_table[] =
38 {
39 {0},
40 {1},
41 {2},
42 {3},
43 {4},
44 {5},
45 {6},
46 {7},
47 {8},
48 {9},
49 {10},
50 {11},
51 {12},
52 {13},
53 {14},
54 {15},
55 {16},
56 { R_RELLONG, 0, 2, 32, 0, 0, true, true},
57 {18},
58 {19},
59 {20},
60 {21},
61 {22},
62 {23},
63 {24},
64 { R_IPRMED, 2, 2,22,1,0, true, true},
65 {26},
66 /* FIXME: What do we do with this - ? */
67 #if 1
68 { R_OPTCALL, 0,2,32,0,0, true, true},
69 #else
70 { R_OPTCALL, 0,3,32,0,0, true, true},
71 #endif
72 };
73
74
75 #define ALIGN(this, boundary) \
76 ((( (this) + ((boundary) -1)) & (~((boundary)-1))))
77
78
79 /* Support for Motorola 88k bcs coff as well as Intel 960 coff */
80
81
82
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)))
87
88 #define TAG_SECTION_NAME ".tagbits"
89
90 /* Libraries shouldn't be doing this stuff anyway! */
91 void fatal();
92 /* void warning(); */
93 \f
94
95 /* initialize a section structure with information
96 * peculiar to this particular implementation of coff
97 */
98
99 static boolean
100 ecoff_new_section_hook(abfd, section)
101 bfd *abfd;
102 asection *section;
103 {
104 return true;
105 }
106 /* actually it makes itself and its children from the file headers */
107 static boolean
108 make_a_section_from_file (abfd, hdr)
109 bfd *abfd;
110 struct scnhdr *hdr;
111 {
112 asection *return_section ;
113
114 { char *name = (char *)xmalloc(9);
115
116 strncpy(name, (char *)&hdr->s_name[0], 8);
117
118 return_section = bfd_make_section(abfd, name);
119 (return_section->name)[8] = 0;
120 }
121
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);
131 #ifdef I960
132 assign (alignment, s_align);
133 #endif
134 assign (line_filepos, s_lnnoptr);
135 /* return_section->linesize = hdr->s_nlnno * sizeof (struct lineno);*/
136
137 #undef assign
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;
145
146 if (hdr->s_nreloc != 0) return_section->flags |= SEC_RELOC;
147
148 return true;
149 }
150
151 bfd_target *
152 ecoff_real_object_p (abfd, nscns, opthdr)
153 bfd *abfd;
154 unsigned short nscns, opthdr;
155 {
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 */
161
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;
168 return 0;
169 }
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);
174
175 /* Now copy data as required; construct all asections etc */
176 tdata = (struct icofdata *) bfd_zalloc (abfd, sizeof (struct icofdata) +
177 sizeof (AOUTHDR));
178 if (tdata == NULL) {
179 bfd_release (abfd, file_info);
180 bfd_error = no_memory;
181 return 0;
182 }
183
184 if (nscns != 0)
185 {
186 unsigned int i;
187 for (i = 0; i < nscns; i++)
188 {
189 make_a_section_from_file (abfd, sections + i);
190 }
191 }
192
193 abfd->flags |= HAS_RELOC | HAS_LINENO | HAS_LOCALS;
194
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;
203
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;
209 return abfd->xvec;
210 }
211
212 bfd_target *
213 ecoff_object_p (abfd)
214 bfd *abfd;
215 {
216 unsigned short magic, nscns, opthdr;
217
218 bfd_error = no_error;
219
220 /* figure out how much to read */
221 if (bfd_read (&magic, 1, sizeof (magic), abfd) != sizeof (magic))
222 return 0;
223
224 magic = bfd_h_getshort (abfd, (unsigned char *)&magic);
225 if (magic != (abfd->xvec->byteorder_big_p ? 0x160 : 0x162)) {
226 bfd_error = wrong_format;
227 return 0;
228 }
229 if (bfd_read (&nscns, 1, sizeof (nscns), abfd) != sizeof (nscns))
230 return 0;
231 nscns = bfd_h_getshort (abfd, (unsigned char *)&nscns);
232
233 if (bfd_seek (abfd,(file_ptr) ((sizeof (long)) * 3), true) < 0)
234 return 0;
235 if (bfd_read (&opthdr, 1, sizeof (opthdr), abfd) != sizeof (opthdr))
236 return 0;
237 opthdr = bfd_h_getshort (abfd, (unsigned char *)&opthdr);
238
239 return ecoff_real_object_p (abfd, nscns, opthdr);
240 }
241
242 static boolean
243 ecoff_mkobject (abfd)
244 bfd *abfd;
245 {
246 char *rawptr;
247
248
249 bfd_error = no_error;
250
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;
255 return false;
256 }
257 set_tdata (abfd, rawptr);
258 return true;
259 }
260 \f
261 static void
262 ecoff_count_linenumbers(abfd)
263 bfd *abfd;
264 {
265 unsigned int limit = bfd_get_symcount(abfd);
266 unsigned int i;
267 asymbol **p;
268 {
269 asection *s = abfd->sections->output_section;
270 while (s) {
271 BFD_ASSERT(s->lineno_count == 0);
272 s = s->next;
273 }
274 }
275
276
277 for (p = abfd->outsymbols,i = 0; i < limit; i++, p++)
278 {
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);
282 if (q->lineno)
283 {
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++;
288 l++;
289 while (l->line_number) {
290 q->symbol.section->output_section->lineno_count++;
291 l++;
292 }
293 }
294 }
295 }
296 }
297
298 static void
299 ecoff_write_symbols(abfd)
300 bfd *abfd;
301 {
302 }
303
304
305 void
306 ecoff_write_linenumbers(abfd)
307 bfd *abfd;
308 {
309 }
310
311
312 asymbol *
313 ecoff_make_empty_symbol(abfd, n)
314 bfd *abfd;
315 unsigned int n;
316 {
317 coff_symbol_type *new = (coff_symbol_type *)xmalloc(sizeof(coff_symbol_type));
318 new->native = 0;
319 new->lineno = (alent *)NULL;
320 new->symbol.the_bfd = abfd;
321 return &new->symbol;
322 }
323
324 /*SUPPRESS 558*/
325 /*SUPPRESS 529*/
326 boolean
327 ecoff_write_object_contents (abfd)
328 bfd *abfd;
329 {
330 return false;
331 }
332 \f
333 /* Calculate the file position for each section. */
334
335 static void
336 ecoff_compute_section_file_positions (abfd)
337 bfd *abfd;
338 {
339 abort();
340 }
341
342 boolean
343 ecoff_set_section_contents (abfd, section, location, offset, count)
344 bfd *abfd;
345 sec_ptr section;
346 unsigned char *location;
347 file_ptr offset;
348 int count;
349 {
350 return false;
351 }
352
353 boolean
354 ecoff_set_section_linenos (abfd, section, location, offset, count)
355 bfd *abfd;
356 sec_ptr section;
357 unsigned char *location;
358 file_ptr offset;
359 int count;
360 {
361 return 0;
362 }
363 \f
364
365 boolean
366 ecoff_close_and_cleanup (abfd)
367 bfd *abfd;
368 {
369 return false;
370 }
371 \f
372 static
373 struct sec *section_from_bfd_index(abfd, index)
374 bfd *abfd;
375 int index;
376 {
377 if (index > 0) {
378 struct sec *answer = abfd->sections;
379
380 while (--index) {
381 answer = answer->next;
382 }
383 return answer;
384 }
385 return 0;
386 }
387
388 static int
389 ecoff_get_symcount_upper_bound (abfd)
390 bfd *abfd;
391 {
392 fatal("call to ecoff_get_symcount_upper_bound");
393 return 0;
394 }
395
396 static symindex
397 ecoff_get_first_symbol (abfd)
398 bfd * abfd;
399 {
400 return 0;
401 }
402
403 static symindex
404 ecoff_get_next_symbol (abfd, oidx)
405 bfd *abfd;
406 symindex oidx;
407 {
408 if (oidx == BFD_NO_MORE_SYMBOLS) return BFD_NO_MORE_SYMBOLS;
409 return ++oidx >= bfd_get_symcount (abfd) ? BFD_NO_MORE_SYMBOLS : oidx;
410 }
411
412 static char *
413 ecoff_symbol_name (abfd, idx)
414 bfd *abfd;
415 symindex idx;
416 {
417 return (obj_symbols (abfd) + idx)->symbol.name;
418 }
419
420 static long
421 ecoff_symbol_value (abfd, idx)
422 bfd *abfd;
423 symindex idx;
424 {
425 return (obj_symbols (abfd) + idx)->symbol.value;
426 }
427
428 static symclass
429 ecoff_classify_symbol (abfd, idx)
430 bfd *abfd;
431 symindex idx;
432 {
433 abort();
434 }
435
436 static boolean
437 ecoff_symbol_hasclass (abfd, idx, class)
438 bfd *abfd;
439 symindex idx;
440 symclass class;
441 {
442 abort();
443 }
444
445
446
447
448 static
449 boolean
450 ecoff_slurp_line_table (abfd, asect)
451 bfd *abfd;
452 asection *asect;
453 {
454 return true;
455 }
456
457 static boolean
458 ecoff_slurp_symbol_table(abfd)
459 bfd *abfd;
460 {
461 abort();
462 }
463
464 unsigned int
465 ecoff_get_symtab_upper_bound (abfd)
466 bfd *abfd;
467 {
468 if (!ecoff_slurp_symbol_table (abfd)) return 0;
469
470 return (bfd_get_symcount (abfd)+1) * (sizeof (coff_symbol_type *));
471 }
472
473
474 unsigned int
475 ecoff_get_symtab(abfd, alocation)
476 bfd *abfd;
477 asymbol **alocation;
478 {
479 unsigned int counter = 0;
480 coff_symbol_type *symbase;
481 coff_symbol_type **location = (coff_symbol_type **)(alocation);
482
483 if (!ecoff_slurp_symbol_table (abfd)) return 0;
484
485 for (symbase = obj_symbols (abfd); counter++ < bfd_get_symcount (abfd);)
486 *(location++) = symbase++;
487 *location++ =0;
488 return counter;
489 }
490
491 unsigned int
492 ecoff_get_reloc_upper_bound (abfd, asect)
493 bfd *abfd;
494 sec_ptr asect;
495 {
496 if (bfd_get_format (abfd) != bfd_object) {
497 bfd_error = invalid_operation;
498 return 0;
499 }
500
501 return (asect->reloc_count + 1) * sizeof(arelent *);
502 }
503
504
505
506
507 boolean
508 ecoff_slurp_reloc_table (abfd, asect)
509 bfd *abfd;
510 sec_ptr asect;
511 {
512 abort();
513 }
514
515
516 /* This is stupid. This function should be a boolean predicate */
517 unsigned int
518 ecoff_canonicalize_reloc (abfd, section, relptr)
519 bfd *abfd;
520 sec_ptr section;
521 arelent **relptr;
522 {
523 return 0;
524 }
525
526 boolean
527 ecoff_get_section_contents (abfd, section, location, offset, count)
528 bfd *abfd;
529 sec_ptr section;
530 PTR location;
531 file_ptr offset;
532 int count;
533 {
534 if (count) {
535 if (offset >= section->size) return false;
536
537 bfd_seek (abfd, section->filepos + offset, SEEK_SET);
538
539 return (bfd_read (location, 1, count, abfd) == count) ? true:false;
540 }
541 else return true;
542 }
543
544 alent *
545 ecoff_get_lineno(ignore_abfd, ignore_symbol)
546 bfd *ignore_abfd;
547 PTR ignore_symbol;
548 {
549 return (alent *)NULL;
550 }
551
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
565
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 */
571
572 (HAS_RELOC | EXEC_P | /* object flags */
573 HAS_LINENO | HAS_DEBUG |
574 HAS_SYMS | HAS_LOCALS | DYNAMIC | WP_TEXT),
575
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 */
581
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 */
585 bfd_false},
586 JUMP_TABLE (ecoff)
587 };
588
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 */
594
595 (HAS_RELOC | EXEC_P | /* object flags */
596 HAS_LINENO | HAS_DEBUG |
597 HAS_SYMS | HAS_LOCALS | DYNAMIC | WP_TEXT),
598
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 */
604
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 */
608 bfd_false},
609 JUMP_TABLE(ecoff)
610 };