From ef49295e308b58ac946476901d3678f537dd63b6 Mon Sep 17 00:00:00 2001 From: "yu.dongliang" <18588496441@163.com> Date: Mon, 10 Aug 2026 00:50:01 +0800 Subject: [PATCH] 1, support -fpic to make PIC .o, 2, support .rela.dyn & .got to use global vars of .so, 3, use _start.s of libc instead of ../sysroot/lib/x64/_start.s to init global vars of .so 4, delete VLA from SCF. --- core/scf_3ac.c | 49 +--- core/scf_basic_block.h | 3 - core/scf_core_types.h | 5 +- core/scf_function.h | 2 +- core/scf_lex_word.h | 1 + core/scf_operator.c | 3 - core/scf_operator_dag.c | 7 - core/scf_operator_handler_3ac.c | 68 ------ core/scf_optimizer.c | 2 - core/scf_variable.c | 6 +- core/scf_variable.h | 16 +- elf/scf_elf.c | 65 +++--- elf/scf_elf.h | 8 +- elf/scf_elf_arm32.c | 3 +- elf/scf_elf_arm32_so.c | 4 +- elf/scf_elf_arm64.c | 3 +- elf/scf_elf_arm64_so.c | 4 +- elf/scf_elf_link.c | 150 ++++++++----- elf/scf_elf_link.h | 1 + elf/scf_elf_naja.c | 3 +- elf/scf_elf_naja_so.c | 4 +- elf/scf_elf_native.c | 50 +++-- elf/scf_elf_native.h | 15 +- elf/scf_elf_native32.c | 48 ++-- elf/scf_elf_native32.h | 37 +-- elf/scf_elf_x64.c | 79 +++++-- elf/scf_elf_x64_so.c | 312 +++++++++++++++++++++----- examples/hello.c | 2 +- examples/libmy1.c | 6 + examples/scf_printf.c | 11 +- examples/test_libmy1.c | 9 + lex/scf_lex.c | 1 + native/risc/scf_risc_reg.c | 2 +- native/x64/scf_x64.c | 10 +- native/x64/scf_x64.h | 13 +- native/x64/scf_x64_inst.c | 190 +--------------- native/x64/scf_x64_inst_binary.c | 2 +- native/x64/scf_x64_inst_cmp.c | 2 +- native/x64/scf_x64_inst_common.c | 10 +- native/x64/scf_x64_inst_div.c | 7 +- native/x64/scf_x64_inst_mul.c | 11 +- native/x64/scf_x64_inst_shift.c | 6 +- native/x64/scf_x64_inst_util.c | 88 +++++++- native/x64/scf_x64_peephole.c | 3 +- native/x64/scf_x64_rcg.c | 289 +++++++++++------------- native/x64/scf_x64_reg.c | 61 ++++- native/x64/scf_x64_reg.h | 5 +- parse/Makefile | 1 - parse/main.c | 56 +++-- parse/scf_dfa_container.c | 2 +- parse/scf_dfa_expr.c | 8 +- parse/scf_dfa_identity.c | 7 +- parse/scf_dfa_sizeof.c | 2 +- parse/scf_dfa_util.h | 7 + parse/scf_dfa_va_arg.c | 25 ++- parse/scf_dfa_var.c | 274 +--------------------- parse/scf_operator_handler_const.c | 9 - parse/scf_operator_handler_semantic.c | 41 +--- parse/scf_parse.c | 25 ++- parse/scf_parse.h | 3 +- sysroot/include/stdarg.h | 21 ++ sysroot/lib/x64/_start.s | 32 ++- 62 files changed, 1040 insertions(+), 1149 deletions(-) create mode 100644 examples/libmy1.c create mode 100644 examples/test_libmy1.c create mode 100644 sysroot/include/stdarg.h diff --git a/core/scf_3ac.c b/core/scf_3ac.c index 1331e92..5560a19 100644 --- a/core/scf_3ac.c +++ b/core/scf_3ac.c @@ -60,9 +60,6 @@ static scf_3ac_operator_t _3ac_operators[] = { {SCF_OP_VA_ARG, "va_arg"}, {SCF_OP_VA_END, "va_end"}, - {SCF_OP_VLA_ALLOC, "vla_alloc"}, - {SCF_OP_VLA_FREE, "vla_free"}, - {SCF_OP_RETURN, "return"}, {SCF_OP_GOTO, "jmp"}, @@ -95,7 +92,6 @@ static scf_3ac_operator_t _3ac_operators[] = { {SCF_OP_3AC_JB, "jb"}, {SCF_OP_3AC_JBE, "jbe"}, - {SCF_OP_3AC_DUMP, "core_dump"}, {SCF_OP_3AC_NOP, "nop"}, {SCF_OP_3AC_END, "end"}, @@ -683,36 +679,8 @@ int scf_3ac_code_to_dag(scf_3ac_code_t* c, scf_list_t* dag) return ret; } - } else if (SCF_OP_VLA_ALLOC == c->op->type) { - - dst = c->dsts->data[0]; - ret = scf_dag_get_node(dag, dst->node, &dst->dag_node); - if (ret < 0) - return ret; - - scf_dag_node_t* alloc = scf_dag_node_alloc(c->op->type, NULL, NULL); - if (!alloc) - return -ENOMEM; - scf_list_add_tail(dag, &alloc->list); - - ret = scf_dag_node_add_child(alloc, dst->dag_node); - if (ret < 0) - return ret; - - for (i = 0; i < c->srcs->size; i++) { - src = c->srcs->data[i]; - - ret = scf_dag_get_node(dag, src->node, &src->dag_node); - if (ret < 0) - return ret; - - ret = scf_dag_node_add_child(alloc, src->dag_node); - if (ret < 0) - return ret; - } } else if (SCF_OP_3AC_CMP == c->op->type - || SCF_OP_3AC_TEQ == c->op->type - || SCF_OP_3AC_DUMP == c->op->type) { + || SCF_OP_3AC_TEQ == c->op->type) { scf_dag_node_t* dn_cmp = scf_dag_node_alloc(c->op->type, NULL, NULL); @@ -1338,10 +1306,6 @@ static int _3ac_find_basic_block_start(scf_list_t* h) continue; } #endif - if (SCF_OP_3AC_DUMP == c->op->type) { - c->basic_block_start = 1; - continue; - } if (SCF_OP_3AC_END == c->op->type) { c->basic_block_start = 1; @@ -1526,11 +1490,6 @@ static int _3ac_split_basic_blocks(scf_list_t* h, scf_function_t* f) continue; } - if (SCF_OP_3AC_DUMP == c->op->type) { - bb->dump_flag = 1; - continue; - } - if (SCF_OP_3AC_END == c->op->type) { bb->end_flag = 1; continue; @@ -1580,11 +1539,7 @@ static int _3ac_split_basic_blocks(scf_list_t* h, scf_function_t* f) else if (SCF_OP_RETURN == c->op->type) bb->ret_flag = 1; - else if (SCF_OP_VLA_ALLOC == c->op->type) { - bb->vla_flag = 1; - f ->vla_flag = 1; - - } else if (SCF_OP_VA_START == c->op->type + else if (SCF_OP_VA_START == c->op->type || SCF_OP_VA_ARG == c->op->type || SCF_OP_VA_END == c->op->type) bb->varg_flag = 1; diff --git a/core/scf_basic_block.h b/core/scf_basic_block.h index 218a03c..d6f91e6 100644 --- a/core/scf_basic_block.h +++ b/core/scf_basic_block.h @@ -91,7 +91,6 @@ struct scf_basic_block_s uint32_t jmp_flag :1; uint32_t jcc_flag :1; uint32_t ret_flag :1; - uint32_t vla_flag :1; uint32_t end_flag :1; uint32_t varg_flag :1; uint32_t dump_flag :1; @@ -109,8 +108,6 @@ struct scf_basic_block_s uint32_t visit_flag :1; uint32_t block_flag :1; uint32_t native_flag :1; - - scf_basic_block_t* vla_free; }; typedef int (*scf_basic_block_bfs_pt)(scf_basic_block_t* bb, void* data, scf_vector_t* queue); diff --git a/core/scf_core_types.h b/core/scf_core_types.h index a7e225e..988d8b0 100644 --- a/core/scf_core_types.h +++ b/core/scf_core_types.h @@ -102,13 +102,11 @@ enum scf_core_types SCF_OP_POINTER, // -> struct member SCF_OP_DOT, // . dot - SCF_OP_VLA_ALLOC, // variable length array, VLA - SCF_OP_VLA_FREE, - SCF_OP_VAR_ARGS, // ... variable args SCF_OP_VA_START, SCF_OP_VA_ARG, + SCF_OP_VA_COPY, SCF_OP_VA_END, // 49 @@ -190,7 +188,6 @@ enum scf_core_types SCF_OP_3AC_RELOAD, // reload a var from memory, only for 3ac & native SCF_OP_3AC_RESAVE, // resave a var to memory, only for 3ac & native - SCF_OP_3AC_DUMP, SCF_OP_3AC_NOP, SCF_OP_3AC_END, diff --git a/core/scf_function.h b/core/scf_function.h index a655887..d0596a7 100644 --- a/core/scf_function.h +++ b/core/scf_function.h @@ -64,7 +64,7 @@ struct scf_function_s { uint32_t vargs_flag:1; uint32_t void_flag :1; uint32_t call_flag :1; - uint32_t vla_flag :1; + uint32_t pic_flag :1; uint32_t compile_flag:1; uint32_t native_flag :1; diff --git a/core/scf_lex_word.h b/core/scf_lex_word.h index 92a2b5d..54eeaea 100644 --- a/core/scf_lex_word.h +++ b/core/scf_lex_word.h @@ -64,6 +64,7 @@ enum scf_lex_words SCF_LEX_WORD_KEY_NEW, // create class object SCF_LEX_WORD_KEY_CONTAINER, // container_of SCF_LEX_WORD_KEY_VA_ARG, // va_arg + SCF_LEX_WORD_KEY_VA_COPY, // va_copy SCF_LEX_WORD_KEY_DEFINED, // #defined SCF_LEX_WORD_Q_MASK, // ? diff --git a/core/scf_operator.c b/core/scf_operator.c index 4219d0c..7b9160f 100644 --- a/core/scf_operator.c +++ b/core/scf_operator.c @@ -84,9 +84,6 @@ static scf_operator_t base_operators[] = {"switch", NULL, SCF_OP_SWITCH, 15, -1, SCF_OP_ASSOCIATIVITY_LEFT}, {"case", NULL, SCF_OP_CASE, 15, -1, SCF_OP_ASSOCIATIVITY_LEFT}, {"default", NULL, SCF_OP_DEFAULT, 15, -1, SCF_OP_ASSOCIATIVITY_LEFT}, - - {"vla_alloc", NULL, SCF_OP_VLA_ALLOC, 15, -1, SCF_OP_ASSOCIATIVITY_LEFT}, - {"vla_free", NULL, SCF_OP_VLA_FREE, 15, -1, SCF_OP_ASSOCIATIVITY_LEFT}, }; scf_operator_t* scf_find_base_operator(const char* name, const int nb_operands) diff --git a/core/scf_operator_dag.c b/core/scf_operator_dag.c index 0e5f0c8..62ebd0e 100644 --- a/core/scf_operator_dag.c +++ b/core/scf_operator_dag.c @@ -390,12 +390,6 @@ static int _scf_dag_op_return(scf_list_t* h, scf_dag_node_t* parent, scf_dag_nod return _scf_3ac_code_N(h, SCF_OP_RETURN, NULL, nodes, nb_nodes); } -static int _scf_dag_op_vla_alloc(scf_list_t* h, scf_dag_node_t* parent, scf_dag_node_t** nodes, int nb_nodes) -{ - assert(4 == nb_nodes); - return _scf_3ac_code_N(h, SCF_OP_VLA_ALLOC, nodes[0], nodes + 1, 3); -} - static int _scf_dag_op_cmp(scf_list_t* h, scf_dag_node_t* parent, scf_dag_node_t** nodes, int nb_nodes) { assert(2 == nb_nodes); @@ -472,7 +466,6 @@ scf_dag_operator_t dag_operators[] = {SCF_OP_LT, SCF_OP_ASSOCIATIVITY_LEFT, _scf_dag_op_lt}, {SCF_OP_LE, SCF_OP_ASSOCIATIVITY_LEFT, _scf_dag_op_le}, - {SCF_OP_VLA_ALLOC, SCF_OP_ASSOCIATIVITY_LEFT, _scf_dag_op_vla_alloc}, {SCF_OP_RETURN, SCF_OP_ASSOCIATIVITY_LEFT, _scf_dag_op_return}, {SCF_OP_3AC_CMP, SCF_OP_ASSOCIATIVITY_LEFT, _scf_dag_op_cmp}, {SCF_OP_3AC_TEQ, SCF_OP_ASSOCIATIVITY_LEFT, _scf_dag_op_teq}, diff --git a/core/scf_operator_handler_3ac.c b/core/scf_operator_handler_3ac.c index b93a3a1..7290950 100644 --- a/core/scf_operator_handler_3ac.c +++ b/core/scf_operator_handler_3ac.c @@ -1178,72 +1178,6 @@ static int _scf_op_while(scf_ast_t* ast, scf_node_t** nodes, int nb_nodes, void* return 0; } -static int _scf_op_vla_alloc(scf_ast_t* ast, scf_node_t** nodes, int nb_nodes, void* data) -{ - assert(4 == nb_nodes); - - scf_handler_data_t* d = data; - scf_variable_t* v; - scf_type_t* t; - scf_node_t* parent = nodes[0]->parent; - scf_node_t* zero; - - t = scf_block_find_type_type(ast->current_block, SCF_VAR_INT); - v = SCF_VAR_ALLOC_BY_TYPE(NULL, t, 1, 0, NULL); - if (!v) - return -ENOMEM; - v->data.u64 = 0; - v->const_literal_flag = 1; - - zero = scf_node_alloc(NULL, v->type, v); - scf_variable_free(v); - v = NULL; - if (!zero) - return -ENOMEM; - - int ret = scf_node_add_child(parent, zero); - if (ret < 0) { - scf_node_free(zero); - return ret; - } - - scf_3ac_operand_t* dst; - scf_3ac_code_t* cmp; - scf_3ac_code_t* jgt; - scf_3ac_code_t* core; - scf_node_t* srcs[] = {nodes[1], zero}; - - cmp = scf_3ac_code_NN(SCF_OP_3AC_CMP, NULL, 0, srcs, 2); - if (!cmp) - return -ENOMEM; - - jgt = scf_3ac_jmp_code(SCF_OP_3AC_JGT, NULL); - if (!jgt) { - scf_3ac_code_free(cmp); - return -ENOMEM; - } - - core = scf_3ac_code_NN(SCF_OP_3AC_DUMP, NULL, 0, nodes + 1, 3); - if (!core) { - scf_3ac_code_free(jgt); - scf_3ac_code_free(cmp); - return -ENOMEM; - } - - scf_list_add_tail(d->_3ac_list_head, &cmp->list); - scf_list_add_tail(d->_3ac_list_head, &jgt->list); - scf_list_add_tail(d->_3ac_list_head, &core->list); - - dst = jgt->dsts->data[0]; - dst->code = core; - - ret = scf_vector_add(d->branch_ops->_breaks, jgt); - if (ret < 0) - return ret; - - return _scf_3ac_code_N(d->_3ac_list_head, SCF_OP_VLA_ALLOC, nodes[0], nodes + 1, 3); -} - static int _scf_op_default(scf_ast_t* ast, scf_node_t** nodes, int nb_nodes, void* data) { return 0; @@ -2568,8 +2502,6 @@ scf_operator_handler_pt __operator_handlers[SCF_N_3AC_OPS] = [SCF_OP_SWITCH ] = _scf_op_switch, [SCF_OP_CASE ] = _scf_op_case, [SCF_OP_DEFAULT] = _scf_op_default, - - [SCF_OP_VLA_ALLOC] = _scf_op_vla_alloc, }; scf_operator_handler_pt scf_find_3ac_operator_handler(const int type) diff --git a/core/scf_optimizer.c b/core/scf_optimizer.c index 1b84c12..133a513 100644 --- a/core/scf_optimizer.c +++ b/core/scf_optimizer.c @@ -25,7 +25,6 @@ extern scf_optimizer_t scf_optimizer_basic_block; extern scf_optimizer_t scf_optimizer_const_teq; extern scf_optimizer_t scf_optimizer_loop; -extern scf_optimizer_t scf_optimizer_vla; extern scf_optimizer_t scf_optimizer_group; extern scf_optimizer_t scf_optimizer_generate_loads_saves; @@ -57,7 +56,6 @@ static scf_optimizer_t* scf_optimizers[] = &scf_optimizer_dominators, &scf_optimizer_loop, - &scf_optimizer_vla, &scf_optimizer_group, &scf_optimizer_generate_loads_saves, diff --git a/core/scf_variable.c b/core/scf_variable.c index bcd9cdb..7a1a9e2 100644 --- a/core/scf_variable.c +++ b/core/scf_variable.c @@ -298,7 +298,7 @@ void scf_variable_free(scf_variable_t* v) } } -void scf_variable_add_array_dimention(scf_variable_t* array, int num, scf_expr_t* vla) +void scf_variable_add_array_dimention(scf_variable_t* array, int num) { assert(array); @@ -307,7 +307,6 @@ void scf_variable_add_array_dimention(scf_variable_t* array, int num, scf_expr_t array->dimentions = p; array->dimentions[array->nb_dimentions].num = num; - array->dimentions[array->nb_dimentions].vla = vla; array->nb_dimentions++; } @@ -466,9 +465,6 @@ int scf_variable_size(scf_variable_t* v) assert(v->nb_dimentions > 0); - if (v->vla_flag) - return sizeof(void*); - int capacity = 1; int j; diff --git a/core/scf_variable.h b/core/scf_variable.h index aa501f5..077b7b5 100644 --- a/core/scf_variable.h +++ b/core/scf_variable.h @@ -5,8 +5,7 @@ #include"scf_lex_word.h" typedef struct { - scf_expr_t* vla; // variable length array - int num; // const length array + int num; // const length array } scf_dimention_t; struct scf_variable_s { @@ -67,7 +66,6 @@ struct scf_variable_s { uint32_t global_flag :1; uint32_t member_flag :1; - uint32_t vla_flag :1; uint32_t arg_flag :1; uint32_t auto_gc_flag:1; uint32_t anon_flag :1; @@ -92,13 +90,13 @@ int scf_member_offset(scf_member_t* m); int scf_member_add_index(scf_member_t* m, scf_variable_t* member, int index); scf_variable_t* scf_variable_alloc(scf_lex_word_t* w, scf_type_t* t); -scf_variable_t* scf_variable_clone(scf_variable_t* var); -scf_variable_t* scf_variable_ref(scf_variable_t* var); -void scf_variable_free(scf_variable_t* var); +scf_variable_t* scf_variable_clone(scf_variable_t* v); +scf_variable_t* scf_variable_ref (scf_variable_t* v); +void scf_variable_free (scf_variable_t* v); -void scf_variable_print(scf_variable_t* var); +void scf_variable_print(scf_variable_t* v); -void scf_variable_add_array_dimention(scf_variable_t* array, int num, scf_expr_t* vla); +void scf_variable_add_array_dimention(scf_variable_t* array, int num); void scf_variable_set_array_member(scf_variable_t* array, int index, scf_variable_t* member); void scf_variable_get_array_member(scf_variable_t* array, int index, scf_variable_t* member); @@ -121,7 +119,7 @@ static inline int scf_variable_const(scf_variable_t* v) return v->const_literal_flag; if (v->nb_pointers + v->nb_dimentions > 0) - return v->const_literal_flag && !v->vla_flag; + return v->const_literal_flag; return v->const_flag && 0 == v->nb_pointers && 0 == v->nb_dimentions; } diff --git a/elf/scf_elf.c b/elf/scf_elf.c index 1d5c020..e41a82e 100644 --- a/elf/scf_elf.c +++ b/elf/scf_elf.c @@ -114,11 +114,8 @@ int scf_elf_close(scf_elf_context_t* elf) int scf_elf_add_sym(scf_elf_context_t* elf, const scf_elf_sym_t* sym, const char* sh_name) { - if (elf && sym && sh_name) { - - if (elf->ops && elf->ops->add_sym) - return elf->ops->add_sym(elf, sym, sh_name); - } + if (elf && elf->ops && elf->ops->add_sym && sym && sh_name) + return elf->ops->add_sym(elf, sym, sh_name); scf_loge("\n"); return -1; @@ -142,11 +139,8 @@ int scf_elf_add_syms(scf_elf_context_t* elf, const scf_vector_t* syms, const cha int scf_elf_add_section(scf_elf_context_t* elf, const scf_elf_section_t* section) { - if (elf && section) { - - if (elf->ops && elf->ops->add_section) - return elf->ops->add_section(elf, section); - } + if (elf && elf->ops && elf->ops->add_section && section) + return elf->ops->add_section(elf, section); scf_loge("\n"); return -1; @@ -154,23 +148,26 @@ int scf_elf_add_section(scf_elf_context_t* elf, const scf_elf_section_t* section int scf_elf_add_rela_section(scf_elf_context_t* elf, const scf_elf_section_t* section, scf_vector_t* relas) { - if (elf && section && relas) { - - if (elf->ops && elf->ops->add_rela_section) - return elf->ops->add_rela_section(elf, section, relas); - } + if (elf && elf->ops && elf->ops->add_rela_section && section && relas) + return elf->ops->add_rela_section(elf, section, relas); scf_loge("\n"); return -1; } -int scf_elf_add_dyn_rela(scf_elf_context_t* elf, const scf_elf_rela_t* rela) +int scf_elf_add_plt_rela(scf_elf_context_t* elf, const scf_elf_rela_t* rela) { - if (elf && rela) { + if (elf && elf->ops && elf->ops->add_plt_rela && rela) + return elf->ops->add_plt_rela(elf, rela); - if (elf->ops && elf->ops->add_dyn_rela) - return elf->ops->add_dyn_rela(elf, rela); - } + scf_loge("\n"); + return -1; +} + +int scf_elf_add_got_rela(scf_elf_context_t* elf, const scf_elf_rela_t* rela) +{ + if (elf && elf->ops && elf->ops->add_got_rela && rela) + return elf->ops->add_got_rela(elf, rela); scf_loge("\n"); return -1; @@ -178,11 +175,8 @@ int scf_elf_add_dyn_rela(scf_elf_context_t* elf, const scf_elf_rela_t* rela) int scf_elf_add_dyn_need(scf_elf_context_t* elf, const char* soname) { - if (elf && soname) { - - if (elf->ops && elf->ops->add_dyn_need) - return elf->ops->add_dyn_need(elf, soname); - } + if (elf && elf->ops && elf->ops->add_dyn_need && soname) + return elf->ops->add_dyn_need(elf, soname); scf_loge("\n"); return -1; @@ -190,11 +184,8 @@ int scf_elf_add_dyn_need(scf_elf_context_t* elf, const char* soname) int scf_elf_read_section(scf_elf_context_t* elf, scf_elf_section_t** psection, const char* name) { - if (elf && psection && name) { - - if (elf->ops && elf->ops->read_section) - return elf->ops->read_section(elf, psection, name); - } + if (elf && elf->ops && elf->ops->read_section && psection && name) + return elf->ops->read_section(elf, psection, name); scf_loge("\n"); return -1; @@ -202,11 +193,8 @@ int scf_elf_read_section(scf_elf_context_t* elf, scf_elf_section_t** psection, c int scf_elf_read_syms(scf_elf_context_t* elf, scf_vector_t* syms, const char* sh_name) { - if (elf && syms && sh_name) { - - if (elf->ops && elf->ops->read_syms) - return elf->ops->read_syms(elf, syms, sh_name); - } + if (elf && elf->ops && elf->ops->read_syms && syms && sh_name) + return elf->ops->read_syms(elf, syms, sh_name); scf_loge("\n"); return -1; @@ -214,11 +202,8 @@ int scf_elf_read_syms(scf_elf_context_t* elf, scf_vector_t* syms, const char* sh int scf_elf_read_relas(scf_elf_context_t* elf, scf_vector_t* relas, const char* sh_name) { - if (elf && relas && sh_name) { - - if (elf->ops && elf->ops->read_relas) - return elf->ops->read_relas(elf, relas, sh_name); - } + if (elf && elf->ops && elf->ops->read_relas && relas && sh_name) + return elf->ops->read_relas(elf, relas, sh_name); scf_loge("\n"); return -1; diff --git a/elf/scf_elf.h b/elf/scf_elf.h index 0a40786..0c290c9 100644 --- a/elf/scf_elf.h +++ b/elf/scf_elf.h @@ -27,6 +27,7 @@ typedef struct { uint8_t st_info; uint8_t dyn_flag:1; + uint8_t got_flag:1; } scf_elf_sym_t; typedef struct { @@ -79,7 +80,8 @@ struct scf_elf_ops_s int (*add_rela_section)(scf_elf_context_t* elf, const scf_elf_section_t* section, scf_vector_t* relas); int (*add_dyn_need)(scf_elf_context_t* elf, const char* soname); - int (*add_dyn_rela)(scf_elf_context_t* elf, const scf_elf_rela_t* rela); + int (*add_plt_rela)(scf_elf_context_t* elf, const scf_elf_rela_t* rela); + int (*add_got_rela)(scf_elf_context_t* elf, const scf_elf_rela_t* rela); int (*write_rel )(scf_elf_context_t* elf); int (*write_dyn )(scf_elf_context_t* elf, const char* sysroot); @@ -108,8 +110,10 @@ int scf_elf_add_syms(scf_elf_context_t* elf, const scf_vector_t* syms, const ch int scf_elf_add_section (scf_elf_context_t* elf, const scf_elf_section_t* section); int scf_elf_add_rela_section(scf_elf_context_t* elf, const scf_elf_section_t* section, scf_vector_t* relas); + int scf_elf_add_dyn_need(scf_elf_context_t* elf, const char* soname); -int scf_elf_add_dyn_rela(scf_elf_context_t* elf, const scf_elf_rela_t* rela); +int scf_elf_add_plt_rela(scf_elf_context_t* elf, const scf_elf_rela_t* rela); +int scf_elf_add_got_rela(scf_elf_context_t* elf, const scf_elf_rela_t* rela); int scf_elf_read_section(scf_elf_context_t* elf, scf_elf_section_t** psection, const char* name); diff --git a/elf/scf_elf_arm32.c b/elf/scf_elf_arm32.c index 6e66b0f..f4223ed 100644 --- a/elf/scf_elf_arm32.c +++ b/elf/scf_elf_arm32.c @@ -452,7 +452,8 @@ scf_elf_ops_t elf_ops_arm32 = .add_rela_section = elf32_add_rela_section, .add_dyn_need = elf32_add_dyn_need, - .add_dyn_rela = elf32_add_dyn_rela, + .add_plt_rela = elf32_add_plt_rela, + .add_got_rela = elf32_add_got_rela, .read_syms = elf32_read_syms, .read_relas = elf32_read_relas, diff --git a/elf/scf_elf_arm32_so.c b/elf/scf_elf_arm32_so.c index fc1dee0..7c323ec 100644 --- a/elf/scf_elf_arm32_so.c +++ b/elf/scf_elf_arm32_so.c @@ -737,8 +737,8 @@ int __arm32_elf_post_dyn(elf_native_t* arm32, uint64_t rx_base, uint64_t rw_base got_plt++; } - for (i = 0; i < arm32->dyn_relas->size; i++) { - r = arm32->dyn_relas->data[i]; + for (i = 0; i < arm32->plt_relas->size; i++) { + r = arm32->plt_relas->data[i]; int sym_idx = ELF32_R_SYM(r->r_info); assert(sym_idx > 0); diff --git a/elf/scf_elf_arm64.c b/elf/scf_elf_arm64.c index 3cfe50e..647b8b6 100644 --- a/elf/scf_elf_arm64.c +++ b/elf/scf_elf_arm64.c @@ -464,7 +464,8 @@ scf_elf_ops_t elf_ops_arm64 = .add_rela_section = elf_add_rela_section, .add_dyn_need = elf_add_dyn_need, - .add_dyn_rela = elf_add_dyn_rela, + .add_plt_rela = elf_add_plt_rela, + .add_got_rela = elf_add_got_rela, .read_syms = elf_read_syms, .read_relas = elf_read_relas, diff --git a/elf/scf_elf_arm64_so.c b/elf/scf_elf_arm64_so.c index 783c4e9..54287f0 100644 --- a/elf/scf_elf_arm64_so.c +++ b/elf/scf_elf_arm64_so.c @@ -722,8 +722,8 @@ int __arm64_elf_post_dyn(elf_native_t* arm64, uint64_t rx_base, uint64_t rw_base got_plt++; } - for (i = 0; i < arm64->dyn_relas->size; i++) { - Elf64_Rela* r = arm64->dyn_relas->data[i]; + for (i = 0; i < arm64->plt_relas->size; i++) { + Elf64_Rela* r = arm64->plt_relas->data[i]; int sym_idx = ELF64_R_SYM(r->r_info); assert(sym_idx > 0); diff --git a/elf/scf_elf_link.c b/elf/scf_elf_link.c index ba62981..d60d32e 100644 --- a/elf/scf_elf_link.c +++ b/elf/scf_elf_link.c @@ -27,85 +27,79 @@ int __scf_elf_file_open(scf_elf_file_t** pfile) int ret; ef->text = scf_string_alloc(); - if (!ef->text) { - ret = -ENOMEM; + if (!ef->text) goto text_error; - } ef->rodata = scf_string_alloc(); - if (!ef->rodata) { - ret = -ENOMEM; + if (!ef->rodata) goto rodata_error; - } ef->data = scf_string_alloc(); - if (!ef->data) { - ret = -ENOMEM; + if (!ef->data) goto data_error; - } ef->debug_abbrev = scf_string_alloc(); - if (!ef->debug_abbrev) { - ret = -ENOMEM; + if (!ef->debug_abbrev) goto debug_abbrev_error; - } ef->debug_info = scf_string_alloc(); - if (!ef->debug_info) { - ret = -ENOMEM; + if (!ef->debug_info) goto debug_info_error; - } ef->debug_line = scf_string_alloc(); - if (!ef->debug_line) { - ret = -ENOMEM; + if (!ef->debug_line) goto debug_line_error; - } ef->debug_str = scf_string_alloc(); - if (!ef->debug_str) { - ret = -ENOMEM; + if (!ef->debug_str) goto debug_str_error; - } ef->syms = scf_vector_alloc(); - if (!ef->syms) { - ret = -ENOMEM; + if (!ef->syms) goto syms_error; - } ef->text_relas = scf_vector_alloc(); - if (!ef->text_relas) { - ret = -ENOMEM; + if (!ef->text_relas) goto text_relas_error; - } ef->data_relas = scf_vector_alloc(); - if (!ef->data_relas) { - ret = -ENOMEM; + if (!ef->data_relas) goto data_relas_error; - } ef->debug_line_relas = scf_vector_alloc(); - if (!ef->debug_line_relas) { - ret = -ENOMEM; + if (!ef->debug_line_relas) goto debug_line_relas_error; - } ef->debug_info_relas = scf_vector_alloc(); - if (!ef->debug_info_relas) { - ret = -ENOMEM; + if (!ef->debug_info_relas) goto debug_info_relas_error; - } - ef->dyn_syms = scf_vector_alloc(); + ef->dyn_syms = scf_vector_alloc(); + if (!ef->dyn_syms) + goto dyn_syms_error; + ef->dyn_needs = scf_vector_alloc(); - ef->rela_plt = scf_vector_alloc(); + if (!ef->dyn_needs) + goto dyn_needs_error; + + ef->rela_plt = scf_vector_alloc(); + if (!ef->rela_plt) + goto rela_plt_error; + + ef->rela_dyn = scf_vector_alloc(); + if (!ef->rela_dyn) + goto rela_dyn_error; *pfile = ef; return 0; -elf_open_error: +rela_dyn_error: + scf_vector_free(ef->rela_plt); +rela_plt_error: + scf_vector_free(ef->dyn_needs); +dyn_needs_error: + scf_vector_free(ef->dyn_syms); +dyn_syms_error: scf_vector_free(ef->debug_info_relas); debug_info_relas_error: scf_vector_free(ef->debug_line_relas); @@ -132,8 +126,9 @@ rodata_error: text_error: if (ef->name) scf_string_free(ef->name); + free(ef); - return ret; + return -ENOMEM; } int scf_elf_file_open(scf_elf_file_t** pfile, const char* path, const char* mode, const char* arch) @@ -172,14 +167,6 @@ int scf_so_file_open(scf_elf_file_t** pso, const char* path, const char* mode, c so->name = scf_string_cstr(path); - so->dyn_syms = scf_vector_alloc(); - if (!so->dyn_syms) - return -ENOMEM; - - so->rela_plt = scf_vector_alloc(); - if (!so->rela_plt) - return -ENOMEM; - ret = scf_elf_read_syms(so->elf, so->dyn_syms, ".dynsym"); if (ret < 0) { scf_loge("\n"); @@ -235,6 +222,11 @@ int scf_elf_file_close(scf_elf_file_t* ef, void (*rela_free)(void*), void (*sym_ scf_vector_clear(ef->syms, sym_free); scf_vector_free (ef->syms); + scf_vector_free (ef->dyn_syms); + scf_vector_free (ef->dyn_needs); + scf_vector_free (ef->rela_plt); + scf_vector_free (ef->rela_dyn); + free(ef); return 0; } @@ -834,17 +826,15 @@ static int _find_so_sym(scf_elf_file_t** pso, scf_vector_t* dlls, scf_elf_sym_t* break; } - if (j == dlls->size) { - scf_loge("linker don't find symbel '%s'\n", sym->name); + if (j >= dlls->size) return -1; - } if (pso) *pso = so; return 0; } -static int link_relas(scf_elf_file_t* exec, char* afiles[], int nb_afiles, char* sofiles[], int nb_sofiles, const char* arch) +static int link_relas(scf_elf_file_t* exec, char* afiles[], int nb_afiles, char* sofiles[], int nb_sofiles, const char* arch, int dyn_flag) { scf_elf_rela_t* rela = NULL; scf_elf_sym_t* sym = NULL; @@ -906,6 +896,8 @@ static int link_relas(scf_elf_file_t* exec, char* afiles[], int nb_afiles, char* sym = exec->syms->data[sym_idx - 1]; + scf_logd("sym: %s, ELF64_R_TYPE: %ld\n", sym->name, ELF64_R_TYPE(rela->r_info)); + uint32_t offset = 0; uint32_t size = 0; @@ -923,11 +915,31 @@ static int link_relas(scf_elf_file_t* exec, char* afiles[], int nb_afiles, char* continue; } + int got_flag = 0; + ret = _find_so_sym(&so, dlls, sym); - if (ret < 0) { - scf_loge("\n"); + + if (!strcmp(arch, "x64")) { + + switch (ELF64_R_TYPE(rela->r_info)) + { + case R_X86_64_GOTPCREL: + got_flag = 1; + break; + + default: + if (ret < 0 && !dyn_flag) { + scf_loge("linker don't find symbol '%s'\n", sym->name); + return -1; + } + break; + }; + + } else if (ret < 0) { + scf_loge("linker don't find symbol '%s'\n", sym->name); return -1; } + sym->dyn_flag = 1; int j; @@ -948,8 +960,9 @@ static int link_relas(scf_elf_file_t* exec, char* afiles[], int nb_afiles, char* free(sym2); return -ENOMEM; } - sym2->st_info = ELF64_ST_INFO(STB_GLOBAL, STT_FUNC); + sym2->st_info = ELF64_ST_INFO(STB_GLOBAL, STT_NOTYPE); sym2->dyn_flag = 1; + sym2->got_flag = got_flag; if (scf_vector_add(exec->dyn_syms, sym2) < 0) { scf_loge("\n"); @@ -957,17 +970,23 @@ static int link_relas(scf_elf_file_t* exec, char* afiles[], int nb_afiles, char* } } - scf_vector_add_unique(exec->dyn_needs, so); + if (so) + scf_vector_add_unique(exec->dyn_needs, so); + scf_vector_del(exec->text_relas, rela); - scf_vector_add(exec->rela_plt, rela); + + if (got_flag) + scf_vector_add(exec->rela_dyn, rela); + else + scf_vector_add(exec->rela_plt, rela); 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_logd("j: %d, sym: %s, r_offset: %#lx, r_addend: %ld\n", j, - sym->name, rela->r_offset, rela->r_addend); + scf_logi("j: %d, sym: %s, r_offset: %#lx, r_addend: %ld, got_flag: %d\n", j, + sym->name, rela->r_offset, rela->r_addend, got_flag); } for (i = 0; i < exec->data_relas->size; i++) { @@ -1059,7 +1078,7 @@ int scf_elf_link(scf_vector_t* objs, scf_vector_t* afiles, scf_vector_t* sofiles return ret; } - ret = link_relas(exec, (char**)afiles->data, afiles->size, (char**)sofiles->data, sofiles->size, arch); + ret = link_relas(exec, (char**)afiles->data, afiles->size, (char**)sofiles->data, sofiles->size, arch, dyn_flag); if (ret < 0) { scf_loge("\n"); return ret; @@ -1083,10 +1102,19 @@ int scf_elf_link(scf_vector_t* objs, scf_vector_t* afiles, scf_vector_t* sofiles } } + for (i = 0; i < exec->rela_dyn->size; i++) { + rela = exec->rela_dyn->data[i]; + + if (scf_elf_add_got_rela(exec->elf, rela) < 0) { + scf_loge("\n"); + return -1; + } + } + for (i = 0; i < exec->rela_plt->size; i++) { rela = exec->rela_plt->data[i]; - if (scf_elf_add_dyn_rela(exec->elf, rela) < 0) { + if (scf_elf_add_plt_rela(exec->elf, rela) < 0) { scf_loge("\n"); return -1; } diff --git a/elf/scf_elf_link.h b/elf/scf_elf_link.h index acd6fca..b89500c 100644 --- a/elf/scf_elf_link.h +++ b/elf/scf_elf_link.h @@ -38,6 +38,7 @@ typedef struct { scf_vector_t* dyn_syms; scf_vector_t* rela_plt; + scf_vector_t* rela_dyn; scf_vector_t* dyn_needs; } scf_elf_file_t; diff --git a/elf/scf_elf_naja.c b/elf/scf_elf_naja.c index 513910a..ea77acc 100644 --- a/elf/scf_elf_naja.c +++ b/elf/scf_elf_naja.c @@ -464,7 +464,8 @@ scf_elf_ops_t elf_ops_naja = .add_rela_section = elf_add_rela_section, .add_dyn_need = elf_add_dyn_need, - .add_dyn_rela = elf_add_dyn_rela, + .add_plt_rela = elf_add_plt_rela, + .add_got_rela = elf_add_got_rela, .read_syms = elf_read_syms, .read_relas = elf_read_relas, diff --git a/elf/scf_elf_naja_so.c b/elf/scf_elf_naja_so.c index 0193d5e..fd725d7 100644 --- a/elf/scf_elf_naja_so.c +++ b/elf/scf_elf_naja_so.c @@ -722,8 +722,8 @@ int __naja_elf_post_dyn(elf_native_t* naja, uint64_t rx_base, uint64_t rw_base, got_plt++; } - for (i = 0; i < naja->dyn_relas->size; i++) { - Elf64_Rela* r = naja->dyn_relas->data[i]; + for (i = 0; i < naja->plt_relas->size; i++) { + Elf64_Rela* r = naja->plt_relas->data[i]; int sym_idx = ELF64_R_SYM(r->r_info); assert(sym_idx > 0); diff --git a/elf/scf_elf_native.c b/elf/scf_elf_native.c index a4187da..a196ffc 100644 --- a/elf/scf_elf_native.c +++ b/elf/scf_elf_native.c @@ -78,6 +78,7 @@ int elf_add_sym(scf_elf_context_t* elf, const scf_elf_sym_t* sym, const char* sh xsym->sym.st_info = sym->st_info; xsym->dyn_flag = sym->dyn_flag; + xsym->got_flag = sym->got_flag; int ret = scf_vector_add(vec, xsym); if (ret < 0) { @@ -613,24 +614,13 @@ int elf_add_dyn_need(scf_elf_context_t* elf, const char* soname) return 0; } -int elf_add_dyn_rela(scf_elf_context_t* elf, const scf_elf_rela_t* rela) +static int __add_elf_rela(scf_vector_t* vec, const scf_elf_rela_t* rela) { - elf_native_t* e = elf->priv; - - if (!e || !elf->fp) - return -1; - - if (!e->dyn_relas) { - e->dyn_relas = scf_vector_alloc(); - if (!e->dyn_relas) - return -ENOMEM; - } - Elf64_Rela* r = calloc(1, sizeof(Elf64_Rela)); if (!r) return -ENOMEM; - if (scf_vector_add(e->dyn_relas, r) < 0) { + if (scf_vector_add(vec, r) < 0) { free(r); return -ENOMEM; } @@ -638,10 +628,41 @@ int elf_add_dyn_rela(scf_elf_context_t* elf, const scf_elf_rela_t* rela) r->r_offset = rela->r_offset; r->r_addend = rela->r_addend; r->r_info = rela->r_info; - return 0; } +int elf_add_got_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->got_relas) { + e->got_relas = scf_vector_alloc(); + if (!e->got_relas) + return -ENOMEM; + } + + return __add_elf_rela(e->got_relas, rela); +} + +int elf_add_plt_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->plt_relas) { + e->plt_relas = scf_vector_alloc(); + if (!e->plt_relas) + return -ENOMEM; + } + + return __add_elf_rela(e->plt_relas, rela); +} + int elf_read_relas(scf_elf_context_t* elf, scf_vector_t* relas, const char* sh_name) { elf_native_t* e = elf->priv; @@ -1055,4 +1076,3 @@ void elf_process_syms(elf_native_t* e, uint32_t cs_index) } } } - diff --git a/elf/scf_elf_native.h b/elf/scf_elf_native.h index e1273b7..4de226c 100644 --- a/elf/scf_elf_native.h +++ b/elf/scf_elf_native.h @@ -34,8 +34,11 @@ typedef struct { Elf64_Sym sym; int index; - uint8_t dyn_flag:1; + int plt_got_index; + + uint8_t dyn_flag:1; + uint8_t got_flag:1; } elf_sym_t; typedef struct { @@ -56,18 +59,22 @@ typedef struct { scf_vector_t* dynsyms; scf_vector_t* dyn_needs; - scf_vector_t* dyn_relas; + scf_vector_t* plt_relas; + scf_vector_t* got_relas; int n_plts; + int n_gots; elf_section_t* gnu_hash; elf_section_t* interp; elf_section_t* dynsym; elf_section_t* dynstr; + elf_section_t* rela_dyn; elf_section_t* rela_plt; elf_section_t* plt; elf_section_t* dynamic; elf_section_t* got_plt; + elf_section_t* got; } elf_native_t; @@ -85,7 +92,8 @@ int elf_read_shstrtab(scf_elf_context_t* elf); int elf_read_section (scf_elf_context_t* elf, scf_elf_section_t** psection, const char* name); int elf_add_dyn_need(scf_elf_context_t* elf, const char* soname); -int elf_add_dyn_rela(scf_elf_context_t* elf, const scf_elf_rela_t* rela); +int elf_add_plt_rela(scf_elf_context_t* elf, const scf_elf_rela_t* rela); +int elf_add_got_rela(scf_elf_context_t* elf, const scf_elf_rela_t* rela); int elf_read_phdrs (scf_elf_context_t* elf, scf_vector_t* phdrs); int elf_read_relas (scf_elf_context_t* elf, scf_vector_t* relas, const char* sh_name); @@ -158,4 +166,3 @@ static inline void section_header(Elf64_Shdr* sh, } #endif - diff --git a/elf/scf_elf_native32.c b/elf/scf_elf_native32.c index deef2cb..a703c9c 100644 --- a/elf/scf_elf_native32.c +++ b/elf/scf_elf_native32.c @@ -619,24 +619,13 @@ int elf32_add_dyn_need(scf_elf_context_t* elf, const char* soname) return 0; } -int elf32_add_dyn_rela(scf_elf_context_t* elf, const scf_elf_rela_t* rela) +static int __add_elf32_rela(scf_vector_t* vec, 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) { + if (scf_vector_add(vec, r) < 0) { free(r); return -ENOMEM; } @@ -648,6 +637,38 @@ int elf32_add_dyn_rela(scf_elf_context_t* elf, const scf_elf_rela_t* rela) return 0; } +int elf32_add_got_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->got_relas) { + e->got_relas = scf_vector_alloc(); + if (!e->got_relas) + return -ENOMEM; + } + + return __add_elf32_rela(e->got_relas, rela); +} + +int elf32_add_plt_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->plt_relas) { + e->plt_relas = scf_vector_alloc(); + if (!e->plt_relas) + return -ENOMEM; + } + + return __add_elf32_rela(e->plt_relas, rela); +} + int elf32_read_relas(scf_elf_context_t* elf, scf_vector_t* relas, const char* sh_name) { elf_native_t* e = elf->priv; @@ -1095,4 +1116,3 @@ void elf32_process_syms(elf_native_t* e, uint32_t cs_index) } } } - diff --git a/elf/scf_elf_native32.h b/elf/scf_elf_native32.h index ca53874..a3a001c 100644 --- a/elf/scf_elf_native32.h +++ b/elf/scf_elf_native32.h @@ -36,34 +36,39 @@ typedef struct { } elf_sym_t; typedef struct { - Elf32_Ehdr eh; + Elf32_Ehdr eh; - Elf32_Shdr sh_null; + Elf32_Shdr sh_null; - scf_vector_t* sections; - scf_vector_t* phdrs; + scf_vector_t* sections; + scf_vector_t* phdrs; - Elf32_Shdr sh_symtab; - scf_vector_t* symbols; + Elf32_Shdr sh_symtab; + scf_vector_t* symbols; - Elf32_Shdr sh_strtab; + Elf32_Shdr sh_strtab; - Elf32_Shdr sh_shstrtab; - scf_string_t* sh_shstrtab_data; + Elf32_Shdr sh_shstrtab; + scf_string_t* sh_shstrtab_data; - scf_vector_t* dynsyms; - scf_vector_t* dyn_needs; - scf_vector_t* dyn_relas; + scf_vector_t* dynsyms; + scf_vector_t* dyn_needs; + scf_vector_t* plt_relas; + scf_vector_t* got_relas; + int n_plts; + int n_gots; + + elf_section_t* gnu_hash; 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_dyn; elf_section_t* rela_plt; elf_section_t* plt; elf_section_t* dynamic; elf_section_t* got_plt; + elf_section_t* got; } elf_native_t; @@ -79,7 +84,8 @@ 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_add_plt_rela(scf_elf_context_t* elf, const scf_elf_rela_t* rela); +int elf32_add_got_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); @@ -151,4 +157,3 @@ static inline void section_header(Elf32_Shdr* sh, } #endif - diff --git a/elf/scf_elf_x64.c b/elf/scf_elf_x64.c index 147d1e0..132cddf 100644 --- a/elf/scf_elf_x64.c +++ b/elf/scf_elf_x64.c @@ -165,12 +165,12 @@ static int _x64_elf_link_sections(elf_native_t* x64, uint32_t cs_index, uint32_t || ds_index == rs->sh.sh_info) continue; - if (!strcmp(rs->name->data, ".rela.plt")) + if (!strcmp(rs->name->data, ".rela.plt") || !strcmp(rs->name->data, ".rela.dyn")) continue; s = x64->sections->data[rs->sh.sh_info - 1]; - scf_logd("s: %s, rs: %s, rs->sh.sh_info: %u\n", s->name->data, rs->name->data, rs->sh.sh_info); + scf_logi("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)); @@ -228,7 +228,7 @@ static void _x64_elf_process_syms(elf_native_t* x64, uint32_t cs_index) if (SHT_RELA != s->sh.sh_type) continue; - if (!strcmp(s->name->data, ".rela.plt")) + if (!strcmp(s->name->data, ".rela.plt") || !strcmp(s->name->data, ".rela.dyn")) continue; assert(s->data_len % sizeof(Elf64_Rela) == 0); @@ -417,7 +417,22 @@ static int _x64_elf_write_exec(scf_elf_context_t* elf, const char* sysroot) int nb_phdrs = 3; if (x64->dynsyms && x64->dynsyms->size > 0) { - x64->n_plts = x64->dynsyms->size; + x64->n_plts = 0; + x64->n_gots = 0; + + elf_sym_t* sym; + int i; + + for (i = 0; i < x64->dynsyms->size; i++) { + sym = x64->dynsyms->data[i]; + + if (sym->got_flag) + sym->plt_got_index = x64->n_gots++; + else + sym->plt_got_index = x64->n_plts++; + } + + scf_logw("n_plts: %d, n_gots: %d\n", x64->n_plts, x64->n_gots); __x64_elf_add_dyn(x64, sysroot); nb_phdrs = 6; @@ -437,9 +452,7 @@ static int _x64_elf_write_exec(scf_elf_context_t* elf, const char* sysroot) elf_section_t* crela = NULL; elf_section_t* drela = NULL; elf_sym_t* sym; - int ret; - int i; _x64_elf_process_sections(x64, §ion_offset, &cs, &ros, &ds, &crela, &drela); @@ -498,7 +511,7 @@ static int _x64_elf_write_exec(scf_elf_context_t* elf, const char* sysroot) // write null section header fwrite(&x64->sh_null, sizeof(x64->sh_null), 1, elf->fp); - // write user's section header + // write user's section headers section_offset = phdr_offset + sizeof(Elf64_Phdr) * nb_phdrs; _x64_elf_write_section_headers(elf, nb_sections, section_offset, strtab_offset, shstrtab_offset); @@ -514,11 +527,18 @@ static int _x64_elf_write_exec(scf_elf_context_t* elf, const char* sysroot) __x64_elf_write_rodata(elf, r_base, ros->offset, ros->data_len); if (6 == nb_phdrs) { - __x64_elf_write_data (elf, rw_base, x64->dynamic->offset, x64->dynamic->data_len + x64->got_plt->data_len + ds->data_len); + uint64_t ds_len = x64->dynamic->data_len + ds->data_len; + + if (x64->got_plt) + ds_len += x64->got_plt->data_len; + + if (x64->got) + ds_len += x64->got->data_len; + + __x64_elf_write_data (elf, rw_base, x64->dynamic->offset, ds_len); __x64_elf_write_dynamic(elf, rw_base, x64->dynamic->offset, x64->dynamic->data_len); - } else { + } else __x64_elf_write_data(elf, rw_base, ds->offset, ds->data_len); - } #endif elf_write_sections(elf); @@ -543,16 +563,29 @@ static int _x64_elf_write_dyn(scf_elf_context_t* elf, const char* sysroot) return -ENOMEM; } - x64->n_plts = x64->dynsyms->size; + x64->n_plts = 0; + x64->n_gots = 0; + + for (i = 0; i < x64->dynsyms->size; i++) { + sym = x64->dynsyms->data[i]; + + if (sym->got_flag) + sym->plt_got_index = x64->n_gots++; + else + sym->plt_got_index = x64->n_plts++; + } + + scf_logw("n_plts: %d, n_gots: %d\n", x64->n_plts, x64->n_gots); for (i = 0; i < x64->symbols->size; i++) { sym = x64->symbols->data[i]; - if (ELF64_ST_INFO(STB_GLOBAL, STT_FUNC) != sym->sym.st_info) - continue; + if (ELF64_ST_INFO(STB_GLOBAL, STT_FUNC) == sym->sym.st_info) { + if (!entry) + entry = sym; - if (!entry) - entry = sym; + } else if (ELF64_ST_INFO(STB_GLOBAL, STT_OBJECT) != sym->sym.st_info) + continue; ret = scf_vector_add(x64->dynsyms, sym); if (ret < 0) @@ -628,7 +661,7 @@ static int _x64_elf_write_dyn(scf_elf_context_t* elf, const char* sysroot) // write null section header fwrite(&x64->sh_null, sizeof(x64->sh_null), 1, elf->fp); - // write user's section header + // write user's section headers section_offset = phdr_offset + sizeof(Elf64_Phdr) * nb_phdrs; _x64_elf_write_section_headers(elf, nb_sections, section_offset, strtab_offset, shstrtab_offset); @@ -636,10 +669,15 @@ static int _x64_elf_write_dyn(scf_elf_context_t* elf, const char* sysroot) __x64_elf_write_text (elf, rx_base, 0, cs->offset + cs->data_len); __x64_elf_write_rodata(elf, r_base, ros->offset, ros->data_len); + uint64_t ds_len = x64->dynamic->data_len + ds->data_len; + if (x64->got_plt) - __x64_elf_write_data(elf, rw_base, x64->dynamic->offset, x64->dynamic->data_len + x64->got_plt->data_len + ds->data_len); - else - __x64_elf_write_data(elf, rw_base, x64->dynamic->offset, x64->dynamic->data_len + ds->data_len); + ds_len += x64->got_plt->data_len; + + if (x64->got) + ds_len += x64->got->data_len; + + __x64_elf_write_data(elf, rw_base, x64->dynamic->offset, ds_len); __x64_elf_write_dynamic(elf, rw_base, x64->dynamic->offset, x64->dynamic->data_len); @@ -664,7 +702,8 @@ scf_elf_ops_t elf_ops_x64 = .add_rela_section = elf_add_rela_section, .add_dyn_need = elf_add_dyn_need, - .add_dyn_rela = elf_add_dyn_rela, + .add_plt_rela = elf_add_plt_rela, + .add_got_rela = elf_add_got_rela, .read_syms = elf_read_syms, .read_relas = elf_read_relas, diff --git a/elf/scf_elf_x64_so.c b/elf/scf_elf_x64_so.c index 4639d2c..396d379 100644 --- a/elf/scf_elf_x64_so.c +++ b/elf/scf_elf_x64_so.c @@ -170,7 +170,7 @@ static int _x64_elf_add_gnu_hash(elf_native_t* x64, elf_section_t** ps) #define HASH_BUCKETS 3 #define HASH_BLOOMS 1 - int n_syms = x64->dynsyms->size - x64->n_plts; + int n_syms = x64->dynsyms->size - x64->n_plts - x64->n_gots; int len = sizeof(uint32_t) * 4 + sizeof(uint64_t) * HASH_BLOOMS + sizeof(uint32_t) * HASH_BUCKETS @@ -361,6 +361,87 @@ static int _x64_elf_add_got_plt(elf_native_t* x64, elf_section_t** ps) return 0; } +static int _x64_elf_add_got(elf_native_t* x64, 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"); + if (!s->name) { + free(s); + return -ENOMEM; + } + + s->data = calloc(x64->n_gots, sizeof(void*)); + if (!s->data) { + scf_string_free(s->name); + free(s); + return -ENOMEM; + } + s->data_len = x64->n_gots * sizeof(void*); + + s->index = 1; + + s->sh.sh_type = SHT_PROGBITS; + s->sh.sh_flags = SHF_ALLOC | SHF_WRITE; + s->sh.sh_addralign = 8; + + int ret = scf_vector_add(x64->sections, s); + if (ret < 0) { + scf_string_free(s->name); + free(s->data); + free(s); + return -ENOMEM; + } + + *ps = s; + return 0; +} + +static int _x64_elf_add_rela_dyn(elf_native_t* x64, 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.dyn"); + if (!s->name) { + free(s); + return -ENOMEM; + } + + s->data = calloc(x64->n_gots, sizeof(Elf64_Rela)); + if (!s->data) { + scf_string_free(s->name); + free(s); + return -ENOMEM; + } + s->data_len = x64->n_gots * sizeof(Elf64_Rela); + + s->index = 1; + + s->sh.sh_type = SHT_RELA; + s->sh.sh_flags = SHF_ALLOC | SHF_INFO_LINK; + s->sh.sh_addralign = 8; + s->sh.sh_entsize = sizeof(Elf64_Rela); + + int ret = scf_vector_add(x64->sections, s); + if (ret < 0) { + scf_string_free(s->name); + free(s->data); + free(s); + return -ENOMEM; + } + + *ps = s; + return 0; +} + static int _x64_elf_add_rela_plt(elf_native_t* x64, elf_section_t** ps) { elf_section_t* s; @@ -639,6 +720,7 @@ int __x64_elf_add_dyn(elf_native_t* x64, const char* sysroot) ".dynsym", ".dynstr", // ".gnu.version_r", + ".rela.dyn", ".rela.plt", ".plt", @@ -647,6 +729,7 @@ int __x64_elf_add_dyn(elf_native_t* x64, const char* sysroot) ".dynamic", ".got.plt", + ".got", ".data", }; @@ -660,11 +743,13 @@ int __x64_elf_add_dyn(elf_native_t* x64, const char* sysroot) // _x64_elf_add_gnu_version_r(x64, &x64->gnu_version_r); + _x64_elf_add_rela_dyn(x64, &x64->rela_dyn); _x64_elf_add_rela_plt(x64, &x64->rela_plt); _x64_elf_add_plt(x64, &x64->plt); - _x64_elf_add_dynamic(x64, &x64->dynamic, 4); + _x64_elf_add_dynamic(x64, &x64->dynamic, 6); _x64_elf_add_got_plt(x64, &x64->got_plt); + _x64_elf_add_got (x64, &x64->got); scf_string_t* str = scf_string_alloc(); @@ -715,31 +800,41 @@ int __x64_elf_add_dyn(elf_native_t* x64, const char* sysroot) i = x64->dyn_needs->size; - 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)x64->dynstr; - dyns[i + 1].d_un.d_ptr = (uintptr_t)x64->dynsym; - dyns[i + 2].d_un.d_val = str->len; - dyns[i + 3].d_un.d_val = sizeof(Elf64_Sym); - dyns[i + 4].d_un.d_ptr = (uintptr_t)x64->got_plt; - dyns[i + 5].d_un.d_ptr = sizeof(Elf64_Rela); - dyns[i + 6].d_un.d_ptr = DT_RELA; - dyns[i + 7].d_un.d_ptr = (uintptr_t)x64->rela_plt; -// dyns[i + 8].d_un.d_ptr = (uintptr_t)x64->gnu_version_r; -// dyns[i + 9].d_un.d_ptr = 1; -// dyns[i +10].d_un.d_ptr = (uintptr_t)x64->gnu_version; - dyns[i +8].d_un.d_ptr = 0; + 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; +#if 0 + dyns[i + 8].d_tag = DT_VERNEED; + dyns[i + 9].d_tag = DT_VERNEEDNUM; + dyns[i + 10].d_tag = DT_VERSYM; +#endif + dyns[i + 8].d_tag = DT_RELA; + dyns[i + 9].d_tag = DT_RELASZ; + dyns[i + 10].d_tag = DT_RELAENT; + dyns[i + 11].d_tag = DT_NULL; + + dyns[i ].d_un.d_ptr = (uintptr_t)x64->dynstr; + dyns[i + 1].d_un.d_ptr = (uintptr_t)x64->dynsym; + dyns[i + 2].d_un.d_val = str->len; + dyns[i + 3].d_un.d_val = sizeof(Elf64_Sym); + dyns[i + 4].d_un.d_ptr = (uintptr_t)x64->got_plt; + dyns[i + 5].d_un.d_ptr = sizeof(Elf64_Rela); + dyns[i + 6].d_un.d_ptr = DT_RELA; + dyns[i + 7].d_un.d_ptr = (uintptr_t)x64->rela_plt; +#if 0 + dyns[i + 8].d_un.d_ptr = (uintptr_t)x64->gnu_version_r; + dyns[i + 9].d_un.d_ptr = 1; + dyns[i + 10].d_un.d_ptr = (uintptr_t)x64->gnu_version; +#endif + dyns[i + 8].d_un.d_ptr = (uintptr_t)x64->rela_dyn; + dyns[i + 9].d_un.d_ptr = x64->rela_dyn->data_len; + dyns[i + 10].d_un.d_ptr = sizeof(Elf64_Rela); + dyns[i + 11].d_un.d_ptr = 0; x64->dynstr->data = str->data; x64->dynstr->data_len = str->len; @@ -747,6 +842,7 @@ int __x64_elf_add_dyn(elf_native_t* x64, const char* sysroot) str->data = NULL; str->len = 0; str->capacity = 0; + scf_string_free(str); str = NULL; @@ -757,6 +853,8 @@ int __x64_elf_add_dyn(elf_native_t* x64, const char* sysroot) x64->gnu_version_r->link = x64->dynstr; x64->gnu_version_r->info = x64->interp; #endif + x64->rela_dyn->link = x64->dynsym; + x64->rela_dyn->info = x64->got; __x64_section_update_index2(x64, sh_names, sizeof(sh_names) / sizeof(sh_names[0])); @@ -797,6 +895,7 @@ int __x64_so_add_dyn(elf_native_t* x64, const char* sysroot) ".gnu.hash", ".dynsym", ".dynstr", + ".rela.dyn", ".rela.plt", ".plt", @@ -805,6 +904,7 @@ int __x64_so_add_dyn(elf_native_t* x64, const char* sysroot) ".dynamic", ".got.plt", + ".got", ".data", }; @@ -813,10 +913,12 @@ int __x64_so_add_dyn(elf_native_t* x64, const char* sysroot) if (x64->dyn_needs) { __x64_section_update_index(x64, sizeof(sh_names_plt) / sizeof(sh_names_plt[0])); + _x64_elf_add_rela_dyn(x64, &x64->rela_dyn); _x64_elf_add_rela_plt(x64, &x64->rela_plt); _x64_elf_add_plt (x64, &x64->plt); - _x64_elf_add_dynamic (x64, &x64->dynamic, 4); + _x64_elf_add_dynamic (x64, &x64->dynamic, 6); _x64_elf_add_got_plt (x64, &x64->got_plt); + _x64_elf_add_got (x64, &x64->got); } else { __x64_section_update_index(x64, sizeof(sh_names) / sizeof(sh_names[0])); @@ -830,7 +932,7 @@ int __x64_so_add_dyn(elf_native_t* x64, const char* sysroot) scf_string_t* str = scf_string_alloc(); char c = '\0'; - int j = x64->n_plts; + int j = x64->n_plts + x64->n_gots; int i; scf_string_cat_cstr_len(str, &c, 1); @@ -907,21 +1009,27 @@ int __x64_so_add_dyn(elf_native_t* x64, const char* sysroot) dyns[i + 4].d_un.d_val = sizeof(Elf64_Sym); if (x64->dyn_needs) { - dyns[i + 5].d_tag = DT_PLTGOT; - dyns[i + 6].d_tag = DT_PLTRELSZ; - dyns[i + 7].d_tag = DT_PLTREL; - dyns[i + 8].d_tag = DT_JMPREL; - - dyns[i + 5].d_un.d_ptr = (uintptr_t)x64->got_plt; - dyns[i + 6].d_un.d_ptr = x64->rela_plt->data_len; - dyns[i + 7].d_un.d_ptr = DT_RELA; - dyns[i + 8].d_un.d_ptr = (uintptr_t)x64->rela_plt; - - dyns[i + 9].d_tag = DT_NULL; - dyns[i + 9].d_un.d_ptr = 0; + dyns[i + 5].d_tag = DT_PLTGOT; + dyns[i + 6].d_tag = DT_PLTRELSZ; + dyns[i + 7].d_tag = DT_PLTREL; + dyns[i + 8].d_tag = DT_JMPREL; + dyns[i + 5].d_un.d_ptr = (uintptr_t)x64->got_plt; + dyns[i + 6].d_un.d_ptr = x64->rela_plt->data_len; + dyns[i + 7].d_un.d_ptr = DT_RELA; + dyns[i + 8].d_un.d_ptr = (uintptr_t)x64->rela_plt; + + dyns[i + 9].d_tag = DT_RELA; + dyns[i + 10].d_tag = DT_RELASZ; + dyns[i + 11].d_tag = DT_RELAENT; + dyns[i + 9].d_un.d_ptr = (uintptr_t)x64->rela_dyn; + dyns[i + 10].d_un.d_ptr = x64->rela_dyn->data_len; + dyns[i + 11].d_un.d_ptr = sizeof(Elf64_Rela); + + dyns[i + 12].d_tag = DT_NULL; + dyns[i + 12].d_un.d_ptr = 0; } else { - dyns[i + 5].d_tag = DT_NULL; - dyns[i + 5].d_un.d_ptr = 0; + dyns[i + 5].d_tag = DT_NULL; + dyns[i + 5].d_un.d_ptr = 0; } x64->dynstr->data = str->data; @@ -930,6 +1038,7 @@ int __x64_so_add_dyn(elf_native_t* x64, const char* sysroot) str->data = NULL; str->len = 0; str->capacity = 0; + scf_string_free(str); str = NULL; @@ -940,6 +1049,9 @@ int __x64_so_add_dyn(elf_native_t* x64, const char* sysroot) x64->rela_plt->link = x64->dynsym; x64->rela_plt->info = x64->got_plt; + x64->rela_dyn->link = x64->dynsym; + x64->rela_dyn->info = x64->got; + __x64_section_update_index2(x64, sh_names_plt, sizeof(sh_names_plt) / sizeof(sh_names_plt[0])); } else __x64_section_update_index2(x64, sh_names, sizeof(sh_names) / sizeof(sh_names[0])); @@ -963,6 +1075,7 @@ static void __x64_dynamic_update(elf_native_t* x64, uint64_t rx_base, uint64_t r case DT_SYMTAB: case DT_STRTAB: case DT_JMPREL: + case DT_RELA: case DT_VERSYM: dtags[i].d_un.d_ptr = s->offset + rx_base; s->sh.sh_addr = s->offset + rx_base; @@ -1006,19 +1119,19 @@ static void __x64_plt_link(elf_native_t* x64, uint64_t rx_base, uint64_t rw_base x64->rela_plt->sh.sh_addr = rx_base + x64->rela_plt->offset; x64->dynamic->sh.sh_addr = rw_base + x64->dynamic->offset; x64->got_plt->sh.sh_addr = rw_base + x64->got_plt->offset; - x64->plt->sh.sh_addr = rx_base + x64->plt->offset; + x64-> plt->sh.sh_addr = rx_base + x64-> plt->offset; scf_logd("rw_base: %#lx, offset: %#lx\n", rw_base, x64->got_plt->offset); scf_logd("got_addr: %#lx\n", x64->got_plt->sh.sh_addr); Elf64_Rela* rela_plt = (Elf64_Rela*)x64->rela_plt->data; - Elf64_Sym* dynsym = (Elf64_Sym* )x64->dynsym->data; - uint64_t* got_plt = (uint64_t* )x64->got_plt->data; - uint8_t* plt = (uint8_t* )x64->plt->data; + uint64_t* got_plt = (uint64_t* )x64-> got_plt->data; + uint8_t* plt = (uint8_t* )x64-> plt->data; uint64_t got_addr = x64->got_plt->sh.sh_addr + 8; - uint64_t plt_addr = x64->plt->sh.sh_addr; - int32_t offset = got_addr - plt_addr - 6; + uint64_t plt_addr = x64-> plt->sh.sh_addr; + + int32_t offset = got_addr - plt_addr - 6; got_plt[0] = x64->dynamic->sh.sh_addr; got_plt[1] = 0; @@ -1041,11 +1154,26 @@ static void __x64_plt_link(elf_native_t* x64, uint64_t rx_base, uint64_t rw_base got_addr += 16; plt_addr += 16; + elf_sym_t* sym; int i; + int j = 0; + int n = 0; + for (i = 0; i < x64->n_plts; i++) { + + while (j < x64->dynsyms->size) { + sym = x64->dynsyms->data[j]; + + j++; + + if (!sym->got_flag && i + 1 == ++n) + break; + } + assert(j <= x64->dynsyms->size); + rela_plt[i].r_offset = got_addr; rela_plt[i].r_addend = 0; - rela_plt[i].r_info = ELF64_R_INFO(i + 1, R_X86_64_JUMP_SLOT); + rela_plt[i].r_info = ELF64_R_INFO(j, R_X86_64_JUMP_SLOT); scf_logd("got_addr: %#lx\n", got_addr); @@ -1064,15 +1192,88 @@ static void __x64_plt_link(elf_native_t* x64, uint64_t rx_base, uint64_t rw_base got_plt++; } - for (i = 0; i < x64->dyn_relas->size; i++) { - Elf64_Rela* r = x64->dyn_relas->data[i]; + if (!x64->plt_relas) + return; + + Elf64_Rela* r; + + for (i = 0; i < x64->plt_relas->size; i++) { + r = x64->plt_relas->data[i]; + + int sym_idx = ELF64_R_SYM(r->r_info); + + assert(sym_idx > 0); + assert(sym_idx - 1 < x64->dynsyms->size); + + sym = x64->dynsyms->data[sym_idx - 1]; + + uint64_t plt_addr = x64->plt->sh.sh_addr + (sym->plt_got_index + 1) * 16; + + int32_t offset = plt_addr - (cs_base + r->r_offset) + r->r_addend; + + memcpy(cs->data + r->r_offset, &offset, sizeof(offset)); + } +} + +static void __x64_got_link(elf_native_t* x64, uint64_t rx_base, uint64_t rw_base, elf_section_t* cs) +{ + uint64_t cs_base = rx_base + cs->offset; + + x64->rela_dyn->sh.sh_addr = rx_base + x64->rela_dyn->offset; + x64->got ->sh.sh_addr = rw_base + x64->got->offset; + + Elf64_Rela* rela_dyn = (Elf64_Rela*)x64->rela_dyn->data; + uint64_t* got = (uint64_t* )x64->got->data; + + uint64_t got_addr = x64->got->sh.sh_addr; + + elf_sym_t* sym; + int i; + int j = 0; + int n = 0; + + for (i = 0; i < x64->n_gots; i++) { + + while (j < x64->dynsyms->size) { + sym = x64->dynsyms->data[j]; + + j++; + + if (sym->got_flag && i + 1 == ++n) + break; + } + assert(j <= x64->dynsyms->size); + + rela_dyn[i].r_offset = got_addr; + rela_dyn[i].r_addend = 0; + rela_dyn[i].r_info = ELF64_R_INFO(j, R_X86_64_GLOB_DAT); + + scf_logd("got_addr: %#lx\n", got_addr); + + *got = 0; + + got_addr += 8; + got++; + } + + if (!x64->got_relas) + return; + + Elf64_Rela* r; + + for (i = 0; i < x64->got_relas->size; i++) { + r = x64->got_relas->data[i]; int sym_idx = ELF64_R_SYM(r->r_info); + assert(sym_idx > 0); + assert(sym_idx - 1 < x64->dynsyms->size); - uint64_t plt_addr = x64->plt->sh.sh_addr + sym_idx * 16; + sym = x64->dynsyms->data[sym_idx - 1]; - int32_t offset = plt_addr - (cs_base + r->r_offset) + r->r_addend; + uint64_t got_addr = x64->got->sh.sh_addr + sym->plt_got_index * 8; + + int32_t offset = got_addr - (cs_base + r->r_offset) + r->r_addend; memcpy(cs->data + r->r_offset, &offset, sizeof(offset)); } @@ -1088,6 +1289,9 @@ void __x64_elf_post_dyn(elf_native_t* x64, uint64_t rx_base, uint64_t rw_base, e if (x64->plt) __x64_plt_link(x64, rx_base, rw_base, cs); + if (x64->got) + __x64_got_link(x64, rx_base, rw_base, cs); + __x64_dynamic_update(x64, rx_base, rw_base); __x64_dynsym_update (x64); } diff --git a/examples/hello.c b/examples/hello.c index a4f61fe..4cc8c43 100644 --- a/examples/hello.c +++ b/examples/hello.c @@ -1,4 +1,4 @@ -#include"stdio.h" +#include int main() { diff --git a/examples/libmy1.c b/examples/libmy1.c new file mode 100644 index 0000000..87eb357 --- /dev/null +++ b/examples/libmy1.c @@ -0,0 +1,6 @@ +int g_i = 2; + +int f(int a) +{ + return g_i + a; +} diff --git a/examples/scf_printf.c b/examples/scf_printf.c index e6df4f9..e38964b 100644 --- a/examples/scf_printf.c +++ b/examples/scf_printf.c @@ -1,13 +1,4 @@ -struct va_list -{ - uint8_t* iptr; - uint8_t* fptr; - uint8_t* optr; - - intptr_t ireg; - intptr_t freg; - intptr_t others; -}; +#include int scf_ulong2a(char* buf, int* pn, int size, uint64_t num) { diff --git a/examples/test_libmy1.c b/examples/test_libmy1.c new file mode 100644 index 0000000..005cb6e --- /dev/null +++ b/examples/test_libmy1.c @@ -0,0 +1,9 @@ +#include + +extern int g_i; + +int main() +{ + printf("result: %d\n", g_i); + return 0; +} diff --git a/lex/scf_lex.c b/lex/scf_lex.c index 693aef6..26dcbd3 100644 --- a/lex/scf_lex.c +++ b/lex/scf_lex.c @@ -116,6 +116,7 @@ static scf_key_word_t key_words[] = {SCF_CSTR("__builtin_va_start"), SCF_LEX_WORD_KEY_VA_START}, {SCF_CSTR("__builtin_va_arg"), SCF_LEX_WORD_KEY_VA_ARG}, + {SCF_CSTR("__builtin_va_copy"), SCF_LEX_WORD_KEY_VA_COPY}, {SCF_CSTR("__builtin_va_end"), SCF_LEX_WORD_KEY_VA_END}, }; diff --git a/native/risc/scf_risc_reg.c b/native/risc/scf_risc_reg.c index 2f75ea9..0e8f2e1 100644 --- a/native/risc/scf_risc_reg.c +++ b/native/risc/scf_risc_reg.c @@ -286,7 +286,7 @@ int risc_select_free_reg(scf_register_t** preg, scf_3ac_code_t* c, scf_function_ } assert(0 == r->dag_nodes->size); - r = f->rops->find_register_type_id_bytes(0, r->id, f->rops->MAX_BYTES); + r = f->rops->find_register_type_id_bytes(is_float, r->id, f->rops->MAX_BYTES); assert(0 == r->dag_nodes->size); diff --git a/native/x64/scf_x64.c b/native/x64/scf_x64.c index 94b2b89..421d334 100644 --- a/native/x64/scf_x64.c +++ b/native/x64/scf_x64.c @@ -242,9 +242,9 @@ static int _x64_function_finish(scf_function_t* f) scf_logd("### local: %#x, local_vars_size: %#x, callee_saved_size: %#x\n", local, f->local_vars_size, f->callee_saved_size); - if (f->bp_used_flag || f->vla_flag || f->call_flag) { + if (f->bp_used_flag || f->call_flag) { - if (f->bp_used_flag || f->vla_flag) { + if (f->bp_used_flag) { inst = x64_make_inst_G2E(mov, rsp, rbp); X64_INST_ADD_CHECK(end, inst, NULL); end->inst_bytes += inst->len; @@ -260,13 +260,13 @@ static int _x64_function_finish(scf_function_t* f) f->init_code_bytes = 0; - if (f->bp_used_flag || f->vla_flag || f->call_flag) { + if (f->bp_used_flag || f->call_flag) { inst = x64_make_inst_G(push, rbp); X64_INST_ADD_CHECK(f->init_code, inst, NULL); f->init_code_bytes += inst->len; - if (f->bp_used_flag || f->vla_flag) { + if (f->bp_used_flag) { inst = x64_make_inst_G2E(mov, rbp, rsp); X64_INST_ADD_CHECK(f->init_code, inst, NULL); f->init_code_bytes += inst->len; @@ -381,7 +381,7 @@ static int _x64_argv_prepare(scf_graph_t* g, scf_basic_block_t* bb, scf_function if (l == scf_list_sentinel(&f->dag_list_head)) continue; - int ret = _x64_rcg_make_node(&gn, g, dn, v->rabi); + int ret = x64_rcg_make_node(&gn, g, dn, v->rabi); if (ret < 0) return ret; diff --git a/native/x64/scf_x64.h b/native/x64/scf_x64.h index 47e13c8..42f4ec3 100644 --- a/native/x64/scf_x64.h +++ b/native/x64/scf_x64.h @@ -32,8 +32,9 @@ typedef int (*x64_inst_handler_pt)(scf_native_t* ctx, scf_3ac_code_t* c); x64_rcg_handler_pt scf_x64_find_rcg_handler (const int op_type); x64_inst_handler_pt scf_x64_find_inst_handler(const int op_type); -int x64_rcg_find_node(scf_graph_node_t** pp, scf_graph_t* g, scf_dag_node_t* dn, scf_register_t* reg); -int _x64_rcg_make_node(scf_graph_node_t** pp, scf_graph_t* g, scf_dag_node_t* dn, scf_register_t* reg); +int x64_rcg_make (scf_3ac_code_t* c, scf_graph_t* g, scf_dag_node_t* dn, scf_register_t* reg); +int x64_rcg_find_node(scf_graph_node_t** pp, scf_graph_t* g, scf_dag_node_t* dn, scf_register_t* reg); +int x64_rcg_make_node(scf_graph_node_t** pp, scf_graph_t* g, scf_dag_node_t* dn, scf_register_t* reg); int scf_x64_open (scf_native_t* ctx, const char* arch); int scf_x64_close (scf_native_t* ctx); @@ -57,10 +58,10 @@ int x64_load_bb_colors (scf_basic_block_t* bb, scf_bb_group_t* bbg, scf_function int x64_load_bb_colors2(scf_basic_block_t* bb, scf_bb_group_t* bbg, scf_function_t* f); int x64_init_bb_colors (scf_basic_block_t* bb); -scf_instruction_t* x64_make_inst_M (scf_rela_t** prela, scf_x64_OpCode_t* OpCode, scf_variable_t* v, scf_register_t* r_base); -scf_instruction_t* x64_make_inst_I2M(scf_rela_t** prela, scf_x64_OpCode_t* OpCode, scf_variable_t* v_dst, scf_register_t* r_base, uint8_t* imm, int32_t size); -scf_instruction_t* x64_make_inst_G2M(scf_rela_t** prela, scf_x64_OpCode_t* OpCode, scf_variable_t* v_dst, scf_register_t* r_base, scf_register_t* r_src); -scf_instruction_t* x64_make_inst_M2G(scf_rela_t** prela, scf_x64_OpCode_t* OpCode, scf_register_t* r_dst, scf_register_t* r_base, scf_variable_t* v_src); +scf_instruction_t* x64_make_inst_M (scf_rela_t** prela, scf_x64_OpCode_t* OpCode, scf_variable_t* v, scf_register_t* r_base, scf_3ac_code_t* c, scf_function_t* f); +scf_instruction_t* x64_make_inst_I2M(scf_rela_t** prela, scf_x64_OpCode_t* OpCode, scf_variable_t* v_dst, scf_register_t* r_base, uint8_t* imm, int32_t size, scf_3ac_code_t* c, scf_function_t* f); +scf_instruction_t* x64_make_inst_G2M(scf_rela_t** prela, scf_x64_OpCode_t* OpCode, scf_variable_t* v_dst, scf_register_t* r_base, scf_register_t* r_src, scf_3ac_code_t* c, scf_function_t* f); +scf_instruction_t* x64_make_inst_M2G(scf_rela_t** prela, scf_x64_OpCode_t* OpCode, scf_register_t* r_dst, scf_register_t* r_base, scf_variable_t* v_src, scf_3ac_code_t* c, scf_function_t* f); int x64_float_OpCode_type(int OpCode_type, int var_type); diff --git a/native/x64/scf_x64_inst.c b/native/x64/scf_x64_inst.c index e10d024..2abb52c 100644 --- a/native/x64/scf_x64_inst.c +++ b/native/x64/scf_x64_inst.c @@ -443,7 +443,7 @@ static int _x64_call_update_dsts(scf_3ac_code_t* c, scf_function_t* f, scf_regis scf_rela_t* rela = NULL; - inst = x64_make_inst_G2M(&rela, mov, dn->var, NULL, rs); + inst = x64_make_inst_G2M(&rela, mov, dn->var, NULL, rs, c, f); X64_INST_ADD_CHECK(c, inst, rela); X64_RELA_ADD_CHECK(f->data_relas, rela, c, dn->var, NULL); } @@ -565,7 +565,7 @@ static int _x64_inst_call_handler(scf_native_t* ctx, scf_3ac_code_t* c) inst = x64_make_inst_E(call, r_pf); X64_INST_ADD_CHECK(c, inst, NULL); } else { - inst = x64_make_inst_M(&rela, call, dn->var, NULL); + inst = x64_make_inst_M(&rela, call, dn->var, NULL, c, f); X64_INST_ADD_CHECK(c, inst, rela); X64_RELA_ADD_CHECK(f->data_relas, rela, c, dn->var, NULL); } @@ -649,7 +649,7 @@ static int _x64_inst_unary(scf_native_t* ctx, scf_3ac_code_t* c, int OpCode_type } else { scf_rela_t* rela = NULL; - inst = x64_make_inst_M(&rela, OpCode, var, NULL); + inst = x64_make_inst_M(&rela, OpCode, var, NULL, c, f); X64_INST_ADD_CHECK(c, inst, rela); X64_RELA_ADD_CHECK(f->data_relas, rela, c, var, NULL); } @@ -696,7 +696,7 @@ static int _x64_inst_unary_assign(scf_native_t* ctx, scf_3ac_code_t* c, int OpCo } else { scf_rela_t* rela = NULL; - inst = x64_make_inst_M(&rela, OpCode, var, NULL); + inst = x64_make_inst_M(&rela, OpCode, var, NULL, c, f); X64_INST_ADD_CHECK(c, inst, rela); X64_RELA_ADD_CHECK(f->data_relas, rela, c, var, NULL); } @@ -774,7 +774,7 @@ static int _x64_inst_neg_handler(scf_native_t* ctx, scf_3ac_code_t* c) scf_rela_t* rela = NULL; - inst = x64_make_inst_M2G(&rela, sub, rd, NULL, v); + inst = x64_make_inst_M2G(&rela, sub, rd, NULL, v, c, f); X64_INST_ADD_CHECK(c, inst, rela); X64_RELA_ADD_CHECK(f->data_relas, rela, c, v, NULL); } @@ -829,7 +829,7 @@ static int _x64_inst_inc_float(scf_function_t* f, scf_3ac_code_t* c, int INC) X64_SELECT_REG_CHECK(&rs, src->dag_node, c, f, 1); - inst = x64_make_inst_M2G(&rela, OpCode, rs, NULL, v1); + inst = x64_make_inst_M2G(&rela, OpCode, rs, NULL, v1, c, f); X64_INST_ADD_CHECK(c, inst, rela); X64_RELA_ADD_CHECK(f->data_relas, rela, c, v1, NULL); return 0; @@ -883,7 +883,7 @@ static int _x64_inst_inc(scf_native_t* ctx, scf_3ac_code_t* c, int INC, int ADD) } else { scf_rela_t* rela = NULL; - inst = x64_make_inst_I2M(&rela, OpCode, v, NULL, (uint8_t*)&v->data_size, imm_size); + inst = x64_make_inst_I2M(&rela, OpCode, v, NULL, (uint8_t*)&v->data_size, imm_size, c, f); X64_INST_ADD_CHECK(c, inst, rela); X64_RELA_ADD_CHECK(f->data_relas, rela, c, v, NULL); } @@ -902,7 +902,7 @@ static int _x64_inst_inc(scf_native_t* ctx, scf_3ac_code_t* c, int INC, int ADD) } else { scf_rela_t* rela = NULL; - inst = x64_make_inst_M(&rela, OpCode, v, NULL); + inst = x64_make_inst_M(&rela, OpCode, v, NULL, c, f); X64_INST_ADD_CHECK(c, inst, rela); X64_RELA_ADD_CHECK(f->data_relas, rela, c, v, NULL); } @@ -1175,7 +1175,7 @@ static int _x64_inst_address_of_handler(scf_native_t* ctx, scf_3ac_code_t* c) } lea = x64_find_OpCode(SCF_X64_LEA, 8,8, SCF_X64_E2G); - inst = x64_make_inst_M2G(&rela, lea, rd, NULL, src->dag_node->var); + inst = x64_make_inst_M2G(&rela, lea, rd, NULL, src->dag_node->var, c, f); X64_INST_ADD_CHECK(c, inst, rela); X64_RELA_ADD_CHECK(f->data_relas, rela, c, src->dag_node->var, NULL); return 0; @@ -1477,171 +1477,6 @@ static int _x64_inst_mod_assign_handler(scf_native_t* ctx, scf_3ac_code_t* c) return _div_mod_assign(ctx, c, 1); } -static int _x64_inst_dump_handler(scf_native_t* ctx, scf_3ac_code_t* c) -{ - if (!c->srcs || c->srcs->size != 3) - return -EINVAL; - - scf_x64_context_t* x64 = ctx->priv; - scf_function_t* f = x64->f; - scf_3ac_operand_t* src = c->srcs->data[0]; - scf_3ac_operand_t* logf = c->srcs->data[1]; - scf_3ac_operand_t* msg = c->srcs->data[2]; - - if (!logf || !logf->dag_node) - return -EINVAL; - - if (!msg || !msg->dag_node) - return -EINVAL; - - scf_instruction_t* inst = NULL; - scf_register_t* rs = NULL; - scf_register_t* rd = NULL; - scf_register_t* rdi = x64_find_register("rdi"); - scf_register_t* rsi = x64_find_register("rsi"); - scf_register_t* rax = x64_find_register("rax"); - - scf_x64_OpCode_t* lea = x64_find_OpCode(SCF_X64_LEA, 8, 8, SCF_X64_E2G); - scf_x64_OpCode_t* call = x64_find_OpCode(SCF_X64_CALL,4, 4, SCF_X64_I); - scf_x64_OpCode_t* xor = x64_find_OpCode(SCF_X64_XOR, 8, 8, SCF_X64_G2E); - scf_x64_OpCode_t* mov = x64_find_OpCode(SCF_X64_MOV, 8, 8, SCF_X64_G2E); - - if (!c->instructions) { - c->instructions = scf_vector_alloc(); - if (!c->instructions) - return -ENOMEM; - } - - X64_SELECT_REG_CHECK(&rs, src->dag_node, c, f, 1); - - inst = x64_make_inst_G2E(mov, rsi, rs); - X64_INST_ADD_CHECK(c, inst, NULL); - - scf_rela_t* rela = NULL; - - inst = x64_make_inst_M2G(&rela, lea, rdi, NULL, msg->dag_node->var); - X64_INST_ADD_CHECK(c, inst, rela); - X64_RELA_ADD_CHECK(f->data_relas, rela, c, msg->dag_node->var, NULL); - - inst = x64_make_inst_G2E(xor, rax, rax); - X64_INST_ADD_CHECK(c, inst, NULL); - - // call printf() to show msg - uint32_t imm = 0; - inst = x64_make_inst_I(call, (uint8_t*)&imm, sizeof(imm)); - X64_INST_ADD_CHECK(c, inst, NULL); - - rela = calloc(1, sizeof(scf_rela_t)); - if (!rela) - return -ENOMEM; - rela->inst_offset = 1; - X64_RELA_ADD_CHECK(f->text_relas, rela, c, NULL, logf->dag_node->var->func_ptr); - - inst = x64_make_inst_G2E(xor, rax, rax); - X64_INST_ADD_CHECK(c, inst, NULL); - - inst = x64_make_inst_G2P(mov, rax, 0, rax); - X64_INST_ADD_CHECK(c, inst, NULL); - return 0; -} - -static int _x64_inst_vla_alloc_handler(scf_native_t* ctx, scf_3ac_code_t* c) -{ - if (!c->dsts || c->dsts->size != 1) - return -EINVAL; - - if (!c->srcs || c->srcs->size != 3) - return -EINVAL; - - scf_x64_context_t* x64 = ctx->priv; - scf_function_t* f = x64->f; - scf_3ac_operand_t* dst = c->dsts->data[0]; - scf_3ac_operand_t* src = c->srcs->data[0]; - - if (!dst || !dst->dag_node) - return -EINVAL; - - if (!src || !src->dag_node) - return -EINVAL; - - scf_instruction_t* inst = NULL; - scf_register_t* rs = NULL; - scf_register_t* rd = NULL; - scf_register_t* rsp = x64_find_register("rsp"); - - scf_x64_OpCode_t* add = x64_find_OpCode(SCF_X64_ADD, 4, 8, SCF_X64_I2E); - scf_x64_OpCode_t* and = x64_find_OpCode(SCF_X64_AND, 4, 8, SCF_X64_I2E); - scf_x64_OpCode_t* sub = x64_find_OpCode(SCF_X64_SUB, 8, 8, SCF_X64_E2G); - scf_x64_OpCode_t* mov = x64_find_OpCode(SCF_X64_MOV, 8, 8, SCF_X64_G2E); - - if (!c->instructions) { - c->instructions = scf_vector_alloc(); - if (!c->instructions) - return -ENOMEM; - } - - X64_SELECT_REG_CHECK(&rs, src->dag_node, c, f, 1); - - uint32_t imm = 0xf; - inst = x64_make_inst_I2E(add, rs, (uint8_t*)&imm, sizeof(imm)); - X64_INST_ADD_CHECK(c, inst, NULL); - - imm = ~0xf; - inst = x64_make_inst_I2E(and, rs, (uint8_t*)&imm, sizeof(imm)); - X64_INST_ADD_CHECK(c, inst, NULL); - - inst = x64_make_inst_E2G(sub, rsp, rs); - X64_INST_ADD_CHECK(c, inst, NULL); - - int ret = x64_save_var(src->dag_node, c, f); - if (ret < 0) - return ret; - - X64_SELECT_REG_CHECK(&rd, dst->dag_node, c, f, 0); - - inst = x64_make_inst_G2E(mov, rd, rsp); - X64_INST_ADD_CHECK(c, inst, NULL); - return 0; -} - -static int _x64_inst_vla_free_handler(scf_native_t* ctx, scf_3ac_code_t* c) -{ - if (!c->dsts || c->dsts->size != 1) - return -EINVAL; - - if (!c->srcs || c->srcs->size != 3) - return -EINVAL; - - scf_x64_context_t* x64 = ctx->priv; - scf_function_t* f = x64->f; - scf_3ac_operand_t* src = c->srcs->data[0]; - - if (!src || !src->dag_node) - return -EINVAL; - - scf_instruction_t* inst = NULL; - scf_register_t* rs = NULL; - scf_register_t* rsp = x64_find_register("rsp"); - scf_x64_OpCode_t* add = x64_find_OpCode(SCF_X64_ADD, 8, 8, SCF_X64_E2G); - scf_x64_OpCode_t* xor = x64_find_OpCode(SCF_X64_XOR, 8, 8, SCF_X64_G2E); - - if (!c->instructions) { - c->instructions = scf_vector_alloc(); - if (!c->instructions) - return -ENOMEM; - } - - X64_SELECT_REG_CHECK(&rs, src->dag_node, c, f, 1); - - inst = x64_make_inst_E2G(add, rsp, rs); - X64_INST_ADD_CHECK(c, inst, NULL); - - inst = x64_make_inst_G2E(xor, rs, rs); - X64_INST_ADD_CHECK(c, inst, NULL); - - return x64_save_var(src->dag_node, c, f); -} - static int _x64_inst_return_handler(scf_native_t* ctx, scf_3ac_code_t* c) { if (!c->srcs || c->srcs->size < 1) @@ -1758,7 +1593,7 @@ static int _x64_inst_return_handler(scf_native_t* ctx, scf_3ac_code_t* c) inst = x64_make_inst_I2G(mov, rd, (uint8_t*)&v->data, rd->bytes); X64_INST_ADD_CHECK(c, inst, NULL); } else { - inst = x64_make_inst_M2G(&rela, mov, rd, NULL, v); + inst = x64_make_inst_M2G(&rela, mov, rd, NULL, v, c, f); X64_INST_ADD_CHECK(c, inst, rela); X64_RELA_ADD_CHECK(f->data_relas, rela, c, v, NULL); } @@ -2442,14 +2277,9 @@ static x64_inst_handler_pt x64_inst_handlers[] = [SCF_OP_AND_ASSIGN ] = _x64_inst_and_assign_handler, [SCF_OP_OR_ASSIGN ] = _x64_inst_or_assign_handler, - [SCF_OP_VLA_ALLOC ] = _x64_inst_vla_alloc_handler, - [SCF_OP_VLA_FREE ] = _x64_inst_vla_free_handler, - [SCF_OP_RETURN ] = _x64_inst_return_handler, [SCF_OP_GOTO ] = _x64_inst_goto_handler, - [SCF_OP_3AC_DUMP ] = _x64_inst_dump_handler, - [SCF_OP_3AC_JZ ] = _x64_inst_jz_handler, [SCF_OP_3AC_JNZ ] = _x64_inst_jnz_handler, [SCF_OP_3AC_JGT ] = _x64_inst_jgt_handler, diff --git a/native/x64/scf_x64_inst_binary.c b/native/x64/scf_x64_inst_binary.c index ec83545..63a329c 100644 --- a/native/x64/scf_x64_inst_binary.c +++ b/native/x64/scf_x64_inst_binary.c @@ -44,7 +44,7 @@ static int _binary_assign_sib_float(scf_register_t* rb, scf_register_t* ri, int3 X64_INST_ADD_CHECK(c, inst, NULL); OpCode = x64_find_OpCode(OpCode_type, v->size, v->size, SCF_X64_E2G); - inst = x64_make_inst_M2G(&rela, OpCode, rs, NULL, src->var); + inst = x64_make_inst_M2G(&rela, OpCode, rs, NULL, src->var, c, f); X64_INST_ADD_CHECK(c, inst, rela); X64_RELA_ADD_CHECK(f->data_relas, rela, c, src->var, NULL); diff --git a/native/x64/scf_x64_inst_cmp.c b/native/x64/scf_x64_inst_cmp.c index 2230212..e4de880 100644 --- a/native/x64/scf_x64_inst_cmp.c +++ b/native/x64/scf_x64_inst_cmp.c @@ -70,7 +70,7 @@ static int _inst_cmp(scf_dag_node_t* src0, scf_dag_node_t* src1, scf_3ac_code_t* inst = x64_make_inst_E2G(cmp, rs0, rs1); X64_INST_ADD_CHECK(c, inst, NULL); } else { - inst = x64_make_inst_M2G(&rela, cmp, rs0, NULL, src1->var); + inst = x64_make_inst_M2G(&rela, cmp, rs0, NULL, src1->var, c, f); X64_INST_ADD_CHECK(c, inst, rela); X64_RELA_ADD_CHECK(f->data_relas, rela, c, src1->var, NULL); } diff --git a/native/x64/scf_x64_inst_common.c b/native/x64/scf_x64_inst_common.c index 52e7b00..117925a 100644 --- a/native/x64/scf_x64_inst_common.c +++ b/native/x64/scf_x64_inst_common.c @@ -127,7 +127,7 @@ static int _x64_inst_op2_imm(int OpCode_type, scf_dag_node_t* dst, scf_dag_node_ OpCode = x64_find_OpCode(OpCode_type, src_size, dst_size, SCF_X64_I2E); if (OpCode) { - inst = x64_make_inst_I2M(&rela, OpCode, dst->var, NULL, (uint8_t*)&src->var->data, src_size); + inst = x64_make_inst_I2M(&rela, OpCode, dst->var, NULL, (uint8_t*)&src->var->data, src_size, c, f); X64_INST_ADD_CHECK(c, inst, rela); X64_RELA_ADD_CHECK(f->data_relas, rela, c, dst->var, NULL); return 0; @@ -144,7 +144,7 @@ static int _x64_inst_op2_imm(int OpCode_type, scf_dag_node_t* dst, scf_dag_node_ src->var->tmp_flag = 1; X64_SELECT_REG_CHECK(&rs, src, c, f, 1); - inst = x64_make_inst_G2M(&rela, OpCode, dst->var, NULL, rs); + inst = x64_make_inst_G2M(&rela, OpCode, dst->var, NULL, rs, c, f); X64_INST_ADD_CHECK(c, inst, rela); X64_RELA_ADD_CHECK(f->data_relas, rela, c, dst->var, NULL); @@ -220,7 +220,7 @@ int x64_inst_op2(int OpCode_type, scf_dag_node_t* dst, scf_dag_node_t* src, scf_ return -EINVAL; } - inst = x64_make_inst_M2G(&rela, OpCode, rd, NULL, src->var); + inst = x64_make_inst_M2G(&rela, OpCode, rd, NULL, src->var, c, f); X64_INST_ADD_CHECK(c, inst, rela); X64_RELA_ADD_CHECK(f->data_relas, rela, c, src->var, NULL); } @@ -276,7 +276,7 @@ int x64_inst_movx(scf_dag_node_t* dst, scf_dag_node_t* src, scf_3ac_code_t* c, s } else { scf_rela_t* rela = NULL; - inst = x64_make_inst_M2G(&rela, movx, rd, NULL, src->var); + inst = x64_make_inst_M2G(&rela, movx, rd, NULL, src->var, c, f); X64_INST_ADD_CHECK(c, inst, rela); X64_RELA_ADD_CHECK(f->data_relas, rela, c, src->var, NULL); } @@ -339,7 +339,7 @@ int x64_inst_float_cast(scf_dag_node_t* dst, scf_dag_node_t* src, scf_3ac_code_t } else { scf_rela_t* rela = NULL; - inst = x64_make_inst_M2G(&rela, OpCode, rd, NULL, src->var); + inst = x64_make_inst_M2G(&rela, OpCode, rd, NULL, src->var, c, f); X64_INST_ADD_CHECK(c, inst, rela); X64_RELA_ADD_CHECK(f->data_relas, rela, c, src->var, NULL); } diff --git a/native/x64/scf_x64_inst_div.c b/native/x64/scf_x64_inst_div.c index eebb869..9c55d3d 100644 --- a/native/x64/scf_x64_inst_div.c +++ b/native/x64/scf_x64_inst_div.c @@ -64,7 +64,7 @@ int x64_inst_int_div(scf_dag_node_t* dst, scf_dag_node_t* src, scf_3ac_code_t* c scf_rela_t* rela = NULL; mov = x64_find_OpCode(SCF_X64_MOV, size, size, SCF_X64_E2G); - inst = x64_make_inst_M2G(&rela, mov, rl, NULL, dst->var); + inst = x64_make_inst_M2G(&rela, mov, rl, NULL, dst->var, c, f); X64_INST_ADD_CHECK(c, inst, rela); X64_RELA_ADD_CHECK(f->data_relas, rela, c, dst->var, NULL); } @@ -88,7 +88,7 @@ int x64_inst_int_div(scf_dag_node_t* dst, scf_dag_node_t* src, scf_3ac_code_t* c } else { scf_rela_t* rela = NULL; - inst = x64_make_inst_M(&rela, div, src->var, NULL); + inst = x64_make_inst_M(&rela, div, src->var, NULL, c, f); X64_INST_ADD_CHECK(c, inst, rela); X64_RELA_ADD_CHECK(f->data_relas, rela, c, src->var, NULL); } @@ -109,7 +109,7 @@ int x64_inst_int_div(scf_dag_node_t* dst, scf_dag_node_t* src, scf_3ac_code_t* c scf_rela_t* rela = NULL; mov = x64_find_OpCode(SCF_X64_MOV, dst->var->size, dst->var->size, SCF_X64_G2E); - inst = x64_make_inst_G2M(&rela, mov, dst->var, NULL, result); + inst = x64_make_inst_G2M(&rela, mov, dst->var, NULL, result, c, f); X64_INST_ADD_CHECK(c, inst, rela); X64_RELA_ADD_CHECK(f->data_relas, rela, c, dst->var, NULL); } @@ -128,4 +128,3 @@ int x64_inst_int_div(scf_dag_node_t* dst, scf_dag_node_t* src, scf_3ac_code_t* c return 0; } - diff --git a/native/x64/scf_x64_inst_mul.c b/native/x64/scf_x64_inst_mul.c index 7fcc0db..ca23841 100644 --- a/native/x64/scf_x64_inst_mul.c +++ b/native/x64/scf_x64_inst_mul.c @@ -19,7 +19,7 @@ static int _int_mul_src(scf_x64_OpCode_t* mul, scf_register_t* rh, scf_dag_node_ } else { scf_rela_t* rela = NULL; - inst = x64_make_inst_M(&rela, mul, src->var, NULL); + inst = x64_make_inst_M(&rela, mul, src->var, NULL, c, f); X64_INST_ADD_CHECK(c, inst, rela); X64_RELA_ADD_CHECK(f->data_relas, rela, c, src->var, NULL); } @@ -119,14 +119,14 @@ int x64_inst_int_mul(scf_dag_node_t* dst, scf_dag_node_t* src, scf_3ac_code_t* c X64_INST_ADD_CHECK(c, inst, NULL); } - inst = x64_make_inst_M(&rela, mul, dst->var, NULL); + inst = x64_make_inst_M(&rela, mul, dst->var, NULL, c, f); X64_INST_ADD_CHECK(c, inst, rela); X64_RELA_ADD_CHECK(f->data_relas, rela, c, dst->var, NULL); - } else { + } else { mov2 = x64_find_OpCode(SCF_X64_MOV, size, size, SCF_X64_E2G); - inst = x64_make_inst_M2G(&rela, mov2, rl, NULL, dst->var); + inst = x64_make_inst_M2G(&rela, mov2, rl, NULL, dst->var, c, f); X64_INST_ADD_CHECK(c, inst, rela); X64_RELA_ADD_CHECK(f->data_relas, rela, c, dst->var, NULL); @@ -142,11 +142,10 @@ int x64_inst_int_mul(scf_dag_node_t* dst, scf_dag_node_t* src, scf_3ac_code_t* c X64_INST_ADD_CHECK(c, inst, NULL); } } else { - inst = x64_make_inst_G2M(&rela, mov, dst->var, NULL, rl); + inst = x64_make_inst_G2M(&rela, mov, dst->var, NULL, rl, c, f); X64_INST_ADD_CHECK(c, inst, rela); X64_RELA_ADD_CHECK(f->data_relas, rela, c, dst->var, NULL); } return 0; } - diff --git a/native/x64/scf_x64_inst_shift.c b/native/x64/scf_x64_inst_shift.c index 9444828..ec438c2 100644 --- a/native/x64/scf_x64_inst_shift.c +++ b/native/x64/scf_x64_inst_shift.c @@ -37,7 +37,7 @@ static int _shift_count(scf_dag_node_t* count, scf_3ac_code_t* c, scf_function_t scf_rela_t* rela = NULL; mov = x64_find_OpCode(SCF_X64_MOV, 1, 1, SCF_X64_E2G); - inst = x64_make_inst_M2G(&rela, mov, cl, NULL, count->var); + inst = x64_make_inst_M2G(&rela, mov, cl, NULL, count->var, c, f); X64_INST_ADD_CHECK(c, inst, rela); X64_RELA_ADD_CHECK(f->data_relas, rela, c, count->var, NULL); } @@ -87,12 +87,12 @@ static int _x64_shift(scf_native_t* ctx, scf_3ac_code_t* c, scf_dag_node_t* dst, if (0 != count->color) { shift = x64_find_OpCode(OpCode_type, 1, dst->var->size, SCF_X64_G2E); - inst = x64_make_inst_M(&rela, shift, dst->var, NULL); + inst = x64_make_inst_M(&rela, shift, dst->var, NULL, c, f); X64_INST_ADD_CHECK(c, inst, rela); X64_RELA_ADD_CHECK(f->data_relas, rela, c, dst->var, NULL); } else { shift = x64_find_OpCode(OpCode_type, 1, dst->var->size, SCF_X64_I2E); - inst = x64_make_inst_I2M(&rela, shift, dst->var, NULL, (uint8_t*)&count->var->data, 1); + inst = x64_make_inst_I2M(&rela, shift, dst->var, NULL, (uint8_t*)&count->var->data, 1, c, f); X64_INST_ADD_CHECK(c, inst, rela); X64_RELA_ADD_CHECK(f->data_relas, rela, c, dst->var, NULL); } diff --git a/native/x64/scf_x64_inst_util.c b/native/x64/scf_x64_inst_util.c index d475604..9d9d760 100644 --- a/native/x64/scf_x64_inst_util.c +++ b/native/x64/scf_x64_inst_util.c @@ -325,6 +325,46 @@ scf_instruction_t* x64_make_inst_I2E(scf_x64_OpCode_t* OpCode, scf_register_t* r return inst; } +int x64_make_inst_pic(scf_register_t** r_base, scf_variable_t* v, scf_3ac_code_t* c, scf_function_t* f) +{ + assert(!*r_base); + + int ret = x64_select_free_reg(r_base, c, f, 0); + if (ret < 0) { + scf_loge("PIC: select free reg failed\n"); + return ret; + } + + scf_rela_t* rela = NULL; + scf_x64_OpCode_t* mov = x64_find_OpCode(SCF_X64_MOV, 8, 8, SCF_X64_E2G); + scf_instruction_t* inst = _x64_make_OpCode(mov, 8, *r_base, NULL, NULL); + if (!inst) + return -ENOMEM; + + ret = _x64_make_disp(&rela, inst, (*r_base)->id, -1, 0); + if (ret < 0) { + free(inst); + return ret; + } + + X64_INST_ADD_CHECK(c, inst, rela); + + if (SCF_FUNCTION_PTR == v->type && v->const_literal_flag) { + assert(v->func_ptr); + + X64_RELA_ADD_CHECK(f->text_relas, rela, c, v, v->func_ptr); + } else + X64_RELA_ADD_CHECK(f->data_relas, rela, c, v, NULL); + + rela->type = R_X86_64_GOTPCREL; + + inst->dst.base = *r_base; + inst->src.base = NULL; + inst->src.disp = 0; + inst->src.mem_flag = 1; + return 0; +} + scf_instruction_t* x64_make_inst_L(scf_rela_t** prela, scf_x64_OpCode_t* OpCode) { uint8_t reg = 0; @@ -365,7 +405,7 @@ scf_instruction_t* x64_make_inst_L(scf_rela_t** prela, scf_x64_OpCode_t* OpCode) return inst; } -scf_instruction_t* x64_make_inst_M(scf_rela_t** prela, scf_x64_OpCode_t* OpCode, scf_variable_t* v, scf_register_t* r_base) +scf_instruction_t* x64_make_inst_M(scf_rela_t** prela, scf_x64_OpCode_t* OpCode, scf_variable_t* v, scf_register_t* r_base, scf_3ac_code_t* c, scf_function_t* f) { scf_register_t* rbp = x64_find_register("rbp"); @@ -386,6 +426,16 @@ scf_instruction_t* x64_make_inst_M(scf_rela_t** prela, scf_x64_OpCode_t* OpCode, } else if (v->global_flag) { base = -1; offset = 0; + + if (v->extern_flag && f->pic_flag) { + assert(!r_base); + + int ret = x64_make_inst_pic(&r_base, v, c, f); + if (ret < 0) + return NULL; + + base = r_base->id; + } } else { scf_loge("temp var should give a register\n"); return NULL; @@ -468,7 +518,7 @@ scf_instruction_t* x64_make_inst_I2L(scf_rela_t** prela, scf_x64_OpCode_t* OpCod return inst; } -scf_instruction_t* x64_make_inst_I2M(scf_rela_t** prela, scf_x64_OpCode_t* OpCode, scf_variable_t* v_dst, scf_register_t* r_base, uint8_t* imm, int32_t size) +scf_instruction_t* x64_make_inst_I2M(scf_rela_t** prela, scf_x64_OpCode_t* OpCode, scf_variable_t* v_dst, scf_register_t* r_base, uint8_t* imm, int32_t size, scf_3ac_code_t* c, scf_function_t* f) { scf_register_t* rbp = x64_find_register("rbp"); @@ -489,6 +539,16 @@ scf_instruction_t* x64_make_inst_I2M(scf_rela_t** prela, scf_x64_OpCode_t* OpCod } else if (v_dst->global_flag) { base = -1; offset = 0; + + if (v_dst->extern_flag && f->pic_flag) { + assert(!r_base); + + int ret = x64_make_inst_pic(&r_base, v_dst, c, f); + if (ret < 0) + return NULL; + + base = r_base->id; + } } else { scf_loge("temp var should give a register\n"); return NULL; @@ -555,7 +615,7 @@ scf_instruction_t* x64_make_inst_G2L(scf_rela_t** prela, scf_x64_OpCode_t* OpCod return inst; } -scf_instruction_t* x64_make_inst_G2M(scf_rela_t** prela, scf_x64_OpCode_t* OpCode, scf_variable_t* v_dst, scf_register_t* r_base, scf_register_t* r_src) +scf_instruction_t* x64_make_inst_G2M(scf_rela_t** prela, scf_x64_OpCode_t* OpCode, scf_variable_t* v_dst, scf_register_t* r_base, scf_register_t* r_src, scf_3ac_code_t* c, scf_function_t* f) { if (OpCode->ModRM_OpCode_used) { scf_loge("ModRM opcode invalid\n"); @@ -579,6 +639,16 @@ scf_instruction_t* x64_make_inst_G2M(scf_rela_t** prela, scf_x64_OpCode_t* OpCod } else if (v_dst->global_flag) { base = -1; offset = 0; + + if (v_dst->extern_flag && f->pic_flag) { + assert(!r_base); + + int ret = x64_make_inst_pic(&r_base, v_dst, c, f); + if (ret < 0) + return NULL; + + base = r_base->id; + } } else { scf_loge("temp var should give a register\n"); return NULL; @@ -633,7 +703,7 @@ scf_instruction_t* x64_make_inst_L2G(scf_rela_t** prela, scf_x64_OpCode_t* OpCod return inst; } -scf_instruction_t* x64_make_inst_M2G(scf_rela_t** prela, scf_x64_OpCode_t* OpCode, scf_register_t* r_dst, scf_register_t* r_base, scf_variable_t* v_src) +scf_instruction_t* x64_make_inst_M2G(scf_rela_t** prela, scf_x64_OpCode_t* OpCode, scf_register_t* r_dst, scf_register_t* r_base, scf_variable_t* v_src, scf_3ac_code_t* c, scf_function_t* f) { if (OpCode->ModRM_OpCode_used) { scf_loge("ModRM opcode invalid\n"); @@ -656,6 +726,16 @@ scf_instruction_t* x64_make_inst_M2G(scf_rela_t** prela, scf_x64_OpCode_t* OpCod } else if (v_src->global_flag) { base = -1; offset = 0; + + if (v_src->extern_flag && f->pic_flag) { + assert(!r_base); + + int ret = x64_make_inst_pic(&r_base, v_src, c, f); + if (ret < 0) + return NULL; + + base = r_base->id; + } } else { scf_loge("temp var should give a register\n"); return NULL; diff --git a/native/x64/scf_x64_peephole.c b/native/x64/scf_x64_peephole.c index e4e41a8..9f09af6 100644 --- a/native/x64/scf_x64_peephole.c +++ b/native/x64/scf_x64_peephole.c @@ -356,7 +356,8 @@ static int _x64_peephole_cmp(scf_vector_t* save_insts, scf_vector_t* peep_insts, else goto check; - ret = __x64_peep_dst_was_mem(inst, id); + if (id->base) + ret = __x64_peep_dst_was_mem(inst, id); } if (ret < 0) diff --git a/native/x64/scf_x64_rcg.c b/native/x64/scf_x64_rcg.c index 58f7344..baf144b 100644 --- a/native/x64/scf_x64_rcg.c +++ b/native/x64/scf_x64_rcg.c @@ -27,7 +27,7 @@ int x64_rcg_find_node(scf_graph_node_t** pp, scf_graph_t* g, scf_dag_node_t* dn, return 0; } -int _x64_rcg_make_node(scf_graph_node_t** pp, scf_graph_t* g, scf_dag_node_t* dn, scf_register_t* reg) +int x64_rcg_make_node(scf_graph_node_t** pp, scf_graph_t* g, scf_dag_node_t* dn, scf_register_t* reg) { x64_rcg_node_t* rn; x64_rcg_node_t tmp; @@ -69,7 +69,7 @@ int _x64_rcg_make_node(scf_graph_node_t** pp, scf_graph_t* g, scf_dag_node_t* dn return 0; } -static int _x64_rcg_make_edge(scf_graph_node_t* gn0, scf_graph_node_t* gn1) +static int x64_rcg_make_edge(scf_graph_node_t* gn0, scf_graph_node_t* gn1) { if (gn0 == gn1) return 0; @@ -114,7 +114,7 @@ static int _x64_rcg_active_vars(scf_graph_t* g, scf_vector_t* active_vars) if (!ds0->active) continue; - ret = _x64_rcg_make_node(&gn0, g, dn0, NULL); + ret = x64_rcg_make_node(&gn0, g, dn0, NULL); if (ret < 0) return ret; @@ -126,13 +126,13 @@ static int _x64_rcg_active_vars(scf_graph_t* g, scf_vector_t* active_vars) if (!ds1->active) continue; - ret = _x64_rcg_make_node(&gn1, g, dn1, NULL); + ret = x64_rcg_make_node(&gn1, g, dn1, NULL); if (ret < 0) return ret; assert(gn0 != gn1); - ret = _x64_rcg_make_edge(gn0, gn1); + ret = x64_rcg_make_edge(gn0, gn1); if (ret < 0) return ret; } @@ -163,7 +163,7 @@ static int _x64_rcg_operands(scf_graph_t* g, scf_vector_t* operands) if (scf_variable_const(dn0->var)) continue; - int ret = _x64_rcg_make_node(&gn0, g, dn0, NULL); + int ret = x64_rcg_make_node(&gn0, g, dn0, NULL); if (ret < 0) return ret; @@ -175,14 +175,14 @@ static int _x64_rcg_operands(scf_graph_t* g, scf_vector_t* operands) if (scf_variable_const(dn1->var)) continue; - ret = _x64_rcg_make_node(&gn1, g, dn1, NULL); + ret = x64_rcg_make_node(&gn1, g, dn1, NULL); if (ret < 0) return ret; if (gn1 == gn0) continue; - ret = _x64_rcg_make_edge(gn0, gn1); + ret = x64_rcg_make_edge(gn0, gn1); if (ret < 0) return ret; } @@ -208,14 +208,14 @@ static int _x64_rcg_to_active_vars(scf_graph_t* g, scf_graph_node_t* gn0, scf_ve if (!ds1->active) continue; - ret = _x64_rcg_make_node(&gn1, g, dn1, NULL); + ret = x64_rcg_make_node(&gn1, g, dn1, NULL); if (ret < 0) return ret; if (gn0 == gn1) continue; - ret = _x64_rcg_make_edge(gn0, gn1); + ret = x64_rcg_make_edge(gn0, gn1); if (ret < 0) return ret; } @@ -223,8 +223,7 @@ static int _x64_rcg_to_active_vars(scf_graph_t* g, scf_graph_node_t* gn0, scf_ve return 0; } -static int _x64_rcg_make(scf_3ac_code_t* c, scf_graph_t* g, scf_dag_node_t* dn, - scf_register_t* reg, scf_x64_OpCode_t* OpCode) +int x64_rcg_make(scf_3ac_code_t* c, scf_graph_t* g, scf_dag_node_t* dn, scf_register_t* reg) { scf_graph_node_t* gn0 = NULL; scf_graph_node_t* gn1; @@ -235,7 +234,7 @@ static int _x64_rcg_make(scf_3ac_code_t* c, scf_graph_t* g, scf_dag_node_t* dn, int i; if (dn || reg) { - ret = _x64_rcg_make_node(&gn0, g, dn, reg); + ret = x64_rcg_make_node(&gn0, g, dn, reg); if (ret < 0) { scf_loge("\n"); return ret; @@ -256,7 +255,7 @@ static int _x64_rcg_make(scf_3ac_code_t* c, scf_graph_t* g, scf_dag_node_t* dn, return 0; } -static int _x64_rcg_make2(scf_3ac_code_t* c, scf_dag_node_t* dn, scf_register_t* reg, scf_x64_OpCode_t* OpCode) +static int x64_rcg_make2(scf_3ac_code_t* c, scf_dag_node_t* dn, scf_register_t* reg) { if (c->rcg) scf_graph_free(c->rcg); @@ -265,7 +264,7 @@ static int _x64_rcg_make2(scf_3ac_code_t* c, scf_dag_node_t* dn, scf_register_t* if (!c->rcg) return -ENOMEM; - return _x64_rcg_make(c, c->rcg, dn, reg, OpCode); + return x64_rcg_make(c, c->rcg, dn, reg); } static int _x64_rcg_call(scf_native_t* ctx, scf_3ac_code_t* c, scf_graph_t* g) @@ -328,7 +327,7 @@ static int _x64_rcg_call(scf_native_t* ctx, scf_3ac_code_t* c, scf_graph_t* g) r = NULL; gn = NULL; - ret = _x64_rcg_make_node(&gn, g, dn, r); + ret = x64_rcg_make_node(&gn, g, dn, r); if (ret < 0) { scf_loge("\n"); return ret; @@ -355,7 +354,7 @@ static int _x64_rcg_call(scf_native_t* ctx, scf_3ac_code_t* c, scf_graph_t* g) continue; gn = NULL; - ret = _x64_rcg_make_node(&gn, g, dn, dn->rabi2); + ret = x64_rcg_make_node(&gn, g, dn, dn->rabi2); if (ret < 0) { scf_loge("\n"); return ret; @@ -368,7 +367,7 @@ static int _x64_rcg_call(scf_native_t* ctx, scf_3ac_code_t* c, scf_graph_t* g) if (!dn_pf->var->const_literal_flag) { - ret = _x64_rcg_make_node(&gn_pf, g, dn_pf, NULL); + ret = x64_rcg_make_node(&gn_pf, g, dn_pf, NULL); if (ret < 0) { scf_loge("\n"); return ret; @@ -381,7 +380,7 @@ static int _x64_rcg_call(scf_native_t* ctx, scf_3ac_code_t* c, scf_graph_t* g) rabi = x64_find_register_type_id_bytes(0, x64_abi_regs[i], dn_pf->var->size); - ret = _x64_rcg_make_node(&gn_rabi, g, NULL, rabi); + ret = x64_rcg_make_node(&gn_rabi, g, NULL, rabi); if (ret < 0) { scf_loge("\n"); return ret; @@ -389,7 +388,7 @@ static int _x64_rcg_call(scf_native_t* ctx, scf_3ac_code_t* c, scf_graph_t* g) assert(gn_pf != gn_rabi); - ret = _x64_rcg_make_edge(gn_pf, gn_rabi); + ret = x64_rcg_make_edge(gn_pf, gn_rabi); if (ret < 0) return ret; } @@ -418,115 +417,115 @@ static int _x64_rcg_pointer_handler(scf_native_t* ctx, scf_3ac_code_t* c, scf_gr { scf_3ac_operand_t* dst = c->dsts->data[0]; - int ret = _x64_rcg_make2(c, dst->dag_node, NULL, NULL); + int ret = x64_rcg_make2(c, dst->dag_node, NULL); if (ret < 0) return ret; - return _x64_rcg_make(c, g, dst->dag_node, NULL, NULL); + return x64_rcg_make(c, g, dst->dag_node, NULL); } static int _x64_rcg_assign_pointer_handler(scf_native_t* ctx, scf_3ac_code_t* c, scf_graph_t* g) { - int ret = _x64_rcg_make2(c, NULL, NULL, NULL); + int ret = x64_rcg_make2(c, NULL, NULL); if (ret < 0) return ret; - return _x64_rcg_make(c, g, NULL, NULL, NULL); + return x64_rcg_make(c, g, NULL, NULL); } static int _x64_rcg_array_index_handler(scf_native_t* ctx, scf_3ac_code_t* c, scf_graph_t* g) { scf_3ac_operand_t* dst = c->dsts->data[0]; - int ret = _x64_rcg_make2(c, dst->dag_node, NULL, NULL); + int ret = x64_rcg_make2(c, dst->dag_node, NULL); if (ret < 0) return ret; - return _x64_rcg_make(c, g, dst->dag_node, NULL, NULL); + return x64_rcg_make(c, g, dst->dag_node, NULL); } static int _x64_rcg_assign_array_index_handler(scf_native_t* ctx, scf_3ac_code_t* c, scf_graph_t* g) { - int ret = _x64_rcg_make2(c, NULL, NULL, NULL); + int ret = x64_rcg_make2(c, NULL, NULL); if (ret < 0) return ret; - return _x64_rcg_make(c, g, NULL, NULL, NULL); + return x64_rcg_make(c, g, NULL, NULL); } static int _x64_rcg_bit_not_handler(scf_native_t* ctx, scf_3ac_code_t* c, scf_graph_t* g) { scf_3ac_operand_t* dst = c->dsts->data[0]; - int ret = _x64_rcg_make2(c, dst->dag_node, NULL, NULL); + int ret = x64_rcg_make2(c, dst->dag_node, NULL); if (ret < 0) return ret; - return _x64_rcg_make(c, g, dst->dag_node, NULL, NULL); + return x64_rcg_make(c, g, dst->dag_node, NULL); } static int _x64_rcg_logic_not_handler(scf_native_t* ctx, scf_3ac_code_t* c, scf_graph_t* g) { scf_3ac_operand_t* dst = c->dsts->data[0]; - int ret = _x64_rcg_make2(c, dst->dag_node, NULL, NULL); + int ret = x64_rcg_make2(c, dst->dag_node, NULL); if (ret < 0) return ret; - return _x64_rcg_make(c, g, dst->dag_node, NULL, NULL); + return x64_rcg_make(c, g, dst->dag_node, NULL); } static int _x64_rcg_neg_handler(scf_native_t* ctx, scf_3ac_code_t* c, scf_graph_t* g) { scf_3ac_operand_t* dst = c->dsts->data[0]; - int ret = _x64_rcg_make2(c, dst->dag_node, NULL, NULL); + int ret = x64_rcg_make2(c, dst->dag_node, NULL); if (ret < 0) return ret; - return _x64_rcg_make(c, g, dst->dag_node, NULL, NULL); + return x64_rcg_make(c, g, dst->dag_node, NULL); } static int _x64_rcg_dereference_handler(scf_native_t* ctx, scf_3ac_code_t* c, scf_graph_t* g) { scf_3ac_operand_t* dst = c->dsts->data[0]; - int ret = _x64_rcg_make2(c, dst->dag_node, NULL, NULL); + int ret = x64_rcg_make2(c, dst->dag_node, NULL); if (ret < 0) return ret; - return _x64_rcg_make(c, g, dst->dag_node, NULL, NULL); + return x64_rcg_make(c, g, dst->dag_node, NULL); } static int _x64_rcg_assign_dereference_handler(scf_native_t* ctx, scf_3ac_code_t* c, scf_graph_t* g) { - int ret = _x64_rcg_make2(c, NULL, NULL, NULL); + int ret = x64_rcg_make2(c, NULL, NULL); if (ret < 0) return ret; - return _x64_rcg_make(c, g, NULL, NULL, NULL); + return x64_rcg_make(c, g, NULL, NULL); } static int _x64_rcg_address_of_handler(scf_native_t* ctx, scf_3ac_code_t* c, scf_graph_t* g) { scf_3ac_operand_t* dst = c->dsts->data[0]; - int ret = _x64_rcg_make2(c, dst->dag_node, NULL, NULL); + int ret = x64_rcg_make2(c, dst->dag_node, NULL); if (ret < 0) return ret; - return _x64_rcg_make(c, g, dst->dag_node, NULL, NULL); + return x64_rcg_make(c, g, dst->dag_node, NULL); } static int _x64_rcg_cast_handler(scf_native_t* ctx, scf_3ac_code_t* c, scf_graph_t* g) { scf_3ac_operand_t* dst = c->dsts->data[0]; - int ret = _x64_rcg_make2(c, dst->dag_node, NULL, NULL); + int ret = x64_rcg_make2(c, dst->dag_node, NULL); if (ret < 0) return ret; - return _x64_rcg_make(c, g, dst->dag_node, NULL, NULL); + return x64_rcg_make(c, g, dst->dag_node, NULL); } static int _x64_rcg_mul_div_mod(scf_native_t* ctx, scf_3ac_code_t* c, scf_graph_t* g) @@ -548,7 +547,7 @@ static int _x64_rcg_mul_div_mod(scf_native_t* ctx, scf_3ac_code_t* c, scf_graph_ } if (scf_variable_float(src->dag_node->var)) - return _x64_rcg_make(c, g, dn, NULL, NULL); + return x64_rcg_make(c, g, dn, NULL); int size = x64_variable_size(src->dag_node->var); int ret = 0; @@ -567,12 +566,12 @@ static int _x64_rcg_mul_div_mod(scf_native_t* ctx, scf_3ac_code_t* c, scf_graph_ case SCF_OP_DIV: case SCF_OP_MUL_ASSIGN: case SCF_OP_DIV_ASSIGN: - ret = _x64_rcg_make(c, g, dst->dag_node, rl, NULL); + ret = x64_rcg_make(c, g, dst->dag_node, rl); break; case SCF_OP_MOD: case SCF_OP_MOD_ASSIGN: - ret = _x64_rcg_make(c, g, dst->dag_node, rh, NULL); + ret = x64_rcg_make(c, g, dst->dag_node, rh); break; default: @@ -582,11 +581,11 @@ static int _x64_rcg_mul_div_mod(scf_native_t* ctx, scf_3ac_code_t* c, scf_graph_ if (ret < 0) return ret; - ret = _x64_rcg_make(c, g, NULL, rl, NULL); + ret = x64_rcg_make(c, g, NULL, rl); if (ret < 0) return ret; - ret = _x64_rcg_make(c, g, NULL, rh, NULL); + ret = x64_rcg_make(c, g, NULL, rh); if (ret < 0) return ret; @@ -628,22 +627,22 @@ static int _x64_rcg_add_handler(scf_native_t* ctx, scf_3ac_code_t* c, scf_graph_ { scf_3ac_operand_t* dst = c->dsts->data[0]; - int ret = _x64_rcg_make2(c, dst->dag_node, NULL, NULL); + int ret = x64_rcg_make2(c, dst->dag_node, NULL); if (ret < 0) return ret; - return _x64_rcg_make(c, g, dst->dag_node, NULL, NULL); + return x64_rcg_make(c, g, dst->dag_node, NULL); } static int _x64_rcg_sub_handler(scf_native_t* ctx, scf_3ac_code_t* c, scf_graph_t* g) { scf_3ac_operand_t* dst = c->dsts->data[0]; - int ret = _x64_rcg_make2(c, dst->dag_node, NULL, NULL); + int ret = x64_rcg_make2(c, dst->dag_node, NULL); if (ret < 0) return ret; - return _x64_rcg_make(c, g, dst->dag_node, NULL, NULL); + return x64_rcg_make(c, g, dst->dag_node, NULL); } static int _x64_rcg_shift(scf_native_t* ctx, scf_3ac_code_t* c, scf_graph_t* g) @@ -655,7 +654,7 @@ static int _x64_rcg_shift(scf_native_t* ctx, scf_3ac_code_t* c, scf_graph_t* g) scf_3ac_operand_t* count = c->srcs->data[c->srcs->size - 1]; scf_graph_node_t* gn = NULL; scf_graph_node_t* gn_cl = NULL; - scf_register_t* cl = x64_find_register_type_id_bytes(0, SCF_X64_REG_CL, count->dag_node->var->size); + scf_register_t* cl = x64_find_register_type_id_bytes(0, SCF_X64_REG_CL, count->dag_node->var->size); if (!count || !count->dag_node) return -EINVAL; @@ -667,26 +666,26 @@ static int _x64_rcg_shift(scf_native_t* ctx, scf_3ac_code_t* c, scf_graph_t* g) } if (scf_variable_const(count->dag_node->var)) - return _x64_rcg_make(c, g, dn, NULL, NULL); + return x64_rcg_make(c, g, dn, NULL); - int ret = _x64_rcg_make_node(&gn, g, count->dag_node, cl); + int ret = x64_rcg_make_node(&gn, g, count->dag_node, cl); if (ret < 0) return ret; - ret = _x64_rcg_make(c, g, dn, NULL, NULL); + ret = x64_rcg_make(c, g, dn, NULL); if (ret < 0) return ret; - ret = _x64_rcg_make_node(&gn_cl, g, NULL, cl); + ret = x64_rcg_make_node(&gn_cl, g, NULL, cl); if (ret < 0) return ret; if (dn) { - ret = _x64_rcg_make_node(&gn, g, dn, NULL); + ret = x64_rcg_make_node(&gn, g, dn, NULL); if (ret < 0) return ret; - ret = _x64_rcg_make_edge(gn_cl, gn); + ret = x64_rcg_make_edge(gn_cl, gn); if (ret < 0) return ret; } @@ -696,11 +695,11 @@ static int _x64_rcg_shift(scf_native_t* ctx, scf_3ac_code_t* c, scf_graph_t* g) scf_3ac_operand_t* src = c->srcs->data[i]; scf_graph_node_t* gn_src = NULL; - ret = _x64_rcg_make_node(&gn_src, g, src->dag_node, NULL); + ret = x64_rcg_make_node(&gn_src, g, src->dag_node, NULL); if (ret < 0) return ret; - ret = _x64_rcg_make_edge(gn_cl, gn_src); + ret = x64_rcg_make_edge(gn_cl, gn_src); if (ret < 0) return ret; } @@ -738,49 +737,40 @@ static int _x64_rcg_bit_and_handler(scf_native_t* ctx, scf_3ac_code_t* c, scf_gr { scf_3ac_operand_t* dst = c->dsts->data[0]; - int ret = _x64_rcg_make2(c, dst->dag_node, NULL, NULL); + int ret = x64_rcg_make2(c, dst->dag_node, NULL); if (ret < 0) return ret; - return _x64_rcg_make(c, g, dst->dag_node, NULL, NULL); + return x64_rcg_make(c, g, dst->dag_node, NULL); } static int _x64_rcg_bit_or_handler(scf_native_t* ctx, scf_3ac_code_t* c, scf_graph_t* g) { scf_3ac_operand_t* dst = c->dsts->data[0]; - int ret = _x64_rcg_make2(c, dst->dag_node, NULL, NULL); + int ret = x64_rcg_make2(c, dst->dag_node, NULL); if (ret < 0) return ret; - return _x64_rcg_make(c, g, dst->dag_node, NULL, NULL); -} - -static int _x64_rcg_dump_handler(scf_native_t* ctx, scf_3ac_code_t* c, scf_graph_t* g) -{ - int ret = _x64_rcg_make2(c, NULL, NULL, NULL); - if (ret < 0) - return ret; - - return _x64_rcg_make(c, g, NULL, NULL, NULL); + return x64_rcg_make(c, g, dst->dag_node, NULL); } static int _x64_rcg_cmp_handler(scf_native_t* ctx, scf_3ac_code_t* c, scf_graph_t* g) { - int ret = _x64_rcg_make2(c, NULL, NULL, NULL); + int ret = x64_rcg_make2(c, NULL, NULL); if (ret < 0) return ret; - return _x64_rcg_make(c, g, NULL, NULL, NULL); + return x64_rcg_make(c, g, NULL, NULL); } static int _x64_rcg_teq_handler(scf_native_t* ctx, scf_3ac_code_t* c, scf_graph_t* g) { - int ret = _x64_rcg_make2(c, NULL, NULL, NULL); + int ret = x64_rcg_make2(c, NULL, NULL); if (ret < 0) return ret; - return _x64_rcg_make(c, g, NULL, NULL, NULL); + return x64_rcg_make(c, g, NULL, NULL); } #define X64_RCG_SET(setcc) \ @@ -788,10 +778,10 @@ static int _x64_rcg_##setcc##_handler(scf_native_t* ctx, scf_3ac_code_t* c, scf_ { \ scf_3ac_operand_t* dst = c->dsts->data[0]; \ \ - int ret = _x64_rcg_make2(c, dst->dag_node, NULL, NULL); \ + int ret = x64_rcg_make2(c, dst->dag_node, NULL); \ if (ret < 0) \ return ret; \ - return _x64_rcg_make(c, g, dst->dag_node, NULL, NULL); \ + return x64_rcg_make(c, g, dst->dag_node, NULL); \ } X64_RCG_SET(setz) X64_RCG_SET(setnz) @@ -805,10 +795,10 @@ static int _x64_rcg_##op##_handler(scf_native_t* ctx, scf_3ac_code_t* c, scf_gra { \ scf_3ac_operand_t* dst = c->dsts->data[0]; \ \ - int ret = _x64_rcg_make2(c, dst->dag_node, NULL, NULL); \ + int ret = x64_rcg_make2(c, dst->dag_node, NULL); \ if (ret < 0) \ return ret; \ - return _x64_rcg_make(c, g, dst->dag_node, NULL, NULL); \ + return x64_rcg_make(c, g, dst->dag_node, NULL); \ } X64_RCG_CMP(eq) X64_RCG_CMP(ne) @@ -821,33 +811,33 @@ static int _x64_rcg_assign_handler(scf_native_t* ctx, scf_3ac_code_t* c, scf_gra { scf_3ac_operand_t* dst = c->dsts->data[0]; - int ret = _x64_rcg_make2(c, dst->dag_node, NULL, NULL); + int ret = x64_rcg_make2(c, dst->dag_node, NULL); if (ret < 0) return ret; - return _x64_rcg_make(c, g, dst->dag_node, NULL, NULL); + return x64_rcg_make(c, g, dst->dag_node, NULL); } static int _x64_rcg_add_assign_handler(scf_native_t* ctx, scf_3ac_code_t* c, scf_graph_t* g) { scf_3ac_operand_t* dst = c->dsts->data[0]; - int ret = _x64_rcg_make2(c, dst->dag_node, NULL, NULL); + int ret = x64_rcg_make2(c, dst->dag_node, NULL); if (ret < 0) return ret; - return _x64_rcg_make(c, g, dst->dag_node, NULL, NULL); + return x64_rcg_make(c, g, dst->dag_node, NULL); } static int _x64_rcg_sub_assign_handler(scf_native_t* ctx, scf_3ac_code_t* c, scf_graph_t* g) { scf_3ac_operand_t* dst = c->dsts->data[0]; - int ret = _x64_rcg_make2(c, dst->dag_node, NULL, NULL); + int ret = x64_rcg_make2(c, dst->dag_node, NULL); if (ret < 0) return ret; - return _x64_rcg_make(c, g, dst->dag_node, NULL, NULL); + return x64_rcg_make(c, g, dst->dag_node, NULL); } static int _x64_rcg_mul_assign_handler(scf_native_t* ctx, scf_3ac_code_t* c, scf_graph_t* g) @@ -879,40 +869,22 @@ static int _x64_rcg_and_assign_handler(scf_native_t* ctx, scf_3ac_code_t* c, scf { scf_3ac_operand_t* dst = c->dsts->data[0]; - int ret = _x64_rcg_make2(c, dst->dag_node, NULL, NULL); + int ret = x64_rcg_make2(c, dst->dag_node, NULL); if (ret < 0) return ret; - return _x64_rcg_make(c, g, dst->dag_node, NULL, NULL); + return x64_rcg_make(c, g, dst->dag_node, NULL); } static int _x64_rcg_or_assign_handler(scf_native_t* ctx, scf_3ac_code_t* c, scf_graph_t* g) { scf_3ac_operand_t* dst = c->dsts->data[0]; - int ret = _x64_rcg_make2(c, dst->dag_node, NULL, NULL); - if (ret < 0) - return ret; - - return _x64_rcg_make(c, g, dst->dag_node, NULL, NULL); -} - -static int _x64_rcg_vla_alloc_handler(scf_native_t* ctx, scf_3ac_code_t* c, scf_graph_t* g) -{ - int ret = _x64_rcg_make2(c, NULL, NULL, NULL); + int ret = x64_rcg_make2(c, dst->dag_node, NULL); if (ret < 0) return ret; - return _x64_rcg_make(c, g, NULL, NULL, NULL); -} - -static int _x64_rcg_vla_free_handler(scf_native_t* ctx, scf_3ac_code_t* c, scf_graph_t* g) -{ - int ret = _x64_rcg_make2(c, NULL, NULL, NULL); - if (ret < 0) - return ret; - - return _x64_rcg_make(c, g, NULL, NULL, NULL); + return x64_rcg_make(c, g, dst->dag_node, NULL); } static int _x64_rcg_return_handler(scf_native_t* ctx, scf_3ac_code_t* c, scf_graph_t* g) @@ -924,11 +896,11 @@ static int _x64_rcg_return_handler(scf_native_t* ctx, scf_3ac_code_t* c, scf_gra scf_graph_node_t* gn; scf_dag_node_t* dn; - int ret = _x64_rcg_make2(c, NULL, NULL, NULL); + int ret = x64_rcg_make2(c, NULL, NULL); if (ret < 0) return ret; - ret = _x64_rcg_make(c, g, NULL, NULL, NULL); + ret = x64_rcg_make(c, g, NULL, NULL); if (ret < 0) return ret; @@ -954,7 +926,7 @@ static int _x64_rcg_return_handler(scf_native_t* ctx, scf_3ac_code_t* c, scf_gra } else r = x64_find_register_type_id_bytes(is_float, x64_abi_ret_regs[i], size); - ret = _x64_rcg_make_node(&gn, g, dn, r); + ret = x64_rcg_make_node(&gn, g, dn, r); if (ret < 0) return ret; } @@ -971,11 +943,11 @@ static int _x64_rcg_memset_handler(scf_native_t* ctx, scf_3ac_code_t* c, scf_gra scf_dag_node_t* dn; scf_register_t* r; - int ret = _x64_rcg_make2(c, NULL, NULL, NULL); + int ret = x64_rcg_make2(c, NULL, NULL); if (ret < 0) return ret; - ret = _x64_rcg_make(c, g, NULL, NULL, NULL); + ret = x64_rcg_make(c, g, NULL, NULL); if (ret < 0) return ret; @@ -1000,7 +972,7 @@ static int _x64_rcg_memset_handler(scf_native_t* ctx, scf_3ac_code_t* c, scf_gra else return -EINVAL; - ret = _x64_rcg_make_node(&gn, g, dn, r); + ret = x64_rcg_make_node(&gn, g, dn, r); if (ret < 0) return ret; } @@ -1033,17 +1005,30 @@ X64_RCG_JCC(jbe) static int _x64_rcg_save_handler(scf_native_t* ctx, scf_3ac_code_t* c, scf_graph_t* g) { - int ret = _x64_rcg_make2(c, NULL, NULL, NULL); + if (!c->srcs || c->srcs->size != 1) + return -EINVAL; + + scf_3ac_operand_t* src = c->srcs->data[0]; + scf_dag_node_t* dn = src->dag_node; + + int ret = x64_rcg_make2(c, dn, NULL); if (ret < 0) return ret; - return _x64_rcg_make(c, g, NULL, NULL, NULL); + return x64_rcg_make(c, g, dn, NULL); } static int _x64_rcg_load_handler(scf_native_t* ctx, scf_3ac_code_t* c, scf_graph_t* g) { - return 0; + if (!c->dsts || c->dsts->size != 1) + return -EINVAL; + + scf_3ac_operand_t* dst = c->dsts->data[0]; + scf_dag_node_t* dn = dst->dag_node; + + return x64_rcg_make2(c, dn, NULL); } + static int _x64_rcg_nop_handler(scf_native_t* ctx, scf_3ac_code_t* c, scf_graph_t* g) { return 0; @@ -1056,24 +1041,24 @@ static int _x64_rcg_end_handler(scf_native_t* ctx, scf_3ac_code_t* c, scf_graph_ #define X64_RCG_BINARY_ASSIGN(name) \ static int _x64_rcg_##name##_assign_dereference_handler(scf_native_t* ctx, scf_3ac_code_t* c, scf_graph_t* g) \ { \ - int ret = _x64_rcg_make2(c, NULL, NULL, NULL); \ + int ret = x64_rcg_make2(c, NULL, NULL); \ if (ret < 0) \ return ret; \ - return _x64_rcg_make(c, g, NULL, NULL, NULL); \ + return x64_rcg_make(c, g, NULL, NULL); \ } \ static int _x64_rcg_##name##_assign_array_index_handler(scf_native_t* ctx, scf_3ac_code_t* c, scf_graph_t* g) \ { \ - int ret = _x64_rcg_make2(c, NULL, NULL, NULL); \ + int ret = x64_rcg_make2(c, NULL, NULL); \ if (ret < 0) \ return ret; \ - return _x64_rcg_make(c, g, NULL, NULL, NULL); \ + return x64_rcg_make(c, g, NULL, NULL); \ } \ static int _x64_rcg_##name##_assign_pointer_handler(scf_native_t* ctx, scf_3ac_code_t* c, scf_graph_t* g) \ { \ - int ret = _x64_rcg_make2(c, NULL, NULL, NULL); \ + int ret = x64_rcg_make2(c, NULL, NULL); \ if (ret < 0) \ return ret; \ - return _x64_rcg_make(c, g, NULL, NULL, NULL); \ + return x64_rcg_make(c, g, NULL, NULL); \ } X64_RCG_BINARY_ASSIGN(add) @@ -1100,31 +1085,31 @@ X64_RCG_SHIFT_ASSIGN(shr) #define X64_RCG_UNARY_ASSIGN(name) \ static int _x64_rcg_##name##_handler(scf_native_t* ctx, scf_3ac_code_t* c, scf_graph_t* g) \ { \ - int ret = _x64_rcg_make2(c, NULL, NULL, NULL); \ + int ret = x64_rcg_make2(c, NULL, NULL); \ if (ret < 0) \ return ret; \ - return _x64_rcg_make(c, g, NULL, NULL, NULL); \ + return x64_rcg_make(c, g, NULL, NULL); \ } \ static int _x64_rcg_##name##_dereference_handler(scf_native_t* ctx, scf_3ac_code_t* c, scf_graph_t* g) \ { \ - int ret = _x64_rcg_make2(c, NULL, NULL, NULL); \ + int ret = x64_rcg_make2(c, NULL, NULL); \ if (ret < 0) \ return ret; \ - return _x64_rcg_make(c, g, NULL, NULL, NULL); \ + return x64_rcg_make(c, g, NULL, NULL); \ } \ static int _x64_rcg_##name##_array_index_handler(scf_native_t* ctx, scf_3ac_code_t* c, scf_graph_t* g) \ { \ - int ret = _x64_rcg_make2(c, NULL, NULL, NULL); \ + int ret = x64_rcg_make2(c, NULL, NULL); \ if (ret < 0) \ return ret; \ - return _x64_rcg_make(c, g, NULL, NULL, NULL); \ + return x64_rcg_make(c, g, NULL, NULL); \ } \ static int _x64_rcg_##name##_pointer_handler(scf_native_t* ctx, scf_3ac_code_t* c, scf_graph_t* g) \ { \ - int ret = _x64_rcg_make2(c, NULL, NULL, NULL); \ + int ret = x64_rcg_make2(c, NULL, NULL); \ if (ret < 0) \ return ret; \ - return _x64_rcg_make(c, g, NULL, NULL, NULL); \ + return x64_rcg_make(c, g, NULL, NULL); \ } X64_RCG_UNARY_ASSIGN(inc) X64_RCG_UNARY_ASSIGN(dec) @@ -1134,37 +1119,37 @@ static int _x64_rcg_##name##_handler(scf_native_t* ctx, scf_3ac_code_t* c, scf_g { \ scf_3ac_operand_t* dst = c->dsts->data[0]; \ \ - int ret = _x64_rcg_make2(c, dst->dag_node, NULL, NULL); \ + int ret = x64_rcg_make2(c, dst->dag_node, NULL); \ if (ret < 0) \ return ret; \ - return _x64_rcg_make(c, g, dst->dag_node, NULL, NULL); \ + return x64_rcg_make(c, g, dst->dag_node, NULL); \ } \ static int _x64_rcg_##name##_dereference_handler(scf_native_t* ctx, scf_3ac_code_t* c, scf_graph_t* g) \ { \ scf_3ac_operand_t* dst = c->dsts->data[0]; \ \ - int ret = _x64_rcg_make2(c, dst->dag_node, NULL, NULL); \ + int ret = x64_rcg_make2(c, dst->dag_node, NULL); \ if (ret < 0) \ return ret; \ - return _x64_rcg_make(c, g, dst->dag_node, NULL, NULL); \ + return x64_rcg_make(c, g, dst->dag_node, NULL); \ } \ static int _x64_rcg_##name##_array_index_handler(scf_native_t* ctx, scf_3ac_code_t* c, scf_graph_t* g) \ { \ scf_3ac_operand_t* dst = c->dsts->data[0]; \ \ - int ret = _x64_rcg_make2(c, dst->dag_node, NULL, NULL); \ + int ret = x64_rcg_make2(c, dst->dag_node, NULL); \ if (ret < 0) \ return ret; \ - return _x64_rcg_make(c, g, dst->dag_node, NULL, NULL); \ + return x64_rcg_make(c, g, dst->dag_node, NULL); \ } \ static int _x64_rcg_##name##_pointer_handler(scf_native_t* ctx, scf_3ac_code_t* c, scf_graph_t* g) \ { \ scf_3ac_operand_t* dst = c->dsts->data[0]; \ \ - int ret = _x64_rcg_make2(c, dst->dag_node, NULL, NULL); \ + int ret = x64_rcg_make2(c, dst->dag_node, NULL); \ if (ret < 0) \ return ret; \ - return _x64_rcg_make(c, g, dst->dag_node, NULL, NULL); \ + return x64_rcg_make(c, g, dst->dag_node, NULL); \ } X64_RCG_UNARY_POST_ASSIGN(inc_post) X64_RCG_UNARY_POST_ASSIGN(dec_post) @@ -1173,20 +1158,20 @@ static int _x64_rcg_address_of_array_index_handler(scf_native_t* ctx, scf_3ac_co { scf_3ac_operand_t* dst = c->dsts->data[0]; - int ret = _x64_rcg_make2(c, dst->dag_node, NULL, NULL); + int ret = x64_rcg_make2(c, dst->dag_node, NULL); if (ret < 0) return ret; - return _x64_rcg_make(c, g, dst->dag_node, NULL, NULL); + return x64_rcg_make(c, g, dst->dag_node, NULL); } static int _x64_rcg_address_of_pointer_handler(scf_native_t* ctx, scf_3ac_code_t* c, scf_graph_t* g) { scf_3ac_operand_t* dst = c->dsts->data[0]; - int ret = _x64_rcg_make2(c, dst->dag_node, NULL, NULL); + int ret = x64_rcg_make2(c, dst->dag_node, NULL); if (ret < 0) return ret; - return _x64_rcg_make(c, g, dst->dag_node, NULL, NULL); + return x64_rcg_make(c, g, dst->dag_node, NULL); } static int _x64_rcg_push_rax_handler(scf_native_t* ctx, scf_3ac_code_t* c, scf_graph_t* g) @@ -1200,28 +1185,28 @@ static int _x64_rcg_pop_rax_handler(scf_native_t* ctx, scf_3ac_code_t* c, scf_gr static int _x64_rcg_va_start_handler(scf_native_t* ctx, scf_3ac_code_t* c, scf_graph_t* g) { - int ret = _x64_rcg_make2(c, NULL, NULL, NULL); + int ret = x64_rcg_make2(c, NULL, NULL); if (ret < 0) return ret; - return _x64_rcg_make(c, g, NULL, NULL, NULL); + return x64_rcg_make(c, g, NULL, NULL); } static int _x64_rcg_va_end_handler(scf_native_t* ctx, scf_3ac_code_t* c, scf_graph_t* g) { - int ret = _x64_rcg_make2(c, NULL, NULL, NULL); + int ret = x64_rcg_make2(c, NULL, NULL); if (ret < 0) return ret; - return _x64_rcg_make(c, g, NULL, NULL, NULL); + return x64_rcg_make(c, g, NULL, NULL); } static int _x64_rcg_va_arg_handler(scf_native_t* ctx, scf_3ac_code_t* c, scf_graph_t* g) { scf_3ac_operand_t* dst = c->dsts->data[0]; - int ret = _x64_rcg_make2(c, dst->dag_node, NULL, NULL); + int ret = x64_rcg_make2(c, dst->dag_node, NULL); if (ret < 0) return ret; - return _x64_rcg_make(c, g, dst->dag_node, NULL, NULL); + return x64_rcg_make(c, g, dst->dag_node, NULL); } static x64_rcg_handler_pt x64_rcg_handlers[SCF_N_3AC_OPS] = @@ -1282,14 +1267,10 @@ static x64_rcg_handler_pt x64_rcg_handlers[SCF_N_3AC_OPS] = [SCF_OP_AND_ASSIGN ] = _x64_rcg_and_assign_handler, [SCF_OP_OR_ASSIGN ] = _x64_rcg_or_assign_handler, - [SCF_OP_VLA_ALLOC ] = _x64_rcg_vla_alloc_handler, - [SCF_OP_VLA_FREE ] = _x64_rcg_vla_free_handler, - [SCF_OP_RETURN ] = _x64_rcg_return_handler, [SCF_OP_3AC_CMP ] = _x64_rcg_cmp_handler, [SCF_OP_3AC_TEQ ] = _x64_rcg_teq_handler, - [SCF_OP_3AC_DUMP ] = _x64_rcg_dump_handler, [SCF_OP_3AC_SETZ ] = _x64_rcg_setz_handler, [SCF_OP_3AC_SETNZ ] = _x64_rcg_setnz_handler, diff --git a/native/x64/scf_x64_reg.c b/native/x64/scf_x64_reg.c index d017fab..5988fd3 100644 --- a/native/x64/scf_x64_reg.c +++ b/native/x64/scf_x64_reg.c @@ -413,7 +413,7 @@ int x64_save_var2(scf_dag_node_t* dn, scf_register_t* r, scf_3ac_code_t* c, scf_ mov = x64_find_OpCode(SCF_X64_MOV, r->bytes, r->bytes, SCF_X64_G2E); } - inst = x64_make_inst_G2M(&rela, mov, v, NULL, r); + inst = x64_make_inst_G2M(&rela, mov, v, NULL, r, c, f); X64_INST_ADD_CHECK(c, inst, rela); X64_RELA_ADD_CHECK(f->data_relas, rela, c, v, NULL); @@ -570,7 +570,7 @@ static scf_register_t* _x64_reg_cached_min_vars(scf_register_t** regs, int nb_re return r_min; } -scf_register_t* x64_select_overflowed_reg(scf_dag_node_t* dn, scf_3ac_code_t* c) +scf_register_t* x64_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; @@ -578,16 +578,20 @@ scf_register_t* x64_select_overflowed_reg(scf_dag_node_t* dn, scf_3ac_code_t* c) scf_register_t* free_regs[sizeof(x64_registers) / sizeof(x64_registers[0])]; int nb_free_regs = 0; - int is_float = scf_variable_float(dn->var); - int bytes = x64_variable_size(dn->var); + int bytes = 8; int ret; int i; int j; - scf_logd("bytes: %d\n", bytes); - assert(c->rcg); + if (dn) { + is_float = scf_variable_float(dn->var); + bytes = x64_variable_size (dn->var); + } + + scf_logd("bytes: %d\n", bytes); + ret = x64_rcg_find_node(&gn, c->rcg, dn, NULL); if (ret < 0) neighbors = c->rcg->nodes; @@ -694,6 +698,37 @@ scf_register_t* x64_select_overflowed_reg(scf_dag_node_t* dn, scf_3ac_code_t* c) return NULL; } +int x64_select_free_reg(scf_register_t** preg, scf_3ac_code_t* c, scf_function_t* f, int is_float) +{ + scf_register_t* r; + + r = x64_select_overflowed_reg(NULL, c, is_float); + if (!r) { + scf_loge("\n"); + return -1; + } + + int ret = x64_overflow_reg(r, c, f); + if (ret < 0) { + scf_loge("overflow reg failed\n"); + return ret; + } + assert(0 == r->dag_nodes->size); + + r = x64_find_register_type_id_bytes(is_float, r->id, 8); + + assert(0 == r->dag_nodes->size); + + ret = x64_rcg_make(c, c->rcg, NULL, r); + if (ret < 0) + return ret; + + r->used = 1; + + *preg = r; + return 0; +} + int x64_load_const(scf_register_t* r, scf_dag_node_t* dn, scf_3ac_code_t* c, scf_function_t* f) { scf_instruction_t* inst; @@ -717,16 +752,18 @@ int x64_load_const(scf_register_t* r, scf_dag_node_t* dn, scf_3ac_code_t* c, scf lea = x64_find_OpCode(SCF_X64_LEA, size, size, SCF_X64_E2G); - inst = x64_make_inst_M2G(&rela, lea, r, NULL, v); + inst = x64_make_inst_M2G(&rela, lea, r, NULL, v, NULL, NULL); X64_INST_ADD_CHECK(c, inst, rela); X64_RELA_ADD_CHECK(f->data_relas, rela, c, v, NULL); } else if (v->nb_dimentions > 0) { assert(v->const_literal_flag); + assert(!v->extern_flag || !f->pic_flag); + lea = x64_find_OpCode(SCF_X64_LEA, size, size, SCF_X64_E2G); - inst = x64_make_inst_M2G(&rela, lea, r, NULL, v); + inst = x64_make_inst_M2G(&rela, lea, r, NULL, v, NULL, NULL); X64_INST_ADD_CHECK(c, inst, rela); X64_RELA_ADD_CHECK(f->data_relas, rela, c, v, NULL); @@ -739,7 +776,7 @@ int x64_load_const(scf_register_t* r, scf_dag_node_t* dn, scf_3ac_code_t* c, scf v->tmp_flag = 0; lea = x64_find_OpCode(SCF_X64_LEA, size, size, SCF_X64_E2G); - inst = x64_make_inst_M2G(&rela, lea, r, NULL, v); + inst = x64_make_inst_M2G(&rela, lea, r, NULL, v, NULL, NULL); X64_INST_ADD_CHECK(c, inst, rela); X64_RELA_ADD_CHECK(f->text_relas, rela, c, NULL, v->func_ptr); } else { @@ -825,7 +862,7 @@ int x64_load_reg(scf_register_t* r, scf_dag_node_t* dn, scf_3ac_code_t* c, scf_f return -EINVAL; } - inst = x64_make_inst_M2G(&rela, mov, r, NULL, dn->var); + inst = x64_make_inst_M2G(&rela, mov, r, NULL, dn->var, c, f); X64_INST_ADD_CHECK(c, inst, rela); X64_RELA_ADD_CHECK(f->data_relas, rela, c, dn->var, NULL); @@ -854,7 +891,7 @@ int x64_select_reg(scf_register_t** preg, scf_dag_node_t* dn, scf_3ac_code_t* c, } #endif } else { - r = x64_select_overflowed_reg(dn, c); + r = x64_select_overflowed_reg(dn, c, is_float); if (!r) { scf_loge("\n"); return -1; @@ -991,7 +1028,7 @@ int x64_array_index_reg(x64_sib_t* sib, scf_dag_node_t* base, scf_dag_node_t* in int32_t disp = 0; - if ((vb->nb_pointers > 0 && 0 == vb->nb_dimentions) || vb->vla_flag) { + if (vb->nb_pointers > 0 && 0 == vb->nb_dimentions) { ret = x64_select_reg(&rb, base, c, f, 1); if (ret < 0) { diff --git a/native/x64/scf_x64_reg.h b/native/x64/scf_x64_reg.h index 23bf2d1..346a98a 100644 --- a/native/x64/scf_x64_reg.h +++ b/native/x64/scf_x64_reg.h @@ -101,7 +101,7 @@ scf_vector_t* x64_register_colors(); scf_register_t* x64_find_abi_register(int index, int bytes); -scf_register_t* x64_select_overflowed_reg(scf_dag_node_t* dn, scf_3ac_code_t* c); +scf_register_t* x64_select_overflowed_reg(scf_dag_node_t* dn, scf_3ac_code_t* c, int is_float); int x64_reg_cached_vars(scf_register_t* r); @@ -127,7 +127,8 @@ int x64_reg_used (scf_register_t* r, scf_dag_node_t* dn); int x64_overflow_reg (scf_register_t* r, scf_3ac_code_t* c, scf_function_t* f); int x64_overflow_reg2(scf_register_t* r, scf_dag_node_t* dn, scf_3ac_code_t* c, scf_function_t* f); -int x64_select_reg(scf_register_t** preg, scf_dag_node_t* dn, scf_3ac_code_t* c, scf_function_t* f, int load_flag); +int x64_select_free_reg(scf_register_t** preg, scf_3ac_code_t* c, scf_function_t* f, int is_float); +int x64_select_reg (scf_register_t** preg, scf_dag_node_t* dn, scf_3ac_code_t* c, scf_function_t* f, int load_flag); int x64_dereference_reg(x64_sib_t* sib, scf_dag_node_t* base, scf_dag_node_t* member, scf_3ac_code_t* c, scf_function_t* f); diff --git a/parse/Makefile b/parse/Makefile index 1f588d0..8cba095 100644 --- a/parse/Makefile +++ b/parse/Makefile @@ -123,7 +123,6 @@ CFILES += ../core/scf_optimizer_dominators_reverse.c CFILES += ../core/scf_optimizer_basic_block.c CFILES += ../core/scf_optimizer_const_teq.c CFILES += ../core/scf_optimizer_loop.c -CFILES += ../core/scf_optimizer_vla.c CFILES += ../core/scf_optimizer_group.c CFILES += ../core/scf_optimizer_generate_loads_saves.c diff --git a/parse/main.c b/parse/main.c index 041367f..e2f46b1 100644 --- a/parse/main.c +++ b/parse/main.c @@ -45,15 +45,18 @@ static char* __arm32_sofiles[] = void usage(char* path) { - fprintf(stderr, "Usage: %s [-std=..] [-c] [-p/-t] [-d] [-a arch] [-s sysroot] [-Dmacro / -D macro] [-Iinclude / -I include] [-lsofile / -l sofile] [-Lsopath / -L sopath] [-o out] src0 [src1]\n\n", path); + fprintf(stderr, "Usage: %s [-std=..] [-fpic / -fPIC] [-c] [-p/-t] [-shared] [-a arch] [-s sysroot] [-Dmacro / -D macro] [-Iinclude / -I include] [-lsofile / -l sofile] [-Lsopath / -L sopath] [-o out] src0 [src1]\n\n", path); + fprintf(stderr, "-std: c89 or c99 version\n"); + fprintf(stderr, "-fpic: PIC, position independent code\n"); + fprintf(stderr, "-shared: output dynamic library .so\n\n"); + fprintf(stderr, "-c: only compile, not link\n"); fprintf(stderr, "-p: only parse, not compile\n"); fprintf(stderr, "-t: only 3ac code, not compile\n\n"); fprintf(stderr, "-a: select cpu arch (x64, arm64, naja, or eda), default is x64\n"); - fprintf(stderr, "-s: sysroot dir, default is '../lib'\n"); - fprintf(stderr, "-d: output dynamic library .so\n\n"); + fprintf(stderr, "-s: sysroot dir, default is '../sysroot'\n\n"); fprintf(stderr, "-D: define a macro\n"); fprintf(stderr, "-I: include paths for .h file\n"); @@ -309,8 +312,8 @@ int main(int argc, char* argv[]) goto error; } - int obj_size = objs->size; - int so_size = sofiles->size; + int n_objs = objs->size; + int n_sofiles = sofiles->size; char* sysroot = "../sysroot"; char* arch = "x64"; @@ -319,6 +322,7 @@ int main(int argc, char* argv[]) int _3ac = 0; int _parse = 0; int dyn = 0; + int pic = 0; int c_version = SCF_C99; int i; @@ -329,6 +333,8 @@ int main(int argc, char* argv[]) goto error; } + int n_srcs = srcs->size; + for (i = 1; i < argc; i++) { if ('-' == argv[i][0]) { @@ -338,6 +344,12 @@ int main(int argc, char* argv[]) continue; } + if ('f' == argv[i][1]) { + if (!strcmp(argv[i] + 1, "fpic") || !strcmp(argv[i] + 1, "fPIC")) + pic = 1; + continue; + } + if ('p' == argv[i][1]) { link = 0; _3ac = 0; @@ -352,14 +364,6 @@ int main(int argc, char* argv[]) continue; } - if ('d' == argv[i][1]) { - dyn = 1; - link = 1; - _3ac = 0; - _parse = 0; - continue; - } - if ('a' == argv[i][1]) { if (++i >= argc || '-' == argv[i][0]) { @@ -387,7 +391,13 @@ int main(int argc, char* argv[]) || !strcmp(std, "ansi")) c_version = SCF_C89; - scf_logi("%s, c_version: %d\n", argv[i], c_version); + continue; + + } else if (!strcmp(argv[i] + 1, "shared")) { + dyn = 1; + link = 1; + _3ac = 0; + _parse = 0; continue; } @@ -528,7 +538,7 @@ int main(int argc, char* argv[]) exec = out; } - if (srcs->size > 0) { + if (srcs->size > n_srcs) { scf_parse_t* parse = NULL; ret = scf_parse_open(&parse, inc_paths, c_version); @@ -572,7 +582,7 @@ int main(int argc, char* argv[]) } if (!_parse) { - ret = scf_parse_compile(parse, arch, _3ac); + ret = scf_parse_compile(parse, arch, _3ac, pic); if (ret < 0) { scf_loge("\n"); goto error; @@ -589,8 +599,8 @@ int main(int argc, char* argv[]) parse = NULL; } - obj_size = objs->size; - so_size = sofiles->size; + n_objs = objs->size; + n_sofiles = sofiles->size; if (link) { ret = add_so_files(sofiles, lib_paths, lib_files); @@ -619,7 +629,7 @@ int main(int argc, char* argv[]) else MAIN_ADD_FILES(__objs, __sofiles, "x64"); - if (srcs->size > 0) { + if (srcs->size > n_srcs) { ret = scf_vector_add(objs, obj); if (ret < 0) goto error; @@ -653,8 +663,8 @@ error: scf_vector_free(srcs); if (sofiles) { - for (i = so_size; i < sofiles->size; i++) { - char* file = sofiles->data[i]; + for (i = n_sofiles; i < sofiles->size; i++) { + char* file = sofiles->data[i]; scf_logd("i: %d, file: %p, %s\n", i, file, file); @@ -665,8 +675,8 @@ error: } if (objs) { - for (i = obj_size; i < objs->size - 1; i++) { - char* file = objs->data[i]; + for (i = n_objs; i < objs->size - 1; i++) { + char* file = objs->data[i]; free(file); } diff --git a/parse/scf_dfa_container.c b/parse/scf_dfa_container.c index 03d1bbb..a9c4c1e 100644 --- a/parse/scf_dfa_container.c +++ b/parse/scf_dfa_container.c @@ -166,7 +166,7 @@ static int _container_action_rp(scf_dfa_t* dfa, scf_vector_t* words, void* data) scf_stack_t* s = d->module_datas[dfa_module_container.index]; dfa_container_data_t* cd = scf_stack_top(s); - if (d->current_va_arg) + if (d->current_va_arg || d->current_va_copy) return SCF_DFA_NEXT_SYNTAX; if (!cd) { diff --git a/parse/scf_dfa_expr.c b/parse/scf_dfa_expr.c index 47b0772..49a2187 100644 --- a/parse/scf_dfa_expr.c +++ b/parse/scf_dfa_expr.c @@ -413,10 +413,8 @@ static int _expr_action_rp_cast(scf_dfa_t* dfa, scf_vector_t* words, void* data) return SCF_DFA_NEXT_SYNTAX; } - if (d->current_va_arg) { - scf_logw("SCF_DFA_NEXT_SYNTAX\n"); + if (d->current_va_arg || d->current_va_copy) return SCF_DFA_NEXT_SYNTAX; - } scf_variable_t* var = NULL; scf_node_t* node_var = NULL; @@ -904,6 +902,7 @@ static int _dfa_init_syntax_expr(scf_dfa_t* dfa) SCF_DFA_GET_MODULE_NODE(dfa, type, star, star); SCF_DFA_GET_MODULE_NODE(dfa, va_arg, arg, va_arg); + SCF_DFA_GET_MODULE_NODE(dfa, va_arg, copy, va_copy); SCF_DFA_GET_MODULE_NODE(dfa, va_arg, rp, va_rp); SCF_DFA_GET_MODULE_NODE(dfa, container, container, container); @@ -941,6 +940,9 @@ static int _dfa_init_syntax_expr(scf_dfa_t* dfa) scf_dfa_node_add_child(va_rp, comma); scf_dfa_node_add_child(va_rp, semicolon); + // va_copy(dst, src) + scf_dfa_node_add_child(expr, va_copy); + // sizeof() scf_dfa_node_add_child(expr, _sizeof); scf_dfa_node_add_child(sizeof_rp, rp); diff --git a/parse/scf_dfa_identity.c b/parse/scf_dfa_identity.c index 01d08bf..48d9ae9 100644 --- a/parse/scf_dfa_identity.c +++ b/parse/scf_dfa_identity.c @@ -22,8 +22,11 @@ static int _identity_action_identity(scf_dfa_t* dfa, scf_vector_t* words, void* } id->identity = w; - id->const_flag = d->const_flag; - d ->const_flag = 0; + id->const_flag = d->const_flag; + id->extern_flag = d->extern_flag; + + d->const_flag = 0; + d->extern_flag = 0; return SCF_DFA_NEXT_WORD; } diff --git a/parse/scf_dfa_sizeof.c b/parse/scf_dfa_sizeof.c index aec0be7..bdfb92e 100644 --- a/parse/scf_dfa_sizeof.c +++ b/parse/scf_dfa_sizeof.c @@ -82,7 +82,7 @@ static int _sizeof_action_rp(scf_dfa_t* dfa, scf_vector_t* words, void* data) scf_stack_t* s = d->module_datas[dfa_module_sizeof.index]; dfa_sizeof_data_t* sd = scf_stack_top(s); - if (d->current_va_arg) + if (d->current_va_arg || d->current_va_copy) return SCF_DFA_NEXT_SYNTAX; if (!sd) { diff --git a/parse/scf_dfa_util.h b/parse/scf_dfa_util.h index b38ea2e..5e56969 100644 --- a/parse/scf_dfa_util.h +++ b/parse/scf_dfa_util.h @@ -228,6 +228,13 @@ static inline int scf_dfa_is_va_arg(scf_dfa_t* dfa, void* word) return SCF_LEX_WORD_KEY_VA_ARG == w->type; } +static inline int scf_dfa_is_va_copy(scf_dfa_t* dfa, void* word) +{ + scf_lex_word_t* w = word; + + return SCF_LEX_WORD_KEY_VA_COPY == w->type; +} + static inline int scf_dfa_is_va_end(scf_dfa_t* dfa, void* word) { scf_lex_word_t* w = word; diff --git a/parse/scf_dfa_va_arg.c b/parse/scf_dfa_va_arg.c index 918690c..06e718a 100644 --- a/parse/scf_dfa_va_arg.c +++ b/parse/scf_dfa_va_arg.c @@ -31,6 +31,14 @@ static int _va_arg_action_start(scf_dfa_t* dfa, scf_vector_t* words, void* data) return SCF_DFA_NEXT_WORD; } +static int _va_arg_action_copy(scf_dfa_t* dfa, scf_vector_t* words, void* data) +{ + scf_lex_word_t* w = words->data[words->size - 1]; + + scf_loge("%s:%d:%d, NOT support 'va_copy'\n", w->file->data, w->line, w->pos); + return SCF_DFA_ERROR; +} + static int _va_arg_action_arg(scf_dfa_t* dfa, scf_vector_t* words, void* data) { scf_parse_t* parse = dfa->priv; @@ -114,7 +122,7 @@ static int _va_arg_action_ap(scf_dfa_t* dfa, scf_vector_t* words, void* data) return SCF_DFA_ERROR; } - if (scf_ast_find_type(&t, parse->ast, "va_list") < 0) { + if (scf_ast_find_type(&t, parse->ast, "__builtin_va_list") < 0) { scf_loge("type 'va_list' not found, line: %d\n", w->line); return SCF_DFA_ERROR; } @@ -135,6 +143,9 @@ static int _va_arg_action_ap(scf_dfa_t* dfa, scf_vector_t* words, void* data) else if (d->current_va_arg) scf_node_add_child(d->current_va_arg, node); + else if (d->current_va_copy) + scf_node_add_child(d->current_va_copy, node); + else if (d->current_va_end) scf_node_add_child(d->current_va_end, node); else { @@ -242,7 +253,6 @@ static int _va_arg_action_rp(scf_dfa_t* dfa, scf_vector_t* words, void* data) } if (!id->type) { - if (_type_find_type(dfa, id) < 0) { scf_loge("\n"); return SCF_DFA_ERROR; @@ -264,6 +274,7 @@ static int _va_arg_action_rp(scf_dfa_t* dfa, scf_vector_t* words, void* data) d->current_va_start = NULL; d->current_va_arg = NULL; + d->current_va_copy = NULL; d->current_va_end = NULL; return SCF_DFA_NEXT_WORD; @@ -271,6 +282,7 @@ static int _va_arg_action_rp(scf_dfa_t* dfa, scf_vector_t* words, void* data) d->current_va_start = NULL; d->current_va_arg = NULL; + d->current_va_copy = NULL; d->current_va_end = NULL; return SCF_DFA_SWITCH_TO; @@ -288,6 +300,7 @@ static int _dfa_init_module_va_arg(scf_dfa_t* dfa) SCF_DFA_MODULE_NODE(dfa, va_arg, start, scf_dfa_is_va_start, _va_arg_action_start); SCF_DFA_MODULE_NODE(dfa, va_arg, arg, scf_dfa_is_va_arg, _va_arg_action_arg); + SCF_DFA_MODULE_NODE(dfa, va_arg, copy, scf_dfa_is_va_copy, _va_arg_action_copy); SCF_DFA_MODULE_NODE(dfa, va_arg, end, scf_dfa_is_va_end, _va_arg_action_end); SCF_DFA_MODULE_NODE(dfa, va_arg, ap, scf_dfa_is_identity, _va_arg_action_ap); @@ -313,6 +326,7 @@ static int _dfa_init_syntax_va_arg(scf_dfa_t* dfa) SCF_DFA_GET_MODULE_NODE(dfa, va_arg, start, start); SCF_DFA_GET_MODULE_NODE(dfa, va_arg, arg, arg); + SCF_DFA_GET_MODULE_NODE(dfa, va_arg, copy, copy); SCF_DFA_GET_MODULE_NODE(dfa, va_arg, end, end); SCF_DFA_GET_MODULE_NODE(dfa, va_arg, ap, ap); @@ -326,6 +340,7 @@ static int _dfa_init_syntax_va_arg(scf_dfa_t* dfa) SCF_DFA_GET_MODULE_NODE(dfa, type, star, star); SCF_DFA_GET_MODULE_NODE(dfa, identity, identity, identity); + // va_start(ap, fmt) scf_dfa_node_add_child(start, lp); scf_dfa_node_add_child(lp, ap); scf_dfa_node_add_child(ap, comma); @@ -333,9 +348,15 @@ static int _dfa_init_syntax_va_arg(scf_dfa_t* dfa) scf_dfa_node_add_child(fmt, rp); scf_dfa_node_add_child(rp, semicolon); + // va_copy(ap2, ap) + scf_dfa_node_add_child(copy, lp); + scf_dfa_node_add_child(comma, ap); + + // va_end(ap) scf_dfa_node_add_child(end, lp); scf_dfa_node_add_child(ap, rp); + // va_arg(ap, type) scf_dfa_node_add_child(arg, lp); scf_dfa_node_add_child(ap, type); diff --git a/parse/scf_dfa_var.c b/parse/scf_dfa_var.c index 8a8a948..8e8c083 100644 --- a/parse/scf_dfa_var.c +++ b/parse/scf_dfa_var.c @@ -164,7 +164,7 @@ static int _var_add_var(scf_dfa_t* dfa, dfa_data_t* d) for (i = 0; i < id0->type_def->nb_dimentions; i++) { dim = &id0->type_def->dimentions[i]; - scf_variable_add_array_dimention(v, dim->num, NULL); + scf_variable_add_array_dimention(v, dim->num); } v->const_literal_flag = id0->type_def->nb_dimentions > 0; @@ -248,239 +248,6 @@ static int _var_init_expr(scf_dfa_t* dfa, dfa_data_t* d, scf_vector_t* words, in return 0; } -static int _var_add_vla(scf_ast_t* ast, scf_variable_t* vla) -{ - scf_function_t* f = NULL; - scf_expr_t* e = NULL; - scf_expr_t* e2 = NULL; - scf_node_t* mul = NULL; - - if (scf_ast_find_function(&f, ast, "printf") < 0 || !f) { - scf_loge("printf() NOT found, which used to print error message when the variable length of array '%s' <= 0, file: %s, line: %d\n", - vla->w->text->data, vla->w->file->data, vla->w->line); - return SCF_DFA_ERROR; - } - - int size = vla->data_size; - int i; - - for (i = 0; i < vla->nb_dimentions; i++) { - - if (vla->dimentions[i].num > 0) { - size *= vla->dimentions[i].num; - continue; - } - - if (0 == vla->dimentions[i].num) { - scf_loge("\n"); - - scf_expr_free(e); - return SCF_DFA_ERROR; - } - - if (!vla->dimentions[i].vla) { - scf_loge("\n"); - - scf_expr_free(e); - return SCF_DFA_ERROR; - } - - if (!e) { - e = scf_expr_clone(vla->dimentions[i].vla); - if (!e) - return -ENOMEM; - continue; - } - - e2 = scf_expr_clone(vla->dimentions[i].vla); - if (!e2) { - scf_expr_free(e); - return -ENOMEM; - } - - mul = scf_node_alloc(vla->w, SCF_OP_MUL, NULL); - if (!mul) { - scf_expr_free(e2); - scf_expr_free(e); - return -ENOMEM; - } - - int ret = scf_expr_add_node(e, mul); - if (ret < 0) { - scf_expr_free(mul); - scf_expr_free(e2); - scf_expr_free(e); - return ret; - } - - ret = scf_expr_add_node(e, e2); - if (ret < 0) { - scf_expr_free(e2); - scf_expr_free(e); - return ret; - } - } - - assert(e); - - scf_variable_t* v; - scf_type_t* t; - scf_node_t* node; - - if (size > 1) { - mul = scf_node_alloc(vla->w, SCF_OP_MUL, NULL); - if (!mul) { - scf_expr_free(e); - return -ENOMEM; - } - - int ret = scf_expr_add_node(e, mul); - if (ret < 0) { - scf_expr_free(mul); - scf_expr_free(e); - return ret; - } - - t = scf_block_find_type_type(ast->current_block, SCF_VAR_INT); - v = SCF_VAR_ALLOC_BY_TYPE(vla->w, t, 1, 0, NULL); - if (!v) { - scf_expr_free(e); - return SCF_DFA_ERROR; - } - v->data.i64 = size; - v->global_flag = 1; - v->const_literal_flag = 1; - - node = scf_node_alloc(NULL, v->type, v); - scf_variable_free(v); - v = NULL; - if (!node) { - scf_expr_free(e); - return SCF_DFA_ERROR; - } - - ret = scf_expr_add_node(e, node); - if (ret < 0) { - scf_node_free(node); - scf_expr_free(e); - return ret; - } - } - - scf_node_t* assign; - scf_node_t* len; - scf_node_t* alloc; - - // len = e - assign = scf_node_alloc(vla->w, SCF_OP_ASSIGN, NULL); - if (!assign) { - scf_expr_free(e); - return SCF_DFA_ERROR; - } - - scf_node_add_child(assign, e->nodes[0]); - e->nodes[0] = assign; - assign->parent = e; - - scf_node_add_child((scf_node_t*)ast->current_block, e); - e = NULL; - - t = scf_block_find_type_type(ast->current_block, SCF_VAR_INT); - v = SCF_VAR_ALLOC_BY_TYPE(vla->w, t, 0, 0, NULL); - if (!v) - return SCF_DFA_ERROR; - v->tmp_flag = 1; - - len = scf_node_alloc(NULL, v->type, v); - if (!len) { - scf_variable_free(v); - return SCF_DFA_ERROR; - } - - scf_node_add_child(assign, len); - SCF_XCHG(assign->nodes[0], assign->nodes[1]); - - // vla_alloc(vla, len, printf, msg) - len = scf_node_alloc(NULL, v->type, v); - scf_variable_free(v); - v = NULL; - if (!len) - return SCF_DFA_ERROR; - - alloc = scf_node_alloc(vla->w, SCF_OP_VLA_ALLOC, NULL); - if (!alloc) { - scf_node_free(len); - return -ENOMEM; - } - - // vla node - node = scf_node_alloc(NULL, vla->type, vla); - if (!node) { - scf_node_free(len); - scf_node_free(alloc); - return SCF_DFA_ERROR; - } - - scf_node_add_child(alloc, node); - scf_node_add_child(alloc, len); - node = NULL; - len = NULL; - - // printf() node - t = scf_block_find_type_type(ast->current_block, SCF_FUNCTION_PTR); - v = SCF_VAR_ALLOC_BY_TYPE(f->node.w, t, 1, 1, f); - if (!v) { - scf_node_free(alloc); - return SCF_DFA_ERROR; - } - v->const_literal_flag = 1; - - node = scf_node_alloc(NULL, v->type, v); - scf_variable_free(v); - v = NULL; - if (!node) { - scf_node_free(alloc); - return SCF_DFA_ERROR; - } - - scf_node_add_child(alloc, node); - node = NULL; - - // msg - char msg[1024]; - snprintf(msg, sizeof(msg) - 1, "\033[31merror:\033[0m variable length '%%d' of array '%s' not more than 0, file: %s, line: %d\n", - vla->w->text->data, vla->w->file->data, vla->w->line); - - t = scf_block_find_type_type(ast->current_block, SCF_VAR_CHAR); - v = SCF_VAR_ALLOC_BY_TYPE(vla->w, t, 1, 1, NULL); - if (!v) { - scf_node_free(alloc); - return SCF_DFA_ERROR; - } - v->const_literal_flag = 1; - v->global_flag = 1; - - v->data.s = scf_string_cstr(msg); - if (!v->data.s) { - scf_node_free(alloc); - scf_variable_free(v); - return -ENOMEM; - } - - node = scf_node_alloc(NULL, v->type, v); - scf_variable_free(v); - v = NULL; - if (!node) { - scf_node_free(alloc); - return SCF_DFA_ERROR; - } - scf_node_add_child(alloc, node); - node = NULL; - - scf_node_add_child((scf_node_t*)ast->current_block, alloc); - return 0; -} - static int _var_add_typedef(scf_ast_t* ast, dfa_data_t* d) { scf_variable_t* v; @@ -517,7 +284,6 @@ static int _var_add_typedef(scf_ast_t* ast, dfa_data_t* d) assert(0 == scf_vector_del(ast->current_block->scope->vars, d->current_var)); - d->current_var->vla_flag = 0; d->current_var = NULL; } @@ -548,12 +314,6 @@ static int _var_action_comma(scf_dfa_t* dfa, scf_vector_t* words, void* data) return SCF_DFA_SWITCH_TO; } - - if (d->current_var->vla_flag) { - - if (_var_add_vla(parse->ast, d->current_var) < 0) - return SCF_DFA_ERROR; - } } if (d->expr_local_flag > 0 && _var_init_expr(dfa, d, words, 0) < 0) @@ -598,12 +358,6 @@ static int _var_action_semicolon(scf_dfa_t* dfa, scf_vector_t* words, void* data return SCF_DFA_OK; } - - if (d->current_var->vla_flag) { - - if (_var_add_vla(parse->ast, d->current_var) < 0) - return SCF_DFA_ERROR; - } } if (d->expr_local_flag > 0) { @@ -653,12 +407,6 @@ static int _var_action_assign(scf_dfa_t* dfa, scf_vector_t* words, void* data) return SCF_DFA_ERROR; } - if (d->current_var->vla_flag) { - - if (_var_add_vla(parse->ast, d->current_var) < 0) - return SCF_DFA_ERROR; - } - if (d->current_var->nb_dimentions > 0) { scf_logi("var array '%s' init, nb_dimentions: %d\n", d->current_var->w->text->data, d->current_var->nb_dimentions); return SCF_DFA_NEXT_WORD; @@ -751,7 +499,7 @@ static int _var_action_ls(scf_dfa_t* dfa, scf_vector_t* words, void* data) d->expr = NULL; } - scf_variable_add_array_dimention(d->current_var, -1, NULL); + scf_variable_add_array_dimention(d->current_var, -1); d->current_var->const_literal_flag = 1; SCF_DFA_PUSH_HOOK(scf_dfa_find_node(dfa, "var_rs"), SCF_DFA_HOOK_POST); @@ -785,23 +533,9 @@ static int _var_action_rs(scf_dfa_t* dfa, scf_vector_t* words, void* data) if (!scf_variable_const(r) && SCF_OP_ASSIGN != d->expr->nodes[0]->type) { - if (d->current_var->typedef_flag) { - scf_loge("variable length array '%s' can't be type defined, file: %s, line: %d\n", - d->current_var->w->text->data, w->file->data, w->line); - goto error; - } - - if (!d->current_var->local_flag) { - scf_loge("variable length array '%s' must in local scope, file: %s, line: %d\n", - d->current_var->w->text->data, w->file->data, w->line); - goto error; - } - - scf_logw("define variable length array, file: %s, line: %d\n", w->file->data, w->line); + scf_loge("%s:%d:%d, NOT support VLA (variable length array)\n", w->file->data, w->line, w->pos); + goto error; - d->current_var->dimentions[d->current_var->dim_index].vla = d->expr; - d->current_var->vla_flag = 1; - d->expr = NULL; } else { d->current_var->dimentions[d->current_var->dim_index].num = r->data.i; diff --git a/parse/scf_operator_handler_const.c b/parse/scf_operator_handler_const.c index 41ff57b..cfa654c 100644 --- a/parse/scf_operator_handler_const.c +++ b/parse/scf_operator_handler_const.c @@ -367,13 +367,6 @@ static int _scf_op_const_default(scf_ast_t* ast, scf_node_t** nodes, int nb_node return 0; } -static int _scf_op_const_vla_alloc(scf_ast_t* ast, scf_node_t** nodes, int nb_nodes, void* data) -{ - assert(4 == nb_nodes); - - return 0; -} - static int _scf_op_const_for(scf_ast_t* ast, scf_node_t** nodes, int nb_nodes, void* data) { assert(4 == nb_nodes); @@ -1017,8 +1010,6 @@ scf_operator_handler_pt const_operator_handlers[SCF_N_OPS] = [SCF_OP_SWITCH ] = _scf_op_const_switch, [SCF_OP_CASE ] = _scf_op_const_case, [SCF_OP_DEFAULT ] = _scf_op_const_default, - - [SCF_OP_VLA_ALLOC ] = _scf_op_const_vla_alloc, }; scf_operator_handler_pt scf_find_const_operator_handler(const int type) diff --git a/parse/scf_operator_handler_semantic.c b/parse/scf_operator_handler_semantic.c index dcb7c5a..9918ff6 100644 --- a/parse/scf_operator_handler_semantic.c +++ b/parse/scf_operator_handler_semantic.c @@ -886,7 +886,7 @@ static int _scf_op_semantic_pointer(scf_ast_t* ast, scf_node_t** nodes, int nb_n int i; for (i = 0; i < v1->nb_dimentions; i++) - scf_variable_add_array_dimention(r, v1->dimentions[i].num, NULL); + scf_variable_add_array_dimention(r, v1->dimentions[i].num); *d->pret = r; return 0; @@ -933,7 +933,7 @@ static int _scf_op_semantic_array_index(scf_ast_t* ast, scf_node_t** nodes, int int nb_pointers = 0; if (v0->nb_dimentions > 0) { - if (v0->dimentions[0].num < 0 && !v0->dimentions[0].vla) { + if (v0->dimentions[0].num < 0) { scf_loge("\n"); return -1; } @@ -947,16 +947,18 @@ static int _scf_op_semantic_array_index(scf_ast_t* ast, scf_node_t** nodes, int return -1; } - if (v1->data.i >= v0->dimentions[0].num && !v0->dimentions[0].vla) { + if (v1->data.i >= v0->dimentions[0].num) { if (!v0->member_flag) { - scf_loge("array index '%s' >= size %d, real: %d, file: %s, line: %d\n", - v1->w->text->data, v0->dimentions[0].num, v1->data.i, v1->w->file->data, v1->w->line); + scf_loge("%s:%d:%d, array index '%s' >= size %d, real: %d\n", + v1->w->file->data, v1->w->line, v1->w->pos, + v1->w->text->data, v0->dimentions[0].num, v1->data.i); return -1; } - scf_logw("array index '%s' >= size %d, real: %d, confirm it for a zero-array end of a struct? file: %s, line: %d\n", - v1->w->text->data, v0->dimentions[0].num, v1->data.i, v1->w->file->data, v1->w->line); + scf_logw("%s:%d:%d, array index '%s' >= size %d, real: %d, confirm it for a zero-array end of a struct?\n", + v1->w->file->data, v1->w->line, v1->w->pos, + v1->w->text->data, v0->dimentions[0].num, v1->data.i); } } } else if (0 == v0->nb_dimentions && v0->nb_pointers > 0) { @@ -980,19 +982,8 @@ static int _scf_op_semantic_array_index(scf_ast_t* ast, scf_node_t** nodes, int r->member_flag = v0->member_flag; int i; - for (i = 1; i < v0->nb_dimentions; i++) { - scf_expr_t* vla = NULL; - - if (v0->dimentions[i].vla) { - vla = scf_expr_clone(v0->dimentions[i].vla); - if (!vla) { - scf_variable_free(r); - return -ENOMEM; - } - } - - scf_variable_add_array_dimention(r, v0->dimentions[i].num, vla); - } + for (i = 1; i < v0->nb_dimentions; i++) + scf_variable_add_array_dimention(r, v0->dimentions[i].num); *d->pret = r; return 0; @@ -1446,14 +1437,6 @@ static int _scf_op_semantic_default(scf_ast_t* ast, scf_node_t** nodes, int nb_n return 0; } -static int _scf_op_semantic_vla_alloc(scf_ast_t* ast, scf_node_t** nodes, int nb_nodes, void* data) -{ - assert(4 == nb_nodes); - - scf_logw("\n"); - return 0; -} - static int _scf_op_semantic_for(scf_ast_t* ast, scf_node_t** nodes, int nb_nodes, void* data) { assert(4 == nb_nodes); @@ -3212,8 +3195,6 @@ scf_operator_handler_pt semantic_operator_handlers[SCF_N_OPS] = [SCF_OP_SWITCH ] = _scf_op_semantic_switch, [SCF_OP_CASE ] = _scf_op_semantic_case, [SCF_OP_DEFAULT ] = _scf_op_semantic_default, - - [SCF_OP_VLA_ALLOC ] = _scf_op_semantic_vla_alloc, }; scf_operator_handler_pt scf_find_semantic_operator_handler(const int type) diff --git a/parse/scf_parse.c b/parse/scf_parse.c index 38a3836..20e6636 100644 --- a/parse/scf_parse.c +++ b/parse/scf_parse.c @@ -1356,9 +1356,9 @@ static int _fill_data(scf_parse_t* parse, scf_variable_t* v, scf_string_t* data, int size; uint8_t* v_data; - if (v->global_flag) { + if (v->global_flag) name = v->w->text->data; - } else + else name = v->signature->data; scf_logd("v_%d_%d/%s, nb_dimentions: %d\n", v->w->line, v->w->pos, v->w->text->data, v->nb_dimentions); @@ -1875,13 +1875,18 @@ static int _scf_parse_add_text_relas(scf_parse_t* parse, scf_elf_context_t* elf, for (j = 0; j < f->data_relas->size; j++) { r = f->data_relas->data[j]; - char* name; - if (r->var->global_flag) + uint16_t shndx = SCF_SHNDX_DATA; + char* name; + + if (r->var->global_flag) { name = r->var->w->text->data; - else + + if (r->var->extern_flag) + shndx = 0; + } else name = r->var->signature->data; - ret = scf_symtab_add_rela(relas, parse->symtab, r, name, 2); + ret = scf_symtab_add_rela(relas, parse->symtab, r, name, shndx); if (ret < 0) { scf_loge("\n"); goto error; @@ -2013,7 +2018,7 @@ int scf_eda_write_cpk(scf_parse_t* parse, const char* out, scf_vector_t* functio return 0; } -int scf_parse_native_functions(scf_parse_t* parse, scf_vector_t* functions, const char* arch) +int scf_parse_native_functions(scf_parse_t* parse, scf_vector_t* functions, const char* arch, int pic_flag) { scf_function_t* f; scf_native_t* native; @@ -2033,7 +2038,9 @@ int scf_parse_native_functions(scf_parse_t* parse, scf_vector_t* functions, cons if (f->native_flag) continue; + f->native_flag = 1; + f->pic_flag = pic_flag; ret = scf_native_select_inst(native, f); if (ret < 0) { @@ -2267,7 +2274,7 @@ int scf_parse_fill_code(scf_parse_t* parse, scf_vector_t* functions, scf_vector_ return 0; } -int scf_parse_compile(scf_parse_t* parse, const char* arch, int _3ac) +int scf_parse_compile(scf_parse_t* parse, const char* arch, int _3ac, int pic_flag) { scf_block_t* b = parse->ast->root_block; if (!b) @@ -2290,7 +2297,7 @@ int scf_parse_compile(scf_parse_t* parse, const char* arch, int _3ac) if (_3ac) goto error; - ret = scf_parse_native_functions(parse, functions, arch); + ret = scf_parse_native_functions(parse, functions, arch, pic_flag); error: scf_vector_free(functions); return ret; diff --git a/parse/scf_parse.h b/parse/scf_parse.h index 2dbbcc5..cff60ce 100644 --- a/parse/scf_parse.h +++ b/parse/scf_parse.h @@ -100,6 +100,7 @@ struct dfa_data_s { scf_node_t* current_va_start; scf_node_t* current_va_arg; + scf_node_t* current_va_copy; scf_node_t* current_va_end; uint32_t typedef_flag:1; @@ -126,7 +127,7 @@ int scf_parse_open (scf_parse_t** pparse, const scf_vector_t* inc_paths, int c_v int scf_parse_close(scf_parse_t* parse); int scf_parse_file (scf_parse_t* parse, const char* path, scf_vector_t** macros, scf_lex_word_t* include); -int scf_parse_compile(scf_parse_t* parse, const char* arch, int _3ac); +int scf_parse_compile(scf_parse_t* parse, const char* arch, int _3ac, int pic_flag); int scf_parse_to_obj (scf_parse_t* parse, const char* out, const char* arch); int _find_global_var(scf_node_t* node, void* arg, scf_vector_t* vec); diff --git a/sysroot/include/stdarg.h b/sysroot/include/stdarg.h new file mode 100644 index 0000000..3256f80 --- /dev/null +++ b/sysroot/include/stdarg.h @@ -0,0 +1,21 @@ +#ifndef _STDARG_H +#define _STDARG_H + +#ifdef __cplusplus +extern "C" { +#endif + +#define __NEED_va_list + +#include + +#define va_start(v,l) __builtin_va_start(v,l) +#define va_end(v) __builtin_va_end(v) +#define va_arg(v,l) __builtin_va_arg(v,l) +#define va_copy(d,s) __builtin_va_copy(d,s) + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/sysroot/lib/x64/_start.s b/sysroot/lib/x64/_start.s index 2df9e03..dbd839b 100644 --- a/sysroot/lib/x64/_start.s +++ b/sysroot/lib/x64/_start.s @@ -1,20 +1,18 @@ .text -.global _start, main - +.global _start _start: - mov %rsp, %rsi - add $8, %rsi # argv - mov %rsi, %rdx -1: - mov (%rdx), %rdi - add $8, %rdx # envp - test %rdi, %rdi - jnz 1b - - mov (%rsp), %rdi # argc + endbr64 + xor %ebp,%ebp + mov %rdx,%r9 + pop %rsi + mov %rsp,%rdx + and $-16,%rsp + push %rax + push %rsp + xor %r8d,%r8d + xor %ecx,%ecx - call main - mov %rax, %rdi - mov $60, %rax - syscall -.fill 5, 1, 0 + lea main(%rip), %rdi + call __libc_start_main + hlt +.fill 3, 1, 0 -- 2.25.1