Skip to content

Commit 096ab51

Browse files
authored
[lldb][MachO] MachO corefile support for riscv32 binaries (#137092)
Add support for reading a macho corefile with CPU_TYPE_RISCV and the riscv32 general purpose register file. I added code for the floating point and exception registers too, but haven't exercised this. If we start putting the full CSR register bank in a riscv corefile, it'll be in separate 4k byte chunks, but I don't have a corefile to test against that so I haven't written the code to read it. The RegisterContextDarwin_riscv32 is copied & in the style of the other RegisterContextDarwin classes; it's not the first choice I would make for representing this, but it wasn't worth changing for this cputype. rdar://145014653
1 parent 31c7997 commit 096ab51

File tree

7 files changed

+1931
-0
lines changed

7 files changed

+1931
-0
lines changed

lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp

Lines changed: 152 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
#include "Plugins/Process/Utility/RegisterContextDarwin_arm.h"
1313
#include "Plugins/Process/Utility/RegisterContextDarwin_arm64.h"
1414
#include "Plugins/Process/Utility/RegisterContextDarwin_i386.h"
15+
#include "Plugins/Process/Utility/RegisterContextDarwin_riscv32.h"
1516
#include "Plugins/Process/Utility/RegisterContextDarwin_x86_64.h"
1617
#include "lldb/Core/Debugger.h"
1718
#include "lldb/Core/Module.h"
@@ -769,6 +770,147 @@ class RegisterContextDarwin_arm64_Mach : public RegisterContextDarwin_arm64 {
769770
}
770771
};
771772

