1 //===-- BinaryHolder.h - Utility class for accessing binaries -------------===//
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
7 //===----------------------------------------------------------------------===//
9 // This program is a utility that aims to be a dropin replacement for
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"
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
37 using TimestampTy
= sys::TimePoint
<std::chrono::seconds
>;
39 BinaryHolder(bool Verbose
= false) : Verbose(Verbose
) {}
41 // Forward declarations for friend declaration.
45 /// Base class shared by cached entries, representing objects and archives.
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
{
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());
71 return errorCodeToError(object::object_error::invalid_file_type
);
72 Result
.push_back(Derived
);
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
);
86 return Object
.takeError();
87 return cast
<ObjectFileType
>(*Object
);
91 std::vector
<std::unique_ptr
<object::ObjectFile
>> Objects
;
95 /// Cached entry holding one or more (in the of a fat binary) archive files.
96 class ArchiveEntry
: public EntryBase
{
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);
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());
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
;
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("/", {});
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
;