blob: d38157d57ddbd2d25a6896f4102a8e50058bc30b [file] [log] [blame]
Juan Cespedes1c2be911997-06-09 01:12:01 +02001#include <stdio.h>
2#include <errno.h>
3#include <unistd.h>
Juan Cespedes1c2be911997-06-09 01:12:01 +02004#include <sys/ptrace.h>
Juan Cespedes1c2be911997-06-09 01:12:01 +02005#include <sys/wait.h>
Juan Cespedes155a4081997-06-11 01:19:35 +02006#include <signal.h>
Juan Cespedes1c2be911997-06-09 01:12:01 +02007
Juan Cespedes96935a91997-08-09 23:45:39 +02008#include "elf.h"
9#include "trace.h"
10
Juan Cespedes5b2f9811997-07-17 00:05:10 +020011extern void print_function(const char *, int);
Juan Cespedes96935a91997-08-09 23:45:39 +020012extern void read_config_file(const char *);
Juan Cespedes24c82531997-06-25 00:02:58 +020013
Juan Cespedesd3ac65f1997-06-16 00:20:35 +020014int pid;
15
Juan Cespedes96935a91997-08-09 23:45:39 +020016int debug = 0;
Juan Cespedes5b2f9811997-07-17 00:05:10 +020017FILE * output = stderr;
18
19unsigned long return_addr;
20unsigned char return_value;
21struct library_symbol * current_symbol;
22
Juan Cespedes5b2f9811997-07-17 00:05:10 +020023static void usage(void)
24{
25 fprintf(stderr," Usage: ltrace [-d][-o output] <program> [<arguments>...]\n");
26}
27
Juan Cespedes1c2be911997-06-09 01:12:01 +020028int main(int argc, char **argv)
29{
Juan Cespedes1c2be911997-06-09 01:12:01 +020030 int status;
Juan Cespedesad783621997-06-10 17:11:33 +020031 struct library_symbol * tmp = NULL;
32
Juan Cespedes5b2f9811997-07-17 00:05:10 +020033 while ((argc>2) && (argv[1][0] == '-') && (argv[1][2] == '\0')) {
Juan Cespedesad783621997-06-10 17:11:33 +020034 switch(argv[1][1]) {
35 case 'd': debug++;
36 break;
Juan Cespedes5b2f9811997-07-17 00:05:10 +020037 case 'o': output = fopen(argv[2], "w");
38 if (!output) {
39 fprintf(stderr, "Can't open %s for output: %s\n", argv[2], sys_errlist[errno]);
40 exit(1);
41 }
42 argc--; argv++;
43 break;
Juan Cespedesad783621997-06-10 17:11:33 +020044 default: fprintf(stderr, "Unknown option '%c'\n", argv[1][1]);
Juan Cespedes5b2f9811997-07-17 00:05:10 +020045 usage();
Juan Cespedesad783621997-06-10 17:11:33 +020046 exit(1);
47 }
48 argc--; argv++;
49 }
Juan Cespedes1c2be911997-06-09 01:12:01 +020050
51 if (argc<2) {
Juan Cespedes5b2f9811997-07-17 00:05:10 +020052 usage();
Juan Cespedes1c2be911997-06-09 01:12:01 +020053 exit(1);
54 }
Juan Cespedesad783621997-06-10 17:11:33 +020055 if (!read_elf(argv[1])) {
Juan Cespedes5b2f9811997-07-17 00:05:10 +020056 fprintf(stderr, "%s: Not dynamically linked\n", argv[1]);
Juan Cespedes1c2be911997-06-09 01:12:01 +020057 exit(1);
58 }
Juan Cespedes96935a91997-08-09 23:45:39 +020059 pid = attach_process(argv[1], argv+1);
Juan Cespedes5b2f9811997-07-17 00:05:10 +020060 fprintf(output, "pid %u attached\n", pid);
Juan Cespedesad783621997-06-10 17:11:33 +020061
Juan Cespedes6ddb1da1997-08-11 22:32:14 +020062#if 0
Juan Cespedesad783621997-06-10 17:11:33 +020063 /* Enable breakpoints: */
Juan Cespedes5b2f9811997-07-17 00:05:10 +020064 fprintf(output, "Enabling breakpoints...\n");
Juan Cespedes96935a91997-08-09 23:45:39 +020065 enable_all_breakpoints();
Juan Cespedes6ddb1da1997-08-11 22:32:14 +020066#endif
Juan Cespedes96935a91997-08-09 23:45:39 +020067 fprintf(output, "Reading config file(s)...\n");
68 read_config_file("/etc/ltrace.cfg");
69 read_config_file(".ltracerc");
Juan Cespedesad783621997-06-10 17:11:33 +020070 ptrace(PTRACE_CONT, pid, 1, 0);
71
Juan Cespedes1c2be911997-06-09 01:12:01 +020072 while(1) {
Juan Cespedesad783621997-06-10 17:11:33 +020073 int eip;
Juan Cespedesd3ac65f1997-06-16 00:20:35 +020074 int esp;
Juan Cespedesad783621997-06-10 17:11:33 +020075 int function_seen;
76
Juan Cespedes155a4081997-06-11 01:19:35 +020077 pid = wait4(-1, &status, 0, NULL);
Juan Cespedes1c2be911997-06-09 01:12:01 +020078 if (pid==-1) {
79 if (errno == ECHILD) {
Juan Cespedes5b2f9811997-07-17 00:05:10 +020080 fprintf(output, "No more children\n");
Juan Cespedes1c2be911997-06-09 01:12:01 +020081 exit(0);
82 }
83 perror("wait4");
84 exit(1);
85 }
86 if (WIFEXITED(status)) {
Juan Cespedes5b2f9811997-07-17 00:05:10 +020087 fprintf(output, "pid %u exited\n", pid);
Juan Cespedes1c2be911997-06-09 01:12:01 +020088 continue;
89 }
Juan Cespedes155a4081997-06-11 01:19:35 +020090 if (WIFSIGNALED(status)) {
Juan Cespedes5b2f9811997-07-17 00:05:10 +020091 fprintf(output, "pid %u exited on signal %u\n", pid, WTERMSIG(status));
Juan Cespedes155a4081997-06-11 01:19:35 +020092 continue;
93 }
Juan Cespedesad783621997-06-10 17:11:33 +020094 if (!WIFSTOPPED(status)) {
Juan Cespedes5b2f9811997-07-17 00:05:10 +020095 fprintf(output, "pid %u ???\n", pid);
Juan Cespedesad783621997-06-10 17:11:33 +020096 continue;
97 }
Juan Cespedes155a4081997-06-11 01:19:35 +020098 if (WSTOPSIG(status) != SIGTRAP) {
Juan Cespedes5b2f9811997-07-17 00:05:10 +020099 fprintf(output, "Signal: %u\n", WSTOPSIG(status));
Juan Cespedes155a4081997-06-11 01:19:35 +0200100 ptrace(PTRACE_CONT, pid, 1, WSTOPSIG(status));
101 continue;
102 }
Juan Cespedesad783621997-06-10 17:11:33 +0200103 /* pid is stopped... */
Juan Cespedes96935a91997-08-09 23:45:39 +0200104 eip = ptrace(PTRACE_PEEKUSER, pid, 4*EIP, 0);
105 esp = ptrace(PTRACE_PEEKUSER, pid, 4*UESP, 0);
Juan Cespedesd3ac65f1997-06-16 00:20:35 +0200106#if 0
Juan Cespedes5b2f9811997-07-17 00:05:10 +0200107 fprintf(output,"EIP = 0x%08x\n", eip);
108 fprintf(output,"ESP = 0x%08x\n", esp);
Juan Cespedesd3ac65f1997-06-16 00:20:35 +0200109#endif
Juan Cespedes5b2f9811997-07-17 00:05:10 +0200110 fprintf(output,"[0x%08x] ", ptrace(PTRACE_PEEKTEXT, pid, esp, 0));
Juan Cespedesad783621997-06-10 17:11:33 +0200111 tmp = library_symbols;
112 function_seen = 0;
113 while(tmp) {
114 if (eip == tmp->addr+1) {
Juan Cespedesad783621997-06-10 17:11:33 +0200115 function_seen = 1;
Juan Cespedesd3ac65f1997-06-16 00:20:35 +0200116 print_function(tmp->name, esp);
Juan Cespedes96935a91997-08-09 23:45:39 +0200117 delete_breakpoint(pid, tmp->addr, tmp->old_value);
118 ptrace(PTRACE_POKEUSER, pid, 4*EIP, eip-1);
Juan Cespedesad783621997-06-10 17:11:33 +0200119 ptrace(PTRACE_SINGLESTEP, pid, 0, 0);
Juan Cespedes155a4081997-06-11 01:19:35 +0200120 pid = wait4(-1, &status, 0, NULL);
Juan Cespedesad783621997-06-10 17:11:33 +0200121 if (pid==-1) {
122 if (errno == ECHILD) {
Juan Cespedes5b2f9811997-07-17 00:05:10 +0200123 fprintf(output, "No more children\n");
Juan Cespedesad783621997-06-10 17:11:33 +0200124 exit(0);
125 }
126 perror("wait4");
127 exit(1);
128 }
Juan Cespedes96935a91997-08-09 23:45:39 +0200129 insert_breakpoint(pid, tmp->addr, tmp->old_value);
Juan Cespedesad783621997-06-10 17:11:33 +0200130 ptrace(PTRACE_CONT, pid, 1, 0);
131 break;
132 }
133 tmp = tmp->next;
134 }
135 if (!function_seen) {
Juan Cespedes5b2f9811997-07-17 00:05:10 +0200136 fprintf(output, "pid %u stopped; continuing it...\n", pid);
Juan Cespedes1c2be911997-06-09 01:12:01 +0200137 ptrace(PTRACE_CONT, pid, 1, 0);
Juan Cespedes1c2be911997-06-09 01:12:01 +0200138 }
139 }
140 exit(0);
141}