mirror of
https://sourceware.org/git/binutils-gdb.git
synced 2024-12-09 04:21:49 +08:00
1094 lines
27 KiB
C
1094 lines
27 KiB
C
/* 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 */
|