Changes to support stabs-in-coff

This commit is contained in:
Stan Shebs 1993-09-07 17:39:56 +00:00
parent f3e8b15d8e
commit 4064305ec0
6 changed files with 536 additions and 95 deletions

View File

@ -1,3 +1,14 @@
Tue Sep 7 10:22:52 1993 Stan Shebs (shebs@rtl.cygnus.com)
* read.c: (s_stab, s_xstab, s_desc): New functions to parse
various stab-related directives.
* read.h: (s_stab, s_xstab, s_desc): New function prototypes.
* write.c: (merge_data_into_text): Fix ifdef tangle.
* config/obj-coffbfd.c (current_stab_symbol): Fake symbol
for stab reader to use.
* config/obj-coffbfdh.h (obj_symbol_type): Added fields for
stab reader, macros to access.
Fri Sep 3 16:44:03 1993 Ken Raeburn (raeburn@cambridge.cygnus.com)
* config/obj-elf.h (elf_symbol): Fixed name of elf_symbol_type.

View File

@ -31,7 +31,7 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
Hacked for BFDness by steve chamberlain
This object module now supports the Hitachi H8/{3|5}00 and the AMD 29k
This object module now supports everything but the i960 and i860.
sac@cygnus.com
*/
@ -80,6 +80,12 @@ const short seg_N_TYPE[] =
int function_lineoff = -1; /* Offset in line#s where the last function
started (the odd entry for line #0) */
/* This is used along with macros in the .h file to fake the .stabX
directive reader into thinking it's working on a real symbol, when
it's actually only a temporary that will get converted into a
stab-section symbol later. */
symbolS current_stab_symbol;
static symbolS *last_line_symbol;
@ -149,7 +155,6 @@ void EXFUN (obj_coff_section, (void));
static void EXFUN (tag_init, (void));
static void EXFUN (tag_insert, (char *name, symbolS * symbolP));
static struct hash_control *tag_hash;
static symbolS *def_symbol_in_progress = NULL;

View File

@ -122,10 +122,28 @@ typedef struct
union internal_auxent ost_auxent[OBJ_COFF_MAX_AUXENTRIES]; /* Auxiliary entry. */
unsigned int ost_flags; /* obj_coff internal use only flags */
/* For stabs-in-coff. */
unsigned long n_strx; /* index into string table of name */
unsigned char n_type; /* type of symbol */
unsigned char n_other; /* misc info (usually empty) */
unsigned short n_desc; /* description field */
bfd_vma n_value; /* value of symbol */
}
obj_symbol_type;
#define S_SET_OFFSET_2(S,V) ((S)->sy_symbol.n_strx = (V))
#define S_SET_OTHER(S,V) ((S)->sy_symbol.n_other = (V))
#define S_SET_TYPE(S,T) ((S)->sy_symbol.n_type = (T))
#define S_SET_DESC(S,D) ((S)->sy_symbol.n_desc = (D))
#define S_GET_OFFSET_2(S) ((S)->sy_symbol.n_strx)
#define S_GET_OTHER(S) ((S)->sy_symbol.n_other)
#define S_GET_TYPE(S) ((S)->sy_symbol.n_type)
#define S_GET_DESC(S) ((S)->sy_symbol.n_desc)
#ifndef DO_NOT_STRIP
#define DO_NOT_STRIP 0
#define DO_STRIP 1
@ -530,4 +548,12 @@ extern SCNHDR text_section_header;
? (S_SET_SEGMENT (symp, S_GET_SEGMENT (symp->sy_value.X_add_symbol)), 0) \
: 0)
#define SEPARATE_STAB_SECTIONS
#define MAKE_STAB_SYMBOL(SYM, STR, SEC) \
{ extern symbolS current_stab_symbol; \
(SYM) = &current_stab_symbol; \
(SYM)->sy_symbol.n_strx = get_stab_string_offset(STR, SEC); \
}
/* end of obj-coffbfd.h */

View File

