From 15a9a957541702815fde60bcf382316cbc5e4e6e Mon Sep 17 00:00:00 2001 From: Florian Boor Date: Tue, 13 Dec 2011 10:47:27 +0100 Subject: gdbserver: Add 7.2a since 7.2 disappeared from the GNU mirrors Signed-off-by: Florian Boor --- .../gdb/gdb-7.2a/gdb-6.8-fix-compile-karmic.patch | 22 + recipes/gdb/gdb-7.2a/gdb-6.8-mingw-3.patch | 374 ++++++ .../gdb-6.8-pr9638-ppc-canadian-configh.patch | 179 +++ recipes/gdb/gdb-7.2a/gdb-tcsetpgrp.patch | 43 + recipes/gdb/gdb-7.2a/gdbserver-cflags-last.diff | 15 + .../gdb/gdb-7.2a/renesas-sh-native-support.patch | 1410 ++++++++++++++++++++ recipes/gdb/gdb_7.2a.bb | 21 + recipes/gdb/gdbserver_7.2a.bb | 11 + 8 files changed, 2075 insertions(+) create mode 100644 recipes/gdb/gdb-7.2a/gdb-6.8-fix-compile-karmic.patch create mode 100644 recipes/gdb/gdb-7.2a/gdb-6.8-mingw-3.patch create mode 100644 recipes/gdb/gdb-7.2a/gdb-6.8-pr9638-ppc-canadian-configh.patch create mode 100644 recipes/gdb/gdb-7.2a/gdb-tcsetpgrp.patch create mode 100644 recipes/gdb/gdb-7.2a/gdbserver-cflags-last.diff create mode 100644 recipes/gdb/gdb-7.2a/renesas-sh-native-support.patch create mode 100644 recipes/gdb/gdb_7.2a.bb create mode 100644 recipes/gdb/gdbserver_7.2a.bb 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 + #endif ++#ifdef _WIN32 ++#include ++#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 \n"); ++ monitor_output (" Set environment variable in remote environment\n"); ++ monitor_output (" cd \n"); ++ monitor_output (" Change current working directory\n"); ++ monitor_output (" pwd\n"); ++ monitor_output (" Print current working directory\n"); ++ monitor_output (" shell \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 + #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 + #include + ++#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 + ++#ifdef HAVE_CONFIG_H + #include "config.h" ++#endif + + #ifdef HAVE_STRING_H + #include +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 + #include + ++#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 + #include + ++#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 + #include +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 + #include + ++#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 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 +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 ++ ++#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 ++#include ++#include ++#include ++ ++/* 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 ++ ++#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 . */ + + #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 ++#include ++#include ++#include ++#include ++ ++#include ++ ++#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 . */ ++#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 . */ ++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 . */ ++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 . */ ++ ++ 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 + #include + +-#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 + #include + +-#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 + #include + +-#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 + #include + +-#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" + -- cgit 1.2.3-korg