123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320 |
- /*
- * heap_symShow.c - convert addresses to line number and function name
- */
- #include <string.h>
- #include <stdlib.h>
- #include <stdio.h>
- #include "../private.h"
- #include "../context.h"
- #undef lub_heap_init /* defined for cygwin builds */
- #ifdef HAVE_CONFIG_H
- #include "config.h"
- #endif /* HAVE_CONFIG_H */
- extern void sysheap_suppress_leak_detection(void);
- extern void sysheap_restore_leak_detection(void);
- #if defined(__CYGWIN__)
- /*---------------------------------------------------------
- * under CYGWIN we have the nasty behaviour that
- * argv[0] is the program name without the .exe extension
- * which is needed to load the symbol table; hence this
- * crufty hack *8-)
- *--------------------------------------------------------- */
- void
- cygwin_lub_heap_init(const char *file_name)
- {
- char buffer[80];
- sprintf(buffer,"%s.exe",file_name);
- lub_heap_init(buffer);
- }
- /*--------------------------------------------------------- */
- #endif /* __CYGWIN__ */
- #ifndef HAVE_LIBBFD
- /*--------------------------------------------------------- */
- /*
- * Simple vanilla dump of symbols address
- * This is automatically used unless GPL support has been
- * configured.
- */
- void
- lub_heap_symShow(unsigned address)
- {
- printf(" 0x%08x",address);
- }
- /*--------------------------------------------------------- */
- bool_t
- lub_heap_symMatch(unsigned address,
- const char *substring)
- {
- return BOOL_TRUE;
- }
- /*--------------------------------------------------------- */
- /*
- * dummy initialisation call
- */
- void
- lub_heap_init(const char *file_name)
- {
- file_name = file_name;
- lub_heap__set_framecount(MAX_BACKTRACE);
- }
- /*--------------------------------------------------------- */
- #else /* HAVE_LIBBFD */
- /*
- This file is part of the CLISH project http://clish.sourceforge.net/
- The code in this file is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; version 2
-
- This code is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- Derived from addr2line.c in the GNU binutils package by Ulrich.Lauther@mchp.siemens.de
- */
- #include "bfd.h"
- /*--------------------------------------------------------- */
- /* These global variables are used to pass information between
- translate_addresses and find_address_in_section. */
- /*--------------------------------------------------------- */
- typedef struct
- {
- bfd_vma pc;
- asymbol **syms;
- const char *file_name;
- const char *fn_name;
- unsigned int line_num;
- bfd_boolean found;
- } info_t;
- /*--------------------------------------------------------- */
- typedef struct
- {
- bfd *abfd;
- asymbol **syms; /* Symbol table. */
- } lub_heap_posix_t;
- /*--------------------------------------------------------- */
- static lub_heap_posix_t my_instance; /* instance of this class */
- /*--------------------------------------------------------- */
- /* Look for an address in a section. This is called via
- bfd_map_over_sections. */
- /*--------------------------------------------------------- */
- static void
- find_address_in_section (bfd *abfd,
- asection *section,
- void *data)
- {
- info_t *info = data;
- bfd_vma vma;
- bfd_size_type size;
- if (info->found)
- return;
- if ((bfd_get_section_flags (abfd, section) & SEC_ALLOC) == 0)
- return;
- vma = bfd_get_section_vma (abfd, section);
- if (info->pc < vma)
- return;
- size = bfd_get_section_size (section);
- if (info->pc >= vma + size)
- return;
- info->found = bfd_find_nearest_line (abfd,
- section,
- info->syms,
- info->pc - vma,
- &info->file_name,
- &info->fn_name,
- &info->line_num);
- if(!info->line_num || !info->file_name)
- {
- info->found = 0;
- }
- if(info->found)
- {
- const char *last_file_name;
- const char *last_fn_name;
- unsigned last_line_num;
-
- bfd_find_nearest_line (abfd,
- section,
- info->syms,
- vma + size - 1,
- &last_file_name,
- &last_fn_name,
- &last_line_num);
- if( (last_file_name == info->file_name)
- && (last_fn_name == info->fn_name )
- && (last_line_num == info->line_num))
- {
- info->found = FALSE;
- }
- }
- if(info->found)
- {
- /* strip to the basename */
- char *p;
- p = strrchr (info->file_name, '/');
- if (NULL != p)
- {
- info->file_name = p + 1;
- }
- }
- }
- /*--------------------------------------------------------- */
- static void
- lub_heap_posix_fini(void)
- {
- lub_heap_posix_t *this = &my_instance;
- if (this->syms != NULL)
- {
- free (this->syms);
- this->syms = NULL;
- }
- if(this->abfd)
- {
- bfd_close (this->abfd);
- }
- }
- /*--------------------------------------------------------- */
- void
- lub_heap_init(const char *file_name)
- {
- lub_heap_posix_t *this = &my_instance;
- /* remember to cleanup */
- atexit(lub_heap_posix_fini);
-
- /* switch on leak detection */
- lub_heap__set_framecount(MAX_BACKTRACE);
- sysheap_suppress_leak_detection();
- bfd_init ();
-
- this->syms = NULL;
- this->abfd = bfd_openr (file_name, "pe-i386");
- if (this->abfd)
- {
- if(bfd_check_format_matches (this->abfd, bfd_object,NULL))
- {
- unsigned int size;
- long symcount = 0;
-
- if (!(bfd_get_file_flags (this->abfd) & HAS_SYMS) == 0)
- {
- /* Read in the symbol table. */
- symcount = bfd_read_minisymbols (this->abfd,
- FALSE,
- (void*)&this->syms,
- &size);
- if(0 == symcount)
- {
- /* try reading dynamic symbols */
- symcount = bfd_read_minisymbols (this->abfd,
- TRUE /* dynamic */,
- (void*)&this->syms,
- &size);
- }
- }
- if(0 == symcount)
- {
- fprintf(stderr,"*** no symbols found in '%s'\n",bfd_get_filename(this->abfd));
- }
- }
- }
- sysheap_restore_leak_detection();
- }
- /*--------------------------------------------------------- */
- static void
- _lub_heap_symGetInfo(lub_heap_posix_t *this,
- unsigned address,
- info_t *info)
- {
- info->pc = address;
- info->syms = this->syms;
- info->fn_name = NULL;
- info->file_name = NULL;
- info->line_num = 0;
- info->found = FALSE;
-
- sysheap_suppress_leak_detection();
- if(NULL != this->abfd)
- {
- bfd_map_over_sections (this->abfd,
- find_address_in_section,
- info);
- }
- sysheap_restore_leak_detection();
- }
- /*--------------------------------------------------------- */
- void
- lub_heap_symShow(unsigned address)
- {
- lub_heap_posix_t *this = &my_instance;
- info_t info;
- _lub_heap_symGetInfo(this,address,&info);
- if(!info.found)
- {
- if(this->abfd && this->syms)
- {
- /* a line with the function names */
- printf("%26s","");
- }
- printf(" 0x%08x",address);
- if(!this->abfd)
- {
- /* aline with the function names */
- printf(" - lub_heap_init() not called.");
- }
- }
- else
- {
- printf(" %20s:%-4d",info.file_name,info.line_num);
- printf(" %s()",info.fn_name);
- }
- }
- /*--------------------------------------------------------- */
- bool_t
- lub_heap_symMatch(unsigned address,
- const char *substring)
- {
- lub_heap_posix_t *this = &my_instance;
- info_t info;
- bool_t result = BOOL_FALSE;
- _lub_heap_symGetInfo(this,address,&info);
- if(info.found)
- {
- if(strstr(info.fn_name,substring))
- {
- result = TRUE;
- }
- }
- return result;
- }
- /*--------------------------------------------------------- */
- #endif /* HAVE_LIBBFD */
|