LLDB mainline
ObjectFilePECOFF.cpp
Go to the documentation of this file.
1//===-- ObjectFilePECOFF.cpp ----------------------------------------------===//
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 "ObjectFilePECOFF.h"
10#include "PECallFrameInfo.h"
11#include "WindowsMiniDump.h"
12
13#include "lldb/Core/Module.h"
16#include "lldb/Core/Section.h"
21#include "lldb/Target/Process.h"
23#include "lldb/Target/Target.h"
29#include "lldb/Utility/Log.h"
31#include "lldb/Utility/Timer.h"
32#include "lldb/Utility/UUID.h"
33
34#include "llvm/BinaryFormat/COFF.h"
35#include "llvm/Object/COFFImportFile.h"
36#include "llvm/Support/CRC.h"
37#include "llvm/Support/Error.h"
38#include "llvm/Support/FormatAdapters.h"
39#include "llvm/Support/MemoryBuffer.h"
40#include "llvm/TargetParser/Host.h"
41#include <optional>
42
43#define IMAGE_DOS_SIGNATURE 0x5A4D // MZ
44#define IMAGE_NT_SIGNATURE 0x00004550 // PE00
45#define OPT_HEADER_MAGIC_PE32 0x010b
46#define OPT_HEADER_MAGIC_PE32_PLUS 0x020b
47
48using namespace lldb;
49using namespace lldb_private;
50
52
53namespace {
54
55static constexpr OptionEnumValueElement g_abi_enums[] = {
56 {
57 llvm::Triple::UnknownEnvironment,
58 "default",
59 "Use default target (if it is Windows) or MSVC",
60 },
61 {
62 llvm::Triple::MSVC,
63 "msvc",
64 "MSVC ABI",
65 },
66 {
67 llvm::Triple::GNU,
68 "gnu",
69 "MinGW / Itanium ABI",
70 },
71};
72
73#define LLDB_PROPERTIES_objectfilepecoff
74#include "ObjectFilePECOFFProperties.inc"
75
76enum {
77#define LLDB_PROPERTIES_objectfilepecoff
78#include "ObjectFilePECOFFPropertiesEnum.inc"
79};
80
81class PluginProperties : public Properties {
82public:
83 static llvm::StringRef GetSettingName() {
85 }
86
87 PluginProperties() {
88 m_collection_sp = std::make_shared<OptionValueProperties>(GetSettingName());
89 m_collection_sp->Initialize(g_objectfilepecoff_properties_def);
90 }
91
92 llvm::Triple::EnvironmentType ABI() const {
93 return GetPropertyAtIndexAs<llvm::Triple::EnvironmentType>(
94 ePropertyABI, llvm::Triple::UnknownEnvironment);
95 }
96
97 OptionValueDictionary *ModuleABIMap() const {
98 return m_collection_sp->GetPropertyAtIndexAsOptionValueDictionary(
99 ePropertyModuleABIMap);
100 }
101};
102
103} // namespace
104
105static PluginProperties &GetGlobalPluginProperties() {
106 static PluginProperties g_settings;
107 return g_settings;
108}
109
110static bool GetDebugLinkContents(const llvm::object::COFFObjectFile &coff_obj,
111 std::string &gnu_debuglink_file,
112 uint32_t &gnu_debuglink_crc) {
113 static constexpr llvm::StringLiteral g_sect_name_gnu_debuglink(
114 ".gnu_debuglink");
115 for (const auto &section : coff_obj.sections()) {
116 auto name = section.getName();
117 if (!name) {
118 llvm::consumeError(name.takeError());
119 continue;
120 }
121 if (*name == g_sect_name_gnu_debuglink) {
122 auto content = section.getContents();
123 if (!content) {
124 llvm::consumeError(content.takeError());
125 return false;
126 }
127 DataExtractor data(
128 content->data(), content->size(),
129 coff_obj.isLittleEndian() ? eByteOrderLittle : eByteOrderBig, 4);
130 lldb::offset_t gnu_debuglink_offset = 0;
131 const char *file = data.GetCStr(&gnu_debuglink_offset);
132 if (!file)
133 return false;
134 gnu_debuglink_file = file;
135 // Align to the next 4-byte offset
136 gnu_debuglink_offset = llvm::alignTo(gnu_debuglink_offset, 4);
137 data.GetU32(&gnu_debuglink_offset, &gnu_debuglink_crc, 1);
138 return true;
139 }
140 }
141 return false;
142}
143
144static UUID GetCoffUUID(llvm::object::COFFObjectFile &coff_obj) {
145 const llvm::codeview::DebugInfo *pdb_info = nullptr;
146 llvm::StringRef pdb_file;
147
148 // First, prefer to use the PDB build id. LLD generates this even for mingw
149 // targets without PDB output, and it does not get stripped either.
150 if (!coff_obj.getDebugPDBInfo(pdb_info, pdb_file) && pdb_info) {
151 if (pdb_info->PDB70.CVSignature == llvm::OMF::Signature::PDB70) {
153 memcpy(&info.Uuid, pdb_info->PDB70.Signature, sizeof(info.Uuid));
154 info.Age = pdb_info->PDB70.Age;
155 return UUID(info);
156 }
157 }
158
159 std::string gnu_debuglink_file;
160 uint32_t gnu_debuglink_crc;
161
162 // The GNU linker normally does not write a PDB build id (unless requested
163 // with the --build-id option), so we should fall back to using the crc
164 // from .gnu_debuglink if it exists, just like how ObjectFileELF does it.
165 if (!GetDebugLinkContents(coff_obj, gnu_debuglink_file, gnu_debuglink_crc)) {
166 // If there is no .gnu_debuglink section, then this may be an object
167 // containing DWARF debug info for .gnu_debuglink, so calculate the crc of
168 // the object itself.
169 auto raw_data = coff_obj.getData();
171 "Calculating module crc32 %s with size %" PRIu64 " KiB",
172 FileSpec(coff_obj.getFileName()).GetFilename().str().c_str(),
173 static_cast<lldb::offset_t>(raw_data.size()) / 1024);
174 gnu_debuglink_crc = llvm::crc32(0, llvm::arrayRefFromStringRef(raw_data));
175 }
176 // Use 4 bytes of crc from the .gnu_debuglink section.
177 llvm::support::ulittle32_t data(gnu_debuglink_crc);
178 return UUID(&data, sizeof(data));
179}
180
182
189
192 debugger, PluginProperties::GetSettingName())) {
193 const bool is_global_setting = true;
195 debugger, GetGlobalPluginProperties().GetValueProperties(),
196 "Properties for the PE/COFF object-file plug-in.", is_global_setting);
197 }
198}
199
203
205 return "Portable Executable and Common Object File Format object file reader "
206 "(32 and 64 bit)";
207}
208
210 const lldb::ModuleSP &module_sp, DataExtractorSP extractor_sp,
211 lldb::offset_t data_offset, const lldb_private::FileSpec *file_p,
212 lldb::offset_t file_offset, lldb::offset_t length) {
213 FileSpec file = file_p ? *file_p : FileSpec();
214 if (!extractor_sp || !extractor_sp->HasData()) {
215 DataBufferSP data_sp = MapFileData(file, length, file_offset);
216 if (!data_sp)
217 return nullptr;
218 data_offset = 0;
219 extractor_sp = std::make_shared<DataExtractor>(data_sp);
220 }
221
222 if (!ObjectFilePECOFF::MagicBytesMatch(extractor_sp))
223 return nullptr;
224
225 // Update the data to contain the entire file if it doesn't already
226 if (extractor_sp->GetByteSize() < length) {
227 DataBufferSP data_sp = MapFileData(file, length, file_offset);
228 if (!data_sp)
229 return nullptr;
230 extractor_sp = std::make_shared<DataExtractor>(data_sp);
231 }
232
233 auto objfile_up = std::make_unique<ObjectFilePECOFF>(
234 module_sp, extractor_sp, data_offset, file_p, file_offset, length);
235 if (!objfile_up || !objfile_up->ParseHeader())
236 return nullptr;
237
238 // Cache coff binary.
239 if (!objfile_up->CreateBinary())
240 return nullptr;
241 return objfile_up.release();
242}
243
245 const lldb::ModuleSP &module_sp, lldb::WritableDataBufferSP data_sp,
246 const lldb::ProcessSP &process_sp, lldb::addr_t header_addr) {
247 if (!data_sp)
248 return nullptr;
249 DataExtractorSP extractor_sp =
250 std::make_shared<DataExtractor>(data_sp, eByteOrderLittle, 4);
251 if (!ObjectFilePECOFF::MagicBytesMatch(extractor_sp))
252 return nullptr;
253 auto objfile_up = std::make_unique<ObjectFilePECOFF>(
254 module_sp, data_sp, process_sp, header_addr);
255 if (objfile_up.get() && objfile_up->ParseHeader()) {
256 return objfile_up.release();
257 }
258 return nullptr;
259}
260
262 const lldb_private::FileSpec &file, lldb::DataExtractorSP &extractor_sp,
263 lldb::offset_t file_offset, lldb::offset_t length) {
264 if (!extractor_sp || !extractor_sp->HasData() ||
266 return {};
267
268 Log *log = GetLog(LLDBLog::Object);
269
270 if (extractor_sp->GetByteSize() < length)
271 if (DataBufferSP full_sp = MapFileData(file, -1, file_offset))
272 extractor_sp->SetData(std::move(full_sp));
273 auto binary = llvm::object::createBinary(llvm::MemoryBufferRef(
274 toStringRef(extractor_sp->GetSharedDataBuffer()->GetData()),
275 file.GetFilename()));
276
277 if (!binary) {
278 LLDB_LOG_ERROR(log, binary.takeError(),
279 "Failed to create binary for file ({1}): {0}", file);
280 return {};
281 }
282
283 auto *COFFObj = llvm::dyn_cast<llvm::object::COFFObjectFile>(binary->get());
284 if (!COFFObj)
285 return {};
286
287 ModuleSpec module_spec(file);
288 ArchSpec &spec = module_spec.GetArchitecture();
289 lldb_private::UUID &uuid = module_spec.GetUUID();
290 if (!uuid.IsValid())
291 uuid = GetCoffUUID(*COFFObj);
292
293 static llvm::Triple::EnvironmentType default_env = [] {
294 auto def_target = llvm::Triple(
295 llvm::Triple::normalize(llvm::sys::getDefaultTargetTriple()));
296 if (def_target.getOS() == llvm::Triple::Win32 &&
297 def_target.getEnvironment() != llvm::Triple::UnknownEnvironment)
298 return def_target.getEnvironment();
299 return llvm::Triple::MSVC;
300 }();
301
302 // Check for a module-specific override.
303 OptionValueSP module_env_option;
304 const auto *map = GetGlobalPluginProperties().ModuleABIMap();
305 if (map->GetNumValues() > 0) {
306 // Step 1: Try with the exact file name.
307 auto name = file.GetFilename();
308 module_env_option = map->GetValueForKey(name);
309 if (!module_env_option) {
310 // Step 2: Try with the file name in lowercase.
311 auto name_lower = name.lower();
312 module_env_option = map->GetValueForKey(llvm::StringRef(name_lower));
313 }
314 if (!module_env_option) {
315 // Step 3: Try with the file name with ".debug" suffix stripped.
316 auto name_stripped = name;
317 if (name_stripped.consume_back_insensitive(".debug")) {
318 module_env_option = map->GetValueForKey(name_stripped);
319 if (!module_env_option) {
320 // Step 4: Try with the file name in lowercase with ".debug" suffix
321 // stripped.
322 auto name_lower = name_stripped.lower();
323 module_env_option = map->GetValueForKey(llvm::StringRef(name_lower));
324 }
325 }
326 }
327 }
328 llvm::Triple::EnvironmentType env;
329 if (module_env_option)
330 env =
331 module_env_option->GetValueAs<llvm::Triple::EnvironmentType>().value_or(
332 static_cast<llvm::Triple::EnvironmentType>(0));
333 else
334 env = GetGlobalPluginProperties().ABI();
335
336 if (env == llvm::Triple::UnknownEnvironment)
337 env = default_env;
338
339 ModuleSpecList specs;
340 switch (COFFObj->getMachine()) {
341 case MachineAmd64:
342 spec.SetTriple("x86_64-pc-windows");
343 spec.GetTriple().setEnvironment(env);
344 specs.Append(module_spec);
345 break;
346 case MachineX86:
347 spec.SetTriple("i386-pc-windows");
348 spec.GetTriple().setEnvironment(env);
349 specs.Append(module_spec);
350 break;
351 case MachineArmNt:
352 spec.SetTriple("armv7-pc-windows");
353 spec.GetTriple().setEnvironment(env);
354 specs.Append(module_spec);
355 break;
356 case MachineArm64:
357 case MachineArm64X:
358 spec.SetTriple("aarch64-pc-windows");
359 spec.GetTriple().setEnvironment(env);
360 specs.Append(module_spec);
361 break;
362 default:
363 break;
364 }
365
366 return specs;
367}
368
372 // Outfile and process_sp are validated by PluginManager::SaveCore
373 assert(options.GetOutputFile().has_value());
374 assert(process_sp);
375 return SaveMiniDump(process_sp, options, error);
376}
377
379 lldb::offset_t offset = 0;
380 uint16_t magic = extractor_sp->GetU16(&offset);
381 return magic == IMAGE_DOS_SIGNATURE;
382}
383
385 // TODO: We need to complete this mapping of COFF symbol types to LLDB ones.
386 // For now, here's a hack to make sure our function have types.
387 const auto complex_type =
388 coff_symbol_type >> llvm::COFF::SCT_COMPLEX_TYPE_SHIFT;
389 if (complex_type == llvm::COFF::IMAGE_SYM_DTYPE_FUNCTION) {
391 }
392 const auto base_type = coff_symbol_type & 0xff;
393 if (base_type == llvm::COFF::IMAGE_SYM_TYPE_NULL &&
394 complex_type == llvm::COFF::IMAGE_SYM_DTYPE_NULL) {
395 // Unknown type. LLD and GNU ld uses this for variables on MinGW, so
396 // consider these symbols to be data to enable printing.
398 }
400}
401
403 if (m_binary)
404 return true;
405
406 Log *log = GetLog(LLDBLog::Object);
407
408 auto binary = llvm::object::createBinary(llvm::MemoryBufferRef(
409 toStringRef(m_data_nsp->GetData()), m_file.GetFilename()));
410 if (!binary) {
411 LLDB_LOG_ERROR(log, binary.takeError(),
412 "Failed to create binary for file ({1}): {0}", m_file);
413 return false;
414 }
415
416 // Make sure we only handle COFF format.
417 m_binary =
418 llvm::unique_dyn_cast<llvm::object::COFFObjectFile>(std::move(*binary));
419 if (!m_binary)
420 return false;
421
422 LLDB_LOG(log, "this = {0}, module = {1} ({2}), file = {3}, binary = {4}",
423 this, GetModule().get(), GetModule()->GetSpecificationDescription(),
424 m_file.GetPath(), m_binary.get());
425 return true;
426}
427
429 DataExtractorSP extractor_sp,
430 lldb::offset_t data_offset,
431 const FileSpec *file,
432 lldb::offset_t file_offset,
433 lldb::offset_t length)
434 : ObjectFile(module_sp, file, file_offset, length, extractor_sp,
435 data_offset),
438 m_deps_filespec() {}
439
441 WritableDataBufferSP header_data_sp,
442 const lldb::ProcessSP &process_sp,
443 addr_t header_addr)
444 : ObjectFile(module_sp, process_sp, header_addr,
445 std::make_shared<DataExtractor>(header_data_sp)),
448 m_deps_filespec() {}
449
451
453 ModuleSP module_sp(GetModule());
454 if (module_sp) {
455 std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex());
456 m_sect_headers.clear();
457 m_data_nsp->SetByteOrder(eByteOrderLittle);
458 lldb::offset_t offset = 0;
459
461 offset = m_dos_header.e_lfanew;
462 uint32_t pe_signature = m_data_nsp->GetU32(&offset);
463 if (pe_signature != IMAGE_NT_SIGNATURE)
464 return false;
465 if (ParseCOFFHeader(*m_data_nsp, &offset, m_coff_header)) {
466 if (m_coff_header.hdrsize > 0)
468 ParseSectionHeaders(offset);
469 }
470 m_data_nsp->SetAddressByteSize(GetAddressByteSize());
471 return true;
472 }
473 }
474 return false;
475}
476
478 bool value_is_offset) {
479 bool changed = false;
480 ModuleSP module_sp = GetModule();
481 if (module_sp) {
482 size_t num_loaded_sections = 0;
483 SectionList *section_list = GetSectionList();
484 if (section_list) {
485 if (!value_is_offset) {
486 value -= m_image_base;
487 }
488
489 const size_t num_sections = section_list->GetSize();
490 size_t sect_idx = 0;
491
492 for (sect_idx = 0; sect_idx < num_sections; ++sect_idx) {
493 // Iterate through the object file sections to find all of the sections
494 // that have SHF_ALLOC in their flag bits.
495 SectionSP section_sp(section_list->GetSectionAtIndex(sect_idx));
496 if (section_sp && !section_sp->IsThreadSpecific()) {
497 if (target.SetSectionLoadAddress(
498 section_sp, section_sp->GetFileAddress() + value))
499 ++num_loaded_sections;
500 }
501 }
502 changed = num_loaded_sections > 0;
503 }
504 }
505 return changed;
506}
507
509
511 return (m_coff_header.flags & llvm::COFF::IMAGE_FILE_DLL) == 0;
512}
513
516 return 8;
518 return 4;
519 return 4;
520}
521
522// NeedsEndianSwap
523//
524// Return true if an endian swap needs to occur when extracting data from this
525// file.
527#if defined(__LITTLE_ENDIAN__)
528 return false;
529#else
530 return true;
531#endif
532}
533// ParseDOSHeader
536 bool success = false;
537 lldb::offset_t offset = 0;
538 success = data.ValidOffsetForDataOfSize(0, sizeof(dos_header));
539
540 if (success) {
541 dos_header.e_magic = data.GetU16(&offset); // Magic number
543
544 if (success) {
545 dos_header.e_cblp = data.GetU16(&offset); // Bytes on last page of file
546 dos_header.e_cp = data.GetU16(&offset); // Pages in file
547 dos_header.e_crlc = data.GetU16(&offset); // Relocations
549 data.GetU16(&offset); // Size of header in paragraphs
551 data.GetU16(&offset); // Minimum extra paragraphs needed
553 data.GetU16(&offset); // Maximum extra paragraphs needed
554 dos_header.e_ss = data.GetU16(&offset); // Initial (relative) SS value
555 dos_header.e_sp = data.GetU16(&offset); // Initial SP value
556 dos_header.e_csum = data.GetU16(&offset); // Checksum
557 dos_header.e_ip = data.GetU16(&offset); // Initial IP value
558 dos_header.e_cs = data.GetU16(&offset); // Initial (relative) CS value
560 data.GetU16(&offset); // File address of relocation table
561 dos_header.e_ovno = data.GetU16(&offset); // Overlay number
562
563 dos_header.e_res[0] = data.GetU16(&offset); // Reserved words
564 dos_header.e_res[1] = data.GetU16(&offset); // Reserved words
565 dos_header.e_res[2] = data.GetU16(&offset); // Reserved words
566 dos_header.e_res[3] = data.GetU16(&offset); // Reserved words
567
569 data.GetU16(&offset); // OEM identifier (for e_oeminfo)
571 data.GetU16(&offset); // OEM information; e_oemid specific
572 dos_header.e_res2[0] = data.GetU16(&offset); // Reserved words
573 dos_header.e_res2[1] = data.GetU16(&offset); // Reserved words
574 dos_header.e_res2[2] = data.GetU16(&offset); // Reserved words
575 dos_header.e_res2[3] = data.GetU16(&offset); // Reserved words
576 dos_header.e_res2[4] = data.GetU16(&offset); // Reserved words
577 dos_header.e_res2[5] = data.GetU16(&offset); // Reserved words
578 dos_header.e_res2[6] = data.GetU16(&offset); // Reserved words
579 dos_header.e_res2[7] = data.GetU16(&offset); // Reserved words
580 dos_header.e_res2[8] = data.GetU16(&offset); // Reserved words
581 dos_header.e_res2[9] = data.GetU16(&offset); // Reserved words
582
584 data.GetU32(&offset); // File address of new exe header
585 }
586 }
587 if (!success)
588 memset(&dos_header, 0, sizeof(dos_header));
589 return success;
590}
591
592// ParserCOFFHeader
594 lldb::offset_t *offset_ptr,
596 bool success =
597 data.ValidOffsetForDataOfSize(*offset_ptr, sizeof(coff_header));
598 if (success) {
599 coff_header.machine = data.GetU16(offset_ptr);
600 coff_header.nsects = data.GetU16(offset_ptr);
601 coff_header.modtime = data.GetU32(offset_ptr);
602 coff_header.symoff = data.GetU32(offset_ptr);
603 coff_header.nsyms = data.GetU32(offset_ptr);
604 coff_header.hdrsize = data.GetU16(offset_ptr);
605 coff_header.flags = data.GetU16(offset_ptr);
606 }
607 if (!success)
608 memset(&coff_header, 0, sizeof(coff_header));
609 return success;
610}
611
613 bool success = false;
614 const lldb::offset_t end_offset = *offset_ptr + m_coff_header.hdrsize;
615 if (*offset_ptr < end_offset) {
616 success = true;
617 m_coff_header_opt.magic = m_data_nsp->GetU16(offset_ptr);
618 m_coff_header_opt.major_linker_version = m_data_nsp->GetU8(offset_ptr);
619 m_coff_header_opt.minor_linker_version = m_data_nsp->GetU8(offset_ptr);
620 m_coff_header_opt.code_size = m_data_nsp->GetU32(offset_ptr);
621 m_coff_header_opt.data_size = m_data_nsp->GetU32(offset_ptr);
622 m_coff_header_opt.bss_size = m_data_nsp->GetU32(offset_ptr);
623 m_coff_header_opt.entry = m_data_nsp->GetU32(offset_ptr);
624 m_coff_header_opt.code_offset = m_data_nsp->GetU32(offset_ptr);
625
626 const uint32_t addr_byte_size = GetAddressByteSize();
627
628 if (*offset_ptr < end_offset) {
630 // PE32 only
631 m_coff_header_opt.data_offset = m_data_nsp->GetU32(offset_ptr);
632 } else
633 m_coff_header_opt.data_offset = 0;
634
635 if (*offset_ptr < end_offset) {
636 m_coff_header_opt.image_base =
637 m_data_nsp->GetMaxU64(offset_ptr, addr_byte_size);
638 m_coff_header_opt.sect_alignment = m_data_nsp->GetU32(offset_ptr);
639 m_coff_header_opt.file_alignment = m_data_nsp->GetU32(offset_ptr);
640 m_coff_header_opt.major_os_system_version =
641 m_data_nsp->GetU16(offset_ptr);
642 m_coff_header_opt.minor_os_system_version =
643 m_data_nsp->GetU16(offset_ptr);
644 m_coff_header_opt.major_image_version = m_data_nsp->GetU16(offset_ptr);
645 m_coff_header_opt.minor_image_version = m_data_nsp->GetU16(offset_ptr);
646 m_coff_header_opt.major_subsystem_version =
647 m_data_nsp->GetU16(offset_ptr);
648 m_coff_header_opt.minor_subsystem_version =
649 m_data_nsp->GetU16(offset_ptr);
650 m_coff_header_opt.reserved1 = m_data_nsp->GetU32(offset_ptr);
651 m_coff_header_opt.image_size = m_data_nsp->GetU32(offset_ptr);
652 m_coff_header_opt.header_size = m_data_nsp->GetU32(offset_ptr);
653 m_coff_header_opt.checksum = m_data_nsp->GetU32(offset_ptr);
654 m_coff_header_opt.subsystem = m_data_nsp->GetU16(offset_ptr);
655 m_coff_header_opt.dll_flags = m_data_nsp->GetU16(offset_ptr);
656 m_coff_header_opt.stack_reserve_size =
657 m_data_nsp->GetMaxU64(offset_ptr, addr_byte_size);
658 m_coff_header_opt.stack_commit_size =
659 m_data_nsp->GetMaxU64(offset_ptr, addr_byte_size);
660 m_coff_header_opt.heap_reserve_size =
661 m_data_nsp->GetMaxU64(offset_ptr, addr_byte_size);
662 m_coff_header_opt.heap_commit_size =
663 m_data_nsp->GetMaxU64(offset_ptr, addr_byte_size);
664 m_coff_header_opt.loader_flags = m_data_nsp->GetU32(offset_ptr);
665 uint32_t num_data_dir_entries = m_data_nsp->GetU32(offset_ptr);
666 m_coff_header_opt.data_dirs.clear();
667 m_coff_header_opt.data_dirs.resize(num_data_dir_entries);
668 uint32_t i;
669 for (i = 0; i < num_data_dir_entries; i++) {
670 m_coff_header_opt.data_dirs[i].vmaddr =
671 m_data_nsp->GetU32(offset_ptr);
672 m_coff_header_opt.data_dirs[i].vmsize =
673 m_data_nsp->GetU32(offset_ptr);
674 }
675
676 m_image_base = m_coff_header_opt.image_base;
677 }
678 }
679 }
680 // Make sure we are on track for section data which follows
681 *offset_ptr = end_offset;
682 return success;
683}
684
685uint32_t ObjectFilePECOFF::GetRVA(const Address &addr) const {
686 return addr.GetFileAddress() - m_image_base;
687}
688
690 SectionList *sect_list = GetSectionList();
691 if (!sect_list)
692 return Address(GetFileAddress(rva));
693
694 return Address(GetFileAddress(rva), sect_list);
695}
696
698 return m_image_base + rva;
699}
700
701DataExtractor ObjectFilePECOFF::ReadImageData(uint32_t offset, size_t size) {
702 if (!size)
703 return {};
704
705 if (m_data_nsp->ValidOffsetForDataOfSize(offset, size))
706 return DataExtractor(*m_data_nsp, offset, size);
707
708 ProcessSP process_sp(m_process_wp.lock());
709 DataExtractor data;
710 if (process_sp) {
711 auto data_up = std::make_unique<DataBufferHeap>(size, 0);
712 Status readmem_error;
713 size_t bytes_read =
714 process_sp->ReadMemory(m_image_base + offset, data_up->GetBytes(),
715 data_up->GetByteSize(), readmem_error);
716 if (bytes_read == size) {
717 DataBufferSP buffer_sp(data_up.release());
718 data.SetData(buffer_sp, 0, buffer_sp->GetByteSize());
719 }
720 }
721 return data;
722}
723
725 Address addr = GetAddress(rva);
726 SectionSP sect = addr.GetSection();
727 if (!sect)
728 return {};
729 rva = sect->GetFileOffset() + addr.GetOffset();
730
731 return ReadImageData(rva, size);
732}
733
734// ParseSectionHeaders
736 uint32_t section_header_data_offset) {
737 const uint32_t nsects = m_coff_header.nsects;
738 m_sect_headers.clear();
739
740 if (nsects > 0) {
741 const size_t section_header_byte_size = nsects * sizeof(section_header_t);
742 DataExtractor section_header_data =
743 ReadImageData(section_header_data_offset, section_header_byte_size);
744
745 lldb::offset_t offset = 0;
746 if (section_header_data.ValidOffsetForDataOfSize(
747 offset, section_header_byte_size)) {
748 m_sect_headers.resize(nsects);
749
750 for (uint32_t idx = 0; idx < nsects; ++idx) {
751 const void *name_data = section_header_data.GetData(&offset, 8);
752 if (name_data) {
753 memcpy(m_sect_headers[idx].name, name_data, 8);
754 m_sect_headers[idx].vmsize = section_header_data.GetU32(&offset);
755 m_sect_headers[idx].vmaddr = section_header_data.GetU32(&offset);
756 m_sect_headers[idx].size = section_header_data.GetU32(&offset);
757 m_sect_headers[idx].offset = section_header_data.GetU32(&offset);
758 m_sect_headers[idx].reloff = section_header_data.GetU32(&offset);
759 m_sect_headers[idx].lineoff = section_header_data.GetU32(&offset);
760 m_sect_headers[idx].nreloc = section_header_data.GetU16(&offset);
761 m_sect_headers[idx].nline = section_header_data.GetU16(&offset);
762 m_sect_headers[idx].flags = section_header_data.GetU32(&offset);
763 }
764 }
765 }
766 }
767
768 return !m_sect_headers.empty();
769}
770
772 llvm::StringRef hdr_name(sect.name, std::size(sect.name));
773 hdr_name = hdr_name.split('\0').first;
774 if (hdr_name.consume_front("/")) {
775 lldb::offset_t stroff;
776 if (!to_integer(hdr_name, stroff, 10))
777 return "";
778 lldb::offset_t string_file_offset =
779 m_coff_header.symoff + (m_coff_header.nsyms * 18) + stroff;
780 if (const char *name = m_data_nsp->GetCStr(&string_file_offset))
781 return name;
782 return "";
783 }
784 return hdr_name;
785}
786
788 SectionList *sect_list = GetSectionList();
789 rva_symbol_list_t sorted_exports = AppendFromExportTable(sect_list, symtab);
790 AppendFromCOFFSymbolTable(sect_list, symtab, sorted_exports);
791}
792
793static bool RVASymbolListCompareRVA(const std::pair<uint32_t, uint32_t> &a,
794 const std::pair<uint32_t, uint32_t> &b) {
795 return a.first < b.first;
796}
797
799 SectionList *sect_list, Symtab &symtab,
800 const ObjectFilePECOFF::rva_symbol_list_t &sorted_exports) {
801 const uint32_t num_syms = m_binary->getNumberOfSymbols();
802 if (num_syms == 0)
803 return;
804 // Check that this is not a bigobj; we do not support bigobj.
805 if (m_binary->getSymbolTableEntrySize() !=
806 sizeof(llvm::object::coff_symbol16))
807 return;
808
809 Log *log = GetLog(LLDBLog::Object);
810 symtab.Reserve(symtab.GetNumSymbols() + num_syms);
811 for (const auto &sym_ref : m_binary->symbols()) {
812 const auto coff_sym_ref = m_binary->getCOFFSymbol(sym_ref);
813 auto name_or_error = sym_ref.getName();
814 if (!name_or_error) {
815 LLDB_LOG_ERROR(log, name_or_error.takeError(),
816 "ObjectFilePECOFF::AppendFromCOFFSymbolTable - failed to "
817 "get symbol table entry name: {0}");
818 continue;
819 }
820 const llvm::StringRef sym_name = *name_or_error;
821 Symbol symbol;
822 symbol.GetMangled().SetValue(ConstString(sym_name));
823 int16_t section_number =
824 static_cast<int16_t>(coff_sym_ref.getSectionNumber());
825 if (section_number >= 1) {
826 symbol.GetAddressRef() = Address(
827 sect_list->FindSectionByID(section_number), coff_sym_ref.getValue());
828 const auto symbol_type = MapSymbolType(coff_sym_ref.getType());
829 symbol.SetType(symbol_type);
830
831 // Check for duplicate of exported symbols:
832 const uint32_t symbol_rva = symbol.GetAddressRef().GetFileAddress() -
833 m_coff_header_opt.image_base;
834 const auto &first_match = std::lower_bound(
835 sorted_exports.begin(), sorted_exports.end(),
836 std::make_pair(symbol_rva, 0), RVASymbolListCompareRVA);
837 for (auto it = first_match;
838 it != sorted_exports.end() && it->first == symbol_rva; ++it) {
839 Symbol *exported = symtab.SymbolAtIndex(it->second);
840 if (symbol_type != lldb::eSymbolTypeInvalid)
841 exported->SetType(symbol_type);
842 if (exported->GetMangled() == symbol.GetMangled()) {
843 symbol.SetExternal(true);
844 // We don't want the symbol to be duplicated (e.g. when running
845 // `disas -n func`), but we also don't want to erase this entry (to
846 // preserve the original symbol order), so we mark it as additional.
848 } else {
849 // It is possible for a symbol to be exported in a different name
850 // from its original. In this case keep both entries so lookup using
851 // either names will work. If this symbol has an invalid type, replace
852 // it with the type from the export symbol.
853 if (symbol.GetType() == lldb::eSymbolTypeInvalid)
854 symbol.SetType(exported->GetType());
855 }
856 }
857 } else if (section_number == llvm::COFF::IMAGE_SYM_ABSOLUTE) {
858 symbol.GetAddressRef() = Address(coff_sym_ref.getValue());
860 }
861 symtab.AddSymbol(symbol);
862 }
863}
864
867 Symtab &symtab) {
868 const auto *export_table = m_binary->getExportTable();
869 if (!export_table)
870 return {};
871 const uint32_t num_syms = export_table->AddressTableEntries;
872 if (num_syms == 0)
873 return {};
874
875 Log *log = GetLog(LLDBLog::Object);
876 rva_symbol_list_t export_list;
877 symtab.Reserve(symtab.GetNumSymbols() + num_syms);
878 // Read each export table entry, ordered by ordinal instead of by name.
879 for (const auto &entry : m_binary->export_directories()) {
880 llvm::StringRef sym_name;
881 if (auto err = entry.getSymbolName(sym_name)) {
882 LLDB_LOG_ERROR(log, std::move(err),
883 "ObjectFilePECOFF::AppendFromExportTable - failed to get "
884 "export table entry name: {0}");
885 continue;
886 }
887 Symbol symbol;
888 // Note: symbol name may be empty if it is only exported by ordinal.
889 symbol.GetMangled().SetValue(ConstString(sym_name));
890
891 uint32_t ordinal;
892 llvm::cantFail(entry.getOrdinal(ordinal));
893 symbol.SetID(ordinal);
894
895 bool is_forwarder;
896 llvm::cantFail(entry.isForwarder(is_forwarder));
897 if (is_forwarder) {
898 // Forwarder exports are redirected by the loader transparently, but keep
899 // it in symtab and make a note using the symbol name.
900 llvm::StringRef forwarder_name;
901 if (auto err = entry.getForwardTo(forwarder_name)) {
902 LLDB_LOG_ERROR(log, std::move(err),
903 "ObjectFilePECOFF::AppendFromExportTable - failed to "
904 "get forwarder name of forwarder export '{1}': {0}",
905 sym_name);
906 continue;
907 }
908 llvm::SmallString<256> new_name = {symbol.GetDisplayName().GetStringRef(),
909 " (forwarded to ", forwarder_name,
910 ")"};
911 symbol.GetMangled().SetDemangledName(ConstString(new_name.str()));
913 }
914
915 uint32_t function_rva;
916 if (auto err = entry.getExportRVA(function_rva)) {
917 LLDB_LOG_ERROR(log, std::move(err),
918 "ObjectFilePECOFF::AppendFromExportTable - failed to get "
919 "address of export entry '{1}': {0}",
920 sym_name);
921 continue;
922 }
923 // Skip the symbol if it doesn't look valid.
924 if (function_rva == 0 && sym_name.empty())
925 continue;
926 symbol.GetAddressRef() =
927 Address(m_coff_header_opt.image_base + function_rva, sect_list);
928
929 // An exported symbol may be either code or data. Guess by checking whether
930 // the section containing the symbol is executable.
932 if (!is_forwarder)
933 if (auto section_sp = symbol.GetAddressRef().GetSection())
934 if (section_sp->GetPermissions() & ePermissionsExecutable)
936 symbol.SetExternal(true);
937 uint32_t idx = symtab.AddSymbol(symbol);
938 export_list.push_back(std::make_pair(function_rva, idx));
939 }
940 llvm::stable_sort(export_list, RVASymbolListCompareRVA);
941 return export_list;
942}
943
944std::unique_ptr<CallFrameInfo> ObjectFilePECOFF::CreateCallFrameInfo() {
945 if (llvm::COFF::EXCEPTION_TABLE >= m_coff_header_opt.data_dirs.size())
946 return {};
947
948 data_directory data_dir_exception =
949 m_coff_header_opt.data_dirs[llvm::COFF::EXCEPTION_TABLE];
950 if (!data_dir_exception.vmaddr)
951 return {};
952
953 // TODO: decode ARM64 .pdata/.xdata so optimized frameless code unwinds.
954 if (m_coff_header.machine != llvm::COFF::IMAGE_FILE_MACHINE_AMD64)
955 return {};
956
957 return std::make_unique<PECallFrameInfo>(*this, data_dir_exception.vmaddr,
958 data_dir_exception.vmsize);
959}
960
963 if (m_binary->is64()) {
964 if (m_binary->getTLSDirectory64())
965 addr = m_binary->getTLSDirectory64()->AddressOfIndex.value();
966 } else if (m_binary->getTLSDirectory32())
967 addr = m_binary->getTLSDirectory32()->AddressOfIndex.value();
968
969 if (addr == 0)
971 return addr;
972}
973
975 // TODO: determine this for COFF
976 return false;
977}
978
980 const section_header_t &sect) {
981 static constexpr llvm::StringLiteral g_code_sect_name(".code");
982 static constexpr llvm::StringLiteral g_CODE_sect_name("CODE");
983 static constexpr llvm::StringLiteral g_data_sect_name(".data");
984 static constexpr llvm::StringLiteral g_DATA_sect_name("DATA");
985 static constexpr llvm::StringLiteral g_bss_sect_name(".bss");
986 static constexpr llvm::StringLiteral g_BSS_sect_name("BSS");
987
988 if (sect.flags & llvm::COFF::IMAGE_SCN_CNT_CODE &&
989 ((sect_name == g_code_sect_name) || (sect_name == g_CODE_sect_name))) {
990 return eSectionTypeCode;
991 }
992 if (sect.flags & llvm::COFF::IMAGE_SCN_CNT_INITIALIZED_DATA &&
993 ((sect_name == g_data_sect_name) || (sect_name == g_DATA_sect_name))) {
994 if (sect.size == 0 && sect.offset == 0)
996 else
997 return eSectionTypeData;
998 }
999 if (sect.flags & llvm::COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA &&
1000 ((sect_name == g_bss_sect_name) || (sect_name == g_BSS_sect_name))) {
1001 if (sect.size == 0)
1002 return eSectionTypeZeroFill;
1003 else
1004 return eSectionTypeData;
1005 }
1006
1007 if (sect_name.consume_front(".debug_"))
1008 return GetDWARFSectionTypeFromName(sect_name);
1009
1010 SectionType section_type =
1011 llvm::StringSwitch<SectionType>(sect_name)
1012 // PE/COFF image-file section names are limited to 8 characters,
1013 // so the linker truncates the longer source names. Match both.
1014 .Cases({".eh_frame", ".eh_fram"}, eSectionTypeEHFrame)
1015 .Cases({".gosymtab", ".gosymta"}, eSectionTypeGoSymtab)
1016 .Cases({".lldbsummaries", ".lldbsum"},
1018 .Cases({".lldbformatters", ".lldbfor"},
1020 .Case(".debug", eSectionTypeDebug)
1021 .Case(".stabstr", eSectionTypeDataCString)
1022 .Case(".reloc", eSectionTypeOther)
1023 .Case("swiftast", eSectionTypeSwiftModules)
1024 .Default(eSectionTypeInvalid);
1025 if (section_type != eSectionTypeInvalid)
1026 return section_type;
1027
1028 if (sect.flags & llvm::COFF::IMAGE_SCN_CNT_CODE)
1029 return eSectionTypeCode;
1030 if (sect.flags & llvm::COFF::IMAGE_SCN_CNT_INITIALIZED_DATA)
1031 return eSectionTypeData;
1032 if (sect.flags & llvm::COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA) {
1033 if (sect.size == 0)
1034 return eSectionTypeZeroFill;
1035 else
1036 return eSectionTypeData;
1037 }
1038 return eSectionTypeOther;
1039}
1040
1042 // For executables, SizeOfRawData (getFileSize()) is aligned by
1043 // FileAlignment and the actual section size is in VirtualSize
1044 // (getByteSize()). See the comment on
1045 // llvm::object::COFFObjectFile::getSectionSize().
1046 if (m_binary->getPE32Header() || m_binary->getPE32PlusHeader())
1047 return std::min(section->GetByteSize(), section->GetFileSize());
1048 return section->GetFileSize();
1049}
1050
1052 if (m_sections_up)
1053 return;
1054 m_sections_up = std::make_unique<SectionList>();
1055 ModuleSP module_sp(GetModule());
1056 if (module_sp) {
1057 SectionSP header_sp = std::make_shared<Section>(
1058 module_sp, this, ~user_id_t(0), "PECOFF header", eSectionTypeOther,
1059 m_coff_header_opt.image_base, m_coff_header_opt.header_size,
1060 /*file_offset*/ 0, m_coff_header_opt.header_size,
1061 m_coff_header_opt.sect_alignment,
1062 /*flags*/ 0);
1063 header_sp->SetPermissions(ePermissionsReadable);
1064 m_sections_up->AddSection(header_sp);
1065 unified_section_list.AddSection(header_sp);
1066
1067 const uint32_t nsects = m_sect_headers.size();
1068 for (uint32_t idx = 0; idx < nsects; ++idx) {
1069 llvm::StringRef sect_name = GetSectionName(m_sect_headers[idx]);
1070 SectionType section_type = GetSectionType(sect_name, m_sect_headers[idx]);
1071
1072 SectionSP section_sp = std::make_shared<Section>(
1073 module_sp, // Module to which this section belongs
1074 this, // Object file to which this section belongs
1075 idx + 1, // Section ID is the 1 based section index.
1076 sect_name.str(), // Name of this section
1077 section_type,
1078 m_coff_header_opt.image_base +
1079 m_sect_headers[idx].vmaddr, // File VM address == addresses as
1080 // they are found in the object file
1081 m_sect_headers[idx].vmsize, // VM size in bytes of this section
1082 m_sect_headers[idx]
1083 .offset, // Offset to the data for this section in the file
1084 m_sect_headers[idx]
1085 .size, // Size in bytes of this section as found in the file
1086 m_coff_header_opt.sect_alignment, // Section alignment
1087 m_sect_headers[idx].flags); // Flags for this section
1088
1089 uint32_t permissions = 0;
1090 if (m_sect_headers[idx].flags & llvm::COFF::IMAGE_SCN_MEM_EXECUTE)
1091 permissions |= ePermissionsExecutable;
1092 if (m_sect_headers[idx].flags & llvm::COFF::IMAGE_SCN_MEM_READ)
1093 permissions |= ePermissionsReadable;
1094 if (m_sect_headers[idx].flags & llvm::COFF::IMAGE_SCN_MEM_WRITE)
1095 permissions |= ePermissionsWritable;
1096 section_sp->SetPermissions(permissions);
1097
1098 m_sections_up->AddSection(section_sp);
1099 unified_section_list.AddSection(section_sp);
1100 }
1101 }
1102}
1103
1105 if (m_uuid.IsValid())
1106 return m_uuid;
1107
1108 if (!CreateBinary())
1109 return UUID();
1110
1112 return m_uuid;
1113}
1114
1115std::optional<FileSpec> ObjectFilePECOFF::GetDebugLink() {
1116 std::string gnu_debuglink_file;
1117 uint32_t gnu_debuglink_crc;
1118 if (GetDebugLinkContents(*m_binary, gnu_debuglink_file, gnu_debuglink_crc))
1119 return FileSpec(gnu_debuglink_file);
1120 return std::nullopt;
1121}
1122
1123std::optional<FileSpec> ObjectFilePECOFF::GetPDBPath() {
1124 llvm::StringRef pdb_file;
1125 const llvm::codeview::DebugInfo *pdb_info = nullptr;
1126 if (llvm::Error Err = m_binary->getDebugPDBInfo(pdb_info, pdb_file)) {
1127 // DebugInfo section is corrupt.
1128 Log *log = GetLog(LLDBLog::Object);
1129 llvm::StringRef file = m_binary->getFileName();
1131 log, std::move(Err),
1132 "Failed to read Codeview record for PDB debug info file ({1}): {0}",
1133 file);
1134 return std::nullopt;
1135 }
1136 if (pdb_file.empty()) {
1137 // No DebugInfo section present.
1138 return std::nullopt;
1139 }
1140 return FileSpec(pdb_file, FileSpec::GuessPathStyle(pdb_file).value_or(
1141 FileSpec::Style::native));
1142}
1143
1145 ModuleSP module_sp(GetModule());
1146 if (!module_sp)
1147 return 0;
1148
1149 std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex());
1150 if (m_deps_filespec)
1151 return m_deps_filespec->GetSize();
1152
1153 // Cache coff binary if it is not done yet.
1154 if (!CreateBinary())
1155 return 0;
1156
1157 Log *log = GetLog(LLDBLog::Object);
1158 LLDB_LOG(log, "this = {0}, module = {1} ({2}), file = {3}, binary = {4}",
1159 this, GetModule().get(), GetModule()->GetSpecificationDescription(),
1160 m_file.GetPath(), m_binary.get());
1161
1163
1164 for (const auto &entry : m_binary->import_directories()) {
1165 llvm::StringRef dll_name;
1166 // Report a bogus entry.
1167 if (llvm::Error e = entry.getName(dll_name)) {
1168 LLDB_LOGF(log,
1169 "ObjectFilePECOFF::ParseDependentModules() - failed to get "
1170 "import directory entry name: %s",
1171 llvm::toString(std::move(e)).c_str());
1172 continue;
1173 }
1174
1175 // At this moment we only have the base name of the DLL. The full path can
1176 // only be seen after the dynamic loading. Our best guess is Try to get it
1177 // with the help of the object file's directory.
1178 FileSpec dll_specs(dll_name);
1179 dll_specs.SetDirectory(m_file.GetDirectory());
1180
1181 if (FileSystem::Instance().Exists(dll_specs))
1182 m_deps_filespec->Append(dll_specs);
1183 else {
1184 // Known DLLs or DLL not found in the object file directory.
1185 m_deps_filespec->EmplaceBack(dll_name);
1186 }
1187 }
1188 return m_deps_filespec->GetSize();
1189}
1190
1192 auto num_modules = ParseDependentModules();
1193 auto original_size = files.GetSize();
1194
1195 for (unsigned i = 0; i < num_modules; ++i)
1196 files.AppendIfUnique(m_deps_filespec->GetFileSpecAtIndex(i));
1197
1198 return files.GetSize() - original_size;
1199}
1200
1202 if (m_entry_point_address.IsValid())
1203 return m_entry_point_address;
1204
1205 if (!ParseHeader() || !IsExecutable())
1206 return m_entry_point_address;
1207
1208 SectionList *section_list = GetSectionList();
1209 addr_t file_addr = m_coff_header_opt.entry + m_coff_header_opt.image_base;
1210
1211 if (!section_list)
1212 m_entry_point_address.SetOffset(file_addr);
1213 else
1214 m_entry_point_address.ResolveAddressUsingFileSections(file_addr,
1215 section_list);
1216 return m_entry_point_address;
1217}
1218
1220 return Address(GetSectionList()->GetSectionAtIndex(0), 0);
1221}
1222
1223// Dump
1224//
1225// Dump the specifics of the runtime file container (such as any headers
1226// segments, sections, etc).
1228 ModuleSP module_sp(GetModule());
1229 if (module_sp) {
1230 std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex());
1231 s->Printf("%p: ", static_cast<void *>(this));
1232 s->Indent();
1233 s->PutCString("ObjectFilePECOFF");
1234
1235 ArchSpec header_arch = GetArchitecture();
1236
1237 *s << ", file = '" << m_file
1238 << "', arch = " << header_arch.GetArchitectureName() << "\n";
1239
1240 SectionList *sections = GetSectionList();
1241 if (sections)
1242 sections->Dump(s->AsRawOstream(), s->GetIndentLevel(), nullptr, true,
1243 UINT32_MAX);
1244
1245 if (m_symtab_up)
1246 m_symtab_up->Dump(s, nullptr, eSortOrderNone);
1247
1248 if (m_dos_header.e_magic)
1250 if (m_coff_header.machine) {
1252 if (m_coff_header.hdrsize)
1254 }
1255 s->EOL();
1257 s->EOL();
1258
1260 s->EOL();
1261 }
1262}
1263
1264// DumpDOSHeader
1265//
1266// Dump the MS-DOS header to the specified output stream
1268 s->PutCString("MSDOS Header\n");
1269 s->Printf(" e_magic = 0x%4.4x\n", header.e_magic);
1270 s->Printf(" e_cblp = 0x%4.4x\n", header.e_cblp);
1271 s->Printf(" e_cp = 0x%4.4x\n", header.e_cp);
1272 s->Printf(" e_crlc = 0x%4.4x\n", header.e_crlc);
1273 s->Printf(" e_cparhdr = 0x%4.4x\n", header.e_cparhdr);
1274 s->Printf(" e_minalloc = 0x%4.4x\n", header.e_minalloc);
1275 s->Printf(" e_maxalloc = 0x%4.4x\n", header.e_maxalloc);
1276 s->Printf(" e_ss = 0x%4.4x\n", header.e_ss);
1277 s->Printf(" e_sp = 0x%4.4x\n", header.e_sp);
1278 s->Printf(" e_csum = 0x%4.4x\n", header.e_csum);
1279 s->Printf(" e_ip = 0x%4.4x\n", header.e_ip);
1280 s->Printf(" e_cs = 0x%4.4x\n", header.e_cs);
1281 s->Printf(" e_lfarlc = 0x%4.4x\n", header.e_lfarlc);
1282 s->Printf(" e_ovno = 0x%4.4x\n", header.e_ovno);
1283 s->Printf(" e_res[4] = { 0x%4.4x, 0x%4.4x, 0x%4.4x, 0x%4.4x }\n",
1284 header.e_res[0], header.e_res[1], header.e_res[2], header.e_res[3]);
1285 s->Printf(" e_oemid = 0x%4.4x\n", header.e_oemid);
1286 s->Printf(" e_oeminfo = 0x%4.4x\n", header.e_oeminfo);
1287 s->Printf(" e_res2[10] = { 0x%4.4x, 0x%4.4x, 0x%4.4x, 0x%4.4x, 0x%4.4x, "
1288 "0x%4.4x, 0x%4.4x, 0x%4.4x, 0x%4.4x, 0x%4.4x }\n",
1289 header.e_res2[0], header.e_res2[1], header.e_res2[2],
1290 header.e_res2[3], header.e_res2[4], header.e_res2[5],
1291 header.e_res2[6], header.e_res2[7], header.e_res2[8],
1292 header.e_res2[9]);
1293 s->Printf(" e_lfanew = 0x%8.8x\n", header.e_lfanew);
1294}
1295
1296// DumpCOFFHeader
1297//
1298// Dump the COFF header to the specified output stream
1300 s->PutCString("COFF Header\n");
1301 s->Printf(" machine = 0x%4.4x\n", header.machine);
1302 s->Printf(" nsects = 0x%4.4x\n", header.nsects);
1303 s->Printf(" modtime = 0x%8.8x\n", header.modtime);
1304 s->Printf(" symoff = 0x%8.8x\n", header.symoff);
1305 s->Printf(" nsyms = 0x%8.8x\n", header.nsyms);
1306 s->Printf(" hdrsize = 0x%4.4x\n", header.hdrsize);
1307}
1308
1309// DumpOptCOFFHeader
1310//
1311// Dump the optional COFF header to the specified output stream
1313 const coff_opt_header_t &header) {
1314 s->PutCString("Optional COFF Header\n");
1315 s->Printf(" magic = 0x%4.4x\n", header.magic);
1316 s->Printf(" major_linker_version = 0x%2.2x\n",
1317 header.major_linker_version);
1318 s->Printf(" minor_linker_version = 0x%2.2x\n",
1319 header.minor_linker_version);
1320 s->Printf(" code_size = 0x%8.8x\n", header.code_size);
1321 s->Printf(" data_size = 0x%8.8x\n", header.data_size);
1322 s->Printf(" bss_size = 0x%8.8x\n", header.bss_size);
1323 s->Printf(" entry = 0x%8.8x\n", header.entry);
1324 s->Printf(" code_offset = 0x%8.8x\n", header.code_offset);
1325 s->Printf(" data_offset = 0x%8.8x\n", header.data_offset);
1326 s->Printf(" image_base = 0x%16.16" PRIx64 "\n",
1327 header.image_base);
1328 s->Printf(" sect_alignment = 0x%8.8x\n", header.sect_alignment);
1329 s->Printf(" file_alignment = 0x%8.8x\n", header.file_alignment);
1330 s->Printf(" major_os_system_version = 0x%4.4x\n",
1332 s->Printf(" minor_os_system_version = 0x%4.4x\n",
1334 s->Printf(" major_image_version = 0x%4.4x\n",
1335 header.major_image_version);
1336 s->Printf(" minor_image_version = 0x%4.4x\n",
1337 header.minor_image_version);
1338 s->Printf(" major_subsystem_version = 0x%4.4x\n",
1340 s->Printf(" minor_subsystem_version = 0x%4.4x\n",
1342 s->Printf(" reserved1 = 0x%8.8x\n", header.reserved1);
1343 s->Printf(" image_size = 0x%8.8x\n", header.image_size);
1344 s->Printf(" header_size = 0x%8.8x\n", header.header_size);
1345 s->Printf(" checksum = 0x%8.8x\n", header.checksum);
1346 s->Printf(" subsystem = 0x%4.4x\n", header.subsystem);
1347 s->Printf(" dll_flags = 0x%4.4x\n", header.dll_flags);
1348 s->Printf(" stack_reserve_size = 0x%16.16" PRIx64 "\n",
1349 header.stack_reserve_size);
1350 s->Printf(" stack_commit_size = 0x%16.16" PRIx64 "\n",
1351 header.stack_commit_size);
1352 s->Printf(" heap_reserve_size = 0x%16.16" PRIx64 "\n",
1353 header.heap_reserve_size);
1354 s->Printf(" heap_commit_size = 0x%16.16" PRIx64 "\n",
1355 header.heap_commit_size);
1356 s->Printf(" loader_flags = 0x%8.8x\n", header.loader_flags);
1357 s->Printf(" num_data_dir_entries = 0x%8.8x\n",
1358 (uint32_t)header.data_dirs.size());
1359 uint32_t i;
1360 for (i = 0; i < header.data_dirs.size(); i++) {
1361 s->Printf(" data_dirs[%2u] vmaddr = 0x%8.8x, vmsize = 0x%8.8x\n", i,
1362 header.data_dirs[i].vmaddr, header.data_dirs[i].vmsize);
1363 }
1364}
1365// DumpSectionHeader
1366//
1367// Dump a single ELF section header to the specified output stream
1369 const section_header_t &sh) {
1370 std::string name = std::string(GetSectionName(sh));
1371 s->Printf("%-16s 0x%8.8x 0x%8.8x 0x%8.8x 0x%8.8x 0x%8.8x 0x%8.8x 0x%4.4x "
1372 "0x%4.4x 0x%8.8x\n",
1373 name.c_str(), sh.vmaddr, sh.vmsize, sh.offset, sh.size, sh.reloff,
1374 sh.lineoff, sh.nreloc, sh.nline, sh.flags);
1375}
1376
1377// DumpSectionHeaders
1378//
1379// Dump all of the ELF section header to the specified output stream
1381
1382 s->PutCString("Section Headers\n");
1383 s->PutCString("IDX name vm addr vm size file off file "
1384 "size reloc off line off nreloc nline flags\n");
1385 s->PutCString("==== ---------------- ---------- ---------- ---------- "
1386 "---------- ---------- ---------- ------ ------ ----------\n");
1387
1388 uint32_t idx = 0;
1389 SectionHeaderCollIter pos, end = m_sect_headers.end();
1390
1391 for (pos = m_sect_headers.begin(); pos != end; ++pos, ++idx) {
1392 s->Printf("[%2u] ", idx);
1394 }
1395}
1396
1397// DumpDependentModules
1398//
1399// Dump all of the dependent modules to the specified output stream
1401 auto num_modules = ParseDependentModules();
1402 if (num_modules > 0) {
1403 s->PutCString("Dependent Modules\n");
1404 for (unsigned i = 0; i < num_modules; ++i) {
1405 auto spec = m_deps_filespec->GetFileSpecAtIndex(i);
1406 s->Format(" {0}\n", spec.GetFilename());
1407 }
1408 }
1409}
1410
1412 switch (m_coff_header_opt.subsystem) {
1413 case llvm::COFF::IMAGE_SUBSYSTEM_NATIVE:
1414 case llvm::COFF::IMAGE_SUBSYSTEM_WINDOWS_GUI:
1415 case llvm::COFF::IMAGE_SUBSYSTEM_WINDOWS_CUI:
1416 case llvm::COFF::IMAGE_SUBSYSTEM_NATIVE_WINDOWS:
1417 case llvm::COFF::IMAGE_SUBSYSTEM_WINDOWS_CE_GUI:
1418 case llvm::COFF::IMAGE_SUBSYSTEM_XBOX:
1419 case llvm::COFF::IMAGE_SUBSYSTEM_WINDOWS_BOOT_APPLICATION:
1420 return true;
1421 default:
1422 return false;
1423 }
1424}
1425
1427 uint16_t machine = m_coff_header.machine;
1428 switch (machine) {
1429 default:
1430 break;
1431 case llvm::COFF::IMAGE_FILE_MACHINE_AMD64:
1432 case llvm::COFF::IMAGE_FILE_MACHINE_I386:
1433 case llvm::COFF::IMAGE_FILE_MACHINE_POWERPC:
1434 case llvm::COFF::IMAGE_FILE_MACHINE_POWERPCFP:
1435 case llvm::COFF::IMAGE_FILE_MACHINE_ARM:
1436 case llvm::COFF::IMAGE_FILE_MACHINE_ARMNT:
1437 case llvm::COFF::IMAGE_FILE_MACHINE_THUMB:
1438 case llvm::COFF::IMAGE_FILE_MACHINE_ARM64:
1439 ArchSpec arch;
1441 IsWindowsSubsystem() ? llvm::Triple::Win32
1442 : llvm::Triple::UnknownOS);
1443 return arch;
1444 }
1445 return ArchSpec();
1446}
1447
1449 if (m_coff_header.machine != 0) {
1450 if ((m_coff_header.flags & llvm::COFF::IMAGE_FILE_DLL) == 0)
1451 return eTypeExecutable;
1452 else
1453 return eTypeSharedLibrary;
1454 }
1455 return eTypeExecutable;
1456}
1457
static llvm::raw_ostream & error(Stream &strm)
static PluginProperties & GetGlobalPluginProperties()
#define LLDB_LOG(log,...)
The LLDB_LOG* macros defined below are the way to emit log messages.
Definition Log.h:375
#define LLDB_LOGF(log,...)
Definition Log.h:389
#define LLDB_LOG_ERROR(log, error,...)
Definition Log.h:405
static PluginProperties & GetGlobalPluginProperties()
#define OPT_HEADER_MAGIC_PE32
#define OPT_HEADER_MAGIC_PE32_PLUS
static bool RVASymbolListCompareRVA(const std::pair< uint32_t, uint32_t > &a, const std::pair< uint32_t, uint32_t > &b)
#define IMAGE_NT_SIGNATURE
static UUID GetCoffUUID(llvm::object::COFFObjectFile &coff_obj)
static bool GetDebugLinkContents(const llvm::object::COFFObjectFile &coff_obj, std::string &gnu_debuglink_file, uint32_t &gnu_debuglink_crc)
#define IMAGE_DOS_SIGNATURE
#define LLDB_PLUGIN_DEFINE(PluginName)
#define LLDB_SCOPED_TIMERF(...)
Definition Timer.h:86
ObjectFile::Strata CalculateStrata() override
The object file should be able to calculate the strata of the object file.
bool IsExecutable() const override
Tells whether this object file is capable of being the main executable for a process.
void DumpSectionHeaders(lldb_private::Stream *s)
std::unique_ptr< llvm::object::COFFObjectFile > m_binary
dos_header_t m_dos_header
lldb_private::DataExtractor ReadImageDataByRVA(uint32_t rva, size_t size)
llvm::StringRef GetSectionName(const section_header_t &sect)
lldb_private::Address GetEntryPointAddress() override
Returns the address of the Entry Point in this object file - if the object file doesn't have an entry...
std::optional< lldb_private::FileSpecList > m_deps_filespec
~ObjectFilePECOFF() override
static bool ParseDOSHeader(lldb_private::DataExtractor &data, dos_header_t &dos_header)
uint32_t GetDependentModules(lldb_private::FileSpecList &files) override
Extract the dependent modules from an object file.
lldb_private::Address GetBaseAddress() override
Returns base address of this object file.
static lldb_private::ModuleSpecList GetModuleSpecifications(const lldb_private::FileSpec &file, lldb::DataExtractorSP &extractor_sp, lldb::offset_t file_offset, lldb::offset_t length)
lldb::addr_t m_image_base
void DumpSectionHeader(lldb_private::Stream *s, const section_header_t &sh)
std::unique_ptr< lldb_private::CallFrameInfo > CreateCallFrameInfo() override
Creates a plugin-specific call frame info.
size_t GetSectionDataSize(lldb_private::Section *section) override
static void DebuggerInitialize(lldb_private::Debugger &debugger)
ObjectFile::Type CalculateType() override
The object file should be able to calculate its type by looking at its file header and possibly the s...
lldb_private::ArchSpec GetArchitecture() override
Get the ArchSpec for this object file.
static void DumpCOFFHeader(lldb_private::Stream *s, const coff_header_t &header)
lldb::addr_t GetTlsIndexAddress() const
bool ParseHeader() override
Attempts to parse the object header.
struct ObjectFilePECOFF::section_header section_header_t
void DumpDependentModules(lldb_private::Stream *s)
static bool MagicBytesMatch(lldb::DataExtractorSP extractor_sp)
lldb_private::UUID m_uuid
lldb_private::UUID GetUUID() override
Gets the UUID for this object file.
std::vector< std::pair< uint32_t, uint32_t > > rva_symbol_list_t
static llvm::StringRef GetPluginNameStatic()
bool SetLoadAddress(lldb_private::Target &target, lldb::addr_t value, bool value_is_offset) override
Sets the load address for an entire module, assuming a rigid slide of sections, if possible in the im...
SectionHeaderColl::iterator SectionHeaderCollIter
SectionHeaderColl m_sect_headers
static lldb_private::ObjectFile * CreateMemoryInstance(const lldb::ModuleSP &module_sp, lldb::WritableDataBufferSP data_sp, const lldb::ProcessSP &process_sp, lldb::addr_t header_addr)
static llvm::StringRef GetPluginDescriptionStatic()
coff_opt_header_t m_coff_header_opt
static bool SaveCore(const lldb::ProcessSP &process_sp, lldb_private::SaveCoreOptions &options, lldb_private::Status &error)
bool ParseCOFFOptionalHeader(lldb::offset_t *offset_ptr)
bool IsStripped() override
Detect if this object file has been stripped of local symbols.
uint32_t ParseDependentModules()
struct ObjectFilePECOFF::coff_header coff_header_t
bool NeedsEndianSwap() const
static ObjectFile * CreateInstance(const lldb::ModuleSP &module_sp, lldb::DataExtractorSP extractor_sp, lldb::offset_t data_offset, const lldb_private::FileSpec *file, lldb::offset_t offset, lldb::offset_t length)
lldb::addr_t GetFileAddress(uint32_t rva) const
struct ObjectFilePECOFF::coff_opt_header coff_opt_header_t
void ParseSymtab(lldb_private::Symtab &symtab) override
Parse the symbol table into the provides symbol table object.
void CreateSections(lldb_private::SectionList &unified_section_list) override
void Dump(lldb_private::Stream *s) override
Dump a description of this object to a Stream.
rva_symbol_list_t AppendFromExportTable(lldb_private::SectionList *sect_list, lldb_private::Symtab &symtab)
coff_header_t m_coff_header
lldb_private::Address GetAddress(uint32_t rva)
static void Initialize()
ObjectFilePECOFF(const lldb::ModuleSP &module_sp, lldb::DataExtractorSP extractor_sp, lldb::offset_t data_offset, const lldb_private::FileSpec *file, lldb::offset_t file_offset, lldb::offset_t length)
lldb::ByteOrder GetByteOrder() const override
Gets whether endian swapping should occur when extracting data from this object file.
lldb_private::DataExtractor ReadImageData(uint32_t offset, size_t size)
void AppendFromCOFFSymbolTable(lldb_private::SectionList *sect_list, lldb_private::Symtab &symtab, const rva_symbol_list_t &sorted_exports)
std::optional< lldb_private::FileSpec > GetDebugLink()
Return the contents of the .gnu_debuglink section, if the object file contains it.
bool ParseSectionHeaders(uint32_t offset)
static lldb::SymbolType MapSymbolType(uint16_t coff_symbol_type)
uint32_t GetRVA(const lldb_private::Address &addr) const
uint32_t GetAddressByteSize() const override
Gets the address size in bytes for the current object file.
static void DumpOptCOFFHeader(lldb_private::Stream *s, const coff_opt_header_t &header)
static lldb::SectionType GetSectionType(llvm::StringRef sect_name, const section_header_t &sect)
static bool ParseCOFFHeader(lldb_private::DataExtractor &data, lldb::offset_t *offset_ptr, coff_header_t &coff_header)
std::optional< lldb_private::FileSpec > GetPDBPath()
struct ObjectFilePECOFF::dos_header dos_header_t
static void Terminate()
lldb_private::Address m_entry_point_address
static void DumpDOSHeader(lldb_private::Stream *s, const dos_header_t &header)
A section + offset based address class.
Definition Address.h:62
lldb::SectionSP GetSection() const
Get const accessor for the section.
Definition Address.h:426
lldb::addr_t GetFileAddress() const
Get the file address.
Definition Address.cpp:283
lldb::addr_t GetOffset() const
Get the section relative offset value.
Definition Address.h:329
An architecture specification class.
Definition ArchSpec.h:32
llvm::Triple & GetTriple()
Architecture triple accessor.
Definition ArchSpec.h:547
bool SetTriple(const llvm::Triple &triple)
Architecture triple setter.
Definition ArchSpec.cpp:952
bool SetArchitecture(ArchitectureType arch_type, uint32_t cpu, uint32_t sub, uint32_t os=0)
Change the architecture object type, CPU type and OS type.
const char * GetArchitectureName() const
Returns a static string representing the current architecture.
Definition ArchSpec.cpp:745
A uniqued constant string class.
Definition ConstString.h:40
llvm::StringRef GetStringRef() const
Get the string value as a llvm::StringRef.
An data extractor class.
const char * GetCStr(lldb::offset_t *offset_ptr) const
Extract a C string from *offset_ptr.
bool ValidOffsetForDataOfSize(lldb::offset_t offset, lldb::offset_t length) const
Test the availability of length bytes of data from offset.
uint32_t GetU32(lldb::offset_t *offset_ptr) const
Extract a uint32_t value from *offset_ptr.
uint16_t GetU16(lldb::offset_t *offset_ptr) const
Extract a uint16_t value from *offset_ptr.
virtual lldb::offset_t SetData(const void *bytes, lldb::offset_t length, lldb::ByteOrder byte_order)
Set data with a buffer that is caller owned.
A class to manage flag bits.
Definition Debugger.h:103
A file collection class.
size_t GetSize() const
Get the number of files in the file list.
bool AppendIfUnique(const FileSpec &file)
Append a FileSpec object if unique.
A file utility class.
Definition FileSpec.h:56
static std::optional< Style > GuessPathStyle(llvm::StringRef absolute_path)
Attempt to guess path style for a given path string.
Definition FileSpec.cpp:326
llvm::StringRef GetFilename() const
Filename string const get accessor.
Definition FileSpec.h:248
void SetDirectory(llvm::StringRef directory)
Directory string set accessor.
Definition FileSpec.cpp:358
static FileSystem & Instance()
void SetDemangledName(ConstString name)
Definition Mangled.h:162
void SetValue(ConstString name)
Set the string value in this object.
Definition Mangled.cpp:123
lldb::ModuleSP GetModule() const
Get const accessor for the module pointer.
void Append(const ModuleSpec &spec)
Definition ModuleSpec.h:371
ArchSpec & GetArchitecture()
Definition ModuleSpec.h:93
std::unique_ptr< lldb_private::SectionList > m_sections_up
Definition ObjectFile.h:786
static lldb::DataBufferSP MapFileData(const FileSpec &file, uint64_t Size, uint64_t Offset)
std::unique_ptr< lldb_private::Symtab > m_symtab_up
Definition ObjectFile.h:789
static lldb::SectionType GetDWARFSectionTypeFromName(llvm::StringRef name)
Parses the section type from a section name for DWARF sections.
DataExtractorNSP m_data_nsp
The data for this object file so things can be parsed lazily.
Definition ObjectFile.h:778
@ eTypeExecutable
A normal executable.
Definition ObjectFile.h:55
@ eTypeSharedLibrary
A shared library that can be used during execution.
Definition ObjectFile.h:63
virtual SectionList * GetSectionList(bool update_module_section_list=true)
Gets the section list for the currently selected architecture (and object for archives).
ObjectFile(const lldb::ModuleSP &module_sp, const FileSpec *file_spec_ptr, lldb::offset_t file_offset, lldb::offset_t length, lldb::DataExtractorSP extractor_sp, lldb::offset_t data_offset)
Construct with a parent module, offset, and header data.
lldb::ProcessWP m_process_wp
Definition ObjectFile.h:782
static lldb::OptionValuePropertiesSP GetSettingForObjectFilePlugin(Debugger &debugger, llvm::StringRef setting_name)
static bool CreateSettingForObjectFilePlugin(Debugger &debugger, const lldb::OptionValuePropertiesSP &properties_sp, llvm::StringRef description, bool is_global_property)
static bool RegisterPlugin(llvm::StringRef name, llvm::StringRef description, ABICreateInstance create_callback)
static bool UnregisterPlugin(ABICreateInstance create_callback)
const std::optional< lldb_private::FileSpec > GetOutputFile() const
lldb::SectionSP FindSectionByID(lldb::user_id_t sect_id) const
Definition Section.cpp:584
size_t GetSize() const
Definition Section.h:76
size_t AddSection(const lldb::SectionSP &section_sp)
Definition Section.cpp:483
void Dump(llvm::raw_ostream &s, unsigned indent, Target *target, bool show_header, uint32_t depth) const
Definition Section.cpp:648
lldb::SectionSP GetSectionAtIndex(size_t idx) const
Definition Section.cpp:555
lldb::addr_t GetByteSize() const
Definition Section.h:196
lldb::offset_t GetFileSize() const
Definition Section.h:186
An error handling class.
Definition Status.h:118
A stream class that can stream formatted output to a file.
Definition Stream.h:28
void Format(const char *format, Args &&... args)
Forwards the arguments to llvm::formatv and writes to the stream.
Definition Stream.h:370
llvm::raw_ostream & AsRawOstream()
Returns a raw_ostream that forwards the data to this Stream object.
Definition Stream.h:405
size_t Indent(llvm::StringRef s="")
Indent the current line in the stream.
Definition Stream.cpp:157
size_t Printf(const char *format,...) __attribute__((format(printf
Output printf formatted output to the stream.
Definition Stream.cpp:134
size_t PutCString(llvm::StringRef cstr)
Output a C string to the stream.
Definition Stream.cpp:63
size_t EOL()
Output and End of Line character to the stream.
Definition Stream.cpp:155
unsigned GetIndentLevel() const
Get the current indentation level.
Definition Stream.cpp:193
void SetType(lldb::SymbolType type)
Definition Symbol.h:199
Mangled & GetMangled()
Definition Symbol.h:162
Address & GetAddressRef()
Definition Symbol.h:78
lldb::SymbolType GetType() const
Definition Symbol.h:197
void SetDemangledNameIsSynthesized(bool b)
Definition Symbol.h:265
ConstString GetDisplayName() const
Definition Symbol.cpp:199
void SetExternal(bool b)
Definition Symbol.h:227
void SetID(uint32_t uid)
Definition Symbol.h:160
Symbol * SymbolAtIndex(size_t idx)
Definition Symtab.cpp:226
uint32_t AddSymbol(const Symbol &symbol)
Definition Symtab.cpp:62
size_t GetNumSymbols() const
Definition Symtab.cpp:75
void Reserve(size_t count)
Definition Symtab.cpp:49
bool SetSectionLoadAddress(const lldb::SectionSP &section, lldb::addr_t load_addr, bool warn_multiple=false)
Definition Target.cpp:3532
Represents UUID's of various sizes.
Definition UUID.h:27
bool IsValid() const
Definition UUID.h:69
#define LLDB_INVALID_CPUTYPE
#define LLDB_INVALID_ADDRESS
#define UINT32_MAX
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
bool SaveMiniDump(const lldb::ProcessSP &process_sp, SaveCoreOptions &core_options, lldb_private::Status &error)
uint64_t offset_t
Definition lldb-types.h:86
std::shared_ptr< lldb_private::Process > ProcessSP
SymbolType
Symbol types.
@ eSymbolTypeAbsolute
@ eSymbolTypeAdditional
When symbols take more than one entry, the extra entries get this type.
ByteOrder
Byte ordering definitions.
uint64_t user_id_t
Definition lldb-types.h:83
std::shared_ptr< lldb_private::DataBuffer > DataBufferSP
std::shared_ptr< lldb_private::Section > SectionSP
std::shared_ptr< lldb_private::WritableDataBuffer > WritableDataBufferSP
uint64_t addr_t
Definition lldb-types.h:80
@ eSectionTypeInvalid
@ eSectionTypeZeroFill
@ eSectionTypeLLDBFormatters
@ eSectionTypeEHFrame
@ eSectionTypeLLDBTypeSummaries
@ eSectionTypeGoSymtab
@ eSectionTypeSwiftModules
@ eSectionTypeDataCString
Inlined C string data.
std::shared_ptr< lldb_private::DataExtractor > DataExtractorSP
std::shared_ptr< lldb_private::Module > ModuleSP
std::shared_ptr< lldb_private::OptionValue > OptionValueSP
std::vector< data_directory > data_dirs
struct lldb_private::UUID::CvRecordPdb70::@270014123013057306020052025020177330273131255133 Uuid
llvm::support::ulittle32_t Age
Definition UUID.h:47