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/Target/ExecutionContext.h" 20 #include "lldb/Target/Platform.h" 21 #include "lldb/Target/StackFrame.h" 22 #include "lldb/Target/Target.h" 23 24 using namespace lldb_private; 25 26 const char * 27 ExpressionSourceCode::g_expression_prefix = R"( 28 #ifndef NULL 29 #define NULL (__null) 30 #endif 31 #ifndef Nil 32 #define Nil (__null) 33 #endif 34 #ifndef nil 35 #define nil (__null) 36 #endif 37 #ifndef YES 38 #define YES ((BOOL)1) 39 #endif 40 #ifndef NO 41 #define NO ((BOOL)0) 42 #endif 43 typedef __INT8_TYPE__ int8_t; 44 typedef __UINT8_TYPE__ uint8_t; 45 typedef __INT16_TYPE__ int16_t; 46 typedef __UINT16_TYPE__ uint16_t; 47 typedef __INT32_TYPE__ int32_t; 48 typedef __UINT32_TYPE__ uint32_t; 49 typedef __INT64_TYPE__ int64_t; 50 typedef __UINT64_TYPE__ uint64_t; 51 typedef __INTPTR_TYPE__ intptr_t; 52 typedef __UINTPTR_TYPE__ uintptr_t; 53 typedef __SIZE_TYPE__ size_t; 54 typedef __PTRDIFF_TYPE__ ptrdiff_t; 55 typedef unsigned short unichar; 56 extern "C" 57 { 58 int printf(const char * __restrict, ...); 59 } 60 )"; 61 62 namespace { 63 64 class AddMacroState 65 { 66 enum State 67 { 68 CURRENT_FILE_NOT_YET_PUSHED, 69 CURRENT_FILE_PUSHED, 70 CURRENT_FILE_POPPED 71 }; 72 73 public: 74 AddMacroState(const FileSpec ¤t_file, const uint32_t current_file_line) 75 : m_state(CURRENT_FILE_NOT_YET_PUSHED), 76 m_current_file(current_file), 77 m_current_file_line(current_file_line) 78 { } 79 80 void 81 StartFile(const FileSpec &file) 82 { 83 m_file_stack.push_back(file); 84 if (file == m_current_file) 85 m_state = CURRENT_FILE_PUSHED; 86 } 87 88 void 89 EndFile() 90 { 91 if (m_file_stack.size() == 0) 92 return; 93 94 FileSpec old_top = m_file_stack.back(); 95 m_file_stack.pop_back(); 96 if (old_top == m_current_file) 97 m_state = CURRENT_FILE_POPPED; 98 } 99 100 // An entry is valid if it occurs before the current line in 101 // the current file. 102 bool 103 IsValidEntry(uint32_t line) 104 { 105 switch (m_state) 106 { 107 case CURRENT_FILE_NOT_YET_PUSHED: 108 return true; 109 case CURRENT_FILE_POPPED: 110 return false; 111 case CURRENT_FILE_PUSHED: 112 // If we are in file included in the current file, 113 // the entry should be added. 114 if (m_file_stack.back() != m_current_file) 115 return true; 116 117 if (line >= m_current_file_line) 118 return false; 119 else 120 return true; 121 } 122 } 123 124 private: 125 std::vector<FileSpec> m_file_stack; 126 State m_state; 127 FileSpec m_current_file; 128 uint32_t m_current_file_line; 129 }; 130 131 } // anonymous namespace 132 133 static void 134 AddMacros(const DebugMacros *dm, CompileUnit *comp_unit, AddMacroState &state, StreamString &stream) 135 { 136 if (dm == nullptr) 137 return; 138 139 for (size_t i = 0; i < dm->GetNumMacroEntries(); i++) 140 { 141 const DebugMacroEntry &entry = dm->GetMacroEntryAtIndex(i); 142 uint32_t line; 143 144 switch (entry.GetType()) 145 { 146 case DebugMacroEntry::DEFINE: 147 if (state.IsValidEntry(entry.GetLineNumber())) 148 stream.Printf("#define %s\n", entry.GetMacroString().AsCString()); 149 else 150 return; 151 break; 152 case DebugMacroEntry::UNDEF: 153 if (state.IsValidEntry(entry.GetLineNumber())) 154 stream.Printf("#undef %s\n", entry.GetMacroString().AsCString()); 155 else 156 return; 157 break; 158 case DebugMacroEntry::START_FILE: 159 line = entry.GetLineNumber(); 160 if (state.IsValidEntry(line)) 161 state.StartFile(entry.GetFileSpec(comp_unit)); 162 else 163 return; 164 break; 165 case DebugMacroEntry::END_FILE: 166 state.EndFile(); 167 break; 168 case DebugMacroEntry::INDIRECT: 169 AddMacros(entry.GetIndirectDebugMacros(), comp_unit, state, stream); 170 break; 171 default: 172 // This is an unknown/invalid entry. Ignore. 173 break; 174 } 175 } 176 } 177 178 bool ExpressionSourceCode::GetText (std::string &text, lldb::LanguageType wrapping_language, bool const_object, bool static_method, ExecutionContext &exe_ctx) const 179 { 180 const char *target_specific_defines = "typedef signed char BOOL;\n"; 181 std::string module_macros; 182 183 if (Target *target = exe_ctx.GetTargetPtr()) 184 { 185 if (target->GetArchitecture().GetMachine() == llvm::Triple::aarch64) 186 { 187 target_specific_defines = "typedef bool BOOL;\n"; 188 } 189 if (target->GetArchitecture().GetMachine() == llvm::Triple::x86_64) 190 { 191 if (lldb::PlatformSP platform_sp = target->GetPlatform()) 192 { 193 static ConstString g_platform_ios_simulator ("ios-simulator"); 194 if (platform_sp->GetPluginName() == g_platform_ios_simulator) 195 { 196 target_specific_defines = "typedef bool BOOL;\n"; 197 } 198 } 199 } 200 201 if (ClangModulesDeclVendor *decl_vendor = target->GetClangModulesDeclVendor()) 202 { 203 ClangPersistentVariables *persistent_vars = llvm::cast<ClangPersistentVariables>(target->GetPersistentExpressionStateForLanguage(lldb::eLanguageTypeC)); 204 const ClangModulesDeclVendor::ModuleVector &hand_imported_modules = persistent_vars->GetHandLoadedClangModules(); 205 ClangModulesDeclVendor::ModuleVector modules_for_macros; 206 207 for (ClangModulesDeclVendor::ModuleID module : hand_imported_modules) 208 { 209 modules_for_macros.push_back(module); 210 } 211 212 if (target->GetEnableAutoImportClangModules()) 213 { 214 if (StackFrame *frame = exe_ctx.GetFramePtr()) 215 { 216 if (Block *block = frame->GetFrameBlock()) 217 { 218 SymbolContext sc; 219 220 block->CalculateSymbolContext(&sc); 221 222 if (sc.comp_unit) 223 { 224 StreamString error_stream; 225 226 decl_vendor->AddModulesForCompileUnit(*sc.comp_unit, modules_for_macros, error_stream); 227 } 228 } 229 } 230 } 231 232 decl_vendor->ForEachMacro(modules_for_macros, [&module_macros] (const std::string &expansion) -> bool { 233 module_macros.append(expansion); 234 module_macros.append("\n"); 235 return false; 236 }); 237 } 238 239 } 240 241 StreamString debug_macros_stream; 242 if (StackFrame *frame = exe_ctx.GetFramePtr()) 243 { 244 const SymbolContext &sc = frame->GetSymbolContext( 245 lldb:: eSymbolContextCompUnit | lldb::eSymbolContextLineEntry); 246 247 if (sc.comp_unit && sc.line_entry.IsValid()) 248 { 249 DebugMacros *dm = sc.comp_unit->GetDebugMacros(); 250 if (dm) 251 { 252 AddMacroState state(sc.line_entry.file, sc.line_entry.line); 253 AddMacros(dm, sc.comp_unit, state, debug_macros_stream); 254 } 255 } 256 } 257 258 if (m_wrap) 259 { 260 switch (wrapping_language) 261 { 262 default: 263 return false; 264 case lldb::eLanguageTypeC: 265 case lldb::eLanguageTypeC_plus_plus: 266 case lldb::eLanguageTypeObjC: 267 break; 268 } 269 270 StreamString wrap_stream; 271 272 wrap_stream.Printf("%s\n%s\n%s\n%s\n%s\n", 273 module_macros.c_str(), 274 debug_macros_stream.GetData(), 275 g_expression_prefix, 276 target_specific_defines, 277 m_prefix.c_str()); 278 279 switch (wrapping_language) 280 { 281 default: 282 break; 283 case lldb::eLanguageTypeC: 284 wrap_stream.Printf("void \n" 285 "%s(void *$__lldb_arg) \n" 286 "{ \n" 287 " %s; \n" 288 "} \n", 289 m_name.c_str(), 290 m_body.c_str()); 291 break; 292 case lldb::eLanguageTypeC_plus_plus: 293 wrap_stream.Printf("void \n" 294 "$__lldb_class::%s(void *$__lldb_arg) %s\n" 295 "{ \n" 296 " %s; \n" 297 "} \n", 298 m_name.c_str(), 299 (const_object ? "const" : ""), 300 m_body.c_str()); 301 break; 302 case lldb::eLanguageTypeObjC: 303 if (static_method) 304 { 305 wrap_stream.Printf("@interface $__lldb_objc_class ($__lldb_category) \n" 306 "+(void)%s:(void *)$__lldb_arg; \n" 307 "@end \n" 308 "@implementation $__lldb_objc_class ($__lldb_category) \n" 309 "+(void)%s:(void *)$__lldb_arg \n" 310 "{ \n" 311 " %s; \n" 312 "} \n" 313 "@end \n", 314 m_name.c_str(), 315 m_name.c_str(), 316 m_body.c_str()); 317 } 318 else 319 { 320 wrap_stream.Printf("@interface $__lldb_objc_class ($__lldb_category) \n" 321 "-(void)%s:(void *)$__lldb_arg; \n" 322 "@end \n" 323 "@implementation $__lldb_objc_class ($__lldb_category) \n" 324 "-(void)%s:(void *)$__lldb_arg \n" 325 "{ \n" 326 " %s; \n" 327 "} \n" 328 "@end \n", 329 m_name.c_str(), 330 m_name.c_str(), 331 m_body.c_str()); 332 } 333 break; 334 } 335 336 text = wrap_stream.GetString(); 337 } 338 else 339 { 340 text.append(m_body); 341 } 342 343 return true; 344 } 345