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