@ -40,13 +40,15 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#include <ctype.h>
#include "as.h"
#ifdef BFD_ASSEMBLER
#include "subsegs.h"
#endif
#include "obstack.h"
#include "listing.h"
/* We need this, despite the apparent object format dependency, since
it defines stab types, which all object formats can use now. */
#include "aout/stab_gnu.h"
#ifndef TC_START_LABEL
#define TC_START_LABEL(x,y) (x==':')
@ -203,6 +205,7 @@ static const pseudo_typeS potable[] =
{"byte", cons, 1},
{"comm", s_comm, 0},
{"data", s_data, 0},
{"desc", s_desc, 0},
/* dim */
{"double", float_cons, 'd'},
/* dsect */
@ -250,6 +253,9 @@ static const pseudo_typeS potable[] =
{"single", float_cons, 'f'},
/* size */
{"space", s_space, 0},
{"stabd", s_stab, 'd'},
{"stabn", s_stab, 'n'},
{"stabs", s_stab, 's'},
{"string", stringer, 1},
/* tag */
{"text", s_text, 0},
@ -257,6 +263,7 @@ static const pseudo_typeS potable[] =
/* type */
/* use */
/* val */
{"xstabs", s_xstab, 's'},
{"word", cons, 2},
{NULL} /* end sentinel */
};
@ -435,7 +442,12 @@ read_a_source_file (name)
}
else if (c == '=' || input_line_pointer[1] == '=')
else if (c == '='
|| (input_line_pointer[1] == '='
#ifdef TC_EQUAL_IN_INSN
&& ! TC_EQUAL_IN_INSN (c, input_line_pointer)
#endif
))
{
equals (s);
demand_empty_rest_of_line ();
@ -508,7 +520,11 @@ read_a_source_file (name)
/* WARNING: c has char, which may be end-of-line. */
/* Also: input_line_pointer->`\0` where c was. */
*input_line_pointer = c;
while (!is_end_of_line[*input_line_pointer])
while (!is_end_of_line[*input_line_pointer]
#ifdef TC_EOL_IN_INSN
|| TC_EOL_IN_INSN (input_line_pointer)
#endif
)
{
input_line_pointer++;
}
@ -837,8 +853,8 @@ s_comm ()
S_SET_EXTERNAL (symbolP);
}
#ifdef OBJ_VMS
if ( (!temp) || !flagseen['1'])
S_GET_OTHER(symbolP) = const_flag;
if ( (!temp) || !flagseen['1'])
S_GET_OTHER(symbolP) = const_flag;
#endif /* not OBJ_VMS */
know (symbolP->sy_frag == &zero_address_frag);
demand_empty_rest_of_line ();
@ -1701,11 +1717,15 @@ emit_expr (exp, nbytes)
defined, and otherwise uses 0. */
#ifdef BFD_ASSEMBLER
#ifdef TC_CONS_FIX_NEW
TC_CONS_FIX_NEW (frag_now, p - frag_now->fr_literal, nbytes, exp);
#else
fix_new_exp (frag_now, p - frag_now->fr_literal, nbytes, exp, 0,
/* @@ Should look at CPU word size. */
nbytes == 2 ? BFD_RELOC_16
: nbytes == 8 ? BFD_RELOC_64
: BFD_RELOC_32);
#endif
#else
#ifdef TC_CONS_FIX_NEW
TC_CONS_FIX_NEW (frag_now, p - frag_now->fr_literal, nbytes, exp);
@ -2632,4 +2652,428 @@ s_ignore (arg)
return;
} /* s_ignore() */
/*
* Handle .stabX directives, which used to be open-coded.
* So much creeping featurism overloaded the semantics that we decided
* to put all .stabX thinking in one place. Here.
*
* We try to make any .stabX directive legal. Other people's AS will often
* do assembly-time consistency checks: eg assigning meaning to n_type bits
* and "protecting" you from setting them to certain values. (They also zero
* certain bits before emitting symbols. Tut tut.)
*
* If an expression is not absolute we either gripe or use the relocation
* information. Other people's assemblers silently forget information they
* don't need and invent information they need that you didn't supply.
*/
void
change_to_section (name, len, exp)
char *name;
unsigned int len;
unsigned int exp;
{
#ifndef BFD_ASSEMBLER
unsigned int i;
extern segment_info_type segment_info[];
/* Find out if we've already got a section of this name etc */
for (i = SEG_E0; i < SEG_E9 && segment_info[i].scnhdr.s_name[0]; i++)
{
if (strncmp (segment_info[i].scnhdr.s_name, name, len) == 0)
{
subseg_new (i, exp);
return;
}
}
/* No section, add one */
strncpy (segment_info[i].scnhdr.s_name, name, 8);
segment_info[i].scnhdr.s_flags = 0 /* STYP_NOLOAD */;
subseg_new (i, exp);
#endif
}
/*
* Build a string dictionary entry for a .stabX symbol.
* The symbol is added to the .<secname>str section.
*/
static unsigned int
get_stab_string_offset (string, secname)
char *string, *secname;
{
segT save_seg;
segT seg;
subsegT save_subseg;
unsigned int length;
unsigned int old_gdb_string_index;
char *clengthP;
int i;
char c;
/* @@FIXME -- there should be no static data here!
This also has the effect of making all stab string tables large enough
to contain all the contents written to any of them. This only matters
with the Solaris native compiler for the moment, but it should be fixed
anyways. */
static unsigned int gdb_string_index = 0;
old_gdb_string_index = 0;
length = strlen (string);
clengthP = (char *) &length;
if (length > 0)
{ /* Ordinary case. */
save_seg = now_seg;
save_subseg = now_subseg;
/* Create the stabstr sections, if they are not already created. */
{
char *newsecname = xmalloc (strlen (secname) + 4);
strcpy (newsecname, secname);
strcat (newsecname, "str");
#ifdef BFD_ASSEMBLER
seg = bfd_get_section_by_name (stdoutput, newsecname);
if (seg == 0)
{
seg = bfd_make_section_old_way (stdoutput, newsecname);
bfd_set_section_flags (stdoutput, seg, SEC_READONLY | SEC_ALLOC);
}
#else
change_to_section(newsecname, strlen(newsecname), 0);
#endif
/* free (newsecname);*/
}
#ifdef BFD_ASSEMBLER
subseg_new ((char *) seg->name, save_subseg);
#else
/* subseg_new (seg, save_subseg); */
#endif
old_gdb_string_index = gdb_string_index;
i = 0;
while ((c = *string++))
{
i++;
gdb_string_index++;
FRAG_APPEND_1_CHAR (c);
}
{
FRAG_APPEND_1_CHAR ((char) 0);
i++;
gdb_string_index++;
}
while (i % 4 != 0)
{
FRAG_APPEND_1_CHAR ((char) 0);
i++;
gdb_string_index++;
}
#ifdef BFD_ASSEMBLER
subseg_new ((char *) save_seg->name, save_subseg);
#else
/* subseg_new (save_seg, save_subseg); */
#endif
}
return old_gdb_string_index;
}
/* This can handle different kinds of stabs (s,n,d) and different
kinds of stab sections. */
static void
s_stab_generic (what, secname)
int what;
char *secname;
{
extern int listing;
symbolS *symbol;
char *string;
int saved_type = 0;
int length;
int goof = 0;
int seg_is_new = 0;
long longint;
segT saved_seg = now_seg;
segT seg;
subsegT saved_subseg = now_subseg;
subsegT subseg;
int offset;
int valu;
char *toP;
valu = ((char *) obstack_next_free (&frags)) - frag_now->fr_literal;
#ifdef SEPARATE_STAB_SECTIONS
#ifdef BFD_ASSEMBLER
seg = bfd_get_section_by_name (stdoutput, secname);
if (seg == 0)
{
seg = subseg_new (secname, 0);
bfd_set_section_flags (stdoutput, seg,
SEC_READONLY | SEC_ALLOC | SEC_RELOC);
subseg_set (saved_seg, subseg);
seg_is_new = 1;
}
#else
change_to_section (secname, strlen(secname), 0);
#endif
#endif /* SEPARATE_STAB_SECTIONS */
/*
* Enter with input_line_pointer pointing past .stabX and any following
* whitespace.
*/
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;
}
}
else
string = "";
/*
* Input_line_pointer->after ','. String->symbol name.
*/
if (!goof)
{
#ifdef MAKE_STAB_SYMBOL
MAKE_STAB_SYMBOL(symbol, string, secname);
#else
symbol = symbol_new (string, undefined_section, 0, (struct frag *) 0);
#endif
/* Make sure that the rest of this is going to work. */
if (symbol == NULL)
as_fatal ("no stab symbol created");
switch (what)
{
case 'd':
S_SET_NAME (symbol, NULL); /* .stabd feature. */
#ifdef STAB_SYMBOL_SET_VALUE
STAB_SYMBOL_SET_VALUE (symbol, valu);
#else
S_SET_VALUE (symbol, valu);
#endif
#if STAB_SYMBOL_SET_SEGMENT
#else
S_SET_SEGMENT (symbol, now_seg);
#endif
symbol->sy_frag = frag_now;
break;
case 'n':
symbol->sy_frag = &zero_address_frag;
break;
case 's':
symbol->sy_frag = &zero_address_frag;
break;
default:
BAD_CASE (what);
break;
}
if (get_absolute_expression_and_terminator (&longint) == ',')
{
saved_type = longint;
S_SET_TYPE (symbol, saved_type);
}
else
{
as_bad ("I want a comma after the n_type expression");
goof = 1;
input_line_pointer--; /* Backup over a non-',' char. */
}
}
if (!goof)
{
if (get_absolute_expression_and_terminator (&longint) == ',')
S_SET_OTHER (symbol, longint);
else
{
as_bad ("I want a comma after the n_other expression");
goof = 1;
input_line_pointer--; /* Backup over a non-',' char. */
}
}
if (!goof)
{
S_SET_DESC (symbol, 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++;
}
}
}
/* Line is messed up - ignore it and get out of here. */
if (goof)
{
ignore_rest_of_line ();
subseg_new (saved_seg, saved_subseg);
return;
}
#ifdef BFD_ASSEMBLER
subseg_new ((char *) seg->name, subseg);
#endif
#if 0 /* needed for elf only? */
if (seg_is_new)
/* allocate and discard -- filled in later */
(void) frag_more (12);
#endif
#ifdef SEPARATE_STAB_SECTIONS
change_to_section(secname, strlen(secname), 0);
toP = frag_more (8);
/* the string index portion of the stab */
md_number_to_chars (toP, (valueT) S_GET_OFFSET_2(symbol), 4);
md_number_to_chars (toP + 4, (valueT) S_GET_TYPE(symbol), 1);
md_number_to_chars (toP + 5, (valueT) S_GET_OTHER(symbol), 1);
md_number_to_chars (toP + 6, (valueT) S_GET_DESC(symbol), 2);
#endif
#ifdef SEPARATE_STAB_SECTIONS
if (what == 's' || what == 'n')
{
cons (4);
input_line_pointer--;
}
else
{
char *p = frag_more (4);
md_number_to_chars (p, 0, 4);
}
#ifdef BFD_ASSEMBLER
subseg_new ((char *) saved_seg->name, subseg);
#else
/* subseg_new (saved_seg, subseg); */
#endif
#else
if (what == 's' || what == 'n')
{
pseudo_set (symbol);
S_SET_TYPE (symbol, saved_type);
}
#endif
#if 0 /* for elf only? */
if (what == 's' && S_GET_TYPE (symbol) == N_SO)
{
fragS *fragp = seg_info (seg)->frchainP->frch_root;
while (fragp
&& fragp->fr_address + fragp->fr_fix < 12)
fragp = fragp->fr_next;
assert (fragp != 0);
assert (fragp->fr_type == rs_fill);
assert (fragp->fr_address == 0 && fragp->fr_fix >= 12);
md_number_to_chars (fragp->fr_literal, (valueT) symbol->sy_name_offset,
4);
}
#endif
#ifndef NO_LISTING
if (listing)
switch (S_GET_TYPE (symbol))
{
case N_SLINE:
listing_source_line (S_GET_DESC (symbol));
break;
case N_SO:
case N_SOL:
listing_source_file (string);
break;
}
#endif /* !NO_LISTING */
#ifdef SEPARATE_STAB_SECTIONS
subseg_new (saved_seg, saved_subseg);
#endif
demand_empty_rest_of_line ();
}
/* Regular stab directive. */
void
s_stab (what)
int what;
{
s_stab_generic (what, ".stab");
}
/* "Extended stabs", used in Solaris only now. */
void
s_xstab (what)
int what;
{
int length;
char *secname;
secname = demand_copy_C_string (&length);
SKIP_WHITESPACE ();
if (*input_line_pointer == ',')
input_line_pointer++;
else
{
as_bad ("comma missing in .xstabs");
ignore_rest_of_line ();
return;
}
s_stab_generic (what, secname);
}
/* Frob invented at RMS' request. Set the n_desc of a symbol. */
void
s_desc ()
{
char *name;
char c;
char *p;
symbolS *symbolP;
int temp;
name = input_line_pointer;
c = get_symbol_end ();
p = input_line_pointer;
*p = c;
SKIP_WHITESPACE ();
if (*input_line_pointer != ',')
{
*p = 0;
as_bad ("Expected comma after name \"%s\"", name);
*p = c;
ignore_rest_of_line ();
}
else
{
input_line_pointer++;
temp = get_absolute_expression ();
*p = 0;
symbolP = symbol_find_or_make (name);
*p = c;
S_SET_DESC (symbolP, temp);
}
demand_empty_rest_of_line ();
} /* s_desc() */
/* end of read.c */

