| Kate Stone | b9c1b51 | 2016-09-06 20:57:50 +0000 | [diff] [blame] | 1 | //===-- AppleGetPendingItemsHandler.cpp -------------------------------*- C++ | 
|  | 2 | //-*-===// | 
| Jason Molenda | 2fd8335 | 2014-02-05 05:44:54 +0000 | [diff] [blame] | 3 | // | 
| Chandler Carruth | 2946cd7 | 2019-01-19 08:50:56 +0000 | [diff] [blame] | 4 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | 
|  | 5 | // See https://llvm.org/LICENSE.txt for license information. | 
|  | 6 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | 
| Jason Molenda | 2fd8335 | 2014-02-05 05:44:54 +0000 | [diff] [blame] | 7 | // | 
|  | 8 | //===----------------------------------------------------------------------===// | 
|  | 9 |  | 
|  | 10 | #include "AppleGetPendingItemsHandler.h" | 
|  | 11 |  | 
| Jason Molenda | 2fd8335 | 2014-02-05 05:44:54 +0000 | [diff] [blame] | 12 |  | 
| Jason Molenda | 2fd8335 | 2014-02-05 05:44:54 +0000 | [diff] [blame] | 13 | #include "lldb/Core/Module.h" | 
| Jason Molenda | 2fd8335 | 2014-02-05 05:44:54 +0000 | [diff] [blame] | 14 | #include "lldb/Core/Value.h" | 
| Sean Callanan | 579e70c | 2016-03-19 00:03:59 +0000 | [diff] [blame] | 15 | #include "lldb/Expression/DiagnosticManager.h" | 
| Jim Ingham | 151c032 | 2015-09-15 21:13:50 +0000 | [diff] [blame] | 16 | #include "lldb/Expression/FunctionCaller.h" | 
|  | 17 | #include "lldb/Expression/UtilityFunction.h" | 
| Jason Molenda | 2fd8335 | 2014-02-05 05:44:54 +0000 | [diff] [blame] | 18 | #include "lldb/Symbol/ClangASTContext.h" | 
|  | 19 | #include "lldb/Symbol/Symbol.h" | 
|  | 20 | #include "lldb/Target/ExecutionContext.h" | 
|  | 21 | #include "lldb/Target/Process.h" | 
|  | 22 | #include "lldb/Target/Target.h" | 
|  | 23 | #include "lldb/Target/Thread.h" | 
| Zachary Turner | bf9a773 | 2017-02-02 21:39:50 +0000 | [diff] [blame] | 24 | #include "lldb/Utility/ConstString.h" | 
| Zachary Turner | 6f9e690 | 2017-03-03 20:56:28 +0000 | [diff] [blame] | 25 | #include "lldb/Utility/Log.h" | 
| Zachary Turner | bf9a773 | 2017-02-02 21:39:50 +0000 | [diff] [blame] | 26 | #include "lldb/Utility/StreamString.h" | 
| Jason Molenda | 2fd8335 | 2014-02-05 05:44:54 +0000 | [diff] [blame] | 27 |  | 
|  | 28 | using namespace lldb; | 
|  | 29 | using namespace lldb_private; | 
|  | 30 |  | 
| Kate Stone | b9c1b51 | 2016-09-06 20:57:50 +0000 | [diff] [blame] | 31 | const char *AppleGetPendingItemsHandler::g_get_pending_items_function_name = | 
|  | 32 | "__lldb_backtrace_recording_get_pending_items"; | 
|  | 33 | const char *AppleGetPendingItemsHandler::g_get_pending_items_function_code = | 
|  | 34 | "                                  \n\ | 
| Jason Molenda | 2fd8335 | 2014-02-05 05:44:54 +0000 | [diff] [blame] | 35 | extern \"C\"                                                                                                    \n\ | 
|  | 36 | {                                                                                                               \n\ | 
|  | 37 | /*                                                                                                          \n\ | 
|  | 38 | * mach defines                                                                                             \n\ | 
|  | 39 | */                                                                                                         \n\ | 
|  | 40 | \n\ | 
|  | 41 | typedef unsigned int uint32_t;                                                                              \n\ | 
|  | 42 | typedef unsigned long long uint64_t;                                                                        \n\ | 
|  | 43 | typedef uint32_t mach_port_t;                                                                               \n\ | 
|  | 44 | typedef mach_port_t vm_map_t;                                                                               \n\ | 
|  | 45 | typedef int kern_return_t;                                                                                  \n\ | 
|  | 46 | typedef uint64_t mach_vm_address_t;                                                                         \n\ | 
|  | 47 | typedef uint64_t mach_vm_size_t;                                                                            \n\ | 
|  | 48 | \n\ | 
|  | 49 | mach_port_t mach_task_self ();                                                                              \n\ | 
|  | 50 | kern_return_t mach_vm_deallocate (vm_map_t target, mach_vm_address_t address, mach_vm_size_t size);         \n\ | 
|  | 51 | \n\ | 
|  | 52 | /*                                                                                                          \n\ | 
|  | 53 | * libBacktraceRecording defines                                                                            \n\ | 
|  | 54 | */                                                                                                         \n\ | 
|  | 55 | \n\ | 
|  | 56 | typedef uint32_t queue_list_scope_t;                                                                        \n\ | 
|  | 57 | typedef void *dispatch_queue_t;                                                                             \n\ | 
|  | 58 | typedef void *introspection_dispatch_queue_info_t;                                                          \n\ | 
|  | 59 | typedef void *introspection_dispatch_item_info_ref;                                                         \n\ | 
|  | 60 | \n\ | 
|  | 61 | extern uint64_t __introspection_dispatch_queue_get_pending_items (dispatch_queue_t queue,                   \n\ | 
|  | 62 | introspection_dispatch_item_info_ref *returned_queues_buffer,  \n\ | 
|  | 63 | uint64_t *returned_queues_buffer_size);                        \n\ | 
|  | 64 | extern int printf(const char *format, ...);                                                                 \n\ | 
|  | 65 | \n\ | 
|  | 66 | /*                                                                                                          \n\ | 
|  | 67 | * return type define                                                                                       \n\ | 
|  | 68 | */                                                                                                         \n\ | 
|  | 69 | \n\ | 
|  | 70 | struct get_pending_items_return_values                                                                      \n\ | 
|  | 71 | {                                                                                                           \n\ | 
|  | 72 | uint64_t pending_items_buffer_ptr;    /* the address of the items buffer from libBacktraceRecording */  \n\ | 
|  | 73 | uint64_t pending_items_buffer_size;   /* the size of the items buffer from libBacktraceRecording */     \n\ | 
|  | 74 | uint64_t count;                /* the number of items included in the queues buffer */                  \n\ | 
|  | 75 | };                                                                                                          \n\ | 
|  | 76 | \n\ | 
|  | 77 | void  __lldb_backtrace_recording_get_pending_items                                                          \n\ | 
|  | 78 | (struct get_pending_items_return_values *return_buffer,          \n\ | 
|  | 79 | int debug,                                                      \n\ | 
|  | 80 | uint64_t /* dispatch_queue_t */ queue,                          \n\ | 
|  | 81 | void *page_to_free,                                             \n\ | 
|  | 82 | uint64_t page_to_free_size)                                     \n\ | 
|  | 83 | {                                                                                                               \n\ | 
|  | 84 | if (debug)                                                                                                  \n\ | 
|  | 85 | printf (\"entering get_pending_items with args return_buffer == %p, debug == %d, queue == 0x%llx, page_to_free == %p, page_to_free_size == 0x%llx\\n\", return_buffer, debug, queue, page_to_free, page_to_free_size); \n\ | 
|  | 86 | if (page_to_free != 0)                                                                                      \n\ | 
|  | 87 | {                                                                                                           \n\ | 
|  | 88 | mach_vm_deallocate (mach_task_self(), (mach_vm_address_t) page_to_free, (mach_vm_size_t) page_to_free_size); \n\ | 
|  | 89 | }                                                                                                           \n\ | 
|  | 90 | \n\ | 
|  | 91 | return_buffer->count = __introspection_dispatch_queue_get_pending_items (                                   \n\ | 
|  | 92 | (void*) queue,                                            \n\ | 
|  | 93 | (void**)&return_buffer->pending_items_buffer_ptr,         \n\ | 
|  | 94 | &return_buffer->pending_items_buffer_size);               \n\ | 
|  | 95 | if (debug)                                                                                                  \n\ | 
|  | 96 | printf(\"result was count %lld\\n\", return_buffer->count);                                             \n\ | 
|  | 97 | }                                                                                                               \n\ | 
|  | 98 | }                                                                                                               \n\ | 
|  | 99 | "; | 
|  | 100 |  | 
| Saleem Abdulrasool | 16ff860 | 2016-05-18 01:59:10 +0000 | [diff] [blame] | 101 | AppleGetPendingItemsHandler::AppleGetPendingItemsHandler(Process *process) | 
| Kate Stone | b9c1b51 | 2016-09-06 20:57:50 +0000 | [diff] [blame] | 102 | : m_process(process), m_get_pending_items_impl_code(), | 
| Saleem Abdulrasool | 16ff860 | 2016-05-18 01:59:10 +0000 | [diff] [blame] | 103 | m_get_pending_items_function_mutex(), | 
|  | 104 | m_get_pending_items_return_buffer_addr(LLDB_INVALID_ADDRESS), | 
| Kate Stone | b9c1b51 | 2016-09-06 20:57:50 +0000 | [diff] [blame] | 105 | m_get_pending_items_retbuffer_mutex() {} | 
| Jason Molenda | 2fd8335 | 2014-02-05 05:44:54 +0000 | [diff] [blame] | 106 |  | 
| Kate Stone | b9c1b51 | 2016-09-06 20:57:50 +0000 | [diff] [blame] | 107 | AppleGetPendingItemsHandler::~AppleGetPendingItemsHandler() {} | 
| Jason Molenda | 2fd8335 | 2014-02-05 05:44:54 +0000 | [diff] [blame] | 108 |  | 
| Kate Stone | b9c1b51 | 2016-09-06 20:57:50 +0000 | [diff] [blame] | 109 | void AppleGetPendingItemsHandler::Detach() { | 
|  | 110 | if (m_process && m_process->IsAlive() && | 
|  | 111 | m_get_pending_items_return_buffer_addr != LLDB_INVALID_ADDRESS) { | 
|  | 112 | std::unique_lock<std::mutex> lock(m_get_pending_items_retbuffer_mutex, | 
|  | 113 | std::defer_lock); | 
|  | 114 | lock.try_lock(); // Even if we don't get the lock, deallocate the buffer | 
|  | 115 | m_process->DeallocateMemory(m_get_pending_items_return_buffer_addr); | 
|  | 116 | } | 
| Jason Molenda | 2fd8335 | 2014-02-05 05:44:54 +0000 | [diff] [blame] | 117 | } | 
|  | 118 |  | 
| Adrian Prantl | 0509724 | 2018-04-30 16:49:04 +0000 | [diff] [blame] | 119 | // Compile our __lldb_backtrace_recording_get_pending_items() function (from | 
|  | 120 | // the source above in g_get_pending_items_function_code) if we don't find that | 
|  | 121 | // function in the inferior already with USE_BUILTIN_FUNCTION defined.  (e.g. | 
|  | 122 | // this would be the case for testing.) | 
| Jason Molenda | 2fd8335 | 2014-02-05 05:44:54 +0000 | [diff] [blame] | 123 | // | 
| Kate Stone | b9c1b51 | 2016-09-06 20:57:50 +0000 | [diff] [blame] | 124 | // Insert the __lldb_backtrace_recording_get_pending_items into the inferior | 
|  | 125 | // process if needed. | 
| Jason Molenda | 2fd8335 | 2014-02-05 05:44:54 +0000 | [diff] [blame] | 126 | // | 
| Kate Stone | b9c1b51 | 2016-09-06 20:57:50 +0000 | [diff] [blame] | 127 | // Write the get_pending_items_arglist into the inferior's memory space to | 
|  | 128 | // prepare for the call. | 
|  | 129 | // | 
|  | 130 | // Returns the address of the arguments written down in the inferior process, | 
| Adrian Prantl | 0509724 | 2018-04-30 16:49:04 +0000 | [diff] [blame] | 131 | // which can be used to make the function call. | 
| Jason Molenda | 2fd8335 | 2014-02-05 05:44:54 +0000 | [diff] [blame] | 132 |  | 
| Kate Stone | b9c1b51 | 2016-09-06 20:57:50 +0000 | [diff] [blame] | 133 | lldb::addr_t AppleGetPendingItemsHandler::SetupGetPendingItemsFunction( | 
|  | 134 | Thread &thread, ValueList &get_pending_items_arglist) { | 
|  | 135 | ThreadSP thread_sp(thread.shared_from_this()); | 
|  | 136 | ExecutionContext exe_ctx(thread_sp); | 
|  | 137 | DiagnosticManager diagnostics; | 
|  | 138 | Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_SYSTEM_RUNTIME)); | 
| Jim Ingham | 6896b35 | 2016-03-21 19:21:13 +0000 | [diff] [blame] | 139 |  | 
| Kate Stone | b9c1b51 | 2016-09-06 20:57:50 +0000 | [diff] [blame] | 140 | lldb::addr_t args_addr = LLDB_INVALID_ADDRESS; | 
|  | 141 | FunctionCaller *get_pending_items_caller = nullptr; | 
| Sean Callanan | 579e70c | 2016-03-19 00:03:59 +0000 | [diff] [blame] | 142 |  | 
| Kate Stone | b9c1b51 | 2016-09-06 20:57:50 +0000 | [diff] [blame] | 143 | // Scope for mutex locker: | 
|  | 144 | { | 
|  | 145 | std::lock_guard<std::mutex> guard(m_get_pending_items_function_mutex); | 
| Saleem Abdulrasool | 16ff860 | 2016-05-18 01:59:10 +0000 | [diff] [blame] | 146 |  | 
| Kate Stone | b9c1b51 | 2016-09-06 20:57:50 +0000 | [diff] [blame] | 147 | // First stage is to make the ClangUtility to hold our injected function: | 
| Jason Molenda | 2fd8335 | 2014-02-05 05:44:54 +0000 | [diff] [blame] | 148 |  | 
| Jonas Devlieghere | 70355ac | 2019-02-12 03:47:39 +0000 | [diff] [blame] | 149 | if (!m_get_pending_items_impl_code) { | 
| Konrad Kleine | 248a130 | 2019-05-23 11:14:47 +0000 | [diff] [blame^] | 150 | if (g_get_pending_items_function_code != nullptr) { | 
| Zachary Turner | 97206d5 | 2017-05-12 04:51:55 +0000 | [diff] [blame] | 151 | Status error; | 
| Kate Stone | b9c1b51 | 2016-09-06 20:57:50 +0000 | [diff] [blame] | 152 | m_get_pending_items_impl_code.reset( | 
|  | 153 | exe_ctx.GetTargetRef().GetUtilityFunctionForLanguage( | 
|  | 154 | g_get_pending_items_function_code, eLanguageTypeObjC, | 
|  | 155 | g_get_pending_items_function_name, error)); | 
|  | 156 | if (error.Fail()) { | 
|  | 157 | if (log) | 
|  | 158 | log->Printf("Failed to get UtilityFunction for pending-items " | 
|  | 159 | "introspection: %s.", | 
|  | 160 | error.AsCString()); | 
|  | 161 | return args_addr; | 
| Jason Molenda | 2fd8335 | 2014-02-05 05:44:54 +0000 | [diff] [blame] | 162 | } | 
| Sean Callanan | 579e70c | 2016-03-19 00:03:59 +0000 | [diff] [blame] | 163 |  | 
| Kate Stone | b9c1b51 | 2016-09-06 20:57:50 +0000 | [diff] [blame] | 164 | if (!m_get_pending_items_impl_code->Install(diagnostics, exe_ctx)) { | 
|  | 165 | if (log) { | 
|  | 166 | log->Printf("Failed to install pending-items introspection."); | 
| Sean Callanan | 579e70c | 2016-03-19 00:03:59 +0000 | [diff] [blame] | 167 | diagnostics.Dump(log); | 
| Kate Stone | b9c1b51 | 2016-09-06 20:57:50 +0000 | [diff] [blame] | 168 | } | 
|  | 169 | m_get_pending_items_impl_code.reset(); | 
|  | 170 | return args_addr; | 
| Sean Callanan | 579e70c | 2016-03-19 00:03:59 +0000 | [diff] [blame] | 171 | } | 
| Kate Stone | b9c1b51 | 2016-09-06 20:57:50 +0000 | [diff] [blame] | 172 | } else { | 
|  | 173 | if (log) | 
|  | 174 | log->Printf("No pending-items introspection code found."); | 
|  | 175 | return LLDB_INVALID_ADDRESS; | 
|  | 176 | } | 
| Sean Callanan | 579e70c | 2016-03-19 00:03:59 +0000 | [diff] [blame] | 177 |  | 
| Kate Stone | b9c1b51 | 2016-09-06 20:57:50 +0000 | [diff] [blame] | 178 | // Next make the runner function for our implementation utility function. | 
| Zachary Turner | 97206d5 | 2017-05-12 04:51:55 +0000 | [diff] [blame] | 179 | Status error; | 
| Kate Stone | b9c1b51 | 2016-09-06 20:57:50 +0000 | [diff] [blame] | 180 | ClangASTContext *clang_ast_context = | 
|  | 181 | thread.GetProcess()->GetTarget().GetScratchClangASTContext(); | 
|  | 182 | CompilerType get_pending_items_return_type = | 
|  | 183 | clang_ast_context->GetBasicType(eBasicTypeVoid).GetPointerType(); | 
|  | 184 | get_pending_items_caller = | 
|  | 185 | m_get_pending_items_impl_code->MakeFunctionCaller( | 
|  | 186 | get_pending_items_return_type, get_pending_items_arglist, | 
|  | 187 | thread_sp, error); | 
| Jason Molenda | ed2977f | 2016-10-27 23:52:46 +0000 | [diff] [blame] | 188 | if (error.Fail() || get_pending_items_caller == nullptr) { | 
| Kate Stone | b9c1b51 | 2016-09-06 20:57:50 +0000 | [diff] [blame] | 189 | if (log) | 
|  | 190 | log->Printf("Failed to install pending-items introspection function " | 
|  | 191 | "caller: %s.", | 
|  | 192 | error.AsCString()); | 
|  | 193 | m_get_pending_items_impl_code.reset(); | 
| Jason Molenda | 2fd8335 | 2014-02-05 05:44:54 +0000 | [diff] [blame] | 194 | return args_addr; | 
| Kate Stone | b9c1b51 | 2016-09-06 20:57:50 +0000 | [diff] [blame] | 195 | } | 
|  | 196 | } | 
|  | 197 | } | 
|  | 198 |  | 
|  | 199 | diagnostics.Clear(); | 
|  | 200 |  | 
|  | 201 | if (get_pending_items_caller == nullptr) { | 
|  | 202 | if (log) | 
|  | 203 | log->Printf("Failed to get get_pending_items_caller."); | 
|  | 204 | return LLDB_INVALID_ADDRESS; | 
|  | 205 | } | 
|  | 206 |  | 
|  | 207 | // Now write down the argument values for this particular call.  This looks | 
| Adrian Prantl | 0509724 | 2018-04-30 16:49:04 +0000 | [diff] [blame] | 208 | // like it might be a race condition if other threads were calling into here, | 
|  | 209 | // but actually it isn't because we allocate a new args structure for this | 
|  | 210 | // call by passing args_addr = LLDB_INVALID_ADDRESS... | 
| Kate Stone | b9c1b51 | 2016-09-06 20:57:50 +0000 | [diff] [blame] | 211 |  | 
|  | 212 | if (!get_pending_items_caller->WriteFunctionArguments( | 
|  | 213 | exe_ctx, args_addr, get_pending_items_arglist, diagnostics)) { | 
|  | 214 | if (log) { | 
|  | 215 | log->Printf("Error writing pending-items function arguments."); | 
|  | 216 | diagnostics.Dump(log); | 
| Jason Molenda | 2fd8335 | 2014-02-05 05:44:54 +0000 | [diff] [blame] | 217 | } | 
| Sean Callanan | 579e70c | 2016-03-19 00:03:59 +0000 | [diff] [blame] | 218 |  | 
| Jason Molenda | 2fd8335 | 2014-02-05 05:44:54 +0000 | [diff] [blame] | 219 | return args_addr; | 
| Kate Stone | b9c1b51 | 2016-09-06 20:57:50 +0000 | [diff] [blame] | 220 | } | 
|  | 221 |  | 
|  | 222 | return args_addr; | 
| Jason Molenda | 2fd8335 | 2014-02-05 05:44:54 +0000 | [diff] [blame] | 223 | } | 
|  | 224 |  | 
|  | 225 | AppleGetPendingItemsHandler::GetPendingItemsReturnInfo | 
| Kate Stone | b9c1b51 | 2016-09-06 20:57:50 +0000 | [diff] [blame] | 226 | AppleGetPendingItemsHandler::GetPendingItems(Thread &thread, addr_t queue, | 
|  | 227 | addr_t page_to_free, | 
|  | 228 | uint64_t page_to_free_size, | 
| Zachary Turner | 97206d5 | 2017-05-12 04:51:55 +0000 | [diff] [blame] | 229 | Status &error) { | 
| Kate Stone | b9c1b51 | 2016-09-06 20:57:50 +0000 | [diff] [blame] | 230 | lldb::StackFrameSP thread_cur_frame = thread.GetStackFrameAtIndex(0); | 
|  | 231 | ProcessSP process_sp(thread.CalculateProcess()); | 
|  | 232 | TargetSP target_sp(thread.CalculateTarget()); | 
|  | 233 | ClangASTContext *clang_ast_context = target_sp->GetScratchClangASTContext(); | 
|  | 234 | Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_SYSTEM_RUNTIME)); | 
| Jason Molenda | 2fd8335 | 2014-02-05 05:44:54 +0000 | [diff] [blame] | 235 |  | 
| Kate Stone | b9c1b51 | 2016-09-06 20:57:50 +0000 | [diff] [blame] | 236 | GetPendingItemsReturnInfo return_value; | 
|  | 237 | return_value.items_buffer_ptr = LLDB_INVALID_ADDRESS; | 
|  | 238 | return_value.items_buffer_size = 0; | 
|  | 239 | return_value.count = 0; | 
| Jason Molenda | 2fd8335 | 2014-02-05 05:44:54 +0000 | [diff] [blame] | 240 |  | 
| Kate Stone | b9c1b51 | 2016-09-06 20:57:50 +0000 | [diff] [blame] | 241 | error.Clear(); | 
| Jason Molenda | 2fd8335 | 2014-02-05 05:44:54 +0000 | [diff] [blame] | 242 |  | 
| Jonas Devlieghere | a6682a4 | 2018-12-15 00:15:33 +0000 | [diff] [blame] | 243 | if (!thread.SafeToCallFunctions()) { | 
| Jason Molenda | 2a6c252 | 2014-02-15 00:20:40 +0000 | [diff] [blame] | 244 | if (log) | 
| Kate Stone | b9c1b51 | 2016-09-06 20:57:50 +0000 | [diff] [blame] | 245 | log->Printf("Not safe to call functions on thread 0x%" PRIx64, | 
|  | 246 | thread.GetID()); | 
|  | 247 | error.SetErrorString("Not safe to call functions on this thread."); | 
| Jason Molenda | 2fd8335 | 2014-02-05 05:44:54 +0000 | [diff] [blame] | 248 | return return_value; | 
| Kate Stone | b9c1b51 | 2016-09-06 20:57:50 +0000 | [diff] [blame] | 249 | } | 
|  | 250 |  | 
|  | 251 | // Set up the arguments for a call to | 
|  | 252 |  | 
|  | 253 | // struct get_pending_items_return_values | 
|  | 254 | // { | 
|  | 255 | //     uint64_t pending_items_buffer_ptr;    /* the address of the items | 
|  | 256 | //     buffer from libBacktraceRecording */ | 
|  | 257 | //     uint64_t pending_items_buffer_size;   /* the size of the items buffer | 
|  | 258 | //     from libBacktraceRecording */ | 
|  | 259 | //     uint64_t count;                /* the number of items included in the | 
|  | 260 | //     queues buffer */ | 
|  | 261 | // }; | 
|  | 262 | // | 
|  | 263 | // void  __lldb_backtrace_recording_get_pending_items | 
|  | 264 | //                                            (struct | 
|  | 265 | //                                            get_pending_items_return_values | 
|  | 266 | //                                            *return_buffer, | 
|  | 267 | //                                             int debug, | 
|  | 268 | //                                             uint64_t /* dispatch_queue_t */ | 
|  | 269 | //                                             queue | 
|  | 270 | //                                             void *page_to_free, | 
|  | 271 | //                                             uint64_t page_to_free_size) | 
|  | 272 |  | 
|  | 273 | // Where the return_buffer argument points to a 24 byte region of memory | 
| Adrian Prantl | 0509724 | 2018-04-30 16:49:04 +0000 | [diff] [blame] | 274 | // already allocated by lldb in the inferior process. | 
| Kate Stone | b9c1b51 | 2016-09-06 20:57:50 +0000 | [diff] [blame] | 275 |  | 
|  | 276 | CompilerType clang_void_ptr_type = | 
|  | 277 | clang_ast_context->GetBasicType(eBasicTypeVoid).GetPointerType(); | 
|  | 278 | Value return_buffer_ptr_value; | 
|  | 279 | return_buffer_ptr_value.SetValueType(Value::eValueTypeScalar); | 
|  | 280 | return_buffer_ptr_value.SetCompilerType(clang_void_ptr_type); | 
|  | 281 |  | 
|  | 282 | CompilerType clang_int_type = clang_ast_context->GetBasicType(eBasicTypeInt); | 
|  | 283 | Value debug_value; | 
|  | 284 | debug_value.SetValueType(Value::eValueTypeScalar); | 
|  | 285 | debug_value.SetCompilerType(clang_int_type); | 
|  | 286 |  | 
|  | 287 | CompilerType clang_uint64_type = | 
|  | 288 | clang_ast_context->GetBasicType(eBasicTypeUnsignedLongLong); | 
|  | 289 | Value queue_value; | 
|  | 290 | queue_value.SetValueType(Value::eValueTypeScalar); | 
|  | 291 | queue_value.SetCompilerType(clang_uint64_type); | 
|  | 292 |  | 
|  | 293 | Value page_to_free_value; | 
|  | 294 | page_to_free_value.SetValueType(Value::eValueTypeScalar); | 
|  | 295 | page_to_free_value.SetCompilerType(clang_void_ptr_type); | 
|  | 296 |  | 
|  | 297 | Value page_to_free_size_value; | 
|  | 298 | page_to_free_size_value.SetValueType(Value::eValueTypeScalar); | 
|  | 299 | page_to_free_size_value.SetCompilerType(clang_uint64_type); | 
|  | 300 |  | 
|  | 301 | std::lock_guard<std::mutex> guard(m_get_pending_items_retbuffer_mutex); | 
|  | 302 | if (m_get_pending_items_return_buffer_addr == LLDB_INVALID_ADDRESS) { | 
|  | 303 | addr_t bufaddr = process_sp->AllocateMemory( | 
|  | 304 | 32, ePermissionsReadable | ePermissionsWritable, error); | 
|  | 305 | if (!error.Success() || bufaddr == LLDB_INVALID_ADDRESS) { | 
|  | 306 | if (log) | 
|  | 307 | log->Printf("Failed to allocate memory for return buffer for get " | 
|  | 308 | "current queues func call"); | 
|  | 309 | return return_value; | 
|  | 310 | } | 
|  | 311 | m_get_pending_items_return_buffer_addr = bufaddr; | 
|  | 312 | } | 
|  | 313 |  | 
|  | 314 | ValueList argument_values; | 
|  | 315 |  | 
|  | 316 | return_buffer_ptr_value.GetScalar() = m_get_pending_items_return_buffer_addr; | 
|  | 317 | argument_values.PushValue(return_buffer_ptr_value); | 
|  | 318 |  | 
|  | 319 | debug_value.GetScalar() = 0; | 
|  | 320 | argument_values.PushValue(debug_value); | 
|  | 321 |  | 
|  | 322 | queue_value.GetScalar() = queue; | 
|  | 323 | argument_values.PushValue(queue_value); | 
|  | 324 |  | 
|  | 325 | if (page_to_free != LLDB_INVALID_ADDRESS) | 
|  | 326 | page_to_free_value.GetScalar() = page_to_free; | 
|  | 327 | else | 
|  | 328 | page_to_free_value.GetScalar() = 0; | 
|  | 329 | argument_values.PushValue(page_to_free_value); | 
|  | 330 |  | 
|  | 331 | page_to_free_size_value.GetScalar() = page_to_free_size; | 
|  | 332 | argument_values.PushValue(page_to_free_size_value); | 
|  | 333 |  | 
|  | 334 | addr_t args_addr = SetupGetPendingItemsFunction(thread, argument_values); | 
|  | 335 |  | 
|  | 336 | DiagnosticManager diagnostics; | 
|  | 337 | ExecutionContext exe_ctx; | 
|  | 338 | FunctionCaller *get_pending_items_caller = | 
|  | 339 | m_get_pending_items_impl_code->GetFunctionCaller(); | 
|  | 340 |  | 
|  | 341 | EvaluateExpressionOptions options; | 
|  | 342 | options.SetUnwindOnError(true); | 
|  | 343 | options.SetIgnoreBreakpoints(true); | 
|  | 344 | options.SetStopOthers(true); | 
| Adrian Prantl | 4c03ea1 | 2019-04-05 22:43:42 +0000 | [diff] [blame] | 345 | options.SetTimeout(process_sp->GetUtilityExpressionTimeout()); | 
| Kate Stone | b9c1b51 | 2016-09-06 20:57:50 +0000 | [diff] [blame] | 346 | options.SetTryAllThreads(false); | 
| Raphael Isemann | c01783a | 2018-08-29 22:50:54 +0000 | [diff] [blame] | 347 | options.SetIsForUtilityExpr(true); | 
| Kate Stone | b9c1b51 | 2016-09-06 20:57:50 +0000 | [diff] [blame] | 348 | thread.CalculateExecutionContext(exe_ctx); | 
|  | 349 |  | 
| Konrad Kleine | 248a130 | 2019-05-23 11:14:47 +0000 | [diff] [blame^] | 350 | if (get_pending_items_caller == nullptr) { | 
| Kate Stone | b9c1b51 | 2016-09-06 20:57:50 +0000 | [diff] [blame] | 351 | error.SetErrorString("Unable to compile function to call " | 
|  | 352 | "__introspection_dispatch_queue_get_pending_items"); | 
|  | 353 | return return_value; | 
|  | 354 | } | 
|  | 355 |  | 
|  | 356 | ExpressionResults func_call_ret; | 
|  | 357 | Value results; | 
|  | 358 | func_call_ret = get_pending_items_caller->ExecuteFunction( | 
|  | 359 | exe_ctx, &args_addr, options, diagnostics, results); | 
|  | 360 | if (func_call_ret != eExpressionCompleted || !error.Success()) { | 
|  | 361 | if (log) | 
|  | 362 | log->Printf("Unable to call " | 
|  | 363 | "__introspection_dispatch_queue_get_pending_items(), got " | 
|  | 364 | "ExpressionResults %d, error contains %s", | 
|  | 365 | func_call_ret, error.AsCString("")); | 
|  | 366 | error.SetErrorString("Unable to call " | 
|  | 367 | "__introspection_dispatch_queue_get_pending_items() " | 
|  | 368 | "for list of queues"); | 
|  | 369 | return return_value; | 
|  | 370 | } | 
|  | 371 |  | 
|  | 372 | return_value.items_buffer_ptr = m_process->ReadUnsignedIntegerFromMemory( | 
|  | 373 | m_get_pending_items_return_buffer_addr, 8, LLDB_INVALID_ADDRESS, error); | 
|  | 374 | if (!error.Success() || | 
|  | 375 | return_value.items_buffer_ptr == LLDB_INVALID_ADDRESS) { | 
|  | 376 | return_value.items_buffer_ptr = LLDB_INVALID_ADDRESS; | 
|  | 377 | return return_value; | 
|  | 378 | } | 
|  | 379 |  | 
|  | 380 | return_value.items_buffer_size = m_process->ReadUnsignedIntegerFromMemory( | 
|  | 381 | m_get_pending_items_return_buffer_addr + 8, 8, 0, error); | 
|  | 382 |  | 
|  | 383 | if (!error.Success()) { | 
|  | 384 | return_value.items_buffer_ptr = LLDB_INVALID_ADDRESS; | 
|  | 385 | return return_value; | 
|  | 386 | } | 
|  | 387 |  | 
|  | 388 | return_value.count = m_process->ReadUnsignedIntegerFromMemory( | 
|  | 389 | m_get_pending_items_return_buffer_addr + 16, 8, 0, error); | 
|  | 390 | if (!error.Success()) { | 
|  | 391 | return_value.items_buffer_ptr = LLDB_INVALID_ADDRESS; | 
|  | 392 | return return_value; | 
|  | 393 | } | 
|  | 394 |  | 
|  | 395 | if (log) | 
|  | 396 | log->Printf("AppleGetPendingItemsHandler called " | 
|  | 397 | "__introspection_dispatch_queue_get_pending_items " | 
|  | 398 | "(page_to_free == 0x%" PRIx64 ", size = %" PRId64 | 
|  | 399 | "), returned page is at 0x%" PRIx64 ", size %" PRId64 | 
|  | 400 | ", count = %" PRId64, | 
|  | 401 | page_to_free, page_to_free_size, return_value.items_buffer_ptr, | 
|  | 402 | return_value.items_buffer_size, return_value.count); | 
|  | 403 |  | 
|  | 404 | return return_value; | 
| Jason Molenda | 2fd8335 | 2014-02-05 05:44:54 +0000 | [diff] [blame] | 405 | } |