From: David Blaikie Date: Tue, 1 Dec 2015 18:07:07 +0000 (+0000) Subject: [llvm-dwp] Correctly update debug_str_offsets.dwo when linking dwo files X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=0fb89f7b8241946815f6eb9ae59589e184d9b016;p=oota-llvm.git [llvm-dwp] Correctly update debug_str_offsets.dwo when linking dwo files This doesn't deduplicate strings in the debug_str section, nor does it properly wire up the index so that debug_info can /find/ these strings, but it does correct the str_offsets specifically. Follow up patches to address those related/next issues. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@254431 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/test/tools/llvm-dwp/X86/simple.test b/test/tools/llvm-dwp/X86/simple.test index 26215bdc8c9..d70bdda072c 100644 --- a/test/tools/llvm-dwp/X86/simple.test +++ b/test/tools/llvm-dwp/X86/simple.test @@ -47,12 +47,12 @@ CHECK: .debug_str.dwo contents: CHECK: "clang version CHECK: 0x[[ACPP:.*]]: "a.cpp" FIXME: Remove duplicates -CHECK: "clang version +CHECK: 0x[[SECONDREV:.*]]: "clang version CHECK: 0x[[BCPP:.*]]: "b.cpp" CHECK: .debug_str_offsets.dwo contents: CHECK: : 00000000 CHECK: : [[ACPP]] -CHECK: : 00000000 +CHECK: : [[SECONDREV]] FIXME: Update str offset indexes, this should be BCPP \/ -CHECK: : [[ACPP]] +CHECK: : [[BCPP]] diff --git a/tools/llvm-dwp/llvm-dwp.cpp b/tools/llvm-dwp/llvm-dwp.cpp index 7f9f6678db0..c89be222e6c 100644 --- a/tools/llvm-dwp/llvm-dwp.cpp +++ b/tools/llvm-dwp/llvm-dwp.cpp @@ -9,6 +9,7 @@ #include "llvm/MC/MCSectionELF.h" #include "llvm/MC/MCStreamer.h" #include "llvm/Object/ObjectFile.h" +#include "llvm/Support/DataExtractor.h" #include "llvm/Support/Options.h" #include "llvm/Support/FileSystem.h" #include "llvm/Support/MemoryBuffer.h" @@ -21,6 +22,7 @@ #include using namespace llvm; +using namespace llvm::object; using namespace cl; OptionCategory DwpCategory("Specific Options"); @@ -36,39 +38,88 @@ static int error(const Twine &Error, const Twine &Context) { return 1; } -static std::error_code writeSection(MCStreamer &Out, MCSection *OutSection, - const object::SectionRef &Sym) { - StringRef Contents; - if (auto Err = Sym.getContents(Contents)) - return Err; - Out.SwitchSection(OutSection); - Out.EmitBytes(Contents); +static std::error_code +writeStringsAndOffsets(MCStreamer &Out, StringMap &Strings, + uint32_t &StringOffset, MCSection *StrOffsetSection, + StringRef CurStrSection, StringRef CurStrOffsetSection) { + // Could possibly produce an error or warning if one of these was non-null but + // the other was null. + if (CurStrSection.empty() || CurStrOffsetSection.empty()) + return std::error_code(); + + DenseMap OffsetRemapping; + + DataExtractor Data(CurStrSection, true, 0); + uint32_t LocalOffset = 0; + uint32_t PrevOffset = 0; + while (const char *s = Data.getCStr(&LocalOffset)) { + StringRef Str(s, LocalOffset - PrevOffset - 1); + OffsetRemapping[PrevOffset] = StringOffset; + // insert, if successful, write new string to the str.dwo section + StringOffset += Str.size() + 1; + PrevOffset = LocalOffset; + } + + Data = DataExtractor(CurStrOffsetSection, true, 0); + + Out.SwitchSection(StrOffsetSection); + + uint32_t Offset = 0; + uint64_t Size = CurStrOffsetSection.size(); + while (Offset < Size) { + auto OldOffset = Data.getU32(&Offset); + auto NewOffset = OffsetRemapping[OldOffset]; + Out.EmitIntValue(NewOffset, 4); + } + return std::error_code(); } static std::error_code write(MCStreamer &Out, ArrayRef Inputs) { + const auto &MCOFI = *Out.getContext().getObjectFileInfo(); + MCSection *const StrSection = MCOFI.getDwarfStrDWOSection(); + MCSection *const StrOffsetSection = MCOFI.getDwarfStrOffDWOSection(); + const StringMap KnownSections = { + {"debug_info.dwo", MCOFI.getDwarfInfoDWOSection()}, + {"debug_types.dwo", MCOFI.getDwarfTypesDWOSection()}, + {"debug_str_offsets.dwo", StrOffsetSection}, + {"debug_str.dwo", StrSection}, + {"debug_loc.dwo", MCOFI.getDwarfLocDWOSection()}, + {"debug_abbrev.dwo", MCOFI.getDwarfAbbrevDWOSection()}}; + + StringMap Strings; + uint32_t StringOffset = 0; + for (const auto &Input : Inputs) { auto ErrOrObj = object::ObjectFile::createObjectFile(Input); if (!ErrOrObj) return ErrOrObj.getError(); const auto *Obj = ErrOrObj->getBinary(); + StringRef CurStrSection; + StringRef CurStrOffsetSection; for (const auto &Section : Obj->sections()) { - const auto &MCOFI = *Out.getContext().getObjectFileInfo(); - static const StringMap KnownSections = { - {"debug_info.dwo", MCOFI.getDwarfInfoDWOSection()}, - {"debug_types.dwo", MCOFI.getDwarfTypesDWOSection()}, - {"debug_str_offsets.dwo", MCOFI.getDwarfStrOffDWOSection()}, - {"debug_str.dwo", MCOFI.getDwarfStrDWOSection()}, - {"debug_loc.dwo", MCOFI.getDwarfLocDWOSection()}, - {"debug_abbrev.dwo", MCOFI.getDwarfAbbrevDWOSection()}}; StringRef Name; if (std::error_code Err = Section.getName(Name)) return Err; if (MCSection *OutSection = - KnownSections.lookup(Name.substr(Name.find_first_not_of("._")))) - if (auto Err = writeSection(Out, OutSection, Section)) + KnownSections.lookup(Name.substr(Name.find_first_not_of("._")))) { + StringRef Contents; + if (auto Err = Section.getContents(Contents)) return Err; + if (OutSection == StrOffsetSection) { + CurStrOffsetSection = Contents; + continue; + } + if (OutSection == StrSection) + CurStrSection = Contents; + Out.SwitchSection(OutSection); + Out.EmitBytes(Contents); + } } + if (auto Err = + writeStringsAndOffsets(Out, Strings, StringOffset, StrOffsetSection, + CurStrSection, CurStrOffsetSection)) + return Err; } return std::error_code(); }