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