From a8cffe2670bad2346de2d54f677213e828b9c9f7 Mon Sep 17 00:00:00 2001 From: "yu.dongliang" <18588496441@163.com> Date: Sat, 25 Mar 2023 17:39:18 +0800 Subject: [PATCH] 1, make a framework for risc native code generation, 2, add a bytecode generation named 'naja' for script language, 3, move some similar code to scf_elf_native.c in dir elf/ . --- elf/scf_dwarf_info.c | 2 +- elf/scf_dwarf_line.c | 2 +- elf/scf_elf.c | 2 + elf/scf_elf_arm64.c | 1117 ++----------------------------- elf/scf_elf_arm64.h | 65 +- elf/scf_elf_arm64_so.c | 70 +- elf/scf_elf_naja.c | 476 ++++++++++++++ elf/scf_elf_naja.h | 20 + elf/scf_elf_naja_so.c | 879 +++++++++++++++++++++++++ elf/scf_elf_native.c | 1004 ++++++++++++++++++++++++++++ elf/scf_elf_native.h | 152 +++++ elf/scf_elf_x64.c | 1054 ++---------------------------- elf/scf_elf_x64.h | 67 +- elf/scf_elf_x64_so.c | 70 +- native/risc/scf_naja.c | 1415 ++++++++++++++++++++++++++++++++++++++++ native/risc/scf_risc.c | 2 + parse/Makefile | 4 + parse/main.c | 2 +- 18 files changed, 4123 insertions(+), 2280 deletions(-) create mode 100644 elf/scf_elf_naja.c create mode 100644 elf/scf_elf_naja.h create mode 100644 elf/scf_elf_naja_so.c create mode 100644 elf/scf_elf_native.c create mode 100644 elf/scf_elf_native.h create mode 100644 native/risc/scf_naja.c diff --git a/elf/scf_dwarf_info.c b/elf/scf_dwarf_info.c index 9a1bbaf..818f878 100644 --- a/elf/scf_dwarf_info.c +++ b/elf/scf_dwarf_info.c @@ -313,7 +313,7 @@ static int _add_rela_common(scf_dwarf_debug_t* debug, const char* sym, uint64_t rela->addend = addend; rela->type = type; - if (!strcmp(debug->arch, "arm64")) { + if (!strcmp(debug->arch, "arm64") || !strcmp(debug->arch, "naja")) { switch (type) { diff --git a/elf/scf_dwarf_line.c b/elf/scf_dwarf_line.c index 2c6e594..ac44410 100644 --- a/elf/scf_dwarf_line.c +++ b/elf/scf_dwarf_line.c @@ -681,7 +681,7 @@ int scf_dwarf_line_encode(scf_dwarf_debug_t* debug, scf_dwarf_line_machine_t* lm rela->addend = result->address; rela->text_offset = debug_line->len; - if (!strcmp(debug->arch, "arm64")) + if (!strcmp(debug->arch, "arm64") || !strcmp(debug->arch, "naja")) rela->type = R_AARCH64_ABS64; DWARF_DEBUG_LINE_FILL (lm->address); diff --git a/elf/scf_elf.c b/elf/scf_elf.c index 2aad8e8..5577d72 100644 --- a/elf/scf_elf.c +++ b/elf/scf_elf.c @@ -2,11 +2,13 @@ extern scf_elf_ops_t elf_ops_x64; extern scf_elf_ops_t elf_ops_arm64; +extern scf_elf_ops_t elf_ops_naja; scf_elf_ops_t* elf_ops_array[] = { &elf_ops_x64, &elf_ops_arm64, + &elf_ops_naja, NULL, }; diff --git a/elf/scf_elf_arm64.c b/elf/scf_elf_arm64.c index e76a9ef..ea13de4 100644 --- a/elf/scf_elf_arm64.c +++ b/elf/scf_elf_arm64.c @@ -1,937 +1,14 @@ #include"scf_elf_arm64.h" #include"scf_elf_link.h" -static int _arm64_elf_open(scf_elf_context_t* elf) -{ - if (!elf) - return -EINVAL; - - scf_elf_arm64_t* arm64 = calloc(1, sizeof(scf_elf_arm64_t)); - if (!arm64) - return -ENOMEM; - - arm64->sh_null.sh_type = SHT_NULL; - - arm64->sh_symtab.sh_type = SHT_SYMTAB; - arm64->sh_symtab.sh_flags = 0; - arm64->sh_symtab.sh_addralign = 8; - - arm64->sh_strtab.sh_type = SHT_STRTAB; - arm64->sh_strtab.sh_flags = 0; - arm64->sh_strtab.sh_addralign = 1; - - arm64->sh_shstrtab.sh_type = SHT_STRTAB; - arm64->sh_shstrtab.sh_flags = 0; - arm64->sh_shstrtab.sh_addralign = 1; - - arm64->sections = scf_vector_alloc(); - arm64->symbols = scf_vector_alloc(); - - elf->priv = arm64; - return 0; -} - -static int _arm64_elf_close(scf_elf_context_t* elf) -{ - scf_elf_arm64_t* arm64 = elf->priv; - - if (arm64) { - free(arm64); - arm64 = NULL; - } - return 0; -} - -static int _arm64_elf_add_sym(scf_elf_context_t* elf, const scf_elf_sym_t* sym, const char* sh_name) -{ - scf_elf_arm64_sym_t* xsym; - scf_elf_arm64_t* arm64 = elf->priv; - scf_vector_t* vec = NULL; - - if (!strcmp(sh_name, ".symtab")) - vec = arm64->symbols; - - else if (!strcmp(sh_name, ".dynsym")) { - - if (!arm64->dynsyms) { - arm64->dynsyms = scf_vector_alloc(); - if (!arm64->dynsyms) - return -ENOMEM; - } - - vec = arm64->dynsyms; - } else - return -EINVAL; - - xsym = calloc(1, sizeof(scf_elf_arm64_sym_t)); - if (!xsym) - return -ENOMEM; - - if (sym->name) - xsym->name = scf_string_cstr(sym->name); - else - xsym->name = NULL; - - xsym->sym.st_size = sym->st_size; - xsym->sym.st_value = sym->st_value; - xsym->sym.st_shndx = sym->st_shndx; - xsym->sym.st_info = sym->st_info; - - xsym->dyn_flag = sym->dyn_flag; - - int ret = scf_vector_add(vec, xsym); - if (ret < 0) { - scf_string_free(xsym->name); - free(xsym); - return ret; - } - - xsym->index = vec->size; - return 0; -} - -static int _arm64_elf_add_section(scf_elf_context_t* elf, const scf_elf_section_t* section) -{ - scf_elf_arm64_t* arm64 = elf->priv; - - scf_elf_arm64_section_t* s; - scf_elf_arm64_section_t* s2; - int i; - - if (section->index > 0) { - - for (i = arm64->sections->size - 1; i >= 0; i--) { - s = arm64->sections->data[i]; - - if (s->index == section->index) { - scf_loge("s->index: %d\n", s->index); - return -1; - } - } - } - - s = calloc(1, sizeof(scf_elf_arm64_section_t)); - if (!s) - return -ENOMEM; - - s->name = scf_string_cstr(section->name); - if (!s->name) { - free(s); - return -ENOMEM; - } - - s->sh.sh_type = section->sh_type; - s->sh.sh_flags = section->sh_flags; - s->sh.sh_addralign = section->sh_addralign; - - if (section->data && section->data_len > 0) { - s->data = malloc(section->data_len); - if (!s->data) { - scf_string_free(s->name); - free(s); - return -ENOMEM; - } - - memcpy(s->data, section->data, section->data_len); - s->data_len = section->data_len; - } - - if (scf_vector_add(arm64->sections, s) < 0) { - if (s->data) - free(s->data); - scf_string_free(s->name); - free(s); - return -ENOMEM; - } - - if (0 == section->index) - s->index = arm64->sections->size; - else { - s->index = section->index; - - for (i = arm64->sections->size - 2; i >= 0; i--) { - s2 = arm64->sections->data[i]; - - if (s2->index < s->index) - break; - - arm64->sections->data[i + 1] = s2; - } - - arm64->sections->data[i + 1] = s; - } - - return s->index; -} - -static int _arm64_elf_add_rela_section(scf_elf_context_t* elf, const scf_elf_section_t* section, scf_vector_t* relas) -{ - if (relas->size <= 0) { - scf_loge("\n"); - return -EINVAL; - } - - scf_elf_arm64_t* arm64 = elf->priv; - - scf_elf_arm64_section_t* s = calloc(1, sizeof(scf_elf_arm64_section_t)); - if (!s) - return -ENOMEM; - - s->name = scf_string_cstr(section->name); - if (!s->name) { - free(s); - return -ENOMEM; - } - - s->index = arm64->sections->size + 1; - s->sh.sh_type = SHT_RELA; - s->sh.sh_flags = SHF_INFO_LINK; - s->sh.sh_addralign = section->sh_addralign; - s->sh.sh_link = section->sh_link; - s->sh.sh_info = section->sh_info; - s->sh.sh_entsize = sizeof(Elf64_Rela); - - s->data_len = sizeof(Elf64_Rela) * relas->size; - - s->data = malloc(s->data_len); - if (!s->data) { - scf_string_free(s->name); - free(s); - return -ENOMEM; - } - - Elf64_Rela* pr = (Elf64_Rela*) s->data; - - int i; - for (i = 0; i < relas->size; i++) { - - scf_elf_rela_t* r = relas->data[i]; - - - pr[i].r_offset = r->r_offset; - pr[i].r_info = r->r_info; - pr[i].r_addend = r->r_addend; - } - - if (scf_vector_add(arm64->sections, s) < 0) { - free(s->data); - scf_string_free(s->name); - free(s); - return -ENOMEM; - } - return s->index; -} - -static int _arm64_elf_read_shstrtab(scf_elf_context_t* elf) -{ - scf_elf_arm64_t* arm64 = elf->priv; - - if (!elf->fp) - return -EINVAL; - - int ret = fseek(elf->fp, elf->start, SEEK_SET); - if (ret < 0) - return ret; - - ret = fread(&arm64->eh, sizeof(Elf64_Ehdr), 1, elf->fp); - if (ret != 1) - return -1; - - if (ELFMAG0 != arm64->eh.e_ident[EI_MAG0] - || ELFMAG1 != arm64->eh.e_ident[EI_MAG1] - || ELFMAG2 != arm64->eh.e_ident[EI_MAG2] - || ELFMAG3 != arm64->eh.e_ident[EI_MAG3]) { - - scf_loge("not elf file\n"); - return -1; - } - - long offset = arm64->eh.e_shoff + arm64->eh.e_shentsize * arm64->eh.e_shstrndx; - fseek(elf->fp, elf->start + offset, SEEK_SET); - - ret = fread(&arm64->sh_shstrtab, sizeof(Elf64_Shdr), 1, elf->fp); - if (ret != 1) - return -1; - - if (!arm64->sh_shstrtab_data) { - arm64->sh_shstrtab_data = scf_string_alloc(); - if (!arm64->sh_shstrtab_data) - return -ENOMEM; - } - - void* p = realloc(arm64->sh_shstrtab_data->data, arm64->sh_shstrtab.sh_size); - if (!p) - return -ENOMEM; - arm64->sh_shstrtab_data->data = p; - arm64->sh_shstrtab_data->len = arm64->sh_shstrtab.sh_size; - arm64->sh_shstrtab_data->capacity = arm64->sh_shstrtab.sh_size; - - fseek(elf->fp, elf->start + arm64->sh_shstrtab.sh_offset, SEEK_SET); - - ret = fread(arm64->sh_shstrtab_data->data, arm64->sh_shstrtab.sh_size, 1, elf->fp); - if (ret != 1) - return -1; -#if 0 - int i; - for (i = 0; i < arm64->sh_shstrtab.sh_size; i++) { - - unsigned char c = arm64->sh_shstrtab_data->data[i]; - if (c) - printf("%c", c); - else - printf("\n"); - } - printf("\n"); -#endif - return 0; -} - -static int __arm64_elf_read_section_data(scf_elf_context_t* elf, scf_elf_arm64_section_t* s) -{ - s->data_len = s->sh.sh_size; - - if (s->sh.sh_size > 0) { - - s->data = malloc(s->sh.sh_size); - if (!s->data) - return -1; - - fseek(elf->fp, elf->start + s->sh.sh_offset, SEEK_SET); - - int ret = fread(s->data, s->data_len, 1, elf->fp); - if (ret != 1) { - free(s->data); - s->data = NULL; - s->data_len = 0; - return -1; - } - } - - return 0; -} - -static int __arm64_elf_read_section_by_index(scf_elf_context_t* elf, scf_elf_arm64_section_t** psection, const int index) -{ - scf_elf_arm64_t* arm64 = elf->priv; - - if (!arm64 || !elf->fp) - return -1; - - if (!arm64->sh_shstrtab_data) { - - int ret = _arm64_elf_read_shstrtab(elf); - if (ret < 0) - return ret; - } - - if (index >= arm64->eh.e_shnum) - return -EINVAL; - - scf_elf_arm64_section_t* s; - int i; - for (i = 0; i < arm64->sections->size; i++) { - s = arm64->sections->data[i]; - - if (index == s->index) { - - if (s->data || __arm64_elf_read_section_data(elf, s) == 0) { - *psection = s; - return 0; - } - return -1; - } - } - - s = calloc(1, sizeof(scf_elf_arm64_section_t)); - if (!s) - return -ENOMEM; - - long offset = arm64->eh.e_shoff + arm64->eh.e_shentsize * index; - fseek(elf->fp, elf->start + offset, SEEK_SET); - - int ret = fread(&s->sh, sizeof(Elf64_Shdr), 1, elf->fp); - if (ret != 1) { - free(s); - return -1; - } - - s->index = index; - s->name = scf_string_cstr(arm64->sh_shstrtab_data->data + s->sh.sh_name); - if (!s->name) { - free(s); - return -1; - } - - ret = scf_vector_add(arm64->sections, s); - if (ret < 0) { - scf_string_free(s->name); - free(s); - return -1; - } - - if (__arm64_elf_read_section_data(elf, s) == 0) { - *psection = s; - return 0; - } - return -1; -} - -static int __arm64_elf_read_section(scf_elf_context_t* elf, scf_elf_arm64_section_t** psection, const char* name) -{ - scf_elf_arm64_t* arm64 = elf->priv; - - if (!arm64 || !elf->fp) - return -1; - - if (!arm64->sh_shstrtab_data) { - - int ret = _arm64_elf_read_shstrtab(elf); - if (ret < 0) - return ret; - } - - scf_elf_arm64_section_t* s; - int i; - for (i = 0; i < arm64->sections->size; i++) { - s = arm64->sections->data[i]; - - if (!scf_string_cmp_cstr(s->name, name)) { - - if (s->data || __arm64_elf_read_section_data(elf, s) == 0) { - *psection = s; - return 0; - } - return -1; - } - } - - int j; - for (j = 1; j < arm64->eh.e_shnum; j++) { - - for (i = 0; i < arm64->sections->size; i++) { - s = arm64->sections->data[i]; - - if (j == s->index) - break; - } - - if (i < arm64->sections->size) - continue; - - s = calloc(1, sizeof(scf_elf_arm64_section_t)); - if (!s) - return -ENOMEM; - - long offset = arm64->eh.e_shoff + arm64->eh.e_shentsize * j; - fseek(elf->fp, elf->start + offset, SEEK_SET); - - int ret = fread(&s->sh, sizeof(Elf64_Shdr), 1, elf->fp); - if (ret != 1) { - free(s); - return -1; - } - - s->index = j; - s->name = scf_string_cstr(arm64->sh_shstrtab_data->data + s->sh.sh_name); - if (!s->name) { - free(s); - return -1; - } - - ret = scf_vector_add(arm64->sections, s); - if (ret < 0) { - scf_string_free(s->name); - free(s); - return -1; - } - - if (!scf_string_cmp_cstr(s->name, name)) - break; - } - - if (j < arm64->eh.e_shnum) { - - if (!s->data) { - if (__arm64_elf_read_section_data(elf, s) == 0) { - *psection = s; - return 0; - } - - return -1; - } else - assert(s->data_len == s->sh.sh_size); - - *psection = s; - return 0; - } - - return -404; -} - -static int _arm64_elf_read_syms(scf_elf_context_t* elf, scf_vector_t* syms, const char* sh_name) -{ - scf_elf_arm64_t* arm64 = elf->priv; - - if (!arm64 || !elf->fp) - return -1; - - scf_elf_arm64_section_t* symtab = NULL; - scf_elf_arm64_section_t* strtab = NULL; - - char* sh_strtab_name = NULL; - - if (!strcmp(sh_name, ".symtab")) - sh_strtab_name = ".strtab"; - - else if (!strcmp(sh_name, ".dynsym")) - sh_strtab_name = ".dynstr"; - else - return -EINVAL; - - int ret = __arm64_elf_read_section(elf, &symtab, sh_name); - if (ret < 0) { - scf_loge("\n"); - return -1; - } - - ret = __arm64_elf_read_section(elf, &strtab, sh_strtab_name); - if (ret < 0) { - scf_loge("\n"); - return -1; - } - - assert(symtab->data_len % sizeof(Elf64_Sym) == 0); - - scf_elf_sym_t* esym; - Elf64_Sym* sym; - int i; - for (i = 0; i < symtab->data_len; i += sizeof(Elf64_Sym)) { - - sym = (Elf64_Sym*)(symtab->data + i); - - assert(sym->st_name < strtab->data_len); - - if (STT_NOTYPE == sym->st_info && 0 == i) - continue; - - esym = calloc(1, sizeof(scf_elf_sym_t)); - if (!esym) - return -ENOMEM; - - esym->name = strtab->data + sym->st_name; - esym->st_size = sym->st_size; - esym->st_value = sym->st_value; - esym->st_shndx = sym->st_shndx; - esym->st_info = sym->st_info; - - if (scf_vector_add(syms, esym) < 0) { - free(esym); - return -ENOMEM; - } - } - - return 0; -} - -static int _arm64_elf_add_dyn_need(scf_elf_context_t* elf, const char* soname) -{ - scf_elf_arm64_t* arm64 = elf->priv; - - if (!arm64 || !elf->fp) - return -1; - - if (!arm64->dyn_needs) { - arm64->dyn_needs = scf_vector_alloc(); - if (!arm64->dyn_needs) - return -ENOMEM; - } - - scf_string_t* s = scf_string_cstr(soname); - if (!s) - return -ENOMEM; - - if (scf_vector_add(arm64->dyn_needs, s) < 0) { - scf_string_free(s); - return -ENOMEM; - } - - scf_loge("soname: %s\n", soname); - return 0; -} - -static int _arm64_elf_add_dyn_rela(scf_elf_context_t* elf, const scf_elf_rela_t* rela) -{ - scf_elf_arm64_t* arm64 = elf->priv; - - if (!arm64 || !elf->fp) - return -1; - - if (!arm64->dyn_relas) { - arm64->dyn_relas = scf_vector_alloc(); - if (!arm64->dyn_relas) - return -ENOMEM; - } - - Elf64_Rela* r = calloc(1, sizeof(Elf64_Rela)); - if (!r) - return -ENOMEM; - - if (scf_vector_add(arm64->dyn_relas, r) < 0) { - free(r); - return -ENOMEM; - } - - r->r_offset = rela->r_offset; - r->r_addend = rela->r_addend; - r->r_info = rela->r_info; - - return 0; -} - -static int _arm64_elf_read_relas(scf_elf_context_t* elf, scf_vector_t* relas, const char* sh_name) -{ - scf_elf_arm64_t* arm64 = elf->priv; - - if (!arm64 || !elf->fp) - return -1; - - scf_elf_arm64_section_t* sh_rela = NULL; - scf_elf_arm64_section_t* symtab = NULL; - scf_elf_arm64_section_t* strtab = NULL; - - char* symtab_name = NULL; - char* strtab_name = NULL; - - int ret = __arm64_elf_read_section(elf, &sh_rela, sh_name); - if (ret < 0) - return ret; - - scf_loge("sh_rela: %u\n", sh_rela->sh.sh_link); - - ret = __arm64_elf_read_section_by_index(elf, &symtab, sh_rela->sh.sh_link); - if (ret < 0) { - scf_loge("\n"); - return ret; - } - - ret = __arm64_elf_read_section_by_index(elf, &strtab, symtab->sh.sh_link); - if (ret < 0) { - scf_loge("\n"); - return ret; - } - - assert(sh_rela->data_len % sizeof(Elf64_Rela) == 0); - - scf_elf_rela_t* erela; - Elf64_Rela* rela; - Elf64_Sym* sym; - - int i; - for (i = 0; i < sh_rela->data_len; i += sizeof(Elf64_Rela)) { - - rela = (Elf64_Rela*)(sh_rela->data + i); - - int sym_idx = ELF64_R_SYM(rela->r_info); - - assert(sym_idx < symtab->data_len / sizeof(Elf64_Sym)); - - sym = (Elf64_Sym*)(symtab->data + sym_idx * sizeof(Elf64_Sym)); - - assert(sym->st_name < strtab->data_len); - - erela = calloc(1, sizeof(scf_elf_rela_t)); - if (!erela) - return -ENOMEM; - - erela->name = strtab->data + sym->st_name; - erela->r_offset = rela->r_offset; - erela->r_info = rela->r_info; - erela->r_addend = rela->r_addend; - - if (scf_vector_add(relas, erela) < 0) { - scf_loge("\n"); - free(erela); - return -ENOMEM; - } - } - - return 0; -} - -static int _arm64_elf_read_section(scf_elf_context_t* elf, scf_elf_section_t** psection, const char* name) -{ - scf_elf_arm64_section_t* s = NULL; - scf_elf_section_t* s2; - scf_elf_arm64_t* arm64 = elf->priv; - - if (!arm64 || !elf->fp) - return -1; - - int ret = __arm64_elf_read_section(elf, &s, name); - if (ret < 0) - return ret; - - s2 = calloc(1, sizeof(scf_elf_section_t)); - if (!s2) - return -ENOMEM; - - s2->index = s->index; - s2->name = s->name->data; - s2->data = s->data; - s2->data_len = s->data_len; - s2->sh_type = s->sh.sh_type; - s2->sh_flags = s->sh.sh_flags; - s2->sh_addralign = s->sh.sh_addralign; - - *psection = s2; - return 0; -} - -static void _arm64_elf_header_fill(Elf64_Ehdr* eh, uint16_t e_type, Elf64_Addr e_entry, - Elf64_Off e_phoff, uint16_t e_phnum, uint16_t e_shnum, uint16_t e_shstrndx) -{ - eh->e_ident[EI_MAG0] = ELFMAG0; - eh->e_ident[EI_MAG1] = ELFMAG1; - eh->e_ident[EI_MAG2] = ELFMAG2; - eh->e_ident[EI_MAG3] = ELFMAG3; - eh->e_ident[EI_CLASS] = ELFCLASS64; - eh->e_ident[EI_DATA] = ELFDATA2LSB; - eh->e_ident[EI_VERSION] = EV_CURRENT; - eh->e_ident[EI_OSABI] = ELFOSABI_SYSV; - - eh->e_type = e_type; - eh->e_machine = EM_AARCH64; - eh->e_version = EV_CURRENT; - eh->e_entry = e_entry; - eh->e_ehsize = sizeof(Elf64_Ehdr); - - eh->e_phoff = e_phoff; - eh->e_phentsize = sizeof(Elf64_Phdr); - eh->e_phnum = e_phnum; - - eh->e_shoff = sizeof(Elf64_Ehdr); - eh->e_shentsize = sizeof(Elf64_Shdr); - eh->e_shnum = e_shnum; - eh->e_shstrndx = e_shstrndx; -} - -static void _arm64_elf_section_header_fill(Elf64_Shdr* sh, - uint32_t sh_name, - Elf64_Addr sh_addr, - Elf64_Off sh_offset, - uint64_t sh_size, - uint32_t sh_link, - uint32_t sh_info, - uint64_t sh_entsize) -{ - sh->sh_name = sh_name; - sh->sh_addr = sh_addr; - sh->sh_offset = sh_offset; - sh->sh_size = sh_size; - sh->sh_link = sh_link; - sh->sh_info = sh_info; - sh->sh_entsize = sh_entsize; -} - static int _arm64_elf_write_rel(scf_elf_context_t* elf) { - scf_elf_arm64_t* arm64 = elf->priv; - - int nb_sections = 1 + arm64->sections->size + 1 + 1 + 1; - uint64_t shstrtab_offset = 1; - uint64_t strtab_offset = 1; - Elf64_Off section_offset = sizeof(arm64->eh) + sizeof(Elf64_Shdr) * nb_sections; - - // write elf header - _arm64_elf_header_fill(&arm64->eh, ET_REL, 0, 0, 0, nb_sections, nb_sections - 1); - fwrite(&arm64->eh, sizeof(arm64->eh), 1, elf->fp); - - // write null section header - fwrite(&arm64->sh_null, sizeof(arm64->sh_null), 1, elf->fp); - - // write user's section header - int i; - for (i = 0; i < arm64->sections->size; i++) { - scf_elf_arm64_section_t* s = arm64->sections->data[i]; - - if (SHT_RELA == s->sh.sh_type) - s->sh.sh_link = nb_sections - 3; - - _arm64_elf_section_header_fill(&s->sh, shstrtab_offset, 0, - section_offset, s->data_len, - s->sh.sh_link, s->sh.sh_info, s->sh.sh_entsize); - s->sh.sh_addralign = 8; - - section_offset += s->data_len; - shstrtab_offset += s->name->len + 1; - - fwrite(&s->sh, sizeof(s->sh), 1, elf->fp); - } - - // set user's symbols' name - int nb_local_syms = 1; - - for (i = 0; i < arm64->symbols->size; i++) { - scf_elf_arm64_sym_t* sym = arm64->symbols->data[i]; - - if (sym->name) { - sym->sym.st_name = strtab_offset; - strtab_offset += sym->name->len + 1; - } else - sym->sym.st_name = 0; - - if (STB_LOCAL == ELF64_ST_BIND(sym->sym.st_info)) - nb_local_syms++; - } - - scf_loge("arm64->symbols->size: %d\n", arm64->symbols->size); - // write symtab section header - _arm64_elf_section_header_fill(&arm64->sh_symtab, shstrtab_offset, 0, - section_offset, (arm64->symbols->size + 1) * sizeof(Elf64_Sym), - nb_sections - 2, nb_local_syms, sizeof(Elf64_Sym)); - fwrite(&arm64->sh_symtab, sizeof(arm64->sh_symtab), 1, elf->fp); - section_offset += (arm64->symbols->size + 1) * sizeof(Elf64_Sym); - shstrtab_offset += strlen(".symtab") + 1; - - // write strtab section header - _arm64_elf_section_header_fill(&arm64->sh_strtab, shstrtab_offset, 0, - section_offset, strtab_offset, - 0, 0, 0); - fwrite(&arm64->sh_strtab, sizeof(arm64->sh_strtab), 1, elf->fp); - section_offset += strtab_offset; - shstrtab_offset += strlen(".strtab") + 1; - - // write shstrtab section header - uint64_t shstrtab_len = shstrtab_offset + strlen(".shstrtab") + 1; - _arm64_elf_section_header_fill(&arm64->sh_shstrtab, shstrtab_offset, 0, - section_offset, shstrtab_len, 0, 0, 0); - fwrite(&arm64->sh_shstrtab, sizeof(arm64->sh_shstrtab), 1, elf->fp); - - // write user's section data - for (i = 0; i < arm64->sections->size; i++) { - scf_elf_arm64_section_t* s = arm64->sections->data[i]; - - scf_loge("sh->name: %s, data: %p, len: %d\n", s->name->data, s->data, s->data_len); - - if (s->data && s->data_len > 0) - fwrite(s->data, s->data_len, 1, elf->fp); - } - - // write user's symbols data (symtab section) - // entry index 0 in symtab is NOTYPE - Elf64_Sym sym0 = {0}; - sym0.st_info = ELF64_ST_INFO(STB_LOCAL, STT_NOTYPE); - fwrite(&sym0, sizeof(sym0), 1, elf->fp); - - for (i = 0; i < arm64->symbols->size; i++) { - scf_elf_arm64_sym_t* sym = arm64->symbols->data[i]; - - fwrite(&sym->sym, sizeof(sym->sym), 1, elf->fp); - } - - // write strtab data (strtab section, symbol names of symtab) - uint8_t c = 0; - fwrite(&c, sizeof(c), 1, elf->fp); - for (i = 0; i < arm64->symbols->size; i++) { - scf_elf_arm64_sym_t* sym = arm64->symbols->data[i]; - - if (sym->name) - fwrite(sym->name->data, sym->name->len + 1, 1, elf->fp); - } - - // write shstrtab data (shstrtab section, section names of all sections) - fwrite(&c, sizeof(c), 1, elf->fp); - for (i = 0; i < arm64->sections->size; i++) { - scf_elf_arm64_section_t* s = arm64->sections->data[i]; - - fwrite(s->name->data, s->name->len + 1, 1, elf->fp); - } - - char* str = ".symtab\0.strtab\0.shstrtab\0"; - int str_len = strlen(".symtab") + strlen(".strtab") + strlen(".shstrtab") + 3; - fwrite(str, str_len, 1, elf->fp); - return 0; -} - -static int _sym_cmp(const void* v0, const void* v1) -{ - const scf_elf_arm64_sym_t* sym0 = *(const scf_elf_arm64_sym_t**)v0; - const scf_elf_arm64_sym_t* sym1 = *(const scf_elf_arm64_sym_t**)v1; - - if (STB_LOCAL == ELF64_ST_BIND(sym0->sym.st_info)) { - if (STB_GLOBAL == ELF64_ST_BIND(sym1->sym.st_info)) - return -1; - } else if (STB_LOCAL == ELF64_ST_BIND(sym1->sym.st_info)) - return 1; - return 0; -} - -static int _arm64_elf_find_sym(scf_elf_arm64_sym_t** psym, Elf64_Rela* rela, scf_vector_t* symbols) -{ - scf_elf_arm64_sym_t* sym; - scf_elf_arm64_sym_t* sym2; - - int sym_idx = ELF64_R_SYM(rela->r_info); - int j; - - assert(sym_idx >= 1); - assert(sym_idx - 1 < symbols->size); - - sym = symbols->data[sym_idx - 1]; - - if (0 == sym->sym.st_shndx) { - - int n = 0; - - for (j = 0; j < symbols->size; j++) { - sym2 = symbols->data[j]; - - if (0 == sym2->sym.st_shndx) - continue; - - if (STB_LOCAL == ELF64_ST_BIND(sym2->sym.st_info)) - continue; - - if (!strcmp(sym2->name->data, sym->name->data)) { - sym = sym2; - sym_idx = j + 1; - n++; - } - } - - if (0 == n) { - scf_loge("global symbol: %s not found\n", sym->name->data); - return -1; - - } else if (n > 1) { - scf_loge("tow global symbol: %s\n", sym->name->data); - return -1; - } - } else if (ELF64_ST_TYPE(sym->sym.st_info) == STT_SECTION) { - - for (j = symbols->size - 1; j >= 0; j--) { - sym2 = symbols->data[j]; - - if (ELF64_ST_TYPE(sym2->sym.st_info) != STT_SECTION) - continue; - - if (sym2->sym.st_shndx == sym->sym.st_shndx) { - sym = sym2; - sym_idx = j + 1; - break; - } - } - - assert(j >= 0); - } - - *psym = sym; - return sym_idx; + return elf_write_rel(elf, EM_AARCH64); } -static int _arm64_elf_link_cs(scf_elf_arm64_t* arm64, scf_elf_arm64_section_t* s, scf_elf_arm64_section_t* rs, uint64_t cs_base) +static int _arm64_elf_link_cs(elf_native_t* arm64, elf_section_t* s, elf_section_t* rs, uint64_t cs_base) { - scf_elf_arm64_sym_t* sym; + elf_sym_t* sym; Elf64_Rela* rela; assert(rs->data_len % sizeof(Elf64_Rela) == 0); @@ -953,7 +30,7 @@ static int _arm64_elf_link_cs(scf_elf_arm64_t* arm64, scf_elf_arm64_section_t* s continue; } - int j = _arm64_elf_find_sym(&sym, rela, arm64->symbols); + int j = elf_find_sym(&sym, rela, arm64->symbols); if (j < 0) return -1; @@ -1005,9 +82,9 @@ static int _arm64_elf_link_cs(scf_elf_arm64_t* arm64, scf_elf_arm64_section_t* s return 0; } -static int _arm64_elf_link_ds(scf_elf_arm64_t* arm64, scf_elf_arm64_section_t* s, scf_elf_arm64_section_t* rs) +static int _arm64_elf_link_ds(elf_native_t* arm64, elf_section_t* s, elf_section_t* rs) { - scf_elf_arm64_sym_t* sym; + elf_sym_t* sym; Elf64_Rela* rela; assert(rs->data_len % sizeof(Elf64_Rela) == 0); @@ -1018,7 +95,7 @@ static int _arm64_elf_link_ds(scf_elf_arm64_t* arm64, scf_elf_arm64_section_t* s rela = (Elf64_Rela* )(rs->data + i); sym = NULL; - int j = _arm64_elf_find_sym(&sym, rela, arm64->symbols); + int j = elf_find_sym(&sym, rela, arm64->symbols); if (j < 0) return -1; @@ -1048,10 +125,10 @@ static int _arm64_elf_link_ds(scf_elf_arm64_t* arm64, scf_elf_arm64_section_t* s return 0; } -static int _arm64_elf_link_debug(scf_elf_arm64_t* arm64, scf_elf_arm64_section_t* s, scf_elf_arm64_section_t* rs) +static int _arm64_elf_link_debug(elf_native_t* arm64, elf_section_t* s, elf_section_t* rs) { - scf_elf_arm64_sym_t* sym; - scf_elf_arm64_sym_t* sym2; + elf_sym_t* sym; + elf_sym_t* sym2; Elf64_Rela* rela; assert(rs->data_len % sizeof(Elf64_Rela) == 0); @@ -1062,7 +139,7 @@ static int _arm64_elf_link_debug(scf_elf_arm64_t* arm64, scf_elf_arm64_section_t rela = (Elf64_Rela* )(rs->data + i); sym = NULL; - int j = _arm64_elf_find_sym(&sym, rela, arm64->symbols); + int j = elf_find_sym(&sym, rela, arm64->symbols); if (j < 0) return -1; @@ -1108,10 +185,10 @@ static int _arm64_elf_link_debug(scf_elf_arm64_t* arm64, scf_elf_arm64_section_t return 0; } -static int _arm64_elf_link_sections(scf_elf_arm64_t* arm64, uint32_t cs_index, uint32_t ds_index) +static int _arm64_elf_link_sections(elf_native_t* arm64, uint32_t cs_index, uint32_t ds_index) { - scf_elf_arm64_section_t* s; - scf_elf_arm64_section_t* rs; + elf_section_t* s; + elf_section_t* rs; int i; for (i = 0; i < arm64->sections->size; i++) { @@ -1144,81 +221,10 @@ static int _arm64_elf_link_sections(scf_elf_arm64_t* arm64, uint32_t cs_index, u return 0; } -static void _arm64_elf_process_syms(scf_elf_arm64_t* arm64, uint32_t cs_index) -{ - scf_elf_arm64_section_t* s; - scf_elf_arm64_sym_t* sym; - Elf64_Rela* rela; - - int i; - int j; - int k; - int shndx = 20; -#if 1 - for (i = arm64->symbols->size - 1; i >= 0; i--) { - sym = arm64->symbols->data[i]; - - if (STT_SECTION == ELF64_ST_TYPE(sym->sym.st_info)) { - if (shndx > cs_index) { - - shndx = sym->sym.st_shndx; - - assert(sym->sym.st_shndx - 1 < arm64->sections->size); - - sym->section = arm64->sections->data[sym->sym.st_shndx - 1]; - continue; - } - } else if (0 != sym->sym.st_shndx) { - - if (sym->sym.st_shndx - 1 < arm64->sections->size) - sym->section = arm64->sections->data[sym->sym.st_shndx - 1]; - continue; - } - - assert(0 == scf_vector_del(arm64->symbols, sym)); - - scf_string_free(sym->name); - free(sym); - } -#endif - qsort(arm64->symbols->data, arm64->symbols->size, sizeof(void*), _sym_cmp); - - for (j = 0; j < arm64->sections->size; j++) { - s = arm64->sections->data[j]; - - if (SHT_RELA != s->sh.sh_type) - continue; - - if (!strcmp(s->name->data, ".rela.plt")) - continue; - - assert(s->data_len % sizeof(Elf64_Rela) == 0); - - int sym_idx; - for (k = 0; k < s->data_len; k += sizeof(Elf64_Rela)) { - - rela = (Elf64_Rela*)(s->data + k); - - sym_idx = ELF64_R_SYM(rela->r_info); - - for (i = 0; i < arm64->symbols->size; i++) { - sym = arm64->symbols->data[i]; - - if (sym_idx == sym->index) - break; - } - - assert(i < arm64->symbols->size); - - rela->r_info = ELF64_R_INFO(i + 1, ELF64_R_TYPE(rela->r_info)); - } - } -} - static int _arm64_elf_write_exec(scf_elf_context_t* elf) { - scf_elf_arm64_t* arm64 = elf->priv; - int nb_phdrs = 3; + elf_native_t* arm64 = elf->priv; + int nb_phdrs = 3; if (arm64->dynsyms && arm64->dynsyms->size) { __arm64_elf_add_dyn(arm64); @@ -1232,13 +238,13 @@ static int _arm64_elf_write_exec(scf_elf_context_t* elf) Elf64_Off phdr_offset = sizeof(arm64->eh) + sizeof(Elf64_Shdr) * nb_sections; Elf64_Off section_offset = phdr_offset + sizeof(Elf64_Phdr) * nb_phdrs; - scf_elf_arm64_section_t* s; - scf_elf_arm64_section_t* cs = NULL; - scf_elf_arm64_section_t* ros = NULL; - scf_elf_arm64_section_t* ds = NULL; - scf_elf_arm64_section_t* crela = NULL; - scf_elf_arm64_section_t* drela = NULL; - scf_elf_arm64_sym_t* sym; + elf_section_t* s; + elf_section_t* cs = NULL; + elf_section_t* ros = NULL; + elf_section_t* ds = NULL; + elf_section_t* crela = NULL; + elf_section_t* drela = NULL; + elf_sym_t* sym; int i; for (i = 0; i < arm64->sections->size; i++) { @@ -1323,7 +329,7 @@ static int _arm64_elf_write_exec(scf_elf_context_t* elf) if (ret < 0) return ret; - _arm64_elf_process_syms(arm64, cs->index); + elf_process_syms(arm64, cs->index); cs ->sh.sh_addr = cs_base; ds ->sh.sh_addr = ds_base; @@ -1350,7 +356,7 @@ static int _arm64_elf_write_exec(scf_elf_context_t* elf) } // write elf header - _arm64_elf_header_fill(&arm64->eh, ET_EXEC, _start, phdr_offset, nb_phdrs, nb_sections, nb_sections - 1); + elf_header(&arm64->eh, ET_EXEC, EM_AARCH64, _start, phdr_offset, nb_phdrs, nb_sections, nb_sections - 1); fwrite(&arm64->eh, sizeof(arm64->eh), 1, elf->fp); // write null section header @@ -1365,7 +371,7 @@ static int _arm64_elf_write_exec(scf_elf_context_t* elf) if (SHT_RELA == s->sh.sh_type && 0 == s->sh.sh_link) s->sh.sh_link = nb_sections - 3; - _arm64_elf_section_header_fill(&s->sh, shstrtab_offset, s->sh.sh_addr, + section_header(&s->sh, shstrtab_offset, s->sh.sh_addr, section_offset, s->data_len, s->sh.sh_link, s->sh.sh_info, s->sh.sh_entsize); @@ -1395,7 +401,7 @@ static int _arm64_elf_write_exec(scf_elf_context_t* elf) } // write symtab section header - _arm64_elf_section_header_fill(&arm64->sh_symtab, shstrtab_offset, 0, + section_header(&arm64->sh_symtab, shstrtab_offset, 0, section_offset, (arm64->symbols->size + 1) * sizeof(Elf64_Sym), nb_sections - 2, nb_local_syms, sizeof(Elf64_Sym)); @@ -1405,7 +411,7 @@ static int _arm64_elf_write_exec(scf_elf_context_t* elf) shstrtab_offset += strlen(".symtab") + 1; // write strtab section header - _arm64_elf_section_header_fill(&arm64->sh_strtab, shstrtab_offset, 0, + section_header(&arm64->sh_strtab, shstrtab_offset, 0, section_offset, strtab_offset, 0, 0, 0); fwrite(&arm64->sh_strtab, sizeof(arm64->sh_strtab), 1, elf->fp); @@ -1414,7 +420,7 @@ static int _arm64_elf_write_exec(scf_elf_context_t* elf) // write shstrtab section header uint64_t shstrtab_len = shstrtab_offset + strlen(".shstrtab") + 1; - _arm64_elf_section_header_fill(&arm64->sh_shstrtab, shstrtab_offset, 0, + section_header(&arm64->sh_shstrtab, shstrtab_offset, 0, section_offset, shstrtab_len, 0, 0, 0); fwrite(&arm64->sh_shstrtab, sizeof(arm64->sh_shstrtab), 1, elf->fp); @@ -1438,47 +444,10 @@ static int _arm64_elf_write_exec(scf_elf_context_t* elf) } #endif - // write user's section data - for (i = 0; i < arm64->sections->size; i++) { - s = arm64->sections->data[i]; - - if (s->data && s->data_len > 0) - fwrite(s->data, s->data_len, 1, elf->fp); - } - - // write user's symbols data (symtab section) - // entry index 0 in symtab is NOTYPE - Elf64_Sym sym0 = {0}; - sym0.st_info = ELF64_ST_INFO(STB_LOCAL, STT_NOTYPE); - - fwrite(&sym0, sizeof(sym0), 1, elf->fp); - for (i = 0; i < arm64->symbols->size; i++) { - sym = arm64->symbols->data[i]; - - fwrite(&sym->sym, sizeof(sym->sym), 1, elf->fp); - } - - // write strtab data (strtab section, symbol names of symtab) - uint8_t c = 0; - fwrite(&c, sizeof(c), 1, elf->fp); - for (i = 0; i < arm64->symbols->size; i++) { - sym = arm64->symbols->data[i]; - - if (sym->name) - fwrite(sym->name->data, sym->name->len + 1, 1, elf->fp); - } - - // write shstrtab data (shstrtab section, section names of all sections) - fwrite(&c, sizeof(c), 1, elf->fp); - for (i = 0; i < arm64->sections->size; i++) { - s = arm64->sections->data[i]; - - fwrite(s->name->data, s->name->len + 1, 1, elf->fp); - } - - char* str = ".symtab\0.strtab\0.shstrtab\0"; - int str_len = strlen(".symtab") + strlen(".strtab") + strlen(".shstrtab") + 3; - fwrite(str, str_len, 1, elf->fp); + elf_write_sections(elf); + elf_write_symtab (elf); + elf_write_strtab (elf); + elf_write_shstrtab(elf); return 0; } @@ -1486,20 +455,20 @@ scf_elf_ops_t elf_ops_arm64 = { .machine = "arm64", - .open = _arm64_elf_open, - .close = _arm64_elf_close, + .open = elf_open, + .close = elf_close, - .add_sym = _arm64_elf_add_sym, - .add_section = _arm64_elf_add_section, + .add_sym = elf_add_sym, + .add_section = elf_add_section, - .add_rela_section = _arm64_elf_add_rela_section, + .add_rela_section = elf_add_rela_section, - .add_dyn_need = _arm64_elf_add_dyn_need, - .add_dyn_rela = _arm64_elf_add_dyn_rela, + .add_dyn_need = elf_add_dyn_need, + .add_dyn_rela = elf_add_dyn_rela, - .read_syms = _arm64_elf_read_syms, - .read_relas = _arm64_elf_read_relas, - .read_section = _arm64_elf_read_section, + .read_syms = elf_read_syms, + .read_relas = elf_read_relas, + .read_section = elf_read_section, .write_rel = _arm64_elf_write_rel, .write_exec = _arm64_elf_write_exec, diff --git a/elf/scf_elf_arm64.h b/elf/scf_elf_arm64.h index 947768b..7eae07f 100644 --- a/elf/scf_elf_arm64.h +++ b/elf/scf_elf_arm64.h @@ -2,71 +2,12 @@ #define SCF_ELF_ARM64_H #include"scf_elf.h" +#include"scf_elf_native.h" #include"scf_vector.h" #include"scf_string.h" -typedef struct scf_elf_arm64_section_s scf_elf_arm64_section_t; - -struct scf_elf_arm64_section_s -{ - scf_elf_arm64_section_t* link; - scf_elf_arm64_section_t* info; - - scf_string_t* name; - - Elf64_Shdr sh; - - uint64_t offset; - - uint16_t index; - uint8_t* data; - int data_len; -}; - -typedef struct { - scf_elf_arm64_section_t* section; - - scf_string_t* name; - - Elf64_Sym sym; - - int index; - uint8_t dyn_flag:1; -} scf_elf_arm64_sym_t; - -typedef struct { - Elf64_Ehdr eh; - - Elf64_Shdr sh_null; - - scf_vector_t* sections; - - Elf64_Shdr sh_symtab; - scf_vector_t* symbols; - - Elf64_Shdr sh_strtab; - - Elf64_Shdr sh_shstrtab; - scf_string_t* sh_shstrtab_data; - - scf_vector_t* dynsyms; - scf_vector_t* dyn_needs; - scf_vector_t* dyn_relas; - - scf_elf_arm64_section_t* interp; - scf_elf_arm64_section_t* dynsym; - scf_elf_arm64_section_t* dynstr; - scf_elf_arm64_section_t* gnu_version; - scf_elf_arm64_section_t* gnu_version_r; - scf_elf_arm64_section_t* rela_plt; - scf_elf_arm64_section_t* plt; - scf_elf_arm64_section_t* dynamic; - scf_elf_arm64_section_t* got_plt; - -} scf_elf_arm64_t; - -int __arm64_elf_add_dyn (scf_elf_arm64_t* arm64); -int __arm64_elf_post_dyn(scf_elf_arm64_t* arm64, uint64_t rx_base, uint64_t rw_base, scf_elf_arm64_section_t* cs); +int __arm64_elf_add_dyn (elf_native_t* arm64); +int __arm64_elf_post_dyn(elf_native_t* arm64, uint64_t rx_base, uint64_t rw_base, elf_section_t* cs); int __arm64_elf_write_phdr (scf_elf_context_t* elf, uint64_t rx_base, uint64_t offset, uint32_t nb_phdrs); int __arm64_elf_write_interp (scf_elf_context_t* elf, uint64_t rx_base, uint64_t offset, uint64_t len); diff --git a/elf/scf_elf_arm64_so.c b/elf/scf_elf_arm64_so.c index ddca5fc..6745089 100644 --- a/elf/scf_elf_arm64_so.c +++ b/elf/scf_elf_arm64_so.c @@ -37,11 +37,11 @@ static uint32_t _arm64_elf_hash(const uint8_t* p) return k; } -static int _arm64_elf_add_interp(scf_elf_arm64_t* arm64, scf_elf_arm64_section_t** ps) +static int _arm64_elf_add_interp(elf_native_t* arm64, elf_section_t** ps) { - scf_elf_arm64_section_t* s; + elf_section_t* s; - s = calloc(1, sizeof(scf_elf_arm64_section_t)); + s = calloc(1, sizeof(elf_section_t)); if (!s) return -ENOMEM; @@ -82,11 +82,11 @@ static int _arm64_elf_add_interp(scf_elf_arm64_t* arm64, scf_elf_arm64_section_t return 0; } -static int _arm64_elf_add_gnu_version(scf_elf_arm64_t* arm64, scf_elf_arm64_section_t** ps) +static int _arm64_elf_add_gnu_version(elf_native_t* arm64, elf_section_t** ps) { - scf_elf_arm64_section_t* s; + elf_section_t* s; - s = calloc(1, sizeof(scf_elf_arm64_section_t)); + s = calloc(1, sizeof(elf_section_t)); if (!s) return -ENOMEM; @@ -122,11 +122,11 @@ static int _arm64_elf_add_gnu_version(scf_elf_arm64_t* arm64, scf_elf_arm64_sect return 0; } -static int _arm64_elf_add_gnu_version_r(scf_elf_arm64_t* arm64, scf_elf_arm64_section_t** ps) +static int _arm64_elf_add_gnu_version_r(elf_native_t* arm64, elf_section_t** ps) { - scf_elf_arm64_section_t* s; + elf_section_t* s; - s = calloc(1, sizeof(scf_elf_arm64_section_t)); + s = calloc(1, sizeof(elf_section_t)); if (!s) return -ENOMEM; @@ -162,11 +162,11 @@ static int _arm64_elf_add_gnu_version_r(scf_elf_arm64_t* arm64, scf_elf_arm64_se return 0; } -static int _arm64_elf_add_dynsym(scf_elf_arm64_t* arm64, scf_elf_arm64_section_t** ps) +static int _arm64_elf_add_dynsym(elf_native_t* arm64, elf_section_t** ps) { - scf_elf_arm64_section_t* s; + elf_section_t* s; - s = calloc(1, sizeof(scf_elf_arm64_section_t)); + s = calloc(1, sizeof(elf_section_t)); if (!s) return -ENOMEM; @@ -204,11 +204,11 @@ static int _arm64_elf_add_dynsym(scf_elf_arm64_t* arm64, scf_elf_arm64_section_t return 0; } -static int _arm64_elf_add_dynstr(scf_elf_arm64_t* arm64, scf_elf_arm64_section_t** ps) +static int _arm64_elf_add_dynstr(elf_native_t* arm64, elf_section_t** ps) { - scf_elf_arm64_section_t* s; + elf_section_t* s; - s = calloc(1, sizeof(scf_elf_arm64_section_t)); + s = calloc(1, sizeof(elf_section_t)); if (!s) return -ENOMEM; @@ -236,11 +236,11 @@ static int _arm64_elf_add_dynstr(scf_elf_arm64_t* arm64, scf_elf_arm64_section_t return 0; } -static int _arm64_elf_add_dynamic(scf_elf_arm64_t* arm64, scf_elf_arm64_section_t** ps) +static int _arm64_elf_add_dynamic(elf_native_t* arm64, elf_section_t** ps) { - scf_elf_arm64_section_t* s; + elf_section_t* s; - s = calloc(1, sizeof(scf_elf_arm64_section_t)); + s = calloc(1, sizeof(elf_section_t)); if (!s) return -ENOMEM; @@ -279,11 +279,11 @@ static int _arm64_elf_add_dynamic(scf_elf_arm64_t* arm64, scf_elf_arm64_section_ return 0; } -static int _arm64_elf_add_got_plt(scf_elf_arm64_t* arm64, scf_elf_arm64_section_t** ps) +static int _arm64_elf_add_got_plt(elf_native_t* arm64, elf_section_t** ps) { - scf_elf_arm64_section_t* s; + elf_section_t* s; - s = calloc(1, sizeof(scf_elf_arm64_section_t)); + s = calloc(1, sizeof(elf_section_t)); if (!s) return -ENOMEM; @@ -319,11 +319,11 @@ static int _arm64_elf_add_got_plt(scf_elf_arm64_t* arm64, scf_elf_arm64_section_ return 0; } -static int _arm64_elf_add_rela_plt(scf_elf_arm64_t* arm64, scf_elf_arm64_section_t** ps) +static int _arm64_elf_add_rela_plt(elf_native_t* arm64, elf_section_t** ps) { - scf_elf_arm64_section_t* s; + elf_section_t* s; - s = calloc(1, sizeof(scf_elf_arm64_section_t)); + s = calloc(1, sizeof(elf_section_t)); if (!s) return -ENOMEM; @@ -360,11 +360,11 @@ static int _arm64_elf_add_rela_plt(scf_elf_arm64_t* arm64, scf_elf_arm64_section return 0; } -static int _arm64_elf_add_plt(scf_elf_arm64_t* arm64, scf_elf_arm64_section_t** ps) +static int _arm64_elf_add_plt(elf_native_t* arm64, elf_section_t** ps) { - scf_elf_arm64_section_t* s; + elf_section_t* s; - s = calloc(1, sizeof(scf_elf_arm64_section_t)); + s = calloc(1, sizeof(elf_section_t)); if (!s) return -ENOMEM; @@ -412,8 +412,8 @@ static int _arm64_elf_add_plt(scf_elf_arm64_t* arm64, scf_elf_arm64_section_t** static int _section_cmp(const void* v0, const void* v1) { - const scf_elf_arm64_section_t* s0 = *(const scf_elf_arm64_section_t**)v0; - const scf_elf_arm64_section_t* s1 = *(const scf_elf_arm64_section_t**)v1; + const elf_section_t* s0 = *(const elf_section_t**)v0; + const elf_section_t* s1 = *(const elf_section_t**)v1; if (s0->index < s1->index) return -1; @@ -422,10 +422,10 @@ static int _section_cmp(const void* v0, const void* v1) return 0; } -int __arm64_elf_add_dyn (scf_elf_arm64_t* arm64) +int __arm64_elf_add_dyn (elf_native_t* arm64) { - scf_elf_arm64_section_t* s; - scf_elf_arm64_sym_t* sym; + elf_section_t* s; + elf_sym_t* sym; Elf64_Rela* rela; int i; @@ -505,7 +505,7 @@ int __arm64_elf_add_dyn (scf_elf_arm64_t* arm64) memcpy(&syms[0], &sym0, sizeof(Elf64_Sym)); for (i = 0; i < arm64->dynsyms->size; i++) { - scf_elf_arm64_sym_t* xsym = arm64->dynsyms->data[i]; + elf_sym_t* xsym = arm64->dynsyms->data[i]; memcpy(&syms[i + 1], &xsym->sym, sizeof(Elf64_Sym)); @@ -653,7 +653,7 @@ int __arm64_elf_add_dyn (scf_elf_arm64_t* arm64) return 0; } -int __arm64_elf_post_dyn(scf_elf_arm64_t* arm64, uint64_t rx_base, uint64_t rw_base, scf_elf_arm64_section_t* cs) +int __arm64_elf_post_dyn(elf_native_t* arm64, uint64_t rx_base, uint64_t rw_base, elf_section_t* cs) { uint64_t cs_base = rx_base + cs->offset; @@ -748,7 +748,7 @@ int __arm64_elf_post_dyn(scf_elf_arm64_t* arm64, uint64_t rx_base, uint64_t rw_b for (i = arm64->dyn_needs->size; i < arm64->dynamic->data_len / sizeof(Elf64_Dyn); i++) { - scf_elf_arm64_section_t* s = (scf_elf_arm64_section_t*)dtags[i].d_un.d_ptr; + elf_section_t* s = (elf_section_t*)dtags[i].d_un.d_ptr; switch (dtags[i].d_tag) { diff --git a/elf/scf_elf_naja.c b/elf/scf_elf_naja.c new file mode 100644 index 0000000..fe4e21f --- /dev/null +++ b/elf/scf_elf_naja.c @@ -0,0 +1,476 @@ +#include"scf_elf_naja.h" +#include"scf_elf_link.h" + +static int _naja_elf_write_rel(scf_elf_context_t* elf) +{ + return elf_write_rel(elf, EM_AARCH64); +} + +static int _naja_elf_link_cs(elf_native_t* naja, elf_section_t* s, elf_section_t* rs, uint64_t cs_base) +{ + elf_sym_t* sym; + Elf64_Rela* rela; + + assert(rs->data_len % sizeof(Elf64_Rela) == 0); + + int i; + for (i = 0; i < rs->data_len; i += sizeof(Elf64_Rela)) { + + rela = (Elf64_Rela* )(rs->data + i); + sym = NULL; + + int sym_idx = ELF64_R_SYM(rela->r_info); + + assert(sym_idx >= 1); + assert(sym_idx - 1 < naja->symbols->size); + + sym = naja->symbols->data[sym_idx - 1]; + if (sym->dyn_flag) { + scf_loge("sym '%s' in dynamic so\n", sym->name->data); + continue; + } + + int j = elf_find_sym(&sym, rela, naja->symbols); + if (j < 0) + return -1; + + int32_t offset = sym->sym.st_value - (cs_base + rela->r_offset) + rela->r_addend; + + rela->r_info = ELF64_R_INFO(j, ELF64_R_TYPE(rela->r_info)); + + switch (ELF64_R_TYPE(rela->r_info)) { + + case R_AARCH64_CALL26: + + assert(0 == (offset & 0x3)); + + offset >>= 2; + + if (offset > 0x1ffffff || offset < -0x1ffffff) { + scf_loge("\n"); + return -EINVAL; + } + + offset &= 0x3ffffff; + offset |= (0x25 << 26); + + scf_loge("sym: %s, offset: %#x, %#lx\n", sym->name->data, offset, rela->r_offset); + + *(uint32_t*)(s->data + rela->r_offset) = offset; + break; + + case R_AARCH64_ADR_PREL_PG_HI21: + + offset >>= 12; + offset = ((offset & 0x3) << 29) | (((offset >> 2) & 0x7ffff) << 5); + + *(uint32_t*)(s->data + rela->r_offset) |= offset; + break; + + case R_AARCH64_ADD_ABS_LO12_NC: + + *(uint32_t*)(s->data + rela->r_offset) |= (sym->sym.st_value & 0xfff) << 10; + break; + + default: + scf_loge("\n"); + return -EINVAL; + break; + }; + } + + return 0; +} + +static int _naja_elf_link_ds(elf_native_t* naja, elf_section_t* s, elf_section_t* rs) +{ + elf_sym_t* sym; + Elf64_Rela* rela; + + assert(rs->data_len % sizeof(Elf64_Rela) == 0); + + int i; + for (i = 0; i < rs->data_len; i += sizeof(Elf64_Rela)) { + + rela = (Elf64_Rela* )(rs->data + i); + sym = NULL; + + int j = elf_find_sym(&sym, rela, naja->symbols); + if (j < 0) + return -1; + + assert(ELF64_R_TYPE(rela->r_info) == R_X86_64_64 + || ELF64_R_TYPE(rela->r_info) == R_X86_64_32); + + uint64_t offset = sym->sym.st_value + rela->r_addend; + + rela->r_info = ELF64_R_INFO(j, ELF64_R_TYPE(rela->r_info)); + + switch (ELF64_R_TYPE(rela->r_info)) { + + case R_AARCH64_ABS64: + memcpy(s->data + rela->r_offset, &offset, 8); + break; + + case R_AARCH64_ABS32: + memcpy(s->data + rela->r_offset, &offset, 4); + break; + default: + scf_loge("\n"); + return -EINVAL; + break; + }; + } + + return 0; +} + +static int _naja_elf_link_debug(elf_native_t* naja, elf_section_t* s, elf_section_t* rs) +{ + elf_sym_t* sym; + elf_sym_t* sym2; + Elf64_Rela* rela; + + assert(rs->data_len % sizeof(Elf64_Rela) == 0); + + int i; + for (i = 0; i < rs->data_len; i += sizeof(Elf64_Rela)) { + + rela = (Elf64_Rela* )(rs->data + i); + sym = NULL; + + int j = elf_find_sym(&sym, rela, naja->symbols); + if (j < 0) + return -1; + + uint64_t offset = sym->sym.st_value + rela->r_addend; + + if (!strncmp(sym->name->data, ".debug_", 7)) { + + int k = ELF64_R_SYM(rela->r_info); + + sym2 = naja->symbols->data[k - 1]; + + offset = sym2->sym.st_value + rela->r_addend; + rela->r_addend = offset; + + } else if (!strcmp(sym->name->data, ".text")) { + + int k = ELF64_R_SYM(rela->r_info); + + sym2 = naja->symbols->data[k - 1]; + + offset = sym2->sym.st_value; + rela->r_addend = sym2->sym.st_value - sym->sym.st_value; + } + + rela->r_info = ELF64_R_INFO(j, ELF64_R_TYPE(rela->r_info)); + + switch (ELF64_R_TYPE(rela->r_info)) { + + case R_AARCH64_ABS64: + memcpy(s->data + rela->r_offset, &offset, 8); + break; + + case R_AARCH64_ABS32: + memcpy(s->data + rela->r_offset, &offset, 4); + break; + default: + scf_loge("\n"); + return -EINVAL; + break; + }; + } + + return 0; +} + +static int _naja_elf_link_sections(elf_native_t* naja, uint32_t cs_index, uint32_t ds_index) +{ + elf_section_t* s; + elf_section_t* rs; + + int i; + for (i = 0; i < naja->sections->size; i++) { + rs = naja->sections->data[i]; + + if (SHT_RELA != rs->sh.sh_type) + continue; + + assert(rs->sh.sh_info < naja->sections->size); + + if (cs_index == rs->sh.sh_info + || ds_index == rs->sh.sh_info) + continue; + + if (!strcmp(rs->name->data, ".rela.plt")) + continue; + + s = naja->sections->data[rs->sh.sh_info - 1]; + + scf_loge("s: %s, rs: %s, rs->sh.sh_info: %u\n", s->name->data, rs->name->data, rs->sh.sh_info); + + assert(!strcmp(s->name->data, rs->name->data + 5)); + + if (_naja_elf_link_debug(naja, s, rs) < 0) { + scf_loge("\n"); + return -1; + } + } + + return 0; +} + +static int _naja_elf_write_exec(scf_elf_context_t* elf) +{ + elf_native_t* naja = elf->priv; + int nb_phdrs = 3; + + if (naja->dynsyms && naja->dynsyms->size) { + __naja_elf_add_dyn(naja); + nb_phdrs = 6; + } + + int nb_sections = 1 + naja->sections->size + 1 + 1 + 1; + uint64_t shstrtab_offset = 1; + uint64_t strtab_offset = 1; + uint64_t dynstr_offset = 1; + Elf64_Off phdr_offset = sizeof(naja->eh) + sizeof(Elf64_Shdr) * nb_sections; + Elf64_Off section_offset = phdr_offset + sizeof(Elf64_Phdr) * nb_phdrs; + + elf_section_t* s; + elf_section_t* cs = NULL; + elf_section_t* ros = NULL; + elf_section_t* ds = NULL; + elf_section_t* crela = NULL; + elf_section_t* drela = NULL; + elf_sym_t* sym; + + int i; + for (i = 0; i < naja->sections->size; i++) { + s = naja->sections->data[i]; + + if (!strcmp(".text", s->name->data)) { + + assert(s->data_len > 0); + assert(!cs); + cs = s; + + } else if (!strcmp(".rodata", s->name->data)) { + + assert(s->data_len >= 0); + assert(!ros); + ros = s; + + } else if (!strcmp(".data", s->name->data)) { + + assert(s->data_len >= 0); + assert(!ds); + ds = s; + + } else if (!strcmp(".rela.text", s->name->data)) { + + assert(!crela); + crela = s; + + } else if (!strcmp(".rela.data", s->name->data)) { + + assert(!drela); + drela = s; + } + + s->offset = section_offset; + section_offset += s->data_len; + } + assert(crela); + + uint64_t cs_align = (cs ->offset + cs ->data_len + 0x200000 - 1) >> 21 << 21; + uint64_t ro_align = (ros->offset + ros->data_len + 0x200000 - 1) >> 21 << 21; + + uint64_t rx_base = 0x400000; + uint64_t r_base = 0x400000 + cs_align; + uint64_t rw_base = 0x400000 + cs_align + ro_align; + + uint64_t cs_base = cs->offset + rx_base; + uint64_t ro_base = ros->offset + r_base; + uint64_t ds_base = ds->offset + rw_base; + uint64_t _start = 0; + + for (i = 0; i < naja->symbols->size; i++) { + sym = naja->symbols->data[i]; + + uint32_t shndx = sym->sym.st_shndx; + + if (shndx == cs->index) + sym->sym.st_value += cs_base; + + else if (shndx == ros->index) + sym->sym.st_value += ro_base; + + else if (shndx == ds->index) + sym->sym.st_value += ds_base; + + scf_logd("sym: %s, %#lx, st_shndx: %d\n", sym->name->data, sym->sym.st_value, sym->sym.st_shndx); + } + + int ret = _naja_elf_link_cs(naja, cs, crela, cs_base); + if (ret < 0) { + scf_loge("ret: %d\n", ret); + return ret; + } + + if (drela) { + ret = _naja_elf_link_ds(naja, ds, drela); + if (ret < 0) + return ret; + } + + ret = _naja_elf_link_sections(naja, cs->index, ds->index); + if (ret < 0) + return ret; + + elf_process_syms(naja, cs->index); + + cs ->sh.sh_addr = cs_base; + ds ->sh.sh_addr = ds_base; + ros->sh.sh_addr = ro_base; + + + if (6 == nb_phdrs) { + __naja_elf_post_dyn(naja, rx_base, rw_base, cs); + } + + for (i = 0; i < naja->symbols->size; i++) { + sym = naja->symbols->data[i]; + + if (!strcmp(sym->name->data, "_start")) { + + if (0 != _start) { + scf_loge("\n"); + return -EINVAL; + } + + _start = sym->sym.st_value; + break; + } + } + + // write elf header + elf_header(&naja->eh, ET_EXEC, EM_AARCH64, _start, phdr_offset, nb_phdrs, nb_sections, nb_sections - 1); + fwrite(&naja->eh, sizeof(naja->eh), 1, elf->fp); + + // write null section header + fwrite(&naja->sh_null, sizeof(naja->sh_null), 1, elf->fp); + + // write user's section header + section_offset = phdr_offset + sizeof(Elf64_Phdr) * nb_phdrs; + + for (i = 0; i < naja->sections->size; i++) { + s = naja->sections->data[i]; + + if (SHT_RELA == s->sh.sh_type && 0 == s->sh.sh_link) + s->sh.sh_link = nb_sections - 3; + + section_header(&s->sh, shstrtab_offset, s->sh.sh_addr, + section_offset, s->data_len, + s->sh.sh_link, s->sh.sh_info, s->sh.sh_entsize); + + if (SHT_STRTAB != s->sh.sh_type) + s->sh.sh_addralign = 8; + + section_offset += s->data_len; + shstrtab_offset += s->name->len + 1; + + fwrite(&s->sh, sizeof(s->sh), 1, elf->fp); + } + + // set user's symbols' name + int nb_local_syms = 1; + + for (i = 0; i < naja->symbols->size; i++) { + sym = naja->symbols->data[i]; + + if (sym->name) { + sym->sym.st_name = strtab_offset; + strtab_offset += sym->name->len + 1; + } else + sym->sym.st_name = 0; + + if (STB_LOCAL == ELF64_ST_BIND(sym->sym.st_info)) + nb_local_syms++; + } + + // write symtab section header + section_header(&naja->sh_symtab, shstrtab_offset, 0, + section_offset, (naja->symbols->size + 1) * sizeof(Elf64_Sym), + nb_sections - 2, nb_local_syms, sizeof(Elf64_Sym)); + + fwrite(&naja->sh_symtab, sizeof(naja->sh_symtab), 1, elf->fp); + + section_offset += (naja->symbols->size + 1) * sizeof(Elf64_Sym); + shstrtab_offset += strlen(".symtab") + 1; + + // write strtab section header + section_header(&naja->sh_strtab, shstrtab_offset, 0, + section_offset, strtab_offset, + 0, 0, 0); + fwrite(&naja->sh_strtab, sizeof(naja->sh_strtab), 1, elf->fp); + section_offset += strtab_offset; + shstrtab_offset += strlen(".strtab") + 1; + + // write shstrtab section header + uint64_t shstrtab_len = shstrtab_offset + strlen(".shstrtab") + 1; + section_header(&naja->sh_shstrtab, shstrtab_offset, 0, + section_offset, shstrtab_len, 0, 0, 0); + fwrite(&naja->sh_shstrtab, sizeof(naja->sh_shstrtab), 1, elf->fp); + +#if 1 + if (6 == nb_phdrs) { + __naja_elf_write_phdr(elf, rx_base, phdr_offset, nb_phdrs); + + __naja_elf_write_interp(elf, rx_base, naja->interp->offset, naja->interp->data_len); + } + + __naja_elf_write_text (elf, rx_base, 0, cs->offset + cs->data_len); + __naja_elf_write_rodata(elf, r_base, ros->offset, ros->data_len); + + if (6 == nb_phdrs) { + __naja_elf_write_data(elf, rw_base, naja->dynamic->offset, + naja->dynamic->data_len + naja->got_plt->data_len + ds->data_len); + + __naja_elf_write_dynamic(elf, rw_base, naja->dynamic->offset, naja->dynamic->data_len); + } else { + __naja_elf_write_data(elf, rw_base, ds->offset, ds->data_len); + } +#endif + + elf_write_sections(elf); + elf_write_symtab (elf); + elf_write_strtab (elf); + elf_write_shstrtab(elf); + return 0; +} + +scf_elf_ops_t elf_ops_naja = +{ + .machine = "naja", + + .open = elf_open, + .close = elf_close, + + .add_sym = elf_add_sym, + .add_section = elf_add_section, + + .add_rela_section = elf_add_rela_section, + + .add_dyn_need = elf_add_dyn_need, + .add_dyn_rela = elf_add_dyn_rela, + + .read_syms = elf_read_syms, + .read_relas = elf_read_relas, + .read_section = elf_read_section, + + .write_rel = _naja_elf_write_rel, + .write_exec = _naja_elf_write_exec, +}; + diff --git a/elf/scf_elf_naja.h b/elf/scf_elf_naja.h new file mode 100644 index 0000000..ab586b7 --- /dev/null +++ b/elf/scf_elf_naja.h @@ -0,0 +1,20 @@ +#ifndef SCF_ELF_NAJA_H +#define SCF_ELF_NAJA_H + +#include"scf_elf.h" +#include"scf_elf_native.h" +#include"scf_vector.h" +#include"scf_string.h" + +int __naja_elf_add_dyn (elf_native_t* naja); +int __naja_elf_post_dyn(elf_native_t* naja, uint64_t rx_base, uint64_t rw_base, elf_section_t* cs); + +int __naja_elf_write_phdr (scf_elf_context_t* elf, uint64_t rx_base, uint64_t offset, uint32_t nb_phdrs); +int __naja_elf_write_interp (scf_elf_context_t* elf, uint64_t rx_base, uint64_t offset, uint64_t len); +int __naja_elf_write_text (scf_elf_context_t* elf, uint64_t rx_base, uint64_t offset, uint64_t len); +int __naja_elf_write_rodata (scf_elf_context_t* elf, uint64_t r_base, uint64_t offset, uint64_t len); +int __naja_elf_write_data (scf_elf_context_t* elf, uint64_t rw_base, uint64_t offset, uint64_t len); +int __naja_elf_write_dynamic(scf_elf_context_t* elf, uint64_t rw_base, uint64_t offset, uint64_t len); + +#endif + diff --git a/elf/scf_elf_naja_so.c b/elf/scf_elf_naja_so.c new file mode 100644 index 0000000..345a9af --- /dev/null +++ b/elf/scf_elf_naja_so.c @@ -0,0 +1,879 @@ +#include"scf_elf_naja.h" +#include"scf_elf_link.h" + +static uint32_t naja_plt_lazy[8] = { + 0xa9bf7bf0, // stp x16, x30, [sp, #-16]! + 0x90000010, // adrp x16, 0 + 0xf9400211, // ldr x17, [x16, #0] + 0x91000210, // add x16, x16, #0 + + 0xd61f0220, // br x17 + 0xd503201f, // nop + 0xd503201f, // nop + 0xd503201f, // nop +}; + +static uint32_t naja_plt[4] = { + 0x90000010, // adrp x16, 0 + 0xf9400211, // ldr x17, [x16, #0] + 0x91000210, // add x16, x16, #0 + 0xd61f0220, // br x17 +}; + + +static uint32_t _naja_elf_hash(const uint8_t* p) +{ + uint32_t k = 0; + uint32_t u = 0; + + while (*p) { + k = (k << 4) + *p++; + u = k & 0xf0000000; + + if (u) + k ^= u >> 24; + k &= ~u; + } + return k; +} + +static int _naja_elf_add_interp(elf_native_t* naja, elf_section_t** ps) +{ + elf_section_t* s; + + s = calloc(1, sizeof(elf_section_t)); + if (!s) + return -ENOMEM; + + s->name = scf_string_cstr(".interp"); + if (!s->name) { + free(s); + return -ENOMEM; + } + + char* interp = "/lib/ld-linux-aarch64.so.1"; + size_t len = strlen(interp); + size_t align = (len + 1 + 7) & ~0x7; + + s->data = calloc(1, align); + if (!s->data) { + scf_string_free(s->name); + free(s); + return -ENOMEM; + } + memcpy(s->data, interp, len); + s->data_len = align; + + s->index = 1; + + s->sh.sh_type = SHT_PROGBITS; + s->sh.sh_flags = SHF_ALLOC; + s->sh.sh_addralign = 1; + + int ret = scf_vector_add(naja->sections, s); + if (ret < 0) { + scf_string_free(s->name); + free(s->data); + free(s); + return -ENOMEM; + } + + *ps = s; + return 0; +} + +static int _naja_elf_add_gnu_version(elf_native_t* naja, elf_section_t** ps) +{ + elf_section_t* s; + + s = calloc(1, sizeof(elf_section_t)); + if (!s) + return -ENOMEM; + + s->name = scf_string_cstr(".gnu.version"); + if (!s->name) { + free(s); + return -ENOMEM; + } + + s->data = calloc(naja->dynsyms->size, sizeof(Elf64_Versym)); + if (!s->data) { + scf_string_free(s->name); + free(s); + return -ENOMEM; + } + s->data_len = naja->dynsyms->size * sizeof(Elf64_Versym); + + s->index = 1; + + s->sh.sh_type = SHT_GNU_versym; + s->sh.sh_flags = SHF_ALLOC; + s->sh.sh_addralign = 8; + + int ret = scf_vector_add(naja->sections, s); + if (ret < 0) { + scf_string_free(s->name); + free(s->data); + free(s); + return -ENOMEM; + } + + *ps = s; + return 0; +} + +static int _naja_elf_add_gnu_version_r(elf_native_t* naja, elf_section_t** ps) +{ + elf_section_t* s; + + s = calloc(1, sizeof(elf_section_t)); + if (!s) + return -ENOMEM; + + s->name = scf_string_cstr(".gnu.version_r"); + if (!s->name) { + free(s); + return -ENOMEM; + } + + s->data = calloc(1, sizeof(Elf64_Verneed) + sizeof(Elf64_Vernaux)); + if (!s->data) { + scf_string_free(s->name); + free(s); + return -ENOMEM; + } + s->data_len = sizeof(Elf64_Verneed) + sizeof(Elf64_Vernaux); + + s->index = 1; + + s->sh.sh_type = SHT_GNU_verneed; + s->sh.sh_flags = SHF_ALLOC; + s->sh.sh_addralign = 8; + + int ret = scf_vector_add(naja->sections, s); + if (ret < 0) { + scf_string_free(s->name); + free(s->data); + free(s); + return -ENOMEM; + } + + *ps = s; + return 0; +} + +static int _naja_elf_add_dynsym(elf_native_t* naja, elf_section_t** ps) +{ + elf_section_t* s; + + s = calloc(1, sizeof(elf_section_t)); + if (!s) + return -ENOMEM; + + s->name = scf_string_cstr(".dynsym"); + if (!s->name) { + free(s); + return -ENOMEM; + } + + s->data = calloc(naja->dynsyms->size + 1, sizeof(Elf64_Sym)); + if (!s->data) { + scf_string_free(s->name); + free(s); + return -ENOMEM; + } + s->data_len = (naja->dynsyms->size + 1) * sizeof(Elf64_Sym); + + s->index = 1; + + s->sh.sh_type = SHT_DYNSYM; + s->sh.sh_flags = SHF_ALLOC; + s->sh.sh_info = 1; + s->sh.sh_addralign = 8; + s->sh.sh_entsize = sizeof(Elf64_Sym); + + int ret = scf_vector_add(naja->sections, s); + if (ret < 0) { + scf_string_free(s->name); + free(s->data); + free(s); + return -ENOMEM; + } + + *ps = s; + return 0; +} + +static int _naja_elf_add_dynstr(elf_native_t* naja, elf_section_t** ps) +{ + elf_section_t* s; + + s = calloc(1, sizeof(elf_section_t)); + if (!s) + return -ENOMEM; + + s->name = scf_string_cstr(".dynstr"); + if (!s->name) { + free(s); + return -ENOMEM; + } + + s->index = 1; + + s->sh.sh_type = SHT_STRTAB; + s->sh.sh_flags = SHF_ALLOC; + s->sh.sh_addralign = 1; + + int ret = scf_vector_add(naja->sections, s); + if (ret < 0) { + scf_string_free(s->name); + free(s->data); + free(s); + return -ENOMEM; + } + + *ps = s; + return 0; +} + +static int _naja_elf_add_dynamic(elf_native_t* naja, elf_section_t** ps) +{ + elf_section_t* s; + + s = calloc(1, sizeof(elf_section_t)); + if (!s) + return -ENOMEM; + + s->name = scf_string_cstr(".dynamic"); + if (!s->name) { + free(s); + return -ENOMEM; + } + + int nb_tags = naja->dyn_needs->size + 11 + 1; + + s->data = calloc(nb_tags, sizeof(Elf64_Dyn)); + if (!s->data) { + scf_string_free(s->name); + free(s); + return -ENOMEM; + } + s->data_len = nb_tags * sizeof(Elf64_Dyn); + + s->index = 1; + + s->sh.sh_type = SHT_PROGBITS; + s->sh.sh_flags = SHF_ALLOC | SHF_WRITE; + s->sh.sh_addralign = 8; + s->sh.sh_entsize = sizeof(Elf64_Dyn); + + int ret = scf_vector_add(naja->sections, s); + if (ret < 0) { + scf_string_free(s->name); + free(s->data); + free(s); + return -ENOMEM; + } + + *ps = s; + return 0; +} + +static int _naja_elf_add_got_plt(elf_native_t* naja, elf_section_t** ps) +{ + elf_section_t* s; + + s = calloc(1, sizeof(elf_section_t)); + if (!s) + return -ENOMEM; + + s->name = scf_string_cstr(".got.plt"); + if (!s->name) { + free(s); + return -ENOMEM; + } + + s->data = calloc(naja->dynsyms->size + 3, sizeof(void*)); + if (!s->data) { + scf_string_free(s->name); + free(s); + return -ENOMEM; + } + s->data_len = (naja->dynsyms->size + 3) * sizeof(void*); + + s->index = 1; + + s->sh.sh_type = SHT_PROGBITS; + s->sh.sh_flags = SHF_ALLOC | SHF_WRITE; + s->sh.sh_addralign = 8; + + int ret = scf_vector_add(naja->sections, s); + if (ret < 0) { + scf_string_free(s->name); + free(s->data); + free(s); + return -ENOMEM; + } + + *ps = s; + return 0; +} + +static int _naja_elf_add_rela_plt(elf_native_t* naja, elf_section_t** ps) +{ + elf_section_t* s; + + s = calloc(1, sizeof(elf_section_t)); + if (!s) + return -ENOMEM; + + s->name = scf_string_cstr(".rela.plt"); + if (!s->name) { + free(s); + return -ENOMEM; + } + + s->data = calloc(naja->dynsyms->size, sizeof(Elf64_Rela)); + if (!s->data) { + scf_string_free(s->name); + free(s); + return -ENOMEM; + } + s->data_len = naja->dynsyms->size * sizeof(Elf64_Rela); + + s->index = 1; + + s->sh.sh_type = SHT_RELA; + s->sh.sh_flags = SHF_ALLOC | SHF_INFO_LINK; + s->sh.sh_addralign = 8; + s->sh.sh_entsize = sizeof(Elf64_Rela); + + int ret = scf_vector_add(naja->sections, s); + if (ret < 0) { + scf_string_free(s->name); + free(s->data); + free(s); + return -ENOMEM; + } + + *ps = s; + return 0; +} + +static int _naja_elf_add_plt(elf_native_t* naja, elf_section_t** ps) +{ + elf_section_t* s; + + s = calloc(1, sizeof(elf_section_t)); + if (!s) + return -ENOMEM; + + s->name = scf_string_cstr(".plt"); + if (!s->name) { + free(s); + return -ENOMEM; + } + + s->data = malloc(sizeof(naja_plt_lazy) + sizeof(naja_plt) * naja->dynsyms->size); + if (!s->data) { + scf_string_free(s->name); + free(s); + return -ENOMEM; + } + + memcpy(s->data, naja_plt_lazy, sizeof(naja_plt_lazy)); + s->data_len = sizeof(naja_plt_lazy); + + int i; + for (i = 0; i < naja->dynsyms->size; i++) { + + memcpy(s->data + s->data_len, naja_plt, sizeof(naja_plt)); + + s->data_len += sizeof(naja_plt); + } + + s->index = 1; + + s->sh.sh_type = SHT_PROGBITS; + s->sh.sh_flags = SHF_ALLOC; + s->sh.sh_addralign = 1; + + int ret = scf_vector_add(naja->sections, s); + if (ret < 0) { + scf_string_free(s->name); + free(s->data); + free(s); + return -ENOMEM; + } + + *ps = s; + return 0; +} + +static int _section_cmp(const void* v0, const void* v1) +{ + const elf_section_t* s0 = *(const elf_section_t**)v0; + const elf_section_t* s1 = *(const elf_section_t**)v1; + + if (s0->index < s1->index) + return -1; + else if (s0->index > s1->index) + return 1; + return 0; +} + +int __naja_elf_add_dyn (elf_native_t* naja) +{ + elf_section_t* s; + elf_sym_t* sym; + Elf64_Rela* rela; + + int i; + for (i = naja->symbols->size - 1; i >= 0; i--) { + sym = naja->symbols->data[i]; + + uint16_t shndx = sym->sym.st_shndx; + + if (STT_SECTION == ELF64_ST_TYPE(sym->sym.st_info)) { + if (shndx > 0) { + assert(shndx - 1 < naja->sections->size); + sym->section = naja->sections->data[shndx - 1]; + } + } else if (0 != shndx) { + if (shndx - 1 < naja->sections->size) + sym->section = naja->sections->data[shndx - 1]; + } + } + + char* sh_names[] = { + ".interp", + ".dynsym", + ".dynstr", +// ".gnu.version_r", + ".rela.plt", + ".plt", + + ".text", + ".rodata", + + ".dynamic", + ".got.plt", + ".data", + }; + + for (i = 0; i < naja->sections->size; i++) { + s = naja->sections->data[i]; + + s->index = naja->sections->size + 1 + sizeof(sh_names) / sizeof(sh_names[0]); + + scf_logw("s: %s, link: %d, info: %d\n", s->name->data, s->sh.sh_link, s->sh.sh_info); + + if (s->sh.sh_link > 0) { + assert(s->sh.sh_link - 1 < naja->sections->size); + + s->link = naja->sections->data[s->sh.sh_link - 1]; + } + + if (s->sh.sh_info > 0) { + assert(s->sh.sh_info - 1 < naja->sections->size); + + s->info = naja->sections->data[s->sh.sh_info - 1]; + } + } + + _naja_elf_add_interp(naja, &naja->interp); + _naja_elf_add_dynsym(naja, &naja->dynsym); + _naja_elf_add_dynstr(naja, &naja->dynstr); + +// _naja_elf_add_gnu_version_r(naja, &naja->gnu_version_r); + + _naja_elf_add_rela_plt(naja, &naja->rela_plt); + _naja_elf_add_plt(naja, &naja->plt); + + _naja_elf_add_dynamic(naja, &naja->dynamic); + _naja_elf_add_got_plt(naja, &naja->got_plt); + + scf_string_t* str = scf_string_alloc(); + + char c = '\0'; + scf_string_cat_cstr_len(str, &c, 1); + + Elf64_Sym* syms = (Elf64_Sym* )naja->dynsym->data; + Elf64_Sym sym0 = {0}; + + sym0.st_info = ELF64_ST_INFO(STB_LOCAL, STT_NOTYPE); + memcpy(&syms[0], &sym0, sizeof(Elf64_Sym)); + + for (i = 0; i < naja->dynsyms->size; i++) { + elf_sym_t* xsym = naja->dynsyms->data[i]; + + memcpy(&syms[i + 1], &xsym->sym, sizeof(Elf64_Sym)); + + syms[i + 1].st_name = str->len; + + scf_loge("i: %d, st_value: %#lx\n", i, syms[i + 1].st_value); + + scf_string_cat_cstr_len(str, xsym->name->data, xsym->name->len + 1); + } + +#if 0 + Elf64_Verneed* verneeds = (Elf64_Verneed*) naja->gnu_version_r->data; + Elf64_Vernaux* vernauxs = (Elf64_Vernaux*)(naja->gnu_version_r->data +sizeof(Elf64_Verneed)); + + verneeds[0].vn_version = VER_NEED_CURRENT; + verneeds[0].vn_file = str->len; + verneeds[0].vn_cnt = 1; + verneeds[0].vn_aux = sizeof(Elf64_Verneed); + verneeds[0].vn_next = 0; + + scf_string_cat_cstr_len(str, "libc.so.6", strlen("libc.so.6") + 1); + + vernauxs[0].vna_hash = _naja_elf_hash("GLIBC_2.4"); + vernauxs[0].vna_flags = 0; + vernauxs[0].vna_other = 2; + vernauxs[0].vna_name = str->len; + vernauxs[0].vna_next = 0; + + scf_string_cat_cstr_len(str, "GLIBC_2.4", strlen("GLIBC_2.4") + 1); +#endif + + Elf64_Dyn* dyns = (Elf64_Dyn*)naja->dynamic->data; + + size_t prefix = strlen("../lib/naja"); + + for (i = 0; i < naja->dyn_needs->size; i++) { + scf_string_t* needed = naja->dyn_needs->data[i]; + + dyns[i].d_tag = DT_NEEDED; + dyns[i].d_un.d_val = str->len; + + scf_logw("i: %d, %s, %s\n", i, needed->data, needed->data + prefix); + + scf_string_cat_cstr_len(str, needed->data + prefix, needed->len - prefix + 1); + } + + dyns[i].d_tag = DT_STRTAB; + dyns[i + 1].d_tag = DT_SYMTAB; + dyns[i + 2].d_tag = DT_STRSZ; + dyns[i + 3].d_tag = DT_SYMENT; + dyns[i + 4].d_tag = DT_PLTGOT; + dyns[i + 5].d_tag = DT_PLTRELSZ; + dyns[i + 6].d_tag = DT_PLTREL; + dyns[i + 7].d_tag = DT_JMPREL; +// dyns[i + 8].d_tag = DT_VERNEED; +// dyns[i + 9].d_tag = DT_VERNEEDNUM; +// dyns[i +10].d_tag = DT_VERSYM; + dyns[i +8].d_tag = DT_NULL; + + dyns[i].d_un.d_ptr = (uintptr_t)naja->dynstr; + dyns[i + 1].d_un.d_ptr = (uintptr_t)naja->dynsym; + dyns[i + 2].d_un.d_val = str->len; + dyns[i + 3].d_un.d_val = sizeof(Elf64_Sym); + dyns[i + 4].d_un.d_ptr = (uintptr_t)naja->got_plt; + dyns[i + 5].d_un.d_ptr = sizeof(Elf64_Rela); + dyns[i + 6].d_un.d_ptr = DT_RELA; + dyns[i + 7].d_un.d_ptr = (uintptr_t)naja->rela_plt; +// dyns[i + 8].d_un.d_ptr = (uintptr_t)naja->gnu_version_r; +// dyns[i + 9].d_un.d_ptr = 1; +// dyns[i +10].d_un.d_ptr = (uintptr_t)naja->gnu_version; + dyns[i +8].d_un.d_ptr = 0; + + int fill = 8 - (str->len & 0x7); + if (fill > 0) + scf_string_fill_zero(str, fill); + + naja->dynstr->data = str->data; + naja->dynstr->data_len = str->len; + + str->data = NULL; + str->len = 0; + str->capacity = 0; + scf_string_free(str); + str = NULL; + + naja->rela_plt->link = naja->dynsym; + naja->rela_plt->info = naja->got_plt; + naja->dynsym ->link = naja->dynstr; +#if 0 + naja->gnu_version_r->link = naja->dynstr; + naja->gnu_version_r->info = naja->interp; +#endif + + for (i = 0; i < naja->sections->size; i++) { + s = naja->sections->data[i]; + + int j; + for (j = 0; j < sizeof(sh_names) / sizeof(sh_names[0]); j++) { + if (!strcmp(s->name->data, sh_names[j])) + break; + } + + if (j < sizeof(sh_names) / sizeof(sh_names[0])) + s->index = j + 1; + + scf_logd("i: %d, s: %s, index: %d\n", i, s->name->data, s->index); + } + + qsort(naja->sections->data, naja->sections->size, sizeof(void*), _section_cmp); + + int j = sizeof(sh_names) / sizeof(sh_names[0]); + + for (i = j; i < naja->sections->size; i++) { + s = naja->sections->data[i]; + + s->index = i + 1; + } + + for (i = 0; i < naja->sections->size; i++) { + s = naja->sections->data[i]; + + scf_loge("i: %d, s: %s, index: %d\n", i, s->name->data, s->index); + + if (s->link) { + scf_logd("link: %s, index: %d\n", s->link->name->data, s->link->index); + s->sh.sh_link = s->link->index; + } + + if (s->info) { + scf_logd("info: %s, index: %d\n", s->info->name->data, s->info->index); + s->sh.sh_info = s->info->index; + } + } + +#if 1 + for (i = 0; i < naja->symbols->size; i++) { + sym = naja->symbols->data[i]; + + if (sym->section) { + scf_logw("sym: %s, index: %d->%d\n", sym->name->data, sym->sym.st_shndx, sym->section->index); + sym->sym.st_shndx = sym->section->index; + } + } +#endif + return 0; +} + +int __naja_elf_post_dyn(elf_native_t* naja, uint64_t rx_base, uint64_t rw_base, elf_section_t* cs) +{ + uint64_t cs_base = rx_base + cs->offset; + +// naja->gnu_version_r->sh.sh_addr = rx_base + naja->gnu_version_r->offset; + + naja->rela_plt->sh.sh_addr = rx_base + naja->rela_plt->offset; + naja->dynamic->sh.sh_addr = rw_base + naja->dynamic->offset; + naja->got_plt->sh.sh_addr = rw_base + naja->got_plt->offset; + naja->interp->sh.sh_addr = rx_base + naja->interp->offset; + naja->plt->sh.sh_addr = rx_base + naja->plt->offset; + + scf_loge("rw_base: %#lx, offset: %#lx\n", rw_base, naja->got_plt->offset); + scf_loge("got_addr: %#lx\n", naja->got_plt->sh.sh_addr); + + Elf64_Rela* rela_plt = (Elf64_Rela*)naja->rela_plt->data; + Elf64_Sym* dynsym = (Elf64_Sym* )naja->dynsym->data; + uint64_t* got_plt = (uint64_t* )naja->got_plt->data; + uint32_t* plt = (uint32_t* )naja->plt->data; + + uint64_t got_addr = naja->got_plt->sh.sh_addr; + uint64_t plt_addr = naja->plt->sh.sh_addr; + int32_t offset = got_addr - plt_addr; + + got_plt[0] = naja->dynamic->sh.sh_addr; + got_addr += 8; + + got_plt[1] = 0; + got_plt[2] = 0; + got_plt += 3; + got_addr += 8; + + scf_loge("got_addr: %#lx, plt_addr: %#lx, offset: %d, %#x\n", got_addr, plt_addr, offset, offset); + + plt[1] |= (((offset >> 12) & 0x3) << 29) | (((offset >> 14) & 0x7ffff) << 5); + plt[2] |= ((got_addr & 0xfff) >> 3) << 10; + plt[3] |= (got_addr & 0xfff) << 10; + + got_addr += 8; + plt_addr += sizeof(naja_plt_lazy); + plt += sizeof(naja_plt_lazy) / sizeof(naja_plt_lazy[0]); + + int i; + for (i = 0; i < naja->dynsyms->size; i++) { + rela_plt[i].r_offset = got_addr; + rela_plt[i].r_addend = 0; + rela_plt[i].r_info = ELF64_R_INFO(i + 1, R_AARCH64_JUMP_SLOT); + + *got_plt = naja->plt->sh.sh_addr; + + offset = got_addr - plt_addr; + + scf_loge("i: %d, got_addr: %#lx, plt_addr: %#lx, offset: %d, %#x\n", i, got_addr, plt_addr, offset, offset); + + plt[0] |= (((offset >> 12) & 0x3) << 29) | (((offset >> 14) & 0x7ffff) << 5); + plt[1] |= ((got_addr & 0xfff) >> 3) << 10; + plt[2] |= (got_addr & 0xfff) << 10; + + plt += sizeof(naja_plt) / sizeof(naja_plt[0]); + plt_addr += sizeof(naja_plt); + got_addr += 8; + got_plt++; + } + + for (i = 0; i < naja->dyn_relas->size; i++) { + Elf64_Rela* r = naja->dyn_relas->data[i]; + + int sym_idx = ELF64_R_SYM(r->r_info); + assert(sym_idx > 0); + + assert(ELF64_R_TYPE(r->r_info) == R_AARCH64_CALL26); + + uint64_t plt_addr = naja->plt->sh.sh_addr + sizeof(naja_plt_lazy) + (sym_idx - 1) * sizeof(naja_plt); + + int32_t offset = plt_addr - (cs_base + r->r_offset) + r->r_addend; + + assert(0 == (offset & 0x3)); + + offset >>= 2; + + if (offset > 0x1ffffff || offset < -0x1ffffff) { + scf_loge("\n"); + return -EINVAL; + } + + offset &= 0x3ffffff; + offset |= (0x25 << 26); + + *(uint32_t*)(cs->data + r->r_offset) = offset; + } + + Elf64_Dyn* dtags = (Elf64_Dyn*)naja->dynamic->data; + + for (i = naja->dyn_needs->size; i < naja->dynamic->data_len / sizeof(Elf64_Dyn); i++) { + + elf_section_t* s = (elf_section_t*)dtags[i].d_un.d_ptr; + + switch (dtags[i].d_tag) { + + case DT_SYMTAB: + case DT_STRTAB: + case DT_JMPREL: + case DT_VERNEED: + case DT_VERSYM: + dtags[i].d_un.d_ptr = s->offset + rx_base; + s->sh.sh_addr = s->offset + rx_base; + break; + + case DT_PLTGOT: + dtags[i].d_un.d_ptr = s->offset + rw_base; + s->sh.sh_addr = s->offset + rw_base; + break; + default: + break; + }; + } + + return 0; +} + +int __naja_elf_write_phdr(scf_elf_context_t* elf, uint64_t rx_base, uint64_t offset, uint32_t nb_phdrs) +{ + // write program header + + Elf64_Phdr ph_phdr = {0}; + + ph_phdr.p_type = PT_PHDR; + ph_phdr.p_flags = PF_R; + ph_phdr.p_offset = offset; + ph_phdr.p_vaddr = rx_base + offset; + ph_phdr.p_paddr = ph_phdr.p_vaddr; + ph_phdr.p_filesz = sizeof(Elf64_Phdr) * nb_phdrs; + ph_phdr.p_memsz = ph_phdr.p_filesz; + ph_phdr.p_align = 0x8; + + fwrite(&ph_phdr, sizeof(ph_phdr), 1, elf->fp); + return 0; +} + +int __naja_elf_write_interp(scf_elf_context_t* elf, uint64_t rx_base, uint64_t offset, uint64_t len) +{ + Elf64_Phdr ph_interp = {0}; + + ph_interp.p_type = PT_INTERP; + ph_interp.p_flags = PF_R; + ph_interp.p_offset = offset; + ph_interp.p_vaddr = rx_base + offset; + ph_interp.p_paddr = ph_interp.p_vaddr; + ph_interp.p_filesz = len; + ph_interp.p_memsz = ph_interp.p_filesz; + ph_interp.p_align = 0x1; + + fwrite(&ph_interp, sizeof(ph_interp), 1, elf->fp); + return 0; +} + +int __naja_elf_write_text(scf_elf_context_t* elf, uint64_t rx_base, uint64_t offset, uint64_t len) +{ + Elf64_Phdr ph_text = {0}; + + ph_text.p_type = PT_LOAD; + ph_text.p_flags = PF_R | PF_X; + ph_text.p_offset = 0; + ph_text.p_vaddr = rx_base + offset; + ph_text.p_paddr = ph_text.p_vaddr; + ph_text.p_filesz = len; + ph_text.p_memsz = ph_text.p_filesz; + ph_text.p_align = 0x200000; + + fwrite(&ph_text, sizeof(ph_text), 1, elf->fp); + return 0; +} + +int __naja_elf_write_rodata(scf_elf_context_t* elf, uint64_t r_base, uint64_t offset, uint64_t len) +{ + Elf64_Phdr ph_rodata = {0}; + + ph_rodata.p_type = PT_LOAD; + ph_rodata.p_flags = PF_R; + ph_rodata.p_offset = offset; + ph_rodata.p_vaddr = r_base + offset; + ph_rodata.p_paddr = ph_rodata.p_vaddr; + ph_rodata.p_filesz = len; + ph_rodata.p_memsz = ph_rodata.p_filesz; + ph_rodata.p_align = 0x200000; + + fwrite(&ph_rodata, sizeof(ph_rodata), 1, elf->fp); + return 0; +} + +int __naja_elf_write_data(scf_elf_context_t* elf, uint64_t rw_base, uint64_t offset, uint64_t len) +{ + Elf64_Phdr ph_data = {0}; + + ph_data.p_type = PT_LOAD; + ph_data.p_flags = PF_R | PF_W; + ph_data.p_offset = offset; + ph_data.p_vaddr = rw_base + offset; + ph_data.p_paddr = ph_data.p_vaddr; + ph_data.p_filesz = len; + ph_data.p_memsz = ph_data.p_filesz; + ph_data.p_align = 0x200000; + + fwrite(&ph_data, sizeof(ph_data), 1, elf->fp); + return 0; +} + +int __naja_elf_write_dynamic(scf_elf_context_t* elf, uint64_t rw_base, uint64_t offset, uint64_t len) +{ + Elf64_Phdr ph_dynamic = {0}; + + ph_dynamic.p_type = PT_DYNAMIC; + ph_dynamic.p_flags = PF_R | PF_W; + ph_dynamic.p_offset = offset; + ph_dynamic.p_vaddr = rw_base + offset; + ph_dynamic.p_paddr = ph_dynamic.p_vaddr; + ph_dynamic.p_filesz = len; + ph_dynamic.p_memsz = ph_dynamic.p_filesz; + ph_dynamic.p_align = 0x8; + + fwrite(&ph_dynamic, sizeof(Elf64_Phdr), 1, elf->fp); + return 0; +} + diff --git a/elf/scf_elf_native.c b/elf/scf_elf_native.c new file mode 100644 index 0000000..9a38604 --- /dev/null +++ b/elf/scf_elf_native.c @@ -0,0 +1,1004 @@ +#include"scf_elf_native.h" +#include"scf_elf_link.h" + +int elf_open(scf_elf_context_t* elf) +{ + if (!elf) + return -EINVAL; + + elf_native_t* e = calloc(1, sizeof(elf_native_t)); + if (!e) + return -ENOMEM; + + e->sh_null.sh_type = SHT_NULL; + + e->sh_symtab.sh_type = SHT_SYMTAB; + e->sh_symtab.sh_flags = 0; + e->sh_symtab.sh_addralign = 8; + + e->sh_strtab.sh_type = SHT_STRTAB; + e->sh_strtab.sh_flags = 0; + e->sh_strtab.sh_addralign = 1; + + e->sh_shstrtab.sh_type = SHT_STRTAB; + e->sh_shstrtab.sh_flags = 0; + e->sh_shstrtab.sh_addralign = 1; + + e->sections = scf_vector_alloc(); + e->symbols = scf_vector_alloc(); + + elf->priv = e; + return 0; +} + +int elf_close(scf_elf_context_t* elf) +{ + elf_native_t* e = elf->priv; + + if (e) { + free(e); + e = NULL; + } + return 0; +} + +int elf_add_sym(scf_elf_context_t* elf, const scf_elf_sym_t* sym, const char* sh_name) +{ + elf_sym_t* xsym; + elf_native_t* e = elf->priv; + scf_vector_t* vec = NULL; + + if (!strcmp(sh_name, ".symtab")) + vec = e->symbols; + + else if (!strcmp(sh_name, ".dynsym")) { + + if (!e->dynsyms) { + e->dynsyms = scf_vector_alloc(); + if (!e->dynsyms) + return -ENOMEM; + } + + vec = e->dynsyms; + } else + return -EINVAL; + + xsym = calloc(1, sizeof(elf_sym_t)); + if (!xsym) + return -ENOMEM; + + if (sym->name) + xsym->name = scf_string_cstr(sym->name); + else + xsym->name = NULL; + + xsym->sym.st_size = sym->st_size; + xsym->sym.st_value = sym->st_value; + xsym->sym.st_shndx = sym->st_shndx; + xsym->sym.st_info = sym->st_info; + + xsym->dyn_flag = sym->dyn_flag; + + int ret = scf_vector_add(vec, xsym); + if (ret < 0) { + scf_string_free(xsym->name); + free(xsym); + return ret; + } + + xsym->index = vec->size; + return 0; +} + +int elf_add_section(scf_elf_context_t* elf, const scf_elf_section_t* section) +{ + elf_native_t* e = elf->priv; + + elf_section_t* s; + elf_section_t* s2; + int i; + + if (section->index > 0) { + + for (i = e->sections->size - 1; i >= 0; i--) { + s = e->sections->data[i]; + + if (s->index == section->index) { + scf_loge("s->index: %d\n", s->index); + return -1; + } + } + } + + s = calloc(1, sizeof(elf_section_t)); + if (!s) + return -ENOMEM; + + s->name = scf_string_cstr(section->name); + if (!s->name) { + free(s); + return -ENOMEM; + } + + s->sh.sh_type = section->sh_type; + s->sh.sh_flags = section->sh_flags; + s->sh.sh_addralign = section->sh_addralign; + + if (section->data && section->data_len > 0) { + s->data = malloc(section->data_len); + if (!s->data) { + scf_string_free(s->name); + free(s); + return -ENOMEM; + } + + memcpy(s->data, section->data, section->data_len); + s->data_len = section->data_len; + } + + if (scf_vector_add(e->sections, s) < 0) { + if (s->data) + free(s->data); + scf_string_free(s->name); + free(s); + return -ENOMEM; + } + + if (0 == section->index) + s->index = e->sections->size; + else { + s->index = section->index; + + for (i = e->sections->size - 2; i >= 0; i--) { + s2 = e->sections->data[i]; + + if (s2->index < s->index) + break; + + e->sections->data[i + 1] = s2; + } + + e->sections->data[i + 1] = s; + } + + return s->index; +} + +int elf_add_rela_section(scf_elf_context_t* elf, const scf_elf_section_t* section, scf_vector_t* relas) +{ + if (relas->size <= 0) { + scf_loge("\n"); + return -EINVAL; + } + + elf_native_t* e = elf->priv; + + elf_section_t* s = calloc(1, sizeof(elf_section_t)); + if (!s) + return -ENOMEM; + + s->name = scf_string_cstr(section->name); + if (!s->name) { + free(s); + return -ENOMEM; + } + + s->index = e->sections->size + 1; + s->sh.sh_type = SHT_RELA; + s->sh.sh_flags = SHF_INFO_LINK; + s->sh.sh_addralign = section->sh_addralign; + s->sh.sh_link = section->sh_link; + s->sh.sh_info = section->sh_info; + s->sh.sh_entsize = sizeof(Elf64_Rela); + + s->data_len = sizeof(Elf64_Rela) * relas->size; + + s->data = malloc(s->data_len); + if (!s->data) { + scf_string_free(s->name); + free(s); + return -ENOMEM; + } + + Elf64_Rela* pr = (Elf64_Rela*) s->data; + + int i; + for (i = 0; i < relas->size; i++) { + + scf_elf_rela_t* r = relas->data[i]; + + + pr[i].r_offset = r->r_offset; + pr[i].r_info = r->r_info; + pr[i].r_addend = r->r_addend; + } + + if (scf_vector_add(e->sections, s) < 0) { + free(s->data); + scf_string_free(s->name); + free(s); + return -ENOMEM; + } + return s->index; +} + +int elf_read_shstrtab(scf_elf_context_t* elf) +{ + elf_native_t* e = elf->priv; + + if (!elf->fp) + return -EINVAL; + + int ret = fseek(elf->fp, elf->start, SEEK_SET); + if (ret < 0) + return ret; + + ret = fread(&e->eh, sizeof(Elf64_Ehdr), 1, elf->fp); + if (ret != 1) + return -1; + + if (ELFMAG0 != e->eh.e_ident[EI_MAG0] + || ELFMAG1 != e->eh.e_ident[EI_MAG1] + || ELFMAG2 != e->eh.e_ident[EI_MAG2] + || ELFMAG3 != e->eh.e_ident[EI_MAG3]) { + + scf_loge("not elf file\n"); + return -1; + } + + long offset = e->eh.e_shoff + e->eh.e_shentsize * e->eh.e_shstrndx; + fseek(elf->fp, elf->start + offset, SEEK_SET); + + ret = fread(&e->sh_shstrtab, sizeof(Elf64_Shdr), 1, elf->fp); + if (ret != 1) + return -1; + + if (!e->sh_shstrtab_data) { + e->sh_shstrtab_data = scf_string_alloc(); + if (!e->sh_shstrtab_data) + return -ENOMEM; + } + + void* p = realloc(e->sh_shstrtab_data->data, e->sh_shstrtab.sh_size); + if (!p) + return -ENOMEM; + e->sh_shstrtab_data->data = p; + e->sh_shstrtab_data->len = e->sh_shstrtab.sh_size; + e->sh_shstrtab_data->capacity = e->sh_shstrtab.sh_size; + + fseek(elf->fp, elf->start + e->sh_shstrtab.sh_offset, SEEK_SET); + + ret = fread(e->sh_shstrtab_data->data, e->sh_shstrtab.sh_size, 1, elf->fp); + if (ret != 1) + return -1; +#if 0 + int i; + for (i = 0; i < e->sh_shstrtab.sh_size; i++) { + + unsigned char c = e->sh_shstrtab_data->data[i]; + if (c) + printf("%c", c); + else + printf("\n"); + } + printf("\n"); +#endif + return 0; +} + +static int __elf_read_section_data(scf_elf_context_t* elf, elf_section_t* s) +{ + s->data_len = s->sh.sh_size; + + if (s->sh.sh_size > 0) { + + s->data = malloc(s->sh.sh_size); + if (!s->data) + return -1; + + fseek(elf->fp, elf->start + s->sh.sh_offset, SEEK_SET); + + int ret = fread(s->data, s->data_len, 1, elf->fp); + if (ret != 1) { + free(s->data); + s->data = NULL; + s->data_len = 0; + return -1; + } + } + + return 0; +} + +static int __elf_read_section_by_index(scf_elf_context_t* elf, elf_section_t** psection, const int index) +{ + elf_native_t* e = elf->priv; + + if (!e || !elf->fp) + return -1; + + if (!e->sh_shstrtab_data) { + + int ret = elf_read_shstrtab(elf); + if (ret < 0) + return ret; + } + + if (index >= e->eh.e_shnum) + return -EINVAL; + + elf_section_t* s; + int i; + for (i = 0; i < e->sections->size; i++) { + s = e->sections->data[i]; + + if (index == s->index) { + + if (s->data || __elf_read_section_data(elf, s) == 0) { + *psection = s; + return 0; + } + return -1; + } + } + + s = calloc(1, sizeof(elf_section_t)); + if (!s) + return -ENOMEM; + + long offset = e->eh.e_shoff + e->eh.e_shentsize * index; + fseek(elf->fp, elf->start + offset, SEEK_SET); + + int ret = fread(&s->sh, sizeof(Elf64_Shdr), 1, elf->fp); + if (ret != 1) { + free(s); + return -1; + } + + s->index = index; + s->name = scf_string_cstr(e->sh_shstrtab_data->data + s->sh.sh_name); + if (!s->name) { + free(s); + return -1; + } + + ret = scf_vector_add(e->sections, s); + if (ret < 0) { + scf_string_free(s->name); + free(s); + return -1; + } + + if (__elf_read_section_data(elf, s) == 0) { + *psection = s; + return 0; + } + return -1; +} + +static int __elf_read_section(scf_elf_context_t* elf, elf_section_t** psection, const char* name) +{ + elf_native_t* e = elf->priv; + + if (!e || !elf->fp) + return -1; + + if (!e->sh_shstrtab_data) { + + int ret = elf_read_shstrtab(elf); + if (ret < 0) + return ret; + } + + elf_section_t* s; + int i; + for (i = 0; i < e->sections->size; i++) { + s = e->sections->data[i]; + + if (!scf_string_cmp_cstr(s->name, name)) { + + if (s->data || __elf_read_section_data(elf, s) == 0) { + *psection = s; + return 0; + } + return -1; + } + } + + int j; + for (j = 1; j < e->eh.e_shnum; j++) { + + for (i = 0; i < e->sections->size; i++) { + s = e->sections->data[i]; + + if (j == s->index) + break; + } + + if (i < e->sections->size) + continue; + + s = calloc(1, sizeof(elf_section_t)); + if (!s) + return -ENOMEM; + + long offset = e->eh.e_shoff + e->eh.e_shentsize * j; + fseek(elf->fp, elf->start + offset, SEEK_SET); + + int ret = fread(&s->sh, sizeof(Elf64_Shdr), 1, elf->fp); + if (ret != 1) { + free(s); + return -1; + } + + s->index = j; + s->name = scf_string_cstr(e->sh_shstrtab_data->data + s->sh.sh_name); + if (!s->name) { + free(s); + return -1; + } + + ret = scf_vector_add(e->sections, s); + if (ret < 0) { + scf_string_free(s->name); + free(s); + return -1; + } + + if (!scf_string_cmp_cstr(s->name, name)) + break; + } + + if (j < e->eh.e_shnum) { + + if (!s->data) { + if (__elf_read_section_data(elf, s) == 0) { + *psection = s; + return 0; + } + + return -1; + } else + assert(s->data_len == s->sh.sh_size); + + *psection = s; + return 0; + } + + return -404; +} + +int elf_read_syms(scf_elf_context_t* elf, scf_vector_t* syms, const char* sh_name) +{ + elf_native_t* e = elf->priv; + + if (!e || !elf->fp) + return -1; + + elf_section_t* symtab = NULL; + elf_section_t* strtab = NULL; + + char* sh_strtab_name = NULL; + + if (!strcmp(sh_name, ".symtab")) + sh_strtab_name = ".strtab"; + + else if (!strcmp(sh_name, ".dynsym")) + sh_strtab_name = ".dynstr"; + else + return -EINVAL; + + int ret = __elf_read_section(elf, &symtab, sh_name); + if (ret < 0) { + scf_loge("\n"); + return -1; + } + + ret = __elf_read_section(elf, &strtab, sh_strtab_name); + if (ret < 0) { + scf_loge("\n"); + return -1; + } + + assert(symtab->data_len % sizeof(Elf64_Sym) == 0); + + scf_elf_sym_t* esym; + Elf64_Sym* sym; + int i; + for (i = 0; i < symtab->data_len; i += sizeof(Elf64_Sym)) { + + sym = (Elf64_Sym*)(symtab->data + i); + + assert(sym->st_name < strtab->data_len); + + if (STT_NOTYPE == sym->st_info && 0 == i) + continue; + + esym = calloc(1, sizeof(scf_elf_sym_t)); + if (!esym) + return -ENOMEM; + + esym->name = strtab->data + sym->st_name; + esym->st_size = sym->st_size; + esym->st_value = sym->st_value; + esym->st_shndx = sym->st_shndx; + esym->st_info = sym->st_info; + + if (scf_vector_add(syms, esym) < 0) { + free(esym); + return -ENOMEM; + } + } + + return 0; +} + +int elf_add_dyn_need(scf_elf_context_t* elf, const char* soname) +{ + elf_native_t* e = elf->priv; + + if (!e || !elf->fp) + return -1; + + if (!e->dyn_needs) { + e->dyn_needs = scf_vector_alloc(); + if (!e->dyn_needs) + return -ENOMEM; + } + + scf_string_t* s = scf_string_cstr(soname); + if (!s) + return -ENOMEM; + + if (scf_vector_add(e->dyn_needs, s) < 0) { + scf_string_free(s); + return -ENOMEM; + } + + scf_loge("soname: %s\n", soname); + return 0; +} + +int elf_add_dyn_rela(scf_elf_context_t* elf, const scf_elf_rela_t* rela) +{ + elf_native_t* e = elf->priv; + + if (!e || !elf->fp) + return -1; + + if (!e->dyn_relas) { + e->dyn_relas = scf_vector_alloc(); + if (!e->dyn_relas) + return -ENOMEM; + } + + Elf64_Rela* r = calloc(1, sizeof(Elf64_Rela)); + if (!r) + return -ENOMEM; + + if (scf_vector_add(e->dyn_relas, r) < 0) { + free(r); + return -ENOMEM; + } + + r->r_offset = rela->r_offset; + r->r_addend = rela->r_addend; + r->r_info = rela->r_info; + + return 0; +} + +int elf_read_relas(scf_elf_context_t* elf, scf_vector_t* relas, const char* sh_name) +{ + elf_native_t* e = elf->priv; + + if (!e || !elf->fp) + return -1; + + elf_section_t* sh_rela = NULL; + elf_section_t* symtab = NULL; + elf_section_t* strtab = NULL; + + char* symtab_name = NULL; + char* strtab_name = NULL; + + int ret = __elf_read_section(elf, &sh_rela, sh_name); + if (ret < 0) + return ret; + + scf_loge("sh_rela: %u\n", sh_rela->sh.sh_link); + + ret = __elf_read_section_by_index(elf, &symtab, sh_rela->sh.sh_link); + if (ret < 0) { + scf_loge("\n"); + return ret; + } + + ret = __elf_read_section_by_index(elf, &strtab, symtab->sh.sh_link); + if (ret < 0) { + scf_loge("\n"); + return ret; + } + + assert(sh_rela->data_len % sizeof(Elf64_Rela) == 0); + + scf_elf_rela_t* erela; + Elf64_Rela* rela; + Elf64_Sym* sym; + + int i; + for (i = 0; i < sh_rela->data_len; i += sizeof(Elf64_Rela)) { + + rela = (Elf64_Rela*)(sh_rela->data + i); + + int sym_idx = ELF64_R_SYM(rela->r_info); + + assert(sym_idx < symtab->data_len / sizeof(Elf64_Sym)); + + sym = (Elf64_Sym*)(symtab->data + sym_idx * sizeof(Elf64_Sym)); + + assert(sym->st_name < strtab->data_len); + + erela = calloc(1, sizeof(scf_elf_rela_t)); + if (!erela) + return -ENOMEM; + + erela->name = strtab->data + sym->st_name; + erela->r_offset = rela->r_offset; + erela->r_info = rela->r_info; + erela->r_addend = rela->r_addend; + + if (scf_vector_add(relas, erela) < 0) { + scf_loge("\n"); + free(erela); + return -ENOMEM; + } + } + + return 0; +} + +int elf_read_section(scf_elf_context_t* elf, scf_elf_section_t** psection, const char* name) +{ + elf_section_t* s = NULL; + scf_elf_section_t* s2; + elf_native_t* e = elf->priv; + + if (!e || !elf->fp) + return -1; + + int ret = __elf_read_section(elf, &s, name); + if (ret < 0) + return ret; + + s2 = calloc(1, sizeof(scf_elf_section_t)); + if (!s2) + return -ENOMEM; + + s2->index = s->index; + s2->name = s->name->data; + s2->data = s->data; + s2->data_len = s->data_len; + s2->sh_type = s->sh.sh_type; + s2->sh_flags = s->sh.sh_flags; + s2->sh_addralign = s->sh.sh_addralign; + + *psection = s2; + return 0; +} + +int elf_write_symtab(scf_elf_context_t* elf) +{ + elf_native_t* e = elf->priv; + Elf64_Sym s0 = {0}; + elf_sym_t* s; + + s0.st_info = ELF64_ST_INFO(STB_LOCAL, STT_NOTYPE); + + fwrite(&s0, sizeof(s0), 1, elf->fp); // entry index 0 in symtab is NOTYPE + + int i; + for (i = 0; i < e->symbols->size; i++) { + s = e->symbols->data[i]; + + fwrite(&s->sym, sizeof(s->sym), 1, elf->fp); + } + + return 0; +} + +int elf_write_strtab(scf_elf_context_t* elf) +{ + elf_sym_t* s; + elf_native_t* e = elf->priv; + uint8_t c = 0; + + fwrite(&c, sizeof(c), 1, elf->fp); + + int i; + for (i = 0; i < e->symbols->size; i++) { + s = e->symbols->data[i]; + + if (s->name) + fwrite(s->name->data, s->name->len + 1, 1, elf->fp); + } + + return 0; +} + +int elf_write_shstrtab(scf_elf_context_t* elf) +{ + elf_section_t* s; + elf_native_t* e = elf->priv; + uint8_t c = 0; + char* str = ".symtab\0.strtab\0.shstrtab\0"; + int len = strlen(".symtab") + strlen(".strtab") + strlen(".shstrtab") + 3; + + fwrite(&c, sizeof(c), 1, elf->fp); + + int i; + for (i = 0; i < e->sections->size; i++) { + s = e->sections->data[i]; + + fwrite(s->name->data, s->name->len + 1, 1, elf->fp); + } + + fwrite(str, len, 1, elf->fp); + return 0; +} + +int elf_write_sections(scf_elf_context_t* elf) +{ + elf_section_t* s; + elf_native_t* e = elf->priv; + + int i; + for (i = 0; i < e->sections->size; i++) { + s = e->sections->data[i]; + + scf_loge("sh->name: %s, data: %p, len: %d\n", s->name->data, s->data, s->data_len); + + if (s->data && s->data_len > 0) + fwrite(s->data, s->data_len, 1, elf->fp); + } + + return 0; +} + +int elf_write_rel(scf_elf_context_t* elf, uint16_t e_machine) +{ + elf_native_t* e = elf->priv; + elf_section_t* s; + elf_sym_t* sym; + + int nb_sections = 1 + e->sections->size + 1 + 1 + 1; + uint64_t shstrtab = 1; + uint64_t strtab = 1; + uint64_t symtab = sizeof(Elf64_Sym ) * (e->symbols->size + 1); + Elf64_Off offset = sizeof(Elf64_Ehdr) + sizeof(Elf64_Shdr) * nb_sections; + + // write elf header + elf_header(&e->eh, ET_REL, e_machine, 0, 0, 0, nb_sections, nb_sections - 1); + fwrite (&e->eh, sizeof(e->eh), 1, elf->fp); + + // write null section header + fwrite(&e->sh_null, sizeof(e->sh_null), 1, elf->fp); + + // write user's section header + int i; + for (i = 0; i < e->sections->size; i++) { + s = e->sections->data[i]; + + if (SHT_RELA == s->sh.sh_type) + s->sh.sh_link = nb_sections - 3; + + section_header(&s->sh, shstrtab, 0, offset, + s->data_len, + s->sh.sh_link, + s->sh.sh_info, + s->sh.sh_entsize); + + s->sh.sh_addralign = 8; + + offset += s->data_len; + shstrtab += s->name->len + 1; + + fwrite(&s->sh, sizeof(s->sh), 1, elf->fp); + } + + // set user's symbols' name + int local_syms = 1; + + for (i = 0; i < e->symbols->size; i++) { + sym = e->symbols->data[i]; + + if (sym->name) { + sym->sym.st_name = strtab; + strtab += sym->name->len + 1; + } else + sym->sym.st_name = 0; + + if (STB_LOCAL == ELF64_ST_BIND(sym->sym.st_info)) + local_syms++; + } + + scf_loge("e->symbols->size: %d\n", e->symbols->size); + // .symtab header + section_header(&e->sh_symtab, shstrtab, 0, offset, symtab, nb_sections - 2, local_syms, sizeof(Elf64_Sym)); + + offset += symtab; + shstrtab += strlen(".symtab") + 1; + + // .strtab header + section_header(&e->sh_strtab, shstrtab, 0, offset, strtab, 0, 0, 0); + + offset += strtab; + shstrtab += strlen(".strtab") + 1; + + // .shstrtab header + uint64_t shstrtab_len = shstrtab + strlen(".shstrtab") + 1; + + section_header(&e->sh_shstrtab, shstrtab, 0, offset, shstrtab_len, 0, 0, 0); + + fwrite(&e->sh_symtab, sizeof(e->sh_symtab), 1, elf->fp); + fwrite(&e->sh_strtab, sizeof(e->sh_strtab), 1, elf->fp); + fwrite(&e->sh_shstrtab, sizeof(e->sh_shstrtab), 1, elf->fp); + + elf_write_sections(elf); // write user's section data + + elf_write_symtab (elf); // write .symtab data (user's symbols) + elf_write_strtab (elf); // write .strtab data (symbol names of symtab) + elf_write_shstrtab(elf); // write .shstrtab data (section names of all sections) + return 0; +} + +int elf_sym_cmp(const void* v0, const void* v1) +{ + const elf_sym_t* sym0 = *(const elf_sym_t**)v0; + const elf_sym_t* sym1 = *(const elf_sym_t**)v1; + + if (STB_LOCAL == ELF64_ST_BIND(sym0->sym.st_info)) { + + if (STB_GLOBAL == ELF64_ST_BIND(sym1->sym.st_info)) + return -1; + + } else if (STB_LOCAL == ELF64_ST_BIND(sym1->sym.st_info)) + return 1; + + return 0; +} + +int elf_find_sym(elf_sym_t** psym, Elf64_Rela* rela, scf_vector_t* symbols) +{ + elf_sym_t* sym; + elf_sym_t* sym2; + + int sym_idx = ELF64_R_SYM(rela->r_info); + int j; + + assert(sym_idx >= 1); + assert(sym_idx - 1 < symbols->size); + + sym = symbols->data[sym_idx - 1]; + + if (0 == sym->sym.st_shndx) { + + int n = 0; + + for (j = 0; j < symbols->size; j++) { + sym2 = symbols->data[j]; + + if (0 == sym2->sym.st_shndx) + continue; + + if (STB_LOCAL == ELF64_ST_BIND(sym2->sym.st_info)) + continue; + + if (!strcmp(sym2->name->data, sym->name->data)) { + sym = sym2; + sym_idx = j + 1; + n++; + } + } + + if (0 == n) { + scf_loge("global symbol: %s not found\n", sym->name->data); + return -1; + + } else if (n > 1) { + scf_loge("tow global symbol: %s\n", sym->name->data); + return -1; + } + } else if (ELF64_ST_TYPE(sym->sym.st_info) == STT_SECTION) { + + for (j = symbols->size - 1; j >= 0; j--) { + sym2 = symbols->data[j]; + + if (ELF64_ST_TYPE(sym2->sym.st_info) != STT_SECTION) + continue; + + if (sym2->sym.st_shndx == sym->sym.st_shndx) { + sym = sym2; + sym_idx = j + 1; + break; + } + } + + assert(j >= 0); + } + + *psym = sym; + return sym_idx; +} + +void elf_process_syms(elf_native_t* e, uint32_t cs_index) +{ + elf_section_t* s; + Elf64_Rela* rela; + elf_sym_t* sym; + + int i; + int j; + int k; + int shndx = 20; +#if 1 + for (i = e->symbols->size - 1; i >= 0; i--) { + sym = e->symbols->data[i]; + + if (STT_SECTION == ELF64_ST_TYPE(sym->sym.st_info)) { + if (shndx > cs_index) { + + shndx = sym->sym.st_shndx; + + assert(sym->sym.st_shndx - 1 < e->sections->size); + + sym->section = e->sections->data[sym->sym.st_shndx - 1]; + continue; + } + } else if (0 != sym->sym.st_shndx) { + + if (sym->sym.st_shndx - 1 < e->sections->size) + sym->section = e->sections->data[sym->sym.st_shndx - 1]; + continue; + } + + assert(0 == scf_vector_del(e->symbols, sym)); + + scf_string_free(sym->name); + free(sym); + } +#endif + qsort(e->symbols->data, e->symbols->size, sizeof(void*), elf_sym_cmp); + + for (j = 0; j < e->sections->size; j++) { + s = e->sections->data[j]; + + if (SHT_RELA != s->sh.sh_type) + continue; + + if (!strcmp(s->name->data, ".rela.plt")) + continue; + + assert(s->data_len % sizeof(Elf64_Rela) == 0); + + int sym_idx; + for (k = 0; k < s->data_len; k += sizeof(Elf64_Rela)) { + + rela = (Elf64_Rela*)(s->data + k); + + sym_idx = ELF64_R_SYM(rela->r_info); + + for (i = 0; i < e->symbols->size; i++) { + sym = e->symbols->data[i]; + + if (sym_idx == sym->index) + break; + } + + assert(i < e->symbols->size); + + rela->r_info = ELF64_R_INFO(i + 1, ELF64_R_TYPE(rela->r_info)); + } + } +} + diff --git a/elf/scf_elf_native.h b/elf/scf_elf_native.h new file mode 100644 index 0000000..08916c3 --- /dev/null +++ b/elf/scf_elf_native.h @@ -0,0 +1,152 @@ +#ifndef SCF_ELF_NATIVE_H +#define SCF_ELF_NATIVE_H + +#include"scf_elf.h" +#include"scf_vector.h" +#include"scf_string.h" + +typedef struct elf_section_s elf_section_t; + +struct elf_section_s +{ + elf_section_t* link; + elf_section_t* info; + + scf_string_t* name; + + Elf64_Shdr sh; + + uint64_t offset; + + uint16_t index; + uint8_t* data; + int data_len; +}; + +typedef struct { + elf_section_t* section; + + scf_string_t* name; + + Elf64_Sym sym; + + int index; + uint8_t dyn_flag:1; + +} elf_sym_t; + +typedef struct { + Elf64_Ehdr eh; + + Elf64_Shdr sh_null; + + scf_vector_t* sections; + + Elf64_Shdr sh_symtab; + scf_vector_t* symbols; + + Elf64_Shdr sh_strtab; + + Elf64_Shdr sh_shstrtab; + scf_string_t* sh_shstrtab_data; + + scf_vector_t* dynsyms; + scf_vector_t* dyn_needs; + scf_vector_t* dyn_relas; + + elf_section_t* interp; + elf_section_t* dynsym; + elf_section_t* dynstr; + elf_section_t* gnu_version; + elf_section_t* gnu_version_r; + elf_section_t* rela_plt; + elf_section_t* plt; + elf_section_t* dynamic; + elf_section_t* got_plt; + +} elf_native_t; + + +int elf_open (scf_elf_context_t* elf); +int elf_close(scf_elf_context_t* elf); + +int elf_add_sym (scf_elf_context_t* elf, const scf_elf_sym_t* sym, const char* sh_name); + +int elf_add_section (scf_elf_context_t* elf, const scf_elf_section_t* section); + +int elf_add_rela_section(scf_elf_context_t* elf, const scf_elf_section_t* section, scf_vector_t* relas); + +int elf_read_shstrtab(scf_elf_context_t* elf); +int elf_read_section (scf_elf_context_t* elf, scf_elf_section_t** psection, const char* name); + +int elf_add_dyn_need(scf_elf_context_t* elf, const char* soname); +int elf_add_dyn_rela(scf_elf_context_t* elf, const scf_elf_rela_t* rela); + +int elf_read_relas (scf_elf_context_t* elf, scf_vector_t* relas, const char* sh_name); +int elf_read_syms (scf_elf_context_t* elf, scf_vector_t* syms, const char* sh_name); + +int elf_find_sym (elf_sym_t** psym, Elf64_Rela* rela, scf_vector_t* symbols); +void elf_process_syms(elf_native_t* native, uint32_t cs_index); + +int elf_write_sections(scf_elf_context_t* elf); +int elf_write_shstrtab(scf_elf_context_t* elf); +int elf_write_symtab (scf_elf_context_t* elf); +int elf_write_strtab (scf_elf_context_t* elf); +int elf_write_rel (scf_elf_context_t* elf, uint16_t e_machine); + +int elf_sym_cmp(const void* v0, const void* v1); + +static inline void elf_header(Elf64_Ehdr* eh, + uint16_t e_type, + uint16_t e_machine, + Elf64_Addr e_entry, + Elf64_Off e_phoff, + uint16_t e_phnum, + uint16_t e_shnum, + uint16_t e_shstrndx) +{ + eh->e_ident[EI_MAG0] = ELFMAG0; + eh->e_ident[EI_MAG1] = ELFMAG1; + eh->e_ident[EI_MAG2] = ELFMAG2; + eh->e_ident[EI_MAG3] = ELFMAG3; + eh->e_ident[EI_CLASS] = ELFCLASS64; + eh->e_ident[EI_DATA] = ELFDATA2LSB; + eh->e_ident[EI_VERSION] = EV_CURRENT; + eh->e_ident[EI_OSABI] = ELFOSABI_SYSV; + + eh->e_type = e_type; + eh->e_machine = e_machine; + eh->e_version = EV_CURRENT; + eh->e_entry = e_entry; + eh->e_ehsize = sizeof(Elf64_Ehdr); + + eh->e_phoff = e_phoff; + eh->e_phentsize = sizeof(Elf64_Phdr); + eh->e_phnum = e_phnum; + + eh->e_shoff = sizeof(Elf64_Ehdr); + eh->e_shentsize = sizeof(Elf64_Shdr); + eh->e_shnum = e_shnum; + eh->e_shstrndx = e_shstrndx; +} + +static inline void section_header(Elf64_Shdr* sh, + uint32_t sh_name, + Elf64_Addr sh_addr, + Elf64_Off sh_offset, + uint64_t sh_size, + uint32_t sh_link, + uint32_t sh_info, + uint64_t sh_entsize) +{ + sh->sh_name = sh_name; + sh->sh_addr = sh_addr; + sh->sh_offset = sh_offset; + sh->sh_size = sh_size; + sh->sh_link = sh_link; + sh->sh_info = sh_info; + sh->sh_entsize = sh_entsize; +} + +#endif + diff --git a/elf/scf_elf_x64.c b/elf/scf_elf_x64.c index 195e8e7..eec6161 100644 --- a/elf/scf_elf_x64.c +++ b/elf/scf_elf_x64.c @@ -1,937 +1,14 @@ #include"scf_elf_x64.h" #include"scf_elf_link.h" -static int _x64_elf_open(scf_elf_context_t* elf) -{ - if (!elf) - return -EINVAL; - - scf_elf_x64_t* x64 = calloc(1, sizeof(scf_elf_x64_t)); - if (!x64) - return -ENOMEM; - - x64->sh_null.sh_type = SHT_NULL; - - x64->sh_symtab.sh_type = SHT_SYMTAB; - x64->sh_symtab.sh_flags = 0; - x64->sh_symtab.sh_addralign = 8; - - x64->sh_strtab.sh_type = SHT_STRTAB; - x64->sh_strtab.sh_flags = 0; - x64->sh_strtab.sh_addralign = 1; - - x64->sh_shstrtab.sh_type = SHT_STRTAB; - x64->sh_shstrtab.sh_flags = 0; - x64->sh_shstrtab.sh_addralign = 1; - - x64->sections = scf_vector_alloc(); - x64->symbols = scf_vector_alloc(); - - elf->priv = x64; - return 0; -} - -static int _x64_elf_close(scf_elf_context_t* elf) -{ - scf_elf_x64_t* x64 = elf->priv; - - if (x64) { - free(x64); - x64 = NULL; - } - return 0; -} - -static int _x64_elf_add_sym(scf_elf_context_t* elf, const scf_elf_sym_t* sym, const char* sh_name) -{ - scf_elf_x64_sym_t* xsym; - scf_elf_x64_t* x64 = elf->priv; - scf_vector_t* vec = NULL; - - if (!strcmp(sh_name, ".symtab")) - vec = x64->symbols; - - else if (!strcmp(sh_name, ".dynsym")) { - - if (!x64->dynsyms) { - x64->dynsyms = scf_vector_alloc(); - if (!x64->dynsyms) - return -ENOMEM; - } - - vec = x64->dynsyms; - } else - return -EINVAL; - - xsym = calloc(1, sizeof(scf_elf_x64_sym_t)); - if (!xsym) - return -ENOMEM; - - if (sym->name) - xsym->name = scf_string_cstr(sym->name); - else - xsym->name = NULL; - - xsym->sym.st_size = sym->st_size; - xsym->sym.st_value = sym->st_value; - xsym->sym.st_shndx = sym->st_shndx; - xsym->sym.st_info = sym->st_info; - - xsym->dyn_flag = sym->dyn_flag; - - int ret = scf_vector_add(vec, xsym); - if (ret < 0) { - scf_string_free(xsym->name); - free(xsym); - return ret; - } - - xsym->index = vec->size; - return 0; -} - -static int _x64_elf_add_section(scf_elf_context_t* elf, const scf_elf_section_t* section) -{ - scf_elf_x64_t* x64 = elf->priv; - - scf_elf_x64_section_t* s; - scf_elf_x64_section_t* s2; - int i; - - if (section->index > 0) { - - for (i = x64->sections->size - 1; i >= 0; i--) { - s = x64->sections->data[i]; - - if (s->index == section->index) { - scf_loge("s->index: %d\n", s->index); - return -1; - } - } - } - - s = calloc(1, sizeof(scf_elf_x64_section_t)); - if (!s) - return -ENOMEM; - - s->name = scf_string_cstr(section->name); - if (!s->name) { - free(s); - return -ENOMEM; - } - - s->sh.sh_type = section->sh_type; - s->sh.sh_flags = section->sh_flags; - s->sh.sh_addralign = section->sh_addralign; - - if (section->data && section->data_len > 0) { - s->data = malloc(section->data_len); - if (!s->data) { - scf_string_free(s->name); - free(s); - return -ENOMEM; - } - - memcpy(s->data, section->data, section->data_len); - s->data_len = section->data_len; - } - - if (scf_vector_add(x64->sections, s) < 0) { - if (s->data) - free(s->data); - scf_string_free(s->name); - free(s); - return -ENOMEM; - } - - if (0 == section->index) - s->index = x64->sections->size; - else { - s->index = section->index; - - for (i = x64->sections->size - 2; i >= 0; i--) { - s2 = x64->sections->data[i]; - - if (s2->index < s->index) - break; - - x64->sections->data[i + 1] = s2; - } - - x64->sections->data[i + 1] = s; - } - - return s->index; -} - -static int _x64_elf_add_rela_section(scf_elf_context_t* elf, const scf_elf_section_t* section, scf_vector_t* relas) -{ - if (relas->size <= 0) { - scf_loge("\n"); - return -EINVAL; - } - - scf_elf_x64_t* x64 = elf->priv; - - scf_elf_x64_section_t* s = calloc(1, sizeof(scf_elf_x64_section_t)); - if (!s) - return -ENOMEM; - - s->name = scf_string_cstr(section->name); - if (!s->name) { - free(s); - return -ENOMEM; - } - - s->index = x64->sections->size + 1; - s->sh.sh_type = SHT_RELA; - s->sh.sh_flags = SHF_INFO_LINK; - s->sh.sh_addralign = section->sh_addralign; - s->sh.sh_link = section->sh_link; - s->sh.sh_info = section->sh_info; - s->sh.sh_entsize = sizeof(Elf64_Rela); - - s->data_len = sizeof(Elf64_Rela) * relas->size; - - s->data = malloc(s->data_len); - if (!s->data) { - scf_string_free(s->name); - free(s); - return -ENOMEM; - } - - Elf64_Rela* pr = (Elf64_Rela*) s->data; - - int i; - for (i = 0; i < relas->size; i++) { - - scf_elf_rela_t* r = relas->data[i]; - - - pr[i].r_offset = r->r_offset; - pr[i].r_info = r->r_info; - pr[i].r_addend = r->r_addend; - } - - if (scf_vector_add(x64->sections, s) < 0) { - free(s->data); - scf_string_free(s->name); - free(s); - return -ENOMEM; - } - return s->index; -} - -static int _x64_elf_read_shstrtab(scf_elf_context_t* elf) -{ - scf_elf_x64_t* x64 = elf->priv; - - if (!elf->fp) - return -EINVAL; - - int ret = fseek(elf->fp, elf->start, SEEK_SET); - if (ret < 0) - return ret; - - ret = fread(&x64->eh, sizeof(Elf64_Ehdr), 1, elf->fp); - if (ret != 1) - return -1; - - if (ELFMAG0 != x64->eh.e_ident[EI_MAG0] - || ELFMAG1 != x64->eh.e_ident[EI_MAG1] - || ELFMAG2 != x64->eh.e_ident[EI_MAG2] - || ELFMAG3 != x64->eh.e_ident[EI_MAG3]) { - - scf_loge("not elf file\n"); - return -1; - } - - long offset = x64->eh.e_shoff + x64->eh.e_shentsize * x64->eh.e_shstrndx; - fseek(elf->fp, elf->start + offset, SEEK_SET); - - ret = fread(&x64->sh_shstrtab, sizeof(Elf64_Shdr), 1, elf->fp); - if (ret != 1) - return -1; - - if (!x64->sh_shstrtab_data) { - x64->sh_shstrtab_data = scf_string_alloc(); - if (!x64->sh_shstrtab_data) - return -ENOMEM; - } - - void* p = realloc(x64->sh_shstrtab_data->data, x64->sh_shstrtab.sh_size); - if (!p) - return -ENOMEM; - x64->sh_shstrtab_data->data = p; - x64->sh_shstrtab_data->len = x64->sh_shstrtab.sh_size; - x64->sh_shstrtab_data->capacity = x64->sh_shstrtab.sh_size; - - fseek(elf->fp, elf->start + x64->sh_shstrtab.sh_offset, SEEK_SET); - - ret = fread(x64->sh_shstrtab_data->data, x64->sh_shstrtab.sh_size, 1, elf->fp); - if (ret != 1) - return -1; -#if 0 - int i; - for (i = 0; i < x64->sh_shstrtab.sh_size; i++) { - - unsigned char c = x64->sh_shstrtab_data->data[i]; - if (c) - printf("%c", c); - else - printf("\n"); - } - printf("\n"); -#endif - return 0; -} - -static int __x64_elf_read_section_data(scf_elf_context_t* elf, scf_elf_x64_section_t* s) -{ - s->data_len = s->sh.sh_size; - - if (s->sh.sh_size > 0) { - - s->data = malloc(s->sh.sh_size); - if (!s->data) - return -1; - - fseek(elf->fp, elf->start + s->sh.sh_offset, SEEK_SET); - - int ret = fread(s->data, s->data_len, 1, elf->fp); - if (ret != 1) { - free(s->data); - s->data = NULL; - s->data_len = 0; - return -1; - } - } - - return 0; -} - -static int __x64_elf_read_section_by_index(scf_elf_context_t* elf, scf_elf_x64_section_t** psection, const int index) -{ - scf_elf_x64_t* x64 = elf->priv; - - if (!x64 || !elf->fp) - return -1; - - if (!x64->sh_shstrtab_data) { - - int ret = _x64_elf_read_shstrtab(elf); - if (ret < 0) - return ret; - } - - if (index >= x64->eh.e_shnum) - return -EINVAL; - - scf_elf_x64_section_t* s; - int i; - for (i = 0; i < x64->sections->size; i++) { - s = x64->sections->data[i]; - - if (index == s->index) { - - if (s->data || __x64_elf_read_section_data(elf, s) == 0) { - *psection = s; - return 0; - } - return -1; - } - } - - s = calloc(1, sizeof(scf_elf_x64_section_t)); - if (!s) - return -ENOMEM; - - long offset = x64->eh.e_shoff + x64->eh.e_shentsize * index; - fseek(elf->fp, elf->start + offset, SEEK_SET); - - int ret = fread(&s->sh, sizeof(Elf64_Shdr), 1, elf->fp); - if (ret != 1) { - free(s); - return -1; - } - - s->index = index; - s->name = scf_string_cstr(x64->sh_shstrtab_data->data + s->sh.sh_name); - if (!s->name) { - free(s); - return -1; - } - - ret = scf_vector_add(x64->sections, s); - if (ret < 0) { - scf_string_free(s->name); - free(s); - return -1; - } - - if (__x64_elf_read_section_data(elf, s) == 0) { - *psection = s; - return 0; - } - return -1; -} - -static int __x64_elf_read_section(scf_elf_context_t* elf, scf_elf_x64_section_t** psection, const char* name) -{ - scf_elf_x64_t* x64 = elf->priv; - - if (!x64 || !elf->fp) - return -1; - - if (!x64->sh_shstrtab_data) { - - int ret = _x64_elf_read_shstrtab(elf); - if (ret < 0) - return ret; - } - - scf_elf_x64_section_t* s; - int i; - for (i = 0; i < x64->sections->size; i++) { - s = x64->sections->data[i]; - - if (!scf_string_cmp_cstr(s->name, name)) { - - if (s->data || __x64_elf_read_section_data(elf, s) == 0) { - *psection = s; - return 0; - } - return -1; - } - } - - int j; - for (j = 1; j < x64->eh.e_shnum; j++) { - - for (i = 0; i < x64->sections->size; i++) { - s = x64->sections->data[i]; - - if (j == s->index) - break; - } - - if (i < x64->sections->size) - continue; - - s = calloc(1, sizeof(scf_elf_x64_section_t)); - if (!s) - return -ENOMEM; - - long offset = x64->eh.e_shoff + x64->eh.e_shentsize * j; - fseek(elf->fp, elf->start + offset, SEEK_SET); - - int ret = fread(&s->sh, sizeof(Elf64_Shdr), 1, elf->fp); - if (ret != 1) { - free(s); - return -1; - } - - s->index = j; - s->name = scf_string_cstr(x64->sh_shstrtab_data->data + s->sh.sh_name); - if (!s->name) { - free(s); - return -1; - } - - ret = scf_vector_add(x64->sections, s); - if (ret < 0) { - scf_string_free(s->name); - free(s); - return -1; - } - - if (!scf_string_cmp_cstr(s->name, name)) - break; - } - - if (j < x64->eh.e_shnum) { - - if (!s->data) { - if (__x64_elf_read_section_data(elf, s) == 0) { - *psection = s; - return 0; - } - - return -1; - } else - assert(s->data_len == s->sh.sh_size); - - *psection = s; - return 0; - } - - return -404; -} - -static int _x64_elf_read_syms(scf_elf_context_t* elf, scf_vector_t* syms, const char* sh_name) -{ - scf_elf_x64_t* x64 = elf->priv; - - if (!x64 || !elf->fp) - return -1; - - scf_elf_x64_section_t* symtab = NULL; - scf_elf_x64_section_t* strtab = NULL; - - char* sh_strtab_name = NULL; - - if (!strcmp(sh_name, ".symtab")) - sh_strtab_name = ".strtab"; - - else if (!strcmp(sh_name, ".dynsym")) - sh_strtab_name = ".dynstr"; - else - return -EINVAL; - - int ret = __x64_elf_read_section(elf, &symtab, sh_name); - if (ret < 0) { - scf_loge("\n"); - return -1; - } - - ret = __x64_elf_read_section(elf, &strtab, sh_strtab_name); - if (ret < 0) { - scf_loge("\n"); - return -1; - } - - assert(symtab->data_len % sizeof(Elf64_Sym) == 0); - - scf_elf_sym_t* esym; - Elf64_Sym* sym; - int i; - for (i = 0; i < symtab->data_len; i += sizeof(Elf64_Sym)) { - - sym = (Elf64_Sym*)(symtab->data + i); - - assert(sym->st_name < strtab->data_len); - - if (STT_NOTYPE == sym->st_info) - continue; - - esym = calloc(1, sizeof(scf_elf_sym_t)); - if (!esym) - return -ENOMEM; - - esym->name = strtab->data + sym->st_name; - esym->st_size = sym->st_size; - esym->st_value = sym->st_value; - esym->st_shndx = sym->st_shndx; - esym->st_info = sym->st_info; - - if (scf_vector_add(syms, esym) < 0) { - free(esym); - return -ENOMEM; - } - } - - return 0; -} - -static int _x64_elf_add_dyn_need(scf_elf_context_t* elf, const char* soname) -{ - scf_elf_x64_t* x64 = elf->priv; - - if (!x64 || !elf->fp) - return -1; - - if (!x64->dyn_needs) { - x64->dyn_needs = scf_vector_alloc(); - if (!x64->dyn_needs) - return -ENOMEM; - } - - scf_string_t* s = scf_string_cstr(soname); - if (!s) - return -ENOMEM; - - if (scf_vector_add(x64->dyn_needs, s) < 0) { - scf_string_free(s); - return -ENOMEM; - } - - scf_loge("soname: %s\n", soname); - return 0; -} - -static int _x64_elf_add_dyn_rela(scf_elf_context_t* elf, const scf_elf_rela_t* rela) -{ - scf_elf_x64_t* x64 = elf->priv; - - if (!x64 || !elf->fp) - return -1; - - if (!x64->dyn_relas) { - x64->dyn_relas = scf_vector_alloc(); - if (!x64->dyn_relas) - return -ENOMEM; - } - - Elf64_Rela* r = calloc(1, sizeof(Elf64_Rela)); - if (!r) - return -ENOMEM; - - if (scf_vector_add(x64->dyn_relas, r) < 0) { - free(r); - return -ENOMEM; - } - - r->r_offset = rela->r_offset; - r->r_addend = rela->r_addend; - r->r_info = rela->r_info; - - return 0; -} - -static int _x64_elf_read_relas(scf_elf_context_t* elf, scf_vector_t* relas, const char* sh_name) -{ - scf_elf_x64_t* x64 = elf->priv; - - if (!x64 || !elf->fp) - return -1; - - scf_elf_x64_section_t* sh_rela = NULL; - scf_elf_x64_section_t* symtab = NULL; - scf_elf_x64_section_t* strtab = NULL; - - char* symtab_name = NULL; - char* strtab_name = NULL; - - int ret = __x64_elf_read_section(elf, &sh_rela, sh_name); - if (ret < 0) - return ret; - - scf_loge("sh_rela: %u\n", sh_rela->sh.sh_link); - - ret = __x64_elf_read_section_by_index(elf, &symtab, sh_rela->sh.sh_link); - if (ret < 0) { - scf_loge("\n"); - return ret; - } - - ret = __x64_elf_read_section_by_index(elf, &strtab, symtab->sh.sh_link); - if (ret < 0) { - scf_loge("\n"); - return ret; - } - - assert(sh_rela->data_len % sizeof(Elf64_Rela) == 0); - - scf_elf_rela_t* erela; - Elf64_Rela* rela; - Elf64_Sym* sym; - - int i; - for (i = 0; i < sh_rela->data_len; i += sizeof(Elf64_Rela)) { - - rela = (Elf64_Rela*)(sh_rela->data + i); - - int sym_idx = ELF64_R_SYM(rela->r_info); - - assert(sym_idx < symtab->data_len / sizeof(Elf64_Sym)); - - sym = (Elf64_Sym*)(symtab->data + sym_idx * sizeof(Elf64_Sym)); - - assert(sym->st_name < strtab->data_len); - - erela = calloc(1, sizeof(scf_elf_rela_t)); - if (!erela) - return -ENOMEM; - - erela->name = strtab->data + sym->st_name; - erela->r_offset = rela->r_offset; - erela->r_info = rela->r_info; - erela->r_addend = rela->r_addend; - - if (scf_vector_add(relas, erela) < 0) { - scf_loge("\n"); - free(erela); - return -ENOMEM; - } - } - - return 0; -} - -static int _x64_elf_read_section(scf_elf_context_t* elf, scf_elf_section_t** psection, const char* name) -{ - scf_elf_x64_section_t* s = NULL; - scf_elf_section_t* s2; - scf_elf_x64_t* x64 = elf->priv; - - if (!x64 || !elf->fp) - return -1; - - int ret = __x64_elf_read_section(elf, &s, name); - if (ret < 0) - return ret; - - s2 = calloc(1, sizeof(scf_elf_section_t)); - if (!s2) - return -ENOMEM; - - s2->index = s->index; - s2->name = s->name->data; - s2->data = s->data; - s2->data_len = s->data_len; - s2->sh_type = s->sh.sh_type; - s2->sh_flags = s->sh.sh_flags; - s2->sh_addralign = s->sh.sh_addralign; - - *psection = s2; - return 0; -} - -static void _x64_elf_header_fill(Elf64_Ehdr* eh, uint16_t e_type, Elf64_Addr e_entry, - Elf64_Off e_phoff, uint16_t e_phnum, uint16_t e_shnum, uint16_t e_shstrndx) -{ - eh->e_ident[EI_MAG0] = ELFMAG0; - eh->e_ident[EI_MAG1] = ELFMAG1; - eh->e_ident[EI_MAG2] = ELFMAG2; - eh->e_ident[EI_MAG3] = ELFMAG3; - eh->e_ident[EI_CLASS] = ELFCLASS64; - eh->e_ident[EI_DATA] = ELFDATA2LSB; - eh->e_ident[EI_VERSION] = EV_CURRENT; - eh->e_ident[EI_OSABI] = ELFOSABI_SYSV; - - eh->e_type = e_type; - eh->e_machine = EM_X86_64; - eh->e_version = EV_CURRENT; - eh->e_entry = e_entry; - eh->e_ehsize = sizeof(Elf64_Ehdr); - - eh->e_phoff = e_phoff; - eh->e_phentsize = sizeof(Elf64_Phdr); - eh->e_phnum = e_phnum; - - eh->e_shoff = sizeof(Elf64_Ehdr); - eh->e_shentsize = sizeof(Elf64_Shdr); - eh->e_shnum = e_shnum; - eh->e_shstrndx = e_shstrndx; -} - -static void _x64_elf_section_header_fill(Elf64_Shdr* sh, - uint32_t sh_name, - Elf64_Addr sh_addr, - Elf64_Off sh_offset, - uint64_t sh_size, - uint32_t sh_link, - uint32_t sh_info, - uint64_t sh_entsize) -{ - sh->sh_name = sh_name; - sh->sh_addr = sh_addr; - sh->sh_offset = sh_offset; - sh->sh_size = sh_size; - sh->sh_link = sh_link; - sh->sh_info = sh_info; - sh->sh_entsize = sh_entsize; -} - static int _x64_elf_write_rel(scf_elf_context_t* elf) { - scf_elf_x64_t* x64 = elf->priv; - - int nb_sections = 1 + x64->sections->size + 1 + 1 + 1; - uint64_t shstrtab_offset = 1; - uint64_t strtab_offset = 1; - Elf64_Off section_offset = sizeof(x64->eh) + sizeof(Elf64_Shdr) * nb_sections; - - // write elf header - _x64_elf_header_fill(&x64->eh, ET_REL, 0, 0, 0, nb_sections, nb_sections - 1); - fwrite(&x64->eh, sizeof(x64->eh), 1, elf->fp); - - // write null section header - fwrite(&x64->sh_null, sizeof(x64->sh_null), 1, elf->fp); - - // write user's section header - int i; - for (i = 0; i < x64->sections->size; i++) { - scf_elf_x64_section_t* s = x64->sections->data[i]; - - if (SHT_RELA == s->sh.sh_type) - s->sh.sh_link = nb_sections - 3; - - _x64_elf_section_header_fill(&s->sh, shstrtab_offset, 0, - section_offset, s->data_len, - s->sh.sh_link, s->sh.sh_info, s->sh.sh_entsize); - s->sh.sh_addralign = 8; - - section_offset += s->data_len; - shstrtab_offset += s->name->len + 1; - - fwrite(&s->sh, sizeof(s->sh), 1, elf->fp); - } - - // set user's symbols' name - int nb_local_syms = 1; - - for (i = 0; i < x64->symbols->size; i++) { - scf_elf_x64_sym_t* sym = x64->symbols->data[i]; - - if (sym->name) { - sym->sym.st_name = strtab_offset; - strtab_offset += sym->name->len + 1; - } else - sym->sym.st_name = 0; - - if (STB_LOCAL == ELF64_ST_BIND(sym->sym.st_info)) - nb_local_syms++; - } - - scf_loge("x64->symbols->size: %d\n", x64->symbols->size); - // write symtab section header - _x64_elf_section_header_fill(&x64->sh_symtab, shstrtab_offset, 0, - section_offset, (x64->symbols->size + 1) * sizeof(Elf64_Sym), - nb_sections - 2, nb_local_syms, sizeof(Elf64_Sym)); - fwrite(&x64->sh_symtab, sizeof(x64->sh_symtab), 1, elf->fp); - section_offset += (x64->symbols->size + 1) * sizeof(Elf64_Sym); - shstrtab_offset += strlen(".symtab") + 1; - - // write strtab section header - _x64_elf_section_header_fill(&x64->sh_strtab, shstrtab_offset, 0, - section_offset, strtab_offset, - 0, 0, 0); - fwrite(&x64->sh_strtab, sizeof(x64->sh_strtab), 1, elf->fp); - section_offset += strtab_offset; - shstrtab_offset += strlen(".strtab") + 1; - - // write shstrtab section header - uint64_t shstrtab_len = shstrtab_offset + strlen(".shstrtab") + 1; - _x64_elf_section_header_fill(&x64->sh_shstrtab, shstrtab_offset, 0, - section_offset, shstrtab_len, 0, 0, 0); - fwrite(&x64->sh_shstrtab, sizeof(x64->sh_shstrtab), 1, elf->fp); - - // write user's section data - for (i = 0; i < x64->sections->size; i++) { - scf_elf_x64_section_t* s = x64->sections->data[i]; - - scf_loge("sh->name: %s, data: %p, len: %d\n", s->name->data, s->data, s->data_len); - - if (s->data && s->data_len > 0) - fwrite(s->data, s->data_len, 1, elf->fp); - } - - // write user's symbols data (symtab section) - // entry index 0 in symtab is NOTYPE - Elf64_Sym sym0 = {0}; - sym0.st_info = ELF64_ST_INFO(STB_LOCAL, STT_NOTYPE); - fwrite(&sym0, sizeof(sym0), 1, elf->fp); - - for (i = 0; i < x64->symbols->size; i++) { - scf_elf_x64_sym_t* sym = x64->symbols->data[i]; - - fwrite(&sym->sym, sizeof(sym->sym), 1, elf->fp); - } - - // write strtab data (strtab section, symbol names of symtab) - uint8_t c = 0; - fwrite(&c, sizeof(c), 1, elf->fp); - for (i = 0; i < x64->symbols->size; i++) { - scf_elf_x64_sym_t* sym = x64->symbols->data[i]; - - if (sym->name) - fwrite(sym->name->data, sym->name->len + 1, 1, elf->fp); - } - - // write shstrtab data (shstrtab section, section names of all sections) - fwrite(&c, sizeof(c), 1, elf->fp); - for (i = 0; i < x64->sections->size; i++) { - scf_elf_x64_section_t* s = x64->sections->data[i]; - - fwrite(s->name->data, s->name->len + 1, 1, elf->fp); - } - - char* str = ".symtab\0.strtab\0.shstrtab\0"; - int str_len = strlen(".symtab") + strlen(".strtab") + strlen(".shstrtab") + 3; - fwrite(str, str_len, 1, elf->fp); - return 0; -} - -static int _sym_cmp(const void* v0, const void* v1) -{ - const scf_elf_x64_sym_t* sym0 = *(const scf_elf_x64_sym_t**)v0; - const scf_elf_x64_sym_t* sym1 = *(const scf_elf_x64_sym_t**)v1; - - if (STB_LOCAL == ELF64_ST_BIND(sym0->sym.st_info)) { - if (STB_GLOBAL == ELF64_ST_BIND(sym1->sym.st_info)) - return -1; - } else if (STB_LOCAL == ELF64_ST_BIND(sym1->sym.st_info)) - return 1; - return 0; + return elf_write_rel(elf, EM_X86_64); } -static int _x64_elf_find_sym(scf_elf_x64_sym_t** psym, Elf64_Rela* rela, scf_vector_t* symbols) +static int _x64_elf_link_cs(elf_native_t* x64, elf_section_t* s, elf_section_t* rs, uint64_t cs_base) { - scf_elf_x64_sym_t* sym; - scf_elf_x64_sym_t* sym2; - - int sym_idx = ELF64_R_SYM(rela->r_info); - int j; - - assert(sym_idx >= 1); - assert(sym_idx - 1 < symbols->size); - - sym = symbols->data[sym_idx - 1]; - - if (0 == sym->sym.st_shndx) { - - int n = 0; - - for (j = 0; j < symbols->size; j++) { - sym2 = symbols->data[j]; - - if (0 == sym2->sym.st_shndx) - continue; - - if (STB_LOCAL == ELF64_ST_BIND(sym2->sym.st_info)) - continue; - - if (!strcmp(sym2->name->data, sym->name->data)) { - sym = sym2; - sym_idx = j + 1; - n++; - } - } - - if (0 == n) { - scf_loge("global symbol: %s not found\n", sym->name->data); - return -1; - - } else if (n > 1) { - scf_loge("tow global symbol: %s\n", sym->name->data); - return -1; - } - } else if (ELF64_ST_TYPE(sym->sym.st_info) == STT_SECTION) { - - for (j = symbols->size - 1; j >= 0; j--) { - sym2 = symbols->data[j]; - - if (ELF64_ST_TYPE(sym2->sym.st_info) != STT_SECTION) - continue; - - if (sym2->sym.st_shndx == sym->sym.st_shndx) { - sym = sym2; - sym_idx = j + 1; - break; - } - } - - assert(j >= 0); - } - - *psym = sym; - return sym_idx; -} - -static int _x64_elf_link_cs(scf_elf_x64_t* x64, scf_elf_x64_section_t* s, scf_elf_x64_section_t* rs, uint64_t cs_base) -{ - scf_elf_x64_sym_t* sym; + elf_sym_t* sym; Elf64_Rela* rela; assert(rs->data_len % sizeof(Elf64_Rela) == 0); @@ -953,7 +30,7 @@ static int _x64_elf_link_cs(scf_elf_x64_t* x64, scf_elf_x64_section_t* s, scf_el continue; } - int j = _x64_elf_find_sym(&sym, rela, x64->symbols); + int j = elf_find_sym(&sym, rela, x64->symbols); if (j < 0) return -1; @@ -969,9 +46,9 @@ static int _x64_elf_link_cs(scf_elf_x64_t* x64, scf_elf_x64_section_t* s, scf_el return 0; } -static int _x64_elf_link_ds(scf_elf_x64_t* x64, scf_elf_x64_section_t* s, scf_elf_x64_section_t* rs) +static int _x64_elf_link_ds(elf_native_t* x64, elf_section_t* s, elf_section_t* rs) { - scf_elf_x64_sym_t* sym; + elf_sym_t* sym; Elf64_Rela* rela; assert(rs->data_len % sizeof(Elf64_Rela) == 0); @@ -982,7 +59,7 @@ static int _x64_elf_link_ds(scf_elf_x64_t* x64, scf_elf_x64_section_t* s, scf_el rela = (Elf64_Rela* )(rs->data + i); sym = NULL; - int j = _x64_elf_find_sym(&sym, rela, x64->symbols); + int j = elf_find_sym(&sym, rela, x64->symbols); if (j < 0) return -1; @@ -1011,10 +88,10 @@ static int _x64_elf_link_ds(scf_elf_x64_t* x64, scf_elf_x64_section_t* s, scf_el return 0; } -static int _x64_elf_link_debug(scf_elf_x64_t* x64, scf_elf_x64_section_t* s, scf_elf_x64_section_t* rs) +static int _x64_elf_link_debug(elf_native_t* x64, elf_section_t* s, elf_section_t* rs) { - scf_elf_x64_sym_t* sym; - scf_elf_x64_sym_t* sym2; + elf_sym_t* sym; + elf_sym_t* sym2; Elf64_Rela* rela; assert(rs->data_len % sizeof(Elf64_Rela) == 0); @@ -1025,7 +102,7 @@ static int _x64_elf_link_debug(scf_elf_x64_t* x64, scf_elf_x64_section_t* s, scf rela = (Elf64_Rela* )(rs->data + i); sym = NULL; - int j = _x64_elf_find_sym(&sym, rela, x64->symbols); + int j = elf_find_sym(&sym, rela, x64->symbols); if (j < 0) return -1; @@ -1070,10 +147,10 @@ static int _x64_elf_link_debug(scf_elf_x64_t* x64, scf_elf_x64_section_t* s, scf return 0; } -static int _x64_elf_link_sections(scf_elf_x64_t* x64, uint32_t cs_index, uint32_t ds_index) +static int _x64_elf_link_sections(elf_native_t* x64, uint32_t cs_index, uint32_t ds_index) { - scf_elf_x64_section_t* s; - scf_elf_x64_section_t* rs; + elf_section_t* s; + elf_section_t* rs; int i; for (i = 0; i < x64->sections->size; i++) { @@ -1106,11 +183,11 @@ static int _x64_elf_link_sections(scf_elf_x64_t* x64, uint32_t cs_index, uint32_ return 0; } -static void _x64_elf_process_syms(scf_elf_x64_t* x64, uint32_t cs_index) +static void _x64_elf_process_syms(elf_native_t* x64, uint32_t cs_index) { - scf_elf_x64_section_t* s; - scf_elf_x64_sym_t* sym; - Elf64_Rela* rela; + elf_section_t* s; + elf_sym_t* sym; + Elf64_Rela* rela; int i; int j; @@ -1143,7 +220,7 @@ static void _x64_elf_process_syms(scf_elf_x64_t* x64, uint32_t cs_index) free(sym); } #endif - qsort(x64->symbols->data, x64->symbols->size, sizeof(void*), _sym_cmp); + qsort(x64->symbols->data, x64->symbols->size, sizeof(void*), elf_sym_cmp); for (j = 0; j < x64->sections->size; j++) { s = x64->sections->data[j]; @@ -1179,8 +256,8 @@ static void _x64_elf_process_syms(scf_elf_x64_t* x64, uint32_t cs_index) static int _x64_elf_write_exec(scf_elf_context_t* elf) { - scf_elf_x64_t* x64 = elf->priv; - int nb_phdrs = 3; + elf_native_t* x64 = elf->priv; + int nb_phdrs = 3; if (x64->dynsyms && x64->dynsyms->size) { __x64_elf_add_dyn(x64); @@ -1194,13 +271,13 @@ static int _x64_elf_write_exec(scf_elf_context_t* elf) Elf64_Off phdr_offset = sizeof(x64->eh) + sizeof(Elf64_Shdr) * nb_sections; Elf64_Off section_offset = phdr_offset + sizeof(Elf64_Phdr) * nb_phdrs; - scf_elf_x64_section_t* s; - scf_elf_x64_section_t* cs = NULL; - scf_elf_x64_section_t* ros = NULL; - scf_elf_x64_section_t* ds = NULL; - scf_elf_x64_section_t* crela = NULL; - scf_elf_x64_section_t* drela = NULL; - scf_elf_x64_sym_t* sym; + elf_section_t* s; + elf_section_t* cs = NULL; + elf_section_t* ros = NULL; + elf_section_t* ds = NULL; + elf_section_t* crela = NULL; + elf_section_t* drela = NULL; + elf_sym_t* sym; int i; for (i = 0; i < x64->sections->size; i++) { @@ -1310,7 +387,7 @@ static int _x64_elf_write_exec(scf_elf_context_t* elf) } // write elf header - _x64_elf_header_fill(&x64->eh, ET_EXEC, _start, phdr_offset, nb_phdrs, nb_sections, nb_sections - 1); + elf_header(&x64->eh, ET_EXEC, EM_X86_64, _start, phdr_offset, nb_phdrs, nb_sections, nb_sections - 1); fwrite(&x64->eh, sizeof(x64->eh), 1, elf->fp); // write null section header @@ -1325,7 +402,7 @@ static int _x64_elf_write_exec(scf_elf_context_t* elf) if (SHT_RELA == s->sh.sh_type && 0 == s->sh.sh_link) s->sh.sh_link = nb_sections - 3; - _x64_elf_section_header_fill(&s->sh, shstrtab_offset, s->sh.sh_addr, + section_header(&s->sh, shstrtab_offset, s->sh.sh_addr, section_offset, s->data_len, s->sh.sh_link, s->sh.sh_info, s->sh.sh_entsize); @@ -1355,7 +432,7 @@ static int _x64_elf_write_exec(scf_elf_context_t* elf) } // write symtab section header - _x64_elf_section_header_fill(&x64->sh_symtab, shstrtab_offset, 0, + section_header(&x64->sh_symtab, shstrtab_offset, 0, section_offset, (x64->symbols->size + 1) * sizeof(Elf64_Sym), nb_sections - 2, nb_local_syms, sizeof(Elf64_Sym)); @@ -1365,7 +442,7 @@ static int _x64_elf_write_exec(scf_elf_context_t* elf) shstrtab_offset += strlen(".symtab") + 1; // write strtab section header - _x64_elf_section_header_fill(&x64->sh_strtab, shstrtab_offset, 0, + section_header(&x64->sh_strtab, shstrtab_offset, 0, section_offset, strtab_offset, 0, 0, 0); fwrite(&x64->sh_strtab, sizeof(x64->sh_strtab), 1, elf->fp); @@ -1374,7 +451,7 @@ static int _x64_elf_write_exec(scf_elf_context_t* elf) // write shstrtab section header uint64_t shstrtab_len = shstrtab_offset + strlen(".shstrtab") + 1; - _x64_elf_section_header_fill(&x64->sh_shstrtab, shstrtab_offset, 0, + section_header(&x64->sh_shstrtab, shstrtab_offset, 0, section_offset, shstrtab_len, 0, 0, 0); fwrite(&x64->sh_shstrtab, sizeof(x64->sh_shstrtab), 1, elf->fp); @@ -1398,47 +475,10 @@ static int _x64_elf_write_exec(scf_elf_context_t* elf) } #endif - // write user's section data - for (i = 0; i < x64->sections->size; i++) { - s = x64->sections->data[i]; - - if (s->data && s->data_len > 0) - fwrite(s->data, s->data_len, 1, elf->fp); - } - - // write user's symbols data (symtab section) - // entry index 0 in symtab is NOTYPE - Elf64_Sym sym0 = {0}; - sym0.st_info = ELF64_ST_INFO(STB_LOCAL, STT_NOTYPE); - - fwrite(&sym0, sizeof(sym0), 1, elf->fp); - for (i = 0; i < x64->symbols->size; i++) { - sym = x64->symbols->data[i]; - - fwrite(&sym->sym, sizeof(sym->sym), 1, elf->fp); - } - - // write strtab data (strtab section, symbol names of symtab) - uint8_t c = 0; - fwrite(&c, sizeof(c), 1, elf->fp); - for (i = 0; i < x64->symbols->size; i++) { - sym = x64->symbols->data[i]; - - if (sym->name) - fwrite(sym->name->data, sym->name->len + 1, 1, elf->fp); - } - - // write shstrtab data (shstrtab section, section names of all sections) - fwrite(&c, sizeof(c), 1, elf->fp); - for (i = 0; i < x64->sections->size; i++) { - s = x64->sections->data[i]; - - fwrite(s->name->data, s->name->len + 1, 1, elf->fp); - } - - char* str = ".symtab\0.strtab\0.shstrtab\0"; - int str_len = strlen(".symtab") + strlen(".strtab") + strlen(".shstrtab") + 3; - fwrite(str, str_len, 1, elf->fp); + elf_write_sections(elf); + elf_write_symtab (elf); + elf_write_strtab (elf); + elf_write_shstrtab(elf); return 0; } @@ -1446,20 +486,20 @@ scf_elf_ops_t elf_ops_x64 = { .machine = "x64", - .open = _x64_elf_open, - .close = _x64_elf_close, + .open = elf_open, + .close = elf_close, - .add_sym = _x64_elf_add_sym, - .add_section = _x64_elf_add_section, + .add_sym = elf_add_sym, + .add_section = elf_add_section, - .add_rela_section = _x64_elf_add_rela_section, + .add_rela_section = elf_add_rela_section, - .add_dyn_need = _x64_elf_add_dyn_need, - .add_dyn_rela = _x64_elf_add_dyn_rela, + .add_dyn_need = elf_add_dyn_need, + .add_dyn_rela = elf_add_dyn_rela, - .read_syms = _x64_elf_read_syms, - .read_relas = _x64_elf_read_relas, - .read_section = _x64_elf_read_section, + .read_syms = elf_read_syms, + .read_relas = elf_read_relas, + .read_section = elf_read_section, .write_rel = _x64_elf_write_rel, .write_exec = _x64_elf_write_exec, diff --git a/elf/scf_elf_x64.h b/elf/scf_elf_x64.h index eea7244..ddc828d 100644 --- a/elf/scf_elf_x64.h +++ b/elf/scf_elf_x64.h @@ -2,71 +2,10 @@ #define SCF_ELF_X64_H #include"scf_elf.h" -#include"scf_vector.h" -#include"scf_string.h" +#include"scf_elf_native.h" -typedef struct scf_elf_x64_section_s scf_elf_x64_section_t; - -struct scf_elf_x64_section_s -{ - scf_elf_x64_section_t* link; - scf_elf_x64_section_t* info; - - scf_string_t* name; - - Elf64_Shdr sh; - - uint64_t offset; - - uint16_t index; - uint8_t* data; - int data_len; -}; - -typedef struct { - scf_elf_x64_section_t* section; - - scf_string_t* name; - - Elf64_Sym sym; - - int index; - uint8_t dyn_flag:1; -} scf_elf_x64_sym_t; - -typedef struct { - Elf64_Ehdr eh; - - Elf64_Shdr sh_null; - - scf_vector_t* sections; - - Elf64_Shdr sh_symtab; - scf_vector_t* symbols; - - Elf64_Shdr sh_strtab; - - Elf64_Shdr sh_shstrtab; - scf_string_t* sh_shstrtab_data; - - scf_vector_t* dynsyms; - scf_vector_t* dyn_needs; - scf_vector_t* dyn_relas; - - scf_elf_x64_section_t* interp; - scf_elf_x64_section_t* dynsym; - scf_elf_x64_section_t* dynstr; - scf_elf_x64_section_t* gnu_version; - scf_elf_x64_section_t* gnu_version_r; - scf_elf_x64_section_t* rela_plt; - scf_elf_x64_section_t* plt; - scf_elf_x64_section_t* dynamic; - scf_elf_x64_section_t* got_plt; - -} scf_elf_x64_t; - -int __x64_elf_add_dyn (scf_elf_x64_t* x64); -int __x64_elf_post_dyn(scf_elf_x64_t* x64, uint64_t rx_base, uint64_t rw_base, scf_elf_x64_section_t* cs); +int __x64_elf_add_dyn (elf_native_t* x64); +int __x64_elf_post_dyn(elf_native_t* x64, uint64_t rx_base, uint64_t rw_base, elf_section_t* cs); int __x64_elf_write_phdr (scf_elf_context_t* elf, uint64_t rx_base, uint64_t offset, uint32_t nb_phdrs); int __x64_elf_write_interp (scf_elf_context_t* elf, uint64_t rx_base, uint64_t offset, uint64_t len); diff --git a/elf/scf_elf_x64_so.c b/elf/scf_elf_x64_so.c index 579786e..2a92e9a 100644 --- a/elf/scf_elf_x64_so.c +++ b/elf/scf_elf_x64_so.c @@ -17,11 +17,11 @@ static uint32_t _x64_elf_hash(const uint8_t* p) return k; } -static int _x64_elf_add_interp(scf_elf_x64_t* x64, scf_elf_x64_section_t** ps) +static int _x64_elf_add_interp(elf_native_t* x64, elf_section_t** ps) { - scf_elf_x64_section_t* s; + elf_section_t* s; - s = calloc(1, sizeof(scf_elf_x64_section_t)); + s = calloc(1, sizeof(elf_section_t)); if (!s) return -ENOMEM; @@ -62,11 +62,11 @@ static int _x64_elf_add_interp(scf_elf_x64_t* x64, scf_elf_x64_section_t** ps) return 0; } -static int _x64_elf_add_gnu_version(scf_elf_x64_t* x64, scf_elf_x64_section_t** ps) +static int _x64_elf_add_gnu_version(elf_native_t* x64, elf_section_t** ps) { - scf_elf_x64_section_t* s; + elf_section_t* s; - s = calloc(1, sizeof(scf_elf_x64_section_t)); + s = calloc(1, sizeof(elf_section_t)); if (!s) return -ENOMEM; @@ -102,11 +102,11 @@ static int _x64_elf_add_gnu_version(scf_elf_x64_t* x64, scf_elf_x64_section_t** return 0; } -static int _x64_elf_add_gnu_version_r(scf_elf_x64_t* x64, scf_elf_x64_section_t** ps) +static int _x64_elf_add_gnu_version_r(elf_native_t* x64, elf_section_t** ps) { - scf_elf_x64_section_t* s; + elf_section_t* s; - s = calloc(1, sizeof(scf_elf_x64_section_t)); + s = calloc(1, sizeof(elf_section_t)); if (!s) return -ENOMEM; @@ -142,11 +142,11 @@ static int _x64_elf_add_gnu_version_r(scf_elf_x64_t* x64, scf_elf_x64_section_t* return 0; } -static int _x64_elf_add_dynsym(scf_elf_x64_t* x64, scf_elf_x64_section_t** ps) +static int _x64_elf_add_dynsym(elf_native_t* x64, elf_section_t** ps) { - scf_elf_x64_section_t* s; + elf_section_t* s; - s = calloc(1, sizeof(scf_elf_x64_section_t)); + s = calloc(1, sizeof(elf_section_t)); if (!s) return -ENOMEM; @@ -184,11 +184,11 @@ static int _x64_elf_add_dynsym(scf_elf_x64_t* x64, scf_elf_x64_section_t** ps) return 0; } -static int _x64_elf_add_dynstr(scf_elf_x64_t* x64, scf_elf_x64_section_t** ps) +static int _x64_elf_add_dynstr(elf_native_t* x64, elf_section_t** ps) { - scf_elf_x64_section_t* s; + elf_section_t* s; - s = calloc(1, sizeof(scf_elf_x64_section_t)); + s = calloc(1, sizeof(elf_section_t)); if (!s) return -ENOMEM; @@ -216,11 +216,11 @@ static int _x64_elf_add_dynstr(scf_elf_x64_t* x64, scf_elf_x64_section_t** ps) return 0; } -static int _x64_elf_add_dynamic(scf_elf_x64_t* x64, scf_elf_x64_section_t** ps) +static int _x64_elf_add_dynamic(elf_native_t* x64, elf_section_t** ps) { - scf_elf_x64_section_t* s; + elf_section_t* s; - s = calloc(1, sizeof(scf_elf_x64_section_t)); + s = calloc(1, sizeof(elf_section_t)); if (!s) return -ENOMEM; @@ -259,11 +259,11 @@ static int _x64_elf_add_dynamic(scf_elf_x64_t* x64, scf_elf_x64_section_t** ps) return 0; } -static int _x64_elf_add_got_plt(scf_elf_x64_t* x64, scf_elf_x64_section_t** ps) +static int _x64_elf_add_got_plt(elf_native_t* x64, elf_section_t** ps) { - scf_elf_x64_section_t* s; + elf_section_t* s; - s = calloc(1, sizeof(scf_elf_x64_section_t)); + s = calloc(1, sizeof(elf_section_t)); if (!s) return -ENOMEM; @@ -299,11 +299,11 @@ static int _x64_elf_add_got_plt(scf_elf_x64_t* x64, scf_elf_x64_section_t** ps) return 0; } -static int _x64_elf_add_rela_plt(scf_elf_x64_t* x64, scf_elf_x64_section_t** ps) +static int _x64_elf_add_rela_plt(elf_native_t* x64, elf_section_t** ps) { - scf_elf_x64_section_t* s; + elf_section_t* s; - s = calloc(1, sizeof(scf_elf_x64_section_t)); + s = calloc(1, sizeof(elf_section_t)); if (!s) return -ENOMEM; @@ -340,11 +340,11 @@ static int _x64_elf_add_rela_plt(scf_elf_x64_t* x64, scf_elf_x64_section_t** ps) return 0; } -static int _x64_elf_add_plt(scf_elf_x64_t* x64, scf_elf_x64_section_t** ps) +static int _x64_elf_add_plt(elf_native_t* x64, elf_section_t** ps) { - scf_elf_x64_section_t* s; + elf_section_t* s; - s = calloc(1, sizeof(scf_elf_x64_section_t)); + s = calloc(1, sizeof(elf_section_t)); if (!s) return -ENOMEM; @@ -416,8 +416,8 @@ static int _x64_elf_add_plt(scf_elf_x64_t* x64, scf_elf_x64_section_t** ps) static int _section_cmp(const void* v0, const void* v1) { - const scf_elf_x64_section_t* s0 = *(const scf_elf_x64_section_t**)v0; - const scf_elf_x64_section_t* s1 = *(const scf_elf_x64_section_t**)v1; + const elf_section_t* s0 = *(const elf_section_t**)v0; + const elf_section_t* s1 = *(const elf_section_t**)v1; if (s0->index < s1->index) return -1; @@ -426,10 +426,10 @@ static int _section_cmp(const void* v0, const void* v1) return 0; } -int __x64_elf_add_dyn (scf_elf_x64_t* x64) +int __x64_elf_add_dyn (elf_native_t* x64) { - scf_elf_x64_section_t* s; - scf_elf_x64_sym_t* sym; + elf_section_t* s; + elf_sym_t* sym; Elf64_Rela* rela; int i; @@ -509,7 +509,7 @@ int __x64_elf_add_dyn (scf_elf_x64_t* x64) memcpy(&syms[0], &sym0, sizeof(Elf64_Sym)); for (i = 0; i < x64->dynsyms->size; i++) { - scf_elf_x64_sym_t* xsym = x64->dynsyms->data[i]; + elf_sym_t* xsym = x64->dynsyms->data[i]; memcpy(&syms[i + 1], &xsym->sym, sizeof(Elf64_Sym)); @@ -649,7 +649,7 @@ int __x64_elf_add_dyn (scf_elf_x64_t* x64) return 0; } -int __x64_elf_post_dyn(scf_elf_x64_t* x64, uint64_t rx_base, uint64_t rw_base, scf_elf_x64_section_t* cs) +int __x64_elf_post_dyn(elf_native_t* x64, uint64_t rx_base, uint64_t rw_base, elf_section_t* cs) { uint64_t cs_base = rx_base + cs->offset; @@ -734,7 +734,7 @@ int __x64_elf_post_dyn(scf_elf_x64_t* x64, uint64_t rx_base, uint64_t rw_base, s for (i = x64->dyn_needs->size; i < x64->dynamic->data_len / sizeof(Elf64_Dyn); i++) { - scf_elf_x64_section_t* s = (scf_elf_x64_section_t*)dtags[i].d_un.d_ptr; + elf_section_t* s = (elf_section_t*)dtags[i].d_un.d_ptr; switch (dtags[i].d_tag) { diff --git a/native/risc/scf_naja.c b/native/risc/scf_naja.c new file mode 100644 index 0000000..53ee2cd --- /dev/null +++ b/native/risc/scf_naja.c @@ -0,0 +1,1415 @@ +#include"scf_risc.h" + +int naja_inst_I2G(scf_3ac_code_t* c, scf_register_t* rd, uint64_t imm, int bytes) +{ + scf_instruction_t* inst; + + uint64_t invert = ~imm; + uint32_t opcode; + + if (0 == (invert >> 32)) { + + // movn rd, invert[15:0] + opcode = (0xf << 26) | (rd->id << 21) | (0x1 << 20) | (0x7 << 16) | (invert & 0xffff); + inst = risc_make_inst(c, opcode); + RISC_INST_ADD_CHECK(c->instructions, inst); + + if (invert >> 16) { + // movk rd, imm[31:16] + opcode = (0xf << 26) | (rd->id << 21) | (0x1 << 20) | (0x1 << 16)| ((imm >> 16) & 0xffff); + inst = risc_make_inst(c, opcode); + RISC_INST_ADD_CHECK(c->instructions, inst); + } + + return 0; + } + + // mov rd, imm[15:0] + opcode = (0xf << 26) | (rd->id << 21) | (0x1 << 20) | (imm & 0xffff); + inst = risc_make_inst(c, opcode); + RISC_INST_ADD_CHECK(c->instructions, inst); + + imm >>= 16; + if (imm & 0xffff) { + + // movk rd, imm[31:16] + opcode = (0xf << 26) | (rd->id << 21) | (0x1 << 20) | (0x1 << 16) | (imm & 0xffff); + inst = risc_make_inst(c, opcode); + RISC_INST_ADD_CHECK(c->instructions, inst); + } + + imm >>= 16; + if (imm & 0xffff) { + + // movk rd, imm[47:32] + opcode = (0xf << 26) | (rd->id << 21) | (0x1 << 20) | (0x2 << 16) | (imm & 0xffff); + inst = risc_make_inst(c, opcode); + RISC_INST_ADD_CHECK(c->instructions, inst); + } + + imm >>= 16; + if (imm & 0xffff) { + + // movk rd, imm[63:48] + opcode = (0xf << 26) | (rd->id << 21) | (0x1 << 20) | (0x3 << 16) | (imm & 0xffff); + inst = risc_make_inst(c, opcode); + RISC_INST_ADD_CHECK(c->instructions, inst); + } + + return 0; +} + +int naja_inst_ADR2G(scf_3ac_code_t* c, scf_function_t* f, scf_register_t* rd, scf_variable_t* vs) +{ + scf_register_t* fp = risc_find_register("fp"); + scf_instruction_t* inst = NULL; + scf_rela_t* rela = NULL; + + int64_t offset; + uint32_t opcode; + uint32_t SIZE = 0; + uint32_t S = 1; + + int size = risc_variable_size(vs); + + if (vs->local_flag || vs->tmp_flag) { + + offset = vs->bp_offset; + + if (offset >= 0 && offset <= 0x7fff) + + opcode = (0 << 26) | (rd->id << 21) | (0x1 << 20) | (offset << 5) | fp->id; + + else if (offset < 0 && -offset <= 0x7fff) + + opcode = (1 << 26) | (rd->id << 21) | (0x1 << 20) | ((-offset) << 5) | fp->id; + + else { + int ret = naja_inst_I2G(c, rd, offset, 8); + if (ret < 0) + return ret; + + opcode = (0 << 26) | (rd->id << 21) | (rd->id << 5) | fp->id; + } + + inst = risc_make_inst(c, opcode); + RISC_INST_ADD_CHECK(c->instructions, inst); + + } else if (vs->global_flag) { + offset = 0; + + opcode = (0x2a << 26) | (rd->id << 21); + inst = risc_make_inst(c, opcode); + RISC_INST_ADD_CHECK(c->instructions, inst); + RISC_RELA_ADD_CHECK(f->data_relas, rela, c, vs, NULL); + rela->type = R_AARCH64_ADR_PREL_PG_HI21; + + opcode = (0 << 26) | (rd->id << 21) | (0x1 << 20) | rd->id; + inst = risc_make_inst(c, opcode); + RISC_INST_ADD_CHECK(c->instructions, inst); + RISC_RELA_ADD_CHECK(f->data_relas, rela, c, vs, NULL); + rela->type = R_AARCH64_ADD_ABS_LO12_NC; + + } else { + scf_loge("temp var should give a register\n"); + return -EINVAL; + } + + return 0; +} + +int naja_inst_M2G(scf_3ac_code_t* c, scf_function_t* f, scf_register_t* rd, scf_register_t* rb, scf_variable_t* vs) +{ + scf_register_t* fp = risc_find_register("fp"); + scf_register_t* ri = NULL; + scf_instruction_t* inst = NULL; + scf_rela_t* rela = NULL; + + int64_t offset; + uint32_t opcode; + uint32_t SIZE = 0; + + int size = risc_variable_size(vs); + + if (!rb) { + if (vs->local_flag || vs->tmp_flag) { + + offset = vs->bp_offset; + rb = fp; + + } else if (vs->global_flag) { + offset = 0; + + int ret = naja_inst_ADR2G(c, f, rd, vs); + if (ret < 0) + return -EINVAL; + + rb = rd; + + } else { + scf_loge("temp var should give a register\n"); + return -EINVAL; + } + + } else { + if (vs->local_flag || vs->tmp_flag) + offset = vs->bp_offset; + else + offset = vs->offset; + } + + if (1 == size) + SIZE = 0; + else if (2 == size) { + + if (offset & 0x1) { + scf_loge("memory align error\n"); + return -EINVAL; + } + + offset >> 1; + SIZE = 1; + + } else if (4 == size) { + + if (offset & 0x3) { + scf_loge("memory align error\n"); + return -EINVAL; + } + + offset >> 2; + SIZE = 2; + + } else if (8 == size) { + + if (offset & 0x7) { + scf_loge("memory align error\n"); + return -EINVAL; + } + + offset >> 3; + SIZE = 3; + } else + return -EINVAL; + + + if (offset >= -0x7ff && offset <= 0x7ff) + opcode = (0x4 << 26) | ((offset & 0xfff) << 5) | rb->id; + else { + int ret = risc_select_free_reg(&ri, c, f, 0); + if (ret < 0) { + scf_loge("\n"); + return -EINVAL; + } + + ret = naja_inst_I2G(c, ri, offset, 4); + if (ret < 0) + return ret; + + opcode = (0xc << 26) | (SIZE << 10) | (ri->id << 5) | rb->id; + } + + if (rd->bytes > size && scf_variable_signed(vs)) + opcode |= 0x1 << 19; + + opcode |= (rd->id << 21) | SIZE << 17; + opcode |= RISC_COLOR_TYPE(rd->color) << 30; + + inst = risc_make_inst(c, opcode); + RISC_INST_ADD_CHECK(c->instructions, inst); + + return 0; +} + +int naja_inst_G2M(scf_3ac_code_t* c, scf_function_t* f, scf_register_t* rs, scf_register_t* rb, scf_variable_t* vs) +{ + scf_register_t* fp = risc_find_register("fp"); + scf_register_t* ri = NULL; + scf_instruction_t* inst = NULL; + scf_rela_t* rela = NULL; + + int64_t offset; + uint32_t opcode; + uint32_t SIZE = 0; + + int size = risc_variable_size(vs); + + if (!rb) { + if (vs->local_flag || vs->tmp_flag) { + + offset = vs->bp_offset; + rb = fp; + + } else if (vs->global_flag) { + offset = 0; + + int ret = risc_select_free_reg(&rb, c, f, 0); + if (ret < 0) { + scf_loge("\n"); + return -EINVAL; + } + + ret = naja_inst_ADR2G(c, f, rb, vs); + if (ret < 0) + return -EINVAL; + + } else { + scf_loge("temp var should give a register\n"); + return -EINVAL; + } + + } else { + if (vs->local_flag || vs->tmp_flag) + offset = vs->bp_offset; + else + offset = vs->offset; + } + + if (1 == size) + SIZE = 0; + else if (2 == size) { + + if (offset & 0x1) { + scf_loge("memory align error\n"); + return -EINVAL; + } + + offset >> 1; + SIZE = 1; + + } else if (4 == size) { + + if (offset & 0x3) { + scf_loge("memory align error\n"); + return -EINVAL; + } + + offset >> 2; + SIZE = 2; + + } else if (8 == size) { + + if (offset & 0x7) { + scf_loge("memory align error\n"); + return -EINVAL; + } + + offset >> 3; + SIZE = 3; + + } else + return -EINVAL; + + if (offset >= -0x7ff && offset <= 0x7ff) + opcode = (0x5 << 26) | ((offset & 0xfff) << 5) | rb->id; + else { + int ret = risc_select_free_reg(&ri, c, f, 0); + if (ret < 0) { + scf_loge("\n"); + return -EINVAL; + } + + ret = naja_inst_I2G(c, ri, offset, 4); + if (ret < 0) + return ret; + + opcode = (0xd << 26) | (SIZE << 10) | (ri->id << 5) | rb->id; + } + + opcode |= (rs->id << 21) | SIZE << 17; + opcode |= RISC_COLOR_TYPE(rs->color) << 30; + + inst = risc_make_inst(c, opcode); + RISC_INST_ADD_CHECK(c->instructions, inst); + + return 0; +} + +int naja_inst_ISTR2G(scf_3ac_code_t* c, scf_function_t* f, scf_register_t* rd, scf_variable_t* v) +{ + scf_instruction_t* inst = NULL; + scf_rela_t* rela = NULL; + + int size1 = risc_variable_size(v); + + assert(8 == rd->bytes); + assert(8 == size1); + + v->global_flag = 1; + v->local_flag = 0; + v->tmp_flag = 0; + + uint32_t opcode; + + opcode = (0x2a << 26) | (rd->id << 21); + inst = risc_make_inst(c, opcode); + RISC_INST_ADD_CHECK(c->instructions, inst); + RISC_RELA_ADD_CHECK(f->data_relas, rela, c, v, NULL); + rela->type = R_AARCH64_ADR_PREL_PG_HI21; + + opcode = (0 << 26) | (rd->id << 21) | (0x1 << 20) | rd->id; + inst = risc_make_inst(c, opcode); + RISC_INST_ADD_CHECK(c->instructions, inst); + RISC_RELA_ADD_CHECK(f->data_relas, rela, c, v, NULL); + rela->type = R_AARCH64_ADD_ABS_LO12_NC; + + return 0; +} + +int naja_inst_G2P(scf_3ac_code_t* c, scf_function_t* f, scf_register_t* rs, scf_register_t* rb, int32_t offset, int size) +{ + scf_register_t* ri = NULL; + scf_instruction_t* inst = NULL; + + uint32_t opcode; + uint32_t SIZE = 0; + + if (!rb) + return -EINVAL; + + if (1 == size) + SIZE = 0; + else if (2 == size) { + + if (offset & 0x1) { + scf_loge("memory align error\n"); + return -EINVAL; + } + + offset >> 1; + SIZE = 1; + + } else if (4 == size) { + + if (offset & 0x3) { + scf_loge("memory align error\n"); + return -EINVAL; + } + + offset >> 2; + SIZE = 2; + + } else if (8 == size) { + + if (offset & 0x7) { + scf_loge("memory align error\n"); + return -EINVAL; + } + + offset >> 3; + SIZE = 3; + + } else + return -EINVAL; + + if (offset >= -0x7ff && offset <= 0x7ff) + opcode = (0x5 << 26) | ((offset & 0xfff) << 5) | rb->id; + else { + int ret = risc_select_free_reg(&ri, c, f, 0); + if (ret < 0) { + scf_loge("\n"); + return -EINVAL; + } + + ret = naja_inst_I2G(c, ri, offset, 4); + if (ret < 0) + return ret; + + opcode = (0xd << 26) | (SIZE << 10) | (ri->id << 5) | rb->id; + } + + opcode |= (rs->id << 21) | SIZE << 17; + opcode |= RISC_COLOR_TYPE(rs->color) << 30; + + inst = risc_make_inst(c, opcode); + RISC_INST_ADD_CHECK(c->instructions, inst); + + return 0; +} + +int naja_inst_P2G(scf_3ac_code_t* c, scf_function_t* f, scf_register_t* rd, scf_register_t* rb, int32_t offset, int size) +{ + scf_register_t* ri = NULL; + scf_instruction_t* inst = NULL; + + uint32_t opcode; + uint32_t SIZE = 0; + + if (!rb) + return -EINVAL; + + if (1 == size) + SIZE = 0; + else if (2 == size) { + + if (offset & 0x1) { + scf_loge("memory align error\n"); + return -EINVAL; + } + + offset >> 1; + SIZE = 1; + + } else if (4 == size) { + + if (offset & 0x3) { + scf_loge("memory align error\n"); + return -EINVAL; + } + + offset >> 2; + SIZE = 2; + + } else if (8 == size) { + + if (offset & 0x7) { + scf_loge("memory align error\n"); + return -EINVAL; + } + + offset >> 3; + SIZE = 3; + + } else + return -EINVAL; + + if (offset >= -0x7ff && offset <= 0x7ff) + opcode = (0x4 << 26) | ((offset & 0xfff) << 5) | rb->id; + else { + int ret = risc_select_free_reg(&ri, c, f, 0); + if (ret < 0) { + scf_loge("\n"); + return -EINVAL; + } + + ret = naja_inst_I2G(c, ri, offset, 4); + if (ret < 0) + return ret; + + opcode = (0xc << 26) | (SIZE << 10) | (ri->id << 5) | rb->id; + } + + opcode |= (rd->id << 21) | SIZE << 17; + opcode |= RISC_COLOR_TYPE(rd->color) << 30; + + inst = risc_make_inst(c, opcode); + RISC_INST_ADD_CHECK(c->instructions, inst); + return 0; +} + +int naja_inst_ADRP2G(scf_3ac_code_t* c, scf_function_t* f, scf_register_t* rd, scf_register_t* rb, int32_t offset) +{ + scf_register_t* r = NULL; + scf_instruction_t* inst = NULL; + + uint32_t opcode = 0; + + if (offset >= 0 && offset <= 0x7fff) + opcode = (0 << 26) | (rd->id << 21) | (1 << 20) | (offset << 5) | rb->id; + + else if (offset < 0 && offset >= -0x7fff) + opcode = (1 << 26) | (rd->id << 21) | (1 << 20) | ((-offset) << 5) | rb->id; + + else { + int ret = risc_select_free_reg(&r, c, f, 0); + if (ret < 0) + return ret; + + ret = naja_inst_I2G(c, r, offset, 4); + if (ret < 0) + return ret; + + opcode = (0 << 26) | (rd->id << 21) | (r->id << 5) | rb->id; + } + + inst = risc_make_inst(c, opcode); + RISC_INST_ADD_CHECK(c->instructions, inst); + return 0; +} + +int naja_inst_ADRSIB2G(scf_3ac_code_t* c, scf_function_t* f, scf_register_t* rd, scf_sib_t* sib) +{ + scf_register_t* rb = sib->base; + scf_register_t* ri = sib->index; + scf_instruction_t* inst = NULL; + + assert(0 == sib->disp); + + if (!rb || !ri) + return -EINVAL; + + uint32_t opcode; + uint32_t SH; + + if (1 == sib->scale) + SH = 0; + + else if (2 == sib->scale) + SH = 1; + + else if (4 == sib->scale) + SH = 2; + + else if (8 == sib->scale) + SH = 3; + else + return -EINVAL; + + opcode = (0 << 26) | (rd->id << 21) | (SH << 10) | (ri->id << 5) | rb->id; + inst = risc_make_inst(c, opcode); + RISC_INST_ADD_CHECK(c->instructions, inst); + return 0; +} + +int naja_inst_SIB2G(scf_3ac_code_t* c, scf_function_t* f, scf_register_t* rd, scf_sib_t* sib) +{ + scf_register_t* rb = sib->base; + scf_register_t* ri = sib->index; + scf_instruction_t* inst = NULL; + + assert(0 == sib->disp); + + if (!rb || !ri) + return -EINVAL; + + int scale = sib->scale; + int size = sib->size; + + uint32_t opcode; + uint32_t SIZE = 0; + + if (1 == size) + SIZE = 0; + + else if (2 == size) + SIZE = 1; + + else if (4 == size) + SIZE = 2; + + else if (8 == size) + SIZE = 3; + else + return -EINVAL; + + opcode = (0xc << 26) | (rd->id << 21) | (SIZE << 10) | (ri->id << 5) | rb->id; + opcode |= SIZE << 17; + opcode |= RISC_COLOR_TYPE(rd->color) << 30; + + inst = risc_make_inst(c, opcode); + RISC_INST_ADD_CHECK(c->instructions, inst); + + return 0; +} + +int naja_inst_G2SIB(scf_3ac_code_t* c, scf_function_t* f, scf_register_t* rs, scf_sib_t* sib) +{ + scf_register_t* rb = sib->base; + scf_register_t* ri = sib->index; + scf_instruction_t* inst = NULL; + + assert(0 == sib->disp); + + if (!rb || !ri) + return -EINVAL; + + int scale = sib->scale; + int size = sib->size; + + uint32_t opcode; + uint32_t SIZE = 0; + + if (1 == size) + SIZE = 0; + + else if (2 == size) + SIZE = 1; + + else if (4 == size) + SIZE = 2; + + else if (8 == size) + SIZE = 3; + else + return -EINVAL; + + opcode = (0xd << 26) | (rs->id << 21) | (SIZE << 10) | (ri->id << 5) | rb->id; + opcode |= SIZE << 17; + opcode |= RISC_COLOR_TYPE(rs->color) << 26; + + inst = risc_make_inst(c, opcode); + RISC_INST_ADD_CHECK(c->instructions, inst); + + return 0; +} + +int naja_inst_M2GF(scf_3ac_code_t* c, scf_function_t* f, scf_register_t* rd, scf_register_t* rb, scf_variable_t* vs) +{ + return naja_inst_M2G(c, f, rd, rb, vs); +} + +scf_instruction_t* naja_inst_PUSH(scf_3ac_code_t* c, scf_register_t* r) +{ + scf_instruction_t* inst; + uint32_t opcode; + + opcode = (0x5 << 26) | (r->id << 21) | (1 << 20) | (3 << 17) | (1 << 5) | 0x1f; + inst = risc_make_inst(c, opcode); + + return inst; +} + +scf_instruction_t* naja_inst_POP(scf_3ac_code_t* c, scf_register_t* r) +{ + scf_instruction_t* inst; + uint32_t opcode; + + opcode = (0x4 << 26) | (r->id << 21) | (1 << 20) | (3 << 17) | ((0xfff & -1) << 5) | 0x1f; + inst = risc_make_inst(c, opcode); + + return inst; +} + +scf_instruction_t* naja_inst_RET(scf_3ac_code_t* c) +{ + scf_instruction_t* inst; + uint32_t opcode; + + opcode = 0x38 << 26; + inst = risc_make_inst(c, opcode); + + return inst; +} + +scf_instruction_t* naja_inst_MOV_SP(scf_3ac_code_t* c, scf_register_t* rd, scf_register_t* rs) +{ + scf_instruction_t* inst; + uint32_t opcode; + + opcode = (0xf << 26) | (rd->id << 21) | rs->id; + inst = risc_make_inst(c, opcode); + + return inst; +} + +scf_instruction_t* naja_inst_MOV_G(scf_3ac_code_t* c, scf_register_t* rd, scf_register_t* rs) +{ + scf_instruction_t* inst; + uint32_t opcode; + + opcode = (0xf << 26) | (rd->id << 21) | rs->id; + inst = risc_make_inst(c, opcode); + + return inst; +} + +scf_instruction_t* naja_inst_MVN(scf_3ac_code_t* c, scf_register_t* rd, scf_register_t* rs) +{ + scf_instruction_t* inst; + uint32_t opcode; + + opcode = (0xf << 26) | (rd->id << 21) | (3 << 16) | rs->id; + inst = risc_make_inst(c, opcode); + + return inst; +} + +scf_instruction_t* naja_inst_FMOV_G(scf_3ac_code_t* c, scf_register_t* rd, scf_register_t* rs) +{ + scf_instruction_t* inst; + uint32_t opcode; + + opcode = (0x1f << 26) | (rd->id << 21) | rs->id; + inst = risc_make_inst(c, opcode); + + return inst; +} + +scf_instruction_t* naja_inst_MOVSX(scf_3ac_code_t* c, scf_register_t* rd, scf_register_t* rs, int size) +{ + scf_instruction_t* inst; + uint32_t opcode; + uint32_t S; + + if (1 == size) + S = 5; + else if (2 == size) + S = 6; + else if (4 == size) + S = 7; + else + return NULL; + + opcode = (0xf << 26) | (rd->id << 21) | (1 << 19) | (S << 16)| rs->id; + inst = risc_make_inst(c, opcode); + + return inst; +} + +scf_instruction_t* naja_inst_MOVZX(scf_3ac_code_t* c, scf_register_t* rd, scf_register_t* rs, int size) +{ + scf_instruction_t* inst; + uint32_t opcode; + uint32_t S; + + if (1 == size) + S = 5; + else if (2 == size) + S = 6; + else if (4 == size) + S = 7; + else + return NULL; + + opcode = (0xf << 26) | (rd->id << 21) | (S << 16)| rs->id; + inst = risc_make_inst(c, opcode); + + return inst; +} + +scf_instruction_t* naja_inst_CVTSS2SD(scf_3ac_code_t* c, scf_register_t* rd, scf_register_t* rs) +{ + scf_instruction_t* inst; + uint32_t opcode; + uint32_t S; + + opcode = (0x1f << 26) | (rd->id << 21) | (1 << 16) | rs->id; + inst = risc_make_inst(c, opcode); + + return inst; +} + +scf_instruction_t* naja_inst_CVTSD2SS(scf_3ac_code_t* c, scf_register_t* rd, scf_register_t* rs) +{ + scf_instruction_t* inst; + uint32_t opcode; + + opcode = (0x1f << 26) | (rd->id << 21) | (2 << 16) | rs->id; + inst = risc_make_inst(c, opcode); + + return inst; +} + +scf_instruction_t* naja_inst_CVTF2SI(scf_3ac_code_t* c, scf_register_t* rd, scf_register_t* rs) +{ + scf_instruction_t* inst; + uint32_t opcode; + uint32_t S; + + if (4 == rd->bytes) + S = 0x4; + else + S = 0x5; + + opcode = (0x1f << 26) | (rd->id << 21) | (S << 16) | rs->id; + inst = risc_make_inst(c, opcode); + + return inst; +} + +scf_instruction_t* naja_inst_CVTF2UI(scf_3ac_code_t* c, scf_register_t* rd, scf_register_t* rs) +{ + scf_instruction_t* inst; + uint32_t opcode; + uint32_t S; + + if (4 == rd->bytes) + S = 0x6; + else + S = 0x7; + + opcode = (0x1f << 26) | (rd->id << 21) | (S << 16) | rs->id; + inst = risc_make_inst(c, opcode); + + return inst; +} + +scf_instruction_t* naja_inst_CVTSI2F(scf_3ac_code_t* c, scf_register_t* rd, scf_register_t* rs) +{ + scf_instruction_t* inst; + uint32_t opcode; + uint32_t S; + + if (4 == rd->bytes) + S = 0xc; + else + S = 0xd; + + opcode = (0x1f << 26) | (rd->id << 21) | (S << 16) | rs->id; + inst = risc_make_inst(c, opcode); + + return inst; +} + +scf_instruction_t* naja_inst_CVTUI2F(scf_3ac_code_t* c, scf_register_t* rd, scf_register_t* rs) +{ + scf_instruction_t* inst; + uint32_t opcode; + uint32_t S; + + if (4 == rd->bytes) + S = 0xe; + else + S = 0xf; + + opcode = (0x1f << 26) | (rd->id << 21) | (S << 16) | rs->id; + inst = risc_make_inst(c, opcode); + + return inst; +} + +scf_instruction_t* naja_inst_SUB_IMM(scf_3ac_code_t* c, scf_register_t* rd, scf_register_t* rs, uint64_t imm) +{ + scf_instruction_t* inst; + uint32_t opcode; + + if (imm > 0x7fff) { + scf_loge("NOT support too big imm: %#lx\n", imm); + return NULL; + } + + opcode = (1 << 26) | (rd->id << 21) | (1 << 20) | (imm << 5) | rs->id; + inst = risc_make_inst(c, opcode); + + return inst; +} + +scf_instruction_t* naja_inst_CMP_IMM(scf_3ac_code_t* c, scf_register_t* rs, uint64_t imm) +{ + scf_instruction_t* inst; + uint32_t opcode; + + if (imm > 0x7fff) { + scf_loge("NOT support too big imm: %#lx\n", imm); + return NULL; + } + + opcode = (9 << 26) | (1 << 20) | (imm << 5) | rs->id; + inst = risc_make_inst(c, opcode); + + return inst; +} + +scf_instruction_t* naja_inst_ADD_IMM(scf_3ac_code_t* c, scf_register_t* rd, scf_register_t* rs, uint64_t imm) +{ + scf_instruction_t* inst; + uint32_t opcode; + + if (imm > 0x7fff) { + scf_loge("NOT support too big imm: %#lx\n", imm); + return NULL; + } + + opcode = (0 << 26) | (rd->id << 21) | (1 << 20) | (imm << 5) | rs->id; + inst = risc_make_inst(c, opcode); + + return inst; +} + +scf_instruction_t* naja_inst_ADD_G(scf_3ac_code_t* c, scf_register_t* rd, scf_register_t* rs0, scf_register_t* rs1) +{ + scf_instruction_t* inst; + uint32_t opcode; + + opcode = (0 << 26) | (rd->id << 21) | (rs1->id << 5) | rs0->id; + inst = risc_make_inst(c, opcode); + + return inst; +} + +scf_instruction_t* naja_inst_SHL(scf_3ac_code_t* c, scf_register_t* rd, scf_register_t* rs0, scf_register_t* rs1) +{ + scf_instruction_t* inst; + uint32_t opcode; + + opcode = (0xf << 26) | (rd->id << 21) | (1 << 19) | (rs1->id << 5) | rs0->id; + inst = risc_make_inst(c, opcode); + + return inst; +} + +scf_instruction_t* naja_inst_SHR(scf_3ac_code_t* c, scf_register_t* rd, scf_register_t* rs0, scf_register_t* rs1) +{ + scf_instruction_t* inst; + uint32_t opcode; + + opcode = (0xf << 26) | (rd->id << 21) | (1 << 19) | (1 << 16) | (rs1->id << 5) | rs0->id; + inst = risc_make_inst(c, opcode); + + return inst; +} + +scf_instruction_t* naja_inst_ASR(scf_3ac_code_t* c, scf_register_t* rd, scf_register_t* rs0, scf_register_t* rs1) +{ + scf_instruction_t* inst; + uint32_t opcode; + + opcode = (0xf << 26) | (rd->id << 21) | (1 << 19) | (2 << 16) | (rs1->id << 5) | rs0->id; + inst = risc_make_inst(c, opcode); + + return inst; +} + +scf_instruction_t* naja_inst_AND_G(scf_3ac_code_t* c, scf_register_t* rd, scf_register_t* rs0, scf_register_t* rs1) +{ + scf_instruction_t* inst; + uint32_t opcode; + + opcode = (0x6 << 26) | (rd->id << 21) | (rs1->id << 5) | rs0->id; + inst = risc_make_inst(c, opcode); + + return inst; +} + +scf_instruction_t* naja_inst_OR_G(scf_3ac_code_t* c, scf_register_t* rd, scf_register_t* rs0, scf_register_t* rs1) +{ + scf_instruction_t* inst; + uint32_t opcode; + + opcode = (0x7 << 26) | (rd->id << 21) | (rs1->id << 5) | rs0->id; + inst = risc_make_inst(c, opcode); + + return inst; +} + +scf_instruction_t* naja_inst_SUB_G(scf_3ac_code_t* c, scf_register_t* rd, scf_register_t* rs0, scf_register_t* rs1) +{ + scf_instruction_t* inst; + uint32_t opcode; + + opcode = (0x1 << 26) | (rd->id << 21) | (rs1->id << 5) | rs0->id; + inst = risc_make_inst(c, opcode); + + return inst; +} + +scf_instruction_t* naja_inst_CMP_G(scf_3ac_code_t* c, scf_register_t* rs0, scf_register_t* rs1) +{ + scf_instruction_t* inst; + uint32_t opcode; + + opcode = (0x9 << 26) | (rs1->id << 5) | rs0->id; + inst = risc_make_inst(c, opcode); + + return inst; +} + +scf_instruction_t* naja_inst_FCMP(scf_3ac_code_t* c, scf_register_t* rs0, scf_register_t* rs1) +{ + scf_instruction_t* inst; + uint32_t opcode; + + opcode = (0x19 << 26) | (rs1->id << 5) | rs0->id; + inst = risc_make_inst(c, opcode); + + return inst; +} + +scf_instruction_t* naja_inst_NEG(scf_3ac_code_t* c, scf_register_t* rd, scf_register_t* rs) +{ + scf_instruction_t* inst; + uint32_t opcode; + + opcode = (0xf << 26) | (rd->id << 21) | (0x4 << 16) | rs->id; + inst = risc_make_inst(c, opcode); + + return inst; +} + +scf_instruction_t* naja_inst_TEQ(scf_3ac_code_t* c, scf_register_t* rs) +{ + scf_instruction_t* inst; + uint32_t opcode; + + opcode = (0x14 << 26) | (rs->id << 5) | rs->id; + inst = risc_make_inst(c, opcode); + + return inst; +} + +scf_instruction_t* naja_inst_FADD(scf_3ac_code_t* c, scf_register_t* rd, scf_register_t* rs0, scf_register_t* rs1) +{ + scf_instruction_t* inst; + uint32_t opcode; + + opcode = (0x10 << 26) | (rd->id << 21) | (rs1->id << 5) | rs0->id; + inst = risc_make_inst(c, opcode); + + return inst; +} + +scf_instruction_t* naja_inst_FSUB(scf_3ac_code_t* c, scf_register_t* rd, scf_register_t* rs0, scf_register_t* rs1) +{ + scf_instruction_t* inst; + uint32_t opcode; + + opcode = (0x11 << 26) | (rd->id << 21) | (rs1->id << 5) | rs0->id; + inst = risc_make_inst(c, opcode); + + return inst; +} + +scf_instruction_t* naja_inst_MUL(scf_3ac_code_t* c, scf_register_t* rd, scf_register_t* rs0, scf_register_t* rs1) +{ + scf_instruction_t* inst; + uint32_t opcode; + + opcode = (0x2 << 26) | (rd->id << 21) | (2 << 18) | (rs1->id << 5) | rs0->id; + inst = risc_make_inst(c, opcode); + + return inst; +} + +scf_instruction_t* naja_inst_FMUL(scf_3ac_code_t* c, scf_register_t* rd, scf_register_t* rs0, scf_register_t* rs1) +{ + scf_instruction_t* inst; + uint32_t opcode; + + opcode = (0x12 << 26) | (rd->id << 21) | (1 << 20) | (2 << 18) | (rs1->id << 5) | rs0->id; + inst = risc_make_inst(c, opcode); + + return inst; +} + +scf_instruction_t* naja_inst_FDIV(scf_3ac_code_t* c, scf_register_t* rd, scf_register_t* rs0, scf_register_t* rs1) +{ + scf_instruction_t* inst; + uint32_t opcode; + + opcode = (0x13 << 26) | (rd->id << 21) | (1 << 20) | (2 << 18) | (rs1->id << 5) | rs0->id; + inst = risc_make_inst(c, opcode); + + return inst; +} + +scf_instruction_t* naja_inst_DIV(scf_3ac_code_t* c, scf_register_t* rd, scf_register_t* rs0, scf_register_t* rs1) +{ + scf_instruction_t* inst; + uint32_t opcode; + + opcode = (0x3 << 26) | (rd->id << 21) | (2 << 18) | (rs1->id << 5) | rs0->id; + inst = risc_make_inst(c, opcode); + + return inst; +} + +scf_instruction_t* naja_inst_SDIV(scf_3ac_code_t* c, scf_register_t* rd, scf_register_t* rs0, scf_register_t* rs1) +{ + scf_instruction_t* inst; + uint32_t opcode; + + opcode = (0x3 << 26) | (rd->id << 21) | (1 << 20) | (2 << 18) | (rs1->id << 5) | rs0->id; + inst = risc_make_inst(c, opcode); + + return inst; +} + +scf_instruction_t* naja_inst_MSUB(scf_3ac_code_t* c, scf_register_t* rd, scf_register_t* rm, scf_register_t* rn, scf_register_t* ra) +{ + scf_instruction_t* inst; + uint32_t opcode; + + opcode = (0x2 << 26) | (rd->id << 21) | (1 << 20) | (1 << 18) | (ra->id << 10) | (rm->id << 5) | rn->id; + inst = risc_make_inst(c, opcode); + + return inst; +} + +scf_instruction_t* naja_inst_BL(scf_3ac_code_t* c) +{ + scf_instruction_t* inst; + uint32_t opcode; + + opcode = (0x18 << 26); + inst = risc_make_inst(c, opcode); + + return inst; +} + +scf_instruction_t* naja_inst_BLR(scf_3ac_code_t* c, scf_register_t* r) +{ + scf_instruction_t* inst; + uint32_t opcode; + + opcode = (0x1a << 26) | (r->id << 21); + inst = risc_make_inst(c, opcode); + + return inst; +} + +scf_instruction_t* naja_inst_SETZ(scf_3ac_code_t* c, scf_register_t* rd) +{ + scf_instruction_t* inst; + uint32_t opcode; + uint32_t cc = 1; + + opcode = (0xb << 26) | (rd->id << 21); + inst = risc_make_inst(c, opcode); + + return inst; +} +scf_instruction_t* naja_inst_SETNZ(scf_3ac_code_t* c, scf_register_t* rd) +{ + scf_instruction_t* inst; + uint32_t opcode; + uint32_t cc = 0; + + opcode = (0xb << 26) | (rd->id << 21) | (1 << 17); + inst = risc_make_inst(c, opcode); + + return inst; +} +scf_instruction_t* naja_inst_SETGT(scf_3ac_code_t* c, scf_register_t* rd) +{ + scf_instruction_t* inst; + uint32_t opcode; + + opcode = (0xb << 26) | (rd->id << 21) | (3 << 17); + inst = risc_make_inst(c, opcode); + + return inst; +} +scf_instruction_t* naja_inst_SETGE(scf_3ac_code_t* c, scf_register_t* rd) +{ + scf_instruction_t* inst; + uint32_t opcode; + + opcode = (0xb << 26) | (rd->id << 21) | (2 << 17); + inst = risc_make_inst(c, opcode); + + return inst; +} +scf_instruction_t* naja_inst_SETLT(scf_3ac_code_t* c, scf_register_t* rd) +{ + scf_instruction_t* inst; + uint32_t opcode; + + opcode = (0xb << 26) | (rd->id << 21) | (5 << 17); + inst = risc_make_inst(c, opcode); + + return inst; +} +scf_instruction_t* naja_inst_SETLE(scf_3ac_code_t* c, scf_register_t* rd) +{ + scf_instruction_t* inst; + uint32_t opcode; + + opcode = (0xb << 26) | (rd->id << 21) | (4 << 17); + inst = risc_make_inst(c, opcode); + + return inst; +} + +scf_instruction_t* naja_inst_JMP(scf_3ac_code_t* c) +{ + scf_instruction_t* inst; + uint32_t opcode; + + opcode = 0x8 << 26; + inst = risc_make_inst(c, opcode); + + return inst; +} + +scf_instruction_t* naja_inst_JZ(scf_3ac_code_t* c) +{ + scf_instruction_t* inst; + uint32_t opcode; + + opcode = (0xa << 26) | 1; + inst = risc_make_inst(c, opcode); + + return inst; +} + +scf_instruction_t* naja_inst_JNZ(scf_3ac_code_t* c) +{ + scf_instruction_t* inst; + uint32_t opcode; + + opcode = (0xa << 26) | (1 << 1) | 1; + inst = risc_make_inst(c, opcode); + + return inst; +} + +scf_instruction_t* naja_inst_JGT(scf_3ac_code_t* c) +{ + scf_instruction_t* inst; + uint32_t opcode; + + opcode = (0xa << 26) | (3 << 1) | 1; + inst = risc_make_inst(c, opcode); + + return inst; +} + +scf_instruction_t* naja_inst_JGE(scf_3ac_code_t* c) +{ + scf_instruction_t* inst; + uint32_t opcode; + + opcode = (0xa << 26) | (2 << 1) | 1; + inst = risc_make_inst(c, opcode); + + return inst; +} + +scf_instruction_t* naja_inst_JLT(scf_3ac_code_t* c) +{ + scf_instruction_t* inst; + uint32_t opcode; + + opcode = (0xa << 26) | (5 << 1) | 1; + inst = risc_make_inst(c, opcode); + + return inst; +} + +scf_instruction_t* naja_inst_JLE(scf_3ac_code_t* c) +{ + scf_instruction_t* inst; + uint32_t opcode; + + opcode = (0xa << 26) | (4 << 1) | 1; + inst = risc_make_inst(c, opcode); + + return inst; +} + +scf_instruction_t* naja_inst_JA(scf_3ac_code_t* c) +{ + return NULL; +} +scf_instruction_t* naja_inst_JB(scf_3ac_code_t* c) +{ + return NULL; +} +scf_instruction_t* naja_inst_JAE(scf_3ac_code_t* c) +{ + return NULL; +} +scf_instruction_t* naja_inst_JBE(scf_3ac_code_t* c) +{ + return NULL; +} + +void naja_set_jmp_offset(scf_instruction_t* inst, int32_t bytes) +{ + if (0xa == inst->code[3] && 1 == (inst->code[0] & 1)) { + + if (bytes >= 0 && bytes < (0x1 << 20)) { + bytes >>= 2; + bytes <<= 5; + + } else if (bytes < 0 && bytes > -(0x1 << 20)) { + + bytes >>= 2; + bytes &= 0x7ffff; + bytes <<= 5; + } else + assert(0); + + inst->code[0] |= 0xff & bytes; + inst->code[1] |= 0xff & (bytes >> 8); + inst->code[2] |= 0xff & (bytes >> 16); + + } else { + assert(8 == inst->code[3]); + + bytes >>= 2; + + assert(bytes < (0x1 << 26) && bytes > -(0x1 << 26)); + + inst->code[0] |= 0xff & bytes; + inst->code[1] |= 0xff & (bytes >> 8); + inst->code[2] |= 0xff & (bytes >> 16); + inst->code[3] |= 0x3 & (bytes >> 24); + } +} + +scf_inst_ops_t inst_ops_naja = +{ + .name = "naja", + + .BL = naja_inst_BL, + .BLR = naja_inst_BLR, + .PUSH = naja_inst_PUSH, + .POP = naja_inst_POP, + .TEQ = naja_inst_TEQ, + .NEG = naja_inst_NEG, + + .MOVZX = naja_inst_MOVZX, + .MOVSX = naja_inst_MOVSX, + .MVN = naja_inst_MVN, + .MOV_G = naja_inst_MOV_G, + .MOV_SP = naja_inst_MOV_SP, + + .ADD_G = naja_inst_ADD_G, + .ADD_IMM = naja_inst_ADD_IMM, + .SUB_G = naja_inst_SUB_G, + .SUB_IMM = naja_inst_SUB_IMM, + .CMP_G = naja_inst_CMP_G, + .CMP_IMM = naja_inst_CMP_IMM, + .AND_G = naja_inst_AND_G, + .OR_G = naja_inst_OR_G, + + .MUL = naja_inst_MUL, + .DIV = naja_inst_DIV, + .SDIV = naja_inst_SDIV, + .MSUB = naja_inst_MSUB, + + .SHL = naja_inst_SHL, + .SHR = naja_inst_SHR, + .ASR = naja_inst_ASR, + + .CVTSS2SD = naja_inst_CVTSS2SD, + .CVTSD2SS = naja_inst_CVTSD2SS, + .CVTF2SI = naja_inst_CVTF2SI, + .CVTF2UI = naja_inst_CVTF2UI, + .CVTSI2F = naja_inst_CVTSI2F, + .CVTUI2F = naja_inst_CVTUI2F, + + .FCMP = naja_inst_FCMP, + .FADD = naja_inst_FADD, + .FSUB = naja_inst_FSUB, + .FMUL = naja_inst_FMUL, + .FDIV = naja_inst_FDIV, + .FMOV_G = naja_inst_FMOV_G, + + .JA = naja_inst_JA, + .JB = naja_inst_JB, + .JZ = naja_inst_JZ, + .JNZ = naja_inst_JNZ, + .JGT = naja_inst_JGT, + .JGE = naja_inst_JGE, + .JLT = naja_inst_JLT, + .JLE = naja_inst_JLE, + .JAE = naja_inst_JAE, + .JBE = naja_inst_JBE, + .JMP = naja_inst_JMP, + .RET = naja_inst_RET, + + .SETZ = naja_inst_SETZ, + .SETNZ = naja_inst_SETNZ, + .SETGT = naja_inst_SETGT, + .SETGE = naja_inst_SETGE, + .SETLT = naja_inst_SETLT, + .SETLE = naja_inst_SETLE, + + .I2G = naja_inst_I2G, + .M2G = naja_inst_M2G, + .M2GF = naja_inst_M2GF, + .G2M = naja_inst_G2M, + .G2P = naja_inst_G2P, + .P2G = naja_inst_P2G, + .ISTR2G = naja_inst_ISTR2G, + .SIB2G = naja_inst_SIB2G, + .G2SIB = naja_inst_G2SIB, + .ADR2G = naja_inst_ADR2G, + .ADRP2G = naja_inst_ADRP2G, + .ADRSIB2G = naja_inst_ADRSIB2G, + + .set_jmp_offset = naja_set_jmp_offset, +}; + diff --git a/native/risc/scf_risc.c b/native/risc/scf_risc.c index 05617b1..9d80829 100644 --- a/native/risc/scf_risc.c +++ b/native/risc/scf_risc.c @@ -4,10 +4,12 @@ #include"scf_3ac.h" extern scf_inst_ops_t inst_ops_arm64; +extern scf_inst_ops_t inst_ops_naja; static scf_inst_ops_t* inst_ops_array[] = { &inst_ops_arm64, + &inst_ops_naja, NULL }; diff --git a/parse/Makefile b/parse/Makefile index 0cb8dce..0766f2f 100644 --- a/parse/Makefile +++ b/parse/Makefile @@ -37,13 +37,17 @@ CFILES += ../native/risc/scf_risc_opcode.c CFILES += ../native/risc/scf_risc_rcg.c CFILES += ../native/risc/scf_risc_reg.c CFILES += ../native/risc/scf_arm64.c +CFILES += ../native/risc/scf_naja.c CFILES += ../elf/scf_elf.c CFILES += ../elf/scf_elf_link.c +CFILES += ../elf/scf_elf_native.c CFILES += ../elf/scf_elf_x64.c CFILES += ../elf/scf_elf_x64_so.c CFILES += ../elf/scf_elf_arm64.c CFILES += ../elf/scf_elf_arm64_so.c +CFILES += ../elf/scf_elf_naja.c +CFILES += ../elf/scf_elf_naja_so.c CFILES += ../elf/scf_dwarf.c CFILES += ../elf/scf_dwarf_abbrev.c CFILES += ../elf/scf_dwarf_info.c diff --git a/parse/main.c b/parse/main.c index eb0551f..aae7583 100644 --- a/parse/main.c +++ b/parse/main.c @@ -158,7 +158,7 @@ int main(int argc, char* argv[]) } while (0) - if (!strcmp(arch, "arm64")) + if (!strcmp(arch, "arm64") || !strcmp(arch, "naja")) MAIN_ADD_FILES(__arm64_objs, __arm64_sofiles); else MAIN_ADD_FILES(__objs, __sofiles); -- 2.25.1