LLDB mainline
ObjectFileCOFF.cpp
Go to the documentation of this file.
1//===-- ObjectFileCOFF.cpp ------------------------------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#include "ObjectFileCOFF.h"
10
11#include "lldb/Core/Module.h"
15
16#include "llvm/Support/Error.h"
17#include "llvm/Support/FormatAdapters.h"
18
19using namespace lldb;
20using namespace lldb_private;
21
22using namespace llvm;
23using namespace llvm::object;
24
25static bool IsCOFFObjectFile(const DataBufferSP &data) {
26 return identify_magic(toStringRef(data->GetData())) ==
27 file_magic::coff_object;
28}
29
31
33
35
41
45
48 offset_t data_offset, const FileSpec *file,
49 offset_t file_offset, offset_t length) {
51
52 if (!data_sp) {
53 data_sp = MapFileData(*file, length, file_offset);
54 if (!data_sp) {
55 LLDB_LOG(log,
56 "Failed to create ObjectFileCOFF instance: cannot read file {0}",
57 file->GetPath());
58 return nullptr;
59 }
60 data_offset = 0;
61 }
62
63 assert(data_sp && "must have mapped file at this point");
64
65 if (!IsCOFFObjectFile(data_sp))
66 return nullptr;
67
68 if (data_sp->GetByteSize() < length) {
69 data_sp = MapFileData(*file, length, file_offset);
70 if (!data_sp) {
71 LLDB_LOG(log,
72 "Failed to create ObjectFileCOFF instance: cannot read file {0}",
73 file->GetPath());
74 return nullptr;
75 }
76 data_offset = 0;
77 }
78
79
80 MemoryBufferRef buffer{toStringRef(data_sp->GetData()),
81 file->GetFilename().GetStringRef()};
82
83 Expected<std::unique_ptr<Binary>> binary = createBinary(buffer);
84 if (!binary) {
85 LLDB_LOG_ERROR(log, binary.takeError(),
86 "Failed to create binary for file ({1}): {0}",
87 file->GetPath());
88 return nullptr;
89 }
90
91 LLDB_LOG(log, "ObjectFileCOFF::ObjectFileCOFF module = {1} ({2}), file = {3}",
92 module_sp.get(), module_sp->GetSpecificationDescription(),
93 file->GetPath());
94
95 return new ObjectFileCOFF(unique_dyn_cast<COFFObjectFile>(std::move(*binary)),
96 module_sp, data_sp, data_offset, file, file_offset,
97 length);
98}
99
101 const ModuleSP &module_sp, WritableDataBufferSP data_sp,
102 const ProcessSP &process_sp, addr_t header) {
103 // FIXME: do we need to worry about construction from a memory region?
104 return nullptr;
105}
106
108 const FileSpec &file, DataBufferSP &data_sp, offset_t data_offset,
109 offset_t file_offset, offset_t length, ModuleSpecList &specs) {
110 if (!IsCOFFObjectFile(data_sp))
111 return 0;
112
113 MemoryBufferRef buffer{toStringRef(data_sp->GetData()),
114 file.GetFilename().GetStringRef()};
115 Expected<std::unique_ptr<Binary>> binary = createBinary(buffer);
116 if (!binary) {
117 Log *log = GetLog(LLDBLog::Object);
118 LLDB_LOG_ERROR(log, binary.takeError(),
119 "Failed to create binary for file ({1}): {0}",
120 file.GetFilename());
121 return 0;
122 }
123
124 std::unique_ptr<COFFObjectFile> object =
125 unique_dyn_cast<COFFObjectFile>(std::move(*binary));
126 switch (static_cast<COFF::MachineTypes>(object->getMachine())) {
127 case COFF::IMAGE_FILE_MACHINE_I386:
128 specs.Append(ModuleSpec(file, ArchSpec("i686-unknown-windows-msvc")));
129 return 1;
130 case COFF::IMAGE_FILE_MACHINE_AMD64:
131 specs.Append(ModuleSpec(file, ArchSpec("x86_64-unknown-windows-msvc")));
132 return 1;
133 case COFF::IMAGE_FILE_MACHINE_ARMNT:
134 specs.Append(ModuleSpec(file, ArchSpec("armv7-unknown-windows-msvc")));
135 return 1;
136 case COFF::IMAGE_FILE_MACHINE_ARM64:
137 specs.Append(ModuleSpec(file, ArchSpec("aarch64-unknown-windows-msvc")));
138 return 1;
139 default:
140 return 0;
141 }
142}
143
145 ModuleSP module(GetModule());
146 if (!module)
147 return;
148
149 std::lock_guard<std::recursive_mutex> guard(module->GetMutex());
150
151 stream->Printf("%p: ", static_cast<void *>(this));
152 stream->Indent();
153 stream->PutCString("ObjectFileCOFF");
154 *stream << ", file = '" << m_file
155 << "', arch = " << GetArchitecture().GetArchitectureName() << '\n';
156
157 if (SectionList *sections = GetSectionList())
158 sections->Dump(stream->AsRawOstream(), stream->GetIndentLevel(), nullptr,
159 true, std::numeric_limits<uint32_t>::max());
160}
161
163 return const_cast<ObjectFileCOFF *>(this)->GetArchitecture().GetAddressByteSize();
164}
165
167 switch (static_cast<COFF::MachineTypes>(m_object->getMachine())) {
168 case COFF::IMAGE_FILE_MACHINE_I386:
169 return ArchSpec("i686-unknown-windows-msvc");
170 case COFF::IMAGE_FILE_MACHINE_AMD64:
171 return ArchSpec("x86_64-unknown-windows-msvc");
172 case COFF::IMAGE_FILE_MACHINE_ARMNT:
173 return ArchSpec("armv7-unknown-windows-msvc");
174 case COFF::IMAGE_FILE_MACHINE_ARM64:
175 return ArchSpec("aarch64-unknown-windows-msvc");
176 default:
177 return ArchSpec();
178 }
179}
180
182 if (m_sections_up)
183 return;
184
185 m_sections_up = std::make_unique<SectionList>();
186 ModuleSP module(GetModule());
187 if (!module)
188 return;
189
190 std::lock_guard<std::recursive_mutex> guard(module->GetMutex());
191
192 auto SectionType = [](StringRef Name,
193 const coff_section *Section) -> lldb::SectionType {
194 // DWARF Debug Sections
195 if (Name.consume_front(".debug_"))
196 return GetDWARFSectionTypeFromName(Name);
197
198 lldb::SectionType type = StringSwitch<lldb::SectionType>(Name)
199 // CodeView Debug Sections: .debug$S, .debug$T
200 .StartsWith(".debug$", eSectionTypeDebug)
201 .Case("clangast", eSectionTypeOther)
202 .Default(eSectionTypeInvalid);
203 if (type != eSectionTypeInvalid)
204 return type;
205
206 if (Section->Characteristics & COFF::IMAGE_SCN_CNT_CODE)
207 return eSectionTypeCode;
208 if (Section->Characteristics & COFF::IMAGE_SCN_CNT_INITIALIZED_DATA)
209 return eSectionTypeData;
210 if (Section->Characteristics & COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA)
211 return Section->SizeOfRawData ? eSectionTypeData : eSectionTypeZeroFill;
212 return eSectionTypeOther;
213 };
214 auto Permissions = [](const object::coff_section *Section) -> uint32_t {
215 uint32_t permissions = 0;
216 if (Section->Characteristics & COFF::IMAGE_SCN_MEM_EXECUTE)
217 permissions |= lldb::ePermissionsExecutable;
218 if (Section->Characteristics & COFF::IMAGE_SCN_MEM_READ)
219 permissions |= lldb::ePermissionsReadable;
220 if (Section->Characteristics & COFF::IMAGE_SCN_MEM_WRITE)
221 permissions |= lldb::ePermissionsWritable;
222 return permissions;
223 };
224
225 for (const auto &SecRef : m_object->sections()) {
226 const auto COFFSection = m_object->getCOFFSection(SecRef);
227
228 llvm::Expected<StringRef> Name = SecRef.getName();
229 StringRef SectionName = Name ? *Name : COFFSection->Name;
230 if (!Name)
231 consumeError(Name.takeError());
232
233 SectionSP section =
234 std::make_unique<Section>(module, this,
235 static_cast<user_id_t>(SecRef.getIndex()),
236 ConstString(SectionName),
237 SectionType(SectionName, COFFSection),
238 COFFSection->VirtualAddress,
239 COFFSection->VirtualSize,
240 COFFSection->PointerToRawData,
241 COFFSection->SizeOfRawData,
242 COFFSection->getAlignment(),
243 0);
244 section->SetPermissions(Permissions(COFFSection));
245
246 m_sections_up->AddSection(section);
247 sections.AddSection(section);
248 }
249}
250
252 Log *log = GetLog(LLDBLog::Object);
253
254 SectionList *sections = GetSectionList();
255 symtab.Reserve(symtab.GetNumSymbols() + m_object->getNumberOfSymbols());
256
257 auto SymbolType = [](const COFFSymbolRef &Symbol) -> lldb::SymbolType {
258 if (Symbol.getComplexType() == COFF::IMAGE_SYM_DTYPE_FUNCTION)
259 return eSymbolTypeCode;
260 if (Symbol.getBaseType() == COFF::IMAGE_SYM_TYPE_NULL &&
261 Symbol.getComplexType() == COFF::IMAGE_SYM_DTYPE_NULL)
262 return eSymbolTypeData;
263 return eSymbolTypeInvalid;
264 };
265
266 for (const auto &SymRef : m_object->symbols()) {
267 const auto COFFSymRef = m_object->getCOFFSymbol(SymRef);
268
269 Expected<StringRef> NameOrErr = SymRef.getName();
270 if (!NameOrErr) {
271 LLDB_LOG_ERROR(log, NameOrErr.takeError(),
272 "ObjectFileCOFF: failed to get symbol name: {0}");
273 continue;
274 }
275
276 Symbol symbol;
277 symbol.GetMangled().SetValue(ConstString(*NameOrErr));
278
279 int16_t SecIdx = static_cast<int16_t>(COFFSymRef.getSectionNumber());
280 if (SecIdx == COFF::IMAGE_SYM_ABSOLUTE) {
281 symbol.GetAddressRef() = Address{COFFSymRef.getValue()};
283 } else if (SecIdx >= 1) {
284 symbol.GetAddressRef() = Address(sections->GetSectionAtIndex(SecIdx - 1),
285 COFFSymRef.getValue());
286 symbol.SetType(SymbolType(COFFSymRef));
287 }
288
289 symtab.AddSymbol(symbol);
290 }
291
292 LLDB_LOG(log, "ObjectFileCOFF::ParseSymtab processed {0} symbols",
293 m_object->getNumberOfSymbols());
294}
295
297 ModuleSP module(GetModule());
298 if (!module)
299 return false;
300
301 std::lock_guard<std::recursive_mutex> guard(module->GetMutex());
302
303 m_data.SetByteOrder(eByteOrderLittle);
304 m_data.SetAddressByteSize(GetAddressByteSize());
305
306 return true;
307}
#define LLDB_LOG(log,...)
The LLDB_LOG* macros defined below are the way to emit log messages.
Definition Log.h:369
#define LLDB_LOG_ERROR(log, error,...)
Definition Log.h:392
static bool IsCOFFObjectFile(const DataBufferSP &data)
#define LLDB_PLUGIN_DEFINE(PluginName)
uint32_t GetAddressByteSize() const override
Gets the address size in bytes for the current object file.
void ParseSymtab(lldb_private::Symtab &) override
Parse the symbol table into the provides symbol table object.
static lldb_private::ObjectFile * CreateInstance(const lldb::ModuleSP &module_sp, lldb::DataBufferSP data_sp, lldb::offset_t data_offset, const lldb_private::FileSpec *file, lldb::offset_t file_offset, lldb::offset_t length)
static size_t GetModuleSpecifications(const lldb_private::FileSpec &file, lldb::DataBufferSP &data_sp, lldb::offset_t data_offset, lldb::offset_t file_offset, lldb::offset_t length, lldb_private::ModuleSpecList &specs)
static lldb_private::ObjectFile * CreateMemoryInstance(const lldb::ModuleSP &module_sp, lldb::WritableDataBufferSP data_sp, const lldb::ProcessSP &process_sp, lldb::addr_t header)
static void Initialize()
void Dump(lldb_private::Stream *stream) override
Dump a description of this object to a Stream.
void CreateSections(lldb_private::SectionList &) override
static char ID
static llvm::StringRef GetPluginDescriptionStatic()
lldb_private::ArchSpec GetArchitecture() override
Get the ArchSpec for this object file.
~ObjectFileCOFF() override
bool ParseHeader() override
Attempts to parse the object header.
static void Terminate()
ObjectFileCOFF(std::unique_ptr< llvm::object::COFFObjectFile > object, const lldb::ModuleSP &module_sp, lldb::DataBufferSP data_sp, lldb::offset_t data_offset, const lldb_private::FileSpec *file, lldb::offset_t file_offset, lldb::offset_t length)
std::unique_ptr< llvm::object::COFFObjectFile > m_object
static llvm::StringRef GetPluginNameStatic()
A section + offset based address class.
Definition Address.h:62
An architecture specification class.
Definition ArchSpec.h:31
uint32_t GetAddressByteSize() const
Returns the size in bytes of an address of the current architecture.
Definition ArchSpec.cpp:685
const char * GetArchitectureName() const
Returns a static string representing the current architecture.
Definition ArchSpec.cpp:548
A uniqued constant string class.
Definition ConstString.h:40
llvm::StringRef GetStringRef() const
Get the string value as a llvm::StringRef.
A file utility class.
Definition FileSpec.h:57
const ConstString & GetFilename() const
Filename string const get accessor.
Definition FileSpec.h:251
size_t GetPath(char *path, size_t max_path_length, bool denormalize=true) const
Extract the full path to the file.
Definition FileSpec.cpp:374
void SetValue(ConstString name)
Set the string value in this object.
Definition Mangled.cpp:124
lldb::ModuleSP GetModule() const
Get const accessor for the module pointer.
void Append(const ModuleSpec &spec)
Definition ModuleSpec.h:308
A plug-in interface definition class for object file parsers.
Definition ObjectFile.h:45
DataExtractor m_data
The data for this object file so things can be parsed lazily.
Definition ObjectFile.h:784
std::unique_ptr< lldb_private::SectionList > m_sections_up
Definition ObjectFile.h:788
static lldb::DataBufferSP MapFileData(const FileSpec &file, uint64_t Size, uint64_t Offset)
static lldb::SectionType GetDWARFSectionTypeFromName(llvm::StringRef name)
Parses the section type from a section name for DWARF sections.
virtual SectionList * GetSectionList(bool update_module_section_list=true)
Gets the section list for the currently selected architecture (and object for archives).
static bool RegisterPlugin(llvm::StringRef name, llvm::StringRef description, ABICreateInstance create_callback)
static bool UnregisterPlugin(ABICreateInstance create_callback)
size_t AddSection(const lldb::SectionSP &section_sp)
Definition Section.cpp:482
lldb::SectionSP GetSectionAtIndex(size_t idx) const
Definition Section.cpp:551
A stream class that can stream formatted output to a file.
Definition Stream.h:28
llvm::raw_ostream & AsRawOstream()
Returns a raw_ostream that forwards the data to this Stream object.
Definition Stream.h:400
size_t Indent(llvm::StringRef s="")
Indent the current line in the stream.
Definition Stream.cpp:157
size_t Printf(const char *format,...) __attribute__((format(printf
Output printf formatted output to the stream.
Definition Stream.cpp:134
size_t PutCString(llvm::StringRef cstr)
Output a C string to the stream.
Definition Stream.cpp:65
unsigned GetIndentLevel() const
Get the current indentation level.
Definition Stream.cpp:187
void SetType(lldb::SymbolType type)
Definition Symbol.h:171
Mangled & GetMangled()
Definition Symbol.h:147
Address & GetAddressRef()
Definition Symbol.h:73
uint32_t AddSymbol(const Symbol &symbol)
Definition Symtab.cpp:64
size_t GetNumSymbols() const
Definition Symtab.cpp:77
void Reserve(size_t count)
Definition Symtab.cpp:51
A class that represents a running process on the host machine.
Log * GetLog(Cat mask)
Retrieve the Log object for the channel associated with the given log enum.
Definition Log.h:332
uint64_t offset_t
Definition lldb-types.h:85
std::shared_ptr< lldb_private::Process > ProcessSP
SymbolType
Symbol types.
@ eSymbolTypeAbsolute
uint64_t user_id_t
Definition lldb-types.h:82
std::shared_ptr< lldb_private::DataBuffer > DataBufferSP
std::shared_ptr< lldb_private::Section > SectionSP
std::shared_ptr< lldb_private::WritableDataBuffer > WritableDataBufferSP
uint64_t addr_t
Definition lldb-types.h:80
@ eSectionTypeInvalid
@ eSectionTypeZeroFill
std::shared_ptr< lldb_private::Module > ModuleSP