1 // Copyright (C) 2019 The Android Open Source Project
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //      http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #include "repr/symbol/exported_symbol_set.h"
16 
17 #include "repr/ir_representation.h"
18 #include "utils/stl_utils.h"
19 #include "utils/string_utils.h"
20 
21 #include <fnmatch.h>
22 #include <cxxabi.h>
23 
24 
25 namespace header_checker {
26 namespace repr {
27 
28 
IsCppSymbol(const std::string & name)29 static inline bool IsCppSymbol(const std::string &name) {
30   return utils::StartsWith(name, "_Z");
31 }
32 
33 
HasMatchingGlobPattern(const ExportedSymbolSet::GlobPatternSet & patterns,const char * text)34 static inline bool HasMatchingGlobPattern(
35     const ExportedSymbolSet::GlobPatternSet &patterns, const char *text) {
36   for (auto &&pattern : patterns) {
37     if (fnmatch(pattern.c_str(), text, 0) == 0) {
38       return true;
39     }
40   }
41   return false;
42 }
43 
44 
HasMatchingGlobPattern(const ExportedSymbolSet::GlobPatternSet & patterns,const std::string & text)45 static inline bool HasMatchingGlobPattern(
46     const ExportedSymbolSet::GlobPatternSet &patterns,
47     const std::string &text) {
48   return HasMatchingGlobPattern(patterns, text.c_str());
49 }
50 
51 
AddFunction(const std::string & name,ElfSymbolIR::ElfSymbolBinding binding)52 void ExportedSymbolSet::AddFunction(const std::string &name,
53                                     ElfSymbolIR::ElfSymbolBinding binding) {
54   funcs_.emplace(name, ElfFunctionIR(name, binding));
55 }
56 
57 
AddVar(const std::string & name,ElfSymbolIR::ElfSymbolBinding binding)58 void ExportedSymbolSet::AddVar(const std::string &name,
59                                ElfSymbolIR::ElfSymbolBinding binding) {
60   vars_.emplace(name, ElfObjectIR(name, binding));
61 }
62 
63 
HasSymbol(const std::string & name) const64 bool ExportedSymbolSet::HasSymbol(const std::string &name) const {
65   if (funcs_.find(name) != funcs_.end()) {
66     return true;
67   }
68 
69   if (vars_.find(name) != vars_.end()) {
70     return true;
71   }
72 
73   if (HasMatchingGlobPattern(glob_patterns_, name)) {
74     return true;
75   }
76 
77   if (IsCppSymbol(name) && HasDemangledCppSymbolsOrPatterns()) {
78     std::unique_ptr<char, utils::FreeDeleter> demangled_name_c_str(
79         abi::__cxa_demangle(name.c_str(), nullptr, nullptr, nullptr));
80 
81     if (demangled_name_c_str) {
82       std::string_view demangled_name(demangled_name_c_str.get());
83 
84       if (demangled_cpp_symbols_.find(demangled_name) !=
85           demangled_cpp_symbols_.end()) {
86         return true;
87       }
88 
89       if (HasMatchingGlobPattern(demangled_cpp_glob_patterns_,
90                                  demangled_name_c_str.get())) {
91         return true;
92       }
93     }
94   }
95 
96   return false;
97 }
98 
99 
100 }  // namespace repr
101 }  // namespace header_checker
102