1, make a framework for risc native code generation,
authoryu.dongliang <18588496441@163.com>
Sat, 25 Mar 2023 09:39:18 +0000 (17:39 +0800)
committeryu.dongliang <18588496441@163.com>
Sat, 25 Mar 2023 09:39:23 +0000 (17:39 +0800)
2, add a bytecode generation named 'naja' for script language,
3, move some similar code to scf_elf_native.c in dir elf/ .

18 files changed:
elf/scf_dwarf_info.c
elf/scf_dwarf_line.c
elf/scf_elf.c
elf/scf_elf_arm64.c
elf/scf_elf_arm64.h
elf/scf_elf_arm64_so.c
elf/scf_elf_naja.c [new file with mode: 0644]
elf/scf_elf_naja.h [new file with mode: 0644]
elf/scf_elf_naja_so.c [new file with mode: 0644]
elf/scf_elf_native.c [new file with mode: 0644]
elf/scf_elf_native.h [new file with mode: 0644]
elf/scf_elf_x64.c
elf/scf_elf_x64.h
elf/scf_elf_x64_so.c
native/risc/scf_naja.c [new file with mode: 0644]
native/risc/scf_risc.c
parse/Makefile
parse/main.c

index 9a1bbafc10ed3b5e4e7d5d68a7268e88ce62c68c..818f87865139f6a1739dbfdaa1c6a3ecdd308b97 100644 (file)
@@ -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) {
 
index 2c6e594dd082b4e5d37d66b97dfd083bd42e42aa..ac44410159b525fdd4798837ea575052fd29232b 100644 (file)
@@ -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);
index 2aad8e89f5a9a7b832536f3933e9188798197bc0..5577d72de69e5f5b596b27b7402312261a657ca0 100644 (file)
@@ -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,
 };
index e76a9ef4952cd6153c2d0b7da37b839f0f14c8fd..ea13de447214be1384c0bc20323161dceb685337 100644 (file)
 #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,
index 947768bc4f7dd0489c4e46ce7699948afc2b09da..7eae07fe011d6ebcd28ed920ba461dd2854764a0 100644 (file)
@@ -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);
index ddca5fca95a4a7dc8068c45057f78852a051e080..6745089cb4602578b3c592153b06d97708e4b4be 100644 (file)
@@ -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 (file)
index 0000000..fe4e21f
--- /dev/null
@@ -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 (file)
index 0000000..ab586b7
--- /dev/null
@@ -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 (file)
index 0000000..345a9af
--- /dev/null
@@ -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 (file)
index 0000000..9a38604
--- /dev/null
@@ -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 (file)
index 0000000..08916c3
--- /dev/null
@@ -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
+
index 195e8e74f74cb515e08d9f79193e6692a83b3b39..eec6161dc37c2852e9aa38c266843724cdefb403 100644 (file)
 #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,
index eea72449927bac0e366a14ab9b709cf3613da0ab..ddc828d1ffeac360cd8767ef081bfd9ac83419f1 100644 (file)
@@ -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);
index 579786e14d3c92c300ddbb72ea0855e3cf040026..2a92e9a85cb9790149ee73542bb4d5aff9b0f602 100644 (file)
@@ -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 (file)
index 0000000..53ee2cd
--- /dev/null
@@ -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,
+};
+
index 05617b12ef26c62277419dafea868436a4a6f4db..9d808296436228f98f70e3c065bbe545a439b2c3 100644 (file)
@@ -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
 };
index 0cb8dce6ac8523c8fde18b555a858d68b65ba5ac..0766f2f2ec14f3bd5d22385028e199ef6c14fde9 100644 (file)
@@ -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
index eb0551f571c17ed04715c419d3ad92e8a58eb6f5..aae7583d7c79c421d82cab96693594431c75da65 100644 (file)
@@ -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);