diff --git a/src/elf_check_elf.c b/src/elf_check_elf.c index fed8a7a6f51bf96c4ed12d4490f882df5a17df40..3cc23081d98f8d5aa33e899ffe82a6e41d51182e 100644 --- a/src/elf_check_elf.c +++ b/src/elf_check_elf.c @@ -11,6 +11,7 @@ // See the Mulan PSL v2 for more details. #include +#include #include #include @@ -59,14 +60,13 @@ static bool is_dynsym_valid(Elf64_Sym *sym, const char *name) return true; } -static void check_rela_dyn(elf_link_t *elf_link) +static void check_rela_dyn(elf_link_t *elf_link, elf_file_t *out_ef) { if (is_share_mode(elf_link)) { return; } // static mode only some dynsym can be UND - elf_file_t *out_ef = &elf_link->out_ef; Elf64_Shdr *sec = elf_find_section_by_name(out_ef, ".rela.dyn"); int len = sec->sh_size / sec->sh_entsize; Elf64_Rela *relas = (void *)out_ef->hdr + sec->sh_offset; @@ -85,12 +85,11 @@ static void check_rela_dyn(elf_link_t *elf_link) } } -static void check_dynamic(elf_link_t *elf_link) +static void check_dynamic(elf_link_t *elf_link, elf_file_t *out_ef) { Elf64_Dyn *dyn_arr = NULL; Elf64_Dyn *dyn = NULL; int dyn_count = 0; - elf_file_t *out_ef = &elf_link->out_ef; Elf64_Shdr *sec = elf_find_section_by_name(out_ef, ".dynamic"); if (is_share_mode(elf_link) == false) { @@ -109,11 +108,50 @@ static void check_dynamic(elf_link_t *elf_link) si_panic("DT_BIND_NOW is needed\n"); } +// .rela.init_array no use, .init_array will set by .rely.dyn in ld.so +static void check_func(elf_file_t *out_ef, unsigned long func_point) +{ + Elf64_Rela *rela = elf_get_rela_by_addr(out_ef, func_point); + + // 00000000001222d0 0000000000000008 R_X86_64_RELATIVE 30720 + // rela must be type R_X86_64_RELATIVE + if (ELF64_R_TYPE(rela->r_info) != R_X86_64_RELATIVE) { + si_panic("rela type wrong, %lx\n", rela->r_addend); + } + + // addr must in symbol table + Elf64_Sym *sym = elf_find_symbol_by_addr(out_ef, rela->r_addend); + if (sym == NULL) { + si_panic("function addr is wrong, %lx\n", rela->r_addend); + } + const char *sym_name = elf_get_sym_name(out_ef, sym); + SI_LOG_DEBUG(" %s\n", sym_name); +} + +static void check_func_array(elf_file_t *out_ef, char *sec_name) +{ + SI_LOG_DEBUG("check func addr in %s:\n", sec_name); + Elf64_Shdr *sec = elf_find_section_by_name(out_ef, sec_name); + int count = sec->sh_size / sizeof(unsigned long); + for (int i = 0; i < count; i++) { + unsigned long addr = sec->sh_addr + (i * sizeof(unsigned long)); + check_func(out_ef, addr); + } +} + +// .init_array .fini_array is func addr +static void check_init_fini_array(elf_file_t *out_ef) +{ + check_func_array(out_ef, ".init_array"); + check_func_array(out_ef, ".fini_array"); +} + void elf_check_elf(elf_link_t *elf_link) { elf_file_t *out_ef = &elf_link->out_ef; check_bss_addr(out_ef); check_data_section_addr(out_ef); - check_rela_dyn(elf_link); - check_dynamic(elf_link); + check_rela_dyn(elf_link, out_ef); + check_dynamic(elf_link, out_ef); + check_init_fini_array(out_ef); } diff --git a/src/elf_read_elf.c b/src/elf_read_elf.c index c1a10ed5378a36cf6726b25bd5c5c5d3214d3173..bda80ca7be611135b057b9aa7b86faca3039ba0b 100644 --- a/src/elf_read_elf.c +++ b/src/elf_read_elf.c @@ -246,6 +246,21 @@ Elf64_Sym *elf_find_symbol_by_name(elf_file_t *ef, const char *sym_name) return &syms[i]; } +Elf64_Sym *elf_find_symbol_by_addr(elf_file_t *ef, unsigned long addr) +{ + Elf64_Sym *syms = elf_get_symtab_array(ef); + int count = elf_get_symtab_count(ef); + + for (int i = 0; i < count; i++) { + Elf64_Sym *sym = &syms[i]; + if (sym->st_value == addr) { + return sym; + } + } + + return NULL; +} + unsigned long elf_find_symbol_addr_by_name(elf_file_t *ef, char *sym_name) { Elf64_Sym *sym = elf_find_symbol_by_name(ef, sym_name); diff --git a/src/elf_read_elf.h b/src/elf_read_elf.h index a641ed3f13695de78ac420ce310d8442097cf649..fb527061e45cf694afbe0cc61e737b5ec3b0692e 100644 --- a/src/elf_read_elf.h +++ b/src/elf_read_elf.h @@ -174,6 +174,7 @@ bool elf_is_same_symbol_name(const char *a, const char *b); bool elf_is_symbol_at_libc(elf_file_t *ef, Elf64_Sym *sym); unsigned elf_find_symbol_index_by_name(elf_file_t *ef, const char *name); Elf64_Sym *elf_find_symbol_by_name(elf_file_t *ef, const char *sym_name); +Elf64_Sym *elf_find_symbol_by_addr(elf_file_t *ef, unsigned long addr); unsigned long elf_find_symbol_addr_by_name(elf_file_t *ef, char *sym_name); Elf64_Sym *elf_find_dynsym_by_name(elf_file_t *ef, const char *name); int find_dynsym_index_by_name(elf_file_t *ef, const char *name, bool clear); diff --git a/src/elf_relocation.c b/src/elf_relocation.c index 3abc8bc52158c9f3a0aaa970742e1edacf3e5695..3e565ca0382ef85a153233aafd3e86aa912965c2 100644 --- a/src/elf_relocation.c +++ b/src/elf_relocation.c @@ -49,7 +49,7 @@ static void modify_local_call_sec(elf_link_t *elf_link, elf_file_t *ef, Elf64_Sh int ret = 0; name = elf_get_section_name(ef, sec); - SI_LOG_DEBUG("sec %s\n", name); + SI_LOG_DEBUG("%s sec %s\n", ef->file_name, name); for (int i = 0; i < len; i++) { rela = &relas[i]; diff --git a/src/elf_relocation_x86_64.c b/src/elf_relocation_x86_64.c index 4159e1b4c412079e33957b43a4f3449a0cf881f7..ae6b4fdd3f24be9ee3402f060ae2009f9d8d9990 100644 --- a/src/elf_relocation_x86_64.c +++ b/src/elf_relocation_x86_64.c @@ -399,6 +399,9 @@ int modify_local_call_rela(elf_link_t *elf_link, elf_file_t *ef, Elf64_Rela *rel modify_insn_imm_offset(elf_link, ef, rela, sym); break; case R_X86_64_64: + // .rela.init_array no use, .init_array will set by .rely.dyn in ld.so + // 00000000001222d0 0000000f00000001 R_X86_64_64 000000000002ee10 .text + 1910 + break; case R_X86_64_32S: // direct value, data is already write break;