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/FileSpecList.h"
14 #include "lldb/Core/Module.h"
15 #include "lldb/Core/ModuleSpec.h"
16 #include "lldb/Core/PluginManager.h"
17 #include "lldb/Core/Section.h"
18 #include "lldb/Core/StreamFile.h"
19 #include "lldb/Symbol/ObjectFile.h"
20 #include "lldb/Target/Process.h"
21 #include "lldb/Target/SectionLoadList.h"
22 #include "lldb/Target/Target.h"
23 #include "lldb/Utility/ArchSpec.h"
24 #include "lldb/Utility/DataBufferHeap.h"
25 #include "lldb/Utility/FileSpec.h"
26 #include "lldb/Utility/Log.h"
27 #include "lldb/Utility/StreamString.h"
28 #include "lldb/Utility/Timer.h"
29 #include "lldb/Utility/UUID.h"
30 #include "llvm/BinaryFormat/COFF.h"
31
32 #include "llvm/Object/COFFImportFile.h"
33 #include "llvm/Support/Error.h"
34 #include "llvm/Support/MemoryBuffer.h"
35
36 #define IMAGE_DOS_SIGNATURE 0x5A4D // MZ
37 #define IMAGE_NT_SIGNATURE 0x00004550 // PE00
38 #define OPT_HEADER_MAGIC_PE32 0x010b
39 #define OPT_HEADER_MAGIC_PE32_PLUS 0x020b
40
41 using namespace lldb;
42 using namespace lldb_private;
43
LLDB_PLUGIN_DEFINE(ObjectFilePECOFF)44 LLDB_PLUGIN_DEFINE(ObjectFilePECOFF)
45
46 static UUID GetCoffUUID(llvm::object::COFFObjectFile &coff_obj) {
47 const llvm::codeview::DebugInfo *pdb_info = nullptr;
48 llvm::StringRef pdb_file;
49
50 if (!coff_obj.getDebugPDBInfo(pdb_info, pdb_file) && pdb_info) {
51 if (pdb_info->PDB70.CVSignature == llvm::OMF::Signature::PDB70) {
52 UUID::CvRecordPdb70 info;
53 memcpy(&info.Uuid, pdb_info->PDB70.Signature, sizeof(info.Uuid));
54 info.Age = pdb_info->PDB70.Age;
55 return UUID::fromCvRecord(info);
56 }
57 }
58
59 return UUID();
60 }
61
62 char ObjectFilePECOFF::ID;
63
Initialize()64 void ObjectFilePECOFF::Initialize() {
65 PluginManager::RegisterPlugin(
66 GetPluginNameStatic(), GetPluginDescriptionStatic(), CreateInstance,
67 CreateMemoryInstance, GetModuleSpecifications, SaveCore);
68 }
69
Terminate()70 void ObjectFilePECOFF::Terminate() {
71 PluginManager::UnregisterPlugin(CreateInstance);
72 }
73
GetPluginNameStatic()74 lldb_private::ConstString ObjectFilePECOFF::GetPluginNameStatic() {
75 static ConstString g_name("pe-coff");
76 return g_name;
77 }
78
GetPluginDescriptionStatic()79 const char *ObjectFilePECOFF::GetPluginDescriptionStatic() {
80 return "Portable Executable and Common Object File Format object file reader "
81 "(32 and 64 bit)";
82 }
83
CreateInstance(const lldb::ModuleSP & module_sp,DataBufferSP & data_sp,lldb::offset_t data_offset,const lldb_private::FileSpec * file_p,lldb::offset_t file_offset,lldb::offset_t length)84 ObjectFile *ObjectFilePECOFF::CreateInstance(const lldb::ModuleSP &module_sp,
85 DataBufferSP &data_sp,
86 lldb::offset_t data_offset,
87 const lldb_private::FileSpec *file_p,
88 lldb::offset_t file_offset,
89 lldb::offset_t length) {
90 FileSpec file = file_p ? *file_p : FileSpec();
91 if (!data_sp) {
92 data_sp = MapFileData(file, length, file_offset);
93 if (!data_sp)
94 return nullptr;
95 data_offset = 0;
96 }
97
98 if (!ObjectFilePECOFF::MagicBytesMatch(data_sp))
99 return nullptr;
100
101 // Update the data to contain the entire file if it doesn't already
102 if (data_sp->GetByteSize() < length) {
103 data_sp = MapFileData(file, length, file_offset);
104 if (!data_sp)
105 return nullptr;
106 }
107
108 auto objfile_up = std::make_unique<ObjectFilePECOFF>(
109 module_sp, data_sp, data_offset, file_p, file_offset, length);
110 if (!objfile_up || !objfile_up->ParseHeader())
111 return nullptr;
112
113 // Cache coff binary.
114 if (!objfile_up->CreateBinary())
115 return nullptr;
116 return objfile_up.release();
117 }
118
CreateMemoryInstance(const lldb::ModuleSP & module_sp,lldb::DataBufferSP & data_sp,const lldb::ProcessSP & process_sp,lldb::addr_t header_addr)119 ObjectFile *ObjectFilePECOFF::CreateMemoryInstance(
120 const lldb::ModuleSP &module_sp, lldb::DataBufferSP &data_sp,
121 const lldb::ProcessSP &process_sp, lldb::addr_t header_addr) {
122 if (!data_sp || !ObjectFilePECOFF::MagicBytesMatch(data_sp))
123 return nullptr;
124 auto objfile_up = std::make_unique<ObjectFilePECOFF>(
125 module_sp, data_sp, process_sp, header_addr);
126 if (objfile_up.get() && objfile_up->ParseHeader()) {
127 return objfile_up.release();
128 }
129 return nullptr;
130 }
131
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)132 size_t ObjectFilePECOFF::GetModuleSpecifications(
133 const lldb_private::FileSpec &file, lldb::DataBufferSP &data_sp,
134 lldb::offset_t data_offset, lldb::offset_t file_offset,
135 lldb::offset_t length, lldb_private::ModuleSpecList &specs) {
136 const size_t initial_count = specs.GetSize();
137 if (!data_sp || !ObjectFilePECOFF::MagicBytesMatch(data_sp))
138 return initial_count;
139
140 Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_OBJECT));
141
142 if (data_sp->GetByteSize() < length)
143 if (DataBufferSP full_sp = MapFileData(file, -1, file_offset))
144 data_sp = std::move(full_sp);
145 auto binary = llvm::object::createBinary(llvm::MemoryBufferRef(
146 toStringRef(data_sp->GetData()), file.GetFilename().GetStringRef()));
147
148 if (!binary) {
149 LLDB_LOG_ERROR(log, binary.takeError(),
150 "Failed to create binary for file ({1}): {0}", file);
151 return initial_count;
152 }
153
154 auto *COFFObj = llvm::dyn_cast<llvm::object::COFFObjectFile>(binary->get());
155 if (!COFFObj)
156 return initial_count;
157
158 ModuleSpec module_spec(file);
159 ArchSpec &spec = module_spec.GetArchitecture();
160 lldb_private::UUID &uuid = module_spec.GetUUID();
161 if (!uuid.IsValid())
162 uuid = GetCoffUUID(*COFFObj);
163
164 switch (COFFObj->getMachine()) {
165 case MachineAmd64:
166 spec.SetTriple("x86_64-pc-windows");
167 specs.Append(module_spec);
168 break;
169 case MachineX86:
170 spec.SetTriple("i386-pc-windows");
171 specs.Append(module_spec);
172 spec.SetTriple("i686-pc-windows");
173 specs.Append(module_spec);
174 break;
175 case MachineArmNt:
176 spec.SetTriple("armv7-pc-windows");
177 specs.Append(module_spec);
178 break;
179 case MachineArm64:
180 spec.SetTriple("aarch64-pc-windows");
181 specs.Append(module_spec);
182 break;
183 default:
184 break;
185 }
186
187 return specs.GetSize() - initial_count;
188 }
189
SaveCore(const lldb::ProcessSP & process_sp,const lldb_private::FileSpec & outfile,lldb_private::Status & error)190 bool ObjectFilePECOFF::SaveCore(const lldb::ProcessSP &process_sp,
191 const lldb_private::FileSpec &outfile,
192 lldb_private::Status &error) {
193 return SaveMiniDump(process_sp, outfile, error);
194 }
195
MagicBytesMatch(DataBufferSP & data_sp)196 bool ObjectFilePECOFF::MagicBytesMatch(DataBufferSP &data_sp) {
197 DataExtractor data(data_sp, eByteOrderLittle, 4);
198 lldb::offset_t offset = 0;
199 uint16_t magic = data.GetU16(&offset);
200 return magic == IMAGE_DOS_SIGNATURE;
201 }
202
MapSymbolType(uint16_t coff_symbol_type)203 lldb::SymbolType ObjectFilePECOFF::MapSymbolType(uint16_t coff_symbol_type) {
204 // TODO: We need to complete this mapping of COFF symbol types to LLDB ones.
205 // For now, here's a hack to make sure our function have types.
206 const auto complex_type =
207 coff_symbol_type >> llvm::COFF::SCT_COMPLEX_TYPE_SHIFT;
208 if (complex_type == llvm::COFF::IMAGE_SYM_DTYPE_FUNCTION) {
209 return lldb::eSymbolTypeCode;
210 }
211 return lldb::eSymbolTypeInvalid;
212 }
213
CreateBinary()214 bool ObjectFilePECOFF::CreateBinary() {
215 if (m_binary)
216 return true;
217
218 Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_OBJECT));
219
220 auto binary = llvm::object::createBinary(llvm::MemoryBufferRef(
221 toStringRef(m_data.GetData()), m_file.GetFilename().GetStringRef()));
222 if (!binary) {
223 LLDB_LOG_ERROR(log, binary.takeError(),
224 "Failed to create binary for file ({1}): {0}", m_file);
225 return false;
226 }
227
228 // Make sure we only handle COFF format.
229 m_binary =
230 llvm::unique_dyn_cast<llvm::object::COFFObjectFile>(std::move(*binary));
231 if (!m_binary)
232 return false;
233
234 LLDB_LOG(log, "this = {0}, module = {1} ({2}), file = {3}, binary = {4}",
235 this, GetModule().get(), GetModule()->GetSpecificationDescription(),
236 m_file.GetPath(), m_binary.get());
237 return true;
238 }
239
ObjectFilePECOFF(const lldb::ModuleSP & module_sp,DataBufferSP & data_sp,lldb::offset_t data_offset,const FileSpec * file,lldb::offset_t file_offset,lldb::offset_t length)240 ObjectFilePECOFF::ObjectFilePECOFF(const lldb::ModuleSP &module_sp,
241 DataBufferSP &data_sp,
242 lldb::offset_t data_offset,
243 const FileSpec *file,
244 lldb::offset_t file_offset,
245 lldb::offset_t length)
246 : ObjectFile(module_sp, file, file_offset, length, data_sp, data_offset),
247 m_dos_header(), m_coff_header(), m_sect_headers(),
248 m_entry_point_address(), m_deps_filespec() {
249 ::memset(&m_dos_header, 0, sizeof(m_dos_header));
250 ::memset(&m_coff_header, 0, sizeof(m_coff_header));
251 }
252
ObjectFilePECOFF(const lldb::ModuleSP & module_sp,DataBufferSP & header_data_sp,const lldb::ProcessSP & process_sp,addr_t header_addr)253 ObjectFilePECOFF::ObjectFilePECOFF(const lldb::ModuleSP &module_sp,
254 DataBufferSP &header_data_sp,
255 const lldb::ProcessSP &process_sp,
256 addr_t header_addr)
257 : ObjectFile(module_sp, process_sp, header_addr, header_data_sp),
258 m_dos_header(), m_coff_header(), m_sect_headers(),
259 m_entry_point_address(), m_deps_filespec() {
260 ::memset(&m_dos_header, 0, sizeof(m_dos_header));
261 ::memset(&m_coff_header, 0, sizeof(m_coff_header));
262 }
263
~ObjectFilePECOFF()264 ObjectFilePECOFF::~ObjectFilePECOFF() {}
265
ParseHeader()266 bool ObjectFilePECOFF::ParseHeader() {
267 ModuleSP module_sp(GetModule());
268 if (module_sp) {
269 std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex());
270 m_sect_headers.clear();
271 m_data.SetByteOrder(eByteOrderLittle);
272 lldb::offset_t offset = 0;
273
274 if (ParseDOSHeader(m_data, m_dos_header)) {
275 offset = m_dos_header.e_lfanew;
276 uint32_t pe_signature = m_data.GetU32(&offset);
277 if (pe_signature != IMAGE_NT_SIGNATURE)
278 return false;
279 if (ParseCOFFHeader(m_data, &offset, m_coff_header)) {
280 if (m_coff_header.hdrsize > 0)
281 ParseCOFFOptionalHeader(&offset);
282 ParseSectionHeaders(offset);
283 }
284 m_data.SetAddressByteSize(GetAddressByteSize());
285 return true;
286 }
287 }
288 return false;
289 }
290
SetLoadAddress(Target & target,addr_t value,bool value_is_offset)291 bool ObjectFilePECOFF::SetLoadAddress(Target &target, addr_t value,
292 bool value_is_offset) {
293 bool changed = false;
294 ModuleSP module_sp = GetModule();
295 if (module_sp) {
296 size_t num_loaded_sections = 0;
297 SectionList *section_list = GetSectionList();
298 if (section_list) {
299 if (!value_is_offset) {
300 value -= m_image_base;
301 }
302
303 const size_t num_sections = section_list->GetSize();
304 size_t sect_idx = 0;
305
306 for (sect_idx = 0; sect_idx < num_sections; ++sect_idx) {
307 // Iterate through the object file sections to find all of the sections
308 // that have SHF_ALLOC in their flag bits.
309 SectionSP section_sp(section_list->GetSectionAtIndex(sect_idx));
310 if (section_sp && !section_sp->IsThreadSpecific()) {
311 if (target.GetSectionLoadList().SetSectionLoadAddress(
312 section_sp, section_sp->GetFileAddress() + value))
313 ++num_loaded_sections;
314 }
315 }
316 changed = num_loaded_sections > 0;
317 }
318 }
319 return changed;
320 }
321
GetByteOrder() const322 ByteOrder ObjectFilePECOFF::GetByteOrder() const { return eByteOrderLittle; }
323
IsExecutable() const324 bool ObjectFilePECOFF::IsExecutable() const {
325 return (m_coff_header.flags & llvm::COFF::IMAGE_FILE_DLL) == 0;
326 }
327
GetAddressByteSize() const328 uint32_t ObjectFilePECOFF::GetAddressByteSize() const {
329 if (m_coff_header_opt.magic == OPT_HEADER_MAGIC_PE32_PLUS)
330 return 8;
331 else if (m_coff_header_opt.magic == OPT_HEADER_MAGIC_PE32)
332 return 4;
333 return 4;
334 }
335
336 // NeedsEndianSwap
337 //
338 // Return true if an endian swap needs to occur when extracting data from this
339 // file.
NeedsEndianSwap() const340 bool ObjectFilePECOFF::NeedsEndianSwap() const {
341 #if defined(__LITTLE_ENDIAN__)
342 return false;
343 #else
344 return true;
345 #endif
346 }
347 // ParseDOSHeader
ParseDOSHeader(DataExtractor & data,dos_header_t & dos_header)348 bool ObjectFilePECOFF::ParseDOSHeader(DataExtractor &data,
349 dos_header_t &dos_header) {
350 bool success = false;
351 lldb::offset_t offset = 0;
352 success = data.ValidOffsetForDataOfSize(0, sizeof(dos_header));
353
354 if (success) {
355 dos_header.e_magic = data.GetU16(&offset); // Magic number
356 success = dos_header.e_magic == IMAGE_DOS_SIGNATURE;
357
358 if (success) {
359 dos_header.e_cblp = data.GetU16(&offset); // Bytes on last page of file
360 dos_header.e_cp = data.GetU16(&offset); // Pages in file
361 dos_header.e_crlc = data.GetU16(&offset); // Relocations
362 dos_header.e_cparhdr =
363 data.GetU16(&offset); // Size of header in paragraphs
364 dos_header.e_minalloc =
365 data.GetU16(&offset); // Minimum extra paragraphs needed
366 dos_header.e_maxalloc =
367 data.GetU16(&offset); // Maximum extra paragraphs needed
368 dos_header.e_ss = data.GetU16(&offset); // Initial (relative) SS value
369 dos_header.e_sp = data.GetU16(&offset); // Initial SP value
370 dos_header.e_csum = data.GetU16(&offset); // Checksum
371 dos_header.e_ip = data.GetU16(&offset); // Initial IP value
372 dos_header.e_cs = data.GetU16(&offset); // Initial (relative) CS value
373 dos_header.e_lfarlc =
374 data.GetU16(&offset); // File address of relocation table
375 dos_header.e_ovno = data.GetU16(&offset); // Overlay number
376
377 dos_header.e_res[0] = data.GetU16(&offset); // Reserved words
378 dos_header.e_res[1] = data.GetU16(&offset); // Reserved words
379 dos_header.e_res[2] = data.GetU16(&offset); // Reserved words
380 dos_header.e_res[3] = data.GetU16(&offset); // Reserved words
381
382 dos_header.e_oemid =
383 data.GetU16(&offset); // OEM identifier (for e_oeminfo)
384 dos_header.e_oeminfo =
385 data.GetU16(&offset); // OEM information; e_oemid specific
386 dos_header.e_res2[0] = data.GetU16(&offset); // Reserved words
387 dos_header.e_res2[1] = data.GetU16(&offset); // Reserved words
388 dos_header.e_res2[2] = data.GetU16(&offset); // Reserved words
389 dos_header.e_res2[3] = data.GetU16(&offset); // Reserved words
390 dos_header.e_res2[4] = data.GetU16(&offset); // Reserved words
391 dos_header.e_res2[5] = data.GetU16(&offset); // Reserved words
392 dos_header.e_res2[6] = data.GetU16(&offset); // Reserved words
393 dos_header.e_res2[7] = data.GetU16(&offset); // Reserved words
394 dos_header.e_res2[8] = data.GetU16(&offset); // Reserved words
395 dos_header.e_res2[9] = data.GetU16(&offset); // Reserved words
396
397 dos_header.e_lfanew =
398 data.GetU32(&offset); // File address of new exe header
399 }
400 }
401 if (!success)
402 memset(&dos_header, 0, sizeof(dos_header));
403 return success;
404 }
405
406 // ParserCOFFHeader
ParseCOFFHeader(DataExtractor & data,lldb::offset_t * offset_ptr,coff_header_t & coff_header)407 bool ObjectFilePECOFF::ParseCOFFHeader(DataExtractor &data,
408 lldb::offset_t *offset_ptr,
409 coff_header_t &coff_header) {
410 bool success =
411 data.ValidOffsetForDataOfSize(*offset_ptr, sizeof(coff_header));
412 if (success) {
413 coff_header.machine = data.GetU16(offset_ptr);
414 coff_header.nsects = data.GetU16(offset_ptr);
415 coff_header.modtime = data.GetU32(offset_ptr);
416 coff_header.symoff = data.GetU32(offset_ptr);
417 coff_header.nsyms = data.GetU32(offset_ptr);
418 coff_header.hdrsize = data.GetU16(offset_ptr);
419 coff_header.flags = data.GetU16(offset_ptr);
420 }
421 if (!success)
422 memset(&coff_header, 0, sizeof(coff_header));
423 return success;
424 }
425
ParseCOFFOptionalHeader(lldb::offset_t * offset_ptr)426 bool ObjectFilePECOFF::ParseCOFFOptionalHeader(lldb::offset_t *offset_ptr) {
427 bool success = false;
428 const lldb::offset_t end_offset = *offset_ptr + m_coff_header.hdrsize;
429 if (*offset_ptr < end_offset) {
430 success = true;
431 m_coff_header_opt.magic = m_data.GetU16(offset_ptr);
432 m_coff_header_opt.major_linker_version = m_data.GetU8(offset_ptr);
433 m_coff_header_opt.minor_linker_version = m_data.GetU8(offset_ptr);
434 m_coff_header_opt.code_size = m_data.GetU32(offset_ptr);
435 m_coff_header_opt.data_size = m_data.GetU32(offset_ptr);
436 m_coff_header_opt.bss_size = m_data.GetU32(offset_ptr);
437 m_coff_header_opt.entry = m_data.GetU32(offset_ptr);
438 m_coff_header_opt.code_offset = m_data.GetU32(offset_ptr);
439
440 const uint32_t addr_byte_size = GetAddressByteSize();
441
442 if (*offset_ptr < end_offset) {
443 if (m_coff_header_opt.magic == OPT_HEADER_MAGIC_PE32) {
444 // PE32 only
445 m_coff_header_opt.data_offset = m_data.GetU32(offset_ptr);
446 } else
447 m_coff_header_opt.data_offset = 0;
448
449 if (*offset_ptr < end_offset) {
450 m_coff_header_opt.image_base =
451 m_data.GetMaxU64(offset_ptr, addr_byte_size);
452 m_coff_header_opt.sect_alignment = m_data.GetU32(offset_ptr);
453 m_coff_header_opt.file_alignment = m_data.GetU32(offset_ptr);
454 m_coff_header_opt.major_os_system_version = m_data.GetU16(offset_ptr);
455 m_coff_header_opt.minor_os_system_version = m_data.GetU16(offset_ptr);
456 m_coff_header_opt.major_image_version = m_data.GetU16(offset_ptr);
457 m_coff_header_opt.minor_image_version = m_data.GetU16(offset_ptr);
458 m_coff_header_opt.major_subsystem_version = m_data.GetU16(offset_ptr);
459 m_coff_header_opt.minor_subsystem_version = m_data.GetU16(offset_ptr);
460 m_coff_header_opt.reserved1 = m_data.GetU32(offset_ptr);
461 m_coff_header_opt.image_size = m_data.GetU32(offset_ptr);
462 m_coff_header_opt.header_size = m_data.GetU32(offset_ptr);
463 m_coff_header_opt.checksum = m_data.GetU32(offset_ptr);
464 m_coff_header_opt.subsystem = m_data.GetU16(offset_ptr);
465 m_coff_header_opt.dll_flags = m_data.GetU16(offset_ptr);
466 m_coff_header_opt.stack_reserve_size =
467 m_data.GetMaxU64(offset_ptr, addr_byte_size);
468 m_coff_header_opt.stack_commit_size =
469 m_data.GetMaxU64(offset_ptr, addr_byte_size);
470 m_coff_header_opt.heap_reserve_size =
471 m_data.GetMaxU64(offset_ptr, addr_byte_size);
472 m_coff_header_opt.heap_commit_size =
473 m_data.GetMaxU64(offset_ptr, addr_byte_size);
474 m_coff_header_opt.loader_flags = m_data.GetU32(offset_ptr);
475 uint32_t num_data_dir_entries = m_data.GetU32(offset_ptr);
476 m_coff_header_opt.data_dirs.clear();
477 m_coff_header_opt.data_dirs.resize(num_data_dir_entries);
478 uint32_t i;
479 for (i = 0; i < num_data_dir_entries; i++) {
480 m_coff_header_opt.data_dirs[i].vmaddr = m_data.GetU32(offset_ptr);
481 m_coff_header_opt.data_dirs[i].vmsize = m_data.GetU32(offset_ptr);
482 }
483
484 m_image_base = m_coff_header_opt.image_base;
485 }
486 }
487 }
488 // Make sure we are on track for section data which follows
489 *offset_ptr = end_offset;
490 return success;
491 }
492
GetRVA(const Address & addr) const493 uint32_t ObjectFilePECOFF::GetRVA(const Address &addr) const {
494 return addr.GetFileAddress() - m_image_base;
495 }
496
GetAddress(uint32_t rva)497 Address ObjectFilePECOFF::GetAddress(uint32_t rva) {
498 SectionList *sect_list = GetSectionList();
499 if (!sect_list)
500 return Address(GetFileAddress(rva));
501
502 return Address(GetFileAddress(rva), sect_list);
503 }
504
GetFileAddress(uint32_t rva) const505 lldb::addr_t ObjectFilePECOFF::GetFileAddress(uint32_t rva) const {
506 return m_image_base + rva;
507 }
508
ReadImageData(uint32_t offset,size_t size)509 DataExtractor ObjectFilePECOFF::ReadImageData(uint32_t offset, size_t size) {
510 if (!size)
511 return {};
512
513 if (m_data.ValidOffsetForDataOfSize(offset, size))
514 return DataExtractor(m_data, offset, size);
515
516 ProcessSP process_sp(m_process_wp.lock());
517 DataExtractor data;
518 if (process_sp) {
519 auto data_up = std::make_unique<DataBufferHeap>(size, 0);
520 Status readmem_error;
521 size_t bytes_read =
522 process_sp->ReadMemory(m_image_base + offset, data_up->GetBytes(),
523 data_up->GetByteSize(), readmem_error);
524 if (bytes_read == size) {
525 DataBufferSP buffer_sp(data_up.release());
526 data.SetData(buffer_sp, 0, buffer_sp->GetByteSize());
527 }
528 }
529 return data;
530 }
531
ReadImageDataByRVA(uint32_t rva,size_t size)532 DataExtractor ObjectFilePECOFF::ReadImageDataByRVA(uint32_t rva, size_t size) {
533 Address addr = GetAddress(rva);
534 SectionSP sect = addr.GetSection();
535 if (!sect)
536 return {};
537 rva = sect->GetFileOffset() + addr.GetOffset();
538
539 return ReadImageData(rva, size);
540 }
541
542 // ParseSectionHeaders
ParseSectionHeaders(uint32_t section_header_data_offset)543 bool ObjectFilePECOFF::ParseSectionHeaders(
544 uint32_t section_header_data_offset) {
545 const uint32_t nsects = m_coff_header.nsects;
546 m_sect_headers.clear();
547
548 if (nsects > 0) {
549 const size_t section_header_byte_size = nsects * sizeof(section_header_t);
550 DataExtractor section_header_data =
551 ReadImageData(section_header_data_offset, section_header_byte_size);
552
553 lldb::offset_t offset = 0;
554 if (section_header_data.ValidOffsetForDataOfSize(
555 offset, section_header_byte_size)) {
556 m_sect_headers.resize(nsects);
557
558 for (uint32_t idx = 0; idx < nsects; ++idx) {
559 const void *name_data = section_header_data.GetData(&offset, 8);
560 if (name_data) {
561 memcpy(m_sect_headers[idx].name, name_data, 8);
562 m_sect_headers[idx].vmsize = section_header_data.GetU32(&offset);
563 m_sect_headers[idx].vmaddr = section_header_data.GetU32(&offset);
564 m_sect_headers[idx].size = section_header_data.GetU32(&offset);
565 m_sect_headers[idx].offset = section_header_data.GetU32(&offset);
566 m_sect_headers[idx].reloff = section_header_data.GetU32(&offset);
567 m_sect_headers[idx].lineoff = section_header_data.GetU32(&offset);
568 m_sect_headers[idx].nreloc = section_header_data.GetU16(&offset);
569 m_sect_headers[idx].nline = section_header_data.GetU16(&offset);
570 m_sect_headers[idx].flags = section_header_data.GetU32(&offset);
571 }
572 }
573 }
574 }
575
576 return !m_sect_headers.empty();
577 }
578
GetSectionName(const section_header_t & sect)579 llvm::StringRef ObjectFilePECOFF::GetSectionName(const section_header_t §) {
580 llvm::StringRef hdr_name(sect.name, llvm::array_lengthof(sect.name));
581 hdr_name = hdr_name.split('\0').first;
582 if (hdr_name.consume_front("/")) {
583 lldb::offset_t stroff;
584 if (!to_integer(hdr_name, stroff, 10))
585 return "";
586 lldb::offset_t string_file_offset =
587 m_coff_header.symoff + (m_coff_header.nsyms * 18) + stroff;
588 if (const char *name = m_data.GetCStr(&string_file_offset))
589 return name;
590 return "";
591 }
592 return hdr_name;
593 }
594
595 // GetNListSymtab
GetSymtab()596 Symtab *ObjectFilePECOFF::GetSymtab() {
597 ModuleSP module_sp(GetModule());
598 if (module_sp) {
599 std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex());
600 if (m_symtab_up == nullptr) {
601 SectionList *sect_list = GetSectionList();
602 m_symtab_up = std::make_unique<Symtab>(this);
603 std::lock_guard<std::recursive_mutex> guard(m_symtab_up->GetMutex());
604
605 const uint32_t num_syms = m_coff_header.nsyms;
606
607 if (m_file && num_syms > 0 && m_coff_header.symoff > 0) {
608 const uint32_t symbol_size = 18;
609 const size_t symbol_data_size = num_syms * symbol_size;
610 // Include the 4-byte string table size at the end of the symbols
611 DataExtractor symtab_data =
612 ReadImageData(m_coff_header.symoff, symbol_data_size + 4);
613 lldb::offset_t offset = symbol_data_size;
614 const uint32_t strtab_size = symtab_data.GetU32(&offset);
615 if (strtab_size > 0) {
616 DataExtractor strtab_data = ReadImageData(
617 m_coff_header.symoff + symbol_data_size, strtab_size);
618
619 offset = 0;
620 std::string symbol_name;
621 Symbol *symbols = m_symtab_up->Resize(num_syms);
622 for (uint32_t i = 0; i < num_syms; ++i) {
623 coff_symbol_t symbol;
624 const uint32_t symbol_offset = offset;
625 const char *symbol_name_cstr = nullptr;
626 // If the first 4 bytes of the symbol string are zero, then they
627 // are followed by a 4-byte string table offset. Else these
628 // 8 bytes contain the symbol name
629 if (symtab_data.GetU32(&offset) == 0) {
630 // Long string that doesn't fit into the symbol table name, so
631 // now we must read the 4 byte string table offset
632 uint32_t strtab_offset = symtab_data.GetU32(&offset);
633 symbol_name_cstr = strtab_data.PeekCStr(strtab_offset);
634 symbol_name.assign(symbol_name_cstr);
635 } else {
636 // Short string that fits into the symbol table name which is 8
637 // bytes
638 offset += sizeof(symbol.name) - 4; // Skip remaining
639 symbol_name_cstr = symtab_data.PeekCStr(symbol_offset);
640 if (symbol_name_cstr == nullptr)
641 break;
642 symbol_name.assign(symbol_name_cstr, sizeof(symbol.name));
643 }
644 symbol.value = symtab_data.GetU32(&offset);
645 symbol.sect = symtab_data.GetU16(&offset);
646 symbol.type = symtab_data.GetU16(&offset);
647 symbol.storage = symtab_data.GetU8(&offset);
648 symbol.naux = symtab_data.GetU8(&offset);
649 symbols[i].GetMangled().SetValue(ConstString(symbol_name.c_str()));
650 if ((int16_t)symbol.sect >= 1) {
651 Address symbol_addr(sect_list->FindSectionByID(symbol.sect),
652 symbol.value);
653 symbols[i].GetAddressRef() = symbol_addr;
654 symbols[i].SetType(MapSymbolType(symbol.type));
655 }
656
657 if (symbol.naux > 0) {
658 i += symbol.naux;
659 offset += symbol.naux * symbol_size;
660 }
661 }
662 }
663 }
664
665 // Read export header
666 if (coff_data_dir_export_table < m_coff_header_opt.data_dirs.size() &&
667 m_coff_header_opt.data_dirs[coff_data_dir_export_table].vmsize > 0 &&
668 m_coff_header_opt.data_dirs[coff_data_dir_export_table].vmaddr > 0) {
669 export_directory_entry export_table;
670 uint32_t data_start =
671 m_coff_header_opt.data_dirs[coff_data_dir_export_table].vmaddr;
672
673 DataExtractor symtab_data = ReadImageDataByRVA(
674 data_start, m_coff_header_opt.data_dirs[0].vmsize);
675 lldb::offset_t offset = 0;
676
677 // Read export_table header
678 export_table.characteristics = symtab_data.GetU32(&offset);
679 export_table.time_date_stamp = symtab_data.GetU32(&offset);
680 export_table.major_version = symtab_data.GetU16(&offset);
681 export_table.minor_version = symtab_data.GetU16(&offset);
682 export_table.name = symtab_data.GetU32(&offset);
683 export_table.base = symtab_data.GetU32(&offset);
684 export_table.number_of_functions = symtab_data.GetU32(&offset);
685 export_table.number_of_names = symtab_data.GetU32(&offset);
686 export_table.address_of_functions = symtab_data.GetU32(&offset);
687 export_table.address_of_names = symtab_data.GetU32(&offset);
688 export_table.address_of_name_ordinals = symtab_data.GetU32(&offset);
689
690 bool has_ordinal = export_table.address_of_name_ordinals != 0;
691
692 lldb::offset_t name_offset = export_table.address_of_names - data_start;
693 lldb::offset_t name_ordinal_offset =
694 export_table.address_of_name_ordinals - data_start;
695
696 Symbol *symbols = m_symtab_up->Resize(export_table.number_of_names);
697
698 std::string symbol_name;
699
700 // Read each export table entry
701 for (size_t i = 0; i < export_table.number_of_names; ++i) {
702 uint32_t name_ordinal =
703 has_ordinal ? symtab_data.GetU16(&name_ordinal_offset) : i;
704 uint32_t name_address = symtab_data.GetU32(&name_offset);
705
706 const char *symbol_name_cstr =
707 symtab_data.PeekCStr(name_address - data_start);
708 symbol_name.assign(symbol_name_cstr);
709
710 lldb::offset_t function_offset = export_table.address_of_functions -
711 data_start +
712 sizeof(uint32_t) * name_ordinal;
713 uint32_t function_rva = symtab_data.GetU32(&function_offset);
714
715 Address symbol_addr(m_coff_header_opt.image_base + function_rva,
716 sect_list);
717 symbols[i].GetMangled().SetValue(ConstString(symbol_name.c_str()));
718 symbols[i].GetAddressRef() = symbol_addr;
719 symbols[i].SetType(lldb::eSymbolTypeCode);
720 symbols[i].SetDebug(true);
721 }
722 }
723 m_symtab_up->CalculateSymbolSizes();
724 }
725 }
726 return m_symtab_up.get();
727 }
728
CreateCallFrameInfo()729 std::unique_ptr<CallFrameInfo> ObjectFilePECOFF::CreateCallFrameInfo() {
730 if (coff_data_dir_exception_table >= m_coff_header_opt.data_dirs.size())
731 return {};
732
733 data_directory data_dir_exception =
734 m_coff_header_opt.data_dirs[coff_data_dir_exception_table];
735 if (!data_dir_exception.vmaddr)
736 return {};
737
738 if (m_coff_header.machine != llvm::COFF::IMAGE_FILE_MACHINE_AMD64)
739 return {};
740
741 return std::make_unique<PECallFrameInfo>(*this, data_dir_exception.vmaddr,
742 data_dir_exception.vmsize);
743 }
744
IsStripped()745 bool ObjectFilePECOFF::IsStripped() {
746 // TODO: determine this for COFF
747 return false;
748 }
749
GetSectionType(llvm::StringRef sect_name,const section_header_t & sect)750 SectionType ObjectFilePECOFF::GetSectionType(llvm::StringRef sect_name,
751 const section_header_t §) {
752 ConstString const_sect_name(sect_name);
753 static ConstString g_code_sect_name(".code");
754 static ConstString g_CODE_sect_name("CODE");
755 static ConstString g_data_sect_name(".data");
756 static ConstString g_DATA_sect_name("DATA");
757 static ConstString g_bss_sect_name(".bss");
758 static ConstString g_BSS_sect_name("BSS");
759
760 if (sect.flags & llvm::COFF::IMAGE_SCN_CNT_CODE &&
761 ((const_sect_name == g_code_sect_name) ||
762 (const_sect_name == g_CODE_sect_name))) {
763 return eSectionTypeCode;
764 }
765 if (sect.flags & llvm::COFF::IMAGE_SCN_CNT_INITIALIZED_DATA &&
766 ((const_sect_name == g_data_sect_name) ||
767 (const_sect_name == g_DATA_sect_name))) {
768 if (sect.size == 0 && sect.offset == 0)
769 return eSectionTypeZeroFill;
770 else
771 return eSectionTypeData;
772 }
773 if (sect.flags & llvm::COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA &&
774 ((const_sect_name == g_bss_sect_name) ||
775 (const_sect_name == g_BSS_sect_name))) {
776 if (sect.size == 0)
777 return eSectionTypeZeroFill;
778 else
779 return eSectionTypeData;
780 }
781
782 SectionType section_type =
783 llvm::StringSwitch<SectionType>(sect_name)
784 .Case(".debug", eSectionTypeDebug)
785 .Case(".stabstr", eSectionTypeDataCString)
786 .Case(".reloc", eSectionTypeOther)
787 .Case(".debug_abbrev", eSectionTypeDWARFDebugAbbrev)
788 .Case(".debug_aranges", eSectionTypeDWARFDebugAranges)
789 .Case(".debug_frame", eSectionTypeDWARFDebugFrame)
790 .Case(".debug_info", eSectionTypeDWARFDebugInfo)
791 .Case(".debug_line", eSectionTypeDWARFDebugLine)
792 .Case(".debug_loc", eSectionTypeDWARFDebugLoc)
793 .Case(".debug_loclists", eSectionTypeDWARFDebugLocLists)
794 .Case(".debug_macinfo", eSectionTypeDWARFDebugMacInfo)
795 .Case(".debug_names", eSectionTypeDWARFDebugNames)
796 .Case(".debug_pubnames", eSectionTypeDWARFDebugPubNames)
797 .Case(".debug_pubtypes", eSectionTypeDWARFDebugPubTypes)
798 .Case(".debug_ranges", eSectionTypeDWARFDebugRanges)
799 .Case(".debug_str", eSectionTypeDWARFDebugStr)
800 .Case(".debug_types", eSectionTypeDWARFDebugTypes)
801 // .eh_frame can be truncated to 8 chars.
802 .Cases(".eh_frame", ".eh_fram", eSectionTypeEHFrame)
803 .Case(".gosymtab", eSectionTypeGoSymtab)
804 .Default(eSectionTypeInvalid);
805 if (section_type != eSectionTypeInvalid)
806 return section_type;
807
808 if (sect.flags & llvm::COFF::IMAGE_SCN_CNT_CODE)
809 return eSectionTypeCode;
810 if (sect.flags & llvm::COFF::IMAGE_SCN_CNT_INITIALIZED_DATA)
811 return eSectionTypeData;
812 if (sect.flags & llvm::COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA) {
813 if (sect.size == 0)
814 return eSectionTypeZeroFill;
815 else
816 return eSectionTypeData;
817 }
818 return eSectionTypeOther;
819 }
820
CreateSections(SectionList & unified_section_list)821 void ObjectFilePECOFF::CreateSections(SectionList &unified_section_list) {
822 if (m_sections_up)
823 return;
824 m_sections_up = std::make_unique<SectionList>();
825 ModuleSP module_sp(GetModule());
826 if (module_sp) {
827 std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex());
828
829 SectionSP header_sp = std::make_shared<Section>(
830 module_sp, this, ~user_id_t(0), ConstString("PECOFF header"),
831 eSectionTypeOther, m_coff_header_opt.image_base,
832 m_coff_header_opt.header_size,
833 /*file_offset*/ 0, m_coff_header_opt.header_size,
834 m_coff_header_opt.sect_alignment,
835 /*flags*/ 0);
836 header_sp->SetPermissions(ePermissionsReadable);
837 m_sections_up->AddSection(header_sp);
838 unified_section_list.AddSection(header_sp);
839
840 const uint32_t nsects = m_sect_headers.size();
841 ModuleSP module_sp(GetModule());
842 for (uint32_t idx = 0; idx < nsects; ++idx) {
843 llvm::StringRef sect_name = GetSectionName(m_sect_headers[idx]);
844 ConstString const_sect_name(sect_name);
845 SectionType section_type = GetSectionType(sect_name, m_sect_headers[idx]);
846
847 SectionSP section_sp(new Section(
848 module_sp, // Module to which this section belongs
849 this, // Object file to which this section belongs
850 idx + 1, // Section ID is the 1 based section index.
851 const_sect_name, // Name of this section
852 section_type,
853 m_coff_header_opt.image_base +
854 m_sect_headers[idx].vmaddr, // File VM address == addresses as
855 // they are found in the object file
856 m_sect_headers[idx].vmsize, // VM size in bytes of this section
857 m_sect_headers[idx]
858 .offset, // Offset to the data for this section in the file
859 m_sect_headers[idx]
860 .size, // Size in bytes of this section as found in the file
861 m_coff_header_opt.sect_alignment, // Section alignment
862 m_sect_headers[idx].flags)); // Flags for this section
863
864 uint32_t permissions = 0;
865 if (m_sect_headers[idx].flags & llvm::COFF::IMAGE_SCN_MEM_EXECUTE)
866 permissions |= ePermissionsExecutable;
867 if (m_sect_headers[idx].flags & llvm::COFF::IMAGE_SCN_MEM_READ)
868 permissions |= ePermissionsReadable;
869 if (m_sect_headers[idx].flags & llvm::COFF::IMAGE_SCN_MEM_WRITE)
870 permissions |= ePermissionsWritable;
871 section_sp->SetPermissions(permissions);
872
873 m_sections_up->AddSection(section_sp);
874 unified_section_list.AddSection(section_sp);
875 }
876 }
877 }
878
GetUUID()879 UUID ObjectFilePECOFF::GetUUID() {
880 if (m_uuid.IsValid())
881 return m_uuid;
882
883 if (!CreateBinary())
884 return UUID();
885
886 m_uuid = GetCoffUUID(*m_binary);
887 return m_uuid;
888 }
889
ParseDependentModules()890 uint32_t ObjectFilePECOFF::ParseDependentModules() {
891 ModuleSP module_sp(GetModule());
892 if (!module_sp)
893 return 0;
894
895 std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex());
896 if (m_deps_filespec)
897 return m_deps_filespec->GetSize();
898
899 // Cache coff binary if it is not done yet.
900 if (!CreateBinary())
901 return 0;
902
903 Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_OBJECT));
904 LLDB_LOG(log, "this = {0}, module = {1} ({2}), file = {3}, binary = {4}",
905 this, GetModule().get(), GetModule()->GetSpecificationDescription(),
906 m_file.GetPath(), m_binary.get());
907
908 m_deps_filespec = FileSpecList();
909
910 for (const auto &entry : m_binary->import_directories()) {
911 llvm::StringRef dll_name;
912 // Report a bogus entry.
913 if (llvm::Error e = entry.getName(dll_name)) {
914 LLDB_LOGF(log,
915 "ObjectFilePECOFF::ParseDependentModules() - failed to get "
916 "import directory entry name: %s",
917 llvm::toString(std::move(e)).c_str());
918 continue;
919 }
920
921 // At this moment we only have the base name of the DLL. The full path can
922 // only be seen after the dynamic loading. Our best guess is Try to get it
923 // with the help of the object file's directory.
924 llvm::SmallString<128> dll_fullpath;
925 FileSpec dll_specs(dll_name);
926 dll_specs.GetDirectory().SetString(m_file.GetDirectory().GetCString());
927
928 if (!llvm::sys::fs::real_path(dll_specs.GetPath(), dll_fullpath))
929 m_deps_filespec->EmplaceBack(dll_fullpath);
930 else {
931 // Known DLLs or DLL not found in the object file directory.
932 m_deps_filespec->EmplaceBack(dll_name);
933 }
934 }
935 return m_deps_filespec->GetSize();
936 }
937
GetDependentModules(FileSpecList & files)938 uint32_t ObjectFilePECOFF::GetDependentModules(FileSpecList &files) {
939 auto num_modules = ParseDependentModules();
940 auto original_size = files.GetSize();
941
942 for (unsigned i = 0; i < num_modules; ++i)
943 files.AppendIfUnique(m_deps_filespec->GetFileSpecAtIndex(i));
944
945 return files.GetSize() - original_size;
946 }
947
GetEntryPointAddress()948 lldb_private::Address ObjectFilePECOFF::GetEntryPointAddress() {
949 if (m_entry_point_address.IsValid())
950 return m_entry_point_address;
951
952 if (!ParseHeader() || !IsExecutable())
953 return m_entry_point_address;
954
955 SectionList *section_list = GetSectionList();
956 addr_t file_addr = m_coff_header_opt.entry + m_coff_header_opt.image_base;
957
958 if (!section_list)
959 m_entry_point_address.SetOffset(file_addr);
960 else
961 m_entry_point_address.ResolveAddressUsingFileSections(file_addr,
962 section_list);
963 return m_entry_point_address;
964 }
965
GetBaseAddress()966 Address ObjectFilePECOFF::GetBaseAddress() {
967 return Address(GetSectionList()->GetSectionAtIndex(0), 0);
968 }
969
970 // Dump
971 //
972 // Dump the specifics of the runtime file container (such as any headers
973 // segments, sections, etc).
Dump(Stream * s)974 void ObjectFilePECOFF::Dump(Stream *s) {
975 ModuleSP module_sp(GetModule());
976 if (module_sp) {
977 std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex());
978 s->Printf("%p: ", static_cast<void *>(this));
979 s->Indent();
980 s->PutCString("ObjectFilePECOFF");
981
982 ArchSpec header_arch = GetArchitecture();
983
984 *s << ", file = '" << m_file
985 << "', arch = " << header_arch.GetArchitectureName() << "\n";
986
987 SectionList *sections = GetSectionList();
988 if (sections)
989 sections->Dump(s->AsRawOstream(), s->GetIndentLevel(), nullptr, true,
990 UINT32_MAX);
991
992 if (m_symtab_up)
993 m_symtab_up->Dump(s, nullptr, eSortOrderNone);
994
995 if (m_dos_header.e_magic)
996 DumpDOSHeader(s, m_dos_header);
997 if (m_coff_header.machine) {
998 DumpCOFFHeader(s, m_coff_header);
999 if (m_coff_header.hdrsize)
1000 DumpOptCOFFHeader(s, m_coff_header_opt);
1001 }
1002 s->EOL();
1003 DumpSectionHeaders(s);
1004 s->EOL();
1005
1006 DumpDependentModules(s);
1007 s->EOL();
1008 }
1009 }
1010
1011 // DumpDOSHeader
1012 //
1013 // Dump the MS-DOS header to the specified output stream
DumpDOSHeader(Stream * s,const dos_header_t & header)1014 void ObjectFilePECOFF::DumpDOSHeader(Stream *s, const dos_header_t &header) {
1015 s->PutCString("MSDOS Header\n");
1016 s->Printf(" e_magic = 0x%4.4x\n", header.e_magic);
1017 s->Printf(" e_cblp = 0x%4.4x\n", header.e_cblp);
1018 s->Printf(" e_cp = 0x%4.4x\n", header.e_cp);
1019 s->Printf(" e_crlc = 0x%4.4x\n", header.e_crlc);
1020 s->Printf(" e_cparhdr = 0x%4.4x\n", header.e_cparhdr);
1021 s->Printf(" e_minalloc = 0x%4.4x\n", header.e_minalloc);
1022 s->Printf(" e_maxalloc = 0x%4.4x\n", header.e_maxalloc);
1023 s->Printf(" e_ss = 0x%4.4x\n", header.e_ss);
1024 s->Printf(" e_sp = 0x%4.4x\n", header.e_sp);
1025 s->Printf(" e_csum = 0x%4.4x\n", header.e_csum);
1026 s->Printf(" e_ip = 0x%4.4x\n", header.e_ip);
1027 s->Printf(" e_cs = 0x%4.4x\n", header.e_cs);
1028 s->Printf(" e_lfarlc = 0x%4.4x\n", header.e_lfarlc);
1029 s->Printf(" e_ovno = 0x%4.4x\n", header.e_ovno);
1030 s->Printf(" e_res[4] = { 0x%4.4x, 0x%4.4x, 0x%4.4x, 0x%4.4x }\n",
1031 header.e_res[0], header.e_res[1], header.e_res[2], header.e_res[3]);
1032 s->Printf(" e_oemid = 0x%4.4x\n", header.e_oemid);
1033 s->Printf(" e_oeminfo = 0x%4.4x\n", header.e_oeminfo);
1034 s->Printf(" e_res2[10] = { 0x%4.4x, 0x%4.4x, 0x%4.4x, 0x%4.4x, 0x%4.4x, "
1035 "0x%4.4x, 0x%4.4x, 0x%4.4x, 0x%4.4x, 0x%4.4x }\n",
1036 header.e_res2[0], header.e_res2[1], header.e_res2[2],
1037 header.e_res2[3], header.e_res2[4], header.e_res2[5],
1038 header.e_res2[6], header.e_res2[7], header.e_res2[8],
1039 header.e_res2[9]);
1040 s->Printf(" e_lfanew = 0x%8.8x\n", header.e_lfanew);
1041 }
1042
1043 // DumpCOFFHeader
1044 //
1045 // Dump the COFF header to the specified output stream
DumpCOFFHeader(Stream * s,const coff_header_t & header)1046 void ObjectFilePECOFF::DumpCOFFHeader(Stream *s, const coff_header_t &header) {
1047 s->PutCString("COFF Header\n");
1048 s->Printf(" machine = 0x%4.4x\n", header.machine);
1049 s->Printf(" nsects = 0x%4.4x\n", header.nsects);
1050 s->Printf(" modtime = 0x%8.8x\n", header.modtime);
1051 s->Printf(" symoff = 0x%8.8x\n", header.symoff);
1052 s->Printf(" nsyms = 0x%8.8x\n", header.nsyms);
1053 s->Printf(" hdrsize = 0x%4.4x\n", header.hdrsize);
1054 }
1055
1056 // DumpOptCOFFHeader
1057 //
1058 // Dump the optional COFF header to the specified output stream
DumpOptCOFFHeader(Stream * s,const coff_opt_header_t & header)1059 void ObjectFilePECOFF::DumpOptCOFFHeader(Stream *s,
1060 const coff_opt_header_t &header) {
1061 s->PutCString("Optional COFF Header\n");
1062 s->Printf(" magic = 0x%4.4x\n", header.magic);
1063 s->Printf(" major_linker_version = 0x%2.2x\n",
1064 header.major_linker_version);
1065 s->Printf(" minor_linker_version = 0x%2.2x\n",
1066 header.minor_linker_version);
1067 s->Printf(" code_size = 0x%8.8x\n", header.code_size);
1068 s->Printf(" data_size = 0x%8.8x\n", header.data_size);
1069 s->Printf(" bss_size = 0x%8.8x\n", header.bss_size);
1070 s->Printf(" entry = 0x%8.8x\n", header.entry);
1071 s->Printf(" code_offset = 0x%8.8x\n", header.code_offset);
1072 s->Printf(" data_offset = 0x%8.8x\n", header.data_offset);
1073 s->Printf(" image_base = 0x%16.16" PRIx64 "\n",
1074 header.image_base);
1075 s->Printf(" sect_alignment = 0x%8.8x\n", header.sect_alignment);
1076 s->Printf(" file_alignment = 0x%8.8x\n", header.file_alignment);
1077 s->Printf(" major_os_system_version = 0x%4.4x\n",
1078 header.major_os_system_version);
1079 s->Printf(" minor_os_system_version = 0x%4.4x\n",
1080 header.minor_os_system_version);
1081 s->Printf(" major_image_version = 0x%4.4x\n",
1082 header.major_image_version);
1083 s->Printf(" minor_image_version = 0x%4.4x\n",
1084 header.minor_image_version);
1085 s->Printf(" major_subsystem_version = 0x%4.4x\n",
1086 header.major_subsystem_version);
1087 s->Printf(" minor_subsystem_version = 0x%4.4x\n",
1088 header.minor_subsystem_version);
1089 s->Printf(" reserved1 = 0x%8.8x\n", header.reserved1);
1090 s->Printf(" image_size = 0x%8.8x\n", header.image_size);
1091 s->Printf(" header_size = 0x%8.8x\n", header.header_size);
1092 s->Printf(" checksum = 0x%8.8x\n", header.checksum);
1093 s->Printf(" subsystem = 0x%4.4x\n", header.subsystem);
1094 s->Printf(" dll_flags = 0x%4.4x\n", header.dll_flags);
1095 s->Printf(" stack_reserve_size = 0x%16.16" PRIx64 "\n",
1096 header.stack_reserve_size);
1097 s->Printf(" stack_commit_size = 0x%16.16" PRIx64 "\n",
1098 header.stack_commit_size);
1099 s->Printf(" heap_reserve_size = 0x%16.16" PRIx64 "\n",
1100 header.heap_reserve_size);
1101 s->Printf(" heap_commit_size = 0x%16.16" PRIx64 "\n",
1102 header.heap_commit_size);
1103 s->Printf(" loader_flags = 0x%8.8x\n", header.loader_flags);
1104 s->Printf(" num_data_dir_entries = 0x%8.8x\n",
1105 (uint32_t)header.data_dirs.size());
1106 uint32_t i;
1107 for (i = 0; i < header.data_dirs.size(); i++) {
1108 s->Printf(" data_dirs[%2u] vmaddr = 0x%8.8x, vmsize = 0x%8.8x\n", i,
1109 header.data_dirs[i].vmaddr, header.data_dirs[i].vmsize);
1110 }
1111 }
1112 // DumpSectionHeader
1113 //
1114 // Dump a single ELF section header to the specified output stream
DumpSectionHeader(Stream * s,const section_header_t & sh)1115 void ObjectFilePECOFF::DumpSectionHeader(Stream *s,
1116 const section_header_t &sh) {
1117 std::string name = std::string(GetSectionName(sh));
1118 s->Printf("%-16s 0x%8.8x 0x%8.8x 0x%8.8x 0x%8.8x 0x%8.8x 0x%8.8x 0x%4.4x "
1119 "0x%4.4x 0x%8.8x\n",
1120 name.c_str(), sh.vmaddr, sh.vmsize, sh.offset, sh.size, sh.reloff,
1121 sh.lineoff, sh.nreloc, sh.nline, sh.flags);
1122 }
1123
1124 // DumpSectionHeaders
1125 //
1126 // Dump all of the ELF section header to the specified output stream
DumpSectionHeaders(Stream * s)1127 void ObjectFilePECOFF::DumpSectionHeaders(Stream *s) {
1128
1129 s->PutCString("Section Headers\n");
1130 s->PutCString("IDX name vm addr vm size file off file "
1131 "size reloc off line off nreloc nline flags\n");
1132 s->PutCString("==== ---------------- ---------- ---------- ---------- "
1133 "---------- ---------- ---------- ------ ------ ----------\n");
1134
1135 uint32_t idx = 0;
1136 SectionHeaderCollIter pos, end = m_sect_headers.end();
1137
1138 for (pos = m_sect_headers.begin(); pos != end; ++pos, ++idx) {
1139 s->Printf("[%2u] ", idx);
1140 ObjectFilePECOFF::DumpSectionHeader(s, *pos);
1141 }
1142 }
1143
1144 // DumpDependentModules
1145 //
1146 // Dump all of the dependent modules to the specified output stream
DumpDependentModules(lldb_private::Stream * s)1147 void ObjectFilePECOFF::DumpDependentModules(lldb_private::Stream *s) {
1148 auto num_modules = ParseDependentModules();
1149 if (num_modules > 0) {
1150 s->PutCString("Dependent Modules\n");
1151 for (unsigned i = 0; i < num_modules; ++i) {
1152 auto spec = m_deps_filespec->GetFileSpecAtIndex(i);
1153 s->Printf(" %s\n", spec.GetFilename().GetCString());
1154 }
1155 }
1156 }
1157
IsWindowsSubsystem()1158 bool ObjectFilePECOFF::IsWindowsSubsystem() {
1159 switch (m_coff_header_opt.subsystem) {
1160 case llvm::COFF::IMAGE_SUBSYSTEM_NATIVE:
1161 case llvm::COFF::IMAGE_SUBSYSTEM_WINDOWS_GUI:
1162 case llvm::COFF::IMAGE_SUBSYSTEM_WINDOWS_CUI:
1163 case llvm::COFF::IMAGE_SUBSYSTEM_NATIVE_WINDOWS:
1164 case llvm::COFF::IMAGE_SUBSYSTEM_WINDOWS_CE_GUI:
1165 case llvm::COFF::IMAGE_SUBSYSTEM_XBOX:
1166 case llvm::COFF::IMAGE_SUBSYSTEM_WINDOWS_BOOT_APPLICATION:
1167 return true;
1168 default:
1169 return false;
1170 }
1171 }
1172
GetArchitecture()1173 ArchSpec ObjectFilePECOFF::GetArchitecture() {
1174 uint16_t machine = m_coff_header.machine;
1175 switch (machine) {
1176 default:
1177 break;
1178 case llvm::COFF::IMAGE_FILE_MACHINE_AMD64:
1179 case llvm::COFF::IMAGE_FILE_MACHINE_I386:
1180 case llvm::COFF::IMAGE_FILE_MACHINE_POWERPC:
1181 case llvm::COFF::IMAGE_FILE_MACHINE_POWERPCFP:
1182 case llvm::COFF::IMAGE_FILE_MACHINE_ARM:
1183 case llvm::COFF::IMAGE_FILE_MACHINE_ARMNT:
1184 case llvm::COFF::IMAGE_FILE_MACHINE_THUMB:
1185 case llvm::COFF::IMAGE_FILE_MACHINE_ARM64:
1186 ArchSpec arch;
1187 arch.SetArchitecture(eArchTypeCOFF, machine, LLDB_INVALID_CPUTYPE,
1188 IsWindowsSubsystem() ? llvm::Triple::Win32
1189 : llvm::Triple::UnknownOS);
1190 return arch;
1191 }
1192 return ArchSpec();
1193 }
1194
CalculateType()1195 ObjectFile::Type ObjectFilePECOFF::CalculateType() {
1196 if (m_coff_header.machine != 0) {
1197 if ((m_coff_header.flags & llvm::COFF::IMAGE_FILE_DLL) == 0)
1198 return eTypeExecutable;
1199 else
1200 return eTypeSharedLibrary;
1201 }
1202 return eTypeExecutable;
1203 }
1204
CalculateStrata()1205 ObjectFile::Strata ObjectFilePECOFF::CalculateStrata() { return eStrataUser; }
1206
1207 // PluginInterface protocol
GetPluginName()1208 ConstString ObjectFilePECOFF::GetPluginName() { return GetPluginNameStatic(); }
1209
GetPluginVersion()1210 uint32_t ObjectFilePECOFF::GetPluginVersion() { return 1; }
1211