1 //===-- ExpressionSourceCode.cpp --------------------------------*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 #include "lldb/Expression/ExpressionSourceCode.h"
12 #include "Plugins/ExpressionParser/Clang/ClangModulesDeclVendor.h"
13 #include "Plugins/ExpressionParser/Clang/ClangPersistentVariables.h"
14 #include "lldb/Symbol/Block.h"
15 #include "lldb/Symbol/CompileUnit.h"
16 #include "lldb/Symbol/DebugMacros.h"
17 #include "lldb/Symbol/TypeSystem.h"
18 #include "lldb/Symbol/VariableList.h"
19 #include "lldb/Target/ExecutionContext.h"
20 #include "lldb/Target/Language.h"
21 #include "lldb/Target/Platform.h"
22 #include "lldb/Target/StackFrame.h"
23 #include "lldb/Target/Target.h"
24 #include "lldb/Utility/StreamString.h"
26 using namespace lldb_private;
28 const char *ExpressionSourceCode::g_expression_prefix = R"(
44 typedef __INT8_TYPE__ int8_t;
45 typedef __UINT8_TYPE__ uint8_t;
46 typedef __INT16_TYPE__ int16_t;
47 typedef __UINT16_TYPE__ uint16_t;
48 typedef __INT32_TYPE__ int32_t;
49 typedef __UINT32_TYPE__ uint32_t;
50 typedef __INT64_TYPE__ int64_t;
51 typedef __UINT64_TYPE__ uint64_t;
52 typedef __INTPTR_TYPE__ intptr_t;
53 typedef __UINTPTR_TYPE__ uintptr_t;
54 typedef __SIZE_TYPE__ size_t;
55 typedef __PTRDIFF_TYPE__ ptrdiff_t;
56 typedef unsigned short unichar;
59 int printf(const char * __restrict, ...);
63 static const char *c_start_marker = " /*LLDB_BODY_START*/\n ";
64 static const char *c_end_marker = ";\n /*LLDB_BODY_END*/\n";
70 CURRENT_FILE_NOT_YET_PUSHED,
76 AddMacroState(const FileSpec ¤t_file, const uint32_t current_file_line)
77 : m_state(CURRENT_FILE_NOT_YET_PUSHED), m_current_file(current_file),
78 m_current_file_line(current_file_line) {}
80 void StartFile(const FileSpec &file) {
81 m_file_stack.push_back(file);
82 if (file == m_current_file)
83 m_state = CURRENT_FILE_PUSHED;
87 if (m_file_stack.size() == 0)
90 FileSpec old_top = m_file_stack.back();
91 m_file_stack.pop_back();
92 if (old_top == m_current_file)
93 m_state = CURRENT_FILE_POPPED;
96 // An entry is valid if it occurs before the current line in the current
98 bool IsValidEntry(uint32_t line) {
100 case CURRENT_FILE_NOT_YET_PUSHED:
102 case CURRENT_FILE_PUSHED:
103 // If we are in file included in the current file, the entry should be
105 if (m_file_stack.back() != m_current_file)
108 return line < m_current_file_line;
115 std::vector<FileSpec> m_file_stack;
117 FileSpec m_current_file;
118 uint32_t m_current_file_line;
121 } // anonymous namespace
123 static void AddMacros(const DebugMacros *dm, CompileUnit *comp_unit,
124 AddMacroState &state, StreamString &stream) {
128 for (size_t i = 0; i < dm->GetNumMacroEntries(); i++) {
129 const DebugMacroEntry &entry = dm->GetMacroEntryAtIndex(i);
132 switch (entry.GetType()) {
133 case DebugMacroEntry::DEFINE:
134 if (state.IsValidEntry(entry.GetLineNumber()))
135 stream.Printf("#define %s\n", entry.GetMacroString().AsCString());
139 case DebugMacroEntry::UNDEF:
140 if (state.IsValidEntry(entry.GetLineNumber()))
141 stream.Printf("#undef %s\n", entry.GetMacroString().AsCString());
145 case DebugMacroEntry::START_FILE:
146 line = entry.GetLineNumber();
147 if (state.IsValidEntry(line))
148 state.StartFile(entry.GetFileSpec(comp_unit));
152 case DebugMacroEntry::END_FILE:
155 case DebugMacroEntry::INDIRECT:
156 AddMacros(entry.GetIndirectDebugMacros(), comp_unit, state, stream);
159 // This is an unknown/invalid entry. Ignore.
165 static void AddLocalVariableDecls(const lldb::VariableListSP &var_list_sp,
166 StreamString &stream) {
167 for (size_t i = 0; i < var_list_sp->GetSize(); i++) {
168 lldb::VariableSP var_sp = var_list_sp->GetVariableAtIndex(i);
170 ConstString var_name = var_sp->GetName();
171 if (!var_name || var_name == ConstString("this") ||
172 var_name == ConstString(".block_descriptor"))
175 stream.Printf("using $__lldb_local_vars::%s;\n", var_name.AsCString());
179 bool ExpressionSourceCode::GetText(std::string &text,
180 lldb::LanguageType wrapping_language,
182 ExecutionContext &exe_ctx) const {
183 const char *target_specific_defines = "typedef signed char BOOL;\n";
184 std::string module_macros;
186 Target *target = exe_ctx.GetTargetPtr();
188 if (target->GetArchitecture().GetMachine() == llvm::Triple::aarch64) {
189 target_specific_defines = "typedef bool BOOL;\n";
191 if (target->GetArchitecture().GetMachine() == llvm::Triple::x86_64) {
192 if (lldb::PlatformSP platform_sp = target->GetPlatform()) {
193 static ConstString g_platform_ios_simulator("ios-simulator");
194 if (platform_sp->GetPluginName() == g_platform_ios_simulator) {
195 target_specific_defines = "typedef bool BOOL;\n";
200 if (ClangModulesDeclVendor *decl_vendor =
201 target->GetClangModulesDeclVendor()) {
202 ClangPersistentVariables *persistent_vars =
203 llvm::cast<ClangPersistentVariables>(
204 target->GetPersistentExpressionStateForLanguage(
205 lldb::eLanguageTypeC));
206 const ClangModulesDeclVendor::ModuleVector &hand_imported_modules =
207 persistent_vars->GetHandLoadedClangModules();
208 ClangModulesDeclVendor::ModuleVector modules_for_macros;
210 for (ClangModulesDeclVendor::ModuleID module : hand_imported_modules) {
211 modules_for_macros.push_back(module);
214 if (target->GetEnableAutoImportClangModules()) {
215 if (StackFrame *frame = exe_ctx.GetFramePtr()) {
216 if (Block *block = frame->GetFrameBlock()) {
219 block->CalculateSymbolContext(&sc);
222 StreamString error_stream;
224 decl_vendor->AddModulesForCompileUnit(
225 *sc.comp_unit, modules_for_macros, error_stream);
231 decl_vendor->ForEachMacro(
233 [&module_macros](const std::string &expansion) -> bool {
234 module_macros.append(expansion);
235 module_macros.append("\n");
241 StreamString debug_macros_stream;
242 StreamString lldb_local_var_decls;
243 if (StackFrame *frame = exe_ctx.GetFramePtr()) {
244 const SymbolContext &sc = frame->GetSymbolContext(
245 lldb::eSymbolContextCompUnit | lldb::eSymbolContextLineEntry);
247 if (sc.comp_unit && sc.line_entry.IsValid()) {
248 DebugMacros *dm = sc.comp_unit->GetDebugMacros();
250 AddMacroState state(sc.line_entry.file, sc.line_entry.line);
251 AddMacros(dm, sc.comp_unit, state, debug_macros_stream);
255 ConstString object_name;
256 if (Language::LanguageIsCPlusPlus(frame->GetLanguage())) {
257 if (target->GetInjectLocalVariables(&exe_ctx)) {
258 lldb::VariableListSP var_list_sp =
259 frame->GetInScopeVariableList(false, true);
260 AddLocalVariableDecls(var_list_sp, lldb_local_var_decls);
266 switch (wrapping_language) {
269 case lldb::eLanguageTypeC:
270 case lldb::eLanguageTypeC_plus_plus:
271 case lldb::eLanguageTypeObjC:
275 StreamString wrap_stream;
277 wrap_stream.Printf("%s\n%s\n%s\n%s\n%s\n", module_macros.c_str(),
278 debug_macros_stream.GetData(), g_expression_prefix,
279 target_specific_defines, m_prefix.c_str());
281 // First construct a tagged form of the user expression so we can find it
283 std::string tagged_body;
284 switch (wrapping_language) {
286 tagged_body = m_body;
288 case lldb::eLanguageTypeC:
289 case lldb::eLanguageTypeC_plus_plus:
290 case lldb::eLanguageTypeObjC:
291 tagged_body.append(c_start_marker);
292 tagged_body.append(m_body);
293 tagged_body.append(c_end_marker);
296 switch (wrapping_language) {
299 case lldb::eLanguageTypeC:
300 wrap_stream.Printf("void \n"
301 "%s(void *$__lldb_arg) \n"
306 m_name.c_str(), lldb_local_var_decls.GetData(),
307 tagged_body.c_str());
309 case lldb::eLanguageTypeC_plus_plus:
310 wrap_stream.Printf("void \n"
311 "$__lldb_class::%s(void *$__lldb_arg) \n"
316 m_name.c_str(), lldb_local_var_decls.GetData(),
317 tagged_body.c_str());
319 case lldb::eLanguageTypeObjC:
322 "@interface $__lldb_objc_class ($__lldb_category) \n"
323 "+(void)%s:(void *)$__lldb_arg; \n"
325 "@implementation $__lldb_objc_class ($__lldb_category) \n"
326 "+(void)%s:(void *)$__lldb_arg \n"
331 m_name.c_str(), m_name.c_str(), tagged_body.c_str());
334 "@interface $__lldb_objc_class ($__lldb_category) \n"
335 "-(void)%s:(void *)$__lldb_arg; \n"
337 "@implementation $__lldb_objc_class ($__lldb_category) \n"
338 "-(void)%s:(void *)$__lldb_arg \n"
343 m_name.c_str(), m_name.c_str(), tagged_body.c_str());
348 text = wrap_stream.GetString();
356 bool ExpressionSourceCode::GetOriginalBodyBounds(
357 std::string transformed_text, lldb::LanguageType wrapping_language,
358 size_t &start_loc, size_t &end_loc) {
359 const char *start_marker;
360 const char *end_marker;
362 switch (wrapping_language) {
365 case lldb::eLanguageTypeC:
366 case lldb::eLanguageTypeC_plus_plus:
367 case lldb::eLanguageTypeObjC:
368 start_marker = c_start_marker;
369 end_marker = c_end_marker;
373 start_loc = transformed_text.find(start_marker);
374 if (start_loc == std::string::npos)
376 start_loc += strlen(start_marker);
377 end_loc = transformed_text.find(end_marker);
378 return end_loc != std::string::npos;