This revision was landed with ongoing or failed builds.
This revision was automatically updated to reflect the committed changes.
mgorny marked an inline comment as done.
Closed by commit rG9b1d27b2fa72: [lldb] [Process/FreeBSDKernel] Support finding 
all processes (authored by mgorny).
Herald added a project: LLDB.

Changed prior to commit:
  https://reviews.llvm.org/D116255?vs=396789&id=397968#toc

Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D116255/new/

https://reviews.llvm.org/D116255

Files:
  lldb/source/Plugins/Process/FreeBSDKernel/ProcessFreeBSDKernel.cpp
  lldb/source/Plugins/Process/FreeBSDKernel/ProcessFreeBSDKernel.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-hacks.patch
  
lldb/test/API/functionalities/postmortem/FreeBSDKernel/tools/libfbsdvmcore-print-offsets.patch
  
lldb/test/API/functionalities/postmortem/FreeBSDKernel/tools/lldb-minimize-processes.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
===================================================================
--- lldb/test/API/functionalities/postmortem/FreeBSDKernel/tools/test.script
+++ lldb/test/API/functionalities/postmortem/FreeBSDKernel/tools/test.script
@@ -1,5 +1,11 @@
 thread list
-register read pc
+register read --all
+bt
+thread select 2
+register read --all
+bt
+thread select 3
+register read --all
 bt
 p *(int*)&hz
 memory read &hz
