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