All of lore.kernel.org
 help / color / mirror / Atom feed
From: Richard Henderson <rth@twiddle.net>
To: qemu-devel@nongnu.org
Cc: blauwirbel@gmail.com
Subject: [Qemu-devel] [PATCH 1/4] tcg: Add debug_info to JIT ELF image.
Date: Sat, 24 Mar 2012 10:47:36 -0700	[thread overview]
Message-ID: <1332611259-14940-2-git-send-email-rth@twiddle.net> (raw)
In-Reply-To: <1332611259-14940-1-git-send-email-rth@twiddle.net>

This allows us to actually supply a function name in softmmu builds;
gdb doesn't pick up the minimal symbol table otherwise.  Also add a
bit of documentation and statically generate more of the ELF image.

Signed-off-by: Richard Henderson <rth@twiddle.net>
---
 tcg/tcg.c |  233 +++++++++++++++++++++++++++++++++++++++++--------------------
 1 files changed, 158 insertions(+), 75 deletions(-)

diff --git a/tcg/tcg.c b/tcg/tcg.c
index eb595ce..df4edc0 100644
--- a/tcg/tcg.c
+++ b/tcg/tcg.c
@@ -2252,8 +2252,17 @@ void tcg_dump_info(FILE *f, fprintf_function cpu_fprintf)
 #endif
 
 #ifdef ELF_HOST_MACHINE
-/* The backend should define ELF_HOST_MACHINE to indicate both what value to
-   put into the ELF image and to indicate support for the feature.  */
+/* In order to use this feature, the backend needs to do three things:
+
+   (1) Define ELF_HOST_MACHINE to indicate both what value to
+       put into the ELF image and to indicate support for the feature.
+
+   (2) Define tcg_register_jit.  This should create a buffer containing
+       the contents of a .debug_frame section that describes the post-
+       prologue unwind info for the tcg machine.
+
+   (3) Call tcg_register_jit_int, with the constructed .debug_frame.
+*/
 
 /* Begin GDB interface.  THE FOLLOWING MUST MATCH GDB DOCS.  */
 typedef enum {
@@ -2300,96 +2309,169 @@ static int find_string(const char *strtab, const char *str)
     }
 }
 
