Forgot to add these files. They are referent to the last commit,

"Implementing the catch syscall feature".
This commit is contained in:
Sergio Durigan Junior 2009-09-15 03:32:06 +00:00
parent a96d9b2e9a
commit fbbe92c5af
4 changed files with 952 additions and 0 deletions

View File

@ -0,0 +1,25 @@
/* This file is used to test the 'catch syscall' feature on GDB.
Please, if you are going to edit this file DO NOT change the syscalls
being called (nor the order of them). If you really must do this, then
take a look at catch-syscall.exp and modify there too.
Written by Sergio Durigan Junior <sergiodj@linux.vnet.ibm.com>
September, 2008 */
#include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h>
int
main (void)
{
/* A close() with a wrong argument. We are only
interested in the syscall. */
close (-1);
chroot (".");
/* The last syscall. Do not change this. */
_exit (0);
}

View File

@ -0,0 +1,445 @@
# Copyright 1997, 1999, 2007, 2008 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/>.
# This program tests the 'catch syscall' functionality.
#
# It was written by Sergio Durigan Junior <sergiodj@linux.vnet.ibm.com>
# on September/2008.
if { [is_remote target] || ![isnative] } then {
continue
}
set prms_id 0
set bug_id 0
global srcfile
set testfile "catch-syscall"
set srcfile ${testfile}.c
set binfile ${objdir}/${subdir}/${testfile}
# All (but the last) syscalls from the example code
# They are ordered according to the file, so do not change this.
set all_syscalls { "close" "chroot" }
set all_syscalls_numbers { }
# The last syscall (exit()) does not return, so
# we cannot expect the catchpoint to be triggered
# twice. It is a special case.
set last_syscall "exit_group"
if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug}] != "" } {
untested catch-syscall.exp
return -1
}
# Until "catch syscall" is implemented on other targets...
if {![istarget "hppa*-hp-hpux*"] && ![istarget "*-linux*"]} then {
continue
}
# This shall be updated whenever 'catch syscall' is implemented
# on some architecture.
#if { ![istarget "i\[34567\]86-*-linux*"]
if { ![istarget "x86_64-*-linux*"] && ![istarget "i\[34567\]86-*-linux*"]
&& ![istarget "powerpc-*-linux*"] && ![istarget "powerpc64-*-linux*"] } {
continue
}
# Internal procedure used to check if, after issuing a 'catch syscall'
# command (without arguments), the 'info breakpoints' command displays
# that '"any syscall"' is to be caught.
proc check_info_bp_any_syscall {} {
global gdb_prompt
# Verifying that the catchpoint appears in the 'info breakpoints'
# command, but with "<any syscall>".
set thistest "catch syscall appears in 'info breakpoints'"
gdb_test "info breakpoints" ".*catchpoint.*keep y.*syscall \"<any syscall>\".*" $thistest
}
# Internal procedure used to check if, after issuing a 'catch syscall X'
# command (with arguments), the 'info breakpoints' command displays
# that the syscall 'X' is to be caught.
proc check_info_bp_specific_syscall { syscall } {
global gdb_prompt
set thistest "syscall(s) $syscall appears in 'info breakpoints'"
gdb_test "info breakpoints" ".*catchpoint.*keep y.*syscall(\[(\]s\[)\])? (.)?${syscall}(.)?.*" $thistest
}
# Internal procedure used to check if, after issuing a 'catch syscall X'
# command (with many arguments), the 'info breakpoints' command displays
# that the syscalls 'X' are to be caught.
proc check_info_bp_many_syscalls { syscalls } {
global gdb_prompt
set filter_str ""
foreach name $syscalls {
set filter_str "${filter_str}${name}, "
}
set filter_str [ string trimright $filter_str ", " ]
set thistest "syscalls $filter_str appears in 'info breakpoints'"
gdb_test "info breakpoints" ".*catchpoint.*keep y.*syscalls (.)?${filter_str}(.)?.*" $thistest
}
# This procedure checks if there was a call to a syscall.
proc check_call_to_syscall { syscall } {
global gdb_prompt
set thistest "program has called $syscall"
gdb_test "continue" "Catchpoint .*(call to syscall .?${syscall}.?).*" $thistest
}
# This procedure checks if the syscall returned.
proc check_return_from_syscall { syscall } {
global gdb_prompt
set thistest "syscall $syscall has returned"
gdb_test "continue" "Catchpoint .*(returned from syscall (.)?${syscall}(.)?).*" $thistest
}
# Internal procedure that performs two 'continue' commands and checks if
# a syscall call AND return occur.
proc check_continue { syscall } {
global gdb_prompt
# Testing if the 'continue' stops at the
# specified syscall_name. If it does, then it should
# first print that the infeior has called the syscall,
# and after print that the syscall has returned.
# Testing if the inferiorr has called the syscall.
check_call_to_syscall $syscall
# And now, that the syscall has returned.
check_return_from_syscall $syscall
}
# Inserts a syscall catchpoint with an argument.
proc insert_catch_syscall_with_arg { syscall } {
global gdb_prompt
# Trying to set the catchpoint
set thistest "catch syscall with arguments ($syscall)"
gdb_test "catch syscall $syscall" "Catchpoint .*(syscall (.)?${syscall}(.)?( \[\[0-9\]+\])?).*" $thistest
check_info_bp_specific_syscall $syscall
}
# Inserts a syscall catchpoint with many arguments.
proc insert_catch_syscall_with_many_args { syscalls numbers } {
global gdb_prompt
set catch [ join $syscalls " " ]
set filter_str ""
foreach name $syscalls number $numbers {
set filter_str "${filter_str}'${name}' \[${number}\] "
}
set filter_str [ string trimright $filter_str " " ]
# Trying to set the catchpoint
set thistest "catch syscall with arguments ($filter_str)"
gdb_test "catch syscall $catch" "Catchpoint .*(syscalls (.)?${filter_str}(.)?).*" $thistest
check_info_bp_many_syscalls $syscalls
}
proc check_for_program_end {} {
global gdb_prompt
# Deleting the catchpoints
delete_breakpoints
set thistest "successful program end"
gdb_test "continue" "Program exited normally.*" $thistest
}
proc test_catch_syscall_without_args {} {
global gdb_prompt all_syscalls last_syscall
# Trying to set the syscall
set thistest "setting catch syscall without arguments"
gdb_test "catch syscall" "Catchpoint .*(syscall).*" $thistest
check_info_bp_any_syscall
# We have to check every syscall
foreach name $all_syscalls {
check_continue $name
}
# At last but not least, we check if the inferior
# has called the last (exit) syscall.
check_call_to_syscall $last_syscall
# Now let's see if the inferior correctly finishes.
check_for_program_end
}
proc test_catch_syscall_with_args {} {
global gdb_prompt
set syscall_name "close"
insert_catch_syscall_with_arg $syscall_name
# Can we continue until we catch the syscall?
check_continue $syscall_name
# Now let's see if the inferior correctly finishes.
check_for_program_end
}
proc test_catch_syscall_with_many_args {} {
global gdb_prompt all_syscalls all_syscalls_numbers
insert_catch_syscall_with_many_args $all_syscalls $all_syscalls_numbers
# Can we continue until we catch the syscalls?
foreach name $all_syscalls {
check_continue $name
}
# Now let's see if the inferior correctly finishes.
check_for_program_end
}
proc test_catch_syscall_with_wrong_args {} {
global gdb_prompt
# mlock is not called from the source
set syscall_name "mlock"
insert_catch_syscall_with_arg $syscall_name
# Now, we must verify if the program stops with a continue.
# If it doesn't, everything is right (since we don't have
# a syscall named "mlock" in it). Otherwise, this is a failure.
set thistest "catch syscall with unused syscall ($syscall_name)"
gdb_test "continue" "Program exited normally.*" $thistest
}
proc test_catch_syscall_restarting_inferior {} {
global gdb_prompt
set syscall_name "chroot"
insert_catch_syscall_with_arg $syscall_name
# Let's first reach the call of the syscall.
check_call_to_syscall $syscall_name
# Now, restart the program
rerun_to_main
# And check for call/return
check_continue $syscall_name
# Can we finish?
check_for_program_end
}
proc do_syscall_tests {} {
global gdb_prompt srcdir
# First, we need to set GDB datadir.
send_gdb "set data-directory $srcdir/..\n"
gdb_expect 10 {
-re "$gdb_prompt $" {
verbose "Setting GDB datadir to $srcdir/..." 2
}
timeout {
error "Couldn't set GDB datadir."
}
}
# Verify that the 'catch syscall' help is available
set thistest "help catch syscall"
gdb_test "help catch syscall" "Catch system calls.*" $thistest
# Try to set a catchpoint to a nonsense syscall
set thistest "catch syscall to a nonsense syscall is prohibited"
gdb_test "catch syscall nonsense_syscall" "Unknown syscall name .*" $thistest
# Testing the 'catch syscall' command without arguments.
# This test should catch any syscalls.
if [runto_main] then { test_catch_syscall_without_args }
# Testing the 'catch syscall' command with arguments.
# This test should only catch the specified syscall.
if [runto_main] then { test_catch_syscall_with_args }
# Testing the 'catch syscall' command with many arguments.
# This test should catch $all_syscalls.
if [runto_main] then { test_catch_syscall_with_many_args }
# Testing the 'catch syscall' command with WRONG arguments.
# This test should not trigger any catchpoints.
if [runto_main] then { test_catch_syscall_with_wrong_args }
# Testing the 'catch' syscall command during a restart of
# the inferior.
if [runto_main] then { test_catch_syscall_restarting_inferior }
}
proc test_catch_syscall_fail_noxml {} {
global gdb_prompt
# Sanitizing.
delete_breakpoints
# Testing to see if we receive a warning when calling "catch syscall"
# without XML support.
set thistest "Catch syscall displays a warning when there is no XML support"
gdb_test "catch syscall" "warning: Could not open .*warning: Could not load the syscall XML file .*GDB will not be able to display syscall names.*Catchpoint .*(syscall).*" $thistest
# Since the catchpoint was set, we must check if it's present at
# "info breakpoints"
check_info_bp_any_syscall
# Sanitizing.
delete_breakpoints
}
proc test_catch_syscall_without_args_noxml {} {
# We will need the syscall names even not using it
# because we need to know know many syscalls are in
# the example file.
global gdb_prompt all_syscalls last_syscall
delete_breakpoints
set thistest "Catch syscall without arguments and without XML support"
gdb_test "catch syscall" "Catchpoint .*(syscall).*"
# Now, we should be able to set a catchpoint,
# and GDB shall not display the warning anymore.
foreach name $all_syscalls {
# Unfortunately, we don't know the syscall number
# that will be caught because this information is
# arch-dependent. Thus, we try to catch anything
# similar to a number.
check_continue "\[0-9\]*"
}
# At last but not least, we check if the inferior
# has called the last (exit) syscall.
check_call_to_syscall "\[0-9\]*"
delete_breakpoints
}
proc test_catch_syscall_with_args_noxml {} {
global gdb_prompt
# The number of the "close" syscall. This is our
# option for a "long-estabilished" syscall in all
# Linux architectures, but unfortunately x86_64 and
# a few other platforms don't "follow the convention".
# Because of this, we need this ugly check :-(.
set close_number ""
if { [istarget "x86_64-*-linux*"] } {
set close_number "3"
} else {
set close_number "6"
}
delete_breakpoints
insert_catch_syscall_with_arg $close_number
check_continue $close_number
delete_breakpoints
}
proc test_catch_syscall_with_wrong_args_noxml {} {
global gdb_prompt
delete_breakpoints
# Even without XML support, GDB should not accept unknown
# syscall names for the catchpoint.
set thistest "Catch a nonsense syscall without XML support"
gdb_test "catch syscall nonsense_syscall" "Unknown syscall name .nonsense_syscall.*" $thistest
delete_breakpoints
}
proc do_syscall_tests_without_xml {} {
global gdb_prompt srcdir
# In this case, we don't need to set GDB's datadir because
# we want GDB to display only numbers, not names. So, let's
# begin with the tests.
# The first test is to see if GDB displays a warning when we
# try to catch syscalls without the XML support.
test_catch_syscall_fail_noxml
# Now, let's test if we can catch syscalls without XML support.
# We should succeed, but GDB is not supposed to print syscall names.
if [runto_main] then { test_catch_syscall_without_args_noxml }
# The only valid argument "catch syscall" should accept is the
# syscall number, and not the name (since it can't translate a
# name to a number).
#
# It's worth mentioning that we only try to catch the syscall
# close(). This is because the syscall number is an arch-dependent
# information, so we can't assume that we know every syscall number
# in this system. Therefore, we have decided to use a "long-estabilished"
# system call, and close() just sounded the right choice :-).
if [runto_main] then { test_catch_syscall_with_args_noxml }
# Now, we'll try to provide a syscall name (valid or not) to the command,
# and expect it to fail.
if [runto_main] then { test_catch_syscall_with_wrong_args_noxml }
}
# This procedure fills the vector "all_syscalls_numbers" with the proper
# numbers for the used syscalls according to the architecture.
proc fill_all_syscalls_numbers {} {
global all_syscalls_numbers
# For Linux on x86, PPC and PPC64, the numbers for the syscalls "close" and
# "chroot" are the same.
if { ![istarget "i\[34567\]86-*-linux*"]
|| ![istarget "powerpc-*-linux*"] || ![istarget "powerpc64-*-linux*"] } {
set all_syscalls_numbers { "6" "61" }
}
}
# Start with a fresh gdb
gdb_exit
gdb_start
gdb_reinitialize_dir $srcdir/$subdir
gdb_load ${binfile}
# Execute the tests, using XML support
do_syscall_tests
# Restart gdb
gdb_exit
gdb_start
gdb_reinitialize_dir $srcdir/$subdir
gdb_load ${binfile}
# Execute the tests, without XML support. In this case, GDB will
# only display syscall numbers, and not syscall names.
do_syscall_tests_without_xml

432
gdb/xml-syscall.c Normal file
View File

@ -0,0 +1,432 @@
/* Functions that provide the mechanism to parse a syscall XML file
and get its values.
Copyright (C) 1986, 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996,
1998, 1999, 2000, 2001, 2003, 2004, 2005, 2006, 2007, 2008
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 "defs.h"
#include "gdbtypes.h"
#include "xml-support.h"
#include "xml-syscall.h"
/* For the struct syscall definition. */
#include "target.h"
#include "filenames.h"
#include "gdb_assert.h"
#ifndef HAVE_LIBEXPAT
/* Dummy functions to indicate that there's no support for fetching
syscalls information. */
static void
syscall_warn_user (void)
{
static int have_warned = 0;
if (!have_warned)
{
have_warned = 1;
warning (_("Can not parse XML syscalls information; XML support was "
"disabled at compile time."));
}
}
void
set_xml_syscall_file_name (const char *name)
{
syscall_warn_user ();
}
void
get_syscall_by_number (int syscall_number,
struct syscall *s)
{
syscall_warn_user ();
s->number = syscall_number;
s->name = NULL;
}
void
get_syscall_by_name (const char *syscall_name,
struct syscall *s)
{
syscall_warn_user ();
s->number = UNKNOWN_SYSCALL;
s->name = syscall_name;
}
const char **
get_syscall_names (void)
{
syscall_warn_user ();
return NULL;
}
#else /* ! HAVE_LIBEXPAT */
/* Structure which describes a syscall. */
typedef struct syscall_desc
{
/* The syscall number. */
int number;
/* The syscall name. */
char *name;
} *syscall_desc_p;
DEF_VEC_P(syscall_desc_p);
/* Structure that represents syscalls information. */
struct syscalls_info
{
/* The syscalls. */
VEC(syscall_desc_p) *syscalls;
};
/* Callback data for syscall information parsing. */
struct syscall_parsing_data
{
/* The syscalls_info we are building. */
struct syscalls_info *sysinfo;
};
/* Structure used to store information about the available syscalls in
the system. */
static const struct syscalls_info *_sysinfo = NULL;
/* A flag to tell if we already initialized the structure above. */
static int have_initialized_sysinfo = 0;
/* The filename of the syscall's XML. */
static const char *xml_syscall_file = NULL;
static struct syscalls_info *
allocate_syscalls_info (void)
{
return XZALLOC (struct syscalls_info);
}
static void
sysinfo_free_syscalls_desc (struct syscall_desc *sd)
{
xfree (sd->name);
}
static void
free_syscalls_info (void *arg)
{
struct syscalls_info *sysinfo = arg;
struct syscall_desc *sysdesc;
int i;
for (i = 0;
VEC_iterate (syscall_desc_p, sysinfo->syscalls, i, sysdesc);
i++)
sysinfo_free_syscalls_desc (sysdesc);
VEC_free (syscall_desc_p, sysinfo->syscalls);
xfree (sysinfo);
}
struct cleanup *
make_cleanup_free_syscalls_info (struct syscalls_info *sysinfo)
{
return make_cleanup (free_syscalls_info, sysinfo);
}
static void
syscall_create_syscall_desc (struct syscalls_info *sysinfo,
const char *name, int number)
{
struct syscall_desc *sysdesc = XZALLOC (struct syscall_desc);
sysdesc->name = xstrdup (name);
sysdesc->number = number;
VEC_safe_push (syscall_desc_p, sysinfo->syscalls, sysdesc);
}
/* Handle the start of a <syscalls_info> element. */
static void
syscall_start_syscalls_info (struct gdb_xml_parser *parser,
const struct gdb_xml_element *element,
void *user_data,
VEC(gdb_xml_value_s) *attributes)
{
struct syscall_parsing_data *data = user_data;
struct syscalls_info *sysinfo = data->sysinfo;
}
/* Handle the start of a <syscall> element. */
static void
syscall_start_syscall (struct gdb_xml_parser *parser,
const struct gdb_xml_element *element,
void *user_data, VEC(gdb_xml_value_s) *attributes)
{
struct syscall_parsing_data *data = user_data;
struct gdb_xml_value *attrs = VEC_address (gdb_xml_value_s, attributes);
int len, i;
/* syscall info. */
char *name = NULL;
int number = 0;
len = VEC_length (gdb_xml_value_s, attributes);
for (i = 0; i < len; i++)
{
if (strcmp (attrs[i].name, "name") == 0)
name = attrs[i].value;
else if (strcmp (attrs[i].name, "number") == 0)
number = * (ULONGEST *) attrs[i].value;
else
internal_error (__FILE__, __LINE__,
_("Unknown attribute name '%s'."), attrs[i].name);
}
syscall_create_syscall_desc (data->sysinfo, name, number);
}
/* The elements and attributes of an XML syscall document. */
static const struct gdb_xml_attribute syscall_attr[] = {
{ "number", GDB_XML_AF_NONE, gdb_xml_parse_attr_ulongest, NULL },
{ "name", GDB_XML_AF_NONE, NULL, NULL },
{ NULL, GDB_XML_AF_NONE, NULL, NULL }
};
static const struct gdb_xml_element syscalls_info_children[] = {
{ "syscall", syscall_attr, NULL,
GDB_XML_EF_OPTIONAL | GDB_XML_EF_REPEATABLE,
syscall_start_syscall, NULL },
{ NULL, NULL, NULL, GDB_XML_EF_NONE, NULL, NULL }
};
static const struct gdb_xml_element syselements[] = {
{ "syscalls_info", NULL, syscalls_info_children,
GDB_XML_EF_NONE, syscall_start_syscalls_info, NULL },
{ NULL, NULL, NULL, GDB_XML_EF_NONE, NULL, NULL }
};
static struct syscalls_info *
syscall_parse_xml (const char *document, xml_fetch_another fetcher,
void *fetcher_baton)
{
struct cleanup *result_cleanup;
struct gdb_xml_parser *parser;
struct syscall_parsing_data data;
char *expanded_text;
int i;
parser = gdb_xml_create_parser_and_cleanup (_("syscalls info"),
syselements, &data);
memset (&data, 0, sizeof (struct syscall_parsing_data));
data.sysinfo = allocate_syscalls_info ();
result_cleanup = make_cleanup_free_syscalls_info (data.sysinfo);
if (gdb_xml_parse (parser, document) == 0)
{
/* Parsed successfully. */
discard_cleanups (result_cleanup);
return data.sysinfo;
}
else
{
warning (_("Could not load XML syscalls info; ignoring"));
do_cleanups (result_cleanup);
return NULL;
}
}
/* Function responsible for initializing the information
about the syscalls. It reads the XML file and fills the
struct syscalls_info with the values.
Returns the struct syscalls_info if the file is valid, NULL otherwise. */
static const struct syscalls_info *
xml_init_syscalls_info (const char *filename)
{
char *full_file;
char *dirname;
struct syscalls_info *sysinfo;
struct cleanup *back_to;
full_file = xml_fetch_content_from_file (filename, gdb_datadir);
if (full_file == NULL)
{
warning (_("Could not open \"%s\""), filename);
return NULL;
}
back_to = make_cleanup (xfree, full_file);
dirname = ldirname (filename);
if (dirname != NULL)
make_cleanup (xfree, dirname);
sysinfo = syscall_parse_xml (full_file, xml_fetch_content_from_file, dirname);
do_cleanups (back_to);
return sysinfo;
}
/* Initializes the syscalls_info structure according to the
architecture. */
static void
init_sysinfo (void)
{
/* Did we already try to initialize the structure? */
if (have_initialized_sysinfo)
return;
/* if (xml_syscall_file == NULL)
internal_error (__FILE__, __LINE__,
_("This architecture has not set the XML syscall file "
"name. This is a bug and should not happen; please "
"report it.")); */
_sysinfo = xml_init_syscalls_info (xml_syscall_file);
have_initialized_sysinfo = 1;
if (_sysinfo == NULL)
{
if (xml_syscall_file)
/* The initialization failed. Let's show a warning
message to the user (just this time) and leave. */
warning (_("Could not load the syscall XML file `%s'.\n\
GDB will not be able to display syscall names."), xml_syscall_file);
else
/* There's no file to open. Let's warn the user. */
warning (_("There is no XML file to open.\n\
GDB will not be able to display syscall names."));
}
}
static int
xml_get_syscall_number (const struct syscalls_info *sysinfo,
const char *syscall_name)
{
struct syscall_desc *sysdesc;
int i;
if (sysinfo == NULL
|| syscall_name == NULL)
return UNKNOWN_SYSCALL;
for (i = 0;
VEC_iterate(syscall_desc_p, sysinfo->syscalls, i, sysdesc);
i++)
if (strcmp (sysdesc->name, syscall_name) == 0)
return sysdesc->number;
return UNKNOWN_SYSCALL;
}
static const char *
xml_get_syscall_name (const struct syscalls_info *sysinfo,
int syscall_number)
{
struct syscall_desc *sysdesc;
int i;
if (sysinfo == NULL
|| syscall_number < 0)
return NULL;
for (i = 0;
VEC_iterate(syscall_desc_p, sysinfo->syscalls, i, sysdesc);
i++)
if (sysdesc->number == syscall_number)
return sysdesc->name;
return NULL;
}
static int
xml_number_of_syscalls (const struct syscalls_info *sysinfo)
{
return (sysinfo == NULL ? 0 : VEC_length (syscall_desc_p,
sysinfo->syscalls));
}
static const char **
xml_list_of_syscalls (const struct syscalls_info *sysinfo)
{
struct syscall_desc *sysdesc;
const char **names = NULL;
int nsyscalls;
int i;
if (sysinfo == NULL)
return NULL;
nsyscalls = VEC_length (syscall_desc_p, sysinfo->syscalls);
names = xmalloc ((nsyscalls + 1) * sizeof (char *));
for (i = 0;
VEC_iterate (syscall_desc_p, sysinfo->syscalls, i, sysdesc);
i++)
names[i] = sysdesc->name;
names[i] = NULL;
return names;
}
void
set_xml_syscall_file_name (const char *name)
{
xml_syscall_file = name;
}
void
get_syscall_by_number (int syscall_number,
struct syscall *s)
{
init_sysinfo ();
s->number = syscall_number;
s->name = xml_get_syscall_name (_sysinfo, syscall_number);
}
void
get_syscall_by_name (const char *syscall_name,
struct syscall *s)
{
init_sysinfo ();
s->number = xml_get_syscall_number (_sysinfo, syscall_name);
s->name = syscall_name;
}
const char **
get_syscall_names (void)
{
init_sysinfo ();
return xml_list_of_syscalls (_sysinfo);
}
#endif /* ! HAVE_LIBEXPAT */

50
gdb/xml-syscall.h Normal file
View File

@ -0,0 +1,50 @@
/* Functions that provide the mechanism to parse a syscall XML file
and get its values.
Copyright (C) 2009 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 XML_SYSCALL_H
#define XML_SYSCALL_H 1
/* Function used to set the name of the file which contains
information about the system calls present in the current
architecture.
This function *should* be called before anything else, otherwise
GDB won't be able to find the correct XML file to open and get
the syscalls definitions. */
void set_xml_syscall_file_name (const char *name);
/* Function that retrieves the syscall name corresponding to the given
number. It puts the requested information inside 'struct syscall'. */
void get_syscall_by_number (int syscall_number, struct syscall *s);
/* Function that retrieves the syscall number corresponding to the given
name. It puts the requested information inside 'struct syscall'. */
void get_syscall_by_name (const char *syscall_name, struct syscall *s);
/* Function used to retrieve the list of syscalls in the system. This list
is returned as an array of strings. Returns the list of syscalls in the
system, or NULL otherwise. */
const char **get_syscall_names (void);
#endif /* XML_SYSCALL_H */