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 ConstString g_sect_name_gnu_debuglink(".gnu_debuglink");
114 for (const auto &section : coff_obj.sections()) {
115 auto name = section.getName();
116 if (!name) {
117 llvm::consumeError(name.takeError());
118 continue;
119 }
120 if (*name == g_sect_name_gnu_debuglink.GetStringRef()) {
121 auto content = section.getContents();
122 if (!content) {
123 llvm::consumeError(content.takeError());
124 return false;
125 }
126 DataExtractor data(
127 content->data(), content->size(),
128 coff_obj.isLittleEndian() ? eByteOrderLittle : eByteOrderBig, 4);
129 lldb::offset_t gnu_debuglink_offset = 0;
130 gnu_debuglink_file = data.GetCStr(&gnu_debuglink_offset);
131 // Align to the next 4-byte offset
132 gnu_debuglink_offset = llvm::alignTo(gnu_debuglink_offset, 4);
133 data.GetU32(&gnu_debuglink_offset, &gnu_debuglink_crc, 1);
134 return true;
135 }
136 }
137 return false;
138}
139
140static UUID GetCoffUUID(llvm::object::COFFObjectFile &coff_obj) {
141 const llvm::codeview::DebugInfo *pdb_info = nullptr;
142 llvm::StringRef pdb_file;
143
144 // First, prefer to use the PDB build id. LLD generates this even for mingw
145 // targets without PDB output, and it does not get stripped either.
146 if (!coff_obj.getDebugPDBInfo(pdb_info, pdb_file) && pdb_info) {
147 if (pdb_info->PDB70.CVSignature == llvm::OMF::Signature::PDB70) {
149 memcpy(&info.Uuid, pdb_info->PDB70.Signature, sizeof(info.Uuid));
150 info.Age = pdb_info->PDB70.Age;
151 return UUID(info);
152 }
153 }
154
155 std::string gnu_debuglink_file;
156 uint32_t gnu_debuglink_crc;
157
158 // The GNU linker normally does not write a PDB build id (unless requested
159 // with the --build-id option), so we should fall back to using the crc
160 // from .gnu_debuglink if it exists, just like how ObjectFileELF does it.
161 if (!GetDebugLinkContents(coff_obj, gnu_debuglink_file, gnu_debuglink_crc)) {
162 // If there is no .gnu_debuglink section, then this may be an object
163 // containing DWARF debug info for .gnu_debuglink, so calculate the crc of
164 // the object itself.
165 auto raw_data = coff_obj.getData();
167 "Calculating module crc32 %s with size %" PRIu64 " KiB",
168 FileSpec(coff_obj.getFileName()).GetFilename().AsCString(),
169 static_cast<lldb::offset_t>(raw_data.size()) / 1024);
170 gnu_debuglink_crc = llvm::crc32(0, llvm::arrayRefFromStringRef(raw_data));
171 }
172 // Use 4 bytes of crc from the .gnu_debuglink section.
173 llvm::support::ulittle32_t data(gnu_debuglink_crc);
174 return UUID(&data, sizeof(data));
175}
176
178
185
188 debugger, PluginProperties::GetSettingName())) {
189 const bool is_global_setting = true;
191 debugger, GetGlobalPluginProperties().GetValueProperties(),
192 "Properties for the PE/COFF object-file plug-in.", is_global_setting);
193 }
194}
195
199
201 return "Portable Executable and Common Object File Format object file reader "
202 "(32 and 64 bit)";
203}
204
206 const lldb::ModuleSP &module_sp, DataExtractorSP extractor_sp,
207 lldb::offset_t data_offset, const lldb_private::FileSpec *file_p,
208 lldb::offset_t file_offset, lldb::offset_t length) {
209 FileSpec file = file_p ? *file_p : FileSpec();
210 if (!extractor_sp || !extractor_sp->HasData()) {
211 DataBufferSP data_sp = MapFileData(file, length, file_offset);
212 if (!data_sp)
213 return nullptr;
214 data_offset = 0;
215 extractor_sp = std::make_shared<DataExtractor>(data_sp);
216 }
217
218 if (!ObjectFilePECOFF::MagicBytesMatch(extractor_sp))
219 return nullptr;
220
221 // Update the data to contain the entire file if it doesn't already
222 if (extractor_sp->GetByteSize() < length) {
223 DataBufferSP data_sp = MapFileData(file, length, file_offset);
224 if (!data_sp)
225 return nullptr;
226 extractor_sp = std::make_shared<DataExtractor>(data_sp);
227 }
228
229 auto objfile_up = std::make_unique<ObjectFilePECOFF>(
230 module_sp, extractor_sp, data_offset, file_p, file_offset, length);
231 if (!objfile_up || !objfile_up->ParseHeader())
232 return nullptr;
233
234 // Cache coff binary.
235 if (!objfile_up->CreateBinary())
236 return nullptr;
237 return objfile_up.release();
238}
239
241 const lldb::ModuleSP &module_sp, lldb::WritableDataBufferSP data_sp,
242 const lldb::ProcessSP &process_sp, lldb::addr_t header_addr) {
243 if (!data_sp)
244 return nullptr;
245 DataExtractorSP extractor_sp =
246 std::make_shared<DataExtractor>(data_sp, eByteOrderLittle, 4);
247 if (!ObjectFilePECOFF::MagicBytesMatch(extractor_sp))
248 return nullptr;
249 auto objfile_up = std::make_unique<ObjectFilePECOFF>(
250 module_sp, data_sp, process_sp, header_addr);
251 if (objfile_up.get() && objfile_up->ParseHeader()) {
252 return objfile_up.release();
253 }
254 return nullptr;
255}
256
258 const lldb_private::FileSpec &file, lldb::DataExtractorSP &extractor_sp,
259 lldb::offset_t file_offset, lldb::offset_t length) {
260 if (!extractor_sp || !extractor_sp->HasData() ||
262 return {};
263
264 Log *log = GetLog(LLDBLog::Object);
265
266 if (extractor_sp->GetByteSize() < length)
267 if (DataBufferSP full_sp = MapFileData(file, -1, file_offset))
268 extractor_sp->SetData(std::move(full_sp));
269 auto binary = llvm::object::createBinary(llvm::MemoryBufferRef(
270 toStringRef(extractor_sp->GetSharedDataBuffer()->GetData()),
271 file.GetFilename().GetStringRef()));
272
273 if (!binary) {
274 LLDB_LOG_ERROR(log, binary.takeError(),
275 "Failed to create binary for file ({1}): {0}", file);
276 return {};
277 }
278
279 auto *COFFObj = llvm::dyn_cast<llvm::object::COFFObjectFile>(binary->get());
280 if (!COFFObj)
281 return {};
282
283 ModuleSpec module_spec(file);
284 ArchSpec &spec = module_spec.GetArchitecture();
285 lldb_private::UUID &uuid = module_spec.GetUUID();
286 if (!uuid.IsValid())
287 uuid = GetCoffUUID(*COFFObj);
288
289 static llvm::Triple::EnvironmentType default_env = [] {
290 auto def_target = llvm::Triple(
291 llvm::Triple::normalize(llvm::sys::getDefaultTargetTriple()));
292 if (def_target.getOS() == llvm::Triple::Win32 &&
293 def_target.getEnvironment() != llvm::Triple::UnknownEnvironment)
294 return def_target.getEnvironment();
295 return llvm::Triple::MSVC;
296 }();
297
298 // Check for a module-specific override.
299 OptionValueSP module_env_option;
300 const auto *map = GetGlobalPluginProperties().ModuleABIMap();
301 if (map->GetNumValues() > 0) {
302 // Step 1: Try with the exact file name.
303 auto name = file.GetFilename();
304 module_env_option = map->GetValueForKey(name);
305 if (!module_env_option) {
306 // Step 2: Try with the file name in lowercase.
307 auto name_lower = name.GetStringRef().lower();
308 module_env_option = map->GetValueForKey(llvm::StringRef(name_lower));
309 }
310 if (!module_env_option) {
311 // Step 3: Try with the file name with ".debug" suffix stripped.
312 auto name_stripped = name.GetStringRef();
313 if (name_stripped.consume_back_insensitive(".debug")) {
314 module_env_option = map->GetValueForKey(name_stripped);
315 if (!module_env_option) {
316 // Step 4: Try with the file name in lowercase with ".debug" suffix
317 // stripped.
318 auto name_lower = name_stripped.lower();
319 module_env_option = map->GetValueForKey(llvm::StringRef(name_lower));
320 }
321 }
322 }
323 }
324 llvm::Triple::EnvironmentType env;
325 if (module_env_option)
326 env =
327 module_env_option->GetValueAs<llvm::Triple::EnvironmentType>().value_or(
328 static_cast<llvm::Triple::EnvironmentType>(0));
329 else
330 env = GetGlobalPluginProperties().ABI();
331
332 if (env == llvm::Triple::UnknownEnvironment)
333 env = default_env;
334
335 ModuleSpecList specs;
336 switch (COFFObj->getMachine()) {
337 case MachineAmd64:
338 spec.SetTriple("x86_64-pc-windows");
339 spec.GetTriple().setEnvironment(env);
340 specs.Append(module_spec);
341 break;
342 case MachineX86:
343 spec.SetTriple("i386-pc-windows");
344 spec.GetTriple().setEnvironment(env);
345 specs.Append(module_spec);
346 break;
347 case MachineArmNt:
348 spec.SetTriple("armv7-pc-windows");
349 spec.GetTriple().setEnvironment(env);
350 specs.Append(module_spec);
351 break;
352 case MachineArm64:
353 case MachineArm64X:
354 spec.SetTriple("aarch64-pc-windows");
355 spec.GetTriple().setEnvironment(env);
356 specs.Append(module_spec);
357 break;
358 default:
359 break;
360 }
361
362 return specs;
363}
364
368 // Outfile and process_sp are validated by PluginManager::SaveCore
369 assert(options.GetOutputFile().has_value());
370 assert(process_sp);
371 return SaveMiniDump(process_sp, options, error);
372}
373
375 lldb::offset_t offset = 0;
376 uint16_t magic = extractor_sp->GetU16(&offset);
377 return magic == IMAGE_DOS_SIGNATURE;
378}
379
381 // TODO: We need to complete this mapping of COFF symbol types to LLDB ones.
382 // For now, here's a hack to make sure our function have types.
383 const auto complex_type =
384 coff_symbol_type >> llvm::COFF::SCT_COMPLEX_TYPE_SHIFT;
385 if (complex_type == llvm::COFF::IMAGE_SYM_DTYPE_FUNCTION) {
387 }
388 const auto base_type = coff_symbol_type & 0xff;
389 if (base_type == llvm::COFF::IMAGE_SYM_TYPE_NULL &&
390 complex_type == llvm::COFF::IMAGE_SYM_DTYPE_NULL) {
391 // Unknown type. LLD and GNU ld uses this for variables on MinGW, so
392 // consider these symbols to be data to enable printing.
394 }
396}
397
399 if (m_binary)
400 return true;
401
402 Log *log = GetLog(LLDBLog::Object);
403
404 auto binary = llvm::object::createBinary(llvm::MemoryBufferRef(
405 toStringRef(m_data_nsp->GetData()), m_file.GetFilename().GetStringRef()));
406 if (!binary) {
407 LLDB_LOG_ERROR(log, binary.takeError(),
408 "Failed to create binary for file ({1}): {0}", m_file);
409 return false;
410 }
411
412 // Make sure we only handle COFF format.
413 m_binary =
414 llvm::unique_dyn_cast<llvm::object::COFFObjectFile>(std::move(*binary));
415 if (!m_binary)
416 return false;
417
418 LLDB_LOG(log, "this = {0}, module = {1} ({2}), file = {3}, binary = {4}",
419 this, GetModule().get(), GetModule()->GetSpecificationDescription(),
420 m_file.GetPath(), m_binary.get());
421 return true;
422}
423
425 DataExtractorSP extractor_sp,
426 lldb::offset_t data_offset,
427 const FileSpec *file,
428 lldb::offset_t file_offset,
429 lldb::offset_t length)
430 : ObjectFile(module_sp, file, file_offset, length, extractor_sp,
431 data_offset),
434 m_deps_filespec() {}
435
437 WritableDataBufferSP header_data_sp,
438 const lldb::ProcessSP &process_sp,
439 addr_t header_addr)
440 : ObjectFile(module_sp, process_sp, header_addr,
441 std::make_shared<DataExtractor>(header_data_sp)),
444 m_deps_filespec() {}
445
447
449 ModuleSP module_sp(GetModule());
450 if (module_sp) {
451 std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex());
452 m_sect_headers.clear();
453 m_data_nsp->SetByteOrder(eByteOrderLittle);
454 lldb::offset_t offset = 0;
455
457 offset = m_dos_header.e_lfanew;
458 uint32_t pe_signature = m_data_nsp->GetU32(&offset);
459 if (pe_signature != IMAGE_NT_SIGNATURE)
460 return false;
461 if (ParseCOFFHeader(*m_data_nsp, &offset, m_coff_header)) {
462 if (m_coff_header.hdrsize > 0)
464 ParseSectionHeaders(offset);
465 }
466 m_data_nsp->SetAddressByteSize(GetAddressByteSize());
467 return true;
468 }
469 }
470 return false;
471}
472
474 bool value_is_offset) {
475 bool changed = false;
476 ModuleSP module_sp = GetModule();
477 if (module_sp) {
478 size_t num_loaded_sections = 0;
479 SectionList *section_list = GetSectionList();
480 if (section_list) {
481 if (!value_is_offset) {
482 value -= m_image_base;
483 }
484
485 const size_t num_sections = section_list->GetSize();
486 size_t sect_idx = 0;
487
488 for (sect_idx = 0; sect_idx < num_sections; ++sect_idx) {
489 // Iterate through the object file sections to find all of the sections
490 // that have SHF_ALLOC in their flag bits.
491 SectionSP section_sp(section_list->GetSectionAtIndex(sect_idx));
492 if (section_sp && !section_sp->IsThreadSpecific()) {
493 if (target.SetSectionLoadAddress(
494 section_sp, section_sp->GetFileAddress() + value))
495 ++num_loaded_sections;
496 }
497 }
498 changed = num_loaded_sections > 0;
499 }
500 }
501 return changed;
502}
503
505
507 return (m_coff_header.flags & llvm::COFF::IMAGE_FILE_DLL) == 0;
508}
509
512 return 8;
514 return 4;
515 return 4;
516}
517
518// NeedsEndianSwap
519//
520// Return true if an endian swap needs to occur when extracting data from this
521// file.
523#if defined(__LITTLE_ENDIAN__)
524 return false;
525#else
526 return true;
527#endif
528}
529// ParseDOSHeader
532 bool success = false;
533 lldb::offset_t offset = 0;
534 success = data.ValidOffsetForDataOfSize(0, sizeof(dos_header));
535
536 if (success) {
537 dos_header.e_magic = data.GetU16(&offset); // Magic number
539
540 if (success) {
541 dos_header.e_cblp = data.GetU16(&offset); // Bytes on last page of file
542 dos_header.e_cp = data.GetU16(&offset); // Pages in file
543 dos_header.e_crlc = data.GetU16(&offset); // Relocations
545 data.GetU16(&offset); // Size of header in paragraphs
547 data.GetU16(&offset); // Minimum extra paragraphs needed
549 data.GetU16(&offset); // Maximum extra paragraphs needed
550 dos_header.e_ss = data.GetU16(&offset); // Initial (relative) SS value
551 dos_header.e_sp = data.GetU16(&offset); // Initial SP value
552 dos_header.e_csum = data.GetU16(&offset); // Checksum
553 dos_header.e_ip = data.GetU16(&offset); // Initial IP value
554 dos_header.e_cs = data.GetU16(&offset); // Initial (relative) CS value
556 data.GetU16(&offset); // File address of relocation table
557 dos_header.e_ovno = data.GetU16(&offset); // Overlay number
558
559 dos_header.e_res[0] = data.GetU16(&offset); // Reserved words
560 dos_header.e_res[1] = data.GetU16(&offset); // Reserved words
561 dos_header.e_res[2] = data.GetU16(&offset); // Reserved words
562 dos_header.e_res[3] = data.GetU16(&offset); // Reserved words
563
565 data.GetU16(&offset); // OEM identifier (for e_oeminfo)
567 data.GetU16(&offset); // OEM information; e_oemid specific
568 dos_header.e_res2[0] = data.GetU16(&offset); // Reserved words
569 dos_header.e_res2[1] = data.GetU16(&offset); // Reserved words
570 dos_header.e_res2[2] = data.GetU16(&offset); // Reserved words
571 dos_header.e_res2[3] = data.GetU16(&offset); // Reserved words
572 dos_header.e_res2[4] = data.GetU16(&offset); // Reserved words
573 dos_header.e_res2[5] = data.GetU16(&offset); // Reserved words
574 dos_header.e_res2[6] = data.GetU16(&offset); // Reserved words
575 dos_header.e_res2[7] = data.GetU16(&offset); // Reserved words
576 dos_header.e_res2[8] = data.GetU16(&offset); // Reserved words
577 dos_header.e_res2[9] = data.GetU16(&offset); // Reserved words
578
580 data.GetU32(&offset); // File address of new exe header
581 }
582 }
583 if (!success)
584 memset(&dos_header, 0, sizeof(dos_header));
585 return success;
586}
587
588// ParserCOFFHeader
590 lldb::offset_t *offset_ptr,
592 bool success =
593 data.ValidOffsetForDataOfSize(*offset_ptr, sizeof(coff_header));
594 if (success) {
595 coff_header.machine = data.GetU16(offset_ptr);
596 coff_header.nsects = data.GetU16(offset_ptr);
597 coff_header.modtime = data.GetU32(offset_ptr);
598 coff_header.symoff = data.GetU32(offset_ptr);
599 coff_header.nsyms = data.GetU32(offset_ptr);
600 coff_header.hdrsize = data.GetU16(offset_ptr);
601 coff_header.flags = data.GetU16(offset_ptr);
602 }
603 if (!success)
604 memset(&coff_header, 0, sizeof(coff_header));
605 return success;
606}
607
609 bool success = false;
610 const lldb::offset_t end_offset = *offset_ptr + m_coff_header.hdrsize;
611 if (*offset_ptr < end_offset) {
612 success = true;
613 m_coff_header_opt.magic = m_data_nsp->GetU16(offset_ptr);
614 m_coff_header_opt.major_linker_version = m_data_nsp->GetU8(offset_ptr);
615 m_coff_header_opt.minor_linker_version = m_data_nsp->GetU8(offset_ptr);
616 m_coff_header_opt.code_size = m_data_nsp->GetU32(offset_ptr);
617 m_coff_header_opt.data_size = m_data_nsp->GetU32(offset_ptr);
618 m_coff_header_opt.bss_size = m_data_nsp->GetU32(offset_ptr);
619 m_coff_header_opt.entry = m_data_nsp->GetU32(offset_ptr);
620 m_coff_header_opt.code_offset = m_data_nsp->GetU32(offset_ptr);
621
622 const uint32_t addr_byte_size = GetAddressByteSize();
623
624 if (*offset_ptr < end_offset) {
626 // PE32 only
627 m_coff_header_opt.data_offset = m_data_nsp->GetU32(offset_ptr);
628 } else
629 m_coff_header_opt.data_offset = 0;
630
631 if (*offset_ptr < end_offset) {
632 m_coff_header_opt.image_base =
633 m_data_nsp->GetMaxU64(offset_ptr, addr_byte_size);
634 m_coff_header_opt.sect_alignment = m_data_nsp->GetU32(offset_ptr);
635 m_coff_header_opt.file_alignment = m_data_nsp->GetU32(offset_ptr);
636 m_coff_header_opt.major_os_system_version =
637 m_data_nsp->GetU16(offset_ptr);
638 m_coff_header_opt.minor_os_system_version =
639 m_data_nsp->GetU16(offset_ptr);
640 m_coff_header_opt.major_image_version = m_data_nsp->GetU16(offset_ptr);
641 m_coff_header_opt.minor_image_version = m_data_nsp->GetU16(offset_ptr);
642 m_coff_header_opt.major_subsystem_version =
643 m_data_nsp->GetU16(offset_ptr);
644 m_coff_header_opt.minor_subsystem_version =
645 m_data_nsp->GetU16(offset_ptr);
646 m_coff_header_opt.reserved1 = m_data_nsp->GetU32(offset_ptr);
647 m_coff_header_opt.image_size = m_data_nsp->GetU32(offset_ptr);
648 m_coff_header_opt.header_size = m_data_nsp->GetU32(offset_ptr);
649 m_coff_header_opt.checksum = m_data_nsp->GetU32(offset_ptr);
650 m_coff_header_opt.subsystem = m_data_nsp->GetU16(offset_ptr);
651 m_coff_header_opt.dll_flags = m_data_nsp->GetU16(offset_ptr);
652 m_coff_header_opt.stack_reserve_size =
653 m_data_nsp->GetMaxU64(offset_ptr, addr_byte_size);
654 m_coff_header_opt.stack_commit_size =
655 m_data_nsp->GetMaxU64(offset_ptr, addr_byte_size);
656 m_coff_header_opt.heap_reserve_size =
657 m_data_nsp->GetMaxU64(offset_ptr, addr_byte_size);
658 m_coff_header_opt.heap_commit_size =
659 m_data_nsp->GetMaxU64(offset_ptr, addr_byte_size);
660 m_coff_header_opt.loader_flags = m_data_nsp->GetU32(offset_ptr);
661 uint32_t num_data_dir_entries = m_data_nsp->GetU32(offset_ptr);
662 m_coff_header_opt.data_dirs.clear();
663 m_coff_header_opt.data_dirs.resize(num_data_dir_entries);
664 uint32_t i;
665 for (i = 0; i < num_data_dir_entries; i++) {
666 m_coff_header_opt.data_dirs[i].vmaddr =
667 m_data_nsp->GetU32(offset_ptr);
668 m_coff_header_opt.data_dirs[i].vmsize =
669 m_data_nsp->GetU32(offset_ptr);
670 }
671
672 m_image_base = m_coff_header_opt.image_base;
673 }
674 }
675 }
676 // Make sure we are on track for section data which follows
677 *offset_ptr = end_offset;
678 return success;
679}
680
681uint32_t ObjectFilePECOFF::GetRVA(const Address &addr) const {
682 return addr.GetFileAddress() - m_image_base;
683}
684
686 SectionList *sect_list = GetSectionList();
687 if (!sect_list)
688 return Address(GetFileAddress(rva));
689
690 return Address(GetFileAddress(rva), sect_list);
691}
692
694 return m_image_base + rva;
695}
696
697DataExtractor ObjectFilePECOFF::ReadImageData(uint32_t offset, size_t size) {
698 if (!size)
699 return {};
700
701 if (m_data_nsp->ValidOffsetForDataOfSize(offset, size))
702 return DataExtractor(*m_data_nsp, offset, size);
703
704 ProcessSP process_sp(m_process_wp.lock());
705 DataExtractor data;
706 if (process_sp) {
707 auto data_up = std::make_unique<DataBufferHeap>(size, 0);
708 Status readmem_error;
709 size_t bytes_read =
710 process_sp->ReadMemory(m_image_base + offset, data_up->GetBytes(),
711 data_up->GetByteSize(), readmem_error);
712 if (bytes_read == size) {
713 DataBufferSP buffer_sp(data_up.release());
714 data.SetData(buffer_sp, 0, buffer_sp->GetByteSize());
715 }
716 }
717 return data;
718}
719
721 Address addr = GetAddress(rva);
722 SectionSP sect = addr.GetSection();
723 if (!sect)
724 return {};
725 rva = sect->GetFileOffset() + addr.GetOffset();
726
727 return ReadImageData(rva, size);
728}
729
730// ParseSectionHeaders
732 uint32_t section_header_data_offset) {
733 const uint32_t nsects = m_coff_header.nsects;
734 m_sect_headers.clear();
735
736 if (nsects > 0) {
737 const size_t section_header_byte_size = nsects * sizeof(section_header_t);
738 DataExtractor section_header_data =
739 ReadImageData(section_header_data_offset, section_header_byte_size);
740
741 lldb::offset_t offset = 0;
742 if (section_header_data.ValidOffsetForDataOfSize(
743 offset, section_header_byte_size)) {
744 m_sect_headers.resize(nsects);
745
746 for (uint32_t idx = 0; idx < nsects; ++idx) {
747 const void *name_data = section_header_data.GetData(&offset, 8);
748 if (name_data) {
749 memcpy(m_sect_headers[idx].name, name_data, 8);
750 m_sect_headers[idx].vmsize = section_header_data.GetU32(&offset);
751 m_sect_headers[idx].vmaddr = section_header_data.GetU32(&offset);
752 m_sect_headers[idx].size = section_header_data.GetU32(&offset);
753 m_sect_headers[idx].offset = section_header_data.GetU32(&offset);
754 m_sect_headers[idx].reloff = section_header_data.GetU32(&offset);
755 m_sect_headers[idx].lineoff = section_header_data.GetU32(&offset);
756 m_sect_headers[idx].nreloc = section_header_data.GetU16(&offset);
757 m_sect_headers[idx].nline = section_header_data.GetU16(&offset);
758 m_sect_headers[idx].flags = section_header_data.GetU32(&offset);
759 }
760 }
761 }
762 }
763
764 return !m_sect_headers.empty();
765}
766
768 llvm::StringRef hdr_name(sect.name, std::size(sect.name));
769 hdr_name = hdr_name.split('\0').first;
770 if (hdr_name.consume_front("/")) {
771 lldb::offset_t stroff;
772 if (!to_integer(hdr_name, stroff, 10))
773 return "";
774 lldb::offset_t string_file_offset =
775 m_coff_header.symoff + (m_coff_header.nsyms * 18) + stroff;
776 if (const char *name = m_data_nsp->GetCStr(&string_file_offset))
777 return name;
778 return "";
779 }
780 return hdr_name;
781}
782
784 SectionList *sect_list = GetSectionList();
785 rva_symbol_list_t sorted_exports = AppendFromExportTable(sect_list, symtab);
786 AppendFromCOFFSymbolTable(sect_list, symtab, sorted_exports);
787}
788
789static bool RVASymbolListCompareRVA(const std::pair<uint32_t, uint32_t> &a,
790 const std::pair<uint32_t, uint32_t> &b) {
791 return a.first < b.first;
792}
793
795 SectionList *sect_list, Symtab &symtab,
796 const ObjectFilePECOFF::rva_symbol_list_t &sorted_exports) {
797 const uint32_t num_syms = m_binary->getNumberOfSymbols();
798 if (num_syms == 0)
799 return;
800 // Check that this is not a bigobj; we do not support bigobj.
801 if (m_binary->getSymbolTableEntrySize() !=
802 sizeof(llvm::object::coff_symbol16))
803 return;
804
805 Log *log = GetLog(LLDBLog::Object);
806 symtab.Reserve(symtab.GetNumSymbols() + num_syms);
807 for (const auto &sym_ref : m_binary->symbols()) {
808 const auto coff_sym_ref = m_binary->getCOFFSymbol(sym_ref);
809 auto name_or_error = sym_ref.getName();
810 if (!name_or_error) {
811 LLDB_LOG_ERROR(log, name_or_error.takeError(),
812 "ObjectFilePECOFF::AppendFromCOFFSymbolTable - failed to "
813 "get symbol table entry name: {0}");
814 continue;
815 }
816 const llvm::StringRef sym_name = *name_or_error;
817 Symbol symbol;
818 symbol.GetMangled().SetValue(ConstString(sym_name));
819 int16_t section_number =
820 static_cast<int16_t>(coff_sym_ref.getSectionNumber());
821 if (section_number >= 1) {
822 symbol.GetAddressRef() = Address(
823 sect_list->FindSectionByID(section_number), coff_sym_ref.getValue());
824 const auto symbol_type = MapSymbolType(coff_sym_ref.getType());
825 symbol.SetType(symbol_type);
826
827 // Check for duplicate of exported symbols:
828 const uint32_t symbol_rva = symbol.GetAddressRef().GetFileAddress() -
829 m_coff_header_opt.image_base;
830 const auto &first_match = std::lower_bound(
831 sorted_exports.begin(), sorted_exports.end(),
832 std::make_pair(symbol_rva, 0), RVASymbolListCompareRVA);
833 for (auto it = first_match;
834 it != sorted_exports.end() && it->first == symbol_rva; ++it) {
835 Symbol *exported = symtab.SymbolAtIndex(it->second);
836 if (symbol_type != lldb::eSymbolTypeInvalid)
837 exported->SetType(symbol_type);
838 if (exported->GetMangled() == symbol.GetMangled()) {
839 symbol.SetExternal(true);
840 // We don't want the symbol to be duplicated (e.g. when running
841 // `disas -n func`), but we also don't want to erase this entry (to
842 // preserve the original symbol order), so we mark it as additional.
844 } else {
845 // It is possible for a symbol to be exported in a different name
846 // from its original. In this case keep both entries so lookup using
847 // either names will work. If this symbol has an invalid type, replace
848 // it with the type from the export symbol.
849 if (symbol.GetType() == lldb::eSymbolTypeInvalid)
850 symbol.SetType(exported->GetType());
851 }
852 }
853 } else if (section_number == llvm::COFF::IMAGE_SYM_ABSOLUTE) {
854 symbol.GetAddressRef() = Address(coff_sym_ref.getValue());
856 }
857 symtab.AddSymbol(symbol);
858 }
859}
860
863 Symtab &symtab) {
864 const auto *export_table = m_binary->getExportTable();
865 if (!export_table)
866 return {};
867 const uint32_t num_syms = export_table->AddressTableEntries;
868 if (num_syms == 0)
869 return {};
870
871 Log *log = GetLog(LLDBLog::Object);
872 rva_symbol_list_t export_list;
873 symtab.Reserve(symtab.GetNumSymbols() + num_syms);
874 // Read each export table entry, ordered by ordinal instead of by name.
875 for (const auto &entry : m_binary->export_directories()) {
876 llvm::StringRef sym_name;
877 if (auto err = entry.getSymbolName(sym_name)) {
878 LLDB_LOG_ERROR(log, std::move(err),
879 "ObjectFilePECOFF::AppendFromExportTable - failed to get "
880 "export table entry name: {0}");
881 continue;
882 }
883 Symbol symbol;
884 // Note: symbol name may be empty if it is only exported by ordinal.
885 symbol.GetMangled().SetValue(ConstString(sym_name));
886
887 uint32_t ordinal;
888 llvm::cantFail(entry.getOrdinal(ordinal));
889 symbol.SetID(ordinal);
890
891 bool is_forwarder;
892 llvm::cantFail(entry.isForwarder(is_forwarder));
893 if (is_forwarder) {
894 // Forwarder exports are redirected by the loader transparently, but keep
895 // it in symtab and make a note using the symbol name.
896 llvm::StringRef forwarder_name;
897 if (auto err = entry.getForwardTo(forwarder_name)) {
898 LLDB_LOG_ERROR(log, std::move(err),
899 "ObjectFilePECOFF::AppendFromExportTable - failed to "
900 "get forwarder name of forwarder export '{1}': {0}",
901 sym_name);
902 continue;
903 }
904 llvm::SmallString<256> new_name = {symbol.GetDisplayName().GetStringRef(),
905 " (forwarded to ", forwarder_name,
906 ")"};
907 symbol.GetMangled().SetDemangledName(ConstString(new_name.str()));
909 }
910
911 uint32_t function_rva;
912 if (auto err = entry.getExportRVA(function_rva)) {
913 LLDB_LOG_ERROR(log, std::move(err),
914 "ObjectFilePECOFF::AppendFromExportTable - failed to get "
915 "address of export entry '{1}': {0}",
916 sym_name);
917 continue;
918 }
919 // Skip the symbol if it doesn't look valid.
920 if (function_rva == 0 && sym_name.empty())
921 continue;
922 symbol.GetAddressRef() =
923 Address(m_coff_header_opt.image_base + function_rva, sect_list);
924
925 // An exported symbol may be either code or data. Guess by checking whether
926 // the section containing the symbol is executable.
928 if (!is_forwarder)
929 if (auto section_sp = symbol.GetAddressRef().GetSection())
930 if (section_sp->GetPermissions() & ePermissionsExecutable)
932 symbol.SetExternal(true);
933 uint32_t idx = symtab.AddSymbol(symbol);
934 export_list.push_back(std::make_pair(function_rva, idx));
935 }
936 llvm::stable_sort(export_list, RVASymbolListCompareRVA);
937 return export_list;
938}
939
940std::unique_ptr<CallFrameInfo> ObjectFilePECOFF::CreateCallFrameInfo() {
941 if (llvm::COFF::EXCEPTION_TABLE >= m_coff_header_opt.data_dirs.size())
942 return {};
943
944 data_directory data_dir_exception =
945 m_coff_header_opt.data_dirs[llvm::COFF::EXCEPTION_TABLE];
946 if (!data_dir_exception.vmaddr)
947 return {};
948
949 if (m_coff_header.machine != llvm::COFF::IMAGE_FILE_MACHINE_AMD64)
950 return {};
951
952 return std::make_unique<PECallFrameInfo>(*this, data_dir_exception.vmaddr,
953 data_dir_exception.vmsize);
954}
955
957 // TODO: determine this for COFF
958 return false;
959}
960
962 const section_header_t &sect) {
963 ConstString const_sect_name(sect_name);
964 static ConstString g_code_sect_name(".code");
965 static ConstString g_CODE_sect_name("CODE");
966 static ConstString g_data_sect_name(".data");
967 static ConstString g_DATA_sect_name("DATA");
968 static ConstString g_bss_sect_name(".bss");
969 static ConstString g_BSS_sect_name("BSS");
970
971 if (sect.flags & llvm::COFF::IMAGE_SCN_CNT_CODE &&
972 ((const_sect_name == g_code_sect_name) ||
973 (const_sect_name == g_CODE_sect_name))) {
974 return eSectionTypeCode;
975 }
976 if (sect.flags & llvm::COFF::IMAGE_SCN_CNT_INITIALIZED_DATA &&
977 ((const_sect_name == g_data_sect_name) ||
978 (const_sect_name == g_DATA_sect_name))) {
979 if (sect.size == 0 && sect.offset == 0)
981 else
982 return eSectionTypeData;
983 }
984 if (sect.flags & llvm::COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA &&
985 ((const_sect_name == g_bss_sect_name) ||
986 (const_sect_name == g_BSS_sect_name))) {
987 if (sect.size == 0)
989 else
990 return eSectionTypeData;
991 }
992
993 if (sect_name.consume_front(".debug_"))
994 return GetDWARFSectionTypeFromName(sect_name);
995
996 SectionType section_type =
997 llvm::StringSwitch<SectionType>(sect_name)
998 .Case(".debug", eSectionTypeDebug)
999 .Case(".stabstr", eSectionTypeDataCString)
1000 .Case(".reloc", eSectionTypeOther)
1001 // .eh_frame can be truncated to 8 chars.
1002 .Cases({".eh_frame", ".eh_fram"}, eSectionTypeEHFrame)
1003 .Case(".gosymtab", eSectionTypeGoSymtab)
1004 .Case(".lldbsummaries", lldb::eSectionTypeLLDBTypeSummaries)
1005 .Case(".lldbformatters", lldb::eSectionTypeLLDBFormatters)
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(new 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->Printf(" %s\n", spec.GetFilename().GetCString());
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:369
#define LLDB_LOGF(log,...)
Definition Log.h:383
#define LLDB_LOG_ERROR(log, error,...)
Definition Log.h:399
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:432
lldb::addr_t GetFileAddress() const
Get the file address.
Definition Address.cpp:281
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:457
bool SetTriple(const llvm::Triple &triple)
Architecture triple setter.
Definition ArchSpec.cpp:739
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.
Definition ArchSpec.cpp:843
const char * GetArchitectureName() const
Returns a static string representing the current architecture.
Definition ArchSpec.cpp:548
A uniqued constant string class.
Definition ConstString.h:40
const char * AsCString(const char *value_if_empty=nullptr) const
Get the string value as a C string.
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:101
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:57
void SetDirectory(ConstString directory)
Directory string set accessor.
Definition FileSpec.cpp:342
static std::optional< Style > GuessPathStyle(llvm::StringRef absolute_path)
Attempt to guess path style for a given path string.
Definition FileSpec.cpp:310
const ConstString & GetFilename() const
Filename string const get accessor.
Definition FileSpec.h:250
size_t GetPath(char *path, size_t max_path_length, bool denormalize=true) const
Extract the full path to the file.
Definition FileSpec.cpp:374
void SetDemangledName(ConstString name)
Definition Mangled.h:138
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:341
ArchSpec & GetArchitecture()
Definition ModuleSpec.h:93
std::unique_ptr< lldb_private::SectionList > m_sections_up
Definition ObjectFile.h:774
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:775
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:767
@ 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:771
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:581
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:645
lldb::SectionSP GetSectionAtIndex(size_t idx) const
Definition Section.cpp:552
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
llvm::raw_ostream & AsRawOstream()
Returns a raw_ostream that forwards the data to this Stream object.
Definition Stream.h:418
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:65
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:171
Mangled & GetMangled()
Definition Symbol.h:147
Address & GetAddressRef()
Definition Symbol.h:73
lldb::SymbolType GetType() const
Definition Symbol.h:169
void SetDemangledNameIsSynthesized(bool b)
Definition Symbol.h:230
ConstString GetDisplayName() const
Definition Symbol.cpp:169
void SetExternal(bool b)
Definition Symbol.h:199
void SetID(uint32_t uid)
Definition Symbol.h:145
Symbol * SymbolAtIndex(size_t idx)
Definition Symtab.cpp:228
uint32_t AddSymbol(const Symbol &symbol)
Definition Symtab.cpp:64
size_t GetNumSymbols() const
Definition Symtab.cpp:77
void Reserve(size_t count)
Definition Symtab.cpp:51
bool SetSectionLoadAddress(const lldb::SectionSP &section, lldb::addr_t load_addr, bool warn_multiple=false)
Definition Target.cpp:3339
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:332
bool SaveMiniDump(const lldb::ProcessSP &process_sp, SaveCoreOptions &core_options, lldb_private::Status &error)
uint64_t offset_t
Definition lldb-types.h:85
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:82
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