-static void tcg_register_jit_int(void *buf, size_t buf_size,
+static void tcg_register_jit_int(void *buf_ptr, size_t buf_size,
                                  void *debug_frame, size_t debug_frame_size)
 {
-    static const char strings[64] =
-        "\0"
-        ".text\0"
-        ".debug_frame\0"
-        ".symtab\0"
-        ".strtab\0"
-        "code_gen_buffer";
+    struct __attribute__((packed)) DebugInfo {
+        uint32_t  len;
+        uint16_t  version;
+        uint32_t  abbrev;
+        uint8_t   ptr_size;
+        uint8_t   cu_die;
+        uint16_t  cu_lang;
+        uintptr_t cu_low_pc;
+        uintptr_t cu_high_pc;
+        uint8_t   fn_die;
+        char      fn_name[16];
+        uintptr_t fn_low_pc;
+        uintptr_t fn_high_pc;
+        uint8_t   cu_eoc;
+    };
 
     struct ElfImage {
         ElfW(Ehdr) ehdr;
         ElfW(Phdr) phdr;
-        ElfW(Shdr) shdr[5];
-        ElfW(Sym)  sym[1];
-        char       str[64];
+        ElfW(Shdr) shdr[7];
+        ElfW(Sym)  sym[2];
+        struct DebugInfo di;
+        uint8_t    da[24];
+        char       str[80];
+    };
+
+    struct ElfImage *img;
+
+    static const struct ElfImage img_template = {
+        .ehdr = {
+            .e_ident[EI_MAG0] = ELFMAG0,
+            .e_ident[EI_MAG1] = ELFMAG1,
+            .e_ident[EI_MAG2] = ELFMAG2,
+            .e_ident[EI_MAG3] = ELFMAG3,
+            .e_ident[EI_CLASS] = ELF_CLASS,
+            .e_ident[EI_DATA] = ELF_DATA,
+            .e_ident[EI_VERSION] = EV_CURRENT,
+            .e_type = ET_EXEC,
+            .e_machine = ELF_HOST_MACHINE,
+            .e_version = EV_CURRENT,
+            .e_phoff = offsetof(struct ElfImage, phdr),
+            .e_shoff = offsetof(struct ElfImage, shdr),
+            .e_ehsize = sizeof(ElfW(Shdr)),
+            .e_phentsize = sizeof(ElfW(Phdr)),
+            .e_phnum = 1,
+            .e_shentsize = sizeof(ElfW(Shdr)),
+            .e_shnum = ARRAY_SIZE(img->shdr),
+            .e_shstrndx = ARRAY_SIZE(img->shdr) - 1,
+        },
+        .phdr = {
+            .p_type = PT_LOAD,
+            .p_flags = PF_X,
+        },
+        .shdr = {
+            [0] = { .sh_type = SHT_NULL },
+            /* Trick: The contents of code_gen_buffer are not present in
+               this fake ELF file; that got allocated elsewhere.  Therefore
+               we mark .text as SHT_NOBITS (similar to .bss) so that readers
+               will not look for contents.  We can record any address.  */
+            [1] = { /* .text */
+                .sh_type = SHT_NOBITS,
+                .sh_flags = SHF_EXECINSTR | SHF_ALLOC,
+            },
+            [2] = { /* .debug_info */
+                .sh_type = SHT_PROGBITS,
+                .sh_offset = offsetof(struct ElfImage, di),
+                .sh_size = sizeof(struct DebugInfo),
+            },
+            [3] = { /* .debug_abbrev */
+                .sh_type = SHT_PROGBITS,
+                .sh_offset = offsetof(struct ElfImage, da),
+                .sh_size = sizeof(img->da),
+            },
+            [4] = { /* .debug_frame */
+                .sh_type = SHT_PROGBITS,
+                .sh_offset = sizeof(struct ElfImage),
+            },
+            [5] = { /* .symtab */
+                .sh_type = SHT_SYMTAB,
+                .sh_offset = offsetof(struct ElfImage, sym),
+                .sh_size = sizeof(img->sym),
+                .sh_info = 1,
+                .sh_link = ARRAY_SIZE(img->shdr) - 1,
+                .sh_entsize = sizeof(ElfW(Sym)),
+            },
+            [6] = { /* .strtab */
+                .sh_type = SHT_STRTAB,
+                .sh_offset = offsetof(struct ElfImage, str),
+                .sh_size = sizeof(img->str),
+            }
+        },
+        .sym = {
+            [1] = { /* code_gen_buffer */
+                .st_info = ELF_ST_INFO(STB_GLOBAL, STT_FUNC),
+                .st_shndx = 1,
+            }
+        },
+        .di = {
+            .len = sizeof(struct DebugInfo) - 4,
+            .version = 2,
+            .ptr_size = sizeof(void *),
+            .cu_die = 1,
+            .cu_lang = 0x8001,  /* DW_LANG_Mips_Assembler */
+            .fn_die = 2,
+            .fn_name = "code_gen_buffer"
+        },
+        .da = {
+            1,          /* abbrev number (the cu) */
+            0x11, 1,    /* DW_TAG_compile_unit, has children */
+            0x13, 0x5,  /* DW_AT_language, DW_FORM_data2 */
+            0x11, 0x1,  /* DW_AT_low_pc, DW_FORM_addr */
+            0x12, 0x1,  /* DW_AT_high_pc, DW_FORM_addr */
+            0, 0,       /* end of abbrev */
+            2,          /* abbrev number (the fn) */
+            0x2e, 0,    /* DW_TAG_subprogram, no children */
+            0x3, 0x8,   /* DW_AT_name, DW_FORM_string */
+            0x11, 0x1,  /* DW_AT_low_pc, DW_FORM_addr */
+            0x12, 0x1,  /* DW_AT_high_pc, DW_FORM_addr */
+            0, 0,       /* end of abbrev */
+            0           /* no more abbrev */
+        },
+        .str = "\0" ".text\0" ".debug_info\0" ".debug_abbrev\0"
+               ".debug_frame\0" ".symtab\0" ".strtab\0" "code_gen_buffer",
     };
 
     /* We only need a single jit entry; statically allocate it.  */
     static struct jit_code_entry one_entry;
 
+    uintptr_t buf = (uintptr_t)buf_ptr;
     size_t img_size = sizeof(struct ElfImage) + debug_frame_size;
-    struct ElfImage *img = g_malloc0(img_size);
-
-    img->ehdr.e_ident[EI_MAG0] = ELFMAG0;
-    img->ehdr.e_ident[EI_MAG1] = ELFMAG1;
-    img->ehdr.e_ident[EI_MAG2] = ELFMAG2;
-    img->ehdr.e_ident[EI_MAG3] = ELFMAG3;
-    img->ehdr.e_ident[EI_CLASS] = ELF_CLASS;
-    img->ehdr.e_ident[EI_DATA] = ELF_DATA;
-    img->ehdr.e_ident[EI_VERSION] = EV_CURRENT;
-    img->ehdr.e_type = ET_EXEC;
-    img->ehdr.e_machine = ELF_HOST_MACHINE;
-    img->ehdr.e_version = EV_CURRENT;
-    img->ehdr.e_phoff = offsetof(struct ElfImage, phdr);
-    img->ehdr.e_shoff = offsetof(struct ElfImage, shdr);
-    img->ehdr.e_ehsize = sizeof(ElfW(Shdr));
-    img->ehdr.e_phentsize = sizeof(ElfW(Phdr));
-    img->ehdr.e_phnum = 1;
-    img->ehdr.e_shentsize = sizeof(img->shdr[0]);
-    img->ehdr.e_shnum = ARRAY_SIZE(img->shdr);
-    img->ehdr.e_shstrndx = ARRAY_SIZE(img->shdr) - 1;
-
-    img->phdr.p_type = PT_LOAD;
-    img->phdr.p_offset = (char *)buf - (char *)img;
-    img->phdr.p_vaddr = (ElfW(Addr))buf;
-    img->phdr.p_paddr = img->phdr.p_vaddr;
-    img->phdr.p_filesz = 0;
-    img->phdr.p_memsz = buf_size;
-    img->phdr.p_flags = PF_X;
 
-    memcpy(img->str, strings, sizeof(img->str));
+    img = g_malloc(img_size);
+    *img = img_template;
+    memcpy(img + 1, debug_frame, debug_frame_size);
 
-    img->shdr[0].sh_type = SHT_NULL;
+    img->phdr.p_vaddr = buf;
+    img->phdr.p_paddr = buf;
+    img->phdr.p_memsz = buf_size;
 
-    /* Trick: The contents of code_gen_buffer are not present in this fake
-       ELF file; that got allocated elsewhere, discontiguously.  Therefore
-       we mark .text as SHT_NOBITS (similar to .bss) so that readers will
-       not look for contents.  We can record any address at will.  */
     img->shdr[1].sh_name = find_string(img->str, ".text");
-    img->shdr[1].sh_type = SHT_NOBITS;
-    img->shdr[1].sh_flags = SHF_EXECINSTR | SHF_ALLOC;
-    img->shdr[1].sh_addr = (ElfW(Addr))buf;
+    img->shdr[1].sh_addr = buf;
     img->shdr[1].sh_size = buf_size;
 
-    img->shdr[2].sh_name = find_string(img->str, ".debug_frame");
-    img->shdr[2].sh_type = SHT_PROGBITS;
-    img->shdr[2].sh_offset = sizeof(*img);
-    img->shdr[2].sh_size = debug_frame_size;
-    memcpy(img + 1, debug_frame, debug_frame_size);
+    img->shdr[2].sh_name = find_string(img->str, ".debug_info");
+    img->shdr[3].sh_name = find_string(img->str, ".debug_abbrev");
+
+    img->shdr[4].sh_name = find_string(img->str, ".debug_frame");
+    img->shdr[4].sh_size = debug_frame_size;
+
+    img->shdr[5].sh_name = find_string(img->str, ".symtab");
+    img->shdr[6].sh_name = find_string(img->str, ".strtab");
+
+    img->sym[1].st_name = find_string(img->str, "code_gen_buffer");
+    img->sym[1].st_value = buf;
+    img->sym[1].st_size = buf_size;
 
-    img->shdr[3].sh_name = find_string(img->str, ".symtab");
-    img->shdr[3].sh_type = SHT_SYMTAB;
-    img->shdr[3].sh_offset = offsetof(struct ElfImage, sym);
-    img->shdr[3].sh_size = sizeof(img->sym);
-    img->shdr[3].sh_info = ARRAY_SIZE(img->sym);
-    img->shdr[3].sh_link = img->ehdr.e_shstrndx;
-    img->shdr[3].sh_entsize = sizeof(ElfW(Sym));
-
-    img->shdr[4].sh_name = find_string(img->str, ".strtab");
-    img->shdr[4].sh_type = SHT_STRTAB;
-    img->shdr[4].sh_offset = offsetof(struct ElfImage, str);
-    img->shdr[4].sh_size = sizeof(img->str);
-
-    img->sym[0].st_name = find_string(img->str, "code_gen_buffer");
-    img->sym[0].st_info = ELF_ST_INFO(STB_GLOBAL, STT_FUNC);
-    img->sym[0].st_shndx = 1;
-    img->sym[0].st_value = (ElfW(Addr))buf;
-    img->sym[0].st_size = buf_size;
+    img->di.cu_low_pc = buf;
+    img->di.cu_high_pc = buf_size;
+    img->di.fn_low_pc = buf;
+    img->di.fn_high_pc = buf_size;
 
 #ifdef DEBUG_JIT
     /* Enable this block to be able to debug the ELF image file creation.
@@ -2397,7 +2479,7 @@ static void tcg_register_jit_int(void *buf, size_t buf_size,
     {
         FILE *f = fopen("/tmp/qemu.jit", "w+b");
         if (f) {
-            if (fwrite(img, img_size, 1, f) != buf_size) {
+            if (fwrite(img, img_size, 1, f) != img_size) {
                 /* Avoid stupid unused return value warning for fwrite.  */
             }
             fclose(f);
@@ -2414,7 +2496,8 @@ static void tcg_register_jit_int(void *buf, size_t buf_size,
     __jit_debug_register_code();
 }
 #else
-/* No support for the feature.  Provide the entry point expected by exec.c.  */
+/* No support for the feature.  Provide the entry point expected by exec.c,
+   and implement the internal function we declared earlier.  */
 
 static void tcg_register_jit_int(void *buf, size_t size,
                                  void *debug_frame, size_t debug_frame_size)
-- 
1.7.7.6

  reply	other threads:[~2012-03-24 17:47 UTC|newest]

Thread overview: 8+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2012-03-24 17:47 [Qemu-devel] [PATCH 0/4] GDB Jit interface, v4 Richard Henderson
2012-03-24 17:47 ` Richard Henderson [this message]
2012-03-24 17:47 ` [Qemu-devel] [PATCH 2/4] tcg: Allow ELF_HOST_FLAGS and ELF_OSABI overrides in gdb-jit Richard Henderson
2012-03-24 17:47 ` [Qemu-devel] [PATCH 3/4] tcg-hppa: Add debug_frame support Richard Henderson
2012-03-24 17:47 ` [Qemu-devel] [PATCH 4/4] tcg-sparc: " Richard Henderson
2012-03-24 18:41 ` [Qemu-devel] [PATCH 0/4] GDB Jit interface, v4 Blue Swirl
2012-03-24 19:23   ` Richard Henderson
2012-03-24 21:23     ` Blue Swirl

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1332611259-14940-2-git-send-email-rth@twiddle.net \
    --to=rth@twiddle.net \
    --cc=blauwirbel@gmail.com \
    --cc=qemu-devel@nongnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.