Bug 77985 - DW_AT_comp_dir is omitted when filename is absolute and the file does not contain a specific typedef
Summary: DW_AT_comp_dir is omitted when filename is absolute and the file does not con...
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: debug (show other bugs)
Version: 7.0
: P3 normal
Target Milestone: 7.0
Assignee: Not yet assigned to anyone
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2016-10-14 10:27 UTC by infinity0
Modified: 2016-10-24 11:58 UTC (History)
0 users

See Also:
Host:
Target:
Build:
Known to work:
Known to fail: 4.3.5
Last reconfirmed: 2016-10-14 00:00:00


Attachments
Reproduce the bug; set CC to try it with different compilers (242 bytes, application/x-shellscript)
2016-10-14 10:29 UTC, infinity0
Details
Emit DW_AT_comp_dir even if filename is an absolute path (1.04 KB, patch)
2016-10-14 13:25 UTC, infinity0
Details | Diff
Emit DW_AT_comp_dir even if filename is an absolute path (1005 bytes, patch)
2016-10-14 14:15 UTC, infinity0
Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description infinity0 2016-10-14 10:27:57 UTC
Hi, GCC 7.0.0 (latest snapshot) and GCC 6.1.1 both exhibit the following behaviour:

+ gcc-build/destdir/usr/local/bin/gcc --version
gcc (GCC) 7.0.0 20161009 (experimental)
Copyright (C) 2016 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

+ cat test0.c
typedef __builtin_va_list __gnuc_va_list;
void func (void) {}
+ cat test1.c
void func (void) {}
+ gcc-build/destdir/usr/local/bin/gcc test0.c -g -dA -S -o- | grep comp_dir
	.long	.LASF4	# DW_AT_comp_dir: "/home/infinity0/var/lib/reproducible"
	.uleb128 0x1b	# (DW_AT_comp_dir)
+ gcc-build/destdir/usr/local/bin/gcc test1.c -g -dA -S -o- | grep comp_dir
	.long	.LASF2	# DW_AT_comp_dir: "/home/infinity0/var/lib/reproducible"
	.uleb128 0x1b	# (DW_AT_comp_dir)
+ gcc-build/destdir/usr/local/bin/gcc /home/infinity0/var/lib/reproducible/test0.c -g -dA -S -o- | grep comp_dir
	.long	.LASF4	# DW_AT_comp_dir: "/home/infinity0/var/lib/reproducible"
	.uleb128 0x1b	# (DW_AT_comp_dir)
+ gcc-build/destdir/usr/local/bin/gcc /home/infinity0/var/lib/reproducible/test1.c -g -dA -S -o- | grep comp_dir
# exit code 1

See the attached file for a shell script where you can reproduce this yourself.
Comment 1 infinity0 2016-10-14 10:29:16 UTC
Created attachment 39811 [details]
Reproduce the bug; set CC to try it with different compilers
Comment 2 Richard Biener 2016-10-14 10:57:59 UTC
Confirmed.  Already GCC 4.3 behaves that way.  Must be a feature ;)  (I suppose the bug is that _with_ that typedef we emit a DW_AT_comp_dir attribute).

GCC 3.2.3 didn't do that.

We have:

/* Generate the DIE for the compilation unit.  */

