J'écris un outil qui appelle à DTrace pour suivre le programme que l'utilisateur spécifie. P>
Si mon outil utilise DTrace -C pour exécuter le programme en tant que sous-processus de dtrace, non seulement je ne peux pas transmettre aucun argument au programme, mais le programme fonctionne avec tous les privilèges de dtrace - c'est-à-dire comme la racine (i 'M sur Mac OS X). Cela rend certaines choses qui devraient faire une pause et font évidemment beaucoup de choses qui ne devraient pas travailler possible. P>
L'autre solution que je connaisse est de démarrer le programme moi-même, en la pause en l'envoyant Y a-t-il une manière que je puisse exécuter le programme sous le compte de l'utilisateur, pas en tant que root, mais que DTrace a toujours capable de le retrouver depuis le début? P> SIGSTOP code>, passez son PID à
dTrace -p code>, puis continuez-le en envoyant Il
sigcont code>. Le problème est que soit le programme fonctionne pendant quelques secondes sans être tracé alors que DTrace recueille les informations de symbole ou, si je dors pendant quelques secondes avant de poursuivre le processus, Dtrace se plaint que
objc
7 Réponses :
Créer un programme de lanceur qui attendra un signal de quelque sorte (pas nécessairement un signal littéral, juste une indication que c'est prêt), puis exécutée () votre cible. Maintenant, DTrace -P Le programme de lanceur et une fois que Dtrace est en hausse, laissez le lanceur aller. P>
Encore mieux: rouler tout en un. Créez un tuyau, une fourchette, avez-vous l'enfant d'attendre le tuyau, dttrace -p enfant_pid, écrivez au tuyau, l'enfant se réveille et appelle EXEC.
Semble prometteur. Je ne sais pas que cela fonctionnera, cependant: mon outil est écrit en python et il est conçu pour tracer des programmes de cacao. Sans aucun cacao dans mon outil, je pense que je vais toujours obtenir l'erreur que le fournisseur Objc n'atteignait aucune sondes. Mais je vais l'essayer demain.
Si l'autre réponse ne fonctionne pas pour vous, pouvez-vous exécuter le programme dans GDB, enfreindre la main (ou même plus tôt), obtenir le PID et commencer le script? J'ai essayé cela dans le passé et cela semblait travailler. P>
Quelque chose comme J'ai déposé un bug radar à ce sujet et l'avais fermé comme un duplicata de # 5108629. P> sudo dtruss -f sudo -u
Eh bien, c'est un peu vieux, mais pourquoi pas: -) .. p> Je ne pense pas qu'il existe un moyen de le faire simplement de la ligne de commande, mais comme suggéré, une application de lancement simple, telle que Ce qui suit, le ferait. La fixation manuelle pourrait bien sûr également être remplacée par quelques appels à libdtrace. P>
Ce script prend le nom de l'exécutable (pour une application Ceci est l'info.plist's CFBundleExecutable) que vous souhaitez surveiller sur DTrace en tant que paramètre (vous pouvez ensuite lancer l'application cible après l'exécution de ce script):
string gTarget; /* the name of the target executable */ dtrace:::BEGIN { gTarget = $$1; /* get the target execname from 1st DTrace parameter */ /* * Note: DTrace's execname is limited to 15 characters so if $$1 has more * than 15 characters the simple string comparison "($$1 == execname)" * will fail. We work around this by copying the parameter passed in $$1 * to gTarget and truncating that to 15 characters. */ gTarget[15] = 0; /* truncate to 15 bytes */ gTargetPID = -1; /* invalidate target pid */ } /* * capture target launch (success) */ proc:::exec-success / gTarget == execname / { gTargetPID = pid; } /* * detect when our target exits */ syscall::*exit:entry / pid == gTargetPID / { gTargetPID = -1; /* invalidate target pid */ } /* * capture open arguments */ syscall::open*:entry / ((pid == gTargetPID) || progenyof(gTargetPID)) / { self->arg0 = arg0; self->arg1 = arg1; } /* * track opens */ syscall::open*:return / ((pid == gTargetPID) || progenyof(gTargetPID)) / { this->op_kind = ((self->arg1 & O_ACCMODE) == O_RDONLY) ? "READ" : "WRITE"; this->path0 = self->arg0 ? copyinstr(self->arg0) : "<nil>"; printf("open for %s: <%s> #%d", this->op_kind, this->path0, arg0); }
C'est génial, sauf que lorsque cela fait ce dtrace ne trouve aucun des points de trace du fournisseur PID. Par exemple, je reçois une erreur: "Description de la sonde PID * :: Confstr: retour ne correspond à aucune sondes"
DTRUSS possède l'option -n code> où vous pouvez spécifier le nom du processus que vous souhaitez tracer, sans le démarrer (crédit à la dernière partie de la réponse de @ Kenorb à Https://stackoverflow.com/a/11706251/970301 ). Donc, quelque chose comme ce qui suit devrait le faire:
sudo dtruss -n "$program"
$program
voir Ma réponse sur associé Question " Comment obtenir DTrace d'exécuter la commande traçée avec des privilèges non root ? " [SIC].
Essentiellement, vous pouvez démarrer un processus d'arrière-plan (non root) qui attend 1Sec pour DTRACe pour démarrer (désolé pour la condition de course) et snoops le PID de ce processus. P>
sudo true && \ (sleep 1; cat /etc/hosts) &; \ sudo dtrace -n 'syscall:::entry /pid == $1/ {@[probefunc] = count();}' $! \ && kill $!