From 5c3aeeaf5f6a43279738314ae0c184fb38694120 Mon Sep 17 00:00:00 2001 From: Jason Shui Date: Sat, 7 Oct 2023 19:48:12 +0800 Subject: [PATCH] feat: register operator api refine with optional Signed-off-by: Jason Shui --- .vscode/launch.json | 47 +++++++++++++++++++++++++++++++++ CMakeLists.txt | 2 +- include/debugger.h | 3 +++ include/register_operator.h | 13 +++++++--- scripts/install_env.bash | 14 +++++----- src/debugger.cpp | 22 +++++++++++++--- src/register_operator.cpp | 52 +++++++++++++++++++++---------------- test/debugger_test.cpp | 4 +++ 8 files changed, 121 insertions(+), 36 deletions(-) create mode 100644 .vscode/launch.json diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..69f8008 --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,47 @@ +{ + "configurations": [ + + { + "type": "lldb", + "request": "launch", + "name": "LLDB Launch", + "program": "${workspaceFolder}/build/shuidb", + "args": [ + "${workspaceFolder}/build/hello_world" + ], + "cwd": "${workspaceFolder}" + }, + { + "name": "(gdb) Launch", + "type": "cppdbg", + "request": "launch", + "program": "${workspaceFolder}/build/shuidb", + "args": [ + "${workspaceFolder}/build/hello_world" + ], + "stopAtEntry": false, + "cwd": "${fileDirname}", + "environment": [], + "externalConsole": false, + "MIMode": "gdb", + "miDebuggerPath": "/usr/bin/gdb", + "setupCommands": [ + { + "description": "Test", + "text": "python import sys;sys.path.insert(0, '/usr/share/gcc/python');from libstdcxx.v6.printers import register_libstdcxx_printers;register_libstdcxx_printers(None)", + "ignoreFailures": false + }, + { + "description": "Enable pretty-printing for gdb", + "text": "-enable-pretty-printing", + "ignoreFailures": true + }, + { + "description": "Set Disassembly Flavor to Intel", + "text": "-gdb-set disassembly-flavor intel", + "ignoreFailures": true + } + ] + } + ] +} \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt index a915ff6..685c64c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -3,7 +3,7 @@ set(CMAKE_C_COMPILER clang) set(CMAKE_CXX_COMPILER clang++) set(CMAKE_CXX_STANDARD 20) set(CMAKE_CXX_STANDARD_REQUIRED ON) -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g -stdlib=libc++ -std=c++20 -Wall") +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g -stdlib=libc++ -Wall") project(shuidb) add_library(linenoise external/linenoise/linenoise.c) diff --git a/include/debugger.h b/include/debugger.h index aa1d041..54a08d2 100644 --- a/include/debugger.h +++ b/include/debugger.h @@ -20,10 +20,12 @@ #include #include +#include #include #include #include "breakpoint.h" +#include "register_def.h" #include "type_def.h" namespace shuidb { @@ -37,6 +39,7 @@ class Debugger { void ContinueExecution(); void SetBreakPointAtAddress(std::intptr_t addr); std::vector GetBreakPoints() const; + std::optional> GetRegisters() const; void DumpRegisters() const; StatusType ReadRegister(const std::string& reg_name) const; StatusType WriteRegister(const std::string& reg_name, const uint64_t& val); diff --git a/include/register_operator.h b/include/register_operator.h index 5a169a8..a7ee3dc 100644 --- a/include/register_operator.h +++ b/include/register_operator.h @@ -16,9 +16,11 @@ #pragma once +#include #include #include +#include #include "register_def.h" @@ -26,13 +28,16 @@ namespace shuidb { class RegisterOperator { public: - static uint64_t GetRegisterValue(pid_t pid, Register reg); + static std::optional> GetRegisters( + pid_t pid); + static std::optional GetRegisterValue(pid_t pid, Register reg); + static uint64_t GetRegisterValue(const user_regs_struct& regs, + const Register reg); static void SetRegisterValue(pid_t pid, Register reg, uint64_t value); - static uint64_t GetRegisterValueFromDwarfRegister(pid_t pid, int dwarf_r); + static std::optional GetRegisterValueFromDwarfRegister(pid_t pid, + int dwarf_r); static std::string GetRegisterName(Register reg); static std::optional GetRegisterFromName(const std::string& name); - static void DumpRegisters(pid_t pid); - static bool IsRegisterValid(const std::string& reg_name); }; } // namespace shuidb \ No newline at end of file diff --git a/scripts/install_env.bash b/scripts/install_env.bash index 5742b1d..34c99ca 100755 --- a/scripts/install_env.bash +++ b/scripts/install_env.bash @@ -1,10 +1,12 @@ #!/bin/bash +set -x -sudo bash -c "$(wget -O - https://apt.llvm.org/llvm.sh)" -sudo apt install -y libc++abi-17-dev libc++-17-dev lldb-17 clangd-17 -sudo update-alternatives --install /usr/bin/clang clang /usr/bin/clang-17 100 -sudo update-alternatives --install /usr/bin/clang++ clang++ /usr/bin/clang++-17 100 -sudo update-alternatives --install /usr/bin/lldb lldb /usr/bin/lldb-17 100 -sudo update-alternatives --install /usr/bin/clangd clangd /usr/bin/clangd-17 100 +LLVM_VERSION=16 + +sudo bash -c "$(wget -O - https://apt.llvm.org/llvm.sh)" -- $LLVM_VERSION all +sudo update-alternatives --install /usr/bin/clang clang /usr/bin/clang-$LLVM_VERSION 300 +sudo update-alternatives --install /usr/bin/clang++ clang++ /usr/bin/clang++-$LLVM_VERSION 300 +sudo update-alternatives --install /usr/bin/lldb lldb /usr/bin/lldb-$LLVM_VERSION 300 +sudo update-alternatives --install /usr/bin/clangd clangd /usr/bin/clangd-$LLVM_VERSION 300 clang -v clang++ -v \ No newline at end of file diff --git a/src/debugger.cpp b/src/debugger.cpp index e3233d0..683815a 100644 --- a/src/debugger.cpp +++ b/src/debugger.cpp @@ -118,14 +118,26 @@ std::vector Debugger::GetBreakPoints() const { return bp_addrs; } +std::optional> Debugger::GetRegisters() + const { + if (!IsRunning()) { + PR(ERROR) << "Process is not running"; + return std::nullopt; + } + return RegisterOperator::GetRegisters(pid_); +} + void Debugger::DumpRegisters() const { if (!IsRunning()) { PR(ERROR) << "Process is not running"; return; } - + auto registers_map = GetRegisters(); PR(INFO) << "Registers:"; - RegisterOperator::DumpRegisters(pid_); + for (const auto& [reg, val] : registers_map.value()) { + PR(RAW) << RegisterOperator::GetRegisterName(reg) << " 0x" << std::hex + << std::setfill('0') << std::setw(16) << val; + } } StatusType Debugger::ReadRegister(const std::string& reg_name) const { @@ -140,8 +152,12 @@ StatusType Debugger::ReadRegister(const std::string& reg_name) const { return StatusType::kUnknownRegister; } auto reg_value = RegisterOperator::GetRegisterValue(pid_, reg.value()); + if (!reg_value.has_value()) { + PR(ERROR) << "Failed to get register value"; + return StatusType::kFailed; + } PR(INFO) << reg_name << " 0x" << std::setfill('0') << std::setw(16) - << std::hex << reg_value; + << std::hex << reg_value.value(); return StatusType::kSuccess; } diff --git a/src/register_operator.cpp b/src/register_operator.cpp index 05928f0..9b33fa3 100644 --- a/src/register_operator.cpp +++ b/src/register_operator.cpp @@ -19,15 +19,39 @@ #include #include -#include +#include +#include -#include "utils/output_utils.hpp" +#include "register_def.h" namespace shuidb { -uint64_t RegisterOperator::GetRegisterValue(pid_t pid, Register reg) { +std::optional> +RegisterOperator::GetRegisters(pid_t pid) { user_regs_struct regs; - ptrace(PTRACE_GETREGS, pid, nullptr, ®s); + if (ptrace(PTRACE_GETREGS, pid, nullptr, ®s) == -1) { + return std::nullopt; + } + + std::unordered_map registers; + for (const auto& rd : kRegisterDescriptors) { + registers[rd.reg] = RegisterOperator::GetRegisterValue(pid, rd.reg).value(); + } + return registers; +}; + +std::optional RegisterOperator::GetRegisterValue(pid_t pid, + Register reg) { + user_regs_struct regs; + if (ptrace(PTRACE_GETREGS, pid, nullptr, ®s) == -1) { + return std::nullopt; + } + + return RegisterOperator::GetRegisterValue(regs, reg); +}; + +uint64_t RegisterOperator::GetRegisterValue(const user_regs_struct& regs, + const Register reg) { switch (reg) { case Register::RAX: return regs.rax; @@ -176,8 +200,8 @@ void RegisterOperator::SetRegisterValue(pid_t pid, Register reg, ptrace(PTRACE_SETREGS, pid, nullptr, ®s); }; -uint64_t RegisterOperator::GetRegisterValueFromDwarfRegister(pid_t pid, - int dwarf_r) { +std::optional RegisterOperator::GetRegisterValueFromDwarfRegister( + pid_t pid, int dwarf_r) { auto it = std::find_if( kRegisterDescriptors.begin(), kRegisterDescriptors.end(), [dwarf_r](const RegDescriptor& rd) { return rd.dwarf_r == dwarf_r; }); @@ -214,20 +238,4 @@ std::optional RegisterOperator::GetRegisterFromName( return it->reg; }; -void RegisterOperator::DumpRegisters(pid_t pid) { - for (const auto& rd : kRegisterDescriptors) { - auto value = GetRegisterValue(pid, rd.reg); - PR_RAW << rd.name << " 0x" << std::setfill('0') << std::setw(16) << std::hex - << value; - } -}; - -bool RegisterOperator::IsRegisterValid(const std::string& reg_name) { - auto it = std::find_if( - kRegisterDescriptors.begin(), kRegisterDescriptors.end(), - [reg_name](const RegDescriptor& rd) { return rd.name == reg_name; }); - - return it != kRegisterDescriptors.end(); -}; - } // namespace shuidb \ No newline at end of file diff --git a/test/debugger_test.cpp b/test/debugger_test.cpp index fa46158..0303845 100644 --- a/test/debugger_test.cpp +++ b/test/debugger_test.cpp @@ -56,4 +56,8 @@ TEST_F(DebuggerTest, BreakPointTest) { ASSERT_EQ(debugger_->IsRunning(), true); } +TEST_F(DebuggerTest, DumpRegistersTest) { + debugger_->DumpRegisters(); +} + } // namespace shuidb