Index: lldb/test/API/functionalities/postmortem/FreeBSDKernel/tools/lldb-minimize-processes.patch
===================================================================
--- /dev/null
+++ lldb/test/API/functionalities/postmortem/FreeBSDKernel/tools/lldb-minimize-processes.patch
@@ -0,0 +1,85 @@
+diff --git a/lldb/source/Plugins/Process/FreeBSDKernel/ProcessFreeBSDKernel.cpp b/lldb/source/Plugins/Process/FreeBSDKernel/ProcessFreeBSDKernel.cpp
+index e3707365a9c3..c4a9c82f3c63 100644
+--- a/lldb/source/Plugins/Process/FreeBSDKernel/ProcessFreeBSDKernel.cpp
++++ b/lldb/source/Plugins/Process/FreeBSDKernel/ProcessFreeBSDKernel.cpp
+@@ -38,6 +38,8 @@ public:
+ 
+   size_t DoReadMemory(lldb::addr_t addr, void *buf, size_t size,
+                       lldb_private::Status &error) override;
++  size_t DoWriteMemory(lldb::addr_t vm_addr, const void *buf,
++                       size_t size, Status &error) override;
+ 
+ private:
+   fvc_t *m_fvc;
+@@ -185,6 +187,7 @@ bool ProcessFreeBSDKernel::DoUpdateThreadList(ThreadList &old_thread_list,
+     // iterate through a linked list of all processes
+     // allproc is a pointer to the first list element, p_list field
+     // (found at offset_p_list) specifies the next element
++    lldb::addr_t prev = 0;
+     for (lldb::addr_t proc =
+              ReadPointerFromMemory(FindSymbol("allproc"), error);
+          proc != 0 && proc != LLDB_INVALID_ADDRESS;
+@@ -195,6 +198,8 @@ bool ProcessFreeBSDKernel::DoUpdateThreadList(ThreadList &old_thread_list,
+       char comm[fbsd_maxcomlen + 1];
+       ReadCStringFromMemory(proc + offset_p_comm, comm, sizeof(comm), error);
+ 
++      bool interesting = false;
++
+       // iterate through a linked list of all process' threads
+       // the initial thread is found in process' p_threads, subsequent
+       // elements are linked via td_plist field
+@@ -231,6 +236,7 @@ bool ProcessFreeBSDKernel::DoUpdateThreadList(ThreadList &old_thread_list,
+           // NB: dumppcb can be LLDB_INVALID_ADDRESS if reading it failed
+           pcb_addr = dumppcb;
+           thread_desc += " (crashed)";
++          interesting = true;
+         } else if (oncpu != -1) {
+           // if we managed to read stoppcbs and pcb_size, use them to find
+           // the correct PCB
+@@ -239,13 +245,27 @@ bool ProcessFreeBSDKernel::DoUpdateThreadList(ThreadList &old_thread_list,
+           else
+             pcb_addr = LLDB_INVALID_ADDRESS;
+           thread_desc += llvm::formatv(" (on CPU {0})", oncpu);
++          interesting = true;
+         }
+ 
+         ThreadSP thread_sp{
+             new ThreadFreeBSDKernel(*this, tid, pcb_addr, thread_desc)};
+         new_thread_list.AddThread(thread_sp);
+       }
++
++      if (interesting) {
++        printf("pid %d is interesting\n", pid);
++        if (prev != 0) {
++          printf("will link %d to %d\n", prev, proc);
++          if (!WritePointerToMemory(prev + offset_p_list, proc, error))
++            assert(0 && "write failed");
++        }
++        prev = proc;
++      }
+     }
++    printf("last: %d\n", prev);
++    if (!WritePointerToMemory(prev + offset_p_list, 0, error))
++      assert(0 && "write failed");
+   } else {
+     const uint32_t num_threads = old_thread_list.GetSize(false);
+     for (uint32_t i = 0; i < num_threads; ++i)
+@@ -295,6 +315,18 @@ size_t ProcessFreeBSDKernelFVC::DoReadMemory(lldb::addr_t addr, void *buf,
+   return rd;
+ }
+ 
++size_t ProcessFreeBSDKernelFVC::DoWriteMemory(lldb::addr_t vm_addr, const void *buf,
++                       size_t size, Status &error) {
++  ssize_t rd = 0;
++  rd = fvc_write(m_fvc, vm_addr, buf, size);
++  printf("fvc_write(%p, %p, %d) -> %d\n", vm_addr, buf, size, rd);
++  if (rd < 0 || static_cast<size_t>(rd) != size) {
++    error.SetErrorStringWithFormat("Writing memory failed: %s", GetError());
++    return rd > 0 ? rd : 0;
++  }
++  return rd;
++}
++
+ const char *ProcessFreeBSDKernelFVC::GetError() { return fvc_geterr(m_fvc); }
+ 
+ #endif // LLDB_ENABLE_FBSDVMCORE
Index: lldb/test/API/functionalities/postmortem/FreeBSDKernel/tools/libfbsdvmcore-hacks.patch
===================================================================
--- lldb/test/API/functionalities/postmortem/FreeBSDKernel/tools/libfbsdvmcore-hacks.patch
+++ lldb/test/API/functionalities/postmortem/FreeBSDKernel/tools/libfbsdvmcore-hacks.patch
@@ -1,16 +1,77 @@
+diff --git a/CMakeLists.txt b/CMakeLists.txt
+index 53b401a..ccb289e 100644
+--- a/CMakeLists.txt
++++ b/CMakeLists.txt
+@@ -94,6 +94,7 @@ install(
+     man/fvc_kerndisp.3
+     man/fvc_open.3
+     man/fvc_read.3
++    man/fvc_write.3
+     DESTINATION "${CMAKE_INSTALL_MANDIR}/man3")
+ 
+ install(
 diff --git a/lib/fvc.c b/lib/fvc.c
-index e6b96c1..4033f78 100644
+index e6b96c1..cac7158 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)
+@@ -154,7 +154,7 @@ _fvc_open(fvc_t *kd, const char *uf, const char *mf, char *errout)
+ 		goto failed;
+ 	}
+ 
+-	if ((kd->pmfd = open(mf, O_RDONLY | O_CLOEXEC, 0)) < 0) {
++	if ((kd->pmfd = open(mf, O_RDWR | O_CLOEXEC, 0)) < 0) {
+ 		_fvc_syserr(kd, kd->program, "%s", mf);
+ 		goto failed;
+ 	}
+@@ -297,6 +297,47 @@ 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
++		 * core file in which case the read will return 0 (EOF).
++		 */
++		if (cr == 0)
++			break;
++		cp += cr;
++		kva += cr;
++		len -= cr;
++	}
++
++	return (cp - (char *)buf);
++}
++
++ssize_t
++fvc_write(fvc_t *kd, fvc_addr_t kva, const void *buf, size_t len)
++{
++	int cc;
++	ssize_t cr;
++	off_t pa;
++	const char *cp;
++
++	cp = buf;
++	while (len > 0) {
++		cc = kd->arch->ka_kvatop(kd, kva, &pa);
++		if (cc == 0)
++			return (-1);
++		if (cc > (ssize_t)len)
++			cc = len;
++		errno = 0;
++		if (lseek(kd->pmfd, pa, 0) == -1 && errno != 0) {
++			_fvc_syserr(kd, 0, _PATH_MEM);
++			break;
++		}
++		cr = write(kd->pmfd, cp, cc);
++		if (cr < 0) {
++			_fvc_syserr(kd, kd->program, "fvc_write");
++			break;
++		}
  		/*
  		 * 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)
+@@ -331,3 +372,8 @@ fvc_kerndisp(fvc_t *kd)
  
  	return (kd->arch->ka_kerndisp(kd));
  }
@@ -20,7 +81,7 @@
 +	return pread(fd, buf, count, offset);
 +}
 diff --git a/lib/fvc.h b/lib/fvc.h
-index 8680079..ff1e0f0 100644
+index 8680079..8cff17c 100644
 --- a/lib/fvc.h
 +++ b/lib/fvc.h
 @@ -54,6 +54,8 @@ typedef unsigned char fvc_vm_prot_t;
@@ -32,6 +93,14 @@
  struct fvc_page {
  	unsigned int	kp_version;
  	fvc_addr_t	kp_paddr;
+@@ -76,6 +78,7 @@ fvc_t	 *fvc_open
+ 	    (const char *, const char *, char *,
+ 	    int (*)(const char *, fvc_addr_t *, void *), void *);
+ ssize_t	  fvc_read(fvc_t *, fvc_addr_t, void *, size_t);
++ssize_t	  fvc_write(fvc_t *, fvc_addr_t, const void *, size_t);
+ ssize_t   fvc_kerndisp(fvc_t *);
+ 
+ typedef int fvc_walk_pages_cb_t(struct fvc_page *, void *);
 diff --git a/lib/fvc_amd64.c b/lib/fvc_amd64.c
 index 4d27998..69f1807 100644
 --- a/lib/fvc_amd64.c
@@ -164,3 +233,91 @@
  	if (rd < 0 || rd != (ssize_t)map_len) {
  		_fvc_err(kd, kd->program, "cannot read %zu bytes for bitmap",
  		    map_len);
+diff --git a/man/fbsdvmcore.3 b/man/fbsdvmcore.3
+index 4285ba2..c0d760c 100644
+--- a/man/fbsdvmcore.3
++++ b/man/fbsdvmcore.3
+@@ -89,4 +89,5 @@ etc.
+ .Xr fvc_geterr 3 ,
+ .Xr fvc_kerndisp 3 ,
+ .Xr fvc_open 3 ,
+-.Xr fvc_read 3
++.Xr fvc_read 3 ,
++.Xr fvc_write 3
+diff --git a/man/fvc_geterr.3 b/man/fvc_geterr.3
+index 964a097..7d74c25 100644
+--- a/man/fvc_geterr.3
++++ b/man/fvc_geterr.3
+@@ -66,7 +66,8 @@ or an error has not been captured for
+ .Sh SEE ALSO
+ .Xr fvc 3 ,
+ .Xr fvc_close 3 ,
+-.Xr fvc_read 3
++.Xr fvc_read 3 ,
++.Xr fvc_write 3
+ .Sh BUGS
+ This routine cannot be used to access error conditions due to a failed
+ .Fn fvc_open
+diff --git a/man/fvc_open.3 b/man/fvc_open.3
+index 1f8e3be..4ea93ed 100644
+--- a/man/fvc_open.3
++++ b/man/fvc_open.3
+@@ -166,5 +166,6 @@ was
+ .Xr fvc_geterr 3 ,
+ .Xr fvc_native 3 ,
+ .Xr fvc_read 3 ,
++.Xr fvc_write 3 ,
+ .Xr kmem 4 ,
+ .Xr mem 4
+diff --git a/man/fvc_read.3 b/man/fvc_read.3
+index 7413d59..c18dadc 100644
+--- a/man/fvc_read.3
++++ b/man/fvc_read.3
+@@ -36,18 +36,24 @@
+ .Dt FVC_READ 3
+ .Os
+ .Sh NAME
+-.Nm fvc_read
+-.Nd read kernel virtual memory
++.Nm fvc_read ,
++.Nm fvc_write
++.Nd read or write kernel virtual memory
+ .Sh LIBRARY
+ .Lb libfbsdvmcore
+ .Sh SYNOPSIS
+ .In fvc.h
+ .Ft ssize_t
+ .Fn fvc_read "fvc_t *kd" "kvaddr_t addr" "void *buf" "size_t nbytes"
++.Ft ssize_t
++.Fn fvc_write "fvc_t *kd" "kvaddr_t addr" "void *buf" "size_t nbytes"
+ .Sh DESCRIPTION
+ The
+ .Fn fvc_read
+ function is used to read a crash dump file.
++.Fn fvc_write
++function is used to overwrite parts of a crash dump file.
++Note that only the fragments already present can be written.
+ See
+ .Fn fvc_open 3
+ for information regarding opening kernel crash dumps.
+@@ -63,6 +69,13 @@ to
+ .Fa buf .
+ .Pp
+ The
++.Fn fvc_write
++function transfers
++.Fa nbytes
++bytes of data from
++.Fa buf
++to the kernel space address
++.Fa addr .
+ .Sh RETURN VALUES
+ Upon success, the number of bytes actually transferred is returned.
+ Otherwise, -1 is returned.
+diff --git a/man/fvc_write.3 b/man/fvc_write.3
+new file mode 100644
+index 0000000..f25fc74
+--- /dev/null
++++ b/man/fvc_write.3
+@@ -0,0 +1 @@
++.so man3/fvc_read.3
Index: lldb/test/API/functionalities/postmortem/FreeBSDKernel/tools/copy-sparse.py
===================================================================
--- lldb/test/API/functionalities/postmortem/FreeBSDKernel/tools/copy-sparse.py
+++ lldb/test/API/functionalities/postmortem/FreeBSDKernel/tools/copy-sparse.py
@@ -23,6 +23,8 @@
 
     for l in sys.stdin:
         m = line_re.match(l)
+        if m is None:
+            continue
         offset, size = [int(x) for x in m.groups()]
 
         inf.seek(offset)
Index: lldb/test/API/functionalities/postmortem/FreeBSDKernel/tools/README.rst
===================================================================
--- lldb/test/API/functionalities/postmortem/FreeBSDKernel/tools/README.rst
+++ lldb/test/API/functionalities/postmortem/FreeBSDKernel/tools/README.rst
@@ -12,22 +12,31 @@
 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.
+3. Patch libfbsdvmcore using ``libfbsdvmcore-hacks.patch`` and build LLDB
+   against the patched library.
 
-4. Do a test run of ``test.script`` in LLDB against the kernel + vmcore::
+4. Patch LLDB using ``lldb-minimize-processes.patch`` and build it.
+
+   WARNING: LLDB will now modify core files in order to make the resulting
+   test vmcores smaller.  Make a backup if necessary.
+
+5. 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.
+   ``%RD`` lines.  The vmcore will also be modified to shorten the process
+   list in ``allproc``.
+
+6. Open the vmcore in the patched LLDB again and choose interesting threads
+   for testing.  Update thread numbers in ``test.script`` if necessary.
 
-5. Use the ``copy-sparse.py`` tool to create a sparse version of the vmcore::
+7. 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``::
+8. Compress the sparse vmcore file using ``bzip2``::
 
        bzip2 -9 vmcore.sparse
 
Index: lldb/test/API/functionalities/postmortem/FreeBSDKernel/kernel-i386.yaml
===================================================================
--- lldb/test/API/functionalities/postmortem/FreeBSDKernel/kernel-i386.yaml
+++ lldb/test/API/functionalities/postmortem/FreeBSDKernel/kernel-i386.yaml
@@ -14,6 +14,12 @@
     AddressAlign:    0x80
     Offset:          0x12B7AB0
     Size:            0x2D48D8
+  - Name:            .rodata
+    Type:            SHT_PROGBITS
+    Flags:           [ SHF_ALLOC, SHF_MERGE, SHF_STRINGS ]
+    Address:         0x1400290
+    AddressAlign:    0x10
+    Size:            0x800
 Symbols:
   - Name:            kernbase
     Index:           SHN_ABS
@@ -36,3 +42,87 @@
     Binding:         STB_GLOBAL
     Value:           0x1D8B044
     Size:            0x4
+  - Name:            proc_off_p_comm
+    Type:            STT_OBJECT
+    Section:         .rodata
+    Binding:         STB_GLOBAL
+    Value:           0x1809ABC
+    Size:            0x4
+  - Name:            proc_off_p_hash
+    Type:            STT_OBJECT
+    Section:         .rodata
+    Binding:         STB_GLOBAL
+    Value:           0x1809AC4
+    Size:            0x4
+  - Name:            proc_off_p_list
+    Type:            STT_OBJECT
+    Section:         .rodata
+    Binding:         STB_GLOBAL
+    Value:           0x1809AC0
+    Size:            0x4
+  - Name:            proc_off_p_pid
+    Type:            STT_OBJECT
+    Section:         .rodata
+    Binding:         STB_GLOBAL
+    Value:           0x1809AB8
+    Size:            0x4
+  - Name:            proc_off_p_threads
+    Type:            STT_OBJECT
+    Section:         .rodata
+    Binding:         STB_GLOBAL
+    Value:           0x1809AC8
+    Size:            0x4
+  - Name:            thread_off_td_name
+    Type:            STT_OBJECT
+    Section:         .rodata
+    Binding:         STB_GLOBAL
+    Value:           0x1809AD0
+    Size:            0x4
+  - Name:            thread_off_td_oncpu
+    Type:            STT_OBJECT
+    Section:         .rodata
+    Binding:         STB_GLOBAL
+    Value:           0x1809AD4
+    Size:            0x4
+  - Name:            thread_off_td_pcb
+    Type:            STT_OBJECT
+    Section:         .rodata
+    Binding:         STB_GLOBAL
+    Value:           0x1809AD8
+    Size:            0x4
+  - Name:            thread_off_td_plist
+    Type:            STT_OBJECT
+    Section:         .rodata
+    Binding:         STB_GLOBAL
+    Value:           0x1809ADC
+    Size:            0x4
+  - Name:            thread_off_td_tid
+    Type:            STT_OBJECT
+    Section:         .rodata
+    Binding:         STB_GLOBAL
+    Value:           0x1809ACC
+    Size:            0x4
+  - Name:            dumptid
+    Type:            STT_OBJECT
+    Section:         .bss
+    Binding:         STB_GLOBAL
+    Value:           0x1D2DA60
+    Size:            0x4
+  - Name:            pcb_size
+    Type:            STT_OBJECT
+    Section:         .rodata
+    Binding:         STB_GLOBAL
+    Value:           0x1809A74
+    Size:            0x4
+  - Name:            stoppcbs
+    Type:            STT_OBJECT
+    Section:         .bss
+    Binding:         STB_GLOBAL
+    Value:           0x1D651A4
+    Size:            0x1800
+  - Name:            allproc
+    Type:            STT_OBJECT
+    Section:         .bss
+    Binding:         STB_GLOBAL
+    Value:           0x1D21540
+    Size:            0x4
Index: lldb/test/API/functionalities/postmortem/FreeBSDKernel/kernel-arm64.yaml
===================================================================
--- lldb/test/API/functionalities/postmortem/FreeBSDKernel/kernel-arm64.yaml
+++ lldb/test/API/functionalities/postmortem/FreeBSDKernel/kernel-arm64.yaml
@@ -12,6 +12,12 @@
     Address:         0xFFFF000000C35000
     AddressAlign:    0x1000
     Size:            0x37F000
+  - Name:            .rodata
+    Type:            SHT_PROGBITS
+    Flags:           [ SHF_ALLOC, SHF_MERGE, SHF_STRINGS ]
+    Address:         0xFFFF0000008A72C0
+    AddressAlign:    0x20
+    Size:            0x1000
 Symbols:
   - Name:            kernbase
     Index:           SHN_ABS
@@ -28,3 +34,87 @@
     Binding:         STB_GLOBAL
     Value:           0xFFFF000000E2651C
     Size:            0x4
+  - Name:            proc_off_p_comm
+    Type:            STT_OBJECT
+    Section:         .rodata
+    Binding:         STB_GLOBAL
+    Value:           0xFFFF00000096BC30
+    Size:            0x4
+  - Name:            proc_off_p_hash
+    Type:            STT_OBJECT
+    Section:         .rodata
+    Binding:         STB_GLOBAL
+    Value:           0xFFFF00000096BC38
+    Size:            0x4
+  - Name:            proc_off_p_list
+    Type:            STT_OBJECT
+    Section:         .rodata
+    Binding:         STB_GLOBAL
+    Value:           0xFFFF00000096BC34
+    Size:            0x4
+  - Name:            proc_off_p_pid
+    Type:            STT_OBJECT
+    Section:         .rodata
+    Binding:         STB_GLOBAL
+    Value:           0xFFFF00000096BC2C
+    Size:            0x4
+  - Name:            proc_off_p_threads
+    Type:            STT_OBJECT
+    Section:         .rodata
+    Binding:         STB_GLOBAL
+    Value:           0xFFFF00000096BC3C
+    Size:            0x4
+  - Name:            thread_off_td_name
+    Type:            STT_OBJECT
+    Section:         .rodata
+    Binding:         STB_GLOBAL
+    Value:           0xFFFF00000096BC44
+    Size:            0x4
+  - Name:            thread_off_td_oncpu
+    Type:            STT_OBJECT
+    Section:         .rodata
+    Binding:         STB_GLOBAL
+    Value:           0xFFFF00000096BC48
+    Size:            0x4
+  - Name:            thread_off_td_pcb
+    Type:            STT_OBJECT
+    Section:         .rodata
+    Binding:         STB_GLOBAL
+    Value:           0xFFFF00000096BC4C
+    Size:            0x4
+  - Name:            thread_off_td_plist
+    Type:            STT_OBJECT
+    Section:         .rodata
+    Binding:         STB_GLOBAL
+    Value:           0xFFFF00000096BC50
+    Size:            0x4
+  - Name:            thread_off_td_tid
+    Type:            STT_OBJECT
+    Section:         .rodata
+    Binding:         STB_GLOBAL
+    Value:           0xFFFF00000096BC40
+    Size:            0x4
+  - Name:            dumptid
+    Type:            STT_OBJECT
+    Section:         .bss
+    Binding:         STB_GLOBAL
+    Value:           0xFFFF000000DF3CF0
+    Size:            0x4
+  - Name:            pcb_size
+    Type:            STT_OBJECT
+    Section:         .rodata
+    Binding:         STB_GLOBAL
+    Value:           0xFFFF00000096BC0C
+    Size:            0x4
+  - Name:            stoppcbs
+    Type:            STT_OBJECT
+    Section:         .bss
+    Binding:         STB_GLOBAL
+    Value:           0xFFFF000000E8F640
+    Size:            0x56000
+  - Name:            allproc
+    Type:            STT_OBJECT
+    Section:         .bss
+    Binding:         STB_GLOBAL
+    Value:           0xFFFF000000DE7230
+    Size:            0x8
Index: lldb/test/API/functionalities/postmortem/FreeBSDKernel/kernel-amd64.yaml
===================================================================
--- lldb/test/API/functionalities/postmortem/FreeBSDKernel/kernel-amd64.yaml
+++ lldb/test/API/functionalities/postmortem/FreeBSDKernel/kernel-amd64.yaml
@@ -14,6 +14,12 @@
     AddressAlign:    0x80
     Offset:          0x17BA348
     Size:            0x445C80
+  - Name:            .rodata
+    Type:            SHT_PROGBITS
+    Flags:           [ SHF_ALLOC, SHF_MERGE, SHF_STRINGS ]
+    Address:         0xFFFFFFFF81152D30
+    AddressAlign:    0x10
+    Size:            0x800
 Symbols:
   - Name:            kernbase
     Index:           SHN_ABS
@@ -36,3 +42,87 @@
     Binding:         STB_GLOBAL
     Value:           0xFFFFFFFF81CD4C0C
     Size:            0x4
+  - Name:            proc_off_p_comm
+    Type:            STT_OBJECT
+    Section:         .rodata
+    Binding:         STB_GLOBAL
+    Value:           0xFFFFFFFF815CA624
+    Size:            0x4
+  - Name:            proc_off_p_hash
+    Type:            STT_OBJECT
+    Section:         .rodata
+    Binding:         STB_GLOBAL
+    Value:           0xFFFFFFFF815CA62C
+    Size:            0x4
+  - Name:            proc_off_p_list
+    Type:            STT_OBJECT
+    Section:         .rodata
+    Binding:         STB_GLOBAL
+    Value:           0xFFFFFFFF815CA628
+    Size:            0x4
+  - Name:            proc_off_p_pid
+    Type:            STT_OBJECT
+    Section:         .rodata
+    Binding:         STB_GLOBAL
+    Value:           0xFFFFFFFF815CA620
+    Size:            0x4
+  - Name:            proc_off_p_threads
+    Type:            STT_OBJECT
+    Section:         .rodata
+    Binding:         STB_GLOBAL
+    Value:           0xFFFFFFFF815CA630
+    Size:            0x4
+  - Name:            thread_off_td_name
+    Type:            STT_OBJECT
+    Section:         .rodata
+    Binding:         STB_GLOBAL
+    Value:           0xFFFFFFFF815CA638
+    Size:            0x4
+  - Name:            thread_off_td_oncpu
+    Type:            STT_OBJECT
+    Section:         .rodata
+    Binding:         STB_GLOBAL
+    Value:           0xFFFFFFFF815CA63C
+    Size:            0x4
+  - Name:            thread_off_td_pcb
+    Type:            STT_OBJECT
+    Section:         .rodata
+    Binding:         STB_GLOBAL
+    Value:           0xFFFFFFFF815CA640
+    Size:            0x4
+  - Name:            thread_off_td_plist
+    Type:            STT_OBJECT
+    Section:         .rodata
+    Binding:         STB_GLOBAL
+    Value:           0xFFFFFFFF815CA644
+    Size:            0x4
+  - Name:            thread_off_td_tid
+    Type:            STT_OBJECT
+    Section:         .rodata
+    Binding:         STB_GLOBAL
+    Value:           0xFFFFFFFF815CA634
+    Size:            0x4
+  - Name:            dumptid
+    Type:            STT_OBJECT
+    Section:         .bss
+    Binding:         STB_GLOBAL
+    Value:           0xFFFFFFFF81CA69A8
+    Size:            0x4
+  - Name:            pcb_size
+    Type:            STT_OBJECT
+    Section:         .rodata
+    Binding:         STB_GLOBAL
+    Value:           0xFFFFFFFF815CA590
+    Size:            0x4
+  - Name:            stoppcbs
+    Type:            STT_OBJECT
+    Section:         .bss
+    Binding:         STB_GLOBAL
+    Value:           0xFFFFFFFF81D23E20
+    Size:            0x14000
+  - Name:            allproc
+    Type:            STT_OBJECT
+    Section:         .bss
+    Binding:         STB_GLOBAL
+    Value:           0xFFFFFFFF81C9A2F0
+    Size:            0x8
Index: lldb/test/API/functionalities/postmortem/FreeBSDKernel/TestFreeBSDKernelVMCore.py
===================================================================
--- lldb/test/API/functionalities/postmortem/FreeBSDKernel/TestFreeBSDKernelVMCore.py
+++ lldb/test/API/functionalities/postmortem/FreeBSDKernel/TestFreeBSDKernelVMCore.py
@@ -11,6 +11,7 @@
 @skipIfFBSDVMCoreSupportMissing
 class FreeBSDKernelVMCoreTestCase(TestBase):
     NO_DEBUG_INFO_TESTCASE = True
+    maxDiff = None
 
     mydir = TestBase.compute_mydir(__file__)
 
@@ -28,127 +29,325 @@
                 shutil.copyfileobj(inf, outf)
         return dest
 
-    def do_test(self, kernel_yaml, vmcore_bz2, bt_expected, regs_expected,
-                hz_value=100):
+    def do_test(self, kernel_yaml, vmcore_bz2, numthread, threads={}, hz=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.GetNumThreads(), numthread)
         self.assertEqual(process.GetProcessID(), 0)
 
         # test memory reading
         self.expect("expr -- *(int *) &hz",
-                    substrs=["(int) $0 = %d" % hz_value])
+                    substrs=["(int) $0 = %d" % hz])
 
         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)
+                         struct.pack("<I", hz))
+
+        for thread_index, thread_data in threads.items():
+            bt_expected = thread_data["bt"]
+            regs_expected = thread_data["regs"]
+            thread = process.GetThreadAtIndex(thread_index)
+            self.assertEqual(thread.GetName(), thread_data["name"])
+
+            # test backtrace
+            self.assertEqual(
+                [frame.addr.GetLoadAddress(target) for frame in thread],
+                bt_expected)
+
+            # test registers
+            regs = thread.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",
-                      })
+                numthread=13,
+                threads={
+                    0: {"name": "(pid 806) sysctl (crashed)",
+                        "bt": [0xffffffff80c09ade, 0xffffffff80c09916,
+                               0xffffffff80c09d90, 0xffffffff80c09b93,
+                               0xffffffff80c57d91, 0xffffffff80c19e71,
+                               0xffffffff80c192bc, 0xffffffff80c19933,
+                               0xffffffff80c1977f, 0xffffffff8108ba8c,
+                               0xffffffff810620ce,
+                               ],
+                        "regs": {"rbx": "0x0000000000000000",
+                                 "rbp": "0xfffffe0085cb2760",
+                                 "rsp": "0xfffffe0085cb2748",
+                                 "r12": "0xfffffe0045a6c300",
+                                 "r13": "0xfffff800033693a8",
+                                 "r14": "0x0000000000000000",
+                                 "r15": "0xfffff80003369380",
+                                 "rip": "0xffffffff80c09ade",
+                                 },
+                        },
+                    1: {"name": "(pid 11) idle/idle: cpu0 (on CPU 0)",
+                        "bt": [0xffffffff81057988, 0xffffffff81057949,
+                               0xffffffff8108a5ff, 0xffffffff81062537,
+                               0xffffffff80c1aa38, 0xffffffff80b9d587,
+                               0xffffffff810575b1, 0xffffffff81063b33,
+                               0xffffffff804e3edb, 0xffffffff8104dc6e,
+                               0xffffffff8104dd1f, 0xffffffff80c3f0b4,
+                               0xffffffff80bc7c5e,
+                               ],
+                        "regs": {"rbx": "0xffffffff81d43950",
+                                 "rbp": "0xffffffff81d43820",
+                                 "rsp": "0xffffffff81d43808",
+                                 "r12": "0xfffff80003374000",
+                                 "r13": "0x00000000027be000",
+                                 "r14": "0x0000000000000000",
+                                 "r15": "0xfffffe00009f7300",
+                                 "rip": "0xffffffff81057988",
+                                 },
+                        },
+                    10: {"name": "(pid 11) idle/idle: cpu9",
+                         "bt": [0xffffffff80c3c8c8, 0xffffffff80c16521,
+                                0xffffffff80c3f0b4, 0xffffffff80bc7c5e,
+                                ],
+                         "regs": {"rbx": "0x000000007fff29f4",
+                                  "rbp": "0xfffffe00007a4ad0",
+                                  "rsp": "0xfffffe00007a4a08",
+                                  "r12": "0xfffffe00009fd300",
+                                  "r13": "0x0000000000000608",
+                                  "r14": "0xfffffe00009250c0",
+                                  "r15": "0xfffffe0045a6c300",
+                                  "rip": "0xffffffff80c3c8c8",
+                                  },
+                         },
+                    })
 
     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",
-                      })
+                     numthread=16,
+                     threads={
+                         0: {"name": "(pid 800) sysctl (crashed)",
+                             "bt": [0xffffffff80c09ade, 0xffffffff80c09916,
+                                    0xffffffff80c09d90, 0xffffffff80c09b93,
+                                    0xffffffff80c57d91, 0xffffffff80c19e71,
+                                    0xffffffff80c192bc, 0xffffffff80c19933,
+                                    0xffffffff80c1977f, 0xffffffff8108ba8c,
+                                    0xffffffff810620ce,
+                                    ],
+                             "regs": {"rbx": "0x0000000000000000",
+                                      "rbp": "0xfffffe00798c4760",
+                                      "rsp": "0xfffffe00798c4748",
+                                      "r12": "0xfffffe0045b11c00",
+                                      "r13": "0xfffff800033693a8",
+                                      "r14": "0x0000000000000000",
+                                      "r15": "0xfffff80003369380",
+                                      "rip": "0xffffffff80c09ade",
+                                      },
+                             },
+                         1: {"name": "(pid 28) pagedaemon/dom0 (on CPU 4)",
+                             "bt": [0xffffffff81057988, 0xffffffff81057949,
+                                    0xffffffff8108a5ff, 0xffffffff81062537,
+                                    0xffffffff8107171e, 0xffffffff81075f9c,
+                                    0xffffffff80f4359e, 0xffffffff80f494b4,
+                                    0xffffffff80f47430, 0xffffffff80f46eee,
+                                    0xffffffff80bc7c5e,
+                                    ],
+                             "regs": {"rbx": "0xfffffe00008e2f30",
+                                      "rbp": "0xfffffe00008e2e00",
+                                      "rsp": "0xfffffe00008e2de8",
+                                      "r12": "0xfffff80003845000",
+                                      "r13": "0x00000000027be000",
+                                      "r14": "0x0000000000000004",
+                                      "r15": "0xfffffe00458c2700",
+                                      "rip": "0xffffffff81057988",
+                                      },
+                             },
+                         2: {"name": "(pid 28) pagedaemon/laundry: dom0",
+                             "bt": [0xffffffff80c3c8c8, 0xffffffff80c16521,
+                                    0xffffffff80c15c3b, 0xffffffff80f48dfc,
+                                    0xffffffff80bc7c5e,
+                                    ],
+                             "regs": {"rbx": "0x000000007fff25f1",
+                                      "rbp": "0xfffffe00527dd890",
+                                      "rsp": "0xfffffe00527dd7c8",
+                                      "r12": "0xfffffe0045b13100",
+                                      "r13": "0x0000000000000104",
+                                      "r14": "0xfffffe00008d70c0",
+                                      "r15": "0xfffffe00009f5e00",
+                                      "rip": "0xffffffff80c3c8c8",
+                                      },
+                             },
+                         })
 
     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)
+                     hz=1000,
+                     numthread=10,
+                     threads={
+                         0: {"name": "(pid 939) sysctl (crashed)",
+                             # TODO: fix unwinding
+                             "bt": [0xffff0000004b6e78,
+                                    ],
+                             "regs": {"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",
+                                      },
+                             },
+                         1: {"name": "(pid 21) syncer (on CPU 6)",
+                             # TODO: fix unwinding
+                             "bt": [0xffff000000811370,
+                                    ],
+                             "regs": {"x0": "0x0000000000000000",
+                                      "x1": "0x0000000000000000",
+                                      "x2": "0x0000000000000000",
+                                      "x3": "0x0000000000000000",
+                                      "x4": "0x0000000000000000",
+                                      "x5": "0x0000000000000000",
+                                      "x6": "0x0000000000000000",
+                                      "x7": "0x0000000000000000",
+                                      "x8": "0x0000000000000006",
+                                      "x9": "0x0000000000000560",
+                                      "x10": "0xffff000000e8f640",
+                                      "x11": "0x0000000000000001",
+                                      "x12": "0x0000000056000000",
+                                      "x13": "0x0000000000002af8",
+                                      "x14": "0x0000000000002710",
+                                      "x15": "0x0000000000000002",
+                                      "x16": "0x00000000ffffffff",
+                                      "x17": "0x0000000000000002",
+                                      "x18": "0xffff000000e6db80",
+                                      "x19": "0x0000000000000006",
+                                      "x20": "0xffff0000853a3670",
+                                      "x21": "0xffff0000009279c1",
+                                      "x22": "0x0000000000000804",
+                                      "x23": "0x0000000000000004",
+                                      "x24": "0xffff000082a93000",
+                                      "x25": "0xffffa0000053f080",
+                                      "x26": "0xffff000000e6391c",
+                                      "x27": "0xffff000000e63000",
+                                      "x28": "0x0000000000000004",
+                                      "fp": "0xffff0000853a35c0",
+                                      "sp": "0xffff0000853a35c0",
+                                      "pc": "0xffff000000811370",
+                                      },
+                             },
+                         4: {"name": "(pid 11) idle/idle: cpu2",
+                             # TODO: fix unwinding
+                             "bt": [0xffff0000004ee99c,
+                                    ],
+                             "regs": {"x0": "0x0000000000000000",
+                                      "x1": "0x0000000000000000",
+                                      "x2": "0x0000000000000000",
+                                      "x3": "0x0000000000000000",
+                                      "x4": "0x0000000000000000",
+                                      "x5": "0x0000000000000000",
+                                      "x6": "0x0000000000000000",
+                                      "x7": "0x0000000000000000",
+                                      "x8": "0x00000000ffffffff",
+                                      "x9": "0x0000000000000001",
+                                      "x10": "0x0000000000002710",
+                                      "x11": "0x000000007ff7e333",
+                                      "x12": "0x000000007ff7ba9c",
+                                      "x13": "0x0000000000002af8",
+                                      "x14": "0x0000000000002897",
+                                      "x15": "0x0000000000002af8",
+                                      "x16": "0x00000000000028e1",
+                                      "x17": "0x00000000ffffffff",
+                                      "x18": "0xffff000000e6d380",
+                                      "x19": "0xffffa0000032e580",
+                                      "x20": "0xffff000000b82000",
+                                      "x21": "0xffff000040517100",
+                                      "x22": "0xffffa00000e04580",
+                                      "x23": "0xffff000000b84000",
+                                      "x24": "0x0000000000000001",
+                                      "x25": "0xffff000000dd1000",
+                                      "x26": "0xffff000082783898",
+                                      "x27": "0xffff000000e26000",
+                                      "x28": "0xffff000000b82000",
+                                      "fp": "0xffff0000827835f0",
+                                      "sp": "0xffff000082783570",
+                                      "pc": "0xffff0000004ee99c",
+                                      },
+                             },
+                         })
 
     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",
-                      })
+                     numthread=13,
+                     threads={
+                         0: {"name": "(pid 806) sysctl (crashed)",
+                             "bt": [0x010025c5, 0x01002410,
+                                    0x010027d5, 0x01002644,
+                                    0x01049a2f, 0x01011077,
+                                    0x01010780, 0x01010c7a,
+                                    0x01010ab2, 0x013e9e2d,
+                                    0xffc033f9,
+                                    ],
+                             "regs": {"ebp": "0x151968e4",
+                                      "esp": "0x151968d8",
+                                      "esi": "0x0c77aa80",
+                                      "edi": "0x03f0dc80",
+                                      "eip": "0x010025c5",
+                                      },
+                             },
+                         1: {"name": "(pid 11) idle/idle: cpu0 (on CPU 0)",
+                             "bt": [0x013a91f6, 0x013a91c0,
+                                    0x013e8ce4, 0xffc0319f,
+                                    0x00000028,
+                                    ],
+                             "regs": {"ebp": "0x03d979bc",
+                                      "esp": "0x03d979a0",
+                                      "esi": "0x000007f7",
+                                      "edi": "0x00000000",
+                                      "eip": "0x013a91f6",
+                                      },
+                             },
+                         12: {"name": "(pid 11) idle/idle: cpu11",
+                             "bt": [0x0103012c, 0x0100de0e,
+                                    0x0100b770, 0x010323be,
+                                    0x00fc50b6,
+                                    ],
+                             "regs": {"ebp": "0x03dc4af0",
+                                      "esp": "0x03dc4aa4",
+                                      "esi": "0x03f97e00",
+                                      "edi": "0x000003e8",
+                                      "eip": "0x0103012c",
+                                      },
+                             },
+                         })
Index: lldb/source/Plugins/Process/FreeBSDKernel/ThreadFreeBSDKernel.h
===================================================================
--- lldb/source/Plugins/Process/FreeBSDKernel/ThreadFreeBSDKernel.h
+++ lldb/source/Plugins/Process/FreeBSDKernel/ThreadFreeBSDKernel.h
@@ -14,7 +14,7 @@
 class ThreadFreeBSDKernel : public lldb_private::Thread {
 public:
   ThreadFreeBSDKernel(lldb_private::Process &process, lldb::tid_t tid,
-                      lldb::addr_t pcb_addr);
+                      lldb::addr_t pcb_addr, std::string thread_name);
 
   ~ThreadFreeBSDKernel() override;
 
@@ -25,10 +25,24 @@
   lldb::RegisterContextSP
   CreateRegisterContextForFrame(lldb_private::StackFrame *frame) override;
 
+  const char *GetName() override {
+    if (m_thread_name.empty())
+      return nullptr;
+    return m_thread_name.c_str();
+  }
+
+  void SetName(const char *name) override {
+    if (name && name[0])
+      m_thread_name.assign(name);
+    else
+      m_thread_name.clear();
+  }
+
 protected:
   bool CalculateStopInfo() override;
 
 private:
+  std::string m_thread_name;
   lldb::RegisterContextSP m_thread_reg_ctx_sp;
   lldb::addr_t m_pcb_addr;
 };
Index: lldb/source/Plugins/Process/FreeBSDKernel/ThreadFreeBSDKernel.cpp
===================================================================
--- lldb/source/Plugins/Process/FreeBSDKernel/ThreadFreeBSDKernel.cpp
+++ lldb/source/Plugins/Process/FreeBSDKernel/ThreadFreeBSDKernel.cpp
@@ -24,8 +24,10 @@
 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) {}
+                                         lldb::addr_t pcb_addr,
+                                         std::string thread_name)
+    : Thread(process, tid), m_thread_name(std::move(thread_name)),
+      m_pcb_addr(pcb_addr) {}
 
 ThreadFreeBSDKernel::~ThreadFreeBSDKernel() {}
 
@@ -61,9 +63,8 @@
               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);
+      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 =
Index: lldb/source/Plugins/Process/FreeBSDKernel/ProcessFreeBSDKernel.h
===================================================================
--- lldb/source/Plugins/Process/FreeBSDKernel/ProcessFreeBSDKernel.h
+++ lldb/source/Plugins/Process/FreeBSDKernel/ProcessFreeBSDKernel.h
@@ -46,6 +46,8 @@
 protected:
   bool DoUpdateThreadList(lldb_private::ThreadList &old_thread_list,
                           lldb_private::ThreadList &new_thread_list) override;
+
+  lldb::addr_t FindSymbol(const char* name);
 };
 
 #endif // LLDB_SOURCE_PLUGINS_PROCESS_FREEBSDKERNEL_PROCESSFREEBSDKERNEL_H
Index: lldb/source/Plugins/Process/FreeBSDKernel/ProcessFreeBSDKernel.cpp
===================================================================
--- lldb/source/Plugins/Process/FreeBSDKernel/ProcessFreeBSDKernel.cpp
+++ lldb/source/Plugins/Process/FreeBSDKernel/ProcessFreeBSDKernel.cpp
@@ -137,12 +137,115 @@
       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);
+    Status error;
+
+    // struct field offsets are written as symbols so that we don't have
+    // to figure them out ourselves
+    int32_t offset_p_list = ReadSignedIntegerFromMemory(
+        FindSymbol("proc_off_p_list"), 4, -1, error);
+    int32_t offset_p_pid =
+        ReadSignedIntegerFromMemory(FindSymbol("proc_off_p_pid"), 4, -1, error);
+    int32_t offset_p_threads = ReadSignedIntegerFromMemory(
+        FindSymbol("proc_off_p_threads"), 4, -1, error);
+    int32_t offset_p_comm = ReadSignedIntegerFromMemory(
+        FindSymbol("proc_off_p_comm"), 4, -1, error);
+
+    int32_t offset_td_tid = ReadSignedIntegerFromMemory(
+        FindSymbol("thread_off_td_tid"), 4, -1, error);
+    int32_t offset_td_plist = ReadSignedIntegerFromMemory(
+        FindSymbol("thread_off_td_plist"), 4, -1, error);
+    int32_t offset_td_pcb = ReadSignedIntegerFromMemory(
+        FindSymbol("thread_off_td_pcb"), 4, -1, error);
+    int32_t offset_td_oncpu = ReadSignedIntegerFromMemory(
+        FindSymbol("thread_off_td_oncpu"), 4, -1, error);
+    int32_t offset_td_name = ReadSignedIntegerFromMemory(
+        FindSymbol("thread_off_td_name"), 4, -1, error);
+
+    // fail if we were not able to read any of the offsets
+    if (offset_p_list == -1 || offset_p_pid == -1 || offset_p_threads == -1 ||
+        offset_p_comm == -1 || offset_td_tid == -1 || offset_td_plist == -1 ||
+        offset_td_pcb == -1 || offset_td_oncpu == -1 || offset_td_name == -1)
+      return false;
+
+    // dumptid contains the thread-id of the crashing thread
+    // dumppcb contains its PCB
+    int32_t dumptid =
+        ReadSignedIntegerFromMemory(FindSymbol("dumptid"), 4, -1, error);
+    lldb::addr_t dumppcb = FindSymbol("dumppcb");
+
+    // stoppcbs is an array of PCBs on all CPUs
+    // each element is of size pcb_size
+    int32_t pcbsize =
+        ReadSignedIntegerFromMemory(FindSymbol("pcb_size"), 4, -1, error);
+    lldb::addr_t stoppcbs = FindSymbol("stoppcbs");
+
+    // from FreeBSD sys/param.h
+    constexpr size_t fbsd_maxcomlen = 19;
+
+    // iterate through a linked list of all processes
+    // allproc is a pointer to the first list element, p_list field
+    // (found at offset_p_list) specifies the next element
+    for (lldb::addr_t proc =
+             ReadPointerFromMemory(FindSymbol("allproc"), error);
+         proc != 0 && proc != LLDB_INVALID_ADDRESS;
+         proc = ReadPointerFromMemory(proc + offset_p_list, error)) {
+      int32_t pid =
+          ReadSignedIntegerFromMemory(proc + offset_p_pid, 4, -1, error);
+      // process' command-line string
+      char comm[fbsd_maxcomlen + 1];
+      ReadCStringFromMemory(proc + offset_p_comm, comm, sizeof(comm), error);
+
+      // iterate through a linked list of all process' threads
+      // the initial thread is found in process' p_threads, subsequent
+      // elements are linked via td_plist field
+      for (lldb::addr_t td =
+               ReadPointerFromMemory(proc + offset_p_threads, error);
+           td != 0; td = ReadPointerFromMemory(td + offset_td_plist, error)) {
+        int32_t tid =
+            ReadSignedIntegerFromMemory(td + offset_td_tid, 4, -1, error);
+        lldb::addr_t pcb_addr =
+            ReadPointerFromMemory(td + offset_td_pcb, error);
+        // whether process was on CPU (-1 if not, otherwise CPU number)
+        int32_t oncpu =
+            ReadSignedIntegerFromMemory(td + offset_td_oncpu, 4, -2, error);
+        // thread name
+        char thread_name[fbsd_maxcomlen + 1];
+        ReadCStringFromMemory(td + offset_td_name, thread_name,
+                              sizeof(thread_name), error);
+
+        // if we failed to read TID, ignore this thread
+        if (tid == -1)
+          continue;
+
+        std::string thread_desc = llvm::formatv("(pid {0}) {1}", pid, comm);
+        if (*thread_name && strcmp(thread_name, comm)) {
+          thread_desc += '/';
+          thread_desc += thread_name;
+        }
+
+        // roughly:
+        // 1. if the thread crashed, its PCB is going to be at "dumppcb"
+        // 2. if the thread was on CPU, its PCB is going to be on the CPU
+        // 3. otherwise, its PCB is in the thread struct
+        if (tid == dumptid) {
+          // NB: dumppcb can be LLDB_INVALID_ADDRESS if reading it failed
+          pcb_addr = dumppcb;
+          thread_desc += " (crashed)";
+        } else if (oncpu != -1) {
+          // if we managed to read stoppcbs and pcb_size, use them to find
+          // the correct PCB
+          if (stoppcbs != LLDB_INVALID_ADDRESS && pcbsize > 0)
+            pcb_addr = stoppcbs + oncpu * pcbsize;
+          else
+            pcb_addr = LLDB_INVALID_ADDRESS;
+          thread_desc += llvm::formatv(" (on CPU {0})", oncpu);
+        }
+
+        ThreadSP thread_sp{
+            new ThreadFreeBSDKernel(*this, tid, pcb_addr, thread_desc)};
+        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)
@@ -163,6 +266,12 @@
   return m_dyld_up.get();
 }
 
+lldb::addr_t ProcessFreeBSDKernel::FindSymbol(const char *name) {
+  ModuleSP mod_sp = GetTarget().GetExecutableModule();
+  const Symbol *sym = mod_sp->FindFirstSymbolWithNameAndType(ConstString(name));
+  return sym ? sym->GetLoadAddress(&GetTarget()) : LLDB_INVALID_ADDRESS;
+}
+
 #if LLDB_ENABLE_FBSDVMCORE
 
 ProcessFreeBSDKernelFVC::ProcessFreeBSDKernelFVC(lldb::TargetSP target_sp,
_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to