1 //===-- ExpressionSourceCode.cpp --------------------------------*- C++ -*-===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 10 #include "lldb/Expression/ExpressionSourceCode.h" 11 12 #include "lldb/Core/StreamString.h" 13 #include "Plugins/ExpressionParser/Clang/ClangModulesDeclVendor.h" 14 #include "Plugins/ExpressionParser/Clang/ClangPersistentVariables.h" 15 #include "lldb/Symbol/CompileUnit.h" 16 #include "lldb/Symbol/DebugMacros.h" 17 #include "lldb/Symbol/Block.h" 18 #include "lldb/Symbol/TypeSystem.h" 19 #include "lldb/Symbol/VariableList.h" 20 #include "lldb/Target/ExecutionContext.h" 21 #include "lldb/Target/Language.h" 22 #include "lldb/Target/Platform.h" 23 #include "lldb/Target/StackFrame.h" 24 #include "lldb/Target/Target.h" 25 26 using namespace lldb_private; 27 28 const char * 29 ExpressionSourceCode::g_expression_prefix = R"( 30 #ifndef NULL 31 #define NULL (__null) 32 #endif 33 #ifndef Nil 34 #define Nil (__null) 35 #endif 36 #ifndef nil 37 #define nil (__null) 38 #endif 39 #ifndef YES 40 #define YES ((BOOL)1) 41 #endif 42 #ifndef NO 43 #define NO ((BOOL)0) 44 #endif 45 typedef __INT8_TYPE__ int8_t; 46 typedef __UINT8_TYPE__ uint8_t; 47 typedef __INT16_TYPE__ int16_t; 48 typedef __UINT16_TYPE__ uint16_t; 49 typedef __INT32_TYPE__ int32_t; 50 typedef __UINT32_TYPE__ uint32_t; 51 typedef __INT64_TYPE__ int64_t; 52 typedef __UINT64_TYPE__ uint64_t; 53 typedef __INTPTR_TYPE__ intptr_t; 54 typedef __UINTPTR_TYPE__ uintptr_t; 55 typedef __SIZE_TYPE__ size_t; 56 typedef __PTRDIFF_TYPE__ ptrdiff_t; 57 typedef unsigned short unichar; 58 extern "C" 59 { 60 int printf(const char * __restrict, ...); 61 } 62 )"; 63 64 static const char *c_start_marker = " /*LLDB_BODY_START*/\n "; 65 static const char *c_end_marker = ";\n /*LLDB_BODY_END*/\n"; 66 67 namespace { 68 69 class AddMacroState 70 { 71 enum State 72 { 73 CURRENT_FILE_NOT_YET_PUSHED, 74 CURRENT_FILE_PUSHED, 75 CURRENT_FILE_POPPED 76 }; 77 78 public: 79 AddMacroState(const FileSpec ¤t_file, const uint32_t current_file_line) 80 : m_state(CURRENT_FILE_NOT_YET_PUSHED), 81 m_current_file(current_file), 82 m_current_file_line(current_file_line) 83 { } 84 85 void 86 StartFile(const FileSpec &file) 87 { 88 m_file_stack.push_back(file); 89 if (file == m_current_file) 90 m_state = CURRENT_FILE_PUSHED; 91 } 92 93 void 94 EndFile() 95 { 96 if (m_file_stack.size() == 0) 97 return; 98 99 FileSpec old_top = m_file_stack.back(); 100 m_file_stack.pop_back(); 101 if (old_top == m_current_file) 102 m_state = CURRENT_FILE_POPPED; 103 } 104 105 // An entry is valid if it occurs before the current line in 106 // the current file. 107 bool 108 IsValidEntry(uint32_t line) 109 { 110 switch (m_state) 111 { 112 case CURRENT_FILE_NOT_YET_PUSHED: 113 return true; 114 case CURRENT_FILE_PUSHED: 115 // If we are in file included in the current file, 116 // the entry should be added. 117 if (m_file_stack.back() != m_current_file) 118 return true; 119 120 if (line >= m_current_file_line) 121 return false; 122 else 123 return true; 124 default: 125 return false; 126 } 127 } 128 129 private: 130 std::vector<FileSpec> m_file_stack; 131 State m_state; 132 FileSpec m_current_file; 133 uint32_t m_current_file_line; 134 }; 135 136 } // anonymous namespace 137 138 static void 139 AddMacros(const DebugMacros *dm, CompileUnit *comp_unit, AddMacroState &state, StreamString &stream) 140 { 141 if (dm == nullptr) 142 return; 143 144 for (size_t i = 0; i < dm->GetNumMacroEntries(); i++) 145 { 146 const DebugMacroEntry &entry = dm->GetMacroEntryAtIndex(i); 147 uint32_t line; 148 149 switch (entry.GetType()) 150 { 151 case DebugMacroEntry::DEFINE: 152 if (state.IsValidEntry(entry.GetLineNumber())) 153 stream.Printf("#define %s\n", entry.GetMacroString().AsCString()); 154 else 155 return; 156 break; 157 case DebugMacroEntry::UNDEF: 158 if (state.IsValidEntry(entry.GetLineNumber())) 159 stream.Printf("#undef %s\n", entry.GetMacroString().AsCString()); 160 else 161 return; 162 break; 163 case DebugMacroEntry::START_FILE: 164 line = entry.GetLineNumber(); 165 if (state.IsValidEntry(line)) 166 state.StartFile(entry.GetFileSpec(comp_unit)); 167 else 168 return; 169 break; 170 case DebugMacroEntry::END_FILE: 171 state.EndFile(); 172 break; 173 case DebugMacroEntry::INDIRECT: 174 AddMacros(entry.GetIndirectDebugMacros(), comp_unit, state, stream); 175 break; 176 default: 177 // This is an unknown/invalid entry. Ignore. 178 break; 179 } 180 } 181 } 182 183 static void 184 AddLocalVariableDecls(const lldb::VariableListSP &var_list_sp, StreamString &stream) 185 { 186 for (size_t i = 0; i < var_list_sp->GetSize(); i++) 187 { 188 lldb::VariableSP var_sp = var_list_sp->GetVariableAtIndex(i); 189 190 ConstString var_name = var_sp->GetName(); 191 if (!var_name || var_name == ConstString("this") || var_name == ConstString(".block_descriptor")) 192 continue; 193 194 stream.Printf("using $__lldb_local_vars::%s;\n", var_name.AsCString()); 195 } 196 } 197 198 bool ExpressionSourceCode::GetText (std::string &text, lldb::LanguageType wrapping_language, bool static_method, ExecutionContext &exe_ctx) const 199 { 200 const char *target_specific_defines = "typedef signed char BOOL;\n"; 201 std::string module_macros; 202 203 Target *target = exe_ctx.GetTargetPtr(); 204 if (target) 205 { 206 if (target->GetArchitecture().GetMachine() == llvm::Triple::aarch64) 207 { 208 target_specific_defines = "typedef bool BOOL;\n"; 209 } 210 if (target->GetArchitecture().GetMachine() == llvm::Triple::x86_64) 211 { 212 if (lldb::PlatformSP platform_sp = target->GetPlatform()) 213 { 214 static ConstString g_platform_ios_simulator ("ios-simulator"); 215 if (platform_sp->GetPluginName() == g_platform_ios_simulator) 216 { 217 target_specific_defines = "typedef bool BOOL;\n"; 218 } 219 } 220 } 221 222 if (ClangModulesDeclVendor *decl_vendor = target->GetClangModulesDeclVendor()) 223 { 224 ClangPersistentVariables *persistent_vars = llvm::cast<ClangPersistentVariables>(target->GetPersistentExpressionStateForLanguage(lldb::eLanguageTypeC)); 225 const ClangModulesDeclVendor::ModuleVector &hand_imported_modules = persistent_vars->GetHandLoadedClangModules(); 226 ClangModulesDeclVendor::ModuleVector modules_for_macros; 227 228 for (ClangModulesDeclVendor::ModuleID module : hand_imported_modules) 229 { 230 modules_for_macros.push_back(module); 231 } 232 233 if (target->GetEnableAutoImportClangModules()) 234 { 235 if (StackFrame *frame = exe_ctx.GetFramePtr()) 236 { 237 if (Block *block = frame->GetFrameBlock()) 238 { 239 SymbolContext sc; 240 241 block->CalculateSymbolContext(&sc); 242 243 if (sc.comp_unit) 244 { 245 StreamString error_stream; 246 247 decl_vendor->AddModulesForCompileUnit(*sc.comp_unit, modules_for_macros, error_stream); 248 } 249 } 250 } 251 } 252 253 decl_vendor->ForEachMacro(modules_for_macros, [&module_macros] (const std::string &expansion) -> bool { 254 module_macros.append(expansion); 255 module_macros.append("\n"); 256 return false; 257 }); 258 } 259 260 } 261 262 StreamString debug_macros_stream; 263 StreamString lldb_local_var_decls; 264 if (StackFrame *frame = exe_ctx.GetFramePtr()) 265 { 266 const SymbolContext &sc = frame->GetSymbolContext( 267 lldb:: eSymbolContextCompUnit | lldb::eSymbolContextLineEntry); 268 269 if (sc.comp_unit && sc.line_entry.IsValid()) 270 { 271 DebugMacros *dm = sc.comp_unit->GetDebugMacros(); 272 if (dm) 273 { 274 AddMacroState state(sc.line_entry.file, sc.line_entry.line); 275 AddMacros(dm, sc.comp_unit, state, debug_macros_stream); 276 } 277 } 278 279 ConstString object_name; 280 if (Language::LanguageIsCPlusPlus(frame->GetLanguage())) 281 { 282 if (target->GetInjectLocalVariables(&exe_ctx)) 283 { 284 lldb::VariableListSP var_list_sp = frame->GetInScopeVariableList(false, true); 285 AddLocalVariableDecls(var_list_sp, lldb_local_var_decls); 286 } 287 } 288 } 289 290 if (m_wrap) 291 { 292 switch (wrapping_language) 293 { 294 default: 295 return false; 296 case lldb::eLanguageTypeC: 297 case lldb::eLanguageTypeC_plus_plus: 298 case lldb::eLanguageTypeObjC: 299 break; 300 } 301 302 StreamString wrap_stream; 303 304 wrap_stream.Printf("%s\n%s\n%s\n%s\n%s\n", 305 module_macros.c_str(), 306 debug_macros_stream.GetData(), 307 g_expression_prefix, 308 target_specific_defines, 309 m_prefix.c_str()); 310 311 // First construct a tagged form of the user expression so we can find it later: 312 std::string tagged_body; 313 switch (wrapping_language) 314 { 315 default: 316 tagged_body = m_body; 317 break; 318 case lldb::eLanguageTypeC: 319 case lldb::eLanguageTypeC_plus_plus: 320 case lldb::eLanguageTypeObjC: 321 tagged_body.append(c_start_marker); 322 tagged_body.append(m_body); 323 tagged_body.append(c_end_marker); 324 break; 325 326 } 327 switch (wrapping_language) 328 { 329 default: 330 break; 331 case lldb::eLanguageTypeC: 332 wrap_stream.Printf("void \n" 333 "%s(void *$__lldb_arg) \n" 334 "{ \n" 335 " %s; \n" 336 "%s" 337 "} \n", 338 m_name.c_str(), 339 lldb_local_var_decls.GetData(), 340 tagged_body.c_str()); 341 break; 342 case lldb::eLanguageTypeC_plus_plus: 343 wrap_stream.Printf("void \n" 344 "$__lldb_class::%s(void *$__lldb_arg) \n" 345 "{ \n" 346 " %s; \n" 347 "%s" 348 "} \n", 349 m_name.c_str(), 350 lldb_local_var_decls.GetData(), 351 tagged_body.c_str()); 352 break; 353 case lldb::eLanguageTypeObjC: 354 if (static_method) 355 { 356 wrap_stream.Printf("@interface $__lldb_objc_class ($__lldb_category) \n" 357 "+(void)%s:(void *)$__lldb_arg; \n" 358 "@end \n" 359 "@implementation $__lldb_objc_class ($__lldb_category) \n" 360 "+(void)%s:(void *)$__lldb_arg \n" 361 "{ \n" 362 "%s" 363 "} \n" 364 "@end \n", 365 m_name.c_str(), 366 m_name.c_str(), 367 tagged_body.c_str()); 368 } 369 else 370 { 371 wrap_stream.Printf("@interface $__lldb_objc_class ($__lldb_category) \n" 372 "-(void)%s:(void *)$__lldb_arg; \n" 373 "@end \n" 374 "@implementation $__lldb_objc_class ($__lldb_category) \n" 375 "-(void)%s:(void *)$__lldb_arg \n" 376 "{ \n" 377 "%s" 378 "} \n" 379 "@end \n", 380 m_name.c_str(), 381 m_name.c_str(), 382 tagged_body.c_str()); 383 } 384 break; 385 } 386 387 text = wrap_stream.GetString(); 388 } 389 else 390 { 391 text.append(m_body); 392 } 393 394 return true; 395 } 396 397 bool 398 ExpressionSourceCode::GetOriginalBodyBounds(std::string transformed_text, 399 lldb::LanguageType wrapping_language, 400 size_t &start_loc, 401 size_t &end_loc) 402 { 403 const char *start_marker; 404 const char *end_marker; 405 406 switch (wrapping_language) 407 { 408 default: 409 return false; 410 case lldb::eLanguageTypeC: 411 case lldb::eLanguageTypeC_plus_plus: 412 case lldb::eLanguageTypeObjC: 413 start_marker = c_start_marker; 414 end_marker = c_end_marker; 415 break; 416 } 417 418 start_loc = transformed_text.find(start_marker); 419 if (start_loc == std::string::npos) 420 return false; 421 start_loc += strlen(start_marker); 422 end_loc = transformed_text.find(end_marker); 423 if (end_loc == std::string::npos) 424 return false; 425 return true; 426 } 427 428