From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 19095 invoked by alias); 18 Sep 2012 04:30:34 -0000 Received: (qmail 18805 invoked by uid 22791); 18 Sep 2012 04:30:11 -0000 X-SWARE-Spam-Status: No, hits=-2.5 required=5.0 tests=AWL,BAYES_00,KHOP_RCVD_UNTRUST,KHOP_THREADED,RCVD_IN_DNSWL_LOW,RCVD_IN_HOSTKARMA_YE,SPF_SOFTFAIL,TW_CP,TW_YM X-Spam-Check-By: sourceware.org Received: from mail-pb0-f41.google.com (HELO mail-pb0-f41.google.com) (209.85.160.41) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Tue, 18 Sep 2012 04:29:56 +0000 Received: by pbbro12 with SMTP id ro12so11721438pbb.0 for ; Mon, 17 Sep 2012 21:29:56 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20120113; h=from:to:cc:subject:date:message-id:x-mailer:in-reply-to:references :x-gm-message-state; bh=P3Zd/SfBt8NLkJUn76n5Q/z34V6zl1iZoq51CJjl5NE=; b=J+BVIu+TbxqccD2xeAfa5sw4ZtUX2XNmnRvv/OyqRYRhW/N1lgucKcm9YmVZvCH+S1 HuQ/WI2oMI9gVtw+abzgbkhJXn1iwCmf4B4X1MCz3BMRkHIxBRiI0p4PzrtZ7u8byuBc qCPvq4Op5JQg7HKCTXZ51vI82FQembHwbJMTGubWKSMK0bS3kPLo17SWqi2HsWuJ5mSu GDwRXXkubEsnohcdW4BJGQHF+8L0d2wdwgSQXrppYMNCrEy61/o0y2GlSCt3ruppdjYb j0ubXkaLG5X4ZIkAnsWv2BfH8SyirFNLiOCYWEeSRaC6XWF1VVPDKrRbN1yy7fX00Qv3 ERtg== Received: by 10.68.201.104 with SMTP id jz8mr26827428pbc.141.1347942596322; Mon, 17 Sep 2012 21:29:56 -0700 (PDT) Received: from divine-comedy.divine-comedy (ec2-122-248-200-206.ap-southeast-1.compute.amazonaws.com. [122.248.200.206]) by mx.google.com with ESMTPS id pn4sm8003659pbb.50.2012.09.17.21.29.53 (version=TLSv1/SSLv3 cipher=OTHER); Mon, 17 Sep 2012 21:29:55 -0700 (PDT) From: Sanjoy Das To: gdb-patches@sourceware.org Cc: Sanjoy Das Subject: [PATCH 3/3] Add a test case for the jit-reader interface. Date: Tue, 18 Sep 2012 04:30:00 -0000 Message-Id: <1347942847-31510-4-git-send-email-sanjoy@playingwithpointers.com> In-Reply-To: <1347942847-31510-1-git-send-email-sanjoy@playingwithpointers.com> References: <1347942847-31510-1-git-send-email-sanjoy@playingwithpointers.com> X-Gm-Message-State: ALoCoQkbyt+PKCxCuM1J1wGqBB8KiKenZOrhKiT8q9fgtS+6I7CzHYsLOp7+HxtmaigofG1SxOn9 X-IsSubscribed: yes Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org X-SW-Source: 2012-09/txt/msg00341.txt.bz2 --- gdb/testsuite/ChangeLog | 8 ++ gdb/testsuite/gdb.base/jit-reader.exp | 78 +++++++++++++++++++ gdb/testsuite/gdb.base/jithost.c | 67 ++++++++++++++++ gdb/testsuite/gdb.base/jithost.h | 9 +++ gdb/testsuite/gdb.base/jitreader.c | 136 +++++++++++++++++++++++++++++++++ 5 files changed, 298 insertions(+) create mode 100644 gdb/testsuite/gdb.base/jit-reader.exp create mode 100644 gdb/testsuite/gdb.base/jithost.c create mode 100644 gdb/testsuite/gdb.base/jithost.h create mode 100644 gdb/testsuite/gdb.base/jitreader.c diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog index b458aba..f770475 100644 --- a/gdb/testsuite/ChangeLog +++ b/gdb/testsuite/ChangeLog @@ -1,3 +1,11 @@ +2012-09-18 Sanjoy Das + + * gdb.base/jit-reader.exp (new): Test case for the jit-reader + interface. + * gdb.base/jithost.c (new): Do. + * gdb.base/jithost.h (new): Do. + * gdb.base/jitreader.c (new) : Do. + 2012-09-17 Yao Qi * gdb.base/list.exp (set_listsize): Don't set arg to "unlimited" diff --git a/gdb/testsuite/gdb.base/jit-reader.exp b/gdb/testsuite/gdb.base/jit-reader.exp new file mode 100644 index 0000000..9a85b76 --- /dev/null +++ b/gdb/testsuite/gdb.base/jit-reader.exp @@ -0,0 +1,78 @@ +# Copyright 2011-2012 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +if ![istarget x86_64-*-linux-gnu*] then { + untested jit-reader.exp + return -1; +} + +if {[skip_shlib_tests]} { + untested jit-reader.exp + return -1 +} + +if {[get_compiler_info]} { + warning "Could not get compiler info" + untested jit-reader.exp + return 1 +} + +# +# test running programs +# + +set jit_host jithost +set jit_host_src ${jit_host}.c +set jit_host_bin ${objdir}/${subdir}/${jit_host} + +set include_dir ${objdir}/../../ + +if { [gdb_compile "${srcdir}/${subdir}/${jit_host_src}" "${jit_host_bin}" \ + executable [list debug incdir=${include_dir}]] != "" } { + untested jit-reader.exp + return -1 +} + +set reader "jitreader" +set reader_srcfile "${srcdir}/${subdir}/${reader}.c" +set reader_binfile "${objdir}/${subdir}/${reader}.so" + +# Note: compiling without debug info: the library goes through symbol +# renaming by munging on its symbol table, and that wouldn't work for .debug +# sections. Also, output for "info function" changes when debug info is resent. +if { [gdb_compile_shlib ${reader_srcfile} ${reader_binfile} \ + [list debug incdir=${include_dir}]] != "" } { + untested jit-reader.exp + return -1 +} + +proc jit_reader_test {} { + global jit_host + global reader_binfile + global verbose + + clean_restart $jit_host + + if {$verbose > 0} { + gdb_test "set debug jit 1" + } + + gdb_test_no_output "jit-reader-load ${reader_binfile}" + gdb_test "run" ".*" + + gdb_test "bt" "jit_function_00.*" +} + +jit_reader_test diff --git a/gdb/testsuite/gdb.base/jithost.c b/gdb/testsuite/gdb.base/jithost.c new file mode 100644 index 0000000..967245c --- /dev/null +++ b/gdb/testsuite/gdb.base/jithost.c @@ -0,0 +1,67 @@ +#include +#include +#include +#include +#include + +#include + +#include "gdb/jit-reader.h" +#include "jithost.h" + +typedef enum +{ + JIT_NOACTION = 0, + JIT_REGISTER_FN, + JIT_UNREGISTER_FN +} jit_actions_t; + +struct jit_code_entry +{ + struct jit_code_entry *next_entry; + struct jit_code_entry *prev_entry; + void *symfile_addr; + uint64_t symfile_size; +}; + +struct jit_descriptor +{ + uint32_t version; + uint32_t action_flag; + struct jit_code_entry *relevant_entry; + struct jit_code_entry *first_entry; +}; + +void __attribute__((noinline)) __jit_debug_register_code () { } + +struct jit_descriptor __jit_debug_descriptor = { 1, 0, 0, 0 }; +struct jit_code_entry only_entry; + +typedef void (jit_function_t)(); + +int main(int argc, char **argv) +{ + char *code = mmap(NULL, getpagesize(), PROT_WRITE | PROT_EXEC, + MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + jit_function_t *function = (jit_function_t *) code; + + code[0] = 0xcc; // Generate a SIGTRAP + code[1] = 0xc3; // RET + + struct jithost_abi *symfile = malloc(sizeof(struct jithost_abi)); + symfile->begin = code; + symfile->end = code + 2; + + only_entry.symfile_addr = symfile; + only_entry.symfile_size = sizeof(struct jithost_abi); + + __jit_debug_descriptor.first_entry = + __jit_debug_descriptor.relevant_entry = &only_entry; + __jit_debug_descriptor.action_flag = JIT_REGISTER_FN; + __jit_debug_descriptor.version = 1; + __jit_debug_register_code(); + + function(); + + return 0; +} diff --git a/gdb/testsuite/gdb.base/jithost.h b/gdb/testsuite/gdb.base/jithost.h new file mode 100644 index 0000000..37cf042 --- /dev/null +++ b/gdb/testsuite/gdb.base/jithost.h @@ -0,0 +1,9 @@ +#ifndef JITHOST_H +#define JITHOST_H + +struct jithost_abi { + const char *begin; + const char *end; +}; + +#endif /* JITHOST_H */ diff --git a/gdb/testsuite/gdb.base/jitreader.c b/gdb/testsuite/gdb.base/jitreader.c new file mode 100644 index 0000000..2438b0d --- /dev/null +++ b/gdb/testsuite/gdb.base/jitreader.c @@ -0,0 +1,136 @@ +#include +#include +#include +#include + +#include "gdb/jit-reader.h" +#include "jithost.h" + +GDB_DECLARE_GPL_COMPATIBLE_READER; + +enum RegisterMapping { + AMD64_RA = 16, + AMD64_RSP = 7, +}; + +struct reader_state { + uintptr_t code_begin; + uintptr_t code_end; +}; + +static enum gdb_status +read_debug_info (struct gdb_reader_funcs* self, + struct gdb_symbol_callbacks* cbs, + void* memory, long memory_sz) +{ + struct jithost_abi *symfile = memory; + struct gdb_object* object = cbs->object_open (cbs); + struct gdb_symtab* symtab = cbs->symtab_open (cbs, object, ""); + GDB_CORE_ADDR begin = (GDB_CORE_ADDR) symfile->begin; + GDB_CORE_ADDR end = (GDB_CORE_ADDR) symfile->end; + + cbs->block_open (cbs, symtab, NULL, begin, end, "jit_function_00"); + + cbs->symtab_close (cbs, symtab); + cbs->object_close (cbs, object); + return GDB_SUCCESS; +} + +static void +free_reg_value(struct gdb_reg_value *value) +{ + free (value); +} + +static void +write_register (struct gdb_unwind_callbacks *callbacks, int dw_reg, + uintptr_t value) +{ + const int size = sizeof (uintptr_t); + struct gdb_reg_value *reg_val = + malloc (sizeof(struct gdb_reg_value) + size - 1); + reg_val->defined = 1; + reg_val->free = free_reg_value; + + memcpy (reg_val->value, &value, size); + callbacks->reg_set (callbacks, dw_reg, reg_val); +} + +static int +read_register (struct gdb_unwind_callbacks *callbacks, int dw_reg, uintptr_t *value) +{ + const int size = sizeof (uintptr_t); + struct gdb_reg_value *reg_val = callbacks->reg_get (callbacks, dw_reg); + if (reg_val->size != size || !reg_val->defined) + { + reg_val->free (reg_val); + return 0; + } + memcpy (value, reg_val->value, size); + reg_val->free (reg_val); + return 1; +} + +enum gdb_status +unwind_frame(struct gdb_reader_funcs* self, struct gdb_unwind_callbacks* cbs) +{ + const int word_size = sizeof (uintptr_t); + uintptr_t this_sp, this_ip, prev_ip, prev_sp; + struct reader_state *state = (struct reader_state *) self->priv_data; + + if (!read_register (cbs, AMD64_RA, &this_ip)) + return GDB_FAIL; + + if (this_ip >= state->code_end || this_ip < state->code_begin) + return GDB_FAIL; + + printf("Unwinding %p\n", (void *) this_ip); + + if (!read_register (cbs, AMD64_RSP, &this_sp)) + return GDB_FAIL; + + if (cbs->target_read (this_sp, &prev_ip, word_size) == GDB_FAIL) + return GDB_FAIL; + + prev_sp = this_sp + word_size; + write_register (cbs, AMD64_RA, prev_ip); + write_register (cbs, AMD64_RSP, prev_sp); + return GDB_SUCCESS; +} + +struct gdb_frame_id +get_frame_id (struct gdb_reader_funcs* self, struct gdb_unwind_callbacks* cbs) +{ + struct reader_state *state = (struct reader_state *) self->priv_data; + struct gdb_frame_id frame_id; + + uintptr_t sp; + read_register (cbs, AMD64_RSP, &sp); + + frame_id.code_address = (GDB_CORE_ADDR) state->code_begin; + frame_id.stack_address = (GDB_CORE_ADDR) sp; + + return frame_id; +} + +void +destroy_reader(struct gdb_reader_funcs* self) +{ + free (self->priv_data); + free (self); +} + +extern struct gdb_reader_funcs* gdb_init_reader(void) { + struct reader_state *state = malloc (sizeof (struct reader_state)); + struct gdb_reader_funcs *reader_funcs = + malloc (sizeof (struct gdb_reader_funcs)); + + reader_funcs->reader_version = GDB_READER_INTERFACE_VERSION; + reader_funcs->priv_data = state; + reader_funcs->read = read_debug_info; + reader_funcs->unwind = unwind_frame; + reader_funcs->get_frame_id = get_frame_id; + reader_funcs->destroy = destroy_reader; + + return reader_funcs; +} -- 1.7.10.4