15ec532a9SColin Riley //===-- RenderScriptRuntime.h -----------------------------------*- C++ -*-===//
25ec532a9SColin Riley //
35ec532a9SColin Riley //                     The LLVM Compiler Infrastructure
45ec532a9SColin Riley //
55ec532a9SColin Riley // This file is distributed under the University of Illinois Open Source
65ec532a9SColin Riley // License. See LICENSE.TXT for details.
75ec532a9SColin Riley //
85ec532a9SColin Riley //===----------------------------------------------------------------------===//
95ec532a9SColin Riley 
105ec532a9SColin Riley #ifndef liblldb_RenderScriptRuntime_h_
115ec532a9SColin Riley #define liblldb_RenderScriptRuntime_h_
125ec532a9SColin Riley 
135ec532a9SColin Riley // C Includes
145ec532a9SColin Riley // C++ Includes
15222b937cSEugene Zelenko #include <array>
16222b937cSEugene Zelenko #include <map>
17222b937cSEugene Zelenko #include <memory>
18222b937cSEugene Zelenko #include <string>
19222b937cSEugene Zelenko #include <vector>
20222b937cSEugene Zelenko 
215ec532a9SColin Riley // Other libraries and framework includes
225ec532a9SColin Riley // Project includes
235ec532a9SColin Riley #include "lldb/lldb-private.h"
245ec532a9SColin Riley #include "lldb/Target/LanguageRuntime.h"
255ec532a9SColin Riley #include "lldb/Target/CPPLanguageRuntime.h"
265ec532a9SColin Riley #include "lldb/Core/Module.h"
275ec532a9SColin Riley 
28222b937cSEugene Zelenko namespace lldb_private {
29222b937cSEugene Zelenko namespace lldb_renderscript {
3098156583SEwan Crawford 
315ec532a9SColin Riley typedef uint32_t RSSlot;
325ec532a9SColin Riley class RSModuleDescriptor;
334640cde1SColin Riley struct RSGlobalDescriptor;
344640cde1SColin Riley struct RSKernelDescriptor;
354640cde1SColin Riley 
364640cde1SColin Riley typedef std::shared_ptr<RSModuleDescriptor> RSModuleDescriptorSP;
374640cde1SColin Riley typedef std::shared_ptr<RSGlobalDescriptor> RSGlobalDescriptorSP;
384640cde1SColin Riley typedef std::shared_ptr<RSKernelDescriptor> RSKernelDescriptorSP;
394f8817c2SEwan Crawford typedef std::array<uint32_t, 3> RSCoordinate;
404640cde1SColin Riley 
4198156583SEwan Crawford // Breakpoint Resolvers decide where a breakpoint is placed,
4298156583SEwan Crawford // so having our own allows us to limit the search scope to RS kernel modules.
4398156583SEwan Crawford // As well as check for .expand kernels as a fallback.
4498156583SEwan Crawford class RSBreakpointResolver : public BreakpointResolver
4598156583SEwan Crawford {
4698156583SEwan Crawford public:
4798156583SEwan Crawford     RSBreakpointResolver(Breakpoint *bkpt, ConstString name):
4898156583SEwan Crawford                          BreakpointResolver (bkpt, BreakpointResolver::NameResolver),
4998156583SEwan Crawford                          m_kernel_name(name)
5098156583SEwan Crawford     {
5198156583SEwan Crawford     }
5298156583SEwan Crawford 
5398156583SEwan Crawford     void
5498156583SEwan Crawford     GetDescription(Stream *strm) override
5598156583SEwan Crawford     {
5698156583SEwan Crawford         if (strm)
5798156583SEwan Crawford             strm->Printf("RenderScript kernel breakpoint for '%s'", m_kernel_name.AsCString());
5898156583SEwan Crawford     }
5998156583SEwan Crawford 
6098156583SEwan Crawford     void
6198156583SEwan Crawford     Dump(Stream *s) const override
6298156583SEwan Crawford     {
6398156583SEwan Crawford     }
6498156583SEwan Crawford 
6598156583SEwan Crawford     Searcher::CallbackReturn
6698156583SEwan Crawford     SearchCallback(SearchFilter &filter,
6798156583SEwan Crawford                    SymbolContext &context,
6898156583SEwan Crawford                    Address *addr,
6998156583SEwan Crawford                    bool containing) override;
7098156583SEwan Crawford 
7198156583SEwan Crawford     Searcher::Depth
7298156583SEwan Crawford     GetDepth() override
7398156583SEwan Crawford     {
7498156583SEwan Crawford         return Searcher::eDepthModule;
7598156583SEwan Crawford     }
7698156583SEwan Crawford 
7798156583SEwan Crawford     lldb::BreakpointResolverSP
7898156583SEwan Crawford     CopyForBreakpoint(Breakpoint &breakpoint) override
7998156583SEwan Crawford     {
8098156583SEwan Crawford         lldb::BreakpointResolverSP ret_sp(new RSBreakpointResolver(&breakpoint, m_kernel_name));
8198156583SEwan Crawford         return ret_sp;
8298156583SEwan Crawford     }
8398156583SEwan Crawford 
8498156583SEwan Crawford protected:
8598156583SEwan Crawford     ConstString m_kernel_name;
8698156583SEwan Crawford };
875ec532a9SColin Riley 
885ec532a9SColin Riley struct RSKernelDescriptor
895ec532a9SColin Riley {
905ec532a9SColin Riley public:
914640cde1SColin Riley     RSKernelDescriptor(const RSModuleDescriptor *module, const char *name, uint32_t slot)
925ec532a9SColin Riley         : m_module(module)
935ec532a9SColin Riley         , m_name(name)
945ec532a9SColin Riley         , m_slot(slot)
955ec532a9SColin Riley     {
965ec532a9SColin Riley     }
975ec532a9SColin Riley 
985ec532a9SColin Riley     void Dump(Stream &strm) const;
995ec532a9SColin Riley 
1004640cde1SColin Riley     const RSModuleDescriptor *m_module;
1015ec532a9SColin Riley     ConstString m_name;
1025ec532a9SColin Riley     RSSlot m_slot;
1035ec532a9SColin Riley };
1045ec532a9SColin Riley 
1055ec532a9SColin Riley struct RSGlobalDescriptor
1065ec532a9SColin Riley {
1075ec532a9SColin Riley public:
1084640cde1SColin Riley     RSGlobalDescriptor(const RSModuleDescriptor *module, const char *name )
1095ec532a9SColin Riley         : m_module(module)
1105ec532a9SColin Riley         , m_name(name)
1115ec532a9SColin Riley     {
1125ec532a9SColin Riley     }
1135ec532a9SColin Riley 
1145ec532a9SColin Riley     void Dump(Stream &strm) const;
1155ec532a9SColin Riley 
1164640cde1SColin Riley     const RSModuleDescriptor *m_module;
1175ec532a9SColin Riley     ConstString m_name;
1185ec532a9SColin Riley };
1195ec532a9SColin Riley 
1205ec532a9SColin Riley class RSModuleDescriptor
1215ec532a9SColin Riley {
1225ec532a9SColin Riley public:
1235ec532a9SColin Riley     RSModuleDescriptor(const lldb::ModuleSP &module)
1245ec532a9SColin Riley         : m_module(module)
1255ec532a9SColin Riley     {
1265ec532a9SColin Riley     }
1275ec532a9SColin Riley 
128222b937cSEugene Zelenko     ~RSModuleDescriptor() = default;
1295ec532a9SColin Riley 
1305ec532a9SColin Riley     bool ParseRSInfo();
1315ec532a9SColin Riley 
1325ec532a9SColin Riley     void Dump(Stream &strm) const;
1335ec532a9SColin Riley 
1345ec532a9SColin Riley     const lldb::ModuleSP m_module;
1355ec532a9SColin Riley     std::vector<RSKernelDescriptor> m_kernels;
1365ec532a9SColin Riley     std::vector<RSGlobalDescriptor> m_globals;
1374640cde1SColin Riley     std::map<std::string, std::string> m_pragmas;
1384640cde1SColin Riley     std::string m_resname;
1395ec532a9SColin Riley };
1405ec532a9SColin Riley 
141222b937cSEugene Zelenko } // namespace lldb_renderscript
14298156583SEwan Crawford 
1435ec532a9SColin Riley class RenderScriptRuntime : public lldb_private::CPPLanguageRuntime
1445ec532a9SColin Riley {
1455ec532a9SColin Riley public:
146ef20b08fSColin Riley     enum ModuleKind
147ef20b08fSColin Riley     {
148ef20b08fSColin Riley         eModuleKindIgnored,
149ef20b08fSColin Riley         eModuleKindLibRS,
150ef20b08fSColin Riley         eModuleKindDriver,
151ef20b08fSColin Riley         eModuleKindImpl,
152ef20b08fSColin Riley         eModuleKindKernelObj
153ef20b08fSColin Riley     };
154ef20b08fSColin Riley 
155222b937cSEugene Zelenko     ~RenderScriptRuntime() override;
1565ec532a9SColin Riley 
1575ec532a9SColin Riley     //------------------------------------------------------------------
1585ec532a9SColin Riley     // Static Functions
1595ec532a9SColin Riley     //------------------------------------------------------------------
1605ec532a9SColin Riley     static void Initialize();
1615ec532a9SColin Riley 
1625ec532a9SColin Riley     static void Terminate();
1635ec532a9SColin Riley 
1645ec532a9SColin Riley     static lldb_private::LanguageRuntime *CreateInstance(Process *process, lldb::LanguageType language);
1655ec532a9SColin Riley 
1664640cde1SColin Riley     static lldb::CommandObjectSP GetCommandObject(CommandInterpreter& interpreter);
1674640cde1SColin Riley 
1685ec532a9SColin Riley     static lldb_private::ConstString GetPluginNameStatic();
1695ec532a9SColin Riley 
170ef20b08fSColin Riley     static bool IsRenderScriptModule(const lldb::ModuleSP &module_sp);
171ef20b08fSColin Riley 
172ef20b08fSColin Riley     static ModuleKind GetModuleKind(const lldb::ModuleSP &module_sp);
173ef20b08fSColin Riley 
174ef20b08fSColin Riley     static void ModulesDidLoad(const lldb::ProcessSP& process_sp, const ModuleList &module_list );
175ef20b08fSColin Riley 
176222b937cSEugene Zelenko     bool IsVTableName(const char *name) override;
1775ec532a9SColin Riley 
178222b937cSEugene Zelenko     bool GetDynamicTypeAndAddress(ValueObject &in_value, lldb::DynamicValueType use_dynamic,
1790b6003f3SEnrico Granata                                   TypeAndOrName &class_type_or_name, Address &address,
180222b937cSEugene Zelenko                                   Value::ValueType &value_type) override;
181c74275bcSEnrico Granata 
182222b937cSEugene Zelenko     TypeAndOrName
183c74275bcSEnrico Granata     FixUpDynamicType(const TypeAndOrName& type_and_or_name,
184222b937cSEugene Zelenko                      ValueObject& static_value) override;
1855ec532a9SColin Riley 
186222b937cSEugene Zelenko     bool CouldHaveDynamicValue(ValueObject &in_value) override;
1875ec532a9SColin Riley 
188222b937cSEugene Zelenko     lldb::BreakpointResolverSP CreateExceptionResolver(Breakpoint *bkpt, bool catch_bp, bool throw_bp) override;
1895ec532a9SColin Riley 
1905ec532a9SColin Riley     bool LoadModule(const lldb::ModuleSP &module_sp);
1915ec532a9SColin Riley 
1925ec532a9SColin Riley     bool ProbeModules(const ModuleList module_list);
1935ec532a9SColin Riley 
1945ec532a9SColin Riley     void DumpModules(Stream &strm) const;
1955ec532a9SColin Riley 
1964640cde1SColin Riley     void DumpContexts(Stream &strm) const;
1974640cde1SColin Riley 
1984640cde1SColin Riley     void DumpKernels(Stream &strm) const;
1994640cde1SColin Riley 
200a0f08674SEwan Crawford     bool DumpAllocation(Stream &strm, StackFrame* frame_ptr, const uint32_t id);
201a0f08674SEwan Crawford 
202*b649b005SEwan Crawford     void
203*b649b005SEwan Crawford     ListAllocations(Stream &strm, StackFrame *frame_ptr, const uint32_t index);
20415f2bd95SEwan Crawford 
205018f5a7eSEwan Crawford     void PlaceBreakpointOnKernel(Stream &strm, const char *name, const std::array<int,3> coords,
206018f5a7eSEwan Crawford                                  Error &error, lldb::TargetSP target);
2074640cde1SColin Riley 
2087dc7771cSEwan Crawford     void SetBreakAllKernels(bool do_break, lldb::TargetSP target);
2097dc7771cSEwan Crawford 
2104640cde1SColin Riley     void Status(Stream &strm) const;
2114640cde1SColin Riley 
212222b937cSEugene Zelenko     void ModulesDidLoad(const ModuleList &module_list) override;
213ef20b08fSColin Riley 
21455232f09SEwan Crawford     bool LoadAllocation(Stream &strm, const uint32_t alloc_id, const char* filename, StackFrame* frame_ptr);
21555232f09SEwan Crawford 
21655232f09SEwan Crawford     bool SaveAllocation(Stream &strm, const uint32_t alloc_id, const char* filename, StackFrame* frame_ptr);
21755232f09SEwan Crawford 
218ef20b08fSColin Riley     void Update();
219ef20b08fSColin Riley 
220ef20b08fSColin Riley     void Initiate();
221ef20b08fSColin Riley 
222222b937cSEugene Zelenko     //------------------------------------------------------------------
223222b937cSEugene Zelenko     // PluginInterface protocol
224222b937cSEugene Zelenko     //------------------------------------------------------------------
225222b937cSEugene Zelenko     lldb_private::ConstString GetPluginName() override;
2264640cde1SColin Riley 
227222b937cSEugene Zelenko     uint32_t GetPluginVersion() override;
228222b937cSEugene Zelenko 
2294f8817c2SEwan Crawford     static bool
2304f8817c2SEwan Crawford     GetKernelCoordinate(lldb_renderscript::RSCoordinate &coord, Thread *thread_ptr);
2314f8817c2SEwan Crawford 
232222b937cSEugene Zelenko protected:
23315f2bd95SEwan Crawford     struct ScriptDetails;
23415f2bd95SEwan Crawford     struct AllocationDetails;
2358b244e21SEwan Crawford     struct Element;
23615f2bd95SEwan Crawford 
2377dc7771cSEwan Crawford     void InitSearchFilter(lldb::TargetSP target)
2387dc7771cSEwan Crawford     {
2397dc7771cSEwan Crawford         if (!m_filtersp)
2407dc7771cSEwan Crawford             m_filtersp.reset(new SearchFilterForUnconstrainedSearches(target));
2417dc7771cSEwan Crawford     }
2427dc7771cSEwan Crawford 
24398156583SEwan Crawford     void FixupScriptDetails(lldb_renderscript::RSModuleDescriptorSP rsmodule_sp);
2444640cde1SColin Riley 
2454640cde1SColin Riley     void LoadRuntimeHooks(lldb::ModuleSP module, ModuleKind kind);
2464640cde1SColin Riley 
24715f2bd95SEwan Crawford     bool RefreshAllocation(AllocationDetails* allocation, StackFrame* frame_ptr);
24815f2bd95SEwan Crawford 
24915f2bd95SEwan Crawford     bool EvalRSExpression(const char* expression, StackFrame* frame_ptr, uint64_t* result);
25015f2bd95SEwan Crawford 
2517dc7771cSEwan Crawford     lldb::BreakpointSP CreateKernelBreakpoint(const ConstString& name);
2527dc7771cSEwan Crawford 
2537dc7771cSEwan Crawford     void BreakOnModuleKernels(const lldb_renderscript::RSModuleDescriptorSP rsmodule_sp);
2547dc7771cSEwan Crawford 
2554640cde1SColin Riley     struct RuntimeHook;
2564640cde1SColin Riley     typedef void (RenderScriptRuntime::*CaptureStateFn)(RuntimeHook* hook_info, ExecutionContext &context);  // Please do this!
2574640cde1SColin Riley 
2584640cde1SColin Riley     struct HookDefn
2594640cde1SColin Riley     {
2604640cde1SColin Riley         const char * name;
26182780287SAidan Dodds         const char * symbol_name_m32; // mangled name for the 32 bit architectures
26282780287SAidan Dodds         const char * symbol_name_m64; // mangled name for the 64 bit archs
2634640cde1SColin Riley         uint32_t version;
2644640cde1SColin Riley         ModuleKind kind;
2654640cde1SColin Riley         CaptureStateFn grabber;
2664640cde1SColin Riley     };
2674640cde1SColin Riley 
2684640cde1SColin Riley     struct RuntimeHook
2694640cde1SColin Riley     {
2704640cde1SColin Riley         lldb::addr_t address;
2714640cde1SColin Riley         const HookDefn  *defn;
2724640cde1SColin Riley         lldb::BreakpointSP bp_sp;
2734640cde1SColin Riley     };
2744640cde1SColin Riley 
2754640cde1SColin Riley     typedef std::shared_ptr<RuntimeHook> RuntimeHookSP;
2764640cde1SColin Riley 
2774640cde1SColin Riley     lldb::ModuleSP m_libRS;
2784640cde1SColin Riley     lldb::ModuleSP m_libRSDriver;
2794640cde1SColin Riley     lldb::ModuleSP m_libRSCpuRef;
28098156583SEwan Crawford     std::vector<lldb_renderscript::RSModuleDescriptorSP> m_rsmodules;
28178f339d1SEwan Crawford 
28278f339d1SEwan Crawford     std::vector<std::unique_ptr<ScriptDetails>> m_scripts;
28378f339d1SEwan Crawford     std::vector<std::unique_ptr<AllocationDetails>> m_allocations;
2844640cde1SColin Riley 
28598156583SEwan Crawford     std::map<lldb::addr_t, lldb_renderscript::RSModuleDescriptorSP> m_scriptMappings;
2864640cde1SColin Riley     std::map<lldb::addr_t, RuntimeHookSP> m_runtimeHooks;
2874f8817c2SEwan Crawford     std::map<lldb::user_id_t, std::shared_ptr<uint32_t>> m_conditional_breaks;
2884640cde1SColin Riley 
2897dc7771cSEwan Crawford     lldb::SearchFilterSP m_filtersp; // Needed to create breakpoints through Target API
2907dc7771cSEwan Crawford 
291ef20b08fSColin Riley     bool m_initiated;
2924640cde1SColin Riley     bool m_debuggerPresentFlagged;
2937dc7771cSEwan Crawford     bool m_breakAllKernels;
2944640cde1SColin Riley     static const HookDefn s_runtimeHookDefns[];
2954640cde1SColin Riley     static const size_t s_runtimeHookCount;
2964f8817c2SEwan Crawford     static const std::string s_runtimeExpandSuffix;
2974f8817c2SEwan Crawford     static const std::array<const char *, 3> s_runtimeCoordVars;
2984640cde1SColin Riley 
2995ec532a9SColin Riley private:
3005ec532a9SColin Riley     RenderScriptRuntime(Process *process); // Call CreateInstance instead.
3014640cde1SColin Riley 
3024640cde1SColin Riley     static bool HookCallback(void *baton, StoppointCallbackContext *ctx, lldb::user_id_t break_id,
3034640cde1SColin Riley                              lldb::user_id_t break_loc_id);
3044640cde1SColin Riley 
305018f5a7eSEwan Crawford     static bool KernelBreakpointHit(void *baton, StoppointCallbackContext *ctx,
306018f5a7eSEwan Crawford                                     lldb::user_id_t break_id, lldb::user_id_t break_loc_id);
307018f5a7eSEwan Crawford 
3084640cde1SColin Riley     void HookCallback(RuntimeHook* hook_info, ExecutionContext& context);
3094640cde1SColin Riley 
31082780287SAidan Dodds     bool GetArgSimple(ExecutionContext& context, uint32_t arg, uint64_t* data);
3114640cde1SColin Riley 
3124640cde1SColin Riley     void CaptureScriptInit1(RuntimeHook* hook_info, ExecutionContext& context);
3134640cde1SColin Riley     void CaptureAllocationInit1(RuntimeHook* hook_info, ExecutionContext& context);
314e69df382SEwan Crawford     void CaptureAllocationDestroy(RuntimeHook* hook_info, ExecutionContext& context);
3154640cde1SColin Riley     void CaptureSetGlobalVar1(RuntimeHook* hook_info, ExecutionContext& context);
316e09c44b6SAidan Dodds     void CaptureScriptInvokeForEachMulti(RuntimeHook* hook_info, ExecutionContext& context);
3174640cde1SColin Riley 
318a0f08674SEwan Crawford     AllocationDetails* FindAllocByID(Stream &strm, const uint32_t alloc_id);
31955232f09SEwan Crawford     std::shared_ptr<uint8_t> GetAllocationData(AllocationDetails* allocation, StackFrame* frame_ptr);
3208b244e21SEwan Crawford     void SetElementSize(Element& elem);
321018f5a7eSEwan Crawford     static bool GetFrameVarAsUnsigned(const lldb::StackFrameSP, const char* var_name, uint64_t& val);
3228b244e21SEwan Crawford     void FindStructTypeName(Element& elem, StackFrame* frame_ptr);
323a0f08674SEwan Crawford 
32426e52a70SEwan Crawford     size_t PopulateElementHeaders(const std::shared_ptr<uint8_t> header_buffer, size_t offset, const Element& elem);
32526e52a70SEwan Crawford     size_t CalculateElementHeaderSize(const Element& elem);
32626e52a70SEwan Crawford 
32715f2bd95SEwan Crawford     //
32815f2bd95SEwan Crawford     // Helper functions for jitting the runtime
32915f2bd95SEwan Crawford     //
33015f2bd95SEwan Crawford     bool JITDataPointer(AllocationDetails* allocation, StackFrame* frame_ptr,
33115f2bd95SEwan Crawford                         unsigned int x = 0, unsigned int y = 0, unsigned int z = 0);
33215f2bd95SEwan Crawford 
33315f2bd95SEwan Crawford     bool JITTypePointer(AllocationDetails* allocation, StackFrame* frame_ptr);
33415f2bd95SEwan Crawford 
33515f2bd95SEwan Crawford     bool JITTypePacked(AllocationDetails* allocation, StackFrame* frame_ptr);
33615f2bd95SEwan Crawford 
3378b244e21SEwan Crawford     bool JITElementPacked(Element& elem, const lldb::addr_t context, StackFrame* frame_ptr);
33815f2bd95SEwan Crawford 
3398b244e21SEwan Crawford     bool JITAllocationSize(AllocationDetails* allocation, StackFrame* frame_ptr);
3408b244e21SEwan Crawford 
3418b244e21SEwan Crawford     bool JITSubelements(Element& elem, const lldb::addr_t context, StackFrame* frame_ptr);
342a0f08674SEwan Crawford 
343a0f08674SEwan Crawford     bool JITAllocationStride(AllocationDetails* allocation, StackFrame* frame_ptr);
344a0f08674SEwan Crawford 
34578f339d1SEwan Crawford     // Search for a script detail object using a target address.
34678f339d1SEwan Crawford     // If a script does not currently exist this function will return nullptr.
34778f339d1SEwan Crawford     // If 'create' is true and there is no previous script with this address,
34878f339d1SEwan Crawford     // then a new Script detail object will be created for this address and returned.
34978f339d1SEwan Crawford     ScriptDetails* LookUpScript(lldb::addr_t address, bool create);
35078f339d1SEwan Crawford 
35178f339d1SEwan Crawford     // Search for a previously saved allocation detail object using a target address.
35278f339d1SEwan Crawford     // If an allocation does not exist for this address then nullptr will be returned.
35378f339d1SEwan Crawford     // If 'create' is true and there is no previous allocation then a new allocation
35478f339d1SEwan Crawford     // detail object will be created for this address and returned.
35578f339d1SEwan Crawford     AllocationDetails* LookUpAllocation(lldb::addr_t address, bool create);
3565ec532a9SColin Riley };
3575ec532a9SColin Riley 
3585ec532a9SColin Riley } // namespace lldb_private
3595ec532a9SColin Riley 
3605ec532a9SColin Riley #endif // liblldb_RenderScriptRuntime_h_
361