Skip to content

[lldb][LoongArch64] Add support for LoongArch64 in elf-core for lldb #112296

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Oct 21, 2024
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ RegisterContextPOSIX_loongarch64::GetRegisterInfoAtIndex(size_t reg) {
}

size_t RegisterContextPOSIX_loongarch64::GetRegisterSetCount() {
return m_register_info_up->GetRegisterCount();
return m_register_info_up->GetRegisterSetCount();
}

const lldb_private::RegisterSet *
Expand Down
1 change: 1 addition & 0 deletions lldb/source/Plugins/Process/elf-core/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ add_lldb_library(lldbPluginProcessElfCore PLUGIN
RegisterContextPOSIXCore_s390x.cpp
RegisterContextPOSIXCore_x86_64.cpp
RegisterContextPOSIXCore_riscv64.cpp
RegisterContextPOSIXCore_loongarch64.cpp
RegisterUtilities.cpp

LINK_LIBS
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
//===-- RegisterContextPOSIXCore_loongarch64.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 "RegisterContextPOSIXCore_loongarch64.h"

#include "lldb/Utility/DataBufferHeap.h"

using namespace lldb_private;

std::unique_ptr<RegisterContextCorePOSIX_loongarch64>
RegisterContextCorePOSIX_loongarch64::Create(Thread &thread,
const ArchSpec &arch,
const DataExtractor &gpregset,
llvm::ArrayRef<CoreNote> notes) {
return std::unique_ptr<RegisterContextCorePOSIX_loongarch64>(
new RegisterContextCorePOSIX_loongarch64(
thread,
std::make_unique<RegisterInfoPOSIX_loongarch64>(arch, Flags()),
gpregset, notes));
}

RegisterContextCorePOSIX_loongarch64::RegisterContextCorePOSIX_loongarch64(
Thread &thread,
std::unique_ptr<RegisterInfoPOSIX_loongarch64> register_info,
const DataExtractor &gpregset, llvm::ArrayRef<CoreNote> notes)
: RegisterContextPOSIX_loongarch64(thread, std::move(register_info)) {

m_gpr.SetData(std::make_shared<DataBufferHeap>(gpregset.GetDataStart(),
gpregset.GetByteSize()));
m_gpr.SetByteOrder(gpregset.GetByteOrder());

ArchSpec arch = m_register_info_up->GetTargetArchitecture();
DataExtractor fpregset = getRegset(notes, arch.GetTriple(), FPR_Desc);
m_fpr.SetData(std::make_shared<DataBufferHeap>(fpregset.GetDataStart(),
fpregset.GetByteSize()));
m_fpr.SetByteOrder(fpregset.GetByteOrder());
}

RegisterContextCorePOSIX_loongarch64::~RegisterContextCorePOSIX_loongarch64() =
default;

bool RegisterContextCorePOSIX_loongarch64::ReadGPR() { return true; }

bool RegisterContextCorePOSIX_loongarch64::ReadFPR() { return true; }

bool RegisterContextCorePOSIX_loongarch64::WriteGPR() {
assert(false && "Writing registers is not allowed for core dumps");
return false;
}

bool RegisterContextCorePOSIX_loongarch64::WriteFPR() {
assert(false && "Writing registers is not allowed for core dumps");
return false;
}

bool RegisterContextCorePOSIX_loongarch64::ReadRegister(
const RegisterInfo *reg_info, RegisterValue &value) {
const uint8_t *src = nullptr;
lldb::offset_t offset = reg_info->byte_offset;

if (IsGPR(reg_info->kinds[lldb::eRegisterKindLLDB])) {
src = m_gpr.GetDataStart();
} else if (IsFPR(reg_info->kinds[lldb::eRegisterKindLLDB])) {
src = m_fpr.GetDataStart();
offset -= GetGPRSize();
} else {
return false;
}

Status error;
value.SetFromMemoryData(*reg_info, src + offset, reg_info->byte_size,
lldb::eByteOrderLittle, error);
return error.Success();
}

bool RegisterContextCorePOSIX_loongarch64::WriteRegister(
const RegisterInfo *reg_info, const RegisterValue &value) {
return false;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
//===-- RegisterContextPOSIXCore_loongarch64.h ----------------------*- C++ -*-===//
//
// 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
//
//===----------------------------------------------------------------------===//

#ifndef LLDB_SOURCE_PLUGINS_PROCESS_ELF_CORE_REGISTERCONTEXTPOSIXCORE_LOONGARCH64_H
#define LLDB_SOURCE_PLUGINS_PROCESS_ELF_CORE_REGISTERCONTEXTPOSIXCORE_LOONGARCH64_H

#include "Plugins/Process/Utility/RegisterContextPOSIX_loongarch64.h"
#include "Plugins/Process/Utility/RegisterInfoPOSIX_loongarch64.h"

#include "Plugins/Process/elf-core/RegisterUtilities.h"
#include "lldb/Target/Thread.h"
#include "lldb/Utility/DataExtractor.h"
#include "lldb/Utility/RegisterValue.h"

#include <memory>

class RegisterContextCorePOSIX_loongarch64 : public RegisterContextPOSIX_loongarch64 {
public:
static std::unique_ptr<RegisterContextCorePOSIX_loongarch64>
Create(lldb_private::Thread &thread, const lldb_private::ArchSpec &arch,
const lldb_private::DataExtractor &gpregset,
llvm::ArrayRef<lldb_private::CoreNote> notes);

~RegisterContextCorePOSIX_loongarch64() override;

bool ReadRegister(const lldb_private::RegisterInfo *reg_info,
lldb_private::RegisterValue &value) override;

bool WriteRegister(const lldb_private::RegisterInfo *reg_info,
const lldb_private::RegisterValue &value) override;

protected:
RegisterContextCorePOSIX_loongarch64(
lldb_private::Thread &thread,
std::unique_ptr<RegisterInfoPOSIX_loongarch64> register_info,
const lldb_private::DataExtractor &gpregset,
llvm::ArrayRef<lldb_private::CoreNote> notes);

bool ReadGPR() override;

bool ReadFPR() override;

bool WriteGPR() override;

bool WriteFPR() override;

private:
lldb_private::DataExtractor m_gpr;
lldb_private::DataExtractor m_fpr;
};

#endif // LLDB_SOURCE_PLUGINS_PROCESS_ELF_CORE_REGISTERCONTEXTPOSIXCORE_LOONGARCH64_H
6 changes: 6 additions & 0 deletions lldb/source/Plugins/Process/elf-core/ThreadElfCore.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
#include "RegisterContextLinuxCore_x86_64.h"
#include "RegisterContextPOSIXCore_arm.h"
#include "RegisterContextPOSIXCore_arm64.h"
#include "RegisterContextPOSIXCore_loongarch64.h"
#include "RegisterContextPOSIXCore_mips64.h"
#include "RegisterContextPOSIXCore_powerpc.h"
#include "RegisterContextPOSIXCore_ppc64le.h"
Expand Down Expand Up @@ -171,6 +172,7 @@ ThreadElfCore::CreateRegisterContextForFrame(StackFrame *frame) {

if (!reg_interface && arch.GetMachine() != llvm::Triple::aarch64 &&
arch.GetMachine() != llvm::Triple::arm &&
arch.GetMachine() != llvm::Triple::loongarch64 &&
arch.GetMachine() != llvm::Triple::riscv64) {
LLDB_LOGF(log, "elf-core::%s:: Architecture(%d) or OS(%d) not supported",
__FUNCTION__, arch.GetMachine(), arch.GetTriple().getOS());
Expand All @@ -187,6 +189,10 @@ ThreadElfCore::CreateRegisterContextForFrame(StackFrame *frame) {
*this, std::make_unique<RegisterInfoPOSIX_arm>(arch), m_gpregset_data,
m_notes);
break;
case llvm::Triple::loongarch64:
m_thread_reg_ctx_sp = RegisterContextCorePOSIX_loongarch64::Create(
*this, arch, m_gpregset_data, m_notes);
break;
case llvm::Triple::riscv64:
m_thread_reg_ctx_sp = RegisterContextCorePOSIX_riscv64::Create(
*this, arch, m_gpregset_data, m_notes);
Expand Down
113 changes: 113 additions & 0 deletions lldb/test/API/functionalities/postmortem/elf-core/TestLinuxCore.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,15 @@ class LinuxCoreTestCase(TestBase):
_ppc64le_pid = 28147
_riscv64_gpr_fpr_pid = 1089
_riscv64_gpr_only_pid = 97
_loongarch64_pid = 456735

_aarch64_regions = 4
_i386_regions = 4
_x86_64_regions = 5
_s390x_regions = 2
_ppc64le_regions = 2
_riscv64_regions = 4
_loongarch64_regions = 4

@skipIfLLVMTargetMissing("AArch64")
def test_aarch64(self):
Expand Down Expand Up @@ -82,6 +84,16 @@ def test_riscv64_gpr_only(self):
"a.out",
)

@skipIfLLVMTargetMissing("LoongArch")
def test_loongarch64(self):
"""Test that lldb can read the process information from an loongarch64 linux core file."""
self.do_test(
"linux-loongarch64",
self._loongarch64_pid,
self._loongarch64_regions,
"a.out",
)

@skipIfLLVMTargetMissing("X86")
def test_same_pid_running(self):
"""Test that we read the information from the core correctly even if we have a running
Expand Down Expand Up @@ -833,6 +845,107 @@ def test_riscv64_regs_gpr_only(self):
substrs=["registers were unavailable"],
)

@skipIfLLVMTargetMissing("LoongArch")
def test_loongarch64_regs(self):
# check registers using 64 bit LoongArch64 core file containing GP-registers only
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe this is a terminology difference. To me GP register would mean "general purpose" and not include floating point registers. But perhaps you always have an FPU so they are kinda general in that they always exist.

I'd just change it to "GP and FP registers" to prevent any confusion.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is confusion, I will revise it later.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is confusion, I will revise it later.

target = self.dbg.CreateTarget(None)
self.assertTrue(target, VALID_TARGET)
process = target.LoadCore("linux-loongarch64.core")

values = {}
values["r0"] = "0x0000000000000000"
values["r1"] = "0x000000012000016c"
values["r2"] = "0x0000000000000000"
values["r3"] = "0x00007ffffb8249e0"
values["r4"] = "0x0000000000000000"
values["r5"] = "0x000000012000010c"
values["r6"] = "0x0000000000000000"
values["r7"] = "0x0000000000000000"
values["r8"] = "0x0000000000000000"
values["r9"] = "0x0000000000000000"
values["r10"] = "0x0000000000000000"
values["r11"] = "0x00000000000000dd"
values["r12"] = "0x0000000000000000"
values["r13"] = "0x000000000000002f"
values["r14"] = "0x0000000000000000"
values["r15"] = "0x0000000000000000"
values["r16"] = "0x0000000000000000"
values["r17"] = "0x0000000000000000"
values["r18"] = "0x0000000000000000"
values["r19"] = "0x0000000000000000"
values["r20"] = "0x0000000000000000"
values["r21"] = "0x0000000000000000"
values["r22"] = "0x00007ffffb824a10"
values["r23"] = "0x0000000000000000"
values["r24"] = "0x0000000000000000"
values["r25"] = "0x0000000000000000"
values["r26"] = "0x0000000000000000"
values["r27"] = "0x0000000000000000"
values["r28"] = "0x0000000000000000"
values["r29"] = "0x0000000000000000"
values["r30"] = "0x0000000000000000"
values["r31"] = "0x0000000000000000"
values["orig_a0"] = "0x0000555556b62d50"
values["pc"] = "0x000000012000012c"

fpr_values = {}
fpr_values["f0"] = "0x00000000ffffff05"
fpr_values["f1"] = "0x2525252525252525"
fpr_values["f2"] = "0x2525252525560005"
fpr_values["f3"] = "0x000000000000ffff"
fpr_values["f4"] = "0x0000000000000000"
fpr_values["f5"] = "0x0000000000000008"
fpr_values["f6"] = "0x0f0e0d0c0b0a0908"
fpr_values["f7"] = "0xffffffffffffffff"
fpr_values["f8"] = "0x6261747563657845"
fpr_values["f9"] = "0x766173206562206c"
fpr_values["f10"] = "0xffffffffffffffff"
fpr_values["f11"] = "0xffffffffffffffff"
fpr_values["f12"] = "0xffffffffffffffff"
fpr_values["f13"] = "0xffffffffffffffff"
fpr_values["f14"] = "0xffffffffffffffff"
fpr_values["f15"] = "0xffffffffffffffff"
fpr_values["f16"] = "0xffffffffffffffff"
fpr_values["f17"] = "0xffffffffffffffff"
fpr_values["f18"] = "0xffffffffffffffff"
fpr_values["f19"] = "0xffffffffffffffff"
fpr_values["f20"] = "0xffffffffffffffff"
fpr_values["f21"] = "0xffffffffffffffff"
fpr_values["f22"] = "0xffffffffffffffff"
fpr_values["f23"] = "0xffffffffffffffff"
fpr_values["f24"] = "0xffffffffffffffff"
fpr_values["f25"] = "0xffffffffffffffff"
fpr_values["f26"] = "0xffffffffffffffff"
fpr_values["f27"] = "0xffffffffffffffff"
fpr_values["f28"] = "0xffffffffffffffff"
fpr_values["f29"] = "0xffffffffffffffff"
fpr_values["f30"] = "0xffffffffffffffff"
fpr_values["f31"] = "0xffffffffffffffff"
fpr_values["fcc0"] = "0x01"
fpr_values["fcc1"] = "0x00"
fpr_values["fcc2"] = "0x01"
fpr_values["fcc3"] = "0x01"
fpr_values["fcc4"] = "0x01"
fpr_values["fcc5"] = "0x01"
fpr_values["fcc6"] = "0x00"
fpr_values["fcc7"] = "0x01"
fpr_values["fcsr"] = "0x00"
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are these 8 bit registers?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fcc* is 8 bit . fcsr is 4 byte.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not like fcc registers, fcsr is 32bit.

(lldb) register read fcsr
    fcsr = 0x00000000

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok


for regname, value in values.items():
self.expect(
"register read {}".format(regname),
substrs=["{} = {}".format(regname, value)],
)

for regname, value in fpr_values.items():
self.expect(
"register read {}".format(regname),
substrs=["{} = {}".format(regname, value)],
)

self.expect("register read --all")


def test_get_core_file_api(self):
"""
Test SBProcess::GetCoreFile() API can successfully get the core file.
Expand Down
Binary file not shown.
Binary file not shown.
Loading