aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFlorian Boor <florian.boor@kernelconcepts.de>2011-12-13 10:47:27 +0100
committerFlorian Boor <florian.boor@kernelconcepts.de>2012-09-27 17:36:59 +0200
commit15a9a957541702815fde60bcf382316cbc5e4e6e (patch)
tree1a15b2130a4f970f5b3b627a427d3f5e7ba626a9
parent043e45da4d6cc4da5acb21cf11245d3ddd81b83c (diff)
downloadopenembedded-15a9a957541702815fde60bcf382316cbc5e4e6e.tar.gz
gdbserver: Add 7.2a since 7.2 disappeared from the GNU mirrors
Signed-off-by: Florian Boor <florian.boor@kernelconcepts.de>
-rw-r--r--recipes/gdb/gdb-7.2a/gdb-6.8-fix-compile-karmic.patch22
-rw-r--r--recipes/gdb/gdb-7.2a/gdb-6.8-mingw-3.patch374
-rw-r--r--recipes/gdb/gdb-7.2a/gdb-6.8-pr9638-ppc-canadian-configh.patch179
-rw-r--r--recipes/gdb/gdb-7.2a/gdb-tcsetpgrp.patch43
-rw-r--r--recipes/gdb/gdb-7.2a/gdbserver-cflags-last.diff15
-rw-r--r--recipes/gdb/gdb-7.2a/renesas-sh-native-support.patch1410
-rw-r--r--recipes/gdb/gdb_7.2a.bb21
-rw-r--r--recipes/gdb/gdbserver_7.2a.bb11
8 files changed, 2075 insertions, 0 deletions
diff --git a/recipes/gdb/gdb-7.2a/gdb-6.8-fix-compile-karmic.patch b/recipes/gdb/gdb-7.2a/gdb-6.8-fix-compile-karmic.patch
new file mode 100644
index 0000000000..1080b162aa
--- /dev/null
+++ b/recipes/gdb/gdb-7.2a/gdb-6.8-fix-compile-karmic.patch
@@ -0,0 +1,22 @@
+fix this on karmic
+
+cc1: warnings being treated as errors
+/home/ich/build/arm/armv5t/tmp/work/i686-armv5te-sdk-oe-linux-gnueabi/gdb-cross-sdk-6.8-r2/gdb-6.8/gdb/eval.c: In function 'evaluate_subexp_standard':
+/home/ich/build/arm/armv5t/tmp/work/i686-armv5te-sdk-oe-linux-gnueabi/gdb-cross-sdk-6.8-r2/gdb-6.8/gdb/eval.c:1705: error: 'subscript_array' may be used uninitialized in this function
+/home/ich/build/arm/armv5t/tmp/work/i686-armv5te-sdk-oe-linux-gnueabi/gdb-cross-sdk-6.8-r2/gdb-6.8/gdb/eval.c:1644: note: 'subscript_array' was declared here
+
+
+
+Index: gdb-6.8/gdb/eval.c
+===================================================================
+--- gdb-6.8.orig/gdb/eval.c 2009-08-02 03:25:20.000000000 +0200
++++ gdb-6.8/gdb/eval.c 2009-08-02 03:53:39.000000000 +0200
+@@ -1656,6 +1656,8 @@
+ if (nargs != ndimensions)
+ error (_("Wrong number of subscripts"));
+
++ memset(&subscript_array, 0, sizeof(subscript_array));
++
+ /* Now that we know we have a legal array subscript expression
+ let us actually find out where this element exists in the array. */
+
diff --git a/recipes/gdb/gdb-7.2a/gdb-6.8-mingw-3.patch b/recipes/gdb/gdb-7.2a/gdb-6.8-mingw-3.patch
new file mode 100644
index 0000000000..5bede42eb0
--- /dev/null
+++ b/recipes/gdb/gdb-7.2a/gdb-6.8-mingw-3.patch
@@ -0,0 +1,374 @@
+Index: gdb-7.0/gdb/gdbserver/remote-utils.c
+===================================================================
+--- gdb-7.0.orig/gdb/gdbserver/remote-utils.c 2009-07-06 11:31:20.000000000 -0700
++++ gdb-7.0/gdb/gdbserver/remote-utils.c 2009-10-13 15:16:16.495396950 -0700
+@@ -778,7 +778,12 @@ input_interrupt (int unused)
+
+ cc = read (remote_desc, &c, 1);
+
++#ifdef _WIN32_WINNT
++ // its normal in windows for current_inferior to be null.
++ if (cc != 1 || c != '\003' /*|| current_inferior == NULL*/)
++#else
+ if (cc != 1 || c != '\003' || current_inferior == NULL)
++#endif
+ {
+ fprintf (stderr, "input_interrupt, count = %d c = %d ('%c')\n",
+ cc, c, c);
+Index: gdb-7.0/gdb/gdbserver/server.c
+===================================================================
+--- gdb-7.0.orig/gdb/gdbserver/server.c 2009-06-30 09:35:25.000000000 -0700
++++ gdb-7.0/gdb/gdbserver/server.c 2009-10-13 15:18:08.065401029 -0700
+@@ -31,6 +31,9 @@
+ #if HAVE_MALLOC_H
+ #include <malloc.h>
+ #endif
++#ifdef _WIN32
++#include <windows.h>
++#endif
+
+ ptid_t cont_thread;
+ ptid_t general_thread;
+@@ -502,6 +505,20 @@ monitor_show_help (void)
+ monitor_output (" Enable h/w breakpoint/watchpoint debugging messages\n");
+ monitor_output (" set remote-debug <0|1>\n");
+ monitor_output (" Enable remote protocol debugging messages\n");
++#ifdef _WIN32
++ monitor_output (" get processlist\n");
++ monitor_output (" List remote processes with names and pid\n");
++ monitor_output (" get processlistmi\n");
++ monitor_output (" Process list in an MI-like format\n");
++#endif
++ monitor_output (" set env <name=value>\n");
++ monitor_output (" Set environment variable in remote environment\n");
++ monitor_output (" cd <directory>\n");
++ monitor_output (" Change current working directory\n");
++ monitor_output (" pwd\n");
++ monitor_output (" Print current working directory\n");
++ monitor_output (" shell <command line>\n");
++ monitor_output (" Execute command on remote target\n");
+ monitor_output (" exit\n");
+ monitor_output (" Quit GDBserver\n");
+ }
+@@ -660,6 +677,47 @@ handle_search_memory (char *own_buf, int
+ return; \
+ }
+
++#ifdef _WIN32
++typedef DWORD (__stdcall *GETPROCESSIMAGEFILENAME)(HANDLE hProcess, LPTSTR lpImageFileName, DWORD nSize);
++typedef BOOL (__stdcall *ENUMPROCESSES)(DWORD* pProcessIds, DWORD cb, DWORD* pBytesReturned);
++
++# define HAS_DEVICE(P) \
++((((P)[0] >= 'A' && (P)[0] <= 'Z') || ((P)[0] >= 'a' && (P)[0] <= 'z')) \
++&& (P)[1] == ':')
++# define FILE_SYSTEM_PREFIX_LEN(P) (HAS_DEVICE (P) ? 2 : 0)
++# define ISSLASH(C) ((C) == '/' || (C) == '\\')
++
++char *
++__basename (char const *name)
++{
++ char const *base = name += FILE_SYSTEM_PREFIX_LEN (name);
++ int all_slashes = 1;
++ char const *p;
++
++ for (p = name; *p; p++)
++ {
++ if (ISSLASH (*p))
++ base = p + 1;
++ else
++ all_slashes = 0;
++ }
++
++ /* If NAME is all slashes, arrange to return `/'. */
++ if (*base == '\0' && ISSLASH (*name) && all_slashes)
++ --base;
++
++ /* Make sure the last byte is not a slash. */
++ //assert (all_slashes || !ISSLASH (*(p - 1)));
++
++ return (char *) base;
++}
++#endif
++
++#ifndef _POSIX_PATH_MAX
++#define _POSIX_PATH_MAX 1024
++#define _POSIX_PATH_MAX_WAS_UNDEFINED
++#endif
++
+ /* Handle all of the extended 'q' packets. */
+ void
+ handle_query (char *own_buf, int packet_len, int *new_packet_len_p)
+@@ -1216,6 +1274,158 @@ handle_query (char *own_buf, int packet_
+ debug_threads = 1;
+ monitor_output ("Debug output enabled.\n");
+ }
++#ifdef _WIN32
++ else if (strncmp (mon, "get processlist", 15) == 0)
++ {
++ HINSTANCE lib = LoadLibrary("PSAPI.DLL");
++ GETPROCESSIMAGEFILENAME imageFilename = (GETPROCESSIMAGEFILENAME)GetProcAddress(lib, "GetProcessImageFileNameA");
++ ENUMPROCESSES enumProcesses = (ENUMPROCESSES)GetProcAddress(lib, "EnumProcesses");
++
++ char* name = (char*)malloc(MAX_PATH);
++
++ int miMode = (strcmp(mon, "get processlistmi") == 0);
++
++ DWORD* pids = (DWORD*)malloc(sizeof(DWORD)*1024);
++ memset(pids, 0, sizeof(pids));
++ DWORD size = 0;
++
++ if (!enumProcesses(pids, 1024 * sizeof(DWORD), &size))
++ {
++ free(pids);
++ free(mon);
++ return;
++ }
++
++ int cnt = 0;
++ int number = size / sizeof(DWORD);
++
++ char* miOutput = NULL;
++
++ if (!miMode)
++ monitor_output("Remote process list:\n");
++ else
++ {
++ miOutput = (char*)malloc((number * 255) * sizeof(char));
++ strcpy(miOutput, "^done,processlist=[");
++ }
++
++ for (cnt = 0; cnt < number; cnt++)
++ {
++ HMODULE hProcess = (HMODULE)OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, pids[cnt]);
++ strcpy(name, "");
++ printf(name);
++
++ imageFilename(hProcess, name, MAX_PATH);
++
++ if (pids[cnt] > 4 && strcmp(name, "") != 0)
++ {
++ char item[2048] = "";
++ char tmp[24] = "0";
++ itoa(pids[cnt], tmp, 10);
++ strcat(item, tmp);
++ strcat(item, "=");
++ strcat(item, __basename(name));
++
++ if (!miMode)
++ {
++ strcat(item, "\n");
++ monitor_output(item);
++ }
++ else
++ {
++ strcat(miOutput, item);
++ strcat(miOutput, ",");
++ }
++ }
++
++ CloseHandle(hProcess);
++ }
++
++ if (miMode)
++ {
++ strcat(miOutput, "]\n");
++ monitor_output(miOutput);
++ free(miOutput);
++ }
++
++ FreeLibrary(lib);
++
++ free(pids);
++ free(name);
++ }
++#endif
++ else if (strncmp (mon, "set env ", 8) == 0)
++ {
++ char* envLine = mon + 8;
++ char* envName = strtok(envLine, "= ");
++ char* envValue = strtok(NULL, "= ");
++ if (envName && envValue)
++ {
++#ifdef _WIN32
++ SetEnvironmentVariable(envName, envValue);
++#else
++ setenv(envName, envValue, 1);
++#endif
++ monitor_output("Target environment variable set (");
++ monitor_output(envName);
++ monitor_output(" = ");
++ monitor_output(envValue);
++ monitor_output(").\n");
++ }
++ else
++ monitor_output("Incorrect format for environment variable.\n");
++ }
++ else if (strncmp (mon, "cd ", 3) == 0)
++ {
++ char* dir = mon + 3;
++ if (strlen(dir) > 0)
++ chdir(dir);
++ }
++ else if (strcmp(mon, "pwd") == 0)
++ {
++ long size = _POSIX_PATH_MAX;
++ char* current_directory = (char*)malloc(size);
++ getcwd(current_directory, size);
++ if (strlen(current_directory) > 0)
++ {
++ monitor_output(current_directory);
++ monitor_output("\n");
++ }
++ free(current_directory);
++ }
++ else if (strncmp (mon, "shell ", 6) == 0)
++ {
++ char* arg = mon + 6;
++
++ if (strlen(arg) == 0)
++ {
++ monitor_output("Inferior shells are not supported.");
++ free(mon);
++ return;
++ }
++
++ long size = _POSIX_PATH_MAX;
++ char* current_directory = (char*)malloc(size);
++ getcwd(current_directory, size);
++
++ int rc = system (arg);
++ char msg[255];
++ if (rc == -1)
++ {
++ sprintf(msg, "Cannot execute '%s': %s.\n", arg, strerror(errno));
++ monitor_output(msg);
++ }
++ else if (rc != -1)
++ {
++ sprintf(msg, "'%s' exited with status %d.\n", arg, rc);
++ monitor_output(msg);
++ }
++
++ /* Make sure to return to the directory GDB thinks it is, in case the
++ shell command we just ran changed it. */
++ chdir(current_directory);
++ free(current_directory);
++ }
+ else if (strcmp (mon, "set debug 0") == 0)
+ {
+ debug_threads = 0;
+@@ -1295,6 +1505,11 @@ handle_query (char *own_buf, int packet_
+ own_buf[0] = 0;
+ }
+
++#ifdef _POSIX_PATH_MAX_WAS_UNDEFINED
++#undef _POSIX_PATH_MAX
++#undef _POSIX_PATH_MAX_WAS_UNDEFINED
++#endif
++
+ /* Parse vCont packets. */
+ void
+ handle_v_cont (char *own_buf)
+Index: gdb-7.0/gdb/gdbserver/win32-low.c
+===================================================================
+--- gdb-7.0.orig/gdb/gdbserver/win32-low.c 2009-07-04 11:13:28.000000000 -0700
++++ gdb-7.0/gdb/gdbserver/win32-low.c 2009-10-13 15:16:16.495396950 -0700
+@@ -38,7 +38,7 @@
+ #include <sys/cygwin.h>
+ #endif
+
+-#define LOG 0
++#define LOG 1
+
+ #define OUTMSG(X) do { printf X; fflush (stdout); } while (0)
+ #if LOG
+@@ -556,9 +556,9 @@ win32_create_inferior (char *program, ch
+ }
+ OUTMSG2 (("Command line is \"%s\"\n", args));
+
+-#ifdef CREATE_NEW_PROCESS_GROUP
++//#ifdef CREATE_NEW_PROCESS_GROUP
+ flags |= CREATE_NEW_PROCESS_GROUP;
+-#endif
++//#endif
+
+ ret = create_process (program, args, flags, &pi);
+ err = GetLastError ();
+@@ -699,8 +699,37 @@ win32_kill (int pid)
+ if (current_process_handle == NULL)
+ return -1;
+
+- TerminateProcess (current_process_handle, 0);
+- for (;;)
++ TerminateProcess (current_process_handle, 0);
++
++ // BKS - fix for terminating apps prior to their exit, lets go of execs.
++ winapi_DebugActiveProcessStop DebugActiveProcessStop = NULL;
++ winapi_DebugSetProcessKillOnExit DebugSetProcessKillOnExit = NULL;
++#ifdef _WIN32_WCE
++ HMODULE dll = GetModuleHandle (_T("COREDLL.DLL"));
++#else
++ HMODULE dll = GetModuleHandle (_T("KERNEL32.DLL"));
++#endif
++ DebugActiveProcessStop = GETPROCADDRESS (dll, DebugActiveProcessStop);
++ DebugSetProcessKillOnExit = GETPROCADDRESS (dll, DebugSetProcessKillOnExit);
++
++ if (DebugSetProcessKillOnExit != NULL
++ && DebugActiveProcessStop != NULL)
++ {
++ {
++ struct thread_resume resume;
++ resume.thread = -1;
++ resume.step = 0;
++ resume.sig = 0;
++ resume.leave_stopped = 0;
++ win32_resume (&resume);
++ }
++
++ DebugActiveProcessStop (current_process_id);
++ DebugSetProcessKillOnExit (FALSE);
++ }
++ // end BKS
++
++ for (;;)
+ {
+ if (!child_continue (DBG_CONTINUE, -1))
+ break;
+@@ -1207,6 +1236,7 @@ handle_exception (struct target_waitstat
+
+ ourstatus->kind = TARGET_WAITKIND_STOPPED;
+
++ //printf("handle exception....................%X\n", (unsigned int)code);
+ switch (code)
+ {
+ case EXCEPTION_ACCESS_VIOLATION:
+@@ -1217,7 +1247,13 @@ handle_exception (struct target_waitstat
+ OUTMSG2 (("STATUS_STACK_OVERFLOW"));
+ ourstatus->value.sig = TARGET_SIGNAL_SEGV;
+ break;
+- case STATUS_FLOAT_DENORMAL_OPERAND:
++ // BKS
++ case STATUS_INVALID_HANDLE:
++ OUTMSG2 (("STATUS_INVALID_HANDLE"));
++ ourstatus->value.sig = TARGET_SIGNAL_TRAP;
++ break;
++ // BKS
++ case STATUS_FLOAT_DENORMAL_OPERAND:
+ OUTMSG2 (("STATUS_FLOAT_DENORMAL_OPERAND"));
+ ourstatus->value.sig = TARGET_SIGNAL_FPE;
+ break;
+Index: gdb-7.0/gdb/windows-nat.c
+===================================================================
+--- gdb-7.0.orig/gdb/windows-nat.c 2009-09-30 00:40:10.000000000 -0700
++++ gdb-7.0/gdb/windows-nat.c 2009-10-13 15:16:16.505397243 -0700
+@@ -1035,6 +1035,10 @@ handle_exception (struct target_waitstat
+ DEBUG_EXCEPTION_SIMPLE ("STATUS_STACK_OVERFLOW");
+ ourstatus->value.sig = TARGET_SIGNAL_SEGV;
+ break;
++ case STATUS_INVALID_HANDLE:
++ DEBUG_EXCEPTION_SIMPLE ("STATUS_INVALID_HANDLE");
++ ourstatus->value.sig = TARGET_SIGNAL_TRAP;
++ break;
+ case STATUS_FLOAT_DENORMAL_OPERAND:
+ DEBUG_EXCEPTION_SIMPLE ("STATUS_FLOAT_DENORMAL_OPERAND");
+ ourstatus->value.sig = TARGET_SIGNAL_FPE;
diff --git a/recipes/gdb/gdb-7.2a/gdb-6.8-pr9638-ppc-canadian-configh.patch b/recipes/gdb/gdb-7.2a/gdb-6.8-pr9638-ppc-canadian-configh.patch
new file mode 100644
index 0000000000..83e85ba3cd
--- /dev/null
+++ b/recipes/gdb/gdb-7.2a/gdb-6.8-pr9638-ppc-canadian-configh.patch
@@ -0,0 +1,179 @@
+diff -urN gdb-6.8-pl1/sim/ppc/Makefile.in gdb-6.8-pl2/sim/ppc/Makefile.in
+--- gdb-6.8-pl1/sim/ppc/Makefile.in 2006-05-31 17:14:45.000000000 +0200
++++ gdb-6.8-pl2/sim/ppc/Makefile.in 2008-09-30 15:56:33.000000000 +0200
+@@ -61,7 +61,7 @@
+ AR = @AR@
+ AR_FLAGS = rc
+ CC = @CC@
+-CFLAGS = @CFLAGS@
++CFLAGS = @CFLAGS@ -DHAVE_CONFIG_H
+ CC_FOR_BUILD = @CC_FOR_BUILD@
+ CFLAGS_FOR_BUILD = @CFLAGS_FOR_BUILD@
+ BISON = bison
+@@ -115,8 +115,8 @@
+ $(DEVZERO_CFLAGS)
+ SIM_FPU_CFLAGS = @sim_fpu_cflags@
+
+-STD_CFLAGS = $(CFLAGS) $(INLINE_CFLAGS) $(CONFIG_CFLAGS) $(WARNING_CFLAGS) $(SIM_CFLAGS) $(HDEFINES) $(TDEFINES) $(INCLUDES) $(INTL_CFLAGS) $(SIM_FPU_CFLAGS)
+-NOWARN_CFLAGS = $(CFLAGS) $(INLINE_CFLAGS) $(CONFIG_CFLAGS) $(SIM_CFLAGS) $(HDEFINES) $(TDEFINES) $(INCLUDES) $(SIM_FPU_CFLAGS)
++STD_CFLAGS = $(CFLAGS) -DHAVE_CONFIG_H $(INLINE_CFLAGS) $(CONFIG_CFLAGS) $(WARNING_CFLAGS) $(SIM_CFLAGS) $(HDEFINES) $(TDEFINES) $(INCLUDES) $(INTL_CFLAGS) $(SIM_FPU_CFLAGS)
++NOWARN_CFLAGS = $(CFLAGS) -DHAVE_CONFIG_H $(INLINE_CFLAGS) $(CONFIG_CFLAGS) $(SIM_CFLAGS) $(HDEFINES) $(TDEFINES) $(INCLUDES) $(SIM_FPU_CFLAGS)
+ BUILD_CFLAGS = $(CFLAGS_FOR_BUILD) $(INCLUDES) $(WARNING_CFLAGS)
+
+ BUILD_LDFLAGS =
+diff -urN gdb-6.8-orig/sim/ppc/basics.h gdb-6.8-pl1/sim/ppc/basics.h
+--- gdb-6.8-orig/sim/ppc/basics.h 1999-04-16 03:35:08.000000000 +0200
++++ gdb-6.8-pl1/sim/ppc/basics.h 2008-09-30 15:12:32.000000000 +0200
+@@ -86,7 +86,9 @@
+
+ /* Basic configuration */
+
++#ifdef HAVE_CONFIG_H
+ #include "config.h"
++#endif
+ #include "ppc-config.h"
+ #include "inline.h"
+
+diff -urN gdb-6.8-orig/sim/ppc/debug.c gdb-6.8-pl1/sim/ppc/debug.c
+--- gdb-6.8-orig/sim/ppc/debug.c 1999-04-16 03:35:08.000000000 +0200
++++ gdb-6.8-pl1/sim/ppc/debug.c 2008-09-30 15:12:27.000000000 +0200
+@@ -22,7 +22,9 @@
+ #ifndef _DEBUG_C_
+ #define _DEBUG_C_
+
++#ifdef HAVE_CONFIG_H
+ #include "config.h"
++#endif
+ #include "basics.h"
+
+ #ifdef HAVE_STDLIB_H
+diff -urN gdb-6.8-orig/sim/ppc/dgen.c gdb-6.8-pl1/sim/ppc/dgen.c
+--- gdb-6.8-orig/sim/ppc/dgen.c 1999-04-16 03:35:08.000000000 +0200
++++ gdb-6.8-pl1/sim/ppc/dgen.c 2008-09-30 15:12:22.000000000 +0200
+@@ -27,7 +27,9 @@
+ #include <ctype.h>
+ #include <stdarg.h>
+
++#ifdef HAVE_CONFIG_H
+ #include "config.h"
++#endif
+ #include "misc.h"
+ #include "lf.h"
+ #include "table.h"
+diff -urN gdb-6.8-orig/sim/ppc/filter.c gdb-6.8-pl1/sim/ppc/filter.c
+--- gdb-6.8-orig/sim/ppc/filter.c 1999-04-16 03:35:09.000000000 +0200
++++ gdb-6.8-pl1/sim/ppc/filter.c 2008-09-30 15:12:15.000000000 +0200
+@@ -21,7 +21,9 @@
+
+ #include <stdio.h>
+
++#ifdef HAVE_CONFIG_H
+ #include "config.h"
++#endif
+
+ #ifdef HAVE_STRING_H
+ #include <string.h>
+diff -urN gdb-6.8-orig/sim/ppc/filter_filename.c gdb-6.8-pl1/sim/ppc/filter_filename.c
+--- gdb-6.8-orig/sim/ppc/filter_filename.c 1999-04-16 03:35:08.000000000 +0200
++++ gdb-6.8-pl1/sim/ppc/filter_filename.c 2008-09-30 15:12:11.000000000 +0200
+@@ -18,7 +18,9 @@
+
+ */
+
++#ifdef HAVE_CONFIG_H
+ #include "config.h"
++#endif
+ #include "ppc-config.h"
+ #include "filter_filename.h"
+
+diff -urN gdb-6.8-orig/sim/ppc/igen.c gdb-6.8-pl1/sim/ppc/igen.c
+--- gdb-6.8-orig/sim/ppc/igen.c 2003-06-20 05:59:33.000000000 +0200
++++ gdb-6.8-pl1/sim/ppc/igen.c 2008-09-30 15:12:06.000000000 +0200
+@@ -25,7 +25,9 @@
+ #include "misc.h"
+ #include "lf.h"
+ #include "table.h"
++#ifdef HAVE_CONFIG_H
+ #include "config.h"
++#endif
+
+ #include "filter.h"
+
+diff -urN gdb-6.8-orig/sim/ppc/inline.c gdb-6.8-pl1/sim/ppc/inline.c
+--- gdb-6.8-orig/sim/ppc/inline.c 1999-04-16 03:35:10.000000000 +0200
++++ gdb-6.8-pl1/sim/ppc/inline.c 2008-09-30 15:11:58.000000000 +0200
+@@ -22,7 +22,9 @@
+ #ifndef _INLINE_C_
+ #define _INLINE_C_
+
++#ifdef HAVE_CONFIG_H
+ #include "config.h"
++#endif
+ #include "ppc-config.h"
+
+ #include "inline.h"
+diff -urN gdb-6.8-orig/sim/ppc/lf.c gdb-6.8-pl1/sim/ppc/lf.c
+--- gdb-6.8-orig/sim/ppc/lf.c 2002-05-30 17:07:06.000000000 +0200
++++ gdb-6.8-pl1/sim/ppc/lf.c 2008-09-30 15:33:35.000000000 +0200
+@@ -23,7 +23,9 @@
+ #include <stdarg.h>
+ #include <ctype.h>
+
++#ifdef HAVE_CONFIG_H
+ #include "config.h"
++#endif
+ #include "misc.h"
+ #include "lf.h"
+
+diff -urN gdb-6.8-orig/sim/ppc/misc.c gdb-6.8-pl1/sim/ppc/misc.c
+--- gdb-6.8-orig/sim/ppc/misc.c 1999-04-16 03:35:11.000000000 +0200
++++ gdb-6.8-pl1/sim/ppc/misc.c 2008-09-30 15:11:54.000000000 +0200
+@@ -23,7 +23,9 @@
+ #include <stdarg.h>
+ #include <ctype.h>
+
++#ifdef HAVE_CONFIG_H
+ #include "config.h"
++#endif
+ #include "misc.h"
+
+ #ifdef HAVE_STDLIB_H
+diff -urN gdb-6.8-orig/sim/ppc/misc.h gdb-6.8-pl1/sim/ppc/misc.h
+--- gdb-6.8-orig/sim/ppc/misc.h 2002-01-12 11:21:12.000000000 +0100
++++ gdb-6.8-pl1/sim/ppc/misc.h 2008-09-30 15:11:49.000000000 +0200
+@@ -21,7 +21,9 @@
+
+ /* Frustrating header junk */
+
++#ifdef HAVE_CONFIG_H
+ #include "config.h"
++#endif
+
+ #include <stdio.h>
+ #include <ctype.h>
+diff -urN gdb-6.8-orig/sim/ppc/sim-endian.c gdb-6.8-pl1/sim/ppc/sim-endian.c
+--- gdb-6.8-orig/sim/ppc/sim-endian.c 1999-04-16 03:35:11.000000000 +0200
++++ gdb-6.8-pl1/sim/ppc/sim-endian.c 2008-09-30 15:11:44.000000000 +0200
+@@ -22,7 +22,9 @@
+ #ifndef _SIM_ENDIAN_C_
+ #define _SIM_ENDIAN_C_
+
++#ifdef HAVE_CONFIG_H
+ #include "config.h"
++#endif
+ #include "basics.h"
+
+
+diff -urN gdb-6.8-orig/sim/ppc/table.c gdb-6.8-pl1/sim/ppc/table.c
+--- gdb-6.8-orig/sim/ppc/table.c 2002-01-12 11:21:12.000000000 +0100
++++ gdb-6.8-pl1/sim/ppc/table.c 2008-09-30 15:11:38.000000000 +0200
+@@ -25,7 +25,9 @@
+ #include <fcntl.h>
+ #include <ctype.h>
+
++#ifdef HAVE_CONFIG_H
+ #include "config.h"
++#endif
+ #include "misc.h"
+ #include "lf.h"
+ #include "table.h"
diff --git a/recipes/gdb/gdb-7.2a/gdb-tcsetpgrp.patch b/recipes/gdb/gdb-7.2a/gdb-tcsetpgrp.patch
new file mode 100644
index 0000000000..d642721127
--- /dev/null
+++ b/recipes/gdb/gdb-7.2a/gdb-tcsetpgrp.patch
@@ -0,0 +1,43 @@
+Stuart Hughes, stuarth@freescale.com 8th April 05
+
+Extracted from:
+
+From: Davin Milun (milun@cs.buffalo.edu)
+Subject: Re: xxgdb for Solaris
+View: Complete Thread (4 articles)
+Original Format
+Newsgroups: comp.unix.solaris
+Date: 1995/05/05
+
+Geraldo Veiga <ggv@research.att.com> wrote:
+>Now, how do I avoid those
+>
+>[tcsetpgrp failed in terminal_inferior: Inappropriate ioctl for device]
+>
+>messages at every step the program takes under mxgdb (and xxgdb)?. I am
+>running GDB4.13 under Solaris 2.4.
+
+You need to patch inflow.c.
+
+
+ diff --exclude CVS -uNr gdb-6.0/gdb/inflow.c gdb-6.0.modified/gdb/inflow.c
+Index: gdb-7.1/gdb/inflow.c
+===================================================================
+--- gdb-7.1.orig/gdb/inflow.c 2010-01-21 06:26:12.000000000 -0800
++++ gdb-7.1/gdb/inflow.c 2010-06-09 13:59:33.761358724 -0700
+@@ -308,13 +308,13 @@ terminal_inferior (void)
+ {
+ #ifdef HAVE_TERMIOS
+ result = tcsetpgrp (0, tinfo->process_group);
+- if (!inf->attach_flag)
++ if (!inf->attach_flag && errno != ENOTTY)
+ OOPSY ("tcsetpgrp");
+ #endif
+
+ #ifdef HAVE_SGTTY
+ result = ioctl (0, TIOCSPGRP, &tinfo->process_group);
+- if (!inf->attach_flag)
++ if (!inf->attach_flag && errno != ENOTTY)
+ OOPSY ("TIOCSPGRP");
+ #endif
+ }
diff --git a/recipes/gdb/gdb-7.2a/gdbserver-cflags-last.diff b/recipes/gdb/gdb-7.2a/gdbserver-cflags-last.diff
new file mode 100644
index 0000000000..57e78f6b3d
--- /dev/null
+++ b/recipes/gdb/gdb-7.2a/gdbserver-cflags-last.diff
@@ -0,0 +1,15 @@
+Index: gdb/gdbserver/Makefile.in
+===================================================================
+--- gdb/gdbserver/Makefile.in.orig 2009-07-31 08:23:20.000000000 -0700
++++ gdb/gdbserver/Makefile.in 2009-10-13 14:47:21.365401025 -0700
+@@ -89,8 +89,8 @@ WARN_CFLAGS = -Wall
+ CFLAGS = @CFLAGS@
+
+ # INTERNAL_CFLAGS is the aggregate of all other *CFLAGS macros.
+-INTERNAL_CFLAGS = $(WARN_CFLAGS) ${CFLAGS} ${GLOBAL_CFLAGS} \
+- ${PROFILE_CFLAGS} ${INCLUDE_CFLAGS}
++INTERNAL_CFLAGS = $(WARN_CFLAGS) ${GLOBAL_CFLAGS} \
++ ${PROFILE_CFLAGS} ${INCLUDE_CFLAGS} ${CFLAGS}
+
+ # LDFLAGS is specifically reserved for setting from the command line
+ # when running make.
diff --git a/recipes/gdb/gdb-7.2a/renesas-sh-native-support.patch b/recipes/gdb/gdb-7.2a/renesas-sh-native-support.patch
new file mode 100644
index 0000000000..2495516fa5
--- /dev/null
+++ b/recipes/gdb/gdb-7.2a/renesas-sh-native-support.patch
@@ -0,0 +1,1410 @@
+This patch is taken from http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=576242
+to support build GDB natively for SH target.
+
+-Khem
+
+
+From 56915d38b2422deff54c90bd53ea03c834b3b513 Mon Sep 17 00:00:00 2001
+From: Takashi YOSHII <yoshii.takashi@renesas.com>
+Date: Mon, 8 Mar 2010 10:45:54 +0900
+Subject: [PATCH] Add Renesas SuperH native support
+
+---
+ gdb/Makefile.in | 1 +
+ gdb/config/sh/linux.mh | 8 +
+ gdb/config/sh/nm-linux.h | 54 ++++
+ gdb/config/sh/xm-linux.h | 32 ++
+ gdb/configure.host | 1 +
+ gdb/sh-linux-nat.c | 269 ++++++++++++++++++
+ gdb/sh-linux-tdep.c | 519 ++++++++++++++++++++++++++++++++++
+ gdb/sh-tdep.c | 54 ++--
+ gdb/sh-tdep.h | 49 ++++
+ gdb/testsuite/gdb.asm/asm-source.exp | 5 +
+ gdb/testsuite/gdb.asm/sh-linux.inc | 78 +++++
+ gdb/testsuite/gdb.asm/sh.inc | 3 +-
+ gdb/testsuite/gdb.base/annota1.c | 6 +-
+ gdb/testsuite/gdb.base/annota3.c | 6 +-
+ gdb/testsuite/gdb.base/sigall.c | 6 +-
+ gdb/testsuite/gdb.base/signals.c | 8 +-
+ 16 files changed, 1057 insertions(+), 42 deletions(-)
+ create mode 100644 gdb/config/sh/linux.mh
+ create mode 100644 gdb/config/sh/nm-linux.h
+ create mode 100644 gdb/config/sh/xm-linux.h
+ create mode 100644 gdb/sh-linux-nat.c
+ create mode 100644 gdb/testsuite/gdb.asm/sh-linux.inc
+
+diff --git a/gdb/Makefile.in b/gdb/Makefile.in
+index 72b546d..4325d5f 100644
+--- a/gdb/Makefile.in
++++ b/gdb/Makefile.in
+@@ -1476,6 +1476,7 @@ ALLDEPFILES = \
+ score-tdep.c \
+ ser-go32.c ser-pipe.c ser-tcp.c ser-mingw.c \
+ sh-tdep.c sh64-tdep.c shnbsd-tdep.c shnbsd-nat.c \
++ sh-linux-tdep.c sh-linux-nat.c \
+ sol2-tdep.c \
+ solib-irix.c solib-svr4.c solib-sunos.c \
+ sparc-linux-nat.c sparc-linux-tdep.c \
+diff --git a/gdb/config/sh/linux.mh b/gdb/config/sh/linux.mh
+new file mode 100644
+index 0000000..86fa8b9
+--- /dev/null
++++ b/gdb/config/sh/linux.mh
+@@ -0,0 +1,8 @@
++# Host: Renesas Super-H running GNU/Linux
++NAT_FILE= nm-linux.h
++NATDEPFILES= inf-ptrace.o fork-child.o corelow.o \
++ sh-linux-nat.o \
++ proc-service.o linux-thread-db.o gcore.o \
++ linux-nat.o linux-fork.o
++
++LOADLIBES= -ldl -rdynamic
+diff --git a/gdb/config/sh/nm-linux.h b/gdb/config/sh/nm-linux.h
+new file mode 100644
+index 0000000..4e6fd5a
+--- /dev/null
++++ b/gdb/config/sh/nm-linux.h
+@@ -0,0 +1,54 @@
++/* Native-dependent definitions for SuperH running Linux, 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 NM_LINUX_H
++#define NM_LINUX_H
++
++/* Get generic Linux native definitions. */
++#include "config/nm-linux.h"
++/* 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 substract from u.u_ar0 to get the offset in
++ the core file of the register values. */
++#define KERNEL_U_ADDR 0
++
++#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)
++
++/* Override copies of {fetch,store}_inferior_registers in `infptrace.c'. */
++#define FETCH_INFERIOR_REGISTERS
++
++/* Nevertheless, define CANNOT_{FETCH,STORE}_REGISTER, because we
++ might fall back on the code `infptrace.c' (well a copy of that code
++ in `sh-linux-nat.c' for now) and we can access only the
++ general-purpose registers in that way. */
++extern int cannot_fetch_register (int regno);
++extern int cannot_store_register (int regno);
++#define CANNOT_FETCH_REGISTER(regno) cannot_fetch_register (regno)
++#define CANNOT_STORE_REGISTER(regno) cannot_store_register (regno)
++
++#endif /* NM_LINUX_H */
+diff --git a/gdb/config/sh/xm-linux.h b/gdb/config/sh/xm-linux.h
+new file mode 100644
+index 0000000..6482093
+--- /dev/null
++++ b/gdb/config/sh/xm-linux.h
+@@ -0,0 +1,32 @@
++/* Native support for GNU/Linux, for GDB, the GNU debugger.
++ Copyright (C) 2000 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 XM_LINUX_H
++#define XM_LINUX_H
++
++#define HOST_BYTE_ORDER LITTLE_ENDIAN
++
++#define HAVE_TERMIOS
++
++#define NEED_POSIX_SETPGID
++
++/* Need R_OK etc, but USG isn't defined. */
++#include <unistd.h>
++
++#endif /* #ifndef XM_LINUX_H */
+diff --git a/gdb/configure.host b/gdb/configure.host
+index 794eeee..ebc209b 100644
+--- a/gdb/configure.host
++++ b/gdb/configure.host
+@@ -139,6 +139,7 @@ powerpc64-*-linux*) gdb_host=ppc64-linux
+
+ s390*-*-*) gdb_host=s390 ;;
+
++sh*-*-linux*) gdb_host=linux ;;
+ sh*-*-netbsdelf* | sh*-*-knetbsd*-gnu)
+ gdb_host=nbsd ;;
+ sh*-*-openbsd*) gdb_host=nbsd ;;
+diff --git a/gdb/sh-linux-nat.c b/gdb/sh-linux-nat.c
+new file mode 100644
+index 0000000..18e423d
+--- /dev/null
++++ b/gdb/sh-linux-nat.c
+@@ -0,0 +1,269 @@
++/* Low level SH interface to ptrace, for GDB when running native.
++ Copyright (C) 2002, 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 "target.h"
++#include "arch-utils.h"
++
++#include "gdb_assert.h"
++#include "gdb_string.h"
++#include <sys/ptrace.h>
++#include <sys/user.h>
++#include <sys/procfs.h>
++#include <asm/ptrace.h>
++
++/* Prototypes for supply_gregset etc. */
++#include "gregset.h"
++#include "sh-tdep.h"
++
++/* Defines ps_err_e, struct ps_prochandle. */
++#include "gdb_proc_service.h"
++
++//#include <asm/elf.h>
++
++#define SH_LINUX_NUM_REGS 40
++/* This table must line up with REGISTER_NAME in "sh-tdep.c". */
++static const int regmap[] =
++{
++ /* general registers 0-15 */
++ REG_REG0 , REG_REG0+1 , REG_REG0+2 , REG_REG0+3,
++ REG_REG0+4 , REG_REG0+5 , REG_REG0+6 , REG_REG0+7,
++ REG_REG0+8 , REG_REG0+9 , REG_REG0+10, REG_REG0+11,
++ REG_REG0+12, REG_REG0+13, REG_REG0+14, REG_REG0+15,
++ /* 16 - 22 */
++ REG_PC, REG_PR, REG_GBR, -1, REG_MACH, REG_MACL, REG_SR,
++ /* 23, 24 */
++ REG_FPUL, REG_FPSCR,
++ /* floating point registers 25 - 40 */
++ REG_FPREG0 , REG_FPREG0+1 , REG_FPREG0+2 , REG_FPREG0+3 ,
++ REG_FPREG0+4 , REG_FPREG0+5 , REG_FPREG0+6 , REG_FPREG0+7 ,
++ REG_FPREG0+8 , REG_FPREG0+9 , REG_FPREG0+10, REG_FPREG0+11,
++ REG_FPREG0+12, REG_FPREG0+13, REG_FPREG0+14, REG_FPREG0+15,
++};
++
++CORE_ADDR
++register_u_addr (CORE_ADDR blockend, int regnum)
++{
++ if (regnum < 0 || regnum >= sizeof regmap/sizeof regmap[0])
++ return (CORE_ADDR)-1;
++ return (blockend + 4 * regmap[regnum]);
++}
++
++
++/* Return the address in the core dump or inferior of register REGNO.
++ BLOCKEND is the address of the end of the user structure. */
++
++CORE_ADDR
++register_addr (int regno, CORE_ADDR blockend)
++{
++ CORE_ADDR addr;
++
++ if (regno < 0 || regno >= SH_LINUX_NUM_REGS) {
++ internal_error (__FILE__, __LINE__,
++ _("Got request for bad register number %d."), regno);
++ }
++
++ REGISTER_U_ADDR (addr, blockend, regno);
++
++ return addr;
++}
++
++/* Fetch one register. */
++
++static void
++fetch_register (struct regcache *regcache, int tid, int regno)
++{
++ int val;
++
++ if (cannot_fetch_register (regno))
++ {
++ regcache_raw_supply (regcache, regno, NULL);
++ return;
++ }
++
++ errno = 0;
++ val = ptrace (PTRACE_PEEKUSER, tid, register_addr (regno, 0), 0);
++ if (errno != 0)
++ perror_with_name (_("Couldn't get registers"));
++
++ regcache_raw_supply (regcache, regno, &val);
++}
++
++/* Store one register. */
++
++static void
++store_register (struct regcache *regcache, int tid, int regno)
++{
++ int val;
++
++ if (cannot_store_register (regno))
++ return;
++
++ errno = 0;
++ regcache_raw_collect (regcache, regno, &val);
++ ptrace (PTRACE_POKEUSER, tid, register_addr (regno, 0), val);
++ if (errno != 0)
++ perror_with_name (_("Couldn't write registers"));
++}
++
++/* 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 (struct regcache *regcache, const elf_gregset_t *gregsetp)
++{
++ elf_greg_t *regp = (elf_greg_t *) gregsetp;
++ int i;
++
++ for (i = 0; i < 23; i++)
++ if (regmap[i] == -1)
++ regcache_raw_supply (regcache, i, NULL);
++ else
++ regcache_raw_supply (regcache, i, (char *) (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 (const struct regcache *regcache, elf_gregset_t *gregsetp, int regno)
++{
++ elf_greg_t *regp = (elf_greg_t *) gregsetp;
++ int i;
++
++ for (i = 0; i < 23; i++)
++ if (regmap[i] != -1 && (regno == -1 || regno == i))
++ regcache_raw_collect (regcache, i, (char *) (regp + regmap[i]));
++}
++
++/* 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 (struct regcache *regcache, const elf_fpregset_t *fpregsetp)
++{
++ int i;
++ long *regp = (long *)fpregsetp;
++
++ for (i = 0; i < 16; i++)
++ regcache_raw_supply (regcache, 25 + i, (char *) (regp + i));
++ regcache_raw_supply (regcache, FPUL_REGNUM, (char *) (regp + REG_FPUL - REG_FPREG0));
++ regcache_raw_supply (regcache, FPSCR_REGNUM, (char *) (regp + REG_FPSCR - REG_FPREG0));
++}
++
++/* 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 (const struct regcache *regcache, elf_fpregset_t *fpregsetp, int regno)
++{
++ int i;
++ long *regp = (long *)fpregsetp;
++
++ for (i = 0; i < 16; i++)
++ if ((regno == -1) || (regno == i))
++ regcache_raw_collect (regcache, 25 + i, (char *) (regp + i));
++ if ((regno == -1) || regno == FPSCR_REGNUM)
++ regcache_raw_collect (regcache, FPSCR_REGNUM, (char *) (regp + REG_FPSCR - REG_FPREG0));
++ if ((regno == -1) || regno == FPUL_REGNUM)
++ regcache_raw_collect (regcache, FPUL_REGNUM, (char *) (regp + REG_FPUL - REG_FPREG0));
++}
++
++/* 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)
++{
++ return (regno < 0 || regno >= sizeof regmap / sizeof regmap[0] || regmap[regno] == -1);
++}
++
++int
++cannot_store_register (int regno)
++{
++ return (regno < 0 || regno >= sizeof regmap / sizeof regmap[0] || regmap[regno] == -1);
++}
++
++/* Fetch register values from the inferior.
++ If REGNO is negative, do this for all registers.
++ Otherwise, REGNO specifies which register (so we can save time). */
++
++static void
++sh_linux_fetch_inferior_registers (struct target_ops *ops, struct regcache *regcache, int regno)
++{
++ int i;
++ 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. */
++
++ for (i = 0; i < SH_LINUX_NUM_REGS; i++)
++ if (regno == -1 || regno == i)
++ fetch_register (regcache, tid, i);
++}
++/* Store our register values back into the inferior.
++ If REGNO is negative, do this for all registers.
++ Otherwise, REGNO specifies which register (so we can save time). */
++
++static void
++sh_linux_store_inferior_registers (struct target_ops *ops, struct regcache *regcache, int regno)
++{
++ int i;
++ 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. */
++
++ for (i = 0; i < SH_LINUX_NUM_REGS; i++)
++ if (regno == -1 || regno == i)
++ store_register (regcache, tid, i);
++}
++
++void
++_initialize_sh_linux_nat (void)
++{
++ struct target_ops *t;
++
++ /* Fill in the generic GNU/Linux methods. */
++ t = linux_target ();
++
++ /* Add our register access methods. */
++ t->to_fetch_registers = sh_linux_fetch_inferior_registers;
++ t->to_store_registers = sh_linux_store_inferior_registers;
++
++ /* Register the target. */
++ linux_nat_add_target (t);
++}
+diff --git a/gdb/sh-linux-tdep.c b/gdb/sh-linux-tdep.c
+index da4137b..be95bc9 100644
+--- a/gdb/sh-linux-tdep.c
++++ b/gdb/sh-linux-tdep.c
+@@ -18,11 +18,34 @@
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+ #include "defs.h"
++#include "gdbcore.h"
++#include "frame.h"
++#include "frame-base.h"
++#include "frame-unwind.h"
++#include "dwarf2-frame.h"
++#include "value.h"
++#include "regcache.h"
++#include "inferior.h"
+ #include "osabi.h"
+
++#include "reggroups.h"
++#include "arch-utils.h"
++#include "floatformat.h"
+ #include "solib-svr4.h"
+ #include "symtab.h"
++#include "gdb_string.h"
++#include "command.h"
++#include "gdb_assert.h"
+
++#include <sys/ptrace.h>
++#include <sys/types.h>
++#include <sys/param.h>
++#include <sys/user.h>
++#include <sys/syscall.h>
++
++#include <asm/ptrace.h>
++
++#include "regset.h"
+ #include "glibc-tdep.h"
+ #include "sh-tdep.h"
+
+@@ -69,9 +92,505 @@ static const struct sh_corefile_regmap fpregs_table[] =
+ {-1 /* Terminator. */, 0}
+ };
+
++/* 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 SH 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
++ mov.w 1f,r3
++ trapa #16
++ or r0, r0
++ or r0, r0
++ or r0, r0
++ or r0, r0
++ or r0, r0
++ 1: .word __NR_sigreturn
++ or 0x9305 0xc310 0x200b 0x200b 0x200b 0x200b 0x200b 0x0077.
++
++ 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 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. The PC_IN_SIGTRAMP macro in tm-linux.h arranges to
++ only call us 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. */
++
++#define MOVW(n) (0x9300|((n)-2)) /* Move mem word at PC+n to R3 */
++#define TRAP16 0xc310 /* Syscall w/no args (NR in R3) */
++#define OR_R0_R0 0x200b /* or r0,r0 (insert to avoid hardware bug) */
++
++#define LINUX_SIGTRAMP_INSN0 MOVW(7) /* Move mem word at PC+7 to R3 */
++#define LINUX_SIGTRAMP_INSN1 TRAP16 /* Syscall w/no args (NR in R3) */
++#define LINUX_SIGTRAMP_INSN2 OR_R0_R0 /* or r0,r0 (insert to avoid hardware bug) */
++
++static const unsigned short linux_sigtramp_code[] =
++{
++ LINUX_SIGTRAMP_INSN0,
++ LINUX_SIGTRAMP_INSN1,
++ LINUX_SIGTRAMP_INSN2,
++ LINUX_SIGTRAMP_INSN2,
++ LINUX_SIGTRAMP_INSN2,
++ LINUX_SIGTRAMP_INSN2,
++ LINUX_SIGTRAMP_INSN2,
++ __NR_sigreturn
++};
++
++#define LINUX_SIGTRAMP_LEN (sizeof linux_sigtramp_code)
++
++/* If PC is in a sigtramp routine, return the address of the start of
++ the routine. Otherwise, return 0. */
++
++static CORE_ADDR
++sh_linux_sigtramp_start (struct frame_info *next_frame)
++{
++ CORE_ADDR pc = get_frame_pc (next_frame);
++ gdb_byte buf[LINUX_SIGTRAMP_LEN];
++
++ /* We only recognize a signal trampoline if PC is at the start of
++ one of the three instructions. We optimize for finding the PC at
++ the start, 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 (!safe_frame_unwind_memory (next_frame, pc, buf, LINUX_SIGTRAMP_LEN))
++ return 0;
++
++ if (buf[0] != LINUX_SIGTRAMP_INSN0)
++ {
++ if (buf[0] != LINUX_SIGTRAMP_INSN1)
++ return 0;
++
++ pc -= 2;
++
++ if (!safe_frame_unwind_memory (next_frame, pc, buf, LINUX_SIGTRAMP_LEN))
++ return 0;
++ }
++
++ if (memcmp (buf, linux_sigtramp_code, LINUX_SIGTRAMP_LEN) != 0)
++ return 0;
++
++ return pc;
++}
++
++/* This function does the same for RT signals. Here the instruction
++ sequence is
++ mov.w 1f,r3
++ trapa #16
++ or r0, r0
++ or r0, r0
++ or r0, r0
++ or r0, r0
++ or r0, r0
++ 1: .word __NR_rt_sigreturn
++ or 0x9305 0xc310 0x200b 0x200b 0x200b 0x200b 0x200b 0x00ad.
++
++ The effect is to call the system call rt_sigreturn. */
++
++#define LINUX_RT_SIGTRAMP_INSN0 MOVW(7) /* Move mem word at PC+7 to R3 */
++#define LINUX_RT_SIGTRAMP_INSN1 TRAP16 /* Syscall w/no args (NR in R3) */
++#define LINUX_RT_SIGTRAMP_INSN2 OR_R0_R0 /* or r0,r0 (insert to avoid hardware bug) */
++
++static const unsigned short linux_rt_sigtramp_code[] =
++{
++ LINUX_RT_SIGTRAMP_INSN0,
++ LINUX_RT_SIGTRAMP_INSN1,
++ LINUX_RT_SIGTRAMP_INSN2,
++ LINUX_RT_SIGTRAMP_INSN2,
++ LINUX_RT_SIGTRAMP_INSN2,
++ LINUX_RT_SIGTRAMP_INSN2,
++ LINUX_RT_SIGTRAMP_INSN2,
++ __NR_rt_sigreturn
++};
++
++#define LINUX_RT_SIGTRAMP_LEN (sizeof linux_rt_sigtramp_code)
++
++/* If PC is in a RT sigtramp routine, return the address of the start
++ of the routine. Otherwise, return 0. */
++
++static CORE_ADDR
++sh_linux_rt_sigtramp_start (struct frame_info *next_frame)
++{
++ CORE_ADDR pc = get_frame_pc (next_frame);
++ gdb_byte buf[LINUX_RT_SIGTRAMP_LEN];
++
++ /* We only recognize a signal trampoline if PC is at the start of
++ one of the two instructions. We optimize for finding the PC at
++ the start, 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 (!safe_frame_unwind_memory (next_frame, pc, buf, LINUX_RT_SIGTRAMP_LEN))
++ return 0;
++
++ if (buf[0] != LINUX_RT_SIGTRAMP_INSN0)
++ {
++ if (buf[0] != LINUX_RT_SIGTRAMP_INSN1)
++ return 0;
++
++ pc -= 2;
++
++ if (!safe_frame_unwind_memory (next_frame, pc, buf,
++ LINUX_RT_SIGTRAMP_LEN))
++ return 0;
++ }
++
++ if (memcmp (buf, linux_rt_sigtramp_code, LINUX_RT_SIGTRAMP_LEN) != 0)
++ return 0;
++
++ return pc;
++}
++
++/* Return whether PC is in a GNU/Linux sigtramp routine. */
++
++static int
++sh_linux_sigtramp_p (struct frame_info *this_frame)
++{
++ CORE_ADDR pc = get_frame_pc (this_frame);
++ char *name;
++
++ find_pc_partial_function (pc, &name, NULL, NULL);
++
++ /* 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 (sh_linux_sigtramp_start (this_frame) != 0
++ || sh_linux_rt_sigtramp_start (this_frame) != 0);
++
++ return (strcmp ("__restore", name) == 0
++ || strcmp ("__restore_rt", name) == 0);
++}
++
++/* Offset to struct sigcontext in ucontext, from <asm/ucontext.h>. */
++#define SH_LINUX_UCONTEXT_SIGCONTEXT_OFFSET 12
++
++
++/* Assuming NEXT_FRAME is a frame following a GNU/Linux sigtramp
++ routine, return the address of the associated sigcontext structure. */
++
++static CORE_ADDR
++sh_linux_sigcontext_addr (struct frame_info *this_frame)
++{
++ CORE_ADDR pc;
++ CORE_ADDR sp;
++
++ sp = get_frame_register_unsigned (this_frame, SP_REGNUM);
++
++ pc = sh_linux_sigtramp_start (this_frame);
++ if (pc)
++ {
++ return sp;
++ }
++
++ pc = sh_linux_rt_sigtramp_start (this_frame);
++ if (pc)
++ {
++ CORE_ADDR ucontext_addr;
++
++ /* The sigcontext structure is part of the user context. A
++ pointer to the user context is passed as the third argument
++ to the signal handler. */
++ ucontext_addr = get_frame_register_unsigned (this_frame, ARG0_REGNUM+2);
++ return ucontext_addr + SH_LINUX_UCONTEXT_SIGCONTEXT_OFFSET;
++ }
++
++ error ("Couldn't recognize signal trampoline.");
++ return 0;
++}
++
++/* Signal trampolines. */
++extern struct sh_frame_cache *sh_alloc_frame_cache (void);
++
++static struct sh_frame_cache *
++sh_linux_sigtramp_frame_cache (struct frame_info *this_frame, void **this_cache)
++{
++ struct sh_frame_cache *cache;
++ struct gdbarch_tdep *tdep = gdbarch_tdep (get_current_arch ());
++ CORE_ADDR sigcontext_addr;
++
++ if (*this_cache)
++ return *this_cache;
++
++ cache = sh_alloc_frame_cache ();
++
++ cache->base = get_frame_register_unsigned (this_frame, SP_REGNUM);
++ sigcontext_addr = tdep->sigcontext_addr (this_frame);
++ if (tdep->sc_reg_offset)
++ {
++ int i;
++
++ gdb_assert (tdep->sc_num_regs <= SH_NUM_REGS);
++
++ for (i = 0; i < tdep->sc_num_regs; i++)
++ if (tdep->sc_reg_offset[i] != -1)
++ cache->saved_regs[i] = sigcontext_addr + tdep->sc_reg_offset[i];
++ }
++
++ *this_cache = cache;
++ return cache;
++}
++
++static void
++sh_linux_sigtramp_frame_this_id (struct frame_info *this_frame, void **this_cache,
++ struct frame_id *this_id)
++{
++ struct sh_frame_cache *cache =
++ sh_linux_sigtramp_frame_cache (this_frame, this_cache);
++
++ (*this_id) = frame_id_build (cache->base + 64, cache->pc);
++}
++
++extern struct value * sh_frame_prev_register ();
++static struct value *
++sh_linux_sigtramp_frame_prev_register (struct frame_info *this_frame,
++ void **this_cache, int regnum)
++{
++ sh_linux_sigtramp_frame_cache (this_frame, this_cache);
++
++ return sh_frame_prev_register (this_frame, this_cache, regnum);
++}
++
++static int
++sh_linux_sigtramp_frame_sniffer (const struct frame_unwind *self,
++ struct frame_info *this_frame,
++ void **this_prologue_cache)
++{
++ struct gdbarch_tdep *tdep = gdbarch_tdep (get_frame_arch (this_frame));
++
++ /* We shouldn't even bother if we don't have a sigcontext_addr
++ handler. */
++ if (tdep->sigcontext_addr == NULL)
++ return 0;
++
++ if (tdep->sigtramp_p != NULL)
++ {
++ if (tdep->sigtramp_p (this_frame))
++ return 1;
++ }
++
++ return 0;
++}
++
++static const struct frame_unwind sh_linux_sigtramp_frame_unwind =
++{
++ SIGTRAMP_FRAME,
++ sh_linux_sigtramp_frame_this_id,
++ sh_linux_sigtramp_frame_prev_register,
++ NULL,
++ sh_linux_sigtramp_frame_sniffer
++};
++
++/* Supply register REGNUM from the buffer specified by GREGS and LEN
++ in the general-purpose register set REGSET to register cache
++ REGCACHE. If REGNUM is -1, do this for all registers in REGSET. */
++
++void
++sh_supply_gregset (const struct regset *regset, struct regcache *regcache,
++ int regnum, const void *gregs, size_t len)
++{
++ const struct gdbarch_tdep *tdep = gdbarch_tdep (regset->arch);
++ const char *regs = gregs;
++ int i;
++
++ gdb_assert (len == tdep->sizeof_gregset);
++
++ for (i = 0; i < tdep->gregset_num_regs; i++)
++ {
++ if ((regnum == i || regnum == -1)
++ && tdep->gregset_reg_offset[i] != -1)
++ regcache_raw_supply (regcache, i, regs + tdep->gregset_reg_offset[i]);
++ }
++}
++
++/* Collect register REGNUM from the register cache REGCACHE and store
++ it in the buffer specified by GREGS and LEN as described by the
++ general-purpose register set REGSET. If REGNUM is -1, do this for
++ all registers in REGSET. */
++
++void
++sh_collect_gregset (const struct regset *regset,
++ const struct regcache *regcache,
++ int regnum, void *gregs, size_t len)
++{
++ const struct gdbarch_tdep *tdep = gdbarch_tdep (regset->arch);
++ char *regs = gregs;
++ int i;
++
++ gdb_assert (len == tdep->sizeof_gregset);
++
++ for (i = 0; i < tdep->gregset_num_regs; i++)
++ {
++ if ((regnum == i || regnum == -1)
++ && tdep->gregset_reg_offset[i] != -1)
++ regcache_raw_collect (regcache, i, regs + tdep->gregset_reg_offset[i]);
++ }
++}
++
++/* Supply register REGNUM from the buffer specified by FPREGS and LEN
++ in the floating-point register set REGSET to register cache
++ REGCACHE. If REGNUM is -1, do this for all registers in REGSET. */
++
++static void
++sh_supply_fpregset (const struct regset *regset, struct regcache *regcache,
++ int regnum, const void *fpregs, size_t len)
++{
++ const struct gdbarch_tdep *tdep = gdbarch_tdep (regset->arch);
++ const char *regs = fpregs;
++ int i;
++
++ gdb_assert (len == tdep->sizeof_fpregset);
++ for (i = 0; i < 16; i++)
++ {
++ if (regnum == i+25 || regnum == -1)
++ regcache_raw_supply (regcache, i+25, regs + i*4);
++ }
++ if (regnum == FPSCR_REGNUM || regnum == -1)
++ regcache_raw_supply (regcache, FPSCR_REGNUM, regs + 32*4);
++ if (regnum == FPUL_REGNUM || regnum == -1)
++ regcache_raw_supply (regcache, FPUL_REGNUM, regs + 33*4);
++}
++
++/* Collect register REGNUM from the register cache REGCACHE and store
++ it in the buffer specified by FPREGS and LEN as described by the
++ floating-point register set REGSET. If REGNUM is -1, do this for
++ all registers in REGSET. */
++
++static void
++sh_collect_fpregset (const struct regset *regset,
++ const struct regcache *regcache,
++ int regnum, void *fpregs, size_t len)
++{
++ const struct gdbarch_tdep *tdep = gdbarch_tdep (regset->arch);
++ char *regs = fpregs;
++ int i;
++
++ gdb_assert (len == tdep->sizeof_fpregset);
++ for (i = 0; i < 16; i++)
++ {
++ if (regnum == i+25 || regnum == -1)
++ regcache_raw_collect (regcache, i+25, regs + i*4);
++ }
++ if (regnum == FPSCR_REGNUM || regnum == -1)
++ regcache_raw_collect (regcache, FPSCR_REGNUM, regs + 32*4);
++ if (regnum == FPUL_REGNUM || regnum == -1)
++ regcache_raw_collect (regcache, FPUL_REGNUM, regs + 33*4);
++}
++
++/* Return the appropriate register set for the core section identified
++ by SECT_NAME and SECT_SIZE. */
++
++const struct regset *
++sh_linux_regset_from_core_section (struct gdbarch *gdbarch,
++ const char *sect_name, size_t sect_size)
++{
++ struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
++
++ if (strcmp (sect_name, ".reg") == 0 && sect_size == tdep->sizeof_gregset)
++ {
++ if (tdep->gregset == NULL)
++ tdep->gregset = regset_alloc (gdbarch, sh_supply_gregset,
++ sh_collect_gregset);
++ return tdep->gregset;
++ }
++
++ if ((strcmp (sect_name, ".reg2") == 0 && sect_size == tdep->sizeof_fpregset))
++ {
++ if (tdep->fpregset == NULL)
++ tdep->fpregset = regset_alloc (gdbarch, sh_supply_fpregset,
++ sh_collect_fpregset);
++ return tdep->fpregset;
++ }
++
++ return NULL;
++}
++
++/* The register sets used in GNU/Linux ELF core-dumps are identical to
++ the register sets in `struct user' that are used for a.out
++ core-dumps. These are also used by ptrace(2). 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 GDB used those names in the past. But those
++ names are now used for the register sets used in the `mcontext_t'
++ type, which have a different size and layout. */
++
++/* Mapping between the general-purpose registers in `struct user'
++ format and GDB's register cache layout. */
++
++/* From <sys/reg.h>. */
++static int sh_linux_gregset_reg_offset[] =
++{
++ 0, 4, 8, 12, 16, 20, 24, 28,
++ 32, 36, 40, 44, 48, 52, 56, 60,
++
++ REG_PC*4, REG_PR*4, REG_GBR*4, -1,
++ REG_MACH*4, REG_MACL*4, REG_SR*4,
++};
++
++/* Mapping between the general-purpose registers in `struct
++ sigcontext' format and GDB's register cache layout. */
++
++/* From <asm/sigcontext.h>. */
++static int sh_linux_sc_reg_offset[] =
++{
++ 4, 8, 12, 16, 20, 24, 28, 32,
++ 36, 40, 44, 48, 52, 56, 60, 64,
++ 68, 72, 80, -1,
++ 84, 88, 76
++};
++
+ static void
+ sh_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
+ {
++ struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
++ bfd abfd;
++
++ tdep->gregset_reg_offset = sh_linux_gregset_reg_offset;
++ tdep->gregset_num_regs = ARRAY_SIZE (sh_linux_gregset_reg_offset);
++ tdep->sizeof_gregset = 23 * 4;
++
++ tdep->jb_pc_offset = 32; /* From <bits/setjmp.h>. */
++
++ tdep->sigtramp_p = sh_linux_sigtramp_p;
++ tdep->sigcontext_addr = sh_linux_sigcontext_addr;
++ tdep->sc_reg_offset = sh_linux_sc_reg_offset;
++ tdep->sc_num_regs = ARRAY_SIZE (sh_linux_sc_reg_offset);
++
++ frame_unwind_append_unwinder(gdbarch, &sh_linux_sigtramp_frame_unwind);
++
++ /* If we have a register mapping, enable the generic core file
++ support, unless it has already been enabled. */
++ if (tdep->gregset_reg_offset
++ && !gdbarch_regset_from_core_section_p (gdbarch))
++ set_gdbarch_regset_from_core_section (gdbarch,
++ sh_linux_regset_from_core_section);
++
+ /* GNU/Linux uses SVR4-style shared libraries. */
+ set_gdbarch_skip_trampoline_code (gdbarch, find_solib_trampoline_target);
+ set_solib_svr4_fetch_link_map_offsets
+diff --git a/gdb/sh-tdep.c b/gdb/sh-tdep.c
+index 7e01469..735cc84 100644
+--- a/gdb/sh-tdep.c
++++ b/gdb/sh-tdep.c
+@@ -24,6 +24,9 @@
+ */
+
+ #include "defs.h"
++#include "arch-utils.h"
++#include "command.h"
++#include "dummy-frame.h"
+ #include "frame.h"
+ #include "frame-base.h"
+ #include "frame-unwind.h"
+@@ -40,6 +43,7 @@
+ #include "arch-utils.h"
+ #include "floatformat.h"
+ #include "regcache.h"
++#include "regset.h"
+ #include "doublest.h"
+ #include "osabi.h"
+ #include "reggroups.h"
+@@ -72,23 +76,6 @@ static const char *sh_active_calling_convention = sh_cc_gcc;
+
+ static void (*sh_show_regs) (struct frame_info *);
+
+-#define SH_NUM_REGS 67
+-
+-struct sh_frame_cache
+-{
+- /* Base address. */
+- CORE_ADDR base;
+- LONGEST sp_offset;
+- CORE_ADDR pc;
+-
+- /* Flag showing that a frame has been created in the prologue code. */
+- int uses_fp;
+-
+- /* Saved registers. */
+- CORE_ADDR saved_regs[SH_NUM_REGS];
+- CORE_ADDR saved_sp;
+-};
+-
+ static int
+ sh_is_renesas_calling_convention (struct type *func_type)
+ {
+@@ -1045,7 +1032,7 @@ sh_treat_as_flt_p (struct type *type)
+ return 0;
+ /* Otherwise if the type of that member is float, the whole type is
+ treated as float. */
+- if (TYPE_CODE (TYPE_FIELD_TYPE (type, 0)) == TYPE_CODE_FLT)
++ if (TYPE_CODE (check_typedef (TYPE_FIELD_TYPE (type, 0))) == TYPE_CODE_FLT)
+ return 1;
+ /* Otherwise it's not treated as float. */
+ return 0;
+@@ -1095,7 +1082,7 @@ sh_push_dummy_call_fpu (struct gdbarch *gdbarch,
+ in four registers available. Loop thru args from first to last. */
+ for (argnum = 0; argnum < nargs; argnum++)
+ {
+- type = value_type (args[argnum]);
++ type = check_typedef (value_type (args[argnum]));
+ len = TYPE_LENGTH (type);
+ val = sh_justify_value_in_reg (gdbarch, args[argnum], len);
+
+@@ -2485,7 +2472,7 @@ sh_dwarf2_frame_init_reg (struct gdbarch *gdbarch, int regnum,
+ reg->how = DWARF2_FRAME_REG_UNDEFINED;
+ }
+
+-static struct sh_frame_cache *
++struct sh_frame_cache *
+ sh_alloc_frame_cache (void)
+ {
+ struct sh_frame_cache *cache;
+@@ -2512,7 +2499,7 @@ sh_alloc_frame_cache (void)
+ return cache;
+ }
+
+-static struct sh_frame_cache *
++struct sh_frame_cache *
+ sh_frame_cache (struct frame_info *this_frame, void **this_cache)
+ {
+ struct gdbarch *gdbarch = get_frame_arch (this_frame);
+@@ -2570,9 +2557,9 @@ sh_frame_cache (struct frame_info *this_frame, void **this_cache)
+ return cache;
+ }
+
+-static struct value *
+-sh_frame_prev_register (struct frame_info *this_frame,
+- void **this_cache, int regnum)
++struct value *
++sh_frame_prev_register (struct frame_info *this_frame, void **this_cache,
++ int regnum)
+ {
+ struct gdbarch *gdbarch = get_frame_arch (this_frame);
+ struct sh_frame_cache *cache = sh_frame_cache (this_frame, this_cache);
+@@ -2586,7 +2573,7 @@ sh_frame_prev_register (struct frame_info *this_frame,
+ the current frame. Frob regnum so that we pull the value from
+ the correct place. */
+ if (regnum == gdbarch_pc_regnum (gdbarch))
+- regnum = PR_REGNUM;
++ regnum = PR_REGNUM; /* XXX: really? */
+
+ if (regnum < SH_NUM_REGS && cache->saved_regs[regnum] != -1)
+ return frame_unwind_got_memory (this_frame, regnum,
+@@ -2829,8 +2816,8 @@ sh_regset_from_core_section (struct gdbarch *gdbarch, const char *sect_name,
+ static struct gdbarch *
+ sh_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
+ {
+- struct gdbarch *gdbarch;
+ struct gdbarch_tdep *tdep;
++ struct gdbarch *gdbarch;
+
+ sh_show_regs = sh_generic_show_regs;
+ switch (info.bfd_arch_info->mach)
+@@ -2893,6 +2880,18 @@ sh_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
+ tdep = XZALLOC (struct gdbarch_tdep);
+ gdbarch = gdbarch_alloc (&info, tdep);
+
++ /* General-purpose registers. */
++ tdep->gregset = NULL;
++ tdep->gregset_reg_offset = NULL;
++ tdep->gregset_num_regs = 23;
++ tdep->sizeof_gregset = 0;
++
++ /* Floating-point registers. */
++ tdep->fpregset = NULL;
++ tdep->sizeof_fpregset = 34*4;
++
++ tdep->jb_pc_offset = -1;
++
+ set_gdbarch_short_bit (gdbarch, 2 * TARGET_CHAR_BIT);
+ set_gdbarch_int_bit (gdbarch, 4 * TARGET_CHAR_BIT);
+ set_gdbarch_long_bit (gdbarch, 4 * TARGET_CHAR_BIT);
+@@ -3038,10 +3037,11 @@ sh_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
+ break;
+ }
+
++ dwarf2_append_unwinders (gdbarch);
++
+ /* Hook in ABI-specific overrides, if they have been registered. */
+ gdbarch_init_osabi (info, gdbarch);
+
+- dwarf2_append_unwinders (gdbarch);
+ frame_unwind_append_unwinder (gdbarch, &sh_frame_unwind);
+
+ return gdbarch;
+diff --git a/gdb/sh-tdep.h b/gdb/sh-tdep.h
+index b53d412..f2bea7d 100644
+--- a/gdb/sh-tdep.h
++++ b/gdb/sh-tdep.h
+@@ -22,6 +22,12 @@
+
+ /* Contributed by Steve Chamberlain sac@cygnus.com */
+
++struct frame_info;
++struct gdbarch;
++struct reggroup;
++struct regset;
++struct regcache;
++
+ /* Registers for all SH variants. Used also by sh3-rom.c. */
+ enum
+ {
+@@ -30,6 +36,7 @@ enum
+ ARG0_REGNUM = 4,
+ ARGLAST_REGNUM = 7,
+ FP_REGNUM = 14,
++ SP_REGNUM = 15,
+ PC_REGNUM = 16,
+ PR_REGNUM = 17,
+ GBR_REGNUM = 18,
+@@ -83,8 +90,26 @@ enum
+ FV_LAST_REGNUM = 79
+ };
+
++#define SH_NUM_REGS 67
++
++struct sh_frame_cache
++{
++ /* Base address. */
++ CORE_ADDR base;
++ LONGEST sp_offset;
++ CORE_ADDR pc;
++
++ /* Flag showing that a frame has been created in the prologue code. */
++ int uses_fp;
++
++ /* Saved registers. */
++ CORE_ADDR saved_regs[SH_NUM_REGS];
++ CORE_ADDR saved_sp;
++};
++
+ extern gdbarch_init_ftype sh64_gdbarch_init;
+ extern void sh64_show_regs (struct frame_info *);
++extern struct sh_frame_cache *sh_frame_cache (struct frame_info *next_frame, void **this_cache);
+
+ /* This structure describes a register in a core-file. */
+ struct sh_corefile_regmap
+@@ -93,8 +118,32 @@ struct sh_corefile_regmap
+ unsigned int offset;
+ };
+
++/* sh architecture specific information. */
+ struct gdbarch_tdep
+ {
++ /* General-purpose registers. */
++ struct regset *gregset;
++ int *gregset_reg_offset;
++ int gregset_num_regs;
++ size_t sizeof_gregset;
++
++ /* Floating-point registers. */
++ struct regset *fpregset;
++ size_t sizeof_fpregset;
++
++ /* Offset of saved PC in jmp_buf. */
++ int jb_pc_offset;
++
++ /* Detect sigtramp. */
++ int (*sigtramp_p) (struct frame_info *);
++
++ /* Get address of sigcontext for sigtramp. */
++ CORE_ADDR (*sigcontext_addr) (struct frame_info *);
++
++ /* Offset of registers in `struct sigcontext'. */
++ int *sc_reg_offset;
++ int sc_num_regs;
++
+ /* Non-NULL when debugging from a core file. Provides the offset
+ where each general-purpose register is stored inside the associated
+ core file section. */
+diff --git a/gdb/testsuite/gdb.asm/asm-source.exp b/gdb/testsuite/gdb.asm/asm-source.exp
+index 615182f..dd5ae09 100644
+--- a/gdb/testsuite/gdb.asm/asm-source.exp
++++ b/gdb/testsuite/gdb.asm/asm-source.exp
+@@ -105,6 +105,11 @@ switch -glob -- [istarget] {
+ "powerpc*-*" {
+ set asm-arch powerpc
+ }
++ "sh*-linux*" {
++ set asm-arch sh-linux
++ set asm-flags "-I${srcdir}/${subdir} -I${objdir}/${subdir}"
++ set debug-flags "-gdwarf-2"
++ }
+ "sh*-*-*" {
+ set asm-arch sh
+ set debug-flags "-gdwarf-2"
+diff --git a/gdb/testsuite/gdb.asm/sh-linux.inc b/gdb/testsuite/gdb.asm/sh-linux.inc
+new file mode 100644
+index 0000000..4a0f669
+--- /dev/null
++++ b/gdb/testsuite/gdb.asm/sh-linux.inc
+@@ -0,0 +1,78 @@
++# You'll find a bunch of nop opcodes in the below macros. They are
++# there to keep the code correctly aligned. Be careful to maintain
++# them when changing the code.
++
++ comment "subroutine declare"
++ .purgem gdbasm_declare
++ .macro gdbasm_declare name
++ .align 1
++ .global \name
++\name:
++ .endm
++
++ comment "subroutine prologue"
++ .macro gdbasm_enter
++ mov.l r14,@-r15
++ sts.l pr,@-r15
++ mov r15,r14
++ nop
++ .endm
++
++ comment "subroutine epilogue"
++ .macro gdbasm_leave
++ mov r14,r15
++ lds.l @r15+,pr
++ mov.l @r15+,r14
++ rts
++ nop
++ nop
++ .endm
++
++ comment "subroutine end"
++ .purgem gdbasm_end
++ .macro gdbasm_end name
++ .size \name, .-_foo1
++ .align 1
++ .endm
++
++ comment "subroutine call"
++ .macro gdbasm_call subr
++ mov.l .Lconst\@,r1
++ bra .Lafterconst\@
++ nop
++ .align 2
++.Lconst\@:
++ .long \subr
++.Lafterconst\@:
++ jsr @r1
++ nop
++ .endm
++
++ .macro gdbasm_several_nops
++ nop
++ nop
++ nop
++ nop
++ .endm
++
++ comment "exit (0)"
++ .macro gdbasm_exit0
++ sleep
++ nop
++ .endm
++
++ comment "crt0 startup"
++ .macro gdbasm_startup
++ mov #0,r14
++ .endm
++
++ comment "Declare a data variable"
++ .purgem gdbasm_datavar
++ .macro gdbasm_datavar name value
++ .data
++ .align 2
++ .type \name, @object
++ .size \name, 4
++\name:
++ .long \value
++ .endm
+diff --git a/gdb/testsuite/gdb.asm/sh.inc b/gdb/testsuite/gdb.asm/sh.inc
+index 9ea1b67..c1f189d 100644
+--- a/gdb/testsuite/gdb.asm/sh.inc
++++ b/gdb/testsuite/gdb.asm/sh.inc
+@@ -40,9 +40,8 @@
+ mov.l .Lconst\@,r1
+ bra .Lafterconst\@
+ nop
+- nop
+-.Lconst\@:
+ .align 2
++.Lconst\@:
+ .long \subr
+ .align 1
+ .Lafterconst\@:
+diff --git a/gdb/testsuite/gdb.base/annota1.c b/gdb/testsuite/gdb.base/annota1.c
+index 6a13ee9..fb8aa53 100644
+--- a/gdb/testsuite/gdb.base/annota1.c
++++ b/gdb/testsuite/gdb.base/annota1.c
+@@ -1,9 +1,9 @@
+ #include <stdio.h>
+ #include <signal.h>
+
+-#ifdef __sh__
+-#define signal(a,b) /* Signals not supported on this target - make them go away */
+-#endif
++
++
++
+
+
+ #ifdef PROTOTYPES
+diff --git a/gdb/testsuite/gdb.base/annota3.c b/gdb/testsuite/gdb.base/annota3.c
+index 6a13ee9..fb8aa53 100644
+--- a/gdb/testsuite/gdb.base/annota3.c
++++ b/gdb/testsuite/gdb.base/annota3.c
+@@ -1,9 +1,9 @@
+ #include <stdio.h>
+ #include <signal.h>
+
+-#ifdef __sh__
+-#define signal(a,b) /* Signals not supported on this target - make them go away */
+-#endif
++
++
++
+
+
+ #ifdef PROTOTYPES
+diff --git a/gdb/testsuite/gdb.base/sigall.c b/gdb/testsuite/gdb.base/sigall.c
+index 28ae192..a8ff690 100644
+--- a/gdb/testsuite/gdb.base/sigall.c
++++ b/gdb/testsuite/gdb.base/sigall.c
+@@ -1,9 +1,9 @@
+ #include <signal.h>
+ #include <unistd.h>
+
+-#ifdef __sh__
+-#define signal(a,b) /* Signals not supported on this target - make them go away */
+-#endif
++
++
++
+
+ /* Signal handlers, we set breakpoints in them to make sure that the
+ signals really get delivered. */
+diff --git a/gdb/testsuite/gdb.base/signals.c b/gdb/testsuite/gdb.base/signals.c
+index f1ebcfc..cef4793 100644
+--- a/gdb/testsuite/gdb.base/signals.c
++++ b/gdb/testsuite/gdb.base/signals.c
+@@ -3,10 +3,10 @@
+ #include <signal.h>
+ #include <unistd.h>
+
+-#ifdef __sh__
+-#define signal(a,b) /* Signals not supported on this target - make them go away */
+-#define alarm(a) /* Ditto for alarm() */
+-#endif
++
++
++
++
+
+ static int count = 0;
+
+--
+1.7.0.3
+
diff --git a/recipes/gdb/gdb_7.2a.bb b/recipes/gdb/gdb_7.2a.bb
new file mode 100644
index 0000000000..9631ec9cbb
--- /dev/null
+++ b/recipes/gdb/gdb_7.2a.bb
@@ -0,0 +1,21 @@
+require gdb.inc
+LICENSE = "GPLv3"
+
+PR = "${INC_PR}.0"
+# there is a bug in GCC for SH4 it ICE's at Optlevel >O1
+# so workaround that for now.
+
+CFLAGS_append_sh4 = " -O1"
+SRC_URI += "file://gdb-6.8-fix-compile-karmic.patch \
+ file://gdb-tcsetpgrp.patch \
+ file://gdb-fix-sim-ppc.patch \
+ file://renesas-sh-native-support.patch \
+ "
+S = ${WORKDIR}/${PN}-7.2
+
+# Work-around problems while creating libbfd.a
+EXTRA_OECONF += "--enable-static"
+
+SRC_URI[md5sum] = "a9a8d0ea1ae57837fada5415bd0f92ff"
+SRC_URI[sha256sum] = "9f51739cd45c158aa5df2e7abb703a304b5370e2e9e43c70f5cc0b1c4be5d0c2"
+
diff --git a/recipes/gdb/gdbserver_7.2a.bb b/recipes/gdb/gdbserver_7.2a.bb
new file mode 100644
index 0000000000..d4365de724
--- /dev/null
+++ b/recipes/gdb/gdbserver_7.2a.bb
@@ -0,0 +1,11 @@
+require gdbserver.inc
+
+LICENSE = "GPLv3"
+
+PR = "${INC_PR}.0"
+
+S = ${WORKDIR}/gdb-7.2
+
+SRC_URI[md5sum] = "a9a8d0ea1ae57837fada5415bd0f92ff"
+SRC_URI[sha256sum] = "9f51739cd45c158aa5df2e7abb703a304b5370e2e9e43c70f5cc0b1c4be5d0c2"
+