xref: /freebsd-src/contrib/llvm-project/llvm/lib/InterfaceStub/IFSHandler.cpp (revision 81ad626541db97eb356e2c1d4a20eb2a26a766ab)
1fe6060f1SDimitry Andric //===- IFSHandler.cpp -----------------------------------------------------===//
2fe6060f1SDimitry Andric //
3fe6060f1SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4fe6060f1SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5fe6060f1SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6fe6060f1SDimitry Andric //
7fe6060f1SDimitry Andric //===-----------------------------------------------------------------------===/
8fe6060f1SDimitry Andric 
9fe6060f1SDimitry Andric #include "llvm/InterfaceStub/IFSHandler.h"
10*81ad6265SDimitry Andric #include "llvm/ADT/STLExtras.h"
11fe6060f1SDimitry Andric #include "llvm/ADT/StringRef.h"
12fe6060f1SDimitry Andric #include "llvm/ADT/StringSwitch.h"
13fe6060f1SDimitry Andric #include "llvm/ADT/Triple.h"
14fe6060f1SDimitry Andric #include "llvm/BinaryFormat/ELF.h"
15fe6060f1SDimitry Andric #include "llvm/InterfaceStub/IFSStub.h"
16fe6060f1SDimitry Andric #include "llvm/Support/Error.h"
17*81ad6265SDimitry Andric #include "llvm/Support/GlobPattern.h"
18fe6060f1SDimitry Andric #include "llvm/Support/LineIterator.h"
19fe6060f1SDimitry Andric #include "llvm/Support/YAMLTraits.h"
20*81ad6265SDimitry Andric #include <functional>
21fe6060f1SDimitry Andric 
22fe6060f1SDimitry Andric using namespace llvm;
23fe6060f1SDimitry Andric using namespace llvm::ifs;
24fe6060f1SDimitry Andric 
25fe6060f1SDimitry Andric LLVM_YAML_IS_SEQUENCE_VECTOR(IFSSymbol)
26fe6060f1SDimitry Andric 
27fe6060f1SDimitry Andric namespace llvm {
28fe6060f1SDimitry Andric namespace yaml {
29fe6060f1SDimitry Andric 
30fe6060f1SDimitry Andric /// YAML traits for ELFSymbolType.
31fe6060f1SDimitry Andric template <> struct ScalarEnumerationTraits<IFSSymbolType> {
32fe6060f1SDimitry Andric   static void enumeration(IO &IO, IFSSymbolType &SymbolType) {
33fe6060f1SDimitry Andric     IO.enumCase(SymbolType, "NoType", IFSSymbolType::NoType);
34fe6060f1SDimitry Andric     IO.enumCase(SymbolType, "Func", IFSSymbolType::Func);
35fe6060f1SDimitry Andric     IO.enumCase(SymbolType, "Object", IFSSymbolType::Object);
36fe6060f1SDimitry Andric     IO.enumCase(SymbolType, "TLS", IFSSymbolType::TLS);
37fe6060f1SDimitry Andric     IO.enumCase(SymbolType, "Unknown", IFSSymbolType::Unknown);
38fe6060f1SDimitry Andric     // Treat other symbol types as noise, and map to Unknown.
39fe6060f1SDimitry Andric     if (!IO.outputting() && IO.matchEnumFallback())
40fe6060f1SDimitry Andric       SymbolType = IFSSymbolType::Unknown;
41fe6060f1SDimitry Andric   }
42fe6060f1SDimitry Andric };
43fe6060f1SDimitry Andric 
44fe6060f1SDimitry Andric template <> struct ScalarTraits<IFSEndiannessType> {
45fe6060f1SDimitry Andric   static void output(const IFSEndiannessType &Value, void *,
46fe6060f1SDimitry Andric                      llvm::raw_ostream &Out) {
47fe6060f1SDimitry Andric     switch (Value) {
48fe6060f1SDimitry Andric     case IFSEndiannessType::Big:
49fe6060f1SDimitry Andric       Out << "big";
50fe6060f1SDimitry Andric       break;
51fe6060f1SDimitry Andric     case IFSEndiannessType::Little:
52fe6060f1SDimitry Andric       Out << "little";
53fe6060f1SDimitry Andric       break;
54fe6060f1SDimitry Andric     default:
55fe6060f1SDimitry Andric       llvm_unreachable("Unsupported endianness");
56fe6060f1SDimitry Andric     }
57fe6060f1SDimitry Andric   }
58fe6060f1SDimitry Andric 
59fe6060f1SDimitry Andric   static StringRef input(StringRef Scalar, void *, IFSEndiannessType &Value) {
60fe6060f1SDimitry Andric     Value = StringSwitch<IFSEndiannessType>(Scalar)
61fe6060f1SDimitry Andric                 .Case("big", IFSEndiannessType::Big)
62fe6060f1SDimitry Andric                 .Case("little", IFSEndiannessType::Little)
63fe6060f1SDimitry Andric                 .Default(IFSEndiannessType::Unknown);
64fe6060f1SDimitry Andric     if (Value == IFSEndiannessType::Unknown) {
65fe6060f1SDimitry Andric       return "Unsupported endianness";
66fe6060f1SDimitry Andric     }
67fe6060f1SDimitry Andric     return StringRef();
68fe6060f1SDimitry Andric   }
69fe6060f1SDimitry Andric 
70fe6060f1SDimitry Andric   static QuotingType mustQuote(StringRef) { return QuotingType::None; }
71fe6060f1SDimitry Andric };
72fe6060f1SDimitry Andric 
73fe6060f1SDimitry Andric template <> struct ScalarTraits<IFSBitWidthType> {
74fe6060f1SDimitry Andric   static void output(const IFSBitWidthType &Value, void *,
75fe6060f1SDimitry Andric                      llvm::raw_ostream &Out) {
76fe6060f1SDimitry Andric     switch (Value) {
77fe6060f1SDimitry Andric     case IFSBitWidthType::IFS32:
78fe6060f1SDimitry Andric       Out << "32";
79fe6060f1SDimitry Andric       break;
80fe6060f1SDimitry Andric     case IFSBitWidthType::IFS64:
81fe6060f1SDimitry Andric       Out << "64";
82fe6060f1SDimitry Andric       break;
83fe6060f1SDimitry Andric     default:
84fe6060f1SDimitry Andric       llvm_unreachable("Unsupported bit width");
85fe6060f1SDimitry Andric     }
86fe6060f1SDimitry Andric   }
87fe6060f1SDimitry Andric 
88fe6060f1SDimitry Andric   static StringRef input(StringRef Scalar, void *, IFSBitWidthType &Value) {
89fe6060f1SDimitry Andric     Value = StringSwitch<IFSBitWidthType>(Scalar)
90fe6060f1SDimitry Andric                 .Case("32", IFSBitWidthType::IFS32)
91fe6060f1SDimitry Andric                 .Case("64", IFSBitWidthType::IFS64)
92fe6060f1SDimitry Andric                 .Default(IFSBitWidthType::Unknown);
93fe6060f1SDimitry Andric     if (Value == IFSBitWidthType::Unknown) {
94fe6060f1SDimitry Andric       return "Unsupported bit width";
95fe6060f1SDimitry Andric     }
96fe6060f1SDimitry Andric     return StringRef();
97fe6060f1SDimitry Andric   }
98fe6060f1SDimitry Andric 
99fe6060f1SDimitry Andric   static QuotingType mustQuote(StringRef) { return QuotingType::None; }
100fe6060f1SDimitry Andric };
101fe6060f1SDimitry Andric 
102fe6060f1SDimitry Andric template <> struct MappingTraits<IFSTarget> {
103fe6060f1SDimitry Andric   static void mapping(IO &IO, IFSTarget &Target) {
104fe6060f1SDimitry Andric     IO.mapOptional("ObjectFormat", Target.ObjectFormat);
105fe6060f1SDimitry Andric     IO.mapOptional("Arch", Target.ArchString);
106fe6060f1SDimitry Andric     IO.mapOptional("Endianness", Target.Endianness);
107fe6060f1SDimitry Andric     IO.mapOptional("BitWidth", Target.BitWidth);
108fe6060f1SDimitry Andric   }
109fe6060f1SDimitry Andric 
110fe6060f1SDimitry Andric   // Compacts symbol information into a single line.
111fe6060f1SDimitry Andric   static const bool flow = true; // NOLINT(readability-identifier-naming)
112fe6060f1SDimitry Andric };
113fe6060f1SDimitry Andric 
114fe6060f1SDimitry Andric /// YAML traits for ELFSymbol.
115fe6060f1SDimitry Andric template <> struct MappingTraits<IFSSymbol> {
116fe6060f1SDimitry Andric   static void mapping(IO &IO, IFSSymbol &Symbol) {
117fe6060f1SDimitry Andric     IO.mapRequired("Name", Symbol.Name);
118fe6060f1SDimitry Andric     IO.mapRequired("Type", Symbol.Type);
119fe6060f1SDimitry Andric     // The need for symbol size depends on the symbol type.
120fe6060f1SDimitry Andric     if (Symbol.Type == IFSSymbolType::NoType) {
121*81ad6265SDimitry Andric       // Size is None, so we are reading it in, or it is non 0 so we
122*81ad6265SDimitry Andric       // should emit it.
123*81ad6265SDimitry Andric       if (!Symbol.Size || *Symbol.Size)
124*81ad6265SDimitry Andric         IO.mapOptional("Size", Symbol.Size);
125*81ad6265SDimitry Andric     } else if (Symbol.Type != IFSSymbolType::Func) {
126*81ad6265SDimitry Andric       IO.mapOptional("Size", Symbol.Size);
127fe6060f1SDimitry Andric     }
128fe6060f1SDimitry Andric     IO.mapOptional("Undefined", Symbol.Undefined, false);
129fe6060f1SDimitry Andric     IO.mapOptional("Weak", Symbol.Weak, false);
130fe6060f1SDimitry Andric     IO.mapOptional("Warning", Symbol.Warning);
131fe6060f1SDimitry Andric   }
132fe6060f1SDimitry Andric 
133fe6060f1SDimitry Andric   // Compacts symbol information into a single line.
134fe6060f1SDimitry Andric   static const bool flow = true; // NOLINT(readability-identifier-naming)
135fe6060f1SDimitry Andric };
136fe6060f1SDimitry Andric 
137fe6060f1SDimitry Andric /// YAML traits for ELFStub objects.
138fe6060f1SDimitry Andric template <> struct MappingTraits<IFSStub> {
139fe6060f1SDimitry Andric   static void mapping(IO &IO, IFSStub &Stub) {
140fe6060f1SDimitry Andric     if (!IO.mapTag("!ifs-v1", true))
141fe6060f1SDimitry Andric       IO.setError("Not a .tbe YAML file.");
142fe6060f1SDimitry Andric     IO.mapRequired("IfsVersion", Stub.IfsVersion);
143fe6060f1SDimitry Andric     IO.mapOptional("SoName", Stub.SoName);
144fe6060f1SDimitry Andric     IO.mapOptional("Target", Stub.Target);
145fe6060f1SDimitry Andric     IO.mapOptional("NeededLibs", Stub.NeededLibs);
146fe6060f1SDimitry Andric     IO.mapRequired("Symbols", Stub.Symbols);
147fe6060f1SDimitry Andric   }
148fe6060f1SDimitry Andric };
149fe6060f1SDimitry Andric 
150fe6060f1SDimitry Andric /// YAML traits for ELFStubTriple objects.
151fe6060f1SDimitry Andric template <> struct MappingTraits<IFSStubTriple> {
152fe6060f1SDimitry Andric   static void mapping(IO &IO, IFSStubTriple &Stub) {
153fe6060f1SDimitry Andric     if (!IO.mapTag("!ifs-v1", true))
154fe6060f1SDimitry Andric       IO.setError("Not a .tbe YAML file.");
155fe6060f1SDimitry Andric     IO.mapRequired("IfsVersion", Stub.IfsVersion);
156fe6060f1SDimitry Andric     IO.mapOptional("SoName", Stub.SoName);
157fe6060f1SDimitry Andric     IO.mapOptional("Target", Stub.Target.Triple);
158fe6060f1SDimitry Andric     IO.mapOptional("NeededLibs", Stub.NeededLibs);
159fe6060f1SDimitry Andric     IO.mapRequired("Symbols", Stub.Symbols);
160fe6060f1SDimitry Andric   }
161fe6060f1SDimitry Andric };
162fe6060f1SDimitry Andric } // end namespace yaml
163fe6060f1SDimitry Andric } // end namespace llvm
164fe6060f1SDimitry Andric 
165fe6060f1SDimitry Andric /// Attempt to determine if a Text stub uses target triple.
166fe6060f1SDimitry Andric bool usesTriple(StringRef Buf) {
167fe6060f1SDimitry Andric   for (line_iterator I(MemoryBufferRef(Buf, "ELFStub")); !I.is_at_eof(); ++I) {
168fe6060f1SDimitry Andric     StringRef Line = (*I).trim();
169fe6060f1SDimitry Andric     if (Line.startswith("Target:")) {
170349cc55cSDimitry Andric       if (Line == "Target:" || Line.contains("{")) {
171fe6060f1SDimitry Andric         return false;
172fe6060f1SDimitry Andric       }
173fe6060f1SDimitry Andric     }
174fe6060f1SDimitry Andric   }
175fe6060f1SDimitry Andric   return true;
176fe6060f1SDimitry Andric }
177fe6060f1SDimitry Andric 
178fe6060f1SDimitry Andric Expected<std::unique_ptr<IFSStub>> ifs::readIFSFromBuffer(StringRef Buf) {
179fe6060f1SDimitry Andric   yaml::Input YamlIn(Buf);
180fe6060f1SDimitry Andric   std::unique_ptr<IFSStubTriple> Stub(new IFSStubTriple());
181fe6060f1SDimitry Andric   if (usesTriple(Buf)) {
182fe6060f1SDimitry Andric     YamlIn >> *Stub;
183fe6060f1SDimitry Andric   } else {
184fe6060f1SDimitry Andric     YamlIn >> *static_cast<IFSStub *>(Stub.get());
185fe6060f1SDimitry Andric   }
186fe6060f1SDimitry Andric   if (std::error_code Err = YamlIn.error()) {
187fe6060f1SDimitry Andric     return createStringError(Err, "YAML failed reading as IFS");
188fe6060f1SDimitry Andric   }
189fe6060f1SDimitry Andric 
190fe6060f1SDimitry Andric   if (Stub->IfsVersion > IFSVersionCurrent)
191fe6060f1SDimitry Andric     return make_error<StringError>(
192fe6060f1SDimitry Andric         "IFS version " + Stub->IfsVersion.getAsString() + " is unsupported.",
193fe6060f1SDimitry Andric         std::make_error_code(std::errc::invalid_argument));
194fe6060f1SDimitry Andric   if (Stub->Target.ArchString) {
195fe6060f1SDimitry Andric     Stub->Target.Arch =
196*81ad6265SDimitry Andric         ELF::convertArchNameToEMachine(*Stub->Target.ArchString);
197fe6060f1SDimitry Andric   }
198fe6060f1SDimitry Andric   return std::move(Stub);
199fe6060f1SDimitry Andric }
200fe6060f1SDimitry Andric 
201fe6060f1SDimitry Andric Error ifs::writeIFSToOutputStream(raw_ostream &OS, const IFSStub &Stub) {
20204eeddc0SDimitry Andric   yaml::Output YamlOut(OS, nullptr, /*WrapColumn =*/0);
203fe6060f1SDimitry Andric   std::unique_ptr<IFSStubTriple> CopyStub(new IFSStubTriple(Stub));
204fe6060f1SDimitry Andric   if (Stub.Target.Arch) {
205fe6060f1SDimitry Andric     CopyStub->Target.ArchString = std::string(
206fe6060f1SDimitry Andric         ELF::convertEMachineToArchName(Stub.Target.Arch.getValue()));
207fe6060f1SDimitry Andric   }
208fe6060f1SDimitry Andric   IFSTarget Target = Stub.Target;
209fe6060f1SDimitry Andric 
210fe6060f1SDimitry Andric   if (CopyStub->Target.Triple ||
211fe6060f1SDimitry Andric       (!CopyStub->Target.ArchString && !CopyStub->Target.Endianness &&
212fe6060f1SDimitry Andric        !CopyStub->Target.BitWidth))
213fe6060f1SDimitry Andric     YamlOut << *CopyStub;
214fe6060f1SDimitry Andric   else
215fe6060f1SDimitry Andric     YamlOut << *static_cast<IFSStub *>(CopyStub.get());
216fe6060f1SDimitry Andric   return Error::success();
217fe6060f1SDimitry Andric }
218fe6060f1SDimitry Andric 
219fe6060f1SDimitry Andric Error ifs::overrideIFSTarget(IFSStub &Stub, Optional<IFSArch> OverrideArch,
220fe6060f1SDimitry Andric                              Optional<IFSEndiannessType> OverrideEndianness,
221fe6060f1SDimitry Andric                              Optional<IFSBitWidthType> OverrideBitWidth,
222fe6060f1SDimitry Andric                              Optional<std::string> OverrideTriple) {
223fe6060f1SDimitry Andric   std::error_code OverrideEC(1, std::generic_category());
224fe6060f1SDimitry Andric   if (OverrideArch) {
225fe6060f1SDimitry Andric     if (Stub.Target.Arch &&
226fe6060f1SDimitry Andric         Stub.Target.Arch.getValue() != OverrideArch.getValue()) {
227fe6060f1SDimitry Andric       return make_error<StringError>(
228fe6060f1SDimitry Andric           "Supplied Arch conflicts with the text stub", OverrideEC);
229fe6060f1SDimitry Andric     }
230fe6060f1SDimitry Andric     Stub.Target.Arch = OverrideArch.getValue();
231fe6060f1SDimitry Andric   }
232fe6060f1SDimitry Andric   if (OverrideEndianness) {
233fe6060f1SDimitry Andric     if (Stub.Target.Endianness &&
234fe6060f1SDimitry Andric         Stub.Target.Endianness.getValue() != OverrideEndianness.getValue()) {
235fe6060f1SDimitry Andric       return make_error<StringError>(
236fe6060f1SDimitry Andric           "Supplied Endianness conflicts with the text stub", OverrideEC);
237fe6060f1SDimitry Andric     }
238fe6060f1SDimitry Andric     Stub.Target.Endianness = OverrideEndianness.getValue();
239fe6060f1SDimitry Andric   }
240fe6060f1SDimitry Andric   if (OverrideBitWidth) {
241fe6060f1SDimitry Andric     if (Stub.Target.BitWidth &&
242fe6060f1SDimitry Andric         Stub.Target.BitWidth.getValue() != OverrideBitWidth.getValue()) {
243fe6060f1SDimitry Andric       return make_error<StringError>(
244fe6060f1SDimitry Andric           "Supplied BitWidth conflicts with the text stub", OverrideEC);
245fe6060f1SDimitry Andric     }
246fe6060f1SDimitry Andric     Stub.Target.BitWidth = OverrideBitWidth.getValue();
247fe6060f1SDimitry Andric   }
248fe6060f1SDimitry Andric   if (OverrideTriple) {
249fe6060f1SDimitry Andric     if (Stub.Target.Triple &&
250fe6060f1SDimitry Andric         Stub.Target.Triple.getValue() != OverrideTriple.getValue()) {
251fe6060f1SDimitry Andric       return make_error<StringError>(
252fe6060f1SDimitry Andric           "Supplied Triple conflicts with the text stub", OverrideEC);
253fe6060f1SDimitry Andric     }
254fe6060f1SDimitry Andric     Stub.Target.Triple = OverrideTriple.getValue();
255fe6060f1SDimitry Andric   }
256fe6060f1SDimitry Andric   return Error::success();
257fe6060f1SDimitry Andric }
258fe6060f1SDimitry Andric 
259fe6060f1SDimitry Andric Error ifs::validateIFSTarget(IFSStub &Stub, bool ParseTriple) {
260fe6060f1SDimitry Andric   std::error_code ValidationEC(1, std::generic_category());
261fe6060f1SDimitry Andric   if (Stub.Target.Triple) {
262fe6060f1SDimitry Andric     if (Stub.Target.Arch || Stub.Target.BitWidth || Stub.Target.Endianness ||
263fe6060f1SDimitry Andric         Stub.Target.ObjectFormat) {
264fe6060f1SDimitry Andric       return make_error<StringError>(
265fe6060f1SDimitry Andric           "Target triple cannot be used simultaneously with ELF target format",
266fe6060f1SDimitry Andric           ValidationEC);
267fe6060f1SDimitry Andric     }
268fe6060f1SDimitry Andric     if (ParseTriple) {
269*81ad6265SDimitry Andric       IFSTarget TargetFromTriple = parseTriple(*Stub.Target.Triple);
270fe6060f1SDimitry Andric       Stub.Target.Arch = TargetFromTriple.Arch;
271fe6060f1SDimitry Andric       Stub.Target.BitWidth = TargetFromTriple.BitWidth;
272fe6060f1SDimitry Andric       Stub.Target.Endianness = TargetFromTriple.Endianness;
273fe6060f1SDimitry Andric     }
274fe6060f1SDimitry Andric     return Error::success();
275fe6060f1SDimitry Andric   }
276fe6060f1SDimitry Andric   if (!Stub.Target.Arch || !Stub.Target.BitWidth || !Stub.Target.Endianness) {
277fe6060f1SDimitry Andric     // TODO: unify the error message.
278fe6060f1SDimitry Andric     if (!Stub.Target.Arch) {
279fe6060f1SDimitry Andric       return make_error<StringError>("Arch is not defined in the text stub",
280fe6060f1SDimitry Andric                                      ValidationEC);
281fe6060f1SDimitry Andric     }
282fe6060f1SDimitry Andric     if (!Stub.Target.BitWidth) {
283fe6060f1SDimitry Andric       return make_error<StringError>("BitWidth is not defined in the text stub",
284fe6060f1SDimitry Andric                                      ValidationEC);
285fe6060f1SDimitry Andric     }
286fe6060f1SDimitry Andric     if (!Stub.Target.Endianness) {
287fe6060f1SDimitry Andric       return make_error<StringError>(
288fe6060f1SDimitry Andric           "Endianness is not defined in the text stub", ValidationEC);
289fe6060f1SDimitry Andric     }
290fe6060f1SDimitry Andric   }
291fe6060f1SDimitry Andric   return Error::success();
292fe6060f1SDimitry Andric }
293fe6060f1SDimitry Andric 
294fe6060f1SDimitry Andric IFSTarget ifs::parseTriple(StringRef TripleStr) {
295fe6060f1SDimitry Andric   Triple IFSTriple(TripleStr);
296fe6060f1SDimitry Andric   IFSTarget RetTarget;
297fe6060f1SDimitry Andric   // TODO: Implement a Triple Arch enum to e_machine map.
298fe6060f1SDimitry Andric   switch (IFSTriple.getArch()) {
299fe6060f1SDimitry Andric   case Triple::ArchType::aarch64:
300fe6060f1SDimitry Andric     RetTarget.Arch = (IFSArch)ELF::EM_AARCH64;
301fe6060f1SDimitry Andric     break;
302fe6060f1SDimitry Andric   case Triple::ArchType::x86_64:
303fe6060f1SDimitry Andric     RetTarget.Arch = (IFSArch)ELF::EM_X86_64;
304fe6060f1SDimitry Andric     break;
305fe6060f1SDimitry Andric   default:
306fe6060f1SDimitry Andric     RetTarget.Arch = (IFSArch)ELF::EM_NONE;
307fe6060f1SDimitry Andric   }
308fe6060f1SDimitry Andric   RetTarget.Endianness = IFSTriple.isLittleEndian() ? IFSEndiannessType::Little
309fe6060f1SDimitry Andric                                                     : IFSEndiannessType::Big;
310fe6060f1SDimitry Andric   RetTarget.BitWidth =
311fe6060f1SDimitry Andric       IFSTriple.isArch64Bit() ? IFSBitWidthType::IFS64 : IFSBitWidthType::IFS32;
312fe6060f1SDimitry Andric   return RetTarget;
313fe6060f1SDimitry Andric }
314fe6060f1SDimitry Andric 
315fe6060f1SDimitry Andric void ifs::stripIFSTarget(IFSStub &Stub, bool StripTriple, bool StripArch,
316fe6060f1SDimitry Andric                          bool StripEndianness, bool StripBitWidth) {
317fe6060f1SDimitry Andric   if (StripTriple || StripArch) {
318fe6060f1SDimitry Andric     Stub.Target.Arch.reset();
319fe6060f1SDimitry Andric     Stub.Target.ArchString.reset();
320fe6060f1SDimitry Andric   }
321fe6060f1SDimitry Andric   if (StripTriple || StripEndianness) {
322fe6060f1SDimitry Andric     Stub.Target.Endianness.reset();
323fe6060f1SDimitry Andric   }
324fe6060f1SDimitry Andric   if (StripTriple || StripBitWidth) {
325fe6060f1SDimitry Andric     Stub.Target.BitWidth.reset();
326fe6060f1SDimitry Andric   }
327fe6060f1SDimitry Andric   if (StripTriple) {
328fe6060f1SDimitry Andric     Stub.Target.Triple.reset();
329fe6060f1SDimitry Andric   }
330fe6060f1SDimitry Andric   if (!Stub.Target.Arch && !Stub.Target.BitWidth && !Stub.Target.Endianness) {
331fe6060f1SDimitry Andric     Stub.Target.ObjectFormat.reset();
332fe6060f1SDimitry Andric   }
333fe6060f1SDimitry Andric }
334349cc55cSDimitry Andric 
335*81ad6265SDimitry Andric Error ifs::filterIFSSyms(IFSStub &Stub, bool StripUndefined,
336*81ad6265SDimitry Andric                          const std::vector<std::string> &Exclude) {
337*81ad6265SDimitry Andric   std::function<bool(const IFSSymbol &)> Filter = [](const IFSSymbol &) {
338*81ad6265SDimitry Andric     return false;
339*81ad6265SDimitry Andric   };
340*81ad6265SDimitry Andric 
341*81ad6265SDimitry Andric   if (StripUndefined) {
342*81ad6265SDimitry Andric     Filter = [Filter](const IFSSymbol &Sym) {
343*81ad6265SDimitry Andric       return Sym.Undefined || Filter(Sym);
344*81ad6265SDimitry Andric     };
345349cc55cSDimitry Andric   }
346*81ad6265SDimitry Andric 
347*81ad6265SDimitry Andric   for (StringRef Glob : Exclude) {
348*81ad6265SDimitry Andric     Expected<llvm::GlobPattern> PatternOrErr = llvm::GlobPattern::create(Glob);
349*81ad6265SDimitry Andric     if (!PatternOrErr)
350*81ad6265SDimitry Andric       return PatternOrErr.takeError();
351*81ad6265SDimitry Andric     Filter = [Pattern = *PatternOrErr, Filter](const IFSSymbol &Sym) {
352*81ad6265SDimitry Andric       return Pattern.match(Sym.Name) || Filter(Sym);
353*81ad6265SDimitry Andric     };
354349cc55cSDimitry Andric   }
355*81ad6265SDimitry Andric 
356*81ad6265SDimitry Andric   llvm::erase_if(Stub.Symbols, Filter);
357*81ad6265SDimitry Andric 
358*81ad6265SDimitry Andric   return Error::success();
359349cc55cSDimitry Andric }
360