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