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