From b176e1e92a344be1f241b74f03ee00241bd5cde3 Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Tue, 4 Jul 1995 16:54:49 +0000 Subject: [PATCH] * 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. --- bfd/ChangeLog | 15 ++++++ bfd/bfd-in.h | 19 ++++--- bfd/bfd-in2.h | 8 +++ bfd/elf.c | 77 ++++++++++++++++++++++++---- bfd/elfcode.h | 136 ++++++++++++++++++++++++++++++-------------------- bfd/libelf.h | 7 ++- 6 files changed, 184 insertions(+), 78 deletions(-) diff --git a/bfd/ChangeLog b/bfd/ChangeLog index 2f0c1b71f3f..88de922c335 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,5 +1,20 @@ Tue Jul 4 12:22:21 1995 Ian Lance Taylor + * 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. diff --git a/bfd/bfd-in.h b/bfd/bfd-in.h index 7af736c28db..151e824beea 100644 --- a/bfd/bfd-in.h +++ b/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; diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h index b197e424a8c..1b0ba63f689 100644 --- a/bfd/bfd-in2.h +++ b/bfd/bfd-in2.h @@ -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 **)); diff --git a/bfd/elf.c b/bfd/elf.c index 6fece72e56d..2ff754361ad 100644 --- a/bfd/elf.c +++ b/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; +} diff --git a/bfd/elfcode.h b/bfd/elfcode.h index 2ce8bed4ed2..e0f1b9c1ec2 100644 --- a/bfd/elfcode.h +++ b/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; - - /* 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++) - { - Elf_Internal_Dyn dyn; + /* 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; - elf_swap_dyn_in (elf_hash_table (info)->dynobj, dyncon, &dyn); - if (dyn.d_tag == DT_NEEDED - && dyn.d_un.d_val == strindex) + if (oldsize == _bfd_stringtab_size (elf_hash_table (info)->dynstr)) + { + asection *sdyn; + Elf_External_Dyn *dyncon, *dynconend; + + /* 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) diff --git a/bfd/libelf.h b/bfd/libelf.h index 28b9c9e2347..98d77b2a55e 100644 --- a/bfd/libelf.h +++ b/bfd/libelf.h @@ -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. */ -- 2.30.2