diff -urN a/gdb-7.3.x/gdb/main.c b/gdb-7.3.x/gdb/main.c --- a/gdb-7.3.x/gdb/main.c 2012-07-21 13:40:24.571076202 +0100 +++ b/gdb-7.3.x/gdb/main.c 2012-07-21 13:57:47.558241890 +0100 @@ -45,6 +45,14 @@ #include "python/python.h" #include "objfiles.h" +#ifdef __MINGW32__ +#include <windows.h> +#endif + +#ifdef __APPLE__ +#include <mach-o/dyld.h> +#endif + /* The selected interpreter. This will be used as a set command variable, so it should always be malloc'ed - since do_setshow_command will free it. */ @@ -91,7 +99,7 @@ extern int write_files; /* GDB as it has been invoked from the command line (i.e. argv[0]). */ -static char *gdb_program_name; +char *gdb_program_name; static void print_gdb_help (struct ui_file *); @@ -279,6 +287,43 @@ } } +char* get_program_name(char* argv0) +{ + char new_argv0[1024] = {'\0'}; +#if defined(__linux__) || defined(__CYGWIN__) + size_t len; + if ((len = readlink("/proc/self/exe", new_argv0, sizeof(new_argv0)-1)) != -1) + { + new_argv0[len] = '\0'; + } +#elif defined(__APPLE__) + uint32_t len; + len=(uint32_t)sizeof(new_argv0); + _NSGetExecutablePath(new_argv0, &len); +#else + unsigned long bufsize=sizeof(new_argv0); + if (GetModuleFileName(NULL, new_argv0, bufsize) != 0) + { + /* Early conversion to unix slashes instead of more changes + * everywhere else... */ + char *winslash = strchr(new_argv0,'\\'); + while (winslash) + { + *winslash = '/'; + winslash = strchr(winslash,'\\'); + } + } +#endif + if (!strlen(new_argv0)) + { + return xstrdup(argv0); + } + else + { + return xstrdup(new_argv0); + } +} + static int captured_main (void *data) { @@ -369,7 +414,7 @@ gdb_stdtargerr = gdb_stderr; /* for moment */ gdb_stdtargin = gdb_stdin; /* for moment */ - gdb_program_name = xstrdup (argv[0]); + gdb_program_name = get_program_name (argv[0]); if (! getcwd (gdb_dirbuf, sizeof (gdb_dirbuf))) /* Don't use *_filtered or warning() (which relies on diff -urN a/gdb-7.3.x/gdb/main.h b/gdb-7.3.x/gdb/main.h --- a/gdb-7.3.x/gdb/main.h 2012-07-21 13:40:24.560076126 +0100 +++ b/gdb-7.3.x/gdb/main.h 2012-07-21 13:56:21.561653150 +0100 @@ -36,5 +36,6 @@ extern int return_child_result_value; extern int batch_silent; extern int batch_flag; +extern char *gdb_program_name; #endif diff -urN a/gdb-7.3.x/gdb/python/python.c b/gdb-7.3.x/gdb/python/python.c --- a/gdb-7.3.x/gdb/python/python.c 2012-07-21 13:40:24.554076084 +0100 +++ b/gdb-7.3.x/gdb/python/python.c 2012-07-21 13:56:36.706756791 +0100 @@ -40,6 +40,38 @@ #ifdef HAVE_PYTHON +static char pyver_string[]= +#if defined(HAVE_LIBPYTHON2_4) + "2.4"; +#elif defined(HAVE_LIBPYTHON2_5) + "2.5"; +#elif defined(HAVE_LIBPYTHON2_6) + "2.6"; +#elif defined(HAVE_LIBPYTHON2_7) + "2.7.3"; +#endif + +/* Android NDK-isms. Used to aid finding + Python in exceptional situations. */ + +static char host_name_string[]= +#if defined(__APPLE__) + "darwin"; +#elif defined(__MINGW32__) + "windows"; +#else + "linux"; +#endif + +static char host_arch_string[]= +#if (_LP64==1) || (__WIN64__==1) + "x86_64"; +#else + "x86"; +#endif + +/* End of android NDK-isms */ + #include "libiberty.h" #include "cli/cli-decode.h" #include "charset.h" @@ -954,12 +986,239 @@ /* Initialize the Python code. */ +#ifdef HAVE_PYTHON + +/* Provided input is not NULL, will always return a pointer into it. */ +char* last_n_folder_elements(char* input, char slash, size_t n_folders) +{ + char* temp; + size_t counter; + temp = strrchr(input,slash); + if (temp == NULL) + { + return input; + } + counter = n_folders; + while (counter != 0) + { + while (temp >= input && *temp != slash) + { + --temp; + } + if (temp < input) + { + return input; + } + --temp; + --counter; + } + if (temp[1] == slash) + { + return temp+1; + } + return temp; +} + +/* Either adds a new clue or frees it if already exists. */ +size_t add_clue(size_t n_so_far, char** clues, char* new_clue) +{ + size_t counter; + for (counter = 0; counter < n_so_far; ++counter) + { + if (!strcmp(clues[counter],new_clue)) + { + free(new_clue); + return n_so_far; + } + } + clues[n_so_far++] = new_clue; + return n_so_far; +} + +/* Both python_executable and pythonhome should point to NULL pointers + This function contains some hard coded assumptions, mostly all calls to + last_n_folder_elements make assumptions of a relative layout between gdb + and Python. + For my latest release, I've ended up with a layout that I don't think I'm + going to go with long-term: + Python has a prefix of toolchains/prebuilt/linux-x86/python-2.7.3 + but I'm thinking of dropping the final python-2.7.3 folder. + See notes [1] and [2] below for more details. +*/ +void find_python_executable_and_pythonhome(char** python_executable, + char** pythonhome) +{ + int debug_this = 0; +#ifdef __MINGW32__ + #define PYTHON_EXE "python.exe" + #define OS_STAT _stat +#else + #define PYTHON_EXE "python" + #define OS_STAT stat +#endif + char slash_string[2] = "/"; + char other_slash_string[2] = "\\"; + char* temp; + char* host_py_folders; + char* binexesuffix; + char* gdb_program_name_n; + /* Clues always include binexesuffix */ + char* clues[4]; + size_t n_clues = 0; + size_t counter; + struct OS_STAT buf; + + /* Normalise paths to // or \, depending on whether + or not // was found in gdb_program_name. Do this + first as we will modify --with-python-path also. */ + extern char* gdb_program_name; + if (debug_this) fprintf(stderr,"gdb_program_name is %s\n",gdb_program_name); + gdb_program_name_n = concat(gdb_program_name,NULL); + if (strchr(gdb_program_name_n,'\\')) + { + slash_string[0] = '\\'; + other_slash_string[0] = '/'; + } + temp = strchr(gdb_program_name_n, other_slash_string[0]); + while (temp != NULL) + { + *temp = slash_string[0]; + temp = strchr(temp, other_slash_string[0]); + } +#ifdef __MINGW32__ + /* Ensure drive letter is upper case. */ + if (strlen(gdb_program_name_n)>1 && gdb_program_name_n[1]==':') + { + gdb_program_name_n[0] = toupper(gdb_program_name_n[0]); + } +#endif + /* [1] Get a clue from gdb_program_name_n, remove the program part + once (if) the re-arrangement mentioned at the top of this + function takes place, this clue will be the one that hits. */ + temp = concat(gdb_program_name_n,slash_string,PYTHON_EXE,NULL); + if (strrchr(temp, slash_string[0])!=NULL) + *strrchr(temp, slash_string[0])='\0'; + if (strrchr(temp, slash_string[0])!=NULL) + *strrchr(temp, slash_string[0])='\0'; + strcat(temp,slash_string); + strcat(temp,PYTHON_EXE); + n_clues = add_clue(n_clues, clues, xstrdup( + last_n_folder_elements( temp, slash_string[0], 4) ) ); + free(temp); + + /* binexesuffix is the bit which when appended to the Python prefix + forms the full path to the Python executable. */ + binexesuffix = concat( slash_string, "bin", slash_string, PYTHON_EXE, NULL ); + if (debug_this) fprintf(stderr,"binexesuffix is %s\n",binexesuffix); +#ifdef WITH_PYTHON_PATH + /* Work around problem where python gets confused about where it is, + and then can't find its libraries, etc. + NOTE: Python assumes the following layout: + /foo/bin/python + /foo/lib/pythonX.Y/... + This must be done before calling Py_Initialize. */ + + if (debug_this) fprintf(stderr,"python_libdir is %s\n",python_libdir); + *python_executable = concat (ldirname (python_libdir), binexesuffix, NULL); + if (debug_this) fprintf(stderr,"python_executable is %s\n", + *python_executable); + temp = strchr(*python_executable, other_slash_string[0]); + while (temp != NULL) + { + *temp = slash_string[0]; + temp = strchr(temp, other_slash_string[0]); + } + if (debug_this) fprintf(stderr,"*python_executable (2) is %s\n", + *python_executable); +#endif + + /* If python_executable from WITH_PYTHON_PATH exists use it - usually won't + as it'll be in a build or a temporary install folder. */ + if ( *python_executable == NULL || OS_STAT(*python_executable, &buf) ) + { + /* If *python_executable didn't exist there could still be value in + it as a clue (the last four path elements). */ + if (*python_executable != NULL) + { + n_clues = add_clue(n_clues, clues, xstrdup( last_n_folder_elements( + *python_executable, slash_string[0], 4) ) ); + free(*python_executable); + *python_executable = NULL; + } + } + + if (*python_executable == NULL) + { + n_clues = add_clue(n_clues, clues, concat(binexesuffix, NULL)); + /* [2] - Until rearranged, this clue is the one which will hit. */ + n_clues = add_clue(n_clues, clues, concat(slash_string, "prebuilt", + slash_string, host_name_string, "-", host_arch_string, + slash_string, "python-", pyver_string, binexesuffix, NULL)); + + temp = strrchr(gdb_program_name_n,slash_string[0]); + if (debug_this) fprintf(stderr,"temp is %s\n",temp); + while (temp != NULL && *python_executable == NULL ) + { + if (debug_this) fprintf(stderr,"temp is %s, gdb_program_name_n is %s\n" + ,temp,gdb_program_name_n); + *temp = '\0'; + for (counter = 0; counter < n_clues; ++counter) + { + temp = concat(gdb_program_name_n, clues[counter], NULL); + if (debug_this) fprintf(stderr,"*temp (statcheck) is %s\n",temp); + if (!OS_STAT(temp, &buf)) + { + *python_executable = temp; + break; + } + free(temp); + } + temp = strrchr(gdb_program_name_n,slash_string[0]); + } + } + + if (debug_this) + { + fprintf(stderr,"Clues are:\n"); + for (counter = 0; counter < n_clues; ++counter) + { + fprintf(stderr,"clues[%d] is %s\n",counter,clues[counter]); + } + } + + if (*python_executable && strstr(*python_executable,binexesuffix) != NULL) + { + *pythonhome = xstrdup(*python_executable); + strstr(*pythonhome,binexesuffix)[1]='\0'; + } + if (debug_this) fprintf(stderr,"python_executable is %s, pythonhome is %s\n" + ,*python_executable?*python_executable:"<NOT FOUND>" + ,*pythonhome?*pythonhome:"<NOT FOUND>"); + + for (counter = 0; counter < n_clues; ++counter) + { + free(clues[counter]); + } + free(binexesuffix); + free(gdb_program_name_n); +#undef PYTHON_EXE +#undef OS_STAT +} +#endif + /* Provide a prototype to silence -Wmissing-prototypes. */ extern initialize_file_ftype _initialize_python; void _initialize_python (void) { +#ifdef HAVE_PYTHON + char* python_executable = NULL; + char* pythonhome = NULL; +#ifdef __MINGW32__ + char* putenvstr = NULL; +#endif +#endif add_com ("python", class_obscure, python_command, #ifdef HAVE_PYTHON _("\ @@ -1000,16 +1259,24 @@ &show_python_list); #ifdef HAVE_PYTHON -#ifdef WITH_PYTHON_PATH - /* Work around problem where python gets confused about where it is, - and then can't find its libraries, etc. - NOTE: Python assumes the following layout: - /foo/bin/python - /foo/lib/pythonX.Y/... - This must be done before calling Py_Initialize. */ - Py_SetProgramName (concat (ldirname (python_libdir), SLASH_STRING, "bin", - SLASH_STRING, "python", NULL)); + find_python_executable_and_pythonhome(&python_executable, &pythonhome); + if (python_executable != NULL) + { + Py_SetProgramName (python_executable); + free(python_executable); + } + if (pythonhome != NULL) + { +#if defined(__MINGW32__) + putenvstr=concat("PYTHONHOME=", pythonhome, NULL); + _putenv(putenvstr); + free(putenvstr); +#else + setenv("PYTHONHOME", pythonhome, 1); #endif + free(pythonhome); + } + /* GOOGLE LOCAL Ref# 4455829 Sometimes sitecustomize.py isn't going to be what we want for gdb,