Revision 813da627 tcg/tcg.c
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 */ |
Also available in: Unified diff