1ac7ddfbfSEd Maste //===-- ExpressionSourceCode.cpp --------------------------------*- C++ -*-===// 2ac7ddfbfSEd Maste // 3ac7ddfbfSEd Maste // The LLVM Compiler Infrastructure 4ac7ddfbfSEd Maste // 5ac7ddfbfSEd Maste // This file is distributed under the University of Illinois Open Source 6ac7ddfbfSEd Maste // License. See LICENSE.TXT for details. 7ac7ddfbfSEd Maste // 8ac7ddfbfSEd Maste //===----------------------------------------------------------------------===// 9ac7ddfbfSEd Maste 10ac7ddfbfSEd Maste #include "lldb/Expression/ExpressionSourceCode.h" 11ac7ddfbfSEd Maste 12ac7ddfbfSEd Maste #include "lldb/Core/StreamString.h" 139f2f44ceSEd Maste #include "Plugins/ExpressionParser/Clang/ClangModulesDeclVendor.h" 149f2f44ceSEd Maste #include "Plugins/ExpressionParser/Clang/ClangPersistentVariables.h" 159f2f44ceSEd Maste #include "lldb/Symbol/CompileUnit.h" 169f2f44ceSEd Maste #include "lldb/Symbol/DebugMacros.h" 171c3bbb01SEd Maste #include "lldb/Symbol/Block.h" 189f2f44ceSEd Maste #include "lldb/Symbol/TypeSystem.h" 190127ef0fSEd Maste #include "lldb/Target/ExecutionContext.h" 200127ef0fSEd Maste #include "lldb/Target/Platform.h" 211c3bbb01SEd Maste #include "lldb/Target/StackFrame.h" 220127ef0fSEd Maste #include "lldb/Target/Target.h" 23ac7ddfbfSEd Maste 24ac7ddfbfSEd Maste using namespace lldb_private; 25ac7ddfbfSEd Maste 26ac7ddfbfSEd Maste const char * 27ac7ddfbfSEd Maste ExpressionSourceCode::g_expression_prefix = R"( 281c3bbb01SEd Maste #ifndef NULL 29ac7ddfbfSEd Maste #define NULL (__null) 301c3bbb01SEd Maste #endif 311c3bbb01SEd Maste #ifndef Nil 32ac7ddfbfSEd Maste #define Nil (__null) 331c3bbb01SEd Maste #endif 341c3bbb01SEd Maste #ifndef nil 35ac7ddfbfSEd Maste #define nil (__null) 361c3bbb01SEd Maste #endif 371c3bbb01SEd Maste #ifndef YES 38ac7ddfbfSEd Maste #define YES ((BOOL)1) 391c3bbb01SEd Maste #endif 401c3bbb01SEd Maste #ifndef NO 41ac7ddfbfSEd Maste #define NO ((BOOL)0) 421c3bbb01SEd Maste #endif 430127ef0fSEd Maste typedef __INT8_TYPE__ int8_t; 440127ef0fSEd Maste typedef __UINT8_TYPE__ uint8_t; 450127ef0fSEd Maste typedef __INT16_TYPE__ int16_t; 460127ef0fSEd Maste typedef __UINT16_TYPE__ uint16_t; 470127ef0fSEd Maste typedef __INT32_TYPE__ int32_t; 480127ef0fSEd Maste typedef __UINT32_TYPE__ uint32_t; 490127ef0fSEd Maste typedef __INT64_TYPE__ int64_t; 500127ef0fSEd Maste typedef __UINT64_TYPE__ uint64_t; 510127ef0fSEd Maste typedef __INTPTR_TYPE__ intptr_t; 520127ef0fSEd Maste typedef __UINTPTR_TYPE__ uintptr_t; 53ac7ddfbfSEd Maste typedef __SIZE_TYPE__ size_t; 54ac7ddfbfSEd Maste typedef __PTRDIFF_TYPE__ ptrdiff_t; 55ac7ddfbfSEd Maste typedef unsigned short unichar; 561c3bbb01SEd Maste extern "C" 571c3bbb01SEd Maste { 581c3bbb01SEd Maste int printf(const char * __restrict, ...); 591c3bbb01SEd Maste } 60ac7ddfbfSEd Maste )"; 61ac7ddfbfSEd Maste 629f2f44ceSEd Maste namespace { 639f2f44ceSEd Maste 649f2f44ceSEd Maste class AddMacroState 659f2f44ceSEd Maste { 669f2f44ceSEd Maste enum State 679f2f44ceSEd Maste { 689f2f44ceSEd Maste CURRENT_FILE_NOT_YET_PUSHED, 699f2f44ceSEd Maste CURRENT_FILE_PUSHED, 709f2f44ceSEd Maste CURRENT_FILE_POPPED 719f2f44ceSEd Maste }; 729f2f44ceSEd Maste 739f2f44ceSEd Maste public: 749f2f44ceSEd Maste AddMacroState(const FileSpec ¤t_file, const uint32_t current_file_line) 759f2f44ceSEd Maste : m_state(CURRENT_FILE_NOT_YET_PUSHED), 769f2f44ceSEd Maste m_current_file(current_file), 779f2f44ceSEd Maste m_current_file_line(current_file_line) 789f2f44ceSEd Maste { } 799f2f44ceSEd Maste 809f2f44ceSEd Maste void 819f2f44ceSEd Maste StartFile(const FileSpec &file) 829f2f44ceSEd Maste { 839f2f44ceSEd Maste m_file_stack.push_back(file); 849f2f44ceSEd Maste if (file == m_current_file) 859f2f44ceSEd Maste m_state = CURRENT_FILE_PUSHED; 869f2f44ceSEd Maste } 879f2f44ceSEd Maste 889f2f44ceSEd Maste void 899f2f44ceSEd Maste EndFile() 909f2f44ceSEd Maste { 919f2f44ceSEd Maste if (m_file_stack.size() == 0) 929f2f44ceSEd Maste return; 939f2f44ceSEd Maste 949f2f44ceSEd Maste FileSpec old_top = m_file_stack.back(); 959f2f44ceSEd Maste m_file_stack.pop_back(); 969f2f44ceSEd Maste if (old_top == m_current_file) 979f2f44ceSEd Maste m_state = CURRENT_FILE_POPPED; 989f2f44ceSEd Maste } 999f2f44ceSEd Maste 1009f2f44ceSEd Maste // An entry is valid if it occurs before the current line in 1019f2f44ceSEd Maste // the current file. 1029f2f44ceSEd Maste bool 1039f2f44ceSEd Maste IsValidEntry(uint32_t line) 1049f2f44ceSEd Maste { 1059f2f44ceSEd Maste switch (m_state) 1069f2f44ceSEd Maste { 1079f2f44ceSEd Maste case CURRENT_FILE_NOT_YET_PUSHED: 1089f2f44ceSEd Maste return true; 1099f2f44ceSEd Maste case CURRENT_FILE_POPPED: 1109f2f44ceSEd Maste return false; 1119f2f44ceSEd Maste case CURRENT_FILE_PUSHED: 1129f2f44ceSEd Maste // If we are in file included in the current file, 1139f2f44ceSEd Maste // the entry should be added. 1149f2f44ceSEd Maste if (m_file_stack.back() != m_current_file) 1159f2f44ceSEd Maste return true; 1169f2f44ceSEd Maste 1179f2f44ceSEd Maste if (line >= m_current_file_line) 1189f2f44ceSEd Maste return false; 1199f2f44ceSEd Maste else 1209f2f44ceSEd Maste return true; 1219f2f44ceSEd Maste } 1229f2f44ceSEd Maste } 1239f2f44ceSEd Maste 1249f2f44ceSEd Maste private: 1259f2f44ceSEd Maste std::vector<FileSpec> m_file_stack; 1269f2f44ceSEd Maste State m_state; 1279f2f44ceSEd Maste FileSpec m_current_file; 1289f2f44ceSEd Maste uint32_t m_current_file_line; 1299f2f44ceSEd Maste }; 1309f2f44ceSEd Maste 1319f2f44ceSEd Maste } // anonymous namespace 1329f2f44ceSEd Maste 1339f2f44ceSEd Maste static void 1349f2f44ceSEd Maste AddMacros(const DebugMacros *dm, CompileUnit *comp_unit, AddMacroState &state, StreamString &stream) 1359f2f44ceSEd Maste { 1369f2f44ceSEd Maste if (dm == nullptr) 1379f2f44ceSEd Maste return; 1389f2f44ceSEd Maste 1399f2f44ceSEd Maste for (size_t i = 0; i < dm->GetNumMacroEntries(); i++) 1409f2f44ceSEd Maste { 1419f2f44ceSEd Maste const DebugMacroEntry &entry = dm->GetMacroEntryAtIndex(i); 1429f2f44ceSEd Maste uint32_t line; 1439f2f44ceSEd Maste 1449f2f44ceSEd Maste switch (entry.GetType()) 1459f2f44ceSEd Maste { 1469f2f44ceSEd Maste case DebugMacroEntry::DEFINE: 1479f2f44ceSEd Maste if (state.IsValidEntry(entry.GetLineNumber())) 1489f2f44ceSEd Maste stream.Printf("#define %s\n", entry.GetMacroString().AsCString()); 1499f2f44ceSEd Maste else 1509f2f44ceSEd Maste return; 1519f2f44ceSEd Maste break; 1529f2f44ceSEd Maste case DebugMacroEntry::UNDEF: 1539f2f44ceSEd Maste if (state.IsValidEntry(entry.GetLineNumber())) 1549f2f44ceSEd Maste stream.Printf("#undef %s\n", entry.GetMacroString().AsCString()); 1559f2f44ceSEd Maste else 1569f2f44ceSEd Maste return; 1579f2f44ceSEd Maste break; 1589f2f44ceSEd Maste case DebugMacroEntry::START_FILE: 1599f2f44ceSEd Maste line = entry.GetLineNumber(); 1609f2f44ceSEd Maste if (state.IsValidEntry(line)) 1619f2f44ceSEd Maste state.StartFile(entry.GetFileSpec(comp_unit)); 1629f2f44ceSEd Maste else 1639f2f44ceSEd Maste return; 1649f2f44ceSEd Maste break; 1659f2f44ceSEd Maste case DebugMacroEntry::END_FILE: 1669f2f44ceSEd Maste state.EndFile(); 1679f2f44ceSEd Maste break; 1689f2f44ceSEd Maste case DebugMacroEntry::INDIRECT: 1699f2f44ceSEd Maste AddMacros(entry.GetIndirectDebugMacros(), comp_unit, state, stream); 1709f2f44ceSEd Maste break; 1719f2f44ceSEd Maste default: 1729f2f44ceSEd Maste // This is an unknown/invalid entry. Ignore. 1739f2f44ceSEd Maste break; 1749f2f44ceSEd Maste } 1759f2f44ceSEd Maste } 1769f2f44ceSEd Maste } 177ac7ddfbfSEd Maste 1780127ef0fSEd Maste bool ExpressionSourceCode::GetText (std::string &text, lldb::LanguageType wrapping_language, bool const_object, bool static_method, ExecutionContext &exe_ctx) const 179ac7ddfbfSEd Maste { 1800127ef0fSEd Maste const char *target_specific_defines = "typedef signed char BOOL;\n"; 1811c3bbb01SEd Maste std::string module_macros; 1820127ef0fSEd Maste 1830127ef0fSEd Maste if (Target *target = exe_ctx.GetTargetPtr()) 1840127ef0fSEd Maste { 1850127ef0fSEd Maste if (target->GetArchitecture().GetMachine() == llvm::Triple::aarch64) 1860127ef0fSEd Maste { 1870127ef0fSEd Maste target_specific_defines = "typedef bool BOOL;\n"; 1880127ef0fSEd Maste } 1890127ef0fSEd Maste if (target->GetArchitecture().GetMachine() == llvm::Triple::x86_64) 1900127ef0fSEd Maste { 1910127ef0fSEd Maste if (lldb::PlatformSP platform_sp = target->GetPlatform()) 1920127ef0fSEd Maste { 1931c3bbb01SEd Maste static ConstString g_platform_ios_simulator ("ios-simulator"); 1940127ef0fSEd Maste if (platform_sp->GetPluginName() == g_platform_ios_simulator) 1950127ef0fSEd Maste { 1960127ef0fSEd Maste target_specific_defines = "typedef bool BOOL;\n"; 1970127ef0fSEd Maste } 1980127ef0fSEd Maste } 1990127ef0fSEd Maste } 2001c3bbb01SEd Maste 2011c3bbb01SEd Maste if (ClangModulesDeclVendor *decl_vendor = target->GetClangModulesDeclVendor()) 2021c3bbb01SEd Maste { 2039f2f44ceSEd Maste ClangPersistentVariables *persistent_vars = llvm::cast<ClangPersistentVariables>(target->GetPersistentExpressionStateForLanguage(lldb::eLanguageTypeC)); 2049f2f44ceSEd Maste const ClangModulesDeclVendor::ModuleVector &hand_imported_modules = persistent_vars->GetHandLoadedClangModules(); 2051c3bbb01SEd Maste ClangModulesDeclVendor::ModuleVector modules_for_macros; 2061c3bbb01SEd Maste 2071c3bbb01SEd Maste for (ClangModulesDeclVendor::ModuleID module : hand_imported_modules) 2081c3bbb01SEd Maste { 2091c3bbb01SEd Maste modules_for_macros.push_back(module); 2101c3bbb01SEd Maste } 2111c3bbb01SEd Maste 2121c3bbb01SEd Maste if (target->GetEnableAutoImportClangModules()) 2131c3bbb01SEd Maste { 2141c3bbb01SEd Maste if (StackFrame *frame = exe_ctx.GetFramePtr()) 2151c3bbb01SEd Maste { 2161c3bbb01SEd Maste if (Block *block = frame->GetFrameBlock()) 2171c3bbb01SEd Maste { 2181c3bbb01SEd Maste SymbolContext sc; 2191c3bbb01SEd Maste 2201c3bbb01SEd Maste block->CalculateSymbolContext(&sc); 2211c3bbb01SEd Maste 2221c3bbb01SEd Maste if (sc.comp_unit) 2231c3bbb01SEd Maste { 2241c3bbb01SEd Maste StreamString error_stream; 2251c3bbb01SEd Maste 2261c3bbb01SEd Maste decl_vendor->AddModulesForCompileUnit(*sc.comp_unit, modules_for_macros, error_stream); 2271c3bbb01SEd Maste } 2281c3bbb01SEd Maste } 2291c3bbb01SEd Maste } 2301c3bbb01SEd Maste } 2311c3bbb01SEd Maste 2321c3bbb01SEd Maste decl_vendor->ForEachMacro(modules_for_macros, [&module_macros] (const std::string &expansion) -> bool { 2331c3bbb01SEd Maste module_macros.append(expansion); 2341c3bbb01SEd Maste module_macros.append("\n"); 2351c3bbb01SEd Maste return false; 2361c3bbb01SEd Maste }); 2371c3bbb01SEd Maste } 2381c3bbb01SEd Maste 2390127ef0fSEd Maste } 2400127ef0fSEd Maste 2419f2f44ceSEd Maste StreamString debug_macros_stream; 2429f2f44ceSEd Maste if (StackFrame *frame = exe_ctx.GetFramePtr()) 2439f2f44ceSEd Maste { 2449f2f44ceSEd Maste const SymbolContext &sc = frame->GetSymbolContext( 2459f2f44ceSEd Maste lldb:: eSymbolContextCompUnit | lldb::eSymbolContextLineEntry); 2469f2f44ceSEd Maste 2479f2f44ceSEd Maste if (sc.comp_unit && sc.line_entry.IsValid()) 2489f2f44ceSEd Maste { 2499f2f44ceSEd Maste DebugMacros *dm = sc.comp_unit->GetDebugMacros(); 2509f2f44ceSEd Maste if (dm) 2519f2f44ceSEd Maste { 2529f2f44ceSEd Maste AddMacroState state(sc.line_entry.file, sc.line_entry.line); 2539f2f44ceSEd Maste AddMacros(dm, sc.comp_unit, state, debug_macros_stream); 2549f2f44ceSEd Maste } 2559f2f44ceSEd Maste } 2569f2f44ceSEd Maste } 2579f2f44ceSEd Maste 258ac7ddfbfSEd Maste if (m_wrap) 259ac7ddfbfSEd Maste { 260ac7ddfbfSEd Maste switch (wrapping_language) 261ac7ddfbfSEd Maste { 262ac7ddfbfSEd Maste default: 263ac7ddfbfSEd Maste return false; 264ac7ddfbfSEd Maste case lldb::eLanguageTypeC: 265ac7ddfbfSEd Maste case lldb::eLanguageTypeC_plus_plus: 266ac7ddfbfSEd Maste case lldb::eLanguageTypeObjC: 267ac7ddfbfSEd Maste break; 268ac7ddfbfSEd Maste } 269ac7ddfbfSEd Maste 270ac7ddfbfSEd Maste StreamString wrap_stream; 271ac7ddfbfSEd Maste 2729f2f44ceSEd Maste wrap_stream.Printf("%s\n%s\n%s\n%s\n%s\n", 2731c3bbb01SEd Maste module_macros.c_str(), 2749f2f44ceSEd Maste debug_macros_stream.GetData(), 2751c3bbb01SEd Maste g_expression_prefix, 2761c3bbb01SEd Maste target_specific_defines, 2771c3bbb01SEd Maste m_prefix.c_str()); 2781c3bbb01SEd Maste 279ac7ddfbfSEd Maste switch (wrapping_language) 280ac7ddfbfSEd Maste { 281ac7ddfbfSEd Maste default: 282ac7ddfbfSEd Maste break; 283ac7ddfbfSEd Maste case lldb::eLanguageTypeC: 2841c3bbb01SEd Maste wrap_stream.Printf("void \n" 285ac7ddfbfSEd Maste "%s(void *$__lldb_arg) \n" 286ac7ddfbfSEd Maste "{ \n" 287ac7ddfbfSEd Maste " %s; \n" 288ac7ddfbfSEd Maste "} \n", 289ac7ddfbfSEd Maste m_name.c_str(), 290ac7ddfbfSEd Maste m_body.c_str()); 291ac7ddfbfSEd Maste break; 292ac7ddfbfSEd Maste case lldb::eLanguageTypeC_plus_plus: 2931c3bbb01SEd Maste wrap_stream.Printf("void \n" 294ac7ddfbfSEd Maste "$__lldb_class::%s(void *$__lldb_arg) %s\n" 295ac7ddfbfSEd Maste "{ \n" 296ac7ddfbfSEd Maste " %s; \n" 297ac7ddfbfSEd Maste "} \n", 298ac7ddfbfSEd Maste m_name.c_str(), 299ac7ddfbfSEd Maste (const_object ? "const" : ""), 300ac7ddfbfSEd Maste m_body.c_str()); 301ac7ddfbfSEd Maste break; 302ac7ddfbfSEd Maste case lldb::eLanguageTypeObjC: 303ac7ddfbfSEd Maste if (static_method) 304ac7ddfbfSEd Maste { 3051c3bbb01SEd Maste wrap_stream.Printf("@interface $__lldb_objc_class ($__lldb_category) \n" 306ac7ddfbfSEd Maste "+(void)%s:(void *)$__lldb_arg; \n" 307ac7ddfbfSEd Maste "@end \n" 308ac7ddfbfSEd Maste "@implementation $__lldb_objc_class ($__lldb_category) \n" 309ac7ddfbfSEd Maste "+(void)%s:(void *)$__lldb_arg \n" 310ac7ddfbfSEd Maste "{ \n" 311ac7ddfbfSEd Maste " %s; \n" 312ac7ddfbfSEd Maste "} \n" 313ac7ddfbfSEd Maste "@end \n", 314ac7ddfbfSEd Maste m_name.c_str(), 315ac7ddfbfSEd Maste m_name.c_str(), 316ac7ddfbfSEd Maste m_body.c_str()); 317ac7ddfbfSEd Maste } 318ac7ddfbfSEd Maste else 319ac7ddfbfSEd Maste { 3201c3bbb01SEd Maste wrap_stream.Printf("@interface $__lldb_objc_class ($__lldb_category) \n" 321ac7ddfbfSEd Maste "-(void)%s:(void *)$__lldb_arg; \n" 322ac7ddfbfSEd Maste "@end \n" 323ac7ddfbfSEd Maste "@implementation $__lldb_objc_class ($__lldb_category) \n" 324ac7ddfbfSEd Maste "-(void)%s:(void *)$__lldb_arg \n" 325ac7ddfbfSEd Maste "{ \n" 326ac7ddfbfSEd Maste " %s; \n" 327ac7ddfbfSEd Maste "} \n" 328ac7ddfbfSEd Maste "@end \n", 329ac7ddfbfSEd Maste m_name.c_str(), 330ac7ddfbfSEd Maste m_name.c_str(), 331ac7ddfbfSEd Maste m_body.c_str()); 332ac7ddfbfSEd Maste } 333ac7ddfbfSEd Maste break; 334ac7ddfbfSEd Maste } 335ac7ddfbfSEd Maste 336ac7ddfbfSEd Maste text = wrap_stream.GetString(); 337ac7ddfbfSEd Maste } 338ac7ddfbfSEd Maste else 339ac7ddfbfSEd Maste { 340ac7ddfbfSEd Maste text.append(m_body); 341ac7ddfbfSEd Maste } 342ac7ddfbfSEd Maste 343ac7ddfbfSEd Maste return true; 344ac7ddfbfSEd Maste } 345