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<LineEntry> GetLineEntryForLine(uint32_t line);
42   llvm::Optional<TestFile> m_file;
43   ModuleSP m_module_sp;
44 };
45 
46 void LineEntryTest::SetUp() {
47   auto ExpectedFile = TestFile::fromYamlFile("inlined-functions.yaml");
48   ASSERT_THAT_EXPECTED(ExpectedFile, llvm::Succeeded());
49   m_file.emplace(std::move(*ExpectedFile));
50   m_module_sp = std::make_shared<Module>(m_file->moduleSpec());
51 }
52 
53 llvm::Expected<LineEntry> LineEntryTest::GetLineEntryForLine(uint32_t line) {
54   // TODO: Handle SourceLocationSpec column information
55   SymbolContextList sc_comp_units;
56   SymbolContextList sc_line_entries;
57   FileSpec file_spec("inlined-functions.cpp");
58   m_module_sp->ResolveSymbolContextsForFileSpec(
59       file_spec, line, /*check_inlines=*/true, lldb::eSymbolContextCompUnit,
60       sc_comp_units);
61   if (sc_comp_units.GetSize() == 0)
62     return llvm::createStringError(llvm::inconvertibleErrorCode(),
63                                    "No comp unit found on the test object.");
64 
65   SourceLocationSpec location_spec(file_spec, line, /*column=*/llvm::None,
66                                    /*check_inlines=*/true,
67                                    /*exact_match=*/true);
68 
69   sc_comp_units[0].comp_unit->ResolveSymbolContext(
70       location_spec, eSymbolContextLineEntry, sc_line_entries);
71   if (sc_line_entries.GetSize() == 0)
72     return llvm::createStringError(llvm::inconvertibleErrorCode(),
73                                    "No line entry found on the test object.");
74   return sc_line_entries[0].line_entry;
75 }
76 
77 TEST_F(LineEntryTest, GetSameLineContiguousAddressRangeNoInlines) {
78   auto line_entry = GetLineEntryForLine(18);
79   ASSERT_THAT_EXPECTED(line_entry, llvm::Succeeded());
80   bool include_inlined_functions = false;
81   auto range =
82       line_entry->GetSameLineContiguousAddressRange(include_inlined_functions);
83   ASSERT_EQ(range.GetByteSize(), (uint64_t)0x24);
84 }
85 
86 TEST_F(LineEntryTest, GetSameLineContiguousAddressRangeOneInline) {
87   auto line_entry = GetLineEntryForLine(18);
88   ASSERT_THAT_EXPECTED(line_entry, llvm::Succeeded());
89   bool include_inlined_functions = true;
90   auto range =
91       line_entry->GetSameLineContiguousAddressRange(include_inlined_functions);
92   ASSERT_EQ(range.GetByteSize(), (uint64_t)0x49);
93 }
94 
95 TEST_F(LineEntryTest, GetSameLineContiguousAddressRangeNestedInline) {
96   auto line_entry = GetLineEntryForLine(12);
97   ASSERT_THAT_EXPECTED(line_entry, llvm::Succeeded());
98   bool include_inlined_functions = true;
99   auto range =
100       line_entry->GetSameLineContiguousAddressRange(include_inlined_functions);
101   ASSERT_EQ(range.GetByteSize(), (uint64_t)0x33);
102 }
103 
104 /*
105 # inlined-functions.cpp
106 inline __attribute__((always_inline)) int sum2(int a, int b) {
107     int result = a + b;
108     return result;
109 }
110 
111 int sum3(int a, int b, int c) {
112     int result = a + b + c;
113     return result;
114 }
115 
116 inline __attribute__((always_inline)) int sum4(int a, int b, int c, int d) {
117     int result = sum2(a, b) + sum2(c, d);
118     result += 0;
119     return result;
120 }
121 
122 int main(int argc, char** argv) {
123     sum3(3, 4, 5) + sum2(1, 2);
124     int sum = sum4(1, 2, 3, 4);
125     sum2(5, 6);
126     return 0;
127 }
128 
129 // g++ -c inlined-functions.cpp -o inlined-functions.o -g -Wno-unused-value
130 // obj2yaml inlined-functions.o > inlined-functions.yaml
131 
132 # Dump of source line per address:
133 # inlined-functions.cpp is src.cpp for space considerations.
134 0x20: src.cpp:17
135 0x21: src.cpp:17
136 0x26: src.cpp:17
137 0x27: src.cpp:17
138 0x29: src.cpp:17
139 0x2e: src.cpp:17
140 0x2f: src.cpp:17
141 0x31: src.cpp:17
142 0x36: src.cpp:18
143 0x37: src.cpp:18
144 0x39: src.cpp:18
145 0x3e: src.cpp:18
146 0x3f: src.cpp:18
147 0x41: src.cpp:18
148 0x46: src.cpp:18
149 0x47: src.cpp:18
150 0x49: src.cpp:18
151 0x4e: src.cpp:18
152 0x4f: src.cpp:18
153 0x51: src.cpp:18
154 0x56: src.cpp:18
155 0x57: src.cpp:18
156 0x59: src.cpp:18
157 0x5e: src.cpp:18 -> [email protected]:2
158 0x5f: src.cpp:18 -> [email protected]:2
159 0x61: src.cpp:18 -> [email protected]:2
160 0x66: src.cpp:18 -> [email protected]:2
161 0x67: src.cpp:18 -> [email protected]:2
162 0x69: src.cpp:18 -> [email protected]:2
163 0x6e: src.cpp:18 -> [email protected]:2
164 0x6f: src.cpp:18 -> [email protected]:2
165 0x71: src.cpp:18 -> [email protected]:2
166 0x76: src.cpp:18 -> [email protected]:2
167 0x77: src.cpp:18 -> [email protected]:2
168 0x79: src.cpp:18 -> [email protected]:2
169 0x7e: src.cpp:18 -> [email protected]:2
170 0x7f: src.cpp:19 -> [email protected]:12
171 0x81: src.cpp:19 -> [email protected]:12
172 0x86: src.cpp:19 -> [email protected]:12
173 0x87: src.cpp:19 -> [email protected]:12
174 0x89: src.cpp:19 -> [email protected]:12
175 0x8e: src.cpp:19 -> [email protected]:12 -> [email protected]:2
176 0x8f: src.cpp:19 -> [email protected]:12 -> [email protected]:2
177 0x91: src.cpp:19 -> [email protected]:12 -> [email protected]:2
178 0x96: src.cpp:19 -> [email protected]:12 -> [email protected]:3
179 0x97: src.cpp:19 -> [email protected]:12
180 0x99: src.cpp:19 -> [email protected]:12
181 0x9e: src.cpp:19 -> [email protected]:12
182 0x9f: src.cpp:19 -> [email protected]:12
183 0xa1: src.cpp:19 -> [email protected]:12
184 0xa6: src.cpp:19 -> [email protected]:12 -> [email protected]:2
185 0xa7: src.cpp:19 -> [email protected]:12 -> [email protected]:2
186 0xa9: src.cpp:19 -> [email protected]:12 -> [email protected]:2
187 0xae: src.cpp:19 -> [email protected]:12
188 0xaf: src.cpp:19 -> [email protected]:12
189 0xb1: src.cpp:19 -> [email protected]:12
190 0xb6: src.cpp:19 -> [email protected]:13
191 0xb7: src.cpp:19 -> [email protected]:13
192 0xb9: src.cpp:19 -> [email protected]:14
193 0xbe: src.cpp:19
194 0xbf: src.cpp:19
195 0xc1: src.cpp:19
196 0xc6: src.cpp:19
197 0xc7: src.cpp:19
198 0xc9: src.cpp:19
199 0xce: src.cpp:20 -> [email protected]:2
200 0xcf: src.cpp:20 -> [email protected]:2
201 0xd1: src.cpp:20 -> [email protected]:2
202 0xd6: src.cpp:21
203 0xd7: src.cpp:21
204 0xd9: src.cpp:21
205 0xde: src.cpp:21
206 */
207