* libelf.h (struct elf_link_hash_table): Add needed field. Remove

saw_needed field.
	* elfcode.h (elf_link_add_object_symbols): If elf_dt_needed_name
	is an empty string, don't make a DT_NEEDED entry in the output
	file.  Record all DT_NEEDED entries found in input dynamic
	objects.
	(elf_link_output_extsym): Don't check saw_needed when issuing
	warnings.
	* elf.c (_bfd_elf_link_hash_table_init): Initialize needed, not
	saw_needed.
	(bfd_elf_get_needed_list): New function.
	* bfd-in.h (struct bfd_elf_link_needed_list): Define.
	(bfd_elf_get_needed_list): Define.
	* bfd-in2.h: Rebuild.
PR 7083.
This commit is contained in:
Ian Lance Taylor 1995-07-04 16:54:49 +00:00
parent 194fc93542
commit b176e1e92a
6 changed files with 182 additions and 76 deletions

View File

@ -1,5 +1,20 @@
Tue Jul 4 12:22:21 1995 Ian Lance Taylor <ian@cygnus.com>
* libelf.h (struct elf_link_hash_table): Add needed field. Remove
saw_needed field.
* elfcode.h (elf_link_add_object_symbols): If elf_dt_needed_name
is an empty string, don't make a DT_NEEDED entry in the output
file. Record all DT_NEEDED entries found in input dynamic
objects.
(elf_link_output_extsym): Don't check saw_needed when issuing
warnings.
* elf.c (_bfd_elf_link_hash_table_init): Initialize needed, not
saw_needed.
(bfd_elf_get_needed_list): New function.
* bfd-in.h (struct bfd_elf_link_needed_list): Define.
(bfd_elf_get_needed_list): Define.
* bfd-in2.h: Rebuild.
* ecoff.c (_bfd_ecoff_find_nearest_line): Also initialize
find_buffer and fdrtab_len fields of newly allocated
find_line_info structure.

View File

@ -482,6 +482,9 @@ typedef struct _bfd_link_stack_heap bfd_link_stack_heap;
/* END OF PE STUFF */
extern enum bfd_link_subsystem NT_subsystem;
extern bfd_link_stack_heap NT_stack_heap;
/* Cast from const char * to char * so that caller can assign to
a char * without a warning. */
#define bfd_get_filename(abfd) ((char *) (abfd)->filename)
@ -592,6 +595,14 @@ extern boolean bfd_elf32_record_link_assignment
PARAMS ((bfd *, struct bfd_link_info *, const char *));
extern boolean bfd_elf64_record_link_assignment
PARAMS ((bfd *, struct bfd_link_info *, const char *));
struct bfd_elf_link_needed_list
{
struct bfd_elf_link_needed_list *next;
bfd *by;
const char *name;
};
extern struct bfd_elf_link_needed_list *bfd_elf_get_needed_list
PARAMS ((bfd *, struct bfd_link_info *));
extern boolean bfd_elf32_size_dynamic_sections
PARAMS ((bfd *, const char *, const char *, boolean,
struct bfd_link_info *, struct sec **));
@ -614,11 +625,3 @@ extern boolean bfd_linux_size_dynamic_sections
PARAMS ((bfd *, struct bfd_link_info *));
/* And more from the source. */
/* provide storage for subsystem, stack and heap data which may have been
passed in on the command line. Ld puts this data into a bfd_link_info
struct which ultimately gets passed in to the bfd. When it arrives, copy
it to the following struct so that the data will be available in coffcode.h
where it is needed. The typedef's used are defined in bfd.h */
enum bfd_link_subsystem NT_subsystem;
bfd_link_stack_heap NT_stack_heap;

View File

@ -595,6 +595,14 @@ extern boolean bfd_elf32_record_link_assignment
PARAMS ((bfd *, struct bfd_link_info *, const char *));
extern boolean bfd_elf64_record_link_assignment
PARAMS ((bfd *, struct bfd_link_info *, const char *));
struct bfd_elf_link_needed_list
{
struct bfd_elf_link_needed_list *next;
bfd *by;
const char *name;
};
extern struct bfd_elf_link_needed_list *bfd_elf_get_needed_list
PARAMS ((bfd *, struct bfd_link_info *));
extern boolean bfd_elf32_size_dynamic_sections
PARAMS ((bfd *, const char *, const char *, boolean,
struct bfd_link_info *, struct sec **));

View File

