PageRenderTime 70ms CodeModel.GetById 15ms RepoModel.GetById 2ms app.codeStats 0ms

/tags/ttn-post-libtool-1-4-3-upgrade/SWIG/Tools/WAD/Wad/stack.c

#
C | 309 lines | 197 code | 44 blank | 68 comment | 31 complexity | 4e36e060514f630331bda078b92c87d1 MD5 | raw file
Possible License(s): LGPL-2.1, Cube, GPL-3.0, 0BSD, GPL-2.0
  1. /* -----------------------------------------------------------------------------
  2. * stack.c
  3. *
  4. * This file unwinds the C call stack and creates a list of stack frames.
  5. *
  6. * Author(s) : David Beazley (beazley@cs.uchicago.edu)
  7. *
  8. * Copyright (C) 2000. The University of Chicago.
  9. *
  10. * This library is free software; you can redistribute it and/or
  11. * modify it under the terms of the GNU Lesser General Public
  12. * License as published by the Free Software Foundation; either
  13. * version 2.1 of the License, or (at your option) any later version.
  14. *
  15. * This library is distributed in the hope that it will be useful,
  16. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  17. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  18. * Lesser General Public License for more details.
  19. *
  20. * You should have received a copy of the GNU Lesser General Public
  21. * License along with this library; if not, write to the Free Software
  22. * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  23. *
  24. * See the file COPYING for a complete copy of the LGPL.
  25. * ----------------------------------------------------------------------------- */
  26. #include "wad.h"
  27. static char cvs[] = "$Header$";
  28. /* -----------------------------------------------------------------------------
  29. * new_frame()
  30. *
  31. * Create a new stack frame object and initialize all of the fields.
  32. * ----------------------------------------------------------------------------- */
  33. static WadFrame *
  34. new_frame() {
  35. WadFrame *f;
  36. f = (WadFrame *) wad_malloc(sizeof(WadFrame));
  37. f->frameno = 0;
  38. f->segment = 0;
  39. f->object = 0;
  40. f->pc = 0;
  41. f->sp = 0;
  42. f->sp = 0;
  43. f->stack = 0;
  44. f->stack_size = 0;
  45. f->sym_name = 0;
  46. f->sym_nlen = 0;
  47. f->sym_file = 0;
  48. f->sym_base = 0;
  49. f->sym_size = 0;
  50. f->sym_type = 0;
  51. f->sym_bind = 0;
  52. f->loc_objfile = 0;
  53. f->loc_srcfile = 0;
  54. f->loc_line = 0;
  55. f->debug_check = 0;
  56. f->debug_nargs = -1;
  57. f->debug_args = 0;
  58. f->debug_lastarg = 0;
  59. f->debug_nlocals = 0;
  60. f->debug_locals = 0;
  61. f->debug_lastlocal = 0;
  62. f->debug_str = 0;
  63. f->debug_srcstr = 0;
  64. f->last = 0;
  65. f->next = 0;
  66. f->prev = 0;
  67. return f;
  68. }
  69. /* -----------------------------------------------------------------------------
  70. * stack_unwind()
  71. *
  72. * This function performs a single level of stack unwinding given the stack pointer
  73. * frame pointer and program counter. Validations are made to make sure the stack
  74. * and frame pointers are in valid memory. Updates the values of the sp, pc, and fp
  75. * in-place. Returns a stack frame object on success, 0 if memory is invalid
  76. * or the end of the stack has been reached.
  77. * ----------------------------------------------------------------------------- */
  78. static WadFrame *
  79. stack_unwind(unsigned long *pc, unsigned long *sp, unsigned long *fp) {
  80. WadSegment *sp_seg, *fp_seg;
  81. WadFrame *f;
  82. unsigned long fake_fp;
  83. if (wad_debug_mode & DEBUG_UNWIND) {
  84. wad_printf("::: stack unwind : pc = %x, sp = %x, fp = %x\n", *pc, *sp, *fp);
  85. }
  86. /* Verify that the sp and fp are in mapped memory */
  87. sp_seg = wad_segment_find((void *) *sp);
  88. fp_seg = wad_segment_find((void *) *fp);
  89. /* Make sure the stack pointer is in memory */
  90. if (!sp_seg) {
  91. return 0;
  92. }
  93. if (!fp_seg) {
  94. /* Hmmm. If no frame pointer, we must be off the top of the call stack */
  95. fake_fp = (unsigned long) (sp_seg->vaddr + sp_seg->size);
  96. fp_seg = sp_seg;
  97. } else {
  98. fake_fp = *fp;
  99. }
  100. if (sp_seg != fp_seg) {
  101. /* Whoa. Stack pointer and frame pointer are in different memory segments. */
  102. wad_printf("WAD: Warning. Stack pointer and frame pointer are in different regions.\n");
  103. return 0;
  104. }
  105. /* Check to see if the PC is valid */
  106. if (!wad_segment_valid((void *) *pc)) {
  107. return 0;
  108. }
  109. f = new_frame();
  110. f->pc = *pc;
  111. f->sp = *sp;
  112. f->fp = fake_fp;
  113. f->segment = wad_segment_find((void *) *pc);
  114. f->stack_size = fake_fp - *sp;
  115. /* Make a copy of the call stack */
  116. f->stack = (char *) wad_malloc(f->stack_size);
  117. wad_memcpy(f->stack,(void *) *sp, f->stack_size);
  118. /* Update the sp, fp, and pc */
  119. #ifdef WAD_SOLARIS
  120. *pc = *((unsigned long *) *sp+15); /* %i7 - Return address */
  121. *sp = *((unsigned long *) *sp+14); /* %i6 - frame pointer */
  122. if (wad_segment_valid((void *) *sp)) {
  123. *fp = *((unsigned long *) *sp+14);
  124. } else {
  125. *fp = 0;
  126. }
  127. #endif
  128. #ifdef WAD_LINUX
  129. if (wad_segment_valid((void *) ((unsigned long *) *fp+1))) {
  130. *pc = *((unsigned long *) *fp+1);
  131. *sp = *fp;
  132. } else {
  133. *sp = 0;
  134. }
  135. if (wad_segment_valid((void *) ((unsigned long *) *fp))) {
  136. *fp = *((unsigned long *) *fp);
  137. } else {
  138. *fp = 0;
  139. }
  140. #endif
  141. return f;
  142. }
  143. /* -----------------------------------------------------------------------------
  144. * wad_stack_trace()
  145. *
  146. * Create a stack trace of the process. Returns a linked list of stack frames
  147. * with a limited about debugging information and other details.
  148. * ----------------------------------------------------------------------------- */
  149. WadFrame *
  150. wad_stack_trace(unsigned long pc, unsigned long sp, unsigned long fp) {
  151. WadFrame *firstframe=0, *lastframe=0, *frame=0;
  152. unsigned long p_pc;
  153. unsigned long p_sp;
  154. unsigned long p_fp;
  155. int n = 0;
  156. /* Try to do a stack traceback */
  157. p_pc = pc;
  158. p_sp = sp;
  159. p_fp = fp;
  160. while ((frame = stack_unwind(&p_pc, &p_sp, &p_fp))) {
  161. /* Got a frame successfully */
  162. frame->frameno = n;
  163. if (lastframe) {
  164. lastframe->next = frame;
  165. frame->prev = lastframe;
  166. lastframe = frame;
  167. } else {
  168. firstframe = frame;
  169. lastframe = frame;
  170. }
  171. n++;
  172. }
  173. if (lastframe)
  174. lastframe->last = 1;
  175. return firstframe;
  176. }
  177. /* -----------------------------------------------------------------------------
  178. * wad_stack_debug()
  179. *
  180. * Make a dump of a stack trace
  181. * ----------------------------------------------------------------------------- */
  182. void wad_stack_debug(WadFrame *frame) {
  183. if (wad_debug_mode & DEBUG_STACK) {
  184. /* Walk the exception frames and try to find a return point */
  185. while (frame) {
  186. /* Print out detailed stack trace information */
  187. wad_printf("::: Stack frame - 0x%08x :::\n", frame);
  188. wad_printf(" pc = %x\n", frame->pc);
  189. wad_printf(" sp = %x\n", frame->sp);
  190. wad_printf(" fp = %x\n", frame->fp);
  191. wad_printf(" stack = %x\n", frame->stack);
  192. wad_printf(" size = %x\n", frame->stack_size);
  193. wad_printf(" segment = %x (%s)\n", frame->segment, frame->segment ? frame->segment->mappath : "?");
  194. wad_printf(" object = %x (%s)\n", frame->object, frame->object ? frame->object->path : "?");
  195. if (frame->sym_name) {
  196. wad_printf(" sym_name = %s\n", frame->sym_name);
  197. wad_printf(" sym_base = %x\n", frame->sym_base);
  198. wad_printf(" sym_size = %x\n", frame->sym_size);
  199. wad_printf(" sym_bind = %x\n", frame->sym_bind);
  200. wad_printf(" sym_file = %s\n", frame->sym_file ? frame->sym_file : "");
  201. }
  202. if (frame->loc_srcfile) {
  203. wad_printf(" loc_srcfile = %s\n", frame->loc_srcfile);
  204. }
  205. if (frame->loc_objfile) {
  206. wad_printf(" loc_objfile = %s\n", frame->loc_objfile);
  207. }
  208. wad_printf(" loc_line = %d\n", frame->loc_line);
  209. wad_printf(" debug_nargs = %d\n", frame->debug_nargs);
  210. if (frame->debug_args) {
  211. int i = 0;
  212. WadLocal *p = frame->debug_args;
  213. wad_printf(" debug_args = [ \n");
  214. while (p) {
  215. wad_printf(" arg[%d] : name = '%s', loc = %d, type = %d, stack = %d, reg = %d, line=%d, ptr=%x(%d)\n", i, p->name, p->loc, p->type, p->stack,p->reg,p->line,p->ptr,p->size);
  216. p = p->next;
  217. }
  218. }
  219. wad_printf(" ]\n");
  220. wad_printf(" debug_nlocal = %d\n", frame->debug_nlocals);
  221. if (frame->debug_locals) {
  222. int i = 0;
  223. WadLocal *p = frame->debug_locals;
  224. wad_printf(" debug_locals = [ \n");
  225. while (p) {
  226. wad_printf(" loc[%d] : name = '%s', loc = %d, type = %d, stack = %d, reg = %d, line=%d, ptr=%x(%d)\n", i, p->name, p->loc, p->type, p->stack,p->reg,p->line,p->ptr,p->size);
  227. p = p->next;
  228. }
  229. }
  230. wad_printf(" ]\n");
  231. frame = frame->next;
  232. }
  233. }
  234. }
  235. /* -----------------------------------------------------------------------------
  236. * wad_steal_outarg()
  237. *
  238. * Steal an output argument
  239. * ----------------------------------------------------------------------------- */
  240. long
  241. wad_steal_outarg(WadFrame *f, char *symbol, int argno, int *error) {
  242. long *regs;
  243. WadFrame *lastf = 0;
  244. *error = 0;
  245. /* Start searching */
  246. while (f) {
  247. if (f->sym_name && (strcmp(f->sym_name,symbol) == 0)) {
  248. /* Got a match */
  249. if (lastf) {
  250. #ifdef WAD_SOLARIS
  251. regs = (long *) lastf->stack;
  252. return regs[8+argno];
  253. #endif
  254. #ifdef WAD_LINUX
  255. regs = (long *) f->stack;
  256. return regs[argno+2];
  257. #endif
  258. }
  259. }
  260. lastf = f;
  261. f = f->next;
  262. }
  263. *error = -1;
  264. return 0;
  265. }