diff options
Diffstat (limited to 'bfd/coff-mips.c')
-rw-r--r-- | bfd/coff-mips.c | 1093 |
1 files changed, 1093 insertions, 0 deletions
diff --git a/bfd/coff-mips.c b/bfd/coff-mips.c new file mode 100644 index 0000000..c27e8c3 --- /dev/null +++ b/bfd/coff-mips.c @@ -0,0 +1,1093 @@ +/* MIPS Extended-Coff handler for Binary File Diddling. + Written by Per Bothner. + + FIXME, Needs Copyleft here. */ + +/* This does not compile on anything but a MIPS yet (and I haven't been + able to test it there either since the latest merge!). So it stays + out by default. */ +#ifdef ECOFF_BFD + +#define MIPS 1 +#include "libbfd.h" +#include "sysdep.h" +#include "libcoff.h" /* to allow easier abstraction-breaking */ + +#include "intel-coff.h" + + + + +static reloc_howto_type howto_table[] = +{ + {0}, + {1}, + {2}, + {3}, + {4}, + {5}, + {6}, + {7}, + {8}, + {9}, + {10}, + {11}, + {12}, + {13}, + {14}, + {15}, + {16}, + { R_RELLONG, 0, 2, 32, 0, 0, true, true}, + {18}, + {19}, + {20}, + {21}, + {22}, + {23}, + {24}, + { R_IPRMED, 2, 2,22,1,0, true, true}, + {26}, +/* What do we do with this - ? */ +#if 1 + { R_OPTCALL, 0,2,32,0,0, true, true}, +#else + { R_OPTCALL, 0,3,32,0,0, true, true}, +#endif +}; + + +#define ALIGN(this, boundary) \ + ((( (this) + ((boundary) -1)) & (~((boundary)-1)))) + + +/* Support for Motorola 88k bcs coff as well as Intel 960 coff */ + + +#include <stdio.h> +#include <string.h> + + +/* Align an address by rounding it up to a power of two. It leaves the + address unchanged if align == 0 (2^0 = alignment of 1 byte) */ +#define i960_align(addr, align) \ + ( ((addr) + ((1<<(align))-1)) & (-1 << (align))) + +#define TAG_SECTION_NAME ".tagbits" + +/* Libraries shouldn't be doing this stuff anyway! */ +void fatal(); +/* void warning(); */ + + +/* initialize a section structure with information + * peculiar to this particular implementation of coff + */ + +static void +ecoff_new_section_hook(abfd, section) +bfd *abfd; +asection *section; +{ + + section->output_file_alignment = DEFAULT_SECTION_ALIGNMENT; + section->subsection_alignment = section->output_file_alignment; + if (abfd->flags & D_PAGED) + { + /** + If the output object file is demand paged then the + text section starts at the filehdr, with the first + usefull bit of data at the end of the filehdr+opthdr+ + scnhdrs. Since we don't know how many sections will + be put into the output file, we have to recalculate + the section pads after each additional section has + been created + **/ + asection *ptr = abfd->sections; + unsigned int padding = FILHSZ + AOUTSZ +SCNHSZ * abfd->section_count; + + padding = ALIGN(padding, ptr->output_file_alignment); + while (ptr) + { + ptr->start_pad = padding; + /* Only the first section is padded */ + padding = 0; + ptr = ptr->next; + } + } + else + { + + /* If the object is not demand paged, then all the sections + have no padding + */ + section->start_pad = 0; + } + + + +} +/* actually it makes itself and its children from the file headers */ +static boolean +make_a_section_from_file (abfd, hdr) +bfd *abfd; + struct scnhdr *hdr; + +{ + asection *return_section ; + + { char *name = (char *)xmalloc(9); + + strncpy(name, (char *)&hdr->s_name[0], 8); + + return_section = bfd_make_section(abfd, name); + (return_section->name)[8] = 0; + } + + /* s_paddr is presumed to be = to s_vaddr */ + /* FIXME -- needs to call swapping routines */ +#define assign(to, from) return_section->to = hdr->from + assign (vma, s_vaddr); + assign (original_vma, s_vaddr); + assign (size, s_size); + assign (filepos, s_scnptr); + assign (rel_filepos, s_relptr); + assign (reloc_count, s_nreloc); +#ifdef I960 + assign (alignment, s_align); +#endif + assign (line_filepos, s_lnnoptr); +/* return_section->linesize = hdr->s_nlnno * sizeof (struct lineno);*/ + +#undef assign + return_section->lineno_count = hdr->s_nlnno; + return_section->userdata = (void *)NULL; + return_section->next = (asection *)NULL; + if ((hdr->s_flags & STYP_TEXT) || (hdr->s_flags & STYP_DATA)) + return_section->flags = (SEC_LOAD | SEC_ALLOC); + else if (hdr->s_flags & STYP_BSS) + return_section->flags = SEC_ALLOC; + + if (hdr->s_nreloc != 0) return_section->flags |= SEC_RELOC; + + return true; +} + +bfd_target * +ecoff_real_object_p (abfd, nscns, opthdr) + bfd *abfd; + unsigned short nscns, opthdr; +{ + struct icofdata *tdata; + char *file_info; /* buffer for all the headers */ + long readsize; /* length of file_info */ + struct filehdr* filehdr; /* points into file_info */ + struct scnhdr *sections; /* points into file_info */ + + /* OK, now we know the format, read in the filehdr, soi-disant + "optional header", and all the sections.*/ + readsize = sizeof(struct filehdr) + opthdr + (nscns * sizeof (struct scnhdr)); + file_info = xmalloc (readsize); + if (file_info == NULL) { + bfd_error = no_memory; + return 0; + } + if (bfd_seek (abfd, 0, false) < 0) return 0; + if (bfd_read (file_info, 1, readsize, abfd) != readsize) return 0; + filehdr = (struct filehdr *) file_info; + sections = (struct scnhdr *) (file_info + sizeof (struct filehdr) + opthdr); + + /* Now copy data as required; construct all asections etc */ + tdata = (struct icofdata *) xmalloc (sizeof (struct icofdata) + + sizeof (AOUTHDR)); + if (tdata == NULL) { + bfd_error = no_memory; + return 0; + } + + if (nscns != 0) + { + unsigned int i; + for (i = 0; i < nscns; i++) + { + make_a_section_from_file (abfd, sections + i); + } + } + +#ifdef I960 + /* OK, now make a section for the tagbits if there were any */ +#if 0 + { + AOUTHDR *aouthdr; /* points into tdata! */ + aouthdr = (AOUTHDR *) (((char *) tdata) + sizeof (struct icofdata)); + if (aouthdr->tagentries != 0) { + asection *tag_section = (asection *) xmalloc (sizeof (asection)); + if (tag_section == NULL) { + free (tdata); + return 0; + } + tag_section->size = aouthdr->tagentries * sizeof (TAGBITS); + tag_section->name = TAG_SECTION_NAME; + tag_section->filepos = readsize; /* not surprisingly */ + /* Put this one first */ + tag_section->next = abfd->sections; + abfd->sections = tag_section; + } + } +#endif +#endif +abfd->flags |= HAS_RELOC | HAS_LINENO | HAS_LOCALS; + + + /* FIXME, the guess should be set by OR-ing info from the sections */ + if ((filehdr->f_flags & F_RELFLG) != F_RELFLG) abfd->flags &= ~HAS_RELOC; + if ((filehdr->f_flags & F_EXEC) == F_EXEC) abfd->flags |= EXEC_P; + if ((filehdr->f_flags & F_LNNO) != F_LNNO) abfd->flags &= ~HAS_LINENO; + if ((filehdr->f_flags & F_LSYMS) != F_LSYMS) abfd->flags &= ~HAS_LOCALS; + abfd->tdata = tdata; + bfd_get_symcount (abfd) = filehdr->f_nsyms; + if (filehdr->f_nsyms) abfd->flags |= HAS_SYMS; + + tdata->sym_filepos = filehdr->f_symptr; + tdata->hdr = (struct aouthdr *)(file_info + sizeof (struct filehdr)); + tdata->symbols = (esymbol *)NULL; + bfd_get_start_address (abfd) = exec_hdr (abfd)->entry; + return abfd->xvec; +} + +bfd_target * +ecoff_object_p (abfd) + bfd *abfd; +{ + unsigned short magic, nscns, opthdr; + + bfd_error = no_error; + + /* figure out how much to read */ + if (bfd_read (&magic, 1, sizeof (magic), abfd) != sizeof (magic)) + return 0; + + magic = bfd_h_getshort (abfd, (unsigned char *)&magic); + if (magic != (abfd->xvec->byteorder_big_p ? 0x160 : 0x162)) { + bfd_error = wrong_format; + return 0; + } + if (bfd_read (&nscns, 1, sizeof (nscns), abfd) != sizeof (nscns)) + return 0; + nscns = bfd_h_getshort (abfd, (unsigned char *)&nscns); + + if (bfd_seek (abfd, ((sizeof (long)) * 3), true) < 0) return false; + if (bfd_read (&opthdr, 1, sizeof (opthdr), abfd) != sizeof (opthdr)) + return 0; + opthdr = bfd_h_getshort (abfd, (unsigned char *)&opthdr); + + return ecoff_real_object_p (abfd, nscns, opthdr); +} + +static boolean +ecoff_mkobject (abfd) + bfd *abfd; +{ + char *rawptr; + + + bfd_error = no_error; + + /* Use an intermediate variable for clarity */ + rawptr = xmalloc (sizeof (struct icofdata) + sizeof (AOUTHDR)); + if (rawptr == NULL) { + bfd_error = no_memory; + return false; + } + + abfd->tdata = (struct icofdata *) rawptr; + exec_hdr (abfd) = (AOUTHDR *) (rawptr + sizeof (struct icofdata)); + + return true; +} + +static void +ecoff_count_linenumbers(abfd) +bfd *abfd; +{ + unsigned int limit = bfd_get_symcount(abfd); + unsigned int i = 0; + esymbol **p = (esymbol **)(abfd->outsymbols); + { + asection *s = abfd->sections; + while (s) { + if (s->lineno_count != 0) { + fatal("Bad initial state"); + } + s = s->next; + } + } + + while (i < limit) + { + esymbol *q = *p; + if (q->c.lineno) + { + /* This symbol has a linenumber, increment the + * owning section's linenumber count */ + alent *l = q->c.lineno; + q->c.section->lineno_count++; + l++; + while (l->line_number) { + q->c.section->lineno_count++; + l++; + } + } + p++; + i++; + } +} + +/* + run through the internal symbol table and make all the + pointers and things within the table point to the right places + */ + +static void +ecoff_mangle_symbols(abfd) +bfd *abfd; +{ + esymbol **p = (esymbol **)(abfd->outsymbols); + unsigned int native_index = 0; + unsigned int last_file_index = 0; + unsigned int limit = bfd_get_symcount(abfd); + struct syment *last_file_symbol = (struct syment *)NULL; + while (limit--) { + esymbol *q = *p; + struct syment *native = q->native; + if(native) { + /* Alter the native representation */ + + native->n_value = q->c.value; + if (q->c.flags & BSF_FORT_COMM) { + native->n_scnum = 0; + } + else if (q->c.flags & BSF_DEBUGGING) { + native->n_scnum = -2; + } + else if (q->c.flags & BSF_UNDEFINED) { + native->n_scnum = 0; + } + else if (q->c.flags & BSF_ABSOLUTE) { + native->n_scnum = -1; + } + else { + native->n_scnum = q->c.section->index + 1; + } + if (native->n_numaux) + { + union auxent *a = (union auxent *)(native+1); + /* Relocate symbol indexes */ + if (ISFCN(native->n_type)) + { + a->x_sym.x_fcnary.x_fcn.x_endndx += last_file_index; + } + else if(native->n_sclass == C_BLOCK && q->c.name[1] == 'b') + { + a->x_sym.x_fcnary.x_fcn.x_endndx += last_file_index; + } + + else if (native->n_sclass == C_STRTAG) + { + a->x_sym.x_fcnary.x_fcn.x_endndx += last_file_index; + } + else if (native->n_sclass == C_MOS || native->n_sclass == C_EOS || native->n_sclass == C_MOE) + { + a->x_sym.x_tagndx += last_file_index; + } + } + + + switch (native->n_sclass) { + case C_MOS: + case C_EOS: + case C_REGPARM: + case C_REG: + case 19: /*C_REGARG:FIXME */ + /* Fix so that they have an absolute section */ + native->n_scnum= -1; + break; + + case C_FILE: + /* Chain all the .file symbols together */ + if(last_file_symbol) { + last_file_symbol->n_value = native_index; + } + last_file_symbol = native; + last_file_index = native_index; + break; + case C_NULL: + case C_AUTO: + case C_EXT: + case C_EXTDEF: + case C_LABEL: + case C_ULABEL: + case C_USTATIC: + case C_STRTAG: + case C_FCN: + case C_BLOCK: + case C_STAT: + case C_LEAFPROC: + break; + default: + /* Bogus: This should be returning an error code, not printing + something out! */ + /* warning("Unrecognised sclass %d", native->n_sclass); */ + break; + } + native_index += 1 + native->n_numaux; + } + else { + native_index++; + } + p++; + } +} +static void +ecoff_write_symbols(abfd) +bfd *abfd; +{ +} + + +void +ecoff_write_linenumbers(abfd) +bfd *abfd; +{ +} + + +asymbol * +ecoff_make_empty_symbol(abfd, n) +bfd *abfd; +unsigned int n; +{ + unsigned int j; + esymbol *new = (esymbol *)xmalloc(sizeof(esymbol) * n); + for (j= 0; j < n; j++) { + new[j].native = 0; + new[j].c.lineno = (alent *)NULL; + } + return (asymbol *)new; +} + +/*SUPPRESS 558*/ +/*SUPPRESS 529*/ +boolean +ecoff_write_object_contents (abfd) + bfd *abfd; +{ + return false; +} + +/* Calculate the file position for each section. */ + +static void +ecoff_compute_section_file_positions (abfd) + bfd *abfd; +{ + file_ptr sofar = sizeof (struct filehdr) + sizeof (AOUTHDR); + asection *current; + + sofar += abfd->section_count * sizeof (struct scnhdr); + for (current = abfd->sections; current != NULL; current = current->next) { + sofar = ALIGN(sofar, current->output_file_alignment); + current->filepos = sofar; + /* Only add sections which are loadable */ + if (current->flags & SEC_LOAD) sofar += current->size; +#if 0 + if(current->filepos & (current->alignment-1)) { + sofar += current->alignment - (current->filepos &(current->alignment-1)); + current->filepos = (current->filepos + current->alignment) & -current->alignment; + } +#endif + } + obj_relocbase (abfd) = sofar; +} + +boolean +ecoff_set_section_contents (abfd, section, location, offset, count) + bfd *abfd; + sec_ptr section; + unsigned char *location; + file_ptr offset; + int count; +{ + return false; +} + +boolean +ecoff_set_section_linenos (abfd, section, location, offset, count) + bfd *abfd; + sec_ptr section; + unsigned char *location; + file_ptr offset; + int count; +{ + return 0; +} + + +boolean +ecoff_close_and_cleanup (abfd) + bfd *abfd; +{ + return false; +} + + + + + +static void * +buy_and_read(abfd, where, relative, size) +bfd *abfd; +int where; +boolean relative; +unsigned int size; +{ + void *area = (void *)xmalloc(size); + if (!area) { + bfd_error = no_memory; + return 0; + } + bfd_seek(abfd, where, relative); + if (bfd_read(area, 1, size, abfd) != size){ + bfd_error = system_call_error; + free(area); + return 0; + } + return area; +} + +static +struct sec_struct *section_from_bfd_index(abfd, index) +bfd *abfd; +int index; +{ +if (index > 0) { + struct sec_struct *answer = abfd->sections; + + while (--index) { + answer = answer->next; + } + return answer; +} +return 0; +} + +static int +ecoff_get_symcount_upper_bound (abfd) + bfd *abfd; +{ +fatal("call to ecoff_get_symcount_upper_bound"); +return 0; +} + +static symindex +ecoff_get_first_symbol (abfd) + bfd * abfd; +{ + return 0; +} + +static symindex +ecoff_get_next_symbol (abfd, oidx) + bfd *abfd; + symindex oidx; +{ + if (oidx == BFD_NO_MORE_SYMBOLS) return BFD_NO_MORE_SYMBOLS; + return ++oidx >= bfd_get_symcount (abfd) ? BFD_NO_MORE_SYMBOLS : oidx; +} + +static char * +ecoff_symbol_name (abfd, idx) + bfd *abfd; + symindex idx; +{ + return (obj_symbols (abfd) + idx)->c.name; +} + +static long +ecoff_symbol_value (abfd, idx) + bfd *abfd; + symindex idx; +{ + return (obj_symbols (abfd) + idx)->c.value; +} + +static symclass +ecoff_classify_symbol (abfd, idx) + bfd *abfd; + symindex idx; +{ + esymbol *sym = obj_symbols (abfd) + idx; + + if ((sym->c.flags & BSF_FORT_COMM) != 0) return bfd_symclass_fcommon; + if ((sym->c.flags & BSF_GLOBAL) != 0) return bfd_symclass_global; + if ((sym->c.flags & BSF_DEBUGGING) != 0) return bfd_symclass_debugger; + if ((sym->c.flags & BSF_UNDEFINED) != 0) return bfd_symclass_undefined; + + return bfd_symclass_unknown; +} + +static boolean +ecoff_symbol_hasclass (abfd, idx, class) + bfd *abfd; + symindex idx; + symclass class; +{ + + esymbol *sym = obj_symbols (abfd) + idx; + + switch (class) { + + case bfd_symclass_fcommon: return (sym->c.flags & BSF_FORT_COMM) != 0; + case bfd_symclass_global: return (sym->c.flags & BSF_GLOBAL) != 0; + case bfd_symclass_debugger: return (sym->c.flags & BSF_DEBUGGING) != 0; + case bfd_symclass_undefined: return (sym->c.flags & BSF_UNDEFINED) != 0; + + default: return false; + } +} + + + + +static +boolean +ecoff_slurp_line_table (abfd, asect) + bfd *abfd; + asection *asect; +{ + return true; +} + +static boolean +ecoff_slurp_symbol_table(abfd) + bfd *abfd; +{ + struct syment *native_symbols; + esymbol *cached_area; + char *string_table = (char *)NULL; + unsigned int string_table_size; + unsigned int number_of_symbols = 0; + if (obj_symbols (abfd)) return true; + bfd_seek(abfd, obj_sym_filepos(abfd), false); + /* Read in the symbol table */ + native_symbols = + (struct syment *)buy_and_read(abfd, + obj_sym_filepos(abfd), + false, + bfd_get_symcount(abfd) * sizeof(struct syment)); + if (!native_symbols) { + return false; + } + + + /* Allocate enough room for all the symbols in cached form */ + cached_area = (esymbol *)xmalloc(bfd_get_symcount(abfd) * sizeof(esymbol)); + + + { + + esymbol *dst = cached_area; + unsigned int last_native_index = bfd_get_symcount(abfd); + unsigned int this_index = 0; + while (this_index < last_native_index) + { + struct syment *src = native_symbols + this_index; + if (src->n_zeroes == 0) { + /* This symbol has a name in the string table */ + /* Which means that we'll have to read it in */ + + /* Fetch the size of the string table which is straight after the + * symbol table + */ + if (string_table == (char *)NULL) { + if (bfd_read(&string_table_size, sizeof(string_table_size), 1, abfd) != + sizeof(string_table_size)) { + fatal("Corrupt coff format"); + } + else { + /* Read the string table */ + string_table = + (char *)buy_and_read(abfd,0, true, + string_table_size - sizeof(string_table_size)) ; + + } + } + + + dst->c.name = string_table + src->n_offset - 4; + } + else { + /* Otherwise we have to buy somewhere for this name */ + dst->c.name = xmalloc (SYMNMLEN+1); + strncpy(dst->c.name, src->n_name, SYMNMLEN); + dst->c.name[SYMNMLEN+1] = '\0'; /* Be sure to terminate it */ + } + + /* We use the native name field to point to the cached field */ + src->n_zeroes = (long)dst; + dst->c.section = section_from_bfd_index(abfd, src->n_scnum); + switch (src->n_sclass) + { +#ifdef I960 + case C_LEAFPROC: + dst->c.value = src->n_value - dst->c.section->vma; + dst->c.flags = BSF_EXPORT | BSF_GLOBAL; + dst->c.flags |= BSF_NOT_AT_END; + break; + +#endif + + case C_EXT: + if (src->n_scnum == 0) { + if (src->n_value == 0) + { + dst->c.flags = BSF_UNDEFINED; + } + else { + dst->c.flags = BSF_FORT_COMM; + dst->c.value = src->n_value; + } + } + else { + + /* Base the value as an index from the base of the section */ + if (dst->c.section == (asection *)NULL) + { + dst->c.flags = BSF_EXPORT | BSF_GLOBAL | BSF_ABSOLUTE; + dst->c.value = src->n_value; + } + else + { + dst->c.flags = BSF_EXPORT | BSF_GLOBAL; + dst->c.value = src->n_value - dst->c.section->vma; + } + if (ISFCN(src->n_type)) { + /* A function ext does not go at the end of a file*/ + dst->c.flags |= BSF_NOT_AT_END; + } + + } + + break; + case C_STAT : /* static */ + case C_LABEL : /* label */ + dst->c.flags = BSF_LOCAL; + /* Base the value as an index from the base of the section */ + dst->c.value = src->n_value - dst->c.section->vma; + break; + + case C_MOS : /* member of structure */ + case C_EOS : /* end of structure */ + case C_REGPARM : /* register parameter */ + case C_REG : /* register variable */ + case 19 : /* Intel specific REGARG FIXME */ + case C_TPDEF : /* type definition */ + + case C_ARG: + case C_AUTO: /* automatic variable */ + case C_FIELD: /* bit field */ + case C_ENTAG : /* enumeration tag */ + case C_MOE : /* member of enumeration */ + case C_MOU : /* member of union */ + case C_UNTAG : /* union tag */ + + dst->c.flags = BSF_DEBUGGING; + dst->c.value = src->n_value; + break; + + case C_FILE : /* file name */ + case C_STRTAG : /* structure tag */ + dst->c.flags = BSF_DEBUGGING; + dst->c.value = src->n_value ; + + break; + case C_BLOCK : /* ".bb" or ".eb" */ + case C_FCN : /* ".bf" or ".ef" */ + dst->c.flags = BSF_LOCAL; + /* Base the value as an index from the base of the section */ + dst->c.value = src->n_value - dst->c.section->vma; + + break; + case C_EFCN : /* physical end of function */ + case C_NULL: + case C_EXTDEF : /* external definition */ + case C_ULABEL : /* undefined label */ + case C_USTATIC : /* undefined static */ + case C_LINE : /* line # reformatted as symbol table entry */ + case C_ALIAS : /* duplicate tag */ + case C_HIDDEN : /* ext symbol in dmert public lib */ + + default: + + printf("SICK%d\n",src->n_sclass); + dst->c.flags = BSF_DEBUGGING; + dst->c.value = src->n_value ; + + break; + } + + + + + if (dst->c.flags == 0) fatal("OOOO dear"); + + dst->native = src; + dst->c.udata = 0; + dst->c.lineno = (alent *)NULL; + this_index += src->n_numaux + 1; + dst++; + number_of_symbols++; + } + + } + obj_symbols(abfd) = cached_area; + obj_raw_syments(abfd) = native_symbols; + bfd_get_symcount(abfd) = number_of_symbols; + + /* Slurp the line tables for each section too */ + { + asection *p; + p = abfd->sections; + while (p) { + ecoff_slurp_line_table(abfd, p); + p =p->next; + } + } + return true; +} + +unsigned int +ecoff_get_symtab_upper_bound (abfd) + bfd *abfd; +{ + if (!ecoff_slurp_symbol_table (abfd)) return 0; + + return (bfd_get_symcount (abfd)+1) * (sizeof (esymbol *)); +} + + +unsigned int +ecoff_get_symtab(abfd, alocation) +bfd *abfd; +asymbol **alocation; +{ + unsigned int counter = 0; + esymbol *symbase; + esymbol **location = (esymbol **)(alocation); + + if (!ecoff_slurp_symbol_table (abfd)) return 0; + + for (symbase = obj_symbols (abfd); counter++ < bfd_get_symcount (abfd);) + *(location++) = symbase++; + *location++ =0; + return counter; +} + +unsigned int +ecoff_get_reloc_upper_bound (abfd, asect) + bfd *abfd; + sec_ptr asect; +{ + if (bfd_get_format (abfd) != bfd_object) { + bfd_error = invalid_operation; + return 0; + } + + return (asect->reloc_count + 1) * sizeof(arelent *); +} + + + + +boolean +ecoff_slurp_reloc_table (abfd, asect) + bfd *abfd; + sec_ptr asect; +{ + struct reloc *native_relocs; + arelent *reloc_cache; + + if (asect->relocation) return true; + if (asect->reloc_count ==0) return true; + if (!ecoff_slurp_symbol_table (abfd)) return false; + + native_relocs = (struct reloc *)buy_and_read(abfd, + asect->rel_filepos, + false, + sizeof(struct reloc) * asect->reloc_count); + reloc_cache = (arelent *)xmalloc(asect->reloc_count * sizeof(arelent )); + + { + + unsigned int counter = 0; + arelent *cache_ptr = reloc_cache; + struct reloc *src = native_relocs; + while (counter < asect->reloc_count) + { + cache_ptr->address = src->r_vaddr - asect->original_vma; + cache_ptr->sym = (asymbol *)(src->r_symndx + + obj_raw_syments (abfd))->n_zeroes; + /* The symbols that we have read in have been relocated as if their + * sections started at 0. But the offsets refering to the symbols + * in the raw data have not been modified, so we have to have + * a negative addend to compensate + */ + if (cache_ptr->sym->section) { + cache_ptr->addend = - cache_ptr->sym->section->original_vma; + } + else { + /* If the symbol doesn't have a section then it hasn't been relocated, + * so we don't have to fix it + */ + cache_ptr->addend = 0; + } + + cache_ptr->section = 0; +#if I960 + cache_ptr->howto = howto_table + src->r_type; +#endif +#if M88 + if (src->r_type >= R_PCR16L && src->r_type <= R_VRT32) + { + cache_ptr->howto = howto_table + src->r_type - R_PCR16L; + } + else + { + fatal("unrecognised reloc type %d\n", src->r_type); + } +#endif + cache_ptr++; + src++; + counter++; + } + + } + + free (native_relocs); + asect->relocation = reloc_cache; + return true; +} + + +/* This is stupid. This function should be a boolean predicate */ +unsigned int +ecoff_canonicalize_reloc (abfd, section, relptr) + bfd *abfd; + sec_ptr section; + arelent **relptr; +{ + return 0; +} + +bfd_target ecoff_little_vec = + {"ecoff-littlemips", /* name */ + false, /* data byte order is little */ + false, /* header byte order is little */ + + (HAS_RELOC | EXEC_P | /* object flags */ + HAS_LINENO | HAS_DEBUG | + HAS_SYMS | HAS_LOCALS | DYNAMIC | WP_TEXT), + + (SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* section flags */ + 0, /* valid reloc types */ + '/', /* ar_pad_char */ + 15, /* ar_max_namelen */ + ecoff_close_and_cleanup, /* _close_and_cleanup */ + ecoff_set_section_contents, /* bfd_set_section_contents */ + ecoff_new_section_hook, /* new_section_hook */ + _bfd_dummy_core_file_failing_command, /* _core_file_failing_command */ + _bfd_dummy_core_file_failing_signal, /* _core_file_failing_signal */ + _bfd_dummy_core_file_matches_executable_p, /* _core_file_matches_ex...p */ + + bfd_slurp_coff_armap, /* bfd_slurp_armap */ + _bfd_slurp_extended_name_table, /* bfd_slurp_extended_name_table*/ + bfd_dont_truncate_arname, /* bfd_truncate_arname */ + + ecoff_get_symtab_upper_bound, /* get_symtab_upper_bound */ + ecoff_get_symtab, /* canonicalize_symtab */ + (void (*)())bfd_false, /* bfd_reclaim_symbol_table */ + ecoff_get_reloc_upper_bound, /* get_reloc_upper_bound */ + ecoff_canonicalize_reloc, /* bfd_canonicalize_reloc */ + (void (*)())bfd_false, /* bfd_reclaim_reloc */ + + ecoff_get_symcount_upper_bound, /* bfd_get_symcount_upper_bound */ + ecoff_get_first_symbol, /* bfd_get_first_symbol */ + ecoff_get_next_symbol, /* bfd_get_next_symbol */ + ecoff_classify_symbol, /* bfd_classify_symbol */ + ecoff_symbol_hasclass, /* bfd_symbol_hasclass */ + ecoff_symbol_name, /* bfd_symbol_name */ + ecoff_symbol_value, /* bfd_symbol_value */ + + _do_getllong, _do_putllong, _do_getlshort, _do_putlshort, /* data */ + _do_getllong, _do_putllong, _do_getlshort, _do_putlshort, /* hdrs */ + + {_bfd_dummy_target, ecoff_object_p, /* bfd_check_format */ + bfd_generic_archive_p, _bfd_dummy_target}, + {bfd_false, ecoff_mkobject, bfd_false, /* bfd_set_format */ + bfd_false}, + ecoff_make_empty_symbol, + + + }; + +bfd_target ecoff_big_vec = + {"ecoff-bigmips", /* name */ + true, /* data byte order is big */ + true, /* header byte order is big */ + + (HAS_RELOC | EXEC_P | /* object flags */ + HAS_LINENO | HAS_DEBUG | + HAS_SYMS | HAS_LOCALS | DYNAMIC | WP_TEXT), + + (SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* section flags */ + 0, /* valid reloc types */ + '/', /* ar_pad_char */ + 15, /* ar_max_namelen */ + ecoff_close_and_cleanup, /* _close_and_cleanup */ + ecoff_set_section_contents, /* bfd_set_section_contents */ + ecoff_new_section_hook, /* new_section_hook */ + _bfd_dummy_core_file_failing_command, /* _core_file_failing_command */ + _bfd_dummy_core_file_failing_signal, /* _core_file_failing_signal */ + _bfd_dummy_core_file_matches_executable_p, /* _core_file_matches_ex...p */ + + bfd_slurp_coff_armap, /* bfd_slurp_armap */ + _bfd_slurp_extended_name_table, /* bfd_slurp_extended_name_table*/ + bfd_dont_truncate_arname, /* bfd_truncate_arname */ + + ecoff_get_symtab_upper_bound, /* get_symtab_upper_bound */ + ecoff_get_symtab, /* canonicalize_symtab */ + (void (*)())bfd_false, /* bfd_reclaim_symbol_table */ + ecoff_get_reloc_upper_bound, /* get_reloc_upper_bound */ + ecoff_canonicalize_reloc, /* bfd_canonicalize_reloc */ + (void (*)())bfd_false, /* bfd_reclaim_reloc */ + + ecoff_get_symcount_upper_bound, /* bfd_get_symcount_upper_bound */ + ecoff_get_first_symbol, /* bfd_get_first_symbol */ + ecoff_get_next_symbol, /* bfd_get_next_symbol */ + ecoff_classify_symbol, /* bfd_classify_symbol */ + ecoff_symbol_hasclass, /* bfd_symbol_hasclass */ + ecoff_symbol_name, /* bfd_symbol_name */ + ecoff_symbol_value, /* bfd_symbol_value */ + + _do_getblong, _do_putblong, _do_getbshort, _do_putbshort, /* data */ + _do_getblong, _do_putblong, _do_getbshort, _do_putbshort, /* hdrs */ + + {_bfd_dummy_target, ecoff_object_p, /* bfd_check_format */ + bfd_generic_archive_p, _bfd_dummy_target}, + {bfd_false, ecoff_mkobject, bfd_false, /* bfd_set_format */ + bfd_false}, + ecoff_make_empty_symbol, + + + }; + +#endif /* ECOFF_BFD */ |