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 <sanjoy@playingwithpointers.com> * 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.
This commit is contained in:
parent
80c135e554
commit
2838cc1d36
@ -1,3 +1,11 @@
|
||||
2016-06-17 Sanjoy Das <sanjoy@playingwithpointers.com>
|
||||
|
||||
* 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 <yao.qi@linaro.org>
|
||||
|
||||
* gdb.base/step-over-syscall.exp (break_cond_on_syscall): New
|
||||
|
@ -3256,15 +3256,6 @@
|
||||
* dg-extract-results.sh: Redirect grep output to /dev/null instead
|
||||
of grep -q.
|
||||
|
||||
2012-01-17 Sanjoy Das <sanjoy@playingwithpointers.com>
|
||||
|
||||
* 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 <tromey@redhat.com>
|
||||
|
||||
* gdb.base/catch-signal.c: New file.
|
||||
|
54
gdb/testsuite/gdb.base/jit-protocol.h
Normal file
54
gdb/testsuite/gdb.base/jit-protocol.h
Normal file
@ -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 <http://www.gnu.org/licenses/>. */
|
||||
|
||||
#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 <stdint.h>
|
||||
|
||||
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 */
|
79
gdb/testsuite/gdb.base/jit-reader.exp
Normal file
79
gdb/testsuite/gdb.base/jit-reader.exp
Normal file
@ -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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
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
|
61
gdb/testsuite/gdb.base/jithost.c
Normal file
61
gdb/testsuite/gdb.base/jithost.c
Normal file
@ -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 <http://www.gnu.org/licenses/>. */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <sys/mman.h>
|
||||
|
||||
#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;
|
||||
}
|
27
gdb/testsuite/gdb.base/jithost.h
Normal file
27
gdb/testsuite/gdb.base/jithost.h
Normal file
@ -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 <http://www.gnu.org/licenses/>. */
|
||||
|
||||
#ifndef JITHOST_H
|
||||
#define JITHOST_H
|
||||
|
||||
struct jithost_abi
|
||||
{
|
||||
const char *begin;
|
||||
const char *end;
|
||||
};
|
||||
|
||||
#endif /* JITHOST_H */
|
156
gdb/testsuite/gdb.base/jitreader.c
Normal file
156
gdb/testsuite/gdb.base/jitreader.c
Normal file
@ -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 <http://www.gnu.org/licenses/>. */
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#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;
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user