diff --git a/src/elfmerge/elf_link_common.h b/src/elfmerge/elf_link_common.h index 1db7b96be3baed5aba760ad9a79f8ef2b9da98d3..3f142e70a518acf653582f06ba1be57553ed0b04 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 6edaa2ff7b68dce66d4d58d2ebf5c90e131e29fa..75fb45c287739a57e45c9ba04d764bc976a31638 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 f74b2904d0d0415868a4b5791bfe048561f7e28f..af4b3673fb04c1999a8732318faea3d4ae091da3 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 c9f83d9003fb987cb69842ba536d1d37b048dc36..6e06de31c558889bf4753d7fa7cb6bd760778c1e 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 cfcd600d0623f870d2d1b8043237ef9e59abc696..bb0222d07d429888d6933e687178eb294c393edc 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; }