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