heap_symShow.c 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320
  1. /*
  2. * heap_symShow.c - convert addresses to line number and function name
  3. */
  4. #include <string.h>
  5. #include <stdlib.h>
  6. #include <stdio.h>
  7. #include "../private.h"
  8. #include "../context.h"
  9. #undef lub_heap_init /* defined for cygwin builds */
  10. #ifdef HAVE_CONFIG_H
  11. #include "config.h"
  12. #endif /* HAVE_CONFIG_H */
  13. extern void sysheap_suppress_leak_detection(void);
  14. extern void sysheap_restore_leak_detection(void);
  15. #if defined(__CYGWIN__)
  16. /*---------------------------------------------------------
  17. * under CYGWIN we have the nasty behaviour that
  18. * argv[0] is the program name without the .exe extension
  19. * which is needed to load the symbol table; hence this
  20. * crufty hack *8-)
  21. *--------------------------------------------------------- */
  22. void
  23. cygwin_lub_heap_init(const char *file_name)
  24. {
  25. char buffer[80];
  26. sprintf(buffer,"%s.exe",file_name);
  27. lub_heap_init(buffer);
  28. }
  29. /*--------------------------------------------------------- */
  30. #endif /* __CYGWIN__ */
  31. #ifndef HAVE_LIBBFD
  32. /*--------------------------------------------------------- */
  33. /*
  34. * Simple vanilla dump of symbols address
  35. * This is automatically used unless GPL support has been
  36. * configured.
  37. */
  38. void
  39. lub_heap_symShow(unsigned address)
  40. {
  41. printf(" 0x%08x",address);
  42. }
  43. /*--------------------------------------------------------- */
  44. bool_t
  45. lub_heap_symMatch(unsigned address,
  46. const char *substring)
  47. {
  48. return BOOL_TRUE;
  49. }
  50. /*--------------------------------------------------------- */
  51. /*
  52. * dummy initialisation call
  53. */
  54. void
  55. lub_heap_init(const char *file_name)
  56. {
  57. file_name = file_name;
  58. lub_heap__set_framecount(MAX_BACKTRACE);
  59. }
  60. /*--------------------------------------------------------- */
  61. #else /* HAVE_LIBBFD */
  62. /*
  63. This file is part of the CLISH project http://clish.sourceforge.net/
  64. The code in this file is free software; you can redistribute it and/or modify
  65. it under the terms of the GNU General Public License as published by
  66. the Free Software Foundation; version 2
  67. This code is distributed in the hope that it will be useful,
  68. but WITHOUT ANY WARRANTY; without even the implied warranty of
  69. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  70. GNU General Public License for more details.
  71. You should have received a copy of the GNU General Public License
  72. along with this program; if not, write to the Free Software
  73. Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  74. Derived from addr2line.c in the GNU binutils package by Ulrich.Lauther@mchp.siemens.de
  75. */
  76. #include "bfd.h"
  77. /*--------------------------------------------------------- */
  78. /* These global variables are used to pass information between
  79. translate_addresses and find_address_in_section. */
  80. /*--------------------------------------------------------- */
  81. typedef struct
  82. {
  83. bfd_vma pc;
  84. asymbol **syms;
  85. const char *file_name;
  86. const char *fn_name;
  87. unsigned int line_num;
  88. bfd_boolean found;
  89. } info_t;
  90. /*--------------------------------------------------------- */
  91. typedef struct
  92. {
  93. bfd *abfd;
  94. asymbol **syms; /* Symbol table. */
  95. } lub_heap_posix_t;
  96. /*--------------------------------------------------------- */
  97. static lub_heap_posix_t my_instance; /* instance of this class */
  98. /*--------------------------------------------------------- */
  99. /* Look for an address in a section. This is called via
  100. bfd_map_over_sections. */
  101. /*--------------------------------------------------------- */
  102. static void
  103. find_address_in_section (bfd *abfd,
  104. asection *section,
  105. void *data)
  106. {
  107. info_t *info = data;
  108. bfd_vma vma;
  109. bfd_size_type size;
  110. if (info->found)
  111. return;
  112. if ((bfd_get_section_flags (abfd, section) & SEC_ALLOC) == 0)
  113. return;
  114. vma = bfd_get_section_vma (abfd, section);
  115. if (info->pc < vma)
  116. return;
  117. size = bfd_get_section_size (section);
  118. if (info->pc >= vma + size)
  119. return;
  120. info->found = bfd_find_nearest_line (abfd,
  121. section,
  122. info->syms,
  123. info->pc - vma,
  124. &info->file_name,
  125. &info->fn_name,
  126. &info->line_num);
  127. if(!info->line_num || !info->file_name)
  128. {
  129. info->found = 0;
  130. }
  131. if(info->found)
  132. {
  133. const char *last_file_name;
  134. const char *last_fn_name;
  135. unsigned last_line_num;
  136. bfd_find_nearest_line (abfd,
  137. section,
  138. info->syms,
  139. vma + size - 1,
  140. &last_file_name,
  141. &last_fn_name,
  142. &last_line_num);
  143. if( (last_file_name == info->file_name)
  144. && (last_fn_name == info->fn_name )
  145. && (last_line_num == info->line_num))
  146. {
  147. info->found = FALSE;
  148. }
  149. }
  150. if(info->found)
  151. {
  152. /* strip to the basename */
  153. char *p;
  154. p = strrchr (info->file_name, '/');
  155. if (NULL != p)
  156. {
  157. info->file_name = p + 1;
  158. }
  159. }
  160. }
  161. /*--------------------------------------------------------- */
  162. static void
  163. lub_heap_posix_fini(void)
  164. {
  165. lub_heap_posix_t *this = &my_instance;
  166. if (this->syms != NULL)
  167. {
  168. free (this->syms);
  169. this->syms = NULL;
  170. }
  171. if(this->abfd)
  172. {
  173. bfd_close (this->abfd);
  174. }
  175. }
  176. /*--------------------------------------------------------- */
  177. void
  178. lub_heap_init(const char *file_name)
  179. {
  180. lub_heap_posix_t *this = &my_instance;
  181. /* remember to cleanup */
  182. atexit(lub_heap_posix_fini);
  183. /* switch on leak detection */
  184. lub_heap__set_framecount(MAX_BACKTRACE);
  185. sysheap_suppress_leak_detection();
  186. bfd_init ();
  187. this->syms = NULL;
  188. this->abfd = bfd_openr (file_name, "pe-i386");
  189. if (this->abfd)
  190. {
  191. if(bfd_check_format_matches (this->abfd, bfd_object,NULL))
  192. {
  193. unsigned int size;
  194. long symcount = 0;
  195. if (!(bfd_get_file_flags (this->abfd) & HAS_SYMS) == 0)
  196. {
  197. /* Read in the symbol table. */
  198. symcount = bfd_read_minisymbols (this->abfd,
  199. FALSE,
  200. (void*)&this->syms,
  201. &size);
  202. if(0 == symcount)
  203. {
  204. /* try reading dynamic symbols */
  205. symcount = bfd_read_minisymbols (this->abfd,
  206. TRUE /* dynamic */,
  207. (void*)&this->syms,
  208. &size);
  209. }
  210. }
  211. if(0 == symcount)
  212. {
  213. fprintf(stderr,"*** no symbols found in '%s'\n",bfd_get_filename(this->abfd));
  214. }
  215. }
  216. }
  217. sysheap_restore_leak_detection();
  218. }
  219. /*--------------------------------------------------------- */
  220. static void
  221. _lub_heap_symGetInfo(lub_heap_posix_t *this,
  222. unsigned address,
  223. info_t *info)
  224. {
  225. info->pc = address;
  226. info->syms = this->syms;
  227. info->fn_name = NULL;
  228. info->file_name = NULL;
  229. info->line_num = 0;
  230. info->found = FALSE;
  231. sysheap_suppress_leak_detection();
  232. if(NULL != this->abfd)
  233. {
  234. bfd_map_over_sections (this->abfd,
  235. find_address_in_section,
  236. info);
  237. }
  238. sysheap_restore_leak_detection();
  239. }
  240. /*--------------------------------------------------------- */
  241. void
  242. lub_heap_symShow(unsigned address)
  243. {
  244. lub_heap_posix_t *this = &my_instance;
  245. info_t info;
  246. _lub_heap_symGetInfo(this,address,&info);
  247. if(!info.found)
  248. {
  249. if(this->abfd && this->syms)
  250. {
  251. /* a line with the function names */
  252. printf("%26s","");
  253. }
  254. printf(" 0x%08x",address);
  255. if(!this->abfd)
  256. {
  257. /* aline with the function names */
  258. printf(" - lub_heap_init() not called.");
  259. }
  260. }
  261. else
  262. {
  263. printf(" %20s:%-4d",info.file_name,info.line_num);
  264. printf(" %s()",info.fn_name);
  265. }
  266. }
  267. /*--------------------------------------------------------- */
  268. bool_t
  269. lub_heap_symMatch(unsigned address,
  270. const char *substring)
  271. {
  272. lub_heap_posix_t *this = &my_instance;
  273. info_t info;
  274. bool_t result = BOOL_FALSE;
  275. _lub_heap_symGetInfo(this,address,&info);
  276. if(info.found)
  277. {
  278. if(strstr(info.fn_name,substring))
  279. {
  280. result = TRUE;
  281. }
  282. }
  283. return result;
  284. }
  285. /*--------------------------------------------------------- */
  286. #endif /* HAVE_LIBBFD */