From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([208.118.235.92]:42047) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1SBTZl-0001uB-9T for qemu-devel@nongnu.org; Sat, 24 Mar 2012 12:12:23 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1SBTZi-0006dS-I7 for qemu-devel@nongnu.org; Sat, 24 Mar 2012 12:12:20 -0400 Received: from mail-iy0-f173.google.com ([209.85.210.173]:33320) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1SBTZi-0006HZ-9X for qemu-devel@nongnu.org; Sat, 24 Mar 2012 12:12:18 -0400 Received: by mail-iy0-f173.google.com with SMTP id j26so7213492iaf.4 for ; Sat, 24 Mar 2012 09:12:17 -0700 (PDT) MIME-Version: 1.0 In-Reply-To: <1332185111-20739-2-git-send-email-rth@twiddle.net> References: <1332185111-20739-1-git-send-email-rth@twiddle.net> <1332185111-20739-2-git-send-email-rth@twiddle.net> From: Blue Swirl Date: Sat, 24 Mar 2012 16:11:57 +0000 Message-ID: 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: Richard Henderson Cc: qemu-devel@nongnu.org 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=A0= 2 + > =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_prolo= gue > + =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_S= IZE, > =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 CPU_TEMP_B= UF_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 .len= 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 .len= 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_tar= get_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, -16= */ > + =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, -24= */ > + =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, -32= */ > + =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, -40= */ > + =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, -48= */ > + =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, -56= */ > + =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 .len= 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 .len= 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_tar= get_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, -12= */ > + =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, -16= */ > + =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, -20= */ > + =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(d= ebug_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_GUEST= _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-targ= et.c. */ > =C2=A0static int target_parse_constraint(TCGArgConstraint *ct, const char= **pct_str); > =C2=A0static void tcg_out_ld(TCGContext *s, TCGType type, TCGReg ret, TCG= Reg 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 valu= e 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 it= . =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, discontigu= ously. =C2=A0Therefore > + =C2=A0 =C2=A0 =C2=A0 we mark .text as SHT_NOBITS (similar to .bss) so t= hat readers will > + =C2=A0 =C2=A0 =C2=A0 not look for contents. =C2=A0We can record any add= ress 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_fra= me"); > + =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_bu= ffer"); > + =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 fil= e 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 by= 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)(e= nv, tb_ptr) > =C2=A0#endif > + > +void tcg_register_jit(void *buf, size_t buf_size); > -- > 1.7.7.6 > >