www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - ptrace (process trace system call) on Linux from D

reply "Matej Nanut" <matejnanut gmail.com> writes:
Hello everyone,

I would like to know how to call ptrace (the system call) from D.

I don't know what to import or link.  If my understanding is 
correct, I need to create a .di file of some sort with stuff 
declared in it.  How would I do this?

Thanks, Matej
Apr 25 2012
next sibling parent reply mta`chrono <chrono mta-international.net> writes:
Am 25.04.2012 18:36, schrieb Matej Nanut:
 Hello everyone,
 
 I would like to know how to call ptrace (the system call) from D.
 
 I don't know what to import or link.  If my understanding is correct, I
 need to create a .di file of some sort with stuff declared in it.  How
 would I do this?
 
 Thanks, Matej

Hello Matej, I guess you're asking for http://linux.die.net/man/2/ptrace. normally it's somewhere deep in druntime but I couldn't find it. Maybe someone is able to add it for you. But neverthenless, you can just put some declaration in your D file and call it. ---- import core.stdc.stdio; import core.sys.posix.sys.types; enum __ptrace_request { PTRACE_TRACEME = 0, PTRACE_PEEKTEXT = 1, PTRACE_PEEKDATA = 2, PTRACE_PEEKUSER = 3, PTRACE_POKETEXT = 4, PTRACE_POKEDATA = 5, PTRACE_POKEUSER = 6, PTRACE_CONT = 7, PTRACE_KILL = 8, PTRACE_SINGLESTEP = 9, PTRACE_GETREGS = 12, PTRACE_SETREGS = 13, PTRACE_GETFPREGS = 14, PTRACE_SETFPREGS = 15, PTRACE_ATTACH = 16, PTRACE_DETACH = 17, PTRACE_GETFPXREGS = 18, PTRACE_SETFPXREGS = 19, PTRACE_SYSCALL = 24, PTRACE_SETOPTIONS = 0x4200, PTRACE_GETEVENTMSG = 0x4201, PTRACE_GETSIGINFO = 0x4202, PTRACE_SETSIGINFO = 0x4203 } extern(C) long ptrace(__ptrace_request request, pid_t pid, void *addr, void *data); void main() { // just call ptrace like you would do in C } ----
Apr 25 2012
next sibling parent Artur Skawina <art.08.09 gmail.com> writes:
On 05/07/12 12:45, Stanislav Blinov wrote:
 On Friday, 4 May 2012 at 14:47:05 UTC, Matej Nanut wrote:
 (1) I've managed this by putting the extern ptrace declaration in a seperate
file and call it via filename.ptrace in my program.

You can achieve the same without additional files: // This struct acts as a namespace to hide C declarations, // just like separate module struct PtraceApi { static: extern(C) long ptrace(__ptrace_request request, pid_t pid, void *addr, void *data); } long ptrace(__ptrace_request request, pid_t pid, void *addr, void *data) { auto result = PtraceApi.ptrace(request, pid, addr, data); // Check result and errno for errors... }

struct method names are mangled, including static and extern(C) ones. (they have to be, or you'd get collisions; a way to turn it off for cases like this one would be useful, yes.) artur
May 07 2012
prev sibling parent reply mta`chrono <chrono mta-international.net> writes:
 (2) Is it more D-ish to use something like "enum PTRequest { traceMe =
 0, ... }" instead of the fully capitalised originals?  It doesn't seem
 to affect the working of things.

Yes, that's more D-ish. In new D code I prefer the camelcased ones, but there are cases where you'd like to use the original ones. it's up to! ;-)
 (3) wait() is declared as returning a pid_t in the manpage, and is
 declared as such in core.sys.posix.sys.wait.  In std.c.process however,
 it returns an int.  I can't even find a process.h in my Linux install. 
 What am I supposed to use?  I know it essentially doesn't matter, as
 pid_t is aliased as int.
 Are there D alternatives to wait() and fork() that I could use with
 ptrace() instead of the C posix system functions?
 
 (4) Some things are declared only in core.*, not in std.*.  Will they be
 added at some point or is this how it's supposed to be?

I thing core.* (druntime) is the right place for _all_ bindings to libc. But yeha, there are still some relicts in std.c.* of the good old days. What do you meant by "D alternatives to wait() and fork() that could be used with ptrace()". Maybe I don't understand your intention.
May 07 2012
parent mta`chrono <chrono mta-international.net> writes:
Am 08.05.2012 18:12, schrieb Matej Nanut:
 On Monday, 7 May 2012 at 22:56:07 UTC, mta`chrono wrote:
 What do you meant by "D alternatives to wait() and fork() that could be
 used with ptrace()". Maybe I don't understand your intention.

Nevermind with that; I've been confused since there are exec*() functions in std.process, but no wait() and fork(). I think there's a new std.process in the works that has more D-ish ways to do these. And thanks for the core.* VS std.c.* clarification. I didn't even think of using core.* all the way for libc bindings.

But consider that fork() is a very specific UNIX syscall. There is nothing similar like that on Windows. That's maybe why they didn't wrap it in Phobos. Maybe the same applies to wait() that seems to rely on the UNIX signal stuff. But there should be some kind of derivate on windows, too. But neverthenless you are free to use every C-Funktion. You just need some kind of definition to tell dmd to create the right symbols. If the definition is already present in druntime, it's fine - just use it! otherwise you have to define it yourself.
 
 If struct method names are mangled, does that mean that that way of
 doing it doesn't work? I'll try it anyway, to try and get rid of a few
 extra files.

