xref: /openbsd-src/gnu/llvm/lldb/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.cpp (revision f6aab3d83b51b91c24247ad2c2573574de475a82)
1dda28197Spatrick //===-- ObjectFilePECOFF.cpp ----------------------------------------------===//
2061da546Spatrick //
3061da546Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4061da546Spatrick // See https://llvm.org/LICENSE.txt for license information.
5061da546Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6061da546Spatrick //
7061da546Spatrick //===----------------------------------------------------------------------===//
8061da546Spatrick 
9061da546Spatrick #include "ObjectFilePECOFF.h"
10061da546Spatrick #include "PECallFrameInfo.h"
11061da546Spatrick #include "WindowsMiniDump.h"
12061da546Spatrick 
13061da546Spatrick #include "lldb/Core/FileSpecList.h"
14061da546Spatrick #include "lldb/Core/Module.h"
15061da546Spatrick #include "lldb/Core/ModuleSpec.h"
16061da546Spatrick #include "lldb/Core/PluginManager.h"
17061da546Spatrick #include "lldb/Core/Section.h"
18061da546Spatrick #include "lldb/Core/StreamFile.h"
19*f6aab3d8Srobert #include "lldb/Interpreter/OptionValueDictionary.h"
20*f6aab3d8Srobert #include "lldb/Interpreter/OptionValueProperties.h"
21061da546Spatrick #include "lldb/Symbol/ObjectFile.h"
22061da546Spatrick #include "lldb/Target/Process.h"
23061da546Spatrick #include "lldb/Target/SectionLoadList.h"
24061da546Spatrick #include "lldb/Target/Target.h"
25061da546Spatrick #include "lldb/Utility/ArchSpec.h"
26061da546Spatrick #include "lldb/Utility/DataBufferHeap.h"
27061da546Spatrick #include "lldb/Utility/FileSpec.h"
28*f6aab3d8Srobert #include "lldb/Utility/LLDBLog.h"
29061da546Spatrick #include "lldb/Utility/Log.h"
30061da546Spatrick #include "lldb/Utility/StreamString.h"
31061da546Spatrick #include "lldb/Utility/Timer.h"
32061da546Spatrick #include "lldb/Utility/UUID.h"
33061da546Spatrick 
34*f6aab3d8Srobert #include "llvm/BinaryFormat/COFF.h"
35061da546Spatrick #include "llvm/Object/COFFImportFile.h"
36*f6aab3d8Srobert #include "llvm/Support/CRC.h"
37061da546Spatrick #include "llvm/Support/Error.h"
38*f6aab3d8Srobert #include "llvm/Support/FormatAdapters.h"
39*f6aab3d8Srobert #include "llvm/Support/Host.h"
40061da546Spatrick #include "llvm/Support/MemoryBuffer.h"
41*f6aab3d8Srobert #include <optional>
42061da546Spatrick 
43061da546Spatrick #define IMAGE_DOS_SIGNATURE 0x5A4D    // MZ
44061da546Spatrick #define IMAGE_NT_SIGNATURE 0x00004550 // PE00
45061da546Spatrick #define OPT_HEADER_MAGIC_PE32 0x010b
46061da546Spatrick #define OPT_HEADER_MAGIC_PE32_PLUS 0x020b
47061da546Spatrick 
48061da546Spatrick using namespace lldb;
49061da546Spatrick using namespace lldb_private;
50061da546Spatrick 
51dda28197Spatrick LLDB_PLUGIN_DEFINE(ObjectFilePECOFF)
52dda28197Spatrick 
53*f6aab3d8Srobert namespace {
54*f6aab3d8Srobert 
55*f6aab3d8Srobert static constexpr OptionEnumValueElement g_abi_enums[] = {
56*f6aab3d8Srobert     {
57*f6aab3d8Srobert         llvm::Triple::UnknownEnvironment,
58*f6aab3d8Srobert         "default",
59*f6aab3d8Srobert         "Use default target (if it is Windows) or MSVC",
60*f6aab3d8Srobert     },
61*f6aab3d8Srobert     {
62*f6aab3d8Srobert         llvm::Triple::MSVC,
63*f6aab3d8Srobert         "msvc",
64*f6aab3d8Srobert         "MSVC ABI",
65*f6aab3d8Srobert     },
66*f6aab3d8Srobert     {
67*f6aab3d8Srobert         llvm::Triple::GNU,
68*f6aab3d8Srobert         "gnu",
69*f6aab3d8Srobert         "MinGW / Itanium ABI",
70*f6aab3d8Srobert     },
71*f6aab3d8Srobert };
72*f6aab3d8Srobert 
73*f6aab3d8Srobert #define LLDB_PROPERTIES_objectfilepecoff
74*f6aab3d8Srobert #include "ObjectFilePECOFFProperties.inc"
75*f6aab3d8Srobert 
76*f6aab3d8Srobert enum {
77*f6aab3d8Srobert #define LLDB_PROPERTIES_objectfilepecoff
78*f6aab3d8Srobert #include "ObjectFilePECOFFPropertiesEnum.inc"
79*f6aab3d8Srobert };
80*f6aab3d8Srobert 
81*f6aab3d8Srobert class PluginProperties : public Properties {
82*f6aab3d8Srobert public:
GetSettingName()83*f6aab3d8Srobert   static ConstString GetSettingName() {
84*f6aab3d8Srobert     return ConstString(ObjectFilePECOFF::GetPluginNameStatic());
85*f6aab3d8Srobert   }
86*f6aab3d8Srobert 
PluginProperties()87*f6aab3d8Srobert   PluginProperties() {
88*f6aab3d8Srobert     m_collection_sp = std::make_shared<OptionValueProperties>(GetSettingName());
89*f6aab3d8Srobert     m_collection_sp->Initialize(g_objectfilepecoff_properties);
90*f6aab3d8Srobert   }
91*f6aab3d8Srobert 
ABI() const92*f6aab3d8Srobert   llvm::Triple::EnvironmentType ABI() const {
93*f6aab3d8Srobert     return (llvm::Triple::EnvironmentType)
94*f6aab3d8Srobert         m_collection_sp->GetPropertyAtIndexAsEnumeration(
95*f6aab3d8Srobert             nullptr, ePropertyABI, llvm::Triple::UnknownEnvironment);
96*f6aab3d8Srobert   }
97*f6aab3d8Srobert 
ModuleABIMap() const98*f6aab3d8Srobert   OptionValueDictionary *ModuleABIMap() const {
99*f6aab3d8Srobert     return m_collection_sp->GetPropertyAtIndexAsOptionValueDictionary(
100*f6aab3d8Srobert         nullptr, ePropertyModuleABIMap);
101*f6aab3d8Srobert   }
102*f6aab3d8Srobert };
103*f6aab3d8Srobert 
104*f6aab3d8Srobert } // namespace
105*f6aab3d8Srobert 
GetGlobalPluginProperties()106*f6aab3d8Srobert static PluginProperties &GetGlobalPluginProperties() {
107*f6aab3d8Srobert   static PluginProperties g_settings;
108*f6aab3d8Srobert   return g_settings;
109*f6aab3d8Srobert }
110*f6aab3d8Srobert 
GetDebugLinkContents(const llvm::object::COFFObjectFile & coff_obj,std::string & gnu_debuglink_file,uint32_t & gnu_debuglink_crc)111*f6aab3d8Srobert static bool GetDebugLinkContents(const llvm::object::COFFObjectFile &coff_obj,
112*f6aab3d8Srobert                                  std::string &gnu_debuglink_file,
113*f6aab3d8Srobert                                  uint32_t &gnu_debuglink_crc) {
114*f6aab3d8Srobert   static ConstString g_sect_name_gnu_debuglink(".gnu_debuglink");
115*f6aab3d8Srobert   for (const auto &section : coff_obj.sections()) {
116*f6aab3d8Srobert     auto name = section.getName();
117*f6aab3d8Srobert     if (!name) {
118*f6aab3d8Srobert       llvm::consumeError(name.takeError());
119*f6aab3d8Srobert       continue;
120*f6aab3d8Srobert     }
121*f6aab3d8Srobert     if (*name == g_sect_name_gnu_debuglink.GetStringRef()) {
122*f6aab3d8Srobert       auto content = section.getContents();
123*f6aab3d8Srobert       if (!content) {
124*f6aab3d8Srobert         llvm::consumeError(content.takeError());
125*f6aab3d8Srobert         return false;
126*f6aab3d8Srobert       }
127*f6aab3d8Srobert       DataExtractor data(
128*f6aab3d8Srobert           content->data(), content->size(),
129*f6aab3d8Srobert           coff_obj.isLittleEndian() ? eByteOrderLittle : eByteOrderBig, 4);
130*f6aab3d8Srobert       lldb::offset_t gnu_debuglink_offset = 0;
131*f6aab3d8Srobert       gnu_debuglink_file = data.GetCStr(&gnu_debuglink_offset);
132*f6aab3d8Srobert       // Align to the next 4-byte offset
133*f6aab3d8Srobert       gnu_debuglink_offset = llvm::alignTo(gnu_debuglink_offset, 4);
134*f6aab3d8Srobert       data.GetU32(&gnu_debuglink_offset, &gnu_debuglink_crc, 1);
135*f6aab3d8Srobert       return true;
136*f6aab3d8Srobert     }
137*f6aab3d8Srobert   }
138*f6aab3d8Srobert   return false;
139*f6aab3d8Srobert }
140*f6aab3d8Srobert 
GetCoffUUID(llvm::object::COFFObjectFile & coff_obj)141dda28197Spatrick static UUID GetCoffUUID(llvm::object::COFFObjectFile &coff_obj) {
142061da546Spatrick   const llvm::codeview::DebugInfo *pdb_info = nullptr;
143061da546Spatrick   llvm::StringRef pdb_file;
144061da546Spatrick 
145*f6aab3d8Srobert   // First, prefer to use the PDB build id. LLD generates this even for mingw
146*f6aab3d8Srobert   // targets without PDB output, and it does not get stripped either.
147dda28197Spatrick   if (!coff_obj.getDebugPDBInfo(pdb_info, pdb_file) && pdb_info) {
148061da546Spatrick     if (pdb_info->PDB70.CVSignature == llvm::OMF::Signature::PDB70) {
149be691f3bSpatrick       UUID::CvRecordPdb70 info;
150be691f3bSpatrick       memcpy(&info.Uuid, pdb_info->PDB70.Signature, sizeof(info.Uuid));
151be691f3bSpatrick       info.Age = pdb_info->PDB70.Age;
152*f6aab3d8Srobert       return UUID(info);
153061da546Spatrick     }
154061da546Spatrick   }
155061da546Spatrick 
156*f6aab3d8Srobert   std::string gnu_debuglink_file;
157*f6aab3d8Srobert   uint32_t gnu_debuglink_crc;
158*f6aab3d8Srobert 
159*f6aab3d8Srobert   // The GNU linker normally does not write a PDB build id (unless requested
160*f6aab3d8Srobert   // with the --build-id option), so we should fall back to using the crc
161*f6aab3d8Srobert   // from .gnu_debuglink if it exists, just like how ObjectFileELF does it.
162*f6aab3d8Srobert   if (!GetDebugLinkContents(coff_obj, gnu_debuglink_file, gnu_debuglink_crc)) {
163*f6aab3d8Srobert     // If there is no .gnu_debuglink section, then this may be an object
164*f6aab3d8Srobert     // containing DWARF debug info for .gnu_debuglink, so calculate the crc of
165*f6aab3d8Srobert     // the object itself.
166*f6aab3d8Srobert     auto raw_data = coff_obj.getData();
167*f6aab3d8Srobert     LLDB_SCOPED_TIMERF(
168*f6aab3d8Srobert         "Calculating module crc32 %s with size %" PRIu64 " KiB",
169*f6aab3d8Srobert         FileSpec(coff_obj.getFileName()).GetLastPathComponent().AsCString(),
170*f6aab3d8Srobert         static_cast<lldb::offset_t>(raw_data.size()) / 1024);
171*f6aab3d8Srobert     gnu_debuglink_crc = llvm::crc32(0, llvm::arrayRefFromStringRef(raw_data));
172*f6aab3d8Srobert   }
173*f6aab3d8Srobert   // Use 4 bytes of crc from the .gnu_debuglink section.
174*f6aab3d8Srobert   llvm::support::ulittle32_t data(gnu_debuglink_crc);
175*f6aab3d8Srobert   return UUID(&data, sizeof(data));
176061da546Spatrick }
177061da546Spatrick 
178061da546Spatrick char ObjectFilePECOFF::ID;
179061da546Spatrick 
Initialize()180061da546Spatrick void ObjectFilePECOFF::Initialize() {
181*f6aab3d8Srobert   PluginManager::RegisterPlugin(GetPluginNameStatic(),
182*f6aab3d8Srobert                                 GetPluginDescriptionStatic(), CreateInstance,
183*f6aab3d8Srobert                                 CreateMemoryInstance, GetModuleSpecifications,
184*f6aab3d8Srobert                                 SaveCore, DebuggerInitialize);
185*f6aab3d8Srobert }
186*f6aab3d8Srobert 
DebuggerInitialize(Debugger & debugger)187*f6aab3d8Srobert void ObjectFilePECOFF::DebuggerInitialize(Debugger &debugger) {
188*f6aab3d8Srobert   if (!PluginManager::GetSettingForObjectFilePlugin(
189*f6aab3d8Srobert           debugger, PluginProperties::GetSettingName())) {
190*f6aab3d8Srobert     const bool is_global_setting = true;
191*f6aab3d8Srobert     PluginManager::CreateSettingForObjectFilePlugin(
192*f6aab3d8Srobert         debugger, GetGlobalPluginProperties().GetValueProperties(),
193*f6aab3d8Srobert         ConstString("Properties for the PE/COFF object-file plug-in."),
194*f6aab3d8Srobert         is_global_setting);
195*f6aab3d8Srobert   }
196061da546Spatrick }
197061da546Spatrick 
Terminate()198061da546Spatrick void ObjectFilePECOFF::Terminate() {
199061da546Spatrick   PluginManager::UnregisterPlugin(CreateInstance);
200061da546Spatrick }
201061da546Spatrick 
GetPluginDescriptionStatic()202*f6aab3d8Srobert llvm::StringRef ObjectFilePECOFF::GetPluginDescriptionStatic() {
203061da546Spatrick   return "Portable Executable and Common Object File Format object file reader "
204061da546Spatrick          "(32 and 64 bit)";
205061da546Spatrick }
206061da546Spatrick 
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)207*f6aab3d8Srobert ObjectFile *ObjectFilePECOFF::CreateInstance(
208*f6aab3d8Srobert     const lldb::ModuleSP &module_sp, DataBufferSP data_sp,
209*f6aab3d8Srobert     lldb::offset_t data_offset, const lldb_private::FileSpec *file_p,
210*f6aab3d8Srobert     lldb::offset_t file_offset, lldb::offset_t length) {
211061da546Spatrick   FileSpec file = file_p ? *file_p : FileSpec();
212061da546Spatrick   if (!data_sp) {
213061da546Spatrick     data_sp = MapFileData(file, length, file_offset);
214061da546Spatrick     if (!data_sp)
215061da546Spatrick       return nullptr;
216061da546Spatrick     data_offset = 0;
217061da546Spatrick   }
218061da546Spatrick 
219061da546Spatrick   if (!ObjectFilePECOFF::MagicBytesMatch(data_sp))
220061da546Spatrick     return nullptr;
221061da546Spatrick 
222061da546Spatrick   // Update the data to contain the entire file if it doesn't already
223061da546Spatrick   if (data_sp->GetByteSize() < length) {
224061da546Spatrick     data_sp = MapFileData(file, length, file_offset);
225061da546Spatrick     if (!data_sp)
226061da546Spatrick       return nullptr;
227061da546Spatrick   }
228061da546Spatrick 
229061da546Spatrick   auto objfile_up = std::make_unique<ObjectFilePECOFF>(
230061da546Spatrick       module_sp, data_sp, data_offset, file_p, file_offset, length);
231061da546Spatrick   if (!objfile_up || !objfile_up->ParseHeader())
232061da546Spatrick     return nullptr;
233061da546Spatrick 
234061da546Spatrick   // Cache coff binary.
235061da546Spatrick   if (!objfile_up->CreateBinary())
236061da546Spatrick     return nullptr;
237061da546Spatrick   return objfile_up.release();
238061da546Spatrick }
239061da546Spatrick 
CreateMemoryInstance(const lldb::ModuleSP & module_sp,lldb::WritableDataBufferSP data_sp,const lldb::ProcessSP & process_sp,lldb::addr_t header_addr)240061da546Spatrick ObjectFile *ObjectFilePECOFF::CreateMemoryInstance(
241*f6aab3d8Srobert     const lldb::ModuleSP &module_sp, lldb::WritableDataBufferSP data_sp,
242061da546Spatrick     const lldb::ProcessSP &process_sp, lldb::addr_t header_addr) {
243061da546Spatrick   if (!data_sp || !ObjectFilePECOFF::MagicBytesMatch(data_sp))
244061da546Spatrick     return nullptr;
245061da546Spatrick   auto objfile_up = std::make_unique<ObjectFilePECOFF>(
246061da546Spatrick       module_sp, data_sp, process_sp, header_addr);
247061da546Spatrick   if (objfile_up.get() && objfile_up->ParseHeader()) {
248061da546Spatrick     return objfile_up.release();
249061da546Spatrick   }
250061da546Spatrick   return nullptr;
251061da546Spatrick }
252061da546Spatrick 
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)253061da546Spatrick size_t ObjectFilePECOFF::GetModuleSpecifications(
254061da546Spatrick     const lldb_private::FileSpec &file, lldb::DataBufferSP &data_sp,
255061da546Spatrick     lldb::offset_t data_offset, lldb::offset_t file_offset,
256061da546Spatrick     lldb::offset_t length, lldb_private::ModuleSpecList &specs) {
257061da546Spatrick   const size_t initial_count = specs.GetSize();
258061da546Spatrick   if (!data_sp || !ObjectFilePECOFF::MagicBytesMatch(data_sp))
259061da546Spatrick     return initial_count;
260061da546Spatrick 
261*f6aab3d8Srobert   Log *log = GetLog(LLDBLog::Object);
262061da546Spatrick 
263dda28197Spatrick   if (data_sp->GetByteSize() < length)
264dda28197Spatrick     if (DataBufferSP full_sp = MapFileData(file, -1, file_offset))
265dda28197Spatrick       data_sp = std::move(full_sp);
266dda28197Spatrick   auto binary = llvm::object::createBinary(llvm::MemoryBufferRef(
267dda28197Spatrick       toStringRef(data_sp->GetData()), file.GetFilename().GetStringRef()));
268061da546Spatrick 
269061da546Spatrick   if (!binary) {
270061da546Spatrick     LLDB_LOG_ERROR(log, binary.takeError(),
271061da546Spatrick                    "Failed to create binary for file ({1}): {0}", file);
272061da546Spatrick     return initial_count;
273061da546Spatrick   }
274061da546Spatrick 
275dda28197Spatrick   auto *COFFObj = llvm::dyn_cast<llvm::object::COFFObjectFile>(binary->get());
276dda28197Spatrick   if (!COFFObj)
277061da546Spatrick     return initial_count;
278061da546Spatrick 
279061da546Spatrick   ModuleSpec module_spec(file);
280061da546Spatrick   ArchSpec &spec = module_spec.GetArchitecture();
281061da546Spatrick   lldb_private::UUID &uuid = module_spec.GetUUID();
282061da546Spatrick   if (!uuid.IsValid())
283dda28197Spatrick     uuid = GetCoffUUID(*COFFObj);
284061da546Spatrick 
285*f6aab3d8Srobert   static llvm::Triple::EnvironmentType default_env = [] {
286*f6aab3d8Srobert     auto def_target = llvm::Triple(
287*f6aab3d8Srobert         llvm::Triple::normalize(llvm::sys::getDefaultTargetTriple()));
288*f6aab3d8Srobert     if (def_target.getOS() == llvm::Triple::Win32 &&
289*f6aab3d8Srobert         def_target.getEnvironment() != llvm::Triple::UnknownEnvironment)
290*f6aab3d8Srobert       return def_target.getEnvironment();
291*f6aab3d8Srobert     return llvm::Triple::MSVC;
292*f6aab3d8Srobert   }();
293*f6aab3d8Srobert 
294*f6aab3d8Srobert   // Check for a module-specific override.
295*f6aab3d8Srobert   OptionValueSP module_env_option;
296*f6aab3d8Srobert   const auto *map = GetGlobalPluginProperties().ModuleABIMap();
297*f6aab3d8Srobert   if (map->GetNumValues() > 0) {
298*f6aab3d8Srobert     // Step 1: Try with the exact file name.
299*f6aab3d8Srobert     auto name = file.GetLastPathComponent();
300*f6aab3d8Srobert     module_env_option = map->GetValueForKey(name);
301*f6aab3d8Srobert     if (!module_env_option) {
302*f6aab3d8Srobert       // Step 2: Try with the file name in lowercase.
303*f6aab3d8Srobert       auto name_lower = name.GetStringRef().lower();
304*f6aab3d8Srobert       module_env_option =
305*f6aab3d8Srobert           map->GetValueForKey(ConstString(llvm::StringRef(name_lower)));
306*f6aab3d8Srobert     }
307*f6aab3d8Srobert     if (!module_env_option) {
308*f6aab3d8Srobert       // Step 3: Try with the file name with ".debug" suffix stripped.
309*f6aab3d8Srobert       auto name_stripped = name.GetStringRef();
310*f6aab3d8Srobert       if (name_stripped.consume_back_insensitive(".debug")) {
311*f6aab3d8Srobert         module_env_option = map->GetValueForKey(ConstString(name_stripped));
312*f6aab3d8Srobert         if (!module_env_option) {
313*f6aab3d8Srobert           // Step 4: Try with the file name in lowercase with ".debug" suffix
314*f6aab3d8Srobert           // stripped.
315*f6aab3d8Srobert           auto name_lower = name_stripped.lower();
316*f6aab3d8Srobert           module_env_option =
317*f6aab3d8Srobert               map->GetValueForKey(ConstString(llvm::StringRef(name_lower)));
318*f6aab3d8Srobert         }
319*f6aab3d8Srobert       }
320*f6aab3d8Srobert     }
321*f6aab3d8Srobert   }
322*f6aab3d8Srobert   llvm::Triple::EnvironmentType env;
323*f6aab3d8Srobert   if (module_env_option)
324*f6aab3d8Srobert     env =
325*f6aab3d8Srobert         (llvm::Triple::EnvironmentType)module_env_option->GetEnumerationValue();
326*f6aab3d8Srobert   else
327*f6aab3d8Srobert     env = GetGlobalPluginProperties().ABI();
328*f6aab3d8Srobert 
329*f6aab3d8Srobert   if (env == llvm::Triple::UnknownEnvironment)
330*f6aab3d8Srobert     env = default_env;
331*f6aab3d8Srobert 
332061da546Spatrick   switch (COFFObj->getMachine()) {
333061da546Spatrick   case MachineAmd64:
334061da546Spatrick     spec.SetTriple("x86_64-pc-windows");
335*f6aab3d8Srobert     spec.GetTriple().setEnvironment(env);
336061da546Spatrick     specs.Append(module_spec);
337061da546Spatrick     break;
338061da546Spatrick   case MachineX86:
339061da546Spatrick     spec.SetTriple("i386-pc-windows");
340*f6aab3d8Srobert     spec.GetTriple().setEnvironment(env);
341061da546Spatrick     specs.Append(module_spec);
342061da546Spatrick     break;
343061da546Spatrick   case MachineArmNt:
344061da546Spatrick     spec.SetTriple("armv7-pc-windows");
345*f6aab3d8Srobert     spec.GetTriple().setEnvironment(env);
346061da546Spatrick     specs.Append(module_spec);
347061da546Spatrick     break;
348061da546Spatrick   case MachineArm64:
349061da546Spatrick     spec.SetTriple("aarch64-pc-windows");
350*f6aab3d8Srobert     spec.GetTriple().setEnvironment(env);
351061da546Spatrick     specs.Append(module_spec);
352061da546Spatrick     break;
353061da546Spatrick   default:
354061da546Spatrick     break;
355061da546Spatrick   }
356061da546Spatrick 
357061da546Spatrick   return specs.GetSize() - initial_count;
358061da546Spatrick }
359061da546Spatrick 
SaveCore(const lldb::ProcessSP & process_sp,const lldb_private::FileSpec & outfile,lldb::SaveCoreStyle & core_style,lldb_private::Status & error)360061da546Spatrick bool ObjectFilePECOFF::SaveCore(const lldb::ProcessSP &process_sp,
361061da546Spatrick                                 const lldb_private::FileSpec &outfile,
362be691f3bSpatrick                                 lldb::SaveCoreStyle &core_style,
363061da546Spatrick                                 lldb_private::Status &error) {
364be691f3bSpatrick   core_style = eSaveCoreFull;
365061da546Spatrick   return SaveMiniDump(process_sp, outfile, error);
366061da546Spatrick }
367061da546Spatrick 
MagicBytesMatch(DataBufferSP data_sp)368*f6aab3d8Srobert bool ObjectFilePECOFF::MagicBytesMatch(DataBufferSP data_sp) {
369061da546Spatrick   DataExtractor data(data_sp, eByteOrderLittle, 4);
370061da546Spatrick   lldb::offset_t offset = 0;
371061da546Spatrick   uint16_t magic = data.GetU16(&offset);
372061da546Spatrick   return magic == IMAGE_DOS_SIGNATURE;
373061da546Spatrick }
374061da546Spatrick 
MapSymbolType(uint16_t coff_symbol_type)375061da546Spatrick lldb::SymbolType ObjectFilePECOFF::MapSymbolType(uint16_t coff_symbol_type) {
376061da546Spatrick   // TODO:  We need to complete this mapping of COFF symbol types to LLDB ones.
377061da546Spatrick   // For now, here's a hack to make sure our function have types.
378061da546Spatrick   const auto complex_type =
379061da546Spatrick       coff_symbol_type >> llvm::COFF::SCT_COMPLEX_TYPE_SHIFT;
380061da546Spatrick   if (complex_type == llvm::COFF::IMAGE_SYM_DTYPE_FUNCTION) {
381061da546Spatrick     return lldb::eSymbolTypeCode;
382061da546Spatrick   }
383*f6aab3d8Srobert   const auto base_type = coff_symbol_type & 0xff;
384*f6aab3d8Srobert   if (base_type == llvm::COFF::IMAGE_SYM_TYPE_NULL &&
385*f6aab3d8Srobert       complex_type == llvm::COFF::IMAGE_SYM_DTYPE_NULL) {
386*f6aab3d8Srobert     // Unknown type. LLD and GNU ld uses this for variables on MinGW, so
387*f6aab3d8Srobert     // consider these symbols to be data to enable printing.
388*f6aab3d8Srobert     return lldb::eSymbolTypeData;
389*f6aab3d8Srobert   }
390061da546Spatrick   return lldb::eSymbolTypeInvalid;
391061da546Spatrick }
392061da546Spatrick 
CreateBinary()393061da546Spatrick bool ObjectFilePECOFF::CreateBinary() {
394dda28197Spatrick   if (m_binary)
395061da546Spatrick     return true;
396061da546Spatrick 
397*f6aab3d8Srobert   Log *log = GetLog(LLDBLog::Object);
398061da546Spatrick 
399dda28197Spatrick   auto binary = llvm::object::createBinary(llvm::MemoryBufferRef(
400dda28197Spatrick       toStringRef(m_data.GetData()), m_file.GetFilename().GetStringRef()));
401061da546Spatrick   if (!binary) {
402061da546Spatrick     LLDB_LOG_ERROR(log, binary.takeError(),
403061da546Spatrick                    "Failed to create binary for file ({1}): {0}", m_file);
404061da546Spatrick     return false;
405061da546Spatrick   }
406061da546Spatrick 
407061da546Spatrick   // Make sure we only handle COFF format.
408dda28197Spatrick   m_binary =
409dda28197Spatrick       llvm::unique_dyn_cast<llvm::object::COFFObjectFile>(std::move(*binary));
410dda28197Spatrick   if (!m_binary)
411061da546Spatrick     return false;
412061da546Spatrick 
413dda28197Spatrick   LLDB_LOG(log, "this = {0}, module = {1} ({2}), file = {3}, binary = {4}",
414dda28197Spatrick            this, GetModule().get(), GetModule()->GetSpecificationDescription(),
415dda28197Spatrick            m_file.GetPath(), m_binary.get());
416061da546Spatrick   return true;
417061da546Spatrick }
418061da546Spatrick 
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)419061da546Spatrick ObjectFilePECOFF::ObjectFilePECOFF(const lldb::ModuleSP &module_sp,
420*f6aab3d8Srobert                                    DataBufferSP data_sp,
421061da546Spatrick                                    lldb::offset_t data_offset,
422061da546Spatrick                                    const FileSpec *file,
423061da546Spatrick                                    lldb::offset_t file_offset,
424061da546Spatrick                                    lldb::offset_t length)
425061da546Spatrick     : ObjectFile(module_sp, file, file_offset, length, data_sp, data_offset),
426*f6aab3d8Srobert       m_dos_header(), m_coff_header(), m_coff_header_opt(), m_sect_headers(),
427*f6aab3d8Srobert       m_image_base(LLDB_INVALID_ADDRESS), m_entry_point_address(),
428*f6aab3d8Srobert       m_deps_filespec() {}
429061da546Spatrick 
ObjectFilePECOFF(const lldb::ModuleSP & module_sp,WritableDataBufferSP header_data_sp,const lldb::ProcessSP & process_sp,addr_t header_addr)430061da546Spatrick ObjectFilePECOFF::ObjectFilePECOFF(const lldb::ModuleSP &module_sp,
431*f6aab3d8Srobert                                    WritableDataBufferSP header_data_sp,
432061da546Spatrick                                    const lldb::ProcessSP &process_sp,
433061da546Spatrick                                    addr_t header_addr)
434061da546Spatrick     : ObjectFile(module_sp, process_sp, header_addr, header_data_sp),
435*f6aab3d8Srobert       m_dos_header(), m_coff_header(), m_coff_header_opt(), m_sect_headers(),
436*f6aab3d8Srobert       m_image_base(LLDB_INVALID_ADDRESS), m_entry_point_address(),
437*f6aab3d8Srobert       m_deps_filespec() {}
438061da546Spatrick 
439be691f3bSpatrick ObjectFilePECOFF::~ObjectFilePECOFF() = default;
440061da546Spatrick 
ParseHeader()441061da546Spatrick bool ObjectFilePECOFF::ParseHeader() {
442061da546Spatrick   ModuleSP module_sp(GetModule());
443061da546Spatrick   if (module_sp) {
444061da546Spatrick     std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex());
445061da546Spatrick     m_sect_headers.clear();
446061da546Spatrick     m_data.SetByteOrder(eByteOrderLittle);
447061da546Spatrick     lldb::offset_t offset = 0;
448061da546Spatrick 
449061da546Spatrick     if (ParseDOSHeader(m_data, m_dos_header)) {
450061da546Spatrick       offset = m_dos_header.e_lfanew;
451061da546Spatrick       uint32_t pe_signature = m_data.GetU32(&offset);
452061da546Spatrick       if (pe_signature != IMAGE_NT_SIGNATURE)
453061da546Spatrick         return false;
454061da546Spatrick       if (ParseCOFFHeader(m_data, &offset, m_coff_header)) {
455061da546Spatrick         if (m_coff_header.hdrsize > 0)
456061da546Spatrick           ParseCOFFOptionalHeader(&offset);
457061da546Spatrick         ParseSectionHeaders(offset);
458061da546Spatrick       }
459061da546Spatrick       m_data.SetAddressByteSize(GetAddressByteSize());
460061da546Spatrick       return true;
461061da546Spatrick     }
462061da546Spatrick   }
463061da546Spatrick   return false;
464061da546Spatrick }
465061da546Spatrick 
SetLoadAddress(Target & target,addr_t value,bool value_is_offset)466061da546Spatrick bool ObjectFilePECOFF::SetLoadAddress(Target &target, addr_t value,
467061da546Spatrick                                       bool value_is_offset) {
468061da546Spatrick   bool changed = false;
469061da546Spatrick   ModuleSP module_sp = GetModule();
470061da546Spatrick   if (module_sp) {
471061da546Spatrick     size_t num_loaded_sections = 0;
472061da546Spatrick     SectionList *section_list = GetSectionList();
473061da546Spatrick     if (section_list) {
474061da546Spatrick       if (!value_is_offset) {
475061da546Spatrick         value -= m_image_base;
476061da546Spatrick       }
477061da546Spatrick 
478061da546Spatrick       const size_t num_sections = section_list->GetSize();
479061da546Spatrick       size_t sect_idx = 0;
480061da546Spatrick 
481061da546Spatrick       for (sect_idx = 0; sect_idx < num_sections; ++sect_idx) {
482061da546Spatrick         // Iterate through the object file sections to find all of the sections
483061da546Spatrick         // that have SHF_ALLOC in their flag bits.
484061da546Spatrick         SectionSP section_sp(section_list->GetSectionAtIndex(sect_idx));
485061da546Spatrick         if (section_sp && !section_sp->IsThreadSpecific()) {
486061da546Spatrick           if (target.GetSectionLoadList().SetSectionLoadAddress(
487061da546Spatrick                   section_sp, section_sp->GetFileAddress() + value))
488061da546Spatrick             ++num_loaded_sections;
489061da546Spatrick         }
490061da546Spatrick       }
491061da546Spatrick       changed = num_loaded_sections > 0;
492061da546Spatrick     }
493061da546Spatrick   }
494061da546Spatrick   return changed;
495061da546Spatrick }
496061da546Spatrick 
GetByteOrder() const497061da546Spatrick ByteOrder ObjectFilePECOFF::GetByteOrder() const { return eByteOrderLittle; }
498061da546Spatrick 
IsExecutable() const499061da546Spatrick bool ObjectFilePECOFF::IsExecutable() const {
500061da546Spatrick   return (m_coff_header.flags & llvm::COFF::IMAGE_FILE_DLL) == 0;
501061da546Spatrick }
502061da546Spatrick 
GetAddressByteSize() const503061da546Spatrick uint32_t ObjectFilePECOFF::GetAddressByteSize() const {
504061da546Spatrick   if (m_coff_header_opt.magic == OPT_HEADER_MAGIC_PE32_PLUS)
505061da546Spatrick     return 8;
506061da546Spatrick   else if (m_coff_header_opt.magic == OPT_HEADER_MAGIC_PE32)
507061da546Spatrick     return 4;
508061da546Spatrick   return 4;
509061da546Spatrick }
510061da546Spatrick 
511061da546Spatrick // NeedsEndianSwap
512061da546Spatrick //
513061da546Spatrick // Return true if an endian swap needs to occur when extracting data from this
514061da546Spatrick // file.
NeedsEndianSwap() const515061da546Spatrick bool ObjectFilePECOFF::NeedsEndianSwap() const {
516061da546Spatrick #if defined(__LITTLE_ENDIAN__)
517061da546Spatrick   return false;
518061da546Spatrick #else
519061da546Spatrick   return true;
520061da546Spatrick #endif
521061da546Spatrick }
522061da546Spatrick // ParseDOSHeader
ParseDOSHeader(DataExtractor & data,dos_header_t & dos_header)523061da546Spatrick bool ObjectFilePECOFF::ParseDOSHeader(DataExtractor &data,
524061da546Spatrick                                       dos_header_t &dos_header) {
525061da546Spatrick   bool success = false;
526061da546Spatrick   lldb::offset_t offset = 0;
527061da546Spatrick   success = data.ValidOffsetForDataOfSize(0, sizeof(dos_header));
528061da546Spatrick 
529061da546Spatrick   if (success) {
530061da546Spatrick     dos_header.e_magic = data.GetU16(&offset); // Magic number
531061da546Spatrick     success = dos_header.e_magic == IMAGE_DOS_SIGNATURE;
532061da546Spatrick 
533061da546Spatrick     if (success) {
534061da546Spatrick       dos_header.e_cblp = data.GetU16(&offset); // Bytes on last page of file
535061da546Spatrick       dos_header.e_cp = data.GetU16(&offset);   // Pages in file
536061da546Spatrick       dos_header.e_crlc = data.GetU16(&offset); // Relocations
537061da546Spatrick       dos_header.e_cparhdr =
538061da546Spatrick           data.GetU16(&offset); // Size of header in paragraphs
539061da546Spatrick       dos_header.e_minalloc =
540061da546Spatrick           data.GetU16(&offset); // Minimum extra paragraphs needed
541061da546Spatrick       dos_header.e_maxalloc =
542061da546Spatrick           data.GetU16(&offset);               // Maximum extra paragraphs needed
543061da546Spatrick       dos_header.e_ss = data.GetU16(&offset); // Initial (relative) SS value
544061da546Spatrick       dos_header.e_sp = data.GetU16(&offset); // Initial SP value
545061da546Spatrick       dos_header.e_csum = data.GetU16(&offset); // Checksum
546061da546Spatrick       dos_header.e_ip = data.GetU16(&offset);   // Initial IP value
547061da546Spatrick       dos_header.e_cs = data.GetU16(&offset);   // Initial (relative) CS value
548061da546Spatrick       dos_header.e_lfarlc =
549061da546Spatrick           data.GetU16(&offset); // File address of relocation table
550061da546Spatrick       dos_header.e_ovno = data.GetU16(&offset); // Overlay number
551061da546Spatrick 
552061da546Spatrick       dos_header.e_res[0] = data.GetU16(&offset); // Reserved words
553061da546Spatrick       dos_header.e_res[1] = data.GetU16(&offset); // Reserved words
554061da546Spatrick       dos_header.e_res[2] = data.GetU16(&offset); // Reserved words
555061da546Spatrick       dos_header.e_res[3] = data.GetU16(&offset); // Reserved words
556061da546Spatrick 
557061da546Spatrick       dos_header.e_oemid =
558061da546Spatrick           data.GetU16(&offset); // OEM identifier (for e_oeminfo)
559061da546Spatrick       dos_header.e_oeminfo =
560061da546Spatrick           data.GetU16(&offset); // OEM information; e_oemid specific
561061da546Spatrick       dos_header.e_res2[0] = data.GetU16(&offset); // Reserved words
562061da546Spatrick       dos_header.e_res2[1] = data.GetU16(&offset); // Reserved words
563061da546Spatrick       dos_header.e_res2[2] = data.GetU16(&offset); // Reserved words
564061da546Spatrick       dos_header.e_res2[3] = data.GetU16(&offset); // Reserved words
565061da546Spatrick       dos_header.e_res2[4] = data.GetU16(&offset); // Reserved words
566061da546Spatrick       dos_header.e_res2[5] = data.GetU16(&offset); // Reserved words
567061da546Spatrick       dos_header.e_res2[6] = data.GetU16(&offset); // Reserved words
568061da546Spatrick       dos_header.e_res2[7] = data.GetU16(&offset); // Reserved words
569061da546Spatrick       dos_header.e_res2[8] = data.GetU16(&offset); // Reserved words
570061da546Spatrick       dos_header.e_res2[9] = data.GetU16(&offset); // Reserved words
571061da546Spatrick 
572061da546Spatrick       dos_header.e_lfanew =
573061da546Spatrick           data.GetU32(&offset); // File address of new exe header
574061da546Spatrick     }
575061da546Spatrick   }
576061da546Spatrick   if (!success)
577061da546Spatrick     memset(&dos_header, 0, sizeof(dos_header));
578061da546Spatrick   return success;
579061da546Spatrick }
580061da546Spatrick 
581061da546Spatrick // ParserCOFFHeader
ParseCOFFHeader(DataExtractor & data,lldb::offset_t * offset_ptr,coff_header_t & coff_header)582061da546Spatrick bool ObjectFilePECOFF::ParseCOFFHeader(DataExtractor &data,
583061da546Spatrick                                        lldb::offset_t *offset_ptr,
584061da546Spatrick                                        coff_header_t &coff_header) {
585061da546Spatrick   bool success =
586061da546Spatrick       data.ValidOffsetForDataOfSize(*offset_ptr, sizeof(coff_header));
587061da546Spatrick   if (success) {
588061da546Spatrick     coff_header.machine = data.GetU16(offset_ptr);
589061da546Spatrick     coff_header.nsects = data.GetU16(offset_ptr);
590061da546Spatrick     coff_header.modtime = data.GetU32(offset_ptr);
591061da546Spatrick     coff_header.symoff = data.GetU32(offset_ptr);
592061da546Spatrick     coff_header.nsyms = data.GetU32(offset_ptr);
593061da546Spatrick     coff_header.hdrsize = data.GetU16(offset_ptr);
594061da546Spatrick     coff_header.flags = data.GetU16(offset_ptr);
595061da546Spatrick   }
596061da546Spatrick   if (!success)
597061da546Spatrick     memset(&coff_header, 0, sizeof(coff_header));
598061da546Spatrick   return success;
599061da546Spatrick }
600061da546Spatrick 
ParseCOFFOptionalHeader(lldb::offset_t * offset_ptr)601061da546Spatrick bool ObjectFilePECOFF::ParseCOFFOptionalHeader(lldb::offset_t *offset_ptr) {
602061da546Spatrick   bool success = false;
603061da546Spatrick   const lldb::offset_t end_offset = *offset_ptr + m_coff_header.hdrsize;
604061da546Spatrick   if (*offset_ptr < end_offset) {
605061da546Spatrick     success = true;
606061da546Spatrick     m_coff_header_opt.magic = m_data.GetU16(offset_ptr);
607061da546Spatrick     m_coff_header_opt.major_linker_version = m_data.GetU8(offset_ptr);
608061da546Spatrick     m_coff_header_opt.minor_linker_version = m_data.GetU8(offset_ptr);
609061da546Spatrick     m_coff_header_opt.code_size = m_data.GetU32(offset_ptr);
610061da546Spatrick     m_coff_header_opt.data_size = m_data.GetU32(offset_ptr);
611061da546Spatrick     m_coff_header_opt.bss_size = m_data.GetU32(offset_ptr);
612061da546Spatrick     m_coff_header_opt.entry = m_data.GetU32(offset_ptr);
613061da546Spatrick     m_coff_header_opt.code_offset = m_data.GetU32(offset_ptr);
614061da546Spatrick 
615061da546Spatrick     const uint32_t addr_byte_size = GetAddressByteSize();
616061da546Spatrick 
617061da546Spatrick     if (*offset_ptr < end_offset) {
618061da546Spatrick       if (m_coff_header_opt.magic == OPT_HEADER_MAGIC_PE32) {
619061da546Spatrick         // PE32 only
620061da546Spatrick         m_coff_header_opt.data_offset = m_data.GetU32(offset_ptr);
621061da546Spatrick       } else
622061da546Spatrick         m_coff_header_opt.data_offset = 0;
623061da546Spatrick 
624061da546Spatrick       if (*offset_ptr < end_offset) {
625061da546Spatrick         m_coff_header_opt.image_base =
626061da546Spatrick             m_data.GetMaxU64(offset_ptr, addr_byte_size);
627061da546Spatrick         m_coff_header_opt.sect_alignment = m_data.GetU32(offset_ptr);
628061da546Spatrick         m_coff_header_opt.file_alignment = m_data.GetU32(offset_ptr);
629061da546Spatrick         m_coff_header_opt.major_os_system_version = m_data.GetU16(offset_ptr);
630061da546Spatrick         m_coff_header_opt.minor_os_system_version = m_data.GetU16(offset_ptr);
631061da546Spatrick         m_coff_header_opt.major_image_version = m_data.GetU16(offset_ptr);
632061da546Spatrick         m_coff_header_opt.minor_image_version = m_data.GetU16(offset_ptr);
633061da546Spatrick         m_coff_header_opt.major_subsystem_version = m_data.GetU16(offset_ptr);
634061da546Spatrick         m_coff_header_opt.minor_subsystem_version = m_data.GetU16(offset_ptr);
635061da546Spatrick         m_coff_header_opt.reserved1 = m_data.GetU32(offset_ptr);
636061da546Spatrick         m_coff_header_opt.image_size = m_data.GetU32(offset_ptr);
637061da546Spatrick         m_coff_header_opt.header_size = m_data.GetU32(offset_ptr);
638061da546Spatrick         m_coff_header_opt.checksum = m_data.GetU32(offset_ptr);
639061da546Spatrick         m_coff_header_opt.subsystem = m_data.GetU16(offset_ptr);
640061da546Spatrick         m_coff_header_opt.dll_flags = m_data.GetU16(offset_ptr);
641061da546Spatrick         m_coff_header_opt.stack_reserve_size =
642061da546Spatrick             m_data.GetMaxU64(offset_ptr, addr_byte_size);
643061da546Spatrick         m_coff_header_opt.stack_commit_size =
644061da546Spatrick             m_data.GetMaxU64(offset_ptr, addr_byte_size);
645061da546Spatrick         m_coff_header_opt.heap_reserve_size =
646061da546Spatrick             m_data.GetMaxU64(offset_ptr, addr_byte_size);
647061da546Spatrick         m_coff_header_opt.heap_commit_size =
648061da546Spatrick             m_data.GetMaxU64(offset_ptr, addr_byte_size);
649061da546Spatrick         m_coff_header_opt.loader_flags = m_data.GetU32(offset_ptr);
650061da546Spatrick         uint32_t num_data_dir_entries = m_data.GetU32(offset_ptr);
651061da546Spatrick         m_coff_header_opt.data_dirs.clear();
652061da546Spatrick         m_coff_header_opt.data_dirs.resize(num_data_dir_entries);
653061da546Spatrick         uint32_t i;
654061da546Spatrick         for (i = 0; i < num_data_dir_entries; i++) {
655061da546Spatrick           m_coff_header_opt.data_dirs[i].vmaddr = m_data.GetU32(offset_ptr);
656061da546Spatrick           m_coff_header_opt.data_dirs[i].vmsize = m_data.GetU32(offset_ptr);
657061da546Spatrick         }
658061da546Spatrick 
659061da546Spatrick         m_image_base = m_coff_header_opt.image_base;
660061da546Spatrick       }
661061da546Spatrick     }
662061da546Spatrick   }
663061da546Spatrick   // Make sure we are on track for section data which follows
664061da546Spatrick   *offset_ptr = end_offset;
665061da546Spatrick   return success;
666061da546Spatrick }
667061da546Spatrick 
GetRVA(const Address & addr) const668061da546Spatrick uint32_t ObjectFilePECOFF::GetRVA(const Address &addr) const {
669061da546Spatrick   return addr.GetFileAddress() - m_image_base;
670061da546Spatrick }
671061da546Spatrick 
GetAddress(uint32_t rva)672061da546Spatrick Address ObjectFilePECOFF::GetAddress(uint32_t rva) {
673061da546Spatrick   SectionList *sect_list = GetSectionList();
674061da546Spatrick   if (!sect_list)
675061da546Spatrick     return Address(GetFileAddress(rva));
676061da546Spatrick 
677061da546Spatrick   return Address(GetFileAddress(rva), sect_list);
678061da546Spatrick }
679061da546Spatrick 
GetFileAddress(uint32_t rva) const680061da546Spatrick lldb::addr_t ObjectFilePECOFF::GetFileAddress(uint32_t rva) const {
681061da546Spatrick   return m_image_base + rva;
682061da546Spatrick }
683061da546Spatrick 
ReadImageData(uint32_t offset,size_t size)684061da546Spatrick DataExtractor ObjectFilePECOFF::ReadImageData(uint32_t offset, size_t size) {
685061da546Spatrick   if (!size)
686061da546Spatrick     return {};
687061da546Spatrick 
688dda28197Spatrick   if (m_data.ValidOffsetForDataOfSize(offset, size))
689dda28197Spatrick     return DataExtractor(m_data, offset, size);
690dda28197Spatrick 
691061da546Spatrick   ProcessSP process_sp(m_process_wp.lock());
692061da546Spatrick   DataExtractor data;
693061da546Spatrick   if (process_sp) {
694061da546Spatrick     auto data_up = std::make_unique<DataBufferHeap>(size, 0);
695061da546Spatrick     Status readmem_error;
696061da546Spatrick     size_t bytes_read =
697061da546Spatrick         process_sp->ReadMemory(m_image_base + offset, data_up->GetBytes(),
698061da546Spatrick                                data_up->GetByteSize(), readmem_error);
699061da546Spatrick     if (bytes_read == size) {
700061da546Spatrick       DataBufferSP buffer_sp(data_up.release());
701061da546Spatrick       data.SetData(buffer_sp, 0, buffer_sp->GetByteSize());
702061da546Spatrick     }
703061da546Spatrick   }
704061da546Spatrick   return data;
705061da546Spatrick }
706061da546Spatrick 
ReadImageDataByRVA(uint32_t rva,size_t size)707061da546Spatrick DataExtractor ObjectFilePECOFF::ReadImageDataByRVA(uint32_t rva, size_t size) {
708061da546Spatrick   Address addr = GetAddress(rva);
709061da546Spatrick   SectionSP sect = addr.GetSection();
710061da546Spatrick   if (!sect)
711061da546Spatrick     return {};
712061da546Spatrick   rva = sect->GetFileOffset() + addr.GetOffset();
713061da546Spatrick 
714061da546Spatrick   return ReadImageData(rva, size);
715061da546Spatrick }
716061da546Spatrick 
717061da546Spatrick // ParseSectionHeaders
ParseSectionHeaders(uint32_t section_header_data_offset)718061da546Spatrick bool ObjectFilePECOFF::ParseSectionHeaders(
719061da546Spatrick     uint32_t section_header_data_offset) {
720061da546Spatrick   const uint32_t nsects = m_coff_header.nsects;
721061da546Spatrick   m_sect_headers.clear();
722061da546Spatrick 
723061da546Spatrick   if (nsects > 0) {
724061da546Spatrick     const size_t section_header_byte_size = nsects * sizeof(section_header_t);
725061da546Spatrick     DataExtractor section_header_data =
726061da546Spatrick         ReadImageData(section_header_data_offset, section_header_byte_size);
727061da546Spatrick 
728061da546Spatrick     lldb::offset_t offset = 0;
729061da546Spatrick     if (section_header_data.ValidOffsetForDataOfSize(
730061da546Spatrick             offset, section_header_byte_size)) {
731061da546Spatrick       m_sect_headers.resize(nsects);
732061da546Spatrick 
733061da546Spatrick       for (uint32_t idx = 0; idx < nsects; ++idx) {
734061da546Spatrick         const void *name_data = section_header_data.GetData(&offset, 8);
735061da546Spatrick         if (name_data) {
736061da546Spatrick           memcpy(m_sect_headers[idx].name, name_data, 8);
737061da546Spatrick           m_sect_headers[idx].vmsize = section_header_data.GetU32(&offset);
738061da546Spatrick           m_sect_headers[idx].vmaddr = section_header_data.GetU32(&offset);
739061da546Spatrick           m_sect_headers[idx].size = section_header_data.GetU32(&offset);
740061da546Spatrick           m_sect_headers[idx].offset = section_header_data.GetU32(&offset);
741061da546Spatrick           m_sect_headers[idx].reloff = section_header_data.GetU32(&offset);
742061da546Spatrick           m_sect_headers[idx].lineoff = section_header_data.GetU32(&offset);
743061da546Spatrick           m_sect_headers[idx].nreloc = section_header_data.GetU16(&offset);
744061da546Spatrick           m_sect_headers[idx].nline = section_header_data.GetU16(&offset);
745061da546Spatrick           m_sect_headers[idx].flags = section_header_data.GetU32(&offset);
746061da546Spatrick         }
747061da546Spatrick       }
748061da546Spatrick     }
749061da546Spatrick   }
750061da546Spatrick 
751061da546Spatrick   return !m_sect_headers.empty();
752061da546Spatrick }
753061da546Spatrick 
GetSectionName(const section_header_t & sect)754061da546Spatrick llvm::StringRef ObjectFilePECOFF::GetSectionName(const section_header_t &sect) {
755*f6aab3d8Srobert   llvm::StringRef hdr_name(sect.name, std::size(sect.name));
756061da546Spatrick   hdr_name = hdr_name.split('\0').first;
757061da546Spatrick   if (hdr_name.consume_front("/")) {
758061da546Spatrick     lldb::offset_t stroff;
759061da546Spatrick     if (!to_integer(hdr_name, stroff, 10))
760061da546Spatrick       return "";
761061da546Spatrick     lldb::offset_t string_file_offset =
762061da546Spatrick         m_coff_header.symoff + (m_coff_header.nsyms * 18) + stroff;
763061da546Spatrick     if (const char *name = m_data.GetCStr(&string_file_offset))
764061da546Spatrick       return name;
765061da546Spatrick     return "";
766061da546Spatrick   }
767061da546Spatrick   return hdr_name;
768061da546Spatrick }
769061da546Spatrick 
ParseSymtab(Symtab & symtab)770*f6aab3d8Srobert void ObjectFilePECOFF::ParseSymtab(Symtab &symtab) {
771061da546Spatrick   SectionList *sect_list = GetSectionList();
772*f6aab3d8Srobert   rva_symbol_list_t sorted_exports = AppendFromExportTable(sect_list, symtab);
773*f6aab3d8Srobert   AppendFromCOFFSymbolTable(sect_list, symtab, sorted_exports);
774*f6aab3d8Srobert }
775061da546Spatrick 
RVASymbolListCompareRVA(const std::pair<uint32_t,uint32_t> & a,const std::pair<uint32_t,uint32_t> & b)776*f6aab3d8Srobert static bool RVASymbolListCompareRVA(const std::pair<uint32_t, uint32_t> &a,
777*f6aab3d8Srobert                                     const std::pair<uint32_t, uint32_t> &b) {
778*f6aab3d8Srobert   return a.first < b.first;
779*f6aab3d8Srobert }
780061da546Spatrick 
AppendFromCOFFSymbolTable(SectionList * sect_list,Symtab & symtab,const ObjectFilePECOFF::rva_symbol_list_t & sorted_exports)781*f6aab3d8Srobert void ObjectFilePECOFF::AppendFromCOFFSymbolTable(
782*f6aab3d8Srobert     SectionList *sect_list, Symtab &symtab,
783*f6aab3d8Srobert     const ObjectFilePECOFF::rva_symbol_list_t &sorted_exports) {
784*f6aab3d8Srobert   const uint32_t num_syms = m_binary->getNumberOfSymbols();
785*f6aab3d8Srobert   if (num_syms == 0)
786*f6aab3d8Srobert     return;
787*f6aab3d8Srobert   // Check that this is not a bigobj; we do not support bigobj.
788*f6aab3d8Srobert   if (m_binary->getSymbolTableEntrySize() !=
789*f6aab3d8Srobert       sizeof(llvm::object::coff_symbol16))
790*f6aab3d8Srobert     return;
791061da546Spatrick 
792*f6aab3d8Srobert   Log *log = GetLog(LLDBLog::Object);
793*f6aab3d8Srobert   symtab.Reserve(symtab.GetNumSymbols() + num_syms);
794*f6aab3d8Srobert   for (const auto &sym_ref : m_binary->symbols()) {
795*f6aab3d8Srobert     const auto coff_sym_ref = m_binary->getCOFFSymbol(sym_ref);
796*f6aab3d8Srobert     auto name_or_error = sym_ref.getName();
797*f6aab3d8Srobert     if (auto err = name_or_error.takeError()) {
798*f6aab3d8Srobert       LLDB_LOG(log,
799*f6aab3d8Srobert                "ObjectFilePECOFF::AppendFromCOFFSymbolTable - failed to get "
800*f6aab3d8Srobert                "symbol table entry name: {0}",
801*f6aab3d8Srobert                llvm::fmt_consume(std::move(err)));
802*f6aab3d8Srobert       continue;
803*f6aab3d8Srobert     }
804*f6aab3d8Srobert     const llvm::StringRef sym_name = *name_or_error;
805*f6aab3d8Srobert     Symbol symbol;
806*f6aab3d8Srobert     symbol.GetMangled().SetValue(ConstString(sym_name));
807*f6aab3d8Srobert     int16_t section_number =
808*f6aab3d8Srobert         static_cast<int16_t>(coff_sym_ref.getSectionNumber());
809*f6aab3d8Srobert     if (section_number >= 1) {
810*f6aab3d8Srobert       symbol.GetAddressRef() = Address(
811*f6aab3d8Srobert           sect_list->FindSectionByID(section_number), coff_sym_ref.getValue());
812*f6aab3d8Srobert       const auto symbol_type = MapSymbolType(coff_sym_ref.getType());
813*f6aab3d8Srobert       symbol.SetType(symbol_type);
814*f6aab3d8Srobert 
815*f6aab3d8Srobert       // Check for duplicate of exported symbols:
816*f6aab3d8Srobert       const uint32_t symbol_rva = symbol.GetAddressRef().GetFileAddress() -
817*f6aab3d8Srobert                                   m_coff_header_opt.image_base;
818*f6aab3d8Srobert       const auto &first_match = std::lower_bound(
819*f6aab3d8Srobert           sorted_exports.begin(), sorted_exports.end(),
820*f6aab3d8Srobert           std::make_pair(symbol_rva, 0), RVASymbolListCompareRVA);
821*f6aab3d8Srobert       for (auto it = first_match;
822*f6aab3d8Srobert            it != sorted_exports.end() && it->first == symbol_rva; ++it) {
823*f6aab3d8Srobert         Symbol *exported = symtab.SymbolAtIndex(it->second);
824*f6aab3d8Srobert         if (symbol_type != lldb::eSymbolTypeInvalid)
825*f6aab3d8Srobert           exported->SetType(symbol_type);
826*f6aab3d8Srobert         if (exported->GetMangled() == symbol.GetMangled()) {
827*f6aab3d8Srobert           symbol.SetExternal(true);
828*f6aab3d8Srobert           // We don't want the symbol to be duplicated (e.g. when running
829*f6aab3d8Srobert           // `disas -n func`), but we also don't want to erase this entry (to
830*f6aab3d8Srobert           // preserve the original symbol order), so we mark it as additional.
831*f6aab3d8Srobert           symbol.SetType(lldb::eSymbolTypeAdditional);
832061da546Spatrick         } else {
833*f6aab3d8Srobert           // It is possible for a symbol to be exported in a different name
834*f6aab3d8Srobert           // from its original. In this case keep both entries so lookup using
835*f6aab3d8Srobert           // either names will work. If this symbol has an invalid type, replace
836*f6aab3d8Srobert           // it with the type from the export symbol.
837*f6aab3d8Srobert           if (symbol.GetType() == lldb::eSymbolTypeInvalid)
838*f6aab3d8Srobert             symbol.SetType(exported->GetType());
839061da546Spatrick         }
840061da546Spatrick       }
841*f6aab3d8Srobert     } else if (section_number == llvm::COFF::IMAGE_SYM_ABSOLUTE) {
842*f6aab3d8Srobert       symbol.GetAddressRef() = Address(coff_sym_ref.getValue());
843*f6aab3d8Srobert       symbol.SetType(lldb::eSymbolTypeAbsolute);
844*f6aab3d8Srobert     }
845*f6aab3d8Srobert     symtab.AddSymbol(symbol);
846061da546Spatrick   }
847061da546Spatrick }
848061da546Spatrick 
849*f6aab3d8Srobert ObjectFilePECOFF::rva_symbol_list_t
AppendFromExportTable(SectionList * sect_list,Symtab & symtab)850*f6aab3d8Srobert ObjectFilePECOFF::AppendFromExportTable(SectionList *sect_list,
851*f6aab3d8Srobert                                         Symtab &symtab) {
852*f6aab3d8Srobert   const auto *export_table = m_binary->getExportTable();
853*f6aab3d8Srobert   if (!export_table)
854*f6aab3d8Srobert     return {};
855*f6aab3d8Srobert   const uint32_t num_syms = export_table->AddressTableEntries;
856*f6aab3d8Srobert   if (num_syms == 0)
857*f6aab3d8Srobert     return {};
858061da546Spatrick 
859*f6aab3d8Srobert   Log *log = GetLog(LLDBLog::Object);
860*f6aab3d8Srobert   rva_symbol_list_t export_list;
861*f6aab3d8Srobert   symtab.Reserve(symtab.GetNumSymbols() + num_syms);
862*f6aab3d8Srobert   // Read each export table entry, ordered by ordinal instead of by name.
863*f6aab3d8Srobert   for (const auto &entry : m_binary->export_directories()) {
864*f6aab3d8Srobert     llvm::StringRef sym_name;
865*f6aab3d8Srobert     if (auto err = entry.getSymbolName(sym_name)) {
866*f6aab3d8Srobert       LLDB_LOG(log,
867*f6aab3d8Srobert                "ObjectFilePECOFF::AppendFromExportTable - failed to get export "
868*f6aab3d8Srobert                "table entry name: {0}",
869*f6aab3d8Srobert                llvm::fmt_consume(std::move(err)));
870*f6aab3d8Srobert       continue;
871061da546Spatrick     }
872*f6aab3d8Srobert     Symbol symbol;
873*f6aab3d8Srobert     // Note: symbol name may be empty if it is only exported by ordinal.
874*f6aab3d8Srobert     symbol.GetMangled().SetValue(ConstString(sym_name));
875*f6aab3d8Srobert 
876*f6aab3d8Srobert     uint32_t ordinal;
877*f6aab3d8Srobert     llvm::cantFail(entry.getOrdinal(ordinal));
878*f6aab3d8Srobert     symbol.SetID(ordinal);
879*f6aab3d8Srobert 
880*f6aab3d8Srobert     bool is_forwarder;
881*f6aab3d8Srobert     llvm::cantFail(entry.isForwarder(is_forwarder));
882*f6aab3d8Srobert     if (is_forwarder) {
883*f6aab3d8Srobert       // Forwarder exports are redirected by the loader transparently, but keep
884*f6aab3d8Srobert       // it in symtab and make a note using the symbol name.
885*f6aab3d8Srobert       llvm::StringRef forwarder_name;
886*f6aab3d8Srobert       if (auto err = entry.getForwardTo(forwarder_name)) {
887*f6aab3d8Srobert         LLDB_LOG(log,
888*f6aab3d8Srobert                  "ObjectFilePECOFF::AppendFromExportTable - failed to get "
889*f6aab3d8Srobert                  "forwarder name of forwarder export '{0}': {1}",
890*f6aab3d8Srobert                  sym_name, llvm::fmt_consume(std::move(err)));
891*f6aab3d8Srobert         continue;
892061da546Spatrick       }
893*f6aab3d8Srobert       llvm::SmallString<256> new_name = {symbol.GetDisplayName().GetStringRef(),
894*f6aab3d8Srobert                                          " (forwarded to ", forwarder_name,
895*f6aab3d8Srobert                                          ")"};
896*f6aab3d8Srobert       symbol.GetMangled().SetDemangledName(ConstString(new_name.str()));
897*f6aab3d8Srobert       symbol.SetDemangledNameIsSynthesized(true);
898061da546Spatrick     }
899*f6aab3d8Srobert 
900*f6aab3d8Srobert     uint32_t function_rva;
901*f6aab3d8Srobert     if (auto err = entry.getExportRVA(function_rva)) {
902*f6aab3d8Srobert       LLDB_LOG(log,
903*f6aab3d8Srobert                "ObjectFilePECOFF::AppendFromExportTable - failed to get "
904*f6aab3d8Srobert                "address of export entry '{0}': {1}",
905*f6aab3d8Srobert                sym_name, llvm::fmt_consume(std::move(err)));
906*f6aab3d8Srobert       continue;
907061da546Spatrick     }
908*f6aab3d8Srobert     // Skip the symbol if it doesn't look valid.
909*f6aab3d8Srobert     if (function_rva == 0 && sym_name.empty())
910*f6aab3d8Srobert       continue;
911*f6aab3d8Srobert     symbol.GetAddressRef() =
912*f6aab3d8Srobert         Address(m_coff_header_opt.image_base + function_rva, sect_list);
913*f6aab3d8Srobert 
914*f6aab3d8Srobert     // An exported symbol may be either code or data. Guess by checking whether
915*f6aab3d8Srobert     // the section containing the symbol is executable.
916*f6aab3d8Srobert     symbol.SetType(lldb::eSymbolTypeData);
917*f6aab3d8Srobert     if (!is_forwarder)
918*f6aab3d8Srobert       if (auto section_sp = symbol.GetAddressRef().GetSection())
919*f6aab3d8Srobert         if (section_sp->GetPermissions() & ePermissionsExecutable)
920*f6aab3d8Srobert           symbol.SetType(lldb::eSymbolTypeCode);
921*f6aab3d8Srobert     symbol.SetExternal(true);
922*f6aab3d8Srobert     uint32_t idx = symtab.AddSymbol(symbol);
923*f6aab3d8Srobert     export_list.push_back(std::make_pair(function_rva, idx));
924*f6aab3d8Srobert   }
925*f6aab3d8Srobert   std::stable_sort(export_list.begin(), export_list.end(),
926*f6aab3d8Srobert                    RVASymbolListCompareRVA);
927*f6aab3d8Srobert   return export_list;
928061da546Spatrick }
929061da546Spatrick 
CreateCallFrameInfo()930061da546Spatrick std::unique_ptr<CallFrameInfo> ObjectFilePECOFF::CreateCallFrameInfo() {
931*f6aab3d8Srobert   if (llvm::COFF::EXCEPTION_TABLE >= m_coff_header_opt.data_dirs.size())
932061da546Spatrick     return {};
933061da546Spatrick 
934061da546Spatrick   data_directory data_dir_exception =
935*f6aab3d8Srobert       m_coff_header_opt.data_dirs[llvm::COFF::EXCEPTION_TABLE];
936061da546Spatrick   if (!data_dir_exception.vmaddr)
937061da546Spatrick     return {};
938061da546Spatrick 
939053af629Spatrick   if (m_coff_header.machine != llvm::COFF::IMAGE_FILE_MACHINE_AMD64)
940053af629Spatrick     return {};
941053af629Spatrick 
942061da546Spatrick   return std::make_unique<PECallFrameInfo>(*this, data_dir_exception.vmaddr,
943061da546Spatrick                                            data_dir_exception.vmsize);
944061da546Spatrick }
945061da546Spatrick 
IsStripped()946061da546Spatrick bool ObjectFilePECOFF::IsStripped() {
947061da546Spatrick   // TODO: determine this for COFF
948061da546Spatrick   return false;
949061da546Spatrick }
950061da546Spatrick 
GetSectionType(llvm::StringRef sect_name,const section_header_t & sect)951061da546Spatrick SectionType ObjectFilePECOFF::GetSectionType(llvm::StringRef sect_name,
952061da546Spatrick                                              const section_header_t &sect) {
953061da546Spatrick   ConstString const_sect_name(sect_name);
954061da546Spatrick   static ConstString g_code_sect_name(".code");
955061da546Spatrick   static ConstString g_CODE_sect_name("CODE");
956061da546Spatrick   static ConstString g_data_sect_name(".data");
957061da546Spatrick   static ConstString g_DATA_sect_name("DATA");
958061da546Spatrick   static ConstString g_bss_sect_name(".bss");
959061da546Spatrick   static ConstString g_BSS_sect_name("BSS");
960061da546Spatrick 
961061da546Spatrick   if (sect.flags & llvm::COFF::IMAGE_SCN_CNT_CODE &&
962061da546Spatrick       ((const_sect_name == g_code_sect_name) ||
963061da546Spatrick        (const_sect_name == g_CODE_sect_name))) {
964061da546Spatrick     return eSectionTypeCode;
965061da546Spatrick   }
966061da546Spatrick   if (sect.flags & llvm::COFF::IMAGE_SCN_CNT_INITIALIZED_DATA &&
967061da546Spatrick              ((const_sect_name == g_data_sect_name) ||
968061da546Spatrick               (const_sect_name == g_DATA_sect_name))) {
969061da546Spatrick     if (sect.size == 0 && sect.offset == 0)
970061da546Spatrick       return eSectionTypeZeroFill;
971061da546Spatrick     else
972061da546Spatrick       return eSectionTypeData;
973061da546Spatrick   }
974061da546Spatrick   if (sect.flags & llvm::COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA &&
975061da546Spatrick              ((const_sect_name == g_bss_sect_name) ||
976061da546Spatrick               (const_sect_name == g_BSS_sect_name))) {
977061da546Spatrick     if (sect.size == 0)
978061da546Spatrick       return eSectionTypeZeroFill;
979061da546Spatrick     else
980061da546Spatrick       return eSectionTypeData;
981061da546Spatrick   }
982061da546Spatrick 
983061da546Spatrick   SectionType section_type =
984061da546Spatrick       llvm::StringSwitch<SectionType>(sect_name)
985061da546Spatrick           .Case(".debug", eSectionTypeDebug)
986061da546Spatrick           .Case(".stabstr", eSectionTypeDataCString)
987061da546Spatrick           .Case(".reloc", eSectionTypeOther)
988061da546Spatrick           .Case(".debug_abbrev", eSectionTypeDWARFDebugAbbrev)
989061da546Spatrick           .Case(".debug_aranges", eSectionTypeDWARFDebugAranges)
990061da546Spatrick           .Case(".debug_frame", eSectionTypeDWARFDebugFrame)
991061da546Spatrick           .Case(".debug_info", eSectionTypeDWARFDebugInfo)
992061da546Spatrick           .Case(".debug_line", eSectionTypeDWARFDebugLine)
993061da546Spatrick           .Case(".debug_loc", eSectionTypeDWARFDebugLoc)
994061da546Spatrick           .Case(".debug_loclists", eSectionTypeDWARFDebugLocLists)
995061da546Spatrick           .Case(".debug_macinfo", eSectionTypeDWARFDebugMacInfo)
996061da546Spatrick           .Case(".debug_names", eSectionTypeDWARFDebugNames)
997061da546Spatrick           .Case(".debug_pubnames", eSectionTypeDWARFDebugPubNames)
998061da546Spatrick           .Case(".debug_pubtypes", eSectionTypeDWARFDebugPubTypes)
999061da546Spatrick           .Case(".debug_ranges", eSectionTypeDWARFDebugRanges)
1000061da546Spatrick           .Case(".debug_str", eSectionTypeDWARFDebugStr)
1001061da546Spatrick           .Case(".debug_types", eSectionTypeDWARFDebugTypes)
1002061da546Spatrick           // .eh_frame can be truncated to 8 chars.
1003061da546Spatrick           .Cases(".eh_frame", ".eh_fram", eSectionTypeEHFrame)
1004061da546Spatrick           .Case(".gosymtab", eSectionTypeGoSymtab)
1005061da546Spatrick           .Default(eSectionTypeInvalid);
1006061da546Spatrick   if (section_type != eSectionTypeInvalid)
1007061da546Spatrick     return section_type;
1008061da546Spatrick 
1009061da546Spatrick   if (sect.flags & llvm::COFF::IMAGE_SCN_CNT_CODE)
1010061da546Spatrick     return eSectionTypeCode;
1011061da546Spatrick   if (sect.flags & llvm::COFF::IMAGE_SCN_CNT_INITIALIZED_DATA)
1012061da546Spatrick     return eSectionTypeData;
1013061da546Spatrick   if (sect.flags & llvm::COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA) {
1014061da546Spatrick     if (sect.size == 0)
1015061da546Spatrick       return eSectionTypeZeroFill;
1016061da546Spatrick     else
1017061da546Spatrick       return eSectionTypeData;
1018061da546Spatrick   }
1019061da546Spatrick   return eSectionTypeOther;
1020061da546Spatrick }
1021061da546Spatrick 
CreateSections(SectionList & unified_section_list)1022061da546Spatrick void ObjectFilePECOFF::CreateSections(SectionList &unified_section_list) {
1023061da546Spatrick   if (m_sections_up)
1024061da546Spatrick     return;
1025dda28197Spatrick   m_sections_up = std::make_unique<SectionList>();
1026061da546Spatrick   ModuleSP module_sp(GetModule());
1027061da546Spatrick   if (module_sp) {
1028061da546Spatrick     std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex());
1029061da546Spatrick 
1030061da546Spatrick     SectionSP header_sp = std::make_shared<Section>(
1031061da546Spatrick         module_sp, this, ~user_id_t(0), ConstString("PECOFF header"),
1032061da546Spatrick         eSectionTypeOther, m_coff_header_opt.image_base,
1033061da546Spatrick         m_coff_header_opt.header_size,
1034061da546Spatrick         /*file_offset*/ 0, m_coff_header_opt.header_size,
1035061da546Spatrick         m_coff_header_opt.sect_alignment,
1036061da546Spatrick         /*flags*/ 0);
1037061da546Spatrick     header_sp->SetPermissions(ePermissionsReadable);
1038061da546Spatrick     m_sections_up->AddSection(header_sp);
1039061da546Spatrick     unified_section_list.AddSection(header_sp);
1040061da546Spatrick 
1041061da546Spatrick     const uint32_t nsects = m_sect_headers.size();
1042061da546Spatrick     ModuleSP module_sp(GetModule());
1043061da546Spatrick     for (uint32_t idx = 0; idx < nsects; ++idx) {
1044061da546Spatrick       llvm::StringRef sect_name = GetSectionName(m_sect_headers[idx]);
1045061da546Spatrick       ConstString const_sect_name(sect_name);
1046061da546Spatrick       SectionType section_type = GetSectionType(sect_name, m_sect_headers[idx]);
1047061da546Spatrick 
1048061da546Spatrick       SectionSP section_sp(new Section(
1049061da546Spatrick           module_sp,       // Module to which this section belongs
1050061da546Spatrick           this,            // Object file to which this section belongs
1051061da546Spatrick           idx + 1,         // Section ID is the 1 based section index.
1052061da546Spatrick           const_sect_name, // Name of this section
1053061da546Spatrick           section_type,
1054061da546Spatrick           m_coff_header_opt.image_base +
1055061da546Spatrick               m_sect_headers[idx].vmaddr, // File VM address == addresses as
1056061da546Spatrick                                           // they are found in the object file
1057061da546Spatrick           m_sect_headers[idx].vmsize,     // VM size in bytes of this section
1058061da546Spatrick           m_sect_headers[idx]
1059061da546Spatrick               .offset, // Offset to the data for this section in the file
1060061da546Spatrick           m_sect_headers[idx]
1061061da546Spatrick               .size, // Size in bytes of this section as found in the file
1062061da546Spatrick           m_coff_header_opt.sect_alignment, // Section alignment
1063061da546Spatrick           m_sect_headers[idx].flags));      // Flags for this section
1064061da546Spatrick 
1065061da546Spatrick       uint32_t permissions = 0;
1066061da546Spatrick       if (m_sect_headers[idx].flags & llvm::COFF::IMAGE_SCN_MEM_EXECUTE)
1067061da546Spatrick         permissions |= ePermissionsExecutable;
1068061da546Spatrick       if (m_sect_headers[idx].flags & llvm::COFF::IMAGE_SCN_MEM_READ)
1069061da546Spatrick         permissions |= ePermissionsReadable;
1070061da546Spatrick       if (m_sect_headers[idx].flags & llvm::COFF::IMAGE_SCN_MEM_WRITE)
1071061da546Spatrick         permissions |= ePermissionsWritable;
1072061da546Spatrick       section_sp->SetPermissions(permissions);
1073061da546Spatrick 
1074061da546Spatrick       m_sections_up->AddSection(section_sp);
1075061da546Spatrick       unified_section_list.AddSection(section_sp);
1076061da546Spatrick     }
1077061da546Spatrick   }
1078061da546Spatrick }
1079061da546Spatrick 
GetUUID()1080061da546Spatrick UUID ObjectFilePECOFF::GetUUID() {
1081061da546Spatrick   if (m_uuid.IsValid())
1082061da546Spatrick     return m_uuid;
1083061da546Spatrick 
1084061da546Spatrick   if (!CreateBinary())
1085061da546Spatrick     return UUID();
1086061da546Spatrick 
1087dda28197Spatrick   m_uuid = GetCoffUUID(*m_binary);
1088061da546Spatrick   return m_uuid;
1089061da546Spatrick }
1090061da546Spatrick 
GetDebugLink()1091*f6aab3d8Srobert std::optional<FileSpec> ObjectFilePECOFF::GetDebugLink() {
1092*f6aab3d8Srobert   std::string gnu_debuglink_file;
1093*f6aab3d8Srobert   uint32_t gnu_debuglink_crc;
1094*f6aab3d8Srobert   if (GetDebugLinkContents(*m_binary, gnu_debuglink_file, gnu_debuglink_crc))
1095*f6aab3d8Srobert     return FileSpec(gnu_debuglink_file);
1096*f6aab3d8Srobert   return std::nullopt;
1097*f6aab3d8Srobert }
1098*f6aab3d8Srobert 
ParseDependentModules()1099061da546Spatrick uint32_t ObjectFilePECOFF::ParseDependentModules() {
1100061da546Spatrick   ModuleSP module_sp(GetModule());
1101061da546Spatrick   if (!module_sp)
1102061da546Spatrick     return 0;
1103061da546Spatrick 
1104061da546Spatrick   std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex());
1105061da546Spatrick   if (m_deps_filespec)
1106061da546Spatrick     return m_deps_filespec->GetSize();
1107061da546Spatrick 
1108061da546Spatrick   // Cache coff binary if it is not done yet.
1109061da546Spatrick   if (!CreateBinary())
1110061da546Spatrick     return 0;
1111061da546Spatrick 
1112*f6aab3d8Srobert   Log *log = GetLog(LLDBLog::Object);
1113dda28197Spatrick   LLDB_LOG(log, "this = {0}, module = {1} ({2}), file = {3}, binary = {4}",
1114dda28197Spatrick            this, GetModule().get(), GetModule()->GetSpecificationDescription(),
1115dda28197Spatrick            m_file.GetPath(), m_binary.get());
1116061da546Spatrick 
1117061da546Spatrick   m_deps_filespec = FileSpecList();
1118061da546Spatrick 
1119dda28197Spatrick   for (const auto &entry : m_binary->import_directories()) {
1120061da546Spatrick     llvm::StringRef dll_name;
1121061da546Spatrick     // Report a bogus entry.
1122dda28197Spatrick     if (llvm::Error e = entry.getName(dll_name)) {
1123061da546Spatrick       LLDB_LOGF(log,
1124061da546Spatrick                 "ObjectFilePECOFF::ParseDependentModules() - failed to get "
1125061da546Spatrick                 "import directory entry name: %s",
1126dda28197Spatrick                 llvm::toString(std::move(e)).c_str());
1127061da546Spatrick       continue;
1128061da546Spatrick     }
1129061da546Spatrick 
1130061da546Spatrick     // At this moment we only have the base name of the DLL. The full path can
1131061da546Spatrick     // only be seen after the dynamic loading.  Our best guess is Try to get it
1132061da546Spatrick     // with the help of the object file's directory.
1133061da546Spatrick     llvm::SmallString<128> dll_fullpath;
1134061da546Spatrick     FileSpec dll_specs(dll_name);
1135*f6aab3d8Srobert     dll_specs.SetDirectory(m_file.GetDirectory());
1136061da546Spatrick 
1137061da546Spatrick     if (!llvm::sys::fs::real_path(dll_specs.GetPath(), dll_fullpath))
1138061da546Spatrick       m_deps_filespec->EmplaceBack(dll_fullpath);
1139061da546Spatrick     else {
1140061da546Spatrick       // Known DLLs or DLL not found in the object file directory.
1141061da546Spatrick       m_deps_filespec->EmplaceBack(dll_name);
1142061da546Spatrick     }
1143061da546Spatrick   }
1144061da546Spatrick   return m_deps_filespec->GetSize();
1145061da546Spatrick }
1146061da546Spatrick 
GetDependentModules(FileSpecList & files)1147061da546Spatrick uint32_t ObjectFilePECOFF::GetDependentModules(FileSpecList &files) {
1148061da546Spatrick   auto num_modules = ParseDependentModules();
1149061da546Spatrick   auto original_size = files.GetSize();
1150061da546Spatrick 
1151061da546Spatrick   for (unsigned i = 0; i < num_modules; ++i)
1152061da546Spatrick     files.AppendIfUnique(m_deps_filespec->GetFileSpecAtIndex(i));
1153061da546Spatrick 
1154061da546Spatrick   return files.GetSize() - original_size;
1155061da546Spatrick }
1156061da546Spatrick 
GetEntryPointAddress()1157061da546Spatrick lldb_private::Address ObjectFilePECOFF::GetEntryPointAddress() {
1158061da546Spatrick   if (m_entry_point_address.IsValid())
1159061da546Spatrick     return m_entry_point_address;
1160061da546Spatrick 
1161061da546Spatrick   if (!ParseHeader() || !IsExecutable())
1162061da546Spatrick     return m_entry_point_address;
1163061da546Spatrick 
1164061da546Spatrick   SectionList *section_list = GetSectionList();
1165061da546Spatrick   addr_t file_addr = m_coff_header_opt.entry + m_coff_header_opt.image_base;
1166061da546Spatrick 
1167061da546Spatrick   if (!section_list)
1168061da546Spatrick     m_entry_point_address.SetOffset(file_addr);
1169061da546Spatrick   else
1170061da546Spatrick     m_entry_point_address.ResolveAddressUsingFileSections(file_addr,
1171061da546Spatrick                                                           section_list);
1172061da546Spatrick   return m_entry_point_address;
1173061da546Spatrick }
1174061da546Spatrick 
GetBaseAddress()1175061da546Spatrick Address ObjectFilePECOFF::GetBaseAddress() {
1176061da546Spatrick   return Address(GetSectionList()->GetSectionAtIndex(0), 0);
1177061da546Spatrick }
1178061da546Spatrick 
1179061da546Spatrick // Dump
1180061da546Spatrick //
1181061da546Spatrick // Dump the specifics of the runtime file container (such as any headers
1182061da546Spatrick // segments, sections, etc).
Dump(Stream * s)1183061da546Spatrick void ObjectFilePECOFF::Dump(Stream *s) {
1184061da546Spatrick   ModuleSP module_sp(GetModule());
1185061da546Spatrick   if (module_sp) {
1186061da546Spatrick     std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex());
1187061da546Spatrick     s->Printf("%p: ", static_cast<void *>(this));
1188061da546Spatrick     s->Indent();
1189061da546Spatrick     s->PutCString("ObjectFilePECOFF");
1190061da546Spatrick 
1191061da546Spatrick     ArchSpec header_arch = GetArchitecture();
1192061da546Spatrick 
1193061da546Spatrick     *s << ", file = '" << m_file
1194061da546Spatrick        << "', arch = " << header_arch.GetArchitectureName() << "\n";
1195061da546Spatrick 
1196061da546Spatrick     SectionList *sections = GetSectionList();
1197061da546Spatrick     if (sections)
1198dda28197Spatrick       sections->Dump(s->AsRawOstream(), s->GetIndentLevel(), nullptr, true,
1199dda28197Spatrick                      UINT32_MAX);
1200061da546Spatrick 
1201061da546Spatrick     if (m_symtab_up)
1202061da546Spatrick       m_symtab_up->Dump(s, nullptr, eSortOrderNone);
1203061da546Spatrick 
1204061da546Spatrick     if (m_dos_header.e_magic)
1205061da546Spatrick       DumpDOSHeader(s, m_dos_header);
1206061da546Spatrick     if (m_coff_header.machine) {
1207061da546Spatrick       DumpCOFFHeader(s, m_coff_header);
1208061da546Spatrick       if (m_coff_header.hdrsize)
1209061da546Spatrick         DumpOptCOFFHeader(s, m_coff_header_opt);
1210061da546Spatrick     }
1211061da546Spatrick     s->EOL();
1212061da546Spatrick     DumpSectionHeaders(s);
1213061da546Spatrick     s->EOL();
1214061da546Spatrick 
1215061da546Spatrick     DumpDependentModules(s);
1216061da546Spatrick     s->EOL();
1217061da546Spatrick   }
1218061da546Spatrick }
1219061da546Spatrick 
1220061da546Spatrick // DumpDOSHeader
1221061da546Spatrick //
1222061da546Spatrick // Dump the MS-DOS header to the specified output stream
DumpDOSHeader(Stream * s,const dos_header_t & header)1223061da546Spatrick void ObjectFilePECOFF::DumpDOSHeader(Stream *s, const dos_header_t &header) {
1224061da546Spatrick   s->PutCString("MSDOS Header\n");
1225061da546Spatrick   s->Printf("  e_magic    = 0x%4.4x\n", header.e_magic);
1226061da546Spatrick   s->Printf("  e_cblp     = 0x%4.4x\n", header.e_cblp);
1227061da546Spatrick   s->Printf("  e_cp       = 0x%4.4x\n", header.e_cp);
1228061da546Spatrick   s->Printf("  e_crlc     = 0x%4.4x\n", header.e_crlc);
1229061da546Spatrick   s->Printf("  e_cparhdr  = 0x%4.4x\n", header.e_cparhdr);
1230061da546Spatrick   s->Printf("  e_minalloc = 0x%4.4x\n", header.e_minalloc);
1231061da546Spatrick   s->Printf("  e_maxalloc = 0x%4.4x\n", header.e_maxalloc);
1232061da546Spatrick   s->Printf("  e_ss       = 0x%4.4x\n", header.e_ss);
1233061da546Spatrick   s->Printf("  e_sp       = 0x%4.4x\n", header.e_sp);
1234061da546Spatrick   s->Printf("  e_csum     = 0x%4.4x\n", header.e_csum);
1235061da546Spatrick   s->Printf("  e_ip       = 0x%4.4x\n", header.e_ip);
1236061da546Spatrick   s->Printf("  e_cs       = 0x%4.4x\n", header.e_cs);
1237061da546Spatrick   s->Printf("  e_lfarlc   = 0x%4.4x\n", header.e_lfarlc);
1238061da546Spatrick   s->Printf("  e_ovno     = 0x%4.4x\n", header.e_ovno);
1239061da546Spatrick   s->Printf("  e_res[4]   = { 0x%4.4x, 0x%4.4x, 0x%4.4x, 0x%4.4x }\n",
1240061da546Spatrick             header.e_res[0], header.e_res[1], header.e_res[2], header.e_res[3]);
1241061da546Spatrick   s->Printf("  e_oemid    = 0x%4.4x\n", header.e_oemid);
1242061da546Spatrick   s->Printf("  e_oeminfo  = 0x%4.4x\n", header.e_oeminfo);
1243061da546Spatrick   s->Printf("  e_res2[10] = { 0x%4.4x, 0x%4.4x, 0x%4.4x, 0x%4.4x, 0x%4.4x, "
1244061da546Spatrick             "0x%4.4x, 0x%4.4x, 0x%4.4x, 0x%4.4x, 0x%4.4x }\n",
1245061da546Spatrick             header.e_res2[0], header.e_res2[1], header.e_res2[2],
1246061da546Spatrick             header.e_res2[3], header.e_res2[4], header.e_res2[5],
1247061da546Spatrick             header.e_res2[6], header.e_res2[7], header.e_res2[8],
1248061da546Spatrick             header.e_res2[9]);
1249061da546Spatrick   s->Printf("  e_lfanew   = 0x%8.8x\n", header.e_lfanew);
1250061da546Spatrick }
1251061da546Spatrick 
1252061da546Spatrick // DumpCOFFHeader
1253061da546Spatrick //
1254061da546Spatrick // Dump the COFF header to the specified output stream
DumpCOFFHeader(Stream * s,const coff_header_t & header)1255061da546Spatrick void ObjectFilePECOFF::DumpCOFFHeader(Stream *s, const coff_header_t &header) {
1256061da546Spatrick   s->PutCString("COFF Header\n");
1257061da546Spatrick   s->Printf("  machine = 0x%4.4x\n", header.machine);
1258061da546Spatrick   s->Printf("  nsects  = 0x%4.4x\n", header.nsects);
1259061da546Spatrick   s->Printf("  modtime = 0x%8.8x\n", header.modtime);
1260061da546Spatrick   s->Printf("  symoff  = 0x%8.8x\n", header.symoff);
1261061da546Spatrick   s->Printf("  nsyms   = 0x%8.8x\n", header.nsyms);
1262061da546Spatrick   s->Printf("  hdrsize = 0x%4.4x\n", header.hdrsize);
1263061da546Spatrick }
1264061da546Spatrick 
1265061da546Spatrick // DumpOptCOFFHeader
1266061da546Spatrick //
1267061da546Spatrick // Dump the optional COFF header to the specified output stream
DumpOptCOFFHeader(Stream * s,const coff_opt_header_t & header)1268061da546Spatrick void ObjectFilePECOFF::DumpOptCOFFHeader(Stream *s,
1269061da546Spatrick                                          const coff_opt_header_t &header) {
1270061da546Spatrick   s->PutCString("Optional COFF Header\n");
1271061da546Spatrick   s->Printf("  magic                   = 0x%4.4x\n", header.magic);
1272061da546Spatrick   s->Printf("  major_linker_version    = 0x%2.2x\n",
1273061da546Spatrick             header.major_linker_version);
1274061da546Spatrick   s->Printf("  minor_linker_version    = 0x%2.2x\n",
1275061da546Spatrick             header.minor_linker_version);
1276061da546Spatrick   s->Printf("  code_size               = 0x%8.8x\n", header.code_size);
1277061da546Spatrick   s->Printf("  data_size               = 0x%8.8x\n", header.data_size);
1278061da546Spatrick   s->Printf("  bss_size                = 0x%8.8x\n", header.bss_size);
1279061da546Spatrick   s->Printf("  entry                   = 0x%8.8x\n", header.entry);
1280061da546Spatrick   s->Printf("  code_offset             = 0x%8.8x\n", header.code_offset);
1281061da546Spatrick   s->Printf("  data_offset             = 0x%8.8x\n", header.data_offset);
1282061da546Spatrick   s->Printf("  image_base              = 0x%16.16" PRIx64 "\n",
1283061da546Spatrick             header.image_base);
1284061da546Spatrick   s->Printf("  sect_alignment          = 0x%8.8x\n", header.sect_alignment);
1285061da546Spatrick   s->Printf("  file_alignment          = 0x%8.8x\n", header.file_alignment);
1286061da546Spatrick   s->Printf("  major_os_system_version = 0x%4.4x\n",
1287061da546Spatrick             header.major_os_system_version);
1288061da546Spatrick   s->Printf("  minor_os_system_version = 0x%4.4x\n",
1289061da546Spatrick             header.minor_os_system_version);
1290061da546Spatrick   s->Printf("  major_image_version     = 0x%4.4x\n",
1291061da546Spatrick             header.major_image_version);
1292061da546Spatrick   s->Printf("  minor_image_version     = 0x%4.4x\n",
1293061da546Spatrick             header.minor_image_version);
1294061da546Spatrick   s->Printf("  major_subsystem_version = 0x%4.4x\n",
1295061da546Spatrick             header.major_subsystem_version);
1296061da546Spatrick   s->Printf("  minor_subsystem_version = 0x%4.4x\n",
1297061da546Spatrick             header.minor_subsystem_version);
1298061da546Spatrick   s->Printf("  reserved1               = 0x%8.8x\n", header.reserved1);
1299061da546Spatrick   s->Printf("  image_size              = 0x%8.8x\n", header.image_size);
1300061da546Spatrick   s->Printf("  header_size             = 0x%8.8x\n", header.header_size);
1301061da546Spatrick   s->Printf("  checksum                = 0x%8.8x\n", header.checksum);
1302061da546Spatrick   s->Printf("  subsystem               = 0x%4.4x\n", header.subsystem);
1303061da546Spatrick   s->Printf("  dll_flags               = 0x%4.4x\n", header.dll_flags);
1304061da546Spatrick   s->Printf("  stack_reserve_size      = 0x%16.16" PRIx64 "\n",
1305061da546Spatrick             header.stack_reserve_size);
1306061da546Spatrick   s->Printf("  stack_commit_size       = 0x%16.16" PRIx64 "\n",
1307061da546Spatrick             header.stack_commit_size);
1308061da546Spatrick   s->Printf("  heap_reserve_size       = 0x%16.16" PRIx64 "\n",
1309061da546Spatrick             header.heap_reserve_size);
1310061da546Spatrick   s->Printf("  heap_commit_size        = 0x%16.16" PRIx64 "\n",
1311061da546Spatrick             header.heap_commit_size);
1312061da546Spatrick   s->Printf("  loader_flags            = 0x%8.8x\n", header.loader_flags);
1313061da546Spatrick   s->Printf("  num_data_dir_entries    = 0x%8.8x\n",
1314061da546Spatrick             (uint32_t)header.data_dirs.size());
1315061da546Spatrick   uint32_t i;
1316061da546Spatrick   for (i = 0; i < header.data_dirs.size(); i++) {
1317061da546Spatrick     s->Printf("  data_dirs[%2u] vmaddr = 0x%8.8x, vmsize = 0x%8.8x\n", i,
1318061da546Spatrick               header.data_dirs[i].vmaddr, header.data_dirs[i].vmsize);
1319061da546Spatrick   }
1320061da546Spatrick }
1321061da546Spatrick // DumpSectionHeader
1322061da546Spatrick //
1323061da546Spatrick // Dump a single ELF section header to the specified output stream
DumpSectionHeader(Stream * s,const section_header_t & sh)1324061da546Spatrick void ObjectFilePECOFF::DumpSectionHeader(Stream *s,
1325061da546Spatrick                                          const section_header_t &sh) {
1326dda28197Spatrick   std::string name = std::string(GetSectionName(sh));
1327061da546Spatrick   s->Printf("%-16s 0x%8.8x 0x%8.8x 0x%8.8x 0x%8.8x 0x%8.8x 0x%8.8x 0x%4.4x "
1328061da546Spatrick             "0x%4.4x 0x%8.8x\n",
1329061da546Spatrick             name.c_str(), sh.vmaddr, sh.vmsize, sh.offset, sh.size, sh.reloff,
1330061da546Spatrick             sh.lineoff, sh.nreloc, sh.nline, sh.flags);
1331061da546Spatrick }
1332061da546Spatrick 
1333061da546Spatrick // DumpSectionHeaders
1334061da546Spatrick //
1335061da546Spatrick // Dump all of the ELF section header to the specified output stream
DumpSectionHeaders(Stream * s)1336061da546Spatrick void ObjectFilePECOFF::DumpSectionHeaders(Stream *s) {
1337061da546Spatrick 
1338061da546Spatrick   s->PutCString("Section Headers\n");
1339061da546Spatrick   s->PutCString("IDX  name             vm addr    vm size    file off   file "
1340061da546Spatrick                 "size  reloc off  line off   nreloc nline  flags\n");
1341061da546Spatrick   s->PutCString("==== ---------------- ---------- ---------- ---------- "
1342061da546Spatrick                 "---------- ---------- ---------- ------ ------ ----------\n");
1343061da546Spatrick 
1344061da546Spatrick   uint32_t idx = 0;
1345061da546Spatrick   SectionHeaderCollIter pos, end = m_sect_headers.end();
1346061da546Spatrick 
1347061da546Spatrick   for (pos = m_sect_headers.begin(); pos != end; ++pos, ++idx) {
1348061da546Spatrick     s->Printf("[%2u] ", idx);
1349061da546Spatrick     ObjectFilePECOFF::DumpSectionHeader(s, *pos);
1350061da546Spatrick   }
1351061da546Spatrick }
1352061da546Spatrick 
1353061da546Spatrick // DumpDependentModules
1354061da546Spatrick //
1355061da546Spatrick // Dump all of the dependent modules to the specified output stream
DumpDependentModules(lldb_private::Stream * s)1356061da546Spatrick void ObjectFilePECOFF::DumpDependentModules(lldb_private::Stream *s) {
1357061da546Spatrick   auto num_modules = ParseDependentModules();
1358061da546Spatrick   if (num_modules > 0) {
1359061da546Spatrick     s->PutCString("Dependent Modules\n");
1360061da546Spatrick     for (unsigned i = 0; i < num_modules; ++i) {
1361061da546Spatrick       auto spec = m_deps_filespec->GetFileSpecAtIndex(i);
1362061da546Spatrick       s->Printf("  %s\n", spec.GetFilename().GetCString());
1363061da546Spatrick     }
1364061da546Spatrick   }
1365061da546Spatrick }
1366061da546Spatrick 
IsWindowsSubsystem()1367061da546Spatrick bool ObjectFilePECOFF::IsWindowsSubsystem() {
1368061da546Spatrick   switch (m_coff_header_opt.subsystem) {
1369061da546Spatrick   case llvm::COFF::IMAGE_SUBSYSTEM_NATIVE:
1370061da546Spatrick   case llvm::COFF::IMAGE_SUBSYSTEM_WINDOWS_GUI:
1371061da546Spatrick   case llvm::COFF::IMAGE_SUBSYSTEM_WINDOWS_CUI:
1372061da546Spatrick   case llvm::COFF::IMAGE_SUBSYSTEM_NATIVE_WINDOWS:
1373061da546Spatrick   case llvm::COFF::IMAGE_SUBSYSTEM_WINDOWS_CE_GUI:
1374061da546Spatrick   case llvm::COFF::IMAGE_SUBSYSTEM_XBOX:
1375061da546Spatrick   case llvm::COFF::IMAGE_SUBSYSTEM_WINDOWS_BOOT_APPLICATION:
1376061da546Spatrick     return true;
1377061da546Spatrick   default:
1378061da546Spatrick     return false;
1379061da546Spatrick   }
1380061da546Spatrick }
1381061da546Spatrick 
GetArchitecture()1382061da546Spatrick ArchSpec ObjectFilePECOFF::GetArchitecture() {
1383061da546Spatrick   uint16_t machine = m_coff_header.machine;
1384061da546Spatrick   switch (machine) {
1385061da546Spatrick   default:
1386061da546Spatrick     break;
1387061da546Spatrick   case llvm::COFF::IMAGE_FILE_MACHINE_AMD64:
1388061da546Spatrick   case llvm::COFF::IMAGE_FILE_MACHINE_I386:
1389061da546Spatrick   case llvm::COFF::IMAGE_FILE_MACHINE_POWERPC:
1390061da546Spatrick   case llvm::COFF::IMAGE_FILE_MACHINE_POWERPCFP:
1391061da546Spatrick   case llvm::COFF::IMAGE_FILE_MACHINE_ARM:
1392061da546Spatrick   case llvm::COFF::IMAGE_FILE_MACHINE_ARMNT:
1393061da546Spatrick   case llvm::COFF::IMAGE_FILE_MACHINE_THUMB:
1394061da546Spatrick   case llvm::COFF::IMAGE_FILE_MACHINE_ARM64:
1395061da546Spatrick     ArchSpec arch;
1396061da546Spatrick     arch.SetArchitecture(eArchTypeCOFF, machine, LLDB_INVALID_CPUTYPE,
1397061da546Spatrick                          IsWindowsSubsystem() ? llvm::Triple::Win32
1398061da546Spatrick                                               : llvm::Triple::UnknownOS);
1399061da546Spatrick     return arch;
1400061da546Spatrick   }
1401061da546Spatrick   return ArchSpec();
1402061da546Spatrick }
1403061da546Spatrick 
CalculateType()1404061da546Spatrick ObjectFile::Type ObjectFilePECOFF::CalculateType() {
1405061da546Spatrick   if (m_coff_header.machine != 0) {
1406061da546Spatrick     if ((m_coff_header.flags & llvm::COFF::IMAGE_FILE_DLL) == 0)
1407061da546Spatrick       return eTypeExecutable;
1408061da546Spatrick     else
1409061da546Spatrick       return eTypeSharedLibrary;
1410061da546Spatrick   }
1411061da546Spatrick   return eTypeExecutable;
1412061da546Spatrick }
1413061da546Spatrick 
CalculateStrata()1414061da546Spatrick ObjectFile::Strata ObjectFilePECOFF::CalculateStrata() { return eStrataUser; }
1415