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