https://github.com/DhruvSrivastavaX created https://github.com/llvm/llvm-project/pull/116337
This PR is in reference to porting LLDB on AIX. Link to discussions on llvm discourse and github: 1. https://discourse.llvm.org/t/port-lldb-to-ibm-aix/80640 2. https://github.com/llvm/llvm-project/issues/101657 The complete changes for porting are present in this draft PR: https://github.com/llvm/llvm-project/pull/102601 Added XCOFF Object File Header Parsing for AIX. This PR is an incremental PR to the base: #111814 Details about XCOFF file format on AIX: [XCOFF](https://www.ibm.com/docs/en/aix/7.3?topic=formats-xcoff-object-file-format) Review Request: @labath @DavidSpickett >From 0c63800bdcbadcfceed4c9a81305eda7d5a15960 Mon Sep 17 00:00:00 2001 From: Dhruv-Srivastava <dhruv.srivast...@ibm.com> Date: Fri, 15 Nov 2024 02:16:31 -0600 Subject: [PATCH] Added XCOFF Header Parsing --- .../ObjectFile/XCOFF/ObjectFileXCOFF.cpp | 126 +++++++++++++++++- .../ObjectFile/XCOFF/ObjectFileXCOFF.h | 58 ++++++++ 2 files changed, 181 insertions(+), 3 deletions(-) diff --git a/lldb/source/Plugins/ObjectFile/XCOFF/ObjectFileXCOFF.cpp b/lldb/source/Plugins/ObjectFile/XCOFF/ObjectFileXCOFF.cpp index 3be900f9a4bc9f..c06ece4347822d 100644 --- a/lldb/source/Plugins/ObjectFile/XCOFF/ObjectFileXCOFF.cpp +++ b/lldb/source/Plugins/ObjectFile/XCOFF/ObjectFileXCOFF.cpp @@ -81,9 +81,44 @@ ObjectFile *ObjectFileXCOFF::CreateInstance(const lldb::ModuleSP &module_sp, if (!objfile_up) return nullptr; + // Cache xcoff binary. + if (!objfile_up->CreateBinary()) + return nullptr; + + if (!objfile_up->ParseHeader()) + return nullptr; + return objfile_up.release(); } +bool ObjectFileXCOFF::CreateBinary() { + if (m_binary) + return true; + + Log *log = GetLog(LLDBLog::Object); + + auto binary = llvm::object::XCOFFObjectFile::createObjectFile( + llvm::MemoryBufferRef(toStringRef(m_data.GetData()), + m_file.GetFilename().GetStringRef()), + file_magic::xcoff_object_64); + if (!binary) { + LLDB_LOG_ERROR(log, binary.takeError(), + "Failed to create binary for file ({1}): {0}", m_file); + return false; + } + + // Make sure we only handle XCOFF format. + m_binary = + llvm::unique_dyn_cast<llvm::object::XCOFFObjectFile>(std::move(*binary)); + if (!m_binary) + return false; + + LLDB_LOG(log, "this = {0}, module = {1} ({2}), file = {3}, binary = {4}", + this, GetModule().get(), GetModule()->GetSpecificationDescription(), + m_file.GetPath(), m_binary.get()); + return true; +} + ObjectFile *ObjectFileXCOFF::CreateMemoryInstance( const lldb::ModuleSP &module_sp, WritableDataBufferSP data_sp, const lldb::ProcessSP &process_sp, lldb::addr_t header_addr) { @@ -136,13 +171,92 @@ bool ObjectFileXCOFF::MagicBytesMatch(DataBufferSP &data_sp, return XCOFFHeaderSizeFromMagic(magic) != 0; } -bool ObjectFileXCOFF::ParseHeader() { return false; } +bool ObjectFileXCOFF::ParseHeader() { + ModuleSP module_sp(GetModule()); + if (module_sp) { + std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex()); + lldb::offset_t offset = 0; + + if (ParseXCOFFHeader(m_data, &offset, m_xcoff_header)) { + m_data.SetAddressByteSize(GetAddressByteSize()); + if (m_xcoff_header.auxhdrsize > 0) + ParseXCOFFOptionalHeader(m_data, &offset); + } + return true; + } + + return false; +} + +bool ObjectFileXCOFF::ParseXCOFFHeader(lldb_private::DataExtractor &data, + lldb::offset_t *offset_ptr, + xcoff_header_t &xcoff_header) { + // FIXME: data.ValidOffsetForDataOfSize + xcoff_header.magic = data.GetU16(offset_ptr); + xcoff_header.nsects = data.GetU16(offset_ptr); + xcoff_header.modtime = data.GetU32(offset_ptr); + xcoff_header.symoff = data.GetU64(offset_ptr); + xcoff_header.auxhdrsize = data.GetU16(offset_ptr); + xcoff_header.flags = data.GetU16(offset_ptr); + xcoff_header.nsyms = data.GetU32(offset_ptr); + return true; +} + +bool ObjectFileXCOFF::ParseXCOFFOptionalHeader( + lldb_private::DataExtractor &data, lldb::offset_t *offset_ptr) { + lldb::offset_t init_offset = *offset_ptr; + // FIXME: data.ValidOffsetForDataOfSize + m_xcoff_aux_header.AuxMagic = data.GetU16(offset_ptr); + m_xcoff_aux_header.Version = data.GetU16(offset_ptr); + m_xcoff_aux_header.ReservedForDebugger = data.GetU32(offset_ptr); + m_xcoff_aux_header.TextStartAddr = data.GetU64(offset_ptr); + m_xcoff_aux_header.DataStartAddr = data.GetU64(offset_ptr); + m_xcoff_aux_header.TOCAnchorAddr = data.GetU64(offset_ptr); + m_xcoff_aux_header.SecNumOfEntryPoint = data.GetU16(offset_ptr); + m_xcoff_aux_header.SecNumOfText = data.GetU16(offset_ptr); + m_xcoff_aux_header.SecNumOfData = data.GetU16(offset_ptr); + m_xcoff_aux_header.SecNumOfTOC = data.GetU16(offset_ptr); + m_xcoff_aux_header.SecNumOfLoader = data.GetU16(offset_ptr); + m_xcoff_aux_header.SecNumOfBSS = data.GetU16(offset_ptr); + m_xcoff_aux_header.MaxAlignOfText = data.GetU16(offset_ptr); + m_xcoff_aux_header.MaxAlignOfData = data.GetU16(offset_ptr); + m_xcoff_aux_header.ModuleType = data.GetU16(offset_ptr); + m_xcoff_aux_header.CpuFlag = data.GetU8(offset_ptr); + m_xcoff_aux_header.CpuType = data.GetU8(offset_ptr); + m_xcoff_aux_header.TextPageSize = data.GetU8(offset_ptr); + m_xcoff_aux_header.DataPageSize = data.GetU8(offset_ptr); + m_xcoff_aux_header.StackPageSize = data.GetU8(offset_ptr); + m_xcoff_aux_header.FlagAndTDataAlignment = data.GetU8(offset_ptr); + m_xcoff_aux_header.TextSize = data.GetU64(offset_ptr); + m_xcoff_aux_header.InitDataSize = data.GetU64(offset_ptr); + m_xcoff_aux_header.BssDataSize = data.GetU64(offset_ptr); + m_xcoff_aux_header.EntryPointAddr = data.GetU64(offset_ptr); + m_xcoff_aux_header.MaxStackSize = data.GetU64(offset_ptr); + m_xcoff_aux_header.MaxDataSize = data.GetU64(offset_ptr); + m_xcoff_aux_header.SecNumOfTData = data.GetU16(offset_ptr); + m_xcoff_aux_header.SecNumOfTBSS = data.GetU16(offset_ptr); + m_xcoff_aux_header.XCOFF64Flag = data.GetU16(offset_ptr); + lldb::offset_t last_offset = *offset_ptr; + if ((last_offset - init_offset) < m_xcoff_header.auxhdrsize) + *offset_ptr += (m_xcoff_header.auxhdrsize - (last_offset - init_offset)); + return true; +} ByteOrder ObjectFileXCOFF::GetByteOrder() const { return eByteOrderBig; } bool ObjectFileXCOFF::IsExecutable() const { return true; } -uint32_t ObjectFileXCOFF::GetAddressByteSize() const { return 8; } +uint32_t ObjectFileXCOFF::GetAddressByteSize() const { + if (m_xcoff_header.magic == XCOFF::XCOFF64) + return 8; + else if (m_xcoff_header.magic == XCOFF::XCOFF32) + return 4; + return 4; +} + +AddressClass ObjectFileXCOFF::GetAddressClass(addr_t file_addr) { + return AddressClass::eUnknown; +} void ObjectFileXCOFF::ParseSymtab(Symtab &lldb_symtab) {} @@ -162,7 +276,13 @@ UUID ObjectFileXCOFF::GetUUID() { return UUID(); } uint32_t ObjectFileXCOFF::GetDependentModules(FileSpecList &files) { return 0; } -ObjectFile::Type ObjectFileXCOFF::CalculateType() { return eTypeExecutable; } +ObjectFile::Type ObjectFileXCOFF::CalculateType() { + if (m_xcoff_header.flags & XCOFF::F_EXEC) + return eTypeExecutable; + else if (m_xcoff_header.flags & XCOFF::F_SHROBJ) + return eTypeSharedLibrary; + return eTypeUnknown; +} ObjectFile::Strata ObjectFileXCOFF::CalculateStrata() { return eStrataUnknown; } diff --git a/lldb/source/Plugins/ObjectFile/XCOFF/ObjectFileXCOFF.h b/lldb/source/Plugins/ObjectFile/XCOFF/ObjectFileXCOFF.h index 3a33b97b9e8da1..a155441135bfcb 100644 --- a/lldb/source/Plugins/ObjectFile/XCOFF/ObjectFileXCOFF.h +++ b/lldb/source/Plugins/ObjectFile/XCOFF/ObjectFileXCOFF.h @@ -70,6 +70,8 @@ class ObjectFileXCOFF : public lldb_private::ObjectFile { uint32_t GetAddressByteSize() const override; + lldb_private::AddressClass GetAddressClass(lldb::addr_t file_addr) override; + void ParseSymtab(lldb_private::Symtab &symtab) override; bool IsStripped() override; @@ -98,9 +100,65 @@ class ObjectFileXCOFF : public lldb_private::ObjectFile { const lldb::ProcessSP &process_sp, lldb::addr_t header_addr); protected: + typedef struct xcoff_header { + uint16_t magic; + uint16_t nsects; + uint32_t modtime; + uint64_t symoff; + uint32_t nsyms; + uint16_t auxhdrsize; + uint16_t flags; + } xcoff_header_t; + + typedef struct xcoff_aux_header { + uint16_t AuxMagic; + uint16_t Version; + uint32_t ReservedForDebugger; + uint64_t TextStartAddr; + uint64_t DataStartAddr; + uint64_t TOCAnchorAddr; + uint16_t SecNumOfEntryPoint; + uint16_t SecNumOfText; + uint16_t SecNumOfData; + uint16_t SecNumOfTOC; + uint16_t SecNumOfLoader; + uint16_t SecNumOfBSS; + uint16_t MaxAlignOfText; + uint16_t MaxAlignOfData; + uint16_t ModuleType; + uint8_t CpuFlag; + uint8_t CpuType; + uint8_t TextPageSize; + uint8_t DataPageSize; + uint8_t StackPageSize; + uint8_t FlagAndTDataAlignment; + uint64_t TextSize; + uint64_t InitDataSize; + uint64_t BssDataSize; + uint64_t EntryPointAddr; + uint64_t MaxStackSize; + uint64_t MaxDataSize; + uint16_t SecNumOfTData; + uint16_t SecNumOfTBSS; + uint16_t XCOFF64Flag; + } xcoff_aux_header_t; + + static bool ParseXCOFFHeader(lldb_private::DataExtractor &data, + lldb::offset_t *offset_ptr, + xcoff_header_t &xcoff_header); + bool ParseXCOFFOptionalHeader(lldb_private::DataExtractor &data, + lldb::offset_t *offset_ptr); + static lldb::WritableDataBufferSP MapFileDataWritable(const lldb_private::FileSpec &file, uint64_t Size, uint64_t Offset); + +private: + bool CreateBinary(); + + xcoff_header_t m_xcoff_header; + xcoff_aux_header_t m_xcoff_aux_header; + std::unique_ptr<llvm::object::XCOFFObjectFile> m_binary; }; #endif // LLDB_SOURCE_PLUGINS_OBJECTFILE_XCOFF_OBJECTFILE_H _______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits