* commit '5483057817d071140d94299452b31881c4a6e748': MIPS support to the linker
This commit is contained in:
commit
673c092e0f
@ -16,7 +16,8 @@ LOCAL_LDFLAGS := -shared
|
|||||||
LOCAL_CFLAGS += -fno-stack-protector \
|
LOCAL_CFLAGS += -fno-stack-protector \
|
||||||
-Wstrict-overflow=5 \
|
-Wstrict-overflow=5 \
|
||||||
-fvisibility=hidden \
|
-fvisibility=hidden \
|
||||||
-std=gnu99
|
-std=gnu99 \
|
||||||
|
-Wall -Wextra
|
||||||
|
|
||||||
# Set LINKER_DEBUG to either 1 or 0
|
# Set LINKER_DEBUG to either 1 or 0
|
||||||
#
|
#
|
||||||
@ -33,11 +34,15 @@ LOCAL_CFLAGS += \
|
|||||||
-I$(LOCAL_PATH)/../libc/arch-$(TARGET_ARCH)/bionic
|
-I$(LOCAL_PATH)/../libc/arch-$(TARGET_ARCH)/bionic
|
||||||
|
|
||||||
ifeq ($(TARGET_ARCH),arm)
|
ifeq ($(TARGET_ARCH),arm)
|
||||||
LOCAL_CFLAGS += -DANDROID_ARM_LINKER
|
LOCAL_CFLAGS += -DANDROID_ARM_LINKER
|
||||||
else
|
endif
|
||||||
ifeq ($(TARGET_ARCH),x86)
|
|
||||||
|
ifeq ($(TARGET_ARCH),x86)
|
||||||
LOCAL_CFLAGS += -DANDROID_X86_LINKER
|
LOCAL_CFLAGS += -DANDROID_X86_LINKER
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
ifeq ($(TARGET_ARCH),mips)
|
||||||
|
LOCAL_CFLAGS += -DANDROID_MIPS_LINKER
|
||||||
endif
|
endif
|
||||||
|
|
||||||
LOCAL_MODULE:= linker
|
LOCAL_MODULE:= linker
|
||||||
|
107
linker/arch/mips/begin.S
Normal file
107
linker/arch/mips/begin.S
Normal file
@ -0,0 +1,107 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2012 The Android Open Source Project
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in
|
||||||
|
* the documentation and/or other materials provided with the
|
||||||
|
* distribution.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||||
|
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||||
|
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||||
|
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||||
|
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||||
|
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||||
|
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||||
|
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
|
||||||
|
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
|
* SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
.text
|
||||||
|
.align 4
|
||||||
|
.type __start,@function
|
||||||
|
|
||||||
|
.ent __start
|
||||||
|
.globl __start
|
||||||
|
__start:
|
||||||
|
.set noreorder
|
||||||
|
bal 1f
|
||||||
|
nop
|
||||||
|
1: .cpload $31
|
||||||
|
.set reorder
|
||||||
|
|
||||||
|
/* Discover the load address */
|
||||||
|
la $t0, 1f
|
||||||
|
bal 1f
|
||||||
|
1: subu $t0, $ra, $t0
|
||||||
|
|
||||||
|
#define DT_PLTGOT 3
|
||||||
|
#define DT_MIPS_LOCAL_GOTNO 0x7000000a
|
||||||
|
|
||||||
|
/* Search dynamic table for DT_MIPS_LOCAL_GOTNO and DT_PLTGOT values */
|
||||||
|
la $t1, _DYNAMIC
|
||||||
|
addu $t1, $t0
|
||||||
|
li $t3, DT_PLTGOT
|
||||||
|
li $t4, DT_MIPS_LOCAL_GOTNO
|
||||||
|
0:
|
||||||
|
lw $t2, 0($t1)
|
||||||
|
beqz $t2, .Lrelocate_local_got
|
||||||
|
|
||||||
|
bne $t2, $t3, 1f /* DT_PLTGOT? */
|
||||||
|
lw $s0, 4($t1)
|
||||||
|
addu $s0, $t0
|
||||||
|
b 2f
|
||||||
|
|
||||||
|
1: bne $t2, $t4, 1f /* DT_MIPS_LOCAL_GOTNO? */
|
||||||
|
lw $s1, 4($t1)
|
||||||
|
b 2f
|
||||||
|
|
||||||
|
1:
|
||||||
|
2: addu $t1, 8
|
||||||
|
b 0b
|
||||||
|
|
||||||
|
.Lrelocate_local_got:
|
||||||
|
/*
|
||||||
|
* Relocate the local GOT entries
|
||||||
|
* got[0] is address of lazy resolver function
|
||||||
|
* got[1] may be used for a GNU extension
|
||||||
|
*/
|
||||||
|
|
||||||
|
addu $s0, 4
|
||||||
|
subu $s1, 1
|
||||||
|
lw $t1, ($s0)
|
||||||
|
bgez $t1, 9f
|
||||||
|
addu $s0, 4
|
||||||
|
subu $s1, 1
|
||||||
|
b 9f
|
||||||
|
|
||||||
|
1: lw $t1, ($s0)
|
||||||
|
addu $t1, $t0
|
||||||
|
sw $t1, ($s0)
|
||||||
|
addu $s0, 4
|
||||||
|
9: subu $s1, 1
|
||||||
|
bgez $s1, 1b
|
||||||
|
|
||||||
|
/* call linker_init */
|
||||||
|
move $a0, $sp
|
||||||
|
addiu $sp, -4*4 /* space for arg saves in linker_init */
|
||||||
|
la $t9, __linker_init
|
||||||
|
jalr $t9
|
||||||
|
move $t9, $v0
|
||||||
|
addu $sp, 4*4 /* restore sp */
|
||||||
|
j $t9
|
||||||
|
.end __start
|
||||||
|
|
||||||
|
.section .ctors, "wa"
|
||||||
|
.globl __CTOR_LIST__
|
||||||
|
__CTOR_LIST__:
|
||||||
|
.long -1
|
@ -131,7 +131,9 @@ static void logSignalSummary(int signum, const siginfo_t* info)
|
|||||||
case SIGBUS: signame = "SIGBUS"; break;
|
case SIGBUS: signame = "SIGBUS"; break;
|
||||||
case SIGFPE: signame = "SIGFPE"; break;
|
case SIGFPE: signame = "SIGFPE"; break;
|
||||||
case SIGSEGV: signame = "SIGSEGV"; break;
|
case SIGSEGV: signame = "SIGSEGV"; break;
|
||||||
|
#if defined(SIGSTKFLT)
|
||||||
case SIGSTKFLT: signame = "SIGSTKFLT"; break;
|
case SIGSTKFLT: signame = "SIGSTKFLT"; break;
|
||||||
|
#endif
|
||||||
case SIGPIPE: signame = "SIGPIPE"; break;
|
case SIGPIPE: signame = "SIGPIPE"; break;
|
||||||
default: signame = "???"; break;
|
default: signame = "???"; break;
|
||||||
}
|
}
|
||||||
@ -214,7 +216,9 @@ void debugger_signal_handler(int n, siginfo_t* info, void* unused)
|
|||||||
case SIGABRT:
|
case SIGABRT:
|
||||||
case SIGFPE:
|
case SIGFPE:
|
||||||
case SIGPIPE:
|
case SIGPIPE:
|
||||||
|
#ifdef SIGSTKFLT
|
||||||
case SIGSTKFLT:
|
case SIGSTKFLT:
|
||||||
|
#endif
|
||||||
(void) tgkill(getpid(), gettid(), n);
|
(void) tgkill(getpid(), gettid(), n);
|
||||||
break;
|
break;
|
||||||
default: // SIGILL, SIGBUS, SIGSEGV
|
default: // SIGILL, SIGBUS, SIGSEGV
|
||||||
@ -235,6 +239,8 @@ void debugger_init()
|
|||||||
sigaction(SIGBUS, &act, NULL);
|
sigaction(SIGBUS, &act, NULL);
|
||||||
sigaction(SIGFPE, &act, NULL);
|
sigaction(SIGFPE, &act, NULL);
|
||||||
sigaction(SIGSEGV, &act, NULL);
|
sigaction(SIGSEGV, &act, NULL);
|
||||||
|
#if defined(SIGSTKFLT)
|
||||||
sigaction(SIGSTKFLT, &act, NULL);
|
sigaction(SIGSTKFLT, &act, NULL);
|
||||||
|
#endif
|
||||||
sigaction(SIGPIPE, &act, NULL);
|
sigaction(SIGPIPE, &act, NULL);
|
||||||
}
|
}
|
||||||
|
@ -170,13 +170,13 @@ int dlclose(void *handle)
|
|||||||
#define ANDROID_LIBDL_STRTAB \
|
#define ANDROID_LIBDL_STRTAB \
|
||||||
"dlopen\0dlclose\0dlsym\0dlerror\0dladdr\0dl_unwind_find_exidx\0"
|
"dlopen\0dlclose\0dlsym\0dlerror\0dladdr\0dl_unwind_find_exidx\0"
|
||||||
|
|
||||||
#elif defined(ANDROID_X86_LINKER)
|
#elif defined(ANDROID_X86_LINKER) || defined(ANDROID_MIPS_LINKER)
|
||||||
// 0000000 00011111 111112 22222222 2333333 3333444444444455
|
// 0000000 00011111 111112 22222222 2333333 3333444444444455
|
||||||
// 0123456 78901234 567890 12345678 9012345 6789012345678901
|
// 0123456 78901234 567890 12345678 9012345 6789012345678901
|
||||||
#define ANDROID_LIBDL_STRTAB \
|
#define ANDROID_LIBDL_STRTAB \
|
||||||
"dlopen\0dlclose\0dlsym\0dlerror\0dladdr\0dl_iterate_phdr\0"
|
"dlopen\0dlclose\0dlsym\0dlerror\0dladdr\0dl_iterate_phdr\0"
|
||||||
#else
|
#else
|
||||||
#error Unsupported architecture. Only ARM and x86 are presently supported.
|
#error Unsupported architecture. Only ARM, MIPS, and x86 are presently supported.
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
@ -218,7 +218,7 @@ static Elf32_Sym libdl_symtab[] = {
|
|||||||
st_info: STB_GLOBAL << 4,
|
st_info: STB_GLOBAL << 4,
|
||||||
st_shndx: 1,
|
st_shndx: 1,
|
||||||
},
|
},
|
||||||
#elif defined(ANDROID_X86_LINKER)
|
#elif defined(ANDROID_X86_LINKER) || defined(ANDROID_MIPS_LINKER)
|
||||||
{ st_name: 36,
|
{ st_name: 36,
|
||||||
st_value: (Elf32_Addr) &dl_iterate_phdr,
|
st_value: (Elf32_Addr) &dl_iterate_phdr,
|
||||||
st_info: STB_GLOBAL << 4,
|
st_info: STB_GLOBAL << 4,
|
||||||
|
177
linker/linker.c
177
linker/linker.c
@ -142,9 +142,9 @@ static char tmp_err_buf[768];
|
|||||||
static char __linker_dl_err_buf[768];
|
static char __linker_dl_err_buf[768];
|
||||||
#define DL_ERR(fmt, x...) \
|
#define DL_ERR(fmt, x...) \
|
||||||
do { \
|
do { \
|
||||||
format_buffer(__linker_dl_err_buf, sizeof(__linker_dl_err_buf), \
|
format_buffer(__linker_dl_err_buf, sizeof(__linker_dl_err_buf), \
|
||||||
"%s[%d]: " fmt, __func__, __LINE__, ##x); \
|
"%s[%d]: " fmt, __func__, __LINE__, ##x); \
|
||||||
ERROR(fmt "\n", ##x); \
|
ERROR(fmt "\n", ##x); \
|
||||||
} while(0)
|
} while(0)
|
||||||
|
|
||||||
const char *linker_get_error(void)
|
const char *linker_get_error(void)
|
||||||
@ -350,7 +350,7 @@ _Unwind_Ptr dl_unwind_find_exidx(_Unwind_Ptr pc, int *pcount)
|
|||||||
*pcount = 0;
|
*pcount = 0;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
#elif defined(ANDROID_X86_LINKER)
|
#elif defined(ANDROID_X86_LINKER) || defined(ANDROID_MIPS_LINKER)
|
||||||
/* Here, we only have to provide a callback to iterate across all the
|
/* Here, we only have to provide a callback to iterate across all the
|
||||||
* loaded libraries. gcc_eh does the rest. */
|
* loaded libraries. gcc_eh does the rest. */
|
||||||
int
|
int
|
||||||
@ -455,7 +455,7 @@ soinfo_do_lookup(soinfo *si, const char *name, Elf32_Addr *offset)
|
|||||||
lsi = (soinfo *)d[1];
|
lsi = (soinfo *)d[1];
|
||||||
if (!validate_soinfo(lsi)) {
|
if (!validate_soinfo(lsi)) {
|
||||||
DL_ERR("%5d bad DT_NEEDED pointer in %s",
|
DL_ERR("%5d bad DT_NEEDED pointer in %s",
|
||||||
pid, si->name);
|
pid, lsi->name);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -691,6 +691,8 @@ verify_elf_header(const Elf32_Ehdr* hdr)
|
|||||||
if (hdr->e_machine != EM_ARM) return -1;
|
if (hdr->e_machine != EM_ARM) return -1;
|
||||||
#elif defined(ANDROID_X86_LINKER)
|
#elif defined(ANDROID_X86_LINKER)
|
||||||
if (hdr->e_machine != EM_386) return -1;
|
if (hdr->e_machine != EM_386) return -1;
|
||||||
|
#elif defined(ANDROID_MIPS_LINKER)
|
||||||
|
if (hdr->e_machine != EM_MIPS) return -1;
|
||||||
#endif
|
#endif
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -975,7 +977,7 @@ static int soinfo_relocate(soinfo *si, Elf32_Rel *rel, unsigned count)
|
|||||||
Elf32_Rel *start = rel;
|
Elf32_Rel *start = rel;
|
||||||
unsigned idx;
|
unsigned idx;
|
||||||
|
|
||||||
for (idx = 0; idx < count; ++idx) {
|
for (idx = 0; idx < count; ++idx, ++rel) {
|
||||||
unsigned type = ELF32_R_TYPE(rel->r_info);
|
unsigned type = ELF32_R_TYPE(rel->r_info);
|
||||||
unsigned sym = ELF32_R_SYM(rel->r_info);
|
unsigned sym = ELF32_R_SYM(rel->r_info);
|
||||||
unsigned reloc = (unsigned)(rel->r_offset + si->load_bias);
|
unsigned reloc = (unsigned)(rel->r_offset + si->load_bias);
|
||||||
@ -984,6 +986,9 @@ static int soinfo_relocate(soinfo *si, Elf32_Rel *rel, unsigned count)
|
|||||||
|
|
||||||
DEBUG("%5d Processing '%s' relocation at index %d\n", pid,
|
DEBUG("%5d Processing '%s' relocation at index %d\n", pid,
|
||||||
si->name, idx);
|
si->name, idx);
|
||||||
|
if (type == 0) { // R_*_NONE
|
||||||
|
continue;
|
||||||
|
}
|
||||||
if(sym != 0) {
|
if(sym != 0) {
|
||||||
sym_name = (char *)(strtab + symtab[sym].st_name);
|
sym_name = (char *)(strtab + symtab[sym].st_name);
|
||||||
s = soinfo_do_lookup(si, sym_name, &offset);
|
s = soinfo_do_lookup(si, sym_name, &offset);
|
||||||
@ -1015,9 +1020,8 @@ static int soinfo_relocate(soinfo *si, Elf32_Rel *rel, unsigned count)
|
|||||||
case R_ARM_GLOB_DAT:
|
case R_ARM_GLOB_DAT:
|
||||||
case R_ARM_ABS32:
|
case R_ARM_ABS32:
|
||||||
case R_ARM_RELATIVE: /* Don't care. */
|
case R_ARM_RELATIVE: /* Don't care. */
|
||||||
case R_ARM_NONE: /* Don't care. */
|
|
||||||
#elif defined(ANDROID_X86_LINKER)
|
#elif defined(ANDROID_X86_LINKER)
|
||||||
case R_386_JUMP_SLOT:
|
case R_386_JMP_SLOT:
|
||||||
case R_386_GLOB_DAT:
|
case R_386_GLOB_DAT:
|
||||||
case R_386_32:
|
case R_386_32:
|
||||||
case R_386_RELATIVE: /* Dont' care. */
|
case R_386_RELATIVE: /* Dont' care. */
|
||||||
@ -1046,15 +1050,15 @@ static int soinfo_relocate(soinfo *si, Elf32_Rel *rel, unsigned count)
|
|||||||
} else {
|
} else {
|
||||||
/* We got a definition. */
|
/* We got a definition. */
|
||||||
#if 0
|
#if 0
|
||||||
if((base == 0) && (si->base != 0)){
|
if((base == 0) && (si->base != 0)){
|
||||||
/* linking from libraries to main image is bad */
|
/* linking from libraries to main image is bad */
|
||||||
DL_ERR("%5d cannot locate '%s'...",
|
DL_ERR("%5d cannot locate '%s'...",
|
||||||
pid, strtab + symtab[sym].st_name);
|
pid, strtab + symtab[sym].st_name);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
sym_addr = (unsigned)(s->st_value + offset);
|
sym_addr = (unsigned)(s->st_value + offset);
|
||||||
}
|
}
|
||||||
COUNT_RELOC(RELOC_SYMBOL);
|
COUNT_RELOC(RELOC_SYMBOL);
|
||||||
} else {
|
} else {
|
||||||
s = NULL;
|
s = NULL;
|
||||||
@ -1094,7 +1098,7 @@ static int soinfo_relocate(soinfo *si, Elf32_Rel *rel, unsigned count)
|
|||||||
*((unsigned*)reloc) += sym_addr - rel->r_offset;
|
*((unsigned*)reloc) += sym_addr - rel->r_offset;
|
||||||
break;
|
break;
|
||||||
#elif defined(ANDROID_X86_LINKER)
|
#elif defined(ANDROID_X86_LINKER)
|
||||||
case R_386_JUMP_SLOT:
|
case R_386_JMP_SLOT:
|
||||||
COUNT_RELOC(RELOC_ABSOLUTE);
|
COUNT_RELOC(RELOC_ABSOLUTE);
|
||||||
MARK(rel->r_offset);
|
MARK(rel->r_offset);
|
||||||
TRACE_TYPE(RELO, "%5d RELO JMP_SLOT %08x <- %08x %s\n", pid,
|
TRACE_TYPE(RELO, "%5d RELO JMP_SLOT %08x <- %08x %s\n", pid,
|
||||||
@ -1108,6 +1112,25 @@ static int soinfo_relocate(soinfo *si, Elf32_Rel *rel, unsigned count)
|
|||||||
reloc, sym_addr, sym_name);
|
reloc, sym_addr, sym_name);
|
||||||
*((unsigned*)reloc) = sym_addr;
|
*((unsigned*)reloc) = sym_addr;
|
||||||
break;
|
break;
|
||||||
|
#elif defined(ANDROID_MIPS_LINKER)
|
||||||
|
case R_MIPS_JUMP_SLOT:
|
||||||
|
COUNT_RELOC(RELOC_ABSOLUTE);
|
||||||
|
MARK(rel->r_offset);
|
||||||
|
TRACE_TYPE(RELO, "%5d RELO JMP_SLOT %08x <- %08x %s\n", pid,
|
||||||
|
reloc, sym_addr, sym_name);
|
||||||
|
*((unsigned*)reloc) = sym_addr;
|
||||||
|
break;
|
||||||
|
case R_MIPS_REL32:
|
||||||
|
COUNT_RELOC(RELOC_ABSOLUTE);
|
||||||
|
MARK(rel->r_offset);
|
||||||
|
TRACE_TYPE(RELO, "%5d RELO REL32 %08x <- %08x %s\n", pid,
|
||||||
|
reloc, sym_addr, (sym_name) ? sym_name : "*SECTIONHDR*");
|
||||||
|
if (s) {
|
||||||
|
*((unsigned*)reloc) += sym_addr;
|
||||||
|
} else {
|
||||||
|
*((unsigned*)reloc) += si->base;
|
||||||
|
}
|
||||||
|
break;
|
||||||
#endif /* ANDROID_*_LINKER */
|
#endif /* ANDROID_*_LINKER */
|
||||||
|
|
||||||
#if defined(ANDROID_ARM_LINKER)
|
#if defined(ANDROID_ARM_LINKER)
|
||||||
@ -1154,8 +1177,6 @@ static int soinfo_relocate(soinfo *si, Elf32_Rel *rel, unsigned count)
|
|||||||
reloc, s->st_size, sym_addr, sym_name);
|
reloc, s->st_size, sym_addr, sym_name);
|
||||||
memcpy((void*)reloc, (void*)sym_addr, s->st_size);
|
memcpy((void*)reloc, (void*)sym_addr, s->st_size);
|
||||||
break;
|
break;
|
||||||
case R_ARM_NONE:
|
|
||||||
break;
|
|
||||||
#endif /* ANDROID_ARM_LINKER */
|
#endif /* ANDROID_ARM_LINKER */
|
||||||
|
|
||||||
default:
|
default:
|
||||||
@ -1163,11 +1184,79 @@ static int soinfo_relocate(soinfo *si, Elf32_Rel *rel, unsigned count)
|
|||||||
pid, type, rel, (int) (rel - start));
|
pid, type, rel, (int) (rel - start));
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
rel++;
|
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef ANDROID_MIPS_LINKER
|
||||||
|
int mips_relocate_got(struct soinfo *si)
|
||||||
|
{
|
||||||
|
unsigned *got;
|
||||||
|
unsigned local_gotno, gotsym, symtabno;
|
||||||
|
Elf32_Sym *symtab, *sym;
|
||||||
|
unsigned g;
|
||||||
|
|
||||||
|
got = si->plt_got;
|
||||||
|
local_gotno = si->mips_local_gotno;
|
||||||
|
gotsym = si->mips_gotsym;
|
||||||
|
symtabno = si->mips_symtabno;
|
||||||
|
symtab = si->symtab;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* got[0] is address of lazy resolver function
|
||||||
|
* got[1] may be used for a GNU extension
|
||||||
|
* set it to a recognisable address in case someone calls it
|
||||||
|
* (should be _rtld_bind_start)
|
||||||
|
* FIXME: maybe this should be in a separate routine
|
||||||
|
*/
|
||||||
|
|
||||||
|
if ((si->flags & FLAG_LINKER) == 0) {
|
||||||
|
g = 0;
|
||||||
|
got[g++] = 0xdeadbeef;
|
||||||
|
if (got[g] & 0x80000000) {
|
||||||
|
got[g++] = 0xdeadfeed;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* Relocate the local GOT entries need to be relocated
|
||||||
|
*/
|
||||||
|
for (; g < local_gotno; g++) {
|
||||||
|
got[g] += si->load_bias;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Now for the global GOT entries */
|
||||||
|
sym = symtab + gotsym;
|
||||||
|
got = si->plt_got + local_gotno;
|
||||||
|
for (g = gotsym; g < symtabno; g++, sym++, got++) {
|
||||||
|
const char *sym_name;
|
||||||
|
unsigned base;
|
||||||
|
Elf32_Sym *s;
|
||||||
|
|
||||||
|
/* This is an undefined reference... try to locate it */
|
||||||
|
sym_name = si->strtab + sym->st_name;
|
||||||
|
s = soinfo_do_lookup(si, sym_name, &base);
|
||||||
|
if (s == NULL) {
|
||||||
|
/* We only allow an undefined symbol if this is a weak
|
||||||
|
reference.. */
|
||||||
|
s = &symtab[g];
|
||||||
|
if (ELF32_ST_BIND(s->st_info) != STB_WEAK) {
|
||||||
|
DL_ERR("%5d cannot locate '%s'...\n", pid, sym_name);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
*got = 0;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
/* FIXME: is this sufficient?
|
||||||
|
* For reference see NetBSD link loader
|
||||||
|
* http://cvsweb.netbsd.org/bsdweb.cgi/src/libexec/ld.elf_so/arch/mips/mips_reloc.c?rev=1.53&content-type=text/x-cvsweb-markup
|
||||||
|
*/
|
||||||
|
*got = base + s->st_value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Please read the "Initialization and Termination functions" functions.
|
/* Please read the "Initialization and Termination functions" functions.
|
||||||
* of the linker design note in bionic/linker/README.TXT to understand
|
* of the linker design note in bionic/linker/README.TXT to understand
|
||||||
* what the following code is doing.
|
* what the following code is doing.
|
||||||
@ -1442,8 +1531,10 @@ static int soinfo_link_image(soinfo *si, unsigned wr_offset)
|
|||||||
si->plt_got = (unsigned *)(base + *d);
|
si->plt_got = (unsigned *)(base + *d);
|
||||||
break;
|
break;
|
||||||
case DT_DEBUG:
|
case DT_DEBUG:
|
||||||
|
#if !defined(ANDROID_MIPS_LINKER)
|
||||||
// Set the DT_DEBUG entry to the addres of _r_debug for GDB
|
// Set the DT_DEBUG entry to the addres of _r_debug for GDB
|
||||||
*d = (int) &_r_debug;
|
*d = (int) &_r_debug;
|
||||||
|
#endif
|
||||||
break;
|
break;
|
||||||
case DT_RELA:
|
case DT_RELA:
|
||||||
DL_ERR("%5d DT_RELA not supported", pid);
|
DL_ERR("%5d DT_RELA not supported", pid);
|
||||||
@ -1491,6 +1582,50 @@ static int soinfo_link_image(soinfo *si, unsigned wr_offset)
|
|||||||
DEBUG("%5d Text segment should be writable during relocation.\n",
|
DEBUG("%5d Text segment should be writable during relocation.\n",
|
||||||
pid);
|
pid);
|
||||||
break;
|
break;
|
||||||
|
#if defined(ANDROID_MIPS_LINKER)
|
||||||
|
case DT_NEEDED:
|
||||||
|
case DT_STRSZ:
|
||||||
|
case DT_SYMENT:
|
||||||
|
case DT_RELENT:
|
||||||
|
break;
|
||||||
|
case DT_MIPS_RLD_MAP:
|
||||||
|
/* Set the DT_MIPS_RLD_MAP entry to the addres of _r_debug for GDB */
|
||||||
|
{
|
||||||
|
struct r_debug **dp = (struct r_debug **)*d;
|
||||||
|
*dp = &_r_debug;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case DT_MIPS_RLD_VERSION:
|
||||||
|
case DT_MIPS_FLAGS:
|
||||||
|
case DT_MIPS_BASE_ADDRESS:
|
||||||
|
case DT_MIPS_UNREFEXTNO:
|
||||||
|
case DT_MIPS_RWPLT:
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DT_MIPS_PLTGOT:
|
||||||
|
#if 0
|
||||||
|
/* not yet... */
|
||||||
|
si->mips_pltgot = (unsigned *)(si->base + *d);
|
||||||
|
#endif
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DT_MIPS_SYMTABNO:
|
||||||
|
si->mips_symtabno = *d;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DT_MIPS_LOCAL_GOTNO:
|
||||||
|
si->mips_local_gotno = *d;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DT_MIPS_GOTSYM:
|
||||||
|
si->mips_gotsym = *d;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
DEBUG("%5d Unused DT entry: type 0x%08x arg 0x%08x\n",
|
||||||
|
pid, d[-1], d[0]);
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1552,6 +1687,12 @@ static int soinfo_link_image(soinfo *si, unsigned wr_offset)
|
|||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef ANDROID_MIPS_LINKER
|
||||||
|
if(mips_relocate_got(si)) {
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
si->flags |= FLAG_LINKED;
|
si->flags |= FLAG_LINKED;
|
||||||
DEBUG("[ %5d finished linking %s ]\n", pid, si->name);
|
DEBUG("[ %5d finished linking %s ]\n", pid, si->name);
|
||||||
|
|
||||||
|
@ -150,11 +150,19 @@ struct soinfo
|
|||||||
void (*init_func)(void);
|
void (*init_func)(void);
|
||||||
void (*fini_func)(void);
|
void (*fini_func)(void);
|
||||||
|
|
||||||
#ifdef ANDROID_ARM_LINKER
|
#if defined(ANDROID_ARM_LINKER)
|
||||||
/* ARM EABI section used for stack unwinding. */
|
/* ARM EABI section used for stack unwinding. */
|
||||||
unsigned *ARM_exidx;
|
unsigned *ARM_exidx;
|
||||||
unsigned ARM_exidx_count;
|
unsigned ARM_exidx_count;
|
||||||
|
#elif defined(ANDROID_MIPS_LINKER)
|
||||||
|
#if 0
|
||||||
|
/* not yet */
|
||||||
|
unsigned *mips_pltgot
|
||||||
#endif
|
#endif
|
||||||
|
unsigned mips_symtabno;
|
||||||
|
unsigned mips_local_gotno;
|
||||||
|
unsigned mips_gotsym;
|
||||||
|
#endif /* ANDROID_*_LINKER */
|
||||||
|
|
||||||
unsigned refcount;
|
unsigned refcount;
|
||||||
struct link_map linkmap;
|
struct link_map linkmap;
|
||||||
@ -169,29 +177,31 @@ struct soinfo
|
|||||||
|
|
||||||
extern soinfo libdl_info;
|
extern soinfo libdl_info;
|
||||||
|
|
||||||
#ifdef ANDROID_ARM_LINKER
|
|
||||||
|
|
||||||
|
#include <asm/elf.h>
|
||||||
|
|
||||||
|
#if defined(ANDROID_ARM_LINKER)
|
||||||
|
|
||||||
|
// These aren't defined in <arch-arm/asm/elf.h>.
|
||||||
|
#define R_ARM_REL32 3
|
||||||
#define R_ARM_COPY 20
|
#define R_ARM_COPY 20
|
||||||
#define R_ARM_GLOB_DAT 21
|
#define R_ARM_GLOB_DAT 21
|
||||||
#define R_ARM_JUMP_SLOT 22
|
#define R_ARM_JUMP_SLOT 22
|
||||||
#define R_ARM_RELATIVE 23
|
#define R_ARM_RELATIVE 23
|
||||||
|
|
||||||
/* According to the AAPCS specification, we only
|
#elif defined(ANDROID_MIPS_LINKER)
|
||||||
* need the above relocations. However, in practice,
|
|
||||||
* the following ones turn up from time to time.
|
// These aren't defined in <arch-arm/mips/elf.h>.
|
||||||
*/
|
#define R_MIPS_JUMP_SLOT 127
|
||||||
#define R_ARM_ABS32 2
|
|
||||||
#define R_ARM_REL32 3
|
#define DT_MIPS_PLTGOT 0x70000032
|
||||||
|
#define DT_MIPS_RWPLT 0x70000034
|
||||||
|
|
||||||
#elif defined(ANDROID_X86_LINKER)
|
#elif defined(ANDROID_X86_LINKER)
|
||||||
|
|
||||||
#define R_386_32 1
|
// x86 has everything it needs in <arch-arm/x86/elf.h>.
|
||||||
#define R_386_PC32 2
|
|
||||||
#define R_386_GLOB_DAT 6
|
|
||||||
#define R_386_JUMP_SLOT 7
|
|
||||||
#define R_386_RELATIVE 8
|
|
||||||
|
|
||||||
#endif
|
#endif /* ANDROID_*_LINKER */
|
||||||
|
|
||||||
#ifndef DT_INIT_ARRAY
|
#ifndef DT_INIT_ARRAY
|
||||||
#define DT_INIT_ARRAY 25
|
#define DT_INIT_ARRAY 25
|
||||||
@ -227,10 +237,10 @@ Elf32_Sym *soinfo_find_symbol(soinfo* si, const void *addr);
|
|||||||
Elf32_Sym *soinfo_lookup(soinfo *si, const char *name);
|
Elf32_Sym *soinfo_lookup(soinfo *si, const char *name);
|
||||||
void soinfo_call_constructors(soinfo *si);
|
void soinfo_call_constructors(soinfo *si);
|
||||||
|
|
||||||
#ifdef ANDROID_ARM_LINKER
|
#if defined(ANDROID_ARM_LINKER)
|
||||||
typedef long unsigned int *_Unwind_Ptr;
|
typedef long unsigned int *_Unwind_Ptr;
|
||||||
_Unwind_Ptr dl_unwind_find_exidx(_Unwind_Ptr pc, int *pcount);
|
_Unwind_Ptr dl_unwind_find_exidx(_Unwind_Ptr pc, int *pcount);
|
||||||
#elif defined(ANDROID_X86_LINKER)
|
#elif defined(ANDROID_X86_LINKER) || defined(ANDROID_MIPS_LINKER)
|
||||||
int dl_iterate_phdr(int (*cb)(struct dl_phdr_info *, size_t, void *), void *);
|
int dl_iterate_phdr(int (*cb)(struct dl_phdr_info *, size_t, void *), void *);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -413,20 +413,6 @@ format_integer(char *buffer, size_t buffsize, uint64_t value, int base, int isSi
|
|||||||
format_number(buffer, buffsize, value, base, "0123456789");
|
format_number(buffer, buffsize, value, base, "0123456789");
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Write an octal into a buffer, assumes buffsize > 2 */
|
|
||||||
static void
|
|
||||||
format_octal(char *buffer, size_t buffsize, uint64_t value, int isSigned)
|
|
||||||
{
|
|
||||||
format_integer(buffer, buffsize, value, 8, isSigned);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Write a decimal into a buffer, assumes buffsize > 2 */
|
|
||||||
static void
|
|
||||||
format_decimal(char *buffer, size_t buffsize, uint64_t value, int isSigned)
|
|
||||||
{
|
|
||||||
format_integer(buffer, buffsize, value, 10, isSigned);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Write an hexadecimal into a buffer, isCap is true for capital alphas.
|
/* Write an hexadecimal into a buffer, isCap is true for capital alphas.
|
||||||
* Assumes bufsize > 2 */
|
* Assumes bufsize > 2 */
|
||||||
static void
|
static void
|
||||||
|
Loading…
Reference in New Issue
Block a user