13#include "clang/Basic/CharInfo.h"
14#include "clang/Basic/FileManager.h"
15#include "clang/Basic/SourceManager.h"
16#include "clang/Lex/Lexer.h"
17#include "llvm/ADT/ScopeExit.h"
18#include "llvm/ADT/StringRef.h"
37#define PREFIX_NAME "<lldb wrapper prefix>"
38#define SUFFIX_NAME "<lldb wrapper suffix>"
45#define offsetof(t, d) __builtin_offsetof(t, d)
62typedef __INT8_TYPE__ int8_t;
63typedef __UINT8_TYPE__ uint8_t;
64typedef __INT16_TYPE__ int16_t;
65typedef __UINT16_TYPE__ uint16_t;
66typedef __INT32_TYPE__ int32_t;
67typedef __UINT32_TYPE__ uint32_t;
68typedef __INT64_TYPE__ int64_t;
69typedef __UINT64_TYPE__ uint64_t;
70typedef __INTPTR_TYPE__ intptr_t;
71typedef __UINTPTR_TYPE__ uintptr_t;
72typedef __SIZE_TYPE__ size_t;
73typedef __PTRDIFF_TYPE__ ptrdiff_t;
74typedef unsigned short unichar;
77 int printf(const char * __restrict, ...);
88 CURRENT_FILE_NOT_YET_PUSHED,
94 AddMacroState(
const FileSpec ¤t_file,
const uint32_t current_file_line)
95 : m_current_file(current_file), m_current_file_line(current_file_line) {}
97 void StartFile(
const FileSpec &file) {
98 m_file_stack.push_back(file);
99 if (file == m_current_file)
100 m_state = CURRENT_FILE_PUSHED;
104 if (m_file_stack.size() == 0)
107 FileSpec old_top = m_file_stack.back();
108 m_file_stack.pop_back();
109 if (old_top == m_current_file)
110 m_state = CURRENT_FILE_POPPED;
115 bool IsValidEntry(uint32_t line) {
117 case CURRENT_FILE_NOT_YET_PUSHED:
119 case CURRENT_FILE_PUSHED:
122 if (m_file_stack.back() != m_current_file)
125 return line < m_current_file_line;
132 std::vector<FileSpec> m_file_stack;
133 State m_state = CURRENT_FILE_NOT_YET_PUSHED;
135 uint32_t m_current_file_line;
149 stream <<
"#pragma clang diagnostic push\n";
150 stream <<
"#pragma clang diagnostic ignored \"-Wmacro-redefined\"\n";
151 stream <<
"#pragma clang diagnostic ignored \"-Wbuiltin-macro-redefined\"\n";
152 auto pop_warning = llvm::make_scope_exit([&stream](){
153 stream <<
"#pragma clang diagnostic pop\n";
175 if (state.IsValidEntry(line))
194 llvm::StringRef filename, llvm::StringRef name, llvm::StringRef prefix,
208 llvm::StringSet<> m_tokens;
211 TokenVerifier(std::string body);
214 bool hasToken(llvm::StringRef token)
const {
215 return m_tokens.contains(token);
228 TokenVerifier
const &verifier) {
232 uint32_t numChildren = thisValSP->GetNumChildrenIgnoringErrors();
233 for (uint32_t i = 0; i < numChildren; ++i) {
234 auto childVal = thisValSP->GetChildAtIndex(i);
237 if (!childName.IsEmpty() && verifier.hasToken(childName.GetStringRef()) &&
238 childName !=
"this") {
239 stream.
Printf(
"using $__lldb_local_vars::%s;\n",
240 childName.GetCString());
248TokenVerifier::TokenVerifier(std::string body) {
249 using namespace clang;
254 std::replace(body.begin(), body.end(),
'\n',
' ');
255 std::replace(body.begin(), body.end(),
'\r',
' ');
257 FileSystemOptions file_opts;
258 FileManager file_mgr(file_opts,
263 llvm::IntrusiveRefCntPtr<DiagnosticIDs> diag_ids(
new DiagnosticIDs());
264 llvm::IntrusiveRefCntPtr<DiagnosticOptions> diags_opts(
265 new DiagnosticOptions());
266 DiagnosticsEngine diags(diag_ids, diags_opts);
267 clang::SourceManager SM(diags, file_mgr);
268 auto buf = llvm::MemoryBuffer::getMemBuffer(body);
270 FileID FID = SM.createFileID(buf->getMemBufferRef());
276 Opts.DollarIdents =
true;
277 Opts.CPlusPlus20 =
true;
278 Opts.LineComment =
true;
280 Lexer lex(FID, buf->getMemBufferRef(), SM, Opts);
286 exit = lex.LexFromRawLexer(token);
291 bool invalid =
false;
292 unsigned start = SM.getSpellingColumnNumber(token.getLocation(), &invalid);
299 if (token.isAnnotation())
303 std::string token_str = body.substr(start, token.getLength());
304 if (token_str.empty())
306 m_tokens.insert(token_str);
311 const std::string &expr,
314 TokenVerifier tokens(expr);
318 for (
size_t i = 0; i < var_list_sp->GetSize(); i++) {
324 AddLambdaCaptureDecls(stream, frame, tokens);
331 if (!var_name || var_name ==
".block_descriptor")
334 if (!expr.empty() && !tokens.hasToken(var_name.
GetStringRef()))
339 if ((var_name ==
"self" || var_name ==
"_cmd") && is_objc)
342 stream.
Printf(
"using $__lldb_local_vars::%s;\n", var_name.
AsCString());
348 bool force_add_all_locals, llvm::ArrayRef<std::string> modules)
const {
349 const char *target_specific_defines =
"typedef signed char BOOL;\n";
350 std::string module_macros;
351 llvm::raw_string_ostream module_macros_stream(module_macros);
357 target_specific_defines =
"typedef bool BOOL;\n";
361 if (platform_sp->GetPluginName() ==
"ios-simulator") {
362 target_specific_defines =
"typedef bool BOOL;\n";
367 auto *persistent_vars = llvm::cast<ClangPersistentVariables>(
369 std::shared_ptr<ClangModulesDeclVendor> decl_vendor =
370 persistent_vars->GetClangModulesDeclVendor();
373 persistent_vars->GetHandLoadedClangModules();
377 modules_for_macros.push_back(module);
385 block->CalculateSymbolContext(&sc);
390 decl_vendor->AddModulesForCompileUnit(
391 *sc.
comp_unit, modules_for_macros, error_stream);
397 decl_vendor->ForEachMacro(
399 [&module_macros_stream](llvm::StringRef token,
400 llvm::StringRef expansion) ->
bool {
403 module_macros_stream <<
"#ifndef " << token <<
"\n";
404 module_macros_stream << expansion <<
"\n";
405 module_macros_stream <<
"#endif\n";
415 lldb::eSymbolContextCompUnit | lldb::eSymbolContextLineEntry);
428 force_add_all_locals ?
"" :
m_body, frame);
435 std::string module_imports;
436 for (
const std::string &module : modules) {
437 module_imports.append(
"@import ");
438 module_imports.append(module);
439 module_imports.append(
";\n");
445 module_macros.c_str(), debug_macros_stream.
GetData(),
446 target_specific_defines,
m_prefix.c_str());
450 std::string tagged_body;
452 tagged_body.append(
m_body);
459 "%s(void *$__lldb_arg) \n"
464 module_imports.c_str(),
m_name.c_str(),
465 lldb_local_var_decls.
GetData(), tagged_body.c_str());
470 "$__lldb_class::%s(void *$__lldb_arg) \n"
475 module_imports.c_str(),
m_name.c_str(),
476 lldb_local_var_decls.
GetData(), tagged_body.c_str());
481 "@interface $__lldb_objc_class ($__lldb_category) \n"
482 "-(void)%s:(void *)$__lldb_arg; \n"
484 "@implementation $__lldb_objc_class ($__lldb_category) \n"
485 "-(void)%s:(void *)$__lldb_arg \n"
492 lldb_local_var_decls.
GetData(), tagged_body.c_str());
498 "@interface $__lldb_objc_class ($__lldb_category) \n"
499 "+(void)%s:(void *)$__lldb_arg; \n"
501 "@implementation $__lldb_objc_class ($__lldb_category) \n"
502 "+(void)%s:(void *)$__lldb_arg \n"
509 lldb_local_var_decls.
GetData(), tagged_body.c_str());
513 text = std::string(wrap_stream.
GetString());
522 std::string transformed_text,
size_t &start_loc,
size_t &end_loc) {
524 if (start_loc == std::string::npos)
528 return end_loc != std::string::npos;
static void AddMacros(const DebugMacros *dm, CompileUnit *comp_unit, AddMacroState &state, StreamString &stream)
llvm::Triple::ArchType GetMachine() const
Returns a machine family for the current architecture.
A class that describes a single lexical block.
static const char * g_expression_prefix
ClangExpressionSourceCode(llvm::StringRef filename, llvm::StringRef name, llvm::StringRef prefix, llvm::StringRef body, Wrapping wrap, WrapKind wrap_kind)
WrapKind
The possible ways an expression can be wrapped.
@ ObjCStaticMethod
Wrapped in a static Objective-C method.
@ CppMemberFunction
Wrapped in a non-static member function of a C++ class.
@ ObjCInstanceMethod
Wrapped in an instance Objective-C method.
@ Function
Wrapped in a non-member function.
std::string m_start_marker
String marking the start of the user expression.
static const llvm::StringRef g_prefix_file_name
The file name we use for the wrapper code that we inject before the user expression.
bool GetText(std::string &text, ExecutionContext &exe_ctx, bool add_locals, bool force_add_all_locals, llvm::ArrayRef< std::string > modules) const
Generates the source code that will evaluate the expression.
bool GetOriginalBodyBounds(std::string transformed_text, size_t &start_loc, size_t &end_loc)
const WrapKind m_wrap_kind
How the expression has been wrapped.
static const char * g_expression_suffix
std::string m_end_marker
String marking the end of the user expression.
void AddLocalVariableDecls(StreamString &stream, const std::string &expr, StackFrame *frame) const
Writes "using" declarations for local variables into the specified stream.
std::vector< ModuleID > ModuleVector
A class that describes a compilation unit.
DebugMacros * GetDebugMacros()
A uniqued constant string class.
const char * AsCString(const char *value_if_empty=nullptr) const
Get the string value as a C string.
llvm::StringRef GetStringRef() const
Get the string value as a llvm::StringRef.
ConstString GetMacroString() const
const FileSpec & GetFileSpec(CompileUnit *comp_unit) const
DebugMacros * GetIndirectDebugMacros() const
EntryType GetType() const
uint64_t GetLineNumber() const
DebugMacroEntry GetMacroEntryAtIndex(const size_t index) const
size_t GetNumMacroEntries() const
"lldb/Target/ExecutionContext.h" A class that contains an execution context.
StackFrame * GetFramePtr() const
Returns a pointer to the frame object.
Target * GetTargetPtr() const
Returns a pointer to the target object.
static FileSystem & Instance()
This base class provides an interface to stack frames.
lldb::VariableListSP GetInScopeVariableList(bool get_file_globals, bool must_have_valid_location=false)
Retrieve the list of variables that are in scope at this StackFrame's pc.
const SymbolContext & GetSymbolContext(lldb::SymbolContextItem resolve_scope)
Provide a SymbolContext for this StackFrame's current pc value.
Block * GetFrameBlock()
Get the current lexical scope block for this StackFrame, if possible.
const char * GetData() const
llvm::StringRef GetString() const
size_t Printf(const char *format,...) __attribute__((format(printf
Output printf formatted output to the stream.
Defines a symbol context baton that can be handed other debug core functions.
CompileUnit * comp_unit
The CompileUnit for a given query.
LineEntry line_entry
The LineEntry for a given query.
bool GetEnableAutoImportClangModules() const
bool GetInjectLocalVariables(ExecutionContext *exe_ctx) const
PersistentExpressionState * GetPersistentExpressionStateForLanguage(lldb::LanguageType language)
lldb::PlatformSP GetPlatform()
const ArchSpec & GetArchitecture() const
lldb::ValueObjectSP GetLambdaValueObject(StackFrame *frame)
Returns a ValueObject for the lambda class in the current frame.
A class that represents a running process on the host machine.
std::shared_ptr< lldb_private::Platform > PlatformSP
@ eLanguageTypeC
Non-standardized C, such as K&R.
std::shared_ptr< lldb_private::VariableList > VariableListSP
std::shared_ptr< lldb_private::Variable > VariableSP
bool IsValid() const
Check if a line entry object is valid.
uint32_t line
The source line number, or LLDB_INVALID_LINE_NUMBER if there is no line number information.
const FileSpec & GetFile() const
Helper to access the file.