forked from OSchip/llvm-project
[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:
parent
00fea63627
commit
98ad82a6a1
|
@ -47,12 +47,12 @@ CHECK: .debug_str.dwo contents:
|
||||||
CHECK: "clang version
|
CHECK: "clang version
|
||||||
CHECK: 0x[[ACPP:.*]]: "a.cpp"
|
CHECK: 0x[[ACPP:.*]]: "a.cpp"
|
||||||
FIXME: Remove duplicates
|
FIXME: Remove duplicates
|
||||||
CHECK: "clang version
|
CHECK: 0x[[SECONDREV:.*]]: "clang version
|
||||||
CHECK: 0x[[BCPP:.*]]: "b.cpp"
|
CHECK: 0x[[BCPP:.*]]: "b.cpp"
|
||||||
|
|
||||||
CHECK: .debug_str_offsets.dwo contents:
|
CHECK: .debug_str_offsets.dwo contents:
|
||||||
CHECK: : 00000000
|
CHECK: : 00000000
|
||||||
CHECK: : [[ACPP]]
|
CHECK: : [[ACPP]]
|
||||||
CHECK: : 00000000
|
CHECK: : [[SECONDREV]]
|
||||||
FIXME: Update str offset indexes, this should be BCPP \/
|
FIXME: Update str offset indexes, this should be BCPP \/
|
||||||
CHECK: : [[ACPP]]
|
CHECK: : [[BCPP]]
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
#include "llvm/MC/MCSectionELF.h"
|
#include "llvm/MC/MCSectionELF.h"
|
||||||
#include "llvm/MC/MCStreamer.h"
|
#include "llvm/MC/MCStreamer.h"
|
||||||
#include "llvm/Object/ObjectFile.h"
|
#include "llvm/Object/ObjectFile.h"
|
||||||
|
#include "llvm/Support/DataExtractor.h"
|
||||||
#include "llvm/Support/Options.h"
|
#include "llvm/Support/Options.h"
|
||||||
#include "llvm/Support/FileSystem.h"
|
#include "llvm/Support/FileSystem.h"
|
||||||
#include "llvm/Support/MemoryBuffer.h"
|
#include "llvm/Support/MemoryBuffer.h"
|
||||||
|
@ -21,6 +22,7 @@
|
||||||
#include <unordered_set>
|
#include <unordered_set>
|
||||||
|
|
||||||
using namespace llvm;
|
using namespace llvm;
|
||||||
|
using namespace llvm::object;
|
||||||
using namespace cl;
|
using namespace cl;
|
||||||
|
|
||||||
OptionCategory DwpCategory("Specific Options");
|
OptionCategory DwpCategory("Specific Options");
|
||||||
|
@ -36,39 +38,88 @@ static int error(const Twine &Error, const Twine &Context) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::error_code writeSection(MCStreamer &Out, MCSection *OutSection,
|
static std::error_code
|
||||||
const object::SectionRef &Sym) {
|
writeStringsAndOffsets(MCStreamer &Out, StringMap<uint32_t> &Strings,
|
||||||
StringRef Contents;
|
uint32_t &StringOffset, MCSection *StrOffsetSection,
|
||||||
if (auto Err = Sym.getContents(Contents))
|
StringRef CurStrSection, StringRef CurStrOffsetSection) {
|
||||||
return Err;
|
// Could possibly produce an error or warning if one of these was non-null but
|
||||||
Out.SwitchSection(OutSection);
|
// the other was null.
|
||||||
Out.EmitBytes(Contents);
|
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();
|
return std::error_code();
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::error_code write(MCStreamer &Out, ArrayRef<std::string> Inputs) {
|
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) {
|
for (const auto &Input : Inputs) {
|
||||||
auto ErrOrObj = object::ObjectFile::createObjectFile(Input);
|
auto ErrOrObj = object::ObjectFile::createObjectFile(Input);
|
||||||
if (!ErrOrObj)
|
if (!ErrOrObj)
|
||||||
return ErrOrObj.getError();
|
return ErrOrObj.getError();
|
||||||
const auto *Obj = ErrOrObj->getBinary();
|
const auto *Obj = ErrOrObj->getBinary();
|
||||||
|
StringRef CurStrSection;
|
||||||
|
StringRef CurStrOffsetSection;
|
||||||
for (const auto &Section : Obj->sections()) {
|
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;
|
StringRef Name;
|
||||||
if (std::error_code Err = Section.getName(Name))
|
if (std::error_code Err = Section.getName(Name))
|
||||||
return Err;
|
return Err;
|
||||||
if (MCSection *OutSection =
|
if (MCSection *OutSection =
|
||||||
KnownSections.lookup(Name.substr(Name.find_first_not_of("._"))))
|
KnownSections.lookup(Name.substr(Name.find_first_not_of("._")))) {
|
||||||
if (auto Err = writeSection(Out, OutSection, Section))
|
StringRef Contents;
|
||||||
|
if (auto Err = Section.getContents(Contents))
|
||||||
return Err;
|
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();
|
return std::error_code();
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue