[yaml2obj/obj2yaml] - Add support for .stack_sizes sections.
[llvm-complete.git] / tools / dsymutil / BinaryHolder.h
blob0376d1e786433bd6da52c437f409a050c984976d
1 //===-- BinaryHolder.h - Utility class for accessing binaries -------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This program is a utility that aims to be a dropin replacement for
10 // Darwin's dsymutil.
12 //===----------------------------------------------------------------------===//
13 #ifndef LLVM_TOOLS_DSYMUTIL_BINARYHOLDER_H
14 #define LLVM_TOOLS_DSYMUTIL_BINARYHOLDER_H
16 #include "llvm/ADT/DenseMap.h"
17 #include "llvm/ADT/Triple.h"
18 #include "llvm/Object/Archive.h"
19 #include "llvm/Object/Error.h"
20 #include "llvm/Object/MachOUniversal.h"
21 #include "llvm/Object/ObjectFile.h"
22 #include "llvm/Support/Chrono.h"
23 #include "llvm/Support/Errc.h"
24 #include "llvm/Support/ErrorOr.h"
26 #include <mutex>
28 namespace llvm {
29 namespace dsymutil {
31 /// The BinaryHolder class is responsible for creating and owning
32 /// ObjectFiles and their underlying MemoryBuffers. It differs from a simple
33 /// OwningBinary in that it handles accessing and caching of archives and its
34 /// members.
35 class BinaryHolder {
36 public:
37 using TimestampTy = sys::TimePoint<std::chrono::seconds>;
39 BinaryHolder(bool Verbose = false) : Verbose(Verbose) {}
41 // Forward declarations for friend declaration.
42 class ObjectEntry;
43 class ArchiveEntry;
45 /// Base class shared by cached entries, representing objects and archives.
46 class EntryBase {
47 protected:
48 std::unique_ptr<MemoryBuffer> MemBuffer;
49 std::unique_ptr<object::MachOUniversalBinary> FatBinary;
50 std::string FatBinaryName;
53 /// Cached entry holding one or more (in case of a fat binary) object files.
54 class ObjectEntry : public EntryBase {
55 public:
56 /// Load the given object binary in memory.
57 Error load(StringRef Filename, bool Verbose = false);
59 /// Access all owned ObjectFiles.
60 std::vector<const object::ObjectFile *> getObjects() const;
62 /// Access to a derived version of all the currently owned ObjectFiles. The
63 /// conversion might be invalid, in which case an Error is returned.
64 template <typename ObjectFileType>
65 Expected<std::vector<const ObjectFileType *>> getObjectsAs() const {
66 std::vector<const ObjectFileType *> Result;
67 Result.reserve(Objects.size());
68 for (auto &Object : Objects) {
69 const auto *Derived = dyn_cast<ObjectFileType>(Object.get());
70 if (!Derived)
71 return errorCodeToError(object::object_error::invalid_file_type);
72 Result.push_back(Derived);
74 return Result;
77 /// Access the owned ObjectFile with architecture \p T.
78 Expected<const object::ObjectFile &> getObject(const Triple &T) const;
80 /// Access to a derived version of the currently owned ObjectFile with
81 /// architecture \p T. The conversion must be known to be valid.
82 template <typename ObjectFileType>
83 Expected<const ObjectFileType &> getObjectAs(const Triple &T) const {
84 auto Object = getObject(T);
85 if (!Object)
86 return Object.takeError();
87 return cast<ObjectFileType>(*Object);
90 private:
91 std::vector<std::unique_ptr<object::ObjectFile>> Objects;
92 friend ArchiveEntry;
95 /// Cached entry holding one or more (in the of a fat binary) archive files.
96 class ArchiveEntry : public EntryBase {
97 public:
98 struct KeyTy {
99 std::string Filename;
100 TimestampTy Timestamp;
102 KeyTy() : Filename(), Timestamp() {}
103 KeyTy(StringRef Filename, TimestampTy Timestamp)
104 : Filename(Filename.str()), Timestamp(Timestamp) {}
107 /// Load the given object binary in memory.
108 Error load(StringRef Filename, TimestampTy Timestamp, bool Verbose = false);
110 Expected<const ObjectEntry &> getObjectEntry(StringRef Filename,
111 TimestampTy Timestamp,
112 bool Verbose = false);
114 private:
115 std::vector<std::unique_ptr<object::Archive>> Archives;
116 DenseMap<KeyTy, ObjectEntry> MemberCache;
117 std::mutex MemberCacheMutex;
120 Expected<const ObjectEntry &>
121 getObjectEntry(StringRef Filename, TimestampTy Timestamp = TimestampTy());
123 void clear();
125 private:
126 /// Cache of static archives. Objects that are part of a static archive are
127 /// stored under this object, rather than in the map below.
128 StringMap<ArchiveEntry> ArchiveCache;
129 std::mutex ArchiveCacheMutex;
131 /// Object entries for objects that are not in a static archive.
132 StringMap<ObjectEntry> ObjectCache;
133 std::mutex ObjectCacheMutex;
135 bool Verbose;
138 } // namespace dsymutil
140 template <> struct DenseMapInfo<dsymutil::BinaryHolder::ArchiveEntry::KeyTy> {
142 static inline dsymutil::BinaryHolder::ArchiveEntry::KeyTy getEmptyKey() {
143 return dsymutil::BinaryHolder::ArchiveEntry::KeyTy();
146 static inline dsymutil::BinaryHolder::ArchiveEntry::KeyTy getTombstoneKey() {
147 return dsymutil::BinaryHolder::ArchiveEntry::KeyTy("/", {});
150 static unsigned
151 getHashValue(const dsymutil::BinaryHolder::ArchiveEntry::KeyTy &K) {
152 return hash_combine(DenseMapInfo<StringRef>::getHashValue(K.Filename),
153 DenseMapInfo<unsigned>::getHashValue(
154 K.Timestamp.time_since_epoch().count()));
157 static bool isEqual(const dsymutil::BinaryHolder::ArchiveEntry::KeyTy &LHS,
158 const dsymutil::BinaryHolder::ArchiveEntry::KeyTy &RHS) {
159 return LHS.Filename == RHS.Filename && LHS.Timestamp == RHS.Timestamp;
163 } // namespace llvm
164 #endif