Index: include/lldb/Expression/ExpressionSourceCode.h =================================================================== --- include/lldb/Expression/ExpressionSourceCode.h +++ include/lldb/Expression/ExpressionSourceCode.h @@ -15,38 +15,13 @@ namespace lldb_private { -class ExecutionContext; - class ExpressionSourceCode { public: - static const char *g_expression_prefix; - - static ExpressionSourceCode *CreateWrapped(const char *prefix, - const char *body) { - return new ExpressionSourceCode("$__lldb_expr", prefix, body, true); - } - - static ExpressionSourceCode *CreateUnwrapped(const char *name, - const char *body) { - return new ExpressionSourceCode(name, "", body, false); - } - bool NeedsWrapping() const { return m_wrap; } const char *GetName() const { return m_name.c_str(); } - bool GetText(std::string &text, lldb::LanguageType wrapping_language, - bool static_method, ExecutionContext &exe_ctx, - bool add_locals) const; - - // Given a string returned by GetText, find the beginning and end of the body - // passed to CreateWrapped. Return true if the bounds could be found. This - // will also work on text with FixItHints applied. - static bool GetOriginalBodyBounds(std::string transformed_text, - lldb::LanguageType wrapping_language, - size_t &start_loc, size_t &end_loc); - -private: +protected: ExpressionSourceCode(const char *name, const char *prefix, const char *body, bool wrap) : m_name(name), m_prefix(prefix), m_body(body), m_wrap(wrap) {} Index: lldb.xcodeproj/project.pbxproj =================================================================== --- lldb.xcodeproj/project.pbxproj +++ lldb.xcodeproj/project.pbxproj @@ -172,6 +172,7 @@ 2689005E13353E0E00698AC0 /* ClangASTSource.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 49D7072811B5AD11001AD875 /* ClangASTSource.cpp */; }; 2689006013353E0E00698AC0 /* ClangExpressionDeclMap.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 49F1A74511B3388F003ED505 /* ClangExpressionDeclMap.cpp */; }; 2689006113353E0E00698AC0 /* ClangExpressionParser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 49445C2512245E3600C11A81 /* ClangExpressionParser.cpp */; }; + 4C61465E223059B000D686F9 /* ClangExpressionSourceCode.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4C61465C223059B000D686F9 /* ClangExpressionSourceCode.cpp */; }; 4984BA131B978C55008658D4 /* ClangExpressionVariable.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4984BA0E1B978C3E008658D4 /* ClangExpressionVariable.cpp */; }; 268900D313353E6F00698AC0 /* ClangExternalASTSourceCallbacks.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26E69030129C6BEF00DDECD9 /* ClangExternalASTSourceCallbacks.cpp */; }; 4966DCC4148978A10028481B /* ClangExternalASTSourceCommon.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4966DCC3148978A10028481B /* ClangExternalASTSourceCommon.cpp */; }; @@ -317,7 +318,6 @@ 2660387A211CA90F00329572 /* ExceptionBreakpoint.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26603874211CA90E00329572 /* ExceptionBreakpoint.cpp */; }; 268900EB13353E6F00698AC0 /* ExecutionContext.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26BC7F3510F1B90C00F91463 /* ExecutionContext.cpp */; }; 4C88BC2A1BA3722B00AA0964 /* Expression.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4C88BC291BA3722B00AA0964 /* Expression.cpp */; }; - 49A1CAC51430E8DE00306AC9 /* ExpressionSourceCode.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 49A1CAC31430E8BD00306AC9 /* ExpressionSourceCode.cpp */; }; 4984BA161B979973008658D4 /* ExpressionVariable.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4984BA151B979973008658D4 /* ExpressionVariable.cpp */; }; 4984BA181B979C08008658D4 /* ExpressionVariable.h in Headers */ = {isa = PBXBuildFile; fileRef = 4984BA171B979C08008658D4 /* ExpressionVariable.h */; }; 2689006E13353E1A00698AC0 /* File.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 260C6EA213011581005E16B0 /* File.cpp */; }; @@ -1597,6 +1597,8 @@ 26BC7DC010F1B79500F91463 /* ClangExpressionHelper.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ClangExpressionHelper.h; path = ExpressionParser/Clang/ClangExpressionHelper.h; sourceTree = ""; }; 49445C2512245E3600C11A81 /* ClangExpressionParser.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ClangExpressionParser.cpp; path = ExpressionParser/Clang/ClangExpressionParser.cpp; sourceTree = ""; }; 49445C2912245E5500C11A81 /* ClangExpressionParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ClangExpressionParser.h; path = ExpressionParser/Clang/ClangExpressionParser.h; sourceTree = ""; }; + 4C61465C223059B000D686F9 /* ClangExpressionSourceCode.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ClangExpressionSourceCode.cpp; path = ExpressionParser/Clang/ClangExpressionSourceCode.cpp; sourceTree = ""; }; + 4C61465D223059B000D686F9 /* ClangExpressionSourceCode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ClangExpressionSourceCode.h; path = ExpressionParser/Clang/ClangExpressionSourceCode.h; sourceTree = ""; }; 4984BA0E1B978C3E008658D4 /* ClangExpressionVariable.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ClangExpressionVariable.cpp; path = ExpressionParser/Clang/ClangExpressionVariable.cpp; sourceTree = ""; }; 4984BA0F1B978C3E008658D4 /* ClangExpressionVariable.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ClangExpressionVariable.h; path = ExpressionParser/Clang/ClangExpressionVariable.h; sourceTree = ""; }; 26E69030129C6BEF00DDECD9 /* ClangExternalASTSourceCallbacks.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ClangExternalASTSourceCallbacks.cpp; path = source/Symbol/ClangExternalASTSourceCallbacks.cpp; sourceTree = ""; }; @@ -1887,7 +1889,6 @@ 4C88BC291BA3722B00AA0964 /* Expression.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Expression.cpp; path = source/Expression/Expression.cpp; sourceTree = ""; }; 4C00832C1B9A58A700D5CF24 /* Expression.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Expression.h; path = include/lldb/Expression/Expression.h; sourceTree = ""; }; 4C2479BE1BA39843009C9A7B /* ExpressionParser.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = ExpressionParser.h; path = include/lldb/Expression/ExpressionParser.h; sourceTree = ""; }; - 49A1CAC31430E8BD00306AC9 /* ExpressionSourceCode.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ExpressionSourceCode.cpp; path = source/Expression/ExpressionSourceCode.cpp; sourceTree = ""; }; 49A1CAC11430E21D00306AC9 /* ExpressionSourceCode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ExpressionSourceCode.h; path = include/lldb/Expression/ExpressionSourceCode.h; sourceTree = ""; }; 4C29E77D1BA2403F00DFF855 /* ExpressionTypeSystemHelper.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.h; name = ExpressionTypeSystemHelper.h; path = include/lldb/Expression/ExpressionTypeSystemHelper.h; sourceTree = ""; }; 4984BA151B979973008658D4 /* ExpressionVariable.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ExpressionVariable.cpp; path = source/Expression/ExpressionVariable.cpp; sourceTree = ""; }; @@ -5506,7 +5507,6 @@ 4C00833D1B9F9B8400D5CF24 /* UtilityFunction.h */, 4C00833F1B9F9BA900D5CF24 /* UtilityFunction.cpp */, 49A1CAC11430E21D00306AC9 /* ExpressionSourceCode.h */, - 49A1CAC31430E8BD00306AC9 /* ExpressionSourceCode.cpp */, 4984BA171B979C08008658D4 /* ExpressionVariable.h */, 4984BA151B979973008658D4 /* ExpressionVariable.cpp */, 4C2479BE1BA39843009C9A7B /* ExpressionParser.h */, @@ -6238,6 +6238,8 @@ 49F1A74511B3388F003ED505 /* ClangExpressionDeclMap.cpp */, 49445C2912245E5500C11A81 /* ClangExpressionParser.h */, 49445C2512245E3600C11A81 /* ClangExpressionParser.cpp */, + 4C61465D223059B000D686F9 /* ClangExpressionSourceCode.h */, + 4C61465C223059B000D686F9 /* ClangExpressionSourceCode.cpp */, 4959511B1A1BC48100F6F8FC /* ClangModulesDeclVendor.h */, 4959511E1A1BC4BC00F6F8FC /* ClangModulesDeclVendor.cpp */, 49D4FE821210B5FB00CDB854 /* ClangPersistentVariables.h */, @@ -8014,6 +8016,7 @@ 8C3BD9961EF45DA50016C343 /* MainThreadCheckerRuntime.cpp in Sources */, 23042D121976CA1D00621B2C /* PlatformKalimba.cpp in Sources */, 2689001413353DDE00698AC0 /* CommandObjectBreakpoint.cpp in Sources */, + 4C61465E223059B000D686F9 /* ClangExpressionSourceCode.cpp in Sources */, 2689001513353DDE00698AC0 /* CommandObjectBreakpointCommand.cpp in Sources */, 2689001613353DDE00698AC0 /* CommandObjectCommands.cpp in Sources */, AFEC3362194A8ABA00FF05C6 /* StructuredData.cpp in Sources */, @@ -8539,7 +8542,6 @@ 23DDF226196C3EE600BB8417 /* CommandOptionValidators.cpp in Sources */, B207C4931429607D00F36E4E /* CommandObjectWatchpoint.cpp in Sources */, 26EFC4CD18CFAF0D00865D87 /* ObjectFileJIT.cpp in Sources */, - 49A1CAC51430E8DE00306AC9 /* ExpressionSourceCode.cpp in Sources */, 494260DA14579144003C1C78 /* VerifyDecl.cpp in Sources */, 2657AFB71B86910100958979 /* CompilerDeclContext.cpp in Sources */, 49DA65031485C92A005FF180 /* AppleObjCDeclVendor.cpp in Sources */, Index: source/Expression/ExpressionSourceCode.cpp =================================================================== --- source/Expression/ExpressionSourceCode.cpp +++ source/Expression/ExpressionSourceCode.cpp @@ -1,380 +0,0 @@ -//===-- ExpressionSourceCode.cpp --------------------------------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#include "lldb/Expression/ExpressionSourceCode.h" - -#include "Plugins/ExpressionParser/Clang/ClangModulesDeclVendor.h" -#include "Plugins/ExpressionParser/Clang/ClangPersistentVariables.h" -#include "lldb/Symbol/Block.h" -#include "lldb/Symbol/CompileUnit.h" -#include "lldb/Symbol/DebugMacros.h" -#include "lldb/Symbol/TypeSystem.h" -#include "lldb/Symbol/VariableList.h" -#include "lldb/Target/ExecutionContext.h" -#include "lldb/Target/Language.h" -#include "lldb/Target/Platform.h" -#include "lldb/Target/StackFrame.h" -#include "lldb/Target/Target.h" -#include "lldb/Utility/StreamString.h" - -using namespace lldb_private; - -const char *ExpressionSourceCode::g_expression_prefix = R"( -#ifndef NULL -#define NULL (__null) -#endif -#ifndef Nil -#define Nil (__null) -#endif -#ifndef nil -#define nil (__null) -#endif -#ifndef YES -#define YES ((BOOL)1) -#endif -#ifndef NO -#define NO ((BOOL)0) -#endif -typedef __INT8_TYPE__ int8_t; -typedef __UINT8_TYPE__ uint8_t; -typedef __INT16_TYPE__ int16_t; -typedef __UINT16_TYPE__ uint16_t; -typedef __INT32_TYPE__ int32_t; -typedef __UINT32_TYPE__ uint32_t; -typedef __INT64_TYPE__ int64_t; -typedef __UINT64_TYPE__ uint64_t; -typedef __INTPTR_TYPE__ intptr_t; -typedef __UINTPTR_TYPE__ uintptr_t; -typedef __SIZE_TYPE__ size_t; -typedef __PTRDIFF_TYPE__ ptrdiff_t; -typedef unsigned short unichar; -extern "C" -{ - int printf(const char * __restrict, ...); -} -)"; - -static const char *c_start_marker = " /*LLDB_BODY_START*/\n "; -static const char *c_end_marker = ";\n /*LLDB_BODY_END*/\n"; - -namespace { - -class AddMacroState { - enum State { - CURRENT_FILE_NOT_YET_PUSHED, - CURRENT_FILE_PUSHED, - CURRENT_FILE_POPPED - }; - -public: - AddMacroState(const FileSpec ¤t_file, const uint32_t current_file_line) - : m_state(CURRENT_FILE_NOT_YET_PUSHED), m_current_file(current_file), - m_current_file_line(current_file_line) {} - - void StartFile(const FileSpec &file) { - m_file_stack.push_back(file); - if (file == m_current_file) - m_state = CURRENT_FILE_PUSHED; - } - - void EndFile() { - if (m_file_stack.size() == 0) - return; - - FileSpec old_top = m_file_stack.back(); - m_file_stack.pop_back(); - if (old_top == m_current_file) - m_state = CURRENT_FILE_POPPED; - } - - // An entry is valid if it occurs before the current line in the current - // file. - bool IsValidEntry(uint32_t line) { - switch (m_state) { - case CURRENT_FILE_NOT_YET_PUSHED: - return true; - case CURRENT_FILE_PUSHED: - // If we are in file included in the current file, the entry should be - // added. - if (m_file_stack.back() != m_current_file) - return true; - - return line < m_current_file_line; - default: - return false; - } - } - -private: - std::vector m_file_stack; - State m_state; - FileSpec m_current_file; - uint32_t m_current_file_line; -}; - -} // anonymous namespace - -static void AddMacros(const DebugMacros *dm, CompileUnit *comp_unit, - AddMacroState &state, StreamString &stream) { - if (dm == nullptr) - return; - - for (size_t i = 0; i < dm->GetNumMacroEntries(); i++) { - const DebugMacroEntry &entry = dm->GetMacroEntryAtIndex(i); - uint32_t line; - - switch (entry.GetType()) { - case DebugMacroEntry::DEFINE: - if (state.IsValidEntry(entry.GetLineNumber())) - stream.Printf("#define %s\n", entry.GetMacroString().AsCString()); - else - return; - break; - case DebugMacroEntry::UNDEF: - if (state.IsValidEntry(entry.GetLineNumber())) - stream.Printf("#undef %s\n", entry.GetMacroString().AsCString()); - else - return; - break; - case DebugMacroEntry::START_FILE: - line = entry.GetLineNumber(); - if (state.IsValidEntry(line)) - state.StartFile(entry.GetFileSpec(comp_unit)); - else - return; - break; - case DebugMacroEntry::END_FILE: - state.EndFile(); - break; - case DebugMacroEntry::INDIRECT: - AddMacros(entry.GetIndirectDebugMacros(), comp_unit, state, stream); - break; - default: - // This is an unknown/invalid entry. Ignore. - break; - } - } -} - -static void AddLocalVariableDecls(const lldb::VariableListSP &var_list_sp, - StreamString &stream) { - for (size_t i = 0; i < var_list_sp->GetSize(); i++) { - lldb::VariableSP var_sp = var_list_sp->GetVariableAtIndex(i); - - ConstString var_name = var_sp->GetName(); - if (!var_name || var_name == ConstString("this") || - var_name == ConstString(".block_descriptor")) - continue; - - stream.Printf("using $__lldb_local_vars::%s;\n", var_name.AsCString()); - } -} - -bool ExpressionSourceCode::GetText(std::string &text, - lldb::LanguageType wrapping_language, - bool static_method, - ExecutionContext &exe_ctx, - bool add_locals) const { - const char *target_specific_defines = "typedef signed char BOOL;\n"; - std::string module_macros; - - Target *target = exe_ctx.GetTargetPtr(); - if (target) { - if (target->GetArchitecture().GetMachine() == llvm::Triple::aarch64) { - target_specific_defines = "typedef bool BOOL;\n"; - } - if (target->GetArchitecture().GetMachine() == llvm::Triple::x86_64) { - if (lldb::PlatformSP platform_sp = target->GetPlatform()) { - static ConstString g_platform_ios_simulator("ios-simulator"); - if (platform_sp->GetPluginName() == g_platform_ios_simulator) { - target_specific_defines = "typedef bool BOOL;\n"; - } - } - } - - if (ClangModulesDeclVendor *decl_vendor = - target->GetClangModulesDeclVendor()) { - ClangPersistentVariables *persistent_vars = - llvm::cast( - target->GetPersistentExpressionStateForLanguage( - lldb::eLanguageTypeC)); - const ClangModulesDeclVendor::ModuleVector &hand_imported_modules = - persistent_vars->GetHandLoadedClangModules(); - ClangModulesDeclVendor::ModuleVector modules_for_macros; - - for (ClangModulesDeclVendor::ModuleID module : hand_imported_modules) { - modules_for_macros.push_back(module); - } - - if (target->GetEnableAutoImportClangModules()) { - if (StackFrame *frame = exe_ctx.GetFramePtr()) { - if (Block *block = frame->GetFrameBlock()) { - SymbolContext sc; - - block->CalculateSymbolContext(&sc); - - if (sc.comp_unit) { - StreamString error_stream; - - decl_vendor->AddModulesForCompileUnit( - *sc.comp_unit, modules_for_macros, error_stream); - } - } - } - } - - decl_vendor->ForEachMacro( - modules_for_macros, - [&module_macros](const std::string &expansion) -> bool { - module_macros.append(expansion); - module_macros.append("\n"); - return false; - }); - } - } - - StreamString debug_macros_stream; - StreamString lldb_local_var_decls; - if (StackFrame *frame = exe_ctx.GetFramePtr()) { - const SymbolContext &sc = frame->GetSymbolContext( - lldb::eSymbolContextCompUnit | lldb::eSymbolContextLineEntry); - - if (sc.comp_unit && sc.line_entry.IsValid()) { - DebugMacros *dm = sc.comp_unit->GetDebugMacros(); - if (dm) { - AddMacroState state(sc.line_entry.file, sc.line_entry.line); - AddMacros(dm, sc.comp_unit, state, debug_macros_stream); - } - } - - if (add_locals) { - if (Language::LanguageIsCPlusPlus(frame->GetLanguage())) { - if (target->GetInjectLocalVariables(&exe_ctx)) { - lldb::VariableListSP var_list_sp = - frame->GetInScopeVariableList(false, true); - AddLocalVariableDecls(var_list_sp, lldb_local_var_decls); - } - } - } - } - - if (m_wrap) { - switch (wrapping_language) { - default: - return false; - case lldb::eLanguageTypeC: - case lldb::eLanguageTypeC_plus_plus: - case lldb::eLanguageTypeObjC: - break; - } - - StreamString wrap_stream; - - wrap_stream.Printf("%s\n%s\n%s\n%s\n%s\n", module_macros.c_str(), - debug_macros_stream.GetData(), g_expression_prefix, - target_specific_defines, m_prefix.c_str()); - - // First construct a tagged form of the user expression so we can find it - // later: - std::string tagged_body; - switch (wrapping_language) { - default: - tagged_body = m_body; - break; - case lldb::eLanguageTypeC: - case lldb::eLanguageTypeC_plus_plus: - case lldb::eLanguageTypeObjC: - tagged_body.append(c_start_marker); - tagged_body.append(m_body); - tagged_body.append(c_end_marker); - break; - } - switch (wrapping_language) { - default: - break; - case lldb::eLanguageTypeC: - wrap_stream.Printf("void \n" - "%s(void *$__lldb_arg) \n" - "{ \n" - " %s; \n" - "%s" - "} \n", - m_name.c_str(), lldb_local_var_decls.GetData(), - tagged_body.c_str()); - break; - case lldb::eLanguageTypeC_plus_plus: - wrap_stream.Printf("void \n" - "$__lldb_class::%s(void *$__lldb_arg) \n" - "{ \n" - " %s; \n" - "%s" - "} \n", - m_name.c_str(), lldb_local_var_decls.GetData(), - tagged_body.c_str()); - break; - case lldb::eLanguageTypeObjC: - if (static_method) { - wrap_stream.Printf( - "@interface $__lldb_objc_class ($__lldb_category) \n" - "+(void)%s:(void *)$__lldb_arg; \n" - "@end \n" - "@implementation $__lldb_objc_class ($__lldb_category) \n" - "+(void)%s:(void *)$__lldb_arg \n" - "{ \n" - "%s" - "} \n" - "@end \n", - m_name.c_str(), m_name.c_str(), tagged_body.c_str()); - } else { - wrap_stream.Printf( - "@interface $__lldb_objc_class ($__lldb_category) \n" - "-(void)%s:(void *)$__lldb_arg; \n" - "@end \n" - "@implementation $__lldb_objc_class ($__lldb_category) \n" - "-(void)%s:(void *)$__lldb_arg \n" - "{ \n" - "%s" - "} \n" - "@end \n", - m_name.c_str(), m_name.c_str(), tagged_body.c_str()); - } - break; - } - - text = wrap_stream.GetString(); - } else { - text.append(m_body); - } - - return true; -} - -bool ExpressionSourceCode::GetOriginalBodyBounds( - std::string transformed_text, lldb::LanguageType wrapping_language, - size_t &start_loc, size_t &end_loc) { - const char *start_marker; - const char *end_marker; - - switch (wrapping_language) { - default: - return false; - case lldb::eLanguageTypeC: - case lldb::eLanguageTypeC_plus_plus: - case lldb::eLanguageTypeObjC: - start_marker = c_start_marker; - end_marker = c_end_marker; - break; - } - - start_loc = transformed_text.find(start_marker); - if (start_loc == std::string::npos) - return false; - start_loc += strlen(start_marker); - end_loc = transformed_text.find(end_marker); - return end_loc != std::string::npos; -} Index: source/Expression/LLVMUserExpression.cpp =================================================================== --- source/Expression/LLVMUserExpression.cpp +++ source/Expression/LLVMUserExpression.cpp @@ -12,7 +12,6 @@ #include "lldb/Core/StreamFile.h" #include "lldb/Core/ValueObjectConstResult.h" #include "lldb/Expression/DiagnosticManager.h" -#include "lldb/Expression/ExpressionSourceCode.h" #include "lldb/Expression/IRExecutionUnit.h" #include "lldb/Expression/IRInterpreter.h" #include "lldb/Expression/Materializer.h" Index: source/Expression/UserExpression.cpp =================================================================== --- source/Expression/UserExpression.cpp +++ source/Expression/UserExpression.cpp @@ -20,7 +20,6 @@ #include "lldb/Core/StreamFile.h" #include "lldb/Core/ValueObjectConstResult.h" #include "lldb/Expression/DiagnosticManager.h" -#include "lldb/Expression/ExpressionSourceCode.h" #include "lldb/Expression/IRExecutionUnit.h" #include "lldb/Expression/IRInterpreter.h" #include "lldb/Expression/Materializer.h" Index: source/Expression/UtilityFunction.cpp =================================================================== --- source/Expression/UtilityFunction.cpp +++ source/Expression/UtilityFunction.cpp @@ -15,7 +15,6 @@ #include "lldb/Core/Module.h" #include "lldb/Core/StreamFile.h" #include "lldb/Expression/DiagnosticManager.h" -#include "lldb/Expression/ExpressionSourceCode.h" #include "lldb/Expression/FunctionCaller.h" #include "lldb/Expression/IRExecutionUnit.h" #include "lldb/Expression/UtilityFunction.h" @@ -42,11 +41,8 @@ UtilityFunction::UtilityFunction(ExecutionContextScope &exe_scope, const char *text, const char *name) : Expression(exe_scope), m_execution_unit_sp(), m_jit_module_wp(), - m_function_text(ExpressionSourceCode::g_expression_prefix), - m_function_name(name) { - if (text && text[0]) - m_function_text.append(text); -} + m_function_text(), + m_function_name(name) {} UtilityFunction::~UtilityFunction() { lldb::ProcessSP process_sp(m_jit_process_wp.lock()); Index: source/Plugins/ExpressionParser/Clang/ClangExpressionSourceCode.h =================================================================== --- source/Plugins/ExpressionParser/Clang/ClangExpressionSourceCode.h +++ source/Plugins/ExpressionParser/Clang/ClangExpressionSourceCode.h @@ -0,0 +1,55 @@ +//===-- ClangExpressionSourceCode.h -----------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_ClangExpressionSourceCode_h +#define liblldb_ClangExpressionSourceCode_h + +#include "lldb/Expression/Expression.h" +#include "lldb/Expression/ExpressionSourceCode.h" +#include "lldb/lldb-enumerations.h" +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/StringRef.h" + +#include + +namespace lldb_private { + +class ExecutionContext; + +class ClangExpressionSourceCode : public ExpressionSourceCode { +public: + static const char *g_expression_prefix; + + static ClangExpressionSourceCode *CreateWrapped(const char *prefix, + const char *body) { + return new ClangExpressionSourceCode("$__lldb_expr", prefix, body, true); + } + + uint32_t GetNumBodyLines(); + + bool GetText(std::string &text, lldb::LanguageType wrapping_language, + bool static_method, + ExecutionContext &exe_ctx, + bool add_locals) const; + + // Given a string returned by GetText, find the beginning and end of the body + // passed to CreateWrapped. Return true if the bounds could be found. This + // will also work on text with FixItHints applied. + static bool GetOriginalBodyBounds(std::string transformed_text, + lldb::LanguageType wrapping_language, + size_t &start_loc, size_t &end_loc); + +protected: + ClangExpressionSourceCode(const char *name, const char *prefix, const char *body, + bool wrap) : + ExpressionSourceCode(name, prefix, body, wrap) {} +}; + +} // namespace lldb_private + +#endif Index: source/Plugins/ExpressionParser/Clang/ClangExpressionSourceCode.cpp =================================================================== --- source/Plugins/ExpressionParser/Clang/ClangExpressionSourceCode.cpp +++ source/Plugins/ExpressionParser/Clang/ClangExpressionSourceCode.cpp @@ -0,0 +1,380 @@ +//===-- ClangExpressionSourceCode.cpp ---------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "ClangExpressionSourceCode.h" + +#include "Plugins/ExpressionParser/Clang/ClangModulesDeclVendor.h" +#include "Plugins/ExpressionParser/Clang/ClangPersistentVariables.h" +#include "lldb/Symbol/Block.h" +#include "lldb/Symbol/CompileUnit.h" +#include "lldb/Symbol/DebugMacros.h" +#include "lldb/Symbol/TypeSystem.h" +#include "lldb/Symbol/VariableList.h" +#include "lldb/Target/ExecutionContext.h" +#include "lldb/Target/Language.h" +#include "lldb/Target/Platform.h" +#include "lldb/Target/StackFrame.h" +#include "lldb/Target/Target.h" +#include "lldb/Utility/StreamString.h" + +using namespace lldb_private; + +const char *ClangExpressionSourceCode::g_expression_prefix = R"( +#ifndef NULL +#define NULL (__null) +#endif +#ifndef Nil +#define Nil (__null) +#endif +#ifndef nil +#define nil (__null) +#endif +#ifndef YES +#define YES ((BOOL)1) +#endif +#ifndef NO +#define NO ((BOOL)0) +#endif +typedef __INT8_TYPE__ int8_t; +typedef __UINT8_TYPE__ uint8_t; +typedef __INT16_TYPE__ int16_t; +typedef __UINT16_TYPE__ uint16_t; +typedef __INT32_TYPE__ int32_t; +typedef __UINT32_TYPE__ uint32_t; +typedef __INT64_TYPE__ int64_t; +typedef __UINT64_TYPE__ uint64_t; +typedef __INTPTR_TYPE__ intptr_t; +typedef __UINTPTR_TYPE__ uintptr_t; +typedef __SIZE_TYPE__ size_t; +typedef __PTRDIFF_TYPE__ ptrdiff_t; +typedef unsigned short unichar; +extern "C" +{ + int printf(const char * __restrict, ...); +} +)"; + +static const char *c_start_marker = " /*LLDB_BODY_START*/\n "; +static const char *c_end_marker = ";\n /*LLDB_BODY_END*/\n"; + +namespace { + +class AddMacroState { + enum State { + CURRENT_FILE_NOT_YET_PUSHED, + CURRENT_FILE_PUSHED, + CURRENT_FILE_POPPED + }; + +public: + AddMacroState(const FileSpec ¤t_file, const uint32_t current_file_line) + : m_state(CURRENT_FILE_NOT_YET_PUSHED), m_current_file(current_file), + m_current_file_line(current_file_line) {} + + void StartFile(const FileSpec &file) { + m_file_stack.push_back(file); + if (file == m_current_file) + m_state = CURRENT_FILE_PUSHED; + } + + void EndFile() { + if (m_file_stack.size() == 0) + return; + + FileSpec old_top = m_file_stack.back(); + m_file_stack.pop_back(); + if (old_top == m_current_file) + m_state = CURRENT_FILE_POPPED; + } + + // An entry is valid if it occurs before the current line in the current + // file. + bool IsValidEntry(uint32_t line) { + switch (m_state) { + case CURRENT_FILE_NOT_YET_PUSHED: + return true; + case CURRENT_FILE_PUSHED: + // If we are in file included in the current file, the entry should be + // added. + if (m_file_stack.back() != m_current_file) + return true; + + return line < m_current_file_line; + default: + return false; + } + } + +private: + std::vector m_file_stack; + State m_state; + FileSpec m_current_file; + uint32_t m_current_file_line; +}; + +} // anonymous namespace + +static void AddMacros(const DebugMacros *dm, CompileUnit *comp_unit, + AddMacroState &state, StreamString &stream) { + if (dm == nullptr) + return; + + for (size_t i = 0; i < dm->GetNumMacroEntries(); i++) { + const DebugMacroEntry &entry = dm->GetMacroEntryAtIndex(i); + uint32_t line; + + switch (entry.GetType()) { + case DebugMacroEntry::DEFINE: + if (state.IsValidEntry(entry.GetLineNumber())) + stream.Printf("#define %s\n", entry.GetMacroString().AsCString()); + else + return; + break; + case DebugMacroEntry::UNDEF: + if (state.IsValidEntry(entry.GetLineNumber())) + stream.Printf("#undef %s\n", entry.GetMacroString().AsCString()); + else + return; + break; + case DebugMacroEntry::START_FILE: + line = entry.GetLineNumber(); + if (state.IsValidEntry(line)) + state.StartFile(entry.GetFileSpec(comp_unit)); + else + return; + break; + case DebugMacroEntry::END_FILE: + state.EndFile(); + break; + case DebugMacroEntry::INDIRECT: + AddMacros(entry.GetIndirectDebugMacros(), comp_unit, state, stream); + break; + default: + // This is an unknown/invalid entry. Ignore. + break; + } + } +} + +static void AddLocalVariableDecls(const lldb::VariableListSP &var_list_sp, + StreamString &stream) { + for (size_t i = 0; i < var_list_sp->GetSize(); i++) { + lldb::VariableSP var_sp = var_list_sp->GetVariableAtIndex(i); + + ConstString var_name = var_sp->GetName(); + if (!var_name || var_name == ConstString("this") || + var_name == ConstString(".block_descriptor")) + continue; + + stream.Printf("using $__lldb_local_vars::%s;\n", var_name.AsCString()); + } +} + +bool ClangExpressionSourceCode::GetText(std::string &text, + lldb::LanguageType wrapping_language, + bool static_method, + ExecutionContext &exe_ctx, + bool add_locals) const { + const char *target_specific_defines = "typedef signed char BOOL;\n"; + std::string module_macros; + + Target *target = exe_ctx.GetTargetPtr(); + if (target) { + if (target->GetArchitecture().GetMachine() == llvm::Triple::aarch64) { + target_specific_defines = "typedef bool BOOL;\n"; + } + if (target->GetArchitecture().GetMachine() == llvm::Triple::x86_64) { + if (lldb::PlatformSP platform_sp = target->GetPlatform()) { + static ConstString g_platform_ios_simulator("ios-simulator"); + if (platform_sp->GetPluginName() == g_platform_ios_simulator) { + target_specific_defines = "typedef bool BOOL;\n"; + } + } + } + + if (ClangModulesDeclVendor *decl_vendor = + target->GetClangModulesDeclVendor()) { + ClangPersistentVariables *persistent_vars = + llvm::cast( + target->GetPersistentExpressionStateForLanguage( + lldb::eLanguageTypeC)); + const ClangModulesDeclVendor::ModuleVector &hand_imported_modules = + persistent_vars->GetHandLoadedClangModules(); + ClangModulesDeclVendor::ModuleVector modules_for_macros; + + for (ClangModulesDeclVendor::ModuleID module : hand_imported_modules) { + modules_for_macros.push_back(module); + } + + if (target->GetEnableAutoImportClangModules()) { + if (StackFrame *frame = exe_ctx.GetFramePtr()) { + if (Block *block = frame->GetFrameBlock()) { + SymbolContext sc; + + block->CalculateSymbolContext(&sc); + + if (sc.comp_unit) { + StreamString error_stream; + + decl_vendor->AddModulesForCompileUnit( + *sc.comp_unit, modules_for_macros, error_stream); + } + } + } + } + + decl_vendor->ForEachMacro( + modules_for_macros, + [&module_macros](const std::string &expansion) -> bool { + module_macros.append(expansion); + module_macros.append("\n"); + return false; + }); + } + } + + StreamString debug_macros_stream; + StreamString lldb_local_var_decls; + if (StackFrame *frame = exe_ctx.GetFramePtr()) { + const SymbolContext &sc = frame->GetSymbolContext( + lldb::eSymbolContextCompUnit | lldb::eSymbolContextLineEntry); + + if (sc.comp_unit && sc.line_entry.IsValid()) { + DebugMacros *dm = sc.comp_unit->GetDebugMacros(); + if (dm) { + AddMacroState state(sc.line_entry.file, sc.line_entry.line); + AddMacros(dm, sc.comp_unit, state, debug_macros_stream); + } + } + + if (add_locals) { + if (Language::LanguageIsCPlusPlus(frame->GetLanguage())) { + if (target->GetInjectLocalVariables(&exe_ctx)) { + lldb::VariableListSP var_list_sp = + frame->GetInScopeVariableList(false, true); + AddLocalVariableDecls(var_list_sp, lldb_local_var_decls); + } + } + } + } + + if (m_wrap) { + switch (wrapping_language) { + default: + return false; + case lldb::eLanguageTypeC: + case lldb::eLanguageTypeC_plus_plus: + case lldb::eLanguageTypeObjC: + break; + } + + StreamString wrap_stream; + + wrap_stream.Printf("%s\n%s\n%s\n%s\n%s\n", module_macros.c_str(), + debug_macros_stream.GetData(), g_expression_prefix, + target_specific_defines, m_prefix.c_str()); + + // First construct a tagged form of the user expression so we can find it + // later: + std::string tagged_body; + switch (wrapping_language) { + default: + tagged_body = m_body; + break; + case lldb::eLanguageTypeC: + case lldb::eLanguageTypeC_plus_plus: + case lldb::eLanguageTypeObjC: + tagged_body.append(c_start_marker); + tagged_body.append(m_body); + tagged_body.append(c_end_marker); + break; + } + switch (wrapping_language) { + default: + break; + case lldb::eLanguageTypeC: + wrap_stream.Printf("void \n" + "%s(void *$__lldb_arg) \n" + "{ \n" + " %s; \n" + "%s" + "} \n", + m_name.c_str(), lldb_local_var_decls.GetData(), + tagged_body.c_str()); + break; + case lldb::eLanguageTypeC_plus_plus: + wrap_stream.Printf("void \n" + "$__lldb_class::%s(void *$__lldb_arg) \n" + "{ \n" + " %s; \n" + "%s" + "} \n", + m_name.c_str(), lldb_local_var_decls.GetData(), + tagged_body.c_str()); + break; + case lldb::eLanguageTypeObjC: + if (static_method) { + wrap_stream.Printf( + "@interface $__lldb_objc_class ($__lldb_category) \n" + "+(void)%s:(void *)$__lldb_arg; \n" + "@end \n" + "@implementation $__lldb_objc_class ($__lldb_category) \n" + "+(void)%s:(void *)$__lldb_arg \n" + "{ \n" + "%s" + "} \n" + "@end \n", + m_name.c_str(), m_name.c_str(), tagged_body.c_str()); + } else { + wrap_stream.Printf( + "@interface $__lldb_objc_class ($__lldb_category) \n" + "-(void)%s:(void *)$__lldb_arg; \n" + "@end \n" + "@implementation $__lldb_objc_class ($__lldb_category) \n" + "-(void)%s:(void *)$__lldb_arg \n" + "{ \n" + "%s" + "} \n" + "@end \n", + m_name.c_str(), m_name.c_str(), tagged_body.c_str()); + } + break; + } + + text = wrap_stream.GetString(); + } else { + text.append(m_body); + } + + return true; +} + +bool ClangExpressionSourceCode::GetOriginalBodyBounds( + std::string transformed_text, lldb::LanguageType wrapping_language, + size_t &start_loc, size_t &end_loc) { + const char *start_marker; + const char *end_marker; + + switch (wrapping_language) { + default: + return false; + case lldb::eLanguageTypeC: + case lldb::eLanguageTypeC_plus_plus: + case lldb::eLanguageTypeObjC: + start_marker = c_start_marker; + end_marker = c_end_marker; + break; + } + + start_loc = transformed_text.find(start_marker); + if (start_loc == std::string::npos) + return false; + start_loc += strlen(start_marker); + end_loc = transformed_text.find(end_marker); + return end_loc != std::string::npos; +} Index: source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp =================================================================== --- source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp +++ source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp @@ -21,6 +21,7 @@ #include "ClangDiagnostic.h" #include "ClangExpressionDeclMap.h" #include "ClangExpressionParser.h" +#include "ClangExpressionSourceCode.h" #include "ClangModulesDeclVendor.h" #include "ClangPersistentVariables.h" @@ -404,8 +405,8 @@ if (m_options.GetExecutionPolicy() == eExecutionPolicyTopLevel) { m_transformed_text = m_expr_text; } else { - std::unique_ptr source_code( - ExpressionSourceCode::CreateWrapped(prefix.c_str(), + std::unique_ptr source_code( + ClangExpressionSourceCode::CreateWrapped(prefix.c_str(), m_expr_text.c_str())); if (m_in_cplusplus_method) @@ -529,7 +530,7 @@ size_t fixed_end; const std::string &fixed_expression = diagnostic_manager.GetFixedExpression(); - if (ExpressionSourceCode::GetOriginalBodyBounds( + if (ClangExpressionSourceCode::GetOriginalBodyBounds( fixed_expression, m_expr_lang, fixed_start, fixed_end)) m_fixed_text = fixed_expression.substr(fixed_start, fixed_end - fixed_start); Index: source/Plugins/ExpressionParser/Clang/ClangUtilityFunction.cpp =================================================================== --- source/Plugins/ExpressionParser/Clang/ClangUtilityFunction.cpp +++ source/Plugins/ExpressionParser/Clang/ClangUtilityFunction.cpp @@ -9,6 +9,7 @@ #include "ClangUtilityFunction.h" #include "ClangExpressionDeclMap.h" #include "ClangExpressionParser.h" +#include "ClangExpressionSourceCode.h" #include #if HAVE_SYS_TYPES_H @@ -18,7 +19,6 @@ #include "lldb/Core/Module.h" #include "lldb/Core/StreamFile.h" -#include "lldb/Expression/ExpressionSourceCode.h" #include "lldb/Expression/IRExecutionUnit.h" #include "lldb/Host/Host.h" #include "lldb/Target/ExecutionContext.h" @@ -40,7 +40,11 @@ //------------------------------------------------------------------ ClangUtilityFunction::ClangUtilityFunction(ExecutionContextScope &exe_scope, const char *text, const char *name) - : UtilityFunction(exe_scope, text, name) {} + : UtilityFunction(exe_scope, text, name) { + m_function_text.assign(ClangExpressionSourceCode::g_expression_prefix); + if (text && text[0]) + m_function_text.append(text); +} ClangUtilityFunction::~ClangUtilityFunction() {}