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::COFFObjectFile::create(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 llvm::object::COFFObjectFile *COFFObj = binary->get();
284
285 ModuleSpec module_spec(file);
286 ArchSpec &spec = module_spec.GetArchitecture();
287 lldb_private::UUID &uuid = module_spec.GetUUID();
288 if (!uuid.IsValid())
289 uuid = GetCoffUUID(*COFFObj);
290
291 static llvm::Triple::EnvironmentType default_env = [] {
292 auto def_target = llvm::Triple(
293 llvm::Triple::normalize(llvm::sys::getDefaultTargetTriple()));
294 if (def_target.getOS() == llvm::Triple::Win32 &&
295 def_target.getEnvironment() != llvm::Triple::UnknownEnvironment)
296 return def_target.getEnvironment();
297 return llvm::Triple::MSVC;
298 }();
299
300 // Check for a module-specific override.
301 OptionValueSP module_env_option;
302 const auto *map = GetGlobalPluginProperties().ModuleABIMap();
303 if (map->GetNumValues() > 0) {
304 // Step 1: Try with the exact file name.
305 auto name = file.GetFilename();
306 module_env_option = map->GetValueForKey(name);
307 if (!module_env_option) {
308 // Step 2: Try with the file name in lowercase.
309 auto name_lower = name.lower();
310 module_env_option = map->GetValueForKey(llvm::StringRef(name_lower));
311 }
312 if (!module_env_option) {
313 // Step 3: Try with the file name with ".debug" suffix stripped.
314 auto name_stripped = name;
315 if (name_stripped.consume_back_insensitive(".debug")) {
316 module_env_option = map->GetValueForKey(name_stripped);
317 if (!module_env_option) {
318 // Step 4: Try with the file name in lowercase with ".debug" suffix
319 // stripped.
320 auto name_lower = name_stripped.lower();
321 module_env_option = map->GetValueForKey(llvm::StringRef(name_lower));
322 }
323 }
324 }
325 }
326 llvm::Triple::EnvironmentType env;
327 if (module_env_option)
328 env =
329 module_env_option->GetValueAs<llvm::Triple::EnvironmentType>().value_or(
330 static_cast<llvm::Triple::EnvironmentType>(0));
331 else
332 env = GetGlobalPluginProperties().ABI();
333
334 if (env == llvm::Triple::UnknownEnvironment)
335 env = default_env;
336
337 ModuleSpecList specs;
338 switch (COFFObj->getMachine()) {
339 case MachineAmd64:
340 spec.SetTriple("x86_64-pc-windows");
341 spec.GetTriple().setEnvironment(env);
342 specs.Append(module_spec);
343 break;
344 case MachineX86:
345 spec.SetTriple("i386-pc-windows");
346 spec.GetTriple().setEnvironment(env);
347 specs.Append(module_spec);
348 break;
349 case MachineArmNt:
350 spec.SetTriple("armv7-pc-windows");
351 spec.GetTriple().setEnvironment(env);
352 specs.Append(module_spec);
353 break;
354 case MachineArm64:
355 case MachineArm64X:
356 spec.SetTriple("aarch64-pc-windows");
357 spec.GetTriple().setEnvironment(env);
358 specs.Append(module_spec);
359 break;
360 default:
361 break;
362 }
363
364 return specs;
365}
366
370 // Outfile and process_sp are validated by PluginManager::SaveCore
371 assert(options.GetOutputFile().has_value());
372 assert(process_sp);
373 return SaveMiniDump(process_sp, options, error);
374}
375
377 lldb::offset_t offset = 0;
378 uint16_t magic = extractor_sp->GetU16(&offset);
379 return magic == IMAGE_DOS_SIGNATURE;
380}
381
383 // TODO: We need to complete this mapping of COFF symbol types to LLDB ones.
384 // For now, here's a hack to make sure our function have types.
385 const auto complex_type =
386 coff_symbol_type >> llvm::COFF::SCT_COMPLEX_TYPE_SHIFT;
387 if (complex_type == llvm::COFF::IMAGE_SYM_DTYPE_FUNCTION) {
389 }
390 const auto base_type = coff_symbol_type & 0xff;
391 if (base_type == llvm::COFF::IMAGE_SYM_TYPE_NULL &&
392 complex_type == llvm::COFF::IMAGE_SYM_DTYPE_NULL) {
393 // Unknown type. LLD and GNU ld uses this for variables on MinGW, so
394 // consider these symbols to be data to enable printing.
396 }
398}
399
401 if (m_binary)
402 return true;
403
404 Log *log = GetLog(LLDBLog::Object);
405
406 auto binary = llvm::object::COFFObjectFile::create(llvm::MemoryBufferRef(
407 toStringRef(m_data_nsp->GetData()), m_file.GetFilename()));
408 if (!binary) {
409 LLDB_LOG_ERROR(log, binary.takeError(),
410 "Failed to create binary for file ({1}): {0}", m_file);
411 return false;
412 }
413
414 m_binary = std::move(*binary);
415
416 LLDB_LOG(log, "this = {0}, module = {1} ({2}), file = {3}, binary = {4}",
417 this, GetModule().get(), GetModule()->GetSpecificationDescription(),
418 m_file.GetPath(), m_binary.get());
419 return true;
420}
421
423 DataExtractorSP extractor_sp,
424 lldb::offset_t data_offset,
425 const FileSpec *file,
426 lldb::offset_t file_offset,
427 lldb::offset_t length)
428 : ObjectFile(module_sp, file, file_offset, length, extractor_sp,
429 data_offset),
432 m_deps_filespec() {}
433
435 WritableDataBufferSP header_data_sp,
436 const lldb::ProcessSP &process_sp,
437 addr_t header_addr)
438 : ObjectFile(module_sp, process_sp, header_addr,
439 std::make_shared<DataExtractor>(header_data_sp)),
442 m_deps_filespec() {}
443
445
447 ModuleSP module_sp(GetModule());
448 if (module_sp) {
449 std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex());
450 m_sect_headers.clear();
451 m_data_nsp->SetByteOrder(eByteOrderLittle);
452 lldb::offset_t offset = 0;
453
455 offset = m_dos_header.e_lfanew;
456 uint32_t pe_signature = m_data_nsp->GetU32(&offset);
457 if (pe_signature != IMAGE_NT_SIGNATURE)
458 return false;
459 if (ParseCOFFHeader(*m_data_nsp, &offset, m_coff_header)) {
460 if (m_coff_header.hdrsize > 0)
462 ParseSectionHeaders(offset);
463 }
464 m_data_nsp->SetAddressByteSize(GetAddressByteSize());
465 return true;
466 }
467 }
468 return false;
469}
470
472 bool value_is_offset) {
473 bool changed = false;
474 ModuleSP module_sp = GetModule();
475 if (module_sp) {
476 size_t num_loaded_sections = 0;
477 SectionList *section_list = GetSectionList();
478 if (section_list) {
479 if (!value_is_offset) {
480 value -= m_image_base;
481 }
482
483 const size_t num_sections = section_list->GetSize();
484 size_t sect_idx = 0;
485
486 for (sect_idx = 0; sect_idx < num_sections; ++sect_idx) {
487 // Iterate through the object file sections to find all of the sections
488 // that have SHF_ALLOC in their flag bits.
489 SectionSP section_sp(section_list->GetSectionAtIndex(sect_idx));
490 if (section_sp && !section_sp->IsThreadSpecific()) {
491 if (target.SetSectionLoadAddress(
492 section_sp, section_sp->GetFileAddress() + value))
493 ++num_loaded_sections;
494 }
495 }
496 changed = num_loaded_sections > 0;
497 }
498 }
499 return changed;
500}
501
503
505 return (m_coff_header.flags & llvm::COFF::IMAGE_FILE_DLL) == 0;
506}
507
510 return 8;
512 return 4;
513 return 4;
514}
515
516// NeedsEndianSwap
517//
518// Return true if an endian swap needs to occur when extracting data from this
519// file.
521#if defined(__LITTLE_ENDIAN__)
522 return false;
523#else
524 return true;
525#endif
526}
527// ParseDOSHeader
530 bool success = false;
531 lldb::offset_t offset = 0;
532 success = data.ValidOffsetForDataOfSize(0, sizeof(dos_header));
533
534 if (success) {
535 dos_header.e_magic = data.GetU16(&offset); // Magic number
537
538 if (success) {
539 dos_header.e_cblp = data.GetU16(&offset); // Bytes on last page of file
540 dos_header.e_cp = data.GetU16(&offset); // Pages in file
541 dos_header.e_crlc = data.GetU16(&offset); // Relocations
543 data.GetU16(&offset); // Size of header in paragraphs
545 data.GetU16(&offset); // Minimum extra paragraphs needed
547 data.GetU16(&offset); // Maximum extra paragraphs needed
548 dos_header.e_ss = data.GetU16(&offset); // Initial (relative) SS value
549 dos_header.e_sp = data.GetU16(&offset); // Initial SP value
550 dos_header.e_csum = data.GetU16(&offset); // Checksum
551 dos_header.e_ip = data.GetU16(&offset); // Initial IP value
552 dos_header.e_cs = data.GetU16(&offset); // Initial (relative) CS value
554 data.GetU16(&offset); // File address of relocation table
555 dos_header.e_ovno = data.GetU16(&offset); // Overlay number
556
557 dos_header.e_res[0] = data.GetU16(&offset); // Reserved words
558 dos_header.e_res[1] = data.GetU16(&offset); // Reserved words
559 dos_header.e_res[2] = data.GetU16(&offset); // Reserved words
560 dos_header.e_res[3] = data.GetU16(&offset); // Reserved words
561
563 data.GetU16(&offset); // OEM identifier (for e_oeminfo)
565 data.GetU16(&offset); // OEM information; e_oemid specific
566 dos_header.e_res2[0] = data.GetU16(&offset); // Reserved words
567 dos_header.e_res2[1] = data.GetU16(&offset); // Reserved words
568 dos_header.e_res2[2] = data.GetU16(&offset); // Reserved words
569 dos_header.e_res2[3] = data.GetU16(&offset); // Reserved words
570 dos_header.e_res2[4] = data.GetU16(&offset); // Reserved words
571 dos_header.e_res2[5] = data.GetU16(&offset); // Reserved words
572 dos_header.e_res2[6] = data.GetU16(&offset); // Reserved words
573 dos_header.e_res2[7] = data.GetU16(&offset); // Reserved words
574 dos_header.e_res2[8] = data.GetU16(&offset); // Reserved words
575 dos_header.e_res2[9] = data.GetU16(&offset); // Reserved words
576
578 data.GetU32(&offset); // File address of new exe header
579 }
580 }
581 if (!success)
582 memset(&dos_header, 0, sizeof(dos_header));
583 return success;
584}
585
586// ParserCOFFHeader
588 lldb::offset_t *offset_ptr,
590 bool success =
591 data.ValidOffsetForDataOfSize(*offset_ptr, sizeof(coff_header));
592 if (success) {
593 coff_header.machine = data.GetU16(offset_ptr);
594 coff_header.nsects = data.GetU16(offset_ptr);
595 coff_header.modtime = data.GetU32(offset_ptr);
596 coff_header.symoff = data.GetU32(offset_ptr);
597 coff_header.nsyms = data.GetU32(offset_ptr);
598 coff_header.hdrsize = data.GetU16(offset_ptr);
599 coff_header.flags = data.GetU16(offset_ptr);
600 }
601 if (!success)
602 memset(&coff_header, 0, sizeof(coff_header));
603 return success;
604}
605
607 bool success = false;
608 const lldb::offset_t end_offset = *offset_ptr + m_coff_header.hdrsize;
609 if (*offset_ptr < end_offset) {
610 success = true;
611 m_coff_header_opt.magic = m_data_nsp->GetU16(offset_ptr);
612 m_coff_header_opt.major_linker_version = m_data_nsp->GetU8(offset_ptr);
613 m_coff_header_opt.minor_linker_version = m_data_nsp->GetU8(offset_ptr);
614 m_coff_header_opt.code_size = m_data_nsp->GetU32(offset_ptr);
615 m_coff_header_opt.data_size = m_data_nsp->GetU32(offset_ptr);
616 m_coff_header_opt.bss_size = m_data_nsp->GetU32(offset_ptr);
617 m_coff_header_opt.entry = m_data_nsp->GetU32(offset_ptr);
618 m_coff_header_opt.code_offset = m_data_nsp->GetU32(offset_ptr);
619
620 const uint32_t addr_byte_size = GetAddressByteSize();
621
622 if (*offset_ptr < end_offset) {
624 // PE32 only
625 m_coff_header_opt.data_offset = m_data_nsp->GetU32(offset_ptr);
626 } else
627 m_coff_header_opt.data_offset = 0;
628
629 if (*offset_ptr < end_offset) {
630 m_coff_header_opt.image_base =
631 m_data_nsp->GetMaxU64(offset_ptr, addr_byte_size);
632 m_coff_header_opt.sect_alignment = m_data_nsp->GetU32(offset_ptr);
633 m_coff_header_opt.file_alignment = m_data_nsp->GetU32(offset_ptr);
634 m_coff_header_opt.major_os_system_version =
635 m_data_nsp->GetU16(offset_ptr);
636 m_coff_header_opt.minor_os_system_version =
637 m_data_nsp->GetU16(offset_ptr);
638 m_coff_header_opt.major_image_version = m_data_nsp->GetU16(offset_ptr);
639 m_coff_header_opt.minor_image_version = m_data_nsp->GetU16(offset_ptr);
640 m_coff_header_opt.major_subsystem_version =
641 m_data_nsp->GetU16(offset_ptr);
642 m_coff_header_opt.minor_subsystem_version =
643 m_data_nsp->GetU16(offset_ptr);
644 m_coff_header_opt.reserved1 = m_data_nsp->GetU32(offset_ptr);
645 m_coff_header_opt.image_size = m_data_nsp->GetU32(offset_ptr);
646 m_coff_header_opt.header_size = m_data_nsp->GetU32(offset_ptr);
647 m_coff_header_opt.checksum = m_data_nsp->GetU32(offset_ptr);
648 m_coff_header_opt.subsystem = m_data_nsp->GetU16(offset_ptr);
649 m_coff_header_opt.dll_flags = m_data_nsp->GetU16(offset_ptr);
650 m_coff_header_opt.stack_reserve_size =
651 m_data_nsp->GetMaxU64(offset_ptr, addr_byte_size);
652 m_coff_header_opt.stack_commit_size =
653 m_data_nsp->GetMaxU64(offset_ptr, addr_byte_size);
654 m_coff_header_opt.heap_reserve_size =
655 m_data_nsp->GetMaxU64(offset_ptr, addr_byte_size);
656 m_coff_header_opt.heap_commit_size =
657 m_data_nsp->GetMaxU64(offset_ptr, addr_byte_size);
658 m_coff_header_opt.loader_flags = m_data_nsp->GetU32(offset_ptr);
659 uint32_t num_data_dir_entries = m_data_nsp->GetU32(offset_ptr);
660 m_coff_header_opt.data_dirs.clear();
661 m_coff_header_opt.data_dirs.resize(num_data_dir_entries);
662 uint32_t i;
663 for (i = 0; i < num_data_dir_entries; i++) {
664 m_coff_header_opt.data_dirs[i].vmaddr =
665 m_data_nsp->GetU32(offset_ptr);
666 m_coff_header_opt.data_dirs[i].vmsize =
667 m_data_nsp->GetU32(offset_ptr);
668 }
669
670 m_image_base = m_coff_header_opt.image_base;
671 }
672 }
673 }
674 // Make sure we are on track for section data which follows
675 *offset_ptr = end_offset;
676 return success;
677}
678
679uint32_t ObjectFilePECOFF::GetRVA(const Address &addr) const {
680 return addr.GetFileAddress() - m_image_base;
681}
682
684 SectionList *sect_list = GetSectionList();
685 if (!sect_list)
686 return Address(GetFileAddress(rva));
687
688 return Address(GetFileAddress(rva), sect_list);
689}
690
692 return m_image_base + rva;
693}
694
695DataExtractor ObjectFilePECOFF::ReadImageData(uint32_t offset, size_t size) {
696 if (!size)
697 return {};
698
699 if (m_data_nsp->ValidOffsetForDataOfSize(offset, size))
700 return DataExtractor(*m_data_nsp, offset, size);
701
702 ProcessSP process_sp(m_process_wp.lock());
703 DataExtractor data;
704 if (process_sp) {
705 auto data_up = std::make_unique<DataBufferHeap>(size, 0);
706 Status readmem_error;
707 size_t bytes_read =
708 process_sp->ReadMemory(m_image_base + offset, data_up->GetBytes(),
709 data_up->GetByteSize(), readmem_error);
710 if (bytes_read == size) {
711 DataBufferSP buffer_sp(data_up.release());
712 data.SetData(buffer_sp, 0, buffer_sp->GetByteSize());
713 }
714 }
715 return data;
716}
717
719 Address addr = GetAddress(rva);
720 SectionSP sect = addr.GetSection();
721 if (!sect)
722 return {};
723 rva = sect->GetFileOffset() + addr.GetOffset();
724
725 return ReadImageData(rva, size);
726}
727
728// ParseSectionHeaders
730 uint32_t section_header_data_offset) {
731 const uint32_t nsects = m_coff_header.nsects;
732 m_sect_headers.clear();
733
734 if (nsects > 0) {
735 const size_t section_header_byte_size = nsects * sizeof(section_header_t);
736 DataExtractor section_header_data =
737 ReadImageData(section_header_data_offset, section_header_byte_size);
738
739 lldb::offset_t offset = 0;
740 if (section_header_data.ValidOffsetForDataOfSize(
741 offset, section_header_byte_size)) {
742 m_sect_headers.resize(nsects);
743
744 for (uint32_t idx = 0; idx < nsects; ++idx) {
745 const void *name_data = section_header_data.GetData(&offset, 8);
746 if (name_data) {
747 memcpy(m_sect_headers[idx].name, name_data, 8);
748 m_sect_headers[idx].vmsize = section_header_data.GetU32(&offset);
749 m_sect_headers[idx].vmaddr = section_header_data.GetU32(&offset);
750 m_sect_headers[idx].size = section_header_data.GetU32(&offset);
751 m_sect_headers[idx].offset = section_header_data.GetU32(&offset);
752 m_sect_headers[idx].reloff = section_header_data.GetU32(&offset);
753 m_sect_headers[idx].lineoff = section_header_data.GetU32(&offset);
754 m_sect_headers[idx].nreloc = section_header_data.GetU16(&offset);
755 m_sect_headers[idx].nline = section_header_data.GetU16(&offset);
756 m_sect_headers[idx].flags = section_header_data.GetU32(&offset);
757 }
758 }
759 }
760 }
761
762 return !m_sect_headers.empty();
763}
764
766 llvm::StringRef hdr_name(sect.name, std::size(sect.name));
767 hdr_name = hdr_name.split('\0').first;
768 if (hdr_name.consume_front("/")) {
769 lldb::offset_t stroff;
770 if (!to_integer(hdr_name, stroff, 10))
771 return "";
772 lldb::offset_t string_file_offset =
773 m_coff_header.symoff + (m_coff_header.nsyms * 18) + stroff;
774 if (const char *name = m_data_nsp->GetCStr(&string_file_offset))
775 return name;
776 return "";
777 }
778 return hdr_name;
779}
780
782 SectionList *sect_list = GetSectionList();
783 rva_symbol_list_t sorted_exports = AppendFromExportTable(sect_list, symtab);
784 AppendFromCOFFSymbolTable(sect_list, symtab, sorted_exports);
785}
786
787static bool RVASymbolListCompareRVA(const std::pair<uint32_t, uint32_t> &a,
788 const std::pair<uint32_t, uint32_t> &b) {
789 return a.first < b.first;
790}
791
793 SectionList *sect_list, Symtab &symtab,
794 const ObjectFilePECOFF::rva_symbol_list_t &sorted_exports) {
795 const uint32_t num_syms = m_binary->getNumberOfSymbols();
796 if (num_syms == 0)
797 return;
798 // Check that this is not a bigobj; we do not support bigobj.
799 if (m_binary->getSymbolTableEntrySize() !=
800 sizeof(llvm::object::coff_symbol16))
801 return;
802
803 Log *log = GetLog(LLDBLog::Object);
804 symtab.Reserve(symtab.GetNumSymbols() + num_syms);
805 for (const auto &sym_ref : m_binary->symbols()) {
806 const auto coff_sym_ref = m_binary->getCOFFSymbol(sym_ref);
807 auto name_or_error = sym_ref.getName();
808 if (!name_or_error) {
809 LLDB_LOG_ERROR(log, name_or_error.takeError(),
810 "ObjectFilePECOFF::AppendFromCOFFSymbolTable - failed to "
811 "get symbol table entry name: {0}");
812 continue;
813 }
814 const llvm::StringRef sym_name = *name_or_error;
815 Symbol symbol;
816 symbol.GetMangled().SetValue(ConstString(sym_name));
817 int16_t section_number =
818 static_cast<int16_t>(coff_sym_ref.getSectionNumber());
819 if (section_number >= 1) {
820 symbol.GetAddressRef() = Address(
821 sect_list->FindSectionByID(section_number), coff_sym_ref.getValue());
822 const auto symbol_type = MapSymbolType(coff_sym_ref.getType());
823 symbol.SetType(symbol_type);
824
825 // Check for duplicate of exported symbols:
826 const uint32_t symbol_rva = symbol.GetAddressRef().GetFileAddress() -
827 m_coff_header_opt.image_base;
828 const auto &first_match = std::lower_bound(
829 sorted_exports.begin(), sorted_exports.end(),
830 std::make_pair(symbol_rva, 0), RVASymbolListCompareRVA);
831 for (auto it = first_match;
832 it != sorted_exports.end() && it->first == symbol_rva; ++it) {
833 Symbol *exported = symtab.SymbolAtIndex(it->second);
834 if (symbol_type != lldb::eSymbolTypeInvalid)
835 exported->SetType(symbol_type);
836 if (exported->GetMangled() == symbol.GetMangled()) {
837 symbol.SetExternal(true);
838 // We don't want the symbol to be duplicated (e.g. when running
839 // `disas -n func`), but we also don't want to erase this entry (to
840 // preserve the original symbol order), so we mark it as additional.
842 } else {
843 // It is possible for a symbol to be exported in a different name
844 // from its original. In this case keep both entries so lookup using
845 // either names will work. If this symbol has an invalid type, replace
846 // it with the type from the export symbol.
847 if (symbol.GetType() == lldb::eSymbolTypeInvalid)
848 symbol.SetType(exported->GetType());
849 }
850 }
851 } else if (section_number == llvm::COFF::IMAGE_SYM_ABSOLUTE) {
852 symbol.GetAddressRef() = Address(coff_sym_ref.getValue());
854 }
855 symtab.AddSymbol(symbol);
856 }
857}
858
861 Symtab &symtab) {
862 const auto *export_table = m_binary->getExportTable();
863 if (!export_table)
864 return {};
865 const uint32_t num_syms = export_table->AddressTableEntries;
866 if (num_syms == 0)
867 return {};
868
869 Log *log = GetLog(LLDBLog::Object);
870 rva_symbol_list_t export_list;
871 symtab.Reserve(symtab.GetNumSymbols() + num_syms);
872 // Read each export table entry, ordered by ordinal instead of by name.
873 for (const auto &entry : m_binary->export_directories()) {
874 llvm::StringRef sym_name;
875 if (auto err = entry.getSymbolName(sym_name)) {
876 LLDB_LOG_ERROR(log, std::move(err),
877 "ObjectFilePECOFF::AppendFromExportTable - failed to get "
878 "export table entry name: {0}");
879 continue;
880 }
881 Symbol symbol;
882 // Note: symbol name may be empty if it is only exported by ordinal.
883 symbol.GetMangled().SetValue(ConstString(sym_name));
884
885 uint32_t ordinal;
886 llvm::cantFail(entry.getOrdinal(ordinal));
887 symbol.SetID(ordinal);
888
889 bool is_forwarder;
890 llvm::cantFail(entry.isForwarder(is_forwarder));
891 if (is_forwarder) {
892 // Forwarder exports are redirected by the loader transparently, but keep
893 // it in symtab and make a note using the symbol name.
894 llvm::StringRef forwarder_name;
895 if (auto err = entry.getForwardTo(forwarder_name)) {
896 LLDB_LOG_ERROR(log, std::move(err),
897 "ObjectFilePECOFF::AppendFromExportTable - failed to "
898 "get forwarder name of forwarder export '{1}': {0}",
899 sym_name);
900 continue;
901 }
902 llvm::SmallString<256> new_name = {symbol.GetDisplayName().GetStringRef(),
903 " (forwarded to ", forwarder_name,
904 ")"};
905 symbol.GetMangled().SetDemangledName(ConstString(new_name.str()));
907 }
908
909 uint32_t function_rva;
910 if (auto err = entry.getExportRVA(function_rva)) {
911 LLDB_LOG_ERROR(log, std::move(err),
912 "ObjectFilePECOFF::AppendFromExportTable - failed to get "
913 "address of export entry '{1}': {0}",
914 sym_name);
915 continue;
916 }
917 // Skip the symbol if it doesn't look valid.
918 if (function_rva == 0 && sym_name.empty())
919 continue;
920 symbol.GetAddressRef() =
921 Address(m_coff_header_opt.image_base + function_rva, sect_list);
922
923 // An exported symbol may be either code or data. Guess by checking whether
924 // the section containing the symbol is executable.
926 if (!is_forwarder)
927 if (auto section_sp = symbol.GetAddressRef().GetSection())
928 if (section_sp->GetPermissions() & ePermissionsExecutable)
930 symbol.SetExternal(true);
931 uint32_t idx = symtab.AddSymbol(symbol);
932 export_list.push_back(std::make_pair(function_rva, idx));
933 }
934 llvm::stable_sort(export_list, RVASymbolListCompareRVA);
935 return export_list;
936}
937
938std::unique_ptr<CallFrameInfo> ObjectFilePECOFF::CreateCallFrameInfo() {
939 if (llvm::COFF::EXCEPTION_TABLE >= m_coff_header_opt.data_dirs.size())
940 return {};
941
942 data_directory data_dir_exception =
943 m_coff_header_opt.data_dirs[llvm::COFF::EXCEPTION_TABLE];
944 if (!data_dir_exception.vmaddr)
945 return {};
946
947 // TODO: decode ARM64 .pdata/.xdata so optimized frameless code unwinds.
948 if (m_coff_header.machine != llvm::COFF::IMAGE_FILE_MACHINE_AMD64)
949 return {};
950
951 return std::make_unique<PECallFrameInfo>(*this, data_dir_exception.vmaddr,
952 data_dir_exception.vmsize);
953}
954
957 if (m_binary->is64()) {
958 if (m_binary->getTLSDirectory64())
959 addr = m_binary->getTLSDirectory64()->AddressOfIndex.value();
960 } else if (m_binary->getTLSDirectory32())
961 addr = m_binary->getTLSDirectory32()->AddressOfIndex.value();
962
963 if (addr == 0)
965 return addr;
966}
967
969 // TODO: determine this for COFF
970 return false;
971}
972
974 const section_header_t &sect) {
975 static constexpr llvm::StringLiteral g_code_sect_name(".code");
976 static constexpr llvm::StringLiteral g_CODE_sect_name("CODE");
977 static constexpr llvm::StringLiteral g_data_sect_name(".data");
978 static constexpr llvm::StringLiteral g_DATA_sect_name("DATA");
979 static constexpr llvm::StringLiteral g_bss_sect_name(".bss");
980 static constexpr llvm::StringLiteral g_BSS_sect_name("BSS");
981
982 if (sect.flags & llvm::COFF::IMAGE_SCN_CNT_CODE &&
983 ((sect_name == g_code_sect_name) || (sect_name == g_CODE_sect_name))) {
984 return eSectionTypeCode;
985 }
986 if (sect.flags & llvm::COFF::IMAGE_SCN_CNT_INITIALIZED_DATA &&
987 ((sect_name == g_data_sect_name) || (sect_name == g_DATA_sect_name))) {
988 if (sect.size == 0 && sect.offset == 0)
990 else
991 return eSectionTypeData;
992 }
993 if (sect.flags & llvm::COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA &&
994 ((sect_name == g_bss_sect_name) || (sect_name == g_BSS_sect_name))) {
995 if (sect.size == 0)
997 else
998 return eSectionTypeData;
999 }
1000
1001 if (sect_name.consume_front(".debug_"))
1002 return GetDWARFSectionTypeFromName(sect_name);
1003
1004 SectionType section_type =
1005 llvm::StringSwitch<SectionType>(sect_name)
1006 // PE/COFF image-file section names are limited to 8 characters,
1007 // so the linker truncates the longer source names. Match both.
1008 .Cases({".eh_frame", ".eh_fram"}, eSectionTypeEHFrame)
1009 .Cases({".gosymtab", ".gosymta"}, eSectionTypeGoSymtab)
1010 .Cases({".lldbsummaries", ".lldbsum"},
1012 .Cases({".lldbformatters", ".lldbfor"},
1014 .Case(".debug", eSectionTypeDebug)
1015 .Case(".stabstr", eSectionTypeDataCString)
1016 .Case(".reloc", eSectionTypeOther)
1017 .Case("swiftast", eSectionTypeSwiftModules)
1018 .Default(eSectionTypeInvalid);
1019 if (section_type != eSectionTypeInvalid)
1020 return section_type;
1021
1022 if (sect.flags & llvm::COFF::IMAGE_SCN_CNT_CODE)
1023 return eSectionTypeCode;
1024 if (sect.flags & llvm::COFF::IMAGE_SCN_CNT_INITIALIZED_DATA)
1025 return eSectionTypeData;
1026 if (sect.flags & llvm::COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA) {
1027 if (sect.size == 0)
1028 return eSectionTypeZeroFill;
1029 else
1030 return eSectionTypeData;
1031 }
1032 return eSectionTypeOther;
1033}
1034
1036 // For executables, SizeOfRawData (getFileSize()) is aligned by
1037 // FileAlignment and the actual section size is in VirtualSize
1038 // (getByteSize()). See the comment on
1039 // llvm::object::COFFObjectFile::getSectionSize().
1040 if (m_binary->getPE32Header() || m_binary->getPE32PlusHeader())
1041 return std::min(section->GetByteSize(), section->GetFileSize());
1042 return section->GetFileSize();
1043}
1044
1046 if (m_sections_up)
1047 return;
1048 m_sections_up = std::make_unique<SectionList>();
1049 ModuleSP module_sp(GetModule());
1050 if (module_sp) {
1051 SectionSP header_sp = std::make_shared<Section>(
1052 module_sp, this, ~user_id_t(0), "PECOFF header", eSectionTypeOther,
1053 m_coff_header_opt.image_base, m_coff_header_opt.header_size,
1054 /*file_offset*/ 0, m_coff_header_opt.header_size,
1055 m_coff_header_opt.sect_alignment,
1056 /*flags*/ 0);
1057 header_sp->SetPermissions(ePermissionsReadable);
1058 m_sections_up->AddSection(header_sp);
1059 unified_section_list.AddSection(header_sp);
1060
1061 const uint32_t nsects = m_sect_headers.size();
1062 for (uint32_t idx = 0; idx < nsects; ++idx) {
1063 llvm::StringRef sect_name = GetSectionName(m_sect_headers[idx]);
1064 SectionType section_type = GetSectionType(sect_name, m_sect_headers[idx]);
1065
1066 SectionSP section_sp = std::make_shared<Section>(
1067 module_sp, // Module to which this section belongs
1068 this, // Object file to which this section belongs
1069 idx + 1, // Section ID is the 1 based section index.
1070 sect_name.str(), // Name of this section
1071 section_type,
1072 m_coff_header_opt.image_base +
1073 m_sect_headers[idx].vmaddr, // File VM address == addresses as
1074 // they are found in the object file
1075 m_sect_headers[idx].vmsize, // VM size in bytes of this section
1076 m_sect_headers[idx]
1077 .offset, // Offset to the data for this section in the file
1078 m_sect_headers[idx]
1079 .size, // Size in bytes of this section as found in the file
1080 m_coff_header_opt.sect_alignment, // Section alignment
1081 m_sect_headers[idx].flags); // Flags for this section
1082
1083 uint32_t permissions = 0;
1084 if (m_sect_headers[idx].flags & llvm::COFF::IMAGE_SCN_MEM_EXECUTE)
1085 permissions |= ePermissionsExecutable;
1086 if (m_sect_headers[idx].flags & llvm::COFF::IMAGE_SCN_MEM_READ)
1087 permissions |= ePermissionsReadable;
1088 if (m_sect_headers[idx].flags & llvm::COFF::IMAGE_SCN_MEM_WRITE)
1089 permissions |= ePermissionsWritable;
1090 section_sp->SetPermissions(permissions);
1091
1092 m_sections_up->AddSection(section_sp);
1093 unified_section_list.AddSection(section_sp);
1094 }
1095 }
1096}
1097
1099 if (m_uuid.IsValid())
1100 return m_uuid;
1101
1102 if (!CreateBinary())
1103 return UUID();
1104
1106 return m_uuid;
1107}
1108
1109std::optional<FileSpec> ObjectFilePECOFF::GetDebugLink() {
1110 std::string gnu_debuglink_file;
1111 uint32_t gnu_debuglink_crc;
1112 if (GetDebugLinkContents(*m_binary, gnu_debuglink_file, gnu_debuglink_crc))
1113 return FileSpec(gnu_debuglink_file);
1114 return std::nullopt;
1115}
1116
1117std::optional<FileSpec> ObjectFilePECOFF::GetPDBPath() {
1118 llvm::StringRef pdb_file;
1119 const llvm::codeview::DebugInfo *pdb_info = nullptr;
1120 if (llvm::Error Err = m_binary->getDebugPDBInfo(pdb_info, pdb_file)) {
1121 // DebugInfo section is corrupt.
1122 Log *log = GetLog(LLDBLog::Object);
1123 llvm::StringRef file = m_binary->getFileName();
1125 log, std::move(Err),
1126 "Failed to read Codeview record for PDB debug info file ({1}): {0}",
1127 file);
1128 return std::nullopt;
1129 }
1130 if (pdb_file.empty()) {
1131 // No DebugInfo section present.
1132 return std::nullopt;
1133 }
1134 return FileSpec(pdb_file, FileSpec::GuessPathStyle(pdb_file).value_or(
1135 FileSpec::Style::native));
1136}
1137
1139 ModuleSP module_sp(GetModule());
1140 if (!module_sp)
1141 return 0;
1142
1143 std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex());
1144 if (m_deps_filespec)
1145 return m_deps_filespec->GetSize();
1146
1147 // Cache coff binary if it is not done yet.
1148 if (!CreateBinary())
1149 return 0;
1150
1151 Log *log = GetLog(LLDBLog::Object);
1152 LLDB_LOG(log, "this = {0}, module = {1} ({2}), file = {3}, binary = {4}",
1153 this, GetModule().get(), GetModule()->GetSpecificationDescription(),
1154 m_file.GetPath(), m_binary.get());
1155
1157
1158 for (const auto &entry : m_binary->import_directories()) {
1159 llvm::StringRef dll_name;
1160 // Report a bogus entry.
1161 if (llvm::Error e = entry.getName(dll_name)) {
1162 LLDB_LOGF(log,
1163 "ObjectFilePECOFF::ParseDependentModules() - failed to get "
1164 "import directory entry name: %s",
1165 llvm::toString(std::move(e)).c_str());
1166 continue;
1167 }
1168
1169 // At this moment we only have the base name of the DLL. The full path can
1170 // only be seen after the dynamic loading. Our best guess is Try to get it
1171 // with the help of the object file's directory.
1172 FileSpec dll_specs(dll_name);
1173 dll_specs.SetDirectory(m_file.GetDirectory());
1174
1175 if (FileSystem::Instance().Exists(dll_specs))
1176 m_deps_filespec->Append(dll_specs);
1177 else {
1178 // Known DLLs or DLL not found in the object file directory.
1179 m_deps_filespec->EmplaceBack(dll_name);
1180 }
1181 }
1182 return m_deps_filespec->GetSize();
1183}
1184
1186 auto num_modules = ParseDependentModules();
1187 auto original_size = files.GetSize();
1188
1189 for (unsigned i = 0; i < num_modules; ++i)
1190 files.AppendIfUnique(m_deps_filespec->GetFileSpecAtIndex(i));
1191
1192 return files.GetSize() - original_size;
1193}
1194
1196 if (m_entry_point_address.IsValid())
1197 return m_entry_point_address;
1198
1199 if (!ParseHeader() || !IsExecutable())
1200 return m_entry_point_address;
1201
1202 SectionList *section_list = GetSectionList();
1203 addr_t file_addr = m_coff_header_opt.entry + m_coff_header_opt.image_base;
1204
1205 if (!section_list)
1206 m_entry_point_address.SetOffset(file_addr);
1207 else
1208 m_entry_point_address.ResolveAddressUsingFileSections(file_addr,
1209 section_list);
1210 return m_entry_point_address;
1211}
1212
1214 return Address(GetSectionList()->GetSectionAtIndex(0), 0);
1215}
1216
1217// Dump
1218//
1219// Dump the specifics of the runtime file container (such as any headers
1220// segments, sections, etc).
1222 ModuleSP module_sp(GetModule());
1223 if (module_sp) {
1224 std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex());
1225 s->Printf("%p: ", static_cast<void *>(this));
1226 s->Indent();
1227 s->PutCString("ObjectFilePECOFF");
1228
1229 ArchSpec header_arch = GetArchitecture();
1230
1231 *s << ", file = '" << m_file
1232 << "', arch = " << header_arch.GetArchitectureName() << "\n";
1233
1234 SectionList *sections = GetSectionList();
1235 if (sections)
1236 sections->Dump(s->AsRawOstream(), s->GetIndentLevel(), nullptr, true,
1237 UINT32_MAX);
1238
1239 if (m_symtab_up)
1240 m_symtab_up->Dump(s, nullptr, eSortOrderNone);
1241
1242 if (m_dos_header.e_magic)
1244 if (m_coff_header.machine) {
1246 if (m_coff_header.hdrsize)
1248 }
1249 s->EOL();
1251 s->EOL();
1252
1254 s->EOL();
1255 }
1256}
1257
1258// DumpDOSHeader
1259//
1260// Dump the MS-DOS header to the specified output stream
1262 s->PutCString("MSDOS Header\n");
1263 s->Printf(" e_magic = 0x%4.4x\n", header.e_magic);
1264 s->Printf(" e_cblp = 0x%4.4x\n", header.e_cblp);
1265 s->Printf(" e_cp = 0x%4.4x\n", header.e_cp);
1266 s->Printf(" e_crlc = 0x%4.4x\n", header.e_crlc);
1267 s->Printf(" e_cparhdr = 0x%4.4x\n", header.e_cparhdr);
1268 s->Printf(" e_minalloc = 0x%4.4x\n", header.e_minalloc);
1269 s->Printf(" e_maxalloc = 0x%4.4x\n", header.e_maxalloc);
1270 s->Printf(" e_ss = 0x%4.4x\n", header.e_ss);
1271 s->Printf(" e_sp = 0x%4.4x\n", header.e_sp);
1272 s->Printf(" e_csum = 0x%4.4x\n", header.e_csum);
1273 s->Printf(" e_ip = 0x%4.4x\n", header.e_ip);
1274 s->Printf(" e_cs = 0x%4.4x\n", header.e_cs);
1275 s->Printf(" e_lfarlc = 0x%4.4x\n", header.e_lfarlc);
1276 s->Printf(" e_ovno = 0x%4.4x\n", header.e_ovno);
1277 s->Printf(" e_res[4] = { 0x%4.4x, 0x%4.4x, 0x%4.4x, 0x%4.4x }\n",
1278 header.e_res[0], header.e_res[1], header.e_res[2], header.e_res[3]);
1279 s->Printf(" e_oemid = 0x%4.4x\n", header.e_oemid);
1280 s->Printf(" e_oeminfo = 0x%4.4x\n", header.e_oeminfo);
1281 s->Printf(" e_res2[10] = { 0x%4.4x, 0x%4.4x, 0x%4.4x, 0x%4.4x, 0x%4.4x, "
1282 "0x%4.4x, 0x%4.4x, 0x%4.4x, 0x%4.4x, 0x%4.4x }\n",
1283 header.e_res2[0], header.e_res2[1], header.e_res2[2],
1284 header.e_res2[3], header.e_res2[4], header.e_res2[5],
1285 header.e_res2[6], header.e_res2[7], header.e_res2[8],
1286 header.e_res2[9]);
1287 s->Printf(" e_lfanew = 0x%8.8x\n", header.e_lfanew);
1288}
1289
1290// DumpCOFFHeader
1291//
1292// Dump the COFF header to the specified output stream
1294 s->PutCString("COFF Header\n");
1295 s->Printf(" machine = 0x%4.4x\n", header.machine);
1296 s->Printf(" nsects = 0x%4.4x\n", header.nsects);
1297 s->Printf(" modtime = 0x%8.8x\n", header.modtime);
1298 s->Printf(" symoff = 0x%8.8x\n", header.symoff);
1299 s->Printf(" nsyms = 0x%8.8x\n", header.nsyms);
1300 s->Printf(" hdrsize = 0x%4.4x\n", header.hdrsize);
1301}
1302
1303// DumpOptCOFFHeader
1304//
1305// Dump the optional COFF header to the specified output stream
1307 const coff_opt_header_t &header) {
1308 s->PutCString("Optional COFF Header\n");
1309 s->Printf(" magic = 0x%4.4x\n", header.magic);
1310 s->Printf(" major_linker_version = 0x%2.2x\n",
1311 header.major_linker_version);
1312 s->Printf(" minor_linker_version = 0x%2.2x\n",
1313 header.minor_linker_version);
1314 s->Printf(" code_size = 0x%8.8x\n", header.code_size);
1315 s->Printf(" data_size = 0x%8.8x\n", header.data_size);
1316 s->Printf(" bss_size = 0x%8.8x\n", header.bss_size);
1317 s->Printf(" entry = 0x%8.8x\n", header.entry);
1318 s->Printf(" code_offset = 0x%8.8x\n", header.code_offset);
1319 s->Printf(" data_offset = 0x%8.8x\n", header.data_offset);
1320 s->Printf(" image_base = 0x%16.16" PRIx64 "\n",
1321 header.image_base);
1322 s->Printf(" sect_alignment = 0x%8.8x\n", header.sect_alignment);
1323 s->Printf(" file_alignment = 0x%8.8x\n", header.file_alignment);
1324 s->Printf(" major_os_system_version = 0x%4.4x\n",
1326 s->Printf(" minor_os_system_version = 0x%4.4x\n",
1328 s->Printf(" major_image_version = 0x%4.4x\n",
1329 header.major_image_version);
1330 s->Printf(" minor_image_version = 0x%4.4x\n",
1331 header.minor_image_version);
1332 s->Printf(" major_subsystem_version = 0x%4.4x\n",
1334 s->Printf(" minor_subsystem_version = 0x%4.4x\n",
1336 s->Printf(" reserved1 = 0x%8.8x\n", header.reserved1);
1337 s->Printf(" image_size = 0x%8.8x\n", header.image_size);
1338 s->Printf(" header_size = 0x%8.8x\n", header.header_size);
1339 s->Printf(" checksum = 0x%8.8x\n", header.checksum);
1340 s->Printf(" subsystem = 0x%4.4x\n", header.subsystem);
1341 s->Printf(" dll_flags = 0x%4.4x\n", header.dll_flags);
1342 s->Printf(" stack_reserve_size = 0x%16.16" PRIx64 "\n",
1343 header.stack_reserve_size);
1344 s->Printf(" stack_commit_size = 0x%16.16" PRIx64 "\n",
1345 header.stack_commit_size);
1346 s->Printf(" heap_reserve_size = 0x%16.16" PRIx64 "\n",
1347 header.heap_reserve_size);
1348 s->Printf(" heap_commit_size = 0x%16.16" PRIx64 "\n",
1349 header.heap_commit_size);
1350 s->Printf(" loader_flags = 0x%8.8x\n", header.loader_flags);
1351 s->Printf(" num_data_dir_entries = 0x%8.8x\n",
1352 (uint32_t)header.data_dirs.size());
1353 uint32_t i;
1354 for (i = 0; i < header.data_dirs.size(); i++) {
1355 s->Printf(" data_dirs[%2u] vmaddr = 0x%8.8x, vmsize = 0x%8.8x\n", i,
1356 header.data_dirs[i].vmaddr, header.data_dirs[i].vmsize);
1357 }
1358}
1359// DumpSectionHeader
1360//
1361// Dump a single ELF section header to the specified output stream
1363 const section_header_t &sh) {
1364 std::string name = std::string(GetSectionName(sh));
1365 s->Printf("%-16s 0x%8.8x 0x%8.8x 0x%8.8x 0x%8.8x 0x%8.8x 0x%8.8x 0x%4.4x "
1366 "0x%4.4x 0x%8.8x\n",
1367 name.c_str(), sh.vmaddr, sh.vmsize, sh.offset, sh.size, sh.reloff,
1368 sh.lineoff, sh.nreloc, sh.nline, sh.flags);
1369}
1370
1371// DumpSectionHeaders
1372//
1373// Dump all of the ELF section header to the specified output stream
1375
1376 s->PutCString("Section Headers\n");
1377 s->PutCString("IDX name vm addr vm size file off file "
1378 "size reloc off line off nreloc nline flags\n");
1379 s->PutCString("==== ---------------- ---------- ---------- ---------- "
1380 "---------- ---------- ---------- ------ ------ ----------\n");
1381
1382 uint32_t idx = 0;
1383 SectionHeaderCollIter pos, end = m_sect_headers.end();
1384
1385 for (pos = m_sect_headers.begin(); pos != end; ++pos, ++idx) {
1386 s->Printf("[%2u] ", idx);
1388 }
1389}
1390
1391// DumpDependentModules
1392//
1393// Dump all of the dependent modules to the specified output stream
1395 auto num_modules = ParseDependentModules();
1396 if (num_modules > 0) {
1397 s->PutCString("Dependent Modules\n");
1398 for (unsigned i = 0; i < num_modules; ++i) {
1399 auto spec = m_deps_filespec->GetFileSpecAtIndex(i);
1400 s->Format(" {0}\n", spec.GetFilename());
1401 }
1402 }
1403}
1404
1406 switch (m_coff_header_opt.subsystem) {
1407 case llvm::COFF::IMAGE_SUBSYSTEM_NATIVE:
1408 case llvm::COFF::IMAGE_SUBSYSTEM_WINDOWS_GUI:
1409 case llvm::COFF::IMAGE_SUBSYSTEM_WINDOWS_CUI:
1410 case llvm::COFF::IMAGE_SUBSYSTEM_NATIVE_WINDOWS:
1411 case llvm::COFF::IMAGE_SUBSYSTEM_WINDOWS_CE_GUI:
1412 case llvm::COFF::IMAGE_SUBSYSTEM_XBOX:
1413 case llvm::COFF::IMAGE_SUBSYSTEM_WINDOWS_BOOT_APPLICATION:
1414 return true;
1415 default:
1416 return false;
1417 }
1418}
1419
1421 uint16_t machine = m_coff_header.machine;
1422 switch (machine) {
1423 default:
1424 break;
1425 case llvm::COFF::IMAGE_FILE_MACHINE_AMD64:
1426 case llvm::COFF::IMAGE_FILE_MACHINE_I386:
1427 case llvm::COFF::IMAGE_FILE_MACHINE_POWERPC:
1428 case llvm::COFF::IMAGE_FILE_MACHINE_POWERPCFP:
1429 case llvm::COFF::IMAGE_FILE_MACHINE_ARM:
1430 case llvm::COFF::IMAGE_FILE_MACHINE_ARMNT:
1431 case llvm::COFF::IMAGE_FILE_MACHINE_THUMB:
1432 case llvm::COFF::IMAGE_FILE_MACHINE_ARM64:
1433 ArchSpec arch;
1435 IsWindowsSubsystem() ? llvm::Triple::Win32
1436 : llvm::Triple::UnknownOS);
1437 return arch;
1438 }
1439 return ArchSpec();
1440}
1441
1443 if (m_coff_header.machine != 0) {
1444 if ((m_coff_header.flags & llvm::COFF::IMAGE_FILE_DLL) == 0)
1445 return eTypeExecutable;
1446 else
1447 return eTypeSharedLibrary;
1448 }
1449 return eTypeExecutable;
1450}
1451
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:91
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:789
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:792
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:781
@ 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:785
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:3536
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