@ -122,14 +122,14 @@ elf_get_str_section (abfd, shindex)
if (i_shdrp == 0 || i_shdrp[shindex] == 0)
return 0;
shstrtab = i_shdrp[shindex]->rawdata;
shstrtab = (char *) i_shdrp[shindex]->contents;
if (shstrtab == NULL)
{
/* No cached one, attempt to read, and cache what we read. */
offset = i_shdrp[shindex]->sh_offset;
shstrtabsize = i_shdrp[shindex]->sh_size;
shstrtab = elf_read (abfd, offset, shstrtabsize);
i_shdrp[shindex]->rawdata = (void *) shstrtab;
i_shdrp[shindex]->contents = (PTR) shstrtab;
}
return shstrtab;
}
@ -147,15 +147,15 @@ elf_string_from_elf_section (abfd, shindex, strindex)
hdr = elf_elfsections (abfd)[shindex];
if (!hdr->rawdata
if (hdr->contents == NULL
&& elf_get_str_section (abfd, shindex) == NULL)
return NULL;
return ((char *) hdr->rawdata) + strindex;
return ((char *) hdr->contents) + strindex;
}
/* Make a BFD section from an ELF section. We store a pointer to the
BFD section in the rawdata field of the header. */
BFD section in the bfd_section field of the header. */
boolean
_bfd_elf_make_section_from_shdr (abfd, hdr, name)
@ -166,9 +166,10 @@ _bfd_elf_make_section_from_shdr (abfd, hdr, name)
asection *newsect;
flagword flags;
if (hdr->rawdata != NULL)
if (hdr->bfd_section != NULL)
{
BFD_ASSERT (strcmp (name, ((asection *) hdr->rawdata)->name) == 0);
BFD_ASSERT (strcmp (name,
bfd_get_section_name (abfd, hdr->bfd_section)) == 0);
return true;
}
@ -210,7 +211,7 @@ _bfd_elf_make_section_from_shdr (abfd, hdr, name)
if (! bfd_set_section_flags (abfd, newsect, flags))
return false;
hdr->rawdata = (PTR) newsect;
hdr->bfd_section = newsect;
elf_section_data (newsect)->this_hdr = *hdr;
return true;
@ -301,6 +302,45 @@ bfd_elf_generic_reloc (abfd,
return bfd_reloc_continue;
}
/* Display ELF-specific fields of a symbol. */
void
bfd_elf_print_symbol (ignore_abfd, filep, symbol, how)
bfd *ignore_abfd;
PTR filep;
asymbol *symbol;
bfd_print_symbol_type how;
{
FILE *file = (FILE *) filep;
switch (how)
{
case bfd_print_symbol_name:
fprintf (file, "%s", symbol->name);
break;
case bfd_print_symbol_more:
fprintf (file, "elf ");
fprintf_vma (file, symbol->value);
fprintf (file, " %lx", (long) symbol->flags);
break;
case bfd_print_symbol_all:
{
CONST char *section_name;
section_name = symbol->section ? symbol->section->name : "(*none*)";
bfd_print_symbol_vandf ((PTR) file, symbol);
fprintf (file, " %s\t", section_name);
/* Print the "other" value for a symbol. For common symbols,
we've already printed the size; now print the alignment.
For other symbols, we have no specified alignment, and
we've printed the address; now print the size. */
fprintf_vma (file,
(bfd_is_com_section (symbol->section)
? ((elf_symbol_type *) symbol)->internal_elf_sym.st_value
: ((elf_symbol_type *) symbol)->internal_elf_sym.st_size));
fprintf (file, " %s", symbol->name);
}
break;
}
}
/* Create an entry in an ELF linker hash table. */
struct bfd_hash_entry *
@ -334,7 +374,8 @@ _bfd_elf_link_hash_newfunc (entry, table, string)
ret->dynindx = -1;
ret->dynstr_index = 0;
ret->weakdef = NULL;
ret->copy_offset = 0;
ret->got_offset = (bfd_vma) -1;
ret->plt_offset = (bfd_vma) -1;
ret->type = STT_NOTYPE;
ret->elf_link_hash_flags = 0;
}
@ -352,10 +393,13 @@ _bfd_elf_link_hash_table_init (table, abfd, newfunc)
struct bfd_hash_table *,
const char *));
{
table->dynamic_sections_created = false;
table->dynobj = NULL;
table->dynsymcount = 0;
/* The first dynamic symbol is a dummy. */
table->dynsymcount = 1;
table->dynstr = NULL;
table->bucketcount = 0;
table->needed = NULL;
return _bfd_link_hash_table_init (&table->root, abfd, newfunc);
}
@ -386,7 +430,8 @@ _bfd_elf_link_hash_table_create (abfd)
/* This is a hook for the ELF emulation code in the generic linker to
tell the backend linker what file name to use for the DT_NEEDED
entry for a dynamic object. */
entry for a dynamic object. The generic linker passes name as an
empty string to indicate that no DT_NEEDED entry should be made. */
void
bfd_elf_set_dt_needed_name (abfd, name)
@ -395,3 +440,13 @@ bfd_elf_set_dt_needed_name (abfd, name)
{
elf_dt_needed_name (abfd) = name;
}
/* Get the list of DT_NEEDED entries for a link. */
struct bfd_elf_link_needed_list *
bfd_elf_get_needed_list (abfd, info)
bfd *abfd;
struct bfd_link_info *info;
{
return elf_hash_table (info)->needed;
}

