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