⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dyngen.c

📁 qemu虚拟机代码
💻 C
📖 第 1 页 / 共 5 页
字号:
    int offset, min_offset, pc_offset, data_size;    uint8_t data_allocated[1024];    unsigned int data_index;        memset(data_allocated, 0, sizeof(data_allocated));        p = p_start;    min_offset = p_end - p_start;    while (p < p_start + min_offset) {        insn = get32((uint32_t *)p);        if ((insn & 0x0d5f0000) == 0x051f0000) {            /* ldr reg, [pc, #im] */            offset = insn & 0xfff;            if (!(insn & 0x00800000))                        offset = -offset;            if ((offset & 3) !=0)                error("%s:%04x: ldr pc offset must be 32 bit aligned",                       name, start_offset + p - p_start);            pc_offset = p - p_start + offset + 8;            if (pc_offset <= (p - p_start) ||                 pc_offset >= (p_end - p_start))                error("%s:%04x: ldr pc offset must point inside the function code",                       name, start_offset + p - p_start);            if (pc_offset < min_offset)                min_offset = pc_offset;            if (outfile) {                /* ldr position */                fprintf(outfile, "    arm_ldr_ptr->ptr = gen_code_ptr + %d;\n",                         p - p_start);                /* ldr data index */                data_index = ((p_end - p_start) - pc_offset - 4) >> 2;                fprintf(outfile, "    arm_ldr_ptr->data_ptr = arm_data_ptr + %d;\n",                         data_index);                fprintf(outfile, "    arm_ldr_ptr++;\n");                if (data_index >= sizeof(data_allocated))                    error("%s: too many data", name);                if (!data_allocated[data_index]) {                    ELF_RELOC *rel;                    int i, addend, type;                    const char *sym_name, *p;                    char relname[1024];                    data_allocated[data_index] = 1;                    /* data value */                    addend = get32((uint32_t *)(p_start + pc_offset));                    relname[0] = '\0';                    for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) {                        if (rel->r_offset == (pc_offset + start_offset)) {                            sym_name = get_rel_sym_name(rel);                            /* the compiler leave some unnecessary references to the code */                            get_reloc_expr(relname, sizeof(relname), sym_name);                            type = ELF32_R_TYPE(rel->r_info);                            if (type != R_ARM_ABS32)                                error("%s: unsupported data relocation", name);                            break;                        }                    }                    fprintf(outfile, "    arm_data_ptr[%d] = 0x%x",                            data_index, addend);                    if (relname[0] != '\0')                        fprintf(outfile, " + %s", relname);                    fprintf(outfile, ";\n");                }            }        }        p += 4;    }    data_size = (p_end - p_start) - min_offset;    if (data_size > 0 && outfile) {        fprintf(outfile, "    arm_data_ptr += %d;\n", data_size >> 2);    }    /* the last instruction must be a mov pc, lr */    if (p == p_start)        goto arm_ret_error;    p -= 4;    insn = get32((uint32_t *)p);    if ((insn & 0xffff0000) != 0xe91b0000) {    arm_ret_error:        if (!outfile)            printf("%s: invalid epilog\n", name);    }    return p - p_start;	    }#endif#define MAX_ARGS 3/* generate op code */void gen_code(const char *name, host_ulong offset, host_ulong size,               FILE *outfile, int gen_switch){    int copy_size = 0;    uint8_t *p_start, *p_end;    host_ulong start_offset;    int nb_args, i, n;    uint8_t args_present[MAX_ARGS];    const char *sym_name, *p;    EXE_RELOC *rel;    /* Compute exact size excluding prologue and epilogue instructions.     * Increment start_offset to skip epilogue instructions, then compute     * copy_size the indicate the size of the remaining instructions (in     * bytes).     */    p_start = text + offset;    p_end = p_start + size;    start_offset = offset;#if defined(HOST_I386) || defined(HOST_X86_64)#ifdef CONFIG_FORMAT_COFF    {        uint8_t *p;        p = p_end - 1;        if (p == p_start)            error("empty code for %s", name);        while (*p != 0xc3) {            p--;            if (p <= p_start)                error("ret or jmp expected at the end of %s", name);        }        copy_size = p - p_start;    }#else    {        int len;        len = p_end - p_start;        if (len == 0)            error("empty code for %s", name);        if (p_end[-1] == 0xc3) {            len--;        } else {            error("ret or jmp expected at the end of %s", name);        }        copy_size = len;    }#endif    #elif defined(HOST_PPC)    {        uint8_t *p;        p = (void *)(p_end - 4);        if (p == p_start)            error("empty code for %s", name);        if (get32((uint32_t *)p) != 0x4e800020)            error("blr expected at the end of %s", name);        copy_size = p - p_start;    }#elif defined(HOST_S390)    {        uint8_t *p;        p = (void *)(p_end - 2);        if (p == p_start)            error("empty code for %s", name);        if (get16((uint16_t *)p) != 0x07fe && get16((uint16_t *)p) != 0x07f4)            error("br %%r14 expected at the end of %s", name);        copy_size = p - p_start;    }#elif defined(HOST_ALPHA)    {        uint8_t *p;        p = p_end - 4;#if 0        /* XXX: check why it occurs */        if (p == p_start)            error("empty code for %s", name);#endif        if (get32((uint32_t *)p) != 0x6bfa8001)            error("ret expected at the end of %s", name);        copy_size = p - p_start;	        }#elif defined(HOST_IA64)    {        uint8_t *p;        p = (void *)(p_end - 4);        if (p == p_start)            error("empty code for %s", name);        /* br.ret.sptk.many b0;; */        /* 08 00 84 00 */        if (get32((uint32_t *)p) != 0x00840008)            error("br.ret.sptk.many b0;; expected at the end of %s", name);	copy_size = p_end - p_start;    }#elif defined(HOST_SPARC)    {        uint32_t start_insn, end_insn1, end_insn2;        uint8_t *p;        p = (void *)(p_end - 8);        if (p <= p_start)            error("empty code for %s", name);        start_insn = get32((uint32_t *)(p_start + 0x0));        end_insn1 = get32((uint32_t *)(p + 0x0));        end_insn2 = get32((uint32_t *)(p + 0x4));        if ((start_insn & ~0x1fff) == 0x9de3a000) {            p_start += 0x4;            start_offset += 0x4;            if ((int)(start_insn | ~0x1fff) < -128)                error("Found bogus save at the start of %s", name);            if (end_insn1 != 0x81c7e008 || end_insn2 != 0x81e80000)                error("ret; restore; not found at end of %s", name);        } else {            error("No save at the beginning of %s", name);        }#if 0        /* Skip a preceeding nop, if present.  */        if (p > p_start) {            skip_insn = get32((uint32_t *)(p - 0x4));            if (skip_insn == 0x01000000)                p -= 4;        }#endif        copy_size = p - p_start;    }#elif defined(HOST_SPARC64)    {        uint32_t start_insn, end_insn1, end_insn2, skip_insn;        uint8_t *p;        p = (void *)(p_end - 8);        if (p <= p_start)            error("empty code for %s", name);        start_insn = get32((uint32_t *)(p_start + 0x0));        end_insn1 = get32((uint32_t *)(p + 0x0));        end_insn2 = get32((uint32_t *)(p + 0x4));        if ((start_insn & ~0x1fff) == 0x9de3a000) {            p_start += 0x4;            start_offset += 0x4;            if ((int)(start_insn | ~0x1fff) < -256)                error("Found bogus save at the start of %s", name);            if (end_insn1 != 0x81c7e008 || end_insn2 != 0x81e80000)                error("ret; restore; not found at end of %s", name);        } else {            error("No save at the beginning of %s", name);        }                /* Skip a preceeding nop, if present.  */        if (p > p_start) {            skip_insn = get32((uint32_t *)(p - 0x4));            if (skip_insn == 0x01000000)                p -= 4;        }                copy_size = p - p_start;    }#elif defined(HOST_ARM)    {        if ((p_end - p_start) <= 16)            error("%s: function too small", name);        if (get32((uint32_t *)p_start) != 0xe1a0c00d ||            (get32((uint32_t *)(p_start + 4)) & 0xffff0000) != 0xe92d0000 ||            get32((uint32_t *)(p_start + 8)) != 0xe24cb004)            error("%s: invalid prolog", name);        p_start += 12;        start_offset += 12;        copy_size = arm_emit_ldr_info(name, start_offset, NULL, p_start, p_end,                                       relocs, nb_relocs);    }#elif defined(HOST_M68K)    {        uint8_t *p;        p = (void *)(p_end - 2);        if (p == p_start)            error("empty code for %s", name);        // remove NOP's, probably added for alignment        while ((get16((uint16_t *)p) == 0x4e71) &&               (p>p_start))             p -= 2;        if (get16((uint16_t *)p) != 0x4e75)            error("rts expected at the end of %s", name);        copy_size = p - p_start;    }#else#error unsupported CPU#endif    /* compute the number of arguments by looking at the relocations */    for(i = 0;i < MAX_ARGS; i++)        args_present[i] = 0;    for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) {        host_ulong offset = get_rel_offset(rel);        if (offset >= start_offset &&	    offset < start_offset + (p_end - p_start)) {            sym_name = get_rel_sym_name(rel);            if(!sym_name)                continue;            if (strstart(sym_name, "__op_param", &p) ||                strstart(sym_name, "__op_gen_label", &p)) {                n = strtoul(p, NULL, 10);                if (n > MAX_ARGS)                    error("too many arguments in %s", name);                args_present[n - 1] = 1;            }        }    }        nb_args = 0;    while (nb_args < MAX_ARGS && args_present[nb_args])        nb_args++;    for(i = nb_args; i < MAX_ARGS; i++) {        if (args_present[i])            error("inconsistent argument numbering in %s", name);    }    if (gen_switch == 2) {        fprintf(outfile, "DEF(%s, %d, %d)\n", name + 3, nb_args, copy_size);    } else if (gen_switch == 1) {        /* output C code */        fprintf(outfile, "case INDEX_%s: {\n", name);        if (nb_args > 0) {            fprintf(outfile, "    long ");            for(i = 0; i < nb_args; i++) {                if (i != 0)                    fprintf(outfile, ", ");                fprintf(outfile, "param%d", i + 1);            }            fprintf(outfile, ";\n");        }#if defined(HOST_IA64)        fprintf(outfile, "    extern char %s;\n", name);#else        fprintf(outfile, "    extern void %s();\n", name);#endif        for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) {            host_ulong offset = get_rel_offset(rel);            if (offset >= start_offset &&                offset < start_offset + (p_end - p_start)) {                sym_name = get_rel_sym_name(rel);                if(!sym_name)                    continue;                if (*sym_name &&                     !strstart(sym_name, "__op_param", NULL) &&                    !strstart(sym_name, "__op_jmp", NULL) &&                    !strstart(sym_name, "__op_gen_label", NULL)) {#if defined(HOST_SPARC)		    if (sym_name[0] == '.') {			fprintf(outfile,				"extern char __dot_%s __asm__(\"%s\");\n",				sym_name+1, sym_name);			continue;		    }#endif#if defined(__APPLE__)/* set __attribute((unused)) on darwin because we wan't to avoid warning when we don't use the symbol */                    fprintf(outfile, "extern char %s __attribute__((unused));\n", sym_name);#elif defined(HOST_IA64)			if (ELF64_R_TYPE(rel->r_info) != R_IA64_PCREL21B)				/*				 * PCREL21 br.call targets generally				 * are out of range and need to go				 * through an "import stub".				 */				fprintf(outfile, "    extern char %s;\n",					sym_name);#else                    fprintf(outfile, "extern char %s;\n", sym_name);#endif                }            }        }        fprintf(outfile, "    memcpy(gen_code_ptr, (void *)((char *)&%s+%d), %d);\n",					name, (int)(start_offset - offset), copy_size);        /* emit code offset information */        {            EXE_SYM *sym;            const char *sym_name, *p;            unsigned long val;            int n;            for(i = 0, sym = symtab; i < nb_syms; i++, sym++) {                sym_name = get_sym_name(sym);                if (strstart(sym_name, "__op_label", &p)) {                    uint8_t *ptr;                    unsigned long offset;                                        /* test if the variable refers to a label inside                       the code we are generating */#ifdef CONFIG_FORMAT_COFF                    if (sym->st_shndx == text_shndx) {                        ptr = sdata[coff_text_shndx];                    } else if (sym->st_shndx == data_shndx) {                        ptr = sdata[coff_data_shndx];                    } else {                        ptr = NULL;                    }#elif defined(CONFIG_FORMAT_MACH)                    if(!sym->n_sect)                        continue;                    ptr = sdata[sym->n_sect-1];#else                    ptr = sdata[sym->st_shndx];#endif                    if (!ptr)                        error("__op_labelN in invalid section");                    offset = sym->st_value;#ifdef CONFIG_FORMAT_MACH                    offset -= section_hdr[sym->n_sect-1].addr;#endif                    val = *(unsigned long *)(ptr + offset);#ifdef ELF_USES_RELOCA                    {                        int reloc_shndx, nb_relocs1, j;                        /* try to find a matching relocation */                        reloc_shndx = find_reloc(sym->st_shndx);                        if (reloc_shndx) {                            nb_relocs1 = shdr[reloc_shndx].sh_size /                                 shdr[reloc_shndx].sh_entsize;                            rel = (ELF_RELOC *)sdata[reloc_shndx];                            for(j = 0; j < nb_relocs1; j++) {                                if (rel->r_offset == offset) {				    val = rel->r_addend;                                    break;                                }				rel++;                            }

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -