2010-12-30 00:11:49 +08:00
|
|
|
/* Target-dependent code for Analog Devices Blackfin processor, for GDB.
|
|
|
|
|
2017-01-01 14:50:51 +08:00
|
|
|
Copyright (C) 2005-2017 Free Software Foundation, Inc.
|
2010-12-30 00:11:49 +08:00
|
|
|
|
|
|
|
Contributed by Analog Devices, 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 "arch-utils.h"
|
|
|
|
#include "regcache.h"
|
|
|
|
#include "tramp-frame.h"
|
|
|
|
#include "trad-frame.h"
|
|
|
|
#include "osabi.h"
|
|
|
|
#include "xml-syscall.h"
|
|
|
|
#include "linux-tdep.h"
|
|
|
|
#include "bfin-tdep.h"
|
|
|
|
|
|
|
|
/* From <asm/sigcontext.h>. */
|
|
|
|
|
|
|
|
#define SIGCONTEXT_OFFSET 168
|
|
|
|
|
|
|
|
static const int bfin_linux_sigcontext_reg_offset[BFIN_NUM_REGS] =
|
|
|
|
{
|
|
|
|
0 * 4, /* %r0 */
|
|
|
|
1 * 4, /* %r1 */
|
|
|
|
2 * 4, /* %r2 */
|
|
|
|
3 * 4, /* %r3 */
|
|
|
|
4 * 4, /* %r4 */
|
|
|
|
5 * 4, /* %r5 */
|
|
|
|
6 * 4, /* %r6 */
|
|
|
|
7 * 4, /* %r7 */
|
|
|
|
8 * 4, /* %p0 */
|
|
|
|
9 * 4, /* %p1 */
|
|
|
|
10 * 4, /* %p2 */
|
|
|
|
11 * 4, /* %p3 */
|
|
|
|
12 * 4, /* %p4 */
|
|
|
|
13 * 4, /* %p5 */
|
|
|
|
14 * 4, /* %sp */
|
|
|
|
23 * 4, /* %fp */
|
|
|
|
24 * 4, /* %i0 */
|
|
|
|
25 * 4, /* %i1 */
|
|
|
|
26 * 4, /* %i2 */
|
|
|
|
27 * 4, /* %i3 */
|
|
|
|
28 * 4, /* %m0 */
|
|
|
|
29 * 4, /* %m1 */
|
|
|
|
30 * 4, /* %m2 */
|
|
|
|
31 * 4, /* %m3 */
|
|
|
|
36 * 4, /* %b0 */
|
|
|
|
37 * 4, /* %b1 */
|
|
|
|
38 * 4, /* %b2 */
|
|
|
|
39 * 4, /* %b3 */
|
|
|
|
32 * 4, /* %l0 */
|
|
|
|
33 * 4, /* %l1 */
|
|
|
|
34 * 4, /* %l2 */
|
|
|
|
35 * 4, /* %l3 */
|
|
|
|
17 * 4, /* %a0x */
|
|
|
|
15 * 4, /* %a0w */
|
|
|
|
18 * 4, /* %a1x */
|
|
|
|
16 * 4, /* %a1w */
|
|
|
|
19 * 4, /* %astat */
|
|
|
|
20 * 4, /* %rets */
|
|
|
|
40 * 4, /* %lc0 */
|
|
|
|
42 * 4, /* %lt0 */
|
|
|
|
44 * 4, /* %lb0 */
|
|
|
|
41 * 4, /* %lc1 */
|
|
|
|
43 * 4, /* %lt1 */
|
|
|
|
45 * 4, /* %lb1 */
|
|
|
|
-1, /* %cycles */
|
|
|
|
-1, /* %cycles2 */
|
|
|
|
-1, /* %usp */
|
|
|
|
46 * 4, /* %seqstat */
|
|
|
|
-1, /* syscfg */
|
|
|
|
21 * 4, /* %reti */
|
|
|
|
22 * 4, /* %retx */
|
|
|
|
-1, /* %retn */
|
|
|
|
-1, /* %rete */
|
|
|
|
21 * 4, /* %pc */
|
|
|
|
};
|
|
|
|
|
|
|
|
/* Signal trampolines. */
|
|
|
|
|
|
|
|
static void
|
|
|
|
bfin_linux_sigframe_init (const struct tramp_frame *self,
|
|
|
|
struct frame_info *this_frame,
|
|
|
|
struct trad_frame_cache *this_cache,
|
|
|
|
CORE_ADDR func)
|
|
|
|
{
|
|
|
|
CORE_ADDR sp = get_frame_sp (this_frame);
|
|
|
|
CORE_ADDR pc = get_frame_pc (this_frame);
|
|
|
|
CORE_ADDR sigcontext = sp + SIGCONTEXT_OFFSET;
|
|
|
|
const int *reg_offset = bfin_linux_sigcontext_reg_offset;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
for (i = 0; i < BFIN_NUM_REGS; i++)
|
|
|
|
if (reg_offset[i] != -1)
|
|
|
|
trad_frame_set_reg_addr (this_cache, i, sigcontext + reg_offset[i]);
|
|
|
|
|
|
|
|
/* This would come after the LINK instruction in the ret_from_signal
|
|
|
|
function, hence the frame id would be SP + 8. */
|
|
|
|
trad_frame_set_id (this_cache, frame_id_build (sp + 8, pc));
|
|
|
|
}
|
|
|
|
|
|
|
|
static const struct tramp_frame bfin_linux_sigframe =
|
|
|
|
{
|
|
|
|
SIGTRAMP_FRAME,
|
|
|
|
4,
|
|
|
|
{
|
|
|
|
{ 0x00ADE128, 0xffffffff }, /* P0 = __NR_rt_sigreturn; */
|
|
|
|
{ 0x00A0, 0xffff }, /* EXCPT 0; */
|
|
|
|
{ TRAMP_SENTINEL_INSN, -1 },
|
|
|
|
},
|
|
|
|
bfin_linux_sigframe_init,
|
|
|
|
};
|
|
|
|
|
|
|
|
static LONGEST
|
|
|
|
bfin_linux_get_syscall_number (struct gdbarch *gdbarch,
|
|
|
|
ptid_t ptid)
|
|
|
|
{
|
|
|
|
struct regcache *regcache = get_thread_regcache (ptid);
|
|
|
|
enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
|
|
|
|
/* The content of a register. */
|
|
|
|
gdb_byte buf[4];
|
|
|
|
/* The result. */
|
|
|
|
LONGEST ret;
|
|
|
|
|
|
|
|
/* Getting the system call number from the register.
|
|
|
|
When dealing with Blackfin architecture, this information
|
|
|
|
is stored at %p0 register. */
|
|
|
|
regcache_cooked_read (regcache, BFIN_P0_REGNUM, buf);
|
|
|
|
|
|
|
|
ret = extract_signed_integer (buf, 4, byte_order);
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
bfin_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
|
|
|
|
{
|
|
|
|
linux_init_abi (info, gdbarch);
|
|
|
|
|
|
|
|
/* Set the sigtramp frame sniffer. */
|
|
|
|
tramp_frame_prepend_unwinder (gdbarch, &bfin_linux_sigframe);
|
|
|
|
|
|
|
|
/* Functions for 'catch syscall'. */
|
Partial fix for PR breakpoints/10737: Make syscall info be per-arch instead of global
This patch intends to partially fix PR breakpoints/10737, which is
about making the syscall information (for the "catch syscall" command)
be per-arch, instead of global. This is not a full fix because of the
other issues pointed by Pedro here:
<https://sourceware.org/bugzilla/show_bug.cgi?id=10737#c5>
However, I consider it a good step towards the real fix. It will also
help me fix <https://sourceware.org/bugzilla/show_bug.cgi?id=17402>.
What this patch does, basically, is move the "syscalls_info"
struct to gdbarch. Currently, the syscall information is stored in a
global variable inside gdb/xml-syscall.c, which means that there is no
easy way to correlate this info with the current target or
architecture being used, for example. This causes strange behaviors,
because the syscall info is not re-read when the arch changes. For
example, if you put a syscall catchpoint in syscall 5 on i386 (syscall
open), and then load a x86_64 program on GDB and put the same syscall
5 there (fstat on x86_64), you will still see that GDB tells you that
it is catching "open", even though it is not. With this patch, GDB
correctly says that it will be catching fstat syscalls.
(gdb) set architecture i386
The target architecture is assumed to be i386
(gdb) catch syscall 5
Catchpoint 1 (syscall 'open' [5])
(gdb) set architecture i386:x86-64
The target architecture is assumed to be i386:x86-64
(gdb) catch syscall 5
Catchpoint 2 (syscall 'open' [5])
But with the patch:
(gdb) set architecture i386
The target architecture is assumed to be i386
(gdb) catch syscall 5
Catchpoint 1 (syscall 'open' [5])
(gdb) set architecture i386:x86-64
The target architecture is assumed to be i386:x86-64
(gdb) catch syscall 5
Catchpoint 2 (syscall 'fstat' [5])
As I said, there are still some problems on the "catch syscall"
mechanism, because (for example) the user should be able to "catch
syscall open" on i386, and then expect "open" to be caught also on
x86_64. Currently, it doesn't work. I intend to work on this later.
gdb/
2014-11-20 Sergio Durigan Junior <sergiodj@redhat.com>
PR breakpoints/10737
* amd64-linux-tdep.c (amd64_linux_init_abi_common): Adjust call to
set_xml_syscall_file_name to provide gdbarch.
* arm-linux-tdep.c (arm_linux_init_abi): Likewise.
* bfin-linux-tdep.c (bfin_linux_init_abi): Likewise.
* breakpoint.c (print_it_catch_syscall): Adjust call to
get_syscall_by_number to provide gdbarch.
(print_one_catch_syscall): Likewise.
(print_mention_catch_syscall): Likewise.
(print_recreate_catch_syscall): Likewise.
(catch_syscall_split_args): Adjust calls to get_syscall_by_number
and get_syscall_by_name to provide gdbarch.
(catch_syscall_completer): Adjust call to get_syscall_names to
provide gdbarch.
* gdbarch.c: Regenerate.
* gdbarch.h: Likewise.
* gdbarch.sh: Forward declare "struct syscalls_info".
(xml_syscall_file): New variable.
(syscalls_info): Likewise.
* i386-linux-tdep.c (i386_linux_init_abi): Adjust call to
set_xml_syscall_file_name to provide gdbarch.
* mips-linux-tdep.c (mips_linux_init_abi): Likewise.
* ppc-linux-tdep.c (ppc_linux_init_abi): Likewise.
* s390-linux-tdep.c (s390_gdbarch_init): Likewise.
* sparc-linux-tdep.c (sparc32_linux_init_abi): Likewise.
* sparc64-linux-tdep.c (sparc64_linux_init_abi): Likewise.
* xml-syscall.c: Include gdbarch.h.
(set_xml_syscall_file_name): Accept gdbarch parameter.
(get_syscall_by_number): Likewise.
(get_syscall_by_name): Likewise.
(get_syscall_names): Likewise.
(my_gdb_datadir): Delete global variable.
(struct syscalls_info) <my_gdb_datadir>: New variable.
(struct syscalls_info) <sysinfo>: Rename variable to
"syscalls_info".
(sysinfo): Delete global variable.
(have_initialized_sysinfo): Likewise.
(xml_syscall_file): Likewise.
(sysinfo_free_syscalls_desc): Rename to...
(syscalls_info_free_syscalls_desc): ... this.
(free_syscalls_info): Rename "sysinfo" to "syscalls_info". Adjust
code to the new layout of "struct syscalls_info".
(make_cleanup_free_syscalls_info): Rename parameter "sysinfo" to
"syscalls_info".
(syscall_create_syscall_desc): Likewise.
(syscall_start_syscall): Likewise.
(syscall_parse_xml): Likewise.
(xml_init_syscalls_info): Likewise. Drop "const" from return value.
(init_sysinfo): Rename to...
(init_syscalls_info): ...this. Add gdbarch as a parameter.
Adjust function to deal with gdbarch.
(xml_get_syscall_number): Delete parameter sysinfo. Accept
gdbarch as a parameter. Adjust code.
(xml_get_syscall_name): Likewise.
(xml_list_of_syscalls): Likewise.
(set_xml_syscall_file_name): Accept gdbarch as parameter.
(get_syscall_by_number): Likewise.
(get_syscall_by_name): Likewise.
(get_syscall_names): Likewise.
* xml-syscall.h (set_xml_syscall_file_name): Likewise.
(get_syscall_by_number): Likewise.
(get_syscall_by_name): Likewise.
(get_syscall_names): Likewise.
gdb/testsuite/
2014-11-20 Sergio Durigan Junior <sergiodj@redhat.com>
PR breakpoints/10737
* gdb.base/catch-syscall.exp (do_syscall_tests): Call
test_catch_syscall_multi_arch.
(test_catch_syscall_multi_arch): New function.
2014-11-21 01:28:18 +08:00
|
|
|
set_xml_syscall_file_name (gdbarch, "syscalls/bfin-linux.xml");
|
2010-12-30 00:11:49 +08:00
|
|
|
set_gdbarch_get_syscall_number (gdbarch,
|
|
|
|
bfin_linux_get_syscall_number);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
_initialize_bfin_linux_tdep (void)
|
|
|
|
{
|
|
|
|
gdbarch_register_osabi (bfd_arch_bfin, 0, GDB_OSABI_LINUX,
|
|
|
|
bfin_linux_init_abi);
|
|
|
|
}
|