--- /dev/null
+# REQUIRES: object-emission
+# RUN: llvm-dsymutil -oso-prepend-path=%p/../Inputs -y %s -o - 2>&1 | FileCheck %s
+
+---
+triple: 'armv7-apple-darwin'
+objects:
+ - filename: libfat-test.a(fat-test.o)
+ symbols:
+ - { sym: _armv7_var, objAddr: 0x0, binAddr: 0x1000, size: 0x4 }
+...
+
+# CHECK: libfat-test.a(fat-test.o): No object file for requested architecture
+
--- /dev/null
+if not 'X86' in config.root.targets:
+ config.unsupported = True
--- /dev/null
+/* Compile with:
+ clang -c -g -arch x86_64h -arch x86_64 -arch i386 fat-test.c
+ libtool -static -o libfat-test.a fat-test.o
+
+ To reduce the size of the fat .o:
+ lipo -thin i386 -o fat-test.i386.o fat-test.o
+ lipo -thin x86_64 -o fat-test.x86_64.o fat-test.o
+ lipo -thin x86_64h -o fat-test.x86_64h.o fat-test.o
+ lipo -create -arch x86_64h fat-test.x86_64h.o -arch x86_64 fat-test.x86_64.o -arch i386 fat-test.i386.o -o fat-test.o -segalign i386 8 -segalign x86_64 8 -segalign x86_64h 8
+ */
+#ifdef __x86_64h__
+int x86_64h_var;
+#elif defined(__x86_64__)
+int x86_64_var;
+#else
+int i386_var;
+#endif
--- /dev/null
+# REQUIRES: object-emission
+# RUN: llvm-dsymutil -oso-prepend-path=%p/../Inputs -y %s -o - | llvm-dwarfdump -debug-dump=info - | FileCheck %s
+
+---
+triple: 'i386-apple-darwin'
+objects:
+ - filename: libfat-test.a(fat-test.o)
+ symbols:
+ - { sym: _i386_var, objAddr: 0x0, binAddr: 0x1000, size: 0x4 }
+...
+
+# CHECK: .debug_info contents:
+# CHECK: DW_TAG_variable
+# CHECK-NOT: {{DW_TAG|NULL}}
+# CHECK: DW_AT_name{{.*}}"i386_var"
+
--- /dev/null
+# REQUIRES: object-emission
+# RUN: llvm-dsymutil -oso-prepend-path=%p/../Inputs -y %s -o - | llvm-dwarfdump -debug-dump=info - | FileCheck %s
+
+---
+triple: 'x86_64-apple-darwin'
+objects:
+ - filename: fat-test.o
+ symbols:
+ - { sym: _x86_64_var, objAddr: 0x0, binAddr: 0x1000, size: 0x4 }
+...
+
+# CHECK: .debug_info contents:
+# CHECK: DW_TAG_variable
+# CHECK-NOT: {{DW_TAG|NULL}}
+# CHECK: DW_AT_name{{.*}}"x86_64_var"
+
--- /dev/null
+# REQUIRES: object-emission
+# RUN: llvm-dsymutil -oso-prepend-path=%p/../Inputs -y %s -o - | llvm-dwarfdump -debug-dump=info - | FileCheck %s
+
+---
+triple: 'x86_64h-apple-darwin'
+objects:
+ - filename: fat-test.o
+ symbols:
+ - { sym: _x86_64h_var, objAddr: 0x0, binAddr: 0x1000, size: 0x4 }
+...
+
+# CHECK: .debug_info contents:
+# CHECK: DW_TAG_variable
+# CHECK-NOT: {{DW_TAG|NULL}}
+# CHECK: DW_AT_name{{.*}}"x86_64h_var"
+
return ThumbTriple.getArch() ? ThumbTriple : T;
}
+static std::vector<MemoryBufferRef>
+getMachOFatMemoryBuffers(StringRef Filename, MemoryBuffer &Mem,
+ object::MachOUniversalBinary &Fat) {
+ std::vector<MemoryBufferRef> Buffers;
+ StringRef FatData = Fat.getData();
+ for (auto It = Fat.begin_objects(), End = Fat.end_objects(); It != End;
+ ++It) {
+ StringRef ObjData = FatData.substr(It->getOffset(), It->getSize());
+ Buffers.emplace_back(ObjData, Filename);
+ }
+ return Buffers;
+}
+
void BinaryHolder::changeBackingMemoryBuffer(
std::unique_ptr<MemoryBuffer> &&Buf) {
- CurrentArchive.reset();
- CurrentObjectFile.reset();
+ CurrentArchives.clear();
+ CurrentObjectFiles.clear();
+ CurrentFatBinary.reset();
CurrentMemoryBuffer = std::move(Buf);
}
-ErrorOr<MemoryBufferRef>
-BinaryHolder::GetMemoryBufferForFile(StringRef Filename,
- sys::TimeValue Timestamp) {
+ErrorOr<std::vector<MemoryBufferRef>>
+BinaryHolder::GetMemoryBuffersForFile(StringRef Filename,
+ sys::TimeValue Timestamp) {
if (Verbose)
outs() << "trying to open '" << Filename << "'\n";
// Try that first as it doesn't involve any filesystem access.
- if (auto ErrOrArchiveMember = GetArchiveMemberBuffer(Filename, Timestamp))
- return *ErrOrArchiveMember;
+ if (auto ErrOrArchiveMembers = GetArchiveMemberBuffers(Filename, Timestamp))
+ return *ErrOrArchiveMembers;
// If the name ends with a closing paren, there is a huge chance
// it is an archive member specification.
if (Filename.endswith(")"))
- if (auto ErrOrArchiveMember =
- MapArchiveAndGetMemberBuffer(Filename, Timestamp))
- return *ErrOrArchiveMember;
+ if (auto ErrOrArchiveMembers =
+ MapArchiveAndGetMemberBuffers(Filename, Timestamp))
+ return *ErrOrArchiveMembers;
// Otherwise, just try opening a standard file. If this is an
// archive member specifiaction and any of the above didn't handle it
changeBackingMemoryBuffer(std::move(*ErrOrFile));
if (Verbose)
outs() << "\tloaded file.\n";
- return CurrentMemoryBuffer->getMemBufferRef();
+
+ auto ErrOrFat = object::MachOUniversalBinary::create(
+ CurrentMemoryBuffer->getMemBufferRef());
+ if (ErrOrFat.getError()) {
+ // Not a fat binary must be a standard one. Return a one element vector.
+ return std::vector<MemoryBufferRef>{CurrentMemoryBuffer->getMemBufferRef()};
+ }
+
+ CurrentFatBinary = std::move(*ErrOrFat);
+ return getMachOFatMemoryBuffers(Filename, *CurrentMemoryBuffer,
+ *CurrentFatBinary);
}
-ErrorOr<MemoryBufferRef>
-BinaryHolder::GetArchiveMemberBuffer(StringRef Filename,
- sys::TimeValue Timestamp) {
- if (!CurrentArchive)
+ErrorOr<std::vector<MemoryBufferRef>>
+BinaryHolder::GetArchiveMemberBuffers(StringRef Filename,
+ sys::TimeValue Timestamp) {
+ if (CurrentArchives.empty())
return make_error_code(errc::no_such_file_or_directory);
- StringRef CurArchiveName = CurrentArchive->getFileName();
+ StringRef CurArchiveName = CurrentArchives.front()->getFileName();
if (!Filename.startswith(Twine(CurArchiveName, "(").str()))
return make_error_code(errc::no_such_file_or_directory);
// Remove the archive name and the parens around the archive member name.
Filename = Filename.substr(CurArchiveName.size() + 1).drop_back();
- for (const auto &Child : CurrentArchive->children()) {
- if (auto NameOrErr = Child.getName())
- if (*NameOrErr == Filename) {
- if (Timestamp != sys::TimeValue::PosixZeroTime() &&
- Timestamp != Child.getLastModified()) {
+ std::vector<MemoryBufferRef> Buffers;
+ Buffers.reserve(CurrentArchives.size());
+
+ for (const auto &CurrentArchive : CurrentArchives) {
+ for (const auto &Child : CurrentArchive->children()) {
+ if (auto NameOrErr = Child.getName()) {
+ if (*NameOrErr == Filename) {
+ if (Timestamp != sys::TimeValue::PosixZeroTime() &&
+ Timestamp != Child.getLastModified()) {
+ if (Verbose)
+ outs() << "\tmember had timestamp mismatch.\n";
+ continue;
+ }
if (Verbose)
- outs() << "\tmember had timestamp mismatch.\n";
- continue;
+ outs() << "\tfound member in current archive.\n";
+ auto ErrOrMem = Child.getMemoryBufferRef();
+ if (auto Err = ErrOrMem.getError())
+ return Err;
+ Buffers.push_back(*ErrOrMem);
}
- if (Verbose)
- outs() << "\tfound member in current archive.\n";
- return Child.getMemoryBufferRef();
}
+ }
}
- return make_error_code(errc::no_such_file_or_directory);
+ if (Buffers.empty())
+ return make_error_code(errc::no_such_file_or_directory);
+ return Buffers;
}
-ErrorOr<MemoryBufferRef>
-BinaryHolder::MapArchiveAndGetMemberBuffer(StringRef Filename,
- sys::TimeValue Timestamp) {
+ErrorOr<std::vector<MemoryBufferRef>>
+BinaryHolder::MapArchiveAndGetMemberBuffers(StringRef Filename,
+ sys::TimeValue Timestamp) {
StringRef ArchiveFilename = Filename.substr(0, Filename.find('('));
auto ErrOrBuff = MemoryBuffer::getFileOrSTDIN(ArchiveFilename);
outs() << "\topened new archive '" << ArchiveFilename << "'\n";
changeBackingMemoryBuffer(std::move(*ErrOrBuff));
- auto ErrOrArchive =
- object::Archive::create(CurrentMemoryBuffer->getMemBufferRef());
- if (auto Err = ErrOrArchive.getError())
- return Err;
-
- CurrentArchive = std::move(*ErrOrArchive);
+ std::vector<MemoryBufferRef> ArchiveBuffers;
+ auto ErrOrFat = object::MachOUniversalBinary::create(
+ CurrentMemoryBuffer->getMemBufferRef());
+ if (ErrOrFat.getError()) {
+ // Not a fat binary must be a standard one.
+ ArchiveBuffers.push_back(CurrentMemoryBuffer->getMemBufferRef());
+ } else {
+ CurrentFatBinary = std::move(*ErrOrFat);
+ ArchiveBuffers = getMachOFatMemoryBuffers(
+ ArchiveFilename, *CurrentMemoryBuffer, *CurrentFatBinary);
+ }
- return GetArchiveMemberBuffer(Filename, Timestamp);
+ for (auto MemRef : ArchiveBuffers) {
+ auto ErrOrArchive = object::Archive::create(MemRef);
+ if (auto Err = ErrOrArchive.getError())
+ return Err;
+ CurrentArchives.push_back(std::move(*ErrOrArchive));
+ }
+ return GetArchiveMemberBuffers(Filename, Timestamp);
}
ErrorOr<const object::ObjectFile &>
-BinaryHolder::GetObjectFile(StringRef Filename, sys::TimeValue Timestamp) {
- auto ErrOrMemBufferRef = GetMemoryBufferForFile(Filename, Timestamp);
- if (auto Err = ErrOrMemBufferRef.getError())
- return Err;
+BinaryHolder::getObjfileForArch(const Triple &T) {
+ for (const auto &Obj : CurrentObjectFiles) {
+ if (const auto *MachO = dyn_cast<object::MachOObjectFile>(Obj.get())) {
+ if (getTriple(*MachO).str() == T.str())
+ return *MachO;
+ } else if (Obj->getArch() == T.getArch())
+ return *Obj;
+ }
+
+ return make_error_code(object::object_error::arch_not_found);
+}
- auto ErrOrObjectFile =
- object::ObjectFile::createObjectFile(*ErrOrMemBufferRef);
- if (auto Err = ErrOrObjectFile.getError())
+ErrorOr<std::vector<const object::ObjectFile *>>
+BinaryHolder::GetObjectFiles(StringRef Filename, sys::TimeValue Timestamp) {
+ auto ErrOrMemBufferRefs = GetMemoryBuffersForFile(Filename, Timestamp);
+ if (auto Err = ErrOrMemBufferRefs.getError())
return Err;
- CurrentObjectFile = std::move(*ErrOrObjectFile);
- return *CurrentObjectFile;
+ std::vector<const object::ObjectFile *> Objects;
+ Objects.reserve(ErrOrMemBufferRefs->size());
+
+ CurrentObjectFiles.clear();
+ for (auto MemBuf : *ErrOrMemBufferRefs) {
+ auto ErrOrObjectFile = object::ObjectFile::createObjectFile(MemBuf);
+ if (auto Err = ErrOrObjectFile.getError())
+ return Err;
+
+ Objects.push_back(ErrOrObjectFile->get());
+ CurrentObjectFiles.push_back(std::move(*ErrOrObjectFile));
+ }
+
+ return std::move(Objects);
}
}
}
#include "llvm/ADT/Triple.h"
#include "llvm/Object/Archive.h"
#include "llvm/Object/Error.h"
+#include "llvm/Object/MachOUniversal.h"
#include "llvm/Object/ObjectFile.h"
#include "llvm/Support/Errc.h"
#include "llvm/Support/ErrorOr.h"
/// meaning that a mapping request will invalidate the previous memory
/// mapping.
class BinaryHolder {
- std::unique_ptr<object::Archive> CurrentArchive;
+ std::vector<std::unique_ptr<object::Archive>> CurrentArchives;
std::unique_ptr<MemoryBuffer> CurrentMemoryBuffer;
- std::unique_ptr<object::ObjectFile> CurrentObjectFile;
+ std::vector<std::unique_ptr<object::ObjectFile>> CurrentObjectFiles;
+ std::unique_ptr<object::MachOUniversalBinary> CurrentFatBinary;
bool Verbose;
- /// \brief Get the MemoryBufferRef for the file specification in \p
- /// Filename from the current archive.
+ /// Get the MemoryBufferRefs for the file specification in \p
+ /// Filename from the current archive. Multiple buffers are returned
+ /// when there are multiple architectures available for the
+ /// requested file.
///
/// This function performs no system calls, it just looks up a
/// potential match for the given \p Filename in the currently
/// mapped archive if there is one.
- ErrorOr<MemoryBufferRef> GetArchiveMemberBuffer(StringRef Filename,
- sys::TimeValue Timestamp);
+ ErrorOr<std::vector<MemoryBufferRef>>
+ GetArchiveMemberBuffers(StringRef Filename, sys::TimeValue Timestamp);
- /// \brief Interpret Filename as an archive member specification,
- /// map the corresponding archive to memory and return the
- /// MemoryBufferRef corresponding to the described member.
- ErrorOr<MemoryBufferRef>
- MapArchiveAndGetMemberBuffer(StringRef Filename, sys::TimeValue Timestamp);
+ /// Interpret Filename as an archive member specification map the
+ /// corresponding archive to memory and return the MemoryBufferRefs
+ /// corresponding to the described member. Multiple buffers are
+ /// returned when there are multiple architectures available for the
+ /// requested file.
+ ErrorOr<std::vector<MemoryBufferRef>>
+ MapArchiveAndGetMemberBuffers(StringRef Filename, sys::TimeValue Timestamp);
- /// \brief 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).
+ /// 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).
///
- /// The returned MemoryBufferRef points to a buffer owned by this
+ /// The returned MemoryBufferRefs points to a buffer owned by this
/// object. The buffer is valid until the next call to
/// GetMemoryBufferForFile() on this object.
- ErrorOr<MemoryBufferRef> GetMemoryBufferForFile(StringRef Filename,
- sys::TimeValue Timestamp);
+ /// Multiple buffers are returned when there are multiple
+ /// architectures available for the requested file.
+ ErrorOr<std::vector<MemoryBufferRef>>
+ GetMemoryBuffersForFile(StringRef Filename, sys::TimeValue Timestamp);
void changeBackingMemoryBuffer(std::unique_ptr<MemoryBuffer> &&MemBuf);
+ ErrorOr<const object::ObjectFile &> getObjfileForArch(const Triple &T);
public:
BinaryHolder(bool Verbose) : Verbose(Verbose) {}
- /// \brief Get the ObjectFile designated by the \p Filename. This
+ /// Get the ObjectFiles designated by the \p Filename. This
/// might be an archive member specification of the form
/// /path/to/archive.a(member.o).
///
/// Calling this function invalidates the previous mapping owned by
- /// the BinaryHolder.
- ErrorOr<const object::ObjectFile &>
- GetObjectFile(StringRef Filename,
- sys::TimeValue Timestamp = sys::TimeValue::PosixZeroTime());
+ /// the BinaryHolder. Multiple buffers are returned when there are
+ /// multiple architectures available for the requested file.
+ ErrorOr<std::vector<const object::ObjectFile *>>
+ GetObjectFiles(StringRef Filename,
+ sys::TimeValue Timestamp = sys::TimeValue::PosixZeroTime());
- /// \brief Wraps GetObjectFile() to return a derived ObjectFile type.
+ /// Wraps GetObjectFiles() to return a derived ObjectFile type.
template <typename ObjectFileType>
- ErrorOr<const ObjectFileType &>
- GetFileAs(StringRef Filename,
- sys::TimeValue Timestamp = sys::TimeValue::PosixZeroTime()) {
- auto ErrOrObjFile = GetObjectFile(Filename);
+ ErrorOr<std::vector<const ObjectFileType *>>
+ GetFilesAs(StringRef Filename,
+ sys::TimeValue Timestamp = sys::TimeValue::PosixZeroTime()) {
+ auto ErrOrObjFile = GetObjectFiles(Filename, Timestamp);
if (auto Err = ErrOrObjFile.getError())
return Err;
- if (const auto *Derived = dyn_cast<ObjectFileType>(CurrentObjectFile.get()))
- return *Derived;
- return make_error_code(object::object_error::invalid_file_type);
+
+ std::vector<const ObjectFileType *> Objects;
+ Objects.reserve((*ErrOrObjFile).size());
+ for (const auto &Obj : *ErrOrObjFile) {
+ const auto *Derived = dyn_cast<ObjectFileType>(Obj);
+ if (!Derived)
+ return make_error_code(object::object_error::invalid_file_type);
+ Objects.push_back(Derived);
+ }
+ return std::move(Objects);
}
- /// \brief Access the currently owned ObjectFile. As successfull
- /// call to GetObjectFile() or GetFileAs() must have been performed
- /// before calling this.
- const object::ObjectFile &Get() {
- assert(CurrentObjectFile);
- return *CurrentObjectFile;
+ /// Access the currently owned ObjectFile with architecture \p T. As
+ /// successfull call to GetObjectFiles() or GetFilesAs() must have
+ /// been performed before calling this.
+ ErrorOr<const object::ObjectFile &> Get(const Triple &T) {
+ return getObjfileForArch(T);
}
- /// \brief Access to a derived version of the currently owned
+ /// Access to a derived version of the currently owned
/// ObjectFile. The conversion must be known to be valid.
- template <typename ObjectFileType> const ObjectFileType &GetAs() {
- return cast<ObjectFileType>(*CurrentObjectFile);
+ template <typename ObjectFileType>
+ ErrorOr<const ObjectFileType &> GetAs(const Triple &T) {
+ auto ErrOrObj = Get(T);
+ if (auto Err = ErrOrObj.getError())
+ return Err;
+ return cast<ObjectFileType>(*ErrOrObj);
}
static Triple getTriple(const object::MachOObjectFile &Obj);
void MappingTraits<dsymutil::DebugMap>::mapping(IO &io,
dsymutil::DebugMap &DM) {
io.mapRequired("triple", DM.BinaryTriple);
- io.mapOptional("objects", DM.Objects);
if (void *Ctxt = io.getContext())
reinterpret_cast<YAMLContext *>(Ctxt)->BinaryTriple = DM.BinaryTriple;
+ io.mapOptional("objects", DM.Objects);
}
void MappingTraits<std::unique_ptr<dsymutil::DebugMap>>::mapping(
if (!DM)
DM.reset(new DebugMap());
io.mapRequired("triple", DM->BinaryTriple);
- io.mapOptional("objects", DM->Objects);
if (void *Ctxt = io.getContext())
reinterpret_cast<YAMLContext *>(Ctxt)->BinaryTriple = DM->BinaryTriple;
+ io.mapOptional("objects", DM->Objects);
}
MappingTraits<dsymutil::DebugMapObject>::YamlDMO::YamlDMO(
StringMap<uint64_t> SymbolAddresses;
sys::path::append(Path, Filename);
- auto ErrOrObjectFile = BinHolder.GetObjectFile(Path);
- if (auto EC = ErrOrObjectFile.getError()) {
+ auto ErrOrObjectFiles = BinHolder.GetObjectFiles(Path);
+ if (auto EC = ErrOrObjectFiles.getError()) {
llvm::errs() << "warning: Unable to open " << Path << " " << EC.message()
<< '\n';
- } else {
+ } else if (auto ErrOrObjectFile = BinHolder.Get(Ctxt.BinaryTriple)) {
// Rewrite the object file symbol addresses in the debug map. The
// YAML input is mainly used to test llvm-dsymutil without
// requiring binaries checked-in. If we generate the object files
const DWARFDebugInfoEntryMinimal *DIE = nullptr) const;
bool createStreamer(Triple TheTriple, StringRef OutputFilename);
+
+ /// \brief Attempt to load a debug object from disk.
+ ErrorOr<const object::ObjectFile &> loadObject(BinaryHolder &BinaryHolder,
+ DebugMapObject &Obj,
+ const DebugMap &Map);
/// @}
private:
}
}
+ErrorOr<const object::ObjectFile &>
+DwarfLinker::loadObject(BinaryHolder &BinaryHolder, DebugMapObject &Obj,
+ const DebugMap &Map) {
+ auto ErrOrObjs =
+ BinaryHolder.GetObjectFiles(Obj.getObjectFilename(), Obj.getTimestamp());
+ if (std::error_code EC = ErrOrObjs.getError())
+ reportWarning(Twine(Obj.getObjectFilename()) + ": " + EC.message());
+ auto ErrOrObj = BinaryHolder.Get(Map.getTriple());
+ if (std::error_code EC = ErrOrObj.getError())
+ reportWarning(Twine(Obj.getObjectFilename()) + ": " + EC.message());
+ return ErrOrObj;
+}
+
bool DwarfLinker::link(const DebugMap &Map) {
if (Map.begin() == Map.end()) {
if (Options.Verbose)
outs() << "DEBUG MAP OBJECT: " << Obj->getObjectFilename() << "\n";
- auto ErrOrObj =
- BinHolder.GetObjectFile(Obj->getObjectFilename(), Obj->getTimestamp());
- if (std::error_code EC = ErrOrObj.getError()) {
- reportWarning(Twine(Obj->getObjectFilename()) + ": " + EC.message());
+ auto ErrOrObj = loadObject(BinHolder, *Obj, Map);
+ if (!ErrOrObj)
continue;
- }
// Look for relocations that correspond to debug map entries.
if (!findValidRelocsInDebugInfo(*ErrOrObj, *Obj)) {
void switchToNewDebugMapObject(StringRef Filename, sys::TimeValue Timestamp);
void resetParserState();
uint64_t getMainBinarySymbolAddress(StringRef Name);
- void loadMainBinarySymbols();
- void loadCurrentObjectFileSymbols();
+ void loadMainBinarySymbols(const MachOObjectFile &MainBinary);
+ void loadCurrentObjectFileSymbols(const object::MachOObjectFile &Obj);
void handleStabSymbolTableEntry(uint32_t StringIndex, uint8_t Type,
uint8_t SectionIndex, uint16_t Flags,
uint64_t Value);
sys::path::append(Path, Filename);
auto MachOOrError =
- CurrentObjectHolder.GetFileAs<MachOObjectFile>(Path, Timestamp);
+ CurrentObjectHolder.GetFilesAs<MachOObjectFile>(Path, Timestamp);
if (auto Error = MachOOrError.getError()) {
Warning(Twine("cannot open debug object \"") + Path.str() + "\": " +
Error.message() + "\n");
return;
}
- loadCurrentObjectFileSymbols();
+ auto ErrOrAchObj =
+ CurrentObjectHolder.GetAs<MachOObjectFile>(Result->getTriple());
+ if (auto Err = ErrOrAchObj.getError()) {
+ return Warning(Twine("cannot open debug object \"") + Path.str() + "\": " +
+ Err.message() + "\n");
+ }
+
CurrentDebugMapObject = &Result->addDebugMapObject(Path, Timestamp);
+ loadCurrentObjectFileSymbols(*ErrOrAchObj);
}
/// This main parsing routine tries to open the main binary and if
/// successful iterates over the STAB entries. The real parsing is
/// done in handleStabSymbolTableEntry.
ErrorOr<std::unique_ptr<DebugMap>> MachODebugMapParser::parse() {
- auto MainBinOrError = MainBinaryHolder.GetFileAs<MachOObjectFile>(BinaryPath);
+ auto MainBinOrError =
+ MainBinaryHolder.GetFilesAs<MachOObjectFile>(BinaryPath);
if (auto Error = MainBinOrError.getError())
return Error;
- const MachOObjectFile &MainBinary = *MainBinOrError;
- loadMainBinarySymbols();
+ if (MainBinOrError->size() != 1)
+ return make_error_code(object::object_error::invalid_file_type);
+
+ const MachOObjectFile &MainBinary = *MainBinOrError->front();
+ loadMainBinarySymbols(MainBinary);
Result = make_unique<DebugMap>(BinaryHolder::getTriple(MainBinary));
MainBinaryStrings = MainBinary.getStringTableData();
for (const SymbolRef &Symbol : MainBinary.symbols()) {
}
/// Load the current object file symbols into CurrentObjectAddresses.
-void MachODebugMapParser::loadCurrentObjectFileSymbols() {
+void MachODebugMapParser::loadCurrentObjectFileSymbols(
+ const object::MachOObjectFile &Obj) {
CurrentObjectAddresses.clear();
- for (auto Sym : CurrentObjectHolder.Get().symbols()) {
+ for (auto Sym : Obj.symbols()) {
uint64_t Addr = Sym.getValue();
ErrorOr<StringRef> Name = Sym.getName();
if (!Name)
/// Load the interesting main binary symbols' addresses into
/// MainBinarySymbolAddresses.
-void MachODebugMapParser::loadMainBinarySymbols() {
- const MachOObjectFile &MainBinary = MainBinaryHolder.GetAs<MachOObjectFile>();
+void MachODebugMapParser::loadMainBinarySymbols(
+ const MachOObjectFile &MainBinary) {
section_iterator Section = MainBinary.section_end();
+ MainBinarySymbolAddresses.clear();
for (const auto &Sym : MainBinary.symbols()) {
SymbolRef::Type Type = Sym.getType();
// Skip undefined and STAB entries.