View File

@ -4297,6 +4297,7 @@ elf_link_add_object_symbols (abfd, info)
else
{
asection *s;
boolean add_needed;
const char *name;
bfd_size_type oldsize;
bfd_size_type strindex;
@ -4317,15 +4318,24 @@ elf_link_add_object_symbols (abfd, info)
object. If the object has a DT_SONAME entry, we use it.
Otherwise, if the generic linker stuck something in
elf_dt_needed_name, we use that. Otherwise, we just use the
file name. */
file name. If the generic linker put a null string into
elf_dt_needed_name, we don't make a DT_NEEDED entry at all,
even if there is a DT_SONAME entry. */
add_needed = true;
name = bfd_get_filename (abfd);
if (elf_dt_needed_name (abfd) != NULL)
name = elf_dt_needed_name (abfd);
{
name = elf_dt_needed_name (abfd);
if (*name == '\0')
add_needed = false;
}
s = bfd_get_section_by_name (abfd, ".dynamic");
if (s != NULL)
{
Elf_External_Dyn *extdyn;
Elf_External_Dyn *extdynend;
int elfsec;
unsigned long link;
dynbuf = (Elf_External_Dyn *) malloc (s->_raw_size);
if (dynbuf == NULL)
@ -4338,6 +4348,11 @@ elf_link_add_object_symbols (abfd, info)
(file_ptr) 0, s->_raw_size))
goto error_return;
elfsec = elf_section_from_bfd_section (abfd, s);
if (elfsec == -1)
goto error_return;
link = elf_elfsections (abfd)[elfsec]->sh_link;
extdyn = dynbuf;
extdynend = extdyn + s->_raw_size / sizeof (Elf_External_Dyn);
for (; extdyn < extdynend; extdyn++)
@ -4345,22 +4360,37 @@ elf_link_add_object_symbols (abfd, info)
Elf_Internal_Dyn dyn;
elf_swap_dyn_in (abfd, extdyn, &dyn);
if (dyn.d_tag == DT_SONAME)
if (add_needed && dyn.d_tag == DT_SONAME)
{
int elfsec;
unsigned long link;
elfsec = elf_section_from_bfd_section (abfd, s);
if (elfsec == -1)
goto error_return;
link = elf_elfsections (abfd)[elfsec]->sh_link;
name = elf_string_from_elf_section (abfd, link,
dyn.d_un.d_val);
if (name == NULL)
goto error_return;
}
if (dyn.d_tag == DT_NEEDED)
elf_hash_table (info)->saw_needed = true;
{
struct bfd_elf_link_needed_list *n, **pn;
char *fnm, *anm;
n = bfd_alloc (abfd,
sizeof (struct bfd_elf_link_needed_list));
fnm = elf_string_from_elf_section (abfd, link,
dyn.d_un.d_val);
if (n == NULL || fnm == NULL)
goto error_return;
anm = bfd_alloc (abfd, strlen (fnm) + 1);
if (anm == NULL)
goto error_return;
strcpy (anm, fnm);
n->name = anm;
n->by = abfd;
n->next = NULL;
for (pn = &elf_hash_table (info)->needed;
*pn != NULL;
pn = &(*pn)->next)
;
*pn = n;
}
}
free (dynbuf);
@ -4384,46 +4414,51 @@ elf_link_add_object_symbols (abfd, info)
goto error_return;
}
/* Add a DT_NEEDED entry for this dynamic object. */
oldsize = _bfd_stringtab_size (elf_hash_table (info)->dynstr);
strindex = _bfd_stringtab_add (elf_hash_table (info)->dynstr, name,
true, false);
if (strindex == (bfd_size_type) -1)
goto error_return;
if (oldsize == _bfd_stringtab_size (elf_hash_table (info)->dynstr))
if (add_needed)
{
asection *sdyn;
Elf_External_Dyn *dyncon, *dynconend;
/* Add a DT_NEEDED entry for this dynamic object. */
oldsize = _bfd_stringtab_size (elf_hash_table (info)->dynstr);
strindex = _bfd_stringtab_add (elf_hash_table (info)->dynstr, name,
true, false);
if (strindex == (bfd_size_type) -1)
goto error_return;
/* The hash table size did not change, which means that the
dynamic object name was already entered. If we have
already included this dynamic object in the link, just
ignore it. There is no reason to include a particular
dynamic object more than once. */
sdyn = bfd_get_section_by_name (elf_hash_table (info)->dynobj,
".dynamic");
BFD_ASSERT (sdyn != NULL);
dyncon = (Elf_External_Dyn *) sdyn->contents;
dynconend = (Elf_External_Dyn *) (sdyn->contents + sdyn->_raw_size);
for (; dyncon < dynconend; dyncon++)
if (oldsize == _bfd_stringtab_size (elf_hash_table (info)->dynstr))
{
Elf_Internal_Dyn dyn;
asection *sdyn;
Elf_External_Dyn *dyncon, *dynconend;
elf_swap_dyn_in (elf_hash_table (info)->dynobj, dyncon, &dyn);
if (dyn.d_tag == DT_NEEDED
&& dyn.d_un.d_val == strindex)
/* The hash table size did not change, which means that
the dynamic object name was already entered. If we
have already included this dynamic object in the
link, just ignore it. There is no reason to include
a particular dynamic object more than once. */
sdyn = bfd_get_section_by_name (elf_hash_table (info)->dynobj,
".dynamic");
BFD_ASSERT (sdyn != NULL);
dyncon = (Elf_External_Dyn *) sdyn->contents;
dynconend = (Elf_External_Dyn *) (sdyn->contents +
sdyn->_raw_size);
for (; dyncon < dynconend; dyncon++)
{
if (buf != NULL)
free (buf);
return true;
Elf_Internal_Dyn dyn;
elf_swap_dyn_in (elf_hash_table (info)->dynobj, dyncon,
&dyn);
if (dyn.d_tag == DT_NEEDED
&& dyn.d_un.d_val == strindex)
{
if (buf != NULL)
free (buf);
return true;
}
}
}
}
if (! elf_add_dynamic_entry (info, DT_NEEDED, strindex))
goto error_return;
if (! elf_add_dynamic_entry (info, DT_NEEDED, strindex))
goto error_return;
}
}
if (bfd_seek (abfd,
@ -6237,18 +6272,9 @@ elf_link_output_extsym (h, data)
linker will complain that the symbol is undefined when the
program is run. We don't have to worry about symbols that are
referenced by regular files, because we will already have issued
warnings for them.
FIXME: If we are linking against an object which uses DT_NEEDED,
we don't give this warning, because it might be the case that the
needed dynamic object will define the symbols. Unfortunately,
this makes this type of check much less useful, but the only way
to fix it would be to locate the needed object and read its
symbol table. That seems like a real waste of time just to give
better error messages. */
warnings for them. */
if (! finfo->info->relocateable
&& ! finfo->info->shared
&& ! elf_hash_table (finfo->info)->saw_needed
&& h->root.type == bfd_link_hash_undefined
&& (h->elf_link_hash_flags & ELF_LINK_HASH_REF_DYNAMIC) != 0
&& (h->elf_link_hash_flags & ELF_LINK_HASH_REF_REGULAR) == 0)

View File

@ -144,10 +144,9 @@ struct elf_link_hash_table
/* The number of buckets in the hash table in the .hash section.
This is based on the number of dynamic symbols. */
size_t bucketcount;
/* Whether we are linking against a dynamic object which has a
DT_NEEDED entry in the .dynamic section. This may need to become
a list of DT_NEEDED entries. */
boolean saw_needed;
/* A linked list of DT_NEEDED names found in dynamic objects
included in the link. */
struct bfd_elf_link_needed_list *needed;
};
/* Look up an entry in an ELF linker hash table. */