summaryrefslogtreecommitdiffstats
path: root/libebl
diff options
context:
space:
mode:
Diffstat (limited to 'libebl')
-rw-r--r--libebl/ChangeLog28
-rw-r--r--libebl/Makefile.am3
-rw-r--r--libebl/eblopenbackend.c22
-rw-r--r--libebl/libebl.h12
-rw-r--r--libebl/libeblP.h8
-rw-r--r--libebl/libebl_ppc.h10
-rw-r--r--libebl/libebl_ppc64.h10
-rw-r--r--libebl/ppc64_init.c2
-rw-r--r--libebl/ppc64_symbol.c26
-rw-r--r--libebl/ppc_init.c2
-rw-r--r--libebl/ppc_symbol.c66
11 files changed, 186 insertions, 3 deletions
diff --git a/libebl/ChangeLog b/libebl/ChangeLog
index 5553cc49..68ec2217 100644
--- a/libebl/ChangeLog
+++ b/libebl/ChangeLog
@@ -1,3 +1,31 @@
+2005-08-12 Roland McGrath <[email protected]>
+
+ * libeblP.h (struct ebl): Add bss_plt_p hook.
+ * eblopenbackend.c (default_bss_plt_p): New function.
+ (fill_defaults): Use it.
+ * eblbsspltp.c: New file.
+ * Makefile.am (gen_SOURCES): Add it.
+ * libebl.h: Declare ebl_bss_plt_p.
+ * ppc_symbol.c (ppc_bss_plt_p): New function.
+ * libebl_ppc.h: Declare it.
+ * ppc_init.c (ppc_init): Use it.
+ * ppc64_symbol.c (ppc64_bss_plt_p): New function.
+ * libebl_ppc64.h: Declare it.
+ * ppc64_init.c (ppc64_init): Use it.
+
+ * ebl_check_special_symbol.c: New file.
+ * Makefile.am (gen_SOURCES): Add it.
+ * libebl.h: Declare ebl_check_special_symbol.
+ * libeblP.h (struct ebl): Add check_special_symbol hook.
+ * eblopenbackend.c (default_check_special_symbol): New function.
+ (fill_defaults): Use it.
+ * ppc_symbol.c (ppc_check_special_symbol): New function.
+ * libebl_ppc.h: Add prototype.
+ * ppc_init.c (ppc_init): Use it.
+ * ppc64_symbol.c (ppc64_check_special_symbol): New function.
+ * libebl_ppc64.h: Add prototype.
+ * ppc64_init.c (ppc64_init): Use it.
+
2005-08-07 Ulrich Drepper <[email protected]>
* ppc_init.c: Add support for new DT_PPC_* and R_PPC_* values.
diff --git a/libebl/Makefile.am b/libebl/Makefile.am
index eeac7e54..ead129bd 100644
--- a/libebl/Makefile.am
+++ b/libebl/Makefile.am
@@ -48,7 +48,8 @@ gen_SOURCES = eblopenbackend.c eblclosebackend.c eblstrtab.c \
ebldynamictagcheck.c eblcorenotetypename.c eblobjnotetypename.c \
eblcorenote.c eblobjnote.c ebldebugscnp.c \
eblgotpcreloccheck.c eblcopyrelocp.c eblsectionstripp.c \
- eblelfclass.c eblelfdata.c eblelfmachine.c
+ eblelfclass.c eblelfdata.c eblelfmachine.c \
+ ebl_check_special_symbol.c eblbsspltp.c
libebl_a_SOURCES = $(gen_SOURCES)
diff --git a/libebl/eblopenbackend.c b/libebl/eblopenbackend.c
index a104d737..f3ae7ab1 100644
--- a/libebl/eblopenbackend.c
+++ b/libebl/eblopenbackend.c
@@ -153,6 +153,11 @@ static bool default_object_note (const char *name, uint32_t type,
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,
+ const GElf_Sym *sym,
+ const char *name,
+ const GElf_Shdr *destshdr);
+static bool default_bss_plt_p (Elf *elf);
static void
@@ -181,6 +186,8 @@ fill_defaults (Ebl *result)
result->object_note = default_object_note;
result->debugscn_p = default_debugscn_p;
result->copy_reloc_p = default_copy_reloc_p;
+ result->check_special_symbol = default_check_special_symbol;
+ result->bss_plt_p = default_bss_plt_p;
result->destr = default_destr;
}
@@ -553,3 +560,18 @@ default_copy_reloc_p (int reloc __attribute__ ((unused)))
{
return false;
}
+
+static bool
+default_check_special_symbol (Elf *elf __attribute__ ((unused)),
+ const GElf_Sym *sym __attribute__ ((unused)),
+ const char *name __attribute__ ((unused)),
+ const GElf_Shdr *destshdr __attribute__ ((unused)))
+{
+ return false;
+}
+
+static bool
+default_bss_plt_p (Elf *elf __attribute__ ((unused)))
+{
+ return false;
+}
diff --git a/libebl/libebl.h b/libebl/libebl.h
index a59d4dd4..46373441 100644
--- a/libebl/libebl.h
+++ b/libebl/libebl.h
@@ -112,6 +112,12 @@ extern const char *ebl_dynamic_tag_name (Ebl *ebl, int64_t tag,
/* Check dynamic tag. */
extern bool ebl_dynamic_tag_check (Ebl *ebl, int64_t tag);
+/* Check whether given symbol's st_value and st_size are OK despite failing
+ normal checks. */
+extern bool ebl_check_special_symbol (Ebl *ebl,
+ const GElf_Sym *sym, const char *name,
+ const GElf_Shdr *destshdr);
+
/* Return combined section header flags value. */
extern GElf_Word ebl_sh_flags_combine (Ebl *ebl, GElf_Word flags1,
GElf_Word flags2);
@@ -142,12 +148,14 @@ extern bool ebl_debugscn_p (Ebl *ebl, const char *name);
/* Check whether given relocation is a copy relocation. */
extern bool ebl_copy_reloc_p (Ebl *ebl, int reloc);
-
-/* CHeck whether section should be stripped. */
+/* Check whether section should be stripped. */
extern bool ebl_section_strip_p (Ebl *ebl, const GElf_Ehdr *ehdr,
const GElf_Shdr *shdr, const char *name,
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);
+
/* ELF string table handling. */
struct Ebl_Strtab;
diff --git a/libebl/libeblP.h b/libebl/libeblP.h
index 9d47e8c4..adf51913 100644
--- a/libebl/libeblP.h
+++ b/libebl/libeblP.h
@@ -105,6 +105,14 @@ struct ebl
/* Check whether given relocation is a copy relocation. */
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);
+
+ /* Check if backend uses a bss PLT in this file. */
+ bool (*bss_plt_p) (Elf *elf);
+
/* Destructor for ELF backend handle. */
void (*destr) (struct ebl *);
diff --git a/libebl/libebl_ppc.h b/libebl/libebl_ppc.h
index e3c6d21c..03df06db 100644
--- a/libebl/libebl_ppc.h
+++ b/libebl/libebl_ppc.h
@@ -50,4 +50,14 @@ extern bool ppc_dynamic_tag_check (int64_t tag);
/* Check whether given relocation is a copy relocation. */
extern bool ppc_copy_reloc_p (int reloc);
+/* Check whether given symbol's st_value and st_size are OK despite normal
+ checks. */
+extern bool ppc_check_special_symbol (Elf *elf,
+ 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);
+
+
#endif /* libebl_ppc.h */
diff --git a/libebl/libebl_ppc64.h b/libebl/libebl_ppc64.h
index 148e2249..d8d445ff 100644
--- a/libebl/libebl_ppc64.h
+++ b/libebl/libebl_ppc64.h
@@ -50,4 +50,14 @@ extern bool ppc64_dynamic_tag_check (int64_t tag);
/* Check whether given relocation is a copy relocation. */
extern bool ppc64_copy_reloc_p (int reloc);
+/* Check whether given symbol's st_value and st_size are OK despite normal
+ checks. */
+extern bool ppc64_check_special_symbol (Elf *elf,
+ 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);
+
+
#endif /* libebl_ppc.h */
diff --git a/libebl/ppc64_init.c b/libebl/ppc64_init.c
index 347444c0..c8235bb1 100644
--- a/libebl/ppc64_init.c
+++ b/libebl/ppc64_init.c
@@ -39,6 +39,8 @@ ppc64_init (elf, machine, eh, ehlen)
eh->dynamic_tag_name = ppc64_dynamic_tag_name;
eh->dynamic_tag_check = ppc64_dynamic_tag_check;
eh->copy_reloc_p = ppc64_copy_reloc_p;
+ eh->check_special_symbol = ppc64_check_special_symbol;
+ eh->bss_plt_p = ppc64_bss_plt_p;
eh->destr = ppc64_destr;
return MODVERSION;
diff --git a/libebl/ppc64_symbol.c b/libebl/ppc64_symbol.c
index 457e84e6..ef0f5f70 100644
--- a/libebl/ppc64_symbol.c
+++ b/libebl/ppc64_symbol.c
@@ -19,6 +19,7 @@
#include <assert.h>
#include <elf.h>
#include <stddef.h>
+#include <string.h>
#include <libebl_ppc64.h>
@@ -242,3 +243,28 @@ ppc64_copy_reloc_p (int reloc)
{
return reloc == R_PPC64_COPY;
}
+
+
+/* Check whether given symbol's st_size is ok despite normal check failing. */
+bool
+ppc64_check_special_symbol (Elf *elf,
+ 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");
+}
+
+/* Check if backend uses a bss PLT in this file. */
+bool
+ppc64_bss_plt_p (Elf *elf __attribute__ ((unused)))
+{
+ return true;
+}
diff --git a/libebl/ppc_init.c b/libebl/ppc_init.c
index dca780b5..d76b1b13 100644
--- a/libebl/ppc_init.c
+++ b/libebl/ppc_init.c
@@ -39,6 +39,8 @@ ppc_init (elf, machine, eh, ehlen)
eh->dynamic_tag_name = ppc_dynamic_tag_name;
eh->dynamic_tag_check = ppc_dynamic_tag_check;
eh->copy_reloc_p = ppc_copy_reloc_p;
+ eh->check_special_symbol = ppc_check_special_symbol;
+ eh->bss_plt_p = ppc_bss_plt_p;
eh->destr = ppc_destr;
return MODVERSION;
diff --git a/libebl/ppc_symbol.c b/libebl/ppc_symbol.c
index e865eaab..8afabba2 100644
--- a/libebl/ppc_symbol.c
+++ b/libebl/ppc_symbol.c
@@ -19,6 +19,7 @@
#include <assert.h>
#include <elf.h>
#include <stddef.h>
+#include <string.h>
#include <libebl_ppc.h>
@@ -201,3 +202,68 @@ ppc_copy_reloc_p (int reloc)
{
return reloc == R_PPC_COPY;
}
+
+/* Check whether given symbol's value is ok despite failing normal checks. */
+bool
+ppc_check_special_symbol (Elf *elf,
+ const GElf_Sym *sym,
+ const char *name,
+ const GElf_Shdr *destshdr)
+{
+ if (name == NULL)
+ return false;
+
+ if (!strcmp (name, "_GLOBAL_OFFSET_TABLE_"))
+ {
+ 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")
+ && sym->st_value == destshdr->sh_addr + 0x8000
+ && sym->st_size == 0);
+
+ if (!strcmp (name, "_SDA2_BASE_"))
+ return (!strcmp (sname, ".sdata2")
+ && 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)
+{
+ Elf_Scn *scn = NULL;
+ while ((scn = elf_nextscn (elf, scn)) != NULL)
+ {
+ 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)
+ return false;
+ }
+ }
+ }
+
+ return true;
+}