1fe013be4SDimitry Andric //===- TextStubV5.cpp -----------------------------------------------------===//
2fe013be4SDimitry Andric //
3fe013be4SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4fe013be4SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5fe013be4SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6fe013be4SDimitry Andric //
7fe013be4SDimitry Andric //===----------------------------------------------------------------------===//
8fe013be4SDimitry Andric //
9fe013be4SDimitry Andric // Implements Text Stub JSON mappings.
10fe013be4SDimitry Andric //
11fe013be4SDimitry Andric //===----------------------------------------------------------------------===//
12fe013be4SDimitry Andric #include "TextStubCommon.h"
13fe013be4SDimitry Andric #include "llvm/ADT/StringSwitch.h"
14fe013be4SDimitry Andric #include "llvm/Support/JSON.h"
15fe013be4SDimitry Andric #include <utility>
16fe013be4SDimitry Andric
17fe013be4SDimitry Andric // clang-format off
18fe013be4SDimitry Andric /*
19fe013be4SDimitry Andric
20fe013be4SDimitry Andric JSON Format specification.
21fe013be4SDimitry Andric
22fe013be4SDimitry Andric All library level keys, accept target values and are defaulted if not specified.
23fe013be4SDimitry Andric
24fe013be4SDimitry Andric {
25fe013be4SDimitry Andric "tapi_tbd_version": 5, # Required: TBD version for all documents in file
26fe013be4SDimitry Andric "main_library": { # Required: top level library
27fe013be4SDimitry Andric "target_info": [ # Required: target information
28fe013be4SDimitry Andric {
29fe013be4SDimitry Andric "target": "x86_64-macos",
30c9157d92SDimitry Andric "min_deployment": "10.14" # Optional: minOS defaults to 0
31fe013be4SDimitry Andric },
32fe013be4SDimitry Andric {
33fe013be4SDimitry Andric "target": "arm64-macos",
34fe013be4SDimitry Andric "min_deployment": "10.14"
35fe013be4SDimitry Andric },
36fe013be4SDimitry Andric {
37fe013be4SDimitry Andric "target": "arm64-maccatalyst",
38fe013be4SDimitry Andric "min_deployment": "12.1"
39fe013be4SDimitry Andric }],
40fe013be4SDimitry Andric "flags":[{"attributes": ["flat_namespace"]}], # Optional:
41fe013be4SDimitry Andric "install_names":[{"name":"/S/L/F/Foo.fwk/Foo"}], # Required: library install name
42fe013be4SDimitry Andric "current_versions":[{"version": "1.2"}], # Optional: defaults to 1
43fe013be4SDimitry Andric "compatibility_versions":[{ "version": "1.1"}], # Optional: defaults to 1
44fe013be4SDimitry Andric "rpaths": [ # Optional:
45fe013be4SDimitry Andric {
46fe013be4SDimitry Andric "targets": ["x86_64-macos"], # Optional: defaults to targets in `target-info`
47fe013be4SDimitry Andric "paths": ["@executable_path/.../Frameworks"]
48fe013be4SDimitry Andric }],
49fe013be4SDimitry Andric "parent_umbrellas": [{"umbrella": "System"}],
50fe013be4SDimitry Andric "allowable_clients": [{"clients": ["ClientA"]}],
51fe013be4SDimitry Andric "reexported_libraries": [{"names": ["/u/l/l/foo.dylib"]}],
52fe013be4SDimitry Andric "exported_symbols": [{ # List of export symbols section
53fe013be4SDimitry Andric "targets": ["x86_64-macos", "arm64-macos"], # Optional: defaults to targets in `target-info`
54fe013be4SDimitry Andric "text": { # List of Text segment symbols
55fe013be4SDimitry Andric "global": [ "_func" ],
56fe013be4SDimitry Andric "weak": [],
57fe013be4SDimitry Andric "thread_local": []
58fe013be4SDimitry Andric },
59fe013be4SDimitry Andric "data": { ... }, # List of Data segment symbols
60fe013be4SDimitry Andric }],
61fe013be4SDimitry Andric "reexported_symbols": [{ ... }], # List of reexported symbols section
62fe013be4SDimitry Andric "undefined_symbols": [{ ... }] # List of undefined symbols section
63fe013be4SDimitry Andric },
64fe013be4SDimitry Andric "libraries": [ # Optional: Array of inlined libraries
65fe013be4SDimitry Andric {...}, {...}, {...}
66fe013be4SDimitry Andric ]
67fe013be4SDimitry Andric }
68fe013be4SDimitry Andric */
69fe013be4SDimitry Andric // clang-format on
70fe013be4SDimitry Andric
71fe013be4SDimitry Andric using namespace llvm;
72fe013be4SDimitry Andric using namespace llvm::json;
73fe013be4SDimitry Andric using namespace llvm::MachO;
74fe013be4SDimitry Andric
75fe013be4SDimitry Andric namespace {
76fe013be4SDimitry Andric struct JSONSymbol {
77fe013be4SDimitry Andric SymbolKind Kind;
78fe013be4SDimitry Andric std::string Name;
79fe013be4SDimitry Andric SymbolFlags Flags;
80fe013be4SDimitry Andric };
81fe013be4SDimitry Andric
82fe013be4SDimitry Andric using AttrToTargets = std::map<std::string, TargetList>;
83fe013be4SDimitry Andric using TargetsToSymbols =
84fe013be4SDimitry Andric SmallVector<std::pair<TargetList, std::vector<JSONSymbol>>>;
85fe013be4SDimitry Andric
86fe013be4SDimitry Andric enum TBDKey : size_t {
87fe013be4SDimitry Andric TBDVersion = 0U,
88fe013be4SDimitry Andric MainLibrary,
89fe013be4SDimitry Andric Documents,
90fe013be4SDimitry Andric TargetInfo,
91fe013be4SDimitry Andric Targets,
92fe013be4SDimitry Andric Target,
93fe013be4SDimitry Andric Deployment,
94fe013be4SDimitry Andric Flags,
95fe013be4SDimitry Andric Attributes,
96fe013be4SDimitry Andric InstallName,
97fe013be4SDimitry Andric CurrentVersion,
98fe013be4SDimitry Andric CompatibilityVersion,
99fe013be4SDimitry Andric Version,
100fe013be4SDimitry Andric SwiftABI,
101fe013be4SDimitry Andric ABI,
102fe013be4SDimitry Andric ParentUmbrella,
103fe013be4SDimitry Andric Umbrella,
104fe013be4SDimitry Andric AllowableClients,
105fe013be4SDimitry Andric Clients,
106fe013be4SDimitry Andric ReexportLibs,
107fe013be4SDimitry Andric Names,
108fe013be4SDimitry Andric Name,
109fe013be4SDimitry Andric Exports,
110fe013be4SDimitry Andric Reexports,
111fe013be4SDimitry Andric Undefineds,
112fe013be4SDimitry Andric Data,
113fe013be4SDimitry Andric Text,
114fe013be4SDimitry Andric Weak,
115fe013be4SDimitry Andric ThreadLocal,
116fe013be4SDimitry Andric Globals,
117fe013be4SDimitry Andric ObjCClass,
118fe013be4SDimitry Andric ObjCEHType,
119fe013be4SDimitry Andric ObjCIvar,
120fe013be4SDimitry Andric RPath,
121fe013be4SDimitry Andric Paths,
122fe013be4SDimitry Andric };
123fe013be4SDimitry Andric
124fe013be4SDimitry Andric std::array<StringRef, 64> Keys = {
125fe013be4SDimitry Andric "tapi_tbd_version",
126fe013be4SDimitry Andric "main_library",
127fe013be4SDimitry Andric "libraries",
128fe013be4SDimitry Andric "target_info",
129fe013be4SDimitry Andric "targets",
130fe013be4SDimitry Andric "target",
131fe013be4SDimitry Andric "min_deployment",
132fe013be4SDimitry Andric "flags",
133fe013be4SDimitry Andric "attributes",
134fe013be4SDimitry Andric "install_names",
135fe013be4SDimitry Andric "current_versions",
136fe013be4SDimitry Andric "compatibility_versions",
137fe013be4SDimitry Andric "version",
138fe013be4SDimitry Andric "swift_abi",
139fe013be4SDimitry Andric "abi",
140fe013be4SDimitry Andric "parent_umbrellas",
141fe013be4SDimitry Andric "umbrella",
142fe013be4SDimitry Andric "allowable_clients",
143fe013be4SDimitry Andric "clients",
144fe013be4SDimitry Andric "reexported_libraries",
145fe013be4SDimitry Andric "names",
146fe013be4SDimitry Andric "name",
147fe013be4SDimitry Andric "exported_symbols",
148fe013be4SDimitry Andric "reexported_symbols",
149fe013be4SDimitry Andric "undefined_symbols",
150fe013be4SDimitry Andric "data",
151fe013be4SDimitry Andric "text",
152fe013be4SDimitry Andric "weak",
153fe013be4SDimitry Andric "thread_local",
154fe013be4SDimitry Andric "global",
155fe013be4SDimitry Andric "objc_class",
156fe013be4SDimitry Andric "objc_eh_type",
157fe013be4SDimitry Andric "objc_ivar",
158fe013be4SDimitry Andric "rpaths",
159fe013be4SDimitry Andric "paths",
160fe013be4SDimitry Andric };
161fe013be4SDimitry Andric
getParseErrorMsg(TBDKey Key)162fe013be4SDimitry Andric static llvm::SmallString<128> getParseErrorMsg(TBDKey Key) {
163fe013be4SDimitry Andric return {"invalid ", Keys[Key], " section"};
164fe013be4SDimitry Andric }
165fe013be4SDimitry Andric
getSerializeErrorMsg(TBDKey Key)166fe013be4SDimitry Andric static llvm::SmallString<128> getSerializeErrorMsg(TBDKey Key) {
167fe013be4SDimitry Andric return {"missing ", Keys[Key], " information"};
168fe013be4SDimitry Andric }
169fe013be4SDimitry Andric
170fe013be4SDimitry Andric class JSONStubError : public llvm::ErrorInfo<llvm::json::ParseError> {
171fe013be4SDimitry Andric public:
JSONStubError(Twine ErrMsg)172fe013be4SDimitry Andric JSONStubError(Twine ErrMsg) : Message(ErrMsg.str()) {}
173fe013be4SDimitry Andric
log(llvm::raw_ostream & OS) const174fe013be4SDimitry Andric void log(llvm::raw_ostream &OS) const override { OS << Message << "\n"; }
convertToErrorCode() const175fe013be4SDimitry Andric std::error_code convertToErrorCode() const override {
176fe013be4SDimitry Andric return llvm::inconvertibleErrorCode();
177fe013be4SDimitry Andric }
178fe013be4SDimitry Andric
179fe013be4SDimitry Andric private:
180fe013be4SDimitry Andric std::string Message;
181fe013be4SDimitry Andric };
182fe013be4SDimitry Andric
183fe013be4SDimitry Andric template <typename JsonT, typename StubT = JsonT>
getRequiredValue(TBDKey Key,const Object * Obj,std::function<std::optional<JsonT> (const Object *,StringRef)> GetValue,std::function<std::optional<StubT> (JsonT)> Validate=nullptr)184fe013be4SDimitry Andric Expected<StubT> getRequiredValue(
185fe013be4SDimitry Andric TBDKey Key, const Object *Obj,
186fe013be4SDimitry Andric std::function<std::optional<JsonT>(const Object *, StringRef)> GetValue,
187fe013be4SDimitry Andric std::function<std::optional<StubT>(JsonT)> Validate = nullptr) {
188fe013be4SDimitry Andric std::optional<JsonT> Val = GetValue(Obj, Keys[Key]);
189fe013be4SDimitry Andric if (!Val)
190fe013be4SDimitry Andric return make_error<JSONStubError>(getParseErrorMsg(Key));
191fe013be4SDimitry Andric
192fe013be4SDimitry Andric if (Validate == nullptr)
193fe013be4SDimitry Andric return static_cast<StubT>(*Val);
194fe013be4SDimitry Andric
195fe013be4SDimitry Andric std::optional<StubT> Result = Validate(*Val);
196fe013be4SDimitry Andric if (!Result.has_value())
197fe013be4SDimitry Andric return make_error<JSONStubError>(getParseErrorMsg(Key));
198fe013be4SDimitry Andric return Result.value();
199fe013be4SDimitry Andric }
200fe013be4SDimitry Andric
201fe013be4SDimitry Andric template <typename JsonT, typename StubT = JsonT>
getRequiredValue(TBDKey Key,const Object * Obj,std::function<std::optional<JsonT> (const Object *,StringRef)> const GetValue,StubT DefaultValue,function_ref<std::optional<StubT> (JsonT)> Validate)202fe013be4SDimitry Andric Expected<StubT> getRequiredValue(
203fe013be4SDimitry Andric TBDKey Key, const Object *Obj,
204*de8261c4SDimitry Andric std::function<std::optional<JsonT>(const Object *, StringRef)> const
205*de8261c4SDimitry Andric GetValue,
206*de8261c4SDimitry Andric StubT DefaultValue, function_ref<std::optional<StubT>(JsonT)> Validate) {
207fe013be4SDimitry Andric std::optional<JsonT> Val = GetValue(Obj, Keys[Key]);
208fe013be4SDimitry Andric if (!Val)
209fe013be4SDimitry Andric return DefaultValue;
210fe013be4SDimitry Andric
211fe013be4SDimitry Andric std::optional<StubT> Result;
212fe013be4SDimitry Andric Result = Validate(*Val);
213fe013be4SDimitry Andric if (!Result.has_value())
214fe013be4SDimitry Andric return make_error<JSONStubError>(getParseErrorMsg(Key));
215fe013be4SDimitry Andric return Result.value();
216fe013be4SDimitry Andric }
217fe013be4SDimitry Andric
collectFromArray(TBDKey Key,const Object * Obj,function_ref<void (StringRef)> Append,bool IsRequired=false)218fe013be4SDimitry Andric Error collectFromArray(TBDKey Key, const Object *Obj,
219*de8261c4SDimitry Andric function_ref<void(StringRef)> Append,
220fe013be4SDimitry Andric bool IsRequired = false) {
221fe013be4SDimitry Andric const auto *Values = Obj->getArray(Keys[Key]);
222fe013be4SDimitry Andric if (!Values) {
223fe013be4SDimitry Andric if (IsRequired)
224fe013be4SDimitry Andric return make_error<JSONStubError>(getParseErrorMsg(Key));
225fe013be4SDimitry Andric return Error::success();
226fe013be4SDimitry Andric }
227fe013be4SDimitry Andric
228fe013be4SDimitry Andric for (const Value &Val : *Values) {
229fe013be4SDimitry Andric auto ValStr = Val.getAsString();
230fe013be4SDimitry Andric if (!ValStr.has_value())
231fe013be4SDimitry Andric return make_error<JSONStubError>(getParseErrorMsg(Key));
232fe013be4SDimitry Andric Append(ValStr.value());
233fe013be4SDimitry Andric }
234fe013be4SDimitry Andric
235fe013be4SDimitry Andric return Error::success();
236fe013be4SDimitry Andric }
237fe013be4SDimitry Andric
238fe013be4SDimitry Andric namespace StubParser {
239fe013be4SDimitry Andric
getVersion(const Object * File)240fe013be4SDimitry Andric Expected<FileType> getVersion(const Object *File) {
241fe013be4SDimitry Andric auto VersionOrErr = getRequiredValue<int64_t, FileType>(
242fe013be4SDimitry Andric TBDKey::TBDVersion, File, &Object::getInteger,
243fe013be4SDimitry Andric [](int64_t Val) -> std::optional<FileType> {
244fe013be4SDimitry Andric unsigned Result = Val;
245fe013be4SDimitry Andric if (Result != 5)
246fe013be4SDimitry Andric return std::nullopt;
247fe013be4SDimitry Andric return FileType::TBD_V5;
248fe013be4SDimitry Andric });
249fe013be4SDimitry Andric
250fe013be4SDimitry Andric if (!VersionOrErr)
251fe013be4SDimitry Andric return VersionOrErr.takeError();
252fe013be4SDimitry Andric return *VersionOrErr;
253fe013be4SDimitry Andric }
254fe013be4SDimitry Andric
getTargets(const Object * Section)255fe013be4SDimitry Andric Expected<TargetList> getTargets(const Object *Section) {
256fe013be4SDimitry Andric const auto *Targets = Section->getArray(Keys[TBDKey::Targets]);
257fe013be4SDimitry Andric if (!Targets)
258fe013be4SDimitry Andric return make_error<JSONStubError>(getParseErrorMsg(TBDKey::Targets));
259fe013be4SDimitry Andric
260fe013be4SDimitry Andric TargetList IFTargets;
261fe013be4SDimitry Andric for (const Value &JSONTarget : *Targets) {
262fe013be4SDimitry Andric auto TargetStr = JSONTarget.getAsString();
263fe013be4SDimitry Andric if (!TargetStr.has_value())
264fe013be4SDimitry Andric return make_error<JSONStubError>(getParseErrorMsg(TBDKey::Target));
265fe013be4SDimitry Andric auto TargetOrErr = Target::create(TargetStr.value());
266fe013be4SDimitry Andric if (!TargetOrErr)
267fe013be4SDimitry Andric return make_error<JSONStubError>(getParseErrorMsg(TBDKey::Target));
268fe013be4SDimitry Andric IFTargets.push_back(*TargetOrErr);
269fe013be4SDimitry Andric }
270fe013be4SDimitry Andric return std::move(IFTargets);
271fe013be4SDimitry Andric }
272fe013be4SDimitry Andric
getTargetsSection(const Object * Section)273fe013be4SDimitry Andric Expected<TargetList> getTargetsSection(const Object *Section) {
274fe013be4SDimitry Andric const Array *Targets = Section->getArray(Keys[TBDKey::TargetInfo]);
275fe013be4SDimitry Andric if (!Targets)
276fe013be4SDimitry Andric return make_error<JSONStubError>(getParseErrorMsg(TBDKey::Targets));
277fe013be4SDimitry Andric
278fe013be4SDimitry Andric TargetList IFTargets;
279fe013be4SDimitry Andric for (const Value &JSONTarget : *Targets) {
280fe013be4SDimitry Andric const auto *Obj = JSONTarget.getAsObject();
281fe013be4SDimitry Andric if (!Obj)
282fe013be4SDimitry Andric return make_error<JSONStubError>(getParseErrorMsg(TBDKey::Target));
283fe013be4SDimitry Andric auto TargetStr =
284fe013be4SDimitry Andric getRequiredValue<StringRef>(TBDKey::Target, Obj, &Object::getString);
285fe013be4SDimitry Andric if (!TargetStr)
286fe013be4SDimitry Andric return make_error<JSONStubError>(getParseErrorMsg(TBDKey::Target));
287fe013be4SDimitry Andric auto TargetOrErr = Target::create(*TargetStr);
288fe013be4SDimitry Andric if (!TargetOrErr)
289fe013be4SDimitry Andric return make_error<JSONStubError>(getParseErrorMsg(TBDKey::Target));
290c9157d92SDimitry Andric
291c9157d92SDimitry Andric auto VersionStr = Obj->getString(Keys[TBDKey::Deployment]);
292c9157d92SDimitry Andric VersionTuple Version;
293c9157d92SDimitry Andric if (VersionStr && Version.tryParse(*VersionStr))
294c9157d92SDimitry Andric return make_error<JSONStubError>(getParseErrorMsg(TBDKey::Deployment));
295fe013be4SDimitry Andric TargetOrErr->MinDeployment = Version;
296c9157d92SDimitry Andric
297fe013be4SDimitry Andric // Convert to LLVM::Triple to accurately compute minOS + platform + arch
298fe013be4SDimitry Andric // pairing.
299fe013be4SDimitry Andric IFTargets.push_back(
300fe013be4SDimitry Andric MachO::Target(Triple(getTargetTripleName(*TargetOrErr))));
301fe013be4SDimitry Andric }
302fe013be4SDimitry Andric return std::move(IFTargets);
303fe013be4SDimitry Andric }
304fe013be4SDimitry Andric
collectSymbolsFromSegment(const Object * Segment,TargetsToSymbols & Result,SymbolFlags SectionFlag)305fe013be4SDimitry Andric Error collectSymbolsFromSegment(const Object *Segment, TargetsToSymbols &Result,
306fe013be4SDimitry Andric SymbolFlags SectionFlag) {
307fe013be4SDimitry Andric auto Err = collectFromArray(
308fe013be4SDimitry Andric TBDKey::Globals, Segment, [&Result, &SectionFlag](StringRef Name) {
309fe013be4SDimitry Andric JSONSymbol Sym = {SymbolKind::GlobalSymbol, Name.str(), SectionFlag};
310fe013be4SDimitry Andric Result.back().second.emplace_back(Sym);
311fe013be4SDimitry Andric });
312fe013be4SDimitry Andric if (Err)
313fe013be4SDimitry Andric return Err;
314fe013be4SDimitry Andric
315fe013be4SDimitry Andric Err = collectFromArray(
316fe013be4SDimitry Andric TBDKey::ObjCClass, Segment, [&Result, &SectionFlag](StringRef Name) {
317fe013be4SDimitry Andric JSONSymbol Sym = {SymbolKind::ObjectiveCClass, Name.str(), SectionFlag};
318fe013be4SDimitry Andric Result.back().second.emplace_back(Sym);
319fe013be4SDimitry Andric });
320fe013be4SDimitry Andric if (Err)
321fe013be4SDimitry Andric return Err;
322fe013be4SDimitry Andric
323fe013be4SDimitry Andric Err = collectFromArray(TBDKey::ObjCEHType, Segment,
324fe013be4SDimitry Andric [&Result, &SectionFlag](StringRef Name) {
325fe013be4SDimitry Andric JSONSymbol Sym = {SymbolKind::ObjectiveCClassEHType,
326fe013be4SDimitry Andric Name.str(), SectionFlag};
327fe013be4SDimitry Andric Result.back().second.emplace_back(Sym);
328fe013be4SDimitry Andric });
329fe013be4SDimitry Andric if (Err)
330fe013be4SDimitry Andric return Err;
331fe013be4SDimitry Andric
332fe013be4SDimitry Andric Err = collectFromArray(
333fe013be4SDimitry Andric TBDKey::ObjCIvar, Segment, [&Result, &SectionFlag](StringRef Name) {
334fe013be4SDimitry Andric JSONSymbol Sym = {SymbolKind::ObjectiveCInstanceVariable, Name.str(),
335fe013be4SDimitry Andric SectionFlag};
336fe013be4SDimitry Andric Result.back().second.emplace_back(Sym);
337fe013be4SDimitry Andric });
338fe013be4SDimitry Andric if (Err)
339fe013be4SDimitry Andric return Err;
340fe013be4SDimitry Andric
341fe013be4SDimitry Andric SymbolFlags WeakFlag =
342fe013be4SDimitry Andric SectionFlag |
343fe013be4SDimitry Andric (((SectionFlag & SymbolFlags::Undefined) == SymbolFlags::Undefined)
344fe013be4SDimitry Andric ? SymbolFlags::WeakReferenced
345fe013be4SDimitry Andric : SymbolFlags::WeakDefined);
346fe013be4SDimitry Andric Err = collectFromArray(
347fe013be4SDimitry Andric TBDKey::Weak, Segment, [&Result, WeakFlag](StringRef Name) {
348fe013be4SDimitry Andric JSONSymbol Sym = {SymbolKind::GlobalSymbol, Name.str(), WeakFlag};
349fe013be4SDimitry Andric Result.back().second.emplace_back(Sym);
350fe013be4SDimitry Andric });
351fe013be4SDimitry Andric if (Err)
352fe013be4SDimitry Andric return Err;
353fe013be4SDimitry Andric
354fe013be4SDimitry Andric Err = collectFromArray(
355fe013be4SDimitry Andric TBDKey::ThreadLocal, Segment, [&Result, SectionFlag](StringRef Name) {
356fe013be4SDimitry Andric JSONSymbol Sym = {SymbolKind::GlobalSymbol, Name.str(),
357fe013be4SDimitry Andric SymbolFlags::ThreadLocalValue | SectionFlag};
358fe013be4SDimitry Andric Result.back().second.emplace_back(Sym);
359fe013be4SDimitry Andric });
360fe013be4SDimitry Andric if (Err)
361fe013be4SDimitry Andric return Err;
362fe013be4SDimitry Andric
363fe013be4SDimitry Andric return Error::success();
364fe013be4SDimitry Andric }
365fe013be4SDimitry Andric
getNameSection(const Object * File)366fe013be4SDimitry Andric Expected<StringRef> getNameSection(const Object *File) {
367fe013be4SDimitry Andric const Array *Section = File->getArray(Keys[TBDKey::InstallName]);
368fe013be4SDimitry Andric if (!Section)
369fe013be4SDimitry Andric return make_error<JSONStubError>(getParseErrorMsg(TBDKey::InstallName));
370fe013be4SDimitry Andric
371fe013be4SDimitry Andric assert(!Section->empty() && "unexpected missing install name");
372fe013be4SDimitry Andric // TODO: Just take first for now.
373fe013be4SDimitry Andric const auto *Obj = Section->front().getAsObject();
374fe013be4SDimitry Andric if (!Obj)
375fe013be4SDimitry Andric return make_error<JSONStubError>(getParseErrorMsg(TBDKey::InstallName));
376fe013be4SDimitry Andric
377fe013be4SDimitry Andric return getRequiredValue<StringRef>(TBDKey::Name, Obj, &Object::getString);
378fe013be4SDimitry Andric }
379fe013be4SDimitry Andric
getSymbolSection(const Object * File,TBDKey Key,TargetList & Targets)380fe013be4SDimitry Andric Expected<TargetsToSymbols> getSymbolSection(const Object *File, TBDKey Key,
381fe013be4SDimitry Andric TargetList &Targets) {
382fe013be4SDimitry Andric
383fe013be4SDimitry Andric const Array *Section = File->getArray(Keys[Key]);
384fe013be4SDimitry Andric if (!Section)
385fe013be4SDimitry Andric return TargetsToSymbols();
386fe013be4SDimitry Andric
387fe013be4SDimitry Andric SymbolFlags SectionFlag;
388fe013be4SDimitry Andric switch (Key) {
389fe013be4SDimitry Andric case TBDKey::Reexports:
390fe013be4SDimitry Andric SectionFlag = SymbolFlags::Rexported;
391fe013be4SDimitry Andric break;
392fe013be4SDimitry Andric case TBDKey::Undefineds:
393fe013be4SDimitry Andric SectionFlag = SymbolFlags::Undefined;
394fe013be4SDimitry Andric break;
395fe013be4SDimitry Andric default:
396fe013be4SDimitry Andric SectionFlag = SymbolFlags::None;
397fe013be4SDimitry Andric break;
398fe013be4SDimitry Andric };
399fe013be4SDimitry Andric
400fe013be4SDimitry Andric TargetsToSymbols Result;
401fe013be4SDimitry Andric TargetList MappedTargets;
402fe013be4SDimitry Andric for (auto Val : *Section) {
403fe013be4SDimitry Andric auto *Obj = Val.getAsObject();
404fe013be4SDimitry Andric if (!Obj)
405fe013be4SDimitry Andric continue;
406fe013be4SDimitry Andric
407fe013be4SDimitry Andric auto TargetsOrErr = getTargets(Obj);
408fe013be4SDimitry Andric if (!TargetsOrErr) {
409fe013be4SDimitry Andric MappedTargets = Targets;
410fe013be4SDimitry Andric consumeError(TargetsOrErr.takeError());
411fe013be4SDimitry Andric } else {
412fe013be4SDimitry Andric MappedTargets = *TargetsOrErr;
413fe013be4SDimitry Andric }
414fe013be4SDimitry Andric Result.emplace_back(
415fe013be4SDimitry Andric std::make_pair(std::move(MappedTargets), std::vector<JSONSymbol>()));
416fe013be4SDimitry Andric
417fe013be4SDimitry Andric auto *DataSection = Obj->getObject(Keys[TBDKey::Data]);
418fe013be4SDimitry Andric auto *TextSection = Obj->getObject(Keys[TBDKey::Text]);
419fe013be4SDimitry Andric // There should be at least one valid section.
420fe013be4SDimitry Andric if (!DataSection && !TextSection)
421fe013be4SDimitry Andric return make_error<JSONStubError>(getParseErrorMsg(Key));
422fe013be4SDimitry Andric
423fe013be4SDimitry Andric if (DataSection) {
424fe013be4SDimitry Andric auto Err = collectSymbolsFromSegment(DataSection, Result,
425fe013be4SDimitry Andric SectionFlag | SymbolFlags::Data);
426fe013be4SDimitry Andric if (Err)
427fe013be4SDimitry Andric return std::move(Err);
428fe013be4SDimitry Andric }
429fe013be4SDimitry Andric if (TextSection) {
430fe013be4SDimitry Andric auto Err = collectSymbolsFromSegment(TextSection, Result,
431fe013be4SDimitry Andric SectionFlag | SymbolFlags::Text);
432fe013be4SDimitry Andric if (Err)
433fe013be4SDimitry Andric return std::move(Err);
434fe013be4SDimitry Andric }
435fe013be4SDimitry Andric }
436fe013be4SDimitry Andric
437fe013be4SDimitry Andric return std::move(Result);
438fe013be4SDimitry Andric }
439fe013be4SDimitry Andric
getLibSection(const Object * File,TBDKey Key,TBDKey SubKey,const TargetList & Targets)440fe013be4SDimitry Andric Expected<AttrToTargets> getLibSection(const Object *File, TBDKey Key,
441fe013be4SDimitry Andric TBDKey SubKey,
442fe013be4SDimitry Andric const TargetList &Targets) {
443fe013be4SDimitry Andric auto *Section = File->getArray(Keys[Key]);
444fe013be4SDimitry Andric if (!Section)
445fe013be4SDimitry Andric return AttrToTargets();
446fe013be4SDimitry Andric
447fe013be4SDimitry Andric AttrToTargets Result;
448fe013be4SDimitry Andric TargetList MappedTargets;
449fe013be4SDimitry Andric for (auto Val : *Section) {
450fe013be4SDimitry Andric auto *Obj = Val.getAsObject();
451fe013be4SDimitry Andric if (!Obj)
452fe013be4SDimitry Andric continue;
453fe013be4SDimitry Andric
454fe013be4SDimitry Andric auto TargetsOrErr = getTargets(Obj);
455fe013be4SDimitry Andric if (!TargetsOrErr) {
456fe013be4SDimitry Andric MappedTargets = Targets;
457fe013be4SDimitry Andric consumeError(TargetsOrErr.takeError());
458fe013be4SDimitry Andric } else {
459fe013be4SDimitry Andric MappedTargets = *TargetsOrErr;
460fe013be4SDimitry Andric }
461fe013be4SDimitry Andric auto Err =
462fe013be4SDimitry Andric collectFromArray(SubKey, Obj, [&Result, &MappedTargets](StringRef Key) {
463fe013be4SDimitry Andric Result[Key.str()] = MappedTargets;
464fe013be4SDimitry Andric });
465fe013be4SDimitry Andric if (Err)
466fe013be4SDimitry Andric return std::move(Err);
467fe013be4SDimitry Andric }
468fe013be4SDimitry Andric
469fe013be4SDimitry Andric return std::move(Result);
470fe013be4SDimitry Andric }
471fe013be4SDimitry Andric
getUmbrellaSection(const Object * File,const TargetList & Targets)472fe013be4SDimitry Andric Expected<AttrToTargets> getUmbrellaSection(const Object *File,
473fe013be4SDimitry Andric const TargetList &Targets) {
474fe013be4SDimitry Andric const auto *Umbrella = File->getArray(Keys[TBDKey::ParentUmbrella]);
475fe013be4SDimitry Andric if (!Umbrella)
476fe013be4SDimitry Andric return AttrToTargets();
477fe013be4SDimitry Andric
478fe013be4SDimitry Andric AttrToTargets Result;
479fe013be4SDimitry Andric TargetList MappedTargets;
480fe013be4SDimitry Andric for (auto Val : *Umbrella) {
481fe013be4SDimitry Andric auto *Obj = Val.getAsObject();
482fe013be4SDimitry Andric if (!Obj)
483fe013be4SDimitry Andric return make_error<JSONStubError>(
484fe013be4SDimitry Andric getParseErrorMsg(TBDKey::ParentUmbrella));
485fe013be4SDimitry Andric
486fe013be4SDimitry Andric // Get Targets section.
487fe013be4SDimitry Andric auto TargetsOrErr = getTargets(Obj);
488fe013be4SDimitry Andric if (!TargetsOrErr) {
489fe013be4SDimitry Andric MappedTargets = Targets;
490fe013be4SDimitry Andric consumeError(TargetsOrErr.takeError());
491fe013be4SDimitry Andric } else {
492fe013be4SDimitry Andric MappedTargets = *TargetsOrErr;
493fe013be4SDimitry Andric }
494fe013be4SDimitry Andric
495fe013be4SDimitry Andric auto UmbrellaOrErr =
496fe013be4SDimitry Andric getRequiredValue<StringRef>(TBDKey::Umbrella, Obj, &Object::getString);
497fe013be4SDimitry Andric if (!UmbrellaOrErr)
498fe013be4SDimitry Andric return UmbrellaOrErr.takeError();
499fe013be4SDimitry Andric Result[UmbrellaOrErr->str()] = Targets;
500fe013be4SDimitry Andric }
501fe013be4SDimitry Andric return std::move(Result);
502fe013be4SDimitry Andric }
503fe013be4SDimitry Andric
getSwiftVersion(const Object * File)504fe013be4SDimitry Andric Expected<uint8_t> getSwiftVersion(const Object *File) {
505fe013be4SDimitry Andric const Array *Versions = File->getArray(Keys[TBDKey::SwiftABI]);
506fe013be4SDimitry Andric if (!Versions)
507fe013be4SDimitry Andric return 0;
508fe013be4SDimitry Andric
509fe013be4SDimitry Andric for (const auto &Val : *Versions) {
510fe013be4SDimitry Andric const auto *Obj = Val.getAsObject();
511fe013be4SDimitry Andric if (!Obj)
512fe013be4SDimitry Andric return make_error<JSONStubError>(getParseErrorMsg(TBDKey::SwiftABI));
513fe013be4SDimitry Andric
514fe013be4SDimitry Andric // TODO: Take first for now.
515fe013be4SDimitry Andric return getRequiredValue<int64_t, uint8_t>(TBDKey::ABI, Obj,
516fe013be4SDimitry Andric &Object::getInteger);
517fe013be4SDimitry Andric }
518fe013be4SDimitry Andric
519fe013be4SDimitry Andric return 0;
520fe013be4SDimitry Andric }
521fe013be4SDimitry Andric
getPackedVersion(const Object * File,TBDKey Key)522fe013be4SDimitry Andric Expected<PackedVersion> getPackedVersion(const Object *File, TBDKey Key) {
523fe013be4SDimitry Andric const Array *Versions = File->getArray(Keys[Key]);
524fe013be4SDimitry Andric if (!Versions)
525fe013be4SDimitry Andric return PackedVersion(1, 0, 0);
526fe013be4SDimitry Andric
527fe013be4SDimitry Andric for (const auto &Val : *Versions) {
528fe013be4SDimitry Andric const auto *Obj = Val.getAsObject();
529fe013be4SDimitry Andric if (!Obj)
530fe013be4SDimitry Andric return make_error<JSONStubError>(getParseErrorMsg(Key));
531fe013be4SDimitry Andric
532fe013be4SDimitry Andric auto ValidatePV = [](StringRef Version) -> std::optional<PackedVersion> {
533fe013be4SDimitry Andric PackedVersion PV;
534fe013be4SDimitry Andric auto [success, truncated] = PV.parse64(Version);
535fe013be4SDimitry Andric if (!success || truncated)
536fe013be4SDimitry Andric return std::nullopt;
537fe013be4SDimitry Andric return PV;
538fe013be4SDimitry Andric };
539fe013be4SDimitry Andric // TODO: Take first for now.
540fe013be4SDimitry Andric return getRequiredValue<StringRef, PackedVersion>(
541fe013be4SDimitry Andric TBDKey::Version, Obj, &Object::getString, PackedVersion(1, 0, 0),
542fe013be4SDimitry Andric ValidatePV);
543fe013be4SDimitry Andric }
544fe013be4SDimitry Andric
545fe013be4SDimitry Andric return PackedVersion(1, 0, 0);
546fe013be4SDimitry Andric }
547fe013be4SDimitry Andric
getFlags(const Object * File)548fe013be4SDimitry Andric Expected<TBDFlags> getFlags(const Object *File) {
549fe013be4SDimitry Andric TBDFlags Flags = TBDFlags::None;
550fe013be4SDimitry Andric const Array *Section = File->getArray(Keys[TBDKey::Flags]);
551c9157d92SDimitry Andric if (!Section || Section->empty())
552fe013be4SDimitry Andric return Flags;
553fe013be4SDimitry Andric
554fe013be4SDimitry Andric for (auto &Val : *Section) {
555c9157d92SDimitry Andric // FIXME: Flags currently apply to all target triples.
556fe013be4SDimitry Andric const auto *Obj = Val.getAsObject();
557fe013be4SDimitry Andric if (!Obj)
558fe013be4SDimitry Andric return make_error<JSONStubError>(getParseErrorMsg(TBDKey::Flags));
559fe013be4SDimitry Andric
560fe013be4SDimitry Andric auto FlagsOrErr =
561fe013be4SDimitry Andric collectFromArray(TBDKey::Attributes, Obj, [&Flags](StringRef Flag) {
562fe013be4SDimitry Andric TBDFlags TBDFlag =
563fe013be4SDimitry Andric StringSwitch<TBDFlags>(Flag)
564fe013be4SDimitry Andric .Case("flat_namespace", TBDFlags::FlatNamespace)
565fe013be4SDimitry Andric .Case("not_app_extension_safe",
566fe013be4SDimitry Andric TBDFlags::NotApplicationExtensionSafe)
567c9157d92SDimitry Andric .Case("sim_support", TBDFlags::SimulatorSupport)
568c9157d92SDimitry Andric .Case("not_for_dyld_shared_cache",
569c9157d92SDimitry Andric TBDFlags::OSLibNotForSharedCache)
570fe013be4SDimitry Andric .Default(TBDFlags::None);
571fe013be4SDimitry Andric Flags |= TBDFlag;
572fe013be4SDimitry Andric });
573fe013be4SDimitry Andric
574fe013be4SDimitry Andric if (FlagsOrErr)
575fe013be4SDimitry Andric return std::move(FlagsOrErr);
576fe013be4SDimitry Andric
577fe013be4SDimitry Andric return Flags;
578fe013be4SDimitry Andric }
579fe013be4SDimitry Andric
580fe013be4SDimitry Andric return Flags;
581fe013be4SDimitry Andric }
582fe013be4SDimitry Andric
583fe013be4SDimitry Andric using IFPtr = std::unique_ptr<InterfaceFile>;
parseToInterfaceFile(const Object * File)584fe013be4SDimitry Andric Expected<IFPtr> parseToInterfaceFile(const Object *File) {
585fe013be4SDimitry Andric auto TargetsOrErr = getTargetsSection(File);
586fe013be4SDimitry Andric if (!TargetsOrErr)
587fe013be4SDimitry Andric return TargetsOrErr.takeError();
588fe013be4SDimitry Andric TargetList Targets = *TargetsOrErr;
589fe013be4SDimitry Andric
590fe013be4SDimitry Andric auto NameOrErr = getNameSection(File);
591fe013be4SDimitry Andric if (!NameOrErr)
592fe013be4SDimitry Andric return NameOrErr.takeError();
593fe013be4SDimitry Andric StringRef Name = *NameOrErr;
594fe013be4SDimitry Andric
595fe013be4SDimitry Andric auto CurrVersionOrErr = getPackedVersion(File, TBDKey::CurrentVersion);
596fe013be4SDimitry Andric if (!CurrVersionOrErr)
597fe013be4SDimitry Andric return CurrVersionOrErr.takeError();
598fe013be4SDimitry Andric PackedVersion CurrVersion = *CurrVersionOrErr;
599fe013be4SDimitry Andric
600fe013be4SDimitry Andric auto CompVersionOrErr = getPackedVersion(File, TBDKey::CompatibilityVersion);
601fe013be4SDimitry Andric if (!CompVersionOrErr)
602fe013be4SDimitry Andric return CompVersionOrErr.takeError();
603fe013be4SDimitry Andric PackedVersion CompVersion = *CompVersionOrErr;
604fe013be4SDimitry Andric
605fe013be4SDimitry Andric auto SwiftABIOrErr = getSwiftVersion(File);
606fe013be4SDimitry Andric if (!SwiftABIOrErr)
607fe013be4SDimitry Andric return SwiftABIOrErr.takeError();
608fe013be4SDimitry Andric uint8_t SwiftABI = *SwiftABIOrErr;
609fe013be4SDimitry Andric
610fe013be4SDimitry Andric auto FlagsOrErr = getFlags(File);
611fe013be4SDimitry Andric if (!FlagsOrErr)
612fe013be4SDimitry Andric return FlagsOrErr.takeError();
613fe013be4SDimitry Andric TBDFlags Flags = *FlagsOrErr;
614fe013be4SDimitry Andric
615fe013be4SDimitry Andric auto UmbrellasOrErr = getUmbrellaSection(File, Targets);
616fe013be4SDimitry Andric if (!UmbrellasOrErr)
617fe013be4SDimitry Andric return UmbrellasOrErr.takeError();
618fe013be4SDimitry Andric AttrToTargets Umbrellas = *UmbrellasOrErr;
619fe013be4SDimitry Andric
620fe013be4SDimitry Andric auto ClientsOrErr =
621fe013be4SDimitry Andric getLibSection(File, TBDKey::AllowableClients, TBDKey::Clients, Targets);
622fe013be4SDimitry Andric if (!ClientsOrErr)
623fe013be4SDimitry Andric return ClientsOrErr.takeError();
624fe013be4SDimitry Andric AttrToTargets Clients = *ClientsOrErr;
625fe013be4SDimitry Andric
626fe013be4SDimitry Andric auto RLOrErr =
627fe013be4SDimitry Andric getLibSection(File, TBDKey::ReexportLibs, TBDKey::Names, Targets);
628fe013be4SDimitry Andric if (!RLOrErr)
629fe013be4SDimitry Andric return RLOrErr.takeError();
630fe013be4SDimitry Andric AttrToTargets ReexportLibs = std::move(*RLOrErr);
631fe013be4SDimitry Andric
632fe013be4SDimitry Andric auto RPathsOrErr = getLibSection(File, TBDKey::RPath, TBDKey::Paths, Targets);
633fe013be4SDimitry Andric if (!RPathsOrErr)
634fe013be4SDimitry Andric return RPathsOrErr.takeError();
635fe013be4SDimitry Andric AttrToTargets RPaths = std::move(*RPathsOrErr);
636fe013be4SDimitry Andric
637fe013be4SDimitry Andric auto ExportsOrErr = getSymbolSection(File, TBDKey::Exports, Targets);
638fe013be4SDimitry Andric if (!ExportsOrErr)
639fe013be4SDimitry Andric return ExportsOrErr.takeError();
640fe013be4SDimitry Andric TargetsToSymbols Exports = std::move(*ExportsOrErr);
641fe013be4SDimitry Andric
642fe013be4SDimitry Andric auto ReexportsOrErr = getSymbolSection(File, TBDKey::Reexports, Targets);
643fe013be4SDimitry Andric if (!ReexportsOrErr)
644fe013be4SDimitry Andric return ReexportsOrErr.takeError();
645fe013be4SDimitry Andric TargetsToSymbols Reexports = std::move(*ReexportsOrErr);
646fe013be4SDimitry Andric
647fe013be4SDimitry Andric auto UndefinedsOrErr = getSymbolSection(File, TBDKey::Undefineds, Targets);
648fe013be4SDimitry Andric if (!UndefinedsOrErr)
649fe013be4SDimitry Andric return UndefinedsOrErr.takeError();
650fe013be4SDimitry Andric TargetsToSymbols Undefineds = std::move(*UndefinedsOrErr);
651fe013be4SDimitry Andric
652fe013be4SDimitry Andric IFPtr F(new InterfaceFile);
653fe013be4SDimitry Andric F->setInstallName(Name);
654fe013be4SDimitry Andric F->setCurrentVersion(CurrVersion);
655fe013be4SDimitry Andric F->setCompatibilityVersion(CompVersion);
656fe013be4SDimitry Andric F->setSwiftABIVersion(SwiftABI);
657fe013be4SDimitry Andric F->setTwoLevelNamespace(!(Flags & TBDFlags::FlatNamespace));
658fe013be4SDimitry Andric F->setApplicationExtensionSafe(
659fe013be4SDimitry Andric !(Flags & TBDFlags::NotApplicationExtensionSafe));
660c9157d92SDimitry Andric F->setSimulatorSupport((Flags & TBDFlags::SimulatorSupport));
661c9157d92SDimitry Andric F->setOSLibNotForSharedCache((Flags & TBDFlags::OSLibNotForSharedCache));
662fe013be4SDimitry Andric for (auto &T : Targets)
663fe013be4SDimitry Andric F->addTarget(T);
664fe013be4SDimitry Andric for (auto &[Lib, Targets] : Clients)
665fe013be4SDimitry Andric for (auto Target : Targets)
666fe013be4SDimitry Andric F->addAllowableClient(Lib, Target);
667fe013be4SDimitry Andric for (auto &[Lib, Targets] : ReexportLibs)
668fe013be4SDimitry Andric for (auto Target : Targets)
669fe013be4SDimitry Andric F->addReexportedLibrary(Lib, Target);
670fe013be4SDimitry Andric for (auto &[Lib, Targets] : Umbrellas)
671fe013be4SDimitry Andric for (auto Target : Targets)
672fe013be4SDimitry Andric F->addParentUmbrella(Target, Lib);
673fe013be4SDimitry Andric for (auto &[Path, Targets] : RPaths)
674fe013be4SDimitry Andric for (auto Target : Targets)
675fe013be4SDimitry Andric F->addRPath(Target, Path);
676fe013be4SDimitry Andric for (auto &[Targets, Symbols] : Exports)
677fe013be4SDimitry Andric for (auto &Sym : Symbols)
678fe013be4SDimitry Andric F->addSymbol(Sym.Kind, Sym.Name, Targets, Sym.Flags);
679fe013be4SDimitry Andric for (auto &[Targets, Symbols] : Reexports)
680fe013be4SDimitry Andric for (auto &Sym : Symbols)
681fe013be4SDimitry Andric F->addSymbol(Sym.Kind, Sym.Name, Targets, Sym.Flags);
682fe013be4SDimitry Andric for (auto &[Targets, Symbols] : Undefineds)
683fe013be4SDimitry Andric for (auto &Sym : Symbols)
684fe013be4SDimitry Andric F->addSymbol(Sym.Kind, Sym.Name, Targets, Sym.Flags);
685fe013be4SDimitry Andric
686fe013be4SDimitry Andric return std::move(F);
687fe013be4SDimitry Andric }
688fe013be4SDimitry Andric
getInlinedLibs(const Object * File)689fe013be4SDimitry Andric Expected<std::vector<IFPtr>> getInlinedLibs(const Object *File) {
690fe013be4SDimitry Andric std::vector<IFPtr> IFs;
691fe013be4SDimitry Andric const Array *Files = File->getArray(Keys[TBDKey::Documents]);
692fe013be4SDimitry Andric if (!Files)
693fe013be4SDimitry Andric return std::move(IFs);
694fe013be4SDimitry Andric
695fe013be4SDimitry Andric for (auto Lib : *Files) {
696fe013be4SDimitry Andric auto IFOrErr = parseToInterfaceFile(Lib.getAsObject());
697fe013be4SDimitry Andric if (!IFOrErr)
698fe013be4SDimitry Andric return IFOrErr.takeError();
699fe013be4SDimitry Andric auto IF = std::move(*IFOrErr);
700fe013be4SDimitry Andric IFs.emplace_back(std::move(IF));
701fe013be4SDimitry Andric }
702fe013be4SDimitry Andric return std::move(IFs);
703fe013be4SDimitry Andric }
704fe013be4SDimitry Andric
705fe013be4SDimitry Andric } // namespace StubParser
706fe013be4SDimitry Andric } // namespace
707fe013be4SDimitry Andric
708fe013be4SDimitry Andric Expected<std::unique_ptr<InterfaceFile>>
getInterfaceFileFromJSON(StringRef JSON)709fe013be4SDimitry Andric MachO::getInterfaceFileFromJSON(StringRef JSON) {
710fe013be4SDimitry Andric auto ValOrErr = parse(JSON);
711fe013be4SDimitry Andric if (!ValOrErr)
712fe013be4SDimitry Andric return ValOrErr.takeError();
713fe013be4SDimitry Andric
714fe013be4SDimitry Andric auto *Root = ValOrErr->getAsObject();
715fe013be4SDimitry Andric auto VersionOrErr = StubParser::getVersion(Root);
716fe013be4SDimitry Andric if (!VersionOrErr)
717fe013be4SDimitry Andric return VersionOrErr.takeError();
718fe013be4SDimitry Andric FileType Version = *VersionOrErr;
719fe013be4SDimitry Andric
720fe013be4SDimitry Andric Object *MainLib = Root->getObject(Keys[TBDKey::MainLibrary]);
721fe013be4SDimitry Andric auto IFOrErr = StubParser::parseToInterfaceFile(MainLib);
722fe013be4SDimitry Andric if (!IFOrErr)
723fe013be4SDimitry Andric return IFOrErr.takeError();
724fe013be4SDimitry Andric (*IFOrErr)->setFileType(Version);
725fe013be4SDimitry Andric std::unique_ptr<InterfaceFile> IF(std::move(*IFOrErr));
726fe013be4SDimitry Andric
727fe013be4SDimitry Andric auto IFsOrErr = StubParser::getInlinedLibs(Root);
728fe013be4SDimitry Andric if (!IFsOrErr)
729fe013be4SDimitry Andric return IFsOrErr.takeError();
730fe013be4SDimitry Andric for (auto &File : *IFsOrErr) {
731fe013be4SDimitry Andric File->setFileType(Version);
732fe013be4SDimitry Andric IF->addDocument(std::shared_ptr<InterfaceFile>(std::move(File)));
733fe013be4SDimitry Andric }
734fe013be4SDimitry Andric return std::move(IF);
735fe013be4SDimitry Andric }
736fe013be4SDimitry Andric
737fe013be4SDimitry Andric namespace {
738fe013be4SDimitry Andric
739fe013be4SDimitry Andric template <typename ContainerT = Array>
insertNonEmptyValues(Object & Obj,TBDKey Key,ContainerT && Contents)740fe013be4SDimitry Andric bool insertNonEmptyValues(Object &Obj, TBDKey Key, ContainerT &&Contents) {
741fe013be4SDimitry Andric if (Contents.empty())
742fe013be4SDimitry Andric return false;
743fe013be4SDimitry Andric Obj[Keys[Key]] = std::move(Contents);
744fe013be4SDimitry Andric return true;
745fe013be4SDimitry Andric }
746fe013be4SDimitry Andric
getFormattedStr(const MachO::Target & Targ)747fe013be4SDimitry Andric std::string getFormattedStr(const MachO::Target &Targ) {
748fe013be4SDimitry Andric std::string PlatformStr = Targ.Platform == PLATFORM_MACCATALYST
749fe013be4SDimitry Andric ? "maccatalyst"
750fe013be4SDimitry Andric : getOSAndEnvironmentName(Targ.Platform);
751fe013be4SDimitry Andric return (getArchitectureName(Targ.Arch) + "-" + PlatformStr).str();
752fe013be4SDimitry Andric }
753fe013be4SDimitry Andric
754fe013be4SDimitry Andric template <typename AggregateT>
serializeTargets(const AggregateT Targets,const TargetList & ActiveTargets)755fe013be4SDimitry Andric std::vector<std::string> serializeTargets(const AggregateT Targets,
756fe013be4SDimitry Andric const TargetList &ActiveTargets) {
757fe013be4SDimitry Andric std::vector<std::string> TargetsStr;
758fe013be4SDimitry Andric if (Targets.size() == ActiveTargets.size())
759fe013be4SDimitry Andric return TargetsStr;
760fe013be4SDimitry Andric
761c9157d92SDimitry Andric for (const MachO::Target &Target : Targets)
762fe013be4SDimitry Andric TargetsStr.emplace_back(getFormattedStr(Target));
763c9157d92SDimitry Andric
764fe013be4SDimitry Andric return TargetsStr;
765fe013be4SDimitry Andric }
766fe013be4SDimitry Andric
serializeTargetInfo(const TargetList & ActiveTargets)767fe013be4SDimitry Andric Array serializeTargetInfo(const TargetList &ActiveTargets) {
768fe013be4SDimitry Andric Array Targets;
769fe013be4SDimitry Andric for (const auto Targ : ActiveTargets) {
770fe013be4SDimitry Andric Object TargetInfo;
771c9157d92SDimitry Andric if (!Targ.MinDeployment.empty())
772fe013be4SDimitry Andric TargetInfo[Keys[TBDKey::Deployment]] = Targ.MinDeployment.getAsString();
773fe013be4SDimitry Andric TargetInfo[Keys[TBDKey::Target]] = getFormattedStr(Targ);
774fe013be4SDimitry Andric Targets.emplace_back(std::move(TargetInfo));
775fe013be4SDimitry Andric }
776fe013be4SDimitry Andric return Targets;
777fe013be4SDimitry Andric }
778fe013be4SDimitry Andric
779fe013be4SDimitry Andric template <typename ValueT, typename EntryT = ValueT>
serializeScalar(TBDKey Key,ValueT Value,ValueT Default=ValueT ())780fe013be4SDimitry Andric Array serializeScalar(TBDKey Key, ValueT Value, ValueT Default = ValueT()) {
781fe013be4SDimitry Andric if (Value == Default)
782fe013be4SDimitry Andric return {};
783fe013be4SDimitry Andric Array Container;
784fe013be4SDimitry Andric Object ScalarObj({Object::KV({Keys[Key], EntryT(Value)})});
785fe013be4SDimitry Andric
786fe013be4SDimitry Andric Container.emplace_back(std::move(ScalarObj));
787fe013be4SDimitry Andric return Container;
788fe013be4SDimitry Andric }
789fe013be4SDimitry Andric
790fe013be4SDimitry Andric using TargetsToValuesMap =
791fe013be4SDimitry Andric std::map<std::vector<std::string>, std::vector<std::string>>;
792fe013be4SDimitry Andric
793fe013be4SDimitry Andric template <typename AggregateT = TargetsToValuesMap>
serializeAttrToTargets(AggregateT & Entries,TBDKey Key)794fe013be4SDimitry Andric Array serializeAttrToTargets(AggregateT &Entries, TBDKey Key) {
795fe013be4SDimitry Andric Array Container;
796fe013be4SDimitry Andric for (const auto &[Targets, Values] : Entries) {
797fe013be4SDimitry Andric Object Obj;
798fe013be4SDimitry Andric insertNonEmptyValues(Obj, TBDKey::Targets, std::move(Targets));
799fe013be4SDimitry Andric Obj[Keys[Key]] = Values;
800fe013be4SDimitry Andric Container.emplace_back(std::move(Obj));
801fe013be4SDimitry Andric }
802fe013be4SDimitry Andric return Container;
803fe013be4SDimitry Andric }
804fe013be4SDimitry Andric
805fe013be4SDimitry Andric template <typename ValueT = std::string,
806fe013be4SDimitry Andric typename AggregateT = std::vector<std::pair<MachO::Target, ValueT>>>
serializeField(TBDKey Key,const AggregateT & Values,const TargetList & ActiveTargets,bool IsArray=true)807fe013be4SDimitry Andric Array serializeField(TBDKey Key, const AggregateT &Values,
808fe013be4SDimitry Andric const TargetList &ActiveTargets, bool IsArray = true) {
809fe013be4SDimitry Andric std::map<ValueT, std::set<MachO::Target>> Entries;
810fe013be4SDimitry Andric for (const auto &[Target, Val] : Values)
811fe013be4SDimitry Andric Entries[Val].insert(Target);
812fe013be4SDimitry Andric
813fe013be4SDimitry Andric if (!IsArray) {
814fe013be4SDimitry Andric std::map<std::vector<std::string>, std::string> FinalEntries;
815fe013be4SDimitry Andric for (const auto &[Val, Targets] : Entries)
816fe013be4SDimitry Andric FinalEntries[serializeTargets(Targets, ActiveTargets)] = Val;
817fe013be4SDimitry Andric return serializeAttrToTargets(FinalEntries, Key);
818fe013be4SDimitry Andric }
819fe013be4SDimitry Andric
820fe013be4SDimitry Andric TargetsToValuesMap FinalEntries;
821fe013be4SDimitry Andric for (const auto &[Val, Targets] : Entries)
822fe013be4SDimitry Andric FinalEntries[serializeTargets(Targets, ActiveTargets)].emplace_back(Val);
823fe013be4SDimitry Andric return serializeAttrToTargets(FinalEntries, Key);
824fe013be4SDimitry Andric }
825fe013be4SDimitry Andric
serializeField(TBDKey Key,const std::vector<InterfaceFileRef> & Values,const TargetList & ActiveTargets)826fe013be4SDimitry Andric Array serializeField(TBDKey Key, const std::vector<InterfaceFileRef> &Values,
827fe013be4SDimitry Andric const TargetList &ActiveTargets) {
828fe013be4SDimitry Andric TargetsToValuesMap FinalEntries;
829fe013be4SDimitry Andric for (const auto &Ref : Values) {
830fe013be4SDimitry Andric TargetList Targets{Ref.targets().begin(), Ref.targets().end()};
831fe013be4SDimitry Andric FinalEntries[serializeTargets(Targets, ActiveTargets)].emplace_back(
832fe013be4SDimitry Andric Ref.getInstallName());
833fe013be4SDimitry Andric }
834fe013be4SDimitry Andric return serializeAttrToTargets(FinalEntries, Key);
835fe013be4SDimitry Andric }
836fe013be4SDimitry Andric
837fe013be4SDimitry Andric struct SymbolFields {
838fe013be4SDimitry Andric struct SymbolTypes {
839fe013be4SDimitry Andric std::vector<StringRef> Weaks;
840fe013be4SDimitry Andric std::vector<StringRef> Globals;
841fe013be4SDimitry Andric std::vector<StringRef> TLV;
842fe013be4SDimitry Andric std::vector<StringRef> ObjCClasses;
843fe013be4SDimitry Andric std::vector<StringRef> IVars;
844fe013be4SDimitry Andric std::vector<StringRef> EHTypes;
845fe013be4SDimitry Andric
empty__anon78fc00220c11::SymbolFields::SymbolTypes846fe013be4SDimitry Andric bool empty() const {
847fe013be4SDimitry Andric return Weaks.empty() && Globals.empty() && TLV.empty() &&
848fe013be4SDimitry Andric ObjCClasses.empty() && IVars.empty() && EHTypes.empty();
849fe013be4SDimitry Andric }
850fe013be4SDimitry Andric };
851fe013be4SDimitry Andric SymbolTypes Data;
852fe013be4SDimitry Andric SymbolTypes Text;
853fe013be4SDimitry Andric };
854fe013be4SDimitry Andric
serializeSymbols(InterfaceFile::const_filtered_symbol_range Symbols,const TargetList & ActiveTargets)855fe013be4SDimitry Andric Array serializeSymbols(InterfaceFile::const_filtered_symbol_range Symbols,
856fe013be4SDimitry Andric const TargetList &ActiveTargets) {
857fe013be4SDimitry Andric auto AssignForSymbolType = [](SymbolFields::SymbolTypes &Assignment,
858fe013be4SDimitry Andric const Symbol *Sym) {
859fe013be4SDimitry Andric switch (Sym->getKind()) {
860fe013be4SDimitry Andric case SymbolKind::ObjectiveCClass:
861fe013be4SDimitry Andric Assignment.ObjCClasses.emplace_back(Sym->getName());
862fe013be4SDimitry Andric return;
863fe013be4SDimitry Andric case SymbolKind::ObjectiveCClassEHType:
864fe013be4SDimitry Andric Assignment.EHTypes.emplace_back(Sym->getName());
865fe013be4SDimitry Andric return;
866fe013be4SDimitry Andric case SymbolKind::ObjectiveCInstanceVariable:
867fe013be4SDimitry Andric Assignment.IVars.emplace_back(Sym->getName());
868fe013be4SDimitry Andric return;
869fe013be4SDimitry Andric case SymbolKind::GlobalSymbol: {
870fe013be4SDimitry Andric if (Sym->isWeakReferenced() || Sym->isWeakDefined())
871fe013be4SDimitry Andric Assignment.Weaks.emplace_back(Sym->getName());
872fe013be4SDimitry Andric else if (Sym->isThreadLocalValue())
873fe013be4SDimitry Andric Assignment.TLV.emplace_back(Sym->getName());
874fe013be4SDimitry Andric else
875fe013be4SDimitry Andric Assignment.Globals.emplace_back(Sym->getName());
876fe013be4SDimitry Andric return;
877fe013be4SDimitry Andric }
878fe013be4SDimitry Andric }
879fe013be4SDimitry Andric };
880fe013be4SDimitry Andric
881fe013be4SDimitry Andric std::map<std::vector<std::string>, SymbolFields> Entries;
882fe013be4SDimitry Andric for (const auto *Sym : Symbols) {
883fe013be4SDimitry Andric std::set<MachO::Target> Targets{Sym->targets().begin(),
884fe013be4SDimitry Andric Sym->targets().end()};
885fe013be4SDimitry Andric auto JSONTargets = serializeTargets(Targets, ActiveTargets);
886fe013be4SDimitry Andric if (Sym->isData())
887fe013be4SDimitry Andric AssignForSymbolType(Entries[std::move(JSONTargets)].Data, Sym);
888fe013be4SDimitry Andric else if (Sym->isText())
889fe013be4SDimitry Andric AssignForSymbolType(Entries[std::move(JSONTargets)].Text, Sym);
890fe013be4SDimitry Andric else
891fe013be4SDimitry Andric llvm_unreachable("unexpected symbol type");
892fe013be4SDimitry Andric }
893fe013be4SDimitry Andric
894fe013be4SDimitry Andric auto InsertSymbolsToJSON = [](Object &SymSection, TBDKey SegmentKey,
895fe013be4SDimitry Andric SymbolFields::SymbolTypes &SymField) {
896fe013be4SDimitry Andric if (SymField.empty())
897fe013be4SDimitry Andric return;
898fe013be4SDimitry Andric Object Segment;
899fe013be4SDimitry Andric insertNonEmptyValues(Segment, TBDKey::Globals, std::move(SymField.Globals));
900fe013be4SDimitry Andric insertNonEmptyValues(Segment, TBDKey::ThreadLocal, std::move(SymField.TLV));
901fe013be4SDimitry Andric insertNonEmptyValues(Segment, TBDKey::Weak, std::move(SymField.Weaks));
902fe013be4SDimitry Andric insertNonEmptyValues(Segment, TBDKey::ObjCClass,
903fe013be4SDimitry Andric std::move(SymField.ObjCClasses));
904fe013be4SDimitry Andric insertNonEmptyValues(Segment, TBDKey::ObjCEHType,
905fe013be4SDimitry Andric std::move(SymField.EHTypes));
906fe013be4SDimitry Andric insertNonEmptyValues(Segment, TBDKey::ObjCIvar, std::move(SymField.IVars));
907fe013be4SDimitry Andric insertNonEmptyValues(SymSection, SegmentKey, std::move(Segment));
908fe013be4SDimitry Andric };
909fe013be4SDimitry Andric
910fe013be4SDimitry Andric Array SymbolSection;
911fe013be4SDimitry Andric for (auto &[Targets, Fields] : Entries) {
912fe013be4SDimitry Andric Object AllSyms;
913fe013be4SDimitry Andric insertNonEmptyValues(AllSyms, TBDKey::Targets, std::move(Targets));
914fe013be4SDimitry Andric InsertSymbolsToJSON(AllSyms, TBDKey::Data, Fields.Data);
915fe013be4SDimitry Andric InsertSymbolsToJSON(AllSyms, TBDKey::Text, Fields.Text);
916fe013be4SDimitry Andric SymbolSection.emplace_back(std::move(AllSyms));
917fe013be4SDimitry Andric }
918fe013be4SDimitry Andric
919fe013be4SDimitry Andric return SymbolSection;
920fe013be4SDimitry Andric }
921fe013be4SDimitry Andric
serializeFlags(const InterfaceFile * File)922fe013be4SDimitry Andric Array serializeFlags(const InterfaceFile *File) {
923fe013be4SDimitry Andric // TODO: Give all Targets the same flags for now.
924fe013be4SDimitry Andric Array Flags;
925fe013be4SDimitry Andric if (!File->isTwoLevelNamespace())
926fe013be4SDimitry Andric Flags.emplace_back("flat_namespace");
927fe013be4SDimitry Andric if (!File->isApplicationExtensionSafe())
928fe013be4SDimitry Andric Flags.emplace_back("not_app_extension_safe");
929c9157d92SDimitry Andric if (File->hasSimulatorSupport())
930c9157d92SDimitry Andric Flags.emplace_back("sim_support");
931c9157d92SDimitry Andric if (File->isOSLibNotForSharedCache())
932c9157d92SDimitry Andric Flags.emplace_back("not_for_dyld_shared_cache");
933fe013be4SDimitry Andric return serializeScalar(TBDKey::Attributes, std::move(Flags));
934fe013be4SDimitry Andric }
935fe013be4SDimitry Andric
serializeIF(const InterfaceFile * File)936fe013be4SDimitry Andric Expected<Object> serializeIF(const InterfaceFile *File) {
937fe013be4SDimitry Andric Object Library;
938fe013be4SDimitry Andric
939fe013be4SDimitry Andric // Handle required keys.
940fe013be4SDimitry Andric TargetList ActiveTargets{File->targets().begin(), File->targets().end()};
941fe013be4SDimitry Andric if (!insertNonEmptyValues(Library, TBDKey::TargetInfo,
942fe013be4SDimitry Andric serializeTargetInfo(ActiveTargets)))
943fe013be4SDimitry Andric return make_error<JSONStubError>(getSerializeErrorMsg(TBDKey::TargetInfo));
944fe013be4SDimitry Andric
945fe013be4SDimitry Andric Array Name = serializeScalar<StringRef>(TBDKey::Name, File->getInstallName());
946fe013be4SDimitry Andric if (!insertNonEmptyValues(Library, TBDKey::InstallName, std::move(Name)))
947fe013be4SDimitry Andric return make_error<JSONStubError>(getSerializeErrorMsg(TBDKey::InstallName));
948fe013be4SDimitry Andric
949fe013be4SDimitry Andric // Handle optional keys.
950fe013be4SDimitry Andric Array Flags = serializeFlags(File);
951fe013be4SDimitry Andric insertNonEmptyValues(Library, TBDKey::Flags, std::move(Flags));
952fe013be4SDimitry Andric
953fe013be4SDimitry Andric Array CurrentV = serializeScalar<PackedVersion, std::string>(
954fe013be4SDimitry Andric TBDKey::Version, File->getCurrentVersion(), PackedVersion(1, 0, 0));
955fe013be4SDimitry Andric insertNonEmptyValues(Library, TBDKey::CurrentVersion, std::move(CurrentV));
956fe013be4SDimitry Andric
957fe013be4SDimitry Andric Array CompatV = serializeScalar<PackedVersion, std::string>(
958fe013be4SDimitry Andric TBDKey::Version, File->getCompatibilityVersion(), PackedVersion(1, 0, 0));
959fe013be4SDimitry Andric insertNonEmptyValues(Library, TBDKey::CompatibilityVersion,
960fe013be4SDimitry Andric std::move(CompatV));
961fe013be4SDimitry Andric
962fe013be4SDimitry Andric Array SwiftABI = serializeScalar<uint8_t, int64_t>(
963fe013be4SDimitry Andric TBDKey::ABI, File->getSwiftABIVersion(), 0u);
964fe013be4SDimitry Andric insertNonEmptyValues(Library, TBDKey::SwiftABI, std::move(SwiftABI));
965fe013be4SDimitry Andric
966fe013be4SDimitry Andric Array RPaths = serializeField(TBDKey::Paths, File->rpaths(), ActiveTargets);
967fe013be4SDimitry Andric insertNonEmptyValues(Library, TBDKey::RPath, std::move(RPaths));
968fe013be4SDimitry Andric
969fe013be4SDimitry Andric Array Umbrellas = serializeField(TBDKey::Umbrella, File->umbrellas(),
970fe013be4SDimitry Andric ActiveTargets, /*IsArray=*/false);
971fe013be4SDimitry Andric insertNonEmptyValues(Library, TBDKey::ParentUmbrella, std::move(Umbrellas));
972fe013be4SDimitry Andric
973fe013be4SDimitry Andric Array Clients =
974fe013be4SDimitry Andric serializeField(TBDKey::Clients, File->allowableClients(), ActiveTargets);
975fe013be4SDimitry Andric insertNonEmptyValues(Library, TBDKey::AllowableClients, std::move(Clients));
976fe013be4SDimitry Andric
977fe013be4SDimitry Andric Array ReexportLibs =
978fe013be4SDimitry Andric serializeField(TBDKey::Names, File->reexportedLibraries(), ActiveTargets);
979fe013be4SDimitry Andric insertNonEmptyValues(Library, TBDKey::ReexportLibs, std::move(ReexportLibs));
980fe013be4SDimitry Andric
981fe013be4SDimitry Andric // Handle symbols.
982fe013be4SDimitry Andric Array Exports = serializeSymbols(File->exports(), ActiveTargets);
983fe013be4SDimitry Andric insertNonEmptyValues(Library, TBDKey::Exports, std::move(Exports));
984fe013be4SDimitry Andric
985fe013be4SDimitry Andric Array Reexports = serializeSymbols(File->reexports(), ActiveTargets);
986fe013be4SDimitry Andric insertNonEmptyValues(Library, TBDKey::Reexports, std::move(Reexports));
987fe013be4SDimitry Andric
988fe013be4SDimitry Andric if (!File->isTwoLevelNamespace()) {
989fe013be4SDimitry Andric Array Undefineds = serializeSymbols(File->undefineds(), ActiveTargets);
990fe013be4SDimitry Andric insertNonEmptyValues(Library, TBDKey::Undefineds, std::move(Undefineds));
991fe013be4SDimitry Andric }
992fe013be4SDimitry Andric
993fe013be4SDimitry Andric return std::move(Library);
994fe013be4SDimitry Andric }
995fe013be4SDimitry Andric
getJSON(const InterfaceFile * File,const FileType FileKind)996c9157d92SDimitry Andric Expected<Object> getJSON(const InterfaceFile *File, const FileType FileKind) {
997c9157d92SDimitry Andric assert(FileKind == FileType::TBD_V5 && "unexpected json file format version");
998fe013be4SDimitry Andric Object Root;
999fe013be4SDimitry Andric
1000fe013be4SDimitry Andric auto MainLibOrErr = serializeIF(File);
1001fe013be4SDimitry Andric if (!MainLibOrErr)
1002fe013be4SDimitry Andric return MainLibOrErr;
1003fe013be4SDimitry Andric Root[Keys[TBDKey::MainLibrary]] = std::move(*MainLibOrErr);
1004fe013be4SDimitry Andric Array Documents;
1005fe013be4SDimitry Andric for (const auto &Doc : File->documents()) {
1006fe013be4SDimitry Andric auto LibOrErr = serializeIF(Doc.get());
1007fe013be4SDimitry Andric if (!LibOrErr)
1008fe013be4SDimitry Andric return LibOrErr;
1009fe013be4SDimitry Andric Documents.emplace_back(std::move(*LibOrErr));
1010fe013be4SDimitry Andric }
1011fe013be4SDimitry Andric
1012fe013be4SDimitry Andric Root[Keys[TBDKey::TBDVersion]] = 5;
1013fe013be4SDimitry Andric insertNonEmptyValues(Root, TBDKey::Documents, std::move(Documents));
1014fe013be4SDimitry Andric return std::move(Root);
1015fe013be4SDimitry Andric }
1016fe013be4SDimitry Andric
1017fe013be4SDimitry Andric } // namespace
1018fe013be4SDimitry Andric
serializeInterfaceFileToJSON(raw_ostream & OS,const InterfaceFile & File,const FileType FileKind,bool Compact)1019fe013be4SDimitry Andric Error MachO::serializeInterfaceFileToJSON(raw_ostream &OS,
1020fe013be4SDimitry Andric const InterfaceFile &File,
1021c9157d92SDimitry Andric const FileType FileKind,
1022fe013be4SDimitry Andric bool Compact) {
1023c9157d92SDimitry Andric auto TextFile = getJSON(&File, FileKind);
1024fe013be4SDimitry Andric if (!TextFile)
1025fe013be4SDimitry Andric return TextFile.takeError();
1026fe013be4SDimitry Andric if (Compact)
1027fe013be4SDimitry Andric OS << formatv("{0}", Value(std::move(*TextFile))) << "\n";
1028fe013be4SDimitry Andric else
1029fe013be4SDimitry Andric OS << formatv("{0:2}", Value(std::move(*TextFile))) << "\n";
1030fe013be4SDimitry Andric return Error::success();
1031fe013be4SDimitry Andric }
1032