1 //===- Strings.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 "lld/Common/Strings.h" 10 #include "lld/Common/ErrorHandler.h" 11 #include "lld/Common/LLVM.h" 12 #include "llvm/Demangle/Demangle.h" 13 #include "llvm/Support/GlobPattern.h" 14 #include <algorithm> 15 #include <mutex> 16 #include <vector> 17 18 using namespace llvm; 19 using namespace lld; 20 21 // Returns the demangled C++ symbol name for Name. 22 Optional<std::string> lld::demangleItanium(StringRef Name) { 23 // itaniumDemangle can be used to demangle strings other than symbol 24 // names which do not necessarily start with "_Z". Name can be 25 // either a C or C++ symbol. Don't call itaniumDemangle if the name 26 // does not look like a C++ symbol name to avoid getting unexpected 27 // result for a C symbol that happens to match a mangled type name. 28 if (!Name.startswith("_Z")) 29 return None; 30 31 char *Buf = itaniumDemangle(Name.str().c_str(), nullptr, nullptr, nullptr); 32 if (!Buf) 33 return None; 34 std::string S(Buf); 35 free(Buf); 36 return S; 37 } 38 39 Optional<std::string> lld::demangleMSVC(StringRef Name) { 40 std::string Prefix; 41 if (Name.consume_front("__imp_")) 42 Prefix = "__declspec(dllimport) "; 43 44 // Demangle only C++ names. 45 if (!Name.startswith("?")) 46 return None; 47 48 char *Buf = microsoftDemangle(Name.str().c_str(), nullptr, nullptr, nullptr); 49 if (!Buf) 50 return None; 51 std::string S(Buf); 52 free(Buf); 53 return Prefix + S; 54 } 55 56 StringMatcher::StringMatcher(ArrayRef<StringRef> Pat) { 57 for (StringRef S : Pat) { 58 Expected<GlobPattern> Pat = GlobPattern::create(S); 59 if (!Pat) 60 error(toString(Pat.takeError())); 61 else 62 Patterns.push_back(*Pat); 63 } 64 } 65 66 bool StringMatcher::match(StringRef S) const { 67 for (const GlobPattern &Pat : Patterns) 68 if (Pat.match(S)) 69 return true; 70 return false; 71 } 72 73 // Converts a hex string (e.g. "deadbeef") to a vector. 74 std::vector<uint8_t> lld::parseHex(StringRef S) { 75 std::vector<uint8_t> Hex; 76 while (!S.empty()) { 77 StringRef B = S.substr(0, 2); 78 S = S.substr(2); 79 uint8_t H; 80 if (!to_integer(B, H, 16)) { 81 error("not a hexadecimal value: " + B); 82 return {}; 83 } 84 Hex.push_back(H); 85 } 86 return Hex; 87 } 88 89 // Returns true if S is valid as a C language identifier. 90 bool lld::isValidCIdentifier(StringRef S) { 91 return !S.empty() && (isAlpha(S[0]) || S[0] == '_') && 92 std::all_of(S.begin() + 1, S.end(), 93 [](char C) { return C == '_' || isAlnum(C); }); 94 } 95 96 // Write the contents of the a buffer to a file 97 void lld::saveBuffer(StringRef Buffer, const Twine &Path) { 98 std::error_code EC; 99 raw_fd_ostream OS(Path.str(), EC, sys::fs::OpenFlags::F_None); 100 if (EC) 101 error("cannot create " + Path + ": " + EC.message()); 102 OS << Buffer; 103 } 104