clean ppc/ppc64 handling.
%{_libdir}/libelf.so
%changelog
+* Wed Aug 10 2005 Ulrich Drepper <@redhat.com> 0.113-1
+- elflint: relax a bit. Allow version definitions for defined symbols ag
+ainstDSO versions also for symbols in nobits sections. Allow .rodata
+sectionto have STRINGS and MERGE flag set.
+- strip: add some more compatibility with binutils.
+
* Sat Aug 6 2005 Ulrich Drepper <@redhat.com> 0.113-1
- elflint: relax a bit. Allow version definitions for defined symbols ag
ainstDSO versions also for symbols in nobits sections. Allow .rodata
+2005-08-13 Ulrich Drepper <drepper@redhat.com>
+
+ * libebl.h: Add ehdr parameter to ebl_bss_plt_p and
+ ebl_check_special_symbol.
+ * libeblP.h (struct ebl): Adjust callback functions.
+ * eblopenbackend.c: Adjust dummy functions.
+ * ebl_check_special_symbol.c: Add parameter and pass it on.
+ * eblbsspltp.c: Likewise.
+ * ppc_symbol.c (find_dyn_got): With ehdr passed, simplify search for
+ the dynamic section entry.
+ (ppc_check_special_symbol): Add ehdr parameter.
+ (ppc_bss_plt_p): Likewise.
+ * libebl_ppc.h: Adjust prototypes.
+ * ppc64_symbol.c (ppc_check_special_symbol): Add ehdr parameter.
+ (ppc_bss_plt_p): Likewise.
+ * libebl_ppc64.h: Adjust prototypes.
+
2005-08-12 Roland McGrath <roland@redhat.com>
* ppc_symbol.c (find_dyn_got): New function, broken out of ...
bool
-ebl_check_special_symbol (ebl, sym, name, destshdr)
+ebl_check_special_symbol (ebl, ehdr, sym, name, destshdr)
Ebl *ebl;
+ GElf_Ehdr *ehdr;
const GElf_Sym *sym;
const char *name;
const GElf_Shdr *destshdr;
if (ebl == NULL)
return false;
- return ebl->check_special_symbol (ebl->elf, sym, name, destshdr);
+ return ebl->check_special_symbol (ebl->elf, ehdr, sym, name, destshdr);
}
bool
-ebl_bss_plt_p (ebl)
+ebl_bss_plt_p (ebl, ehdr)
Ebl *ebl;
+ GElf_Ehdr *ehdr;
{
- return ebl == NULL ? false : ebl->bss_plt_p (ebl->elf);
+ return ebl == NULL ? false : ebl->bss_plt_p (ebl->elf, ehdr);
}
uint32_t descsz, const char *desc);
static bool default_debugscn_p (const char *name);
static bool default_copy_reloc_p (int reloc);
-static bool default_check_special_symbol (Elf *elf,
+static bool default_check_special_symbol (Elf *elf, GElf_Ehdr *ehdr,
const GElf_Sym *sym,
const char *name,
const GElf_Shdr *destshdr);
-static bool default_bss_plt_p (Elf *elf);
+static bool default_bss_plt_p (Elf *elf, GElf_Ehdr *ehdr);
static void
static bool
default_check_special_symbol (Elf *elf __attribute__ ((unused)),
+ GElf_Ehdr *ehdr __attribute__ ((unused)),
const GElf_Sym *sym __attribute__ ((unused)),
const char *name __attribute__ ((unused)),
const GElf_Shdr *destshdr __attribute__ ((unused)))
}
static bool
-default_bss_plt_p (Elf *elf __attribute__ ((unused)))
+default_bss_plt_p (Elf *elf __attribute__ ((unused)),
+ GElf_Ehdr *ehdr __attribute__ ((unused)))
{
return false;
}
/* Check whether given symbol's st_value and st_size are OK despite failing
normal checks. */
-extern bool ebl_check_special_symbol (Ebl *ebl,
+extern bool ebl_check_special_symbol (Ebl *ebl, GElf_Ehdr *ehdr,
const GElf_Sym *sym, const char *name,
const GElf_Shdr *destshdr);
bool remove_comment, bool only_remove_debug);
/* Check if backend uses a bss PLT in this file. */
-extern bool ebl_bss_plt_p (Ebl *ebl);
+extern bool ebl_bss_plt_p (Ebl *ebl, GElf_Ehdr *ehdr);
/* ELF string table handling. */
bool (*copy_reloc_p) (int);
/* Check whether given symbol's value is ok despite normal checks. */
- bool (*check_special_symbol) (Elf *elf,
- const GElf_Sym *sym, const char *name,
- const GElf_Shdr *destshdr);
+ bool (*check_special_symbol) (Elf *, GElf_Ehdr *, const GElf_Sym *,
+ const char *, const GElf_Shdr *);
/* Check if backend uses a bss PLT in this file. */
- bool (*bss_plt_p) (Elf *elf);
+ bool (*bss_plt_p) (Elf *, GElf_Ehdr *);
/* Destructor for ELF backend handle. */
void (*destr) (struct ebl *);
/* Check whether given symbol's st_value and st_size are OK despite normal
checks. */
-extern bool ppc_check_special_symbol (Elf *elf,
+extern bool ppc_check_special_symbol (Elf *elf, GElf_Ehdr *ehdr,
const GElf_Sym *sym, const char *name,
const GElf_Shdr *destshdr);
/* Check if backend uses a bss PLT in this file. */
-extern bool ppc_bss_plt_p (Elf *elf);
+extern bool ppc_bss_plt_p (Elf *elf, GElf_Ehdr *ehdr);
#endif /* libebl_ppc.h */
/* Check whether given symbol's st_value and st_size are OK despite normal
checks. */
-extern bool ppc64_check_special_symbol (Elf *elf,
+extern bool ppc64_check_special_symbol (Elf *elf, GElf_Ehdr *ehdr,
const GElf_Sym *sym, const char *name,
const GElf_Shdr *destshdr);
/* Check if backend uses a bss PLT in this file. */
-extern bool ppc64_bss_plt_p (Elf *elf);
+extern bool ppc64_bss_plt_p (Elf *elf, GElf_Ehdr *ehdr);
#endif /* libebl_ppc.h */
return NULL;
}
+
bool
ppc64_dynamic_tag_check (int64_t tag)
{
/* Check whether given symbol's st_value and st_size are OK despite failing
normal checks. */
bool
-ppc64_check_special_symbol (Elf *elf,
+ppc64_check_special_symbol (Elf *elf, GElf_Ehdr *ehdr,
const GElf_Sym *sym __attribute__ ((unused)),
const char *name __attribute__ ((unused)),
const GElf_Shdr *destshdr)
{
- GElf_Ehdr ehdr_mem;
- GElf_Ehdr *ehdr = gelf_getehdr (elf, &ehdr_mem);
- if (ehdr == NULL)
- return false;
const char *sname = elf_strptr (elf, ehdr->e_shstrndx, destshdr->sh_name);
if (sname == NULL)
return false;
- return !strcmp (sname, ".opd");
+ return strcmp (sname, ".opd") == 0;
}
+
/* Check if backend uses a bss PLT in this file. */
bool
-ppc64_bss_plt_p (Elf *elf __attribute__ ((unused)))
+ppc64_bss_plt_p (Elf *elf __attribute__ ((unused)),
+ GElf_Ehdr *ehdr __attribute__ ((unused)))
{
return true;
}
return reloc == R_PPC_COPY;
}
+
/* Look for DT_PPC_GOT. */
static bool
-find_dyn_got (Elf *elf, GElf_Addr *addr)
+find_dyn_got (Elf *elf, GElf_Ehdr *ehdr, GElf_Addr *addr)
{
- Elf_Scn *scn = NULL;
- while ((scn = elf_nextscn (elf, scn)) != NULL)
+ for (int i = 0; i < ehdr->e_phnum; ++i)
{
+ GElf_Phdr phdr_mem;
+ GElf_Phdr *phdr = gelf_getphdr (elf, i, &phdr_mem);
+ if (phdr == NULL || phdr->p_type != PT_DYNAMIC)
+ continue;
+
+ Elf_Scn *scn = gelf_offscn (elf, phdr->p_offset);
GElf_Shdr shdr_mem;
GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
- if (shdr != NULL && shdr->sh_type == SHT_DYNAMIC)
- {
- Elf_Data *data = elf_getdata (scn, NULL);
- if (data == NULL)
- break;
- for (unsigned int i = 0; i < shdr->sh_size / shdr->sh_entsize; ++i)
- {
- GElf_Dyn dyn_mem;
- GElf_Dyn *dyn = gelf_getdyn (data, i, &dyn_mem);
- if (dyn == NULL)
- break;
- if (dyn->d_tag == DT_PPC_GOT)
- {
- *addr = dyn->d_un.d_ptr;
- return true;
- }
- }
- }
+ Elf_Data *data = elf_getdata (scn, NULL);
+ if (shdr != NULL && shdr->sh_type == SHT_DYNAMIC && data != NULL)
+ for (unsigned int j = 0; j < shdr->sh_size / shdr->sh_entsize; ++j)
+ {
+ GElf_Dyn dyn_mem;
+ GElf_Dyn *dyn = gelf_getdyn (data, j, &dyn_mem);
+ if (dyn != NULL && dyn->d_tag == DT_PPC_GOT)
+ {
+ *addr = dyn->d_un.d_ptr;
+ return true;
+ }
+ }
+
+ /* There is only one PT_DYNAMIC entry. */
+ break;
}
return false;
}
+
/* Check whether given symbol's st_value and st_size are OK despite failing
normal checks. */
bool
-ppc_check_special_symbol (Elf *elf,
- const GElf_Sym *sym,
- const char *name,
- const GElf_Shdr *destshdr)
+ppc_check_special_symbol (Elf *elf, GElf_Ehdr *ehdr, const GElf_Sym *sym,
+ const char *name, const GElf_Shdr *destshdr)
{
if (name == NULL)
return false;
- if (!strcmp (name, "_GLOBAL_OFFSET_TABLE_"))
+ if (strcmp (name, "_GLOBAL_OFFSET_TABLE_") == 0)
{
GElf_Addr gotaddr;
- if (find_dyn_got (elf, &gotaddr))
+ if (find_dyn_got (elf, ehdr, &gotaddr))
return sym->st_value == gotaddr;
return sym->st_value == destshdr->sh_addr + 4;
}
- GElf_Ehdr ehdr_mem;
- GElf_Ehdr *ehdr = gelf_getehdr (elf, &ehdr_mem);
- if (ehdr == NULL)
- return false;
const char *sname = elf_strptr (elf, ehdr->e_shstrndx, destshdr->sh_name);
if (sname == NULL)
return false;
- if (!strcmp (name, "_SDA_BASE_"))
- return (!strcmp (sname, ".sdata")
+ if (strcmp (name, "_SDA_BASE_") == 0)
+ return (strcmp (sname, ".sdata") == 0
&& sym->st_value == destshdr->sh_addr + 0x8000
&& sym->st_size == 0);
- if (!strcmp (name, "_SDA2_BASE_"))
- return (!strcmp (sname, ".sdata2")
+ if (strcmp (name, "_SDA2_BASE_") == 0)
+ return (strcmp (sname, ".sdata2") == 0
&& sym->st_value == destshdr->sh_addr + 0x8000
&& sym->st_size == 0);
return false;
}
+
/* Check if backend uses a bss PLT in this file. */
bool
-ppc_bss_plt_p (Elf *elf)
+ppc_bss_plt_p (Elf *elf, GElf_Ehdr *ehdr)
{
GElf_Addr addr;
- return ! find_dyn_got (elf, &addr);
+ return ! find_dyn_got (elf, ehdr, &addr);
}
+2005-08-13 Ulrich Drepper <drepper@redhat.com>
+
+ * elflint.c (check_symtab): Simplify last change a bit. Pass ehdr
+ to ebl_check_special_symbol.
+ (check_sections): Pass ehdr to ebl_bss_plt_p.
+
2005-08-12 Roland McGrath <roland@redhat.com>
* elflint.c (check_symtab): Check that _GLOBAL_OFFSET_TABLE_ st_shndx
{
if (GELF_ST_TYPE (sym->st_info) != STT_TLS)
{
- bool special = ebl_check_special_symbol (ebl, sym, name,
- destshdr);
- if ((sym->st_value - destshdr->sh_addr) > destshdr->sh_size
- && !special)
- ERROR (gettext ("\
+ if (! ebl_check_special_symbol (ebl, ehdr, sym, name,
+ destshdr))
+ {
+ if ((sym->st_value - destshdr->sh_addr)
+ > destshdr->sh_size)
+ ERROR (gettext ("\
section [%2d] '%s': symbol %zu: st_value out of bounds\n"),
- idx, section_name (ebl, idx), cnt);
- else if ((sym->st_value - destshdr->sh_addr + sym->st_size)
- > destshdr->sh_size
- && !special)
- ERROR (gettext ("\
+ idx, section_name (ebl, idx), cnt);
+ else if ((sym->st_value - destshdr->sh_addr
+ + sym->st_size) > destshdr->sh_size)
+ ERROR (gettext ("\
section [%2d] '%s': symbol %zu does not fit completely in referenced section [%2d] '%s'\n"),
- idx, section_name (ebl, idx), cnt,
- (int) xndx, section_name (ebl, xndx));
+ idx, section_name (ebl, idx), cnt,
+ (int) xndx, section_name (ebl, xndx));
+ }
}
else
{
if (destshdr == NULL && xndx == SHN_ABS)
{
/* In a DSO, we have to find the GOT section by name. */
-
- Elf_Scn *gscn = NULL;
-
Elf_Scn *gotscn = NULL;
+ Elf_Scn *gscn = NULL;
while ((gscn = elf_nextscn (ebl->elf, gscn)) != NULL)
{
destshdr = gelf_getshdr (gscn, &destshdr_mem);
destshdr->sh_name);
if (sname != NULL)
{
- if (!strcmp (sname, ".got.plt"))
+ if (strcmp (sname, ".got.plt") == 0)
break;
- if (!strcmp (sname, ".got"))
+ if (strcmp (sname, ".got") == 0)
/* Do not stop looking.
There might be a .got.plt section. */
gotscn = gscn;
if (destshdr != NULL)
{
/* Found it. */
-
- bool special = ebl_check_special_symbol (ebl, sym, name,
- destshdr);
-
- if (sym->st_value != destshdr->sh_addr && !special)
- /* This test is more strict than the psABIs which
- usually allow the symbol to be in the middle of
- the .got section, allowing negative offsets. */
- ERROR (gettext ("\
+ if (!ebl_check_special_symbol (ebl, ehdr, sym, name,
+ destshdr))
+ {
+ if (sym->st_value != destshdr->sh_addr)
+ /* This test is more strict than the psABIs which
+ usually allow the symbol to be in the middle of
+ the .got section, allowing negative offsets. */
+ ERROR (gettext ("\
section [%2d] '%s': _GLOBAL_OFFSET_TABLE_ symbol value %#" PRIx64 " does not match %s section address %#" PRIx64 "\n"),
- idx, section_name (ebl, idx),
- (uint64_t) sym->st_value,
- sname, (uint64_t) destshdr->sh_addr);
+ idx, section_name (ebl, idx),
+ (uint64_t) sym->st_value,
+ sname, (uint64_t) destshdr->sh_addr);
- if (!gnuld && sym->st_size != destshdr->sh_size && !special)
- ERROR (gettext ("\
+ if (!gnuld && sym->st_size != destshdr->sh_size)
+ ERROR (gettext ("\
section [%2d] '%s': _GLOBAL_OFFSET_TABLE_ symbol size %" PRIu64 " does not match %s section size %" PRIu64 "\n"),
- idx, section_name (ebl, idx),
- (uint64_t) sym->st_size,
- sname, (uint64_t) destshdr->sh_size);
+ idx, section_name (ebl, idx),
+ (uint64_t) sym->st_size,
+ sname, (uint64_t) destshdr->sh_size);
+ }
}
else
ERROR (gettext ("\
GElf_Word good_type = special_sections[s].type;
if (special_sections[s].namelen == sizeof ".plt" &&
!memcmp (special_sections[s].name, ".plt", sizeof ".plt")
- && ebl_bss_plt_p (ebl))
+ && ebl_bss_plt_p (ebl, ehdr))
good_type = SHT_NOBITS;
if (shdr->sh_type != good_type