3 #include <sys/ptrace.h>
14 #include "ExitObserver.h"
15 #include "TrapObserver.h"
23 Portal::Portal(Misc::SmartPointer
<Platform::ArgumentList
> argument_list
) : pid(0) {
27 throw PTraceException(Misc::StreamAsString() << "Forking to create child process failed: " << strerror(errno
));
29 ptrace(PTRACE_TRACEME
, 0, NULL
, NULL
);
30 if(execv(argument_list
->get_argument(0).c_str(), argument_list
->get_as_argv()) == -1) {
31 throw PTraceException(Misc::StreamAsString() << "Failed to execute process: " << strerror(errno
));
35 /*ptrace(PTRACE_SETOPTIONS, pid, 0, PTRACE_O_TRACESYSGOOD);*/
37 add_signal_observer(new ExitObserver());
38 add_signal_observer(new TrapObserver());
41 Platform::MemoryAddress
Portal::get_register(register_e which
) const {
42 struct user_regs_struct registers
;
43 if(ptrace(PTRACE_GETREGS
, pid
, NULL
, ®isters
) == -1)
44 throw PTraceException(Misc::StreamAsString() << "Couldn't get register values: " << strerror(errno
));
47 #if AESALON_PLATFORM == AESALON_PLATFORM_x86_64
49 std::cout
<< "Value of RAX requested; RAX is " << registers
.rax
<< ", ORIG_RAX is " << registers
.orig_rax
<< std::endl
;
50 return registers
.orig_rax
;
57 throw PTraceException("Value of invalid register requested");
61 Word
Portal::read_memory(Platform::MemoryAddress address
) const {
62 SWord return_value
= ptrace(PTRACE_PEEKDATA
, pid
, address
, NULL
);
63 if(return_value
== -1 && errno
!= 0)
64 throw PTraceException(Misc::StreamAsString() << "Couldn't read memory: " << strerror(errno
));
65 /* NOTE: what happens if return_value is < 0? . .. */
69 void Portal::write_memory(Platform::MemoryAddress address
, Word value
) {
70 if(ptrace(PTRACE_POKEDATA
, pid
, address
, value
) == -1)
71 throw PTraceException(Misc::StreamAsString() << "Couldn't write memory: " << strerror(errno
));
74 void Portal::write_memory(Platform::MemoryAddress address
, Byte value
) {
75 Word current_value
= read_memory(address
);
76 current_value
&= ~0xff;
77 write_memory(address
, current_value
| value
);
80 void Portal::attach() {
81 ptrace(PTRACE_ATTACH
, pid
, NULL
, NULL
);
84 void Portal::place_breakpoint(Platform::MemoryAddress address
) {
85 Byte original
= read_memory(address
) & 0xff;
86 add_breakpoint(new Breakpoint(address
, original
));
87 write_memory(address
, Byte(0xcc));
90 Misc::SmartPointer
<Breakpoint
> Portal::get_breakpoint_by_id(std::size_t which
) const {
91 for(breakpoint_list_t::const_iterator i
= breakpoint_list
.begin(); i
!= breakpoint_list
.end(); i
++) {
92 if((*i
)->get_id() == which
) return *i
;
97 Misc::SmartPointer
<Breakpoint
> Portal::get_breakpoint_by_address(Platform::MemoryAddress address
) const {
98 for(breakpoint_list_t::const_iterator i
= breakpoint_list
.begin(); i
!= breakpoint_list
.end(); i
++) {
99 if((*i
)->get_address() == address
) return *i
;
105 void Portal::handle_signal() {
107 int status
= wait_for_signal();
108 if(!WIFEXITED(status
) && WIFSTOPPED(status
)) {
109 siginfo_t signal_info
;
110 if(ptrace(PTRACE_GETSIGINFO
, pid
, NULL
, &signal_info
) == -1) {
111 throw PTraceException(Misc::StreamAsString() << "Failed to get signal information: " << strerror(errno
));
113 signal
= signal_info
.si_signo
;
117 std::cout
<< "Portal::handle_signal(): status: (" << status
<< "): ";
119 for(int mask
= 1 << 20; mask
> 0; mask
>>= 1) {
120 std::cout
<< ((status
& mask
)?"1":"0");
123 std::cout
<< ", signal: " << signal
<< std::endl
;
125 for(signal_observer_list_t::iterator i
= signal_observer_list
.begin(); i
!= signal_observer_list
.end(); i
++) {
126 if((*i
)->handle_signal(signal
, status
)) return;
130 void Portal::continue_execution(int signal
) {
131 if(ptrace(PTRACE_CONT
, pid
, NULL
, NULL
) == -1)
132 throw PTraceException(Misc::StreamAsString() << "Couldn't continue program execution: " << strerror(errno
));
135 void Portal::single_step() {
136 if(ptrace(PTRACE_SINGLESTEP
, pid
, NULL
, NULL
) == -1)
137 throw PTraceException(Misc::StreamAsString() << "Couldn't single-step program:" << strerror(errno
));
140 int Portal::wait_for_signal() {
142 if(waitpid(pid
, &status
, 0) == -1) throw PTraceException(Misc::StreamAsString() << "Couldn't waitpid() on child: " << strerror(errno
));
146 void Portal::handle_breakpoint() {
147 Misc::SmartPointer
<Breakpoint
> breakpoint
= get_breakpoint_by_address(get_register(RIP
));
148 if(!breakpoint
.is_valid()) {
149 Message(Message::DEBUG_MESSAGE
, "handle_breakpoint() called on non-breakpoint");
152 write_memory(breakpoint
->get_address(), breakpoint
->get_original());
154 write_memory(breakpoint
->get_address(), breakpoint
->get_breakpoint_character());
157 } // namespace PTrace
158 } // namespace Monitor
159 } // namespace Aesalon