static dw_die_ref
gen_compile_unit_die (const char *filename)
{
  dw_die_ref die;
  const char *language_string = lang_hooks.name;
  int language;

  die = new_die (DW_TAG_compile_unit, NULL, NULL);

  if (filename)
    {
      add_name_attribute (die, filename);
      /* Don't add cwd for <built-in>.  */
      if (!IS_ABSOLUTE_PATH (filename) && filename[0] != '<')
        add_comp_dir_attribute (die);

thus absolute paths are supposed to omit it.
Comment 3 Richard Biener 2016-10-14 11:04:13 UTC
But also:

  /* Add the name for the main input file now.  We delayed this from
     dwarf2out_init to avoid complications with PCH.  */
  add_name_attribute (comp_unit_die (), remap_debug_filename (filename));
  if (!IS_ABSOLUTE_PATH (filename) || targetm.force_at_comp_dir)
    add_comp_dir_attribute (comp_unit_die ());
  else if (get_AT (comp_unit_die (), DW_AT_comp_dir) == NULL)
    {
      bool p = false;
      file_table->traverse<bool *, file_table_relative_p> (&p);
      if (p)
        add_comp_dir_attribute (comp_unit_die ());
    }

where the file table seems to contain "<built-in>".

Index: dwarf2out.c
===================================================================
--- dwarf2out.c (revision 241148)
+++ dwarf2out.c (working copy)
@@ -26422,7 +26422,8 @@ int
 file_table_relative_p (dwarf_file_data **slot, bool *p)
 {
   struct dwarf_file_data *d = *slot;
-  if (!IS_ABSOLUTE_PATH (d->filename))
+  if (!IS_ABSOLUTE_PATH (d->filename)
+      && d->filename[0] != '<')
     {
       *p = true;
       return 0;

fixes this.
Comment 4 infinity0 2016-10-14 11:17:30 UTC
Thanks for the quick response!

What is the reason for "absolute paths are supposed to omit it"? I'm reading the DWARF spec and I can't find a mention of this anywhere.

Even if DW_AT_name is absolute, recording DW_AT_comp_dir is still useful because it could be a different path and this would affect the interpretation of -I flags and so on.

The reason I found this bug was because I am writing a patch to make GCC produce debugging symbols that are reproducible regardless of the build path. (I will explain it in more detail via mail soon.) This bug does not directly affect that; however it does affect how easy it is to write tests to test my patch.

Emitting DW_AT_comp_dir in some cases and not others, also makes it more complex for others to write logic to deal with this attribute.

Piggybacking a slightly unrelated issue: I'm noticing that remap_debug_filename does not get applied to DW_AT_name in certain cases. Is this intentional? Hopefully not, since the easiest way I can write my patch is to apply it to DW_AT_name in all cases.
Comment 5 infinity0 2016-10-14 12:53:23 UTC
> Piggybacking a slightly unrelated issue: [..]

Upon further investigation it seems that, whilst the debug-prefix-maps do not get applied to DW_AT_name filenames in the output of -dA, it does get applied in the final assembled binary. Sorry for the noise.

The other point about DW_AT_comp_dir and absolute paths remains though - I'm thinking it would be simpler to just emit it in all cases, and get rid of the IS_ABSOLUTE_PATH checks. Since most things "in the wild" actually do have this typedef via standard library includes, this is actually the "expected" behaviour, hence why I titled this bug the way it is titled.
Comment 6 Richard Biener 2016-10-14 13:05:48 UTC
So I just fixed the bug here, but yes, I don't know about the design decision.  I suppose CWD was decided to be useless in case of an absolute path to the file.

I don't think the debug info preserves -I paths in any standard way, so what's exactly the reason you consider CWD not redundant here?  [we could rewrite the file-name to relative to CWD]
Comment 7 infinity0 2016-10-14 13:25:14 UTC
Created attachment 39812 [details]
Emit DW_AT_comp_dir even if filename is an absolute path

Suggested patch attached, with a test case.

Note that without this patch, it is hard to test anything relating to DW_AT_comp_dir in the testsuite, since it compiles the test cases using absolute paths.
Comment 8 infinity0 2016-10-14 13:42:42 UTC
(In reply to Richard Biener from comment #6)
> So I just fixed the bug here, but yes, I don't know about the design
> decision.  I suppose CWD was decided to be useless in case of an absolute
> path to the file.
> 
> I don't think the debug info preserves -I paths in any standard way, so
> what's exactly the reason you consider CWD not redundant here?  [we could
> rewrite the file-name to relative to CWD]

Sorry, I only noticed your reply after I posted that patch. The main reasons are:

1. So I can write a test case for the next patch I'd be submitting, since GCC submission processes demand this :p and

2. Reduces code complexity - my patch deletes more lines than it adds.

3. It will be able to handle any extensions to DWARF in the future that add relative paths elsewhere that one would want to resolve against DW_AT_comp_dir. One could reuse the same logic everywhere (in bad pseudo-code):

resolve_some_dwarf_path (path) {
  return relative(path) ? DW_AT_comp_dir/path : path;
}

Conceptually, the working directory is independent from an input file, so it would not be redundant to add it in the general case. *Sometimes*, *parts* of it might be redundant yes - and rewriting the filename to be relative to this, would remove the redundancy. Doing this is compatible with the above points, and I could amend the patch to do this, although I suggest it's not worth the effort (unless there is a function in GCC code that already does this).
Comment 9 infinity0 2016-10-14 14:15:06 UTC
Created attachment 39813 [details]
Emit DW_AT_comp_dir even if filename is an absolute path

Whoops my bad, I did not mean to remove the remap_debug_filename call, that was left over from some experimenting. Fixed now.
Comment 10 Richard Biener 2016-10-17 07:51:15 UTC
Please post the patch to gcc-patches@ where other people can see this and comment.
Comment 11 Richard Biener 2016-10-24 11:57:59 UTC
Author: rguenth
Date: Mon Oct 24 11:57:27 2016
New Revision: 241473

URL: https://gcc.gnu.org/viewcvs?rev=241473&root=gcc&view=rev
Log:
2016-10-24  Ximin Luo  <infinity0@pwned.gg>

	PR debug/77985
	* dwarf2out.c (file_table_relative_p): Remove.
	(gen_compile_unit_die, dwarf2out_early_finish): Emit DW_AT_comp_dir
	also for absolute paths.
	* doc/tm.texi: Update.
	* doc/tm.texi.in (SDB and DWARF) <TARGET_FORCE_AT_COMP_DIR>: Remove.
	* target.def (force_at_comp_dir): Remove hook.
	* config/darwin.h (TARGET_FORCE_AT_COMP_DIR): Remove define.

Modified:
    trunk/gcc/ChangeLog
    trunk/gcc/config/darwin.h
    trunk/gcc/doc/tm.texi
    trunk/gcc/doc/tm.texi.in
    trunk/gcc/dwarf2out.c
    trunk/gcc/target.def
Comment 12 Richard Biener 2016-10-24 11:58:17 UTC
Fixed for GCC 7.