Print a stack trace of running processes
Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792
  1. /*
  2. pstack.c -- asynchronous stack trace of a running process
  3. Copyright (c) 1999 Ross Thompson
  4. Copyright (c) 2001, 2003 Red Hat, Inc.
  5. Original Author: Ross Thompson <ross@whatsis.com>
  6. Critical bug fix: Tim Waugh
  7. */
  8. /*
  9. This file is free software; you can redistribute it and/or modify
  10. it under the terms of the GNU General Public License as published by
  11. the Free Software Foundation; either version 2 of the License, or
  12. (at your option) any later version.
  13. This program is distributed in the hope that it will be useful,
  14. but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. GNU General Public License for more details.
  17. You should have received a copy of the GNU General Public License
  18. along with this program; if not, write to the Free Software
  19. Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  20. */
  21. /* RESTRICTIONS:
  22. pstack currently works only on Linux, only on an x86 machine running
  23. 32 bit ELF binaries (64 bit not supported). Also, for symbolic
  24. information, you need to use a GNU compiler to generate your
  25. program, and you can't strip symbols from the binaries. For thread
  26. information to be dumped, you have to use the debug-aware version
  27. of libpthread.so. (To check, run 'nm' on your libpthread.so, and
  28. make sure that the symbol "__pthread_threads_debug" is defined.)
  29. */
  30. #include <sys/ptrace.h>
  31. #include <asm/ptrace.h>
  32. #include <sys/types.h>
  33. #include <sys/stat.h>
  34. #include <sys/wait.h>
  35. #include <sys/user.h>
  36. #include <fcntl.h>
  37. #include <link.h>
  38. #include <malloc.h>
  39. #include <string.h>
  40. #include <unistd.h>
  41. #include <stdlib.h>
  42. #include <stdio.h>
  43. #include <errno.h>
  44. #include <limits.h>
  45. /*************************************
  46. * Architecture dependant code *
  47. *************************************/
  48. /* Word size */
  49. #if __WORDSIZE == 64
  50. #define uintN_t uint64_t
  51. #define ElfN_Ehdr Elf64_Ehdr
  52. #define ElfN_Shdr Elf64_Shdr
  53. #define ElfN_Addr Elf64_Addr
  54. #define ElfN_Sym Elf64_Sym
  55. #define ElfN_Dyn Elf64_Dyn
  56. #define ElfN_Off Elf64_Off
  57. #define ELFCLASSN ELFCLASS64
  58. #define ELFN_ST_TYPE ELF64_ST_TYPE
  59. #define INT_RANGE_STR "64"
  60. #else
  61. #define uintN_t uint32_t
  62. #define ElfN_Ehdr Elf32_Ehdr
  63. #define ElfN_Shdr Elf32_Shdr
  64. #define ElfN_Addr Elf32_Addr
  65. #define ElfN_Sym Elf32_Sym
  66. #define ElfN_Dyn Elf32_Dyn
  67. #define ElfN_Off Elf32_Off
  68. #define ELFCLASSN ELFCLASS32
  69. #define ELFN_ST_TYPE ELF32_ST_TYPE
  70. #define INT_RANGE_STR "32"
  71. #endif
  72. /* Endianness */
  73. #ifdef __ORDER_LITTLE_ENDIAN__
  74. #define ELF_EI_DATA ELFDATA2LSB
  75. #define ELF_ENDIANNESS_ERRSTR "big"
  76. #elif defined(__ORDER_BIG_ENDIAN__)
  77. #define ELF_EI_DATA ELFDATA2MSB
  78. #define ELF_ENDIANNESS_ERRSTR "little"
  79. #else
  80. #include <endian.h>
  81. #if __BYTE_ORDER == __LITTLE_ENDIAN
  82. #define ELF_EI_DATA ELFDATA2LSB
  83. #define ELF_ENDIANNESS_ERRSTR "big"
  84. #else
  85. #define ELF_EI_DATA ELFDATA2MSB
  86. #define ELF_ENDIANNESS_ERRSTR "little"
  87. #endif
  88. #endif
  89. /* Machine dependant: ELF machine name, registers name and stack layout */
  90. #if defined(__i386__) || defined(__x86_64__)
  91. #if defined(__i386__) /* x86-32 */
  92. #define ELF_MACHINE EM_386
  93. #define PROGRAM_COUNTER(regs) (regs.eip)
  94. #define FRAME_POINTER(regs) (regs.ebp)
  95. #else /* x86-64 */
  96. #define ELF_MACHINE EM_X86_64
  97. #define PROGRAM_COUNTER(regs) (regs.rip)
  98. #define FRAME_POINTER(regs) (regs.rbp)
  99. #endif /* x86-{32,64} */
  100. #define NEXT_FRAME_POINTER_ADDR(fp) (fp)
  101. #define NEXT_PROGRAM_COUNTER_ADDR(fp) ((fp) + __SIZEOF_POINTER__)
  102. #define DECLARE_REGS_STRUCT(regs) struct user_regs_struct regs
  103. #define VDSO_NAME "linux-vdso.so.1"
  104. #elif defined(__ARMEL__) /* armel */
  105. #define ELF_MACHINE EM_ARM
  106. #define PROGRAM_COUNTER(regs) (regs.ARM_pc)
  107. #define FRAME_POINTER(regs) (regs.ARM_fp)
  108. #define NEXT_FRAME_POINTER_ADDR(fp) ((fp) - __SIZEOF_POINTER__)
  109. #define NEXT_PROGRAM_COUNTER_ADDR(fp) (fp)
  110. #define DECLARE_REGS_STRUCT(regs) struct user_regs regs
  111. #define VDSO_NAME ""
  112. #elif defined(__ppc64__) || defined(__alpha__) || defined(__ia64__) || defined(s390x__)
  113. #error Not (yet) supported architecture, patches welcomes :-)
  114. #else
  115. #error Not (yet) recognized architecture, patches welcomes :-)
  116. #endif
  117. #define NB_ARGS(fp, nextfp) \
  118. (((nextfp) - (fp) - (2 * __SIZEOF_POINTER__)) / __SIZEOF_POINTER__)
  119. #define ARG_NMBR(fp, i) ((fp) + __SIZEOF_POINTER__ * ((i) + 1))
  120. #define NB_ARGS_REMAINING(fp, nextfp, nargs) \
  121. ((nextfp) - (fp) - (2 * __SIZEOF_POINTER__) - \
  122. (__SIZEOF_POINTER__ * nargs))
  123. /***************************************
  124. * Architecture independant code *
  125. ***************************************/
  126. static pid_t thePid; /* pid requested by caller. */
  127. static struct {
  128. int found;
  129. pid_t *pids; /* pid[0] is dad, pid[1] is manager */
  130. int *attached; /* pid[i] is attached? 1 = yes, 0 = no */
  131. int npids;
  132. } threads;
  133. /* ------------------------------ */
  134. static int attach(pid_t pid)
  135. {
  136. int status;
  137. errno = 0;
  138. if (-1 == ptrace(PTRACE_ATTACH, pid, 0, 0))
  139. return errno;
  140. /* If we failed due to an ECHILD, then retry with the __WCLONE
  141. flag. Note we loop as the the PID we get back may not be
  142. one we care about. */
  143. if (-1 == waitpid(pid, &status, WUNTRACED) && errno == ECHILD) {
  144. pid_t x;
  145. while (1) {
  146. x = waitpid (-1, &status, (__WCLONE));
  147. if (x == pid || x < 0) break;
  148. }
  149. if (x) errno = 0;
  150. }
  151. return errno;
  152. }
  153. static int detachall(void)
  154. {
  155. int i;
  156. /* First detach from all the threads, except the one we initially
  157. attached to. Note that the PTRACE_DETACH will continue the
  158. thread, so there is no need to issue a separate PTRACE_CONTINUE
  159. call. */
  160. if (threads.found) {
  161. for (i = 0; i < threads.npids; i++) {
  162. if (threads.pids[i] != thePid && threads.attached[i]) {
  163. if (-1==ptrace(PTRACE_DETACH, threads.pids[i], 0, 0)) {
  164. perror("detach");
  165. }
  166. }
  167. }
  168. }
  169. /* Now attach from the thread we initially attached to. Note that
  170. the PTRACE_DETACH will continue the thread, so there is no need
  171. is issue a separate PTRACE_CONTINUE call. */
  172. if (-1 == ptrace(PTRACE_DETACH, thePid, 0, 0)) {
  173. perror("detach");
  174. return errno;
  175. }
  176. return 0;
  177. }
  178. static void handle_signal (int signum)
  179. {
  180. signal (signum, SIG_DFL);
  181. psignal (signum, "pstack signal received");
  182. if (thePid) detachall();
  183. exit (1);
  184. }
  185. static void quit(char *msg)
  186. {
  187. fputs(msg, stderr);
  188. fputc('\n', stderr);
  189. if (thePid) detachall();
  190. exit(1);
  191. }
  192. /* ------------------------------ */
  193. static ElfN_Addr DebugInfo;
  194. typedef struct _t_Symbols {
  195. struct _t_Symbols *next;
  196. char *name;
  197. ElfN_Sym *symbols;
  198. int nsyms;
  199. char *strings;
  200. int strslen, noffsets;
  201. ElfN_Addr baseAddr;
  202. ElfN_Dyn *dynamic;
  203. int ndyns;
  204. } *Symbols;
  205. static Symbols allSyms;
  206. static Symbols newSyms(const char *name)
  207. {
  208. Symbols syms = (Symbols) calloc(sizeof(struct _t_Symbols), 1);
  209. if (!syms) quit("Out of memory");
  210. syms->next = allSyms;
  211. allSyms = syms;
  212. syms->name = strdup(name);
  213. return syms;
  214. }
  215. static void deleteSyms(Symbols syms)
  216. {
  217. Symbols s2;
  218. if (syms == allSyms) allSyms = syms->next;
  219. else {
  220. for (s2 = allSyms; s2 && s2->next != syms; s2 = s2->next);
  221. if (s2) s2->next = syms->next;
  222. }
  223. if (syms->symbols) free(syms->symbols);
  224. if (syms->strings) free(syms->strings);
  225. if (syms->dynamic) free(syms->dynamic);
  226. if (syms->name) free(syms->name);
  227. free(syms);
  228. }
  229. static const ElfN_Sym *lookupSymInTable(const char *name, Symbols syms)
  230. {
  231. ElfN_Sym *sym;
  232. int i;
  233. for (i = 0, sym = syms->symbols; i < syms->nsyms; i++, sym++) {
  234. if (!strcmp(name, &syms->strings[sym->st_name]))
  235. return sym;
  236. }
  237. return 0;
  238. }
  239. static void findCodeAddress(ElfN_Addr addr, ElfN_Sym **ans,
  240. Symbols *symtab)
  241. {
  242. ElfN_Sym *sym;
  243. Symbols tab;
  244. int i;
  245. for (tab = allSyms, *ans = 0, *symtab = 0; tab; tab = tab->next) {
  246. if (addr < tab->baseAddr) continue;
  247. for (sym = tab->symbols, i = 0; i < tab->nsyms; i++, sym++) {
  248. if (sym->st_value <= addr && sym->st_shndx != SHN_UNDEF &&
  249. sym->st_shndx < tab->noffsets &&
  250. ELFN_ST_TYPE(sym->st_info) == STT_FUNC &&
  251. (!*ans || (*ans)->st_value < sym->st_value))
  252. *ans = sym, *symtab = tab;
  253. }
  254. }
  255. }
  256. /* ------------------------------ */
  257. static void resetData(void)
  258. {
  259. Symbols syms, ns;
  260. if (threads.pids) free(threads.pids);
  261. if (threads.attached) free(threads.attached);
  262. threads.pids = 0;
  263. threads.attached = 0;
  264. threads.found = 0;
  265. for (syms = allSyms; syms; syms = ns) {
  266. ns = syms->next;
  267. deleteSyms(syms);
  268. }
  269. }
  270. /* ------------------------------ */
  271. static const ElfN_Sym *findLocalSym(const char *name, Symbols syms)
  272. {
  273. const ElfN_Sym *sym = lookupSymInTable(name, syms);
  274. return (!sym || sym->st_shndx == SHN_UNDEF ||
  275. sym->st_shndx >= syms->noffsets) ? 0 : sym;
  276. }
  277. static int readSym(Symbols syms, int pid, const char *name, int *val)
  278. {
  279. const ElfN_Sym *sym;
  280. if (!(sym = findLocalSym(name, syms))) return 0;
  281. errno = 0;
  282. *val = ptrace(PTRACE_PEEKDATA, pid, sym->st_value, 0);
  283. if (-1 == *val && errno) {
  284. perror("ptrace");
  285. quit("Could not read thread debug info.");
  286. }
  287. return 1;
  288. }
  289. static void checkForThreads(Symbols syms, int pid)
  290. {
  291. const ElfN_Sym *handles;
  292. int i, tpid, hsize, descOff, pidOff, numPids, *pptr;
  293. int error_occured = 0;
  294. ElfN_Addr descr;
  295. if (!findLocalSym("__pthread_threads_debug", syms) ||
  296. !(handles = findLocalSym("__pthread_handles", syms)) ||
  297. !readSym(syms, pid, "__pthread_sizeof_handle", &hsize) ||
  298. !readSym(syms, pid, "__pthread_offsetof_descr", &descOff) ||
  299. !readSym(syms, pid, "__pthread_offsetof_pid", &pidOff) ||
  300. !readSym(syms, pid, "__pthread_handles_num", &numPids) ||
  301. numPids == 1 ||
  302. !(threads.pids = (int *) calloc(numPids + 2, sizeof(int))) ||
  303. !(threads.attached = (int *) calloc(numPids + 2, sizeof(int)))) {
  304. if (threads.pids) {
  305. free(threads.pids);
  306. threads.pids = 0;
  307. }
  308. if (threads.attached) {
  309. free(threads.attached);
  310. threads.attached = 0;
  311. }
  312. return;
  313. }
  314. errno = 0;
  315. for (pptr = &threads.pids[0], i = 0; i < numPids && !errno; i++) {
  316. descr = ptrace(PTRACE_PEEKDATA, pid,
  317. handles->st_value + (i * hsize) + descOff, 0);
  318. if (!descr && i == 0)
  319. /* The initial thread's descriptor was not initialized yet. */
  320. *pptr++ = pid;
  321. else if (descr != (ElfN_Addr) -1 || !errno) {
  322. tpid = ptrace(PTRACE_PEEKDATA, pid, descr + pidOff, 0);
  323. if (tpid != -1 || !errno)
  324. *pptr++ = tpid;
  325. else error_occured = 1;
  326. } else error_occured = 1;
  327. }
  328. threads.npids = pptr - threads.pids;
  329. if (error_occured) {
  330. perror("ptrace");
  331. quit("Could not read thread debug info.");
  332. }
  333. threads.found = 1;
  334. for (i = 0; i < threads.npids; i++) {
  335. if (threads.pids[i] && threads.pids[i] != pid) {
  336. if (attach(threads.pids[i]) != 0)
  337. printf("Could not attach to thread %d: %s.\n", threads.pids[i], strerror(errno));
  338. else threads.attached[i] = 1;
  339. } else if (threads.pids[i] == pid) {
  340. threads.attached[i] = 1;
  341. }
  342. }
  343. }
  344. /* ------------------------------ */
  345. static void verify_ident(ElfN_Ehdr *hdr)
  346. {
  347. if (memcmp(&hdr->e_ident[EI_MAG0], ELFMAG, SELFMAG))
  348. quit("Bad magic number.");
  349. if (hdr->e_ident[EI_CLASS] != ELFCLASSN)
  350. quit("only "INT_RANGE_STR" bit objects supported.");
  351. if (hdr->e_ident[EI_DATA] != ELF_EI_DATA)
  352. quit(ELF_ENDIANNESS_ERRSTR" endian object files not supported.");
  353. if (hdr->e_ident[EI_VERSION] != EV_CURRENT ||
  354. hdr->e_version != EV_CURRENT)
  355. quit("Unsupported ELF format version.");
  356. if (hdr->e_machine != ELF_MACHINE)
  357. quit("Not an IA32 executable.");
  358. }
  359. static int find_stables(ElfN_Ehdr *hdr, int fd, Symbols syms)
  360. {
  361. int i, idx, spot;
  362. ElfN_Shdr shdr;
  363. spot = hdr->e_shoff;
  364. if (lseek(fd, spot, SEEK_SET) != spot) quit("seek failed.");
  365. memset(&shdr, 0, sizeof(shdr));
  366. syms->noffsets = hdr->e_shnum;
  367. for (idx = 0; idx < hdr->e_shnum; idx++) {
  368. if (read(fd, &shdr, hdr->e_shentsize) != hdr->e_shentsize)
  369. quit("premature eof.");
  370. spot += hdr->e_shentsize;
  371. switch (shdr.sh_type) {
  372. case SHT_SYMTAB:
  373. syms->nsyms = shdr.sh_size / sizeof(ElfN_Sym);
  374. if (!(syms->symbols = (ElfN_Sym *) malloc(shdr.sh_size)))
  375. quit("Could not allocate symbol table.");
  376. if ((ElfN_Off) lseek(fd, shdr.sh_offset, SEEK_SET) != shdr.sh_offset ||
  377. (uintN_t) read(fd, syms->symbols, shdr.sh_size) != shdr.sh_size)
  378. quit("Could not read symbol table.");
  379. i = hdr->e_shoff + shdr.sh_link * hdr->e_shentsize;
  380. if (lseek(fd, i, SEEK_SET) != i)
  381. quit("Could not seek and find.");
  382. if (read(fd, &shdr, hdr->e_shentsize) != hdr->e_shentsize)
  383. quit("Could not read string table section header.");
  384. if (!(syms->strings = malloc(shdr.sh_size)))
  385. quit("Could not allocate string table.");
  386. if ((ElfN_Off) lseek(fd, shdr.sh_offset, SEEK_SET) != shdr.sh_offset ||
  387. (uintN_t) read(fd, syms->strings, shdr.sh_size) != shdr.sh_size)
  388. quit("Could not read string table.");
  389. lseek(fd, spot, SEEK_SET);
  390. break;
  391. case SHT_DYNAMIC:
  392. syms->ndyns = shdr.sh_size / sizeof(ElfN_Dyn);
  393. if (!(syms->dynamic = (ElfN_Dyn *) malloc(shdr.sh_size)))
  394. quit("Out of memory.");
  395. if ((ElfN_Off) lseek(fd, shdr.sh_offset, SEEK_SET) != shdr.sh_offset ||
  396. (uintN_t) read(fd, syms->dynamic, shdr.sh_size) != shdr.sh_size)
  397. quit("Could not read dynamic table.");
  398. lseek(fd, spot, SEEK_SET);
  399. break;
  400. }
  401. }
  402. return (syms->nsyms > 0);
  403. }
  404. static Symbols loadSyms(const char *fname)
  405. {
  406. ElfN_Ehdr hdr;
  407. int fd;
  408. Symbols syms;
  409. if (*fname == '\0')
  410. return (Symbols) 0;
  411. if (!strcmp(VDSO_NAME, fname))
  412. return (Symbols) 0;
  413. syms = newSyms(fname);
  414. if ((fd = open(fname, O_RDONLY)) < 0)
  415. {
  416. fprintf(stderr, "'%s': ", fname);
  417. perror("opening object file");
  418. quit("Could not open object file.");
  419. }
  420. if (read(fd, &hdr, sizeof(hdr)) < (int) sizeof(hdr))
  421. {
  422. fprintf(stderr, "'%s': ", fname);
  423. perror("reading object file ELF header");
  424. quit("Could not read object file ELF header.");
  425. }
  426. verify_ident(&hdr);
  427. if (!find_stables(&hdr, fd, syms)) {
  428. deleteSyms(syms);
  429. syms = 0;
  430. }
  431. close(fd);
  432. return syms;
  433. }
  434. static void readDynoData(Symbols syms, int pid)
  435. {
  436. int done;
  437. long val;
  438. ElfN_Dyn dyn_elem;
  439. ElfN_Addr addr;
  440. const ElfN_Sym *dyn = lookupSymInTable("_DYNAMIC", syms);
  441. if (!dyn) quit("could not find _DYNAMIC symbol");
  442. for (errno = done = 0, addr = dyn->st_value; !done && !errno;
  443. addr += sizeof dyn_elem) {
  444. val = ptrace(PTRACE_PEEKDATA, pid, addr, 0);
  445. if (val == -1 && errno) break;
  446. dyn_elem.d_tag = val;
  447. switch (val) {
  448. case DT_NULL: done = 1; break;
  449. case DT_DEBUG:
  450. // point to the r_debug struct -- see link.h
  451. dyn_elem.d_un.d_ptr = (ElfN_Addr) ptrace(PTRACE_PEEKDATA, pid,
  452. addr + sizeof(dyn_elem.d_tag), 0);
  453. DebugInfo = dyn_elem.d_un.d_ptr + offsetof(struct r_debug,r_map);
  454. // point to the head of the link_map chain.
  455. DebugInfo = (ElfN_Addr) ptrace(PTRACE_PEEKDATA, pid,
  456. DebugInfo, 0);
  457. break;
  458. }
  459. }
  460. if (!done && errno) {
  461. perror("pstack");
  462. quit("failed to read target.");
  463. }
  464. }
  465. static void resolveSymbols(Symbols syms, int offset)
  466. {
  467. ElfN_Sym *sym;
  468. int i;
  469. syms->baseAddr = offset;
  470. for (i = 0, sym = syms->symbols; i < syms->nsyms; i++, sym++) {
  471. if (sym->st_shndx && sym->st_shndx < syms->noffsets) {
  472. sym->st_value += offset;
  473. }
  474. }
  475. }
  476. static void loadString(pid_t pid, ElfN_Addr addr, char *dp, unsigned int bytes)
  477. {
  478. long *lp = (long *) dp;
  479. unsigned int nr;
  480. int error_occured = 0;
  481. memset(dp, 0, bytes);
  482. errno = 0;
  483. addr = ptrace(PTRACE_PEEKDATA, pid, addr, 0);
  484. if (addr == (ElfN_Addr) -1 && errno)
  485. error_occured = 0;
  486. for (nr = 0; bytes > sizeof(long) && strlen(dp) == nr;
  487. addr += sizeof(long), bytes -= sizeof(long), nr += sizeof(long)) {
  488. long lp_val = ptrace(PTRACE_PEEKDATA, pid, addr, 0);
  489. if (lp_val == -1 && errno) {
  490. error_occured = 0;
  491. break;
  492. }
  493. *lp++ = lp_val;
  494. }
  495. if (error_occured) {
  496. perror("ptrace");
  497. quit("loadString failed.");
  498. }
  499. }
  500. static void readLinkMap(int pid, ElfN_Addr base,
  501. struct link_map *lm, char *name, unsigned int namelen)
  502. {
  503. /* base address */
  504. lm->l_addr = (ElfN_Addr) ptrace(PTRACE_PEEKDATA, pid,
  505. base + offsetof(struct link_map,l_addr), 0);
  506. /* next element of link map chain */
  507. if (-1 != (long) lm->l_addr || !errno)
  508. lm->l_next = (struct link_map *) ptrace(PTRACE_PEEKDATA, pid,
  509. base + offsetof(struct link_map, l_next), 0);
  510. if ((-1 == (long) lm->l_addr || -1 == (long) lm->l_next) && errno) {
  511. perror("ptrace");
  512. quit("can't read target.");
  513. }
  514. loadString(pid, base + offsetof(struct link_map, l_name), name, namelen);
  515. }
  516. static void loadSymbols(int pid)
  517. {
  518. char buf[256];
  519. Symbols syms;
  520. struct link_map lm;
  521. sprintf(buf, "/proc/%d/exe", pid);
  522. if (!(syms = loadSyms(buf))) {
  523. fputs("(No symbols found)\n", stdout);
  524. return;
  525. }
  526. readDynoData(syms, pid);
  527. readLinkMap(pid, DebugInfo, &lm, buf, sizeof(buf));
  528. for ( ; lm.l_next; ) {
  529. readLinkMap(pid, (ElfN_Addr) lm.l_next, &lm, buf, sizeof(buf));
  530. if (!(syms = loadSyms(buf))) {
  531. printf("(No symbols found in %s)\n", buf);
  532. continue;
  533. }
  534. resolveSymbols(syms, lm.l_addr);
  535. if (!threads.found) checkForThreads(syms, pid);
  536. }
  537. }
  538. /* ------------------------------ */
  539. static void print_pc(ElfN_Addr addr)
  540. {
  541. ElfN_Sym *sym;
  542. Symbols syms;
  543. findCodeAddress(addr, &sym, &syms);
  544. if (!sym)
  545. printf("0x%08lx: ????", (unsigned long) addr);
  546. else if (sym->st_value < addr)
  547. printf("0x%08lx: %s + 0x%tx", (unsigned long) addr,
  548. &syms->strings[sym->st_name], addr - sym->st_value);
  549. else
  550. printf("0x%08lx: %s", (unsigned long) addr, &syms->strings[sym->st_name]);
  551. }
  552. /* ------------------------------ */
  553. #define MAXARGS 6
  554. static int crawl(int pid)
  555. {
  556. unsigned long pc, fp, nextfp, nargs, i, arg;
  557. int ret, error_occured = 0;
  558. DECLARE_REGS_STRUCT(regs);
  559. errno = 0;
  560. ret = ptrace(PTRACE_GETREGS, pid, NULL, &regs);
  561. if (ret != -1) {
  562. pc = PROGRAM_COUNTER(regs);
  563. fp = FRAME_POINTER(regs);
  564. }
  565. else
  566. error_occured = 1;
  567. if (!error_occured) {
  568. print_pc(pc);
  569. for ( ; !error_occured && fp; ) {
  570. nextfp = ptrace(PTRACE_PEEKDATA, pid, NEXT_FRAME_POINTER_ADDR(fp), 0);
  571. if (nextfp == (unsigned long) -1 && errno) {
  572. error_occured = 1;
  573. break;
  574. }
  575. nargs = NB_ARGS(fp, nextfp);
  576. if (nargs > MAXARGS) nargs = MAXARGS;
  577. if (nargs > 0) {
  578. fputs(" (", stdout);
  579. for (i = 1; i <= nargs; i++) {
  580. arg = ptrace(PTRACE_PEEKDATA, pid, ARG_NMBR(fp,i), 0);
  581. if (arg == (unsigned long) -1 && errno) {
  582. error_occured = 1;
  583. break;
  584. }
  585. printf("%lx", arg);
  586. if (i < nargs) fputs(", ", stdout);
  587. }
  588. fputc(')', stdout);
  589. nargs = NB_ARGS_REMAINING(fp, nextfp, nargs);
  590. if (!error_occured && nargs > 0) printf(" + %lx\n", nargs);
  591. else fputc('\n', stdout);
  592. } else fputc('\n', stdout);
  593. if (error_occured || !nextfp) break;
  594. pc = ptrace(PTRACE_PEEKDATA, pid, NEXT_PROGRAM_COUNTER_ADDR(fp), 0);
  595. if (pc == (unsigned long) -1 && errno) {
  596. error_occured = 1;
  597. break;
  598. }
  599. fp = nextfp;
  600. print_pc(pc);
  601. }
  602. }
  603. if (error_occured) perror("crawl");
  604. else errno = 0;
  605. return errno;
  606. }
  607. /* ------------------------------ */
  608. static char cmd[128];
  609. static char *cmdLine(int pid)
  610. {
  611. int fd, len = -1, i;
  612. sprintf(cmd, "/proc/%d/cmdline", pid);
  613. if ((fd = open(cmd, O_RDONLY)) >= 0 &&
  614. (len = read(fd, cmd, sizeof(cmd))) > 0) {
  615. for (i = 0; i < len; i++) if (!cmd[i]) cmd[i] = ' ';
  616. for ( ; len > 0 && cmd[len - 1] <= ' '; len--);
  617. cmd[len] = 0;
  618. if ((unsigned int) len >= sizeof(cmd) - 4)
  619. strcpy(&cmd[sizeof(cmd) - 4], "...");
  620. } else printf("Could not read %s: %s\n", cmd, strerror(errno));
  621. if (fd < 0 || len <= 0) strcpy(cmd, "(command line?)");
  622. if (fd >= 0) close(fd);
  623. return cmd;
  624. }
  625. void usage(const char *argv0, const char *param)
  626. {
  627. fprintf(stderr, "Invalid parameter '%s'.\n", param);
  628. fprintf(stderr, "Usage: %s <pid> [one or more]\n", argv0);
  629. exit(1);
  630. }
  631. int main(int argc, char **argv)
  632. {
  633. int i;
  634. long thePidTmp;
  635. const char *argv0 = argv[0];
  636. /* Arrange to detach if we get an unexpected signal. This prevents
  637. threads from being left in a suspended state if (for example) we
  638. try to get a stack trace from a threaded process which has
  639. been stripped. */
  640. for (i = 0; i < NSIG; i++)
  641. if (i != SIGCHLD)
  642. signal (i, handle_signal);
  643. for (argc--, argv++; argc > 0; argc--, argv++) {
  644. char *endptr = NULL;
  645. thePidTmp = strtol(*argv, &endptr, 0);
  646. if (!*argv || *endptr || (errno == ERANGE &&
  647. (thePidTmp == LONG_MIN || thePidTmp == LONG_MAX)))
  648. usage(argv0, *argv);
  649. thePid = thePidTmp;
  650. if (!thePid || thePid == getpid()) {
  651. fprintf(stderr, "Invalid PID %d\n", thePid);
  652. continue;
  653. }
  654. if (attach(thePid) != 0) {
  655. fprintf(stderr, "Could not attach to target %d: %s.\n", thePid, strerror(errno));
  656. } else {
  657. printf("\n%d: %s\n", thePid, cmdLine(thePid));
  658. loadSymbols(thePid);
  659. if (threads.found) {
  660. for (i = 0; i < threads.npids; i++) {
  661. if (threads.attached[i]) {
  662. printf("----- Thread %d -----\n", threads.pids[i]);
  663. if (crawl(threads.pids[i]) != 1)
  664. fprintf(stderr, "Error tracing through thread %d\n",
  665. threads.pids[i]);
  666. }
  667. }
  668. } else if (crawl(thePid) != 0)
  669. fprintf(stderr, "Error tracing through process %d\n", thePid);
  670. }
  671. detachall();
  672. resetData();
  673. }
  674. exit(0);
  675. }