123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291 |
- /*
- * 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 */
|