Rui Ueyama | 53fe469 | 2017-11-28 02:15:26 +0000 | [diff] [blame] | 1 | //===- Strings.cpp -------------------------------------------------------===// |
| 2 | // |
Chandler Carruth | 2946cd7 | 2019-01-19 08:50:56 +0000 | [diff] [blame^] | 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 |
Rui Ueyama | 53fe469 | 2017-11-28 02:15:26 +0000 | [diff] [blame] | 6 | // |
| 7 | //===----------------------------------------------------------------------===// |
| 8 | |
| 9 | #include "lld/Common/Strings.h" |
Rui Ueyama | ee17371 | 2018-02-28 17:38:19 +0000 | [diff] [blame] | 10 | #include "lld/Common/ErrorHandler.h" |
| 11 | #include "lld/Common/LLVM.h" |
Rui Ueyama | 53fe469 | 2017-11-28 02:15:26 +0000 | [diff] [blame] | 12 | #include "llvm/Demangle/Demangle.h" |
Rui Ueyama | ee17371 | 2018-02-28 17:38:19 +0000 | [diff] [blame] | 13 | #include "llvm/Support/GlobPattern.h" |
| 14 | #include <algorithm> |
| 15 | #include <mutex> |
| 16 | #include <vector> |
| 17 | |
Rui Ueyama | 53fe469 | 2017-11-28 02:15:26 +0000 | [diff] [blame] | 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 | } |
Rui Ueyama | ee17371 | 2018-02-28 17:38:19 +0000 | [diff] [blame] | 38 | |
Nico Weber | da15acb | 2018-09-15 18:27:09 +0000 | [diff] [blame] | 39 | Optional<std::string> lld::demangleMSVC(StringRef Name) { |
Nico Weber | 5ffd8ce | 2018-09-17 16:31:20 +0000 | [diff] [blame] | 40 | std::string Prefix; |
| 41 | if (Name.consume_front("__imp_")) |
| 42 | Prefix = "__declspec(dllimport) "; |
| 43 | |
| 44 | // Demangle only C++ names. |
Nico Weber | da15acb | 2018-09-15 18:27:09 +0000 | [diff] [blame] | 45 | if (!Name.startswith("?")) |
| 46 | return None; |
Nico Weber | 5ffd8ce | 2018-09-17 16:31:20 +0000 | [diff] [blame] | 47 | |
Nico Weber | da15acb | 2018-09-15 18:27:09 +0000 | [diff] [blame] | 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); |
Nico Weber | 5ffd8ce | 2018-09-17 16:31:20 +0000 | [diff] [blame] | 53 | return Prefix + S; |
Rui Ueyama | ee17371 | 2018-02-28 17:38:19 +0000 | [diff] [blame] | 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 | } |
Sam Clegg | 3ad27e9 | 2018-05-22 20:20:25 +0000 | [diff] [blame] | 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 | } |