From 62a3f00dd31c53496696fab98c8523383ceb8fc4 Mon Sep 17 00:00:00 2001 From: yangpan Date: Tue, 20 Feb 2024 10:29:40 +0800 Subject: [PATCH 1/2] =?UTF-8?q?=E5=90=88=E5=B9=B6=E6=8C=87=E5=AE=9Aso?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/elfmerge/elf_link_common.c | 6 ++++-- src/elfmerge/elf_link_elf.c | 14 +++++++++++++- src/elfmerge/elf_relocation.c | 2 +- src/elfmerge/elf_relocation_aarch64.c | 7 +++++-- src/elfmerge/main.c | 4 ++++ 5 files changed, 27 insertions(+), 6 deletions(-) diff --git a/src/elfmerge/elf_link_common.c b/src/elfmerge/elf_link_common.c index b899429..ec50a00 100644 --- a/src/elfmerge/elf_link_common.c +++ b/src/elfmerge/elf_link_common.c @@ -785,6 +785,8 @@ static unsigned long _get_new_addr_by_sym_name(elf_link_t *elf_link, char *sym_n si_panic("not found symbol %s\n", sym_name); } + return NOT_FOUND; + out: if (ELF64_ST_TYPE(sym->st_info) == STT_GNU_IFUNC) { return get_ifunc_new_addr(elf_link, ef, sym, sym_name); @@ -989,11 +991,11 @@ static unsigned long _get_new_addr_by_sym(elf_link_t *elf_link, elf_file_t *ef, char *sym_name = elf_get_sym_name(ef, sym); // WEAK func is used by GNU debug, libc do not have that func - if (is_gnu_weak_symbol(sym) == true) { + if (is_gnu_weak_symbol(sym) == true && !is_share_mode(elf_link)) { return NOT_FOUND; } - if (is_symbol_maybe_undefined(sym_name)) { + if (is_symbol_maybe_undefined(sym_name) && !is_share_mode(elf_link)) { return NOT_FOUND; } diff --git a/src/elfmerge/elf_link_elf.c b/src/elfmerge/elf_link_elf.c index 75fb45c..cbf9b0a 100644 --- a/src/elfmerge/elf_link_elf.c +++ b/src/elfmerge/elf_link_elf.c @@ -628,6 +628,18 @@ static void write_data(elf_link_t *elf_link) p->p_align = SI_HUGEPAGE_ALIGN_SIZE; } +//比较dynamic段中的libtinfo.so.6和in_elfs中的/usr/lib/relocation/usr/lib64/libtinfo.so.6.4.relocation +static bool is_contain_soname(char *so_name, const char *inef_name) { + int idx = 0; + while (so_name[idx] != '\0') { + if (inef_name[idx] == '\0' || so_name[idx] != inef_name[idx]) { + return false; + } + idx++; + } + return true; +} + static bool is_lib_in_elf(elf_link_t *elf_link, char *name) { elf_file_t *ef; @@ -635,7 +647,7 @@ static bool is_lib_in_elf(elf_link_t *elf_link, char *name) for (int i = 0; i < count; i++) { ef = &elf_link->in_efs[i]; - if (strcmp(name, si_basename(ef->file_name)) == 0) { + if (is_contain_soname(name, si_basename(ef->file_name))) { return true; } } diff --git a/src/elfmerge/elf_relocation.c b/src/elfmerge/elf_relocation.c index b40004f..c7ec9c7 100644 --- a/src/elfmerge/elf_relocation.c +++ b/src/elfmerge/elf_relocation.c @@ -140,7 +140,7 @@ static void modify_rela_to_RELATIVE(elf_link_t *elf_link, elf_file_t *src_ef, El // 1008: 48 8b 05 d9 2f 00 00 mov 0x2fd9(%rip),%rax # 3fe8 <__gmon_start__@Base> // some addr need be 0, use by cmp jump char *name = elf_get_sym_name(src_ef, sym); - if (!is_symbol_maybe_undefined(name)) { + if (!is_symbol_maybe_undefined(name) && !is_share_mode(elf_link)) { si_panic("symbol can not be UND, %s %s\n", src_ef->file_name, name); } diff --git a/src/elfmerge/elf_relocation_aarch64.c b/src/elfmerge/elf_relocation_aarch64.c index ddc319c..2b3f346 100644 --- a/src/elfmerge/elf_relocation_aarch64.c +++ b/src/elfmerge/elf_relocation_aarch64.c @@ -1329,7 +1329,7 @@ static void modify_branch_insn(elf_link_t *elf_link, elf_file_t *ef, Elf64_Rela unsigned long new_insn = 0, new_sym_addr = 0, new_offset = 0; elf_file_t *out_ef = &elf_link->out_ef; - if (is_gmon_start_symbol(ef, sym)) { + if (is_gmon_start_symbol(ef, sym) && !is_share_mode(elf_link)) { // __gmon_start__ rela offset point nop, do nothing return; } @@ -1349,7 +1349,7 @@ static void modify_branch_insn(elf_link_t *elf_link, elf_file_t *ef, Elf64_Rela } // WEAK func is used by GNU debug, libc do not have that func - if (is_gnu_weak_symbol(sym) == true) { + if (is_gnu_weak_symbol(sym) == true && !is_share_mode(elf_link)) { goto out; } @@ -1627,6 +1627,9 @@ void modify_rela_plt(elf_link_t *elf_link, si_array_t *arr) if (ret == NOT_FOUND) { ret = 0; } + else { + dst_rela->r_info = ELF64_R_INFO(0, ELF64_R_TYPE(R_AARCH64_RELATIVE)); + } dst_rela->r_addend = ret; break; default: diff --git a/src/elfmerge/main.c b/src/elfmerge/main.c index bb0222d..8ccbdd7 100644 --- a/src/elfmerge/main.c +++ b/src/elfmerge/main.c @@ -59,6 +59,7 @@ int main(int argc, char *argv[]) {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'}, + {ELF_LINK_SHARE_S, no_argument, NULL, 'p'}, {NULL, 0, NULL, 0} }; @@ -123,6 +124,9 @@ int main(int argc, char *argv[]) case 'I': mode = ELF_LINK_STATIC_NOLD; break; + case 'p': + mode = ELF_LINK_SHARE; + break; case 'r': elf_link->flags &= (!RELOC_FLAG); break; -- Gitee From b7364b533eaa2f8bf46212ebca0149c37218d50d Mon Sep 17 00:00:00 2001 From: yangpan Date: Tue, 27 Feb 2024 15:25:16 +0800 Subject: [PATCH 2/2] =?UTF-8?q?=E5=90=88=E5=B9=B6share=E6=A8=A1=E5=BC=8F?= =?UTF-8?q?=E9=99=A4debug=E5=A4=96=E7=9A=84rela=E6=AE=B5?= 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 | 25 +++-- src/elfmerge/elf_read_elf.c | 137 +++++++++++++++++++++++++- src/elfmerge/elf_read_elf.h | 76 ++++++++++++++ src/elfmerge/elf_relocation.c | 68 +++++++++++++ src/elfmerge/elf_relocation.h | 3 + src/elfmerge/elf_relocation_aarch64.c | 8 +- src/elfmerge/elf_write_elf.c | 68 ++++++++++++- src/elfmerge/elf_write_elf.h | 3 + 9 files changed, 369 insertions(+), 22 deletions(-) diff --git a/src/elfmerge/elf_link_common.h b/src/elfmerge/elf_link_common.h index 3f142e7..5d863bf 100644 --- a/src/elfmerge/elf_link_common.h +++ b/src/elfmerge/elf_link_common.h @@ -95,6 +95,9 @@ typedef struct { si_array_t *rela_plt_arr; si_array_t *rela_dyn_arr; + //.rela.init, .rela.text, .rela.data + si_array_t *rela_arr; + // direct symbol mapping si_array_t *symbol_mapping_arr; diff --git a/src/elfmerge/elf_link_elf.c b/src/elfmerge/elf_link_elf.c index cbf9b0a..7d363dc 100644 --- a/src/elfmerge/elf_link_elf.c +++ b/src/elfmerge/elf_link_elf.c @@ -62,6 +62,7 @@ elf_link_t *elf_link_new(void) elf_link->rela_plt_arr = si_array_new(sizeof(elf_obj_mapping_t)); elf_link->rela_dyn_arr = si_array_new(sizeof(elf_obj_mapping_t)); + elf_link->rela_arr = si_array_new(sizeof(elf_obj_mapping_t)); elf_link->hook_func = false; elf_link->direct_call_optimize = false; @@ -506,6 +507,7 @@ static void write_rodata(elf_link_t *elf_link) merge_rodata_sections(elf_link); merge_all_ef_section(elf_link, ".eh_frame_hdr"); + merge_all_ef_section(elf_link, ".eh_frame"); // rodata elf_file_t *out_ef = &elf_link->out_ef; @@ -1776,21 +1778,25 @@ static void elf_link_write_sections(elf_link_t *elf_link) /* .dynamic (merge per section) */ modify_dynamic(elf_link); + /* + * merge per section for below sections: + * .debug_info .debug_line .debug_str .debug_line_str .debug_abbrev + */ + write_debug_info(elf_link); + /* .symtab (merge per section) */ write_symtab(elf_link); /* .strtab (merge per section) */ write_strtab(elf_link); + /* .rela.init, .rela.text */ + if (is_share_mode(elf_link)) { + merge_rela(elf_link); + } + /* .shstrtab (merge per section) */ write_shstrtab(elf_link); - - /* - * merge per section for below sections: - * .debug_info .debug_line .debug_str .debug_line_str .debug_abbrev - */ - write_debug_info(elf_link); - /* * .comment is useless, it's used to hold comments about the generated ELF * (details such as compiler version and execution platform). @@ -1843,6 +1849,11 @@ int elf_link_write(elf_link_t *elf_link) // .rela.plt .plt.got modify_got(elf_link); + // .rela.init, .rela.text + // 目前只支持share模式,因为现有代码会将静态模板的tdata等合并到rodata中,tdata符号缺失 + if(is_share_mode(elf_link)) { + modify_rela_sections(elf_link); + } /* 目前该函数没有实际作用,后续会代替modify_local_call的.rela.init .rela.text部分 */ /* .init .plt .text .fini */ modify_text_section(elf_link); diff --git a/src/elfmerge/elf_read_elf.c b/src/elfmerge/elf_read_elf.c index 7201aea..cf04c4d 100644 --- a/src/elfmerge/elf_read_elf.c +++ b/src/elfmerge/elf_read_elf.c @@ -219,7 +219,7 @@ int elf_find_func_range_by_name(elf_file_t *ef, const char *func_name, return 0; } -unsigned elf_find_symbol_index_by_name(elf_file_t *ef, const char *name) +unsigned int elf_find_symbol_index_by_name(elf_file_t *ef, const char *name) { Elf64_Sym *syms = elf_get_symtab_array(ef); int count = elf_get_symtab_count(ef); @@ -402,13 +402,59 @@ bool elf_is_relro_section(const elf_file_t *ef, const Elf64_Shdr *sechdr) return false; } +bool init_section_filter(const elf_file_t *ef, const Elf64_Shdr *sec) +{ + char *name = elf_get_section_name(ef, sec); + if (strcmp(name, ".init") == 0){ + return true; + } + return false; +} + +bool plt_section_filter(const elf_file_t *ef, const Elf64_Shdr *sec) +{ + char *name = elf_get_section_name(ef, sec); + if (strcmp(name, ".plt") == 0){ + return true; + } + return false; +} + bool text_section_filter(const elf_file_t *ef, const Elf64_Shdr *sec) { (void)ef; - if (!(sec->sh_flags & SHF_EXECINSTR)) { - return false; + char *name = elf_get_section_name(ef, sec); + if (strcmp(name, ".text") == 0){ + return true; } - return true; + return false; +} + +bool fini_section_filter(const elf_file_t *ef, const Elf64_Shdr *sec) +{ + char *name = elf_get_section_name(ef, sec); + if (strcmp(name, ".fini") == 0){ + return true; + } + return false; +} + +bool rela_init_section_filter(const elf_file_t *ef, const Elf64_Shdr *sec) +{ + char *name = elf_get_section_name(ef, sec); + if (strcmp(name, ".rela.init") == 0){ + return true; + } + return false; +} + +bool rela_text_section_filter(const elf_file_t *ef, const Elf64_Shdr *sec) +{ + char *name = elf_get_section_name(ef, sec); + if (strcmp(name, ".rela.text") == 0){ + return true; + } + return false; } bool rodata_section_filter(const elf_file_t *ef, const Elf64_Shdr *sec) @@ -434,10 +480,79 @@ bool rodata_section_filter(const elf_file_t *ef, const Elf64_Shdr *sec) if (strcmp(name, ".eh_frame_hdr") == 0) { return false; } + if (strcmp(name, ".eh_frame") == 0) { + return false; + } return true; } +bool ehframe_section_filter(const elf_file_t *ef, const Elf64_Shdr *sec) +{ + char *name = elf_get_section_name(ef, sec); + if (strcmp(name, ".eh_frame") == 0) { + return true; + } + return false; +} + +bool rela_ehframe_section_filter(const elf_file_t *ef, const Elf64_Shdr *sec) +{ + char *name = elf_get_section_name(ef, sec); + if (strcmp(name, ".rela.eh_frame") == 0) { + return true; + } + return false; +} +bool rela_initarr_section_filter(const elf_file_t *ef, const Elf64_Shdr *sec) +{ + char *name = elf_get_section_name(ef, sec); + if (strcmp(name, ".rela.init_array") == 0) { + return true; + } + return false; +} +bool rela_finiarr_section_filter(const elf_file_t *ef, const Elf64_Shdr *sec) +{ + char *name = elf_get_section_name(ef, sec); + if (strcmp(name, ".rela.fini_array") == 0) { + return true; + } + return false; +} +bool rela_datarelro_section_filter(const elf_file_t *ef, const Elf64_Shdr *sec) +{ + char *name = elf_get_section_name(ef, sec); + if (strcmp(name, ".rela.data.rel.ro") == 0) { + return true; + } + return false; +} +bool rela_data_section_filter(const elf_file_t *ef, const Elf64_Shdr *sec) +{ + char *name = elf_get_section_name(ef, sec); + if (strcmp(name, ".rela.data") == 0) { + return true; + } + return false; +} +bool rela_debuginfo_section_filter(const elf_file_t *ef, const Elf64_Shdr *sec) +{ + char *name = elf_get_section_name(ef, sec); + if (strcmp(name, ".rela.debug_info") == 0) { + return true; + } + return false; +} +bool rela_debugline_section_filter(const elf_file_t *ef, const Elf64_Shdr *sec) +{ + char *name = elf_get_section_name(ef, sec); + if (strcmp(name, ".rela.debug_line") == 0) { + return true; + } + return false; +} + bool got_section_filter(const elf_file_t *ef, const Elf64_Shdr *sec) { char *name = elf_get_section_name(ef, sec); @@ -465,10 +580,24 @@ bool rwdata_section_filter(const elf_file_t *ef, const Elf64_Shdr *sec) if (sec->sh_type != SHT_PROGBITS) { return false; } + char *name = elf_get_section_name(ef, sec); + if (strcmp(name, ".tm_clone_table") == 0) { + return false; + } return true; } +bool tmclonetable_section_filter(const elf_file_t *ef, const Elf64_Shdr *sec) +{ + char *name = elf_get_section_name(ef, sec); + if (strcmp(name, ".tm_clone_table") == 0) { + return true; + } + + return false; +} + bool bss_section_filter(const elf_file_t *ef, const Elf64_Shdr *sec) { (void)ef; diff --git a/src/elfmerge/elf_read_elf.h b/src/elfmerge/elf_read_elf.h index 8824753..5683f44 100644 --- a/src/elfmerge/elf_read_elf.h +++ b/src/elfmerge/elf_read_elf.h @@ -86,6 +86,22 @@ typedef struct { MACRO(SEC_DEBUG_STR, ".debug_str" )\ MACRO(SEC_DEBUG_LINE_STR, ".debug_line_str" )\ MACRO(SEC_DEBUG_ABBREV, ".debug_abbrev" )\ + /* for merge rela sections */ \ + MACRO(SEC_INIT, ".init" )\ + MACRO(SEC_RELA_INIT, ".rela.init" )\ + MACRO(SEC_PLT, ".plt" )\ + MACRO(SEC_RELA_TEXT, ".rela.text" )\ + MACRO(SEC_FINI, ".fini" )\ + MACRO(SEC_EH_FRAME, ".eh_frame" )\ + MACRO(SEC_RELA_EH_FRAME, ".rela.eh_frame" )\ + MACRO(SEC_RELA_INIT_ARRAY, ".rela.init_array" )\ + MACRO(SEC_RELA_FINI_ARRAY, ".rela.fini_array" )\ + MACRO(SEC_RELA_DATA_REL_RO, ".rela.data.rel.ro" )\ + MACRO(SEC_RELA_DATA, ".rela.data" )\ + MACRO(SEC_TM_CLONE_TABLE, ".tm_clone_table" )\ + //MACRO(SEC_RELA_DEBUG_INFO, ".rela.debug_info" ) + //MACRO(SEC_RELA_DEBUG_LINE, ".rela.debug_line" ) + extern char *needed_sections[]; @@ -99,6 +115,28 @@ enum section_types #define GENERATE_STRING(x, ...) #x, extern const char *sec_type_strings[]; +static char *has_rela_names[] = { + ".init_array", + ".init", + ".text", + ".eh_frame", + ".fini_array", + ".data.rel.ro", + ".data", +}; +#define HAS_RELA_NAMES_LEN (sizeof(has_rela_names) / sizeof(has_rela_names[0])) + +static char *rela_names[] = { + ".rela.init", + ".rela.text", + ".rela.eh_frame", + ".rela.init_array", + ".rela.fini_array", + ".rela.data.rel.ro", + ".rela.data", +}; +#define RELA_NAMES_LEN (sizeof(rela_names) / sizeof(rela_names[0])) + static inline const char *sec_type_to_str(int sec_type) { return sec_type_strings[sec_type]; @@ -337,6 +375,28 @@ static inline bool elf_is_rela_plt_name(const char *name) return false; } +static inline bool elf_is_rela_name(const char *name) +{ + for (unsigned i = 0; i < RELA_NAMES_LEN; i++) { + if (strcmp(name, rela_names[i]) == 0) { + return true; + } + } + + return false; +} + +static inline bool is_has_rela(const char *name) +{ + for (unsigned i = 0; i < HAS_RELA_NAMES_LEN; i++) { + if (strcmp(name, has_rela_names[i]) == 0) { + return true; + } + } + + return false; +} + static inline bool elf_is_dynstr_name(const char *name) { if (strcmp(name, ".dynstr") == 0) { @@ -423,6 +483,22 @@ bool debug_line_str_section_filter(const elf_file_t *ef, const Elf64_Shdr *sec); bool debug_abbrev_section_filter(const elf_file_t *ef, const Elf64_Shdr *sec); bool elf_is_same_area(const elf_file_t *ef, const Elf64_Shdr *a, const Elf64_Shdr *b); +bool init_section_filter(const elf_file_t *ef, const Elf64_Shdr *sec); +bool plt_section_filter(const elf_file_t *ef, const Elf64_Shdr *sec); +bool fini_section_filter(const elf_file_t *ef, const Elf64_Shdr *sec); +bool rela_text_section_filter(const elf_file_t *ef, const Elf64_Shdr *sec); +bool rela_init_section_filter(const elf_file_t *ef, const Elf64_Shdr *sec); +bool ehframe_section_filter(const elf_file_t *ef, const Elf64_Shdr *sec); +bool rela_ehframe_section_filter(const elf_file_t *ef, const Elf64_Shdr *sec); +bool rela_initarr_section_filter(const elf_file_t *ef, const Elf64_Shdr *sec); +bool rela_finiarr_section_filter(const elf_file_t *ef, const Elf64_Shdr *sec); +bool rela_datarelro_section_filter(const elf_file_t *ef, const Elf64_Shdr *sec); +bool rela_data_section_filter(const elf_file_t *ef, const Elf64_Shdr *sec); +bool rela_debuginfo_section_filter(const elf_file_t *ef, const Elf64_Shdr *sec); +bool rela_debugline_section_filter(const elf_file_t *ef, const Elf64_Shdr *sec); +bool tmclonetable_section_filter(const elf_file_t *ef, const Elf64_Shdr *sec); + + // ELF void elf_parse_hdr(elf_file_t *ef); void elf_read_elf_phdr(elf_file_t *ef); diff --git a/src/elfmerge/elf_relocation.c b/src/elfmerge/elf_relocation.c index c7ec9c7..4b5c2ab 100644 --- a/src/elfmerge/elf_relocation.c +++ b/src/elfmerge/elf_relocation.c @@ -358,6 +358,19 @@ void modify_rela_dyn(elf_link_t *elf_link) } } +void modify_rela_sections(elf_link_t *elf_link) { + int len = elf_link->rela_arr->len; + elf_obj_mapping_t *obj_rels = elf_link->rela_arr->data; + elf_obj_mapping_t *obj_rel = NULL; + for (int i = 0; i < len; i++) { + obj_rel = &obj_rels[i]; + Elf64_Rela *src_rela = obj_rel->src_obj; + Elf64_Rela *dst_rela = obj_rel->dst_obj; + elf_file_t *src_ef = obj_rel->src_ef; + modify_rela_item(elf_link, src_ef, src_rela, dst_rela); + } +} + void modify_got(elf_link_t *elf_link) { Elf64_Shdr *got_sec = find_tmp_section_by_name(elf_link, ".got"); @@ -389,3 +402,58 @@ void modify_got(elf_link_t *elf_link) // modify .plt.got modify_plt_got(elf_link); } + +void modify_rela_item(elf_link_t *elf_link, elf_file_t *src_ef, Elf64_Rela *src_rela, Elf64_Rela *dst_rela) +{ + // modify r_offset and index + dst_rela->r_offset = get_new_addr_by_old_addr(elf_link, src_ef, src_rela->r_offset); + unsigned int old_index = ELF64_R_SYM(src_rela->r_info); + Elf64_Sym *old_syms = elf_get_symtab_array(src_ef); + Elf64_Sym *old_sym = &old_syms[old_index]; + const char *name = elf_get_sym_name(src_ef, old_sym); + unsigned int new_index = elf_find_symbol_index_by_name(&elf_link->out_ef, name); + dst_rela->r_info = ELF64_R_INFO(new_index, ELF64_R_TYPE(src_rela->r_info)); + int type = ELF64_R_TYPE(src_rela->r_info); + Elf64_Sym *new_syms = elf_get_symtab_array(&elf_link->out_ef); + Elf64_Sym *new_sym = &new_syms[new_index]; + unsigned long old_addr, new_addr; + switch (type) { + case R_AARCH64_ABS32: + case R_AARCH64_ABS64: + case R_AARCH64_PREL32: + case R_AARCH64_CALL26: + case R_AARCH64_JUMP26: + case R_AARCH64_ADD_ABS_LO12_NC: + case R_AARCH64_ADR_PREL_PG_HI21: + case R_AARCH64_LDST16_ABS_LO12_NC: + case R_AARCH64_LDST8_ABS_LO12_NC: + case R_AARCH64_LDST32_ABS_LO12_NC: + case R_AARCH64_LDST128_ABS_LO12_NC: + case R_AARCH64_LDST64_ABS_LO12_NC: + case R_AARCH64_ADR_GOT_PAGE: + case R_AARCH64_LD64_GOT_LO12_NC: + old_addr = old_sym->st_value + src_rela->r_addend; + new_addr = get_new_addr_by_old_addr(elf_link, src_ef, old_addr); + if (new_addr == -1UL) { + si_panic("ABS64: addr is missing\n"); + } + dst_rela->r_addend = new_addr - new_sym->st_value; + SI_LOG_DEBUG("type %d change offset %lx->%lx content %lx->%lx addend %d -> %d\n", type, src_rela->r_offset, dst_rela->r_offset, old_addr, new_addr,src_rela->r_addend, dst_rela->r_addend); + return; + case R_AARCH64_RELATIVE: + if (!elf_is_rela_symbol_null(src_rela)) { + si_panic("%s %lx\n", src_ef->file_name, src_rela->r_offset); + } + // relative type have no sym index + dst_rela->r_addend = get_new_addr_by_old_addr(elf_link, src_ef, src_rela->r_addend); + return; + + default: + SI_LOG_ERR("%s %lx\n", src_ef->file_name, src_rela->r_offset); + si_panic("error not supported type %d\n", type); + } + + // SI_LOG_DEBUG("old r_offset %016lx r_info %016lx r_addend %016lx -> new r_offset %016lx r_info %016lx r_addend %016lx\n", + // src_rela->r_offset, src_rela->r_info, src_rela->r_addend, + // dst_rela->r_offset, dst_rela->r_info, dst_rela->r_addend); +} diff --git a/src/elfmerge/elf_relocation.h b/src/elfmerge/elf_relocation.h index af4b367..7d50597 100644 --- a/src/elfmerge/elf_relocation.h +++ b/src/elfmerge/elf_relocation.h @@ -28,4 +28,7 @@ void modify_rela_plt(elf_link_t *elf_link, si_array_t *arr); void modify_plt_got(elf_link_t *elf_link); void correct_stop_libc_atexit(elf_link_t *elf_link); +void modify_rela_sections(elf_link_t *elf_link); +void modify_rela_item(elf_link_t *elf_link, elf_file_t *src_ef, Elf64_Rela *src_rela, Elf64_Rela *dst_rela); + #endif /* _ELF_RELOCATION_H */ diff --git a/src/elfmerge/elf_relocation_aarch64.c b/src/elfmerge/elf_relocation_aarch64.c index 2b3f346..e4b1cf7 100644 --- a/src/elfmerge/elf_relocation_aarch64.c +++ b/src/elfmerge/elf_relocation_aarch64.c @@ -1624,13 +1624,9 @@ void modify_rela_plt(elf_link_t *elf_link, si_array_t *arr) // 00000000003fffc8 0000000800000402 R_AARCH64_JUMP_SLOT 0000000000000000 puts@GLIBC_2.17 + 0 sym = elf_get_dynsym_by_rela(obj_rel->src_ef, src_rela); ret = get_new_addr_by_symobj(elf_link, obj_rel->src_ef, sym); - if (ret == NOT_FOUND) { - ret = 0; + if (ret != NOT_FOUND) { + dst_rela->r_addend = ret - sym->st_value; } - else { - dst_rela->r_info = ELF64_R_INFO(0, ELF64_R_TYPE(R_AARCH64_RELATIVE)); - } - dst_rela->r_addend = ret; break; default: si_panic("unsupported .rela.plt %ld\n", type); diff --git a/src/elfmerge/elf_write_elf.c b/src/elfmerge/elf_write_elf.c index 9b9d6a7..3c0f633 100644 --- a/src/elfmerge/elf_write_elf.c +++ b/src/elfmerge/elf_write_elf.c @@ -142,13 +142,33 @@ void copy_elf_file(elf_file_t *in, off_t in_offset, elf_file_t *out, off_t out_o (void)memcpy(dest, src, len); } +static int get_has_rela_sec_index(elf_link_t *elf_link, const char *name) +{ + for (unsigned i = 0; i < HAS_RELA_NAMES_LEN; i++) { + if (strstr(name, has_rela_names[i]) != 0) { + Elf64_Shdr *sec = elf_find_section_by_name(&elf_link->out_ef, has_rela_names[i]); + int j = sec - elf_link->out_ef.sechdrs + 1; + return j; + + } + } + si_panic("no section has rela %s\n", name); + return -1; +} + static Elf64_Shdr *add_tmp_section(elf_link_t *elf_link, elf_file_t *ef, Elf64_Shdr *src_sec) { if (is_section_needed(elf_link, ef, src_sec) == false) { return NULL; } + const char* name = elf_get_section_name(ef, src_sec); + int j = elf_link->out_ef.hdr->e_shnum; + if (elf_is_rela_name(name)) { + j = get_has_rela_sec_index(elf_link, name); + } + if (j == MAX_ELF_SECTION - 1) { si_panic("not more new elf sections can be created\n"); } @@ -158,7 +178,13 @@ static Elf64_Shdr *add_tmp_section(elf_link_t *elf_link, elf_file_t *ef, Elf64_S memcpy(dst_sec, src_sec, sizeof(Elf64_Shdr)); append_obj_mapping(elf_link, ef, NULL, src_sec, dst_sec); } + if (elf_is_rela_name(name)) { + return dst_sec; + } + if (is_has_rela(name) && is_share_mode(elf_link)) { + j++; + } j++; elf_link->out_ef.hdr->e_shnum = j; @@ -407,7 +433,7 @@ static void append_section(elf_link_t *elf_link, Elf64_Shdr *dst_sec, elf_file_t } // TODO clean code char *name = elf_get_section_name(ef, sec); - if (strstr(name, "debug") != NULL) { + if (strstr(name, "debug") != NULL || elf_is_rela_name(name)) { is_align_file_offset = false; } // offset in PAGE inherit from in ELF @@ -416,14 +442,29 @@ static void append_section(elf_link_t *elf_link, Elf64_Shdr *dst_sec, elf_file_t // first in section to dst section if (dst_sec->sh_offset == 0) { dst_sec->sh_offset = elf_link->next_file_offset; - if (elf_is_debug_section(ef, dst_sec) || elf_is_rela_debug_section(ef, dst_sec)) { + if (elf_is_debug_section(ef, dst_sec) || elf_is_rela_debug_section(ef, dst_sec) || elf_is_rela_name(name)) { dst_sec->sh_addr = 0; } else { dst_sec->sh_addr = elf_link->next_mem_addr; } } - - write_elf_file_section(elf_link, ef, sec, dst_sec); + void *dst = NULL; + dst = write_elf_file_section(elf_link, ef, sec, dst_sec); + if (elf_is_rela_name(name)) { + si_array_t *arr = elf_link->rela_arr; + void *src = ((void *)ef->hdr) + sec->sh_offset; + int obj_nr = sec->sh_size / sec->sh_entsize; + for (int j = 0; j < obj_nr; j++) { + elf_obj_mapping_t obj_rel = {0}; + obj_rel.src_ef = ef; + obj_rel.src_sec = sec; + obj_rel.src_obj = src; + obj_rel.dst_obj = dst; + si_array_append(arr, &obj_rel); + src = src + sec->sh_entsize; + dst = dst + sec->sh_entsize; + } + } } static void merge_section(elf_link_t *elf_link, Elf64_Shdr *dst_sec, elf_file_t *ef, Elf64_Shdr *sec) @@ -518,9 +559,26 @@ void merge_debug_sections(elf_link_t *elf_link) merge_filter_sections(elf_link, ".debug_line_str", debug_line_str_section_filter); } +void merge_rela(elf_link_t *elf_link) +{ + merge_filter_sections(elf_link, ".rela.init", rela_init_section_filter ); + merge_filter_sections(elf_link, ".rela.text", rela_text_section_filter); + merge_filter_sections(elf_link, ".rela.eh_frame", rela_ehframe_section_filter); + merge_filter_sections(elf_link, ".rela.init_array", rela_initarr_section_filter); + merge_filter_sections(elf_link, ".rela.fini_array", rela_finiarr_section_filter); + merge_filter_sections(elf_link, ".rela.data.rel.ro", rela_datarelro_section_filter); + merge_filter_sections(elf_link, ".rela.data", rela_data_section_filter); + //merge_filter_sections(elf_link, ".rela.debug_info", rela_debuginfo_section_filter); + //merge_filter_sections(elf_link, ".rela.debug_line", rela_debugline_section_filter); +} + + void merge_text_sections(elf_link_t *elf_link) { + merge_filter_sections(elf_link, ".init", init_section_filter); + merge_filter_sections(elf_link, ".plt", plt_section_filter); merge_filter_sections(elf_link, ".text", text_section_filter); + merge_filter_sections(elf_link, ".fini", fini_section_filter); } void merge_rodata_sections(elf_link_t *elf_link) @@ -536,7 +594,7 @@ static void merge_got_section(elf_link_t *elf_link) void merge_rwdata_sections(elf_link_t *elf_link) { merge_filter_sections(elf_link, ".data", rwdata_section_filter); - + merge_filter_sections(elf_link, ".tm_clone_table", tmclonetable_section_filter); // .bss __libc_freeres_ptrs merge_filter_sections(elf_link, ".bss", bss_section_filter); } diff --git a/src/elfmerge/elf_write_elf.h b/src/elfmerge/elf_write_elf.h index 97761cc..41bed6f 100644 --- a/src/elfmerge/elf_write_elf.h +++ b/src/elfmerge/elf_write_elf.h @@ -51,4 +51,7 @@ Elf64_Shdr *merge_all_ef_section(elf_link_t *elf_link, const char *name); int create_elf_file(char *file_name, elf_file_t *elf_file, mode_t mode, uid_t owner, gid_t group); void truncate_elf_file(elf_link_t *elf_link); +//merge rela sections +void merge_rela(elf_link_t *elf_link); + #endif /* _ELF_WRITE_ELF_H */ -- Gitee