* 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:
parent
194fc93542
commit
b176e1e92a
|
@ -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.
|
||||
|
|
19
bfd/bfd-in.h
19
bfd/bfd-in.h
|
@ -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;
|
||||
|
|
|
@ -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 **));
|
||||
|
|
77
bfd/elf.c
77
bfd/elf.c
|
@ -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;
|
||||
}
|
||||
|
|
132
bfd/elfcode.h
132
bfd/elfcode.h
|
@ -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)
|
||||
|
|
|
@ -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. */
|
||||
|
|
Loading…
Reference in New Issue