From 56ae3c65fe89967db68ef81611081458fa8134de Mon Sep 17 00:00:00 2001 From: Zhou Kang Date: Thu, 17 Aug 2023 09:01:41 +0000 Subject: [PATCH] move _init_first to .preinit_array --- src/elf_link_common.h | 34 +++++++++++++++++++++++++- src/elf_link_elf.c | 28 +++++++++++++++++++++ src/elf_write_elf.c | 57 ++++++++++++++++++++++++++++++++++++++++--- 3 files changed, 114 insertions(+), 5 deletions(-) diff --git a/src/elf_link_common.h b/src/elf_link_common.h index 911d1ef..698403e 100644 --- a/src/elf_link_common.h +++ b/src/elf_link_common.h @@ -107,6 +107,9 @@ typedef struct { bool hook_func; unsigned long so_path_struct; + // .preinit_array can not find by name + Elf64_Shdr *preinit_sec; + //elf_sysboost_data_t *sysboost_data; Elf64_Shdr *sysboost_data_sec; } elf_link_t; @@ -159,7 +162,6 @@ static inline bool is_static_nolibc_mode(elf_link_t *elf_link) return elf_link->link_mode == ELF_LINK_STATIC_NOLIBC; } -// libc _init_first is in .init_array, must run before _start // libc __libc_early_init need init before .init_array // dl_main(phdr, phnum, user_entry, auxv) // _dl_call_libc_early_init (GL(dl_ns)[LM_ID_BASE].libc_map, true); @@ -175,6 +177,36 @@ static inline bool is_static_nold_mode(elf_link_t *elf_link) return elf_link->link_mode == ELF_LINK_STATIC_NOLD; } +// libc _init_first is in .init_array, must run before app _start +// _init_first 中赋值libc的环境变量 __environ +// _init_first 函数执行需要移动到 .preinit_array +static inline bool is_need_preinit(elf_link_t *elf_link) +{ + if (is_static_nold_mode(elf_link)) { + return true; + } + + return false; +} + +static inline bool is_init_name(const char *name) +{ + if (strcmp(name, ".init_array") == 0) { + return true; + } + + return false; +} + +static inline bool is_preinit_name(const char *name) +{ + if (strcmp(name, ".preinit_array") == 0) { + return true; + } + + return false; +} + static inline bool is_hook_func(elf_link_t *elf_link) { return elf_link->hook_func; diff --git a/src/elf_link_elf.c b/src/elf_link_elf.c index 7606962..e3091b9 100644 --- a/src/elf_link_elf.c +++ b/src/elf_link_elf.c @@ -708,6 +708,31 @@ static int dynamic_merge_lib(elf_link_t *elf_link, Elf64_Dyn *begin_dyn, int len return len; } +// .dynamic is merge all elf, so mem space is enough +static int dynamic_add_preinit(elf_link_t *elf_link, Elf64_Dyn *begin_dyn, int len) +{ + if (is_need_preinit(elf_link) == false) { + return len; + } + + Elf64_Shdr *sec = elf_link->preinit_sec; + if (sec == NULL) { + si_panic("not found .preinit_array\n"); + } + + Elf64_Dyn *dst_dyn = &begin_dyn[len]; + dst_dyn->d_tag = DT_PREINIT_ARRAY; + dst_dyn->d_un.d_val = sec->sh_addr; + len++; + + dst_dyn++; + dst_dyn->d_tag = DT_PREINIT_ARRAYSZ; + dst_dyn->d_un.d_val = sec->sh_size; + len++; + + return len; +} + static void dynamic_copy_dyn(elf_link_t *elf_link, elf_file_t *src_ef, Elf64_Dyn *src_dyn, Elf64_Dyn *dst_dyn) { dst_dyn->d_tag = src_dyn->d_tag; @@ -913,6 +938,9 @@ static void scan_dynamic(elf_link_t *elf_link) // DT_SONAME len = dynamic_add_obj_from_libc(elf_link, begin_dyn, len); + // DT_PREINIT_ARRAY + len = dynamic_add_preinit(elf_link, begin_dyn, len); + // new addr of INIT FINI STRTAB SYMTAB len = dynamic_copy_obj(elf_link, begin_dyn, len); diff --git a/src/elf_write_elf.c b/src/elf_write_elf.c index 23fbdcf..7d5e4ad 100644 --- a/src/elf_write_elf.c +++ b/src/elf_write_elf.c @@ -157,6 +157,29 @@ static Elf64_Shdr *add_tmp_section(elf_link_t *elf_link, elf_file_t *ef, Elf64_S return dst_sec; } +static Elf64_Shdr *find_sec_exclude_main_ef(elf_link_t *elf_link, const char *name, elf_file_t **lef) +{ + int in_ef_nr = elf_link->in_ef_nr; + elf_file_t *ef = NULL; + Elf64_Shdr *sec = NULL; + elf_file_t *main_ef = get_main_ef(elf_link); + + for (int i = 0; i < in_ef_nr; i++) { + ef = &elf_link->in_efs[i]; + if (ef == main_ef) { + continue; + } + sec = elf_find_section_by_name(ef, name); + if (sec == NULL) { + continue; + } + *lef = ef; + return sec; + } + + return NULL; +} + static Elf64_Shdr *add_tmp_section_by_name(elf_link_t *elf_link, const char *name) { int in_ef_nr = elf_link->in_ef_nr; @@ -178,6 +201,19 @@ static Elf64_Shdr *add_tmp_section_by_name(elf_link_t *elf_link, const char *nam break; } + // move _init_first to .preinit_array + if (is_need_preinit(elf_link) && is_preinit_name(name)) { + if (sec) { + si_panic(".preinit_array not supported\n"); + } + sec = find_sec_exclude_main_ef(elf_link, ".init_array", &ef); + if (sec == NULL) { + return NULL; + } + elf_link->preinit_sec = add_tmp_section(elf_link, ef, sec); + return elf_link->preinit_sec; + } + if (sec == NULL) { return NULL; } @@ -277,6 +313,10 @@ static bool is_merge_libc_first(elf_link_t *elf_link, Elf64_Shdr *tmp_sec, const return true; } + if (is_init_name(name)) { + return true; + } + return false; } @@ -337,15 +377,15 @@ Elf64_Shdr *merge_all_ef_section(elf_link_t *elf_link, const char *name) return elf_merge_section(elf_link, tmp_sec, name, false); } -Elf64_Shdr *merge_libs_ef_section(elf_link_t *elf_link, const char *name) +Elf64_Shdr *merge_libs_ef_section(elf_link_t *elf_link, const char *dst_name, const char *src_name) { - Elf64_Shdr *tmp_sec = add_tmp_section_by_name(elf_link, name); + Elf64_Shdr *tmp_sec = add_tmp_section_by_name(elf_link, dst_name); if (tmp_sec == NULL) { - si_panic("section is not needed, %s\n", name); + si_panic("section is not needed, %s\n", dst_name); return NULL; } - return elf_merge_section(elf_link, tmp_sec, name, true); + return elf_merge_section(elf_link, tmp_sec, src_name, true); } static void append_section(elf_link_t *elf_link, Elf64_Shdr *dst_sec, elf_file_t *ef, Elf64_Shdr *sec) @@ -479,6 +519,15 @@ static int foreach_merge_section_by_name(const void *item, void *pridata) const char *name = item; elf_link_t *elf_link = pridata; + // add .preinit_array section for libc init func + if (is_need_preinit(elf_link) && is_init_name(name)) { + merge_libs_ef_section(elf_link, ".preinit_array", ".init_array"); + + // .init_array + merge_template_ef_section(elf_link, name); + return 0; + } + merge_all_ef_section(elf_link, name); return 0; } -- Gitee