aboutsummaryrefslogtreecommitdiff
path: root/contrib/llvm-project/lldb/source/Plugins/ObjectFile/COFF/ObjectFileCOFF.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm-project/lldb/source/Plugins/ObjectFile/COFF/ObjectFileCOFF.cpp')
-rw-r--r--contrib/llvm-project/lldb/source/Plugins/ObjectFile/COFF/ObjectFileCOFF.cpp311
1 files changed, 311 insertions, 0 deletions
diff --git a/contrib/llvm-project/lldb/source/Plugins/ObjectFile/COFF/ObjectFileCOFF.cpp b/contrib/llvm-project/lldb/source/Plugins/ObjectFile/COFF/ObjectFileCOFF.cpp
new file mode 100644
index 000000000000..a7ad5d27b237
--- /dev/null
+++ b/contrib/llvm-project/lldb/source/Plugins/ObjectFile/COFF/ObjectFileCOFF.cpp
@@ -0,0 +1,311 @@
+//===-- ObjectFileCOFF.cpp ------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "ObjectFileCOFF.h"
+
+#include "lldb/Core/Module.h"
+#include "lldb/Core/ModuleSpec.h"
+#include "lldb/Core/PluginManager.h"
+#include "lldb/Utility/LLDBLog.h"
+
+#include "llvm/Support/Error.h"
+#include "llvm/Support/FormatAdapters.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+using namespace llvm;
+using namespace llvm::object;
+
+static bool IsCOFFObjectFile(const DataBufferSP &data) {
+ return identify_magic(toStringRef(data->GetData())) ==
+ file_magic::coff_object;
+}
+
+LLDB_PLUGIN_DEFINE(ObjectFileCOFF)
+
+char ObjectFileCOFF::ID;
+
+ObjectFileCOFF::~ObjectFileCOFF() = default;
+
+void ObjectFileCOFF::Initialize() {
+ PluginManager::RegisterPlugin(GetPluginNameStatic(),
+ GetPluginDescriptionStatic(), CreateInstance,
+ CreateMemoryInstance, GetModuleSpecifications);
+}
+
+void ObjectFileCOFF::Terminate() {
+ PluginManager::UnregisterPlugin(CreateInstance);
+}
+
+lldb_private::ObjectFile *
+ObjectFileCOFF::CreateInstance(const ModuleSP &module_sp, DataBufferSP data_sp,
+ offset_t data_offset, const FileSpec *file,
+ offset_t file_offset, offset_t length) {
+ Log *log = GetLog(LLDBLog::Object);
+
+ if (!data_sp) {
+ data_sp = MapFileData(*file, length, file_offset);
+ if (!data_sp) {
+ LLDB_LOG(log,
+ "Failed to create ObjectFileCOFF instance: cannot read file {0}",
+ file->GetPath());
+ return nullptr;
+ }
+ data_offset = 0;
+ }
+
+ assert(data_sp && "must have mapped file at this point");
+
+ if (!IsCOFFObjectFile(data_sp))
+ return nullptr;
+
+ if (data_sp->GetByteSize() < length) {
+ data_sp = MapFileData(*file, length, file_offset);
+ if (!data_sp) {
+ LLDB_LOG(log,
+ "Failed to create ObjectFileCOFF instance: cannot read file {0}",
+ file->GetPath());
+ return nullptr;
+ }
+ data_offset = 0;
+ }
+
+
+ MemoryBufferRef buffer{toStringRef(data_sp->GetData()),
+ file->GetFilename().GetStringRef()};
+
+ Expected<std::unique_ptr<Binary>> binary = createBinary(buffer);
+ if (!binary) {
+ LLDB_LOG_ERROR(log, binary.takeError(),
+ "Failed to create binary for file ({1}): {0}",
+ file->GetPath());
+ return nullptr;
+ }
+
+ LLDB_LOG(log, "ObjectFileCOFF::ObjectFileCOFF module = {1} ({2}), file = {3}",
+ module_sp.get(), module_sp->GetSpecificationDescription(),
+ file->GetPath());
+
+ return new ObjectFileCOFF(unique_dyn_cast<COFFObjectFile>(std::move(*binary)),
+ module_sp, data_sp, data_offset, file, file_offset,
+ length);
+}
+
+lldb_private::ObjectFile *ObjectFileCOFF::CreateMemoryInstance(
+ const ModuleSP &module_sp, WritableDataBufferSP data_sp,
+ const ProcessSP &process_sp, addr_t header) {
+ // FIXME: do we need to worry about construction from a memory region?
+ return nullptr;
+}
+
+size_t ObjectFileCOFF::GetModuleSpecifications(
+ const FileSpec &file, DataBufferSP &data_sp, offset_t data_offset,
+ offset_t file_offset, offset_t length, ModuleSpecList &specs) {
+ if (!IsCOFFObjectFile(data_sp))
+ return 0;
+
+ MemoryBufferRef buffer{toStringRef(data_sp->GetData()),
+ file.GetFilename().GetStringRef()};
+ Expected<std::unique_ptr<Binary>> binary = createBinary(buffer);
+ if (!binary) {
+ Log *log = GetLog(LLDBLog::Object);
+ LLDB_LOG_ERROR(log, binary.takeError(),
+ "Failed to create binary for file ({1}): {0}",
+ file.GetFilename());
+ return 0;
+ }
+
+ std::unique_ptr<COFFObjectFile> object =
+ unique_dyn_cast<COFFObjectFile>(std::move(*binary));
+ switch (static_cast<COFF::MachineTypes>(object->getMachine())) {
+ case COFF::IMAGE_FILE_MACHINE_I386:
+ specs.Append(ModuleSpec(file, ArchSpec("i686-unknown-windows-msvc")));
+ return 1;
+ case COFF::IMAGE_FILE_MACHINE_AMD64:
+ specs.Append(ModuleSpec(file, ArchSpec("x86_64-unknown-windows-msvc")));
+ return 1;
+ case COFF::IMAGE_FILE_MACHINE_ARMNT:
+ specs.Append(ModuleSpec(file, ArchSpec("armv7-unknown-windows-msvc")));
+ return 1;
+ case COFF::IMAGE_FILE_MACHINE_ARM64:
+ specs.Append(ModuleSpec(file, ArchSpec("aarch64-unknown-windows-msvc")));
+ return 1;
+ default:
+ return 0;
+ }
+}
+
+void ObjectFileCOFF::Dump(Stream *stream) {
+ ModuleSP module(GetModule());
+ if (!module)
+ return;
+
+ std::lock_guard<std::recursive_mutex> guard(module->GetMutex());
+
+ stream->Printf("%p: ", static_cast<void *>(this));
+ stream->Indent();
+ stream->PutCString("ObjectFileCOFF");
+ *stream << ", file = '" << m_file
+ << "', arch = " << GetArchitecture().GetArchitectureName() << '\n';
+
+ if (SectionList *sections = GetSectionList())
+ sections->Dump(stream->AsRawOstream(), stream->GetIndentLevel(), nullptr,
+ true, std::numeric_limits<uint32_t>::max());
+}
+
+uint32_t ObjectFileCOFF::GetAddressByteSize() const {
+ return const_cast<ObjectFileCOFF *>(this)->GetArchitecture().GetAddressByteSize();
+}
+
+ArchSpec ObjectFileCOFF::GetArchitecture() {
+ switch (static_cast<COFF::MachineTypes>(m_object->getMachine())) {
+ case COFF::IMAGE_FILE_MACHINE_I386:
+ return ArchSpec("i686-unknown-windows-msvc");
+ case COFF::IMAGE_FILE_MACHINE_AMD64:
+ return ArchSpec("x86_64-unknown-windows-msvc");
+ case COFF::IMAGE_FILE_MACHINE_ARMNT:
+ return ArchSpec("armv7-unknown-windows-msvc");
+ case COFF::IMAGE_FILE_MACHINE_ARM64:
+ return ArchSpec("aarch64-unknown-windows-msvc");
+ default:
+ return ArchSpec();
+ }
+}
+
+void ObjectFileCOFF::CreateSections(lldb_private::SectionList &sections) {
+ if (m_sections_up)
+ return;
+
+ m_sections_up = std::make_unique<SectionList>();
+ ModuleSP module(GetModule());
+ if (!module)
+ return;
+
+ std::lock_guard<std::recursive_mutex> guard(module->GetMutex());
+
+ auto SectionType = [](StringRef Name,
+ const coff_section *Section) -> lldb::SectionType {
+ lldb::SectionType type =
+ StringSwitch<lldb::SectionType>(Name)
+ // DWARF Debug Sections
+ .Case(".debug_abbrev", eSectionTypeDWARFDebugAbbrev)
+ .Case(".debug_info", eSectionTypeDWARFDebugInfo)
+ .Case(".debug_line", eSectionTypeDWARFDebugLine)
+ .Case(".debug_pubnames", eSectionTypeDWARFDebugPubNames)
+ .Case(".debug_pubtypes", eSectionTypeDWARFDebugPubTypes)
+ .Case(".debug_str", eSectionTypeDWARFDebugStr)
+ // CodeView Debug Sections: .debug$S, .debug$T
+ .StartsWith(".debug$", eSectionTypeDebug)
+ .Case("clangast", eSectionTypeOther)
+ .Default(eSectionTypeInvalid);
+ if (type != eSectionTypeInvalid)
+ return type;
+
+ if (Section->Characteristics & COFF::IMAGE_SCN_CNT_CODE)
+ return eSectionTypeCode;
+ if (Section->Characteristics & COFF::IMAGE_SCN_CNT_INITIALIZED_DATA)
+ return eSectionTypeData;
+ if (Section->Characteristics & COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA)
+ return Section->SizeOfRawData ? eSectionTypeData : eSectionTypeZeroFill;
+ return eSectionTypeOther;
+ };
+ auto Permissions = [](const object::coff_section *Section) -> uint32_t {
+ uint32_t permissions = 0;
+ if (Section->Characteristics & COFF::IMAGE_SCN_MEM_EXECUTE)
+ permissions |= lldb::ePermissionsExecutable;
+ if (Section->Characteristics & COFF::IMAGE_SCN_MEM_READ)
+ permissions |= lldb::ePermissionsReadable;
+ if (Section->Characteristics & COFF::IMAGE_SCN_MEM_WRITE)
+ permissions |= lldb::ePermissionsWritable;
+ return permissions;
+ };
+
+ for (const auto &SecRef : m_object->sections()) {
+ const auto COFFSection = m_object->getCOFFSection(SecRef);
+
+ llvm::Expected<StringRef> Name = SecRef.getName();
+ StringRef SectionName = Name ? *Name : COFFSection->Name;
+ if (!Name)
+ consumeError(Name.takeError());
+
+ SectionSP section =
+ std::make_unique<Section>(module, this,
+ static_cast<user_id_t>(SecRef.getIndex()),
+ ConstString(SectionName),
+ SectionType(SectionName, COFFSection),
+ COFFSection->VirtualAddress,
+ COFFSection->VirtualSize,
+ COFFSection->PointerToRawData,
+ COFFSection->SizeOfRawData,
+ COFFSection->getAlignment(),
+ 0);
+ section->SetPermissions(Permissions(COFFSection));
+
+ m_sections_up->AddSection(section);
+ sections.AddSection(section);
+ }
+}
+
+void ObjectFileCOFF::ParseSymtab(lldb_private::Symtab &symtab) {
+ Log *log = GetLog(LLDBLog::Object);
+
+ SectionList *sections = GetSectionList();
+ symtab.Reserve(symtab.GetNumSymbols() + m_object->getNumberOfSymbols());
+
+ auto SymbolType = [](const COFFSymbolRef &Symbol) -> lldb::SymbolType {
+ if (Symbol.getComplexType() == COFF::IMAGE_SYM_DTYPE_FUNCTION)
+ return eSymbolTypeCode;
+ if (Symbol.getBaseType() == COFF::IMAGE_SYM_TYPE_NULL &&
+ Symbol.getComplexType() == COFF::IMAGE_SYM_DTYPE_NULL)
+ return eSymbolTypeData;
+ return eSymbolTypeInvalid;
+ };
+
+ for (const auto &SymRef : m_object->symbols()) {
+ const auto COFFSymRef = m_object->getCOFFSymbol(SymRef);
+
+ Expected<StringRef> NameOrErr = SymRef.getName();
+ if (!NameOrErr) {
+ LLDB_LOG_ERROR(log, NameOrErr.takeError(),
+ "ObjectFileCOFF: failed to get symbol name: {0}");
+ continue;
+ }
+
+ Symbol symbol;
+ symbol.GetMangled().SetValue(ConstString(*NameOrErr));
+
+ int16_t SecIdx = static_cast<int16_t>(COFFSymRef.getSectionNumber());
+ if (SecIdx == COFF::IMAGE_SYM_ABSOLUTE) {
+ symbol.GetAddressRef() = Address{COFFSymRef.getValue()};
+ symbol.SetType(eSymbolTypeAbsolute);
+ } else if (SecIdx >= 1) {
+ symbol.GetAddressRef() = Address(sections->GetSectionAtIndex(SecIdx - 1),
+ COFFSymRef.getValue());
+ symbol.SetType(SymbolType(COFFSymRef));
+ }
+
+ symtab.AddSymbol(symbol);
+ }
+
+ LLDB_LOG(log, "ObjectFileCOFF::ParseSymtab processed {0} symbols",
+ m_object->getNumberOfSymbols());
+}
+
+bool ObjectFileCOFF::ParseHeader() {
+ ModuleSP module(GetModule());
+ if (!module)
+ return false;
+
+ std::lock_guard<std::recursive_mutex> guard(module->GetMutex());
+
+ m_data.SetByteOrder(eByteOrderLittle);
+ m_data.SetAddressByteSize(GetAddressByteSize());
+
+ return true;
+}