From patchwork Thu Sep 5 22:40:48 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mike Gulick X-Patchwork-Id: 34405 Received: (qmail 122252 invoked by alias); 5 Sep 2019 22:40:56 -0000 Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org Delivered-To: mailing list gdb-patches@sourceware.org Received: (qmail 122171 invoked by uid 89); 5 Sep 2019 22:40:55 -0000 Authentication-Results: sourceware.org; auth=none X-Spam-SWARE-Status: No, score=-23.6 required=5.0 tests=BAYES_00, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, RCVD_IN_SBL_CSS autolearn=ham version=3.3.1 spammy=83, $HOME, HOME, $home X-HELO: us-smtp-1.mimecast.com Received: from us-smtp-delivery-1.mimecast.com (HELO us-smtp-1.mimecast.com) (207.211.31.120) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Thu, 05 Sep 2019 22:40:52 +0000 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=mathworks.com; s=mimecast20180117; t=1567723250; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=PjteZrOnPSjeiVmE14P3IGr2AvzyXJ9bmnsbXsyCqHk=; b=gEVhh2vT7Av8weBzZAEo0Az8bb7itKojgnVDuXtlizSPe8xY5BStHzHtjM0fzz9S4UYhc+ hpklJs55Sk0c8vjJSorxduM1rDoelYKi9GCVtvBJC+t1k24XY20UB25+Ndfe7PtPQuOre6 JEQ4x6rOsGAwgY8S6KIaRPb2zwBmlTs= Received: from NAM01-BN3-obe.outbound.protection.outlook.com (mail-bn3nam01lp2051.outbound.protection.outlook.com [104.47.33.51]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-285-fXj_90SGP12Wn_2sAqWkeA-1; Thu, 05 Sep 2019 18:40:49 -0400 Received: from DM6PR05MB4156.namprd05.prod.outlook.com (20.176.72.29) by DM6SPR01MB0064.namprd05.prod.outlook.com (20.179.160.204) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.2263.5; Thu, 5 Sep 2019 22:40:48 +0000 Received: from DM6PR05MB4156.namprd05.prod.outlook.com ([fe80::a00e:ddad:be30:b632]) by DM6PR05MB4156.namprd05.prod.outlook.com ([fe80::a00e:ddad:be30:b632%6]) with mapi id 15.20.2220.022; Thu, 5 Sep 2019 22:40:48 +0000 From: Mike Gulick To: "gdb-patches@sourceware.org" CC: Mike Gulick Subject: [RFC] Apply compilation dir to source_path lookup Date: Thu, 5 Sep 2019 22:40:48 +0000 Message-ID: <8058b501-9020-84f1-ecf4-b46bfe3b86e3@mathworks.com> x-ms-exchange-purlcount: 1 x-ms-exchange-transport-forked: True x-ms-oob-tlc-oobclassifiers: OLM:10000; x-ms-exchange-senderadcheck: 1 Content-ID: MIME-Version: 1.0 X-MS-Exchange-CrossTenant-mailboxtype: HOSTED X-MS-Exchange-CrossTenant-userprincipalname: Cz9XB1pprV6M82NiZFPvXnvzpvoPxuUV70bgPshxfhGdxkslTARJ/GPDjRj2TWiDUW+PhxtmxTHJyB3hq4QNvA== X-Mimecast-Spam-Score: 0 Hi, I'm having trouble getting gdb to find the corresponding source for a binary whose compilation directory was rewritten using -fdebug-prefix-map. I am doing this in order to make builds reproducible. I am using this gcc switch to remove a portion of the compile directory, e.g. $ cd $HOME/test/src/ $ gcc -g -o test -fdebug-prefix-map=$HOME= test.c $ dwarfdump test ... DW_AT_name test.c DW_AT_comp_dir /test/src ... When attempting to debug the resulting binary, gdb is unable to find the source file even if I add the removed path $HOME to the gdb source path: $ cd $HOME $ gdb --nh ~/test/src/test GNU gdb (GDB) 8.3 ... (gdb) directory /home/mgulick Source directories searched: /home/mgulick:$cdir:$cwd (gdb) info sources Source files for which symbols have been read in: /test/src/test.c Source files for which symbols will be read in on demand: (gdb) b test.c:3 Breakpoint 1 at 0x664: file test.c, line 3. (gdb) r Starting program: /mathworks/home/mgulick/test/src/test Breakpoint 1, main () at test.c:3 3 test.c: No such file or directory. It turns out that only the source file, i.e. DW_AT_name, is used when searching the source path. This is surprising given the example with '/usr/src/foo-1.0/lib/foo.c' and '/mnt/cross' in the gdb documentation here: https://sourceware.org/gdb/onlinedocs/gdb/Source-Path.html. It seems uncommon for DW_AT_name to be the full path to the source file in most programs I have come across. In that example from the documentation, it is likely that DW_AT_name would be 'lib/foo.c' and DW_AT_comp_dir would be '/usr/src/foo-1.0'. I have implemented two different approaches to handle this, both of which work, and I wanted feedback on a) whether you think this is a legitimate bug/feature, and b) which approach you prefer. Approach 1 is to include another pass in find_and_open_source where the compilation directory is prepended to the filename before searching for the file with openp. This allows the example I provided above to work as-is. Approach 2 is to allow '$cdir' to appear as part of an entry in the source_path. Currently it is only allowed to exist as a standalone entry. This would allow me to say 'directory /home/mgulick/$cdir', and find_and_open_source would expand the $cdir part of this string to the compilation directory. I prefer approach 1 for a couple of reasons: 1) It is simpler for users to understand. It doesn't really require understanding the difference between DW_AT_comp_dir and DW_AT_name. It will match the source file in /home/mgulick/test.c, /test/src/test.c, or /home/mgulick/test/src/test.c. Of course, since '$cdir' is still in source_path, it will also look in /test/src/test/src/test.c, which is a little confusing, but shouldn't be a problem (and we could explicitly remove '$cdir' from the path when doing this search). 2) It seems to match the existing gdb documentation. I dislike approach 2 because it makes the directory strings more complicated, and it also means I'm unable to have a directory named '/home/mgulick/$cdir' (bizarre, I know, but such things are possible). Here is a preliminary patch for the first approach. I will go ahead and add a test-case and re-send a formal patch review request if this seems like an acceptable solution. Thanks, Mike diff --git a/gdb/source.c b/gdb/source.c index b27f210802..b7b5741028 100644 --- a/gdb/source.c +++ b/gdb/source.c @@ -1033,7 +1033,35 @@ find_and_open_source (const char *filename, openp_flags flags = OPF_SEARCH_IN_PATH; if (basenames_may_differ) flags |= OPF_RETURN_REALPATH; + + /* Try to locate file using filename */ result = openp (path, flags, filename, OPEN_MODE, fullname); + if (result < 0 && dirname != NULL) + { + /* Try to locate file using compilation dir + filename. This is helpful + if part of the compilation directory was removed, e.g. using gcc's + -fdebug-prefix-map, and we have added the missing prefix to + source_path. */ + /* Allocate space for dirname, possibly an extra slash, the filename, + and terminating null */ + char * cdir_filename = (char *) + alloca (strlen (dirname) + strlen(SLASH_STRING) + strlen (filename) + 1); + + cdir_filename = strcpy (cdir_filename, dirname); + int len = strlen (cdir_filename); /* last char in cdir_filename */ + + /* Add directory separator if not provided by dirname or filename */ + if (!(IS_DIR_SEPARATOR (cdir_filename[len]) || + IS_DIR_SEPARATOR (filename[0]))) + strcat (cdir_filename, SLASH_STRING); + else if (IS_DIR_SEPARATOR (cdir_filename[len]) && + IS_DIR_SEPARATOR (filename[0])) + /* Both provide a slash, use only one */ + cdir_filename[len] = '\0'; + strcat(cdir_filename,filename); + + result = openp(path, flags, cdir_filename, OPEN_MODE, fullname); + } if (result < 0) { /* Didn't work. Try using just the basename. */