我根据android5.0的linker源码,自己实现了一个加载64位so的功能,将加载so文件换成了加载so的字节数组,不过有一个问题
for (ElfW(Dyn)* d = si->dynamic; d->d_tag != DT_NULL; ++d) {
if (d->d_tag == DT_NEEDED) {
const char* library_name = si->strtab + d->d_un.d_val;
DEBUG("%s needs %s", si->name, library_name);
soinfo* lsi = find_library(library_name, 0, NULL);
if (lsi == NULL) {
strlcpy(tmp_err_buf, linker_get_error_buffer(), sizeof(tmp_err_buf));
DL_ERR("could not load library \"%s\" needed by \"%s\"; caused by %s",
library_name, si->name, tmp_err_buf);
return false;
}
si->add_child(lsi);
*pneeded++ = lsi;
}
}
我看网上有人将 soinfo lsi = find_library(library_name, 0, NULL)*; 修改为了dlopen,并且因为7.0后没有返回soinfo,它这里就没有做 si->add_child(lsi);处理
soinfo_relocate中:
if (sym != 0) {
sym_name = reinterpret_cast<const char*>(si->strtab + si->symtab[sym].st_name);
_ s = soinfo_do_lookup(si, sym_name, &lsi, needed);_
if (s == NULL) {
// We only allow an undefined symbol if this is a weak reference...
s = &si->symtab[sym];
if (ELF_ST_BIND(s->st_info) != STB_WEAK) {
DL_ERR("cannot locate symbol \"%s\" referenced by \"%s\"...", sym_name, si->name);
return -1;
}
s = soinfo_do_lookup(si, sym_name, &lsi, needed); 这里,直接用dlsym返回地址
我参考的是这个地址:https://blog.csdn.net/u010559109/article/details/120460886
请问有没有试过内存加载so字节数组的。代码修改完成后,经常闪退,找不到原因
Fatal signal 11 (SIGSEGV), code 2 (SEGV_ACCERR), fault addr 0x7058ce0760 in tid 8737 (pool-1-thread-1), pid 8686 (com.test.loader)
Android5.0源码:http://aospxref.com/android-5.0.2_r3/xref/bionic/linker/
附部分我结合linker5.0源码修改后的代码
bool ElfReader::ReadElfHeader() {
memcpy(&header_, elfData_, sizeof(header_));
return true;
}
void *mmap_result = mmap(NULL, phdr_size_, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS,
-1, 0);
if (mmap_result == MAP_FAILED) {
DL_ERR("\"%s\" phdr mmap failed: %s", name_, strerror(errno));
return false;
}
memcpy(mmap_result, elfData_ + page_min, phdr_size_);
phdr_mmap_ = mmap_result;
phdr_table_ = reinterpret_cast<ElfW(Phdr) *>(reinterpret_cast<char *>(mmap_result) +
page_offset);
mprotect(reinterpret_cast<void *>(seg_page_start), seg_page_end - seg_page_start,
PROT_WRITE);
if (file_length != 0) {
memcpy(reinterpret_cast<void *>(seg_page_start), elfData_ + file_page_start,
file_length);
}
if (sym != 0) {
bool isNeed = false;
sym_name = reinterpret_cast<const char *>(si->strtab + si->symtab[sym].st_name);
unsigned elf_hash = elfhash(sym_name);
//先从本si拿
ElfW(Sym) *s = soinfo_elf_lookup(si, elf_hash, sym_name);
if (s != NULL) {
sym_addr = static_cast<ElfW(Addr)>(s->st_value + si->load_bias);
} else {
//再从依赖里面拿
for (int i = 0; i < needed_count; i++) {
uintptr_t value = needed[i];
void *handle = reinterpret_cast<void *>(value);
sym_addr = reinterpret_cast<ElfW(Addr)>(dlsym(handle, sym_name));
if (sym_addr) {
isNeed = true;
break;
}
}
}
if (s == NULL && !isNeed) {
// We only allow an undefined symbol if this is a weak reference...
s = &si->symtab[sym];
if (ELF_ST_BIND(s->st_info) != STB_WEAK) {
DL_ERR("cannot locate symbol \"%s\" referenced by \"%s\"...", sym_name,
si->name);
return -1;
}