Based on patches from Donn Terry <donn@interix.com>:

* coffcode.h (enum coff_symbol_classification): Define.
	(bfd_coff_backend_data): Rename _bfd_coff_sym_is_global to
	_bfd_coff_classify_symbol.  Change return type.
	(bfd_coff_classify_symbol): Rename from bfd_coff_sym_is_global.
	(coff_slurp_symbol_table): Use coff_classify_symbol.
	(coff_classify_symbol): New static function.
	(coff_sym_is_global): Never define.
	(bfd_coff_std_swap_table): Initialize with coff_classify_symbol.
	* cofflink.c (coff_link_check_ar_symbols): Use
	bfd_coff_classify_symbol rather than bfd_coff_sym_is_global.
	(coff_link_add_symbols): Likewise.
	(_bfd_coff_link_input_bfd): Likewise.
	* coff-sh.c (bfd_coff_small_swap_table): Initialize with
	coff_classify_symbol.
	* libcoff.h: Rebuild.
This commit is contained in:
Ian Lance Taylor 1999-08-05 21:01:37 +00:00
parent 1198f921ae
commit 5d54c62870
5 changed files with 268 additions and 124 deletions

View File

@ -1,3 +1,22 @@
1999-08-05 Ian Lance Taylor <ian@zembu.com>
Based on patches from Donn Terry <donn@interix.com>:
* coffcode.h (enum coff_symbol_classification): Define.
(bfd_coff_backend_data): Rename _bfd_coff_sym_is_global to
_bfd_coff_classify_symbol. Change return type.
(bfd_coff_classify_symbol): Rename from bfd_coff_sym_is_global.
(coff_slurp_symbol_table): Use coff_classify_symbol.
(coff_classify_symbol): New static function.
(coff_sym_is_global): Never define.
(bfd_coff_std_swap_table): Initialize with coff_classify_symbol.
* cofflink.c (coff_link_check_ar_symbols): Use
bfd_coff_classify_symbol rather than bfd_coff_sym_is_global.
(coff_link_add_symbols): Likewise.
(_bfd_coff_link_input_bfd): Likewise.
* coff-sh.c (bfd_coff_small_swap_table): Initialize with
coff_classify_symbol.
* libcoff.h: Rebuild.
Wed Aug 4 18:08:07 1999 Jeffrey A Law (law@cygnus.com)
* libhppa.h (R_HPPA_LTPSEL, R_HPPA_RTPSEL): New field selectors

View File

@ -2765,7 +2765,7 @@ static const bfd_coff_backend_data bfd_coff_small_swap_table =
coff_mkobject_hook, styp_to_sec_flags, coff_set_alignment_hook,
coff_slurp_symbol_table, symname_in_debug_hook, coff_pointerize_aux_hook,
coff_print_aux, coff_reloc16_extra_cases, coff_reloc16_estimate,
coff_sym_is_global, coff_compute_section_file_positions,
coff_classify_symbol, coff_compute_section_file_positions,
coff_start_final_link, coff_relocate_section, coff_rtype_to_howto,
coff_adjust_symndx, coff_link_add_one_symbol,
coff_link_output_has_begun, coff_final_link_postscript

View File

