[llvm-dsymutil] Add support for __swift_ast MachO DWARF section

Summary:
Xcode's dsymutil emits a __swift_ast DWARF section, which is required for debugging,
and which contains a byte-for-byte dump of the swiftmodule file.
Add this feature to llvm-dsymutil.

Tested with `gobjdump --dwarf=info -s`, by verifying that the contents of
`__DWARF.__swift_ast` match between Xcode's dsymutil and llvm-dsymutil
(Xcode's dwarfdump and llvm-dwarfdump don't currently recognize the
__swift_ast section).

Reviewers: aprantl, friss

Subscribers: llvm-commits, JDevlieghere

Differential Revision: https://reviews.llvm.org/D38504

llvm-svn: 315066
This commit is contained in:
Francis Ricci 2017-10-06 14:49:20 +00:00
parent 3333494132
commit 8aedfde298
10 changed files with 78 additions and 16 deletions

View File

@ -123,6 +123,9 @@ protected:
/// Section for newer gnu pubtypes.
MCSection *DwarfGnuPubTypesSection;
// Section for Swift AST
MCSection *DwarfSwiftASTSection;
MCSection *COFFDebugSymbolsSection;
MCSection *COFFDebugTypesSection;
@ -267,6 +270,7 @@ public:
MCSection *getDwarfAddrSection() const { return DwarfAddrSection; }
MCSection *getDwarfCUIndexSection() const { return DwarfCUIndexSection; }
MCSection *getDwarfTUIndexSection() const { return DwarfTUIndexSection; }
MCSection *getDwarfSwiftASTSection() const { return DwarfSwiftASTSection; }
MCSection *getCOFFDebugSymbolsSection() const {
return COFFDebugSymbolsSection;

View File

@ -214,6 +214,10 @@ void MCObjectFileInfo::initMachOMCObjectFileInfo(const Triple &T) {
Ctx->getMachOSection("__DWARF", "__apple_types", MachO::S_ATTR_DEBUG,
SectionKind::getMetadata(), "types_begin");
DwarfSwiftASTSection =
Ctx->getMachOSection("__DWARF", "__swift_ast", MachO::S_ATTR_DEBUG,
SectionKind::getMetadata());
DwarfAbbrevSection =
Ctx->getMachOSection("__DWARF", "__debug_abbrev", MachO::S_ATTR_DEBUG,
SectionKind::getMetadata(), "section_abbrev");

Binary file not shown.

View File

@ -0,0 +1 @@
SWIFTMODULE DATA

View File

@ -0,0 +1,14 @@
RUN: llvm-dsymutil -oso-prepend-path %p/.. %p/../Inputs/swift-ast.macho.x86_64 -o %T/swift-ast.dSYM -verbose | FileCheck %s --check-prefix=DSYMUTIL
RUN: llvm-readobj -sections -section-data %T/swift-ast.dSYM/Contents/Resources/DWARF/swift-ast.macho.x86_64 | FileCheck %s --check-prefix=READOBJ
The tested object file has been created by the dummy Swift code:
let x = 1
Compiled with: swiftc /tmp/test.swift -Onone -target x86_64-apple-macosx10.9 -c
Linked with: ld swift-ast.o -add_ast_path Inputs/swift-ast.swiftmodule -arch x86_64 -lSystem -macosx_version_min 10.9.0
DSYMUTIL: filename:{{.*}}swift-ast.swiftmodule
DSYMUTIL: DEBUG MAP OBJECT:{{.*}}swift-ast.swiftmodule
READOBJ: Name:{{.*}}__swift_ast
READOBJ: |SWIFTMODULE DATA|

View File

@ -66,6 +66,12 @@ class BinaryHolder {
MapArchiveAndGetMemberBuffers(StringRef Filename,
sys::TimePoint<std::chrono::seconds> Timestamp);
void changeBackingMemoryBuffer(std::unique_ptr<MemoryBuffer> &&MemBuf);
ErrorOr<const object::ObjectFile &> getObjfileForArch(const Triple &T);
public:
BinaryHolder(bool Verbose) : Verbose(Verbose) {}
/// Return the MemoryBufferRef that holds the memory mapping for the
/// given \p Filename. This function will try to parse archive
/// member specifications of the form /path/to/archive.a(member.o).
@ -79,12 +85,6 @@ class BinaryHolder {
GetMemoryBuffersForFile(StringRef Filename,
sys::TimePoint<std::chrono::seconds> Timestamp);
void changeBackingMemoryBuffer(std::unique_ptr<MemoryBuffer> &&MemBuf);
ErrorOr<const object::ObjectFile &> getObjfileForArch(const Triple &T);
public:
BinaryHolder(bool Verbose) : Verbose(Verbose) {}
/// Get the ObjectFiles designated by the \p Filename. This
/// might be an archive member specification of the form
/// /path/to/archive.a(member.o).

View File

@ -21,8 +21,9 @@ namespace dsymutil {
using namespace llvm::object;
DebugMapObject::DebugMapObject(StringRef ObjectFilename,
sys::TimePoint<std::chrono::seconds> Timestamp)
: Filename(ObjectFilename), Timestamp(Timestamp) {}
sys::TimePoint<std::chrono::seconds> Timestamp,
uint8_t Type)
: Filename(ObjectFilename), Timestamp(Timestamp), Type(Type) {}
bool DebugMapObject::addSymbol(StringRef Name, Optional<uint64_t> ObjectAddress,
uint64_t LinkedAddress, uint32_t Size) {
@ -64,8 +65,9 @@ void DebugMapObject::dump() const { print(errs()); }
DebugMapObject &
DebugMap::addDebugMapObject(StringRef ObjectFilePath,
sys::TimePoint<std::chrono::seconds> Timestamp) {
Objects.emplace_back(new DebugMapObject(ObjectFilePath, Timestamp));
sys::TimePoint<std::chrono::seconds> Timestamp,
uint8_t Type) {
Objects.emplace_back(new DebugMapObject(ObjectFilePath, Timestamp, Type));
return *Objects.back();
}
@ -241,7 +243,7 @@ MappingTraits<dsymutil::DebugMapObject>::YamlDMO::denormalize(IO &IO) {
}
}
dsymutil::DebugMapObject Res(Path, sys::toTimePoint(Timestamp));
dsymutil::DebugMapObject Res(Path, sys::toTimePoint(Timestamp), MachO::N_OSO);
for (auto &Entry : Entries) {
auto &Mapping = Entry.second;
Optional<uint64_t> ObjAddress;

View File

@ -94,7 +94,8 @@ public:
/// debug map.
DebugMapObject &
addDebugMapObject(StringRef ObjectFilePath,
sys::TimePoint<std::chrono::seconds> Timestamp);
sys::TimePoint<std::chrono::seconds> Timestamp,
uint8_t Type);
const Triple &getTriple() const { return BinaryTriple; }
@ -154,6 +155,8 @@ public:
return Timestamp;
}
uint8_t getType() const { return Type; }
iterator_range<StringMap<SymbolMapping>::const_iterator> symbols() const {
return make_range(Symbols.begin(), Symbols.end());
}
@ -166,12 +169,13 @@ private:
friend class DebugMap;
/// DebugMapObjects can only be constructed by the owning DebugMap.
DebugMapObject(StringRef ObjectFilename,
sys::TimePoint<std::chrono::seconds> Timestamp);
sys::TimePoint<std::chrono::seconds> Timestamp, uint8_t Type);
std::string Filename;
sys::TimePoint<std::chrono::seconds> Timestamp;
StringMap<SymbolMapping> Symbols;
DenseMap<uint64_t, DebugMapEntry *> AddressToMapping;
uint8_t Type;
/// For YAMLIO support.
///@{

View File

@ -525,6 +525,9 @@ public:
/// Emit the string table described by \p Pool.
void emitStrings(const NonRelocatableStringpool &Pool);
/// Emit the swift_ast section stored in \p Buffers.
void emitSwiftAST(const std::vector<MemoryBufferRef> &Buffers);
/// Emit debug_ranges for \p FuncRange by translating the
/// original \p Entries.
void emitRangesEntries(
@ -708,6 +711,15 @@ void DwarfStreamer::emitStrings(const NonRelocatableStringpool &Pool) {
StringRef(Entry->getKey().data(), Entry->getKey().size() + 1));
}
/// Emit the swift_ast section stored in \p Buffers.
void DwarfStreamer::emitSwiftAST(const std::vector<MemoryBufferRef> &Buffers) {
MCSection *SwiftASTSection = MOFI->getDwarfSwiftASTSection();
SwiftASTSection->setAlignment(1 << 5);
MS->SwitchSection(SwiftASTSection);
for (auto Buf : Buffers)
MS->EmitBytes(Buf.getBuffer());
}
/// Emit the debug_range section contents for \p FuncRange by
/// translating the original \p Entries. The debug_range section
/// format is totally trivial, consisting just of pairs of address
@ -3329,8 +3341,8 @@ void DwarfLinker::loadClangModule(StringRef Filename, StringRef ModulePath,
else
sys::path::append(Path, Filename);
BinaryHolder ObjHolder(Options.Verbose);
auto &Obj =
ModuleMap.addDebugMapObject(Path, sys::TimePoint<std::chrono::seconds>());
auto &Obj = ModuleMap.addDebugMapObject(
Path, sys::TimePoint<std::chrono::seconds>(), MachO::N_OSO);
auto ErrOrObj = loadObject(ObjHolder, Obj, ModuleMap);
if (!ErrOrObj) {
// Try and emit more helpful warnings by applying some heuristics.
@ -3475,6 +3487,19 @@ bool DwarfLinker::link(const DebugMap &Map) {
if (Options.Verbose)
outs() << "DEBUG MAP OBJECT: " << Obj->getObjectFilename() << "\n";
// N_AST objects (swiftmodule files) should get dumped directly into the
// appropriate DWARF section.
if (Obj->getType() == MachO::N_AST) {
auto ErrOrMemBufferRefs = BinHolder.GetMemoryBuffersForFile(
Obj->getObjectFilename(), Obj->getTimestamp());
if (ErrOrMemBufferRefs.getError())
continue;
if (!Options.NoOutput)
Streamer->emitSwiftAST(ErrOrMemBufferRefs.get());
continue;
}
auto ErrOrObj = loadObject(BinHolder, *Obj, Map);
if (!ErrOrObj)
continue;

View File

@ -135,7 +135,8 @@ void MachODebugMapParser::switchToNewDebugMapObject(
Err.message() + "\n");
}
CurrentDebugMapObject = &Result->addDebugMapObject(Path, Timestamp);
CurrentDebugMapObject =
&Result->addDebugMapObject(Path, Timestamp, MachO::N_OSO);
loadCurrentObjectFileSymbols(*ErrOrAchObj);
}
@ -349,6 +350,13 @@ void MachODebugMapParser::handleStabSymbolTableEntry(uint32_t StringIndex,
if (Type == MachO::N_OSO)
return switchToNewDebugMapObject(Name, sys::toTimePoint(Value));
if (Type == MachO::N_AST) {
SmallString<80> Path(PathPrefix);
sys::path::append(Path, Name);
Result->addDebugMapObject(Path, sys::toTimePoint(Value), Type);
return;
}
// If the last N_OSO object file wasn't found,
// CurrentDebugMapObject will be null. Do not update anything
// until we find the next valid N_OSO entry.