Massive changes to generalize coff-bfd support enough to get 29k

working as well as it did before.

This means that 29k now supports multiple sections
This commit is contained in:
Steve Chamberlain 1991-11-29 01:05:58 +00:00
parent ada269da87
commit 63c92fcd96
5 changed files with 523 additions and 430 deletions

View File

@ -1,6 +1,7 @@
TARG_CPU_DEPENDENTS=
LOCAL_LOADLIBES=$(srcdir)/../bfd$(subdir)/libbfd.a
TDEFINES=-DBFD_HEADERS
TDEFINES=-DBFD_HEADERS -DMANY_SEGMENTS -DBFD

View File

@ -100,6 +100,9 @@ bfd *abfd;
void EXFUN(bfd_as_write_hook,(struct internal_filehdr *,
bfd *abfd));
static void EXFUN(fixup_segment,(fixS * fixP,
segT this_segment_type));
static void EXFUN(fill_section,(bfd *abfd ,
struct internal_filehdr *f, unsigned
long *));
@ -207,7 +210,16 @@ seg_info_type seg_info_off_by_4[N_SEG] =
{SEG_E7},
{SEG_E8},
{SEG_E9},
{SEG_REGISTER},
{15},
{16},
{17},
{18},
{19},
{20},
{21},
{22},
{23},
{SEG_REGISTER},0x1111,0x2222,0x3333,0x4444
};
@ -267,7 +279,6 @@ static unsigned int DEFUN(size_section,(abfd, idx),
return size;
}
/* Count the relocations in a chain */
static unsigned int DEFUN(count_entries_in_chain,(idx),
unsigned int idx)
@ -280,9 +291,21 @@ static unsigned int DEFUN(count_entries_in_chain,(idx),
nrelocs = 0;
while (fixup_ptr != (fixS *)NULL)
{
nrelocs ++ ;
fixup_ptr = fixup_ptr->fx_next;
if (TC_COUNT_RELOC(fixup_ptr))
{
#ifdef TC_A29K
if (fixup_ptr->fx_r_type == RELOC_CONSTH)
nrelocs+=2;
else
nrelocs++;
#else
nrelocs++;
#endif
}
fixup_ptr = fixup_ptr->fx_next;
}
return nrelocs;
}
@ -298,7 +321,7 @@ void DEFUN(do_relocs_for,(abfd, file_cursor),
asymbol **ptrs;
unsigned int idx;
asection *section = (asection *)(segment_info[idx].user_stuff);
unsigned int i;
fixS *from;
for (idx = SEG_E0; idx < SEG_E9; idx++)
@ -309,10 +332,15 @@ void DEFUN(do_relocs_for,(abfd, file_cursor),
struct external_reloc *ext_ptr;
struct external_reloc *external_reloc_vec;
unsigned int external_reloc_size;
unsigned int count = 0;
unsigned int base = segment_info[idx].scnhdr.s_paddr;
fixS * fix_ptr = segment_info[idx].fix_root;
nrelocs = count_entries_in_chain(idx);
external_reloc_size = nrelocs * RELSZ;
external_reloc_vec = (struct external_reloc*)alloca(external_reloc_size);
external_reloc_vec =
(struct external_reloc*)alloca(external_reloc_size);
ext_ptr = external_reloc_vec;
@ -323,23 +351,51 @@ void DEFUN(do_relocs_for,(abfd, file_cursor),
symbolS *symbol_ptr;
struct internal_reloc intr;
/* Only output some of the relocations */
if (TC_COUNT_RELOC(fix_ptr))
{
symbolS *dot;
symbol_ptr = fix_ptr->fx_addsy;
/* If this relocation is attached to a symbol then it's ok
to output it */
intr.r_type = TC_COFF_FIX2RTYPE(fix_ptr);
intr.r_vaddr = fix_ptr->fx_frag->fr_address + fix_ptr->fx_where ;
intr.r_vaddr = base + fix_ptr->fx_frag->fr_address + fix_ptr->fx_where ;
intr.r_offset = fix_ptr->fx_offset;
if (symbol_ptr)
intr.r_symndx = symbol_ptr->sy_number;
/* Turn the segment of the symbol into an offset
*/
dot =
segment_info[S_GET_SEGMENT(symbol_ptr)].dot;
if (dot)
{
intr.r_symndx = dot->sy_number;
}
else
intr.r_symndx = -1;
{
intr.r_symndx = symbol_ptr->sy_number;
}
(void)bfd_coff_swap_reloc_out(abfd, &intr, ext_ptr);
ext_ptr++;
#if defined(TC_A29K)
/* The 29k has a special kludge for the high 16 bit reloc.
Two relocations are emmited, R_IHIHALF, and
R_IHCONST. The second one doesn't contain a symbol,
but uses the value for offset */
if (intr.r_type == R_IHIHALF)
{
/* now emit the second bit */
intr.r_type = R_IHCONST;
intr.r_symndx = fix_ptr->fx_addnumber;
(void)bfd_coff_swap_reloc_out(abfd,&intr,ext_ptr);
ext_ptr++;
}
#endif
}
fix_ptr = fix_ptr->fx_next;
}
@ -368,6 +424,7 @@ static void DEFUN(fill_section,(abfd, filehdr, file_cursor),
for (i = SEG_E0; i < SEG_UNKNOWN; i++) {
unsigned int offset = 0;
struct internal_scnhdr *s = &( segment_info[i].scnhdr);
if (s->s_name[0]) {
@ -382,13 +439,11 @@ static void DEFUN(fill_section,(abfd, filehdr, file_cursor),
s->s_flags |= STYP_TEXT;
else if (strcmp(s->s_name,".data")==0)
s->s_flags |= STYP_DATA;
else if (strcmp(s->s_name,".text")==0)
else if (strcmp(s->s_name,".bss")==0)
s->s_flags |= STYP_BSS | STYP_NOLOAD;
while (frag) {
unsigned int fill_size;
unsigned int count;
switch (frag->fr_type) {
case rs_fill:
case rs_align:
@ -404,6 +459,7 @@ static void DEFUN(fill_section,(abfd, filehdr, file_cursor),
fill_size = frag->fr_var;
if (fill_size)
{
unsigned int count ;
unsigned int off = frag->fr_fix;
for (count = frag->fr_offset; count; count--)
{
@ -423,14 +479,14 @@ static void DEFUN(fill_section,(abfd, filehdr, file_cursor),
frag = frag->fr_next;
}
/*paddr += offset;
This causes problems with relocation. For the moment, all
sections start at 0
*/
bfd_write(buffer, s->s_size,1,abfd);
*file_cursor += s->s_size;
paddr += s->s_size;
}
}
}
@ -488,6 +544,12 @@ DEFUN(symbol_to_chars,(abfd, where, symbolP),
{
S_SET_SEGMENT(symbolP, SEG_ABSOLUTE);
}
/* At the same time, relocate all symbols to their output value */
S_SET_VALUE(symbolP,
segment_info[S_GET_SEGMENT(symbolP)].scnhdr.s_paddr
+ S_GET_VALUE(symbolP));
*where += bfd_coff_swap_sym_out(abfd, &symbolP->sy_symbol.ost_entry,
*where);
@ -1259,6 +1321,9 @@ static unsigned int DEFUN_VOID(tie_tags)
symbol_next(symbolP))
{
symbolP->sy_number = symbol_number;
if (SF_GET_TAGGED(symbolP))
{
SA_SET_SYM_TAGNDX
@ -1321,7 +1386,7 @@ static void DEFUN(crawl_symbols,(headers, abfd),
/* Is there a .file symbol ? If not insert one at the beginning. */
/*
* Build up static symbols for the sections
* Build up static symbols for the sections, they are filled in later
*/
@ -1331,47 +1396,21 @@ static void DEFUN(crawl_symbols,(headers, abfd),
{
segment_info[i].dot =
c_section_symbol(segment_info[i].scnhdr.s_name,
i,
ptr,
i-SEG_E0+1,
segment_info[i].scnhdr.s_size,
segment_info[i].scnhdr.s_paddr,
0,0);
i-SEG_E0+1);
}
}
#if defined(DEBUG)
verify_symbol_chain(symbol_rootP, symbol_lastP);
#endif /* DEBUG */
/* Take all the externals out and put them into another chain */
headers->f_nsyms = yank_symbols();
headers->f_nsyms = yank_symbols();
/* Take the externals and glue them onto the end.*/
headers->f_nsyms += glue_symbols();
headers->f_nsyms = tie_tags();
headers->f_nsyms = tie_tags();
know(symbol_externP == NULL);
know(symbol_extern_lastP == NULL);
#if 0
/* FIXME-SOMEDAY
I'm counting line no's here so we know what to put in the section
headers, and I'm resolving the addresses since I'm not sure how to
do it later. I am NOT resolving the linno's representing functions.
Their symbols need a fileptr pointing to this linno when emitted.
Thus, I resolve them on emit. xoxorich. */
for (lineP = lineno_rootP; lineP; lineP = lineP->next)
{
if (lineP->line.l_lnno > 0) {
lineP->line.l_addr.l_paddr += ((fragS*)lineP->frag)->fr_address;
} else {
;
}
text_lineno_number++;
} /* for each line number */
#endif
return;
}
@ -1406,6 +1445,74 @@ char *where;
/* This is a copy from aout. All I do is neglect to actually build the symbol. */
static void obj_coff_stab(what)
int what;
{
char *string;
expressionS e;
int goof = 0; /* TRUE if we have aborted. */
int length;
int saved_type = 0;
long longint;
symbolS *symbolP = 0;
if (what == 's') {
string = demand_copy_C_string(&length);
SKIP_WHITESPACE();
if (*input_line_pointer == ',') {
input_line_pointer++;
} else {
as_bad("I need a comma after symbol's name");
goof = 1;
} /* better be a comma */
} /* skip the string */
/*
* Input_line_pointer->after ','. String->symbol name.
*/
if (!goof) {
if (get_absolute_expression_and_terminator(&longint) != ',') {
as_bad("I want a comma after the n_type expression");
goof = 1;
input_line_pointer--; /* Backup over a non-',' char. */
} /* on error */
} /* no error */
if (!goof) {
if (get_absolute_expression_and_terminator(&longint) != ',') {
as_bad("I want a comma after the n_other expression");
goof = 1;
input_line_pointer--; /* Backup over a non-',' char. */
} /* on error */
} /* no error */
if (!goof) {
get_absolute_expression();
if (what == 's' || what == 'n') {
if (*input_line_pointer != ',') {
as_bad("I want a comma after the n_desc expression");
goof = 1;
} else {
input_line_pointer++;
} /* on goof */
} /* not stabd */
} /* no error */
expression(&e);
if (goof) {
ignore_rest_of_line();
} else {
demand_empty_rest_of_line();
} /* on error */
} /* obj_coff_stab() */
static void
DEFUN(do_linenos_for,(abfd, file_cursor),
bfd *abfd AND
@ -1493,15 +1600,17 @@ extern void DEFUN_VOID(write_object_file)
struct internal_aouthdr aouthdr;
unsigned long file_cursor;
bfd *abfd;
unsigned int addr = 0;
abfd = bfd_openw(out_file_name, TARGET_FORMAT);
if (abfd == 0) {
as_perror ("FATAL: Can't create %s", out_file_name);
exit(42);
}
bfd_set_format(abfd, bfd_object);
bfd_set_arch_mach(abfd, bfd_arch_h8300, 0);
bfd_set_arch_mach(abfd, BFD_ARCH, 0);
string_byte_count = 4;
@ -1525,21 +1634,16 @@ extern void DEFUN_VOID(write_object_file)
remove_subsegs();
#if 1
for (i = SEG_E0; i < SEG_UNKNOWN; i++)
{
relax_segment(segment_info[i].frchainP->frch_root, i);
}
for (i = SEG_E0; i < SEG_UNKNOWN; i++)
{
/* fixup_segment(segment_info[i].fix_root, i);*/
}
#endif
{
unsigned int addr = 0;
filehdr.f_nscns = 0;
/* Find out how big the sections are */
@ -1554,22 +1658,29 @@ extern void DEFUN_VOID(write_object_file)
if (i == SEG_E2) {
/* THis is a special case, we leave the size alone, which will have */
/* been made up from all and any lcomms seen */
}
else {
addr += size_section(abfd, i);
}
}
}
/* Turn the gas native symbol table shape into a coff symbol table */
crawl_symbols(&filehdr, abfd);
for (i = SEG_E0; i < SEG_UNKNOWN; i++)
{
fixup_segment(segment_info[i].fix_root, i);
}
file_cursor = FILHSZ + SCNHSZ * filehdr.f_nscns ;
bfd_seek(abfd, file_cursor, 0);
do_relocs_for(abfd, &file_cursor);
do_linenos_for(abfd, &file_cursor);
@ -1577,17 +1688,17 @@ extern void DEFUN_VOID(write_object_file)
fill_section(abfd,&filehdr, &file_cursor);
filehdr.f_magic = 0x8300;
filehdr.f_magic = COFF_MAGIC;
filehdr.f_timdat = 0;
filehdr.f_flags = 0;
{
{
unsigned int symtable_size = filehdr.f_nsyms * SYMESZ;
char *buffer1 = malloc(symtable_size);
char *buffer2 = malloc(string_byte_count+4);
char *buffer1 = alloca(symtable_size);
char *buffer2 = alloca(string_byte_count+4);
char *ptr = buffer1;
filehdr.f_symptr = bfd_tell(abfd);
w_symbols(abfd,&buffer1, symbol_rootP);
@ -1596,7 +1707,7 @@ extern void DEFUN_VOID(write_object_file)
w_strings(buffer2);
bfd_write(buffer2, 1, string_byte_count, abfd);
}
}
coff_header_append(abfd, &filehdr, &aouthdr);
bfd_close_all_done(abfd);
@ -1764,26 +1875,19 @@ char *filename;
* Build a 'section static' symbol.
*/
symbolS *c_section_symbol(name,idx, value, length, nreloc, nlnno)
symbolS *c_section_symbol(name,idx)
char *name;
long value;
long length;
unsigned short nreloc;
unsigned short nlnno;
int idx;
{
symbolS *symbolP;
symbolP = symbol_new(name,idx,
value,
0,
&zero_address_frag);
S_SET_STORAGE_CLASS(symbolP, C_STAT);
S_SET_NUMBER_AUXILIARY(symbolP, 1);
SA_SET_SCN_SCNLEN(symbolP, length);
SA_SET_SCN_NRELOC(symbolP, nreloc);
SA_SET_SCN_NLINNO(symbolP, nlnno);
SF_SET_STATICS(symbolP);
return symbolP;
@ -1795,6 +1899,22 @@ char **where AND
symbolS *symbol_rootP)
{
symbolS *symbolP;
unsigned int i;
/* First fill in those values we have only just worked out */
for (i = SEG_E0; i < SEG_E9; i++)
{
symbolP = segment_info[i].dot;
if (symbolP)
{
SA_SET_SCN_SCNLEN(symbolP, segment_info[i].scnhdr.s_size);
SA_SET_SCN_NRELOC(symbolP, segment_info[i].scnhdr.s_nreloc);
SA_SET_SCN_NLINNO(symbolP, segment_info[i].scnhdr.s_nlnno);
}
}
/*
* Emit all symbols left in the symbol chain.
*/
@ -1818,12 +1938,51 @@ symbolS *symbol_rootP)
}
} /* w_symbols() */
#if 0
static long fixup_segment(fixP, this_segment_type)
register fixS * fixP;
segT this_segment_type; /* N_TYPE bits for segment. */
static void DEFUN_VOID(obj_coff_lcomm)
{
char *name;
char c;
int temp;
char *p;
symbolS *symbolP;
name = input_line_pointer;
c = get_symbol_end();
p = input_line_pointer;
*p = c;
SKIP_WHITESPACE();
if (*input_line_pointer != ',') {
as_bad("Expected comma after name");
ignore_rest_of_line();
return;
}
if (*input_line_pointer == '\n') {
as_bad("Missing size expression");
return;
}
input_line_pointer++;
if ((temp = get_absolute_expression ()) < 0) {
as_warn("lcomm length (%d.) <0! Ignored.", temp);
ignore_rest_of_line();
return;
}
*p = 0;
symbolP = symbol_find_or_make(name);
S_SET_VALUE(symbolP, segment_info[SEG_E2].scnhdr.s_size);
S_SET_SEGMENT(symbolP, SEG_E2);
segment_info[SEG_E2].scnhdr.s_size += temp;
S_SET_STORAGE_CLASS(symbolP, C_STAT);
demand_empty_rest_of_line();
}
#if 1
static void DEFUN(fixup_segment,(fixP, this_segment_type),
register fixS * fixP AND
segT this_segment_type)
{
register long seg_reloc_count;
register symbolS *add_symbolP;
register symbolS *sub_symbolP;
register long add_number;
@ -1834,10 +1993,9 @@ segT this_segment_type; /* N_TYPE bits for segment. */
register fragS *fragP;
register segT add_symbol_segment = SEG_ABSOLUTE;
/* FIXME: remove this line */ /* fixS *orig = fixP; */
seg_reloc_count = 0;
for ( ; fixP; fixP = fixP->fx_next) {
for ( ; fixP; fixP = fixP->fx_next)
{
fragP = fixP->fx_frag;
know(fragP);
where = fixP->fx_where;
@ -1930,8 +2088,10 @@ segT this_segment_type; /* N_TYPE bits for segment. */
add_number -= md_pcrel_from (fixP);
pcrel = 0; /* Lie. Don't want further pcrel processing. */
fixP->fx_addsy = NULL; /* No relocations please. */
} else {
switch (add_symbol_segment) {
} else
{
switch (add_symbol_segment)
{
case SEG_ABSOLUTE:
#ifdef TC_I960
reloc_callj(fixP); /* See comment about reloc_callj() above*/
@ -1941,8 +2101,9 @@ segT this_segment_type; /* N_TYPE bits for segment. */
add_symbolP = NULL;
break;
default:
seg_reloc_count ++;
add_number += S_GET_VALUE(add_symbolP);
add_number += S_GET_VALUE(add_symbolP) +
segment_info[S_GET_SEGMENT(add_symbolP)].scnhdr.s_paddr ;
break;
case SEG_UNKNOWN:
@ -1958,15 +2119,8 @@ segT this_segment_type; /* N_TYPE bits for segment. */
continue;
} /* COBR */
#endif /* TC_I960 */
/* FIXME-SOON: I think this is trash, but I'm not sure. xoxorich. */
#ifdef comment
#ifdef OBJ_COFF
if (S_IS_COMMON(add_symbolP))
add_number += S_GET_VALUE(add_symbolP);
#endif /* OBJ_COFF */
#endif /* comment */
++seg_reloc_count;
break;
@ -1979,7 +2133,6 @@ segT this_segment_type; /* N_TYPE bits for segment. */
add_number -= md_pcrel_from(fixP);
if (add_symbolP == 0) {
fixP->fx_addsy = & abs_symbol;
++seg_reloc_count;
} /* if there's an add_symbol */
} /* if pcrel */
@ -1992,63 +2145,15 @@ segT this_segment_type; /* N_TYPE bits for segment. */
add_number, size, fragP->fr_address + where);
} /* generic error checking */
} /* not a bit fix */
/* once this fix has been applied, we don't have to output anything
nothing more need be done -*/
md_apply_fix(fixP, add_number);
} /* For each fixS in this segment. */
#ifdef OBJ_COFF
#ifdef TC_I960
{
fixS *topP = fixP;
/* two relocs per callj under coff. */
for (fixP = topP; fixP; fixP = fixP->fx_next) {
if (fixP->fx_callj && fixP->fx_addsy != 0) {
++seg_reloc_count;
} /* if callj and not already fixed. */
} /* for each fix */
}
#endif /* TC_I960 */
#endif /* OBJ_COFF */
return(seg_reloc_count);
} /* fixup_segment() */
#endif
void obj_coff_lcomm(void)
{
char *name;
char c;
int temp;
char *p;
symbolS *symbolP;
name = input_line_pointer;
c = get_symbol_end();
p = input_line_pointer;
*p = c;
SKIP_WHITESPACE();
if (*input_line_pointer != ',') {
as_bad("Expected comma after name");
ignore_rest_of_line();
return;
}
if (*input_line_pointer == '\n') {
as_bad("Missing size expression");
return;
}
input_line_pointer++;
if ((temp = get_absolute_expression ()) < 0) {
as_warn("lcomm length (%d.) <0! Ignored.", temp);
ignore_rest_of_line();
return;
}
*p = 0;
symbolP = symbol_find_or_make(name);
S_SET_VALUE(symbolP, segment_info[SEG_E2].scnhdr.s_size);
S_SET_SEGMENT(symbolP, SEG_E2);
segment_info[SEG_E2].scnhdr.s_size += temp;
S_SET_STORAGE_CLASS(symbolP, C_STAT);
demand_empty_rest_of_line();
}

View File

@ -146,7 +146,7 @@ typedef struct
#define C_DEBUG_SECTION N_DEBUG
#define C_NTV_SECTION N_TV
#define C_PTV_SECTION P_TV
#define C_REGISTER_SECTION 4
#define C_REGISTER_SECTION 20
/*
* Macros to extract information from a symbol table entry.

View File

@ -770,27 +770,6 @@ void md_apply_fix(fixP, val)
fixP->fx_addnumber = val; /* Remember value for emit_reloc */
if (fixP->fx_r_type == NO_RELOC) {
as_fatal("failed sanity check."); /* FIXME-SOON, if this is never used, remove */
switch (fixP->fx_size) {
case 1:
*buf = val;
break;
case 2:
*buf++ = (val>>8);
*buf = val;
break;
case 4:
*buf++ = (val>>24);
*buf++ = (val>>16);
*buf++ = (val>>8);
*buf = val;
break;
default:
as_fatal("failed sanity check.");
}
return;
}
know(fixP->fx_size == 4);
know(fixP->fx_r_type < NO_RELOC);

View File

@ -27,5 +27,13 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#define tc_coff_symbol_emit_hook(a) ; /* not used */
#define AOUT_MACHTYPE 101
#define TC_COFF_FIX2RTYPE(fix_ptr) tc_coff_fix2rtype(fix_ptr)
#define BFD_ARCH bfd_arch_a29k
#define COFF_MAGIC SIPFBOMAGIC
/* Should the reloc be output ?
on the 29k, this is true only if there is a symbol attatched.
on the h8, this is allways true, since no fixup is done
*/
#define TC_COUNT_RELOC(x) (x->fx_addsy)
/* end of tc-a29k.h */