@ -329,6 +329,8 @@ static boolean coff_set_section_contents
static PTR buy_and_read PARAMS ((bfd *, file_ptr, int, size_t));
static boolean coff_slurp_line_table PARAMS ((bfd *, asection *));
static boolean coff_slurp_symbol_table PARAMS ((bfd *));
static enum coff_symbol_classification coff_classify_symbol
PARAMS ((bfd *, struct internal_syment *));
static boolean coff_slurp_reloc_table PARAMS ((bfd *, asection *, asymbol **));
static long coff_canonicalize_reloc
PARAMS ((bfd *, asection *, arelent **, asymbol **));
@ -709,6 +711,22 @@ INTERNAL_DEFINITION
CODE_FRAGMENT
.{* COFF symbol classifications. *}
.
.enum coff_symbol_classification
.{
. {* Global symbol. *}
. COFF_SYMBOL_GLOBAL,
. {* Common symbol. *}
. COFF_SYMBOL_COMMON,
. {* Undefined symbol. *}
. COFF_SYMBOL_UNDEFINED,
. {* Local symbol. *}
. COFF_SYMBOL_LOCAL,
. {* PE section symbol. *}
. COFF_SYMBOL_PE_SECTION
.};
.
Special entry points for gdb to swap in coff symbol table parts:
.typedef struct
.{
@ -853,7 +871,7 @@ dependent COFF routines:
. arelent *r,
. unsigned int shrink,
. struct bfd_link_info *link_info));
. boolean (*_bfd_coff_sym_is_global) PARAMS ((
. enum coff_symbol_classification (*_bfd_coff_classify_symbol) PARAMS ((
. bfd *abfd,
. struct internal_syment *));
. boolean (*_bfd_coff_compute_section_file_positions) PARAMS ((
@ -993,8 +1011,8 @@ dependent COFF routines:
. ((coff_backend_info (abfd)->_bfd_coff_reloc16_estimate)\
. (abfd, section, reloc, shrink, link_info))
.
.#define bfd_coff_sym_is_global(abfd, sym)\
. ((coff_backend_info (abfd)->_bfd_coff_sym_is_global)\
.#define bfd_coff_classify_symbol(abfd, sym)\
. ((coff_backend_info (abfd)->_bfd_coff_classify_symbol)\
. (abfd, sym))
.
.#define bfd_coff_compute_section_file_positions(abfd)\
@ -3569,31 +3587,15 @@ coff_slurp_symbol_table (abfd)
case C_SYSTEM: /* System Wide variable */
#endif
#ifdef COFF_WITH_PE
/* PE uses storage class 0x68 to denote a section symbol */
/* In PE, 0x68 (104) denotes a section symbol */
case C_SECTION:
/* PE uses storage class 0x69 for a weak external symbol. */
/* In PE, 0x69 (105) denotes a weak external symbol. */
case C_NT_WEAK:
#endif
if ((src->u.syment.n_scnum) == 0)
switch (coff_classify_symbol (abfd, &src->u.syment))
{
if ((src->u.syment.n_value) == 0)
{
dst->symbol.section = bfd_und_section_ptr;
dst->symbol.value = 0;
}
else
{
dst->symbol.section = bfd_com_section_ptr;
dst->symbol.value = (src->u.syment.n_value);
}
}
else
{
/* Base the value as an index from the base of the
section */
case COFF_SYMBOL_GLOBAL:
dst->symbol.flags = BSF_EXPORT | BSF_GLOBAL;
#if defined COFF_WITH_PE
/* PE sets the symbol to a value relative to the
start of the section. */
@ -3602,19 +3604,45 @@ coff_slurp_symbol_table (abfd)
dst->symbol.value = (src->u.syment.n_value
- dst->symbol.section->vma);
#endif
if (ISFCN ((src->u.syment.n_type)))
{
/* A function ext does not go at the end of a
file. */
dst->symbol.flags |= BSF_NOT_AT_END | BSF_FUNCTION;
}
break;
case COFF_SYMBOL_COMMON:
dst->symbol.section = bfd_com_section_ptr;
dst->symbol.value = src->u.syment.n_value;
break;
case COFF_SYMBOL_UNDEFINED:
dst->symbol.section = bfd_und_section_ptr;
dst->symbol.value = 0;
break;
case COFF_SYMBOL_PE_SECTION:
dst->symbol.flags |= BSF_EXPORT | BSF_SECTION_SYM;
dst->symbol.value = 0;
break;
case COFF_SYMBOL_LOCAL:
dst->symbol.flags = BSF_LOCAL;
#if defined COFF_WITH_PE
/* PE sets the symbol to a value relative to the
start of the section. */
dst->symbol.value = src->u.syment.n_value;
#else
dst->symbol.value = (src->u.syment.n_value
- dst->symbol.section->vma);
#endif
if (ISFCN ((src->u.syment.n_type)))
dst->symbol.flags |= BSF_NOT_AT_END | BSF_FUNCTION;
break;
}
#ifdef RS6000COFF_C
/* A C_HIDEXT symbol is not global. */
if (src->u.syment.n_sclass == C_HIDEXT)
dst->symbol.flags = BSF_LOCAL;
/* A symbol with a csect entry should not go at the end. */
if (src->u.syment.n_numaux > 0)
dst->symbol.flags |= BSF_NOT_AT_END;
@ -3830,47 +3858,102 @@ coff_slurp_symbol_table (abfd)
return true;
} /* coff_slurp_symbol_table() */
/* Check whether a symbol is globally visible. This is used by the
COFF backend linker code in cofflink.c, since a couple of targets
have globally visible symbols which are not class C_EXT. This
function need not handle the case of n_class == C_EXT. */
/* Classify a COFF symbol. A couple of targets have globally visible
symbols which are not class C_EXT, and this handles those. It also
recognizes some special PE cases. */
#undef OTHER_GLOBAL_CLASS
#ifdef I960
#define OTHER_GLOBAL_CLASS C_LEAFEXT
#endif
#ifdef COFFARM
#define OTHER_GLOBAL_CLASS C_THUMBEXT || syment->n_sclass == C_THUMBEXTFUNC
#else
#ifdef COFF_WITH_PE
#define OTHER_GLOBAL_CLASS C_SECTION
#endif
#endif
#ifdef OTHER_GLOBAL_CLASS
static boolean coff_sym_is_global PARAMS ((bfd *, struct internal_syment *));
static boolean
coff_sym_is_global (abfd, syment)
bfd * abfd ATTRIBUTE_UNUSED;
struct internal_syment * syment;
static enum coff_symbol_classification
coff_classify_symbol (abfd, syment)
bfd *abfd;
struct internal_syment *syment;
{
return (syment->n_sclass == OTHER_GLOBAL_CLASS);
/* FIXME: This partially duplicates the switch in
coff_slurp_symbol_table. */
switch (syment->n_sclass)
{
case C_EXT:
case C_WEAKEXT:
#ifdef I960
case C_LEAFEXT:
#endif
#ifdef ARM
case C_THUMBEXT:
case C_THUMBEXTFUNC:
#endif
#ifdef C_SYSTEM
case C_SYSTEM:
#endif
#ifdef COFF_WITH_PE
case C_NT_WEAK:
#endif
if (syment->n_scnum == 0)
{
if (syment->n_value == 0)
return COFF_SYMBOL_UNDEFINED;
else
return COFF_SYMBOL_COMMON;
}
return COFF_SYMBOL_GLOBAL;
default:
break;
}
#ifdef COFF_WITH_PE
if (syment->n_sclass == C_STAT)
{
if (syment->n_scnum == 0)
{
/* The Microsoft compiler sometimes generates these if a
small static function is inlined every time it is used.
The function is discarded, but the symbol table entry
remains. */
return COFF_SYMBOL_LOCAL;
}
if (syment->n_value == 0)
{
asection *sec;
char buf[SYMNMLEN + 1];
sec = coff_section_from_bfd_index (abfd, syment->n_scnum);
if (sec != NULL
&& (strcmp (bfd_get_section_name (abfd, sec),
_bfd_coff_internal_syment_name (abfd, syment, buf))
== 0))
return COFF_SYMBOL_PE_SECTION;
}
return COFF_SYMBOL_LOCAL;
}
if (syment->n_sclass == C_SECTION)
{
/* In some cases in a DLL generated by the Microsoft linker, the
n_value field will contain garbage. FIXME: This should
probably be handled by the swapping function instead. */
syment->n_value = 0;
if (syment->n_scnum == 0)
return COFF_SYMBOL_UNDEFINED;
return COFF_SYMBOL_PE_SECTION;
}
#endif /* COFF_WITH_PE */
/* If it is not a global symbol, we presume it is a local symbol. */
if (syment->n_scnum == 0)
{
char buf[SYMNMLEN + 1];
(*_bfd_error_handler)
(_("warning: %s: local symbol `%s' has no section"),
bfd_get_filename (abfd),
_bfd_coff_internal_syment_name (abfd, syment, buf));
}
return COFF_SYMBOL_LOCAL;
}
#undef OTHER_GLOBAL_CLASS
#else /* ! defined (OTHER_GLOBAL_CLASS) */
/* sym_is_global should not be defined if it has nothing to do. */
#define coff_sym_is_global 0
#endif /* ! defined (OTHER_GLOBAL_CLASS) */
/*
SUBSUBSECTION
Reading relocations
@ -4291,7 +4374,7 @@ static CONST bfd_coff_backend_data bfd_coff_std_swap_table =
coff_mkobject_hook, styp_to_sec_flags, coff_set_alignment_hook,
coff_slurp_symbol_table, symname_in_debug_hook, coff_pointerize_aux_hook,
coff_print_aux, coff_reloc16_extra_cases, coff_reloc16_estimate,
coff_sym_is_global, coff_compute_section_file_positions,
coff_classify_symbol, coff_compute_section_file_positions,
coff_start_final_link, coff_relocate_section, coff_rtype_to_howto,
coff_adjust_symndx, coff_link_add_one_symbol,
coff_link_output_has_begun, coff_final_link_postscript

View File

@ -225,32 +225,25 @@ coff_link_check_ar_symbols (abfd, info, pneeded)
struct bfd_link_info *info;
boolean *pneeded;
{
boolean (*sym_is_global) PARAMS ((bfd *, struct internal_syment *));
bfd_size_type symesz;
bfd_byte *esym;
bfd_byte *esym_end;
*pneeded = false;
sym_is_global = coff_backend_info (abfd)->_bfd_coff_sym_is_global;
symesz = bfd_coff_symesz (abfd);
esym = (bfd_byte *) obj_coff_external_syms (abfd);
esym_end = esym + obj_raw_syment_count (abfd) * symesz;
while (esym < esym_end)
{
struct internal_syment sym;
enum coff_symbol_classification classification;
bfd_coff_swap_sym_in (abfd, (PTR) esym, (PTR) &sym);
if ((sym.n_sclass == C_EXT
|| sym.n_sclass == C_WEAKEXT
|| (obj_pe (abfd) && sym.n_sclass == C_NT_WEAK)
#ifdef C_SYSTEM
|| sym.n_sclass == C_SYSTEM
#endif
|| (sym_is_global && (*sym_is_global) (abfd, &sym)))
&& (sym.n_scnum != 0 || sym.n_value != 0))
classification = bfd_coff_classify_symbol (abfd, &sym);
if (classification == COFF_SYMBOL_GLOBAL
|| classification == COFF_SYMBOL_COMMON)
{
const char *name;
char buf[SYMNMLEN + 1];
@ -292,7 +285,6 @@ coff_link_add_symbols (abfd, info)
bfd *abfd;
struct bfd_link_info *info;
{
boolean (*sym_is_global) PARAMS ((bfd *, struct internal_syment *));
boolean keep_syms;
boolean default_copy;
bfd_size_type symcount;
@ -306,8 +298,6 @@ coff_link_add_symbols (abfd, info)
keep_syms = obj_coff_keep_syms (abfd);
obj_coff_keep_syms (abfd) = true;
sym_is_global = coff_backend_info (abfd)->_bfd_coff_sym_is_global;
if (info->keep_memory)
default_copy = false;
else
@ -334,17 +324,13 @@ coff_link_add_symbols (abfd, info)
while (esym < esym_end)
{
struct internal_syment sym;
enum coff_symbol_classification classification;
boolean copy;
bfd_coff_swap_sym_in (abfd, (PTR) esym, (PTR) &sym);
if (sym.n_sclass == C_EXT
|| sym.n_sclass == C_WEAKEXT
|| (obj_pe (abfd) && sym.n_sclass == C_NT_WEAK)
#ifdef C_SYSTEM
|| sym.n_sclass == C_SYSTEM
#endif
|| (sym_is_global && (*sym_is_global) (abfd, &sym)))
classification = bfd_coff_classify_symbol (abfd, &sym);
if (classification != COFF_SYMBOL_LOCAL)
{
const char *name;
char buf[SYMNMLEN + 1];
@ -368,25 +354,32 @@ coff_link_add_symbols (abfd, info)
value = sym.n_value;
if (sym.n_scnum == 0)
{
if (value == 0)
{
flags = 0;
section = bfd_und_section_ptr;
}
else
{
flags = BSF_GLOBAL;
section = bfd_com_section_ptr;
}
}
else
switch (classification)
{
default:
abort ();
case COFF_SYMBOL_GLOBAL:
flags = BSF_EXPORT | BSF_GLOBAL;
section = coff_section_from_bfd_index (abfd, sym.n_scnum);
if (! obj_pe (abfd))
value -= section->vma;
break;
case COFF_SYMBOL_UNDEFINED:
flags = 0;
section = bfd_und_section_ptr;
break;
case COFF_SYMBOL_COMMON:
flags = BSF_GLOBAL;
section = bfd_com_section_ptr;
break;
case COFF_SYMBOL_PE_SECTION:
flags = BSF_SECTION_SYM | BSF_GLOBAL;
section = coff_section_from_bfd_index (abfd, sym.n_scnum);
break;
}
if (sym.n_sclass == C_WEAKEXT
@ -481,6 +474,26 @@ coff_link_add_symbols (abfd, info)
}
}
}
if (classification == COFF_SYMBOL_PE_SECTION
&& (*sym_hash)->numaux != 0)
{
/* Some PE sections (such as .bss) have a zero size in
the section header, but a non-zero size in the AUX
record. Correct that here.
FIXME: This is not at all the right place to do this.
For example, it won't help objdump. This needs to be
done when we swap in the section header. */
BFD_ASSERT ((*sym_hash)->numaux == 1);
if (section->_raw_size == 0)
section->_raw_size = (*sym_hash)->aux[0].x_scn.x_scnlen;
/* FIXME: We could test whether the section sizes
matches the size in the aux entry, but apparently
that sometimes fails unexpectedly. */
}
}
esym += (sym.n_numaux + 1) * symesz;
@ -1243,7 +1256,6 @@ _bfd_coff_link_input_bfd (finfo, input_bfd)
struct coff_final_link_info *finfo;
bfd *input_bfd;
{
boolean (*sym_is_global) PARAMS ((bfd *, struct internal_syment *));
boolean (*adjust_symndx) PARAMS ((bfd *, struct bfd_link_info *, bfd *,
asection *, struct internal_reloc *,
boolean *));
@ -1269,7 +1281,6 @@ _bfd_coff_link_input_bfd (finfo, input_bfd)
/* Move all the symbols to the output file. */
output_bfd = finfo->output_bfd;
sym_is_global = coff_backend_info (input_bfd)->_bfd_coff_sym_is_global;
strings = NULL;
syment_base = obj_raw_syment_count (output_bfd);
isymesz = bfd_coff_symesz (input_bfd);
@ -1324,6 +1335,7 @@ _bfd_coff_link_input_bfd (finfo, input_bfd)
while (esym < esym_end)
{
struct internal_syment isym;
enum coff_symbol_classification classification;
boolean skip;
boolean global;
boolean dont_skip_symbol;
@ -1337,14 +1349,22 @@ _bfd_coff_link_input_bfd (finfo, input_bfd)
the symbol. */
isym = *isymp;
if (isym.n_scnum != 0)
*secpp = coff_section_from_bfd_index (input_bfd, isym.n_scnum);
else
classification = bfd_coff_classify_symbol (input_bfd, &isym);
switch (classification)
{
if (isym.n_value == 0)
*secpp = bfd_und_section_ptr;
else
*secpp = bfd_com_section_ptr;
default:
abort ();
case COFF_SYMBOL_GLOBAL:
case COFF_SYMBOL_PE_SECTION:
case COFF_SYMBOL_LOCAL:
*secpp = coff_section_from_bfd_index (input_bfd, isym.n_scnum);
break;
case COFF_SYMBOL_COMMON:
*secpp = bfd_com_section_ptr;
break;
case COFF_SYMBOL_UNDEFINED:
*secpp = bfd_und_section_ptr;
break;
}
/* Extract the flag indicating if this symbol is used by a
@ -1368,28 +1388,34 @@ _bfd_coff_link_input_bfd (finfo, input_bfd)
if (! skip)
{
if (isym.n_sclass == C_EXT
|| isym.n_sclass == C_WEAKEXT
|| (obj_pe (input_bfd) && isym.n_sclass == C_NT_WEAK)
#ifdef C_SYSTEM
|| isym.n_sclass == C_SYSTEM
#endif
|| (sym_is_global && (*sym_is_global) (input_bfd, &isym)))
switch (classification)
{
default:
abort ();
case COFF_SYMBOL_GLOBAL:
case COFF_SYMBOL_COMMON:
case COFF_SYMBOL_PE_SECTION:
/* This is a global symbol. Global symbols come at the
end of the symbol table, so skip them for now.
Locally defined function symbols, however, are an
exception, and are not moved to the end. */
global = true;
if (! ISFCN (isym.n_type) || isym.n_scnum == 0)
if (! ISFCN (isym.n_type))
skip = true;
}
else
{
break;
case COFF_SYMBOL_UNDEFINED:
/* Undefined symbols are left for the end. */
global = true;
skip = true;
break;
case COFF_SYMBOL_LOCAL:
/* This is a local symbol. Skip it if we are discarding
local symbols. */
if (finfo->info->discard == discard_all && ! dont_skip_symbol)
skip = true;
break;
}
}

View File

@ -586,6 +586,22 @@ struct lineno_cache_entry *lineno;
/* Have the line numbers been relocated yet ? */
boolean done_lineno;
} coff_symbol_type;
/* COFF symbol classifications. */
enum coff_symbol_classification
{
/* Global symbol. */
COFF_SYMBOL_GLOBAL,
/* Common symbol. */
COFF_SYMBOL_COMMON,
/* Undefined symbol. */
COFF_SYMBOL_UNDEFINED,
/* Local symbol. */
COFF_SYMBOL_LOCAL,
/* PE section symbol. */
COFF_SYMBOL_PE_SECTION
};
typedef struct
{
void (*_bfd_coff_swap_aux_in) PARAMS ((
@ -722,7 +738,7 @@ typedef struct
arelent *r,
unsigned int shrink,
struct bfd_link_info *link_info));
boolean (*_bfd_coff_sym_is_global) PARAMS ((
enum coff_symbol_classification (*_bfd_coff_classify_symbol) PARAMS ((
bfd *abfd,
struct internal_syment *));
boolean (*_bfd_coff_compute_section_file_positions) PARAMS ((
@ -862,8 +878,8 @@ typedef struct
((coff_backend_info (abfd)->_bfd_coff_reloc16_estimate)\
(abfd, section, reloc, shrink, link_info))
#define bfd_coff_sym_is_global(abfd, sym)\
((coff_backend_info (abfd)->_bfd_coff_sym_is_global)\
#define bfd_coff_classify_symbol(abfd, sym)\
((coff_backend_info (abfd)->_bfd_coff_classify_symbol)\
(abfd, sym))
#define bfd_coff_compute_section_file_positions(abfd)\