Patches to fix bugs reported by roland McGrath

This commit is contained in:
Steve Chamberlain 1991-08-06 21:28:21 +00:00
parent e929a4c57a
commit 1af27af8bc
3 changed files with 123 additions and 54 deletions

View File

@ -80,7 +80,6 @@ ldsym.h
ldvanilla.c
ldver.c
ldver.h
ldversion.c
ldwarn.h
ldwrite.c
ldwrite.h
@ -93,7 +92,10 @@ echo Done in `pwd`.
#
#
# $Log$
# Revision 1.3 1991/08/01 23:59:06 steve
# Revision 1.4 1991/08/06 21:28:21 steve
# Patches to fix bugs reported by roland McGrath
#
# Revision 1.3 1991/08/01 23:59:06 steve
# *** empty log message ***
#
# Revision 1.2 1991/07/16 00:31:15 steve

View File

@ -3,13 +3,11 @@
BFD supplies symbols to be indirected with the BFD_INDIRECT bit
set. Whenever the linker gets one of these, it calls add_indirect
with the symbol. We create an entry into the ldsym hash table as if it
were a normal symbol, but with the SYM_INDIRECT bit set in the
flags.
When it comes time to tie up the symbols at a later date, the flag
will be seen and a call made to do the right thing (tm)
with the symbol. We look up the symbol which this one dereferneces,
and stop if they are the same. If they are not the same, copy all
the information from the current to the dereffed symbol. Set the
indirect bit in the flag. From now on the ldsym_get stuff will
perform the indirection for us, at no charge.
*/
@ -18,41 +16,52 @@
#include "bfd.h"
#include "ld.h"
#include "ldsym.h"
#include "ldmisc.h"
static asymbol **
DEFUN(move_it,(a_list, b_list),
asymbol **a_list AND
asymbol **b_list)
{
asymbol **head = a_list;
asymbol **cursor = head;
if (a_list == 0) return b_list;
if (b_list == 0) return a_list;
while (1) {
asymbol *ptr = cursor[0];
asymbol **next = (asymbol **)(ptr->udata);
if (next == 0) {
ptr->udata = (PTR) b_list;
return head;
}
cursor = next;
}
}
extern ld_config_type config;
void
DEFUN(add_indirect,(ptr),
asymbol **ptr)
{
if (config.relocateable_output == false) {
ldsym_type *sp = ldsym_get((*ptr)->name);
sp->flags |= SYM_INDIRECT;
sp->sdefs_chain = ptr;
}
ldsym_type *lgs = ldsym_get((*ptr)->name);
ldsym_type *new = ldsym_get(((asymbol *)((*ptr)->value))->name);
/* If the mapping has already been done, stop now */
if (lgs == new) return;
lgs->flags |= SYM_INDIRECT;
new->scoms_chain = move_it(new->scoms_chain, lgs->scoms_chain);
lgs->scoms_chain = 0;
new->srefs_chain = move_it(new->srefs_chain, lgs->srefs_chain);
lgs->srefs_chain = 0;
new->sdefs_chain = move_it(new->sdefs_chain, lgs->sdefs_chain);
lgs->sdefs_chain = 0;
lgs->sdefs_chain = (asymbol **)new;
}
void
DEFUN(do_indirect,(ptr),
ldsym_type *ptr)
{
if (config.relocateable_output == false) {
/* Dig out the symbol were indirecting to. It's held in the value
field.
*/
CONST char *name = ((asymbol *)(*(ptr->sdefs_chain))->value)->name;
ldsym_type *new = ldsym_get(name);
/* We have to make a copy of the sdefs_chain item name, since
symbols will be clobbered on writing, and we want to write the
same string twice */
ptr->sdefs_chain[0][0] = new->sdefs_chain[0][0];
ptr->sdefs_chain[0][0].name = name;
}
}

View File

