added and modified linker to support SuperH architecture
This commit is contained in:
parent
92b10af793
commit
ad13c57298
@ -9,7 +9,12 @@ LOCAL_SRC_FILES:= \
|
||||
debugger.c \
|
||||
ba.c
|
||||
|
||||
ifeq ($(TARGET_ARCH),sh)
|
||||
# SH-4A series virtual address range from 0x00000000 to 0x7FFFFFFF.
|
||||
LINKER_TEXT_BASE := 0x70000100
|
||||
else
|
||||
LINKER_TEXT_BASE := 0xB0000100
|
||||
endif
|
||||
|
||||
# The maximum size set aside for the linker, from
|
||||
# LINKER_TEXT_BASE rounded down to a megabyte.
|
||||
@ -31,7 +36,11 @@ else
|
||||
ifeq ($(TARGET_ARCH),x86)
|
||||
LOCAL_CFLAGS += -DANDROID_X86_LINKER
|
||||
else
|
||||
$(error Unsupported TARGET_ARCH $(TARGET_ARCH))
|
||||
ifeq ($(TARGET_ARCH),sh)
|
||||
LOCAL_CFLAGS += -DANDROID_SH_LINKER
|
||||
else
|
||||
$(error Unsupported TARGET_ARCH $(TARGET_ARCH))
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
||||
|
50
linker/arch/sh/begin.S
Normal file
50
linker/arch/sh/begin.S
Normal file
@ -0,0 +1,50 @@
|
||||
/*
|
||||
* Copyright (C) 2009 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
|
||||
.globl _start
|
||||
|
||||
_start:
|
||||
mov r15, r4
|
||||
|
||||
mov.l 0f, r0
|
||||
jsr @r0
|
||||
nop
|
||||
|
||||
/* linker init returns the _entry address in the main image */
|
||||
jmp @r0
|
||||
nop
|
||||
|
||||
.balign 4
|
||||
0: .long __linker_init
|
||||
|
||||
.section .ctors, "wa"
|
||||
.globl __CTOR_LIST__
|
||||
__CTOR_LIST__:
|
||||
.long -1
|
@ -137,6 +137,12 @@ int dlclose(void *handle)
|
||||
#define ANDROID_LIBDL_STRTAB \
|
||||
"dlopen\0dlclose\0dlsym\0dlerror\0dl_iterate_phdr\0"
|
||||
|
||||
#elif defined(ANDROID_SH_LINKER)
|
||||
// 0000000 00011111 111112 22222222 2333333333344444
|
||||
// 0123456 78901234 567890 12345678 9012345678901234
|
||||
#define ANDROID_LIBDL_STRTAB \
|
||||
"dlopen\0dlclose\0dlsym\0dlerror\0dl_iterate_phdr\0"
|
||||
|
||||
#else /* !defined(ANDROID_ARM_LINKER) && !defined(ANDROID_X86_LINKER) */
|
||||
#error Unsupported architecture. Only ARM and x86 are presently supported.
|
||||
#endif
|
||||
@ -181,6 +187,12 @@ static Elf32_Sym libdl_symtab[] = {
|
||||
st_info: STB_GLOBAL << 4,
|
||||
st_shndx: 1,
|
||||
},
|
||||
#elif defined(ANDROID_SH_LINKER)
|
||||
{ st_name: 29,
|
||||
st_value: (Elf32_Addr) &dl_iterate_phdr,
|
||||
st_info: STB_GLOBAL << 4,
|
||||
st_shndx: 1,
|
||||
},
|
||||
#endif
|
||||
};
|
||||
|
||||
|
131
linker/linker.c
131
linker/linker.c
@ -345,7 +345,7 @@ _Unwind_Ptr dl_unwind_find_exidx(_Unwind_Ptr pc, int *pcount)
|
||||
*pcount = 0;
|
||||
return NULL;
|
||||
}
|
||||
#elif defined(ANDROID_X86_LINKER)
|
||||
#elif defined(ANDROID_X86_LINKER) || defined(ANDROID_SH_LINKER)
|
||||
/* Here, we only have to provide a callback to iterate across all the
|
||||
* loaded libraries. gcc_eh does the rest. */
|
||||
int
|
||||
@ -1294,6 +1294,100 @@ static int reloc_library(soinfo *si, Elf32_Rel *rel, unsigned count)
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if defined(ANDROID_SH_LINKER)
|
||||
static int reloc_library_a(soinfo *si, Elf32_Rela *rela, unsigned count)
|
||||
{
|
||||
Elf32_Sym *symtab = si->symtab;
|
||||
const char *strtab = si->strtab;
|
||||
Elf32_Sym *s;
|
||||
unsigned base;
|
||||
Elf32_Rela *start = rela;
|
||||
unsigned idx;
|
||||
|
||||
for (idx = 0; idx < count; ++idx) {
|
||||
unsigned type = ELF32_R_TYPE(rela->r_info);
|
||||
unsigned sym = ELF32_R_SYM(rela->r_info);
|
||||
unsigned reloc = (unsigned)(rela->r_offset + si->base);
|
||||
unsigned sym_addr = 0;
|
||||
char *sym_name = NULL;
|
||||
|
||||
DEBUG("%5d Processing '%s' relocation at index %d\n", pid,
|
||||
si->name, idx);
|
||||
if(sym != 0) {
|
||||
sym_name = (char *)(strtab + symtab[sym].st_name);
|
||||
s = _do_lookup(si, sym_name, &base);
|
||||
if(s == 0) {
|
||||
DL_ERR("%5d cannot locate '%s'...", pid, sym_name);
|
||||
return -1;
|
||||
}
|
||||
#if 0
|
||||
if((base == 0) && (si->base != 0)){
|
||||
/* linking from libraries to main image is bad */
|
||||
DL_ERR("%5d cannot locate '%s'...",
|
||||
pid, strtab + symtab[sym].st_name);
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
if ((s->st_shndx == SHN_UNDEF) && (s->st_value != 0)) {
|
||||
DL_ERR("%5d In '%s', shndx=%d && value=0x%08x. We do not "
|
||||
"handle this yet", pid, si->name, s->st_shndx,
|
||||
s->st_value);
|
||||
return -1;
|
||||
}
|
||||
sym_addr = (unsigned)(s->st_value + base);
|
||||
COUNT_RELOC(RELOC_SYMBOL);
|
||||
} else {
|
||||
s = 0;
|
||||
}
|
||||
|
||||
/* TODO: This is ugly. Split up the relocations by arch into
|
||||
* different files.
|
||||
*/
|
||||
switch(type){
|
||||
case R_SH_JUMP_SLOT:
|
||||
COUNT_RELOC(RELOC_ABSOLUTE);
|
||||
MARK(rela->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_SH_GLOB_DAT:
|
||||
COUNT_RELOC(RELOC_ABSOLUTE);
|
||||
MARK(rela->r_offset);
|
||||
TRACE_TYPE(RELO, "%5d RELO GLOB_DAT %08x <- %08x %s\n", pid,
|
||||
reloc, sym_addr, sym_name);
|
||||
*((unsigned*)reloc) = sym_addr;
|
||||
break;
|
||||
case R_SH_DIR32:
|
||||
COUNT_RELOC(RELOC_ABSOLUTE);
|
||||
MARK(rela->r_offset);
|
||||
TRACE_TYPE(RELO, "%5d RELO DIR32 %08x <- %08x %s\n", pid,
|
||||
reloc, sym_addr, sym_name);
|
||||
*((unsigned*)reloc) += sym_addr;
|
||||
break;
|
||||
case R_SH_RELATIVE:
|
||||
COUNT_RELOC(RELOC_RELATIVE);
|
||||
MARK(rela->r_offset);
|
||||
if(sym){
|
||||
DL_ERR("%5d odd RELATIVE form...", pid);
|
||||
return -1;
|
||||
}
|
||||
TRACE_TYPE(RELO, "%5d RELO RELATIVE %08x <- +%08x\n", pid,
|
||||
reloc, si->base);
|
||||
*((unsigned*)reloc) += si->base;
|
||||
break;
|
||||
|
||||
default:
|
||||
DL_ERR("%5d unknown reloc type %d @ %p (%d)",
|
||||
pid, type, rela, (int) (rela - start));
|
||||
return -1;
|
||||
}
|
||||
rela++;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#endif /* ANDROID_SH_LINKER */
|
||||
|
||||
|
||||
/* Please read the "Initialization and Termination functions" functions.
|
||||
* of the linker design note in bionic/linker/README.TXT to understand
|
||||
@ -1546,24 +1640,40 @@ static int link_image(soinfo *si, unsigned wr_offset)
|
||||
case DT_SYMTAB:
|
||||
si->symtab = (Elf32_Sym *) (si->base + *d);
|
||||
break;
|
||||
#if !defined(ANDROID_SH_LINKER)
|
||||
case DT_PLTREL:
|
||||
if(*d != DT_REL) {
|
||||
DL_ERR("DT_RELA not supported");
|
||||
goto fail;
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
#ifdef ANDROID_SH_LINKER
|
||||
case DT_JMPREL:
|
||||
si->plt_rela = (Elf32_Rela*) (si->base + *d);
|
||||
break;
|
||||
case DT_PLTRELSZ:
|
||||
si->plt_rela_count = *d / sizeof(Elf32_Rela);
|
||||
break;
|
||||
#else
|
||||
case DT_JMPREL:
|
||||
si->plt_rel = (Elf32_Rel*) (si->base + *d);
|
||||
break;
|
||||
case DT_PLTRELSZ:
|
||||
si->plt_rel_count = *d / 8;
|
||||
break;
|
||||
#endif
|
||||
case DT_REL:
|
||||
si->rel = (Elf32_Rel*) (si->base + *d);
|
||||
break;
|
||||
case DT_RELSZ:
|
||||
si->rel_count = *d / 8;
|
||||
break;
|
||||
#ifdef ANDROID_SH_LINKER
|
||||
case DT_RELASZ:
|
||||
si->rela_count = *d / sizeof(Elf32_Rela);
|
||||
break;
|
||||
#endif
|
||||
case DT_PLTGOT:
|
||||
/* Save this in case we decide to do lazy binding. We don't yet. */
|
||||
si->plt_got = (unsigned *)(si->base + *d);
|
||||
@ -1572,9 +1682,15 @@ static int link_image(soinfo *si, unsigned wr_offset)
|
||||
// Set the DT_DEBUG entry to the addres of _r_debug for GDB
|
||||
*d = (int) &_r_debug;
|
||||
break;
|
||||
#ifdef ANDROID_SH_LINKER
|
||||
case DT_RELA:
|
||||
si->rela = (Elf32_Rela *) (si->base + *d);
|
||||
break;
|
||||
#else
|
||||
case DT_RELA:
|
||||
DL_ERR("%5d DT_RELA not supported", pid);
|
||||
goto fail;
|
||||
#endif
|
||||
case DT_INIT:
|
||||
si->init_func = (void (*)(void))(si->base + *d);
|
||||
DEBUG("%5d %s constructors (init func) found at %p\n",
|
||||
@ -1654,6 +1770,19 @@ static int link_image(soinfo *si, unsigned wr_offset)
|
||||
goto fail;
|
||||
}
|
||||
|
||||
#ifdef ANDROID_SH_LINKER
|
||||
if(si->plt_rela) {
|
||||
DEBUG("[ %5d relocating %s plt ]\n", pid, si->name );
|
||||
if(reloc_library_a(si, si->plt_rela, si->plt_rela_count))
|
||||
goto fail;
|
||||
}
|
||||
if(si->rela) {
|
||||
DEBUG("[ %5d relocating %s ]\n", pid, si->name );
|
||||
if(reloc_library_a(si, si->rela, si->rela_count))
|
||||
goto fail;
|
||||
}
|
||||
#endif /* ANDROID_SH_LINKER */
|
||||
|
||||
si->flags |= FLAG_LINKED;
|
||||
DEBUG("[ %5d finished linking %s ]\n", pid, si->name);
|
||||
|
||||
|
@ -122,6 +122,14 @@ struct soinfo
|
||||
Elf32_Rel *rel;
|
||||
unsigned rel_count;
|
||||
|
||||
#ifdef ANDROID_SH_LINKER
|
||||
Elf32_Rela *plt_rela;
|
||||
unsigned plt_rela_count;
|
||||
|
||||
Elf32_Rela *rela;
|
||||
unsigned rela_count;
|
||||
#endif /* ANDROID_SH_LINKER */
|
||||
|
||||
unsigned *preinit_array;
|
||||
unsigned preinit_array_count;
|
||||
|
||||
@ -147,10 +155,15 @@ struct soinfo
|
||||
extern soinfo libdl_info;
|
||||
|
||||
/* these must all be powers of two */
|
||||
#ifdef ARCH_SH
|
||||
#define LIBBASE 0x60000000
|
||||
#define LIBLAST 0x70000000
|
||||
#define LIBINC 0x00100000
|
||||
#else
|
||||
#define LIBBASE 0x80000000
|
||||
#define LIBLAST 0x90000000
|
||||
#define LIBINC 0x00100000
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef ANDROID_ARM_LINKER
|
||||
|
||||
@ -167,6 +180,13 @@ extern soinfo libdl_info;
|
||||
#define R_386_JUMP_SLOT 7
|
||||
#define R_386_RELATIVE 8
|
||||
|
||||
#elif defined(ANDROID_SH_LINKER)
|
||||
|
||||
#define R_SH_DIR32 1
|
||||
#define R_SH_GLOB_DAT 163
|
||||
#define R_SH_JUMP_SLOT 164
|
||||
#define R_SH_RELATIVE 165
|
||||
|
||||
#endif /* ANDROID_*_LINKER */
|
||||
|
||||
|
||||
@ -209,7 +229,7 @@ const char *linker_get_error(void);
|
||||
#ifdef ANDROID_ARM_LINKER
|
||||
typedef long unsigned int *_Unwind_Ptr;
|
||||
_Unwind_Ptr dl_unwind_find_exidx(_Unwind_Ptr pc, int *pcount);
|
||||
#elif defined(ANDROID_X86_LINKER)
|
||||
#elif defined(ANDROID_X86_LINKER) || defined(ANDROID_SH_LINKER)
|
||||
int dl_iterate_phdr(int (*cb)(struct dl_phdr_info *, size_t, void *), void *);
|
||||
#endif
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user