From 2838cc1d36e55bf6d45cf971bf401f895e575849 Mon Sep 17 00:00:00 2001 From: Sanjoy Das Date: Fri, 17 Jun 2016 19:24:08 +0100 Subject: [PATCH] Add a test case for the jit-reader interface Originally intended to be committed on 2013-01-17 in 675921c059dbaddd02ab2eb8a1eaf77b3ac727dd (Test case for the jit-reader), but by mistake the files were not added. Fortunately they still work. gdb/testsuite/ChangeLog: 2016-06-17 Sanjoy Das * gdb.base/jit-reader.exp: New file. * 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. --- gdb/testsuite/ChangeLog | 8 ++ gdb/testsuite/ChangeLog-1993-2013 | 9 -- gdb/testsuite/gdb.base/jit-protocol.h | 54 +++++++++ gdb/testsuite/gdb.base/jit-reader.exp | 79 +++++++++++++ gdb/testsuite/gdb.base/jithost.c | 61 ++++++++++ gdb/testsuite/gdb.base/jithost.h | 27 +++++ gdb/testsuite/gdb.base/jitreader.c | 156 ++++++++++++++++++++++++++ 7 files changed, 385 insertions(+), 9 deletions(-) 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 69aad53bfb1..e5f1c543c78 100644 --- a/gdb/testsuite/ChangeLog +++ b/gdb/testsuite/ChangeLog @@ -1,3 +1,11 @@ +2016-06-17 Sanjoy Das + + * gdb.base/jit-reader.exp: New file. + * 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. + 2016-06-17 Yao Qi * gdb.base/step-over-syscall.exp (break_cond_on_syscall): New diff --git a/gdb/testsuite/ChangeLog-1993-2013 b/gdb/testsuite/ChangeLog-1993-2013 index cc761ee2802..8e01dc508c0 100644 --- a/gdb/testsuite/ChangeLog-1993-2013 +++ b/gdb/testsuite/ChangeLog-1993-2013 @@ -3256,15 +3256,6 @@ * dg-extract-results.sh: Redirect grep output to /dev/null instead of grep -q. -2012-01-17 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. - 2013-01-16 Tom Tromey * gdb.base/catch-signal.c: 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 00000000000..7d0b34f57c4 --- /dev/null +++ b/gdb/testsuite/gdb.base/jit-protocol.h @@ -0,0 +1,54 @@ +/* Copyright (C) 2009-2017 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 00000000000..b5e297aaf7f --- /dev/null +++ b/gdb/testsuite/gdb.base/jit-reader.exp @@ -0,0 +1,79 @@ +# Copyright 2012-2016 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 +} + +proc jit_reader_test {} { + global jit_host_bin + global jit_reader_bin + global verbose + + clean_restart $jit_host_bin + gdb_load_shlib $jit_reader_bin + + if {$verbose > 0} { + gdb_test_no_output "set debug jit 1" + } + + gdb_test_no_output "jit-reader-load ${jit_reader_bin}" "jit-reader-load" + 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 00000000000..09ab377b926 --- /dev/null +++ b/gdb/testsuite/gdb.base/jithost.c @@ -0,0 +1,61 @@ +/* Copyright (C) 2009-2016 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 00000000000..31d9009c4f2 --- /dev/null +++ b/gdb/testsuite/gdb.base/jithost.h @@ -0,0 +1,27 @@ +/* Copyright (C) 2009-2016 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 00000000000..850fb46c8de --- /dev/null +++ b/gdb/testsuite/gdb.base/jitreader.c @@ -0,0 +1,156 @@ +/* Copyright (C) 2009-2016 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); +} + +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; +} -- 2.30.2