1 //===-- RenderScriptRuntime.h -----------------------------------*- C++ -*-===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 10 #ifndef liblldb_RenderScriptRuntime_h_ 11 #define liblldb_RenderScriptRuntime_h_ 12 13 // C Includes 14 // C++ Includes 15 #include <array> 16 #include <map> 17 #include <memory> 18 #include <string> 19 #include <vector> 20 21 // Other libraries and framework includes 22 // Project includes 23 #include "lldb/Core/Module.h" 24 #include "lldb/Expression/LLVMUserExpression.h" 25 #include "lldb/Target/CPPLanguageRuntime.h" 26 #include "lldb/Target/LanguageRuntime.h" 27 #include "lldb/lldb-private.h" 28 29 namespace lldb_private { 30 namespace lldb_renderscript { 31 32 typedef uint32_t RSSlot; 33 class RSModuleDescriptor; 34 struct RSGlobalDescriptor; 35 struct RSKernelDescriptor; 36 37 typedef std::shared_ptr<RSModuleDescriptor> RSModuleDescriptorSP; 38 typedef std::shared_ptr<RSGlobalDescriptor> RSGlobalDescriptorSP; 39 typedef std::shared_ptr<RSKernelDescriptor> RSKernelDescriptorSP; 40 typedef std::array<uint32_t, 3> RSCoordinate; 41 42 // Breakpoint Resolvers decide where a breakpoint is placed, 43 // so having our own allows us to limit the search scope to RS kernel modules. 44 // As well as check for .expand kernels as a fallback. 45 class RSBreakpointResolver : public BreakpointResolver { 46 public: 47 RSBreakpointResolver(Breakpoint *bkpt, ConstString name) 48 : BreakpointResolver(bkpt, BreakpointResolver::NameResolver), 49 m_kernel_name(name) {} 50 51 void GetDescription(Stream *strm) override { 52 if (strm) 53 strm->Printf("RenderScript kernel breakpoint for '%s'", 54 m_kernel_name.AsCString()); 55 } 56 57 void Dump(Stream *s) const override {} 58 59 Searcher::CallbackReturn SearchCallback(SearchFilter &filter, 60 SymbolContext &context, Address *addr, 61 bool containing) override; 62 63 Searcher::Depth GetDepth() override { return Searcher::eDepthModule; } 64 65 lldb::BreakpointResolverSP 66 CopyForBreakpoint(Breakpoint &breakpoint) override { 67 lldb::BreakpointResolverSP ret_sp( 68 new RSBreakpointResolver(&breakpoint, m_kernel_name)); 69 return ret_sp; 70 } 71 72 protected: 73 ConstString m_kernel_name; 74 }; 75 76 struct RSKernelDescriptor { 77 public: 78 RSKernelDescriptor(const RSModuleDescriptor *module, const char *name, 79 uint32_t slot) 80 : m_module(module), m_name(name), m_slot(slot) {} 81 82 void Dump(Stream &strm) const; 83 84 const RSModuleDescriptor *m_module; 85 ConstString m_name; 86 RSSlot m_slot; 87 }; 88 89 struct RSGlobalDescriptor { 90 public: 91 RSGlobalDescriptor(const RSModuleDescriptor *module, const char *name) 92 : m_module(module), m_name(name) {} 93 94 void Dump(Stream &strm) const; 95 96 const RSModuleDescriptor *m_module; 97 ConstString m_name; 98 }; 99 100 class RSModuleDescriptor { 101 public: 102 RSModuleDescriptor(const lldb::ModuleSP &module) : m_module(module) {} 103 104 ~RSModuleDescriptor() = default; 105 106 bool ParseRSInfo(); 107 108 void Dump(Stream &strm) const; 109 110 const lldb::ModuleSP m_module; 111 std::vector<RSKernelDescriptor> m_kernels; 112 std::vector<RSGlobalDescriptor> m_globals; 113 std::map<std::string, std::string> m_pragmas; 114 std::string m_resname; 115 }; 116 117 } // namespace lldb_renderscript 118 119 class RenderScriptRuntime : public lldb_private::CPPLanguageRuntime { 120 public: 121 enum ModuleKind { 122 eModuleKindIgnored, 123 eModuleKindLibRS, 124 eModuleKindDriver, 125 eModuleKindImpl, 126 eModuleKindKernelObj 127 }; 128 129 ~RenderScriptRuntime() override; 130 131 //------------------------------------------------------------------ 132 // Static Functions 133 //------------------------------------------------------------------ 134 static void Initialize(); 135 136 static void Terminate(); 137 138 static lldb_private::LanguageRuntime * 139 CreateInstance(Process *process, lldb::LanguageType language); 140 141 static lldb::CommandObjectSP 142 GetCommandObject(CommandInterpreter &interpreter); 143 144 static lldb_private::ConstString GetPluginNameStatic(); 145 146 static bool IsRenderScriptModule(const lldb::ModuleSP &module_sp); 147 148 static ModuleKind GetModuleKind(const lldb::ModuleSP &module_sp); 149 150 static void ModulesDidLoad(const lldb::ProcessSP &process_sp, 151 const ModuleList &module_list); 152 153 bool IsVTableName(const char *name) override; 154 155 bool GetDynamicTypeAndAddress(ValueObject &in_value, 156 lldb::DynamicValueType use_dynamic, 157 TypeAndOrName &class_type_or_name, 158 Address &address, 159 Value::ValueType &value_type) override; 160 161 TypeAndOrName FixUpDynamicType(const TypeAndOrName &type_and_or_name, 162 ValueObject &static_value) override; 163 164 bool CouldHaveDynamicValue(ValueObject &in_value) override; 165 166 lldb::BreakpointResolverSP CreateExceptionResolver(Breakpoint *bkpt, 167 bool catch_bp, 168 bool throw_bp) override; 169 170 bool LoadModule(const lldb::ModuleSP &module_sp); 171 172 void DumpModules(Stream &strm) const; 173 174 void DumpContexts(Stream &strm) const; 175 176 void DumpKernels(Stream &strm) const; 177 178 bool DumpAllocation(Stream &strm, StackFrame *frame_ptr, const uint32_t id); 179 180 void ListAllocations(Stream &strm, StackFrame *frame_ptr, 181 const uint32_t index); 182 183 bool RecomputeAllAllocations(Stream &strm, StackFrame *frame_ptr); 184 185 void PlaceBreakpointOnKernel(Stream &strm, const char *name, 186 const std::array<int, 3> coords, Error &error, 187 lldb::TargetSP target); 188 189 void SetBreakAllKernels(bool do_break, lldb::TargetSP target); 190 191 void Status(Stream &strm) const; 192 193 void ModulesDidLoad(const ModuleList &module_list) override; 194 195 bool LoadAllocation(Stream &strm, const uint32_t alloc_id, 196 const char *filename, StackFrame *frame_ptr); 197 198 bool SaveAllocation(Stream &strm, const uint32_t alloc_id, 199 const char *filename, StackFrame *frame_ptr); 200 201 void Update(); 202 203 void Initiate(); 204 205 //------------------------------------------------------------------ 206 // PluginInterface protocol 207 //------------------------------------------------------------------ 208 lldb_private::ConstString GetPluginName() override; 209 210 uint32_t GetPluginVersion() override; 211 212 static bool GetKernelCoordinate(lldb_renderscript::RSCoordinate &coord, 213 Thread *thread_ptr); 214 215 protected: 216 struct ScriptDetails; 217 struct AllocationDetails; 218 struct Element; 219 220 void InitSearchFilter(lldb::TargetSP target) { 221 if (!m_filtersp) 222 m_filtersp.reset(new SearchFilterForUnconstrainedSearches(target)); 223 } 224 225 void FixupScriptDetails(lldb_renderscript::RSModuleDescriptorSP rsmodule_sp); 226 227 void LoadRuntimeHooks(lldb::ModuleSP module, ModuleKind kind); 228 229 bool RefreshAllocation(AllocationDetails *allocation, StackFrame *frame_ptr); 230 231 bool EvalRSExpression(const char *expression, StackFrame *frame_ptr, 232 uint64_t *result); 233 234 lldb::BreakpointSP CreateKernelBreakpoint(const ConstString &name); 235 236 void BreakOnModuleKernels( 237 const lldb_renderscript::RSModuleDescriptorSP rsmodule_sp); 238 239 struct RuntimeHook; 240 typedef void (RenderScriptRuntime::*CaptureStateFn)( 241 RuntimeHook *hook_info, 242 ExecutionContext &context); // Please do this! 243 244 struct HookDefn { 245 const char *name; 246 const char *symbol_name_m32; // mangled name for the 32 bit architectures 247 const char *symbol_name_m64; // mangled name for the 64 bit archs 248 uint32_t version; 249 ModuleKind kind; 250 CaptureStateFn grabber; 251 }; 252 253 struct RuntimeHook { 254 lldb::addr_t address; 255 const HookDefn *defn; 256 lldb::BreakpointSP bp_sp; 257 }; 258 259 typedef std::shared_ptr<RuntimeHook> RuntimeHookSP; 260 261 lldb::ModuleSP m_libRS; 262 lldb::ModuleSP m_libRSDriver; 263 lldb::ModuleSP m_libRSCpuRef; 264 std::vector<lldb_renderscript::RSModuleDescriptorSP> m_rsmodules; 265 266 std::vector<std::unique_ptr<ScriptDetails>> m_scripts; 267 std::vector<std::unique_ptr<AllocationDetails>> m_allocations; 268 269 std::map<lldb::addr_t, lldb_renderscript::RSModuleDescriptorSP> 270 m_scriptMappings; 271 std::map<lldb::addr_t, RuntimeHookSP> m_runtimeHooks; 272 std::map<lldb::user_id_t, std::shared_ptr<uint32_t>> m_conditional_breaks; 273 274 lldb::SearchFilterSP 275 m_filtersp; // Needed to create breakpoints through Target API 276 277 bool m_initiated; 278 bool m_debuggerPresentFlagged; 279 bool m_breakAllKernels; 280 static const HookDefn s_runtimeHookDefns[]; 281 static const size_t s_runtimeHookCount; 282 LLVMUserExpression::IRPasses *m_ir_passes; 283 284 private: 285 RenderScriptRuntime(Process *process); // Call CreateInstance instead. 286 287 static bool HookCallback(void *baton, StoppointCallbackContext *ctx, 288 lldb::user_id_t break_id, 289 lldb::user_id_t break_loc_id); 290 291 static bool KernelBreakpointHit(void *baton, StoppointCallbackContext *ctx, 292 lldb::user_id_t break_id, 293 lldb::user_id_t break_loc_id); 294 295 void HookCallback(RuntimeHook *hook_info, ExecutionContext &context); 296 297 void CaptureScriptInit(RuntimeHook *hook_info, ExecutionContext &context); 298 299 void CaptureAllocationInit(RuntimeHook *hook_info, ExecutionContext &context); 300 301 void CaptureAllocationDestroy(RuntimeHook *hook_info, 302 ExecutionContext &context); 303 304 void CaptureSetGlobalVar(RuntimeHook *hook_info, ExecutionContext &context); 305 306 void CaptureScriptInvokeForEachMulti(RuntimeHook *hook_info, 307 ExecutionContext &context); 308 309 AllocationDetails *FindAllocByID(Stream &strm, const uint32_t alloc_id); 310 311 std::shared_ptr<uint8_t> GetAllocationData(AllocationDetails *allocation, 312 StackFrame *frame_ptr); 313 314 void SetElementSize(Element &elem); 315 316 static bool GetFrameVarAsUnsigned(const lldb::StackFrameSP, 317 const char *var_name, uint64_t &val); 318 319 void FindStructTypeName(Element &elem, StackFrame *frame_ptr); 320 321 size_t PopulateElementHeaders(const std::shared_ptr<uint8_t> header_buffer, 322 size_t offset, const Element &elem); 323 324 size_t CalculateElementHeaderSize(const Element &elem); 325 326 // 327 // Helper functions for jitting the runtime 328 // 329 330 bool JITDataPointer(AllocationDetails *allocation, StackFrame *frame_ptr, 331 uint32_t x = 0, uint32_t y = 0, uint32_t z = 0); 332 333 bool JITTypePointer(AllocationDetails *allocation, StackFrame *frame_ptr); 334 335 bool JITTypePacked(AllocationDetails *allocation, StackFrame *frame_ptr); 336 337 bool JITElementPacked(Element &elem, const lldb::addr_t context, 338 StackFrame *frame_ptr); 339 340 bool JITAllocationSize(AllocationDetails *allocation, StackFrame *frame_ptr); 341 342 bool JITSubelements(Element &elem, const lldb::addr_t context, 343 StackFrame *frame_ptr); 344 345 bool JITAllocationStride(AllocationDetails *allocation, 346 StackFrame *frame_ptr); 347 348 // Search for a script detail object using a target address. 349 // If a script does not currently exist this function will return nullptr. 350 // If 'create' is true and there is no previous script with this address, 351 // then a new Script detail object will be created for this address and 352 // returned. 353 ScriptDetails *LookUpScript(lldb::addr_t address, bool create); 354 355 // Search for a previously saved allocation detail object using a target 356 // address. 357 // If an allocation does not exist for this address then nullptr will be 358 // returned. 359 AllocationDetails *LookUpAllocation(lldb::addr_t address); 360 361 // Creates a new allocation with the specified address assigning a new ID and 362 // removes 363 // any previous stored allocation which has the same address. 364 AllocationDetails *CreateAllocation(lldb::addr_t address); 365 366 bool GetOverrideExprOptions(clang::TargetOptions &prototype) override; 367 368 bool GetIRPasses(LLVMUserExpression::IRPasses &passes) override; 369 }; 370 371 } // namespace lldb_private 372 373 #endif // liblldb_RenderScriptRuntime_h_ 374