diff --git a/llvm/include/llvm/MC/MCContext.h b/llvm/include/llvm/MC/MCContext.h --- a/llvm/include/llvm/MC/MCContext.h +++ b/llvm/include/llvm/MC/MCContext.h @@ -698,6 +698,9 @@ /// Add an entry to the debug prefix map. void addDebugPrefixMapEntry(const std::string &From, const std::string &To); + /// Remap one path in-place as per the debug prefix map. + void remapDebugPath(SmallVectorImpl &Path); + // Remaps all debug directory paths in-place as per the debug prefix map. void RemapDebugPaths(); diff --git a/llvm/include/llvm/MC/MCDwarf.h b/llvm/include/llvm/MC/MCDwarf.h --- a/llvm/include/llvm/MC/MCDwarf.h +++ b/llvm/include/llvm/MC/MCDwarf.h @@ -22,6 +22,7 @@ #include "llvm/MC/StringTableBuilder.h" #include "llvm/Support/Error.h" #include "llvm/Support/MD5.h" +#include "llvm/Support/StringSaver.h" #include #include #include @@ -48,6 +49,8 @@ /// Manage the .debug_line_str section contents, if we use it. class MCDwarfLineStr { + BumpPtrAllocator Alloc; + StringSaver Saver{Alloc}; MCSymbol *LineStrLabel = nullptr; StringTableBuilder LineStrings{StringTableBuilder::DWARF}; bool UseRelocs = false; @@ -57,6 +60,8 @@ /// v5 line table). explicit MCDwarfLineStr(MCContext &Ctx); + StringSaver &getSaver() { return Saver; } + /// Emit a reference to the string. void emitRef(MCStreamer *MCOS, StringRef Path); diff --git a/llvm/lib/MC/MCContext.cpp b/llvm/lib/MC/MCContext.cpp --- a/llvm/lib/MC/MCContext.cpp +++ b/llvm/lib/MC/MCContext.cpp @@ -855,30 +855,29 @@ DebugPrefixMap.insert(std::make_pair(From, To)); } +void MCContext::remapDebugPath(SmallVectorImpl &Path) { + for (const auto &[From, To] : DebugPrefixMap) + if (llvm::sys::path::replace_path_prefix(Path, From, To)) + break; +} + void MCContext::RemapDebugPaths() { const auto &DebugPrefixMap = this->DebugPrefixMap; if (DebugPrefixMap.empty()) return; - const auto RemapDebugPath = [&DebugPrefixMap](std::string &Path) { - SmallString<256> P(Path); - for (const auto &Entry : DebugPrefixMap) { - if (llvm::sys::path::replace_path_prefix(P, Entry.first, Entry.second)) { - Path = P.str().str(); - break; - } - } - }; - // Remap compilation directory. - std::string CompDir = std::string(CompilationDir.str()); - RemapDebugPath(CompDir); - CompilationDir = CompDir; + remapDebugPath(CompilationDir); // Remap MCDwarfDirs in all compilation units. - for (auto &CUIDTablePair : MCDwarfLineTablesCUMap) - for (auto &Dir : CUIDTablePair.second.getMCDwarfDirs()) - RemapDebugPath(Dir); + SmallString<256> P; + for (auto &CUIDTablePair : MCDwarfLineTablesCUMap) { + for (auto &Dir : CUIDTablePair.second.getMCDwarfDirs()) { + P = Dir; + remapDebugPath(P); + Dir = std::string(P); + } + } } //===----------------------------------------------------------------------===// diff --git a/llvm/lib/MC/MCDwarf.cpp b/llvm/lib/MC/MCDwarf.cpp --- a/llvm/lib/MC/MCDwarf.cpp +++ b/llvm/lib/MC/MCDwarf.cpp @@ -416,9 +416,15 @@ : dwarf::DW_FORM_string); MCOS->emitULEB128IntValue(MCDwarfDirs.size() + 1); // Try not to emit an empty compilation directory. - const StringRef CompDir = CompilationDir.empty() - ? MCOS->getContext().getCompilationDir() - : StringRef(CompilationDir); + SmallString<256> Dir; + StringRef CompDir = MCOS->getContext().getCompilationDir(); + if (!CompilationDir.empty()) { + Dir = CompilationDir; + MCOS->getContext().remapDebugPath(Dir); + CompDir = Dir.str(); + if (LineStr) + CompDir = LineStr->getSaver().save(CompDir); + } if (LineStr) { // Record path strings, emit references here. LineStr->emitRef(MCOS, CompDir); diff --git a/llvm/test/MC/ELF/debug-prefix-map.s b/llvm/test/MC/ELF/debug-prefix-map.s --- a/llvm/test/MC/ELF/debug-prefix-map.s +++ b/llvm/test/MC/ELF/debug-prefix-map.s @@ -31,19 +31,20 @@ # MAP_V4: DW_AT_decl_file [DW_FORM_data4] ("src_root{{(/|\\)+}}src.s") # MAP_V4-NOT: .foo -## FIXME DW_AT_decl_file and include_directories are not mapped # MAP_V5: DW_AT_name [DW_FORM_string] ("src.s") # MAP_V5: DW_AT_comp_dir [DW_FORM_string] ("src_root") -# MAP_V5: DW_AT_decl_file [DW_FORM_data4] ("{{.*}}.foo{{(/|\\)+}}src.s") -# MAP_V5: include_directories[ 0] = .debug_line_str[0x00000000] = "{{.*}}.foo" +## include_directories[0] is relative to DW_AT_comp_dir, so there are two src_root +## path components. This is not great but acceptable, because the -fdebug-prefix-map= +## destination path is supposed to be absolute in practice. +# MAP_V5: DW_AT_decl_file [DW_FORM_data4] ("src_root{{(/|\\)+}}src_root{{(/|\\)+}}src.s") +# MAP_V5: include_directories[ 0] = .debug_line_str[0x00000000] = "src_root" # MAPABS_V4: DW_AT_name [DW_FORM_string] ("src.s") # MAPABS_V4: DW_AT_comp_dir [DW_FORM_string] ("{{(/|\\)+}}src_root") # MAPABS_V4: DW_AT_decl_file [DW_FORM_data4] ("{{(/|\\)+}}src_root{{(/|\\)+}}src.s") # MAPABS_V4-NOT: .foo -## FIXME DW_AT_decl_file and include_directories are not mapped # MAPABS_V5: DW_AT_name [DW_FORM_string] ("src.s") # MAPABS_V5: DW_AT_comp_dir [DW_FORM_string] ("{{(/|\\)+}}src_root") -# MAPABS_V5: DW_AT_decl_file [DW_FORM_data4] ("{{.*}}.foo{{(/|\\)+}}src.s") -# MAPABS_V5: include_directories[ 0] = .debug_line_str[0x00000000] = "{{.*}}.foo" +# MAPABS_V5: DW_AT_decl_file [DW_FORM_data4] ("/src_root{{(/|\\)+}}src.s") +# MAPABS_V5: include_directories[ 0] = .debug_line_str[0x00000000] = "/src_root"