Skip to content

Commit ca4cd08

Browse files
[lldb][AIX] Added XCOFF Object File Header for AIX (#111814)
Added XCOFF Object File Header for AIX. Added base functionality for XCOFF support. Will enhance the files in incremental PRs Details about XCOFF file format on AIX: [XCOFF](https://www.ibm.com/docs/en/aix/7.3?topic=formats-xcoff-object-file-format)
1 parent 469ac11 commit ca4cd08

File tree

7 files changed

+343
-0
lines changed

7 files changed

+343
-0
lines changed

lldb/source/Plugins/ObjectFile/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,5 +6,6 @@ add_subdirectory(Mach-O)
66
add_subdirectory(Minidump)
77
add_subdirectory(PDB)
88
add_subdirectory(PECOFF)
9+
add_subdirectory(XCOFF)
910
add_subdirectory(Placeholder)
1011
add_subdirectory(wasm)
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
add_lldb_library(lldbPluginObjectFileXCOFF PLUGIN
2+
ObjectFileXCOFF.cpp
3+
4+
LINK_LIBS
5+
lldbCore
6+
lldbHost
7+
lldbSymbol
8+
lldbTarget
9+
LINK_COMPONENTS
10+
BinaryFormat
11+
Object
12+
Support
13+
)
Lines changed: 191 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,191 @@
1+
//===-- ObjectFileXCOFF.cpp
2+
//-------------------------------------------------===//
3+
//
4+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
5+
// See https://llvm.org/LICENSE.txt for license information.
6+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7+
//
8+
//===----------------------------------------------------------------------===//
9+
10+
#include "ObjectFileXCOFF.h"
11+
12+
#include <algorithm>
13+
#include <cassert>
14+
#include <cstring>
15+
#include <unordered_map>
16+
17+
#include "lldb/Core/Module.h"
18+
#include "lldb/Core/ModuleSpec.h"
19+
#include "lldb/Core/PluginManager.h"
20+
#include "lldb/Core/Progress.h"
21+
#include "lldb/Core/Section.h"
22+
#include "lldb/Host/FileSystem.h"
23+
#include "lldb/Symbol/SymbolContext.h"
24+
#include "lldb/Target/Process.h"
25+
#include "lldb/Target/Target.h"
26+
#include "lldb/Utility/ArchSpec.h"
27+
#include "lldb/Utility/DataBufferHeap.h"
28+
#include "lldb/Utility/FileSpecList.h"
29+
#include "lldb/Utility/LLDBLog.h"
30+
#include "lldb/Utility/Log.h"
31+
#include "lldb/Utility/RangeMap.h"
32+
#include "lldb/Utility/Status.h"
33+
#include "lldb/Utility/Stream.h"
34+
#include "llvm/ADT/StringRef.h"
35+
#include "llvm/BinaryFormat/XCOFF.h"
36+
#include "llvm/Object/XCOFFObjectFile.h"
37+
#include "llvm/Support/MemoryBuffer.h"
38+
39+
using namespace llvm;
40+
using namespace lldb;
41+
using namespace lldb_private;
42+
43+
LLDB_PLUGIN_DEFINE(ObjectFileXCOFF)
44+
45+
// FIXME: target 64bit at this moment.
46+
47+
// Static methods.
48+
void ObjectFileXCOFF::Initialize() {
49+
PluginManager::RegisterPlugin(GetPluginNameStatic(),
50+
GetPluginDescriptionStatic(), CreateInstance,
51+
CreateMemoryInstance, GetModuleSpecifications);
52+
}
53+
54+
void ObjectFileXCOFF::Terminate() {
55+
PluginManager::UnregisterPlugin(CreateInstance);
56+
}
57+
58+
ObjectFile *ObjectFileXCOFF::CreateInstance(const lldb::ModuleSP &module_sp,
59+
DataBufferSP data_sp,
60+
lldb::offset_t data_offset,
61+
const lldb_private::FileSpec *file,
62+
lldb::offset_t file_offset,
63+
lldb::offset_t length) {
64+
if (!data_sp) {
65+
data_sp = MapFileData(*file, length, file_offset);
66+
if (!data_sp)
67+
return nullptr;
68+
data_offset = 0;
69+
}
70+
if (!ObjectFileXCOFF::MagicBytesMatch(data_sp, data_offset, length))
71+
return nullptr;
72+
// Update the data to contain the entire file if it doesn't already
73+
if (data_sp->GetByteSize() < length) {
74+
data_sp = MapFileData(*file, length, file_offset);
75+
if (!data_sp)
76+
return nullptr;
77+
data_offset = 0;
78+
}
79+
auto objfile_up = std::make_unique<ObjectFileXCOFF>(
80+
module_sp, data_sp, data_offset, file, file_offset, length);
81+
if (!objfile_up)
82+
return nullptr;
83+
84+
return objfile_up.release();
85+
}
86+
87+
ObjectFile *ObjectFileXCOFF::CreateMemoryInstance(
88+
const lldb::ModuleSP &module_sp, WritableDataBufferSP data_sp,
89+
const lldb::ProcessSP &process_sp, lldb::addr_t header_addr) {
90+
return nullptr;
91+
}
92+
93+
size_t ObjectFileXCOFF::GetModuleSpecifications(
94+
const lldb_private::FileSpec &file, lldb::DataBufferSP &data_sp,
95+
lldb::offset_t data_offset, lldb::offset_t file_offset,
96+
lldb::offset_t length, lldb_private::ModuleSpecList &specs) {
97+
const size_t initial_count = specs.GetSize();
98+
99+
if (ObjectFileXCOFF::MagicBytesMatch(data_sp, 0, data_sp->GetByteSize())) {
100+
ArchSpec arch_spec =
101+
ArchSpec(eArchTypeXCOFF, XCOFF::TCPU_PPC64, LLDB_INVALID_CPUTYPE);
102+
ModuleSpec spec(file, arch_spec);
103+
spec.GetArchitecture().SetArchitecture(eArchTypeXCOFF, XCOFF::TCPU_PPC64,
104+
LLDB_INVALID_CPUTYPE,
105+
llvm::Triple::AIX);
106+
specs.Append(spec);
107+
}
108+
return specs.GetSize() - initial_count;
109+
}
110+
111+
static uint32_t XCOFFHeaderSizeFromMagic(uint32_t magic) {
112+
switch (magic) {
113+
/* TODO: 32bit not supported yet
114+
case XCOFF::XCOFF32:
115+
return sizeof(struct llvm::object::XCOFFFileHeader32);
116+
*/
117+
118+
case XCOFF::XCOFF64:
119+
return sizeof(struct llvm::object::XCOFFFileHeader64);
120+
break;
121+
122+
default:
123+
break;
124+
}
125+
return 0;
126+
}
127+
128+
bool ObjectFileXCOFF::MagicBytesMatch(DataBufferSP &data_sp,
129+
lldb::addr_t data_offset,
130+
lldb::addr_t data_length) {
131+
lldb_private::DataExtractor data;
132+
data.SetData(data_sp, data_offset, data_length);
133+
data.SetByteOrder(eByteOrderBig);
134+
lldb::offset_t offset = 0;
135+
uint16_t magic = data.GetU16(&offset);
136+
return XCOFFHeaderSizeFromMagic(magic) != 0;
137+
}
138+
139+
bool ObjectFileXCOFF::ParseHeader() { return false; }
140+
141+
ByteOrder ObjectFileXCOFF::GetByteOrder() const { return eByteOrderBig; }
142+
143+
bool ObjectFileXCOFF::IsExecutable() const { return true; }
144+
145+
uint32_t ObjectFileXCOFF::GetAddressByteSize() const { return 8; }
146+
147+
void ObjectFileXCOFF::ParseSymtab(Symtab &lldb_symtab) {}
148+
149+
bool ObjectFileXCOFF::IsStripped() { return false; }
150+
151+
void ObjectFileXCOFF::CreateSections(SectionList &unified_section_list) {}
152+
153+
void ObjectFileXCOFF::Dump(Stream *s) {}
154+
155+
ArchSpec ObjectFileXCOFF::GetArchitecture() {
156+
ArchSpec arch_spec =
157+
ArchSpec(eArchTypeXCOFF, XCOFF::TCPU_PPC64, LLDB_INVALID_CPUTYPE);
158+
return arch_spec;
159+
}
160+
161+
UUID ObjectFileXCOFF::GetUUID() { return UUID(); }
162+
163+
uint32_t ObjectFileXCOFF::GetDependentModules(FileSpecList &files) { return 0; }
164+
165+
ObjectFile::Type ObjectFileXCOFF::CalculateType() { return eTypeExecutable; }
166+
167+
ObjectFile::Strata ObjectFileXCOFF::CalculateStrata() { return eStrataUnknown; }
168+
169+
lldb::WritableDataBufferSP
170+
ObjectFileXCOFF::MapFileDataWritable(const FileSpec &file, uint64_t Size,
171+
uint64_t Offset) {
172+
return FileSystem::Instance().CreateWritableDataBuffer(file.GetPath(), Size,
173+
Offset);
174+
}
175+
176+
ObjectFileXCOFF::ObjectFileXCOFF(const lldb::ModuleSP &module_sp,
177+
DataBufferSP data_sp,
178+
lldb::offset_t data_offset,
179+
const FileSpec *file,
180+
lldb::offset_t file_offset,
181+
lldb::offset_t length)
182+
: ObjectFile(module_sp, file, file_offset, length, data_sp, data_offset) {
183+
if (file)
184+
m_file = *file;
185+
}
186+
187+
ObjectFileXCOFF::ObjectFileXCOFF(const lldb::ModuleSP &module_sp,
188+
DataBufferSP header_data_sp,
189+
const lldb::ProcessSP &process_sp,
190+
addr_t header_addr)
191+
: ObjectFile(module_sp, process_sp, header_addr, header_data_sp) {}
Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
//===-- ObjectFileXCOFF.h --------------------------------------- -*- C++
2+
//-*-===//
3+
//
4+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
5+
// See https://llvm.org/LICENSE.txt for license information.
6+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7+
//
8+
//===----------------------------------------------------------------------===//
9+
10+
#ifndef LLDB_SOURCE_PLUGINS_OBJECTFILE_XCOFF_OBJECTFILEXCOFF_H
11+
#define LLDB_SOURCE_PLUGINS_OBJECTFILE_XCOFF_OBJECTFILEXCOFF_H
12+
13+
#include <cstdint>
14+
15+
#include <vector>
16+
17+
#include "lldb/Symbol/ObjectFile.h"
18+
#include "lldb/Utility/ArchSpec.h"
19+
#include "lldb/Utility/FileSpec.h"
20+
#include "lldb/Utility/UUID.h"
21+
#include "lldb/lldb-private.h"
22+
#include "llvm/Object/XCOFFObjectFile.h"
23+
24+
/// \class ObjectFileXCOFF
25+
/// Generic XCOFF object file reader.
26+
///
27+
/// This class provides a generic XCOFF (32/64 bit) reader plugin implementing
28+
/// the ObjectFile protocol.
29+
class ObjectFileXCOFF : public lldb_private::ObjectFile {
30+
public:
31+
// Static Functions
32+
static void Initialize();
33+
34+
static void Terminate();
35+
36+
static llvm::StringRef GetPluginNameStatic() { return "xcoff"; }
37+
38+
static llvm::StringRef GetPluginDescriptionStatic() {
39+
return "XCOFF object file reader.";
40+
}
41+
42+
static lldb_private::ObjectFile *
43+
CreateInstance(const lldb::ModuleSP &module_sp, lldb::DataBufferSP data_sp,
44+
lldb::offset_t data_offset, const lldb_private::FileSpec *file,
45+
lldb::offset_t file_offset, lldb::offset_t length);
46+
47+
static lldb_private::ObjectFile *CreateMemoryInstance(
48+
const lldb::ModuleSP &module_sp, lldb::WritableDataBufferSP data_sp,
49+
const lldb::ProcessSP &process_sp, lldb::addr_t header_addr);
50+
51+
static size_t GetModuleSpecifications(const lldb_private::FileSpec &file,
52+
lldb::DataBufferSP &data_sp,
53+
lldb::offset_t data_offset,
54+
lldb::offset_t file_offset,
55+
lldb::offset_t length,
56+
lldb_private::ModuleSpecList &specs);
57+
58+
static bool MagicBytesMatch(lldb::DataBufferSP &data_sp, lldb::addr_t offset,
59+
lldb::addr_t length);
60+
61+
// PluginInterface protocol
62+
llvm::StringRef GetPluginName() override { return GetPluginNameStatic(); }
63+
64+
// ObjectFile Protocol.
65+
bool ParseHeader() override;
66+
67+
lldb::ByteOrder GetByteOrder() const override;
68+
69+
bool IsExecutable() const override;
70+
71+
uint32_t GetAddressByteSize() const override;
72+
73+
void ParseSymtab(lldb_private::Symtab &symtab) override;
74+
75+
bool IsStripped() override;
76+
77+
void CreateSections(lldb_private::SectionList &unified_section_list) override;
78+
79+
void Dump(lldb_private::Stream *s) override;
80+
81+
lldb_private::ArchSpec GetArchitecture() override;
82+
83+
lldb_private::UUID GetUUID() override;
84+
85+
uint32_t GetDependentModules(lldb_private::FileSpecList &files) override;
86+
87+
ObjectFile::Type CalculateType() override;
88+
89+
ObjectFile::Strata CalculateStrata() override;
90+
91+
ObjectFileXCOFF(const lldb::ModuleSP &module_sp, lldb::DataBufferSP data_sp,
92+
lldb::offset_t data_offset,
93+
const lldb_private::FileSpec *file, lldb::offset_t offset,
94+
lldb::offset_t length);
95+
96+
ObjectFileXCOFF(const lldb::ModuleSP &module_sp,
97+
lldb::DataBufferSP header_data_sp,
98+
const lldb::ProcessSP &process_sp, lldb::addr_t header_addr);
99+
100+
protected:
101+
static lldb::WritableDataBufferSP
102+
MapFileDataWritable(const lldb_private::FileSpec &file, uint64_t Size,
103+
uint64_t Offset);
104+
};
105+
106+
#endif // LLDB_SOURCE_PLUGINS_OBJECTFILE_XCOFF_OBJECTFILE_H
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
# RUN: yaml2obj %s -o %t
2+
# RUN: lldb-test object-file %t | FileCheck %s
3+
4+
# CHECK: Plugin name: xcoff
5+
# CHECK: Architecture: powerpc64-ibm-aix
6+
# CHECK: Executable: true
7+
# CHECK: Stripped: false
8+
# CHECK: Type: executable
9+
# CHECK: Strata: unknown
10+
11+
--- !XCOFF
12+
FileHeader:
13+
MagicNumber: 0x1F7
14+
NumberOfSections: 1
15+
CreationTime: 000000000
16+
Flags: 0x0000
17+
Sections:
18+
- Name: .text
19+
Address: 0x100000438
20+
Size: 0x38
21+
FileOffsetToData: 0x0
22+
FileOffsetToLineNumbers: 0x0
23+
NumberOfLineNumbers: 0x0
24+
Flags: [ STYP_TEXT ]
25+
SectionData: E8C20000E94204
26+
StringTable: {}
27+
...

lldb/tools/lldb-server/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ if(CMAKE_SYSTEM_NAME MATCHES "Darwin")
2020
list(APPEND LLDB_PLUGINS lldbPluginObjectFileMachO)
2121
elseif(CMAKE_SYSTEM_NAME MATCHES "Windows")
2222
list(APPEND LLDB_PLUGINS lldbPluginObjectFilePECOFF)
23+
elseif(CMAKE_SYSTEM_NAME MATCHES "AIX")
24+
list(APPEND LLDB_PLUGINS lldbPluginObjectFileXCOFF)
2325
else()
2426
list(APPEND LLDB_PLUGINS lldbPluginObjectFileELF)
2527
endif()

lldb/tools/lldb-server/SystemInitializerLLGS.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,9 @@ using HostObjectFile = ObjectFileMachO;
1414
#elif defined(_WIN32)
1515
#include "Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.h"
1616
using HostObjectFile = ObjectFilePECOFF;
17+
#elif defined(_AIX)
18+
#include "Plugins/ObjectFile/XCOFF/ObjectFileXCOFF.h"
19+
using HostObjectFile = ObjectFileXCOFF;
1720
#else
1821
#include "Plugins/ObjectFile/ELF/ObjectFileELF.h"
1922
using HostObjectFile = ObjectFileELF;

0 commit comments

Comments
 (0)