Reputation: 414
I am trying to do some very basic stuff using ptrace but I am a getting a really odd behavior.
unsigned long start=strtoul(start_text,NULL,16);
long start_data;
if ((start_data = ptrace(PTRACE_PEEKTEXT,child_pid,(void*)start,NULL))<0){
free_memory(vars,registers,size);
exit(1);
}
start_text
is a string to a valid place in another program, the value of start
is correct, the value of child_pid
is also correct.
For some reason, for some values of start
the call works properly, but for some it fails.
I tried to understand what causes this so I wrote this:
ptrace(PTRACE_PEEKTEXT,child_pid,(void*)start,NULL);
printf("%d",errno);
but errno
is 0 every time.
Can anyone please explain what causes the problem?
Upvotes: 1
Views: 636
Reputation: 57912
From Linux's ptrace
man page:
Since the value returned by a successful PTRACE_PEEK* request may be -1, the caller must clear errno before the call, and then check it afterward to determine whether or not an error occurred.
That is, it could be that the value you're reading just happens to be -1
, or in your case, some other negative number (i.e. a 64-bit value with the high bit set).
So unlike most other system call functions, you can't check for success by testing whether the returned value is negative. You should instead do
errno = 0;
start_data = ptrace(PTRACE_PEEKTEXT,child_pid,(void*)start,NULL));
if (errno != 0) {
// handle error
}
Note the importance of setting errno = 0
first. As with other system calls, if ptrace
succeeds it may leave the value of errno
unchanged. So unless you clear errno
first, you won't be able to tell whether a nonzero value afterward indicates that ptrace
failed, or whether ptrace
succeeded and the value was left over from some previous call that failed.
(My version of man page suggests that the ptrace
library wrapper may actually set errno
to zero upon success, but doesn't make it clear exactly when, so it is best not to rely on this behavior.)
Upvotes: 1