1*2fd83355SJason Molenda //===-- AppleGetItemInfoHandler.cpp -------------------------------*- C++ -*-===// 2*2fd83355SJason Molenda // 3*2fd83355SJason Molenda // The LLVM Compiler Infrastructure 4*2fd83355SJason Molenda // 5*2fd83355SJason Molenda // This file is distributed under the University of Illinois Open Source 6*2fd83355SJason Molenda // License. See LICENSE.TXT for details. 7*2fd83355SJason Molenda // 8*2fd83355SJason Molenda //===----------------------------------------------------------------------===// 9*2fd83355SJason Molenda 10*2fd83355SJason Molenda #include "AppleGetItemInfoHandler.h" 11*2fd83355SJason Molenda 12*2fd83355SJason Molenda // C Includes 13*2fd83355SJason Molenda // C++ Includes 14*2fd83355SJason Molenda // Other libraries and framework includes 15*2fd83355SJason Molenda // Project includes 16*2fd83355SJason Molenda 17*2fd83355SJason Molenda #include "clang/AST/ASTContext.h" 18*2fd83355SJason Molenda #include "clang/AST/DeclCXX.h" 19*2fd83355SJason Molenda 20*2fd83355SJason Molenda #include "lldb/Core/ConstString.h" 21*2fd83355SJason Molenda #include "lldb/Core/Log.h" 22*2fd83355SJason Molenda #include "lldb/Core/Module.h" 23*2fd83355SJason Molenda #include "lldb/Core/StreamString.h" 24*2fd83355SJason Molenda #include "lldb/Core/Value.h" 25*2fd83355SJason Molenda #include "lldb/Expression/ClangExpression.h" 26*2fd83355SJason Molenda #include "lldb/Expression/ClangFunction.h" 27*2fd83355SJason Molenda #include "lldb/Expression/ClangUtilityFunction.h" 28*2fd83355SJason Molenda #include "lldb/Symbol/ClangASTContext.h" 29*2fd83355SJason Molenda #include "lldb/Symbol/Symbol.h" 30*2fd83355SJason Molenda #include "lldb/Target/ExecutionContext.h" 31*2fd83355SJason Molenda #include "lldb/Target/Process.h" 32*2fd83355SJason Molenda #include "lldb/Target/Target.h" 33*2fd83355SJason Molenda #include "lldb/Target/Thread.h" 34*2fd83355SJason Molenda 35*2fd83355SJason Molenda using namespace lldb; 36*2fd83355SJason Molenda using namespace lldb_private; 37*2fd83355SJason Molenda 38*2fd83355SJason Molenda const char *AppleGetItemInfoHandler::g_get_item_info_function_name = "__lldb_backtrace_recording_get_item_info"; 39*2fd83355SJason Molenda const char *AppleGetItemInfoHandler::g_get_item_info_function_code = " \n\ 40*2fd83355SJason Molenda extern \"C\" \n\ 41*2fd83355SJason Molenda { \n\ 42*2fd83355SJason Molenda /* \n\ 43*2fd83355SJason Molenda * mach defines \n\ 44*2fd83355SJason Molenda */ \n\ 45*2fd83355SJason Molenda \n\ 46*2fd83355SJason Molenda typedef unsigned int uint32_t; \n\ 47*2fd83355SJason Molenda typedef unsigned long long uint64_t; \n\ 48*2fd83355SJason Molenda typedef uint32_t mach_port_t; \n\ 49*2fd83355SJason Molenda typedef mach_port_t vm_map_t; \n\ 50*2fd83355SJason Molenda typedef int kern_return_t; \n\ 51*2fd83355SJason Molenda typedef uint64_t mach_vm_address_t; \n\ 52*2fd83355SJason Molenda typedef uint64_t mach_vm_size_t; \n\ 53*2fd83355SJason Molenda \n\ 54*2fd83355SJason Molenda mach_port_t mach_task_self (); \n\ 55*2fd83355SJason Molenda kern_return_t mach_vm_deallocate (vm_map_t target, mach_vm_address_t address, mach_vm_size_t size); \n\ 56*2fd83355SJason Molenda \n\ 57*2fd83355SJason Molenda /* \n\ 58*2fd83355SJason Molenda * libBacktraceRecording defines \n\ 59*2fd83355SJason Molenda */ \n\ 60*2fd83355SJason Molenda \n\ 61*2fd83355SJason Molenda typedef uint32_t queue_list_scope_t; \n\ 62*2fd83355SJason Molenda typedef void *dispatch_queue_t; \n\ 63*2fd83355SJason Molenda typedef void *introspection_dispatch_queue_info_t; \n\ 64*2fd83355SJason Molenda typedef void *introspection_dispatch_item_info_ref; \n\ 65*2fd83355SJason Molenda \n\ 66*2fd83355SJason Molenda extern uint64_t __introspection_dispatch_queue_item_get_info (introspection_dispatch_item_info_ref item_info_ref, \n\ 67*2fd83355SJason Molenda introspection_dispatch_item_info_ref *returned_queues_buffer, \n\ 68*2fd83355SJason Molenda uint64_t *returned_queues_buffer_size); \n\ 69*2fd83355SJason Molenda extern int printf(const char *format, ...); \n\ 70*2fd83355SJason Molenda \n\ 71*2fd83355SJason Molenda /* \n\ 72*2fd83355SJason Molenda * return type define \n\ 73*2fd83355SJason Molenda */ \n\ 74*2fd83355SJason Molenda \n\ 75*2fd83355SJason Molenda struct get_item_info_return_values \n\ 76*2fd83355SJason Molenda { \n\ 77*2fd83355SJason Molenda uint64_t item_info_buffer_ptr; /* the address of the items buffer from libBacktraceRecording */ \n\ 78*2fd83355SJason Molenda uint64_t item_info_buffer_size; /* the size of the items buffer from libBacktraceRecording */ \n\ 79*2fd83355SJason Molenda }; \n\ 80*2fd83355SJason Molenda \n\ 81*2fd83355SJason Molenda void __lldb_backtrace_recording_get_item_info \n\ 82*2fd83355SJason Molenda (struct get_item_info_return_values *return_buffer, \n\ 83*2fd83355SJason Molenda int debug, \n\ 84*2fd83355SJason Molenda uint64_t /* introspection_dispatch_item_info_ref item_info_ref */ item, \n\ 85*2fd83355SJason Molenda void *page_to_free, \n\ 86*2fd83355SJason Molenda uint64_t page_to_free_size) \n\ 87*2fd83355SJason Molenda { \n\ 88*2fd83355SJason Molenda if (debug) \n\ 89*2fd83355SJason Molenda printf (\"entering get_item_info with args return_buffer == %p, debug == %d, item == 0x%llx, page_to_free == %p, page_to_free_size == 0x%llx\\n\", return_buffer, debug, item, page_to_free, page_to_free_size); \n\ 90*2fd83355SJason Molenda if (page_to_free != 0) \n\ 91*2fd83355SJason Molenda { \n\ 92*2fd83355SJason Molenda mach_vm_deallocate (mach_task_self(), (mach_vm_address_t) page_to_free, (mach_vm_size_t) page_to_free_size); \n\ 93*2fd83355SJason Molenda } \n\ 94*2fd83355SJason Molenda \n\ 95*2fd83355SJason Molenda __introspection_dispatch_queue_item_get_info ((void*) item, \n\ 96*2fd83355SJason Molenda (void**)&return_buffer->item_info_buffer_ptr, \n\ 97*2fd83355SJason Molenda &return_buffer->item_info_buffer_size); \n\ 98*2fd83355SJason Molenda } \n\ 99*2fd83355SJason Molenda } \n\ 100*2fd83355SJason Molenda "; 101*2fd83355SJason Molenda 102*2fd83355SJason Molenda AppleGetItemInfoHandler::AppleGetItemInfoHandler (Process *process) : 103*2fd83355SJason Molenda m_process (process), 104*2fd83355SJason Molenda m_get_item_info_function (), 105*2fd83355SJason Molenda m_get_item_info_impl_code (), 106*2fd83355SJason Molenda m_get_item_info_function_mutex(), 107*2fd83355SJason Molenda m_get_item_info_return_buffer_addr (LLDB_INVALID_ADDRESS), 108*2fd83355SJason Molenda m_get_item_info_retbuffer_mutex() 109*2fd83355SJason Molenda { 110*2fd83355SJason Molenda } 111*2fd83355SJason Molenda 112*2fd83355SJason Molenda AppleGetItemInfoHandler::~AppleGetItemInfoHandler () 113*2fd83355SJason Molenda { 114*2fd83355SJason Molenda } 115*2fd83355SJason Molenda 116*2fd83355SJason Molenda void 117*2fd83355SJason Molenda AppleGetItemInfoHandler::Detach () 118*2fd83355SJason Molenda { 119*2fd83355SJason Molenda 120*2fd83355SJason Molenda if (m_process && m_process->IsAlive() && m_get_item_info_return_buffer_addr != LLDB_INVALID_ADDRESS) 121*2fd83355SJason Molenda { 122*2fd83355SJason Molenda Mutex::Locker locker; 123*2fd83355SJason Molenda locker.TryLock (m_get_item_info_retbuffer_mutex); // Even if we don't get the lock, deallocate the buffer 124*2fd83355SJason Molenda m_process->DeallocateMemory (m_get_item_info_return_buffer_addr); 125*2fd83355SJason Molenda } 126*2fd83355SJason Molenda } 127*2fd83355SJason Molenda 128*2fd83355SJason Molenda // Compile our __lldb_backtrace_recording_get_item_info() function (from the 129*2fd83355SJason Molenda // source above in g_get_item_info_function_code) if we don't find that function in the inferior 130*2fd83355SJason Molenda // already with USE_BUILTIN_FUNCTION defined. (e.g. this would be the case for testing.) 131*2fd83355SJason Molenda // 132*2fd83355SJason Molenda // Insert the __lldb_backtrace_recording_get_item_info into the inferior process if needed. 133*2fd83355SJason Molenda // 134*2fd83355SJason Molenda // Write the get_item_info_arglist into the inferior's memory space to prepare for the call. 135*2fd83355SJason Molenda // 136*2fd83355SJason Molenda // Returns the address of the arguments written down in the inferior process, which can be used to 137*2fd83355SJason Molenda // make the function call. 138*2fd83355SJason Molenda 139*2fd83355SJason Molenda lldb::addr_t 140*2fd83355SJason Molenda AppleGetItemInfoHandler::SetupGetItemInfoFunction (Thread &thread, ValueList &get_item_info_arglist) 141*2fd83355SJason Molenda { 142*2fd83355SJason Molenda ExecutionContext exe_ctx (thread.shared_from_this()); 143*2fd83355SJason Molenda Address impl_code_address; 144*2fd83355SJason Molenda StreamString errors; 145*2fd83355SJason Molenda Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_SYSTEM_RUNTIME)); 146*2fd83355SJason Molenda lldb::addr_t args_addr = LLDB_INVALID_ADDRESS; 147*2fd83355SJason Molenda 148*2fd83355SJason Molenda // Scope for mutex locker: 149*2fd83355SJason Molenda { 150*2fd83355SJason Molenda Mutex::Locker locker(m_get_item_info_function_mutex); 151*2fd83355SJason Molenda 152*2fd83355SJason Molenda // First stage is to make the ClangUtility to hold our injected function: 153*2fd83355SJason Molenda 154*2fd83355SJason Molenda #define USE_BUILTIN_FUNCTION 0 // Define this to 1 and we will use the get_implementation function found in the target. 155*2fd83355SJason Molenda // This is useful for debugging additions to the get_impl function 'cause you don't have 156*2fd83355SJason Molenda // to bother with string-ifying the code into g_get_item_info_function_code. 157*2fd83355SJason Molenda 158*2fd83355SJason Molenda if (USE_BUILTIN_FUNCTION) 159*2fd83355SJason Molenda { 160*2fd83355SJason Molenda ConstString our_utility_function_name("__lldb_backtrace_recording_get_item_info"); 161*2fd83355SJason Molenda SymbolContextList sc_list; 162*2fd83355SJason Molenda 163*2fd83355SJason Molenda exe_ctx.GetTargetRef().GetImages().FindSymbolsWithNameAndType (our_utility_function_name, eSymbolTypeCode, sc_list); 164*2fd83355SJason Molenda if (sc_list.GetSize() == 1) 165*2fd83355SJason Molenda { 166*2fd83355SJason Molenda SymbolContext sc; 167*2fd83355SJason Molenda sc_list.GetContextAtIndex(0, sc); 168*2fd83355SJason Molenda if (sc.symbol != NULL) 169*2fd83355SJason Molenda impl_code_address = sc.symbol->GetAddress(); 170*2fd83355SJason Molenda 171*2fd83355SJason Molenda //lldb::addr_t addr = impl_code_address.GetOpcodeLoadAddress (exe_ctx.GetTargetPtr()); 172*2fd83355SJason Molenda //printf ("Getting address for our_utility_function: 0x%" PRIx64 ".\n", addr); 173*2fd83355SJason Molenda } 174*2fd83355SJason Molenda else 175*2fd83355SJason Molenda { 176*2fd83355SJason Molenda //printf ("Could not find queues introspection function address.\n"); 177*2fd83355SJason Molenda return args_addr; 178*2fd83355SJason Molenda } 179*2fd83355SJason Molenda } 180*2fd83355SJason Molenda else if (!m_get_item_info_impl_code.get()) 181*2fd83355SJason Molenda { 182*2fd83355SJason Molenda if (g_get_item_info_function_code != NULL) 183*2fd83355SJason Molenda { 184*2fd83355SJason Molenda m_get_item_info_impl_code.reset (new ClangUtilityFunction (g_get_item_info_function_code, 185*2fd83355SJason Molenda g_get_item_info_function_name)); 186*2fd83355SJason Molenda if (!m_get_item_info_impl_code->Install(errors, exe_ctx)) 187*2fd83355SJason Molenda { 188*2fd83355SJason Molenda if (log) 189*2fd83355SJason Molenda log->Printf ("Failed to install get-item-info introspection: %s.", errors.GetData()); 190*2fd83355SJason Molenda m_get_item_info_impl_code.reset(); 191*2fd83355SJason Molenda return args_addr; 192*2fd83355SJason Molenda } 193*2fd83355SJason Molenda } 194*2fd83355SJason Molenda else 195*2fd83355SJason Molenda { 196*2fd83355SJason Molenda if (log) 197*2fd83355SJason Molenda log->Printf("No get-item-info introspection code found."); 198*2fd83355SJason Molenda errors.Printf ("No get-item-info introspection code found."); 199*2fd83355SJason Molenda return LLDB_INVALID_ADDRESS; 200*2fd83355SJason Molenda } 201*2fd83355SJason Molenda 202*2fd83355SJason Molenda impl_code_address.Clear(); 203*2fd83355SJason Molenda impl_code_address.SetOffset(m_get_item_info_impl_code->StartAddress()); 204*2fd83355SJason Molenda } 205*2fd83355SJason Molenda else 206*2fd83355SJason Molenda { 207*2fd83355SJason Molenda impl_code_address.Clear(); 208*2fd83355SJason Molenda impl_code_address.SetOffset(m_get_item_info_impl_code->StartAddress()); 209*2fd83355SJason Molenda } 210*2fd83355SJason Molenda 211*2fd83355SJason Molenda // Next make the runner function for our implementation utility function. 212*2fd83355SJason Molenda if (!m_get_item_info_function.get()) 213*2fd83355SJason Molenda { 214*2fd83355SJason Molenda ClangASTContext *clang_ast_context = thread.GetProcess()->GetTarget().GetScratchClangASTContext(); 215*2fd83355SJason Molenda ClangASTType get_item_info_return_type = clang_ast_context->GetBasicType(eBasicTypeVoid).GetPointerType(); 216*2fd83355SJason Molenda m_get_item_info_function.reset(new ClangFunction (thread, 217*2fd83355SJason Molenda get_item_info_return_type, 218*2fd83355SJason Molenda impl_code_address, 219*2fd83355SJason Molenda get_item_info_arglist)); 220*2fd83355SJason Molenda 221*2fd83355SJason Molenda errors.Clear(); 222*2fd83355SJason Molenda unsigned num_errors = m_get_item_info_function->CompileFunction(errors); 223*2fd83355SJason Molenda if (num_errors) 224*2fd83355SJason Molenda { 225*2fd83355SJason Molenda if (log) 226*2fd83355SJason Molenda log->Printf ("Error compiling get-item-info function: \"%s\".", errors.GetData()); 227*2fd83355SJason Molenda return args_addr; 228*2fd83355SJason Molenda } 229*2fd83355SJason Molenda 230*2fd83355SJason Molenda errors.Clear(); 231*2fd83355SJason Molenda if (!m_get_item_info_function->WriteFunctionWrapper(exe_ctx, errors)) 232*2fd83355SJason Molenda { 233*2fd83355SJason Molenda if (log) 234*2fd83355SJason Molenda log->Printf ("Error Inserting get-item-info function: \"%s\".", errors.GetData()); 235*2fd83355SJason Molenda return args_addr; 236*2fd83355SJason Molenda } 237*2fd83355SJason Molenda } 238*2fd83355SJason Molenda } 239*2fd83355SJason Molenda 240*2fd83355SJason Molenda errors.Clear(); 241*2fd83355SJason Molenda 242*2fd83355SJason Molenda // Now write down the argument values for this particular call. This looks like it might be a race condition 243*2fd83355SJason Molenda // if other threads were calling into here, but actually it isn't because we allocate a new args structure for 244*2fd83355SJason Molenda // this call by passing args_addr = LLDB_INVALID_ADDRESS... 245*2fd83355SJason Molenda 246*2fd83355SJason Molenda if (!m_get_item_info_function->WriteFunctionArguments (exe_ctx, args_addr, impl_code_address, get_item_info_arglist, errors)) 247*2fd83355SJason Molenda { 248*2fd83355SJason Molenda if (log) 249*2fd83355SJason Molenda log->Printf ("Error writing get-item-info function arguments: \"%s\".", errors.GetData()); 250*2fd83355SJason Molenda return args_addr; 251*2fd83355SJason Molenda } 252*2fd83355SJason Molenda 253*2fd83355SJason Molenda return args_addr; 254*2fd83355SJason Molenda } 255*2fd83355SJason Molenda 256*2fd83355SJason Molenda AppleGetItemInfoHandler::GetItemInfoReturnInfo 257*2fd83355SJason Molenda AppleGetItemInfoHandler::GetItemInfo (Thread &thread, uint64_t item, addr_t page_to_free, uint64_t page_to_free_size, Error &error) 258*2fd83355SJason Molenda { 259*2fd83355SJason Molenda lldb::StackFrameSP thread_cur_frame = thread.GetStackFrameAtIndex(0); 260*2fd83355SJason Molenda ProcessSP process_sp (thread.CalculateProcess()); 261*2fd83355SJason Molenda TargetSP target_sp (thread.CalculateTarget()); 262*2fd83355SJason Molenda ClangASTContext *clang_ast_context = target_sp->GetScratchClangASTContext(); 263*2fd83355SJason Molenda Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_SYSTEM_RUNTIME)); 264*2fd83355SJason Molenda 265*2fd83355SJason Molenda GetItemInfoReturnInfo return_value; 266*2fd83355SJason Molenda return_value.item_buffer_ptr = LLDB_INVALID_ADDRESS; 267*2fd83355SJason Molenda return_value.item_buffer_size = 0; 268*2fd83355SJason Molenda 269*2fd83355SJason Molenda error.Clear(); 270*2fd83355SJason Molenda 271*2fd83355SJason Molenda // Set up the arguments for a call to 272*2fd83355SJason Molenda 273*2fd83355SJason Molenda // struct get_item_info_return_values 274*2fd83355SJason Molenda // { 275*2fd83355SJason Molenda // uint64_t item_info_buffer_ptr; /* the address of the items buffer from libBacktraceRecording */ 276*2fd83355SJason Molenda // uint64_t item_info_buffer_size; /* the size of the items buffer from libBacktraceRecording */ 277*2fd83355SJason Molenda // }; 278*2fd83355SJason Molenda // 279*2fd83355SJason Molenda // void __lldb_backtrace_recording_get_item_info 280*2fd83355SJason Molenda // (struct get_item_info_return_values *return_buffer, 281*2fd83355SJason Molenda // int debug, 282*2fd83355SJason Molenda // uint64_t item, 283*2fd83355SJason Molenda // void *page_to_free, 284*2fd83355SJason Molenda // uint64_t page_to_free_size) 285*2fd83355SJason Molenda 286*2fd83355SJason Molenda // Where the return_buffer argument points to a 24 byte region of memory already allocated by lldb in 287*2fd83355SJason Molenda // the inferior process. 288*2fd83355SJason Molenda 289*2fd83355SJason Molenda ClangASTType clang_void_ptr_type = clang_ast_context->GetBasicType(eBasicTypeVoid).GetPointerType(); 290*2fd83355SJason Molenda Value return_buffer_ptr_value; 291*2fd83355SJason Molenda return_buffer_ptr_value.SetValueType (Value::eValueTypeScalar); 292*2fd83355SJason Molenda return_buffer_ptr_value.SetClangType (clang_void_ptr_type); 293*2fd83355SJason Molenda 294*2fd83355SJason Molenda ClangASTType clang_int_type = clang_ast_context->GetBasicType(eBasicTypeInt); 295*2fd83355SJason Molenda Value debug_value; 296*2fd83355SJason Molenda debug_value.SetValueType (Value::eValueTypeScalar); 297*2fd83355SJason Molenda debug_value.SetClangType (clang_int_type); 298*2fd83355SJason Molenda 299*2fd83355SJason Molenda ClangASTType clang_uint64_type = clang_ast_context->GetBasicType(eBasicTypeUnsignedLongLong); 300*2fd83355SJason Molenda Value item_value; 301*2fd83355SJason Molenda item_value.SetValueType (Value::eValueTypeScalar); 302*2fd83355SJason Molenda item_value.SetClangType (clang_uint64_type); 303*2fd83355SJason Molenda 304*2fd83355SJason Molenda Value page_to_free_value; 305*2fd83355SJason Molenda page_to_free_value.SetValueType (Value::eValueTypeScalar); 306*2fd83355SJason Molenda page_to_free_value.SetClangType (clang_void_ptr_type); 307*2fd83355SJason Molenda 308*2fd83355SJason Molenda Value page_to_free_size_value; 309*2fd83355SJason Molenda page_to_free_size_value.SetValueType (Value::eValueTypeScalar); 310*2fd83355SJason Molenda page_to_free_size_value.SetClangType (clang_uint64_type); 311*2fd83355SJason Molenda 312*2fd83355SJason Molenda 313*2fd83355SJason Molenda Mutex::Locker locker(m_get_item_info_retbuffer_mutex); 314*2fd83355SJason Molenda if (m_get_item_info_return_buffer_addr == LLDB_INVALID_ADDRESS) 315*2fd83355SJason Molenda { 316*2fd83355SJason Molenda addr_t bufaddr = process_sp->AllocateMemory (32, ePermissionsReadable | ePermissionsWritable, error); 317*2fd83355SJason Molenda if (!error.Success() || bufaddr == LLDB_INVALID_ADDRESS) 318*2fd83355SJason Molenda { 319*2fd83355SJason Molenda if (log) 320*2fd83355SJason Molenda log->Printf ("Failed to allocate memory for return buffer for get current queues func call"); 321*2fd83355SJason Molenda return return_value; 322*2fd83355SJason Molenda } 323*2fd83355SJason Molenda m_get_item_info_return_buffer_addr = bufaddr; 324*2fd83355SJason Molenda } 325*2fd83355SJason Molenda 326*2fd83355SJason Molenda ValueList argument_values; 327*2fd83355SJason Molenda 328*2fd83355SJason Molenda return_buffer_ptr_value.GetScalar() = m_get_item_info_return_buffer_addr; 329*2fd83355SJason Molenda argument_values.PushValue (return_buffer_ptr_value); 330*2fd83355SJason Molenda 331*2fd83355SJason Molenda debug_value.GetScalar() = 0; 332*2fd83355SJason Molenda argument_values.PushValue (debug_value); 333*2fd83355SJason Molenda 334*2fd83355SJason Molenda item_value.GetScalar() = item; 335*2fd83355SJason Molenda argument_values.PushValue (item_value); 336*2fd83355SJason Molenda 337*2fd83355SJason Molenda if (page_to_free != LLDB_INVALID_ADDRESS) 338*2fd83355SJason Molenda page_to_free_value.GetScalar() = page_to_free; 339*2fd83355SJason Molenda else 340*2fd83355SJason Molenda page_to_free_value.GetScalar() = 0; 341*2fd83355SJason Molenda argument_values.PushValue (page_to_free_value); 342*2fd83355SJason Molenda 343*2fd83355SJason Molenda page_to_free_size_value.GetScalar() = page_to_free_size; 344*2fd83355SJason Molenda argument_values.PushValue (page_to_free_size_value); 345*2fd83355SJason Molenda 346*2fd83355SJason Molenda addr_t args_addr = SetupGetItemInfoFunction (thread, argument_values); 347*2fd83355SJason Molenda 348*2fd83355SJason Molenda StreamString errors; 349*2fd83355SJason Molenda ExecutionContext exe_ctx; 350*2fd83355SJason Molenda EvaluateExpressionOptions options; 351*2fd83355SJason Molenda options.SetUnwindOnError (true); 352*2fd83355SJason Molenda options.SetIgnoreBreakpoints (true); 353*2fd83355SJason Molenda options.SetStopOthers (true); 354*2fd83355SJason Molenda thread.CalculateExecutionContext (exe_ctx); 355*2fd83355SJason Molenda 356*2fd83355SJason Molenda if (m_get_item_info_function == NULL) 357*2fd83355SJason Molenda { 358*2fd83355SJason Molenda error.SetErrorString ("Unable to compile function to call __introspection_dispatch_queue_item_get_info"); 359*2fd83355SJason Molenda return return_value; 360*2fd83355SJason Molenda } 361*2fd83355SJason Molenda 362*2fd83355SJason Molenda 363*2fd83355SJason Molenda ExecutionResults func_call_ret; 364*2fd83355SJason Molenda Value results; 365*2fd83355SJason Molenda func_call_ret = m_get_item_info_function->ExecuteFunction (exe_ctx, &args_addr, options, errors, results); 366*2fd83355SJason Molenda if (func_call_ret != eExecutionCompleted || !error.Success()) 367*2fd83355SJason Molenda { 368*2fd83355SJason Molenda if (log) 369*2fd83355SJason Molenda log->Printf ("Unable to call __introspection_dispatch_queue_item_get_info(), got ExecutionResults %d, error contains %s", func_call_ret, error.AsCString("")); 370*2fd83355SJason Molenda error.SetErrorString ("Unable to call __introspection_dispatch_queue_get_item_info() for list of queues"); 371*2fd83355SJason Molenda return return_value; 372*2fd83355SJason Molenda } 373*2fd83355SJason Molenda 374*2fd83355SJason Molenda return_value.item_buffer_ptr = m_process->ReadUnsignedIntegerFromMemory (m_get_item_info_return_buffer_addr, 8, LLDB_INVALID_ADDRESS, error); 375*2fd83355SJason Molenda if (!error.Success() || return_value.item_buffer_ptr == LLDB_INVALID_ADDRESS) 376*2fd83355SJason Molenda { 377*2fd83355SJason Molenda return_value.item_buffer_ptr = LLDB_INVALID_ADDRESS; 378*2fd83355SJason Molenda return return_value; 379*2fd83355SJason Molenda } 380*2fd83355SJason Molenda 381*2fd83355SJason Molenda return_value.item_buffer_size = m_process->ReadUnsignedIntegerFromMemory (m_get_item_info_return_buffer_addr + 8, 8, 0, error); 382*2fd83355SJason Molenda 383*2fd83355SJason Molenda if (!error.Success()) 384*2fd83355SJason Molenda { 385*2fd83355SJason Molenda return_value.item_buffer_ptr = LLDB_INVALID_ADDRESS; 386*2fd83355SJason Molenda return return_value; 387*2fd83355SJason Molenda } 388*2fd83355SJason Molenda 389*2fd83355SJason Molenda return return_value; 390*2fd83355SJason Molenda } 391