View File

@ -53,91 +53,46 @@ extern const char comment_chars[];
extern const char line_comment_chars[];
extern const char line_separator_chars[];
#if __STDC__ == 1
char *demand_copy_C_string (int *len_pointer);
char get_absolute_expression_and_terminator (long *val_pointer);
long get_absolute_expression (void);
void add_include_dir (char *path);
void big_cons (int nbytes);
void cons (unsigned int nbytes);
void demand_empty_rest_of_line (void);
void equals (char *sym_name);
void float_cons (int float_type);
void ignore_rest_of_line (void);
void pseudo_set (symbolS * symbolP);
void read_a_source_file (char *name);
void read_begin (void);
void s_abort (void);
void s_align_bytes (int arg);
void s_align_ptwo (void);
void s_app_file (void);
/* void s_bss(void); -- unneeded; always static when used */
void s_comm (void);
void s_data (void);
void s_else (int arg);
void s_end (int arg);
void s_endif (int arg);
void s_fill (void);
void s_globl (void);
void s_if (int arg);
void s_ifdef (int arg);
void s_ifeqs (int arg);
void s_ignore (int arg);
void s_include (int arg);
void s_lcomm (int needs_align);
void s_lsym (void);
void s_org (void);
void s_set (void);
void s_space (int mult);
void s_text (void);
#else /* not __STDC__ */
char *demand_copy_C_string ();
char get_absolute_expression_and_terminator ();
long get_absolute_expression ();
void add_include_dir ();
void big_cons ();
void cons ();
void demand_empty_rest_of_line ();
void equals ();
void float_cons ();
void ignore_rest_of_line ();
void pseudo_set ();
void read_a_source_file ();
void read_begin ();
void s_abort ();
void s_align_bytes ();
void s_align_ptwo ();
void s_app_file ();
/* void s_bss(); -- unneeded; always static when used */
void s_comm ();
void s_data ();
void s_else ();
void s_end ();
void s_endif ();
void s_fill ();
void s_globl ();
void s_if ();
void s_ifdef ();
void s_ifeqs ();
void s_ignore ();
void s_include ();
void s_lcomm ();
void s_lsym ();
void s_org ();
void s_set ();
void s_space ();
void s_text ();
#endif /* not __STDC__ */
/*
* Local Variables:
* comment-column: 0
* fill-column: 131
* End:
*/
char *demand_copy_C_string PARAMS ((int *len_pointer));
char get_absolute_expression_and_terminator PARAMS ((long *val_pointer));
long get_absolute_expression PARAMS ((void));
void add_include_dir PARAMS ((char *path));
void big_cons PARAMS ((int nbytes));
void cons PARAMS ((unsigned int nbytes));
void demand_empty_rest_of_line PARAMS ((void));
void emit_expr PARAMS ((expressionS *exp, unsigned int nbytes));
void equals PARAMS ((char *sym_name));
void float_cons PARAMS ((int float_type));
void ignore_rest_of_line PARAMS ((void));
void pseudo_set PARAMS ((symbolS * symbolP));
void read_a_source_file PARAMS ((char *name));
void read_begin PARAMS ((void));
void s_abort PARAMS ((void));
void s_align_bytes PARAMS ((int arg));
void s_align_ptwo PARAMS ((void));
void s_app_file PARAMS ((int));
void s_app_line PARAMS ((void));
void s_comm PARAMS ((void));
void s_data PARAMS ((void));
void s_desc PARAMS ((void));
void s_else PARAMS ((int arg));
void s_end PARAMS ((int arg));
void s_endif PARAMS ((int arg));
void s_fill PARAMS ((void));
void s_globl PARAMS ((void));
void s_if PARAMS ((int arg));
void s_ifdef PARAMS ((int arg));
void s_ifeqs PARAMS ((int arg));
void s_ignore PARAMS ((int arg));
void s_include PARAMS ((int arg));
void s_lcomm PARAMS ((int needs_align));
void s_lsym PARAMS ((void));
void s_org PARAMS ((void));
void s_set PARAMS ((void));
void s_space PARAMS ((int mult));
void s_stab PARAMS ((int what));
void s_text PARAMS ((void));
void stringer PARAMS ((int append_zero));
void s_xstab PARAMS ((int what));
/* end of read.h */

View File

@ -750,7 +750,7 @@ write_contents (abfd, sec, xxx)
static void
merge_data_into_text ()
{
#ifdef BFD_ASSEMBLER
#if defined(BFD_ASSEMBLER) || defined(MANY_SEGMENTS)
seg_info (text_section)->frchainP->frch_last->fr_next =
seg_info (data_section)->frchainP->frch_root;
seg_info (text_section)->frchainP->frch_last =