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