mirror of
https://github.com/RGBCube/serenity
synced 2025-07-27 06:57:45 +00:00
LibDebug+Everywhere: Avoid void* -> FlatPtr -> void* dance
And limit the `void*` to the functions that interface the system (i.e. ptrace wrappers). This generally makes the code less riddled with casts.
This commit is contained in:
parent
b27b22a68c
commit
6d64b13a1b
15 changed files with 97 additions and 96 deletions
|
@ -129,27 +129,27 @@ OwnPtr<DebugSession> DebugSession::exec_and_attach(String const& command,
|
|||
return debug_session;
|
||||
}
|
||||
|
||||
bool DebugSession::poke(void* address, FlatPtr data)
|
||||
bool DebugSession::poke(FlatPtr address, FlatPtr data)
|
||||
{
|
||||
if (ptrace(PT_POKE, m_debuggee_pid, (void*)address, (void*)data) < 0) {
|
||||
if (ptrace(PT_POKE, m_debuggee_pid, bit_cast<void*>(address), bit_cast<void*>(data)) < 0) {
|
||||
perror("PT_POKE");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
Optional<FlatPtr> DebugSession::peek(void* address) const
|
||||
Optional<FlatPtr> DebugSession::peek(FlatPtr address) const
|
||||
{
|
||||
Optional<FlatPtr> result;
|
||||
auto rc = ptrace(PT_PEEK, m_debuggee_pid, address, nullptr);
|
||||
auto rc = ptrace(PT_PEEK, m_debuggee_pid, bit_cast<void*>(address), nullptr);
|
||||
if (errno == 0)
|
||||
result = static_cast<FlatPtr>(rc);
|
||||
return result;
|
||||
}
|
||||
|
||||
bool DebugSession::poke_debug(u32 register_index, FlatPtr data)
|
||||
bool DebugSession::poke_debug(u32 register_index, FlatPtr data) const
|
||||
{
|
||||
if (ptrace(PT_POKEDEBUG, m_debuggee_pid, reinterpret_cast<void*>(register_index), (void*)data) < 0) {
|
||||
if (ptrace(PT_POKEDEBUG, m_debuggee_pid, bit_cast<void*>(static_cast<FlatPtr>(register_index)), bit_cast<void*>(data)) < 0) {
|
||||
perror("PT_POKEDEBUG");
|
||||
return false;
|
||||
}
|
||||
|
@ -158,14 +158,14 @@ bool DebugSession::poke_debug(u32 register_index, FlatPtr data)
|
|||
|
||||
Optional<FlatPtr> DebugSession::peek_debug(u32 register_index) const
|
||||
{
|
||||
Optional<FlatPtr> result;
|
||||
int rc = ptrace(PT_PEEKDEBUG, m_debuggee_pid, reinterpret_cast<FlatPtr*>(register_index), nullptr);
|
||||
auto rc = ptrace(PT_PEEKDEBUG, m_debuggee_pid, bit_cast<void*>(static_cast<FlatPtr>(register_index)), nullptr);
|
||||
if (errno == 0)
|
||||
result = static_cast<FlatPtr>(rc);
|
||||
return result;
|
||||
return static_cast<FlatPtr>(rc);
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
bool DebugSession::insert_breakpoint(void* address)
|
||||
bool DebugSession::insert_breakpoint(FlatPtr address)
|
||||
{
|
||||
// We insert a software breakpoint by
|
||||
// patching the first byte of the instruction at 'address'
|
||||
|
@ -174,7 +174,7 @@ bool DebugSession::insert_breakpoint(void* address)
|
|||
if (m_breakpoints.contains(address))
|
||||
return false;
|
||||
|
||||
auto original_bytes = peek(reinterpret_cast<FlatPtr*>(address));
|
||||
auto original_bytes = peek(address);
|
||||
|
||||
if (!original_bytes.has_value())
|
||||
return false;
|
||||
|
@ -190,11 +190,11 @@ bool DebugSession::insert_breakpoint(void* address)
|
|||
return true;
|
||||
}
|
||||
|
||||
bool DebugSession::disable_breakpoint(void* address)
|
||||
bool DebugSession::disable_breakpoint(FlatPtr address)
|
||||
{
|
||||
auto breakpoint = m_breakpoints.get(address);
|
||||
VERIFY(breakpoint.has_value());
|
||||
if (!poke(reinterpret_cast<FlatPtr*>(reinterpret_cast<char*>(breakpoint.value().address)), breakpoint.value().original_first_word))
|
||||
if (!poke(breakpoint.value().address, breakpoint.value().original_first_word))
|
||||
return false;
|
||||
|
||||
auto bp = m_breakpoints.get(breakpoint.value().address).value();
|
||||
|
@ -203,14 +203,14 @@ bool DebugSession::disable_breakpoint(void* address)
|
|||
return true;
|
||||
}
|
||||
|
||||
bool DebugSession::enable_breakpoint(void* address)
|
||||
bool DebugSession::enable_breakpoint(FlatPtr address)
|
||||
{
|
||||
auto breakpoint = m_breakpoints.get(address);
|
||||
VERIFY(breakpoint.has_value());
|
||||
|
||||
VERIFY(breakpoint.value().state == BreakPointState::Disabled);
|
||||
|
||||
if (!poke(reinterpret_cast<FlatPtr*>(breakpoint.value().address), (breakpoint.value().original_first_word & ~(FlatPtr)0xff) | BREAKPOINT_INSTRUCTION))
|
||||
if (!poke(breakpoint.value().address, (breakpoint.value().original_first_word & ~static_cast<FlatPtr>(0xff)) | BREAKPOINT_INSTRUCTION))
|
||||
return false;
|
||||
|
||||
auto bp = m_breakpoints.get(breakpoint.value().address).value();
|
||||
|
@ -219,7 +219,7 @@ bool DebugSession::enable_breakpoint(void* address)
|
|||
return true;
|
||||
}
|
||||
|
||||
bool DebugSession::remove_breakpoint(void* address)
|
||||
bool DebugSession::remove_breakpoint(FlatPtr address)
|
||||
{
|
||||
if (!disable_breakpoint(address))
|
||||
return false;
|
||||
|
@ -228,12 +228,12 @@ bool DebugSession::remove_breakpoint(void* address)
|
|||
return true;
|
||||
}
|
||||
|
||||
bool DebugSession::breakpoint_exists(void* address) const
|
||||
bool DebugSession::breakpoint_exists(FlatPtr address) const
|
||||
{
|
||||
return m_breakpoints.contains(address);
|
||||
}
|
||||
|
||||
bool DebugSession::insert_watchpoint(void* address, u32 ebp)
|
||||
bool DebugSession::insert_watchpoint(FlatPtr address, u32 ebp)
|
||||
{
|
||||
auto current_register_status = peek_debug(DEBUG_CONTROL_REGISTER);
|
||||
if (!current_register_status.has_value())
|
||||
|
@ -250,7 +250,7 @@ bool DebugSession::insert_watchpoint(void* address, u32 ebp)
|
|||
return false;
|
||||
WatchPoint watchpoint { address, next_available_index, ebp };
|
||||
|
||||
if (!poke_debug(next_available_index, reinterpret_cast<uintptr_t>(address)))
|
||||
if (!poke_debug(next_available_index, bit_cast<FlatPtr>(address)))
|
||||
return false;
|
||||
|
||||
dr7_value |= (1u << (next_available_index * 2)); // Enable local breakpoint for our index
|
||||
|
@ -268,14 +268,14 @@ bool DebugSession::insert_watchpoint(void* address, u32 ebp)
|
|||
return true;
|
||||
}
|
||||
|
||||
bool DebugSession::remove_watchpoint(void* address)
|
||||
bool DebugSession::remove_watchpoint(FlatPtr address)
|
||||
{
|
||||
if (!disable_watchpoint(address))
|
||||
return false;
|
||||
return m_watchpoints.remove(address);
|
||||
}
|
||||
|
||||
bool DebugSession::disable_watchpoint(void* address)
|
||||
bool DebugSession::disable_watchpoint(FlatPtr address)
|
||||
{
|
||||
VERIFY(watchpoint_exists(address));
|
||||
auto watchpoint = m_watchpoints.get(address).value();
|
||||
|
@ -291,7 +291,7 @@ bool DebugSession::disable_watchpoint(void* address)
|
|||
return true;
|
||||
}
|
||||
|
||||
bool DebugSession::watchpoint_exists(void* address) const
|
||||
bool DebugSession::watchpoint_exists(FlatPtr address) const
|
||||
{
|
||||
return m_watchpoints.contains(address);
|
||||
}
|
||||
|
@ -308,7 +308,7 @@ PtraceRegisters DebugSession::get_registers() const
|
|||
|
||||
void DebugSession::set_registers(PtraceRegisters const& regs)
|
||||
{
|
||||
if (ptrace(PT_SETREGS, m_debuggee_pid, reinterpret_cast<void*>(&const_cast<PtraceRegisters&>(regs)), 0) < 0) {
|
||||
if (ptrace(PT_SETREGS, m_debuggee_pid, bit_cast<void*>(®s), 0) < 0) {
|
||||
perror("PT_SETREGS");
|
||||
VERIFY_NOT_REACHED();
|
||||
}
|
||||
|
@ -334,7 +334,7 @@ int DebugSession::continue_debuggee_and_wait(ContinueType type)
|
|||
return wstatus;
|
||||
}
|
||||
|
||||
void* DebugSession::single_step()
|
||||
FlatPtr DebugSession::single_step()
|
||||
{
|
||||
// Single stepping works by setting the x86 TRAP flag bit in the eflags register.
|
||||
// This flag causes the cpu to enter single-stepping mode, which causes
|
||||
|
@ -365,7 +365,7 @@ void* DebugSession::single_step()
|
|||
regs.rflags &= ~(TRAP_FLAG);
|
||||
#endif
|
||||
set_registers(regs);
|
||||
return (void*)regs.ip();
|
||||
return regs.ip();
|
||||
}
|
||||
|
||||
void DebugSession::detach()
|
||||
|
@ -390,8 +390,8 @@ Optional<DebugSession::InsertBreakpointAtSymbolResult> DebugSession::insert_brea
|
|||
if (!symbol.has_value())
|
||||
return IterationDecision::Continue;
|
||||
|
||||
auto breakpoint_address = symbol.value().value() + lib.base_address;
|
||||
bool rc = this->insert_breakpoint(reinterpret_cast<void*>(breakpoint_address));
|
||||
FlatPtr breakpoint_address = symbol->value() + lib.base_address;
|
||||
bool rc = this->insert_breakpoint(breakpoint_address);
|
||||
if (!rc)
|
||||
return IterationDecision::Break;
|
||||
|
||||
|
@ -408,7 +408,7 @@ Optional<DebugSession::InsertBreakpointAtSourcePositionResult> DebugSession::ins
|
|||
return {};
|
||||
|
||||
auto address = address_and_source_position.value().address;
|
||||
bool rc = this->insert_breakpoint(reinterpret_cast<void*>(address));
|
||||
bool rc = this->insert_breakpoint(address);
|
||||
if (!rc)
|
||||
return {};
|
||||
|
||||
|
|
|
@ -32,15 +32,15 @@ public:
|
|||
virtual ~DebugSession() override;
|
||||
|
||||
// ^Debug::ProcessInspector
|
||||
virtual bool poke(void* address, FlatPtr data) override;
|
||||
virtual Optional<FlatPtr> peek(void* address) const override;
|
||||
virtual bool poke(FlatPtr address, FlatPtr data) override;
|
||||
virtual Optional<FlatPtr> peek(FlatPtr address) const override;
|
||||
virtual PtraceRegisters get_registers() const override;
|
||||
virtual void set_registers(PtraceRegisters const&) override;
|
||||
virtual void for_each_loaded_library(Function<IterationDecision(LoadedLibrary const&)>) const override;
|
||||
|
||||
int pid() const { return m_debuggee_pid; }
|
||||
|
||||
bool poke_debug(u32 register_index, FlatPtr data);
|
||||
bool poke_debug(u32 register_index, FlatPtr data) const;
|
||||
Optional<FlatPtr> peek_debug(u32 register_index) const;
|
||||
|
||||
enum class BreakPointState {
|
||||
|
@ -49,7 +49,7 @@ public:
|
|||
};
|
||||
|
||||
struct BreakPoint {
|
||||
void* address { nullptr };
|
||||
FlatPtr address { 0 };
|
||||
FlatPtr original_first_word { 0 };
|
||||
BreakPointState state { BreakPointState::Disabled };
|
||||
};
|
||||
|
@ -70,22 +70,22 @@ public:
|
|||
|
||||
Optional<InsertBreakpointAtSourcePositionResult> insert_breakpoint(String const& filename, size_t line_number);
|
||||
|
||||
bool insert_breakpoint(void* address);
|
||||
bool disable_breakpoint(void* address);
|
||||
bool enable_breakpoint(void* address);
|
||||
bool remove_breakpoint(void* address);
|
||||
bool breakpoint_exists(void* address) const;
|
||||
bool insert_breakpoint(FlatPtr address);
|
||||
bool disable_breakpoint(FlatPtr address);
|
||||
bool enable_breakpoint(FlatPtr address);
|
||||
bool remove_breakpoint(FlatPtr address);
|
||||
bool breakpoint_exists(FlatPtr address) const;
|
||||
|
||||
struct WatchPoint {
|
||||
void* address { nullptr };
|
||||
FlatPtr address { 0 };
|
||||
u32 debug_register_index { 0 };
|
||||
u32 ebp { 0 };
|
||||
};
|
||||
|
||||
bool insert_watchpoint(void* address, u32 ebp);
|
||||
bool remove_watchpoint(void* address);
|
||||
bool disable_watchpoint(void* address);
|
||||
bool watchpoint_exists(void* address) const;
|
||||
bool insert_watchpoint(FlatPtr address, u32 ebp);
|
||||
bool remove_watchpoint(FlatPtr address);
|
||||
bool disable_watchpoint(FlatPtr address);
|
||||
bool watchpoint_exists(FlatPtr address) const;
|
||||
|
||||
void dump_breakpoints()
|
||||
{
|
||||
|
@ -104,7 +104,7 @@ public:
|
|||
int continue_debuggee_and_wait(ContinueType type = ContinueType::FreeRun);
|
||||
|
||||
// Returns the new eip
|
||||
void* single_step();
|
||||
FlatPtr single_step();
|
||||
|
||||
void detach();
|
||||
|
||||
|
@ -141,8 +141,8 @@ private:
|
|||
String m_source_root;
|
||||
bool m_is_debuggee_dead { false };
|
||||
|
||||
HashMap<void*, BreakPoint> m_breakpoints;
|
||||
HashMap<void*, WatchPoint> m_watchpoints;
|
||||
HashMap<FlatPtr, BreakPoint> m_breakpoints;
|
||||
HashMap<FlatPtr, WatchPoint> m_watchpoints;
|
||||
|
||||
// Maps from library name to LoadedLibrary object
|
||||
HashMap<String, NonnullOwnPtr<LoadedLibrary>> m_loaded_libraries;
|
||||
|
@ -216,8 +216,8 @@ void DebugSession::run(DesiredInitialDebugeeState initial_debugee_state, Callbac
|
|||
found_ebp = true;
|
||||
break;
|
||||
}
|
||||
auto return_address = peek(reinterpret_cast<u32*>(current_ebp + sizeof(FlatPtr)));
|
||||
auto next_ebp = peek(reinterpret_cast<u32*>(current_ebp));
|
||||
auto return_address = peek(current_ebp + sizeof(FlatPtr));
|
||||
auto next_ebp = peek(current_ebp);
|
||||
VERIFY(return_address.has_value());
|
||||
VERIFY(next_ebp.has_value());
|
||||
current_instruction = return_address.value();
|
||||
|
@ -235,11 +235,11 @@ void DebugSession::run(DesiredInitialDebugeeState initial_debugee_state, Callbac
|
|||
Optional<BreakPoint> current_breakpoint;
|
||||
|
||||
if (state == State::FreeRun || state == State::Syscall) {
|
||||
current_breakpoint = m_breakpoints.get((void*)((uintptr_t)current_instruction - 1));
|
||||
current_breakpoint = m_breakpoints.get(current_instruction - 1);
|
||||
if (current_breakpoint.has_value())
|
||||
state = State::FreeRun;
|
||||
} else {
|
||||
current_breakpoint = m_breakpoints.get((void*)current_instruction);
|
||||
current_breakpoint = m_breakpoints.get(current_instruction);
|
||||
}
|
||||
|
||||
if (current_breakpoint.has_value()) {
|
||||
|
@ -250,7 +250,7 @@ void DebugSession::run(DesiredInitialDebugeeState initial_debugee_state, Callbac
|
|||
// because the cpu has just executed the INT3 we patched into the instruction.
|
||||
// 2. We restore the original first byte of the instruction,
|
||||
// because it was patched with INT3.
|
||||
auto breakpoint_addr = reinterpret_cast<uintptr_t>(current_breakpoint.value().address);
|
||||
auto breakpoint_addr = bit_cast<FlatPtr>(current_breakpoint.value().address);
|
||||
#if ARCH(I386)
|
||||
regs.eip = breakpoint_addr;
|
||||
#else
|
||||
|
@ -278,8 +278,9 @@ void DebugSession::run(DesiredInitialDebugeeState initial_debugee_state, Callbac
|
|||
|
||||
bool did_single_step = false;
|
||||
|
||||
auto current_breakpoint_address = bit_cast<FlatPtr>(current_breakpoint.value().address);
|
||||
// Re-enable the breakpoint if it wasn't removed by the user
|
||||
if (current_breakpoint.has_value() && m_breakpoints.contains(current_breakpoint.value().address)) {
|
||||
if (current_breakpoint.has_value() && m_breakpoints.contains(current_breakpoint_address)) {
|
||||
// The current breakpoint was removed to make it transparent to the user.
|
||||
// We now want to re-enable it - the code execution flow could hit it again.
|
||||
// To re-enable the breakpoint, we first perform a single step and execute the
|
||||
|
@ -288,7 +289,7 @@ void DebugSession::run(DesiredInitialDebugeeState initial_debugee_state, Callbac
|
|||
// If the user manually inserted a breakpoint at the current instruction,
|
||||
// we need to disable that breakpoint because we want to singlestep over that
|
||||
// instruction (we re-enable it again later anyways).
|
||||
if (m_breakpoints.contains(current_breakpoint.value().address) && m_breakpoints.get(current_breakpoint.value().address).value().state == BreakPointState::Enabled) {
|
||||
if (m_breakpoints.contains(current_breakpoint_address) && m_breakpoints.get(current_breakpoint_address).value().state == BreakPointState::Enabled) {
|
||||
disable_breakpoint(current_breakpoint.value().address);
|
||||
}
|
||||
auto stopped_address = single_step();
|
||||
|
|
|
@ -62,7 +62,7 @@ void AbbreviationsMap::populate_map()
|
|||
}
|
||||
} while (current_attribute_specification.attribute != Attribute::None || current_attribute_specification.form != AttributeDataForm::None);
|
||||
|
||||
m_entries.set((u32)abbreviation_code, move(abbreviation_entry));
|
||||
m_entries.set(static_cast<u32>(abbreviation_code), move(abbreviation_entry));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -36,8 +36,8 @@ Value evaluate(ReadonlyBytes bytes, [[maybe_unused]] PtraceRegisters const& regs
|
|||
#endif
|
||||
|
||||
default:
|
||||
dbgln("DWARF expr addr: {}", (const void*)bytes.data());
|
||||
dbgln("unsupported opcode: {}", (u8)opcode);
|
||||
dbgln("DWARF expr addr: {:p}", bytes.data());
|
||||
dbgln("unsupported opcode: {}", opcode);
|
||||
VERIFY_NOT_REACHED();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,8 +15,8 @@ namespace Debug {
|
|||
class ProcessInspector {
|
||||
public:
|
||||
virtual ~ProcessInspector() { }
|
||||
virtual bool poke(void* address, FlatPtr data) = 0;
|
||||
virtual Optional<FlatPtr> peek(void* address) const = 0;
|
||||
virtual bool poke(FlatPtr address, FlatPtr data) = 0;
|
||||
virtual Optional<FlatPtr> peek(FlatPtr address) const = 0;
|
||||
virtual PtraceRegisters get_registers() const = 0;
|
||||
virtual void set_registers(PtraceRegisters const&) = 0;
|
||||
virtual void for_each_loaded_library(Function<IterationDecision(LoadedLibrary const&)>) const = 0;
|
||||
|
|
|
@ -10,8 +10,8 @@ namespace Debug::StackFrameUtils {
|
|||
|
||||
Optional<StackFrameInfo> get_info(ProcessInspector const& inspector, FlatPtr current_ebp)
|
||||
{
|
||||
auto return_address = inspector.peek(reinterpret_cast<u32*>(current_ebp + sizeof(FlatPtr)));
|
||||
auto next_ebp = inspector.peek(reinterpret_cast<u32*>(current_ebp));
|
||||
auto return_address = inspector.peek(current_ebp + sizeof(FlatPtr));
|
||||
auto next_ebp = inspector.peek(current_ebp);
|
||||
if (!return_address.has_value() || !next_ebp.has_value())
|
||||
return {};
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue