mirror of
https://github.com/bminor/binutils-gdb.git
synced 2025-12-27 09:38:57 +00:00
Patches to fix bugs reported by roland McGrath
This commit is contained in:
81
ld/ldindr.c
81
ld/ldindr.c
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user