From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 24226 invoked by alias); 12 Jan 2012 03:07:05 -0000 Received: (qmail 24213 invoked by uid 22791); 12 Jan 2012 03:07:03 -0000 X-SWARE-Spam-Status: No, hits=-2.4 required=5.0 tests=AWL,BAYES_00,DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,RCVD_IN_DNSWL_LOW,TW_BJ,TW_CP,T_RP_MATCHES_RCVD X-Spam-Check-By: sourceware.org Received: from mail-gx0-f201.google.com (HELO mail-gx0-f201.google.com) (209.85.161.201) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Thu, 12 Jan 2012 03:06:50 +0000 Received: by ggnp1 with SMTP id p1so155976ggn.0 for ; Wed, 11 Jan 2012 19:06:48 -0800 (PST) Received: by 10.236.175.42 with SMTP id y30mr4281957yhl.3.1326337608728; Wed, 11 Jan 2012 19:06:48 -0800 (PST) Received: by 10.236.175.42 with SMTP id y30mr4281949yhl.3.1326337608673; Wed, 11 Jan 2012 19:06:48 -0800 (PST) Received: from wpzn4.hot.corp.google.com (216-239-44-65.google.com [216.239.44.65]) by gmr-mx.google.com with ESMTPS id r74si1335273yhh.4.2012.01.11.19.06.48 (version=TLSv1/SSLv3 cipher=AES128-SHA); Wed, 11 Jan 2012 19:06:48 -0800 (PST) Received: from elbrus2.mtv.corp.google.com (elbrus2.mtv.corp.google.com [172.18.111.111]) by wpzn4.hot.corp.google.com (Postfix) with ESMTP id 80A141E0058; Wed, 11 Jan 2012 19:06:48 -0800 (PST) Received: by elbrus2.mtv.corp.google.com (Postfix, from userid 74925) id 14DBE190AFD; Wed, 11 Jan 2012 19:06:47 -0800 (PST) To: gdb-patches@sourceware.org Cc: ppluzhnikov@google.com Subject: [patch] Fix for PR gdb/9538 (loading of separate debuginfo and symlinks). Message-Id: <20120112030648.14DBE190AFD@elbrus2.mtv.corp.google.com> Date: Thu, 12 Jan 2012 03:12:00 -0000 From: ppluzhnikov@google.com (Paul Pluzhnikov) X-IsSubscribed: yes Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org X-SW-Source: 2012-01/txt/msg00391.txt.bz2 Greetings, Attached is a proposed fix for PR gdb/9538. Mostly it just moves code around, and adds a "try realpath(objfile->name) if searching with objfile->name fails." The added test fails before the patch, and succeeds after it. Tested on Linux/x86_64. Thanks, -- Paul Pluzhnikov 2012-01-11 Paul Pluzhnikov PR gdb/9538 * symfile.c (find_separate_debug_file): New function. (terminate_after_last_dir_separator): Likewise. (find_separate_debug_file_by_debuglink): Also try realpath. testsuite/ChangeLog: PR gdb/9538 * gdb.base/sepdebug.exp: New test. Index: symfile.c =================================================================== RCS file: /cvs/src/src/gdb/symfile.c,v retrieving revision 1.325 diff -u -p -r1.325 symfile.c --- symfile.c 12 Jan 2012 00:00:01 -0000 1.325 +++ symfile.c 12 Jan 2012 01:34:01 -0000 @@ -1441,35 +1441,15 @@ show_debug_file_directory (struct ui_fil #define DEBUG_SUBDIRECTORY ".debug" #endif -char * -find_separate_debug_file_by_debuglink (struct objfile *objfile) -{ - char *basename, *debugdir; - char *dir = NULL; - char *debugfile = NULL; - char *canon_name = NULL; - unsigned long crc32; +static char * +find_separate_debug_file (const char *dir, const char *debuglink, + unsigned long crc32, struct objfile *objfile) +{ + char *debugdir; + char *debugfile; + char *canon_name; int i; - basename = get_debug_link_info (objfile, &crc32); - - if (basename == NULL) - /* There's no separate debug info, hence there's no way we could - load it => no warning. */ - goto cleanup_return_debugfile; - - dir = xstrdup (objfile->name); - - /* Strip off the final filename part, leaving the directory name, - followed by a slash. The directory can be relative or absolute. */ - for (i = strlen(dir) - 1; i >= 0; i--) - { - if (IS_DIR_SEPARATOR (dir[i])) - break; - } - /* If I is -1 then no directory is present there and DIR will be "". */ - dir[i+1] = '\0'; - /* Set I to max (strlen (canon_name), strlen (dir)). */ canon_name = lrealpath (dir); i = strlen (dir); @@ -1480,12 +1460,12 @@ find_separate_debug_file_by_debuglink (s + i + strlen (DEBUG_SUBDIRECTORY) + strlen ("/") - + strlen (basename) + + strlen (debuglink) + 1); /* First try in the same directory as the original file. */ strcpy (debugfile, dir); - strcat (debugfile, basename); + strcat (debugfile, debuglink); if (separate_debug_file_exists (debugfile, crc32, objfile)) goto cleanup_return_debugfile; @@ -1494,7 +1474,7 @@ find_separate_debug_file_by_debuglink (s strcpy (debugfile, dir); strcat (debugfile, DEBUG_SUBDIRECTORY); strcat (debugfile, "/"); - strcat (debugfile, basename); + strcat (debugfile, debuglink); if (separate_debug_file_exists (debugfile, crc32, objfile)) goto cleanup_return_debugfile; @@ -1520,7 +1500,7 @@ find_separate_debug_file_by_debuglink (s debugfile[debugdir_end - debugdir] = 0; strcat (debugfile, "/"); strcat (debugfile, dir); - strcat (debugfile, basename); + strcat (debugfile, debuglink); if (separate_debug_file_exists (debugfile, crc32, objfile)) goto cleanup_return_debugfile; @@ -1536,7 +1516,7 @@ find_separate_debug_file_by_debuglink (s debugfile[debugdir_end - debugdir] = 0; strcat (debugfile, canon_name + strlen (gdb_sysroot)); strcat (debugfile, "/"); - strcat (debugfile, basename); + strcat (debugfile, debuglink); if (separate_debug_file_exists (debugfile, crc32, objfile)) goto cleanup_return_debugfile; @@ -1551,8 +1531,61 @@ find_separate_debug_file_by_debuglink (s cleanup_return_debugfile: xfree (canon_name); - xfree (basename); + return debugfile; +} + +static void +terminate_after_last_dir_separator (char *path) +{ + int i; + + /* Strip off the final filename part, leaving the directory name, + followed by a slash. The directory can be relative or absolute. */ + for (i = strlen(path) - 1; i >= 0; i--) + { + if (IS_DIR_SEPARATOR (path[i])) + break; + } + /* If I is -1 then no directory is present there and DIR will be "". */ + path[i+1] = '\0'; +} + +char * +find_separate_debug_file_by_debuglink (struct objfile *objfile) +{ + char *debuglink; + char *dir; + char *debugfile; + unsigned long crc32; + + debuglink = get_debug_link_info (objfile, &crc32); + + if (debuglink == NULL) + /* There's no separate debug info, hence there's no way we could + load it => no warning. */ + return NULL; + + dir = xstrdup (objfile->name); + terminate_after_last_dir_separator (dir); + + debugfile = find_separate_debug_file (dir, debuglink, crc32, objfile); xfree (dir); + + if (debugfile != NULL) + goto cleanup_return_debugfile; + + /* For PR gdb/9538, try again with realpath. */ + dir = lrealpath (objfile->name); + if (dir == NULL) + goto cleanup_return_debugfile; + + terminate_after_last_dir_separator (dir); + debugfile = find_separate_debug_file (dir, debuglink, crc32, objfile); + xfree (dir); + + cleanup_return_debugfile: + xfree (debuglink); + return debugfile; } Index: testsuite/gdb.base/sepdebug.exp =================================================================== RCS file: /cvs/src/src/gdb/testsuite/gdb.base/sepdebug.exp,v retrieving revision 1.33 diff -u -p -r1.33 sepdebug.exp --- testsuite/gdb.base/sepdebug.exp 4 Jan 2012 08:17:46 -0000 1.33 +++ testsuite/gdb.base/sepdebug.exp 12 Jan 2012 01:34:01 -0000 @@ -45,7 +45,7 @@ if { [gdb_compile "${srcdir}/${subdir}/ # Note: the procedure gdb_gnu_strip_debug will produce an executable called # ${binfile}, which is just like the executable ($binfile) but without -# the debuginfo. Instead $binfile has a .gnudebuglink section which contains +# the debuginfo. Instead $binfile has a .gnu_debuglink section which contains # the name of a debuginfo only file. This file will be stored in the # gdb.base/ subdirectory. @@ -55,9 +55,25 @@ if [gdb_gnu_strip_debug $binfile] { return -1 } +# +# PR gdb/9538. Verify that symlinked executable still finds the separate +# debuginfo. +# gdb_exit gdb_start gdb_reinitialize_dir $srcdir/$subdir +set subsubdir ${objdir}/${subdir}/pr9538 +exec mkdir ${subsubdir} +exec ln -s ${binfile} ${subsubdir} +gdb_load ${subsubdir}/${testfile}${EXEEXT} +if { $gdb_file_cmd_debug_info != "debug" } then { + fail "No debug information found." +} +gdb_exit +exec rm -rf ${subsubdir} + +gdb_start +gdb_reinitialize_dir $srcdir/$subdir gdb_load ${binfile} if { $gdb_file_cmd_debug_info != "debug" } then { fail "No debug information found."