heap_symShow.c 7.4 KB

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