blob: 12d9a673e038683c3a6a1b51d2d071fc018bb4f1 [file] [log] [blame]
Greg Claytonf754f882011-09-09 20:33:05 +00001//===-- ObjectFilePECOFF.cpp ------------------------------------*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10#include "ObjectFilePECOFF.h"
Adrian McCarthyf7d18932015-11-20 23:09:11 +000011#include "WindowsMiniDump.h"
Greg Claytonf754f882011-09-09 20:33:05 +000012
Greg Claytonf754f882011-09-09 20:33:05 +000013#include "lldb/Core/FileSpecList.h"
14#include "lldb/Core/Module.h"
Greg Claytonf4d6de62013-04-24 22:29:28 +000015#include "lldb/Core/ModuleSpec.h"
Greg Claytonf754f882011-09-09 20:33:05 +000016#include "lldb/Core/PluginManager.h"
17#include "lldb/Core/Section.h"
18#include "lldb/Core/StreamFile.h"
Greg Claytonf754f882011-09-09 20:33:05 +000019#include "lldb/Symbol/ObjectFile.h"
Adrian McCarthyf7d18932015-11-20 23:09:11 +000020#include "lldb/Target/Process.h"
Virgile Bello2756adf2014-03-08 17:17:20 +000021#include "lldb/Target/SectionLoadList.h"
22#include "lldb/Target/Target.h"
Pavel Labath5f19b902017-11-13 16:16:33 +000023#include "lldb/Utility/ArchSpec.h"
Zachary Turner666cc0b2017-03-04 01:30:05 +000024#include "lldb/Utility/DataBufferHeap.h"
Zachary Turner5713a052017-03-22 18:40:07 +000025#include "lldb/Utility/FileSpec.h"
Aaron Smith037ed1b2018-12-06 21:36:39 +000026#include "lldb/Utility/Log.h"
Zachary Turnerbf9a7732017-02-02 21:39:50 +000027#include "lldb/Utility/StreamString.h"
Pavel Labath38d06322017-06-29 14:32:17 +000028#include "lldb/Utility/Timer.h"
Zachary Turner666cc0b2017-03-04 01:30:05 +000029#include "lldb/Utility/UUID.h"
Pavel Labath5f19b902017-11-13 16:16:33 +000030#include "llvm/BinaryFormat/COFF.h"
Greg Claytonf754f882011-09-09 20:33:05 +000031
Aaron Smith037ed1b2018-12-06 21:36:39 +000032#include "llvm/Object/COFFImportFile.h"
33#include "llvm/Support/Error.h"
Zachary Turner3f4a4b32017-02-24 18:56:49 +000034#include "llvm/Support/MemoryBuffer.h"
35
Kate Stoneb9c1b512016-09-06 20:57:50 +000036#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
Greg Claytonf754f882011-09-09 20:33:05 +000040
Greg Claytonf754f882011-09-09 20:33:05 +000041using namespace lldb;
42using namespace lldb_private;
43
Kate Stoneb9c1b512016-09-06 20:57:50 +000044void ObjectFilePECOFF::Initialize() {
45 PluginManager::RegisterPlugin(
46 GetPluginNameStatic(), GetPluginDescriptionStatic(), CreateInstance,
47 CreateMemoryInstance, GetModuleSpecifications, SaveCore);
Greg Claytonf754f882011-09-09 20:33:05 +000048}
49
Kate Stoneb9c1b512016-09-06 20:57:50 +000050void ObjectFilePECOFF::Terminate() {
51 PluginManager::UnregisterPlugin(CreateInstance);
Greg Claytonf754f882011-09-09 20:33:05 +000052}
53
Kate Stoneb9c1b512016-09-06 20:57:50 +000054lldb_private::ConstString ObjectFilePECOFF::GetPluginNameStatic() {
55 static ConstString g_name("pe-coff");
56 return g_name;
Greg Claytonf754f882011-09-09 20:33:05 +000057}
58
Kate Stoneb9c1b512016-09-06 20:57:50 +000059const char *ObjectFilePECOFF::GetPluginDescriptionStatic() {
60 return "Portable Executable and Common Object File Format object file reader "
61 "(32 and 64 bit)";
Greg Claytonf754f882011-09-09 20:33:05 +000062}
63
Kate Stoneb9c1b512016-09-06 20:57:50 +000064ObjectFile *ObjectFilePECOFF::CreateInstance(const lldb::ModuleSP &module_sp,
65 DataBufferSP &data_sp,
66 lldb::offset_t data_offset,
67 const lldb_private::FileSpec *file,
68 lldb::offset_t file_offset,
69 lldb::offset_t length) {
70 if (!data_sp) {
Pavel Labath50251fc2017-12-21 10:54:30 +000071 data_sp = MapFileData(file, length, file_offset);
Zachary Turner3f4a4b32017-02-24 18:56:49 +000072 if (!data_sp)
73 return nullptr;
Kate Stoneb9c1b512016-09-06 20:57:50 +000074 data_offset = 0;
75 }
Greg Claytonf754f882011-09-09 20:33:05 +000076
Zachary Turner3f4a4b32017-02-24 18:56:49 +000077 if (!ObjectFilePECOFF::MagicBytesMatch(data_sp))
78 return nullptr;
79
80 // Update the data to contain the entire file if it doesn't already
81 if (data_sp->GetByteSize() < length) {
Pavel Labath50251fc2017-12-21 10:54:30 +000082 data_sp = MapFileData(file, length, file_offset);
Zachary Turner3f4a4b32017-02-24 18:56:49 +000083 if (!data_sp)
84 return nullptr;
Kate Stoneb9c1b512016-09-06 20:57:50 +000085 }
Zachary Turner3f4a4b32017-02-24 18:56:49 +000086
87 auto objfile_ap = llvm::make_unique<ObjectFilePECOFF>(
88 module_sp, data_sp, data_offset, file, file_offset, length);
89 if (!objfile_ap || !objfile_ap->ParseHeader())
90 return nullptr;
91
Aaron Smith037ed1b2018-12-06 21:36:39 +000092 // Cache coff binary.
93 if (!objfile_ap->CreateBinary())
94 return nullptr;
95
Zachary Turner3f4a4b32017-02-24 18:56:49 +000096 return objfile_ap.release();
Greg Claytonf754f882011-09-09 20:33:05 +000097}
98
Kate Stoneb9c1b512016-09-06 20:57:50 +000099ObjectFile *ObjectFilePECOFF::CreateMemoryInstance(
100 const lldb::ModuleSP &module_sp, lldb::DataBufferSP &data_sp,
101 const lldb::ProcessSP &process_sp, lldb::addr_t header_addr) {
Walter Erquinigo344546b2016-10-17 20:28:19 +0000102 if (!data_sp || !ObjectFilePECOFF::MagicBytesMatch(data_sp))
103 return nullptr;
104 auto objfile_ap = llvm::make_unique<ObjectFilePECOFF>(
105 module_sp, data_sp, process_sp, header_addr);
106 if (objfile_ap.get() && objfile_ap->ParseHeader()) {
107 return objfile_ap.release();
108 }
109 return nullptr;
Greg Claytonc9660542012-02-05 02:38:54 +0000110}
111
Kate Stoneb9c1b512016-09-06 20:57:50 +0000112size_t ObjectFilePECOFF::GetModuleSpecifications(
113 const lldb_private::FileSpec &file, lldb::DataBufferSP &data_sp,
114 lldb::offset_t data_offset, lldb::offset_t file_offset,
115 lldb::offset_t length, lldb_private::ModuleSpecList &specs) {
116 const size_t initial_count = specs.GetSize();
Virgile Bello89eb1ba2014-03-09 09:59:36 +0000117
Kate Stoneb9c1b512016-09-06 20:57:50 +0000118 if (ObjectFilePECOFF::MagicBytesMatch(data_sp)) {
119 DataExtractor data;
120 data.SetData(data_sp, data_offset, length);
121 data.SetByteOrder(eByteOrderLittle);
Virgile Bello89eb1ba2014-03-09 09:59:36 +0000122
Kate Stoneb9c1b512016-09-06 20:57:50 +0000123 dos_header_t dos_header;
124 coff_header_t coff_header;
Virgile Bello89eb1ba2014-03-09 09:59:36 +0000125
Kate Stoneb9c1b512016-09-06 20:57:50 +0000126 if (ParseDOSHeader(data, dos_header)) {
127 lldb::offset_t offset = dos_header.e_lfanew;
128 uint32_t pe_signature = data.GetU32(&offset);
129 if (pe_signature != IMAGE_NT_SIGNATURE)
130 return false;
131 if (ParseCOFFHeader(data, &offset, coff_header)) {
132 ArchSpec spec;
133 if (coff_header.machine == MachineAmd64) {
134 spec.SetTriple("x86_64-pc-windows");
135 specs.Append(ModuleSpec(file, spec));
136 } else if (coff_header.machine == MachineX86) {
137 spec.SetTriple("i386-pc-windows");
138 specs.Append(ModuleSpec(file, spec));
139 spec.SetTriple("i686-pc-windows");
140 specs.Append(ModuleSpec(file, spec));
Aaron Smith037ed1b2018-12-06 21:36:39 +0000141 } else if (coff_header.machine == MachineArmNt) {
Stephane Sezer7b6e8ef2017-10-24 23:40:59 +0000142 spec.SetTriple("arm-pc-windows");
143 specs.Append(ModuleSpec(file, spec));
144 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000145 }
Virgile Bello89eb1ba2014-03-09 09:59:36 +0000146 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000147 }
Virgile Bello89eb1ba2014-03-09 09:59:36 +0000148
Kate Stoneb9c1b512016-09-06 20:57:50 +0000149 return specs.GetSize() - initial_count;
Greg Claytonf4d6de62013-04-24 22:29:28 +0000150}
151
Kate Stoneb9c1b512016-09-06 20:57:50 +0000152bool ObjectFilePECOFF::SaveCore(const lldb::ProcessSP &process_sp,
153 const lldb_private::FileSpec &outfile,
Zachary Turner97206d52017-05-12 04:51:55 +0000154 lldb_private::Status &error) {
Kate Stoneb9c1b512016-09-06 20:57:50 +0000155 return SaveMiniDump(process_sp, outfile, error);
Adrian McCarthyf7d18932015-11-20 23:09:11 +0000156}
157
Kate Stoneb9c1b512016-09-06 20:57:50 +0000158bool ObjectFilePECOFF::MagicBytesMatch(DataBufferSP &data_sp) {
159 DataExtractor data(data_sp, eByteOrderLittle, 4);
160 lldb::offset_t offset = 0;
161 uint16_t magic = data.GetU16(&offset);
162 return magic == IMAGE_DOS_SIGNATURE;
163}
Greg Claytonf4d6de62013-04-24 22:29:28 +0000164
Kate Stoneb9c1b512016-09-06 20:57:50 +0000165lldb::SymbolType ObjectFilePECOFF::MapSymbolType(uint16_t coff_symbol_type) {
166 // TODO: We need to complete this mapping of COFF symbol types to LLDB ones.
167 // For now, here's a hack to make sure our function have types.
168 const auto complex_type =
169 coff_symbol_type >> llvm::COFF::SCT_COMPLEX_TYPE_SHIFT;
170 if (complex_type == llvm::COFF::IMAGE_SYM_DTYPE_FUNCTION) {
171 return lldb::eSymbolTypeCode;
172 }
173 return lldb::eSymbolTypeInvalid;
174}
175
Aaron Smith037ed1b2018-12-06 21:36:39 +0000176bool ObjectFilePECOFF::CreateBinary() {
177 if (m_owningbin)
178 return true;
179
180 Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_OBJECT));
181
182 auto binary = llvm::object::createBinary(m_file.GetPath());
183 if (!binary) {
184 if (log)
185 log->Printf("ObjectFilePECOFF::CreateBinary() - failed to create binary "
186 "for file (%s): %s",
187 m_file ? m_file.GetPath().c_str() : "<NULL>",
188 errorToErrorCode(binary.takeError()).message().c_str());
189 return false;
190 }
191
192 // Make sure we only handle COFF format.
193 if (!binary->getBinary()->isCOFF() &&
194 !binary->getBinary()->isCOFFImportFile())
195 return false;
196
197 m_owningbin = OWNBINType(std::move(*binary));
198 if (log)
199 log->Printf("%p ObjectFilePECOFF::CreateBinary() module = %p (%s), file = "
200 "%s, binary = %p (Bin = %p)",
201 static_cast<void *>(this),
202 static_cast<void *>(GetModule().get()),
203 GetModule()->GetSpecificationDescription().c_str(),
204 m_file ? m_file.GetPath().c_str() : "<NULL>",
205 static_cast<void *>(m_owningbin.getPointer()),
206 static_cast<void *>(m_owningbin->getBinary()));
207 return true;
208}
209
Kate Stoneb9c1b512016-09-06 20:57:50 +0000210ObjectFilePECOFF::ObjectFilePECOFF(const lldb::ModuleSP &module_sp,
211 DataBufferSP &data_sp,
212 lldb::offset_t data_offset,
213 const FileSpec *file,
214 lldb::offset_t file_offset,
215 lldb::offset_t length)
216 : ObjectFile(module_sp, file, file_offset, length, data_sp, data_offset),
217 m_dos_header(), m_coff_header(), m_coff_header_opt(), m_sect_headers(),
Aaron Smith037ed1b2018-12-06 21:36:39 +0000218 m_entry_point_address(), m_deps_filespec(), m_owningbin() {
Kate Stoneb9c1b512016-09-06 20:57:50 +0000219 ::memset(&m_dos_header, 0, sizeof(m_dos_header));
220 ::memset(&m_coff_header, 0, sizeof(m_coff_header));
221 ::memset(&m_coff_header_opt, 0, sizeof(m_coff_header_opt));
222}
223
Walter Erquinigo344546b2016-10-17 20:28:19 +0000224ObjectFilePECOFF::ObjectFilePECOFF(const lldb::ModuleSP &module_sp,
225 DataBufferSP &header_data_sp,
226 const lldb::ProcessSP &process_sp,
227 addr_t header_addr)
228 : ObjectFile(module_sp, process_sp, header_addr, header_data_sp),
229 m_dos_header(), m_coff_header(), m_coff_header_opt(), m_sect_headers(),
Aaron Smith037ed1b2018-12-06 21:36:39 +0000230 m_entry_point_address(), m_deps_filespec(), m_owningbin() {
Walter Erquinigo344546b2016-10-17 20:28:19 +0000231 ::memset(&m_dos_header, 0, sizeof(m_dos_header));
232 ::memset(&m_coff_header, 0, sizeof(m_coff_header));
233 ::memset(&m_coff_header_opt, 0, sizeof(m_coff_header_opt));
234}
235
Kate Stoneb9c1b512016-09-06 20:57:50 +0000236ObjectFilePECOFF::~ObjectFilePECOFF() {}
237
238bool ObjectFilePECOFF::ParseHeader() {
239 ModuleSP module_sp(GetModule());
240 if (module_sp) {
241 std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex());
242 m_sect_headers.clear();
243 m_data.SetByteOrder(eByteOrderLittle);
Greg Claytonc7bece562013-01-25 18:06:21 +0000244 lldb::offset_t offset = 0;
Greg Claytonf754f882011-09-09 20:33:05 +0000245
Kate Stoneb9c1b512016-09-06 20:57:50 +0000246 if (ParseDOSHeader(m_data, m_dos_header)) {
247 offset = m_dos_header.e_lfanew;
248 uint32_t pe_signature = m_data.GetU32(&offset);
249 if (pe_signature != IMAGE_NT_SIGNATURE)
250 return false;
251 if (ParseCOFFHeader(m_data, &offset, m_coff_header)) {
252 if (m_coff_header.hdrsize > 0)
253 ParseCOFFOptionalHeader(&offset);
254 ParseSectionHeaders(offset);
255 }
256 return true;
Adrian McCarthyc35b91c2016-01-26 00:58:09 +0000257 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000258 }
259 return false;
Adrian McCarthyc35b91c2016-01-26 00:58:09 +0000260}
Greg Claytonf754f882011-09-09 20:33:05 +0000261
Kate Stoneb9c1b512016-09-06 20:57:50 +0000262bool ObjectFilePECOFF::SetLoadAddress(Target &target, addr_t value,
263 bool value_is_offset) {
264 bool changed = false;
265 ModuleSP module_sp = GetModule();
266 if (module_sp) {
267 size_t num_loaded_sections = 0;
268 SectionList *section_list = GetSectionList();
269 if (section_list) {
270 if (!value_is_offset) {
271 value -= m_image_base;
272 }
Greg Claytonf754f882011-09-09 20:33:05 +0000273
Kate Stoneb9c1b512016-09-06 20:57:50 +0000274 const size_t num_sections = section_list->GetSize();
275 size_t sect_idx = 0;
Greg Claytonf754f882011-09-09 20:33:05 +0000276
Kate Stoneb9c1b512016-09-06 20:57:50 +0000277 for (sect_idx = 0; sect_idx < num_sections; ++sect_idx) {
Adrian Prantl05097242018-04-30 16:49:04 +0000278 // Iterate through the object file sections to find all of the sections
279 // that have SHF_ALLOC in their flag bits.
Kate Stoneb9c1b512016-09-06 20:57:50 +0000280 SectionSP section_sp(section_list->GetSectionAtIndex(sect_idx));
281 if (section_sp && !section_sp->IsThreadSpecific()) {
282 if (target.GetSectionLoadList().SetSectionLoadAddress(
283 section_sp, section_sp->GetFileAddress() + value))
284 ++num_loaded_sections;
Greg Clayton28469ca2011-09-10 01:04:42 +0000285 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000286 }
287 changed = num_loaded_sections > 0;
Greg Claytonf754f882011-09-09 20:33:05 +0000288 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000289 }
290 return changed;
Greg Claytonf754f882011-09-09 20:33:05 +0000291}
292
Kate Stoneb9c1b512016-09-06 20:57:50 +0000293ByteOrder ObjectFilePECOFF::GetByteOrder() const { return eByteOrderLittle; }
Virgile Bello2756adf2014-03-08 17:17:20 +0000294
Kate Stoneb9c1b512016-09-06 20:57:50 +0000295bool ObjectFilePECOFF::IsExecutable() const {
296 return (m_coff_header.flags & llvm::COFF::IMAGE_FILE_DLL) == 0;
Virgile Bello2756adf2014-03-08 17:17:20 +0000297}
298
Kate Stoneb9c1b512016-09-06 20:57:50 +0000299uint32_t ObjectFilePECOFF::GetAddressByteSize() const {
300 if (m_coff_header_opt.magic == OPT_HEADER_MAGIC_PE32_PLUS)
301 return 8;
302 else if (m_coff_header_opt.magic == OPT_HEADER_MAGIC_PE32)
Greg Claytonf754f882011-09-09 20:33:05 +0000303 return 4;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000304 return 4;
Greg Claytonf754f882011-09-09 20:33:05 +0000305}
306
307//----------------------------------------------------------------------
308// NeedsEndianSwap
309//
Adrian Prantl05097242018-04-30 16:49:04 +0000310// Return true if an endian swap needs to occur when extracting data from this
311// file.
Greg Claytonf754f882011-09-09 20:33:05 +0000312//----------------------------------------------------------------------
Kate Stoneb9c1b512016-09-06 20:57:50 +0000313bool ObjectFilePECOFF::NeedsEndianSwap() const {
Greg Claytonf754f882011-09-09 20:33:05 +0000314#if defined(__LITTLE_ENDIAN__)
Kate Stoneb9c1b512016-09-06 20:57:50 +0000315 return false;
Greg Claytonf754f882011-09-09 20:33:05 +0000316#else
Kate Stoneb9c1b512016-09-06 20:57:50 +0000317 return true;
Greg Claytonf754f882011-09-09 20:33:05 +0000318#endif
319}
320//----------------------------------------------------------------------
321// ParseDOSHeader
322//----------------------------------------------------------------------
Kate Stoneb9c1b512016-09-06 20:57:50 +0000323bool ObjectFilePECOFF::ParseDOSHeader(DataExtractor &data,
324 dos_header_t &dos_header) {
325 bool success = false;
326 lldb::offset_t offset = 0;
327 success = data.ValidOffsetForDataOfSize(0, sizeof(dos_header));
Greg Claytonf754f882011-09-09 20:33:05 +0000328
Kate Stoneb9c1b512016-09-06 20:57:50 +0000329 if (success) {
330 dos_header.e_magic = data.GetU16(&offset); // Magic number
331 success = dos_header.e_magic == IMAGE_DOS_SIGNATURE;
332
333 if (success) {
334 dos_header.e_cblp = data.GetU16(&offset); // Bytes on last page of file
335 dos_header.e_cp = data.GetU16(&offset); // Pages in file
336 dos_header.e_crlc = data.GetU16(&offset); // Relocations
337 dos_header.e_cparhdr =
338 data.GetU16(&offset); // Size of header in paragraphs
339 dos_header.e_minalloc =
340 data.GetU16(&offset); // Minimum extra paragraphs needed
341 dos_header.e_maxalloc =
342 data.GetU16(&offset); // Maximum extra paragraphs needed
343 dos_header.e_ss = data.GetU16(&offset); // Initial (relative) SS value
344 dos_header.e_sp = data.GetU16(&offset); // Initial SP value
345 dos_header.e_csum = data.GetU16(&offset); // Checksum
346 dos_header.e_ip = data.GetU16(&offset); // Initial IP value
347 dos_header.e_cs = data.GetU16(&offset); // Initial (relative) CS value
348 dos_header.e_lfarlc =
349 data.GetU16(&offset); // File address of relocation table
350 dos_header.e_ovno = data.GetU16(&offset); // Overlay number
351
352 dos_header.e_res[0] = data.GetU16(&offset); // Reserved words
353 dos_header.e_res[1] = data.GetU16(&offset); // Reserved words
354 dos_header.e_res[2] = data.GetU16(&offset); // Reserved words
355 dos_header.e_res[3] = data.GetU16(&offset); // Reserved words
356
357 dos_header.e_oemid =
358 data.GetU16(&offset); // OEM identifier (for e_oeminfo)
359 dos_header.e_oeminfo =
360 data.GetU16(&offset); // OEM information; e_oemid specific
361 dos_header.e_res2[0] = data.GetU16(&offset); // Reserved words
362 dos_header.e_res2[1] = data.GetU16(&offset); // Reserved words
363 dos_header.e_res2[2] = data.GetU16(&offset); // Reserved words
364 dos_header.e_res2[3] = data.GetU16(&offset); // Reserved words
365 dos_header.e_res2[4] = data.GetU16(&offset); // Reserved words
366 dos_header.e_res2[5] = data.GetU16(&offset); // Reserved words
367 dos_header.e_res2[6] = data.GetU16(&offset); // Reserved words
368 dos_header.e_res2[7] = data.GetU16(&offset); // Reserved words
369 dos_header.e_res2[8] = data.GetU16(&offset); // Reserved words
370 dos_header.e_res2[9] = data.GetU16(&offset); // Reserved words
371
372 dos_header.e_lfanew =
373 data.GetU32(&offset); // File address of new exe header
374 }
375 }
376 if (!success)
377 memset(&dos_header, 0, sizeof(dos_header));
378 return success;
379}
Greg Claytonf754f882011-09-09 20:33:05 +0000380
381//----------------------------------------------------------------------
382// ParserCOFFHeader
383//----------------------------------------------------------------------
Kate Stoneb9c1b512016-09-06 20:57:50 +0000384bool ObjectFilePECOFF::ParseCOFFHeader(DataExtractor &data,
385 lldb::offset_t *offset_ptr,
386 coff_header_t &coff_header) {
387 bool success =
388 data.ValidOffsetForDataOfSize(*offset_ptr, sizeof(coff_header));
389 if (success) {
390 coff_header.machine = data.GetU16(offset_ptr);
391 coff_header.nsects = data.GetU16(offset_ptr);
392 coff_header.modtime = data.GetU32(offset_ptr);
393 coff_header.symoff = data.GetU32(offset_ptr);
394 coff_header.nsyms = data.GetU32(offset_ptr);
395 coff_header.hdrsize = data.GetU16(offset_ptr);
396 coff_header.flags = data.GetU16(offset_ptr);
397 }
398 if (!success)
399 memset(&coff_header, 0, sizeof(coff_header));
400 return success;
Greg Claytonf754f882011-09-09 20:33:05 +0000401}
402
Kate Stoneb9c1b512016-09-06 20:57:50 +0000403bool ObjectFilePECOFF::ParseCOFFOptionalHeader(lldb::offset_t *offset_ptr) {
404 bool success = false;
405 const lldb::offset_t end_offset = *offset_ptr + m_coff_header.hdrsize;
406 if (*offset_ptr < end_offset) {
407 success = true;
408 m_coff_header_opt.magic = m_data.GetU16(offset_ptr);
409 m_coff_header_opt.major_linker_version = m_data.GetU8(offset_ptr);
410 m_coff_header_opt.minor_linker_version = m_data.GetU8(offset_ptr);
411 m_coff_header_opt.code_size = m_data.GetU32(offset_ptr);
412 m_coff_header_opt.data_size = m_data.GetU32(offset_ptr);
413 m_coff_header_opt.bss_size = m_data.GetU32(offset_ptr);
414 m_coff_header_opt.entry = m_data.GetU32(offset_ptr);
415 m_coff_header_opt.code_offset = m_data.GetU32(offset_ptr);
Greg Claytonf754f882011-09-09 20:33:05 +0000416
Kate Stoneb9c1b512016-09-06 20:57:50 +0000417 const uint32_t addr_byte_size = GetAddressByteSize();
Greg Claytonf754f882011-09-09 20:33:05 +0000418
Kate Stoneb9c1b512016-09-06 20:57:50 +0000419 if (*offset_ptr < end_offset) {
420 if (m_coff_header_opt.magic == OPT_HEADER_MAGIC_PE32) {
421 // PE32 only
422 m_coff_header_opt.data_offset = m_data.GetU32(offset_ptr);
423 } else
424 m_coff_header_opt.data_offset = 0;
Virgile Bello2756adf2014-03-08 17:17:20 +0000425
Kate Stoneb9c1b512016-09-06 20:57:50 +0000426 if (*offset_ptr < end_offset) {
427 m_coff_header_opt.image_base =
428 m_data.GetMaxU64(offset_ptr, addr_byte_size);
429 m_coff_header_opt.sect_alignment = m_data.GetU32(offset_ptr);
430 m_coff_header_opt.file_alignment = m_data.GetU32(offset_ptr);
431 m_coff_header_opt.major_os_system_version = m_data.GetU16(offset_ptr);
432 m_coff_header_opt.minor_os_system_version = m_data.GetU16(offset_ptr);
433 m_coff_header_opt.major_image_version = m_data.GetU16(offset_ptr);
434 m_coff_header_opt.minor_image_version = m_data.GetU16(offset_ptr);
435 m_coff_header_opt.major_subsystem_version = m_data.GetU16(offset_ptr);
436 m_coff_header_opt.minor_subsystem_version = m_data.GetU16(offset_ptr);
437 m_coff_header_opt.reserved1 = m_data.GetU32(offset_ptr);
438 m_coff_header_opt.image_size = m_data.GetU32(offset_ptr);
439 m_coff_header_opt.header_size = m_data.GetU32(offset_ptr);
440 m_coff_header_opt.checksum = m_data.GetU32(offset_ptr);
441 m_coff_header_opt.subsystem = m_data.GetU16(offset_ptr);
442 m_coff_header_opt.dll_flags = m_data.GetU16(offset_ptr);
443 m_coff_header_opt.stack_reserve_size =
444 m_data.GetMaxU64(offset_ptr, addr_byte_size);
445 m_coff_header_opt.stack_commit_size =
446 m_data.GetMaxU64(offset_ptr, addr_byte_size);
447 m_coff_header_opt.heap_reserve_size =
448 m_data.GetMaxU64(offset_ptr, addr_byte_size);
449 m_coff_header_opt.heap_commit_size =
450 m_data.GetMaxU64(offset_ptr, addr_byte_size);
451 m_coff_header_opt.loader_flags = m_data.GetU32(offset_ptr);
452 uint32_t num_data_dir_entries = m_data.GetU32(offset_ptr);
453 m_coff_header_opt.data_dirs.clear();
454 m_coff_header_opt.data_dirs.resize(num_data_dir_entries);
455 uint32_t i;
456 for (i = 0; i < num_data_dir_entries; i++) {
457 m_coff_header_opt.data_dirs[i].vmaddr = m_data.GetU32(offset_ptr);
458 m_coff_header_opt.data_dirs[i].vmsize = m_data.GetU32(offset_ptr);
Greg Claytonf754f882011-09-09 20:33:05 +0000459 }
Greg Claytonf754f882011-09-09 20:33:05 +0000460
Kate Stoneb9c1b512016-09-06 20:57:50 +0000461 m_file_offset = m_coff_header_opt.image_base;
462 m_image_base = m_coff_header_opt.image_base;
463 }
464 }
465 }
466 // Make sure we are on track for section data which follows
467 *offset_ptr = end_offset;
468 return success;
469}
Greg Claytonf754f882011-09-09 20:33:05 +0000470
Walter Erquinigo344546b2016-10-17 20:28:19 +0000471DataExtractor ObjectFilePECOFF::ReadImageData(uint32_t offset, size_t size) {
472 if (m_file) {
Aaron Smith037ed1b2018-12-06 21:36:39 +0000473 // A bit of a hack, but we intend to write to this buffer, so we can't
Zachary Turner7f6a7a32017-03-06 23:42:14 +0000474 // mmap it.
Pavel Labath50251fc2017-12-21 10:54:30 +0000475 auto buffer_sp = MapFileData(m_file, size, offset);
Walter Erquinigo344546b2016-10-17 20:28:19 +0000476 return DataExtractor(buffer_sp, GetByteOrder(), GetAddressByteSize());
477 }
478 ProcessSP process_sp(m_process_wp.lock());
479 DataExtractor data;
480 if (process_sp) {
481 auto data_ap = llvm::make_unique<DataBufferHeap>(size, 0);
Zachary Turner97206d52017-05-12 04:51:55 +0000482 Status readmem_error;
Walter Erquinigo344546b2016-10-17 20:28:19 +0000483 size_t bytes_read =
484 process_sp->ReadMemory(m_image_base + offset, data_ap->GetBytes(),
485 data_ap->GetByteSize(), readmem_error);
486 if (bytes_read == size) {
487 DataBufferSP buffer_sp(data_ap.release());
488 data.SetData(buffer_sp, 0, buffer_sp->GetByteSize());
489 }
490 }
491 return data;
492}
493
Greg Claytonf754f882011-09-09 20:33:05 +0000494//----------------------------------------------------------------------
495// ParseSectionHeaders
496//----------------------------------------------------------------------
Kate Stoneb9c1b512016-09-06 20:57:50 +0000497bool ObjectFilePECOFF::ParseSectionHeaders(
498 uint32_t section_header_data_offset) {
499 const uint32_t nsects = m_coff_header.nsects;
500 m_sect_headers.clear();
Greg Claytonf754f882011-09-09 20:33:05 +0000501
Kate Stoneb9c1b512016-09-06 20:57:50 +0000502 if (nsects > 0) {
Kate Stoneb9c1b512016-09-06 20:57:50 +0000503 const size_t section_header_byte_size = nsects * sizeof(section_header_t);
Walter Erquinigo344546b2016-10-17 20:28:19 +0000504 DataExtractor section_header_data =
505 ReadImageData(section_header_data_offset, section_header_byte_size);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000506
507 lldb::offset_t offset = 0;
508 if (section_header_data.ValidOffsetForDataOfSize(
509 offset, section_header_byte_size)) {
510 m_sect_headers.resize(nsects);
511
512 for (uint32_t idx = 0; idx < nsects; ++idx) {
513 const void *name_data = section_header_data.GetData(&offset, 8);
514 if (name_data) {
515 memcpy(m_sect_headers[idx].name, name_data, 8);
516 m_sect_headers[idx].vmsize = section_header_data.GetU32(&offset);
517 m_sect_headers[idx].vmaddr = section_header_data.GetU32(&offset);
518 m_sect_headers[idx].size = section_header_data.GetU32(&offset);
519 m_sect_headers[idx].offset = section_header_data.GetU32(&offset);
520 m_sect_headers[idx].reloff = section_header_data.GetU32(&offset);
521 m_sect_headers[idx].lineoff = section_header_data.GetU32(&offset);
522 m_sect_headers[idx].nreloc = section_header_data.GetU16(&offset);
523 m_sect_headers[idx].nline = section_header_data.GetU16(&offset);
524 m_sect_headers[idx].flags = section_header_data.GetU32(&offset);
Greg Claytonf754f882011-09-09 20:33:05 +0000525 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000526 }
Greg Claytonf754f882011-09-09 20:33:05 +0000527 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000528 }
529
530 return m_sect_headers.empty() == false;
Greg Claytonf754f882011-09-09 20:33:05 +0000531}
532
Kate Stoneb9c1b512016-09-06 20:57:50 +0000533bool ObjectFilePECOFF::GetSectionName(std::string &sect_name,
534 const section_header_t &sect) {
535 if (sect.name[0] == '/') {
536 lldb::offset_t stroff = strtoul(&sect.name[1], NULL, 10);
537 lldb::offset_t string_file_offset =
538 m_coff_header.symoff + (m_coff_header.nsyms * 18) + stroff;
539 const char *name = m_data.GetCStr(&string_file_offset);
540 if (name) {
541 sect_name = name;
542 return true;
Greg Claytonf754f882011-09-09 20:33:05 +0000543 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000544
545 return false;
546 }
547 sect_name = sect.name;
548 return true;
549}
Greg Claytonf754f882011-09-09 20:33:05 +0000550
551//----------------------------------------------------------------------
552// GetNListSymtab
553//----------------------------------------------------------------------
Kate Stoneb9c1b512016-09-06 20:57:50 +0000554Symtab *ObjectFilePECOFF::GetSymtab() {
555 ModuleSP module_sp(GetModule());
556 if (module_sp) {
557 std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex());
558 if (m_symtab_ap.get() == NULL) {
559 SectionList *sect_list = GetSectionList();
560 m_symtab_ap.reset(new Symtab(this));
561 std::lock_guard<std::recursive_mutex> guard(m_symtab_ap->GetMutex());
562
563 const uint32_t num_syms = m_coff_header.nsyms;
564
Walter Erquinigo344546b2016-10-17 20:28:19 +0000565 if (m_file && num_syms > 0 && m_coff_header.symoff > 0) {
Kate Stoneb9c1b512016-09-06 20:57:50 +0000566 const uint32_t symbol_size = 18;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000567 const size_t symbol_data_size = num_syms * symbol_size;
568 // Include the 4-byte string table size at the end of the symbols
Walter Erquinigo344546b2016-10-17 20:28:19 +0000569 DataExtractor symtab_data =
570 ReadImageData(m_coff_header.symoff, symbol_data_size + 4);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000571 lldb::offset_t offset = symbol_data_size;
572 const uint32_t strtab_size = symtab_data.GetU32(&offset);
Walter Erquinigo344546b2016-10-17 20:28:19 +0000573 if (strtab_size > 0) {
574 DataExtractor strtab_data = ReadImageData(
575 m_coff_header.symoff + symbol_data_size, strtab_size);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000576
Walter Erquinigo344546b2016-10-17 20:28:19 +0000577 // First 4 bytes should be zeroed after strtab_size has been read,
578 // because it is used as offset 0 to encode a NULL string.
Saleem Abdulrasoolf76e0992017-07-19 15:46:21 +0000579 uint32_t *strtab_data_start = const_cast<uint32_t *>(
580 reinterpret_cast<const uint32_t *>(strtab_data.GetDataStart()));
Walter Erquinigo344546b2016-10-17 20:28:19 +0000581 strtab_data_start[0] = 0;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000582
Walter Erquinigo344546b2016-10-17 20:28:19 +0000583 offset = 0;
584 std::string symbol_name;
585 Symbol *symbols = m_symtab_ap->Resize(num_syms);
586 for (uint32_t i = 0; i < num_syms; ++i) {
587 coff_symbol_t symbol;
588 const uint32_t symbol_offset = offset;
589 const char *symbol_name_cstr = NULL;
590 // If the first 4 bytes of the symbol string are zero, then they
591 // are followed by a 4-byte string table offset. Else these
592 // 8 bytes contain the symbol name
593 if (symtab_data.GetU32(&offset) == 0) {
Adrian Prantl05097242018-04-30 16:49:04 +0000594 // Long string that doesn't fit into the symbol table name, so
595 // now we must read the 4 byte string table offset
Walter Erquinigo344546b2016-10-17 20:28:19 +0000596 uint32_t strtab_offset = symtab_data.GetU32(&offset);
597 symbol_name_cstr = strtab_data.PeekCStr(strtab_offset);
598 symbol_name.assign(symbol_name_cstr);
599 } else {
600 // Short string that fits into the symbol table name which is 8
601 // bytes
602 offset += sizeof(symbol.name) - 4; // Skip remaining
603 symbol_name_cstr = symtab_data.PeekCStr(symbol_offset);
604 if (symbol_name_cstr == NULL)
605 break;
606 symbol_name.assign(symbol_name_cstr, sizeof(symbol.name));
607 }
608 symbol.value = symtab_data.GetU32(&offset);
609 symbol.sect = symtab_data.GetU16(&offset);
610 symbol.type = symtab_data.GetU16(&offset);
611 symbol.storage = symtab_data.GetU8(&offset);
612 symbol.naux = symtab_data.GetU8(&offset);
613 symbols[i].GetMangled().SetValue(ConstString(symbol_name.c_str()));
614 if ((int16_t)symbol.sect >= 1) {
615 Address symbol_addr(sect_list->GetSectionAtIndex(symbol.sect - 1),
616 symbol.value);
617 symbols[i].GetAddressRef() = symbol_addr;
618 symbols[i].SetType(MapSymbolType(symbol.type));
619 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000620
Walter Erquinigo344546b2016-10-17 20:28:19 +0000621 if (symbol.naux > 0) {
622 i += symbol.naux;
623 offset += symbol_size;
624 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000625 }
626 }
627 }
628
629 // Read export header
630 if (coff_data_dir_export_table < m_coff_header_opt.data_dirs.size() &&
631 m_coff_header_opt.data_dirs[coff_data_dir_export_table].vmsize > 0 &&
632 m_coff_header_opt.data_dirs[coff_data_dir_export_table].vmaddr > 0) {
633 export_directory_entry export_table;
634 uint32_t data_start =
635 m_coff_header_opt.data_dirs[coff_data_dir_export_table].vmaddr;
Walter Erquinigo344546b2016-10-17 20:28:19 +0000636
637 uint32_t address_rva = data_start;
638 if (m_file) {
639 Address address(m_coff_header_opt.image_base + data_start, sect_list);
640 address_rva =
641 address.GetSection()->GetFileOffset() + address.GetOffset();
642 }
643 DataExtractor symtab_data =
644 ReadImageData(address_rva, m_coff_header_opt.data_dirs[0].vmsize);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000645 lldb::offset_t offset = 0;
646
647 // Read export_table header
648 export_table.characteristics = symtab_data.GetU32(&offset);
649 export_table.time_date_stamp = symtab_data.GetU32(&offset);
650 export_table.major_version = symtab_data.GetU16(&offset);
651 export_table.minor_version = symtab_data.GetU16(&offset);
652 export_table.name = symtab_data.GetU32(&offset);
653 export_table.base = symtab_data.GetU32(&offset);
654 export_table.number_of_functions = symtab_data.GetU32(&offset);
655 export_table.number_of_names = symtab_data.GetU32(&offset);
656 export_table.address_of_functions = symtab_data.GetU32(&offset);
657 export_table.address_of_names = symtab_data.GetU32(&offset);
658 export_table.address_of_name_ordinals = symtab_data.GetU32(&offset);
659
660 bool has_ordinal = export_table.address_of_name_ordinals != 0;
661
662 lldb::offset_t name_offset = export_table.address_of_names - data_start;
663 lldb::offset_t name_ordinal_offset =
664 export_table.address_of_name_ordinals - data_start;
665
666 Symbol *symbols = m_symtab_ap->Resize(export_table.number_of_names);
667
668 std::string symbol_name;
669
670 // Read each export table entry
671 for (size_t i = 0; i < export_table.number_of_names; ++i) {
672 uint32_t name_ordinal =
673 has_ordinal ? symtab_data.GetU16(&name_ordinal_offset) : i;
674 uint32_t name_address = symtab_data.GetU32(&name_offset);
675
676 const char *symbol_name_cstr =
677 symtab_data.PeekCStr(name_address - data_start);
678 symbol_name.assign(symbol_name_cstr);
679
680 lldb::offset_t function_offset = export_table.address_of_functions -
681 data_start +
682 sizeof(uint32_t) * name_ordinal;
683 uint32_t function_rva = symtab_data.GetU32(&function_offset);
684
685 Address symbol_addr(m_coff_header_opt.image_base + function_rva,
686 sect_list);
687 symbols[i].GetMangled().SetValue(ConstString(symbol_name.c_str()));
688 symbols[i].GetAddressRef() = symbol_addr;
689 symbols[i].SetType(lldb::eSymbolTypeCode);
690 symbols[i].SetDebug(true);
691 }
692 }
Davide Italiano407c6912018-11-02 21:59:14 +0000693 m_symtab_ap->CalculateSymbolSizes();
Kate Stoneb9c1b512016-09-06 20:57:50 +0000694 }
695 }
696 return m_symtab_ap.get();
697}
698
699bool ObjectFilePECOFF::IsStripped() {
700 // TODO: determine this for COFF
701 return false;
702}
703
704void ObjectFilePECOFF::CreateSections(SectionList &unified_section_list) {
705 if (!m_sections_ap.get()) {
706 m_sections_ap.reset(new SectionList());
707
Greg Claytona1743492012-03-13 23:14:29 +0000708 ModuleSP module_sp(GetModule());
Kate Stoneb9c1b512016-09-06 20:57:50 +0000709 if (module_sp) {
710 std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex());
711 const uint32_t nsects = m_sect_headers.size();
712 ModuleSP module_sp(GetModule());
713 for (uint32_t idx = 0; idx < nsects; ++idx) {
714 std::string sect_name;
715 GetSectionName(sect_name, m_sect_headers[idx]);
716 ConstString const_sect_name(sect_name.c_str());
717 static ConstString g_code_sect_name(".code");
718 static ConstString g_CODE_sect_name("CODE");
719 static ConstString g_data_sect_name(".data");
720 static ConstString g_DATA_sect_name("DATA");
721 static ConstString g_bss_sect_name(".bss");
722 static ConstString g_BSS_sect_name("BSS");
723 static ConstString g_debug_sect_name(".debug");
724 static ConstString g_reloc_sect_name(".reloc");
725 static ConstString g_stab_sect_name(".stab");
726 static ConstString g_stabstr_sect_name(".stabstr");
727 static ConstString g_sect_name_dwarf_debug_abbrev(".debug_abbrev");
728 static ConstString g_sect_name_dwarf_debug_aranges(".debug_aranges");
729 static ConstString g_sect_name_dwarf_debug_frame(".debug_frame");
730 static ConstString g_sect_name_dwarf_debug_info(".debug_info");
731 static ConstString g_sect_name_dwarf_debug_line(".debug_line");
732 static ConstString g_sect_name_dwarf_debug_loc(".debug_loc");
George Rimare4dee262018-10-23 09:46:15 +0000733 static ConstString g_sect_name_dwarf_debug_loclists(".debug_loclists");
Kate Stoneb9c1b512016-09-06 20:57:50 +0000734 static ConstString g_sect_name_dwarf_debug_macinfo(".debug_macinfo");
Pavel Labatha041d842018-06-01 12:06:45 +0000735 static ConstString g_sect_name_dwarf_debug_names(".debug_names");
Kate Stoneb9c1b512016-09-06 20:57:50 +0000736 static ConstString g_sect_name_dwarf_debug_pubnames(".debug_pubnames");
737 static ConstString g_sect_name_dwarf_debug_pubtypes(".debug_pubtypes");
738 static ConstString g_sect_name_dwarf_debug_ranges(".debug_ranges");
739 static ConstString g_sect_name_dwarf_debug_str(".debug_str");
Greg Clayton2550ca12018-05-08 17:19:24 +0000740 static ConstString g_sect_name_dwarf_debug_types(".debug_types");
Kate Stoneb9c1b512016-09-06 20:57:50 +0000741 static ConstString g_sect_name_eh_frame(".eh_frame");
742 static ConstString g_sect_name_go_symtab(".gosymtab");
743 SectionType section_type = eSectionTypeOther;
744 if (m_sect_headers[idx].flags & llvm::COFF::IMAGE_SCN_CNT_CODE &&
745 ((const_sect_name == g_code_sect_name) ||
746 (const_sect_name == g_CODE_sect_name))) {
747 section_type = eSectionTypeCode;
748 } else if (m_sect_headers[idx].flags &
749 llvm::COFF::IMAGE_SCN_CNT_INITIALIZED_DATA &&
750 ((const_sect_name == g_data_sect_name) ||
751 (const_sect_name == g_DATA_sect_name))) {
Zachary Turner9cad24a2018-11-09 16:06:44 +0000752 if (m_sect_headers[idx].size == 0 && m_sect_headers[idx].offset == 0)
753 section_type = eSectionTypeZeroFill;
754 else
755 section_type = eSectionTypeData;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000756 } else if (m_sect_headers[idx].flags &
757 llvm::COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA &&
758 ((const_sect_name == g_bss_sect_name) ||
759 (const_sect_name == g_BSS_sect_name))) {
760 if (m_sect_headers[idx].size == 0)
761 section_type = eSectionTypeZeroFill;
762 else
763 section_type = eSectionTypeData;
764 } else if (const_sect_name == g_debug_sect_name) {
765 section_type = eSectionTypeDebug;
766 } else if (const_sect_name == g_stabstr_sect_name) {
767 section_type = eSectionTypeDataCString;
768 } else if (const_sect_name == g_reloc_sect_name) {
769 section_type = eSectionTypeOther;
770 } else if (const_sect_name == g_sect_name_dwarf_debug_abbrev)
771 section_type = eSectionTypeDWARFDebugAbbrev;
772 else if (const_sect_name == g_sect_name_dwarf_debug_aranges)
773 section_type = eSectionTypeDWARFDebugAranges;
774 else if (const_sect_name == g_sect_name_dwarf_debug_frame)
775 section_type = eSectionTypeDWARFDebugFrame;
776 else if (const_sect_name == g_sect_name_dwarf_debug_info)
777 section_type = eSectionTypeDWARFDebugInfo;
778 else if (const_sect_name == g_sect_name_dwarf_debug_line)
779 section_type = eSectionTypeDWARFDebugLine;
780 else if (const_sect_name == g_sect_name_dwarf_debug_loc)
781 section_type = eSectionTypeDWARFDebugLoc;
George Rimare4dee262018-10-23 09:46:15 +0000782 else if (const_sect_name == g_sect_name_dwarf_debug_loclists)
783 section_type = eSectionTypeDWARFDebugLocLists;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000784 else if (const_sect_name == g_sect_name_dwarf_debug_macinfo)
785 section_type = eSectionTypeDWARFDebugMacInfo;
Pavel Labatha041d842018-06-01 12:06:45 +0000786 else if (const_sect_name == g_sect_name_dwarf_debug_names)
787 section_type = eSectionTypeDWARFDebugNames;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000788 else if (const_sect_name == g_sect_name_dwarf_debug_pubnames)
789 section_type = eSectionTypeDWARFDebugPubNames;
790 else if (const_sect_name == g_sect_name_dwarf_debug_pubtypes)
791 section_type = eSectionTypeDWARFDebugPubTypes;
792 else if (const_sect_name == g_sect_name_dwarf_debug_ranges)
793 section_type = eSectionTypeDWARFDebugRanges;
794 else if (const_sect_name == g_sect_name_dwarf_debug_str)
795 section_type = eSectionTypeDWARFDebugStr;
Greg Clayton2550ca12018-05-08 17:19:24 +0000796 else if (const_sect_name == g_sect_name_dwarf_debug_types)
797 section_type = eSectionTypeDWARFDebugTypes;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000798 else if (const_sect_name == g_sect_name_eh_frame)
799 section_type = eSectionTypeEHFrame;
800 else if (const_sect_name == g_sect_name_go_symtab)
801 section_type = eSectionTypeGoSymtab;
802 else if (m_sect_headers[idx].flags & llvm::COFF::IMAGE_SCN_CNT_CODE) {
803 section_type = eSectionTypeCode;
804 } else if (m_sect_headers[idx].flags &
805 llvm::COFF::IMAGE_SCN_CNT_INITIALIZED_DATA) {
806 section_type = eSectionTypeData;
807 } else if (m_sect_headers[idx].flags &
808 llvm::COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA) {
809 if (m_sect_headers[idx].size == 0)
810 section_type = eSectionTypeZeroFill;
811 else
812 section_type = eSectionTypeData;
Greg Claytonf754f882011-09-09 20:33:05 +0000813 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000814
815 // Use a segment ID of the segment index shifted left by 8 so they
816 // never conflict with any of the sections.
817 SectionSP section_sp(new Section(
818 module_sp, // Module to which this section belongs
819 this, // Object file to which this section belongs
820 idx + 1, // Section ID is the 1 based segment index shifted right by
821 // 8 bits as not to collide with any of the 256 section IDs
822 // that are possible
823 const_sect_name, // Name of this section
824 section_type, // This section is a container of other sections.
825 m_coff_header_opt.image_base +
826 m_sect_headers[idx].vmaddr, // File VM address == addresses as
827 // they are found in the object file
828 m_sect_headers[idx].vmsize, // VM size in bytes of this section
829 m_sect_headers[idx]
830 .offset, // Offset to the data for this section in the file
831 m_sect_headers[idx]
832 .size, // Size in bytes of this section as found in the file
833 m_coff_header_opt.sect_alignment, // Section alignment
834 m_sect_headers[idx].flags)); // Flags for this section
835
836 // section_sp->SetIsEncrypted (segment_is_encrypted);
837
838 unified_section_list.AddSection(section_sp);
839 m_sections_ap->AddSection(section_sp);
840 }
Greg Claytonf754f882011-09-09 20:33:05 +0000841 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000842 }
Greg Claytonf754f882011-09-09 20:33:05 +0000843}
844
Kate Stoneb9c1b512016-09-06 20:57:50 +0000845bool ObjectFilePECOFF::GetUUID(UUID *uuid) { return false; }
846
Aaron Smith037ed1b2018-12-06 21:36:39 +0000847uint32_t ObjectFilePECOFF::ParseDependentModules() {
848 ModuleSP module_sp(GetModule());
849 if (!module_sp)
850 return 0;
851
852 std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex());
853 if (m_deps_filespec)
854 return m_deps_filespec->GetSize();
855
856 // Cache coff binary if it is not done yet.
857 if (!CreateBinary())
858 return 0;
859
860 Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_OBJECT));
861 if (log)
862 log->Printf("%p ObjectFilePECOFF::ParseDependentModules() module = %p "
863 "(%s), binary = %p (Bin = %p)",
864 static_cast<void *>(this), static_cast<void *>(module_sp.get()),
865 module_sp->GetSpecificationDescription().c_str(),
866 static_cast<void *>(m_owningbin.getPointer()),
867 m_owningbin ? static_cast<void *>(m_owningbin->getBinary())
868 : nullptr);
869
870 auto COFFObj =
871 llvm::dyn_cast<llvm::object::COFFObjectFile>(m_owningbin->getBinary());
872 if (!COFFObj)
873 return 0;
874
875 m_deps_filespec = FileSpecList();
876
877 for (const auto &entry : COFFObj->import_directories()) {
878 llvm::StringRef dll_name;
879 auto ec = entry.getName(dll_name);
880 // Report a bogus entry.
881 if (ec != std::error_code()) {
882 if (log)
883 log->Printf("ObjectFilePECOFF::ParseDependentModules() - failed to get "
884 "import directory entry name: %s",
885 ec.message().c_str());
886 continue;
887 }
888
889 // At this moment we only have the base name of the DLL. The full path can
890 // only be seen after the dynamic loading. Our best guess is Try to get it
891 // with the help of the object file's directory.
Stella Stamenovab3f44ad2018-12-10 17:23:28 +0000892 llvm::SmallString<128> dll_fullpath;
Aaron Smith037ed1b2018-12-06 21:36:39 +0000893 FileSpec dll_specs(dll_name);
894 dll_specs.GetDirectory().SetString(m_file.GetDirectory().GetCString());
895
896 if (!llvm::sys::fs::real_path(dll_specs.GetPath(), dll_fullpath))
897 m_deps_filespec->Append(FileSpec(dll_fullpath));
898 else {
899 // Known DLLs or DLL not found in the object file directory.
900 m_deps_filespec->Append(FileSpec(dll_name));
901 }
902 }
903 return m_deps_filespec->GetSize();
904}
905
Kate Stoneb9c1b512016-09-06 20:57:50 +0000906uint32_t ObjectFilePECOFF::GetDependentModules(FileSpecList &files) {
Aaron Smith037ed1b2018-12-06 21:36:39 +0000907 auto num_modules = ParseDependentModules();
908 auto original_size = files.GetSize();
909
910 for (unsigned i = 0; i < num_modules; ++i)
911 files.AppendIfUnique(m_deps_filespec->GetFileSpecAtIndex(i));
912
913 return files.GetSize() - original_size;
Greg Clayton3046e662013-07-10 01:23:25 +0000914}
915
Kate Stoneb9c1b512016-09-06 20:57:50 +0000916lldb_private::Address ObjectFilePECOFF::GetEntryPointAddress() {
917 if (m_entry_point_address.IsValid())
Stephane Sezer8e38c662016-03-23 18:00:13 +0000918 return m_entry_point_address;
Stephane Sezer8e38c662016-03-23 18:00:13 +0000919
Kate Stoneb9c1b512016-09-06 20:57:50 +0000920 if (!ParseHeader() || !IsExecutable())
921 return m_entry_point_address;
922
923 SectionList *section_list = GetSectionList();
Aleksandr Urakova5235af2018-12-03 13:31:13 +0000924 addr_t file_addr = m_coff_header_opt.entry + m_coff_header_opt.image_base;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000925
926 if (!section_list)
Aleksandr Urakova5235af2018-12-03 13:31:13 +0000927 m_entry_point_address.SetOffset(file_addr);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000928 else
Aleksandr Urakova5235af2018-12-03 13:31:13 +0000929 m_entry_point_address.ResolveAddressUsingFileSections(file_addr, section_list);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000930 return m_entry_point_address;
931}
Greg Claytonf754f882011-09-09 20:33:05 +0000932
933//----------------------------------------------------------------------
934// Dump
935//
936// Dump the specifics of the runtime file container (such as any headers
937// segments, sections, etc).
938//----------------------------------------------------------------------
Kate Stoneb9c1b512016-09-06 20:57:50 +0000939void ObjectFilePECOFF::Dump(Stream *s) {
940 ModuleSP module_sp(GetModule());
941 if (module_sp) {
942 std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex());
943 s->Printf("%p: ", static_cast<void *>(this));
944 s->Indent();
945 s->PutCString("ObjectFilePECOFF");
Saleem Abdulrasool324a1032014-04-04 04:06:10 +0000946
Kate Stoneb9c1b512016-09-06 20:57:50 +0000947 ArchSpec header_arch;
948 GetArchitecture(header_arch);
Saleem Abdulrasool324a1032014-04-04 04:06:10 +0000949
Kate Stoneb9c1b512016-09-06 20:57:50 +0000950 *s << ", file = '" << m_file
951 << "', arch = " << header_arch.GetArchitectureName() << "\n";
Saleem Abdulrasool324a1032014-04-04 04:06:10 +0000952
Kate Stoneb9c1b512016-09-06 20:57:50 +0000953 SectionList *sections = GetSectionList();
954 if (sections)
955 sections->Dump(s, NULL, true, UINT32_MAX);
Saleem Abdulrasool324a1032014-04-04 04:06:10 +0000956
Kate Stoneb9c1b512016-09-06 20:57:50 +0000957 if (m_symtab_ap.get())
958 m_symtab_ap->Dump(s, NULL, eSortOrderNone);
Greg Claytona1743492012-03-13 23:14:29 +0000959
Kate Stoneb9c1b512016-09-06 20:57:50 +0000960 if (m_dos_header.e_magic)
961 DumpDOSHeader(s, m_dos_header);
962 if (m_coff_header.machine) {
963 DumpCOFFHeader(s, m_coff_header);
964 if (m_coff_header.hdrsize)
965 DumpOptCOFFHeader(s, m_coff_header_opt);
Greg Claytonf754f882011-09-09 20:33:05 +0000966 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000967 s->EOL();
968 DumpSectionHeaders(s);
969 s->EOL();
Aaron Smith037ed1b2018-12-06 21:36:39 +0000970
971 DumpDependentModules(s);
972 s->EOL();
Kate Stoneb9c1b512016-09-06 20:57:50 +0000973 }
Greg Claytonf754f882011-09-09 20:33:05 +0000974}
975
976//----------------------------------------------------------------------
977// DumpDOSHeader
978//
979// Dump the MS-DOS header to the specified output stream
980//----------------------------------------------------------------------
Kate Stoneb9c1b512016-09-06 20:57:50 +0000981void ObjectFilePECOFF::DumpDOSHeader(Stream *s, const dos_header_t &header) {
982 s->PutCString("MSDOS Header\n");
983 s->Printf(" e_magic = 0x%4.4x\n", header.e_magic);
984 s->Printf(" e_cblp = 0x%4.4x\n", header.e_cblp);
985 s->Printf(" e_cp = 0x%4.4x\n", header.e_cp);
986 s->Printf(" e_crlc = 0x%4.4x\n", header.e_crlc);
987 s->Printf(" e_cparhdr = 0x%4.4x\n", header.e_cparhdr);
988 s->Printf(" e_minalloc = 0x%4.4x\n", header.e_minalloc);
989 s->Printf(" e_maxalloc = 0x%4.4x\n", header.e_maxalloc);
990 s->Printf(" e_ss = 0x%4.4x\n", header.e_ss);
991 s->Printf(" e_sp = 0x%4.4x\n", header.e_sp);
992 s->Printf(" e_csum = 0x%4.4x\n", header.e_csum);
993 s->Printf(" e_ip = 0x%4.4x\n", header.e_ip);
994 s->Printf(" e_cs = 0x%4.4x\n", header.e_cs);
995 s->Printf(" e_lfarlc = 0x%4.4x\n", header.e_lfarlc);
996 s->Printf(" e_ovno = 0x%4.4x\n", header.e_ovno);
997 s->Printf(" e_res[4] = { 0x%4.4x, 0x%4.4x, 0x%4.4x, 0x%4.4x }\n",
998 header.e_res[0], header.e_res[1], header.e_res[2], header.e_res[3]);
999 s->Printf(" e_oemid = 0x%4.4x\n", header.e_oemid);
1000 s->Printf(" e_oeminfo = 0x%4.4x\n", header.e_oeminfo);
1001 s->Printf(" e_res2[10] = { 0x%4.4x, 0x%4.4x, 0x%4.4x, 0x%4.4x, 0x%4.4x, "
1002 "0x%4.4x, 0x%4.4x, 0x%4.4x, 0x%4.4x, 0x%4.4x }\n",
1003 header.e_res2[0], header.e_res2[1], header.e_res2[2],
1004 header.e_res2[3], header.e_res2[4], header.e_res2[5],
1005 header.e_res2[6], header.e_res2[7], header.e_res2[8],
1006 header.e_res2[9]);
1007 s->Printf(" e_lfanew = 0x%8.8x\n", header.e_lfanew);
Greg Claytonf754f882011-09-09 20:33:05 +00001008}
1009
1010//----------------------------------------------------------------------
1011// DumpCOFFHeader
1012//
1013// Dump the COFF header to the specified output stream
1014//----------------------------------------------------------------------
Kate Stoneb9c1b512016-09-06 20:57:50 +00001015void ObjectFilePECOFF::DumpCOFFHeader(Stream *s, const coff_header_t &header) {
1016 s->PutCString("COFF Header\n");
1017 s->Printf(" machine = 0x%4.4x\n", header.machine);
1018 s->Printf(" nsects = 0x%4.4x\n", header.nsects);
1019 s->Printf(" modtime = 0x%8.8x\n", header.modtime);
1020 s->Printf(" symoff = 0x%8.8x\n", header.symoff);
1021 s->Printf(" nsyms = 0x%8.8x\n", header.nsyms);
1022 s->Printf(" hdrsize = 0x%4.4x\n", header.hdrsize);
Greg Claytonf754f882011-09-09 20:33:05 +00001023}
1024
1025//----------------------------------------------------------------------
1026// DumpOptCOFFHeader
1027//
1028// Dump the optional COFF header to the specified output stream
1029//----------------------------------------------------------------------
Kate Stoneb9c1b512016-09-06 20:57:50 +00001030void ObjectFilePECOFF::DumpOptCOFFHeader(Stream *s,
1031 const coff_opt_header_t &header) {
1032 s->PutCString("Optional COFF Header\n");
1033 s->Printf(" magic = 0x%4.4x\n", header.magic);
1034 s->Printf(" major_linker_version = 0x%2.2x\n",
1035 header.major_linker_version);
1036 s->Printf(" minor_linker_version = 0x%2.2x\n",
1037 header.minor_linker_version);
1038 s->Printf(" code_size = 0x%8.8x\n", header.code_size);
1039 s->Printf(" data_size = 0x%8.8x\n", header.data_size);
1040 s->Printf(" bss_size = 0x%8.8x\n", header.bss_size);
1041 s->Printf(" entry = 0x%8.8x\n", header.entry);
1042 s->Printf(" code_offset = 0x%8.8x\n", header.code_offset);
1043 s->Printf(" data_offset = 0x%8.8x\n", header.data_offset);
1044 s->Printf(" image_base = 0x%16.16" PRIx64 "\n",
1045 header.image_base);
1046 s->Printf(" sect_alignment = 0x%8.8x\n", header.sect_alignment);
1047 s->Printf(" file_alignment = 0x%8.8x\n", header.file_alignment);
1048 s->Printf(" major_os_system_version = 0x%4.4x\n",
1049 header.major_os_system_version);
1050 s->Printf(" minor_os_system_version = 0x%4.4x\n",
1051 header.minor_os_system_version);
1052 s->Printf(" major_image_version = 0x%4.4x\n",
1053 header.major_image_version);
1054 s->Printf(" minor_image_version = 0x%4.4x\n",
1055 header.minor_image_version);
1056 s->Printf(" major_subsystem_version = 0x%4.4x\n",
1057 header.major_subsystem_version);
1058 s->Printf(" minor_subsystem_version = 0x%4.4x\n",
1059 header.minor_subsystem_version);
1060 s->Printf(" reserved1 = 0x%8.8x\n", header.reserved1);
1061 s->Printf(" image_size = 0x%8.8x\n", header.image_size);
1062 s->Printf(" header_size = 0x%8.8x\n", header.header_size);
1063 s->Printf(" checksum = 0x%8.8x\n", header.checksum);
1064 s->Printf(" subsystem = 0x%4.4x\n", header.subsystem);
1065 s->Printf(" dll_flags = 0x%4.4x\n", header.dll_flags);
1066 s->Printf(" stack_reserve_size = 0x%16.16" PRIx64 "\n",
1067 header.stack_reserve_size);
1068 s->Printf(" stack_commit_size = 0x%16.16" PRIx64 "\n",
1069 header.stack_commit_size);
1070 s->Printf(" heap_reserve_size = 0x%16.16" PRIx64 "\n",
1071 header.heap_reserve_size);
1072 s->Printf(" heap_commit_size = 0x%16.16" PRIx64 "\n",
1073 header.heap_commit_size);
1074 s->Printf(" loader_flags = 0x%8.8x\n", header.loader_flags);
1075 s->Printf(" num_data_dir_entries = 0x%8.8x\n",
1076 (uint32_t)header.data_dirs.size());
1077 uint32_t i;
1078 for (i = 0; i < header.data_dirs.size(); i++) {
1079 s->Printf(" data_dirs[%2u] vmaddr = 0x%8.8x, vmsize = 0x%8.8x\n", i,
1080 header.data_dirs[i].vmaddr, header.data_dirs[i].vmsize);
1081 }
Greg Claytonf754f882011-09-09 20:33:05 +00001082}
1083//----------------------------------------------------------------------
1084// DumpSectionHeader
1085//
1086// Dump a single ELF section header to the specified output stream
1087//----------------------------------------------------------------------
Kate Stoneb9c1b512016-09-06 20:57:50 +00001088void ObjectFilePECOFF::DumpSectionHeader(Stream *s,
1089 const section_header_t &sh) {
1090 std::string name;
1091 GetSectionName(name, sh);
1092 s->Printf("%-16s 0x%8.8x 0x%8.8x 0x%8.8x 0x%8.8x 0x%8.8x 0x%8.8x 0x%4.4x "
1093 "0x%4.4x 0x%8.8x\n",
1094 name.c_str(), sh.vmaddr, sh.vmsize, sh.offset, sh.size, sh.reloff,
1095 sh.lineoff, sh.nreloc, sh.nline, sh.flags);
Greg Claytonf754f882011-09-09 20:33:05 +00001096}
1097
Greg Claytonf754f882011-09-09 20:33:05 +00001098//----------------------------------------------------------------------
1099// DumpSectionHeaders
1100//
1101// Dump all of the ELF section header to the specified output stream
1102//----------------------------------------------------------------------
Kate Stoneb9c1b512016-09-06 20:57:50 +00001103void ObjectFilePECOFF::DumpSectionHeaders(Stream *s) {
1104
1105 s->PutCString("Section Headers\n");
1106 s->PutCString("IDX name vm addr vm size file off file "
1107 "size reloc off line off nreloc nline flags\n");
1108 s->PutCString("==== ---------------- ---------- ---------- ---------- "
1109 "---------- ---------- ---------- ------ ------ ----------\n");
1110
1111 uint32_t idx = 0;
1112 SectionHeaderCollIter pos, end = m_sect_headers.end();
1113
1114 for (pos = m_sect_headers.begin(); pos != end; ++pos, ++idx) {
1115 s->Printf("[%2u] ", idx);
1116 ObjectFilePECOFF::DumpSectionHeader(s, *pos);
1117 }
Greg Claytonf754f882011-09-09 20:33:05 +00001118}
1119
Aaron Smith037ed1b2018-12-06 21:36:39 +00001120//----------------------------------------------------------------------
1121// DumpDependentModules
1122//
1123// Dump all of the dependent modules to the specified output stream
1124//----------------------------------------------------------------------
1125void ObjectFilePECOFF::DumpDependentModules(lldb_private::Stream *s) {
1126 auto num_modules = ParseDependentModules();
1127 if (num_modules > 0) {
1128 s->PutCString("Dependent Modules\n");
1129 for (unsigned i = 0; i < num_modules; ++i) {
1130 auto spec = m_deps_filespec->GetFileSpecAtIndex(i);
1131 s->Printf(" %s\n", spec.GetFilename().GetCString());
1132 }
1133 }
1134}
1135
Zachary Turnerfb3b3bd2016-09-20 20:44:50 +00001136bool ObjectFilePECOFF::IsWindowsSubsystem() {
1137 switch (m_coff_header_opt.subsystem) {
1138 case llvm::COFF::IMAGE_SUBSYSTEM_NATIVE:
1139 case llvm::COFF::IMAGE_SUBSYSTEM_WINDOWS_GUI:
1140 case llvm::COFF::IMAGE_SUBSYSTEM_WINDOWS_CUI:
1141 case llvm::COFF::IMAGE_SUBSYSTEM_NATIVE_WINDOWS:
1142 case llvm::COFF::IMAGE_SUBSYSTEM_WINDOWS_CE_GUI:
1143 case llvm::COFF::IMAGE_SUBSYSTEM_XBOX:
1144 case llvm::COFF::IMAGE_SUBSYSTEM_WINDOWS_BOOT_APPLICATION:
1145 return true;
1146 default:
1147 return false;
1148 }
1149}
1150
Kate Stoneb9c1b512016-09-06 20:57:50 +00001151bool ObjectFilePECOFF::GetArchitecture(ArchSpec &arch) {
1152 uint16_t machine = m_coff_header.machine;
1153 switch (machine) {
1154 case llvm::COFF::IMAGE_FILE_MACHINE_AMD64:
1155 case llvm::COFF::IMAGE_FILE_MACHINE_I386:
1156 case llvm::COFF::IMAGE_FILE_MACHINE_POWERPC:
1157 case llvm::COFF::IMAGE_FILE_MACHINE_POWERPCFP:
1158 case llvm::COFF::IMAGE_FILE_MACHINE_ARM:
1159 case llvm::COFF::IMAGE_FILE_MACHINE_ARMNT:
1160 case llvm::COFF::IMAGE_FILE_MACHINE_THUMB:
Zachary Turnerfb3b3bd2016-09-20 20:44:50 +00001161 arch.SetArchitecture(eArchTypeCOFF, machine, LLDB_INVALID_CPUTYPE,
1162 IsWindowsSubsystem() ? llvm::Triple::Win32
1163 : llvm::Triple::UnknownOS);
Kate Stoneb9c1b512016-09-06 20:57:50 +00001164 return true;
1165 default:
1166 break;
1167 }
1168 return false;
Greg Claytonf754f882011-09-09 20:33:05 +00001169}
1170
Kate Stoneb9c1b512016-09-06 20:57:50 +00001171ObjectFile::Type ObjectFilePECOFF::CalculateType() {
1172 if (m_coff_header.machine != 0) {
1173 if ((m_coff_header.flags & llvm::COFF::IMAGE_FILE_DLL) == 0)
1174 return eTypeExecutable;
1175 else
1176 return eTypeSharedLibrary;
1177 }
1178 return eTypeExecutable;
Greg Claytonf754f882011-09-09 20:33:05 +00001179}
1180
Kate Stoneb9c1b512016-09-06 20:57:50 +00001181ObjectFile::Strata ObjectFilePECOFF::CalculateStrata() { return eStrataUser; }
Zachary Turner9cad24a2018-11-09 16:06:44 +00001182
Greg Claytonf754f882011-09-09 20:33:05 +00001183//------------------------------------------------------------------
1184// PluginInterface protocol
1185//------------------------------------------------------------------
Kate Stoneb9c1b512016-09-06 20:57:50 +00001186ConstString ObjectFilePECOFF::GetPluginName() { return GetPluginNameStatic(); }
Greg Claytonf754f882011-09-09 20:33:05 +00001187
Kate Stoneb9c1b512016-09-06 20:57:50 +00001188uint32_t ObjectFilePECOFF::GetPluginVersion() { return 1; }