/Users/buildslave/jenkins/workspace/coverage/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/IRForTarget.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | //===-- IRForTarget.cpp ---------------------------------------------------===// |
2 | | // |
3 | | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
4 | | // See https://llvm.org/LICENSE.txt for license information. |
5 | | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
6 | | // |
7 | | //===----------------------------------------------------------------------===// |
8 | | |
9 | | #include "IRForTarget.h" |
10 | | |
11 | | #include "ClangExpressionDeclMap.h" |
12 | | #include "ClangUtil.h" |
13 | | |
14 | | #include "Plugins/TypeSystem/Clang/TypeSystemClang.h" |
15 | | #include "llvm/IR/Constants.h" |
16 | | #include "llvm/IR/DataLayout.h" |
17 | | #include "llvm/IR/Operator.h" |
18 | | #include "llvm/IR/InstrTypes.h" |
19 | | #include "llvm/IR/Instructions.h" |
20 | | #include "llvm/IR/Intrinsics.h" |
21 | | #include "llvm/IR/LegacyPassManager.h" |
22 | | #include "llvm/IR/Metadata.h" |
23 | | #include "llvm/IR/Module.h" |
24 | | #include "llvm/IR/ValueSymbolTable.h" |
25 | | #include "llvm/Support/raw_ostream.h" |
26 | | #include "llvm/Transforms/IPO.h" |
27 | | |
28 | | #include "clang/AST/ASTContext.h" |
29 | | |
30 | | #include "lldb/Core/dwarf.h" |
31 | | #include "lldb/Expression/IRExecutionUnit.h" |
32 | | #include "lldb/Expression/IRInterpreter.h" |
33 | | #include "lldb/Symbol/CompilerType.h" |
34 | | #include "lldb/Utility/ConstString.h" |
35 | | #include "lldb/Utility/DataBufferHeap.h" |
36 | | #include "lldb/Utility/Endian.h" |
37 | | #include "lldb/Utility/LLDBLog.h" |
38 | | #include "lldb/Utility/Log.h" |
39 | | #include "lldb/Utility/Scalar.h" |
40 | | #include "lldb/Utility/StreamString.h" |
41 | | |
42 | | #include <map> |
43 | | #include <optional> |
44 | | |
45 | | using namespace llvm; |
46 | | using lldb_private::LLDBLog; |
47 | | |
48 | | typedef SmallVector<Instruction *, 2> InstrList; |
49 | | |
50 | | IRForTarget::FunctionValueCache::FunctionValueCache(Maker const &maker) |
51 | 22.5k | : m_maker(maker), m_values() {} |
52 | | |
53 | 22.5k | IRForTarget::FunctionValueCache::~FunctionValueCache() = default; |
54 | | |
55 | | llvm::Value * |
56 | 25.9k | IRForTarget::FunctionValueCache::GetValue(llvm::Function *function) { |
57 | 25.9k | if (!m_values.count(function)) { |
58 | 19.7k | llvm::Value *ret = m_maker(function); |
59 | 19.7k | m_values[function] = ret; |
60 | 19.7k | return ret; |
61 | 19.7k | } |
62 | 6.12k | return m_values[function]; |
63 | 25.9k | } |
64 | | |
65 | 6.86k | static llvm::Value *FindEntryInstruction(llvm::Function *function) { |
66 | 6.86k | if (function->empty()) |
67 | 0 | return nullptr; |
68 | | |
69 | 6.86k | return function->getEntryBlock().getFirstNonPHIOrDbg(); |
70 | 6.86k | } |
71 | | |
72 | | IRForTarget::IRForTarget(lldb_private::ClangExpressionDeclMap *decl_map, |
73 | | bool resolve_vars, |
74 | | lldb_private::IRExecutionUnit &execution_unit, |
75 | | lldb_private::Stream &error_stream, |
76 | | const char *func_name) |
77 | 9.61k | : m_resolve_vars(resolve_vars), m_func_name(func_name), |
78 | 9.61k | m_decl_map(decl_map), m_error_stream(error_stream), |
79 | 9.61k | m_execution_unit(execution_unit), |
80 | 9.61k | m_entry_instruction_finder(FindEntryInstruction) {} |
81 | | |
82 | | /* Handy utility functions used at several places in the code */ |
83 | | |
84 | 1.90k | static std::string PrintValue(const Value *value, bool truncate = false) { |
85 | 1.90k | std::string s; |
86 | 1.90k | if (value) { |
87 | 1.90k | raw_string_ostream rso(s); |
88 | 1.90k | value->print(rso); |
89 | 1.90k | rso.flush(); |
90 | 1.90k | if (truncate) |
91 | 0 | s.resize(s.length() - 1); |
92 | 1.90k | } |
93 | 1.90k | return s; |
94 | 1.90k | } |
95 | | |
96 | 30 | static std::string PrintType(const llvm::Type *type, bool truncate = false) { |
97 | 30 | std::string s; |
98 | 30 | raw_string_ostream rso(s); |
99 | 30 | type->print(rso); |
100 | 30 | rso.flush(); |
101 | 30 | if (truncate) |
102 | 0 | s.resize(s.length() - 1); |
103 | 30 | return s; |
104 | 30 | } |
105 | | |
106 | 9.57k | bool IRForTarget::FixFunctionLinkage(llvm::Function &llvm_function) { |
107 | 9.57k | llvm_function.setLinkage(GlobalValue::ExternalLinkage); |
108 | | |
109 | 9.57k | return true; |
110 | 9.57k | } |
111 | | |
112 | | clang::NamedDecl *IRForTarget::DeclForGlobal(const GlobalValue *global_val, |
113 | 84.9k | Module *module) { |
114 | 84.9k | NamedMDNode *named_metadata = |
115 | 84.9k | module->getNamedMetadata("clang.global.decl.ptrs"); |
116 | | |
117 | 84.9k | if (!named_metadata) |
118 | 0 | return nullptr; |
119 | | |
120 | 84.9k | unsigned num_nodes = named_metadata->getNumOperands(); |
121 | 84.9k | unsigned node_index; |
122 | | |
123 | 348k | for (node_index = 0; node_index < num_nodes; ++node_index263k ) { |
124 | 297k | llvm::MDNode *metadata_node = |
125 | 297k | dyn_cast<llvm::MDNode>(named_metadata->getOperand(node_index)); |
126 | 297k | if (!metadata_node) |
127 | 0 | return nullptr; |
128 | | |
129 | 297k | if (metadata_node->getNumOperands() != 2) |
130 | 0 | continue; |
131 | | |
132 | 297k | if (mdconst::dyn_extract_or_null<GlobalValue>( |
133 | 297k | metadata_node->getOperand(0)) != global_val) |
134 | 263k | continue; |
135 | | |
136 | 34.5k | ConstantInt *constant_int = |
137 | 34.5k | mdconst::dyn_extract<ConstantInt>(metadata_node->getOperand(1)); |
138 | | |
139 | 34.5k | if (!constant_int) |
140 | 0 | return nullptr; |
141 | | |
142 | 34.5k | uintptr_t ptr = constant_int->getZExtValue(); |
143 | | |
144 | 34.5k | return reinterpret_cast<clang::NamedDecl *>(ptr); |
145 | 34.5k | } |
146 | | |
147 | 50.3k | return nullptr; |
148 | 84.9k | } |
149 | | |
150 | 84.9k | clang::NamedDecl *IRForTarget::DeclForGlobal(GlobalValue *global_val) { |
151 | 84.9k | return DeclForGlobal(global_val, m_module); |
152 | 84.9k | } |
153 | | |
154 | | /// Returns true iff the mangled symbol is for a static guard variable. |
155 | | static bool isGuardVariableSymbol(llvm::StringRef mangled_symbol, |
156 | 47.8k | bool check_ms_abi = true) { |
157 | 47.8k | bool result = mangled_symbol.startswith("_ZGV"); // Itanium ABI guard variable |
158 | 47.8k | if (check_ms_abi) |
159 | 30.1k | result |= mangled_symbol.endswith("@4IA"); // Microsoft ABI |
160 | 47.8k | return result; |
161 | 47.8k | } |
162 | | |
163 | 9.57k | bool IRForTarget::CreateResultVariable(llvm::Function &llvm_function) { |
164 | 9.57k | lldb_private::Log *log(GetLog(LLDBLog::Expressions)); |
165 | | |
166 | 9.57k | if (!m_resolve_vars) |
167 | 2.66k | return true; |
168 | | |
169 | | // Find the result variable. If it doesn't exist, we can give up right here. |
170 | | |
171 | 6.91k | ValueSymbolTable &value_symbol_table = m_module->getValueSymbolTable(); |
172 | | |
173 | 6.91k | llvm::StringRef result_name; |
174 | 6.91k | bool found_result = false; |
175 | | |
176 | 17.6k | for (StringMapEntry<llvm::Value *> &value_symbol : value_symbol_table) { |
177 | 17.6k | result_name = value_symbol.first(); |
178 | | |
179 | | // Check if this is a guard variable. It seems this causes some hiccups |
180 | | // on Windows, so let's only check for Itanium guard variables. |
181 | 17.6k | bool is_guard_var = isGuardVariableSymbol(result_name, /*MS ABI*/ false); |
182 | | |
183 | 17.6k | if (result_name.contains("$__lldb_expr_result_ptr") && !is_guard_var5.17k ) { |
184 | 5.10k | found_result = true; |
185 | 5.10k | m_result_is_pointer = true; |
186 | 5.10k | break; |
187 | 5.10k | } |
188 | | |
189 | 12.5k | if (result_name.contains("$__lldb_expr_result") && !is_guard_var3.04k ) { |
190 | 1.69k | found_result = true; |
191 | 1.69k | m_result_is_pointer = false; |
192 | 1.69k | break; |
193 | 1.69k | } |
194 | 12.5k | } |
195 | | |
196 | 6.91k | if (!found_result) { |
197 | 105 | LLDB_LOG(log, "Couldn't find result variable"); |
198 | | |
199 | 105 | return true; |
200 | 105 | } |
201 | | |
202 | 6.80k | LLDB_LOG(log, "Result name: \"{0}\"", result_name); |
203 | | |
204 | 6.80k | Value *result_value = m_module->getNamedValue(result_name); |
205 | | |
206 | 6.80k | if (!result_value) { |
207 | 0 | LLDB_LOG(log, "Result variable had no data"); |
208 | |
|
209 | 0 | m_error_stream.Format("Internal error [IRForTarget]: Result variable's " |
210 | 0 | "name ({0}) exists, but not its definition\n", |
211 | 0 | result_name); |
212 | |
|
213 | 0 | return false; |
214 | 0 | } |
215 | | |
216 | 6.80k | LLDB_LOG(log, "Found result in the IR: \"{0}\"", |
217 | 6.80k | PrintValue(result_value, false)); |
218 | | |
219 | 6.80k | GlobalVariable *result_global = dyn_cast<GlobalVariable>(result_value); |
220 | | |
221 | 6.80k | if (!result_global) { |
222 | 0 | LLDB_LOG(log, "Result variable isn't a GlobalVariable"); |
223 | |
|
224 | 0 | m_error_stream.Format("Internal error [IRForTarget]: Result variable ({0}) " |
225 | 0 | "is defined, but is not a global variable\n", |
226 | 0 | result_name); |
227 | |
|
228 | 0 | return false; |
229 | 0 | } |
230 | | |
231 | 6.80k | clang::NamedDecl *result_decl = DeclForGlobal(result_global); |
232 | 6.80k | if (!result_decl) { |
233 | 0 | LLDB_LOG(log, "Result variable doesn't have a corresponding Decl"); |
234 | |
|
235 | 0 | m_error_stream.Format("Internal error [IRForTarget]: Result variable ({0}) " |
236 | 0 | "does not have a corresponding Clang entity\n", |
237 | 0 | result_name); |
238 | |
|
239 | 0 | return false; |
240 | 0 | } |
241 | | |
242 | 6.80k | if (log) { |
243 | 12 | std::string decl_desc_str; |
244 | 12 | raw_string_ostream decl_desc_stream(decl_desc_str); |
245 | 12 | result_decl->print(decl_desc_stream); |
246 | 12 | decl_desc_stream.flush(); |
247 | | |
248 | 12 | LLDB_LOG(log, "Found result decl: \"{0}\"", decl_desc_str); |
249 | 12 | } |
250 | | |
251 | 6.80k | clang::VarDecl *result_var = dyn_cast<clang::VarDecl>(result_decl); |
252 | 6.80k | if (!result_var) { |
253 | 0 | LLDB_LOG(log, "Result variable Decl isn't a VarDecl"); |
254 | |
|
255 | 0 | m_error_stream.Format("Internal error [IRForTarget]: Result variable " |
256 | 0 | "({0})'s corresponding Clang entity isn't a " |
257 | 0 | "variable\n", |
258 | 0 | result_name); |
259 | |
|
260 | 0 | return false; |
261 | 0 | } |
262 | | |
263 | | // Get the next available result name from m_decl_map and create the |
264 | | // persistent variable for it |
265 | | |
266 | | // If the result is an Lvalue, it is emitted as a pointer; see |
267 | | // ASTResultSynthesizer::SynthesizeBodyResult. |
268 | 6.80k | if (m_result_is_pointer) { |
269 | 5.10k | clang::QualType pointer_qual_type = result_var->getType(); |
270 | 5.10k | const clang::Type *pointer_type = pointer_qual_type.getTypePtr(); |
271 | | |
272 | 5.10k | const clang::PointerType *pointer_pointertype = |
273 | 5.10k | pointer_type->getAs<clang::PointerType>(); |
274 | 5.10k | const clang::ObjCObjectPointerType *pointer_objcobjpointertype = |
275 | 5.10k | pointer_type->getAs<clang::ObjCObjectPointerType>(); |
276 | | |
277 | 5.10k | if (pointer_pointertype) { |
278 | 5.09k | clang::QualType element_qual_type = pointer_pointertype->getPointeeType(); |
279 | | |
280 | 5.09k | m_result_type = lldb_private::TypeFromParser( |
281 | 5.09k | m_decl_map->GetTypeSystem()->GetType(element_qual_type)); |
282 | 5.09k | } else if (18 pointer_objcobjpointertype18 ) { |
283 | 18 | clang::QualType element_qual_type = |
284 | 18 | clang::QualType(pointer_objcobjpointertype->getObjectType(), 0); |
285 | | |
286 | 18 | m_result_type = lldb_private::TypeFromParser( |
287 | 18 | m_decl_map->GetTypeSystem()->GetType(element_qual_type)); |
288 | 18 | } else { |
289 | 0 | LLDB_LOG(log, "Expected result to have pointer type, but it did not"); |
290 | |
|
291 | 0 | m_error_stream.Format("Internal error [IRForTarget]: Lvalue result ({0}) " |
292 | 0 | "is not a pointer variable\n", |
293 | 0 | result_name); |
294 | |
|
295 | 0 | return false; |
296 | 0 | } |
297 | 5.10k | } else { |
298 | 1.69k | m_result_type = lldb_private::TypeFromParser( |
299 | 1.69k | m_decl_map->GetTypeSystem()->GetType(result_var->getType())); |
300 | 1.69k | } |
301 | | |
302 | 6.80k | lldb::TargetSP target_sp(m_execution_unit.GetTarget()); |
303 | 6.80k | std::optional<uint64_t> bit_size = m_result_type.GetBitSize(target_sp.get()); |
304 | 6.80k | if (!bit_size) { |
305 | 0 | lldb_private::StreamString type_desc_stream; |
306 | 0 | m_result_type.DumpTypeDescription(&type_desc_stream); |
307 | |
|
308 | 0 | LLDB_LOG(log, "Result type has unknown size"); |
309 | |
|
310 | 0 | m_error_stream.Printf("Error [IRForTarget]: Size of result type '%s' " |
311 | 0 | "couldn't be determined\n", |
312 | 0 | type_desc_stream.GetData()); |
313 | 0 | return false; |
314 | 0 | } |
315 | | |
316 | 6.80k | if (log) { |
317 | 12 | lldb_private::StreamString type_desc_stream; |
318 | 12 | m_result_type.DumpTypeDescription(&type_desc_stream); |
319 | | |
320 | 12 | LLDB_LOG(log, "Result decl type: \"{0}\"", type_desc_stream.GetData()); |
321 | 12 | } |
322 | | |
323 | 6.80k | m_result_name = lldb_private::ConstString("$RESULT_NAME"); |
324 | | |
325 | 6.80k | LLDB_LOG(log, "Creating a new result global: \"{0}\" with size {1}", |
326 | 6.80k | m_result_name, |
327 | 6.80k | m_result_type.GetByteSize(target_sp.get()).value_or(0)); |
328 | | |
329 | | // Construct a new result global and set up its metadata |
330 | | |
331 | 6.80k | GlobalVariable *new_result_global = new GlobalVariable( |
332 | 6.80k | (*m_module), result_global->getValueType(), false, /* not constant */ |
333 | 6.80k | GlobalValue::ExternalLinkage, nullptr, /* no initializer */ |
334 | 6.80k | m_result_name.GetCString()); |
335 | | |
336 | | // It's too late in compilation to create a new VarDecl for this, but we |
337 | | // don't need to. We point the metadata at the old VarDecl. This creates an |
338 | | // odd anomaly: a variable with a Value whose name is something like $0 and a |
339 | | // Decl whose name is $__lldb_expr_result. This condition is handled in |
340 | | // ClangExpressionDeclMap::DoMaterialize, and the name of the variable is |
341 | | // fixed up. |
342 | | |
343 | 6.80k | ConstantInt *new_constant_int = |
344 | 6.80k | ConstantInt::get(llvm::Type::getInt64Ty(m_module->getContext()), |
345 | 6.80k | reinterpret_cast<uintptr_t>(result_decl), false); |
346 | | |
347 | 6.80k | llvm::Metadata *values[2]; |
348 | 6.80k | values[0] = ConstantAsMetadata::get(new_result_global); |
349 | 6.80k | values[1] = ConstantAsMetadata::get(new_constant_int); |
350 | | |
351 | 6.80k | ArrayRef<Metadata *> value_ref(values, 2); |
352 | | |
353 | 6.80k | MDNode *persistent_global_md = MDNode::get(m_module->getContext(), value_ref); |
354 | 6.80k | NamedMDNode *named_metadata = |
355 | 6.80k | m_module->getNamedMetadata("clang.global.decl.ptrs"); |
356 | 6.80k | named_metadata->addOperand(persistent_global_md); |
357 | | |
358 | 6.80k | LLDB_LOG(log, "Replacing \"{0}\" with \"{1}\"", PrintValue(result_global), |
359 | 6.80k | PrintValue(new_result_global)); |
360 | | |
361 | 6.80k | if (result_global->use_empty()) { |
362 | | // We need to synthesize a store for this variable, because otherwise |
363 | | // there's nothing to put into its equivalent persistent variable. |
364 | | |
365 | 405 | BasicBlock &entry_block(llvm_function.getEntryBlock()); |
366 | 405 | Instruction *first_entry_instruction(entry_block.getFirstNonPHIOrDbg()); |
367 | | |
368 | 405 | if (!first_entry_instruction) |
369 | 0 | return false; |
370 | | |
371 | 405 | if (!result_global->hasInitializer()) { |
372 | 0 | LLDB_LOG(log, "Couldn't find initializer for unused variable"); |
373 | |
|
374 | 0 | m_error_stream.Format("Internal error [IRForTarget]: Result variable " |
375 | 0 | "({0}) has no writes and no initializer\n", |
376 | 0 | result_name); |
377 | |
|
378 | 0 | return false; |
379 | 0 | } |
380 | | |
381 | 405 | Constant *initializer = result_global->getInitializer(); |
382 | | |
383 | 405 | StoreInst *synthesized_store = |
384 | 405 | new StoreInst(initializer, new_result_global, first_entry_instruction); |
385 | | |
386 | 405 | LLDB_LOG(log, "Synthesized result store \"{0}\"\n", |
387 | 405 | PrintValue(synthesized_store)); |
388 | 6.40k | } else { |
389 | 6.40k | result_global->replaceAllUsesWith(new_result_global); |
390 | 6.40k | } |
391 | | |
392 | 6.80k | if (!m_decl_map->AddPersistentVariable( |
393 | 6.80k | result_decl, m_result_name, m_result_type, true, m_result_is_pointer)) |
394 | 0 | return false; |
395 | | |
396 | 6.80k | result_global->eraseFromParent(); |
397 | | |
398 | 6.80k | return true; |
399 | 6.80k | } |
400 | | |
401 | | bool IRForTarget::RewriteObjCConstString(llvm::GlobalVariable *ns_str, |
402 | 60 | llvm::GlobalVariable *cstr) { |
403 | 60 | lldb_private::Log *log(GetLog(LLDBLog::Expressions)); |
404 | | |
405 | 60 | Type *ns_str_ty = ns_str->getType(); |
406 | | |
407 | 60 | Type *i8_ptr_ty = Type::getInt8PtrTy(m_module->getContext()); |
408 | 60 | Type *i32_ty = Type::getInt32Ty(m_module->getContext()); |
409 | 60 | Type *i8_ty = Type::getInt8Ty(m_module->getContext()); |
410 | | |
411 | 60 | if (!m_CFStringCreateWithBytes) { |
412 | 48 | lldb::addr_t CFStringCreateWithBytes_addr; |
413 | | |
414 | 48 | static lldb_private::ConstString g_CFStringCreateWithBytes_str( |
415 | 48 | "CFStringCreateWithBytes"); |
416 | | |
417 | 48 | bool missing_weak = false; |
418 | 48 | CFStringCreateWithBytes_addr = |
419 | 48 | m_execution_unit.FindSymbol(g_CFStringCreateWithBytes_str, |
420 | 48 | missing_weak); |
421 | 48 | if (CFStringCreateWithBytes_addr == LLDB_INVALID_ADDRESS || missing_weak46 ) { |
422 | 2 | LLDB_LOG(log, "Couldn't find CFStringCreateWithBytes in the target"); |
423 | | |
424 | 2 | m_error_stream.Printf("Error [IRForTarget]: Rewriting an Objective-C " |
425 | 2 | "constant string requires " |
426 | 2 | "CFStringCreateWithBytes\n"); |
427 | | |
428 | 2 | return false; |
429 | 2 | } |
430 | | |
431 | 46 | LLDB_LOG(log, "Found CFStringCreateWithBytes at {0}", |
432 | 46 | CFStringCreateWithBytes_addr); |
433 | | |
434 | | // Build the function type: |
435 | | // |
436 | | // CFStringRef CFStringCreateWithBytes ( |
437 | | // CFAllocatorRef alloc, |
438 | | // const UInt8 *bytes, |
439 | | // CFIndex numBytes, |
440 | | // CFStringEncoding encoding, |
441 | | // Boolean isExternalRepresentation |
442 | | // ); |
443 | | // |
444 | | // We make the following substitutions: |
445 | | // |
446 | | // CFStringRef -> i8* |
447 | | // CFAllocatorRef -> i8* |
448 | | // UInt8 * -> i8* |
449 | | // CFIndex -> long (i32 or i64, as appropriate; we ask the module for its |
450 | | // pointer size for now) CFStringEncoding -> i32 Boolean -> i8 |
451 | | |
452 | 46 | Type *arg_type_array[5]; |
453 | | |
454 | 46 | arg_type_array[0] = i8_ptr_ty; |
455 | 46 | arg_type_array[1] = i8_ptr_ty; |
456 | 46 | arg_type_array[2] = m_intptr_ty; |
457 | 46 | arg_type_array[3] = i32_ty; |
458 | 46 | arg_type_array[4] = i8_ty; |
459 | | |
460 | 46 | ArrayRef<Type *> CFSCWB_arg_types(arg_type_array, 5); |
461 | | |
462 | 46 | llvm::FunctionType *CFSCWB_ty = |
463 | 46 | FunctionType::get(ns_str_ty, CFSCWB_arg_types, false); |
464 | | |
465 | | // Build the constant containing the pointer to the function |
466 | 46 | PointerType *CFSCWB_ptr_ty = PointerType::getUnqual(CFSCWB_ty); |
467 | 46 | Constant *CFSCWB_addr_int = |
468 | 46 | ConstantInt::get(m_intptr_ty, CFStringCreateWithBytes_addr, false); |
469 | 46 | m_CFStringCreateWithBytes = { |
470 | 46 | CFSCWB_ty, ConstantExpr::getIntToPtr(CFSCWB_addr_int, CFSCWB_ptr_ty)}; |
471 | 46 | } |
472 | | |
473 | 58 | ConstantDataSequential *string_array = nullptr; |
474 | | |
475 | 58 | if (cstr) |
476 | 56 | string_array = dyn_cast<ConstantDataSequential>(cstr->getInitializer()); |
477 | | |
478 | 58 | Constant *alloc_arg = Constant::getNullValue(i8_ptr_ty); |
479 | 58 | Constant *bytes_arg = cstr ? cstr56 : Constant::getNullValue(i8_ptr_ty)2 ; |
480 | 58 | Constant *numBytes_arg = ConstantInt::get( |
481 | 58 | m_intptr_ty, cstr ? (string_array->getNumElements() - 1) * string_array->getElementByteSize()56 : 02 , false); |
482 | 58 | int encoding_flags = 0; |
483 | 58 | switch (cstr ? string_array->getElementByteSize()56 : 12 ) { |
484 | 56 | case 1: |
485 | 56 | encoding_flags = 0x08000100; /* 0x08000100 is kCFStringEncodingUTF8 */ |
486 | 56 | break; |
487 | 2 | case 2: |
488 | 2 | encoding_flags = 0x0100; /* 0x0100 is kCFStringEncodingUTF16 */ |
489 | 2 | break; |
490 | 0 | case 4: |
491 | 0 | encoding_flags = 0x0c000100; /* 0x0c000100 is kCFStringEncodingUTF32 */ |
492 | 0 | break; |
493 | 0 | default: |
494 | 0 | encoding_flags = 0x0600; /* fall back to 0x0600, kCFStringEncodingASCII */ |
495 | 0 | LLDB_LOG(log, "Encountered an Objective-C constant string with unusual " |
496 | 58 | "element size {0}", |
497 | 58 | string_array->getElementByteSize()); |
498 | 58 | } |
499 | 58 | Constant *encoding_arg = ConstantInt::get(i32_ty, encoding_flags, false); |
500 | 58 | Constant *isExternal_arg = |
501 | 58 | ConstantInt::get(i8_ty, 0x0, false); /* 0x0 is false */ |
502 | | |
503 | 58 | Value *argument_array[5]; |
504 | | |
505 | 58 | argument_array[0] = alloc_arg; |
506 | 58 | argument_array[1] = bytes_arg; |
507 | 58 | argument_array[2] = numBytes_arg; |
508 | 58 | argument_array[3] = encoding_arg; |
509 | 58 | argument_array[4] = isExternal_arg; |
510 | | |
511 | 58 | ArrayRef<Value *> CFSCWB_arguments(argument_array, 5); |
512 | | |
513 | 58 | FunctionValueCache CFSCWB_Caller( |
514 | 58 | [this, &CFSCWB_arguments](llvm::Function *function) -> llvm::Value * { |
515 | 58 | return CallInst::Create( |
516 | 58 | m_CFStringCreateWithBytes, CFSCWB_arguments, |
517 | 58 | "CFStringCreateWithBytes", |
518 | 58 | llvm::cast<Instruction>( |
519 | 58 | m_entry_instruction_finder.GetValue(function))); |
520 | 58 | }); |
521 | | |
522 | 58 | if (!UnfoldConstant(ns_str, nullptr, CFSCWB_Caller, m_entry_instruction_finder, |
523 | 58 | m_error_stream)) { |
524 | 0 | LLDB_LOG(log, "Couldn't replace the NSString with the result of the call"); |
525 | |
|
526 | 0 | m_error_stream.Printf("error [IRForTarget internal]: Couldn't replace an " |
527 | 0 | "Objective-C constant string with a dynamic " |
528 | 0 | "string\n"); |
529 | |
|
530 | 0 | return false; |
531 | 0 | } |
532 | | |
533 | 58 | ns_str->eraseFromParent(); |
534 | | |
535 | 58 | return true; |
536 | 58 | } |
537 | | |
538 | 9.61k | bool IRForTarget::RewriteObjCConstStrings() { |
539 | 9.61k | lldb_private::Log *log(GetLog(LLDBLog::Expressions)); |
540 | | |
541 | 9.61k | ValueSymbolTable &value_symbol_table = m_module->getValueSymbolTable(); |
542 | | |
543 | 87.0k | for (StringMapEntry<llvm::Value *> &value_symbol : value_symbol_table) { |
544 | 87.0k | llvm::StringRef value_name = value_symbol.first(); |
545 | | |
546 | 87.0k | if (value_name.contains("_unnamed_cfstring_")) { |
547 | 60 | Value *nsstring_value = value_symbol.second; |
548 | | |
549 | 60 | GlobalVariable *nsstring_global = |
550 | 60 | dyn_cast<GlobalVariable>(nsstring_value); |
551 | | |
552 | 60 | if (!nsstring_global) { |
553 | 0 | LLDB_LOG(log, "NSString variable is not a GlobalVariable"); |
554 | |
|
555 | 0 | m_error_stream.Printf("Internal error [IRForTarget]: An Objective-C " |
556 | 0 | "constant string is not a global variable\n"); |
557 | |
|
558 | 0 | return false; |
559 | 0 | } |
560 | | |
561 | 60 | if (!nsstring_global->hasInitializer()) { |
562 | 0 | LLDB_LOG(log, "NSString variable does not have an initializer"); |
563 | |
|
564 | 0 | m_error_stream.Printf("Internal error [IRForTarget]: An Objective-C " |
565 | 0 | "constant string does not have an initializer\n"); |
566 | |
|
567 | 0 | return false; |
568 | 0 | } |
569 | | |
570 | 60 | ConstantStruct *nsstring_struct = |
571 | 60 | dyn_cast<ConstantStruct>(nsstring_global->getInitializer()); |
572 | | |
573 | 60 | if (!nsstring_struct) { |
574 | 0 | LLDB_LOG(log, |
575 | 0 | "NSString variable's initializer is not a ConstantStruct"); |
576 | |
|
577 | 0 | m_error_stream.Printf("Internal error [IRForTarget]: An Objective-C " |
578 | 0 | "constant string is not a structure constant\n"); |
579 | |
|
580 | 0 | return false; |
581 | 0 | } |
582 | | |
583 | | // We expect the following structure: |
584 | | // |
585 | | // struct { |
586 | | // int *isa; |
587 | | // int flags; |
588 | | // char *str; |
589 | | // long length; |
590 | | // }; |
591 | | |
592 | 60 | if (nsstring_struct->getNumOperands() != 4) { |
593 | |
|
594 | 0 | LLDB_LOG(log, |
595 | 0 | "NSString variable's initializer structure has an " |
596 | 0 | "unexpected number of members. Should be 4, is {0}", |
597 | 0 | nsstring_struct->getNumOperands()); |
598 | |
|
599 | 0 | m_error_stream.Printf("Internal error [IRForTarget]: The struct for an " |
600 | 0 | "Objective-C constant string is not as " |
601 | 0 | "expected\n"); |
602 | |
|
603 | 0 | return false; |
604 | 0 | } |
605 | | |
606 | 60 | Constant *nsstring_member = nsstring_struct->getOperand(2); |
607 | | |
608 | 60 | if (!nsstring_member) { |
609 | 0 | LLDB_LOG(log, "NSString initializer's str element was empty"); |
610 | |
|
611 | 0 | m_error_stream.Printf("Internal error [IRForTarget]: An Objective-C " |
612 | 0 | "constant string does not have a string " |
613 | 0 | "initializer\n"); |
614 | |
|
615 | 0 | return false; |
616 | 0 | } |
617 | | |
618 | 60 | auto *cstr_global = dyn_cast<GlobalVariable>(nsstring_member); |
619 | 60 | if (!cstr_global) { |
620 | 0 | LLDB_LOG(log, |
621 | 0 | "NSString initializer's str element is not a GlobalVariable"); |
622 | |
|
623 | 0 | m_error_stream.Printf("Internal error [IRForTarget]: Unhandled" |
624 | 0 | "constant string initializer\n"); |
625 | |
|
626 | 0 | return false; |
627 | 0 | } |
628 | | |
629 | 60 | if (!cstr_global->hasInitializer()) { |
630 | 0 | LLDB_LOG(log, "NSString initializer's str element does not have an " |
631 | 0 | "initializer"); |
632 | |
|
633 | 0 | m_error_stream.Printf("Internal error [IRForTarget]: An Objective-C " |
634 | 0 | "constant string's string initializer doesn't " |
635 | 0 | "point to initialized data\n"); |
636 | |
|
637 | 0 | return false; |
638 | 0 | } |
639 | | |
640 | | /* |
641 | | if (!cstr_array) |
642 | | { |
643 | | if (log) |
644 | | log->PutCString("NSString initializer's str element is not a |
645 | | ConstantArray"); |
646 | | |
647 | | if (m_error_stream) |
648 | | m_error_stream.Printf("Internal error [IRForTarget]: An |
649 | | Objective-C constant string's string initializer doesn't point to an |
650 | | array\n"); |
651 | | |
652 | | return false; |
653 | | } |
654 | | |
655 | | if (!cstr_array->isCString()) |
656 | | { |
657 | | if (log) |
658 | | log->PutCString("NSString initializer's str element is not a C |
659 | | string array"); |
660 | | |
661 | | if (m_error_stream) |
662 | | m_error_stream.Printf("Internal error [IRForTarget]: An |
663 | | Objective-C constant string's string initializer doesn't point to a C |
664 | | string\n"); |
665 | | |
666 | | return false; |
667 | | } |
668 | | */ |
669 | | |
670 | 60 | ConstantDataArray *cstr_array = |
671 | 60 | dyn_cast<ConstantDataArray>(cstr_global->getInitializer()); |
672 | | |
673 | 60 | if (cstr_array) |
674 | 58 | LLDB_LOG(log, "Found NSString constant {0}, which contains \"{1}\"", |
675 | 60 | value_name, cstr_array->getAsString()); |
676 | 2 | else |
677 | 2 | LLDB_LOG(log, "Found NSString constant {0}, which contains \"\"", |
678 | 60 | value_name); |
679 | | |
680 | 60 | if (!cstr_array) |
681 | 2 | cstr_global = nullptr; |
682 | | |
683 | 60 | if (!RewriteObjCConstString(nsstring_global, cstr_global)) { |
684 | 2 | LLDB_LOG(log, "Error rewriting the constant string"); |
685 | | |
686 | | // We don't print an error message here because RewriteObjCConstString |
687 | | // has done so for us. |
688 | | |
689 | 2 | return false; |
690 | 2 | } |
691 | 60 | } |
692 | 87.0k | } |
693 | | |
694 | 86.7k | for (StringMapEntry<llvm::Value *> &value_symbol : value_symbol_table)9.60k { |
695 | 86.7k | llvm::StringRef value_name = value_symbol.first(); |
696 | | |
697 | 86.7k | if (value_name == "__CFConstantStringClassReference") { |
698 | 46 | GlobalVariable *gv = dyn_cast<GlobalVariable>(value_symbol.second); |
699 | | |
700 | 46 | if (!gv) { |
701 | 0 | LLDB_LOG(log, |
702 | 0 | "__CFConstantStringClassReference is not a global variable"); |
703 | |
|
704 | 0 | m_error_stream.Printf("Internal error [IRForTarget]: Found a " |
705 | 0 | "CFConstantStringClassReference, but it is not a " |
706 | 0 | "global object\n"); |
707 | |
|
708 | 0 | return false; |
709 | 0 | } |
710 | | |
711 | 46 | gv->eraseFromParent(); |
712 | | |
713 | 46 | break; |
714 | 46 | } |
715 | 86.7k | } |
716 | | |
717 | 9.60k | return true; |
718 | 9.60k | } |
719 | | |
720 | 387k | static bool IsObjCSelectorRef(Value *value) { |
721 | 387k | GlobalVariable *global_variable = dyn_cast<GlobalVariable>(value); |
722 | | |
723 | 387k | return !(!global_variable || !global_variable->hasName()10.5k || |
724 | 387k | !global_variable->getName().startswith("OBJC_SELECTOR_REFERENCES_")10.5k ); |
725 | 387k | } |
726 | | |
727 | | // This function does not report errors; its callers are responsible. |
728 | 540 | bool IRForTarget::RewriteObjCSelector(Instruction *selector_load) { |
729 | 540 | lldb_private::Log *log(GetLog(LLDBLog::Expressions)); |
730 | | |
731 | 540 | LoadInst *load = dyn_cast<LoadInst>(selector_load); |
732 | | |
733 | 540 | if (!load) |
734 | 0 | return false; |
735 | | |
736 | | // Unpack the message name from the selector. In LLVM IR, an objc_msgSend |
737 | | // gets represented as |
738 | | // |
739 | | // %sel = load ptr, ptr @OBJC_SELECTOR_REFERENCES_, align 8 |
740 | | // call i8 @objc_msgSend(ptr %obj, ptr %sel, ...) |
741 | | // |
742 | | // where %obj is the object pointer and %sel is the selector. |
743 | | // |
744 | | // @"OBJC_SELECTOR_REFERENCES_" is a pointer to a character array called |
745 | | // @"\01L_OBJC_METH_VAR_NAME_". |
746 | | // @"\01L_OBJC_METH_VAR_NAME_" contains the string. |
747 | | |
748 | | // Find the pointer's initializer and get the string from its target. |
749 | | |
750 | 540 | GlobalVariable *_objc_selector_references_ = |
751 | 540 | dyn_cast<GlobalVariable>(load->getPointerOperand()); |
752 | | |
753 | 540 | if (!_objc_selector_references_ || |
754 | 540 | !_objc_selector_references_->hasInitializer()) |
755 | 0 | return false; |
756 | | |
757 | 540 | Constant *osr_initializer = _objc_selector_references_->getInitializer(); |
758 | 540 | if (!osr_initializer) |
759 | 0 | return false; |
760 | | |
761 | | // Find the string's initializer (a ConstantArray) and get the string from it |
762 | | |
763 | 540 | GlobalVariable *_objc_meth_var_name_ = |
764 | 540 | dyn_cast<GlobalVariable>(osr_initializer); |
765 | | |
766 | 540 | if (!_objc_meth_var_name_ || !_objc_meth_var_name_->hasInitializer()) |
767 | 0 | return false; |
768 | | |
769 | 540 | Constant *omvn_initializer = _objc_meth_var_name_->getInitializer(); |
770 | | |
771 | 540 | ConstantDataArray *omvn_initializer_array = |
772 | 540 | dyn_cast<ConstantDataArray>(omvn_initializer); |
773 | | |
774 | 540 | if (!omvn_initializer_array->isString()) |
775 | 0 | return false; |
776 | | |
777 | 540 | std::string omvn_initializer_string = |
778 | 540 | std::string(omvn_initializer_array->getAsString()); |
779 | | |
780 | 540 | LLDB_LOG(log, "Found Objective-C selector reference \"{0}\"", |
781 | 540 | omvn_initializer_string); |
782 | | |
783 | | // Construct a call to sel_registerName |
784 | | |
785 | 540 | if (!m_sel_registerName) { |
786 | 536 | lldb::addr_t sel_registerName_addr; |
787 | | |
788 | 536 | bool missing_weak = false; |
789 | 536 | static lldb_private::ConstString g_sel_registerName_str("sel_registerName"); |
790 | 536 | sel_registerName_addr = m_execution_unit.FindSymbol(g_sel_registerName_str, |
791 | 536 | missing_weak); |
792 | 536 | if (sel_registerName_addr == LLDB_INVALID_ADDRESS || missing_weak) |
793 | 0 | return false; |
794 | | |
795 | 536 | LLDB_LOG(log, "Found sel_registerName at {0}", sel_registerName_addr); |
796 | | |
797 | | // Build the function type: struct objc_selector |
798 | | // *sel_registerName(uint8_t*) |
799 | | |
800 | | // The below code would be "more correct," but in actuality what's required |
801 | | // is uint8_t* |
802 | | // Type *sel_type = StructType::get(m_module->getContext()); |
803 | | // Type *sel_ptr_type = PointerType::getUnqual(sel_type); |
804 | 536 | Type *sel_ptr_type = Type::getInt8PtrTy(m_module->getContext()); |
805 | | |
806 | 536 | Type *type_array[1]; |
807 | | |
808 | 536 | type_array[0] = llvm::Type::getInt8PtrTy(m_module->getContext()); |
809 | | |
810 | 536 | ArrayRef<Type *> srN_arg_types(type_array, 1); |
811 | | |
812 | 536 | llvm::FunctionType *srN_type = |
813 | 536 | FunctionType::get(sel_ptr_type, srN_arg_types, false); |
814 | | |
815 | | // Build the constant containing the pointer to the function |
816 | 536 | PointerType *srN_ptr_ty = PointerType::getUnqual(srN_type); |
817 | 536 | Constant *srN_addr_int = |
818 | 536 | ConstantInt::get(m_intptr_ty, sel_registerName_addr, false); |
819 | 536 | m_sel_registerName = {srN_type, |
820 | 536 | ConstantExpr::getIntToPtr(srN_addr_int, srN_ptr_ty)}; |
821 | 536 | } |
822 | | |
823 | 540 | CallInst *srN_call = |
824 | 540 | CallInst::Create(m_sel_registerName, _objc_meth_var_name_, |
825 | 540 | "sel_registerName", selector_load); |
826 | | |
827 | | // Replace the load with the call in all users |
828 | | |
829 | 540 | selector_load->replaceAllUsesWith(srN_call); |
830 | | |
831 | 540 | selector_load->eraseFromParent(); |
832 | | |
833 | 540 | return true; |
834 | 540 | } |
835 | | |
836 | 233k | bool IRForTarget::RewriteObjCSelectors(BasicBlock &basic_block) { |
837 | 233k | lldb_private::Log *log(GetLog(LLDBLog::Expressions)); |
838 | | |
839 | 233k | InstrList selector_loads; |
840 | | |
841 | 1.28M | for (Instruction &inst : basic_block) { |
842 | 1.28M | if (LoadInst *load = dyn_cast<LoadInst>(&inst)) |
843 | 387k | if (IsObjCSelectorRef(load->getPointerOperand())) |
844 | 540 | selector_loads.push_back(&inst); |
845 | 1.28M | } |
846 | | |
847 | 233k | for (Instruction *inst : selector_loads) { |
848 | 540 | if (!RewriteObjCSelector(inst)) { |
849 | 0 | m_error_stream.Printf("Internal error [IRForTarget]: Couldn't change a " |
850 | 0 | "static reference to an Objective-C selector to a " |
851 | 0 | "dynamic reference\n"); |
852 | |
|
853 | 0 | LLDB_LOG(log, "Couldn't rewrite a reference to an Objective-C selector"); |
854 | |
|
855 | 0 | return false; |
856 | 0 | } |
857 | 540 | } |
858 | | |
859 | 233k | return true; |
860 | 233k | } |
861 | | |
862 | | // This function does not report errors; its callers are responsible. |
863 | 28 | bool IRForTarget::RewritePersistentAlloc(llvm::Instruction *persistent_alloc) { |
864 | 28 | lldb_private::Log *log(GetLog(LLDBLog::Expressions)); |
865 | | |
866 | 28 | AllocaInst *alloc = dyn_cast<AllocaInst>(persistent_alloc); |
867 | | |
868 | 28 | MDNode *alloc_md = alloc->getMetadata("clang.decl.ptr"); |
869 | | |
870 | 28 | if (!alloc_md || !alloc_md->getNumOperands()) |
871 | 0 | return false; |
872 | | |
873 | 28 | ConstantInt *constant_int = |
874 | 28 | mdconst::dyn_extract<ConstantInt>(alloc_md->getOperand(0)); |
875 | | |
876 | 28 | if (!constant_int) |
877 | 0 | return false; |
878 | | |
879 | | // We attempt to register this as a new persistent variable with the DeclMap. |
880 | | |
881 | 28 | uintptr_t ptr = constant_int->getZExtValue(); |
882 | | |
883 | 28 | clang::VarDecl *decl = reinterpret_cast<clang::VarDecl *>(ptr); |
884 | | |
885 | 28 | lldb_private::TypeFromParser result_decl_type( |
886 | 28 | m_decl_map->GetTypeSystem()->GetType(decl->getType())); |
887 | | |
888 | 28 | StringRef decl_name(decl->getName()); |
889 | 28 | lldb_private::ConstString persistent_variable_name(decl_name.data(), |
890 | 28 | decl_name.size()); |
891 | 28 | if (!m_decl_map->AddPersistentVariable(decl, persistent_variable_name, |
892 | 28 | result_decl_type, false, false)) |
893 | 4 | return false; |
894 | | |
895 | 24 | GlobalVariable *persistent_global = new GlobalVariable( |
896 | 24 | (*m_module), alloc->getType(), false, /* not constant */ |
897 | 24 | GlobalValue::ExternalLinkage, nullptr, /* no initializer */ |
898 | 24 | alloc->getName().str()); |
899 | | |
900 | | // What we're going to do here is make believe this was a regular old |
901 | | // external variable. That means we need to make the metadata valid. |
902 | | |
903 | 24 | NamedMDNode *named_metadata = |
904 | 24 | m_module->getOrInsertNamedMetadata("clang.global.decl.ptrs"); |
905 | | |
906 | 24 | llvm::Metadata *values[2]; |
907 | 24 | values[0] = ConstantAsMetadata::get(persistent_global); |
908 | 24 | values[1] = ConstantAsMetadata::get(constant_int); |
909 | | |
910 | 24 | ArrayRef<llvm::Metadata *> value_ref(values, 2); |
911 | | |
912 | 24 | MDNode *persistent_global_md = MDNode::get(m_module->getContext(), value_ref); |
913 | 24 | named_metadata->addOperand(persistent_global_md); |
914 | | |
915 | | // Now, since the variable is a pointer variable, we will drop in a load of |
916 | | // that pointer variable. |
917 | | |
918 | 24 | LoadInst *persistent_load = new LoadInst(persistent_global->getValueType(), |
919 | 24 | persistent_global, "", alloc); |
920 | | |
921 | 24 | LLDB_LOG(log, "Replacing \"{0}\" with \"{1}\"", PrintValue(alloc), |
922 | 24 | PrintValue(persistent_load)); |
923 | | |
924 | 24 | alloc->replaceAllUsesWith(persistent_load); |
925 | 24 | alloc->eraseFromParent(); |
926 | | |
927 | 24 | return true; |
928 | 28 | } |
929 | | |
930 | 233k | bool IRForTarget::RewritePersistentAllocs(llvm::BasicBlock &basic_block) { |
931 | 233k | if (!m_resolve_vars) |
932 | 208k | return true; |
933 | | |
934 | 24.9k | lldb_private::Log *log(GetLog(LLDBLog::Expressions)); |
935 | | |
936 | 24.9k | InstrList pvar_allocs; |
937 | | |
938 | 109k | for (Instruction &inst : basic_block) { |
939 | | |
940 | 109k | if (AllocaInst *alloc = dyn_cast<AllocaInst>(&inst)) { |
941 | 14.0k | llvm::StringRef alloc_name = alloc->getName(); |
942 | | |
943 | 14.0k | if (alloc_name.startswith("$") && !alloc_name.startswith("$__lldb")6.94k ) { |
944 | 32 | if (alloc_name.find_first_of("0123456789") == 1) { |
945 | 4 | LLDB_LOG(log, "Rejecting a numeric persistent variable."); |
946 | | |
947 | 4 | m_error_stream.Printf("Error [IRForTarget]: Names starting with $0, " |
948 | 4 | "$1, ... are reserved for use as result " |
949 | 4 | "names\n"); |
950 | | |
951 | 4 | return false; |
952 | 4 | } |
953 | | |
954 | 28 | pvar_allocs.push_back(alloc); |
955 | 28 | } |
956 | 14.0k | } |
957 | 109k | } |
958 | | |
959 | 24.9k | for (Instruction *inst : pvar_allocs) { |
960 | 28 | if (!RewritePersistentAlloc(inst)) { |
961 | 4 | m_error_stream.Printf("Internal error [IRForTarget]: Couldn't rewrite " |
962 | 4 | "the creation of a persistent variable\n"); |
963 | | |
964 | 4 | LLDB_LOG(log, "Couldn't rewrite the creation of a persistent variable"); |
965 | | |
966 | 4 | return false; |
967 | 4 | } |
968 | 28 | } |
969 | | |
970 | 24.9k | return true; |
971 | 24.9k | } |
972 | | |
973 | | // This function does not report errors; its callers are responsible. |
974 | 341k | bool IRForTarget::MaybeHandleVariable(Value *llvm_value_ptr) { |
975 | 341k | lldb_private::Log *log(GetLog(LLDBLog::Expressions)); |
976 | | |
977 | 341k | LLDB_LOG(log, "MaybeHandleVariable ({0})", PrintValue(llvm_value_ptr)); |
978 | | |
979 | 341k | if (ConstantExpr *constant_expr = dyn_cast<ConstantExpr>(llvm_value_ptr)) { |
980 | 19 | switch (constant_expr->getOpcode()) { |
981 | 9 | default: |
982 | 9 | break; |
983 | 10 | case Instruction::GetElementPtr: |
984 | 10 | case Instruction::BitCast: |
985 | 10 | Value *s = constant_expr->getOperand(0); |
986 | 10 | if (!MaybeHandleVariable(s)) |
987 | 0 | return false; |
988 | 19 | } |
989 | 341k | } else if (GlobalVariable *global_variable = |
990 | 341k | dyn_cast<GlobalVariable>(llvm_value_ptr)) { |
991 | 65.3k | if (!GlobalValue::isExternalLinkage(global_variable->getLinkage())) |
992 | 51.4k | return true; |
993 | | |
994 | 13.8k | clang::NamedDecl *named_decl = DeclForGlobal(global_variable); |
995 | | |
996 | 13.8k | if (!named_decl) { |
997 | 0 | if (IsObjCSelectorRef(llvm_value_ptr)) |
998 | 0 | return true; |
999 | | |
1000 | 0 | if (!global_variable->hasExternalLinkage()) |
1001 | 0 | return true; |
1002 | | |
1003 | 0 | LLDB_LOG(log, "Found global variable \"{0}\" without metadata", |
1004 | 0 | global_variable->getName()); |
1005 | |
|
1006 | 0 | return false; |
1007 | 0 | } |
1008 | | |
1009 | 13.8k | llvm::StringRef name(named_decl->getName()); |
1010 | | |
1011 | 13.8k | clang::ValueDecl *value_decl = dyn_cast<clang::ValueDecl>(named_decl); |
1012 | 13.8k | if (value_decl == nullptr) |
1013 | 0 | return false; |
1014 | | |
1015 | 13.8k | lldb_private::CompilerType compiler_type = |
1016 | 13.8k | m_decl_map->GetTypeSystem()->GetType(value_decl->getType()); |
1017 | | |
1018 | 13.8k | const Type *value_type = nullptr; |
1019 | | |
1020 | 13.8k | if (name.startswith("$")) { |
1021 | | // The $__lldb_expr_result name indicates the return value has allocated |
1022 | | // as a static variable. Per the comment at |
1023 | | // ASTResultSynthesizer::SynthesizeBodyResult, accesses to this static |
1024 | | // variable need to be redirected to the result of dereferencing a |
1025 | | // pointer that is passed in as one of the arguments. |
1026 | | // |
1027 | | // Consequently, when reporting the size of the type, we report a pointer |
1028 | | // type pointing to the type of $__lldb_expr_result, not the type itself. |
1029 | | // |
1030 | | // We also do this for any user-declared persistent variables. |
1031 | 7.02k | compiler_type = compiler_type.GetPointerType(); |
1032 | 7.02k | value_type = PointerType::get(global_variable->getType(), 0); |
1033 | 7.02k | } else { |
1034 | 6.87k | value_type = global_variable->getType(); |
1035 | 6.87k | } |
1036 | | |
1037 | 13.8k | auto *target = m_execution_unit.GetTarget().get(); |
1038 | 13.8k | std::optional<uint64_t> value_size = compiler_type.GetByteSize(target); |
1039 | 13.8k | if (!value_size) |
1040 | 0 | return false; |
1041 | 13.8k | std::optional<size_t> opt_alignment = compiler_type.GetTypeBitAlign(target); |
1042 | 13.8k | if (!opt_alignment) |
1043 | 0 | return false; |
1044 | 13.8k | lldb::offset_t value_alignment = (*opt_alignment + 7ull) / 8ull; |
1045 | | |
1046 | 13.8k | LLDB_LOG(log, |
1047 | 13.8k | "Type of \"{0}\" is [clang \"{1}\", llvm \"{2}\"] [size {3}, " |
1048 | 13.8k | "align {4}]", |
1049 | 13.8k | name, |
1050 | 13.8k | lldb_private::ClangUtil::GetQualType(compiler_type).getAsString(), |
1051 | 13.8k | PrintType(value_type), *value_size, value_alignment); |
1052 | | |
1053 | 13.8k | if (named_decl) |
1054 | 13.8k | m_decl_map->AddValueToStruct(named_decl, lldb_private::ConstString(name), |
1055 | 13.8k | llvm_value_ptr, *value_size, |
1056 | 13.8k | value_alignment); |
1057 | 276k | } else if (isa<llvm::Function>(llvm_value_ptr)) { |
1058 | 0 | LLDB_LOG(log, "Function pointers aren't handled right now"); |
1059 | |
|
1060 | 0 | return false; |
1061 | 0 | } |
1062 | | |
1063 | 290k | return true; |
1064 | 341k | } |
1065 | | |
1066 | | // This function does not report errors; its callers are responsible. |
1067 | 67 | bool IRForTarget::HandleSymbol(Value *symbol) { |
1068 | 67 | lldb_private::Log *log(GetLog(LLDBLog::Expressions)); |
1069 | | |
1070 | 67 | lldb_private::ConstString name(symbol->getName().str().c_str()); |
1071 | | |
1072 | 67 | lldb::addr_t symbol_addr = |
1073 | 67 | m_decl_map->GetSymbolAddress(name, lldb::eSymbolTypeAny); |
1074 | | |
1075 | 67 | if (symbol_addr == LLDB_INVALID_ADDRESS) { |
1076 | 0 | LLDB_LOG(log, "Symbol \"{0}\" had no address", name); |
1077 | |
|
1078 | 0 | return false; |
1079 | 0 | } |
1080 | | |
1081 | 67 | LLDB_LOG(log, "Found \"{0}\" at {1}", name, symbol_addr); |
1082 | | |
1083 | 67 | Type *symbol_type = symbol->getType(); |
1084 | | |
1085 | 67 | Constant *symbol_addr_int = ConstantInt::get(m_intptr_ty, symbol_addr, false); |
1086 | | |
1087 | 67 | Value *symbol_addr_ptr = |
1088 | 67 | ConstantExpr::getIntToPtr(symbol_addr_int, symbol_type); |
1089 | | |
1090 | 67 | LLDB_LOG(log, "Replacing {0} with {1}", PrintValue(symbol), |
1091 | 67 | PrintValue(symbol_addr_ptr)); |
1092 | | |
1093 | 67 | symbol->replaceAllUsesWith(symbol_addr_ptr); |
1094 | | |
1095 | 67 | return true; |
1096 | 67 | } |
1097 | | |
1098 | 132k | bool IRForTarget::MaybeHandleCallArguments(CallInst *Old) { |
1099 | 132k | lldb_private::Log *log(GetLog(LLDBLog::Expressions)); |
1100 | | |
1101 | 132k | LLDB_LOG(log, "MaybeHandleCallArguments({0})", PrintValue(Old)); |
1102 | | |
1103 | 132k | for (unsigned op_index = 0, num_ops = Old->arg_size(); |
1104 | 460k | op_index < num_ops; ++op_index328k ) |
1105 | | // conservatively believe that this is a store |
1106 | 328k | if (!MaybeHandleVariable(Old->getArgOperand(op_index))) { |
1107 | 0 | m_error_stream.Printf("Internal error [IRForTarget]: Couldn't rewrite " |
1108 | 0 | "one of the arguments of a function call.\n"); |
1109 | |
|
1110 | 0 | return false; |
1111 | 0 | } |
1112 | | |
1113 | 132k | return true; |
1114 | 132k | } |
1115 | | |
1116 | 59 | bool IRForTarget::HandleObjCClass(Value *classlist_reference) { |
1117 | 59 | lldb_private::Log *log(GetLog(LLDBLog::Expressions)); |
1118 | | |
1119 | 59 | GlobalVariable *global_variable = |
1120 | 59 | dyn_cast<GlobalVariable>(classlist_reference); |
1121 | | |
1122 | 59 | if (!global_variable) |
1123 | 0 | return false; |
1124 | | |
1125 | 59 | Constant *initializer = global_variable->getInitializer(); |
1126 | | |
1127 | 59 | if (!initializer) |
1128 | 0 | return false; |
1129 | | |
1130 | 59 | if (!initializer->hasName()) |
1131 | 0 | return false; |
1132 | | |
1133 | 59 | StringRef name(initializer->getName()); |
1134 | 59 | lldb_private::ConstString name_cstr(name.str().c_str()); |
1135 | 59 | lldb::addr_t class_ptr = |
1136 | 59 | m_decl_map->GetSymbolAddress(name_cstr, lldb::eSymbolTypeObjCClass); |
1137 | | |
1138 | 59 | LLDB_LOG(log, "Found reference to Objective-C class {0} ({1})", name, |
1139 | 59 | (unsigned long long)class_ptr); |
1140 | | |
1141 | 59 | if (class_ptr == LLDB_INVALID_ADDRESS) |
1142 | 0 | return false; |
1143 | | |
1144 | 59 | if (global_variable->use_empty()) |
1145 | 0 | return false; |
1146 | | |
1147 | 59 | SmallVector<LoadInst *, 2> load_instructions; |
1148 | | |
1149 | 118 | for (llvm::User *u : global_variable->users()) { |
1150 | 118 | if (LoadInst *load_instruction = dyn_cast<LoadInst>(u)) |
1151 | 59 | load_instructions.push_back(load_instruction); |
1152 | 118 | } |
1153 | | |
1154 | 59 | if (load_instructions.empty()) |
1155 | 0 | return false; |
1156 | | |
1157 | 59 | Constant *class_addr = ConstantInt::get(m_intptr_ty, (uint64_t)class_ptr); |
1158 | | |
1159 | 59 | for (LoadInst *load_instruction : load_instructions) { |
1160 | 59 | Constant *class_bitcast = |
1161 | 59 | ConstantExpr::getIntToPtr(class_addr, load_instruction->getType()); |
1162 | | |
1163 | 59 | load_instruction->replaceAllUsesWith(class_bitcast); |
1164 | | |
1165 | 59 | load_instruction->eraseFromParent(); |
1166 | 59 | } |
1167 | | |
1168 | 59 | return true; |
1169 | 59 | } |
1170 | | |
1171 | 233k | bool IRForTarget::RemoveCXAAtExit(BasicBlock &basic_block) { |
1172 | 233k | std::vector<CallInst *> calls_to_remove; |
1173 | | |
1174 | 1.28M | for (Instruction &inst : basic_block) { |
1175 | 1.28M | CallInst *call = dyn_cast<CallInst>(&inst); |
1176 | | |
1177 | | // MaybeHandleCallArguments handles error reporting; we are silent here |
1178 | 1.28M | if (!call) |
1179 | 1.15M | continue; |
1180 | | |
1181 | 131k | bool remove = false; |
1182 | | |
1183 | 131k | llvm::Function *func = call->getCalledFunction(); |
1184 | | |
1185 | 131k | if (func && func->getName() == "__cxa_atexit"127k ) |
1186 | 2 | remove = true; |
1187 | | |
1188 | 131k | llvm::Value *val = call->getCalledOperand(); |
1189 | | |
1190 | 131k | if (val && val->getName() == "__cxa_atexit") |
1191 | 2 | remove = true; |
1192 | | |
1193 | 131k | if (remove) |
1194 | 2 | calls_to_remove.push_back(call); |
1195 | 131k | } |
1196 | | |
1197 | 233k | for (CallInst *ci : calls_to_remove) |
1198 | 2 | ci->eraseFromParent(); |
1199 | | |
1200 | 233k | return true; |
1201 | 233k | } |
1202 | | |
1203 | 233k | bool IRForTarget::ResolveCalls(BasicBlock &basic_block) { |
1204 | | // Prepare the current basic block for execution in the remote process |
1205 | | |
1206 | 1.28M | for (Instruction &inst : basic_block) { |
1207 | 1.28M | CallInst *call = dyn_cast<CallInst>(&inst); |
1208 | | |
1209 | | // MaybeHandleCallArguments handles error reporting; we are silent here |
1210 | 1.28M | if (call && !MaybeHandleCallArguments(call)132k ) |
1211 | 0 | return false; |
1212 | 1.28M | } |
1213 | | |
1214 | 233k | return true; |
1215 | 233k | } |
1216 | | |
1217 | 9.56k | bool IRForTarget::ResolveExternals(Function &llvm_function) { |
1218 | 9.56k | lldb_private::Log *log(GetLog(LLDBLog::Expressions)); |
1219 | | |
1220 | 64.1k | for (GlobalVariable &global_var : m_module->globals()) { |
1221 | 64.1k | llvm::StringRef global_name = global_var.getName(); |
1222 | | |
1223 | 64.1k | LLDB_LOG(log, "Examining {0}, DeclForGlobalValue returns {1}", global_name, |
1224 | 64.1k | static_cast<void *>(DeclForGlobal(&global_var))); |
1225 | | |
1226 | 64.1k | if (global_name.startswith("OBJC_IVAR")) { |
1227 | 67 | if (!HandleSymbol(&global_var)) { |
1228 | 0 | m_error_stream.Format("Error [IRForTarget]: Couldn't find Objective-C " |
1229 | 0 | "indirect ivar symbol {0}\n", |
1230 | 0 | global_name); |
1231 | |
|
1232 | 0 | return false; |
1233 | 0 | } |
1234 | 64.0k | } else if (global_name.contains("OBJC_CLASSLIST_REFERENCES_$")) { |
1235 | 57 | if (!HandleObjCClass(&global_var)) { |
1236 | 0 | m_error_stream.Printf("Error [IRForTarget]: Couldn't resolve the class " |
1237 | 0 | "for an Objective-C static method call\n"); |
1238 | |
|
1239 | 0 | return false; |
1240 | 0 | } |
1241 | 64.0k | } else if (global_name.contains("OBJC_CLASSLIST_SUP_REFS_$")) { |
1242 | 2 | if (!HandleObjCClass(&global_var)) { |
1243 | 0 | m_error_stream.Printf("Error [IRForTarget]: Couldn't resolve the class " |
1244 | 0 | "for an Objective-C static method call\n"); |
1245 | |
|
1246 | 0 | return false; |
1247 | 0 | } |
1248 | 64.0k | } else if (DeclForGlobal(&global_var)) { |
1249 | 13.8k | if (!MaybeHandleVariable(&global_var)) { |
1250 | 0 | m_error_stream.Format("Internal error [IRForTarget]: Couldn't rewrite " |
1251 | 0 | "external variable {0}\n", |
1252 | 0 | global_name); |
1253 | |
|
1254 | 0 | return false; |
1255 | 0 | } |
1256 | 13.8k | } |
1257 | 64.1k | } |
1258 | | |
1259 | 9.56k | return true; |
1260 | 9.56k | } |
1261 | | |
1262 | 532k | static bool isGuardVariableRef(Value *V) { |
1263 | 532k | GlobalVariable *GV = dyn_cast<GlobalVariable>(V); |
1264 | | |
1265 | 532k | if (!GV || !GV->hasName()30.1k || !isGuardVariableSymbol(GV->getName())30.1k ) |
1266 | 520k | return false; |
1267 | | |
1268 | 12.8k | return true; |
1269 | 532k | } |
1270 | | |
1271 | 6.40k | void IRForTarget::TurnGuardLoadIntoZero(llvm::Instruction *guard_load) { |
1272 | 6.40k | Constant *zero(Constant::getNullValue(guard_load->getType())); |
1273 | 6.40k | guard_load->replaceAllUsesWith(zero); |
1274 | 6.40k | guard_load->eraseFromParent(); |
1275 | 6.40k | } |
1276 | | |
1277 | 6.40k | static void ExciseGuardStore(Instruction *guard_store) { |
1278 | 6.40k | guard_store->eraseFromParent(); |
1279 | 6.40k | } |
1280 | | |
1281 | 233k | bool IRForTarget::RemoveGuards(BasicBlock &basic_block) { |
1282 | | // Eliminate any reference to guard variables found. |
1283 | | |
1284 | 233k | InstrList guard_loads; |
1285 | 233k | InstrList guard_stores; |
1286 | | |
1287 | 1.29M | for (Instruction &inst : basic_block) { |
1288 | | |
1289 | 1.29M | if (LoadInst *load = dyn_cast<LoadInst>(&inst)) |
1290 | 393k | if (isGuardVariableRef(load->getPointerOperand())) |
1291 | 6.40k | guard_loads.push_back(&inst); |
1292 | | |
1293 | 1.29M | if (StoreInst *store = dyn_cast<StoreInst>(&inst)) |
1294 | 139k | if (isGuardVariableRef(store->getPointerOperand())) |
1295 | 6.40k | guard_stores.push_back(&inst); |
1296 | 1.29M | } |
1297 | | |
1298 | 233k | for (Instruction *inst : guard_loads) |
1299 | 6.40k | TurnGuardLoadIntoZero(inst); |
1300 | | |
1301 | 233k | for (Instruction *inst : guard_stores) |
1302 | 6.40k | ExciseGuardStore(inst); |
1303 | | |
1304 | 233k | return true; |
1305 | 233k | } |
1306 | | |
1307 | | // This function does not report errors; its callers are responsible. |
1308 | | bool IRForTarget::UnfoldConstant(Constant *old_constant, |
1309 | | llvm::Function *llvm_function, |
1310 | | FunctionValueCache &value_maker, |
1311 | | FunctionValueCache &entry_instruction_finder, |
1312 | 12.9k | lldb_private::Stream &error_stream) { |
1313 | 12.9k | SmallVector<User *, 16> users; |
1314 | | |
1315 | | // We do this because the use list might change, invalidating our iterator. |
1316 | | // Much better to keep a work list ourselves. |
1317 | 12.9k | for (llvm::User *u : old_constant->users()) |
1318 | 12.9k | users.push_back(u); |
1319 | | |
1320 | 25.9k | for (size_t i = 0; i < users.size(); ++i12.9k ) { |
1321 | 12.9k | User *user = users[i]; |
1322 | | |
1323 | 12.9k | if (Constant *constant = dyn_cast<Constant>(user)) { |
1324 | | // synthesize a new non-constant equivalent of the constant |
1325 | | |
1326 | 14 | if (ConstantExpr *constant_expr = dyn_cast<ConstantExpr>(constant)) { |
1327 | 14 | switch (constant_expr->getOpcode()) { |
1328 | 0 | default: |
1329 | 0 | error_stream.Printf("error [IRForTarget internal]: Unhandled " |
1330 | 0 | "constant expression type: \"%s\"", |
1331 | 0 | PrintValue(constant_expr).c_str()); |
1332 | 0 | return false; |
1333 | 0 | case Instruction::BitCast: { |
1334 | 0 | FunctionValueCache bit_cast_maker( |
1335 | 0 | [&value_maker, &entry_instruction_finder, old_constant, |
1336 | 0 | constant_expr](llvm::Function *function) -> llvm::Value * { |
1337 | | // UnaryExpr |
1338 | | // OperandList[0] is value |
1339 | |
|
1340 | 0 | if (constant_expr->getOperand(0) != old_constant) |
1341 | 0 | return constant_expr; |
1342 | | |
1343 | 0 | return new BitCastInst( |
1344 | 0 | value_maker.GetValue(function), constant_expr->getType(), |
1345 | 0 | "", llvm::cast<Instruction>( |
1346 | 0 | entry_instruction_finder.GetValue(function))); |
1347 | 0 | }); |
1348 | |
|
1349 | 0 | if (!UnfoldConstant(constant_expr, llvm_function, bit_cast_maker, |
1350 | 0 | entry_instruction_finder, error_stream)) |
1351 | 0 | return false; |
1352 | 0 | } break; |
1353 | 14 | case Instruction::GetElementPtr: { |
1354 | | // GetElementPtrConstantExpr |
1355 | | // OperandList[0] is base |
1356 | | // OperandList[1]... are indices |
1357 | | |
1358 | 14 | FunctionValueCache get_element_pointer_maker( |
1359 | 14 | [&value_maker, &entry_instruction_finder, old_constant, |
1360 | 14 | constant_expr](llvm::Function *function) -> llvm::Value * { |
1361 | 14 | auto *gep = cast<llvm::GEPOperator>(constant_expr); |
1362 | 14 | Value *ptr = gep->getPointerOperand(); |
1363 | | |
1364 | 14 | if (ptr == old_constant) |
1365 | 14 | ptr = value_maker.GetValue(function); |
1366 | | |
1367 | 14 | std::vector<Value *> index_vector; |
1368 | 28 | for (Value *operand : gep->indices()) { |
1369 | 28 | if (operand == old_constant) |
1370 | 0 | operand = value_maker.GetValue(function); |
1371 | | |
1372 | 28 | index_vector.push_back(operand); |
1373 | 28 | } |
1374 | | |
1375 | 14 | ArrayRef<Value *> indices(index_vector); |
1376 | | |
1377 | 14 | return GetElementPtrInst::Create( |
1378 | 14 | gep->getSourceElementType(), ptr, indices, "", |
1379 | 14 | llvm::cast<Instruction>( |
1380 | 14 | entry_instruction_finder.GetValue(function))); |
1381 | 14 | }); |
1382 | | |
1383 | 14 | if (!UnfoldConstant(constant_expr, llvm_function, |
1384 | 14 | get_element_pointer_maker, |
1385 | 14 | entry_instruction_finder, error_stream)) |
1386 | 0 | return false; |
1387 | 14 | } break; |
1388 | 14 | } |
1389 | 14 | } else { |
1390 | 0 | error_stream.Printf( |
1391 | 0 | "error [IRForTarget internal]: Unhandled constant type: \"%s\"", |
1392 | 0 | PrintValue(constant).c_str()); |
1393 | 0 | return false; |
1394 | 0 | } |
1395 | 12.9k | } else { |
1396 | 12.9k | if (Instruction *inst = llvm::dyn_cast<Instruction>(user)) { |
1397 | 12.9k | if (llvm_function && inst->getParent()->getParent() != llvm_function12.9k ) { |
1398 | 2 | error_stream.PutCString("error: Capturing non-local variables in " |
1399 | 2 | "expressions is unsupported.\n"); |
1400 | 2 | return false; |
1401 | 2 | } |
1402 | 12.9k | inst->replaceUsesOfWith( |
1403 | 12.9k | old_constant, value_maker.GetValue(inst->getParent()->getParent())); |
1404 | 12.9k | } else { |
1405 | 0 | error_stream.Printf( |
1406 | 0 | "error [IRForTarget internal]: Unhandled non-constant type: \"%s\"", |
1407 | 0 | PrintValue(user).c_str()); |
1408 | 0 | return false; |
1409 | 0 | } |
1410 | 12.9k | } |
1411 | 12.9k | } |
1412 | | |
1413 | 12.9k | if (!isa<GlobalValue>(old_constant)) { |
1414 | 14 | old_constant->destroyConstant(); |
1415 | 14 | } |
1416 | | |
1417 | 12.9k | return true; |
1418 | 12.9k | } |
1419 | | |
1420 | 9.56k | bool IRForTarget::ReplaceVariables(Function &llvm_function) { |
1421 | 9.56k | if (!m_resolve_vars) |
1422 | 2.66k | return true; |
1423 | | |
1424 | 6.90k | lldb_private::Log *log(GetLog(LLDBLog::Expressions)); |
1425 | | |
1426 | 6.90k | m_decl_map->DoStructLayout(); |
1427 | | |
1428 | 6.90k | LLDB_LOG(log, "Element arrangement:"); |
1429 | | |
1430 | 6.90k | uint32_t num_elements; |
1431 | 6.90k | uint32_t element_index; |
1432 | | |
1433 | 6.90k | size_t size; |
1434 | 6.90k | lldb::offset_t alignment; |
1435 | | |
1436 | 6.90k | if (!m_decl_map->GetStructInfo(num_elements, size, alignment)) |
1437 | 0 | return false; |
1438 | | |
1439 | 6.90k | Function::arg_iterator iter(llvm_function.arg_begin()); |
1440 | | |
1441 | 6.90k | if (iter == llvm_function.arg_end()) { |
1442 | 0 | m_error_stream.Printf("Internal error [IRForTarget]: Wrapper takes no " |
1443 | 0 | "arguments (should take at least a struct pointer)"); |
1444 | |
|
1445 | 0 | return false; |
1446 | 0 | } |
1447 | | |
1448 | 6.90k | Argument *argument = &*iter; |
1449 | | |
1450 | 6.90k | if (argument->getName().equals("this")) { |
1451 | 154 | ++iter; |
1452 | | |
1453 | 154 | if (iter == llvm_function.arg_end()) { |
1454 | 0 | m_error_stream.Printf("Internal error [IRForTarget]: Wrapper takes only " |
1455 | 0 | "'this' argument (should take a struct pointer " |
1456 | 0 | "too)"); |
1457 | |
|
1458 | 0 | return false; |
1459 | 0 | } |
1460 | | |
1461 | 154 | argument = &*iter; |
1462 | 6.74k | } else if (argument->getName().equals("self")) { |
1463 | 73 | ++iter; |
1464 | | |
1465 | 73 | if (iter == llvm_function.arg_end()) { |
1466 | 0 | m_error_stream.Printf("Internal error [IRForTarget]: Wrapper takes only " |
1467 | 0 | "'self' argument (should take '_cmd' and a struct " |
1468 | 0 | "pointer too)"); |
1469 | |
|
1470 | 0 | return false; |
1471 | 0 | } |
1472 | | |
1473 | 73 | if (!iter->getName().equals("_cmd")) { |
1474 | 0 | m_error_stream.Format("Internal error [IRForTarget]: Wrapper takes '{0}' " |
1475 | 0 | "after 'self' argument (should take '_cmd')", |
1476 | 0 | iter->getName()); |
1477 | |
|
1478 | 0 | return false; |
1479 | 0 | } |
1480 | | |
1481 | 73 | ++iter; |
1482 | | |
1483 | 73 | if (iter == llvm_function.arg_end()) { |
1484 | 0 | m_error_stream.Printf("Internal error [IRForTarget]: Wrapper takes only " |
1485 | 0 | "'self' and '_cmd' arguments (should take a struct " |
1486 | 0 | "pointer too)"); |
1487 | |
|
1488 | 0 | return false; |
1489 | 0 | } |
1490 | | |
1491 | 73 | argument = &*iter; |
1492 | 73 | } |
1493 | | |
1494 | 6.90k | if (!argument->getName().equals("$__lldb_arg")) { |
1495 | 0 | m_error_stream.Format("Internal error [IRForTarget]: Wrapper takes an " |
1496 | 0 | "argument named '{0}' instead of the struct pointer", |
1497 | 0 | argument->getName()); |
1498 | |
|
1499 | 0 | return false; |
1500 | 0 | } |
1501 | | |
1502 | 6.90k | LLDB_LOG(log, "Arg: \"{0}\"", PrintValue(argument)); |
1503 | | |
1504 | 6.90k | BasicBlock &entry_block(llvm_function.getEntryBlock()); |
1505 | 6.90k | Instruction *FirstEntryInstruction(entry_block.getFirstNonPHIOrDbg()); |
1506 | | |
1507 | 6.90k | if (!FirstEntryInstruction) { |
1508 | 0 | m_error_stream.Printf("Internal error [IRForTarget]: Couldn't find the " |
1509 | 0 | "first instruction in the wrapper for use in " |
1510 | 0 | "rewriting"); |
1511 | |
|
1512 | 0 | return false; |
1513 | 0 | } |
1514 | | |
1515 | 6.90k | LLVMContext &context(m_module->getContext()); |
1516 | 6.90k | IntegerType *offset_type(Type::getInt32Ty(context)); |
1517 | | |
1518 | 6.90k | if (!offset_type) { |
1519 | 0 | m_error_stream.Printf( |
1520 | 0 | "Internal error [IRForTarget]: Couldn't produce an offset type"); |
1521 | |
|
1522 | 0 | return false; |
1523 | 0 | } |
1524 | | |
1525 | 19.7k | for (element_index = 0; 6.90k element_index < num_elements; ++element_index12.8k ) { |
1526 | 12.8k | const clang::NamedDecl *decl = nullptr; |
1527 | 12.8k | Value *value = nullptr; |
1528 | 12.8k | lldb::offset_t offset; |
1529 | 12.8k | lldb_private::ConstString name; |
1530 | | |
1531 | 12.8k | if (!m_decl_map->GetStructElement(decl, value, offset, name, |
1532 | 12.8k | element_index)) { |
1533 | 0 | m_error_stream.Printf( |
1534 | 0 | "Internal error [IRForTarget]: Structure information is incomplete"); |
1535 | |
|
1536 | 0 | return false; |
1537 | 0 | } |
1538 | | |
1539 | 12.8k | LLDB_LOG(log, " \"{0}\" (\"{1}\") placed at {2}", name, |
1540 | 12.8k | decl->getNameAsString(), offset); |
1541 | | |
1542 | 12.8k | if (value) { |
1543 | 12.8k | LLDB_LOG(log, " Replacing [{0}]", PrintValue(value)); |
1544 | | |
1545 | 12.8k | FunctionValueCache body_result_maker( |
1546 | 12.8k | [this, name, offset_type, offset, argument, |
1547 | 12.8k | value](llvm::Function *function) -> llvm::Value * { |
1548 | | // Per the comment at ASTResultSynthesizer::SynthesizeBodyResult, |
1549 | | // in cases where the result variable is an rvalue, we have to |
1550 | | // synthesize a dereference of the appropriate structure entry in |
1551 | | // order to produce the static variable that the AST thinks it is |
1552 | | // accessing. |
1553 | | |
1554 | 12.8k | llvm::Instruction *entry_instruction = llvm::cast<Instruction>( |
1555 | 12.8k | m_entry_instruction_finder.GetValue(function)); |
1556 | | |
1557 | 12.8k | Type *int8Ty = Type::getInt8Ty(function->getContext()); |
1558 | 12.8k | ConstantInt *offset_int( |
1559 | 12.8k | ConstantInt::get(offset_type, offset, true)); |
1560 | 12.8k | GetElementPtrInst *get_element_ptr = GetElementPtrInst::Create( |
1561 | 12.8k | int8Ty, argument, offset_int, "", entry_instruction); |
1562 | | |
1563 | 12.8k | if (name == m_result_name && !m_result_is_pointer6.80k ) { |
1564 | 1.69k | LoadInst *load = new LoadInst(value->getType(), get_element_ptr, |
1565 | 1.69k | "", entry_instruction); |
1566 | | |
1567 | 1.69k | return load; |
1568 | 11.1k | } else { |
1569 | 11.1k | return get_element_ptr; |
1570 | 11.1k | } |
1571 | 12.8k | }); |
1572 | | |
1573 | 12.8k | if (Constant *constant = dyn_cast<Constant>(value)) { |
1574 | 12.8k | if (!UnfoldConstant(constant, &llvm_function, body_result_maker, |
1575 | 12.8k | m_entry_instruction_finder, m_error_stream)) { |
1576 | 2 | return false; |
1577 | 2 | } |
1578 | 12.8k | } else if (Instruction *0 instruction0 = dyn_cast<Instruction>(value)) { |
1579 | 0 | if (instruction->getParent()->getParent() != &llvm_function) { |
1580 | 0 | m_error_stream.PutCString("error: Capturing non-local variables in " |
1581 | 0 | "expressions is unsupported.\n"); |
1582 | 0 | return false; |
1583 | 0 | } |
1584 | 0 | value->replaceAllUsesWith( |
1585 | 0 | body_result_maker.GetValue(instruction->getParent()->getParent())); |
1586 | 0 | } else { |
1587 | 0 | LLDB_LOG(log, "Unhandled non-constant type: \"{0}\"", |
1588 | 0 | PrintValue(value)); |
1589 | 0 | return false; |
1590 | 0 | } |
1591 | | |
1592 | 12.8k | if (GlobalVariable *var = dyn_cast<GlobalVariable>(value)) |
1593 | 12.8k | var->eraseFromParent(); |
1594 | 12.8k | } |
1595 | 12.8k | } |
1596 | | |
1597 | 6.89k | LLDB_LOG(log, "Total structure [align {0}, size {1}]", (int64_t)alignment, |
1598 | 6.89k | (uint64_t)size); |
1599 | | |
1600 | 6.89k | return true; |
1601 | 6.90k | } |
1602 | | |
1603 | 9.61k | bool IRForTarget::runOnModule(Module &llvm_module) { |
1604 | 9.61k | lldb_private::Log *log(GetLog(LLDBLog::Expressions)); |
1605 | | |
1606 | 9.61k | m_module = &llvm_module; |
1607 | 9.61k | m_target_data = std::make_unique<DataLayout>(m_module); |
1608 | 9.61k | m_intptr_ty = llvm::Type::getIntNTy(m_module->getContext(), |
1609 | 9.61k | m_target_data->getPointerSizeInBits()); |
1610 | | |
1611 | 9.61k | if (log) { |
1612 | 20 | std::string s; |
1613 | 20 | raw_string_ostream oss(s); |
1614 | | |
1615 | 20 | m_module->print(oss, nullptr); |
1616 | | |
1617 | 20 | oss.flush(); |
1618 | | |
1619 | 20 | LLDB_LOG(log, "Module as passed in to IRForTarget: \n\"{0}\"", s); |
1620 | 20 | } |
1621 | | |
1622 | 9.61k | Function *const main_function = |
1623 | 9.61k | m_func_name.IsEmpty() ? nullptr45 |
1624 | 9.61k | : m_module->getFunction(m_func_name.GetStringRef())9.57k ; |
1625 | | |
1626 | 9.61k | if (!m_func_name.IsEmpty() && !main_function9.57k ) { |
1627 | 0 | LLDB_LOG(log, "Couldn't find \"{0}()\" in the module", m_func_name); |
1628 | |
|
1629 | 0 | m_error_stream.Format("Internal error [IRForTarget]: Couldn't find wrapper " |
1630 | 0 | "'{0}' in the module", |
1631 | 0 | m_func_name); |
1632 | |
|
1633 | 0 | return false; |
1634 | 0 | } |
1635 | | |
1636 | 9.61k | if (main_function) { |
1637 | 9.57k | if (!FixFunctionLinkage(*main_function)) { |
1638 | 0 | LLDB_LOG(log, "Couldn't fix the linkage for the function"); |
1639 | |
|
1640 | 0 | return false; |
1641 | 0 | } |
1642 | 9.57k | } |
1643 | | |
1644 | 9.61k | llvm::Type *int8_ty = Type::getInt8Ty(m_module->getContext()); |
1645 | | |
1646 | 9.61k | m_reloc_placeholder = new llvm::GlobalVariable( |
1647 | 9.61k | (*m_module), int8_ty, false /* IsConstant */, |
1648 | 9.61k | GlobalVariable::InternalLinkage, Constant::getNullValue(int8_ty), |
1649 | 9.61k | "reloc_placeholder", nullptr /* InsertBefore */, |
1650 | 9.61k | GlobalVariable::NotThreadLocal /* ThreadLocal */, 0 /* AddressSpace */); |
1651 | | |
1652 | | //////////////////////////////////////////////////////////// |
1653 | | // Replace $__lldb_expr_result with a persistent variable |
1654 | | // |
1655 | | |
1656 | 9.61k | if (main_function) { |
1657 | 9.57k | if (!CreateResultVariable(*main_function)) { |
1658 | 0 | LLDB_LOG(log, "CreateResultVariable() failed"); |
1659 | | |
1660 | | // CreateResultVariable() reports its own errors, so we don't do so here |
1661 | |
|
1662 | 0 | return false; |
1663 | 0 | } |
1664 | 9.57k | } |
1665 | | |
1666 | 9.61k | if (log && log->GetVerbose()20 ) { |
1667 | 0 | std::string s; |
1668 | 0 | raw_string_ostream oss(s); |
1669 | |
|
1670 | 0 | m_module->print(oss, nullptr); |
1671 | |
|
1672 | 0 | oss.flush(); |
1673 | |
|
1674 | 0 | LLDB_LOG(log, "Module after creating the result variable: \n\"{0}\"", s); |
1675 | 0 | } |
1676 | | |
1677 | 22.7k | for (llvm::Function &function : *m_module) { |
1678 | 233k | for (BasicBlock &bb : function) { |
1679 | 233k | if (!RemoveGuards(bb)) { |
1680 | 0 | LLDB_LOG(log, "RemoveGuards() failed"); |
1681 | | |
1682 | | // RemoveGuards() reports its own errors, so we don't do so here |
1683 | |
|
1684 | 0 | return false; |
1685 | 0 | } |
1686 | | |
1687 | 233k | if (!RewritePersistentAllocs(bb)) { |
1688 | 8 | LLDB_LOG(log, "RewritePersistentAllocs() failed"); |
1689 | | |
1690 | | // RewritePersistentAllocs() reports its own errors, so we don't do so |
1691 | | // here |
1692 | | |
1693 | 8 | return false; |
1694 | 8 | } |
1695 | | |
1696 | 233k | if (!RemoveCXAAtExit(bb)) { |
1697 | 0 | LLDB_LOG(log, "RemoveCXAAtExit() failed"); |
1698 | | |
1699 | | // RemoveCXAAtExit() reports its own errors, so we don't do so here |
1700 | |
|
1701 | 0 | return false; |
1702 | 0 | } |
1703 | 233k | } |
1704 | 22.7k | } |
1705 | | |
1706 | | /////////////////////////////////////////////////////////////////////////////// |
1707 | | // Fix all Objective-C constant strings to use NSStringWithCString:encoding: |
1708 | | // |
1709 | | |
1710 | 9.61k | if (!RewriteObjCConstStrings()) { |
1711 | 2 | LLDB_LOG(log, "RewriteObjCConstStrings() failed"); |
1712 | | |
1713 | | // RewriteObjCConstStrings() reports its own errors, so we don't do so here |
1714 | | |
1715 | 2 | return false; |
1716 | 2 | } |
1717 | | |
1718 | 22.7k | for (llvm::Function &function : *m_module)9.60k { |
1719 | 233k | for (llvm::BasicBlock &bb : function) { |
1720 | 233k | if (!RewriteObjCSelectors(bb)) { |
1721 | 0 | LLDB_LOG(log, "RewriteObjCSelectors() failed"); |
1722 | | |
1723 | | // RewriteObjCSelectors() reports its own errors, so we don't do so |
1724 | | // here |
1725 | |
|
1726 | 0 | return false; |
1727 | 0 | } |
1728 | 233k | } |
1729 | 22.7k | } |
1730 | | |
1731 | 22.7k | for (llvm::Function &function : *m_module)9.60k { |
1732 | 233k | for (BasicBlock &bb : function) { |
1733 | 233k | if (!ResolveCalls(bb)) { |
1734 | 0 | LLDB_LOG(log, "ResolveCalls() failed"); |
1735 | | |
1736 | | // ResolveCalls() reports its own errors, so we don't do so here |
1737 | |
|
1738 | 0 | return false; |
1739 | 0 | } |
1740 | 233k | } |
1741 | 22.7k | } |
1742 | | |
1743 | | //////////////////////////////////////////////////////////////////////// |
1744 | | // Run function-level passes that only make sense on the main function |
1745 | | // |
1746 | | |
1747 | 9.60k | if (main_function) { |
1748 | 9.56k | if (!ResolveExternals(*main_function)) { |
1749 | 0 | LLDB_LOG(log, "ResolveExternals() failed"); |
1750 | | |
1751 | | // ResolveExternals() reports its own errors, so we don't do so here |
1752 | |
|
1753 | 0 | return false; |
1754 | 0 | } |
1755 | | |
1756 | 9.56k | if (!ReplaceVariables(*main_function)) { |
1757 | 2 | LLDB_LOG(log, "ReplaceVariables() failed"); |
1758 | | |
1759 | | // ReplaceVariables() reports its own errors, so we don't do so here |
1760 | | |
1761 | 2 | return false; |
1762 | 2 | } |
1763 | 9.56k | } |
1764 | | |
1765 | 9.60k | if (log && log->GetVerbose()20 ) { |
1766 | 0 | std::string s; |
1767 | 0 | raw_string_ostream oss(s); |
1768 | |
|
1769 | 0 | m_module->print(oss, nullptr); |
1770 | |
|
1771 | 0 | oss.flush(); |
1772 | |
|
1773 | 0 | LLDB_LOG(log, "Module after preparing for execution: \n\"{0}\"", s); |
1774 | 0 | } |
1775 | | |
1776 | 9.60k | return true; |
1777 | 9.60k | } |