1 //===-- ProcessMinidump.cpp -------------------------------------*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 
10 // Project includes
11 #include "ProcessMinidump.h"
12 #include "ThreadMinidump.h"
13 
14 // Other libraries and framework includes
15 #include "lldb/Core/Module.h"
16 #include "lldb/Core/ModuleSpec.h"
17 #include "lldb/Core/PluginManager.h"
18 #include "lldb/Core/Section.h"
19 #include "lldb/Core/State.h"
20 #include "lldb/Target/DynamicLoader.h"
21 #include "lldb/Target/MemoryRegionInfo.h"
22 #include "lldb/Target/SectionLoadList.h"
23 #include "lldb/Target/Target.h"
24 #include "lldb/Target/UnixSignals.h"
25 #include "lldb/Utility/DataBufferLLVM.h"
26 #include "lldb/Utility/LLDBAssert.h"
27 #include "lldb/Utility/Log.h"
28 
29 #include "llvm/Support/MemoryBuffer.h"
30 #include "llvm/Support/Threading.h"
31 
32 // C includes
33 // C++ includes
34 
35 using namespace lldb;
36 using namespace lldb_private;
37 using namespace minidump;
38 
39 //------------------------------------------------------------------
40 /// A placeholder module used for minidumps, where the original
41 /// object files may not be available (so we can't parse the object
42 /// files to extract the set of sections/segments)
43 ///
44 /// This placeholder module has a single synthetic section (.module_image)
45 /// which represents the module memory range covering the whole module.
46 //------------------------------------------------------------------
47 class PlaceholderModule : public Module {
48 public:
49   PlaceholderModule(const FileSpec &file_spec, const ArchSpec &arch) :
50     Module(file_spec, arch) {}
51 
52   // Creates a synthetic module section covering the whole module image
53   // (and sets the section load address as well)
54   void CreateImageSection(const MinidumpModule *module, Target& target) {
55     const ConstString section_name(".module_image");
56     lldb::SectionSP section_sp(new Section(
57         shared_from_this(),     // Module to which this section belongs.
58         nullptr,                // ObjectFile
59         0,                      // Section ID.
60         section_name,           // Section name.
61         eSectionTypeContainer,  // Section type.
62         module->base_of_image,  // VM address.
63         module->size_of_image,  // VM size in bytes of this section.
64         0,                      // Offset of this section in the file.
65         module->size_of_image,  // Size of the section as found in the file.
66         12,                     // Alignment of the section (log2)
67         0,                      // Flags for this section.
68         1));                    // Number of host bytes per target byte
69     section_sp->SetPermissions(ePermissionsExecutable | ePermissionsReadable);
70     GetSectionList()->AddSection(section_sp);
71     target.GetSectionLoadList().SetSectionLoadAddress(
72         section_sp, module->base_of_image);
73   }
74 
75   ObjectFile *GetObjectFile() override { return nullptr; }
76 
77   SectionList *GetSectionList() override {
78     return Module::GetUnifiedSectionList();
79   }
80 };
81 
82 ConstString ProcessMinidump::GetPluginNameStatic() {
83   static ConstString g_name("minidump");
84   return g_name;
85 }
86 
87 const char *ProcessMinidump::GetPluginDescriptionStatic() {
88   return "Minidump plug-in.";
89 }
90 
91 lldb::ProcessSP ProcessMinidump::CreateInstance(lldb::TargetSP target_sp,
92                                                 lldb::ListenerSP listener_sp,
93                                                 const FileSpec *crash_file) {
94   if (!crash_file)
95     return nullptr;
96 
97   lldb::ProcessSP process_sp;
98   // Read enough data for the Minidump header
99   constexpr size_t header_size = sizeof(MinidumpHeader);
100   auto DataPtr =
101       DataBufferLLVM::CreateSliceFromPath(crash_file->GetPath(), header_size, 0);
102   if (!DataPtr)
103     return nullptr;
104 
105   assert(DataPtr->GetByteSize() == header_size);
106 
107   // first, only try to parse the header, beacuse we need to be fast
108   llvm::ArrayRef<uint8_t> HeaderBytes = DataPtr->GetData();
109   const MinidumpHeader *header = MinidumpHeader::Parse(HeaderBytes);
110   if (header == nullptr)
111     return nullptr;
112 
113   auto AllData = DataBufferLLVM::CreateSliceFromPath(crash_file->GetPath(), -1, 0);
114   if (!AllData)
115     return nullptr;
116 
117   auto minidump_parser = MinidumpParser::Create(AllData);
118   // check if the parser object is valid
119   if (!minidump_parser)
120     return nullptr;
121 
122   return std::make_shared<ProcessMinidump>(target_sp, listener_sp, *crash_file,
123                                            minidump_parser.getValue());
124 }
125 
126 bool ProcessMinidump::CanDebug(lldb::TargetSP target_sp,
127                                bool plugin_specified_by_name) {
128   return true;
129 }
130 
131 ProcessMinidump::ProcessMinidump(lldb::TargetSP target_sp,
132                                  lldb::ListenerSP listener_sp,
133                                  const FileSpec &core_file,
134                                  MinidumpParser minidump_parser)
135     : Process(target_sp, listener_sp), m_minidump_parser(minidump_parser),
136       m_core_file(core_file), m_is_wow64(false) {}
137 
138 ProcessMinidump::~ProcessMinidump() {
139   Clear();
140   // We need to call finalize on the process before destroying ourselves
141   // to make sure all of the broadcaster cleanup goes as planned. If we
142   // destruct this class, then Process::~Process() might have problems
143   // trying to fully destroy the broadcaster.
144   Finalize();
145 }
146 
147 void ProcessMinidump::Initialize() {
148   static llvm::once_flag g_once_flag;
149 
150   llvm::call_once(g_once_flag, []() {
151     PluginManager::RegisterPlugin(GetPluginNameStatic(),
152                                   GetPluginDescriptionStatic(),
153                                   ProcessMinidump::CreateInstance);
154   });
155 }
156 
157 void ProcessMinidump::Terminate() {
158   PluginManager::UnregisterPlugin(ProcessMinidump::CreateInstance);
159 }
160 
161 Status ProcessMinidump::DoLoadCore() {
162   Status error;
163 
164   m_thread_list = m_minidump_parser.GetThreads();
165   m_active_exception = m_minidump_parser.GetExceptionStream();
166   ReadModuleList();
167   GetTarget().SetArchitecture(GetArchitecture());
168 
169   llvm::Optional<lldb::pid_t> pid = m_minidump_parser.GetPid();
170   if (!pid) {
171     error.SetErrorString("failed to parse PID");
172     return error;
173   }
174   SetID(pid.getValue());
175 
176   return error;
177 }
178 
179 DynamicLoader *ProcessMinidump::GetDynamicLoader() {
180   if (m_dyld_ap.get() == nullptr)
181     m_dyld_ap.reset(DynamicLoader::FindPlugin(this, nullptr));
182   return m_dyld_ap.get();
183 }
184 
185 ConstString ProcessMinidump::GetPluginName() { return GetPluginNameStatic(); }
186 
187 uint32_t ProcessMinidump::GetPluginVersion() { return 1; }
188 
189 Status ProcessMinidump::DoDestroy() { return Status(); }
190 
191 void ProcessMinidump::RefreshStateAfterStop() {
192   if (!m_active_exception)
193     return;
194 
195   if (m_active_exception->exception_record.exception_code ==
196       MinidumpException::DumpRequested) {
197     return;
198   }
199 
200   lldb::StopInfoSP stop_info;
201   lldb::ThreadSP stop_thread;
202 
203   Process::m_thread_list.SetSelectedThreadByID(m_active_exception->thread_id);
204   stop_thread = Process::m_thread_list.GetSelectedThread();
205   ArchSpec arch = GetArchitecture();
206 
207   if (arch.GetTriple().getOS() == llvm::Triple::Linux) {
208     stop_info = StopInfo::CreateStopReasonWithSignal(
209         *stop_thread, m_active_exception->exception_record.exception_code);
210   } else {
211     std::string desc;
212     llvm::raw_string_ostream desc_stream(desc);
213     desc_stream << "Exception "
214                 << llvm::format_hex(
215                        m_active_exception->exception_record.exception_code, 8)
216                 << " encountered at address "
217                 << llvm::format_hex(
218                        m_active_exception->exception_record.exception_address,
219                        8);
220     stop_info = StopInfo::CreateStopReasonWithException(
221         *stop_thread, desc_stream.str().c_str());
222   }
223 
224   stop_thread->SetStopInfo(stop_info);
225 }
226 
227 bool ProcessMinidump::IsAlive() { return true; }
228 
229 bool ProcessMinidump::WarnBeforeDetach() const { return false; }
230 
231 size_t ProcessMinidump::ReadMemory(lldb::addr_t addr, void *buf, size_t size,
232                                    Status &error) {
233   // Don't allow the caching that lldb_private::Process::ReadMemory does
234   // since we have it all cached in our dump file anyway.
235   return DoReadMemory(addr, buf, size, error);
236 }
237 
238 size_t ProcessMinidump::DoReadMemory(lldb::addr_t addr, void *buf, size_t size,
239                                      Status &error) {
240 
241   llvm::ArrayRef<uint8_t> mem = m_minidump_parser.GetMemory(addr, size);
242   if (mem.empty()) {
243     error.SetErrorString("could not parse memory info");
244     return 0;
245   }
246 
247   std::memcpy(buf, mem.data(), mem.size());
248   return mem.size();
249 }
250 
251 ArchSpec ProcessMinidump::GetArchitecture() {
252   if (!m_is_wow64) {
253     return m_minidump_parser.GetArchitecture();
254   }
255 
256   llvm::Triple triple;
257   triple.setVendor(llvm::Triple::VendorType::UnknownVendor);
258   triple.setArch(llvm::Triple::ArchType::x86);
259   triple.setOS(llvm::Triple::OSType::Win32);
260   return ArchSpec(triple);
261 }
262 
263 Status ProcessMinidump::GetMemoryRegionInfo(lldb::addr_t load_addr,
264                                             MemoryRegionInfo &range_info) {
265   Status error;
266   auto info = m_minidump_parser.GetMemoryRegionInfo(load_addr);
267   if (!info) {
268     error.SetErrorString("No valid MemoryRegionInfo found!");
269     return error;
270   }
271   range_info = info.getValue();
272   return error;
273 }
274 
275 void ProcessMinidump::Clear() { Process::m_thread_list.Clear(); }
276 
277 bool ProcessMinidump::UpdateThreadList(ThreadList &old_thread_list,
278                                        ThreadList &new_thread_list) {
279   uint32_t num_threads = 0;
280   if (m_thread_list.size() > 0)
281     num_threads = m_thread_list.size();
282 
283   for (lldb::tid_t tid = 0; tid < num_threads; ++tid) {
284     llvm::ArrayRef<uint8_t> context;
285     if (!m_is_wow64)
286       context = m_minidump_parser.GetThreadContext(m_thread_list[tid]);
287     else
288       context = m_minidump_parser.GetThreadContextWow64(m_thread_list[tid]);
289 
290     lldb::ThreadSP thread_sp(
291         new ThreadMinidump(*this, m_thread_list[tid], context));
292     new_thread_list.AddThread(thread_sp);
293   }
294   return new_thread_list.GetSize(false) > 0;
295 }
296 
297 void ProcessMinidump::ReadModuleList() {
298   std::vector<const MinidumpModule *> filtered_modules =
299       m_minidump_parser.GetFilteredModuleList();
300 
301   for (auto module : filtered_modules) {
302     llvm::Optional<std::string> name =
303         m_minidump_parser.GetMinidumpString(module->module_name_rva);
304 
305     if (!name)
306       continue;
307 
308     Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_MODULES));
309     if (log) {
310       log->Printf("ProcessMinidump::%s found module: name: %s %#010" PRIx64
311                   "-%#010" PRIx64 " size: %" PRIu32,
312                   __FUNCTION__, name.getValue().c_str(),
313                   uint64_t(module->base_of_image),
314                   module->base_of_image + module->size_of_image,
315                   uint32_t(module->size_of_image));
316     }
317 
318     // check if the process is wow64 - a 32 bit windows process running on a
319     // 64 bit windows
320     if (llvm::StringRef(name.getValue()).endswith_lower("wow64.dll")) {
321       m_is_wow64 = true;
322     }
323 
324     const auto file_spec =
325         FileSpec(name.getValue(), true, GetArchitecture().GetTriple());
326     ModuleSpec module_spec = file_spec;
327     Status error;
328     lldb::ModuleSP module_sp = GetTarget().GetSharedModule(module_spec, &error);
329     if (!module_sp || error.Fail()) {
330       // We failed to locate a matching local object file. Fortunately,
331       // the minidump format encodes enough information about each module's
332       // memory range to allow us to create placeholder modules.
333       //
334       // This enables most LLDB functionality involving address-to-module
335       // translations (ex. identifing the module for a stack frame PC) and
336       // modules/sections commands (ex. target modules list, ...)
337       auto placeholder_module =
338           std::make_shared<PlaceholderModule>(file_spec, GetArchitecture());
339       placeholder_module->CreateImageSection(module, GetTarget());
340       module_sp = placeholder_module;
341       GetTarget().GetImages().Append(module_sp);
342     }
343 
344     if (log) {
345       log->Printf("ProcessMinidump::%s load module: name: %s", __FUNCTION__,
346                   name.getValue().c_str());
347     }
348 
349     bool load_addr_changed = false;
350     module_sp->SetLoadAddress(GetTarget(), module->base_of_image, false,
351                               load_addr_changed);
352   }
353 }
354 
355 bool ProcessMinidump::GetProcessInfo(ProcessInstanceInfo &info) {
356   info.Clear();
357   info.SetProcessID(GetID());
358   info.SetArchitecture(GetArchitecture());
359   lldb::ModuleSP module_sp = GetTarget().GetExecutableModule();
360   if (module_sp) {
361     const bool add_exe_file_as_first_arg = false;
362     info.SetExecutableFile(GetTarget().GetExecutableModule()->GetFileSpec(),
363                            add_exe_file_as_first_arg);
364   }
365   return true;
366 }
367