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" 1081ad6265SDimitry Andric #include "llvm/ADT/STLExtras.h" 11fe6060f1SDimitry Andric #include "llvm/ADT/StringRef.h" 12fe6060f1SDimitry Andric #include "llvm/ADT/StringSwitch.h" 13fe6060f1SDimitry Andric #include "llvm/BinaryFormat/ELF.h" 14fe6060f1SDimitry Andric #include "llvm/InterfaceStub/IFSStub.h" 15fe6060f1SDimitry Andric #include "llvm/Support/Error.h" 1681ad6265SDimitry Andric #include "llvm/Support/GlobPattern.h" 17fe6060f1SDimitry Andric #include "llvm/Support/LineIterator.h" 18fe6060f1SDimitry Andric #include "llvm/Support/YAMLTraits.h" 1906c3fb27SDimitry Andric #include "llvm/TargetParser/Triple.h" 2081ad6265SDimitry Andric #include <functional> 21bdd1243dSDimitry Andric #include <optional> 22fe6060f1SDimitry Andric 23fe6060f1SDimitry Andric using namespace llvm; 24fe6060f1SDimitry Andric using namespace llvm::ifs; 25fe6060f1SDimitry Andric 26fe6060f1SDimitry Andric LLVM_YAML_IS_SEQUENCE_VECTOR(IFSSymbol) 27fe6060f1SDimitry Andric 28fe6060f1SDimitry Andric namespace llvm { 29fe6060f1SDimitry Andric namespace yaml { 30fe6060f1SDimitry Andric 31fe6060f1SDimitry Andric /// YAML traits for ELFSymbolType. 32fe6060f1SDimitry Andric template <> struct ScalarEnumerationTraits<IFSSymbolType> { 33fe6060f1SDimitry Andric static void enumeration(IO &IO, IFSSymbolType &SymbolType) { 34fe6060f1SDimitry Andric IO.enumCase(SymbolType, "NoType", IFSSymbolType::NoType); 35fe6060f1SDimitry Andric IO.enumCase(SymbolType, "Func", IFSSymbolType::Func); 36fe6060f1SDimitry Andric IO.enumCase(SymbolType, "Object", IFSSymbolType::Object); 37fe6060f1SDimitry Andric IO.enumCase(SymbolType, "TLS", IFSSymbolType::TLS); 38fe6060f1SDimitry Andric IO.enumCase(SymbolType, "Unknown", IFSSymbolType::Unknown); 39fe6060f1SDimitry Andric // Treat other symbol types as noise, and map to Unknown. 40fe6060f1SDimitry Andric if (!IO.outputting() && IO.matchEnumFallback()) 41fe6060f1SDimitry Andric SymbolType = IFSSymbolType::Unknown; 42fe6060f1SDimitry Andric } 43fe6060f1SDimitry Andric }; 44fe6060f1SDimitry Andric 45fe6060f1SDimitry Andric template <> struct ScalarTraits<IFSEndiannessType> { 46fe6060f1SDimitry Andric static void output(const IFSEndiannessType &Value, void *, 47fe6060f1SDimitry Andric llvm::raw_ostream &Out) { 48fe6060f1SDimitry Andric switch (Value) { 49fe6060f1SDimitry Andric case IFSEndiannessType::Big: 50fe6060f1SDimitry Andric Out << "big"; 51fe6060f1SDimitry Andric break; 52fe6060f1SDimitry Andric case IFSEndiannessType::Little: 53fe6060f1SDimitry Andric Out << "little"; 54fe6060f1SDimitry Andric break; 55fe6060f1SDimitry Andric default: 56fe6060f1SDimitry Andric llvm_unreachable("Unsupported endianness"); 57fe6060f1SDimitry Andric } 58fe6060f1SDimitry Andric } 59fe6060f1SDimitry Andric 60fe6060f1SDimitry Andric static StringRef input(StringRef Scalar, void *, IFSEndiannessType &Value) { 61fe6060f1SDimitry Andric Value = StringSwitch<IFSEndiannessType>(Scalar) 62fe6060f1SDimitry Andric .Case("big", IFSEndiannessType::Big) 63fe6060f1SDimitry Andric .Case("little", IFSEndiannessType::Little) 64fe6060f1SDimitry Andric .Default(IFSEndiannessType::Unknown); 65fe6060f1SDimitry Andric if (Value == IFSEndiannessType::Unknown) { 66fe6060f1SDimitry Andric return "Unsupported endianness"; 67fe6060f1SDimitry Andric } 68fe6060f1SDimitry Andric return StringRef(); 69fe6060f1SDimitry Andric } 70fe6060f1SDimitry Andric 71fe6060f1SDimitry Andric static QuotingType mustQuote(StringRef) { return QuotingType::None; } 72fe6060f1SDimitry Andric }; 73fe6060f1SDimitry Andric 74fe6060f1SDimitry Andric template <> struct ScalarTraits<IFSBitWidthType> { 75fe6060f1SDimitry Andric static void output(const IFSBitWidthType &Value, void *, 76fe6060f1SDimitry Andric llvm::raw_ostream &Out) { 77fe6060f1SDimitry Andric switch (Value) { 78fe6060f1SDimitry Andric case IFSBitWidthType::IFS32: 79fe6060f1SDimitry Andric Out << "32"; 80fe6060f1SDimitry Andric break; 81fe6060f1SDimitry Andric case IFSBitWidthType::IFS64: 82fe6060f1SDimitry Andric Out << "64"; 83fe6060f1SDimitry Andric break; 84fe6060f1SDimitry Andric default: 85fe6060f1SDimitry Andric llvm_unreachable("Unsupported bit width"); 86fe6060f1SDimitry Andric } 87fe6060f1SDimitry Andric } 88fe6060f1SDimitry Andric 89fe6060f1SDimitry Andric static StringRef input(StringRef Scalar, void *, IFSBitWidthType &Value) { 90fe6060f1SDimitry Andric Value = StringSwitch<IFSBitWidthType>(Scalar) 91fe6060f1SDimitry Andric .Case("32", IFSBitWidthType::IFS32) 92fe6060f1SDimitry Andric .Case("64", IFSBitWidthType::IFS64) 93fe6060f1SDimitry Andric .Default(IFSBitWidthType::Unknown); 94fe6060f1SDimitry Andric if (Value == IFSBitWidthType::Unknown) { 95fe6060f1SDimitry Andric return "Unsupported bit width"; 96fe6060f1SDimitry Andric } 97fe6060f1SDimitry Andric return StringRef(); 98fe6060f1SDimitry Andric } 99fe6060f1SDimitry Andric 100fe6060f1SDimitry Andric static QuotingType mustQuote(StringRef) { return QuotingType::None; } 101fe6060f1SDimitry Andric }; 102fe6060f1SDimitry Andric 103fe6060f1SDimitry Andric template <> struct MappingTraits<IFSTarget> { 104fe6060f1SDimitry Andric static void mapping(IO &IO, IFSTarget &Target) { 105fe6060f1SDimitry Andric IO.mapOptional("ObjectFormat", Target.ObjectFormat); 106fe6060f1SDimitry Andric IO.mapOptional("Arch", Target.ArchString); 107fe6060f1SDimitry Andric IO.mapOptional("Endianness", Target.Endianness); 108fe6060f1SDimitry Andric IO.mapOptional("BitWidth", Target.BitWidth); 109fe6060f1SDimitry Andric } 110fe6060f1SDimitry Andric 111fe6060f1SDimitry Andric // Compacts symbol information into a single line. 112fe6060f1SDimitry Andric static const bool flow = true; // NOLINT(readability-identifier-naming) 113fe6060f1SDimitry Andric }; 114fe6060f1SDimitry Andric 115fe6060f1SDimitry Andric /// YAML traits for ELFSymbol. 116fe6060f1SDimitry Andric template <> struct MappingTraits<IFSSymbol> { 117fe6060f1SDimitry Andric static void mapping(IO &IO, IFSSymbol &Symbol) { 118fe6060f1SDimitry Andric IO.mapRequired("Name", Symbol.Name); 119fe6060f1SDimitry Andric IO.mapRequired("Type", Symbol.Type); 120fe6060f1SDimitry Andric // The need for symbol size depends on the symbol type. 121fe6060f1SDimitry Andric if (Symbol.Type == IFSSymbolType::NoType) { 12281ad6265SDimitry Andric // Size is None, so we are reading it in, or it is non 0 so we 12381ad6265SDimitry Andric // should emit it. 12481ad6265SDimitry Andric if (!Symbol.Size || *Symbol.Size) 12581ad6265SDimitry Andric IO.mapOptional("Size", Symbol.Size); 12681ad6265SDimitry Andric } else if (Symbol.Type != IFSSymbolType::Func) { 12781ad6265SDimitry Andric IO.mapOptional("Size", Symbol.Size); 128fe6060f1SDimitry Andric } 129fe6060f1SDimitry Andric IO.mapOptional("Undefined", Symbol.Undefined, false); 130fe6060f1SDimitry Andric IO.mapOptional("Weak", Symbol.Weak, false); 131fe6060f1SDimitry Andric IO.mapOptional("Warning", Symbol.Warning); 132fe6060f1SDimitry Andric } 133fe6060f1SDimitry Andric 134fe6060f1SDimitry Andric // Compacts symbol information into a single line. 135fe6060f1SDimitry Andric static const bool flow = true; // NOLINT(readability-identifier-naming) 136fe6060f1SDimitry Andric }; 137fe6060f1SDimitry Andric 138fe6060f1SDimitry Andric /// YAML traits for ELFStub objects. 139fe6060f1SDimitry Andric template <> struct MappingTraits<IFSStub> { 140fe6060f1SDimitry Andric static void mapping(IO &IO, IFSStub &Stub) { 141fe6060f1SDimitry Andric if (!IO.mapTag("!ifs-v1", true)) 142fe6060f1SDimitry Andric IO.setError("Not a .tbe YAML file."); 143fe6060f1SDimitry Andric IO.mapRequired("IfsVersion", Stub.IfsVersion); 144fe6060f1SDimitry Andric IO.mapOptional("SoName", Stub.SoName); 145fe6060f1SDimitry Andric IO.mapOptional("Target", Stub.Target); 146fe6060f1SDimitry Andric IO.mapOptional("NeededLibs", Stub.NeededLibs); 147fe6060f1SDimitry Andric IO.mapRequired("Symbols", Stub.Symbols); 148fe6060f1SDimitry Andric } 149fe6060f1SDimitry Andric }; 150fe6060f1SDimitry Andric 151fe6060f1SDimitry Andric /// YAML traits for ELFStubTriple objects. 152fe6060f1SDimitry Andric template <> struct MappingTraits<IFSStubTriple> { 153fe6060f1SDimitry Andric static void mapping(IO &IO, IFSStubTriple &Stub) { 154fe6060f1SDimitry Andric if (!IO.mapTag("!ifs-v1", true)) 155fe6060f1SDimitry Andric IO.setError("Not a .tbe YAML file."); 156fe6060f1SDimitry Andric IO.mapRequired("IfsVersion", Stub.IfsVersion); 157fe6060f1SDimitry Andric IO.mapOptional("SoName", Stub.SoName); 158fe6060f1SDimitry Andric IO.mapOptional("Target", Stub.Target.Triple); 159fe6060f1SDimitry Andric IO.mapOptional("NeededLibs", Stub.NeededLibs); 160fe6060f1SDimitry Andric IO.mapRequired("Symbols", Stub.Symbols); 161fe6060f1SDimitry Andric } 162fe6060f1SDimitry Andric }; 163fe6060f1SDimitry Andric } // end namespace yaml 164fe6060f1SDimitry Andric } // end namespace llvm 165fe6060f1SDimitry Andric 166fe6060f1SDimitry Andric /// Attempt to determine if a Text stub uses target triple. 167fe6060f1SDimitry Andric bool usesTriple(StringRef Buf) { 168fe6060f1SDimitry Andric for (line_iterator I(MemoryBufferRef(Buf, "ELFStub")); !I.is_at_eof(); ++I) { 169fe6060f1SDimitry Andric StringRef Line = (*I).trim(); 1705f757f3fSDimitry Andric if (Line.starts_with("Target:")) { 171349cc55cSDimitry Andric if (Line == "Target:" || Line.contains("{")) { 172fe6060f1SDimitry Andric return false; 173fe6060f1SDimitry Andric } 174fe6060f1SDimitry Andric } 175fe6060f1SDimitry Andric } 176fe6060f1SDimitry Andric return true; 177fe6060f1SDimitry Andric } 178fe6060f1SDimitry Andric 179fe6060f1SDimitry Andric Expected<std::unique_ptr<IFSStub>> ifs::readIFSFromBuffer(StringRef Buf) { 180fe6060f1SDimitry Andric yaml::Input YamlIn(Buf); 181fe6060f1SDimitry Andric std::unique_ptr<IFSStubTriple> Stub(new IFSStubTriple()); 182fe6060f1SDimitry Andric if (usesTriple(Buf)) { 183fe6060f1SDimitry Andric YamlIn >> *Stub; 184fe6060f1SDimitry Andric } else { 185fe6060f1SDimitry Andric YamlIn >> *static_cast<IFSStub *>(Stub.get()); 186fe6060f1SDimitry Andric } 187fe6060f1SDimitry Andric if (std::error_code Err = YamlIn.error()) { 188fe6060f1SDimitry Andric return createStringError(Err, "YAML failed reading as IFS"); 189fe6060f1SDimitry Andric } 190fe6060f1SDimitry Andric 191fe6060f1SDimitry Andric if (Stub->IfsVersion > IFSVersionCurrent) 192fe6060f1SDimitry Andric return make_error<StringError>( 193fe6060f1SDimitry Andric "IFS version " + Stub->IfsVersion.getAsString() + " is unsupported.", 194fe6060f1SDimitry Andric std::make_error_code(std::errc::invalid_argument)); 195fe6060f1SDimitry Andric if (Stub->Target.ArchString) { 19606c3fb27SDimitry Andric uint16_t eMachine = 19781ad6265SDimitry Andric ELF::convertArchNameToEMachine(*Stub->Target.ArchString); 19806c3fb27SDimitry Andric if (eMachine == ELF::EM_NONE) 19906c3fb27SDimitry Andric return createStringError( 20006c3fb27SDimitry Andric std::make_error_code(std::errc::invalid_argument), 20106c3fb27SDimitry Andric "IFS arch '" + *Stub->Target.ArchString + "' is unsupported"); 20206c3fb27SDimitry Andric Stub->Target.Arch = eMachine; 203fe6060f1SDimitry Andric } 204*7a6dacacSDimitry Andric for (const auto &Item : Stub->Symbols) { 205*7a6dacacSDimitry Andric if (Item.Type == IFSSymbolType::Unknown) 206*7a6dacacSDimitry Andric return createStringError( 207*7a6dacacSDimitry Andric std::make_error_code(std::errc::invalid_argument), 208*7a6dacacSDimitry Andric "IFS symbol type for symbol '" + Item.Name + "' is unsupported"); 209*7a6dacacSDimitry Andric } 210fe6060f1SDimitry Andric return std::move(Stub); 211fe6060f1SDimitry Andric } 212fe6060f1SDimitry Andric 213fe6060f1SDimitry Andric Error ifs::writeIFSToOutputStream(raw_ostream &OS, const IFSStub &Stub) { 21404eeddc0SDimitry Andric yaml::Output YamlOut(OS, nullptr, /*WrapColumn =*/0); 215fe6060f1SDimitry Andric std::unique_ptr<IFSStubTriple> CopyStub(new IFSStubTriple(Stub)); 216fe6060f1SDimitry Andric if (Stub.Target.Arch) { 217753f127fSDimitry Andric CopyStub->Target.ArchString = 218bdd1243dSDimitry Andric std::string(ELF::convertEMachineToArchName(*Stub.Target.Arch)); 219fe6060f1SDimitry Andric } 220fe6060f1SDimitry Andric IFSTarget Target = Stub.Target; 221fe6060f1SDimitry Andric 222fe6060f1SDimitry Andric if (CopyStub->Target.Triple || 223fe6060f1SDimitry Andric (!CopyStub->Target.ArchString && !CopyStub->Target.Endianness && 224fe6060f1SDimitry Andric !CopyStub->Target.BitWidth)) 225fe6060f1SDimitry Andric YamlOut << *CopyStub; 226fe6060f1SDimitry Andric else 227fe6060f1SDimitry Andric YamlOut << *static_cast<IFSStub *>(CopyStub.get()); 228fe6060f1SDimitry Andric return Error::success(); 229fe6060f1SDimitry Andric } 230fe6060f1SDimitry Andric 231bdd1243dSDimitry Andric Error ifs::overrideIFSTarget( 232bdd1243dSDimitry Andric IFSStub &Stub, std::optional<IFSArch> OverrideArch, 233bdd1243dSDimitry Andric std::optional<IFSEndiannessType> OverrideEndianness, 234bdd1243dSDimitry Andric std::optional<IFSBitWidthType> OverrideBitWidth, 235bdd1243dSDimitry Andric std::optional<std::string> OverrideTriple) { 236fe6060f1SDimitry Andric std::error_code OverrideEC(1, std::generic_category()); 237fe6060f1SDimitry Andric if (OverrideArch) { 238bdd1243dSDimitry Andric if (Stub.Target.Arch && *Stub.Target.Arch != *OverrideArch) { 239fe6060f1SDimitry Andric return make_error<StringError>( 240fe6060f1SDimitry Andric "Supplied Arch conflicts with the text stub", OverrideEC); 241fe6060f1SDimitry Andric } 242bdd1243dSDimitry Andric Stub.Target.Arch = *OverrideArch; 243fe6060f1SDimitry Andric } 244fe6060f1SDimitry Andric if (OverrideEndianness) { 245fe6060f1SDimitry Andric if (Stub.Target.Endianness && 246bdd1243dSDimitry Andric *Stub.Target.Endianness != *OverrideEndianness) { 247fe6060f1SDimitry Andric return make_error<StringError>( 248fe6060f1SDimitry Andric "Supplied Endianness conflicts with the text stub", OverrideEC); 249fe6060f1SDimitry Andric } 250bdd1243dSDimitry Andric Stub.Target.Endianness = *OverrideEndianness; 251fe6060f1SDimitry Andric } 252fe6060f1SDimitry Andric if (OverrideBitWidth) { 253bdd1243dSDimitry Andric if (Stub.Target.BitWidth && *Stub.Target.BitWidth != *OverrideBitWidth) { 254fe6060f1SDimitry Andric return make_error<StringError>( 255fe6060f1SDimitry Andric "Supplied BitWidth conflicts with the text stub", OverrideEC); 256fe6060f1SDimitry Andric } 257bdd1243dSDimitry Andric Stub.Target.BitWidth = *OverrideBitWidth; 258fe6060f1SDimitry Andric } 259fe6060f1SDimitry Andric if (OverrideTriple) { 260bdd1243dSDimitry Andric if (Stub.Target.Triple && *Stub.Target.Triple != *OverrideTriple) { 261fe6060f1SDimitry Andric return make_error<StringError>( 262fe6060f1SDimitry Andric "Supplied Triple conflicts with the text stub", OverrideEC); 263fe6060f1SDimitry Andric } 264bdd1243dSDimitry Andric Stub.Target.Triple = *OverrideTriple; 265fe6060f1SDimitry Andric } 266fe6060f1SDimitry Andric return Error::success(); 267fe6060f1SDimitry Andric } 268fe6060f1SDimitry Andric 269fe6060f1SDimitry Andric Error ifs::validateIFSTarget(IFSStub &Stub, bool ParseTriple) { 270fe6060f1SDimitry Andric std::error_code ValidationEC(1, std::generic_category()); 271fe6060f1SDimitry Andric if (Stub.Target.Triple) { 272fe6060f1SDimitry Andric if (Stub.Target.Arch || Stub.Target.BitWidth || Stub.Target.Endianness || 273fe6060f1SDimitry Andric Stub.Target.ObjectFormat) { 274fe6060f1SDimitry Andric return make_error<StringError>( 275fe6060f1SDimitry Andric "Target triple cannot be used simultaneously with ELF target format", 276fe6060f1SDimitry Andric ValidationEC); 277fe6060f1SDimitry Andric } 278fe6060f1SDimitry Andric if (ParseTriple) { 27981ad6265SDimitry Andric IFSTarget TargetFromTriple = parseTriple(*Stub.Target.Triple); 280fe6060f1SDimitry Andric Stub.Target.Arch = TargetFromTriple.Arch; 281fe6060f1SDimitry Andric Stub.Target.BitWidth = TargetFromTriple.BitWidth; 282fe6060f1SDimitry Andric Stub.Target.Endianness = TargetFromTriple.Endianness; 283fe6060f1SDimitry Andric } 284fe6060f1SDimitry Andric return Error::success(); 285fe6060f1SDimitry Andric } 286fe6060f1SDimitry Andric if (!Stub.Target.Arch || !Stub.Target.BitWidth || !Stub.Target.Endianness) { 287fe6060f1SDimitry Andric // TODO: unify the error message. 288fe6060f1SDimitry Andric if (!Stub.Target.Arch) { 289fe6060f1SDimitry Andric return make_error<StringError>("Arch is not defined in the text stub", 290fe6060f1SDimitry Andric ValidationEC); 291fe6060f1SDimitry Andric } 292fe6060f1SDimitry Andric if (!Stub.Target.BitWidth) { 293fe6060f1SDimitry Andric return make_error<StringError>("BitWidth is not defined in the text stub", 294fe6060f1SDimitry Andric ValidationEC); 295fe6060f1SDimitry Andric } 296fe6060f1SDimitry Andric if (!Stub.Target.Endianness) { 297fe6060f1SDimitry Andric return make_error<StringError>( 298fe6060f1SDimitry Andric "Endianness is not defined in the text stub", ValidationEC); 299fe6060f1SDimitry Andric } 300fe6060f1SDimitry Andric } 301fe6060f1SDimitry Andric return Error::success(); 302fe6060f1SDimitry Andric } 303fe6060f1SDimitry Andric 304fe6060f1SDimitry Andric IFSTarget ifs::parseTriple(StringRef TripleStr) { 305fe6060f1SDimitry Andric Triple IFSTriple(TripleStr); 306fe6060f1SDimitry Andric IFSTarget RetTarget; 307fe6060f1SDimitry Andric // TODO: Implement a Triple Arch enum to e_machine map. 308fe6060f1SDimitry Andric switch (IFSTriple.getArch()) { 309fe6060f1SDimitry Andric case Triple::ArchType::aarch64: 310fe6060f1SDimitry Andric RetTarget.Arch = (IFSArch)ELF::EM_AARCH64; 311fe6060f1SDimitry Andric break; 312fe6060f1SDimitry Andric case Triple::ArchType::x86_64: 313fe6060f1SDimitry Andric RetTarget.Arch = (IFSArch)ELF::EM_X86_64; 314fe6060f1SDimitry Andric break; 31506c3fb27SDimitry Andric case Triple::ArchType::riscv64: 31606c3fb27SDimitry Andric RetTarget.Arch = (IFSArch)ELF::EM_RISCV; 31706c3fb27SDimitry Andric break; 318fe6060f1SDimitry Andric default: 319fe6060f1SDimitry Andric RetTarget.Arch = (IFSArch)ELF::EM_NONE; 320fe6060f1SDimitry Andric } 321fe6060f1SDimitry Andric RetTarget.Endianness = IFSTriple.isLittleEndian() ? IFSEndiannessType::Little 322fe6060f1SDimitry Andric : IFSEndiannessType::Big; 323fe6060f1SDimitry Andric RetTarget.BitWidth = 324fe6060f1SDimitry Andric IFSTriple.isArch64Bit() ? IFSBitWidthType::IFS64 : IFSBitWidthType::IFS32; 325fe6060f1SDimitry Andric return RetTarget; 326fe6060f1SDimitry Andric } 327fe6060f1SDimitry Andric 328fe6060f1SDimitry Andric void ifs::stripIFSTarget(IFSStub &Stub, bool StripTriple, bool StripArch, 329fe6060f1SDimitry Andric bool StripEndianness, bool StripBitWidth) { 330fe6060f1SDimitry Andric if (StripTriple || StripArch) { 331fe6060f1SDimitry Andric Stub.Target.Arch.reset(); 332fe6060f1SDimitry Andric Stub.Target.ArchString.reset(); 333fe6060f1SDimitry Andric } 334fe6060f1SDimitry Andric if (StripTriple || StripEndianness) { 335fe6060f1SDimitry Andric Stub.Target.Endianness.reset(); 336fe6060f1SDimitry Andric } 337fe6060f1SDimitry Andric if (StripTriple || StripBitWidth) { 338fe6060f1SDimitry Andric Stub.Target.BitWidth.reset(); 339fe6060f1SDimitry Andric } 340fe6060f1SDimitry Andric if (StripTriple) { 341fe6060f1SDimitry Andric Stub.Target.Triple.reset(); 342fe6060f1SDimitry Andric } 343fe6060f1SDimitry Andric if (!Stub.Target.Arch && !Stub.Target.BitWidth && !Stub.Target.Endianness) { 344fe6060f1SDimitry Andric Stub.Target.ObjectFormat.reset(); 345fe6060f1SDimitry Andric } 346fe6060f1SDimitry Andric } 347349cc55cSDimitry Andric 34881ad6265SDimitry Andric Error ifs::filterIFSSyms(IFSStub &Stub, bool StripUndefined, 34981ad6265SDimitry Andric const std::vector<std::string> &Exclude) { 35081ad6265SDimitry Andric std::function<bool(const IFSSymbol &)> Filter = [](const IFSSymbol &) { 35181ad6265SDimitry Andric return false; 35281ad6265SDimitry Andric }; 35381ad6265SDimitry Andric 35481ad6265SDimitry Andric if (StripUndefined) { 35581ad6265SDimitry Andric Filter = [Filter](const IFSSymbol &Sym) { 35681ad6265SDimitry Andric return Sym.Undefined || Filter(Sym); 35781ad6265SDimitry Andric }; 358349cc55cSDimitry Andric } 35981ad6265SDimitry Andric 36081ad6265SDimitry Andric for (StringRef Glob : Exclude) { 36181ad6265SDimitry Andric Expected<llvm::GlobPattern> PatternOrErr = llvm::GlobPattern::create(Glob); 36281ad6265SDimitry Andric if (!PatternOrErr) 36381ad6265SDimitry Andric return PatternOrErr.takeError(); 36481ad6265SDimitry Andric Filter = [Pattern = *PatternOrErr, Filter](const IFSSymbol &Sym) { 36581ad6265SDimitry Andric return Pattern.match(Sym.Name) || Filter(Sym); 36681ad6265SDimitry Andric }; 367349cc55cSDimitry Andric } 36881ad6265SDimitry Andric 36981ad6265SDimitry Andric llvm::erase_if(Stub.Symbols, Filter); 37081ad6265SDimitry Andric 37181ad6265SDimitry Andric return Error::success(); 372349cc55cSDimitry Andric } 373