13#include "clang/AST/TypeBase.h"
14#include "clang/Basic/CharInfo.h"
15#include "clang/Basic/FileManager.h"
16#include "clang/Basic/SourceManager.h"
17#include "clang/Lex/Lexer.h"
18#include "llvm/ADT/ScopeExit.h"
19#include "llvm/ADT/StringRef.h"
38#define PREFIX_NAME "<lldb wrapper prefix>"
39#define SUFFIX_NAME "<lldb wrapper suffix>"
46#define offsetof(t, d) __builtin_offsetof(t, d)
63typedef __INT8_TYPE__ int8_t;
64typedef __UINT8_TYPE__ uint8_t;
65typedef __INT16_TYPE__ int16_t;
66typedef __UINT16_TYPE__ uint16_t;
67typedef __INT32_TYPE__ int32_t;
68typedef __UINT32_TYPE__ uint32_t;
69typedef __INT64_TYPE__ int64_t;
70typedef __UINT64_TYPE__ uint64_t;
71typedef __INTPTR_TYPE__ intptr_t;
72typedef __UINTPTR_TYPE__ uintptr_t;
73typedef __SIZE_TYPE__ size_t;
74typedef __PTRDIFF_TYPE__ ptrdiff_t;
75typedef unsigned short unichar;
78 int printf(const char * __restrict, ...);
89 CURRENT_FILE_NOT_YET_PUSHED,
95 AddMacroState(
const FileSpec ¤t_file,
const uint32_t current_file_line)
96 : m_current_file(current_file), m_current_file_line(current_file_line) {}
98 void StartFile(
const FileSpec &file) {
99 m_file_stack.push_back(file);
100 if (file == m_current_file)
101 m_state = CURRENT_FILE_PUSHED;
105 if (m_file_stack.size() == 0)
108 FileSpec old_top = m_file_stack.back();
109 m_file_stack.pop_back();
110 if (old_top == m_current_file)
111 m_state = CURRENT_FILE_POPPED;
116 bool IsValidEntry(uint32_t line) {
118 case CURRENT_FILE_NOT_YET_PUSHED:
120 case CURRENT_FILE_PUSHED:
123 if (m_file_stack.back() != m_current_file)
126 return line < m_current_file_line;
133 std::vector<FileSpec> m_file_stack;
134 State m_state = CURRENT_FILE_NOT_YET_PUSHED;
136 uint32_t m_current_file_line;
150 stream <<
"#pragma clang diagnostic push\n";
151 stream <<
"#pragma clang diagnostic ignored \"-Wmacro-redefined\"\n";
152 stream <<
"#pragma clang diagnostic ignored \"-Wbuiltin-macro-redefined\"\n";
153 llvm::scope_exit pop_warning(
154 [&stream]() { stream <<
"#pragma clang diagnostic pop\n"; });
175 if (state.IsValidEntry(line))
206 if (
auto this_this_sp = this_sp->GetChildMemberWithName(
"this"))
207 return clang::Qualifiers::fromCVRMask(
208 this_this_sp->GetCompilerType().GetPointeeType().GetTypeQualifiers());
211 return clang::Qualifiers::fromCVRMask(
212 this_sp->GetCompilerType().GetPointeeType().GetTypeQualifiers());
216 llvm::StringRef filename, llvm::StringRef name, llvm::StringRef prefix,
230 llvm::StringSet<> m_tokens;
233 TokenVerifier(std::string body);
236 bool hasToken(llvm::StringRef token)
const {
237 return m_tokens.contains(token);
250 TokenVerifier
const &verifier) {
254 uint32_t numChildren = thisValSP->GetNumChildrenIgnoringErrors();
255 for (uint32_t i = 0; i < numChildren; ++i) {
256 auto childVal = thisValSP->GetChildAtIndex(i);
259 if (!childName.IsEmpty() && verifier.hasToken(childName.GetStringRef()) &&
260 childName !=
"this") {
261 stream.
Printf(
"using $__lldb_local_vars::%s;\n",
262 childName.GetCString());
270TokenVerifier::TokenVerifier(std::string body) {
271 using namespace clang;
276 llvm::replace(body,
'\n',
' ');
277 llvm::replace(body,
'\r',
' ');
279 FileSystemOptions file_opts;
280 FileManager file_mgr(file_opts,
285 DiagnosticOptions diags_opts;
286 DiagnosticsEngine diags(DiagnosticIDs::create(), diags_opts);
287 clang::SourceManager SM(diags, file_mgr);
288 auto buf = llvm::MemoryBuffer::getMemBuffer(body);
290 FileID FID = SM.createFileID(buf->getMemBufferRef());
296 Opts.DollarIdents =
true;
297 Opts.CPlusPlus20 =
true;
298 Opts.LineComment =
true;
300 Lexer lex(FID, buf->getMemBufferRef(), SM, Opts);
306 exit = lex.LexFromRawLexer(token);
311 bool invalid =
false;
312 unsigned start = SM.getSpellingColumnNumber(token.getLocation(), &invalid);
319 if (token.isAnnotation())
323 std::string token_str = body.substr(start, token.getLength());
324 if (token_str.empty())
326 m_tokens.insert(token_str);
331 const std::string &expr,
334 TokenVerifier tokens(expr);
338 for (
size_t i = 0; i < var_list_sp->GetSize(); i++) {
344 AddLambdaCaptureDecls(stream, frame, tokens);
351 if (!var_name || var_name ==
".block_descriptor")
354 if (!expr.empty() && !tokens.hasToken(var_name.
GetStringRef()))
359 if ((var_name ==
"self" || var_name ==
"_cmd") && is_objc)
362 stream.
Printf(
"using $__lldb_local_vars::%s;\n", var_name.
AsCString());
369 bool force_add_all_locals,
370 llvm::ArrayRef<std::string> modules,
371 bool ignore_context_qualifiers)
const {
372 const char *target_specific_defines =
"typedef signed char BOOL;\n";
373 std::string module_macros;
374 llvm::raw_string_ostream module_macros_stream(module_macros);
380 target_specific_defines =
"typedef bool BOOL;\n";
384 if (platform_sp->GetPluginName() ==
"ios-simulator") {
385 target_specific_defines =
"typedef bool BOOL;\n";
390 auto *persistent_vars = llvm::cast<ClangPersistentVariables>(
392 std::shared_ptr<ClangModulesDeclVendor> decl_vendor =
393 persistent_vars->GetClangModulesDeclVendor();
396 persistent_vars->GetHandLoadedClangModules();
400 modules_for_macros.push_back(module);
408 block->CalculateSymbolContext(&sc);
411 if (
auto err = decl_vendor->AddModulesForCompileUnit(
415 "Error while loading hand-imported modules:\n{0}");
421 decl_vendor->ForEachMacro(
423 [&module_macros_stream](llvm::StringRef token,
424 llvm::StringRef expansion) ->
bool {
427 module_macros_stream <<
"#ifndef " << token <<
"\n";
428 module_macros_stream << expansion <<
"\n";
429 module_macros_stream <<
"#endif\n";
439 lldb::eSymbolContextCompUnit | lldb::eSymbolContextLineEntry);
452 force_add_all_locals ?
"" :
m_body, frame);
459 std::string module_imports;
460 for (
const std::string &module : modules) {
461 module_imports.append(
"@import ");
462 module_imports.append(module);
463 module_imports.append(
";\n");
469 module_macros.c_str(), debug_macros_stream.
GetData(),
470 target_specific_defines,
m_prefix.c_str());
474 std::string tagged_body;
476 tagged_body.append(
m_body);
483 "%s(void *$__lldb_arg) \n"
488 module_imports.c_str(),
m_name.c_str(),
489 lldb_local_var_decls.
GetData(), tagged_body.c_str());
494 "$__lldb_class::%s(void *$__lldb_arg) %s \n"
499 module_imports.c_str(),
m_name.c_str(),
500 ignore_context_qualifiers
505 lldb_local_var_decls.
GetData(), tagged_body.c_str());
510 "@interface $__lldb_objc_class ($__lldb_category) \n"
511 "-(void)%s:(void *)$__lldb_arg; \n"
513 "@implementation $__lldb_objc_class ($__lldb_category) \n"
514 "-(void)%s:(void *)$__lldb_arg \n"
521 lldb_local_var_decls.
GetData(), tagged_body.c_str());
527 "@interface $__lldb_objc_class ($__lldb_category) \n"
528 "+(void)%s:(void *)$__lldb_arg; \n"
530 "@implementation $__lldb_objc_class ($__lldb_category) \n"
531 "+(void)%s:(void *)$__lldb_arg \n"
538 lldb_local_var_decls.
GetData(), tagged_body.c_str());
542 text = std::string(wrap_stream.
GetString());
551 std::string transformed_text,
size_t &start_loc,
size_t &end_loc) {
553 if (start_loc == std::string::npos)
557 return end_loc != std::string::npos;
static void AddMacros(const DebugMacros *dm, CompileUnit *comp_unit, AddMacroState &state, StreamString &stream)
static clang::Qualifiers GetFrameCVQualifiers(StackFrame *frame)
Return qualifers of the current C++ method.
#define LLDB_LOG_ERROR(log, error,...)
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, bool ignore_context_qualifiers) 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.
ExpressionSourceCode(llvm::StringRef name, llvm::StringRef prefix, llvm::StringRef body, Wrapping wrap)
static FileSystem & Instance()
This base class provides an interface to stack frames.
virtual 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.
virtual const SymbolContext & GetSymbolContext(lldb::SymbolContextItem resolve_scope)
Provide a SymbolContext for this StackFrame's current pc value.
virtual Block * GetFrameBlock()
Get the current lexical scope block for this StackFrame, if possible.
virtual lldb::ValueObjectSP FindVariable(ConstString name)
Attempt to reconstruct the ValueObject for a variable with a given name from within the current Stack...
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.
Log * GetLog(Cat mask)
Retrieve the Log object for the channel associated with the given log enum.
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.