diff options
Diffstat (limited to 'gnu/llvm/tools/lld/ELF/Strings.cpp')
| -rw-r--r-- | gnu/llvm/tools/lld/ELF/Strings.cpp | 98 |
1 files changed, 98 insertions, 0 deletions
diff --git a/gnu/llvm/tools/lld/ELF/Strings.cpp b/gnu/llvm/tools/lld/ELF/Strings.cpp new file mode 100644 index 00000000000..0c21e8819d6 --- /dev/null +++ b/gnu/llvm/tools/lld/ELF/Strings.cpp @@ -0,0 +1,98 @@ +//===- Strings.cpp -------------------------------------------------------===// +// +// The LLVM Linker +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "Strings.h" +#include "Error.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/ADT/Twine.h" +#include "llvm/Config/config.h" +#include <algorithm> + +#ifdef HAVE_CXXABI_H +#include <cxxabi.h> +#endif + +using namespace llvm; +using namespace lld; +using namespace lld::elf; + +// Returns true if S matches T. S can contain glob meta-characters. +// The asterisk ('*') matches zero or more characters, and the question +// mark ('?') matches one character. +bool elf::globMatch(StringRef S, StringRef T) { + for (;;) { + if (S.empty()) + return T.empty(); + if (S[0] == '*') { + S = S.substr(1); + if (S.empty()) + // Fast path. If a pattern is '*', it matches anything. + return true; + for (size_t I = 0, E = T.size(); I < E; ++I) + if (globMatch(S, T.substr(I))) + return true; + return false; + } + if (T.empty() || (S[0] != T[0] && S[0] != '?')) + return false; + S = S.substr(1); + T = T.substr(1); + } +} + +// Converts a hex string (e.g. "deadbeef") to a vector. +std::vector<uint8_t> elf::parseHex(StringRef S) { + std::vector<uint8_t> Hex; + while (!S.empty()) { + StringRef B = S.substr(0, 2); + S = S.substr(2); + uint8_t H; + if (B.getAsInteger(16, H)) { + error("not a hexadecimal value: " + B); + return {}; + } + Hex.push_back(H); + } + return Hex; +} + +static bool isAlpha(char C) { + return ('a' <= C && C <= 'z') || ('A' <= C && C <= 'Z') || C == '_'; +} + +static bool isAlnum(char C) { return isAlpha(C) || ('0' <= C && C <= '9'); } + +// Returns true if S is valid as a C language identifier. +bool elf::isValidCIdentifier(StringRef S) { + return !S.empty() && isAlpha(S[0]) && + std::all_of(S.begin() + 1, S.end(), isAlnum); +} + +// Returns the demangled C++ symbol name for Name. +std::string elf::demangle(StringRef Name) { +#if !defined(HAVE_CXXABI_H) + return Name; +#else + // __cxa_demangle can be used to demangle strings other than symbol + // names which do not necessarily start with "_Z". Name can be + // either a C or C++ symbol. Don't call __cxa_demangle if the name + // does not look like a C++ symbol name to avoid getting unexpected + // result for a C symbol that happens to match a mangled type name. + if (!Name.startswith("_Z")) + return Name; + + char *Buf = + abi::__cxa_demangle(Name.str().c_str(), nullptr, nullptr, nullptr); + if (!Buf) + return Name; + std::string S(Buf); + free(Buf); + return S; +#endif +} |
