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
184}
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
198}
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),
425 m_dos_header(), m_coff_header(), m_coff_header_opt(), m_sect_headers(),
426 m_image_base(LLDB_INVALID_ADDRESS), m_entry_point_address(),
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),
434 m_dos_header(), m_coff_header(), m_coff_header_opt(), m_sect_headers(),
435 m_image_base(LLDB_INVALID_ADDRESS), m_entry_point_address(),
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();
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 }
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()) {
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);
611 m_coff_header_opt.entry = m_data.GetU32(offset_ptr);
613
614 const uint32_t addr_byte_size = GetAddressByteSize();
615
616 if (*offset_ptr < end_offset) {
618 // PE32 only
620 } else
622
623 if (*offset_ptr < end_offset) {
625 m_data.GetMaxU64(offset_ptr, addr_byte_size);
641 m_data.GetMaxU64(offset_ptr, addr_byte_size);
643 m_data.GetMaxU64(offset_ptr, addr_byte_size);
645 m_data.GetMaxU64(offset_ptr, addr_byte_size);
647 m_data.GetMaxU64(offset_ptr, addr_byte_size);
649 uint32_t num_data_dir_entries = m_data.GetU32(offset_ptr);
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
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() -
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 if (log)
865 log->Format(
866 __FILE__, __func__,
867 "ObjectFilePECOFF::AppendFromExportTable - failed to get export "
868 "table entry name: {0}",
869 llvm::fmt_consume(std::move(err)));
870 else
871 llvm::consumeError(std::move(err));
872 continue;
873 }
874 Symbol symbol;
875 // Note: symbol name may be empty if it is only exported by ordinal.
876 symbol.GetMangled().SetValue(ConstString(sym_name));
877
878 uint32_t ordinal;
879 llvm::cantFail(entry.getOrdinal(ordinal));
880 symbol.SetID(ordinal);
881
882 bool is_forwarder;
883 llvm::cantFail(entry.isForwarder(is_forwarder));
884 if (is_forwarder) {
885 // Forwarder exports are redirected by the loader transparently, but keep
886 // it in symtab and make a note using the symbol name.
887 llvm::StringRef forwarder_name;
888 if (auto err = entry.getForwardTo(forwarder_name)) {
889 if (log)
890 log->Format(__FILE__, __func__,
891 "ObjectFilePECOFF::AppendFromExportTable - failed to get "
892 "forwarder name of forwarder export '{0}': {1}",
893 sym_name, llvm::fmt_consume(std::move(err)));
894 else
895 llvm::consumeError(std::move(err));
896 continue;
897 }
898 llvm::SmallString<256> new_name = {symbol.GetDisplayName().GetStringRef(),
899 " (forwarded to ", forwarder_name,
900 ")"};
901 symbol.GetMangled().SetDemangledName(ConstString(new_name.str()));
903 }
904
905 uint32_t function_rva;
906 if (auto err = entry.getExportRVA(function_rva)) {
907 if (log)
908 log->Format(__FILE__, __func__,
909 "ObjectFilePECOFF::AppendFromExportTable - failed to get "
910 "address of export entry '{0}': {1}",
911 sym_name, llvm::fmt_consume(std::move(err)));
912 else
913 llvm::consumeError(std::move(err));
914 continue;
915 }
916 // Skip the symbol if it doesn't look valid.
917 if (function_rva == 0 && sym_name.empty())
918 continue;
919 symbol.GetAddressRef() =
920 Address(m_coff_header_opt.image_base + function_rva, sect_list);
921
922 // An exported symbol may be either code or data. Guess by checking whether
923 // the section containing the symbol is executable.
925 if (!is_forwarder)
926 if (auto section_sp = symbol.GetAddressRef().GetSection())
927 if (section_sp->GetPermissions() & ePermissionsExecutable)
929 symbol.SetExternal(true);
930 uint32_t idx = symtab.AddSymbol(symbol);
931 export_list.push_back(std::make_pair(function_rva, idx));
932 }
933 std::stable_sort(export_list.begin(), export_list.end(),
935 return export_list;
936}
937
938std::unique_ptr<CallFrameInfo> ObjectFilePECOFF::CreateCallFrameInfo() {
939 if (llvm::COFF::EXCEPTION_TABLE >= m_coff_header_opt.data_dirs.size())
940 return {};
941
942 data_directory data_dir_exception =
943 m_coff_header_opt.data_dirs[llvm::COFF::EXCEPTION_TABLE];
944 if (!data_dir_exception.vmaddr)
945 return {};
946
947 if (m_coff_header.machine != llvm::COFF::IMAGE_FILE_MACHINE_AMD64)
948 return {};
949
950 return std::make_unique<PECallFrameInfo>(*this, data_dir_exception.vmaddr,
951 data_dir_exception.vmsize);
952}
953
955 // TODO: determine this for COFF
956 return false;
957}
958
960 const section_header_t &sect) {
961 ConstString const_sect_name(sect_name);
962 static ConstString g_code_sect_name(".code");
963 static ConstString g_CODE_sect_name("CODE");
964 static ConstString g_data_sect_name(".data");
965 static ConstString g_DATA_sect_name("DATA");
966 static ConstString g_bss_sect_name(".bss");
967 static ConstString g_BSS_sect_name("BSS");
968
969 if (sect.flags & llvm::COFF::IMAGE_SCN_CNT_CODE &&
970 ((const_sect_name == g_code_sect_name) ||
971 (const_sect_name == g_CODE_sect_name))) {
972 return eSectionTypeCode;
973 }
974 if (sect.flags & llvm::COFF::IMAGE_SCN_CNT_INITIALIZED_DATA &&
975 ((const_sect_name == g_data_sect_name) ||
976 (const_sect_name == g_DATA_sect_name))) {
977 if (sect.size == 0 && sect.offset == 0)
979 else
980 return eSectionTypeData;
981 }
982 if (sect.flags & llvm::COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA &&
983 ((const_sect_name == g_bss_sect_name) ||
984 (const_sect_name == g_BSS_sect_name))) {
985 if (sect.size == 0)
987 else
988 return eSectionTypeData;
989 }
990
991 SectionType section_type =
992 llvm::StringSwitch<SectionType>(sect_name)
993 .Case(".debug", eSectionTypeDebug)
994 .Case(".stabstr", eSectionTypeDataCString)
995 .Case(".reloc", eSectionTypeOther)
996 .Case(".debug_abbrev", eSectionTypeDWARFDebugAbbrev)
997 .Case(".debug_aranges", eSectionTypeDWARFDebugAranges)
998 .Case(".debug_frame", eSectionTypeDWARFDebugFrame)
999 .Case(".debug_info", eSectionTypeDWARFDebugInfo)
1000 .Case(".debug_line", eSectionTypeDWARFDebugLine)
1001 .Case(".debug_loc", eSectionTypeDWARFDebugLoc)
1002 .Case(".debug_loclists", eSectionTypeDWARFDebugLocLists)
1003 .Case(".debug_macinfo", eSectionTypeDWARFDebugMacInfo)
1004 .Case(".debug_names", eSectionTypeDWARFDebugNames)
1005 .Case(".debug_pubnames", eSectionTypeDWARFDebugPubNames)
1006 .Case(".debug_pubtypes", eSectionTypeDWARFDebugPubTypes)
1007 .Case(".debug_ranges", eSectionTypeDWARFDebugRanges)
1008 .Case(".debug_str", eSectionTypeDWARFDebugStr)
1009 .Case(".debug_types", eSectionTypeDWARFDebugTypes)
1010 // .eh_frame can be truncated to 8 chars.
1011 .Cases(".eh_frame", ".eh_fram", eSectionTypeEHFrame)
1012 .Case(".gosymtab", eSectionTypeGoSymtab)
1013 .Case(".lldbsummaries", lldb::eSectionTypeLLDBTypeSummaries)
1014 .Case(".lldbformatters", lldb::eSectionTypeLLDBFormatters)
1015 .Case("swiftast", eSectionTypeSwiftModules)
1016 .Default(eSectionTypeInvalid);
1017 if (section_type != eSectionTypeInvalid)
1018 return section_type;
1019
1020 if (sect.flags & llvm::COFF::IMAGE_SCN_CNT_CODE)
1021 return eSectionTypeCode;
1022 if (sect.flags & llvm::COFF::IMAGE_SCN_CNT_INITIALIZED_DATA)
1023 return eSectionTypeData;
1024 if (sect.flags & llvm::COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA) {
1025 if (sect.size == 0)
1026 return eSectionTypeZeroFill;
1027 else
1028 return eSectionTypeData;
1029 }
1030 return eSectionTypeOther;
1031}
1032
1034 // For executables, SizeOfRawData (getFileSize()) is aligned by
1035 // FileAlignment and the actual section size is in VirtualSize
1036 // (getByteSize()). See the comment on
1037 // llvm::object::COFFObjectFile::getSectionSize().
1038 if (m_binary->getPE32Header() || m_binary->getPE32PlusHeader())
1039 return std::min(section->GetByteSize(), section->GetFileSize());
1040 return section->GetFileSize();
1041}
1042
1044 if (m_sections_up)
1045 return;
1046 m_sections_up = std::make_unique<SectionList>();
1047 ModuleSP module_sp(GetModule());
1048 if (module_sp) {
1049 std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex());
1050
1051 SectionSP header_sp = std::make_shared<Section>(
1052 module_sp, this, ~user_id_t(0), ConstString("PECOFF header"),
1055 /*file_offset*/ 0, m_coff_header_opt.header_size,
1057 /*flags*/ 0);
1058 header_sp->SetPermissions(ePermissionsReadable);
1059 m_sections_up->AddSection(header_sp);
1060 unified_section_list.AddSection(header_sp);
1061
1062 const uint32_t nsects = m_sect_headers.size();
1063 for (uint32_t idx = 0; idx < nsects; ++idx) {
1064 llvm::StringRef sect_name = GetSectionName(m_sect_headers[idx]);
1065 ConstString const_sect_name(sect_name);
1066 SectionType section_type = GetSectionType(sect_name, m_sect_headers[idx]);
1067
1068 SectionSP section_sp(new Section(
1069 module_sp, // Module to which this section belongs
1070 this, // Object file to which this section belongs
1071 idx + 1, // Section ID is the 1 based section index.
1072 const_sect_name, // Name of this section
1073 section_type,
1075 m_sect_headers[idx].vmaddr, // File VM address == addresses as
1076 // they are found in the object file
1077 m_sect_headers[idx].vmsize, // VM size in bytes of this section
1078 m_sect_headers[idx]
1079 .offset, // Offset to the data for this section in the file
1080 m_sect_headers[idx]
1081 .size, // Size in bytes of this section as found in the file
1082 m_coff_header_opt.sect_alignment, // Section alignment
1083 m_sect_headers[idx].flags)); // Flags for this section
1084
1085 uint32_t permissions = 0;
1086 if (m_sect_headers[idx].flags & llvm::COFF::IMAGE_SCN_MEM_EXECUTE)
1087 permissions |= ePermissionsExecutable;
1088 if (m_sect_headers[idx].flags & llvm::COFF::IMAGE_SCN_MEM_READ)
1089 permissions |= ePermissionsReadable;
1090 if (m_sect_headers[idx].flags & llvm::COFF::IMAGE_SCN_MEM_WRITE)
1091 permissions |= ePermissionsWritable;
1092 section_sp->SetPermissions(permissions);
1093
1094 m_sections_up->AddSection(section_sp);
1095 unified_section_list.AddSection(section_sp);
1096 }
1097 }
1098}
1099
1101 if (m_uuid.IsValid())
1102 return m_uuid;
1103
1104 if (!CreateBinary())
1105 return UUID();
1106
1108 return m_uuid;
1109}
1110
1111std::optional<FileSpec> ObjectFilePECOFF::GetDebugLink() {
1112 std::string gnu_debuglink_file;
1113 uint32_t gnu_debuglink_crc;
1114 if (GetDebugLinkContents(*m_binary, gnu_debuglink_file, gnu_debuglink_crc))
1115 return FileSpec(gnu_debuglink_file);
1116 return std::nullopt;
1117}
1118
1120 ModuleSP module_sp(GetModule());
1121 if (!module_sp)
1122 return 0;
1123
1124 std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex());
1125 if (m_deps_filespec)
1126 return m_deps_filespec->GetSize();
1127
1128 // Cache coff binary if it is not done yet.
1129 if (!CreateBinary())
1130 return 0;
1131
1132 Log *log = GetLog(LLDBLog::Object);
1133 LLDB_LOG(log, "this = {0}, module = {1} ({2}), file = {3}, binary = {4}",
1134 this, GetModule().get(), GetModule()->GetSpecificationDescription(),
1135 m_file.GetPath(), m_binary.get());
1136
1138
1139 for (const auto &entry : m_binary->import_directories()) {
1140 llvm::StringRef dll_name;
1141 // Report a bogus entry.
1142 if (llvm::Error e = entry.getName(dll_name)) {
1143 LLDB_LOGF(log,
1144 "ObjectFilePECOFF::ParseDependentModules() - failed to get "
1145 "import directory entry name: %s",
1146 llvm::toString(std::move(e)).c_str());
1147 continue;
1148 }
1149
1150 // At this moment we only have the base name of the DLL. The full path can
1151 // only be seen after the dynamic loading. Our best guess is Try to get it
1152 // with the help of the object file's directory.
1153 llvm::SmallString<128> dll_fullpath;
1154 FileSpec dll_specs(dll_name);
1155 dll_specs.SetDirectory(m_file.GetDirectory());
1156
1157 if (!llvm::sys::fs::real_path(dll_specs.GetPath(), dll_fullpath))
1158 m_deps_filespec->EmplaceBack(dll_fullpath);
1159 else {
1160 // Known DLLs or DLL not found in the object file directory.
1161 m_deps_filespec->EmplaceBack(dll_name);
1162 }
1163 }
1164 return m_deps_filespec->GetSize();
1165}
1166
1168 auto num_modules = ParseDependentModules();
1169 auto original_size = files.GetSize();
1170
1171 for (unsigned i = 0; i < num_modules; ++i)
1172 files.AppendIfUnique(m_deps_filespec->GetFileSpecAtIndex(i));
1173
1174 return files.GetSize() - original_size;
1175}
1176
1179 return m_entry_point_address;
1180
1181 if (!ParseHeader() || !IsExecutable())
1182 return m_entry_point_address;
1183
1184 SectionList *section_list = GetSectionList();
1186
1187 if (!section_list)
1189 else
1191 section_list);
1192 return m_entry_point_address;
1193}
1194
1196 return Address(GetSectionList()->GetSectionAtIndex(0), 0);
1197}
1198
1199// Dump
1200//
1201// Dump the specifics of the runtime file container (such as any headers
1202// segments, sections, etc).
1204 ModuleSP module_sp(GetModule());
1205 if (module_sp) {
1206 std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex());
1207 s->Printf("%p: ", static_cast<void *>(this));
1208 s->Indent();
1209 s->PutCString("ObjectFilePECOFF");
1210
1211 ArchSpec header_arch = GetArchitecture();
1212
1213 *s << ", file = '" << m_file
1214 << "', arch = " << header_arch.GetArchitectureName() << "\n";
1215
1216 SectionList *sections = GetSectionList();
1217 if (sections)
1218 sections->Dump(s->AsRawOstream(), s->GetIndentLevel(), nullptr, true,
1219 UINT32_MAX);
1220
1221 if (m_symtab_up)
1222 m_symtab_up->Dump(s, nullptr, eSortOrderNone);
1223
1226 if (m_coff_header.machine) {
1230 }
1231 s->EOL();
1233 s->EOL();
1234
1236 s->EOL();
1237 }
1238}
1239
1240// DumpDOSHeader
1241//
1242// Dump the MS-DOS header to the specified output stream
1244 s->PutCString("MSDOS Header\n");
1245 s->Printf(" e_magic = 0x%4.4x\n", header.e_magic);
1246 s->Printf(" e_cblp = 0x%4.4x\n", header.e_cblp);
1247 s->Printf(" e_cp = 0x%4.4x\n", header.e_cp);
1248 s->Printf(" e_crlc = 0x%4.4x\n", header.e_crlc);
1249 s->Printf(" e_cparhdr = 0x%4.4x\n", header.e_cparhdr);
1250 s->Printf(" e_minalloc = 0x%4.4x\n", header.e_minalloc);
1251 s->Printf(" e_maxalloc = 0x%4.4x\n", header.e_maxalloc);
1252 s->Printf(" e_ss = 0x%4.4x\n", header.e_ss);
1253 s->Printf(" e_sp = 0x%4.4x\n", header.e_sp);
1254 s->Printf(" e_csum = 0x%4.4x\n", header.e_csum);
1255 s->Printf(" e_ip = 0x%4.4x\n", header.e_ip);
1256 s->Printf(" e_cs = 0x%4.4x\n", header.e_cs);
1257 s->Printf(" e_lfarlc = 0x%4.4x\n", header.e_lfarlc);
1258 s->Printf(" e_ovno = 0x%4.4x\n", header.e_ovno);
1259 s->Printf(" e_res[4] = { 0x%4.4x, 0x%4.4x, 0x%4.4x, 0x%4.4x }\n",
1260 header.e_res[0], header.e_res[1], header.e_res[2], header.e_res[3]);
1261 s->Printf(" e_oemid = 0x%4.4x\n", header.e_oemid);
1262 s->Printf(" e_oeminfo = 0x%4.4x\n", header.e_oeminfo);
1263 s->Printf(" e_res2[10] = { 0x%4.4x, 0x%4.4x, 0x%4.4x, 0x%4.4x, 0x%4.4x, "
1264 "0x%4.4x, 0x%4.4x, 0x%4.4x, 0x%4.4x, 0x%4.4x }\n",
1265 header.e_res2[0], header.e_res2[1], header.e_res2[2],
1266 header.e_res2[3], header.e_res2[4], header.e_res2[5],
1267 header.e_res2[6], header.e_res2[7], header.e_res2[8],
1268 header.e_res2[9]);
1269 s->Printf(" e_lfanew = 0x%8.8x\n", header.e_lfanew);
1270}
1271
1272// DumpCOFFHeader
1273//
1274// Dump the COFF header to the specified output stream
1276 s->PutCString("COFF Header\n");
1277 s->Printf(" machine = 0x%4.4x\n", header.machine);
1278 s->Printf(" nsects = 0x%4.4x\n", header.nsects);
1279 s->Printf(" modtime = 0x%8.8x\n", header.modtime);
1280 s->Printf(" symoff = 0x%8.8x\n", header.symoff);
1281 s->Printf(" nsyms = 0x%8.8x\n", header.nsyms);
1282 s->Printf(" hdrsize = 0x%4.4x\n", header.hdrsize);
1283}
1284
1285// DumpOptCOFFHeader
1286//
1287// Dump the optional COFF header to the specified output stream
1289 const coff_opt_header_t &header) {
1290 s->PutCString("Optional COFF Header\n");
1291 s->Printf(" magic = 0x%4.4x\n", header.magic);
1292 s->Printf(" major_linker_version = 0x%2.2x\n",
1293 header.major_linker_version);
1294 s->Printf(" minor_linker_version = 0x%2.2x\n",
1295 header.minor_linker_version);
1296 s->Printf(" code_size = 0x%8.8x\n", header.code_size);
1297 s->Printf(" data_size = 0x%8.8x\n", header.data_size);
1298 s->Printf(" bss_size = 0x%8.8x\n", header.bss_size);
1299 s->Printf(" entry = 0x%8.8x\n", header.entry);
1300 s->Printf(" code_offset = 0x%8.8x\n", header.code_offset);
1301 s->Printf(" data_offset = 0x%8.8x\n", header.data_offset);
1302 s->Printf(" image_base = 0x%16.16" PRIx64 "\n",
1303 header.image_base);
1304 s->Printf(" sect_alignment = 0x%8.8x\n", header.sect_alignment);
1305 s->Printf(" file_alignment = 0x%8.8x\n", header.file_alignment);
1306 s->Printf(" major_os_system_version = 0x%4.4x\n",
1308 s->Printf(" minor_os_system_version = 0x%4.4x\n",
1310 s->Printf(" major_image_version = 0x%4.4x\n",
1311 header.major_image_version);
1312 s->Printf(" minor_image_version = 0x%4.4x\n",
1313 header.minor_image_version);
1314 s->Printf(" major_subsystem_version = 0x%4.4x\n",
1316 s->Printf(" minor_subsystem_version = 0x%4.4x\n",
1318 s->Printf(" reserved1 = 0x%8.8x\n", header.reserved1);
1319 s->Printf(" image_size = 0x%8.8x\n", header.image_size);
1320 s->Printf(" header_size = 0x%8.8x\n", header.header_size);
1321 s->Printf(" checksum = 0x%8.8x\n", header.checksum);
1322 s->Printf(" subsystem = 0x%4.4x\n", header.subsystem);
1323 s->Printf(" dll_flags = 0x%4.4x\n", header.dll_flags);
1324 s->Printf(" stack_reserve_size = 0x%16.16" PRIx64 "\n",
1325 header.stack_reserve_size);
1326 s->Printf(" stack_commit_size = 0x%16.16" PRIx64 "\n",
1327 header.stack_commit_size);
1328 s->Printf(" heap_reserve_size = 0x%16.16" PRIx64 "\n",
1329 header.heap_reserve_size);
1330 s->Printf(" heap_commit_size = 0x%16.16" PRIx64 "\n",
1331 header.heap_commit_size);
1332 s->Printf(" loader_flags = 0x%8.8x\n", header.loader_flags);
1333 s->Printf(" num_data_dir_entries = 0x%8.8x\n",
1334 (uint32_t)header.data_dirs.size());
1335 uint32_t i;
1336 for (i = 0; i < header.data_dirs.size(); i++) {
1337 s->Printf(" data_dirs[%2u] vmaddr = 0x%8.8x, vmsize = 0x%8.8x\n", i,
1338 header.data_dirs[i].vmaddr, header.data_dirs[i].vmsize);
1339 }
1340}
1341// DumpSectionHeader
1342//
1343// Dump a single ELF section header to the specified output stream
1345 const section_header_t &sh) {
1346 std::string name = std::string(GetSectionName(sh));
1347 s->Printf("%-16s 0x%8.8x 0x%8.8x 0x%8.8x 0x%8.8x 0x%8.8x 0x%8.8x 0x%4.4x "
1348 "0x%4.4x 0x%8.8x\n",
1349 name.c_str(), sh.vmaddr, sh.vmsize, sh.offset, sh.size, sh.reloff,
1350 sh.lineoff, sh.nreloc, sh.nline, sh.flags);
1351}
1352
1353// DumpSectionHeaders
1354//
1355// Dump all of the ELF section header to the specified output stream
1357
1358 s->PutCString("Section Headers\n");
1359 s->PutCString("IDX name vm addr vm size file off file "
1360 "size reloc off line off nreloc nline flags\n");
1361 s->PutCString("==== ---------------- ---------- ---------- ---------- "
1362 "---------- ---------- ---------- ------ ------ ----------\n");
1363
1364 uint32_t idx = 0;
1365 SectionHeaderCollIter pos, end = m_sect_headers.end();
1366
1367 for (pos = m_sect_headers.begin(); pos != end; ++pos, ++idx) {
1368 s->Printf("[%2u] ", idx);
1370 }
1371}
1372
1373// DumpDependentModules
1374//
1375// Dump all of the dependent modules to the specified output stream
1377 auto num_modules = ParseDependentModules();
1378 if (num_modules > 0) {
1379 s->PutCString("Dependent Modules\n");
1380 for (unsigned i = 0; i < num_modules; ++i) {
1381 auto spec = m_deps_filespec->GetFileSpecAtIndex(i);
1382 s->Printf(" %s\n", spec.GetFilename().GetCString());
1383 }
1384 }
1385}
1386
1388 switch (m_coff_header_opt.subsystem) {
1389 case llvm::COFF::IMAGE_SUBSYSTEM_NATIVE:
1390 case llvm::COFF::IMAGE_SUBSYSTEM_WINDOWS_GUI:
1391 case llvm::COFF::IMAGE_SUBSYSTEM_WINDOWS_CUI:
1392 case llvm::COFF::IMAGE_SUBSYSTEM_NATIVE_WINDOWS:
1393 case llvm::COFF::IMAGE_SUBSYSTEM_WINDOWS_CE_GUI:
1394 case llvm::COFF::IMAGE_SUBSYSTEM_XBOX:
1395 case llvm::COFF::IMAGE_SUBSYSTEM_WINDOWS_BOOT_APPLICATION:
1396 return true;
1397 default:
1398 return false;
1399 }
1400}
1401
1403 uint16_t machine = m_coff_header.machine;
1404 switch (machine) {
1405 default:
1406 break;
1407 case llvm::COFF::IMAGE_FILE_MACHINE_AMD64:
1408 case llvm::COFF::IMAGE_FILE_MACHINE_I386:
1409 case llvm::COFF::IMAGE_FILE_MACHINE_POWERPC:
1410 case llvm::COFF::IMAGE_FILE_MACHINE_POWERPCFP:
1411 case llvm::COFF::IMAGE_FILE_MACHINE_ARM:
1412 case llvm::COFF::IMAGE_FILE_MACHINE_ARMNT:
1413 case llvm::COFF::IMAGE_FILE_MACHINE_THUMB:
1414 case llvm::COFF::IMAGE_FILE_MACHINE_ARM64:
1415 ArchSpec arch;
1417 IsWindowsSubsystem() ? llvm::Triple::Win32
1418 : llvm::Triple::UnknownOS);
1419 return arch;
1420 }
1421 return ArchSpec();
1422}
1423
1425 if (m_coff_header.machine != 0) {
1426 if ((m_coff_header.flags & llvm::COFF::IMAGE_FILE_DLL) == 0)
1427 return eTypeExecutable;
1428 else
1429 return eTypeSharedLibrary;
1430 }
1431 return eTypeExecutable;
1432}
1433
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)
Definition: PluginManager.h:32
#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()
bool NeedsEndianSwap() const
lldb::addr_t GetFileAddress(uint32_t rva) const
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)
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
bool ResolveAddressUsingFileSections(lldb::addr_t addr, const SectionList *sections)
Resolve a file virtual address using a section list.
Definition: Address.cpp:250
lldb::SectionSP GetSection() const
Get const accessor for the section.
Definition: Address.h:439
lldb::addr_t GetFileAddress() const
Get the file address.
Definition: Address.cpp:293
lldb::addr_t GetOffset() const
Get the section relative offset value.
Definition: Address.h:329
bool IsValid() const
Check if the object state is valid.
Definition: Address.h:355
bool SetOffset(lldb::addr_t offset)
Set accessor for the offset.
Definition: Address.h:448
An architecture specification class.
Definition: ArchSpec.h:31
llvm::Triple & GetTriple()
Architecture triple accessor.
Definition: ArchSpec.h:461
bool SetTriple(const llvm::Triple &triple)
Architecture triple setter.
Definition: ArchSpec.cpp:765
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:869
const char * GetArchitectureName() const
Returns a static string representing the current architecture.
Definition: ArchSpec.cpp:570
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.
Definition: ConstString.h:188
llvm::StringRef GetStringRef() const
Get the string value as a llvm::StringRef.
Definition: ConstString.h:197
An data extractor class.
Definition: DataExtractor.h:48
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.
const void * GetData(lldb::offset_t *offset_ptr, lldb::offset_t length) const
Extract length bytes from *offset_ptr.
void SetByteOrder(lldb::ByteOrder byte_order)
Set the byte_order value.
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.
uint64_t GetMaxU64(lldb::offset_t *offset_ptr, size_t byte_size) const
Extract an unsigned integer of size byte_size from *offset_ptr.
void SetAddressByteSize(uint32_t addr_size)
Set the address byte size.
uint8_t GetU8(lldb::offset_t *offset_ptr) const
Extract a uint8_t value from *offset_ptr.
A class to manage flag bits.
Definition: Debugger.h:80
A file collection class.
Definition: FileSpecList.h:91
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
void SetDirectory(ConstString directory)
Directory string set accessor.
Definition: FileSpec.cpp:335
const ConstString & GetFilename() const
Filename string const get accessor.
Definition: FileSpec.h:240
const ConstString & GetDirectory() const
Directory string const get accessor.
Definition: FileSpec.h:223
size_t GetPath(char *path, size_t max_path_length, bool denormalize=true) const
Extract the full path to the file.
Definition: FileSpec.cpp:367
void Format(llvm::StringRef file, llvm::StringRef function, const char *format, Args &&... args)
Definition: Log.h:238
void SetDemangledName(ConstString name)
Definition: Mangled.h:137
void SetValue(ConstString name)
Set the string value in this object.
Definition: Mangled.cpp:120
lldb::ModuleSP GetModule() const
Get const accessor for the module pointer.
Definition: ModuleChild.cpp:24
void Append(const ModuleSpec &spec)
Definition: ModuleSpec.h:308
ArchSpec & GetArchitecture()
Definition: ModuleSpec.h:89
A plug-in interface definition class for object file parsers.
Definition: ObjectFile.h:44
DataExtractor m_data
The data for this object file so things can be parsed lazily.
Definition: ObjectFile.h:758
std::unique_ptr< lldb_private::SectionList > m_sections_up
Definition: ObjectFile.h:762
static lldb::DataBufferSP MapFileData(const FileSpec &file, uint64_t Size, uint64_t Offset)
Definition: ObjectFile.cpp:673
std::unique_ptr< lldb_private::Symtab > m_symtab_up
Definition: ObjectFile.h:763
@ eTypeExecutable
A normal executable.
Definition: ObjectFile.h:53
@ eTypeSharedLibrary
A shared library that can be used during execution.
Definition: ObjectFile.h:61
virtual SectionList * GetSectionList(bool update_module_section_list=true)
Gets the section list for the currently selected architecture (and object for archives).
Definition: ObjectFile.cpp:602
lldb::ProcessWP m_process_wp
Definition: ObjectFile.h:759
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:481
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:550
bool SetSectionLoadAddress(const lldb::SectionSP &section_sp, lldb::addr_t load_addr, bool warn_multiple=false)
lldb::addr_t GetByteSize() const
Definition: Section.h:170
lldb::offset_t GetFileSize() const
Definition: Section.h:160
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:401
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:170
Mangled & GetMangled()
Definition: Symbol.h:146
Address & GetAddressRef()
Definition: Symbol.h:72
lldb::SymbolType GetType() const
Definition: Symbol.h:168
void SetDemangledNameIsSynthesized(bool b)
Definition: Symbol.h:229
ConstString GetDisplayName() const
Definition: Symbol.cpp:169
void SetExternal(bool b)
Definition: Symbol.h:198
void SetID(uint32_t uid)
Definition: Symbol.h:144
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
SectionLoadList & GetSectionLoadList()
Definition: Target.h:1154
bool IsValid() const
Definition: UUID.h:69
#define LLDB_INVALID_CPUTYPE
Definition: lldb-defines.h:104
#define LLDB_INVALID_ADDRESS
Definition: lldb-defines.h:82
#define UINT32_MAX
Definition: lldb-defines.h:19
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)
Definition: SBAddress.h:15
uint64_t offset_t
Definition: lldb-types.h:85
std::shared_ptr< lldb_private::Process > ProcessSP
Definition: lldb-forward.h:389
SymbolType
Symbol types.
@ eSymbolTypeInvalid
@ eSymbolTypeAbsolute
@ eSymbolTypeAdditional
When symbols take more than one entry, the extra entries get this type.
ByteOrder
Byte ordering definitions.
@ eByteOrderLittle
uint64_t user_id_t
Definition: lldb-types.h:82
std::shared_ptr< lldb_private::DataBuffer > DataBufferSP
Definition: lldb-forward.h:336
std::shared_ptr< lldb_private::Section > SectionSP
Definition: lldb-forward.h:418
std::shared_ptr< lldb_private::WritableDataBuffer > WritableDataBufferSP
Definition: lldb-forward.h:337
uint64_t addr_t
Definition: lldb-types.h:80
@ eSectionTypeData
@ eSectionTypeInvalid
@ eSectionTypeDWARFDebugPubNames
@ eSectionTypeZeroFill
@ eSectionTypeDWARFDebugFrame
@ eSectionTypeDWARFDebugLocLists
DWARF v5 .debug_loclists.
@ eSectionTypeDWARFDebugTypes
DWARF .debug_types section.
@ eSectionTypeDWARFDebugMacInfo
@ eSectionTypeOther
@ eSectionTypeLLDBFormatters
@ eSectionTypeDWARFDebugNames
DWARF v5 .debug_names.
@ eSectionTypeEHFrame
@ eSectionTypeDWARFDebugInfo
@ eSectionTypeDWARFDebugRanges
@ eSectionTypeLLDBTypeSummaries
@ eSectionTypeGoSymtab
@ eSectionTypeDWARFDebugLine
@ eSectionTypeDWARFDebugPubTypes
@ eSectionTypeDWARFDebugStr
@ eSectionTypeDWARFDebugLoc
@ eSectionTypeCode
@ eSectionTypeSwiftModules
@ eSectionTypeDebug
@ eSectionTypeDWARFDebugAranges
@ eSectionTypeDWARFDebugAbbrev
@ eSectionTypeDataCString
Inlined C string data.
std::shared_ptr< lldb_private::Module > ModuleSP
Definition: lldb-forward.h:373
std::shared_ptr< lldb_private::OptionValue > OptionValueSP
Definition: lldb-forward.h:384
std::vector< data_directory > data_dirs
struct lldb_private::UUID::CvRecordPdb70::@41 Uuid
llvm::support::ulittle32_t Age
Definition: UUID.h:46