This revision was automatically updated to reflect the committed changes.
Closed by commit rGaedb328a4dc9: [lldb] Introduce a FreeBSDKernel plugin for
vmcores (authored by mgorny).
Herald added a project: LLDB.
Repository:
rG LLVM Github Monorepo
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D114911/new/
https://reviews.llvm.org/D114911
Files:
lldb/cmake/modules/LLDBConfig.cmake
lldb/packages/Python/lldbsuite/test/lldbtest.py
lldb/source/Plugins/Process/CMakeLists.txt
lldb/source/Plugins/Process/FreeBSDKernel/CMakeLists.txt
lldb/source/Plugins/Process/FreeBSDKernel/ProcessFreeBSDKernel.cpp
lldb/source/Plugins/Process/FreeBSDKernel/ProcessFreeBSDKernel.h
lldb/source/Plugins/Process/FreeBSDKernel/RegisterContextFreeBSDKernel_arm64.cpp
lldb/source/Plugins/Process/FreeBSDKernel/RegisterContextFreeBSDKernel_arm64.h
lldb/source/Plugins/Process/FreeBSDKernel/RegisterContextFreeBSDKernel_i386.cpp
lldb/source/Plugins/Process/FreeBSDKernel/RegisterContextFreeBSDKernel_i386.h
lldb/source/Plugins/Process/FreeBSDKernel/RegisterContextFreeBSDKernel_x86_64.cpp
lldb/source/Plugins/Process/FreeBSDKernel/RegisterContextFreeBSDKernel_x86_64.h
lldb/source/Plugins/Process/FreeBSDKernel/ThreadFreeBSDKernel.cpp
lldb/source/Plugins/Process/FreeBSDKernel/ThreadFreeBSDKernel.h
lldb/test/API/functionalities/postmortem/FreeBSDKernel/TestFreeBSDKernelVMCore.py
lldb/test/API/functionalities/postmortem/FreeBSDKernel/kernel-amd64.yaml
lldb/test/API/functionalities/postmortem/FreeBSDKernel/kernel-arm64.yaml
lldb/test/API/functionalities/postmortem/FreeBSDKernel/kernel-i386.yaml
lldb/test/API/functionalities/postmortem/FreeBSDKernel/tools/README.rst
lldb/test/API/functionalities/postmortem/FreeBSDKernel/tools/copy-sparse.py
lldb/test/API/functionalities/postmortem/FreeBSDKernel/tools/libfbsdvmcore-print-offsets.patch
lldb/test/API/functionalities/postmortem/FreeBSDKernel/tools/test.script
lldb/test/API/functionalities/postmortem/FreeBSDKernel/vmcore-amd64-full.bz2
lldb/test/API/functionalities/postmortem/FreeBSDKernel/vmcore-amd64-minidump.bz2
lldb/test/API/functionalities/postmortem/FreeBSDKernel/vmcore-arm64-minidump.bz2
lldb/test/API/functionalities/postmortem/FreeBSDKernel/vmcore-i386-minidump.bz2
Index: lldb/test/API/functionalities/postmortem/FreeBSDKernel/tools/test.script
===================================================================
--- /dev/null
+++ lldb/test/API/functionalities/postmortem/FreeBSDKernel/tools/test.script
@@ -0,0 +1,5 @@
+thread list
+register read pc
+bt
+p *(int*)&hz
+memory read &hz
Index: lldb/test/API/functionalities/postmortem/FreeBSDKernel/tools/libfbsdvmcore-print-offsets.patch
===================================================================
--- /dev/null
+++ lldb/test/API/functionalities/postmortem/FreeBSDKernel/tools/libfbsdvmcore-print-offsets.patch
@@ -0,0 +1,166 @@
+diff --git a/lib/fvc.c b/lib/fvc.c
+index e6b96c1..4033f78 100644
+--- a/lib/fvc.c
++++ b/lib/fvc.c
+@@ -297,6 +297,7 @@ fvc_read(fvc_t *kd, fvc_addr_t kva, void *buf, size_t len)
+ _fvc_syserr(kd, kd->program, "fvc_read");
+ break;
+ }
++ printf("%% RD: %zu %d\n", pa, cc);
+ /*
+ * If ka_kvatop returns a bogus value or our core file is
+ * truncated, we might wind up seeking beyond the end of the
+@@ -331,3 +332,8 @@ fvc_kerndisp(fvc_t *kd)
+
+ return (kd->arch->ka_kerndisp(kd));
+ }
++
++ssize_t xpread(int fd, void *buf, size_t count, off_t offset) {
++ printf("%% RD: %zu %zu\n", offset, count);
++ return pread(fd, buf, count, offset);
++}
+diff --git a/lib/fvc.h b/lib/fvc.h
+index 8680079..ff1e0f0 100644
+--- a/lib/fvc.h
++++ b/lib/fvc.h
+@@ -54,6 +54,8 @@ typedef unsigned char fvc_vm_prot_t;
+ #define FVC_VM_PROT_WRITE ((fvc_vm_prot_t) 0x02)
+ #define FVC_VM_PROT_EXECUTE ((fvc_vm_prot_t) 0x04)
+
++ssize_t xpread(int fd, void *buf, size_t count, off_t offset);
++
+ struct fvc_page {
+ unsigned int kp_version;
+ fvc_addr_t kp_paddr;
+diff --git a/lib/fvc_amd64.c b/lib/fvc_amd64.c
+index 4d27998..69f1807 100644
+--- a/lib/fvc_amd64.c
++++ b/lib/fvc_amd64.c
+@@ -205,7 +205,7 @@ _amd64_vatop(fvc_t *kd, fvc_addr_t va, off_t *pa)
+ _fvc_err(kd, kd->program, "_amd64_vatop: pdpe_pa not found");
+ goto invalid;
+ }
+- if (pread(kd->pmfd, &pdpe, sizeof(pdpe), ofs) != sizeof(pdpe)) {
++ if (xpread(kd->pmfd, &pdpe, sizeof(pdpe), ofs) != sizeof(pdpe)) {
+ _fvc_syserr(kd, kd->program, "_amd64_vatop: read pdpe");
+ goto invalid;
+ }
+@@ -237,7 +237,7 @@ _amd64_vatop(fvc_t *kd, fvc_addr_t va, off_t *pa)
+ _fvc_syserr(kd, kd->program, "_amd64_vatop: pde_pa not found");
+ goto invalid;
+ }
+- if (pread(kd->pmfd, &pde, sizeof(pde), ofs) != sizeof(pde)) {
++ if (xpread(kd->pmfd, &pde, sizeof(pde), ofs) != sizeof(pde)) {
+ _fvc_syserr(kd, kd->program, "_amd64_vatop: read pde");
+ goto invalid;
+ }
+@@ -269,7 +269,7 @@ _amd64_vatop(fvc_t *kd, fvc_addr_t va, off_t *pa)
+ _fvc_err(kd, kd->program, "_amd64_vatop: pte_pa not found");
+ goto invalid;
+ }
+- if (pread(kd->pmfd, &pte, sizeof(pte), ofs) != sizeof(pte)) {
++ if (xpread(kd->pmfd, &pte, sizeof(pte), ofs) != sizeof(pte)) {
+ _fvc_syserr(kd, kd->program, "_amd64_vatop: read");
+ goto invalid;
+ }
+diff --git a/lib/fvc_minidump_aarch64.c b/lib/fvc_minidump_aarch64.c
+index 4b8477a..a1c5b42 100644
+--- a/lib/fvc_minidump_aarch64.c
++++ b/lib/fvc_minidump_aarch64.c
+@@ -86,7 +86,7 @@ _aarch64_minidump_initvtop(fvc_t *kd)
+ return (-1);
+ }
+ kd->vmst = vmst;
+- if (pread(kd->pmfd, &vmst->hdr, sizeof(vmst->hdr), 0) !=
++ if (xpread(kd->pmfd, &vmst->hdr, sizeof(vmst->hdr), 0) !=
+ sizeof(vmst->hdr)) {
+ _fvc_err(kd, kd->program, "cannot read dump header");
+ return (-1);
+diff --git a/lib/fvc_minidump_amd64.c b/lib/fvc_minidump_amd64.c
+index 93e8238..0d2237f 100644
+--- a/lib/fvc_minidump_amd64.c
++++ b/lib/fvc_minidump_amd64.c
+@@ -126,7 +126,7 @@ _amd64_minidump_initvtop(fvc_t *kd)
+ return (-1);
+ }
+ kd->vmst = vmst;
+- if (pread(kd->pmfd, &vmst->hdr, sizeof(vmst->hdr), 0) !=
++ if (xpread(kd->pmfd, &vmst->hdr, sizeof(vmst->hdr), 0) !=
+ sizeof(vmst->hdr)) {
+ _fvc_err(kd, kd->program, "cannot read dump header");
+ return (-1);
+@@ -269,7 +269,7 @@ _amd64_minidump_vatop(fvc_t *kd, fvc_addr_t va, off_t *pa)
+ (uintmax_t)a);
+ goto invalid;
+ }
+- if (pread(kd->pmfd, &pt, AMD64_PAGE_SIZE, ofs) !=
++ if (xpread(kd->pmfd, &pt, AMD64_PAGE_SIZE, ofs) !=
+ AMD64_PAGE_SIZE) {
+ _fvc_err(kd, kd->program,
+ "cannot read page table entry for %ju",
+diff --git a/lib/fvc_minidump_i386.c b/lib/fvc_minidump_i386.c
+index 61cc3db..b3ab955 100644
+--- a/lib/fvc_minidump_i386.c
++++ b/lib/fvc_minidump_i386.c
+@@ -94,7 +94,7 @@ _i386_minidump_initvtop(fvc_t *kd)
+ return (-1);
+ }
+ kd->vmst = vmst;
+- if (pread(kd->pmfd, &vmst->hdr, sizeof(vmst->hdr), 0) !=
++ if (xpread(kd->pmfd, &vmst->hdr, sizeof(vmst->hdr), 0) !=
+ sizeof(vmst->hdr)) {
+ _fvc_err(kd, kd->program, "cannot read dump header");
+ return (-1);
+diff --git a/lib/fvc_private.c b/lib/fvc_private.c
+index 0069a54..fc798fe 100644
+--- a/lib/fvc_private.c
++++ b/lib/fvc_private.c
+@@ -130,7 +130,7 @@ _fvc_is_minidump(fvc_t *kd)
+ {
+ char minihdr[8];
+
+- if (pread(kd->pmfd, &minihdr, 8, 0) == 8 &&
++ if (xpread(kd->pmfd, &minihdr, 8, 0) == 8 &&
+ memcmp(&minihdr, "minidump", 8) == 0)
+ return (1);
+ return (0);
+@@ -256,6 +256,7 @@ _fvc_pmap_get(fvc_t *kd, u_long idx, size_t len)
+
+ if ((off_t)off >= kd->pt_sparse_off)
+ return (NULL);
++ printf("%% RD: %zu %zu\n", kd->page_map_off+off, len);
+ return (void *)((uintptr_t)kd->page_map + off);
+ }
+
+@@ -270,8 +271,13 @@ _fvc_map_get(fvc_t *kd, u_long pa, unsigned int page_size)
+ return NULL;
+
+ addr = (uintptr_t)kd->page_map + off;
+- if (off >= kd->pt_sparse_off)
++ if (off >= kd->pt_sparse_off) {
++
+ addr = (uintptr_t)kd->sparse_map + (off - kd->pt_sparse_off);
++ printf("%% RD: %zu %u\n", off, page_size);
++ }
++ else
++ printf("%% RD: %zu %u\n", kd->page_map_off+off, page_size);
+ return (void *)addr;
+ }
+
+@@ -289,6 +295,7 @@ _fvc_pt_init(fvc_t *kd, size_t dump_avail_size, off_t dump_avail_off,
+ if (dump_avail_size > 0) {
+ kd->dump_avail = mmap(NULL, kd->dump_avail_size, PROT_READ,
+ MAP_PRIVATE, kd->pmfd, dump_avail_off);
++ printf("%% RD: %zu %zu\n", dump_avail_off, dump_avail_size);
+ } else {
+ /*
+ * Older version minidumps don't provide dump_avail[],
+@@ -309,7 +316,7 @@ _fvc_pt_init(fvc_t *kd, size_t dump_avail_size, off_t dump_avail_off,
+ map_len);
+ return (-1);
+ }
+- rd = pread(kd->pmfd, kd->pt_map, map_len, map_off);
++ rd = xpread(kd->pmfd, kd->pt_map, map_len, map_off);
+ if (rd < 0 || rd != (ssize_t)map_len) {
+ _fvc_err(kd, kd->program, "cannot read %zu bytes for bitmap",
+ map_len);
Index: lldb/test/API/functionalities/postmortem/FreeBSDKernel/tools/copy-sparse.py
===================================================================
--- /dev/null
+++ lldb/test/API/functionalities/postmortem/FreeBSDKernel/tools/copy-sparse.py
@@ -0,0 +1,34 @@
+#!/usr/bin/env python
+
+import argparse
+import re
+import sys
+
+
+def main():
+ argp = argparse.ArgumentParser()
+ argp.add_argument('infile', type=argparse.FileType('rb'),
+ help='Input vmcore file')
+ argp.add_argument('outfile', type=argparse.FileType('wb'),
+ help='Output vmcore file')
+ args = argp.parse_args()
+
+ inf = args.infile
+ outf = args.outfile
+ line_re = re.compile(r"^% RD: (\d+) (\d+)")
+
+ # copy the first chunk that usually includes ELF headers
+ # (not output by patched libfbsdvmcore since libelf reads this)
+ outf.write(inf.read(1024))
+
+ for l in sys.stdin:
+ m = line_re.match(l)
+ offset, size = [int(x) for x in m.groups()]
+
+ inf.seek(offset)
+ outf.seek(offset)
+ outf.write(inf.read(size))
+
+
+if __name__ == "__main__":
+ main()
Index: lldb/test/API/functionalities/postmortem/FreeBSDKernel/tools/README.rst
===================================================================
--- /dev/null
+++ lldb/test/API/functionalities/postmortem/FreeBSDKernel/tools/README.rst
@@ -0,0 +1,36 @@
+How to create vmcores for tests
+===============================
+
+1. Boot a FreeBSD VM with as little memory as possible and create a core dump
+ per `FreeBSD Handbook Kernel Debugging Chapter`_. Note that you may need to
+ reboot with more memory after the kernel panic as otherwise savecore(8) may
+ fail.
+
+ For instance, I was able to boot FreeBSD and qemu-system-x86_64 with 128 MiB
+ RAM but had to increase it to 256 MiB for the boot after kernel panic.
+
+2. Transfer the kernel image (``/boot/kernel/kernel``) and vmcore
+ (``/var/crash/vmcore.latest``) from the VM.
+
+3. Patch libfbsdvmcore using ``libfbsdvmcore-print-offsets.patch`` and build
+ LLDB against the patched library.
+
+4. Do a test run of ``test.script`` in LLDB against the kernel + vmcore::
+
+ lldb -b -s test.script --core /path/to/core /path/to/kernel
+
+ If everything works fine, the LLDB output should be interspersed with
+ ``%RD`` lines.
+
+5. Use the ``copy-sparse.py`` tool to create a sparse version of the vmcore::
+
+ lldb -b -s test.script --core /path/to/core /path/to/kernel |
+ grep '^% RD' | python copy-sparse.py /path/to/core vmcore.sparse
+
+6. Compress the sparse vmcore file using ``bzip2``::
+
+ bzip2 -9 vmcore.sparse
+
+
+.. _FreeBSD Handbook Kernel Debugging Chapter:
+ https://docs.freebsd.org/en/books/developers-handbook/kerneldebug/
Index: lldb/test/API/functionalities/postmortem/FreeBSDKernel/kernel-i386.yaml
===================================================================
--- /dev/null
+++ lldb/test/API/functionalities/postmortem/FreeBSDKernel/kernel-i386.yaml
@@ -0,0 +1,38 @@
+--- !ELF
+FileHeader:
+ Class: ELFCLASS32
+ Data: ELFDATA2LSB
+ OSABI: ELFOSABI_FREEBSD
+ Type: ET_EXEC
+ Machine: EM_386
+ Entry: 0x8F9000
+Sections:
+ - Name: .bss
+ Type: SHT_NOBITS
+ Flags: [ SHF_WRITE, SHF_ALLOC ]
+ Address: 0x1AB7B00
+ AddressAlign: 0x80
+ Offset: 0x12B7AB0
+ Size: 0x2D48D8
+Symbols:
+ - Name: kernbase
+ Index: SHN_ABS
+ Binding: STB_GLOBAL
+ Value: 0x800000
+ - Name: dumppcb
+ Type: STT_OBJECT
+ Section: .bss
+ Value: 0x1D2D9A0
+ Size: 0xC0
+ - Name: hz
+ Type: STT_OBJECT
+ Section: .bss
+ Binding: STB_GLOBAL
+ Value: 0x1D4053C
+ Size: 0x4
+ - Name: IdlePDPT
+ Type: STT_OBJECT
+ Section: .bss
+ Binding: STB_GLOBAL
+ Value: 0x1D8B044
+ Size: 0x4
Index: lldb/test/API/functionalities/postmortem/FreeBSDKernel/kernel-arm64.yaml
===================================================================
--- /dev/null
+++ lldb/test/API/functionalities/postmortem/FreeBSDKernel/kernel-arm64.yaml
@@ -0,0 +1,30 @@
+--- !ELF
+FileHeader:
+ Class: ELFCLASS64
+ Data: ELFDATA2LSB
+ Type: ET_EXEC
+ Machine: EM_AARCH64
+ Entry: 0xFFFF000000000800
+Sections:
+ - Name: .bss
+ Type: SHT_NOBITS
+ Flags: [ SHF_WRITE, SHF_ALLOC ]
+ Address: 0xFFFF000000C35000
+ AddressAlign: 0x1000
+ Size: 0x37F000
+Symbols:
+ - Name: kernbase
+ Index: SHN_ABS
+ Binding: STB_GLOBAL
+ Value: 0xFFFF000000000000
+ - Name: dumppcb
+ Type: STT_OBJECT
+ Section: .bss
+ Value: 0xFFFF000000DF3790
+ Size: 0x560
+ - Name: hz
+ Type: STT_OBJECT
+ Section: .bss
+ Binding: STB_GLOBAL
+ Value: 0xFFFF000000E2651C
+ Size: 0x4
Index: lldb/test/API/functionalities/postmortem/FreeBSDKernel/kernel-amd64.yaml
===================================================================
--- /dev/null
+++ lldb/test/API/functionalities/postmortem/FreeBSDKernel/kernel-amd64.yaml
@@ -0,0 +1,38 @@
+--- !ELF
+FileHeader:
+ Class: ELFCLASS64
+ Data: ELFDATA2LSB
+ OSABI: ELFOSABI_FREEBSD
+ Type: ET_EXEC
+ Machine: EM_X86_64
+ Entry: 0xFFFFFFFF8037C000
+Sections:
+ - Name: .bss
+ Type: SHT_NOBITS
+ Flags: [ SHF_WRITE, SHF_ALLOC ]
+ Address: 0xFFFFFFFF819BA380
+ AddressAlign: 0x80
+ Offset: 0x17BA348
+ Size: 0x445C80
+Symbols:
+ - Name: kernbase
+ Index: SHN_ABS
+ Binding: STB_GLOBAL
+ Value: 0xFFFFFFFF80000000
+ - Name: KPML4phys
+ Type: STT_OBJECT
+ Section: .bss
+ Binding: STB_GLOBAL
+ Value: 0xFFFFFFFF81D47EB8
+ Size: 0x8
+ - Name: dumppcb
+ Type: STT_OBJECT
+ Section: .bss
+ Value: 0xFFFFFFFF81CA6868
+ Size: 0x140
+ - Name: hz
+ Type: STT_OBJECT
+ Section: .bss
+ Binding: STB_GLOBAL
+ Value: 0xFFFFFFFF81CD4C0C
+ Size: 0x4
Index: lldb/test/API/functionalities/postmortem/FreeBSDKernel/TestFreeBSDKernelVMCore.py
===================================================================
--- /dev/null
+++ lldb/test/API/functionalities/postmortem/FreeBSDKernel/TestFreeBSDKernelVMCore.py
@@ -0,0 +1,153 @@
+import bz2
+import shutil
+import struct
+
+import lldb
+from lldbsuite.test.decorators import *
+from lldbsuite.test.lldbtest import *
+from lldbsuite.test import lldbutil
+
+
+class FreeBSDKernelVMCoreTestCase(TestBase):
+ NO_DEBUG_INFO_TESTCASE = True
+
+ mydir = TestBase.compute_mydir(__file__)
+
+ def make_target(self, src_filename):
+ src = self.getSourcePath(src_filename)
+ dest = self.getBuildArtifact("kernel")
+ self.yaml2obj(src, dest, max_size=30*1024*1024)
+ return self.dbg.CreateTarget(dest)
+
+ def make_vmcore(self, src_filename):
+ src = self.getSourcePath(src_filename)
+ dest = self.getBuildArtifact("vmcore")
+ with bz2.open(src, "rb") as inf:
+ with open(dest, "wb") as outf:
+ shutil.copyfileobj(inf, outf)
+ return dest
+
+ def do_test(self, kernel_yaml, vmcore_bz2, bt_expected, regs_expected,
+ hz_value=100):
+ target = self.make_target(kernel_yaml)
+ vmcore_file = self.make_vmcore(vmcore_bz2)
+ process = target.LoadCore(vmcore_file)
+
+ self.assertTrue(process, PROCESS_IS_VALID)
+ self.assertEqual(process.GetNumThreads(), 1)
+ self.assertEqual(process.GetProcessID(), 0)
+
+ # test memory reading
+ self.expect("expr -- *(int *) &hz",
+ substrs=["(int) $0 = %d" % hz_value])
+
+ main_mod = target.GetModuleAtIndex(0)
+ hz_addr = (main_mod.FindSymbols("hz")[0].symbol.addr
+ .GetLoadAddress(target))
+ error = lldb.SBError()
+ self.assertEqual(process.ReadMemory(hz_addr, 4, error),
+ struct.pack("<I", hz_value))
+
+ # test backtrace
+ self.assertEqual(
+ [process.GetThreadAtIndex(0).GetFrameAtIndex(i).addr
+ .GetLoadAddress(target) for i in range(len(bt_expected))],
+ bt_expected)
+
+ # test registers
+ regs = process.GetThreadAtIndex(0).GetFrameAtIndex(0).GetRegisters()
+ reg_values = {}
+ for regset in regs:
+ for reg in regset:
+ if reg.value is None:
+ continue
+ reg_values[reg.name] = reg.value
+ self.assertEqual(reg_values, regs_expected)
+
+ self.dbg.DeleteTarget(target)
+
+ def test_amd64_full_vmcore(self):
+ self.do_test("kernel-amd64.yaml", "vmcore-amd64-full.bz2",
+ [0xffffffff80c09ade, 0xffffffff80c09916,
+ 0xffffffff80c09d90, 0xffffffff80c09b93,
+ 0xffffffff80c57d91, 0xffffffff80c19e71,
+ 0xffffffff80c192bc, 0xffffffff80c19933,
+ 0xffffffff80c1977f, 0xffffffff8108ba8c,
+ 0xffffffff810620ce],
+ {"rbx": "0x0000000000000000",
+ "rbp": "0xfffffe0085cb2760",
+ "rsp": "0xfffffe0085cb2748",
+ "r12": "0xfffffe0045a6c300",
+ "r13": "0xfffff800033693a8",
+ "r14": "0x0000000000000000",
+ "r15": "0xfffff80003369380",
+ "rip": "0xffffffff80c09ade",
+ })
+
+ def test_amd64_minidump(self):
+ self.do_test("kernel-amd64.yaml", "vmcore-amd64-minidump.bz2",
+ [0xffffffff80c09ade, 0xffffffff80c09916,
+ 0xffffffff80c09d90, 0xffffffff80c09b93,
+ 0xffffffff80c57d91, 0xffffffff80c19e71,
+ 0xffffffff80c192bc, 0xffffffff80c19933,
+ 0xffffffff80c1977f, 0xffffffff8108ba8c,
+ 0xffffffff810620ce],
+ {"rbx": "0x0000000000000000",
+ "rbp": "0xfffffe00798c4760",
+ "rsp": "0xfffffe00798c4748",
+ "r12": "0xfffffe0045b11c00",
+ "r13": "0xfffff800033693a8",
+ "r14": "0x0000000000000000",
+ "r15": "0xfffff80003369380",
+ "rip": "0xffffffff80c09ade",
+ })
+
+ def test_arm64_minidump(self):
+ self.do_test("kernel-arm64.yaml", "vmcore-arm64-minidump.bz2",
+ [0xffff0000004b6e78], # TODO: fix unwinding
+ {"x0": "0x0000000000000000",
+ "x1": "0x0000000000000000",
+ "x2": "0x0000000000000000",
+ "x3": "0x0000000000000000",
+ "x4": "0x0000000000000000",
+ "x5": "0x0000000000000000",
+ "x6": "0x0000000000000000",
+ "x7": "0x0000000000000000",
+ "x8": "0xffffa00001548700",
+ "x9": "0x0000000000000000",
+ "x10": "0xffffa00000e04580",
+ "x11": "0x0000000000000000",
+ "x12": "0x000000000008950a",
+ "x13": "0x0000000000089500",
+ "x14": "0x0000000000000039",
+ "x15": "0x0000000000000000",
+ "x16": "0x00000000ffffffd8",
+ "x17": "0x0000000000000000",
+ "x18": "0xffff000000e6d380",
+ "x19": "0xffff000000af9000",
+ "x20": "0xffff000000b82000",
+ "x21": "0xffffa00000319da8",
+ "x22": "0xffff000000b84000",
+ "x23": "0xffff000000b84000",
+ "x24": "0xffff000000b55000",
+ "x25": "0x0000000000000000",
+ "x26": "0x0000000000040800",
+ "x27": "0x0000000000000000",
+ "x28": "0x00000000002019ca",
+ "fp": "0xffff0000d58f23b0",
+ "sp": "0xffff0000d58f23b0",
+ "pc": "0xffff0000004b6e78",
+ },
+ hz_value=1000)
+
+ def test_i386_minidump(self):
+ self.do_test("kernel-i386.yaml", "vmcore-i386-minidump.bz2",
+ [0x010025c5, 0x01002410, 0x010027d5, 0x01002644,
+ 0x01049a2f, 0x01011077, 0x01010780, 0x01010c7a,
+ 0x01010ab2, 0x013e9e2d, 0xffc033f9],
+ {"ebp": "0x151968e4",
+ "esp": "0x151968d8",
+ "esi": "0x0c77aa80",
+ "edi": "0x03f0dc80",
+ "eip": "0x010025c5",
+ })
Index: lldb/source/Plugins/Process/FreeBSDKernel/ThreadFreeBSDKernel.h
===================================================================
--- /dev/null
+++ lldb/source/Plugins/Process/FreeBSDKernel/ThreadFreeBSDKernel.h
@@ -0,0 +1,36 @@
+//===-- ThreadFreeBSDKernel.h ------------------------------------- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLDB_SOURCE_PLUGINS_PROCESS_FREEBSDKERNEL_THREADFREEBSDKERNEL_H
+#define LLDB_SOURCE_PLUGINS_PROCESS_FREEBSDKERNEL_THREADFREEBSDKERNEL_H
+
+#include "lldb/Target/Thread.h"
+
+class ThreadFreeBSDKernel : public lldb_private::Thread {
+public:
+ ThreadFreeBSDKernel(lldb_private::Process &process, lldb::tid_t tid,
+ lldb::addr_t pcb_addr);
+
+ ~ThreadFreeBSDKernel() override;
+
+ void RefreshStateAfterStop() override;
+
+ lldb::RegisterContextSP GetRegisterContext() override;
+
+ lldb::RegisterContextSP
+ CreateRegisterContextForFrame(lldb_private::StackFrame *frame) override;
+
+protected:
+ bool CalculateStopInfo() override;
+
+private:
+ lldb::RegisterContextSP m_thread_reg_ctx_sp;
+ lldb::addr_t m_pcb_addr;
+};
+
+#endif // LLDB_SOURCE_PLUGINS_PROCESS_FREEBSDKERNEL_THREADFREEBSDKERNEL_H
Index: lldb/source/Plugins/Process/FreeBSDKernel/ThreadFreeBSDKernel.cpp
===================================================================
--- /dev/null
+++ lldb/source/Plugins/Process/FreeBSDKernel/ThreadFreeBSDKernel.cpp
@@ -0,0 +1,85 @@
+//===-- ThreadFreeBSDKernel.cpp -------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "ThreadFreeBSDKernel.h"
+
+#include "lldb/Target/Unwind.h"
+#include "lldb/Utility/Log.h"
+
+#include "Plugins/Process/Utility/RegisterContextFreeBSD_i386.h"
+#include "Plugins/Process/Utility/RegisterContextFreeBSD_x86_64.h"
+#include "Plugins/Process/Utility/RegisterInfoPOSIX_arm64.h"
+#include "ProcessFreeBSDKernel.h"
+#include "RegisterContextFreeBSDKernel_arm64.h"
+#include "RegisterContextFreeBSDKernel_i386.h"
+#include "RegisterContextFreeBSDKernel_x86_64.h"
+#include "ThreadFreeBSDKernel.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+ThreadFreeBSDKernel::ThreadFreeBSDKernel(Process &process, lldb::tid_t tid,
+ lldb::addr_t pcb_addr)
+ : Thread(process, tid), m_pcb_addr(pcb_addr) {}
+
+ThreadFreeBSDKernel::~ThreadFreeBSDKernel() {}
+
+void ThreadFreeBSDKernel::RefreshStateAfterStop() {}
+
+lldb::RegisterContextSP ThreadFreeBSDKernel::GetRegisterContext() {
+ if (!m_reg_context_sp)
+ m_reg_context_sp = CreateRegisterContextForFrame(nullptr);
+ return m_reg_context_sp;
+}
+
+lldb::RegisterContextSP
+ThreadFreeBSDKernel::CreateRegisterContextForFrame(StackFrame *frame) {
+ RegisterContextSP reg_ctx_sp;
+ uint32_t concrete_frame_idx = 0;
+
+ if (frame)
+ concrete_frame_idx = frame->GetConcreteFrameIndex();
+
+ if (concrete_frame_idx == 0) {
+ if (m_thread_reg_ctx_sp)
+ return m_thread_reg_ctx_sp;
+
+ ProcessFreeBSDKernel *process =
+ static_cast<ProcessFreeBSDKernel *>(GetProcess().get());
+ ArchSpec arch = process->GetTarget().GetArchitecture();
+
+ switch (arch.GetMachine()) {
+ case llvm::Triple::aarch64:
+ m_thread_reg_ctx_sp =
+ std::make_shared<RegisterContextFreeBSDKernel_arm64>(
+ *this, std::make_unique<RegisterInfoPOSIX_arm64>(arch, 0),
+ m_pcb_addr);
+ break;
+ case llvm::Triple::x86:
+ m_thread_reg_ctx_sp =
+ std::make_shared<RegisterContextFreeBSDKernel_i386>(
+ *this, new RegisterContextFreeBSD_i386(arch), m_pcb_addr);
+ break;
+ case llvm::Triple::x86_64:
+ m_thread_reg_ctx_sp =
+ std::make_shared<RegisterContextFreeBSDKernel_x86_64>(
+ *this, new RegisterContextFreeBSD_x86_64(arch), m_pcb_addr);
+ break;
+ default:
+ assert(false && "Unsupported architecture passed to ThreadFreeBSDKernel");
+ break;
+ }
+
+ reg_ctx_sp = m_thread_reg_ctx_sp;
+ } else {
+ reg_ctx_sp = GetUnwinder().CreateRegisterContextForFrame(frame);
+ }
+ return reg_ctx_sp;
+}
+
+bool ThreadFreeBSDKernel::CalculateStopInfo() { return false; }
Index: lldb/source/Plugins/Process/FreeBSDKernel/RegisterContextFreeBSDKernel_x86_64.h
===================================================================
--- /dev/null
+++ lldb/source/Plugins/Process/FreeBSDKernel/RegisterContextFreeBSDKernel_x86_64.h
@@ -0,0 +1,41 @@
+//===-- RegisterContextFreeBSDKernel_x86_64.h -------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLDB_SOURCE_PLUGINS_PROCESS_FREEBSDKERNEL_REGISTERCONTEXTFREEBSDKERNEL_X86_64_H
+#define LLDB_SOURCE_PLUGINS_PROCESS_FREEBSDKERNEL_REGISTERCONTEXTFREEBSDKERNEL_X86_64_H
+
+#include "Plugins/Process/Utility/RegisterContextPOSIX_x86.h"
+#include "Plugins/Process/elf-core/RegisterUtilities.h"
+
+class RegisterContextFreeBSDKernel_x86_64 : public RegisterContextPOSIX_x86 {
+public:
+ RegisterContextFreeBSDKernel_x86_64(
+ lldb_private::Thread &thread,
+ lldb_private::RegisterInfoInterface *register_info,
+ lldb::addr_t pcb_addr);
+
+ bool ReadRegister(const lldb_private::RegisterInfo *reg_info,
+ lldb_private::RegisterValue &value) override;
+
+ bool WriteRegister(const lldb_private::RegisterInfo *reg_info,
+ const lldb_private::RegisterValue &value) override;
+
+protected:
+ bool ReadGPR() override;
+
+ bool ReadFPR() override;
+
+ bool WriteGPR() override;
+
+ bool WriteFPR() override;
+
+private:
+ lldb::addr_t m_pcb_addr;
+};
+
+#endif // LLDB_SOURCE_PLUGINS_PROCESS_FREEBSDKERNEL_REGISTERCONTEXTFREEBSDKERNEL_X86_64_H
Index: lldb/source/Plugins/Process/FreeBSDKernel/RegisterContextFreeBSDKernel_x86_64.cpp
===================================================================
--- /dev/null
+++ lldb/source/Plugins/Process/FreeBSDKernel/RegisterContextFreeBSDKernel_x86_64.cpp
@@ -0,0 +1,88 @@
+//===-- RegisterContextFreeBSDKernel_x86_64.cpp ---------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "RegisterContextFreeBSDKernel_x86_64.h"
+
+#include "lldb/Target/Process.h"
+#include "lldb/Target/Thread.h"
+#include "lldb/Utility/RegisterValue.h"
+#include "llvm/Support/Endian.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+RegisterContextFreeBSDKernel_x86_64::RegisterContextFreeBSDKernel_x86_64(
+ Thread &thread, RegisterInfoInterface *register_info, lldb::addr_t pcb_addr)
+ : RegisterContextPOSIX_x86(thread, 0, register_info), m_pcb_addr(pcb_addr) {
+}
+
+bool RegisterContextFreeBSDKernel_x86_64::ReadGPR() { return true; }
+
+bool RegisterContextFreeBSDKernel_x86_64::ReadFPR() { return true; }
+
+bool RegisterContextFreeBSDKernel_x86_64::WriteGPR() {
+ assert(0);
+ return false;
+}
+
+bool RegisterContextFreeBSDKernel_x86_64::WriteFPR() {
+ assert(0);
+ return false;
+}
+
+bool RegisterContextFreeBSDKernel_x86_64::ReadRegister(
+ const RegisterInfo *reg_info, RegisterValue &value) {
+ if (m_pcb_addr == LLDB_INVALID_ADDRESS)
+ return false;
+
+ struct {
+ llvm::support::ulittle64_t r15;
+ llvm::support::ulittle64_t r14;
+ llvm::support::ulittle64_t r13;
+ llvm::support::ulittle64_t r12;
+ llvm::support::ulittle64_t rbp;
+ llvm::support::ulittle64_t rsp;
+ llvm::support::ulittle64_t rbx;
+ llvm::support::ulittle64_t rip;
+ } pcb;
+
+ Status error;
+ size_t rd =
+ m_thread.GetProcess()->ReadMemory(m_pcb_addr, &pcb, sizeof(pcb), error);
+ if (rd != sizeof(pcb))
+ return false;
+
+ uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB];
+ switch (reg) {
+#define REG(x) \
+ case lldb_##x##_x86_64: \
+ value = pcb.x; \
+ break;
+
+ REG(r15);
+ REG(r14);
+ REG(r13);
+ REG(r12);
+ REG(rbp);
+ REG(rsp);
+ REG(rbx);
+ REG(rip);
+
+#undef REG
+
+ default:
+ return false;
+ }
+
+ return true;
+}
+
+bool RegisterContextFreeBSDKernel_x86_64::WriteRegister(
+ const RegisterInfo *reg_info, const RegisterValue &value) {
+ return false;
+}
Index: lldb/source/Plugins/Process/FreeBSDKernel/RegisterContextFreeBSDKernel_i386.h
===================================================================
--- /dev/null
+++ lldb/source/Plugins/Process/FreeBSDKernel/RegisterContextFreeBSDKernel_i386.h
@@ -0,0 +1,41 @@
+//===-- RegisterContextFreeBSDKernel_i386.h ---------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLDB_SOURCE_PLUGINS_PROCESS_FREEBSDKERNEL_REGISTERCONTEXTFREEBSDKERNEL_I386_H
+#define LLDB_SOURCE_PLUGINS_PROCESS_FREEBSDKERNEL_REGISTERCONTEXTFREEBSDKERNEL_I386_H
+
+#include "Plugins/Process/Utility/RegisterContextPOSIX_x86.h"
+#include "Plugins/Process/elf-core/RegisterUtilities.h"
+
+class RegisterContextFreeBSDKernel_i386 : public RegisterContextPOSIX_x86 {
+public:
+ RegisterContextFreeBSDKernel_i386(
+ lldb_private::Thread &thread,
+ lldb_private::RegisterInfoInterface *register_info,
+ lldb::addr_t pcb_addr);
+
+ bool ReadRegister(const lldb_private::RegisterInfo *reg_info,
+ lldb_private::RegisterValue &value) override;
+
+ bool WriteRegister(const lldb_private::RegisterInfo *reg_info,
+ const lldb_private::RegisterValue &value) override;
+
+protected:
+ bool ReadGPR() override;
+
+ bool ReadFPR() override;
+
+ bool WriteGPR() override;
+
+ bool WriteFPR() override;
+
+private:
+ lldb::addr_t m_pcb_addr;
+};
+
+#endif // LLDB_SOURCE_PLUGINS_PROCESS_FREEBSDKERNEL_REGISTERCONTEXTFREEBSDKERNEL_I386_H
Index: lldb/source/Plugins/Process/FreeBSDKernel/RegisterContextFreeBSDKernel_i386.cpp
===================================================================
--- /dev/null
+++ lldb/source/Plugins/Process/FreeBSDKernel/RegisterContextFreeBSDKernel_i386.cpp
@@ -0,0 +1,83 @@
+//===-- RegisterContextFreeBSDKernel_i386.cpp -----------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "RegisterContextFreeBSDKernel_i386.h"
+
+#include "lldb/Target/Process.h"
+#include "lldb/Target/Thread.h"
+#include "lldb/Utility/RegisterValue.h"
+#include "llvm/Support/Endian.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+RegisterContextFreeBSDKernel_i386::RegisterContextFreeBSDKernel_i386(
+ Thread &thread, RegisterInfoInterface *register_info, lldb::addr_t pcb_addr)
+ : RegisterContextPOSIX_x86(thread, 0, register_info), m_pcb_addr(pcb_addr) {
+}
+
+bool RegisterContextFreeBSDKernel_i386::ReadGPR() { return true; }
+
+bool RegisterContextFreeBSDKernel_i386::ReadFPR() { return true; }
+
+bool RegisterContextFreeBSDKernel_i386::WriteGPR() {
+ assert(0);
+ return false;
+}
+
+bool RegisterContextFreeBSDKernel_i386::WriteFPR() {
+ assert(0);
+ return false;
+}
+
+bool RegisterContextFreeBSDKernel_i386::ReadRegister(
+ const RegisterInfo *reg_info, RegisterValue &value) {
+ if (m_pcb_addr == LLDB_INVALID_ADDRESS)
+ return false;
+
+ struct {
+ llvm::support::ulittle32_t edi;
+ llvm::support::ulittle32_t esi;
+ llvm::support::ulittle32_t ebp;
+ llvm::support::ulittle32_t esp;
+ llvm::support::ulittle32_t ebx;
+ llvm::support::ulittle32_t eip;
+ } pcb;
+
+ Status error;
+ size_t rd =
+ m_thread.GetProcess()->ReadMemory(m_pcb_addr, &pcb, sizeof(pcb), error);
+ if (rd != sizeof(pcb))
+ return false;
+
+ uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB];
+ switch (reg) {
+#define REG(x) \
+ case lldb_##x##_i386: \
+ value = pcb.x; \
+ break;
+
+ REG(edi);
+ REG(esi);
+ REG(ebp);
+ REG(esp);
+ REG(eip);
+
+#undef REG
+
+ default:
+ return false;
+ }
+
+ return true;
+}
+
+bool RegisterContextFreeBSDKernel_i386::WriteRegister(
+ const RegisterInfo *reg_info, const RegisterValue &value) {
+ return false;
+}
Index: lldb/source/Plugins/Process/FreeBSDKernel/RegisterContextFreeBSDKernel_arm64.h
===================================================================
--- /dev/null
+++ lldb/source/Plugins/Process/FreeBSDKernel/RegisterContextFreeBSDKernel_arm64.h
@@ -0,0 +1,41 @@
+//===-- RegisterContextFreeBSDKernel_arm64.h --------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLDB_SOURCE_PLUGINS_PROCESS_FREEBSDKERNEL_REGISTERCONTEXTFREEBSDKERNEL_ARM64_H
+#define LLDB_SOURCE_PLUGINS_PROCESS_FREEBSDKERNEL_REGISTERCONTEXTFREEBSDKERNEL_ARM64_H
+
+#include "Plugins/Process/Utility/RegisterContextPOSIX_arm64.h"
+#include "Plugins/Process/elf-core/RegisterUtilities.h"
+
+class RegisterContextFreeBSDKernel_arm64 : public RegisterContextPOSIX_arm64 {
+public:
+ RegisterContextFreeBSDKernel_arm64(
+ lldb_private::Thread &thread,
+ std::unique_ptr<RegisterInfoPOSIX_arm64> register_info_up,
+ lldb::addr_t pcb_addr);
+
+ bool ReadRegister(const lldb_private::RegisterInfo *reg_info,
+ lldb_private::RegisterValue &value) override;
+
+ bool WriteRegister(const lldb_private::RegisterInfo *reg_info,
+ const lldb_private::RegisterValue &value) override;
+
+protected:
+ bool ReadGPR() override;
+
+ bool ReadFPR() override;
+
+ bool WriteGPR() override;
+
+ bool WriteFPR() override;
+
+private:
+ lldb::addr_t m_pcb_addr;
+};
+
+#endif // LLDB_SOURCE_PLUGINS_PROCESS_FREEBSDKERNEL_REGISTERCONTEXTFREEBSDKERNEL_ARM64_H
Index: lldb/source/Plugins/Process/FreeBSDKernel/RegisterContextFreeBSDKernel_arm64.cpp
===================================================================
--- /dev/null
+++ lldb/source/Plugins/Process/FreeBSDKernel/RegisterContextFreeBSDKernel_arm64.cpp
@@ -0,0 +1,110 @@
+//===-- RegisterContextFreeBSDKernel_arm64.cpp ----------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "RegisterContextFreeBSDKernel_arm64.h"
+#include "Plugins/Process/Utility/lldb-arm64-register-enums.h"
+
+#include "lldb/Target/Process.h"
+#include "lldb/Target/Thread.h"
+#include "lldb/Utility/RegisterValue.h"
+#include "llvm/Support/Endian.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+RegisterContextFreeBSDKernel_arm64::RegisterContextFreeBSDKernel_arm64(
+ Thread &thread, std::unique_ptr<RegisterInfoPOSIX_arm64> register_info_up,
+ lldb::addr_t pcb_addr)
+ : RegisterContextPOSIX_arm64(thread, std::move(register_info_up)),
+ m_pcb_addr(pcb_addr) {}
+
+bool RegisterContextFreeBSDKernel_arm64::ReadGPR() { return true; }
+
+bool RegisterContextFreeBSDKernel_arm64::ReadFPR() { return true; }
+
+bool RegisterContextFreeBSDKernel_arm64::WriteGPR() {
+ assert(0);
+ return false;
+}
+
+bool RegisterContextFreeBSDKernel_arm64::WriteFPR() {
+ assert(0);
+ return false;
+}
+
+bool RegisterContextFreeBSDKernel_arm64::ReadRegister(
+ const RegisterInfo *reg_info, RegisterValue &value) {
+ if (m_pcb_addr == LLDB_INVALID_ADDRESS)
+ return false;
+
+ struct {
+ llvm::support::ulittle64_t x[30];
+ llvm::support::ulittle64_t lr;
+ llvm::support::ulittle64_t _reserved;
+ llvm::support::ulittle64_t sp;
+ } pcb;
+
+ Status error;
+ size_t rd =
+ m_thread.GetProcess()->ReadMemory(m_pcb_addr, &pcb, sizeof(pcb), error);
+ if (rd != sizeof(pcb))
+ return false;
+
+ uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB];
+ switch (reg) {
+ case gpr_x0_arm64:
+ case gpr_x1_arm64:
+ case gpr_x2_arm64:
+ case gpr_x3_arm64:
+ case gpr_x4_arm64:
+ case gpr_x5_arm64:
+ case gpr_x6_arm64:
+ case gpr_x7_arm64:
+ case gpr_x8_arm64:
+ case gpr_x9_arm64:
+ case gpr_x10_arm64:
+ case gpr_x11_arm64:
+ case gpr_x12_arm64:
+ case gpr_x13_arm64:
+ case gpr_x14_arm64:
+ case gpr_x15_arm64:
+ case gpr_x16_arm64:
+ case gpr_x17_arm64:
+ case gpr_x18_arm64:
+ case gpr_x19_arm64:
+ case gpr_x20_arm64:
+ case gpr_x21_arm64:
+ case gpr_x22_arm64:
+ case gpr_x23_arm64:
+ case gpr_x24_arm64:
+ case gpr_x25_arm64:
+ case gpr_x26_arm64:
+ case gpr_x27_arm64:
+ case gpr_x28_arm64:
+ case gpr_fp_arm64:
+ static_assert(gpr_fp_arm64 - gpr_x0_arm64 == 29,
+ "nonconsecutive arm64 register numbers");
+ value = pcb.x[reg - gpr_x0_arm64];
+ break;
+ case gpr_sp_arm64:
+ value = pcb.sp;
+ break;
+ case gpr_pc_arm64:
+ // The pc of crashing thread is stored in lr.
+ value = pcb.lr;
+ break;
+ default:
+ return false;
+ }
+ return true;
+}
+
+bool RegisterContextFreeBSDKernel_arm64::WriteRegister(
+ const RegisterInfo *reg_info, const RegisterValue &value) {
+ return false;
+}
Index: lldb/source/Plugins/Process/FreeBSDKernel/ProcessFreeBSDKernel.h
===================================================================
--- /dev/null
+++ lldb/source/Plugins/Process/FreeBSDKernel/ProcessFreeBSDKernel.h
@@ -0,0 +1,60 @@
+//===-- ProcessFreeBSDKernel.h ----------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLDB_SOURCE_PLUGINS_PROCESS_FREEBSDKERNEL_PROCESSFREEBSDKERNEL_H
+#define LLDB_SOURCE_PLUGINS_PROCESS_FREEBSDKERNEL_PROCESSFREEBSDKERNEL_H
+
+#include "lldb/Target/PostMortemProcess.h"
+
+class ProcessFreeBSDKernel : public lldb_private::PostMortemProcess {
+public:
+ ProcessFreeBSDKernel(lldb::TargetSP target_sp, lldb::ListenerSP listener,
+ const lldb_private::FileSpec &core_file, void *fvc);
+
+ ~ProcessFreeBSDKernel() override;
+
+ static lldb::ProcessSP
+ CreateInstance(lldb::TargetSP target_sp, lldb::ListenerSP listener,
+ const lldb_private::FileSpec *crash_file_path,
+ bool can_connect);
+
+ static void Initialize();
+
+ static void Terminate();
+
+ static llvm::StringRef GetPluginNameStatic() { return "freebsd-kernel"; }
+
+ static llvm::StringRef GetPluginDescriptionStatic() {
+ return "FreeBSD kernel vmcore debugging plug-in.";
+ }
+
+ llvm::StringRef GetPluginName() override { return GetPluginNameStatic(); }
+
+ lldb_private::Status DoDestroy() override;
+
+ bool CanDebug(lldb::TargetSP target_sp,
+ bool plugin_specified_by_name) override;
+
+ void RefreshStateAfterStop() override;
+
+ lldb_private::Status DoLoadCore() override;
+
+ size_t DoReadMemory(lldb::addr_t addr, void *buf, size_t size,
+ lldb_private::Status &error) override;
+
+ lldb_private::DynamicLoader *GetDynamicLoader() override;
+
+protected:
+ bool DoUpdateThreadList(lldb_private::ThreadList &old_thread_list,
+ lldb_private::ThreadList &new_thread_list) override;
+
+private:
+ void *m_fvc;
+};
+
+#endif // LLDB_SOURCE_PLUGINS_PROCESS_FREEBSDKERNEL_PROCESSFREEBSDKERNEL_H
Index: lldb/source/Plugins/Process/FreeBSDKernel/ProcessFreeBSDKernel.cpp
===================================================================
--- /dev/null
+++ lldb/source/Plugins/Process/FreeBSDKernel/ProcessFreeBSDKernel.cpp
@@ -0,0 +1,126 @@
+//===-- ProcessFreeBSDKernel.cpp ------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/Core/Module.h"
+#include "lldb/Core/PluginManager.h"
+#include "lldb/Target/DynamicLoader.h"
+
+#include "ProcessFreeBSDKernel.h"
+#include "ThreadFreeBSDKernel.h"
+#include "Plugins/DynamicLoader/Static/DynamicLoaderStatic.h"
+
+#include <fvc.h>
+
+using namespace lldb;
+using namespace lldb_private;
+
+LLDB_PLUGIN_DEFINE(ProcessFreeBSDKernel)
+
+ProcessFreeBSDKernel::ProcessFreeBSDKernel(lldb::TargetSP target_sp,
+ ListenerSP listener_sp,
+ const FileSpec &core_file, void *fvc)
+ : PostMortemProcess(target_sp, listener_sp), m_fvc(fvc) {}
+
+ProcessFreeBSDKernel::~ProcessFreeBSDKernel() {
+ if (m_fvc)
+ fvc_close(static_cast<fvc_t *>(m_fvc));
+}
+
+lldb::ProcessSP ProcessFreeBSDKernel::CreateInstance(lldb::TargetSP target_sp,
+ ListenerSP listener_sp,
+ const FileSpec *crash_file,
+ bool can_connect) {
+ lldb::ProcessSP process_sp;
+ ModuleSP executable = target_sp->GetExecutableModule();
+ if (crash_file && !can_connect && executable) {
+ fvc_t *fvc = fvc_open(
+ executable->GetFileSpec().GetPath().c_str(),
+ crash_file->GetPath().c_str(), nullptr, nullptr, nullptr);
+ if (fvc)
+ process_sp = std::make_shared<ProcessFreeBSDKernel>(
+ target_sp, listener_sp, *crash_file, fvc);
+ }
+ return process_sp;
+}
+
+void ProcessFreeBSDKernel::Initialize() {
+ static llvm::once_flag g_once_flag;
+
+ llvm::call_once(g_once_flag, []() {
+ PluginManager::RegisterPlugin(GetPluginNameStatic(),
+ GetPluginDescriptionStatic(), CreateInstance);
+ });
+}
+
+void ProcessFreeBSDKernel::Terminate() {
+ PluginManager::UnregisterPlugin(ProcessFreeBSDKernel::CreateInstance);
+}
+
+Status ProcessFreeBSDKernel::DoDestroy() { return Status(); }
+
+bool ProcessFreeBSDKernel::CanDebug(lldb::TargetSP target_sp,
+ bool plugin_specified_by_name) {
+ return true;
+}
+
+void ProcessFreeBSDKernel::RefreshStateAfterStop() {}
+
+bool ProcessFreeBSDKernel::DoUpdateThreadList(ThreadList &old_thread_list,
+ ThreadList &new_thread_list) {
+ if (old_thread_list.GetSize(false) == 0) {
+ // Make up the thread the first time this is called so we can set our one
+ // and only core thread state up.
+
+ // We cannot construct a thread without a register context as that crashes
+ // LLDB but we can construct a process without threads to provide minimal
+ // memory reading support.
+ switch (GetTarget().GetArchitecture().GetMachine()) {
+ case llvm::Triple::aarch64:
+ case llvm::Triple::x86:
+ case llvm::Triple::x86_64:
+ break;
+ default:
+ return false;
+ }
+
+ const Symbol *pcb_sym =
+ GetTarget().GetExecutableModule()->FindFirstSymbolWithNameAndType(
+ ConstString("dumppcb"));
+ ThreadSP thread_sp(new ThreadFreeBSDKernel(
+ *this, 1, pcb_sym ? pcb_sym->GetFileAddress() : LLDB_INVALID_ADDRESS));
+ new_thread_list.AddThread(thread_sp);
+ } else {
+ const uint32_t num_threads = old_thread_list.GetSize(false);
+ for (uint32_t i = 0; i < num_threads; ++i)
+ new_thread_list.AddThread(old_thread_list.GetThreadAtIndex(i, false));
+ }
+ return new_thread_list.GetSize(false) > 0;
+}
+
+Status ProcessFreeBSDKernel::DoLoadCore() {
+ // The core is already loaded by CreateInstance().
+ return Status();
+}
+
+size_t ProcessFreeBSDKernel::DoReadMemory(lldb::addr_t addr, void *buf,
+ size_t size, Status &error) {
+ ssize_t rd = fvc_read(static_cast<fvc_t *>(m_fvc), addr, buf, size);
+ if (rd < 0 || static_cast<size_t>(rd) != size) {
+ error.SetErrorStringWithFormat("Reading memory failed: %s",
+ fvc_geterr(static_cast<fvc_t *>(m_fvc)));
+ return rd > 0 ? rd : 0;
+ }
+ return rd;
+}
+
+DynamicLoader *ProcessFreeBSDKernel::GetDynamicLoader() {
+ if (m_dyld_up.get() == nullptr)
+ m_dyld_up.reset(DynamicLoader::FindPlugin(
+ this, DynamicLoaderStatic::GetPluginNameStatic()));
+ return m_dyld_up.get();
+}
Index: lldb/source/Plugins/Process/FreeBSDKernel/CMakeLists.txt
===================================================================
--- /dev/null
+++ lldb/source/Plugins/Process/FreeBSDKernel/CMakeLists.txt
@@ -0,0 +1,19 @@
+if (NOT FBSDVMCore_FOUND)
+ message(STATUS "Skipping FreeBSDKernel plugin due to missing libfbsdvmcore")
+ return()
+endif()
+
+add_lldb_library(lldbPluginProcessFreeBSDKernel PLUGIN
+ ProcessFreeBSDKernel.cpp
+ RegisterContextFreeBSDKernel_arm64.cpp
+ RegisterContextFreeBSDKernel_i386.cpp
+ RegisterContextFreeBSDKernel_x86_64.cpp
+ ThreadFreeBSDKernel.cpp
+
+ LINK_LIBS
+ lldbCore
+ lldbTarget
+ fbsdvmcore
+ LINK_COMPONENTS
+ Support
+ )
Index: lldb/source/Plugins/Process/CMakeLists.txt
===================================================================
--- lldb/source/Plugins/Process/CMakeLists.txt
+++ lldb/source/Plugins/Process/CMakeLists.txt
@@ -18,3 +18,4 @@
add_subdirectory(elf-core)
add_subdirectory(mach-core)
add_subdirectory(minidump)
+add_subdirectory(FreeBSDKernel)
Index: lldb/packages/Python/lldbsuite/test/lldbtest.py
===================================================================
--- lldb/packages/Python/lldbsuite/test/lldbtest.py
+++ lldb/packages/Python/lldbsuite/test/lldbtest.py
@@ -1570,7 +1570,7 @@
return os.environ["CC"]
- def yaml2obj(self, yaml_path, obj_path):
+ def yaml2obj(self, yaml_path, obj_path, max_size=None):
"""
Create an object file at the given path from a yaml file.
@@ -1580,6 +1580,8 @@
if not yaml2obj_bin:
self.assertTrue(False, "No valid yaml2obj executable specified")
command = [yaml2obj_bin, "-o=%s" % obj_path, yaml_path]
+ if max_size is not None:
+ command += ["--max-size=%d" % max_size]
self.runBuildCommand(command)
def getBuildFlags(
Index: lldb/cmake/modules/LLDBConfig.cmake
===================================================================
--- lldb/cmake/modules/LLDBConfig.cmake
+++ lldb/cmake/modules/LLDBConfig.cmake
@@ -58,6 +58,7 @@
add_optional_dependency(LLDB_ENABLE_LUA "Enable Lua scripting support in LLDB" LuaAndSwig LUAANDSWIG_FOUND)
add_optional_dependency(LLDB_ENABLE_PYTHON "Enable Python scripting support in LLDB" PythonAndSwig PYTHONANDSWIG_FOUND)
add_optional_dependency(LLDB_ENABLE_LIBXML2 "Enable Libxml 2 support in LLDB" LibXml2 LIBXML2_FOUND VERSION 2.8)
+add_optional_dependency(LLDB_ENABLE_FBSDVMCORE "Enable libfbsdvmcore support in LLDB" FBSDVMCore FBSDVMCORE_FOUND)
option(LLDB_USE_SYSTEM_SIX "Use six.py shipped with system and do not install a copy of it" OFF)
option(LLDB_USE_ENTITLEMENTS "When codesigning, use entitlements if available" ON)
_______________________________________________
lldb-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits