mirror of
https://sourceware.org/git/binutils-gdb.git
synced 2024-12-03 23:34:02 +08:00
Extend pdp11-aout symbol table format and code for .stab symbols.
* bfd/pdp11.c (pdp11_external_nlist): Repurposed e_unused to e_desc. (N_STAB, is_stab): Needed new function is_stab to disambiguate normal vs. .stab symbol table type values, replacing N_STAB mask. (translate_from_native_sym_flags): Determine correct section for different .stab types. (translate_to_native_sym_flags): Leave .stab types intact. (translate_symbol_table): Error if symbol indicates overlay; store desc field from .stab symbols. (write_syms): Output desc field with symbol. (aout_link_check_ar_symbols): Skip .stab symbols. (aout_link_add_symbols): Correctly distinguish .stab symbols. (aout_link_write_other_symbol): Write 0 for desk and ovly fields. (aout_link_write_symbols): Write 0 for desk and ovly fields; correctly distinguish .stab symbols and select calculate their section and value; and copy desc and ovly fields from input symbol to output symbol.
This commit is contained in:
parent
470e738f6d
commit
a975c88e65
@ -1,3 +1,25 @@
|
||||
2020-06-04 Stephen Casner <casner@acm.org>
|
||||
|
||||
Extend pdp11-aout symbol table format to accommodate .stab
|
||||
symbols and implement correct handling of them.
|
||||
|
||||
* pdp11.c (pdp11_external_nlist): Repurposed e_unused to e_desc.
|
||||
(N_STAB, is_stab): Needed new function is_stab to disambiguate
|
||||
normal vs. .stab symbol table type values, replacing N_STAB mask.
|
||||
(translate_from_native_sym_flags): Determine correct section for
|
||||
different .stab types.
|
||||
(translate_to_native_sym_flags): Leave .stab types intact.
|
||||
(translate_symbol_table): Error if symbol indicates overlay;
|
||||
store desc field from .stab symbols.
|
||||
(write_syms): Output desc field with symbol.
|
||||
(aout_link_check_ar_symbols): Skip .stab symbols.
|
||||
(aout_link_add_symbols): Correctly distinguish .stab symbols.
|
||||
(aout_link_write_other_symbol): Write 0 for desk and ovly fields.
|
||||
(aout_link_write_symbols): Write 0 for desk and ovly fields;
|
||||
correctly distinguish .stab symbols and select calculate their
|
||||
section and value; and copy desc and ovly fields from input symbol
|
||||
to output symbol.
|
||||
|
||||
2020-06-04 Stephen Casner <casner@acm.org>
|
||||
|
||||
* aoutx.h (translate_symbol_table): Comment had external and
|
||||
|
155
bfd/pdp11.c
155
bfd/pdp11.c
@ -22,7 +22,9 @@
|
||||
/* BFD backend for PDP-11, running 2.11BSD in particular.
|
||||
|
||||
This file was hacked up by looking hard at the existing vaxnetbsd
|
||||
back end and the header files in 2.11BSD.
|
||||
back end and the header files in 2.11BSD. The symbol table format
|
||||
of 2.11BSD has been extended to accommodate .stab symbols. See
|
||||
struct pdp11_external_nlist below for details.
|
||||
|
||||
TODO
|
||||
* support for V7 file formats
|
||||
@ -101,10 +103,23 @@ struct pdp11_external_exec
|
||||
|
||||
#define A_FLAG_RELOC_STRIPPED 0x0001
|
||||
|
||||
/* The following struct defines the format of an entry in the object file
|
||||
symbol table. In the original 2.11BSD struct the index into the string
|
||||
table is stored as a long, but the PDP11 C convention for storing a long in
|
||||
memory placed the most significant word first even though the bytes within a
|
||||
word are stored least significant first. So here the string table index is
|
||||
considered to be just 16 bits and the first two bytes of the struct were
|
||||
previously named e_unused. To extend the symbol table format to accommodate
|
||||
.stab symbols, the e_unused bytes are renamed e_desc to store the desc field
|
||||
of the .stab symbol. The GDP Project's STABS document says that the "other"
|
||||
field is almost always unused and can be set to zero; the only nonzero cases
|
||||
identified were for stabs in their own sections, which does not apply for
|
||||
pdp11 a.out format, and for a special case of GNU Modula2 which is not
|
||||
supported for the PDP11. */
|
||||
#define external_nlist pdp11_external_nlist
|
||||
struct pdp11_external_nlist
|
||||
{
|
||||
bfd_byte e_unused[2]; /* Unused. */
|
||||
bfd_byte e_desc[2]; /* The desc field for .stab symbols, else 0. */
|
||||
bfd_byte e_strx[2]; /* Index into string table of name. */
|
||||
bfd_byte e_type[1]; /* Type of symbol. */
|
||||
bfd_byte e_ovly[1]; /* Overlay number. */
|
||||
@ -151,6 +166,13 @@ static bfd_boolean MY(write_object_contents) (bfd *);
|
||||
#include "aout/stab_gnu.h"
|
||||
#include "aout/ar.h"
|
||||
|
||||
/* The symbol type numbers for the 16-bit a.out format from 2.11BSD differ from
|
||||
those defined in aout64.h so we must redefine them here. N_EXT changes from
|
||||
0x01 to 0x20 which creates a conflict with some .stab values, in particular
|
||||
between undefined externals (N_UNDF+N_EXT) vs. global variables (N_GYSM) and
|
||||
between external bss symbols (N_BSS+N_EXT) vs. function names (N_FUN). We
|
||||
disambiguate those conflicts with a hack in is_stab() to look for the ':' in
|
||||
the global variable or function name string. */
|
||||
#undef N_TYPE
|
||||
#undef N_UNDF
|
||||
#undef N_ABS
|
||||
@ -170,7 +192,12 @@ static bfd_boolean MY(write_object_contents) (bfd *);
|
||||
#define N_REG 0x14 /* Register symbol. */
|
||||
#define N_FN 0x1f /* File name. */
|
||||
#define N_EXT 0x20 /* External flag. */
|
||||
#define N_STAB 0xc0 /* Not relevant; modified aout64.h's 0xe0 to avoid N_EXT. */
|
||||
/* Type numbers from .stab entries that could conflict:
|
||||
N_GSYM 0x20 Global variable [conflict with external undef]
|
||||
N_FNAME 0x22 Function name (for BSD Fortran) [ignored]
|
||||
N_FUN 0x24 Function name [conflict with external BSS]
|
||||
N_NOMAP 0x34 No DST map for sym. [ext. reg. doesn't exist]
|
||||
*/
|
||||
|
||||
#define RELOC_SIZE 2
|
||||
|
||||
@ -300,6 +327,19 @@ NAME (aout, reloc_name_lookup) (bfd *abfd ATTRIBUTE_UNUSED,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Disambiguate conflicts between normal symbol types and .stab symbol types
|
||||
(undefined externals N_UNDF+N_EXT vs. global variables N_GYSM and external
|
||||
bss symbols N_BSS+N_EXT vs. function names N_FUN) with a hack to look for
|
||||
the ':' in the global variable or function name string. */
|
||||
|
||||
static int
|
||||
is_stab (int type, const char *name)
|
||||
{
|
||||
if (type == N_GSYM || type == N_FUN)
|
||||
return (index(name, ':') != NULL);
|
||||
return (type > N_FUN);
|
||||
}
|
||||
|
||||
static int
|
||||
pdp11_aout_write_headers (bfd *abfd, struct internal_exec *execp)
|
||||
{
|
||||
@ -1325,7 +1365,7 @@ translate_from_native_sym_flags (bfd *abfd,
|
||||
{
|
||||
flagword visible;
|
||||
|
||||
if (cache_ptr->type == N_FN)
|
||||
if (is_stab (cache_ptr->type, cache_ptr->symbol.name))
|
||||
{
|
||||
asection *sec;
|
||||
|
||||
@ -1333,20 +1373,25 @@ translate_from_native_sym_flags (bfd *abfd,
|
||||
cache_ptr->symbol.flags = BSF_DEBUGGING;
|
||||
|
||||
/* Work out the symbol section. */
|
||||
switch (cache_ptr->type & N_TYPE)
|
||||
switch (cache_ptr->type)
|
||||
{
|
||||
case N_TEXT:
|
||||
case N_SO:
|
||||
case N_SOL:
|
||||
case N_FUN:
|
||||
case N_ENTRY:
|
||||
case N_SLINE:
|
||||
case N_FN:
|
||||
sec = obj_textsec (abfd);
|
||||
break;
|
||||
case N_DATA:
|
||||
case N_STSYM:
|
||||
case N_DSLINE:
|
||||
sec = obj_datasec (abfd);
|
||||
break;
|
||||
case N_BSS:
|
||||
case N_LCSYM:
|
||||
case N_BSLINE:
|
||||
sec = obj_bsssec (abfd);
|
||||
break;
|
||||
default:
|
||||
case N_ABS:
|
||||
sec = bfd_abs_section_ptr;
|
||||
break;
|
||||
}
|
||||
@ -1418,10 +1463,12 @@ translate_to_native_sym_flags (bfd *abfd,
|
||||
bfd_vma value = cache_ptr->value;
|
||||
asection *sec;
|
||||
bfd_vma off;
|
||||
const char *name = cache_ptr->name != NULL ? cache_ptr->name : "*unknown*";
|
||||
|
||||
/* Mask out any existing type bits in case copying from one section
|
||||
to another. */
|
||||
sym_pointer->e_type[0] &= ~N_TYPE;
|
||||
if (!is_stab (sym_pointer->e_type[0], name))
|
||||
sym_pointer->e_type[0] &= ~N_TYPE;
|
||||
|
||||
sec = bfd_asymbol_section (cache_ptr);
|
||||
off = 0;
|
||||
@ -1433,7 +1480,7 @@ translate_to_native_sym_flags (bfd *abfd,
|
||||
_bfd_error_handler
|
||||
/* xgettext:c-format */
|
||||
(_("%pB: can not represent section for symbol `%s' in a.out object file format"),
|
||||
abfd, cache_ptr->name != NULL ? cache_ptr->name : "*unknown*");
|
||||
abfd, name);
|
||||
bfd_set_error (bfd_error_nonrepresentable_section);
|
||||
return FALSE;
|
||||
}
|
||||
@ -1511,6 +1558,7 @@ NAME (aout, translate_symbol_table) (bfd *abfd,
|
||||
for (; ext < ext_end; ext++, in++)
|
||||
{
|
||||
bfd_vma x;
|
||||
int ovly;
|
||||
|
||||
x = GET_WORD (abfd, ext->e_strx);
|
||||
in->symbol.the_bfd = abfd;
|
||||
@ -1533,9 +1581,19 @@ NAME (aout, translate_symbol_table) (bfd *abfd,
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
ovly = H_GET_8 (abfd, ext->e_ovly);
|
||||
if (ovly != 0)
|
||||
{
|
||||
_bfd_error_handler
|
||||
(_("%pB: symbol indicates overlay (not supported)"), abfd);
|
||||
bfd_set_error (bfd_error_bad_value);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
in->symbol.value = GET_WORD (abfd, ext->e_value);
|
||||
/* TODO: is 0 a safe value here? */
|
||||
in->desc = 0;
|
||||
/* e_desc is zero for normal symbols but for .stab symbols it
|
||||
carries the desc field in our extended 2.11BSD format. */
|
||||
in->desc = H_GET_16 (abfd, ext->e_desc);
|
||||
in->other = 0;
|
||||
in->type = H_GET_8 (abfd, ext->e_type);
|
||||
in->symbol.udata.p = NULL;
|
||||
@ -1686,23 +1744,27 @@ NAME (aout, write_syms) (bfd *abfd)
|
||||
bfd_size_type indx;
|
||||
struct external_nlist nsp;
|
||||
|
||||
PUT_WORD (abfd, 0, nsp.e_unused);
|
||||
|
||||
indx = add_to_stringtab (abfd, strtab, g->name, FALSE);
|
||||
if (indx == (bfd_size_type) -1)
|
||||
goto error_return;
|
||||
PUT_WORD (abfd, indx, nsp.e_strx);
|
||||
|
||||
if (bfd_asymbol_flavour(g) == abfd->xvec->flavour)
|
||||
H_PUT_8 (abfd, aout_symbol(g)->type, nsp.e_type);
|
||||
{
|
||||
H_PUT_16 (abfd, aout_symbol (g)->desc, nsp.e_desc);
|
||||
H_PUT_8 (abfd, 0, nsp.e_ovly);
|
||||
H_PUT_8 (abfd, aout_symbol (g)->type, nsp.e_type);
|
||||
}
|
||||
else
|
||||
H_PUT_8 (abfd, 0, nsp.e_type);
|
||||
{
|
||||
H_PUT_16 (abfd, 0, nsp.e_desc);
|
||||
H_PUT_8 (abfd, 0, nsp.e_ovly);
|
||||
H_PUT_8 (abfd, 0, nsp.e_type);
|
||||
}
|
||||
|
||||
if (! translate_to_native_sym_flags (abfd, g, &nsp))
|
||||
goto error_return;
|
||||
|
||||
H_PUT_8 (abfd, 0, nsp.e_ovly);
|
||||
|
||||
if (bfd_bwrite ((void *)&nsp, (bfd_size_type) EXTERNAL_NLIST_SIZE, abfd)
|
||||
!= EXTERNAL_NLIST_SIZE)
|
||||
goto error_return;
|
||||
@ -2643,17 +2705,17 @@ aout_link_check_ar_symbols (bfd *abfd,
|
||||
for (; p < pend; p++)
|
||||
{
|
||||
int type = H_GET_8 (abfd, p->e_type);
|
||||
const char *name;
|
||||
const char *name = strings + GET_WORD (abfd, p->e_strx);
|
||||
struct bfd_link_hash_entry *h;
|
||||
|
||||
/* Ignore symbols that are not externally visible. This is an
|
||||
optimization only, as we check the type more thoroughly
|
||||
below. */
|
||||
if ((type & N_EXT) == 0
|
||||
|| is_stab(type, name)
|
||||
|| type == N_FN)
|
||||
continue;
|
||||
|
||||
name = strings + GET_WORD (abfd, p->e_strx);
|
||||
h = bfd_link_hash_lookup (info->hash, name, FALSE, FALSE, TRUE);
|
||||
|
||||
/* We are only interested in symbols that are currently
|
||||
@ -2863,6 +2925,10 @@ aout_link_add_symbols (bfd *abfd, struct bfd_link_info *info)
|
||||
|
||||
type = H_GET_8 (abfd, p->e_type);
|
||||
|
||||
/* Ignore debugging symbols. */
|
||||
if (is_stab(type, name))
|
||||
continue;
|
||||
|
||||
/* PR 19629: Corrupt binaries can contain illegal string offsets. */
|
||||
if (GET_WORD (abfd, p->e_strx) >= obj_aout_external_string_size (abfd))
|
||||
return FALSE;
|
||||
@ -2873,8 +2939,8 @@ aout_link_add_symbols (bfd *abfd, struct bfd_link_info *info)
|
||||
switch (type)
|
||||
{
|
||||
default:
|
||||
/* Anything else should be a debugging symbol. */
|
||||
BFD_ASSERT ((type & N_STAB) != 0);
|
||||
/* Shouldn't be any types not covered. */
|
||||
BFD_ASSERT (0);
|
||||
continue;
|
||||
|
||||
case N_UNDF:
|
||||
@ -3077,12 +3143,14 @@ aout_link_write_other_symbol (struct bfd_hash_entry *bh, void *data)
|
||||
}
|
||||
|
||||
H_PUT_8 (output_bfd, type, outsym.e_type);
|
||||
H_PUT_8 (output_bfd, 0, outsym.e_ovly);
|
||||
indx = add_to_stringtab (output_bfd, flaginfo->strtab, h->root.root.string,
|
||||
FALSE);
|
||||
if (indx == (bfd_size_type) -1)
|
||||
/* FIXME: No way to handle errors. */
|
||||
abort ();
|
||||
|
||||
PUT_WORD (output_bfd, 0, outsym.e_desc);
|
||||
PUT_WORD (output_bfd, indx, outsym.e_strx);
|
||||
PUT_WORD (output_bfd, val, outsym.e_value);
|
||||
|
||||
@ -4097,6 +4165,8 @@ aout_link_write_symbols (struct aout_final_link_info *flaginfo, bfd *input_bfd)
|
||||
&& discard != discard_all)
|
||||
{
|
||||
H_PUT_8 (output_bfd, N_TEXT, outsym->e_type);
|
||||
H_PUT_8 (output_bfd, 0, outsym->e_ovly);
|
||||
H_PUT_16 (output_bfd, 0, outsym->e_desc);
|
||||
strtab_index = add_to_stringtab (output_bfd, flaginfo->strtab,
|
||||
bfd_get_filename (input_bfd), FALSE);
|
||||
if (strtab_index == (bfd_size_type) -1)
|
||||
@ -4210,7 +4280,7 @@ aout_link_write_symbols (struct aout_final_link_info *flaginfo, bfd *input_bfd)
|
||||
case strip_none:
|
||||
break;
|
||||
case strip_debugger:
|
||||
if ((type & N_STAB) != 0)
|
||||
if (is_stab (type, name))
|
||||
skip = TRUE;
|
||||
break;
|
||||
case strip_some:
|
||||
@ -4230,7 +4300,33 @@ aout_link_write_symbols (struct aout_final_link_info *flaginfo, bfd *input_bfd)
|
||||
}
|
||||
|
||||
/* Get the value of the symbol. */
|
||||
if ((type & N_TYPE) == N_TEXT
|
||||
if (is_stab (type, name))
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
default:
|
||||
symsec = bfd_abs_section_ptr;
|
||||
break;
|
||||
case N_SO:
|
||||
case N_SOL:
|
||||
case N_FUN:
|
||||
case N_ENTRY:
|
||||
case N_SLINE:
|
||||
case N_FN:
|
||||
symsec = obj_textsec (input_bfd);
|
||||
break;
|
||||
case N_STSYM:
|
||||
case N_DSLINE:
|
||||
symsec = obj_datasec (input_bfd);
|
||||
break;
|
||||
case N_LCSYM:
|
||||
case N_BSLINE:
|
||||
symsec = obj_bsssec (input_bfd);
|
||||
break;
|
||||
}
|
||||
val = GET_WORD (input_bfd, sym->e_value);
|
||||
}
|
||||
else if ((type & N_TYPE) == N_TEXT
|
||||
|| type == N_WEAKT)
|
||||
symsec = obj_textsec (input_bfd);
|
||||
else if ((type & N_TYPE) == N_DATA
|
||||
@ -4258,11 +4354,6 @@ aout_link_write_symbols (struct aout_final_link_info *flaginfo, bfd *input_bfd)
|
||||
val = GET_WORD (input_bfd, sym->e_value);
|
||||
symsec = NULL;
|
||||
}
|
||||
else if ((type & N_STAB) != 0)
|
||||
{
|
||||
val = GET_WORD (input_bfd, sym->e_value);
|
||||
symsec = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* If we get here with an indirect symbol, it means that
|
||||
@ -4376,7 +4467,7 @@ aout_link_write_symbols (struct aout_final_link_info *flaginfo, bfd *input_bfd)
|
||||
case discard_sec_merge:
|
||||
break;
|
||||
case discard_l:
|
||||
if ((type & N_STAB) == 0
|
||||
if (!is_stab (type, name)
|
||||
&& bfd_is_local_label_name (input_bfd, name))
|
||||
skip = TRUE;
|
||||
break;
|
||||
@ -4500,6 +4591,8 @@ aout_link_write_symbols (struct aout_final_link_info *flaginfo, bfd *input_bfd)
|
||||
/* Copy this symbol into the list of symbols we are going to
|
||||
write out. */
|
||||
H_PUT_8 (output_bfd, type, outsym->e_type);
|
||||
H_PUT_8 (output_bfd, H_GET_8 (input_bfd, sym->e_ovly), outsym->e_ovly);
|
||||
H_PUT_16 (output_bfd, H_GET_16 (input_bfd, sym->e_desc), outsym->e_desc);
|
||||
copy = FALSE;
|
||||
if (! flaginfo->info->keep_memory)
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user