blob: 4f2d08a6290eae5b60a84768ff652e831ab800a8 [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"
Juan Cespedesc9a48b91997-08-17 02:45:40 +020010#include "symbols.h"
Juan Cespedes96935a91997-08-09 23:45:39 +020011
Juan Cespedes5b2f9811997-07-17 00:05:10 +020012extern void print_function(const char *, int);
Juan Cespedes96935a91997-08-09 23:45:39 +020013extern void read_config_file(const char *);
Juan Cespedes24c82531997-06-25 00:02:58 +020014
Juan Cespedesd3ac65f1997-06-16 00:20:35 +020015int pid;
16
Juan Cespedes96935a91997-08-09 23:45:39 +020017int debug = 0;
Juan Cespedes5b2f9811997-07-17 00:05:10 +020018FILE * output = stderr;
19
20unsigned long return_addr;
21unsigned char return_value;
22struct library_symbol * current_symbol;
23
Juan Cespedes5b2f9811997-07-17 00:05:10 +020024static void usage(void)
25{
26 fprintf(stderr," Usage: ltrace [-d][-o output] <program> [<arguments>...]\n");
27}
28
Juan Cespedes1c2be911997-06-09 01:12:01 +020029int main(int argc, char **argv)
30{
Juan Cespedes1c2be911997-06-09 01:12:01 +020031 int status;
Juan Cespedesad783621997-06-10 17:11:33 +020032 struct library_symbol * tmp = NULL;
33
Juan Cespedes5b2f9811997-07-17 00:05:10 +020034 while ((argc>2) && (argv[1][0] == '-') && (argv[1][2] == '\0')) {
Juan Cespedesad783621997-06-10 17:11:33 +020035 switch(argv[1][1]) {
36 case 'd': debug++;
37 break;
Juan Cespedes5b2f9811997-07-17 00:05:10 +020038 case 'o': output = fopen(argv[2], "w");
39 if (!output) {
40 fprintf(stderr, "Can't open %s for output: %s\n", argv[2], sys_errlist[errno]);
41 exit(1);
42 }
43 argc--; argv++;
44 break;
Juan Cespedesad783621997-06-10 17:11:33 +020045 default: fprintf(stderr, "Unknown option '%c'\n", argv[1][1]);
Juan Cespedes5b2f9811997-07-17 00:05:10 +020046 usage();
Juan Cespedesad783621997-06-10 17:11:33 +020047 exit(1);
48 }
49 argc--; argv++;
50 }
Juan Cespedes1c2be911997-06-09 01:12:01 +020051
52 if (argc<2) {
Juan Cespedes5b2f9811997-07-17 00:05:10 +020053 usage();
Juan Cespedes1c2be911997-06-09 01:12:01 +020054 exit(1);
55 }
Juan Cespedesad783621997-06-10 17:11:33 +020056 if (!read_elf(argv[1])) {
Juan Cespedes5b2f9811997-07-17 00:05:10 +020057 fprintf(stderr, "%s: Not dynamically linked\n", argv[1]);
Juan Cespedes1c2be911997-06-09 01:12:01 +020058 exit(1);
59 }
Juan Cespedes96935a91997-08-09 23:45:39 +020060 pid = attach_process(argv[1], argv+1);
Juan Cespedes5b2f9811997-07-17 00:05:10 +020061 fprintf(output, "pid %u attached\n", pid);
Juan Cespedesad783621997-06-10 17:11:33 +020062
Juan Cespedesc9a48b91997-08-17 02:45:40 +020063#if 1
Juan Cespedesad783621997-06-10 17:11:33 +020064 /* Enable breakpoints: */
Juan Cespedes5b2f9811997-07-17 00:05:10 +020065 fprintf(output, "Enabling breakpoints...\n");
Juan Cespedesc9a48b91997-08-17 02:45:40 +020066 enable_all_breakpoints(pid);
Juan Cespedes6ddb1da1997-08-11 22:32:14 +020067#endif
Juan Cespedes96935a91997-08-09 23:45:39 +020068 fprintf(output, "Reading config file(s)...\n");
69 read_config_file("/etc/ltrace.cfg");
70 read_config_file(".ltracerc");
Juan Cespedesc9a48b91997-08-17 02:45:40 +020071 continue_process(pid, 0);
Juan Cespedesad783621997-06-10 17:11:33 +020072
Juan Cespedes1c2be911997-06-09 01:12:01 +020073 while(1) {
Juan Cespedesc9a48b91997-08-17 02:45:40 +020074 unsigned long eip;
Juan Cespedesd3ac65f1997-06-16 00:20:35 +020075 int esp;
Juan Cespedesad783621997-06-10 17:11:33 +020076 int function_seen;
77
Juan Cespedes155a4081997-06-11 01:19:35 +020078 pid = wait4(-1, &status, 0, NULL);
Juan Cespedes1c2be911997-06-09 01:12:01 +020079 if (pid==-1) {
80 if (errno == ECHILD) {
Juan Cespedes5b2f9811997-07-17 00:05:10 +020081 fprintf(output, "No more children\n");
Juan Cespedes1c2be911997-06-09 01:12:01 +020082 exit(0);
83 }
84 perror("wait4");
85 exit(1);
86 }
87 if (WIFEXITED(status)) {
Juan Cespedes5b2f9811997-07-17 00:05:10 +020088 fprintf(output, "pid %u exited\n", pid);
Juan Cespedes1c2be911997-06-09 01:12:01 +020089 continue;
90 }
Juan Cespedes155a4081997-06-11 01:19:35 +020091 if (WIFSIGNALED(status)) {
Juan Cespedes5b2f9811997-07-17 00:05:10 +020092 fprintf(output, "pid %u exited on signal %u\n", pid, WTERMSIG(status));
Juan Cespedes155a4081997-06-11 01:19:35 +020093 continue;
94 }
Juan Cespedesad783621997-06-10 17:11:33 +020095 if (!WIFSTOPPED(status)) {
Juan Cespedes5b2f9811997-07-17 00:05:10 +020096 fprintf(output, "pid %u ???\n", pid);
Juan Cespedesad783621997-06-10 17:11:33 +020097 continue;
98 }
Juan Cespedes155a4081997-06-11 01:19:35 +020099 if (WSTOPSIG(status) != SIGTRAP) {
Juan Cespedesc9a48b91997-08-17 02:45:40 +0200100 fprintf(output, "[0x%08lx] Signal: %u\n", get_eip(pid), WSTOPSIG(status));
101 continue_process(pid, WSTOPSIG(status));
Juan Cespedes155a4081997-06-11 01:19:35 +0200102 continue;
103 }
Juan Cespedesad783621997-06-10 17:11:33 +0200104 /* pid is stopped... */
Juan Cespedesc9a48b91997-08-17 02:45:40 +0200105 eip = get_eip(pid);
Juan Cespedes96935a91997-08-09 23:45:39 +0200106 esp = ptrace(PTRACE_PEEKUSER, pid, 4*UESP, 0);
Juan Cespedesd3ac65f1997-06-16 00:20:35 +0200107#if 0
Juan Cespedes5b2f9811997-07-17 00:05:10 +0200108 fprintf(output,"EIP = 0x%08x\n", eip);
109 fprintf(output,"ESP = 0x%08x\n", esp);
Juan Cespedesd3ac65f1997-06-16 00:20:35 +0200110#endif
Juan Cespedes5b2f9811997-07-17 00:05:10 +0200111 fprintf(output,"[0x%08x] ", ptrace(PTRACE_PEEKTEXT, pid, esp, 0));
Juan Cespedesad783621997-06-10 17:11:33 +0200112 tmp = library_symbols;
113 function_seen = 0;
114 while(tmp) {
Juan Cespedesc9a48b91997-08-17 02:45:40 +0200115 if (eip == tmp->addr) {
Juan Cespedesad783621997-06-10 17:11:33 +0200116 function_seen = 1;
Juan Cespedesd3ac65f1997-06-16 00:20:35 +0200117 print_function(tmp->name, esp);
Juan Cespedesc9a48b91997-08-17 02:45:40 +0200118 continue_after_breakpoint(pid, eip, tmp->old_value, 0);
Juan Cespedesad783621997-06-10 17:11:33 +0200119 break;
120 }
121 tmp = tmp->next;
122 }
123 if (!function_seen) {
Juan Cespedes5b2f9811997-07-17 00:05:10 +0200124 fprintf(output, "pid %u stopped; continuing it...\n", pid);
Juan Cespedesc9a48b91997-08-17 02:45:40 +0200125 continue_process(pid, 0);
Juan Cespedes1c2be911997-06-09 01:12:01 +0200126 }
127 }
128 exit(0);
129}