Skip to content

Commit 349ec00

Browse files
[AIX][Coredump] AIX Coredump debugging Implementation (#25)
Creates a general framework to be able to debug an AIX generated coredump file. At this point, we are only supporting 64-bit core files using this general framework. With this implementation, LLDB can recognise and debug any 64-bit AIX coredump file. Most of the generic debugging commands work after this: # bin/lldb --core /home/dhruv/LLDB/tests/core (lldb) target create --core "/home/dhruv/LLDB/tests/core" Core file '/home/dhruv/LLDB/tests/core' (powerpc64) was loaded. (lldb) bt * thread #1, stop reason = SIGSEGV * frame #0: 0x0000000100000940 coretest64`main at core.c:5 frame #1: 0x00000001000004ac coretest64`__start + 116 (lldb) process status Process 18446744071562067991 stopped * thread #1, stop reason = SIGSEGV frame #0: 0x0000000100000940 coretest64`main at core.c:5 2 char *str; 3 int a = 10; 4 str = "GfG"; -> 5 *(str+1) = 'n'; 6 return a; 7 } And others like memory read, image list, image dump sections, disassembly etc
1 parent 04c8834 commit 349ec00

16 files changed

+1484
-1
lines changed

lldb/source/Plugins/DynamicLoader/AIX-DYLD/DynamicLoaderAIXDYLD.cpp

Lines changed: 61 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -228,6 +228,65 @@ void DynamicLoaderAIXDYLD::ResolveExecutableModule(
228228
target.SetExecutableModule(module_sp, eLoadDependentsNo);
229229
}
230230

231+
bool DynamicLoaderAIXDYLD::IsCoreFile() const {
232+
return !m_process->IsLiveDebugSession();
233+
}
234+
235+
void DynamicLoaderAIXDYLD::FillCoreLoaderData(lldb_private::DataExtractor &data,
236+
uint64_t loader_offset, uint64_t loader_size ) {
237+
238+
static char *buffer = (char *)malloc(loader_size);
239+
struct ld_info ldinfo[64];
240+
char *buffer_complete;
241+
struct ld_info *ptr;
242+
int i = 0;
243+
244+
Log *log = GetLog(LLDBLog::DynamicLoader);
245+
LLDB_LOGF(log, "DynamicLoaderAIXDYLD::%s()", __FUNCTION__);
246+
ByteOrder byteorder = data.GetByteOrder();
247+
data.ExtractBytes(loader_offset, loader_size, eByteOrderBig, buffer);
248+
buffer_complete = buffer + loader_size;
249+
ldinfo[0].ldinfo_next = 1;
250+
251+
while (ldinfo[i++].ldinfo_next != 0) {
252+
253+
ptr = (struct ld_info *)buffer;
254+
ldinfo[i].ldinfo_next = ptr->ldinfo_next;
255+
ldinfo[i].ldinfo_flags = ptr->ldinfo_flags;
256+
ldinfo[i].ldinfo_core = ptr->ldinfo_core;
257+
ldinfo[i].ldinfo_textorg = ptr->ldinfo_textorg;
258+
ldinfo[i].ldinfo_textsize = ptr->ldinfo_textsize;
259+
ldinfo[i].ldinfo_dataorg = ptr->ldinfo_dataorg;
260+
ldinfo[i].ldinfo_datasize = ptr->ldinfo_datasize;
261+
262+
char *filename = &ptr->ldinfo_filename[0];
263+
char *membername = filename + (strlen(filename) + 1);
264+
strcpy(ldinfo[i].ldinfo_filename, filename);
265+
266+
buffer += ptr->ldinfo_next;
267+
struct ld_info *ptr2 = &(ldinfo[i]);
268+
char *pathName = ptr2->ldinfo_filename;
269+
char pathWithMember[PATH_MAX] = {0};
270+
if (strlen(membername) > 0) {
271+
sprintf(pathWithMember, "%s(%s)", pathName, membername);
272+
} else {
273+
sprintf(pathWithMember, "%s", pathName);
274+
}
275+
276+
FileSpec file(pathWithMember);
277+
ModuleSpec module_spec(file, m_process->GetTarget().GetArchitecture());
278+
LLDB_LOGF(log, "Module :%s", pathWithMember);
279+
if (ModuleSP module_sp = m_process->GetTarget().GetOrCreateModule(module_spec, true /* notify */)) {
280+
UpdateLoadedSectionsByType(module_sp, LLDB_INVALID_ADDRESS, (lldb::addr_t)ptr2->ldinfo_textorg, false, 1);
281+
UpdateLoadedSectionsByType(module_sp, LLDB_INVALID_ADDRESS, (lldb::addr_t)ptr2->ldinfo_dataorg, false, 2);
282+
// FIXME: .tdata, .bss
283+
}
284+
if (ptr2->ldinfo_next == 0) {
285+
ptr2 = nullptr;
286+
}
287+
}
288+
}
289+
231290
void DynamicLoaderAIXDYLD::DidAttach() {
232291
Log *log = GetLog(LLDBLog::DynamicLoader);
233292
LLDB_LOGF(log, "DynamicLoaderAIXDYLD::%s()", __FUNCTION__);
@@ -361,7 +420,8 @@ void DynamicLoaderAIXDYLD::DidLaunch() {
361420
#endif
362421
}
363422

364-
Status DynamicLoaderAIXDYLD::CanLoadImage() { return Status(); }
423+
Status DynamicLoaderAIXDYLD::CanLoadImage() {
424+
return Status(); }
365425

366426
ThreadPlanSP
367427
DynamicLoaderAIXDYLD::GetStepThroughTrampolinePlan(Thread &thread,

lldb/source/Plugins/DynamicLoader/AIX-DYLD/DynamicLoaderAIXDYLD.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,9 @@ class DynamicLoaderAIXDYLD : public DynamicLoader {
3333
lldb::addr_t module_addr);
3434
void OnUnloadModule(lldb::addr_t module_addr);
3535

36+
void FillCoreLoaderData(lldb_private::DataExtractor &data,
37+
uint64_t loader_offset, uint64_t loader_size);
38+
3639
void DidAttach() override;
3740
void DidLaunch() override;
3841
Status CanLoadImage() override;
@@ -49,6 +52,9 @@ class DynamicLoaderAIXDYLD : public DynamicLoader {
4952
/// Loads Module from inferior process.
5053
void ResolveExecutableModule(lldb::ModuleSP &module_sp);
5154

55+
/// Returns true if the process is for a core file.
56+
bool IsCoreFile() const;
57+
5258
private:
5359
std::map<lldb::ModuleSP, lldb::addr_t> m_loaded_modules;
5460
};
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
add_lldb_library(lldbPluginObjectFileAIXCore PLUGIN
2+
ObjectFileAIXCore.cpp
3+
4+
LINK_LIBS
5+
lldbCore
6+
lldbHost
7+
lldbSymbol
8+
lldbTarget
9+
lldbUtility
10+
lldbPluginProcessUtility
11+
LINK_COMPONENTS
12+
Support
13+
)
Lines changed: 254 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,254 @@
1+
//===-- ObjectFileAIXCore.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 "ObjectFileAIXCore.h"
10+
11+
#include <algorithm>
12+
#include <cassert>
13+
#include <unordered_map>
14+
#include <string.h>
15+
16+
#include "lldb/Utility/FileSpecList.h"
17+
#include "lldb/Core/Module.h"
18+
#include "lldb/Core/ModuleSpec.h"
19+
#include "lldb/Core/PluginManager.h"
20+
#include "lldb/Host/FileSystem.h"
21+
#include "lldb/Symbol/SymbolContext.h"
22+
#include "lldb/Target/Process.h"
23+
#include "lldb/Target/Target.h"
24+
#include "lldb/Utility/ArchSpec.h"
25+
#include "lldb/Utility/DataBufferHeap.h"
26+
#include "lldb/Utility/LLDBLog.h"
27+
#include "lldb/Utility/Log.h"
28+
#include "lldb/Utility/Stream.h"
29+
#include "llvm/ADT/StringRef.h"
30+
#include "llvm/BinaryFormat/XCOFF.h"
31+
#include "llvm/Support/MemoryBuffer.h"
32+
#include "llvm/Object/XCOFFObjectFile.h"
33+
34+
using namespace llvm;
35+
using namespace lldb;
36+
using namespace lldb_private;
37+
38+
LLDB_PLUGIN_DEFINE(ObjectFileAIXCore)
39+
40+
enum CoreVersion : uint64_t {AIXCORE32 = 0xFEEDDB1, AIXCORE64 = 0xFEEDDB2};
41+
42+
bool m_is_core = false;
43+
44+
// Static methods.
45+
void ObjectFileAIXCore::Initialize() {
46+
PluginManager::RegisterPlugin(GetPluginNameStatic(),
47+
GetPluginDescriptionStatic(), CreateInstance,
48+
CreateMemoryInstance, GetModuleSpecifications);
49+
}
50+
51+
void ObjectFileAIXCore::Terminate() {
52+
PluginManager::UnregisterPlugin(CreateInstance);
53+
}
54+
55+
ObjectFile *ObjectFileAIXCore::CreateInstance(const lldb::ModuleSP &module_sp,
56+
DataBufferSP data_sp,
57+
lldb::offset_t data_offset,
58+
const lldb_private::FileSpec *file,
59+
lldb::offset_t file_offset,
60+
lldb::offset_t length) {
61+
62+
if(m_is_core)
63+
{
64+
65+
bool mapped_writable = false;
66+
if (!data_sp) {
67+
data_sp = MapFileDataWritable(*file, length, file_offset);
68+
if (!data_sp)
69+
return nullptr;
70+
data_offset = 0;
71+
mapped_writable = true;
72+
}
73+
74+
assert(data_sp);
75+
76+
const uint8_t *magic = data_sp->GetBytes() + data_offset;
77+
78+
// Update the data to contain the entire file if it doesn't already
79+
if (data_sp->GetByteSize() < length) {
80+
data_sp = MapFileDataWritable(*file, length, file_offset);
81+
if (!data_sp)
82+
return nullptr;
83+
data_offset = 0;
84+
mapped_writable = true;
85+
magic = data_sp->GetBytes();
86+
}
87+
88+
// If we didn't map the data as writable take ownership of the buffer.
89+
if (!mapped_writable) {
90+
data_sp = std::make_shared<DataBufferHeap>(data_sp->GetBytes(),
91+
data_sp->GetByteSize());
92+
data_offset = 0;
93+
magic = data_sp->GetBytes();
94+
}
95+
96+
std::unique_ptr<ObjectFileAIXCore> objfile_up(new ObjectFileAIXCore(
97+
module_sp, data_sp, data_offset, file, file_offset, length));
98+
ArchSpec spec = objfile_up->GetArchitecture();
99+
objfile_up->SetModulesArchitecture(spec);
100+
return objfile_up.release();
101+
102+
}
103+
}
104+
105+
ObjectFile *ObjectFileAIXCore::CreateMemoryInstance(
106+
const lldb::ModuleSP &module_sp, WritableDataBufferSP data_sp,
107+
const lldb::ProcessSP &process_sp, lldb::addr_t header_addr) {
108+
return nullptr;
109+
}
110+
111+
size_t ObjectFileAIXCore::GetModuleSpecifications(
112+
const lldb_private::FileSpec &file, lldb::DataBufferSP &data_sp,
113+
lldb::offset_t data_offset, lldb::offset_t file_offset,
114+
lldb::offset_t length, lldb_private::ModuleSpecList &specs) {
115+
const size_t initial_count = specs.GetSize();
116+
117+
if (ObjectFileAIXCore::MagicBytesMatch(data_sp, 0, data_sp->GetByteSize())) {
118+
// Need new ArchType???
119+
ArchSpec arch_spec = ArchSpec(eArchTypeXCOFF, XCOFF::TCPU_PPC64, LLDB_INVALID_CPUTYPE);
120+
ModuleSpec spec(file, arch_spec);
121+
spec.GetArchitecture().SetArchitecture(eArchTypeXCOFF, XCOFF::TCPU_PPC64, LLDB_INVALID_CPUTYPE, llvm::Triple::AIX);
122+
specs.Append(spec);
123+
}
124+
return specs.GetSize() - initial_count;
125+
}
126+
127+
static uint32_t AIXCoreHeaderCheckFromMagic(uint32_t magic) {
128+
129+
Log *log = GetLog(LLDBLog::Modules);
130+
switch (magic) {
131+
case AIXCORE32:
132+
LLDB_LOGF(log, "ObjectFileAIXCore: 32-bit not supported");
133+
break;
134+
case AIXCORE64:
135+
m_is_core = true;
136+
return 1;
137+
break;
138+
}
139+
return 0;
140+
}
141+
142+
bool ObjectFileAIXCore::MagicBytesMatch(DataBufferSP &data_sp,
143+
lldb::addr_t data_offset,
144+
lldb::addr_t data_length) {
145+
lldb_private::DataExtractor data;
146+
data.SetData(data_sp, data_offset, data_length);
147+
lldb::offset_t offset = 0;
148+
offset += 4; // Skipping to the coredump version
149+
uint32_t magic = data.GetU32(&offset);
150+
return AIXCoreHeaderCheckFromMagic(magic) != 0;
151+
}
152+
153+
bool ObjectFileAIXCore::ParseHeader() {
154+
155+
return false;
156+
}
157+
158+
ByteOrder ObjectFileAIXCore::GetByteOrder() const {
159+
return eByteOrderBig;
160+
}
161+
162+
bool ObjectFileAIXCore::IsExecutable() const {
163+
return false;
164+
}
165+
166+
uint32_t ObjectFileAIXCore::GetAddressByteSize() const {
167+
return 8;
168+
}
169+
170+
AddressClass ObjectFileAIXCore::GetAddressClass(addr_t file_addr) {
171+
return AddressClass::eUnknown;
172+
}
173+
174+
lldb::SymbolType ObjectFileAIXCore::MapSymbolType(llvm::object::SymbolRef::Type sym_type) {
175+
if (sym_type == llvm::object::SymbolRef::ST_Function)
176+
return lldb::eSymbolTypeCode;
177+
else if (sym_type == llvm::object::SymbolRef::ST_Data)
178+
return lldb::eSymbolTypeData;
179+
return lldb::eSymbolTypeInvalid;
180+
}
181+
182+
void ObjectFileAIXCore::ParseSymtab(Symtab &lldb_symtab) {
183+
}
184+
185+
bool ObjectFileAIXCore::IsStripped() {
186+
return false;
187+
}
188+
189+
void ObjectFileAIXCore::CreateSections(SectionList &unified_section_list) {
190+
}
191+
192+
void ObjectFileAIXCore::Dump(Stream *s) {
193+
}
194+
195+
ArchSpec ObjectFileAIXCore::GetArchitecture() {
196+
ArchSpec arch_spec = ArchSpec(eArchTypeXCOFF, XCOFF::TCPU_PPC64, LLDB_INVALID_CPUTYPE);
197+
return arch_spec;
198+
}
199+
200+
UUID ObjectFileAIXCore::GetUUID() {
201+
return UUID();
202+
}
203+
204+
uint32_t ObjectFileAIXCore::GetDependentModules(FileSpecList &files) {
205+
206+
auto original_size = files.GetSize();
207+
return files.GetSize() - original_size;
208+
}
209+
210+
Address ObjectFileAIXCore::GetImageInfoAddress(Target *target) {
211+
return Address();
212+
}
213+
214+
lldb_private::Address ObjectFileAIXCore::GetBaseAddress() {
215+
return lldb_private::Address();
216+
}
217+
ObjectFile::Type ObjectFileAIXCore::CalculateType() {
218+
return eTypeCoreFile;
219+
}
220+
221+
ObjectFile::Strata ObjectFileAIXCore::CalculateStrata() {
222+
return eStrataUnknown;
223+
}
224+
225+
std::vector<ObjectFile::LoadableData>
226+
ObjectFileAIXCore::GetLoadableData(Target &target) {
227+
std::vector<LoadableData> loadables;
228+
return loadables;
229+
}
230+
231+
lldb::WritableDataBufferSP
232+
ObjectFileAIXCore::MapFileDataWritable(const FileSpec &file, uint64_t Size,
233+
uint64_t Offset) {
234+
return FileSystem::Instance().CreateWritableDataBuffer(file.GetPath(), Size,
235+
Offset);
236+
}
237+
238+
ObjectFileAIXCore::ObjectFileAIXCore(const lldb::ModuleSP &module_sp,
239+
DataBufferSP data_sp, lldb::offset_t data_offset,
240+
const FileSpec *file, lldb::offset_t file_offset,
241+
lldb::offset_t length)
242+
: ObjectFile(module_sp, file, file_offset, length, data_sp, data_offset)
243+
{
244+
if (file)
245+
m_file = *file;
246+
}
247+
248+
ObjectFileAIXCore::ObjectFileAIXCore(const lldb::ModuleSP &module_sp,
249+
DataBufferSP header_data_sp,
250+
const lldb::ProcessSP &process_sp,
251+
addr_t header_addr)
252+
: ObjectFile(module_sp, process_sp, header_addr, header_data_sp)
253+
{
254+
}

0 commit comments

Comments
 (0)