summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
author"Steven J. Hill" <sjhill@realitydiluted.com>2006-01-14 19:18:52 +0000
committer"Steven J. Hill" <sjhill@realitydiluted.com>2006-01-14 19:18:52 +0000
commitad842abbb4a49f5c89092a6844f1535c933381ba (patch)
tree98903649805fd3ac0b517bf1c206e3b82ba44eb9
parent04c3ae8212af7ae1152116a8c632f1df5c4f5a75 (diff)
downloaduClibc-alpine-ad842abbb4a49f5c89092a6844f1535c933381ba.tar.bz2
uClibc-alpine-ad842abbb4a49f5c89092a6844f1535c933381ba.tar.xz
Merge from trunk.
-rw-r--r--ldso/ldso/x86_64/dl-debug.h9
-rw-r--r--ldso/ldso/x86_64/elfinterp.c29
-rw-r--r--ldso/ldso/x86_64/resolve.S63
3 files changed, 82 insertions, 19 deletions
diff --git a/ldso/ldso/x86_64/dl-debug.h b/ldso/ldso/x86_64/dl-debug.h
index 21412bd03..d605a0385 100644
--- a/ldso/ldso/x86_64/dl-debug.h
+++ b/ldso/ldso/x86_64/dl-debug.h
@@ -30,7 +30,10 @@
*/
static const char *_dl_reltypes_tab[] = {
- [0] "R_X86_64_NONE", "R_X86_64_64", "R_X86_64_PC32", "R_X86_64_GOT32",
- [4] "R_X86_64_PLT32", "R_X86_64_COPY", "R_X86_64_GLOB_DAT", "R_X86_64_JUMP_SLOT",
- [8] "R_X86_64_RELATIVE", "R_X86_64_GOTPCREL", "R_X86_64_32"
+ [ 0] "R_X86_64_NONE", "R_X86_64_64", "R_X86_64_PC32", "R_X86_64_GOT32",
+ [ 4] "R_X86_64_PLT32", "R_X86_64_COPY", "R_X86_64_GLOB_DAT", "R_X86_64_JUMP_SLOT",
+ [ 8] "R_X86_64_RELATIVE", "R_X86_64_GOTPCREL", "R_X86_64_32", "R_X86_64_32S",
+ [12] "R_X86_64_16", "R_X86_64_PC16", "R_X86_64_8", "R_X86_64_PC8",
+ [16] "R_X86_64_DTPMOD64", "R_X86_64_DTPOFF64", "R_X86_64_TPOFF64", "R_X86_64_TLSGD",
+ [20] "R_X86_64_TLSLD", "R_X86_64_DTPOFF32", "R_X86_64_GOTTPOFF", "R_X86_64_TPOFF32"
};
diff --git a/ldso/ldso/x86_64/elfinterp.c b/ldso/ldso/x86_64/elfinterp.c
index 66552d879..ef0fcb4e4 100644
--- a/ldso/ldso/x86_64/elfinterp.c
+++ b/ldso/ldso/x86_64/elfinterp.c
@@ -165,6 +165,7 @@ _dl_do_reloc(struct elf_resolve *tpnt, struct dyn_elf *scope,
int reloc_type;
int symtab_index;
char *symname;
+ ElfW(Sym) *sym;
ElfW(Addr) *reloc_addr;
ElfW(Addr) symbol_addr;
#if defined (__SUPPORT_LD_DEBUG__)
@@ -174,8 +175,9 @@ _dl_do_reloc(struct elf_resolve *tpnt, struct dyn_elf *scope,
reloc_addr = (ElfW(Addr)*)(tpnt->loadaddr + (unsigned long)rpnt->r_offset);
reloc_type = ELF_R_TYPE(rpnt->r_info);
symtab_index = ELF_R_SYM(rpnt->r_info);
+ sym = &symtab[symtab_index];
symbol_addr = 0;
- symname = strtab + symtab[symtab_index].st_name;
+ symname = strtab + sym->st_name;
if (symtab_index) {
symbol_addr = (ElfW(Addr))_dl_find_hash(symname, scope, tpnt,
@@ -185,7 +187,7 @@ _dl_do_reloc(struct elf_resolve *tpnt, struct dyn_elf *scope,
* might have been intentional. We should not be linking local
* symbols here, so all bases should be covered.
*/
- if (unlikely(!symbol_addr && ELF_ST_BIND(symtab[symtab_index].st_info) != STB_WEAK)) {
+ if (unlikely(!symbol_addr && ELF_ST_BIND(sym->st_info) != STB_WEAK)) {
_dl_dprintf(2, "%s: can't resolve symbol '%s'\n", _dl_progname, symname);
_dl_exit(1);
};
@@ -209,7 +211,7 @@ _dl_do_reloc(struct elf_resolve *tpnt, struct dyn_elf *scope,
case R_X86_64_GLOB_DAT:
case R_X86_64_JUMP_SLOT:
- *reloc_addr = symbol_addr;
+ *reloc_addr = symbol_addr + rpnt->r_addend;
break;
/* handled by elf_machine_relative()
@@ -217,33 +219,33 @@ _dl_do_reloc(struct elf_resolve *tpnt, struct dyn_elf *scope,
*reloc_addr = map->l_addr + rpnt->r_addend;
break;
*/
-#if 0
case R_X86_64_DTPMOD64:
+ *reloc_addr = 1;
break;
case R_X86_64_DTPOFF64:
- *reloc_addr = symbol_addr + rpnt->r_addend;
+ *reloc_addr = sym->st_value + rpnt->r_addend;
break;
case R_X86_64_TPOFF64:
- *reloc_addr = symbol_addr + rpnt->r_addend;
+ *reloc_addr = sym->st_value + rpnt->r_addend - symbol_addr;
break;
case R_X86_64_32:
- *reloc_addr = symbol_addr + rpnt->r_addend;
+ *(unsigned int *) reloc_addr = symbol_addr + rpnt->r_addend;
+ /* XXX: should check for overflow eh ? */
break;
-#endif
case R_X86_64_COPY:
if (symbol_addr) {
#if defined (__SUPPORT_LD_DEBUG__)
if (_dl_debug_move)
_dl_dprintf(_dl_debug_file,
"\t%s move %d bytes from %x to %x\n",
- symname, symtab[symtab_index].st_size,
+ symname, sym->st_size,
symbol_addr, reloc_addr);
#endif
_dl_memcpy((char *)reloc_addr,
(char *)symbol_addr,
- symtab[symtab_index].st_size);
+ sym->st_size);
} else
_dl_dprintf(_dl_debug_file, "no symbol_addr to copy !?\n");
break;
@@ -261,7 +263,6 @@ _dl_do_reloc(struct elf_resolve *tpnt, struct dyn_elf *scope,
return 0;
}
-#if 0
static int
_dl_do_lazy_reloc(struct elf_resolve *tpnt, struct dyn_elf *scope,
ELF_RELOC *rpnt, ElfW(Sym) *symtab, char *strtab)
@@ -288,7 +289,7 @@ _dl_do_lazy_reloc(struct elf_resolve *tpnt, struct dyn_elf *scope,
case R_X86_64_NONE:
break;
case R_X86_64_JUMP_SLOT:
- *reloc_addr = tpnt->loadaddr + symtab[symtab_index].st_value;
+ *reloc_addr += (unsigned long)tpnt->loadaddr;
break;
default:
_dl_exit(1);
@@ -302,17 +303,13 @@ _dl_do_lazy_reloc(struct elf_resolve *tpnt, struct dyn_elf *scope,
return 0;
}
-#endif
void
_dl_parse_lazy_relocation_information(struct dyn_elf *rpnt,
unsigned long rel_addr,
unsigned long rel_size)
{
- _dl_parse_relocation_information(rpnt, rel_addr, rel_size);
-/* jump slot isnt working
(void)_dl_parse(rpnt->dyn, NULL, rel_addr, rel_size, _dl_do_lazy_reloc);
-*/
}
int
diff --git a/ldso/ldso/x86_64/resolve.S b/ldso/ldso/x86_64/resolve.S
new file mode 100644
index 000000000..5d55d0c73
--- /dev/null
+++ b/ldso/ldso/x86_64/resolve.S
@@ -0,0 +1,63 @@
+/*
+ * This function is _not_ called directly. It is jumped to (so no return
+ * address is on the stack) when attempting to use a symbol that has not yet
+ * been resolved. The first time a jump symbol (such as a function call inside
+ * a shared library) is used (before it gets resolved) it will jump here to
+ * _dl_linux_resolve. When we get called the stack looks like this:
+ * reloc_entry
+ * tpnt
+ *
+ * This function saves all the registers, puts a copy of reloc_entry and tpnt
+ * on the stack (as function arguments) then make the function call
+ * _dl_linux_resolver(tpnt, reloc_entry). _dl_linux_resolver() figures out
+ * where the jump symbol is _really_ supposed to have jumped to and returns
+ * that to us. Once we have that, we overwrite tpnt with this fixed up
+ * address. We then clean up after ourselves, put all the registers back how we
+ * found them, then we jump to where the fixed up address, which is where the
+ * jump symbol that got us here really wanted to jump to in the first place.
+ * found them, then we jump to the fixed up address, which is where the jump
+ * symbol that got us here really wanted to jump to in the first place.
+ * -Erik Andersen
+ */
+
+/* more info taken from glibc/sysdeps/x86_64/dl-trampoline.S */
+
+.text
+
+.global _dl_linux_resolve
+.type _dl_linux_resolve,%function
+.align 16
+
+_dl_linux_resolve:
+ subq $56,%rsp
+ /* Preserve registers otherwise clobbered. */
+ movq %rax, (%rsp)
+ movq %rcx, 8(%rsp)
+ movq %rdx, 16(%rsp)
+ movq %rsi, 24(%rsp)
+ movq %rdi, 32(%rsp)
+ movq %r8, 40(%rsp)
+ movq %r9, 48(%rsp)
+
+ movq 64(%rsp), %rsi /* Copy args pushed by PLT in register. */
+ movq %rsi, %r11 /* Multiply by 24 */
+ addq %r11, %rsi
+ addq %r11, %rsi
+ shlq $3, %rsi
+ movq 56(%rsp), %rdi /* %rdi: link_map, %rsi: reloc_offset */
+ call _dl_linux_resolver /* Call resolver. */
+ movq %rax, %r11 /* Save return value */
+
+ /* Get register content back. */
+ movq 48(%rsp), %r9
+ movq 40(%rsp), %r8
+ movq 32(%rsp), %rdi
+ movq 24(%rsp), %rsi
+ movq 16(%rsp), %rdx
+ movq 8(%rsp), %rcx
+ movq (%rsp), %rax
+
+ addq $72, %rsp /* Adjust stack(PLT did 2 pushes) */
+ jmp *%r11 /* Jump to function address. */
+
+.size _dl_linux_resolve,.-_dl_linux_resolve