LLDB mainline
ProcessFreeBSDKernelCore.cpp
Go to the documentation of this file.
1//===----------------------------------------------------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#include "lldb/Core/Module.h"
14#include "lldb/Symbol/Type.h"
17#include "lldb/Utility/Log.h"
19
20#include "llvm/Support/Error.h"
21
25
26using namespace lldb;
27using namespace lldb_private;
28
30
31namespace {
32
33#define LLDB_PROPERTIES_processfreebsdkernelcore
34#include "ProcessFreeBSDKernelCoreProperties.inc"
35
36enum {
37#define LLDB_PROPERTIES_processfreebsdkernelcore
38#include "ProcessFreeBSDKernelCorePropertiesEnum.inc"
39};
40
41class PluginProperties : public Properties {
42public:
43 static llvm::StringRef GetSettingName() {
45 }
46
47 PluginProperties() : Properties() {
48 m_collection_sp = std::make_shared<OptionValueProperties>(GetSettingName());
49 m_collection_sp->Initialize(g_processfreebsdkernelcore_properties_def);
50 }
51
52 ~PluginProperties() override = default;
53
54 bool GetReadOnly() const {
55 const uint32_t idx = ePropertyReadOnly;
56 return GetPropertyAtIndexAs<bool>(idx, true);
57 }
58};
59
60} // namespace
61
62static PluginProperties &GetGlobalPluginProperties() {
63 static PluginProperties g_settings;
64 return g_settings;
65}
66
68 : public CommandObjectParsed {
69public:
71 CommandInterpreter &interpreter)
73 interpreter, "process plugin refresh-threads",
74 "Refresh the thread list from the FreeBSD kernel core. The thread "
75 "list and related data structures may be being read from live "
76 "memory (/dev/mem), which may have changed since the last refresh. "
77 "This command clears LLDB's thread list and memory cache then "
78 "re-reads the kernel's allproc/zombie lists to rebuild the thread "
79 "list from scratch.",
80 "process plugin refresh-threads",
81 eCommandRequiresProcess | eCommandTryTargetAPILock) {}
82
84
85protected:
86 void DoExecute(Args &command, CommandReturnObject &result) override {
87 // TODO: Return early for elf-core based implementation.
88
89 auto process = static_cast<ProcessFreeBSDKernelCore *>(
90 m_interpreter.GetExecutionContext().GetProcessPtr());
91
92 // Clear the memory cache so DoUpdateThreadList() will re-read allproc,
93 // zombproc, and all thread/proc structures fresh from the core dump instead
94 // of getting stale cached values.
95 process->m_memory_cache.Clear();
96
97 // Clear both thread lists to guarantee that UpdateThreadListIfNeeded() sees
98 // size == 0 and enters the rebuild path regardless of stop-ID state.
99 // UpdateThreadListIfNeeded() passes m_thread_list_real as old_thread_list
100 // to DoUpdateThreadList(), and DoUpdateThreadList() only rebuilds from
101 // scratch when old_thread_list is empty. m_thread_list is the public copy
102 // that is sync'd from m_thread_list_real afterwards.
103 process->m_thread_list_real.Clear();
104 process->m_thread_list.Clear();
105
106 // This calls UpdateThreadListIfNeeded() to rebuild the process thread list.
107 const uint32_t num_threads =
108 process->GetThreadList().GetSize(/*can_update=*/true);
110 "Thread list refreshed, {0} thread{1} found.", num_threads,
111 num_threads == 1 ? "" : "s");
113 }
114};
115
117 ListenerSP listener_sp,
118 const FileSpec &core_file)
119 : PostMortemProcess(target_sp, listener_sp, core_file) {}
120
122 m_thread_list.Clear();
123
124 // We need to call finalize on the process before destroying ourselves to
125 // make sure all of the broadcaster cleanup goes as planned. If we destruct
126 // this class, then Process::~Process() might have problems trying to fully
127 // destroy the broadcaster.
128 Finalize(/*destructing=*/true);
129}
130
132 lldb::TargetSP target_sp, ListenerSP listener_sp,
133 const FileSpec *crash_file, bool can_connect) {
134 ModuleSP executable = target_sp->GetExecutableModule();
135 if (crash_file && !can_connect && executable) {
136 char errbuf[_POSIX2_LINE_MAX];
137 kvm_t *kvm =
138 kvm_open2(executable->GetFileSpec().GetPath().c_str(),
139 crash_file->GetPath().c_str(), O_RDONLY, errbuf, nullptr);
140 if (kvm) {
141 kvm_close(kvm);
142 return std::make_shared<ProcessFreeBSDKernelCore>(target_sp, listener_sp,
143 *crash_file);
144 }
145 LLDB_LOGF(GetLog(LLDBLog::Process), "FreeBSD-Kernel-Core: %s", errbuf);
146 }
147 return nullptr;
148}
149
155
158 debugger, PluginProperties::GetSettingName())) {
159 const bool is_global_setting = true;
162 "Properties for the freebsd-kernel process plug-in.",
163 is_global_setting);
164 }
165}
166
170
172 bool plugin_specified_by_name) {
173 return true;
174}
175
177 if (!m_command_sp) {
178 CommandInterpreter &interp =
180 m_command_sp = std::make_unique<CommandObjectMultiword>(
181 interp, "process plugin",
182 "Commands for the FreeBSD kernel process plug-in.",
183 "process plugin <subcommand> [<subcommand-options>]");
184 m_command_sp->LoadSubCommand(
185 "refresh-threads",
188 }
189 return m_command_sp.get();
190}
191
193 ModuleSP executable = GetTarget().GetExecutableModule();
194 if (!executable)
196 "ProcessFreeBSDKernelCore: no executable module set on target");
197
198 char errbuf[_POSIX2_LINE_MAX];
199 m_kvm = kvm_open2(executable->GetFileSpec().GetPath().c_str(),
200 GetCoreFile().GetPath().c_str(), O_RDWR, errbuf, nullptr);
201
202 if (!m_kvm) {
203 LLDB_LOGF(GetLog(LLDBLog::Process), "FreeBSD-Kernel-Core: %s", errbuf);
205 "ProcessFreeBSDKernelCore: kvm_open2 failed for core '%s' "
206 "with kernel '%s'",
207 GetCoreFile().GetPath().c_str(),
208 executable->GetFileSpec().GetPath().c_str());
209 }
210
212
213 return Status();
214}
215
222
224 if (!m_kvm)
225 return Status::FromErrorString("kvm file descriptor is not set.");
226
227 kvm_close(m_kvm);
228 return Status();
229}
230
237
239 const void *buf, size_t size,
240 Status &error) {
241 if (GetGlobalPluginProperties().GetReadOnly()) {
243 "Memory writes are currently disabled. You can enable them with "
244 "`settings set plugin.process.freebsd-kernel-core.read-only false`.");
245 return 0;
246 }
247
248 ssize_t rd = 0;
249 rd = kvm_write(m_kvm, addr, buf, size);
250 if (rd < 0 || static_cast<size_t>(rd) != size) {
251 error = Status::FromErrorStringWithFormat("Writing memory failed: %s",
252 GetError());
253 return rd > 0 ? rd : 0;
254 }
255 return rd;
256}
257
259 ThreadList &new_thread_list) {
260 if (old_thread_list.GetSize(false) == 0) {
261 // Make up the thread the first time this is called so we can set our one
262 // and only core thread state up.
263
264 // We cannot construct a thread without a register context as that crashes
265 // LLDB but we can construct a process without threads to provide minimal
266 // memory reading support.
267 switch (GetTarget().GetArchitecture().GetMachine()) {
268 case llvm::Triple::arm:
269 case llvm::Triple::aarch64:
270 case llvm::Triple::ppc64le:
271 case llvm::Triple::riscv64:
272 case llvm::Triple::x86:
273 case llvm::Triple::x86_64:
274 break;
275 default:
276 return false;
277 }
278
280
281 // struct field offsets are written as symbols so that we don't have
282 // to figure them out ourselves
283 // Process-related offsets:
284 int32_t offset_p_list = ReadSignedIntegerFromMemory(
285 FindSymbol("proc_off_p_list"), 4, -1, error);
286 if (error.Fail())
287 return false;
288
289 int32_t offset_p_pid =
290 ReadSignedIntegerFromMemory(FindSymbol("proc_off_p_pid"), 4, -1, error);
291 if (error.Fail())
292 return false;
293
294 int32_t offset_p_threads = ReadSignedIntegerFromMemory(
295 FindSymbol("proc_off_p_threads"), 4, -1, error);
296 if (error.Fail())
297 return false;
298
299 int32_t offset_p_comm = ReadSignedIntegerFromMemory(
300 FindSymbol("proc_off_p_comm"), 4, -1, error);
301 if (error.Fail())
302 return false;
303
304 // Thread-related offsets:
305 int32_t offset_td_tid = ReadSignedIntegerFromMemory(
306 FindSymbol("thread_off_td_tid"), 4, -1, error);
307 if (error.Fail())
308 return false;
309
310 int32_t offset_td_plist = ReadSignedIntegerFromMemory(
311 FindSymbol("thread_off_td_plist"), 4, -1, error);
312 if (error.Fail())
313 return false;
314
315 int32_t offset_td_pcb = ReadSignedIntegerFromMemory(
316 FindSymbol("thread_off_td_pcb"), 4, -1, error);
317 if (error.Fail())
318 return false;
319
320 int32_t offset_td_oncpu = ReadSignedIntegerFromMemory(
321 FindSymbol("thread_off_td_oncpu"), 4, -1, error);
322 if (error.Fail())
323 return false;
324
325 int32_t offset_td_name = ReadSignedIntegerFromMemory(
326 FindSymbol("thread_off_td_name"), 4, -1, error);
327 if (error.Fail())
328 return false;
329
330 // Fail if we were not able to read any of the offsets.
331 if (offset_p_list == -1 || offset_p_pid == -1 || offset_p_threads == -1 ||
332 offset_p_comm == -1 || offset_td_tid == -1 || offset_td_plist == -1 ||
333 offset_td_pcb == -1 || offset_td_oncpu == -1 || offset_td_name == -1)
334 return false;
335
336 // dumptid contains the thread-id of the crashing thread
337 // dumppcb contains its PCB
338 int32_t dumptid =
339 ReadSignedIntegerFromMemory(FindSymbol("dumptid"), 4, -1, error);
340 if (error.Fail())
341 return false;
342
343 lldb::addr_t dumppcb = FindSymbol("dumppcb");
344
345 // stoppcbs is an array of PCBs on all CPUs.
346 // Each element is of size pcb_size.
347 int32_t pcbsize =
348 ReadSignedIntegerFromMemory(FindSymbol("pcb_size"), 4, -1, error);
349 if (error.Fail())
350 return false;
351
352 lldb::addr_t stoppcbs = FindSymbol("stoppcbs");
353
354 // Read stopped_cpus bitmask and mp_maxid for CPU validation.
355 lldb::addr_t stopped_cpus = FindSymbol("stopped_cpus");
356 uint32_t mp_maxid = 0;
357
358 if (stopped_cpus != LLDB_INVALID_ADDRESS) {
359 // https://cgit.freebsd.org/src/tree/sys/kern/subr_smp.c
360 mp_maxid =
361 ReadSignedIntegerFromMemory(FindSymbol("mp_maxid"), 4, 0, error);
362 if (error.Fail())
363 stopped_cpus = LLDB_INVALID_ADDRESS;
364 }
365
366 uint32_t long_size_bytes = GetAddressByteSize();
367 uint32_t long_bit = long_size_bytes * 8;
368
369 if (auto type_system_or_err =
370 GetTarget().GetScratchTypeSystemForLanguage(eLanguageTypeC)) {
371 CompilerType long_type =
372 (*type_system_or_err)->GetBasicTypeFromAST(eBasicTypeLong);
373 if (long_type.IsValid())
374 if (auto size = long_type.GetByteSize(nullptr))
375 long_size_bytes = *size;
376 long_bit = long_size_bytes * 8;
377 } else
378 llvm::consumeError(type_system_or_err.takeError());
379
380 // https://cgit.freebsd.org/src/tree/sys/sys/param.h
381 constexpr size_t fbsd_maxcomlen = 19;
382
383 // Iterate through a linked list of all processes then order incrementally
384 // by pid. Though new processes are added to the head of this list, process
385 // ids may be reused as well. So we cannot rely on it being in a particular
386 // order.
387 const lldb::addr_t allproc_addr = FindSymbol("allproc");
388 if (allproc_addr == LLDB_INVALID_ADDRESS)
389 return false;
390
391 std::vector<std::pair<lldb::addr_t, int32_t>> process_addrs;
392 llvm::Expected<lldb::addr_t> proc_or_err =
393 ReadPointerFromMemory(allproc_addr);
394 for (; proc_or_err && *proc_or_err != 0;
395 proc_or_err = ReadPointerFromMemory(*proc_or_err + offset_p_list)) {
396 lldb::addr_t proc = *proc_or_err;
397 int32_t pid =
398 ReadSignedIntegerFromMemory(proc + offset_p_pid, 4, -1, error);
399 if (error.Fail())
400 return false;
401 process_addrs.emplace_back(proc, pid);
402 }
403
404 if (!proc_or_err) {
405 llvm::consumeError(proc_or_err.takeError());
406 return false;
407 }
408
409 std::sort(process_addrs.begin(), process_addrs.end(),
410 [](const auto &a, const auto &b) { return a.second < b.second; });
411
412 for (auto [proc, pid] : process_addrs) {
413 // process' command-line string
414 char comm[fbsd_maxcomlen + 1];
415 ReadCStringFromMemory(proc + offset_p_comm, comm, sizeof(comm), error);
416 if (error.Fail())
417 continue;
418
419 // Iterate through a linked list of all process' threads
420 // the initial thread is found in process' p_threads, subsequent
421 // elements are linked via td_plist field.
422 // If reading memory fails, skip to the next thread.
423 llvm::Expected<lldb::addr_t> td_or_err =
424 ReadPointerFromMemory(proc + offset_p_threads);
425 for (; td_or_err && *td_or_err != 0;
426 td_or_err = ReadPointerFromMemory(*td_or_err + offset_td_plist)) {
427 lldb::addr_t td = *td_or_err;
428 int32_t tid =
429 ReadSignedIntegerFromMemory(td + offset_td_tid, 4, -1, error);
430 if (error.Fail())
431 continue;
432
433 llvm::Expected<lldb::addr_t> pcb_addr_or_err =
434 ReadPointerFromMemory(td + offset_td_pcb);
435 if (!pcb_addr_or_err) {
436 llvm::consumeError(pcb_addr_or_err.takeError());
437 continue;
438 }
439 lldb::addr_t pcb_addr = *pcb_addr_or_err;
440
441 // whether process was on CPU (-1 if not, otherwise CPU number)
442 int32_t oncpu =
443 ReadSignedIntegerFromMemory(td + offset_td_oncpu, 4, -2, error);
444 if (error.Fail())
445 continue;
446
447 // thread name
448 char thread_name[fbsd_maxcomlen + 1];
449 ReadCStringFromMemory(td + offset_td_name, thread_name,
450 sizeof(thread_name), error);
451 if (error.Fail())
452 continue;
453
454 // If we failed to read TID, ignore this thread.
455 if (tid == -1)
456 continue;
457
458 std::string thread_desc = llvm::formatv("(pid {0}) {1}", pid, comm);
459 if (*thread_name && strcmp(thread_name, comm)) {
460 thread_desc += '/';
461 thread_desc += thread_name;
462 }
463
464 // Roughly:
465 // 1. if the thread crashed, its PCB is going to be at "dumppcb"
466 // 2. if the thread was on CPU, its PCB is going to be on the CPU
467 // 3. otherwise, its PCB is in the thread struct
468 if (tid == dumptid) {
469 // NB: dumppcb can be LLDB_INVALID_ADDRESS if reading it failed
470 pcb_addr = dumppcb;
471 thread_desc += " (crashed)";
472 } else if (oncpu != -1) {
473 // Verify the CPU is actually in the stopped set before using
474 // its stoppcbs entry.
475 bool is_stopped = false;
476 if (oncpu >= 0 && static_cast<uint32_t>(oncpu) <= mp_maxid &&
477 stopped_cpus != LLDB_INVALID_ADDRESS) {
478 uint32_t bit = oncpu % long_bit;
479 uint32_t word = oncpu / long_bit;
480 lldb::addr_t mask_addr = stopped_cpus + word * long_size_bytes;
481 uint64_t mask = ReadUnsignedIntegerFromMemory(
482 mask_addr, long_size_bytes, 0, error);
483 if (error.Success())
484 is_stopped = (mask & (1ULL << bit)) != 0;
485 }
486
487 // If we managed to read stoppcbs and pcb_size and the cpu is marked
488 // as stopped, use them to find the correct PCB.
489 if (is_stopped && stoppcbs != LLDB_INVALID_ADDRESS && pcbsize > 0) {
490 pcb_addr = stoppcbs + oncpu * pcbsize;
491 } else {
492 pcb_addr = LLDB_INVALID_ADDRESS;
493 }
494 thread_desc += llvm::formatv(" (on CPU {0})", oncpu);
495 }
496
497 auto thread =
498 new ThreadFreeBSDKernelCore(*this, tid, pcb_addr, thread_desc);
499
500 if (tid == dumptid)
501 thread->SetIsCrashedThread(true);
502
503 new_thread_list.AddThread(static_cast<ThreadSP>(thread));
504 }
505
506 // If reading thread list has failed, return with false.
507 if (!td_or_err) {
508 llvm::consumeError(td_or_err.takeError());
509 return false;
510 }
511 }
512 } else {
513 const uint32_t num_threads = old_thread_list.GetSize(false);
514 for (uint32_t i = 0; i < num_threads; ++i)
515 new_thread_list.AddThread(old_thread_list.GetThreadAtIndex(i, false));
516 }
517 return new_thread_list.GetSize(false) > 0;
518}
519
520size_t
522 void *buf, size_t size, Status &error) {
523 lldb::addr_t addr = process_addr.GetValue();
524 ssize_t rd = 0;
525 rd = kvm_read2(m_kvm, addr, buf, size);
526 if (rd < 0 || static_cast<size_t>(rd) != size) {
527 error = Status::FromErrorStringWithFormat("Reading memory failed: %s",
528 GetError());
529 return rd > 0 ? rd : 0;
530 }
531 return rd;
532}
533
536 const Symbol *sym = mod_sp->FindFirstSymbolWithNameAndType(ConstString(name));
537 return sym ? sym->GetLoadAddress(&GetTarget()) : LLDB_INVALID_ADDRESS;
538}
539
541 kssize_t displacement = kvm_kerndisp(m_kvm);
542
543 if (displacement == 0)
544 return;
545
546 Target &target = GetTarget();
547 lldb::ModuleSP kernel_module_sp = target.GetExecutableModule();
548 if (!kernel_module_sp)
549 return;
550
551 bool changed = false;
552 kernel_module_sp->SetLoadAddress(target,
553 static_cast<lldb::addr_t>(displacement),
554 /*value_is_offset=*/true, changed);
555
556 if (changed) {
557 ModuleList loaded_module_list;
558 loaded_module_list.Append(kernel_module_sp);
559 target.ModulesDidLoad(loaded_module_list);
560 }
561}
562
564 Target &target = GetTarget();
565 Debugger &debugger = target.GetDebugger();
566
568
569 // Find msgbufp symbol (pointer to message buffer)
570 lldb::addr_t msgbufp_addr = FindSymbol("msgbufp");
571 if (msgbufp_addr == LLDB_INVALID_ADDRESS)
572 return;
573
574 // Read the pointer value
575 llvm::Expected<lldb::addr_t> msgbufp_or_err =
576 ReadPointerFromMemory(msgbufp_addr);
577 if (!msgbufp_or_err) {
578 llvm::consumeError(msgbufp_or_err.takeError());
579 return;
580 }
581 lldb::addr_t msgbufp = *msgbufp_or_err;
582
583 // Get the type information for struct msgbuf from DWARF
584 TypeQuery query("msgbuf");
585 TypeResults results;
586 target.GetImages().FindTypes(nullptr, query, results);
587
588 uint64_t offset_msg_ptr = 0;
589 uint64_t offset_msg_size = 0;
590 uint64_t offset_msg_wseq = 0;
591 uint64_t offset_msg_rseq = 0;
592
593 if (results.GetTypeMap().GetSize() > 0) {
594 // Found type info - use it to get field offsets
595 CompilerType msgbuf_type =
596 results.GetTypeMap().GetTypeAtIndex(0)->GetForwardCompilerType();
597
598 uint32_t num_fields = msgbuf_type.GetNumFields();
599 int field_found = 0;
600 for (uint32_t i = 0; i < num_fields; i++) {
601 std::string field_name;
602 uint64_t field_offset = 0;
603
604 msgbuf_type.GetFieldAtIndex(i, field_name, &field_offset, nullptr,
605 nullptr);
606
607 if (field_name == "msg_ptr") {
608 offset_msg_ptr = field_offset / 8; // Convert bits to bytes
609 field_found++;
610 } else if (field_name == "msg_size") {
611 offset_msg_size = field_offset / 8;
612 field_found++;
613 } else if (field_name == "msg_wseq") {
614 offset_msg_wseq = field_offset / 8;
615 field_found++;
616 } else if (field_name == "msg_rseq") {
617 offset_msg_rseq = field_offset / 8;
618 field_found++;
619 }
620 }
621
622 if (field_found != 4) {
623 LLDB_LOGF(
625 "FreeBSD-Kernel-Core: Could not find all required fields for msgbuf");
626 return;
627 }
628 } else {
629 // Fallback: use hardcoded offsets based on struct layout
630 // struct msgbuf layout (from sys/sys/msgbuf.h):
631 // char *msg_ptr; - offset 0
632 // u_int msg_magic; - offset ptr_size
633 // u_int msg_size; - offset ptr_size + 4
634 // u_int msg_wseq; - offset ptr_size + 8
635 // u_int msg_rseq; - offset ptr_size + 12
636 uint32_t ptr_size = GetAddressByteSize();
637 offset_msg_ptr = 0;
638 offset_msg_size = ptr_size + 4;
639 offset_msg_wseq = ptr_size + 8;
640 offset_msg_rseq = ptr_size + 12;
641 }
642
643 // Read struct msgbuf fields
644 llvm::Expected<lldb::addr_t> bufp_or_err =
645 ReadPointerFromMemory(msgbufp + offset_msg_ptr);
646 if (!bufp_or_err) {
647 llvm::consumeError(bufp_or_err.takeError());
648 return;
649 }
650 lldb::addr_t bufp = *bufp_or_err;
651
652 uint32_t size =
653 ReadUnsignedIntegerFromMemory(msgbufp + offset_msg_size, 4, 0, error);
654 if (error.Fail() || size == 0)
655 return;
656
657 uint32_t wseq =
658 ReadUnsignedIntegerFromMemory(msgbufp + offset_msg_wseq, 4, 0, error);
659 if (error.Fail())
660 return;
661
662 uint32_t rseq =
663 ReadUnsignedIntegerFromMemory(msgbufp + offset_msg_rseq, 4, 0, error);
664 if (error.Fail())
665 return;
666
667 // Convert sequences to positions
668 // MSGBUF_SEQ_TO_POS macro in FreeBSD: ((seq) % (size))
669 uint32_t rseq_pos = rseq % size;
670 uint32_t wseq_pos = wseq % size;
671
672 if (rseq_pos == wseq_pos)
673 return;
674
675 // Print crash info at once using stream
676 lldb::StreamSP stream_sp = debugger.GetAsyncOutputStream();
677 if (!stream_sp)
678 return;
679
680 stream_sp->PutCString("\nUnread portion of the kernel message buffer:\n");
681
682 // Read ring buffer in at most two chunks
683 if (rseq_pos < wseq_pos) {
684 // No wrap: read from rseq_pos to wseq_pos
685 size_t len = wseq_pos - rseq_pos;
686 std::string buf(len, '\0');
687 size_t bytes_read = ReadMemory(bufp + rseq_pos, &buf[0], len, error);
688 if (error.Success() && bytes_read > 0) {
689 buf.resize(bytes_read);
690 *stream_sp << buf;
691 }
692 } else {
693 // Wrap around: read from rseq_pos to end, then from start to wseq_pos
694 size_t len1 = size - rseq_pos;
695 std::string buf1(len1, '\0');
696 size_t bytes_read1 = ReadMemory(bufp + rseq_pos, &buf1[0], len1, error);
697 if (error.Success() && bytes_read1 > 0) {
698 buf1.resize(bytes_read1);
699 *stream_sp << buf1;
700 }
701
702 if (wseq_pos > 0) {
703 std::string buf2(wseq_pos, '\0');
704 size_t bytes_read2 = ReadMemory(bufp, &buf2[0], wseq_pos, error);
705 if (error.Success() && bytes_read2 > 0) {
706 buf2.resize(bytes_read2);
707 *stream_sp << buf2;
708 }
709 }
710 }
711
712 stream_sp->PutChar('\n');
713 stream_sp->Flush();
714}
715
716const char *ProcessFreeBSDKernelCore::GetError() { return kvm_geterr(m_kvm); }
static llvm::raw_ostream & error(Stream &strm)
#define bit
static PluginProperties & GetGlobalPluginProperties()
#define LLDB_LOGF(log,...)
Definition Log.h:389
#define LLDB_PLUGIN_DEFINE(PluginName)
static PluginProperties & GetGlobalPluginProperties()
void DoExecute(Args &command, CommandReturnObject &result) override
CommandObjectProcessFreeBSDKernelCoreRefreshThreads(CommandInterpreter &interpreter)
~CommandObjectProcessFreeBSDKernelCoreRefreshThreads() override=default
static llvm::StringRef GetPluginNameStatic()
lldb_private::Status DoDestroy() override
static llvm::StringRef GetPluginNameStatic()
ProcessFreeBSDKernelCore(lldb::TargetSP target_sp, lldb::ListenerSP listener, const lldb_private::FileSpec &core_file)
lldb::addr_t FindSymbol(const char *name)
static lldb::ProcessSP CreateInstance(lldb::TargetSP target_sp, lldb::ListenerSP listener, const lldb_private::FileSpec *crash_file_path, bool can_connect)
void RefreshStateAfterStop() override
Currently called as part of ShouldStop.
static void DebuggerInitialize(lldb_private::Debugger &debugger)
static llvm::StringRef GetPluginDescriptionStatic()
lldb_private::Status DoLoadCore() override
lldb_private::CommandObject * GetPluginCommandObject() override
Return a multi-word command object that can be used to expose plug-in specific commands.
friend class CommandObjectProcessFreeBSDKernelCoreRefreshThreads
lldb_private::DynamicLoader * GetDynamicLoader() override
Get the dynamic loader plug-in for this process.
size_t DoWriteMemory(lldb::addr_t addr, const void *buf, size_t size, lldb_private::Status &error) override
Actually do the writing of memory to a process.
bool DoUpdateThreadList(lldb_private::ThreadList &old_thread_list, lldb_private::ThreadList &new_thread_list) override
Update the thread list following process plug-in's specific logic.
size_t DoReadMemory(const lldb_private::ProcessAddress &addr, void *buf, size_t size, lldb_private::Status &error) override
Actually do the reading of memory from a process.
bool CanDebug(lldb::TargetSP target_sp, bool plugin_specified_by_name) override
Check if a plug-in instance can debug the file in module.
std::unique_ptr< lldb_private::CommandObjectMultiword > m_command_sp
A command line argument class.
Definition Args.h:33
CommandObjectParsed(CommandInterpreter &interpreter, const char *name, const char *help=nullptr, const char *syntax=nullptr, uint32_t flags=0)
CommandInterpreter & m_interpreter
void SetStatus(lldb::ReturnStatus status)
void void AppendMessageWithFormatv(const char *format, Args &&...args)
Generic representation of a type in a programming language.
CompilerType GetBasicTypeFromAST(lldb::BasicType basic_type) const
Create related types using the current type's AST.
CompilerType GetFieldAtIndex(size_t idx, std::string &name, uint64_t *bit_offset_ptr, uint32_t *bitfield_bit_size_ptr, bool *is_bitfield_ptr) const
llvm::Expected< uint64_t > GetByteSize(ExecutionContextScope *exe_scope) const
Return the size of the type in bytes.
uint32_t GetNumFields() const
A uniqued constant string class.
Definition ConstString.h:40
CommandInterpreter & GetCommandInterpreter()
Definition Debugger.h:182
lldb::StreamUP GetAsyncOutputStream()
static DynamicLoader * FindPlugin(Process *process, llvm::StringRef plugin_name)
Find a dynamic loader plugin for a given process.
A file utility class.
Definition FileSpec.h:56
size_t GetPath(char *path, size_t max_path_length, bool denormalize=true) const
Extract the full path to the file.
Definition FileSpec.cpp:380
void Clear(bool clear_invalid_ranges=false)
Definition Memory.cpp:34
A collection class for Module objects.
Definition ModuleList.h:125
void FindTypes(Module *search_first, const TypeQuery &query, lldb_private::TypeResults &results) const
Find types using a type-matching object that contains all search parameters.
void Append(const lldb::ModuleSP &module_sp, bool notify=true)
Append a module to the module list.
static bool RegisterPlugin(llvm::StringRef name, llvm::StringRef description, ABICreateInstance create_callback)
static bool CreateSettingForProcessPlugin(Debugger &debugger, const lldb::OptionValuePropertiesSP &properties_sp, llvm::StringRef description, bool is_global_property)
static lldb::OptionValuePropertiesSP GetSettingForProcessPlugin(Debugger &debugger, llvm::StringRef setting_name)
static bool UnregisterPlugin(ABICreateInstance create_callback)
PostMortemProcess(lldb::TargetSP target_sp, lldb::ListenerSP listener_sp, const FileSpec &core_file)
FileSpec GetCoreFile() const override
Provide a way to retrieve the core dump file that is loaded for debugging.
An address in a process, qualified by an address space.
lldb::addr_t GetValue() const
int64_t ReadSignedIntegerFromMemory(lldb::addr_t load_addr, size_t byte_size, int64_t fail_value, Status &error)
Definition Process.cpp:2552
size_t ReadCStringFromMemory(lldb::addr_t vm_addr, char *cstr, size_t cstr_max_len, Status &error)
Read a NULL terminated C string from memory.
Definition Process.cpp:2383
virtual size_t ReadMemory(const ProcessAddress &process_addr, void *buf, size_t size, Status &error)
Read of memory from a process.
Definition Process.cpp:2083
lldb::DynamicLoaderUP m_dyld_up
Definition Process.h:3552
llvm::Expected< lldb::addr_t > ReadPointerFromMemory(lldb::addr_t vm_addr)
Definition Process.cpp:2563
uint64_t ReadUnsignedIntegerFromMemory(lldb::addr_t load_addr, size_t byte_size, uint64_t fail_value, Status &error)
Reads an unsigned integer of the specified byte size from process memory.
Definition Process.cpp:2502
friend class Target
Definition Process.h:373
MemoryCache m_memory_cache
Definition Process.h:3575
uint32_t GetAddressByteSize() const
Definition Process.cpp:3983
virtual void Finalize(bool destructing)
This object is about to be destroyed, do any necessary cleanup.
Definition Process.cpp:578
ThreadList m_thread_list
The threads for this process as the user will see them.
Definition Process.h:3522
friend class DynamicLoader
Definition Process.h:370
friend class Debugger
Definition Process.h:369
friend class ThreadList
Definition Process.h:374
Target & GetTarget()
Get the target object pointer for this module.
Definition Process.h:1266
lldb::OptionValuePropertiesSP GetValueProperties() const
An error handling class.
Definition Status.h:118
static Status FromErrorStringWithFormat(const char *format,...) __attribute__((format(printf
Definition Status.cpp:106
static Status FromErrorString(const char *str)
Definition Status.h:141
lldb::addr_t GetLoadAddress(Target *target) const
Definition Symbol.cpp:605
void ModulesDidLoad(ModuleList &module_list)
This call may preload module symbols, and may do so in parallel depending on the following target set...
Definition Target.cpp:1941
Debugger & GetDebugger() const
Definition Target.h:1337
lldb::ModuleSP GetExecutableModule()
Gets the module for the main executable.
Definition Target.cpp:1625
const ModuleList & GetImages() const
Get accessor for the images for this process.
Definition Target.h:1254
void AddThread(const lldb::ThreadSP &thread_sp)
uint32_t GetSize(bool can_update=true)
lldb::ThreadSP GetThreadAtIndex(uint32_t idx, bool can_update=true)
uint32_t GetSize() const
Definition TypeMap.cpp:51
lldb::TypeSP GetTypeAtIndex(uint32_t idx)
Definition TypeMap.cpp:59
A class that contains all state required for type lookups.
Definition Type.h:104
This class tracks the state and results of a TypeQuery.
Definition Type.h:344
TypeMap & GetTypeMap()
Definition Type.h:386
#define LLDB_INVALID_ADDRESS
A class that represents a running process on the host machine.
Log * GetLog(Cat mask)
Retrieve the Log object for the channel associated with the given log enum.
Definition Log.h:338
std::shared_ptr< lldb_private::Thread > ThreadSP
std::shared_ptr< lldb_private::CommandObject > CommandObjectSP
@ eLanguageTypeC
Non-standardized C, such as K&R.
std::shared_ptr< lldb_private::Stream > StreamSP
std::shared_ptr< lldb_private::Process > ProcessSP
@ eReturnStatusSuccessFinishResult
std::shared_ptr< lldb_private::Listener > ListenerSP
uint64_t addr_t
Definition lldb-types.h:80
std::shared_ptr< lldb_private::Target > TargetSP
std::shared_ptr< lldb_private::Module > ModuleSP