proc.c revision 029171fffcf6328768866cf510763b2eb927f1bd
1750ca8c13f402a40b01802dcb5c88e092ff68125Petr Machata#define _GNU_SOURCE /* For getline. */ 2d44c6b8b090b8b7aa9d971d9e0bfd848732a3071Juan Cespedes#include "config.h" 3d44c6b8b090b8b7aa9d971d9e0bfd848732a3071Juan Cespedes 41fe93d5b55ad2b8d4009a63e343db19cc1f21bb0Juan Cespedes#include <sys/types.h> 59a5420c82a2fd81681572a2e3859ea1671c3bdedPetr Machata#include <sys/stat.h> 69a5420c82a2fd81681572a2e3859ea1671c3bdedPetr Machata#include <fcntl.h> 7bfb26c745705a839f1ef5fc45e1b32135b9bc3e7Zachary T Welch#include <inttypes.h> 847cae1e251a212425cae5ac6e736de0cb0bbf714Joe Damato#include <link.h> 91fe93d5b55ad2b8d4009a63e343db19cc1f21bb0Juan Cespedes#include <stdio.h> 101fe93d5b55ad2b8d4009a63e343db19cc1f21bb0Juan Cespedes#include <string.h> 111fe93d5b55ad2b8d4009a63e343db19cc1f21bb0Juan Cespedes#include <signal.h> 12273ea6d18164e35ee40524e853a6f04706d3bdffJuan Cespedes#include <unistd.h> 139a5420c82a2fd81681572a2e3859ea1671c3bdedPetr Machata#include <dirent.h> 149a5420c82a2fd81681572a2e3859ea1671c3bdedPetr Machata#include <ctype.h> 159a5420c82a2fd81681572a2e3859ea1671c3bdedPetr Machata#include <errno.h> 169a5420c82a2fd81681572a2e3859ea1671c3bdedPetr Machata#include <sys/syscall.h> 17750ca8c13f402a40b01802dcb5c88e092ff68125Petr Machata#include <error.h> 189a5420c82a2fd81681572a2e3859ea1671c3bdedPetr Machata 19a611fc8f887c099b04cb764f477b9289a4c21d6ePetr Machata#include "common.h" 209294d82f67e20f5f2b61f317ad04f5cb717c7d27Petr Machata#include "breakpoint.h" 21366c2f46d844f040458df9b7e35fc3b8527ed2d3Petr Machata#include "proc.h" 222b46cfc1127d390eddd9593fe5ce5399c1f68130Petr Machata#include "library.h" 23273ea6d18164e35ee40524e853a6f04706d3bdffJuan Cespedes 24273ea6d18164e35ee40524e853a6f04706d3bdffJuan Cespedes/* /proc/pid doesn't exist just after the fork, and sometimes `ltrace' 25273ea6d18164e35ee40524e853a6f04706d3bdffJuan Cespedes * couldn't open it to find the executable. So it may be necessary to 26273ea6d18164e35ee40524e853a6f04706d3bdffJuan Cespedes * have a bit delay 27273ea6d18164e35ee40524e853a6f04706d3bdffJuan Cespedes */ 28273ea6d18164e35ee40524e853a6f04706d3bdffJuan Cespedes 292d45b1a8e26a36a9f85dc49e721c4390ca93dc40Ian Wienand#define MAX_DELAY 100000 /* 100000 microseconds = 0.1 seconds */ 301fe93d5b55ad2b8d4009a63e343db19cc1f21bb0Juan Cespedes 319a5420c82a2fd81681572a2e3859ea1671c3bdedPetr Machata#define PROC_PID_FILE(VAR, FORMAT, PID) \ 329a5420c82a2fd81681572a2e3859ea1671c3bdedPetr Machata char VAR[strlen(FORMAT) + 6]; \ 339a5420c82a2fd81681572a2e3859ea1671c3bdedPetr Machata sprintf(VAR, FORMAT, PID) 349a5420c82a2fd81681572a2e3859ea1671c3bdedPetr Machata 351fe93d5b55ad2b8d4009a63e343db19cc1f21bb0Juan Cespedes/* 36e0660df7f943cc832694db3b8b6778c0ff65860dJuan Cespedes * Returns a (malloc'd) file name corresponding to a running pid 371fe93d5b55ad2b8d4009a63e343db19cc1f21bb0Juan Cespedes */ 38f13505251e6402460f6cc7ec84e0d8ca91607b4fJuan Cespedeschar * 39f13505251e6402460f6cc7ec84e0d8ca91607b4fJuan Cespedespid2name(pid_t pid) { 401fe93d5b55ad2b8d4009a63e343db19cc1f21bb0Juan Cespedes if (!kill(pid, 0)) { 412d45b1a8e26a36a9f85dc49e721c4390ca93dc40Ian Wienand int delay = 0; 42273ea6d18164e35ee40524e853a6f04706d3bdffJuan Cespedes 439a5420c82a2fd81681572a2e3859ea1671c3bdedPetr Machata PROC_PID_FILE(proc_exe, "/proc/%d/exe", pid); 44273ea6d18164e35ee40524e853a6f04706d3bdffJuan Cespedes 452d45b1a8e26a36a9f85dc49e721c4390ca93dc40Ian Wienand while (delay < MAX_DELAY) { 46273ea6d18164e35ee40524e853a6f04706d3bdffJuan Cespedes if (!access(proc_exe, F_OK)) { 47273ea6d18164e35ee40524e853a6f04706d3bdffJuan Cespedes return strdup(proc_exe); 48273ea6d18164e35ee40524e853a6f04706d3bdffJuan Cespedes } 49273ea6d18164e35ee40524e853a6f04706d3bdffJuan Cespedes delay += 1000; /* 1 milisecond */ 50273ea6d18164e35ee40524e853a6f04706d3bdffJuan Cespedes } 511fe93d5b55ad2b8d4009a63e343db19cc1f21bb0Juan Cespedes } 52273ea6d18164e35ee40524e853a6f04706d3bdffJuan Cespedes return NULL; 531fe93d5b55ad2b8d4009a63e343db19cc1f21bb0Juan Cespedes} 5447cae1e251a212425cae5ac6e736de0cb0bbf714Joe Damato 559a5420c82a2fd81681572a2e3859ea1671c3bdedPetr Machatastatic FILE * 569a5420c82a2fd81681572a2e3859ea1671c3bdedPetr Machataopen_status_file(pid_t pid) 579a5420c82a2fd81681572a2e3859ea1671c3bdedPetr Machata{ 589a5420c82a2fd81681572a2e3859ea1671c3bdedPetr Machata PROC_PID_FILE(fn, "/proc/%d/status", pid); 599a5420c82a2fd81681572a2e3859ea1671c3bdedPetr Machata /* Don't complain if we fail. This would typically happen 609a5420c82a2fd81681572a2e3859ea1671c3bdedPetr Machata when the process is about to terminate, and these files are 619a5420c82a2fd81681572a2e3859ea1671c3bdedPetr Machata not available anymore. This function is called from the 629a5420c82a2fd81681572a2e3859ea1671c3bdedPetr Machata event loop, and we don't want to clutter the output just 639a5420c82a2fd81681572a2e3859ea1671c3bdedPetr Machata because the process terminates. */ 649a5420c82a2fd81681572a2e3859ea1671c3bdedPetr Machata return fopen(fn, "r"); 659a5420c82a2fd81681572a2e3859ea1671c3bdedPetr Machata} 669a5420c82a2fd81681572a2e3859ea1671c3bdedPetr Machata 679a5420c82a2fd81681572a2e3859ea1671c3bdedPetr Machatastatic char * 689a5420c82a2fd81681572a2e3859ea1671c3bdedPetr Machatafind_line_starting(FILE * file, const char * prefix, size_t len) 699a5420c82a2fd81681572a2e3859ea1671c3bdedPetr Machata{ 709a5420c82a2fd81681572a2e3859ea1671c3bdedPetr Machata char * line = NULL; 719a5420c82a2fd81681572a2e3859ea1671c3bdedPetr Machata size_t line_len = 0; 729a5420c82a2fd81681572a2e3859ea1671c3bdedPetr Machata while (!feof(file)) { 739a5420c82a2fd81681572a2e3859ea1671c3bdedPetr Machata if (getline(&line, &line_len, file) < 0) 749a5420c82a2fd81681572a2e3859ea1671c3bdedPetr Machata return NULL; 759a5420c82a2fd81681572a2e3859ea1671c3bdedPetr Machata if (strncmp(line, prefix, len) == 0) 769a5420c82a2fd81681572a2e3859ea1671c3bdedPetr Machata return line; 779a5420c82a2fd81681572a2e3859ea1671c3bdedPetr Machata } 789a5420c82a2fd81681572a2e3859ea1671c3bdedPetr Machata return NULL; 799a5420c82a2fd81681572a2e3859ea1671c3bdedPetr Machata} 809a5420c82a2fd81681572a2e3859ea1671c3bdedPetr Machata 819a5420c82a2fd81681572a2e3859ea1671c3bdedPetr Machatastatic void 822b46cfc1127d390eddd9593fe5ce5399c1f68130Petr Machataeach_line_starting(FILE *file, const char *prefix, 832b46cfc1127d390eddd9593fe5ce5399c1f68130Petr Machata enum callback_status (*cb)(const char *line, 842b46cfc1127d390eddd9593fe5ce5399c1f68130Petr Machata const char *prefix, 852b46cfc1127d390eddd9593fe5ce5399c1f68130Petr Machata void *data), 862b46cfc1127d390eddd9593fe5ce5399c1f68130Petr Machata void *data) 879a5420c82a2fd81681572a2e3859ea1671c3bdedPetr Machata{ 889a5420c82a2fd81681572a2e3859ea1671c3bdedPetr Machata size_t len = strlen(prefix); 899a5420c82a2fd81681572a2e3859ea1671c3bdedPetr Machata char * line; 909a5420c82a2fd81681572a2e3859ea1671c3bdedPetr Machata while ((line = find_line_starting(file, prefix, len)) != NULL) { 912b46cfc1127d390eddd9593fe5ce5399c1f68130Petr Machata enum callback_status st = (*cb)(line, prefix, data); 929a5420c82a2fd81681572a2e3859ea1671c3bdedPetr Machata free (line); 932b46cfc1127d390eddd9593fe5ce5399c1f68130Petr Machata if (st == CBS_STOP) 949a5420c82a2fd81681572a2e3859ea1671c3bdedPetr Machata return; 959a5420c82a2fd81681572a2e3859ea1671c3bdedPetr Machata } 969a5420c82a2fd81681572a2e3859ea1671c3bdedPetr Machata} 979a5420c82a2fd81681572a2e3859ea1671c3bdedPetr Machata 982b46cfc1127d390eddd9593fe5ce5399c1f68130Petr Machatastatic enum callback_status 992b46cfc1127d390eddd9593fe5ce5399c1f68130Petr Machataprocess_leader_cb(const char *line, const char *prefix, void *data) 1009a5420c82a2fd81681572a2e3859ea1671c3bdedPetr Machata{ 1019a5420c82a2fd81681572a2e3859ea1671c3bdedPetr Machata pid_t * pidp = data; 1029a5420c82a2fd81681572a2e3859ea1671c3bdedPetr Machata *pidp = atoi(line + strlen(prefix)); 1032b46cfc1127d390eddd9593fe5ce5399c1f68130Petr Machata return CBS_STOP; 1049a5420c82a2fd81681572a2e3859ea1671c3bdedPetr Machata} 1059a5420c82a2fd81681572a2e3859ea1671c3bdedPetr Machata 1069a5420c82a2fd81681572a2e3859ea1671c3bdedPetr Machatapid_t 1079a5420c82a2fd81681572a2e3859ea1671c3bdedPetr Machataprocess_leader(pid_t pid) 1089a5420c82a2fd81681572a2e3859ea1671c3bdedPetr Machata{ 1091974dbccbf10a2dd8e06724d2fb4eb61fd91076aPetr Machata pid_t tgid = 0; 1109a5420c82a2fd81681572a2e3859ea1671c3bdedPetr Machata FILE * file = open_status_file(pid); 1119a5420c82a2fd81681572a2e3859ea1671c3bdedPetr Machata if (file != NULL) { 1129a5420c82a2fd81681572a2e3859ea1671c3bdedPetr Machata each_line_starting(file, "Tgid:\t", &process_leader_cb, &tgid); 1139a5420c82a2fd81681572a2e3859ea1671c3bdedPetr Machata fclose(file); 1149a5420c82a2fd81681572a2e3859ea1671c3bdedPetr Machata } 1159a5420c82a2fd81681572a2e3859ea1671c3bdedPetr Machata 1169a5420c82a2fd81681572a2e3859ea1671c3bdedPetr Machata return tgid; 1179a5420c82a2fd81681572a2e3859ea1671c3bdedPetr Machata} 1189a5420c82a2fd81681572a2e3859ea1671c3bdedPetr Machata 1192b46cfc1127d390eddd9593fe5ce5399c1f68130Petr Machatastatic enum callback_status 1202b46cfc1127d390eddd9593fe5ce5399c1f68130Petr Machataprocess_stopped_cb(const char *line, const char *prefix, void *data) 1219a5420c82a2fd81681572a2e3859ea1671c3bdedPetr Machata{ 1229a5420c82a2fd81681572a2e3859ea1671c3bdedPetr Machata char c = line[strlen(prefix)]; 1239a5420c82a2fd81681572a2e3859ea1671c3bdedPetr Machata // t:tracing stop, T:job control stop 1249a5420c82a2fd81681572a2e3859ea1671c3bdedPetr Machata *(int *)data = (c == 't' || c == 'T'); 1252b46cfc1127d390eddd9593fe5ce5399c1f68130Petr Machata return CBS_STOP; 1269a5420c82a2fd81681572a2e3859ea1671c3bdedPetr Machata} 1279a5420c82a2fd81681572a2e3859ea1671c3bdedPetr Machata 1289a5420c82a2fd81681572a2e3859ea1671c3bdedPetr Machataint 1299a5420c82a2fd81681572a2e3859ea1671c3bdedPetr Machataprocess_stopped(pid_t pid) 1309a5420c82a2fd81681572a2e3859ea1671c3bdedPetr Machata{ 1319a5420c82a2fd81681572a2e3859ea1671c3bdedPetr Machata int is_stopped = -1; 1329a5420c82a2fd81681572a2e3859ea1671c3bdedPetr Machata FILE * file = open_status_file(pid); 1339a5420c82a2fd81681572a2e3859ea1671c3bdedPetr Machata if (file != NULL) { 1349a5420c82a2fd81681572a2e3859ea1671c3bdedPetr Machata each_line_starting(file, "State:\t", &process_stopped_cb, 1359a5420c82a2fd81681572a2e3859ea1671c3bdedPetr Machata &is_stopped); 1369a5420c82a2fd81681572a2e3859ea1671c3bdedPetr Machata fclose(file); 1379a5420c82a2fd81681572a2e3859ea1671c3bdedPetr Machata } 1389a5420c82a2fd81681572a2e3859ea1671c3bdedPetr Machata return is_stopped; 1399a5420c82a2fd81681572a2e3859ea1671c3bdedPetr Machata} 1409a5420c82a2fd81681572a2e3859ea1671c3bdedPetr Machata 1412b46cfc1127d390eddd9593fe5ce5399c1f68130Petr Machatastatic enum callback_status 1422b46cfc1127d390eddd9593fe5ce5399c1f68130Petr Machataprocess_status_cb(const char *line, const char *prefix, void *data) 1439a5420c82a2fd81681572a2e3859ea1671c3bdedPetr Machata{ 144617ff0bb228c64df4bb6682321338aecfec2d170Petr Machata const char * status = line + strlen(prefix); 145617ff0bb228c64df4bb6682321338aecfec2d170Petr Machata const char c = *status; 146617ff0bb228c64df4bb6682321338aecfec2d170Petr Machata 147617ff0bb228c64df4bb6682321338aecfec2d170Petr Machata#define RETURN(C) do { \ 148617ff0bb228c64df4bb6682321338aecfec2d170Petr Machata *(enum process_status *)data = C; \ 1492b46cfc1127d390eddd9593fe5ce5399c1f68130Petr Machata return CBS_STOP; \ 150617ff0bb228c64df4bb6682321338aecfec2d170Petr Machata } while (0) 151617ff0bb228c64df4bb6682321338aecfec2d170Petr Machata 152617ff0bb228c64df4bb6682321338aecfec2d170Petr Machata switch (c) { 153617ff0bb228c64df4bb6682321338aecfec2d170Petr Machata case 'Z': RETURN(ps_zombie); 154617ff0bb228c64df4bb6682321338aecfec2d170Petr Machata case 't': RETURN(ps_tracing_stop); 155cbe29c6c0ad01839a81272c4715ea73d17e89611Petr Machata case 'T': 156617ff0bb228c64df4bb6682321338aecfec2d170Petr Machata /* This can be either "T (stopped)" or, for older 157617ff0bb228c64df4bb6682321338aecfec2d170Petr Machata * kernels, "T (tracing stop)". */ 158617ff0bb228c64df4bb6682321338aecfec2d170Petr Machata if (!strcmp(status, "T (stopped)\n")) 159617ff0bb228c64df4bb6682321338aecfec2d170Petr Machata RETURN(ps_stop); 160617ff0bb228c64df4bb6682321338aecfec2d170Petr Machata else if (!strcmp(status, "T (tracing stop)\n")) 161617ff0bb228c64df4bb6682321338aecfec2d170Petr Machata RETURN(ps_tracing_stop); 162617ff0bb228c64df4bb6682321338aecfec2d170Petr Machata else { 163617ff0bb228c64df4bb6682321338aecfec2d170Petr Machata fprintf(stderr, "Unknown process status: %s", 164617ff0bb228c64df4bb6682321338aecfec2d170Petr Machata status); 165617ff0bb228c64df4bb6682321338aecfec2d170Petr Machata RETURN(ps_stop); /* Some sort of stop 166617ff0bb228c64df4bb6682321338aecfec2d170Petr Machata * anyway. */ 167617ff0bb228c64df4bb6682321338aecfec2d170Petr Machata } 168cbe29c6c0ad01839a81272c4715ea73d17e89611Petr Machata case 'D': 169cbe29c6c0ad01839a81272c4715ea73d17e89611Petr Machata case 'S': RETURN(ps_sleeping); 170617ff0bb228c64df4bb6682321338aecfec2d170Petr Machata } 171617ff0bb228c64df4bb6682321338aecfec2d170Petr Machata 172617ff0bb228c64df4bb6682321338aecfec2d170Petr Machata RETURN(ps_other); 173617ff0bb228c64df4bb6682321338aecfec2d170Petr Machata#undef RETURN 1749a5420c82a2fd81681572a2e3859ea1671c3bdedPetr Machata} 1759a5420c82a2fd81681572a2e3859ea1671c3bdedPetr Machata 176617ff0bb228c64df4bb6682321338aecfec2d170Petr Machataenum process_status 1779a5420c82a2fd81681572a2e3859ea1671c3bdedPetr Machataprocess_status(pid_t pid) 1789a5420c82a2fd81681572a2e3859ea1671c3bdedPetr Machata{ 179617ff0bb228c64df4bb6682321338aecfec2d170Petr Machata enum process_status ret = ps_invalid; 1809a5420c82a2fd81681572a2e3859ea1671c3bdedPetr Machata FILE * file = open_status_file(pid); 1819a5420c82a2fd81681572a2e3859ea1671c3bdedPetr Machata if (file != NULL) { 1829a5420c82a2fd81681572a2e3859ea1671c3bdedPetr Machata each_line_starting(file, "State:\t", &process_status_cb, &ret); 1839a5420c82a2fd81681572a2e3859ea1671c3bdedPetr Machata fclose(file); 184750ca8c13f402a40b01802dcb5c88e092ff68125Petr Machata if (ret == ps_invalid) 185750ca8c13f402a40b01802dcb5c88e092ff68125Petr Machata error(0, errno, "process_status %d", pid); 186750ca8c13f402a40b01802dcb5c88e092ff68125Petr Machata } else 187750ca8c13f402a40b01802dcb5c88e092ff68125Petr Machata /* If the file is not present, the process presumably 188750ca8c13f402a40b01802dcb5c88e092ff68125Petr Machata * exited already. */ 189750ca8c13f402a40b01802dcb5c88e092ff68125Petr Machata ret = ps_zombie; 190750ca8c13f402a40b01802dcb5c88e092ff68125Petr Machata 1919a5420c82a2fd81681572a2e3859ea1671c3bdedPetr Machata return ret; 1929a5420c82a2fd81681572a2e3859ea1671c3bdedPetr Machata} 1939a5420c82a2fd81681572a2e3859ea1671c3bdedPetr Machata 1949a5420c82a2fd81681572a2e3859ea1671c3bdedPetr Machatastatic int 1959a5420c82a2fd81681572a2e3859ea1671c3bdedPetr Machataall_digits(const char *str) 1969a5420c82a2fd81681572a2e3859ea1671c3bdedPetr Machata{ 1979a5420c82a2fd81681572a2e3859ea1671c3bdedPetr Machata while (isdigit(*str)) 1989a5420c82a2fd81681572a2e3859ea1671c3bdedPetr Machata str++; 1999a5420c82a2fd81681572a2e3859ea1671c3bdedPetr Machata return !*str; 2009a5420c82a2fd81681572a2e3859ea1671c3bdedPetr Machata} 2019a5420c82a2fd81681572a2e3859ea1671c3bdedPetr Machata 2029a5420c82a2fd81681572a2e3859ea1671c3bdedPetr Machataint 2039a5420c82a2fd81681572a2e3859ea1671c3bdedPetr Machataprocess_tasks(pid_t pid, pid_t **ret_tasks, size_t *ret_n) 2049a5420c82a2fd81681572a2e3859ea1671c3bdedPetr Machata{ 2059a5420c82a2fd81681572a2e3859ea1671c3bdedPetr Machata PROC_PID_FILE(fn, "/proc/%d/task", pid); 2069a5420c82a2fd81681572a2e3859ea1671c3bdedPetr Machata DIR * d = opendir(fn); 2079a5420c82a2fd81681572a2e3859ea1671c3bdedPetr Machata if (d == NULL) 2089a5420c82a2fd81681572a2e3859ea1671c3bdedPetr Machata return -1; 2099a5420c82a2fd81681572a2e3859ea1671c3bdedPetr Machata 2109a5420c82a2fd81681572a2e3859ea1671c3bdedPetr Machata pid_t *tasks = NULL; 2119a5420c82a2fd81681572a2e3859ea1671c3bdedPetr Machata size_t n = 0; 2129a5420c82a2fd81681572a2e3859ea1671c3bdedPetr Machata size_t alloc = 0; 2139a5420c82a2fd81681572a2e3859ea1671c3bdedPetr Machata 2149a5420c82a2fd81681572a2e3859ea1671c3bdedPetr Machata while (1) { 2159a5420c82a2fd81681572a2e3859ea1671c3bdedPetr Machata struct dirent entry; 2169a5420c82a2fd81681572a2e3859ea1671c3bdedPetr Machata struct dirent *result; 2179a5420c82a2fd81681572a2e3859ea1671c3bdedPetr Machata if (readdir_r(d, &entry, &result) != 0) { 2189a5420c82a2fd81681572a2e3859ea1671c3bdedPetr Machata free(tasks); 2199a5420c82a2fd81681572a2e3859ea1671c3bdedPetr Machata return -1; 2209a5420c82a2fd81681572a2e3859ea1671c3bdedPetr Machata } 2219a5420c82a2fd81681572a2e3859ea1671c3bdedPetr Machata if (result == NULL) 2229a5420c82a2fd81681572a2e3859ea1671c3bdedPetr Machata break; 2239a5420c82a2fd81681572a2e3859ea1671c3bdedPetr Machata if (result->d_type == DT_DIR && all_digits(result->d_name)) { 2249a5420c82a2fd81681572a2e3859ea1671c3bdedPetr Machata pid_t npid = atoi(result->d_name); 2259a5420c82a2fd81681572a2e3859ea1671c3bdedPetr Machata if (n >= alloc) { 2269a5420c82a2fd81681572a2e3859ea1671c3bdedPetr Machata alloc = alloc > 0 ? (2 * alloc) : 8; 2279a5420c82a2fd81681572a2e3859ea1671c3bdedPetr Machata pid_t *ntasks = realloc(tasks, 2289a5420c82a2fd81681572a2e3859ea1671c3bdedPetr Machata sizeof(*tasks) * alloc); 2299a5420c82a2fd81681572a2e3859ea1671c3bdedPetr Machata if (ntasks == NULL) { 2309a5420c82a2fd81681572a2e3859ea1671c3bdedPetr Machata free(tasks); 2319a5420c82a2fd81681572a2e3859ea1671c3bdedPetr Machata return -1; 2329a5420c82a2fd81681572a2e3859ea1671c3bdedPetr Machata } 2339a5420c82a2fd81681572a2e3859ea1671c3bdedPetr Machata tasks = ntasks; 2349a5420c82a2fd81681572a2e3859ea1671c3bdedPetr Machata } 2359a5420c82a2fd81681572a2e3859ea1671c3bdedPetr Machata if (n >= alloc) 2369a5420c82a2fd81681572a2e3859ea1671c3bdedPetr Machata abort(); 2379a5420c82a2fd81681572a2e3859ea1671c3bdedPetr Machata tasks[n++] = npid; 2389a5420c82a2fd81681572a2e3859ea1671c3bdedPetr Machata } 2399a5420c82a2fd81681572a2e3859ea1671c3bdedPetr Machata } 2409a5420c82a2fd81681572a2e3859ea1671c3bdedPetr Machata 2419a5420c82a2fd81681572a2e3859ea1671c3bdedPetr Machata closedir(d); 2429a5420c82a2fd81681572a2e3859ea1671c3bdedPetr Machata 2439a5420c82a2fd81681572a2e3859ea1671c3bdedPetr Machata *ret_tasks = tasks; 2449a5420c82a2fd81681572a2e3859ea1671c3bdedPetr Machata *ret_n = n; 2459a5420c82a2fd81681572a2e3859ea1671c3bdedPetr Machata return 0; 2469a5420c82a2fd81681572a2e3859ea1671c3bdedPetr Machata} 2479a5420c82a2fd81681572a2e3859ea1671c3bdedPetr Machata 2486a7997de9eabf9b0c6e32309ca08870198eb864bPetr Machata/* On native 64-bit system, we need to be careful when handling cross 2496a7997de9eabf9b0c6e32309ca08870198eb864bPetr Machata * tracing. This select appropriate pointer depending on host and 2506a7997de9eabf9b0c6e32309ca08870198eb864bPetr Machata * target architectures. XXX Really we should abstract this into the 2516a7997de9eabf9b0c6e32309ca08870198eb864bPetr Machata * ABI object, as theorized about somewhere on pmachata/revamp 2526a7997de9eabf9b0c6e32309ca08870198eb864bPetr Machata * branch. */ 2536a7997de9eabf9b0c6e32309ca08870198eb864bPetr Machatastatic void * 2546a7997de9eabf9b0c6e32309ca08870198eb864bPetr Machataselect_32_64(struct Process *proc, void *p32, void *p64) 2556a7997de9eabf9b0c6e32309ca08870198eb864bPetr Machata{ 2566a7997de9eabf9b0c6e32309ca08870198eb864bPetr Machata if (sizeof(long) == 4 || proc->mask_32bit) 2576a7997de9eabf9b0c6e32309ca08870198eb864bPetr Machata return p32; 2586a7997de9eabf9b0c6e32309ca08870198eb864bPetr Machata else 2596a7997de9eabf9b0c6e32309ca08870198eb864bPetr Machata return p64; 2606a7997de9eabf9b0c6e32309ca08870198eb864bPetr Machata} 2616a7997de9eabf9b0c6e32309ca08870198eb864bPetr Machata 2626a7997de9eabf9b0c6e32309ca08870198eb864bPetr Machatastatic int 2636a7997de9eabf9b0c6e32309ca08870198eb864bPetr Machatafetch_dyn64(struct Process *proc, target_address_t *addr, Elf64_Dyn *ret) 2646a7997de9eabf9b0c6e32309ca08870198eb864bPetr Machata{ 2656a7997de9eabf9b0c6e32309ca08870198eb864bPetr Machata if (umovebytes(proc, *addr, ret, sizeof(*ret)) != sizeof(*ret)) 2666a7997de9eabf9b0c6e32309ca08870198eb864bPetr Machata return -1; 2676a7997de9eabf9b0c6e32309ca08870198eb864bPetr Machata *addr += sizeof(*ret); 2686a7997de9eabf9b0c6e32309ca08870198eb864bPetr Machata return 0; 2696a7997de9eabf9b0c6e32309ca08870198eb864bPetr Machata} 2706a7997de9eabf9b0c6e32309ca08870198eb864bPetr Machata 2716a7997de9eabf9b0c6e32309ca08870198eb864bPetr Machatastatic int 2726a7997de9eabf9b0c6e32309ca08870198eb864bPetr Machatafetch_dyn32(struct Process *proc, target_address_t *addr, Elf64_Dyn *ret) 2736a7997de9eabf9b0c6e32309ca08870198eb864bPetr Machata{ 2746a7997de9eabf9b0c6e32309ca08870198eb864bPetr Machata Elf32_Dyn dyn; 2756a7997de9eabf9b0c6e32309ca08870198eb864bPetr Machata if (umovebytes(proc, *addr, &dyn, sizeof(dyn)) != sizeof(dyn)) 2766a7997de9eabf9b0c6e32309ca08870198eb864bPetr Machata return -1; 2776a7997de9eabf9b0c6e32309ca08870198eb864bPetr Machata 2786a7997de9eabf9b0c6e32309ca08870198eb864bPetr Machata *addr += sizeof(dyn); 2796a7997de9eabf9b0c6e32309ca08870198eb864bPetr Machata ret->d_tag = dyn.d_tag; 2806a7997de9eabf9b0c6e32309ca08870198eb864bPetr Machata ret->d_un.d_val = dyn.d_un.d_val; 2816a7997de9eabf9b0c6e32309ca08870198eb864bPetr Machata 2826a7997de9eabf9b0c6e32309ca08870198eb864bPetr Machata return 0; 2836a7997de9eabf9b0c6e32309ca08870198eb864bPetr Machata} 2846a7997de9eabf9b0c6e32309ca08870198eb864bPetr Machata 2856a7997de9eabf9b0c6e32309ca08870198eb864bPetr Machatastatic int (* 2866a7997de9eabf9b0c6e32309ca08870198eb864bPetr Machatadyn_fetcher(struct Process *proc))(struct Process *, 2876a7997de9eabf9b0c6e32309ca08870198eb864bPetr Machata target_address_t *, Elf64_Dyn *) 2886a7997de9eabf9b0c6e32309ca08870198eb864bPetr Machata{ 2896a7997de9eabf9b0c6e32309ca08870198eb864bPetr Machata return select_32_64(proc, fetch_dyn32, fetch_dyn64); 2906a7997de9eabf9b0c6e32309ca08870198eb864bPetr Machata} 2916a7997de9eabf9b0c6e32309ca08870198eb864bPetr Machata 29247cae1e251a212425cae5ac6e736de0cb0bbf714Joe Damatostatic int 2936a7997de9eabf9b0c6e32309ca08870198eb864bPetr Machatafind_dynamic_entry_addr(struct Process *proc, target_address_t src_addr, 2946a7997de9eabf9b0c6e32309ca08870198eb864bPetr Machata int d_tag, target_address_t *ret) 2956a7997de9eabf9b0c6e32309ca08870198eb864bPetr Machata{ 2962b46cfc1127d390eddd9593fe5ce5399c1f68130Petr Machata fprintf(stderr, "find_dynamic_entry_addr %d %p %d\n", 2976a7997de9eabf9b0c6e32309ca08870198eb864bPetr Machata proc->pid, src_addr, d_tag); 29847cae1e251a212425cae5ac6e736de0cb0bbf714Joe Damato 29947cae1e251a212425cae5ac6e736de0cb0bbf714Joe Damato debug(DEBUG_FUNCTION, "find_dynamic_entry()"); 30047cae1e251a212425cae5ac6e736de0cb0bbf714Joe Damato 3016a7997de9eabf9b0c6e32309ca08870198eb864bPetr Machata if (ret == NULL || src_addr == 0 || d_tag < 0 || d_tag > DT_NUM) 30247cae1e251a212425cae5ac6e736de0cb0bbf714Joe Damato return -1; 30347cae1e251a212425cae5ac6e736de0cb0bbf714Joe Damato 3046a7997de9eabf9b0c6e32309ca08870198eb864bPetr Machata int i = 0; 3056a7997de9eabf9b0c6e32309ca08870198eb864bPetr Machata while (1) { 3066a7997de9eabf9b0c6e32309ca08870198eb864bPetr Machata Elf64_Dyn entry; 3076a7997de9eabf9b0c6e32309ca08870198eb864bPetr Machata if (dyn_fetcher(proc)(proc, &src_addr, &entry) < 0 3086a7997de9eabf9b0c6e32309ca08870198eb864bPetr Machata || entry.d_tag == DT_NULL 3096a7997de9eabf9b0c6e32309ca08870198eb864bPetr Machata || i++ > 100) { /* Arbitrary cut-off so that we 3106a7997de9eabf9b0c6e32309ca08870198eb864bPetr Machata * don't loop forever if the 3116a7997de9eabf9b0c6e32309ca08870198eb864bPetr Machata * binary is corrupted. */ 3126a7997de9eabf9b0c6e32309ca08870198eb864bPetr Machata debug(2, "Couldn't find address for dtag!"); 3136a7997de9eabf9b0c6e32309ca08870198eb864bPetr Machata return -1; 3146a7997de9eabf9b0c6e32309ca08870198eb864bPetr Machata } 3156a7997de9eabf9b0c6e32309ca08870198eb864bPetr Machata 31647cae1e251a212425cae5ac6e736de0cb0bbf714Joe Damato if (entry.d_tag == d_tag) { 3172b46cfc1127d390eddd9593fe5ce5399c1f68130Petr Machata fprintf(stderr, " hit\n"); 3186a7997de9eabf9b0c6e32309ca08870198eb864bPetr Machata *ret = (target_address_t)entry.d_un.d_val; 3196a7997de9eabf9b0c6e32309ca08870198eb864bPetr Machata debug(2, "found address: %p in dtag %d\n", *ret, d_tag); 32017476b7bfac0e1cb68f9a1dbdb65dab2ac2160c6Petr Machata return 0; 32147cae1e251a212425cae5ac6e736de0cb0bbf714Joe Damato } 32247cae1e251a212425cae5ac6e736de0cb0bbf714Joe Damato } 3236a7997de9eabf9b0c6e32309ca08870198eb864bPetr Machata} 3246a7997de9eabf9b0c6e32309ca08870198eb864bPetr Machata 3256a7997de9eabf9b0c6e32309ca08870198eb864bPetr Machata/* Our own type for representing 32-bit linkmap. We can't rely on the 3266a7997de9eabf9b0c6e32309ca08870198eb864bPetr Machata * definition in link.h, because that's only accurate for our host 3276a7997de9eabf9b0c6e32309ca08870198eb864bPetr Machata * architecture, not for target architecture (where the traced process 3286a7997de9eabf9b0c6e32309ca08870198eb864bPetr Machata * runs). */ 3296a7997de9eabf9b0c6e32309ca08870198eb864bPetr Machata#define LT_LINK_MAP(BITS) \ 3306a7997de9eabf9b0c6e32309ca08870198eb864bPetr Machata { \ 3316a7997de9eabf9b0c6e32309ca08870198eb864bPetr Machata Elf##BITS##_Addr l_addr; \ 3326a7997de9eabf9b0c6e32309ca08870198eb864bPetr Machata Elf##BITS##_Addr l_name; \ 3336a7997de9eabf9b0c6e32309ca08870198eb864bPetr Machata Elf##BITS##_Addr l_ld; \ 3346a7997de9eabf9b0c6e32309ca08870198eb864bPetr Machata Elf##BITS##_Addr l_next; \ 3356a7997de9eabf9b0c6e32309ca08870198eb864bPetr Machata Elf##BITS##_Addr l_prev; \ 3366a7997de9eabf9b0c6e32309ca08870198eb864bPetr Machata } 3376a7997de9eabf9b0c6e32309ca08870198eb864bPetr Machatastruct lt_link_map_32 LT_LINK_MAP(32); 3386a7997de9eabf9b0c6e32309ca08870198eb864bPetr Machatastruct lt_link_map_64 LT_LINK_MAP(64); 33947cae1e251a212425cae5ac6e736de0cb0bbf714Joe Damato 3406a7997de9eabf9b0c6e32309ca08870198eb864bPetr Machatastatic int 3416a7997de9eabf9b0c6e32309ca08870198eb864bPetr Machatafetch_lm64(struct Process *proc, target_address_t addr, 3426a7997de9eabf9b0c6e32309ca08870198eb864bPetr Machata struct lt_link_map_64 *ret) 3436a7997de9eabf9b0c6e32309ca08870198eb864bPetr Machata{ 3446a7997de9eabf9b0c6e32309ca08870198eb864bPetr Machata if (umovebytes(proc, addr, ret, sizeof(*ret)) != sizeof(*ret)) 3456a7997de9eabf9b0c6e32309ca08870198eb864bPetr Machata return -1; 3466a7997de9eabf9b0c6e32309ca08870198eb864bPetr Machata return 0; 3476a7997de9eabf9b0c6e32309ca08870198eb864bPetr Machata} 3486a7997de9eabf9b0c6e32309ca08870198eb864bPetr Machata 3496a7997de9eabf9b0c6e32309ca08870198eb864bPetr Machatastatic int 3506a7997de9eabf9b0c6e32309ca08870198eb864bPetr Machatafetch_lm32(struct Process *proc, target_address_t addr, 3516a7997de9eabf9b0c6e32309ca08870198eb864bPetr Machata struct lt_link_map_64 *ret) 3526a7997de9eabf9b0c6e32309ca08870198eb864bPetr Machata{ 3536a7997de9eabf9b0c6e32309ca08870198eb864bPetr Machata struct lt_link_map_32 lm; 3546a7997de9eabf9b0c6e32309ca08870198eb864bPetr Machata if (umovebytes(proc, addr, &lm, sizeof(lm)) != sizeof(lm)) 3556a7997de9eabf9b0c6e32309ca08870198eb864bPetr Machata return -1; 3566a7997de9eabf9b0c6e32309ca08870198eb864bPetr Machata 3576a7997de9eabf9b0c6e32309ca08870198eb864bPetr Machata ret->l_addr = lm.l_addr; 3586a7997de9eabf9b0c6e32309ca08870198eb864bPetr Machata ret->l_name = lm.l_name; 3596a7997de9eabf9b0c6e32309ca08870198eb864bPetr Machata ret->l_ld = lm.l_ld; 3606a7997de9eabf9b0c6e32309ca08870198eb864bPetr Machata ret->l_next = lm.l_next; 3616a7997de9eabf9b0c6e32309ca08870198eb864bPetr Machata ret->l_prev = lm.l_prev; 3626a7997de9eabf9b0c6e32309ca08870198eb864bPetr Machata 3636a7997de9eabf9b0c6e32309ca08870198eb864bPetr Machata return 0; 3646a7997de9eabf9b0c6e32309ca08870198eb864bPetr Machata} 3656a7997de9eabf9b0c6e32309ca08870198eb864bPetr Machata 3666a7997de9eabf9b0c6e32309ca08870198eb864bPetr Machatastatic int (* 3676a7997de9eabf9b0c6e32309ca08870198eb864bPetr Machatalm_fetcher(struct Process *proc))(struct Process *, 3686a7997de9eabf9b0c6e32309ca08870198eb864bPetr Machata target_address_t, struct lt_link_map_64 *) 3696a7997de9eabf9b0c6e32309ca08870198eb864bPetr Machata{ 3706a7997de9eabf9b0c6e32309ca08870198eb864bPetr Machata return select_32_64(proc, fetch_lm32, fetch_lm64); 3716a7997de9eabf9b0c6e32309ca08870198eb864bPetr Machata} 3726a7997de9eabf9b0c6e32309ca08870198eb864bPetr Machata 3736a7997de9eabf9b0c6e32309ca08870198eb864bPetr Machata/* The same as above holds for struct r_debug. */ 3746a7997de9eabf9b0c6e32309ca08870198eb864bPetr Machata#define LT_R_DEBUG(BITS) \ 3756a7997de9eabf9b0c6e32309ca08870198eb864bPetr Machata { \ 3766a7997de9eabf9b0c6e32309ca08870198eb864bPetr Machata int r_version; \ 3776a7997de9eabf9b0c6e32309ca08870198eb864bPetr Machata Elf##BITS##_Addr r_map; \ 3786a7997de9eabf9b0c6e32309ca08870198eb864bPetr Machata Elf##BITS##_Addr r_brk; \ 3796a7997de9eabf9b0c6e32309ca08870198eb864bPetr Machata int r_state; \ 3806a7997de9eabf9b0c6e32309ca08870198eb864bPetr Machata Elf##BITS##_Addr r_ldbase; \ 3816a7997de9eabf9b0c6e32309ca08870198eb864bPetr Machata } 3826a7997de9eabf9b0c6e32309ca08870198eb864bPetr Machata 3836a7997de9eabf9b0c6e32309ca08870198eb864bPetr Machatastruct lt_r_debug_32 LT_R_DEBUG(32); 3846a7997de9eabf9b0c6e32309ca08870198eb864bPetr Machatastruct lt_r_debug_64 LT_R_DEBUG(64); 3856a7997de9eabf9b0c6e32309ca08870198eb864bPetr Machata 3866a7997de9eabf9b0c6e32309ca08870198eb864bPetr Machatastatic int 3876a7997de9eabf9b0c6e32309ca08870198eb864bPetr Machatafetch_rd64(struct Process *proc, target_address_t addr, 3886a7997de9eabf9b0c6e32309ca08870198eb864bPetr Machata struct lt_r_debug_64 *ret) 3896a7997de9eabf9b0c6e32309ca08870198eb864bPetr Machata{ 3906a7997de9eabf9b0c6e32309ca08870198eb864bPetr Machata if (umovebytes(proc, addr, ret, sizeof(*ret)) != sizeof(*ret)) 3916a7997de9eabf9b0c6e32309ca08870198eb864bPetr Machata return -1; 3926a7997de9eabf9b0c6e32309ca08870198eb864bPetr Machata return 0; 3936a7997de9eabf9b0c6e32309ca08870198eb864bPetr Machata} 3946a7997de9eabf9b0c6e32309ca08870198eb864bPetr Machata 3956a7997de9eabf9b0c6e32309ca08870198eb864bPetr Machatastatic int 3966a7997de9eabf9b0c6e32309ca08870198eb864bPetr Machatafetch_rd32(struct Process *proc, target_address_t addr, 3976a7997de9eabf9b0c6e32309ca08870198eb864bPetr Machata struct lt_r_debug_64 *ret) 3986a7997de9eabf9b0c6e32309ca08870198eb864bPetr Machata{ 3996a7997de9eabf9b0c6e32309ca08870198eb864bPetr Machata struct lt_r_debug_32 rd; 4006a7997de9eabf9b0c6e32309ca08870198eb864bPetr Machata if (umovebytes(proc, addr, &rd, sizeof(rd)) != sizeof(rd)) 4016a7997de9eabf9b0c6e32309ca08870198eb864bPetr Machata return -1; 4026a7997de9eabf9b0c6e32309ca08870198eb864bPetr Machata 4036a7997de9eabf9b0c6e32309ca08870198eb864bPetr Machata ret->r_version = rd.r_version; 4046a7997de9eabf9b0c6e32309ca08870198eb864bPetr Machata ret->r_map = rd.r_map; 4056a7997de9eabf9b0c6e32309ca08870198eb864bPetr Machata ret->r_brk = rd.r_brk; 4066a7997de9eabf9b0c6e32309ca08870198eb864bPetr Machata ret->r_state = rd.r_state; 4076a7997de9eabf9b0c6e32309ca08870198eb864bPetr Machata ret->r_ldbase = rd.r_ldbase; 4086a7997de9eabf9b0c6e32309ca08870198eb864bPetr Machata 4096a7997de9eabf9b0c6e32309ca08870198eb864bPetr Machata return 0; 4106a7997de9eabf9b0c6e32309ca08870198eb864bPetr Machata} 4116a7997de9eabf9b0c6e32309ca08870198eb864bPetr Machata 4126a7997de9eabf9b0c6e32309ca08870198eb864bPetr Machatastatic int (* 4136a7997de9eabf9b0c6e32309ca08870198eb864bPetr Machatardebug_fetcher(struct Process *proc))(struct Process *, 4146a7997de9eabf9b0c6e32309ca08870198eb864bPetr Machata target_address_t, struct lt_r_debug_64 *) 4156a7997de9eabf9b0c6e32309ca08870198eb864bPetr Machata{ 4166a7997de9eabf9b0c6e32309ca08870198eb864bPetr Machata return select_32_64(proc, fetch_rd32, fetch_rd64); 41747cae1e251a212425cae5ac6e736de0cb0bbf714Joe Damato} 418f0bd98b3e6753d8609a3054a61f2df6f9cdac10aJoe Damato 419f0bd98b3e6753d8609a3054a61f2df6f9cdac10aJoe Damatostatic void 4206a7997de9eabf9b0c6e32309ca08870198eb864bPetr Machatacrawl_linkmap(struct Process *proc, struct lt_r_debug_64 *dbg) 4212b46cfc1127d390eddd9593fe5ce5399c1f68130Petr Machata{ 422f0bd98b3e6753d8609a3054a61f2df6f9cdac10aJoe Damato debug (DEBUG_FUNCTION, "crawl_linkmap()"); 423f0bd98b3e6753d8609a3054a61f2df6f9cdac10aJoe Damato 424f0bd98b3e6753d8609a3054a61f2df6f9cdac10aJoe Damato if (!dbg || !dbg->r_map) { 425f0bd98b3e6753d8609a3054a61f2df6f9cdac10aJoe Damato debug(2, "Debug structure or it's linkmap are NULL!"); 426f0bd98b3e6753d8609a3054a61f2df6f9cdac10aJoe Damato return; 427f0bd98b3e6753d8609a3054a61f2df6f9cdac10aJoe Damato } 428f0bd98b3e6753d8609a3054a61f2df6f9cdac10aJoe Damato 4296a7997de9eabf9b0c6e32309ca08870198eb864bPetr Machata target_address_t addr = (target_address_t)dbg->r_map; 430f0bd98b3e6753d8609a3054a61f2df6f9cdac10aJoe Damato 4316a7997de9eabf9b0c6e32309ca08870198eb864bPetr Machata while (addr != 0) { 4326a7997de9eabf9b0c6e32309ca08870198eb864bPetr Machata struct lt_link_map_64 rlm; 4336a7997de9eabf9b0c6e32309ca08870198eb864bPetr Machata if (lm_fetcher(proc)(proc, addr, &rlm) < 0) { 43474d80544c9ad0b1c5ff94dda639e12ddf1d2ca1cPetr Machata debug(2, "Unable to read link map"); 435f0bd98b3e6753d8609a3054a61f2df6f9cdac10aJoe Damato return; 436f0bd98b3e6753d8609a3054a61f2df6f9cdac10aJoe Damato } 437f0bd98b3e6753d8609a3054a61f2df6f9cdac10aJoe Damato 43889ac0395a9e018f4d4dbda9d3e27159419a92da2Petr Machata target_address_t key = addr; 4396a7997de9eabf9b0c6e32309ca08870198eb864bPetr Machata addr = (target_address_t)rlm.l_next; 4406a7997de9eabf9b0c6e32309ca08870198eb864bPetr Machata if (rlm.l_name == 0) { 44174d80544c9ad0b1c5ff94dda639e12ddf1d2ca1cPetr Machata debug(2, "Name of mapped library is NULL"); 442f0bd98b3e6753d8609a3054a61f2df6f9cdac10aJoe Damato return; 443f0bd98b3e6753d8609a3054a61f2df6f9cdac10aJoe Damato } 444f0bd98b3e6753d8609a3054a61f2df6f9cdac10aJoe Damato 4456a7997de9eabf9b0c6e32309ca08870198eb864bPetr Machata char lib_name[BUFSIZ]; 4466a7997de9eabf9b0c6e32309ca08870198eb864bPetr Machata umovebytes(proc, (target_address_t)rlm.l_name, 4476a7997de9eabf9b0c6e32309ca08870198eb864bPetr Machata lib_name, sizeof(lib_name)); 448f0bd98b3e6753d8609a3054a61f2df6f9cdac10aJoe Damato 4492b46cfc1127d390eddd9593fe5ce5399c1f68130Petr Machata if (*lib_name == '\0') { 4502b46cfc1127d390eddd9593fe5ce5399c1f68130Petr Machata /* VDSO. No associated file, XXX but we might 4512b46cfc1127d390eddd9593fe5ce5399c1f68130Petr Machata * load it from the address space of the 4522b46cfc1127d390eddd9593fe5ce5399c1f68130Petr Machata * process. */ 453f0bd98b3e6753d8609a3054a61f2df6f9cdac10aJoe Damato continue; 454f0bd98b3e6753d8609a3054a61f2df6f9cdac10aJoe Damato } 455f0bd98b3e6753d8609a3054a61f2df6f9cdac10aJoe Damato 45689ac0395a9e018f4d4dbda9d3e27159419a92da2Petr Machata /* Do we have that library already? */ 45789ac0395a9e018f4d4dbda9d3e27159419a92da2Petr Machata if (proc_each_library(proc, NULL, library_with_key_cb, &key)) 45889ac0395a9e018f4d4dbda9d3e27159419a92da2Petr Machata continue; 45989ac0395a9e018f4d4dbda9d3e27159419a92da2Petr Machata 46089ac0395a9e018f4d4dbda9d3e27159419a92da2Petr Machata fprintf(stderr, "DSO addr=%#lx, name='%s'\n", 46189ac0395a9e018f4d4dbda9d3e27159419a92da2Petr Machata rlm.l_addr, lib_name); 462b5f80ac8982c40f79915ce1e1cb9bf8650ac5fe7Petr Machata 463b5f80ac8982c40f79915ce1e1cb9bf8650ac5fe7Petr Machata struct library *lib = malloc(sizeof(*lib)); 4642b46cfc1127d390eddd9593fe5ce5399c1f68130Petr Machata if (lib == NULL) { 465b5f80ac8982c40f79915ce1e1cb9bf8650ac5fe7Petr Machata fail: 466b5f80ac8982c40f79915ce1e1cb9bf8650ac5fe7Petr Machata if (lib != NULL) 467b5f80ac8982c40f79915ce1e1cb9bf8650ac5fe7Petr Machata library_destroy(lib); 4682b46cfc1127d390eddd9593fe5ce5399c1f68130Petr Machata error(0, errno, "Couldn't load ELF object %s\n", 4692b46cfc1127d390eddd9593fe5ce5399c1f68130Petr Machata lib_name); 4702b46cfc1127d390eddd9593fe5ce5399c1f68130Petr Machata continue; 471f0bd98b3e6753d8609a3054a61f2df6f9cdac10aJoe Damato } 472b5f80ac8982c40f79915ce1e1cb9bf8650ac5fe7Petr Machata library_init(lib, LT_LIBTYPE_DSO); 473b5f80ac8982c40f79915ce1e1cb9bf8650ac5fe7Petr Machata 474b5f80ac8982c40f79915ce1e1cb9bf8650ac5fe7Petr Machata if (ltelf_read_library(lib, proc, lib_name, rlm.l_addr) < 0) 475b5f80ac8982c40f79915ce1e1cb9bf8650ac5fe7Petr Machata goto fail; 476b5f80ac8982c40f79915ce1e1cb9bf8650ac5fe7Petr Machata 47789ac0395a9e018f4d4dbda9d3e27159419a92da2Petr Machata lib->key = key; 4782b46cfc1127d390eddd9593fe5ce5399c1f68130Petr Machata proc_add_library(proc, lib); 479f0bd98b3e6753d8609a3054a61f2df6f9cdac10aJoe Damato } 480f0bd98b3e6753d8609a3054a61f2df6f9cdac10aJoe Damato return; 481f0bd98b3e6753d8609a3054a61f2df6f9cdac10aJoe Damato} 482f0bd98b3e6753d8609a3054a61f2df6f9cdac10aJoe Damato 483029171fffcf6328768866cf510763b2eb927f1bdPetr Machata/* A struct stored at proc->debug. */ 484029171fffcf6328768866cf510763b2eb927f1bdPetr Machatastruct debug_struct 485029171fffcf6328768866cf510763b2eb927f1bdPetr Machata{ 486029171fffcf6328768866cf510763b2eb927f1bdPetr Machata target_address_t debug_addr; 487029171fffcf6328768866cf510763b2eb927f1bdPetr Machata int state; 488029171fffcf6328768866cf510763b2eb927f1bdPetr Machata}; 489029171fffcf6328768866cf510763b2eb927f1bdPetr Machata 4906a7997de9eabf9b0c6e32309ca08870198eb864bPetr Machatastatic int 4916a7997de9eabf9b0c6e32309ca08870198eb864bPetr Machataload_debug_struct(struct Process *proc, struct lt_r_debug_64 *ret) 4926a7997de9eabf9b0c6e32309ca08870198eb864bPetr Machata{ 493f0bd98b3e6753d8609a3054a61f2df6f9cdac10aJoe Damato debug(DEBUG_FUNCTION, "load_debug_struct"); 494f0bd98b3e6753d8609a3054a61f2df6f9cdac10aJoe Damato 495029171fffcf6328768866cf510763b2eb927f1bdPetr Machata struct debug_struct *debug = proc->debug; 496029171fffcf6328768866cf510763b2eb927f1bdPetr Machata 497029171fffcf6328768866cf510763b2eb927f1bdPetr Machata if (rdebug_fetcher(proc)(proc, debug->debug_addr, ret) < 0) { 498f0bd98b3e6753d8609a3054a61f2df6f9cdac10aJoe Damato debug(2, "This process does not have a debug structure!\n"); 4996a7997de9eabf9b0c6e32309ca08870198eb864bPetr Machata return -1; 500f0bd98b3e6753d8609a3054a61f2df6f9cdac10aJoe Damato } 501f0bd98b3e6753d8609a3054a61f2df6f9cdac10aJoe Damato 5026a7997de9eabf9b0c6e32309ca08870198eb864bPetr Machata return 0; 503f0bd98b3e6753d8609a3054a61f2df6f9cdac10aJoe Damato} 504f0bd98b3e6753d8609a3054a61f2df6f9cdac10aJoe Damato 505f0bd98b3e6753d8609a3054a61f2df6f9cdac10aJoe Damatostatic void 50612affff3c88731a0880690442485494e540f7a58Petr Machatardebug_bp_on_hit(struct breakpoint *bp, struct Process *proc) 5072b46cfc1127d390eddd9593fe5ce5399c1f68130Petr Machata{ 5082b46cfc1127d390eddd9593fe5ce5399c1f68130Petr Machata fprintf(stderr, "======= HIT\n"); 509f0bd98b3e6753d8609a3054a61f2df6f9cdac10aJoe Damato 510f0bd98b3e6753d8609a3054a61f2df6f9cdac10aJoe Damato debug(DEBUG_FUNCTION, "arch_check_dbg"); 511f0bd98b3e6753d8609a3054a61f2df6f9cdac10aJoe Damato 5126a7997de9eabf9b0c6e32309ca08870198eb864bPetr Machata struct lt_r_debug_64 rdbg; 5136a7997de9eabf9b0c6e32309ca08870198eb864bPetr Machata if (load_debug_struct(proc, &rdbg) < 0) { 514f0bd98b3e6753d8609a3054a61f2df6f9cdac10aJoe Damato debug(2, "Unable to load debug structure!"); 515f0bd98b3e6753d8609a3054a61f2df6f9cdac10aJoe Damato return; 516f0bd98b3e6753d8609a3054a61f2df6f9cdac10aJoe Damato } 517f0bd98b3e6753d8609a3054a61f2df6f9cdac10aJoe Damato 518029171fffcf6328768866cf510763b2eb927f1bdPetr Machata struct debug_struct *debug = proc->debug; 5196a7997de9eabf9b0c6e32309ca08870198eb864bPetr Machata if (rdbg.r_state == RT_CONSISTENT) { 520f0bd98b3e6753d8609a3054a61f2df6f9cdac10aJoe Damato debug(2, "Linkmap is now consistent"); 521029171fffcf6328768866cf510763b2eb927f1bdPetr Machata if (debug->state == RT_ADD) { 522f0bd98b3e6753d8609a3054a61f2df6f9cdac10aJoe Damato debug(2, "Adding DSO to linkmap"); 5232b46cfc1127d390eddd9593fe5ce5399c1f68130Petr Machata //data.proc = proc; 5246a7997de9eabf9b0c6e32309ca08870198eb864bPetr Machata crawl_linkmap(proc, &rdbg); 5252b46cfc1127d390eddd9593fe5ce5399c1f68130Petr Machata //&data); 526029171fffcf6328768866cf510763b2eb927f1bdPetr Machata } else if (debug->state == RT_DELETE) { 527f0bd98b3e6753d8609a3054a61f2df6f9cdac10aJoe Damato debug(2, "Removing DSO from linkmap"); 528f0bd98b3e6753d8609a3054a61f2df6f9cdac10aJoe Damato } else { 529f0bd98b3e6753d8609a3054a61f2df6f9cdac10aJoe Damato debug(2, "Unexpected debug state!"); 530f0bd98b3e6753d8609a3054a61f2df6f9cdac10aJoe Damato } 531f0bd98b3e6753d8609a3054a61f2df6f9cdac10aJoe Damato } 532f0bd98b3e6753d8609a3054a61f2df6f9cdac10aJoe Damato 533029171fffcf6328768866cf510763b2eb927f1bdPetr Machata debug->state = rdbg.r_state; 534f0bd98b3e6753d8609a3054a61f2df6f9cdac10aJoe Damato} 535f0bd98b3e6753d8609a3054a61f2df6f9cdac10aJoe Damato 536f0bd98b3e6753d8609a3054a61f2df6f9cdac10aJoe Damatoint 53752dbfb161efeab85bddc880966db2f7af9b9cf9aPetr Machatalinkmap_init(struct Process *proc, target_address_t dyn_addr) 5382b46cfc1127d390eddd9593fe5ce5399c1f68130Petr Machata{ 5392b46cfc1127d390eddd9593fe5ce5399c1f68130Petr Machata //struct cb_data data; 540f0bd98b3e6753d8609a3054a61f2df6f9cdac10aJoe Damato 541f0bd98b3e6753d8609a3054a61f2df6f9cdac10aJoe Damato debug(DEBUG_FUNCTION, "linkmap_init()"); 5422b46cfc1127d390eddd9593fe5ce5399c1f68130Petr Machata fprintf(stderr, "linkmap_init dyn_addr=%p\n", dyn_addr); 543f0bd98b3e6753d8609a3054a61f2df6f9cdac10aJoe Damato 544029171fffcf6328768866cf510763b2eb927f1bdPetr Machata struct debug_struct *debug = malloc(sizeof(*debug)); 545029171fffcf6328768866cf510763b2eb927f1bdPetr Machata if (debug == NULL) { 546029171fffcf6328768866cf510763b2eb927f1bdPetr Machata error(0, errno, "couldn't allocate debug struct"); 54789ac0395a9e018f4d4dbda9d3e27159419a92da2Petr Machata fail: 548029171fffcf6328768866cf510763b2eb927f1bdPetr Machata proc->debug = NULL; 549029171fffcf6328768866cf510763b2eb927f1bdPetr Machata free(debug); 550f0bd98b3e6753d8609a3054a61f2df6f9cdac10aJoe Damato return -1; 551f0bd98b3e6753d8609a3054a61f2df6f9cdac10aJoe Damato } 552029171fffcf6328768866cf510763b2eb927f1bdPetr Machata proc->debug = debug; 553f0bd98b3e6753d8609a3054a61f2df6f9cdac10aJoe Damato 554029171fffcf6328768866cf510763b2eb927f1bdPetr Machata if (find_dynamic_entry_addr(proc, dyn_addr, DT_DEBUG, 555029171fffcf6328768866cf510763b2eb927f1bdPetr Machata &debug->debug_addr) == -1) { 556029171fffcf6328768866cf510763b2eb927f1bdPetr Machata debug(2, "Couldn't find debug structure!"); 557029171fffcf6328768866cf510763b2eb927f1bdPetr Machata goto fail; 558029171fffcf6328768866cf510763b2eb927f1bdPetr Machata } 559f0bd98b3e6753d8609a3054a61f2df6f9cdac10aJoe Damato 5606a7997de9eabf9b0c6e32309ca08870198eb864bPetr Machata int status; 5616a7997de9eabf9b0c6e32309ca08870198eb864bPetr Machata struct lt_r_debug_64 rdbg; 5626a7997de9eabf9b0c6e32309ca08870198eb864bPetr Machata if ((status = load_debug_struct(proc, &rdbg)) < 0) { 563f0bd98b3e6753d8609a3054a61f2df6f9cdac10aJoe Damato debug(2, "No debug structure or no memory to allocate one!"); 5646a7997de9eabf9b0c6e32309ca08870198eb864bPetr Machata return status; 565f0bd98b3e6753d8609a3054a61f2df6f9cdac10aJoe Damato } 566f0bd98b3e6753d8609a3054a61f2df6f9cdac10aJoe Damato 5672b46cfc1127d390eddd9593fe5ce5399c1f68130Petr Machata //data.lte = lte; 568f0bd98b3e6753d8609a3054a61f2df6f9cdac10aJoe Damato 56989ac0395a9e018f4d4dbda9d3e27159419a92da2Petr Machata target_address_t addr = (target_address_t)rdbg.r_brk; 57089ac0395a9e018f4d4dbda9d3e27159419a92da2Petr Machata if (arch_translate_address(proc, addr, &addr) < 0) 57189ac0395a9e018f4d4dbda9d3e27159419a92da2Petr Machata goto fail; 57289ac0395a9e018f4d4dbda9d3e27159419a92da2Petr Machata fprintf(stderr, " r_brk=%p\n", addr); 57389ac0395a9e018f4d4dbda9d3e27159419a92da2Petr Machata 5749df15016447915a61526af8cb81c588913bcf44cPetr Machata struct breakpoint *rdebug_bp = insert_breakpoint(proc, addr, NULL); 5752b46cfc1127d390eddd9593fe5ce5399c1f68130Petr Machata static struct bp_callbacks rdebug_callbacks = { 57612affff3c88731a0880690442485494e540f7a58Petr Machata .on_hit = rdebug_bp_on_hit, 5772b46cfc1127d390eddd9593fe5ce5399c1f68130Petr Machata }; 5782b46cfc1127d390eddd9593fe5ce5399c1f68130Petr Machata rdebug_bp->cbs = &rdebug_callbacks; 579f0bd98b3e6753d8609a3054a61f2df6f9cdac10aJoe Damato 5806a7997de9eabf9b0c6e32309ca08870198eb864bPetr Machata crawl_linkmap(proc, &rdbg); 581f0bd98b3e6753d8609a3054a61f2df6f9cdac10aJoe Damato 582f0bd98b3e6753d8609a3054a61f2df6f9cdac10aJoe Damato return 0; 583f0bd98b3e6753d8609a3054a61f2df6f9cdac10aJoe Damato} 5849a5420c82a2fd81681572a2e3859ea1671c3bdedPetr Machata 5859a5420c82a2fd81681572a2e3859ea1671c3bdedPetr Machataint 5869a5420c82a2fd81681572a2e3859ea1671c3bdedPetr Machatatask_kill (pid_t pid, int sig) 5879a5420c82a2fd81681572a2e3859ea1671c3bdedPetr Machata{ 5889a5420c82a2fd81681572a2e3859ea1671c3bdedPetr Machata // Taken from GDB 5899a5420c82a2fd81681572a2e3859ea1671c3bdedPetr Machata int ret; 5909a5420c82a2fd81681572a2e3859ea1671c3bdedPetr Machata 5919a5420c82a2fd81681572a2e3859ea1671c3bdedPetr Machata errno = 0; 5929a5420c82a2fd81681572a2e3859ea1671c3bdedPetr Machata ret = syscall (__NR_tkill, pid, sig); 5939a5420c82a2fd81681572a2e3859ea1671c3bdedPetr Machata return ret; 5949a5420c82a2fd81681572a2e3859ea1671c3bdedPetr Machata} 595