27 #include "llvm/BinaryFormat/ELF.h"
28 #include "llvm/Support/Threading.h"
37 namespace ELF = llvm::ELF;
42 return "ELF core dump plug-in.";
50 lldb::ListenerSP listener_sp,
53 lldb::ProcessSP process_sp;
54 if (crash_file && !can_connect) {
58 const size_t header_size =
sizeof(llvm::ELF::Elf64_Ehdr);
61 crash_file->
GetPath(), header_size, 0);
62 if (data_sp && data_sp->GetByteSize() == header_size &&
67 if (elf_header.
Parse(data, &data_offset)) {
72 if (elf_header.
e_type == llvm::ELF::ET_CORE)
73 process_sp = std::make_shared<ProcessElfCore>(target_sp, listener_sp,
82 bool plugin_specified_by_name) {
85 ModuleSpec core_module_spec(m_core_file, target_sp->GetArchitecture());
87 nullptr,
nullptr,
nullptr));
88 if (m_core_module_sp) {
89 ObjectFile *core_objfile = m_core_module_sp->GetObjectFile();
99 lldb::ListenerSP listener_sp,
125 last_entry->
data.GetRangeEnd() == range_entry.
data.GetRangeBase() &&
128 last_entry->
data.SetRangeEnd(range_entry.
data.GetRangeEnd());
136 ((header.
p_flags & llvm::ELF::PF_R) ? lldb::ePermissionsReadable : 0u) |
137 ((header.
p_flags & llvm::ELF::PF_W) ? lldb::ePermissionsWritable : 0u) |
138 ((header.
p_flags & llvm::ELF::PF_X) ? lldb::ePermissionsExecutable : 0u);
150 error.SetErrorString(
"invalid core module");
155 if (core ==
nullptr) {
156 error.SetErrorString(
"invalid core object file");
160 llvm::ArrayRef<elf::ELFProgramHeader> segments = core->
ProgramHeaders();
161 if (segments.size() == 0) {
162 error.SetErrorString(
"core file has no segments");
170 bool ranges_are_sorted =
true;
179 if (H.p_type == llvm::ELF::PT_NOTE) {
184 if (H.p_type == llvm::ELF::PT_LOAD) {
186 if (vm_addr > last_addr)
187 ranges_are_sorted =
false;
192 if (!ranges_are_sorted) {
209 bool siginfo_signal_found =
false;
210 bool prstatus_signal_found =
false;
213 if (thread_data.signo != 0)
214 siginfo_signal_found =
true;
215 if (thread_data.prstatus_sig != 0)
216 prstatus_signal_found =
true;
218 if (!siginfo_signal_found) {
221 if (prstatus_signal_found) {
223 thread_data.signo = thread_data.prstatus_sig;
234 if (!exe_module_sp) {
254 m_dyld_up.reset(DynamicLoader::FindPlugin(
265 for (
lldb::tid_t tid = 0; tid < num_threads; ++tid) {
270 return new_thread_list.
GetSize(
false) > 0;
294 if (permission_entry) {
295 if (permission_entry->
Contains(load_addr)) {
298 const Flags permissions(permission_entry->
data);
300 ? MemoryRegionInfo::eYes
301 : MemoryRegionInfo::eNo);
303 ? MemoryRegionInfo::eYes
304 : MemoryRegionInfo::eNo);
306 ? MemoryRegionInfo::eYes
307 : MemoryRegionInfo::eNo);
308 region_info.
SetMapped(MemoryRegionInfo::eYes);
309 }
else if (load_addr < permission_entry->GetRangeBase()) {
315 region_info.
SetMapped(MemoryRegionInfo::eNo);
325 region_info.
SetMapped(MemoryRegionInfo::eNo);
333 if (core_objfile ==
nullptr)
339 if (address_range ==
nullptr || address_range->
GetRangeEnd() < addr) {
340 error.SetErrorStringWithFormat(
"core file does not contain 0x%" PRIx64,
349 size_t bytes_to_read = size;
350 size_t bytes_copied = 0;
356 if (file_start == file_end)
361 if (file_end > file_start + offset)
362 bytes_left = file_end - (file_start + offset);
364 if (bytes_to_read > bytes_left)
365 bytes_to_read = bytes_left;
370 core_objfile->
CopyData(offset + file_start, bytes_to_read, buf);
382 static llvm::once_flag g_once_flag;
384 llvm::call_once(g_once_flag, []() {
404 int pr_version = data.
GetU32(&offset);
409 LLDB_LOGF(log,
"FreeBSD PRSTATUS unexpected version %d", pr_version);
432 int pr_version = data.
GetU32(&offset);
437 LLDB_LOGF(log,
"FreeBSD PRPSINFO unexpected version %d", pr_version);
457 return llvm::make_error<llvm::StringError>(
458 "Error parsing NetBSD core(5) notes: Unsupported procinfo version",
459 llvm::inconvertibleErrorCode());
463 return llvm::make_error<llvm::StringError>(
464 "Error parsing NetBSD core(5) notes: Unsupported procinfo size",
465 llvm::inconvertibleErrorCode());
467 cpi_signo = data.
GetU32(&offset);
474 cpi_pid = data.
GetU32(&offset);
484 cpi_nlwps = data.
GetU32(&offset);
487 cpi_siglwp = data.
GetU32(&offset);
489 return llvm::Error::success();
496 int version = data.
GetU32(&offset);
504 llvm::Expected<std::vector<CoreNote>>
507 std::vector<CoreNote> result;
511 if (!note.
Parse(segment, &offset))
512 return llvm::make_error<llvm::StringError>(
513 "Unable to parse note segment", llvm::inconvertibleErrorCode());
515 size_t note_start = offset;
516 size_t note_size = llvm::alignTo(note.
n_descsz, 4);
518 result.push_back({note,
DataExtractor(segment, note_start, note_size)});
522 return std::move(result);
527 bool lp64 = (arch.
GetMachine() == llvm::Triple::aarch64 ||
531 bool have_prstatus =
false;
532 bool have_prpsinfo =
false;
534 for (
const auto ¬e : notes) {
535 if (note.info.n_name !=
"FreeBSD")
538 if ((note.info.n_type == ELF::NT_PRSTATUS && have_prstatus) ||
539 (note.info.n_type == ELF::NT_PRPSINFO && have_prpsinfo)) {
544 have_prstatus =
false;
545 have_prpsinfo =
false;
548 switch (note.info.n_type) {
549 case ELF::NT_PRSTATUS:
550 have_prstatus =
true;
553 case ELF::NT_PRPSINFO:
554 have_prpsinfo =
true;
557 case ELF::NT_FREEBSD_THRMISC: {
559 thread_data.
name = note.data.GetCStr(&offset, 20);
562 case ELF::NT_FREEBSD_PROCSTAT_AUXV:
567 thread_data.
notes.push_back(note);
571 if (!have_prstatus) {
572 return llvm::make_error<llvm::StringError>(
573 "Could not find NT_PRSTATUS note in core file.",
574 llvm::inconvertibleErrorCode());
577 return llvm::Error::success();
604 bool had_nt_regs =
false;
613 for (
const auto ¬e : notes) {
614 llvm::StringRef name = note.info.n_name;
616 if (name ==
"NetBSD-CORE") {
626 }
else if (name.consume_front(
"NetBSD-CORE@")) {
628 if (name.getAsInteger(10, tid))
629 return llvm::make_error<llvm::StringError>(
630 "Error parsing NetBSD core(5) notes: Cannot convert LWP ID "
632 llvm::inconvertibleErrorCode());
635 case llvm::Triple::aarch64: {
646 thread_data.
tid = tid;
648 return llvm::make_error<llvm::StringError>(
649 "Could not find general purpose registers note in core file.",
650 llvm::inconvertibleErrorCode());
653 if (!had_nt_regs || tid != thread_data.
tid)
654 return llvm::make_error<llvm::StringError>(
655 "Error parsing NetBSD core(5) notes: Unexpected order "
656 "of NOTEs PT_GETFPREG before PT_GETREG",
657 llvm::inconvertibleErrorCode());
658 thread_data.
notes.push_back(note);
661 case llvm::Triple::x86: {
672 thread_data.
tid = tid;
674 return llvm::make_error<llvm::StringError>(
675 "Could not find general purpose registers note in core file.",
676 llvm::inconvertibleErrorCode());
679 if (!had_nt_regs || tid != thread_data.
tid)
680 return llvm::make_error<llvm::StringError>(
681 "Error parsing NetBSD core(5) notes: Unexpected order "
682 "of NOTEs PT_GETFPREG before PT_GETREG",
683 llvm::inconvertibleErrorCode());
684 thread_data.
notes.push_back(note);
687 case llvm::Triple::x86_64: {
698 thread_data.
tid = tid;
700 return llvm::make_error<llvm::StringError>(
701 "Could not find general purpose registers note in core file.",
702 llvm::inconvertibleErrorCode());
705 if (!had_nt_regs || tid != thread_data.
tid)
706 return llvm::make_error<llvm::StringError>(
707 "Error parsing NetBSD core(5) notes: Unexpected order "
708 "of NOTEs PT_GETFPREG before PT_GETREG",
709 llvm::inconvertibleErrorCode());
710 thread_data.
notes.push_back(note);
724 return llvm::make_error<llvm::StringError>(
725 "Error parsing NetBSD core(5) notes: No threads information "
726 "specified in notes",
727 llvm::inconvertibleErrorCode());
730 return llvm::make_error<llvm::StringError>(
731 "Error parsing NetBSD core(5) notes: Mismatch between the number "
732 "of LWPs in netbsd_elfcore_procinfo and the number of LWPs specified "
734 llvm::inconvertibleErrorCode());
746 if (data.tid == siglwp) {
754 return llvm::make_error<llvm::StringError>(
755 "Error parsing NetBSD core(5) notes: Signal passed to unknown LWP",
756 llvm::inconvertibleErrorCode());
759 return llvm::Error::success();
764 for (
const auto ¬e : notes) {
767 if (!llvm::StringRef(note.info.n_name).startswith(
"OpenBSD"))
770 switch (note.info.n_type) {
781 thread_data.
notes.push_back(note);
786 return llvm::make_error<llvm::StringError>(
787 "Could not find general purpose registers note in core file.",
788 llvm::inconvertibleErrorCode());
791 return llvm::Error::success();
808 bool have_prstatus =
false;
809 bool have_prpsinfo =
false;
811 for (
const auto ¬e : notes) {
812 if (note.info.n_name !=
"CORE" && note.info.n_name !=
"LINUX")
815 if ((note.info.n_type == ELF::NT_PRSTATUS && have_prstatus) ||
816 (note.info.n_type == ELF::NT_PRPSINFO && have_prpsinfo)) {
821 have_prstatus =
false;
822 have_prpsinfo =
false;
825 switch (note.info.n_type) {
826 case ELF::NT_PRSTATUS: {
827 have_prstatus =
true;
835 size_t len = note.data.GetByteSize() - header_size;
839 case ELF::NT_PRPSINFO: {
840 have_prpsinfo =
true;
849 case ELF::NT_SIGINFO: {
860 const uint64_t count = note.data.GetAddress(&offset);
861 note.data.GetAddress(&offset);
862 for (uint64_t i = 0; i < count; ++i) {
864 entry.
start = note.data.GetAddress(&offset);
865 entry.
end = note.data.GetAddress(&offset);
866 entry.
file_ofs = note.data.GetAddress(&offset);
869 for (uint64_t i = 0; i < count; ++i) {
870 const char *path = note.data.GetCStr(&offset);
880 thread_data.
notes.push_back(note);
887 return llvm::Error::success();
896 assert(segment_header.
p_type == llvm::ELF::PT_NOTE);
900 return notes_or_error.takeError();
902 case llvm::Triple::FreeBSD:
904 case llvm::Triple::Linux:
906 case llvm::Triple::NetBSD:
908 case llvm::Triple::OpenBSD:
911 return llvm::make_error<llvm::StringError>(
912 "Don't know how to parse core file. Unsupported OS.",
913 llvm::inconvertibleErrorCode());
932 if (target_arch.
IsMIPS()) {
952 const bool add_exe_file_as_first_arg =
false;
954 add_exe_file_as_first_arg);