//===-- ObjectFileXCOFF.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 "ObjectFileXCOFF.h" #include #include #include #include #include "lldb/Core/Module.h" #include "lldb/Core/ModuleSpec.h" #include "lldb/Core/PluginManager.h" #include "lldb/Core/Progress.h" #include "lldb/Core/Section.h" #include "lldb/Host/FileSystem.h" #include "lldb/Symbol/SymbolContext.h" #include "lldb/Target/Process.h" #include "lldb/Target/Target.h" #include "lldb/Utility/ArchSpec.h" #include "lldb/Utility/DataBufferHeap.h" #include "lldb/Utility/FileSpecList.h" #include "lldb/Utility/LLDBLog.h" #include "lldb/Utility/Log.h" #include "lldb/Utility/RangeMap.h" #include "lldb/Utility/Status.h" #include "lldb/Utility/Stream.h" #include "llvm/ADT/StringRef.h" #include "llvm/BinaryFormat/XCOFF.h" #include "llvm/Object/XCOFFObjectFile.h" #include "llvm/Support/MemoryBuffer.h" using namespace llvm; using namespace lldb; using namespace lldb_private; LLDB_PLUGIN_DEFINE(ObjectFileXCOFF) // FIXME: target 64bit at this moment. // Static methods. void ObjectFileXCOFF::Initialize() { PluginManager::RegisterPlugin(GetPluginNameStatic(), GetPluginDescriptionStatic(), CreateInstance, CreateMemoryInstance, GetModuleSpecifications); } void ObjectFileXCOFF::Terminate() { PluginManager::UnregisterPlugin(CreateInstance); } ObjectFile *ObjectFileXCOFF::CreateInstance(const lldb::ModuleSP &module_sp, DataBufferSP data_sp, lldb::offset_t data_offset, const lldb_private::FileSpec *file, lldb::offset_t file_offset, lldb::offset_t length) { if (!data_sp) { data_sp = MapFileData(*file, length, file_offset); if (!data_sp) return nullptr; data_offset = 0; } if (!ObjectFileXCOFF::MagicBytesMatch(data_sp, data_offset, length)) return nullptr; // Update the data to contain the entire file if it doesn't already if (data_sp->GetByteSize() < length) { data_sp = MapFileData(*file, length, file_offset); if (!data_sp) return nullptr; data_offset = 0; } auto objfile_up = std::make_unique( module_sp, data_sp, data_offset, file, file_offset, length); if (!objfile_up) return nullptr; return objfile_up.release(); } ObjectFile *ObjectFileXCOFF::CreateMemoryInstance( const lldb::ModuleSP &module_sp, WritableDataBufferSP data_sp, const lldb::ProcessSP &process_sp, lldb::addr_t header_addr) { return nullptr; } size_t ObjectFileXCOFF::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) { const size_t initial_count = specs.GetSize(); if (ObjectFileXCOFF::MagicBytesMatch(data_sp, 0, data_sp->GetByteSize())) { ArchSpec arch_spec = ArchSpec(eArchTypeXCOFF, XCOFF::TCPU_PPC64, LLDB_INVALID_CPUTYPE); ModuleSpec spec(file, arch_spec); spec.GetArchitecture().SetArchitecture(eArchTypeXCOFF, XCOFF::TCPU_PPC64, LLDB_INVALID_CPUTYPE, llvm::Triple::AIX); specs.Append(spec); } return specs.GetSize() - initial_count; } static uint32_t XCOFFHeaderSizeFromMagic(uint32_t magic) { switch (magic) { /* TODO: 32bit not supported yet case XCOFF::XCOFF32: return sizeof(struct llvm::object::XCOFFFileHeader32); */ case XCOFF::XCOFF64: return sizeof(struct llvm::object::XCOFFFileHeader64); break; default: break; } return 0; } bool ObjectFileXCOFF::MagicBytesMatch(DataBufferSP &data_sp, lldb::addr_t data_offset, lldb::addr_t data_length) { lldb_private::DataExtractor data; data.SetData(data_sp, data_offset, data_length); data.SetByteOrder(eByteOrderBig); lldb::offset_t offset = 0; uint16_t magic = data.GetU16(&offset); return XCOFFHeaderSizeFromMagic(magic) != 0; } bool ObjectFileXCOFF::ParseHeader() { return false; } ByteOrder ObjectFileXCOFF::GetByteOrder() const { return eByteOrderBig; } bool ObjectFileXCOFF::IsExecutable() const { return true; } uint32_t ObjectFileXCOFF::GetAddressByteSize() const { return 8; } void ObjectFileXCOFF::ParseSymtab(Symtab &lldb_symtab) {} bool ObjectFileXCOFF::IsStripped() { return false; } void ObjectFileXCOFF::CreateSections(SectionList &unified_section_list) {} void ObjectFileXCOFF::Dump(Stream *s) {} ArchSpec ObjectFileXCOFF::GetArchitecture() { ArchSpec arch_spec = ArchSpec(eArchTypeXCOFF, XCOFF::TCPU_PPC64, LLDB_INVALID_CPUTYPE); return arch_spec; } UUID ObjectFileXCOFF::GetUUID() { return UUID(); } uint32_t ObjectFileXCOFF::GetDependentModules(FileSpecList &files) { return 0; } ObjectFile::Type ObjectFileXCOFF::CalculateType() { return eTypeExecutable; } ObjectFile::Strata ObjectFileXCOFF::CalculateStrata() { return eStrataUnknown; } lldb::WritableDataBufferSP ObjectFileXCOFF::MapFileDataWritable(const FileSpec &file, uint64_t Size, uint64_t Offset) { return FileSystem::Instance().CreateWritableDataBuffer(file.GetPath(), Size, Offset); } ObjectFileXCOFF::ObjectFileXCOFF(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) : ObjectFile(module_sp, file, file_offset, length, data_sp, data_offset) { if (file) m_file = *file; } ObjectFileXCOFF::ObjectFileXCOFF(const lldb::ModuleSP &module_sp, DataBufferSP header_data_sp, const lldb::ProcessSP &process_sp, addr_t header_addr) : ObjectFile(module_sp, process_sp, header_addr, header_data_sp) {}