summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPavel Labath <pavel@labath.sk>2019-01-16 12:30:41 +0000
committerPavel Labath <pavel@labath.sk>2019-01-16 12:30:41 +0000
commit7fed798070f44a92026c93e8b58b53164f3d1596 (patch)
treec28c885d0ed7a8e75bea69eeba2801a87f14b06c
parentc2ec4c18228e59c85b6a4ec7f56d1aa7a91767d1 (diff)
DWARF: Add some support for non-native directory separators
Summary: If we opened a file which was produced on system with different path syntax, we would parse the paths from the debug info incorrectly. The reason for that is that we would parse the paths as they were native. For example this meant that on linux we would treat the entire windows path as a single file name with no directory component, and then we would concatenate that with the single directory component from the DW_AT_comp_dir attribute. When parsing posix paths on windows, we would at least get the directory separators right, but we still would treat the posix paths as relative, and concatenate them where we shouldn't. This patch attempts to remedy this by guessing the path syntax used in each compile unit. (Unfortunately, there is no info in DWARF which would give the definitive path style used by the produces, so guessing is all we can do.) Currently, this guessing is based on the DW_AT_comp_dir attribute of the compile unit, but this can be refined later if needed (for example, the DW_AT_name of the compile unit may also contain some useful info). This style is then used when parsing the line table of that compile unit. This patch is sufficient to make the line tables come out right, and enable breakpoint setting by file name work correctly. Setting a breakpoint by full path still has some kinks (specifically, using a windows-style full path will not work on linux because the path will be parsed as a linux path), but this will require larger changes in how breakpoint setting works. Reviewers: clayborg, zturner, JDevlieghere Subscribers: aprantl, lldb-commits Differential Revision: https://reviews.llvm.org/D56543
-rw-r--r--lldb/include/lldb/Utility/FileSpec.h4
-rw-r--r--lldb/lit/SymbolFile/DWARF/Inputs/dir-separator-no-comp-dir-relative-name.lldbinit3
-rw-r--r--lldb/lit/SymbolFile/DWARF/Inputs/dir-separator-posix.lldbinit3
-rw-r--r--lldb/lit/SymbolFile/DWARF/Inputs/dir-separator-windows.lldbinit7
-rw-r--r--lldb/lit/SymbolFile/DWARF/dir-separator-no-comp-dir-relative-name.s62
-rw-r--r--lldb/lit/SymbolFile/DWARF/dir-separator-no-comp-dir.s62
-rw-r--r--lldb/lit/SymbolFile/DWARF/dir-separator-posix.s67
-rw-r--r--lldb/lit/SymbolFile/DWARF/dir-separator-windows.s67
-rw-r--r--lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugLine.cpp14
-rw-r--r--lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugLine.h6
-rw-r--r--lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp74
-rw-r--r--lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.h6
-rw-r--r--lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp77
-rw-r--r--lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h2
-rw-r--r--lldb/source/Utility/FileSpec.cpp5
15 files changed, 382 insertions, 77 deletions
diff --git a/lldb/include/lldb/Utility/FileSpec.h b/lldb/include/lldb/Utility/FileSpec.h
index 0699ab7b5c9..03c2fa1d156 100644
--- a/lldb/include/lldb/Utility/FileSpec.h
+++ b/lldb/include/lldb/Utility/FileSpec.h
@@ -326,6 +326,10 @@ public:
//------------------------------------------------------------------
bool IsAbsolute() const;
+ /// Make the FileSpec absolute by treating it relative to \a dir. Absolute
+ /// FileSpecs are never changed by this function.
+ void MakeAbsolute(const FileSpec &dir);
+
/// Temporary helper for FileSystem change.
void SetPath(llvm::StringRef p) { SetFile(p); }
diff --git a/lldb/lit/SymbolFile/DWARF/Inputs/dir-separator-no-comp-dir-relative-name.lldbinit b/lldb/lit/SymbolFile/DWARF/Inputs/dir-separator-no-comp-dir-relative-name.lldbinit
new file mode 100644
index 00000000000..390408ec8cc
--- /dev/null
+++ b/lldb/lit/SymbolFile/DWARF/Inputs/dir-separator-no-comp-dir-relative-name.lldbinit
@@ -0,0 +1,3 @@
+image dump line-table a.c
+breakpoint set -f a.c -l 1
+breakpoint set -f foo/b.c -l 1
diff --git a/lldb/lit/SymbolFile/DWARF/Inputs/dir-separator-posix.lldbinit b/lldb/lit/SymbolFile/DWARF/Inputs/dir-separator-posix.lldbinit
new file mode 100644
index 00000000000..73a8a491bb2
--- /dev/null
+++ b/lldb/lit/SymbolFile/DWARF/Inputs/dir-separator-posix.lldbinit
@@ -0,0 +1,3 @@
+image dump line-table a.c
+breakpoint set -f a.c -l 1
+breakpoint set -f /tmp/b.c -l 1
diff --git a/lldb/lit/SymbolFile/DWARF/Inputs/dir-separator-windows.lldbinit b/lldb/lit/SymbolFile/DWARF/Inputs/dir-separator-windows.lldbinit
new file mode 100644
index 00000000000..8737aafc8a2
--- /dev/null
+++ b/lldb/lit/SymbolFile/DWARF/Inputs/dir-separator-windows.lldbinit
@@ -0,0 +1,7 @@
+image dump line-table a.c
+breakpoint set -f a.c -l 1
+breakpoint set -f C:/tmp/b.c -l 1
+
+# This will fail on non-windows systems because the path will by parsed
+# according to posix rules
+# breakpoint set -f 'C:\tmp\b.c' -l 1
diff --git a/lldb/lit/SymbolFile/DWARF/dir-separator-no-comp-dir-relative-name.s b/lldb/lit/SymbolFile/DWARF/dir-separator-no-comp-dir-relative-name.s
new file mode 100644
index 00000000000..6df3a3d3e48
--- /dev/null
+++ b/lldb/lit/SymbolFile/DWARF/dir-separator-no-comp-dir-relative-name.s
@@ -0,0 +1,62 @@
+# Test that parsing of line tables works reasonably, even if the host directory
+# separator does not match the separator of the compile unit.
+
+# REQUIRES: lld
+
+# RUN: llvm-mc -triple x86_64-pc-linux %s -filetype=obj > %t.o
+# RUN: ld.lld %t.o -o %t
+# RUN: %lldb %t -s %S/Inputs/dir-separator-no-comp-dir-relative-name.lldbinit -o exit | FileCheck %s
+
+# CHECK-LABEL: image dump line-table a.c
+# CHECK: Line table for foo/a.c
+# CHECK-NEXT: 0x0000000000201000: foo/a.c:1
+# CHECK-NEXT: 0x0000000000201001: foo/b.c:1
+# CHECK-NEXT: 0x0000000000201002: foo/b.c:1
+# CHECK-EMPTY:
+
+# CHECK-LABEL: breakpoint set -f a.c -l 1
+# CHECK: Breakpoint 1: {{.*}}`_start,
+
+# CHECK-LABEL: breakpoint set -f foo/b.c -l 1
+# CHECK: Breakpoint 2: {{.*}}`_start + 1,
+
+ .text
+ .globl _start
+_start:
+ .file 1 "foo/a.c"
+ .loc 1 1 0
+ nop
+ .file 2 "foo/b.c"
+ .loc 2 1 0
+ nop
+
+ .section .debug_str,"MS",@progbits,1
+.Linfo_string1:
+ .asciz "foo/a.c"
+ .section .debug_abbrev,"",@progbits
+ .byte 1 # Abbreviation Code
+ .byte 17 # DW_TAG_compile_unit
+ .byte 0 # DW_CHILDREN_no
+ .byte 19 # DW_AT_language
+ .byte 5 # DW_FORM_data2
+ .byte 3 # DW_AT_name
+ .byte 14 # DW_FORM_strp
+ .byte 16 # DW_AT_stmt_list
+ .byte 23 # DW_FORM_sec_offset
+ .byte 0 # EOM(1)
+ .byte 0 # EOM(2)
+ .byte 0 # EOM(3)
+ .section .debug_info,"",@progbits
+.Lcu_begin0:
+ .long .Lcu_end0-.Lcu_start0 # Length of Unit
+.Lcu_start0:
+ .short 4 # DWARF version number
+ .long .debug_abbrev # Offset Into Abbrev. Section
+ .byte 8 # Address Size (in bytes)
+ .byte 1 # Abbrev [1] 0xb:0x1f DW_TAG_compile_unit
+ .short 12 # DW_AT_language
+ .long .Linfo_string1 # DW_AT_name
+ .long .Lline_table_start0 # DW_AT_stmt_list
+.Lcu_end0:
+ .section .debug_line,"",@progbits
+.Lline_table_start0:
diff --git a/lldb/lit/SymbolFile/DWARF/dir-separator-no-comp-dir.s b/lldb/lit/SymbolFile/DWARF/dir-separator-no-comp-dir.s
new file mode 100644
index 00000000000..9e3281a334f
--- /dev/null
+++ b/lldb/lit/SymbolFile/DWARF/dir-separator-no-comp-dir.s
@@ -0,0 +1,62 @@
+# Test that we properly determine the path syntax of a compile unit even if the
+# compile unit does not have a DW_AT_comp_dir attribute.
+
+# REQUIRES: lld
+
+# RUN: llvm-mc -triple x86_64-pc-linux %s -filetype=obj > %t.o
+# RUN: ld.lld %t.o -o %t
+# RUN: %lldb %t -s %S/Inputs/dir-separator-windows.lldbinit -o exit | FileCheck %s
+
+# CHECK-LABEL: image dump line-table a.c
+# CHECK: Line table for C:\tmp\a.c
+# CHECK-NEXT: 0x0000000000201000: C:\tmp\a.c:1
+# CHECK-NEXT: 0x0000000000201001: C:\tmp\b.c:1
+# CHECK-NEXT: 0x0000000000201002: C:\tmp\b.c:1
+# CHECK-EMPTY:
+
+# CHECK-LABEL: breakpoint set -f a.c -l 1
+# CHECK: Breakpoint 1: {{.*}}`_start,
+
+# CHECK-LABEL: breakpoint set -f C:/tmp/b.c -l 1
+# CHECK: Breakpoint 2: {{.*}}`_start + 1,
+
+ .text
+ .globl _start
+_start:
+ .file 1 "C:\\tmp\\a.c"
+ .loc 1 1 0
+ nop
+ .file 2 "C:\\tmp\\b.c"
+ .loc 2 1 0
+ nop
+
+ .section .debug_str,"MS",@progbits,1
+.Linfo_string1:
+ .asciz "C:\\tmp\\a.c"
+ .section .debug_abbrev,"",@progbits
+ .byte 1 # Abbreviation Code
+ .byte 17 # DW_TAG_compile_unit
+ .byte 0 # DW_CHILDREN_no
+ .byte 19 # DW_AT_language
+ .byte 5 # DW_FORM_data2
+ .byte 3 # DW_AT_name
+ .byte 14 # DW_FORM_strp
+ .byte 16 # DW_AT_stmt_list
+ .byte 23 # DW_FORM_sec_offset
+ .byte 0 # EOM(1)
+ .byte 0 # EOM(2)
+ .byte 0 # EOM(3)
+ .section .debug_info,"",@progbits
+.Lcu_begin0:
+ .long .Lcu_end0-.Lcu_start0 # Length of Unit
+.Lcu_start0:
+ .short 4 # DWARF version number
+ .long .debug_abbrev # Offset Into Abbrev. Section
+ .byte 8 # Address Size (in bytes)
+ .byte 1 # Abbrev [1] 0xb:0x1f DW_TAG_compile_unit
+ .short 12 # DW_AT_language
+ .long .Linfo_string1 # DW_AT_name
+ .long .Lline_table_start0 # DW_AT_stmt_list
+.Lcu_end0:
+ .section .debug_line,"",@progbits
+.Lline_table_start0:
diff --git a/lldb/lit/SymbolFile/DWARF/dir-separator-posix.s b/lldb/lit/SymbolFile/DWARF/dir-separator-posix.s
new file mode 100644
index 00000000000..976038a9f8b
--- /dev/null
+++ b/lldb/lit/SymbolFile/DWARF/dir-separator-posix.s
@@ -0,0 +1,67 @@
+# Test that parsing of line tables works reasonably, even if the host directory
+# separator does not match the separator of the compile unit.
+
+# REQUIRES: lld
+
+# RUN: llvm-mc -triple x86_64-pc-linux %s -filetype=obj > %t.o
+# RUN: ld.lld %t.o -o %t
+# RUN: %lldb %t -s %S/Inputs/dir-separator-posix.lldbinit -o exit | FileCheck %s
+
+# CHECK-LABEL: image dump line-table a.c
+# CHECK: Line table for /tmp/a.c
+# CHECK-NEXT: 0x0000000000201000: /tmp/a.c:1
+# CHECK-NEXT: 0x0000000000201001: /tmp/b.c:1
+# CHECK-NEXT: 0x0000000000201002: /tmp/b.c:1
+# CHECK-EMPTY:
+
+# CHECK-LABEL: breakpoint set -f a.c -l 1
+# CHECK: Breakpoint 1: {{.*}}`_start,
+
+# CHECK-LABEL: breakpoint set -f /tmp/b.c -l 1
+# CHECK: Breakpoint 2: {{.*}}`_start + 1,
+
+ .text
+ .globl _start
+_start:
+ .file 1 "/tmp/a.c"
+ .loc 1 1 0
+ nop
+ .file 2 "/tmp/b.c"
+ .loc 2 1 0
+ nop
+
+ .section .debug_str,"MS",@progbits,1
+.Linfo_string1:
+ .asciz "a.c"
+.Linfo_string2:
+ .asciz "/tmp"
+ .section .debug_abbrev,"",@progbits
+ .byte 1 # Abbreviation Code
+ .byte 17 # DW_TAG_compile_unit
+ .byte 0 # DW_CHILDREN_no
+ .byte 19 # DW_AT_language
+ .byte 5 # DW_FORM_data2
+ .byte 3 # DW_AT_name
+ .byte 14 # DW_FORM_strp
+ .byte 16 # DW_AT_stmt_list
+ .byte 23 # DW_FORM_sec_offset
+ .byte 27 # DW_AT_comp_dir
+ .byte 14 # DW_FORM_strp
+ .byte 0 # EOM(1)
+ .byte 0 # EOM(2)
+ .byte 0 # EOM(3)
+ .section .debug_info,"",@progbits
+.Lcu_begin0:
+ .long .Lcu_end0-.Lcu_start0 # Length of Unit
+.Lcu_start0:
+ .short 4 # DWARF version number
+ .long .debug_abbrev # Offset Into Abbrev. Section
+ .byte 8 # Address Size (in bytes)
+ .byte 1 # Abbrev [1] 0xb:0x1f DW_TAG_compile_unit
+ .short 12 # DW_AT_language
+ .long .Linfo_string1 # DW_AT_name
+ .long .Lline_table_start0 # DW_AT_stmt_list
+ .long .Linfo_string2 # DW_AT_comp_dir
+.Lcu_end0:
+ .section .debug_line,"",@progbits
+.Lline_table_start0:
diff --git a/lldb/lit/SymbolFile/DWARF/dir-separator-windows.s b/lldb/lit/SymbolFile/DWARF/dir-separator-windows.s
new file mode 100644
index 00000000000..30308ab9dfb
--- /dev/null
+++ b/lldb/lit/SymbolFile/DWARF/dir-separator-windows.s
@@ -0,0 +1,67 @@
+# Test that parsing of line tables works reasonably, even if the host directory
+# separator does not match the separator of the compile unit.
+
+# REQUIRES: lld
+
+# RUN: llvm-mc -triple x86_64-pc-linux %s -filetype=obj > %t.o
+# RUN: ld.lld %t.o -o %t
+# RUN: %lldb %t -s %S/Inputs/dir-separator-windows.lldbinit -o exit | FileCheck %s
+
+# CHECK-LABEL: image dump line-table a.c
+# CHECK: Line table for C:\tmp\a.c
+# CHECK-NEXT: 0x0000000000201000: C:\tmp\a.c:1
+# CHECK-NEXT: 0x0000000000201001: C:\tmp\b.c:1
+# CHECK-NEXT: 0x0000000000201002: C:\tmp\b.c:1
+# CHECK-EMPTY:
+
+# CHECK-LABEL: breakpoint set -f a.c -l 1
+# CHECK: Breakpoint 1: {{.*}}`_start,
+
+# CHECK-LABEL: breakpoint set -f C:/tmp/b.c -l 1
+# CHECK: Breakpoint 2: {{.*}}`_start + 1,
+
+ .text
+ .globl _start
+_start:
+ .file 1 "C:\\tmp\\a.c"
+ .loc 1 1 0
+ nop
+ .file 2 "C:\\tmp\\b.c"
+ .loc 2 1 0
+ nop
+
+ .section .debug_str,"MS",@progbits,1
+.Linfo_string1:
+ .asciz "a.c"
+.Linfo_string2:
+ .asciz "C:\\tmp"
+ .section .debug_abbrev,"",@progbits
+ .byte 1 # Abbreviation Code
+ .byte 17 # DW_TAG_compile_unit
+ .byte 0 # DW_CHILDREN_no
+ .byte 19 # DW_AT_language
+ .byte 5 # DW_FORM_data2
+ .byte 3 # DW_AT_name
+ .byte 14 # DW_FORM_strp
+ .byte 16 # DW_AT_stmt_list
+ .byte 23 # DW_FORM_sec_offset
+ .byte 27 # DW_AT_comp_dir
+ .byte 14 # DW_FORM_strp
+ .byte 0 # EOM(1)
+ .byte 0 # EOM(2)
+ .byte 0 # EOM(3)
+ .section .debug_info,"",@progbits
+.Lcu_begin0:
+ .long .Lcu_end0-.Lcu_start0 # Length of Unit
+.Lcu_start0:
+ .short 4 # DWARF version number
+ .long .debug_abbrev # Offset Into Abbrev. Section
+ .byte 8 # Address Size (in bytes)
+ .byte 1 # Abbrev [1] 0xb:0x1f DW_TAG_compile_unit
+ .short 12 # DW_AT_language
+ .long .Linfo_string1 # DW_AT_name
+ .long .Lline_table_start0 # DW_AT_stmt_list
+ .long .Linfo_string2 # DW_AT_comp_dir
+.Lcu_end0:
+ .section .debug_line,"",@progbits
+.Lline_table_start0:
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugLine.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugLine.cpp
index d9f50122bd6..cd50d40887e 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugLine.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugLine.cpp
@@ -18,6 +18,7 @@
#include "lldb/Utility/Log.h"
#include "lldb/Utility/Timer.h"
+#include "DWARFUnit.h"
#include "LogChannelDWARF.h"
#include "SymbolFileDWARF.h"
@@ -528,8 +529,7 @@ bool DWARFDebugLine::ParsePrologue(const DWARFDataExtractor &debug_line_data,
bool DWARFDebugLine::ParseSupportFiles(
const lldb::ModuleSP &module_sp, const DWARFDataExtractor &debug_line_data,
- const lldb_private::FileSpec &cu_comp_dir, dw_offset_t stmt_list,
- FileSpecList &support_files, DWARFUnit *dwarf_cu) {
+ dw_offset_t stmt_list, FileSpecList &support_files, DWARFUnit *dwarf_cu) {
lldb::offset_t offset = stmt_list;
Prologue prologue;
@@ -545,7 +545,9 @@ bool DWARFDebugLine::ParseSupportFiles(
std::string remapped_file;
for (uint32_t file_idx = 1;
- prologue.GetFile(file_idx, cu_comp_dir, file_spec); ++file_idx) {
+ prologue.GetFile(file_idx, dwarf_cu->GetCompilationDirectory(),
+ dwarf_cu->GetPathStyle(), file_spec);
+ ++file_idx) {
if (module_sp->RemapSourceFile(file_spec.GetPath(), remapped_file))
file_spec.SetFile(remapped_file, FileSpec::Style::native);
support_files.Append(file_spec);
@@ -947,10 +949,12 @@ void DWARFDebugLine::Prologue::Dump(Log *log) {
//}
bool DWARFDebugLine::Prologue::GetFile(uint32_t file_idx,
- const lldb_private::FileSpec &comp_dir, FileSpec &file) const {
+ const FileSpec &comp_dir,
+ FileSpec::Style style,
+ FileSpec &file) const {
uint32_t idx = file_idx - 1; // File indexes are 1 based...
if (idx < file_names.size()) {
- file.SetFile(file_names[idx].name, FileSpec::Style::native);
+ file.SetFile(file_names[idx].name, style);
if (file.IsRelative()) {
if (file_names[idx].dir_idx > 0) {
const uint32_t dir_idx = file_names[idx].dir_idx - 1;
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugLine.h b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugLine.h
index 04f72e03a2d..976e4038c6f 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugLine.h
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugLine.h
@@ -14,6 +14,7 @@
#include <string>
#include <vector>
+#include "lldb/Utility/FileSpec.h"
#include "lldb/lldb-private.h"
#include "DWARFDataExtractor.h"
@@ -99,6 +100,7 @@ public:
file_names.clear();
}
bool GetFile(uint32_t file_idx, const lldb_private::FileSpec &cu_comp_dir,
+ lldb_private::FileSpec::Style style,
lldb_private::FileSpec &file) const;
};
@@ -207,9 +209,9 @@ public:
static bool
ParseSupportFiles(const lldb::ModuleSP &module_sp,
const lldb_private::DWARFDataExtractor &debug_line_data,
- const lldb_private::FileSpec &cu_comp_dir,
dw_offset_t stmt_list,
- lldb_private::FileSpecList &support_files, DWARFUnit *dwarf_cu);
+ lldb_private::FileSpecList &support_files,
+ DWARFUnit *dwarf_cu);
static bool
ParsePrologue(const lldb_private::DWARFDataExtractor &debug_line_data,
lldb::offset_t *offset_ptr, Prologue *prologue,
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp
index 7afc71bc24f..f794a77587f 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp
@@ -766,6 +766,80 @@ bool DWARFUnit::GetIsOptimized() {
return m_is_optimized == eLazyBoolYes;
}
+FileSpec::Style DWARFUnit::GetPathStyle() {
+ if (!m_comp_dir)
+ ComputeCompDirAndGuessPathStyle();
+ return m_comp_dir->GetPathStyle();
+}
+
+const FileSpec &DWARFUnit::GetCompilationDirectory() {
+ if (!m_comp_dir)
+ ComputeCompDirAndGuessPathStyle();
+ return *m_comp_dir;
+}
+
+// DWARF2/3 suggests the form hostname:pathname for compilation directory.
+// Remove the host part if present.
+static llvm::StringRef
+removeHostnameFromPathname(llvm::StringRef path_from_dwarf) {
+ llvm::StringRef host, path;
+ std::tie(host, path) = path_from_dwarf.split(':');
+
+ if (host.contains('/'))
+ return path_from_dwarf;
+
+ // check whether we have a windows path, and so the first character is a
+ // drive-letter not a hostname.
+ if (host.size() == 1 && llvm::isAlpha(host[0]) && path.startswith("\\"))
+ return path_from_dwarf;
+
+ return path;
+}
+
+static FileSpec resolveCompDir(const FileSpec &path) {
+ bool is_symlink = SymbolFileDWARF::GetSymlinkPaths().FindFileIndex(
+ 0, path, /*full*/ true) != UINT32_MAX;
+
+ if (!is_symlink)
+ return path;
+
+ namespace fs = llvm::sys::fs;
+ if (fs::get_file_type(path.GetPath(), false) != fs::file_type::symlink_file)
+ return path;
+
+ FileSpec resolved_symlink;
+ const auto error = FileSystem::Instance().Readlink(path, resolved_symlink);
+ if (error.Success())
+ return resolved_symlink;
+
+ return path;
+}
+
+void DWARFUnit::ComputeCompDirAndGuessPathStyle() {
+ m_comp_dir = FileSpec();
+ const DWARFDebugInfoEntry *die = GetUnitDIEPtrOnly();
+ if (!die)
+ return;
+
+ auto guess = [](llvm::StringRef str) {
+ if (str.startswith("/"))
+ return FileSpec::Style::posix;
+ if (str.size() > 3 && llvm::isAlpha(str[0]) && str.substr(1, 2) == ":\\")
+ return FileSpec::Style::windows;
+ return FileSpec::Style::native;
+ };
+ llvm::StringRef comp_dir = removeHostnameFromPathname(
+ die->GetAttributeValueAsString(m_dwarf, this, DW_AT_comp_dir, NULL));
+ if (!comp_dir.empty()) {
+ m_comp_dir = resolveCompDir(FileSpec(comp_dir, guess(comp_dir)));
+ } else {
+ // Try to detect the style based on the DW_AT_name attribute, but just store
+ // the detected style in the m_comp_dir field.
+ m_comp_dir = FileSpec("", guess(die->GetAttributeValueAsString(
+ m_dwarf, this, DW_AT_name, NULL)));
+ }
+}
+
SymbolFileDWARFDwo *DWARFUnit::GetDwoSymbolFile() const {
return m_dwo_symbol_file.get();
}
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.h b/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.h
index 178c894686e..c6cff7ac5c6 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.h
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.h
@@ -169,6 +169,9 @@ public:
bool GetIsOptimized();
+ const lldb_private::FileSpec &GetCompilationDirectory();
+ lldb_private::FileSpec::Style GetPathStyle();
+
SymbolFileDWARFDwo *GetDwoSymbolFile() const;
dw_offset_t GetBaseObjOffset() const;
@@ -214,6 +217,7 @@ protected:
lldb::LanguageType m_language_type = lldb::eLanguageTypeUnknown;
bool m_is_dwarf64 = false;
lldb_private::LazyBool m_is_optimized = lldb_private::eLazyBoolCalculate;
+ llvm::Optional<lldb_private::FileSpec> m_comp_dir;
dw_addr_t m_addr_base = 0; // Value of DW_AT_addr_base
dw_addr_t m_ranges_base = 0; // Value of DW_AT_ranges_base
// If this is a dwo compile unit this is the offset of the base compile unit
@@ -249,6 +253,8 @@ private:
void AddUnitDIE(const DWARFDebugInfoEntry &cu_die);
void ExtractDIEsEndCheck(lldb::offset_t offset) const;
+ void ComputeCompDirAndGuessPathStyle();
+
DISALLOW_COPY_AND_ASSIGN(DWARFUnit);
};
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
index 2a0a89f0b25..33cd2aba496 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
@@ -158,64 +158,8 @@ static const SymbolFileDWARFPropertiesSP &GetGlobalPluginProperties() {
} // anonymous namespace end
-static const char *removeHostnameFromPathname(const char *path_from_dwarf) {
- if (!path_from_dwarf || !path_from_dwarf[0]) {
- return path_from_dwarf;
- }
-
- const char *colon_pos = strchr(path_from_dwarf, ':');
- if (nullptr == colon_pos) {
- return path_from_dwarf;
- }
-
- const char *slash_pos = strchr(path_from_dwarf, '/');
- if (slash_pos && (slash_pos < colon_pos)) {
- return path_from_dwarf;
- }
-
- // check whether we have a windows path, and so the first character is a
- // drive-letter not a hostname.
- if (colon_pos == path_from_dwarf + 1 && isalpha(*path_from_dwarf) &&
- strlen(path_from_dwarf) > 2 && '\\' == path_from_dwarf[2]) {
- return path_from_dwarf;
- }
-
- return colon_pos + 1;
-}
-
-static FileSpec resolveCompDir(const char *path_from_dwarf) {
- if (!path_from_dwarf)
- return FileSpec();
-
- // DWARF2/3 suggests the form hostname:pathname for compilation directory.
- // Remove the host part if present.
- const char *local_path = removeHostnameFromPathname(path_from_dwarf);
- if (!local_path)
- return FileSpec();
-
- bool is_symlink = false;
- // Always normalize our compile unit directory to get rid of redundant
- // slashes and other path anomalies before we use it for path prepending
- FileSpec local_spec(local_path);
- const auto &file_specs = GetGlobalPluginProperties()->GetSymLinkPaths();
- for (size_t i = 0; i < file_specs.GetSize() && !is_symlink; ++i)
- is_symlink = FileSpec::Equal(file_specs.GetFileSpecAtIndex(i),
- local_spec, true);
-
- if (!is_symlink)
- return local_spec;
-
- namespace fs = llvm::sys::fs;
- if (fs::get_file_type(local_spec.GetPath(), false) !=
- fs::file_type::symlink_file)
- return local_spec;
-
- FileSpec resolved_symlink;
- const auto error = FileSystem::Instance().Readlink(local_spec, resolved_symlink);
- if (error.Success())
- return resolved_symlink;
-
- return local_spec;
+const FileSpecList &SymbolFileDWARF::GetSymlinkPaths() {
+ return GetGlobalPluginProperties()->GetSymLinkPaths();
}
DWARFUnit *SymbolFileDWARF::GetBaseCompileUnit() {
@@ -810,17 +754,12 @@ lldb::CompUnitSP SymbolFileDWARF::ParseCompileUnit(DWARFUnit *dwarf_cu,
if (module_sp) {
const DWARFDIE cu_die = dwarf_cu->DIE();
if (cu_die) {
- FileSpec cu_file_spec(cu_die.GetName());
+ FileSpec cu_file_spec(cu_die.GetName(), dwarf_cu->GetPathStyle());
if (cu_file_spec) {
// If we have a full path to the compile unit, we don't need to
// resolve the file. This can be expensive e.g. when the source
- // files are
- // NFS mounted.
- if (cu_file_spec.IsRelative()) {
- const char *cu_comp_dir{
- cu_die.GetAttributeValueAsString(DW_AT_comp_dir, nullptr)};
- cu_file_spec.PrependPathComponent(resolveCompDir(cu_comp_dir));
- }
+ // files are NFS mounted.
+ cu_file_spec.MakeAbsolute(dwarf_cu->GetCompilationDirectory());
std::string remapped_file;
if (module_sp->RemapSourceFile(cu_file_spec.GetPath(),
@@ -947,8 +886,6 @@ bool SymbolFileDWARF::ParseSupportFiles(CompileUnit &comp_unit,
const DWARFBaseDIE cu_die = dwarf_cu->GetUnitDIEOnly();
if (cu_die) {
- FileSpec cu_comp_dir = resolveCompDir(
- cu_die.GetAttributeValueAsString(DW_AT_comp_dir, nullptr));
const dw_offset_t stmt_list = cu_die.GetAttributeValueAsUnsigned(
DW_AT_stmt_list, DW_INVALID_OFFSET);
if (stmt_list != DW_INVALID_OFFSET) {
@@ -956,8 +893,8 @@ bool SymbolFileDWARF::ParseSupportFiles(CompileUnit &comp_unit,
// supposed to be the compile unit itself.
support_files.Append(comp_unit);
return DWARFDebugLine::ParseSupportFiles(
- comp_unit.GetModule(), get_debug_line_data(), cu_comp_dir,
- stmt_list, support_files, dwarf_cu);
+ comp_unit.GetModule(), get_debug_line_data(), stmt_list,
+ support_files, dwarf_cu);
}
}
}
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h
index d351289f8b5..e6fe19e75c1 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h
+++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h
@@ -86,6 +86,8 @@ public:
static lldb_private::SymbolFile *
CreateInstance(lldb_private::ObjectFile *obj_file);
+ static const lldb_private::FileSpecList &GetSymlinkPaths();
+
//------------------------------------------------------------------
// Constructors and Destructors
//------------------------------------------------------------------
diff --git a/lldb/source/Utility/FileSpec.cpp b/lldb/source/Utility/FileSpec.cpp
index 954968b7a8a..e621ada794e 100644
--- a/lldb/source/Utility/FileSpec.cpp
+++ b/lldb/source/Utility/FileSpec.cpp
@@ -557,6 +557,11 @@ bool FileSpec::IsAbsolute() const {
return llvm::sys::path::is_absolute(current_path, m_style);
}
+void FileSpec::MakeAbsolute(const FileSpec &dir) {
+ if (IsRelative())
+ PrependPathComponent(dir);
+}
+
void llvm::format_provider<FileSpec>::format(const FileSpec &F,
raw_ostream &Stream,
StringRef Style) {