* Fw: Unreviewed patch (m32r-linux support) @ 2004-09-15 8:01 Kei Sakamoto 2004-09-15 11:25 ` Mark Kettenis 0 siblings, 1 reply; 11+ messages in thread From: Kei Sakamoto @ 2004-09-15 8:01 UTC (permalink / raw) To: Mark Kettenis; +Cc: gdb-patches [-- Attachment #1: Type: text/plain, Size: 11090 bytes --] Mark, Would you review the attached patch? I'm afraid that you are still busy because of moving. But it seems you are the best person to review it because I revised it based on your advise. If you are too busy, please let me know. Thank you. Kei Sakamoto > Hello, > > Would anyone take a look at this patch? > Thank you in advance. > > Kei Sakamoto > > From: "Kei Sakamoto" <sakamoto.kei@renesas.com> > To: <gdb-patches@sources.redhat.com> > Sent: Friday, August 20, 2004 3:14 PM > Subject: Re: [RFA/m32r] m32r-linux support > > > > Hello, > > > > I revised the patch of m32r-linux support. > > > > Thanks to Mark Kettenis' advice, I removed many unnecessary codes > > from it and simplified it. But it still contains some stuff > > to support older versions of Linux because Linux/M32R does not > > support PTRACE_GETREGS. > > > > I also removed the gdbserver support from it. I'll post it > > as another patch after this patch is accepted. > > > > OK to commit? > > > > 2004-08-20 Kei Sakamoto <sakamoto.kei@renesas.com> > > > > Add m32r-linux support. > > * configure.tgt: Add m32r*-*-linux*. > > * Makefile.in (ALLDEPFILES): Add m32r-tdep.c, m32r-linux-nat.c and > > m32r-linux-tdep.c. > > (m32r-linux-nat.o, m32r-linux-tdep.o): New dependencies. > > * m32r-linux-nat.c, m32r-linux-tdep.c, config/m32r/linux.mh, > > config/m32r/linux.mt, config/m32r/m32r.mh, config/m32r/nm-linux.h, > > config/m32r/tm-linux.h: New files. > > > > Kei Sakamoto said: > > > > > Hello, Mark, > > > > > > Thank you for your reply. It is very useful. > > > > > > There is the summer holidays in Japan next week. So I'll modify my > > > patch and post it after that. > > > > > > Kei Sakamoto > > > > > > Mark Kettenis said: > > > > From: "Kei Sakamoto" <sakamoto.kei@renesas.com> > > > > Date: Thu, 5 Aug 2004 14:11:07 +0900 > > > > > > > > Hello, > > > > > > > > Hi Kei, > > > > > > > > First can you seperate out the gdbserver support, and submit that as a > > > > seperate patch? Daniel will have to review that part of the code. > > > > Making it seperate will make it more likely that the code can be > > > > checked in soon. > > > > > > > > The attached patch adds m32r-linux support. > > > > The M32R architecture is not added to the official Linux kernel yet. > > > > But Linux on M32R is already available. > > > > http://www.linux-m32r.org/ > > > > > > > > So Linux/M32R is a brand new port? Great, but in that case I have > > > > some comments. It looks like you based your GDB port on the > > > > Linux/i386 stuff. That's great, but you must realize that part of the > > > > i386 code that you copied and modified is only there to support older > > > > versions of Linux. I hope it isn't necessary for Linux/M32R and would > > > > like you to remove it before this gets committed. I've got a few > > > > other comments too. Here we go... > > > > > > > > diff -u -r1.144 configure.tgt=0A= > > > > --- configure.tgt 26 Jun 2004 10:06:34 -0000 1.144=0A= > > > > +++ configure.tgt 5 Aug 2004 04:48:33 -0000=0A= > > > > @@ -102,7 +103,10 @@ > > > > ;; > > > > ia64*-*-*) gdb_target=ia64 ;; > > > > > > > > -m32r-*-*) gdb_target=m32r ;; > > > > +m32r*-*-elf*) gdb_target=m32r ;; > > > > +m32r*-*-linux*) gdb_target=linux > > > > + build_gdbserver=3Dyes > > > > + ;; > > > > > > > > m68hc11*-*-*|m6811*-*-*) gdb_target=m68hc11 ;; > > > > > > > > It might be a good idea to keep m32r-*-* as the generic M32R target. > > > > Just put the m32r-*-* entry in front of it. > > > > > > > > diff -N m32r-linux-nat.c > > > > --- /dev/null 1 Jan 1970 00:00:00 -0000 > > > > +++ m32r-linux-nat.c 5 Aug 2004 04:48:33 -0000 > > > > +/* The register sets used in GNU/Linux ELF core-dumps are identical to > > > > + the register sets in `struct user' that is used for a.out > > > > + core-dumps, and is also used by `ptrace'. The corresponding types > > > > + are `elf_gregset_t' for the general-purpose registers (with > > > > + `elf_greg_t' the type of a single GP register) and `elf_fpregset_t' > > > > + for the floating-point registers. > > > > + > > > > + Those types used to be available under the names `gregset_t' and > > > > + `fpregset_t' too, and this file used those names in the past. But > > > > + those names are now used for the register sets used in the > > > > + `mcontext_t' type, and have a different size and layout. */ > > > > + > > > > +/* Mapping between the general-purpose registers in `struct user' > > > > + format and GDB's register array layout. */ > > > > +static int regmap[] = { > > > > + 4, 5, 6, 7, 0, 1, 2, 8, > > > > + 9, 10, 11, 12, 13, 24, 25, 23, > > > > + 19, 31, 26, 23, 20, 30, 16, 15, > > > > + 32 > > > > +}; > > > > > > > > Does Linux/M32R support a.out? That would really surprise me. So I > > > > don't think you need this stuff. > > > > > > > > +#define M32R_NUM_GREGS 25=0A= > > > > > > > > I think that one really belongs in m32r-tdep.h. > > > > > > > > +/* Doee apply to the corresponding SET requests as well. * > > > > +#define GETREGS_SUPPLIES(regno) (0 <=3D (regno) && (regno) <= > > > M32R_NUM_GREGS) > > > > +#define GETFPREGS_SUPPLIES(regno) 0 > > > > > > > > Does the M32R support floating point registers at all? If not, you > > > > could rip out all the FPREGS stuff. > > > > > > > > +/* Does the current host support the GETREGS request? */ > > > > +int have_ptrace_getregs = > > > > +#ifdef HAVE_PTRACE_GETREGS > > > > + 1 > > > > +#else > > > > + 0 > > > > +#endif > > > > + ; > > > > > > > > I really hope that all released M32R kernels support the > > > > PTRACE_GETREGS request. In that case this should not be necessary. > > > > > > > > > > > > +/* Support for the user struct. */ > > > > + > > > > +/* Return the address of register REGNUM. BLOCKEND is the value of > > > > + u.u_ar0, which should point to the registers. */ > > > > + > > > > +CORE_ADDR > > > > +register_u_addr (CORE_ADDR blockend, int regnum) > > > > +{ > > > > + return (blockend + 4 * regmap[regnum]); > > > > +} > > > > + > > > > +/* Return the size of the user struct. */ > > > > + > > > > +int > > > > +kernel_u_size (void) > > > > +{ > > > > + return (sizeof (struct user)); > > > > +} > > > > > > > > The `user struct' is a wart from ancient UNIX. There really is no > > > > point in supporting it on modern versions of Linux. If Linux/M32R is > > > > ELF-only and fully supports PTRACE_GETREGS, this can go too. > > > > > > > > +#ifdef HAVE_PTRACE_GETREGS > > > > + > > > > +/* Fetch all general-purpose registers from process/thread TID and > > > > + store their values in GDB's register array. */ > > > > + > > > > +static void > > > > +fetch_regs (int tid) > > > > +{ > > > > + elf_gregset_t regs; > > > > + > > > > > > > > This code in #ifdef HAVE_PTRACE_GETREGS can be simplified considerably > > > > if you assume that PTRACE_GETREGS works. Move the code to > > > > fetch_inferior_registers() and store_inferior_registers() below. > > > > > > > > +/* Transferring arbitrary registers between GDB and inferior. */ > > > > + > > > > +/* Check if register REGNO in the child process is accessible. > > > > + If we are accessing registers directly via the U area, only the > > > > + general-purpose registers are available. > > > > + All registers should be accessible if we have GETREGS support. */ > > > > + > > > > +int > > > > +cannot_fetch_register (int regno) > > > > +{ > > > > + gdb_assert (regno >= 0 && regno < NUM_REGS); > > > > + return (!have_ptrace_getregs && regmap[regno] == -1); > > > > +} > > > > + > > > > +int > > > > +cannot_store_register (int regno) > > > > +{ > > > > + gdb_assert (regno >= 0 && regno < NUM_REGS); > > > > + return (!have_ptrace_getregs && regmap[regno] == -1); > > > > +} > > > > > > > > These functions should no longer be necessary. > > > > > > > > +/* Accessing registers through the U area, one at a time. */ > > > > + > > > > +/* Fetch one register. */ > > > > + > > > > +static void > > > > +fetch_register (int regno) > > > > +{ > > > > + int tid; > > > > + int val; > > > > + > > > > + gdb_assert (!have_ptrace_getregs); > > > > + if (cannot_fetch_register (regno)) > > > > + { > > > > + regcache_raw_supply (current_regcache, regno, NULL); > > > > + return; > > > > + }= > > > > > > > > This can go too; no U area anymore :-). > > > > > > > > diff -N config/m32r/linux.mh > > > > --- /dev/null 1 Jan 1970 00:00:00 -0000 > > > > +++ config/m32r/linux.mh 5 Aug 2004 04:48:34 -0000 > > > > @@ -0,0 +1,9 @@ > > > > +# Host: M32R based machine running GNU/Linux > > > > + > > > > +NAT_FILE= nm-linux.h > > > > +NATDEPFILES= infptrace.o inftarg.o fork-child.o corelow.o \ > > > > + core-aout.o m32r-linux-nat.o linux-proc.o gcore.o \ > > > > + proc-service.o thread-db.o lin-lwp.o linux-nat.o > > > > + > > > > +LOADLIBES=3D -ldl -rdynamic > > > > > > > > core-aout.o shouldn't be necessary. > > > > > > > > diff -N config/m32r/m32r.mh > > > > > > > > Please remove this file. > > > > > > > > diff -u -r1.7 m32r.mt > > > > --- config/m32r/m32r.mt 16 Oct 2003 02:36:39 -0000 1.7 > > > > +++ config/m32r/m32r.mt 5 Aug 2004 04:48:34 -0000 > > > > @@ -1,4 +1,5 @@ > > > > # Target: Renesas m32r processor > > > > TDEPFILES= m32r-tdep.o monitor.o m32r-rom.o dsrec.o remote-m32r-sdi.o > > > > +TM_FILE= tm-m32r.h > > > > SIM_OBS = remote-sim.o > > > > SIM = ../sim/m32r/libsim.a > > > > > > > > This shouldn't be necessary. See below. > > > > > > > > diff -N config/m32r/nm-linux.h > > > > --- /dev/null 1 Jan 1970 00:00:00 -0000 > > > > +++ config/m32r/nm-linux.h 5 Aug 2004 04:48:34 -0000 > > > > > > > > [snip] > > > > > > > > +/* Support for the user area. */ > > > > + > > > > +/* Return the size of the user struct. */ > > > > +extern int kernel_u_size (void); > > > > +#define KERNEL_U_SIZE kernel_u_size() > > > > + > > > > +/* This is the amount to subtract from u.u_ar0 > > > > + to get the offset in the core file of the register values. */ > > > > +#define KERNEL_U_ADDR 0x0 > > > > + > > > > +/* Offset of the registers within the user area. */ > > > > +#define U_REGS_OFFSET 0 > > > > + > > > > +extern CORE_ADDR register_u_addr (CORE_ADDR blockend, int regnum); > > > > +#define REGISTER_U_ADDR(addr, blockend, regnum) \ > > > > + (addr) = register_u_addr (blockend, regnum) > > > > > > > > This user area stuff can go too. > > > > > > > > diff -N config/m32r/tm-m32r.h > > > > > > > > This file contains nothing useful. Please remove and adjust tm-linux.h. > > > > > > > > I hope you can make the changes. The simplifications will make > > > > maintaining the code much easier. > > > [-- Attachment #2: m32r-linux.patch --] [-- Type: application/octet-stream, Size: 26453 bytes --] Index: Makefile.in =================================================================== RCS file: /cvs/src/src/gdb/Makefile.in,v retrieving revision 1.608 diff -u -r1.608 Makefile.in --- Makefile.in 14 Aug 2004 20:40:14 -0000 1.608 +++ Makefile.in 20 Aug 2004 05:54:29 -0000 @@ -1373,6 +1373,8 @@ infptrace.c inftarg.c irix4-nat.c irix5-nat.c \ libunwind-frame.c \ lynx-nat.c m3-nat.c \ + m32r-tdep.c \ + m32r-linux-tdep.c m32r-linux-nat.c \ m68hc11-tdep.c \ m68k-tdep.c \ m68kbsd-nat.c m68kbsd-tdep.c \ @@ -2114,6 +2116,11 @@ $(expression_h) $(value_h) $(gdbcore_h) $(target_h) $(m2_lang_h) m2-valprint.o: m2-valprint.c $(defs_h) $(symtab_h) $(gdbtypes_h) \ $(m2_lang_h) +m32r-linux-nat.o: m32r-linux-nat.c $(defs_h) $(inferior_h) $(gdbcore_h) \ + $(regcache_h) $(linux_nat_h) $(gdb_assert_h) $(gdb_string_h) +m32r-linux-tdep.o: m32r-linux-tdep.c $(defs_h) $(gdbcore_h) $(frame_h) \ + $(value_h) $(regcache_h) $(inferior_h) $(osabi_h) $(reggroups_h) \ + $(gdb_string_h) $(glibc_tdep_h) $(solib_svr4_h) m32r-rom.o: m32r-rom.c $(defs_h) $(gdbcore_h) $(target_h) $(monitor_h) \ $(serial_h) $(symtab_h) $(command_h) $(gdbcmd_h) $(symfile_h) \ $(gdb_string_h) $(objfiles_h) $(inferior_h) $(regcache_h) Index: configure.tgt =================================================================== RCS file: /cvs/src/src/gdb/configure.tgt,v retrieving revision 1.146 diff -u -r1.146 configure.tgt --- configure.tgt 12 Aug 2004 22:29:56 -0000 1.146 +++ configure.tgt 20 Aug 2004 05:54:29 -0000 @@ -106,7 +106,8 @@ ;; ia64*-*-*) gdb_target=ia64 ;; -m32r-*-*) gdb_target=m32r ;; +m32r*-*-linux*) gdb_target=linux ;; +m32r*-*-*) gdb_target=m32r ;; m68hc11*-*-*|m6811*-*-*) gdb_target=m68hc11 ;; Index: m32r-linux-nat.c =================================================================== RCS file: m32r-linux-nat.c diff -N m32r-linux-nat.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ m32r-linux-nat.c 20 Aug 2004 05:54:29 -0000 @@ -0,0 +1,345 @@ +/* Native-dependent code for GNU/Linux m32r. + + Copyright 2004 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 2 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, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include "defs.h" +#include "inferior.h" +#include "gdbcore.h" +#include "regcache.h" +#include "linux-nat.h" + +#include "gdb_assert.h" +#include "gdb_string.h" +#include <sys/ptrace.h> +#include <sys/user.h> +#include <sys/procfs.h> + +/* Prototypes for supply_gregset etc. */ +#include "gregset.h" +\f + + +/* The register sets used in GNU/Linux ELF core-dumps are identical to + the register sets in `struct user' that is used by `ptrace'. The + corresponding types are `elf_gregset_t' for the general-purpose + registers (with `elf_greg_t' the type of a single GP register) and + `elf_fpregset_t' for the floating-point registers. + + Those types used to be available under the names `gregset_t' and + `fpregset_t' too, and this file used those names in the past. But + those names are now used for the register sets used in the + `mcontext_t' type, and have a different size and layout. */ + +/* Mapping between the general-purpose registers in `struct user' + format and GDB's register array layout. */ +static int regmap[] = { + 4, 5, 6, 7, 0, 1, 2, 8, + 9, 10, 11, 12, 13, 24, 25, 23, + 19, 31, 26, 23, 20, 30, 16, 15, + 32 +}; + +/* Doee apply to the corresponding SET requests as well. */ +#define GETREGS_SUPPLIES(regno) (0 <= (regno) && (regno) <= NUM_REGS) + +/* Does the current host support the GETREGS request? */ +int have_ptrace_getregs = +#ifdef HAVE_PTRACE_GETREGS + 1 +#else + 0 +#endif + ; +\f + +/* Transfering the general-purpose registers between GDB, inferiors + and core files. */ + +/* Fill GDB's register array with the general-purpose register values + in *GREGSETP. */ + +void +supply_gregset (elf_gregset_t * gregsetp) +{ + elf_greg_t *regp = (elf_greg_t *) gregsetp; + int i; + + for (i = 0; i < NUM_REGS; i++) + regcache_raw_supply (current_regcache, i, regp + regmap[i]); +} + +/* Fill register REGNO (if it is a general-purpose register) in + *GREGSETPS with the value in GDB's register array. If REGNO is -1, + do this for all registers. */ + +void +fill_gregset (elf_gregset_t * gregsetp, int regno) +{ + elf_greg_t *regp = (elf_greg_t *) gregsetp; + int i; + + for (i = 0; i < NUM_REGS; i++) + if (regno == -1 || regno == i) + regcache_raw_collect (current_regcache, i, regp + regmap[i]); +} + +#ifdef HAVE_PTRACE_GETREGS + +/* Fetch all general-purpose registers from process/thread TID and + store their values in GDB's register array. */ + +static void +fetch_regs (int tid) +{ + elf_gregset_t regs; + + if (ptrace (PTRACE_GETREGS, tid, 0, (int) ®s) < 0) + { + if (errno == EIO) + { + /* The kernel we're running on doesn't support the GETREGS + request. Reset `have_ptrace_getregs'. */ + have_ptrace_getregs = 0; + return; + } + + perror_with_name ("Couldn't get registers"); + } + + supply_gregset (®s); +} + +/* Store all valid general-purpose registers in GDB's register array + into the process/thread specified by TID. */ + +static void +store_regs (int tid, int regno) +{ + elf_gregset_t regs; + + if (ptrace (PTRACE_GETREGS, tid, 0, (int) ®s) < 0) + perror_with_name ("Couldn't get registers"); + + fill_gregset (®s, regno); + + if (ptrace (PTRACE_SETREGS, tid, 0, (int) ®s) < 0) + perror_with_name ("Couldn't write registers"); +} + +#else + +static void +fetch_regs (int tid) +{ +} +static void +store_regs (int tid, int regno) +{ +} + +#endif +\f + +/* Transfering floating-point registers between GDB, inferiors and cores. */ + +/* Fill GDB's register array with the floating-point register values in + *FPREGSETP. */ + +void +supply_fpregset (elf_fpregset_t * fpregsetp) +{ +} + +/* Fill register REGNO (if it is a floating-point register) in + *FPREGSETP with the value in GDB's register array. If REGNO is -1, + do this for all registers. */ + +void +fill_fpregset (elf_fpregset_t * fpregsetp, int regno) +{ +} + +\f + +/* Transferring arbitrary registers between GDB and inferior. */ + +/* Check if register REGNO in the child process is accessible. + If we are accessing registers directly via the U area, only the + general-purpose registers are available. + All registers should be accessible if we have GETREGS support. */ + +int +cannot_fetch_register (int regno) +{ + gdb_assert (regno >= 0 && regno < NUM_REGS); + return (!have_ptrace_getregs && regmap[regno] == -1); +} + +int +cannot_store_register (int regno) +{ + gdb_assert (regno >= 0 && regno < NUM_REGS); + return (!have_ptrace_getregs && regmap[regno] == -1); +} + +/* Accessing registers through the U area, one at a time. */ + +/* Fetch one register. */ + +static void +fetch_register (int regno) +{ + int tid; + int val; + + gdb_assert (!have_ptrace_getregs); + if (cannot_fetch_register (regno)) + { + regcache_raw_supply (current_regcache, regno, NULL); + return; + } + + /* GNU/Linux LWP ID's are process ID's. */ + tid = TIDGET (inferior_ptid); + if (tid == 0) + tid = PIDGET (inferior_ptid); /* Not a threaded program. */ + + errno = 0; + val = ptrace (PTRACE_PEEKUSER, tid, 4 * regmap[regno], 0); + if (errno != 0) + error ("Couldn't read register %s (#%d): %s.", REGISTER_NAME (regno), + regno, safe_strerror (errno)); + + regcache_raw_supply (current_regcache, regno, &val); +} + +/* Store one register. */ + +static void +store_register (int regno) +{ + int tid; + int val; + + gdb_assert (!have_ptrace_getregs); + if (cannot_store_register (regno)) + return; + + /* GNU/Linux LWP ID's are process ID's. */ + tid = TIDGET (inferior_ptid); + if (tid == 0) + tid = PIDGET (inferior_ptid); /* Not a threaded program. */ + + errno = 0; + regcache_raw_collect (current_regcache, regno, &val); + ptrace (PTRACE_POKEUSER, tid, 4 * regmap[regno], val); + if (errno != 0) + error ("Couldn't write register %s (#%d): %s.", REGISTER_NAME (regno), + regno, safe_strerror (errno)); +} + +/* Fetch register REGNO from the child process. If REGNO is -1, do + this for all registers (including the floating point and SSE + registers). */ + +void +fetch_inferior_registers (int regno) +{ + int tid; + + /* Use the old method of peeking around in `struct user' if the + GETREGS request isn't available. */ + if (!have_ptrace_getregs) + { + int i; + + for (i = 0; i < NUM_REGS; i++) + if (regno == -1 || regno == i) + fetch_register (i); + + return; + } + + /* GNU/Linux LWP ID's are process ID's. */ + tid = TIDGET (inferior_ptid); + if (tid == 0) + tid = PIDGET (inferior_ptid); /* Not a threaded program. */ + + /* Use the PTRACE_GETFPXREGS request whenever possible, since it + transfers more registers in one system call, and we'll cache the + results. */ + if (regno == -1) + { + fetch_regs (tid); + + /* The call above might reset `have_ptrace_getregs'. */ + if (!have_ptrace_getregs) + { + fetch_inferior_registers (regno); + return; + } + + return; + } + + if (GETREGS_SUPPLIES (regno)) + { + fetch_regs (tid); + return; + } + + internal_error (__FILE__, __LINE__, + "Got request for bad register number %d.", regno); +} + +/* Store register REGNO back into the child process. If REGNO is -1, + do this for all registers (including the floating point and SSE + registers). */ +void +store_inferior_registers (int regno) +{ + int tid; + + /* Use the old method of poking around in `struct user' if the + SETREGS request isn't available. */ + if (!have_ptrace_getregs) + { + int i; + + for (i = 0; i < NUM_REGS; i++) + if (regno == -1 || regno == i) + store_register (i); + + return; + } + + /* GNU/Linux LWP ID's are process ID's. */ + if ((tid = TIDGET (inferior_ptid)) == 0) + tid = PIDGET (inferior_ptid); /* Not a threaded program. */ + + if (regno == -1 || GETREGS_SUPPLIES (regno)) + { + store_regs (tid, regno); + return; + } + + internal_error (__FILE__, __LINE__, + "Got request to store bad register number %d.", regno); +} Index: m32r-linux-tdep.c =================================================================== RCS file: m32r-linux-tdep.c diff -N m32r-linux-tdep.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ m32r-linux-tdep.c 20 Aug 2004 05:54:29 -0000 @@ -0,0 +1,334 @@ +/* Target-dependent code for GNU/Linux m32r. + + Copyright 2004 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 2 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, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include "defs.h" +#include "gdbcore.h" +#include "frame.h" +#include "value.h" +#include "regcache.h" +#include "inferior.h" +#include "osabi.h" +#include "reggroups.h" + +#include "gdb_string.h" + +#include "glibc-tdep.h" +#include "solib-svr4.h" + +#include "trad-frame.h" +#include "frame-unwind.h" +\f + +/* Recognizing signal handler frames. */ + +/* GNU/Linux has two flavors of signals. Normal signal handlers, and + "realtime" (RT) signals. The RT signals can provide additional + information to the signal handler if the SA_SIGINFO flag is set + when establishing a signal handler using `sigaction'. It is not + unlikely that future versions of GNU/Linux will support SA_SIGINFO + for normal signals too. */ + +/* When the m32r Linux kernel calls a signal handler and the + SA_RESTORER flag isn't set, the return address points to a bit of + code on the stack. This function returns whether the PC appears to + be within this bit of code. + + The instruction sequence for normal signals is + ldi r7, #__NR_sigreturn + trap #2 + or 0x67 0x77 0x10 0xf2. + + Checking for the code sequence should be somewhat reliable, because + the effect is to call the system call sigreturn. This is unlikely + to occur anywhere other than in a signal trampoline. + + It kind of sucks that we have to read memory from the process in + order to identify a signal trampoline, but there doesn't seem to be + any other way. Therefore we only do the memory reads if no + function name could be identified, which should be the case since + the code is on the stack. + + Detection of signal trampolines for handlers that set the + SA_RESTORER flag is in general not possible. Unfortunately this is + what the GNU C Library has been doing for quite some time now. + However, as of version 2.1.2, the GNU C Library uses signal + trampolines (named __restore and __restore_rt) that are identical + to the ones used by the kernel. Therefore, these trampolines are + supported too. */ + +/* If PC is in a sigtramp routine, return the address of the start of + the routine. Otherwise, return 0. */ + +static CORE_ADDR +m32r_linux_sigtramp_start (CORE_ADDR pc) +{ + /* We only recognize a signal trampoline if PC is at the start of + one of the instructions. We optimize for finding the PC at the + start of the instruction sequence, as will be the case when the + trampoline is not the first frame on the stack. We assume that + in the case where the PC is not at the start of the instruction + sequence, there will be a few trailing readable bytes on the + stack. */ + + if (pc % 2 != 0) + { + if (read_memory_unsigned_integer (pc, 2) == 0x10f2) + pc -= 2; + else + return 0; + } + + if (read_memory_unsigned_integer (pc, 4) != 0x677710f2) + return 0; + + return pc; +} + +/* This function does the same for RT signals. Here the instruction + sequence is + ldi r7, #__NR_rt_sigreturn + trap #2 + or 0x97 0xf0 0x00 0xad 0x10 0xf2 0xf0 0x00. + + The effect is to call the system call rt_sigreturn. */ + +/* If PC is in a RT sigtramp routine, return the address of the start + of the routine. Otherwise, return 0. */ + +static CORE_ADDR +m32r_linux_rt_sigtramp_start (CORE_ADDR pc) +{ + /* We only recognize a signal trampoline if PC is at the start of + one of the instructions. We optimize for finding the PC at the + start of the instruction sequence, as will be the case when the + trampoline is not the first frame on the stack. We assume that + in the case where the PC is not at the start of the instruction + sequence, there will be a few trailing readable bytes on the + stack. */ + + if (pc % 2 != 0) + return 0; + + switch (read_memory_unsigned_integer (pc, 4)) + { + case 0x97f000ad: + if (read_memory_unsigned_integer (pc + 4, 4) == 0x10f2f000) + return pc; + break; + case 0x10f2f000: + if (read_memory_unsigned_integer (pc - 4, 4) == 0x97f000ad) + return pc - 4; + break; + } + + return 0; +} + +static int +m32r_linux_pc_in_sigtramp (CORE_ADDR pc, char *name) +{ + /* If we have NAME, we can optimize the search. The trampolines are + named __restore and __restore_rt. However, they aren't dynamically + exported from the shared C library, so the trampoline may appear to + be part of the preceding function. This should always be sigaction, + __sigaction, or __libc_sigaction (all aliases to the same function). */ + if (name == NULL || strstr (name, "sigaction") != NULL) + return (m32r_linux_sigtramp_start (pc) != 0 + || m32r_linux_rt_sigtramp_start (pc) != 0); + + return (strcmp ("__restore", name) == 0 + || strcmp ("__restore_rt", name) == 0); +} + +/* From <asm/sigcontext.h>. */ +static int m32r_linux_sc_reg_offset[] = { + 4 * 4, /* r0 */ + 5 * 4, /* r1 */ + 6 * 4, /* r2 */ + 7 * 4, /* r3 */ + 0 * 4, /* r4 */ + 1 * 4, /* r5 */ + 2 * 4, /* r6 */ + 8 * 4, /* r7 */ + 9 * 4, /* r8 */ + 10 * 4, /* r9 */ + 11 * 4, /* r10 */ + 12 * 4, /* r11 */ + 13 * 4, /* r12 */ + 21 * 4, /* fp */ + 22 * 4, /* lr */ + -1 * 4, /* sp */ + 16 * 4, /* psw */ + -1 * 4, /* cbr */ + 23 * 4, /* spi */ + 20 * 4, /* spu */ + 19 * 4, /* bpc */ + 17 * 4, /* pc */ + 15 * 4, /* accl */ + 14 * 4 /* acch */ +}; + +#define M32R_SP_REGNUM 15 + +struct m32r_frame_cache +{ + CORE_ADDR base, pc; + struct trad_frame_saved_reg *saved_regs; +}; + +static struct m32r_frame_cache * +m32r_linux_sigtramp_frame_cache (struct frame_info *next_frame, + void **this_cache) +{ + struct m32r_frame_cache *cache; + CORE_ADDR sigcontext_addr, addr; + int regnum; + + if ((*this_cache) != NULL) + return (*this_cache); + cache = FRAME_OBSTACK_ZALLOC (struct m32r_frame_cache); + (*this_cache) = cache; + cache->saved_regs = trad_frame_alloc_saved_regs (next_frame); + + cache->base = frame_unwind_register_unsigned (next_frame, M32R_SP_REGNUM); + sigcontext_addr = cache->base + 4; + + cache->pc = frame_pc_unwind (next_frame); + addr = m32r_linux_sigtramp_start (cache->pc); + if (addr == 0) + { + /* If this is a RT signal trampoline, adjust SIGCONTEXT_ADDR + accordingly. */ + addr = m32r_linux_rt_sigtramp_start (cache->pc); + if (addr) + sigcontext_addr += 128; + else + addr = frame_func_unwind (next_frame); + } + cache->pc = addr; + + cache->saved_regs = trad_frame_alloc_saved_regs (next_frame); + + for (regnum = 0; regnum < sizeof (m32r_linux_sc_reg_offset) / 4; regnum++) + { + if (m32r_linux_sc_reg_offset[regnum] >= 0) + cache->saved_regs[regnum].addr = + sigcontext_addr + m32r_linux_sc_reg_offset[regnum]; + } + + return cache; +} + +static void +m32r_linux_sigtramp_frame_this_id (struct frame_info *next_frame, + void **this_cache, + struct frame_id *this_id) +{ + struct m32r_frame_cache *cache = + m32r_linux_sigtramp_frame_cache (next_frame, this_cache); + + (*this_id) = frame_id_build (cache->base, cache->pc); +} + +static void +m32r_linux_sigtramp_frame_prev_register (struct frame_info *next_frame, + void **this_cache, + int regnum, int *optimizedp, + enum lval_type *lvalp, + CORE_ADDR *addrp, + int *realnump, void *valuep) +{ + struct m32r_frame_cache *cache = + m32r_linux_sigtramp_frame_cache (next_frame, this_cache); + + trad_frame_get_prev_register (next_frame, cache->saved_regs, regnum, + optimizedp, lvalp, addrp, realnump, valuep); +} + +static const struct frame_unwind m32r_linux_sigtramp_frame_unwind = { + SIGTRAMP_FRAME, + m32r_linux_sigtramp_frame_this_id, + m32r_linux_sigtramp_frame_prev_register +}; + +static const struct frame_unwind * +m32r_linux_sigtramp_frame_sniffer (struct frame_info *next_frame) +{ + CORE_ADDR pc = frame_pc_unwind (next_frame); + char *name; + + find_pc_partial_function (pc, &name, NULL, NULL); + if (m32r_linux_pc_in_sigtramp (pc, name)) + return &m32r_linux_sigtramp_frame_unwind; + + return NULL; +} + +static struct link_map_offsets * +m32r_linux_svr4_fetch_link_map_offsets (void) +{ + static struct link_map_offsets lmo; + static struct link_map_offsets *lmp = NULL; + + if (lmp == NULL) + { + lmp = &lmo; + + /* Everything we need is in the first 8 bytes. */ + lmo.r_debug_size = 8; + lmo.r_map_offset = 4; + lmo.r_map_size = 4; + + /* Everything we need is in the first 20 bytes. */ + lmo.link_map_size = 20; + lmo.l_addr_offset = 0; + lmo.l_addr_size = 4; + lmo.l_name_offset = 4; + lmo.l_name_size = 4; + lmo.l_next_offset = 12; + lmo.l_next_size = 4; + lmo.l_prev_offset = 16; + lmo.l_prev_size = 4; + } + + return lmp; +} + +static void +m32r_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) +{ + struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); + + frame_unwind_append_sniffer (gdbarch, m32r_linux_sigtramp_frame_sniffer); + + set_solib_svr4_fetch_link_map_offsets + (gdbarch, m32r_linux_svr4_fetch_link_map_offsets); +} + +/* Provide a prototype to silence -Wmissing-prototypes. */ +extern void _initialize_m32r_linux_tdep (void); + +void +_initialize_m32r_linux_tdep (void) +{ + gdbarch_register_osabi (bfd_arch_m32r, 0, GDB_OSABI_LINUX, + m32r_linux_init_abi); +} Index: config/m32r/linux.mh =================================================================== RCS file: config/m32r/linux.mh diff -N config/m32r/linux.mh --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ config/m32r/linux.mh 20 Aug 2004 05:54:29 -0000 @@ -0,0 +1,8 @@ +# Host: M32R based machine running GNU/Linux + +NAT_FILE= nm-linux.h +NATDEPFILES= infptrace.o inftarg.o fork-child.o corelow.o \ + m32r-linux-nat.o linux-proc.o gcore.o \ + proc-service.o thread-db.o lin-lwp.o linux-nat.o + +LOADLIBES= -ldl -rdynamic Index: config/m32r/linux.mt =================================================================== RCS file: config/m32r/linux.mt diff -N config/m32r/linux.mt --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ config/m32r/linux.mt 20 Aug 2004 05:54:29 -0000 @@ -0,0 +1,6 @@ +# Target: Renesas M32R running GNU/Linux +TDEPFILES= m32r-tdep.o m32r-linux-tdep.o remote-m32r-sdi.o glibc-tdep.o solib.o solib-svr4.o solib-legacy.o +TM_FILE= tm-linux.h + +SIM_OBS = remote-sim.o +SIM = ../sim/m32r/libsim.a Index: config/m32r/m32r.mh =================================================================== RCS file: config/m32r/m32r.mh diff -N config/m32r/m32r.mh --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ config/m32r/m32r.mh 20 Aug 2004 05:54:29 -0000 @@ -0,0 +1,8 @@ +# Host: M32R running GNU/Linux + +NAT_FILE= nm-linux.h +NATDEPFILES= infptrace.o inftarg.o fork-child.o corelow.o \ + core-regset.o linux-proc.o gcore.o \ + proc-service.o thread-db.o lin-lwp.o + +LOADLIBES = -ldl -rdynamic Index: config/m32r/nm-linux.h =================================================================== RCS file: config/m32r/nm-linux.h diff -N config/m32r/nm-linux.h --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ config/m32r/nm-linux.h 20 Aug 2004 05:54:29 -0000 @@ -0,0 +1,29 @@ +/* Definitions to make GDB run on an M32R based machine under GNU/Linux. + Copyright 2004 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 2 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, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#ifndef NM_M32R_LINUX_H +#define NM_M32R_LINUX_H + +#include "config/nm-linux.h" + +/* Override copies of {fetch,store}_inferior_registers in infptrace.c. */ +#define FETCH_INFERIOR_REGISTERS + +#endif /* NM_M32R_LINUX_H */ Index: config/m32r/tm-linux.h =================================================================== RCS file: config/m32r/tm-linux.h diff -N config/m32r/tm-linux.h --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ config/m32r/tm-linux.h 20 Aug 2004 05:54:29 -0000 @@ -0,0 +1,29 @@ +/* Target-specific definitions for GNU/Linux running on a Renesas + M32R. + + Copyright 2004 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 2 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, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#ifndef TM_LINUX_H +#define TM_LINUX_H + +/* Pull in GNU/Linux generic defs. */ +#include "config/tm-linux.h" + +#endif /* #ifndef TM_LINUX_H */ ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: Fw: Unreviewed patch (m32r-linux support) 2004-09-15 8:01 Fw: Unreviewed patch (m32r-linux support) Kei Sakamoto @ 2004-09-15 11:25 ` Mark Kettenis 2004-09-16 4:32 ` Kei Sakamoto ` (2 more replies) 0 siblings, 3 replies; 11+ messages in thread From: Mark Kettenis @ 2004-09-15 11:25 UTC (permalink / raw) To: sakamoto.kei; +Cc: gdb-patches From: "Kei Sakamoto" <sakamoto.kei@renesas.com> Date: Wed, 15 Sep 2004 17:00:46 +0900 Mark, Would you review the attached patch? I'm afraid that you are still busy because of moving. But it seems you are the best person to review it because I revised it based on your advise. If you are too busy, please let me know. Ah yes, unfortunately I've been pretty busy up until now. Anyway, before I start giving you more ill-guided advise, can I ask you a few question first? Are there any plans to support the PTRACE_GETREGS/PTRACE_SETREGS requests? I really think a modern Linux port should support those (and only those), but Linux/M32R isn't going to support them, the code can be simplified even more. Are there any plans to support a FPU? Meanwhile I have a few more comments concerning m32r-linux-tdep.c. m32r_linux_sigtramp_start should use safe_frame_unwind_memory instead of read_memory_unsigned_integer, otherwise there might be unwanted interaction between signal handlers and breakpoints. Please take a look at the recent changes to i386-linux-tdep.c to get an idea how things should look. Instead of rolling your own m32r_linux_svr4_fetch_link_map_offsets, please use the generic svr4_ilp32_fetch_link_map_offsets. Also you'll have to s/TM_FILE/DEPRECATED_TM_FILE/g in your linux.mt file, because of some recent changes. Hopefully, this doesn't discourage you. On the bright side, these changes will make it easier to maintain the Linux/M32R port in the future. Cheers, Mark ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: Fw: Unreviewed patch (m32r-linux support) 2004-09-15 11:25 ` Mark Kettenis @ 2004-09-16 4:32 ` Kei Sakamoto 2004-09-16 13:59 ` Andrew Cagney 2004-09-28 10:04 ` [RFA/m32r] revised m32r-linux patch Kei Sakamoto 2 siblings, 0 replies; 11+ messages in thread From: Kei Sakamoto @ 2004-09-16 4:32 UTC (permalink / raw) To: Mark Kettenis; +Cc: gdb-patches Mark, Thank you for reviewing my patch. > Anyway, before I start giving you more ill-guided advise, Your advise is very well-guided. :-) > Are there any plans to support the PTRACE_GETREGS/PTRACE_SETREGS > requests? I really think a modern Linux port should support those > (and only those), but Linux/M32R isn't going to support them, the code > can be simplified even more. It sounds reasonable. I'll implement PTRACE_GETREGS/PTRACE_SETREGS on Linux/M32R kernel and simplify the register handling codes. > Are there any plans to support a FPU? Some chips of M32R have FPU. But their target is ECU (Engine Control Unit) and does not support Linux because ECU doesn't need a large OS like Linux. So FPU support is not necessary for Linux/M32R. > Meanwhile I have a few more comments concerning m32r-linux-tdep.c. OK. I'll revise my patch. === Kei Sakamoto Renesas Technology Corp. sakamoto.kei@renesas.com ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: Fw: Unreviewed patch (m32r-linux support) 2004-09-15 11:25 ` Mark Kettenis 2004-09-16 4:32 ` Kei Sakamoto @ 2004-09-16 13:59 ` Andrew Cagney 2004-09-28 10:04 ` [RFA/m32r] revised m32r-linux patch Kei Sakamoto 2 siblings, 0 replies; 11+ messages in thread From: Andrew Cagney @ 2004-09-16 13:59 UTC (permalink / raw) To: Mark Kettenis; +Cc: sakamoto.kei, gdb-patches > Also you'll have to s/TM_FILE/DEPRECATED_TM_FILE/g in your linux.mt > file, because of some recent changes. This is acceptable as the patch was submitted before the deprecation was formalized. Andrew ^ permalink raw reply [flat|nested] 11+ messages in thread
* [RFA/m32r] revised m32r-linux patch 2004-09-15 11:25 ` Mark Kettenis 2004-09-16 4:32 ` Kei Sakamoto 2004-09-16 13:59 ` Andrew Cagney @ 2004-09-28 10:04 ` Kei Sakamoto 2004-09-28 12:31 ` Mark Kettenis 2004-09-28 19:53 ` [RFA/m32r] " Eli Zaretskii 2 siblings, 2 replies; 11+ messages in thread From: Kei Sakamoto @ 2004-09-28 10:04 UTC (permalink / raw) To: Mark Kettenis; +Cc: gdb-patches [-- Attachment #1: Type: text/plain, Size: 790 bytes --] Hello, I revised the patch of m32r-linux support as you adviced. Linux/M32R kernel now supports PTRACE_GETREGS/SETREGS. So m32r-linux uses only PTRACE_GETREGS/SETREGS. I also replaced read_memory_unsigned_integer with safe_frame_unwind_memory . OK to commit? 2004-09-28 Kei Sakamoto <sakamoto.kei@renesas.com> Add m32r-linux support. * configure.tgt: Add m32r*-*-linux*. * Makefile.in (ALLDEPFILES): Add m32r-tdep.c, m32r-linux-nat.c and m32r-linux-tdep.c. (m32r-linux-nat.o, m32r-linux-tdep.o): New dependencies. * m32r-tdep.c: Move some definitions to m32r-tdep.h. * m32r-tdep.h, m32r-linux-nat.c, m32r-linux-tdep.c, config/m32r/linux.mh, config/m32r/linux.mt, config/m32r/m32r.mh, config/m32r/nm-linux.h, config/m32r/tm-linux.h: New files. [-- Attachment #2: m32r-linux.patch --] [-- Type: application/octet-stream, Size: 28501 bytes --] Index: Makefile.in =================================================================== RCS file: /cvs/src/src/gdb/Makefile.in,v retrieving revision 1.629 diff -a -u -r1.629 Makefile.in --- Makefile.in 27 Sep 2004 19:55:16 -0000 1.629 +++ Makefile.in 28 Sep 2004 09:47:40 -0000 @@ -719,6 +719,7 @@ linespec_h = linespec.h linux_nat_h = linux-nat.h $(target_h) m2_lang_h = m2-lang.h +m32r_tdep_h = m32r-tdep.h m68k_tdep_h = m68k-tdep.h m88k_tdep_h = m88k-tdep.h macroexp_h = macroexp.h @@ -1381,6 +1382,8 @@ libunwind-frame.c \ lynx-nat.c m3-nat.c \ m68hc11-tdep.c \ + m32r-tdep.c \ + m32r-linux-nat.c m32r-linux-tdep.c \ m68k-tdep.c \ m68kbsd-nat.c m68kbsd-tdep.c \ m88k-tdep.c m88kbsd-nat.c \ @@ -2137,15 +2140,21 @@ $(expression_h) $(value_h) $(gdbcore_h) $(target_h) $(m2_lang_h) m2-valprint.o: m2-valprint.c $(defs_h) $(symtab_h) $(gdbtypes_h) \ $(m2_lang_h) +m32r-linux-nat.o: m32r-linux-nat.c $(defs_h) $(inferior_h) $(gdbcore_h) \ + $(regcache_h) $(linux_nat_h) $(gdb_assert_h) $(gdb_string_h) \ + $(m32r_tdep_h) +m32r-linux-tdep.o: m32r-linux-tdep.c $(defs_h) $(gdbcore_h) $(frame_h) \ + $(value_h) $(regcache_h) $(inferior_h) $(osabi_h) $(reggroups_h) \ + $(gdb_string_h) $(glibc_tdep_h) $(solib_svr4_h) $(m32r_tdep_h) m32r-rom.o: m32r-rom.c $(defs_h) $(gdbcore_h) $(target_h) $(monitor_h) \ - $(serial_h) $(symtab_h) $(command_h) $(gdbcmd_h) $(symfile_h) \ - $(gdb_string_h) $(objfiles_h) $(inferior_h) $(regcache_h) + $(serial_h) $(symtab_h) $(command_h) $(gdbcmd_h) $(symfile_h) \ + $(gdb_string_h) $(objfiles_h) $(inferior_h) $(regcache_h) m32r-stub.o: m32r-stub.c $(syscall_h) -m32r-tdep.o: m32r-tdep.c $(defs_h) $(frame_h) $(frame_unwind_h) \ + m32r-tdep.o: m32r-tdep.c $(defs_h) $(frame_h) $(frame_unwind_h) \ $(frame_base_h) $(symtab_h) $(gdbtypes_h) $(gdbcmd_h) $(gdbcore_h) \ $(gdb_string_h) $(value_h) $(inferior_h) $(symfile_h) $(objfiles_h) \ $(language_h) $(arch_utils_h) $(regcache_h) $(trad_frame_h) \ - $(dis_asm_h) $(gdb_assert_h) + $(dis_asm_h) $(gdb_assert_h) $(m32r_tdep_h) m68hc11-tdep.o: m68hc11-tdep.c $(defs_h) $(frame_h) $(frame_unwind_h) \ $(frame_base_h) $(dwarf2_frame_h) $(trad_frame_h) $(symtab_h) \ $(gdbtypes_h) $(gdbcmd_h) $(gdbcore_h) $(gdb_string_h) $(value_h) \ Index: configure.tgt =================================================================== RCS file: /cvs/src/src/gdb/configure.tgt,v retrieving revision 1.146 diff -a -u -r1.146 configure.tgt --- configure.tgt 12 Aug 2004 22:29:56 -0000 1.146 +++ configure.tgt 28 Sep 2004 09:47:40 -0000 @@ -106,7 +106,8 @@ ;; ia64*-*-*) gdb_target=ia64 ;; -m32r-*-*) gdb_target=m32r ;; +m32r*-*-linux*) gdb_target=linux ;; +m32r*-*-*) gdb_target=m32r ;; m68hc11*-*-*|m6811*-*-*) gdb_target=m68hc11 ;; Index: m32r-linux-nat.c =================================================================== RCS file: m32r-linux-nat.c diff -N m32r-linux-nat.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ m32r-linux-nat.c 28 Sep 2004 09:47:40 -0000 @@ -0,0 +1,234 @@ +/* Native-dependent code for GNU/Linux m32r. + + Copyright 2004 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 2 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, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include "defs.h" +#include "inferior.h" +#include "gdbcore.h" +#include "regcache.h" +#include "linux-nat.h" + +#include "gdb_assert.h" +#include "gdb_string.h" +#include <sys/ptrace.h> +#include <sys/user.h> +#include <sys/procfs.h> + +/* Prototypes for supply_gregset etc. */ +#include "gregset.h" + +#include "m32r-tdep.h" + +\f + + +/* Since EVB register is not available for native debug, we reduce + the number of registers. */ +#define M32R_LINUX_NUM_REGS (M32R_NUM_REGS - 1) + +/* Mapping between the general-purpose registers in `struct user' + format and GDB's register array layout. */ +static int regmap[] = { + 4, 5, 6, 7, 0, 1, 2, 8, + 9, 10, 11, 12, 13, 24, 25, 23, + 19, 19, 26, 23, 22, 20, 16, 15 +}; + +#define PSW_REGMAP 19 +#define BBPSW_REGMAP 21 +#define SPU_REGMAP 23 +#define SPI_REGMAP 26 + +/* Doee apply to the corresponding SET requests as well. */ +#define GETREGS_SUPPLIES(regno) (0 <= (regno) && (regno) <= M32R_LINUX_NUM_REGS) + +\f + +/* Transfering the general-purpose registers between GDB, inferiors + and core files. */ + +/* Fill GDB's register array with the general-purpose register values + in *GREGSETP. */ + +void +supply_gregset (elf_gregset_t * gregsetp) +{ + elf_greg_t *regp = (elf_greg_t *) gregsetp; + int i; + unsigned long psw, bbpsw; + + psw = *(regp + PSW_REGMAP); + bbpsw = *(regp + BBPSW_REGMAP); + + for (i = 0; i < M32R_LINUX_NUM_REGS; i++) + { + switch (i) + { + case PSW_REGNUM: + *(regp + regmap[i]) = ((0x00c1 & bbpsw) << 8) | ((0xc100 & psw) >> 8); + break; + case CBR_REGNUM: + *(regp + regmap[i]) = ((psw >> 8) & 1); + break; + } + + if (i != M32R_SP_REGNUM) + regcache_raw_supply (current_regcache, i, regp + regmap[i]); + else if (psw & 0x8000) + regcache_raw_supply (current_regcache, i, regp + SPU_REGMAP); + else + regcache_raw_supply (current_regcache, i, regp + SPI_REGMAP); + } +} + +/* Fetch all general-purpose registers from process/thread TID and + store their values in GDB's register array. */ + +static void +fetch_regs (int tid) +{ + elf_gregset_t regs; + + if (ptrace (PTRACE_GETREGS, tid, 0, (int) ®s) < 0) + perror_with_name ("Couldn't get registers"); + + supply_gregset (®s); +} + +/* Fill register REGNO (if it is a general-purpose register) in + *GREGSETPS with the value in GDB's register array. If REGNO is -1, + do this for all registers. */ + +void +fill_gregset (elf_gregset_t * gregsetp, int regno) +{ + elf_greg_t *regp = (elf_greg_t *) gregsetp; + int i; + unsigned long psw, bbpsw, tmp; + + psw = *(regp + PSW_REGMAP); + bbpsw = *(regp + BBPSW_REGMAP); + + for (i = 0; i < M32R_LINUX_NUM_REGS; i++) + { + if (regno != -1 && regno != i) + continue; + + if (i == CBR_REGNUM || i == PSW_REGNUM) + continue; + + if (i == SPU_REGNUM || i == SPI_REGNUM) + continue; + + if (i != M32R_SP_REGNUM) + regcache_raw_collect (current_regcache, i, regp + regmap[i]); + else if (psw & 0x8000) + regcache_raw_collect (current_regcache, i, regp + SPU_REGMAP); + else + regcache_raw_collect (current_regcache, i, regp + SPI_REGMAP); + } +} + +/* Store all valid general-purpose registers in GDB's register array + into the process/thread specified by TID. */ + +static void +store_regs (int tid, int regno) +{ + elf_gregset_t regs; + + if (ptrace (PTRACE_GETREGS, tid, 0, (int) ®s) < 0) + perror_with_name ("Couldn't get registers"); + + fill_gregset (®s, regno); + + if (ptrace (PTRACE_SETREGS, tid, 0, (int) ®s) < 0) + perror_with_name ("Couldn't write registers"); +} + +\f + +/* Transfering floating-point registers between GDB, inferiors and cores. + Since M32R has no floating-point registers, these functions do nothing. */ + +void +supply_fpregset (gdb_fpregset_t *fpregs) +{ +} + +void +fill_fpregset (gdb_fpregset_t *fpregs, int regno) +{ +} + +\f + +/* Transferring arbitrary registers between GDB and inferior. */ + +/* Fetch register REGNO from the child process. If REGNO is -1, do + this for all registers (including the floating point and SSE + registers). */ + +void +fetch_inferior_registers (int regno) +{ + int tid; + + /* GNU/Linux LWP ID's are process ID's. */ + tid = TIDGET (inferior_ptid); + if (tid == 0) + tid = PIDGET (inferior_ptid); /* Not a threaded program. */ + + /* Use the PTRACE_GETREGS request whenever possible, since it + transfers more registers in one system call, and we'll cache the + results. */ + if (regno == -1 || GETREGS_SUPPLIES (regno)) + { + fetch_regs (tid); + return; + } + + internal_error (__FILE__, __LINE__, + "Got request for bad register number %d.", regno); +} + +/* Store register REGNO back into the child process. If REGNO is -1, + do this for all registers (including the floating point and SSE + registers). */ +void +store_inferior_registers (int regno) +{ + int tid; + + /* GNU/Linux LWP ID's are process ID's. */ + if ((tid = TIDGET (inferior_ptid)) == 0) + tid = PIDGET (inferior_ptid); /* Not a threaded program. */ + + /* Use the PTRACE_SETREGS request whenever possible, since it + transfers more registers in one system call. */ + if (regno == -1 || GETREGS_SUPPLIES (regno)) + { + store_regs (tid, regno); + return; + } + + internal_error (__FILE__, __LINE__, + "Got request to store bad register number %d.", regno); +} Index: m32r-linux-tdep.c =================================================================== RCS file: m32r-linux-tdep.c diff -N m32r-linux-tdep.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ m32r-linux-tdep.c 28 Sep 2004 09:47:40 -0000 @@ -0,0 +1,337 @@ +/* Target-dependent code for GNU/Linux m32r. + + Copyright 2004 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 2 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, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include "defs.h" +#include "gdbcore.h" +#include "frame.h" +#include "value.h" +#include "regcache.h" +#include "inferior.h" +#include "osabi.h" +#include "reggroups.h" + +#include "gdb_string.h" + +#include "glibc-tdep.h" +#include "solib-svr4.h" + +#include "trad-frame.h" +#include "frame-unwind.h" + +#include "m32r-tdep.h" +\f + +/* Recognizing signal handler frames. */ + +/* GNU/Linux has two flavors of signals. Normal signal handlers, and + "realtime" (RT) signals. The RT signals can provide additional + information to the signal handler if the SA_SIGINFO flag is set + when establishing a signal handler using `sigaction'. It is not + unlikely that future versions of GNU/Linux will support SA_SIGINFO + for normal signals too. */ + +/* When the m32r Linux kernel calls a signal handler and the + SA_RESTORER flag isn't set, the return address points to a bit of + code on the stack. This function returns whether the PC appears to + be within this bit of code. + + The instruction sequence for normal signals is + ldi r7, #__NR_sigreturn + trap #2 + or 0x67 0x77 0x10 0xf2. + + Checking for the code sequence should be somewhat reliable, because + the effect is to call the system call sigreturn. This is unlikely + to occur anywhere other than in a signal trampoline. + + It kind of sucks that we have to read memory from the process in + order to identify a signal trampoline, but there doesn't seem to be + any other way. Therefore we only do the memory reads if no + function name could be identified, which should be the case since + the code is on the stack. + + Detection of signal trampolines for handlers that set the + SA_RESTORER flag is in general not possible. Unfortunately this is + what the GNU C Library has been doing for quite some time now. + However, as of version 2.1.2, the GNU C Library uses signal + trampolines (named __restore and __restore_rt) that are identical + to the ones used by the kernel. Therefore, these trampolines are + supported too. */ + +static const unsigned char linux_sigtramp_code[] = +{ + 0x67, 0x77, 0x10, 0xf2, +}; + +/* If PC is in a sigtramp routine, return the address of the start of + the routine. Otherwise, return 0. */ + +static CORE_ADDR +m32r_linux_sigtramp_start (CORE_ADDR pc, struct frame_info *next_frame) +{ + unsigned char buf[4]; + + /* We only recognize a signal trampoline if PC is at the start of + one of the instructions. We optimize for finding the PC at the + start of the instruction sequence, as will be the case when the + trampoline is not the first frame on the stack. We assume that + in the case where the PC is not at the start of the instruction + sequence, there will be a few trailing readable bytes on the + stack. */ + + if (pc % 2 != 0) + { + if (!safe_frame_unwind_memory (next_frame, pc, buf, 2)) + return 0; + + if (memcmp (buf, linux_sigtramp_code, 2) == 0) + pc -= 2; + else + return 0; + } + + if (!safe_frame_unwind_memory (next_frame, pc, buf, 4)) + return 0; + + if (memcmp (buf, linux_sigtramp_code, 4) != 0) + return 0; + + return pc; +} + +/* This function does the same for RT signals. Here the instruction + sequence is + ldi r7, #__NR_rt_sigreturn + trap #2 + or 0x97 0xf0 0x00 0xad 0x10 0xf2 0xf0 0x00. + + The effect is to call the system call rt_sigreturn. */ + +static const unsigned char linux_rt_sigtramp_code[] = +{ + 0x97, 0xf0, 0x00, 0xad, 0x10, 0xf2, 0xf0, 0x00, +}; + +/* If PC is in a RT sigtramp routine, return the address of the start + of the routine. Otherwise, return 0. */ + +static CORE_ADDR +m32r_linux_rt_sigtramp_start (CORE_ADDR pc, struct frame_info *next_frame) +{ + unsigned char buf[4]; + + /* We only recognize a signal trampoline if PC is at the start of + one of the instructions. We optimize for finding the PC at the + start of the instruction sequence, as will be the case when the + trampoline is not the first frame on the stack. We assume that + in the case where the PC is not at the start of the instruction + sequence, there will be a few trailing readable bytes on the + stack. */ + + if (pc % 2 != 0) + return 0; + + if (!safe_frame_unwind_memory (next_frame, pc, buf, 4)) + return 0; + + if (memcmp (buf, linux_rt_sigtramp_code, 4) == 0) + { + if (!safe_frame_unwind_memory (next_frame, pc + 4, buf, 4)) + return 0; + + if (memcmp (buf, linux_rt_sigtramp_code + 4, 4) == 0) + return pc; + } + else if (memcmp (buf, linux_rt_sigtramp_code + 4, 4) == 0) + { + if (!safe_frame_unwind_memory (next_frame, pc - 4, buf, 4)) + return 0; + + if (memcmp (buf, linux_rt_sigtramp_code, 4) == 0) + return pc - 4; + } + + return 0; +} + +static int +m32r_linux_pc_in_sigtramp (CORE_ADDR pc, char *name, struct frame_info *next_frame) +{ + /* If we have NAME, we can optimize the search. The trampolines are + named __restore and __restore_rt. However, they aren't dynamically + exported from the shared C library, so the trampoline may appear to + be part of the preceding function. This should always be sigaction, + __sigaction, or __libc_sigaction (all aliases to the same function). */ + if (name == NULL || strstr (name, "sigaction") != NULL) + return (m32r_linux_sigtramp_start (pc, next_frame) != 0 + || m32r_linux_rt_sigtramp_start (pc, next_frame) != 0); + + return (strcmp ("__restore", name) == 0 + || strcmp ("__restore_rt", name) == 0); +} + +/* From <asm/sigcontext.h>. */ +static int m32r_linux_sc_reg_offset[] = { + 4 * 4, /* r0 */ + 5 * 4, /* r1 */ + 6 * 4, /* r2 */ + 7 * 4, /* r3 */ + 0 * 4, /* r4 */ + 1 * 4, /* r5 */ + 2 * 4, /* r6 */ + 8 * 4, /* r7 */ + 9 * 4, /* r8 */ + 10 * 4, /* r9 */ + 11 * 4, /* r10 */ + 12 * 4, /* r11 */ + 13 * 4, /* r12 */ + 21 * 4, /* fp */ + 22 * 4, /* lr */ + -1 * 4, /* sp */ + 16 * 4, /* psw */ + -1 * 4, /* cbr */ + 23 * 4, /* spi */ + 20 * 4, /* spu */ + 19 * 4, /* bpc */ + 17 * 4, /* pc */ + 15 * 4, /* accl */ + 14 * 4 /* acch */ +}; + +struct m32r_frame_cache +{ + CORE_ADDR base, pc; + struct trad_frame_saved_reg *saved_regs; +}; + +static struct m32r_frame_cache * +m32r_linux_sigtramp_frame_cache (struct frame_info *next_frame, + void **this_cache) +{ + struct m32r_frame_cache *cache; + CORE_ADDR sigcontext_addr, addr; + int regnum; + + if ((*this_cache) != NULL) + return (*this_cache); + cache = FRAME_OBSTACK_ZALLOC (struct m32r_frame_cache); + (*this_cache) = cache; + cache->saved_regs = trad_frame_alloc_saved_regs (next_frame); + + cache->base = frame_unwind_register_unsigned (next_frame, M32R_SP_REGNUM); + sigcontext_addr = cache->base + 4; + + cache->pc = frame_pc_unwind (next_frame); + addr = m32r_linux_sigtramp_start (cache->pc, next_frame); + if (addr == 0) + { + /* If this is a RT signal trampoline, adjust SIGCONTEXT_ADDR + accordingly. */ + addr = m32r_linux_rt_sigtramp_start (cache->pc, next_frame); + if (addr) + sigcontext_addr += 128; + else + addr = frame_func_unwind (next_frame); + } + cache->pc = addr; + + cache->saved_regs = trad_frame_alloc_saved_regs (next_frame); + + for (regnum = 0; regnum < sizeof (m32r_linux_sc_reg_offset) / 4; regnum++) + { + if (m32r_linux_sc_reg_offset[regnum] >= 0) + cache->saved_regs[regnum].addr = + sigcontext_addr + m32r_linux_sc_reg_offset[regnum]; + } + + return cache; +} + +static void +m32r_linux_sigtramp_frame_this_id (struct frame_info *next_frame, + void **this_cache, + struct frame_id *this_id) +{ + struct m32r_frame_cache *cache = + m32r_linux_sigtramp_frame_cache (next_frame, this_cache); + + (*this_id) = frame_id_build (cache->base, cache->pc); +} + +static void +m32r_linux_sigtramp_frame_prev_register (struct frame_info *next_frame, + void **this_cache, + int regnum, int *optimizedp, + enum lval_type *lvalp, + CORE_ADDR *addrp, + int *realnump, void *valuep) +{ + struct m32r_frame_cache *cache = + m32r_linux_sigtramp_frame_cache (next_frame, this_cache); + + trad_frame_get_prev_register (next_frame, cache->saved_regs, regnum, + optimizedp, lvalp, addrp, realnump, valuep); +} + +static const struct frame_unwind m32r_linux_sigtramp_frame_unwind = { + SIGTRAMP_FRAME, + m32r_linux_sigtramp_frame_this_id, + m32r_linux_sigtramp_frame_prev_register +}; + +static const struct frame_unwind * +m32r_linux_sigtramp_frame_sniffer (struct frame_info *next_frame) +{ + CORE_ADDR pc = frame_pc_unwind (next_frame); + char *name; + + find_pc_partial_function (pc, &name, NULL, NULL); + if (m32r_linux_pc_in_sigtramp (pc, name, next_frame)) + return &m32r_linux_sigtramp_frame_unwind; + + return NULL; +} + +static void +m32r_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) +{ + struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); + + /* Since EVB register is not available for native debug, we reduce + the number of registers. */ + set_gdbarch_num_regs (gdbarch, M32R_NUM_REGS - 1); + + frame_unwind_append_sniffer (gdbarch, m32r_linux_sigtramp_frame_sniffer); + + /* GNU/Linux uses SVR4-style shared libraries. */ + set_solib_svr4_fetch_link_map_offsets + (gdbarch, svr4_ilp32_fetch_link_map_offsets); +} + +/* Provide a prototype to silence -Wmissing-prototypes. */ +extern void _initialize_m32r_linux_tdep (void); + +void +_initialize_m32r_linux_tdep (void) +{ + gdbarch_register_osabi (bfd_arch_m32r, 0, GDB_OSABI_LINUX, + m32r_linux_init_abi); +} Index: m32r-tdep.c =================================================================== RCS file: /cvs/src/src/gdb/m32r-tdep.c,v retrieving revision 1.30 diff -a -u -r1.30 m32r-tdep.c --- m32r-tdep.c 2 Aug 2004 19:44:40 -0000 1.30 +++ m32r-tdep.c 28 Sep 2004 09:47:41 -0000 @@ -41,27 +41,7 @@ #include "gdb_assert.h" -struct gdbarch_tdep -{ - /* gdbarch target dependent data here. Currently unused for M32R. */ -}; - -/* m32r register names. */ - -enum -{ - R0_REGNUM = 0, - R3_REGNUM = 3, - M32R_FP_REGNUM = 13, - LR_REGNUM = 14, - M32R_SP_REGNUM = 15, - PSW_REGNUM = 16, - M32R_PC_REGNUM = 21, - /* m32r calling convention. */ - ARG1_REGNUM = R0_REGNUM, - ARGN_REGNUM = R3_REGNUM, - RET1_REGNUM = R0_REGNUM, -}; +#include "m32r-tdep.h" /* Local functions */ @@ -238,18 +218,12 @@ "evb" }; -static int -m32r_num_regs (void) -{ - return (sizeof (m32r_register_names) / sizeof (m32r_register_names[0])); -} - static const char * m32r_register_name (int reg_nr) { if (reg_nr < 0) return NULL; - if (reg_nr >= m32r_num_regs ()) + if (reg_nr >= M32R_NUM_REGS) return NULL; return m32r_register_names[reg_nr]; } @@ -921,7 +895,7 @@ set_gdbarch_write_pc (gdbarch, m32r_write_pc); set_gdbarch_unwind_sp (gdbarch, m32r_unwind_sp); - set_gdbarch_num_regs (gdbarch, m32r_num_regs ()); + set_gdbarch_num_regs (gdbarch, M32R_NUM_REGS); set_gdbarch_sp_regnum (gdbarch, M32R_SP_REGNUM); set_gdbarch_register_name (gdbarch, m32r_register_name); set_gdbarch_register_type (gdbarch, m32r_register_type); Index: m32r-tdep.h =================================================================== RCS file: m32r-tdep.h diff -N m32r-tdep.h --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ m32r-tdep.h 28 Sep 2004 09:47:41 -0000 @@ -0,0 +1,52 @@ +/* Target-dependent code for Renesas M32R, for GDB. + + Copyright 2004 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 2 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, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#ifndef M32R_TDEP_H +#define M32R_TDEP_H + +struct gdbarch_tdep +{ + /* gdbarch target dependent data here. Currently unused for M32R. */ +}; + +/* m32r register names. */ + +enum m32r_regnum +{ + R0_REGNUM = 0, + R3_REGNUM = 3, + M32R_FP_REGNUM = 13, + LR_REGNUM = 14, + M32R_SP_REGNUM = 15, + PSW_REGNUM = 16, + CBR_REGNUM = 17, + SPU_REGNUM = 18, + SPI_REGNUM = 19, + M32R_PC_REGNUM = 21, + /* m32r calling convention. */ + ARG1_REGNUM = R0_REGNUM, + ARGN_REGNUM = R3_REGNUM, + RET1_REGNUM = R0_REGNUM, +}; + +#define M32R_NUM_REGS 25 + +#endif /* m32r-tdep.h */ Index: config/m32r/linux.mh =================================================================== RCS file: config/m32r/linux.mh diff -N config/m32r/linux.mh --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ config/m32r/linux.mh 28 Sep 2004 09:47:41 -0000 @@ -0,0 +1,8 @@ +# Host: M32R based machine running GNU/Linux + +NAT_FILE= nm-linux.h +NATDEPFILES= infptrace.o inftarg.o fork-child.o corelow.o \ + m32r-linux-nat.o linux-proc.o gcore.o \ + proc-service.o thread-db.o linux-nat.o + +LOADLIBES= -ldl -rdynamic Index: config/m32r/linux.mt =================================================================== RCS file: config/m32r/linux.mt diff -N config/m32r/linux.mt --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ config/m32r/linux.mt 28 Sep 2004 09:47:41 -0000 @@ -0,0 +1,6 @@ +# Target: Renesas M32R running GNU/Linux +TDEPFILES= m32r-tdep.o m32r-linux-tdep.o remote-m32r-sdi.o glibc-tdep.o solib.o solib-svr4.o solib-legacy.o +TM_FILE= tm-linux.h + +SIM_OBS = remote-sim.o +SIM = ../sim/m32r/libsim.a Index: config/m32r/m32r.mh =================================================================== RCS file: config/m32r/m32r.mh diff -N config/m32r/m32r.mh --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ config/m32r/m32r.mh 28 Sep 2004 09:47:41 -0000 @@ -0,0 +1,8 @@ +# Host: M32R running GNU/Linux + +NAT_FILE= nm-linux.h +NATDEPFILES= infptrace.o inftarg.o fork-child.o corelow.o \ + core-regset.o linux-proc.o gcore.o \ + proc-service.o thread-db.o lin-lwp.o + +LOADLIBES = -ldl -rdynamic Index: config/m32r/nm-linux.h =================================================================== RCS file: config/m32r/nm-linux.h diff -N config/m32r/nm-linux.h --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ config/m32r/nm-linux.h 28 Sep 2004 09:47:41 -0000 @@ -0,0 +1,29 @@ +/* Definitions to make GDB run on an M32R based machine under GNU/Linux. + Copyright 2004 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 2 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, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#ifndef NM_M32R_LINUX_H +#define NM_M32R_LINUX_H + +#include "config/nm-linux.h" + +/* Override copies of {fetch,store}_inferior_registers in infptrace.c. */ +#define FETCH_INFERIOR_REGISTERS + +#endif /* NM_M32R_LINUX_H */ Index: config/m32r/tm-linux.h =================================================================== RCS file: config/m32r/tm-linux.h diff -N config/m32r/tm-linux.h --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ config/m32r/tm-linux.h 28 Sep 2004 09:47:41 -0000 @@ -0,0 +1,29 @@ +/* Target-specific definitions for GNU/Linux running on a Renesas + M32R. + + Copyright 2004 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 2 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, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#ifndef TM_LINUX_H +#define TM_LINUX_H + +/* Pull in GNU/Linux generic defs. */ +#include "config/tm-linux.h" + +#endif /* #ifndef TM_LINUX_H */ ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [RFA/m32r] revised m32r-linux patch 2004-09-28 10:04 ` [RFA/m32r] revised m32r-linux patch Kei Sakamoto @ 2004-09-28 12:31 ` Mark Kettenis 2004-09-30 9:35 ` Kei Sakamoto 2004-09-28 19:53 ` [RFA/m32r] " Eli Zaretskii 1 sibling, 1 reply; 11+ messages in thread From: Mark Kettenis @ 2004-09-28 12:31 UTC (permalink / raw) To: sakamoto.kei; +Cc: gdb-patches From: "Kei Sakamoto" <sakamoto.kei@renesas.com> Date: Tue, 28 Sep 2004 19:04:14 +0900 Hello, I revised the patch of m32r-linux support as you adviced. Linux/M32R kernel now supports PTRACE_GETREGS/SETREGS. So m32r-linux uses only PTRACE_GETREGS/SETREGS. I also replaced read_memory_unsigned_integer with safe_frame_unwind_memory . Great. OK to commit? Is this a patch against the current CVS sources? I'm asking since your linux.mt file sets TM_FILE, but that should be DEPRECATED_TM_FILE. Also please set it to config/tm-linux.h, and remove config/m32r/tm-linux.h. Oh and remove your m32r.mh file too. It's a duplicate of linux.mh and unused. Don't forget to adjust the ChangeLog entry. Sorry, but I'll have to ask you to resumbit the patch again. But we're really close now. Mark ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [RFA/m32r] revised m32r-linux patch 2004-09-28 12:31 ` Mark Kettenis @ 2004-09-30 9:35 ` Kei Sakamoto 2004-10-01 0:20 ` Kei Sakamoto 0 siblings, 1 reply; 11+ messages in thread From: Kei Sakamoto @ 2004-09-30 9:35 UTC (permalink / raw) To: gdb-patches Mark and Eli, Thank you for your comments. I fixed my patch. A list of changes are below. - Replace TM_FILE with DEPRECATED_TM_FILE - Use config/tm-linux.h instead of confif/m32r/tm-linux.h - Remove config/m32r/tm-linux.h and config/m32r/m32r.mh - Add m32r-linux-nat.c and m32r-linux-tdep.c to config/djgpp/fnchange.lst - Stop using linux-proc.c OK to commit now? 2004-09-30 Kei Sakamoto <sakamoto.kei@renesas.com> Add m32r-linux support. * configure.tgt: Add m32r*-*-linux*. * Makefile.in (ALLDEPFILES): Add m32r-tdep.c, m32r-linux-nat.c and m32r-linux-tdep.c. (m32r-linux-nat.o, m32r-linux-tdep.o): New dependencies. * m32r-tdep.c: Move some definitions to m32r-tdep.h. * config/djgpp/fnchange.lst: Add m32r-linux-nat.c and m32r-linux-tdep.c. * m32r-tdep.h, m32r-linux-nat.c, m32r-linux-tdep.c, config/m32r/linux.mh, config/m32r/linux.mt, config/m32r/nm-linux.h: New files. ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [RFA/m32r] revised m32r-linux patch 2004-09-30 9:35 ` Kei Sakamoto @ 2004-10-01 0:20 ` Kei Sakamoto 2004-10-01 7:18 ` Mark Kettenis 0 siblings, 1 reply; 11+ messages in thread From: Kei Sakamoto @ 2004-10-01 0:20 UTC (permalink / raw) To: gdb-patches [-- Attachment #1: Type: text/plain, Size: 1039 bytes --] I'm sorry. I forgot to attach the patch file... > Mark and Eli, > > Thank you for your comments. > > I fixed my patch. A list of changes are below. > > - Replace TM_FILE with DEPRECATED_TM_FILE > - Use config/tm-linux.h instead of confif/m32r/tm-linux.h > - Remove config/m32r/tm-linux.h and config/m32r/m32r.mh > - Add m32r-linux-nat.c and m32r-linux-tdep.c to config/djgpp/fnchange.lst > - Stop using linux-proc.c > > OK to commit now? > > > 2004-09-30 Kei Sakamoto <sakamoto.kei@renesas.com> > > Add m32r-linux support. > * configure.tgt: Add m32r*-*-linux*. > * Makefile.in (ALLDEPFILES): Add m32r-tdep.c, m32r-linux-nat.c > and m32r-linux-tdep.c. > (m32r-linux-nat.o, m32r-linux-tdep.o): New dependencies. > * m32r-tdep.c: Move some definitions to m32r-tdep.h. > * config/djgpp/fnchange.lst: Add m32r-linux-nat.c and > m32r-linux-tdep.c. > * m32r-tdep.h, m32r-linux-nat.c, m32r-linux-tdep.c, > config/m32r/linux.mh, config/m32r/linux.mt, > config/m32r/nm-linux.h: New files. > [-- Attachment #2: m32r-linux.patch --] [-- Type: application/octet-stream, Size: 27316 bytes --] Index: Makefile.in =================================================================== RCS file: /cvs/src/src/gdb/Makefile.in,v retrieving revision 1.631 diff -u -a -r1.631 Makefile.in --- Makefile.in 28 Sep 2004 19:00:52 -0000 1.631 +++ Makefile.in 30 Sep 2004 09:14:12 -0000 @@ -720,6 +720,7 @@ linespec_h = linespec.h linux_nat_h = linux-nat.h $(target_h) m2_lang_h = m2-lang.h +m32r_tdep_h = m32r-tdep.h m68k_tdep_h = m68k-tdep.h m88k_tdep_h = m88k-tdep.h macroexp_h = macroexp.h @@ -1382,6 +1383,8 @@ libunwind-frame.c \ lynx-nat.c m3-nat.c \ m68hc11-tdep.c \ + m32r-tdep.c \ + m32r-linux-nat.c m32r-linux-tdep.c \ m68k-tdep.c \ m68kbsd-nat.c m68kbsd-tdep.c \ m88k-tdep.c m88kbsd-nat.c \ @@ -2131,15 +2134,21 @@ $(expression_h) $(value_h) $(gdbcore_h) $(target_h) $(m2_lang_h) m2-valprint.o: m2-valprint.c $(defs_h) $(symtab_h) $(gdbtypes_h) \ $(m2_lang_h) +m32r-linux-nat.o: m32r-linux-nat.c $(defs_h) $(inferior_h) $(gdbcore_h) \ + $(regcache_h) $(linux_nat_h) $(gdb_assert_h) $(gdb_string_h) \ + $(m32r_tdep_h) +m32r-linux-tdep.o: m32r-linux-tdep.c $(defs_h) $(gdbcore_h) $(frame_h) \ + $(value_h) $(regcache_h) $(inferior_h) $(osabi_h) $(reggroups_h) \ + $(gdb_string_h) $(glibc_tdep_h) $(solib_svr4_h) $(m32r_tdep_h) m32r-rom.o: m32r-rom.c $(defs_h) $(gdbcore_h) $(target_h) $(monitor_h) \ - $(serial_h) $(symtab_h) $(command_h) $(gdbcmd_h) $(symfile_h) \ - $(gdb_string_h) $(objfiles_h) $(inferior_h) $(regcache_h) + $(serial_h) $(symtab_h) $(command_h) $(gdbcmd_h) $(symfile_h) \ + $(gdb_string_h) $(objfiles_h) $(inferior_h) $(regcache_h) m32r-stub.o: m32r-stub.c $(syscall_h) m32r-tdep.o: m32r-tdep.c $(defs_h) $(frame_h) $(frame_unwind_h) \ $(frame_base_h) $(symtab_h) $(gdbtypes_h) $(gdbcmd_h) $(gdbcore_h) \ $(gdb_string_h) $(value_h) $(inferior_h) $(symfile_h) $(objfiles_h) \ $(language_h) $(arch_utils_h) $(regcache_h) $(trad_frame_h) \ - $(dis_asm_h) $(gdb_assert_h) + $(dis_asm_h) $(gdb_assert_h) $(m32r_tdep_h) m68hc11-tdep.o: m68hc11-tdep.c $(defs_h) $(frame_h) $(frame_unwind_h) \ $(frame_base_h) $(dwarf2_frame_h) $(trad_frame_h) $(symtab_h) \ $(gdbtypes_h) $(gdbcmd_h) $(gdbcore_h) $(gdb_string_h) $(value_h) \ Index: configure.tgt =================================================================== RCS file: /cvs/src/src/gdb/configure.tgt,v retrieving revision 1.148 diff -u -a -r1.148 configure.tgt --- configure.tgt 28 Sep 2004 20:39:17 -0000 1.148 +++ configure.tgt 30 Sep 2004 09:14:12 -0000 @@ -106,7 +106,8 @@ ;; ia64*-*-*) gdb_target=ia64 ;; -m32r-*-*) gdb_target=m32r ;; +m32r*-*-linux*) gdb_target=linux ;; +m32r*-*-*) gdb_target=m32r ;; m68hc11*-*-*|m6811*-*-*) gdb_target=m68hc11 ;; Index: m32r-linux-nat.c =================================================================== RCS file: m32r-linux-nat.c diff -N m32r-linux-nat.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ m32r-linux-nat.c 30 Sep 2004 09:14:12 -0000 @@ -0,0 +1,234 @@ +/* Native-dependent code for GNU/Linux m32r. + + Copyright 2004 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 2 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, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include "defs.h" +#include "inferior.h" +#include "gdbcore.h" +#include "regcache.h" +#include "linux-nat.h" + +#include "gdb_assert.h" +#include "gdb_string.h" +#include <sys/ptrace.h> +#include <sys/user.h> +#include <sys/procfs.h> + +/* Prototypes for supply_gregset etc. */ +#include "gregset.h" + +#include "m32r-tdep.h" + +\f + + +/* Since EVB register is not available for native debug, we reduce + the number of registers. */ +#define M32R_LINUX_NUM_REGS (M32R_NUM_REGS - 1) + +/* Mapping between the general-purpose registers in `struct user' + format and GDB's register array layout. */ +static int regmap[] = { + 4, 5, 6, 7, 0, 1, 2, 8, + 9, 10, 11, 12, 13, 24, 25, 23, + 19, 19, 26, 23, 22, 20, 16, 15 +}; + +#define PSW_REGMAP 19 +#define BBPSW_REGMAP 21 +#define SPU_REGMAP 23 +#define SPI_REGMAP 26 + +/* Doee apply to the corresponding SET requests as well. */ +#define GETREGS_SUPPLIES(regno) (0 <= (regno) && (regno) <= M32R_LINUX_NUM_REGS) + +\f + +/* Transfering the general-purpose registers between GDB, inferiors + and core files. */ + +/* Fill GDB's register array with the general-purpose register values + in *GREGSETP. */ + +void +supply_gregset (elf_gregset_t * gregsetp) +{ + elf_greg_t *regp = (elf_greg_t *) gregsetp; + int i; + unsigned long psw, bbpsw; + + psw = *(regp + PSW_REGMAP); + bbpsw = *(regp + BBPSW_REGMAP); + + for (i = 0; i < M32R_LINUX_NUM_REGS; i++) + { + switch (i) + { + case PSW_REGNUM: + *(regp + regmap[i]) = ((0x00c1 & bbpsw) << 8) | ((0xc100 & psw) >> 8); + break; + case CBR_REGNUM: + *(regp + regmap[i]) = ((psw >> 8) & 1); + break; + } + + if (i != M32R_SP_REGNUM) + regcache_raw_supply (current_regcache, i, regp + regmap[i]); + else if (psw & 0x8000) + regcache_raw_supply (current_regcache, i, regp + SPU_REGMAP); + else + regcache_raw_supply (current_regcache, i, regp + SPI_REGMAP); + } +} + +/* Fetch all general-purpose registers from process/thread TID and + store their values in GDB's register array. */ + +static void +fetch_regs (int tid) +{ + elf_gregset_t regs; + + if (ptrace (PTRACE_GETREGS, tid, 0, (int) ®s) < 0) + perror_with_name ("Couldn't get registers"); + + supply_gregset (®s); +} + +/* Fill register REGNO (if it is a general-purpose register) in + *GREGSETPS with the value in GDB's register array. If REGNO is -1, + do this for all registers. */ + +void +fill_gregset (elf_gregset_t * gregsetp, int regno) +{ + elf_greg_t *regp = (elf_greg_t *) gregsetp; + int i; + unsigned long psw, bbpsw, tmp; + + psw = *(regp + PSW_REGMAP); + bbpsw = *(regp + BBPSW_REGMAP); + + for (i = 0; i < M32R_LINUX_NUM_REGS; i++) + { + if (regno != -1 && regno != i) + continue; + + if (i == CBR_REGNUM || i == PSW_REGNUM) + continue; + + if (i == SPU_REGNUM || i == SPI_REGNUM) + continue; + + if (i != M32R_SP_REGNUM) + regcache_raw_collect (current_regcache, i, regp + regmap[i]); + else if (psw & 0x8000) + regcache_raw_collect (current_regcache, i, regp + SPU_REGMAP); + else + regcache_raw_collect (current_regcache, i, regp + SPI_REGMAP); + } +} + +/* Store all valid general-purpose registers in GDB's register array + into the process/thread specified by TID. */ + +static void +store_regs (int tid, int regno) +{ + elf_gregset_t regs; + + if (ptrace (PTRACE_GETREGS, tid, 0, (int) ®s) < 0) + perror_with_name ("Couldn't get registers"); + + fill_gregset (®s, regno); + + if (ptrace (PTRACE_SETREGS, tid, 0, (int) ®s) < 0) + perror_with_name ("Couldn't write registers"); +} + +\f + +/* Transfering floating-point registers between GDB, inferiors and cores. + Since M32R has no floating-point registers, these functions do nothing. */ + +void +supply_fpregset (gdb_fpregset_t *fpregs) +{ +} + +void +fill_fpregset (gdb_fpregset_t *fpregs, int regno) +{ +} + +\f + +/* Transferring arbitrary registers between GDB and inferior. */ + +/* Fetch register REGNO from the child process. If REGNO is -1, do + this for all registers (including the floating point and SSE + registers). */ + +void +fetch_inferior_registers (int regno) +{ + int tid; + + /* GNU/Linux LWP ID's are process ID's. */ + tid = TIDGET (inferior_ptid); + if (tid == 0) + tid = PIDGET (inferior_ptid); /* Not a threaded program. */ + + /* Use the PTRACE_GETREGS request whenever possible, since it + transfers more registers in one system call, and we'll cache the + results. */ + if (regno == -1 || GETREGS_SUPPLIES (regno)) + { + fetch_regs (tid); + return; + } + + internal_error (__FILE__, __LINE__, + "Got request for bad register number %d.", regno); +} + +/* Store register REGNO back into the child process. If REGNO is -1, + do this for all registers (including the floating point and SSE + registers). */ +void +store_inferior_registers (int regno) +{ + int tid; + + /* GNU/Linux LWP ID's are process ID's. */ + if ((tid = TIDGET (inferior_ptid)) == 0) + tid = PIDGET (inferior_ptid); /* Not a threaded program. */ + + /* Use the PTRACE_SETREGS request whenever possible, since it + transfers more registers in one system call. */ + if (regno == -1 || GETREGS_SUPPLIES (regno)) + { + store_regs (tid, regno); + return; + } + + internal_error (__FILE__, __LINE__, + "Got request to store bad register number %d.", regno); +} Index: m32r-linux-tdep.c =================================================================== RCS file: m32r-linux-tdep.c diff -N m32r-linux-tdep.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ m32r-linux-tdep.c 30 Sep 2004 09:14:12 -0000 @@ -0,0 +1,337 @@ +/* Target-dependent code for GNU/Linux m32r. + + Copyright 2004 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 2 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, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include "defs.h" +#include "gdbcore.h" +#include "frame.h" +#include "value.h" +#include "regcache.h" +#include "inferior.h" +#include "osabi.h" +#include "reggroups.h" + +#include "gdb_string.h" + +#include "glibc-tdep.h" +#include "solib-svr4.h" + +#include "trad-frame.h" +#include "frame-unwind.h" + +#include "m32r-tdep.h" +\f + +/* Recognizing signal handler frames. */ + +/* GNU/Linux has two flavors of signals. Normal signal handlers, and + "realtime" (RT) signals. The RT signals can provide additional + information to the signal handler if the SA_SIGINFO flag is set + when establishing a signal handler using `sigaction'. It is not + unlikely that future versions of GNU/Linux will support SA_SIGINFO + for normal signals too. */ + +/* When the m32r Linux kernel calls a signal handler and the + SA_RESTORER flag isn't set, the return address points to a bit of + code on the stack. This function returns whether the PC appears to + be within this bit of code. + + The instruction sequence for normal signals is + ldi r7, #__NR_sigreturn + trap #2 + or 0x67 0x77 0x10 0xf2. + + Checking for the code sequence should be somewhat reliable, because + the effect is to call the system call sigreturn. This is unlikely + to occur anywhere other than in a signal trampoline. + + It kind of sucks that we have to read memory from the process in + order to identify a signal trampoline, but there doesn't seem to be + any other way. Therefore we only do the memory reads if no + function name could be identified, which should be the case since + the code is on the stack. + + Detection of signal trampolines for handlers that set the + SA_RESTORER flag is in general not possible. Unfortunately this is + what the GNU C Library has been doing for quite some time now. + However, as of version 2.1.2, the GNU C Library uses signal + trampolines (named __restore and __restore_rt) that are identical + to the ones used by the kernel. Therefore, these trampolines are + supported too. */ + +static const unsigned char linux_sigtramp_code[] = +{ + 0x67, 0x77, 0x10, 0xf2, +}; + +/* If PC is in a sigtramp routine, return the address of the start of + the routine. Otherwise, return 0. */ + +static CORE_ADDR +m32r_linux_sigtramp_start (CORE_ADDR pc, struct frame_info *next_frame) +{ + unsigned char buf[4]; + + /* We only recognize a signal trampoline if PC is at the start of + one of the instructions. We optimize for finding the PC at the + start of the instruction sequence, as will be the case when the + trampoline is not the first frame on the stack. We assume that + in the case where the PC is not at the start of the instruction + sequence, there will be a few trailing readable bytes on the + stack. */ + + if (pc % 2 != 0) + { + if (!safe_frame_unwind_memory (next_frame, pc, buf, 2)) + return 0; + + if (memcmp (buf, linux_sigtramp_code, 2) == 0) + pc -= 2; + else + return 0; + } + + if (!safe_frame_unwind_memory (next_frame, pc, buf, 4)) + return 0; + + if (memcmp (buf, linux_sigtramp_code, 4) != 0) + return 0; + + return pc; +} + +/* This function does the same for RT signals. Here the instruction + sequence is + ldi r7, #__NR_rt_sigreturn + trap #2 + or 0x97 0xf0 0x00 0xad 0x10 0xf2 0xf0 0x00. + + The effect is to call the system call rt_sigreturn. */ + +static const unsigned char linux_rt_sigtramp_code[] = +{ + 0x97, 0xf0, 0x00, 0xad, 0x10, 0xf2, 0xf0, 0x00, +}; + +/* If PC is in a RT sigtramp routine, return the address of the start + of the routine. Otherwise, return 0. */ + +static CORE_ADDR +m32r_linux_rt_sigtramp_start (CORE_ADDR pc, struct frame_info *next_frame) +{ + unsigned char buf[4]; + + /* We only recognize a signal trampoline if PC is at the start of + one of the instructions. We optimize for finding the PC at the + start of the instruction sequence, as will be the case when the + trampoline is not the first frame on the stack. We assume that + in the case where the PC is not at the start of the instruction + sequence, there will be a few trailing readable bytes on the + stack. */ + + if (pc % 2 != 0) + return 0; + + if (!safe_frame_unwind_memory (next_frame, pc, buf, 4)) + return 0; + + if (memcmp (buf, linux_rt_sigtramp_code, 4) == 0) + { + if (!safe_frame_unwind_memory (next_frame, pc + 4, buf, 4)) + return 0; + + if (memcmp (buf, linux_rt_sigtramp_code + 4, 4) == 0) + return pc; + } + else if (memcmp (buf, linux_rt_sigtramp_code + 4, 4) == 0) + { + if (!safe_frame_unwind_memory (next_frame, pc - 4, buf, 4)) + return 0; + + if (memcmp (buf, linux_rt_sigtramp_code, 4) == 0) + return pc - 4; + } + + return 0; +} + +static int +m32r_linux_pc_in_sigtramp (CORE_ADDR pc, char *name, struct frame_info *next_frame) +{ + /* If we have NAME, we can optimize the search. The trampolines are + named __restore and __restore_rt. However, they aren't dynamically + exported from the shared C library, so the trampoline may appear to + be part of the preceding function. This should always be sigaction, + __sigaction, or __libc_sigaction (all aliases to the same function). */ + if (name == NULL || strstr (name, "sigaction") != NULL) + return (m32r_linux_sigtramp_start (pc, next_frame) != 0 + || m32r_linux_rt_sigtramp_start (pc, next_frame) != 0); + + return (strcmp ("__restore", name) == 0 + || strcmp ("__restore_rt", name) == 0); +} + +/* From <asm/sigcontext.h>. */ +static int m32r_linux_sc_reg_offset[] = { + 4 * 4, /* r0 */ + 5 * 4, /* r1 */ + 6 * 4, /* r2 */ + 7 * 4, /* r3 */ + 0 * 4, /* r4 */ + 1 * 4, /* r5 */ + 2 * 4, /* r6 */ + 8 * 4, /* r7 */ + 9 * 4, /* r8 */ + 10 * 4, /* r9 */ + 11 * 4, /* r10 */ + 12 * 4, /* r11 */ + 13 * 4, /* r12 */ + 21 * 4, /* fp */ + 22 * 4, /* lr */ + -1 * 4, /* sp */ + 16 * 4, /* psw */ + -1 * 4, /* cbr */ + 23 * 4, /* spi */ + 20 * 4, /* spu */ + 19 * 4, /* bpc */ + 17 * 4, /* pc */ + 15 * 4, /* accl */ + 14 * 4 /* acch */ +}; + +struct m32r_frame_cache +{ + CORE_ADDR base, pc; + struct trad_frame_saved_reg *saved_regs; +}; + +static struct m32r_frame_cache * +m32r_linux_sigtramp_frame_cache (struct frame_info *next_frame, + void **this_cache) +{ + struct m32r_frame_cache *cache; + CORE_ADDR sigcontext_addr, addr; + int regnum; + + if ((*this_cache) != NULL) + return (*this_cache); + cache = FRAME_OBSTACK_ZALLOC (struct m32r_frame_cache); + (*this_cache) = cache; + cache->saved_regs = trad_frame_alloc_saved_regs (next_frame); + + cache->base = frame_unwind_register_unsigned (next_frame, M32R_SP_REGNUM); + sigcontext_addr = cache->base + 4; + + cache->pc = frame_pc_unwind (next_frame); + addr = m32r_linux_sigtramp_start (cache->pc, next_frame); + if (addr == 0) + { + /* If this is a RT signal trampoline, adjust SIGCONTEXT_ADDR + accordingly. */ + addr = m32r_linux_rt_sigtramp_start (cache->pc, next_frame); + if (addr) + sigcontext_addr += 128; + else + addr = frame_func_unwind (next_frame); + } + cache->pc = addr; + + cache->saved_regs = trad_frame_alloc_saved_regs (next_frame); + + for (regnum = 0; regnum < sizeof (m32r_linux_sc_reg_offset) / 4; regnum++) + { + if (m32r_linux_sc_reg_offset[regnum] >= 0) + cache->saved_regs[regnum].addr = + sigcontext_addr + m32r_linux_sc_reg_offset[regnum]; + } + + return cache; +} + +static void +m32r_linux_sigtramp_frame_this_id (struct frame_info *next_frame, + void **this_cache, + struct frame_id *this_id) +{ + struct m32r_frame_cache *cache = + m32r_linux_sigtramp_frame_cache (next_frame, this_cache); + + (*this_id) = frame_id_build (cache->base, cache->pc); +} + +static void +m32r_linux_sigtramp_frame_prev_register (struct frame_info *next_frame, + void **this_cache, + int regnum, int *optimizedp, + enum lval_type *lvalp, + CORE_ADDR *addrp, + int *realnump, void *valuep) +{ + struct m32r_frame_cache *cache = + m32r_linux_sigtramp_frame_cache (next_frame, this_cache); + + trad_frame_get_prev_register (next_frame, cache->saved_regs, regnum, + optimizedp, lvalp, addrp, realnump, valuep); +} + +static const struct frame_unwind m32r_linux_sigtramp_frame_unwind = { + SIGTRAMP_FRAME, + m32r_linux_sigtramp_frame_this_id, + m32r_linux_sigtramp_frame_prev_register +}; + +static const struct frame_unwind * +m32r_linux_sigtramp_frame_sniffer (struct frame_info *next_frame) +{ + CORE_ADDR pc = frame_pc_unwind (next_frame); + char *name; + + find_pc_partial_function (pc, &name, NULL, NULL); + if (m32r_linux_pc_in_sigtramp (pc, name, next_frame)) + return &m32r_linux_sigtramp_frame_unwind; + + return NULL; +} + +static void +m32r_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) +{ + struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); + + /* Since EVB register is not available for native debug, we reduce + the number of registers. */ + set_gdbarch_num_regs (gdbarch, M32R_NUM_REGS - 1); + + frame_unwind_append_sniffer (gdbarch, m32r_linux_sigtramp_frame_sniffer); + + /* GNU/Linux uses SVR4-style shared libraries. */ + set_solib_svr4_fetch_link_map_offsets + (gdbarch, svr4_ilp32_fetch_link_map_offsets); +} + +/* Provide a prototype to silence -Wmissing-prototypes. */ +extern void _initialize_m32r_linux_tdep (void); + +void +_initialize_m32r_linux_tdep (void) +{ + gdbarch_register_osabi (bfd_arch_m32r, 0, GDB_OSABI_LINUX, + m32r_linux_init_abi); +} Index: m32r-tdep.c =================================================================== RCS file: /cvs/src/src/gdb/m32r-tdep.c,v retrieving revision 1.30 diff -u -a -r1.30 m32r-tdep.c --- m32r-tdep.c 2 Aug 2004 19:44:40 -0000 1.30 +++ m32r-tdep.c 30 Sep 2004 09:14:12 -0000 @@ -41,27 +41,7 @@ #include "gdb_assert.h" -struct gdbarch_tdep -{ - /* gdbarch target dependent data here. Currently unused for M32R. */ -}; - -/* m32r register names. */ - -enum -{ - R0_REGNUM = 0, - R3_REGNUM = 3, - M32R_FP_REGNUM = 13, - LR_REGNUM = 14, - M32R_SP_REGNUM = 15, - PSW_REGNUM = 16, - M32R_PC_REGNUM = 21, - /* m32r calling convention. */ - ARG1_REGNUM = R0_REGNUM, - ARGN_REGNUM = R3_REGNUM, - RET1_REGNUM = R0_REGNUM, -}; +#include "m32r-tdep.h" /* Local functions */ @@ -238,18 +218,12 @@ "evb" }; -static int -m32r_num_regs (void) -{ - return (sizeof (m32r_register_names) / sizeof (m32r_register_names[0])); -} - static const char * m32r_register_name (int reg_nr) { if (reg_nr < 0) return NULL; - if (reg_nr >= m32r_num_regs ()) + if (reg_nr >= M32R_NUM_REGS) return NULL; return m32r_register_names[reg_nr]; } @@ -921,7 +895,7 @@ set_gdbarch_write_pc (gdbarch, m32r_write_pc); set_gdbarch_unwind_sp (gdbarch, m32r_unwind_sp); - set_gdbarch_num_regs (gdbarch, m32r_num_regs ()); + set_gdbarch_num_regs (gdbarch, M32R_NUM_REGS); set_gdbarch_sp_regnum (gdbarch, M32R_SP_REGNUM); set_gdbarch_register_name (gdbarch, m32r_register_name); set_gdbarch_register_type (gdbarch, m32r_register_type); Index: m32r-tdep.h =================================================================== RCS file: m32r-tdep.h diff -N m32r-tdep.h --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ m32r-tdep.h 30 Sep 2004 09:14:12 -0000 @@ -0,0 +1,52 @@ +/* Target-dependent code for Renesas M32R, for GDB. + + Copyright 2004 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 2 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, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#ifndef M32R_TDEP_H +#define M32R_TDEP_H + +struct gdbarch_tdep +{ + /* gdbarch target dependent data here. Currently unused for M32R. */ +}; + +/* m32r register names. */ + +enum m32r_regnum +{ + R0_REGNUM = 0, + R3_REGNUM = 3, + M32R_FP_REGNUM = 13, + LR_REGNUM = 14, + M32R_SP_REGNUM = 15, + PSW_REGNUM = 16, + CBR_REGNUM = 17, + SPU_REGNUM = 18, + SPI_REGNUM = 19, + M32R_PC_REGNUM = 21, + /* m32r calling convention. */ + ARG1_REGNUM = R0_REGNUM, + ARGN_REGNUM = R3_REGNUM, + RET1_REGNUM = R0_REGNUM, +}; + +#define M32R_NUM_REGS 25 + +#endif /* m32r-tdep.h */ Index: config/djgpp/fnchange.lst =================================================================== RCS file: /cvs/src/src/gdb/config/djgpp/fnchange.lst,v retrieving revision 1.82 diff -u -a -r1.82 fnchange.lst --- config/djgpp/fnchange.lst 3 Sep 2004 19:08:17 -0000 1.82 +++ config/djgpp/fnchange.lst 30 Sep 2004 09:14:12 -0000 @@ -138,6 +138,8 @@ @V@/gdb/ia64-linux-nat.c @V@/gdb/ia64lx-tdep.c @V@/gdb/jv-exp.tab.c @V@/gdb/jv-exp_tab.c @V@/gdb/m2-exp.tab.c @V@/gdb/m2-exp_tab.c +@V@/gdb/m32r-linux-nat.c @V@/gdb/m32rlnxnat.c +@V@/gdb/m32r-linux-tdep.c @V@/gdb/m32rlnxtdep.c @V@/gdb/m68klinux-nat.c @V@/gdb/m68kl-nat.c @V@/gdb/m68klinux-tdep.c @V@/gdb/m68kl-tdep.c @V@/gdb/m68kbsd-nat.c @V@/gdb/m68bsd-nat.c Index: config/m32r/linux.mh =================================================================== RCS file: config/m32r/linux.mh diff -N config/m32r/linux.mh --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ config/m32r/linux.mh 30 Sep 2004 09:14:12 -0000 @@ -0,0 +1,8 @@ +# Host: M32R based machine running GNU/Linux + +NAT_FILE= nm-linux.h +NATDEPFILES= infptrace.o inftarg.o fork-child.o corelow.o \ + m32r-linux-nat.o gcore.o proc-service.o thread-db.o \ + linux-nat.o + +LOADLIBES= -ldl -rdynamic Index: config/m32r/linux.mt =================================================================== RCS file: config/m32r/linux.mt diff -N config/m32r/linux.mt --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ config/m32r/linux.mt 30 Sep 2004 09:14:12 -0000 @@ -0,0 +1,6 @@ +# Target: Renesas M32R running GNU/Linux +TDEPFILES= m32r-tdep.o m32r-linux-tdep.o remote-m32r-sdi.o glibc-tdep.o solib.o solib-svr4.o solib-legacy.o +DEPRECATED_TM_FILE= config/tm-linux.h + +SIM_OBS = remote-sim.o +SIM = ../sim/m32r/libsim.a Index: config/m32r/nm-linux.h =================================================================== RCS file: config/m32r/nm-linux.h diff -N config/m32r/nm-linux.h --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ config/m32r/nm-linux.h 30 Sep 2004 09:14:12 -0000 @@ -0,0 +1,29 @@ +/* Definitions to make GDB run on an M32R based machine under GNU/Linux. + Copyright 2004 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 2 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, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#ifndef NM_M32R_LINUX_H +#define NM_M32R_LINUX_H + +#include "config/nm-linux.h" + +/* Override copies of {fetch,store}_inferior_registers in infptrace.c. */ +#define FETCH_INFERIOR_REGISTERS + +#endif /* NM_M32R_LINUX_H */ ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [RFA/m32r] revised m32r-linux patch 2004-10-01 0:20 ` Kei Sakamoto @ 2004-10-01 7:18 ` Mark Kettenis 2004-10-01 7:33 ` [commit/m32r] " Kei Sakamoto 0 siblings, 1 reply; 11+ messages in thread From: Mark Kettenis @ 2004-10-01 7:18 UTC (permalink / raw) To: sakamoto.kei; +Cc: gdb-patches From: "Kei Sakamoto" <sakamoto.kei@renesas.com> Date: Fri, 1 Oct 2004 09:20:37 +0900 I'm sorry. I forgot to attach the patch file... ;-) > OK to commit now? Yes please. Thanks for your contribution! > 2004-09-30 Kei Sakamoto <sakamoto.kei@renesas.com> > > Add m32r-linux support. > * configure.tgt: Add m32r*-*-linux*. > * Makefile.in (ALLDEPFILES): Add m32r-tdep.c, m32r-linux-nat.c > and m32r-linux-tdep.c. > (m32r-linux-nat.o, m32r-linux-tdep.o): New dependencies. > * m32r-tdep.c: Move some definitions to m32r-tdep.h. > * config/djgpp/fnchange.lst: Add m32r-linux-nat.c and > m32r-linux-tdep.c. > * m32r-tdep.h, m32r-linux-nat.c, m32r-linux-tdep.c, > config/m32r/linux.mh, config/m32r/linux.mt, > config/m32r/nm-linux.h: New files. > ^ permalink raw reply [flat|nested] 11+ messages in thread
* [commit/m32r] revised m32r-linux patch 2004-10-01 7:18 ` Mark Kettenis @ 2004-10-01 7:33 ` Kei Sakamoto 0 siblings, 0 replies; 11+ messages in thread From: Kei Sakamoto @ 2004-10-01 7:33 UTC (permalink / raw) To: Mark Kettenis; +Cc: gdb-patches I committed the following patch. Thenk you. Kei Sakamoto > From: "Kei Sakamoto" <sakamoto.kei@renesas.com> > Date: Fri, 1 Oct 2004 09:20:37 +0900 > > I'm sorry. I forgot to attach the patch file... > > ;-) > > > OK to commit now? > > Yes please. Thanks for your contribution! > > > 2004-09-30 Kei Sakamoto <sakamoto.kei@renesas.com> > > > > Add m32r-linux support. > > * configure.tgt: Add m32r*-*-linux*. > > * Makefile.in (ALLDEPFILES): Add m32r-tdep.c, m32r-linux-nat.c > > and m32r-linux-tdep.c. > > (m32r-linux-nat.o, m32r-linux-tdep.o): New dependencies. > > * m32r-tdep.c: Move some definitions to m32r-tdep.h. > > * config/djgpp/fnchange.lst: Add m32r-linux-nat.c and > > m32r-linux-tdep.c. > > * m32r-tdep.h, m32r-linux-nat.c, m32r-linux-tdep.c, > > config/m32r/linux.mh, config/m32r/linux.mt, > > config/m32r/nm-linux.h: New files. ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [RFA/m32r] revised m32r-linux patch 2004-09-28 10:04 ` [RFA/m32r] revised m32r-linux patch Kei Sakamoto 2004-09-28 12:31 ` Mark Kettenis @ 2004-09-28 19:53 ` Eli Zaretskii 1 sibling, 0 replies; 11+ messages in thread From: Eli Zaretskii @ 2004-09-28 19:53 UTC (permalink / raw) To: Kei Sakamoto; +Cc: kettenis, gdb-patches > From: "Kei Sakamoto" <sakamoto.kei@renesas.com> > Cc: <gdb-patches@sources.redhat.com> > Date: Tue, 28 Sep 2004 19:04:14 +0900 > > * m32r-tdep.c: Move some definitions to m32r-tdep.h. > * m32r-tdep.h, m32r-linux-nat.c, m32r-linux-tdep.c, ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ These file names need entries in config/djgpp/fnchange.lst. ^ permalink raw reply [flat|nested] 11+ messages in thread
end of thread, other threads:[~2004-10-01 7:33 UTC | newest] Thread overview: 11+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2004-09-15 8:01 Fw: Unreviewed patch (m32r-linux support) Kei Sakamoto 2004-09-15 11:25 ` Mark Kettenis 2004-09-16 4:32 ` Kei Sakamoto 2004-09-16 13:59 ` Andrew Cagney 2004-09-28 10:04 ` [RFA/m32r] revised m32r-linux patch Kei Sakamoto 2004-09-28 12:31 ` Mark Kettenis 2004-09-30 9:35 ` Kei Sakamoto 2004-10-01 0:20 ` Kei Sakamoto 2004-10-01 7:18 ` Mark Kettenis 2004-10-01 7:33 ` [commit/m32r] " Kei Sakamoto 2004-09-28 19:53 ` [RFA/m32r] " Eli Zaretskii
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox