32 #include "llvm/BinaryFormat/Magic.h"
33 #include "llvm/Support/MemoryBuffer.h"
34 #include "llvm/Support/Threading.h"
42 using namespace minidump;
51 class PlaceholderObjectFile :
public ObjectFile {
53 PlaceholderObjectFile(
const lldb::ModuleSP &module_sp,
56 :
ObjectFile(module_sp, &module_spec.GetFileSpec(), 0,
58 m_arch(module_spec.GetArchitecture()), m_uuid(module_spec.GetUUID()),
59 m_base(base), m_size(size) {
60 m_symtab_up = std::make_unique<Symtab>(
this);
66 ConstString GetPluginName()
override {
return GetStaticPluginName(); }
67 uint32_t GetPluginVersion()
override {
return 1; }
68 bool ParseHeader()
override {
return true; }
69 Type CalculateType()
override {
return eTypeUnknown; }
70 Strata CalculateStrata()
override {
return eStrataUnknown; }
71 uint32_t GetDependentModules(FileSpecList &file_list)
override {
return 0; }
72 bool IsExecutable()
const override {
return false; }
73 ArchSpec GetArchitecture()
override {
return m_arch; }
74 UUID GetUUID()
override {
return m_uuid; }
75 Symtab *GetSymtab()
override {
return m_symtab_up.get(); }
76 bool IsStripped()
override {
return true; }
77 ByteOrder GetByteOrder()
const override {
return m_arch.GetByteOrder(); }
79 uint32_t GetAddressByteSize()
const override {
80 return m_arch.GetAddressByteSize();
83 Address GetBaseAddress()
override {
84 return Address(m_sections_up->GetSectionAtIndex(0), 0);
87 void CreateSections(
SectionList &unified_section_list)
override {
88 m_sections_up = std::make_unique<SectionList>();
89 auto section_sp = std::make_shared<Section>(
93 section_sp->SetPermissions(ePermissionsReadable | ePermissionsExecutable);
94 m_sections_up->AddSection(section_sp);
95 unified_section_list.
AddSection(std::move(section_sp));
99 bool value_is_offset)
override {
100 assert(!value_is_offset);
101 assert(value == m_base);
104 GetModule()->GetSectionList();
105 assert(m_sections_up->GetNumSections(0) == 1);
108 m_sections_up->GetSectionAtIndex(0), m_base);
112 void Dump(
Stream *s)
override {
113 s->
Format(
"Placeholder object file for {0} loaded at [{1:x}-{2:x})\n",
114 GetFileSpec(), m_base, m_base + m_size);
117 lldb::addr_t GetBaseImageAddress()
const {
return m_base; }
147 void HashElfTextSection(ModuleSP module_sp, std::vector<uint8_t> &breakpad_uuid,
148 std::vector<uint8_t> &facebook_uuid) {
149 SectionList *sect_list = module_sp->GetSectionList();
150 if (sect_list ==
nullptr)
155 constexpr
size_t kMDGUIDSize = 16;
156 constexpr
size_t kBreakpadPageSize = 4096;
161 const size_t text_size = sect_sp->GetFileSize();
162 const size_t read_size = std::min<size_t>(
163 llvm::alignTo(text_size, kMDGUIDSize), kBreakpadPageSize);
164 sect_sp->GetObjectFile()->GetData(sect_sp->GetFileOffset(), read_size, data);
166 breakpad_uuid.assign(kMDGUIDSize, 0);
167 facebook_uuid.assign(kMDGUIDSize, 0);
172 for (
size_t i = 0; i < kMDGUIDSize; i++)
173 facebook_uuid[i] ^= text_size % 255;
181 while (ptr < ptr_end) {
182 for (
unsigned i = 0; i < kMDGUIDSize; i++) {
183 breakpad_uuid[i] ^= ptr[i];
184 facebook_uuid[i] ^= ptr[i];
197 const char *ProcessMinidump::GetPluginDescriptionStatic() {
198 return "Minidump plug-in.";
201 lldb::ProcessSP ProcessMinidump::CreateInstance(lldb::TargetSP target_sp,
202 lldb::ListenerSP listener_sp,
205 if (!crash_file || can_connect)
208 lldb::ProcessSP process_sp;
210 constexpr
size_t header_size =
sizeof(Header);
211 auto DataPtr = FileSystem::Instance().CreateDataBuffer(crash_file->
GetPath(),
216 lldbassert(DataPtr->GetByteSize() == header_size);
217 if (identify_magic(toStringRef(DataPtr->GetData())) != llvm::file_magic::minidump)
221 FileSystem::Instance().CreateDataBuffer(crash_file->
GetPath(), -1, 0);
225 return std::make_shared<ProcessMinidump>(target_sp, listener_sp, *crash_file,
229 bool ProcessMinidump::CanDebug(lldb::TargetSP target_sp,
230 bool plugin_specified_by_name) {
234 ProcessMinidump::ProcessMinidump(lldb::TargetSP target_sp,
235 lldb::ListenerSP listener_sp,
237 DataBufferSP core_data)
239 m_core_data(std::move(core_data)), m_is_wow64(false) {}
251 static llvm::once_flag g_once_flag;
253 llvm::call_once(g_once_flag, []() {
266 if (!expected_parser)
267 return Status(expected_parser.takeError());
275 case llvm::Triple::x86:
276 case llvm::Triple::x86_64:
277 case llvm::Triple::arm:
278 case llvm::Triple::aarch64:
283 error.SetErrorStringWithFormat(
"unsupported minidump architecture: %s",
299 "Unable to retrieve process ID from minidump file, setting process ID "
303 SetID(pid.getValue());
319 constexpr
uint32_t BreakpadDumpRequested = 0xFFFFFFFF;
321 BreakpadDumpRequested) {
334 lldb::StopInfoSP stop_info;
335 lldb::ThreadSP stop_thread;
341 if (arch.
GetTriple().getOS() == llvm::Triple::Linux) {
350 *stop_thread, signo);
351 }
else if (arch.
GetTriple().getVendor() == llvm::Triple::Apple) {
358 llvm::raw_string_ostream desc_stream(desc);
359 desc_stream <<
"Exception "
362 <<
" encountered at address "
366 *stop_thread, desc_stream.str().c_str());
369 stop_thread->SetStopInfo(stop_info);
388 error.SetErrorString(
"could not parse memory info");
392 std::memcpy(buf, mem.data(), mem.size());
402 triple.setVendor(llvm::Triple::VendorType::UnknownVendor);
403 triple.setArch(llvm::Triple::ArchType::x86);
404 triple.setOS(llvm::Triple::OSType::Win32);
422 modules.
ForEach([&](
const ModuleSP &module_sp) {
423 SectionList *sections = module_sp->GetSectionList();
424 for (
size_t i = 0; i < sections->
GetSize(); ++i) {
430 section_sp->GetByteSize());
436 to_add.emplace_back();
437 to_add.back().GetRange() = section_range;
438 to_add.back().SetLLDBPermissions(section_sp->GetPermissions());
440 to_add.back().SetName(module_sp->GetFileSpec().GetPath().c_str());
468 LocationDescriptor context_location = thread.Context;
476 llvm::ArrayRef<uint8_t> context;
482 lldb::ThreadSP thread_sp(
new ThreadMinidump(*
this, thread, context));
485 return new_thread_list.
GetSize(
false) > 0;
489 llvm::StringRef name,
500 const auto dmp_bytes = minidump_uuid.
GetBytes();
501 const auto mod_bytes = module_sp->GetUUID().GetBytes();
502 const bool match = dmp_bytes.empty() || mod_bytes.empty() ||
503 mod_bytes.take_front(dmp_bytes.size()) == dmp_bytes;
505 LLDB_LOG(log,
"Partial uuid match for {0}.", name);
516 std::vector<uint8_t> breakpad_uuid;
517 std::vector<uint8_t> facebook_uuid;
518 HashElfTextSection(module_sp, breakpad_uuid, facebook_uuid);
519 if (dmp_bytes == llvm::ArrayRef<uint8_t>(breakpad_uuid)) {
520 LLDB_LOG(log,
"Breakpad .text hash match for {0}.", name);
523 if (dmp_bytes == llvm::ArrayRef<uint8_t>(facebook_uuid)) {
524 LLDB_LOG(log,
"Facebook .text hash match for {0}.", name);
536 std::vector<const minidump::Module *> filtered_modules =
541 for (
auto module : filtered_modules) {
543 module->ModuleNameRVA));
544 const uint64_t load_addr = module->BaseOfImage;
545 const uint64_t load_size = module->SizeOfImage;
546 LLDB_LOG(log,
"found module: name: {0} {1:x10}-{2:x10} size: {3}", name,
547 load_addr, load_addr + load_size, load_size);
551 if (llvm::StringRef(name).endswith_lower(
"wow64.dll")) {
565 LLDB_LOG(log,
"Full uuid match for {0}.", name);
586 auto *objfile = module_sp->GetObjectFile();
587 if (objfile && objfile->GetPluginName() ==
588 PlaceholderObjectFile::GetStaticPluginName()) {
589 if (((PlaceholderObjectFile *)objfile)->GetBaseImageAddress() !=
603 "Unable to locate the matching object file, creating a "
604 "placeholder module for: {0}",
607 module_sp = Module::CreateModuleFromObjectFile<PlaceholderObjectFile>(
608 module_spec, load_addr, load_size);
612 bool load_addr_changed =
false;
613 module_sp->SetLoadAddress(
GetTarget(), load_addr,
false,
624 const bool add_exe_file_as_first_arg =
false;
626 add_exe_file_as_first_arg);
642 #define INIT_BOOL(VAR, LONG, SHORT, DESC) \
643 VAR(LLDB_OPT_SET_1, false, LONG, SHORT, DESC, false, true)
644 #define APPEND_OPT(VAR) \
645 m_option_group.Append(&VAR, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1)
717 return DumpLinux() ||
721 return DumpLinux() ||
725 return DumpLinux() ||
729 return DumpLinux() ||
733 return DumpLinux() ||
737 return DumpLinux() ||
741 return DumpLinux() ||
745 return DumpLinux() ||
749 return DumpLinux() ||
753 return DumpLinux() ||
795 "Dump information from the minidump file.", nullptr),
798 "Dump the everything in the minidump."),
799 INIT_BOOL(m_dump_directory,
"directory",
'd',
800 "Dump the minidump directory map."),
801 INIT_BOOL(m_dump_linux_cpuinfo,
"cpuinfo",
'C',
802 "Dump linux /proc/cpuinfo."),
803 INIT_BOOL(m_dump_linux_proc_status,
"status",
's',
804 "Dump linux /proc/<pid>/status."),
805 INIT_BOOL(m_dump_linux_lsb_release,
"lsb-release",
'r',
806 "Dump linux /etc/lsb-release."),
807 INIT_BOOL(m_dump_linux_cmdline,
"cmdline",
'c',
808 "Dump linux /proc/<pid>/cmdline."),
809 INIT_BOOL(m_dump_linux_environ,
"environ",
'e',
810 "Dump linux /proc/<pid>/environ."),
811 INIT_BOOL(m_dump_linux_auxv,
"auxv",
'x',
812 "Dump linux /proc/<pid>/auxv."),
813 INIT_BOOL(m_dump_linux_maps,
"maps",
'm',
814 "Dump linux /proc/<pid>/maps."),
815 INIT_BOOL(m_dump_linux_proc_stat,
"stat",
'S',
816 "Dump linux /proc/<pid>/stat."),
817 INIT_BOOL(m_dump_linux_proc_uptime,
"uptime",
'u',
818 "Dump linux process uptime."),
819 INIT_BOOL(m_dump_linux_proc_fd,
"fd",
'f',
820 "Dump linux /proc/<pid>/fd."),
821 INIT_BOOL(m_dump_linux_all,
"linux",
'l',
822 "Dump all linux streams."),
823 INIT_BOOL(m_fb_app_data,
"fb-app-data", 1,
824 "Dump Facebook application custom data."),
825 INIT_BOOL(m_fb_build_id,
"fb-build-id", 2,
826 "Dump the Facebook build ID."),
828 "Dump Facebook application version string."),
829 INIT_BOOL(m_fb_java_stack,
"fb-java-stack", 4,
830 "Dump Facebook java stack."),
831 INIT_BOOL(m_fb_dalvik,
"fb-dalvik-info", 5,
832 "Dump Facebook Dalvik info."),
833 INIT_BOOL(m_fb_unwind,
"fb-unwind-symbols", 6,
834 "Dump Facebook unwind symbols."),
835 INIT_BOOL(m_fb_error_log,
"fb-error-log", 7,
836 "Dump Facebook error log."),
837 INIT_BOOL(m_fb_app_state,
"fb-app-state-log", 8,
838 "Dump Facebook java stack."),
839 INIT_BOOL(m_fb_abort,
"fb-abort-reason", 9,
840 "Dump Facebook abort reason."),
841 INIT_BOOL(m_fb_thread,
"fb-thread-name", 10,
842 "Dump Facebook thread name."),
844 "Dump Facebook logcat."),
845 INIT_BOOL(m_fb_all,
"facebook", 12,
"Dump all Facebook streams.") {
886 SetDefaultOptionsIfNoneAreSet();
889 m_interpreter.GetExecutionContext().GetProcessPtr());
894 s.
Printf(
"RVA SIZE TYPE StreamType\n");
895 s.
Printf(
"---------- ---------- ---------- --------------------------\n");
898 "0x%8.8x 0x%8.8x 0x%8.8x %s\n", (
uint32_t)stream_desc.Location.RVA,
899 (
uint32_t)stream_desc.Location.DataSize,
900 (
unsigned)(StreamType)stream_desc.Type,
904 auto DumpTextStream = [&](StreamType stream_type,
905 llvm::StringRef label) ->
void {
906 auto bytes = minidump.
GetStream(stream_type);
907 if (!bytes.empty()) {
910 s.
Printf(
"%s:\n%s\n\n", label.data(), bytes.data());
913 auto DumpBinaryStream = [&](StreamType stream_type,
914 llvm::StringRef label) ->
void {
915 auto bytes = minidump.
GetStream(stream_type);
916 if (!bytes.empty()) {
919 s.
Printf(
"%s:\n", label.data());
923 bytes.size(), 16, 0, 0, 0);
928 if (DumpLinuxCPUInfo())
929 DumpTextStream(StreamType::LinuxCPUInfo,
"/proc/cpuinfo");
930 if (DumpLinuxProcStatus())
931 DumpTextStream(StreamType::LinuxProcStatus,
"/proc/PID/status");
932 if (DumpLinuxLSBRelease())
933 DumpTextStream(StreamType::LinuxLSBRelease,
"/etc/lsb-release");
934 if (DumpLinuxCMDLine())
935 DumpTextStream(StreamType::LinuxCMDLine,
"/proc/PID/cmdline");
936 if (DumpLinuxEnviron())
937 DumpTextStream(StreamType::LinuxEnviron,
"/proc/PID/environ");
939 DumpBinaryStream(StreamType::LinuxAuxv,
"/proc/PID/auxv");
941 DumpTextStream(StreamType::LinuxMaps,
"/proc/PID/maps");
942 if (DumpLinuxProcStat())
943 DumpTextStream(StreamType::LinuxProcStat,
"/proc/PID/stat");
944 if (DumpLinuxProcUptime())
945 DumpTextStream(StreamType::LinuxProcUptime,
"uptime");
946 if (DumpLinuxProcFD())
947 DumpTextStream(StreamType::LinuxProcFD,
"/proc/PID/fd");
948 if (DumpFacebookAppData())
949 DumpTextStream(StreamType::FacebookAppCustomData,
950 "Facebook App Data");
951 if (DumpFacebookBuildID()) {
952 auto bytes = minidump.
GetStream(StreamType::FacebookBuildID);
953 if (bytes.size() >= 4) {
958 s.
Printf(
"Facebook Build ID:\n");
959 s.
Printf(
"%u\n", build_id);
963 if (DumpFacebookVersionName())
964 DumpTextStream(StreamType::FacebookAppVersionName,
965 "Facebook Version String");
966 if (DumpFacebookJavaStack())
967 DumpTextStream(StreamType::FacebookJavaStack,
968 "Facebook Java Stack");
969 if (DumpFacebookDalvikInfo())
970 DumpTextStream(StreamType::FacebookDalvikInfo,
971 "Facebook Dalvik Info");
972 if (DumpFacebookUnwindSymbols())
973 DumpBinaryStream(StreamType::FacebookUnwindSymbols,
974 "Facebook Unwind Symbols Bytes");
975 if (DumpFacebookErrorLog())
976 DumpTextStream(StreamType::FacebookDumpErrorLog,
977 "Facebook Error Log");
978 if (DumpFacebookAppStateLog())
979 DumpTextStream(StreamType::FacebookAppStateLog,
980 "Faceook Application State Log");
981 if (DumpFacebookAbortReason())
982 DumpTextStream(StreamType::FacebookAbortReason,
983 "Facebook Abort Reason");
984 if (DumpFacebookThreadName())
985 DumpTextStream(StreamType::FacebookThreadName,
986 "Facebook Thread Name");
987 if (DumpFacebookLogcat())
988 DumpTextStream(StreamType::FacebookLogcat,
998 "Commands for operating on a ProcessMinidump process.",
999 "process plugin <subcommand> [<subcommand-options>]") {
1000 LoadSubCommand(
"dump",
1009 m_command_sp = std::make_shared<CommandObjectMultiwordProcessMinidump>(
1010 GetTarget().GetDebugger().GetCommandInterpreter());