From: "Edgar E. Iglesias" <[email protected]>

Add support for CPIC (Calls PIC) only binaries. These ELF
files are not PIC themselves (as ordinary o32 binaries).

External calls via function pointers don't work yet.

Signed-off-by: Edgar E. Iglesias <[email protected]>
---
 sysdeps/linux-gnu/mipsel/arch.h |    2 ++
 sysdeps/linux-gnu/mipsel/plt.c  |   36 +++++++++++++++++++++++++++++++++++-
 2 files changed, 37 insertions(+), 1 deletions(-)

diff --git a/sysdeps/linux-gnu/mipsel/arch.h b/sysdeps/linux-gnu/mipsel/arch.h
index 4fa3a93..684b546 100644
--- a/sysdeps/linux-gnu/mipsel/arch.h
+++ b/sysdeps/linux-gnu/mipsel/arch.h
@@ -60,6 +60,8 @@ struct arch_library_symbol_data {
 
        /* Set for FUNCs that have GOT entries but not PLT entries.  */
        int gotonly : 1;
+       /* Set for FUNCs that have PLT entries that are always used.  */
+       int pltalways : 1;
 };
 
 #endif /* LTRACE_MIPS_ARCH_H */
diff --git a/sysdeps/linux-gnu/mipsel/plt.c b/sysdeps/linux-gnu/mipsel/plt.c
index f49f04f..09abf26 100644
--- a/sysdeps/linux-gnu/mipsel/plt.c
+++ b/sysdeps/linux-gnu/mipsel/plt.c
@@ -16,6 +16,12 @@
    @{
  */
 
+/* Are we in pure CPIC mode (the non-PIC ABI extension)?  */
+static inline int mips_elf_is_cpic(unsigned int elf_flags)
+{
+       return (elf_flags & (EF_MIPS_PIC | EF_MIPS_CPIC)) == EF_MIPS_CPIC;
+}
+
 /**
    \param lte Structure containing link table entry information
    \param ndx Index into .dynsym
@@ -43,6 +49,13 @@ GElf_Addr
 arch_plt_sym_val(struct ltelf *lte, size_t ndx, GElf_Rela *rela)
 {
     debug(1,"plt_addr %zx ndx %#zx",lte->arch.pltgot_addr, ndx);
+
+    if (mips_elf_is_cpic(lte->ehdr.e_flags)) {
+        /* Return a pointer into the PLT.  */
+        return lte->plt_addr + 16 * 2 + (ndx * 16);
+    }
+
+    /* Return a pointer to a GOT entry.  */
     return lte->arch.pltgot_addr +
            sizeof(void *) * (lte->arch.mips_local_gotno
                              + (ndx - lte->arch.mips_gotsym));
@@ -70,7 +83,8 @@ void *
 sym2addr(Process *proc, struct library_symbol *sym) {
     long ret;
 
-    if (!sym->arch.gotonly && sym->plt_type == LS_TOPLT_NONE) {
+    if (sym->arch.pltalways
+        || (!sym->arch.gotonly && sym->plt_type == LS_TOPLT_NONE)) {
         return sym->enter_addr;
     }
 
@@ -120,6 +134,10 @@ arch_get_sym_info(struct ltelf *lte, const char *filename,
 {
        const char *name;
 
+       if (mips_elf_is_cpic(lte->ehdr.e_flags)) {
+               return elf_get_sym_info(lte, filename, sym_index, rela, sym);
+       }
+
        /* Fixup the offset.  */
        sym_index += lte->arch.mips_gotsym;
 
@@ -158,6 +176,15 @@ arch_elf_init(struct ltelf *lte, struct library *lib)
 {
        Elf_Scn *scn;
        GElf_Shdr shdr;
+
+       /* FIXME: for CPIC we should really scan both GOT tables
+        * to pick up relocations to external functions. Right now
+        * function pointers from the main binary to external functions
+        * can't be traced in CPIC mode.  */
+       if (mips_elf_is_cpic(lte->ehdr.e_flags)) {
+               return 0; /* We are already done.  */
+       }
+
        if (elf_get_section_type(lte, SHT_DYNAMIC, &scn, &shdr) < 0
            || scn == NULL) {
        fail:
@@ -210,6 +237,10 @@ void arch_symbol_ret(struct Process *proc, struct 
library_symbol *libsym)
        if (libsym->arch.type != MIPS_PLT_UNRESOLVED)
                return;
 
+       /* Get out if we are always using the PLT.  */
+       if (libsym->arch.pltalways)
+               return;
+
        resolved_addr = sym2addr(proc, libsym);
        libsym->arch.resolved_addr = (uintptr_t) resolved_addr;
        libsym->arch.type = MIPS_PLT_RESOLVED;
@@ -329,6 +360,8 @@ arch_elf_add_plt_entry(struct Process *proc, struct ltelf 
*lte,
                /* Delay breakpoint activation until the symbol gets
                 * resolved.  */
                libsym->delayed = 1;
+       } else if (mips_elf_is_cpic(lte->ehdr.e_flags)) {
+               libsym->arch.pltalways = 1;
        }
 
        *ret = libsym;
@@ -343,6 +376,7 @@ fail:
 int
 arch_library_symbol_init(struct library_symbol *libsym)
 {
+       libsym->arch.pltalways = 0;
        libsym->arch.gotonly = 0;
        libsym->arch.type = MIPS_PLT_UNRESOLVED;
        if (libsym->plt_type == LS_TOPLT_NONE) {
-- 
1.7.8.6


_______________________________________________
Ltrace-devel mailing list
[email protected]
http://lists.alioth.debian.org/cgi-bin/mailman/listinfo/ltrace-devel

Reply via email to