int _jit_block_record_label(jit_block_t block) { jit_builder_t builder = block->func->builder; jit_label_t num; jit_block_t *blocks; if(block->label >= builder->max_label_blocks) { num = builder->max_label_blocks; if(num < 64) { num = 64; } while(num <= block->label) { num *= 2; } blocks = (jit_block_t *)jit_realloc (builder->label_blocks, num * sizeof(jit_block_t)); if(!blocks) { return 0; } jit_memzero(blocks + builder->max_label_blocks, sizeof(jit_block_t) * (num - builder->max_label_blocks)); builder->label_blocks = blocks; builder->max_label_blocks = num; } builder->label_blocks[block->label] = block; return 1; }
/* * Append data to a section. */ static int add_to_section (jit_section_t section, const void *buf, unsigned int len) { char *data = (char *)jit_realloc(section->data, section->data_len + len); if(!data) { return 0; } section->data = data; jit_memcpy(data + section->data_len, buf, len); section->data_len += len; return 1; }
/* * Add a string to the dynamic string section. * * TODO: use a hash table to cache previous names. */ static Elf_Word add_dyn_string(jit_writeelf_t writeelf, const char *name) { jit_section_t section; char *data; Elf_Word index; unsigned int name_len = jit_strlen(name) + 1; section = &(writeelf->sections[writeelf->dynamic_string_section]); data = (char *)jit_realloc(section->data, section->data_len + name_len); if(!data) { return 0; } section->data = data; jit_strcpy(data + section->data_len, name); index = (Elf_Word)(section->data_len); section->data_len += name_len; return index; }
jit_insn_t _jit_block_add_insn(jit_block_t block) { jit_builder_t builder = block->func->builder; jit_insn_t insn; int num; jit_insn_t *insns; /* Allocate the instruction from the builder's memory pool */ insn = jit_memory_pool_alloc(&(builder->insn_pool), struct _jit_insn); if(!insn) { return 0; } /* Make space for the instruction in the function's instruction list */ if(builder->num_insns >= builder->max_insns) { num = builder->max_insns * 2; if(num < 64) { num = 64; } insns = (jit_insn_t *)jit_realloc (builder->insns, num * sizeof(jit_insn_t)); if(!insns) { return 0; } builder->insns = insns; builder->max_insns = num; } else { insns = builder->insns; } insns[builder->num_insns] = insn; block->last_insn = (builder->num_insns)++; /* Return the instruction, which is now ready to fill in */ return insn; }
void _jit_prolog(jit_state_t *_jit) { jit_int32_t offset; if (_jitc->function) jit_epilog(); assert(jit_regset_cmp_ui(&_jitc->regarg, 0) == 0); jit_regset_set_ui(&_jitc->regsav, 0); offset = _jitc->functions.offset; if (offset >= _jitc->functions.length) { jit_realloc((jit_pointer_t *)&_jitc->functions.ptr, _jitc->functions.length * sizeof(jit_function_t), (_jitc->functions.length + 16) * sizeof(jit_function_t)); _jitc->functions.length += 16; } _jitc->function = _jitc->functions.ptr + _jitc->functions.offset++; _jitc->function->self.size = stack_framesize; _jitc->function->self.argi = _jitc->function->self.argf = _jitc->function->self.aoff = _jitc->function->self.alen = 0; /* float conversion */ _jitc->function->self.aoff = -8; _jitc->function->self.call = jit_call_default; jit_alloc((jit_pointer_t *)&_jitc->function->regoff, _jitc->reglen * sizeof(jit_int32_t)); _jitc->function->prolog = jit_new_node_no_link(jit_code_prolog); jit_link(_jitc->function->prolog); _jitc->function->prolog->w.w = offset; _jitc->function->epilog = jit_new_node_no_link(jit_code_epilog); /* u: label value * v: offset in blocks vector * w: offset in functions vector */ _jitc->function->epilog->w.w = offset; jit_regset_new(&_jitc->function->regset); }
static void _patch(jit_state_t *_jit, jit_word_t instr, jit_node_t *node) { jit_int32_t flag; assert(node->flag & jit_flag_node); if (node->code == jit_code_movi) flag = node->v.n->flag; else flag = node->u.n->flag; assert(!(flag & jit_flag_patch)); if (_jitc->patches.offset >= _jitc->patches.length) { jit_realloc((jit_pointer_t *)&_jitc->patches.ptr, _jitc->patches.length * sizeof(jit_patch_t), (_jitc->patches.length + 1024) * sizeof(jit_patch_t)); memset(_jitc->patches.ptr + _jitc->patches.length, 0, 1024 * sizeof(jit_patch_t)); _jitc->patches.length += 1024; } _jitc->patches.ptr[_jitc->patches.offset].inst = instr; _jitc->patches.ptr[_jitc->patches.offset].node = node; ++_jitc->patches.offset; }
/* * Get or add a section. */ static jit_section_t get_section (jit_writeelf_t writeelf, const char *name, jit_int type, Elf_Word flags, Elf_Word entry_size, Elf_Word alignment) { int index; jit_section_t section; /* Search the section table for an existing section by this name */ for(index = 0; index < writeelf->num_sections; ++index) { section = &(writeelf->sections[index]); if(!jit_strcmp(get_string(writeelf, section->shdr.sh_name), name)) { return section; } } /* Create a new section and clear it */ section = (jit_section_t)jit_realloc (writeelf->sections, (writeelf->num_sections + 1) * sizeof(struct jit_section)); if(!section) { return 0; } writeelf->sections = section; section += writeelf->num_sections; jit_memzero(section, sizeof(struct jit_section)); /* Set the section's name. If this is the first section created, then it is the string table itself, and we have to add the name to the section itself to start the ball rolling */ if(writeelf->regular_string_section < 0) { section->data = (char *)jit_malloc(jit_strlen(name) + 2); if(!(section->data)) { return 0; } section->data_len = jit_strlen(name) + 2; section->data[0] = '\0'; /* Empty string is always first */ jit_strcpy(section->data + 1, name); section->shdr.sh_name = 1; writeelf->regular_string_section = writeelf->num_sections; } else { section->shdr.sh_name = add_string(writeelf, name); if(!(section->shdr.sh_name)) { return 0; } } /* Set the other section properties */ section->shdr.sh_type = (Elf_Word)type; section->shdr.sh_flags = flags; section->shdr.sh_entsize = entry_size; section->shdr.sh_addralign = alignment; /* Increase the section count and return */ ++(writeelf->num_sections); return section; }
/* * Implementation */ void jit_init_debug(const char *progname) { #if DISASSEMBLER bfd_init(); if (progname) disasm_bfd = bfd_openr(progname, NULL); if (disasm_bfd == NULL) { #if defined(__linux__) disasm_bfd = bfd_openr("/proc/self/exe", NULL); if (disasm_bfd == NULL) #endif return; } bfd_check_format(disasm_bfd, bfd_object); bfd_check_format(disasm_bfd, bfd_archive); disasm_print = disassembler(disasm_bfd); assert(disasm_print); INIT_DISASSEMBLE_INFO(disasm_info, disasm_stream, fprintf); # if defined(__i386__) || defined(__x86_64__) disasm_info.arch = bfd_arch_i386; # if defined(__x86_64__) # if __WORDSIZE == 32 disasm_info.mach = bfd_mach_x64_32; # else disasm_info.mach = bfd_mach_x86_64; # endif # else disasm_info.mach = bfd_mach_i386_i386; # endif # endif # if defined(__powerpc__) disasm_info.arch = bfd_arch_powerpc; disasm_info.mach = bfd_mach_ppc64; # if HAVE_DISASSEMBLE_INIT_FOR_TARGET disassemble_init_for_target(&disasm_info); # elif HAVE_DISASSEMBLE_INIT_POWERPC disassemble_init_powerpc(&disasm_info); # endif # if defined(__powerpc64__) disasm_info.disassembler_options = "64"; # endif # if HAVE_DISASSEMBLE_INIT_FOR_TARGET disassemble_init_for_target(&disasm_info); # elif HAVE_DISASSEMBLE_INIT_POWERPC disassemble_init_powerpc(&disasm_info); # endif # endif # if defined(__sparc__) disasm_info.endian = disasm_info.display_endian = BFD_ENDIAN_BIG; # endif # if defined(__s390__) || defined(__s390x__) disasm_info.arch = bfd_arch_s390; # if __WORDSIZE == 32 disasm_info.mach = bfd_mach_s390_31; # else disasm_info.mach = bfd_mach_s390_64; # endif disasm_info.endian = disasm_info.display_endian = BFD_ENDIAN_BIG; disasm_info.disassembler_options = "zarch"; # endif # if defined(__alpha__) disasm_info.arch = bfd_arch_alpha; disasm_info.mach = bfd_mach_alpha_ev6; # endif disasm_info.print_address_func = disasm_print_address; if (bfd_get_file_flags(disasm_bfd) & HAS_SYMS) { asymbol **in; asymbol **out; asymbol *symbol; long offset; long sym_count; long dyn_count; long sym_storage; long dyn_storage; if ((sym_storage = bfd_get_symtab_upper_bound(disasm_bfd)) >= 0) { if (bfd_get_file_flags(disasm_bfd) & DYNAMIC) { dyn_storage = bfd_get_dynamic_symtab_upper_bound(disasm_bfd); # if defined(__alpha__) /* XXX */ if (dyn_storage < 0) dyn_storage = 0; # else assert(dyn_storage >= 0); # endif } else dyn_storage = 0; jit_alloc((jit_pointer_t *)&disasm_symbols, (sym_storage + dyn_storage) * sizeof(asymbol *)); sym_count = bfd_canonicalize_symtab(disasm_bfd, disasm_symbols); assert(sym_count >= 0); if (dyn_storage) { dyn_count = bfd_canonicalize_dynamic_symtab(disasm_bfd, disasm_symbols + sym_count); assert(dyn_count >= 0); } else dyn_count = 0; disasm_num_symbols = sym_count + dyn_count; disasm_num_synthetic = bfd_get_synthetic_symtab(disasm_bfd, sym_count, disasm_symbols, dyn_count, disasm_symbols + sym_count, &disasm_synthetic); if (disasm_num_synthetic > 0) { jit_realloc((jit_pointer_t *)&disasm_symbols, (sym_storage + dyn_storage) * sizeof(asymbol *), (sym_storage + dyn_storage + disasm_num_synthetic) * sizeof(asymbol *)); for (offset = 0; offset < disasm_num_synthetic; offset++) disasm_symbols[disasm_num_symbols++] = disasm_synthetic + offset; } /* remove symbols not useful for disassemble */ in = out = disasm_symbols; for (offset = 0; offset < disasm_num_symbols; offset++) { symbol = *in++; if (symbol->name && symbol->name[0] != '\0' && !(symbol->flags & (BSF_DEBUGGING | BSF_SECTION_SYM)) && !bfd_is_und_section(symbol->section) && !bfd_is_com_section(symbol->section)) *out++ = symbol; } disasm_num_symbols = out - disasm_symbols; qsort(disasm_symbols, disasm_num_symbols, sizeof(asymbol *), disasm_compare_symbols); } } #endif }