LCOV - code coverage report
Current view: top level - mnt/wasteland/wcohen/systemtap_write/systemtap - dwarf_wrappers.cxx (source / functions) Hit Total Coverage
Test: stap.info Lines: 58 71 81.7 %
Date: 2013-03-08 Functions: 7 7 100.0 %
Branches: 75 156 48.1 %

           Branch data     Line data    Source code
       1                 :            : // -*- C++ -*-
       2                 :            : // Copyright (C) 2008-2011 Red Hat Inc.
       3                 :            : //
       4                 :            : // This file is part of systemtap, and is free software.  You can
       5                 :            : // redistribute it and/or modify it under the terms of the GNU General
       6                 :            : // Public License (GPL); either version 2, or (at your option) any
       7                 :            : // later version.
       8                 :            : 
       9                 :            : #include "dwarf_wrappers.h"
      10                 :            : #include "staptree.h"
      11                 :            : #include "util.h"
      12                 :            : 
      13                 :            : #include <cstring>
      14                 :            : #include <sstream>
      15                 :            : #include <string>
      16                 :            : #include <elfutils/libdwfl.h>
      17                 :            : #include <dwarf.h>
      18                 :            : 
      19                 :            : using namespace std;
      20                 :            : 
      21                 :     378484 : void dwfl_assert(const string& desc, int rc)
      22                 :            : {
      23         [ -  + ]:     378484 :   if (rc == 0)
      24                 :     378484 :     return;
      25 [ #  # ][ #  # ]:          0 :   string msg = _F("libdwfl failure (%s): ", desc.c_str());
      26         [ #  # ]:          0 :   if (rc < 0)
      27 [ #  # ][ #  # ]:          0 :     msg += (dwfl_errmsg (rc) ?: "?");
                 [ #  # ]
      28                 :            :   else
      29         [ #  # ]:          0 :     msg += std::strerror (rc);
      30         [ #  # ]:     378484 :   throw semantic_error (msg);
      31                 :            : }
      32                 :            : 
      33                 :     121956 : void dwarf_assert(const string& desc, int rc)
      34                 :            : {
      35         [ -  + ]:     121956 :   if (rc == 0)
      36                 :     121956 :     return;
      37 [ #  # ][ #  # ]:          0 :   string msg = _F("libdw failure (%s): ", desc.c_str());
      38         [ #  # ]:          0 :   if (rc < 0)
      39 [ #  # ][ #  # ]:          0 :     msg += dwarf_errmsg (rc);
      40                 :            :   else
      41         [ #  # ]:          0 :     msg += std::strerror (rc);
      42         [ #  # ]:     121956 :   throw semantic_error (msg);
      43                 :            : }
      44                 :            : 
      45                 :            : 
      46                 :            : #if !_ELFUTILS_PREREQ(0, 143)
      47                 :            : // Elfutils prior to 0.143 didn't use attr_integrate when looking up the
      48                 :            : // decl_file or decl_line, so the attributes would sometimes be missed.  For
      49                 :            : // those old versions, we define custom implementations to do the integration.
      50                 :            : 
      51                 :            : const char *
      52                 :            : dwarf_decl_file_integrate (Dwarf_Die *die)
      53                 :            : {
      54                 :            :   Dwarf_Attribute attr_mem;
      55                 :            :   Dwarf_Sword idx = 0;
      56                 :            :   if (dwarf_formsdata (dwarf_attr_integrate (die, DW_AT_decl_file, &attr_mem),
      57                 :            :                        &idx) != 0
      58                 :            :       || idx == 0)
      59                 :            :     return NULL;
      60                 :            : 
      61                 :            :   Dwarf_Die cudie;
      62                 :            :   Dwarf_Files *files = NULL;
      63                 :            :   if (dwarf_getsrcfiles (dwarf_diecu (die, &cudie, NULL, NULL),
      64                 :            :                          &files, NULL) != 0)
      65                 :            :     return NULL;
      66                 :            : 
      67                 :            :   return dwarf_filesrc(files, idx, NULL, NULL);
      68                 :            : }
      69                 :            : 
      70                 :            : int
      71                 :            : dwarf_decl_line_integrate (Dwarf_Die *die, int *linep)
      72                 :            : {
      73                 :            :   Dwarf_Attribute attr_mem;
      74                 :            :   Dwarf_Sword line;
      75                 :            : 
      76                 :            :   int res = dwarf_formsdata (dwarf_attr_integrate
      77                 :            :                              (die, DW_AT_decl_line, &attr_mem),
      78                 :            :                              &line);
      79                 :            :   if (res == 0)
      80                 :            :     *linep = line;
      81                 :            : 
      82                 :            :   return res;
      83                 :            : }
      84                 :            : 
      85                 :            : #endif // !_ELFUTILS_PREREQ(0, 143)
      86                 :            : 
      87                 :            : 
      88                 :            : static bool
      89                 :      67778 : dwarf_type_name(Dwarf_Die *type_die, ostream& o)
      90                 :            : {
      91                 :            :   // if we've gotten down to a basic type, then we're done
      92                 :      67778 :   bool done = true;
      93 [ +  - ][ +  +  :      67778 :   switch (dwarf_tag(type_die))
             +  +  +  +  
                      + ]
      94                 :            :     {
      95                 :            :     case DW_TAG_enumeration_type:
      96         [ +  - ]:        154 :       o << "enum ";
      97                 :        154 :       break;
      98                 :            :     case DW_TAG_structure_type:
      99         [ +  - ]:      12885 :       o << "struct ";
     100                 :      12885 :       break;
     101                 :            :     case DW_TAG_union_type:
     102         [ +  - ]:         32 :       o << "union ";
     103                 :         32 :       break;
     104                 :            :     case DW_TAG_class_type:
     105         [ +  - ]:       7031 :       o << "class ";
     106                 :       7031 :       break;
     107                 :            :     case DW_TAG_typedef:
     108                 :            :     case DW_TAG_base_type:
     109                 :       7865 :       break;
     110                 :            : 
     111                 :            :     // modifier types that require recursion first
     112                 :            :     case DW_TAG_reference_type:
     113                 :            :     case DW_TAG_rvalue_reference_type:
     114                 :            :     case DW_TAG_pointer_type:
     115                 :            :     case DW_TAG_array_type:
     116                 :            :     case DW_TAG_const_type:
     117                 :            :     case DW_TAG_volatile_type:
     118                 :      39774 :       done = false;
     119                 :      39774 :       break;
     120                 :            : 
     121                 :            :     // unknown tag
     122                 :            :     default:
     123                 :         37 :       return false;
     124                 :            :     }
     125         [ +  + ]:      67741 :   if (done)
     126                 :            :     {
     127                 :            :       // this follows gdb precedent that anonymous structs/unions
     128                 :            :       // are displayed as "struct {...}" and "union {...}".
     129 [ +  - ][ +  + ]:      27967 :       o << (dwarf_diename(type_die) ?: "{...}");
                 [ +  - ]
     130                 :      27967 :       return true;
     131                 :            :     }
     132                 :            : 
     133                 :            :   // otherwise, this die is a type modifier.
     134                 :            : 
     135                 :            :   // recurse into the referent type
     136                 :            :   Dwarf_Die subtype_die_mem, *subtype_die;
     137         [ +  - ]:      39774 :   subtype_die = dwarf_attr_die(type_die, DW_AT_type, &subtype_die_mem);
     138                 :            : 
     139                 :            :   // NB: va_list is a builtin type that shows up in the debuginfo as a
     140                 :            :   // "struct __va_list_tag*", but it has to be called only va_list.
     141 [ +  + ][ +  + ]:     105175 :   if (subtype_die != NULL &&
         [ +  + ][ -  + ]
                 [ -  + ]
     142         [ +  - ]:      39609 :       dwarf_tag(type_die) == DW_TAG_pointer_type &&
     143         [ +  - ]:      17836 :       dwarf_tag(subtype_die) == DW_TAG_structure_type &&
     144 [ +  - ][ +  - ]:       7956 :       strcmp(dwarf_diename(subtype_die) ?: "", "__va_list_tag") == 0)
     145                 :            :     {
     146         [ #  # ]:          0 :       o << "va_list";
     147                 :          0 :       return true;
     148                 :            :     }
     149                 :            : 
     150                 :            :   // if it can't be named, just call it "void"
     151 [ +  + ][ +  + ]:      79383 :   if (subtype_die == NULL ||
                 [ +  + ]
     152         [ +  - ]:      39609 :       !dwarf_type_name(subtype_die, o))
     153         [ +  - ]:        202 :     o << "void";
     154                 :            : 
     155 [ +  - ][ +  -  :      39774 :   switch (dwarf_tag(type_die))
             +  +  +  +  
                      - ]
     156                 :            :     {
     157                 :            :     case DW_TAG_reference_type:
     158         [ +  - ]:       3801 :       o << "&";
     159                 :       3801 :       break;
     160                 :            :     case DW_TAG_rvalue_reference_type:
     161         [ #  # ]:          0 :       o << "&&";
     162                 :          0 :       break;
     163                 :            :     case DW_TAG_pointer_type:
     164         [ +  - ]:      17930 :       o << "*";
     165                 :      17930 :       break;
     166                 :            :     case DW_TAG_array_type:
     167         [ +  - ]:         15 :       o << "[]";
     168                 :         15 :       break;
     169                 :            :     case DW_TAG_const_type:
     170                 :            :       // NB: the debuginfo may sometimes have an extra const tag
     171                 :            :       // on reference types, which is redundant to us.
     172 [ +  + ][ +  + ]:      50111 :       if (subtype_die == NULL ||
         [ +  - ][ +  + ]
     173         [ +  - ]:      17947 :           (dwarf_tag(subtype_die) != DW_TAG_reference_type &&
     174         [ +  - ]:      14146 :            dwarf_tag(subtype_die) != DW_TAG_rvalue_reference_type))
     175         [ +  - ]:      14217 :         o << " const";
     176                 :      18018 :       break;
     177                 :            :     case DW_TAG_volatile_type:
     178         [ +  - ]:         10 :       o << " volatile";
     179                 :         10 :       break;
     180                 :            :     default:
     181                 :          0 :       return false;
     182                 :            :     }
     183                 :            : 
     184                 :      67778 :   return true;
     185                 :            : }
     186                 :            : 
     187                 :            : 
     188                 :            : bool
     189                 :      25257 : dwarf_type_name(Dwarf_Die *type_die, string& type_name)
     190                 :            : {
     191         [ +  - ]:      25257 :   ostringstream o;
     192         [ +  - ]:      25257 :   bool ret = dwarf_type_name(type_die, o);
     193 [ +  - ][ +  - ]:      25257 :   type_name = o.str();
                 [ +  - ]
     194         [ +  - ]:      25257 :   return ret;
     195                 :            : }
     196                 :            : 
     197                 :            : 
     198                 :            : string
     199                 :       2912 : dwarf_type_name(Dwarf_Die *type_die)
     200                 :            : {
     201         [ +  - ]:       2912 :   ostringstream o;
     202 [ +  - ][ +  - ]:       2912 :   return dwarf_type_name(type_die, o) ? o.str() : "<unknown>";
         [ +  - ][ #  # ]
         [ -  + ][ +  - ]
                 [ #  # ]
     203 [ +  - ][ +  - ]:       7242 : }
     204                 :            : 
     205                 :            : 
     206                 :            : /* vim: set sw=2 ts=8 cino=>4,n-2,{2,^-2,t0,(0,u0,w1,M1 : */

Generated by: LCOV version 1.9