1 //===-- TestLineEntry.cpp ------------------------------*- C++ -*-===// 2 // 3 // 4 // The LLVM Compiler Infrastructure 5 // 6 // This file is distributed under the University of Illinois Open Source 7 // License. See LICENSE.TXT for details. 8 // 9 //===----------------------------------------------------------------------===// 10 11 #include "gtest/gtest.h" 12 #include <iostream> 13 14 #include "Plugins/ObjectFile/Mach-O/ObjectFileMachO.h" 15 #include "Plugins/SymbolFile/DWARF/DWARFASTParserClang.h" 16 #include "Plugins/SymbolFile/DWARF/SymbolFileDWARF.h" 17 #include "TestingSupport/TestUtilities.h" 18 #include "lldb/Symbol/ClangASTContext.h" 19 20 #include "lldb/Core/Module.h" 21 #include "lldb/Host/FileSystem.h" 22 #include "lldb/Host/HostInfo.h" 23 #include "lldb/Symbol/CompileUnit.h" 24 #include "lldb/Symbol/SymbolContext.h" 25 #include "lldb/Utility/StreamString.h" 26 27 #include "llvm/Support/FileUtilities.h" 28 #include "llvm/Support/Program.h" 29 #include "llvm/Testing/Support/Error.h" 30 31 using namespace lldb_private; 32 using namespace lldb; 33 34 class LineEntryTest : public testing::Test { 35 public: 36 void SetUp() override { 37 FileSystem::Initialize(); 38 HostInfo::Initialize(); 39 ObjectFileMachO::Initialize(); 40 SymbolFileDWARF::Initialize(); 41 ClangASTContext::Initialize(); 42 } 43 44 void TearDown() override { 45 ClangASTContext::Terminate(); 46 SymbolFileDWARF::Terminate(); 47 ObjectFileMachO::Terminate(); 48 HostInfo::Terminate(); 49 FileSystem::Terminate(); 50 } 51 52 protected: 53 llvm::Expected<ModuleSP> GetModule(); 54 llvm::Expected<LineEntry> GetLineEntryForLine(uint32_t line); 55 ModuleSP m_module_sp; 56 }; 57 58 llvm::Expected<ModuleSP> LineEntryTest::GetModule() { 59 if (m_module_sp) 60 return m_module_sp; 61 62 llvm::SmallString<128> obj; 63 if (auto ec = llvm::sys::fs::createTemporaryFile("source-%%%%%%", "obj", obj)) 64 return llvm::errorCodeToError(ec); 65 llvm::FileRemover obj_remover(obj); 66 if (auto error = ReadYAMLObjectFile("inlined-functions.yaml", obj)) 67 return llvm::Error(std::move(error)); 68 69 m_module_sp = std::make_shared<Module>(ModuleSpec(FileSpec(obj))); 70 // Preload because the temporary file will be gone once we exit this function. 71 m_module_sp->PreloadSymbols(); 72 return m_module_sp; 73 } 74 75 llvm::Expected<LineEntry> LineEntryTest::GetLineEntryForLine(uint32_t line) { 76 auto expected_module_so = GetModule(); 77 78 if (!expected_module_so) 79 return llvm::createStringError(llvm::inconvertibleErrorCode(), 80 "Not able to get module for test object."); 81 82 auto module = expected_module_so->get(); 83 bool check_inlines = true; 84 bool exact = true; 85 SymbolContextList sc_comp_units; 86 SymbolContextList sc_line_entries; 87 FileSpec file_spec("inlined-functions.cpp"); 88 module->ResolveSymbolContextsForFileSpec(file_spec, line, check_inlines, 89 lldb::eSymbolContextCompUnit, 90 sc_comp_units); 91 if (sc_comp_units.GetSize() == 0) 92 return llvm::createStringError(llvm::inconvertibleErrorCode(), 93 "No comp unit found on the test object."); 94 sc_comp_units[0].comp_unit->ResolveSymbolContext( 95 file_spec, line, check_inlines, exact, eSymbolContextLineEntry, 96 sc_line_entries); 97 if (sc_line_entries.GetSize() == 0) 98 return llvm::createStringError(llvm::inconvertibleErrorCode(), 99 "No line entry found on the test object."); 100 return sc_line_entries[0].line_entry; 101 } 102 103 TEST_F(LineEntryTest, GetSameLineContiguousAddressRangeNoInlines) { 104 auto line_entry = GetLineEntryForLine(18); 105 ASSERT_THAT_EXPECTED(line_entry, llvm::Succeeded()); 106 bool include_inlined_functions = false; 107 auto range = 108 line_entry->GetSameLineContiguousAddressRange(include_inlined_functions); 109 ASSERT_EQ(range.GetByteSize(), (uint64_t)0x24); 110 } 111 112 TEST_F(LineEntryTest, GetSameLineContiguousAddressRangeOneInline) { 113 auto line_entry = GetLineEntryForLine(18); 114 ASSERT_THAT_EXPECTED(line_entry, llvm::Succeeded()); 115 bool include_inlined_functions = true; 116 auto range = 117 line_entry->GetSameLineContiguousAddressRange(include_inlined_functions); 118 ASSERT_EQ(range.GetByteSize(), (uint64_t)0x49); 119 } 120 121 TEST_F(LineEntryTest, GetSameLineContiguousAddressRangeNestedInline) { 122 auto line_entry = GetLineEntryForLine(12); 123 ASSERT_THAT_EXPECTED(line_entry, llvm::Succeeded()); 124 bool include_inlined_functions = true; 125 auto range = 126 line_entry->GetSameLineContiguousAddressRange(include_inlined_functions); 127 ASSERT_EQ(range.GetByteSize(), (uint64_t)0x33); 128 } 129 130 /* 131 # inlined-functions.cpp 132 inline __attribute__((always_inline)) int sum2(int a, int b) { 133 int result = a + b; 134 return result; 135 } 136 137 int sum3(int a, int b, int c) { 138 int result = a + b + c; 139 return result; 140 } 141 142 inline __attribute__((always_inline)) int sum4(int a, int b, int c, int d) { 143 int result = sum2(a, b) + sum2(c, d); 144 result += 0; 145 return result; 146 } 147 148 int main(int argc, char** argv) { 149 sum3(3, 4, 5) + sum2(1, 2); 150 int sum = sum4(1, 2, 3, 4); 151 sum2(5, 6); 152 return 0; 153 } 154 155 // g++ -c inlined-functions.cpp -o inlined-functions.o -g -Wno-unused-value 156 // obj2yaml inlined-functions.o > inlined-functions.yaml 157 158 # Dump of source line per address: 159 # inlined-functions.cpp is src.cpp for space considerations. 160 0x20: src.cpp:17 161 0x21: src.cpp:17 162 0x26: src.cpp:17 163 0x27: src.cpp:17 164 0x29: src.cpp:17 165 0x2e: src.cpp:17 166 0x2f: src.cpp:17 167 0x31: src.cpp:17 168 0x36: src.cpp:18 169 0x37: src.cpp:18 170 0x39: src.cpp:18 171 0x3e: src.cpp:18 172 0x3f: src.cpp:18 173 0x41: src.cpp:18 174 0x46: src.cpp:18 175 0x47: src.cpp:18 176 0x49: src.cpp:18 177 0x4e: src.cpp:18 178 0x4f: src.cpp:18 179 0x51: src.cpp:18 180 0x56: src.cpp:18 181 0x57: src.cpp:18 182 0x59: src.cpp:18 183 0x5e: src.cpp:18 -> [email protected]:2 184 0x5f: src.cpp:18 -> [email protected]:2 185 0x61: src.cpp:18 -> [email protected]:2 186 0x66: src.cpp:18 -> [email protected]:2 187 0x67: src.cpp:18 -> [email protected]:2 188 0x69: src.cpp:18 -> [email protected]:2 189 0x6e: src.cpp:18 -> [email protected]:2 190 0x6f: src.cpp:18 -> [email protected]:2 191 0x71: src.cpp:18 -> [email protected]:2 192 0x76: src.cpp:18 -> [email protected]:2 193 0x77: src.cpp:18 -> [email protected]:2 194 0x79: src.cpp:18 -> [email protected]:2 195 0x7e: src.cpp:18 -> [email protected]:2 196 0x7f: src.cpp:19 -> [email protected]:12 197 0x81: src.cpp:19 -> [email protected]:12 198 0x86: src.cpp:19 -> [email protected]:12 199 0x87: src.cpp:19 -> [email protected]:12 200 0x89: src.cpp:19 -> [email protected]:12 201 0x8e: src.cpp:19 -> [email protected]:12 -> [email protected]:2 202 0x8f: src.cpp:19 -> [email protected]:12 -> [email protected]:2 203 0x91: src.cpp:19 -> [email protected]:12 -> [email protected]:2 204 0x96: src.cpp:19 -> [email protected]:12 -> [email protected]:3 205 0x97: src.cpp:19 -> [email protected]:12 206 0x99: src.cpp:19 -> [email protected]:12 207 0x9e: src.cpp:19 -> [email protected]:12 208 0x9f: src.cpp:19 -> [email protected]:12 209 0xa1: src.cpp:19 -> [email protected]:12 210 0xa6: src.cpp:19 -> [email protected]:12 -> [email protected]:2 211 0xa7: src.cpp:19 -> [email protected]:12 -> [email protected]:2 212 0xa9: src.cpp:19 -> [email protected]:12 -> [email protected]:2 213 0xae: src.cpp:19 -> [email protected]:12 214 0xaf: src.cpp:19 -> [email protected]:12 215 0xb1: src.cpp:19 -> [email protected]:12 216 0xb6: src.cpp:19 -> [email protected]:13 217 0xb7: src.cpp:19 -> [email protected]:13 218 0xb9: src.cpp:19 -> [email protected]:14 219 0xbe: src.cpp:19 220 0xbf: src.cpp:19 221 0xc1: src.cpp:19 222 0xc6: src.cpp:19 223 0xc7: src.cpp:19 224 0xc9: src.cpp:19 225 0xce: src.cpp:20 -> [email protected]:2 226 0xcf: src.cpp:20 -> [email protected]:2 227 0xd1: src.cpp:20 -> [email protected]:2 228 0xd6: src.cpp:21 229 0xd7: src.cpp:21 230 0xd9: src.cpp:21 231 0xde: src.cpp:21 232 */ 233