mirror of
https://github.com/espressif/binutils-gdb.git
synced 2025-06-25 13:27:26 +08:00
Made multiple sections with subsections work.
This commit is contained in:
@ -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;
|
||||||
|
Reference in New Issue
Block a user