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