llvm.org GIT mirror llvm / 6dbc644
[TextAPI] TBD Reader/Writer Add basic infrastructure for reading and writting TBD files (version 1 - 3). The TextAPI library is not used by anything yet (besides the unit tests). Tool support will be added in a separate commit. The TBD format is currently documented in the implementation file (TextStub.cpp). https://reviews.llvm.org/D53945 Update: This contains changes to fix issues discovered by the bots: - add parentheses to silence warnings. - rename variables - use PlatformType from BinaryFormat - Trying if switching from a vector to an array will appeas the bots. - Replace the tuple with a struct to work around an explicit constructor bug. - This fixes an issue where we were leaking the YAML document if there was a parsing error. Updated the license information in all files. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@356820 91177308-0d34-0410-b5e6-96231b3b80d8 Juergen Ributzka 7 months ago
21 changed file(s) with 3195 addition(s) and 1 deletion(s). Raw diff Collapse all Expand all
0 //===- llvm/TextAPI/MachO/Architecture.def - Architecture -----------------===//
1 //
2 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
3 // See https://llvm.org/LICENSE.txt for license information.
4 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
5 //
6 //===----------------------------------------------------------------------===//
7
8 #ifndef ARCHINFO
9 #define ARCHINFO(arch)
10 #endif
11
12 ///
13 /// X86 architectures sorted by cpu type and sub type id.
14 ///
15 ARCHINFO(i386, MachO::CPU_TYPE_I386, MachO::CPU_SUBTYPE_I386_ALL)
16 ARCHINFO(x86_64, MachO::CPU_TYPE_X86_64, MachO::CPU_SUBTYPE_X86_64_ALL)
17 ARCHINFO(x86_64h, MachO::CPU_TYPE_X86_64, MachO::CPU_SUBTYPE_X86_64_H)
18
19
20 ///
21 /// ARM architectures sorted by cpu sub type id.
22 ///
23 ARCHINFO(armv4t, MachO::CPU_TYPE_ARM, MachO::CPU_SUBTYPE_ARM_V4T)
24 ARCHINFO(armv6, MachO::CPU_TYPE_ARM, MachO::CPU_SUBTYPE_ARM_V6)
25 ARCHINFO(armv5, MachO::CPU_TYPE_ARM, MachO::CPU_SUBTYPE_ARM_V5TEJ)
26 ARCHINFO(armv7, MachO::CPU_TYPE_ARM, MachO::CPU_SUBTYPE_ARM_V7)
27 ARCHINFO(armv7s, MachO::CPU_TYPE_ARM, MachO::CPU_SUBTYPE_ARM_V7S)
28 ARCHINFO(armv7k, MachO::CPU_TYPE_ARM, MachO::CPU_SUBTYPE_ARM_V7K)
29 ARCHINFO(armv6m, MachO::CPU_TYPE_ARM, MachO::CPU_SUBTYPE_ARM_V6M)
30 ARCHINFO(armv7m, MachO::CPU_TYPE_ARM, MachO::CPU_SUBTYPE_ARM_V7M)
31 ARCHINFO(armv7em, MachO::CPU_TYPE_ARM, MachO::CPU_SUBTYPE_ARM_V7EM)
32
33
34 ///
35 /// ARM64 architectures sorted by cpu sub type id.
36 ///
37 ARCHINFO(arm64, MachO::CPU_TYPE_ARM64, MachO::CPU_SUBTYPE_ARM64_ALL)
0 //===- llvm/TextAPI/MachO/Architecture.h - Architecture ---------*- C++ -*-===//
1 //
2 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
3 // See https://llvm.org/LICENSE.txt for license information.
4 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
5 //
6 //===----------------------------------------------------------------------===//
7 //
8 // Defines the architecture enum and helper methods.
9 //
10 //===----------------------------------------------------------------------===//
11
12 #ifndef LLVM_TEXTAPI_MACHO_ARCHITECTURE_H
13 #define LLVM_TEXTAPI_MACHO_ARCHITECTURE_H
14
15 #include "llvm/ADT/StringRef.h"
16 #include "llvm/Support/raw_ostream.h"
17
18 namespace llvm {
19 namespace MachO {
20
21 /// Defines the architecture slices that are supported by Text-based Stub files.
22 enum class Architecture : uint8_t {
23 #define ARCHINFO(Arch, Type, SubType) Arch,
24 #include "llvm/TextAPI/MachO/Architecture.def"
25 #undef ARCHINFO
26 unknown, // this has to go last.
27 };
28
29 /// Convert a CPU Type and Subtype pair to an architecture slice.
30 Architecture getArchitectureFromCpuType(uint32_t CPUType, uint32_t CPUSubType);
31
32 /// Convert a name to an architecture slice.
33 Architecture getArchitectureFromName(StringRef Name);
34
35 /// Convert an architecture slice to a string.
36 StringRef getArchitectureName(Architecture Arch);
37
38 /// Convert an architecture slice to a CPU Type and Subtype pair.
39 std::pair getCPUTypeFromArchitecture(Architecture Arch);
40
41 raw_ostream &operator<<(raw_ostream &OS, Architecture Arch);
42
43 } // end namespace MachO.
44 } // end namespace llvm.
45
46 #endif // LLVM_TEXTAPI_MACHO_ARCHITECTURE_H
0 //===- llvm/TextAPI/MachO/ArchitectureSet.h - ArchitectureSet ---*- C++ -*-===//
1 //
2 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
3 // See https://llvm.org/LICENSE.txt for license information.
4 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
5 //
6 //===----------------------------------------------------------------------===//
7 //
8 // Defines the architecture set.
9 //
10 //===----------------------------------------------------------------------===//
11
12 #ifndef LLVM_TEXTAPI_MACHO_ARCHITECTURE_SET_H
13 #define LLVM_TEXTAPI_MACHO_ARCHITECTURE_SET_H
14
15 #include "llvm/Support/raw_ostream.h"
16 #include "llvm/TextAPI/MachO/Architecture.h"
17 #include
18 #include
19 #include
20 #include
21
22 namespace llvm {
23 namespace MachO {
24
25 class ArchitectureSet {
26 private:
27 using ArchSetType = uint32_t;
28
29 const static ArchSetType EndIndexVal =
30 std::numeric_limits::max();
31 ArchSetType ArchSet{0};
32
33 public:
34 constexpr ArchitectureSet() = default;
35 constexpr ArchitectureSet(ArchSetType Raw) : ArchSet(Raw) {}
36 ArchitectureSet(Architecture Arch) : ArchitectureSet() { set(Arch); }
37 ArchitectureSet(const std::vector &Archs);
38
39 void set(Architecture Arch) {
40 if (Arch == Architecture::unknown)
41 return;
42 ArchSet |= 1U << static_cast(Arch);
43 }
44
45 void clear(Architecture Arch) { ArchSet &= ~(1U << static_cast(Arch)); }
46
47 bool has(Architecture Arch) const {
48 return ArchSet & (1U << static_cast(Arch));
49 }
50
51 bool contains(ArchitectureSet Archs) const {
52 return (ArchSet & Archs.ArchSet) == Archs.ArchSet;
53 }
54
55 size_t count() const;
56
57 bool empty() const { return ArchSet == 0; }
58
59 ArchSetType rawValue() const { return ArchSet; }
60
61 template
62 class arch_iterator
63 : public std::iterator {
64 private:
65 ArchSetType Index;
66 Ty *ArchSet;
67
68 void findNextSetBit() {
69 if (Index == EndIndexVal)
70 return;
71
72 do {
73 if (*ArchSet & (1UL << ++Index))
74 return;
75 } while (Index < sizeof(Ty) * 8);
76
77 Index = EndIndexVal;
78 }
79
80 public:
81 arch_iterator(Ty *ArchSet, ArchSetType Index = 0)
82 : Index(Index), ArchSet(ArchSet) {
83 if (Index != EndIndexVal && !(*ArchSet & (1UL << Index)))
84 findNextSetBit();
85 }
86
87 Architecture operator*() const { return static_cast(Index); }
88
89 arch_iterator &operator++() {
90 findNextSetBit();
91 return *this;
92 }
93
94 arch_iterator operator++(int) {
95 auto tmp = *this;
96 findNextSetBit();
97 return tmp;
98 }
99
100 bool operator==(const arch_iterator &o) const {
101 return std::tie(Index, ArchSet) == std::tie(o.Index, o.ArchSet);
102 }
103
104 bool operator!=(const arch_iterator &o) const { return !(*this == o); }
105 };
106
107 ArchitectureSet operator&(const ArchitectureSet &o) {
108 return {ArchSet & o.ArchSet};
109 }
110
111 ArchitectureSet operator|(const ArchitectureSet &o) {
112 return {ArchSet | o.ArchSet};
113 }
114
115 ArchitectureSet &operator|=(const ArchitectureSet &o) {
116 ArchSet |= o.ArchSet;
117 return *this;
118 }
119
120 ArchitectureSet &operator|=(const Architecture &Arch) {
121 set(Arch);
122 return *this;
123 }
124
125 bool operator==(const ArchitectureSet &o) const {
126 return ArchSet == o.ArchSet;
127 }
128
129 bool operator!=(const ArchitectureSet &o) const {
130 return ArchSet != o.ArchSet;
131 }
132
133 bool operator<(const ArchitectureSet &o) const { return ArchSet < o.ArchSet; }
134
135 using iterator = arch_iterator;
136 using const_iterator = arch_iterator;
137
138 iterator begin() { return {&ArchSet}; }
139 iterator end() { return {&ArchSet, EndIndexVal}; }
140
141 const_iterator begin() const { return {&ArchSet}; }
142 const_iterator end() const { return {&ArchSet, EndIndexVal}; }
143
144 operator std::string() const;
145 operator std::vector() const;
146 void print(raw_ostream &OS) const;
147 };
148
149 inline ArchitectureSet operator|(const Architecture &lhs,
150 const Architecture &rhs) {
151 return ArchitectureSet(lhs) | ArchitectureSet(rhs);
152 }
153
154 raw_ostream &operator<<(raw_ostream &OS, ArchitectureSet Set);
155
156 } // end namespace MachO.
157 } // end namespace llvm.
158
159 #endif // LLVM_TEXTAPI_MACHO_ARCHITECTURE_SET_H
0 //===- llvm/TextAPI/MachO/IntefaceFile.h - TAPI Interface File --*- C++ -*-===//
1 //
2 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
3 // See https://llvm.org/LICENSE.txt for license information.
4 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
5 //
6 //===----------------------------------------------------------------------===//
7 //
8 // A generic and abstract interface representation for linkable objects. This
9 // could be an MachO executable, bundle, dylib, or text-based stub file.
10 //
11 //===----------------------------------------------------------------------===//
12
13 #ifndef LLVM_TEXTAPI_MACHO_INTERFACE_FILE_H
14 #define LLVM_TEXTAPI_MACHO_INTERFACE_FILE_H
15
16 #include "llvm/ADT/BitmaskEnum.h"
17 #include "llvm/ADT/DenseMap.h"
18 #include "llvm/ADT/Hashing.h"
19 #include "llvm/ADT/StringRef.h"
20 #include "llvm/ADT/iterator.h"
21 #include "llvm/BinaryFormat/MachO.h"
22 #include "llvm/BinaryFormat/Magic.h"
23 #include "llvm/Support/Allocator.h"
24 #include "llvm/Support/Error.h"
25 #include "llvm/TextAPI/MachO/Architecture.h"
26 #include "llvm/TextAPI/MachO/ArchitectureSet.h"
27 #include "llvm/TextAPI/MachO/PackedVersion.h"
28 #include "llvm/TextAPI/MachO/Symbol.h"
29
30 namespace llvm {
31 namespace MachO {
32
33 /// Defines the list of MachO platforms.
34 enum class PlatformKind : unsigned {
35 unknown,
36 macOS = MachO::PLATFORM_MACOS,
37 iOS = MachO::PLATFORM_IOS,
38 tvOS = MachO::PLATFORM_TVOS,
39 watchOS = MachO::PLATFORM_WATCHOS,
40 bridgeOS = MachO::PLATFORM_BRIDGEOS,
41 };
42
43 /// Defines a list of Objective-C constraints.
44 enum class ObjCConstraintType : unsigned {
45 /// No constraint.
46 None = 0,
47
48 /// Retain/Release.
49 Retain_Release = 1,
50
51 /// Retain/Release for Simulator.
52 Retain_Release_For_Simulator = 2,
53
54 /// Retain/Release or Garbage Collection.
55 Retain_Release_Or_GC = 3,
56
57 /// Garbage Collection.
58 GC = 4,
59 };
60
61 // clang-format off
62
63 /// Defines the file type this file represents.
64 enum FileType : unsigned {
65 /// Invalid file type.
66 Invalid = 0U,
67
68 /// Text-based stub file (.tbd) version 1.0
69 TBD_V1 = 1U << 0,
70
71 /// Text-based stub file (.tbd) version 2.0
72 TBD_V2 = 1U << 1,
73
74 /// Text-based stub file (.tbd) version 3.0
75 TBD_V3 = 1U << 2,
76
77 All = ~0U,
78
79 LLVM_MARK_AS_BITMASK_ENUM(/*LargestValue=*/All),
80 };
81
82 // clang-format on
83
84 /// Reference to an interface file.
85 class InterfaceFileRef {
86 public:
87 InterfaceFileRef() = default;
88
89 InterfaceFileRef(StringRef InstallName) : InstallName(InstallName) {}
90
91 InterfaceFileRef(StringRef InstallName, ArchitectureSet Archs)
92 : InstallName(InstallName), Architectures(Archs) {}
93
94 StringRef getInstallName() const { return InstallName; };
95 void addArchitectures(ArchitectureSet Archs) { Architectures |= Archs; }
96 ArchitectureSet getArchitectures() const { return Architectures; }
97 bool hasArchitecture(Architecture Arch) const {
98 return Architectures.has(Arch);
99 }
100
101 bool operator==(const InterfaceFileRef &O) const {
102 return std::tie(InstallName, Architectures) ==
103 std::tie(O.InstallName, O.Architectures);
104 }
105
106 bool operator<(const InterfaceFileRef &O) const {
107 return std::tie(InstallName, Architectures) <
108 std::tie(O.InstallName, O.Architectures);
109 }
110
111 private:
112 std::string InstallName;
113 ArchitectureSet Architectures;
114 };
115
116 } // end namespace MachO.
117
118 struct SymbolsMapKey {
119 MachO::SymbolKind Kind;
120 StringRef Name;
121
122 SymbolsMapKey(MachO::SymbolKind Kind, StringRef Name)
123 : Kind(Kind), Name(Name) {}
124 };
125 template <> struct DenseMapInfo {
126 static inline SymbolsMapKey getEmptyKey() {
127 return SymbolsMapKey(MachO::SymbolKind::GlobalSymbol, StringRef{});
128 }
129
130 static inline SymbolsMapKey getTombstoneKey() {
131 return SymbolsMapKey(MachO::SymbolKind::ObjectiveCInstanceVariable,
132 StringRef{});
133 }
134
135 static unsigned getHashValue(const SymbolsMapKey &Key) {
136 return hash_combine(hash_value(Key.Kind), hash_value(Key.Name));
137 }
138
139 static bool isEqual(const SymbolsMapKey &LHS, const SymbolsMapKey &RHS) {
140 return std::tie(LHS.Kind, LHS.Name) == std::tie(RHS.Kind, RHS.Name);
141 }
142 };
143
144 namespace MachO {
145
146 /// Defines the interface file.
147 class InterfaceFile {
148 public:
149 /// Set the path from which this file was generated (if applicable).
150 ///
151 /// \param Path_ The path to the source file.
152 void setPath(StringRef Path_) { Path = Path_; }
153
154 /// Get the path from which this file was generated (if applicable).
155 ///
156 /// \return The path to the source file or empty.
157 StringRef getPath() const { return Path; }
158
159 /// Set the file type.
160 ///
161 /// This is used by the YAML writer to identify the specification it should
162 /// use for writing the file.
163 ///
164 /// \param Kind The file type.
165 void setFileType(FileType Kind) { FileKind = Kind; }
166
167 /// Get the file type.
168 ///
169 /// \return The file type.
170 FileType getFileType() const { return FileKind; }
171
172 /// Set the platform.
173 void setPlatform(PlatformKind Platform_) { Platform = Platform_; }
174
175 /// Get the platform.
176 PlatformKind getPlatform() const { return Platform; }
177
178 /// Specify the set of supported architectures by this file.
179 void setArchitectures(ArchitectureSet Architectures_) {
180 Architectures = Architectures_;
181 }
182
183 /// Add the set of supported architectures by this file.
184 void addArchitectures(ArchitectureSet Architectures_) {
185 Architectures |= Architectures_;
186 }
187
188 /// Add supported architecture by this file..
189 void addArch(Architecture Arch) { Architectures.set(Arch); }
190
191 /// Get the set of supported architectures.
192 ArchitectureSet getArchitectures() const { return Architectures; }
193
194 /// Set the install name of the library.
195 void setInstallName(StringRef InstallName_) { InstallName = InstallName_; }
196
197 /// Get the install name of the library.
198 StringRef getInstallName() const { return InstallName; }
199
200 /// Set the current version of the library.
201 void setCurrentVersion(PackedVersion Version) { CurrentVersion = Version; }
202
203 /// Get the current version of the library.
204 PackedVersion getCurrentVersion() const { return CurrentVersion; }
205
206 /// Set the compatibility version of the library.
207 void setCompatibilityVersion(PackedVersion Version) {
208 CompatibilityVersion = Version;
209 }
210
211 /// Get the compatibility version of the library.
212 PackedVersion getCompatibilityVersion() const { return CompatibilityVersion; }
213
214 /// Set the Swift ABI version of the library.
215 void setSwiftABIVersion(uint8_t Version) { SwiftABIVersion = Version; }
216
217 /// Get the Swift ABI version of the library.
218 uint8_t getSwiftABIVersion() const { return SwiftABIVersion; }
219
220 /// Specify if the library uses two-level namespace (or flat namespace).
221 void setTwoLevelNamespace(bool V = true) { IsTwoLevelNamespace = V; }
222
223 /// Check if the library uses two-level namespace.
224 bool isTwoLevelNamespace() const { return IsTwoLevelNamespace; }
225
226 /// Specify if the library is application extension safe (or not).
227 void setApplicationExtensionSafe(bool V = true) { IsAppExtensionSafe = V; }
228
229 /// Check if the library is application extension safe.
230 bool isApplicationExtensionSafe() const { return IsAppExtensionSafe; }
231
232 /// Set the Objective-C constraint.
233 void setObjCConstraint(ObjCConstraintType Constraint) {
234 ObjcConstraint = Constraint;
235 }
236
237 /// Get the Objective-C constraint.
238 ObjCConstraintType getObjCConstraint() const { return ObjcConstraint; }
239
240 /// Specify if this file was generated during InstallAPI (or not).
241 void setInstallAPI(bool V = true) { IsInstallAPI = V; }
242
243 /// Check if this file was generated during InstallAPI.
244 bool isInstallAPI() const { return IsInstallAPI; }
245
246 /// Set the parent umbrella framework.
247 void setParentUmbrella(StringRef Parent) { ParentUmbrella = Parent; }
248
249 /// Get the parent umbrella framework.
250 StringRef getParentUmbrella() const { return ParentUmbrella; }
251
252 /// Add an allowable client.
253 ///
254 /// Mach-O Dynamic libraries have the concept of allowable clients that are
255 /// checked during static link time. The name of the application or library
256 /// that is being generated needs to match one of the allowable clients or the
257 /// linker refuses to link this library.
258 ///
259 /// \param Name The name of the client that is allowed to link this library.
260 /// \param Architectures The set of architecture for which this applies.
261 void addAllowableClient(StringRef Name, ArchitectureSet Architectures);
262
263 /// Get the list of allowable clients.
264 ///
265 /// \return Returns a list of allowable clients.
266 const std::vector &allowableClients() const {
267 return AllowableClients;
268 }
269
270 /// Add a re-exported library.
271 ///
272 /// \param InstallName The name of the library to re-export.
273 /// \param Architectures The set of architecture for which this applies.
274 void addReexportedLibrary(StringRef InstallName,
275 ArchitectureSet Architectures);
276
277 /// Get the list of re-exported libraries.
278 ///
279 /// \return Returns a list of re-exported libraries.
280 const std::vector &reexportedLibraries() const {
281 return ReexportedLibraries;
282 }
283
284 /// Add an architecture/UUID pair.
285 ///
286 /// \param Arch The architecture for which this applies.
287 /// \param UUID The UUID of the library for the specified architecture.
288 void addUUID(Architecture Arch, StringRef UUID);
289
290 /// Add an architecture/UUID pair.
291 ///
292 /// \param Arch The architecture for which this applies.
293 /// \param UUID The UUID of the library for the specified architecture.
294 void addUUID(Architecture Arch, uint8_t UUID[16]);
295
296 /// Get the list of architecture/UUID pairs.
297 ///
298 /// \return Returns a list of architecture/UUID pairs.
299 const std::vector> &uuids() const {
300 return UUIDs;
301 }
302
303 /// Add a symbol to the symbols list or extend an existing one.
304 void addSymbol(SymbolKind Kind, StringRef Name, ArchitectureSet Architectures,
305 SymbolFlags Flags = SymbolFlags::None);
306
307 using SymbolMapType = DenseMap;
308 struct const_symbol_iterator
309 : public iterator_adaptor_base<
310 const_symbol_iterator, SymbolMapType::const_iterator,
311 std::forward_iterator_tag, const Symbol *, ptrdiff_t,
312 const Symbol *, const Symbol *> {
313 const_symbol_iterator() = default;
314
315 template
316 const_symbol_iterator(U &&u)
317 : iterator_adaptor_base(std::forward(u)) {}
318
319 reference operator*() const { return I->second; }
320 pointer operator->() const { return I->second; }
321 };
322 using const_symbol_range = iterator_range;
323
324 // Custom iterator to return only exported symbols.
325 struct const_export_iterator
326 : public iterator_adaptor_base<
327 const_export_iterator, const_symbol_iterator,
328 std::forward_iterator_tag, const Symbol *> {
329 const_symbol_iterator _end;
330
331 void skipToNextSymbol() {
332 while (I != _end && I->isUndefined())
333 ++I;
334 }
335
336 const_export_iterator() = default;
337 template
338 const_export_iterator(U &&it, U &&end)
339 : iterator_adaptor_base(std::forward(it)),
340 _end(std::forward(end)) {
341 skipToNextSymbol();
342 }
343
344 const_export_iterator &operator++() {
345 ++I;
346 skipToNextSymbol();
347 return *this;
348 }
349
350 const_export_iterator operator++(int) {
351 const_export_iterator tmp(*this);
352 ++(*this);
353 return tmp;
354 }
355 };
356 using const_export_range = llvm::iterator_range;
357
358 // Custom iterator to return only undefined symbols.
359 struct const_undefined_iterator
360 : public iterator_adaptor_base<
361 const_undefined_iterator, const_symbol_iterator,
362 std::forward_iterator_tag, const Symbol *> {
363 const_symbol_iterator _end;
364
365 void skipToNextSymbol() {
366 while (I != _end && !I->isUndefined())
367 ++I;
368 }
369
370 const_undefined_iterator() = default;
371 template
372 const_undefined_iterator(U &&it, U &&end)
373 : iterator_adaptor_base(std::forward(it)),
374 _end(std::forward(end)) {
375 skipToNextSymbol();
376 }
377
378 const_undefined_iterator &operator++() {
379 ++I;
380 skipToNextSymbol();
381 return *this;
382 }
383
384 const_undefined_iterator operator++(int) {
385 const_undefined_iterator tmp(*this);
386 ++(*this);
387 return tmp;
388 }
389 };
390 using const_undefined_range = llvm::iterator_range;
391
392 const_symbol_range symbols() const {
393 return {Symbols.begin(), Symbols.end()};
394 }
395 const_export_range exports() const {
396 return {{Symbols.begin(), Symbols.end()}, {Symbols.end(), Symbols.end()}};
397 }
398 const_undefined_range undefineds() const {
399 return {{Symbols.begin(), Symbols.end()}, {Symbols.end(), Symbols.end()}};
400 }
401
402 private:
403 llvm::BumpPtrAllocator Allocator;
404 StringRef copyString(StringRef String) {
405 if (String.empty())
406 return {};
407
408 void *Ptr = Allocator.Allocate(String.size(), 1);
409 memcpy(Ptr, String.data(), String.size());
410 return StringRef(reinterpret_cast(Ptr), String.size());
411 }
412
413 std::string Path;
414 FileType FileKind;
415 PlatformKind Platform;
416 ArchitectureSet Architectures;
417 std::string InstallName;
418 PackedVersion CurrentVersion;
419 PackedVersion CompatibilityVersion;
420 uint8_t SwiftABIVersion{0};
421 bool IsTwoLevelNamespace{false};
422 bool IsAppExtensionSafe{false};
423 bool IsInstallAPI{false};
424 ObjCConstraintType ObjcConstraint = ObjCConstraintType::None;
425 std::string ParentUmbrella;
426 std::vector AllowableClients;
427 std::vector ReexportedLibraries;
428 std::vector> UUIDs;
429 SymbolMapType Symbols;
430 };
431
432 } // end namespace MachO.
433 } // end namespace llvm.
434
435 #endif // LLVM_TEXTAPI_MACHO_INTERFACE_FILE_H
0 //===- llvm/TextAPI/MachO/PackedVersion.h - PackedVersion -------*- C++ -*-===//
1 //
2 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
3 // See https://llvm.org/LICENSE.txt for license information.
4 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
5 //
6 //===----------------------------------------------------------------------===//
7 //
8 // Defines the Mach-O packed version format.
9 //
10 //===----------------------------------------------------------------------===//
11
12 #ifndef LLVM_TEXTAPI_MACHO_PACKED_VERSION_H
13 #define LLVM_TEXTAPI_MACHO_PACKED_VERSION_H
14
15 #include "llvm/ADT/StringRef.h"
16 #include "llvm/Support/raw_ostream.h"
17
18 namespace llvm {
19 namespace MachO {
20
21 class PackedVersion {
22 uint32_t Version{0};
23
24 public:
25 constexpr PackedVersion() = default;
26 explicit constexpr PackedVersion(uint32_t RawVersion) : Version(RawVersion) {}
27 PackedVersion(unsigned Major, unsigned Minor, unsigned Subminor)
28 : Version((Major << 16) | ((Minor & 0xff) << 8) | (Subminor & 0xff)) {}
29
30 bool empty() const { return Version == 0; }
31
32 /// Retrieve the major version number.
33 unsigned getMajor() const { return Version >> 16; }
34
35 /// Retrieve the minor version number, if provided.
36 unsigned getMinor() const { return (Version >> 8) & 0xff; }
37
38 /// Retrieve the subminor version number, if provided.
39 unsigned getSubminor() const { return Version & 0xff; }
40
41 bool parse32(StringRef Str);
42 std::pair parse64(StringRef Str);
43
44 bool operator<(const PackedVersion &O) const { return Version < O.Version; }
45
46 bool operator==(const PackedVersion &O) const { return Version == O.Version; }
47
48 bool operator!=(const PackedVersion &O) const { return Version != O.Version; }
49
50 uint32_t rawValue() const { return Version; }
51
52 void print(raw_ostream &OS) const;
53 };
54
55 inline raw_ostream &operator<<(raw_ostream &OS, const PackedVersion &Version) {
56 Version.print(OS);
57 return OS;
58 }
59
60 } // end namespace MachO.
61 } // end namespace llvm.
62
63 #endif // LLVM_TEXTAPI_MACHO_PACKED_VERSION_H
0 //===- llvm/TextAPI/Symbol.h - TAPI Symbol ----------------------*- C++ -*-===//
1 //
2 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
3 // See https://llvm.org/LICENSE.txt for license information.
4 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
5 //
6 //===----------------------------------------------------------------------===//
7
8 #ifndef LLVM_TEXTAPI_MACHO_SYMBOL_H
9 #define LLVM_TEXTAPI_MACHO_SYMBOL_H
10
11 #include "llvm/ADT/BitmaskEnum.h"
12 #include "llvm/ADT/StringRef.h"
13 #include "llvm/Support/Error.h"
14 #include "llvm/Support/raw_ostream.h"
15 #include "llvm/TextAPI/MachO/ArchitectureSet.h"
16
17 namespace llvm {
18 namespace MachO {
19
20 // clang-format off
21
22 /// Symbol flags.
23 enum class SymbolFlags : uint8_t {
24 /// No flags
25 None = 0,
26
27 /// Thread-local value symbol
28 ThreadLocalValue = 1U << 0,
29
30 /// Weak defined symbol
31 WeakDefined = 1U << 1,
32
33 /// Weak referenced symbol
34 WeakReferenced = 1U << 2,
35
36 /// Undefined
37 Undefined = 1U << 3,
38
39 LLVM_MARK_AS_BITMASK_ENUM(/*LargestValue=*/Undefined),
40 };
41
42 // clang-format on
43
44 enum class SymbolKind : uint8_t {
45 GlobalSymbol,
46 ObjectiveCClass,
47 ObjectiveCClassEHType,
48 ObjectiveCInstanceVariable,
49 };
50
51 class Symbol {
52 public:
53 constexpr Symbol(SymbolKind Kind, StringRef Name,
54 ArchitectureSet Architectures, SymbolFlags Flags)
55 : Name(Name), Architectures(Architectures), Kind(Kind), Flags(Flags) {}
56
57 SymbolKind getKind() const { return Kind; }
58 StringRef getName() const { return Name; }
59 ArchitectureSet getArchitectures() const { return Architectures; }
60 void addArchitectures(ArchitectureSet Archs) { Architectures |= Archs; }
61 SymbolFlags getFlags() const { return Flags; }
62
63 bool isWeakDefined() const {
64 return (Flags & SymbolFlags::WeakDefined) == SymbolFlags::WeakDefined;
65 }
66
67 bool isWeakReferenced() const {
68 return (Flags & SymbolFlags::WeakReferenced) == SymbolFlags::WeakReferenced;
69 }
70
71 bool isThreadLocalValue() const {
72 return (Flags & SymbolFlags::ThreadLocalValue) ==
73 SymbolFlags::ThreadLocalValue;
74 }
75
76 bool isUndefined() const {
77 return (Flags & SymbolFlags::Undefined) == SymbolFlags::Undefined;
78 }
79
80 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
81 void dump(raw_ostream &OS) const;
82 void dump() const { dump(llvm::errs()); }
83 #endif
84
85 private:
86 StringRef Name;
87 ArchitectureSet Architectures;
88 SymbolKind Kind;
89 SymbolFlags Flags;
90 };
91
92 } // end namespace MachO.
93 } // end namespace llvm.
94
95 #endif // LLVM_TEXTAPI_MACHO_SYMBOL_H
0 //===--- TextAPIReader.h - Text API Reader ----------------------*- C++ -*-===//
1 //
2 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
3 // See https://llvm.org/LICENSE.txt for license information.
4 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
5 //
6 //===----------------------------------------------------------------------===//
7
8 #ifndef LLVM_TEXTAPI_MACHO_READER_H
9 #define LLVM_TEXTAPI_MACHO_READER_H
10
11 #include "llvm/Support/Error.h"
12 #include "llvm/Support/MemoryBuffer.h"
13
14 namespace llvm {
15 namespace MachO {
16
17 class InterfaceFile;
18
19 class TextAPIReader {
20 public:
21 static Expected>
22 get(std::unique_ptr InputBuffer);
23
24 static Expected>
25 getUnmanaged(llvm::MemoryBuffer *InputBuffer);
26
27 TextAPIReader() = delete;
28 };
29
30 } // end namespace MachO.
31 } // end namespace llvm.
32
33 #endif // LLVM_TEXTAPI_MACHO_READER_H
0 //===--- TextAPIWriter.h - Text API Writer ----------------------*- C++ -*-===//
1 //
2 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
3 // See https://llvm.org/LICENSE.txt for license information.
4 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
5 //
6 //===----------------------------------------------------------------------===//
7
8 #ifndef LLVM_TEXTAPI_MACHO_WRITER_H
9 #define LLVM_TEXTAPI_MACHO_WRITER_H
10
11 #include "llvm/Support/MemoryBuffer.h"
12
13 namespace llvm {
14 namespace MachO {
15
16 class InterfaceFile;
17
18 class TextAPIWriter {
19 public:
20 TextAPIWriter() = delete;
21
22 static Error writeToStream(raw_ostream &os, const InterfaceFile &);
23 };
24
25 } // end namespace MachO.
26 } // end namespace llvm.
27
28 #endif // LLVM_TEXTAPI_MACHO_WRITER_H
0 add_llvm_library(LLVMTextAPI
11 ELF/ELFStub.cpp
22 ELF/TBEHandler.cpp
3 MachO/Architecture.cpp
4 MachO/ArchitectureSet.cpp
5 MachO/InterfaceFile.cpp
6 MachO/PackedVersion.cpp
7 MachO/Symbol.cpp
8 MachO/TextStub.cpp
9 MachO/TextStubCommon.cpp
310
411 ADDITIONAL_HEADER_DIRS
512 "${LLVM_MAIN_INCLUDE_DIR}/llvm/TextAPI"
0 //===- Architecture.cpp ---------------------------------------------------===//
1 //
2 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
3 // See https://llvm.org/LICENSE.txt for license information.
4 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
5 //
6 //===----------------------------------------------------------------------===//
7 //
8 // Implements the architecture helper functions.
9 //
10 //===----------------------------------------------------------------------===//
11
12 #include "llvm/TextAPI/MachO/Architecture.h"
13 #include "llvm/ADT/StringSwitch.h"
14 #include "llvm/BinaryFormat/MachO.h"
15
16 namespace llvm {
17 namespace MachO {
18
19 Architecture getArchitectureFromCpuType(uint32_t CPUType, uint32_t CPUSubType) {
20 #define ARCHINFO(Arch, Type, Subtype) \
21 if (CPUType == (Type) && \
22 (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) == (Subtype)) \
23 return Architecture::Arch;
24 #include "llvm/TextAPI/MachO/Architecture.def"
25 #undef ARCHINFO
26
27 return Architecture::unknown;
28 }
29
30 Architecture getArchitectureFromName(StringRef Name) {
31 return StringSwitch(Name)
32 #define ARCHINFO(Arch, Type, Subtype) .Case(#Arch, Architecture::Arch)
33 #include "llvm/TextAPI/MachO/Architecture.def"
34 #undef ARCHINFO
35 .Default(Architecture::unknown);
36 }
37
38 StringRef getArchitectureName(Architecture Arch) {
39 switch (Arch) {
40 #define ARCHINFO(Arch, Type, Subtype) \
41 case Architecture::Arch: \
42 return #Arch;
43 #include "llvm/TextAPI/MachO/Architecture.def"
44 #undef ARCHINFO
45 case Architecture::unknown:
46 return "unknown";
47 }
48
49 // Appease some compilers that cannot figure out that this is a fully covered
50 // switch statement.
51 return "unknown";
52 }
53
54 std::pair getCPUTypeFromArchitecture(Architecture Arch) {
55 switch (Arch) {
56 #define ARCHINFO(Arch, Type, Subtype) \
57 case Architecture::Arch: \
58 return std::make_pair(Type, Subtype);
59 #include "llvm/TextAPI/MachO/Architecture.def"
60 #undef ARCHINFO
61 case Architecture::unknown:
62 return std::make_pair(0, 0);
63 }
64
65 // Appease some compilers that cannot figure out that this is a fully covered
66 // switch statement.
67 return std::make_pair(0, 0);
68 }
69
70 raw_ostream &operator<<(raw_ostream &OS, Architecture Arch) {
71 OS << getArchitectureName(Arch);
72 return OS;
73 }
74
75 } // end namespace MachO.
76 } // end namespace llvm.
0 //===- ArchitectureSet.cpp ------------------------------------------------===//
1 //
2 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
3 // See https://llvm.org/LICENSE.txt for license information.
4 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
5 //
6 //===----------------------------------------------------------------------===//
7 //
8 // Implements the architecture set.
9 //
10 //===----------------------------------------------------------------------===//
11
12 #include "llvm/TextAPI/MachO/ArchitectureSet.h"
13
14 namespace llvm {
15 namespace MachO {
16
17 ArchitectureSet::ArchitectureSet(const std::vector &Archs)
18 : ArchitectureSet() {
19 for (auto Arch : Archs) {
20 if (Arch == Architecture::unknown)
21 continue;
22 set(Arch);
23 }
24 }
25
26 size_t ArchitectureSet::count() const {
27 // popcnt
28 size_t Cnt = 0;
29 for (unsigned i = 0; i < sizeof(ArchSetType) * 8; ++i)
30 if (ArchSet & (1U << i))
31 ++Cnt;
32 return Cnt;
33 }
34
35 ArchitectureSet::operator std::string() const {
36 if (empty())
37 return "[(empty)]";
38
39 std::string result;
40 auto size = count();
41 for (auto arch : *this) {
42 result.append(getArchitectureName(arch));
43 size -= 1;
44 if (size)
45 result.append(" ");
46 }
47 return result;
48 }
49
50 ArchitectureSet::operator std::vector() const {
51 std::vector archs;
52 for (auto arch : *this) {
53 if (arch == Architecture::unknown)
54 continue;
55 archs.emplace_back(arch);
56 }
57 return archs;
58 }
59
60 void ArchitectureSet::print(raw_ostream &os) const { os << std::string(*this); }
61
62 raw_ostream &operator<<(raw_ostream &os, ArchitectureSet set) {
63 set.print(os);
64 return os;
65 }
66
67 } // end namespace MachO.
68 } // end namespace llvm.
0 //===- InterfaceFile.cpp --------------------------------------------------===//
1 //
2 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
3 // See https://llvm.org/LICENSE.txt for license information.
4 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
5 //
6 //===----------------------------------------------------------------------===//
7 //
8 // Implements the Interface File.
9 //
10 //===----------------------------------------------------------------------===//
11
12 #include "llvm/TextAPI/MachO/InterfaceFile.h"
13 #include
14 #include
15
16 using namespace llvm::MachO;
17
18 namespace llvm {
19 namespace MachO {
20 namespace detail {
21 template
22 typename C::iterator addEntry(C &Container, StringRef InstallName) {
23 auto I =
24 std::lower_bound(std::begin(Container), std::end(Container), InstallName,
25 [](const InterfaceFileRef &LHS, const StringRef &RHS) {
26 return LHS.getInstallName() < RHS;
27 });
28 if ((I != std::end(Container)) && !(InstallName < I->getInstallName()))
29 return I;
30
31 return Container.emplace(I, InstallName);
32 }
33 } // end namespace detail.
34
35 void InterfaceFile::addAllowableClient(StringRef Name,
36 ArchitectureSet Architectures) {
37 auto Client = detail::addEntry(AllowableClients, Name);
38 Client->addArchitectures(Architectures);
39 }
40
41 void InterfaceFile::addReexportedLibrary(StringRef InstallName,
42 ArchitectureSet Architectures) {
43 auto Lib = detail::addEntry(ReexportedLibraries, InstallName);
44 Lib->addArchitectures(Architectures);
45 }
46
47 void InterfaceFile::addUUID(Architecture Arch, StringRef UUID) {
48 auto I = std::lower_bound(UUIDs.begin(), UUIDs.end(), Arch,
49 [](const std::pair &LHS,
50 Architecture RHS) { return LHS.first < RHS; });
51
52 if ((I != UUIDs.end()) && !(Arch < I->first)) {
53 I->second = UUID;
54 return;
55 }
56
57 UUIDs.emplace(I, Arch, UUID);
58 return;
59 }
60
61 void InterfaceFile::addUUID(Architecture Arch, uint8_t UUID[16]) {
62 std::stringstream Stream;
63 for (unsigned i = 0; i < 16; ++i) {
64 if (i == 4 || i == 6 || i == 8 || i == 10)
65 Stream << '-';
66 Stream << std::setfill('0') << std::setw(2) << std::uppercase << std::hex
67 << static_cast(UUID[i]);
68 }
69 addUUID(Arch, Stream.str());
70 }
71
72 void InterfaceFile::addSymbol(SymbolKind Kind, StringRef Name,
73 ArchitectureSet Archs, SymbolFlags Flags) {
74 Name = copyString(Name);
75 auto result = Symbols.try_emplace(SymbolsMapKey{Kind, Name}, nullptr);
76 if (result.second)
77 result.first->second = new (Allocator) Symbol{Kind, Name, Archs, Flags};
78 else
79 result.first->second->addArchitectures(Archs);
80 }
81
82 } // end namespace MachO.
83 } // end namespace llvm.
0 //===- PackedVersion.cpp --------------------------------------------------===//
1 //
2 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
3 // See https://llvm.org/LICENSE.txt for license information.
4 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
5 //
6 //===----------------------------------------------------------------------===//
7 //
8 // Implements the Mach-O packed version.
9 //
10 //===----------------------------------------------------------------------===//
11
12 #include "llvm/TextAPI/MachO/PackedVersion.h"
13 #include "llvm/ADT/SmallString.h"
14 #include "llvm/ADT/SmallVector.h"
15 #include "llvm/ADT/StringExtras.h"
16 #include "llvm/Support/Format.h"
17 #include "llvm/Support/raw_ostream.h"
18
19 namespace llvm {
20 namespace MachO {
21
22 bool PackedVersion::parse32(StringRef Str) {
23 Version = 0;
24
25 if (Str.empty())
26 return false;
27
28 SmallVector Parts;
29 SplitString(Str, Parts, ".");
30
31 if (Parts.size() > 3)
32 return false;
33
34 unsigned long long Num;
35 if (getAsUnsignedInteger(Parts[0], 10, Num))
36 return false;
37
38 if (Num > UINT16_MAX)
39 return false;
40
41 Version = Num << 16;
42
43 for (unsigned i = 1, ShiftNum = 8; i < Parts.size(); ++i, ShiftNum -= 8) {
44 if (getAsUnsignedInteger(Parts[i], 10, Num))
45 return false;
46
47 if (Num > UINT8_MAX)
48 return false;
49
50 Version |= (Num << ShiftNum);
51 }
52
53 return true;
54 }
55
56 std::pair PackedVersion::parse64(StringRef Str) {
57 bool Truncated = false;
58 Version = 0;
59
60 if (Str.empty())
61 return std::make_pair(false, Truncated);
62
63 SmallVector Parts;
64 SplitString(Str, Parts, ".");
65
66 if (Parts.size() > 5)
67 return std::make_pair(false, Truncated);
68
69 unsigned long long Num;
70 if (getAsUnsignedInteger(Parts[0], 10, Num))
71 return std::make_pair(false, Truncated);
72
73 if (Num > 0xFFFFFFULL)
74 return std::make_pair(false, Truncated);
75
76 if (Num > 0xFFFFULL) {
77 Num = 0xFFFFULL;
78 Truncated = true;
79 }
80 Version = Num << 16;
81
82 for (unsigned i = 1, ShiftNum = 8; i < Parts.size() && i < 3;
83 ++i, ShiftNum -= 8) {
84 if (getAsUnsignedInteger(Parts[i], 10, Num))
85 return std::make_pair(false, Truncated);
86
87 if (Num > 0x3FFULL)
88 return std::make_pair(false, Truncated);
89
90 if (Num > 0xFFULL) {
91 Num = 0xFFULL;
92 Truncated = true;
93 }
94 Version |= (Num << ShiftNum);
95 }
96
97 if (Parts.size() > 3)
98 Truncated = true;
99
100 return std::make_pair(true, Truncated);
101 }
102
103 void PackedVersion::print(raw_ostream &OS) const {
104 OS << format("%d", getMajor());
105 if (getMinor() || getSubminor())
106 OS << format(".%d", getMinor());
107 if (getSubminor())
108 OS << format(".%d", getSubminor());
109 }
110
111 } // end namespace MachO.
112 } // end namespace llvm.
0 //===- Symbol.cpp ---------------------------------------------------------===//
1 //
2 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
3 // See https://llvm.org/LICENSE.txt for license information.
4 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
5 //
6 //===----------------------------------------------------------------------===//
7 //
8 // Implements the Symbol.
9 //
10 //===----------------------------------------------------------------------===//
11
12 #include "llvm/TextAPI/MachO/Symbol.h"
13 #include
14
15 namespace llvm {
16 namespace MachO {
17
18 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
19 LLVM_DUMP_METHOD void Symbol::dump(raw_ostream &OS) const {
20 std::string Result;
21 if (isUndefined())
22 Result += "(undef) ";
23 if (isWeakDefined())
24 Result += "(weak-def) ";
25 if (isWeakReferenced())
26 Result += "(weak-ref) ";
27 if (isThreadLocalValue())
28 Result += "(tlv) ";
29 switch (Kind) {
30 case SymbolKind::GlobalSymbol:
31 Result + Name.str();
32 break;
33 case SymbolKind::ObjectiveCClass:
34 Result + "(ObjC Class) " + Name.str();
35 break;
36 case SymbolKind::ObjectiveCClassEHType:
37 Result + "(ObjC Class EH) " + Name.str();
38 break;
39 case SymbolKind::ObjectiveCInstanceVariable:
40 Result + "(ObjC IVar) " + Name.str();
41 break;
42 }
43 OS << Result;
44 }
45 #endif
46
47 } // end namespace MachO.
48 } // end namespace llvm.
0 //===- TextAPIContext.h ---------------------------------------------------===//
1 //
2 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
3 // See https://llvm.org/LICENSE.txt for license information.
4 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
5 //
6 //===----------------------------------------------------------------------===//
7 //
8 // Defines the YAML Context for the TextAPI Reader/Writer.
9 //
10 //===----------------------------------------------------------------------===//
11
12 #ifndef LLVM_TEXTAPI_MACHO_CONTEXT_H
13 #define LLVM_TEXTAPI_MACHO_CONTEXT_H
14
15 #include "llvm/Support/MemoryBuffer.h"
16 #include
17
18 namespace llvm {
19 namespace MachO {
20
21 enum FileType : unsigned;
22
23 struct TextAPIContext {
24 std::string ErrorMessage;
25 std::string Path;
26 FileType FileKind;
27 };
28
29 } // end namespace MachO.
30 } // end namespace llvm.
31
32 #endif // LLVM_TEXTAPI_MACHO_CONTEXT_H
0 //===- TextStub.cpp -------------------------------------------------------===//
1 //
2 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
3 // See https://llvm.org/LICENSE.txt for license information.
4 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
5 //
6 //===----------------------------------------------------------------------===//
7 //
8 // Implements the text stub file reader/writer.
9 //
10 //===----------------------------------------------------------------------===//
11
12 #include "TextAPIContext.h"
13 #include "TextStubCommon.h"
14 #include "llvm/ADT/BitmaskEnum.h"
15 #include "llvm/ADT/SmallString.h"
16 #include "llvm/ADT/StringRef.h"
17 #include "llvm/Support/Allocator.h"
18 #include "llvm/Support/SourceMgr.h"
19 #include "llvm/Support/YAMLTraits.h"
20 #include "llvm/Support/raw_ostream.h"
21 #include "llvm/TextAPI/MachO/Architecture.h"
22 #include "llvm/TextAPI/MachO/ArchitectureSet.h"
23 #include "llvm/TextAPI/MachO/InterfaceFile.h"
24 #include "llvm/TextAPI/MachO/PackedVersion.h"
25 #include "llvm/TextAPI/MachO/TextAPIReader.h"
26 #include "llvm/TextAPI/MachO/TextAPIWriter.h"
27 #include
28 #include
29
30 // clang-format off
31 /*
32
33 YAML Format specification.
34
35 The TBD v1 format only support two level address libraries and is per
36 definition application extension safe.
37
38 --- # the tag !tapi-tbd-v1 is optional and
39 # shouldn't be emitted to support older linker.
40 archs: [ armv7, armv7s, arm64 ] # the list of architecture slices that are
41 # supported by this file.
42 platform: ios # Specifies the platform (macosx, ios, etc)
43 install-name: /u/l/libfoo.dylib #
44 current-version: 1.2.3 # Optional: defaults to 1.0
45 compatibility-version: 1.0 # Optional: defaults to 1.0
46 swift-version: 0 # Optional: defaults to 0
47 objc-constraint: none # Optional: defaults to none
48 exports: # List of export sections
49 ...
50
51 Each export section is defined as following:
52
53 - archs: [ arm64 ] # the list of architecture slices
54 allowed-clients: [ client ] # Optional: List of clients
55 re-exports: [ ] # Optional: List of re-exports
56 symbols: [ _sym ] # Optional: List of symbols
57 objc-classes: [] # Optional: List of Objective-C classes
58 objc-ivars: [] # Optional: List of Objective C Instance
59 # Variables
60 weak-def-symbols: [] # Optional: List of weak defined symbols
61 thread-local-symbols: [] # Optional: List of thread local symbols
62 */
63
64 /*
65
66 YAML Format specification.
67
68 --- !tapi-tbd-v2
69 archs: [ armv7, armv7s, arm64 ] # the list of architecture slices that are
70 # supported by this file.
71 uuids: [ armv7:... ] # Optional: List of architecture and UUID pairs.
72 platform: ios # Specifies the platform (macosx, ios, etc)
73 flags: [] # Optional:
74 install-name: /u/l/libfoo.dylib #
75 current-version: 1.2.3 # Optional: defaults to 1.0
76 compatibility-version: 1.0 # Optional: defaults to 1.0
77 swift-version: 0 # Optional: defaults to 0
78 objc-constraint: retain_release # Optional: defaults to retain_release
79 parent-umbrella: # Optional:
80 exports: # List of export sections
81 ...
82 undefineds: # List of undefineds sections
83 ...
84
85 Each export section is defined as following:
86
87 - archs: [ arm64 ] # the list of architecture slices
88 allowed-clients: [ client ] # Optional: List of clients
89 re-exports: [ ] # Optional: List of re-exports
90 symbols: [ _sym ] # Optional: List of symbols
91 objc-classes: [] # Optional: List of Objective-C classes
92 objc-ivars: [] # Optional: List of Objective C Instance
93 # Variables
94 weak-def-symbols: [] # Optional: List of weak defined symbols
95 thread-local-symbols: [] # Optional: List of thread local symbols
96
97 Each undefineds section is defined as following:
98 - archs: [ arm64 ] # the list of architecture slices
99 symbols: [ _sym ] # Optional: List of symbols
100 objc-classes: [] # Optional: List of Objective-C classes
101 objc-ivars: [] # Optional: List of Objective C Instance Variables
102 weak-ref-symbols: [] # Optional: List of weak defined symbols
103 */
104
105 /*
106
107 YAML Format specification.
108
109 --- !tapi-tbd-v3
110 archs: [ armv7, armv7s, arm64 ] # the list of architecture slices that are
111 # supported by this file.
112 uuids: [ armv7:... ] # Optional: List of architecture and UUID pairs.
113 platform: ios # Specifies the platform (macosx, ios, etc)
114 flags: [] # Optional:
115 install-name: /u/l/libfoo.dylib #
116 current-version: 1.2.3 # Optional: defaults to 1.0
117 compatibility-version: 1.0 # Optional: defaults to 1.0
118 swift-abi-version: 0 # Optional: defaults to 0
119 objc-constraint: retain_release # Optional: defaults to retain_release
120 parent-umbrella: # Optional:
121 exports: # List of export sections
122 ...
123 undefineds: # List of undefineds sections
124 ...
125
126 Each export section is defined as following:
127
128 - archs: [ arm64 ] # the list of architecture slices
129 allowed-clients: [ client ] # Optional: List of clients
130 re-exports: [ ] # Optional: List of re-exports
131 symbols: [ _sym ] # Optional: List of symbols
132 objc-classes: [] # Optional: List of Objective-C classes
133 objc-eh-types: [] # Optional: List of Objective-C classes
134 # with EH
135 objc-ivars: [] # Optional: List of Objective C Instance
136 # Variables
137 weak-def-symbols: [] # Optional: List of weak defined symbols
138 thread-local-symbols: [] # Optional: List of thread local symbols
139
140 Each undefineds section is defined as following:
141 - archs: [ arm64 ] # the list of architecture slices
142 symbols: [ _sym ] # Optional: List of symbols
143 objc-classes: [] # Optional: List of Objective-C classes
144 objc-eh-types: [] # Optional: List of Objective-C classes
145 # with EH
146 objc-ivars: [] # Optional: List of Objective C Instance Variables
147 weak-ref-symbols: [] # Optional: List of weak defined symbols
148 */
149 // clang-format on
150
151 using namespace llvm;
152 using namespace llvm::yaml;
153 using namespace llvm::MachO;
154
155 namespace {
156 struct ExportSection {
157 std::vector Architectures;
158 std::vector AllowableClients;
159 std::vector ReexportedLibraries;
160 std::vector Symbols;
161 std::vector Classes;
162 std::vector ClassEHs;
163 std::vector IVars;
164 std::vector WeakDefSymbols;
165 std::vector TLVSymbols;
166 };
167
168 struct UndefinedSection {
169 std::vector Architectures;
170 std::vector Symbols;
171 std::vector Classes;
172 std::vector ClassEHs;
173 std::vector IVars;
174 std::vector WeakRefSymbols;
175 };
176
177 // clang-format off
178 enum TBDFlags : unsigned {
179 None = 0U,
180 FlatNamespace = 1U << 0,
181 NotApplicationExtensionSafe = 1U << 1,
182 InstallAPI = 1U << 2,
183 LLVM_MARK_AS_BITMASK_ENUM(/*LargestValue=*/InstallAPI),
184 };
185 // clang-format on
186 } // end anonymous namespace.
187
188 LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(Architecture)
189 LLVM_YAML_IS_SEQUENCE_VECTOR(ExportSection)
190 LLVM_YAML_IS_SEQUENCE_VECTOR(UndefinedSection)
191
192 namespace llvm {
193 namespace yaml {
194
195 template <> struct MappingTraits {
196 static void mapping(IO &IO, ExportSection &Section) {
197 const auto *Ctx = reinterpret_cast(IO.getContext());
198 assert((!Ctx || (Ctx && Ctx->FileKind != FileType::Invalid)) &&
199 "File type is not set in YAML context");
200
201 IO.mapRequired("archs", Section.Architectures);
202 if (Ctx->FileKind == FileType::TBD_V1)
203 IO.mapOptional("allowed-clients", Section.AllowableClients);
204 else
205 IO.mapOptional("allowable-clients", Section.AllowableClients);
206 IO.mapOptional("re-exports", Section.ReexportedLibraries);
207 IO.mapOptional("symbols", Section.Symbols);
208 IO.mapOptional("objc-classes", Section.Classes);
209 if (Ctx->FileKind == FileType::TBD_V3)
210 IO.mapOptional("objc-eh-types", Section.ClassEHs);
211 IO.mapOptional("objc-ivars", Section.IVars);
212 IO.mapOptional("weak-def-symbols", Section.WeakDefSymbols);
213 IO.mapOptional("thread-local-symbols", Section.TLVSymbols);
214 }
215 };
216
217 template <> struct MappingTraits {
218 static void mapping(IO &IO, UndefinedSection &Section) {
219 const auto *Ctx = reinterpret_cast(IO.getContext());
220 assert((!Ctx || (Ctx && Ctx->FileKind != FileType::Invalid)) &&
221 "File type is not set in YAML context");
222
223 IO.mapRequired("archs", Section.Architectures);
224 IO.mapOptional("symbols", Section.Symbols);
225 IO.mapOptional("objc-classes", Section.Classes);
226 if (Ctx->FileKind == FileType::TBD_V3)
227 IO.mapOptional("objc-eh-types", Section.ClassEHs);
228 IO.mapOptional("objc-ivars", Section.IVars);
229 IO.mapOptional("weak-ref-symbols", Section.WeakRefSymbols);
230 }
231 };
232
233 template <> struct ScalarBitSetTraits {
234 static void bitset(IO &IO, TBDFlags &Flags) {
235 IO.bitSetCase(Flags, "flat_namespace", TBDFlags::FlatNamespace);
236 IO.bitSetCase(Flags, "not_app_extension_safe",
237 TBDFlags::NotApplicationExtensionSafe);
238 IO.bitSetCase(Flags, "installapi", TBDFlags::InstallAPI);
239 }
240 };
241
242 template <> struct MappingTraits {
243 struct NormalizedTBD {
244 explicit NormalizedTBD(IO &IO) {}
245 NormalizedTBD(IO &IO, const InterfaceFile *&File) {
246 Architectures = File->getArchitectures();
247 UUIDs = File->uuids();
248 Platform = File->getPlatform();
249 InstallName = File->getInstallName();
250 CurrentVersion = PackedVersion(File->getCurrentVersion());
251 CompatibilityVersion = PackedVersion(File->getCompatibilityVersion());
252 SwiftABIVersion = File->getSwiftABIVersion();
253 ObjCConstraint = File->getObjCConstraint();
254
255 Flags = TBDFlags::None;
256 if (!File->isApplicationExtensionSafe())
257 Flags |= TBDFlags::NotApplicationExtensionSafe;
258
259 if (!File->isTwoLevelNamespace())
260 Flags |= TBDFlags::FlatNamespace;
261
262 if (File->isInstallAPI())
263 Flags |= TBDFlags::InstallAPI;
264
265 ParentUmbrella = File->getParentUmbrella();
266
267 std::set ArchSet;
268 for (const auto &Library : File->allowableClients())
269 ArchSet.insert(Library.getArchitectures());
270
271 for (const auto &Library : File->reexportedLibraries())
272 ArchSet.insert(Library.getArchitectures());
273
274 std::map SymbolToArchSet;
275 for (const auto *Symbol : File->exports()) {
276 auto Architectures = Symbol->getArchitectures();
277 SymbolToArchSet[Symbol] = Architectures;
278 ArchSet.insert(Architectures);
279 }
280
281 for (auto Architectures : ArchSet) {
282 ExportSection Section;
283 Section.Architectures = Architectures;
284
285 for (const auto &Library : File->allowableClients())
286 if (Library.getArchitectures() == Architectures)
287 Section.AllowableClients.emplace_back(Library.getInstallName());
288
289 for (const auto &Library : File->reexportedLibraries())
290 if (Library.getArchitectures() == Architectures)
291 Section.ReexportedLibraries.emplace_back(Library.getInstallName());
292
293 for (const auto &SymArch : SymbolToArchSet) {
294 if (SymArch.second != Architectures)
295 continue;
296
297 const auto *Symbol = SymArch.first;
298 switch (Symbol->getKind()) {
299 case SymbolKind::GlobalSymbol:
300 if (Symbol->isWeakDefined())
301 Section.WeakDefSymbols.emplace_back(Symbol->getName());
302 else if (Symbol->isThreadLocalValue())
303 Section.TLVSymbols.emplace_back(Symbol->getName());
304 else
305 Section.Symbols.emplace_back(Symbol->getName());
306 break;
307 case SymbolKind::ObjectiveCClass:
308 if (File->getFileType() != FileType::TBD_V3)
309 Section.Classes.emplace_back(
310 copyString("_" + Symbol->getName().str()));
311 else
312 Section.Classes.emplace_back(Symbol->getName());
313 break;
314 case SymbolKind::ObjectiveCClassEHType:
315 if (File->getFileType() != FileType::TBD_V3)
316 Section.Symbols.emplace_back(
317 copyString("_OBJC_EHTYPE_$_" + Symbol->getName().str()));
318 else
319 Section.ClassEHs.emplace_back(Symbol->getName());
320 break;
321 case SymbolKind::ObjectiveCInstanceVariable:
322 if (File->getFileType() != FileType::TBD_V3)
323 Section.IVars.emplace_back(
324 copyString("_" + Symbol->getName().str()));
325 else
326 Section.IVars.emplace_back(Symbol->getName());
327 break;
328 }
329 }
330 llvm::sort(Section.Symbols.begin(), Section.Symbols.end());
331 llvm::sort(Section.Classes.begin(), Section.Classes.end());
332 llvm::sort(Section.ClassEHs.begin(), Section.ClassEHs.end());
333 llvm::sort(Section.IVars.begin(), Section.IVars.end());
334 llvm::sort(Section.WeakDefSymbols.begin(),
335 Section.WeakDefSymbols.end());
336 llvm::sort(Section.TLVSymbols.begin(), Section.TLVSymbols.end());
337 Exports.emplace_back(std::move(Section));
338 }
339
340 ArchSet.clear();
341 SymbolToArchSet.clear();
342
343 for (const auto *Symbol : File->undefineds()) {
344 auto Architectures = Symbol->getArchitectures();
345 SymbolToArchSet[Symbol] = Architectures;
346 ArchSet.insert(Architectures);
347 }
348
349 for (auto Architectures : ArchSet) {
350 UndefinedSection Section;
351 Section.Architectures = Architectures;
352
353 for (const auto &SymArch : SymbolToArchSet) {
354 if (SymArch.second != Architectures)
355 continue;
356
357 const auto *Symbol = SymArch.first;
358 switch (Symbol->getKind()) {
359 case SymbolKind::GlobalSymbol:
360 if (Symbol->isWeakReferenced())
361 Section.WeakRefSymbols.emplace_back(Symbol->getName());
362 else
363 Section.Symbols.emplace_back(Symbol->getName());
364 break;
365 case SymbolKind::ObjectiveCClass:
366 if (File->getFileType() != FileType::TBD_V3)
367 Section.Classes.emplace_back(
368 copyString("_" + Symbol->getName().str()));
369 else
370 Section.Classes.emplace_back(Symbol->getName());
371 break;
372 case SymbolKind::ObjectiveCClassEHType:
373 if (File->getFileType() != FileType::TBD_V3)
374 Section.Symbols.emplace_back(
375 copyString("_OBJC_EHTYPE_$_" + Symbol->getName().str()));
376 else
377 Section.ClassEHs.emplace_back(Symbol->getName());
378 break;
379 case SymbolKind::ObjectiveCInstanceVariable:
380 if (File->getFileType() != FileType::TBD_V3)
381 Section.IVars.emplace_back(
382 copyString("_" + Symbol->getName().str()));
383 else
384 Section.IVars.emplace_back(Symbol->getName());
385 break;
386 }
387 }
388 llvm::sort(Section.Symbols.begin(), Section.Symbols.end());
389 llvm::sort(Section.Classes.begin(), Section.Classes.end());
390 llvm::sort(Section.ClassEHs.begin(), Section.ClassEHs.end());
391 llvm::sort(Section.IVars.begin(), Section.IVars.end());
392 llvm::sort(Section.WeakRefSymbols.begin(),
393 Section.WeakRefSymbols.end());
394 Undefineds.emplace_back(std::move(Section));
395 }
396 }
397
398 const InterfaceFile *denormalize(IO &IO) {
399 auto Ctx = reinterpret_cast(IO.getContext());
400 assert(Ctx);
401
402 auto *File = new InterfaceFile;
403 File->setPath(Ctx->Path);
404 File->setFileType(Ctx->FileKind);
405 for (auto &ID : UUIDs)
406 File->addUUID(ID.first, ID.second);
407 File->setPlatform(Platform);
408 File->setArchitectures(Architectures);
409 File->setInstallName(InstallName);
410 File->setCurrentVersion(CurrentVersion);
411 File->setCompatibilityVersion(CompatibilityVersion);
412 File->setSwiftABIVersion(SwiftABIVersion);
413 File->setObjCConstraint(ObjCConstraint);
414 File->setParentUmbrella(ParentUmbrella);
415
416 if (Ctx->FileKind == FileType::TBD_V1) {
417 File->setTwoLevelNamespace();
418 File->setApplicationExtensionSafe();
419 } else {
420 File->setTwoLevelNamespace(!(Flags & TBDFlags::FlatNamespace));
421 File->setApplicationExtensionSafe(
422 !(Flags & TBDFlags::NotApplicationExtensionSafe));
423 File->setInstallAPI(Flags & TBDFlags::InstallAPI);
424 }
425
426 for (const auto &Section : Exports) {
427 for (const auto &Library : Section.AllowableClients)
428 File->addAllowableClient(Library, Section.Architectures);
429 for (const auto &Library : Section.ReexportedLibraries)
430 File->addReexportedLibrary(Library, Section.Architectures);
431
432 for (const auto &Symbol : Section.Symbols) {
433 if (Ctx->FileKind != FileType::TBD_V3 &&
434 Symbol.value.startswith("_OBJC_EHTYPE_$_"))
435 File->addSymbol(SymbolKind::ObjectiveCClassEHType,
436 Symbol.value.drop_front(15), Section.Architectures);
437 else
438 File->addSymbol(SymbolKind::GlobalSymbol, Symbol,
439 Section.Architectures);
440 }
441 for (auto &Symbol : Section.Classes) {
442 auto Name = Symbol.value;
443 if (Ctx->FileKind != FileType::TBD_V3)
444 Name = Name.drop_front();
445 File->addSymbol(SymbolKind::ObjectiveCClass, Name,
446 Section.Architectures);
447 }
448 for (auto &Symbol : Section.ClassEHs)
449 File->addSymbol(SymbolKind::ObjectiveCClassEHType, Symbol,
450 Section.Architectures);
451 for (auto &Symbol : Section.IVars) {
452 auto Name = Symbol.value;
453 if (Ctx->FileKind != FileType::TBD_V3)
454 Name = Name.drop_front();
455 File->addSymbol(SymbolKind::ObjectiveCInstanceVariable, Name,
456 Section.Architectures);
457 }
458 for (auto &Symbol : Section.WeakDefSymbols)
459 File->addSymbol(SymbolKind::GlobalSymbol, Symbol,
460 Section.Architectures, SymbolFlags::WeakDefined);
461 for (auto &Symbol : Section.TLVSymbols)
462 File->addSymbol(SymbolKind::GlobalSymbol, Symbol,
463 Section.Architectures, SymbolFlags::ThreadLocalValue);
464 }
465
466 for (const auto &Section : Undefineds) {
467 for (auto &Symbol : Section.Symbols) {
468 if (Ctx->FileKind != FileType::TBD_V3 &&
469 Symbol.value.startswith("_OBJC_EHTYPE_$_"))
470 File->addSymbol(SymbolKind::ObjectiveCClassEHType,
471 Symbol.value.drop_front(15), Section.Architectures,
472 SymbolFlags::Undefined);
473 else
474 File->addSymbol(SymbolKind::GlobalSymbol, Symbol,
475 Section.Architectures, SymbolFlags::Undefined);
476 }
477 for (auto &Symbol : Section.Classes) {
478 auto Name = Symbol.value;
479 if (Ctx->FileKind != FileType::TBD_V3)
480 Name = Name.drop_front();
481 File->addSymbol(SymbolKind::ObjectiveCClass, Name,
482 Section.Architectures, SymbolFlags::Undefined);
483 }
484 for (auto &Symbol : Section.ClassEHs)
485 File->addSymbol(SymbolKind::ObjectiveCClassEHType, Symbol,
486 Section.Architectures, SymbolFlags::Undefined);
487 for (auto &Symbol : Section.IVars) {
488 auto Name = Symbol.value;
489 if (Ctx->FileKind != FileType::TBD_V3)
490 Name = Name.drop_front();
491 File->addSymbol(SymbolKind::ObjectiveCInstanceVariable, Name,
492 Section.Architectures, SymbolFlags::Undefined);
493 }
494 for (auto &Symbol : Section.WeakRefSymbols)
495 File->addSymbol(SymbolKind::GlobalSymbol, Symbol,
496 Section.Architectures,
497 SymbolFlags::Undefined | SymbolFlags::WeakReferenced);
498 }
499
500 return File;
501 }
502
503 llvm::BumpPtrAllocator Allocator;
504 StringRef copyString(StringRef String) {
505 if (String.empty())
506 return {};
507
508 void *Ptr = Allocator.Allocate(String.size(), 1);
509 memcpy(Ptr, String.data(), String.size());
510 return StringRef(reinterpret_cast(Ptr), String.size());
511 }
512
513 std::vector Architectures;
514 std::vector UUIDs;
515 PlatformKind Platform{PlatformKind::unknown};
516 StringRef InstallName;
517 PackedVersion CurrentVersion;
518 PackedVersion CompatibilityVersion;
519 SwiftVersion SwiftABIVersion{0};
520 ObjCConstraintType ObjCConstraint{ObjCConstraintType::None};
521 TBDFlags Flags{TBDFlags::None};
522 StringRef ParentUmbrella;
523 std::vector Exports;
524 std::vector Undefineds;
525 };
526
527 static void mapping(IO &IO, const InterfaceFile *&File) {
528 auto *Ctx = reinterpret_cast(IO.getContext());
529 assert((!Ctx || !IO.outputting() ||
530 (Ctx && Ctx->FileKind != FileType::Invalid)) &&
531 "File type is not set in YAML context");
532 MappingNormalization Keys(IO, File);
533
534 // prope file type when reading.
535 if (!IO.outputting()) {
536 if (IO.mapTag("!tapi-tbd-v2", false))
537 Ctx->FileKind = FileType::TBD_V2;
538 else if (IO.mapTag("!tapi-tbd-v3", false))
539 Ctx->FileKind = FileType::TBD_V2;
540 else if (IO.mapTag("!tapi-tbd-v1", false) ||
541 IO.mapTag("tag:yaml.org,2002:map", false))
542 Ctx->FileKind = FileType::TBD_V1;
543 else {
544 IO.setError("unsupported file type");
545 return;
546 }
547 }
548
549 // Set file tyoe when writing.
550 if (IO.outputting()) {
551 switch (Ctx->FileKind) {
552 default:
553 llvm_unreachable("unexpected file type");
554 case FileType::TBD_V1:
555 // Don't write the tag into the .tbd file for TBD v1.
556 break;
557 case FileType::TBD_V2:
558 IO.mapTag("!tapi-tbd-v2", true);
559 break;
560 case FileType::TBD_V3:
561 IO.mapTag("!tapi-tbd-v3", true);
562 break;
563 }
564 }
565
566 IO.mapRequired("archs", Keys->Architectures);
567 if (Ctx->FileKind != FileType::TBD_V1)
568 IO.mapOptional("uuids", Keys->UUIDs);
569 IO.mapRequired("platform", Keys->Platform);
570 if (Ctx->FileKind != FileType::TBD_V1)
571 IO.mapOptional("flags", Keys->Flags, TBDFlags::None);
572 IO.mapRequired("install-name", Keys->InstallName);
573 IO.mapOptional("current-version", Keys->CurrentVersion,
574 PackedVersion(1, 0, 0));
575 IO.mapOptional("compatibility-version", Keys->CompatibilityVersion,
576 PackedVersion(1, 0, 0));
577 if (Ctx->FileKind != FileType::TBD_V3)
578 IO.mapOptional("swift-version", Keys->SwiftABIVersion, SwiftVersion(0));
579 else
580 IO.mapOptional("swift-abi-version", Keys->SwiftABIVersion,
581 SwiftVersion(0));
582 IO.mapOptional("objc-constraint", Keys->ObjCConstraint,
583 (Ctx->FileKind == FileType::TBD_V1)
584 ? ObjCConstraintType::None
585 : ObjCConstraintType::Retain_Release);
586 if (Ctx->FileKind != FileType::TBD_V1)
587 IO.mapOptional("parent-umbrella", Keys->ParentUmbrella, StringRef());
588 IO.mapOptional("exports", Keys->Exports);
589 if (Ctx->FileKind != FileType::TBD_V1)
590 IO.mapOptional("undefineds", Keys->Undefineds);
591 }
592 };
593
594 template <>
595 struct DocumentListTraits> {
596 static size_t size(IO &IO, std::vector &Seq) {
597 return Seq.size();
598 }
599 static const InterfaceFile *&
600 element(IO &IO, std::vector &Seq, size_t Index) {
601 if (Index >= Seq.size())
602 Seq.resize(Index + 1);
603 return Seq[Index];
604 }
605 };
606
607 } // end namespace yaml.
608
609 namespace MachO {
610 static void DiagHandler(const SMDiagnostic &Diag, void *Context) {
611 auto *File = static_cast(Context);
612 SmallString<1024> Message;
613 raw_svector_ostream S(Message);
614
615 SMDiagnostic NewDiag(*Diag.getSourceMgr(), Diag.getLoc(), File->Path,
616 Diag.getLineNo(), Diag.getColumnNo(), Diag.getKind(),
617 Diag.getMessage(), Diag.getLineContents(),
618 Diag.getRanges(), Diag.getFixIts());
619
620 NewDiag.print(nullptr, S);
621 File->ErrorMessage = ("malformed file\n" + Message).str();
622 }
623
624 Expected>
625 TextAPIReader::get(std::unique_ptr InputBuffer) {
626 TextAPIContext Ctx;
627 Ctx.Path = InputBuffer->getBufferIdentifier();
628 yaml::Input YAMLIn(InputBuffer->getBuffer(), &Ctx, DiagHandler, &Ctx);
629
630 // Fill vector with interface file objects created by parsing the YAML file.
631 std::vector Files;
632 YAMLIn >> Files;
633
634 auto File = std::unique_ptr(
635 const_cast(Files.front()));
636
637 if (YAMLIn.error())
638 return make_error(Ctx.ErrorMessage, YAMLIn.error());
639
640 return File;
641 }
642
643 Error TextAPIWriter::writeToStream(raw_ostream &OS, const InterfaceFile &File) {
644 TextAPIContext Ctx;
645 Ctx.Path = File.getPath();
646 Ctx.FileKind = File.getFileType();
647 llvm::yaml::Output YAMLOut(OS, &Ctx, /*WrapColumn=*/80);
648
649 std::vector Files;
650 Files.emplace_back(&File);
651
652 // Stream out yaml.
653 YAMLOut << Files;
654
655 return Error::success();
656 }
657
658 } // end namespace MachO.
659 } // end namespace llvm.
0 //===- TextStubCommon.cpp -------------------------------------------------===//
1 //
2 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
3 // See https://llvm.org/LICENSE.txt for license information.
4 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
5 //
6 //===----------------------------------------------------------------------===//
7 //
8 // Implememts common Text Stub YAML mappings.
9 //
10 //===----------------------------------------------------------------------===//
11
12 #include "TextStubCommon.h"
13 #include "TextAPIContext.h"
14
15 using namespace llvm::MachO;
16
17 namespace llvm {
18 namespace yaml {
19
20 void ScalarTraits::output(const FlowStringRef &Value, void *Ctx,
21 raw_ostream &OS) {
22 ScalarTraits::output(Value, Ctx, OS);
23 }
24 StringRef ScalarTraits::input(StringRef Value, void *Ctx,
25 FlowStringRef &Out) {
26 return ScalarTraits::input(Value, Ctx, Out.value);
27 }
28 QuotingType ScalarTraits::mustQuote(StringRef Name) {
29 return ScalarTraits::mustQuote(Name);
30 }
31
32 void ScalarEnumerationTraits::enumeration(
33 IO &IO, ObjCConstraintType &Constraint) {
34 IO.enumCase(Constraint, "none", ObjCConstraintType::None);
35 IO.enumCase(Constraint, "retain_release", ObjCConstraintType::Retain_Release);
36 IO.enumCase(Constraint, "retain_release_for_simulator",
37 ObjCConstraintType::Retain_Release_For_Simulator);
38 IO.enumCase(Constraint, "retain_release_or_gc",
39 ObjCConstraintType::Retain_Release_Or_GC);
40 IO.enumCase(Constraint, "gc", ObjCConstraintType::GC);
41 }
42
43 void ScalarTraits::output(const PlatformKind &Value, void *,
44 raw_ostream &OS) {
45 switch (Value) {
46 default:
47 llvm_unreachable("unexpected platform");
48 break;
49 case PlatformKind::macOS:
50 OS << "macosx";
51 break;
52 case PlatformKind::iOS:
53 OS << "ios";
54 break;
55 case PlatformKind::watchOS:
56 OS << "watchos";
57 break;
58 case PlatformKind::tvOS:
59 OS << "tvos";
60 break;
61 case PlatformKind::bridgeOS:
62 OS << "bridgeos";
63 break;
64 }
65 }
66 StringRef ScalarTraits::input(StringRef Scalar, void *,
67 PlatformKind &Value) {
68 Value = StringSwitch(Scalar)
69 .Case("macosx", PlatformKind::macOS)
70 .Case("ios", PlatformKind::iOS)
71 .Case("watchos", PlatformKind::watchOS)
72 .Case("tvos", PlatformKind::tvOS)
73 .Case("bridgeos", PlatformKind::bridgeOS)
74 .Default(PlatformKind::unknown);
75
76 if (Value == PlatformKind::unknown)
77 return "unknown platform";
78 return {};
79 }
80 QuotingType ScalarTraits::mustQuote(StringRef) {
81 return QuotingType::None;
82 }
83
84 void ScalarBitSetTraits::bitset(IO &IO,
85 ArchitectureSet &Archs) {
86 #define ARCHINFO(arch, type, subtype) \
87 IO.bitSetCase(Archs, #arch, 1U << static_cast(Architecture::arch));
88 #include "llvm/TextAPI/MachO/Architecture.def"
89 #undef ARCHINFO
90 }
91
92 void ScalarTraits::output(const Architecture &Value, void *,
93 raw_ostream &OS) {
94 OS << Value;
95 }
96 StringRef ScalarTraits::input(StringRef Scalar, void *,
97 Architecture &Value) {
98 Value = getArchitectureFromName(Scalar);
99 return {};
100 }
101 QuotingType ScalarTraits::mustQuote(StringRef) {
102 return QuotingType::None;
103 }
104
105 void ScalarTraits::output(const PackedVersion &Value, void *,
106 raw_ostream &OS) {
107 OS << Value;
108 }
109 StringRef ScalarTraits::input(StringRef Scalar, void *,
110 PackedVersion &Value) {
111 if (!Value.parse32(Scalar))
112 return "invalid packed version string.";
113 return {};
114 }
115 QuotingType ScalarTraits::mustQuote(StringRef) {
116 return QuotingType::None;
117 }
118
119 void ScalarTraits::output(const SwiftVersion &Value, void *,
120 raw_ostream &OS) {
121 switch (Value) {
122 case 1:
123 OS << "1.0";
124 break;
125 case 2:
126 OS << "1.1";
127 break;
128 case 3:
129 OS << "2.0";
130 break;
131 case 4:
132 OS << "3.0";
133 break;
134 default:
135 OS << (unsigned)Value;
136 break;
137 }
138 }
139 StringRef ScalarTraits::input(StringRef Scalar, void *,
140 SwiftVersion &Value) {
141 Value = StringSwitch(Scalar)
142 .Case("1.0", 1)
143 .Case("1.1", 2)
144 .Case("2.0", 3)
145 .Case("3.0", 4)
146 .Default(0);
147 if (Value != SwiftVersion(0))
148 return {};
149
150 if (Scalar.getAsInteger(10, Value))
151 return "invalid Swift ABI version.";
152
153 return StringRef();
154 }
155 QuotingType ScalarTraits::mustQuote(StringRef) {
156 return QuotingType::None;
157 }
158
159 void ScalarTraits::output(const UUID &Value, void *, raw_ostream &OS) {
160 OS << Value.first << ": " << Value.second;
161 }
162 StringRef ScalarTraits::input(StringRef Scalar, void *, UUID &Value) {
163 auto Split = Scalar.split(':');
164 auto Arch = Split.first.trim();
165 auto UUID = Split.second.trim();
166 if (UUID.empty())
167 return "invalid uuid string pair";
168 Value.first = getArchitectureFromName(Arch);
169 Value.second = UUID;
170 return {};
171 }
172 QuotingType ScalarTraits::mustQuote(StringRef) {
173 return QuotingType::Single;
174 }
175
176 } // end namespace yaml.
177 } // end namespace llvm.
0 //===- TextStubCommon.h ---------------------------------------------------===//
1 //
2 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
3 // See https://llvm.org/LICENSE.txt for license information.
4 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
5 //
6 //===----------------------------------------------------------------------===//
7 //
8 // Defines common Text Stub YAML mappings.
9 //
10 //===----------------------------------------------------------------------===//
11
12 #ifndef LLVM_TEXTAPI_TEXT_STUB_COMMON_H
13 #define LLVM_TEXTAPI_TEXT_STUB_COMMON_H
14
15 #include "llvm/ADT/StringRef.h"
16 #include "llvm/ADT/StringSwitch.h"
17 #include "llvm/Support/YAMLTraits.h"
18 #include "llvm/TextAPI/MachO/Architecture.h"
19 #include "llvm/TextAPI/MachO/ArchitectureSet.h"
20 #include "llvm/TextAPI/MachO/InterfaceFile.h"
21 #include "llvm/TextAPI/MachO/PackedVersion.h"
22
23 using UUID = std::pair;
24
25 LLVM_YAML_STRONG_TYPEDEF(llvm::StringRef, FlowStringRef)
26 LLVM_YAML_STRONG_TYPEDEF(uint8_t, SwiftVersion)
27 LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(UUID)
28 LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(FlowStringRef)
29
30 namespace llvm {
31 namespace yaml {
32
33 template <> struct ScalarTraits {
34 static void output(const FlowStringRef &, void *, raw_ostream &);
35 static StringRef input(StringRef, void *, FlowStringRef &);
36 static QuotingType mustQuote(StringRef);
37 };
38
39 template <> struct ScalarEnumerationTraits {
40 static void enumeration(IO &, MachO::ObjCConstraintType &);
41 };
42
43 template <> struct ScalarTraits {
44 static void output(const MachO::PlatformKind &, void *, raw_ostream &);
45 static StringRef input(StringRef, void *, MachO::PlatformKind &);
46 static QuotingType mustQuote(StringRef);
47 };
48
49 template <> struct ScalarBitSetTraits {
50 static void bitset(IO &, MachO::ArchitectureSet &);
51 };
52
53 template <> struct ScalarTraits {
54 static void output(const MachO::Architecture &, void *, raw_ostream &);
55 static StringRef input(StringRef, void *, MachO::Architecture &);
56 static QuotingType mustQuote(StringRef);
57 };
58
59 template <> struct ScalarTraits {
60 static void output(const MachO::PackedVersion &, void *, raw_ostream &);
61 static StringRef input(StringRef, void *, MachO::PackedVersion &);
62 static QuotingType mustQuote(StringRef);
63 };
64
65 template <> struct ScalarTraits {
66 static void output(const SwiftVersion &, void *, raw_ostream &);
67 static StringRef input(StringRef, void *, SwiftVersion &);
68 static QuotingType mustQuote(StringRef);
69 };
70
71 template <> struct ScalarTraits {
72 static void output(const UUID &, void *, raw_ostream &);
73 static StringRef input(StringRef, void *, UUID &);
74 static QuotingType mustQuote(StringRef);
75 };
76
77 } // end namespace yaml.
78 } // end namespace llvm.
79
80 #endif // LLVM_TEXTAPI_TEXT_STUB_COMMON_H
33
44 add_llvm_unittest(TextAPITests
55 ELFYAMLTest.cpp
6 TextStubV1Tests.cpp
7 TextStubV2Tests.cpp
68 )
79
8 target_link_libraries(TextAPITests PRIVATE LLVMTestingSupport)
10 target_link_libraries(TextAPITests PRIVATE LLVMTestingSupport)
0 //===-- TextStubV1Tests.cpp - TBD V1 File Test ----------------------------===//
1 //
2 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
3 // See https://llvm.org/LICENSE.txt for license information.
4 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
5 //
6 //===-----------------------------------------------------------------------===/
7
8 #include "llvm/TextAPI/MachO/InterfaceFile.h"
9 #include "llvm/TextAPI/MachO/TextAPIReader.h"
10 #include "llvm/TextAPI/MachO/TextAPIWriter.h"
11 #include "gtest/gtest.h"
12 #include
13 #include
14
15 using namespace llvm;
16 using namespace llvm::MachO;
17
18 struct ExportedSymbol {
19 SymbolKind Kind;
20 std::string Name;
21 bool WeakDefined;
22 bool ThreadLocalValue;
23 };
24 using ExportedSymbolSeq = std::vector;
25
26 inline bool operator<(const ExportedSymbol &lhs, const ExportedSymbol &rhs) {
27 return std::tie(lhs.Kind, lhs.Name) < std::tie(rhs.Kind, rhs.Name);
28 }
29
30 inline bool operator==(const ExportedSymbol &lhs, const ExportedSymbol &rhs) {
31 return std::tie(lhs.Kind, lhs.Name, lhs.WeakDefined, lhs.ThreadLocalValue) ==
32 std::tie(rhs.Kind, rhs.Name, rhs.WeakDefined, rhs.ThreadLocalValue);
33 }
34
35 static ExportedSymbol TBDv1Symbols[] = {
36 {SymbolKind::GlobalSymbol, "$ld$hide$os9.0$_sym1", false, false},
37 {SymbolKind::GlobalSymbol, "_sym1", false, false},
38 {SymbolKind::GlobalSymbol, "_sym2", false, false},
39 {SymbolKind::GlobalSymbol, "_sym3", false, false},
40 {SymbolKind::GlobalSymbol, "_sym4", false, false},
41 {SymbolKind::GlobalSymbol, "_sym5", false, false},
42 {SymbolKind::GlobalSymbol, "_tlv1", false, true},
43 {SymbolKind::GlobalSymbol, "_tlv2", false, true},
44 {SymbolKind::GlobalSymbol, "_tlv3", false, true},
45 {SymbolKind::GlobalSymbol, "_weak1", true, false},
46 {SymbolKind::GlobalSymbol, "_weak2", true, false},
47 {SymbolKind::GlobalSymbol, "_weak3", true, false},
48 {SymbolKind::ObjectiveCClass, "class1", false, false},
49 {SymbolKind::ObjectiveCClass, "class2", false, false},
50 {SymbolKind::ObjectiveCClass, "class3", false, false},
51 {SymbolKind::ObjectiveCInstanceVariable, "class1._ivar1", false, false},
52 {SymbolKind::ObjectiveCInstanceVariable, "class1._ivar2", false, false},
53 {SymbolKind::ObjectiveCInstanceVariable, "class1._ivar3", false, false},
54 };
55
56 namespace TBDv1 {
57
58 TEST(TBDv1, ReadFile) {
59 static const char tbd_v1_file1[] =
60 "---\n"
61 "archs: [ armv7, armv7s, armv7k, arm64 ]\n"
62 "platform: ios\n"
63 "install-name: Test.dylib\n"
64 "current-version: 2.3.4\n"
65 "compatibility-version: 1.0\n"
66 "swift-version: 1.1\n"
67 "exports:\n"
68 " - archs: [ armv7, armv7s, armv7k, arm64 ]\n"
69 " allowed-clients: [ clientA ]\n"
70 " re-exports: [ /usr/lib/libfoo.dylib ]\n"
71 " symbols: [ _sym1, _sym2, _sym3, _sym4, $ld$hide$os9.0$_sym1 ]\n"
72 " objc-classes: [ _class1, _class2 ]\n"
73 " objc-ivars: [ _class1._ivar1, _class1._ivar2 ]\n"
74 " weak-def-symbols: [ _weak1, _weak2 ]\n"
75 " thread-local-symbols: [ _tlv1, _tlv2 ]\n"
76 " - archs: [ armv7, armv7s, armv7k ]\n"
77 " symbols: [ _sym5 ]\n"
78 " objc-classes: [ _class3 ]\n"
79 " objc-ivars: [ _class1._ivar3 ]\n"
80 " weak-def-symbols: [ _weak3 ]\n"
81 " thread-local-symbols: [ _tlv3 ]\n"
82 "...\n";
83
84 auto Buffer = MemoryBuffer::getMemBuffer(tbd_v1_file1, "Test.tbd");
85 auto Result = TextAPIReader::get(std::move(Buffer));
86 EXPECT_TRUE(!!Result);
87 auto File = std::move(Result.get());
88 EXPECT_EQ(FileType::TBD_V1, File->getFileType());
89 auto Archs = Architecture::armv7 | Architecture::armv7s |
90 Architecture::armv7k | Architecture::arm64;
91 EXPECT_EQ(Archs, File->getArchitectures());
92 EXPECT_EQ(PlatformKind::iOS, File->getPlatform());
93 EXPECT_EQ(std::string("Test.dylib"), File->getInstallName());
94 EXPECT_EQ(PackedVersion(2, 3, 4), File->getCurrentVersion());
95 EXPECT_EQ(PackedVersion(1, 0, 0), File->getCompatibilityVersion());
96 EXPECT_EQ(2U, File->getSwiftABIVersion());
97 EXPECT_EQ(ObjCConstraintType::None, File->getObjCConstraint());
98 EXPECT_TRUE(File->isTwoLevelNamespace());
99 EXPECT_TRUE(File->isApplicationExtensionSafe());
100 EXPECT_FALSE(File->isInstallAPI());
101 InterfaceFileRef client("clientA", Archs);
102 InterfaceFileRef reexport("/usr/lib/libfoo.dylib", Archs);
103 EXPECT_EQ(1U, File->allowableClients().size());
104 EXPECT_EQ(client, File->allowableClients().front());
105 EXPECT_EQ(1U, File->reexportedLibraries().size());
106 EXPECT_EQ(reexport, File->reexportedLibraries().front());
107
108 ExportedSymbolSeq Exports;
109 for (const auto *Sym : File->symbols()) {
110 EXPECT_FALSE(Sym->isWeakReferenced());
111 EXPECT_FALSE(Sym->isUndefined());
112 Exports.emplace_back(ExportedSymbol{Sym->getKind(), Sym->getName(),
113 Sym->isWeakDefined(),
114 Sym->isThreadLocalValue()});
115 }
116 llvm::sort(Exports.begin(), Exports.end());
117
118 EXPECT_EQ(sizeof(TBDv1Symbols) / sizeof(ExportedSymbol), Exports.size());
119 EXPECT_TRUE(
120 std::equal(Exports.begin(), Exports.end(), std::begin(TBDv1Symbols)));
121 }
122
123 TEST(TBDv1, ReadFile2) {
124 static const char tbd_v1_file2[] = "--- !tapi-tbd-v1\n"
125 "archs: [ armv7, armv7s, armv7k, arm64 ]\n"
126 "platform: ios\n"
127 "install-name: Test.dylib\n"
128 "...\n";
129
130 auto Buffer = MemoryBuffer::getMemBuffer(tbd_v1_file2, "Test.tbd");
131 auto Result = TextAPIReader::get(std::move(Buffer));
132 EXPECT_TRUE(!!Result);
133 auto File = std::move(Result.get());
134 EXPECT_EQ(FileType::TBD_V1, File->getFileType());
135 auto Archs = Architecture::armv7 | Architecture::armv7s |
136 Architecture::armv7k | Architecture::arm64;
137 EXPECT_EQ(Archs, File->getArchitectures());
138 EXPECT_EQ(PlatformKind::iOS, File->getPlatform());
139 EXPECT_EQ(std::string("Test.dylib"), File->getInstallName());
140 EXPECT_EQ(PackedVersion(1, 0, 0), File->getCurrentVersion());
141 EXPECT_EQ(PackedVersion(1, 0, 0), File->getCompatibilityVersion());
142 EXPECT_EQ(0U, File->getSwiftABIVersion());
143 EXPECT_EQ(ObjCConstraintType::None, File->getObjCConstraint());
144 EXPECT_TRUE(File->isTwoLevelNamespace());
145 EXPECT_TRUE(File->isApplicationExtensionSafe());
146 EXPECT_FALSE(File->isInstallAPI());
147 EXPECT_EQ(0U, File->allowableClients().size());
148 EXPECT_EQ(0U, File->reexportedLibraries().size());
149 }
150
151 TEST(TBDv1, WriteFile) {
152 static const char tbd_v1_file3[] =
153 "---\n"
154 "archs: [ i386, x86_64 ]\n"
155 "platform: macosx\n"
156 "install-name: '/usr/lib/libfoo.dylib'\n"
157 "current-version: 1.2.3\n"
158 "compatibility-version: 0\n"
159 "swift-version: 5\n"
160 "objc-constraint: retain_release\n"
161 "exports: \n"
162 " - archs: [ i386 ]\n"
163 " symbols: [ _sym1 ]\n"
164 " weak-def-symbols: [ _sym2 ]\n"
165 " thread-local-symbols: [ _sym3 ]\n"
166 " - archs: [ x86_64 ]\n"
167 " allowed-clients: [ clientA ]\n"
168 " re-exports: [ '/usr/lib/libfoo.dylib' ]\n"
169 " symbols: [ '_OBJC_EHTYPE_$_Class1' ]\n"
170 " objc-classes: [ _Class1 ]\n"
171 " objc-ivars: [ _Class1._ivar1 ]\n"
172 "...\n";
173
174 InterfaceFile File;
175 File.setPath("libfoo.dylib");
176 File.setInstallName("/usr/lib/libfoo.dylib");
177 File.setFileType(FileType::TBD_V1);
178 File.setArchitectures(Architecture::i386 | Architecture::x86_64);
179 File.setPlatform(PlatformKind::macOS);
180 File.setCurrentVersion(PackedVersion(1, 2, 3));
181 File.setSwiftABIVersion(5);
182 File.setObjCConstraint(ObjCConstraintType::Retain_Release);
183 File.addAllowableClient("clientA", Architecture::x86_64);
184 File.addReexportedLibrary("/usr/lib/libfoo.dylib", Architecture::x86_64);
185 File.addSymbol(SymbolKind::GlobalSymbol, "_sym1", Architecture::i386);
186 File.addSymbol(SymbolKind::GlobalSymbol, "_sym2", Architecture::i386,
187 SymbolFlags::WeakDefined);
188 File.addSymbol(SymbolKind::GlobalSymbol, "_sym3", Architecture::i386,
189 SymbolFlags::ThreadLocalValue);
190 File.addSymbol(SymbolKind::ObjectiveCClass, "Class1", Architecture::x86_64);
191 File.addSymbol(SymbolKind::ObjectiveCClassEHType, "Class1",
192 Architecture::x86_64);
193 File.addSymbol(SymbolKind::ObjectiveCInstanceVariable, "Class1._ivar1",
194 Architecture::x86_64);
195
196 SmallString<4096> Buffer;
197 raw_svector_ostream OS(Buffer);
198 auto Result = TextAPIWriter::writeToStream(OS, File);
199 EXPECT_FALSE(Result);
200 EXPECT_STREQ(tbd_v1_file3, Buffer.c_str());
201 }
202
203 TEST(TBDv1, Platform_macOS) {
204 static const char tbd_v1_platform_macos[] = "---\n"
205 "archs: [ x86_64 ]\n"
206 "platform: macosx\n"
207 "install-name: Test.dylib\n"
208 "...\n";
209
210 auto Buffer = MemoryBuffer::getMemBuffer(tbd_v1_platform_macos, "Test.tbd");
211 auto Result = TextAPIReader::get(std::move(Buffer));
212 EXPECT_TRUE(!!Result);
213 auto File = std::move(Result.get());
214 EXPECT_EQ(FileType::TBD_V1, File->getFileType());
215 EXPECT_EQ(PlatformKind::macOS, File->getPlatform());
216 }
217
218 TEST(TBDv1, Platform_iOS) {
219 static const char tbd_v1_platform_ios[] = "---\n"
220 "archs: [ arm64 ]\n"
221 "platform: ios\n"
222 "install-name: Test.dylib\n"
223 "...\n";
224
225 auto Buffer = MemoryBuffer::getMemBuffer(tbd_v1_platform_ios, "Test.tbd");
226 auto Result = TextAPIReader::get(std::move(Buffer));
227 EXPECT_TRUE(!!Result);
228 auto File = std::move(Result.get());
229 EXPECT_EQ(FileType::TBD_V1, File->getFileType());
230 EXPECT_EQ(PlatformKind::iOS, File->getPlatform());
231 }
232
233 TEST(TBDv1, Platform_watchOS) {
234 static const char tbd_v1_platform_watchos[] = "---\n"
235 "archs: [ armv7k ]\n"
236 "platform: watchos\n"
237 "install-name: Test.dylib\n"
238 "...\n";
239
240 auto Buffer = MemoryBuffer::getMemBuffer(tbd_v1_platform_watchos, "Test.tbd");
241 auto Result = TextAPIReader::get(std::move(Buffer));
242 EXPECT_TRUE(!!Result);
243 auto File = std::move(Result.get());
244 EXPECT_EQ(FileType::TBD_V1, File->getFileType());
245 EXPECT_EQ(PlatformKind::watchOS, File->getPlatform());
246 }
247
248 TEST(TBDv1, Platform_tvOS) {
249 static const char tbd_v1_platform_tvos[] = "---\n"
250 "archs: [ arm64 ]\n"
251 "platform: tvos\n"
252 "install-name: Test.dylib\n"
253 "...\n";
254
255 auto Buffer = MemoryBuffer::getMemBuffer(tbd_v1_platform_tvos, "Test.tbd");
256 auto Result = TextAPIReader::get(std::move(Buffer));
257 EXPECT_TRUE(!!Result);
258 auto File = std::move(Result.get());
259 EXPECT_EQ(FileType::TBD_V1, File->getFileType());
260 EXPECT_EQ(PlatformKind::tvOS, File->getPlatform());
261 }
262
263 TEST(TBDv1, Platform_bridgeOS) {
264 static const char tbd_v1_platform_bridgeos[] = "---\n"
265 "archs: [ armv7k ]\n"
266 "platform: bridgeos\n"
267 "install-name: Test.dylib\n"
268 "...\n";
269
270 auto Buffer =
271 MemoryBuffer::getMemBuffer(tbd_v1_platform_bridgeos, "Test.tbd");
272 auto Result = TextAPIReader::get(std::move(Buffer));
273 EXPECT_TRUE(!!Result);
274 auto File = std::move(Result.get());
275 EXPECT_EQ(FileType::TBD_V1, File->getFileType());
276 EXPECT_EQ(PlatformKind::bridgeOS, File->getPlatform());
277 }
278
279 TEST(TBDv1, Swift_1_0) {
280 static const char tbd_v1_swift_1_0[] = "---\n"
281 "archs: [ arm64 ]\n"
282 "platform: ios\n"
283 "install-name: Test.dylib\n"
284 "swift-version: 1.0\n"
285 "...\n";
286
287 auto Buffer = MemoryBuffer::getMemBuffer(tbd_v1_swift_1_0, "Test.tbd");
288 auto Result = TextAPIReader::get(std::move(Buffer));
289 EXPECT_TRUE(!!Result);
290 auto File = std::move(Result.get());
291 EXPECT_EQ(FileType::TBD_V1, File->getFileType());
292 EXPECT_EQ(1U, File->getSwiftABIVersion());
293 }
294
295 TEST(TBDv1, Swift_1_1) {
296 static const char tbd_v1_swift_1_1[] = "---\n"
297 "archs: [ arm64 ]\n"
298 "platform: ios\n"
299 "install-name: Test.dylib\n"
300 "swift-version: 1.1\n"
301 "...\n";
302
303 auto Buffer = MemoryBuffer::getMemBuffer(tbd_v1_swift_1_1, "Test.tbd");
304 auto Result = TextAPIReader::get(std::move(Buffer));
305 EXPECT_TRUE(!!Result);
306 auto File = std::move(Result.get());
307 EXPECT_EQ(FileType::TBD_V1, File->getFileType());
308 EXPECT_EQ(2U, File->getSwiftABIVersion());
309 }
310
311 TEST(TBDv1, Swift_2_0) {
312 static const char tbd_v1_swift_2_0[] = "---\n"
313 "archs: [ arm64 ]\n"
314 "platform: ios\n"
315 "install-name: Test.dylib\n"
316 "swift-version: 2.0\n"
317 "...\n";
318
319 auto Buffer = MemoryBuffer::getMemBuffer(tbd_v1_swift_2_0, "Test.tbd");
320 auto Result = TextAPIReader::get(std::move(Buffer));
321 EXPECT_TRUE(!!Result);
322 auto File = std::move(Result.get());
323 EXPECT_EQ(FileType::TBD_V1, File->getFileType());
324 EXPECT_EQ(3U, File->getSwiftABIVersion());
325 }
326
327 TEST(TBDv1, Swift_3_0) {
328 static const char tbd_v1_swift_3_0[] = "---\n"
329 "archs: [ arm64 ]\n"
330 "platform: ios\n"
331 "install-name: Test.dylib\n"
332 "swift-version: 3.0\n"
333 "...\n";
334
335 auto Buffer = MemoryBuffer::getMemBuffer(tbd_v1_swift_3_0, "Test.tbd");
336 auto Result = TextAPIReader::get(std::move(Buffer));
337 EXPECT_TRUE(!!Result);
338 auto File = std::move(Result.get());
339 EXPECT_EQ(FileType::TBD_V1, File->getFileType());
340 EXPECT_EQ(4U, File->getSwiftABIVersion());
341 }
342
343 TEST(TBDv1, Swift_4_0) {
344 static const char tbd_v1_swift_4_0[] = "---\n"
345 "archs: [ arm64 ]\n"
346 "platform: ios\n"
347 "install-name: Test.dylib\n"
348 "swift-version: 4.0\n"
349 "...\n";
350
351 auto Buffer = MemoryBuffer::getMemBuffer(tbd_v1_swift_4_0, "Test.tbd");
352 auto Result = TextAPIReader::get(std::move(Buffer));
353 EXPECT_FALSE(!!Result);
354 auto errorMessage = toString(Result.takeError());
355 EXPECT_EQ("malformed file\nTest.tbd:5:16: error: invalid Swift ABI "
356 "version.\nswift-version: 4.0\n ^~~\n",
357 errorMessage);
358 }
359
360 TEST(TBDv1, Swift_5) {
361 static const char tbd_v1_swift_5[] = "---\n"
362 "archs: [ arm64 ]\n"
363 "platform: ios\n"
364 "install-name: Test.dylib\n"
365 "swift-version: 5\n"
366 "...\n";
367
368 auto Buffer = MemoryBuffer::getMemBuffer(tbd_v1_swift_5, "Test.tbd");
369 auto Result = TextAPIReader::get(std::move(Buffer));
370 EXPECT_TRUE(!!Result);
371 auto File = std::move(Result.get());
372 EXPECT_EQ(FileType::TBD_V1, File->getFileType());
373 EXPECT_EQ(5U, File->getSwiftABIVersion());
374 }
375
376 TEST(TBDv1, Swift_99) {
377 static const char tbd_v1_swift_99[] = "---\n"
378 "archs: [ arm64 ]\n"
379 "platform: ios\n"
380 "install-name: Test.dylib\n"
381 "swift-version: 99\n"
382 "...\n";
383
384 auto Buffer = MemoryBuffer::getMemBuffer(tbd_v1_swift_99, "Test.tbd");
385 auto Result = TextAPIReader::get(std::move(Buffer));
386 EXPECT_TRUE(!!Result);
387 auto File = std::move(Result.get());
388 EXPECT_EQ(FileType::TBD_V1, File->getFileType());
389 EXPECT_EQ(99U, File->getSwiftABIVersion());
390 }
391
392 TEST(TBDv1, UnknownArchitecture) {
393 static const char tbd_v1_file_unknown_architecture[] =
394 "---\n"
395 "archs: [ foo ]\n"
396 "platform: macosx\n"
397 "install-name: Test.dylib\n"
398 "...\n";
399
400 auto Buffer =
401 MemoryBuffer::getMemBuffer(tbd_v1_file_unknown_architecture, "Test.tbd");
402 auto Result = TextAPIReader::get(std::move(Buffer));
403 EXPECT_TRUE(!!Result);
404 }
405
406 TEST(TBDv1, UnknownPlatform) {
407 static const char tbd_v1_file_unknown_platform[] = "---\n"
408 "archs: [ i386 ]\n"
409 "platform: newOS\n"
410 "...\n";
411
412 auto Buffer =
413 MemoryBuffer::getMemBuffer(tbd_v1_file_unknown_platform, "Test.tbd");
414 auto Result = TextAPIReader::get(std::move(Buffer));
415 EXPECT_FALSE(!!Result);
416 auto errorMessage = toString(Result.takeError());
417 EXPECT_EQ("malformed file\nTest.tbd:3:11: error: unknown platform\nplatform: "
418 "newOS\n ^~~~~\n",
419 errorMessage);
420 }
421
422 TEST(TBDv1, MalformedFile1) {
423 static const char malformed_file1[] = "---\n"
424 "archs: [ arm64 ]\n"
425 "foobar: \"Unsupported key\"\n"
426 "...\n";
427
428 auto Buffer = MemoryBuffer::getMemBuffer(malformed_file1, "Test.tbd");
429 auto Result = TextAPIReader::get(std::move(Buffer));
430 EXPECT_FALSE(!!Result);
431 auto errorMessage = toString(Result.takeError());
432 ASSERT_EQ("malformed file\nTest.tbd:2:1: error: missing required key "
433 "'platform'\narchs: [ arm64 ]\n^\n",
434 errorMessage);
435 }
436
437 TEST(TBDv1, MalformedFile2) {
438 static const char malformed_file2[] = "---\n"
439 "archs: [ arm64 ]\n"
440 "platform: ios\n"
441 "install-name: Test.dylib\n"
442 "foobar: \"Unsupported key\"\n"
443 "...\n";
444
445 auto Buffer = MemoryBuffer::getMemBuffer(malformed_file2, "Test.tbd");
446 auto Result = TextAPIReader::get(std::move(Buffer));
447 EXPECT_FALSE(!!Result);
448 auto errorMessage = toString(Result.takeError());
449 ASSERT_EQ(
450 "malformed file\nTest.tbd:5:9: error: unknown key 'foobar'\nfoobar: "
451 "\"Unsupported key\"\n ^~~~~~~~~~~~~~~~~\n",
452 errorMessage);
453 }
454
455 } // end namespace TBDv1.
0 //===-- TextStubV2Tests.cpp - TBD V2 File Test ----------------------------===//
1 //
2 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
3 // See https://llvm.org/LICENSE.txt for license information.
4 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
5 //
6 //===-----------------------------------------------------------------------===/
7
8 #include "llvm/TextAPI/MachO/InterfaceFile.h"
9 #include "llvm/TextAPI/MachO/TextAPIReader.h"
10 #include "llvm/TextAPI/MachO/TextAPIWriter.h"
11 #include "gtest/gtest.h"
12 #include
13 #include
14
15 using namespace llvm;
16 using namespace llvm::MachO;
17
18 struct ExportedSymbol {
19 SymbolKind Kind;
20 std::string Name;
21 bool WeakDefined;
22 bool ThreadLocalValue;
23 };
24 using ExportedSymbolSeq = std::vector;
25
26 inline bool operator<(const ExportedSymbol &lhs, const ExportedSymbol &rhs) {
27 return std::tie(lhs.Kind, lhs.Name) < std::tie(rhs.Kind, rhs.Name);
28 }
29
30 inline bool operator==(const ExportedSymbol &lhs, const ExportedSymbol &rhs) {
31 return std::tie(lhs.Kind, lhs.Name, lhs.WeakDefined, lhs.ThreadLocalValue) ==
32 std::tie(rhs.Kind, rhs.Name, rhs.WeakDefined, rhs.ThreadLocalValue);
33 }
34
35 static ExportedSymbol TBDv2Symbols[] = {
36 {SymbolKind::GlobalSymbol, "$ld$hide$os9.0$_sym1", false, false},
37 {SymbolKind::GlobalSymbol, "_sym1", false, false},
38 {SymbolKind::GlobalSymbol, "_sym2", false, false},
39 {SymbolKind::GlobalSymbol, "_sym3", false, false},
40 {SymbolKind::GlobalSymbol, "_sym4", false, false},
41 {SymbolKind::GlobalSymbol, "_sym5", false, false},
42 {SymbolKind::GlobalSymbol, "_tlv1", false, true},
43 {SymbolKind::GlobalSymbol, "_tlv2", false, true},
44 {SymbolKind::GlobalSymbol, "_tlv3", false, true},
45 {SymbolKind::GlobalSymbol, "_weak1", true, false},
46 {SymbolKind::GlobalSymbol, "_weak2", true, false},
47 {SymbolKind::GlobalSymbol, "_weak3", true, false},
48 {SymbolKind::ObjectiveCClass, "class1", false, false},
49 {SymbolKind::ObjectiveCClass, "class2", false, false},
50 {SymbolKind::ObjectiveCClass, "class3", false, false},
51 {SymbolKind::ObjectiveCInstanceVariable, "class1._ivar1", false, false},
52 {SymbolKind::ObjectiveCInstanceVariable, "class1._ivar2", false, false},
53 {SymbolKind::ObjectiveCInstanceVariable, "class1._ivar3", false, false},
54 };
55
56 namespace TBDv2 {
57
58 TEST(TBDv2, ReadFile) {
59 static const char tbd_v2_file1[] =
60 "--- !tapi-tbd-v2\n"
61 "archs: [ armv7, armv7s, armv7k, arm64 ]\n"
62 "platform: ios\n"
63 "flags: [ installapi ]\n"
64 "install-name: Test.dylib\n"
65 "current-version: 2.3.4\n"
66 "compatibility-version: 1.0\n"
67 "swift-version: 1.1\n"
68 "parent-umbrella: Umbrella.dylib\n"
69 "exports:\n"
70 " - archs: [ armv7, armv7s, armv7k, arm64 ]\n"
71 " allowable-clients: [ clientA ]\n"
72 " re-exports: [ /usr/lib/libfoo.dylib ]\n"
73 " symbols: [ _sym1, _sym2, _sym3, _sym4, $ld$hide$os9.0$_sym1 ]\n"
74 " objc-classes: [ _class1, _class2 ]\n"
75 " objc-ivars: [ _class1._ivar1, _class1._ivar2 ]\n"
76 " weak-def-symbols: [ _weak1, _weak2 ]\n"
77 " thread-local-symbols: [ _tlv1, _tlv2 ]\n"
78 " - archs: [ armv7, armv7s, armv7k ]\n"
79 " symbols: [ _sym5 ]\n"
80 " objc-classes: [ _class3 ]\n"
81 " objc-ivars: [ _class1._ivar3 ]\n"
82 " weak-def-symbols: [ _weak3 ]\n"
83 " thread-local-symbols: [ _tlv3 ]\n"
84 "...\n";
85
86 auto Buffer = MemoryBuffer::getMemBuffer(tbd_v2_file1, "Test.tbd");
87 auto Result = TextAPIReader::get(std::move(Buffer));
88 EXPECT_TRUE(!!Result);
89 auto File = std::move(Result.get());
90 EXPECT_EQ(FileType::TBD_V2, File->getFileType());
91 auto Archs = Architecture::armv7 | Architecture::armv7s |
92 Architecture::armv7k | Architecture::arm64;
93 EXPECT_EQ(Archs, File->getArchitectures());
94 EXPECT_EQ(PlatformKind::iOS, File->getPlatform());
95 EXPECT_EQ(std::string("Test.dylib"), File->getInstallName());
96 EXPECT_EQ(PackedVersion(2, 3, 4), File->getCurrentVersion());
97 EXPECT_EQ(PackedVersion(1, 0, 0), File->getCompatibilityVersion());
98 EXPECT_EQ(2U, File->getSwiftABIVersion());
99 EXPECT_EQ(ObjCConstraintType::Retain_Release, File->getObjCConstraint());
100 EXPECT_TRUE(File->isTwoLevelNamespace());
101 EXPECT_TRUE(File->isApplicationExtensionSafe());
102 EXPECT_TRUE(File->isInstallAPI());
103 InterfaceFileRef client("clientA", Archs);
104 InterfaceFileRef reexport("/usr/lib/libfoo.dylib", Archs);
105 EXPECT_EQ(1U, File->allowableClients().size());
106 EXPECT_EQ(client, File->allowableClients().front());
107 EXPECT_EQ(1U, File->reexportedLibraries().size());
108 EXPECT_EQ(reexport, File->reexportedLibraries().front());
109
110 ExportedSymbolSeq Exports;
111 for (const auto *Sym : File->symbols()) {
112 EXPECT_FALSE(Sym->isWeakReferenced());
113 EXPECT_FALSE(Sym->isUndefined());
114 Exports.emplace_back(ExportedSymbol{Sym->getKind(), Sym->getName(),
115 Sym->isWeakDefined(),
116 Sym->isThreadLocalValue()});
117 }
118 llvm::sort(Exports.begin(), Exports.end());
119
120 EXPECT_EQ(sizeof(TBDv2Symbols) / sizeof(ExportedSymbol), Exports.size());
121 EXPECT_TRUE(
122 std::equal(Exports.begin(), Exports.end(), std::begin(TBDv2Symbols)));
123 }
124
125 TEST(TBDv2, ReadFile2) {
126 static const char tbd_v2_file2[] =
127 "--- !tapi-tbd-v2\n"
128 "archs: [ armv7, armv7s, armv7k, arm64 ]\n"
129 "platform: ios\n"
130 "flags: [ flat_namespace, not_app_extension_safe ]\n"
131 "install-name: Test.dylib\n"
132 "swift-version: 1.1\n"
133 "exports:\n"
134 " - archs: [ armv7, armv7s, armv7k, arm64 ]\n"
135 " symbols: [ _sym1, _sym2, _sym3, _sym4, $ld$hide$os9.0$_sym1 ]\n"
136 " objc-classes: [ _class1, _class2 ]\n"
137 " objc-ivars: [ _class1._ivar1, _class1._ivar2 ]\n"
138 " weak-def-symbols: [ _weak1, _weak2 ]\n"
139 " thread-local-symbols: [ _tlv1, _tlv2 ]\n"
140 " - archs: [ armv7, armv7s, armv7k ]\n"
141 " symbols: [ _sym5 ]\n"
142 " objc-classes: [ _class3 ]\n"
143 " objc-ivars: [ _class1._ivar3 ]\n"
144 " weak-def-symbols: [ _weak3 ]\n"
145 " thread-local-symbols: [ _tlv3 ]\n"
146 "undefineds:\n"
147 " - archs: [ armv7, armv7s, armv7k, arm64 ]\n"
148 " symbols: [ _undefSym1, _undefSym2, _undefSym3 ]\n"
149 " objc-classes: [ _undefClass1, _undefClass2 ]\n"
150 " objc-ivars: [ _undefClass1._ivar1, _undefClass1._ivar2 ]\n"
151 " weak-ref-symbols: [ _undefWeak1, _undefWeak2 ]\n"
152 "...\n";
153
154 auto Buffer = MemoryBuffer::getMemBuffer(tbd_v2_file2, "Test.tbd");
155 auto Result = TextAPIReader::get(std::move(Buffer));
156 EXPECT_TRUE(!!Result);
157 auto File = std::move(Result.get());
158 EXPECT_EQ(FileType::TBD_V2, File->getFileType());
159 auto Archs = Architecture::armv7 | Architecture::armv7s |
160 Architecture::armv7k | Architecture::arm64;
161 EXPECT_EQ(Archs, File->getArchitectures());
162 EXPECT_EQ(PlatformKind::iOS, File->getPlatform());
163 EXPECT_EQ(std::string("Test.dylib"), File->getInstallName());
164 EXPECT_EQ(PackedVersion(1, 0, 0), File->getCurrentVersion());
165 EXPECT_EQ(PackedVersion(1, 0, 0), File->getCompatibilityVersion());
166 EXPECT_EQ(2U, File->getSwiftABIVersion());
167 EXPECT_EQ(ObjCConstraintType::Retain_Release, File->getObjCConstraint());
168 EXPECT_FALSE(File->isTwoLevelNamespace());
169 EXPECT_FALSE(File->isApplicationExtensionSafe());
170 EXPECT_FALSE(File->isInstallAPI());
171 EXPECT_EQ(0U, File->allowableClients().size());
172 EXPECT_EQ(0U, File->reexportedLibraries().size());
173 }
174
175 TEST(TBDv2, WriteFile) {
176 static const char tbd_v2_file3[] =
177 "--- !tapi-tbd-v2\n"
178 "archs: [ i386, x86_64 ]\n"
179 "platform: macosx\n"
180 "install-name: '/usr/lib/libfoo.dylib'\n"
181 "current-version: 1.2.3\n"
182 "compatibility-version: 0\n"
183 "swift-version: 5\n"
184 "exports: \n"
185 " - archs: [ i386 ]\n"
186 " symbols: [ _sym1 ]\n"
187 " weak-def-symbols: [ _sym2 ]\n"
188 " thread-local-symbols: [ _sym3 ]\n"
189 " - archs: [ x86_64 ]\n"
190 " allowable-clients: [ clientA ]\n"
191 " re-exports: [ '/usr/lib/libfoo.dylib' ]\n"
192 " symbols: [ '_OBJC_EHTYPE_$_Class1' ]\n"
193 " objc-classes: [ _Class1 ]\n"
194 " objc-ivars: [ _Class1._ivar1 ]\n"
195 "...\n";
196
197 InterfaceFile File;
198 File.setPath("libfoo.dylib");
199 File.setInstallName("/usr/lib/libfoo.dylib");
200 File.setFileType(FileType::TBD_V2);
201 File.setArchitectures(Architecture::i386 | Architecture::x86_64);
202 File.setPlatform(PlatformKind::macOS);
203 File.setCurrentVersion(PackedVersion(1, 2, 3));
204 File.setTwoLevelNamespace();
205 File.setApplicationExtensionSafe();
206 File.setSwiftABIVersion(5);
207 File.setObjCConstraint(ObjCConstraintType::Retain_Release);
208 File.addAllowableClient("clientA", Architecture::x86_64);
209 File.addReexportedLibrary("/usr/lib/libfoo.dylib", Architecture::x86_64);
210 File.addSymbol(SymbolKind::GlobalSymbol, "_sym1", Architecture::i386);
211 File.addSymbol(SymbolKind::GlobalSymbol, "_sym2", Architecture::i386,
212 SymbolFlags::WeakDefined);
213 File.addSymbol(SymbolKind::GlobalSymbol, "_sym3", Architecture::i386,
214 SymbolFlags::ThreadLocalValue);
215 File.addSymbol(SymbolKind::ObjectiveCClass, "Class1", Architecture::x86_64);
216 File.addSymbol(SymbolKind::ObjectiveCClassEHType, "Class1",
217 Architecture::x86_64);
218 File.addSymbol(SymbolKind::ObjectiveCInstanceVariable, "Class1._ivar1",
219 Architecture::x86_64);
220
221 SmallString<4096> Buffer;
222 raw_svector_ostream OS(Buffer);
223 auto Result = TextAPIWriter::writeToStream(OS, File);
224 EXPECT_FALSE(Result);
225 EXPECT_STREQ(tbd_v2_file3, Buffer.c_str());
226 }
227
228 TEST(TBDv2, Platform_macOS) {
229 static const char tbd_v1_platform_macos[] = "--- !tapi-tbd-v2\n"
230 "archs: [ x86_64 ]\n"
231 "platform: macosx\n"
232 "install-name: Test.dylib\n"
233 "...\n";
234
235 auto Buffer = MemoryBuffer::getMemBuffer(tbd_v1_platform_macos, "Test.tbd");
236 auto Result = TextAPIReader::get(std::move(Buffer));
237 EXPECT_TRUE(!!Result);
238 auto File = std::move(Result.get());
239 EXPECT_EQ(FileType::TBD_V2, File->getFileType());
240 EXPECT_EQ(PlatformKind::macOS, File->getPlatform());
241 }
242
243 TEST(TBDv2, Platform_iOS) {
244 static const char tbd_v1_platform_ios[] = "--- !tapi-tbd-v2\n"
245 "archs: [ arm64 ]\n"
246 "platform: ios\n"
247 "install-name: Test.dylib\n"
248 "...\n";
249
250 auto Buffer = MemoryBuffer::getMemBuffer(tbd_v1_platform_ios, "Test.tbd");
251 auto Result = TextAPIReader::get(std::move(Buffer));
252 EXPECT_TRUE(!!Result);
253 auto File = std::move(Result.get());
254 EXPECT_EQ(FileType::TBD_V2, File->getFileType());
255 EXPECT_EQ(PlatformKind::iOS, File->getPlatform());
256 }
257
258 TEST(TBDv2, Platform_watchOS) {
259 static const char tbd_v1_platform_watchos[] = "--- !tapi-tbd-v2\n"
260 "archs: [ armv7k ]\n"
261 "platform: watchos\n"
262 "install-name: Test.dylib\n"
263 "...\n";
264
265 auto Buffer = MemoryBuffer::getMemBuffer(tbd_v1_platform_watchos, "Test.tbd");
266 auto Result = TextAPIReader::get(std::move(Buffer));
267 EXPECT_TRUE(!!Result);
268 auto File = std::move(Result.get());
269 EXPECT_EQ(FileType::TBD_V2, File->getFileType());
270 EXPECT_EQ(PlatformKind::watchOS, File->getPlatform());
271 }
272
273 TEST(TBDv2, Platform_tvOS) {
274 static const char tbd_v1_platform_tvos[] = "--- !tapi-tbd-v2\n"
275 "archs: [ arm64 ]\n"
276 "platform: tvos\n"
277 "install-name: Test.dylib\n"
278 "...\n";
279
280 auto Buffer = MemoryBuffer::getMemBuffer(tbd_v1_platform_tvos, "Test.tbd");
281 auto Result = TextAPIReader::get(std::move(Buffer));
282 EXPECT_TRUE(!!Result);
283 auto File = std::move(Result.get());
284 EXPECT_EQ(FileType::TBD_V2, File->getFileType());
285 EXPECT_EQ(PlatformKind::tvOS, File->getPlatform());
286 }
287
288 TEST(TBDv2, Platform_bridgeOS) {
289 static const char tbd_v1_platform_bridgeos[] = "--- !tapi-tbd-v2\n"
290 "archs: [ armv7k ]\n"
291 "platform: bridgeos\n"
292 "install-name: Test.dylib\n"
293 "...\n";
294
295 auto Buffer =
296 MemoryBuffer::getMemBuffer(tbd_v1_platform_bridgeos, "Test.tbd");
297 auto Result = TextAPIReader::get(std::move(Buffer));
298 EXPECT_TRUE(!!Result);
299 auto File = std::move(Result.get());
300 EXPECT_EQ(FileType::TBD_V2, File->getFileType());
301 EXPECT_EQ(PlatformKind::bridgeOS, File->getPlatform());
302 }
303
304 TEST(TBDv2, Swift_1_0) {
305 static const char tbd_v1_swift_1_0[] = "--- !tapi-tbd-v2\n"
306 "archs: [ arm64 ]\n"
307 "platform: ios\n"
308 "install-name: Test.dylib\n"
309 "swift-version: 1.0\n"
310 "...\n";
311
312 auto Buffer = MemoryBuffer::getMemBuffer(tbd_v1_swift_1_0, "Test.tbd");
313 auto Result = TextAPIReader::get(std::move(Buffer));
314 EXPECT_TRUE(!!Result);
315 auto File = std::move(Result.get());
316 EXPECT_EQ(FileType::TBD_V2, File->getFileType());
317 EXPECT_EQ(1U, File->getSwiftABIVersion());
318 }
319
320 TEST(TBDv2, Swift_1_1) {
321 static const char tbd_v1_swift_1_1[] = "--- !tapi-tbd-v2\n"
322 "archs: [ arm64 ]\n"
323 "platform: ios\n"
324 "install-name: Test.dylib\n"
325 "swift-version: 1.1\n"
326 "...\n";
327
328 auto Buffer = MemoryBuffer::getMemBuffer(tbd_v1_swift_1_1, "Test.tbd");
329 auto Result = TextAPIReader::get(std::move(Buffer));
330 EXPECT_TRUE(!!Result);
331 auto File = std::move(Result.get());
332 EXPECT_EQ(FileType::TBD_V2, File->getFileType());
333 EXPECT_EQ(2U, File->getSwiftABIVersion());
334 }
335
336 TEST(TBDv2, Swift_2_0) {
337 static const char tbd_v1_swift_2_0[] = "--- !tapi-tbd-v2\n"
338 "archs: [ arm64 ]\n"
339 "platform: ios\n"
340 "install-name: Test.dylib\n"
341 "swift-version: 2.0\n"
342 "...\n";
343
344 auto Buffer = MemoryBuffer::getMemBuffer(tbd_v1_swift_2_0, "Test.tbd");
345 auto Result = TextAPIReader::get(std::move(Buffer));
346 EXPECT_TRUE(!!Result);
347 auto File = std::move(Result.get());
348 EXPECT_EQ(FileType::TBD_V2, File->getFileType());
349 EXPECT_EQ(3U, File->getSwiftABIVersion());
350 }
351
352 TEST(TBDv2, Swift_3_0) {
353 static const char tbd_v1_swift_3_0[] = "--- !tapi-tbd-v2\n"
354 "archs: [ arm64 ]\n"
355 "platform: ios\n"
356 "install-name: Test.dylib\n"
357 "swift-version: 3.0\n"
358 "...\n";
359
360 auto Buffer = MemoryBuffer::getMemBuffer(tbd_v1_swift_3_0, "Test.tbd");
361 auto Result = TextAPIReader::get(std::move(Buffer));
362 EXPECT_TRUE(!!Result);
363 auto File = std::move(Result.get());
364 EXPECT_EQ(FileType::TBD_V2, File->getFileType());
365 EXPECT_EQ(4U, File->getSwiftABIVersion());
366 }
367
368 TEST(TBDv2, Swift_4_0) {
369 static const char tbd_v1_swift_4_0[] = "--- !tapi-tbd-v2\n"
370 "archs: [ arm64 ]\n"
371 "platform: ios\n"
372 "install-name: Test.dylib\n"
373 "swift-version: 4.0\n"
374 "...\n";
375
376 auto Buffer = MemoryBuffer::getMemBuffer(tbd_v1_swift_4_0, "Test.tbd");
377 auto Result = TextAPIReader::get(std::move(Buffer));
378 EXPECT_FALSE(!!Result);
379 auto errorMessage = toString(Result.takeError());
380 EXPECT_EQ("malformed file\nTest.tbd:5:16: error: invalid Swift ABI "
381 "version.\nswift-version: 4.0\n ^~~\n",
382 errorMessage);
383 }
384
385 TEST(TBDv2, Swift_5) {
386 static const char tbd_v1_swift_5[] = "--- !tapi-tbd-v2\n"
387 "archs: [ arm64 ]\n"
388 "platform: ios\n"
389 "install-name: Test.dylib\n"
390 "swift-version: 5\n"
391 "...\n";
392
393 auto Buffer = MemoryBuffer::getMemBuffer(tbd_v1_swift_5, "Test.tbd");
394 auto Result = TextAPIReader::get(std::move(Buffer));
395 EXPECT_TRUE(!!Result);
396 auto File = std::move(Result.get());
397 EXPECT_EQ(FileType::TBD_V2, File->getFileType());
398 EXPECT_EQ(5U, File->getSwiftABIVersion());
399 }
400
401 TEST(TBDv2, Swift_99) {
402 static const char tbd_v1_swift_99[] = "--- !tapi-tbd-v2\n"
403 "archs: [ arm64 ]\n"
404 "platform: ios\n"
405 "install-name: Test.dylib\n"
406 "swift-version: 99\n"
407 "...\n";
408
409 auto Buffer = MemoryBuffer::getMemBuffer(tbd_v1_swift_99, "Test.tbd");
410 auto Result = TextAPIReader::get(std::move(Buffer));
411 EXPECT_TRUE(!!Result);
412 auto File = std::move(Result.get());
413 EXPECT_EQ(FileType::TBD_V2, File->getFileType());
414 EXPECT_EQ(99U, File->getSwiftABIVersion());
415 }
416
417 TEST(TBDv2, UnknownArchitecture) {
418 static const char tbd_v2_file_unknown_architecture[] =
419 "--- !tapi-tbd-v2\n"
420 "archs: [ foo ]\n"
421 "platform: macosx\n"
422 "install-name: Test.dylib\n"
423 "...\n";
424
425 auto Buffer =
426 MemoryBuffer::getMemBuffer(tbd_v2_file_unknown_architecture, "Test.tbd");
427 auto Result = TextAPIReader::get(std::move(Buffer));
428 EXPECT_TRUE(!!Result);
429 }
430
431 TEST(TBDv2, UnknownPlatform) {
432 static const char tbd_v2_file_unknown_platform[] = "--- !tapi-tbd-v2\n"
433 "archs: [ i386 ]\n"
434 "platform: newOS\n"
435 "...\n";
436
437 auto Buffer =
438 MemoryBuffer::getMemBuffer(tbd_v2_file_unknown_platform, "Test.tbd");
439 auto Result = TextAPIReader::get(std::move(Buffer));
440 EXPECT_FALSE(!!Result);
441 auto errorMessage = toString(Result.takeError());
442 EXPECT_EQ("malformed file\nTest.tbd:3:11: error: unknown platform\nplatform: "
443 "newOS\n ^~~~~\n",
444 errorMessage);
445 }
446
447 TEST(TBDv2, MalformedFile1) {
448 static const char malformed_file1[] = "--- !tapi-tbd-v2\n"
449 "archs: [ arm64 ]\n"
450 "foobar: \"Unsupported key\"\n"
451 "...\n";
452
453 auto Buffer = MemoryBuffer::getMemBuffer(malformed_file1, "Test.tbd");
454 auto Result = TextAPIReader::get(std::move(Buffer));
455 EXPECT_FALSE(!!Result);
456 auto errorMessage = toString(Result.takeError());
457 ASSERT_EQ("malformed file\nTest.tbd:2:1: error: missing required key "
458 "'platform'\narchs: [ arm64 ]\n^\n",
459 errorMessage);
460 }
461
462 TEST(TBDv2, MalformedFile2) {
463 static const char malformed_file2[] = "--- !tapi-tbd-v2\n"
464 "archs: [ arm64 ]\n"
465 "platform: ios\n"
466 "install-name: Test.dylib\n"
467 "foobar: \"Unsupported key\"\n"
468 "...\n";
469
470 auto Buffer = MemoryBuffer::getMemBuffer(malformed_file2, "Test.tbd");
471 auto Result = TextAPIReader::get(std::move(Buffer));
472 EXPECT_FALSE(!!Result);
473 auto errorMessage = toString(Result.takeError());
474 ASSERT_EQ(
475 "malformed file\nTest.tbd:5:9: error: unknown key 'foobar'\nfoobar: "
476 "\"Unsupported key\"\n ^~~~~~~~~~~~~~~~~\n",
477 errorMessage);
478 }
479
480 } // namespace TBDv2