Index: llvm/trunk/include/llvm/MC/MCContext.h =================================================================== --- llvm/trunk/include/llvm/MC/MCContext.h +++ llvm/trunk/include/llvm/MC/MCContext.h @@ -137,6 +137,9 @@ /// The compilation directory to use for DW_AT_comp_dir. SmallString<128> CompilationDir; + /// Prefix replacement map for source file information. + std::map DebugPrefixMap; + /// The main file name if passed in explicitly. std::string MainFileName; @@ -490,6 +493,21 @@ /// Set the compilation directory for DW_AT_comp_dir void setCompilationDir(StringRef S) { CompilationDir = S.str(); } + /// Get the debug prefix map. + const std::map & + getDebugPrefixMap() const { + return DebugPrefixMap; + } + + /// Add an entry to the debug prefix map. + void addDebugPrefixMapEntry(const std::string &From, const std::string &To); + + // Remaps the given path in-place as per the debug prefix map. + void RemapDebugPath(std::string *Path); + + // Remaps the compilation dir as per the debug prefix map. + void RemapCompilationDir(); + /// Get the main file name for use in error messages and debug /// info. This can be set to ensure we've got the correct file name /// after preprocessing or for -save-temps. Index: llvm/trunk/include/llvm/MC/MCDwarf.h =================================================================== --- llvm/trunk/include/llvm/MC/MCDwarf.h +++ llvm/trunk/include/llvm/MC/MCDwarf.h @@ -301,6 +301,8 @@ FileNumber)); } + void RemapDwarfDirs(MCContext &Context); + void setRootFile(StringRef Directory, StringRef FileName, MD5::MD5Result *Checksum, Optional Source) { Header.CompilationDir = Directory; Index: llvm/trunk/lib/MC/MCContext.cpp =================================================================== --- llvm/trunk/lib/MC/MCContext.cpp +++ llvm/trunk/lib/MC/MCContext.cpp @@ -535,6 +535,26 @@ return *new (MCSubtargetAllocator.Allocate()) MCSubtargetInfo(STI); } +void MCContext::addDebugPrefixMapEntry(const std::string &From, + const std::string &To) { + DebugPrefixMap.insert(std::make_pair(From, To)); +} + +void MCContext::RemapDebugPath(std::string *Path) { + for (const auto &Entry : DebugPrefixMap) + if (StringRef(*Path).startswith(Entry.first)) { + std::string RemappedPath = + (Twine(Entry.second) + Path->substr(Entry.first.size())).str(); + Path->swap(RemappedPath); + } +} + +void MCContext::RemapCompilationDir() { + std::string CompDir = CompilationDir.str(); + RemapDebugPath(&CompDir); + CompilationDir = CompDir; +} + //===----------------------------------------------------------------------===// // Dwarf Management //===----------------------------------------------------------------------===// Index: llvm/trunk/lib/MC/MCDwarf.cpp =================================================================== --- llvm/trunk/lib/MC/MCDwarf.cpp +++ llvm/trunk/lib/MC/MCDwarf.cpp @@ -250,8 +250,11 @@ MCOS->SwitchSection(context.getObjectFileInfo()->getDwarfLineSection()); // Handle the rest of the Compile Units. - for (const auto &CUIDTablePair : LineTables) - CUIDTablePair.second.EmitCU(MCOS, Params, LineStr); + for (const auto &CUIDTablePair : LineTables) { + auto &LineTable = context.getMCDwarfLineTable(CUIDTablePair.first); + LineTable.RemapDwarfDirs(MCOS->getContext()); + LineTable.EmitCU(MCOS, Params, LineStr); + } if (LineStr) LineStr->emitSection(MCOS); @@ -394,13 +397,13 @@ if (LineStr) { // Record path strings, emit references here. LineStr->emitRef(MCOS, CompDir); - for (auto &Dir : MCDwarfDirs) + for (const auto &Dir : MCDwarfDirs) LineStr->emitRef(MCOS, Dir); } else { // The list of directory paths. Compilation directory comes first. MCOS->EmitBytes(CompDir); MCOS->EmitBytes(StringRef("\0", 1)); - for (auto &Dir : MCDwarfDirs) { + for (const auto &Dir : MCDwarfDirs) { MCOS->EmitBytes(Dir); // The DirectoryName, and... MCOS->EmitBytes(StringRef("\0", 1)); // its null terminator. } @@ -631,6 +634,11 @@ return FileNumber; } +void MCDwarfLineTable::RemapDwarfDirs(MCContext &Context) { + for (auto &Dir : Header.MCDwarfDirs) + Context.RemapDebugPath(&Dir); +} + /// Utility function to emit the encoding to a streamer. void MCDwarfLineAddr::Emit(MCStreamer *MCOS, MCDwarfLineTableParams Params, int64_t LineDelta, uint64_t AddrDelta) { Index: llvm/trunk/lib/MC/MCObjectStreamer.cpp =================================================================== --- llvm/trunk/lib/MC/MCObjectStreamer.cpp +++ llvm/trunk/lib/MC/MCObjectStreamer.cpp @@ -661,6 +661,9 @@ } void MCObjectStreamer::FinishImpl() { + // Remap the compilation directory before emitting. + getContext().RemapCompilationDir(); + // If we are generating dwarf for assembly source files dump out the sections. if (getContext().getGenDwarfForAssembly()) MCGenDwarfInfo::Emit(this); Index: llvm/trunk/test/MC/ELF/debug-prefix-map.s =================================================================== --- llvm/trunk/test/MC/ELF/debug-prefix-map.s +++ llvm/trunk/test/MC/ELF/debug-prefix-map.s @@ -0,0 +1,17 @@ +// RUN: mkdir -p %t.foo +// RUN: cp %s %t.foo/src.s +// RUN: cd %t.foo + +// RUN: llvm-mc -triple=x86_64-linux-unknown -g src.s -filetype=obj -o out.o +// RUN: llvm-dwarfdump -v -debug-info out.o | FileCheck --check-prefix=NO_MAP %s +// RUN: llvm-mc -triple=x86_64-linux-unknown -g src.s -filetype=obj -o out.o -fdebug-prefix-map=%t.foo=src_root +// RUN: llvm-dwarfdump -v -debug-info out.o | FileCheck --check-prefix=MAP --implicit-check-not ".foo" %s + +f: + nop + +// NO_MAP: DW_AT_comp_dir [DW_FORM_string] ("{{.*}}.foo") + +// MAP: DW_AT_name [DW_FORM_string] ("src.s") +// MAP: DW_AT_comp_dir [DW_FORM_string] ("src_root") +// MAP: DW_AT_decl_file [DW_FORM_data4] ("src_root/src.s") Index: llvm/trunk/tools/llvm-mc/llvm-mc.cpp =================================================================== --- llvm/trunk/tools/llvm-mc/llvm-mc.cpp +++ llvm/trunk/tools/llvm-mc/llvm-mc.cpp @@ -152,6 +152,11 @@ DebugCompilationDir("fdebug-compilation-dir", cl::desc("Specifies the debug info's compilation dir")); +static cl::list +DebugPrefixMap("fdebug-prefix-map", + cl::desc("Map file source paths in debug info"), + cl::value_desc("= separated key-value pairs")); + static cl::opt MainFileName("main-file-name", cl::desc("Specifies the name we should consider the input file")); @@ -387,6 +392,10 @@ if (!sys::fs::current_path(CWD)) Ctx.setCompilationDir(CWD); } + for (const auto &Arg : DebugPrefixMap) { + const auto &KV = StringRef(Arg).split('='); + Ctx.addDebugPrefixMapEntry(KV.first, KV.second); + } if (!MainFileName.empty()) Ctx.setMainFileName(MainFileName); if (GenDwarfForAssembly && DwarfVersion >= 5) {