From 8645b3cd97a749643c64d875819fb13884cabb23 Mon Sep 17 00:00:00 2001 From: Zhou Kang Date: Fri, 30 Jun 2023 02:05:00 +0000 Subject: [PATCH] fix addr for ld.so --- src/elf_link_common.c | 32 ++++++++++--- src/elf_link_common.h | 6 ++- src/elf_link_elf.c | 93 ++++++++++++++++++++++++++++--------- src/elf_read_elf.c | 2 +- src/elf_relocation.c | 13 ++++-- src/elf_relocation_x86_64.c | 2 +- tests/test_simple/Makefile | 2 +- 7 files changed, 113 insertions(+), 37 deletions(-) diff --git a/src/elf_link_common.c b/src/elf_link_common.c index 39685e8..5e8d664 100644 --- a/src/elf_link_common.c +++ b/src/elf_link_common.c @@ -91,10 +91,10 @@ void show_symbol_mapping(elf_link_t *elf_link) elf_symbol_mapping_t *sym_maps = elf_link->symbol_mapping_arr->data; elf_symbol_mapping_t *sym_map = NULL; - printf("symbol_name symbol_addr\n"); + SI_LOG_DEBUG("symbol_name symbol_addr\n"); for (int i = 0; i < len; i++) { sym_map = &sym_maps[i]; - printf("%-32s %016lx\n", sym_map->symbol_name, sym_map->symbol_addr); + SI_LOG_DEBUG("%-32s %016lx\n", sym_map->symbol_name, sym_map->symbol_addr); } } @@ -165,23 +165,36 @@ static unsigned long vdso_get_new_addr(Elf64_Sym *sym) return 0UL - PAGE_SIZE + (unsigned long)sym->st_value; } +#ifdef __aarch64__ +// __kernel_clock_gettime #define VDSO_PREFIX_LEN (sizeof("__kernel_") - 1) +#define DL_SYSINFO_DSO_OFFSET (0x2e8) +#else +// __vdso_clock_gettime +#define VDSO_PREFIX_LEN (sizeof("__vdso_") - 1) +#define DL_SYSINFO_DSO_OFFSET (0x2e8) +#endif + static char *vdso_name_to_syscall_name(char *name) { return name + VDSO_PREFIX_LEN; } -// AT_SYSINFO_EHDR is addr of vdso header, but here compute it +// AT_SYSINFO_EHDR is addr of vdso header +// it can not use dlsym to find vdso symbol static unsigned long vdso_hdr_addr_cur() { - // find func in vdso, vdso is only 4K, so get elf hdr by align - unsigned long func = (unsigned long)dlsym(RTLD_DEFAULT, "__kernel_clock_gettime"); + // _rtld_global_ro->_dl_sysinfo_dso, offset is fixed by libc + unsigned long addr = (unsigned long)dlsym(0, "_rtld_global_ro"); char *error = dlerror(); if (error != NULL) { si_panic("%s\n", error); } - - return ALIGN(func, PAGE_SIZE) - PAGE_SIZE; + addr = addr + DL_SYSINFO_DSO_OFFSET; +#ifdef __aarch64__ + si_panic("TODO: DL_SYSINFO_DSO_OFFSET is need check\n"); +#endif + return *(unsigned long *)addr; } void init_vdso_symbol_addr(elf_link_t *elf_link) @@ -233,6 +246,9 @@ void init_ld_symbol_addr(elf_link_t *elf_link) for (int j = 0; j < sym_count; j++) { Elf64_Sym *sym = &syms[j]; char *name = elf_get_dynsym_name(ef, sym); + if (name == NULL || name[0] == '\0') { + continue; + } unsigned long symbol_addr = ld_get_new_addr(hdr_addr, sym); append_symbol_mapping(elf_link, name, symbol_addr); } @@ -251,6 +267,8 @@ void init_symbol_mapping(elf_link_t *elf_link) if (is_direct_vdso_optimize(elf_link) == true) { init_vdso_symbol_addr(elf_link); } + + show_symbol_mapping(elf_link); } void show_sec_mapping(elf_link_t *elf_link) diff --git a/src/elf_link_common.h b/src/elf_link_common.h index 4c6092c..afa91f4 100644 --- a/src/elf_link_common.h +++ b/src/elf_link_common.h @@ -47,6 +47,7 @@ enum RtoMode { ELF_LINK_STATIC_NOLD, }; +/* #define SYSBOOST_DATA_ALIGN (8) #define SYSBOOST_DATA_VERSION (1) #define SYSBOOST_DATA_SEC_NAME ".sysboost_data" @@ -59,6 +60,7 @@ typedef struct { char pad[7]; unsigned long entry_addr; } elf_sysboost_data_t; +*/ typedef struct { elf_file_t in_efs[MAX_ELF_FILE]; @@ -93,7 +95,7 @@ typedef struct { bool hook_func; unsigned long so_path_struct; - elf_sysboost_data_t *sysboost_data; + //elf_sysboost_data_t *sysboost_data; Elf64_Shdr *sysboost_data_sec; } elf_link_t; @@ -166,7 +168,7 @@ static inline elf_file_t *get_template_ef(elf_link_t *elf_link) static inline elf_file_t *get_main_ef(elf_link_t *elf_link) { - if (is_share_mode(elf_link) == true) { + if (is_share_mode(elf_link) || is_static_nold_mode(elf_link)) { return &elf_link->in_efs[0]; } diff --git a/src/elf_link_elf.c b/src/elf_link_elf.c index b9ce90e..61bad71 100644 --- a/src/elf_link_elf.c +++ b/src/elf_link_elf.c @@ -377,6 +377,24 @@ static void append_section(elf_link_t *elf_link, Elf64_Shdr *dst_sec, elf_file_t write_elf_file_section(elf_link, ef, sec, dst_sec); } +static void merge_section(elf_link_t *elf_link, Elf64_Shdr *dst_sec, elf_file_t *ef, Elf64_Shdr *sec) +{ + // in append_section, the first section need change this + dst_sec->sh_offset = 0; + dst_sec->sh_addr = 0; + + append_section(elf_link, dst_sec, ef, sec); + dst_sec->sh_size = elf_link->next_mem_addr - dst_sec->sh_addr; +} + +static void merge_section_with_name(elf_link_t *elf_link, Elf64_Shdr *dst_sec, char *sec_name) +{ + elf_file_t *ef = get_main_ef(elf_link); + Elf64_Shdr *sec = elf_find_section_by_name(ef, sec_name); + merge_section(elf_link, dst_sec, ef, sec); + SI_LOG_DEBUG("section %-20s %08lx %08lx %06lx\n", sec_name, dst_sec->sh_addr, dst_sec->sh_offset, dst_sec->sh_size); +} + static void merge_filter_section(elf_link_t *elf_link, Elf64_Shdr *dst_sec, elf_file_t *ef, section_filter_func filter) { int count = ef->hdr->e_shnum; @@ -410,7 +428,7 @@ static void merge_filter_sections(elf_link_t *elf_link, char *sec_name, section_ } dst_sec->sh_size = elf_link->next_mem_addr - dst_sec->sh_addr; - SI_LOG_DEBUG("merge_filter_sections: section %-20s %08lx %08lx %06lx\n", sec_name, dst_sec->sh_addr, dst_sec->sh_offset, dst_sec->sh_size); + SI_LOG_DEBUG("section %-20s %08lx %08lx %06lx\n", sec_name, dst_sec->sh_addr, dst_sec->sh_offset, dst_sec->sh_size); } static void merge_text_sections(elf_link_t *elf_link) @@ -524,7 +542,7 @@ static void copy_from_old_elf(elf_link_t *elf_link) copy_elf_file(template_ef, 0, out_ef, 0, elf_link->next_file_offset); elf_link->next_mem_addr = elf_link->next_file_offset; - // reserve 3 segment space + // reserve 3 segment space, main ELF may not have TLS segment write_elf_file_zero(elf_link, template_ef->hdr->e_phentsize * 3); // copy old sections, remove RELA @@ -575,6 +593,8 @@ static void modify_INTERP_segment(elf_link_t *elf_link) p->p_offset = tmp_sec->sh_offset; p->p_vaddr = p->p_offset; p->p_paddr = p->p_offset; + p->p_filesz = tmp_sec->sh_size; + p->p_memsz = p->p_filesz; } static void modify_GNU_EH_FRAME_segment(elf_link_t *elf_link) @@ -609,6 +629,7 @@ static void write_so_path_struct(elf_link_t *elf_link) } } +/* static void write_sysboost_section(elf_link_t *elf_link) { if (is_static_mode(elf_link) == false) { @@ -633,9 +654,10 @@ static void write_sysboost_section(elf_link_t *elf_link) sec->sh_entsize = 0; elf_link->sysboost_data_sec = sec; } +*/ // call after .text ready -static void modify_app_entry_addr(elf_link_t *elf_link) +/*static void modify_app_entry_addr(elf_link_t *elf_link) { if (is_static_mode(elf_link) == false) { return; @@ -645,10 +667,10 @@ static void modify_app_entry_addr(elf_link_t *elf_link) unsigned long old_sym_addr = find_sym_old_addr(main_ef, "main"); unsigned long new_sym_addr = get_new_addr_by_old_addr(elf_link, main_ef, old_sym_addr); elf_link->sysboost_data->entry_addr = new_sym_addr; -} +}*/ // call after .shstrtab ready -static void append_sysboost_sec_name(elf_link_t *elf_link) +/*static void append_sysboost_sec_name(elf_link_t *elf_link) { if (is_static_mode(elf_link) == false) { return; @@ -658,29 +680,55 @@ static void append_sysboost_sec_name(elf_link_t *elf_link) unsigned int index = elf_link->out_ef.shstrtab_sec->sh_size; elf_link->sysboost_data_sec->sh_name = index; elf_link->out_ef.shstrtab_sec->sh_size += sizeof(SYSBOOST_DATA_SEC_NAME); +}*/ + +// main ELF and libc.so have .interp, need to ignore it +// .interp .note.gnu.property .note.gnu.build-id .note.ABI-tag +static void write_interp_and_note(elf_link_t *elf_link) +{ + Elf64_Shdr *sec = NULL; + Elf64_Shdr *begin_sec = NULL; + Elf64_Shdr *end_sec = NULL; + char *name = NULL; + + begin_sec = find_tmp_section_by_name(elf_link, ".interp"); + // end is before .gnu.hash + end_sec = find_tmp_section_by_name(elf_link, ".gnu.hash"); + + if (begin_sec == NULL || end_sec == NULL) { + si_panic("section not found\n"); + } + + for (sec = begin_sec; sec < end_sec; sec = sec + 1) { + name = elf_get_tmp_section_name(elf_link, sec); + merge_section_with_name(elf_link, sec, name); + } } // .interp .note.gnu.build-id .note.ABI-tag .gnu.hash .dynsym .dynstr .gnu.version .gnu.version_r .rela.dyn .rela.plt static void write_first_LOAD_segment(elf_link_t *elf_link) { - Elf64_Phdr *p; + Elf64_Phdr *p = NULL; int count = elf_link->out_ef.hdr->e_shnum; Elf64_Shdr *sechdrs = elf_link->out_ef.sechdrs; char *name = NULL; - // first segment sec is SHF_ALLOC, end by SHF_EXECINSTR - for (int i = 1; i < count; i++) { - if (!(sechdrs[i].sh_flags & SHF_ALLOC)) { - continue; - } + // main ELF and libc.so have .interp, need to ignore it + // .interp .note.gnu.property .note.gnu.build-id .note.ABI-tag + write_interp_and_note(elf_link); + + // first sec is .gnu.hash, end by SHF_EXECINSTR + Elf64_Shdr *sec = find_tmp_section_by_name(elf_link, ".gnu.hash"); + int i = sec - sechdrs; + for (; i < count; i++) { if (sechdrs[i].sh_flags & SHF_EXECINSTR) { break; } // write after NOTE section, so it can load in first PAGE memory - if ((sechdrs[i - 1].sh_type == SHT_NOTE) && (sechdrs[i].sh_type != SHT_NOTE)) { + /*if ((sechdrs[i - 1].sh_type == SHT_NOTE) && (sechdrs[i].sh_type != SHT_NOTE)) { write_sysboost_section(elf_link); - } + }*/ name = elf_get_tmp_section_name(elf_link, &sechdrs[i]); if (is_direct_call_optimize(elf_link) == true) { @@ -1367,7 +1415,7 @@ static void write_shstrtab(elf_link_t *elf_link) elf_link->out_ef.shstrtab_data = (char *)elf_link->out_ef.hdr + sec->sh_offset; - append_sysboost_sec_name(elf_link); + //append_sysboost_sec_name(elf_link); } static void modify_section_name_index(elf_link_t *elf_link) @@ -1401,7 +1449,7 @@ static void modify_elf_header(elf_link_t *elf_link) elf_file_t *template_ef = get_template_ef(elf_link); hdr->e_entry = get_new_addr_by_old_addr(elf_link, template_ef, hdr->e_entry); - modify_app_entry_addr(elf_link); + //modify_app_entry_addr(elf_link); // set hugepage flag elf_set_hugepage(elf_link); @@ -1414,7 +1462,7 @@ char *disabled_funcs[] = { "__do_global_dtors_aux", }; #define DISABLED_FUNCS_LEN (sizeof(disabled_funcs) / sizeof(disabled_funcs[0])) -#define AARCH64_INSN_RET 0xD65F03C0 +#define AARCH64_INSN_RET 0xD65F03C0U #define X86_64_INSN_RET 0xC3 static void modify_init_and_fini(elf_link_t *elf_link) { @@ -1498,14 +1546,13 @@ int elf_link_write(elf_link_t *elf_link) return -1; } - // copy first LOAD segment + // copy ELF header and PHDR segment copy_from_old_elf(elf_link); - // elf_show_segments(&elf_link->out_ef); elf_link_write_sections(elf_link); - // PHDR segment - if (is_share_mode(elf_link)) { + // modify PHDR and INTERP segment + if (is_share_mode(elf_link) || is_static_nold_mode(elf_link)) { modify_PHDR_segment(elf_link); modify_INTERP_segment(elf_link); } @@ -1530,13 +1577,15 @@ int elf_link_write(elf_link_t *elf_link) modify_symtab(elf_link); // sort symbol must before get_new_sym_index + + // symbol addr ready before rela use it + init_symbol_mapping(elf_link); + // .rela.dyn modify_rela_dyn(elf_link); // .rela.plt .plt.got modify_got(elf_link); - init_symbol_mapping(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/elf_read_elf.c b/src/elf_read_elf.c index 4d0429a..db69dee 100644 --- a/src/elf_read_elf.c +++ b/src/elf_read_elf.c @@ -119,7 +119,7 @@ unsigned elf_find_symbol_index_by_name(elf_file_t *ef, const char *name) return i; } - si_panic("%s fail %s\n", __func__, name); + si_panic("find symbol fail %s %s\n", ef->file_name, name); return ~0U; /* unreachable */ } diff --git a/src/elf_relocation.c b/src/elf_relocation.c index c0e5fbf..040125b 100644 --- a/src/elf_relocation.c +++ b/src/elf_relocation.c @@ -116,6 +116,7 @@ static void modify_rela_to_RELATIVE(elf_link_t *elf_link, elf_file_t *src_ef, El void modify_rela_dyn_item(elf_link_t *elf_link, elf_file_t *src_ef, Elf64_Rela *src_rela, Elf64_Rela *dst_rela) { int type; + Elf64_Sym *sym = elf_get_dynsym_by_rela(src_ef, src_rela); // modify offset dst_rela->r_offset = get_new_addr_by_old_addr(elf_link, src_ef, src_rela->r_offset); @@ -150,6 +151,15 @@ void modify_rela_dyn_item(elf_link_t *elf_link, elf_file_t *src_ef, Elf64_Rela * // some symbol do not export in .dynsym, change to R_AARCH64_RELATIVE modify_rela_to_RELATIVE(elf_link, src_ef, src_rela, dst_rela); break; + case R_X86_64_64: + case R_AARCH64_ABS64: + // [44] .bss NOBITS 00000000001f3520 1f2510 00d590 00 WA 0 0 32 + // 00000000001f2698 0000000e00000001 R_X86_64_64 0000000000000000 _rtld_global@GLIBC_PRIVATE + 0 + // 14: 0000000000000000 0 OBJECT GLOBAL DEFAULT UND _rtld_global@GLIBC_PRIVATE (37) + if ((ELF64_ST_TYPE(sym->st_info) == STT_FUNC) || (ELF64_ST_TYPE(sym->st_info) == STT_OBJECT)) { + modify_rela_to_RELATIVE(elf_link, src_ef, src_rela, dst_rela); + } + break; case R_X86_64_IRELATIVE: // 000000000002f9e0 0000000000000025 R_X86_64_IRELATIVE 15ec0 // 129: 0000000000015ec0 40 FUNC LOCAL DEFAULT 13 __x86_cpu_features_ifunc @@ -158,9 +168,6 @@ void modify_rela_dyn_item(elf_link_t *elf_link, elf_file_t *src_ef, Elf64_Rela * case R_AARCH64_RELATIVE: dst_rela->r_addend = get_new_addr_by_old_addr(elf_link, src_ef, src_rela->r_addend); break; - case R_X86_64_64: - case R_AARCH64_ABS64: - break; case R_AARCH64_TLS_TPREL: // all TLS got entry will be modified directly when processing instructions later, // so no .dyn.rela entry is needed. diff --git a/src/elf_relocation_x86_64.c b/src/elf_relocation_x86_64.c index dc6d2d7..42b74f0 100644 --- a/src/elf_relocation_x86_64.c +++ b/src/elf_relocation_x86_64.c @@ -241,7 +241,7 @@ int modify_local_call_rela(elf_link_t *elf_link, elf_file_t *ef, Elf64_Rela *rel Elf64_Sym *sym = NULL; int ret = 0; - sym = (Elf64_Sym *)((void *)ef->hdr + ef->symtab_sec->sh_offset) + ELF64_R_SYM(rela->r_info); + sym = elf_get_symtab_by_rela(ef, rela); switch (ELF64_R_TYPE(rela->r_info)) { case R_X86_64_NONE: diff --git a/tests/test_simple/Makefile b/tests/test_simple/Makefile index 04c4f76..261d425 100644 --- a/tests/test_simple/Makefile +++ b/tests/test_simple/Makefile @@ -36,7 +36,7 @@ simple: simple_app readelf -W -a $(TEST_APP).rto > simple_app.rto.elf objdump -d $(TEST_APP).rto > simple_app.rto.asm @echo ===run=== - $(TEST_APP).rto + #$(TEST_APP).rto rto: gdb --args $(SYSBOOST) --static-nold $(TEST_APP) $(LIBC) -- Gitee