summaryrefslogtreecommitdiffstats
path: root/gnu/llvm/tools/lld/ELF/Strings.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'gnu/llvm/tools/lld/ELF/Strings.cpp')
-rw-r--r--gnu/llvm/tools/lld/ELF/Strings.cpp98
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
+}