From: yu.dongliang <18588496441@163.com> Date: Sun, 14 May 2023 09:24:15 +0000 (+0800) Subject: support arm32: 'hanoi.c' and 'hello.c' of 'scf/examples' test ok X-Git-Url: http://baseworks.info/?a=commitdiff_plain;h=09743a3fc02e621daaddd60569a6595af1341590;p=scf.git support arm32: 'hanoi.c' and 'hello.c' of 'scf/examples' test ok --- diff --git a/elf/scf_dwarf_info.c b/elf/scf_dwarf_info.c index 818f878..b270d16 100644 --- a/elf/scf_dwarf_info.c +++ b/elf/scf_dwarf_info.c @@ -330,6 +330,21 @@ static int _add_rela_common(scf_dwarf_debug_t* debug, const char* sym, uint64_t return -EINVAL; break; }; + + } else if (!strcmp(debug->arch, "arm32")) { + + switch (type) { + + case R_X86_64_32: + case R_X86_64_64: + rela->type = R_ARM_ABS32; + break; + + default: + scf_loge("\n"); + return -EINVAL; + break; + }; } return 0; diff --git a/elf/scf_dwarf_line.c b/elf/scf_dwarf_line.c index ac44410..0bd4fb3 100644 --- a/elf/scf_dwarf_line.c +++ b/elf/scf_dwarf_line.c @@ -683,6 +683,8 @@ int scf_dwarf_line_encode(scf_dwarf_debug_t* debug, scf_dwarf_line_machine_t* lm if (!strcmp(debug->arch, "arm64") || !strcmp(debug->arch, "naja")) rela->type = R_AARCH64_ABS64; + else if (!strcmp(debug->arch, "arm32")) + rela->type = R_ARM_ABS32; DWARF_DEBUG_LINE_FILL (lm->address); } diff --git a/elf/scf_elf.c b/elf/scf_elf.c index 60a4ef4..1764f53 100644 --- a/elf/scf_elf.c +++ b/elf/scf_elf.c @@ -2,12 +2,14 @@ extern scf_elf_ops_t elf_ops_x64; extern scf_elf_ops_t elf_ops_arm64; +extern scf_elf_ops_t elf_ops_arm32; extern scf_elf_ops_t elf_ops_naja; scf_elf_ops_t* elf_ops_array[] = { &elf_ops_x64, &elf_ops_arm64, + &elf_ops_arm32, &elf_ops_naja, NULL, diff --git a/elf/scf_elf_arm32.c b/elf/scf_elf_arm32.c new file mode 100644 index 0000000..cdedc55 --- /dev/null +++ b/elf/scf_elf_arm32.c @@ -0,0 +1,463 @@ +#include"scf_elf_arm32.h" +#include"scf_elf_link.h" + +static int _arm32_elf_write_rel(scf_elf_context_t* elf) +{ + return elf32_write_rel(elf, EM_ARM); +} + +static int _arm32_elf_link_cs(elf_native_t* arm32, elf_section_t* s, elf_section_t* rs, uint64_t cs_base) +{ + elf_sym_t* sym; + Elf32_Rela* rela; + + assert(rs->data_len % sizeof(Elf32_Rela) == 0); + + int i; + for (i = 0; i < rs->data_len; i += sizeof(Elf32_Rela)) { + + rela = (Elf32_Rela* )(rs->data + i); + sym = NULL; + + int sym_idx = ELF32_R_SYM(rela->r_info); + + scf_loge("i: %d, sym_idx '%d'\n", i, sym_idx); + + assert(sym_idx >= 1); + assert(sym_idx - 1 < arm32->symbols->size); + + sym = arm32->symbols->data[sym_idx - 1]; + if (sym->dyn_flag) { + scf_loge("sym '%s' in dynamic so\n", sym->name->data); + continue; + } + + int j = elf32_find_sym(&sym, rela, arm32->symbols); + if (j < 0) + return -1; + + int32_t offset = sym->sym.st_value - (cs_base + rela->r_offset) + rela->r_addend; + + rela->r_info = ELF32_R_INFO(j, ELF32_R_TYPE(rela->r_info)); + + switch (ELF32_R_TYPE(rela->r_info)) { + + case R_ARM_CALL: + + offset -= 8; // 'pc' is 'current + 8'. + assert(0 == (offset & 0x3)); + + scf_loge("sym: %s, offset: %#x, %#x\n", sym->name->data, offset, rela->r_offset); + offset >>= 2; + + if (offset > 0x7fffff || offset < -0x7fffff) { + scf_loge("\n"); + return -EINVAL; + } + + scf_loge("sym: %s, offset: %#x, %#x\n", sym->name->data, offset, rela->r_offset); + + *(uint32_t*)(s->data + rela->r_offset) &= 0xff000000; + *(uint32_t*)(s->data + rela->r_offset) |= 0x00ffffff & offset; + break; + + case R_ARM_REL32: + scf_loge("sym: %s, offset: %#x, %#x, st_value: %#x, cs: %#lx\n", sym->name->data, offset, rela->r_offset, + sym->sym.st_value, cs_base + rela->r_offset); + + *(uint32_t*)(s->data + rela->r_offset) += offset; + break; + default: + scf_loge("ELF32_R_TYPE(rela->r_info): %d\n", ELF32_R_TYPE(rela->r_info)); + return -EINVAL; + break; + }; + } + + return 0; +} + +static int _arm32_elf_link_ds(elf_native_t* arm32, elf_section_t* s, elf_section_t* rs) +{ + elf_sym_t* sym; + Elf32_Rela* rela; + + assert(rs->data_len % sizeof(Elf32_Rela) == 0); + + int i; + for (i = 0; i < rs->data_len; i += sizeof(Elf32_Rela)) { + + rela = (Elf32_Rela* )(rs->data + i); + sym = NULL; + + int j = elf32_find_sym(&sym, rela, arm32->symbols); + if (j < 0) + return -1; + + assert(ELF32_R_TYPE(rela->r_info) == R_ARM_ABS32); + + uint64_t offset = sym->sym.st_value + rela->r_addend; + + rela->r_info = ELF32_R_INFO(j, ELF32_R_TYPE(rela->r_info)); + + switch (ELF32_R_TYPE(rela->r_info)) { + + case R_ARM_ABS32: + memcpy(s->data + rela->r_offset, &offset, 4); + break; + default: + scf_loge("\n"); + return -EINVAL; + break; + }; + } + + return 0; +} + +static int _arm32_elf_link_debug(elf_native_t* arm32, elf_section_t* s, elf_section_t* rs) +{ + elf_sym_t* sym; + elf_sym_t* sym2; + Elf32_Rela* rela; + + assert(rs->data_len % sizeof(Elf32_Rela) == 0); + + int i; + for (i = 0; i < rs->data_len; i += sizeof(Elf32_Rela)) { + + rela = (Elf32_Rela* )(rs->data + i); + sym = NULL; + + int j = elf32_find_sym(&sym, rela, arm32->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 = ELF32_R_SYM(rela->r_info); + + sym2 = arm32->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 = ELF32_R_SYM(rela->r_info); + + sym2 = arm32->symbols->data[k - 1]; + + offset = sym2->sym.st_value; + rela->r_addend = sym2->sym.st_value - sym->sym.st_value; + } + + rela->r_info = ELF32_R_INFO(j, ELF32_R_TYPE(rela->r_info)); + + switch (ELF32_R_TYPE(rela->r_info)) { + + case R_ARM_ABS32: + memcpy(s->data + rela->r_offset, &offset, 4); + break; + default: + scf_loge("\n"); + return -EINVAL; + break; + }; + } + + return 0; +} + +static int _arm32_elf_link_sections(elf_native_t* arm32, uint32_t cs_index, uint32_t ds_index) +{ + elf_section_t* s; + elf_section_t* rs; + + int i; + for (i = 0; i < arm32->sections->size; i++) { + rs = arm32->sections->data[i]; + + if (SHT_RELA != rs->sh.sh_type) + continue; + + assert(rs->sh.sh_info < arm32->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 = arm32->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 (_arm32_elf_link_debug(arm32, s, rs) < 0) { + scf_loge("\n"); + return -1; + } + } + + return 0; +} + +static int _arm32_elf_write_exec(scf_elf_context_t* elf) +{ + elf_native_t* arm32 = elf->priv; + int nb_phdrs = 3; + + if (arm32->dynsyms && arm32->dynsyms->size) { + __arm32_elf_add_dyn(arm32); + nb_phdrs = 6; + } + + int nb_sections = 1 + arm32->sections->size + 1 + 1 + 1; + uint64_t shstrtab_offset = 1; + uint64_t strtab_offset = 1; + uint64_t dynstr_offset = 1; + Elf32_Off phdr_offset = sizeof(arm32->eh) + sizeof(Elf32_Shdr) * nb_sections; + Elf32_Off section_offset = phdr_offset + sizeof(Elf32_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 < arm32->sections->size; i++) { + s = arm32->sections->data[i]; + + scf_logw("i: %d, section: %s\n", i, s->name->data); + + 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; + scf_loge("i: %d, section: %s\n", i, s->name->data); + + } 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 < arm32->symbols->size; i++) { + sym = arm32->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 = _arm32_elf_link_cs(arm32, cs, crela, cs_base); + if (ret < 0) { + scf_loge("ret: %d\n", ret); + return ret; + } + + if (drela) { + ret = _arm32_elf_link_ds(arm32, ds, drela); + if (ret < 0) + return ret; + } + + ret = _arm32_elf_link_sections(arm32, cs->index, ds->index); + if (ret < 0) + return ret; + + elf32_process_syms(arm32, cs->index); + + cs ->sh.sh_addr = cs_base; + ds ->sh.sh_addr = ds_base; + ros->sh.sh_addr = ro_base; + + if (6 == nb_phdrs) + __arm32_elf_post_dyn(arm32, rx_base, rw_base, cs); + + for (i = 0; i < arm32->symbols->size; i++) { + sym = arm32->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(&arm32->eh, ET_EXEC, EM_ARM, _start, phdr_offset, nb_phdrs, nb_sections, nb_sections - 1); + fwrite(&arm32->eh, sizeof(arm32->eh), 1, elf->fp); + + // write null section header + fwrite(&arm32->sh_null, sizeof(arm32->sh_null), 1, elf->fp); + + // write user's section header + section_offset = phdr_offset + sizeof(Elf32_Phdr) * nb_phdrs; + + for (i = 0; i < arm32->sections->size; i++) { + s = arm32->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 = 4; + + 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 < arm32->symbols->size; i++) { + sym = arm32->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 == ELF32_ST_BIND(sym->sym.st_info)) + nb_local_syms++; + } + + // write symtab section header + section_header(&arm32->sh_symtab, shstrtab_offset, 0, + section_offset, (arm32->symbols->size + 1) * sizeof(Elf32_Sym), + nb_sections - 2, nb_local_syms, sizeof(Elf32_Sym)); + + fwrite(&arm32->sh_symtab, sizeof(arm32->sh_symtab), 1, elf->fp); + + section_offset += (arm32->symbols->size + 1) * sizeof(Elf32_Sym); + shstrtab_offset += strlen(".symtab") + 1; + + // write strtab section header + section_header(&arm32->sh_strtab, shstrtab_offset, 0, + section_offset, strtab_offset, + 0, 0, 0); + fwrite(&arm32->sh_strtab, sizeof(arm32->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(&arm32->sh_shstrtab, shstrtab_offset, 0, + section_offset, shstrtab_len, 0, 0, 0); + fwrite(&arm32->sh_shstrtab, sizeof(arm32->sh_shstrtab), 1, elf->fp); + +#if 1 + if (6 == nb_phdrs) { + __arm32_elf_write_phdr(elf, rx_base, phdr_offset, nb_phdrs); + + __arm32_elf_write_interp(elf, rx_base, arm32->interp->offset, arm32->interp->data_len); + } + + __arm32_elf_write_text (elf, rx_base, 0, cs->offset + cs->data_len); + __arm32_elf_write_rodata(elf, r_base, ros->offset, ros->data_len); + + if (6 == nb_phdrs) { + __arm32_elf_write_data(elf, rw_base, arm32->dynamic->offset, + arm32->dynamic->data_len + arm32->got_plt->data_len + ds->data_len); + + __arm32_elf_write_dynamic(elf, rw_base, arm32->dynamic->offset, arm32->dynamic->data_len); + } else { + __arm32_elf_write_data(elf, rw_base, ds->offset, ds->data_len); + } +#endif + + elf32_write_sections(elf); + elf32_write_symtab (elf); + elf32_write_strtab (elf); + elf32_write_shstrtab(elf); + return 0; +} + +scf_elf_ops_t elf_ops_arm32 = +{ + .machine = "arm32", + + .open = elf32_open, + .close = elf32_close, + + .add_sym = elf32_add_sym, + .add_section = elf32_add_section, + + .add_rela_section = elf32_add_rela_section, + + .add_dyn_need = elf32_add_dyn_need, + .add_dyn_rela = elf32_add_dyn_rela, + + .read_syms = elf32_read_syms, + .read_relas = elf32_read_relas, + .read_section = elf32_read_section, + + .write_rel = _arm32_elf_write_rel, + .write_exec = _arm32_elf_write_exec, +}; + diff --git a/elf/scf_elf_arm32.h b/elf/scf_elf_arm32.h new file mode 100644 index 0000000..bc606f3 --- /dev/null +++ b/elf/scf_elf_arm32.h @@ -0,0 +1,20 @@ +#ifndef SCF_ELF_ARM32_H +#define SCF_ELF_ARM32_H + +#include"scf_elf.h" +#include"scf_elf_native32.h" +#include"scf_vector.h" +#include"scf_string.h" + +int __arm32_elf_add_dyn (elf_native_t* arm32); +int __arm32_elf_post_dyn(elf_native_t* arm32, uint64_t rx_base, uint64_t rw_base, elf_section_t* cs); + +int __arm32_elf_write_phdr (scf_elf_context_t* elf, uint64_t rx_base, uint64_t offset, uint32_t nb_phdrs); +int __arm32_elf_write_interp (scf_elf_context_t* elf, uint64_t rx_base, uint64_t offset, uint64_t len); +int __arm32_elf_write_text (scf_elf_context_t* elf, uint64_t rx_base, uint64_t offset, uint64_t len); +int __arm32_elf_write_rodata (scf_elf_context_t* elf, uint64_t r_base, uint64_t offset, uint64_t len); +int __arm32_elf_write_data (scf_elf_context_t* elf, uint64_t rw_base, uint64_t offset, uint64_t len); +int __arm32_elf_write_dynamic(scf_elf_context_t* elf, uint64_t rw_base, uint64_t offset, uint64_t len); + +#endif + diff --git a/elf/scf_elf_arm32_so.c b/elf/scf_elf_arm32_so.c new file mode 100644 index 0000000..60f078b --- /dev/null +++ b/elf/scf_elf_arm32_so.c @@ -0,0 +1,894 @@ +#include"scf_elf_arm32.h" +#include"scf_elf_link.h" + +static uint32_t arm32_plt_lazy[5] = { + 0xe52de004, // push {lr} + 0xe59fe004, // ldr lr, [pc, #4] + 0xe08fe00e, // add lr, pc, lr + 0xe5bef008, // ldr pc, [lr, #8]! + + 0x00000000, // +}; + +static uint32_t arm32_plt[3] = { + 0xe28fc600, // add r12, pc, #0, 12 + 0xe28cca00, // add r12, r12, #16, 20 + 0xe5bcf000, // ldr pc, [r12, #0]! +}; + + +static uint32_t _arm32_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 _arm32_elf_add_interp(elf_native_t* arm32, 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-armhf.so.3"; + 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(arm32->sections, s); + if (ret < 0) { + scf_string_free(s->name); + free(s->data); + free(s); + return -ENOMEM; + } + + *ps = s; + return 0; +} + +static int _arm32_elf_add_gnu_version(elf_native_t* arm32, 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(arm32->dynsyms->size, sizeof(Elf32_Versym)); + if (!s->data) { + scf_string_free(s->name); + free(s); + return -ENOMEM; + } + s->data_len = arm32->dynsyms->size * sizeof(Elf32_Versym); + + s->index = 1; + + s->sh.sh_type = SHT_GNU_versym; + s->sh.sh_flags = SHF_ALLOC; + s->sh.sh_addralign = 4; + + int ret = scf_vector_add(arm32->sections, s); + if (ret < 0) { + scf_string_free(s->name); + free(s->data); + free(s); + return -ENOMEM; + } + + *ps = s; + return 0; +} + +static int _arm32_elf_add_gnu_version_r(elf_native_t* arm32, 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(Elf32_Verneed) + sizeof(Elf32_Vernaux)); + if (!s->data) { + scf_string_free(s->name); + free(s); + return -ENOMEM; + } + s->data_len = sizeof(Elf32_Verneed) + sizeof(Elf32_Vernaux); + + s->index = 1; + + s->sh.sh_type = SHT_GNU_verneed; + s->sh.sh_flags = SHF_ALLOC; + s->sh.sh_addralign = 4; + + int ret = scf_vector_add(arm32->sections, s); + if (ret < 0) { + scf_string_free(s->name); + free(s->data); + free(s); + return -ENOMEM; + } + + *ps = s; + return 0; +} + +static int _arm32_elf_add_dynsym(elf_native_t* arm32, 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(arm32->dynsyms->size + 1, sizeof(Elf32_Sym)); + if (!s->data) { + scf_string_free(s->name); + free(s); + return -ENOMEM; + } + s->data_len = (arm32->dynsyms->size + 1) * sizeof(Elf32_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 = 4; + s->sh.sh_entsize = sizeof(Elf32_Sym); + + int ret = scf_vector_add(arm32->sections, s); + if (ret < 0) { + scf_string_free(s->name); + free(s->data); + free(s); + return -ENOMEM; + } + + *ps = s; + return 0; +} + +static int _arm32_elf_add_dynstr(elf_native_t* arm32, 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(arm32->sections, s); + if (ret < 0) { + scf_string_free(s->name); + free(s->data); + free(s); + return -ENOMEM; + } + + *ps = s; + return 0; +} + +static int _arm32_elf_add_dynamic(elf_native_t* arm32, 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 = arm32->dyn_needs->size + 11 + 1; + + s->data = calloc(nb_tags, sizeof(Elf32_Dyn)); + if (!s->data) { + scf_string_free(s->name); + free(s); + return -ENOMEM; + } + s->data_len = nb_tags * sizeof(Elf32_Dyn); + + scf_logw("nb_tags: %d\n", nb_tags); + + s->index = 1; + + s->sh.sh_type = SHT_PROGBITS; + s->sh.sh_flags = SHF_ALLOC | SHF_WRITE; + s->sh.sh_addralign = 4; + s->sh.sh_entsize = sizeof(Elf32_Dyn); + + int ret = scf_vector_add(arm32->sections, s); + if (ret < 0) { + scf_string_free(s->name); + free(s->data); + free(s); + return -ENOMEM; + } + + *ps = s; + return 0; +} + +static int _arm32_elf_add_got_plt(elf_native_t* arm32, 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(arm32->dynsyms->size + 4, sizeof(uint32_t)); + if (!s->data) { + scf_string_free(s->name); + free(s); + return -ENOMEM; + } + s->data_len = (arm32->dynsyms->size + 4) * sizeof(uint32_t); + + s->index = 1; + + s->sh.sh_type = SHT_PROGBITS; + s->sh.sh_flags = SHF_ALLOC | SHF_WRITE; + s->sh.sh_addralign = 4; + + int ret = scf_vector_add(arm32->sections, s); + if (ret < 0) { + scf_string_free(s->name); + free(s->data); + free(s); + return -ENOMEM; + } + + *ps = s; + return 0; +} + +static int _arm32_elf_add_rela_plt(elf_native_t* arm32, 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(arm32->dynsyms->size, sizeof(Elf32_Rela)); + if (!s->data) { + scf_string_free(s->name); + free(s); + return -ENOMEM; + } + s->data_len = arm32->dynsyms->size * sizeof(Elf32_Rela); + + s->index = 1; + + s->sh.sh_type = SHT_RELA; + s->sh.sh_flags = SHF_ALLOC | SHF_INFO_LINK; + s->sh.sh_addralign = 4; + s->sh.sh_entsize = sizeof(Elf32_Rela); + + int ret = scf_vector_add(arm32->sections, s); + if (ret < 0) { + scf_string_free(s->name); + free(s->data); + free(s); + return -ENOMEM; + } + + *ps = s; + return 0; +} + +static int _arm32_elf_add_plt(elf_native_t* arm32, 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(arm32_plt_lazy) + sizeof(arm32_plt) * arm32->dynsyms->size); + if (!s->data) { + scf_string_free(s->name); + free(s); + return -ENOMEM; + } + + memcpy(s->data, arm32_plt_lazy, sizeof(arm32_plt_lazy)); + s->data_len = sizeof(arm32_plt_lazy); + + int i; + for (i = 0; i < arm32->dynsyms->size; i++) { + + memcpy(s->data + s->data_len, arm32_plt, sizeof(arm32_plt)); + + s->data_len += sizeof(arm32_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(arm32->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 __arm32_elf_add_dyn (elf_native_t* arm32) +{ + elf_section_t* s; + elf_sym_t* sym; + Elf32_Rela* rela; + + int i; + for (i = arm32->symbols->size - 1; i >= 0; i--) { + sym = arm32->symbols->data[i]; + + uint16_t shndx = sym->sym.st_shndx; + + if (STT_SECTION == ELF32_ST_TYPE(sym->sym.st_info)) { + if (shndx > 0) { + assert(shndx - 1 < arm32->sections->size); + sym->section = arm32->sections->data[shndx - 1]; + } + } else if (0 != shndx) { + if (shndx - 1 < arm32->sections->size) + sym->section = arm32->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 < arm32->sections->size; i++) { + s = arm32->sections->data[i]; + + s->index = arm32->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 < arm32->sections->size); + + s->link = arm32->sections->data[s->sh.sh_link - 1]; + } + + if (s->sh.sh_info > 0) { + assert(s->sh.sh_info - 1 < arm32->sections->size); + + s->info = arm32->sections->data[s->sh.sh_info - 1]; + } + } + + _arm32_elf_add_interp(arm32, &arm32->interp); + _arm32_elf_add_dynsym(arm32, &arm32->dynsym); + _arm32_elf_add_dynstr(arm32, &arm32->dynstr); + +// _arm32_elf_add_gnu_version_r(arm32, &arm32->gnu_version_r); + + _arm32_elf_add_rela_plt(arm32, &arm32->rela_plt); + _arm32_elf_add_plt(arm32, &arm32->plt); + + _arm32_elf_add_dynamic(arm32, &arm32->dynamic); + _arm32_elf_add_got_plt(arm32, &arm32->got_plt); + + scf_string_t* str = scf_string_alloc(); + + char c = '\0'; + scf_string_cat_cstr_len(str, &c, 1); + + Elf32_Sym* syms = (Elf32_Sym* )arm32->dynsym->data; + Elf32_Sym sym0 = {0}; + + sym0.st_info = ELF32_ST_INFO(STB_LOCAL, STT_NOTYPE); + memcpy(&syms[0], &sym0, sizeof(Elf32_Sym)); + + for (i = 0; i < arm32->dynsyms->size; i++) { + elf_sym_t* xsym = arm32->dynsyms->data[i]; + + memcpy(&syms[i + 1], &xsym->sym, sizeof(Elf32_Sym)); + + syms[i + 1].st_name = str->len; + + scf_loge("i: %d, st_value: %#x\n", i, syms[i + 1].st_value); + + scf_string_cat_cstr_len(str, xsym->name->data, xsym->name->len + 1); + } + +#if 0 + Elf32_Verneed* verneeds = (Elf32_Verneed*) arm32->gnu_version_r->data; + Elf32_Vernaux* vernauxs = (Elf32_Vernaux*)(arm32->gnu_version_r->data +sizeof(Elf32_Verneed)); + + verneeds[0].vn_version = VER_NEED_CURRENT; + verneeds[0].vn_file = str->len; + verneeds[0].vn_cnt = 1; + verneeds[0].vn_aux = sizeof(Elf32_Verneed); + verneeds[0].vn_next = 0; + + scf_string_cat_cstr_len(str, "libc.so.6", strlen("libc.so.6") + 1); + + vernauxs[0].vna_hash = _arm32_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 + + Elf32_Dyn* dyns = (Elf32_Dyn*)arm32->dynamic->data; + + size_t prefix = strlen("../lib/arm32/"); + + for (i = 0; i < arm32->dyn_needs->size; i++) { + scf_string_t* needed = arm32->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)arm32->dynstr; + dyns[i + 1].d_un.d_ptr = (uintptr_t)arm32->dynsym; + dyns[i + 2].d_un.d_val = str->len; + dyns[i + 3].d_un.d_val = sizeof(Elf32_Sym); + dyns[i + 4].d_un.d_ptr = (uintptr_t)arm32->got_plt; + dyns[i + 5].d_un.d_ptr = sizeof(Elf32_Rela); + dyns[i + 6].d_un.d_ptr = DT_RELA; + dyns[i + 7].d_un.d_ptr = (uintptr_t)arm32->rela_plt; +// dyns[i + 8].d_un.d_ptr = (uintptr_t)arm32->gnu_version_r; +// dyns[i + 9].d_un.d_ptr = 1; +// dyns[i +10].d_un.d_ptr = (uintptr_t)arm32->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); + + arm32->dynstr->data = str->data; + arm32->dynstr->data_len = str->len; + + str->data = NULL; + str->len = 0; + str->capacity = 0; + scf_string_free(str); + str = NULL; + + arm32->rela_plt->link = arm32->dynsym; + arm32->rela_plt->info = arm32->got_plt; + arm32->dynsym ->link = arm32->dynstr; +#if 0 + arm32->gnu_version_r->link = arm32->dynstr; + arm32->gnu_version_r->info = arm32->interp; +#endif + + for (i = 0; i < arm32->sections->size; i++) { + s = arm32->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(arm32->sections->data, arm32->sections->size, sizeof(void*), _section_cmp); + + int j = sizeof(sh_names) / sizeof(sh_names[0]); + + for (i = j; i < arm32->sections->size; i++) { + s = arm32->sections->data[i]; + + s->index = i + 1; + } + + for (i = 0; i < arm32->sections->size; i++) { + s = arm32->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 (s == arm32->dynstr) + dyns[arm32->dyn_needs->size].d_un.d_ptr = i; + + else if (arm32->dynsym == s) + dyns[arm32->dyn_needs->size + 1].d_un.d_ptr = i; + + else if (arm32->got_plt == s) + dyns[arm32->dyn_needs->size + 4].d_un.d_ptr = i; + + else if (arm32->rela_plt == s) + dyns[arm32->dyn_needs->size + 7].d_un.d_ptr = i; + } + + for (i = 0; i < arm32->symbols->size; i++) { + sym = arm32->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; + } + } + + return 0; +} + +int __arm32_elf_post_dyn(elf_native_t* arm32, uint64_t rx_base, uint64_t rw_base, elf_section_t* cs) +{ + uint64_t cs_base = rx_base + cs->offset; + +// arm32->gnu_version_r->sh.sh_addr = rx_base + arm32->gnu_version_r->offset; + + arm32->rela_plt->sh.sh_addr = rx_base + arm32->rela_plt->offset; + arm32->dynamic->sh.sh_addr = rw_base + arm32->dynamic->offset; + arm32->got_plt->sh.sh_addr = rw_base + arm32->got_plt->offset; + arm32->interp->sh.sh_addr = rx_base + arm32->interp->offset; + arm32->plt->sh.sh_addr = rx_base + arm32->plt->offset; + + scf_loge("rw_base: %#lx, offset: %#lx\n", rw_base, arm32->got_plt->offset); + scf_loge("got_addr: %#x\n", arm32->got_plt->sh.sh_addr); + + Elf32_Rela* r; + Elf32_Rela* rela_plt = (Elf32_Rela*)arm32->rela_plt->data; + Elf32_Dyn* dtags = (Elf32_Dyn* )arm32->dynamic->data; + Elf32_Sym* dynsym = (Elf32_Sym* )arm32->dynsym->data; + uint32_t* got_plt = (uint32_t* )arm32->got_plt->data; + uint32_t* plt = (uint32_t* )arm32->plt->data; + + uint64_t got_addr = arm32->got_plt->sh.sh_addr; + uint64_t plt_addr = arm32->plt->sh.sh_addr; + int32_t offset = got_addr - plt_addr; + + got_plt[0] = arm32->dynamic->sh.sh_addr; + got_plt[1] = 0; + got_plt[2] = 0; + got_plt[3] = arm32->plt->sh.sh_addr; + got_plt += 4; + got_addr +=16; + + scf_loge("got_addr: %#lx, plt_addr: %#lx, offset: %d, %#x\n", got_addr, plt_addr, offset, offset); + + plt[4] = offset - 16; + + plt_addr += sizeof(arm32_plt_lazy); + plt += sizeof(arm32_plt_lazy) / sizeof(arm32_plt_lazy[0]); + + int i; + for (i = 0; i < arm32->dynsyms->size; i++) { + rela_plt[i].r_offset = got_addr; + rela_plt[i].r_addend = 0; + rela_plt[i].r_info = ELF32_R_INFO(i + 1, R_ARM_JUMP_SLOT); + + *got_plt = arm32->plt->sh.sh_addr; + + offset = got_addr - plt_addr - 8; // 'pc = current + 8' + + scf_loge("i: %d, got_addr: %#lx, plt_addr: %#lx, offset: %d, %#x\n", i, got_addr, plt_addr, offset, offset); + + scf_logw("got_plt[%d]: %#x\n", i, *got_plt); + + if (offset > 0xfffffff) { + scf_loge("\n"); + return -EINVAL; + } + + plt[0] |= (offset >> 20) & 0xff; + plt[1] |= (offset >> 12) & 0xff; + plt[2] |= offset & 0xfff; + + plt += sizeof(arm32_plt) / sizeof(arm32_plt[0]); + plt_addr += sizeof(arm32_plt); + got_addr += 4; + got_plt++; + } + + for (i = 0; i < arm32->dyn_relas->size; i++) { + r = arm32->dyn_relas->data[i]; + + int sym_idx = ELF32_R_SYM(r->r_info); + assert(sym_idx > 0); + + assert(ELF32_R_TYPE(r->r_info) == R_ARM_CALL); + + uint64_t plt_addr = arm32->plt->sh.sh_addr + sizeof(arm32_plt_lazy) + (sym_idx - 1) * sizeof(arm32_plt); + + int32_t offset = plt_addr - (cs_base + r->r_offset) + r->r_addend - 8; // 'pc' is 'current + 8' + + assert(0 == (offset & 0x3)); + + offset >>= 2; + + if (offset > 0x7fffff || offset < -0x7fffff) { + scf_loge("\n"); + return -EINVAL; + } + + offset &= 0xffffff; + offset |= (0xeb << 24); + + *(uint32_t*)(cs->data + r->r_offset) = offset; + } + + for (i = arm32->dyn_needs->size; i < arm32->dynamic->data_len / sizeof(Elf32_Dyn); i++) { + + elf_section_t* s; + + switch (dtags[i].d_tag) { + + case DT_SYMTAB: + case DT_STRTAB: + case DT_JMPREL: + s = arm32->sections->data[dtags[i].d_un.d_ptr]; + + dtags[i].d_un.d_ptr = s->offset + rx_base; + s->sh.sh_addr = s->offset + rx_base; + break; + + case DT_PLTGOT: + s = arm32->sections->data[dtags[i].d_un.d_ptr]; + + dtags[i].d_un.d_ptr = s->offset + rw_base; + s->sh.sh_addr = s->offset + rw_base; + break; + default: + break; + }; + } + + return 0; +} + +int __arm32_elf_write_phdr(scf_elf_context_t* elf, uint64_t rx_base, uint64_t offset, uint32_t nb_phdrs) +{ + // write program header + + Elf32_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(Elf32_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 __arm32_elf_write_interp(scf_elf_context_t* elf, uint64_t rx_base, uint64_t offset, uint64_t len) +{ + Elf32_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 __arm32_elf_write_text(scf_elf_context_t* elf, uint64_t rx_base, uint64_t offset, uint64_t len) +{ + Elf32_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 __arm32_elf_write_rodata(scf_elf_context_t* elf, uint64_t r_base, uint64_t offset, uint64_t len) +{ + Elf32_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 __arm32_elf_write_data(scf_elf_context_t* elf, uint64_t rw_base, uint64_t offset, uint64_t len) +{ + Elf32_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 __arm32_elf_write_dynamic(scf_elf_context_t* elf, uint64_t rw_base, uint64_t offset, uint64_t len) +{ + Elf32_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(Elf32_Phdr), 1, elf->fp); + return 0; +} + diff --git a/elf/scf_elf_link.c b/elf/scf_elf_link.c index 514f16f..c1de02e 100644 --- a/elf/scf_elf_link.c +++ b/elf/scf_elf_link.c @@ -274,9 +274,17 @@ int scf_elf_file_read(scf_elf_file_t* ef) #define ELF_READ_RELAS(sname) \ do { \ int ret = scf_elf_read_relas(ef->elf, ef->sname##_relas, ".rela."#sname); \ - if (ret < 0 && ret != -404) { \ - scf_loge("\n"); \ - return ret; \ + if (ret < 0) { \ + if (ret != -404) { \ + scf_loge("\n"); \ + return ret; \ + } \ + \ + ret = scf_elf_read_relas(ef->elf, ef->sname##_relas, ".rel."#sname); \ + if (ret < 0 && ret != -404) { \ + scf_loge("\n"); \ + return ret; \ + } \ } \ } while(0); @@ -425,7 +433,7 @@ sym_error: return ret; } -static int merge_relas(scf_vector_t* dst, scf_vector_t* src, size_t offset, int nb_syms) +static int merge_relas(scf_vector_t* dst, scf_vector_t* src, size_t offset, int nb_syms, const int bits) { scf_elf_rela_t* rela; scf_elf_rela_t* rela2; @@ -435,7 +443,11 @@ static int merge_relas(scf_vector_t* dst, scf_vector_t* src, size_t offset, int rela2 = src->data[j]; rela2->r_offset += offset; - rela2->r_info = ELF64_R_INFO(ELF64_R_SYM(rela2->r_info) + nb_syms, ELF64_R_TYPE(rela2->r_info)); + + if (64 == bits) + rela2->r_info = ELF64_R_INFO(ELF64_R_SYM(rela2->r_info) + nb_syms, ELF64_R_TYPE(rela2->r_info)); + else + rela2->r_info = ELF32_R_INFO(ELF32_R_SYM(rela2->r_info) + nb_syms, ELF32_R_TYPE(rela2->r_info)); rela = calloc(1, sizeof(scf_elf_rela_t)); if (!rela) @@ -453,6 +465,8 @@ static int merge_relas(scf_vector_t* dst, scf_vector_t* src, size_t offset, int return -ENOMEM; } + scf_logw("j: %d, nb_syms: %d:%ld, sym: %s\n", j, nb_syms, ELF32_R_SYM(rela2->r_info), rela2->name); + rela->r_offset = rela2->r_offset; rela->r_info = rela2->r_info; rela->r_addend = rela2->r_addend; @@ -517,6 +531,8 @@ static int merge_syms(scf_elf_file_t* exec, scf_elf_file_t* obj) return -ENOMEM; } + scf_loge("sym: %d, %s\n", exec->syms->size, sym->name); + if (scf_vector_add(exec->syms, sym) < 0) { scf_loge("\n"); return -ENOMEM; @@ -531,13 +547,13 @@ static int merge_syms(scf_elf_file_t* exec, scf_elf_file_t* obj) return 0; } -static int merge_obj(scf_elf_file_t* exec, scf_elf_file_t* obj) +static int merge_obj(scf_elf_file_t* exec, scf_elf_file_t* obj, const int bits) { int nb_syms = exec->syms->size; #define MERGE_RELAS(dst, src, offset) \ do { \ - int ret = merge_relas(dst, src, offset, nb_syms); \ + int ret = merge_relas(dst, src, offset, nb_syms, bits); \ if (ret < 0) { \ scf_loge("\n"); \ return ret; \ @@ -581,7 +597,14 @@ static int merge_obj(scf_elf_file_t* exec, scf_elf_file_t* obj) static int merge_objs(scf_elf_file_t* exec, char* inputs[], int nb_inputs, const char* arch) { int nb_syms = 0; + int bits; int i; + + if (!strcmp(arch, "x64") || !strcmp(arch, "arm64") || !strcmp(arch, "naja")) + bits = 64; + else + bits = 32; + for (i = 0; i < nb_inputs; i++) { scf_elf_sym_t* sym; @@ -599,7 +622,9 @@ static int merge_objs(scf_elf_file_t* exec, char* inputs[], int nb_inputs, const return -1; } - int ret = merge_obj(exec, obj); + scf_loge("i: %d, input: %s\n", i, inputs[i]); + + int ret = merge_obj(exec, obj, bits); if (ret < 0) { scf_loge("\n"); return -1; @@ -612,14 +637,19 @@ static int merge_objs(scf_elf_file_t* exec, char* inputs[], int nb_inputs, const return 0; } -static int _find_sym(scf_elf_sym_t** psym, scf_elf_rela_t* rela, scf_vector_t* symbols) +static int _find_sym(scf_elf_sym_t** psym, scf_elf_rela_t* rela, scf_vector_t* symbols, const int bits) { scf_elf_sym_t* sym; scf_elf_sym_t* sym2; - int sym_idx = ELF64_R_SYM(rela->r_info); + int sym_idx; int j; + if (64 == bits) + sym_idx = ELF64_R_SYM(rela->r_info); + else + sym_idx = ELF32_R_SYM(rela->r_info); + assert(sym_idx >= 1); assert(sym_idx - 1 < symbols->size); @@ -716,6 +746,12 @@ static int merge_ar_obj(scf_elf_file_t* exec, scf_ar_file_t* ar, uint32_t offset { scf_elf_file_t* obj = NULL; + int bits; + if (!strcmp(arch, "x64") || !strcmp(arch, "arm64") || !strcmp(arch, "naja")) + bits = 64; + else + bits = 32; + int ret = __scf_elf_file_open(&obj); if (ret < 0) { scf_loge("\n"); @@ -741,7 +777,7 @@ static int merge_ar_obj(scf_elf_file_t* exec, scf_ar_file_t* ar, uint32_t offset return -1; } - ret = merge_obj(exec, obj); + ret = merge_obj(exec, obj, bits); if (ret < 0) { scf_loge("\n"); return -1; @@ -801,6 +837,12 @@ static int link_relas(scf_elf_file_t* exec, char* afiles[], int nb_afiles, char* scf_vector_t* dlls = scf_vector_alloc(); int i; + int bits; + if (!strcmp(arch, "x64") || !strcmp(arch, "arm64") || !strcmp(arch, "naja")) + bits = 64; + else + bits = 32; + for (i = 0; i < nb_afiles; i++) { if (scf_ar_file_open(&ar, afiles[i]) < 0) { @@ -831,15 +873,19 @@ static int link_relas(scf_elf_file_t* exec, char* afiles[], int nb_afiles, char* rela = exec->text_relas->data[i]; sym = NULL; - int sym_idx = _find_sym(&sym, rela, exec->syms); + int sym_idx = _find_sym(&sym, rela, exec->syms, bits); if (sym_idx >= 0) { i++; continue; } - sym_idx = ELF64_R_SYM(rela->r_info); - sym = exec->syms->data[sym_idx - 1]; + if (64 == bits) + sym_idx = ELF64_R_SYM(rela->r_info); + else + sym_idx = ELF32_R_SYM(rela->r_info); + + sym = exec->syms->data[sym_idx - 1]; uint32_t offset = 0; uint32_t size = 0; @@ -896,7 +942,10 @@ static int link_relas(scf_elf_file_t* exec, char* afiles[], int nb_afiles, char* scf_vector_del(exec->text_relas, rela); scf_vector_add(exec->rela_plt, rela); - rela->r_info = ELF64_R_INFO(j + 1, ELF64_R_TYPE(rela->r_info)); + if (64 == bits) + rela->r_info = ELF64_R_INFO(j + 1, ELF64_R_TYPE(rela->r_info)); + else + rela->r_info = ELF32_R_INFO(j + 1, ELF32_R_TYPE(rela->r_info)); scf_loge("j: %d, sym: %s, r_offset: %#lx, r_addend: %ld\n", j, sym->name, rela->r_offset, rela->r_addend); @@ -906,13 +955,17 @@ static int link_relas(scf_elf_file_t* exec, char* afiles[], int nb_afiles, char* rela = exec->data_relas->data[i]; sym = NULL; - int sym_idx = _find_sym(&sym, rela, exec->syms); + int sym_idx = _find_sym(&sym, rela, exec->syms, bits); if (sym_idx >= 0) continue; - sym_idx = ELF64_R_SYM(rela->r_info); - sym = exec->syms->data[sym_idx - 1]; + if (64 == bits) + sym_idx = ELF64_R_SYM(rela->r_info); + else + sym_idx = ELF32_R_SYM(rela->r_info); + + sym = exec->syms->data[sym_idx - 1]; uint32_t offset = 0; uint32_t size = 0; @@ -942,7 +995,10 @@ static int link_relas(scf_elf_file_t* exec, char* afiles[], int nb_afiles, char* for (j = 0; j < so->rela_plt->size; j++) { rela = so->rela_plt->data[j]; - sym_idx = ELF64_R_SYM(rela->r_info); + if (64 == bits) + sym_idx = ELF64_R_SYM(rela->r_info); + else + sym_idx = ELF32_R_SYM(rela->r_info); if (sym_idx <= 0) continue; diff --git a/elf/scf_elf_native.h b/elf/scf_elf_native.h index 179b4b5..d36abc1 100644 --- a/elf/scf_elf_native.h +++ b/elf/scf_elf_native.h @@ -90,6 +90,9 @@ int elf_read_syms (scf_elf_context_t* elf, scf_vector_t* syms, const char* s 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 elf32_find_sym (elf_sym_t** psym, Elf32_Rela* rela, scf_vector_t* symbols); +void elf32_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); diff --git a/elf/scf_elf_native32.c b/elf/scf_elf_native32.c new file mode 100644 index 0000000..70384a8 --- /dev/null +++ b/elf/scf_elf_native32.c @@ -0,0 +1,1098 @@ +#include"scf_elf_native32.h" +#include"scf_elf_link.h" + +int elf32_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 = 4; + + 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 elf32_close(scf_elf_context_t* elf) +{ + elf_native_t* e = elf->priv; + + if (e) { + free(e); + e = NULL; + } + return 0; +} + +int elf32_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 elf32_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 elf32_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(Elf32_Rela); + + s->data_len = sizeof(Elf32_Rela) * relas->size; + + s->data = malloc(s->data_len); + if (!s->data) { + scf_string_free(s->name); + free(s); + return -ENOMEM; + } + + Elf32_Rela* pr = (Elf32_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 elf32_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(Elf32_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(Elf32_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 = elf32_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(Elf32_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; +} + +int elf32_read_phdrs(scf_elf_context_t* elf, scf_vector_t* phdrs) +{ + elf_native_t* e = elf->priv; + scf_elf_phdr_t* ph; + Elf32_Ehdr eh; + + if (!e || !elf->fp) + return -1; + + if (!elf->fp) + return -EINVAL; + + int ret = fseek(elf->fp, elf->start, SEEK_SET); + if (ret < 0) + return ret; + + ret = fread(&eh, sizeof(Elf32_Ehdr), 1, elf->fp); + if (ret != 1) + return -1; + + if (ELFMAG0 != eh.e_ident[EI_MAG0] + || ELFMAG1 != eh.e_ident[EI_MAG1] + || ELFMAG2 != eh.e_ident[EI_MAG2] + || ELFMAG3 != eh.e_ident[EI_MAG3]) { + + scf_loge("not elf file\n"); + return -1; + } + + fseek(elf->fp, elf->start + eh.e_phoff, SEEK_SET); + + int i; + for (i = 0; i < eh.e_phnum; i++) { + + ph = calloc(1, sizeof(scf_elf_phdr_t)); + if (!ph) + return -ENOMEM; + + ret = fread(&ph->ph, sizeof(Elf32_Phdr), 1, elf->fp); + + if (ret != 1) { + free(ph); + return -1; + } + + if (scf_vector_add(phdrs, ph) < 0) { + free(ph); + return -ENOMEM; + } + } + + return 0; +} + +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 = elf32_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(Elf32_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 elf32_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(Elf32_Sym) == 0); + + scf_loge("0: syms->size: %d, %ld\n", syms->size, symtab->data_len / sizeof(Elf32_Sym)); + + scf_elf_sym_t* esym; + Elf32_Sym* sym; + int i; + int j = 0; + for (i = 0; i < symtab->data_len; i += sizeof(Elf32_Sym)) { + + sym = (Elf32_Sym*)(symtab->data + i); + + assert(sym->st_name < strtab->data_len); + + if (STT_NOTYPE == sym->st_info && 0 == i) { + j++; + 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; + } + } + + scf_loge("1: j: %d, syms->size: %d, %ld\n", j, syms->size, symtab->data_len / sizeof(Elf32_Sym)); + + return 0; +} + +int elf32_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 elf32_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; + } + + Elf32_Rela* r = calloc(1, sizeof(Elf32_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 elf32_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; + + scf_elf_rela_t* erela; + elf_section_t* sh_rela = NULL; + elf_section_t* symtab = NULL; + elf_section_t* strtab = NULL; + Elf32_Rela* rela; + Elf32_Rel* rel; + Elf32_Sym* sym; + + char* symtab_name = NULL; + char* strtab_name = NULL; + int i; + + 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; + } + + + if (SHT_RELA == sh_rela->sh.sh_type) { + + assert(sh_rela->data_len % sizeof(Elf32_Rela) == 0); + + for (i = 0; i < sh_rela->data_len; i += sizeof(Elf32_Rela)) { + + rela = (Elf32_Rela*)(sh_rela->data + i); + + int sym_idx = ELF32_R_SYM(rela->r_info); + + assert(sym_idx < symtab->data_len / sizeof(Elf32_Sym)); + + sym = (Elf32_Sym*)(symtab->data + sym_idx * sizeof(Elf32_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; + } + } + + } else { + assert(sh_rela->data_len % sizeof(Elf32_Rel) == 0); + + for (i = 0; i < sh_rela->data_len; i += sizeof(Elf32_Rel)) { + + rel = (Elf32_Rel*)(sh_rela->data + i); + + int sym_idx = ELF32_R_SYM(rel->r_info); + + assert(sym_idx < symtab->data_len / sizeof(Elf32_Sym)); + + sym = (Elf32_Sym*)(symtab->data + sym_idx * sizeof(Elf32_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 = rel->r_offset; + erela->r_info = rel->r_info; + + if (scf_vector_add(relas, erela) < 0) { + scf_loge("\n"); + free(erela); + return -ENOMEM; + } + } + } + + return 0; +} + +int elf32_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 elf32_write_symtab(scf_elf_context_t* elf) +{ + elf_native_t* e = elf->priv; + Elf32_Sym s0 = {0}; + elf_sym_t* s; + + s0.st_info = ELF32_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 elf32_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 elf32_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 elf32_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 elf32_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(Elf32_Sym ) * (e->symbols->size + 1); + Elf32_Off offset = sizeof(Elf32_Ehdr) + sizeof(Elf32_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 = 4; + + 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 == ELF32_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(Elf32_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); + + elf32_write_sections(elf); // write user's section data + + elf32_write_symtab (elf); // write .symtab data (user's symbols) + elf32_write_strtab (elf); // write .strtab data (symbol names of symtab) + elf32_write_shstrtab(elf); // write .shstrtab data (section names of all sections) + return 0; +} + +int elf32_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 == ELF32_ST_BIND(sym0->sym.st_info)) { + + if (STB_GLOBAL == ELF32_ST_BIND(sym1->sym.st_info)) + return -1; + + } else if (STB_LOCAL == ELF32_ST_BIND(sym1->sym.st_info)) + return 1; + + return 0; +} + +int elf32_find_sym(elf_sym_t** psym, Elf32_Rela* rela, scf_vector_t* symbols) +{ + elf_sym_t* sym; + elf_sym_t* sym2; + + int sym_idx = ELF32_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 == ELF32_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 (ELF32_ST_TYPE(sym->sym.st_info) == STT_SECTION) { + + for (j = symbols->size - 1; j >= 0; j--) { + sym2 = symbols->data[j]; + + if (ELF32_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 elf32_process_syms(elf_native_t* e, uint32_t cs_index) +{ + elf_section_t* s; + Elf32_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 == ELF32_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*), elf32_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(Elf32_Rela) == 0); + + int sym_idx; + for (k = 0; k < s->data_len; k += sizeof(Elf32_Rela)) { + + rela = (Elf32_Rela*)(s->data + k); + + sym_idx = ELF32_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 = ELF32_R_INFO(i + 1, ELF32_R_TYPE(rela->r_info)); + } + } +} + diff --git a/elf/scf_elf_native32.h b/elf/scf_elf_native32.h new file mode 100644 index 0000000..ca53874 --- /dev/null +++ b/elf/scf_elf_native32.h @@ -0,0 +1,154 @@ +#ifndef SCF_ELF_NATIVE32_H +#define SCF_ELF_NATIVE32_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; + + Elf32_Shdr sh; + + uint64_t offset; + + uint16_t index; + uint8_t* data; + int data_len; +}; + +typedef struct { + elf_section_t* section; + + scf_string_t* name; + + Elf32_Sym sym; + + int index; + uint8_t dyn_flag:1; + +} elf_sym_t; + +typedef struct { + Elf32_Ehdr eh; + + Elf32_Shdr sh_null; + + scf_vector_t* sections; + scf_vector_t* phdrs; + + Elf32_Shdr sh_symtab; + scf_vector_t* symbols; + + Elf32_Shdr sh_strtab; + + Elf32_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 elf32_open (scf_elf_context_t* elf); +int elf32_close(scf_elf_context_t* elf); + +int elf32_add_sym (scf_elf_context_t* elf, const scf_elf_sym_t* sym, const char* sh_name); +int elf32_add_section (scf_elf_context_t* elf, const scf_elf_section_t* section); +int elf32_add_rela_section(scf_elf_context_t* elf, const scf_elf_section_t* section, scf_vector_t* relas); + +int elf32_read_shstrtab(scf_elf_context_t* elf); +int elf32_read_section (scf_elf_context_t* elf, scf_elf_section_t** psection, const char* name); + +int elf32_add_dyn_need(scf_elf_context_t* elf, const char* soname); +int elf32_add_dyn_rela(scf_elf_context_t* elf, const scf_elf_rela_t* rela); + +int elf32_read_phdrs (scf_elf_context_t* elf, scf_vector_t* phdrs); +int elf32_read_relas (scf_elf_context_t* elf, scf_vector_t* relas, const char* sh_name); +int elf32_read_syms (scf_elf_context_t* elf, scf_vector_t* syms, const char* sh_name); + +int elf32_find_sym (elf_sym_t** psym, Elf32_Rela* rela, scf_vector_t* symbols); +void elf32_process_syms(elf_native_t* native, uint32_t cs_index); + +int elf32_write_sections(scf_elf_context_t* elf); +int elf32_write_shstrtab(scf_elf_context_t* elf); +int elf32_write_symtab (scf_elf_context_t* elf); +int elf32_write_strtab (scf_elf_context_t* elf); +int elf32_write_rel (scf_elf_context_t* elf, uint16_t e_machine); + +int elf32_sym_cmp(const void* v0, const void* v1); + +static inline void elf_header(Elf32_Ehdr* eh, + uint16_t e_type, + uint16_t e_machine, + Elf32_Addr e_entry, + Elf32_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] = ELFCLASS32; + 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(Elf32_Ehdr); + + eh->e_flags = 0x5000400; + + eh->e_phoff = e_phoff; + eh->e_phentsize = sizeof(Elf32_Phdr); + eh->e_phnum = e_phnum; + + eh->e_shoff = sizeof(Elf32_Ehdr); + eh->e_shentsize = sizeof(Elf32_Shdr); + eh->e_shnum = e_shnum; + eh->e_shstrndx = e_shstrndx; +} + +static inline void section_header(Elf32_Shdr* sh, + uint32_t sh_name, + Elf32_Addr sh_addr, + Elf32_Off sh_offset, + uint64_t sh_size, + uint32_t sh_link, + uint32_t sh_info, + uint64_t sh_entsize) +{ + sh->sh_name = sh_name; + sh->sh_addr = sh_addr; + sh->sh_offset = sh_offset; + sh->sh_size = sh_size; + sh->sh_link = sh_link; + sh->sh_info = sh_info; + sh->sh_entsize = sh_entsize; +} + +#endif + diff --git a/lib/arm32/_start.o b/lib/arm32/_start.o new file mode 100644 index 0000000..9aa3713 Binary files /dev/null and b/lib/arm32/_start.o differ diff --git a/lib/arm32/_start.s b/lib/arm32/_start.s new file mode 100644 index 0000000..cc8b58a --- /dev/null +++ b/lib/arm32/_start.s @@ -0,0 +1,8 @@ +.text +.global _start, main + +_start: + bl main + mov r7, #1 + swi #0 +.fill 4, 1, 0 diff --git a/lib/arm32/lib/ld-linux-armhf.so.3 b/lib/arm32/lib/ld-linux-armhf.so.3 new file mode 100755 index 0000000..27cf789 Binary files /dev/null and b/lib/arm32/lib/ld-linux-armhf.so.3 differ diff --git a/lib/arm32/libc.so.6 b/lib/arm32/libc.so.6 new file mode 100755 index 0000000..9a76155 Binary files /dev/null and b/lib/arm32/libc.so.6 differ diff --git a/native/risc/scf_arm32.c b/native/risc/scf_arm32.c new file mode 100644 index 0000000..20e6d94 --- /dev/null +++ b/native/risc/scf_arm32.c @@ -0,0 +1,1954 @@ +#include"scf_risc.h" + +int arm32_inst_I2G(scf_3ac_code_t* c, scf_register_t* rd, uint64_t imm, int bytes) +{ + scf_instruction_t* inst; + + uint32_t opcode; + + // mov rd, imm[15:0] + opcode = (0xe3 << 24) | (((imm >> 12 ) & 0xf) << 16) | (rd->id << 12) | (imm & 0xfff); + inst = risc_make_inst(c, opcode); + RISC_INST_ADD_CHECK(c->instructions, inst); + + imm >>= 16; + if (imm & 0xffff) { + + // movk rd, imm[31:16] + opcode = (0xe3 << 24) | (0x1 << 22) | (((imm >> 12 ) & 0xf) << 16) | (rd->id << 12) | (imm & 0xfff); + inst = risc_make_inst(c, opcode); + RISC_INST_ADD_CHECK(c->instructions, inst); + } + + return 0; +} + +int arm32_inst_ADR2G(scf_3ac_code_t* c, scf_function_t* f, scf_register_t* rd, scf_variable_t* vs) +{ + scf_register_t* fp = f->rops->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 = f->rops->variable_size(vs); + + if (vs->local_flag || vs->tmp_flag) { + + offset = vs->bp_offset; + + if (offset >= 0 && offset <= 0xff) + + opcode = (0xe2 << 24) | (0x8 << 20) | (fp->id << 16) | (rd->id << 12) | offset; + + else if (offset < 0 && -offset <= 0xff) + + opcode = (0xe2 << 24) | (0x4 << 20) | (fp->id << 16) | (rd->id << 12) | (-offset); + + else { + int ret = arm32_inst_I2G(c, rd, offset, 4); + if (ret < 0) + return ret; + + opcode = (0xe0 << 24) | (0x8 << 20) | (fp->id << 16) | (rd->id << 12) | rd->id; + } + + inst = risc_make_inst(c, opcode); + RISC_INST_ADD_CHECK(c->instructions, inst); + + } else if (vs->global_flag) { + offset = 0; + + opcode = (0xe3 << 24) | (rd->id << 12); + 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_ARM_REL32; + + opcode = (0xe3 << 24) | (0x4 << 20) | (rd->id << 12); + inst = risc_make_inst(c, opcode); + RISC_INST_ADD_CHECK(c->instructions, inst); + + opcode = (0xe7 << 24) | (0x9 << 20) | (rd->id << 16) | (rd->id << 12) | 0xf; + inst = risc_make_inst(c, opcode); + RISC_INST_ADD_CHECK(c->instructions, inst); + + opcode = (0xe0 << 24) | (0x8 << 20) | (rd->id << 16) | (rd->id << 12) | 0xf; + inst = risc_make_inst(c, opcode); + RISC_INST_ADD_CHECK(c->instructions, inst); + + } else { + scf_loge("temp var should give a register\n"); + return -EINVAL; + } + + return 0; +} + +int arm32_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 = f->rops->find_register("fp"); + scf_register_t* ri = NULL; + scf_instruction_t* inst = NULL; + scf_rela_t* rela = NULL; + + int32_t offset; + uint32_t opcode; + + int size = f->rops->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; + + opcode = (0xe3 << 24) | (rd->id << 12); + 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_ARM_REL32; + + opcode = (0xe3 << 24) | (0x4 << 20) | (rd->id << 12); + inst = risc_make_inst(c, opcode); + RISC_INST_ADD_CHECK(c->instructions, inst); + + opcode = (0xe7 << 24) | (0x9 << 20) | (rd->id << 16) | (rd->id << 12) | 0xf; + inst = risc_make_inst(c, opcode); + RISC_INST_ADD_CHECK(c->instructions, inst); + + opcode = (0xe0 << 24) | (0x8 << 20) | (rd->id << 16) | (rd->id << 12) | 0xf; + inst = risc_make_inst(c, opcode); + RISC_INST_ADD_CHECK(c->instructions, inst); + + 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) { + + if (scf_variable_signed(vs)) { + + if (offset >= 0 && offset < 0xff) + opcode = (0xe1 << 24) | (0xd << 20) | (rb->id << 16) | (rd->id << 12) | (((offset & 0xf0) | 0xd) << 4) | (offset & 0xf); + + else if (offset < 0 && offset >= -0xff) { + offset = -offset; + opcode = (0xe1 << 24) | (0x5 << 20) | (rb->id << 16) | (rd->id << 12) | (((offset & 0xf0) | 0xd) << 4) | (offset & 0xf); + + } else { + int ret = risc_select_free_reg(&ri, c, f, 0); + if (ret < 0) { + scf_loge("\n"); + return -EINVAL; + } + + ret = arm32_inst_I2G(c, ri, offset, 4); + if (ret < 0) + return ret; + + opcode = (0xe1 << 24) | (0x9 << 20) | (rb->id << 16) | (rd->id << 12) | (0xd << 4) | ri->id; + } + + } else { + if (offset >= 0 && offset < 0xfff) + opcode = (0xe5 << 24) | (0xd << 20) | (rb->id << 16) | (rd->id << 12) | offset; + + else if (offset < 0 && offset >= -0xfff) { + offset = -offset; + opcode = (0xe5 << 24) | (0x5 << 20) | (rb->id << 16) | (rd->id << 12) | offset; + + } else { + int ret = risc_select_free_reg(&ri, c, f, 0); + if (ret < 0) { + scf_loge("\n"); + return -EINVAL; + } + + ret = arm32_inst_I2G(c, ri, offset, 4); + if (ret < 0) + return ret; + + opcode = (0xe7 << 24) | (0xd << 20) | (rb->id << 16) | (rd->id << 12) | ri->id; + } + } + + } else if (2 == size) { + + if (offset & 0x1) { + scf_loge("memory align error\n"); + return -EINVAL; + } + + if (offset >= 0 && offset < 0xff) + opcode = (0xe1 << 24) | (0xd << 20) | (rb->id << 16) | (rd->id << 12) | (((offset & 0xf0) | 0xb) << 4) | (offset & 0xf); + + else if (offset < 0 && offset >= -0xff) { + offset = -offset; + opcode = (0xe1 << 24) | (0x5 << 20) | (rb->id << 16) | (rd->id << 12) | (((offset & 0xf0) | 0xb) << 4) | (offset & 0xf); + + } else { + int ret = risc_select_free_reg(&ri, c, f, 0); + if (ret < 0) { + scf_loge("\n"); + return -EINVAL; + } + + ret = arm32_inst_I2G(c, ri, offset, 4); + if (ret < 0) + return ret; + + opcode = (0xe1 << 24) | (0x9 << 20) | (rb->id << 16) | (rd->id << 12) | (0xb << 4) | ri->id; + } + + if (scf_variable_signed(vs)) + opcode |= 0x1 << 6; + + } else if (4 == size) { + + if (offset & 0x3) { + scf_loge("memory align error\n"); + return -EINVAL; + } + + if (offset >= 0 && offset < 0xfff) + opcode = (0xe5 << 24) | (0x9 << 20) | (rb->id << 16) | (rd->id << 12) | offset; + + else if (offset < 0 && offset >= -0xfff) { + offset = -offset; + opcode = (0xe5 << 24) | (0x1 << 20) | (rb->id << 16) | (rd->id << 12) | offset; + + } else { + int ret = risc_select_free_reg(&ri, c, f, 0); + if (ret < 0) { + scf_loge("\n"); + return -EINVAL; + } + + ret = arm32_inst_I2G(c, ri, offset, 4); + if (ret < 0) + return ret; + + opcode = (0xe7 << 24) | (0x9 << 20) | (rb->id << 16) | (rd->id << 12) | ri->id; + } + + } else + return -EINVAL; + + inst = risc_make_inst(c, opcode); + RISC_INST_ADD_CHECK(c->instructions, inst); + return 0; +} + +int arm32_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 = f->rops->find_register("fp"); + scf_register_t* ri = NULL; + scf_instruction_t* inst = NULL; + scf_rela_t* rela = NULL; + + int32_t offset; + uint32_t opcode; + + int size = f->rops->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 = arm32_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) { + + if (offset >= 0 && offset < 0xfff) + opcode = (0xe5 << 24) | (0xc << 20) | (rb->id << 16) | (rs->id << 12) | offset; + + else if (offset < 0 && offset >= -0xfff) { + offset = -offset; + opcode = (0xe5 << 24) | (0x4 << 20) | (rb->id << 16) | (rs->id << 12) | offset; + + } else { + int ret = risc_select_free_reg(&ri, c, f, 0); + if (ret < 0) { + scf_loge("\n"); + return -EINVAL; + } + + ret = arm32_inst_I2G(c, ri, offset, 4); + if (ret < 0) + return ret; + + opcode = (0xe7 << 24) | (0xc << 20) | (rb->id << 16) | (rs->id << 12) | ri->id; + } + + } else if (2 == size) { + + if (offset & 0x1) { + scf_loge("memory align error\n"); + return -EINVAL; + } + + if (offset >= 0 && offset < 0xff) + opcode = (0xe1 << 24) | (0xc << 20) | (rb->id << 16) | (rs->id << 12) | (((offset & 0xf0) | 0xb) << 4) | (offset & 0xf); + + else if (offset < 0 && offset >= -0xff) { + offset = -offset; + opcode = (0xe1 << 24) | (0x4 << 20) | (rb->id << 16) | (rs->id << 12) | (((offset & 0xf0) | 0xb) << 4) | (offset & 0xf); + + } else { + int ret = risc_select_free_reg(&ri, c, f, 0); + if (ret < 0) { + scf_loge("\n"); + return -EINVAL; + } + + ret = arm32_inst_I2G(c, ri, offset, 4); + if (ret < 0) + return ret; + + opcode = (0xe1 << 24) | (0x8 << 20) | (rb->id << 16) | (rs->id << 12) | (0xb << 4) | ri->id; + } + + } else if (4 == size) { + + if (offset & 0x3) { + scf_loge("memory align error\n"); + return -EINVAL; + } + + if (offset >= 0 && offset < 0xfff) + opcode = (0xe5 << 24) | (0x8 << 20) | (rb->id << 16) | (rs->id << 12) | offset; + + else if (offset < 0 && offset >= -0xfff) { + offset = -offset; + opcode = (0xe5 << 24) | (0x0 << 20) | (rb->id << 16) | (rs->id << 12) | offset; + + } else { + int ret = risc_select_free_reg(&ri, c, f, 0); + if (ret < 0) { + scf_loge("\n"); + return -EINVAL; + } + + ret = arm32_inst_I2G(c, ri, offset, 4); + if (ret < 0) + return ret; + + opcode = (0xe7 << 24) | (0x8 << 20) | (rb->id << 16) | (rs->id << 12) | ri->id; + } + + } else + return -EINVAL; + + inst = risc_make_inst(c, opcode); + RISC_INST_ADD_CHECK(c->instructions, inst); + + return 0; +} +//////// +int arm32_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 = f->rops->variable_size(v); + + assert(4 == rd->bytes); + assert(4 == size1); + + v->global_flag = 1; + v->local_flag = 0; + v->tmp_flag = 0; + + uint32_t opcode; + + opcode = (0xe3 << 24) | (rd->id << 12); + 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_ARM_REL32; + + opcode = (0xe3 << 24) | (0x4 << 20) | (rd->id << 12); + inst = risc_make_inst(c, opcode); + RISC_INST_ADD_CHECK(c->instructions, inst); + + opcode = (0xe7 << 24) | (0x9 << 20) | (rd->id << 16) | (rd->id << 12) | 0xf; + inst = risc_make_inst(c, opcode); + RISC_INST_ADD_CHECK(c->instructions, inst); + + opcode = (0xe0 << 24) | (0x8 << 20) | (rd->id << 16) | (rd->id << 12) | 0xf; + inst = risc_make_inst(c, opcode); + RISC_INST_ADD_CHECK(c->instructions, inst); + + return 0; +} + +int arm32_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; + + if (!rb) + return -EINVAL; + + if (1 == size) { + + if (offset >= 0 && offset < 0xfff) + opcode = (0xe5 << 24) | (0xc << 20) | (rb->id << 16) | (rs->id << 12) | offset; + + else if (offset < 0 && offset >= -0xfff) { + offset = -offset; + opcode = (0xe5 << 24) | (0x4 << 20) | (rb->id << 16) | (rs->id << 12) | offset; + + } else { + int ret = risc_select_free_reg(&ri, c, f, 0); + if (ret < 0) { + scf_loge("\n"); + return -EINVAL; + } + + ret = arm32_inst_I2G(c, ri, offset, 4); + if (ret < 0) + return ret; + + opcode = (0xe7 << 24) | (0xc << 20) | (rb->id << 16) | (rs->id << 12) | ri->id; + } + + } else if (2 == size) { + + if (offset & 0x1) { + scf_loge("memory align error\n"); + return -EINVAL; + } + + if (offset >= 0 && offset < 0xff) + opcode = (0xe1 << 24) | (0xc << 20) | (rb->id << 16) | (rs->id << 12) | (((offset & 0xf0) | 0xb) << 4) | (offset & 0xf); + + else if (offset < 0 && offset >= -0xff) { + offset = -offset; + opcode = (0xe1 << 24) | (0x4 << 20) | (rb->id << 16) | (rs->id << 12) | (((offset & 0xf0) | 0xb) << 4) | (offset & 0xf); + + } else { + int ret = risc_select_free_reg(&ri, c, f, 0); + if (ret < 0) { + scf_loge("\n"); + return -EINVAL; + } + + ret = arm32_inst_I2G(c, ri, offset, 4); + if (ret < 0) + return ret; + + opcode = (0xe1 << 24) | (0x8 << 20) | (rb->id << 16) | (rs->id << 12) | (0xb << 4) | ri->id; + } + + } else if (4 == size) { + + if (offset & 0x3) { + scf_loge("memory align error\n"); + return -EINVAL; + } + + if (offset >= 0 && offset < 0xfff) + opcode = (0xe5 << 24) | (0x8 << 20) | (rb->id << 16) | (rs->id << 12) | offset; + + else if (offset < 0 && offset >= -0xfff) { + offset = -offset; + opcode = (0xe5 << 24) | (0x0 << 20) | (rb->id << 16) | (rs->id << 12) | offset; + + } else { + int ret = risc_select_free_reg(&ri, c, f, 0); + if (ret < 0) { + scf_loge("\n"); + return -EINVAL; + } + + ret = arm32_inst_I2G(c, ri, offset, 4); + if (ret < 0) + return ret; + + opcode = (0xe7 << 24) | (0x8 << 20) | (rb->id << 16) | (rs->id << 12) | ri->id; + } + + } else + return -EINVAL; + + inst = risc_make_inst(c, opcode); + RISC_INST_ADD_CHECK(c->instructions, inst); + + return 0; +} + +int arm32_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; + uint32_t S = 1; + + if (!rb) + return -EINVAL; + + if (1 == size) { + + if (offset >= 0 && offset < 0xfff) + opcode = (0xe5 << 24) | (0xd << 20) | (rb->id << 16) | (rd->id << 12) | offset; + + else if (offset < 0 && offset >= -0xfff) { + offset = -offset; + opcode = (0xe5 << 24) | (0x5 << 20) | (rb->id << 16) | (rd->id << 12) | offset; + + } else { + int ret = risc_select_free_reg(&ri, c, f, 0); + if (ret < 0) { + scf_loge("\n"); + return -EINVAL; + } + + ret = arm32_inst_I2G(c, ri, offset, 4); + if (ret < 0) + return ret; + + opcode = (0xe7 << 24) | (0xd << 20) | (rb->id << 16) | (rd->id << 12) | ri->id; + } + + } else if (2 == size) { + + if (offset & 0x1) { + scf_loge("memory align error\n"); + return -EINVAL; + } + + if (offset >= 0 && offset < 0xff) + opcode = (0xe1 << 24) | (0xd << 20) | (rb->id << 16) | (rd->id << 12) | (((offset & 0xf0) | 0xb) << 4) | (offset & 0xf); + + else if (offset < 0 && offset >= -0xff) { + offset = -offset; + opcode = (0xe1 << 24) | (0x5 << 20) | (rb->id << 16) | (rd->id << 12) | (((offset & 0xf0) | 0xb) << 4) | (offset & 0xf); + + } else { + int ret = risc_select_free_reg(&ri, c, f, 0); + if (ret < 0) { + scf_loge("\n"); + return -EINVAL; + } + + ret = arm32_inst_I2G(c, ri, offset, 4); + if (ret < 0) + return ret; + + opcode = (0xe1 << 24) | (0x9 << 20) | (rb->id << 16) | (rd->id << 12) | (0xb << 4) | ri->id; + } + + } else if (4 == size) { + + if (offset & 0x3) { + scf_loge("memory align error\n"); + return -EINVAL; + } + + if (offset >= 0 && offset < 0xfff) + opcode = (0xe5 << 24) | (0x9 << 20) | (rb->id << 16) | (rd->id << 12) | offset; + + else if (offset < 0 && offset >= -0xfff) { + offset = -offset; + opcode = (0xe5 << 24) | (0x1 << 20) | (rb->id << 16) | (rd->id << 12) | offset; + + } else { + int ret = risc_select_free_reg(&ri, c, f, 0); + if (ret < 0) { + scf_loge("\n"); + return -EINVAL; + } + + ret = arm32_inst_I2G(c, ri, offset, 4); + if (ret < 0) + return ret; + + opcode = (0xe7 << 24) | (0x9 << 20) | (rb->id << 16) | (rd->id << 12) | ri->id; + } + + } else + return -EINVAL; + + inst = risc_make_inst(c, opcode); + RISC_INST_ADD_CHECK(c->instructions, inst); + return 0; +} + +int arm32_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 <= 0xff) + opcode = (0xe2 << 24) | (0x8 << 20) | (rb->id << 16) | (rd->id << 12) | offset; + + else if (offset < 0 && offset >= -0xff) { + offset = -offset; + opcode = (0xe2 << 24) | (0x4 << 20) | (rb->id << 16) | (rd->id << 12) | offset; + + } else { + int ret = risc_select_free_reg(&r, c, f, 0); + if (ret < 0) + return ret; + + ret = arm32_inst_I2G(c, r, offset, 4); + if (ret < 0) + return ret; + + opcode = (0xe0 << 24) | (0x8 << 20) | (rb->id << 16) | (rd->id << 12) | r->id; + } + + inst = risc_make_inst(c, opcode); + RISC_INST_ADD_CHECK(c->instructions, inst); + return 0; +} + +int arm32_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 + return -EINVAL; + + opcode = (0xe0 << 24) | (0x8 << 20) | (rb->id << 16) | (rd->id << 12) | (SH << 7) | ri->id; + inst = risc_make_inst(c, opcode); + RISC_INST_ADD_CHECK(c->instructions, inst); + return 0; +} + +int arm32_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; + + if (1 == size) + opcode = (0xe7 << 24) | (0xd << 20) | (rb->id << 16) | (rd->id << 12) | ri->id; + + else if (2 == size) + opcode = (0xf8 << 24) | (0x3 << 20) | (rb->id << 16) | (rd->id << 12) | (0x1 << 4) | ri->id; + + else if (4 == size) + opcode = (0xe7 << 24) | (0x9 << 20) | (rb->id << 16) | (rd->id << 12) | (0x2 << 7) | ri->id; + else + return -EINVAL; + + inst = risc_make_inst(c, opcode); + RISC_INST_ADD_CHECK(c->instructions, inst); + + return 0; +} + +int arm32_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; + + if (1 == size) + opcode = (0xe7 << 24) | (0xc << 20) | (rb->id << 16) | (rs->id << 12) | ri->id; + + else if (2 == size) + opcode = (0xf8 << 24) | (0x2 << 20) | (rb->id << 16) | (rs->id << 12) | (0x1 << 4) | ri->id; + + else if (4 == size) + opcode = (0xe7 << 24) | (0x8 << 20) | (rb->id << 16) | (rs->id << 12) | (0x2 << 7) | ri->id; + else + return -EINVAL; + + inst = risc_make_inst(c, opcode); + RISC_INST_ADD_CHECK(c->instructions, inst); + + return 0; +} + +int arm32_inst_M2GF(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 = f->rops->find_register("fp"); + scf_register_t* ro = NULL; + scf_instruction_t* inst = NULL; + scf_rela_t* rela = NULL; + + int32_t offset; + uint32_t opcode; + uint32_t SIZE = 0; + uint32_t D = 0; + uint32_t V = 0; + + int size = f->rops->variable_size(vs); + + scf_loge("\n"); + return -EINVAL; + + 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) + return ret; + + opcode = (0xe3 << 24) | (rb->id << 12); + 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_ARM_REL32; + + opcode = (0xe3 << 24) | (0x4 << 20) | (rb->id << 12); + inst = risc_make_inst(c, opcode); + RISC_INST_ADD_CHECK(c->instructions, inst); + + opcode = (0xe7 << 24) | (0x9 << 20) | (rb->id << 16) | (rb->id << 12) | 0xf; + inst = risc_make_inst(c, opcode); + RISC_INST_ADD_CHECK(c->instructions, inst); + + opcode = (0xe0 << 24) | (0x8 << 20) | (rb->id << 16) | (rb->id << 12) | 0xf; + inst = risc_make_inst(c, opcode); + RISC_INST_ADD_CHECK(c->instructions, inst); + + } 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 (2 == size) { + + if (offset & 0x1) { + scf_loge("memory align error\n"); + return -EINVAL; + } + + offset >>= 1; + SIZE = 1; + D = rd->id & 0x1; + V = rd->id >> 1; + + } else if (4 == size) { + + if (offset & 0x3) { + scf_loge("memory align error\n"); + return -EINVAL; + } + + offset >>= 2; + SIZE = 2; + D = rd->id & 0x1; + V = rd->id >> 1; + + } else if (8 == size) { + + if (offset & 0x7) { + scf_loge("memory align error\n"); + return -EINVAL; + } + + offset >>= 3; + SIZE = 3; + V = rd->id & 0xf; + D = (rd->id >> 4) & 0x1; + } else + return -EINVAL; + + if (offset >= 0 && offset < 0xff) + opcode = (0xed << 24) | (0x9 << 20) | (rb->id << 16) | (0x2 << 10) | (SIZE << 8) | offset; + + else if (offset < 0 && offset >= -0xff) { + offset = -offset; + opcode = (0xed << 24) | (0x1 << 20) | (rb->id << 16) | (0x2 << 10) | (SIZE << 8) | offset; + + } else { + int ret = risc_select_free_reg(&ro, c, f, 0); + if (ret < 0) + return ret; + + ret = arm32_inst_I2G(c, ro, offset, 4); + if (ret < 0) + return ret; + + opcode = (0xe0 << 24) | (0x8 << 20) | (rb->id << 16) | (ro->id << 12) | (SIZE << 7) | ro->id; + inst = risc_make_inst(c, opcode); + RISC_INST_ADD_CHECK(c->instructions, inst); + + opcode = (0xed << 24) | (0x9 << 20) | (ro->id << 16) | (0x2 << 10) | (SIZE << 8) | 0; + } + + opcode |= (D << 22) | (V << 12); + inst = risc_make_inst(c, opcode); + RISC_INST_ADD_CHECK(c->instructions, inst); + + return 0; +} + +scf_instruction_t* arm32_inst_PUSH(scf_3ac_code_t* c, scf_register_t* r) +{ + scf_instruction_t* inst; + uint32_t opcode; + + opcode = (0xe5 << 24) | (0x2 << 20) | (0xd << 16) | (r->id << 12) | 0x4; + inst = risc_make_inst(c, opcode); + + return inst; +} + +scf_instruction_t* arm32_inst_POP(scf_3ac_code_t* c, scf_register_t* r) +{ + scf_instruction_t* inst; + uint32_t opcode; + + opcode = (0xe4 << 24) | (0x9 << 20) | (0xd << 16) | (r->id << 12) | 0x4; + inst = risc_make_inst(c, opcode); + + return inst; +} + +scf_instruction_t* arm32_inst_RET(scf_3ac_code_t* c) +{ + scf_instruction_t* inst; + uint32_t opcode; + + opcode = 0xe12fff1e; + inst = risc_make_inst(c, opcode); + + return inst; +} + +scf_instruction_t* arm32_inst_MOV_SP(scf_3ac_code_t* c, scf_register_t* rd, scf_register_t* rs) +{ + scf_instruction_t* inst; + uint32_t opcode; + + opcode = (0xe1 << 24) | (0xa << 20) | (rd->id << 12) | rs->id; + inst = risc_make_inst(c, opcode); + + return inst; +} + +scf_instruction_t* arm32_inst_MOV_G(scf_3ac_code_t* c, scf_register_t* rd, scf_register_t* rs) +{ + scf_instruction_t* inst; + uint32_t opcode; + + opcode = (0xe1 << 24) | (0xa << 20) | (rd->id << 12) | rs->id; + inst = risc_make_inst(c, opcode); + + return inst; +} + +scf_instruction_t* arm32_inst_MVN(scf_3ac_code_t* c, scf_register_t* rd, scf_register_t* rs) +{ + scf_instruction_t* inst; + uint32_t opcode; + + opcode = (0xe1 << 24) | (0xe << 20) | (rd->id << 12) | rs->id; + inst = risc_make_inst(c, opcode); + + return inst; +} + +scf_instruction_t* arm32_inst_FMOV_G(scf_3ac_code_t* c, scf_register_t* rd, scf_register_t* rs) +{ + scf_instruction_t* inst; + uint32_t opcode; + + opcode = (0xee << 24) | (0xe << 20) | (rd->id << 12) | rs->id; + inst = risc_make_inst(c, opcode); + + return inst; +} + +scf_instruction_t* arm32_inst_MOVSX(scf_3ac_code_t* c, scf_register_t* rd, scf_register_t* rs, int size) +{ + scf_instruction_t* inst; + uint32_t opcode; + + if (1 == size) + opcode = (0xe6 << 24) | (0xa << 20) | (0xf << 16) | (rd->id << 12) | (0x7 << 4) | rs->id; + + else if (2 == size) + opcode = (0xe6 << 24) | (0xb << 20) | (0xf << 16) | (rd->id << 12) | (0x7 << 4) | rs->id; + else + return NULL; + + inst = risc_make_inst(c, opcode); + + return inst; +} + +scf_instruction_t* arm32_inst_MOVZX(scf_3ac_code_t* c, scf_register_t* rd, scf_register_t* rs, int size) +{ + scf_instruction_t* inst; + uint32_t opcode; + + if (1 == size) + opcode = (0xe6 << 24) | (0xe << 20) | (0xf << 16) | (rd->id << 12) | (0x7 << 4) | rs->id; + + else if (2 == size) + opcode = (0xe6 << 24) | (0xf << 20) | (0xf << 16) | (rd->id << 12) | (0x7 << 4) | rs->id; + else + return NULL; + + inst = risc_make_inst(c, opcode); + + return inst; +} + +scf_instruction_t* arm32_inst_CVTSS2SD(scf_3ac_code_t* c, scf_register_t* rd, scf_register_t* rs) +{ + scf_instruction_t* inst; + uint32_t opcode; + + uint32_t M = rs->id & 0x1; + uint32_t Vm = rs->id >> 1; + uint32_t D = rd->id >> 4; + uint32_t Vd = rd->id & 0xf; + + opcode = (0xee << 24) | (0xb7 << 16) | (0xa << 8) | (0xc << 4) | (D << 22) | (Vd << 12) | (M << 5) | Vm; + inst = risc_make_inst(c, opcode); + + return inst; +} + +scf_instruction_t* arm32_inst_CVTSD2SS(scf_3ac_code_t* c, scf_register_t* rd, scf_register_t* rs) +{ + scf_instruction_t* inst; + uint32_t opcode; + + uint32_t M = rd->id >> 4; + uint32_t Vm = rd->id & 0xf; + uint32_t D = rs->id & 0x1; + uint32_t Vd = rs->id >> 1; + + opcode = (0xee << 24) | (0xb7 << 16) | (0xb << 8) | (0xc << 4) | (D << 22) | (Vd << 12) | (M << 5) | Vm; + inst = risc_make_inst(c, opcode); + + return inst; +} + +scf_instruction_t* arm32_inst_CVTF2SI(scf_3ac_code_t* c, scf_register_t* rd, scf_register_t* rs) +{ + scf_instruction_t* inst; + uint32_t opcode; + + uint32_t M = rs->id & 0x1; + uint32_t Vm = rs->id >> 1; + uint32_t D = 15 >> 4; + uint32_t Vd = 15 & 0xf; + uint32_t SZ = (8 == rs->bytes) ? 0x3 : 0x2; + + opcode = (0xee << 24) | (0xb << 20) | (D << 22) | (0xd << 16) | (Vd << 12) | (0x2 << 10) | (SZ << 8) | (0x3 << 6) | (M << 5) | Vm; + inst = risc_make_inst(c, opcode); + if (!inst) + return NULL; + + if (scf_vector_add(c->instructions, inst) < 0) { + free(inst); + return NULL; + } + + opcode = (0xee << 24) | (0x1 << 20) | (Vd << 16) | (rd->id << 12) | (0xa << 8) | (D << 7) | (0x1 << 4); + inst = risc_make_inst(c, opcode); + return inst; +} + +scf_instruction_t* arm32_inst_CVTF2UI(scf_3ac_code_t* c, scf_register_t* rd, scf_register_t* rs) +{ + scf_instruction_t* inst; + uint32_t opcode; + + uint32_t M = rs->id & 0x1; + uint32_t Vm = rs->id >> 1; + uint32_t D = 15 >> 4; + uint32_t Vd = 15 & 0xf; + uint32_t SZ = (8 == rs->bytes) ? 0x3 : 0x2; + + opcode = (0xee << 24) | (0xb << 20) | (D << 22) | (0xc << 16) | (Vd << 12) | (0x2 << 10) | (SZ << 8) | (0x3 << 6) | (M << 5) | Vm; + inst = risc_make_inst(c, opcode); + if (!inst) + return NULL; + + if (scf_vector_add(c->instructions, inst) < 0) { + free(inst); + return NULL; + } + + opcode = (0xee << 24) | (0x1 << 20) | (Vd << 16) | (rd->id << 12) | (0xa << 8) | (D << 7) | (0x1 << 4); + inst = risc_make_inst(c, opcode); + return inst; +} + +scf_instruction_t* arm32_inst_CVTSI2F(scf_3ac_code_t* c, scf_register_t* rd, scf_register_t* rs) +{ + scf_instruction_t* inst; + uint32_t opcode; + + uint32_t D = rs->id & 0x1; + uint32_t Vd = rs->id >> 1; + uint32_t M = 15 >> 4; + uint32_t Vm = 15 & 0xf; + uint32_t SZ = (8 == rd->bytes) ? 0x3 : 0x2; + + opcode = (0xee << 24) | (0x0 << 20) | (Vm << 16) | (rd->id << 12) | (0xa << 8) | (M << 7) | (0x1 << 4); + inst = risc_make_inst(c, opcode); + if (!inst) + return NULL; + + if (scf_vector_add(c->instructions, inst) < 0) { + free(inst); + return NULL; + } + + opcode = (0xee << 24) | (0xb << 20) | (D << 22) | (0x8 << 16) | (Vd << 12) | (0x2 << 10) | (SZ << 8) | (0x3 << 6) | (M << 5) | Vm; + inst = risc_make_inst(c, opcode); + + return inst; +} + +scf_instruction_t* arm32_inst_CVTUI2F(scf_3ac_code_t* c, scf_register_t* rd, scf_register_t* rs) +{ + scf_instruction_t* inst; + uint32_t opcode; + + uint32_t D = rs->id & 0x1; + uint32_t Vd = rs->id >> 1; + uint32_t M = 15 >> 4; + uint32_t Vm = 15 & 0xf; + uint32_t SZ = (8 == rd->bytes) ? 0x3 : 0x2; + + opcode = (0xee << 24) | (0x0 << 20) | (Vm << 16) | (rd->id << 12) | (0xa << 8) | (M << 7) | (0x1 << 4); + inst = risc_make_inst(c, opcode); + if (!inst) + return NULL; + + if (scf_vector_add(c->instructions, inst) < 0) { + free(inst); + return NULL; + } + + opcode = (0xee << 24) | (0xb << 20) | (D << 22) | (0x8 << 16) | (Vd << 12) | (0x2 << 10) | (SZ << 8) | (0x1 << 6) | (M << 5) | Vm; + inst = risc_make_inst(c, opcode); + + return inst; +} + +scf_instruction_t* arm32_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; + uint32_t sh = 0; + + if (imm > 0xff) { + scf_loge("NOT support too big imm: %#lx\n", imm); + return NULL; + } + + opcode = (0xe2 << 24) | (0x4 << 20) | (rs->id << 16) | (rd->id << 12) | imm; + inst = risc_make_inst(c, opcode); + + return inst; +} + +scf_instruction_t* arm32_inst_CMP_IMM(scf_3ac_code_t* c, scf_register_t* rs, uint64_t imm) +{ + scf_instruction_t* inst; + uint32_t opcode; + uint32_t sh = 0; + + if (imm > 0xff) { + scf_loge("NOT support too big imm: %#lx\n", imm); + return NULL; + } + + opcode = (0xe3 << 24) | (0x5 << 20) | (rs->id << 16) | imm; + inst = risc_make_inst(c, opcode); + + return inst; +} + +scf_instruction_t* arm32_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; + uint32_t sh = 0; + + if (imm > 0xff) { + scf_loge("NOT support too big imm: %#lx\n", imm); + return NULL; + } + + opcode = (0xe2 << 24) | (0x8 << 20) | (rs->id << 16) | (rd->id << 12) | imm; + inst = risc_make_inst(c, opcode); + + return inst; +} + +scf_instruction_t* arm32_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 = (0xe0 << 24) | (0x8 << 20) | (rs0->id << 16) | (rd->id << 12) | rs1->id; + inst = risc_make_inst(c, opcode); + + return inst; +} + +scf_instruction_t* arm32_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 = (0xe1 << 24) | (0xa << 20) | (rd->id << 12) | (rs1->id << 8) | (0x1 << 4) | rs0->id; + inst = risc_make_inst(c, opcode); + + return inst; +} + +scf_instruction_t* arm32_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 = (0xe1 << 24) | (0xa << 20) | (rd->id << 12) | (rs1->id << 8) | (0x3 << 4) | rs0->id; + inst = risc_make_inst(c, opcode); + + return inst; +} + +scf_instruction_t* arm32_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 = (0xe1 << 24) | (0xa << 20) | (rd->id << 12) | (rs1->id << 8) | (0x5 << 4) | rs0->id; + inst = risc_make_inst(c, opcode); + + return inst; +} + +scf_instruction_t* arm32_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 = (0xe0 << 24) | (0x0 << 20) | (rs0->id << 16) | (rd->id << 12) | rs1->id; + inst = risc_make_inst(c, opcode); + + return inst; +} + +scf_instruction_t* arm32_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 = (0xe1 << 24) | (0x8 << 20) | (rs0->id << 16) | (rd->id << 12) | rs1->id; + inst = risc_make_inst(c, opcode); + + return inst; +} + +scf_instruction_t* arm32_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 = (0xe0 << 24) | (0x4 << 20) | (rs0->id << 16) | (rd->id << 12) | rs1->id; + inst = risc_make_inst(c, opcode); + + return inst; +} + +scf_instruction_t* arm32_inst_CMP_G(scf_3ac_code_t* c, scf_register_t* rs0, scf_register_t* rs1) +{ + scf_instruction_t* inst; + uint32_t opcode; + + opcode = (0xe1 << 24) | (0x5 << 20) | (rs0->id << 16) | rs1->id; + inst = risc_make_inst(c, opcode); + + return inst; +} + +scf_instruction_t* arm32_inst_FCMP(scf_3ac_code_t* c, scf_register_t* rs0, scf_register_t* rs1) +{ + scf_instruction_t* inst; + uint32_t opcode; + uint32_t D; + uint32_t M; + uint32_t Vd; + uint32_t Vm; + uint32_t SIZE; + + if (8 == rs0->bytes) { + D = rs0->id >> 4; + Vd = rs0->id & 0xf; + + M = rs1->id >> 4; + Vm = rs1->id & 0xf; + + SIZE = 3; + + } else { + D = rs0->id & 0x1; + Vd = rs0->id >> 1; + + M = rs1->id & 0x1; + Vm = rs1->id >> 1; + + SIZE = 2; + } + + opcode = (0xee << 24) | (0x1 << 23) | (D << 22) | (0x3 << 20) | (0x4 << 16) | (Vd << 12) | (0x2 << 10) | (SIZE << 8) | (0x1 << 6) | (M << 5) | Vm; + inst = risc_make_inst(c, opcode); + + return inst; +} + +scf_instruction_t* arm32_inst_NEG(scf_3ac_code_t* c, scf_register_t* rd, scf_register_t* rs) +{ + scf_instruction_t* inst; + uint32_t opcode; + + opcode = (0xe1 << 24) | (0x3 << 20) | (rs->id << 16) | rs->id; + inst = risc_make_inst(c, opcode); + + return inst; +} + +scf_instruction_t* arm32_inst_TEQ(scf_3ac_code_t* c, scf_register_t* rs) +{ + scf_instruction_t* inst; + uint32_t opcode; + + opcode = (0xe1 << 24) | (0x3 << 20) | (rs->id << 16) | rs->id; + inst = risc_make_inst(c, opcode); + + return inst; +} + +scf_instruction_t* arm32_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; + uint32_t D; + uint32_t M; + uint32_t N; + uint32_t Vd; + uint32_t Vm; + uint32_t Vn; + uint32_t SIZE; + + if (8 == rd->bytes) { + D = rd->id >> 4; + Vd = rd->id & 0xf; + + M = rs1->id >> 4; + Vm = rs1->id & 0xf; + + N = rs0->id >> 4; + Vn = rs0->id & 0xf; + + SIZE = 3; + + } else { + D = rd->id & 0x1; + Vd = rd->id >> 1; + + M = rs1->id & 0x1; + Vm = rs1->id >> 1; + + N = rs0->id & 0x1; + Vn = rs0->id >> 1; + + SIZE = 2; + } + + opcode = (0xee << 24) | (D << 22) | (0x3 << 20) | (Vn << 16) | (Vd << 12) | (0x2 << 10) | (SIZE << 8) | (N << 7) | (M << 5) | Vm; + inst = risc_make_inst(c, opcode); + + return inst; +} + +scf_instruction_t* arm32_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; + uint32_t D; + uint32_t M; + uint32_t N; + uint32_t Vd; + uint32_t Vm; + uint32_t Vn; + uint32_t SIZE; + + if (8 == rd->bytes) { + D = rd->id >> 4; + Vd = rd->id & 0xf; + + M = rs1->id >> 4; + Vm = rs1->id & 0xf; + + N = rs0->id >> 4; + Vn = rs0->id & 0xf; + + SIZE = 3; + + } else { + D = rd->id & 0x1; + Vd = rd->id >> 1; + + M = rs1->id & 0x1; + Vm = rs1->id >> 1; + + N = rs0->id & 0x1; + Vn = rs0->id >> 1; + + SIZE = 2; + } + + opcode = (0xee << 24) | (D << 22) | (0x3 << 20) | (Vn << 16) | (Vd << 12) | (0x2 << 10) | (SIZE << 8) | (N << 7) | (0x1 << 6) | (M << 5) | Vm; + inst = risc_make_inst(c, opcode); + + return inst; +} + +scf_instruction_t* arm32_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 = (0xe0 << 24) | (rd->id << 16) | (rs1->id << 8) | (0x9 << 4) | rs0->id; + inst = risc_make_inst(c, opcode); + + return inst; +} + +scf_instruction_t* arm32_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; + uint32_t D; + uint32_t M; + uint32_t N; + uint32_t Vd; + uint32_t Vm; + uint32_t Vn; + uint32_t SIZE; + + if (8 == rd->bytes) { + D = rd->id >> 4; + Vd = rd->id & 0xf; + + M = rs1->id >> 4; + Vm = rs1->id & 0xf; + + N = rs0->id >> 4; + Vn = rs0->id & 0xf; + + SIZE = 3; + + } else { + D = rd->id & 0x1; + Vd = rd->id >> 1; + + M = rs1->id & 0x1; + Vm = rs1->id >> 1; + + N = rs0->id & 0x1; + Vn = rs0->id >> 1; + + SIZE = 2; + } + + opcode = (0xee << 24) | (0x0 << 23) | (D << 22) | (0x1 << 21) | (Vn << 16) | (Vd << 12) | (0x2 << 10) | (SIZE << 8) | (N << 7) | (M << 5) | Vm; + inst = risc_make_inst(c, opcode); + + return inst; +} + +scf_instruction_t* arm32_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; + uint32_t D; + uint32_t M; + uint32_t N; + uint32_t Vd; + uint32_t Vm; + uint32_t Vn; + uint32_t SIZE; + + if (8 == rd->bytes) { + D = rd->id >> 4; + Vd = rd->id & 0xf; + + M = rs1->id >> 4; + Vm = rs1->id & 0xf; + + N = rs0->id >> 4; + Vn = rs0->id & 0xf; + + SIZE = 3; + + } else { + D = rd->id & 0x1; + Vd = rd->id >> 1; + + M = rs1->id & 0x1; + Vm = rs1->id >> 1; + + N = rs0->id & 0x1; + Vn = rs0->id >> 1; + + SIZE = 2; + } + + opcode = (0xee << 24) | (0x1 << 23) | (D << 22) | (Vn << 16) | (Vd << 12) | (0x2 << 10) | (SIZE << 8) | (N << 7) | (M << 5) | Vm; + inst = risc_make_inst(c, opcode); + + return inst; +} + +scf_instruction_t* arm32_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 = (0xe7 << 24) | (0x3 << 20) | (rd->id << 16) | (0xf << 12) | (rs1->id << 8) | (0x1 << 4) | rs0->id; + inst = risc_make_inst(c, opcode); + + return inst; +} + +scf_instruction_t* arm32_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 = (0xe7 << 24) | (0x1 << 20) | (rd->id << 16) | (0xf << 12) | (rs1->id << 8) | (0x1 << 4) | rs0->id; + inst = risc_make_inst(c, opcode); + + return inst; +} + +scf_instruction_t* arm32_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 = (0xe0 << 24) | (0x6 << 20) | (rd->id << 16) | (ra->id << 12) | (rm->id << 8) | (0x9 << 4) | rn->id; + inst = risc_make_inst(c, opcode); + + return inst; +} + +int arm32_inst_BL(scf_3ac_code_t* c, scf_function_t* f, scf_function_t* pf) +{ + scf_instruction_t* inst; + scf_rela_t* rela; + uint32_t opcode; + + opcode = 0xeb << 24; + inst = risc_make_inst(c, opcode); + + RISC_INST_ADD_CHECK(c->instructions, inst); + RISC_RELA_ADD_CHECK(f->text_relas, rela, c, NULL, pf); + + rela->type = R_ARM_CALL; + return 0; +} + +scf_instruction_t* arm32_inst_BLR(scf_3ac_code_t* c, scf_register_t* r) +{ + scf_instruction_t* inst; + uint32_t opcode; + + opcode = 0xe12fff30 | r->id; + inst = risc_make_inst(c, opcode); + + return inst; +} + +scf_instruction_t* arm32_inst_SETZ(scf_3ac_code_t* c, scf_register_t* rd) +{ + scf_instruction_t* inst; + uint32_t opcode; + uint32_t cc = 1; + + opcode = ((8 == rd->bytes) << 1) | (0x1a << 24) | (0x1 << 23) | (0x1f << 16) | (cc << 12) | (0x3f << 5) | rd->id; + inst = risc_make_inst(c, opcode); + + return inst; +} +scf_instruction_t* arm32_inst_SETNZ(scf_3ac_code_t* c, scf_register_t* rd) +{ + scf_instruction_t* inst; + uint32_t opcode; + uint32_t cc = 0; + + opcode = ((8 == rd->bytes) << 1) | (0x1a << 24) | (0x1 << 23) | (0x1f << 16) | (cc << 12) | (0x3f << 5) | rd->id; + inst = risc_make_inst(c, opcode); + + return inst; +} +scf_instruction_t* arm32_inst_SETGT(scf_3ac_code_t* c, scf_register_t* rd) +{ + scf_instruction_t* inst; + uint32_t opcode; + uint32_t cc = 0xd; + + opcode = ((8 == rd->bytes) << 1) | (0x1a << 24) | (0x1 << 23) | (0x1f << 16) | (cc << 12) | (0x3f << 5) | rd->id; + inst = risc_make_inst(c, opcode); + + return inst; +} +scf_instruction_t* arm32_inst_SETGE(scf_3ac_code_t* c, scf_register_t* rd) +{ + scf_instruction_t* inst; + uint32_t opcode; + uint32_t cc = 0xb; + + opcode = ((8 == rd->bytes) << 1) | (0x1a << 24) | (0x1 << 23) | (0x1f << 16) | (cc << 12) | (0x3f << 5) | rd->id; + inst = risc_make_inst(c, opcode); + + return inst; +} +scf_instruction_t* arm32_inst_SETLT(scf_3ac_code_t* c, scf_register_t* rd) +{ + scf_instruction_t* inst; + uint32_t opcode; + uint32_t cc = 0xa; + + opcode = ((8 == rd->bytes) << 1) | (0x1a << 24) | (0x1 << 23) | (0x1f << 16) | (cc << 12) | (0x3f << 5) | rd->id; + inst = risc_make_inst(c, opcode); + + return inst; +} +scf_instruction_t* arm32_inst_SETLE(scf_3ac_code_t* c, scf_register_t* rd) +{ + scf_instruction_t* inst; + uint32_t opcode; + uint32_t cc = 0xc; + + opcode = ((8 == rd->bytes) << 1) | (0x1a << 24) | (0x1 << 23) | (0x1f << 16) | (cc << 12) | (0x3f << 5) | rd->id; + inst = risc_make_inst(c, opcode); + + return inst; +} + +scf_instruction_t* arm32_inst_JMP(scf_3ac_code_t* c) +{ + scf_instruction_t* inst; + uint32_t opcode; + + opcode = 0xea000000; + inst = risc_make_inst(c, opcode); + + return inst; +} + +scf_instruction_t* arm32_inst_JZ(scf_3ac_code_t* c) +{ + scf_instruction_t* inst; + uint32_t opcode; + + opcode = 0x0a000000; + inst = risc_make_inst(c, opcode); + + return inst; +} + +scf_instruction_t* arm32_inst_JNZ(scf_3ac_code_t* c) +{ + scf_instruction_t* inst; + uint32_t opcode; + + opcode = 0x1a000000; + inst = risc_make_inst(c, opcode); + + return inst; +} + +scf_instruction_t* arm32_inst_JGT(scf_3ac_code_t* c) +{ + scf_instruction_t* inst; + uint32_t opcode; + + opcode = 0xca000000; + inst = risc_make_inst(c, opcode); + + return inst; +} + +scf_instruction_t* arm32_inst_JGE(scf_3ac_code_t* c) +{ + scf_instruction_t* inst; + uint32_t opcode; + + opcode = 0xaa000000; + inst = risc_make_inst(c, opcode); + + return inst; +} + +scf_instruction_t* arm32_inst_JLT(scf_3ac_code_t* c) +{ + scf_instruction_t* inst; + uint32_t opcode; + + opcode = 0xba000000; + inst = risc_make_inst(c, opcode); + + return inst; +} + +scf_instruction_t* arm32_inst_JLE(scf_3ac_code_t* c) +{ + scf_instruction_t* inst; + uint32_t opcode; + + opcode = 0xda000000; + inst = risc_make_inst(c, opcode); + + return inst; +} + +scf_instruction_t* arm32_inst_JA(scf_3ac_code_t* c) +{ + return NULL; +} +scf_instruction_t* arm32_inst_JB(scf_3ac_code_t* c) +{ + return NULL; +} +scf_instruction_t* arm32_inst_JAE(scf_3ac_code_t* c) +{ + return NULL; +} +scf_instruction_t* arm32_inst_JBE(scf_3ac_code_t* c) +{ + return NULL; +} + +void arm32_set_jmp_offset(scf_instruction_t* inst, int32_t bytes) +{ + bytes -= 8; // 'pc = current + 8' + bytes >>= 2; + + assert(bytes < 0x7fffff && bytes > -0x7fffff); + + inst->code[0] |= 0xff & bytes; + inst->code[1] |= 0xff & (bytes >> 8); + inst->code[2] |= 0xff & (bytes >> 16); +} + +int arm32_cmp_update(scf_3ac_code_t* c, scf_function_t* f, scf_instruction_t* cmp) +{ + scf_instruction_t* inst; + scf_register_t* r12 = f->rops->find_register_type_id_bytes(0, 12, 4); + scf_register_t* r14 = f->rops->find_register_type_id_bytes(0, 14, 4); + scf_register_t* r0; + + uint32_t opcode; + uint32_t mov; + uint32_t i0; + uint32_t i1; + + opcode = cmp->code[0]; + opcode |= cmp->code[1] << 8; + opcode |= cmp->code[2] << 16; + opcode |= cmp->code[3] << 24; + + switch (cmp->code[3]) { + // arm32 + case 0xe3: // imm + i0 = (opcode >> 16) & 0xf; + r0 = f->rops->find_register_type_id_bytes(0, i0, 4); + inst = f->iops->MOV_G(c, r12, r0); // use r12 to backup r0 + RISC_INST_ADD_CHECK(c->instructions, inst); + + opcode &= ~(0xf << 16); + opcode |= (0xc << 16); + break; + + case 0xe1: // register + i0 = (opcode >> 16) & 0xf; + i1 = (opcode ) & 0xf; + + r0 = f->rops->find_register_type_id_bytes(0, i0, 4); + inst = f->iops->MOV_G(c, r12, r0); // use r16 to backup r0 + RISC_INST_ADD_CHECK(c->instructions, inst); + + r0 = f->rops->find_register_type_id_bytes(0, i1, 4); + inst = f->iops->MOV_G(c, r14, r0); // use r17 to backup r1 + RISC_INST_ADD_CHECK(c->instructions, inst); + + opcode &= ~(0xf << 16); + opcode |= (0xc << 16); + + opcode &= ~0xf; + opcode |= 0xe; + break; + default: + scf_loge("%#x\n", opcode); + return -EINVAL; + break; + }; + + cmp->code[0] = 0xff & opcode; + cmp->code[1] = 0xff & (opcode >> 8); + cmp->code[2] = 0xff & (opcode >> 16); + cmp->code[3] = 0xff & (opcode >> 24); + return 0; +} + +int arm32_set_rel_veneer(scf_function_t* f) +{ + scf_basic_block_t* bb; + scf_instruction_t* inst; + scf_3ac_code_t* c; + scf_3ac_code_t* end; + scf_list_t* l; + scf_rela_t* r; + + int bytes = f->init_code_bytes; + + for (l = scf_list_head(&f->basic_block_list_head); l != scf_list_sentinel(&f->basic_block_list_head); l = scf_list_next(l)) { + bb = scf_list_data(l, scf_basic_block_t, list); + + bytes += bb->code_bytes; + } + + l = scf_list_tail(&bb->code_list_head); + end = scf_list_data(l, scf_3ac_code_t, list); + + int i; + for (i = 0; i < f->data_relas->size; i++) { + r = f->data_relas->data[i]; + + int offset = bytes - r->inst_offset - 16; // 'pc = current + 8' + + inst = risc_make_inst(end, offset - 4); + RISC_INST_ADD_CHECK(end->instructions, inst); + + r->inst_offset = bytes; + + bytes += 4; + end->inst_bytes += 4; + bb ->code_bytes += 4; + + r->inst->code[0] = 0xff & offset; + r->inst->code[1] &= 0xf0; + r->inst->code[1] |= 0x0f & (offset >> 8); + r->inst->code[2] &= 0xf0; + r->inst->code[2] |= 0x0f & (offset >> 12); + + int j; + for (j = 0; j < r->code->instructions->size; j++) { + inst = r->code->instructions->data[j]; + + if (inst == r->inst) + break; + } + + assert(r->code->instructions->size > j + 1); + + inst = r->code->instructions->data[j + 1]; + + inst->code[0] = 0xff & (offset >> 16); + inst->code[1] &= 0xf0; + inst->code[1] |= 0x0f & (offset >> 24); + inst->code[2] &= 0xf0; + inst->code[2] |= 0x0f & (offset >> 28); + } + + return 0; +} + +scf_inst_ops_t inst_ops_arm32 = +{ + .name = "arm32", + + .BL = arm32_inst_BL, + .BLR = arm32_inst_BLR, + .PUSH = arm32_inst_PUSH, + .POP = arm32_inst_POP, + .TEQ = arm32_inst_TEQ, + .NEG = arm32_inst_NEG, + + .MOVZX = arm32_inst_MOVZX, + .MOVSX = arm32_inst_MOVSX, + .MVN = arm32_inst_MVN, + .MOV_G = arm32_inst_MOV_G, + .MOV_SP = arm32_inst_MOV_SP, + + .ADD_G = arm32_inst_ADD_G, + .ADD_IMM = arm32_inst_ADD_IMM, + .SUB_G = arm32_inst_SUB_G, + .SUB_IMM = arm32_inst_SUB_IMM, + .CMP_G = arm32_inst_CMP_G, + .CMP_IMM = arm32_inst_CMP_IMM, + .AND_G = arm32_inst_AND_G, + .OR_G = arm32_inst_OR_G, + + .MUL = arm32_inst_MUL, + .DIV = arm32_inst_DIV, + .SDIV = arm32_inst_SDIV, + .MSUB = arm32_inst_MSUB, + + .SHL = arm32_inst_SHL, + .SHR = arm32_inst_SHR, + .ASR = arm32_inst_ASR, + + .CVTSS2SD = arm32_inst_CVTSS2SD, + .CVTSD2SS = arm32_inst_CVTSD2SS, + .CVTF2SI = arm32_inst_CVTF2SI, + .CVTF2UI = arm32_inst_CVTF2UI, + .CVTSI2F = arm32_inst_CVTSI2F, + .CVTUI2F = arm32_inst_CVTUI2F, + + .FCMP = arm32_inst_FCMP, + .FADD = arm32_inst_FADD, + .FSUB = arm32_inst_FSUB, + .FMUL = arm32_inst_FMUL, + .FDIV = arm32_inst_FDIV, + .FMOV_G = arm32_inst_FMOV_G, + + .JA = arm32_inst_JA, + .JB = arm32_inst_JB, + .JZ = arm32_inst_JZ, + .JNZ = arm32_inst_JNZ, + .JGT = arm32_inst_JGT, + .JGE = arm32_inst_JGE, + .JLT = arm32_inst_JLT, + .JLE = arm32_inst_JLE, + .JAE = arm32_inst_JAE, + .JBE = arm32_inst_JBE, + .JMP = arm32_inst_JMP, + .RET = arm32_inst_RET, + + .SETZ = arm32_inst_SETZ, + .SETNZ = arm32_inst_SETNZ, + .SETGT = arm32_inst_SETGT, + .SETGE = arm32_inst_SETGE, + .SETLT = arm32_inst_SETLT, + .SETLE = arm32_inst_SETLE, + + .I2G = arm32_inst_I2G, + .M2G = arm32_inst_M2G, + .M2GF = arm32_inst_M2GF, + .G2M = arm32_inst_G2M, + .G2P = arm32_inst_G2P, + .P2G = arm32_inst_P2G, + .ISTR2G = arm32_inst_ISTR2G, + .SIB2G = arm32_inst_SIB2G, + .G2SIB = arm32_inst_G2SIB, + .ADR2G = arm32_inst_ADR2G, + .ADRP2G = arm32_inst_ADRP2G, + .ADRSIB2G = arm32_inst_ADRSIB2G, + + .cmp_update = arm32_cmp_update, + .set_jmp_offset = arm32_set_jmp_offset, + .set_rel_veneer = arm32_set_rel_veneer, +}; + diff --git a/native/risc/scf_arm64.c b/native/risc/scf_arm64.c index d51f810..b23801b 100644 --- a/native/risc/scf_arm64.c +++ b/native/risc/scf_arm64.c @@ -70,7 +70,7 @@ int arm64_inst_ADR2G(scf_3ac_code_t* c, scf_function_t* f, scf_register_t* rd, s uint32_t SIZE = 0; uint32_t S = 1; - int size = risc_variable_size(vs); + int size = f->rops->variable_size(vs); if (vs->local_flag || vs->tmp_flag) { @@ -130,7 +130,7 @@ int arm64_inst_M2G(scf_3ac_code_t* c, scf_function_t* f, scf_register_t* rd, scf uint32_t SIZE = 0; uint32_t S = 1; - int size = risc_variable_size(vs); + int size = f->rops->variable_size(vs); if (!rb) { if (vs->local_flag || vs->tmp_flag) { @@ -251,7 +251,7 @@ int arm64_inst_G2M(scf_3ac_code_t* c, scf_function_t* f, scf_register_t* rs, scf uint32_t SIZE = 0; uint32_t S = 1; - int size = risc_variable_size(vs); + int size = f->rops->variable_size(vs); if (!rb) { if (vs->local_flag || vs->tmp_flag) { @@ -356,7 +356,7 @@ int arm64_inst_ISTR2G(scf_3ac_code_t* c, scf_function_t* f, scf_register_t* rd, scf_instruction_t* inst = NULL; scf_rela_t* rela = NULL; - int size1 = risc_variable_size(v); + int size1 = f->rops->variable_size(v); assert(8 == rd->bytes); assert(8 == size1); @@ -716,7 +716,7 @@ int arm64_inst_M2GF(scf_3ac_code_t* c, scf_function_t* f, scf_register_t* rd, sc uint32_t SIZE = 0; uint32_t S = 1; - int size = risc_variable_size(vs); + int size = f->rops->variable_size(vs); if (!rb) { if (vs->local_flag || vs->tmp_flag) { @@ -1305,15 +1305,20 @@ scf_instruction_t* arm64_inst_MSUB(scf_3ac_code_t* c, scf_register_t* rd, scf_re return inst; } -scf_instruction_t* arm64_inst_BL(scf_3ac_code_t* c) +int arm64_inst_BL(scf_3ac_code_t* c, scf_function_t* f, scf_function_t* pf) { scf_instruction_t* inst; + scf_rela_t* rela; uint32_t opcode; opcode = 0x25 << 26; inst = risc_make_inst(c, opcode); - return inst; + RISC_INST_ADD_CHECK(c->instructions, inst); + RISC_RELA_ADD_CHECK(f->text_relas, rela, c, NULL, pf); + + rela->type = R_AARCH64_CALL26; + return 0; } scf_instruction_t* arm64_inst_BLR(scf_3ac_code_t* c, scf_register_t* r) diff --git a/native/risc/scf_naja.c b/native/risc/scf_naja.c index 2fa5c4f..40d0ea4 100644 --- a/native/risc/scf_naja.c +++ b/native/risc/scf_naja.c @@ -70,7 +70,7 @@ int naja_inst_ADR2G(scf_3ac_code_t* c, scf_function_t* f, scf_register_t* rd, sc uint32_t SIZE = 0; uint32_t S = 1; - int size = risc_variable_size(vs); + int size = f->rops->variable_size(vs); if (vs->local_flag || vs->tmp_flag) { @@ -120,16 +120,16 @@ int naja_inst_ADR2G(scf_3ac_code_t* c, scf_function_t* f, scf_register_t* rd, sc 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 = f->rops->find_register("fp"); - scf_register_t* ri = NULL; - scf_instruction_t* inst = NULL; - scf_rela_t* rela = NULL; + scf_register_t* fp = f->rops->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); + int size = f->rops->variable_size(vs); if (!rb) { if (vs->local_flag || vs->tmp_flag) { @@ -228,16 +228,16 @@ int naja_inst_M2G(scf_3ac_code_t* c, scf_function_t* f, scf_register_t* rd, scf_ 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 = f->rops->find_register("fp"); - scf_register_t* ri = NULL; - scf_instruction_t* inst = NULL; - scf_rela_t* rela = NULL; + scf_register_t* fp = f->rops->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); + int size = f->rops->variable_size(vs); if (!rb) { if (vs->local_flag || vs->tmp_flag) { @@ -340,7 +340,7 @@ int naja_inst_ISTR2G(scf_3ac_code_t* c, scf_function_t* f, scf_register_t* rd, s scf_instruction_t* inst = NULL; scf_rela_t* rela = NULL; - int size1 = risc_variable_size(v); + int size1 = f->rops->variable_size(v); assert(8 == rd->bytes); assert(8 == size1); @@ -1125,15 +1125,20 @@ scf_instruction_t* naja_inst_MSUB(scf_3ac_code_t* c, scf_register_t* rd, scf_reg return inst; } -scf_instruction_t* naja_inst_BL(scf_3ac_code_t* c) +int naja_inst_BL(scf_3ac_code_t* c, scf_function_t* f, scf_function_t* pf) { scf_instruction_t* inst; + scf_rela_t* rela; uint32_t opcode; opcode = (0x18 << 26); inst = risc_make_inst(c, opcode); - return inst; + RISC_INST_ADD_CHECK(c->instructions, inst); + RISC_RELA_ADD_CHECK(f->text_relas, rela, c, NULL, pf); + + rela->type = R_AARCH64_CALL26; + return 0; } scf_instruction_t* naja_inst_BLR(scf_3ac_code_t* c, scf_register_t* r) diff --git a/native/risc/scf_risc.c b/native/risc/scf_risc.c index f338387..5f46cdb 100644 --- a/native/risc/scf_risc.c +++ b/native/risc/scf_risc.c @@ -4,14 +4,17 @@ #include"scf_3ac.h" extern scf_regs_ops_t regs_ops_arm64; +extern scf_regs_ops_t regs_ops_arm32; extern scf_regs_ops_t regs_ops_naja; extern scf_inst_ops_t inst_ops_arm64; +extern scf_inst_ops_t inst_ops_arm32; extern scf_inst_ops_t inst_ops_naja; static scf_inst_ops_t* inst_ops_array[] = { &inst_ops_arm64, + &inst_ops_arm32, &inst_ops_naja, NULL @@ -20,6 +23,7 @@ static scf_inst_ops_t* inst_ops_array[] = static scf_regs_ops_t* regs_ops_array[] = { ®s_ops_arm64, + ®s_ops_arm32, ®s_ops_naja, NULL @@ -81,7 +85,7 @@ static void _risc_argv_rabi(scf_function_t* f) f->args_float = 0; int bp_int = -8; - int bp_floats = -8 - (int)RISC_ABI_NB * 8; + int bp_floats = -8 - (int)f->rops->ABI_NB * 8; int bp_others = 16; int i; @@ -93,22 +97,22 @@ static void _risc_argv_rabi(scf_function_t* f) assert(f->inline_flag); } - int is_float = scf_variable_float(v); - int size = risc_variable_size(v); + int is_float = scf_variable_float(v); + int size = f->rops->variable_size (v); if (is_float) { - if (f->args_float < RISC_ABI_NB) { + if (f->args_float < f->rops->ABI_NB) { - v->rabi = f->rops->find_register_type_id_bytes(is_float, risc_abi_float_regs[f->args_float], size); + v->rabi = f->rops->find_register_type_id_bytes(is_float, f->rops->abi_float_regs[f->args_float], size); v->bp_offset = bp_floats; bp_floats -= 8; f->args_float++; continue; } - } else if (f->args_int < RISC_ABI_NB) { + } else if (f->args_int < f->rops->ABI_NB) { - v->rabi = f->rops->find_register_type_id_bytes(is_float, risc_abi_regs[f->args_int], size); + v->rabi = f->rops->find_register_type_id_bytes(is_float, f->rops->abi_regs[f->args_int], size); v->bp_offset = bp_int; bp_int -= 8; f->args_int++; @@ -138,7 +142,7 @@ static int _risc_function_init(scf_function_t* f, scf_vector_t* local_vars) _risc_argv_rabi(f); - int local_vars_size = 8 + RISC_ABI_NB * 8 * 2; + int local_vars_size = 8 + f->rops->ABI_NB * 8 * 2; for (i = 0; i < local_vars->size; i++) { v = local_vars->data[i]; @@ -281,12 +285,12 @@ static int _risc_function_finish(scf_native_t* ctx, scf_function_t* f) f->init_code_bytes = 0; int i; - for (i = 0; i < RISC_ABI_CALLEE_SAVES_NB; i++) { + for (i = 0; i < f->rops->ABI_CALLEE_SAVES_NB; i++) { - r = f->rops->find_register_type_id_bytes(0, risc_abi_callee_saves[i], 8); + r = f->rops->find_register_type_id_bytes(0, f->rops->abi_callee_saves[i], 8); if (!r->used) { - r = f->rops->find_register_type_id_bytes(0, risc_abi_callee_saves[i], 4); + r = f->rops->find_register_type_id_bytes(0, f->rops->abi_callee_saves[i], 4); if (!r->used) continue; @@ -580,7 +584,7 @@ static int _risc_select_bb_regs(scf_basic_block_t* bb, scf_native_t* ctx) goto error; } - ret = scf_risc_graph_kcolor(g, 16, colors); + ret = scf_risc_graph_kcolor(g, 16, colors, f); if (ret < 0) goto error; @@ -631,7 +635,7 @@ static int _risc_select_bb_group_regs(scf_bb_group_t* bbg, scf_native_t* ctx) goto error; } - ret = scf_risc_graph_kcolor(g, 16, colors); + ret = scf_risc_graph_kcolor(g, 16, colors, f); if (ret < 0) goto error; @@ -1193,6 +1197,10 @@ int scf_risc_select_inst(scf_native_t* ctx, scf_function_t* f) _risc_set_offset_for_relas(ctx, f, f->text_relas); _risc_set_offset_for_relas(ctx, f, f->data_relas); + + if (f->iops->set_rel_veneer) + return f->iops->set_rel_veneer(f); + return 0; } diff --git a/native/risc/scf_risc.h b/native/risc/scf_risc.h index 4259da1..3821c12 100644 --- a/native/risc/scf_risc.h +++ b/native/risc/scf_risc.h @@ -82,7 +82,7 @@ int scf_risc_select(scf_native_t* ctx); int risc_optimize_peephole(scf_native_t* ctx, scf_function_t* f); -int scf_risc_graph_kcolor(scf_graph_t* graph, int k, scf_vector_t* colors); +int scf_risc_graph_kcolor(scf_graph_t* graph, int k, scf_vector_t* colors, scf_function_t* f); intptr_t risc_bb_find_color (scf_vector_t* dn_colors, scf_dag_node_t* dn); diff --git a/native/risc/scf_risc_bb_color.c b/native/risc/scf_risc_bb_color.c index a65991f..ee58d60 100644 --- a/native/risc/scf_risc_bb_color.c +++ b/native/risc/scf_risc_bb_color.c @@ -170,8 +170,6 @@ int risc_bb_save_dn(intptr_t color, scf_dag_node_t* dn, scf_3ac_code_t* c, scf_b int risc_bb_load_dn2(intptr_t color, scf_dag_node_t* dn, scf_basic_block_t* bb, scf_function_t* f) { scf_register_t* r0; - scf_register_t* r16 = f->rops->find_register_type_id_bytes(0, 16, 8); - scf_register_t* r17 = f->rops->find_register_type_id_bytes(0, 17, 8); scf_instruction_t* cmp = NULL; scf_instruction_t* inst; scf_3ac_code_t* c; diff --git a/native/risc/scf_risc_graph.c b/native/risc/scf_risc_graph.c index f05b156..6765e79 100644 --- a/native/risc/scf_risc_graph.c +++ b/native/risc/scf_risc_graph.c @@ -1,7 +1,7 @@ #include"scf_graph.h" #include"scf_risc.h" -static intptr_t _risc_color_select(scf_graph_node_t* node, scf_vector_t* colors) +static intptr_t _risc_color_select(scf_graph_node_t* node, scf_vector_t* colors, scf_function_t* f) { risc_rcg_node_t* rn = node->data; @@ -16,7 +16,7 @@ static intptr_t _risc_color_select(scf_graph_node_t* node, scf_vector_t* colors) int bytes = RISC_COLOR_BYTES(c); uint32_t type = RISC_COLOR_TYPE(c); - if (bytes == risc_variable_size(rn->dag_node->var) + if (bytes == f->rops->variable_size (rn->dag_node->var) && type == scf_variable_float(rn->dag_node->var)) return c; } @@ -111,7 +111,7 @@ static int _risc_kcolor_delete(scf_graph_t* graph, int k, scf_vector_t* deleted_ } static int _risc_kcolor_fill(scf_graph_t* graph, int k, scf_vector_t* colors, - scf_vector_t* deleted_nodes) + scf_vector_t* deleted_nodes, scf_function_t* f) { scf_logd("graph->nodes->size: %d\n", graph->nodes->size); int i; @@ -157,7 +157,7 @@ static int _risc_kcolor_fill(scf_graph_t* graph, int k, scf_vector_t* colors, assert(colors2->size >= 0); if (0 == node->color) { - node->color = _risc_color_select(node, colors2); + node->color = _risc_color_select(node, colors2, f); if (0 == node->color) { node->color = -1; scf_logd("colors2->size: %d\n", colors2->size); @@ -336,7 +336,7 @@ static void _risc_kcolor_process_conflict(scf_graph_t* graph) } } -static int _risc_graph_kcolor(scf_graph_t* graph, int k, scf_vector_t* colors) +static int _risc_graph_kcolor(scf_graph_t* graph, int k, scf_vector_t* colors, scf_function_t* f) { int ret = -1; scf_vector_t* colors2 = NULL; @@ -354,7 +354,7 @@ static int _risc_graph_kcolor(scf_graph_t* graph, int k, scf_vector_t* colors) if (0 == _risc_kcolor_check(graph)) { scf_logd("graph->nodes->size: %d\n", graph->nodes->size); - ret = _risc_kcolor_fill(graph, k, colors, deleted_nodes); + ret = _risc_kcolor_fill(graph, k, colors, deleted_nodes, f); if (ret < 0) goto error; @@ -386,12 +386,12 @@ static int _risc_graph_kcolor(scf_graph_t* graph, int k, scf_vector_t* colors) goto error; } - int reg_size0 = risc_variable_size(rn0->dag_node->var); - int reg_size1 = risc_variable_size(rn1->dag_node->var); + int reg_size0 = f->rops->variable_size(rn0->dag_node->var); + int reg_size1 = f->rops->variable_size(rn1->dag_node->var); if (reg_size0 > reg_size1) { - node0->color = _risc_color_select(node0, colors2); + node0->color = _risc_color_select(node0, colors2, f); if (0 == node0->color) goto overflow; @@ -409,7 +409,7 @@ static int _risc_graph_kcolor(scf_graph_t* graph, int k, scf_vector_t* colors) assert(!scf_vector_find(colors2, (void*)node1->color)); } else { - node1->color = _risc_color_select(node1, colors2); + node1->color = _risc_color_select(node1, colors2, f); if (0 == node1->color) goto overflow; @@ -436,7 +436,7 @@ static int _risc_graph_kcolor(scf_graph_t* graph, int k, scf_vector_t* colors) if (ret < 0) goto error; - ret = scf_risc_graph_kcolor(graph, k - 1, colors2); + ret = scf_risc_graph_kcolor(graph, k - 1, colors2, f); if (ret < 0) goto error; @@ -460,7 +460,7 @@ overflow: goto error; node_max->color = -1; - ret = scf_risc_graph_kcolor(graph, k, colors); + ret = scf_risc_graph_kcolor(graph, k, colors, f); if (ret < 0) goto error; @@ -469,7 +469,7 @@ overflow: goto error; } - ret = _risc_kcolor_fill(graph, k, colors, deleted_nodes); + ret = _risc_kcolor_fill(graph, k, colors, deleted_nodes, f); if (ret < 0) goto error; @@ -487,7 +487,7 @@ error: return ret; } -int scf_risc_graph_kcolor(scf_graph_t* graph, int k, scf_vector_t* colors) +int scf_risc_graph_kcolor(scf_graph_t* graph, int k, scf_vector_t* colors, scf_function_t* f) { if (!graph || !colors || 0 == colors->size) { scf_loge("\n"); @@ -496,7 +496,7 @@ int scf_risc_graph_kcolor(scf_graph_t* graph, int k, scf_vector_t* colors) _risc_kcolor_process_conflict(graph); - return _risc_graph_kcolor(graph, k, colors); + return _risc_graph_kcolor(graph, k, colors, f); } diff --git a/native/risc/scf_risc_inst.c b/native/risc/scf_risc_inst.c index d6bedbd..560275f 100644 --- a/native/risc/scf_risc_inst.c +++ b/native/risc/scf_risc_inst.c @@ -29,7 +29,7 @@ } -static int _risc_inst_call_stack_size(scf_3ac_code_t* c) +static int _risc_inst_call_stack_size(scf_3ac_code_t* c, scf_function_t* f) { int stack_size = 0; @@ -41,7 +41,7 @@ static int _risc_inst_call_stack_size(scf_3ac_code_t* c) if (src->dag_node->rabi2) continue; - int size = risc_variable_size(v); + int size = f->rops->variable_size(v); if (size & 0x7) size = (size + 7) >> 3 << 3; @@ -63,7 +63,7 @@ static int _risc_inst_call_argv(scf_native_t* ctx, scf_3ac_code_t* c, scf_functi scf_risc_OpCode_t* lea; scf_risc_OpCode_t* mov; scf_risc_OpCode_t* movx; - scf_instruction_t* inst; + scf_instruction_t* inst; uint32_t opcode; @@ -71,14 +71,15 @@ static int _risc_inst_call_argv(scf_native_t* ctx, scf_3ac_code_t* c, scf_functi int ret; int i; for (i = c->srcs->size - 1; i >= 1; i--) { - scf_3ac_operand_t* src = c->srcs->data[i]; - scf_variable_t* v = src->dag_node->var; - scf_register_t* rd = src->rabi; - scf_register_t* rabi = src->dag_node->rabi2; - scf_register_t* rs = NULL; - int size = risc_variable_size(v); - int is_float = scf_variable_float(v); + scf_3ac_operand_t* src = c->srcs->data[i]; + scf_variable_t* v = src->dag_node->var; + scf_register_t* rd = src->rabi; + scf_register_t* rabi = src->dag_node->rabi2; + scf_register_t* rs = NULL; + + int size = f->rops->variable_size (v); + int is_float = scf_variable_float(v); if (!rabi) { rabi = f->rops->find_register_type_id_bytes(is_float, SCF_RISC_REG_X0, size); @@ -90,16 +91,19 @@ static int _risc_inst_call_argv(scf_native_t* ctx, scf_3ac_code_t* c, scf_functi } } + scf_loge("i: %d, size: %d, v: %s\n", i, size, v->w->text->data); + movx = NULL; if (!is_float) { - mov = risc_find_OpCode(SCF_RISC_MOV, 8, 8, SCF_RISC_G2E); + mov = risc_find_OpCode(SCF_RISC_MOV, f->rops->MAX_BYTES, f->rops->MAX_BYTES, SCF_RISC_G2E); + + if (size < f->rops->MAX_BYTES) { - if (size < 8) { if (scf_variable_signed(v)) - movx = risc_find_OpCode(SCF_RISC_MOVSX, size, 8, SCF_RISC_E2G); + movx = risc_find_OpCode(SCF_RISC_MOVSX, size, f->rops->MAX_BYTES, SCF_RISC_E2G); else if (size < 4) - movx = risc_find_OpCode(SCF_RISC_MOVZX, size, 8, SCF_RISC_E2G); + movx = risc_find_OpCode(SCF_RISC_MOVZX, size, f->rops->MAX_BYTES, SCF_RISC_E2G); } if (0 == src->dag_node->color) { @@ -116,7 +120,7 @@ static int _risc_inst_call_argv(scf_native_t* ctx, scf_3ac_code_t* c, scf_functi return ret; } - rabi = f->rops->find_register_color_bytes(rabi->color, 8); + rabi = f->rops->find_register_color_bytes(rabi->color, f->rops->MAX_BYTES); rs = rabi; } else { if (src->dag_node->color < 0) @@ -153,7 +157,7 @@ static int _risc_inst_call_argv(scf_native_t* ctx, scf_3ac_code_t* c, scf_functi } RISC_SELECT_REG_CHECK(&rs, src->dag_node, c, f, 1); - rs = f->rops->find_register_color_bytes(rs->color, 8); + rs = f->rops->find_register_color_bytes(rs->color, f->rops->MAX_BYTES); } if (movx) { @@ -228,7 +232,7 @@ static int _risc_call_save_ret_regs(scf_3ac_code_t* c, scf_function_t* f, scf_fu r = f->rops->find_register_type_id_bytes(is_float, 0, 8); } else - r = f->rops->find_register_type_id_bytes(is_float, risc_abi_ret_regs[i], 8); + r = f->rops->find_register_type_id_bytes(is_float, f->rops->abi_ret_regs[i], f->rops->MAX_BYTES); int ret = f->rops->overflow_reg(r, c, f); if (ret < 0) { @@ -254,7 +258,7 @@ static int _risc_dst_reg_valid(scf_function_t* f, scf_register_t* rd, scf_regist for (i = abi_idx; i < abi_total; i++) { - r = f->rops->find_register_type_id_bytes(RISC_COLOR_TYPE(rd->color), risc_abi_ret_regs[i], rd->bytes); + r = f->rops->find_register_type_id_bytes(RISC_COLOR_TYPE(rd->color), f->rops->abi_ret_regs[i], rd->bytes); if (RISC_COLOR_CONFLICT(r->color, rd->color)) return 0; @@ -308,7 +312,7 @@ static int _risc_call_update_dsts(scf_native_t* ctx, scf_3ac_code_t* c, scf_func continue; int is_float = scf_variable_float(v); - int dst_size = risc_variable_size (v); + int dst_size = f->rops->variable_size (v); if (is_float) { if (i > 0) { @@ -328,7 +332,7 @@ static int _risc_call_update_dsts(scf_native_t* ctx, scf_3ac_code_t* c, scf_func idx_float++; } else { - rs = f->rops->find_register_type_id_bytes(is_float, risc_abi_ret_regs[idx_int], dst_size); + rs = f->rops->find_register_type_id_bytes(is_float, f->rops->abi_ret_regs[idx_int], dst_size); mov = risc_find_OpCode(SCF_RISC_MOV, dst_size, dst_size, SCF_RISC_G2E); @@ -408,12 +412,16 @@ static int _risc_inst_call_handler(scf_native_t* ctx, scf_3ac_code_t* c) return -EINVAL; } - scf_risc_context_t* risc = ctx->priv; - scf_function_t* f = risc->f; + scf_instruction_t* inst_sp2 = NULL; + scf_instruction_t* inst_sp = NULL; + scf_instruction_t* inst; + + scf_risc_context_t* risc = ctx->priv; + scf_function_t* f = risc->f; - scf_3ac_operand_t* src0 = c->srcs->data[0]; - scf_variable_t* var_pf = src0->dag_node->var; - scf_function_t* pf = var_pf->func_ptr; + scf_3ac_operand_t* src0 = c->srcs->data[0]; + scf_variable_t* var_pf = src0->dag_node->var; + scf_function_t* pf = var_pf->func_ptr; if (SCF_FUNCTION_PTR != var_pf->type || !pf) { scf_loge("\n"); @@ -429,9 +437,6 @@ static int _risc_inst_call_handler(scf_native_t* ctx, scf_3ac_code_t* c) scf_register_t* lr = f->rops->find_register("lr"); scf_register_t* sp = f->rops->find_register("sp"); scf_register_t* x0 = f->rops->find_register("x0"); - scf_instruction_t* inst; - scf_instruction_t* inst_sp = NULL; - scf_instruction_t* inst_sp2 = NULL; lr->used = 1; sp->used = 1; @@ -460,7 +465,7 @@ static int _risc_inst_call_handler(scf_native_t* ctx, scf_3ac_code_t* c) risc_call_rabi(NULL, NULL, c, f); - int32_t stack_size = _risc_inst_call_stack_size(c); + int32_t stack_size = _risc_inst_call_stack_size(c, f); if (stack_size > 0) { inst_sp = risc_make_inst(c, 0); inst_sp2 = risc_make_inst(c, 0); @@ -474,14 +479,16 @@ static int _risc_inst_call_handler(scf_native_t* ctx, scf_3ac_code_t* c) return ret; } - scf_register_t* saved_regs[RISC_ABI_CALLER_SAVES_NB]; + scf_register_t* saved_regs[RISC_ABI_CALLER_SAVES_MAX]; - int save_size = f->rops->caller_save_regs(c, f, risc_abi_caller_saves, RISC_ABI_CALLER_SAVES_NB, stack_size, saved_regs); + int save_size = f->rops->caller_save_regs(c, f, f->rops->abi_caller_saves, f->rops->ABI_CALLER_SAVES_NB, stack_size, saved_regs); if (save_size < 0) { scf_loge("\n"); return save_size; } + scf_loge("stack_size: %d, save_size: %d\n", stack_size, save_size); + if (stack_size > 0) { assert(inst_sp); assert(inst_sp2); @@ -517,19 +524,33 @@ static int _risc_inst_call_handler(scf_native_t* ctx, scf_3ac_code_t* c) inst = NULL; } else return -ENOMEM; + + } else { + scf_vector_del(c->instructions, inst_sp2); + + free(inst_sp2); + inst_sp2 = NULL; } + + } else { + scf_vector_del(c->instructions, inst_sp); + scf_vector_del(c->instructions, inst_sp2); + + free(inst_sp); + free(inst_sp2); + + inst_sp = NULL; + inst_sp2 = NULL; } if (var_pf->const_literal_flag) { assert(0 == src0->dag_node->color); - inst = ctx->iops->BL(c); - RISC_INST_ADD_CHECK(c->instructions, inst); - - scf_rela_t* rela = NULL; - - RISC_RELA_ADD_CHECK(f->text_relas, rela, c, NULL, pf); - rela->type = R_AARCH64_CALL26; + ret = ctx->iops->BL(c, f, pf); + if (ret < 0) { + scf_loge("\n"); + return ret; + } } else { assert(0 != src0->dag_node->color); @@ -559,11 +580,11 @@ static int _risc_inst_call_handler(scf_native_t* ctx, scf_3ac_code_t* c) } int nb_updated = 0; - scf_register_t* updated_regs[RISC_ABI_RET_NB * 2]; + scf_register_t* updated_regs[RISC_ABI_RET_MAX * 2]; if (pf->rets && pf->rets->size > 0 && c->dsts) { - nb_updated = _risc_call_update_dsts(ctx, c, f, updated_regs, RISC_ABI_RET_NB * 2); + nb_updated = _risc_call_update_dsts(ctx, c, f, updated_regs, f->rops->ABI_RET_NB * 2); if (nb_updated < 0) { scf_loge("\n"); return nb_updated; @@ -571,7 +592,7 @@ static int _risc_inst_call_handler(scf_native_t* ctx, scf_3ac_code_t* c) } if (save_size > 0) { - ret = f->rops->pop_regs(c, f, saved_regs, save_size >> 3, updated_regs, nb_updated); + ret = f->rops->pop_regs(c, f, saved_regs, save_size / f->rops->MAX_BYTES, updated_regs, nb_updated); if (ret < 0) { scf_loge("\n"); return ret; @@ -827,7 +848,7 @@ static int _risc_inst_neg_handler(scf_native_t* ctx, scf_3ac_code_t* c) uint32_t opcode; int is_float = scf_variable_float(v); - int size = risc_variable_size(v); + int size = f->rops->variable_size(v); if (!is_float) { @@ -980,7 +1001,7 @@ static int _risc_inst_inc_pointer_handler(scf_native_t* ctx, scf_3ac_code_t* c) scf_register_t* r = NULL; scf_sib_t sib = {0}; - int size = risc_variable_size(vm); + int size = f->rops->variable_size(vm); int ret = risc_pointer_reg(&sib, base->dag_node, member->dag_node, c, f); if (ret < 0) @@ -1047,7 +1068,7 @@ static int _risc_inst_dec_pointer_handler(scf_native_t* ctx, scf_3ac_code_t* c) scf_register_t* r = NULL; scf_sib_t sib = {0}; - int size = risc_variable_size(vm); + int size = f->rops->variable_size(vm); int ret = risc_pointer_reg(&sib, base->dag_node, member->dag_node, c, f); if (ret < 0) @@ -1122,7 +1143,7 @@ static int _risc_inst_inc_post_pointer_handler(scf_native_t* ctx, scf_3ac_code_t scf_register_t* rd = NULL; scf_sib_t sib = {0}; - int size = risc_variable_size(vm); + int size = f->rops->variable_size(vm); int ret = risc_pointer_reg(&sib, base->dag_node, member->dag_node, c, f); if (ret < 0) @@ -1200,7 +1221,7 @@ static int _risc_inst_dec_post_pointer_handler(scf_native_t* ctx, scf_3ac_code_t scf_register_t* rd = NULL; scf_sib_t sib = {0}; - int size = risc_variable_size(vm); + int size = f->rops->variable_size(vm); int ret = risc_pointer_reg(&sib, base->dag_node, member->dag_node, c, f); if (ret < 0) @@ -1814,7 +1835,7 @@ static int _risc_inst_va_start_handler(scf_native_t* ctx, scf_3ac_code_t* c) scf_variable_t* v = ap->dag_node->var; int offset_int = -f->args_int * 8 - 8; - int offset_float = -f->args_float * 8 - RISC_ABI_NB * 8 - 8; + int offset_float = -f->args_float * 8 - f->rops->ABI_NB * 8 - 8; int offset_others = 16; if (v->bp_offset >= 0) { @@ -1963,7 +1984,7 @@ static int _risc_inst_va_arg_handler(scf_native_t* ctx, scf_3ac_code_t* c) RISC_SELECT_REG_CHECK(&rptr, ptr->dag_node, c, f, 0); int is_float = scf_variable_float(v); - int size = risc_variable_size(v); + int size = f->rops->variable_size(v); uint32_t nints = RISC_ABI_NB; uint32_t nfloats = RISC_ABI_NB; @@ -3291,8 +3312,8 @@ static int _risc_inst_cast_handler(scf_native_t* ctx, scf_3ac_code_t* c) scf_variable_t* vs = s->var; scf_variable_t* vd = d->var; - int src_size = risc_variable_size(vs); - int dst_size = risc_variable_size(vd); + int src_size = f->rops->variable_size(vs); + int dst_size = f->rops->variable_size(vd); RISC_SELECT_REG_CHECK(&rd, d, c, f, 0); @@ -3585,8 +3606,8 @@ static int _risc_inst_return_handler(scf_native_t* ctx, scf_3ac_code_t* c) v = src->dag_node->var; - int size = risc_variable_size(v); - int is_float = scf_variable_float(v); + int size = f->rops->variable_size (v); + int is_float = scf_variable_float(v); if (i > 0 && is_float) { scf_loge("\n"); @@ -3607,7 +3628,7 @@ static int _risc_inst_return_handler(scf_native_t* ctx, scf_3ac_code_t* c) return -1; } else { - rd = f->rops->find_register_type_id_bytes(is_float, risc_abi_ret_regs[i], retsize); + rd = f->rops->find_register_type_id_bytes(is_float, f->rops->abi_ret_regs[i], retsize); if (0 == src->dag_node->color) { if (rd->bytes > size) @@ -3714,7 +3735,7 @@ static int _risc_inst_memset_handler(scf_native_t* ctx, scf_3ac_code_t* c) #if 0 #define RISC_MEMSET_LOAD_REG(r, dn) \ do { \ - int size = risc_variable_size(dn->var); \ + int size = f->rops->variable_size(dn->var); \ assert(8 == size); \ \ if (0 == dn->color) { \ @@ -3769,12 +3790,12 @@ static int _risc_inst_end_handler(scf_native_t* ctx, scf_3ac_code_t* c) scf_register_t* r; int i; - for (i = RISC_ABI_CALLEE_SAVES_NB - 1; i >= 0; i--) { + for (i = f->rops->ABI_CALLEE_SAVES_NB - 1; i >= 0; i--) { - r = f->rops->find_register_type_id_bytes(0, risc_abi_callee_saves[i], 8); + r = f->rops->find_register_type_id_bytes(0, f->rops->abi_callee_saves[i], 8); if (!r->used) { - r = f->rops->find_register_type_id_bytes(0, risc_abi_callee_saves[i], 4); + r = f->rops->find_register_type_id_bytes(0, f->rops->abi_callee_saves[i], 4); if (!r->used) continue; @@ -3998,7 +4019,7 @@ static int _risc_inst_assign_handler(scf_native_t* ctx, scf_3ac_code_t* c) assert(0 != d->color); - int size = risc_variable_size(v); + int size = f->rops->variable_size(v); int is_float = scf_variable_float(v); RISC_SELECT_REG_CHECK(&rd, d, c, f, 0); @@ -5011,7 +5032,7 @@ static int _risc_inst_assign_array_index_handler(scf_native_t* ctx, scf_3ac_code scf_instruction_t* inst; int is_float = scf_variable_float(vs); - int size = risc_variable_size (vs); + int size = f->rops->variable_size (vs); if (size > vscale->data.i) size = vscale->data.i; @@ -5093,7 +5114,7 @@ static int _risc_inst_add_assign_array_index_handler(scf_native_t* ctx, scf_3ac_ scf_instruction_t* inst; int is_float = scf_variable_float(vs); - int size = risc_variable_size (vs); + int size = f->rops->variable_size (vs); if (size > vscale->data.i) size = vscale->data.i; @@ -5192,7 +5213,7 @@ static int _risc_inst_sub_assign_array_index_handler(scf_native_t* ctx, scf_3ac_ scf_instruction_t* inst; int is_float = scf_variable_float(vs); - int size = risc_variable_size (vs); + int size = f->rops->variable_size (vs); if (size > vscale->data.i) size = vscale->data.i; @@ -5293,7 +5314,7 @@ static int _risc_inst_and_assign_array_index_handler(scf_native_t* ctx, scf_3ac_ scf_instruction_t* inst; int is_float = scf_variable_float(vs); - int size = risc_variable_size (vs); + int size = f->rops->variable_size (vs); if (size > vscale->data.i) size = vscale->data.i; @@ -5383,7 +5404,7 @@ static int _risc_inst_or_assign_array_index_handler(scf_native_t* ctx, scf_3ac_c scf_instruction_t* inst; int is_float = scf_variable_float(vs); - int size = risc_variable_size (vs); + int size = f->rops->variable_size (vs); if (size > vscale->data.i) size = vscale->data.i; diff --git a/native/risc/scf_risc_rcg.c b/native/risc/scf_risc_rcg.c index 23af842..c106364 100644 --- a/native/risc/scf_risc_rcg.c +++ b/native/risc/scf_risc_rcg.c @@ -302,7 +302,7 @@ static int _risc_rcg_call(scf_native_t* ctx, scf_3ac_code_t* c, scf_graph_t* g) if (c->dsts) { - if (c->dsts->size > RISC_ABI_RET_NB) { + if (c->dsts->size > f->rops->ABI_RET_NB) { scf_loge("\n"); return -EINVAL; } @@ -321,13 +321,13 @@ static int _risc_rcg_call(scf_native_t* ctx, scf_3ac_code_t* c, scf_graph_t* g) continue; int is_float = scf_variable_float(dn->var); - int size = risc_variable_size (dn->var); + int size = f->rops->variable_size (dn->var); if (0 == i) r = f->rops->find_register_type_id_bytes(is_float, SCF_RISC_REG_X0, size); else if (!is_float) - r = f->rops->find_register_type_id_bytes(is_float, risc_abi_ret_regs[i], size); + r = f->rops->find_register_type_id_bytes(is_float, f->rops->abi_ret_regs[i], size); else r = NULL; @@ -383,7 +383,7 @@ static int _risc_rcg_call(scf_native_t* ctx, scf_3ac_code_t* c, scf_graph_t* g) scf_register_t* rabi = NULL; scf_graph_node_t* gn_rabi = NULL; - rabi = f->rops->find_register_type_id_bytes(0, risc_abi_regs[i], dn_pf->var->size); + rabi = f->rops->find_register_type_id_bytes(0, f->rops->abi_regs[i], dn_pf->var->size); ret = _risc_rcg_make_node(&gn_rabi, g, NULL, rabi); if (ret < 0) { @@ -862,7 +862,7 @@ static int _risc_rcg_return_handler(scf_native_t* ctx, scf_3ac_code_t* c, scf_gr dn = src->dag_node; int is_float = scf_variable_float(dn->var); - int size = risc_variable_size(dn->var); + int size = f->rops->variable_size(dn->var); size = size > 4 ? 8 : 4; @@ -874,7 +874,7 @@ static int _risc_rcg_return_handler(scf_native_t* ctx, scf_3ac_code_t* c, scf_gr r = f->rops->find_register_type_id_bytes(is_float, 0, size); } else - r = f->rops->find_register_type_id_bytes(is_float, risc_abi_ret_regs[i], size); + r = f->rops->find_register_type_id_bytes(is_float, f->rops->abi_ret_regs[i], size); ret = _risc_rcg_make_node(&gn, g, dn, r); if (ret < 0) @@ -904,28 +904,6 @@ static int _risc_rcg_memset_handler(scf_native_t* ctx, scf_3ac_code_t* c, scf_gr if (!c->srcs || c->srcs->size != 3) return -EINVAL; #if 0 - for (i = 0; i < c->srcs->size; i++) { - src = c->srcs->data[i]; - dn = src->dag_node; - - int size = risc_variable_size (dn->var); - size = size > 4 ? 8 : 4; - - if (0 == i) - r = risc_find_register_type_id_bytes(0, SCF_RISC_REG_DI, size); - - else if (1 == i) - r = risc_find_register_type_id_bytes(0, SCF_RISC_REG_AX, size); - - else if (2 == i) - r = risc_find_register_type_id_bytes(0, SCF_RISC_REG_CX, size); - else - return -EINVAL; - - ret = _risc_rcg_make_node(&gn, g, dn, r, NULL); - if (ret < 0) - return ret; - } #endif return 0; } diff --git a/native/risc/scf_risc_reg.c b/native/risc/scf_risc_reg.c index 3b7d661..dda0bca 100644 --- a/native/risc/scf_risc_reg.c +++ b/native/risc/scf_risc_reg.c @@ -7,8 +7,8 @@ int risc_save_var2(scf_dag_node_t* dn, scf_register_t* r, scf_3ac_code_t* c, scf scf_risc_OpCode_t* mov; scf_instruction_t* inst; - int size = risc_variable_size(v); - int is_float = scf_variable_float(v); + int size = f->rops->variable_size (v); + int is_float = scf_variable_float(v); assert(size == r->bytes); @@ -89,8 +89,8 @@ int risc_load_const(scf_register_t* r, scf_dag_node_t* dn, scf_3ac_code_t* c, sc v = dn->var; r->used = 1; - int size = risc_variable_size(v); - int is_float = scf_variable_float(v); + int size = f->rops->variable_size (v); + int is_float = scf_variable_float(v); if (SCF_FUNCTION_PTR == v->type) { @@ -130,8 +130,8 @@ int risc_load_reg(scf_register_t* r, scf_dag_node_t* dn, scf_3ac_code_t* c, scf_ scf_instruction_t* inst; scf_rela_t* rela = NULL; - int is_float = scf_variable_float(dn->var); - int var_size = risc_variable_size(dn->var); + int is_float = scf_variable_float(dn->var); + int var_size = f->rops->variable_size (dn->var); r->used = 1; @@ -209,7 +209,7 @@ int risc_select_reg(scf_register_t** preg, scf_dag_node_t* dn, scf_3ac_code_t* c int ret; int is_float = scf_variable_float(dn->var); - int var_size = risc_variable_size(dn->var); + int var_size = f->rops->variable_size(dn->var); if (dn->color > 0) { r = f->rops->find_register_color(dn->color); @@ -361,7 +361,7 @@ int risc_pointer_reg(scf_sib_t* sib, scf_dag_node_t* base, scf_dag_node_t* membe sib->index = NULL; sib->scale = 0; sib->disp = disp; - sib->size = risc_variable_size(vm); + sib->size = f->rops->variable_size(vm); return 0; } @@ -562,17 +562,17 @@ void risc_call_rabi(int* p_nints, int* p_nfloats, scf_3ac_code_t* c, scf_functio src = c->srcs->data[i]; dn = src->dag_node; - int is_float = scf_variable_float(dn->var); - int size = risc_variable_size (dn->var); + int is_float = scf_variable_float(dn->var); + int size = f->rops->variable_size (dn->var); if (is_float) { - if (nfloats < RISC_ABI_NB) - dn->rabi2 = f->rops->find_register_type_id_bytes(is_float, risc_abi_float_regs[nfloats++], size); + if (nfloats < f->rops->ABI_NB) + dn->rabi2 = f->rops->find_register_type_id_bytes(is_float, f->rops->abi_float_regs[nfloats++], size); else dn->rabi2 = NULL; } else { - if (nints < RISC_ABI_NB) - dn->rabi2 = f->rops->find_register_type_id_bytes(is_float, risc_abi_regs[nints++], size); + if (nints < f->rops->ABI_NB) + dn->rabi2 = f->rops->find_register_type_id_bytes(is_float, f->rops->abi_regs[nints++], size); else dn->rabi2 = NULL; } diff --git a/native/risc/scf_risc_reg.h b/native/risc/scf_risc_reg.h index 4fea8c2..abd1e68 100644 --- a/native/risc/scf_risc_reg.h +++ b/native/risc/scf_risc_reg.h @@ -31,127 +31,17 @@ assert(dn->color > 0); \ } while (0) -static uint32_t risc_abi_regs[] = -{ - SCF_RISC_REG_X0, - SCF_RISC_REG_X1, - SCF_RISC_REG_X2, - SCF_RISC_REG_X3, - SCF_RISC_REG_X4, - SCF_RISC_REG_X5, - SCF_RISC_REG_X6, - SCF_RISC_REG_X7, -}; - -static uint32_t risc_abi_float_regs[] = -{ - SCF_RISC_REG_D0, - SCF_RISC_REG_D1, - SCF_RISC_REG_D2, - SCF_RISC_REG_D3, - SCF_RISC_REG_D4, - SCF_RISC_REG_D5, - SCF_RISC_REG_D6, - SCF_RISC_REG_D7, -}; -#define RISC_ABI_NB (sizeof(risc_abi_regs) / sizeof(risc_abi_regs[0])) - -static uint32_t risc_abi_ret_regs[] = -{ - SCF_RISC_REG_X0, - SCF_RISC_REG_X1, - SCF_RISC_REG_X2, - SCF_RISC_REG_X3, -}; -#define RISC_ABI_RET_NB (sizeof(risc_abi_ret_regs) / sizeof(risc_abi_ret_regs[0])) - -static uint32_t risc_abi_caller_saves[] = -{ - SCF_RISC_REG_X0, - SCF_RISC_REG_X1, - SCF_RISC_REG_X2, - SCF_RISC_REG_X3, - SCF_RISC_REG_X4, - SCF_RISC_REG_X5, - SCF_RISC_REG_X6, - SCF_RISC_REG_X7, - - SCF_RISC_REG_X9, - SCF_RISC_REG_X10, - SCF_RISC_REG_X11, - SCF_RISC_REG_X12, - SCF_RISC_REG_X13, - SCF_RISC_REG_X14, - SCF_RISC_REG_X15, -}; -#define RISC_ABI_CALLER_SAVES_NB (sizeof(risc_abi_caller_saves) / sizeof(risc_abi_caller_saves[0])) - -static uint32_t risc_abi_callee_saves[] = -{ - SCF_RISC_REG_X19, - SCF_RISC_REG_X20, - SCF_RISC_REG_X21, - SCF_RISC_REG_X22, - SCF_RISC_REG_X23, - SCF_RISC_REG_X24, - SCF_RISC_REG_X25, - SCF_RISC_REG_X26, - SCF_RISC_REG_X27, - SCF_RISC_REG_X28, - SCF_RISC_REG_X29, - SCF_RISC_REG_X30, -}; -#define RISC_ABI_CALLEE_SAVES_NB (sizeof(risc_abi_callee_saves) / sizeof(risc_abi_callee_saves[0])) - -static inline int risc_variable_size(scf_variable_t* v) -{ - if (v->nb_dimentions > 0) - return 8; - - if (v->type >= SCF_STRUCT && 0 == v->nb_pointers) - return 8; - - return v->size < 4 ? 4 : v->size; -} - -typedef int (*risc_sib_fill_pt)(scf_sib_t* sib, scf_dag_node_t* base, scf_dag_node_t* index, scf_3ac_code_t* c, scf_function_t* f); - -int risc_registers_init(); -int risc_registers_reset(); -void risc_registers_clear(); -scf_vector_t* risc_register_colors(); - -scf_register_t* risc_find_register(const char* name); - -scf_register_t* risc_find_register_type_id_bytes(uint32_t type, uint32_t id, int bytes); - -scf_register_t* risc_find_register_color(intptr_t color); - -scf_register_t* risc_find_register_color_bytes(intptr_t color, int bytes); - -scf_register_t* risc_find_abi_register(int index, int bytes); - -scf_register_t* risc_select_overflowed_reg(scf_dag_node_t* dn, scf_3ac_code_t* c, int is_float); - -int risc_reg_cached_vars(scf_register_t* r); - -int risc_save_var(scf_dag_node_t* dn, scf_3ac_code_t* c, scf_function_t* f); +#define RISC_ABI_CALLER_SAVES_MAX 32 +#define RISC_ABI_RET_MAX 8 -int risc_save_var2(scf_dag_node_t* dn, scf_register_t* r, scf_3ac_code_t* c, scf_function_t* f); - -int risc_pop_regs(scf_3ac_code_t* c, scf_function_t* f, scf_register_t** regs, int nb_regs, scf_register_t** updated_regs, int nb_updated); +int risc_save_var (scf_dag_node_t* dn, scf_3ac_code_t* c, scf_function_t* f); -int risc_caller_save_regs(scf_3ac_code_t* c, scf_function_t* f, uint32_t* regs, int nb_regs, int stack_size, scf_register_t** saved_regs); +int risc_save_var2(scf_dag_node_t* dn, scf_register_t* r, scf_3ac_code_t* c, scf_function_t* f); -int risc_save_reg(scf_register_t* r, scf_3ac_code_t* c, scf_function_t* f); +int risc_save_reg (scf_register_t* r, scf_3ac_code_t* c, scf_function_t* f); int risc_load_const(scf_register_t* r, scf_dag_node_t* dn, scf_3ac_code_t* c, scf_function_t* f); int risc_load_reg (scf_register_t* r, scf_dag_node_t* dn, scf_3ac_code_t* c, scf_function_t* f); -int risc_reg_used (scf_register_t* r, scf_dag_node_t* dn); - -int risc_overflow_reg (scf_register_t* r, scf_3ac_code_t* c, scf_function_t* f); -int risc_overflow_reg2(scf_register_t* r, scf_dag_node_t* dn, scf_3ac_code_t* c, scf_function_t* f); -int risc_overflow_reg3(scf_register_t* r, scf_dag_node_t* dn, scf_3ac_code_t* c, scf_function_t* f); int risc_select_reg(scf_register_t** preg, scf_dag_node_t* dn, scf_3ac_code_t* c, scf_function_t* f, int load_flag); @@ -165,39 +55,5 @@ int risc_array_index_reg(scf_sib_t* sib, scf_dag_node_t* base, s void risc_call_rabi(int* p_nints, int* p_nfloats, scf_3ac_code_t* c, scf_function_t* f); -static inline int risc_inst_data_is_reg(scf_inst_data_t* id) -{ - scf_register_t* fp = (scf_register_t*)risc_find_register("fp"); - scf_register_t* sp = (scf_register_t*)risc_find_register("sp"); - - if (!id->flag && id->base && id->base != sp && id->base != fp && 0 == id->imm_size) - return 1; - return 0; -} - -static inline int risc_inst_data_is_local(scf_inst_data_t* id) -{ - scf_register_t* fp = (scf_register_t*)risc_find_register("fp"); - scf_register_t* sp = (scf_register_t*)risc_find_register("sp"); - - if (id->flag && (id->base == fp || id->base == sp)) - return 1; - return 0; -} - -static inline int risc_inst_data_is_global(scf_inst_data_t* id) -{ - if (id->flag && !id->base) - return 1; - return 0; -} - -static inline int risc_inst_data_is_const(scf_inst_data_t* id) -{ - if (!id->flag && id->imm_size > 0) - return 1; - return 0; -} - #endif diff --git a/native/risc/scf_risc_reg_arm32.c b/native/risc/scf_risc_reg_arm32.c new file mode 100644 index 0000000..36108b1 --- /dev/null +++ b/native/risc/scf_risc_reg_arm32.c @@ -0,0 +1,937 @@ +#include"scf_risc.h" + +#define SCF_RISC_REG_FP 11 +#define SCF_RISC_REG_SP 13 +#define SCF_RISC_REG_LR 14 +#define SCF_RISC_REG_PC 15 + +scf_register_t arm32_registers[] = { + + {0, 1, "b0", RISC_COLOR(0, 0, 0x1), NULL, 0, 0}, + {0, 2, "h0", RISC_COLOR(0, 0, 0x3), NULL, 0, 0}, + {0, 4, "x0", RISC_COLOR(0, 0, 0xf), NULL, 0, 0}, + + {1, 1, "b1", RISC_COLOR(0, 1, 0x1), NULL, 0, 0}, + {1, 2, "h1", RISC_COLOR(0, 1, 0x3), NULL, 0, 0}, + {1, 4, "x1", RISC_COLOR(0, 1, 0xf), NULL, 0, 0}, + + {2, 1, "b2", RISC_COLOR(0, 2, 0x1), NULL, 0, 0}, + {2, 2, "h2", RISC_COLOR(0, 2, 0x3), NULL, 0, 0}, + {2, 4, "x2", RISC_COLOR(0, 2, 0xf), NULL, 0, 0}, + + {3, 1, "b3", RISC_COLOR(0, 3, 0x1), NULL, 0, 0}, + {3, 2, "h3", RISC_COLOR(0, 3, 0x3), NULL, 0, 0}, + {3, 4, "x3", RISC_COLOR(0, 3, 0xf), NULL, 0, 0}, + + {4, 1, "b4", RISC_COLOR(0, 4, 0x1), NULL, 0, 0}, + {4, 2, "h4", RISC_COLOR(0, 4, 0x3), NULL, 0, 0}, + {4, 4, "x4", RISC_COLOR(0, 4, 0xf), NULL, 0, 0}, + + {5, 1, "b5", RISC_COLOR(0, 5, 0x1), NULL, 0, 0}, + {5, 2, "h5", RISC_COLOR(0, 5, 0x3), NULL, 0, 0}, + {5, 4, "x5", RISC_COLOR(0, 5, 0xf), NULL, 0, 0}, + + {6, 1, "b6", RISC_COLOR(0, 6, 0x1), NULL, 0, 0}, + {6, 2, "h6", RISC_COLOR(0, 6, 0x3), NULL, 0, 0}, + {6, 4, "x6", RISC_COLOR(0, 6, 0xf), NULL, 0, 0}, + + {7, 1, "b7", RISC_COLOR(0, 7, 0x1), NULL, 0, 0}, + {7, 2, "h7", RISC_COLOR(0, 7, 0x3), NULL, 0, 0}, + {7, 4, "x7", RISC_COLOR(0, 7, 0xf), NULL, 0, 0}, + + {8, 1, "b8", RISC_COLOR(0, 8, 0x1), NULL, 0, 0}, + {8, 2, "h8", RISC_COLOR(0, 8, 0x3), NULL, 0, 0}, + {8, 4, "x8", RISC_COLOR(0, 8, 0xf), NULL, 0, 0}, + + {9, 1, "b9", RISC_COLOR(0, 9, 0x1), NULL, 0, 0}, + {9, 2, "h9", RISC_COLOR(0, 9, 0x3), NULL, 0, 0}, + {9, 4, "x9", RISC_COLOR(0, 9, 0xf), NULL, 0, 0}, + + {10, 1, "b10", RISC_COLOR(0, 10, 0x1), NULL, 0, 0}, + {10, 2, "h10", RISC_COLOR(0, 10, 0x3), NULL, 0, 0}, + {10, 4, "x10", RISC_COLOR(0, 10, 0xf), NULL, 0, 0}, + + {11, 4, "fp", RISC_COLOR(0, 11, 0xf), NULL, 0, 0}, + + {12, 4, "x12", RISC_COLOR(0, 12, 0xf), NULL, 0, 0}, + + {13, 4, "sp", RISC_COLOR(0, 13, 0xf), NULL, 0, 0}, + + {14, 4, "lr", RISC_COLOR(0, 14, 0xf), NULL, 0, 0}, + +// {15, 4, "pc", RISC_COLOR(0, 15, 0xf), NULL, 0, 0}, + +#if 0 + {0, 2, "h0", RISC_COLOR(1, 0, 0x3), NULL, 0, 0}, + {0, 4, "s0", RISC_COLOR(1, 0, 0xf), NULL, 0, 0}, + {0, 8, "d0", RISC_COLOR(1, 0, 0xff), NULL, 0, 0}, + + {1, 2, "h1", RISC_COLOR(1, 1, 0x3), NULL, 0, 0}, + {1, 4, "s1", RISC_COLOR(1, 1, 0xf), NULL, 0, 0}, + {1, 8, "d1", RISC_COLOR(1, 1, 0xff), NULL, 0, 0}, + + {2, 2, "h2", RISC_COLOR(1, 2, 0x3), NULL, 0, 0}, + {2, 4, "s2", RISC_COLOR(1, 2, 0xf), NULL, 0, 0}, + {2, 8, "d2", RISC_COLOR(1, 2, 0xff), NULL, 0, 0}, + + {3, 2, "h3", RISC_COLOR(1, 3, 0x3), NULL, 0, 0}, + {3, 4, "s3", RISC_COLOR(1, 3, 0xf), NULL, 0, 0}, + {3, 8, "d3", RISC_COLOR(1, 3, 0xff), NULL, 0, 0}, + + {4, 2, "h4", RISC_COLOR(1, 4, 0x3), NULL, 0, 0}, + {4, 4, "s4", RISC_COLOR(1, 4, 0xf), NULL, 0, 0}, + {4, 8, "d4", RISC_COLOR(1, 4, 0xff), NULL, 0, 0}, + + {5, 2, "h5", RISC_COLOR(1, 5, 0x3), NULL, 0, 0}, + {5, 4, "s5", RISC_COLOR(1, 5, 0xf), NULL, 0, 0}, + {5, 8, "d5", RISC_COLOR(1, 5, 0xff), NULL, 0, 0}, + + {6, 2, "h6", RISC_COLOR(1, 6, 0x3), NULL, 0, 0}, + {6, 4, "s6", RISC_COLOR(1, 6, 0xf), NULL, 0, 0}, + {6, 8, "d6", RISC_COLOR(1, 6, 0xff), NULL, 0, 0}, + + {7, 2, "h7", RISC_COLOR(1, 7, 0x3), NULL, 0, 0}, + {7, 4, "s7", RISC_COLOR(1, 7, 0xf), NULL, 0, 0}, + {7, 8, "d7", RISC_COLOR(1, 7, 0xff), NULL, 0, 0}, + + {8, 2, "h8", RISC_COLOR(1, 8, 0x3), NULL, 0, 0}, + {8, 4, "s8", RISC_COLOR(1, 8, 0xf), NULL, 0, 0}, + {8, 8, "d8", RISC_COLOR(1, 8, 0xff), NULL, 0, 0}, + + {9, 2, "h9", RISC_COLOR(1, 9, 0x3), NULL, 0, 0}, + {9, 4, "s9", RISC_COLOR(1, 9, 0xf), NULL, 0, 0}, + {9, 8, "d9", RISC_COLOR(1, 9, 0xff), NULL, 0, 0}, + + {10, 2, "h10", RISC_COLOR(1, 10, 0x3), NULL, 0, 0}, + {10, 4, "s10", RISC_COLOR(1, 10, 0xf), NULL, 0, 0}, + {10, 8, "d10", RISC_COLOR(1, 10, 0xff), NULL, 0, 0}, + + {11, 2, "h11", RISC_COLOR(1, 11, 0x3), NULL, 0, 0}, + {11, 4, "s11", RISC_COLOR(1, 11, 0xf), NULL, 0, 0}, + {11, 8, "d11", RISC_COLOR(1, 11, 0xff), NULL, 0, 0}, + + {12, 2, "h12", RISC_COLOR(1, 12, 0x3), NULL, 0, 0}, + {12, 4, "s12", RISC_COLOR(1, 12, 0xf), NULL, 0, 0}, + {12, 8, "d12", RISC_COLOR(1, 12, 0xff), NULL, 0, 0}, + + {13, 2, "h13", RISC_COLOR(1, 13, 0x3), NULL, 0, 0}, + {13, 4, "s13", RISC_COLOR(1, 13, 0xf), NULL, 0, 0}, + {13, 8, "d13", RISC_COLOR(1, 13, 0xff), NULL, 0, 0}, + + {14, 2, "h14", RISC_COLOR(1, 14, 0x3), NULL, 0, 0}, + {14, 4, "s14", RISC_COLOR(1, 14, 0xf), NULL, 0, 0}, + {14, 8, "d14", RISC_COLOR(1, 14, 0xff), NULL, 0, 0}, + + {15, 2, "h15", RISC_COLOR(1, 15, 0x3), NULL, 0, 0}, + {15, 4, "s15", RISC_COLOR(1, 15, 0xf), NULL, 0, 0}, + {15, 8, "d15", RISC_COLOR(1, 15, 0xff), NULL, 0, 0}, + + {16, 2, "h16", RISC_COLOR(1, 16, 0x3), NULL, 0, 0}, + {16, 4, "s16", RISC_COLOR(1, 16, 0xf), NULL, 0, 0}, + {16, 8, "d16", RISC_COLOR(1, 16, 0xff), NULL, 0, 0}, + + {17, 2, "h17", RISC_COLOR(1, 17, 0x3), NULL, 0, 0}, + {17, 4, "s17", RISC_COLOR(1, 17, 0xf), NULL, 0, 0}, + {17, 8, "d17", RISC_COLOR(1, 17, 0xff), NULL, 0, 0}, + + {18, 2, "h18", RISC_COLOR(1, 18, 0x3), NULL, 0, 0}, + {18, 4, "s18", RISC_COLOR(1, 18, 0xf), NULL, 0, 0}, + {18, 8, "d18", RISC_COLOR(1, 18, 0xff), NULL, 0, 0}, + + {19, 2, "h19", RISC_COLOR(1, 19, 0x3), NULL, 0, 0}, + {19, 4, "s19", RISC_COLOR(1, 19, 0xf), NULL, 0, 0}, + {19, 8, "d19", RISC_COLOR(1, 19, 0xff), NULL, 0, 0}, + + {20, 2, "h20", RISC_COLOR(1, 20, 0x3), NULL, 0, 0}, + {20, 4, "s20", RISC_COLOR(1, 20, 0xf), NULL, 0, 0}, + {20, 8, "d20", RISC_COLOR(1, 20, 0xff), NULL, 0, 0}, + + {21, 2, "h21", RISC_COLOR(1, 21, 0x3), NULL, 0, 0}, + {21, 4, "s21", RISC_COLOR(1, 21, 0xf), NULL, 0, 0}, + {21, 8, "d21", RISC_COLOR(1, 21, 0xff), NULL, 0, 0}, + + {22, 2, "h22", RISC_COLOR(1, 22, 0x3), NULL, 0, 0}, + {22, 4, "s22", RISC_COLOR(1, 22, 0xf), NULL, 0, 0}, + {22, 8, "d22", RISC_COLOR(1, 22, 0xff), NULL, 0, 0}, + + {23, 2, "h23", RISC_COLOR(1, 23, 0x3), NULL, 0, 0}, + {23, 4, "s23", RISC_COLOR(1, 23, 0xf), NULL, 0, 0}, + {23, 8, "d23", RISC_COLOR(1, 23, 0xff), NULL, 0, 0}, + + {24, 2, "h24", RISC_COLOR(1, 24, 0x3), NULL, 0, 0}, + {24, 4, "s24", RISC_COLOR(1, 24, 0xf), NULL, 0, 0}, + {24, 8, "d24", RISC_COLOR(1, 24, 0xff), NULL, 0, 0}, + + {25, 2, "h25", RISC_COLOR(1, 25, 0x3), NULL, 0, 0}, + {25, 4, "s25", RISC_COLOR(1, 25, 0xf), NULL, 0, 0}, + {25, 8, "d25", RISC_COLOR(1, 25, 0xff), NULL, 0, 0}, + + {26, 2, "h26", RISC_COLOR(1, 26, 0x3), NULL, 0, 0}, + {26, 4, "s26", RISC_COLOR(1, 26, 0xf), NULL, 0, 0}, + {26, 8, "d26", RISC_COLOR(1, 26, 0xff), NULL, 0, 0}, + + {27, 2, "h27", RISC_COLOR(1, 27, 0x3), NULL, 0, 0}, + {27, 4, "s27", RISC_COLOR(1, 27, 0xf), NULL, 0, 0}, + {27, 8, "d27", RISC_COLOR(1, 27, 0xff), NULL, 0, 0}, + + {28, 2, "h28", RISC_COLOR(1, 28, 0x3), NULL, 0, 0}, + {28, 4, "s28", RISC_COLOR(1, 28, 0xf), NULL, 0, 0}, + {28, 8, "d28", RISC_COLOR(1, 28, 0xff), NULL, 0, 0}, + + {29, 2, "h29", RISC_COLOR(1, 29, 0x3), NULL, 0, 0}, + {29, 4, "s29", RISC_COLOR(1, 29, 0xf), NULL, 0, 0}, + {29, 8, "d29", RISC_COLOR(1, 29, 0xff), NULL, 0, 0}, + + {30, 2, "h30", RISC_COLOR(1, 30, 0x3), NULL, 0, 0}, + {30, 4, "s30", RISC_COLOR(1, 30, 0xf), NULL, 0, 0}, + {30, 8, "d30", RISC_COLOR(1, 30, 0xff), NULL, 0, 0}, + + {31, 2, "h31", RISC_COLOR(1, 31, 0x3), NULL, 0, 0}, + {31, 4, "s31", RISC_COLOR(1, 31, 0xf), NULL, 0, 0}, + {31, 8, "d31", RISC_COLOR(1, 31, 0xff), NULL, 0, 0}, +#endif +}; + +static uint32_t arm32_abi_regs[] = +{ + SCF_RISC_REG_X0, + SCF_RISC_REG_X1, + SCF_RISC_REG_X2, + SCF_RISC_REG_X3, +}; + +static uint32_t arm32_abi_float_regs[] = +{ + SCF_RISC_REG_D0, + SCF_RISC_REG_D1, + SCF_RISC_REG_D2, + SCF_RISC_REG_D3, + SCF_RISC_REG_D4, + SCF_RISC_REG_D5, + SCF_RISC_REG_D6, + SCF_RISC_REG_D7, +}; + +static uint32_t arm32_abi_ret_regs[] = +{ + SCF_RISC_REG_X0, + SCF_RISC_REG_X1, + SCF_RISC_REG_X2, + SCF_RISC_REG_X3, +}; + +static uint32_t arm32_abi_caller_saves[] = +{ + SCF_RISC_REG_X0, + SCF_RISC_REG_X1, + SCF_RISC_REG_X2, + SCF_RISC_REG_X3, +}; + +static uint32_t arm32_abi_callee_saves[] = +{ + SCF_RISC_REG_X4, + SCF_RISC_REG_X5, + SCF_RISC_REG_X6, + SCF_RISC_REG_X7, + SCF_RISC_REG_X8, + SCF_RISC_REG_X9, + SCF_RISC_REG_X10, + SCF_RISC_REG_X11, + SCF_RISC_REG_X13, + SCF_RISC_REG_X14, +}; + +static int arm32_variable_size(scf_variable_t* v) +{ + if (v->nb_dimentions > 0) + return 4; + + if (v->nb_pointers > 0) + return 4; + + if (v->type >= SCF_STRUCT) + return 4; + + return v->size; +} + +scf_register_t* arm32_find_register(const char* name) +{ + int i; + for (i = 0; i < sizeof(arm32_registers) / sizeof(arm32_registers[0]); i++) { + + scf_register_t* r = &(arm32_registers[i]); + + if (!strcmp(r->name, name)) + return r; + } + return NULL; +} + +scf_register_t* arm32_find_register_type_id_bytes(uint32_t type, uint32_t id, int bytes) +{ + int i; + + if (bytes > 4 && 0 == type) + bytes = 4; + + for (i = 0; i < sizeof(arm32_registers) / sizeof(arm32_registers[0]); i++) { + + scf_register_t* r = &(arm32_registers[i]); + + if (RISC_COLOR_TYPE(r->color) == type && r->id == id && r->bytes == bytes) + return r; + } + return NULL; +} + +scf_register_t* arm32_find_register_color(intptr_t color) +{ + int i; + for (i = 0; i < sizeof(arm32_registers) / sizeof(arm32_registers[0]); i++) { + + scf_register_t* r = &(arm32_registers[i]); + + if (r->color == color) + return r; + } + return NULL; +} + +scf_register_t* arm32_find_register_color_bytes(intptr_t color, int bytes) +{ + int i; + + if (bytes > 4 && 0 == RISC_COLOR_TYPE(color)) + bytes = 4; + + for (i = 0; i < sizeof(arm32_registers) / sizeof(arm32_registers[0]); i++) { + + scf_register_t* r = &(arm32_registers[i]); + + if (RISC_COLOR_CONFLICT(r->color, color) && r->bytes == bytes) + return r; + } + return NULL; +} + +scf_vector_t* arm32_register_colors() +{ + scf_vector_t* colors = scf_vector_alloc(); + if (!colors) + return NULL; + + int i; + for (i = 0; i < sizeof(arm32_registers) / sizeof(arm32_registers[0]); i++) { + + scf_register_t* r = &(arm32_registers[i]); + + if (SCF_RISC_REG_SP == r->id + || SCF_RISC_REG_FP == r->id + || SCF_RISC_REG_LR == r->id + || SCF_RISC_REG_X12 == r->id) + continue; + + int ret = scf_vector_add(colors, (void*)r->color); + if (ret < 0) { + scf_vector_free(colors); + return NULL; + } + } +#if 0 + srand(time(NULL)); + for (i = 0; i < colors->size; i++) { + int j = rand() % colors->size; + + void* t = colors->data[i]; + colors->data[i] = colors->data[j]; + colors->data[j] = t; + } +#endif + return colors; +} + +int arm32_reg_cached_vars(scf_register_t* r) +{ + int nb_vars = 0; + int i; + + for (i = 0; i < sizeof(arm32_registers) / sizeof(arm32_registers[0]); i++) { + + scf_register_t* r2 = &(arm32_registers[i]); + + if (SCF_RISC_REG_SP == r2->id + || SCF_RISC_REG_FP == r2->id + || SCF_RISC_REG_LR == r2->id + || SCF_RISC_REG_X12 == r2->id) + continue; + + if (!RISC_COLOR_CONFLICT(r->color, r2->color)) + continue; + + nb_vars += r2->dag_nodes->size; + } + + return nb_vars; +} + +int arm32_registers_init() +{ + int i; + for (i = 0; i < sizeof(arm32_registers) / sizeof(arm32_registers[0]); i++) { + + scf_register_t* r = &(arm32_registers[i]); + + if (SCF_RISC_REG_SP == r->id + || SCF_RISC_REG_FP == r->id + || SCF_RISC_REG_LR == r->id + || SCF_RISC_REG_X12 == r->id) + continue; + + assert(!r->dag_nodes); + + r->dag_nodes = scf_vector_alloc(); + if (!r->dag_nodes) + return -ENOMEM; + + r->used = 0; + } + + return 0; +} + +void arm32_registers_clear() +{ + int i; + for (i = 0; i < sizeof(arm32_registers) / sizeof(arm32_registers[0]); i++) { + + scf_register_t* r = &(arm32_registers[i]); + + if (SCF_RISC_REG_SP == r->id + || SCF_RISC_REG_FP == r->id + || SCF_RISC_REG_LR == r->id + || SCF_RISC_REG_X12 == r->id) + continue; + + if (r->dag_nodes) { + scf_vector_free(r->dag_nodes); + r->dag_nodes = NULL; + } + + r->used = 0; + } +} + +static scf_register_t* risc_reg_cached_min_vars(scf_register_t** regs, int nb_regs) +{ + scf_register_t* r_min = NULL; + + int min = 0; + int i; + + for (i = 0; i < nb_regs; i++) { + scf_register_t* r = regs[i]; + + int nb_vars = arm32_reg_cached_vars(r); + + if (!r_min) { + r_min = r; + min = nb_vars; + continue; + } + + if (min > nb_vars) { + r_min = r; + min = nb_vars; + } + } + + return r_min; +} + +int arm32_caller_save_regs(scf_3ac_code_t* c, scf_function_t* f, uint32_t* regs, int nb_regs, int stack_size, scf_register_t** saved_regs) +{ + int i; + int j; + scf_instruction_t* inst; + scf_register_t* r; + scf_register_t* r2; + scf_register_t* sp = arm32_find_register("sp"); + + uint32_t opcode; + + int ret; + int size = 0; + int k = 0; + + for (j = 0; j < nb_regs; j++) { + r2 = arm32_find_register_type_id_bytes(0, regs[j], f->rops->MAX_BYTES); + + for (i = 0; i < sizeof(arm32_registers) / sizeof(arm32_registers[0]); i++) { + r = &(arm32_registers[i]); + + if (SCF_RISC_REG_SP == r->id + || SCF_RISC_REG_FP == r->id + || SCF_RISC_REG_LR == r->id + || SCF_RISC_REG_X12 == r->id) + continue; + + if (0 == r->dag_nodes->size) + continue; + + if (RISC_COLOR_CONFLICT(r2->color, r->color)) + break; + } + + if (i == sizeof(arm32_registers) / sizeof(arm32_registers[0])) + continue; + + if (stack_size > 0) { + ret = f->iops->G2P(c, f, r2, sp, size + stack_size, r2->bytes); + if (ret < 0) + return ret; + } else { + inst = f->iops->PUSH(NULL, r2); + RISC_INST_ADD_CHECK(c->instructions, inst); + } + + saved_regs[k++] = r2; + size += r2->bytes; + } + + while (size & 0xf) { + r2 = saved_regs[k - 1]; + + if (stack_size > 0) { + ret = f->iops->G2P(c, f, r2, sp, size + stack_size, r2->bytes); + if (ret < 0) + return ret; + + } else { + inst = f->iops->PUSH(NULL, r2); + RISC_INST_ADD_CHECK(c->instructions, inst); + } + + saved_regs[k++] = r2; + size += r2->bytes; + } + + if (stack_size > 0) { + for (j = 0; j < k / 2; j++) { + + i = k - 1 - j; + SCF_XCHG(saved_regs[i], saved_regs[j]); + } + } + + return size; +} + +int arm32_pop_regs(scf_3ac_code_t* c, scf_function_t* f, scf_register_t** regs, int nb_regs, scf_register_t** updated_regs, int nb_updated) +{ + int i; + int j; + + scf_register_t* sp = arm32_find_register("sp"); + scf_register_t* r; + scf_register_t* r2; + scf_instruction_t* inst; + + for (j = nb_regs - 1; j >= 0; j--) { + r2 = regs[j]; + + for (i = 0; i < sizeof(arm32_registers) / sizeof(arm32_registers[0]); i++) { + r = &(arm32_registers[i]); + + if (SCF_RISC_REG_SP == r->id + || SCF_RISC_REG_FP == r->id + || SCF_RISC_REG_LR == r->id + || SCF_RISC_REG_X12 == r->id) + continue; + + if (0 == r->dag_nodes->size) + continue; + + if (RISC_COLOR_CONFLICT(r2->color, r->color)) + break; + } + + if (i == sizeof(arm32_registers) / sizeof(arm32_registers[0])) + continue; + + for (i = 0; i < nb_updated; i++) { + + r = updated_regs[i]; + + if (RISC_COLOR_CONFLICT(r2->color, r->color)) + break; + } + + if (i == nb_updated) { + inst = f->iops->POP(c, r2); + RISC_INST_ADD_CHECK(c->instructions, inst); + } else { + inst = f->iops->ADD_IMM(c, sp, sp, 4); + RISC_INST_ADD_CHECK(c->instructions, inst); + } + } + return 0; +} + +int arm32_registers_reset() +{ + int i; + for (i = 0; i < sizeof(arm32_registers) / sizeof(arm32_registers[0]); i++) { + + scf_register_t* r = &(arm32_registers[i]); + + if (SCF_RISC_REG_SP == r->id + || SCF_RISC_REG_FP == r->id + || SCF_RISC_REG_LR == r->id + || SCF_RISC_REG_X12 == r->id) + continue; + + if (!r->dag_nodes) + continue; + + int j = 0; + while (j < r->dag_nodes->size) { + scf_dag_node_t* dn = r->dag_nodes->data[j]; + + if (dn->var->w) + scf_logw("drop: v_%d_%d/%s\n", dn->var->w->line, dn->var->w->pos, dn->var->w->text->data); + else + scf_logw("drop: v_%#lx\n", 0xffff & (uintptr_t)dn->var); + + int ret = scf_vector_del(r->dag_nodes, dn); + if (ret < 0) { + scf_loge("\n"); + return ret; + } + + dn->loaded = 0; + dn->color = 0; + } + } + + return 0; +} + + +int arm32_overflow_reg(scf_register_t* r, scf_3ac_code_t* c, scf_function_t* f) +{ + int i; + + for (i = 0; i < sizeof(arm32_registers) / sizeof(arm32_registers[0]); i++) { + + scf_register_t* r2 = &(arm32_registers[i]); + + if (SCF_RISC_REG_SP == r2->id + || SCF_RISC_REG_FP == r2->id + || SCF_RISC_REG_LR == r2->id + || SCF_RISC_REG_X12 == r2->id) + continue; + + if (!RISC_COLOR_CONFLICT(r->color, r2->color)) + continue; + + int ret = risc_save_reg(r2, c, f); + if (ret < 0) { + scf_loge("\n"); + return ret; + } + } + + r->used = 1; + return 0; +} + +int arm32_overflow_reg2(scf_register_t* r, scf_dag_node_t* dn, scf_3ac_code_t* c, scf_function_t* f) +{ + scf_register_t* r2; + scf_dag_node_t* dn2; + + int i; + int j; + + for (i = 0; i < sizeof(arm32_registers) / sizeof(arm32_registers[0]); i++) { + + r2 = &(arm32_registers[i]); + + if (SCF_RISC_REG_SP == r2->id + || SCF_RISC_REG_FP == r2->id + || SCF_RISC_REG_LR == r2->id + || SCF_RISC_REG_X12 == r2->id) + continue; + + if (!RISC_COLOR_CONFLICT(r->color, r2->color)) + continue; + + for (j = 0; j < r2->dag_nodes->size; ) { + dn2 = r2->dag_nodes->data[j]; + + if (dn2 == dn) { + j++; + continue; + } + + int ret = risc_save_var(dn2, c, f); + if (ret < 0) + return ret; + } + } + + r->used = 1; + return 0; +} + +int arm32_overflow_reg3(scf_register_t* r, scf_dag_node_t* dn, scf_3ac_code_t* c, scf_function_t* f) +{ + scf_register_t* r2; + scf_dn_status_t* ds2; + scf_dag_node_t* dn2; + + int i; + int j; + int ret; + + for (i = 0; i < sizeof(arm32_registers) / sizeof(arm32_registers[0]); i++) { + + r2 = &(arm32_registers[i]); + + if (SCF_RISC_REG_SP == r2->id + || SCF_RISC_REG_FP == r2->id + || SCF_RISC_REG_LR == r2->id + || SCF_RISC_REG_X12 == r2->id) + continue; + + if (!RISC_COLOR_CONFLICT(r->color, r2->color)) + continue; + + for (j = 0; j < r2->dag_nodes->size; ) { + dn2 = r2->dag_nodes->data[j]; + + if (dn2 == dn) { + j++; + continue; + } + + ds2 = scf_vector_find_cmp(c->active_vars, dn2, scf_dn_status_cmp); + if (!ds2) { + j++; + continue; + } + + if (!ds2->active) { + j++; + continue; + } +#if 1 + scf_variable_t* v = dn->var; + scf_variable_t* v2 = dn2->var; + if (v->w) + scf_loge("v_%d_%d/%s, bp_offset: %d\n", v->w->line, v->w->pos, v->w->text->data, v->bp_offset); + else + scf_loge("v_%#lx, bp_offset: %d\n", 0xffff & (uintptr_t)v, v->bp_offset); + + if (v2->w) + scf_loge("v2_%d_%d/%s, bp_offset: %d\n", v2->w->line, v2->w->pos, v2->w->text->data, v2->bp_offset); + else + scf_loge("v2_%#lx, bp_offset: %d\n", 0xffff & (uintptr_t)v2, v2->bp_offset); +#endif + int ret = risc_save_var(dn2, c, f); + if (ret < 0) + return ret; + } + } + + r->used = 1; + return 0; +} + +int arm32_reg_used(scf_register_t* r, scf_dag_node_t* dn) +{ + scf_register_t* r2; + scf_dag_node_t* dn2; + + int i; + int j; + + for (i = 0; i < sizeof(arm32_registers) / sizeof(arm32_registers[0]); i++) { + + r2 = &(arm32_registers[i]); + + if (SCF_RISC_REG_SP == r2->id + || SCF_RISC_REG_FP == r2->id + || SCF_RISC_REG_LR == r2->id + || SCF_RISC_REG_X12 == r2->id) + continue; + + if (!RISC_COLOR_CONFLICT(r->color, r2->color)) + continue; + + for (j = 0; j < r2->dag_nodes->size; j++) { + dn2 = r2->dag_nodes->data[j]; + + if (dn2 != dn) + return 1; + } + } + return 0; +} + +scf_register_t* arm32_select_overflowed_reg(scf_dag_node_t* dn, scf_3ac_code_t* c, int is_float) +{ + scf_vector_t* neighbors = NULL; + scf_graph_node_t* gn = NULL; + scf_register_t* free_regs[sizeof(arm32_registers) / sizeof(arm32_registers[0])]; + + int nb_free_regs = 0; + int bytes = 4; + int ret; + int i; + int j; + + assert(c->rcg); + + if (dn) { + is_float = scf_variable_float(dn->var); + bytes = arm32_variable_size (dn->var); + } + + ret = risc_rcg_find_node(&gn, c->rcg, dn, NULL); + if (ret < 0) + neighbors = c->rcg->nodes; + else + neighbors = gn->neighbors; + + for (i = 0; i < sizeof(arm32_registers) / sizeof(arm32_registers[0]); i++) { + + scf_register_t* r = &(arm32_registers[i]); + + if (SCF_RISC_REG_SP == r->id + || SCF_RISC_REG_FP == r->id + || SCF_RISC_REG_LR == r->id + || SCF_RISC_REG_X12 == r->id) + continue; + + if (r->bytes < bytes || RISC_COLOR_TYPE(r->color) != is_float) + continue; + + for (j = 0; j < neighbors->size; j++) { + + scf_graph_node_t* neighbor = neighbors->data[j]; + risc_rcg_node_t* rn = neighbor->data; + + if (rn->dag_node) { + if (rn->dag_node->color <= 0) + continue; + + if (RISC_COLOR_CONFLICT(r->color, rn->dag_node->color)) + break; + } else { + assert(rn->reg); + + if (RISC_COLOR_CONFLICT(r->color, rn->reg->color)) + break; + } + } + + if (j == neighbors->size) + free_regs[nb_free_regs++] = r; + } + + if (nb_free_regs > 0) + return risc_reg_cached_min_vars(free_regs, nb_free_regs); + + for (i = 0; i < sizeof(arm32_registers) / sizeof(arm32_registers[0]); i++) { + + scf_register_t* r = &(arm32_registers[i]); + + if (SCF_RISC_REG_SP == r->id + || SCF_RISC_REG_FP == r->id + || SCF_RISC_REG_LR == r->id + || SCF_RISC_REG_X12 == r->id) + continue; + + if (r->bytes < bytes || RISC_COLOR_TYPE(r->color) != is_float) + continue; + + if (c->dsts) { + scf_3ac_operand_t* dst; + + for (j = 0; j < c->dsts->size; j++) { + dst = c->dsts->data[j]; + + if (dst->dag_node && dst->dag_node->color > 0 + && RISC_COLOR_CONFLICT(r->color, dst->dag_node->color)) + break; + } + + if (j < c->dsts->size) + continue; + } + + if (c->srcs) { + scf_3ac_operand_t* src; + + for (j = 0; j < c->srcs->size; j++) { + src = c->srcs->data[j]; + + if (src->dag_node && src->dag_node->color > 0 + && RISC_COLOR_CONFLICT(r->color, src->dag_node->color)) + break; + } + + if (j < c->srcs->size) + continue; + } + + return r; + } + + return NULL; +} + +scf_regs_ops_t regs_ops_arm32 = +{ + .name = "arm32", + + .abi_regs = arm32_abi_regs, + .abi_float_regs = arm32_abi_float_regs, + .abi_ret_regs = arm32_abi_ret_regs, + .abi_caller_saves = arm32_abi_caller_saves, + .abi_callee_saves = arm32_abi_callee_saves, + + .ABI_NB = sizeof(arm32_abi_regs) / sizeof(uint32_t), + .ABI_RET_NB = sizeof(arm32_abi_ret_regs) / sizeof(uint32_t), + .ABI_CALLER_SAVES_NB = sizeof(arm32_abi_caller_saves) / sizeof(uint32_t), + .ABI_CALLEE_SAVES_NB = sizeof(arm32_abi_callee_saves) / sizeof(uint32_t), + + .MAX_BYTES = 4, + + .registers_init = arm32_registers_init, + .registers_reset = arm32_registers_reset, + .registers_clear = arm32_registers_clear, + .register_colors = arm32_register_colors, + + .reg_used = arm32_reg_used, + .reg_cached_vars = arm32_reg_cached_vars, + + .variable_size = arm32_variable_size, + + .caller_save_regs = arm32_caller_save_regs, + .pop_regs = arm32_pop_regs, + + .find_register = arm32_find_register, + .find_register_color = arm32_find_register_color, + .find_register_color_bytes = arm32_find_register_color_bytes, + .find_register_type_id_bytes = arm32_find_register_type_id_bytes, + + .select_overflowed_reg = arm32_select_overflowed_reg, + .overflow_reg = arm32_overflow_reg, + .overflow_reg2 = arm32_overflow_reg2, + .overflow_reg3 = arm32_overflow_reg3, +}; + diff --git a/native/risc/scf_risc_reg_arm64.c b/native/risc/scf_risc_reg_arm64.c index 4560f4b..8a7b321 100644 --- a/native/risc/scf_risc_reg_arm64.c +++ b/native/risc/scf_risc_reg_arm64.c @@ -1,5 +1,9 @@ #include"scf_risc.h" +#define SCF_RISC_REG_FP 29 +#define SCF_RISC_REG_LR 30 +#define SCF_RISC_REG_SP 31 + scf_register_t arm64_registers[] = { {0, 4, "w0", RISC_COLOR(0, 0, 0xf), NULL, 0, 0}, @@ -231,6 +235,85 @@ scf_register_t arm64_registers[] = { {31, 8, "d31", RISC_COLOR(1, 31, 0xff), NULL, 0, 0}, }; +static uint32_t arm64_abi_regs[] = +{ + SCF_RISC_REG_X0, + SCF_RISC_REG_X1, + SCF_RISC_REG_X2, + SCF_RISC_REG_X3, + SCF_RISC_REG_X4, + SCF_RISC_REG_X5, + SCF_RISC_REG_X6, + SCF_RISC_REG_X7, +}; + +static uint32_t arm64_abi_float_regs[] = +{ + SCF_RISC_REG_D0, + SCF_RISC_REG_D1, + SCF_RISC_REG_D2, + SCF_RISC_REG_D3, + SCF_RISC_REG_D4, + SCF_RISC_REG_D5, + SCF_RISC_REG_D6, + SCF_RISC_REG_D7, +}; + +static uint32_t arm64_abi_ret_regs[] = +{ + SCF_RISC_REG_X0, + SCF_RISC_REG_X1, + SCF_RISC_REG_X2, + SCF_RISC_REG_X3, +}; + +static uint32_t arm64_abi_caller_saves[] = +{ + SCF_RISC_REG_X0, + SCF_RISC_REG_X1, + SCF_RISC_REG_X2, + SCF_RISC_REG_X3, + SCF_RISC_REG_X4, + SCF_RISC_REG_X5, + SCF_RISC_REG_X6, + SCF_RISC_REG_X7, + + SCF_RISC_REG_X9, + SCF_RISC_REG_X10, + SCF_RISC_REG_X11, + SCF_RISC_REG_X12, + SCF_RISC_REG_X13, + SCF_RISC_REG_X14, + SCF_RISC_REG_X15, +}; + +static uint32_t arm64_abi_callee_saves[] = +{ + SCF_RISC_REG_X19, + SCF_RISC_REG_X20, + SCF_RISC_REG_X21, + SCF_RISC_REG_X22, + SCF_RISC_REG_X23, + SCF_RISC_REG_X24, + SCF_RISC_REG_X25, + SCF_RISC_REG_X26, + SCF_RISC_REG_X27, + SCF_RISC_REG_X28, + SCF_RISC_REG_X29, + SCF_RISC_REG_X30, +}; + +static int arm64_variable_size(scf_variable_t* v) +{ + if (v->nb_dimentions > 0) + return 8; + + if (v->type >= SCF_STRUCT && 0 == v->nb_pointers) + return 8; + + return v->size < 4 ? 4 : v->size; +} + scf_register_t* arm64_find_register(const char* name) { int i; @@ -394,7 +477,7 @@ void arm64_registers_clear() } } -scf_register_t* risc_reg_cached_min_vars(scf_register_t** regs, int nb_regs) +static scf_register_t* risc_reg_cached_min_vars(scf_register_t** regs, int nb_regs) { scf_register_t* r_min = NULL; @@ -775,7 +858,7 @@ scf_register_t* arm64_select_overflowed_reg(scf_dag_node_t* dn, scf_3ac_code_t* if (dn) { is_float = scf_variable_float(dn->var); - bytes = risc_variable_size (dn->var); + bytes = arm64_variable_size (dn->var); } ret = risc_rcg_find_node(&gn, c->rcg, dn, NULL); @@ -874,10 +957,28 @@ scf_register_t* arm64_select_overflowed_reg(scf_dag_node_t* dn, scf_3ac_code_t* return NULL; } +#define RISC_ABI_NB (sizeof(arm64_abi_regs) / sizeof(arm64_abi_regs[0])) +#define RISC_ABI_RET_NB (sizeof(risc_abi_ret_regs) / sizeof(risc_abi_ret_regs[0])) +#define RISC_ABI_CALLER_SAVES_NB (sizeof(risc_abi_caller_saves) / sizeof(risc_abi_caller_saves[0])) +#define RISC_ABI_CALLEE_SAVES_NB (sizeof(risc_abi_callee_saves) / sizeof(risc_abi_callee_saves[0])) + scf_regs_ops_t regs_ops_arm64 = { .name = "arm64", + .abi_regs = arm64_abi_regs, + .abi_float_regs = arm64_abi_float_regs, + .abi_ret_regs = arm64_abi_ret_regs, + .abi_caller_saves = arm64_abi_caller_saves, + .abi_callee_saves = arm64_abi_callee_saves, + + .ABI_NB = sizeof(arm64_abi_regs) / sizeof(uint32_t), + .ABI_RET_NB = sizeof(arm64_abi_ret_regs) / sizeof(uint32_t), + .ABI_CALLER_SAVES_NB = sizeof(arm64_abi_caller_saves) / sizeof(uint32_t), + .ABI_CALLEE_SAVES_NB = sizeof(arm64_abi_callee_saves) / sizeof(uint32_t), + + .MAX_BYTES = 8, + .registers_init = arm64_registers_init, .registers_reset = arm64_registers_reset, .registers_clear = arm64_registers_clear, @@ -886,6 +987,8 @@ scf_regs_ops_t regs_ops_arm64 = .reg_used = arm64_reg_used, .reg_cached_vars = arm64_reg_cached_vars, + .variable_size = arm64_variable_size, + .caller_save_regs = arm64_caller_save_regs, .pop_regs = arm64_pop_regs, @@ -904,6 +1007,19 @@ scf_regs_ops_t regs_ops_naja = { .name = "naja", + .abi_regs = arm64_abi_regs, + .abi_float_regs = arm64_abi_float_regs, + .abi_ret_regs = arm64_abi_ret_regs, + .abi_caller_saves = arm64_abi_caller_saves, + .abi_callee_saves = arm64_abi_callee_saves, + + .ABI_NB = sizeof(arm64_abi_regs) / sizeof(uint32_t), + .ABI_RET_NB = sizeof(arm64_abi_ret_regs) / sizeof(uint32_t), + .ABI_CALLER_SAVES_NB = sizeof(arm64_abi_caller_saves) / sizeof(uint32_t), + .ABI_CALLEE_SAVES_NB = sizeof(arm64_abi_callee_saves) / sizeof(uint32_t), + + .MAX_BYTES = 8, + .registers_init = arm64_registers_init, .registers_reset = arm64_registers_reset, .registers_clear = arm64_registers_clear, @@ -912,6 +1028,8 @@ scf_regs_ops_t regs_ops_naja = .reg_used = arm64_reg_used, .reg_cached_vars = arm64_reg_cached_vars, + .variable_size = arm64_variable_size, + .caller_save_regs = arm64_caller_save_regs, .pop_regs = arm64_pop_regs, diff --git a/native/risc/scf_risc_util.h b/native/risc/scf_risc_util.h index bed67ce..5e943f2 100644 --- a/native/risc/scf_risc_util.h +++ b/native/risc/scf_risc_util.h @@ -222,12 +222,10 @@ enum scf_risc_REGs { SCF_RISC_REG_X28 = 28, SCF_RISC_REG_X29 = 29, - SCF_RISC_REG_FP = 29, SCF_RISC_REG_X30 = 30, - SCF_RISC_REG_LR = 30, - SCF_RISC_REG_SP = 31, + SCF_RISC_REG_X31 = 31, }; enum scf_risc_EG_types { diff --git a/native/scf_native.h b/native/scf_native.h index e5b0b66..e3cf74f 100644 --- a/native/scf_native.h +++ b/native/scf_native.h @@ -99,6 +99,19 @@ struct scf_regs_ops_s { const char* name; + uint32_t* abi_regs; + uint32_t* abi_float_regs; + uint32_t* abi_ret_regs; + uint32_t* abi_caller_saves; + uint32_t* abi_callee_saves; + + const int ABI_NB; + const int ABI_RET_NB; + const int ABI_CALLER_SAVES_NB; + const int ABI_CALLEE_SAVES_NB; + + const int MAX_BYTES; + int (*registers_init )(); int (*registers_reset )(); void (*registers_clear )(); @@ -107,6 +120,8 @@ struct scf_regs_ops_s int (*reg_used )(scf_register_t* r, scf_dag_node_t* dn); int (*reg_cached_vars )(scf_register_t* r); + int (*variable_size )(scf_variable_t* v); + int (*caller_save_regs)(scf_3ac_code_t* c, scf_function_t* f, uint32_t* regs, int nb_regs, int stack_size, scf_register_t** saved_regs); int (*pop_regs )(scf_3ac_code_t* c, scf_function_t* f, scf_register_t** regs, int nb_regs, scf_register_t** updated_regs, int nb_updated); @@ -126,7 +141,7 @@ struct scf_inst_ops_s { const char* name; - scf_instruction_t* (*BL )(scf_3ac_code_t* c); + int (*BL )(scf_3ac_code_t* c, scf_function_t* f, scf_function_t* pf); scf_instruction_t* (*BLR )(scf_3ac_code_t* c, scf_register_t* r); scf_instruction_t* (*PUSH )(scf_3ac_code_t* c, scf_register_t* r); scf_instruction_t* (*POP )(scf_3ac_code_t* c, scf_register_t* r); @@ -143,68 +158,69 @@ struct scf_inst_ops_s scf_instruction_t* (*ADD_IMM )(scf_3ac_code_t* c, scf_register_t* rd, scf_register_t* rs, uint64_t imm); scf_instruction_t* (*SUB_G )(scf_3ac_code_t* c, scf_register_t* rd, scf_register_t* rs0, scf_register_t* rs1); scf_instruction_t* (*SUB_IMM )(scf_3ac_code_t* c, scf_register_t* rd, scf_register_t* rs, uint64_t imm); - scf_instruction_t* (*CMP_G)(scf_3ac_code_t* c, scf_register_t* rs0, scf_register_t* rs1); - scf_instruction_t* (*CMP_IMM)(scf_3ac_code_t* c, scf_register_t* rs, uint64_t imm); - scf_instruction_t* (*AND_G)(scf_3ac_code_t* c, scf_register_t* rd, scf_register_t* rs0, scf_register_t* rs1); - scf_instruction_t* (*OR_G)(scf_3ac_code_t* c, scf_register_t* rd, scf_register_t* rs0, scf_register_t* rs1); + scf_instruction_t* (*CMP_G )(scf_3ac_code_t* c, scf_register_t* rs0, scf_register_t* rs1); + scf_instruction_t* (*CMP_IMM )(scf_3ac_code_t* c, scf_register_t* rs, uint64_t imm); + scf_instruction_t* (*AND_G )(scf_3ac_code_t* c, scf_register_t* rd, scf_register_t* rs0, scf_register_t* rs1); + scf_instruction_t* (*OR_G )(scf_3ac_code_t* c, scf_register_t* rd, scf_register_t* rs0, scf_register_t* rs1); scf_instruction_t* (*MUL )(scf_3ac_code_t* c, scf_register_t* rd, scf_register_t* rs0, scf_register_t* rs1); scf_instruction_t* (*DIV )(scf_3ac_code_t* c, scf_register_t* rd, scf_register_t* rs0, scf_register_t* rs1); scf_instruction_t* (*SDIV )(scf_3ac_code_t* c, scf_register_t* rd, scf_register_t* rs0, scf_register_t* rs1); scf_instruction_t* (*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* (*SHL)(scf_3ac_code_t* c, scf_register_t* rd, scf_register_t* rs0, scf_register_t* rs1); - scf_instruction_t* (*SHR)(scf_3ac_code_t* c, scf_register_t* rd, scf_register_t* rs0, scf_register_t* rs1); - scf_instruction_t* (*ASR)(scf_3ac_code_t* c, scf_register_t* rd, scf_register_t* rs0, scf_register_t* rs1); + scf_instruction_t* (*SHL )(scf_3ac_code_t* c, scf_register_t* rd, scf_register_t* rs0, scf_register_t* rs1); + scf_instruction_t* (*SHR )(scf_3ac_code_t* c, scf_register_t* rd, scf_register_t* rs0, scf_register_t* rs1); + scf_instruction_t* (*ASR )(scf_3ac_code_t* c, scf_register_t* rd, scf_register_t* rs0, scf_register_t* rs1); scf_instruction_t* (*CVTSS2SD)(scf_3ac_code_t* c, scf_register_t* rd, scf_register_t* rs); scf_instruction_t* (*CVTSD2SS)(scf_3ac_code_t* c, scf_register_t* rd, scf_register_t* rs); - scf_instruction_t* (*CVTF2SI)(scf_3ac_code_t* c, scf_register_t* rd, scf_register_t* rs); - scf_instruction_t* (*CVTF2UI)(scf_3ac_code_t* c, scf_register_t* rd, scf_register_t* rs); - scf_instruction_t* (*CVTSI2F)(scf_3ac_code_t* c, scf_register_t* rd, scf_register_t* rs); - scf_instruction_t* (*CVTUI2F)(scf_3ac_code_t* c, scf_register_t* rd, scf_register_t* rs); - - scf_instruction_t* (*FCMP)(scf_3ac_code_t* c, scf_register_t* rs0, scf_register_t* rs1); - scf_instruction_t* (*FADD)(scf_3ac_code_t* c, scf_register_t* rd, scf_register_t* rs0, scf_register_t* rs1); - scf_instruction_t* (*FSUB)(scf_3ac_code_t* c, scf_register_t* rd, scf_register_t* rs0, scf_register_t* rs1); - scf_instruction_t* (*FMUL)(scf_3ac_code_t* c, scf_register_t* rd, scf_register_t* rs0, scf_register_t* rs1); - scf_instruction_t* (*FDIV)(scf_3ac_code_t* c, scf_register_t* rd, scf_register_t* rs0, scf_register_t* rs1); - scf_instruction_t* (*FMOV_G)(scf_3ac_code_t* c, scf_register_t* rd, scf_register_t* rs); - - scf_instruction_t* (*JA )(scf_3ac_code_t* c); - scf_instruction_t* (*JB )(scf_3ac_code_t* c); - scf_instruction_t* (*JZ )(scf_3ac_code_t* c); - scf_instruction_t* (*JNZ)(scf_3ac_code_t* c); - scf_instruction_t* (*JGT)(scf_3ac_code_t* c); - scf_instruction_t* (*JGE)(scf_3ac_code_t* c); - scf_instruction_t* (*JLT)(scf_3ac_code_t* c); - scf_instruction_t* (*JLE)(scf_3ac_code_t* c); - scf_instruction_t* (*JMP)(scf_3ac_code_t* c); - scf_instruction_t* (*JAE)(scf_3ac_code_t* c); - scf_instruction_t* (*JBE)(scf_3ac_code_t* c); - scf_instruction_t* (*RET)(scf_3ac_code_t* c); - - scf_instruction_t* (*SETZ )(scf_3ac_code_t* c, scf_register_t* rd); - scf_instruction_t* (*SETNZ)(scf_3ac_code_t* c, scf_register_t* rd); - scf_instruction_t* (*SETGT)(scf_3ac_code_t* c, scf_register_t* rd); - scf_instruction_t* (*SETGE)(scf_3ac_code_t* c, scf_register_t* rd); - scf_instruction_t* (*SETLT)(scf_3ac_code_t* c, scf_register_t* rd); - scf_instruction_t* (*SETLE)(scf_3ac_code_t* c, scf_register_t* rd); - - int (*I2G )(scf_3ac_code_t* c, scf_register_t* rd, uint64_t imm, int bytes); - int (*M2G )(scf_3ac_code_t* c, scf_function_t* f, scf_register_t* rd, scf_register_t* rb, scf_variable_t* vs); - int (*M2GF )(scf_3ac_code_t* c, scf_function_t* f, scf_register_t* rd, scf_register_t* rb, scf_variable_t* vs); - int (*G2M )(scf_3ac_code_t* c, scf_function_t* f, scf_register_t* rs, scf_register_t* rb, scf_variable_t* vs); - int (*G2P )(scf_3ac_code_t* c, scf_function_t* f, scf_register_t* rs, scf_register_t* rb, int32_t offset, int size); - int (*P2G )(scf_3ac_code_t* c, scf_function_t* f, scf_register_t* rd, scf_register_t* rb, int32_t offset, int size); - int (*ISTR2G)(scf_3ac_code_t* c, scf_function_t* f, scf_register_t* rd, scf_variable_t* vs); - int (*SIB2G )(scf_3ac_code_t* c, scf_function_t* f, scf_register_t* rd, scf_sib_t* sib); - int (*G2SIB )(scf_3ac_code_t* c, scf_function_t* f, scf_register_t* rd, scf_sib_t* sib); - int (*ADR2G )(scf_3ac_code_t* c, scf_function_t* f, scf_register_t* rd, scf_variable_t* vs); - int (*ADRP2G)(scf_3ac_code_t* c, scf_function_t* f, scf_register_t* rd, scf_register_t* rb, int32_t offset); - - int (*ADRSIB2G )(scf_3ac_code_t* c, scf_function_t* f, scf_register_t* rd, scf_sib_t* sib); - int (*cmp_update)(scf_3ac_code_t* c, scf_function_t* f, scf_instruction_t* inst); + scf_instruction_t* (*CVTF2SI )(scf_3ac_code_t* c, scf_register_t* rd, scf_register_t* rs); + scf_instruction_t* (*CVTF2UI )(scf_3ac_code_t* c, scf_register_t* rd, scf_register_t* rs); + scf_instruction_t* (*CVTSI2F )(scf_3ac_code_t* c, scf_register_t* rd, scf_register_t* rs); + scf_instruction_t* (*CVTUI2F )(scf_3ac_code_t* c, scf_register_t* rd, scf_register_t* rs); + + scf_instruction_t* (*FCMP )(scf_3ac_code_t* c, scf_register_t* rs0, scf_register_t* rs1); + scf_instruction_t* (*FADD )(scf_3ac_code_t* c, scf_register_t* rd, scf_register_t* rs0, scf_register_t* rs1); + scf_instruction_t* (*FSUB )(scf_3ac_code_t* c, scf_register_t* rd, scf_register_t* rs0, scf_register_t* rs1); + scf_instruction_t* (*FMUL )(scf_3ac_code_t* c, scf_register_t* rd, scf_register_t* rs0, scf_register_t* rs1); + scf_instruction_t* (*FDIV )(scf_3ac_code_t* c, scf_register_t* rd, scf_register_t* rs0, scf_register_t* rs1); + scf_instruction_t* (*FMOV_G )(scf_3ac_code_t* c, scf_register_t* rd, scf_register_t* rs); + + scf_instruction_t* (*JA )(scf_3ac_code_t* c); + scf_instruction_t* (*JB )(scf_3ac_code_t* c); + scf_instruction_t* (*JZ )(scf_3ac_code_t* c); + scf_instruction_t* (*JNZ )(scf_3ac_code_t* c); + scf_instruction_t* (*JGT )(scf_3ac_code_t* c); + scf_instruction_t* (*JGE )(scf_3ac_code_t* c); + scf_instruction_t* (*JLT )(scf_3ac_code_t* c); + scf_instruction_t* (*JLE )(scf_3ac_code_t* c); + scf_instruction_t* (*JMP )(scf_3ac_code_t* c); + scf_instruction_t* (*JAE )(scf_3ac_code_t* c); + scf_instruction_t* (*JBE )(scf_3ac_code_t* c); + scf_instruction_t* (*RET )(scf_3ac_code_t* c); + + scf_instruction_t* (*SETZ )(scf_3ac_code_t* c, scf_register_t* rd); + scf_instruction_t* (*SETNZ )(scf_3ac_code_t* c, scf_register_t* rd); + scf_instruction_t* (*SETGT )(scf_3ac_code_t* c, scf_register_t* rd); + scf_instruction_t* (*SETGE )(scf_3ac_code_t* c, scf_register_t* rd); + scf_instruction_t* (*SETLT )(scf_3ac_code_t* c, scf_register_t* rd); + scf_instruction_t* (*SETLE )(scf_3ac_code_t* c, scf_register_t* rd); + + int (*I2G )(scf_3ac_code_t* c, scf_register_t* rd, uint64_t imm, int bytes); + int (*M2G )(scf_3ac_code_t* c, scf_function_t* f, scf_register_t* rd, scf_register_t* rb, scf_variable_t* vs); + int (*M2GF )(scf_3ac_code_t* c, scf_function_t* f, scf_register_t* rd, scf_register_t* rb, scf_variable_t* vs); + int (*G2M )(scf_3ac_code_t* c, scf_function_t* f, scf_register_t* rs, scf_register_t* rb, scf_variable_t* vs); + int (*G2P )(scf_3ac_code_t* c, scf_function_t* f, scf_register_t* rs, scf_register_t* rb, int32_t offset, int size); + int (*P2G )(scf_3ac_code_t* c, scf_function_t* f, scf_register_t* rd, scf_register_t* rb, int32_t offset, int size); + int (*ISTR2G )(scf_3ac_code_t* c, scf_function_t* f, scf_register_t* rd, scf_variable_t* vs); + int (*SIB2G )(scf_3ac_code_t* c, scf_function_t* f, scf_register_t* rd, scf_sib_t* sib); + int (*G2SIB )(scf_3ac_code_t* c, scf_function_t* f, scf_register_t* rd, scf_sib_t* sib); + int (*ADR2G )(scf_3ac_code_t* c, scf_function_t* f, scf_register_t* rd, scf_variable_t* vs); + int (*ADRP2G )(scf_3ac_code_t* c, scf_function_t* f, scf_register_t* rd, scf_register_t* rb, int32_t offset); + int (*ADRSIB2G )(scf_3ac_code_t* c, scf_function_t* f, scf_register_t* rd, scf_sib_t* sib); + + int (*cmp_update )(scf_3ac_code_t* c, scf_function_t* f, scf_instruction_t* inst); + int (*set_rel_veneer)(scf_function_t* f); void (*set_jmp_offset)(scf_instruction_t* inst, int32_t bytes); }; diff --git a/parse/Makefile b/parse/Makefile index f6faa4c..1795ff2 100644 --- a/parse/Makefile +++ b/parse/Makefile @@ -37,16 +37,21 @@ CFILES += ../native/risc/scf_risc_opcode.c CFILES += ../native/risc/scf_risc_rcg.c CFILES += ../native/risc/scf_risc_reg.c CFILES += ../native/risc/scf_risc_reg_arm64.c +CFILES += ../native/risc/scf_risc_reg_arm32.c CFILES += ../native/risc/scf_arm64.c +CFILES += ../native/risc/scf_arm32.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_native32.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_arm32.c +CFILES += ../elf/scf_elf_arm32_so.c CFILES += ../elf/scf_elf_naja.c CFILES += ../elf/scf_elf_naja_so.c CFILES += ../elf/scf_dwarf.c diff --git a/parse/main.c b/parse/main.c index b4aedef..0eae6c3 100644 --- a/parse/main.c +++ b/parse/main.c @@ -27,6 +27,17 @@ static char* __arm64_sofiles[] = "../lib/arm64/libc.so.6", }; +static char* __arm32_objs[] = +{ + "../lib/arm32/_start.o", +}; + +static char* __arm32_sofiles[] = +{ + "../lib/arm32//lib/ld-linux-armhf.so.3", + "../lib/arm32/libc.so.6", +}; + void usage(char* path) { fprintf(stderr, "Usage: %s [-c] [-a arch] [-o out] src0 [src1]\n\n", path); @@ -177,6 +188,9 @@ int main(int argc, char* argv[]) if (!strcmp(arch, "arm64") || !strcmp(arch, "naja")) MAIN_ADD_FILES(__arm64_objs, __arm64_sofiles); + + else if (!strcmp(arch, "arm32")) + MAIN_ADD_FILES(__arm32_objs, __arm32_sofiles); else MAIN_ADD_FILES(__objs, __sofiles); diff --git a/parse/scf_parse2.c b/parse/scf_parse2.c index b1db283..98b9d9b 100644 --- a/parse/scf_parse2.c +++ b/parse/scf_parse2.c @@ -1845,6 +1845,15 @@ static int _scf_parse_add_data_relas(scf_parse_t* parse, scf_elf_context_t* elf) s.sh_link = 0; s.sh_info = SCF_SHNDX_DATA; + if (!strcmp(elf->ops->machine, "arm32")) { + + for (i = 0; i < relas->size; i++) { + rela = relas->data[i]; + + rela->r_info = ELF32_R_INFO(ELF64_R_SYM(rela->r_info), ELF64_R_TYPE(rela->r_info)); + } + } + ret = scf_elf_add_rela_section(elf, &s, relas); } error: @@ -1925,9 +1934,10 @@ static int _add_debug_section(scf_elf_context_t* elf, const char* name, const sc static int _add_debug_relas(scf_vector_t* debug_relas, scf_parse_t* parse, scf_elf_context_t* elf, int sh_index, const char* sh_name) { - scf_elf_sym_t* sym; - scf_vector_t* relas; - scf_rela_t* r; + scf_elf_rela_t* rela; + scf_elf_sym_t* sym; + scf_vector_t* relas; + scf_rela_t* r; int ret; int i; @@ -1955,7 +1965,7 @@ static int _add_debug_relas(scf_vector_t* debug_relas, scf_parse_t* parse, scf_e return -EINVAL; } - scf_elf_rela_t* rela = calloc(1, sizeof(scf_elf_rela_t)); + rela = calloc(1, sizeof(scf_elf_rela_t)); if (!rela) return -ENOMEM; @@ -1985,6 +1995,15 @@ static int _add_debug_relas(scf_vector_t* debug_relas, scf_parse_t* parse, scf_e s.sh_link = 0; s.sh_info = sh_index; + if (!strcmp(elf->ops->machine, "arm32")) { + + for (i = 0; i < relas->size; i++) { + rela = relas->data[i]; + + rela->r_info = ELF32_R_INFO(ELF64_R_SYM(rela->r_info), ELF64_R_TYPE(rela->r_info)); + } + } + ret = scf_elf_add_rela_section(elf, &s, relas); #endif @@ -2151,6 +2170,7 @@ static int _scf_parse_add_text_relas(scf_parse_t* parse, scf_elf_context_t* elf, if (relas->size > 0) { scf_elf_section_t s = {0}; + scf_elf_rela_t* r; s.name = ".rela.text"; s.sh_type = SHT_RELA; @@ -2161,6 +2181,15 @@ static int _scf_parse_add_text_relas(scf_parse_t* parse, scf_elf_context_t* elf, s.sh_link = 0; s.sh_info = SCF_SHNDX_TEXT; + if (!strcmp(elf->ops->machine, "arm32")) { + + for (i = 0; i < relas->size; i++) { + r = relas->data[i]; + + r->r_info = ELF32_R_INFO(ELF64_R_SYM(r->r_info), ELF64_R_TYPE(r->r_info)); + } + } + ret = scf_elf_add_rela_section(elf, &s, relas); } error: diff --git a/vm/Makefile b/vm/Makefile index 9d1be3e..cbc0a74 100644 --- a/vm/Makefile +++ b/vm/Makefile @@ -3,10 +3,13 @@ CFILES += ../util/scf_string.c CFILES += ../elf/scf_elf.c CFILES += ../elf/scf_elf_link.c CFILES += ../elf/scf_elf_native.c +CFILES += ../elf/scf_elf_native32.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_arm32.c +CFILES += ../elf/scf_elf_arm32_so.c CFILES += ../elf/scf_elf_naja.c CFILES += ../elf/scf_elf_naja_so.c CFILES += ../elf/scf_dwarf.c