Browse Source

bfd/

* bfd-in.h (enum notice_asneeded_action): Define.
	* bfd-in2.h: Regenerate.
	* elflink.c (elf_link_add_object_symbols): Call linker "notice"
	function with NULL name for as-needed handling.
ld/
	* ld.h (handle_asneeded_cref): Declare.
	* ldcref.c: Include objalloc.h.
	(old_table, old_count, old_tab, alloc_mark): New variables.
	(tabsize, entsize, refsize, old_symcount): Likewise.
	(add_cref): Use bfd_hash_allocate for refs.
	(handle_asneeded_cref): New function.
	* ldmain.c (notice): Call handle_asneeded_cref for NULL name.
cr-0x5f1
Alan Modra 20 years ago
parent
commit
5061a8853b
  1. 7
      bfd/ChangeLog
  2. 6
      bfd/bfd-in.h
  3. 6
      bfd/bfd-in2.h
  4. 16
      bfd/elflink.c
  5. 10
      ld/ChangeLog
  6. 3
      ld/ld.h
  7. 134
      ld/ldcref.c
  8. 7
      ld/ldmain.c

7
bfd/ChangeLog

@ -1,3 +1,10 @@
2006-07-19 Alan Modra <amodra@bigpond.net.au>
* bfd-in.h (enum notice_asneeded_action): Define.
* bfd-in2.h: Regenerate.
* elflink.c (elf_link_add_object_symbols): Call linker "notice"
function with NULL name for as-needed handling.
2006-07-18 Paul Brook <paul@codesourcery.com>
* bfd-in2.h: Regenerate.

6
bfd/bfd-in.h

@ -638,6 +638,12 @@ enum dynamic_lib_link_class {
DYN_NO_NEEDED = 8
};
enum notice_asneeded_action {
notice_as_needed,
notice_not_needed,
notice_needed
};
extern bfd_boolean bfd_elf_record_link_assignment
(bfd *, struct bfd_link_info *, const char *, bfd_boolean,
bfd_boolean);

6
bfd/bfd-in2.h

@ -645,6 +645,12 @@ enum dynamic_lib_link_class {
DYN_NO_NEEDED = 8
};
enum notice_asneeded_action {
notice_as_needed,
notice_not_needed,
notice_needed
};
extern bfd_boolean bfd_elf_record_link_assignment
(bfd *, struct bfd_link_info *, const char *, bfd_boolean,
bfd_boolean);

16
bfd/elflink.c

@ -3551,6 +3551,13 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info)
if (alloc_mark == NULL)
goto error_free_vers;
/* Make a special call to the linker "notice" function to
tell it that we are about to handle an as-needed lib. */
if (!(*info->callbacks->notice) (info, NULL, abfd, NULL,
notice_as_needed))
return FALSE;
/* Clone the symbol table and sym hashes. Remember some
pointers into the symbol table, and dynamic symbol count. */
old_hash = (char *) old_tab + tabsize;
@ -4241,6 +4248,12 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info)
}
}
/* Make a special call to the linker "notice" function to
tell it that symbols added for crefs may need to be removed. */
if (!(*info->callbacks->notice) (info, NULL, abfd, NULL,
notice_not_needed))
return FALSE;
free (old_tab);
objalloc_free_block ((struct objalloc *) htab->root.table.memory,
alloc_mark);
@ -4251,6 +4264,9 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info)
if (old_tab != NULL)
{
if (!(*info->callbacks->notice) (info, NULL, abfd, NULL,
notice_needed))
return FALSE;
free (old_tab);
old_tab = NULL;
}

10
ld/ChangeLog

@ -1,3 +1,13 @@
2006-07-19 Alan Modra <amodra@bigpond.net.au>
* ld.h (handle_asneeded_cref): Declare.
* ldcref.c: Include objalloc.h.
(old_table, old_count, old_tab, alloc_mark): New variables.
(tabsize, entsize, refsize, old_symcount): Likewise.
(add_cref): Use bfd_hash_allocate for refs.
(handle_asneeded_cref): New function.
* ldmain.c (notice): Call handle_asneeded_cref for NULL name.
2006-07-14 Michael Wetherell <mike.wetherell@ntlworld.com>
* configure.tgt (i[3-7]86-*-solaris2*, i[3-7]86-*-solaris*): Correct

3
ld/ld.h

