1 //===-- AddressResolverName.cpp ---------------------------------*- C++ -*-===// 2 // 3 // The LLVM Compiler Infrastructure 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 "lldb/Core/AddressResolverName.h" 11 12 #include "lldb/Core/Address.h" // for Address, operator== 13 #include "lldb/Core/AddressRange.h" // for AddressRange 14 #include "lldb/Core/Module.h" 15 #include "lldb/Symbol/Function.h" 16 #include "lldb/Symbol/Symbol.h" 17 #include "lldb/Symbol/SymbolContext.h" 18 #include "lldb/Utility/Log.h" 19 #include "lldb/Utility/Logging.h" // for GetLogIfAllCategoriesSet, LIB... 20 #include "lldb/Utility/Stream.h" // for Stream 21 #include "lldb/lldb-enumerations.h" // for SymbolType::eSymbolTypeCode 22 #include "lldb/lldb-forward.h" // for ModuleSP 23 #include "lldb/lldb-types.h" // for addr_t 24 #include "llvm/ADT/StringRef.h" // for StringRef 25 26 #include <memory> // for shared_ptr 27 #include <string> // for string 28 #include <vector> // for vector 29 30 #include <stdint.h> // for uint32_t 31 32 using namespace lldb; 33 using namespace lldb_private; 34 35 AddressResolverName::AddressResolverName(const char *func_name, 36 AddressResolver::MatchType type) 37 : AddressResolver(), m_func_name(func_name), m_class_name(nullptr), 38 m_regex(), m_match_type(type) { 39 if (m_match_type == AddressResolver::Regexp) { 40 if (!m_regex.Compile(m_func_name.GetStringRef())) { 41 Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_BREAKPOINTS)); 42 43 if (log) 44 log->Warning("function name regexp: \"%s\" did not compile.", 45 m_func_name.AsCString()); 46 } 47 } 48 } 49 50 AddressResolverName::AddressResolverName(RegularExpression &func_regex) 51 : AddressResolver(), m_func_name(nullptr), m_class_name(nullptr), 52 m_regex(func_regex), m_match_type(AddressResolver::Regexp) {} 53 54 AddressResolverName::AddressResolverName(const char *class_name, 55 const char *method, 56 AddressResolver::MatchType type) 57 : AddressResolver(), m_func_name(method), m_class_name(class_name), 58 m_regex(), m_match_type(type) {} 59 60 AddressResolverName::~AddressResolverName() = default; 61 62 // FIXME: Right now we look at the module level, and call the module's 63 // "FindFunctions". 64 // Greg says he will add function tables, maybe at the CompileUnit level to 65 // accelerate function 66 // lookup. At that point, we should switch the depth to CompileUnit, and look 67 // in these tables. 68 69 Searcher::CallbackReturn 70 AddressResolverName::SearchCallback(SearchFilter &filter, 71 SymbolContext &context, Address *addr, 72 bool containing) { 73 SymbolContextList func_list; 74 SymbolContextList sym_list; 75 76 bool skip_prologue = true; 77 uint32_t i; 78 SymbolContext sc; 79 Address func_addr; 80 81 Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_BREAKPOINTS)); 82 83 if (m_class_name) { 84 if (log) 85 log->Warning("Class/method function specification not supported yet.\n"); 86 return Searcher::eCallbackReturnStop; 87 } 88 89 const bool include_symbols = false; 90 const bool include_inlines = true; 91 const bool append = false; 92 switch (m_match_type) { 93 case AddressResolver::Exact: 94 if (context.module_sp) { 95 context.module_sp->FindSymbolsWithNameAndType(m_func_name, 96 eSymbolTypeCode, sym_list); 97 context.module_sp->FindFunctions(m_func_name, nullptr, 98 eFunctionNameTypeAuto, include_symbols, 99 include_inlines, append, func_list); 100 } 101 break; 102 103 case AddressResolver::Regexp: 104 if (context.module_sp) { 105 context.module_sp->FindSymbolsMatchingRegExAndType( 106 m_regex, eSymbolTypeCode, sym_list); 107 context.module_sp->FindFunctions(m_regex, include_symbols, 108 include_inlines, append, func_list); 109 } 110 break; 111 112 case AddressResolver::Glob: 113 if (log) 114 log->Warning("glob is not supported yet."); 115 break; 116 } 117 118 // Remove any duplicates between the function list and the symbol list 119 if (func_list.GetSize()) { 120 for (i = 0; i < func_list.GetSize(); i++) { 121 if (!func_list.GetContextAtIndex(i, sc)) 122 continue; 123 124 if (sc.function == nullptr) 125 continue; 126 uint32_t j = 0; 127 while (j < sym_list.GetSize()) { 128 SymbolContext symbol_sc; 129 if (sym_list.GetContextAtIndex(j, symbol_sc)) { 130 if (symbol_sc.symbol && symbol_sc.symbol->ValueIsAddress()) { 131 if (sc.function->GetAddressRange().GetBaseAddress() == 132 symbol_sc.symbol->GetAddressRef()) { 133 sym_list.RemoveContextAtIndex(j); 134 continue; // Don't increment j 135 } 136 } 137 } 138 139 j++; 140 } 141 } 142 143 for (i = 0; i < func_list.GetSize(); i++) { 144 if (func_list.GetContextAtIndex(i, sc)) { 145 if (sc.function) { 146 func_addr = sc.function->GetAddressRange().GetBaseAddress(); 147 addr_t byte_size = sc.function->GetAddressRange().GetByteSize(); 148 if (skip_prologue) { 149 const uint32_t prologue_byte_size = 150 sc.function->GetPrologueByteSize(); 151 if (prologue_byte_size) { 152 func_addr.SetOffset(func_addr.GetOffset() + prologue_byte_size); 153 byte_size -= prologue_byte_size; 154 } 155 } 156 157 if (filter.AddressPasses(func_addr)) { 158 AddressRange new_range(func_addr, byte_size); 159 m_address_ranges.push_back(new_range); 160 } 161 } 162 } 163 } 164 } 165 166 for (i = 0; i < sym_list.GetSize(); i++) { 167 if (sym_list.GetContextAtIndex(i, sc)) { 168 if (sc.symbol && sc.symbol->ValueIsAddress()) { 169 func_addr = sc.symbol->GetAddressRef(); 170 addr_t byte_size = sc.symbol->GetByteSize(); 171 172 if (skip_prologue) { 173 const uint32_t prologue_byte_size = sc.symbol->GetPrologueByteSize(); 174 if (prologue_byte_size) { 175 func_addr.SetOffset(func_addr.GetOffset() + prologue_byte_size); 176 byte_size -= prologue_byte_size; 177 } 178 } 179 180 if (filter.AddressPasses(func_addr)) { 181 AddressRange new_range(func_addr, byte_size); 182 m_address_ranges.push_back(new_range); 183 } 184 } 185 } 186 } 187 return Searcher::eCallbackReturnContinue; 188 } 189 190 Searcher::Depth AddressResolverName::GetDepth() { 191 return Searcher::eDepthModule; 192 } 193 194 void AddressResolverName::GetDescription(Stream *s) { 195 s->PutCString("Address by function name: "); 196 197 if (m_match_type == AddressResolver::Regexp) 198 s->Printf("'%s' (regular expression)", m_regex.GetText().str().c_str()); 199 else 200 s->Printf("'%s'", m_func_name.AsCString()); 201 } 202