@ -26,9 +26,40 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
Written by Steve Chamberlain steve@cygnus.com
All symbol handling for the linker
*/
We keep a hash table of global symbols. Each entry in a hash table
is called an ldsym_type. Each has three chains; a pointer to a
chain of definitions for the symbol (hopefully one long), a pointer
to a chain of references to the symbol, and a pointer to a chain of
common symbols. Each pointer points into the canonical symbol table
provided by bfd, each one of which points to an asymbol. Duringing
linkage, the linker uses the udata field to point to the next entry
in a canonical table....
ld_sym
| |
+----------+ +----------+
| defs | a canonical symbol table
+----------+ +----------+
| refs | -----> | one entry| -----> asymbol
+----------+ +----------+ | |
| coms | | | +---------+
+----------+ +----------+ | udata |-----> another canonical symbol
+---------+
It is very simple to make all the symbol pointers point to the same
definition - just run down the chain and make the asymbols pointers
within the canonical table point to the asymbol attacthed to the
definition of the symbol.
*/
#include "sysdep.h"
#include "bfd.h"
@ -61,12 +92,15 @@ extern boolean option_longmap ;
static ldsym_type *global_symbol_hash_table[TABSIZE];
/* Compute the hash code for symbol name KEY. */
static
#ifdef __GNUC__
inline
#endif
int
hash_string (key)
char *key;
DEFUN(hash_string,(key),
CONST char *key)
{
register char *cp;
register CONST char *cp;
register int k;
cp = key;
@ -77,6 +111,28 @@ hash_string (key)
return k;
}
static
#ifdef __GNUC__
inline
#endif ldsym_type *bp;
ldsym_type *
DEFUN(search,(key,hashval) ,
CONST char *key AND
int hashval)
{
ldsym_type *bp;
for (bp = global_symbol_hash_table[hashval]; bp; bp = bp->link)
if (! strcmp (key, bp->name)) {
if (bp->flags & SYM_INDIRECT) {
/* Use the symbol we're aliased to instead */
return (ldsym_type *)(bp->sdefs_chain);
}
return bp;
}
return 0;
}
/* Get the symbol table entry for the global symbol named KEY.
Create one if there is none. */
ldsym_type *
@ -91,10 +147,10 @@ DEFUN(ldsym_get,(key),
hashval = hash_string (key) % TABSIZE;
/* Search the bucket. */
for (bp = global_symbol_hash_table[hashval]; bp; bp = bp->link)
if (! strcmp (key, bp->name))
return bp;
bp = search(key, hashval);
if(bp) {
return bp;
}
/* Nothing was found; create a new symbol table entry. */
@ -132,12 +188,7 @@ DEFUN(ldsym_get_soft,(key),
hashval = hash_string (key) % TABSIZE;
/* Search the bucket. */
for (bp = global_symbol_hash_table[hashval]; bp; bp = bp->link)
if (! strcmp (key, bp->name))
return bp;
return 0;
return search(key, hashval);
}
@ -214,6 +265,11 @@ ldsym_print_symbol_table ()
for (sp = symbol_head; sp; sp = sp->next)
{
if (sp->flags & SYM_INDIRECT) {
fprintf(stdout,"indirect %s to %s\n",
sp->name, (((ldsym_type *)(sp->sdefs_chain))->name));
}
else {
if (sp->sdefs_chain)
{
asymbol *defsym = *(sp->sdefs_chain);
@ -247,7 +303,9 @@ ldsym_print_symbol_table ()
else {
printf("undefined ");
printf("%s ",sp->name);
}
}
print_nl();
}
@ -352,7 +410,7 @@ asymbol **symbol_table;
{
FOR_EACH_LDSYM(sp)
{
if (sp->sdefs_chain != (asymbol **)NULL) {
if ((sp->flags & SYM_INDIRECT) == 0 && sp->sdefs_chain != (asymbol **)NULL) {
asymbol *bufp = (*(sp->sdefs_chain));
if ((bufp->flags & BSF_KEEP) ==0) {