summaryrefslogtreecommitdiffstats
path: root/recipes-devtools/gdb/files/0009-Patch-microblaze-Initial-support-for-native-gdb.patch
diff options
context:
space:
mode:
Diffstat (limited to 'recipes-devtools/gdb/files/0009-Patch-microblaze-Initial-support-for-native-gdb.patch')
-rw-r--r--recipes-devtools/gdb/files/0009-Patch-microblaze-Initial-support-for-native-gdb.patch495
1 files changed, 0 insertions, 495 deletions
diff --git a/recipes-devtools/gdb/files/0009-Patch-microblaze-Initial-support-for-native-gdb.patch b/recipes-devtools/gdb/files/0009-Patch-microblaze-Initial-support-for-native-gdb.patch
deleted file mode 100644
index 1ad6b89c..00000000
--- a/recipes-devtools/gdb/files/0009-Patch-microblaze-Initial-support-for-native-gdb.patch
+++ /dev/null
@@ -1,495 +0,0 @@
1From c7b918283f2e438deef78aae84f6b748a7a1bb54 Mon Sep 17 00:00:00 2001
2From: David Holsgrove <david.holsgrove@petalogix.com>
3Date: Fri, 20 Jul 2012 15:18:35 +1000
4Subject: [PATCH 09/16] [Patch, microblaze]: Initial support for native gdb
5
6microblaze: Follow PPC method of getting setting registers
7using PTRACE PEEK/POKE
8
9Signed-off-by: David Holsgrove <david.holsgrove@petalogix.com>
10Upstream-Status: Pending
11---
12 gdb/Makefile.in | 4 +-
13 gdb/config/microblaze/linux.mh | 10 +
14 gdb/microblaze-linux-nat.c | 431 +++++++++++++++++++++++++++++++++++++++++
15 3 files changed, 443 insertions(+), 2 deletions(-)
16 create mode 100644 gdb/config/microblaze/linux.mh
17 create mode 100644 gdb/microblaze-linux-nat.c
18
19diff --git a/gdb/Makefile.in b/gdb/Makefile.in
20index f2c16ec..12870a4 100644
21--- a/gdb/Makefile.in
22+++ b/gdb/Makefile.in
23@@ -904,7 +904,7 @@ top.h bsd-kvm.h gdb-stabs.h reggroups.h \
24 annotate.h sim-regno.h dictionary.h dfp.h main.h frame-unwind.h \
25 remote-fileio.h i386-linux-tdep.h vax-tdep.h objc-lang.h \
26 sentinel-frame.h bcache.h symfile.h windows-tdep.h linux-tdep.h \
27-gdb_usleep.h jit.h xml-syscall.h microblaze-tdep.h \
28+gdb_usleep.h jit.h xml-syscall.h microblaze-tdep.h microblaze-linux-tdep.h \
29 psymtab.h psympriv.h progspace.h bfin-tdep.h ia64-hpux-tdep.h \
30 amd64-darwin-tdep.h charset-list.h \
31 config/djgpp/langinfo.h config/djgpp/nl_types.h darwin-nat.h \
32@@ -1631,7 +1631,7 @@ ALLDEPFILES = \
33 m68kbsd-nat.c m68kbsd-tdep.c \
34 m68klinux-nat.c m68klinux-tdep.c \
35 m88k-tdep.c m88kbsd-nat.c \
36- microblaze-tdep.c microblaze-linux-tdep.c \
37+ microblaze-tdep.c microblaze-linux-nat.c microblaze-linux-tdep.c \
38 mingw-hdep.c \
39 mips-linux-nat.c mips-linux-tdep.c \
40 mips-irix-tdep.c \
41diff --git a/gdb/config/microblaze/linux.mh b/gdb/config/microblaze/linux.mh
42new file mode 100644
43index 0000000..547d103
44--- /dev/null
45+++ b/gdb/config/microblaze/linux.mh
46@@ -0,0 +1,10 @@
47+# Host: Microblaze, running Linux
48+
49+NAT_FILE= config/nm-linux.h
50+NATDEPFILES= inf-ptrace.o fork-child.o \
51+ microblaze-linux-nat.o proc-service.o linux-thread-db.o \
52+ linux-nat.o linux-osdata.o linux-fork.o linux-procfs.o linux-ptrace.o \
53+ linux-waitpid.o
54+NAT_CDEPS = $(srcdir)/proc-service.list
55+
56+LOADLIBES = -ldl $(RDYNAMIC)
57diff --git a/gdb/microblaze-linux-nat.c b/gdb/microblaze-linux-nat.c
58new file mode 100644
59index 0000000..81f8346
60--- /dev/null
61+++ b/gdb/microblaze-linux-nat.c
62@@ -0,0 +1,431 @@
63+/* Microblaze GNU/Linux native support.
64+
65+ Copyright (C) 1988-1989, 1991-1992, 1994, 1996, 2000-2012 Free
66+ Software Foundation, Inc.
67+
68+ This file is part of GDB.
69+
70+ This program is free software; you can redistribute it and/or modify
71+ it under the terms of the GNU General Public License as published by
72+ the Free Software Foundation; either version 3 of the License, or
73+ (at your option) any later version.
74+
75+ This program is distributed in the hope that it will be useful,
76+ but WITHOUT ANY WARRANTY; without even the implied warranty of
77+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
78+ GNU General Public License for more details.
79+
80+ You should have received a copy of the GNU General Public License
81+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
82+
83+#include "defs.h"
84+#include "arch-utils.h"
85+#include "dis-asm.h"
86+#include "frame.h"
87+#include "trad-frame.h"
88+#include "symtab.h"
89+#include "value.h"
90+#include "gdbcmd.h"
91+#include "breakpoint.h"
92+#include "inferior.h"
93+#include "regcache.h"
94+#include "target.h"
95+#include "frame.h"
96+#include "frame-base.h"
97+#include "frame-unwind.h"
98+#include "dwarf2-frame.h"
99+#include "osabi.h"
100+
101+#include "gdb_assert.h"
102+#include <string.h>
103+#include "target-descriptions.h"
104+#include "opcodes/microblaze-opcm.h"
105+#include "opcodes/microblaze-dis.h"
106+
107+#include "linux-nat.h"
108+#include "target-descriptions.h"
109+
110+#include <sys/user.h>
111+#include <sys/utsname.h>
112+#include <sys/procfs.h>
113+#include <sys/ptrace.h>
114+
115+/* Prototypes for supply_gregset etc. */
116+#include "gregset.h"
117+
118+#include "microblaze-tdep.h"
119+
120+#include <elf/common.h>
121+#include "auxv.h"
122+
123+/* Defines ps_err_e, struct ps_prochandle. */
124+#include "gdb_proc_service.h"
125+
126+/* On GNU/Linux, threads are implemented as pseudo-processes, in which
127+ case we may be tracing more than one process at a time. In that
128+ case, inferior_ptid will contain the main process ID and the
129+ individual thread (process) ID. get_thread_id () is used to get
130+ the thread id if it's available, and the process id otherwise. */
131+
132+int
133+get_thread_id (ptid_t ptid)
134+{
135+ int tid = ptid_get_lwp (ptid);
136+ if (0 == tid)
137+ tid = ptid_get_pid (ptid);
138+ return tid;
139+}
140+
141+#define GET_THREAD_ID(PTID) get_thread_id (PTID)
142+
143+/* Non-zero if our kernel may support the PTRACE_GETREGS and
144+ PTRACE_SETREGS requests, for reading and writing the
145+ general-purpose registers. Zero if we've tried one of
146+ them and gotten an error. */
147+int have_ptrace_getsetregs = 1;
148+
149+static int
150+microblaze_register_u_addr (struct gdbarch *gdbarch, int regno)
151+{
152+ int u_addr = -1;
153+ struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
154+ /* NOTE: cagney/2003-11-25: This is the word size used by the ptrace
155+ interface, and not the wordsize of the program's ABI. */
156+ int wordsize = sizeof (long);
157+
158+ /* General purpose registers occupy 1 slot each in the buffer. */
159+ if (regno >= MICROBLAZE_R0_REGNUM
160+ && regno <= MICROBLAZE_FSR_REGNUM)
161+ u_addr = (regno * wordsize);
162+
163+ return u_addr;
164+}
165+
166+
167+static void
168+fetch_register (struct regcache *regcache, int tid, int regno)
169+{
170+ struct gdbarch *gdbarch = get_regcache_arch (regcache);
171+ struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
172+ /* This isn't really an address. But ptrace thinks of it as one. */
173+ CORE_ADDR regaddr = microblaze_register_u_addr (gdbarch, regno);
174+ int bytes_transferred;
175+ unsigned int offset; /* Offset of registers within the u area. */
176+ char buf[MAX_REGISTER_SIZE];
177+
178+ if (regaddr == -1)
179+ {
180+ memset (buf, '\0', register_size (gdbarch, regno)); /* Supply zeroes */
181+ regcache_raw_supply (regcache, regno, buf);
182+ return;
183+ }
184+
185+ /* Read the raw register using sizeof(long) sized chunks. On a
186+ 32-bit platform, 64-bit floating-point registers will require two
187+ transfers. */
188+ for (bytes_transferred = 0;
189+ bytes_transferred < register_size (gdbarch, regno);
190+ bytes_transferred += sizeof (long))
191+ {
192+ long l;
193+
194+ errno = 0;
195+ l = ptrace (PTRACE_PEEKUSER, tid, (PTRACE_TYPE_ARG3) regaddr, 0);
196+ regaddr += sizeof (long);
197+ if (errno != 0)
198+ {
199+ char message[128];
200+ sprintf (message, "reading register %s (#%d)",
201+ gdbarch_register_name (gdbarch, regno), regno);
202+ perror_with_name (message);
203+ }
204+ memcpy (&buf[bytes_transferred], &l, sizeof (l));
205+ }
206+
207+ /* Now supply the register. Keep in mind that the regcache's idea
208+ of the register's size may not be a multiple of sizeof
209+ (long). */
210+ if (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_LITTLE)
211+ {
212+ /* Little-endian values are always found at the left end of the
213+ bytes transferred. */
214+ regcache_raw_supply (regcache, regno, buf);
215+ }
216+ else if (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG)
217+ {
218+ /* Big-endian values are found at the right end of the bytes
219+ transferred. */
220+ size_t padding = (bytes_transferred - register_size (gdbarch, regno));
221+ regcache_raw_supply (regcache, regno, buf + padding);
222+ }
223+ else
224+ internal_error (__FILE__, __LINE__,
225+ _("fetch_register: unexpected byte order: %d"),
226+ gdbarch_byte_order (gdbarch));
227+}
228+
229+/* This function actually issues the request to ptrace, telling
230+ it to get all general-purpose registers and put them into the
231+ specified regset.
232+
233+ If the ptrace request does not exist, this function returns 0
234+ and properly sets the have_ptrace_* flag. If the request fails,
235+ this function calls perror_with_name. Otherwise, if the request
236+ succeeds, then the regcache gets filled and 1 is returned. */
237+static int
238+fetch_all_gp_regs (struct regcache *regcache, int tid)
239+{
240+ struct gdbarch *gdbarch = get_regcache_arch (regcache);
241+ struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
242+ gdb_gregset_t gregset;
243+
244+ if (ptrace (PTRACE_GETREGS, tid, 0, (void *) &gregset) < 0)
245+ {
246+ if (errno == EIO)
247+ {
248+ have_ptrace_getsetregs = 0;
249+ return 0;
250+ }
251+ perror_with_name (_("Couldn't get general-purpose registers."));
252+ }
253+
254+ supply_gregset (regcache, (const gdb_gregset_t *) &gregset);
255+
256+ return 1;
257+}
258+
259+
260+/* This is a wrapper for the fetch_all_gp_regs function. It is
261+ responsible for verifying if this target has the ptrace request
262+ that can be used to fetch all general-purpose registers at one
263+ shot. If it doesn't, then we should fetch them using the
264+ old-fashioned way, which is to iterate over the registers and
265+ request them one by one. */
266+static void
267+fetch_gp_regs (struct regcache *regcache, int tid)
268+{
269+ struct gdbarch *gdbarch = get_regcache_arch (regcache);
270+ struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
271+ int i;
272+
273+ if (have_ptrace_getsetregs)
274+ if (fetch_all_gp_regs (regcache, tid))
275+ return;
276+
277+ /* If we've hit this point, it doesn't really matter which
278+ architecture we are using. We just need to read the
279+ registers in the "old-fashioned way". */
280+ for (i = MICROBLAZE_R0_REGNUM; i <= MICROBLAZE_FSR_REGNUM; i++)
281+ fetch_register (regcache, tid, i);
282+}
283+
284+
285+static void
286+store_register (const struct regcache *regcache, int tid, int regno)
287+{
288+ struct gdbarch *gdbarch = get_regcache_arch (regcache);
289+ struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
290+ /* This isn't really an address. But ptrace thinks of it as one. */
291+ CORE_ADDR regaddr = microblaze_register_u_addr (gdbarch, regno);
292+ int i;
293+ size_t bytes_to_transfer;
294+ char buf[MAX_REGISTER_SIZE];
295+
296+ if (regaddr == -1)
297+ return;
298+
299+ /* First collect the register. Keep in mind that the regcache's
300+ idea of the register's size may not be a multiple of sizeof
301+ (long). */
302+ memset (buf, 0, sizeof buf);
303+ bytes_to_transfer = align_up (register_size (gdbarch, regno), sizeof (long));
304+ if (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_LITTLE)
305+ {
306+ /* Little-endian values always sit at the left end of the buffer. */
307+ regcache_raw_collect (regcache, regno, buf);
308+ }
309+ else if (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG)
310+ {
311+ /* Big-endian values sit at the right end of the buffer. */
312+ size_t padding = (bytes_to_transfer - register_size (gdbarch, regno));
313+ regcache_raw_collect (regcache, regno, buf + padding);
314+ }
315+
316+ for (i = 0; i < bytes_to_transfer; i += sizeof (long))
317+ {
318+ long l;
319+
320+ memcpy (&l, &buf[i], sizeof (l));
321+ errno = 0;
322+ ptrace (PTRACE_POKEUSER, tid, (PTRACE_TYPE_ARG3) regaddr, l);
323+ regaddr += sizeof (long);
324+
325+ if (errno != 0)
326+ {
327+ char message[128];
328+ sprintf (message, "writing register %s (#%d)",
329+ gdbarch_register_name (gdbarch, regno), regno);
330+ perror_with_name (message);
331+ }
332+ }
333+}
334+
335+/* This function actually issues the request to ptrace, telling
336+ it to store all general-purpose registers present in the specified
337+ regset.
338+
339+ If the ptrace request does not exist, this function returns 0
340+ and properly sets the have_ptrace_* flag. If the request fails,
341+ this function calls perror_with_name. Otherwise, if the request
342+ succeeds, then the regcache is stored and 1 is returned. */
343+static int
344+store_all_gp_regs (const struct regcache *regcache, int tid, int regno)
345+{
346+ struct gdbarch *gdbarch = get_regcache_arch (regcache);
347+ struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
348+ gdb_gregset_t gregset;
349+
350+ if (ptrace (PTRACE_GETREGS, tid, 0, (void *) &gregset) < 0)
351+ {
352+ if (errno == EIO)
353+ {
354+ have_ptrace_getsetregs = 0;
355+ return 0;
356+ }
357+ perror_with_name (_("Couldn't get general-purpose registers."));
358+ }
359+
360+ fill_gregset (regcache, &gregset, regno);
361+
362+ if (ptrace (PTRACE_SETREGS, tid, 0, (void *) &gregset) < 0)
363+ {
364+ if (errno == EIO)
365+ {
366+ have_ptrace_getsetregs = 0;
367+ return 0;
368+ }
369+ perror_with_name (_("Couldn't set general-purpose registers."));
370+ }
371+
372+ return 1;
373+}
374+
375+/* This is a wrapper for the store_all_gp_regs function. It is
376+ responsible for verifying if this target has the ptrace request
377+ that can be used to store all general-purpose registers at one
378+ shot. If it doesn't, then we should store them using the
379+ old-fashioned way, which is to iterate over the registers and
380+ store them one by one. */
381+static void
382+store_gp_regs (const struct regcache *regcache, int tid, int regno)
383+{
384+ struct gdbarch *gdbarch = get_regcache_arch (regcache);
385+ struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
386+ int i;
387+
388+ if (have_ptrace_getsetregs)
389+ if (store_all_gp_regs (regcache, tid, regno))
390+ return;
391+
392+ /* If we hit this point, it doesn't really matter which
393+ architecture we are using. We just need to store the
394+ registers in the "old-fashioned way". */
395+ for (i = MICROBLAZE_R0_REGNUM; i <= MICROBLAZE_FSR_REGNUM; i++)
396+ store_register (regcache, tid, i);
397+}
398+
399+
400+/* Fetch registers from the child process. Fetch all registers if
401+ regno == -1, otherwise fetch all general registers or all floating
402+ point registers depending upon the value of regno. */
403+
404+static void
405+microblaze_linux_fetch_inferior_registers (struct target_ops *ops,
406+ struct regcache *regcache, int regno)
407+{
408+ /* Get the thread id for the ptrace call. */
409+ int tid = GET_THREAD_ID (inferior_ptid);
410+
411+ if (regno == -1)
412+ fetch_gp_regs (regcache, tid);
413+ else
414+ fetch_register (regcache, tid, regno);
415+}
416+
417+/* Store registers back into the inferior. Store all registers if
418+ regno == -1, otherwise store all general registers or all floating
419+ point registers depending upon the value of regno. */
420+
421+static void
422+microblaze_linux_store_inferior_registers (struct target_ops *ops,
423+ struct regcache *regcache, int regno)
424+{
425+ /* Get the thread id for the ptrace call. */
426+ int tid = GET_THREAD_ID (inferior_ptid);
427+
428+ if (regno >= 0)
429+ store_register (regcache, tid, regno);
430+ else
431+ store_gp_regs (regcache, tid, -1);
432+}
433+
434+/* Wrapper functions for the standard regset handling, used by
435+ thread debugging. */
436+
437+void
438+fill_gregset (const struct regcache *regcache,
439+ gdb_gregset_t *gregsetp, int regno)
440+{
441+ microblaze_collect_gregset (NULL, regcache, regno, gregsetp);
442+}
443+
444+void
445+supply_gregset (struct regcache *regcache, const gdb_gregset_t *gregsetp)
446+{
447+ microblaze_supply_gregset (NULL, regcache, -1, gregsetp);
448+}
449+
450+void
451+fill_fpregset (const struct regcache *regcache,
452+ gdb_fpregset_t *fpregsetp, int regno)
453+{
454+ /* FIXME. */
455+}
456+
457+void
458+supply_fpregset (struct regcache *regcache, const gdb_fpregset_t *fpregsetp)
459+{
460+ /* FIXME. */
461+}
462+
463+static const struct target_desc *
464+microblaze_linux_read_description (struct target_ops *ops)
465+{
466+ CORE_ADDR microblaze_hwcap = 0;
467+
468+ if (target_auxv_search (ops, AT_HWCAP, &microblaze_hwcap) != 1)
469+ return NULL;
470+
471+ return NULL;
472+}
473+
474+
475+void _initialize_microblaze_linux_nat (void);
476+
477+void
478+_initialize_microblaze_linux_nat (void)
479+{
480+ struct target_ops *t;
481+
482+ /* Fill in the generic GNU/Linux methods. */
483+ t = linux_target ();
484+
485+ /* Add our register access methods. */
486+ t->to_fetch_registers = microblaze_linux_fetch_inferior_registers;
487+ t->to_store_registers = microblaze_linux_store_inferior_registers;
488+
489+ t->to_read_description = microblaze_linux_read_description;
490+
491+ /* Register the target. */
492+ linux_nat_add_target (t);
493+}
494--
4951.9.0