]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/tools/lld/ELF/Strings.cpp
Merge ^/head r308227 through r308490.
[FreeBSD/FreeBSD.git] / contrib / llvm / tools / lld / ELF / Strings.cpp
1 //===- Strings.cpp -------------------------------------------------------===//
2 //
3 //                             The LLVM Linker
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9
10 #include "Strings.h"
11 #include "Error.h"
12 #include "llvm/ADT/StringRef.h"
13 #include "llvm/ADT/Twine.h"
14 #include "llvm/Config/config.h"
15 #include <algorithm>
16
17 #ifdef HAVE_CXXABI_H
18 #include <cxxabi.h>
19 #endif
20
21 using namespace llvm;
22 using namespace lld;
23 using namespace lld::elf;
24
25 // Returns true if S matches T. S can contain glob meta-characters.
26 // The asterisk ('*') matches zero or more characters, and the question
27 // mark ('?') matches one character.
28 bool elf::globMatch(StringRef S, StringRef T) {
29   for (;;) {
30     if (S.empty())
31       return T.empty();
32     if (S[0] == '*') {
33       S = S.substr(1);
34       if (S.empty())
35         // Fast path. If a pattern is '*', it matches anything.
36         return true;
37       for (size_t I = 0, E = T.size(); I < E; ++I)
38         if (globMatch(S, T.substr(I)))
39           return true;
40       return false;
41     }
42     if (T.empty() || (S[0] != T[0] && S[0] != '?'))
43       return false;
44     S = S.substr(1);
45     T = T.substr(1);
46   }
47 }
48
49 // Converts a hex string (e.g. "deadbeef") to a vector.
50 std::vector<uint8_t> elf::parseHex(StringRef S) {
51   std::vector<uint8_t> Hex;
52   while (!S.empty()) {
53     StringRef B = S.substr(0, 2);
54     S = S.substr(2);
55     uint8_t H;
56     if (B.getAsInteger(16, H)) {
57       error("not a hexadecimal value: " + B);
58       return {};
59     }
60     Hex.push_back(H);
61   }
62   return Hex;
63 }
64
65 static bool isAlpha(char C) {
66   return ('a' <= C && C <= 'z') || ('A' <= C && C <= 'Z') || C == '_';
67 }
68
69 static bool isAlnum(char C) { return isAlpha(C) || ('0' <= C && C <= '9'); }
70
71 // Returns true if S is valid as a C language identifier.
72 bool elf::isValidCIdentifier(StringRef S) {
73   return !S.empty() && isAlpha(S[0]) &&
74          std::all_of(S.begin() + 1, S.end(), isAlnum);
75 }
76
77 // Returns the demangled C++ symbol name for Name.
78 std::string elf::demangle(StringRef Name) {
79 #if !defined(HAVE_CXXABI_H)
80   return Name;
81 #else
82   // __cxa_demangle can be used to demangle strings other than symbol
83   // names which do not necessarily start with "_Z". Name can be
84   // either a C or C++ symbol. Don't call __cxa_demangle if the name
85   // does not look like a C++ symbol name to avoid getting unexpected
86   // result for a C symbol that happens to match a mangled type name.
87   if (!Name.startswith("_Z"))
88     return Name;
89
90   char *Buf =
91       abi::__cxa_demangle(Name.str().c_str(), nullptr, nullptr, nullptr);
92   if (!Buf)
93     return Name;
94   std::string S(Buf);
95   free(Buf);
96   return S;
97 #endif
98 }