DebugSession.h 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350
  1. /*
  2. * Copyright (c) 2020, Itamar S. <itamar8910@gmail.com>
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #pragma once
  7. #include <AK/ByteString.h>
  8. #include <AK/Demangle.h>
  9. #include <AK/Function.h>
  10. #include <AK/HashMap.h>
  11. #include <AK/NonnullRefPtr.h>
  12. #include <AK/Optional.h>
  13. #include <AK/OwnPtr.h>
  14. #include <LibCore/MappedFile.h>
  15. #include <LibDebug/DebugInfo.h>
  16. #include <LibDebug/ProcessInspector.h>
  17. #include <signal.h>
  18. #include <stdio.h>
  19. #include <sys/arch/regs.h>
  20. #include <sys/ptrace.h>
  21. #include <sys/wait.h>
  22. #include <unistd.h>
  23. namespace Debug {
  24. class DebugSession : public ProcessInspector {
  25. public:
  26. static OwnPtr<DebugSession> exec_and_attach(ByteString const& command, ByteString source_root = {}, Function<ErrorOr<void>()> setup_child = {}, Function<void(float)> on_initialization_progress = {});
  27. static OwnPtr<DebugSession> attach(pid_t pid, ByteString source_root = {}, Function<void(float)> on_initialization_progress = {});
  28. virtual ~DebugSession() override;
  29. // ^Debug::ProcessInspector
  30. virtual bool poke(FlatPtr address, FlatPtr data) override;
  31. virtual Optional<FlatPtr> peek(FlatPtr address) const override;
  32. virtual PtraceRegisters get_registers() const override;
  33. virtual void set_registers(PtraceRegisters const&) override;
  34. virtual void for_each_loaded_library(Function<IterationDecision(LoadedLibrary const&)>) const override;
  35. int pid() const { return m_debuggee_pid; }
  36. bool poke_debug(u32 register_index, FlatPtr data) const;
  37. Optional<FlatPtr> peek_debug(u32 register_index) const;
  38. enum class BreakPointState {
  39. Enabled,
  40. Disabled,
  41. };
  42. struct BreakPoint {
  43. FlatPtr address { 0 };
  44. FlatPtr original_first_word { 0 };
  45. BreakPointState state { BreakPointState::Disabled };
  46. };
  47. struct InsertBreakpointAtSymbolResult {
  48. ByteString library_name;
  49. FlatPtr address { 0 };
  50. };
  51. Optional<InsertBreakpointAtSymbolResult> insert_breakpoint(ByteString const& symbol_name);
  52. struct InsertBreakpointAtSourcePositionResult {
  53. ByteString library_name;
  54. ByteString filename;
  55. size_t line_number { 0 };
  56. FlatPtr address { 0 };
  57. };
  58. Optional<InsertBreakpointAtSourcePositionResult> insert_breakpoint(ByteString const& filename, size_t line_number);
  59. bool insert_breakpoint(FlatPtr address);
  60. bool disable_breakpoint(FlatPtr address);
  61. bool enable_breakpoint(FlatPtr address);
  62. bool remove_breakpoint(FlatPtr address);
  63. bool breakpoint_exists(FlatPtr address) const;
  64. struct WatchPoint {
  65. FlatPtr address { 0 };
  66. u32 debug_register_index { 0 };
  67. u32 ebp { 0 };
  68. };
  69. bool insert_watchpoint(FlatPtr address, u32 ebp);
  70. bool remove_watchpoint(FlatPtr address);
  71. bool disable_watchpoint(FlatPtr address);
  72. bool watchpoint_exists(FlatPtr address) const;
  73. void dump_breakpoints()
  74. {
  75. for (auto addr : m_breakpoints.keys()) {
  76. dbgln("{}", addr);
  77. }
  78. }
  79. enum class ContinueType {
  80. FreeRun,
  81. Syscall,
  82. };
  83. void continue_debuggee(ContinueType type = ContinueType::FreeRun);
  84. void stop_debuggee();
  85. // Returns the wstatus result of waitpid()
  86. int continue_debuggee_and_wait(ContinueType type = ContinueType::FreeRun);
  87. // Returns the new eip
  88. FlatPtr single_step();
  89. void detach();
  90. enum DesiredInitialDebugeeState {
  91. Running,
  92. Stopped
  93. };
  94. template<typename Callback>
  95. void run(DesiredInitialDebugeeState, Callback);
  96. enum DebugDecision {
  97. Continue,
  98. SingleStep,
  99. ContinueBreakAtSyscall,
  100. Detach,
  101. Kill,
  102. };
  103. enum DebugBreakReason {
  104. Breakpoint,
  105. Syscall,
  106. Exited,
  107. };
  108. private:
  109. explicit DebugSession(pid_t, ByteString source_root, Function<void(float)> on_initialization_progress = {});
  110. // x86 breakpoint instruction "int3"
  111. static constexpr u8 BREAKPOINT_INSTRUCTION = 0xcc;
  112. ErrorOr<void> update_loaded_libs();
  113. int m_debuggee_pid { -1 };
  114. ByteString m_source_root;
  115. bool m_is_debuggee_dead { false };
  116. HashMap<FlatPtr, BreakPoint> m_breakpoints;
  117. HashMap<FlatPtr, WatchPoint> m_watchpoints;
  118. // Maps from library name to LoadedLibrary object
  119. HashMap<ByteString, NonnullOwnPtr<LoadedLibrary>> m_loaded_libraries;
  120. Function<void(float)> m_on_initialization_progress;
  121. };
  122. template<typename Callback>
  123. void DebugSession::run(DesiredInitialDebugeeState initial_debugee_state, Callback callback)
  124. {
  125. enum class State {
  126. FirstIteration,
  127. FreeRun,
  128. Syscall,
  129. ConsecutiveBreakpoint,
  130. SingleStep,
  131. };
  132. State state { State::FirstIteration };
  133. auto do_continue_and_wait = [&]() {
  134. int wstatus = continue_debuggee_and_wait((state == State::Syscall) ? ContinueType::Syscall : ContinueType::FreeRun);
  135. // FIXME: This check actually only checks whether the debuggee
  136. // stopped because it hit a breakpoint/syscall/is in single stepping mode or not
  137. if (WSTOPSIG(wstatus) != SIGTRAP && WSTOPSIG(wstatus) != SIGSTOP) {
  138. callback(DebugBreakReason::Exited, Optional<PtraceRegisters>());
  139. m_is_debuggee_dead = true;
  140. return true;
  141. }
  142. return false;
  143. };
  144. for (;;) {
  145. if ((state == State::FirstIteration && initial_debugee_state == DesiredInitialDebugeeState::Running) || state == State::FreeRun || state == State::Syscall) {
  146. if (do_continue_and_wait())
  147. break;
  148. }
  149. if (state == State::FirstIteration)
  150. state = State::FreeRun;
  151. auto regs = get_registers();
  152. #if ARCH(X86_64)
  153. FlatPtr current_instruction = regs.rip;
  154. #elif ARCH(AARCH64)
  155. FlatPtr current_instruction;
  156. TODO_AARCH64();
  157. #elif ARCH(RISCV64)
  158. FlatPtr current_instruction;
  159. TODO_RISCV64();
  160. #else
  161. # error Unknown architecture
  162. #endif
  163. auto debug_status = peek_debug(DEBUG_STATUS_REGISTER);
  164. if (debug_status.has_value() && (debug_status.value() & 0b1111) > 0) {
  165. // Tripped a watchpoint
  166. auto watchpoint_index = debug_status.value() & 0b1111;
  167. Optional<WatchPoint> watchpoint {};
  168. for (auto wp : m_watchpoints) {
  169. if ((watchpoint_index & (1 << wp.value.debug_register_index)) == 0)
  170. continue;
  171. watchpoint = wp.value;
  172. break;
  173. }
  174. if (watchpoint.has_value()) {
  175. auto required_ebp = watchpoint.value().ebp;
  176. auto found_ebp = false;
  177. #if ARCH(X86_64)
  178. FlatPtr current_ebp = regs.rbp;
  179. #elif ARCH(AARCH64)
  180. FlatPtr current_ebp;
  181. TODO_AARCH64();
  182. #elif ARCH(RISCV64)
  183. FlatPtr current_ebp;
  184. TODO_RISCV64();
  185. #else
  186. # error Unknown architecture
  187. #endif
  188. do {
  189. if (current_ebp == required_ebp) {
  190. found_ebp = true;
  191. break;
  192. }
  193. auto return_address = peek(current_ebp + sizeof(FlatPtr));
  194. auto next_ebp = peek(current_ebp);
  195. VERIFY(return_address.has_value());
  196. VERIFY(next_ebp.has_value());
  197. current_instruction = return_address.value();
  198. current_ebp = next_ebp.value();
  199. } while (current_ebp && current_instruction);
  200. if (!found_ebp) {
  201. dbgln("Removing watchpoint at {:p} because it went out of scope!", watchpoint.value().address);
  202. remove_watchpoint(watchpoint.value().address);
  203. continue;
  204. }
  205. }
  206. }
  207. Optional<BreakPoint> current_breakpoint;
  208. if (state == State::FreeRun || state == State::Syscall) {
  209. current_breakpoint = m_breakpoints.get(current_instruction - 1);
  210. if (current_breakpoint.has_value())
  211. state = State::FreeRun;
  212. } else {
  213. current_breakpoint = m_breakpoints.get(current_instruction);
  214. }
  215. if (current_breakpoint.has_value()) {
  216. // We want to make the breakpoint transparent to the user of the debugger.
  217. // To achieve this, we perform two rollbacks:
  218. // 1. Set regs.eip to point at the actual address of the instruction we broke on.
  219. // regs.eip currently points to one byte after the address of the original instruction,
  220. // because the cpu has just executed the INT3 we patched into the instruction.
  221. // 2. We restore the original first byte of the instruction,
  222. // because it was patched with INT3.
  223. auto breakpoint_addr = bit_cast<FlatPtr>(current_breakpoint.value().address);
  224. #if ARCH(X86_64)
  225. regs.rip = breakpoint_addr;
  226. #elif ARCH(AARCH64)
  227. (void)breakpoint_addr;
  228. TODO_AARCH64();
  229. #elif ARCH(RISCV64)
  230. (void)breakpoint_addr;
  231. TODO_RISCV64();
  232. #else
  233. # error Unknown architecture
  234. #endif
  235. set_registers(regs);
  236. disable_breakpoint(current_breakpoint.value().address);
  237. }
  238. DebugBreakReason reason = (state == State::Syscall && !current_breakpoint.has_value()) ? DebugBreakReason::Syscall : DebugBreakReason::Breakpoint;
  239. DebugDecision decision = callback(reason, regs);
  240. if (reason == DebugBreakReason::Syscall) {
  241. // skip the exit from the syscall
  242. if (do_continue_and_wait())
  243. break;
  244. }
  245. if (decision == DebugDecision::Continue) {
  246. state = State::FreeRun;
  247. } else if (decision == DebugDecision::ContinueBreakAtSyscall) {
  248. state = State::Syscall;
  249. }
  250. bool did_single_step = false;
  251. // Re-enable the breakpoint if it wasn't removed by the user
  252. if (current_breakpoint.has_value()) {
  253. auto current_breakpoint_address = bit_cast<FlatPtr>(current_breakpoint.value().address);
  254. if (m_breakpoints.contains(current_breakpoint_address)) {
  255. // The current breakpoint was removed to make it transparent to the user.
  256. // We now want to re-enable it - the code execution flow could hit it again.
  257. // To re-enable the breakpoint, we first perform a single step and execute the
  258. // instruction of the breakpoint, and then redo the INT3 patch in its first byte.
  259. // If the user manually inserted a breakpoint at the current instruction,
  260. // we need to disable that breakpoint because we want to singlestep over that
  261. // instruction (we re-enable it again later anyways).
  262. if (m_breakpoints.contains(current_breakpoint_address) && m_breakpoints.get(current_breakpoint_address).value().state == BreakPointState::Enabled) {
  263. disable_breakpoint(current_breakpoint.value().address);
  264. }
  265. auto stopped_address = single_step();
  266. enable_breakpoint(current_breakpoint.value().address);
  267. did_single_step = true;
  268. // If there is another breakpoint after the current one,
  269. // Then we are already on it (because of single_step)
  270. auto breakpoint_at_next_instruction = m_breakpoints.get(stopped_address);
  271. if (breakpoint_at_next_instruction.has_value()
  272. && breakpoint_at_next_instruction.value().state == BreakPointState::Enabled) {
  273. state = State::ConsecutiveBreakpoint;
  274. }
  275. }
  276. }
  277. if (decision == DebugDecision::SingleStep) {
  278. state = State::SingleStep;
  279. }
  280. if (decision == DebugDecision::Detach) {
  281. detach();
  282. break;
  283. }
  284. if (decision == DebugDecision::Kill) {
  285. kill(m_debuggee_pid, SIGTERM);
  286. break;
  287. }
  288. if (state == State::SingleStep && !did_single_step) {
  289. single_step();
  290. }
  291. }
  292. }
  293. }