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