From: Frederic Riss Date: Fri, 24 Jul 2015 06:41:11 +0000 (+0000) Subject: [dsymutil] Implement support for universal mach-o object files. X-Git-Url: http://plrg.eecs.uci.edu/git/?a=commitdiff_plain;h=fa7f7bd01705bb0eeae8a4b708e0022ddfb3391d;p=oota-llvm.git [dsymutil] Implement support for universal mach-o object files. This patch allows llvm-dsymutil to read universal (aka fat) macho object files and archives. The patch touches nearly everything in the BinaryHolder, but it is fairly mechinical: the methods that returned MemoryBufferRefs or ObjectFiles now return a vector of those, and the high-level access function takes a triple argument to select the architecture. There is no support yet for handling fat executables and thus no support for writing fat object files. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@243096 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/test/tools/dsymutil/ARM/fat-arch-not-found.test b/test/tools/dsymutil/ARM/fat-arch-not-found.test new file mode 100644 index 00000000000..89b518cd16f --- /dev/null +++ b/test/tools/dsymutil/ARM/fat-arch-not-found.test @@ -0,0 +1,13 @@ +# 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 + diff --git a/test/tools/dsymutil/ARM/lit.local.cfg b/test/tools/dsymutil/ARM/lit.local.cfg new file mode 100644 index 00000000000..c8625f4d9d2 --- /dev/null +++ b/test/tools/dsymutil/ARM/lit.local.cfg @@ -0,0 +1,2 @@ +if not 'X86' in config.root.targets: + config.unsupported = True diff --git a/test/tools/dsymutil/Inputs/fat-test.c b/test/tools/dsymutil/Inputs/fat-test.c new file mode 100644 index 00000000000..42c1fce1ec3 --- /dev/null +++ b/test/tools/dsymutil/Inputs/fat-test.c @@ -0,0 +1,17 @@ +/* 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 diff --git a/test/tools/dsymutil/Inputs/fat-test.o b/test/tools/dsymutil/Inputs/fat-test.o new file mode 100644 index 00000000000..8159cc74977 Binary files /dev/null and b/test/tools/dsymutil/Inputs/fat-test.o differ diff --git a/test/tools/dsymutil/Inputs/libfat-test.a b/test/tools/dsymutil/Inputs/libfat-test.a new file mode 100644 index 00000000000..6b34b0fd6f9 Binary files /dev/null and b/test/tools/dsymutil/Inputs/libfat-test.a differ diff --git a/test/tools/dsymutil/X86/fat-archive-input-i386.test b/test/tools/dsymutil/X86/fat-archive-input-i386.test new file mode 100644 index 00000000000..7f17ff48372 --- /dev/null +++ b/test/tools/dsymutil/X86/fat-archive-input-i386.test @@ -0,0 +1,16 @@ +# 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" + diff --git a/test/tools/dsymutil/X86/fat-object-input-x86_64.test b/test/tools/dsymutil/X86/fat-object-input-x86_64.test new file mode 100644 index 00000000000..489afece120 --- /dev/null +++ b/test/tools/dsymutil/X86/fat-object-input-x86_64.test @@ -0,0 +1,16 @@ +# 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" + diff --git a/test/tools/dsymutil/X86/fat-object-input-x86_64h.test b/test/tools/dsymutil/X86/fat-object-input-x86_64h.test new file mode 100644 index 00000000000..f611f5516f5 --- /dev/null +++ b/test/tools/dsymutil/X86/fat-object-input-x86_64h.test @@ -0,0 +1,16 @@ +# 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" + diff --git a/tools/dsymutil/BinaryHolder.cpp b/tools/dsymutil/BinaryHolder.cpp index 3f0c9b11260..7ff4fd69957 100644 --- a/tools/dsymutil/BinaryHolder.cpp +++ b/tools/dsymutil/BinaryHolder.cpp @@ -28,30 +28,44 @@ Triple BinaryHolder::getTriple(const object::MachOObjectFile &Obj) { return ThumbTriple.getArch() ? ThumbTriple : T; } +static std::vector +getMachOFatMemoryBuffers(StringRef Filename, MemoryBuffer &Mem, + object::MachOUniversalBinary &Fat) { + std::vector 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 &&Buf) { - CurrentArchive.reset(); - CurrentObjectFile.reset(); + CurrentArchives.clear(); + CurrentObjectFiles.clear(); + CurrentFatBinary.reset(); CurrentMemoryBuffer = std::move(Buf); } -ErrorOr -BinaryHolder::GetMemoryBufferForFile(StringRef Filename, - sys::TimeValue Timestamp) { +ErrorOr> +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 @@ -65,43 +79,64 @@ BinaryHolder::GetMemoryBufferForFile(StringRef Filename, 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{CurrentMemoryBuffer->getMemBufferRef()}; + } + + CurrentFatBinary = std::move(*ErrOrFat); + return getMachOFatMemoryBuffers(Filename, *CurrentMemoryBuffer, + *CurrentFatBinary); } -ErrorOr -BinaryHolder::GetArchiveMemberBuffer(StringRef Filename, - sys::TimeValue Timestamp) { - if (!CurrentArchive) +ErrorOr> +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 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 -BinaryHolder::MapArchiveAndGetMemberBuffer(StringRef Filename, - sys::TimeValue Timestamp) { +ErrorOr> +BinaryHolder::MapArchiveAndGetMemberBuffers(StringRef Filename, + sys::TimeValue Timestamp) { StringRef ArchiveFilename = Filename.substr(0, Filename.find('(')); auto ErrOrBuff = MemoryBuffer::getFileOrSTDIN(ArchiveFilename); @@ -112,29 +147,60 @@ BinaryHolder::MapArchiveAndGetMemberBuffer(StringRef Filename, 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 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 -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(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> +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 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); } } } diff --git a/tools/dsymutil/BinaryHolder.h b/tools/dsymutil/BinaryHolder.h index e4558580f9a..9d7b4bd8787 100644 --- a/tools/dsymutil/BinaryHolder.h +++ b/tools/dsymutil/BinaryHolder.h @@ -17,6 +17,7 @@ #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" @@ -37,77 +38,95 @@ namespace dsymutil { /// meaning that a mapping request will invalidate the previous memory /// mapping. class BinaryHolder { - std::unique_ptr CurrentArchive; + std::vector> CurrentArchives; std::unique_ptr CurrentMemoryBuffer; - std::unique_ptr CurrentObjectFile; + std::vector> CurrentObjectFiles; + std::unique_ptr 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 GetArchiveMemberBuffer(StringRef Filename, - sys::TimeValue Timestamp); + ErrorOr> + 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 - 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> + 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 GetMemoryBufferForFile(StringRef Filename, - sys::TimeValue Timestamp); + /// Multiple buffers are returned when there are multiple + /// architectures available for the requested file. + ErrorOr> + GetMemoryBuffersForFile(StringRef Filename, sys::TimeValue Timestamp); void changeBackingMemoryBuffer(std::unique_ptr &&MemBuf); + ErrorOr 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 - 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> + 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 - ErrorOr - GetFileAs(StringRef Filename, - sys::TimeValue Timestamp = sys::TimeValue::PosixZeroTime()) { - auto ErrOrObjFile = GetObjectFile(Filename); + ErrorOr> + 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(CurrentObjectFile.get())) - return *Derived; - return make_error_code(object::object_error::invalid_file_type); + + std::vector Objects; + Objects.reserve((*ErrOrObjFile).size()); + for (const auto &Obj : *ErrOrObjFile) { + const auto *Derived = dyn_cast(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 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 const ObjectFileType &GetAs() { - return cast(*CurrentObjectFile); + template + ErrorOr GetAs(const Triple &T) { + auto ErrOrObj = Get(T); + if (auto Err = ErrOrObj.getError()) + return Err; + return cast(*ErrOrObj); } static Triple getTriple(const object::MachOObjectFile &Obj); diff --git a/tools/dsymutil/DebugMap.cpp b/tools/dsymutil/DebugMap.cpp index 24dedfcb673..e29c885b5ac 100644 --- a/tools/dsymutil/DebugMap.cpp +++ b/tools/dsymutil/DebugMap.cpp @@ -178,9 +178,9 @@ SequenceTraits>>::element( void MappingTraits::mapping(IO &io, dsymutil::DebugMap &DM) { io.mapRequired("triple", DM.BinaryTriple); - io.mapOptional("objects", DM.Objects); if (void *Ctxt = io.getContext()) reinterpret_cast(Ctxt)->BinaryTriple = DM.BinaryTriple; + io.mapOptional("objects", DM.Objects); } void MappingTraits>::mapping( @@ -188,9 +188,9 @@ void MappingTraits>::mapping( if (!DM) DM.reset(new DebugMap()); io.mapRequired("triple", DM->BinaryTriple); - io.mapOptional("objects", DM->Objects); if (void *Ctxt = io.getContext()) reinterpret_cast(Ctxt)->BinaryTriple = DM->BinaryTriple; + io.mapOptional("objects", DM->Objects); } MappingTraits::YamlDMO::YamlDMO( @@ -210,11 +210,11 @@ MappingTraits::YamlDMO::denormalize(IO &IO) { StringMap 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 diff --git a/tools/dsymutil/DwarfLinker.cpp b/tools/dsymutil/DwarfLinker.cpp index ba136d1d96f..484c86aa5df 100644 --- a/tools/dsymutil/DwarfLinker.cpp +++ b/tools/dsymutil/DwarfLinker.cpp @@ -1410,6 +1410,11 @@ private: const DWARFDebugInfoEntryMinimal *DIE = nullptr) const; bool createStreamer(Triple TheTriple, StringRef OutputFilename); + + /// \brief Attempt to load a debug object from disk. + ErrorOr loadObject(BinaryHolder &BinaryHolder, + DebugMapObject &Obj, + const DebugMap &Map); /// @} private: @@ -3008,6 +3013,19 @@ void DwarfLinker::patchFrameInfoForObject(const DebugMapObject &DMO, } } +ErrorOr +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()) { @@ -3027,12 +3045,9 @@ bool DwarfLinker::link(const DebugMap &Map) { 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)) { diff --git a/tools/dsymutil/MachODebugMapParser.cpp b/tools/dsymutil/MachODebugMapParser.cpp index cda43494b9b..33554f12122 100644 --- a/tools/dsymutil/MachODebugMapParser.cpp +++ b/tools/dsymutil/MachODebugMapParser.cpp @@ -58,8 +58,8 @@ private: 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); @@ -92,27 +92,38 @@ void MachODebugMapParser::switchToNewDebugMapObject(StringRef Filename, sys::path::append(Path, Filename); auto MachOOrError = - CurrentObjectHolder.GetFileAs(Path, Timestamp); + CurrentObjectHolder.GetFilesAs(Path, Timestamp); if (auto Error = MachOOrError.getError()) { Warning(Twine("cannot open debug object \"") + Path.str() + "\": " + Error.message() + "\n"); return; } - loadCurrentObjectFileSymbols(); + auto ErrOrAchObj = + CurrentObjectHolder.GetAs(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> MachODebugMapParser::parse() { - auto MainBinOrError = MainBinaryHolder.GetFileAs(BinaryPath); + auto MainBinOrError = + MainBinaryHolder.GetFilesAs(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(BinaryHolder::getTriple(MainBinary)); MainBinaryStrings = MainBinary.getStringTableData(); for (const SymbolRef &Symbol : MainBinary.symbols()) { @@ -189,10 +200,11 @@ void MachODebugMapParser::handleStabSymbolTableEntry(uint32_t StringIndex, } /// 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 Name = Sym.getName(); if (!Name) @@ -213,9 +225,10 @@ uint64_t MachODebugMapParser::getMainBinarySymbolAddress(StringRef Name) { /// Load the interesting main binary symbols' addresses into /// MainBinarySymbolAddresses. -void MachODebugMapParser::loadMainBinarySymbols() { - const MachOObjectFile &MainBinary = MainBinaryHolder.GetAs(); +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.