[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.

llvm-svn: 254431
This commit is contained in:
David Blaikie 2015-12-01 18:07:07 +00:00
parent 00fea63627
commit 98ad82a6a1
2 changed files with 71 additions and 20 deletions

View File

@ -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]]

View File

@ -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 <unordered_set>
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<uint32_t> &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<uint32_t, uint32_t> 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<std::string> Inputs) {
const auto &MCOFI = *Out.getContext().getObjectFileInfo();
MCSection *const StrSection = MCOFI.getDwarfStrDWOSection();
MCSection *const StrOffsetSection = MCOFI.getDwarfStrOffDWOSection();
const StringMap<MCSection *> 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<uint32_t> 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<MCSection *> 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();
}