rela->addend = addend;
rela->type = type;
- if (!strcmp(debug->arch, "arm64")) {
+ if (!strcmp(debug->arch, "arm64") || !strcmp(debug->arch, "naja")) {
switch (type) {
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);
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,
};
#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);
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;
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);
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;
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);
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;
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++) {
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);
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++) {
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;
}
// 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
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);
}
// 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));
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);
// 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);
}
#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;
}
{
.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,
#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);
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;
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;
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;
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;
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;
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;
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;
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;
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;
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;
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;
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));
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;
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) {
--- /dev/null
+#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,
+};
+
--- /dev/null
+#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
+
--- /dev/null
+#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;
+}
+
--- /dev/null
+#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));
+ }
+ }
+}
+
--- /dev/null
+#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
+
#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);
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;
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);
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;
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);
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;
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++) {
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;
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];
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);
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++) {
}
// 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
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);
}
// 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));
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);
// 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);
}
#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;
}
{
.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,
#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);
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;
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;
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;
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;
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;
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;
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;
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;
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;
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;
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;
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));
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;
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) {
--- /dev/null
+#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,
+};
+
#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
};
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
} 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);