From 39d13fa5f83f40c0c92f5acc34ccc85a0fc29fc8 Mon Sep 17 00:00:00 2001 From: yangpan Date: Thu, 4 Jan 2024 10:46:44 +0800 Subject: [PATCH] =?UTF-8?q?=E4=B8=8D=E4=BE=9D=E8=B5=96relocation=E4=BF=A1?= =?UTF-8?q?=E6=81=AF=E4=BF=AE=E6=94=B9data=E6=AE=B5=E9=9C=80=E9=87=8D?= =?UTF-8?q?=E5=AE=9A=E4=BD=8D=E7=9A=84=E5=8F=98=E9=87=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/elfmerge/elf_link_common.h | 3 ++ src/elfmerge/elf_link_elf.c | 6 +++ src/elfmerge/elf_relocation.h | 1 + src/elfmerge/elf_relocation_aarch64.c | 66 +++++++++++++++++++++++++++ src/elfmerge/main.c | 4 ++ 5 files changed, 80 insertions(+) diff --git a/src/elfmerge/elf_link_common.h b/src/elfmerge/elf_link_common.h index 1db7b96..3f142e7 100644 --- a/src/elfmerge/elf_link_common.h +++ b/src/elfmerge/elf_link_common.h @@ -51,6 +51,8 @@ #define ELF_LINK_STATIC_NOLIBC_S "static-nolibc" #define ELF_LINK_STATIC_NOLD_S "static-nold" +#define RELOC_FLAG (1<<0) + enum RtoMode { ELF_LINK_SHARE = 0, ELF_LINK_STATIC, @@ -78,6 +80,7 @@ typedef struct { elf_file_t out_ef; unsigned int in_ef_nr; unsigned int link_mode; + unsigned int flags; elf_file_t vdso_ef; elf_file_t ld_ef; diff --git a/src/elfmerge/elf_link_elf.c b/src/elfmerge/elf_link_elf.c index 6edaa2f..75fb45c 100644 --- a/src/elfmerge/elf_link_elf.c +++ b/src/elfmerge/elf_link_elf.c @@ -67,6 +67,7 @@ elf_link_t *elf_link_new(void) elf_link->direct_call_optimize = false; elf_link->direct_vdso_optimize = false; elf_link->delete_symbol_version = true; + elf_link->flags |= RELOC_FLAG; // out file not create elf_link->out_ef.fd = -1; @@ -1834,6 +1835,11 @@ int elf_link_write(elf_link_t *elf_link) /* .init .plt .text .fini */ modify_text_section(elf_link); + /*代替modify_local_call的.rela.data, .rela.data.rel.ro, .rela.init_array .rela.fini_array部分*/ + if (!elf_link->flags & RELOC_FLAG) { + modify_data_section(elf_link); + } + // modify local call to use jump // .rela.init .rela.text .rela.rodata .rela.tdata .rela.init_array .rela.data modify_local_call(elf_link); diff --git a/src/elfmerge/elf_relocation.h b/src/elfmerge/elf_relocation.h index f74b290..af4b367 100644 --- a/src/elfmerge/elf_relocation.h +++ b/src/elfmerge/elf_relocation.h @@ -21,6 +21,7 @@ void modify_rela_dyn(elf_link_t *elf_link); void modify_got(elf_link_t *elf_link); void modify_local_call(elf_link_t *elf_link); void modify_text_section(elf_link_t *elf_link); +void modify_data_section(elf_link_t *elf_link); int modify_local_call_rela(elf_link_t *elf_link, elf_file_t *ef, Elf64_Rela *rela); void modify_rela_plt(elf_link_t *elf_link, si_array_t *arr); diff --git a/src/elfmerge/elf_relocation_aarch64.c b/src/elfmerge/elf_relocation_aarch64.c index c9f83d9..6e06de3 100644 --- a/src/elfmerge/elf_relocation_aarch64.c +++ b/src/elfmerge/elf_relocation_aarch64.c @@ -512,6 +512,72 @@ int modify_text_section(elf_link_t *elf_link) return ret; } +int modify_by_rela_dyn(elf_link_t *elf_link, elf_file_t *ef, Elf64_Shdr *dyn_sec, Elf64_Shdr *sec) +{ + int len = dyn_sec->sh_size / dyn_sec->sh_entsize; + Elf64_Rela *relas = (void *)ef->hdr + dyn_sec->sh_offset; + Elf64_Rela *rela = NULL; + unsigned long sec_start, sec_end; + unsigned long old_addr = 0, new_addr = 0; + unsigned long old_offset = 0, new_offset = 0; + elf_file_t *out_ef = &elf_link->out_ef; + char *name = NULL; + + if(!dyn_sec || !sec) { + SI_LOG_ERR("section is NUll\n"); + return -1; + } + sec_start = sec->sh_addr; + sec_end = sec_start + sec->sh_size; + name = elf_get_section_name(ef, sec); + SI_LOG_EMERG("modify_by_rela_dyn: %s section start %lx end %lx\n", name, sec_start, sec_end); + for (int i = 0; i < len; i++) { + rela = &relas[i]; + if (sec_start <= rela->r_offset && rela->r_offset < sec_end) { + /* bash.relocation和libtinfo.so.6.4.relocation中 */ + /* .rela.dyn只有R_AARCH64_RELATIVE和R_AARCH64_GLOB_DAT两种类型 */ + /* 根据地址判断,R_AARCH64_GLOB_DAT只包含got表中重定位,暂时无相应修改 */ + switch (ELF64_R_TYPE(rela->r_info)){ + case R_AARCH64_RELATIVE: + old_offset = rela->r_offset; + new_offset = get_new_addr_by_old_addr(elf_link, ef, old_offset); + old_addr = rela->r_addend; + new_addr = get_new_addr_by_old_addr(elf_link, ef, old_addr); + elf_write_u64(out_ef, new_offset, new_addr); + SI_LOG_EMERG("change offset %lx->%lx content %lx->%lx\n", + old_offset, new_offset, old_addr, new_addr); + default: + continue; + } + } + } + return 0; +} +void modify_data_section(elf_link_t *elf_link) +{ + elf_file_t *ef; + int count = elf_link->in_ef_nr; + Elf64_Shdr *rela_dyn_sec, *data_sec, *data_rel_ro_sec, *init_array_sec, *fini_array_sec; + + for (int i = 0; i < count; i++) { + ef = &elf_link->in_efs[i]; + /* sysboost_static_template暂不支持 */ + if (!strcmp(ef->file_name, "/usr/lib/relocation/sysboost_static_template.relocation")) + continue; + SI_LOG_EMERG("file name %s\n", ef->file_name); + rela_dyn_sec = elf_find_section_by_name(ef, ".rela.dyn"); + data_sec = elf_find_section_by_name(ef, ".data"); + data_rel_ro_sec = elf_find_section_by_name(ef, ".data.rel.ro"); + init_array_sec = elf_find_section_by_name(ef, ".init_array"); + fini_array_sec = elf_find_section_by_name(ef, ".fini_array"); + modify_by_rela_dyn(elf_link, ef, rela_dyn_sec, data_sec); + modify_by_rela_dyn(elf_link, ef, rela_dyn_sec, data_rel_ro_sec); + modify_by_rela_dyn(elf_link, ef, rela_dyn_sec, init_array_sec); + modify_by_rela_dyn(elf_link, ef, rela_dyn_sec, fini_array_sec); + } + return; +} + // B // Branch causes an unconditional branch to a label at a PC-relative offset, with a hint that this is not a subroutine call or return. // Format diff --git a/src/elfmerge/main.c b/src/elfmerge/main.c index cfcd600..bb0222d 100644 --- a/src/elfmerge/main.c +++ b/src/elfmerge/main.c @@ -55,6 +55,7 @@ int main(int argc, char *argv[]) {"unset-rto", required_argument, NULL, '0'}, {"get-rto", required_argument, NULL, '2'}, {"hook", no_argument, NULL, 'h'}, + {"noreloc", no_argument, NULL, 'r'}, {ELF_LINK_STATIC_S, no_argument, NULL, 'S'}, {ELF_LINK_STATIC_NOLIBC_S, no_argument, NULL, 'N'}, {ELF_LINK_STATIC_NOLD_S, no_argument, NULL, 'I'}, @@ -122,6 +123,9 @@ int main(int argc, char *argv[]) case 'I': mode = ELF_LINK_STATIC_NOLD; break; + case 'r': + elf_link->flags &= (!RELOC_FLAG); + break; default: return -1; } -- Gitee