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;
394640cde1SColin Riley 
4098156583SEwan Crawford // Breakpoint Resolvers decide where a breakpoint is placed,
4198156583SEwan Crawford // so having our own allows us to limit the search scope to RS kernel modules.
4298156583SEwan Crawford // As well as check for .expand kernels as a fallback.
4398156583SEwan Crawford class RSBreakpointResolver : public BreakpointResolver
4498156583SEwan Crawford {
4598156583SEwan Crawford public:
4698156583SEwan Crawford     RSBreakpointResolver(Breakpoint *bkpt, ConstString name):
4798156583SEwan Crawford                          BreakpointResolver (bkpt, BreakpointResolver::NameResolver),
4898156583SEwan Crawford                          m_kernel_name(name)
4998156583SEwan Crawford     {
5098156583SEwan Crawford     }
5198156583SEwan Crawford 
5298156583SEwan Crawford     void
5398156583SEwan Crawford     GetDescription(Stream *strm) override
5498156583SEwan Crawford     {
5598156583SEwan Crawford         if (strm)
5698156583SEwan Crawford             strm->Printf("RenderScript kernel breakpoint for '%s'", m_kernel_name.AsCString());
5798156583SEwan Crawford     }
5898156583SEwan Crawford 
5998156583SEwan Crawford     void
6098156583SEwan Crawford     Dump(Stream *s) const override
6198156583SEwan Crawford     {
6298156583SEwan Crawford     }
6398156583SEwan Crawford 
6498156583SEwan Crawford     Searcher::CallbackReturn
6598156583SEwan Crawford     SearchCallback(SearchFilter &filter,
6698156583SEwan Crawford                    SymbolContext &context,
6798156583SEwan Crawford                    Address *addr,
6898156583SEwan Crawford                    bool containing) override;
6998156583SEwan Crawford 
7098156583SEwan Crawford     Searcher::Depth
7198156583SEwan Crawford     GetDepth() override
7298156583SEwan Crawford     {
7398156583SEwan Crawford         return Searcher::eDepthModule;
7498156583SEwan Crawford     }
7598156583SEwan Crawford 
7698156583SEwan Crawford     lldb::BreakpointResolverSP
7798156583SEwan Crawford     CopyForBreakpoint(Breakpoint &breakpoint) override
7898156583SEwan Crawford     {
7998156583SEwan Crawford         lldb::BreakpointResolverSP ret_sp(new RSBreakpointResolver(&breakpoint, m_kernel_name));
8098156583SEwan Crawford         return ret_sp;
8198156583SEwan Crawford     }
8298156583SEwan Crawford 
8398156583SEwan Crawford protected:
8498156583SEwan Crawford     ConstString m_kernel_name;
8598156583SEwan Crawford };
865ec532a9SColin Riley 
875ec532a9SColin Riley struct RSKernelDescriptor
885ec532a9SColin Riley {
895ec532a9SColin Riley public:
904640cde1SColin Riley     RSKernelDescriptor(const RSModuleDescriptor *module, const char *name, uint32_t slot)
915ec532a9SColin Riley         : m_module(module)
925ec532a9SColin Riley         , m_name(name)
935ec532a9SColin Riley         , m_slot(slot)
945ec532a9SColin Riley     {
955ec532a9SColin Riley     }
965ec532a9SColin Riley 
975ec532a9SColin Riley     void Dump(Stream &strm) const;
985ec532a9SColin Riley 
994640cde1SColin Riley     const RSModuleDescriptor *m_module;
1005ec532a9SColin Riley     ConstString m_name;
1015ec532a9SColin Riley     RSSlot m_slot;
1025ec532a9SColin Riley };
1035ec532a9SColin Riley 
1045ec532a9SColin Riley struct RSGlobalDescriptor
1055ec532a9SColin Riley {
1065ec532a9SColin Riley public:
1074640cde1SColin Riley     RSGlobalDescriptor(const RSModuleDescriptor *module, const char *name )
1085ec532a9SColin Riley         : m_module(module)
1095ec532a9SColin Riley         , m_name(name)
1105ec532a9SColin Riley     {
1115ec532a9SColin Riley     }
1125ec532a9SColin Riley 
1135ec532a9SColin Riley     void Dump(Stream &strm) const;
1145ec532a9SColin Riley 
1154640cde1SColin Riley     const RSModuleDescriptor *m_module;
1165ec532a9SColin Riley     ConstString m_name;
1175ec532a9SColin Riley };
1185ec532a9SColin Riley 
1195ec532a9SColin Riley class RSModuleDescriptor
1205ec532a9SColin Riley {
1215ec532a9SColin Riley public:
1225ec532a9SColin Riley     RSModuleDescriptor(const lldb::ModuleSP &module)
1235ec532a9SColin Riley         : m_module(module)
1245ec532a9SColin Riley     {
1255ec532a9SColin Riley     }
1265ec532a9SColin Riley 
127222b937cSEugene Zelenko     ~RSModuleDescriptor() = default;
1285ec532a9SColin Riley 
1295ec532a9SColin Riley     bool ParseRSInfo();
1305ec532a9SColin Riley 
1315ec532a9SColin Riley     void Dump(Stream &strm) const;
1325ec532a9SColin Riley 
1335ec532a9SColin Riley     const lldb::ModuleSP m_module;
1345ec532a9SColin Riley     std::vector<RSKernelDescriptor> m_kernels;
1355ec532a9SColin Riley     std::vector<RSGlobalDescriptor> m_globals;
1364640cde1SColin Riley     std::map<std::string, std::string> m_pragmas;
1374640cde1SColin Riley     std::string m_resname;
1385ec532a9SColin Riley };
1395ec532a9SColin Riley 
140222b937cSEugene Zelenko } // namespace lldb_renderscript
14198156583SEwan Crawford 
1425ec532a9SColin Riley class RenderScriptRuntime : public lldb_private::CPPLanguageRuntime
1435ec532a9SColin Riley {
1445ec532a9SColin Riley public:
145ef20b08fSColin Riley     enum ModuleKind
146ef20b08fSColin Riley     {
147ef20b08fSColin Riley         eModuleKindIgnored,
148ef20b08fSColin Riley         eModuleKindLibRS,
149ef20b08fSColin Riley         eModuleKindDriver,
150ef20b08fSColin Riley         eModuleKindImpl,
151ef20b08fSColin Riley         eModuleKindKernelObj
152ef20b08fSColin Riley     };
153ef20b08fSColin Riley 
154222b937cSEugene Zelenko     ~RenderScriptRuntime() override;
1555ec532a9SColin Riley 
1565ec532a9SColin Riley     //------------------------------------------------------------------
1575ec532a9SColin Riley     // Static Functions
1585ec532a9SColin Riley     //------------------------------------------------------------------
1595ec532a9SColin Riley     static void Initialize();
1605ec532a9SColin Riley 
1615ec532a9SColin Riley     static void Terminate();
1625ec532a9SColin Riley 
1635ec532a9SColin Riley     static lldb_private::LanguageRuntime *CreateInstance(Process *process, lldb::LanguageType language);
1645ec532a9SColin Riley 
1654640cde1SColin Riley     static lldb::CommandObjectSP GetCommandObject(CommandInterpreter& interpreter);
1664640cde1SColin Riley 
1675ec532a9SColin Riley     static lldb_private::ConstString GetPluginNameStatic();
1685ec532a9SColin Riley 
169ef20b08fSColin Riley     static bool IsRenderScriptModule(const lldb::ModuleSP &module_sp);
170ef20b08fSColin Riley 
171ef20b08fSColin Riley     static ModuleKind GetModuleKind(const lldb::ModuleSP &module_sp);
172ef20b08fSColin Riley 
173ef20b08fSColin Riley     static void ModulesDidLoad(const lldb::ProcessSP& process_sp, const ModuleList &module_list );
174ef20b08fSColin Riley 
175222b937cSEugene Zelenko     bool IsVTableName(const char *name) override;
1765ec532a9SColin Riley 
177222b937cSEugene Zelenko     bool GetDynamicTypeAndAddress(ValueObject &in_value, lldb::DynamicValueType use_dynamic,
1780b6003f3SEnrico Granata                                   TypeAndOrName &class_type_or_name, Address &address,
179222b937cSEugene Zelenko                                   Value::ValueType &value_type) override;
180c74275bcSEnrico Granata 
181222b937cSEugene Zelenko     TypeAndOrName
182c74275bcSEnrico Granata     FixUpDynamicType(const TypeAndOrName& type_and_or_name,
183222b937cSEugene Zelenko                      ValueObject& static_value) override;
1845ec532a9SColin Riley 
185222b937cSEugene Zelenko     bool CouldHaveDynamicValue(ValueObject &in_value) override;
1865ec532a9SColin Riley 
187222b937cSEugene Zelenko     lldb::BreakpointResolverSP CreateExceptionResolver(Breakpoint *bkpt, bool catch_bp, bool throw_bp) override;
1885ec532a9SColin Riley 
1895ec532a9SColin Riley     bool LoadModule(const lldb::ModuleSP &module_sp);
1905ec532a9SColin Riley 
1915ec532a9SColin Riley     bool ProbeModules(const ModuleList module_list);
1925ec532a9SColin Riley 
1935ec532a9SColin Riley     void DumpModules(Stream &strm) const;
1945ec532a9SColin Riley 
1954640cde1SColin Riley     void DumpContexts(Stream &strm) const;
1964640cde1SColin Riley 
1974640cde1SColin Riley     void DumpKernels(Stream &strm) const;
1984640cde1SColin Riley 
199a0f08674SEwan Crawford     bool DumpAllocation(Stream &strm, StackFrame* frame_ptr, const uint32_t id);
200a0f08674SEwan Crawford 
20115f2bd95SEwan Crawford     void ListAllocations(Stream &strm, StackFrame* frame_ptr, bool recompute);
20215f2bd95SEwan Crawford 
203018f5a7eSEwan Crawford     void PlaceBreakpointOnKernel(Stream &strm, const char *name, const std::array<int,3> coords,
204018f5a7eSEwan Crawford                                  Error &error, lldb::TargetSP target);
2054640cde1SColin Riley 
2067dc7771cSEwan Crawford     void SetBreakAllKernels(bool do_break, lldb::TargetSP target);
2077dc7771cSEwan Crawford 
2084640cde1SColin Riley     void Status(Stream &strm) const;
2094640cde1SColin Riley 
210222b937cSEugene Zelenko     size_t GetAlternateManglings(const ConstString &mangled, std::vector<ConstString> &alternates) override {
21192935952SSiva Chandra         return static_cast<size_t>(0);
21292935952SSiva Chandra     }
21392935952SSiva Chandra 
214222b937cSEugene Zelenko     void ModulesDidLoad(const ModuleList &module_list) override;
215ef20b08fSColin Riley 
21655232f09SEwan Crawford     bool LoadAllocation(Stream &strm, const uint32_t alloc_id, const char* filename, StackFrame* frame_ptr);
21755232f09SEwan Crawford 
21855232f09SEwan Crawford     bool SaveAllocation(Stream &strm, const uint32_t alloc_id, const char* filename, StackFrame* frame_ptr);
21955232f09SEwan Crawford 
220ef20b08fSColin Riley     void Update();
221ef20b08fSColin Riley 
222ef20b08fSColin Riley     void Initiate();
223ef20b08fSColin Riley 
224222b937cSEugene Zelenko     //------------------------------------------------------------------
225222b937cSEugene Zelenko     // PluginInterface protocol
226222b937cSEugene Zelenko     //------------------------------------------------------------------
227222b937cSEugene Zelenko     lldb_private::ConstString GetPluginName() override;
2284640cde1SColin Riley 
229222b937cSEugene Zelenko     uint32_t GetPluginVersion() override;
230222b937cSEugene Zelenko 
231222b937cSEugene Zelenko protected:
23215f2bd95SEwan Crawford     struct ScriptDetails;
23315f2bd95SEwan Crawford     struct AllocationDetails;
2348b244e21SEwan Crawford     struct Element;
23515f2bd95SEwan Crawford 
2367dc7771cSEwan Crawford     void InitSearchFilter(lldb::TargetSP target)
2377dc7771cSEwan Crawford     {
2387dc7771cSEwan Crawford         if (!m_filtersp)
2397dc7771cSEwan Crawford             m_filtersp.reset(new SearchFilterForUnconstrainedSearches(target));
2407dc7771cSEwan Crawford     }
2417dc7771cSEwan Crawford 
24298156583SEwan Crawford     void FixupScriptDetails(lldb_renderscript::RSModuleDescriptorSP rsmodule_sp);
2434640cde1SColin Riley 
2444640cde1SColin Riley     void LoadRuntimeHooks(lldb::ModuleSP module, ModuleKind kind);
2454640cde1SColin Riley 
24615f2bd95SEwan Crawford     bool RefreshAllocation(AllocationDetails* allocation, StackFrame* frame_ptr);
24715f2bd95SEwan Crawford 
24815f2bd95SEwan Crawford     bool EvalRSExpression(const char* expression, StackFrame* frame_ptr, uint64_t* result);
24915f2bd95SEwan Crawford 
2507dc7771cSEwan Crawford     lldb::BreakpointSP CreateKernelBreakpoint(const ConstString& name);
2517dc7771cSEwan Crawford 
2527dc7771cSEwan Crawford     void BreakOnModuleKernels(const lldb_renderscript::RSModuleDescriptorSP rsmodule_sp);
2537dc7771cSEwan Crawford 
2544640cde1SColin Riley     struct RuntimeHook;
2554640cde1SColin Riley     typedef void (RenderScriptRuntime::*CaptureStateFn)(RuntimeHook* hook_info, ExecutionContext &context);  // Please do this!
2564640cde1SColin Riley 
2574640cde1SColin Riley     struct HookDefn
2584640cde1SColin Riley     {
2594640cde1SColin Riley         const char * name;
26082780287SAidan Dodds         const char * symbol_name_m32; // mangled name for the 32 bit architectures
26182780287SAidan Dodds         const char * symbol_name_m64; // mangled name for the 64 bit archs
2624640cde1SColin Riley         uint32_t version;
2634640cde1SColin Riley         ModuleKind kind;
2644640cde1SColin Riley         CaptureStateFn grabber;
2654640cde1SColin Riley     };
2664640cde1SColin Riley 
2674640cde1SColin Riley     struct RuntimeHook
2684640cde1SColin Riley     {
2694640cde1SColin Riley         lldb::addr_t address;
2704640cde1SColin Riley         const HookDefn  *defn;
2714640cde1SColin Riley         lldb::BreakpointSP bp_sp;
2724640cde1SColin Riley     };
2734640cde1SColin Riley 
2744640cde1SColin Riley     typedef std::shared_ptr<RuntimeHook> RuntimeHookSP;
2754640cde1SColin Riley 
2764640cde1SColin Riley     lldb::ModuleSP m_libRS;
2774640cde1SColin Riley     lldb::ModuleSP m_libRSDriver;
2784640cde1SColin Riley     lldb::ModuleSP m_libRSCpuRef;
27998156583SEwan Crawford     std::vector<lldb_renderscript::RSModuleDescriptorSP> m_rsmodules;
28078f339d1SEwan Crawford 
28178f339d1SEwan Crawford     std::vector<std::unique_ptr<ScriptDetails>> m_scripts;
28278f339d1SEwan Crawford     std::vector<std::unique_ptr<AllocationDetails>> m_allocations;
2834640cde1SColin Riley 
28498156583SEwan Crawford     std::map<lldb::addr_t, lldb_renderscript::RSModuleDescriptorSP> m_scriptMappings;
2854640cde1SColin Riley     std::map<lldb::addr_t, RuntimeHookSP> m_runtimeHooks;
286018f5a7eSEwan Crawford     std::map<lldb::user_id_t, std::shared_ptr<int>> m_conditional_breaks;
2874640cde1SColin Riley 
2887dc7771cSEwan Crawford     lldb::SearchFilterSP m_filtersp; // Needed to create breakpoints through Target API
2897dc7771cSEwan Crawford 
290ef20b08fSColin Riley     bool m_initiated;
2914640cde1SColin Riley     bool m_debuggerPresentFlagged;
2927dc7771cSEwan Crawford     bool m_breakAllKernels;
2934640cde1SColin Riley     static const HookDefn s_runtimeHookDefns[];
2944640cde1SColin Riley     static const size_t s_runtimeHookCount;
2954640cde1SColin Riley 
2965ec532a9SColin Riley private:
297b1651b8dSEwan Crawford     // Used to index expression format strings
298b1651b8dSEwan Crawford     enum ExpressionStrings
299b1651b8dSEwan Crawford     {
300b1651b8dSEwan Crawford        eExprGetOffsetPtr = 0,
301b1651b8dSEwan Crawford        eExprAllocGetType,
302b1651b8dSEwan Crawford        eExprTypeDimX,
303b1651b8dSEwan Crawford        eExprTypeDimY,
304b1651b8dSEwan Crawford        eExprTypeDimZ,
305b1651b8dSEwan Crawford        eExprTypeElemPtr,
306b1651b8dSEwan Crawford        eExprElementType,
307b1651b8dSEwan Crawford        eExprElementKind,
308b1651b8dSEwan Crawford        eExprElementVec,
309b1651b8dSEwan Crawford        eExprElementFieldCount,
310b1651b8dSEwan Crawford        eExprSubelementsId,
311b1651b8dSEwan Crawford        eExprSubelementsName,
312b1651b8dSEwan Crawford        eExprSubelementsArrSize
313b1651b8dSEwan Crawford     };
314b1651b8dSEwan Crawford 
3155ec532a9SColin Riley     RenderScriptRuntime(Process *process); // Call CreateInstance instead.
3164640cde1SColin Riley 
3174640cde1SColin Riley     static bool HookCallback(void *baton, StoppointCallbackContext *ctx, lldb::user_id_t break_id,
3184640cde1SColin Riley                              lldb::user_id_t break_loc_id);
3194640cde1SColin Riley 
320018f5a7eSEwan Crawford     static bool KernelBreakpointHit(void *baton, StoppointCallbackContext *ctx,
321018f5a7eSEwan Crawford                                     lldb::user_id_t break_id, lldb::user_id_t break_loc_id);
322018f5a7eSEwan Crawford 
3234640cde1SColin Riley     void HookCallback(RuntimeHook* hook_info, ExecutionContext& context);
3244640cde1SColin Riley 
32582780287SAidan Dodds     bool GetArgSimple(ExecutionContext& context, uint32_t arg, uint64_t* data);
3264640cde1SColin Riley 
3274640cde1SColin Riley     void CaptureScriptInit1(RuntimeHook* hook_info, ExecutionContext& context);
3284640cde1SColin Riley     void CaptureAllocationInit1(RuntimeHook* hook_info, ExecutionContext& context);
329*e69df382SEwan Crawford     void CaptureAllocationDestroy(RuntimeHook* hook_info, ExecutionContext& context);
3304640cde1SColin Riley     void CaptureSetGlobalVar1(RuntimeHook* hook_info, ExecutionContext& context);
3314640cde1SColin Riley 
332a0f08674SEwan Crawford     AllocationDetails* FindAllocByID(Stream &strm, const uint32_t alloc_id);
33355232f09SEwan Crawford     std::shared_ptr<uint8_t> GetAllocationData(AllocationDetails* allocation, StackFrame* frame_ptr);
3348b244e21SEwan Crawford     void SetElementSize(Element& elem);
335018f5a7eSEwan Crawford     static bool GetFrameVarAsUnsigned(const lldb::StackFrameSP, const char* var_name, uint64_t& val);
3368b244e21SEwan Crawford     void FindStructTypeName(Element& elem, StackFrame* frame_ptr);
337a0f08674SEwan Crawford 
33815f2bd95SEwan Crawford     //
33915f2bd95SEwan Crawford     // Helper functions for jitting the runtime
34015f2bd95SEwan Crawford     //
341b1651b8dSEwan Crawford     const char* JITTemplate(ExpressionStrings e);
342b1651b8dSEwan Crawford 
34315f2bd95SEwan Crawford     bool JITDataPointer(AllocationDetails* allocation, StackFrame* frame_ptr,
34415f2bd95SEwan Crawford                         unsigned int x = 0, unsigned int y = 0, unsigned int z = 0);
34515f2bd95SEwan Crawford 
34615f2bd95SEwan Crawford     bool JITTypePointer(AllocationDetails* allocation, StackFrame* frame_ptr);
34715f2bd95SEwan Crawford 
34815f2bd95SEwan Crawford     bool JITTypePacked(AllocationDetails* allocation, StackFrame* frame_ptr);
34915f2bd95SEwan Crawford 
3508b244e21SEwan Crawford     bool JITElementPacked(Element& elem, const lldb::addr_t context, StackFrame* frame_ptr);
35115f2bd95SEwan Crawford 
3528b244e21SEwan Crawford     bool JITAllocationSize(AllocationDetails* allocation, StackFrame* frame_ptr);
3538b244e21SEwan Crawford 
3548b244e21SEwan Crawford     bool JITSubelements(Element& elem, const lldb::addr_t context, StackFrame* frame_ptr);
355a0f08674SEwan Crawford 
356a0f08674SEwan Crawford     bool JITAllocationStride(AllocationDetails* allocation, StackFrame* frame_ptr);
357a0f08674SEwan Crawford 
35878f339d1SEwan Crawford     // Search for a script detail object using a target address.
35978f339d1SEwan Crawford     // If a script does not currently exist this function will return nullptr.
36078f339d1SEwan Crawford     // If 'create' is true and there is no previous script with this address,
36178f339d1SEwan Crawford     // then a new Script detail object will be created for this address and returned.
36278f339d1SEwan Crawford     ScriptDetails* LookUpScript(lldb::addr_t address, bool create);
36378f339d1SEwan Crawford 
36478f339d1SEwan Crawford     // Search for a previously saved allocation detail object using a target address.
36578f339d1SEwan Crawford     // If an allocation does not exist for this address then nullptr will be returned.
36678f339d1SEwan Crawford     // If 'create' is true and there is no previous allocation then a new allocation
36778f339d1SEwan Crawford     // detail object will be created for this address and returned.
36878f339d1SEwan Crawford     AllocationDetails* LookUpAllocation(lldb::addr_t address, bool create);
3695ec532a9SColin Riley };
3705ec532a9SColin Riley 
3715ec532a9SColin Riley } // namespace lldb_private
3725ec532a9SColin Riley 
3735ec532a9SColin Riley #endif // liblldb_RenderScriptRuntime_h_
374