1"""
2Test basics of linux core file debugging.
3"""
4
5from __future__ import division, print_function
6
7import shutil
8import struct
9import os
10
11import lldb
12from lldbsuite.test.decorators import *
13from lldbsuite.test.lldbtest import *
14from lldbsuite.test import lldbutil
15
16
17class LinuxCoreTestCase(TestBase):
18    NO_DEBUG_INFO_TESTCASE = True
19
20    mydir = TestBase.compute_mydir(__file__)
21
22    _aarch64_pid = 37688
23    _aarch64_pac_pid = 387
24    _i386_pid = 32306
25    _x86_64_pid = 32259
26    _s390x_pid = 1045
27    _ppc64le_pid = 28147
28
29    _aarch64_regions = 4
30    _i386_regions = 4
31    _x86_64_regions = 5
32    _s390x_regions = 2
33    _ppc64le_regions = 2
34
35    @skipIfLLVMTargetMissing("AArch64")
36    @skipIfReproducer  # lldb::FileSP used in typemap cannot be instrumented.
37    def test_aarch64(self):
38        """Test that lldb can read the process information from an aarch64 linux core file."""
39        self.do_test("linux-aarch64", self._aarch64_pid,
40                     self._aarch64_regions, "a.out")
41
42    @skipIfLLVMTargetMissing("X86")
43    @skipIfReproducer  # lldb::FileSP used in typemap cannot be instrumented.
44    def test_i386(self):
45        """Test that lldb can read the process information from an i386 linux core file."""
46        self.do_test("linux-i386", self._i386_pid, self._i386_regions, "a.out")
47
48    @skipIfLLVMTargetMissing("PowerPC")
49    @skipIfReproducer  # lldb::FileSP used in typemap cannot be instrumented.
50    def test_ppc64le(self):
51        """Test that lldb can read the process information from an ppc64le linux core file."""
52        self.do_test("linux-ppc64le", self._ppc64le_pid, self._ppc64le_regions,
53                     "linux-ppc64le.ou")
54
55    @skipIfLLVMTargetMissing("X86")
56    @skipIfReproducer  # lldb::FileSP used in typemap cannot be instrumented.
57    def test_x86_64(self):
58        """Test that lldb can read the process information from an x86_64 linux core file."""
59        self.do_test("linux-x86_64", self._x86_64_pid, self._x86_64_regions,
60                     "a.out")
61
62    @skipIfLLVMTargetMissing("SystemZ")
63    @skipIfReproducer  # lldb::FileSP used in typemap cannot be instrumented.
64    def test_s390x(self):
65        """Test that lldb can read the process information from an s390x linux core file."""
66        self.do_test("linux-s390x", self._s390x_pid, self._s390x_regions,
67                     "a.out")
68
69    @skipIfLLVMTargetMissing("X86")
70    @skipIfReproducer  # lldb::FileSP used in typemap cannot be instrumented.
71    def test_same_pid_running(self):
72        """Test that we read the information from the core correctly even if we have a running
73        process with the same PID around"""
74        exe_file = self.getBuildArtifact("linux-x86_64-pid.out")
75        core_file = self.getBuildArtifact("linux-x86_64-pid.core")
76        shutil.copyfile("linux-x86_64.out", exe_file)
77        shutil.copyfile("linux-x86_64.core", core_file)
78        with open(core_file, "r+b") as f:
79            # These are offsets into the NT_PRSTATUS and NT_PRPSINFO structures in the note
80            # segment of the core file. If you update the file, these offsets may need updating
81            # as well. (Notes can be viewed with readelf --notes.)
82            for pid_offset in [0x1c4, 0x320]:
83                f.seek(pid_offset)
84                self.assertEqual(
85                    struct.unpack(
86                        "<I",
87                        f.read(4))[0],
88                    self._x86_64_pid)
89
90                # We insert our own pid, and make sure the test still
91                # works.
92                f.seek(pid_offset)
93                f.write(struct.pack("<I", os.getpid()))
94        self.do_test(self.getBuildArtifact("linux-x86_64-pid"), os.getpid(),
95                     self._x86_64_regions, "a.out")
96
97    @skipIfLLVMTargetMissing("X86")
98    @skipIfReproducer  # lldb::FileSP used in typemap cannot be instrumented.
99    def test_two_cores_same_pid(self):
100        """Test that we handle the situation if we have two core files with the same PID
101        around"""
102        alttarget = self.dbg.CreateTarget("altmain.out")
103        altprocess = alttarget.LoadCore("altmain.core")
104        self.assertTrue(altprocess, PROCESS_IS_VALID)
105        self.assertEqual(altprocess.GetNumThreads(), 1)
106        self.assertEqual(altprocess.GetProcessID(), self._x86_64_pid)
107
108        altframe = altprocess.GetSelectedThread().GetFrameAtIndex(0)
109        self.assertEqual(altframe.GetFunctionName(), "_start")
110        self.assertEqual(
111            altframe.GetLineEntry().GetLine(),
112            line_number(
113                "altmain.c",
114                "Frame _start"))
115
116        error = lldb.SBError()
117        F = altprocess.ReadCStringFromMemory(
118            altframe.FindVariable("F").GetValueAsUnsigned(), 256, error)
119        self.assertTrue(error.Success())
120        self.assertEqual(F, "_start")
121
122        # without destroying this process, run the test which opens another core file with the
123        # same pid
124        self.do_test("linux-x86_64", self._x86_64_pid, self._x86_64_regions,
125                     "a.out")
126
127
128    @skipIfLLVMTargetMissing("X86")
129    @skipIfWindows
130    @skipIfReproducer
131    def test_read_memory(self):
132        """Test that we are able to read as many bytes as available"""
133        target = self.dbg.CreateTarget("linux-x86_64.out")
134        process = target.LoadCore("linux-x86_64.core")
135        self.assertTrue(process, PROCESS_IS_VALID)
136
137        error = lldb.SBError()
138        bytesread = process.ReadMemory(0x400ff0, 20, error)
139
140        # read only 16 bytes without zero bytes filling
141        self.assertEqual(len(bytesread), 16)
142        self.dbg.DeleteTarget(target)
143
144    @skipIfLLVMTargetMissing("X86")
145    def test_FPR_SSE(self):
146        # check x86_64 core file
147        target = self.dbg.CreateTarget(None)
148        self.assertTrue(target, VALID_TARGET)
149        process = target.LoadCore("linux-fpr_sse_x86_64.core")
150
151        values = {}
152        values["fctrl"] = "0x037f"
153        values["fstat"] = "0x0000"
154        values["ftag"] = "0x00ff"
155        values["fop"] = "0x0000"
156        values["fiseg"] = "0x00000000"
157        values["fioff"] = "0x0040011e"
158        values["foseg"] = "0x00000000"
159        values["fooff"] = "0x00000000"
160        values["mxcsr"] = "0x00001f80"
161        values["mxcsrmask"] = "0x0000ffff"
162        values["st0"] = "{0x99 0xf7 0xcf 0xfb 0x84 0x9a 0x20 0x9a 0xfd 0x3f}"
163        values["st1"] = "{0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x80 0xff 0x3f}"
164        values["st2"] = "{0xfe 0x8a 0x1b 0xcd 0x4b 0x78 0x9a 0xd4 0x00 0x40}"
165        values["st3"] = "{0xac 0x79 0xcf 0xd1 0xf7 0x17 0x72 0xb1 0xfe 0x3f}"
166        values["st4"] = "{0xbc 0xf0 0x17 0x5c 0x29 0x3b 0xaa 0xb8 0xff 0x3f}"
167        values["st5"] = "{0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x80 0xff 0x3f}"
168        values["st6"] = "{0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00}"
169        values["st7"] = "{0x35 0xc2 0x68 0x21 0xa2 0xda 0x0f 0xc9 0x00 0x40}"
170        values["xmm0"] = "{0x29 0x31 0x64 0x46 0x29 0x31 0x64 0x46 0x29 0x31 0x64 0x46 0x29 0x31 0x64 0x46}"
171        values["xmm1"] = "{0x9c 0xed 0x86 0x64 0x9c 0xed 0x86 0x64 0x9c 0xed 0x86 0x64 0x9c 0xed 0x86 0x64}"
172        values["xmm2"] = "{0x07 0xc2 0x1f 0xd7 0x07 0xc2 0x1f 0xd7 0x07 0xc2 0x1f 0xd7 0x07 0xc2 0x1f 0xd7}"
173        values["xmm3"] = "{0xa2 0x20 0x48 0x25 0xa2 0x20 0x48 0x25 0xa2 0x20 0x48 0x25 0xa2 0x20 0x48 0x25}"
174        values["xmm4"] = "{0xeb 0x5a 0xa8 0xc4 0xeb 0x5a 0xa8 0xc4 0xeb 0x5a 0xa8 0xc4 0xeb 0x5a 0xa8 0xc4}"
175        values["xmm5"] = "{0x49 0x41 0x20 0x0b 0x49 0x41 0x20 0x0b 0x49 0x41 0x20 0x0b 0x49 0x41 0x20 0x0b}"
176        values["xmm6"] = "{0xf8 0xf1 0x8b 0x4f 0xf8 0xf1 0x8b 0x4f 0xf8 0xf1 0x8b 0x4f 0xf8 0xf1 0x8b 0x4f}"
177        values["xmm7"] = "{0x13 0xf1 0x30 0xcd 0x13 0xf1 0x30 0xcd 0x13 0xf1 0x30 0xcd 0x13 0xf1 0x30 0xcd}"
178
179        for regname, value in values.items():
180            self.expect("register read {}".format(regname),
181                        substrs=["{} = {}".format(regname, value)])
182
183        # now check i386 core file
184        target = self.dbg.CreateTarget(None)
185        self.assertTrue(target, VALID_TARGET)
186        process = target.LoadCore("linux-fpr_sse_i386.core")
187
188        values["fioff"] = "0x080480cc"
189
190        for regname, value in values.items():
191            self.expect("register read {}".format(regname),
192                        substrs=["{} = {}".format(regname, value)])
193
194    @skipIfLLVMTargetMissing("X86")
195    @skipIfReproducer  # lldb::FileSP used in typemap cannot be instrumented.
196    def test_i386_sysroot(self):
197        """Test that lldb can find the exe for an i386 linux core file using the sysroot."""
198
199        # Copy linux-i386.out to tmp_sysroot/home/labath/test/a.out (since it was compiled as
200        # /home/labath/test/a.out)
201        tmp_sysroot = os.path.join(
202            self.getBuildDir(), "lldb_i386_mock_sysroot")
203        executable = os.path.join(
204            tmp_sysroot, "home", "labath", "test", "a.out")
205        lldbutil.mkdir_p(os.path.dirname(executable))
206        shutil.copyfile("linux-i386.out", executable)
207
208        # Set sysroot and load core
209        self.runCmd("platform select remote-linux --sysroot '%s'" %
210                    tmp_sysroot)
211        target = self.dbg.CreateTarget(None)
212        self.assertTrue(target, VALID_TARGET)
213        process = target.LoadCore("linux-i386.core")
214
215        # Check that we found a.out from the sysroot
216        self.check_all(process, self._i386_pid, self._i386_regions, "a.out")
217
218        self.dbg.DeleteTarget(target)
219
220    @skipIfLLVMTargetMissing("X86")
221    @skipIfWindows
222    @skipIfReproducer  # lldb::FileSP used in typemap cannot be instrumented.
223    def test_x86_64_sysroot(self):
224        """Test that sysroot has more priority then local filesystem."""
225
226        # Copy wrong executable to the location outside of sysroot
227        exe_outside = os.path.join(self.getBuildDir(), "bin", "a.out")
228        lldbutil.mkdir_p(os.path.dirname(exe_outside))
229        shutil.copyfile("altmain.out", exe_outside)
230
231        # Copy correct executable to the location inside sysroot
232        tmp_sysroot = os.path.join(self.getBuildDir(), "mock_sysroot")
233        exe_inside = os.path.join(
234            tmp_sysroot, os.path.relpath(exe_outside, "/"))
235        lldbutil.mkdir_p(os.path.dirname(exe_inside))
236        shutil.copyfile("linux-x86_64.out", exe_inside)
237
238        # Prepare patched core file
239        core_file = os.path.join(self.getBuildDir(), "patched.core")
240        with open("linux-x86_64.core", "rb") as f:
241            core = f.read()
242        core = replace_path(core, "/test" * 817 + "/a.out", exe_outside)
243        with open(core_file, "wb") as f:
244            f.write(core)
245
246        # Set sysroot and load core
247        self.runCmd("platform select remote-linux --sysroot '%s'" %
248                    tmp_sysroot)
249        target = self.dbg.CreateTarget(None)
250        self.assertTrue(target, VALID_TARGET)
251        process = target.LoadCore(core_file)
252
253        # Check that we found executable from the sysroot
254        mod_path = str(target.GetModuleAtIndex(0).GetFileSpec())
255        self.assertEqual(mod_path, exe_inside)
256        self.check_all(process, self._x86_64_pid,
257                       self._x86_64_regions, "a.out")
258
259        self.dbg.DeleteTarget(target)
260
261    @skipIfLLVMTargetMissing("AArch64")
262    def test_aarch64_pac(self):
263        """Test that lldb can unwind stack for AArch64 elf core file with PAC enabled."""
264
265        target = self.dbg.CreateTarget("linux-aarch64-pac.out")
266        self.assertTrue(target, VALID_TARGET)
267        process = target.LoadCore("linux-aarch64-pac.core")
268
269        self.check_all(process, self._aarch64_pac_pid, self._aarch64_regions, "a.out")
270
271        self.dbg.DeleteTarget(target)
272
273    @skipIfLLVMTargetMissing("AArch64")
274    @expectedFailureAll(archs=["aarch64"], oslist=["freebsd"],
275                        bugnumber="llvm.org/pr49415")
276    def test_aarch64_regs(self):
277        # check 64 bit ARM core files
278        target = self.dbg.CreateTarget(None)
279        self.assertTrue(target, VALID_TARGET)
280        process = target.LoadCore("linux-aarch64-neon.core")
281
282        values = {}
283        values["x1"] = "0x000000000000002f"
284        values["w1"] = "0x0000002f"
285        values["fp"] = "0x0000007fc5dd7f20"
286        values["lr"] = "0x0000000000400180"
287        values["sp"] = "0x0000007fc5dd7f00"
288        values["pc"] = "0x000000000040014c"
289        values["v0"] = "{0x00 0x00 0x00 0x00 0x00 0x00 0xe0 0x3f 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00}"
290        values["v1"] = "{0x00 0x00 0x00 0x00 0x00 0x00 0xf8 0x3f 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00}"
291        values["v2"] = "{0x00 0x00 0x00 0x00 0x00 0x00 0x04 0x40 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00}"
292        values["v3"] = "{0x00 0x00 0x00 0x00 0x00 0x00 0x0c 0x40 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00}"
293        values["v4"] = "{0x00 0x00 0x90 0x40 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00}"
294        values["v5"] = "{0x00 0x00 0xb0 0x40 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00}"
295        values["v6"] = "{0x00 0x00 0xd0 0x40 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00}"
296        values["v7"] = "{0x00 0x00 0xf0 0x40 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00}"
297        values["v8"] = "{0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11}"
298        values["v27"] = "{0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00}"
299        values["v28"] = "{0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00}"
300        values["v31"] = "{0x30 0x30 0x30 0x30 0x30 0x30 0x30 0x30 0x30 0x30 0x30 0x30 0x30 0x30 0x30 0x30}"
301        values["s2"] = "0"
302        values["s3"] = "0"
303        values["s4"] = "4.5"
304        values["s5"] = "5.5"
305        values["s6"] = "6.5"
306        values["s7"] = "7.5"
307        values["s8"] = "1.14437e-28"
308        values["s30"] = "0"
309        values["s31"] = "6.40969e-10"
310        values["d0"] = "0.5"
311        values["d1"] = "1.5"
312        values["d2"] = "2.5"
313        values["d3"] = "3.5"
314        values["d4"] = "5.35161536149201e-315"
315        values["d5"] = "5.36197666906508e-315"
316        values["d6"] = "5.37233797663815e-315"
317        values["d7"] = "5.38269928421123e-315"
318        values["d8"] = "1.80107573659442e-226"
319        values["d30"] = "0"
320        values["d31"] = "1.39804328609529e-76"
321        values["fpsr"] = "0x00000000"
322        values["fpcr"] = "0x00000000"
323
324        for regname, value in values.items():
325            self.expect("register read {}".format(regname),
326                        substrs=["{} = {}".format(regname, value)])
327
328        self.expect("register read --all")
329
330    @skipIfLLVMTargetMissing("AArch64")
331    @expectedFailureAll(archs=["aarch64"], oslist=["freebsd"],
332                        bugnumber="llvm.org/pr49415")
333    def test_aarch64_sve_regs_fpsimd(self):
334        # check 64 bit ARM core files
335        target = self.dbg.CreateTarget(None)
336        self.assertTrue(target, VALID_TARGET)
337        process = target.LoadCore("linux-aarch64-sve-fpsimd.core")
338
339        values = {}
340        values["x1"] = "0x000000000000002f"
341        values["w1"] = "0x0000002f"
342        values["fp"] = "0x0000ffffcbad8d50"
343        values["lr"] = "0x0000000000400180"
344        values["sp"] = "0x0000ffffcbad8d30"
345        values["pc"] = "0x000000000040014c"
346        values["cpsr"] = "0x00001000"
347        values["v0"] = "{0x00 0x00 0x00 0x00 0x00 0x00 0xe0 0x3f 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00}"
348        values["v1"] = "{0x00 0x00 0x00 0x00 0x00 0x00 0xf8 0x3f 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00}"
349        values["v2"] = "{0x00 0x00 0x00 0x00 0x00 0x00 0x04 0x40 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00}"
350        values["v3"] = "{0x00 0x00 0x00 0x00 0x00 0x00 0x0c 0x40 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00}"
351        values["v4"] = "{0x00 0x00 0x90 0x40 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00}"
352        values["v5"] = "{0x00 0x00 0xb0 0x40 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00}"
353        values["v6"] = "{0x00 0x00 0xd0 0x40 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00}"
354        values["v7"] = "{0x00 0x00 0xf0 0x40 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00}"
355        values["v8"] = "{0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11}"
356        values["v27"] = "{0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00}"
357        values["v28"] = "{0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00}"
358        values["v31"] = "{0x30 0x30 0x30 0x30 0x30 0x30 0x30 0x30 0x30 0x30 0x30 0x30 0x30 0x30 0x30 0x30}"
359        values["s2"] = "0"
360        values["s3"] = "0"
361        values["s4"] = "4.5"
362        values["s5"] = "5.5"
363        values["s6"] = "6.5"
364        values["s7"] = "7.5"
365        values["s8"] = "1.14437e-28"
366        values["s30"] = "0"
367        values["s31"] = "6.40969e-10"
368        values["d0"] = "0.5"
369        values["d1"] = "1.5"
370        values["d2"] = "2.5"
371        values["d3"] = "3.5"
372        values["d4"] = "5.35161536149201e-315"
373        values["d5"] = "5.36197666906508e-315"
374        values["d6"] = "5.37233797663815e-315"
375        values["d7"] = "5.38269928421123e-315"
376        values["d8"] = "1.80107573659442e-226"
377        values["d30"] = "0"
378        values["d31"] = "1.39804328609529e-76"
379        values["fpsr"] = "0x00000000"
380        values["fpcr"] = "0x00000000"
381        values["vg"] = "0x0000000000000004"
382        values["z0"] = "{0x00 0x00 0x00 0x00 0x00 0x00 0xe0 0x3f 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00}"
383        values["z1"] = "{0x00 0x00 0x00 0x00 0x00 0x00 0xf8 0x3f 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00}"
384        values["z2"] = "{0x00 0x00 0x00 0x00 0x00 0x00 0x04 0x40 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00}"
385        values["z3"] = "{0x00 0x00 0x00 0x00 0x00 0x00 0x0c 0x40 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00}"
386        values["z4"] = "{0x00 0x00 0x90 0x40 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00}"
387        values["z5"] = "{0x00 0x00 0xb0 0x40 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00}"
388        values["z6"] = "{0x00 0x00 0xd0 0x40 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00}"
389        values["z7"] = "{0x00 0x00 0xf0 0x40 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00}"
390        values["z8"] = "{0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00}"
391        values["z27"] = "{0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00}"
392        values["z28"] = "{0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00}"
393        values["z31"] = "{0x30 0x30 0x30 0x30 0x30 0x30 0x30 0x30 0x30 0x30 0x30 0x30 0x30 0x30 0x30 0x30 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00}"
394        values["p0"] = "{0x00 0x00 0x00 0x00}"
395        values["p1"] = "{0x00 0x00 0x00 0x00}"
396        values["p2"] = "{0x00 0x00 0x00 0x00}"
397        values["p4"] = "{0x00 0x00 0x00 0x00}"
398        values["p3"] = "{0x00 0x00 0x00 0x00}"
399        values["p6"] = "{0x00 0x00 0x00 0x00}"
400        values["p5"] = "{0x00 0x00 0x00 0x00}"
401        values["p7"] = "{0x00 0x00 0x00 0x00}"
402        values["p8"] = "{0x00 0x00 0x00 0x00}"
403        values["p9"] = "{0x00 0x00 0x00 0x00}"
404        values["p11"] = "{0x00 0x00 0x00 0x00}"
405        values["p10"] = "{0x00 0x00 0x00 0x00}"
406        values["p12"] = "{0x00 0x00 0x00 0x00}"
407        values["p13"] = "{0x00 0x00 0x00 0x00}"
408        values["p14"] = "{0x00 0x00 0x00 0x00}"
409        values["p15"] = "{0x00 0x00 0x00 0x00}"
410        values["ffr"] = "{0x00 0x00 0x00 0x00}"
411
412        for regname, value in values.items():
413            self.expect("register read {}".format(regname),
414                        substrs=["{} = {}".format(regname, value)])
415
416        self.expect("register read --all")
417
418    @skipIfLLVMTargetMissing("AArch64")
419    def test_aarch64_sve_regs_full(self):
420        # check 64 bit ARM core files
421        target = self.dbg.CreateTarget(None)
422        self.assertTrue(target, VALID_TARGET)
423        process = target.LoadCore("linux-aarch64-sve-full.core")
424
425        values = {}
426        values["fp"] = "0x0000fffffc1ff4f0"
427        values["lr"] = "0x0000000000400170"
428        values["sp"] = "0x0000fffffc1ff4d0"
429        values["pc"] = "0x000000000040013c"
430        values["v0"] = "{0x00 0x00 0xf0 0x40 0x00 0x00 0xf0 0x40 0x00 0x00 0xf0 0x40 0x00 0x00 0xf0 0x40}"
431        values["v1"] = "{0x00 0x00 0x38 0x41 0x00 0x00 0x38 0x41 0x00 0x00 0x38 0x41 0x00 0x00 0x38 0x41}"
432        values["v2"] = "{0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00}"
433        values["v3"] = "{0x00 0x00 0x78 0x41 0x00 0x00 0x78 0x41 0x00 0x00 0x78 0x41 0x00 0x00 0x78 0x41}"
434        values["s0"] = "7.5"
435        values["s1"] = "11.5"
436        values["s2"] = "0"
437        values["s3"] = "15.5"
438        values["d0"] = "65536.0158538818"
439        values["d1"] = "1572864.25476074"
440        values["d2"] = "0"
441        values["d3"] = "25165828.0917969"
442        values["vg"] = "0x0000000000000004"
443        values["z0"] = "{0x00 0x00 0xf0 0x40 0x00 0x00 0xf0 0x40 0x00 0x00 0xf0 0x40 0x00 0x00 0xf0 0x40 0x00 0x00 0xf0 0x40 0x00 0x00 0xf0 0x40 0x00 0x00 0xf0 0x40 0x00 0x00 0xf0 0x40}"
444        values["z1"] = "{0x00 0x00 0x38 0x41 0x00 0x00 0x38 0x41 0x00 0x00 0x38 0x41 0x00 0x00 0x38 0x41 0x00 0x00 0x38 0x41 0x00 0x00 0x38 0x41 0x00 0x00 0x38 0x41 0x00 0x00 0x38 0x41}"
445        values["z2"] = "{0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00}"
446        values["z3"] = "{0x00 0x00 0x78 0x41 0x00 0x00 0x78 0x41 0x00 0x00 0x78 0x41 0x00 0x00 0x78 0x41 0x00 0x00 0x78 0x41 0x00 0x00 0x78 0x41 0x00 0x00 0x78 0x41 0x00 0x00 0x78 0x41}"
447        values["p0"] = "{0x11 0x11 0x11 0x11}"
448        values["p1"] = "{0x11 0x11 0x11 0x11}"
449        values["p2"] = "{0x00 0x00 0x00 0x00}"
450        values["p3"] = "{0x11 0x11 0x11 0x11}"
451        values["p4"] = "{0x00 0x00 0x00 0x00}"
452
453        for regname, value in values.items():
454            self.expect("register read {}".format(regname),
455                        substrs=["{} = {}".format(regname, value)])
456
457        self.expect("register read --all")
458
459    @skipIfLLVMTargetMissing("AArch64")
460    def test_aarch64_pac_regs(self):
461        # Test AArch64/Linux Pointer Authenication register read
462        target = self.dbg.CreateTarget(None)
463        self.assertTrue(target, VALID_TARGET)
464        process = target.LoadCore("linux-aarch64-pac.core")
465
466        values = {"data_mask": "0x007f00000000000", "code_mask": "0x007f00000000000"}
467
468        for regname, value in values.items():
469            self.expect("register read {}".format(regname),
470                        substrs=["{} = {}".format(regname, value)])
471
472        self.expect("register read --all")
473
474    @skipIfLLVMTargetMissing("ARM")
475    def test_arm_core(self):
476        # check 32 bit ARM core file
477        target = self.dbg.CreateTarget(None)
478        self.assertTrue(target, VALID_TARGET)
479        process = target.LoadCore("linux-arm.core")
480
481        values = {}
482        values["r0"] = "0x00000000"
483        values["r1"] = "0x00000001"
484        values["r2"] = "0x00000002"
485        values["r3"] = "0x00000003"
486        values["r4"] = "0x00000004"
487        values["r5"] = "0x00000005"
488        values["r6"] = "0x00000006"
489        values["r7"] = "0x00000007"
490        values["r8"] = "0x00000008"
491        values["r9"] = "0x00000009"
492        values["r10"] = "0x0000000a"
493        values["r11"] = "0x0000000b"
494        values["r12"] = "0x0000000c"
495        values["sp"] = "0x0000000d"
496        values["lr"] = "0x0000000e"
497        values["pc"] = "0x0000000f"
498        values["cpsr"] = "0x00000010"
499        for regname, value in values.items():
500            self.expect("register read {}".format(regname),
501                        substrs=["{} = {}".format(regname, value)])
502
503        self.expect("register read --all")
504
505    def check_memory_regions(self, process, region_count):
506        region_list = process.GetMemoryRegions()
507        self.assertEqual(region_list.GetSize(), region_count)
508
509        region = lldb.SBMemoryRegionInfo()
510
511        # Check we have the right number of regions.
512        self.assertEqual(region_list.GetSize(), region_count)
513
514        # Check that getting a region beyond the last in the list fails.
515        self.assertFalse(
516            region_list.GetMemoryRegionAtIndex(
517                region_count, region))
518
519        # Check each region is valid.
520        for i in range(region_list.GetSize()):
521            # Check we can actually get this region.
522            self.assertTrue(region_list.GetMemoryRegionAtIndex(i, region))
523
524            # Every region in the list should be mapped.
525            self.assertTrue(region.IsMapped())
526
527            # Test the address at the start of a region returns it's enclosing
528            # region.
529            begin_address = region.GetRegionBase()
530            region_at_begin = lldb.SBMemoryRegionInfo()
531            error = process.GetMemoryRegionInfo(begin_address, region_at_begin)
532            self.assertEqual(region, region_at_begin)
533
534            # Test an address in the middle of a region returns it's enclosing
535            # region.
536            middle_address = (region.GetRegionBase() +
537                              region.GetRegionEnd()) // 2
538            region_at_middle = lldb.SBMemoryRegionInfo()
539            error = process.GetMemoryRegionInfo(
540                middle_address, region_at_middle)
541            self.assertEqual(region, region_at_middle)
542
543            # Test the address at the end of a region returns it's enclosing
544            # region.
545            end_address = region.GetRegionEnd() - 1
546            region_at_end = lldb.SBMemoryRegionInfo()
547            error = process.GetMemoryRegionInfo(end_address, region_at_end)
548            self.assertEqual(region, region_at_end)
549
550            # Check that quering the end address does not return this region but
551            # the next one.
552            next_region = lldb.SBMemoryRegionInfo()
553            error = process.GetMemoryRegionInfo(
554                region.GetRegionEnd(), next_region)
555            self.assertNotEqual(region, next_region)
556            self.assertEqual(
557                region.GetRegionEnd(),
558                next_region.GetRegionBase())
559
560        # Check that query beyond the last region returns an unmapped region
561        # that ends at LLDB_INVALID_ADDRESS
562        last_region = lldb.SBMemoryRegionInfo()
563        region_list.GetMemoryRegionAtIndex(region_count - 1, last_region)
564        end_region = lldb.SBMemoryRegionInfo()
565        error = process.GetMemoryRegionInfo(
566            last_region.GetRegionEnd(), end_region)
567        self.assertFalse(end_region.IsMapped())
568        self.assertEqual(
569            last_region.GetRegionEnd(),
570            end_region.GetRegionBase())
571        self.assertEqual(end_region.GetRegionEnd(), lldb.LLDB_INVALID_ADDRESS)
572
573    def check_state(self, process):
574        with open(os.devnull) as devnul:
575            # sanitize test output
576            self.dbg.SetOutputFileHandle(devnul, False)
577            self.dbg.SetErrorFileHandle(devnul, False)
578
579            self.assertTrue(process.is_stopped)
580
581            # Process.Continue
582            error = process.Continue()
583            self.assertFalse(error.Success())
584            self.assertTrue(process.is_stopped)
585
586            # Thread.StepOut
587            thread = process.GetSelectedThread()
588            thread.StepOut()
589            self.assertTrue(process.is_stopped)
590
591            # command line
592            self.dbg.HandleCommand('s')
593            self.assertTrue(process.is_stopped)
594            self.dbg.HandleCommand('c')
595            self.assertTrue(process.is_stopped)
596
597            # restore file handles
598            self.dbg.SetOutputFileHandle(None, False)
599            self.dbg.SetErrorFileHandle(None, False)
600
601    def check_stack(self, process, pid, thread_name):
602        thread = process.GetSelectedThread()
603        self.assertTrue(thread)
604        self.assertEqual(thread.GetThreadID(), pid)
605        self.assertEqual(thread.GetName(), thread_name)
606        backtrace = ["bar", "foo", "_start"]
607        self.assertEqual(thread.GetNumFrames(), len(backtrace))
608        for i in range(len(backtrace)):
609            frame = thread.GetFrameAtIndex(i)
610            self.assertTrue(frame)
611            self.assertEqual(frame.GetFunctionName(), backtrace[i])
612            self.assertEqual(frame.GetLineEntry().GetLine(),
613                             line_number("main.c", "Frame " + backtrace[i]))
614            self.assertEqual(
615                frame.FindVariable("F").GetValueAsUnsigned(), ord(
616                    backtrace[i][0]))
617
618    def check_all(self, process, pid, region_count, thread_name):
619        self.assertTrue(process, PROCESS_IS_VALID)
620        self.assertEqual(process.GetNumThreads(), 1)
621        self.assertEqual(process.GetProcessID(), pid)
622
623        self.check_state(process)
624
625        self.check_stack(process, pid, thread_name)
626
627        self.check_memory_regions(process, region_count)
628
629    def do_test(self, filename, pid, region_count, thread_name):
630        target = self.dbg.CreateTarget(filename + ".out")
631        process = target.LoadCore(filename + ".core")
632
633        self.check_all(process, pid, region_count, thread_name)
634
635        self.dbg.DeleteTarget(target)
636
637
638def replace_path(binary, replace_from, replace_to):
639    src = replace_from.encode()
640    dst = replace_to.encode()
641    dst += b"\0" * (len(src) - len(dst))
642    return binary.replace(src, dst)
643