773+
class RegisterContextDarwin_riscv32_Mach
774+
: public RegisterContextDarwin_riscv32 {
775+
public:
776+
RegisterContextDarwin_riscv32_Mach(lldb_private::Thread &thread,
777+
const DataExtractor &data)
778+
: RegisterContextDarwin_riscv32(thread, 0) {
779+
SetRegisterDataFrom_LC_THREAD(data);
780+
}
781+
782+
void InvalidateAllRegisters() override {
783+
// Do nothing... registers are always valid...
784+
}
785+
786+
void SetRegisterDataFrom_LC_THREAD(const DataExtractor &data) {
787+
lldb::offset_t offset = 0;
788+
SetError(GPRRegSet, Read, -1);
789+
SetError(FPURegSet, Read, -1);
790+
SetError(EXCRegSet, Read, -1);
791+
SetError(CSRRegSet, Read, -1);
792+
bool done = false;
793+
while (!done) {
794+
int flavor = data.GetU32(&offset);
795+
uint32_t count = data.GetU32(&offset);
796+
lldb::offset_t next_thread_state = offset + (count * 4);
797+
switch (flavor) {
798+
case GPRRegSet:
799+
// x0-x31 + pc
800+
if (count >= 32) {
801+
for (uint32_t i = 0; i < 32; ++i)
802+
((uint32_t *)&gpr.x0)[i] = data.GetU32(&offset);
803+
gpr.pc = data.GetU32(&offset);
804+
SetError(GPRRegSet, Read, 0);
805+
}
806+
offset = next_thread_state;
807+
break;
808+
case FPURegSet: {
809+
// f0-f31 + fcsr
810+
if (count >= 32) {
811+
for (uint32_t i = 0; i < 32; ++i)
812+
((uint32_t *)&fpr.f0)[i] = data.GetU32(&offset);
813+
fpr.fcsr = data.GetU32(&offset);
814+
SetError(FPURegSet, Read, 0);
815+
}
816+
}
817+
offset = next_thread_state;
818+
break;
819+
case EXCRegSet:
820+
if (count == 3) {
821+
exc.exception = data.GetU32(&offset);
822+
exc.fsr = data.GetU32(&offset);
823+
exc.far = data.GetU32(&offset);
824+
SetError(EXCRegSet, Read, 0);
825+
}
826+
offset = next_thread_state;
827+
break;
828+
default:
829+
done = true;
830+
break;
831+
}
832+
}
833+
}
834+
835+
static bool Create_LC_THREAD(Thread *thread, Stream &data) {
836+
RegisterContextSP reg_ctx_sp(thread->GetRegisterContext());
837+
if (reg_ctx_sp) {
838+
RegisterContext *reg_ctx = reg_ctx_sp.get();
839+
840+
data.PutHex32(GPRRegSet); // Flavor
841+
data.PutHex32(GPRWordCount);
842+
PrintRegisterValue(reg_ctx, "x0", nullptr, 4, data);
843+
PrintRegisterValue(reg_ctx, "x1", nullptr, 4, data);
844+
PrintRegisterValue(reg_ctx, "x2", nullptr, 4, data);
845+
PrintRegisterValue(reg_ctx, "x3", nullptr, 4, data);
846+
PrintRegisterValue(reg_ctx, "x4", nullptr, 4, data);
847+
PrintRegisterValue(reg_ctx, "x5", nullptr, 4, data);
848+
PrintRegisterValue(reg_ctx, "x6", nullptr, 4, data);
849+
PrintRegisterValue(reg_ctx, "x7", nullptr, 4, data);
850+
PrintRegisterValue(reg_ctx, "x8", nullptr, 4, data);
851+
PrintRegisterValue(reg_ctx, "x9", nullptr, 4, data);
852+
PrintRegisterValue(reg_ctx, "x10", nullptr, 4, data);
853+
PrintRegisterValue(reg_ctx, "x11", nullptr, 4, data);
854+
PrintRegisterValue(reg_ctx, "x12", nullptr, 4, data);
855+
PrintRegisterValue(reg_ctx, "x13", nullptr, 4, data);
856+
PrintRegisterValue(reg_ctx, "x14", nullptr, 4, data);
857+
PrintRegisterValue(reg_ctx, "x15", nullptr, 4, data);
858+
PrintRegisterValue(reg_ctx, "x16", nullptr, 4, data);
859+
PrintRegisterValue(reg_ctx, "x17", nullptr, 4, data);
860+
PrintRegisterValue(reg_ctx, "x18", nullptr, 4, data);
861+
PrintRegisterValue(reg_ctx, "x19", nullptr, 4, data);
862+
PrintRegisterValue(reg_ctx, "x20", nullptr, 4, data);
863+
PrintRegisterValue(reg_ctx, "x21", nullptr, 4, data);
864+
PrintRegisterValue(reg_ctx, "x22", nullptr, 4, data);
865+
PrintRegisterValue(reg_ctx, "x23", nullptr, 4, data);
866+
PrintRegisterValue(reg_ctx, "x24", nullptr, 4, data);
867+
PrintRegisterValue(reg_ctx, "x25", nullptr, 4, data);
868+
PrintRegisterValue(reg_ctx, "x26", nullptr, 4, data);
869+
PrintRegisterValue(reg_ctx, "x27", nullptr, 4, data);
870+
PrintRegisterValue(reg_ctx, "x28", nullptr, 4, data);
871+
PrintRegisterValue(reg_ctx, "x29", nullptr, 4, data);
872+
PrintRegisterValue(reg_ctx, "x30", nullptr, 4, data);
873+
PrintRegisterValue(reg_ctx, "x31", nullptr, 4, data);
874+
PrintRegisterValue(reg_ctx, "pc", nullptr, 4, data);
875+
data.PutHex32(0); // uint32_t pad at the end
876+
877+
// Write out the EXC registers
878+
data.PutHex32(EXCRegSet);
879+
data.PutHex32(EXCWordCount);
880+
PrintRegisterValue(reg_ctx, "exception", nullptr, 4, data);
881+
PrintRegisterValue(reg_ctx, "fsr", nullptr, 4, data);
882+
PrintRegisterValue(reg_ctx, "far", nullptr, 4, data);
883+
return true;
884+
}
885+
return false;
886+
}
887+
888+
protected:
889+
int DoReadGPR(lldb::tid_t tid, int flavor, GPR &gpr) override { return -1; }
890+
891+
int DoReadFPU(lldb::tid_t tid, int flavor, FPU &fpu) override { return -1; }
892+
893+
int DoReadEXC(lldb::tid_t tid, int flavor, EXC &exc) override { return -1; }
894+
895+
int DoReadCSR(lldb::tid_t tid, int flavor, CSR &csr) override { return -1; }
896+
897+
int DoWriteGPR(lldb::tid_t tid, int flavor, const GPR &gpr) override {
898+
return 0;
899+
}
900+
901+
int DoWriteFPU(lldb::tid_t tid, int flavor, const FPU &fpu) override {
902+
return 0;
903+
}
904+
905+
int DoWriteEXC(lldb::tid_t tid, int flavor, const EXC &exc) override {
906+
return 0;
907+
}
908+
909+
int DoWriteCSR(lldb::tid_t tid, int flavor, const CSR &csr) override {
910+
return 0;
911+
}
912+
};
913+
772914
static uint32_t MachHeaderSizeFromMagic(uint32_t magic) {
773915
switch (magic) {
774916
case MH_MAGIC:
@@ -5827,6 +5969,11 @@ ObjectFileMachO::GetThreadContextAtIndex(uint32_t idx,
58275969
reg_ctx_sp =
58285970
std::make_shared<RegisterContextDarwin_x86_64_Mach>(thread, data);
58295971
break;
5972+
5973+
case llvm::MachO::CPU_TYPE_RISCV:
5974+
reg_ctx_sp =
5975+
std::make_shared<RegisterContextDarwin_riscv32_Mach>(thread, data);
5976+
break;
58305977
}
58315978
}
58325979
}
@@ -6695,6 +6842,11 @@ bool ObjectFileMachO::SaveCore(const lldb::ProcessSP &process_sp,
66956842
RegisterContextDarwin_x86_64_Mach::Create_LC_THREAD(
66966843
thread_sp.get(), LC_THREAD_datas[thread_idx]);
66976844
break;
6845+
6846+
case llvm::MachO::CPU_TYPE_RISCV:
6847+
RegisterContextDarwin_riscv32_Mach::Create_LC_THREAD(
6848+
thread_sp.get(), LC_THREAD_datas[thread_idx]);
6849+
break;
66986850
}
66996851
}
67006852
}

lldb/source/Plugins/Process/Utility/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ add_lldb_library(lldbPluginProcessUtility
2020
RegisterContextDarwin_arm.cpp
2121
RegisterContextDarwin_arm64.cpp
2222
RegisterContextDarwin_i386.cpp
23+
RegisterContextDarwin_riscv32.cpp
2324
RegisterContextDarwin_x86_64.cpp
2425
RegisterContextDummy.cpp
2526
RegisterContextFreeBSD_i386.cpp

0 commit comments

Comments
 (0)