It shouldn't work. But you can add another custom ptrace method (_NOT_ extern(C)) with different operators. If you can give more information of your superior intention (what are you going to create?) then I'll might provide a better assistance!
May 08 2012
prev sibling next sibling parent "Matej Nanut" <matejnanut gmail.com> writes:
Thank you for the reply, your recommendation works.

I could however not find ptrace anywhere in druntime.  There is 
only one mention of it in std.process, in a comment.

But I do have some other questions:

(1) Can I declare a ptrace function which calls the original 
ptrace?  (I would like to check the return value and errno for 
exception throwing and such).  I essentially want to shadow the 
original.

(2) Is it more D-ish to use something like "enum PTRequest { 
traceMe = 0, ... }" instead of the fully capitalised originals?  
It doesn't seem to affect the working of things.

(3) wait() is declared as returning a pid_t in the manpage, and 
is declared as such in core.sys.posix.sys.wait.  In std.c.process 
however, it returns an int.  I can't even find a process.h in my 
Linux install.  What am I supposed to use?  I know it essentially 
doesn't matter, as pid_t is aliased as int.

Are there D alternatives to wait() and fork() that I could use 
with ptrace() instead of the C posix system functions?

(4) Some things are declared only in core.*, not in std.*.  Will 
they be added at some point or is this how it's supposed to be?
May 03 2012
prev sibling next sibling parent "Matej Nanut" <matejnanut gmail.com> writes:
(1) I've managed this by putting the extern ptrace declaration in 
a seperate file and call it via filename.ptrace in my program.

Apparently a new std.process is in the works that does supply a 
sort of fork().  I'm sorry for not looking through things 
properly before.
May 04 2012
prev sibling next sibling parent "Stanislav Blinov" <stanislav.blinov gmail.com> writes:
On Friday, 4 May 2012 at 14:47:05 UTC, Matej Nanut wrote:
 (1) I've managed this by putting the extern ptrace declaration 
 in a seperate file and call it via filename.ptrace in my 
 program.

You can achieve the same without additional files: // This struct acts as a namespace to hide C declarations, // just like separate module struct PtraceApi { static: extern(C) long ptrace(__ptrace_request request, pid_t pid, void *addr, void *data); } long ptrace(__ptrace_request request, pid_t pid, void *addr, void *data) { auto result = PtraceApi.ptrace(request, pid, addr, data); // Check result and errno for errors... }
May 07 2012
prev sibling next sibling parent "Stanislav Blinov" <stanislav.blinov gmail.com> writes:
On Monday, 7 May 2012 at 11:30:33 UTC, Artur Skawina wrote:
 struct method names are mangled, including static and extern(C) 
 ones.
 (they have to be, or you'd get collisions; a way to turn it off 
 for
 cases like this one would be useful, yes.)

Hmm, that's right. Silly me. Sorry for the confusion.
May 07 2012
prev sibling next sibling parent "Matej Nanut" <matejnanut gmail.com> writes:
On Monday, 7 May 2012 at 22:56:07 UTC, mta`chrono wrote:
 What do you meant by "D alternatives to wait() and fork() that 
 could be
 used with ptrace()". Maybe I don't understand your intention.

Nevermind with that; I've been confused since there are exec*() functions in std.process, but no wait() and fork(). I think there's a new std.process in the works that has more D-ish ways to do these. And thanks for the core.* VS std.c.* clarification. I didn't even think of using core.* all the way for libc bindings. If struct method names are mangled, does that mean that that way of doing it doesn't work? I'll try it anyway, to try and get rid of a few extra files.
May 08 2012
prev sibling parent "Matej Nanut" <matejnanut gmail.com> writes:
On Tuesday, 8 May 2012 at 16:41:55 UTC, mta`chrono wrote:
 But consider that fork() is a very specific UNIX syscall. There 
 is
 nothing similar like that on Windows. That's maybe why they 
 didn't wrap
 it in Phobos.

Ah yes, very true. I didn't think of that.
 Maybe the same applies to wait() that seems to rely on the UNIX 
 signal
 stuff. But there should be some kind of derivate on windows, 
 too.

I think there must be something similiar, but I assume the usages are slightly different and as such wrapping these things into a common API might hinder performance. Also, since I need these for use with ptrace, the program will only run on Linux (maybe POSIX?) systems anyway (I don't think Windows has ptrace?).
 If struct method names are mangled, does that mean that that 
 way of
 doing it doesn't work? I'll try it anyway, to try and get rid 
 of a few
 extra files.

It shouldn't work. But you can add another custom ptrace method (_NOT_ extern(C)) with different operators.

I do kinda want the same operators though.
 If you can give more information of your superior intention 
 (what are
 you going to create?) then I'll might provide a better 
 assistance!

I basically want to track system calls and mess with the program issuing them. (As per ptrace(PTRACE_SYSCALL, ...).) The common pattern of doing something like this is: --- void main(string[] args) { pid_t childPid; switch (childPid = fork()) { case -1: /* error stuff */ break; case 0: ptrace(PTRACE_TRACEME, 0, null, null); execvp(args[1], args[1 .. $]); break; default: /* do ptrace magic in parent */ break; } } --- And for this I would like the most D-ish way of importing/including/linking wait(), fork() and ptrace(). :-) Thanks, Matej
May 08 2012