clang 23.0.0git
MultiArchSharedLibrary.cpp
Go to the documentation of this file.
1//===- MultiArchSharedLibrary.cpp -----------------------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#include "JSONFormatImpl.h"
10
13#include "llvm/TargetParser/Triple.h"
14
15namespace clang::ssaf {
16
17//----------------------------------------------------------------------------
18// MultiArchSharedLibrary
19//----------------------------------------------------------------------------
20
21llvm::Expected<MultiArchSharedLibrary>
23 auto ExpectedJSON = readJSON(Path);
24 if (!ExpectedJSON) {
25 return ErrorBuilder::wrap(ExpectedJSON.takeError())
26 .context(ErrorMessages::ReadingFromFile, "MultiArchSharedLibrary", Path)
27 .build();
28 }
29
30 Object *RootObjectPtr = ExpectedJSON->getAsObject();
31 if (!RootObjectPtr) {
32 return ErrorBuilder::create(std::errc::invalid_argument,
34 "MultiArchSharedLibrary", "object")
35 .context(ErrorMessages::ReadingFromFile, "MultiArchSharedLibrary", Path)
36 .build();
37 }
38
39 if (auto Err = checkSummaryType(*RootObjectPtr,
41 return ErrorBuilder::wrap(std::move(Err))
42 .context(ErrorMessages::ReadingFromFile, "MultiArchSharedLibrary", Path)
43 .build();
44 }
45
46 auto ExpectedM = readMultiArchSharedLibraryFromObject(*RootObjectPtr);
47 if (!ExpectedM) {
48 return ErrorBuilder::wrap(ExpectedM.takeError())
49 .context(ErrorMessages::ReadingFromFile, "MultiArchSharedLibrary", Path)
50 .build();
51 }
52
53 return std::move(*ExpectedM);
54}
55
57JSONFormat::readMultiArchSharedLibraryFromObject(const Object &RootObject) {
58 const Array *NamespaceArray = RootObject.getArray("namespace");
59 if (!NamespaceArray) {
60 return ErrorBuilder::create(std::errc::invalid_argument,
62 "NestedBuildNamespace", "namespace", "array")
63 .build();
64 }
65
66 auto ExpectedNamespace = nestedBuildNamespaceFromJSON(*NamespaceArray);
67 if (!ExpectedNamespace) {
68 return ErrorBuilder::wrap(ExpectedNamespace.takeError())
69 .context(ErrorMessages::ReadingFromField, "NestedBuildNamespace",
70 "namespace")
71 .build();
72 }
73
74 const Array *MembersArray = RootObject.getArray("members");
75 if (!MembersArray) {
76 return ErrorBuilder::create(std::errc::invalid_argument,
78 "MultiArchSharedLibrary members", "members",
79 "array")
80 .build();
81 }
82
83 MultiArchSharedLibrary M(std::move(*ExpectedNamespace));
84 auto &Members = getMembers(M);
85 const auto &WrapperNamespace = getNamespace(M);
86
87 for (const auto &[Index, MemberValue] : llvm::enumerate(*MembersArray)) {
88 const Object *MemberObject = MemberValue.getAsObject();
89 if (!MemberObject) {
90 return ErrorBuilder::create(std::errc::invalid_argument,
92 "MultiArchSharedLibrary member", Index,
93 "object")
94 .build();
95 }
96
97 if (auto Err = checkSummaryType(*MemberObject, JSONTypeValueLUSummary)) {
98 return ErrorBuilder::wrap(std::move(Err))
100 "MultiArchSharedLibrary member", Index)
101 .build();
102 }
103
104 auto ExpectedMember = readLUSummaryEncodingFromObject(*MemberObject);
105 if (!ExpectedMember) {
106 return ErrorBuilder::wrap(ExpectedMember.takeError())
108 "MultiArchSharedLibrary member", Index)
109 .build();
110 }
111
112 // Every per-arch slice must resolve to the same shared-library identity,
113 // so the member's LUNamespace must equal the wrapper's Namespace.
114 if (WrapperNamespace != getLUNamespace(*ExpectedMember)) {
115 return ErrorBuilder::create(std::errc::invalid_argument,
117 "lu_namespace")
119 "MultiArchSharedLibrary member", Index)
120 .build();
121 }
122
123 auto [It, Inserted] = Members.insert(
124 std::make_unique<LUSummaryEncoding>(std::move(*ExpectedMember)));
125 if (!Inserted) {
126 auto MemberTriple = llvm::Triple::normalize(getTargetTriple(**It).str());
127 return ErrorBuilder::create(std::errc::invalid_argument,
129 "MultiArchSharedLibrary member", Index,
130 MemberTriple)
131 .build();
132 }
133 }
134
135 return std::move(M);
136}
137
138llvm::Error
140 llvm::StringRef Path) {
141 Object RootObject;
142
144
145 RootObject["namespace"] = nestedBuildNamespaceToJSON(getNamespace(M));
146
147 Array MembersArray;
148 MembersArray.reserve(getMembers(M).size());
149 for (const auto &Member : getMembers(M)) {
150 MembersArray.push_back(luSummaryEncodingToJSON(*Member));
151 }
152 RootObject["members"] = std::move(MembersArray);
153
154 if (auto Error = writeJSON(std::move(RootObject), Path)) {
155 return ErrorBuilder::wrap(std::move(Error))
156 .context(ErrorMessages::WritingToFile, "MultiArchSharedLibrary", Path)
157 .build();
158 }
159
160 return llvm::Error::success();
161}
162
163} // namespace clang::ssaf
llvm::json::Array Array
static ErrorBuilder create(std::error_code EC, const char *Fmt, Args &&...ArgVals)
Create an ErrorBuilder with an error code and formatted message.
ErrorBuilder & context(const char *Msg)
Add context information as a plain string.
llvm::Error build() const
Build and return the final error.
static ErrorBuilder wrap(llvm::Error E)
Wrap an existing error and optionally add context.
llvm::Expected< MultiArchSharedLibrary > readMultiArchSharedLibrary(llvm::StringRef Path) override
llvm::Error writeMultiArchSharedLibrary(const MultiArchSharedLibrary &M, llvm::StringRef Path) override
Represents a multi-architecture shared library.
constexpr const char * ReadingFromFile
constexpr const char * ReadingFromField
constexpr const char * FailedToReadObjectAtIndex
constexpr const char * FailedToReadObjectAtField
constexpr const char * MismatchedNestedNamespace
constexpr const char * WritingToFile
constexpr const char * ReadingFromIndex
constexpr const char * FailedInsertionOnDuplication
constexpr const char * FailedToReadObject
constexpr const char * JSONTypeValueMultiArchSharedLibrary
Value written to JSONTypeKey for serialized MultiArchSharedLibrary files.
llvm::json::Array Array
constexpr const char * JSONTypeKey
Root-object key naming the summary kind so files are self-describing.
constexpr const char * JSONTypeValueLUSummary
Value written to JSONTypeKey for serialized LUSummary files.
llvm::json::Object Object
llvm::Expected< Value > readJSON(llvm::StringRef Path)
llvm::Error checkSummaryType(const Object &RootObject, llvm::StringRef ExpectedType)
Reads the JSONTypeKey field from the root object and verifies it equals ExpectedType.
llvm::Error writeJSON(Value &&V, llvm::StringRef Path)