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