diff options
Diffstat (limited to 'bfd/elflink.c')
-rw-r--r-- | bfd/elflink.c | 47 |
1 files changed, 42 insertions, 5 deletions
diff --git a/bfd/elflink.c b/bfd/elflink.c index c42c6e135bd..f8029b0c384 100644 --- a/bfd/elflink.c +++ b/bfd/elflink.c @@ -3234,6 +3234,8 @@ elf_finalize_dynstr (bfd *output_bfd, struct bfd_link_info *info) case DT_RUNPATH: case DT_FILTER: case DT_AUXILIARY: + case DT_AUDIT: + case DT_DEPAUDIT: dyn.d_un.d_val = _bfd_elf_strtab_offset (dynstr, dyn.d_un.d_val); break; default: @@ -3525,6 +3527,7 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info) { asection *s; const char *soname = NULL; + char *audit = NULL; struct bfd_link_needed_list *rpath = NULL, *runpath = NULL; int ret; @@ -3653,6 +3656,11 @@ error_free_dyn: ; *pn = n; } + if (dyn.d_tag == DT_AUDIT) + { + unsigned int tagv = dyn.d_un.d_val; + audit = bfd_elf_string_from_elf_section (abfd, shlink, tagv); + } } free (dynbuf); @@ -3705,6 +3713,9 @@ error_free_dyn: particular dynamic object more than once. */ if (ret > 0) return TRUE; + + /* Save the DT_AUDIT entry for the linker emulation code. */ + elf_dt_audit (abfd) = audit; } /* If this is a dynamic object, we always link against the .dynsym @@ -5451,6 +5462,8 @@ bfd_elf_size_dynamic_sections (bfd *output_bfd, const char *soname, const char *rpath, const char *filter_shlib, + const char *audit, + const char *depaudit, const char * const *auxiliary_filters, struct bfd_link_info *info, asection **sinterpptr, @@ -5603,6 +5616,28 @@ bfd_elf_size_dynamic_sections (bfd *output_bfd, } } + if (audit != NULL) + { + bfd_size_type indx; + + indx = _bfd_elf_strtab_add (elf_hash_table (info)->dynstr, audit, + TRUE); + if (indx == (bfd_size_type) -1 + || !_bfd_elf_add_dynamic_entry (info, DT_AUDIT, indx)) + return FALSE; + } + + if (depaudit != NULL) + { + bfd_size_type indx; + + indx = _bfd_elf_strtab_add (elf_hash_table (info)->dynstr, depaudit, + TRUE); + if (indx == (bfd_size_type) -1 + || !_bfd_elf_add_dynamic_entry (info, DT_DEPAUDIT, indx)) + return FALSE; + } + eif.info = info; eif.verdefs = verdefs; eif.failed = FALSE; @@ -8597,7 +8632,11 @@ elf_link_output_extsym (struct elf_link_hash_entry *h, void *data) sym.st_size = h->size; sym.st_other = h->other; if (h->forced_local) - sym.st_info = ELF_ST_INFO (STB_LOCAL, h->type); + { + sym.st_info = ELF_ST_INFO (STB_LOCAL, h->type); + /* Turn off visibility on local symbol. */ + sym.st_other &= ~ELF_ST_VISIBILITY (-1); + } else if (h->unique_global) sym.st_info = ELF_ST_INFO (STB_GNU_UNIQUE, h->type); else if (h->root.type == bfd_link_hash_undefweak @@ -10669,13 +10708,11 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info) asection *s; bfd_byte *dest; - sym.st_size = e->isym.st_size; - sym.st_other = e->isym.st_other; - - /* Copy the internal symbol as is. + /* Copy the internal symbol and turn off visibility. Note that we saved a word of storage and overwrote the original st_name with the dynstr_index. */ sym = e->isym; + sym.st_other &= ~ELF_ST_VISIBILITY (-1); s = bfd_section_from_elf_index (e->input_bfd, e->isym.st_shndx); |