From 74fc6d9f1859ff1dadfabfe9dd1362bc6d2b51b7 Mon Sep 17 00:00:00 2001 From: Sanjoy Das Date: Tue, 18 Sep 2012 08:52:07 +0530 Subject: [PATCH 3/3] Add a test case for the jit-reader interface. --- gdb/testsuite/ChangeLog | 9 ++ gdb/testsuite/gdb.base/jit-protocol.h | 54 ++++++++++++ gdb/testsuite/gdb.base/jit-reader.exp | 80 +++++++++++++++++ gdb/testsuite/gdb.base/jithost.c | 61 +++++++++++++ gdb/testsuite/gdb.base/jithost.h | 27 ++++++ gdb/testsuite/gdb.base/jitreader.c | 156 +++++++++++++++++++++++++++++++++ 6 files changed, 387 insertions(+) create mode 100644 gdb/testsuite/gdb.base/jit-protocol.h 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 dde24e0..c0566b0 100644 --- a/gdb/testsuite/ChangeLog +++ b/gdb/testsuite/ChangeLog @@ -1,3 +1,12 @@ +2012-01-07 Sanjoy Das + + * gdb.base/jit-reader.exp: New file. Test case for the jit-reader + interface. + * gdb.base/jithost.c: New file. + * gdb.base/jithost.h: New file. + * gdb.base/jitreader.c : New file. + * gdb.base/jit-protocol.h: New file. + 2012-12-25 Jan Kratochvil * gdb.mi/mi-fullname-deleted.exp: New file. diff --git a/gdb/testsuite/gdb.base/jit-protocol.h b/gdb/testsuite/gdb.base/jit-protocol.h new file mode 100644 index 0000000..f7f9285 --- /dev/null +++ b/gdb/testsuite/gdb.base/jit-protocol.h @@ -0,0 +1,54 @@ +/* Copyright (C) 2009-2013 Free Software Foundation, Inc. + + This file is part of GDB. + + 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 . */ + +#ifdef JIT_H +#error "We don't include jit.h directly since we'd like the jit-reader unit \ + tests to break if we make ABI incompatible changes to the structures \ + re-declared here." +#endif + +#ifndef JIT_PROTOCOL_H +#define JIT_PROTOCOL_H + +#include + +typedef enum +{ + JIT_NOACTION = 0, + JIT_REGISTER, + JIT_UNREGISTER +} 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; +}; + +#endif /* JIT_PROTOCOL_H */ diff --git a/gdb/testsuite/gdb.base/jit-reader.exp b/gdb/testsuite/gdb.base/jit-reader.exp new file mode 100644 index 0000000..5034c3a --- /dev/null +++ b/gdb/testsuite/gdb.base/jit-reader.exp @@ -0,0 +1,80 @@ +# Copyright 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 . + +standard_testfile jithost.c + +if { (![istarget x86_64-*-*] && ![istarget i?86-*-*]) || ![is_lp64_target] } { + return -1; +} + +if {[skip_shlib_tests]} { + return -1 +} + +if { ![isnative] } { + return -1 +} + +if {[get_compiler_info]} { + untested "could not get compiler info" + return 1 +} + +set jit_host_src ${srcfile} +set jit_host_bin ${binfile} + +# We inject the complete path to jit-reader.h into the source file +# lest we end up (incorrectly) building against a system-installed +# version. +set jit_reader_header [standard_output_file "../../../gdb/jit-reader.h"] +set jit_reader_flag "-DJIT_READER_H=\"$jit_reader_header\"" + +if { [gdb_compile "${srcdir}/${subdir}/${jit_host_src}" "${jit_host_bin}" \ + executable [list debug additional_flags=$jit_reader_flag]] != "" } { + untested jit-reader.exp + return -1 +} + +set jit_reader jitreader +set jit_reader_src ${jit_reader}.c +set jit_reader_bin [standard_output_file ${jit_reader}.so] + +if { [gdb_compile_shlib "${srcdir}/${subdir}/${jit_reader_src}" "${jit_reader_bin}" \ + [list debug additional_flags=$jit_reader_flag]] != "" } { + untested jit-reader.exp + return -1 +} + +gdb_load_shlibs "${jit_reader_bin}" + +proc jit_reader_test {} { + global jit_host_bin + global jit_reader_bin + global verbose + + clean_restart $jit_host_bin + + if {$verbose > 0} { + gdb_test_no_output "set debug jit 1" + } + + gdb_test_no_output "jit-reader-load ${jit_reader_bin}" + gdb_run_cmd + gdb_test "" "Program received signal SIGTRAP, .*" "expect SIGTRAP" + + 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..413c4cd --- /dev/null +++ b/gdb/testsuite/gdb.base/jithost.c @@ -0,0 +1,61 @@ +/* Copyright (C) 2009-2012 Free Software Foundation, Inc. + + This file is part of GDB. + + 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 . */ + +#include +#include +#include +#include + +#include + +#include JIT_READER_H /* Please see jit-reader.exp for an explanation. */ +#include "jithost.h" +#include "jit-protocol.h" + +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; /* 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 = &only_entry; + __jit_debug_descriptor.relevant_entry = &only_entry; + __jit_debug_descriptor.action_flag = JIT_REGISTER; + __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..52ca87a --- /dev/null +++ b/gdb/testsuite/gdb.base/jithost.h @@ -0,0 +1,27 @@ +/* Copyright (C) 2009-2012 Free Software Foundation, Inc. + + This file is part of GDB. + + 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 . */ + +#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..0c935c4 --- /dev/null +++ b/gdb/testsuite/gdb.base/jitreader.c @@ -0,0 +1,156 @@ +/* Copyright (C) 2009-2012 Free Software Foundation, Inc. + + This file is part of GDB. + + 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 . */ + +#include +#include +#include +#include + +#include JIT_READER_H /* Please see jit-reader.exp for an explanation. */ +#include "jithost.h" + +GDB_DECLARE_GPL_COMPATIBLE_READER; + +enum register_mapping +{ + 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; +} + +static 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; + + 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; +} + +static 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; +} + +static 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