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