Made multiple sections with subsections work.

This commit is contained in:
Steve Chamberlain
1991-11-28 21:22:41 +00:00
parent 67c29f758d
commit f714e310f4

View File

@ -1,5 +1,4 @@
/* coff object file format with bfd
/* coff object file format
Copyright (C) 1989, 1990, 1991 Free Software Foundation, Inc. Copyright (C) 1989, 1990, 1991 Free Software Foundation, Inc.
This file is part of GAS. This file is part of GAS.
@ -23,15 +22,22 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
How does this releate to the rest of GAS ? How does this releate to the rest of GAS ?
Well, all the other files in gas are more or less a black box. It Well, all the other files in gas are more or less a black box. It
takes care of openning files, parsing command lines, stripping blanks takes care of opening files, parsing command lines, stripping blanks
etc etc. This module gets a chance to register what it wants to do by etc etc. This module gets a chance to register what it wants to do by
saying that it is interested in various pseduo ops. The other big saying that it is interested in various pseduo ops. The other big
change is write_object_file. This runs through all the data change is write_object_file. This runs through all the data
structures that gas builds, and outputs the file in the format of our structures that gas builds, and outputs the file in the format of our
choice. choice.
Hacked for BFDness by steve chamberlain Hacked for BFDness by steve chamberlain
Note that this is the first implementation using BFD for coff, and
this is a pretty special case too - it only works at the moment for
the H8. Which *can't* do any relaxing during assembly - because the
linker has to have all the reloc info for fancy stuff later on.
When another machine is supported, relaxing will have to go back in.
sac@cygnus.com sac@cygnus.com
*/ */
@ -42,8 +48,6 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
/* This vector is used to turn an internal segment into a section # /* This vector is used to turn an internal segment into a section #
suitable for insertion into a coff symbol table suitable for insertion into a coff symbol table
*/ */
@ -72,6 +76,7 @@ const short seg_N_TYPE[] = { /* in: segT out: N_TYPE bits */
C_REGISTER_SECTION, /* SEG_REGISTER */ C_REGISTER_SECTION, /* SEG_REGISTER */
}; };
int function_lineoff = -1; /* Offset in line#s where the last function int function_lineoff = -1; /* Offset in line#s where the last function
started (the odd entry for line #0) */ started (the odd entry for line #0) */
@ -241,7 +246,7 @@ static unsigned int DEFUN(size_section,(abfd, idx),
{ {
asection *sec; asection *sec;
unsigned int size = 0; unsigned int size = 0;
fragS *frag = segment_info[idx].frag_root; fragS *frag = segment_info[idx].frchainP->frch_root;
while (frag) { while (frag) {
if (frag->fr_address != size) { if (frag->fr_address != size) {
printf("Out of step\n"); printf("Out of step\n");
@ -366,7 +371,7 @@ static void DEFUN(fill_section,(abfd, filehdr, file_cursor),
struct internal_scnhdr *s = &( segment_info[i].scnhdr); struct internal_scnhdr *s = &( segment_info[i].scnhdr);
if (s->s_name[0]) { if (s->s_name[0]) {
fragS *frag = segment_info[i].frag_root; fragS *frag = segment_info[i].frchainP->frch_root;
char *buffer = alloca(s->s_size); char *buffer = alloca(s->s_size);
s->s_scnptr = *file_cursor; s->s_scnptr = *file_cursor;
s->s_paddr = paddr; s->s_paddr = paddr;
@ -1400,157 +1405,6 @@ char *where;
} }
#if 0
void obj_pre_write_hook(headers)
object_headers *headers;
{
register fixS *fixP;
/* FIXME-SOMEDAY this should be done at
fixup_segment time but I'm going to wait until I
do multiple segments. xoxorich. */
unsigned int i;
unsigned int reloc_size = 0;
for (i =0; i < N_SEG; i++)
{
seg_info_type *s = &(SEG_INFO_FROM_SEG_NUMBER(i));
if (s->real_section)
{
for (fixP = s->fix_root; fixP; fixP = fixP->fx_next) {
if (fixP->fx_addsy) {
s->relocation_number++;
}
}
}
headers->relocation_size += s->relocation_number * RELSZ;
}
/* filehdr */
H_SET_FILE_MAGIC_NUMBER(headers, FILE_HEADER_MAGIC);
H_SET_NUMBER_OF_SECTIONS(headers, 3); /* text+data+bss */
#ifndef OBJ_COFF_OMIT_TIMESTAMP
H_SET_TIME_STAMP(headers, (long)time((long*)0));
#else /* OBJ_COFF_OMIT_TIMESTAMP */
H_SET_TIME_STAMP(headers, 0);
#endif /* OBJ_COFF_OMIT_TIMESTAMP */
H_SET_SYMBOL_TABLE_POINTER(headers, H_GET_SYMBOL_TABLE_FILE_OFFSET(headers));
#if 0
printf("FILHSZ %x\n", FILHSZ);
printf("OBJ_COFF_AOUTHDRSZ %x\n", OBJ_COFF_AOUTHDRSZ);
printf("section headers %x\n", H_GET_NUMBER_OF_SECTIONS(headers) * SCNHSZ);
printf("get text size %x\n", H_GET_TEXT_SIZE(headers));
printf("get data size %x\n", H_GET_DATA_SIZE(headers));
printf("get relocation size %x\n", H_GET_RELOCATION_SIZE(headers));
printf("get lineno size %x\n", H_GET_LINENO_SIZE(headers));
#endif
/* symbol table size allready set */
H_SET_SIZEOF_OPTIONAL_HEADER(headers, OBJ_COFF_AOUTHDRSZ);
H_SET_FLAGS(headers, (text_lineno_number == 0 ? F_LNNO : 0)
| headers->relocation_size ? F_RELFLG : 0
| BYTE_ORDERING);
/* aouthdr */
/* magic number allready set */
H_SET_VERSION_STAMP(headers, 0);
} /* obj_pre_write_hook() */
#endif
/* 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() */
#ifdef DEBUG
/* for debugging */
char *s_get_name(s)
symbolS *s;
{
return((s == NULL) ? "(NULL)" : S_GET_NAME(s));
} /* s_get_name() */
void symbol_dump() {
symbolS *symbolP;
for (symbolP = symbol_rootP; symbolP; symbolP = symbol_next(symbolP)) {
printf("%3ld: 0x%lx \"%s\" type = %ld, class = %d, segment = %d\n",
symbolP->sy_number,
(unsigned long) symbolP,
S_GET_NAME(symbolP),
(long) S_GET_DATA_TYPE(symbolP),
S_GET_STORAGE_CLASS(symbolP),
(int) S_GET_SEGMENT(symbolP));
} /* traverse symbols */
return;
} /* symbol_dump() */
#endif /* DEBUG */
static void static void
DEFUN(do_linenos_for,(abfd, file_cursor), DEFUN(do_linenos_for,(abfd, file_cursor),
@ -1605,7 +1459,29 @@ DEFUN(do_linenos_for,(abfd, file_cursor),
*/ */
/* end of obj-coff.c */ /* end of obj-coff.c */
/* Now we run through the list of frag chains in a segment and
make all the subsegment frags appear at the end of the
list, as if the seg 0 was extra long */
static void DEFUN_VOID(remove_subsegs)
{
unsigned int i;
for (i = SEG_E0; i < SEG_UNKNOWN; i++)
{
frchainS *head = segment_info[i].frchainP;
fragS dummy;
fragS * prev_frag = &dummy;
while (head && head->frch_seg == i)
{
prev_frag->fr_next = head->frch_root;
prev_frag = head->frch_last;
head = head->frch_next;
}
prev_frag->fr_next = 0;
}
}
extern void DEFUN_VOID(write_object_file) extern void DEFUN_VOID(write_object_file)
@ -1639,41 +1515,20 @@ unsigned long file_cursor;
frag */ frag */
subseg_new(frchain_ptr->frch_seg, frchain_ptr->frch_subseg); subseg_new(frchain_ptr->frch_seg, frchain_ptr->frch_subseg);
#define SUB_SEGMENT_ALIGN 2 #define SUB_SEGMENT_ALIGN 1
frag_align(SUB_SEGMENT_ALIGN,0); frag_align(SUB_SEGMENT_ALIGN,0);
frag_wane(frag_now); frag_wane(frag_now);
frag_now->fr_fix = 0; frag_now->fr_fix = 0;
know( frag_now->fr_next == NULL ); know( frag_now->fr_next == NULL );
} }
/* Now build one big frag chain for each segment, linked through
fr_next. */
for (i = SEG_E0; i < SEG_UNKNOWN; i++)
{
fragS ** prev_frag_ptr_ptr ; remove_subsegs();
struct frchain *next_frchain_ptr;
/* struct frag **head_ptr = segment_info[i].frag_root;*/
segment_info[i].frag_root = segment_info[i].frchainP->frch_root;
#if 0
/* Im not sure what this is for */
for (frchain_ptr = segment_info[i].frchainP->frch_root;
frchain_ptr != (struct frchain *)NULL;
frchain_ptr = frchain_ptr->frch_next)
{
*head_ptr = frchain_ptr;
head_ptr = &frchain_ptr->next;
}
#endif
}
#if 1 #if 1
for (i = SEG_E0; i < SEG_UNKNOWN; i++) for (i = SEG_E0; i < SEG_UNKNOWN; i++)
{ {
relax_segment(segment_info[i].frag_root, i); relax_segment(segment_info[i].frchainP->frch_root, i);
} }
for (i = SEG_E0; i < SEG_UNKNOWN; i++) for (i = SEG_E0; i < SEG_UNKNOWN; i++)
@ -1748,9 +1603,10 @@ unsigned long file_cursor;
} }
static void DEFUN(change_to_section,(name, len), static void DEFUN(change_to_section,(name, len, exp),
char *name AND char *name AND
unsigned int len) unsigned int len AND
unsigned int exp)
{ {
unsigned int i; unsigned int i;
/* Find out if we've already got a section of this name etc */ /* Find out if we've already got a section of this name etc */
@ -1758,14 +1614,14 @@ static void DEFUN(change_to_section,(name, len),
{ {
if (strncmp(segment_info[i].scnhdr.s_name, name, len) == 0) if (strncmp(segment_info[i].scnhdr.s_name, name, len) == 0)
{ {
subseg_new(i, 0); subseg_new(i, exp);
return; return;
} }
} }
/* No section, add one */ /* No section, add one */
strncpy(segment_info[i].scnhdr.s_name, name, 8); strncpy(segment_info[i].scnhdr.s_name, name, 8);
subseg_new(i, 0); subseg_new(i, exp);
} }
static void static void
@ -1774,31 +1630,47 @@ DEFUN_VOID(obj_coff_section)
/* Strip out the section name */ /* Strip out the section name */
char *section_name ; char *section_name ;
char *section_name_end; char *section_name_end;
char c;
unsigned int len; unsigned int len;
unsigned int exp;
section_name = input_line_pointer; section_name = input_line_pointer;
get_symbol_end(); c = get_symbol_end();
section_name_end = input_line_pointer; section_name_end = input_line_pointer;
input_line_pointer++;
len = section_name_end - section_name ; len = section_name_end - section_name ;
input_line_pointer++;
SKIP_WHITESPACE();
if (c == ',')
{
exp = get_absolute_expression();
}
else if ( *input_line_pointer == ',')
{
input_line_pointer++;
exp = get_absolute_expression();
}
else
{
exp = 0;
}
change_to_section(section_name, len); change_to_section(section_name, len,exp);
} }
static void obj_coff_text() static void obj_coff_text()
{ {
change_to_section(".text",5); change_to_section(".text",5, get_absolute_expression());
} }
static void obj_coff_data() static void obj_coff_data()
{ {
change_to_section(".data",5); change_to_section(".data",5, get_absolute_expression());
} }
void c_symbol_merge(debug, normal) void c_symbol_merge(debug, normal)
@ -2153,8 +2025,6 @@ void obj_coff_lcomm(void)
symbolS *symbolP; symbolS *symbolP;
name = input_line_pointer; name = input_line_pointer;
c = get_symbol_end(); c = get_symbol_end();
p = input_line_pointer; p = input_line_pointer;
*p = c; *p = c;