@ -1,6 +1,6 @@
/* ld.h -- general linker header file
Copyright 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
2001, 2002, 2003, 2004, 2005
2001, 2002, 2003, 2004, 2005, 2006
Free Software Foundation, Inc.
This file is part of GLD, the Gnu Linker.
@ -288,6 +288,7 @@ extern int parsing_defsym;
extern int yyparse (void);
extern void add_cref (const char *, bfd *, asection *, bfd_vma);
extern bfd_boolean handle_asneeded_cref (bfd *, enum notice_asneeded_action);
extern void output_cref (FILE *);
extern void check_nocrossrefs (void);
extern void ld_abort (const char *, int, const char *) ATTRIBUTE_NORETURN;

134
ld/ldcref.c

@ -27,6 +27,7 @@ Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
#include "sysdep.h"
#include "bfdlink.h"
#include "libiberty.h"
#include "objalloc.h"
#include "ld.h"
#include "ldmain.h"
@ -101,6 +102,16 @@ static bfd_boolean cref_initialized;
static size_t cref_symcount;
/* Used to take a snapshot of the cref hash table when starting to
add syms from an as-needed library. */
static struct bfd_hash_entry **old_table;
static unsigned int old_size;
static unsigned int old_count;
static void *old_tab;
static void *alloc_mark;
static size_t tabsize, entsize, refsize;
static size_t old_symcount;
/* Create an entry in a cref hash table. */
static struct bfd_hash_entry *
@ -165,7 +176,9 @@ add_cref (const char *name,
if (r == NULL)
{
r = xmalloc (sizeof *r);
r = bfd_hash_allocate (&cref_table.root, sizeof *r);
if (r == NULL)
einfo (_("%X%P: cref alloc failed: %E\n"));
r->next = h->refs;
h->refs = r;
r->abfd = abfd;
@ -182,6 +195,125 @@ add_cref (const char *name,
r->def = TRUE;
}
/* Called before loading an as-needed library to take a snapshot of
the cref hash table, and after we have loaded or found that the
library was not needed. */
bfd_boolean
handle_asneeded_cref (bfd *abfd ATTRIBUTE_UNUSED,
enum notice_asneeded_action act)
{
unsigned int i;
if (!cref_initialized)
return TRUE;
if (act == notice_as_needed)
{
char *old_ent, *old_ref;
for (i = 0; i < cref_table.root.size; i++)
{
struct bfd_hash_entry *p;
struct cref_hash_entry *c;
struct cref_ref *r;
for (p = cref_table.root.table[i]; p != NULL; p = p->next)
{
entsize += cref_table.root.entsize;
c = (struct cref_hash_entry *) p;
for (r = c->refs; r != NULL; r = r->next)
refsize += sizeof (struct cref_hash_entry);
}
}
tabsize = cref_table.root.size * sizeof (struct bfd_hash_entry *);
old_tab = xmalloc (tabsize + entsize + refsize);
alloc_mark = bfd_hash_allocate (&cref_table.root, 1);
if (alloc_mark == NULL)
return FALSE;
memcpy (old_tab, cref_table.root.table, tabsize);
old_ent = (char *) old_tab + tabsize;
old_ref = (char *) old_ent + entsize;
old_table = cref_table.root.table;
old_size = cref_table.root.size;
old_count = cref_table.root.count;
old_symcount = cref_symcount;
for (i = 0; i < cref_table.root.size; i++)
{
struct bfd_hash_entry *p;
struct cref_hash_entry *c;
struct cref_ref *r;
for (p = cref_table.root.table[i]; p != NULL; p = p->next)
{
memcpy (old_ent, p, cref_table.root.entsize);
old_ent = (char *) old_ent + cref_table.root.entsize;
c = (struct cref_hash_entry *) p;
for (r = c->refs; r != NULL; r = r->next)
{
memcpy (old_ref, r, sizeof (struct cref_hash_entry));
old_ref = (char *) old_ref + sizeof (struct cref_hash_entry);
}
}
}
return TRUE;
}
if (act == notice_not_needed)
{
char *old_ent, *old_ref;
if (old_tab == NULL)
{
/* The only way old_tab can be NULL is if the cref hash table
had not been initialised when notice_as_needed. */
bfd_hash_table_free (&cref_table.root);
cref_initialized = FALSE;
return TRUE;
}
old_ent = (char *) old_tab + tabsize;
old_ref = (char *) old_ent + entsize;
cref_table.root.table = old_table;
cref_table.root.size = old_size;
cref_table.root.count = old_count;
memcpy (cref_table.root.table, old_tab, tabsize);
cref_symcount = old_symcount;
for (i = 0; i < cref_table.root.size; i++)
{
struct bfd_hash_entry *p;
struct cref_hash_entry *c;
struct cref_ref *r;
for (p = cref_table.root.table[i]; p != NULL; p = p->next)
{
memcpy (p, old_ent, cref_table.root.entsize);
old_ent = (char *) old_ent + cref_table.root.entsize;
c = (struct cref_hash_entry *) p;
for (r = c->refs; r != NULL; r = r->next)
{
memcpy (r, old_ref, sizeof (struct cref_hash_entry));
old_ref = (char *) old_ref + sizeof (struct cref_hash_entry);
}
}
}
objalloc_free_block ((struct objalloc *) cref_table.root.memory,
alloc_mark);
}
else if (act != notice_needed)
return FALSE;
free (old_tab);
old_tab = NULL;
return TRUE;
}
/* Copy the addresses of the hash table entries into an array. This
is called via cref_hash_traverse. We also fill in the demangled
name. */

7
ld/ldmain.c

@ -1523,6 +1523,13 @@ notice (struct bfd_link_info *info,
asection *section,
bfd_vma value)
{
if (name == NULL)
{
if (command_line.cref || nocrossref_list != NULL)
return handle_asneeded_cref (abfd, value);
return TRUE;
}
if (! info->notice_all
|| (info->notice_hash != NULL
&& bfd_hash_lookup (info->notice_hash, name, FALSE, FALSE) != NULL))

Loading…
Cancel
Save