Revision 813da627
b/elf.h | ||
---|---|---|
216 | 216 |
|
217 | 217 |
#define ELF_ST_BIND(x) ((x) >> 4) |
218 | 218 |
#define ELF_ST_TYPE(x) (((unsigned int) x) & 0xf) |
219 |
#define ELF_ST_INFO(bind, type) (((bind) << 4) | ((type) & 0xf)) |
|
219 | 220 |
#define ELF32_ST_BIND(x) ELF_ST_BIND(x) |
220 | 221 |
#define ELF32_ST_TYPE(x) ELF_ST_TYPE(x) |
221 | 222 |
#define ELF64_ST_BIND(x) ELF_ST_BIND(x) |
b/exec.c | ||
---|---|---|
636 | 636 |
cpu_gen_init(); |
637 | 637 |
code_gen_alloc(tb_size); |
638 | 638 |
code_gen_ptr = code_gen_buffer; |
639 |
tcg_register_jit(code_gen_buffer, code_gen_buffer_size); |
|
639 | 640 |
page_init(); |
640 | 641 |
#if !defined(CONFIG_USER_ONLY) || !defined(CONFIG_USE_GUEST_BASE) |
641 | 642 |
/* There's no guest base to take into account, so go ahead and |
b/tcg/i386/tcg-target.c | ||
---|---|---|
1989 | 1989 |
#endif |
1990 | 1990 |
}; |
1991 | 1991 |
|
1992 |
/* Compute frame size via macros, to share between tcg_target_qemu_prologue |
|
1993 |
and tcg_register_jit. */ |
|
1994 |
|
|
1995 |
#define PUSH_SIZE \ |
|
1996 |
((1 + ARRAY_SIZE(tcg_target_callee_save_regs)) \ |
|
1997 |
* (TCG_TARGET_REG_BITS / 8)) |
|
1998 |
|
|
1999 |
#define FRAME_SIZE \ |
|
2000 |
((PUSH_SIZE \ |
|
2001 |
+ TCG_STATIC_CALL_ARGS_SIZE \ |
|
2002 |
+ CPU_TEMP_BUF_NLONGS * sizeof(long) \ |
|
2003 |
+ TCG_TARGET_STACK_ALIGN - 1) \ |
|
2004 |
& ~(TCG_TARGET_STACK_ALIGN - 1)) |
|
2005 |
|
|
1992 | 2006 |
/* Generate global QEMU prologue and epilogue code */ |
1993 | 2007 |
static void tcg_target_qemu_prologue(TCGContext *s) |
1994 | 2008 |
{ |
1995 |
int i, frame_size, push_size, stack_addend;
|
|
2009 |
int i, stack_addend; |
|
1996 | 2010 |
|
1997 | 2011 |
/* TB prologue */ |
1998 | 2012 |
|
1999 | 2013 |
/* Reserve some stack space, also for TCG temps. */ |
2000 |
push_size = 1 + ARRAY_SIZE(tcg_target_callee_save_regs); |
|
2001 |
push_size *= TCG_TARGET_REG_BITS / 8; |
|
2002 |
|
|
2003 |
frame_size = push_size + TCG_STATIC_CALL_ARGS_SIZE + |
|
2004 |
CPU_TEMP_BUF_NLONGS * sizeof(long); |
|
2005 |
frame_size = (frame_size + TCG_TARGET_STACK_ALIGN - 1) & |
|
2006 |
~(TCG_TARGET_STACK_ALIGN - 1); |
|
2007 |
stack_addend = frame_size - push_size; |
|
2014 |
stack_addend = FRAME_SIZE - PUSH_SIZE; |
|
2008 | 2015 |
tcg_set_frame(s, TCG_REG_CALL_STACK, TCG_STATIC_CALL_ARGS_SIZE, |
2009 | 2016 |
CPU_TEMP_BUF_NLONGS * sizeof(long)); |
2010 | 2017 |
|
... | ... | |
2070 | 2077 |
|
2071 | 2078 |
tcg_add_target_add_op_defs(x86_op_defs); |
2072 | 2079 |
} |
2080 |
|
|
2081 |
typedef struct { |
|
2082 |
uint32_t len __attribute__((aligned((sizeof(void *))))); |
|
2083 |
uint32_t id; |
|
2084 |
uint8_t version; |
|
2085 |
char augmentation[1]; |
|
2086 |
uint8_t code_align; |
|
2087 |
uint8_t data_align; |
|
2088 |
uint8_t return_column; |
|
2089 |
} DebugFrameCIE; |
|
2090 |
|
|
2091 |
typedef struct { |
|
2092 |
uint32_t len __attribute__((aligned((sizeof(void *))))); |
|
2093 |
uint32_t cie_offset; |
|
2094 |
tcg_target_long func_start __attribute__((packed)); |
|
2095 |
tcg_target_long func_len __attribute__((packed)); |
|
2096 |
uint8_t def_cfa[4]; |
|
2097 |
uint8_t reg_ofs[14]; |
|
2098 |
} DebugFrameFDE; |
|
2099 |
|
|
2100 |
typedef struct { |
|
2101 |
DebugFrameCIE cie; |
|
2102 |
DebugFrameFDE fde; |
|
2103 |
} DebugFrame; |
|
2104 |
|
|
2105 |
#if TCG_TARGET_REG_BITS == 64 |
|
2106 |
#define ELF_HOST_MACHINE EM_X86_64 |
|
2107 |
static DebugFrame debug_frame = { |
|
2108 |
.cie.len = sizeof(DebugFrameCIE)-4, /* length after .len member */ |
|
2109 |
.cie.id = -1, |
|
2110 |
.cie.version = 1, |
|
2111 |
.cie.code_align = 1, |
|
2112 |
.cie.data_align = 0x78, /* sleb128 -8 */ |
|
2113 |
.cie.return_column = 16, |
|
2114 |
|
|
2115 |
.fde.len = sizeof(DebugFrameFDE)-4, /* length after .len member */ |
|
2116 |
.fde.def_cfa = { |
|
2117 |
12, 7, /* DW_CFA_def_cfa %rsp, ... */ |
|
2118 |
(FRAME_SIZE & 0x7f) | 0x80, /* ... uleb128 FRAME_SIZE */ |
|
2119 |
(FRAME_SIZE >> 7) |
|
2120 |
}, |
|
2121 |
.fde.reg_ofs = { |
|
2122 |
0x90, 1, /* DW_CFA_offset, %rip, -8 */ |
|
2123 |
/* The following ordering must match tcg_target_callee_save_regs. */ |
|
2124 |
0x86, 2, /* DW_CFA_offset, %rbp, -16 */ |
|
2125 |
0x83, 3, /* DW_CFA_offset, %rbx, -24 */ |
|
2126 |
0x8c, 4, /* DW_CFA_offset, %r12, -32 */ |
|
2127 |
0x8d, 5, /* DW_CFA_offset, %r13, -40 */ |
|
2128 |
0x8e, 6, /* DW_CFA_offset, %r14, -48 */ |
|
2129 |
0x8f, 7, /* DW_CFA_offset, %r15, -56 */ |
|
2130 |
} |
|
2131 |
}; |
|
2132 |
#else |
|
2133 |
#define ELF_HOST_MACHINE EM_386 |
|
2134 |
static DebugFrame debug_frame = { |
|
2135 |
.cie.len = sizeof(DebugFrameCIE)-4, /* length after .len member */ |
|
2136 |
.cie.id = -1, |
|
2137 |
.cie.version = 1, |
|
2138 |
.cie.code_align = 1, |
|
2139 |
.cie.data_align = 0x7c, /* sleb128 -4 */ |
|
2140 |
.cie.return_column = 8, |
|
2141 |
|
|
2142 |
.fde.len = sizeof(DebugFrameFDE)-4, /* length after .len member */ |
|
2143 |
.fde.def_cfa = { |
|
2144 |
12, 4, /* DW_CFA_def_cfa %esp, ... */ |
|
2145 |
(FRAME_SIZE & 0x7f) | 0x80, /* ... uleb128 FRAME_SIZE */ |
|
2146 |
(FRAME_SIZE >> 7) |
|
2147 |
}, |
|
2148 |
.fde.reg_ofs = { |
|
2149 |
0x88, 1, /* DW_CFA_offset, %eip, -4 */ |
|
2150 |
/* The following ordering must match tcg_target_callee_save_regs. */ |
|
2151 |
0x85, 2, /* DW_CFA_offset, %ebp, -8 */ |
|
2152 |
0x83, 3, /* DW_CFA_offset, %ebx, -12 */ |
|
2153 |
0x86, 4, /* DW_CFA_offset, %esi, -16 */ |
|
2154 |
0x87, 5, /* DW_CFA_offset, %edi, -20 */ |
|
2155 |
} |
|
2156 |
}; |
|
2157 |
#endif |
|
2158 |
|
|
2159 |
void tcg_register_jit(void *buf, size_t buf_size) |
|
2160 |
{ |
|
2161 |
/* We're expecting a 2 byte uleb128 encoded value. */ |
|
2162 |
assert(FRAME_SIZE >> 14 == 0); |
|
2163 |
|
|
2164 |
debug_frame.fde.func_start = (tcg_target_long) buf; |
|
2165 |
debug_frame.fde.func_len = buf_size; |
|
2166 |
|
|
2167 |
tcg_register_jit_int(buf, buf_size, &debug_frame, sizeof(debug_frame)); |
|
2168 |
} |
b/tcg/tcg.c | ||
---|---|---|
28 | 28 |
|
29 | 29 |
#include "config.h" |
30 | 30 |
|
31 |
/* Define to jump the ELF file used to communicate with GDB. */ |
|
32 |
#undef DEBUG_JIT |
|
33 |
|
|
31 | 34 |
#if !defined(CONFIG_DEBUG_TCG) && !defined(NDEBUG) |
32 | 35 |
/* define it to suppress various consistency checks (faster) */ |
33 | 36 |
#define NDEBUG |
... | ... | |
45 | 48 |
#include "cpu.h" |
46 | 49 |
|
47 | 50 |
#include "tcg-op.h" |
51 |
|
|
52 |
#if TCG_TARGET_REG_BITS == 64 |
|
53 |
# define ELF_CLASS ELFCLASS64 |
|
54 |
#else |
|
55 |
# define ELF_CLASS ELFCLASS32 |
|
56 |
#endif |
|
57 |
#ifdef HOST_WORDS_BIGENDIAN |
|
58 |
# define ELF_DATA ELFDATA2MSB |
|
59 |
#else |
|
60 |
# define ELF_DATA ELFDATA2LSB |
|
61 |
#endif |
|
62 |
|
|
48 | 63 |
#include "elf.h" |
49 | 64 |
|
50 | 65 |
#if defined(CONFIG_USE_GUEST_BASE) && !defined(TCG_TARGET_HAS_GUEST_BASE) |
... | ... | |
57 | 72 |
static void patch_reloc(uint8_t *code_ptr, int type, |
58 | 73 |
tcg_target_long value, tcg_target_long addend); |
59 | 74 |
|
75 |
static void tcg_register_jit_int(void *buf, size_t size, |
|
76 |
void *debug_frame, size_t debug_frame_size) |
|
77 |
__attribute__((unused)); |
|
78 |
|
|
60 | 79 |
/* Forward declarations for functions declared and used in tcg-target.c. */ |
61 | 80 |
static int target_parse_constraint(TCGArgConstraint *ct, const char **pct_str); |
62 | 81 |
static void tcg_out_ld(TCGContext *s, TCGType type, TCGReg ret, TCGReg arg1, |
... | ... | |
2231 | 2250 |
cpu_fprintf(f, "[TCG profiler not compiled]\n"); |
2232 | 2251 |
} |
2233 | 2252 |
#endif |
2253 |
|
|
2254 |
#ifdef ELF_HOST_MACHINE |
|
2255 |
/* The backend should define ELF_HOST_MACHINE to indicate both what value to |
|
2256 |
put into the ELF image and to indicate support for the feature. */ |
|
2257 |
|
|
2258 |
/* Begin GDB interface. THE FOLLOWING MUST MATCH GDB DOCS. */ |
|
2259 |
typedef enum { |
|
2260 |
JIT_NOACTION = 0, |
|
2261 |
JIT_REGISTER_FN, |
|
2262 |
JIT_UNREGISTER_FN |
|
2263 |
} jit_actions_t; |
|
2264 |
|
|
2265 |
struct jit_code_entry { |
|
2266 |
struct jit_code_entry *next_entry; |
|
2267 |
struct jit_code_entry *prev_entry; |
|
2268 |
const void *symfile_addr; |
|
2269 |
uint64_t symfile_size; |
|
2270 |
}; |
|
2271 |
|
|
2272 |
struct jit_descriptor { |
|
2273 |
uint32_t version; |
|
2274 |
uint32_t action_flag; |
|
2275 |
struct jit_code_entry *relevant_entry; |
|
2276 |
struct jit_code_entry *first_entry; |
|
2277 |
}; |
|
2278 |
|
|
2279 |
void __jit_debug_register_code(void) __attribute__((noinline)); |
|
2280 |
void __jit_debug_register_code(void) |
|
2281 |
{ |
|
2282 |
asm(""); |
|
2283 |
} |
|
2284 |
|
|
2285 |
/* Must statically initialize the version, because GDB may check |
|
2286 |
the version before we can set it. */ |
|
2287 |
struct jit_descriptor __jit_debug_descriptor = { 1, 0, 0, 0 }; |
|
2288 |
|
|
2289 |
/* End GDB interface. */ |
|
2290 |
|
|
2291 |
static int find_string(const char *strtab, const char *str) |
|
2292 |
{ |
|
2293 |
const char *p = strtab + 1; |
|
2294 |
|
|
2295 |
while (1) { |
|
2296 |
if (strcmp(p, str) == 0) { |
|
2297 |
return p - strtab; |
|
2298 |
} |
|
2299 |
p += strlen(p) + 1; |
|
2300 |
} |
|
2301 |
} |
|
2302 |
|
|
2303 |
static void tcg_register_jit_int(void *buf, size_t buf_size, |
|
2304 |
void *debug_frame, size_t debug_frame_size) |
|
2305 |
{ |
|
2306 |
static const char strings[64] = |
|
2307 |
"\0" |
|
2308 |
".text\0" |
|
2309 |
".debug_frame\0" |
|
2310 |
".symtab\0" |
|
2311 |
".strtab\0" |
|
2312 |
"code_gen_buffer"; |
|
2313 |
|
|
2314 |
struct ElfImage { |
|
2315 |
ElfW(Ehdr) ehdr; |
|
2316 |
ElfW(Phdr) phdr; |
|
2317 |
ElfW(Shdr) shdr[5]; |
|
2318 |
ElfW(Sym) sym[1]; |
|
2319 |
char str[64]; |
|
2320 |
}; |
|
2321 |
|
|
2322 |
/* We only need a single jit entry; statically allocate it. */ |
|
2323 |
static struct jit_code_entry one_entry; |
|
2324 |
|
|
2325 |
size_t img_size = sizeof(struct ElfImage) + debug_frame_size; |
|
2326 |
struct ElfImage *img = g_malloc0(img_size); |
|
2327 |
|
|
2328 |
img->ehdr.e_ident[EI_MAG0] = ELFMAG0; |
|
2329 |
img->ehdr.e_ident[EI_MAG1] = ELFMAG1; |
|
2330 |
img->ehdr.e_ident[EI_MAG2] = ELFMAG2; |
|
2331 |
img->ehdr.e_ident[EI_MAG3] = ELFMAG3; |
|
2332 |
img->ehdr.e_ident[EI_CLASS] = ELF_CLASS; |
|
2333 |
img->ehdr.e_ident[EI_DATA] = ELF_DATA; |
|
2334 |
img->ehdr.e_ident[EI_VERSION] = EV_CURRENT; |
|
2335 |
img->ehdr.e_type = ET_EXEC; |
|
2336 |
img->ehdr.e_machine = ELF_HOST_MACHINE; |
|
2337 |
img->ehdr.e_version = EV_CURRENT; |
|
2338 |
img->ehdr.e_phoff = offsetof(struct ElfImage, phdr); |
|
2339 |
img->ehdr.e_shoff = offsetof(struct ElfImage, shdr); |
|
2340 |
img->ehdr.e_ehsize = sizeof(ElfW(Shdr)); |
|
2341 |
img->ehdr.e_phentsize = sizeof(ElfW(Phdr)); |
|
2342 |
img->ehdr.e_phnum = 1; |
|
2343 |
img->ehdr.e_shentsize = sizeof(img->shdr[0]); |
|
2344 |
img->ehdr.e_shnum = ARRAY_SIZE(img->shdr); |
|
2345 |
img->ehdr.e_shstrndx = ARRAY_SIZE(img->shdr) - 1; |
|
2346 |
|
|
2347 |
img->phdr.p_type = PT_LOAD; |
|
2348 |
img->phdr.p_offset = (char *)buf - (char *)img; |
|
2349 |
img->phdr.p_vaddr = (ElfW(Addr))buf; |
|
2350 |
img->phdr.p_paddr = img->phdr.p_vaddr; |
|
2351 |
img->phdr.p_filesz = 0; |
|
2352 |
img->phdr.p_memsz = buf_size; |
|
2353 |
img->phdr.p_flags = PF_X; |
|
2354 |
|
|
2355 |
memcpy(img->str, strings, sizeof(img->str)); |
|
2356 |
|
|
2357 |
img->shdr[0].sh_type = SHT_NULL; |
|
2358 |
|
|
2359 |
/* Trick: The contents of code_gen_buffer are not present in this fake |
|
2360 |
ELF file; that got allocated elsewhere, discontiguously. Therefore |
|
2361 |
we mark .text as SHT_NOBITS (similar to .bss) so that readers will |
|
2362 |
not look for contents. We can record any address at will. */ |
|
2363 |
img->shdr[1].sh_name = find_string(img->str, ".text"); |
|
2364 |
img->shdr[1].sh_type = SHT_NOBITS; |
|
2365 |
img->shdr[1].sh_flags = SHF_EXECINSTR | SHF_ALLOC; |
|
2366 |
img->shdr[1].sh_addr = (ElfW(Addr))buf; |
|
2367 |
img->shdr[1].sh_size = buf_size; |
|
2368 |
|
|
2369 |
img->shdr[2].sh_name = find_string(img->str, ".debug_frame"); |
|
2370 |
img->shdr[2].sh_type = SHT_PROGBITS; |
|
2371 |
img->shdr[2].sh_offset = sizeof(*img); |
|
2372 |
img->shdr[2].sh_size = debug_frame_size; |
|
2373 |
memcpy(img + 1, debug_frame, debug_frame_size); |
|
2374 |
|
|
2375 |
img->shdr[3].sh_name = find_string(img->str, ".symtab"); |
|
2376 |
img->shdr[3].sh_type = SHT_SYMTAB; |
|
2377 |
img->shdr[3].sh_offset = offsetof(struct ElfImage, sym); |
|
2378 |
img->shdr[3].sh_size = sizeof(img->sym); |
|
2379 |
img->shdr[3].sh_info = ARRAY_SIZE(img->sym); |
|
2380 |
img->shdr[3].sh_link = img->ehdr.e_shstrndx; |
|
2381 |
img->shdr[3].sh_entsize = sizeof(ElfW(Sym)); |
|
2382 |
|
|
2383 |
img->shdr[4].sh_name = find_string(img->str, ".strtab"); |
|
2384 |
img->shdr[4].sh_type = SHT_STRTAB; |
|
2385 |
img->shdr[4].sh_offset = offsetof(struct ElfImage, str); |
|
2386 |
img->shdr[4].sh_size = sizeof(img->str); |
|
2387 |
|
|
2388 |
img->sym[0].st_name = find_string(img->str, "code_gen_buffer"); |
|
2389 |
img->sym[0].st_info = ELF_ST_INFO(STB_GLOBAL, STT_FUNC); |
|
2390 |
img->sym[0].st_shndx = 1; |
|
2391 |
img->sym[0].st_value = (ElfW(Addr))buf; |
|
2392 |
img->sym[0].st_size = buf_size; |
|
2393 |
|
|
2394 |
#ifdef DEBUG_JIT |
|
2395 |
/* Enable this block to be able to debug the ELF image file creation. |
|
2396 |
One can use readelf, objdump, or other inspection utilities. */ |
|
2397 |
{ |
|
2398 |
FILE *f = fopen("/tmp/qemu.jit", "w+b"); |
|
2399 |
if (f) { |
|
2400 |
if (fwrite(img, img_size, 1, f) != buf_size) { |
|
2401 |
/* Avoid stupid unused return value warning for fwrite. */ |
|
2402 |
} |
|
2403 |
fclose(f); |
|
2404 |
} |
|
2405 |
} |
|
2406 |
#endif |
|
2407 |
|
|
2408 |
one_entry.symfile_addr = img; |
|
2409 |
one_entry.symfile_size = img_size; |
|
2410 |
|
|
2411 |
__jit_debug_descriptor.action_flag = JIT_REGISTER_FN; |
|
2412 |
__jit_debug_descriptor.relevant_entry = &one_entry; |
|
2413 |
__jit_debug_descriptor.first_entry = &one_entry; |
|
2414 |
__jit_debug_register_code(); |
|
2415 |
} |
|
2416 |
#else |
|
2417 |
/* No support for the feature. Provide the entry point expected by exec.c. */ |
|
2418 |
|
|
2419 |
static void tcg_register_jit_int(void *buf, size_t size, |
|
2420 |
void *debug_frame, size_t debug_frame_size) |
|
2421 |
{ |
|
2422 |
} |
|
2423 |
|
|
2424 |
void tcg_register_jit(void *buf, size_t buf_size) |
|
2425 |
{ |
|
2426 |
} |
|
2427 |
#endif /* ELF_HOST_MACHINE */ |
b/tcg/tcg.h | ||
---|---|---|
586 | 586 |
# define tcg_qemu_tb_exec(env, tb_ptr) \ |
587 | 587 |
((tcg_target_ulong (*)(void *, void *))code_gen_prologue)(env, tb_ptr) |
588 | 588 |
#endif |
589 |
|
|
590 |
void tcg_register_jit(void *buf, size_t buf_size); |
Also available in: Unified diff