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