LCOV - code coverage report
Current view: top level - src/utils - trace.c (source / functions) Hit Total Coverage
Test: hostapd hwsim test run 1388338050 Lines: 11 160 6.9 %
Date: 2013-12-29 Functions: 2 12 16.7 %
Branches: 5 102 4.9 %

           Branch data     Line data    Source code
       1                 :            : /*
       2                 :            :  * Backtrace debugging
       3                 :            :  * Copyright (c) 2009, Jouni Malinen <j@w1.fi>
       4                 :            :  *
       5                 :            :  * This software may be distributed under the terms of the BSD license.
       6                 :            :  * See README for more details.
       7                 :            :  */
       8                 :            : 
       9                 :            : #include "includes.h"
      10                 :            : 
      11                 :            : #include "common.h"
      12                 :            : #include "trace.h"
      13                 :            : 
      14                 :            : #ifdef WPA_TRACE
      15                 :            : 
      16                 :            : static struct dl_list active_references =
      17                 :            : { &active_references, &active_references };
      18                 :            : 
      19                 :            : #ifdef WPA_TRACE_BFD
      20                 :            : #include <bfd.h>
      21                 :            : #ifdef __linux__
      22                 :            : #include <demangle.h>
      23                 :            : #else /* __linux__ */
      24                 :            : #include <libiberty/demangle.h>
      25                 :            : #endif /* __linux__ */
      26                 :            : 
      27                 :            : static char *prg_fname = NULL;
      28                 :            : static bfd *cached_abfd = NULL;
      29                 :            : static asymbol **syms = NULL;
      30                 :            : 
      31                 :          0 : static void get_prg_fname(void)
      32                 :            : {
      33                 :            :         char exe[50], fname[512];
      34                 :            :         int len;
      35                 :          0 :         os_snprintf(exe, sizeof(exe) - 1, "/proc/%u/exe", getpid());
      36                 :          0 :         len = readlink(exe, fname, sizeof(fname) - 1);
      37 [ #  # ][ #  # ]:          0 :         if (len < 0 || len >= (int) sizeof(fname)) {
      38                 :          0 :                 perror("readlink");
      39                 :          0 :                 return;
      40                 :            :         }
      41                 :          0 :         fname[len] = '\0';
      42                 :          0 :         prg_fname = strdup(fname);
      43                 :            : }
      44                 :            : 
      45                 :            : 
      46                 :          0 : static bfd * open_bfd(const char *fname)
      47                 :            : {
      48                 :            :         bfd *abfd;
      49                 :            :         char **matching;
      50                 :            : 
      51                 :          0 :         abfd = bfd_openr(prg_fname, NULL);
      52         [ #  # ]:          0 :         if (abfd == NULL) {
      53                 :          0 :                 wpa_printf(MSG_INFO, "bfd_openr failed");
      54                 :          0 :                 return NULL;
      55                 :            :         }
      56                 :            : 
      57         [ #  # ]:          0 :         if (bfd_check_format(abfd, bfd_archive)) {
      58                 :          0 :                 wpa_printf(MSG_INFO, "bfd_check_format failed");
      59                 :          0 :                 bfd_close(abfd);
      60                 :          0 :                 return NULL;
      61                 :            :         }
      62                 :            : 
      63         [ #  # ]:          0 :         if (!bfd_check_format_matches(abfd, bfd_object, &matching)) {
      64                 :          0 :                 wpa_printf(MSG_INFO, "bfd_check_format_matches failed");
      65                 :          0 :                 free(matching);
      66                 :          0 :                 bfd_close(abfd);
      67                 :          0 :                 return NULL;
      68                 :            :         }
      69                 :            : 
      70                 :          0 :         return abfd;
      71                 :            : }
      72                 :            : 
      73                 :            : 
      74                 :          0 : static void read_syms(bfd *abfd)
      75                 :            : {
      76                 :            :         long storage, symcount;
      77                 :          0 :         bfd_boolean dynamic = FALSE;
      78                 :            : 
      79         [ #  # ]:          0 :         if (syms)
      80                 :          0 :                 return;
      81                 :            : 
      82         [ #  # ]:          0 :         if (!(bfd_get_file_flags(abfd) & HAS_SYMS)) {
      83                 :          0 :                 wpa_printf(MSG_INFO, "No symbols");
      84                 :          0 :                 return;
      85                 :            :         }
      86                 :            : 
      87                 :          0 :         storage = bfd_get_symtab_upper_bound(abfd);
      88         [ #  # ]:          0 :         if (storage == 0) {
      89                 :          0 :                 storage = bfd_get_dynamic_symtab_upper_bound(abfd);
      90                 :          0 :                 dynamic = TRUE;
      91                 :            :         }
      92         [ #  # ]:          0 :         if (storage < 0) {
      93                 :          0 :                 wpa_printf(MSG_INFO, "Unknown symtab upper bound");
      94                 :          0 :                 return;
      95                 :            :         }
      96                 :            : 
      97                 :          0 :         syms = malloc(storage);
      98         [ #  # ]:          0 :         if (syms == NULL) {
      99                 :          0 :                 wpa_printf(MSG_INFO, "Failed to allocate memory for symtab "
     100                 :            :                            "(%ld bytes)", storage);
     101                 :          0 :                 return;
     102                 :            :         }
     103         [ #  # ]:          0 :         if (dynamic)
     104                 :          0 :                 symcount = bfd_canonicalize_dynamic_symtab(abfd, syms);
     105                 :            :         else
     106                 :          0 :                 symcount = bfd_canonicalize_symtab(abfd, syms);
     107         [ #  # ]:          0 :         if (symcount < 0) {
     108         [ #  # ]:          0 :                 wpa_printf(MSG_INFO, "Failed to canonicalize %ssymtab",
     109                 :            :                            dynamic ? "dynamic " : "");
     110                 :          0 :                 free(syms);
     111                 :          0 :                 syms = NULL;
     112                 :          0 :                 return;
     113                 :            :         }
     114                 :            : }
     115                 :            : 
     116                 :            : 
     117                 :            : struct bfd_data {
     118                 :            :         bfd_vma pc;
     119                 :            :         bfd_boolean found;
     120                 :            :         const char *filename;
     121                 :            :         const char *function;
     122                 :            :         unsigned int line;
     123                 :            : };
     124                 :            : 
     125                 :            : 
     126                 :          0 : static void find_addr_sect(bfd *abfd, asection *section, void *obj)
     127                 :            : {
     128                 :          0 :         struct bfd_data *data = obj;
     129                 :            :         bfd_vma vma;
     130                 :            :         bfd_size_type size;
     131                 :            : 
     132         [ #  # ]:          0 :         if (data->found)
     133                 :          0 :                 return;
     134                 :            : 
     135         [ #  # ]:          0 :         if (!(bfd_get_section_vma(abfd, section)))
     136                 :          0 :                 return;
     137                 :            : 
     138                 :          0 :         vma = bfd_get_section_vma(abfd, section);
     139         [ #  # ]:          0 :         if (data->pc < vma)
     140                 :          0 :                 return;
     141                 :            : 
     142                 :          0 :         size = bfd_get_section_size(section);
     143         [ #  # ]:          0 :         if (data->pc >= vma + size)
     144                 :          0 :                 return;
     145                 :            : 
     146                 :          0 :         data->found = bfd_find_nearest_line(abfd, section, syms,
     147                 :            :                                             data->pc - vma,
     148                 :            :                                             &data->filename,
     149                 :            :                                             &data->function,
     150                 :            :                                             &data->line);
     151                 :            : }
     152                 :            : 
     153                 :            : 
     154                 :          0 : static void wpa_trace_bfd_addr(void *pc)
     155                 :            : {
     156                 :          0 :         bfd *abfd = cached_abfd;
     157                 :            :         struct bfd_data data;
     158                 :            :         const char *name;
     159                 :          0 :         char *aname = NULL;
     160                 :            :         const char *filename;
     161                 :            : 
     162         [ #  # ]:          0 :         if (abfd == NULL)
     163                 :          0 :                 return;
     164                 :            : 
     165                 :          0 :         data.pc = (bfd_vma) pc;
     166                 :          0 :         data.found = FALSE;
     167                 :          0 :         bfd_map_over_sections(abfd, find_addr_sect, &data);
     168                 :            : 
     169         [ #  # ]:          0 :         if (!data.found)
     170                 :          0 :                 return;
     171                 :            : 
     172                 :            :         do {
     173         [ #  # ]:          0 :                 if (data.function)
     174                 :          0 :                         aname = bfd_demangle(abfd, data.function,
     175                 :            :                                              DMGL_ANSI | DMGL_PARAMS);
     176         [ #  # ]:          0 :                 name = aname ? aname : data.function;
     177                 :          0 :                 filename = data.filename;
     178         [ #  # ]:          0 :                 if (filename) {
     179                 :          0 :                         char *end = os_strrchr(filename, '/');
     180                 :          0 :                         int i = 0;
     181 [ #  # ][ #  # ]:          0 :                         while (*filename && *filename == prg_fname[i] &&
                 [ #  # ]
     182                 :            :                                filename <= end) {
     183                 :          0 :                                 filename++;
     184                 :          0 :                                 i++;
     185                 :            :                         }
     186                 :            :                 }
     187                 :          0 :                 wpa_printf(MSG_INFO, "     %s() %s:%u",
     188                 :            :                            name, filename, data.line);
     189                 :          0 :                 free(aname);
     190                 :            : 
     191                 :          0 :                 data.found = bfd_find_inliner_info(abfd, &data.filename,
     192                 :            :                                                    &data.function, &data.line);
     193         [ #  # ]:          0 :         } while (data.found);
     194                 :            : }
     195                 :            : 
     196                 :            : 
     197                 :          0 : static const char * wpa_trace_bfd_addr2func(void *pc)
     198                 :            : {
     199                 :          0 :         bfd *abfd = cached_abfd;
     200                 :            :         struct bfd_data data;
     201                 :            : 
     202         [ #  # ]:          0 :         if (abfd == NULL)
     203                 :          0 :                 return NULL;
     204                 :            : 
     205                 :          0 :         data.pc = (bfd_vma) pc;
     206                 :          0 :         data.found = FALSE;
     207                 :          0 :         bfd_map_over_sections(abfd, find_addr_sect, &data);
     208                 :            : 
     209         [ #  # ]:          0 :         if (!data.found)
     210                 :          0 :                 return NULL;
     211                 :            : 
     212                 :          0 :         return data.function;
     213                 :            : }
     214                 :            : 
     215                 :            : 
     216                 :          0 : static void wpa_trace_bfd_init(void)
     217                 :            : {
     218         [ #  # ]:          0 :         if (!prg_fname) {
     219                 :          0 :                 get_prg_fname();
     220         [ #  # ]:          0 :                 if (!prg_fname)
     221                 :          0 :                         return;
     222                 :            :         }
     223                 :            : 
     224         [ #  # ]:          0 :         if (!cached_abfd) {
     225                 :          0 :                 cached_abfd = open_bfd(prg_fname);
     226         [ #  # ]:          0 :                 if (!cached_abfd) {
     227                 :          0 :                         wpa_printf(MSG_INFO, "Failed to open bfd");
     228                 :          0 :                         return;
     229                 :            :                 }
     230                 :            :         }
     231                 :            : 
     232                 :          0 :         read_syms(cached_abfd);
     233         [ #  # ]:          0 :         if (!syms) {
     234                 :          0 :                 wpa_printf(MSG_INFO, "Failed to read symbols");
     235                 :          0 :                 return;
     236                 :            :         }
     237                 :            : }
     238                 :            : 
     239                 :            : 
     240                 :          0 : void wpa_trace_dump_funcname(const char *title, void *pc)
     241                 :            : {
     242                 :          0 :         wpa_printf(MSG_INFO, "WPA_TRACE: %s: %p", title, pc);
     243                 :          0 :         wpa_trace_bfd_init();
     244                 :          0 :         wpa_trace_bfd_addr(pc);
     245                 :          0 : }
     246                 :            : 
     247                 :            : #else /* WPA_TRACE_BFD */
     248                 :            : 
     249                 :            : #define wpa_trace_bfd_init() do { } while (0)
     250                 :            : #define wpa_trace_bfd_addr(pc) do { } while (0)
     251                 :            : #define wpa_trace_bfd_addr2func(pc) NULL
     252                 :            : 
     253                 :            : #endif /* WPA_TRACE_BFD */
     254                 :            : 
     255                 :          0 : void wpa_trace_dump_func(const char *title, void **btrace, int btrace_num)
     256                 :            : {
     257                 :            :         char **sym;
     258                 :            :         int i;
     259                 :            :         enum { TRACE_HEAD, TRACE_RELEVANT, TRACE_TAIL } state;
     260                 :            : 
     261                 :          0 :         wpa_trace_bfd_init();
     262                 :          0 :         wpa_printf(MSG_INFO, "WPA_TRACE: %s - START", title);
     263                 :          0 :         sym = backtrace_symbols(btrace, btrace_num);
     264                 :          0 :         state = TRACE_HEAD;
     265         [ #  # ]:          0 :         for (i = 0; i < btrace_num; i++) {
     266                 :          0 :                 const char *func = wpa_trace_bfd_addr2func(btrace[i]);
     267 [ #  # ][ #  # ]:          0 :                 if (state == TRACE_HEAD && func &&
                 [ #  # ]
     268         [ #  # ]:          0 :                     (os_strcmp(func, "wpa_trace_add_ref_func") == 0 ||
     269         [ #  # ]:          0 :                      os_strcmp(func, "wpa_trace_check_ref") == 0 ||
     270                 :          0 :                      os_strcmp(func, "wpa_trace_show") == 0))
     271                 :          0 :                         continue;
     272 [ #  # ][ #  # ]:          0 :                 if (state == TRACE_TAIL && sym && sym[i] &&
         [ #  # ][ #  # ]
     273                 :          0 :                     os_strstr(sym[i], "__libc_start_main"))
     274                 :          0 :                         break;
     275         [ #  # ]:          0 :                 if (state == TRACE_HEAD)
     276                 :          0 :                         state = TRACE_RELEVANT;
     277         [ #  # ]:          0 :                 if (sym)
     278                 :          0 :                         wpa_printf(MSG_INFO, "[%d]: %s", i, sym[i]);
     279                 :            :                 else
     280                 :          0 :                         wpa_printf(MSG_INFO, "[%d]: ?? [%p]", i, btrace[i]);
     281                 :          0 :                 wpa_trace_bfd_addr(btrace[i]);
     282 [ #  # ][ #  # ]:          0 :                 if (state == TRACE_RELEVANT && func &&
                 [ #  # ]
     283                 :          0 :                     os_strcmp(func, "main") == 0)
     284                 :          0 :                         state = TRACE_TAIL;
     285                 :            :         }
     286                 :          0 :         free(sym);
     287                 :          0 :         wpa_printf(MSG_INFO, "WPA_TRACE: %s - END", title);
     288                 :          0 : }
     289                 :            : 
     290                 :            : 
     291                 :          0 : void wpa_trace_show(const char *title)
     292                 :            : {
     293                 :            :         struct info {
     294                 :            :                 WPA_TRACE_INFO
     295                 :            :         } info;
     296                 :          0 :         wpa_trace_record(&info);
     297                 :          0 :         wpa_trace_dump(title, &info);
     298                 :          0 : }
     299                 :            : 
     300                 :            : 
     301                 :      72710 : void wpa_trace_add_ref_func(struct wpa_trace_ref *ref, const void *addr)
     302                 :            : {
     303         [ +  + ]:      72710 :         if (addr == NULL)
     304                 :      72710 :                 return;
     305                 :      47463 :         ref->addr = addr;
     306                 :      47463 :         wpa_trace_record(ref);
     307                 :      47463 :         dl_list_add(&active_references, &ref->list);
     308                 :            : }
     309                 :            : 
     310                 :            : 
     311                 :      79766 : void wpa_trace_check_ref(const void *addr)
     312                 :            : {
     313                 :            :         struct wpa_trace_ref *ref;
     314         [ +  + ]:    1692362 :         dl_list_for_each(ref, &active_references, struct wpa_trace_ref, list) {
     315         [ +  - ]:    1612596 :                 if (addr != ref->addr)
     316                 :    1612596 :                         continue;
     317                 :          0 :                 wpa_trace_show("Freeing referenced memory");
     318                 :          0 :                 wpa_trace_dump("Reference registration", ref);
     319                 :          0 :                 abort();
     320                 :            :         }
     321                 :      79766 : }
     322                 :            : 
     323                 :            : #endif /* WPA_TRACE */

Generated by: LCOV version 1.9