aboutsummaryrefslogtreecommitdiffstats
path: root/contrib/libs/llvm12/tools/dsymutil
diff options
context:
space:
mode:
authororivej <orivej@yandex-team.ru>2022-02-10 16:44:49 +0300
committerDaniil Cherednik <dcherednik@yandex-team.ru>2022-02-10 16:44:49 +0300
commit718c552901d703c502ccbefdfc3c9028d608b947 (patch)
tree46534a98bbefcd7b1f3faa5b52c138ab27db75b7 /contrib/libs/llvm12/tools/dsymutil
parente9656aae26e0358d5378e5b63dcac5c8dbe0e4d0 (diff)
downloadydb-718c552901d703c502ccbefdfc3c9028d608b947.tar.gz
Restoring authorship annotation for <orivej@yandex-team.ru>. Commit 1 of 2.
Diffstat (limited to 'contrib/libs/llvm12/tools/dsymutil')
-rw-r--r--contrib/libs/llvm12/tools/dsymutil/BinaryHolder.cpp526
-rw-r--r--contrib/libs/llvm12/tools/dsymutil/BinaryHolder.h342
-rw-r--r--contrib/libs/llvm12/tools/dsymutil/CFBundle.cpp370
-rw-r--r--contrib/libs/llvm12/tools/dsymutil/CFBundle.h60
-rw-r--r--contrib/libs/llvm12/tools/dsymutil/DebugMap.cpp586
-rw-r--r--contrib/libs/llvm12/tools/dsymutil/DebugMap.h544
-rw-r--r--contrib/libs/llvm12/tools/dsymutil/DwarfLinkerForBinary.cpp1320
-rw-r--r--contrib/libs/llvm12/tools/dsymutil/DwarfLinkerForBinary.h368
-rw-r--r--contrib/libs/llvm12/tools/dsymutil/LinkUtils.h214
-rw-r--r--contrib/libs/llvm12/tools/dsymutil/MachODebugMapParser.cpp1216
-rw-r--r--contrib/libs/llvm12/tools/dsymutil/MachOUtils.cpp1122
-rw-r--r--contrib/libs/llvm12/tools/dsymutil/MachOUtils.h104
-rw-r--r--contrib/libs/llvm12/tools/dsymutil/Options.td374
-rw-r--r--contrib/libs/llvm12/tools/dsymutil/Reproducer.cpp170
-rw-r--r--contrib/libs/llvm12/tools/dsymutil/Reproducer.h154
-rw-r--r--contrib/libs/llvm12/tools/dsymutil/SymbolMap.cpp320
-rw-r--r--contrib/libs/llvm12/tools/dsymutil/SymbolMap.h106
-rw-r--r--contrib/libs/llvm12/tools/dsymutil/dsymutil.cpp1378
-rw-r--r--contrib/libs/llvm12/tools/dsymutil/dsymutil.h112
-rw-r--r--contrib/libs/llvm12/tools/dsymutil/ya.make58
20 files changed, 4722 insertions, 4722 deletions
diff --git a/contrib/libs/llvm12/tools/dsymutil/BinaryHolder.cpp b/contrib/libs/llvm12/tools/dsymutil/BinaryHolder.cpp
index f83521346c..6a90549be5 100644
--- a/contrib/libs/llvm12/tools/dsymutil/BinaryHolder.cpp
+++ b/contrib/libs/llvm12/tools/dsymutil/BinaryHolder.cpp
@@ -1,101 +1,101 @@
-//===-- BinaryHolder.cpp --------------------------------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-//
-// This program is a utility that aims to be a dropin replacement for
-// Darwin's dsymutil.
-//
-//===----------------------------------------------------------------------===//
-
-#include "BinaryHolder.h"
-#include "llvm/Object/MachO.h"
-#include "llvm/Support/WithColor.h"
-#include "llvm/Support/raw_ostream.h"
-
-namespace llvm {
-namespace dsymutil {
-
-static std::pair<StringRef, StringRef>
-getArchiveAndObjectName(StringRef Filename) {
- StringRef Archive = Filename.substr(0, Filename.rfind('('));
- StringRef Object = Filename.substr(Archive.size() + 1).drop_back();
- return {Archive, Object};
-}
-
-static bool isArchive(StringRef Filename) { return Filename.endswith(")"); }
-
-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;
-}
-
-Error BinaryHolder::ArchiveEntry::load(IntrusiveRefCntPtr<vfs::FileSystem> VFS,
- StringRef Filename,
- TimestampTy Timestamp, bool Verbose) {
- StringRef ArchiveFilename = getArchiveAndObjectName(Filename).first;
-
- // Try to load archive and force it to be memory mapped.
- auto ErrOrBuff = (ArchiveFilename == "-")
- ? MemoryBuffer::getSTDIN()
- : VFS->getBufferForFile(ArchiveFilename, -1, false);
- if (auto Err = ErrOrBuff.getError())
- return errorCodeToError(Err);
-
- MemBuffer = std::move(*ErrOrBuff);
-
- if (Verbose)
- WithColor::note() << "loaded archive '" << ArchiveFilename << "'\n";
-
- // Load one or more archive buffers, depending on whether we're dealing with
- // a fat binary.
- std::vector<MemoryBufferRef> ArchiveBuffers;
-
- auto ErrOrFat =
- object::MachOUniversalBinary::create(MemBuffer->getMemBufferRef());
- if (!ErrOrFat) {
- consumeError(ErrOrFat.takeError());
- ArchiveBuffers.push_back(MemBuffer->getMemBufferRef());
- } else {
- FatBinary = std::move(*ErrOrFat);
- FatBinaryName = std::string(ArchiveFilename);
- ArchiveBuffers =
- getMachOFatMemoryBuffers(FatBinaryName, *MemBuffer, *FatBinary);
- }
-
- // Finally, try to load the archives.
- Archives.reserve(ArchiveBuffers.size());
- for (auto MemRef : ArchiveBuffers) {
- auto ErrOrArchive = object::Archive::create(MemRef);
- if (!ErrOrArchive)
- return ErrOrArchive.takeError();
- Archives.push_back(std::move(*ErrOrArchive));
- }
-
- return Error::success();
-}
-
-Error BinaryHolder::ObjectEntry::load(IntrusiveRefCntPtr<vfs::FileSystem> VFS,
+//===-- BinaryHolder.cpp --------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This program is a utility that aims to be a dropin replacement for
+// Darwin's dsymutil.
+//
+//===----------------------------------------------------------------------===//
+
+#include "BinaryHolder.h"
+#include "llvm/Object/MachO.h"
+#include "llvm/Support/WithColor.h"
+#include "llvm/Support/raw_ostream.h"
+
+namespace llvm {
+namespace dsymutil {
+
+static std::pair<StringRef, StringRef>
+getArchiveAndObjectName(StringRef Filename) {
+ StringRef Archive = Filename.substr(0, Filename.rfind('('));
+ StringRef Object = Filename.substr(Archive.size() + 1).drop_back();
+ return {Archive, Object};
+}
+
+static bool isArchive(StringRef Filename) { return Filename.endswith(")"); }
+
+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;
+}
+
+Error BinaryHolder::ArchiveEntry::load(IntrusiveRefCntPtr<vfs::FileSystem> VFS,
+ StringRef Filename,
+ TimestampTy Timestamp, bool Verbose) {
+ StringRef ArchiveFilename = getArchiveAndObjectName(Filename).first;
+
+ // Try to load archive and force it to be memory mapped.
+ auto ErrOrBuff = (ArchiveFilename == "-")
+ ? MemoryBuffer::getSTDIN()
+ : VFS->getBufferForFile(ArchiveFilename, -1, false);
+ if (auto Err = ErrOrBuff.getError())
+ return errorCodeToError(Err);
+
+ MemBuffer = std::move(*ErrOrBuff);
+
+ if (Verbose)
+ WithColor::note() << "loaded archive '" << ArchiveFilename << "'\n";
+
+ // Load one or more archive buffers, depending on whether we're dealing with
+ // a fat binary.
+ std::vector<MemoryBufferRef> ArchiveBuffers;
+
+ auto ErrOrFat =
+ object::MachOUniversalBinary::create(MemBuffer->getMemBufferRef());
+ if (!ErrOrFat) {
+ consumeError(ErrOrFat.takeError());
+ ArchiveBuffers.push_back(MemBuffer->getMemBufferRef());
+ } else {
+ FatBinary = std::move(*ErrOrFat);
+ FatBinaryName = std::string(ArchiveFilename);
+ ArchiveBuffers =
+ getMachOFatMemoryBuffers(FatBinaryName, *MemBuffer, *FatBinary);
+ }
+
+ // Finally, try to load the archives.
+ Archives.reserve(ArchiveBuffers.size());
+ for (auto MemRef : ArchiveBuffers) {
+ auto ErrOrArchive = object::Archive::create(MemRef);
+ if (!ErrOrArchive)
+ return ErrOrArchive.takeError();
+ Archives.push_back(std::move(*ErrOrArchive));
+ }
+
+ return Error::success();
+}
+
+Error BinaryHolder::ObjectEntry::load(IntrusiveRefCntPtr<vfs::FileSystem> VFS,
StringRef Filename, TimestampTy Timestamp,
bool Verbose) {
- // Try to load regular binary and force it to be memory mapped.
- auto ErrOrBuff = (Filename == "-")
- ? MemoryBuffer::getSTDIN()
- : VFS->getBufferForFile(Filename, -1, false);
- if (auto Err = ErrOrBuff.getError())
- return errorCodeToError(Err);
-
+ // Try to load regular binary and force it to be memory mapped.
+ auto ErrOrBuff = (Filename == "-")
+ ? MemoryBuffer::getSTDIN()
+ : VFS->getBufferForFile(Filename, -1, false);
+ if (auto Err = ErrOrBuff.getError())
+ return errorCodeToError(Err);
+
if (Filename != "-" && Timestamp != sys::TimePoint<>()) {
llvm::ErrorOr<vfs::Status> Stat = VFS->status(Filename);
if (!Stat)
@@ -108,178 +108,178 @@ Error BinaryHolder::ObjectEntry::load(IntrusiveRefCntPtr<vfs::FileSystem> VFS,
<< ") and debug map (" << Timestamp << ")\n";
}
- MemBuffer = std::move(*ErrOrBuff);
-
- if (Verbose)
- WithColor::note() << "loaded object.\n";
-
- // Load one or more object buffers, depending on whether we're dealing with a
- // fat binary.
- std::vector<MemoryBufferRef> ObjectBuffers;
-
- auto ErrOrFat =
- object::MachOUniversalBinary::create(MemBuffer->getMemBufferRef());
- if (!ErrOrFat) {
- consumeError(ErrOrFat.takeError());
- ObjectBuffers.push_back(MemBuffer->getMemBufferRef());
- } else {
- FatBinary = std::move(*ErrOrFat);
- FatBinaryName = std::string(Filename);
- ObjectBuffers =
- getMachOFatMemoryBuffers(FatBinaryName, *MemBuffer, *FatBinary);
- }
-
- Objects.reserve(ObjectBuffers.size());
- for (auto MemRef : ObjectBuffers) {
- auto ErrOrObjectFile = object::ObjectFile::createObjectFile(MemRef);
- if (!ErrOrObjectFile)
- return ErrOrObjectFile.takeError();
- Objects.push_back(std::move(*ErrOrObjectFile));
- }
-
- return Error::success();
-}
-
-std::vector<const object::ObjectFile *>
-BinaryHolder::ObjectEntry::getObjects() const {
- std::vector<const object::ObjectFile *> Result;
- Result.reserve(Objects.size());
- for (auto &Object : Objects) {
- Result.push_back(Object.get());
- }
- return Result;
-}
-Expected<const object::ObjectFile &>
-BinaryHolder::ObjectEntry::getObject(const Triple &T) const {
- for (const auto &Obj : Objects) {
- if (const auto *MachO = dyn_cast<object::MachOObjectFile>(Obj.get())) {
- if (MachO->getArchTriple().str() == T.str())
- return *MachO;
- } else if (Obj->getArch() == T.getArch())
- return *Obj;
- }
- return errorCodeToError(object::object_error::arch_not_found);
-}
-
-Expected<const BinaryHolder::ObjectEntry &>
-BinaryHolder::ArchiveEntry::getObjectEntry(StringRef Filename,
- TimestampTy Timestamp,
- bool Verbose) {
- StringRef ArchiveFilename;
- StringRef ObjectFilename;
- std::tie(ArchiveFilename, ObjectFilename) = getArchiveAndObjectName(Filename);
-
- // Try the cache first.
- KeyTy Key = {ObjectFilename, Timestamp};
-
- {
- std::lock_guard<std::mutex> Lock(MemberCacheMutex);
- if (MemberCache.count(Key))
- return MemberCache[Key];
- }
-
- // Create a new ObjectEntry, but don't add it to the cache yet. Loading of
- // the archive members might fail and we don't want to lock the whole archive
- // during this operation.
- ObjectEntry OE;
-
- for (const auto &Archive : Archives) {
- Error Err = Error::success();
- for (auto Child : Archive->children(Err)) {
- if (auto NameOrErr = Child.getName()) {
- if (*NameOrErr == ObjectFilename) {
- auto ModTimeOrErr = Child.getLastModified();
- if (!ModTimeOrErr)
- return ModTimeOrErr.takeError();
-
- if (Timestamp != sys::TimePoint<>() &&
+ MemBuffer = std::move(*ErrOrBuff);
+
+ if (Verbose)
+ WithColor::note() << "loaded object.\n";
+
+ // Load one or more object buffers, depending on whether we're dealing with a
+ // fat binary.
+ std::vector<MemoryBufferRef> ObjectBuffers;
+
+ auto ErrOrFat =
+ object::MachOUniversalBinary::create(MemBuffer->getMemBufferRef());
+ if (!ErrOrFat) {
+ consumeError(ErrOrFat.takeError());
+ ObjectBuffers.push_back(MemBuffer->getMemBufferRef());
+ } else {
+ FatBinary = std::move(*ErrOrFat);
+ FatBinaryName = std::string(Filename);
+ ObjectBuffers =
+ getMachOFatMemoryBuffers(FatBinaryName, *MemBuffer, *FatBinary);
+ }
+
+ Objects.reserve(ObjectBuffers.size());
+ for (auto MemRef : ObjectBuffers) {
+ auto ErrOrObjectFile = object::ObjectFile::createObjectFile(MemRef);
+ if (!ErrOrObjectFile)
+ return ErrOrObjectFile.takeError();
+ Objects.push_back(std::move(*ErrOrObjectFile));
+ }
+
+ return Error::success();
+}
+
+std::vector<const object::ObjectFile *>
+BinaryHolder::ObjectEntry::getObjects() const {
+ std::vector<const object::ObjectFile *> Result;
+ Result.reserve(Objects.size());
+ for (auto &Object : Objects) {
+ Result.push_back(Object.get());
+ }
+ return Result;
+}
+Expected<const object::ObjectFile &>
+BinaryHolder::ObjectEntry::getObject(const Triple &T) const {
+ for (const auto &Obj : Objects) {
+ if (const auto *MachO = dyn_cast<object::MachOObjectFile>(Obj.get())) {
+ if (MachO->getArchTriple().str() == T.str())
+ return *MachO;
+ } else if (Obj->getArch() == T.getArch())
+ return *Obj;
+ }
+ return errorCodeToError(object::object_error::arch_not_found);
+}
+
+Expected<const BinaryHolder::ObjectEntry &>
+BinaryHolder::ArchiveEntry::getObjectEntry(StringRef Filename,
+ TimestampTy Timestamp,
+ bool Verbose) {
+ StringRef ArchiveFilename;
+ StringRef ObjectFilename;
+ std::tie(ArchiveFilename, ObjectFilename) = getArchiveAndObjectName(Filename);
+
+ // Try the cache first.
+ KeyTy Key = {ObjectFilename, Timestamp};
+
+ {
+ std::lock_guard<std::mutex> Lock(MemberCacheMutex);
+ if (MemberCache.count(Key))
+ return MemberCache[Key];
+ }
+
+ // Create a new ObjectEntry, but don't add it to the cache yet. Loading of
+ // the archive members might fail and we don't want to lock the whole archive
+ // during this operation.
+ ObjectEntry OE;
+
+ for (const auto &Archive : Archives) {
+ Error Err = Error::success();
+ for (auto Child : Archive->children(Err)) {
+ if (auto NameOrErr = Child.getName()) {
+ if (*NameOrErr == ObjectFilename) {
+ auto ModTimeOrErr = Child.getLastModified();
+ if (!ModTimeOrErr)
+ return ModTimeOrErr.takeError();
+
+ if (Timestamp != sys::TimePoint<>() &&
Timestamp != std::chrono::time_point_cast<std::chrono::seconds>(
ModTimeOrErr.get())) {
- if (Verbose)
+ if (Verbose)
WithColor::warning()
<< *NameOrErr
<< ": timestamp mismatch between archive member ("
<< ModTimeOrErr.get() << ") and debug map (" << Timestamp
<< ")\n";
- continue;
- }
-
- if (Verbose)
- WithColor::note() << "found member in archive.\n";
-
- auto ErrOrMem = Child.getMemoryBufferRef();
- if (!ErrOrMem)
- return ErrOrMem.takeError();
-
- auto ErrOrObjectFile =
- object::ObjectFile::createObjectFile(*ErrOrMem);
- if (!ErrOrObjectFile)
- return ErrOrObjectFile.takeError();
-
- OE.Objects.push_back(std::move(*ErrOrObjectFile));
- }
- }
- }
- if (Err)
- return std::move(Err);
- }
-
- if (OE.Objects.empty())
- return errorCodeToError(errc::no_such_file_or_directory);
-
- std::lock_guard<std::mutex> Lock(MemberCacheMutex);
- MemberCache.try_emplace(Key, std::move(OE));
- return MemberCache[Key];
-}
-
-Expected<const BinaryHolder::ObjectEntry &>
-BinaryHolder::getObjectEntry(StringRef Filename, TimestampTy Timestamp) {
- if (Verbose)
- WithColor::note() << "trying to open '" << Filename << "'\n";
-
- // If this is an archive, we might have either the object or the archive
- // cached. In this case we can load it without accessing the file system.
- if (isArchive(Filename)) {
- StringRef ArchiveFilename = getArchiveAndObjectName(Filename).first;
- std::lock_guard<std::mutex> Lock(ArchiveCacheMutex);
- if (ArchiveCache.count(ArchiveFilename)) {
- return ArchiveCache[ArchiveFilename].getObjectEntry(Filename, Timestamp,
- Verbose);
- } else {
- ArchiveEntry &AE = ArchiveCache[ArchiveFilename];
- auto Err = AE.load(VFS, Filename, Timestamp, Verbose);
- if (Err) {
- ArchiveCache.erase(ArchiveFilename);
- // Don't return the error here: maybe the file wasn't an archive.
- llvm::consumeError(std::move(Err));
- } else {
- return ArchiveCache[ArchiveFilename].getObjectEntry(Filename, Timestamp,
- Verbose);
- }
- }
- }
-
- // If this is an object, we might have it cached. If not we'll have to load
- // it from the file system and cache it now.
- std::lock_guard<std::mutex> Lock(ObjectCacheMutex);
- if (!ObjectCache.count(Filename)) {
- ObjectEntry &OE = ObjectCache[Filename];
+ continue;
+ }
+
+ if (Verbose)
+ WithColor::note() << "found member in archive.\n";
+
+ auto ErrOrMem = Child.getMemoryBufferRef();
+ if (!ErrOrMem)
+ return ErrOrMem.takeError();
+
+ auto ErrOrObjectFile =
+ object::ObjectFile::createObjectFile(*ErrOrMem);
+ if (!ErrOrObjectFile)
+ return ErrOrObjectFile.takeError();
+
+ OE.Objects.push_back(std::move(*ErrOrObjectFile));
+ }
+ }
+ }
+ if (Err)
+ return std::move(Err);
+ }
+
+ if (OE.Objects.empty())
+ return errorCodeToError(errc::no_such_file_or_directory);
+
+ std::lock_guard<std::mutex> Lock(MemberCacheMutex);
+ MemberCache.try_emplace(Key, std::move(OE));
+ return MemberCache[Key];
+}
+
+Expected<const BinaryHolder::ObjectEntry &>
+BinaryHolder::getObjectEntry(StringRef Filename, TimestampTy Timestamp) {
+ if (Verbose)
+ WithColor::note() << "trying to open '" << Filename << "'\n";
+
+ // If this is an archive, we might have either the object or the archive
+ // cached. In this case we can load it without accessing the file system.
+ if (isArchive(Filename)) {
+ StringRef ArchiveFilename = getArchiveAndObjectName(Filename).first;
+ std::lock_guard<std::mutex> Lock(ArchiveCacheMutex);
+ if (ArchiveCache.count(ArchiveFilename)) {
+ return ArchiveCache[ArchiveFilename].getObjectEntry(Filename, Timestamp,
+ Verbose);
+ } else {
+ ArchiveEntry &AE = ArchiveCache[ArchiveFilename];
+ auto Err = AE.load(VFS, Filename, Timestamp, Verbose);
+ if (Err) {
+ ArchiveCache.erase(ArchiveFilename);
+ // Don't return the error here: maybe the file wasn't an archive.
+ llvm::consumeError(std::move(Err));
+ } else {
+ return ArchiveCache[ArchiveFilename].getObjectEntry(Filename, Timestamp,
+ Verbose);
+ }
+ }
+ }
+
+ // If this is an object, we might have it cached. If not we'll have to load
+ // it from the file system and cache it now.
+ std::lock_guard<std::mutex> Lock(ObjectCacheMutex);
+ if (!ObjectCache.count(Filename)) {
+ ObjectEntry &OE = ObjectCache[Filename];
auto Err = OE.load(VFS, Filename, Timestamp, Verbose);
- if (Err) {
- ObjectCache.erase(Filename);
- return std::move(Err);
- }
- }
-
- return ObjectCache[Filename];
-}
-
-void BinaryHolder::clear() {
- std::lock_guard<std::mutex> ArchiveLock(ArchiveCacheMutex);
- std::lock_guard<std::mutex> ObjectLock(ObjectCacheMutex);
- ArchiveCache.clear();
- ObjectCache.clear();
-}
-
-} // namespace dsymutil
-} // namespace llvm
+ if (Err) {
+ ObjectCache.erase(Filename);
+ return std::move(Err);
+ }
+ }
+
+ return ObjectCache[Filename];
+}
+
+void BinaryHolder::clear() {
+ std::lock_guard<std::mutex> ArchiveLock(ArchiveCacheMutex);
+ std::lock_guard<std::mutex> ObjectLock(ObjectCacheMutex);
+ ArchiveCache.clear();
+ ObjectCache.clear();
+}
+
+} // namespace dsymutil
+} // namespace llvm
diff --git a/contrib/libs/llvm12/tools/dsymutil/BinaryHolder.h b/contrib/libs/llvm12/tools/dsymutil/BinaryHolder.h
index 5e81fe4b93..bf4bcb63b6 100644
--- a/contrib/libs/llvm12/tools/dsymutil/BinaryHolder.h
+++ b/contrib/libs/llvm12/tools/dsymutil/BinaryHolder.h
@@ -1,172 +1,172 @@
-//===-- BinaryHolder.h - Utility class for accessing binaries -------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-//
-// This program is a utility that aims to be a dropin replacement for
-// Darwin's dsymutil.
-//
-//===----------------------------------------------------------------------===//
-#ifndef LLVM_TOOLS_DSYMUTIL_BINARYHOLDER_H
-#define LLVM_TOOLS_DSYMUTIL_BINARYHOLDER_H
-
-#include "llvm/ADT/DenseMap.h"
-#include "llvm/ADT/StringMap.h"
-#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/Chrono.h"
-#include "llvm/Support/Errc.h"
-#include "llvm/Support/ErrorOr.h"
-#include "llvm/Support/VirtualFileSystem.h"
-
-#include <mutex>
-
-namespace llvm {
-namespace dsymutil {
-
-/// The BinaryHolder class is responsible for creating and owning
-/// ObjectFiles and their underlying MemoryBuffers. It differs from a simple
-/// OwningBinary in that it handles accessing and caching of archives and its
-/// members.
-class BinaryHolder {
-public:
- using TimestampTy = sys::TimePoint<std::chrono::seconds>;
-
- BinaryHolder(IntrusiveRefCntPtr<vfs::FileSystem> VFS, bool Verbose = false)
- : VFS(VFS), Verbose(Verbose) {}
-
- // Forward declarations for friend declaration.
- class ObjectEntry;
- class ArchiveEntry;
-
- /// Base class shared by cached entries, representing objects and archives.
- class EntryBase {
- protected:
- std::unique_ptr<MemoryBuffer> MemBuffer;
- std::unique_ptr<object::MachOUniversalBinary> FatBinary;
- std::string FatBinaryName;
- };
-
- /// Cached entry holding one or more (in case of a fat binary) object files.
- class ObjectEntry : public EntryBase {
- public:
- /// Load the given object binary in memory.
- Error load(IntrusiveRefCntPtr<vfs::FileSystem> VFS, StringRef Filename,
+//===-- BinaryHolder.h - Utility class for accessing binaries -------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This program is a utility that aims to be a dropin replacement for
+// Darwin's dsymutil.
+//
+//===----------------------------------------------------------------------===//
+#ifndef LLVM_TOOLS_DSYMUTIL_BINARYHOLDER_H
+#define LLVM_TOOLS_DSYMUTIL_BINARYHOLDER_H
+
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/StringMap.h"
+#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/Chrono.h"
+#include "llvm/Support/Errc.h"
+#include "llvm/Support/ErrorOr.h"
+#include "llvm/Support/VirtualFileSystem.h"
+
+#include <mutex>
+
+namespace llvm {
+namespace dsymutil {
+
+/// The BinaryHolder class is responsible for creating and owning
+/// ObjectFiles and their underlying MemoryBuffers. It differs from a simple
+/// OwningBinary in that it handles accessing and caching of archives and its
+/// members.
+class BinaryHolder {
+public:
+ using TimestampTy = sys::TimePoint<std::chrono::seconds>;
+
+ BinaryHolder(IntrusiveRefCntPtr<vfs::FileSystem> VFS, bool Verbose = false)
+ : VFS(VFS), Verbose(Verbose) {}
+
+ // Forward declarations for friend declaration.
+ class ObjectEntry;
+ class ArchiveEntry;
+
+ /// Base class shared by cached entries, representing objects and archives.
+ class EntryBase {
+ protected:
+ std::unique_ptr<MemoryBuffer> MemBuffer;
+ std::unique_ptr<object::MachOUniversalBinary> FatBinary;
+ std::string FatBinaryName;
+ };
+
+ /// Cached entry holding one or more (in case of a fat binary) object files.
+ class ObjectEntry : public EntryBase {
+ public:
+ /// Load the given object binary in memory.
+ Error load(IntrusiveRefCntPtr<vfs::FileSystem> VFS, StringRef Filename,
TimestampTy Timestamp, bool Verbose = false);
-
- /// Access all owned ObjectFiles.
- std::vector<const object::ObjectFile *> getObjects() const;
-
- /// Access to a derived version of all the currently owned ObjectFiles. The
- /// conversion might be invalid, in which case an Error is returned.
- template <typename ObjectFileType>
- Expected<std::vector<const ObjectFileType *>> getObjectsAs() const {
- std::vector<const ObjectFileType *> Result;
- Result.reserve(Objects.size());
- for (auto &Object : Objects) {
- const auto *Derived = dyn_cast<ObjectFileType>(Object.get());
- if (!Derived)
- return errorCodeToError(object::object_error::invalid_file_type);
- Result.push_back(Derived);
- }
- return Result;
- }
-
- /// Access the owned ObjectFile with architecture \p T.
- Expected<const object::ObjectFile &> getObject(const Triple &T) const;
-
- /// Access to a derived version of the currently owned ObjectFile with
- /// architecture \p T. The conversion must be known to be valid.
- template <typename ObjectFileType>
- Expected<const ObjectFileType &> getObjectAs(const Triple &T) const {
- auto Object = getObject(T);
- if (!Object)
- return Object.takeError();
- return cast<ObjectFileType>(*Object);
- }
-
- private:
- std::vector<std::unique_ptr<object::ObjectFile>> Objects;
- friend ArchiveEntry;
- };
-
- /// Cached entry holding one or more (in the of a fat binary) archive files.
- class ArchiveEntry : public EntryBase {
- public:
- struct KeyTy {
- std::string Filename;
- TimestampTy Timestamp;
-
- KeyTy() : Filename(), Timestamp() {}
- KeyTy(StringRef Filename, TimestampTy Timestamp)
- : Filename(Filename.str()), Timestamp(Timestamp) {}
- };
-
- /// Load the given object binary in memory.
- Error load(IntrusiveRefCntPtr<vfs::FileSystem> VFS, StringRef Filename,
- TimestampTy Timestamp, bool Verbose = false);
-
- Expected<const ObjectEntry &> getObjectEntry(StringRef Filename,
- TimestampTy Timestamp,
- bool Verbose = false);
-
- private:
- std::vector<std::unique_ptr<object::Archive>> Archives;
- DenseMap<KeyTy, ObjectEntry> MemberCache;
- std::mutex MemberCacheMutex;
- };
-
- Expected<const ObjectEntry &>
- getObjectEntry(StringRef Filename, TimestampTy Timestamp = TimestampTy());
-
- void clear();
-
-private:
- /// Cache of static archives. Objects that are part of a static archive are
- /// stored under this object, rather than in the map below.
- StringMap<ArchiveEntry> ArchiveCache;
- std::mutex ArchiveCacheMutex;
-
- /// Object entries for objects that are not in a static archive.
- StringMap<ObjectEntry> ObjectCache;
- std::mutex ObjectCacheMutex;
-
- /// Virtual File System instance.
- IntrusiveRefCntPtr<vfs::FileSystem> VFS;
-
- bool Verbose;
-};
-
-} // namespace dsymutil
-
-template <> struct DenseMapInfo<dsymutil::BinaryHolder::ArchiveEntry::KeyTy> {
-
- static inline dsymutil::BinaryHolder::ArchiveEntry::KeyTy getEmptyKey() {
- return dsymutil::BinaryHolder::ArchiveEntry::KeyTy();
- }
-
- static inline dsymutil::BinaryHolder::ArchiveEntry::KeyTy getTombstoneKey() {
- return dsymutil::BinaryHolder::ArchiveEntry::KeyTy("/", {});
- }
-
- static unsigned
- getHashValue(const dsymutil::BinaryHolder::ArchiveEntry::KeyTy &K) {
- return hash_combine(DenseMapInfo<StringRef>::getHashValue(K.Filename),
- DenseMapInfo<unsigned>::getHashValue(
- K.Timestamp.time_since_epoch().count()));
- }
-
- static bool isEqual(const dsymutil::BinaryHolder::ArchiveEntry::KeyTy &LHS,
- const dsymutil::BinaryHolder::ArchiveEntry::KeyTy &RHS) {
- return LHS.Filename == RHS.Filename && LHS.Timestamp == RHS.Timestamp;
- }
-};
-
-} // namespace llvm
-#endif
+
+ /// Access all owned ObjectFiles.
+ std::vector<const object::ObjectFile *> getObjects() const;
+
+ /// Access to a derived version of all the currently owned ObjectFiles. The
+ /// conversion might be invalid, in which case an Error is returned.
+ template <typename ObjectFileType>
+ Expected<std::vector<const ObjectFileType *>> getObjectsAs() const {
+ std::vector<const ObjectFileType *> Result;
+ Result.reserve(Objects.size());
+ for (auto &Object : Objects) {
+ const auto *Derived = dyn_cast<ObjectFileType>(Object.get());
+ if (!Derived)
+ return errorCodeToError(object::object_error::invalid_file_type);
+ Result.push_back(Derived);
+ }
+ return Result;
+ }
+
+ /// Access the owned ObjectFile with architecture \p T.
+ Expected<const object::ObjectFile &> getObject(const Triple &T) const;
+
+ /// Access to a derived version of the currently owned ObjectFile with
+ /// architecture \p T. The conversion must be known to be valid.
+ template <typename ObjectFileType>
+ Expected<const ObjectFileType &> getObjectAs(const Triple &T) const {
+ auto Object = getObject(T);
+ if (!Object)
+ return Object.takeError();
+ return cast<ObjectFileType>(*Object);
+ }
+
+ private:
+ std::vector<std::unique_ptr<object::ObjectFile>> Objects;
+ friend ArchiveEntry;
+ };
+
+ /// Cached entry holding one or more (in the of a fat binary) archive files.
+ class ArchiveEntry : public EntryBase {
+ public:
+ struct KeyTy {
+ std::string Filename;
+ TimestampTy Timestamp;
+
+ KeyTy() : Filename(), Timestamp() {}
+ KeyTy(StringRef Filename, TimestampTy Timestamp)
+ : Filename(Filename.str()), Timestamp(Timestamp) {}
+ };
+
+ /// Load the given object binary in memory.
+ Error load(IntrusiveRefCntPtr<vfs::FileSystem> VFS, StringRef Filename,
+ TimestampTy Timestamp, bool Verbose = false);
+
+ Expected<const ObjectEntry &> getObjectEntry(StringRef Filename,
+ TimestampTy Timestamp,
+ bool Verbose = false);
+
+ private:
+ std::vector<std::unique_ptr<object::Archive>> Archives;
+ DenseMap<KeyTy, ObjectEntry> MemberCache;
+ std::mutex MemberCacheMutex;
+ };
+
+ Expected<const ObjectEntry &>
+ getObjectEntry(StringRef Filename, TimestampTy Timestamp = TimestampTy());
+
+ void clear();
+
+private:
+ /// Cache of static archives. Objects that are part of a static archive are
+ /// stored under this object, rather than in the map below.
+ StringMap<ArchiveEntry> ArchiveCache;
+ std::mutex ArchiveCacheMutex;
+
+ /// Object entries for objects that are not in a static archive.
+ StringMap<ObjectEntry> ObjectCache;
+ std::mutex ObjectCacheMutex;
+
+ /// Virtual File System instance.
+ IntrusiveRefCntPtr<vfs::FileSystem> VFS;
+
+ bool Verbose;
+};
+
+} // namespace dsymutil
+
+template <> struct DenseMapInfo<dsymutil::BinaryHolder::ArchiveEntry::KeyTy> {
+
+ static inline dsymutil::BinaryHolder::ArchiveEntry::KeyTy getEmptyKey() {
+ return dsymutil::BinaryHolder::ArchiveEntry::KeyTy();
+ }
+
+ static inline dsymutil::BinaryHolder::ArchiveEntry::KeyTy getTombstoneKey() {
+ return dsymutil::BinaryHolder::ArchiveEntry::KeyTy("/", {});
+ }
+
+ static unsigned
+ getHashValue(const dsymutil::BinaryHolder::ArchiveEntry::KeyTy &K) {
+ return hash_combine(DenseMapInfo<StringRef>::getHashValue(K.Filename),
+ DenseMapInfo<unsigned>::getHashValue(
+ K.Timestamp.time_since_epoch().count()));
+ }
+
+ static bool isEqual(const dsymutil::BinaryHolder::ArchiveEntry::KeyTy &LHS,
+ const dsymutil::BinaryHolder::ArchiveEntry::KeyTy &RHS) {
+ return LHS.Filename == RHS.Filename && LHS.Timestamp == RHS.Timestamp;
+ }
+};
+
+} // namespace llvm
+#endif
diff --git a/contrib/libs/llvm12/tools/dsymutil/CFBundle.cpp b/contrib/libs/llvm12/tools/dsymutil/CFBundle.cpp
index 0625afb18a..406c35cc59 100644
--- a/contrib/libs/llvm12/tools/dsymutil/CFBundle.cpp
+++ b/contrib/libs/llvm12/tools/dsymutil/CFBundle.cpp
@@ -1,185 +1,185 @@
-//===- tools/dsymutil/CFBundle.cpp - CFBundle helper ------------*- C++ -*-===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "CFBundle.h"
-
-#ifdef __APPLE__
-#include "llvm/Support/FileSystem.h"
-#include "llvm/Support/Path.h"
-#include "llvm/Support/raw_ostream.h"
-#include <CoreFoundation/CoreFoundation.h>
-#include <assert.h>
-#include <glob.h>
-#include <memory>
-#endif
-
-namespace llvm {
-namespace dsymutil {
-
-#ifdef __APPLE__
-/// Deleter that calls CFRelease rather than deleting the pointer.
-template <typename T> struct CFDeleter {
- void operator()(T *P) {
- if (P)
- ::CFRelease(P);
- }
-};
-
-/// This helper owns any CoreFoundation pointer and will call CFRelease() on
-/// any valid pointer it owns unless that pointer is explicitly released using
-/// the release() member function.
-template <typename T>
-using CFReleaser = std::unique_ptr<std::remove_pointer_t<T>,
- CFDeleter<std::remove_pointer_t<T>>>;
-
-/// RAII wrapper around CFBundleRef.
-class CFString : public CFReleaser<CFStringRef> {
-public:
- CFString(CFStringRef CFStr = nullptr) : CFReleaser<CFStringRef>(CFStr) {}
-
- const char *UTF8(std::string &Str) const {
- return CFString::UTF8(get(), Str);
- }
-
- CFIndex GetLength() const {
- if (CFStringRef Str = get())
- return CFStringGetLength(Str);
- return 0;
- }
-
- static const char *UTF8(CFStringRef CFStr, std::string &Str);
-};
-
-/// Static function that puts a copy of the UTF-8 contents of CFStringRef into
-/// std::string and returns the C string pointer that is contained in the
-/// std::string when successful, nullptr otherwise.
-///
-/// This allows the std::string parameter to own the extracted string, and also
-/// allows that string to be returned as a C string pointer that can be used.
-const char *CFString::UTF8(CFStringRef CFStr, std::string &Str) {
- if (!CFStr)
- return nullptr;
-
- const CFStringEncoding Encoding = kCFStringEncodingUTF8;
- CFIndex MaxUTF8StrLength = CFStringGetLength(CFStr);
- MaxUTF8StrLength =
- CFStringGetMaximumSizeForEncoding(MaxUTF8StrLength, Encoding);
- if (MaxUTF8StrLength > 0) {
- Str.resize(MaxUTF8StrLength);
- if (!Str.empty() &&
- CFStringGetCString(CFStr, &Str[0], Str.size(), Encoding)) {
- Str.resize(strlen(Str.c_str()));
- return Str.c_str();
- }
- }
-
- return nullptr;
-}
-
-/// RAII wrapper around CFBundleRef.
-class CFBundle : public CFReleaser<CFBundleRef> {
-public:
- CFBundle(StringRef Path) : CFReleaser<CFBundleRef>() { SetFromPath(Path); }
-
- CFBundle(CFURLRef Url)
- : CFReleaser<CFBundleRef>(Url ? ::CFBundleCreate(nullptr, Url)
- : nullptr) {}
-
- /// Return the bundle identifier.
- CFStringRef GetIdentifier() const {
- if (CFBundleRef bundle = get())
- return ::CFBundleGetIdentifier(bundle);
- return nullptr;
- }
-
- /// Return value for key.
- CFTypeRef GetValueForInfoDictionaryKey(CFStringRef key) const {
- if (CFBundleRef bundle = get())
- return ::CFBundleGetValueForInfoDictionaryKey(bundle, key);
- return nullptr;
- }
-
-private:
- /// Helper to initialize this instance with a new bundle created from the
- /// given path. This function will recursively remove components from the
- /// path in its search for the nearest Info.plist.
- void SetFromPath(StringRef Path);
-};
-
-void CFBundle::SetFromPath(StringRef Path) {
- // Start from an empty/invalid CFBundle.
- reset();
-
- if (Path.empty() || !sys::fs::exists(Path))
- return;
-
- SmallString<256> RealPath;
- sys::fs::real_path(Path, RealPath, /*expand_tilde*/ true);
-
- do {
- // Create a CFURL from the current path and use it to create a CFBundle.
- CFReleaser<CFURLRef> BundleURL(::CFURLCreateFromFileSystemRepresentation(
- kCFAllocatorDefault, (const UInt8 *)RealPath.data(), RealPath.size(),
- false));
- reset(::CFBundleCreate(kCFAllocatorDefault, BundleURL.get()));
-
- // If we have a valid bundle and find its identifier we are done.
- if (get() != nullptr) {
- if (GetIdentifier() != nullptr)
- return;
- reset();
- }
-
- // Remove the last component of the path and try again until there's
- // nothing left but the root.
- sys::path::remove_filename(RealPath);
- } while (RealPath != sys::path::root_name(RealPath));
-}
-#endif
-
-/// On Darwin, try and find the original executable's Info.plist to extract
-/// information about the bundle. Return default values on other platforms.
-CFBundleInfo getBundleInfo(StringRef ExePath) {
- CFBundleInfo BundleInfo;
-
-#ifdef __APPLE__
- auto PrintError = [&](CFTypeID TypeID) {
- CFString TypeIDCFStr(::CFCopyTypeIDDescription(TypeID));
- std::string TypeIDStr;
- errs() << "The Info.plist key \"CFBundleShortVersionString\" is"
- << "a " << TypeIDCFStr.UTF8(TypeIDStr)
- << ", but it should be a string in: " << ExePath << ".\n";
- };
-
- CFBundle Bundle(ExePath);
- if (CFStringRef BundleID = Bundle.GetIdentifier()) {
- CFString::UTF8(BundleID, BundleInfo.IDStr);
- if (CFTypeRef TypeRef =
- Bundle.GetValueForInfoDictionaryKey(CFSTR("CFBundleVersion"))) {
- CFTypeID TypeID = ::CFGetTypeID(TypeRef);
- if (TypeID == ::CFStringGetTypeID())
- CFString::UTF8((CFStringRef)TypeRef, BundleInfo.VersionStr);
- else
- PrintError(TypeID);
- }
- if (CFTypeRef TypeRef = Bundle.GetValueForInfoDictionaryKey(
- CFSTR("CFBundleShortVersionString"))) {
- CFTypeID TypeID = ::CFGetTypeID(TypeRef);
- if (TypeID == ::CFStringGetTypeID())
- CFString::UTF8((CFStringRef)TypeRef, BundleInfo.ShortVersionStr);
- else
- PrintError(TypeID);
- }
- }
-#endif
-
- return BundleInfo;
-}
-
-} // end namespace dsymutil
-} // end namespace llvm
+//===- tools/dsymutil/CFBundle.cpp - CFBundle helper ------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "CFBundle.h"
+
+#ifdef __APPLE__
+#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/Path.h"
+#include "llvm/Support/raw_ostream.h"
+#include <CoreFoundation/CoreFoundation.h>
+#include <assert.h>
+#include <glob.h>
+#include <memory>
+#endif
+
+namespace llvm {
+namespace dsymutil {
+
+#ifdef __APPLE__
+/// Deleter that calls CFRelease rather than deleting the pointer.
+template <typename T> struct CFDeleter {
+ void operator()(T *P) {
+ if (P)
+ ::CFRelease(P);
+ }
+};
+
+/// This helper owns any CoreFoundation pointer and will call CFRelease() on
+/// any valid pointer it owns unless that pointer is explicitly released using
+/// the release() member function.
+template <typename T>
+using CFReleaser = std::unique_ptr<std::remove_pointer_t<T>,
+ CFDeleter<std::remove_pointer_t<T>>>;
+
+/// RAII wrapper around CFBundleRef.
+class CFString : public CFReleaser<CFStringRef> {
+public:
+ CFString(CFStringRef CFStr = nullptr) : CFReleaser<CFStringRef>(CFStr) {}
+
+ const char *UTF8(std::string &Str) const {
+ return CFString::UTF8(get(), Str);
+ }
+
+ CFIndex GetLength() const {
+ if (CFStringRef Str = get())
+ return CFStringGetLength(Str);
+ return 0;
+ }
+
+ static const char *UTF8(CFStringRef CFStr, std::string &Str);
+};
+
+/// Static function that puts a copy of the UTF-8 contents of CFStringRef into
+/// std::string and returns the C string pointer that is contained in the
+/// std::string when successful, nullptr otherwise.
+///
+/// This allows the std::string parameter to own the extracted string, and also
+/// allows that string to be returned as a C string pointer that can be used.
+const char *CFString::UTF8(CFStringRef CFStr, std::string &Str) {
+ if (!CFStr)
+ return nullptr;
+
+ const CFStringEncoding Encoding = kCFStringEncodingUTF8;
+ CFIndex MaxUTF8StrLength = CFStringGetLength(CFStr);
+ MaxUTF8StrLength =
+ CFStringGetMaximumSizeForEncoding(MaxUTF8StrLength, Encoding);
+ if (MaxUTF8StrLength > 0) {
+ Str.resize(MaxUTF8StrLength);
+ if (!Str.empty() &&
+ CFStringGetCString(CFStr, &Str[0], Str.size(), Encoding)) {
+ Str.resize(strlen(Str.c_str()));
+ return Str.c_str();
+ }
+ }
+
+ return nullptr;
+}
+
+/// RAII wrapper around CFBundleRef.
+class CFBundle : public CFReleaser<CFBundleRef> {
+public:
+ CFBundle(StringRef Path) : CFReleaser<CFBundleRef>() { SetFromPath(Path); }
+
+ CFBundle(CFURLRef Url)
+ : CFReleaser<CFBundleRef>(Url ? ::CFBundleCreate(nullptr, Url)
+ : nullptr) {}
+
+ /// Return the bundle identifier.
+ CFStringRef GetIdentifier() const {
+ if (CFBundleRef bundle = get())
+ return ::CFBundleGetIdentifier(bundle);
+ return nullptr;
+ }
+
+ /// Return value for key.
+ CFTypeRef GetValueForInfoDictionaryKey(CFStringRef key) const {
+ if (CFBundleRef bundle = get())
+ return ::CFBundleGetValueForInfoDictionaryKey(bundle, key);
+ return nullptr;
+ }
+
+private:
+ /// Helper to initialize this instance with a new bundle created from the
+ /// given path. This function will recursively remove components from the
+ /// path in its search for the nearest Info.plist.
+ void SetFromPath(StringRef Path);
+};
+
+void CFBundle::SetFromPath(StringRef Path) {
+ // Start from an empty/invalid CFBundle.
+ reset();
+
+ if (Path.empty() || !sys::fs::exists(Path))
+ return;
+
+ SmallString<256> RealPath;
+ sys::fs::real_path(Path, RealPath, /*expand_tilde*/ true);
+
+ do {
+ // Create a CFURL from the current path and use it to create a CFBundle.
+ CFReleaser<CFURLRef> BundleURL(::CFURLCreateFromFileSystemRepresentation(
+ kCFAllocatorDefault, (const UInt8 *)RealPath.data(), RealPath.size(),
+ false));
+ reset(::CFBundleCreate(kCFAllocatorDefault, BundleURL.get()));
+
+ // If we have a valid bundle and find its identifier we are done.
+ if (get() != nullptr) {
+ if (GetIdentifier() != nullptr)
+ return;
+ reset();
+ }
+
+ // Remove the last component of the path and try again until there's
+ // nothing left but the root.
+ sys::path::remove_filename(RealPath);
+ } while (RealPath != sys::path::root_name(RealPath));
+}
+#endif
+
+/// On Darwin, try and find the original executable's Info.plist to extract
+/// information about the bundle. Return default values on other platforms.
+CFBundleInfo getBundleInfo(StringRef ExePath) {
+ CFBundleInfo BundleInfo;
+
+#ifdef __APPLE__
+ auto PrintError = [&](CFTypeID TypeID) {
+ CFString TypeIDCFStr(::CFCopyTypeIDDescription(TypeID));
+ std::string TypeIDStr;
+ errs() << "The Info.plist key \"CFBundleShortVersionString\" is"
+ << "a " << TypeIDCFStr.UTF8(TypeIDStr)
+ << ", but it should be a string in: " << ExePath << ".\n";
+ };
+
+ CFBundle Bundle(ExePath);
+ if (CFStringRef BundleID = Bundle.GetIdentifier()) {
+ CFString::UTF8(BundleID, BundleInfo.IDStr);
+ if (CFTypeRef TypeRef =
+ Bundle.GetValueForInfoDictionaryKey(CFSTR("CFBundleVersion"))) {
+ CFTypeID TypeID = ::CFGetTypeID(TypeRef);
+ if (TypeID == ::CFStringGetTypeID())
+ CFString::UTF8((CFStringRef)TypeRef, BundleInfo.VersionStr);
+ else
+ PrintError(TypeID);
+ }
+ if (CFTypeRef TypeRef = Bundle.GetValueForInfoDictionaryKey(
+ CFSTR("CFBundleShortVersionString"))) {
+ CFTypeID TypeID = ::CFGetTypeID(TypeRef);
+ if (TypeID == ::CFStringGetTypeID())
+ CFString::UTF8((CFStringRef)TypeRef, BundleInfo.ShortVersionStr);
+ else
+ PrintError(TypeID);
+ }
+ }
+#endif
+
+ return BundleInfo;
+}
+
+} // end namespace dsymutil
+} // end namespace llvm
diff --git a/contrib/libs/llvm12/tools/dsymutil/CFBundle.h b/contrib/libs/llvm12/tools/dsymutil/CFBundle.h
index 103db03516..12eb64ac0b 100644
--- a/contrib/libs/llvm12/tools/dsymutil/CFBundle.h
+++ b/contrib/libs/llvm12/tools/dsymutil/CFBundle.h
@@ -1,30 +1,30 @@
-//===- tools/dsymutil/CFBundle.h - CFBundle helper --------------*- C++ -*-===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_TOOLS_DSYMUTIL_CFBUNDLE_H
-#define LLVM_TOOLS_DSYMUTIL_CFBUNDLE_H
-
-#include "llvm/ADT/StringRef.h"
-#include <string>
-
-namespace llvm {
-namespace dsymutil {
-
-struct CFBundleInfo {
- std::string VersionStr = "1";
- std::string ShortVersionStr = "1.0";
- std::string IDStr;
- bool OmitShortVersion() const { return ShortVersionStr.empty(); }
-};
-
-CFBundleInfo getBundleInfo(llvm::StringRef ExePath);
-
-} // end namespace dsymutil
-} // end namespace llvm
-
-#endif
+//===- tools/dsymutil/CFBundle.h - CFBundle helper --------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TOOLS_DSYMUTIL_CFBUNDLE_H
+#define LLVM_TOOLS_DSYMUTIL_CFBUNDLE_H
+
+#include "llvm/ADT/StringRef.h"
+#include <string>
+
+namespace llvm {
+namespace dsymutil {
+
+struct CFBundleInfo {
+ std::string VersionStr = "1";
+ std::string ShortVersionStr = "1.0";
+ std::string IDStr;
+ bool OmitShortVersion() const { return ShortVersionStr.empty(); }
+};
+
+CFBundleInfo getBundleInfo(llvm::StringRef ExePath);
+
+} // end namespace dsymutil
+} // end namespace llvm
+
+#endif
diff --git a/contrib/libs/llvm12/tools/dsymutil/DebugMap.cpp b/contrib/libs/llvm12/tools/dsymutil/DebugMap.cpp
index 605c1317b9..ba763e65c5 100644
--- a/contrib/libs/llvm12/tools/dsymutil/DebugMap.cpp
+++ b/contrib/libs/llvm12/tools/dsymutil/DebugMap.cpp
@@ -1,294 +1,294 @@
-//===- tools/dsymutil/DebugMap.cpp - Generic debug map representation -----===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "DebugMap.h"
-#include "BinaryHolder.h"
-#include "llvm/ADT/Optional.h"
-#include "llvm/ADT/SmallString.h"
-#include "llvm/ADT/StringMap.h"
-#include "llvm/ADT/StringRef.h"
-#include "llvm/ADT/Triple.h"
-#include "llvm/ADT/iterator_range.h"
-#include "llvm/BinaryFormat/MachO.h"
-#include "llvm/Object/ObjectFile.h"
-#include "llvm/Support/Chrono.h"
-#include "llvm/Support/Error.h"
-#include "llvm/Support/Format.h"
-#include "llvm/Support/MemoryBuffer.h"
-#include "llvm/Support/Path.h"
-#include "llvm/Support/WithColor.h"
-#include "llvm/Support/YAMLTraits.h"
-#include "llvm/Support/raw_ostream.h"
-#include <algorithm>
-#include <cinttypes>
-#include <cstdint>
-#include <memory>
-#include <string>
-#include <utility>
-#include <vector>
-
-namespace llvm {
-
-namespace dsymutil {
-
-using namespace llvm::object;
-
-DebugMapObject::DebugMapObject(StringRef ObjectFilename,
- sys::TimePoint<std::chrono::seconds> Timestamp,
- uint8_t Type)
- : Filename(std::string(ObjectFilename)), Timestamp(Timestamp), Type(Type) {}
-
-bool DebugMapObject::addSymbol(StringRef Name, Optional<uint64_t> ObjectAddress,
- uint64_t LinkedAddress, uint32_t Size) {
- auto InsertResult = Symbols.insert(
- std::make_pair(Name, SymbolMapping(ObjectAddress, LinkedAddress, Size)));
-
- if (ObjectAddress && InsertResult.second)
- AddressToMapping[*ObjectAddress] = &*InsertResult.first;
- return InsertResult.second;
-}
-
-void DebugMapObject::print(raw_ostream &OS) const {
- OS << getObjectFilename() << ":\n";
- // Sort the symbols in alphabetical order, like llvm-nm (and to get
- // deterministic output for testing).
- using Entry = std::pair<StringRef, SymbolMapping>;
- std::vector<Entry> Entries;
- Entries.reserve(Symbols.getNumItems());
+//===- tools/dsymutil/DebugMap.cpp - Generic debug map representation -----===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "DebugMap.h"
+#include "BinaryHolder.h"
+#include "llvm/ADT/Optional.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/StringMap.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/Triple.h"
+#include "llvm/ADT/iterator_range.h"
+#include "llvm/BinaryFormat/MachO.h"
+#include "llvm/Object/ObjectFile.h"
+#include "llvm/Support/Chrono.h"
+#include "llvm/Support/Error.h"
+#include "llvm/Support/Format.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/Path.h"
+#include "llvm/Support/WithColor.h"
+#include "llvm/Support/YAMLTraits.h"
+#include "llvm/Support/raw_ostream.h"
+#include <algorithm>
+#include <cinttypes>
+#include <cstdint>
+#include <memory>
+#include <string>
+#include <utility>
+#include <vector>
+
+namespace llvm {
+
+namespace dsymutil {
+
+using namespace llvm::object;
+
+DebugMapObject::DebugMapObject(StringRef ObjectFilename,
+ sys::TimePoint<std::chrono::seconds> Timestamp,
+ uint8_t Type)
+ : Filename(std::string(ObjectFilename)), Timestamp(Timestamp), Type(Type) {}
+
+bool DebugMapObject::addSymbol(StringRef Name, Optional<uint64_t> ObjectAddress,
+ uint64_t LinkedAddress, uint32_t Size) {
+ auto InsertResult = Symbols.insert(
+ std::make_pair(Name, SymbolMapping(ObjectAddress, LinkedAddress, Size)));
+
+ if (ObjectAddress && InsertResult.second)
+ AddressToMapping[*ObjectAddress] = &*InsertResult.first;
+ return InsertResult.second;
+}
+
+void DebugMapObject::print(raw_ostream &OS) const {
+ OS << getObjectFilename() << ":\n";
+ // Sort the symbols in alphabetical order, like llvm-nm (and to get
+ // deterministic output for testing).
+ using Entry = std::pair<StringRef, SymbolMapping>;
+ std::vector<Entry> Entries;
+ Entries.reserve(Symbols.getNumItems());
for (const auto &Sym : Symbols)
- Entries.push_back(std::make_pair(Sym.getKey(), Sym.getValue()));
- llvm::sort(Entries, [](const Entry &LHS, const Entry &RHS) {
- return LHS.first < RHS.first;
- });
- for (const auto &Sym : Entries) {
- if (Sym.second.ObjectAddress)
- OS << format("\t%016" PRIx64, uint64_t(*Sym.second.ObjectAddress));
- else
- OS << "\t????????????????";
- OS << format(" => %016" PRIx64 "+0x%x\t%s\n",
- uint64_t(Sym.second.BinaryAddress), uint32_t(Sym.second.Size),
- Sym.first.data());
- }
- OS << '\n';
-}
-
-#ifndef NDEBUG
-void DebugMapObject::dump() const { print(errs()); }
-#endif
-
-DebugMapObject &
-DebugMap::addDebugMapObject(StringRef ObjectFilePath,
- sys::TimePoint<std::chrono::seconds> Timestamp,
- uint8_t Type) {
- Objects.emplace_back(new DebugMapObject(ObjectFilePath, Timestamp, Type));
- return *Objects.back();
-}
-
-const DebugMapObject::DebugMapEntry *
-DebugMapObject::lookupSymbol(StringRef SymbolName) const {
- StringMap<SymbolMapping>::const_iterator Sym = Symbols.find(SymbolName);
- if (Sym == Symbols.end())
- return nullptr;
- return &*Sym;
-}
-
-const DebugMapObject::DebugMapEntry *
-DebugMapObject::lookupObjectAddress(uint64_t Address) const {
- auto Mapping = AddressToMapping.find(Address);
- if (Mapping == AddressToMapping.end())
- return nullptr;
- return Mapping->getSecond();
-}
-
-void DebugMap::print(raw_ostream &OS) const {
- yaml::Output yout(OS, /* Ctxt = */ nullptr, /* WrapColumn = */ 0);
- yout << const_cast<DebugMap &>(*this);
-}
-
-#ifndef NDEBUG
-void DebugMap::dump() const { print(errs()); }
-#endif
-
-namespace {
-
-struct YAMLContext {
- StringRef PrependPath;
- Triple BinaryTriple;
-};
-
-} // end anonymous namespace
-
-ErrorOr<std::vector<std::unique_ptr<DebugMap>>>
-DebugMap::parseYAMLDebugMap(StringRef InputFile, StringRef PrependPath,
- bool Verbose) {
- auto ErrOrFile = MemoryBuffer::getFileOrSTDIN(InputFile);
- if (auto Err = ErrOrFile.getError())
- return Err;
-
- YAMLContext Ctxt;
-
- Ctxt.PrependPath = PrependPath;
-
- std::unique_ptr<DebugMap> Res;
- yaml::Input yin((*ErrOrFile)->getBuffer(), &Ctxt);
- yin >> Res;
-
- if (auto EC = yin.error())
- return EC;
- std::vector<std::unique_ptr<DebugMap>> Result;
- Result.push_back(std::move(Res));
- return std::move(Result);
-}
-
-} // end namespace dsymutil
-
-namespace yaml {
-
-// Normalize/Denormalize between YAML and a DebugMapObject.
-struct MappingTraits<dsymutil::DebugMapObject>::YamlDMO {
- YamlDMO(IO &io) { Timestamp = 0; }
- YamlDMO(IO &io, dsymutil::DebugMapObject &Obj);
- dsymutil::DebugMapObject denormalize(IO &IO);
-
- std::string Filename;
- int64_t Timestamp;
- std::vector<dsymutil::DebugMapObject::YAMLSymbolMapping> Entries;
-};
-
-void MappingTraits<std::pair<std::string, DebugMapObject::SymbolMapping>>::
- mapping(IO &io, std::pair<std::string, DebugMapObject::SymbolMapping> &s) {
- io.mapRequired("sym", s.first);
- io.mapOptional("objAddr", s.second.ObjectAddress);
- io.mapRequired("binAddr", s.second.BinaryAddress);
- io.mapOptional("size", s.second.Size);
-}
-
-void MappingTraits<dsymutil::DebugMapObject>::mapping(
- IO &io, dsymutil::DebugMapObject &DMO) {
- MappingNormalization<YamlDMO, dsymutil::DebugMapObject> Norm(io, DMO);
- io.mapRequired("filename", Norm->Filename);
- io.mapOptional("timestamp", Norm->Timestamp);
- io.mapRequired("symbols", Norm->Entries);
-}
-
-void ScalarTraits<Triple>::output(const Triple &val, void *, raw_ostream &out) {
- out << val.str();
-}
-
-StringRef ScalarTraits<Triple>::input(StringRef scalar, void *, Triple &value) {
- value = Triple(scalar);
- return StringRef();
-}
-
-size_t
-SequenceTraits<std::vector<std::unique_ptr<dsymutil::DebugMapObject>>>::size(
- IO &io, std::vector<std::unique_ptr<dsymutil::DebugMapObject>> &seq) {
- return seq.size();
-}
-
-dsymutil::DebugMapObject &
-SequenceTraits<std::vector<std::unique_ptr<dsymutil::DebugMapObject>>>::element(
- IO &, std::vector<std::unique_ptr<dsymutil::DebugMapObject>> &seq,
- size_t index) {
- if (index >= seq.size()) {
- seq.resize(index + 1);
- seq[index].reset(new dsymutil::DebugMapObject);
- }
- return *seq[index];
-}
-
-void MappingTraits<dsymutil::DebugMap>::mapping(IO &io,
- dsymutil::DebugMap &DM) {
- io.mapRequired("triple", DM.BinaryTriple);
- io.mapOptional("binary-path", DM.BinaryPath);
- 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(
- IO &io, std::unique_ptr<dsymutil::DebugMap> &DM) {
- if (!DM)
- DM.reset(new DebugMap());
- io.mapRequired("triple", DM->BinaryTriple);
- io.mapOptional("binary-path", DM->BinaryPath);
- if (void *Ctxt = io.getContext())
- reinterpret_cast<YAMLContext *>(Ctxt)->BinaryTriple = DM->BinaryTriple;
- io.mapOptional("objects", DM->Objects);
-}
-
-MappingTraits<dsymutil::DebugMapObject>::YamlDMO::YamlDMO(
- IO &io, dsymutil::DebugMapObject &Obj) {
- Filename = Obj.Filename;
- Timestamp = sys::toTimeT(Obj.getTimestamp());
- Entries.reserve(Obj.Symbols.size());
- for (auto &Entry : Obj.Symbols)
- Entries.push_back(
- std::make_pair(std::string(Entry.getKey()), Entry.getValue()));
-}
-
-dsymutil::DebugMapObject
-MappingTraits<dsymutil::DebugMapObject>::YamlDMO::denormalize(IO &IO) {
- BinaryHolder BinHolder(vfs::getRealFileSystem(), /* Verbose =*/false);
- const auto &Ctxt = *reinterpret_cast<YAMLContext *>(IO.getContext());
- SmallString<80> Path(Ctxt.PrependPath);
- StringMap<uint64_t> SymbolAddresses;
-
- sys::path::append(Path, Filename);
-
- auto ObjectEntry = BinHolder.getObjectEntry(Path);
- if (!ObjectEntry) {
- auto Err = ObjectEntry.takeError();
- WithColor::warning() << "Unable to open " << Path << " "
- << toString(std::move(Err)) << '\n';
- } else {
- auto Object = ObjectEntry->getObject(Ctxt.BinaryTriple);
- if (!Object) {
- auto Err = Object.takeError();
- WithColor::warning() << "Unable to open " << Path << " "
- << toString(std::move(Err)) << '\n';
- } else {
- for (const auto &Sym : Object->symbols()) {
- Expected<uint64_t> AddressOrErr = Sym.getValue();
- if (!AddressOrErr) {
- // TODO: Actually report errors helpfully.
- consumeError(AddressOrErr.takeError());
- continue;
- }
- Expected<StringRef> Name = Sym.getName();
- Expected<uint32_t> FlagsOrErr = Sym.getFlags();
- if (!Name || !FlagsOrErr ||
- (*FlagsOrErr & (SymbolRef::SF_Absolute | SymbolRef::SF_Common))) {
- // TODO: Actually report errors helpfully.
- if (!FlagsOrErr)
- consumeError(FlagsOrErr.takeError());
- if (!Name)
- consumeError(Name.takeError());
- continue;
- }
- SymbolAddresses[*Name] = *AddressOrErr;
- }
- }
- }
-
- dsymutil::DebugMapObject Res(Path, sys::toTimePoint(Timestamp), MachO::N_OSO);
- for (auto &Entry : Entries) {
- auto &Mapping = Entry.second;
- Optional<uint64_t> ObjAddress;
- if (Mapping.ObjectAddress)
- ObjAddress = *Mapping.ObjectAddress;
- auto AddressIt = SymbolAddresses.find(Entry.first);
- if (AddressIt != SymbolAddresses.end())
- ObjAddress = AddressIt->getValue();
- Res.addSymbol(Entry.first, ObjAddress, Mapping.BinaryAddress, Mapping.Size);
- }
- return Res;
-}
-
-} // end namespace yaml
-} // end namespace llvm
+ Entries.push_back(std::make_pair(Sym.getKey(), Sym.getValue()));
+ llvm::sort(Entries, [](const Entry &LHS, const Entry &RHS) {
+ return LHS.first < RHS.first;
+ });
+ for (const auto &Sym : Entries) {
+ if (Sym.second.ObjectAddress)
+ OS << format("\t%016" PRIx64, uint64_t(*Sym.second.ObjectAddress));
+ else
+ OS << "\t????????????????";
+ OS << format(" => %016" PRIx64 "+0x%x\t%s\n",
+ uint64_t(Sym.second.BinaryAddress), uint32_t(Sym.second.Size),
+ Sym.first.data());
+ }
+ OS << '\n';
+}
+
+#ifndef NDEBUG
+void DebugMapObject::dump() const { print(errs()); }
+#endif
+
+DebugMapObject &
+DebugMap::addDebugMapObject(StringRef ObjectFilePath,
+ sys::TimePoint<std::chrono::seconds> Timestamp,
+ uint8_t Type) {
+ Objects.emplace_back(new DebugMapObject(ObjectFilePath, Timestamp, Type));
+ return *Objects.back();
+}
+
+const DebugMapObject::DebugMapEntry *
+DebugMapObject::lookupSymbol(StringRef SymbolName) const {
+ StringMap<SymbolMapping>::const_iterator Sym = Symbols.find(SymbolName);
+ if (Sym == Symbols.end())
+ return nullptr;
+ return &*Sym;
+}
+
+const DebugMapObject::DebugMapEntry *
+DebugMapObject::lookupObjectAddress(uint64_t Address) const {
+ auto Mapping = AddressToMapping.find(Address);
+ if (Mapping == AddressToMapping.end())
+ return nullptr;
+ return Mapping->getSecond();
+}
+
+void DebugMap::print(raw_ostream &OS) const {
+ yaml::Output yout(OS, /* Ctxt = */ nullptr, /* WrapColumn = */ 0);
+ yout << const_cast<DebugMap &>(*this);
+}
+
+#ifndef NDEBUG
+void DebugMap::dump() const { print(errs()); }
+#endif
+
+namespace {
+
+struct YAMLContext {
+ StringRef PrependPath;
+ Triple BinaryTriple;
+};
+
+} // end anonymous namespace
+
+ErrorOr<std::vector<std::unique_ptr<DebugMap>>>
+DebugMap::parseYAMLDebugMap(StringRef InputFile, StringRef PrependPath,
+ bool Verbose) {
+ auto ErrOrFile = MemoryBuffer::getFileOrSTDIN(InputFile);
+ if (auto Err = ErrOrFile.getError())
+ return Err;
+
+ YAMLContext Ctxt;
+
+ Ctxt.PrependPath = PrependPath;
+
+ std::unique_ptr<DebugMap> Res;
+ yaml::Input yin((*ErrOrFile)->getBuffer(), &Ctxt);
+ yin >> Res;
+
+ if (auto EC = yin.error())
+ return EC;
+ std::vector<std::unique_ptr<DebugMap>> Result;
+ Result.push_back(std::move(Res));
+ return std::move(Result);
+}
+
+} // end namespace dsymutil
+
+namespace yaml {
+
+// Normalize/Denormalize between YAML and a DebugMapObject.
+struct MappingTraits<dsymutil::DebugMapObject>::YamlDMO {
+ YamlDMO(IO &io) { Timestamp = 0; }
+ YamlDMO(IO &io, dsymutil::DebugMapObject &Obj);
+ dsymutil::DebugMapObject denormalize(IO &IO);
+
+ std::string Filename;
+ int64_t Timestamp;
+ std::vector<dsymutil::DebugMapObject::YAMLSymbolMapping> Entries;
+};
+
+void MappingTraits<std::pair<std::string, DebugMapObject::SymbolMapping>>::
+ mapping(IO &io, std::pair<std::string, DebugMapObject::SymbolMapping> &s) {
+ io.mapRequired("sym", s.first);
+ io.mapOptional("objAddr", s.second.ObjectAddress);
+ io.mapRequired("binAddr", s.second.BinaryAddress);
+ io.mapOptional("size", s.second.Size);
+}
+
+void MappingTraits<dsymutil::DebugMapObject>::mapping(
+ IO &io, dsymutil::DebugMapObject &DMO) {
+ MappingNormalization<YamlDMO, dsymutil::DebugMapObject> Norm(io, DMO);
+ io.mapRequired("filename", Norm->Filename);
+ io.mapOptional("timestamp", Norm->Timestamp);
+ io.mapRequired("symbols", Norm->Entries);
+}
+
+void ScalarTraits<Triple>::output(const Triple &val, void *, raw_ostream &out) {
+ out << val.str();
+}
+
+StringRef ScalarTraits<Triple>::input(StringRef scalar, void *, Triple &value) {
+ value = Triple(scalar);
+ return StringRef();
+}
+
+size_t
+SequenceTraits<std::vector<std::unique_ptr<dsymutil::DebugMapObject>>>::size(
+ IO &io, std::vector<std::unique_ptr<dsymutil::DebugMapObject>> &seq) {
+ return seq.size();
+}
+
+dsymutil::DebugMapObject &
+SequenceTraits<std::vector<std::unique_ptr<dsymutil::DebugMapObject>>>::element(
+ IO &, std::vector<std::unique_ptr<dsymutil::DebugMapObject>> &seq,
+ size_t index) {
+ if (index >= seq.size()) {
+ seq.resize(index + 1);
+ seq[index].reset(new dsymutil::DebugMapObject);
+ }
+ return *seq[index];
+}
+
+void MappingTraits<dsymutil::DebugMap>::mapping(IO &io,
+ dsymutil::DebugMap &DM) {
+ io.mapRequired("triple", DM.BinaryTriple);
+ io.mapOptional("binary-path", DM.BinaryPath);
+ 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(
+ IO &io, std::unique_ptr<dsymutil::DebugMap> &DM) {
+ if (!DM)
+ DM.reset(new DebugMap());
+ io.mapRequired("triple", DM->BinaryTriple);
+ io.mapOptional("binary-path", DM->BinaryPath);
+ if (void *Ctxt = io.getContext())
+ reinterpret_cast<YAMLContext *>(Ctxt)->BinaryTriple = DM->BinaryTriple;
+ io.mapOptional("objects", DM->Objects);
+}
+
+MappingTraits<dsymutil::DebugMapObject>::YamlDMO::YamlDMO(
+ IO &io, dsymutil::DebugMapObject &Obj) {
+ Filename = Obj.Filename;
+ Timestamp = sys::toTimeT(Obj.getTimestamp());
+ Entries.reserve(Obj.Symbols.size());
+ for (auto &Entry : Obj.Symbols)
+ Entries.push_back(
+ std::make_pair(std::string(Entry.getKey()), Entry.getValue()));
+}
+
+dsymutil::DebugMapObject
+MappingTraits<dsymutil::DebugMapObject>::YamlDMO::denormalize(IO &IO) {
+ BinaryHolder BinHolder(vfs::getRealFileSystem(), /* Verbose =*/false);
+ const auto &Ctxt = *reinterpret_cast<YAMLContext *>(IO.getContext());
+ SmallString<80> Path(Ctxt.PrependPath);
+ StringMap<uint64_t> SymbolAddresses;
+
+ sys::path::append(Path, Filename);
+
+ auto ObjectEntry = BinHolder.getObjectEntry(Path);
+ if (!ObjectEntry) {
+ auto Err = ObjectEntry.takeError();
+ WithColor::warning() << "Unable to open " << Path << " "
+ << toString(std::move(Err)) << '\n';
+ } else {
+ auto Object = ObjectEntry->getObject(Ctxt.BinaryTriple);
+ if (!Object) {
+ auto Err = Object.takeError();
+ WithColor::warning() << "Unable to open " << Path << " "
+ << toString(std::move(Err)) << '\n';
+ } else {
+ for (const auto &Sym : Object->symbols()) {
+ Expected<uint64_t> AddressOrErr = Sym.getValue();
+ if (!AddressOrErr) {
+ // TODO: Actually report errors helpfully.
+ consumeError(AddressOrErr.takeError());
+ continue;
+ }
+ Expected<StringRef> Name = Sym.getName();
+ Expected<uint32_t> FlagsOrErr = Sym.getFlags();
+ if (!Name || !FlagsOrErr ||
+ (*FlagsOrErr & (SymbolRef::SF_Absolute | SymbolRef::SF_Common))) {
+ // TODO: Actually report errors helpfully.
+ if (!FlagsOrErr)
+ consumeError(FlagsOrErr.takeError());
+ if (!Name)
+ consumeError(Name.takeError());
+ continue;
+ }
+ SymbolAddresses[*Name] = *AddressOrErr;
+ }
+ }
+ }
+
+ dsymutil::DebugMapObject Res(Path, sys::toTimePoint(Timestamp), MachO::N_OSO);
+ for (auto &Entry : Entries) {
+ auto &Mapping = Entry.second;
+ Optional<uint64_t> ObjAddress;
+ if (Mapping.ObjectAddress)
+ ObjAddress = *Mapping.ObjectAddress;
+ auto AddressIt = SymbolAddresses.find(Entry.first);
+ if (AddressIt != SymbolAddresses.end())
+ ObjAddress = AddressIt->getValue();
+ Res.addSymbol(Entry.first, ObjAddress, Mapping.BinaryAddress, Mapping.Size);
+ }
+ return Res;
+}
+
+} // end namespace yaml
+} // end namespace llvm
diff --git a/contrib/libs/llvm12/tools/dsymutil/DebugMap.h b/contrib/libs/llvm12/tools/dsymutil/DebugMap.h
index ee552ed983..3ce8a33a0a 100644
--- a/contrib/libs/llvm12/tools/dsymutil/DebugMap.h
+++ b/contrib/libs/llvm12/tools/dsymutil/DebugMap.h
@@ -1,272 +1,272 @@
-//=- tools/dsymutil/DebugMap.h - Generic debug map representation -*- C++ -*-=//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-//
-/// \file
-///
-/// This file contains the class declaration of the DebugMap
-/// entity. A DebugMap lists all the object files linked together to
-/// produce an executable along with the linked address of all the
-/// atoms used in these object files.
-/// The DebugMap is an input to the DwarfLinker class that will
-/// extract the Dwarf debug information from the referenced object
-/// files and link their usefull debug info together.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_TOOLS_DSYMUTIL_DEBUGMAP_H
-#define LLVM_TOOLS_DSYMUTIL_DEBUGMAP_H
-
-#include "llvm/ADT/DenseMap.h"
-#include "llvm/ADT/Optional.h"
-#include "llvm/ADT/StringMap.h"
-#include "llvm/ADT/StringRef.h"
-#include "llvm/ADT/Triple.h"
-#include "llvm/ADT/iterator_range.h"
-#include "llvm/Object/MachO.h"
-#include "llvm/Support/Chrono.h"
-#include "llvm/Support/ErrorOr.h"
-#include "llvm/Support/YAMLTraits.h"
-#include <chrono>
-#include <cstddef>
-#include <cstdint>
-#include <memory>
-#include <string>
-#include <utility>
-#include <vector>
-
-namespace llvm {
-
-class raw_ostream;
-
-namespace dsymutil {
-
-class DebugMapObject;
-
-/// The DebugMap object stores the list of object files to query for debug
-/// information along with the mapping between the symbols' addresses in the
-/// object file to their linked address in the linked binary.
-///
-/// A DebugMap producer could look like this:
-/// DebugMap *DM = new DebugMap();
-/// for (const auto &Obj: LinkedObjects) {
-/// DebugMapObject &DMO = DM->addDebugMapObject(Obj.getPath());
-/// for (const auto &Sym: Obj.getLinkedSymbols())
-/// DMO.addSymbol(Sym.getName(), Sym.getObjectFileAddress(),
-/// Sym.getBinaryAddress());
-/// }
-///
-/// A DebugMap consumer can then use the map to link the debug
-/// information. For example something along the lines of:
-/// for (const auto &DMO: DM->objects()) {
-/// auto Obj = createBinary(DMO.getObjectFilename());
-/// for (auto &DIE: Obj.getDwarfDIEs()) {
-/// if (SymbolMapping *Sym = DMO.lookup(DIE.getName()))
-/// DIE.relocate(Sym->ObjectAddress, Sym->BinaryAddress);
-/// else
-/// DIE.discardSubtree();
-/// }
-/// }
-class DebugMap {
- Triple BinaryTriple;
- std::string BinaryPath;
- std::vector<uint8_t> BinaryUUID;
- using ObjectContainer = std::vector<std::unique_ptr<DebugMapObject>>;
-
- ObjectContainer Objects;
-
- /// For YAML IO support.
- ///@{
- friend yaml::MappingTraits<std::unique_ptr<DebugMap>>;
- friend yaml::MappingTraits<DebugMap>;
-
- DebugMap() = default;
- ///@}
-
-public:
- DebugMap(const Triple &BinaryTriple, StringRef BinaryPath,
- ArrayRef<uint8_t> BinaryUUID = ArrayRef<uint8_t>())
- : BinaryTriple(BinaryTriple), BinaryPath(std::string(BinaryPath)),
- BinaryUUID(BinaryUUID.begin(), BinaryUUID.end()) {}
-
- using const_iterator = ObjectContainer::const_iterator;
-
- iterator_range<const_iterator> objects() const {
- return make_range(begin(), end());
- }
-
- const_iterator begin() const { return Objects.begin(); }
-
- const_iterator end() const { return Objects.end(); }
-
- unsigned getNumberOfObjects() const { return Objects.size(); }
-
- /// This function adds an DebugMapObject to the list owned by this
- /// debug map.
- DebugMapObject &
- addDebugMapObject(StringRef ObjectFilePath,
- sys::TimePoint<std::chrono::seconds> Timestamp,
- uint8_t Type = llvm::MachO::N_OSO);
-
- const Triple &getTriple() const { return BinaryTriple; }
-
- const ArrayRef<uint8_t> getUUID() const {
- return ArrayRef<uint8_t>(BinaryUUID);
- }
-
- StringRef getBinaryPath() const { return BinaryPath; }
-
- void print(raw_ostream &OS) const;
-
-#ifndef NDEBUG
- void dump() const;
-#endif
-
- /// Read a debug map for \a InputFile.
- static ErrorOr<std::vector<std::unique_ptr<DebugMap>>>
- parseYAMLDebugMap(StringRef InputFile, StringRef PrependPath, bool Verbose);
-};
-
-/// The DebugMapObject represents one object file described by the DebugMap. It
-/// contains a list of mappings between addresses in the object file and in the
-/// linked binary for all the linked atoms in this object file.
-class DebugMapObject {
-public:
- struct SymbolMapping {
- Optional<yaml::Hex64> ObjectAddress;
- yaml::Hex64 BinaryAddress;
- yaml::Hex32 Size;
-
- SymbolMapping(Optional<uint64_t> ObjectAddr, uint64_t BinaryAddress,
- uint32_t Size)
- : BinaryAddress(BinaryAddress), Size(Size) {
- if (ObjectAddr)
- ObjectAddress = *ObjectAddr;
- }
-
- /// For YAML IO support
- SymbolMapping() = default;
- };
-
- using YAMLSymbolMapping = std::pair<std::string, SymbolMapping>;
- using DebugMapEntry = StringMapEntry<SymbolMapping>;
-
- /// Adds a symbol mapping to this DebugMapObject.
- /// \returns false if the symbol was already registered. The request
- /// is discarded in this case.
- bool addSymbol(StringRef SymName, Optional<uint64_t> ObjectAddress,
- uint64_t LinkedAddress, uint32_t Size);
-
- /// Lookup a symbol mapping.
- /// \returns null if the symbol isn't found.
- const DebugMapEntry *lookupSymbol(StringRef SymbolName) const;
-
- /// Lookup an object file address.
- /// \returns null if the address isn't found.
- const DebugMapEntry *lookupObjectAddress(uint64_t Address) const;
-
- StringRef getObjectFilename() const { return Filename; }
-
- sys::TimePoint<std::chrono::seconds> getTimestamp() const {
- return Timestamp;
- }
-
- uint8_t getType() const { return Type; }
-
- iterator_range<StringMap<SymbolMapping>::const_iterator> symbols() const {
- return make_range(Symbols.begin(), Symbols.end());
- }
-
- bool empty() const { return Symbols.empty(); }
-
- void addWarning(StringRef Warning) {
- Warnings.push_back(std::string(Warning));
- }
- const std::vector<std::string> &getWarnings() const { return Warnings; }
-
- void print(raw_ostream &OS) const;
-#ifndef NDEBUG
- void dump() const;
-#endif
-
-private:
- friend class DebugMap;
-
- /// DebugMapObjects can only be constructed by the owning DebugMap.
- DebugMapObject(StringRef ObjectFilename,
- 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;
-
- std::vector<std::string> Warnings;
-
- /// For YAMLIO support.
- ///@{
- friend yaml::MappingTraits<dsymutil::DebugMapObject>;
- friend yaml::SequenceTraits<std::vector<std::unique_ptr<DebugMapObject>>>;
-
- DebugMapObject() = default;
-
-public:
- DebugMapObject(DebugMapObject &&) = default;
- DebugMapObject &operator=(DebugMapObject &&) = default;
- ///@}
-};
-
-} // end namespace dsymutil
-} // end namespace llvm
-
-LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::dsymutil::DebugMapObject::YAMLSymbolMapping)
-
-namespace llvm {
-namespace yaml {
-
-using namespace llvm::dsymutil;
-
-template <>
-struct MappingTraits<std::pair<std::string, DebugMapObject::SymbolMapping>> {
- static void mapping(IO &io,
- std::pair<std::string, DebugMapObject::SymbolMapping> &s);
- static const bool flow = true;
-};
-
-template <> struct MappingTraits<dsymutil::DebugMapObject> {
- struct YamlDMO;
- static void mapping(IO &io, dsymutil::DebugMapObject &DMO);
-};
-
-template <> struct ScalarTraits<Triple> {
- static void output(const Triple &val, void *, raw_ostream &out);
- static StringRef input(StringRef scalar, void *, Triple &value);
- static QuotingType mustQuote(StringRef) { return QuotingType::Single; }
-};
-
-template <>
-struct SequenceTraits<std::vector<std::unique_ptr<dsymutil::DebugMapObject>>> {
- static size_t
- size(IO &io, std::vector<std::unique_ptr<dsymutil::DebugMapObject>> &seq);
- static dsymutil::DebugMapObject &
- element(IO &, std::vector<std::unique_ptr<dsymutil::DebugMapObject>> &seq,
- size_t index);
-};
-
-template <> struct MappingTraits<dsymutil::DebugMap> {
- static void mapping(IO &io, dsymutil::DebugMap &DM);
-};
-
-template <> struct MappingTraits<std::unique_ptr<dsymutil::DebugMap>> {
- static void mapping(IO &io, std::unique_ptr<dsymutil::DebugMap> &DM);
-};
-
-} // end namespace yaml
-} // end namespace llvm
-
-#endif // LLVM_TOOLS_DSYMUTIL_DEBUGMAP_H
+//=- tools/dsymutil/DebugMap.h - Generic debug map representation -*- C++ -*-=//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+/// \file
+///
+/// This file contains the class declaration of the DebugMap
+/// entity. A DebugMap lists all the object files linked together to
+/// produce an executable along with the linked address of all the
+/// atoms used in these object files.
+/// The DebugMap is an input to the DwarfLinker class that will
+/// extract the Dwarf debug information from the referenced object
+/// files and link their usefull debug info together.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TOOLS_DSYMUTIL_DEBUGMAP_H
+#define LLVM_TOOLS_DSYMUTIL_DEBUGMAP_H
+
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/Optional.h"
+#include "llvm/ADT/StringMap.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/Triple.h"
+#include "llvm/ADT/iterator_range.h"
+#include "llvm/Object/MachO.h"
+#include "llvm/Support/Chrono.h"
+#include "llvm/Support/ErrorOr.h"
+#include "llvm/Support/YAMLTraits.h"
+#include <chrono>
+#include <cstddef>
+#include <cstdint>
+#include <memory>
+#include <string>
+#include <utility>
+#include <vector>
+
+namespace llvm {
+
+class raw_ostream;
+
+namespace dsymutil {
+
+class DebugMapObject;
+
+/// The DebugMap object stores the list of object files to query for debug
+/// information along with the mapping between the symbols' addresses in the
+/// object file to their linked address in the linked binary.
+///
+/// A DebugMap producer could look like this:
+/// DebugMap *DM = new DebugMap();
+/// for (const auto &Obj: LinkedObjects) {
+/// DebugMapObject &DMO = DM->addDebugMapObject(Obj.getPath());
+/// for (const auto &Sym: Obj.getLinkedSymbols())
+/// DMO.addSymbol(Sym.getName(), Sym.getObjectFileAddress(),
+/// Sym.getBinaryAddress());
+/// }
+///
+/// A DebugMap consumer can then use the map to link the debug
+/// information. For example something along the lines of:
+/// for (const auto &DMO: DM->objects()) {
+/// auto Obj = createBinary(DMO.getObjectFilename());
+/// for (auto &DIE: Obj.getDwarfDIEs()) {
+/// if (SymbolMapping *Sym = DMO.lookup(DIE.getName()))
+/// DIE.relocate(Sym->ObjectAddress, Sym->BinaryAddress);
+/// else
+/// DIE.discardSubtree();
+/// }
+/// }
+class DebugMap {
+ Triple BinaryTriple;
+ std::string BinaryPath;
+ std::vector<uint8_t> BinaryUUID;
+ using ObjectContainer = std::vector<std::unique_ptr<DebugMapObject>>;
+
+ ObjectContainer Objects;
+
+ /// For YAML IO support.
+ ///@{
+ friend yaml::MappingTraits<std::unique_ptr<DebugMap>>;
+ friend yaml::MappingTraits<DebugMap>;
+
+ DebugMap() = default;
+ ///@}
+
+public:
+ DebugMap(const Triple &BinaryTriple, StringRef BinaryPath,
+ ArrayRef<uint8_t> BinaryUUID = ArrayRef<uint8_t>())
+ : BinaryTriple(BinaryTriple), BinaryPath(std::string(BinaryPath)),
+ BinaryUUID(BinaryUUID.begin(), BinaryUUID.end()) {}
+
+ using const_iterator = ObjectContainer::const_iterator;
+
+ iterator_range<const_iterator> objects() const {
+ return make_range(begin(), end());
+ }
+
+ const_iterator begin() const { return Objects.begin(); }
+
+ const_iterator end() const { return Objects.end(); }
+
+ unsigned getNumberOfObjects() const { return Objects.size(); }
+
+ /// This function adds an DebugMapObject to the list owned by this
+ /// debug map.
+ DebugMapObject &
+ addDebugMapObject(StringRef ObjectFilePath,
+ sys::TimePoint<std::chrono::seconds> Timestamp,
+ uint8_t Type = llvm::MachO::N_OSO);
+
+ const Triple &getTriple() const { return BinaryTriple; }
+
+ const ArrayRef<uint8_t> getUUID() const {
+ return ArrayRef<uint8_t>(BinaryUUID);
+ }
+
+ StringRef getBinaryPath() const { return BinaryPath; }
+
+ void print(raw_ostream &OS) const;
+
+#ifndef NDEBUG
+ void dump() const;
+#endif
+
+ /// Read a debug map for \a InputFile.
+ static ErrorOr<std::vector<std::unique_ptr<DebugMap>>>
+ parseYAMLDebugMap(StringRef InputFile, StringRef PrependPath, bool Verbose);
+};
+
+/// The DebugMapObject represents one object file described by the DebugMap. It
+/// contains a list of mappings between addresses in the object file and in the
+/// linked binary for all the linked atoms in this object file.
+class DebugMapObject {
+public:
+ struct SymbolMapping {
+ Optional<yaml::Hex64> ObjectAddress;
+ yaml::Hex64 BinaryAddress;
+ yaml::Hex32 Size;
+
+ SymbolMapping(Optional<uint64_t> ObjectAddr, uint64_t BinaryAddress,
+ uint32_t Size)
+ : BinaryAddress(BinaryAddress), Size(Size) {
+ if (ObjectAddr)
+ ObjectAddress = *ObjectAddr;
+ }
+
+ /// For YAML IO support
+ SymbolMapping() = default;
+ };
+
+ using YAMLSymbolMapping = std::pair<std::string, SymbolMapping>;
+ using DebugMapEntry = StringMapEntry<SymbolMapping>;
+
+ /// Adds a symbol mapping to this DebugMapObject.
+ /// \returns false if the symbol was already registered. The request
+ /// is discarded in this case.
+ bool addSymbol(StringRef SymName, Optional<uint64_t> ObjectAddress,
+ uint64_t LinkedAddress, uint32_t Size);
+
+ /// Lookup a symbol mapping.
+ /// \returns null if the symbol isn't found.
+ const DebugMapEntry *lookupSymbol(StringRef SymbolName) const;
+
+ /// Lookup an object file address.
+ /// \returns null if the address isn't found.
+ const DebugMapEntry *lookupObjectAddress(uint64_t Address) const;
+
+ StringRef getObjectFilename() const { return Filename; }
+
+ sys::TimePoint<std::chrono::seconds> getTimestamp() const {
+ return Timestamp;
+ }
+
+ uint8_t getType() const { return Type; }
+
+ iterator_range<StringMap<SymbolMapping>::const_iterator> symbols() const {
+ return make_range(Symbols.begin(), Symbols.end());
+ }
+
+ bool empty() const { return Symbols.empty(); }
+
+ void addWarning(StringRef Warning) {
+ Warnings.push_back(std::string(Warning));
+ }
+ const std::vector<std::string> &getWarnings() const { return Warnings; }
+
+ void print(raw_ostream &OS) const;
+#ifndef NDEBUG
+ void dump() const;
+#endif
+
+private:
+ friend class DebugMap;
+
+ /// DebugMapObjects can only be constructed by the owning DebugMap.
+ DebugMapObject(StringRef ObjectFilename,
+ 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;
+
+ std::vector<std::string> Warnings;
+
+ /// For YAMLIO support.
+ ///@{
+ friend yaml::MappingTraits<dsymutil::DebugMapObject>;
+ friend yaml::SequenceTraits<std::vector<std::unique_ptr<DebugMapObject>>>;
+
+ DebugMapObject() = default;
+
+public:
+ DebugMapObject(DebugMapObject &&) = default;
+ DebugMapObject &operator=(DebugMapObject &&) = default;
+ ///@}
+};
+
+} // end namespace dsymutil
+} // end namespace llvm
+
+LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::dsymutil::DebugMapObject::YAMLSymbolMapping)
+
+namespace llvm {
+namespace yaml {
+
+using namespace llvm::dsymutil;
+
+template <>
+struct MappingTraits<std::pair<std::string, DebugMapObject::SymbolMapping>> {
+ static void mapping(IO &io,
+ std::pair<std::string, DebugMapObject::SymbolMapping> &s);
+ static const bool flow = true;
+};
+
+template <> struct MappingTraits<dsymutil::DebugMapObject> {
+ struct YamlDMO;
+ static void mapping(IO &io, dsymutil::DebugMapObject &DMO);
+};
+
+template <> struct ScalarTraits<Triple> {
+ static void output(const Triple &val, void *, raw_ostream &out);
+ static StringRef input(StringRef scalar, void *, Triple &value);
+ static QuotingType mustQuote(StringRef) { return QuotingType::Single; }
+};
+
+template <>
+struct SequenceTraits<std::vector<std::unique_ptr<dsymutil::DebugMapObject>>> {
+ static size_t
+ size(IO &io, std::vector<std::unique_ptr<dsymutil::DebugMapObject>> &seq);
+ static dsymutil::DebugMapObject &
+ element(IO &, std::vector<std::unique_ptr<dsymutil::DebugMapObject>> &seq,
+ size_t index);
+};
+
+template <> struct MappingTraits<dsymutil::DebugMap> {
+ static void mapping(IO &io, dsymutil::DebugMap &DM);
+};
+
+template <> struct MappingTraits<std::unique_ptr<dsymutil::DebugMap>> {
+ static void mapping(IO &io, std::unique_ptr<dsymutil::DebugMap> &DM);
+};
+
+} // end namespace yaml
+} // end namespace llvm
+
+#endif // LLVM_TOOLS_DSYMUTIL_DEBUGMAP_H
diff --git a/contrib/libs/llvm12/tools/dsymutil/DwarfLinkerForBinary.cpp b/contrib/libs/llvm12/tools/dsymutil/DwarfLinkerForBinary.cpp
index 29408e7c49..1cb561dbac 100644
--- a/contrib/libs/llvm12/tools/dsymutil/DwarfLinkerForBinary.cpp
+++ b/contrib/libs/llvm12/tools/dsymutil/DwarfLinkerForBinary.cpp
@@ -1,616 +1,616 @@
-//===- tools/dsymutil/DwarfLinkerForBinary.cpp ----------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "DwarfLinkerForBinary.h"
-#include "BinaryHolder.h"
-#include "DebugMap.h"
-#include "MachOUtils.h"
-#include "dsymutil.h"
-#include "llvm/ADT/ArrayRef.h"
-#include "llvm/ADT/BitVector.h"
-#include "llvm/ADT/DenseMap.h"
-#include "llvm/ADT/DenseMapInfo.h"
-#include "llvm/ADT/DenseSet.h"
-#include "llvm/ADT/FoldingSet.h"
-#include "llvm/ADT/Hashing.h"
-#include "llvm/ADT/IntervalMap.h"
-#include "llvm/ADT/None.h"
-#include "llvm/ADT/Optional.h"
-#include "llvm/ADT/PointerIntPair.h"
-#include "llvm/ADT/STLExtras.h"
-#include "llvm/ADT/SmallString.h"
-#include "llvm/ADT/StringMap.h"
-#include "llvm/ADT/StringRef.h"
-#include "llvm/ADT/Triple.h"
-#include "llvm/ADT/Twine.h"
-#include "llvm/BinaryFormat/Dwarf.h"
-#include "llvm/BinaryFormat/MachO.h"
-#include "llvm/CodeGen/AccelTable.h"
-#include "llvm/CodeGen/AsmPrinter.h"
-#include "llvm/CodeGen/DIE.h"
-#include "llvm/CodeGen/NonRelocatableStringpool.h"
-#include "llvm/Config/config.h"
-#include "llvm/DWARFLinker/DWARFLinkerDeclContext.h"
-#include "llvm/DebugInfo/DIContext.h"
-#include "llvm/DebugInfo/DWARF/DWARFAbbreviationDeclaration.h"
-#include "llvm/DebugInfo/DWARF/DWARFContext.h"
-#include "llvm/DebugInfo/DWARF/DWARFDataExtractor.h"
-#include "llvm/DebugInfo/DWARF/DWARFDebugLine.h"
-#include "llvm/DebugInfo/DWARF/DWARFDebugRangeList.h"
-#include "llvm/DebugInfo/DWARF/DWARFDie.h"
-#include "llvm/DebugInfo/DWARF/DWARFFormValue.h"
-#include "llvm/DebugInfo/DWARF/DWARFSection.h"
-#include "llvm/DebugInfo/DWARF/DWARFUnit.h"
-#include "llvm/MC/MCAsmBackend.h"
-#include "llvm/MC/MCAsmInfo.h"
-#include "llvm/MC/MCCodeEmitter.h"
-#include "llvm/MC/MCContext.h"
-#include "llvm/MC/MCDwarf.h"
-#include "llvm/MC/MCInstrInfo.h"
-#include "llvm/MC/MCObjectFileInfo.h"
-#include "llvm/MC/MCObjectWriter.h"
-#include "llvm/MC/MCRegisterInfo.h"
-#include "llvm/MC/MCSection.h"
-#include "llvm/MC/MCStreamer.h"
-#include "llvm/MC/MCSubtargetInfo.h"
-#include "llvm/MC/MCTargetOptions.h"
-#include "llvm/Object/MachO.h"
-#include "llvm/Object/ObjectFile.h"
-#include "llvm/Object/SymbolicFile.h"
-#include "llvm/Support/Allocator.h"
-#include "llvm/Support/Casting.h"
-#include "llvm/Support/Compiler.h"
-#include "llvm/Support/DJB.h"
-#include "llvm/Support/DataExtractor.h"
-#include "llvm/Support/Error.h"
-#include "llvm/Support/ErrorHandling.h"
-#include "llvm/Support/ErrorOr.h"
-#include "llvm/Support/FileSystem.h"
-#include "llvm/Support/Format.h"
-#include "llvm/Support/LEB128.h"
-#include "llvm/Support/MathExtras.h"
-#include "llvm/Support/MemoryBuffer.h"
-#include "llvm/Support/Path.h"
-#include "llvm/Support/TargetRegistry.h"
-#include "llvm/Support/ThreadPool.h"
-#include "llvm/Support/ToolOutputFile.h"
-#include "llvm/Support/WithColor.h"
-#include "llvm/Support/raw_ostream.h"
-#include "llvm/Target/TargetMachine.h"
-#include "llvm/Target/TargetOptions.h"
-#include "llvm/MC/MCTargetOptionsCommandFlags.h"
-#include <algorithm>
-#include <cassert>
-#include <cinttypes>
-#include <climits>
-#include <cstdint>
-#include <cstdlib>
-#include <cstring>
-#include <limits>
-#include <map>
-#include <memory>
-#include <string>
-#include <system_error>
-#include <tuple>
-#include <utility>
-#include <vector>
-
-namespace llvm {
-
-static mc::RegisterMCTargetOptionsFlags MOF;
-
-namespace dsymutil {
-
-static Error copySwiftInterfaces(
- const std::map<std::string, std::string> &ParseableSwiftInterfaces,
- StringRef Architecture, const LinkOptions &Options) {
- std::error_code EC;
- SmallString<128> InputPath;
- SmallString<128> Path;
- sys::path::append(Path, *Options.ResourceDir, "Swift", Architecture);
- if ((EC = sys::fs::create_directories(Path.str(), true,
- sys::fs::perms::all_all)))
- return make_error<StringError>(
- "cannot create directory: " + toString(errorCodeToError(EC)), EC);
- unsigned BaseLength = Path.size();
-
- for (auto &I : ParseableSwiftInterfaces) {
- StringRef ModuleName = I.first;
- StringRef InterfaceFile = I.second;
- if (!Options.PrependPath.empty()) {
- InputPath.clear();
- sys::path::append(InputPath, Options.PrependPath, InterfaceFile);
- InterfaceFile = InputPath;
- }
- sys::path::append(Path, ModuleName);
- Path.append(".swiftinterface");
- if (Options.Verbose)
- outs() << "copy parseable Swift interface " << InterfaceFile << " -> "
- << Path.str() << '\n';
-
- // copy_file attempts an APFS clone first, so this should be cheap.
- if ((EC = sys::fs::copy_file(InterfaceFile, Path.str())))
- warn(Twine("cannot copy parseable Swift interface ") + InterfaceFile +
- ": " + toString(errorCodeToError(EC)));
- Path.resize(BaseLength);
- }
- return Error::success();
-}
-
-/// Report a warning to the user, optionally including information about a
-/// specific \p DIE related to the warning.
-void DwarfLinkerForBinary::reportWarning(const Twine &Warning,
- StringRef Context,
- const DWARFDie *DIE) const {
-
- warn(Warning, Context);
-
- if (!Options.Verbose || !DIE)
- return;
-
- DIDumpOptions DumpOpts;
- DumpOpts.ChildRecurseDepth = 0;
- DumpOpts.Verbose = Options.Verbose;
-
- WithColor::note() << " in DIE:\n";
- DIE->dump(errs(), 6 /* Indent */, DumpOpts);
-}
-
-bool DwarfLinkerForBinary::createStreamer(const Triple &TheTriple,
- raw_fd_ostream &OutFile) {
- if (Options.NoOutput)
- return true;
-
- Streamer = std::make_unique<DwarfStreamer>(
- Options.FileType, OutFile, Options.Translator, Options.Minimize,
- [&](const Twine &Error, StringRef Context, const DWARFDie *) {
- error(Error, Context);
- },
- [&](const Twine &Warning, StringRef Context, const DWARFDie *) {
- warn(Warning, Context);
- });
- return Streamer->init(TheTriple);
-}
-
-ErrorOr<const object::ObjectFile &>
-DwarfLinkerForBinary::loadObject(const DebugMapObject &Obj,
- const Triple &Triple) {
- auto ObjectEntry =
- BinHolder.getObjectEntry(Obj.getObjectFilename(), Obj.getTimestamp());
- if (!ObjectEntry) {
- auto Err = ObjectEntry.takeError();
- reportWarning(Twine(Obj.getObjectFilename()) + ": " +
- toString(std::move(Err)),
- Obj.getObjectFilename());
- return errorToErrorCode(std::move(Err));
- }
-
- auto Object = ObjectEntry->getObject(Triple);
- if (!Object) {
- auto Err = Object.takeError();
- reportWarning(Twine(Obj.getObjectFilename()) + ": " +
- toString(std::move(Err)),
- Obj.getObjectFilename());
- return errorToErrorCode(std::move(Err));
- }
-
- return *Object;
-}
-
-static Error remarksErrorHandler(const DebugMapObject &DMO,
- DwarfLinkerForBinary &Linker,
- std::unique_ptr<FileError> FE) {
- bool IsArchive = DMO.getObjectFilename().endswith(")");
- // Don't report errors for missing remark files from static
- // archives.
- if (!IsArchive)
- return Error(std::move(FE));
-
- std::string Message = FE->message();
- Error E = FE->takeError();
- Error NewE = handleErrors(std::move(E), [&](std::unique_ptr<ECError> EC) {
- if (EC->convertToErrorCode() != std::errc::no_such_file_or_directory)
- return Error(std::move(EC));
-
- Linker.reportWarning(Message, DMO.getObjectFilename());
- return Error(Error::success());
- });
-
- if (!NewE)
- return Error::success();
-
- return createFileError(FE->getFileName(), std::move(NewE));
-}
-
-static Error emitRemarks(const LinkOptions &Options, StringRef BinaryPath,
- StringRef ArchName, const remarks::RemarkLinker &RL) {
- // Make sure we don't create the directories and the file if there is nothing
- // to serialize.
- if (RL.empty())
- return Error::success();
-
- SmallString<128> InputPath;
- SmallString<128> Path;
- // Create the "Remarks" directory in the "Resources" directory.
- sys::path::append(Path, *Options.ResourceDir, "Remarks");
- if (std::error_code EC = sys::fs::create_directories(Path.str(), true,
- sys::fs::perms::all_all))
- return errorCodeToError(EC);
-
- // Append the file name.
- // For fat binaries, also append a dash and the architecture name.
- sys::path::append(Path, sys::path::filename(BinaryPath));
- if (Options.NumDebugMaps > 1) {
- // More than one debug map means we have a fat binary.
- Path += '-';
- Path += ArchName;
- }
-
- std::error_code EC;
- raw_fd_ostream OS(Options.NoOutput ? "-" : Path.str(), EC, sys::fs::OF_None);
- if (EC)
- return errorCodeToError(EC);
-
- if (Error E = RL.serialize(OS, Options.RemarksFormat))
- return E;
-
- return Error::success();
-}
-
+//===- tools/dsymutil/DwarfLinkerForBinary.cpp ----------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "DwarfLinkerForBinary.h"
+#include "BinaryHolder.h"
+#include "DebugMap.h"
+#include "MachOUtils.h"
+#include "dsymutil.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/BitVector.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/DenseMapInfo.h"
+#include "llvm/ADT/DenseSet.h"
+#include "llvm/ADT/FoldingSet.h"
+#include "llvm/ADT/Hashing.h"
+#include "llvm/ADT/IntervalMap.h"
+#include "llvm/ADT/None.h"
+#include "llvm/ADT/Optional.h"
+#include "llvm/ADT/PointerIntPair.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/StringMap.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/Triple.h"
+#include "llvm/ADT/Twine.h"
+#include "llvm/BinaryFormat/Dwarf.h"
+#include "llvm/BinaryFormat/MachO.h"
+#include "llvm/CodeGen/AccelTable.h"
+#include "llvm/CodeGen/AsmPrinter.h"
+#include "llvm/CodeGen/DIE.h"
+#include "llvm/CodeGen/NonRelocatableStringpool.h"
+#include "llvm/Config/config.h"
+#include "llvm/DWARFLinker/DWARFLinkerDeclContext.h"
+#include "llvm/DebugInfo/DIContext.h"
+#include "llvm/DebugInfo/DWARF/DWARFAbbreviationDeclaration.h"
+#include "llvm/DebugInfo/DWARF/DWARFContext.h"
+#include "llvm/DebugInfo/DWARF/DWARFDataExtractor.h"
+#include "llvm/DebugInfo/DWARF/DWARFDebugLine.h"
+#include "llvm/DebugInfo/DWARF/DWARFDebugRangeList.h"
+#include "llvm/DebugInfo/DWARF/DWARFDie.h"
+#include "llvm/DebugInfo/DWARF/DWARFFormValue.h"
+#include "llvm/DebugInfo/DWARF/DWARFSection.h"
+#include "llvm/DebugInfo/DWARF/DWARFUnit.h"
+#include "llvm/MC/MCAsmBackend.h"
+#include "llvm/MC/MCAsmInfo.h"
+#include "llvm/MC/MCCodeEmitter.h"
+#include "llvm/MC/MCContext.h"
+#include "llvm/MC/MCDwarf.h"
+#include "llvm/MC/MCInstrInfo.h"
+#include "llvm/MC/MCObjectFileInfo.h"
+#include "llvm/MC/MCObjectWriter.h"
+#include "llvm/MC/MCRegisterInfo.h"
+#include "llvm/MC/MCSection.h"
+#include "llvm/MC/MCStreamer.h"
+#include "llvm/MC/MCSubtargetInfo.h"
+#include "llvm/MC/MCTargetOptions.h"
+#include "llvm/Object/MachO.h"
+#include "llvm/Object/ObjectFile.h"
+#include "llvm/Object/SymbolicFile.h"
+#include "llvm/Support/Allocator.h"
+#include "llvm/Support/Casting.h"
+#include "llvm/Support/Compiler.h"
+#include "llvm/Support/DJB.h"
+#include "llvm/Support/DataExtractor.h"
+#include "llvm/Support/Error.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/ErrorOr.h"
+#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/Format.h"
+#include "llvm/Support/LEB128.h"
+#include "llvm/Support/MathExtras.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/Path.h"
+#include "llvm/Support/TargetRegistry.h"
+#include "llvm/Support/ThreadPool.h"
+#include "llvm/Support/ToolOutputFile.h"
+#include "llvm/Support/WithColor.h"
+#include "llvm/Support/raw_ostream.h"
+#include "llvm/Target/TargetMachine.h"
+#include "llvm/Target/TargetOptions.h"
+#include "llvm/MC/MCTargetOptionsCommandFlags.h"
+#include <algorithm>
+#include <cassert>
+#include <cinttypes>
+#include <climits>
+#include <cstdint>
+#include <cstdlib>
+#include <cstring>
+#include <limits>
+#include <map>
+#include <memory>
+#include <string>
+#include <system_error>
+#include <tuple>
+#include <utility>
+#include <vector>
+
+namespace llvm {
+
+static mc::RegisterMCTargetOptionsFlags MOF;
+
+namespace dsymutil {
+
+static Error copySwiftInterfaces(
+ const std::map<std::string, std::string> &ParseableSwiftInterfaces,
+ StringRef Architecture, const LinkOptions &Options) {
+ std::error_code EC;
+ SmallString<128> InputPath;
+ SmallString<128> Path;
+ sys::path::append(Path, *Options.ResourceDir, "Swift", Architecture);
+ if ((EC = sys::fs::create_directories(Path.str(), true,
+ sys::fs::perms::all_all)))
+ return make_error<StringError>(
+ "cannot create directory: " + toString(errorCodeToError(EC)), EC);
+ unsigned BaseLength = Path.size();
+
+ for (auto &I : ParseableSwiftInterfaces) {
+ StringRef ModuleName = I.first;
+ StringRef InterfaceFile = I.second;
+ if (!Options.PrependPath.empty()) {
+ InputPath.clear();
+ sys::path::append(InputPath, Options.PrependPath, InterfaceFile);
+ InterfaceFile = InputPath;
+ }
+ sys::path::append(Path, ModuleName);
+ Path.append(".swiftinterface");
+ if (Options.Verbose)
+ outs() << "copy parseable Swift interface " << InterfaceFile << " -> "
+ << Path.str() << '\n';
+
+ // copy_file attempts an APFS clone first, so this should be cheap.
+ if ((EC = sys::fs::copy_file(InterfaceFile, Path.str())))
+ warn(Twine("cannot copy parseable Swift interface ") + InterfaceFile +
+ ": " + toString(errorCodeToError(EC)));
+ Path.resize(BaseLength);
+ }
+ return Error::success();
+}
+
+/// Report a warning to the user, optionally including information about a
+/// specific \p DIE related to the warning.
+void DwarfLinkerForBinary::reportWarning(const Twine &Warning,
+ StringRef Context,
+ const DWARFDie *DIE) const {
+
+ warn(Warning, Context);
+
+ if (!Options.Verbose || !DIE)
+ return;
+
+ DIDumpOptions DumpOpts;
+ DumpOpts.ChildRecurseDepth = 0;
+ DumpOpts.Verbose = Options.Verbose;
+
+ WithColor::note() << " in DIE:\n";
+ DIE->dump(errs(), 6 /* Indent */, DumpOpts);
+}
+
+bool DwarfLinkerForBinary::createStreamer(const Triple &TheTriple,
+ raw_fd_ostream &OutFile) {
+ if (Options.NoOutput)
+ return true;
+
+ Streamer = std::make_unique<DwarfStreamer>(
+ Options.FileType, OutFile, Options.Translator, Options.Minimize,
+ [&](const Twine &Error, StringRef Context, const DWARFDie *) {
+ error(Error, Context);
+ },
+ [&](const Twine &Warning, StringRef Context, const DWARFDie *) {
+ warn(Warning, Context);
+ });
+ return Streamer->init(TheTriple);
+}
+
+ErrorOr<const object::ObjectFile &>
+DwarfLinkerForBinary::loadObject(const DebugMapObject &Obj,
+ const Triple &Triple) {
+ auto ObjectEntry =
+ BinHolder.getObjectEntry(Obj.getObjectFilename(), Obj.getTimestamp());
+ if (!ObjectEntry) {
+ auto Err = ObjectEntry.takeError();
+ reportWarning(Twine(Obj.getObjectFilename()) + ": " +
+ toString(std::move(Err)),
+ Obj.getObjectFilename());
+ return errorToErrorCode(std::move(Err));
+ }
+
+ auto Object = ObjectEntry->getObject(Triple);
+ if (!Object) {
+ auto Err = Object.takeError();
+ reportWarning(Twine(Obj.getObjectFilename()) + ": " +
+ toString(std::move(Err)),
+ Obj.getObjectFilename());
+ return errorToErrorCode(std::move(Err));
+ }
+
+ return *Object;
+}
+
+static Error remarksErrorHandler(const DebugMapObject &DMO,
+ DwarfLinkerForBinary &Linker,
+ std::unique_ptr<FileError> FE) {
+ bool IsArchive = DMO.getObjectFilename().endswith(")");
+ // Don't report errors for missing remark files from static
+ // archives.
+ if (!IsArchive)
+ return Error(std::move(FE));
+
+ std::string Message = FE->message();
+ Error E = FE->takeError();
+ Error NewE = handleErrors(std::move(E), [&](std::unique_ptr<ECError> EC) {
+ if (EC->convertToErrorCode() != std::errc::no_such_file_or_directory)
+ return Error(std::move(EC));
+
+ Linker.reportWarning(Message, DMO.getObjectFilename());
+ return Error(Error::success());
+ });
+
+ if (!NewE)
+ return Error::success();
+
+ return createFileError(FE->getFileName(), std::move(NewE));
+}
+
+static Error emitRemarks(const LinkOptions &Options, StringRef BinaryPath,
+ StringRef ArchName, const remarks::RemarkLinker &RL) {
+ // Make sure we don't create the directories and the file if there is nothing
+ // to serialize.
+ if (RL.empty())
+ return Error::success();
+
+ SmallString<128> InputPath;
+ SmallString<128> Path;
+ // Create the "Remarks" directory in the "Resources" directory.
+ sys::path::append(Path, *Options.ResourceDir, "Remarks");
+ if (std::error_code EC = sys::fs::create_directories(Path.str(), true,
+ sys::fs::perms::all_all))
+ return errorCodeToError(EC);
+
+ // Append the file name.
+ // For fat binaries, also append a dash and the architecture name.
+ sys::path::append(Path, sys::path::filename(BinaryPath));
+ if (Options.NumDebugMaps > 1) {
+ // More than one debug map means we have a fat binary.
+ Path += '-';
+ Path += ArchName;
+ }
+
+ std::error_code EC;
+ raw_fd_ostream OS(Options.NoOutput ? "-" : Path.str(), EC, sys::fs::OF_None);
+ if (EC)
+ return errorCodeToError(EC);
+
+ if (Error E = RL.serialize(OS, Options.RemarksFormat))
+ return E;
+
+ return Error::success();
+}
+
ErrorOr<DWARFFile &>
-DwarfLinkerForBinary::loadObject(const DebugMapObject &Obj,
- const DebugMap &DebugMap,
- remarks::RemarkLinker &RL) {
- auto ErrorOrObj = loadObject(Obj, DebugMap.getTriple());
-
- if (ErrorOrObj) {
- ContextForLinking.push_back(
- std::unique_ptr<DWARFContext>(DWARFContext::create(*ErrorOrObj)));
- AddressMapForLinking.push_back(
- std::make_unique<AddressManager>(*this, *ErrorOrObj, Obj));
-
+DwarfLinkerForBinary::loadObject(const DebugMapObject &Obj,
+ const DebugMap &DebugMap,
+ remarks::RemarkLinker &RL) {
+ auto ErrorOrObj = loadObject(Obj, DebugMap.getTriple());
+
+ if (ErrorOrObj) {
+ ContextForLinking.push_back(
+ std::unique_ptr<DWARFContext>(DWARFContext::create(*ErrorOrObj)));
+ AddressMapForLinking.push_back(
+ std::make_unique<AddressManager>(*this, *ErrorOrObj, Obj));
+
ObjectsForLinking.push_back(std::make_unique<DWARFFile>(
- Obj.getObjectFilename(), ContextForLinking.back().get(),
- AddressMapForLinking.back().get(),
- Obj.empty() ? Obj.getWarnings() : EmptyWarnings));
-
- Error E = RL.link(*ErrorOrObj);
- if (Error NewE = handleErrors(
- std::move(E), [&](std::unique_ptr<FileError> EC) -> Error {
- return remarksErrorHandler(Obj, *this, std::move(EC));
- }))
- return errorToErrorCode(std::move(NewE));
-
- return *ObjectsForLinking.back();
- }
-
- return ErrorOrObj.getError();
-}
-
-bool DwarfLinkerForBinary::link(const DebugMap &Map) {
- if (!createStreamer(Map.getTriple(), OutFile))
- return false;
-
- ObjectsForLinking.clear();
- ContextForLinking.clear();
- AddressMapForLinking.clear();
-
- DebugMap DebugMap(Map.getTriple(), Map.getBinaryPath());
-
- DWARFLinker GeneralLinker(Streamer.get(), DwarfLinkerClient::Dsymutil);
-
- remarks::RemarkLinker RL;
- if (!Options.RemarksPrependPath.empty())
- RL.setExternalFilePrependPath(Options.RemarksPrependPath);
- GeneralLinker.setObjectPrefixMap(&Options.ObjectPrefixMap);
-
- std::function<StringRef(StringRef)> TranslationLambda = [&](StringRef Input) {
- assert(Options.Translator);
- return Options.Translator(Input);
- };
-
- GeneralLinker.setVerbosity(Options.Verbose);
- GeneralLinker.setStatistics(Options.Statistics);
- GeneralLinker.setNoOutput(Options.NoOutput);
- GeneralLinker.setNoODR(Options.NoODR);
- GeneralLinker.setUpdate(Options.Update);
- GeneralLinker.setNumThreads(Options.Threads);
- GeneralLinker.setAccelTableKind(Options.TheAccelTableKind);
- GeneralLinker.setPrependPath(Options.PrependPath);
- if (Options.Translator)
- GeneralLinker.setStringsTranslator(TranslationLambda);
- GeneralLinker.setWarningHandler(
- [&](const Twine &Warning, StringRef Context, const DWARFDie *DIE) {
- reportWarning(Warning, Context, DIE);
- });
- GeneralLinker.setErrorHandler(
- [&](const Twine &Error, StringRef Context, const DWARFDie *) {
- error(Error, Context);
- });
- GeneralLinker.setObjFileLoader(
- [&DebugMap, &RL, this](StringRef ContainerName,
+ Obj.getObjectFilename(), ContextForLinking.back().get(),
+ AddressMapForLinking.back().get(),
+ Obj.empty() ? Obj.getWarnings() : EmptyWarnings));
+
+ Error E = RL.link(*ErrorOrObj);
+ if (Error NewE = handleErrors(
+ std::move(E), [&](std::unique_ptr<FileError> EC) -> Error {
+ return remarksErrorHandler(Obj, *this, std::move(EC));
+ }))
+ return errorToErrorCode(std::move(NewE));
+
+ return *ObjectsForLinking.back();
+ }
+
+ return ErrorOrObj.getError();
+}
+
+bool DwarfLinkerForBinary::link(const DebugMap &Map) {
+ if (!createStreamer(Map.getTriple(), OutFile))
+ return false;
+
+ ObjectsForLinking.clear();
+ ContextForLinking.clear();
+ AddressMapForLinking.clear();
+
+ DebugMap DebugMap(Map.getTriple(), Map.getBinaryPath());
+
+ DWARFLinker GeneralLinker(Streamer.get(), DwarfLinkerClient::Dsymutil);
+
+ remarks::RemarkLinker RL;
+ if (!Options.RemarksPrependPath.empty())
+ RL.setExternalFilePrependPath(Options.RemarksPrependPath);
+ GeneralLinker.setObjectPrefixMap(&Options.ObjectPrefixMap);
+
+ std::function<StringRef(StringRef)> TranslationLambda = [&](StringRef Input) {
+ assert(Options.Translator);
+ return Options.Translator(Input);
+ };
+
+ GeneralLinker.setVerbosity(Options.Verbose);
+ GeneralLinker.setStatistics(Options.Statistics);
+ GeneralLinker.setNoOutput(Options.NoOutput);
+ GeneralLinker.setNoODR(Options.NoODR);
+ GeneralLinker.setUpdate(Options.Update);
+ GeneralLinker.setNumThreads(Options.Threads);
+ GeneralLinker.setAccelTableKind(Options.TheAccelTableKind);
+ GeneralLinker.setPrependPath(Options.PrependPath);
+ if (Options.Translator)
+ GeneralLinker.setStringsTranslator(TranslationLambda);
+ GeneralLinker.setWarningHandler(
+ [&](const Twine &Warning, StringRef Context, const DWARFDie *DIE) {
+ reportWarning(Warning, Context, DIE);
+ });
+ GeneralLinker.setErrorHandler(
+ [&](const Twine &Error, StringRef Context, const DWARFDie *) {
+ error(Error, Context);
+ });
+ GeneralLinker.setObjFileLoader(
+ [&DebugMap, &RL, this](StringRef ContainerName,
StringRef Path) -> ErrorOr<DWARFFile &> {
- auto &Obj = DebugMap.addDebugMapObject(
- Path, sys::TimePoint<std::chrono::seconds>(), MachO::N_OSO);
-
- if (auto ErrorOrObj = loadObject(Obj, DebugMap, RL)) {
- return *ErrorOrObj;
- } else {
- // Try and emit more helpful warnings by applying some heuristics.
- StringRef ObjFile = ContainerName;
- bool IsClangModule = sys::path::extension(Path).equals(".pcm");
- bool IsArchive = ObjFile.endswith(")");
-
- if (IsClangModule) {
- StringRef ModuleCacheDir = sys::path::parent_path(Path);
- if (sys::fs::exists(ModuleCacheDir)) {
- // If the module's parent directory exists, we assume that the
- // module cache has expired and was pruned by clang. A more
- // adventurous dsymutil would invoke clang to rebuild the module
- // now.
- if (!ModuleCacheHintDisplayed) {
- WithColor::note()
- << "The clang module cache may have expired since "
- "this object file was built. Rebuilding the "
- "object file will rebuild the module cache.\n";
- ModuleCacheHintDisplayed = true;
- }
- } else if (IsArchive) {
- // If the module cache directory doesn't exist at all and the
- // object file is inside a static library, we assume that the
- // static library was built on a different machine. We don't want
- // to discourage module debugging for convenience libraries within
- // a project though.
- if (!ArchiveHintDisplayed) {
- WithColor::note()
- << "Linking a static library that was built with "
- "-gmodules, but the module cache was not found. "
- "Redistributable static libraries should never be "
- "built with module debugging enabled. The debug "
- "experience will be degraded due to incomplete "
- "debug information.\n";
- ArchiveHintDisplayed = true;
- }
- }
- }
-
- return ErrorOrObj.getError();
- }
-
- llvm_unreachable("Unhandled DebugMap object");
- });
- GeneralLinker.setSwiftInterfacesMap(&ParseableSwiftInterfaces);
-
- for (const auto &Obj : Map.objects()) {
- // N_AST objects (swiftmodule files) should get dumped directly into the
- // appropriate DWARF section.
- if (Obj->getType() == MachO::N_AST) {
- if (Options.Verbose)
- outs() << "DEBUG MAP OBJECT: " << Obj->getObjectFilename() << "\n";
-
- StringRef File = Obj->getObjectFilename();
- auto ErrorOrMem = MemoryBuffer::getFile(File);
- if (!ErrorOrMem) {
- warn("Could not open '" + File + "'\n");
- continue;
- }
- sys::fs::file_status Stat;
- if (auto Err = sys::fs::status(File, Stat)) {
- warn(Err.message());
- continue;
- }
- if (!Options.NoTimestamp) {
- // The modification can have sub-second precision so we need to cast
- // away the extra precision that's not present in the debug map.
- auto ModificationTime =
- std::chrono::time_point_cast<std::chrono::seconds>(
- Stat.getLastModificationTime());
- if (ModificationTime != Obj->getTimestamp()) {
- // Not using the helper here as we can easily stream TimePoint<>.
+ auto &Obj = DebugMap.addDebugMapObject(
+ Path, sys::TimePoint<std::chrono::seconds>(), MachO::N_OSO);
+
+ if (auto ErrorOrObj = loadObject(Obj, DebugMap, RL)) {
+ return *ErrorOrObj;
+ } else {
+ // Try and emit more helpful warnings by applying some heuristics.
+ StringRef ObjFile = ContainerName;
+ bool IsClangModule = sys::path::extension(Path).equals(".pcm");
+ bool IsArchive = ObjFile.endswith(")");
+
+ if (IsClangModule) {
+ StringRef ModuleCacheDir = sys::path::parent_path(Path);
+ if (sys::fs::exists(ModuleCacheDir)) {
+ // If the module's parent directory exists, we assume that the
+ // module cache has expired and was pruned by clang. A more
+ // adventurous dsymutil would invoke clang to rebuild the module
+ // now.
+ if (!ModuleCacheHintDisplayed) {
+ WithColor::note()
+ << "The clang module cache may have expired since "
+ "this object file was built. Rebuilding the "
+ "object file will rebuild the module cache.\n";
+ ModuleCacheHintDisplayed = true;
+ }
+ } else if (IsArchive) {
+ // If the module cache directory doesn't exist at all and the
+ // object file is inside a static library, we assume that the
+ // static library was built on a different machine. We don't want
+ // to discourage module debugging for convenience libraries within
+ // a project though.
+ if (!ArchiveHintDisplayed) {
+ WithColor::note()
+ << "Linking a static library that was built with "
+ "-gmodules, but the module cache was not found. "
+ "Redistributable static libraries should never be "
+ "built with module debugging enabled. The debug "
+ "experience will be degraded due to incomplete "
+ "debug information.\n";
+ ArchiveHintDisplayed = true;
+ }
+ }
+ }
+
+ return ErrorOrObj.getError();
+ }
+
+ llvm_unreachable("Unhandled DebugMap object");
+ });
+ GeneralLinker.setSwiftInterfacesMap(&ParseableSwiftInterfaces);
+
+ for (const auto &Obj : Map.objects()) {
+ // N_AST objects (swiftmodule files) should get dumped directly into the
+ // appropriate DWARF section.
+ if (Obj->getType() == MachO::N_AST) {
+ if (Options.Verbose)
+ outs() << "DEBUG MAP OBJECT: " << Obj->getObjectFilename() << "\n";
+
+ StringRef File = Obj->getObjectFilename();
+ auto ErrorOrMem = MemoryBuffer::getFile(File);
+ if (!ErrorOrMem) {
+ warn("Could not open '" + File + "'\n");
+ continue;
+ }
+ sys::fs::file_status Stat;
+ if (auto Err = sys::fs::status(File, Stat)) {
+ warn(Err.message());
+ continue;
+ }
+ if (!Options.NoTimestamp) {
+ // The modification can have sub-second precision so we need to cast
+ // away the extra precision that's not present in the debug map.
+ auto ModificationTime =
+ std::chrono::time_point_cast<std::chrono::seconds>(
+ Stat.getLastModificationTime());
+ if (ModificationTime != Obj->getTimestamp()) {
+ // Not using the helper here as we can easily stream TimePoint<>.
WithColor::warning()
<< File << ": timestamp mismatch between swift interface file ("
<< sys::TimePoint<>(Obj->getTimestamp()) << ") and debug map ("
<< sys::TimePoint<>(Obj->getTimestamp()) << ")\n";
- continue;
- }
- }
-
- // Copy the module into the .swift_ast section.
- if (!Options.NoOutput)
- Streamer->emitSwiftAST((*ErrorOrMem)->getBuffer());
-
- continue;
- }
-
- if (auto ErrorOrObj = loadObject(*Obj, Map, RL))
- GeneralLinker.addObjectFile(*ErrorOrObj);
- else {
+ continue;
+ }
+ }
+
+ // Copy the module into the .swift_ast section.
+ if (!Options.NoOutput)
+ Streamer->emitSwiftAST((*ErrorOrMem)->getBuffer());
+
+ continue;
+ }
+
+ if (auto ErrorOrObj = loadObject(*Obj, Map, RL))
+ GeneralLinker.addObjectFile(*ErrorOrObj);
+ else {
ObjectsForLinking.push_back(std::make_unique<DWARFFile>(
- Obj->getObjectFilename(), nullptr, nullptr,
- Obj->empty() ? Obj->getWarnings() : EmptyWarnings));
- GeneralLinker.addObjectFile(*ObjectsForLinking.back());
- }
- }
-
- // link debug info for loaded object files.
- GeneralLinker.link();
-
- StringRef ArchName = Map.getTriple().getArchName();
- if (Error E = emitRemarks(Options, Map.getBinaryPath(), ArchName, RL))
- return error(toString(std::move(E)));
-
- if (Options.NoOutput)
- return true;
-
- if (Options.ResourceDir && !ParseableSwiftInterfaces.empty()) {
- StringRef ArchName = Triple::getArchTypeName(Map.getTriple().getArch());
- if (auto E =
- copySwiftInterfaces(ParseableSwiftInterfaces, ArchName, Options))
- return error(toString(std::move(E)));
- }
-
- if (Map.getTriple().isOSDarwin() && !Map.getBinaryPath().empty() &&
- Options.FileType == OutputFileType::Object)
- return MachOUtils::generateDsymCompanion(
- Options.VFS, Map, Options.Translator,
- *Streamer->getAsmPrinter().OutStreamer, OutFile);
-
- Streamer->finish();
- return true;
-}
-
-static bool isMachOPairedReloc(uint64_t RelocType, uint64_t Arch) {
- switch (Arch) {
- case Triple::x86:
- return RelocType == MachO::GENERIC_RELOC_SECTDIFF ||
- RelocType == MachO::GENERIC_RELOC_LOCAL_SECTDIFF;
- case Triple::x86_64:
- return RelocType == MachO::X86_64_RELOC_SUBTRACTOR;
- case Triple::arm:
- case Triple::thumb:
- return RelocType == MachO::ARM_RELOC_SECTDIFF ||
- RelocType == MachO::ARM_RELOC_LOCAL_SECTDIFF ||
- RelocType == MachO::ARM_RELOC_HALF ||
- RelocType == MachO::ARM_RELOC_HALF_SECTDIFF;
- case Triple::aarch64:
- return RelocType == MachO::ARM64_RELOC_SUBTRACTOR;
- default:
- return false;
- }
-}
-
-/// Iterate over the relocations of the given \p Section and
-/// store the ones that correspond to debug map entries into the
-/// ValidRelocs array.
-void DwarfLinkerForBinary::AddressManager::findValidRelocsMachO(
- const object::SectionRef &Section, const object::MachOObjectFile &Obj,
+ Obj->getObjectFilename(), nullptr, nullptr,
+ Obj->empty() ? Obj->getWarnings() : EmptyWarnings));
+ GeneralLinker.addObjectFile(*ObjectsForLinking.back());
+ }
+ }
+
+ // link debug info for loaded object files.
+ GeneralLinker.link();
+
+ StringRef ArchName = Map.getTriple().getArchName();
+ if (Error E = emitRemarks(Options, Map.getBinaryPath(), ArchName, RL))
+ return error(toString(std::move(E)));
+
+ if (Options.NoOutput)
+ return true;
+
+ if (Options.ResourceDir && !ParseableSwiftInterfaces.empty()) {
+ StringRef ArchName = Triple::getArchTypeName(Map.getTriple().getArch());
+ if (auto E =
+ copySwiftInterfaces(ParseableSwiftInterfaces, ArchName, Options))
+ return error(toString(std::move(E)));
+ }
+
+ if (Map.getTriple().isOSDarwin() && !Map.getBinaryPath().empty() &&
+ Options.FileType == OutputFileType::Object)
+ return MachOUtils::generateDsymCompanion(
+ Options.VFS, Map, Options.Translator,
+ *Streamer->getAsmPrinter().OutStreamer, OutFile);
+
+ Streamer->finish();
+ return true;
+}
+
+static bool isMachOPairedReloc(uint64_t RelocType, uint64_t Arch) {
+ switch (Arch) {
+ case Triple::x86:
+ return RelocType == MachO::GENERIC_RELOC_SECTDIFF ||
+ RelocType == MachO::GENERIC_RELOC_LOCAL_SECTDIFF;
+ case Triple::x86_64:
+ return RelocType == MachO::X86_64_RELOC_SUBTRACTOR;
+ case Triple::arm:
+ case Triple::thumb:
+ return RelocType == MachO::ARM_RELOC_SECTDIFF ||
+ RelocType == MachO::ARM_RELOC_LOCAL_SECTDIFF ||
+ RelocType == MachO::ARM_RELOC_HALF ||
+ RelocType == MachO::ARM_RELOC_HALF_SECTDIFF;
+ case Triple::aarch64:
+ return RelocType == MachO::ARM64_RELOC_SUBTRACTOR;
+ default:
+ return false;
+ }
+}
+
+/// Iterate over the relocations of the given \p Section and
+/// store the ones that correspond to debug map entries into the
+/// ValidRelocs array.
+void DwarfLinkerForBinary::AddressManager::findValidRelocsMachO(
+ const object::SectionRef &Section, const object::MachOObjectFile &Obj,
const DebugMapObject &DMO, std::vector<ValidReloc> &ValidRelocs) {
- Expected<StringRef> ContentsOrErr = Section.getContents();
- if (!ContentsOrErr) {
- consumeError(ContentsOrErr.takeError());
- Linker.reportWarning("error reading section", DMO.getObjectFilename());
- return;
- }
- DataExtractor Data(*ContentsOrErr, Obj.isLittleEndian(), 0);
- bool SkipNext = false;
-
- for (const object::RelocationRef &Reloc : Section.relocations()) {
- if (SkipNext) {
- SkipNext = false;
- continue;
- }
-
- object::DataRefImpl RelocDataRef = Reloc.getRawDataRefImpl();
- MachO::any_relocation_info MachOReloc = Obj.getRelocation(RelocDataRef);
-
- if (isMachOPairedReloc(Obj.getAnyRelocationType(MachOReloc),
- Obj.getArch())) {
- SkipNext = true;
+ Expected<StringRef> ContentsOrErr = Section.getContents();
+ if (!ContentsOrErr) {
+ consumeError(ContentsOrErr.takeError());
+ Linker.reportWarning("error reading section", DMO.getObjectFilename());
+ return;
+ }
+ DataExtractor Data(*ContentsOrErr, Obj.isLittleEndian(), 0);
+ bool SkipNext = false;
+
+ for (const object::RelocationRef &Reloc : Section.relocations()) {
+ if (SkipNext) {
+ SkipNext = false;
+ continue;
+ }
+
+ object::DataRefImpl RelocDataRef = Reloc.getRawDataRefImpl();
+ MachO::any_relocation_info MachOReloc = Obj.getRelocation(RelocDataRef);
+
+ if (isMachOPairedReloc(Obj.getAnyRelocationType(MachOReloc),
+ Obj.getArch())) {
+ SkipNext = true;
Linker.reportWarning("unsupported relocation in " + *Section.getName() +
" section.",
- DMO.getObjectFilename());
- continue;
- }
-
- unsigned RelocSize = 1 << Obj.getAnyRelocationLength(MachOReloc);
- uint64_t Offset64 = Reloc.getOffset();
- if ((RelocSize != 4 && RelocSize != 8)) {
+ DMO.getObjectFilename());
+ continue;
+ }
+
+ unsigned RelocSize = 1 << Obj.getAnyRelocationLength(MachOReloc);
+ uint64_t Offset64 = Reloc.getOffset();
+ if ((RelocSize != 4 && RelocSize != 8)) {
Linker.reportWarning("unsupported relocation in " + *Section.getName() +
" section.",
- DMO.getObjectFilename());
- continue;
- }
- uint64_t OffsetCopy = Offset64;
- // Mach-o uses REL relocations, the addend is at the relocation offset.
- uint64_t Addend = Data.getUnsigned(&OffsetCopy, RelocSize);
- uint64_t SymAddress;
- int64_t SymOffset;
-
- if (Obj.isRelocationScattered(MachOReloc)) {
- // The address of the base symbol for scattered relocations is
- // stored in the reloc itself. The actual addend will store the
- // base address plus the offset.
- SymAddress = Obj.getScatteredRelocationValue(MachOReloc);
- SymOffset = int64_t(Addend) - SymAddress;
- } else {
- SymAddress = Addend;
- SymOffset = 0;
- }
-
- auto Sym = Reloc.getSymbol();
- if (Sym != Obj.symbol_end()) {
- Expected<StringRef> SymbolName = Sym->getName();
- if (!SymbolName) {
- consumeError(SymbolName.takeError());
- Linker.reportWarning("error getting relocation symbol name.",
- DMO.getObjectFilename());
- continue;
- }
- if (const auto *Mapping = DMO.lookupSymbol(*SymbolName))
- ValidRelocs.emplace_back(Offset64, RelocSize, Addend, Mapping);
- } else if (const auto *Mapping = DMO.lookupObjectAddress(SymAddress)) {
- // Do not store the addend. The addend was the address of the symbol in
- // the object file, the address in the binary that is stored in the debug
- // map doesn't need to be offset.
- ValidRelocs.emplace_back(Offset64, RelocSize, SymOffset, Mapping);
- }
- }
-}
-
-/// Dispatch the valid relocation finding logic to the
-/// appropriate handler depending on the object file format.
-bool DwarfLinkerForBinary::AddressManager::findValidRelocs(
- const object::SectionRef &Section, const object::ObjectFile &Obj,
+ DMO.getObjectFilename());
+ continue;
+ }
+ uint64_t OffsetCopy = Offset64;
+ // Mach-o uses REL relocations, the addend is at the relocation offset.
+ uint64_t Addend = Data.getUnsigned(&OffsetCopy, RelocSize);
+ uint64_t SymAddress;
+ int64_t SymOffset;
+
+ if (Obj.isRelocationScattered(MachOReloc)) {
+ // The address of the base symbol for scattered relocations is
+ // stored in the reloc itself. The actual addend will store the
+ // base address plus the offset.
+ SymAddress = Obj.getScatteredRelocationValue(MachOReloc);
+ SymOffset = int64_t(Addend) - SymAddress;
+ } else {
+ SymAddress = Addend;
+ SymOffset = 0;
+ }
+
+ auto Sym = Reloc.getSymbol();
+ if (Sym != Obj.symbol_end()) {
+ Expected<StringRef> SymbolName = Sym->getName();
+ if (!SymbolName) {
+ consumeError(SymbolName.takeError());
+ Linker.reportWarning("error getting relocation symbol name.",
+ DMO.getObjectFilename());
+ continue;
+ }
+ if (const auto *Mapping = DMO.lookupSymbol(*SymbolName))
+ ValidRelocs.emplace_back(Offset64, RelocSize, Addend, Mapping);
+ } else if (const auto *Mapping = DMO.lookupObjectAddress(SymAddress)) {
+ // Do not store the addend. The addend was the address of the symbol in
+ // the object file, the address in the binary that is stored in the debug
+ // map doesn't need to be offset.
+ ValidRelocs.emplace_back(Offset64, RelocSize, SymOffset, Mapping);
+ }
+ }
+}
+
+/// Dispatch the valid relocation finding logic to the
+/// appropriate handler depending on the object file format.
+bool DwarfLinkerForBinary::AddressManager::findValidRelocs(
+ const object::SectionRef &Section, const object::ObjectFile &Obj,
const DebugMapObject &DMO, std::vector<ValidReloc> &Relocs) {
- // Dispatch to the right handler depending on the file type.
- if (auto *MachOObj = dyn_cast<object::MachOObjectFile>(&Obj))
+ // Dispatch to the right handler depending on the file type.
+ if (auto *MachOObj = dyn_cast<object::MachOObjectFile>(&Obj))
findValidRelocsMachO(Section, *MachOObj, DMO, Relocs);
- else
- Linker.reportWarning(Twine("unsupported object file type: ") +
- Obj.getFileName(),
- DMO.getObjectFilename());
+ else
+ Linker.reportWarning(Twine("unsupported object file type: ") +
+ Obj.getFileName(),
+ DMO.getObjectFilename());
if (Relocs.empty())
- return false;
-
- // Sort the relocations by offset. We will walk the DIEs linearly in
- // the file, this allows us to just keep an index in the relocation
- // array that we advance during our walk, rather than resorting to
- // some associative container. See DwarfLinkerForBinary::NextValidReloc.
+ return false;
+
+ // Sort the relocations by offset. We will walk the DIEs linearly in
+ // the file, this allows us to just keep an index in the relocation
+ // array that we advance during our walk, rather than resorting to
+ // some associative container. See DwarfLinkerForBinary::NextValidReloc.
llvm::sort(Relocs);
- return true;
-}
-
+ return true;
+}
+
/// Look for relocations in the debug_info and debug_addr section that match
/// entries in the debug map. These relocations will drive the Dwarf link by
/// indicating which DIEs refer to symbols present in the linked binary.
-/// \returns whether there are any valid relocations in the debug info.
+/// \returns whether there are any valid relocations in the debug info.
bool DwarfLinkerForBinary::AddressManager::findValidRelocsInDebugSections(
- const object::ObjectFile &Obj, const DebugMapObject &DMO) {
- // Find the debug_info section.
+ const object::ObjectFile &Obj, const DebugMapObject &DMO) {
+ // Find the debug_info section.
bool FoundValidRelocs = false;
- for (const object::SectionRef &Section : Obj.sections()) {
- StringRef SectionName;
- if (Expected<StringRef> NameOrErr = Section.getName())
- SectionName = *NameOrErr;
- else
- consumeError(NameOrErr.takeError());
-
- SectionName = SectionName.substr(SectionName.find_first_not_of("._"));
+ for (const object::SectionRef &Section : Obj.sections()) {
+ StringRef SectionName;
+ if (Expected<StringRef> NameOrErr = Section.getName())
+ SectionName = *NameOrErr;
+ else
+ consumeError(NameOrErr.takeError());
+
+ SectionName = SectionName.substr(SectionName.find_first_not_of("._"));
if (SectionName == "debug_info")
FoundValidRelocs |=
findValidRelocs(Section, Obj, DMO, ValidDebugInfoRelocs);
if (SectionName == "debug_addr")
FoundValidRelocs |=
findValidRelocs(Section, Obj, DMO, ValidDebugAddrRelocs);
- }
+ }
return FoundValidRelocs;
-}
-
+}
+
bool DwarfLinkerForBinary::AddressManager::hasValidDebugAddrRelocationAt(
uint64_t Offset) {
auto It = std::lower_bound(ValidDebugAddrRelocs.begin(),
@@ -619,44 +619,44 @@ bool DwarfLinkerForBinary::AddressManager::hasValidDebugAddrRelocationAt(
}
bool DwarfLinkerForBinary::AddressManager::hasValidDebugInfoRelocationAt(
- uint64_t StartOffset, uint64_t EndOffset, CompileUnit::DIEInfo &Info) {
- assert(NextValidReloc == 0 ||
+ uint64_t StartOffset, uint64_t EndOffset, CompileUnit::DIEInfo &Info) {
+ assert(NextValidReloc == 0 ||
StartOffset > ValidDebugInfoRelocs[NextValidReloc - 1].Offset);
if (NextValidReloc >= ValidDebugInfoRelocs.size())
- return false;
-
+ return false;
+
uint64_t RelocOffset = ValidDebugInfoRelocs[NextValidReloc].Offset;
-
- // We might need to skip some relocs that we didn't consider. For
- // example the high_pc of a discarded DIE might contain a reloc that
- // is in the list because it actually corresponds to the start of a
- // function that is in the debug map.
+
+ // We might need to skip some relocs that we didn't consider. For
+ // example the high_pc of a discarded DIE might contain a reloc that
+ // is in the list because it actually corresponds to the start of a
+ // function that is in the debug map.
while (RelocOffset < StartOffset &&
NextValidReloc < ValidDebugInfoRelocs.size() - 1)
RelocOffset = ValidDebugInfoRelocs[++NextValidReloc].Offset;
-
- if (RelocOffset < StartOffset || RelocOffset >= EndOffset)
- return false;
-
+
+ if (RelocOffset < StartOffset || RelocOffset >= EndOffset)
+ return false;
+
const auto &ValidReloc = ValidDebugInfoRelocs[NextValidReloc++];
- const auto &Mapping = ValidReloc.Mapping->getValue();
- const uint64_t BinaryAddress = Mapping.BinaryAddress;
- const uint64_t ObjectAddress = Mapping.ObjectAddress
- ? uint64_t(*Mapping.ObjectAddress)
- : std::numeric_limits<uint64_t>::max();
- if (Linker.Options.Verbose)
- outs() << "Found valid debug map entry: " << ValidReloc.Mapping->getKey()
- << "\t"
- << format("0x%016" PRIx64 " => 0x%016" PRIx64 "\n", ObjectAddress,
- BinaryAddress);
-
- Info.AddrAdjust = BinaryAddress + ValidReloc.Addend;
- if (Mapping.ObjectAddress)
- Info.AddrAdjust -= ObjectAddress;
- Info.InDebugMap = true;
- return true;
-}
-
+ const auto &Mapping = ValidReloc.Mapping->getValue();
+ const uint64_t BinaryAddress = Mapping.BinaryAddress;
+ const uint64_t ObjectAddress = Mapping.ObjectAddress
+ ? uint64_t(*Mapping.ObjectAddress)
+ : std::numeric_limits<uint64_t>::max();
+ if (Linker.Options.Verbose)
+ outs() << "Found valid debug map entry: " << ValidReloc.Mapping->getKey()
+ << "\t"
+ << format("0x%016" PRIx64 " => 0x%016" PRIx64 "\n", ObjectAddress,
+ BinaryAddress);
+
+ Info.AddrAdjust = BinaryAddress + ValidReloc.Addend;
+ if (Mapping.ObjectAddress)
+ Info.AddrAdjust -= ObjectAddress;
+ Info.InDebugMap = true;
+ return true;
+}
+
/// Get the starting and ending (exclusive) offset for the
/// attribute with index \p Idx descibed by \p Abbrev. \p Offset is
/// supposed to point to the position of the first attribute described
@@ -722,51 +722,51 @@ bool DwarfLinkerForBinary::AddressManager::hasLiveAddressRange(
return false;
}
-/// Apply the valid relocations found by findValidRelocs() to
-/// the buffer \p Data, taking into account that Data is at \p BaseOffset
-/// in the debug_info section.
-///
-/// Like for findValidRelocs(), this function must be called with
-/// monotonic \p BaseOffset values.
-///
-/// \returns whether any reloc has been applied.
-bool DwarfLinkerForBinary::AddressManager::applyValidRelocs(
- MutableArrayRef<char> Data, uint64_t BaseOffset, bool IsLittleEndian) {
- assert(areRelocationsResolved());
- assert((NextValidReloc == 0 ||
+/// Apply the valid relocations found by findValidRelocs() to
+/// the buffer \p Data, taking into account that Data is at \p BaseOffset
+/// in the debug_info section.
+///
+/// Like for findValidRelocs(), this function must be called with
+/// monotonic \p BaseOffset values.
+///
+/// \returns whether any reloc has been applied.
+bool DwarfLinkerForBinary::AddressManager::applyValidRelocs(
+ MutableArrayRef<char> Data, uint64_t BaseOffset, bool IsLittleEndian) {
+ assert(areRelocationsResolved());
+ assert((NextValidReloc == 0 ||
BaseOffset > ValidDebugInfoRelocs[NextValidReloc - 1].Offset) &&
- "BaseOffset should only be increasing.");
+ "BaseOffset should only be increasing.");
if (NextValidReloc >= ValidDebugInfoRelocs.size())
- return false;
-
- // Skip relocs that haven't been applied.
+ return false;
+
+ // Skip relocs that haven't been applied.
while (NextValidReloc < ValidDebugInfoRelocs.size() &&
ValidDebugInfoRelocs[NextValidReloc].Offset < BaseOffset)
- ++NextValidReloc;
-
- bool Applied = false;
- uint64_t EndOffset = BaseOffset + Data.size();
+ ++NextValidReloc;
+
+ bool Applied = false;
+ uint64_t EndOffset = BaseOffset + Data.size();
while (NextValidReloc < ValidDebugInfoRelocs.size() &&
ValidDebugInfoRelocs[NextValidReloc].Offset >= BaseOffset &&
ValidDebugInfoRelocs[NextValidReloc].Offset < EndOffset) {
const auto &ValidReloc = ValidDebugInfoRelocs[NextValidReloc++];
- assert(ValidReloc.Offset - BaseOffset < Data.size());
- assert(ValidReloc.Offset - BaseOffset + ValidReloc.Size <= Data.size());
- char Buf[8];
- uint64_t Value = ValidReloc.Mapping->getValue().BinaryAddress;
- Value += ValidReloc.Addend;
- for (unsigned I = 0; I != ValidReloc.Size; ++I) {
- unsigned Index = IsLittleEndian ? I : (ValidReloc.Size - I - 1);
- Buf[I] = uint8_t(Value >> (Index * 8));
- }
- assert(ValidReloc.Size <= sizeof(Buf));
- memcpy(&Data[ValidReloc.Offset - BaseOffset], Buf, ValidReloc.Size);
- Applied = true;
- }
-
- return Applied;
-}
-
+ assert(ValidReloc.Offset - BaseOffset < Data.size());
+ assert(ValidReloc.Offset - BaseOffset + ValidReloc.Size <= Data.size());
+ char Buf[8];
+ uint64_t Value = ValidReloc.Mapping->getValue().BinaryAddress;
+ Value += ValidReloc.Addend;
+ for (unsigned I = 0; I != ValidReloc.Size; ++I) {
+ unsigned Index = IsLittleEndian ? I : (ValidReloc.Size - I - 1);
+ Buf[I] = uint8_t(Value >> (Index * 8));
+ }
+ assert(ValidReloc.Size <= sizeof(Buf));
+ memcpy(&Data[ValidReloc.Offset - BaseOffset], Buf, ValidReloc.Size);
+ Applied = true;
+ }
+
+ return Applied;
+}
+
llvm::Expected<uint64_t>
DwarfLinkerForBinary::AddressManager::relocateIndexedAddr(uint64_t Offset) {
auto It = std::lower_bound(ValidDebugAddrRelocs.begin(),
@@ -778,11 +778,11 @@ DwarfLinkerForBinary::AddressManager::relocateIndexedAddr(uint64_t Offset) {
return It->Mapping->getValue().BinaryAddress + It->Addend;
}
-bool linkDwarf(raw_fd_ostream &OutFile, BinaryHolder &BinHolder,
- const DebugMap &DM, LinkOptions Options) {
- DwarfLinkerForBinary Linker(OutFile, BinHolder, std::move(Options));
- return Linker.link(DM);
-}
-
-} // namespace dsymutil
-} // namespace llvm
+bool linkDwarf(raw_fd_ostream &OutFile, BinaryHolder &BinHolder,
+ const DebugMap &DM, LinkOptions Options) {
+ DwarfLinkerForBinary Linker(OutFile, BinHolder, std::move(Options));
+ return Linker.link(DM);
+}
+
+} // namespace dsymutil
+} // namespace llvm
diff --git a/contrib/libs/llvm12/tools/dsymutil/DwarfLinkerForBinary.h b/contrib/libs/llvm12/tools/dsymutil/DwarfLinkerForBinary.h
index c6c07d689f..849d2c7fa5 100644
--- a/contrib/libs/llvm12/tools/dsymutil/DwarfLinkerForBinary.h
+++ b/contrib/libs/llvm12/tools/dsymutil/DwarfLinkerForBinary.h
@@ -1,154 +1,154 @@
-//===- tools/dsymutil/DwarfLinkerForBinary.h --------------------*- C++ -*-===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_TOOLS_DSYMUTIL_DWARFLINKER_H
-#define LLVM_TOOLS_DSYMUTIL_DWARFLINKER_H
-
-#include "BinaryHolder.h"
-#include "DebugMap.h"
-#include "LinkUtils.h"
-#include "llvm/DWARFLinker/DWARFLinker.h"
-#include "llvm/DWARFLinker/DWARFLinkerCompileUnit.h"
-#include "llvm/DWARFLinker/DWARFLinkerDeclContext.h"
-#include "llvm/DWARFLinker/DWARFStreamer.h"
-#include "llvm/DebugInfo/DWARF/DWARFContext.h"
-#include "llvm/Remarks/RemarkFormat.h"
-#include "llvm/Remarks/RemarkLinker.h"
-
-namespace llvm {
-namespace dsymutil {
-
-/// The core of the Dsymutil Dwarf linking logic.
-///
-/// The link of the dwarf information from the object files will be
-/// driven by DWARFLinker. DwarfLinkerForBinary reads DebugMap objects
-/// and pass information to the DWARFLinker. DWARFLinker
-/// optimizes DWARF taking into account valid relocations.
-/// Finally, optimized DWARF is passed to DwarfLinkerForBinary through
-/// DWARFEmitter interface.
-class DwarfLinkerForBinary {
-public:
- DwarfLinkerForBinary(raw_fd_ostream &OutFile, BinaryHolder &BinHolder,
- LinkOptions Options)
- : OutFile(OutFile), BinHolder(BinHolder), Options(std::move(Options)) {}
-
- /// Link the contents of the DebugMap.
- bool link(const DebugMap &);
-
- void reportWarning(const Twine &Warning, StringRef Context,
- const DWARFDie *DIE = nullptr) const;
-
- /// Flags passed to DwarfLinker::lookForDIEsToKeep
- enum TraversalFlags {
- TF_Keep = 1 << 0, ///< Mark the traversed DIEs as kept.
- TF_InFunctionScope = 1 << 1, ///< Current scope is a function scope.
- TF_DependencyWalk = 1 << 2, ///< Walking the dependencies of a kept DIE.
- TF_ParentWalk = 1 << 3, ///< Walking up the parents of a kept DIE.
- TF_ODR = 1 << 4, ///< Use the ODR while keeping dependents.
- TF_SkipPC = 1 << 5, ///< Skip all location attributes.
- };
-
-private:
-
- /// Keeps track of relocations.
- class AddressManager : public AddressesMap {
- struct ValidReloc {
- uint64_t Offset;
- uint32_t Size;
- uint64_t Addend;
- const DebugMapObject::DebugMapEntry *Mapping;
-
- ValidReloc(uint64_t Offset, uint32_t Size, uint64_t Addend,
- const DebugMapObject::DebugMapEntry *Mapping)
- : Offset(Offset), Size(Size), Addend(Addend), Mapping(Mapping) {}
-
- bool operator<(const ValidReloc &RHS) const {
- return Offset < RHS.Offset;
- }
+//===- tools/dsymutil/DwarfLinkerForBinary.h --------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TOOLS_DSYMUTIL_DWARFLINKER_H
+#define LLVM_TOOLS_DSYMUTIL_DWARFLINKER_H
+
+#include "BinaryHolder.h"
+#include "DebugMap.h"
+#include "LinkUtils.h"
+#include "llvm/DWARFLinker/DWARFLinker.h"
+#include "llvm/DWARFLinker/DWARFLinkerCompileUnit.h"
+#include "llvm/DWARFLinker/DWARFLinkerDeclContext.h"
+#include "llvm/DWARFLinker/DWARFStreamer.h"
+#include "llvm/DebugInfo/DWARF/DWARFContext.h"
+#include "llvm/Remarks/RemarkFormat.h"
+#include "llvm/Remarks/RemarkLinker.h"
+
+namespace llvm {
+namespace dsymutil {
+
+/// The core of the Dsymutil Dwarf linking logic.
+///
+/// The link of the dwarf information from the object files will be
+/// driven by DWARFLinker. DwarfLinkerForBinary reads DebugMap objects
+/// and pass information to the DWARFLinker. DWARFLinker
+/// optimizes DWARF taking into account valid relocations.
+/// Finally, optimized DWARF is passed to DwarfLinkerForBinary through
+/// DWARFEmitter interface.
+class DwarfLinkerForBinary {
+public:
+ DwarfLinkerForBinary(raw_fd_ostream &OutFile, BinaryHolder &BinHolder,
+ LinkOptions Options)
+ : OutFile(OutFile), BinHolder(BinHolder), Options(std::move(Options)) {}
+
+ /// Link the contents of the DebugMap.
+ bool link(const DebugMap &);
+
+ void reportWarning(const Twine &Warning, StringRef Context,
+ const DWARFDie *DIE = nullptr) const;
+
+ /// Flags passed to DwarfLinker::lookForDIEsToKeep
+ enum TraversalFlags {
+ TF_Keep = 1 << 0, ///< Mark the traversed DIEs as kept.
+ TF_InFunctionScope = 1 << 1, ///< Current scope is a function scope.
+ TF_DependencyWalk = 1 << 2, ///< Walking the dependencies of a kept DIE.
+ TF_ParentWalk = 1 << 3, ///< Walking up the parents of a kept DIE.
+ TF_ODR = 1 << 4, ///< Use the ODR while keeping dependents.
+ TF_SkipPC = 1 << 5, ///< Skip all location attributes.
+ };
+
+private:
+
+ /// Keeps track of relocations.
+ class AddressManager : public AddressesMap {
+ struct ValidReloc {
+ uint64_t Offset;
+ uint32_t Size;
+ uint64_t Addend;
+ const DebugMapObject::DebugMapEntry *Mapping;
+
+ ValidReloc(uint64_t Offset, uint32_t Size, uint64_t Addend,
+ const DebugMapObject::DebugMapEntry *Mapping)
+ : Offset(Offset), Size(Size), Addend(Addend), Mapping(Mapping) {}
+
+ bool operator<(const ValidReloc &RHS) const {
+ return Offset < RHS.Offset;
+ }
bool operator<(uint64_t RHS) const { return Offset < RHS; }
- };
-
- const DwarfLinkerForBinary &Linker;
-
- /// The valid relocations for the current DebugMapObject.
- /// This vector is sorted by relocation offset.
+ };
+
+ const DwarfLinkerForBinary &Linker;
+
+ /// The valid relocations for the current DebugMapObject.
+ /// This vector is sorted by relocation offset.
/// {
std::vector<ValidReloc> ValidDebugInfoRelocs;
std::vector<ValidReloc> ValidDebugAddrRelocs;
/// }
-
- /// Index into ValidRelocs of the next relocation to consider. As we walk
- /// the DIEs in acsending file offset and as ValidRelocs is sorted by file
- /// offset, keeping this index up to date is all we have to do to have a
- /// cheap lookup during the root DIE selection and during DIE cloning.
- unsigned NextValidReloc = 0;
-
- RangesTy AddressRanges;
-
- public:
- AddressManager(DwarfLinkerForBinary &Linker, const object::ObjectFile &Obj,
- const DebugMapObject &DMO)
- : Linker(Linker) {
+
+ /// Index into ValidRelocs of the next relocation to consider. As we walk
+ /// the DIEs in acsending file offset and as ValidRelocs is sorted by file
+ /// offset, keeping this index up to date is all we have to do to have a
+ /// cheap lookup during the root DIE selection and during DIE cloning.
+ unsigned NextValidReloc = 0;
+
+ RangesTy AddressRanges;
+
+ public:
+ AddressManager(DwarfLinkerForBinary &Linker, const object::ObjectFile &Obj,
+ const DebugMapObject &DMO)
+ : Linker(Linker) {
findValidRelocsInDebugSections(Obj, DMO);
-
- // Iterate over the debug map entries and put all the ones that are
- // functions (because they have a size) into the Ranges map. This map is
- // very similar to the FunctionRanges that are stored in each unit, with 2
- // notable differences:
- //
- // 1. Obviously this one is global, while the other ones are per-unit.
- //
- // 2. This one contains not only the functions described in the DIE
- // tree, but also the ones that are only in the debug map.
- //
- // The latter information is required to reproduce dsymutil's logic while
- // linking line tables. The cases where this information matters look like
- // bugs that need to be investigated, but for now we need to reproduce
- // dsymutil's behavior.
- // FIXME: Once we understood exactly if that information is needed,
- // maybe totally remove this (or try to use it to do a real
- // -gline-tables-only on Darwin.
- for (const auto &Entry : DMO.symbols()) {
- const auto &Mapping = Entry.getValue();
- if (Mapping.Size && Mapping.ObjectAddress)
- AddressRanges[*Mapping.ObjectAddress] = ObjFileAddressRange(
- *Mapping.ObjectAddress + Mapping.Size,
- int64_t(Mapping.BinaryAddress) - *Mapping.ObjectAddress);
- }
- }
- virtual ~AddressManager() override { clear(); }
-
- virtual bool areRelocationsResolved() const override { return true; }
-
- bool hasValidRelocs(bool ResetRelocsPtr = true) override {
- if (ResetRelocsPtr)
- NextValidReloc = 0;
+
+ // Iterate over the debug map entries and put all the ones that are
+ // functions (because they have a size) into the Ranges map. This map is
+ // very similar to the FunctionRanges that are stored in each unit, with 2
+ // notable differences:
+ //
+ // 1. Obviously this one is global, while the other ones are per-unit.
+ //
+ // 2. This one contains not only the functions described in the DIE
+ // tree, but also the ones that are only in the debug map.
+ //
+ // The latter information is required to reproduce dsymutil's logic while
+ // linking line tables. The cases where this information matters look like
+ // bugs that need to be investigated, but for now we need to reproduce
+ // dsymutil's behavior.
+ // FIXME: Once we understood exactly if that information is needed,
+ // maybe totally remove this (or try to use it to do a real
+ // -gline-tables-only on Darwin.
+ for (const auto &Entry : DMO.symbols()) {
+ const auto &Mapping = Entry.getValue();
+ if (Mapping.Size && Mapping.ObjectAddress)
+ AddressRanges[*Mapping.ObjectAddress] = ObjFileAddressRange(
+ *Mapping.ObjectAddress + Mapping.Size,
+ int64_t(Mapping.BinaryAddress) - *Mapping.ObjectAddress);
+ }
+ }
+ virtual ~AddressManager() override { clear(); }
+
+ virtual bool areRelocationsResolved() const override { return true; }
+
+ bool hasValidRelocs(bool ResetRelocsPtr = true) override {
+ if (ResetRelocsPtr)
+ NextValidReloc = 0;
return !ValidDebugInfoRelocs.empty() || !ValidDebugAddrRelocs.empty();
- }
-
- /// \defgroup FindValidRelocations Translate debug map into a list
- /// of relevant relocations
- ///
- /// @{
+ }
+
+ /// \defgroup FindValidRelocations Translate debug map into a list
+ /// of relevant relocations
+ ///
+ /// @{
bool findValidRelocsInDebugSections(const object::ObjectFile &Obj,
const DebugMapObject &DMO);
-
- bool findValidRelocs(const object::SectionRef &Section,
- const object::ObjectFile &Obj,
+
+ bool findValidRelocs(const object::SectionRef &Section,
+ const object::ObjectFile &Obj,
const DebugMapObject &DMO,
std::vector<ValidReloc> &ValidRelocs);
-
- void findValidRelocsMachO(const object::SectionRef &Section,
- const object::MachOObjectFile &Obj,
+
+ void findValidRelocsMachO(const object::SectionRef &Section,
+ const object::MachOObjectFile &Obj,
const DebugMapObject &DMO,
std::vector<ValidReloc> &ValidRelocs);
- /// @}
-
+ /// @}
+
/// Checks that there is a relocation in the debug_addr section against a
/// debug map entry between \p StartOffset and \p NextOffset.
///
@@ -157,7 +157,7 @@ private:
/// \returns true and sets Info.InDebugMap if it is the case.
bool hasValidDebugInfoRelocationAt(uint64_t StartOffset, uint64_t EndOffset,
CompileUnit::DIEInfo &Info);
-
+
/// Checks that there is a relocation in the debug_addr section against a
/// debug map entry at the given offset.
bool hasValidDebugAddrRelocationAt(uint64_t Offset);
@@ -167,54 +167,54 @@ private:
bool hasLiveAddressRange(const DWARFDie &DIE,
CompileUnit::DIEInfo &Info) override;
- bool applyValidRelocs(MutableArrayRef<char> Data, uint64_t BaseOffset,
- bool IsLittleEndian) override;
-
+ bool applyValidRelocs(MutableArrayRef<char> Data, uint64_t BaseOffset,
+ bool IsLittleEndian) override;
+
llvm::Expected<uint64_t> relocateIndexedAddr(uint64_t Offset) override;
- RangesTy &getValidAddressRanges() override { return AddressRanges; }
-
- void clear() override {
- AddressRanges.clear();
+ RangesTy &getValidAddressRanges() override { return AddressRanges; }
+
+ void clear() override {
+ AddressRanges.clear();
ValidDebugInfoRelocs.clear();
ValidDebugAddrRelocs.clear();
- NextValidReloc = 0;
- }
- };
-
-private:
- /// \defgroup Helpers Various helper methods.
- ///
- /// @{
- bool createStreamer(const Triple &TheTriple, raw_fd_ostream &OutFile);
-
- /// Attempt to load a debug object from disk.
- ErrorOr<const object::ObjectFile &> loadObject(const DebugMapObject &Obj,
- const Triple &triple);
+ NextValidReloc = 0;
+ }
+ };
+
+private:
+ /// \defgroup Helpers Various helper methods.
+ ///
+ /// @{
+ bool createStreamer(const Triple &TheTriple, raw_fd_ostream &OutFile);
+
+ /// Attempt to load a debug object from disk.
+ ErrorOr<const object::ObjectFile &> loadObject(const DebugMapObject &Obj,
+ const Triple &triple);
ErrorOr<DWARFFile &> loadObject(const DebugMapObject &Obj,
- const DebugMap &DebugMap,
- remarks::RemarkLinker &RL);
-
- raw_fd_ostream &OutFile;
- BinaryHolder &BinHolder;
- LinkOptions Options;
- std::unique_ptr<DwarfStreamer> Streamer;
+ const DebugMap &DebugMap,
+ remarks::RemarkLinker &RL);
+
+ raw_fd_ostream &OutFile;
+ BinaryHolder &BinHolder;
+ LinkOptions Options;
+ std::unique_ptr<DwarfStreamer> Streamer;
std::vector<std::unique_ptr<DWARFFile>> ObjectsForLinking;
- std::vector<std::unique_ptr<DWARFContext>> ContextForLinking;
- std::vector<std::unique_ptr<AddressManager>> AddressMapForLinking;
- std::vector<std::string> EmptyWarnings;
-
- /// A list of all .swiftinterface files referenced by the debug
- /// info, mapping Module name to path on disk. The entries need to
- /// be uniqued and sorted and there are only few entries expected
- /// per compile unit, which is why this is a std::map.
- std::map<std::string, std::string> ParseableSwiftInterfaces;
-
- bool ModuleCacheHintDisplayed = false;
- bool ArchiveHintDisplayed = false;
-};
-
-} // end namespace dsymutil
-} // end namespace llvm
-
-#endif // LLVM_TOOLS_DSYMUTIL_DWARFLINKER_H
+ std::vector<std::unique_ptr<DWARFContext>> ContextForLinking;
+ std::vector<std::unique_ptr<AddressManager>> AddressMapForLinking;
+ std::vector<std::string> EmptyWarnings;
+
+ /// A list of all .swiftinterface files referenced by the debug
+ /// info, mapping Module name to path on disk. The entries need to
+ /// be uniqued and sorted and there are only few entries expected
+ /// per compile unit, which is why this is a std::map.
+ std::map<std::string, std::string> ParseableSwiftInterfaces;
+
+ bool ModuleCacheHintDisplayed = false;
+ bool ArchiveHintDisplayed = false;
+};
+
+} // end namespace dsymutil
+} // end namespace llvm
+
+#endif // LLVM_TOOLS_DSYMUTIL_DWARFLINKER_H
diff --git a/contrib/libs/llvm12/tools/dsymutil/LinkUtils.h b/contrib/libs/llvm12/tools/dsymutil/LinkUtils.h
index 52b36353c6..5b2e372547 100644
--- a/contrib/libs/llvm12/tools/dsymutil/LinkUtils.h
+++ b/contrib/libs/llvm12/tools/dsymutil/LinkUtils.h
@@ -1,107 +1,107 @@
-//===- tools/dsymutil/LinkUtils.h - Dwarf linker utilities ------*- C++ -*-===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_TOOLS_DSYMUTIL_LINKOPTIONS_H
-#define LLVM_TOOLS_DSYMUTIL_LINKOPTIONS_H
-
-#include "SymbolMap.h"
-
-#include "llvm/ADT/Twine.h"
-#include "llvm/Remarks/RemarkFormat.h"
-#include "llvm/Support/VirtualFileSystem.h"
-#include "llvm/Support/WithColor.h"
-
-#include "llvm/DWARFLinker/DWARFLinker.h"
-#include "llvm/DWARFLinker/DWARFStreamer.h"
-#include <string>
-
-namespace llvm {
-namespace dsymutil {
-
-struct LinkOptions {
- /// Verbosity
- bool Verbose = false;
-
- /// Statistics
- bool Statistics = false;
-
- /// Skip emitting output
- bool NoOutput = false;
-
- /// Do not unique types according to ODR
- bool NoODR = false;
-
- /// Update
- bool Update = false;
-
- /// Minimize
- bool Minimize = false;
-
- /// Do not check swiftmodule timestamp
- bool NoTimestamp = false;
-
- /// Number of threads.
- unsigned Threads = 1;
-
- // Output file type.
- OutputFileType FileType = OutputFileType::Object;
-
- /// The accelerator table kind
- AccelTableKind TheAccelTableKind;
-
- /// -oso-prepend-path
- std::string PrependPath;
-
- /// The -object-prefix-map.
- std::map<std::string, std::string> ObjectPrefixMap;
-
- /// The Resources directory in the .dSYM bundle.
- Optional<std::string> ResourceDir;
-
- /// Symbol map translator.
- SymbolMapTranslator Translator;
-
- /// Virtual File System.
- llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS =
- vfs::getRealFileSystem();
-
- /// Fields used for linking and placing remarks into the .dSYM bundle.
- /// @{
-
- /// Number of debug maps processed in total.
- unsigned NumDebugMaps = 0;
-
- /// -remarks-prepend-path: prepend a path to all the external remark file
- /// paths found in remark metadata.
- std::string RemarksPrependPath;
-
- /// The output format of the remarks.
- remarks::Format RemarksFormat = remarks::Format::Bitstream;
-
- /// @}
-
- LinkOptions() = default;
-};
-
-inline void warn(Twine Warning, Twine Context = {}) {
- WithColor::warning() << Warning + "\n";
- if (!Context.isTriviallyEmpty())
- WithColor::note() << Twine("while processing ") + Context + "\n";
-}
-
-inline bool error(Twine Error, Twine Context = {}) {
- WithColor::error() << Error + "\n";
- if (!Context.isTriviallyEmpty())
- WithColor::note() << Twine("while processing ") + Context + "\n";
- return false;
-}
-
-} // end namespace dsymutil
-} // end namespace llvm
-
-#endif // LLVM_TOOLS_DSYMUTIL_LINKOPTIONS_H
+//===- tools/dsymutil/LinkUtils.h - Dwarf linker utilities ------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TOOLS_DSYMUTIL_LINKOPTIONS_H
+#define LLVM_TOOLS_DSYMUTIL_LINKOPTIONS_H
+
+#include "SymbolMap.h"
+
+#include "llvm/ADT/Twine.h"
+#include "llvm/Remarks/RemarkFormat.h"
+#include "llvm/Support/VirtualFileSystem.h"
+#include "llvm/Support/WithColor.h"
+
+#include "llvm/DWARFLinker/DWARFLinker.h"
+#include "llvm/DWARFLinker/DWARFStreamer.h"
+#include <string>
+
+namespace llvm {
+namespace dsymutil {
+
+struct LinkOptions {
+ /// Verbosity
+ bool Verbose = false;
+
+ /// Statistics
+ bool Statistics = false;
+
+ /// Skip emitting output
+ bool NoOutput = false;
+
+ /// Do not unique types according to ODR
+ bool NoODR = false;
+
+ /// Update
+ bool Update = false;
+
+ /// Minimize
+ bool Minimize = false;
+
+ /// Do not check swiftmodule timestamp
+ bool NoTimestamp = false;
+
+ /// Number of threads.
+ unsigned Threads = 1;
+
+ // Output file type.
+ OutputFileType FileType = OutputFileType::Object;
+
+ /// The accelerator table kind
+ AccelTableKind TheAccelTableKind;
+
+ /// -oso-prepend-path
+ std::string PrependPath;
+
+ /// The -object-prefix-map.
+ std::map<std::string, std::string> ObjectPrefixMap;
+
+ /// The Resources directory in the .dSYM bundle.
+ Optional<std::string> ResourceDir;
+
+ /// Symbol map translator.
+ SymbolMapTranslator Translator;
+
+ /// Virtual File System.
+ llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS =
+ vfs::getRealFileSystem();
+
+ /// Fields used for linking and placing remarks into the .dSYM bundle.
+ /// @{
+
+ /// Number of debug maps processed in total.
+ unsigned NumDebugMaps = 0;
+
+ /// -remarks-prepend-path: prepend a path to all the external remark file
+ /// paths found in remark metadata.
+ std::string RemarksPrependPath;
+
+ /// The output format of the remarks.
+ remarks::Format RemarksFormat = remarks::Format::Bitstream;
+
+ /// @}
+
+ LinkOptions() = default;
+};
+
+inline void warn(Twine Warning, Twine Context = {}) {
+ WithColor::warning() << Warning + "\n";
+ if (!Context.isTriviallyEmpty())
+ WithColor::note() << Twine("while processing ") + Context + "\n";
+}
+
+inline bool error(Twine Error, Twine Context = {}) {
+ WithColor::error() << Error + "\n";
+ if (!Context.isTriviallyEmpty())
+ WithColor::note() << Twine("while processing ") + Context + "\n";
+ return false;
+}
+
+} // end namespace dsymutil
+} // end namespace llvm
+
+#endif // LLVM_TOOLS_DSYMUTIL_LINKOPTIONS_H
diff --git a/contrib/libs/llvm12/tools/dsymutil/MachODebugMapParser.cpp b/contrib/libs/llvm12/tools/dsymutil/MachODebugMapParser.cpp
index 37848c561a..4c05326dc2 100644
--- a/contrib/libs/llvm12/tools/dsymutil/MachODebugMapParser.cpp
+++ b/contrib/libs/llvm12/tools/dsymutil/MachODebugMapParser.cpp
@@ -1,609 +1,609 @@
-//===- tools/dsymutil/MachODebugMapParser.cpp - Parse STABS debug maps ----===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "BinaryHolder.h"
-#include "DebugMap.h"
-#include "MachOUtils.h"
-#include "llvm/ADT/Optional.h"
-#include "llvm/Object/MachO.h"
-#include "llvm/Support/Path.h"
-#include "llvm/Support/WithColor.h"
-#include "llvm/Support/raw_ostream.h"
-#include <vector>
-
-namespace {
-using namespace llvm;
-using namespace llvm::dsymutil;
-using namespace llvm::object;
-
-class MachODebugMapParser {
-public:
- MachODebugMapParser(llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS,
- StringRef BinaryPath, ArrayRef<std::string> Archs,
- StringRef PathPrefix = "",
- bool PaperTrailWarnings = false, bool Verbose = false)
- : BinaryPath(std::string(BinaryPath)), Archs(Archs.begin(), Archs.end()),
- PathPrefix(std::string(PathPrefix)),
- PaperTrailWarnings(PaperTrailWarnings), BinHolder(VFS, Verbose),
- CurrentDebugMapObject(nullptr) {}
-
- /// Parses and returns the DebugMaps of the input binary. The binary contains
- /// multiple maps in case it is a universal binary.
- /// \returns an error in case the provided BinaryPath doesn't exist
- /// or isn't of a supported type.
- ErrorOr<std::vector<std::unique_ptr<DebugMap>>> parse();
-
- /// Walk the symbol table and dump it.
- bool dumpStab();
-
-private:
- std::string BinaryPath;
- SmallVector<StringRef, 1> Archs;
- std::string PathPrefix;
- bool PaperTrailWarnings;
-
- /// Owns the MemoryBuffer for the main binary.
- BinaryHolder BinHolder;
- /// Map of the binary symbol addresses.
- StringMap<uint64_t> MainBinarySymbolAddresses;
- StringRef MainBinaryStrings;
- /// The constructed DebugMap.
- std::unique_ptr<DebugMap> Result;
- /// List of common symbols that need to be added to the debug map.
- std::vector<std::string> CommonSymbols;
-
- /// Map of the currently processed object file symbol addresses.
- StringMap<Optional<uint64_t>> CurrentObjectAddresses;
- /// Element of the debug map corresponding to the current object file.
- DebugMapObject *CurrentDebugMapObject;
-
- /// Holds function info while function scope processing.
- const char *CurrentFunctionName;
- uint64_t CurrentFunctionAddress;
-
- std::unique_ptr<DebugMap> parseOneBinary(const MachOObjectFile &MainBinary,
- StringRef BinaryPath);
-
- void
- switchToNewDebugMapObject(StringRef Filename,
- sys::TimePoint<std::chrono::seconds> Timestamp);
- void resetParserState();
- uint64_t getMainBinarySymbolAddress(StringRef Name);
- std::vector<StringRef> getMainBinarySymbolNames(uint64_t Value);
- 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);
-
- template <typename STEType> void handleStabDebugMapEntry(const STEType &STE) {
- handleStabSymbolTableEntry(STE.n_strx, STE.n_type, STE.n_sect, STE.n_desc,
- STE.n_value);
- }
-
- void addCommonSymbols();
-
- /// Dump the symbol table output header.
- void dumpSymTabHeader(raw_ostream &OS, StringRef Arch);
-
- /// Dump the contents of nlist entries.
- void dumpSymTabEntry(raw_ostream &OS, uint64_t Index, uint32_t StringIndex,
- uint8_t Type, uint8_t SectionIndex, uint16_t Flags,
- uint64_t Value);
-
- template <typename STEType>
- void dumpSymTabEntry(raw_ostream &OS, uint64_t Index, const STEType &STE) {
- dumpSymTabEntry(OS, Index, STE.n_strx, STE.n_type, STE.n_sect, STE.n_desc,
- STE.n_value);
- }
- void dumpOneBinaryStab(const MachOObjectFile &MainBinary,
- StringRef BinaryPath);
-
- void Warning(const Twine &Msg, StringRef File = StringRef()) {
- WithColor::warning() << "("
- << MachOUtils::getArchName(
- Result->getTriple().getArchName())
- << ") " << File << " " << Msg << "\n";
-
- if (PaperTrailWarnings) {
- if (!File.empty())
- Result->addDebugMapObject(File, sys::TimePoint<std::chrono::seconds>());
- if (Result->end() != Result->begin()) {
- auto it = Result->end();
- (*--it)->addWarning(Msg.str());
- }
- }
- }
-};
-
-} // anonymous namespace
-
-/// Reset the parser state corresponding to the current object
-/// file. This is to be called after an object file is finished
-/// processing.
-void MachODebugMapParser::resetParserState() {
- CommonSymbols.clear();
- CurrentObjectAddresses.clear();
- CurrentDebugMapObject = nullptr;
-}
-
-/// Commons symbols won't show up in the symbol map but might need to be
-/// relocated. We can add them to the symbol table ourselves by combining the
-/// information in the object file (the symbol name) and the main binary (the
-/// address).
-void MachODebugMapParser::addCommonSymbols() {
- for (auto &CommonSymbol : CommonSymbols) {
- uint64_t CommonAddr = getMainBinarySymbolAddress(CommonSymbol);
- if (CommonAddr == 0) {
- // The main binary doesn't have an address for the given symbol.
- continue;
- }
- if (!CurrentDebugMapObject->addSymbol(CommonSymbol, None /*ObjectAddress*/,
- CommonAddr, 0 /*size*/)) {
- // The symbol is already present.
- continue;
- }
- }
-}
-
-/// Create a new DebugMapObject. This function resets the state of the
-/// parser that was referring to the last object file and sets
-/// everything up to add symbols to the new one.
-void MachODebugMapParser::switchToNewDebugMapObject(
- StringRef Filename, sys::TimePoint<std::chrono::seconds> Timestamp) {
- addCommonSymbols();
- resetParserState();
-
- SmallString<80> Path(PathPrefix);
- sys::path::append(Path, Filename);
-
- auto ObjectEntry = BinHolder.getObjectEntry(Path, Timestamp);
- if (!ObjectEntry) {
- auto Err = ObjectEntry.takeError();
- Warning("unable to open object file: " + toString(std::move(Err)),
- Path.str());
- return;
- }
-
- auto Object = ObjectEntry->getObjectAs<MachOObjectFile>(Result->getTriple());
- if (!Object) {
- auto Err = Object.takeError();
- Warning("unable to open object file: " + toString(std::move(Err)),
- Path.str());
- return;
- }
-
- CurrentDebugMapObject =
- &Result->addDebugMapObject(Path, Timestamp, MachO::N_OSO);
- loadCurrentObjectFileSymbols(*Object);
-}
-
-static std::string getArchName(const object::MachOObjectFile &Obj) {
- Triple T = Obj.getArchTriple();
- return std::string(T.getArchName());
-}
-
-std::unique_ptr<DebugMap>
-MachODebugMapParser::parseOneBinary(const MachOObjectFile &MainBinary,
- StringRef BinaryPath) {
- loadMainBinarySymbols(MainBinary);
- ArrayRef<uint8_t> UUID = MainBinary.getUuid();
- Result =
- std::make_unique<DebugMap>(MainBinary.getArchTriple(), BinaryPath, UUID);
- MainBinaryStrings = MainBinary.getStringTableData();
- for (const SymbolRef &Symbol : MainBinary.symbols()) {
- const DataRefImpl &DRI = Symbol.getRawDataRefImpl();
- if (MainBinary.is64Bit())
- handleStabDebugMapEntry(MainBinary.getSymbol64TableEntry(DRI));
- else
- handleStabDebugMapEntry(MainBinary.getSymbolTableEntry(DRI));
- }
-
- resetParserState();
- return std::move(Result);
-}
-
-// Table that maps Darwin's Mach-O stab constants to strings to allow printing.
-// llvm-nm has very similar code, the strings used here are however slightly
-// different and part of the interface of dsymutil (some project's build-systems
-// parse the ouptut of dsymutil -s), thus they shouldn't be changed.
-struct DarwinStabName {
- uint8_t NType;
- const char *Name;
-};
-
-static const struct DarwinStabName DarwinStabNames[] = {
- {MachO::N_GSYM, "N_GSYM"}, {MachO::N_FNAME, "N_FNAME"},
- {MachO::N_FUN, "N_FUN"}, {MachO::N_STSYM, "N_STSYM"},
- {MachO::N_LCSYM, "N_LCSYM"}, {MachO::N_BNSYM, "N_BNSYM"},
- {MachO::N_PC, "N_PC"}, {MachO::N_AST, "N_AST"},
- {MachO::N_OPT, "N_OPT"}, {MachO::N_RSYM, "N_RSYM"},
- {MachO::N_SLINE, "N_SLINE"}, {MachO::N_ENSYM, "N_ENSYM"},
- {MachO::N_SSYM, "N_SSYM"}, {MachO::N_SO, "N_SO"},
- {MachO::N_OSO, "N_OSO"}, {MachO::N_LSYM, "N_LSYM"},
- {MachO::N_BINCL, "N_BINCL"}, {MachO::N_SOL, "N_SOL"},
- {MachO::N_PARAMS, "N_PARAM"}, {MachO::N_VERSION, "N_VERS"},
- {MachO::N_OLEVEL, "N_OLEV"}, {MachO::N_PSYM, "N_PSYM"},
- {MachO::N_EINCL, "N_EINCL"}, {MachO::N_ENTRY, "N_ENTRY"},
- {MachO::N_LBRAC, "N_LBRAC"}, {MachO::N_EXCL, "N_EXCL"},
- {MachO::N_RBRAC, "N_RBRAC"}, {MachO::N_BCOMM, "N_BCOMM"},
- {MachO::N_ECOMM, "N_ECOMM"}, {MachO::N_ECOML, "N_ECOML"},
- {MachO::N_LENG, "N_LENG"}, {0, nullptr}};
-
-static const char *getDarwinStabString(uint8_t NType) {
- for (unsigned i = 0; DarwinStabNames[i].Name; i++) {
- if (DarwinStabNames[i].NType == NType)
- return DarwinStabNames[i].Name;
- }
- return nullptr;
-}
-
-void MachODebugMapParser::dumpSymTabHeader(raw_ostream &OS, StringRef Arch) {
- OS << "-----------------------------------"
- "-----------------------------------\n";
- OS << "Symbol table for: '" << BinaryPath << "' (" << Arch.data() << ")\n";
- OS << "-----------------------------------"
- "-----------------------------------\n";
- OS << "Index n_strx n_type n_sect n_desc n_value\n";
- OS << "======== -------- ------------------ ------ ------ ----------------\n";
-}
-
-void MachODebugMapParser::dumpSymTabEntry(raw_ostream &OS, uint64_t Index,
- uint32_t StringIndex, uint8_t Type,
- uint8_t SectionIndex, uint16_t Flags,
- uint64_t Value) {
- // Index
- OS << '[' << format_decimal(Index, 6)
- << "] "
- // n_strx
- << format_hex_no_prefix(StringIndex, 8)
- << ' '
- // n_type...
- << format_hex_no_prefix(Type, 2) << " (";
-
- if (Type & MachO::N_STAB)
- OS << left_justify(getDarwinStabString(Type), 13);
- else {
- if (Type & MachO::N_PEXT)
- OS << "PEXT ";
- else
- OS << " ";
- switch (Type & MachO::N_TYPE) {
- case MachO::N_UNDF: // 0x0 undefined, n_sect == NO_SECT
- OS << "UNDF";
- break;
- case MachO::N_ABS: // 0x2 absolute, n_sect == NO_SECT
- OS << "ABS ";
- break;
- case MachO::N_SECT: // 0xe defined in section number n_sect
- OS << "SECT";
- break;
- case MachO::N_PBUD: // 0xc prebound undefined (defined in a dylib)
- OS << "PBUD";
- break;
- case MachO::N_INDR: // 0xa indirect
- OS << "INDR";
- break;
- default:
- OS << format_hex_no_prefix(Type, 2) << " ";
- break;
- }
- if (Type & MachO::N_EXT)
- OS << " EXT";
- else
- OS << " ";
- }
-
- OS << ") "
- // n_sect
- << format_hex_no_prefix(SectionIndex, 2)
- << " "
- // n_desc
- << format_hex_no_prefix(Flags, 4)
- << " "
- // n_value
- << format_hex_no_prefix(Value, 16);
-
- const char *Name = &MainBinaryStrings.data()[StringIndex];
- if (Name && Name[0])
- OS << " '" << Name << "'";
-
- OS << "\n";
-}
-
-void MachODebugMapParser::dumpOneBinaryStab(const MachOObjectFile &MainBinary,
- StringRef BinaryPath) {
- loadMainBinarySymbols(MainBinary);
- MainBinaryStrings = MainBinary.getStringTableData();
- raw_ostream &OS(llvm::outs());
-
- dumpSymTabHeader(OS, getArchName(MainBinary));
- uint64_t Idx = 0;
- for (const SymbolRef &Symbol : MainBinary.symbols()) {
- const DataRefImpl &DRI = Symbol.getRawDataRefImpl();
- if (MainBinary.is64Bit())
- dumpSymTabEntry(OS, Idx, MainBinary.getSymbol64TableEntry(DRI));
- else
- dumpSymTabEntry(OS, Idx, MainBinary.getSymbolTableEntry(DRI));
- Idx++;
- }
-
- OS << "\n\n";
- resetParserState();
-}
-
-static bool shouldLinkArch(SmallVectorImpl<StringRef> &Archs, StringRef Arch) {
- if (Archs.empty() || is_contained(Archs, "all") || is_contained(Archs, "*"))
- return true;
-
- if (Arch.startswith("arm") && Arch != "arm64" && is_contained(Archs, "arm"))
- return true;
-
- SmallString<16> ArchName = Arch;
- if (Arch.startswith("thumb"))
- ArchName = ("arm" + Arch.substr(5)).str();
-
- return is_contained(Archs, ArchName);
-}
-
-bool MachODebugMapParser::dumpStab() {
- auto ObjectEntry = BinHolder.getObjectEntry(BinaryPath);
- if (!ObjectEntry) {
- auto Err = ObjectEntry.takeError();
- WithColor::error() << "cannot load '" << BinaryPath
- << "': " << toString(std::move(Err)) << '\n';
- return false;
- }
-
- auto Objects = ObjectEntry->getObjectsAs<MachOObjectFile>();
- if (!Objects) {
- auto Err = Objects.takeError();
- WithColor::error() << "cannot get '" << BinaryPath
- << "' as MachO file: " << toString(std::move(Err))
- << "\n";
- return false;
- }
-
- for (const auto *Object : *Objects)
- if (shouldLinkArch(Archs, Object->getArchTriple().getArchName()))
- dumpOneBinaryStab(*Object, BinaryPath);
-
- return true;
-}
-
-/// 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::vector<std::unique_ptr<DebugMap>>> MachODebugMapParser::parse() {
- auto ObjectEntry = BinHolder.getObjectEntry(BinaryPath);
- if (!ObjectEntry) {
- return errorToErrorCode(ObjectEntry.takeError());
- }
-
- auto Objects = ObjectEntry->getObjectsAs<MachOObjectFile>();
- if (!Objects) {
- return errorToErrorCode(Objects.takeError());
- }
-
- std::vector<std::unique_ptr<DebugMap>> Results;
- for (const auto *Object : *Objects)
- if (shouldLinkArch(Archs, Object->getArchTriple().getArchName()))
- Results.push_back(parseOneBinary(*Object, BinaryPath));
-
- return std::move(Results);
-}
-
-/// Interpret the STAB entries to fill the DebugMap.
-void MachODebugMapParser::handleStabSymbolTableEntry(uint32_t StringIndex,
- uint8_t Type,
- uint8_t SectionIndex,
- uint16_t Flags,
- uint64_t Value) {
- if (!(Type & MachO::N_STAB))
- return;
-
- const char *Name = &MainBinaryStrings.data()[StringIndex];
-
- // An N_OSO entry represents the start of a new object file description.
- 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.
- if (!CurrentDebugMapObject)
- return;
-
- uint32_t Size = 0;
- switch (Type) {
- case MachO::N_GSYM:
- // This is a global variable. We need to query the main binary
- // symbol table to find its address as it might not be in the
- // debug map (for common symbols).
- Value = getMainBinarySymbolAddress(Name);
- break;
- case MachO::N_FUN:
- // Functions are scopes in STABS. They have an end marker that
- // contains the function size.
- if (Name[0] == '\0') {
- Size = Value;
- Value = CurrentFunctionAddress;
- Name = CurrentFunctionName;
- break;
- } else {
- CurrentFunctionName = Name;
- CurrentFunctionAddress = Value;
- return;
- }
- case MachO::N_STSYM:
- break;
- default:
- return;
- }
-
- auto ObjectSymIt = CurrentObjectAddresses.find(Name);
-
- // If the name of a (non-static) symbol is not in the current object, we
- // check all its aliases from the main binary.
- if (ObjectSymIt == CurrentObjectAddresses.end() && Type != MachO::N_STSYM) {
- for (const auto &Alias : getMainBinarySymbolNames(Value)) {
- ObjectSymIt = CurrentObjectAddresses.find(Alias);
- if (ObjectSymIt != CurrentObjectAddresses.end())
- break;
- }
- }
-
- if (ObjectSymIt == CurrentObjectAddresses.end()) {
- Warning("could not find object file symbol for symbol " + Twine(Name));
- return;
- }
-
- if (!CurrentDebugMapObject->addSymbol(Name, ObjectSymIt->getValue(), Value,
- Size)) {
- Warning(Twine("failed to insert symbol '") + Name + "' in the debug map.");
- return;
- }
-}
-
-/// Load the current object file symbols into CurrentObjectAddresses.
-void MachODebugMapParser::loadCurrentObjectFileSymbols(
- const object::MachOObjectFile &Obj) {
- CurrentObjectAddresses.clear();
-
- for (auto Sym : Obj.symbols()) {
- uint64_t Addr = cantFail(Sym.getValue());
- Expected<StringRef> Name = Sym.getName();
- if (!Name) {
- // TODO: Actually report errors helpfully.
- consumeError(Name.takeError());
- continue;
- }
- // The value of some categories of symbols isn't meaningful. For
- // example common symbols store their size in the value field, not
- // their address. Absolute symbols have a fixed address that can
- // conflict with standard symbols. These symbols (especially the
- // common ones), might still be referenced by relocations. These
- // relocations will use the symbol itself, and won't need an
- // object file address. The object file address field is optional
- // in the DebugMap, leave it unassigned for these symbols.
- uint32_t Flags = cantFail(Sym.getFlags());
- if (Flags & SymbolRef::SF_Absolute) {
- CurrentObjectAddresses[*Name] = None;
- } else if (Flags & SymbolRef::SF_Common) {
- CurrentObjectAddresses[*Name] = None;
- CommonSymbols.push_back(std::string(*Name));
- } else {
- CurrentObjectAddresses[*Name] = Addr;
- }
- }
-}
-
-/// Lookup a symbol address in the main binary symbol table. The
-/// parser only needs to query common symbols, thus not every symbol's
-/// address is available through this function.
-uint64_t MachODebugMapParser::getMainBinarySymbolAddress(StringRef Name) {
- auto Sym = MainBinarySymbolAddresses.find(Name);
- if (Sym == MainBinarySymbolAddresses.end())
- return 0;
- return Sym->second;
-}
-
-/// Get all symbol names in the main binary for the given value.
-std::vector<StringRef>
-MachODebugMapParser::getMainBinarySymbolNames(uint64_t Value) {
- std::vector<StringRef> Names;
- for (const auto &Entry : MainBinarySymbolAddresses) {
- if (Entry.second == Value)
- Names.push_back(Entry.first());
- }
- return Names;
-}
-
-/// Load the interesting main binary symbols' addresses into
-/// MainBinarySymbolAddresses.
-void MachODebugMapParser::loadMainBinarySymbols(
- const MachOObjectFile &MainBinary) {
- section_iterator Section = MainBinary.section_end();
- MainBinarySymbolAddresses.clear();
- for (const auto &Sym : MainBinary.symbols()) {
- Expected<SymbolRef::Type> TypeOrErr = Sym.getType();
- if (!TypeOrErr) {
- // TODO: Actually report errors helpfully.
- consumeError(TypeOrErr.takeError());
- continue;
- }
- SymbolRef::Type Type = *TypeOrErr;
- // Skip undefined and STAB entries.
- if ((Type == SymbolRef::ST_Debug) || (Type == SymbolRef::ST_Unknown))
- continue;
- // In theory, the only symbols of interest are the global variables. These
- // are the only ones that need to be queried because the address of common
- // data won't be described in the debug map. All other addresses should be
- // fetched for the debug map. In reality, by playing with 'ld -r' and
- // export lists, you can get symbols described as N_GSYM in the debug map,
- // but associated with a local symbol. Gather all the symbols, but prefer
- // the global ones.
- uint8_t SymType =
- MainBinary.getSymbolTableEntry(Sym.getRawDataRefImpl()).n_type;
- bool Extern = SymType & (MachO::N_EXT | MachO::N_PEXT);
- Expected<section_iterator> SectionOrErr = Sym.getSection();
- if (!SectionOrErr) {
- // TODO: Actually report errors helpfully.
- consumeError(SectionOrErr.takeError());
- continue;
- }
- Section = *SectionOrErr;
+//===- tools/dsymutil/MachODebugMapParser.cpp - Parse STABS debug maps ----===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "BinaryHolder.h"
+#include "DebugMap.h"
+#include "MachOUtils.h"
+#include "llvm/ADT/Optional.h"
+#include "llvm/Object/MachO.h"
+#include "llvm/Support/Path.h"
+#include "llvm/Support/WithColor.h"
+#include "llvm/Support/raw_ostream.h"
+#include <vector>
+
+namespace {
+using namespace llvm;
+using namespace llvm::dsymutil;
+using namespace llvm::object;
+
+class MachODebugMapParser {
+public:
+ MachODebugMapParser(llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS,
+ StringRef BinaryPath, ArrayRef<std::string> Archs,
+ StringRef PathPrefix = "",
+ bool PaperTrailWarnings = false, bool Verbose = false)
+ : BinaryPath(std::string(BinaryPath)), Archs(Archs.begin(), Archs.end()),
+ PathPrefix(std::string(PathPrefix)),
+ PaperTrailWarnings(PaperTrailWarnings), BinHolder(VFS, Verbose),
+ CurrentDebugMapObject(nullptr) {}
+
+ /// Parses and returns the DebugMaps of the input binary. The binary contains
+ /// multiple maps in case it is a universal binary.
+ /// \returns an error in case the provided BinaryPath doesn't exist
+ /// or isn't of a supported type.
+ ErrorOr<std::vector<std::unique_ptr<DebugMap>>> parse();
+
+ /// Walk the symbol table and dump it.
+ bool dumpStab();
+
+private:
+ std::string BinaryPath;
+ SmallVector<StringRef, 1> Archs;
+ std::string PathPrefix;
+ bool PaperTrailWarnings;
+
+ /// Owns the MemoryBuffer for the main binary.
+ BinaryHolder BinHolder;
+ /// Map of the binary symbol addresses.
+ StringMap<uint64_t> MainBinarySymbolAddresses;
+ StringRef MainBinaryStrings;
+ /// The constructed DebugMap.
+ std::unique_ptr<DebugMap> Result;
+ /// List of common symbols that need to be added to the debug map.
+ std::vector<std::string> CommonSymbols;
+
+ /// Map of the currently processed object file symbol addresses.
+ StringMap<Optional<uint64_t>> CurrentObjectAddresses;
+ /// Element of the debug map corresponding to the current object file.
+ DebugMapObject *CurrentDebugMapObject;
+
+ /// Holds function info while function scope processing.
+ const char *CurrentFunctionName;
+ uint64_t CurrentFunctionAddress;
+
+ std::unique_ptr<DebugMap> parseOneBinary(const MachOObjectFile &MainBinary,
+ StringRef BinaryPath);
+
+ void
+ switchToNewDebugMapObject(StringRef Filename,
+ sys::TimePoint<std::chrono::seconds> Timestamp);
+ void resetParserState();
+ uint64_t getMainBinarySymbolAddress(StringRef Name);
+ std::vector<StringRef> getMainBinarySymbolNames(uint64_t Value);
+ 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);
+
+ template <typename STEType> void handleStabDebugMapEntry(const STEType &STE) {
+ handleStabSymbolTableEntry(STE.n_strx, STE.n_type, STE.n_sect, STE.n_desc,
+ STE.n_value);
+ }
+
+ void addCommonSymbols();
+
+ /// Dump the symbol table output header.
+ void dumpSymTabHeader(raw_ostream &OS, StringRef Arch);
+
+ /// Dump the contents of nlist entries.
+ void dumpSymTabEntry(raw_ostream &OS, uint64_t Index, uint32_t StringIndex,
+ uint8_t Type, uint8_t SectionIndex, uint16_t Flags,
+ uint64_t Value);
+
+ template <typename STEType>
+ void dumpSymTabEntry(raw_ostream &OS, uint64_t Index, const STEType &STE) {
+ dumpSymTabEntry(OS, Index, STE.n_strx, STE.n_type, STE.n_sect, STE.n_desc,
+ STE.n_value);
+ }
+ void dumpOneBinaryStab(const MachOObjectFile &MainBinary,
+ StringRef BinaryPath);
+
+ void Warning(const Twine &Msg, StringRef File = StringRef()) {
+ WithColor::warning() << "("
+ << MachOUtils::getArchName(
+ Result->getTriple().getArchName())
+ << ") " << File << " " << Msg << "\n";
+
+ if (PaperTrailWarnings) {
+ if (!File.empty())
+ Result->addDebugMapObject(File, sys::TimePoint<std::chrono::seconds>());
+ if (Result->end() != Result->begin()) {
+ auto it = Result->end();
+ (*--it)->addWarning(Msg.str());
+ }
+ }
+ }
+};
+
+} // anonymous namespace
+
+/// Reset the parser state corresponding to the current object
+/// file. This is to be called after an object file is finished
+/// processing.
+void MachODebugMapParser::resetParserState() {
+ CommonSymbols.clear();
+ CurrentObjectAddresses.clear();
+ CurrentDebugMapObject = nullptr;
+}
+
+/// Commons symbols won't show up in the symbol map but might need to be
+/// relocated. We can add them to the symbol table ourselves by combining the
+/// information in the object file (the symbol name) and the main binary (the
+/// address).
+void MachODebugMapParser::addCommonSymbols() {
+ for (auto &CommonSymbol : CommonSymbols) {
+ uint64_t CommonAddr = getMainBinarySymbolAddress(CommonSymbol);
+ if (CommonAddr == 0) {
+ // The main binary doesn't have an address for the given symbol.
+ continue;
+ }
+ if (!CurrentDebugMapObject->addSymbol(CommonSymbol, None /*ObjectAddress*/,
+ CommonAddr, 0 /*size*/)) {
+ // The symbol is already present.
+ continue;
+ }
+ }
+}
+
+/// Create a new DebugMapObject. This function resets the state of the
+/// parser that was referring to the last object file and sets
+/// everything up to add symbols to the new one.
+void MachODebugMapParser::switchToNewDebugMapObject(
+ StringRef Filename, sys::TimePoint<std::chrono::seconds> Timestamp) {
+ addCommonSymbols();
+ resetParserState();
+
+ SmallString<80> Path(PathPrefix);
+ sys::path::append(Path, Filename);
+
+ auto ObjectEntry = BinHolder.getObjectEntry(Path, Timestamp);
+ if (!ObjectEntry) {
+ auto Err = ObjectEntry.takeError();
+ Warning("unable to open object file: " + toString(std::move(Err)),
+ Path.str());
+ return;
+ }
+
+ auto Object = ObjectEntry->getObjectAs<MachOObjectFile>(Result->getTriple());
+ if (!Object) {
+ auto Err = Object.takeError();
+ Warning("unable to open object file: " + toString(std::move(Err)),
+ Path.str());
+ return;
+ }
+
+ CurrentDebugMapObject =
+ &Result->addDebugMapObject(Path, Timestamp, MachO::N_OSO);
+ loadCurrentObjectFileSymbols(*Object);
+}
+
+static std::string getArchName(const object::MachOObjectFile &Obj) {
+ Triple T = Obj.getArchTriple();
+ return std::string(T.getArchName());
+}
+
+std::unique_ptr<DebugMap>
+MachODebugMapParser::parseOneBinary(const MachOObjectFile &MainBinary,
+ StringRef BinaryPath) {
+ loadMainBinarySymbols(MainBinary);
+ ArrayRef<uint8_t> UUID = MainBinary.getUuid();
+ Result =
+ std::make_unique<DebugMap>(MainBinary.getArchTriple(), BinaryPath, UUID);
+ MainBinaryStrings = MainBinary.getStringTableData();
+ for (const SymbolRef &Symbol : MainBinary.symbols()) {
+ const DataRefImpl &DRI = Symbol.getRawDataRefImpl();
+ if (MainBinary.is64Bit())
+ handleStabDebugMapEntry(MainBinary.getSymbol64TableEntry(DRI));
+ else
+ handleStabDebugMapEntry(MainBinary.getSymbolTableEntry(DRI));
+ }
+
+ resetParserState();
+ return std::move(Result);
+}
+
+// Table that maps Darwin's Mach-O stab constants to strings to allow printing.
+// llvm-nm has very similar code, the strings used here are however slightly
+// different and part of the interface of dsymutil (some project's build-systems
+// parse the ouptut of dsymutil -s), thus they shouldn't be changed.
+struct DarwinStabName {
+ uint8_t NType;
+ const char *Name;
+};
+
+static const struct DarwinStabName DarwinStabNames[] = {
+ {MachO::N_GSYM, "N_GSYM"}, {MachO::N_FNAME, "N_FNAME"},
+ {MachO::N_FUN, "N_FUN"}, {MachO::N_STSYM, "N_STSYM"},
+ {MachO::N_LCSYM, "N_LCSYM"}, {MachO::N_BNSYM, "N_BNSYM"},
+ {MachO::N_PC, "N_PC"}, {MachO::N_AST, "N_AST"},
+ {MachO::N_OPT, "N_OPT"}, {MachO::N_RSYM, "N_RSYM"},
+ {MachO::N_SLINE, "N_SLINE"}, {MachO::N_ENSYM, "N_ENSYM"},
+ {MachO::N_SSYM, "N_SSYM"}, {MachO::N_SO, "N_SO"},
+ {MachO::N_OSO, "N_OSO"}, {MachO::N_LSYM, "N_LSYM"},
+ {MachO::N_BINCL, "N_BINCL"}, {MachO::N_SOL, "N_SOL"},
+ {MachO::N_PARAMS, "N_PARAM"}, {MachO::N_VERSION, "N_VERS"},
+ {MachO::N_OLEVEL, "N_OLEV"}, {MachO::N_PSYM, "N_PSYM"},
+ {MachO::N_EINCL, "N_EINCL"}, {MachO::N_ENTRY, "N_ENTRY"},
+ {MachO::N_LBRAC, "N_LBRAC"}, {MachO::N_EXCL, "N_EXCL"},
+ {MachO::N_RBRAC, "N_RBRAC"}, {MachO::N_BCOMM, "N_BCOMM"},
+ {MachO::N_ECOMM, "N_ECOMM"}, {MachO::N_ECOML, "N_ECOML"},
+ {MachO::N_LENG, "N_LENG"}, {0, nullptr}};
+
+static const char *getDarwinStabString(uint8_t NType) {
+ for (unsigned i = 0; DarwinStabNames[i].Name; i++) {
+ if (DarwinStabNames[i].NType == NType)
+ return DarwinStabNames[i].Name;
+ }
+ return nullptr;
+}
+
+void MachODebugMapParser::dumpSymTabHeader(raw_ostream &OS, StringRef Arch) {
+ OS << "-----------------------------------"
+ "-----------------------------------\n";
+ OS << "Symbol table for: '" << BinaryPath << "' (" << Arch.data() << ")\n";
+ OS << "-----------------------------------"
+ "-----------------------------------\n";
+ OS << "Index n_strx n_type n_sect n_desc n_value\n";
+ OS << "======== -------- ------------------ ------ ------ ----------------\n";
+}
+
+void MachODebugMapParser::dumpSymTabEntry(raw_ostream &OS, uint64_t Index,
+ uint32_t StringIndex, uint8_t Type,
+ uint8_t SectionIndex, uint16_t Flags,
+ uint64_t Value) {
+ // Index
+ OS << '[' << format_decimal(Index, 6)
+ << "] "
+ // n_strx
+ << format_hex_no_prefix(StringIndex, 8)
+ << ' '
+ // n_type...
+ << format_hex_no_prefix(Type, 2) << " (";
+
+ if (Type & MachO::N_STAB)
+ OS << left_justify(getDarwinStabString(Type), 13);
+ else {
+ if (Type & MachO::N_PEXT)
+ OS << "PEXT ";
+ else
+ OS << " ";
+ switch (Type & MachO::N_TYPE) {
+ case MachO::N_UNDF: // 0x0 undefined, n_sect == NO_SECT
+ OS << "UNDF";
+ break;
+ case MachO::N_ABS: // 0x2 absolute, n_sect == NO_SECT
+ OS << "ABS ";
+ break;
+ case MachO::N_SECT: // 0xe defined in section number n_sect
+ OS << "SECT";
+ break;
+ case MachO::N_PBUD: // 0xc prebound undefined (defined in a dylib)
+ OS << "PBUD";
+ break;
+ case MachO::N_INDR: // 0xa indirect
+ OS << "INDR";
+ break;
+ default:
+ OS << format_hex_no_prefix(Type, 2) << " ";
+ break;
+ }
+ if (Type & MachO::N_EXT)
+ OS << " EXT";
+ else
+ OS << " ";
+ }
+
+ OS << ") "
+ // n_sect
+ << format_hex_no_prefix(SectionIndex, 2)
+ << " "
+ // n_desc
+ << format_hex_no_prefix(Flags, 4)
+ << " "
+ // n_value
+ << format_hex_no_prefix(Value, 16);
+
+ const char *Name = &MainBinaryStrings.data()[StringIndex];
+ if (Name && Name[0])
+ OS << " '" << Name << "'";
+
+ OS << "\n";
+}
+
+void MachODebugMapParser::dumpOneBinaryStab(const MachOObjectFile &MainBinary,
+ StringRef BinaryPath) {
+ loadMainBinarySymbols(MainBinary);
+ MainBinaryStrings = MainBinary.getStringTableData();
+ raw_ostream &OS(llvm::outs());
+
+ dumpSymTabHeader(OS, getArchName(MainBinary));
+ uint64_t Idx = 0;
+ for (const SymbolRef &Symbol : MainBinary.symbols()) {
+ const DataRefImpl &DRI = Symbol.getRawDataRefImpl();
+ if (MainBinary.is64Bit())
+ dumpSymTabEntry(OS, Idx, MainBinary.getSymbol64TableEntry(DRI));
+ else
+ dumpSymTabEntry(OS, Idx, MainBinary.getSymbolTableEntry(DRI));
+ Idx++;
+ }
+
+ OS << "\n\n";
+ resetParserState();
+}
+
+static bool shouldLinkArch(SmallVectorImpl<StringRef> &Archs, StringRef Arch) {
+ if (Archs.empty() || is_contained(Archs, "all") || is_contained(Archs, "*"))
+ return true;
+
+ if (Arch.startswith("arm") && Arch != "arm64" && is_contained(Archs, "arm"))
+ return true;
+
+ SmallString<16> ArchName = Arch;
+ if (Arch.startswith("thumb"))
+ ArchName = ("arm" + Arch.substr(5)).str();
+
+ return is_contained(Archs, ArchName);
+}
+
+bool MachODebugMapParser::dumpStab() {
+ auto ObjectEntry = BinHolder.getObjectEntry(BinaryPath);
+ if (!ObjectEntry) {
+ auto Err = ObjectEntry.takeError();
+ WithColor::error() << "cannot load '" << BinaryPath
+ << "': " << toString(std::move(Err)) << '\n';
+ return false;
+ }
+
+ auto Objects = ObjectEntry->getObjectsAs<MachOObjectFile>();
+ if (!Objects) {
+ auto Err = Objects.takeError();
+ WithColor::error() << "cannot get '" << BinaryPath
+ << "' as MachO file: " << toString(std::move(Err))
+ << "\n";
+ return false;
+ }
+
+ for (const auto *Object : *Objects)
+ if (shouldLinkArch(Archs, Object->getArchTriple().getArchName()))
+ dumpOneBinaryStab(*Object, BinaryPath);
+
+ return true;
+}
+
+/// 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::vector<std::unique_ptr<DebugMap>>> MachODebugMapParser::parse() {
+ auto ObjectEntry = BinHolder.getObjectEntry(BinaryPath);
+ if (!ObjectEntry) {
+ return errorToErrorCode(ObjectEntry.takeError());
+ }
+
+ auto Objects = ObjectEntry->getObjectsAs<MachOObjectFile>();
+ if (!Objects) {
+ return errorToErrorCode(Objects.takeError());
+ }
+
+ std::vector<std::unique_ptr<DebugMap>> Results;
+ for (const auto *Object : *Objects)
+ if (shouldLinkArch(Archs, Object->getArchTriple().getArchName()))
+ Results.push_back(parseOneBinary(*Object, BinaryPath));
+
+ return std::move(Results);
+}
+
+/// Interpret the STAB entries to fill the DebugMap.
+void MachODebugMapParser::handleStabSymbolTableEntry(uint32_t StringIndex,
+ uint8_t Type,
+ uint8_t SectionIndex,
+ uint16_t Flags,
+ uint64_t Value) {
+ if (!(Type & MachO::N_STAB))
+ return;
+
+ const char *Name = &MainBinaryStrings.data()[StringIndex];
+
+ // An N_OSO entry represents the start of a new object file description.
+ 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.
+ if (!CurrentDebugMapObject)
+ return;
+
+ uint32_t Size = 0;
+ switch (Type) {
+ case MachO::N_GSYM:
+ // This is a global variable. We need to query the main binary
+ // symbol table to find its address as it might not be in the
+ // debug map (for common symbols).
+ Value = getMainBinarySymbolAddress(Name);
+ break;
+ case MachO::N_FUN:
+ // Functions are scopes in STABS. They have an end marker that
+ // contains the function size.
+ if (Name[0] == '\0') {
+ Size = Value;
+ Value = CurrentFunctionAddress;
+ Name = CurrentFunctionName;
+ break;
+ } else {
+ CurrentFunctionName = Name;
+ CurrentFunctionAddress = Value;
+ return;
+ }
+ case MachO::N_STSYM:
+ break;
+ default:
+ return;
+ }
+
+ auto ObjectSymIt = CurrentObjectAddresses.find(Name);
+
+ // If the name of a (non-static) symbol is not in the current object, we
+ // check all its aliases from the main binary.
+ if (ObjectSymIt == CurrentObjectAddresses.end() && Type != MachO::N_STSYM) {
+ for (const auto &Alias : getMainBinarySymbolNames(Value)) {
+ ObjectSymIt = CurrentObjectAddresses.find(Alias);
+ if (ObjectSymIt != CurrentObjectAddresses.end())
+ break;
+ }
+ }
+
+ if (ObjectSymIt == CurrentObjectAddresses.end()) {
+ Warning("could not find object file symbol for symbol " + Twine(Name));
+ return;
+ }
+
+ if (!CurrentDebugMapObject->addSymbol(Name, ObjectSymIt->getValue(), Value,
+ Size)) {
+ Warning(Twine("failed to insert symbol '") + Name + "' in the debug map.");
+ return;
+ }
+}
+
+/// Load the current object file symbols into CurrentObjectAddresses.
+void MachODebugMapParser::loadCurrentObjectFileSymbols(
+ const object::MachOObjectFile &Obj) {
+ CurrentObjectAddresses.clear();
+
+ for (auto Sym : Obj.symbols()) {
+ uint64_t Addr = cantFail(Sym.getValue());
+ Expected<StringRef> Name = Sym.getName();
+ if (!Name) {
+ // TODO: Actually report errors helpfully.
+ consumeError(Name.takeError());
+ continue;
+ }
+ // The value of some categories of symbols isn't meaningful. For
+ // example common symbols store their size in the value field, not
+ // their address. Absolute symbols have a fixed address that can
+ // conflict with standard symbols. These symbols (especially the
+ // common ones), might still be referenced by relocations. These
+ // relocations will use the symbol itself, and won't need an
+ // object file address. The object file address field is optional
+ // in the DebugMap, leave it unassigned for these symbols.
+ uint32_t Flags = cantFail(Sym.getFlags());
+ if (Flags & SymbolRef::SF_Absolute) {
+ CurrentObjectAddresses[*Name] = None;
+ } else if (Flags & SymbolRef::SF_Common) {
+ CurrentObjectAddresses[*Name] = None;
+ CommonSymbols.push_back(std::string(*Name));
+ } else {
+ CurrentObjectAddresses[*Name] = Addr;
+ }
+ }
+}
+
+/// Lookup a symbol address in the main binary symbol table. The
+/// parser only needs to query common symbols, thus not every symbol's
+/// address is available through this function.
+uint64_t MachODebugMapParser::getMainBinarySymbolAddress(StringRef Name) {
+ auto Sym = MainBinarySymbolAddresses.find(Name);
+ if (Sym == MainBinarySymbolAddresses.end())
+ return 0;
+ return Sym->second;
+}
+
+/// Get all symbol names in the main binary for the given value.
+std::vector<StringRef>
+MachODebugMapParser::getMainBinarySymbolNames(uint64_t Value) {
+ std::vector<StringRef> Names;
+ for (const auto &Entry : MainBinarySymbolAddresses) {
+ if (Entry.second == Value)
+ Names.push_back(Entry.first());
+ }
+ return Names;
+}
+
+/// Load the interesting main binary symbols' addresses into
+/// MainBinarySymbolAddresses.
+void MachODebugMapParser::loadMainBinarySymbols(
+ const MachOObjectFile &MainBinary) {
+ section_iterator Section = MainBinary.section_end();
+ MainBinarySymbolAddresses.clear();
+ for (const auto &Sym : MainBinary.symbols()) {
+ Expected<SymbolRef::Type> TypeOrErr = Sym.getType();
+ if (!TypeOrErr) {
+ // TODO: Actually report errors helpfully.
+ consumeError(TypeOrErr.takeError());
+ continue;
+ }
+ SymbolRef::Type Type = *TypeOrErr;
+ // Skip undefined and STAB entries.
+ if ((Type == SymbolRef::ST_Debug) || (Type == SymbolRef::ST_Unknown))
+ continue;
+ // In theory, the only symbols of interest are the global variables. These
+ // are the only ones that need to be queried because the address of common
+ // data won't be described in the debug map. All other addresses should be
+ // fetched for the debug map. In reality, by playing with 'ld -r' and
+ // export lists, you can get symbols described as N_GSYM in the debug map,
+ // but associated with a local symbol. Gather all the symbols, but prefer
+ // the global ones.
+ uint8_t SymType =
+ MainBinary.getSymbolTableEntry(Sym.getRawDataRefImpl()).n_type;
+ bool Extern = SymType & (MachO::N_EXT | MachO::N_PEXT);
+ Expected<section_iterator> SectionOrErr = Sym.getSection();
+ if (!SectionOrErr) {
+ // TODO: Actually report errors helpfully.
+ consumeError(SectionOrErr.takeError());
+ continue;
+ }
+ Section = *SectionOrErr;
if ((Section == MainBinary.section_end() || Section->isText()) && !Extern)
- continue;
- uint64_t Addr = cantFail(Sym.getValue());
- Expected<StringRef> NameOrErr = Sym.getName();
- if (!NameOrErr) {
- // TODO: Actually report errors helpfully.
- consumeError(NameOrErr.takeError());
- continue;
- }
- StringRef Name = *NameOrErr;
- if (Name.size() == 0 || Name[0] == '\0')
- continue;
- // Override only if the new key is global.
- if (Extern)
- MainBinarySymbolAddresses[Name] = Addr;
- else
- MainBinarySymbolAddresses.try_emplace(Name, Addr);
- }
-}
-
-namespace llvm {
-namespace dsymutil {
-llvm::ErrorOr<std::vector<std::unique_ptr<DebugMap>>>
-parseDebugMap(llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS,
- StringRef InputFile, ArrayRef<std::string> Archs,
- StringRef PrependPath, bool PaperTrailWarnings, bool Verbose,
- bool InputIsYAML) {
- if (InputIsYAML)
- return DebugMap::parseYAMLDebugMap(InputFile, PrependPath, Verbose);
-
- MachODebugMapParser Parser(VFS, InputFile, Archs, PrependPath,
- PaperTrailWarnings, Verbose);
- return Parser.parse();
-}
-
-bool dumpStab(llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS,
- StringRef InputFile, ArrayRef<std::string> Archs,
- StringRef PrependPath) {
- MachODebugMapParser Parser(VFS, InputFile, Archs, PrependPath, false);
- return Parser.dumpStab();
-}
-} // namespace dsymutil
-} // namespace llvm
+ continue;
+ uint64_t Addr = cantFail(Sym.getValue());
+ Expected<StringRef> NameOrErr = Sym.getName();
+ if (!NameOrErr) {
+ // TODO: Actually report errors helpfully.
+ consumeError(NameOrErr.takeError());
+ continue;
+ }
+ StringRef Name = *NameOrErr;
+ if (Name.size() == 0 || Name[0] == '\0')
+ continue;
+ // Override only if the new key is global.
+ if (Extern)
+ MainBinarySymbolAddresses[Name] = Addr;
+ else
+ MainBinarySymbolAddresses.try_emplace(Name, Addr);
+ }
+}
+
+namespace llvm {
+namespace dsymutil {
+llvm::ErrorOr<std::vector<std::unique_ptr<DebugMap>>>
+parseDebugMap(llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS,
+ StringRef InputFile, ArrayRef<std::string> Archs,
+ StringRef PrependPath, bool PaperTrailWarnings, bool Verbose,
+ bool InputIsYAML) {
+ if (InputIsYAML)
+ return DebugMap::parseYAMLDebugMap(InputFile, PrependPath, Verbose);
+
+ MachODebugMapParser Parser(VFS, InputFile, Archs, PrependPath,
+ PaperTrailWarnings, Verbose);
+ return Parser.parse();
+}
+
+bool dumpStab(llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS,
+ StringRef InputFile, ArrayRef<std::string> Archs,
+ StringRef PrependPath) {
+ MachODebugMapParser Parser(VFS, InputFile, Archs, PrependPath, false);
+ return Parser.dumpStab();
+}
+} // namespace dsymutil
+} // namespace llvm
diff --git a/contrib/libs/llvm12/tools/dsymutil/MachOUtils.cpp b/contrib/libs/llvm12/tools/dsymutil/MachOUtils.cpp
index 943af43058..c91be23ac6 100644
--- a/contrib/libs/llvm12/tools/dsymutil/MachOUtils.cpp
+++ b/contrib/libs/llvm12/tools/dsymutil/MachOUtils.cpp
@@ -1,436 +1,436 @@
-//===-- MachOUtils.cpp - Mach-o specific helpers for dsymutil ------------===//
+//===-- MachOUtils.cpp - Mach-o specific helpers for dsymutil ------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "MachOUtils.h"
+#include "BinaryHolder.h"
+#include "DebugMap.h"
+#include "LinkUtils.h"
+#include "llvm/CodeGen/NonRelocatableStringpool.h"
+#include "llvm/MC/MCAsmLayout.h"
+#include "llvm/MC/MCMachObjectWriter.h"
+#include "llvm/MC/MCObjectStreamer.h"
+#include "llvm/MC/MCSectionMachO.h"
+#include "llvm/MC/MCStreamer.h"
+#include "llvm/Object/MachO.h"
+#include "llvm/Support/FileUtilities.h"
+#include "llvm/Support/Program.h"
+#include "llvm/Support/WithColor.h"
+#include "llvm/Support/raw_ostream.h"
+
+namespace llvm {
+namespace dsymutil {
+namespace MachOUtils {
+
+llvm::Error ArchAndFile::createTempFile() {
+ llvm::SmallString<128> TmpModel;
+ llvm::sys::path::system_temp_directory(true, TmpModel);
+ llvm::sys::path::append(TmpModel, "dsym.tmp%%%%%.dwarf");
+ Expected<sys::fs::TempFile> T = sys::fs::TempFile::create(TmpModel);
+
+ if (!T)
+ return T.takeError();
+
+ File = std::make_unique<sys::fs::TempFile>(std::move(*T));
+ return Error::success();
+}
+
+llvm::StringRef ArchAndFile::path() const { return File->TmpName; }
+
+ArchAndFile::~ArchAndFile() {
+ if (File)
+ if (auto E = File->discard())
+ llvm::consumeError(std::move(E));
+}
+
+std::string getArchName(StringRef Arch) {
+ if (Arch.startswith("thumb"))
+ return (llvm::Twine("arm") + Arch.drop_front(5)).str();
+ return std::string(Arch);
+}
+
+static bool runLipo(StringRef SDKPath, SmallVectorImpl<StringRef> &Args) {
+ auto Path = sys::findProgramByName("lipo", makeArrayRef(SDKPath));
+ if (!Path)
+ Path = sys::findProgramByName("lipo");
+
+ if (!Path) {
+ WithColor::error() << "lipo: " << Path.getError().message() << "\n";
+ return false;
+ }
+
+ std::string ErrMsg;
+ int result = sys::ExecuteAndWait(*Path, Args, None, {}, 0, 0, &ErrMsg);
+ if (result) {
+ WithColor::error() << "lipo: " << ErrMsg << "\n";
+ return false;
+ }
+
+ return true;
+}
+
+bool generateUniversalBinary(SmallVectorImpl<ArchAndFile> &ArchFiles,
+ StringRef OutputFileName,
+ const LinkOptions &Options, StringRef SDKPath) {
+ // No need to merge one file into a universal fat binary.
+ if (ArchFiles.size() == 1) {
+ if (auto E = ArchFiles.front().File->keep(OutputFileName)) {
+ WithColor::error() << "while keeping " << ArchFiles.front().path()
+ << " as " << OutputFileName << ": "
+ << toString(std::move(E)) << "\n";
+ return false;
+ }
+ return true;
+ }
+
+ SmallVector<StringRef, 8> Args;
+ Args.push_back("lipo");
+ Args.push_back("-create");
+
+ for (auto &Thin : ArchFiles)
+ Args.push_back(Thin.path());
+
+ // Align segments to match dsymutil-classic alignment
+ for (auto &Thin : ArchFiles) {
+ Thin.Arch = getArchName(Thin.Arch);
+ Args.push_back("-segalign");
+ Args.push_back(Thin.Arch);
+ Args.push_back("20");
+ }
+
+ Args.push_back("-output");
+ Args.push_back(OutputFileName.data());
+
+ if (Options.Verbose) {
+ outs() << "Running lipo\n";
+ for (auto Arg : Args)
+ outs() << ' ' << Arg;
+ outs() << "\n";
+ }
+
+ return Options.NoOutput ? true : runLipo(SDKPath, Args);
+}
+
+// Return a MachO::segment_command_64 that holds the same values as the passed
+// MachO::segment_command. We do that to avoid having to duplicate the logic
+// for 32bits and 64bits segments.
+struct MachO::segment_command_64 adaptFrom32bits(MachO::segment_command Seg) {
+ MachO::segment_command_64 Seg64;
+ Seg64.cmd = Seg.cmd;
+ Seg64.cmdsize = Seg.cmdsize;
+ memcpy(Seg64.segname, Seg.segname, sizeof(Seg.segname));
+ Seg64.vmaddr = Seg.vmaddr;
+ Seg64.vmsize = Seg.vmsize;
+ Seg64.fileoff = Seg.fileoff;
+ Seg64.filesize = Seg.filesize;
+ Seg64.maxprot = Seg.maxprot;
+ Seg64.initprot = Seg.initprot;
+ Seg64.nsects = Seg.nsects;
+ Seg64.flags = Seg.flags;
+ return Seg64;
+}
+
+// Iterate on all \a Obj segments, and apply \a Handler to them.
+template <typename FunctionTy>
+static void iterateOnSegments(const object::MachOObjectFile &Obj,
+ FunctionTy Handler) {
+ for (const auto &LCI : Obj.load_commands()) {
+ MachO::segment_command_64 Segment;
+ if (LCI.C.cmd == MachO::LC_SEGMENT)
+ Segment = adaptFrom32bits(Obj.getSegmentLoadCommand(LCI));
+ else if (LCI.C.cmd == MachO::LC_SEGMENT_64)
+ Segment = Obj.getSegment64LoadCommand(LCI);
+ else
+ continue;
+
+ Handler(Segment);
+ }
+}
+
+// Transfer the symbols described by \a NList to \a NewSymtab which is just the
+// raw contents of the symbol table for the dSYM companion file. \returns
+// whether the symbol was transferred or not.
+template <typename NListTy>
+static bool transferSymbol(NListTy NList, bool IsLittleEndian,
+ StringRef Strings, SmallVectorImpl<char> &NewSymtab,
+ NonRelocatableStringpool &NewStrings,
+ bool &InDebugNote) {
+ // Do not transfer undefined symbols, we want real addresses.
+ if ((NList.n_type & MachO::N_TYPE) == MachO::N_UNDF)
+ return false;
+
+ // Do not transfer N_AST symbols as their content is copied into a section of
+ // the Mach-O companion file.
+ if (NList.n_type == MachO::N_AST)
+ return false;
+
+ StringRef Name = StringRef(Strings.begin() + NList.n_strx);
+
+ // An N_SO with a filename opens a debugging scope and another one without a
+ // name closes it. Don't transfer anything in the debugging scope.
+ if (InDebugNote) {
+ InDebugNote =
+ (NList.n_type != MachO::N_SO) || (!Name.empty() && Name[0] != '\0');
+ return false;
+ } else if (NList.n_type == MachO::N_SO) {
+ InDebugNote = true;
+ return false;
+ }
+
+ // FIXME: The + 1 is here to mimic dsymutil-classic that has 2 empty
+ // strings at the start of the generated string table (There is
+ // corresponding code in the string table emission).
+ NList.n_strx = NewStrings.getStringOffset(Name) + 1;
+ if (IsLittleEndian != sys::IsLittleEndianHost)
+ MachO::swapStruct(NList);
+
+ NewSymtab.append(reinterpret_cast<char *>(&NList),
+ reinterpret_cast<char *>(&NList + 1));
+ return true;
+}
+
+// Wrapper around transferSymbol to transfer all of \a Obj symbols
+// to \a NewSymtab. This function does not write in the output file.
+// \returns the number of symbols in \a NewSymtab.
+static unsigned transferSymbols(const object::MachOObjectFile &Obj,
+ SmallVectorImpl<char> &NewSymtab,
+ NonRelocatableStringpool &NewStrings) {
+ unsigned Syms = 0;
+ StringRef Strings = Obj.getStringTableData();
+ bool IsLittleEndian = Obj.isLittleEndian();
+ bool InDebugNote = false;
+
+ if (Obj.is64Bit()) {
+ for (const object::SymbolRef &Symbol : Obj.symbols()) {
+ object::DataRefImpl DRI = Symbol.getRawDataRefImpl();
+ if (transferSymbol(Obj.getSymbol64TableEntry(DRI), IsLittleEndian,
+ Strings, NewSymtab, NewStrings, InDebugNote))
+ ++Syms;
+ }
+ } else {
+ for (const object::SymbolRef &Symbol : Obj.symbols()) {
+ object::DataRefImpl DRI = Symbol.getRawDataRefImpl();
+ if (transferSymbol(Obj.getSymbolTableEntry(DRI), IsLittleEndian, Strings,
+ NewSymtab, NewStrings, InDebugNote))
+ ++Syms;
+ }
+ }
+ return Syms;
+}
+
+static MachO::section
+getSection(const object::MachOObjectFile &Obj,
+ const MachO::segment_command &Seg,
+ const object::MachOObjectFile::LoadCommandInfo &LCI, unsigned Idx) {
+ return Obj.getSection(LCI, Idx);
+}
+
+static MachO::section_64
+getSection(const object::MachOObjectFile &Obj,
+ const MachO::segment_command_64 &Seg,
+ const object::MachOObjectFile::LoadCommandInfo &LCI, unsigned Idx) {
+ return Obj.getSection64(LCI, Idx);
+}
+
+// Transfer \a Segment from \a Obj to the output file. This calls into \a Writer
+// to write these load commands directly in the output file at the current
+// position.
//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+// The function also tries to find a hole in the address map to fit the __DWARF
+// segment of \a DwarfSegmentSize size. \a EndAddress is updated to point at the
+// highest segment address.
//
-//===----------------------------------------------------------------------===//
-
-#include "MachOUtils.h"
-#include "BinaryHolder.h"
-#include "DebugMap.h"
-#include "LinkUtils.h"
-#include "llvm/CodeGen/NonRelocatableStringpool.h"
-#include "llvm/MC/MCAsmLayout.h"
-#include "llvm/MC/MCMachObjectWriter.h"
-#include "llvm/MC/MCObjectStreamer.h"
-#include "llvm/MC/MCSectionMachO.h"
-#include "llvm/MC/MCStreamer.h"
-#include "llvm/Object/MachO.h"
-#include "llvm/Support/FileUtilities.h"
-#include "llvm/Support/Program.h"
-#include "llvm/Support/WithColor.h"
-#include "llvm/Support/raw_ostream.h"
-
-namespace llvm {
-namespace dsymutil {
-namespace MachOUtils {
-
-llvm::Error ArchAndFile::createTempFile() {
- llvm::SmallString<128> TmpModel;
- llvm::sys::path::system_temp_directory(true, TmpModel);
- llvm::sys::path::append(TmpModel, "dsym.tmp%%%%%.dwarf");
- Expected<sys::fs::TempFile> T = sys::fs::TempFile::create(TmpModel);
-
- if (!T)
- return T.takeError();
-
- File = std::make_unique<sys::fs::TempFile>(std::move(*T));
- return Error::success();
-}
-
-llvm::StringRef ArchAndFile::path() const { return File->TmpName; }
-
-ArchAndFile::~ArchAndFile() {
- if (File)
- if (auto E = File->discard())
- llvm::consumeError(std::move(E));
-}
-
-std::string getArchName(StringRef Arch) {
- if (Arch.startswith("thumb"))
- return (llvm::Twine("arm") + Arch.drop_front(5)).str();
- return std::string(Arch);
-}
-
-static bool runLipo(StringRef SDKPath, SmallVectorImpl<StringRef> &Args) {
- auto Path = sys::findProgramByName("lipo", makeArrayRef(SDKPath));
- if (!Path)
- Path = sys::findProgramByName("lipo");
-
- if (!Path) {
- WithColor::error() << "lipo: " << Path.getError().message() << "\n";
- return false;
- }
-
- std::string ErrMsg;
- int result = sys::ExecuteAndWait(*Path, Args, None, {}, 0, 0, &ErrMsg);
- if (result) {
- WithColor::error() << "lipo: " << ErrMsg << "\n";
- return false;
- }
-
- return true;
-}
-
-bool generateUniversalBinary(SmallVectorImpl<ArchAndFile> &ArchFiles,
- StringRef OutputFileName,
- const LinkOptions &Options, StringRef SDKPath) {
- // No need to merge one file into a universal fat binary.
- if (ArchFiles.size() == 1) {
- if (auto E = ArchFiles.front().File->keep(OutputFileName)) {
- WithColor::error() << "while keeping " << ArchFiles.front().path()
- << " as " << OutputFileName << ": "
- << toString(std::move(E)) << "\n";
- return false;
- }
- return true;
- }
-
- SmallVector<StringRef, 8> Args;
- Args.push_back("lipo");
- Args.push_back("-create");
-
- for (auto &Thin : ArchFiles)
- Args.push_back(Thin.path());
-
- // Align segments to match dsymutil-classic alignment
- for (auto &Thin : ArchFiles) {
- Thin.Arch = getArchName(Thin.Arch);
- Args.push_back("-segalign");
- Args.push_back(Thin.Arch);
- Args.push_back("20");
- }
-
- Args.push_back("-output");
- Args.push_back(OutputFileName.data());
-
- if (Options.Verbose) {
- outs() << "Running lipo\n";
- for (auto Arg : Args)
- outs() << ' ' << Arg;
- outs() << "\n";
- }
-
- return Options.NoOutput ? true : runLipo(SDKPath, Args);
-}
-
-// Return a MachO::segment_command_64 that holds the same values as the passed
-// MachO::segment_command. We do that to avoid having to duplicate the logic
-// for 32bits and 64bits segments.
-struct MachO::segment_command_64 adaptFrom32bits(MachO::segment_command Seg) {
- MachO::segment_command_64 Seg64;
- Seg64.cmd = Seg.cmd;
- Seg64.cmdsize = Seg.cmdsize;
- memcpy(Seg64.segname, Seg.segname, sizeof(Seg.segname));
- Seg64.vmaddr = Seg.vmaddr;
- Seg64.vmsize = Seg.vmsize;
- Seg64.fileoff = Seg.fileoff;
- Seg64.filesize = Seg.filesize;
- Seg64.maxprot = Seg.maxprot;
- Seg64.initprot = Seg.initprot;
- Seg64.nsects = Seg.nsects;
- Seg64.flags = Seg.flags;
- return Seg64;
-}
-
-// Iterate on all \a Obj segments, and apply \a Handler to them.
-template <typename FunctionTy>
-static void iterateOnSegments(const object::MachOObjectFile &Obj,
- FunctionTy Handler) {
- for (const auto &LCI : Obj.load_commands()) {
- MachO::segment_command_64 Segment;
- if (LCI.C.cmd == MachO::LC_SEGMENT)
- Segment = adaptFrom32bits(Obj.getSegmentLoadCommand(LCI));
- else if (LCI.C.cmd == MachO::LC_SEGMENT_64)
- Segment = Obj.getSegment64LoadCommand(LCI);
- else
- continue;
-
- Handler(Segment);
- }
-}
-
-// Transfer the symbols described by \a NList to \a NewSymtab which is just the
-// raw contents of the symbol table for the dSYM companion file. \returns
-// whether the symbol was transferred or not.
-template <typename NListTy>
-static bool transferSymbol(NListTy NList, bool IsLittleEndian,
- StringRef Strings, SmallVectorImpl<char> &NewSymtab,
- NonRelocatableStringpool &NewStrings,
- bool &InDebugNote) {
- // Do not transfer undefined symbols, we want real addresses.
- if ((NList.n_type & MachO::N_TYPE) == MachO::N_UNDF)
- return false;
-
- // Do not transfer N_AST symbols as their content is copied into a section of
- // the Mach-O companion file.
- if (NList.n_type == MachO::N_AST)
- return false;
-
- StringRef Name = StringRef(Strings.begin() + NList.n_strx);
-
- // An N_SO with a filename opens a debugging scope and another one without a
- // name closes it. Don't transfer anything in the debugging scope.
- if (InDebugNote) {
- InDebugNote =
- (NList.n_type != MachO::N_SO) || (!Name.empty() && Name[0] != '\0');
- return false;
- } else if (NList.n_type == MachO::N_SO) {
- InDebugNote = true;
- return false;
- }
-
- // FIXME: The + 1 is here to mimic dsymutil-classic that has 2 empty
- // strings at the start of the generated string table (There is
- // corresponding code in the string table emission).
- NList.n_strx = NewStrings.getStringOffset(Name) + 1;
- if (IsLittleEndian != sys::IsLittleEndianHost)
- MachO::swapStruct(NList);
-
- NewSymtab.append(reinterpret_cast<char *>(&NList),
- reinterpret_cast<char *>(&NList + 1));
- return true;
-}
-
-// Wrapper around transferSymbol to transfer all of \a Obj symbols
-// to \a NewSymtab. This function does not write in the output file.
-// \returns the number of symbols in \a NewSymtab.
-static unsigned transferSymbols(const object::MachOObjectFile &Obj,
- SmallVectorImpl<char> &NewSymtab,
- NonRelocatableStringpool &NewStrings) {
- unsigned Syms = 0;
- StringRef Strings = Obj.getStringTableData();
- bool IsLittleEndian = Obj.isLittleEndian();
- bool InDebugNote = false;
-
- if (Obj.is64Bit()) {
- for (const object::SymbolRef &Symbol : Obj.symbols()) {
- object::DataRefImpl DRI = Symbol.getRawDataRefImpl();
- if (transferSymbol(Obj.getSymbol64TableEntry(DRI), IsLittleEndian,
- Strings, NewSymtab, NewStrings, InDebugNote))
- ++Syms;
- }
- } else {
- for (const object::SymbolRef &Symbol : Obj.symbols()) {
- object::DataRefImpl DRI = Symbol.getRawDataRefImpl();
- if (transferSymbol(Obj.getSymbolTableEntry(DRI), IsLittleEndian, Strings,
- NewSymtab, NewStrings, InDebugNote))
- ++Syms;
- }
- }
- return Syms;
-}
-
-static MachO::section
-getSection(const object::MachOObjectFile &Obj,
- const MachO::segment_command &Seg,
- const object::MachOObjectFile::LoadCommandInfo &LCI, unsigned Idx) {
- return Obj.getSection(LCI, Idx);
-}
-
-static MachO::section_64
-getSection(const object::MachOObjectFile &Obj,
- const MachO::segment_command_64 &Seg,
- const object::MachOObjectFile::LoadCommandInfo &LCI, unsigned Idx) {
- return Obj.getSection64(LCI, Idx);
-}
-
-// Transfer \a Segment from \a Obj to the output file. This calls into \a Writer
-// to write these load commands directly in the output file at the current
-// position.
-//
-// The function also tries to find a hole in the address map to fit the __DWARF
-// segment of \a DwarfSegmentSize size. \a EndAddress is updated to point at the
-// highest segment address.
-//
-// When the __LINKEDIT segment is transferred, its offset and size are set resp.
-// to \a LinkeditOffset and \a LinkeditSize.
+// When the __LINKEDIT segment is transferred, its offset and size are set resp.
+// to \a LinkeditOffset and \a LinkeditSize.
//
// When the eh_frame section is transferred, its offset and size are set resp.
// to \a EHFrameOffset and \a EHFrameSize.
-template <typename SegmentTy>
-static void transferSegmentAndSections(
- const object::MachOObjectFile::LoadCommandInfo &LCI, SegmentTy Segment,
- const object::MachOObjectFile &Obj, MachObjectWriter &Writer,
+template <typename SegmentTy>
+static void transferSegmentAndSections(
+ const object::MachOObjectFile::LoadCommandInfo &LCI, SegmentTy Segment,
+ const object::MachOObjectFile &Obj, MachObjectWriter &Writer,
uint64_t LinkeditOffset, uint64_t LinkeditSize, uint64_t EHFrameOffset,
uint64_t EHFrameSize, uint64_t DwarfSegmentSize, uint64_t &GapForDwarf,
uint64_t &EndAddress) {
- if (StringRef("__DWARF") == Segment.segname)
- return;
-
+ if (StringRef("__DWARF") == Segment.segname)
+ return;
+
if (StringRef("__TEXT") == Segment.segname && EHFrameSize > 0) {
Segment.fileoff = EHFrameOffset;
Segment.filesize = EHFrameSize;
} else if (StringRef("__LINKEDIT") == Segment.segname) {
- Segment.fileoff = LinkeditOffset;
- Segment.filesize = LinkeditSize;
- // Resize vmsize by rounding to the page size.
- Segment.vmsize = alignTo(LinkeditSize, 0x1000);
+ Segment.fileoff = LinkeditOffset;
+ Segment.filesize = LinkeditSize;
+ // Resize vmsize by rounding to the page size.
+ Segment.vmsize = alignTo(LinkeditSize, 0x1000);
} else {
Segment.fileoff = Segment.filesize = 0;
- }
-
- // Check if the end address of the last segment and our current
- // start address leave a sufficient gap to store the __DWARF
- // segment.
- uint64_t PrevEndAddress = EndAddress;
- EndAddress = alignTo(EndAddress, 0x1000);
- if (GapForDwarf == UINT64_MAX && Segment.vmaddr > EndAddress &&
- Segment.vmaddr - EndAddress >= DwarfSegmentSize)
- GapForDwarf = EndAddress;
-
- // The segments are not necessarily sorted by their vmaddr.
- EndAddress =
- std::max<uint64_t>(PrevEndAddress, Segment.vmaddr + Segment.vmsize);
- unsigned nsects = Segment.nsects;
- if (Obj.isLittleEndian() != sys::IsLittleEndianHost)
- MachO::swapStruct(Segment);
- Writer.W.OS.write(reinterpret_cast<char *>(&Segment), sizeof(Segment));
- for (unsigned i = 0; i < nsects; ++i) {
- auto Sect = getSection(Obj, Segment, LCI, i);
+ }
+
+ // Check if the end address of the last segment and our current
+ // start address leave a sufficient gap to store the __DWARF
+ // segment.
+ uint64_t PrevEndAddress = EndAddress;
+ EndAddress = alignTo(EndAddress, 0x1000);
+ if (GapForDwarf == UINT64_MAX && Segment.vmaddr > EndAddress &&
+ Segment.vmaddr - EndAddress >= DwarfSegmentSize)
+ GapForDwarf = EndAddress;
+
+ // The segments are not necessarily sorted by their vmaddr.
+ EndAddress =
+ std::max<uint64_t>(PrevEndAddress, Segment.vmaddr + Segment.vmsize);
+ unsigned nsects = Segment.nsects;
+ if (Obj.isLittleEndian() != sys::IsLittleEndianHost)
+ MachO::swapStruct(Segment);
+ Writer.W.OS.write(reinterpret_cast<char *>(&Segment), sizeof(Segment));
+ for (unsigned i = 0; i < nsects; ++i) {
+ auto Sect = getSection(Obj, Segment, LCI, i);
if (StringRef("__eh_frame") == Sect.sectname) {
Sect.offset = EHFrameOffset;
Sect.reloff = Sect.nreloc = 0;
} else {
Sect.offset = Sect.reloff = Sect.nreloc = 0;
}
- if (Obj.isLittleEndian() != sys::IsLittleEndianHost)
- MachO::swapStruct(Sect);
- Writer.W.OS.write(reinterpret_cast<char *>(&Sect), sizeof(Sect));
- }
-}
-
-// Write the __DWARF segment load command to the output file.
-static void createDwarfSegment(uint64_t VMAddr, uint64_t FileOffset,
- uint64_t FileSize, unsigned NumSections,
- MCAsmLayout &Layout, MachObjectWriter &Writer) {
- Writer.writeSegmentLoadCommand("__DWARF", NumSections, VMAddr,
- alignTo(FileSize, 0x1000), FileOffset,
- FileSize, /* MaxProt */ 7,
- /* InitProt =*/3);
-
- for (unsigned int i = 0, n = Layout.getSectionOrder().size(); i != n; ++i) {
- MCSection *Sec = Layout.getSectionOrder()[i];
- if (Sec->begin() == Sec->end() || !Layout.getSectionFileSize(Sec))
- continue;
-
- unsigned Align = Sec->getAlignment();
- if (Align > 1) {
- VMAddr = alignTo(VMAddr, Align);
- FileOffset = alignTo(FileOffset, Align);
- }
- Writer.writeSection(Layout, *Sec, VMAddr, FileOffset, 0, 0, 0);
-
- FileOffset += Layout.getSectionAddressSize(Sec);
- VMAddr += Layout.getSectionAddressSize(Sec);
- }
-}
-
-static bool isExecutable(const object::MachOObjectFile &Obj) {
- if (Obj.is64Bit())
- return Obj.getHeader64().filetype != MachO::MH_OBJECT;
- else
- return Obj.getHeader().filetype != MachO::MH_OBJECT;
-}
-
-static bool hasLinkEditSegment(const object::MachOObjectFile &Obj) {
- bool HasLinkEditSegment = false;
- iterateOnSegments(Obj, [&](const MachO::segment_command_64 &Segment) {
- if (StringRef("__LINKEDIT") == Segment.segname)
- HasLinkEditSegment = true;
- });
- return HasLinkEditSegment;
-}
-
-static unsigned segmentLoadCommandSize(bool Is64Bit, unsigned NumSections) {
- if (Is64Bit)
- return sizeof(MachO::segment_command_64) +
- NumSections * sizeof(MachO::section_64);
-
- return sizeof(MachO::segment_command) + NumSections * sizeof(MachO::section);
-}
-
-// Stream a dSYM companion binary file corresponding to the binary referenced
-// by \a DM to \a OutFile. The passed \a MS MCStreamer is setup to write to
-// \a OutFile and it must be using a MachObjectWriter object to do so.
-bool generateDsymCompanion(llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS,
- const DebugMap &DM, SymbolMapTranslator &Translator,
- MCStreamer &MS, raw_fd_ostream &OutFile) {
- auto &ObjectStreamer = static_cast<MCObjectStreamer &>(MS);
- MCAssembler &MCAsm = ObjectStreamer.getAssembler();
- auto &Writer = static_cast<MachObjectWriter &>(MCAsm.getWriter());
-
- // Layout but don't emit.
- ObjectStreamer.flushPendingLabels();
- MCAsmLayout Layout(MCAsm);
- MCAsm.layout(Layout);
-
- BinaryHolder InputBinaryHolder(VFS, false);
-
- auto ObjectEntry = InputBinaryHolder.getObjectEntry(DM.getBinaryPath());
- if (!ObjectEntry) {
- auto Err = ObjectEntry.takeError();
- return error(Twine("opening ") + DM.getBinaryPath() + ": " +
- toString(std::move(Err)),
- "output file streaming");
- }
-
- auto Object =
- ObjectEntry->getObjectAs<object::MachOObjectFile>(DM.getTriple());
- if (!Object) {
- auto Err = Object.takeError();
- return error(Twine("opening ") + DM.getBinaryPath() + ": " +
- toString(std::move(Err)),
- "output file streaming");
- }
-
- auto &InputBinary = *Object;
-
- bool Is64Bit = Writer.is64Bit();
- MachO::symtab_command SymtabCmd = InputBinary.getSymtabLoadCommand();
-
- // Compute the number of load commands we will need.
- unsigned LoadCommandSize = 0;
- unsigned NumLoadCommands = 0;
-
- // Get LC_UUID and LC_BUILD_VERSION.
- MachO::uuid_command UUIDCmd;
- SmallVector<MachO::build_version_command, 2> BuildVersionCmd;
- memset(&UUIDCmd, 0, sizeof(UUIDCmd));
- for (auto &LCI : InputBinary.load_commands()) {
- switch (LCI.C.cmd) {
- case MachO::LC_UUID:
- if (UUIDCmd.cmd)
- return error("Binary contains more than one UUID");
- UUIDCmd = InputBinary.getUuidCommand(LCI);
- ++NumLoadCommands;
- LoadCommandSize += sizeof(UUIDCmd);
- break;
- case MachO::LC_BUILD_VERSION: {
- MachO::build_version_command Cmd;
- memset(&Cmd, 0, sizeof(Cmd));
- Cmd = InputBinary.getBuildVersionLoadCommand(LCI);
- ++NumLoadCommands;
- LoadCommandSize += sizeof(Cmd);
- // LLDB doesn't care about the build tools for now.
- Cmd.ntools = 0;
- BuildVersionCmd.push_back(Cmd);
- break;
- }
- default:
- break;
- }
- }
-
- // If we have a valid symtab to copy, do it.
- bool ShouldEmitSymtab =
- isExecutable(InputBinary) && hasLinkEditSegment(InputBinary);
- if (ShouldEmitSymtab) {
- LoadCommandSize += sizeof(MachO::symtab_command);
- ++NumLoadCommands;
- }
-
+ if (Obj.isLittleEndian() != sys::IsLittleEndianHost)
+ MachO::swapStruct(Sect);
+ Writer.W.OS.write(reinterpret_cast<char *>(&Sect), sizeof(Sect));
+ }
+}
+
+// Write the __DWARF segment load command to the output file.
+static void createDwarfSegment(uint64_t VMAddr, uint64_t FileOffset,
+ uint64_t FileSize, unsigned NumSections,
+ MCAsmLayout &Layout, MachObjectWriter &Writer) {
+ Writer.writeSegmentLoadCommand("__DWARF", NumSections, VMAddr,
+ alignTo(FileSize, 0x1000), FileOffset,
+ FileSize, /* MaxProt */ 7,
+ /* InitProt =*/3);
+
+ for (unsigned int i = 0, n = Layout.getSectionOrder().size(); i != n; ++i) {
+ MCSection *Sec = Layout.getSectionOrder()[i];
+ if (Sec->begin() == Sec->end() || !Layout.getSectionFileSize(Sec))
+ continue;
+
+ unsigned Align = Sec->getAlignment();
+ if (Align > 1) {
+ VMAddr = alignTo(VMAddr, Align);
+ FileOffset = alignTo(FileOffset, Align);
+ }
+ Writer.writeSection(Layout, *Sec, VMAddr, FileOffset, 0, 0, 0);
+
+ FileOffset += Layout.getSectionAddressSize(Sec);
+ VMAddr += Layout.getSectionAddressSize(Sec);
+ }
+}
+
+static bool isExecutable(const object::MachOObjectFile &Obj) {
+ if (Obj.is64Bit())
+ return Obj.getHeader64().filetype != MachO::MH_OBJECT;
+ else
+ return Obj.getHeader().filetype != MachO::MH_OBJECT;
+}
+
+static bool hasLinkEditSegment(const object::MachOObjectFile &Obj) {
+ bool HasLinkEditSegment = false;
+ iterateOnSegments(Obj, [&](const MachO::segment_command_64 &Segment) {
+ if (StringRef("__LINKEDIT") == Segment.segname)
+ HasLinkEditSegment = true;
+ });
+ return HasLinkEditSegment;
+}
+
+static unsigned segmentLoadCommandSize(bool Is64Bit, unsigned NumSections) {
+ if (Is64Bit)
+ return sizeof(MachO::segment_command_64) +
+ NumSections * sizeof(MachO::section_64);
+
+ return sizeof(MachO::segment_command) + NumSections * sizeof(MachO::section);
+}
+
+// Stream a dSYM companion binary file corresponding to the binary referenced
+// by \a DM to \a OutFile. The passed \a MS MCStreamer is setup to write to
+// \a OutFile and it must be using a MachObjectWriter object to do so.
+bool generateDsymCompanion(llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS,
+ const DebugMap &DM, SymbolMapTranslator &Translator,
+ MCStreamer &MS, raw_fd_ostream &OutFile) {
+ auto &ObjectStreamer = static_cast<MCObjectStreamer &>(MS);
+ MCAssembler &MCAsm = ObjectStreamer.getAssembler();
+ auto &Writer = static_cast<MachObjectWriter &>(MCAsm.getWriter());
+
+ // Layout but don't emit.
+ ObjectStreamer.flushPendingLabels();
+ MCAsmLayout Layout(MCAsm);
+ MCAsm.layout(Layout);
+
+ BinaryHolder InputBinaryHolder(VFS, false);
+
+ auto ObjectEntry = InputBinaryHolder.getObjectEntry(DM.getBinaryPath());
+ if (!ObjectEntry) {
+ auto Err = ObjectEntry.takeError();
+ return error(Twine("opening ") + DM.getBinaryPath() + ": " +
+ toString(std::move(Err)),
+ "output file streaming");
+ }
+
+ auto Object =
+ ObjectEntry->getObjectAs<object::MachOObjectFile>(DM.getTriple());
+ if (!Object) {
+ auto Err = Object.takeError();
+ return error(Twine("opening ") + DM.getBinaryPath() + ": " +
+ toString(std::move(Err)),
+ "output file streaming");
+ }
+
+ auto &InputBinary = *Object;
+
+ bool Is64Bit = Writer.is64Bit();
+ MachO::symtab_command SymtabCmd = InputBinary.getSymtabLoadCommand();
+
+ // Compute the number of load commands we will need.
+ unsigned LoadCommandSize = 0;
+ unsigned NumLoadCommands = 0;
+
+ // Get LC_UUID and LC_BUILD_VERSION.
+ MachO::uuid_command UUIDCmd;
+ SmallVector<MachO::build_version_command, 2> BuildVersionCmd;
+ memset(&UUIDCmd, 0, sizeof(UUIDCmd));
+ for (auto &LCI : InputBinary.load_commands()) {
+ switch (LCI.C.cmd) {
+ case MachO::LC_UUID:
+ if (UUIDCmd.cmd)
+ return error("Binary contains more than one UUID");
+ UUIDCmd = InputBinary.getUuidCommand(LCI);
+ ++NumLoadCommands;
+ LoadCommandSize += sizeof(UUIDCmd);
+ break;
+ case MachO::LC_BUILD_VERSION: {
+ MachO::build_version_command Cmd;
+ memset(&Cmd, 0, sizeof(Cmd));
+ Cmd = InputBinary.getBuildVersionLoadCommand(LCI);
+ ++NumLoadCommands;
+ LoadCommandSize += sizeof(Cmd);
+ // LLDB doesn't care about the build tools for now.
+ Cmd.ntools = 0;
+ BuildVersionCmd.push_back(Cmd);
+ break;
+ }
+ default:
+ break;
+ }
+ }
+
+ // If we have a valid symtab to copy, do it.
+ bool ShouldEmitSymtab =
+ isExecutable(InputBinary) && hasLinkEditSegment(InputBinary);
+ if (ShouldEmitSymtab) {
+ LoadCommandSize += sizeof(MachO::symtab_command);
+ ++NumLoadCommands;
+ }
+
// If we have a valid eh_frame to copy, do it.
uint64_t EHFrameSize = 0;
StringRef EHFrameData;
@@ -452,148 +452,148 @@ bool generateDsymCompanion(llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS,
}
}
- unsigned HeaderSize =
- Is64Bit ? sizeof(MachO::mach_header_64) : sizeof(MachO::mach_header);
- // We will copy every segment that isn't __DWARF.
- iterateOnSegments(InputBinary, [&](const MachO::segment_command_64 &Segment) {
- if (StringRef("__DWARF") == Segment.segname)
- return;
-
- ++NumLoadCommands;
- LoadCommandSize += segmentLoadCommandSize(Is64Bit, Segment.nsects);
- });
-
- // We will add our own brand new __DWARF segment if we have debug
- // info.
- unsigned NumDwarfSections = 0;
- uint64_t DwarfSegmentSize = 0;
-
- for (unsigned int i = 0, n = Layout.getSectionOrder().size(); i != n; ++i) {
- MCSection *Sec = Layout.getSectionOrder()[i];
- if (Sec->begin() == Sec->end())
- continue;
-
- if (uint64_t Size = Layout.getSectionFileSize(Sec)) {
- DwarfSegmentSize = alignTo(DwarfSegmentSize, Sec->getAlignment());
- DwarfSegmentSize += Size;
- ++NumDwarfSections;
- }
- }
-
- if (NumDwarfSections) {
- ++NumLoadCommands;
- LoadCommandSize += segmentLoadCommandSize(Is64Bit, NumDwarfSections);
- }
-
- SmallString<0> NewSymtab;
- std::function<StringRef(StringRef)> TranslationLambda =
- Translator ? [&](StringRef Input) { return Translator(Input); }
- : static_cast<std::function<StringRef(StringRef)>>(nullptr);
- // Legacy dsymutil puts an empty string at the start of the line table.
- // thus we set NonRelocatableStringpool(,PutEmptyString=true)
- NonRelocatableStringpool NewStrings(TranslationLambda, true);
- unsigned NListSize = Is64Bit ? sizeof(MachO::nlist_64) : sizeof(MachO::nlist);
- unsigned NumSyms = 0;
- uint64_t NewStringsSize = 0;
- if (ShouldEmitSymtab) {
- NewSymtab.reserve(SymtabCmd.nsyms * NListSize / 2);
- NumSyms = transferSymbols(InputBinary, NewSymtab, NewStrings);
- NewStringsSize = NewStrings.getSize() + 1;
- }
-
- uint64_t SymtabStart = LoadCommandSize;
- SymtabStart += HeaderSize;
- SymtabStart = alignTo(SymtabStart, 0x1000);
-
- // We gathered all the information we need, start emitting the output file.
- Writer.writeHeader(MachO::MH_DSYM, NumLoadCommands, LoadCommandSize, false);
-
- // Write the load commands.
- assert(OutFile.tell() == HeaderSize);
- if (UUIDCmd.cmd != 0) {
- Writer.W.write<uint32_t>(UUIDCmd.cmd);
- Writer.W.write<uint32_t>(sizeof(UUIDCmd));
- OutFile.write(reinterpret_cast<const char *>(UUIDCmd.uuid), 16);
- assert(OutFile.tell() == HeaderSize + sizeof(UUIDCmd));
- }
- for (auto Cmd : BuildVersionCmd) {
- Writer.W.write<uint32_t>(Cmd.cmd);
- Writer.W.write<uint32_t>(sizeof(Cmd));
- Writer.W.write<uint32_t>(Cmd.platform);
- Writer.W.write<uint32_t>(Cmd.minos);
- Writer.W.write<uint32_t>(Cmd.sdk);
- Writer.W.write<uint32_t>(Cmd.ntools);
- }
-
- assert(SymtabCmd.cmd && "No symbol table.");
- uint64_t StringStart = SymtabStart + NumSyms * NListSize;
- if (ShouldEmitSymtab)
- Writer.writeSymtabLoadCommand(SymtabStart, NumSyms, StringStart,
- NewStringsSize);
-
+ unsigned HeaderSize =
+ Is64Bit ? sizeof(MachO::mach_header_64) : sizeof(MachO::mach_header);
+ // We will copy every segment that isn't __DWARF.
+ iterateOnSegments(InputBinary, [&](const MachO::segment_command_64 &Segment) {
+ if (StringRef("__DWARF") == Segment.segname)
+ return;
+
+ ++NumLoadCommands;
+ LoadCommandSize += segmentLoadCommandSize(Is64Bit, Segment.nsects);
+ });
+
+ // We will add our own brand new __DWARF segment if we have debug
+ // info.
+ unsigned NumDwarfSections = 0;
+ uint64_t DwarfSegmentSize = 0;
+
+ for (unsigned int i = 0, n = Layout.getSectionOrder().size(); i != n; ++i) {
+ MCSection *Sec = Layout.getSectionOrder()[i];
+ if (Sec->begin() == Sec->end())
+ continue;
+
+ if (uint64_t Size = Layout.getSectionFileSize(Sec)) {
+ DwarfSegmentSize = alignTo(DwarfSegmentSize, Sec->getAlignment());
+ DwarfSegmentSize += Size;
+ ++NumDwarfSections;
+ }
+ }
+
+ if (NumDwarfSections) {
+ ++NumLoadCommands;
+ LoadCommandSize += segmentLoadCommandSize(Is64Bit, NumDwarfSections);
+ }
+
+ SmallString<0> NewSymtab;
+ std::function<StringRef(StringRef)> TranslationLambda =
+ Translator ? [&](StringRef Input) { return Translator(Input); }
+ : static_cast<std::function<StringRef(StringRef)>>(nullptr);
+ // Legacy dsymutil puts an empty string at the start of the line table.
+ // thus we set NonRelocatableStringpool(,PutEmptyString=true)
+ NonRelocatableStringpool NewStrings(TranslationLambda, true);
+ unsigned NListSize = Is64Bit ? sizeof(MachO::nlist_64) : sizeof(MachO::nlist);
+ unsigned NumSyms = 0;
+ uint64_t NewStringsSize = 0;
+ if (ShouldEmitSymtab) {
+ NewSymtab.reserve(SymtabCmd.nsyms * NListSize / 2);
+ NumSyms = transferSymbols(InputBinary, NewSymtab, NewStrings);
+ NewStringsSize = NewStrings.getSize() + 1;
+ }
+
+ uint64_t SymtabStart = LoadCommandSize;
+ SymtabStart += HeaderSize;
+ SymtabStart = alignTo(SymtabStart, 0x1000);
+
+ // We gathered all the information we need, start emitting the output file.
+ Writer.writeHeader(MachO::MH_DSYM, NumLoadCommands, LoadCommandSize, false);
+
+ // Write the load commands.
+ assert(OutFile.tell() == HeaderSize);
+ if (UUIDCmd.cmd != 0) {
+ Writer.W.write<uint32_t>(UUIDCmd.cmd);
+ Writer.W.write<uint32_t>(sizeof(UUIDCmd));
+ OutFile.write(reinterpret_cast<const char *>(UUIDCmd.uuid), 16);
+ assert(OutFile.tell() == HeaderSize + sizeof(UUIDCmd));
+ }
+ for (auto Cmd : BuildVersionCmd) {
+ Writer.W.write<uint32_t>(Cmd.cmd);
+ Writer.W.write<uint32_t>(sizeof(Cmd));
+ Writer.W.write<uint32_t>(Cmd.platform);
+ Writer.W.write<uint32_t>(Cmd.minos);
+ Writer.W.write<uint32_t>(Cmd.sdk);
+ Writer.W.write<uint32_t>(Cmd.ntools);
+ }
+
+ assert(SymtabCmd.cmd && "No symbol table.");
+ uint64_t StringStart = SymtabStart + NumSyms * NListSize;
+ if (ShouldEmitSymtab)
+ Writer.writeSymtabLoadCommand(SymtabStart, NumSyms, StringStart,
+ NewStringsSize);
+
uint64_t EHFrameStart = StringStart + NewStringsSize;
EHFrameStart = alignTo(EHFrameStart, 0x1000);
uint64_t DwarfSegmentStart = EHFrameStart + EHFrameSize;
- DwarfSegmentStart = alignTo(DwarfSegmentStart, 0x1000);
-
- // Write the load commands for the segments and sections we 'import' from
- // the original binary.
- uint64_t EndAddress = 0;
- uint64_t GapForDwarf = UINT64_MAX;
- for (auto &LCI : InputBinary.load_commands()) {
- if (LCI.C.cmd == MachO::LC_SEGMENT)
+ DwarfSegmentStart = alignTo(DwarfSegmentStart, 0x1000);
+
+ // Write the load commands for the segments and sections we 'import' from
+ // the original binary.
+ uint64_t EndAddress = 0;
+ uint64_t GapForDwarf = UINT64_MAX;
+ for (auto &LCI : InputBinary.load_commands()) {
+ if (LCI.C.cmd == MachO::LC_SEGMENT)
transferSegmentAndSections(
LCI, InputBinary.getSegmentLoadCommand(LCI), InputBinary, Writer,
SymtabStart, StringStart + NewStringsSize - SymtabStart, EHFrameStart,
EHFrameSize, DwarfSegmentSize, GapForDwarf, EndAddress);
- else if (LCI.C.cmd == MachO::LC_SEGMENT_64)
+ else if (LCI.C.cmd == MachO::LC_SEGMENT_64)
transferSegmentAndSections(
LCI, InputBinary.getSegment64LoadCommand(LCI), InputBinary, Writer,
SymtabStart, StringStart + NewStringsSize - SymtabStart, EHFrameStart,
EHFrameSize, DwarfSegmentSize, GapForDwarf, EndAddress);
- }
-
- uint64_t DwarfVMAddr = alignTo(EndAddress, 0x1000);
- uint64_t DwarfVMMax = Is64Bit ? UINT64_MAX : UINT32_MAX;
- if (DwarfVMAddr + DwarfSegmentSize > DwarfVMMax ||
- DwarfVMAddr + DwarfSegmentSize < DwarfVMAddr /* Overflow */) {
- // There is no room for the __DWARF segment at the end of the
- // address space. Look through segments to find a gap.
- DwarfVMAddr = GapForDwarf;
- if (DwarfVMAddr == UINT64_MAX)
- warn("not enough VM space for the __DWARF segment.",
- "output file streaming");
- }
-
- // Write the load command for the __DWARF segment.
- createDwarfSegment(DwarfVMAddr, DwarfSegmentStart, DwarfSegmentSize,
- NumDwarfSections, Layout, Writer);
-
- assert(OutFile.tell() == LoadCommandSize + HeaderSize);
- OutFile.write_zeros(SymtabStart - (LoadCommandSize + HeaderSize));
- assert(OutFile.tell() == SymtabStart);
-
- // Transfer symbols.
- if (ShouldEmitSymtab) {
- OutFile << NewSymtab.str();
- assert(OutFile.tell() == StringStart);
-
- // Transfer string table.
- // FIXME: The NonRelocatableStringpool starts with an empty string, but
- // dsymutil-classic starts the reconstructed string table with 2 of these.
- // Reproduce that behavior for now (there is corresponding code in
- // transferSymbol).
- OutFile << '\0';
- std::vector<DwarfStringPoolEntryRef> Strings =
- NewStrings.getEntriesForEmission();
- for (auto EntryRef : Strings) {
- OutFile.write(EntryRef.getString().data(),
- EntryRef.getString().size() + 1);
- }
- }
- assert(OutFile.tell() == StringStart + NewStringsSize);
-
+ }
+
+ uint64_t DwarfVMAddr = alignTo(EndAddress, 0x1000);
+ uint64_t DwarfVMMax = Is64Bit ? UINT64_MAX : UINT32_MAX;
+ if (DwarfVMAddr + DwarfSegmentSize > DwarfVMMax ||
+ DwarfVMAddr + DwarfSegmentSize < DwarfVMAddr /* Overflow */) {
+ // There is no room for the __DWARF segment at the end of the
+ // address space. Look through segments to find a gap.
+ DwarfVMAddr = GapForDwarf;
+ if (DwarfVMAddr == UINT64_MAX)
+ warn("not enough VM space for the __DWARF segment.",
+ "output file streaming");
+ }
+
+ // Write the load command for the __DWARF segment.
+ createDwarfSegment(DwarfVMAddr, DwarfSegmentStart, DwarfSegmentSize,
+ NumDwarfSections, Layout, Writer);
+
+ assert(OutFile.tell() == LoadCommandSize + HeaderSize);
+ OutFile.write_zeros(SymtabStart - (LoadCommandSize + HeaderSize));
+ assert(OutFile.tell() == SymtabStart);
+
+ // Transfer symbols.
+ if (ShouldEmitSymtab) {
+ OutFile << NewSymtab.str();
+ assert(OutFile.tell() == StringStart);
+
+ // Transfer string table.
+ // FIXME: The NonRelocatableStringpool starts with an empty string, but
+ // dsymutil-classic starts the reconstructed string table with 2 of these.
+ // Reproduce that behavior for now (there is corresponding code in
+ // transferSymbol).
+ OutFile << '\0';
+ std::vector<DwarfStringPoolEntryRef> Strings =
+ NewStrings.getEntriesForEmission();
+ for (auto EntryRef : Strings) {
+ OutFile.write(EntryRef.getString().data(),
+ EntryRef.getString().size() + 1);
+ }
+ }
+ assert(OutFile.tell() == StringStart + NewStringsSize);
+
// Pad till the EH frame start.
OutFile.write_zeros(EHFrameStart - (StringStart + NewStringsSize));
assert(OutFile.tell() == EHFrameStart);
@@ -603,22 +603,22 @@ bool generateDsymCompanion(llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS,
OutFile << EHFrameData;
assert(OutFile.tell() == EHFrameStart + EHFrameSize);
- // Pad till the Dwarf segment start.
+ // Pad till the Dwarf segment start.
OutFile.write_zeros(DwarfSegmentStart - (EHFrameStart + EHFrameSize));
- assert(OutFile.tell() == DwarfSegmentStart);
-
- // Emit the Dwarf sections contents.
- for (const MCSection &Sec : MCAsm) {
- if (Sec.begin() == Sec.end())
- continue;
-
- uint64_t Pos = OutFile.tell();
- OutFile.write_zeros(alignTo(Pos, Sec.getAlignment()) - Pos);
- MCAsm.writeSectionData(OutFile, &Sec, Layout);
- }
-
- return true;
-}
-} // namespace MachOUtils
-} // namespace dsymutil
-} // namespace llvm
+ assert(OutFile.tell() == DwarfSegmentStart);
+
+ // Emit the Dwarf sections contents.
+ for (const MCSection &Sec : MCAsm) {
+ if (Sec.begin() == Sec.end())
+ continue;
+
+ uint64_t Pos = OutFile.tell();
+ OutFile.write_zeros(alignTo(Pos, Sec.getAlignment()) - Pos);
+ MCAsm.writeSectionData(OutFile, &Sec, Layout);
+ }
+
+ return true;
+}
+} // namespace MachOUtils
+} // namespace dsymutil
+} // namespace llvm
diff --git a/contrib/libs/llvm12/tools/dsymutil/MachOUtils.h b/contrib/libs/llvm12/tools/dsymutil/MachOUtils.h
index b1cdd44d38..109da802b0 100644
--- a/contrib/libs/llvm12/tools/dsymutil/MachOUtils.h
+++ b/contrib/libs/llvm12/tools/dsymutil/MachOUtils.h
@@ -1,52 +1,52 @@
-//===-- MachOUtils.h - Mach-o specific helpers for dsymutil --------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-#ifndef LLVM_TOOLS_DSYMUTIL_MACHOUTILS_H
-#define LLVM_TOOLS_DSYMUTIL_MACHOUTILS_H
-
-#include "SymbolMap.h"
-
-#include "llvm/ADT/StringRef.h"
-#include "llvm/Support/FileSystem.h"
-#include "llvm/Support/VirtualFileSystem.h"
-
-#include <string>
-
-namespace llvm {
-class MCStreamer;
-class raw_fd_ostream;
-namespace dsymutil {
-class DebugMap;
-struct LinkOptions;
-namespace MachOUtils {
-
-struct ArchAndFile {
- std::string Arch;
- std::unique_ptr<llvm::sys::fs::TempFile> File;
-
- llvm::Error createTempFile();
- llvm::StringRef path() const;
-
- ArchAndFile(StringRef Arch) : Arch(std::string(Arch)) {}
- ArchAndFile(ArchAndFile &&A) = default;
- ArchAndFile &operator=(ArchAndFile &&A) = default;
- ~ArchAndFile();
-};
-
-bool generateUniversalBinary(SmallVectorImpl<ArchAndFile> &ArchFiles,
- StringRef OutputFileName, const LinkOptions &,
- StringRef SDKPath);
-
-bool generateDsymCompanion(llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS,
- const DebugMap &DM, SymbolMapTranslator &Translator,
- MCStreamer &MS, raw_fd_ostream &OutFile);
-
-std::string getArchName(StringRef Arch);
-} // namespace MachOUtils
-} // namespace dsymutil
-} // namespace llvm
-#endif // LLVM_TOOLS_DSYMUTIL_MACHOUTILS_H
+//===-- MachOUtils.h - Mach-o specific helpers for dsymutil --------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+#ifndef LLVM_TOOLS_DSYMUTIL_MACHOUTILS_H
+#define LLVM_TOOLS_DSYMUTIL_MACHOUTILS_H
+
+#include "SymbolMap.h"
+
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/VirtualFileSystem.h"
+
+#include <string>
+
+namespace llvm {
+class MCStreamer;
+class raw_fd_ostream;
+namespace dsymutil {
+class DebugMap;
+struct LinkOptions;
+namespace MachOUtils {
+
+struct ArchAndFile {
+ std::string Arch;
+ std::unique_ptr<llvm::sys::fs::TempFile> File;
+
+ llvm::Error createTempFile();
+ llvm::StringRef path() const;
+
+ ArchAndFile(StringRef Arch) : Arch(std::string(Arch)) {}
+ ArchAndFile(ArchAndFile &&A) = default;
+ ArchAndFile &operator=(ArchAndFile &&A) = default;
+ ~ArchAndFile();
+};
+
+bool generateUniversalBinary(SmallVectorImpl<ArchAndFile> &ArchFiles,
+ StringRef OutputFileName, const LinkOptions &,
+ StringRef SDKPath);
+
+bool generateDsymCompanion(llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS,
+ const DebugMap &DM, SymbolMapTranslator &Translator,
+ MCStreamer &MS, raw_fd_ostream &OutFile);
+
+std::string getArchName(StringRef Arch);
+} // namespace MachOUtils
+} // namespace dsymutil
+} // namespace llvm
+#endif // LLVM_TOOLS_DSYMUTIL_MACHOUTILS_H
diff --git a/contrib/libs/llvm12/tools/dsymutil/Options.td b/contrib/libs/llvm12/tools/dsymutil/Options.td
index 7bd21b0d43..f704467115 100644
--- a/contrib/libs/llvm12/tools/dsymutil/Options.td
+++ b/contrib/libs/llvm12/tools/dsymutil/Options.td
@@ -1,187 +1,187 @@
-include "llvm/Option/OptParser.td"
-
-class F<string name>: Flag<["--", "-"], name>;
-
-def grp_general : OptionGroup<"Dsymutil">, HelpText<"Dsymutil Options">;
-
-def help: F<"help">,
- HelpText<"Prints this help output.">,
- Group<grp_general>;
-def: Flag<["-"], "h">,
- Alias<help>,
- HelpText<"Alias for --help">,
- Group<grp_general>;
-
-def version: F<"version">,
- HelpText<"Prints the dsymutil version.">,
- Group<grp_general>;
-def: Flag<["-"], "v">,
- Alias<version>,
- HelpText<"Alias for --version">,
- Group<grp_general>;
-
-def verbose: F<"verbose">,
- HelpText<"Enable verbose mode.">,
- Group<grp_general>;
-
-def statistics: F<"statistics">,
- HelpText<"Print statistics about the contribution of each object file to "
- "the linked debug info. This prints a table after linking with the "
- "object file name, the size of the debug info in the object file "
- "(in bytes) and the size contributed (in bytes) to the linked dSYM. "
- "The table is sorted by the output size listing the object files "
- "with the largest contribution first.">,
- Group<grp_general>;
-
-def verify: F<"verify">,
- HelpText<"Run the DWARF verifier on the linked DWARF debug info.">,
- Group<grp_general>;
-
-def no_output: F<"no-output">,
- HelpText<"Do the link in memory, but do not emit the result file.">,
- Group<grp_general>;
-
-def no_swiftmodule_timestamp: F<"no-swiftmodule-timestamp">,
- HelpText<"Don't check timestamp for swiftmodule files.">,
- Group<grp_general>;
-
-def no_odr: F<"no-odr">,
- HelpText<"Do not use ODR (One Definition Rule) for type uniquing.">,
- Group<grp_general>;
-
-def dump_debug_map: F<"dump-debug-map">,
- HelpText<"Parse and dump the debug map to standard output. Not DWARF link will take place.">,
- Group<grp_general>;
-
-def yaml_input: Flag<["-", "--"], "y">,
- HelpText<"Treat the input file is a YAML debug map rather than a binary.">,
- Group<grp_general>;
-
-def papertrail: F<"papertrail">,
- HelpText<"Embed warnings in the linked DWARF debug info.">,
- Group<grp_general>;
-
-def assembly: Flag<["-", "--"], "S">,
- HelpText<"Output textual assembly instead of a binary dSYM companion file.">,
- Group<grp_general>;
-
-def symtab: F<"symtab">,
- HelpText<"Dumps the symbol table found in executable or object file(s) and exits.">,
- Group<grp_general>;
-def: Flag<["-"], "s">,
- Alias<symtab>,
- HelpText<"Alias for --symtab">,
- Group<grp_general>;
-
-def flat: F<"flat">,
- HelpText<"Produce a flat dSYM file (not a bundle).">,
- Group<grp_general>;
-def: Flag<["-"], "f">,
- Alias<flat>,
- HelpText<"Alias for --flat">,
- Group<grp_general>;
-
-def minimize: F<"minimize">,
- HelpText<"When used when creating a dSYM file with Apple accelerator tables, "
- "this option will suppress the emission of the .debug_inlines, "
- ".debug_pubnames, and .debug_pubtypes sections since dsymutil "
- "has better equivalents: .apple_names and .apple_types. When used in "
- "conjunction with --update option, this option will cause redundant "
- "accelerator tables to be removed.">,
- Group<grp_general>;
-def: Flag<["-"], "z">,
- Alias<minimize>,
- HelpText<"Alias for --minimize">,
- Group<grp_general>;
-
-def update: F<"update">,
- HelpText<"Updates existing dSYM files to contain the latest accelerator tables and other DWARF optimizations.">,
- Group<grp_general>;
-def: Flag<["-"], "u">,
- Alias<update>,
- HelpText<"Alias for --update">,
- Group<grp_general>;
-
-def output: Separate<["-", "--"], "o">,
- MetaVarName<"<filename>">,
- HelpText<"Specify the output file. Defaults to <input file>.dwarf">,
- Group<grp_general>;
-def: Separate<["--", "-"], "out">,
- MetaVarName<"<filename>">,
- Alias<output>,
- HelpText<"Alias for -o">,
- Group<grp_general>;
-def: Joined<["--", "-"], "out=">, Alias<output>;
-def: Joined<["-", "--"], "o=">, Alias<output>;
-
-def oso_prepend_path: Separate<["--", "-"], "oso-prepend-path">,
- MetaVarName<"<path>">,
- HelpText<"Specify a directory to prepend to the paths of object files.">,
- Group<grp_general>;
-def: Joined<["--", "-"], "oso-prepend-path=">, Alias<oso_prepend_path>;
-
-def object_prefix_map: Separate<["--", "-"], "object-prefix-map">,
- MetaVarName<"<prefix=remapped>">,
- HelpText<"Remap object file paths (but no source paths) before processing."
- "Use this for Clang objects where the module cache location was"
- "remapped using -fdebug-prefix-map; to help dsymutil"
- "find the Clang module cache.">,
- Group<grp_general>;
-def: Joined<["--", "-"], "object-prefix-map=">, Alias<object_prefix_map>;
-
-def symbolmap: Separate<["--", "-"], "symbol-map">,
- MetaVarName<"<bcsymbolmap>">,
- HelpText<"Updates the existing dSYMs inplace using symbol map specified.">,
- Group<grp_general>;
-def: Joined<["--", "-"], "symbol-map=">, Alias<symbolmap>;
-
-def arch: Separate<["--", "-"], "arch">,
- MetaVarName<"<arch>">,
- HelpText<"Link DWARF debug information only for specified CPU architecture"
- "types. This option can be specified multiple times, once for each"
- "desired architecture. All CPU architectures will be linked by"
- "default.">,
- Group<grp_general>;
-def: Joined<["--", "-"], "arch=">, Alias<arch>;
-
-def accelerator: Separate<["--", "-"], "accelerator">,
- MetaVarName<"<accelerator type>">,
- HelpText<"Specify the desired type of accelerator table. Valid options are 'Apple', 'Dwarf' and 'Default'">,
- Group<grp_general>;
-def: Joined<["--", "-"], "accelerator=">, Alias<accelerator>;
-
-def toolchain: Separate<["--", "-"], "toolchain">,
- MetaVarName<"<toolchain>">,
- HelpText<"Embed toolchain information in dSYM bundle.">,
- Group<grp_general>;
-
-def threads: Separate<["--", "-"], "num-threads">,
- MetaVarName<"<threads>">,
- HelpText<"Specifies the maximum number of simultaneous threads to use when linking multiple architectures.">,
- Group<grp_general>;
-def: Separate<["-"], "j">,
- MetaVarName<"<threads>">,
- HelpText<"Alias for --num-threads">,
- Group<grp_general>;
-
-def gen_reproducer: F<"gen-reproducer">,
- HelpText<"Generate a reproducer consisting of the input object files.">,
- Group<grp_general>;
-
-def use_reproducer: Separate<["--", "-"], "use-reproducer">,
- MetaVarName<"<path>">,
- HelpText<"Use the object files from the given reproducer path.">,
- Group<grp_general>;
-def: Joined<["--", "-"], "use-reproducer=">, Alias<use_reproducer>;
-
-def remarks_prepend_path: Separate<["--", "-"], "remarks-prepend-path">,
- MetaVarName<"<path>">,
- HelpText<"Specify a directory to prepend to the paths of the external remark files.">,
- Group<grp_general>;
-def: Joined<["--", "-"], "remarks-prepend-path=">, Alias<remarks_prepend_path>;
-
-def remarks_output_format: Separate<["--", "-"], "remarks-output-format">,
- MetaVarName<"<format>">,
- HelpText<"Specify the format to be used when serializing the linked remarks.">,
- Group<grp_general>;
-def: Joined<["--", "-"], "remarks-output-format=">, Alias<remarks_output_format>;
+include "llvm/Option/OptParser.td"
+
+class F<string name>: Flag<["--", "-"], name>;
+
+def grp_general : OptionGroup<"Dsymutil">, HelpText<"Dsymutil Options">;
+
+def help: F<"help">,
+ HelpText<"Prints this help output.">,
+ Group<grp_general>;
+def: Flag<["-"], "h">,
+ Alias<help>,
+ HelpText<"Alias for --help">,
+ Group<grp_general>;
+
+def version: F<"version">,
+ HelpText<"Prints the dsymutil version.">,
+ Group<grp_general>;
+def: Flag<["-"], "v">,
+ Alias<version>,
+ HelpText<"Alias for --version">,
+ Group<grp_general>;
+
+def verbose: F<"verbose">,
+ HelpText<"Enable verbose mode.">,
+ Group<grp_general>;
+
+def statistics: F<"statistics">,
+ HelpText<"Print statistics about the contribution of each object file to "
+ "the linked debug info. This prints a table after linking with the "
+ "object file name, the size of the debug info in the object file "
+ "(in bytes) and the size contributed (in bytes) to the linked dSYM. "
+ "The table is sorted by the output size listing the object files "
+ "with the largest contribution first.">,
+ Group<grp_general>;
+
+def verify: F<"verify">,
+ HelpText<"Run the DWARF verifier on the linked DWARF debug info.">,
+ Group<grp_general>;
+
+def no_output: F<"no-output">,
+ HelpText<"Do the link in memory, but do not emit the result file.">,
+ Group<grp_general>;
+
+def no_swiftmodule_timestamp: F<"no-swiftmodule-timestamp">,
+ HelpText<"Don't check timestamp for swiftmodule files.">,
+ Group<grp_general>;
+
+def no_odr: F<"no-odr">,
+ HelpText<"Do not use ODR (One Definition Rule) for type uniquing.">,
+ Group<grp_general>;
+
+def dump_debug_map: F<"dump-debug-map">,
+ HelpText<"Parse and dump the debug map to standard output. Not DWARF link will take place.">,
+ Group<grp_general>;
+
+def yaml_input: Flag<["-", "--"], "y">,
+ HelpText<"Treat the input file is a YAML debug map rather than a binary.">,
+ Group<grp_general>;
+
+def papertrail: F<"papertrail">,
+ HelpText<"Embed warnings in the linked DWARF debug info.">,
+ Group<grp_general>;
+
+def assembly: Flag<["-", "--"], "S">,
+ HelpText<"Output textual assembly instead of a binary dSYM companion file.">,
+ Group<grp_general>;
+
+def symtab: F<"symtab">,
+ HelpText<"Dumps the symbol table found in executable or object file(s) and exits.">,
+ Group<grp_general>;
+def: Flag<["-"], "s">,
+ Alias<symtab>,
+ HelpText<"Alias for --symtab">,
+ Group<grp_general>;
+
+def flat: F<"flat">,
+ HelpText<"Produce a flat dSYM file (not a bundle).">,
+ Group<grp_general>;
+def: Flag<["-"], "f">,
+ Alias<flat>,
+ HelpText<"Alias for --flat">,
+ Group<grp_general>;
+
+def minimize: F<"minimize">,
+ HelpText<"When used when creating a dSYM file with Apple accelerator tables, "
+ "this option will suppress the emission of the .debug_inlines, "
+ ".debug_pubnames, and .debug_pubtypes sections since dsymutil "
+ "has better equivalents: .apple_names and .apple_types. When used in "
+ "conjunction with --update option, this option will cause redundant "
+ "accelerator tables to be removed.">,
+ Group<grp_general>;
+def: Flag<["-"], "z">,
+ Alias<minimize>,
+ HelpText<"Alias for --minimize">,
+ Group<grp_general>;
+
+def update: F<"update">,
+ HelpText<"Updates existing dSYM files to contain the latest accelerator tables and other DWARF optimizations.">,
+ Group<grp_general>;
+def: Flag<["-"], "u">,
+ Alias<update>,
+ HelpText<"Alias for --update">,
+ Group<grp_general>;
+
+def output: Separate<["-", "--"], "o">,
+ MetaVarName<"<filename>">,
+ HelpText<"Specify the output file. Defaults to <input file>.dwarf">,
+ Group<grp_general>;
+def: Separate<["--", "-"], "out">,
+ MetaVarName<"<filename>">,
+ Alias<output>,
+ HelpText<"Alias for -o">,
+ Group<grp_general>;
+def: Joined<["--", "-"], "out=">, Alias<output>;
+def: Joined<["-", "--"], "o=">, Alias<output>;
+
+def oso_prepend_path: Separate<["--", "-"], "oso-prepend-path">,
+ MetaVarName<"<path>">,
+ HelpText<"Specify a directory to prepend to the paths of object files.">,
+ Group<grp_general>;
+def: Joined<["--", "-"], "oso-prepend-path=">, Alias<oso_prepend_path>;
+
+def object_prefix_map: Separate<["--", "-"], "object-prefix-map">,
+ MetaVarName<"<prefix=remapped>">,
+ HelpText<"Remap object file paths (but no source paths) before processing."
+ "Use this for Clang objects where the module cache location was"
+ "remapped using -fdebug-prefix-map; to help dsymutil"
+ "find the Clang module cache.">,
+ Group<grp_general>;
+def: Joined<["--", "-"], "object-prefix-map=">, Alias<object_prefix_map>;
+
+def symbolmap: Separate<["--", "-"], "symbol-map">,
+ MetaVarName<"<bcsymbolmap>">,
+ HelpText<"Updates the existing dSYMs inplace using symbol map specified.">,
+ Group<grp_general>;
+def: Joined<["--", "-"], "symbol-map=">, Alias<symbolmap>;
+
+def arch: Separate<["--", "-"], "arch">,
+ MetaVarName<"<arch>">,
+ HelpText<"Link DWARF debug information only for specified CPU architecture"
+ "types. This option can be specified multiple times, once for each"
+ "desired architecture. All CPU architectures will be linked by"
+ "default.">,
+ Group<grp_general>;
+def: Joined<["--", "-"], "arch=">, Alias<arch>;
+
+def accelerator: Separate<["--", "-"], "accelerator">,
+ MetaVarName<"<accelerator type>">,
+ HelpText<"Specify the desired type of accelerator table. Valid options are 'Apple', 'Dwarf' and 'Default'">,
+ Group<grp_general>;
+def: Joined<["--", "-"], "accelerator=">, Alias<accelerator>;
+
+def toolchain: Separate<["--", "-"], "toolchain">,
+ MetaVarName<"<toolchain>">,
+ HelpText<"Embed toolchain information in dSYM bundle.">,
+ Group<grp_general>;
+
+def threads: Separate<["--", "-"], "num-threads">,
+ MetaVarName<"<threads>">,
+ HelpText<"Specifies the maximum number of simultaneous threads to use when linking multiple architectures.">,
+ Group<grp_general>;
+def: Separate<["-"], "j">,
+ MetaVarName<"<threads>">,
+ HelpText<"Alias for --num-threads">,
+ Group<grp_general>;
+
+def gen_reproducer: F<"gen-reproducer">,
+ HelpText<"Generate a reproducer consisting of the input object files.">,
+ Group<grp_general>;
+
+def use_reproducer: Separate<["--", "-"], "use-reproducer">,
+ MetaVarName<"<path>">,
+ HelpText<"Use the object files from the given reproducer path.">,
+ Group<grp_general>;
+def: Joined<["--", "-"], "use-reproducer=">, Alias<use_reproducer>;
+
+def remarks_prepend_path: Separate<["--", "-"], "remarks-prepend-path">,
+ MetaVarName<"<path>">,
+ HelpText<"Specify a directory to prepend to the paths of the external remark files.">,
+ Group<grp_general>;
+def: Joined<["--", "-"], "remarks-prepend-path=">, Alias<remarks_prepend_path>;
+
+def remarks_output_format: Separate<["--", "-"], "remarks-output-format">,
+ MetaVarName<"<format>">,
+ HelpText<"Specify the format to be used when serializing the linked remarks.">,
+ Group<grp_general>;
+def: Joined<["--", "-"], "remarks-output-format=">, Alias<remarks_output_format>;
diff --git a/contrib/libs/llvm12/tools/dsymutil/Reproducer.cpp b/contrib/libs/llvm12/tools/dsymutil/Reproducer.cpp
index 5c60758c6f..d064086b0f 100644
--- a/contrib/libs/llvm12/tools/dsymutil/Reproducer.cpp
+++ b/contrib/libs/llvm12/tools/dsymutil/Reproducer.cpp
@@ -1,85 +1,85 @@
-//===- Reproducer.cpp -----------------------------------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "Reproducer.h"
-#include "llvm/Support/Path.h"
-
-using namespace llvm;
-using namespace llvm::dsymutil;
-
-static std::string createReproducerDir(std::error_code &EC) {
- SmallString<128> Root;
- if (const char *Path = getenv("DSYMUTIL_REPRODUCER_PATH")) {
- Root.assign(Path);
- EC = sys::fs::create_directory(Root);
- } else {
- EC = sys::fs::createUniqueDirectory("dsymutil", Root);
- }
- return EC ? "" : std::string(Root);
-}
-
-Reproducer::Reproducer() : VFS(vfs::getRealFileSystem()) {}
-Reproducer::~Reproducer() = default;
-
-ReproducerGenerate::ReproducerGenerate(std::error_code &EC)
- : Root(createReproducerDir(EC)), FC() {
- if (!Root.empty())
- FC = std::make_shared<FileCollector>(Root, Root);
- VFS = FileCollector::createCollectorVFS(vfs::getRealFileSystem(), FC);
-}
-
-ReproducerGenerate::~ReproducerGenerate() {
- if (!FC)
- return;
- FC->copyFiles(false);
- SmallString<128> Mapping(Root);
- sys::path::append(Mapping, "mapping.yaml");
- FC->writeMapping(Mapping.str());
- outs() << "reproducer written to " << Root << '\n';
-}
-
-ReproducerUse::~ReproducerUse() = default;
-
-ReproducerUse::ReproducerUse(StringRef Root, std::error_code &EC) {
- SmallString<128> Mapping(Root);
- sys::path::append(Mapping, "mapping.yaml");
- ErrorOr<std::unique_ptr<MemoryBuffer>> Buffer =
- vfs::getRealFileSystem()->getBufferForFile(Mapping.str());
-
- if (!Buffer) {
- EC = Buffer.getError();
- return;
- }
-
- VFS = llvm::vfs::getVFSFromYAML(std::move(Buffer.get()), nullptr, Mapping);
-}
-
-llvm::Expected<std::unique_ptr<Reproducer>>
-Reproducer::createReproducer(ReproducerMode Mode, StringRef Root) {
- switch (Mode) {
- case ReproducerMode::Generate: {
- std::error_code EC;
- std::unique_ptr<Reproducer> Repro =
- std::make_unique<ReproducerGenerate>(EC);
- if (EC)
- return errorCodeToError(EC);
- return std::move(Repro);
- }
- case ReproducerMode::Use: {
- std::error_code EC;
- std::unique_ptr<Reproducer> Repro =
- std::make_unique<ReproducerUse>(Root, EC);
- if (EC)
- return errorCodeToError(EC);
- return std::move(Repro);
- }
- case ReproducerMode::Off:
- return std::make_unique<Reproducer>();
- }
- llvm_unreachable("All cases handled above.");
-}
+//===- Reproducer.cpp -----------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "Reproducer.h"
+#include "llvm/Support/Path.h"
+
+using namespace llvm;
+using namespace llvm::dsymutil;
+
+static std::string createReproducerDir(std::error_code &EC) {
+ SmallString<128> Root;
+ if (const char *Path = getenv("DSYMUTIL_REPRODUCER_PATH")) {
+ Root.assign(Path);
+ EC = sys::fs::create_directory(Root);
+ } else {
+ EC = sys::fs::createUniqueDirectory("dsymutil", Root);
+ }
+ return EC ? "" : std::string(Root);
+}
+
+Reproducer::Reproducer() : VFS(vfs::getRealFileSystem()) {}
+Reproducer::~Reproducer() = default;
+
+ReproducerGenerate::ReproducerGenerate(std::error_code &EC)
+ : Root(createReproducerDir(EC)), FC() {
+ if (!Root.empty())
+ FC = std::make_shared<FileCollector>(Root, Root);
+ VFS = FileCollector::createCollectorVFS(vfs::getRealFileSystem(), FC);
+}
+
+ReproducerGenerate::~ReproducerGenerate() {
+ if (!FC)
+ return;
+ FC->copyFiles(false);
+ SmallString<128> Mapping(Root);
+ sys::path::append(Mapping, "mapping.yaml");
+ FC->writeMapping(Mapping.str());
+ outs() << "reproducer written to " << Root << '\n';
+}
+
+ReproducerUse::~ReproducerUse() = default;
+
+ReproducerUse::ReproducerUse(StringRef Root, std::error_code &EC) {
+ SmallString<128> Mapping(Root);
+ sys::path::append(Mapping, "mapping.yaml");
+ ErrorOr<std::unique_ptr<MemoryBuffer>> Buffer =
+ vfs::getRealFileSystem()->getBufferForFile(Mapping.str());
+
+ if (!Buffer) {
+ EC = Buffer.getError();
+ return;
+ }
+
+ VFS = llvm::vfs::getVFSFromYAML(std::move(Buffer.get()), nullptr, Mapping);
+}
+
+llvm::Expected<std::unique_ptr<Reproducer>>
+Reproducer::createReproducer(ReproducerMode Mode, StringRef Root) {
+ switch (Mode) {
+ case ReproducerMode::Generate: {
+ std::error_code EC;
+ std::unique_ptr<Reproducer> Repro =
+ std::make_unique<ReproducerGenerate>(EC);
+ if (EC)
+ return errorCodeToError(EC);
+ return std::move(Repro);
+ }
+ case ReproducerMode::Use: {
+ std::error_code EC;
+ std::unique_ptr<Reproducer> Repro =
+ std::make_unique<ReproducerUse>(Root, EC);
+ if (EC)
+ return errorCodeToError(EC);
+ return std::move(Repro);
+ }
+ case ReproducerMode::Off:
+ return std::make_unique<Reproducer>();
+ }
+ llvm_unreachable("All cases handled above.");
+}
diff --git a/contrib/libs/llvm12/tools/dsymutil/Reproducer.h b/contrib/libs/llvm12/tools/dsymutil/Reproducer.h
index e965e1ceda..8b3adf63f3 100644
--- a/contrib/libs/llvm12/tools/dsymutil/Reproducer.h
+++ b/contrib/libs/llvm12/tools/dsymutil/Reproducer.h
@@ -1,77 +1,77 @@
-//===- tools/dsymutil/Reproducer.h ------------------------------*- C++ -*-===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_TOOLS_DSYMUTIL_REPRODUCER_H
-#define LLVM_TOOLS_DSYMUTIL_REPRODUCER_H
-
-#include "llvm/Support/Error.h"
-#include "llvm/Support/FileCollector.h"
-#include "llvm/Support/VirtualFileSystem.h"
-
-namespace llvm {
-namespace dsymutil {
-
-/// The reproducer mode.
-enum class ReproducerMode {
- Generate,
- Use,
- Off,
-};
-
-/// The reproducer class manages the sate related to reproducers in dsymutil.
-/// Instances should be created with Reproducer::createReproducer. An instance
-/// of this class is returned when reproducers are off. The VFS returned by
-/// this instance is the real file system.
-class Reproducer {
-public:
- Reproducer();
- virtual ~Reproducer();
-
- IntrusiveRefCntPtr<vfs::FileSystem> getVFS() const { return VFS; }
-
- /// Create a Reproducer instance based on the given mode.
- static llvm::Expected<std::unique_ptr<Reproducer>>
- createReproducer(ReproducerMode Mode, StringRef Root);
-
-protected:
- IntrusiveRefCntPtr<vfs::FileSystem> VFS;
-};
-
-/// Reproducer instance used to generate a new reproducer. The VFS returned by
-/// this instance is a FileCollectorFileSystem that tracks every file used by
-/// dsymutil.
-class ReproducerGenerate : public Reproducer {
-public:
- ReproducerGenerate(std::error_code &EC);
- ~ReproducerGenerate() override;
-
-private:
- /// The path to the reproducer.
- std::string Root;
-
- /// The FileCollector used by the FileCollectorFileSystem.
- std::shared_ptr<FileCollector> FC;
-};
-
-/// Reproducer instance used to use an existing reproducer. The VFS returned by
-/// this instance is a RedirectingFileSystem that remaps paths to their
-/// counterpart in the reproducer.
-class ReproducerUse : public Reproducer {
-public:
- ReproducerUse(StringRef Root, std::error_code &EC);
- ~ReproducerUse() override;
-
-private:
- /// The path to the reproducer.
- std::string Root;
-};
-
-} // end namespace dsymutil
-} // end namespace llvm
-
-#endif // LLVM_TOOLS_DSYMUTIL_REPRODUCER_H
+//===- tools/dsymutil/Reproducer.h ------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TOOLS_DSYMUTIL_REPRODUCER_H
+#define LLVM_TOOLS_DSYMUTIL_REPRODUCER_H
+
+#include "llvm/Support/Error.h"
+#include "llvm/Support/FileCollector.h"
+#include "llvm/Support/VirtualFileSystem.h"
+
+namespace llvm {
+namespace dsymutil {
+
+/// The reproducer mode.
+enum class ReproducerMode {
+ Generate,
+ Use,
+ Off,
+};
+
+/// The reproducer class manages the sate related to reproducers in dsymutil.
+/// Instances should be created with Reproducer::createReproducer. An instance
+/// of this class is returned when reproducers are off. The VFS returned by
+/// this instance is the real file system.
+class Reproducer {
+public:
+ Reproducer();
+ virtual ~Reproducer();
+
+ IntrusiveRefCntPtr<vfs::FileSystem> getVFS() const { return VFS; }
+
+ /// Create a Reproducer instance based on the given mode.
+ static llvm::Expected<std::unique_ptr<Reproducer>>
+ createReproducer(ReproducerMode Mode, StringRef Root);
+
+protected:
+ IntrusiveRefCntPtr<vfs::FileSystem> VFS;
+};
+
+/// Reproducer instance used to generate a new reproducer. The VFS returned by
+/// this instance is a FileCollectorFileSystem that tracks every file used by
+/// dsymutil.
+class ReproducerGenerate : public Reproducer {
+public:
+ ReproducerGenerate(std::error_code &EC);
+ ~ReproducerGenerate() override;
+
+private:
+ /// The path to the reproducer.
+ std::string Root;
+
+ /// The FileCollector used by the FileCollectorFileSystem.
+ std::shared_ptr<FileCollector> FC;
+};
+
+/// Reproducer instance used to use an existing reproducer. The VFS returned by
+/// this instance is a RedirectingFileSystem that remaps paths to their
+/// counterpart in the reproducer.
+class ReproducerUse : public Reproducer {
+public:
+ ReproducerUse(StringRef Root, std::error_code &EC);
+ ~ReproducerUse() override;
+
+private:
+ /// The path to the reproducer.
+ std::string Root;
+};
+
+} // end namespace dsymutil
+} // end namespace llvm
+
+#endif // LLVM_TOOLS_DSYMUTIL_REPRODUCER_H
diff --git a/contrib/libs/llvm12/tools/dsymutil/SymbolMap.cpp b/contrib/libs/llvm12/tools/dsymutil/SymbolMap.cpp
index 07a54795a8..ed0c70888d 100644
--- a/contrib/libs/llvm12/tools/dsymutil/SymbolMap.cpp
+++ b/contrib/libs/llvm12/tools/dsymutil/SymbolMap.cpp
@@ -1,161 +1,161 @@
-//===- tools/dsymutil/SymbolMap.cpp ---------------------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "SymbolMap.h"
-#include "DebugMap.h"
-#include "MachOUtils.h"
-
-#include "llvm/Support/FileSystem.h"
-#include "llvm/Support/Path.h"
-#include "llvm/Support/WithColor.h"
-
-#ifdef __APPLE__
-#include <CoreFoundation/CoreFoundation.h>
-#include <uuid/uuid.h>
-#endif
-
-namespace llvm {
-namespace dsymutil {
-
-StringRef SymbolMapTranslator::operator()(StringRef Input) {
- if (!Input.startswith("__hidden#") && !Input.startswith("___hidden#"))
- return Input;
-
- bool MightNeedUnderscore = false;
- StringRef Line = Input.drop_front(sizeof("__hidden#") - 1);
- if (Line[0] == '#') {
- Line = Line.drop_front();
- MightNeedUnderscore = true;
- }
-
- std::size_t LineNumber = std::numeric_limits<std::size_t>::max();
- Line.split('_').first.getAsInteger(10, LineNumber);
- if (LineNumber >= UnobfuscatedStrings.size()) {
- WithColor::warning() << "reference to a unexisting unobfuscated string "
- << Input << ": symbol map mismatch?\n"
- << Line << '\n';
- return Input;
- }
-
- const std::string &Translation = UnobfuscatedStrings[LineNumber];
- if (!MightNeedUnderscore || !MangleNames)
- return Translation;
-
- // Objective-C symbols for the MachO symbol table start with a \1. Please see
+//===- tools/dsymutil/SymbolMap.cpp ---------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "SymbolMap.h"
+#include "DebugMap.h"
+#include "MachOUtils.h"
+
+#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/Path.h"
+#include "llvm/Support/WithColor.h"
+
+#ifdef __APPLE__
+#include <CoreFoundation/CoreFoundation.h>
+#include <uuid/uuid.h>
+#endif
+
+namespace llvm {
+namespace dsymutil {
+
+StringRef SymbolMapTranslator::operator()(StringRef Input) {
+ if (!Input.startswith("__hidden#") && !Input.startswith("___hidden#"))
+ return Input;
+
+ bool MightNeedUnderscore = false;
+ StringRef Line = Input.drop_front(sizeof("__hidden#") - 1);
+ if (Line[0] == '#') {
+ Line = Line.drop_front();
+ MightNeedUnderscore = true;
+ }
+
+ std::size_t LineNumber = std::numeric_limits<std::size_t>::max();
+ Line.split('_').first.getAsInteger(10, LineNumber);
+ if (LineNumber >= UnobfuscatedStrings.size()) {
+ WithColor::warning() << "reference to a unexisting unobfuscated string "
+ << Input << ": symbol map mismatch?\n"
+ << Line << '\n';
+ return Input;
+ }
+
+ const std::string &Translation = UnobfuscatedStrings[LineNumber];
+ if (!MightNeedUnderscore || !MangleNames)
+ return Translation;
+
+ // Objective-C symbols for the MachO symbol table start with a \1. Please see
// `MangleContext::mangleObjCMethodName` in clang.
- if (Translation[0] == 1)
- return StringRef(Translation).drop_front();
-
- // We need permanent storage for the string we are about to create. Just
- // append it to the vector containing translations. This should only happen
- // during MachO symbol table translation, thus there should be no risk on
- // exponential growth.
- UnobfuscatedStrings.emplace_back("_" + Translation);
- return UnobfuscatedStrings.back();
-}
-
-SymbolMapTranslator SymbolMapLoader::Load(StringRef InputFile,
- const DebugMap &Map) const {
- if (SymbolMap.empty())
- return {};
-
- std::string SymbolMapPath = SymbolMap;
-
-#if __APPLE__
- // Look through the UUID Map.
- if (sys::fs::is_directory(SymbolMapPath) && !Map.getUUID().empty()) {
- uuid_string_t UUIDString;
- uuid_unparse_upper((const uint8_t *)Map.getUUID().data(), UUIDString);
-
- SmallString<256> PlistPath(
- sys::path::parent_path(sys::path::parent_path(InputFile)));
- sys::path::append(PlistPath, StringRef(UUIDString).str() + ".plist");
-
- CFStringRef plistFile = CFStringCreateWithCString(
- kCFAllocatorDefault, PlistPath.c_str(), kCFStringEncodingUTF8);
- CFURLRef fileURL = CFURLCreateWithFileSystemPath(
- kCFAllocatorDefault, plistFile, kCFURLPOSIXPathStyle, false);
- CFReadStreamRef resourceData =
- CFReadStreamCreateWithFile(kCFAllocatorDefault, fileURL);
- if (resourceData) {
- CFReadStreamOpen(resourceData);
- CFDictionaryRef plist = (CFDictionaryRef)CFPropertyListCreateWithStream(
- kCFAllocatorDefault, resourceData, 0, kCFPropertyListImmutable,
- nullptr, nullptr);
-
- if (plist) {
- if (CFDictionaryContainsKey(plist, CFSTR("DBGOriginalUUID"))) {
- CFStringRef OldUUID = (CFStringRef)CFDictionaryGetValue(
- plist, CFSTR("DBGOriginalUUID"));
-
- StringRef UUID(CFStringGetCStringPtr(OldUUID, kCFStringEncodingUTF8));
- SmallString<256> BCSymbolMapPath(SymbolMapPath);
- sys::path::append(BCSymbolMapPath, UUID.str() + ".bcsymbolmap");
- SymbolMapPath = std::string(BCSymbolMapPath);
- }
- CFRelease(plist);
- }
- CFReadStreamClose(resourceData);
- CFRelease(resourceData);
- }
- CFRelease(fileURL);
- CFRelease(plistFile);
- }
-#endif
-
- if (sys::fs::is_directory(SymbolMapPath)) {
- SymbolMapPath += (Twine("/") + sys::path::filename(InputFile) + "-" +
- MachOUtils::getArchName(Map.getTriple().getArchName()) +
- ".bcsymbolmap")
- .str();
- }
-
- auto ErrOrMemBuffer = MemoryBuffer::getFile(SymbolMapPath);
- if (auto EC = ErrOrMemBuffer.getError()) {
- WithColor::warning() << SymbolMapPath << ": " << EC.message()
- << ": not unobfuscating.\n";
- return {};
- }
-
- std::vector<std::string> UnobfuscatedStrings;
- auto &MemBuf = **ErrOrMemBuffer;
- StringRef Data(MemBuf.getBufferStart(),
- MemBuf.getBufferEnd() - MemBuf.getBufferStart());
- StringRef LHS;
- std::tie(LHS, Data) = Data.split('\n');
- bool MangleNames = false;
-
- // Check version string first.
- if (!LHS.startswith("BCSymbolMap Version:")) {
- // Version string not present, warns but try to parse it.
- WithColor::warning() << SymbolMapPath
- << " is missing version string: assuming 1.0.\n";
- UnobfuscatedStrings.emplace_back(LHS);
- } else if (LHS.equals("BCSymbolMap Version: 1.0")) {
- MangleNames = true;
- } else if (LHS.equals("BCSymbolMap Version: 2.0")) {
- MangleNames = false;
- } else {
- StringRef VersionNum;
- std::tie(LHS, VersionNum) = LHS.split(':');
- WithColor::warning() << SymbolMapPath
- << " has unsupported symbol map version" << VersionNum
- << ": not unobfuscating.\n";
- return {};
- }
-
- while (!Data.empty()) {
- std::tie(LHS, Data) = Data.split('\n');
- UnobfuscatedStrings.emplace_back(LHS);
- }
-
- return SymbolMapTranslator(std::move(UnobfuscatedStrings), MangleNames);
-}
-
-} // namespace dsymutil
-} // namespace llvm
+ if (Translation[0] == 1)
+ return StringRef(Translation).drop_front();
+
+ // We need permanent storage for the string we are about to create. Just
+ // append it to the vector containing translations. This should only happen
+ // during MachO symbol table translation, thus there should be no risk on
+ // exponential growth.
+ UnobfuscatedStrings.emplace_back("_" + Translation);
+ return UnobfuscatedStrings.back();
+}
+
+SymbolMapTranslator SymbolMapLoader::Load(StringRef InputFile,
+ const DebugMap &Map) const {
+ if (SymbolMap.empty())
+ return {};
+
+ std::string SymbolMapPath = SymbolMap;
+
+#if __APPLE__
+ // Look through the UUID Map.
+ if (sys::fs::is_directory(SymbolMapPath) && !Map.getUUID().empty()) {
+ uuid_string_t UUIDString;
+ uuid_unparse_upper((const uint8_t *)Map.getUUID().data(), UUIDString);
+
+ SmallString<256> PlistPath(
+ sys::path::parent_path(sys::path::parent_path(InputFile)));
+ sys::path::append(PlistPath, StringRef(UUIDString).str() + ".plist");
+
+ CFStringRef plistFile = CFStringCreateWithCString(
+ kCFAllocatorDefault, PlistPath.c_str(), kCFStringEncodingUTF8);
+ CFURLRef fileURL = CFURLCreateWithFileSystemPath(
+ kCFAllocatorDefault, plistFile, kCFURLPOSIXPathStyle, false);
+ CFReadStreamRef resourceData =
+ CFReadStreamCreateWithFile(kCFAllocatorDefault, fileURL);
+ if (resourceData) {
+ CFReadStreamOpen(resourceData);
+ CFDictionaryRef plist = (CFDictionaryRef)CFPropertyListCreateWithStream(
+ kCFAllocatorDefault, resourceData, 0, kCFPropertyListImmutable,
+ nullptr, nullptr);
+
+ if (plist) {
+ if (CFDictionaryContainsKey(plist, CFSTR("DBGOriginalUUID"))) {
+ CFStringRef OldUUID = (CFStringRef)CFDictionaryGetValue(
+ plist, CFSTR("DBGOriginalUUID"));
+
+ StringRef UUID(CFStringGetCStringPtr(OldUUID, kCFStringEncodingUTF8));
+ SmallString<256> BCSymbolMapPath(SymbolMapPath);
+ sys::path::append(BCSymbolMapPath, UUID.str() + ".bcsymbolmap");
+ SymbolMapPath = std::string(BCSymbolMapPath);
+ }
+ CFRelease(plist);
+ }
+ CFReadStreamClose(resourceData);
+ CFRelease(resourceData);
+ }
+ CFRelease(fileURL);
+ CFRelease(plistFile);
+ }
+#endif
+
+ if (sys::fs::is_directory(SymbolMapPath)) {
+ SymbolMapPath += (Twine("/") + sys::path::filename(InputFile) + "-" +
+ MachOUtils::getArchName(Map.getTriple().getArchName()) +
+ ".bcsymbolmap")
+ .str();
+ }
+
+ auto ErrOrMemBuffer = MemoryBuffer::getFile(SymbolMapPath);
+ if (auto EC = ErrOrMemBuffer.getError()) {
+ WithColor::warning() << SymbolMapPath << ": " << EC.message()
+ << ": not unobfuscating.\n";
+ return {};
+ }
+
+ std::vector<std::string> UnobfuscatedStrings;
+ auto &MemBuf = **ErrOrMemBuffer;
+ StringRef Data(MemBuf.getBufferStart(),
+ MemBuf.getBufferEnd() - MemBuf.getBufferStart());
+ StringRef LHS;
+ std::tie(LHS, Data) = Data.split('\n');
+ bool MangleNames = false;
+
+ // Check version string first.
+ if (!LHS.startswith("BCSymbolMap Version:")) {
+ // Version string not present, warns but try to parse it.
+ WithColor::warning() << SymbolMapPath
+ << " is missing version string: assuming 1.0.\n";
+ UnobfuscatedStrings.emplace_back(LHS);
+ } else if (LHS.equals("BCSymbolMap Version: 1.0")) {
+ MangleNames = true;
+ } else if (LHS.equals("BCSymbolMap Version: 2.0")) {
+ MangleNames = false;
+ } else {
+ StringRef VersionNum;
+ std::tie(LHS, VersionNum) = LHS.split(':');
+ WithColor::warning() << SymbolMapPath
+ << " has unsupported symbol map version" << VersionNum
+ << ": not unobfuscating.\n";
+ return {};
+ }
+
+ while (!Data.empty()) {
+ std::tie(LHS, Data) = Data.split('\n');
+ UnobfuscatedStrings.emplace_back(LHS);
+ }
+
+ return SymbolMapTranslator(std::move(UnobfuscatedStrings), MangleNames);
+}
+
+} // namespace dsymutil
+} // namespace llvm
diff --git a/contrib/libs/llvm12/tools/dsymutil/SymbolMap.h b/contrib/libs/llvm12/tools/dsymutil/SymbolMap.h
index 977de31a5a..636a6126b7 100644
--- a/contrib/libs/llvm12/tools/dsymutil/SymbolMap.h
+++ b/contrib/libs/llvm12/tools/dsymutil/SymbolMap.h
@@ -1,53 +1,53 @@
-//=- tools/dsymutil/SymbolMap.h -----------------------------------*- C++ -*-=//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_TOOLS_DSYMUTIL_SYMBOLMAP_H
-#define LLVM_TOOLS_DSYMUTIL_SYMBOLMAP_H
-
-#include "llvm/ADT/StringRef.h"
-
-#include <string>
-#include <vector>
-
-namespace llvm {
-namespace dsymutil {
-class DebugMap;
-
-/// Callable class to unobfuscate strings based on a BCSymbolMap.
-class SymbolMapTranslator {
-public:
- SymbolMapTranslator() : MangleNames(false) {}
-
- SymbolMapTranslator(std::vector<std::string> UnobfuscatedStrings,
- bool MangleNames)
- : UnobfuscatedStrings(std::move(UnobfuscatedStrings)),
- MangleNames(MangleNames) {}
-
- StringRef operator()(StringRef Input);
-
- operator bool() const { return !UnobfuscatedStrings.empty(); }
-
-private:
- std::vector<std::string> UnobfuscatedStrings;
- bool MangleNames;
-};
-
-/// Class to initialize SymbolMapTranslators from a BCSymbolMap.
-class SymbolMapLoader {
-public:
- SymbolMapLoader(std::string SymbolMap) : SymbolMap(std::move(SymbolMap)) {}
-
- SymbolMapTranslator Load(StringRef InputFile, const DebugMap &Map) const;
-
-private:
- const std::string SymbolMap;
-};
-} // namespace dsymutil
-} // namespace llvm
-
-#endif // LLVM_TOOLS_DSYMUTIL_SYMBOLMAP_H
+//=- tools/dsymutil/SymbolMap.h -----------------------------------*- C++ -*-=//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TOOLS_DSYMUTIL_SYMBOLMAP_H
+#define LLVM_TOOLS_DSYMUTIL_SYMBOLMAP_H
+
+#include "llvm/ADT/StringRef.h"
+
+#include <string>
+#include <vector>
+
+namespace llvm {
+namespace dsymutil {
+class DebugMap;
+
+/// Callable class to unobfuscate strings based on a BCSymbolMap.
+class SymbolMapTranslator {
+public:
+ SymbolMapTranslator() : MangleNames(false) {}
+
+ SymbolMapTranslator(std::vector<std::string> UnobfuscatedStrings,
+ bool MangleNames)
+ : UnobfuscatedStrings(std::move(UnobfuscatedStrings)),
+ MangleNames(MangleNames) {}
+
+ StringRef operator()(StringRef Input);
+
+ operator bool() const { return !UnobfuscatedStrings.empty(); }
+
+private:
+ std::vector<std::string> UnobfuscatedStrings;
+ bool MangleNames;
+};
+
+/// Class to initialize SymbolMapTranslators from a BCSymbolMap.
+class SymbolMapLoader {
+public:
+ SymbolMapLoader(std::string SymbolMap) : SymbolMap(std::move(SymbolMap)) {}
+
+ SymbolMapTranslator Load(StringRef InputFile, const DebugMap &Map) const;
+
+private:
+ const std::string SymbolMap;
+};
+} // namespace dsymutil
+} // namespace llvm
+
+#endif // LLVM_TOOLS_DSYMUTIL_SYMBOLMAP_H
diff --git a/contrib/libs/llvm12/tools/dsymutil/dsymutil.cpp b/contrib/libs/llvm12/tools/dsymutil/dsymutil.cpp
index 347b2dd916..bd73a45cca 100644
--- a/contrib/libs/llvm12/tools/dsymutil/dsymutil.cpp
+++ b/contrib/libs/llvm12/tools/dsymutil/dsymutil.cpp
@@ -1,691 +1,691 @@
-//===- dsymutil.cpp - Debug info dumping utility for llvm -----------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-//
-// This program is a utility that aims to be a dropin replacement for Darwin's
-// dsymutil.
-//===----------------------------------------------------------------------===//
-
-#include "dsymutil.h"
-#include "BinaryHolder.h"
-#include "CFBundle.h"
-#include "DebugMap.h"
-#include "LinkUtils.h"
-#include "MachOUtils.h"
-#include "Reproducer.h"
+//===- dsymutil.cpp - Debug info dumping utility for llvm -----------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This program is a utility that aims to be a dropin replacement for Darwin's
+// dsymutil.
+//===----------------------------------------------------------------------===//
+
+#include "dsymutil.h"
+#include "BinaryHolder.h"
+#include "CFBundle.h"
+#include "DebugMap.h"
+#include "LinkUtils.h"
+#include "MachOUtils.h"
+#include "Reproducer.h"
#include "llvm/ADT/STLExtras.h"
-#include "llvm/ADT/SmallString.h"
-#include "llvm/ADT/SmallVector.h"
-#include "llvm/ADT/StringExtras.h"
-#include "llvm/ADT/StringRef.h"
-#include "llvm/ADT/Triple.h"
-#include "llvm/DebugInfo/DIContext.h"
-#include "llvm/DebugInfo/DWARF/DWARFContext.h"
-#include "llvm/DebugInfo/DWARF/DWARFVerifier.h"
-#include "llvm/Object/Binary.h"
-#include "llvm/Object/MachO.h"
-#include "llvm/Option/Arg.h"
-#include "llvm/Option/ArgList.h"
-#include "llvm/Option/Option.h"
-#include "llvm/Support/CommandLine.h"
-#include "llvm/Support/FileCollector.h"
-#include "llvm/Support/FileSystem.h"
-#include "llvm/Support/InitLLVM.h"
-#include "llvm/Support/ManagedStatic.h"
-#include "llvm/Support/Path.h"
-#include "llvm/Support/TargetSelect.h"
-#include "llvm/Support/ThreadPool.h"
-#include "llvm/Support/WithColor.h"
-#include "llvm/Support/raw_ostream.h"
-#include "llvm/Support/thread.h"
-#include <algorithm>
-#include <cstdint>
-#include <cstdlib>
-#include <string>
-#include <system_error>
-
-using namespace llvm;
-using namespace llvm::dsymutil;
-using namespace object;
-
-namespace {
-enum ID {
- OPT_INVALID = 0, // This is not an option ID.
-#define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM, \
- HELPTEXT, METAVAR, VALUES) \
- OPT_##ID,
-#include "Options.inc"
-#undef OPTION
-};
-
-#define PREFIX(NAME, VALUE) const char *const NAME[] = VALUE;
-#include "Options.inc"
-#undef PREFIX
-
-const opt::OptTable::Info InfoTable[] = {
-#define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM, \
- HELPTEXT, METAVAR, VALUES) \
- { \
- PREFIX, NAME, HELPTEXT, \
- METAVAR, OPT_##ID, opt::Option::KIND##Class, \
- PARAM, FLAGS, OPT_##GROUP, \
- OPT_##ALIAS, ALIASARGS, VALUES},
-#include "Options.inc"
-#undef OPTION
-};
-
-class DsymutilOptTable : public opt::OptTable {
-public:
- DsymutilOptTable() : OptTable(InfoTable) {}
-};
-} // namespace
-
-struct DsymutilOptions {
- bool DumpDebugMap = false;
- bool DumpStab = false;
- bool Flat = false;
- bool InputIsYAMLDebugMap = false;
- bool PaperTrailWarnings = false;
- bool Verify = false;
- std::string SymbolMap;
- std::string OutputFile;
- std::string Toolchain;
- std::string ReproducerPath;
- std::vector<std::string> Archs;
- std::vector<std::string> InputFiles;
- unsigned NumThreads;
- ReproducerMode ReproMode = ReproducerMode::Off;
- dsymutil::LinkOptions LinkOpts;
-};
-
-/// Return a list of input files. This function has logic for dealing with the
-/// special case where we might have dSYM bundles as input. The function
-/// returns an error when the directory structure doesn't match that of a dSYM
-/// bundle.
-static Expected<std::vector<std::string>> getInputs(opt::InputArgList &Args,
- bool DsymAsInput) {
- std::vector<std::string> InputFiles;
- for (auto *File : Args.filtered(OPT_INPUT))
- InputFiles.push_back(File->getValue());
-
- if (!DsymAsInput)
- return InputFiles;
-
- // If we are updating, we might get dSYM bundles as input.
- std::vector<std::string> Inputs;
- for (const auto &Input : InputFiles) {
- if (!sys::fs::is_directory(Input)) {
- Inputs.push_back(Input);
- continue;
- }
-
- // Make sure that we're dealing with a dSYM bundle.
- SmallString<256> BundlePath(Input);
- sys::path::append(BundlePath, "Contents", "Resources", "DWARF");
- if (!sys::fs::is_directory(BundlePath))
- return make_error<StringError>(
- Input + " is a directory, but doesn't look like a dSYM bundle.",
- inconvertibleErrorCode());
-
- // Create a directory iterator to iterate over all the entries in the
- // bundle.
- std::error_code EC;
- sys::fs::directory_iterator DirIt(BundlePath, EC);
- sys::fs::directory_iterator DirEnd;
- if (EC)
- return errorCodeToError(EC);
-
- // Add each entry to the list of inputs.
- while (DirIt != DirEnd) {
- Inputs.push_back(DirIt->path());
- DirIt.increment(EC);
- if (EC)
- return errorCodeToError(EC);
- }
- }
- return Inputs;
-}
-
-// Verify that the given combination of options makes sense.
-static Error verifyOptions(const DsymutilOptions &Options) {
- if (Options.InputFiles.empty()) {
- return make_error<StringError>("no input files specified",
- errc::invalid_argument);
- }
-
+#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringExtras.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/Triple.h"
+#include "llvm/DebugInfo/DIContext.h"
+#include "llvm/DebugInfo/DWARF/DWARFContext.h"
+#include "llvm/DebugInfo/DWARF/DWARFVerifier.h"
+#include "llvm/Object/Binary.h"
+#include "llvm/Object/MachO.h"
+#include "llvm/Option/Arg.h"
+#include "llvm/Option/ArgList.h"
+#include "llvm/Option/Option.h"
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/FileCollector.h"
+#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/InitLLVM.h"
+#include "llvm/Support/ManagedStatic.h"
+#include "llvm/Support/Path.h"
+#include "llvm/Support/TargetSelect.h"
+#include "llvm/Support/ThreadPool.h"
+#include "llvm/Support/WithColor.h"
+#include "llvm/Support/raw_ostream.h"
+#include "llvm/Support/thread.h"
+#include <algorithm>
+#include <cstdint>
+#include <cstdlib>
+#include <string>
+#include <system_error>
+
+using namespace llvm;
+using namespace llvm::dsymutil;
+using namespace object;
+
+namespace {
+enum ID {
+ OPT_INVALID = 0, // This is not an option ID.
+#define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM, \
+ HELPTEXT, METAVAR, VALUES) \
+ OPT_##ID,
+#include "Options.inc"
+#undef OPTION
+};
+
+#define PREFIX(NAME, VALUE) const char *const NAME[] = VALUE;
+#include "Options.inc"
+#undef PREFIX
+
+const opt::OptTable::Info InfoTable[] = {
+#define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM, \
+ HELPTEXT, METAVAR, VALUES) \
+ { \
+ PREFIX, NAME, HELPTEXT, \
+ METAVAR, OPT_##ID, opt::Option::KIND##Class, \
+ PARAM, FLAGS, OPT_##GROUP, \
+ OPT_##ALIAS, ALIASARGS, VALUES},
+#include "Options.inc"
+#undef OPTION
+};
+
+class DsymutilOptTable : public opt::OptTable {
+public:
+ DsymutilOptTable() : OptTable(InfoTable) {}
+};
+} // namespace
+
+struct DsymutilOptions {
+ bool DumpDebugMap = false;
+ bool DumpStab = false;
+ bool Flat = false;
+ bool InputIsYAMLDebugMap = false;
+ bool PaperTrailWarnings = false;
+ bool Verify = false;
+ std::string SymbolMap;
+ std::string OutputFile;
+ std::string Toolchain;
+ std::string ReproducerPath;
+ std::vector<std::string> Archs;
+ std::vector<std::string> InputFiles;
+ unsigned NumThreads;
+ ReproducerMode ReproMode = ReproducerMode::Off;
+ dsymutil::LinkOptions LinkOpts;
+};
+
+/// Return a list of input files. This function has logic for dealing with the
+/// special case where we might have dSYM bundles as input. The function
+/// returns an error when the directory structure doesn't match that of a dSYM
+/// bundle.
+static Expected<std::vector<std::string>> getInputs(opt::InputArgList &Args,
+ bool DsymAsInput) {
+ std::vector<std::string> InputFiles;
+ for (auto *File : Args.filtered(OPT_INPUT))
+ InputFiles.push_back(File->getValue());
+
+ if (!DsymAsInput)
+ return InputFiles;
+
+ // If we are updating, we might get dSYM bundles as input.
+ std::vector<std::string> Inputs;
+ for (const auto &Input : InputFiles) {
+ if (!sys::fs::is_directory(Input)) {
+ Inputs.push_back(Input);
+ continue;
+ }
+
+ // Make sure that we're dealing with a dSYM bundle.
+ SmallString<256> BundlePath(Input);
+ sys::path::append(BundlePath, "Contents", "Resources", "DWARF");
+ if (!sys::fs::is_directory(BundlePath))
+ return make_error<StringError>(
+ Input + " is a directory, but doesn't look like a dSYM bundle.",
+ inconvertibleErrorCode());
+
+ // Create a directory iterator to iterate over all the entries in the
+ // bundle.
+ std::error_code EC;
+ sys::fs::directory_iterator DirIt(BundlePath, EC);
+ sys::fs::directory_iterator DirEnd;
+ if (EC)
+ return errorCodeToError(EC);
+
+ // Add each entry to the list of inputs.
+ while (DirIt != DirEnd) {
+ Inputs.push_back(DirIt->path());
+ DirIt.increment(EC);
+ if (EC)
+ return errorCodeToError(EC);
+ }
+ }
+ return Inputs;
+}
+
+// Verify that the given combination of options makes sense.
+static Error verifyOptions(const DsymutilOptions &Options) {
+ if (Options.InputFiles.empty()) {
+ return make_error<StringError>("no input files specified",
+ errc::invalid_argument);
+ }
+
if (Options.LinkOpts.Update && llvm::is_contained(Options.InputFiles, "-")) {
- // FIXME: We cannot use stdin for an update because stdin will be
- // consumed by the BinaryHolder during the debugmap parsing, and
- // then we will want to consume it again in DwarfLinker. If we
- // used a unique BinaryHolder object that could cache multiple
- // binaries this restriction would go away.
- return make_error<StringError>(
- "standard input cannot be used as input for a dSYM update.",
- errc::invalid_argument);
- }
-
- if (!Options.Flat && Options.OutputFile == "-")
- return make_error<StringError>(
- "cannot emit to standard output without --flat.",
- errc::invalid_argument);
-
- if (Options.InputFiles.size() > 1 && Options.Flat &&
- !Options.OutputFile.empty())
- return make_error<StringError>(
- "cannot use -o with multiple inputs in flat mode.",
- errc::invalid_argument);
-
- if (Options.PaperTrailWarnings && Options.InputIsYAMLDebugMap)
- return make_error<StringError>(
- "paper trail warnings are not supported for YAML input.",
- errc::invalid_argument);
-
- if (!Options.ReproducerPath.empty() &&
- Options.ReproMode != ReproducerMode::Use)
- return make_error<StringError>(
- "cannot combine --gen-reproducer and --use-reproducer.",
- errc::invalid_argument);
-
- return Error::success();
-}
-
-static Expected<AccelTableKind> getAccelTableKind(opt::InputArgList &Args) {
- if (opt::Arg *Accelerator = Args.getLastArg(OPT_accelerator)) {
- StringRef S = Accelerator->getValue();
- if (S == "Apple")
- return AccelTableKind::Apple;
- if (S == "Dwarf")
- return AccelTableKind::Dwarf;
- if (S == "Default")
- return AccelTableKind::Default;
- return make_error<StringError>(
- "invalid accelerator type specified: '" + S +
- "'. Support values are 'Apple', 'Dwarf' and 'Default'.",
- inconvertibleErrorCode());
- }
- return AccelTableKind::Default;
-}
-
-/// Parses the command line options into the LinkOptions struct and performs
-/// some sanity checking. Returns an error in case the latter fails.
-static Expected<DsymutilOptions> getOptions(opt::InputArgList &Args) {
- DsymutilOptions Options;
-
- Options.DumpDebugMap = Args.hasArg(OPT_dump_debug_map);
- Options.DumpStab = Args.hasArg(OPT_symtab);
- Options.Flat = Args.hasArg(OPT_flat);
- Options.InputIsYAMLDebugMap = Args.hasArg(OPT_yaml_input);
- Options.PaperTrailWarnings = Args.hasArg(OPT_papertrail);
- Options.Verify = Args.hasArg(OPT_verify);
-
- Options.LinkOpts.Minimize = Args.hasArg(OPT_minimize);
- Options.LinkOpts.NoODR = Args.hasArg(OPT_no_odr);
- Options.LinkOpts.NoOutput = Args.hasArg(OPT_no_output);
- Options.LinkOpts.NoTimestamp = Args.hasArg(OPT_no_swiftmodule_timestamp);
- Options.LinkOpts.Update = Args.hasArg(OPT_update);
- Options.LinkOpts.Verbose = Args.hasArg(OPT_verbose);
- Options.LinkOpts.Statistics = Args.hasArg(OPT_statistics);
-
- if (opt::Arg *ReproducerPath = Args.getLastArg(OPT_use_reproducer)) {
- Options.ReproMode = ReproducerMode::Use;
- Options.ReproducerPath = ReproducerPath->getValue();
- }
-
- if (Args.hasArg(OPT_gen_reproducer))
- Options.ReproMode = ReproducerMode::Generate;
-
- if (Expected<AccelTableKind> AccelKind = getAccelTableKind(Args)) {
- Options.LinkOpts.TheAccelTableKind = *AccelKind;
- } else {
- return AccelKind.takeError();
- }
-
- if (opt::Arg *SymbolMap = Args.getLastArg(OPT_symbolmap))
- Options.SymbolMap = SymbolMap->getValue();
-
- if (Args.hasArg(OPT_symbolmap))
- Options.LinkOpts.Update = true;
-
- if (Expected<std::vector<std::string>> InputFiles =
- getInputs(Args, Options.LinkOpts.Update)) {
- Options.InputFiles = std::move(*InputFiles);
- } else {
- return InputFiles.takeError();
- }
-
- for (auto *Arch : Args.filtered(OPT_arch))
- Options.Archs.push_back(Arch->getValue());
-
- if (opt::Arg *OsoPrependPath = Args.getLastArg(OPT_oso_prepend_path))
- Options.LinkOpts.PrependPath = OsoPrependPath->getValue();
-
- for (const auto &Arg : Args.getAllArgValues(OPT_object_prefix_map)) {
- auto Split = StringRef(Arg).split('=');
- Options.LinkOpts.ObjectPrefixMap.insert(
- {std::string(Split.first), std::string(Split.second)});
- }
-
- if (opt::Arg *OutputFile = Args.getLastArg(OPT_output))
- Options.OutputFile = OutputFile->getValue();
-
- if (opt::Arg *Toolchain = Args.getLastArg(OPT_toolchain))
- Options.Toolchain = Toolchain->getValue();
-
- if (Args.hasArg(OPT_assembly))
- Options.LinkOpts.FileType = OutputFileType::Assembly;
-
- if (opt::Arg *NumThreads = Args.getLastArg(OPT_threads))
- Options.LinkOpts.Threads = atoi(NumThreads->getValue());
- else
- Options.LinkOpts.Threads = 0; // Use all available hardware threads
-
- if (Options.DumpDebugMap || Options.LinkOpts.Verbose)
- Options.LinkOpts.Threads = 1;
-
- if (getenv("RC_DEBUG_OPTIONS"))
- Options.PaperTrailWarnings = true;
-
- if (opt::Arg *RemarksPrependPath = Args.getLastArg(OPT_remarks_prepend_path))
- Options.LinkOpts.RemarksPrependPath = RemarksPrependPath->getValue();
-
- if (opt::Arg *RemarksOutputFormat =
- Args.getLastArg(OPT_remarks_output_format)) {
- if (Expected<remarks::Format> FormatOrErr =
- remarks::parseFormat(RemarksOutputFormat->getValue()))
- Options.LinkOpts.RemarksFormat = *FormatOrErr;
- else
- return FormatOrErr.takeError();
- }
-
- if (Error E = verifyOptions(Options))
- return std::move(E);
- return Options;
-}
-
-static Error createPlistFile(StringRef Bin, StringRef BundleRoot,
- StringRef Toolchain) {
- // Create plist file to write to.
- SmallString<128> InfoPlist(BundleRoot);
- sys::path::append(InfoPlist, "Contents/Info.plist");
- std::error_code EC;
- raw_fd_ostream PL(InfoPlist, EC, sys::fs::OF_Text);
- if (EC)
- return make_error<StringError>(
- "cannot create Plist: " + toString(errorCodeToError(EC)), EC);
-
- CFBundleInfo BI = getBundleInfo(Bin);
-
- if (BI.IDStr.empty()) {
- StringRef BundleID = *sys::path::rbegin(BundleRoot);
- if (sys::path::extension(BundleRoot) == ".dSYM")
- BI.IDStr = std::string(sys::path::stem(BundleID));
- else
- BI.IDStr = std::string(BundleID);
- }
-
- // Print out information to the plist file.
- PL << "<?xml version=\"1.0\" encoding=\"UTF-8\"\?>\n"
- << "<!DOCTYPE plist PUBLIC \"-//Apple Computer//DTD PLIST 1.0//EN\" "
- << "\"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n"
- << "<plist version=\"1.0\">\n"
- << "\t<dict>\n"
- << "\t\t<key>CFBundleDevelopmentRegion</key>\n"
- << "\t\t<string>English</string>\n"
- << "\t\t<key>CFBundleIdentifier</key>\n"
- << "\t\t<string>com.apple.xcode.dsym.";
- printHTMLEscaped(BI.IDStr, PL);
- PL << "</string>\n"
- << "\t\t<key>CFBundleInfoDictionaryVersion</key>\n"
- << "\t\t<string>6.0</string>\n"
- << "\t\t<key>CFBundlePackageType</key>\n"
- << "\t\t<string>dSYM</string>\n"
- << "\t\t<key>CFBundleSignature</key>\n"
- << "\t\t<string>\?\?\?\?</string>\n";
-
- if (!BI.OmitShortVersion()) {
- PL << "\t\t<key>CFBundleShortVersionString</key>\n";
- PL << "\t\t<string>";
- printHTMLEscaped(BI.ShortVersionStr, PL);
- PL << "</string>\n";
- }
-
- PL << "\t\t<key>CFBundleVersion</key>\n";
- PL << "\t\t<string>";
- printHTMLEscaped(BI.VersionStr, PL);
- PL << "</string>\n";
-
- if (!Toolchain.empty()) {
- PL << "\t\t<key>Toolchain</key>\n";
- PL << "\t\t<string>";
- printHTMLEscaped(Toolchain, PL);
- PL << "</string>\n";
- }
-
- PL << "\t</dict>\n"
- << "</plist>\n";
-
- PL.close();
- return Error::success();
-}
-
-static Error createBundleDir(StringRef BundleBase) {
- SmallString<128> Bundle(BundleBase);
- sys::path::append(Bundle, "Contents", "Resources", "DWARF");
- if (std::error_code EC =
- create_directories(Bundle.str(), true, sys::fs::perms::all_all))
- return make_error<StringError>(
- "cannot create bundle: " + toString(errorCodeToError(EC)), EC);
-
- return Error::success();
-}
-
-static bool verify(StringRef OutputFile, StringRef Arch, bool Verbose) {
- if (OutputFile == "-") {
- WithColor::warning() << "verification skipped for " << Arch
- << "because writing to stdout.\n";
- return true;
- }
-
- Expected<OwningBinary<Binary>> BinOrErr = createBinary(OutputFile);
- if (!BinOrErr) {
- WithColor::error() << OutputFile << ": " << toString(BinOrErr.takeError());
- return false;
- }
-
- Binary &Binary = *BinOrErr.get().getBinary();
- if (auto *Obj = dyn_cast<MachOObjectFile>(&Binary)) {
- raw_ostream &os = Verbose ? errs() : nulls();
- os << "Verifying DWARF for architecture: " << Arch << "\n";
- std::unique_ptr<DWARFContext> DICtx = DWARFContext::create(*Obj);
- DIDumpOptions DumpOpts;
- bool success = DICtx->verify(os, DumpOpts.noImplicitRecursion());
- if (!success)
- WithColor::error() << "verification failed for " << Arch << '\n';
- return success;
- }
-
- return false;
-}
-
-namespace {
-struct OutputLocation {
- OutputLocation(std::string DWARFFile, Optional<std::string> ResourceDir = {})
- : DWARFFile(DWARFFile), ResourceDir(ResourceDir) {}
- /// This method is a workaround for older compilers.
- Optional<std::string> getResourceDir() const { return ResourceDir; }
- std::string DWARFFile;
- Optional<std::string> ResourceDir;
-};
-} // namespace
-
-static Expected<OutputLocation>
-getOutputFileName(StringRef InputFile, const DsymutilOptions &Options) {
- if (Options.OutputFile == "-")
- return OutputLocation(Options.OutputFile);
-
- // When updating, do in place replacement.
- if (Options.OutputFile.empty() &&
- (Options.LinkOpts.Update || !Options.SymbolMap.empty()))
- return OutputLocation(std::string(InputFile));
-
- // If a flat dSYM has been requested, things are pretty simple.
- if (Options.Flat) {
- if (Options.OutputFile.empty()) {
- if (InputFile == "-")
- return OutputLocation{"a.out.dwarf", {}};
- return OutputLocation((InputFile + ".dwarf").str());
- }
-
- return OutputLocation(Options.OutputFile);
- }
-
- // We need to create/update a dSYM bundle.
- // A bundle hierarchy looks like this:
- // <bundle name>.dSYM/
- // Contents/
- // Info.plist
- // Resources/
- // DWARF/
- // <DWARF file(s)>
- std::string DwarfFile =
- std::string(InputFile == "-" ? StringRef("a.out") : InputFile);
- SmallString<128> Path(Options.OutputFile);
- if (Path.empty())
- Path = DwarfFile + ".dSYM";
- if (!Options.LinkOpts.NoOutput) {
- if (auto E = createBundleDir(Path))
- return std::move(E);
- if (auto E = createPlistFile(DwarfFile, Path, Options.Toolchain))
- return std::move(E);
- }
-
- sys::path::append(Path, "Contents", "Resources");
- std::string ResourceDir = std::string(Path.str());
- sys::path::append(Path, "DWARF", sys::path::filename(DwarfFile));
- return OutputLocation(std::string(Path.str()), ResourceDir);
-}
-
-int main(int argc, char **argv) {
- InitLLVM X(argc, argv);
-
- // Parse arguments.
- DsymutilOptTable T;
- unsigned MAI;
- unsigned MAC;
- ArrayRef<const char *> ArgsArr = makeArrayRef(argv + 1, argc - 1);
- opt::InputArgList Args = T.ParseArgs(ArgsArr, MAI, MAC);
-
- void *P = (void *)(intptr_t)getOutputFileName;
- std::string SDKPath = sys::fs::getMainExecutable(argv[0], P);
- SDKPath = std::string(sys::path::parent_path(SDKPath));
-
- for (auto *Arg : Args.filtered(OPT_UNKNOWN)) {
- WithColor::warning() << "ignoring unknown option: " << Arg->getSpelling()
- << '\n';
- }
-
- if (Args.hasArg(OPT_help)) {
- T.PrintHelp(
- outs(), (std::string(argv[0]) + " [options] <input files>").c_str(),
- "manipulate archived DWARF debug symbol files.\n\n"
- "dsymutil links the DWARF debug information found in the object files\n"
- "for the executable <input file> by using debug symbols information\n"
- "contained in its symbol table.\n",
- false);
- return 0;
- }
-
- if (Args.hasArg(OPT_version)) {
- cl::PrintVersionMessage();
- return 0;
- }
-
- auto OptionsOrErr = getOptions(Args);
- if (!OptionsOrErr) {
- WithColor::error() << toString(OptionsOrErr.takeError());
- return 1;
- }
-
- auto &Options = *OptionsOrErr;
-
- InitializeAllTargetInfos();
- InitializeAllTargetMCs();
- InitializeAllTargets();
- InitializeAllAsmPrinters();
-
- auto Repro =
- Reproducer::createReproducer(Options.ReproMode, Options.ReproducerPath);
- if (!Repro) {
- WithColor::error() << toString(Repro.takeError());
- return 1;
- }
-
- Options.LinkOpts.VFS = (*Repro)->getVFS();
-
- for (const auto &Arch : Options.Archs)
- if (Arch != "*" && Arch != "all" &&
- !object::MachOObjectFile::isValidArch(Arch)) {
- WithColor::error() << "unsupported cpu architecture: '" << Arch << "'\n";
- return 1;
- }
-
- SymbolMapLoader SymMapLoader(Options.SymbolMap);
-
- for (auto &InputFile : Options.InputFiles) {
- // Dump the symbol table for each input file and requested arch
- if (Options.DumpStab) {
- if (!dumpStab(Options.LinkOpts.VFS, InputFile, Options.Archs,
- Options.LinkOpts.PrependPath))
- return 1;
- continue;
- }
-
- auto DebugMapPtrsOrErr =
- parseDebugMap(Options.LinkOpts.VFS, InputFile, Options.Archs,
- Options.LinkOpts.PrependPath, Options.PaperTrailWarnings,
- Options.LinkOpts.Verbose, Options.InputIsYAMLDebugMap);
-
- if (auto EC = DebugMapPtrsOrErr.getError()) {
- WithColor::error() << "cannot parse the debug map for '" << InputFile
- << "': " << EC.message() << '\n';
- return 1;
- }
-
- // Remember the number of debug maps that are being processed to decide how
- // to name the remark files.
- Options.LinkOpts.NumDebugMaps = DebugMapPtrsOrErr->size();
-
- if (Options.LinkOpts.Update) {
- // The debug map should be empty. Add one object file corresponding to
- // the input file.
- for (auto &Map : *DebugMapPtrsOrErr)
- Map->addDebugMapObject(InputFile,
- sys::TimePoint<std::chrono::seconds>());
- }
-
- // Ensure that the debug map is not empty (anymore).
- if (DebugMapPtrsOrErr->empty()) {
- WithColor::error() << "no architecture to link\n";
- return 1;
- }
-
- // Shared a single binary holder for all the link steps.
- BinaryHolder BinHolder(Options.LinkOpts.VFS);
-
- // Statistics only require different architectures to be processed
- // sequentially, the link itself can still happen in parallel. Change the
- // thread pool strategy here instead of modifying LinkOpts.Threads.
- ThreadPoolStrategy S = hardware_concurrency(
- Options.LinkOpts.Statistics ? 1 : Options.LinkOpts.Threads);
- if (Options.LinkOpts.Threads == 0) {
- // If NumThreads is not specified, create one thread for each input, up to
- // the number of hardware threads.
- S.ThreadsRequested = DebugMapPtrsOrErr->size();
- S.Limit = true;
- }
- ThreadPool Threads(S);
-
- // If there is more than one link to execute, we need to generate
- // temporary files.
- const bool NeedsTempFiles =
- !Options.DumpDebugMap && (Options.OutputFile != "-") &&
- (DebugMapPtrsOrErr->size() != 1 || Options.LinkOpts.Update);
- const bool Verify = Options.Verify && !Options.LinkOpts.NoOutput;
-
- SmallVector<MachOUtils::ArchAndFile, 4> TempFiles;
- std::atomic_char AllOK(1);
- for (auto &Map : *DebugMapPtrsOrErr) {
- if (Options.LinkOpts.Verbose || Options.DumpDebugMap)
- Map->print(outs());
-
- if (Options.DumpDebugMap)
- continue;
-
- if (!Options.SymbolMap.empty())
- Options.LinkOpts.Translator = SymMapLoader.Load(InputFile, *Map);
-
- if (Map->begin() == Map->end())
- WithColor::warning()
- << "no debug symbols in executable (-arch "
- << MachOUtils::getArchName(Map->getTriple().getArchName()) << ")\n";
-
- // Using a std::shared_ptr rather than std::unique_ptr because move-only
- // types don't work with std::bind in the ThreadPool implementation.
- std::shared_ptr<raw_fd_ostream> OS;
-
- Expected<OutputLocation> OutputLocationOrErr =
- getOutputFileName(InputFile, Options);
- if (!OutputLocationOrErr) {
- WithColor::error() << toString(OutputLocationOrErr.takeError());
- return 1;
- }
- Options.LinkOpts.ResourceDir = OutputLocationOrErr->getResourceDir();
-
- std::string OutputFile = OutputLocationOrErr->DWARFFile;
- if (NeedsTempFiles) {
- TempFiles.emplace_back(Map->getTriple().getArchName().str());
-
- auto E = TempFiles.back().createTempFile();
- if (E) {
- WithColor::error() << toString(std::move(E));
- return 1;
- }
-
- auto &TempFile = *(TempFiles.back().File);
- OS = std::make_shared<raw_fd_ostream>(TempFile.FD,
- /*shouldClose*/ false);
- OutputFile = TempFile.TmpName;
- } else {
- std::error_code EC;
- OS = std::make_shared<raw_fd_ostream>(
- Options.LinkOpts.NoOutput ? "-" : OutputFile, EC, sys::fs::OF_None);
- if (EC) {
- WithColor::error() << OutputFile << ": " << EC.message();
- return 1;
- }
- }
-
- auto LinkLambda = [&, OutputFile](std::shared_ptr<raw_fd_ostream> Stream,
- LinkOptions Options) {
- AllOK.fetch_and(
- linkDwarf(*Stream, BinHolder, *Map, std::move(Options)));
- Stream->flush();
- if (Verify)
- AllOK.fetch_and(verify(OutputFile, Map->getTriple().getArchName(),
- Options.Verbose));
- };
-
- // FIXME: The DwarfLinker can have some very deep recursion that can max
- // out the (significantly smaller) stack when using threads. We don't
- // want this limitation when we only have a single thread.
- if (S.ThreadsRequested == 1)
- LinkLambda(OS, Options.LinkOpts);
- else
- Threads.async(LinkLambda, OS, Options.LinkOpts);
- }
-
- Threads.wait();
-
- if (!AllOK)
- return 1;
-
- if (NeedsTempFiles) {
- Expected<OutputLocation> OutputLocationOrErr =
- getOutputFileName(InputFile, Options);
- if (!OutputLocationOrErr) {
- WithColor::error() << toString(OutputLocationOrErr.takeError());
- return 1;
- }
- if (!MachOUtils::generateUniversalBinary(TempFiles,
- OutputLocationOrErr->DWARFFile,
- Options.LinkOpts, SDKPath))
- return 1;
- }
- }
-
- return 0;
-}
+ // FIXME: We cannot use stdin for an update because stdin will be
+ // consumed by the BinaryHolder during the debugmap parsing, and
+ // then we will want to consume it again in DwarfLinker. If we
+ // used a unique BinaryHolder object that could cache multiple
+ // binaries this restriction would go away.
+ return make_error<StringError>(
+ "standard input cannot be used as input for a dSYM update.",
+ errc::invalid_argument);
+ }
+
+ if (!Options.Flat && Options.OutputFile == "-")
+ return make_error<StringError>(
+ "cannot emit to standard output without --flat.",
+ errc::invalid_argument);
+
+ if (Options.InputFiles.size() > 1 && Options.Flat &&
+ !Options.OutputFile.empty())
+ return make_error<StringError>(
+ "cannot use -o with multiple inputs in flat mode.",
+ errc::invalid_argument);
+
+ if (Options.PaperTrailWarnings && Options.InputIsYAMLDebugMap)
+ return make_error<StringError>(
+ "paper trail warnings are not supported for YAML input.",
+ errc::invalid_argument);
+
+ if (!Options.ReproducerPath.empty() &&
+ Options.ReproMode != ReproducerMode::Use)
+ return make_error<StringError>(
+ "cannot combine --gen-reproducer and --use-reproducer.",
+ errc::invalid_argument);
+
+ return Error::success();
+}
+
+static Expected<AccelTableKind> getAccelTableKind(opt::InputArgList &Args) {
+ if (opt::Arg *Accelerator = Args.getLastArg(OPT_accelerator)) {
+ StringRef S = Accelerator->getValue();
+ if (S == "Apple")
+ return AccelTableKind::Apple;
+ if (S == "Dwarf")
+ return AccelTableKind::Dwarf;
+ if (S == "Default")
+ return AccelTableKind::Default;
+ return make_error<StringError>(
+ "invalid accelerator type specified: '" + S +
+ "'. Support values are 'Apple', 'Dwarf' and 'Default'.",
+ inconvertibleErrorCode());
+ }
+ return AccelTableKind::Default;
+}
+
+/// Parses the command line options into the LinkOptions struct and performs
+/// some sanity checking. Returns an error in case the latter fails.
+static Expected<DsymutilOptions> getOptions(opt::InputArgList &Args) {
+ DsymutilOptions Options;
+
+ Options.DumpDebugMap = Args.hasArg(OPT_dump_debug_map);
+ Options.DumpStab = Args.hasArg(OPT_symtab);
+ Options.Flat = Args.hasArg(OPT_flat);
+ Options.InputIsYAMLDebugMap = Args.hasArg(OPT_yaml_input);
+ Options.PaperTrailWarnings = Args.hasArg(OPT_papertrail);
+ Options.Verify = Args.hasArg(OPT_verify);
+
+ Options.LinkOpts.Minimize = Args.hasArg(OPT_minimize);
+ Options.LinkOpts.NoODR = Args.hasArg(OPT_no_odr);
+ Options.LinkOpts.NoOutput = Args.hasArg(OPT_no_output);
+ Options.LinkOpts.NoTimestamp = Args.hasArg(OPT_no_swiftmodule_timestamp);
+ Options.LinkOpts.Update = Args.hasArg(OPT_update);
+ Options.LinkOpts.Verbose = Args.hasArg(OPT_verbose);
+ Options.LinkOpts.Statistics = Args.hasArg(OPT_statistics);
+
+ if (opt::Arg *ReproducerPath = Args.getLastArg(OPT_use_reproducer)) {
+ Options.ReproMode = ReproducerMode::Use;
+ Options.ReproducerPath = ReproducerPath->getValue();
+ }
+
+ if (Args.hasArg(OPT_gen_reproducer))
+ Options.ReproMode = ReproducerMode::Generate;
+
+ if (Expected<AccelTableKind> AccelKind = getAccelTableKind(Args)) {
+ Options.LinkOpts.TheAccelTableKind = *AccelKind;
+ } else {
+ return AccelKind.takeError();
+ }
+
+ if (opt::Arg *SymbolMap = Args.getLastArg(OPT_symbolmap))
+ Options.SymbolMap = SymbolMap->getValue();
+
+ if (Args.hasArg(OPT_symbolmap))
+ Options.LinkOpts.Update = true;
+
+ if (Expected<std::vector<std::string>> InputFiles =
+ getInputs(Args, Options.LinkOpts.Update)) {
+ Options.InputFiles = std::move(*InputFiles);
+ } else {
+ return InputFiles.takeError();
+ }
+
+ for (auto *Arch : Args.filtered(OPT_arch))
+ Options.Archs.push_back(Arch->getValue());
+
+ if (opt::Arg *OsoPrependPath = Args.getLastArg(OPT_oso_prepend_path))
+ Options.LinkOpts.PrependPath = OsoPrependPath->getValue();
+
+ for (const auto &Arg : Args.getAllArgValues(OPT_object_prefix_map)) {
+ auto Split = StringRef(Arg).split('=');
+ Options.LinkOpts.ObjectPrefixMap.insert(
+ {std::string(Split.first), std::string(Split.second)});
+ }
+
+ if (opt::Arg *OutputFile = Args.getLastArg(OPT_output))
+ Options.OutputFile = OutputFile->getValue();
+
+ if (opt::Arg *Toolchain = Args.getLastArg(OPT_toolchain))
+ Options.Toolchain = Toolchain->getValue();
+
+ if (Args.hasArg(OPT_assembly))
+ Options.LinkOpts.FileType = OutputFileType::Assembly;
+
+ if (opt::Arg *NumThreads = Args.getLastArg(OPT_threads))
+ Options.LinkOpts.Threads = atoi(NumThreads->getValue());
+ else
+ Options.LinkOpts.Threads = 0; // Use all available hardware threads
+
+ if (Options.DumpDebugMap || Options.LinkOpts.Verbose)
+ Options.LinkOpts.Threads = 1;
+
+ if (getenv("RC_DEBUG_OPTIONS"))
+ Options.PaperTrailWarnings = true;
+
+ if (opt::Arg *RemarksPrependPath = Args.getLastArg(OPT_remarks_prepend_path))
+ Options.LinkOpts.RemarksPrependPath = RemarksPrependPath->getValue();
+
+ if (opt::Arg *RemarksOutputFormat =
+ Args.getLastArg(OPT_remarks_output_format)) {
+ if (Expected<remarks::Format> FormatOrErr =
+ remarks::parseFormat(RemarksOutputFormat->getValue()))
+ Options.LinkOpts.RemarksFormat = *FormatOrErr;
+ else
+ return FormatOrErr.takeError();
+ }
+
+ if (Error E = verifyOptions(Options))
+ return std::move(E);
+ return Options;
+}
+
+static Error createPlistFile(StringRef Bin, StringRef BundleRoot,
+ StringRef Toolchain) {
+ // Create plist file to write to.
+ SmallString<128> InfoPlist(BundleRoot);
+ sys::path::append(InfoPlist, "Contents/Info.plist");
+ std::error_code EC;
+ raw_fd_ostream PL(InfoPlist, EC, sys::fs::OF_Text);
+ if (EC)
+ return make_error<StringError>(
+ "cannot create Plist: " + toString(errorCodeToError(EC)), EC);
+
+ CFBundleInfo BI = getBundleInfo(Bin);
+
+ if (BI.IDStr.empty()) {
+ StringRef BundleID = *sys::path::rbegin(BundleRoot);
+ if (sys::path::extension(BundleRoot) == ".dSYM")
+ BI.IDStr = std::string(sys::path::stem(BundleID));
+ else
+ BI.IDStr = std::string(BundleID);
+ }
+
+ // Print out information to the plist file.
+ PL << "<?xml version=\"1.0\" encoding=\"UTF-8\"\?>\n"
+ << "<!DOCTYPE plist PUBLIC \"-//Apple Computer//DTD PLIST 1.0//EN\" "
+ << "\"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n"
+ << "<plist version=\"1.0\">\n"
+ << "\t<dict>\n"
+ << "\t\t<key>CFBundleDevelopmentRegion</key>\n"
+ << "\t\t<string>English</string>\n"
+ << "\t\t<key>CFBundleIdentifier</key>\n"
+ << "\t\t<string>com.apple.xcode.dsym.";
+ printHTMLEscaped(BI.IDStr, PL);
+ PL << "</string>\n"
+ << "\t\t<key>CFBundleInfoDictionaryVersion</key>\n"
+ << "\t\t<string>6.0</string>\n"
+ << "\t\t<key>CFBundlePackageType</key>\n"
+ << "\t\t<string>dSYM</string>\n"
+ << "\t\t<key>CFBundleSignature</key>\n"
+ << "\t\t<string>\?\?\?\?</string>\n";
+
+ if (!BI.OmitShortVersion()) {
+ PL << "\t\t<key>CFBundleShortVersionString</key>\n";
+ PL << "\t\t<string>";
+ printHTMLEscaped(BI.ShortVersionStr, PL);
+ PL << "</string>\n";
+ }
+
+ PL << "\t\t<key>CFBundleVersion</key>\n";
+ PL << "\t\t<string>";
+ printHTMLEscaped(BI.VersionStr, PL);
+ PL << "</string>\n";
+
+ if (!Toolchain.empty()) {
+ PL << "\t\t<key>Toolchain</key>\n";
+ PL << "\t\t<string>";
+ printHTMLEscaped(Toolchain, PL);
+ PL << "</string>\n";
+ }
+
+ PL << "\t</dict>\n"
+ << "</plist>\n";
+
+ PL.close();
+ return Error::success();
+}
+
+static Error createBundleDir(StringRef BundleBase) {
+ SmallString<128> Bundle(BundleBase);
+ sys::path::append(Bundle, "Contents", "Resources", "DWARF");
+ if (std::error_code EC =
+ create_directories(Bundle.str(), true, sys::fs::perms::all_all))
+ return make_error<StringError>(
+ "cannot create bundle: " + toString(errorCodeToError(EC)), EC);
+
+ return Error::success();
+}
+
+static bool verify(StringRef OutputFile, StringRef Arch, bool Verbose) {
+ if (OutputFile == "-") {
+ WithColor::warning() << "verification skipped for " << Arch
+ << "because writing to stdout.\n";
+ return true;
+ }
+
+ Expected<OwningBinary<Binary>> BinOrErr = createBinary(OutputFile);
+ if (!BinOrErr) {
+ WithColor::error() << OutputFile << ": " << toString(BinOrErr.takeError());
+ return false;
+ }
+
+ Binary &Binary = *BinOrErr.get().getBinary();
+ if (auto *Obj = dyn_cast<MachOObjectFile>(&Binary)) {
+ raw_ostream &os = Verbose ? errs() : nulls();
+ os << "Verifying DWARF for architecture: " << Arch << "\n";
+ std::unique_ptr<DWARFContext> DICtx = DWARFContext::create(*Obj);
+ DIDumpOptions DumpOpts;
+ bool success = DICtx->verify(os, DumpOpts.noImplicitRecursion());
+ if (!success)
+ WithColor::error() << "verification failed for " << Arch << '\n';
+ return success;
+ }
+
+ return false;
+}
+
+namespace {
+struct OutputLocation {
+ OutputLocation(std::string DWARFFile, Optional<std::string> ResourceDir = {})
+ : DWARFFile(DWARFFile), ResourceDir(ResourceDir) {}
+ /// This method is a workaround for older compilers.
+ Optional<std::string> getResourceDir() const { return ResourceDir; }
+ std::string DWARFFile;
+ Optional<std::string> ResourceDir;
+};
+} // namespace
+
+static Expected<OutputLocation>
+getOutputFileName(StringRef InputFile, const DsymutilOptions &Options) {
+ if (Options.OutputFile == "-")
+ return OutputLocation(Options.OutputFile);
+
+ // When updating, do in place replacement.
+ if (Options.OutputFile.empty() &&
+ (Options.LinkOpts.Update || !Options.SymbolMap.empty()))
+ return OutputLocation(std::string(InputFile));
+
+ // If a flat dSYM has been requested, things are pretty simple.
+ if (Options.Flat) {
+ if (Options.OutputFile.empty()) {
+ if (InputFile == "-")
+ return OutputLocation{"a.out.dwarf", {}};
+ return OutputLocation((InputFile + ".dwarf").str());
+ }
+
+ return OutputLocation(Options.OutputFile);
+ }
+
+ // We need to create/update a dSYM bundle.
+ // A bundle hierarchy looks like this:
+ // <bundle name>.dSYM/
+ // Contents/
+ // Info.plist
+ // Resources/
+ // DWARF/
+ // <DWARF file(s)>
+ std::string DwarfFile =
+ std::string(InputFile == "-" ? StringRef("a.out") : InputFile);
+ SmallString<128> Path(Options.OutputFile);
+ if (Path.empty())
+ Path = DwarfFile + ".dSYM";
+ if (!Options.LinkOpts.NoOutput) {
+ if (auto E = createBundleDir(Path))
+ return std::move(E);
+ if (auto E = createPlistFile(DwarfFile, Path, Options.Toolchain))
+ return std::move(E);
+ }
+
+ sys::path::append(Path, "Contents", "Resources");
+ std::string ResourceDir = std::string(Path.str());
+ sys::path::append(Path, "DWARF", sys::path::filename(DwarfFile));
+ return OutputLocation(std::string(Path.str()), ResourceDir);
+}
+
+int main(int argc, char **argv) {
+ InitLLVM X(argc, argv);
+
+ // Parse arguments.
+ DsymutilOptTable T;
+ unsigned MAI;
+ unsigned MAC;
+ ArrayRef<const char *> ArgsArr = makeArrayRef(argv + 1, argc - 1);
+ opt::InputArgList Args = T.ParseArgs(ArgsArr, MAI, MAC);
+
+ void *P = (void *)(intptr_t)getOutputFileName;
+ std::string SDKPath = sys::fs::getMainExecutable(argv[0], P);
+ SDKPath = std::string(sys::path::parent_path(SDKPath));
+
+ for (auto *Arg : Args.filtered(OPT_UNKNOWN)) {
+ WithColor::warning() << "ignoring unknown option: " << Arg->getSpelling()
+ << '\n';
+ }
+
+ if (Args.hasArg(OPT_help)) {
+ T.PrintHelp(
+ outs(), (std::string(argv[0]) + " [options] <input files>").c_str(),
+ "manipulate archived DWARF debug symbol files.\n\n"
+ "dsymutil links the DWARF debug information found in the object files\n"
+ "for the executable <input file> by using debug symbols information\n"
+ "contained in its symbol table.\n",
+ false);
+ return 0;
+ }
+
+ if (Args.hasArg(OPT_version)) {
+ cl::PrintVersionMessage();
+ return 0;
+ }
+
+ auto OptionsOrErr = getOptions(Args);
+ if (!OptionsOrErr) {
+ WithColor::error() << toString(OptionsOrErr.takeError());
+ return 1;
+ }
+
+ auto &Options = *OptionsOrErr;
+
+ InitializeAllTargetInfos();
+ InitializeAllTargetMCs();
+ InitializeAllTargets();
+ InitializeAllAsmPrinters();
+
+ auto Repro =
+ Reproducer::createReproducer(Options.ReproMode, Options.ReproducerPath);
+ if (!Repro) {
+ WithColor::error() << toString(Repro.takeError());
+ return 1;
+ }
+
+ Options.LinkOpts.VFS = (*Repro)->getVFS();
+
+ for (const auto &Arch : Options.Archs)
+ if (Arch != "*" && Arch != "all" &&
+ !object::MachOObjectFile::isValidArch(Arch)) {
+ WithColor::error() << "unsupported cpu architecture: '" << Arch << "'\n";
+ return 1;
+ }
+
+ SymbolMapLoader SymMapLoader(Options.SymbolMap);
+
+ for (auto &InputFile : Options.InputFiles) {
+ // Dump the symbol table for each input file and requested arch
+ if (Options.DumpStab) {
+ if (!dumpStab(Options.LinkOpts.VFS, InputFile, Options.Archs,
+ Options.LinkOpts.PrependPath))
+ return 1;
+ continue;
+ }
+
+ auto DebugMapPtrsOrErr =
+ parseDebugMap(Options.LinkOpts.VFS, InputFile, Options.Archs,
+ Options.LinkOpts.PrependPath, Options.PaperTrailWarnings,
+ Options.LinkOpts.Verbose, Options.InputIsYAMLDebugMap);
+
+ if (auto EC = DebugMapPtrsOrErr.getError()) {
+ WithColor::error() << "cannot parse the debug map for '" << InputFile
+ << "': " << EC.message() << '\n';
+ return 1;
+ }
+
+ // Remember the number of debug maps that are being processed to decide how
+ // to name the remark files.
+ Options.LinkOpts.NumDebugMaps = DebugMapPtrsOrErr->size();
+
+ if (Options.LinkOpts.Update) {
+ // The debug map should be empty. Add one object file corresponding to
+ // the input file.
+ for (auto &Map : *DebugMapPtrsOrErr)
+ Map->addDebugMapObject(InputFile,
+ sys::TimePoint<std::chrono::seconds>());
+ }
+
+ // Ensure that the debug map is not empty (anymore).
+ if (DebugMapPtrsOrErr->empty()) {
+ WithColor::error() << "no architecture to link\n";
+ return 1;
+ }
+
+ // Shared a single binary holder for all the link steps.
+ BinaryHolder BinHolder(Options.LinkOpts.VFS);
+
+ // Statistics only require different architectures to be processed
+ // sequentially, the link itself can still happen in parallel. Change the
+ // thread pool strategy here instead of modifying LinkOpts.Threads.
+ ThreadPoolStrategy S = hardware_concurrency(
+ Options.LinkOpts.Statistics ? 1 : Options.LinkOpts.Threads);
+ if (Options.LinkOpts.Threads == 0) {
+ // If NumThreads is not specified, create one thread for each input, up to
+ // the number of hardware threads.
+ S.ThreadsRequested = DebugMapPtrsOrErr->size();
+ S.Limit = true;
+ }
+ ThreadPool Threads(S);
+
+ // If there is more than one link to execute, we need to generate
+ // temporary files.
+ const bool NeedsTempFiles =
+ !Options.DumpDebugMap && (Options.OutputFile != "-") &&
+ (DebugMapPtrsOrErr->size() != 1 || Options.LinkOpts.Update);
+ const bool Verify = Options.Verify && !Options.LinkOpts.NoOutput;
+
+ SmallVector<MachOUtils::ArchAndFile, 4> TempFiles;
+ std::atomic_char AllOK(1);
+ for (auto &Map : *DebugMapPtrsOrErr) {
+ if (Options.LinkOpts.Verbose || Options.DumpDebugMap)
+ Map->print(outs());
+
+ if (Options.DumpDebugMap)
+ continue;
+
+ if (!Options.SymbolMap.empty())
+ Options.LinkOpts.Translator = SymMapLoader.Load(InputFile, *Map);
+
+ if (Map->begin() == Map->end())
+ WithColor::warning()
+ << "no debug symbols in executable (-arch "
+ << MachOUtils::getArchName(Map->getTriple().getArchName()) << ")\n";
+
+ // Using a std::shared_ptr rather than std::unique_ptr because move-only
+ // types don't work with std::bind in the ThreadPool implementation.
+ std::shared_ptr<raw_fd_ostream> OS;
+
+ Expected<OutputLocation> OutputLocationOrErr =
+ getOutputFileName(InputFile, Options);
+ if (!OutputLocationOrErr) {
+ WithColor::error() << toString(OutputLocationOrErr.takeError());
+ return 1;
+ }
+ Options.LinkOpts.ResourceDir = OutputLocationOrErr->getResourceDir();
+
+ std::string OutputFile = OutputLocationOrErr->DWARFFile;
+ if (NeedsTempFiles) {
+ TempFiles.emplace_back(Map->getTriple().getArchName().str());
+
+ auto E = TempFiles.back().createTempFile();
+ if (E) {
+ WithColor::error() << toString(std::move(E));
+ return 1;
+ }
+
+ auto &TempFile = *(TempFiles.back().File);
+ OS = std::make_shared<raw_fd_ostream>(TempFile.FD,
+ /*shouldClose*/ false);
+ OutputFile = TempFile.TmpName;
+ } else {
+ std::error_code EC;
+ OS = std::make_shared<raw_fd_ostream>(
+ Options.LinkOpts.NoOutput ? "-" : OutputFile, EC, sys::fs::OF_None);
+ if (EC) {
+ WithColor::error() << OutputFile << ": " << EC.message();
+ return 1;
+ }
+ }
+
+ auto LinkLambda = [&, OutputFile](std::shared_ptr<raw_fd_ostream> Stream,
+ LinkOptions Options) {
+ AllOK.fetch_and(
+ linkDwarf(*Stream, BinHolder, *Map, std::move(Options)));
+ Stream->flush();
+ if (Verify)
+ AllOK.fetch_and(verify(OutputFile, Map->getTriple().getArchName(),
+ Options.Verbose));
+ };
+
+ // FIXME: The DwarfLinker can have some very deep recursion that can max
+ // out the (significantly smaller) stack when using threads. We don't
+ // want this limitation when we only have a single thread.
+ if (S.ThreadsRequested == 1)
+ LinkLambda(OS, Options.LinkOpts);
+ else
+ Threads.async(LinkLambda, OS, Options.LinkOpts);
+ }
+
+ Threads.wait();
+
+ if (!AllOK)
+ return 1;
+
+ if (NeedsTempFiles) {
+ Expected<OutputLocation> OutputLocationOrErr =
+ getOutputFileName(InputFile, Options);
+ if (!OutputLocationOrErr) {
+ WithColor::error() << toString(OutputLocationOrErr.takeError());
+ return 1;
+ }
+ if (!MachOUtils::generateUniversalBinary(TempFiles,
+ OutputLocationOrErr->DWARFFile,
+ Options.LinkOpts, SDKPath))
+ return 1;
+ }
+ }
+
+ return 0;
+}
diff --git a/contrib/libs/llvm12/tools/dsymutil/dsymutil.h b/contrib/libs/llvm12/tools/dsymutil/dsymutil.h
index f88f57bb20..7080b1bf3b 100644
--- a/contrib/libs/llvm12/tools/dsymutil/dsymutil.h
+++ b/contrib/libs/llvm12/tools/dsymutil/dsymutil.h
@@ -1,56 +1,56 @@
-//===- tools/dsymutil/dsymutil.h - dsymutil high-level functionality ------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-//
-/// \file
-///
-/// This file contains the class declaration for the code that parses STABS
-/// debug maps that are embedded in the binaries symbol tables.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_TOOLS_DSYMUTIL_DSYMUTIL_H
-#define LLVM_TOOLS_DSYMUTIL_DSYMUTIL_H
-
-#include "DebugMap.h"
-#include "LinkUtils.h"
-#include "llvm/ADT/ArrayRef.h"
-#include "llvm/ADT/StringRef.h"
-#include "llvm/Support/Compiler.h"
-#include "llvm/Support/ErrorOr.h"
-#include <memory>
-#include <string>
-#include <vector>
-
-namespace llvm {
-namespace dsymutil {
-
-class BinaryHolder;
-
-/// Extract the DebugMaps from the given file.
-/// The file has to be a MachO object file. Multiple debug maps can be
-/// returned when the file is universal (aka fat) binary.
-ErrorOr<std::vector<std::unique_ptr<DebugMap>>>
-parseDebugMap(llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS,
- StringRef InputFile, ArrayRef<std::string> Archs,
- StringRef PrependPath, bool PaperTrailWarnings, bool Verbose,
- bool InputIsYAML);
-
-/// Dump the symbol table.
-bool dumpStab(llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS,
- StringRef InputFile, ArrayRef<std::string> Archs,
- StringRef PrependPath = "");
-
-/// Link the Dwarf debug info as directed by the passed DebugMap \p DM into a
-/// DwarfFile named \p OutputFilename. \returns false if the link failed.
-bool linkDwarf(raw_fd_ostream &OutFile, BinaryHolder &BinHolder,
- const DebugMap &DM, LinkOptions Options);
-
-} // end namespace dsymutil
-} // end namespace llvm
-
-#endif // LLVM_TOOLS_DSYMUTIL_DSYMUTIL_H
+//===- tools/dsymutil/dsymutil.h - dsymutil high-level functionality ------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+/// \file
+///
+/// This file contains the class declaration for the code that parses STABS
+/// debug maps that are embedded in the binaries symbol tables.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TOOLS_DSYMUTIL_DSYMUTIL_H
+#define LLVM_TOOLS_DSYMUTIL_DSYMUTIL_H
+
+#include "DebugMap.h"
+#include "LinkUtils.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/Compiler.h"
+#include "llvm/Support/ErrorOr.h"
+#include <memory>
+#include <string>
+#include <vector>
+
+namespace llvm {
+namespace dsymutil {
+
+class BinaryHolder;
+
+/// Extract the DebugMaps from the given file.
+/// The file has to be a MachO object file. Multiple debug maps can be
+/// returned when the file is universal (aka fat) binary.
+ErrorOr<std::vector<std::unique_ptr<DebugMap>>>
+parseDebugMap(llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS,
+ StringRef InputFile, ArrayRef<std::string> Archs,
+ StringRef PrependPath, bool PaperTrailWarnings, bool Verbose,
+ bool InputIsYAML);
+
+/// Dump the symbol table.
+bool dumpStab(llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS,
+ StringRef InputFile, ArrayRef<std::string> Archs,
+ StringRef PrependPath = "");
+
+/// Link the Dwarf debug info as directed by the passed DebugMap \p DM into a
+/// DwarfFile named \p OutputFilename. \returns false if the link failed.
+bool linkDwarf(raw_fd_ostream &OutFile, BinaryHolder &BinHolder,
+ const DebugMap &DM, LinkOptions Options);
+
+} // end namespace dsymutil
+} // end namespace llvm
+
+#endif // LLVM_TOOLS_DSYMUTIL_DSYMUTIL_H
diff --git a/contrib/libs/llvm12/tools/dsymutil/ya.make b/contrib/libs/llvm12/tools/dsymutil/ya.make
index 8a3b747e01..2ebc7666d2 100644
--- a/contrib/libs/llvm12/tools/dsymutil/ya.make
+++ b/contrib/libs/llvm12/tools/dsymutil/ya.make
@@ -1,17 +1,17 @@
-# Generated by devtools/yamaker.
-
-PROGRAM()
-
+# Generated by devtools/yamaker.
+
+PROGRAM()
+
OWNER(
orivej
g:cpp-contrib
)
-
+
LICENSE(Apache-2.0 WITH LLVM-exception)
-
+
LICENSE_TEXTS(.yandex_meta/licenses.list.txt)
-PEERDIR(
+PEERDIR(
contrib/libs/llvm12
contrib/libs/llvm12/include
contrib/libs/llvm12/lib/Analysis
@@ -70,29 +70,29 @@ PEERDIR(
contrib/libs/llvm12/lib/Transforms/Scalar
contrib/libs/llvm12/lib/Transforms/Utils
contrib/libs/llvm12/lib/Transforms/Vectorize
-)
-
-ADDINCL(
+)
+
+ADDINCL(
${ARCADIA_BUILD_ROOT}/contrib/libs/llvm12/tools/dsymutil
contrib/libs/llvm12/tools/dsymutil
-)
-
-NO_COMPILER_WARNINGS()
-
-NO_UTIL()
-
-SRCS(
- BinaryHolder.cpp
- CFBundle.cpp
- DebugMap.cpp
- DwarfLinkerForBinary.cpp
- MachODebugMapParser.cpp
- MachOUtils.cpp
- Reproducer.cpp
- SymbolMap.cpp
- dsymutil.cpp
-)
-
+)
+
+NO_COMPILER_WARNINGS()
+
+NO_UTIL()
+
+SRCS(
+ BinaryHolder.cpp
+ CFBundle.cpp
+ DebugMap.cpp
+ DwarfLinkerForBinary.cpp
+ MachODebugMapParser.cpp
+ MachOUtils.cpp
+ Reproducer.cpp
+ SymbolMap.cpp
+ dsymutil.cpp
+)
+
IF (OS_DARWIN AND ARCH_AARCH64)
LDFLAGS(
-framework
@@ -100,4 +100,4 @@ IF (OS_DARWIN AND ARCH_AARCH64)
)
ENDIF()
-END()
+END()