From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([208.118.235.92]:37429) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1SBUOU-0002cT-Bf for qemu-devel@nongnu.org; Sat, 24 Mar 2012 13:04:50 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1SBUOR-0007uD-9e for qemu-devel@nongnu.org; Sat, 24 Mar 2012 13:04:45 -0400 Received: from mail-iy0-f173.google.com ([209.85.210.173]:41474) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1SBUOR-0007u7-1c for qemu-devel@nongnu.org; Sat, 24 Mar 2012 13:04:43 -0400 Received: by iafj26 with SMTP id j26so7278262iaf.4 for ; Sat, 24 Mar 2012 10:04:41 -0700 (PDT) MIME-Version: 1.0 In-Reply-To: References: <1332185111-20739-1-git-send-email-rth@twiddle.net> <1332185111-20739-2-git-send-email-rth@twiddle.net> Date: Sat, 24 Mar 2012 17:04:40 +0000 Message-ID: From: Peter Maydell Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: quoted-printable Subject: Re: [Qemu-devel] [PATCH] tcg: Use the GDB JIT debugging interface. List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: Blue Swirl Cc: qemu-devel@nongnu.org, Richard Henderson Er, this is the v2 patch, which Richard updated based on review comments, can you apply the later v3 one instead? thanks -- PMM On 24 March 2012 16:11, Blue Swirl wrote: > Thanks, applied. > > On Mon, Mar 19, 2012 at 19:25, Richard Henderson wrote: >> This allows us to generate unwind info for the dynamicly generated >> code in the code_gen_buffer. =C2=A0Only i386 is converted at this point. >> >> Signed-off-by: Richard Henderson >> --- >> =C2=A0elf.h =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 | = =C2=A0 =C2=A01 + >> =C2=A0exec.c =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0| = =C2=A0 =C2=A01 + >> =C2=A0tcg/i386/tcg-target.c | =C2=A0114 ++++++++++++++++++++++++++-- >> =C2=A0tcg/tcg.c =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 | =C2=A0194 ++= +++++++++++++++++++++++++++++++++++++++++++++++ >> =C2=A0tcg/tcg.h =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 | =C2=A0 =C2= =A02 + >> =C2=A05 files changed, 303 insertions(+), 9 deletions(-) >> >> diff --git a/elf.h b/elf.h >> index 2e05d34..310e05a 100644 >> --- a/elf.h >> +++ b/elf.h >> @@ -216,6 +216,7 @@ typedef int64_t =C2=A0Elf64_Sxword; >> >> =C2=A0#define ELF_ST_BIND(x) =C2=A0 =C2=A0 =C2=A0 =C2=A0 ((x) >> 4) >> =C2=A0#define ELF_ST_TYPE(x) =C2=A0 =C2=A0 =C2=A0 =C2=A0 (((unsigned int= ) x) & 0xf) >> +#define ELF_ST_INFO(bind, type) (((bind) << 4) | ((type) & 0xf)) >> =C2=A0#define ELF32_ST_BIND(x) =C2=A0 =C2=A0 =C2=A0 ELF_ST_BIND(x) >> =C2=A0#define ELF32_ST_TYPE(x) =C2=A0 =C2=A0 =C2=A0 ELF_ST_TYPE(x) >> =C2=A0#define ELF64_ST_BIND(x) =C2=A0 =C2=A0 =C2=A0 ELF_ST_BIND(x) >> diff --git a/exec.c b/exec.c >> index be392e2..dd24939 100644 >> --- a/exec.c >> +++ b/exec.c >> @@ -636,6 +636,7 @@ void tcg_exec_init(unsigned long tb_size) >> =C2=A0 =C2=A0 cpu_gen_init(); >> =C2=A0 =C2=A0 code_gen_alloc(tb_size); >> =C2=A0 =C2=A0 code_gen_ptr =3D code_gen_buffer; >> + =C2=A0 =C2=A0tcg_register_jit(code_gen_buffer, code_gen_buffer_size); >> =C2=A0 =C2=A0 page_init(); >> =C2=A0#if !defined(CONFIG_USER_ONLY) || !defined(CONFIG_USE_GUEST_BASE) >> =C2=A0 =C2=A0 /* There's no guest base to take into account, so go ahead= and >> diff --git a/tcg/i386/tcg-target.c b/tcg/i386/tcg-target.c >> index 43a51a1..871a7e7 100644 >> --- a/tcg/i386/tcg-target.c >> +++ b/tcg/i386/tcg-target.c >> @@ -1989,22 +1989,29 @@ static int tcg_target_callee_save_regs[] =3D { >> =C2=A0#endif >> =C2=A0}; >> >> +/* Compute frame size via macros, to share between tcg_target_qemu_prol= ogue >> + =C2=A0 and tcg_register_jit. =C2=A0*/ >> + >> +#define PUSH_SIZE \ >> + =C2=A0 =C2=A0((1 + ARRAY_SIZE(tcg_target_callee_save_regs)) \ >> + =C2=A0 =C2=A0 * (TCG_TARGET_REG_BITS / 8)) >> + >> +#define FRAME_SIZE \ >> + =C2=A0 =C2=A0((PUSH_SIZE \ >> + =C2=A0 =C2=A0 =C2=A0+ TCG_STATIC_CALL_ARGS_SIZE \ >> + =C2=A0 =C2=A0 =C2=A0+ CPU_TEMP_BUF_NLONGS * sizeof(long) \ >> + =C2=A0 =C2=A0 =C2=A0+ TCG_TARGET_STACK_ALIGN - 1) \ >> + =C2=A0 =C2=A0 & ~(TCG_TARGET_STACK_ALIGN - 1)) >> + >> =C2=A0/* Generate global QEMU prologue and epilogue code */ >> =C2=A0static void tcg_target_qemu_prologue(TCGContext *s) >> =C2=A0{ >> - =C2=A0 =C2=A0int i, frame_size, push_size, stack_addend; >> + =C2=A0 =C2=A0int i, stack_addend; >> >> =C2=A0 =C2=A0 /* TB prologue */ >> >> =C2=A0 =C2=A0 /* Reserve some stack space, also for TCG temps. =C2=A0*/ >> - =C2=A0 =C2=A0push_size =3D 1 + ARRAY_SIZE(tcg_target_callee_save_regs)= ; >> - =C2=A0 =C2=A0push_size *=3D TCG_TARGET_REG_BITS / 8; >> - >> - =C2=A0 =C2=A0frame_size =3D push_size + TCG_STATIC_CALL_ARGS_SIZE + >> - =C2=A0 =C2=A0 =C2=A0 =C2=A0CPU_TEMP_BUF_NLONGS * sizeof(long); >> - =C2=A0 =C2=A0frame_size =3D (frame_size + TCG_TARGET_STACK_ALIGN - 1) = & >> - =C2=A0 =C2=A0 =C2=A0 =C2=A0~(TCG_TARGET_STACK_ALIGN - 1); >> - =C2=A0 =C2=A0stack_addend =3D frame_size - push_size; >> + =C2=A0 =C2=A0stack_addend =3D FRAME_SIZE - PUSH_SIZE; >> =C2=A0 =C2=A0 tcg_set_frame(s, TCG_REG_CALL_STACK, TCG_STATIC_CALL_ARGS_= SIZE, >> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 CPU_TEMP_= BUF_NLONGS * sizeof(long)); >> >> @@ -2070,3 +2077,92 @@ static void tcg_target_init(TCGContext *s) >> >> =C2=A0 =C2=A0 tcg_add_target_add_op_defs(x86_op_defs); >> =C2=A0} >> + >> +typedef struct { >> + =C2=A0 =C2=A0uint32_t len __attribute__((aligned((sizeof(void *))))); >> + =C2=A0 =C2=A0uint32_t id; >> + =C2=A0 =C2=A0uint8_t version; >> + =C2=A0 =C2=A0char augmentation[1]; >> + =C2=A0 =C2=A0uint8_t code_align; >> + =C2=A0 =C2=A0uint8_t data_align; >> + =C2=A0 =C2=A0uint8_t return_column; >> +} DebugFrameCIE; >> + >> +typedef struct { >> + =C2=A0 =C2=A0uint32_t len __attribute__((aligned((sizeof(void *))))); >> + =C2=A0 =C2=A0uint32_t cie_offset; >> + =C2=A0 =C2=A0tcg_target_long func_start __attribute__((packed)); >> + =C2=A0 =C2=A0tcg_target_long func_len __attribute__((packed)); >> + =C2=A0 =C2=A0uint8_t def_cfa[4]; >> + =C2=A0 =C2=A0uint8_t reg_ofs[14]; >> +} DebugFrameFDE; >> + >> +typedef struct { >> + =C2=A0 =C2=A0DebugFrameCIE cie; >> + =C2=A0 =C2=A0DebugFrameFDE fde; >> +} DebugFrame; >> + >> +#if TCG_TARGET_REG_BITS =3D=3D 64 >> +#define ELF_HOST_MACHINE EM_X86_64 >> +static DebugFrame debug_frame =3D { >> + =C2=A0 =C2=A0.cie.len =3D sizeof(DebugFrameCIE)-4, /* length after .le= n member */ >> + =C2=A0 =C2=A0.cie.id =3D -1, >> + =C2=A0 =C2=A0.cie.version =3D 1, >> + =C2=A0 =C2=A0.cie.code_align =3D 1, >> + =C2=A0 =C2=A0.cie.data_align =3D 0x78, =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 /* sleb128 -8 */ >> + =C2=A0 =C2=A0.cie.return_column =3D 16, >> + >> + =C2=A0 =C2=A0.fde.len =3D sizeof(DebugFrameFDE)-4, /* length after .le= n member */ >> + =C2=A0 =C2=A0.fde.def_cfa =3D { >> + =C2=A0 =C2=A0 =C2=A0 =C2=A012, 7, =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0/* DW_CFA_def_cfa %r= sp, ... */ >> + =C2=A0 =C2=A0 =C2=A0 =C2=A0(FRAME_SIZE & 0x7f) | 0x80, =C2=A0 =C2=A0 /= * ... uleb128 FRAME_SIZE */ >> + =C2=A0 =C2=A0 =C2=A0 =C2=A0(FRAME_SIZE >> 7) >> + =C2=A0 =C2=A0}, >> + =C2=A0 =C2=A0.fde.reg_ofs =3D { >> + =C2=A0 =C2=A0 =C2=A0 =C2=A00x90, 1, =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0/* DW_CFA_offset, %rip, -8= */ >> + =C2=A0 =C2=A0 =C2=A0 =C2=A0/* The following ordering must match tcg_ta= rget_callee_save_regs. =C2=A0*/ >> + =C2=A0 =C2=A0 =C2=A0 =C2=A00x86, 2, =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0/* DW_CFA_offset, %rbp, -1= 6 */ >> + =C2=A0 =C2=A0 =C2=A0 =C2=A00x83, 3, =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0/* DW_CFA_offset, %rbx, -2= 4 */ >> + =C2=A0 =C2=A0 =C2=A0 =C2=A00x8c, 4, =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0/* DW_CFA_offset, %r12, -3= 2 */ >> + =C2=A0 =C2=A0 =C2=A0 =C2=A00x8d, 5, =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0/* DW_CFA_offset, %r13, -4= 0 */ >> + =C2=A0 =C2=A0 =C2=A0 =C2=A00x8e, 6, =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0/* DW_CFA_offset, %r14, -4= 8 */ >> + =C2=A0 =C2=A0 =C2=A0 =C2=A00x8f, 7, =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0/* DW_CFA_offset, %r15, -5= 6 */ >> + =C2=A0 =C2=A0} >> +}; >> +#else >> +#define ELF_HOST_MACHINE EM_386 >> +static DebugFrame debug_frame =3D { >> + =C2=A0 =C2=A0.cie.len =3D sizeof(DebugFrameCIE)-4, /* length after .le= n member */ >> + =C2=A0 =C2=A0.cie.id =3D -1, >> + =C2=A0 =C2=A0.cie.version =3D 1, >> + =C2=A0 =C2=A0.cie.code_align =3D 1, >> + =C2=A0 =C2=A0.cie.data_align =3D 0x7c, =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 /* sleb128 -4 */ >> + =C2=A0 =C2=A0.cie.return_column =3D 8, >> + >> + =C2=A0 =C2=A0.fde.len =3D sizeof(DebugFrameFDE)-4, /* length after .le= n member */ >> + =C2=A0 =C2=A0.fde.def_cfa =3D { >> + =C2=A0 =C2=A0 =C2=A0 =C2=A012, 4, =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0/* DW_CFA_def_cfa %e= sp, ... */ >> + =C2=A0 =C2=A0 =C2=A0 =C2=A0(FRAME_SIZE & 0x7f) | 0x80, =C2=A0 =C2=A0 /= * ... uleb128 FRAME_SIZE */ >> + =C2=A0 =C2=A0 =C2=A0 =C2=A0(FRAME_SIZE >> 7) >> + =C2=A0 =C2=A0}, >> + =C2=A0 =C2=A0.fde.reg_ofs =3D { >> + =C2=A0 =C2=A0 =C2=A0 =C2=A00x88, 1, =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0/* DW_CFA_offset, %eip, -4= */ >> + =C2=A0 =C2=A0 =C2=A0 =C2=A0/* The following ordering must match tcg_ta= rget_callee_save_regs. =C2=A0*/ >> + =C2=A0 =C2=A0 =C2=A0 =C2=A00x85, 2, =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0/* DW_CFA_offset, %ebp, -8= */ >> + =C2=A0 =C2=A0 =C2=A0 =C2=A00x83, 3, =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0/* DW_CFA_offset, %ebx, -1= 2 */ >> + =C2=A0 =C2=A0 =C2=A0 =C2=A00x86, 4, =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0/* DW_CFA_offset, %esi, -1= 6 */ >> + =C2=A0 =C2=A0 =C2=A0 =C2=A00x87, 5, =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0/* DW_CFA_offset, %edi, -2= 0 */ >> + =C2=A0 =C2=A0} >> +}; >> +#endif >> + >> +void tcg_register_jit(void *buf, size_t buf_size) >> +{ >> + =C2=A0 =C2=A0/* We're expecting a 2 byte uleb128 encoded value. =C2=A0= */ >> + =C2=A0 =C2=A0assert(FRAME_SIZE >> 14 =3D=3D 0); >> + >> + =C2=A0 =C2=A0debug_frame.fde.func_start =3D (tcg_target_long) buf; >> + =C2=A0 =C2=A0debug_frame.fde.func_len =3D buf_size; >> + >> + =C2=A0 =C2=A0tcg_register_jit_int(buf, buf_size, &debug_frame, sizeof(= debug_frame)); >> +} >> diff --git a/tcg/tcg.c b/tcg/tcg.c >> index ccfcd1a..eb595ce 100644 >> --- a/tcg/tcg.c >> +++ b/tcg/tcg.c >> @@ -28,6 +28,9 @@ >> >> =C2=A0#include "config.h" >> >> +/* Define to jump the ELF file used to communicate with GDB. =C2=A0*/ >> +#undef DEBUG_JIT >> + >> =C2=A0#if !defined(CONFIG_DEBUG_TCG) && !defined(NDEBUG) >> =C2=A0/* define it to suppress various consistency checks (faster) */ >> =C2=A0#define NDEBUG >> @@ -45,6 +48,18 @@ >> =C2=A0#include "cpu.h" >> >> =C2=A0#include "tcg-op.h" >> + >> +#if TCG_TARGET_REG_BITS =3D=3D 64 >> +# define ELF_CLASS =C2=A0ELFCLASS64 >> +#else >> +# define ELF_CLASS =C2=A0ELFCLASS32 >> +#endif >> +#ifdef HOST_WORDS_BIGENDIAN >> +# define ELF_DATA =C2=A0 ELFDATA2MSB >> +#else >> +# define ELF_DATA =C2=A0 ELFDATA2LSB >> +#endif >> + >> =C2=A0#include "elf.h" >> >> =C2=A0#if defined(CONFIG_USE_GUEST_BASE) && !defined(TCG_TARGET_HAS_GUES= T_BASE) >> @@ -57,6 +72,10 @@ static void tcg_target_qemu_prologue(TCGContext *s); >> =C2=A0static void patch_reloc(uint8_t *code_ptr, int type, >> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 tcg_target_long value, tcg_target_long addend); >> >> +static void tcg_register_jit_int(void *buf, size_t size, >> + =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 void *debug_frame, size_t debug_f= rame_size) >> + =C2=A0 =C2=A0__attribute__((unused)); >> + >> =C2=A0/* Forward declarations for functions declared and used in tcg-tar= get.c. */ >> =C2=A0static int target_parse_constraint(TCGArgConstraint *ct, const cha= r **pct_str); >> =C2=A0static void tcg_out_ld(TCGContext *s, TCGType type, TCGReg ret, TC= GReg arg1, >> @@ -2231,3 +2250,178 @@ void tcg_dump_info(FILE *f, fprintf_function cpu= _fprintf) >> =C2=A0 =C2=A0 cpu_fprintf(f, "[TCG profiler not compiled]\n"); >> =C2=A0} >> =C2=A0#endif >> + >> +#ifdef ELF_HOST_MACHINE >> +/* The backend should define ELF_HOST_MACHINE to indicate both what val= ue to >> + =C2=A0 put into the ELF image and to indicate support for the feature.= =C2=A0*/ >> + >> +/* Begin GDB interface. =C2=A0THE FOLLOWING MUST MATCH GDB DOCS. =C2=A0= */ >> +typedef enum { >> + =C2=A0 =C2=A0JIT_NOACTION =3D 0, >> + =C2=A0 =C2=A0JIT_REGISTER_FN, >> + =C2=A0 =C2=A0JIT_UNREGISTER_FN >> +} jit_actions_t; >> + >> +struct jit_code_entry { >> + =C2=A0 =C2=A0struct jit_code_entry *next_entry; >> + =C2=A0 =C2=A0struct jit_code_entry *prev_entry; >> + =C2=A0 =C2=A0const void *symfile_addr; >> + =C2=A0 =C2=A0uint64_t symfile_size; >> +}; >> + >> +struct jit_descriptor { >> + =C2=A0 =C2=A0uint32_t version; >> + =C2=A0 =C2=A0uint32_t action_flag; >> + =C2=A0 =C2=A0struct jit_code_entry *relevant_entry; >> + =C2=A0 =C2=A0struct jit_code_entry *first_entry; >> +}; >> + >> +void __jit_debug_register_code(void) __attribute__((noinline)); >> +void __jit_debug_register_code(void) >> +{ >> + =C2=A0 =C2=A0asm(""); >> +} >> + >> +/* Must statically initialize the version, because GDB may check >> + =C2=A0 the version before we can set it. =C2=A0*/ >> +struct jit_descriptor __jit_debug_descriptor =3D { 1, 0, 0, 0 }; >> + >> +/* End GDB interface. =C2=A0*/ >> + >> +static int find_string(const char *strtab, const char *str) >> +{ >> + =C2=A0 =C2=A0const char *p =3D strtab + 1; >> + >> + =C2=A0 =C2=A0while (1) { >> + =C2=A0 =C2=A0 =C2=A0 =C2=A0if (strcmp(p, str) =3D=3D 0) { >> + =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0return p - strtab; >> + =C2=A0 =C2=A0 =C2=A0 =C2=A0} >> + =C2=A0 =C2=A0 =C2=A0 =C2=A0p +=3D strlen(p) + 1; >> + =C2=A0 =C2=A0} >> +} >> + >> +static void tcg_register_jit_int(void *buf, size_t buf_size, >> + =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 void *debug_frame, size_t debug_f= rame_size) >> +{ >> + =C2=A0 =C2=A0static const char strings[64] =3D >> + =C2=A0 =C2=A0 =C2=A0 =C2=A0"\0" >> + =C2=A0 =C2=A0 =C2=A0 =C2=A0".text\0" >> + =C2=A0 =C2=A0 =C2=A0 =C2=A0".debug_frame\0" >> + =C2=A0 =C2=A0 =C2=A0 =C2=A0".symtab\0" >> + =C2=A0 =C2=A0 =C2=A0 =C2=A0".strtab\0" >> + =C2=A0 =C2=A0 =C2=A0 =C2=A0"code_gen_buffer"; >> + >> + =C2=A0 =C2=A0struct ElfImage { >> + =C2=A0 =C2=A0 =C2=A0 =C2=A0ElfW(Ehdr) ehdr; >> + =C2=A0 =C2=A0 =C2=A0 =C2=A0ElfW(Phdr) phdr; >> + =C2=A0 =C2=A0 =C2=A0 =C2=A0ElfW(Shdr) shdr[5]; >> + =C2=A0 =C2=A0 =C2=A0 =C2=A0ElfW(Sym) =C2=A0sym[1]; >> + =C2=A0 =C2=A0 =C2=A0 =C2=A0char =C2=A0 =C2=A0 =C2=A0 str[64]; >> + =C2=A0 =C2=A0}; >> + >> + =C2=A0 =C2=A0/* We only need a single jit entry; statically allocate i= t. =C2=A0*/ >> + =C2=A0 =C2=A0static struct jit_code_entry one_entry; >> + >> + =C2=A0 =C2=A0size_t img_size =3D sizeof(struct ElfImage) + debug_frame= _size; >> + =C2=A0 =C2=A0struct ElfImage *img =3D g_malloc0(img_size); >> + >> + =C2=A0 =C2=A0img->ehdr.e_ident[EI_MAG0] =3D ELFMAG0; >> + =C2=A0 =C2=A0img->ehdr.e_ident[EI_MAG1] =3D ELFMAG1; >> + =C2=A0 =C2=A0img->ehdr.e_ident[EI_MAG2] =3D ELFMAG2; >> + =C2=A0 =C2=A0img->ehdr.e_ident[EI_MAG3] =3D ELFMAG3; >> + =C2=A0 =C2=A0img->ehdr.e_ident[EI_CLASS] =3D ELF_CLASS; >> + =C2=A0 =C2=A0img->ehdr.e_ident[EI_DATA] =3D ELF_DATA; >> + =C2=A0 =C2=A0img->ehdr.e_ident[EI_VERSION] =3D EV_CURRENT; >> + =C2=A0 =C2=A0img->ehdr.e_type =3D ET_EXEC; >> + =C2=A0 =C2=A0img->ehdr.e_machine =3D ELF_HOST_MACHINE; >> + =C2=A0 =C2=A0img->ehdr.e_version =3D EV_CURRENT; >> + =C2=A0 =C2=A0img->ehdr.e_phoff =3D offsetof(struct ElfImage, phdr); >> + =C2=A0 =C2=A0img->ehdr.e_shoff =3D offsetof(struct ElfImage, shdr); >> + =C2=A0 =C2=A0img->ehdr.e_ehsize =3D sizeof(ElfW(Shdr)); >> + =C2=A0 =C2=A0img->ehdr.e_phentsize =3D sizeof(ElfW(Phdr)); >> + =C2=A0 =C2=A0img->ehdr.e_phnum =3D 1; >> + =C2=A0 =C2=A0img->ehdr.e_shentsize =3D sizeof(img->shdr[0]); >> + =C2=A0 =C2=A0img->ehdr.e_shnum =3D ARRAY_SIZE(img->shdr); >> + =C2=A0 =C2=A0img->ehdr.e_shstrndx =3D ARRAY_SIZE(img->shdr) - 1; >> + >> + =C2=A0 =C2=A0img->phdr.p_type =3D PT_LOAD; >> + =C2=A0 =C2=A0img->phdr.p_offset =3D (char *)buf - (char *)img; >> + =C2=A0 =C2=A0img->phdr.p_vaddr =3D (ElfW(Addr))buf; >> + =C2=A0 =C2=A0img->phdr.p_paddr =3D img->phdr.p_vaddr; >> + =C2=A0 =C2=A0img->phdr.p_filesz =3D 0; >> + =C2=A0 =C2=A0img->phdr.p_memsz =3D buf_size; >> + =C2=A0 =C2=A0img->phdr.p_flags =3D PF_X; >> + >> + =C2=A0 =C2=A0memcpy(img->str, strings, sizeof(img->str)); >> + >> + =C2=A0 =C2=A0img->shdr[0].sh_type =3D SHT_NULL; >> + >> + =C2=A0 =C2=A0/* Trick: The contents of code_gen_buffer are not present= in this fake >> + =C2=A0 =C2=A0 =C2=A0 ELF file; that got allocated elsewhere, discontig= uously. =C2=A0Therefore >> + =C2=A0 =C2=A0 =C2=A0 we mark .text as SHT_NOBITS (similar to .bss) so = that readers will >> + =C2=A0 =C2=A0 =C2=A0 not look for contents. =C2=A0We can record any ad= dress at will. =C2=A0*/ >> + =C2=A0 =C2=A0img->shdr[1].sh_name =3D find_string(img->str, ".text"); >> + =C2=A0 =C2=A0img->shdr[1].sh_type =3D SHT_NOBITS; >> + =C2=A0 =C2=A0img->shdr[1].sh_flags =3D SHF_EXECINSTR | SHF_ALLOC; >> + =C2=A0 =C2=A0img->shdr[1].sh_addr =3D (ElfW(Addr))buf; >> + =C2=A0 =C2=A0img->shdr[1].sh_size =3D buf_size; >> + >> + =C2=A0 =C2=A0img->shdr[2].sh_name =3D find_string(img->str, ".debug_fr= ame"); >> + =C2=A0 =C2=A0img->shdr[2].sh_type =3D SHT_PROGBITS; >> + =C2=A0 =C2=A0img->shdr[2].sh_offset =3D sizeof(*img); >> + =C2=A0 =C2=A0img->shdr[2].sh_size =3D debug_frame_size; >> + =C2=A0 =C2=A0memcpy(img + 1, debug_frame, debug_frame_size); >> + >> + =C2=A0 =C2=A0img->shdr[3].sh_name =3D find_string(img->str, ".symtab")= ; >> + =C2=A0 =C2=A0img->shdr[3].sh_type =3D SHT_SYMTAB; >> + =C2=A0 =C2=A0img->shdr[3].sh_offset =3D offsetof(struct ElfImage, sym)= ; >> + =C2=A0 =C2=A0img->shdr[3].sh_size =3D sizeof(img->sym); >> + =C2=A0 =C2=A0img->shdr[3].sh_info =3D ARRAY_SIZE(img->sym); >> + =C2=A0 =C2=A0img->shdr[3].sh_link =3D img->ehdr.e_shstrndx; >> + =C2=A0 =C2=A0img->shdr[3].sh_entsize =3D sizeof(ElfW(Sym)); >> + >> + =C2=A0 =C2=A0img->shdr[4].sh_name =3D find_string(img->str, ".strtab")= ; >> + =C2=A0 =C2=A0img->shdr[4].sh_type =3D SHT_STRTAB; >> + =C2=A0 =C2=A0img->shdr[4].sh_offset =3D offsetof(struct ElfImage, str)= ; >> + =C2=A0 =C2=A0img->shdr[4].sh_size =3D sizeof(img->str); >> + >> + =C2=A0 =C2=A0img->sym[0].st_name =3D find_string(img->str, "code_gen_b= uffer"); >> + =C2=A0 =C2=A0img->sym[0].st_info =3D ELF_ST_INFO(STB_GLOBAL, STT_FUNC)= ; >> + =C2=A0 =C2=A0img->sym[0].st_shndx =3D 1; >> + =C2=A0 =C2=A0img->sym[0].st_value =3D (ElfW(Addr))buf; >> + =C2=A0 =C2=A0img->sym[0].st_size =3D buf_size; >> + >> +#ifdef DEBUG_JIT >> + =C2=A0 =C2=A0/* Enable this block to be able to debug the ELF image fi= le creation. >> + =C2=A0 =C2=A0 =C2=A0 One can use readelf, objdump, or other inspection= utilities. =C2=A0*/ >> + =C2=A0 =C2=A0{ >> + =C2=A0 =C2=A0 =C2=A0 =C2=A0FILE *f =3D fopen("/tmp/qemu.jit", "w+b"); >> + =C2=A0 =C2=A0 =C2=A0 =C2=A0if (f) { >> + =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0if (fwrite(img, img_size, 1, = f) !=3D buf_size) { >> + =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0/* Avoid stupid= unused return value warning for fwrite. =C2=A0*/ >> + =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0} >> + =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0fclose(f); >> + =C2=A0 =C2=A0 =C2=A0 =C2=A0} >> + =C2=A0 =C2=A0} >> +#endif >> + >> + =C2=A0 =C2=A0one_entry.symfile_addr =3D img; >> + =C2=A0 =C2=A0one_entry.symfile_size =3D img_size; >> + >> + =C2=A0 =C2=A0__jit_debug_descriptor.action_flag =3D JIT_REGISTER_FN; >> + =C2=A0 =C2=A0__jit_debug_descriptor.relevant_entry =3D &one_entry; >> + =C2=A0 =C2=A0__jit_debug_descriptor.first_entry =3D &one_entry; >> + =C2=A0 =C2=A0__jit_debug_register_code(); >> +} >> +#else >> +/* No support for the feature. =C2=A0Provide the entry point expected b= y exec.c. =C2=A0*/ >> + >> +static void tcg_register_jit_int(void *buf, size_t size, >> + =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 void *debug_frame, size_t debug_f= rame_size) >> +{ >> +} >> + >> +void tcg_register_jit(void *buf, size_t buf_size) >> +{ >> +} >> +#endif /* ELF_HOST_MACHINE */ >> diff --git a/tcg/tcg.h b/tcg/tcg.h >> index 5f6c647..a83bddd 100644 >> --- a/tcg/tcg.h >> +++ b/tcg/tcg.h >> @@ -586,3 +586,5 @@ extern uint8_t code_gen_prologue[]; >> =C2=A0# define tcg_qemu_tb_exec(env, tb_ptr) \ >> =C2=A0 =C2=A0 ((tcg_target_ulong (*)(void *, void *))code_gen_prologue)(= env, tb_ptr) >> =C2=A0#endif >> + >> +void tcg_register_jit(void *buf, size_t buf_size); >> -- >> 1.7.7.6 >> >> > --=20 123456789012345678901234567890123456789012345678901234567890123456789012345= 67890 =C2=A0 =C2=A0 =C2=A0 =C2=A0=C2=A0 1 =C2=A0 =C2=A0 =C2=A0 =C2=A0 2 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 3 =C2=A0 =C2=A0 =C2=A0 =C2=A0 4 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 5 =C2=A0 =C2=A0 =C2=A0 =C2=A0 6 =C2=A0 =C2=A0 =C2=A0 =C2=A0 7 =C2=A0= =C2=A0 =C2=A0 =C2=A0 8