LCOV - code coverage report
Current view: top level - mnt/wasteland/wcohen/systemtap_write/systemtap - dwflpp.cxx (source / functions) Hit Total Coverage
Test: stap.info Lines: 1309 1652 79.2 %
Date: 2013-03-08 Functions: 88 91 96.7 %
Branches: 1688 4235 39.9 %

           Branch data     Line data    Source code
       1                 :            : // C++ interface to dwfl
       2                 :            : // Copyright (C) 2005-2013 Red Hat Inc.
       3                 :            : // Copyright (C) 2005-2007 Intel Corporation.
       4                 :            : // Copyright (C) 2008 James.Bottomley@HansenPartnership.com
       5                 :            : //
       6                 :            : // This file is part of systemtap, and is free software.  You can
       7                 :            : // redistribute it and/or modify it under the terms of the GNU General
       8                 :            : // Public License (GPL); either version 2, or (at your option) any
       9                 :            : // later version.
      10                 :            : 
      11                 :            : #include "dwflpp.h"
      12                 :            : #include "config.h"
      13                 :            : #include "staptree.h"
      14                 :            : #include "elaborate.h"
      15                 :            : #include "tapsets.h"
      16                 :            : #include "task_finder.h"
      17                 :            : #include "translate.h"
      18                 :            : #include "session.h"
      19                 :            : #include "util.h"
      20                 :            : #include "buildrun.h"
      21                 :            : #include "dwarf_wrappers.h"
      22                 :            : #include "auto_free.h"
      23                 :            : #include "hash.h"
      24                 :            : #include "rpm_finder.h"
      25                 :            : #include "setupdwfl.h"
      26                 :            : 
      27                 :            : #include <cstdlib>
      28                 :            : #include <algorithm>
      29                 :            : #include <deque>
      30                 :            : #include <iostream>
      31                 :            : #include <map>
      32                 :            : #include <set>
      33                 :            : #include <sstream>
      34                 :            : #include <stdexcept>
      35                 :            : #include <vector>
      36                 :            : #include <cstdarg>
      37                 :            : #include <cassert>
      38                 :            : #include <iomanip>
      39                 :            : #include <cerrno>
      40                 :            : 
      41                 :            : extern "C" {
      42                 :            : #include <fcntl.h>
      43                 :            : #include <elfutils/libdwfl.h>
      44                 :            : #include <elfutils/libdw.h>
      45                 :            : #include <dwarf.h>
      46                 :            : #include <elf.h>
      47                 :            : #include <obstack.h>
      48                 :            : #include <regex.h>
      49                 :            : #include <glob.h>
      50                 :            : #include <fnmatch.h>
      51                 :            : #include <stdio.h>
      52                 :            : #include <sys/types.h>
      53                 :            : 
      54                 :            : #include "loc2c.h"
      55                 :            : #define __STDC_FORMAT_MACROS
      56                 :            : #include <inttypes.h>
      57                 :            : }
      58                 :            : 
      59                 :            : // Older glibc elf.h don't know about this new constant.
      60                 :            : #ifndef STB_GNU_UNIQUE
      61                 :            : #define STB_GNU_UNIQUE  10
      62                 :            : #endif
      63                 :            : 
      64                 :            : 
      65                 :            : // debug flag to compare to the uncached version from libdw
      66                 :            : // #define DEBUG_DWFLPP_GETSCOPES 1
      67                 :            : 
      68                 :            : 
      69                 :            : using namespace std;
      70                 :            : using namespace __gnu_cxx;
      71                 :            : 
      72                 :            : 
      73         [ +  - ]:       2414 : static string TOK_KERNEL("kernel");
      74                 :            : 
      75                 :            : 
      76                 :       1041 : dwflpp::dwflpp(systemtap_session & session, const string& name, bool kernel_p):
      77                 :            :   sess(session), module(NULL), module_bias(0), mod_info(NULL),
      78                 :            :   module_start(0), module_end(0), cu(NULL),
      79                 :            :   module_dwarf(NULL), function(NULL), blacklist_func(), blacklist_func_ret(),
      80 [ +  - ][ +  - ]:       1041 :   blacklist_file(),  blacklist_enabled(false)
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
      81                 :            : {
      82         [ +  + ]:       1041 :   if (kernel_p)
      83         [ +  + ]:        972 :     setup_kernel(name, session);
      84                 :            :   else
      85                 :            :     {
      86         [ +  - ]:         69 :       vector<string> modules;
      87         [ +  - ]:         69 :       modules.push_back(name);
      88 [ +  - ][ +  - ]:         69 :       setup_user(modules);
      89                 :            :     }
      90                 :       1041 : }
      91                 :            : 
      92                 :         84 : dwflpp::dwflpp(systemtap_session & session, const vector<string>& names,
      93                 :            :                bool kernel_p):
      94                 :            :   sess(session), module(NULL), module_bias(0), mod_info(NULL),
      95                 :            :   module_start(0), module_end(0), cu(NULL),
      96 [ +  - ][ +  - ]:         84 :   module_dwarf(NULL), function(NULL), blacklist_enabled(false)
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
      97                 :            : {
      98         [ +  - ]:         84 :   if (kernel_p)
      99         [ +  - ]:         84 :     setup_kernel(names);
     100                 :            :   else
     101         [ #  # ]:          0 :     setup_user(names);
     102                 :         84 : }
     103                 :            : 
     104                 :      13476 : dwflpp::~dwflpp()
     105                 :            : {
     106         [ +  - ]:       1123 :   delete_map(module_cu_cache);
     107         [ +  - ]:       1123 :   delete_map(cu_function_cache);
     108         [ +  - ]:       1123 :   delete_map(mod_function_cache);
     109         [ +  - ]:       1123 :   delete_map(cu_inl_function_cache);
     110         [ +  - ]:       1123 :   delete_map(global_alias_cache);
     111         [ +  - ]:       1123 :   delete_map(cu_die_parent_cache);
     112                 :            : 
     113         [ +  - ]:       1123 :   dwfl_ptr.reset();
     114                 :            :   // NB: don't "delete mod_info;", as that may be shared
     115                 :            :   // between dwflpp instances, and are stored in
     116                 :            :   // session.module_cache[] anyway.
     117 [ +  - ][ +  - ]:       1123 : }
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
     118                 :            : 
     119                 :            : 
     120                 :       1286 : module_cache::~module_cache ()
     121                 :            : {
     122         [ +  - ]:        643 :   delete_map(cache);
     123                 :        643 : }
     124                 :            : 
     125                 :            : 
     126                 :            : void
     127                 :     414373 : dwflpp::get_module_dwarf(bool required, bool report)
     128                 :            : {
     129                 :     414373 :   module_dwarf = dwfl_module_getdwarf(module, &module_bias);
     130         [ +  + ]:     414373 :   mod_info->dwarf_status = (module_dwarf ? info_present : info_absent);
     131 [ +  + ][ +  - ]:     414373 :   if (!module_dwarf && report)
     132                 :            :     {
     133         [ +  - ]:          8 :       string msg = _("cannot find ");
     134 [ +  - ][ -  + ]:          8 :       if (module_name == "")
     135         [ #  # ]:          0 :         msg += "kernel";
     136                 :            :       else
     137 [ +  - ][ +  - ]:          8 :         msg += string("module ") + module_name;
         [ +  - ][ +  - ]
                 [ +  - ]
     138         [ +  - ]:          8 :       msg += " debuginfo";
     139                 :            : 
     140         [ +  - ]:          8 :       int i = dwfl_errno();
     141         [ +  - ]:          8 :       if (i)
     142 [ +  - ][ +  - ]:          8 :         msg += string(": ") + dwfl_errmsg (i);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
     143                 :            : 
     144         [ +  - ]:          8 :       msg += " [man warning::debuginfo]";
     145                 :            : 
     146                 :            :       /* add module_name to list to find rpm */
     147 [ +  - ][ +  - ]:          8 :       find_debug_rpms(sess, module_name.c_str());
     148                 :            : 
     149         [ -  + ]:          8 :       if (required)
     150         [ #  # ]:          0 :         throw semantic_error (msg);
     151                 :            :       else
     152 [ +  - ][ +  - ]:          8 :         sess.print_warning(msg);
     153                 :            :     }
     154                 :     414373 : }
     155                 :            : 
     156                 :            : 
     157                 :            : void
     158                 :      85120 : dwflpp::focus_on_module(Dwfl_Module * m, module_info * mi)
     159                 :            : {
     160                 :      85120 :   module = m;
     161                 :      85120 :   mod_info = mi;
     162         [ +  - ]:      85120 :   if (m)
     163                 :            :     {
     164                 :            :       module_name = dwfl_module_info(module, NULL, &module_start, &module_end,
     165         [ +  - ]:      85120 :                                      NULL, NULL, NULL, NULL) ?: "module";
     166                 :            :     }
     167                 :            :   else
     168                 :            :     {
     169 [ #  # ][ #  # ]:          0 :       assert(mi && mi->name && mi->name == TOK_KERNEL);
                 [ #  # ]
     170                 :          0 :       module_name = mi->name;
     171                 :          0 :       module_start = 0;
     172                 :          0 :       module_end = 0;
     173                 :          0 :       module_bias = mi->bias;
     174                 :            :     }
     175                 :            : 
     176                 :            :   // Reset existing pointers and names
     177                 :            : 
     178                 :      85120 :   module_dwarf = NULL;
     179                 :            : 
     180                 :      85120 :   cu = NULL;
     181                 :            : 
     182                 :      85120 :   function_name.clear();
     183                 :      85120 :   function = NULL;
     184                 :      85120 : }
     185                 :            : 
     186                 :            : 
     187                 :            : void
     188                 :     265398 : dwflpp::focus_on_cu(Dwarf_Die * c)
     189                 :            : {
     190         [ -  + ]:     265398 :   assert(c);
     191         [ -  + ]:     265398 :   assert(module);
     192                 :            : 
     193                 :     265398 :   cu = c;
     194                 :            : 
     195                 :            :   // Reset existing pointers and names
     196                 :     265398 :   function_name.clear();
     197                 :     265398 :   function = NULL;
     198                 :     265398 : }
     199                 :            : 
     200                 :            : 
     201                 :            : string
     202                 :          0 : dwflpp::cu_name(void)
     203                 :            : {
     204 [ #  # ][ #  # ]:          0 :   return dwarf_diename(cu) ?: "<unknown source>";
     205                 :            : }
     206                 :            : 
     207                 :            : 
     208                 :            : void
     209                 :     698033 : dwflpp::focus_on_function(Dwarf_Die * f)
     210                 :            : {
     211         [ -  + ]:     698033 :   assert(f);
     212         [ -  + ]:     698033 :   assert(module);
     213         [ -  + ]:     698033 :   assert(cu);
     214                 :            : 
     215                 :     698033 :   function = f;
     216         [ +  - ]:     698033 :   function_name = dwarf_diename(function) ?: "function";
     217                 :     698033 : }
     218                 :            : 
     219                 :            : 
     220                 :            : /* Return the Dwarf_Die for the given address in the current module.
     221                 :            :  * The address should be in the module address address space (this
     222                 :            :  * function will take care of any dw bias).
     223                 :            :  */
     224                 :            : Dwarf_Die *
     225                 :         25 : dwflpp::query_cu_containing_address(Dwarf_Addr a)
     226                 :            : {
     227                 :            :   Dwarf_Addr bias;
     228         [ -  + ]:         25 :   assert(dwfl_ptr.get()->dwfl);
     229         [ -  + ]:         25 :   assert(module);
     230         [ +  - ]:         25 :   get_module_dwarf();
     231                 :            : 
     232         [ +  - ]:         25 :   Dwarf_Die* cudie = dwfl_module_addrdie(module, a, &bias);
     233         [ -  + ]:         25 :   assert(bias == module_bias);
     234                 :         25 :   return cudie;
     235                 :            : }
     236                 :            : 
     237                 :            : 
     238                 :            : bool
     239                 :      85119 : dwflpp::module_name_matches(const string& pattern)
     240                 :            : {
     241                 :      85119 :   bool t = (fnmatch(pattern.c_str(), module_name.c_str(), 0) == 0);
     242 [ +  + ][ -  + ]:      85119 :   if (t && sess.verbose>3)
     243                 :          0 :     clog << _F("pattern '%s' matches module '%s'\n",
     244         [ #  # ]:          0 :                pattern.c_str(), module_name.c_str());
     245                 :      85119 :   return t;
     246                 :            : }
     247                 :            : 
     248                 :            : 
     249                 :            : bool
     250                 :     194823 : dwflpp::name_has_wildcard (const string& pattern)
     251                 :            : {
     252                 :     194823 :   return (pattern.find('*') != string::npos ||
     253                 :     131060 :           pattern.find('?') != string::npos ||
     254   [ +  +  +  - ]:     325883 :           pattern.find('[') != string::npos);
                 [ +  + ]
     255                 :            : }
     256                 :            : 
     257                 :            : 
     258                 :            : bool
     259                 :      79135 : dwflpp::module_name_final_match(const string& pattern)
     260                 :            : {
     261                 :            :   // Assume module_name_matches().  Can there be any more matches?
     262                 :            :   // Not unless the pattern is a wildcard, since module names are
     263                 :            :   // presumed unique.
     264                 :      79135 :   return !name_has_wildcard(pattern);
     265                 :            : }
     266                 :            : 
     267                 :            : 
     268                 :            : bool
     269                 :    2774840 : dwflpp::function_name_matches_pattern(const string& name, const string& pattern)
     270                 :            : {
     271                 :    2774840 :   bool t = (fnmatch(pattern.c_str(), name.c_str(), 0) == 0);
     272 [ +  + ][ -  + ]:    2774840 :   if (t && sess.verbose>3)
     273         [ #  # ]:          0 :     clog << _F("pattern '%s' matches function '%s'\n", pattern.c_str(), name.c_str());
     274                 :    2774840 :   return t;
     275                 :            : }
     276                 :            : 
     277                 :            : 
     278                 :            : bool
     279                 :        746 : dwflpp::function_name_matches(const string& pattern)
     280                 :            : {
     281         [ -  + ]:        746 :   assert(function);
     282                 :        746 :   return function_name_matches_pattern(function_name, pattern);
     283                 :            : }
     284                 :            : 
     285                 :            : 
     286                 :            : bool
     287                 :     696083 : dwflpp::function_scope_matches(const vector<string>& scopes)
     288                 :            : {
     289                 :            :   // walk up the containing scopes
     290                 :     696083 :   Dwarf_Die* die = function;
     291         [ -  + ]:     696083 :   for (int i = scopes.size() - 1; i >= 0; --i)
     292                 :            :     {
     293         [ #  # ]:          0 :       die = get_parent_scope(die);
     294                 :            : 
     295                 :            :       // check if this scope matches, and prepend it if so
     296                 :            :       // NB: a NULL die is the global scope, compared as ""
     297 [ #  # ][ #  # ]:          0 :       string name = dwarf_diename(die) ?: "";
                 [ #  # ]
     298         [ #  # ]:          0 :       if (name_has_wildcard(scopes[i]) ?
           [ #  #  #  # ]
         [ #  # ][ #  # ]
     299                 :          0 :           function_name_matches_pattern(name, scopes[i]) :
     300                 :          0 :           name == scopes[i])
     301 [ #  # ][ #  # ]:          0 :         function_name = name + "::" + function_name;
         [ #  # ][ #  # ]
                 [ #  # ]
     302                 :            :       else
     303                 :          0 :         return false;
     304                 :            : 
     305                 :            :       // make sure there's no more if we're at the global scope
     306 [ #  # ][ #  # ]:          0 :       if (!die && i > 0)
     307                 :          0 :         return false;
     308 [ #  # ][ #  # ]:          0 :     }
     309                 :     696083 :   return true;
     310                 :            : }
     311                 :            : 
     312                 :            : 
     313                 :            : void
     314                 :        972 : dwflpp::setup_kernel(const string& name, systemtap_session & s, bool debuginfo_needed)
     315                 :            : {
     316         [ +  + ]:        972 :   if (! sess.module_cache)
     317 [ +  - ][ +  - ]:        531 :     sess.module_cache = new module_cache ();
     318                 :            : 
     319                 :        972 :   unsigned offline_search_matches = 0;
     320 [ +  - ][ +  - ]:        972 :   dwfl_ptr = setup_dwfl_kernel(name, &offline_search_matches, sess);
                 [ +  - ]
     321                 :            : 
     322         [ +  + ]:        972 :   if (offline_search_matches < 1)
     323                 :            :     {
     324         [ +  - ]:          2 :       if (debuginfo_needed) {
     325                 :            :         // Suggest a likely kernel dir to find debuginfo rpm for
     326 [ +  - ][ +  - ]:          2 :         string dir = string(sess.sysroot + "/lib/modules/" + sess.kernel_release );
                 [ +  - ]
     327 [ +  - ][ +  - ]:          2 :         find_debug_rpms(sess, dir.c_str());
                 [ +  - ]
     328                 :            :       }
     329                 :          2 :       throw semantic_error (_F("missing %s kernel/module debuginfo [man warning::debuginfo] under '%s'",
     330 [ +  - ][ +  - ]:          2 :                                 sess.architecture.c_str(), sess.kernel_build_tree.c_str()));
         [ +  - ][ +  - ]
     331                 :            :     }
     332                 :        970 :   Dwfl *dwfl = dwfl_ptr.get()->dwfl;
     333         [ +  - ]:        970 :   if (dwfl != NULL)
     334                 :            :     {
     335                 :        970 :       ptrdiff_t off = 0;
     336         [ -  + ]:        970 :       do
     337                 :            :         {
     338         [ +  - ]:        970 :           assert_no_interrupts();
     339         [ +  - ]:        970 :           off = dwfl_getmodules (dwfl, &add_module_build_id_to_hash, &s, off);
     340                 :            :         }
     341                 :            :       while (off > 0);
     342 [ +  - ][ +  - ]:        972 :       dwfl_assert("dwfl_getmodules", off == 0);
                 [ +  - ]
     343                 :            :     }
     344                 :            : 
     345         [ +  - ]:        970 :   build_blacklist();
     346                 :        970 : }
     347                 :            : 
     348                 :            : void
     349                 :         84 : dwflpp::setup_kernel(const vector<string> &names, bool debuginfo_needed)
     350                 :            : {
     351         [ +  + ]:         84 :   if (! sess.module_cache)
     352 [ +  - ][ +  - ]:         65 :     sess.module_cache = new module_cache ();
     353                 :            : 
     354                 :         84 :   unsigned offline_search_matches = 0;
     355 [ +  - ][ +  - ]:         84 :   set<string> offline_search_names(names.begin(), names.end());
                 [ +  - ]
     356                 :            :   dwfl_ptr = setup_dwfl_kernel(offline_search_names,
     357                 :            :                                &offline_search_matches,
     358 [ +  - ][ +  - ]:         84 :                                sess);
                 [ +  - ]
     359                 :            : 
     360 [ +  - ][ -  + ]:         84 :   if (offline_search_matches < offline_search_names.size())
     361                 :            :     {
     362         [ #  # ]:          0 :       if (debuginfo_needed) {
     363                 :            :         // Suggest a likely kernel dir to find debuginfo rpm for
     364 [ #  # ][ #  # ]:          0 :         string dir = string(sess.sysroot + "/lib/modules/" + sess.kernel_release );
                 [ #  # ]
     365 [ #  # ][ #  # ]:          0 :         find_debug_rpms(sess, dir.c_str());
                 [ #  # ]
     366                 :            :       }
     367                 :          0 :       throw semantic_error (_F("missing %s kernel/module debuginfo [man warning::debuginfo] under '%s'",
     368 [ #  # ][ #  # ]:          0 :                                sess.architecture.c_str(), sess.kernel_build_tree.c_str()));
         [ #  # ][ #  # ]
     369                 :            :     }
     370                 :            : 
     371 [ +  - ][ +  - ]:         84 :   build_blacklist();
     372                 :         84 : }
     373                 :            : 
     374                 :            : 
     375                 :            : void
     376                 :         69 : dwflpp::setup_user(const vector<string>& modules, bool debuginfo_needed)
     377                 :            : {
     378         [ +  + ]:         69 :   if (! sess.module_cache)
     379 [ +  - ][ +  - ]:         49 :     sess.module_cache = new module_cache ();
     380                 :            : 
     381         [ +  - ]:         69 :   vector<string>::const_iterator it = modules.begin();
     382 [ +  - ][ +  - ]:         69 :   dwfl_ptr = setup_dwfl_user(it, modules.end(), debuginfo_needed, sess);
         [ +  - ][ +  - ]
     383 [ +  - ][ +  - ]:         69 :   if (debuginfo_needed && it != modules.end())
         [ +  - ][ -  + ]
                 [ +  - ]
           [ -  +  #  # ]
     384                 :          0 :     dwfl_assert (string(_F("missing process %s %s debuginfo",
     385                 :            :                            (*it).c_str(), sess.architecture.c_str())),
     386 [ #  # ][ #  # ]:          0 :                            dwfl_ptr.get()->dwfl);
         [ #  # ][ #  # ]
                 [ #  # ]
     387                 :         69 : }
     388                 :            : 
     389                 :            : void
     390                 :      56812 : dwflpp::iterate_over_modules(int (* callback)(Dwfl_Module *, void **,
     391                 :            :                                               const char *, Dwarf_Addr,
     392                 :            :                                               void *),
     393                 :            :                              void *data)
     394                 :            : {
     395                 :      56812 :   dwfl_getmodules (dwfl_ptr.get()->dwfl, callback, data, 0);
     396                 :            : 
     397                 :            :   // Don't complain if we exited dwfl_getmodules early.
     398                 :            :   // This could be a $target variable error that will be
     399                 :            :   // reported soon anyway.
     400                 :            :   // dwfl_assert("dwfl_getmodules", off == 0);
     401                 :            : 
     402                 :            :   // PR6864 XXX: For dwarfless case (if .../vmlinux is missing), then the
     403                 :            :   // "kernel" module is not reported in the loop above.  However, we
     404                 :            :   // may be able to make do with symbol table data.
     405                 :      56812 : }
     406                 :            : 
     407                 :            : 
     408                 :            : void
     409                 :      44955 : dwflpp::iterate_over_cus (int (*callback)(Dwarf_Die * die, void * arg),
     410                 :            :                           void * data, bool want_types)
     411                 :            : {
     412         [ +  - ]:      44955 :   get_module_dwarf(false);
     413                 :      44955 :   Dwarf *dw = module_dwarf;
     414         [ +  - ]:      89910 :   if (!dw) return;
     415                 :            : 
     416         [ +  - ]:      44955 :   vector<Dwarf_Die>* v = module_cu_cache[dw];
     417         [ +  + ]:      44955 :   if (v == 0)
     418                 :            :     {
     419 [ +  - ][ +  - ]:       4527 :       v = new vector<Dwarf_Die>;
     420         [ +  - ]:       4527 :       module_cu_cache[dw] = v;
     421                 :            : 
     422                 :       4527 :       Dwarf_Off off = 0;
     423                 :            :       size_t cuhl;
     424                 :            :       Dwarf_Off noff;
     425 [ +  - ][ +  + ]:     655608 :       while (dwarf_nextcu (dw, off, &noff, &cuhl, NULL, NULL, NULL) == 0)
     426                 :            :         {
     427         [ +  - ]:     651081 :           assert_no_interrupts();
     428                 :            :           Dwarf_Die die_mem;
     429                 :            :           Dwarf_Die *die;
     430         [ +  - ]:     651081 :           die = dwarf_offdie (dw, off + cuhl, &die_mem);
     431                 :            :           /* Skip partial units. */
     432 [ +  - ][ +  - ]:     651081 :           if (dwarf_tag (die) == DW_TAG_compile_unit)
     433         [ +  - ]:     651081 :             v->push_back (*die); /* copy */
     434                 :     651081 :           off = noff;
     435                 :            :         }
     436                 :            :     }
     437                 :            : 
     438 [ +  + ][ +  - ]:      44955 :   if (want_types && module_tus_read.find(dw) == module_tus_read.end())
         [ +  - ][ +  + ]
         [ +  + ][ +  + ]
           [ +  +  #  #  
                   #  # ]
     439                 :            :     {
     440                 :            :       // Process type units.
     441                 :        678 :       Dwarf_Off off = 0;
     442                 :            :       size_t cuhl;
     443                 :            :       Dwarf_Off noff;
     444                 :            :       uint64_t type_signature;
     445         [ +  + ]:       1357 :       while (dwarf_next_unit (dw, off, &noff, &cuhl, NULL, NULL, NULL, NULL,
     446         [ +  - ]:        679 :                               &type_signature, NULL) == 0)
     447                 :            :         {
     448         [ +  - ]:          1 :           assert_no_interrupts();
     449                 :            :           Dwarf_Die die_mem;
     450                 :            :           Dwarf_Die *die;
     451         [ +  - ]:          1 :           die = dwarf_offdie_types (dw, off + cuhl, &die_mem);
     452                 :            :           /* Skip partial units. */
     453 [ +  - ][ +  - ]:          1 :           if (dwarf_tag (die) == DW_TAG_type_unit)
     454         [ +  - ]:          1 :             v->push_back (*die); /* copy */
     455                 :          1 :           off = noff;
     456                 :            :         }
     457         [ +  - ]:        678 :       module_tus_read.insert(dw);
     458                 :            :     }
     459                 :            : 
     460 [ +  - ][ +  - ]:   13977428 :   for (vector<Dwarf_Die>::iterator i = v->begin(); i != v->end(); ++i)
         [ +  - ][ +  + ]
     461                 :            :     {
     462         [ +  - ]:   13932473 :       int rc = (*callback)(&*i, data);
     463         [ +  - ]:   13932473 :       assert_no_interrupts();
     464         [ +  + ]:   13932473 :       if (rc != DWARF_CB_OK)
     465                 :          1 :         break;
     466                 :            :     }
     467                 :            : }
     468                 :            : 
     469                 :            : 
     470                 :            : bool
     471                 :    2590110 : dwflpp::func_is_inline()
     472                 :            : {
     473         [ -  + ]:    2590110 :   assert (function);
     474                 :    2590110 :   return dwarf_func_inline (function) != 0;
     475                 :            : }
     476                 :            : 
     477                 :            : 
     478                 :            : bool
     479                 :         40 : dwflpp::func_is_exported()
     480                 :            : {
     481         [ -  + ]:         40 :   const char *name = dwarf_linkage_name (function) ?: dwarf_diename (function);
     482                 :            : 
     483         [ -  + ]:         40 :   assert (function);
     484                 :            : 
     485                 :         40 :   int syms = dwfl_module_getsymtab (module);
     486 [ +  - ][ +  - ]:         40 :   dwfl_assert (_("Getting symbols"), syms >= 0);
                 [ +  - ]
     487                 :            : 
     488         [ +  + ]:    3662184 :   for (int i = 0; i < syms; i++)
     489                 :            :     {
     490                 :            :       GElf_Sym sym;
     491                 :            :       GElf_Word shndxp;
     492         [ +  - ]:    3662144 :       const char *symname = dwfl_module_getsym(module, i, &sym, &shndxp);
     493 [ +  - ][ +  + ]:    3662144 :       if (symname
     494                 :    3662144 :           && strcmp (name, symname) == 0)
     495                 :            :         {
     496 [ +  - ][ +  + ]:         39 :           if (GELF_ST_TYPE(sym.st_info) == STT_FUNC
         [ +  - ][ -  + ]
     497                 :            :               && (GELF_ST_BIND(sym.st_info) == STB_GLOBAL
     498                 :            :                   || GELF_ST_BIND(sym.st_info) == STB_WEAK
     499                 :            :                   || GELF_ST_BIND(sym.st_info) == STB_GNU_UNIQUE))
     500                 :         34 :             return true;
     501                 :            :           else
     502                 :          5 :             return false;
     503                 :            :         }
     504                 :            :     }
     505                 :         40 :   return false;
     506                 :            : }
     507                 :            : 
     508                 :            : void
     509                 :     393799 : dwflpp::cache_inline_instances (Dwarf_Die* die)
     510                 :            : {
     511                 :            :   // If this is an inline instance, link it back to its origin
     512                 :            :   Dwarf_Die origin;
     513 [ +  - ][ +  + ]:     520121 :   if (dwarf_tag(die) == DW_TAG_inlined_subroutine &&
         [ +  - ][ +  + ]
     514         [ +  - ]:     126322 :       dwarf_attr_die(die, DW_AT_abstract_origin, &origin))
     515                 :            :     {
     516         [ +  - ]:     126322 :       vector<Dwarf_Die>*& v = cu_inl_function_cache[origin.addr];
     517         [ +  + ]:     126322 :       if (!v)
     518 [ +  - ][ +  - ]:      47263 :         v = new vector<Dwarf_Die>;
     519         [ +  - ]:     126322 :       v->push_back(*die);
     520                 :            :     }
     521                 :            : 
     522                 :            :   // Recurse through other scopes that may contain inlines
     523                 :            :   Dwarf_Die child, import;
     524 [ +  - ][ +  + ]:     393799 :   if (dwarf_child(die, &child) == 0)
     525         [ +  + ]:    3624555 :     do
     526                 :            :       {
     527         [ +  - ]:    3624555 :         switch (dwarf_tag (&child))
              [ +  -  + ]
     528                 :            :           {
     529                 :            :           // tags that could contain inlines
     530                 :            :           case DW_TAG_compile_unit:
     531                 :            :           case DW_TAG_module:
     532                 :            :           case DW_TAG_lexical_block:
     533                 :            :           case DW_TAG_with_stmt:
     534                 :            :           case DW_TAG_catch_block:
     535                 :            :           case DW_TAG_try_block:
     536                 :            :           case DW_TAG_entry_point:
     537                 :            :           case DW_TAG_inlined_subroutine:
     538                 :            :           case DW_TAG_subprogram:
     539         [ +  - ]:     392064 :             cache_inline_instances(&child);
     540                 :     392064 :             break;
     541                 :            : 
     542                 :            :           // imported dies should be followed
     543                 :            :           case DW_TAG_imported_unit:
     544 [ #  # ][ #  # ]:          0 :             if (dwarf_attr_die(&child, DW_AT_import, &import))
     545         [ #  # ]:          0 :               cache_inline_instances(&import);
     546                 :          0 :             break;
     547                 :            : 
     548                 :            :           // nothing to do for other tags
     549                 :            :           default:
     550                 :    3232491 :             break;
     551                 :            :           }
     552                 :            :       }
     553         [ +  - ]:    3624555 :     while (dwarf_siblingof(&child, &child) == 0);
     554                 :     393799 : }
     555                 :            : 
     556                 :            : 
     557                 :            : void
     558                 :     111376 : dwflpp::iterate_over_inline_instances (int (* callback)(Dwarf_Die * die, void * arg),
     559                 :            :                                        void * data)
     560                 :            : {
     561         [ -  + ]:     111376 :   assert (function);
     562         [ -  + ]:     111376 :   assert (func_is_inline ());
     563                 :            : 
     564         [ +  + ]:     111376 :   if (cu_inl_function_cache_done.insert(cu->addr).second)
     565                 :       1735 :     cache_inline_instances(cu);
     566                 :            : 
     567                 :     111376 :   vector<Dwarf_Die>* v = cu_inl_function_cache[function->addr];
     568         [ +  + ]:     111376 :   if (!v)
     569                 :     111376 :     return;
     570                 :            : 
     571 [ +  - ][ +  - ]:     295020 :   for (vector<Dwarf_Die>::iterator i = v->begin(); i != v->end(); ++i)
         [ +  - ][ +  + ]
     572                 :            :     {
     573         [ +  - ]:     213596 :       int rc = (*callback)(&*i, data);
     574         [ +  - ]:     213596 :       assert_no_interrupts();
     575         [ -  + ]:     213596 :       if (rc != DWARF_CB_OK)
     576                 :          0 :         break;
     577                 :            :     }
     578                 :            : }
     579                 :            : 
     580                 :            : 
     581                 :            : void
     582                 :    6247086 : dwflpp::cache_die_parents(cu_die_parent_cache_t* parents, Dwarf_Die* die)
     583                 :            : {
     584                 :            :   // Record and recurse through DIEs we care about
     585                 :            :   Dwarf_Die child, import;
     586 [ +  - ][ +  + ]:    6247086 :   if (dwarf_child(die, &child) == 0)
     587         [ +  + ]:   42063955 :     do
     588                 :            :       {
     589         [ +  - ]:   42063955 :         switch (dwarf_tag (&child))
           [ +  +  -  + ]
     590                 :            :           {
     591                 :            :           // normal tags to recurse
     592                 :            :           case DW_TAG_compile_unit:
     593                 :            :           case DW_TAG_module:
     594                 :            :           case DW_TAG_lexical_block:
     595                 :            :           case DW_TAG_with_stmt:
     596                 :            :           case DW_TAG_catch_block:
     597                 :            :           case DW_TAG_try_block:
     598                 :            :           case DW_TAG_entry_point:
     599                 :            :           case DW_TAG_inlined_subroutine:
     600                 :            :           case DW_TAG_subprogram:
     601                 :            :           case DW_TAG_namespace:
     602                 :            :           case DW_TAG_class_type:
     603                 :            :           case DW_TAG_structure_type:
     604 [ +  - ][ +  - ]:    6237602 :             parents->insert(make_pair(child.addr, *die));
     605         [ +  - ]:    6237602 :             cache_die_parents(parents, &child);
     606                 :    6237602 :             break;
     607                 :            : 
     608                 :            :           // record only, nothing to recurse
     609                 :            :           case DW_TAG_label:
     610 [ +  - ][ +  - ]:     118334 :             parents->insert(make_pair(child.addr, *die));
     611                 :     118334 :             break;
     612                 :            : 
     613                 :            :           // imported dies should be followed
     614                 :            :           case DW_TAG_imported_unit:
     615 [ #  # ][ #  # ]:          0 :             if (dwarf_attr_die(&child, DW_AT_import, &import))
     616                 :            :               {
     617 [ #  # ][ #  # ]:          0 :                 parents->insert(make_pair(import.addr, *die));
     618         [ #  # ]:          0 :                 cache_die_parents(parents, &import);
     619                 :            :               }
     620                 :          0 :             break;
     621                 :            : 
     622                 :            :           // nothing to do for other tags
     623                 :            :           default:
     624                 :   35708019 :             break;
     625                 :            :           }
     626                 :            :       }
     627         [ +  - ]:   42063955 :     while (dwarf_siblingof(&child, &child) == 0);
     628                 :    6247086 : }
     629                 :            : 
     630                 :            : 
     631                 :            : cu_die_parent_cache_t*
     632                 :      67022 : dwflpp::get_die_parents()
     633                 :            : {
     634         [ -  + ]:      67022 :   assert (cu);
     635                 :            : 
     636                 :      67022 :   cu_die_parent_cache_t *& parents = cu_die_parent_cache[cu->addr];
     637         [ +  + ]:      67022 :   if (!parents)
     638                 :            :     {
     639 [ +  - ][ +  - ]:       9484 :       parents = new cu_die_parent_cache_t;
     640                 :       9484 :       cache_die_parents(parents, cu);
     641         [ -  + ]:       9484 :       if (sess.verbose > 4)
     642 [ #  # ][ #  # ]:          0 :         clog << _F("die parent cache %s:%s size %zu", module_name.c_str(),
         [ #  # ][ #  # ]
     643         [ #  # ]:          0 :                    cu_name().c_str(), parents->size()) << endl;
     644                 :            :     }
     645                 :      67022 :   return parents;
     646                 :            : }
     647                 :            : 
     648                 :            : 
     649                 :            : vector<Dwarf_Die>
     650                 :        684 : dwflpp::getscopes_die(Dwarf_Die* die)
     651                 :            : {
     652         [ +  - ]:        684 :   cu_die_parent_cache_t *parents = get_die_parents();
     653                 :            : 
     654         [ +  - ]:        684 :   vector<Dwarf_Die> scopes;
     655                 :        684 :   Dwarf_Die *scope = die;
     656         [ +  - ]:        684 :   cu_die_parent_cache_t::iterator it;
     657         [ +  + ]:       2066 :   do
     658                 :            :     {
     659         [ +  - ]:       2066 :       scopes.push_back(*scope);
     660         [ +  - ]:       2066 :       it = parents->find(scope->addr);
     661         [ +  - ]:       2066 :       scope = &it->second;
     662                 :            :     }
     663         [ +  - ]:       2066 :   while (it != parents->end());
     664                 :            : 
     665                 :            : #ifdef DEBUG_DWFLPP_GETSCOPES
     666                 :            :   Dwarf_Die *dscopes = NULL;
     667                 :            :   int nscopes = dwarf_getscopes_die(die, &dscopes);
     668                 :            : 
     669                 :            :   assert(nscopes == (int)scopes.size());
     670                 :            :   for (unsigned i = 0; i < scopes.size(); ++i)
     671                 :            :     assert(scopes[i].addr == dscopes[i].addr);
     672                 :            :   free(dscopes);
     673                 :            : #endif
     674                 :            : 
     675                 :        684 :   return scopes;
     676                 :            : }
     677                 :            : 
     678                 :            : 
     679                 :            : std::vector<Dwarf_Die>
     680                 :      66338 : dwflpp::getscopes(Dwarf_Die* die)
     681                 :            : {
     682         [ +  - ]:      66338 :   cu_die_parent_cache_t *parents = get_die_parents();
     683                 :            : 
     684         [ +  - ]:      66338 :   vector<Dwarf_Die> scopes;
     685                 :            : 
     686                 :            :   Dwarf_Die origin;
     687                 :      66338 :   Dwarf_Die *scope = die;
     688         [ +  - ]:      66338 :   cu_die_parent_cache_t::iterator it;
     689         [ +  + ]:     132714 :   do
     690                 :            :     {
     691         [ +  - ]:     132714 :       scopes.push_back(*scope);
     692 [ +  - ][ +  + ]:     133007 :       if (dwarf_tag(scope) == DW_TAG_inlined_subroutine &&
         [ +  - ][ +  + ]
     693         [ +  - ]:        293 :           dwarf_attr_die(scope, DW_AT_abstract_origin, &origin))
     694                 :        293 :         scope = &origin;
     695                 :            : 
     696         [ +  - ]:     132714 :       it = parents->find(scope->addr);
     697         [ +  - ]:     132714 :       scope = &it->second;
     698                 :            :     }
     699         [ +  - ]:     132714 :   while (it != parents->end());
     700                 :            : 
     701                 :            : #ifdef DEBUG_DWFLPP_GETSCOPES
     702                 :            :   // there isn't an exact libdw equivalent, but if dwarf_getscopes on the
     703                 :            :   // entrypc returns the same first die, then all the scopes should match
     704                 :            :   Dwarf_Addr pc;
     705                 :            :   if (die_entrypc(die, &pc))
     706                 :            :     {
     707                 :            :       Dwarf_Die *dscopes = NULL;
     708                 :            :       int nscopes = dwarf_getscopes(cu, pc, &dscopes);
     709                 :            :       if (nscopes > 0 && dscopes[0].addr == die->addr)
     710                 :            :         {
     711                 :            :           assert(nscopes == (int)scopes.size());
     712                 :            :           for (unsigned i = 0; i < scopes.size(); ++i)
     713                 :            :             assert(scopes[i].addr == dscopes[i].addr);
     714                 :            :         }
     715                 :            :       free(dscopes);
     716                 :            :     }
     717                 :            : #endif
     718                 :            : 
     719                 :      66338 :   return scopes;
     720                 :            : }
     721                 :            : 
     722                 :            : 
     723                 :            : std::vector<Dwarf_Die>
     724                 :         25 : dwflpp::getscopes(Dwarf_Addr pc)
     725                 :            : {
     726                 :            :   // The die_parent_cache doesn't help us without knowing where the pc is
     727                 :            :   // contained, so we have to do this one the old fashioned way.
     728                 :            : 
     729         [ -  + ]:         25 :   assert (cu);
     730                 :            : 
     731         [ +  - ]:         25 :   vector<Dwarf_Die> scopes;
     732                 :            : 
     733                 :            :   Dwarf_Die* dwarf_scopes;
     734         [ +  - ]:         25 :   int nscopes = dwarf_getscopes(cu, pc, &dwarf_scopes);
     735         [ +  - ]:         25 :   if (nscopes > 0)
     736                 :            :     {
     737         [ +  - ]:         25 :       scopes.assign(dwarf_scopes, dwarf_scopes + nscopes);
     738                 :         25 :       free(dwarf_scopes);
     739                 :            :     }
     740                 :            : 
     741                 :            : #ifdef DEBUG_DWFLPP_GETSCOPES
     742                 :            :   // check that getscopes on the starting die gets the same result
     743                 :            :   if (!scopes.empty())
     744                 :            :     {
     745                 :            :       vector<Dwarf_Die> other = getscopes(&scopes[0]);
     746                 :            :       assert(scopes.size() == other.size());
     747                 :            :       for (unsigned i = 0; i < scopes.size(); ++i)
     748                 :            :         assert(scopes[i].addr == other[i].addr);
     749                 :            :     }
     750                 :            : #endif
     751                 :            : 
     752                 :         25 :   return scopes;
     753                 :            : }
     754                 :            : 
     755                 :            : 
     756                 :            : Dwarf_Die*
     757                 :          0 : dwflpp::get_parent_scope(Dwarf_Die* die)
     758                 :            : {
     759                 :            :   Dwarf_Die specification;
     760 [ #  # ][ #  # ]:          0 :   if (dwarf_attr_die(die, DW_AT_specification, &specification))
     761                 :          0 :     die = &specification;
     762                 :            : 
     763         [ #  # ]:          0 :   cu_die_parent_cache_t *parents = get_die_parents();
     764         [ #  # ]:          0 :   cu_die_parent_cache_t::iterator it = parents->find(die->addr);
     765 [ #  # ][ #  # ]:          0 :   while (it != parents->end())
     766                 :            :     {
     767         [ #  # ]:          0 :       Dwarf_Die* scope = &it->second;
     768 [ #  # ][ #  # ]:          0 :       switch (dwarf_tag (scope))
     769                 :            :         {
     770                 :            :         case DW_TAG_namespace:
     771                 :            :         case DW_TAG_class_type:
     772                 :            :         case DW_TAG_structure_type:
     773                 :          0 :           return scope;
     774                 :            : 
     775                 :            :         default:
     776                 :          0 :           break;
     777                 :            :         }
     778         [ #  # ]:          0 :       it = parents->find(scope->addr);
     779                 :            :     }
     780                 :          0 :   return NULL;
     781                 :            : }
     782                 :            : 
     783                 :            : static const char*
     784                 :   80567326 : cache_type_prefix(Dwarf_Die* type)
     785                 :            : {
     786   [ +  +  +  + ]:   80567326 :   switch (dwarf_tag(type))
     787                 :            :     {
     788                 :            :     case DW_TAG_enumeration_type:
     789                 :    4544356 :       return "enum ";
     790                 :            :     case DW_TAG_structure_type:
     791                 :            :     case DW_TAG_class_type:
     792                 :            :       // treating struct/class as equals
     793                 :   49442489 :       return "struct ";
     794                 :            :     case DW_TAG_union_type:
     795                 :     788072 :       return "union ";
     796                 :            :     }
     797                 :   80567326 :   return "";
     798                 :            : }
     799                 :            : 
     800                 :            : /* GCC might generate a struct/class without DW_AT_declaration,
     801                 :            :    but that only contains members which have DW_AT_declaration
     802                 :            :    set.  We aren't interested in those.  PR14434 (GCC bug #54181).  */
     803                 :            : static bool
     804                 :   80567192 : has_only_decl_members (Dwarf_Die *die)
     805                 :            : {
     806                 :            :   Dwarf_Die child, import;
     807 [ +  - ][ +  + ]:   80567192 :   if (dwarf_child(die, &child) != 0)
     808                 :   26297425 :     return false; /* no members */
     809                 :            : 
     810         [ +  + ]:        904 :   do
     811                 :            :     {
     812 [ +  - ][ +  + ]:   54270532 :       if (! dwarf_hasattr(&child, DW_AT_declaration))
     813                 :   54269625 :         return false; /* real member found.  */
     814         [ +  - ]:        907 :       int tag = dwarf_tag(&child);
     815 [ +  - ][ +  - ]:        911 :       if ((tag == DW_TAG_namespace
         [ +  + ][ +  + ]
                 [ +  + ]
     816                 :            :            || tag == DW_TAG_structure_type
     817                 :            :            || tag == DW_TAG_class_type)
     818         [ +  - ]:          4 :           && ! has_only_decl_members (&child))
     819                 :          3 :         return false; /* real grand child member found.  */
     820                 :            : 
     821                 :            :       // Unlikely to ever happen, but if there is an imported unit
     822                 :            :       // then check its children as if they are children of this DIE.
     823 [ -  + ][ #  # ]:        904 :       if (tag == DW_TAG_imported_unit
         [ #  # ][ -  + ]
     824         [ #  # ]:          0 :           && dwarf_attr_die(&child, DW_AT_import, &import)
     825         [ #  # ]:          0 :           && ! has_only_decl_members (&import))
     826                 :          0 :         return false;
     827                 :            :     }
     828         [ +  - ]:        904 :   while (dwarf_siblingof(&child, &child) == 0);
     829                 :            : 
     830                 :   80567192 :   return true; /* Tried all children and grandchildren. */
     831                 :            : }
     832                 :            : 
     833                 :            : int
     834                 :  108163870 : dwflpp::global_alias_caching_callback(Dwarf_Die *die, bool has_inner_types,
     835                 :            :                                       const string& prefix, void *arg)
     836                 :            : {
     837                 :  108163870 :   cu_type_cache_t *cache = static_cast<cu_type_cache_t*>(arg);
     838                 :  108163870 :   const char *name = dwarf_diename(die);
     839                 :            : 
     840         [ +  + ]:  188731058 :   if (!name || dwarf_hasattr(die, DW_AT_declaration)
           [ +  +  +  + ]
                 [ +  + ]
     841                 :   80567188 :       || has_only_decl_members(die))
     842                 :   27596820 :     return DWARF_CB_OK;
     843                 :            : 
     844                 :   80567050 :   int tag = dwarf_tag(die);
     845 [ +  + ][ +  + ]:   80567050 :   if (has_inner_types && (tag == DW_TAG_namespace
         [ +  + ][ +  + ]
     846                 :            :                           || tag == DW_TAG_structure_type
     847                 :            :                           || tag == DW_TAG_class_type))
     848                 :            :     iterate_over_types(die, has_inner_types, prefix + name + "::",
     849 [ +  - ][ +  - ]:      10089 :                        global_alias_caching_callback, arg);
                 [ +  - ]
     850                 :            : 
     851         [ +  + ]:   80567050 :   if (tag != DW_TAG_namespace)
     852                 :            :     {
     853 [ +  - ][ +  - ]:   80566856 :       string type_name = prefix + cache_type_prefix(die) + name;
         [ +  - ][ +  - ]
     854 [ +  - ][ +  - ]:   80566856 :       if (cache->find(type_name) == cache->end())
                 [ +  - ]
     855 [ +  - ][ +  - ]:   80566856 :         (*cache)[type_name] = *die;
     856                 :            :     }
     857                 :            : 
     858                 :  108163870 :   return DWARF_CB_OK;
     859                 :            : }
     860                 :            : 
     861                 :            : int
     862                 :   13262408 : dwflpp::global_alias_caching_callback_cus(Dwarf_Die *die, void *arg)
     863                 :            : {
     864                 :            :   mod_cu_type_cache_t *global_alias_cache;
     865                 :   13262408 :   global_alias_cache = &static_cast<dwflpp *>(arg)->global_alias_cache;
     866                 :            : 
     867                 :   13262408 :   cu_type_cache_t *v = (*global_alias_cache)[die->addr];
     868         [ +  + ]:   13262408 :   if (v != 0)
     869                 :   12986105 :     return DWARF_CB_OK;
     870                 :            : 
     871 [ +  - ][ +  - ]:     276303 :   v = new cu_type_cache_t;
     872                 :     276303 :   (*global_alias_cache)[die->addr] = v;
     873                 :     276303 :   iterate_over_globals(die, global_alias_caching_callback, v);
     874                 :            : 
     875                 :   13262408 :   return DWARF_CB_OK;
     876                 :            : }
     877                 :            : 
     878                 :            : Dwarf_Die *
     879                 :      20477 : dwflpp::declaration_resolve_other_cus(const string& name)
     880                 :            : {
     881                 :      20477 :   iterate_over_cus(global_alias_caching_callback_cus, this, true);
     882 [ +  - ][ +  - ]:   17327320 :   for (mod_cu_type_cache_t::iterator i = global_alias_cache.begin();
                 [ +  + ]
     883         [ +  - ]:    8663660 :          i != global_alias_cache.end(); ++i)
     884                 :            :     {
     885                 :    8652111 :       cu_type_cache_t *v = (*i).second;
     886 [ +  - ][ +  - ]:    8652111 :       if (v->find(name) != v->end())
                 [ +  + ]
     887         [ +  - ]:       8928 :         return & ((*v)[name]);
     888                 :            :     }
     889                 :            : 
     890                 :      20477 :   return NULL;
     891                 :            : }
     892                 :            : 
     893                 :            : Dwarf_Die *
     894                 :        470 : dwflpp::declaration_resolve(const string& name)
     895                 :            : {
     896                 :        470 :   cu_type_cache_t *v = global_alias_cache[cu->addr];
     897         [ +  + ]:        470 :   if (v == 0) // need to build the cache, just once per encountered module/cu
     898                 :            :     {
     899 [ +  - ][ +  - ]:         15 :       v = new cu_type_cache_t;
     900                 :         15 :       global_alias_cache[cu->addr] = v;
     901                 :         15 :       iterate_over_globals(cu, global_alias_caching_callback, v);
     902         [ -  + ]:         15 :       if (sess.verbose > 4)
     903 [ #  # ][ #  # ]:          0 :         clog << _F("global alias cache %s:%s size %zu", module_name.c_str(),
         [ #  # ][ #  # ]
     904         [ #  # ]:          0 :                    cu_name().c_str(), v->size()) << endl;
     905                 :            :     }
     906                 :            : 
     907                 :            :   // XXX: it may be desirable to search other modules' declarations
     908                 :            :   // too, in case a module/shared-library processes a
     909                 :            :   // forward-declared pointer type only, where the actual definition
     910                 :            :   // may only be in vmlinux or the application.
     911                 :            : 
     912 [ +  - ][ +  - ]:        470 :   if (v->find(name) == v->end())
     913                 :        470 :     return declaration_resolve_other_cus(name);
     914                 :            : 
     915                 :        470 :   return & ((*v)[name]);
     916                 :            : }
     917                 :            : 
     918                 :            : Dwarf_Die *
     919                 :        470 : dwflpp::declaration_resolve(Dwarf_Die *type)
     920                 :            : {
     921         [ +  - ]:        470 :   const char* name = dwarf_diename(type);
     922         [ -  + ]:        470 :   if (!name)
     923                 :          0 :     return NULL;
     924                 :            : 
     925 [ +  - ][ +  - ]:        470 :   string type_name = cache_type_prefix(type) + string(name);
         [ +  - ][ +  - ]
     926 [ +  - ][ +  - ]:        470 :   return declaration_resolve(type_name);
     927                 :            : }
     928                 :            : 
     929                 :            : 
     930                 :            : int
     931                 :   36186619 : dwflpp::cu_function_caching_callback (Dwarf_Die* func, void *arg)
     932                 :            : {
     933                 :   36186619 :   cu_function_cache_t* v = static_cast<cu_function_cache_t*>(arg);
     934                 :   36186619 :   const char *name = dwarf_diename(func);
     935         [ -  + ]:   36186619 :   if (!name)
     936                 :          0 :     return DWARF_CB_OK;
     937                 :            : 
     938 [ +  - ][ +  - ]:   36186619 :   v->insert(make_pair(string(name), *func));
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
     939                 :   36186619 :   return DWARF_CB_OK;
     940                 :            : }
     941                 :            : 
     942                 :            : 
     943                 :            : int
     944                 :     484963 : dwflpp::mod_function_caching_callback (Dwarf_Die* cu, void *arg)
     945                 :            : {
     946                 :     484963 :   dwarf_getfuncs (cu, cu_function_caching_callback, arg, 0);
     947                 :     484963 :   return DWARF_CB_OK;
     948                 :            : }
     949                 :            : 
     950                 :            : 
     951                 :            : int
     952                 :      97912 : dwflpp::iterate_over_functions (int (* callback)(Dwarf_Die * func, base_query * q),
     953                 :            :                                 base_query * q, const string& function)
     954                 :            : {
     955                 :      97912 :   int rc = DWARF_CB_OK;
     956         [ -  + ]:      97912 :   assert (module);
     957         [ -  + ]:      97912 :   assert (cu);
     958                 :            : 
     959         [ +  - ]:      97912 :   cu_function_cache_t *v = cu_function_cache[cu->addr];
     960         [ +  + ]:      97912 :   if (v == 0)
     961                 :            :     {
     962 [ +  - ][ +  - ]:      44199 :       v = new cu_function_cache_t;
     963         [ +  - ]:      44199 :       cu_function_cache[cu->addr] = v;
     964         [ +  - ]:      44199 :       dwarf_getfuncs (cu, cu_function_caching_callback, v, 0);
     965         [ -  + ]:      44199 :       if (sess.verbose > 4)
     966 [ #  # ][ #  # ]:          0 :         clog << _F("function cache %s:%s size %zu", module_name.c_str(),
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
     967         [ #  # ]:          0 :                    cu_name().c_str(), v->size()) << endl;
     968         [ +  - ]:      44199 :       mod_info->update_symtab(v);
     969                 :            :     }
     970                 :            : 
     971         [ +  - ]:      97912 :   cu_function_cache_t::iterator it;
     972         [ +  - ]:      97912 :   cu_function_cache_range_t range = v->equal_range(function);
     973         [ +  + ]:      97912 :   if (range.first != range.second)
     974                 :            :     {
     975 [ +  - ][ +  + ]:      60843 :       for (it = range.first; it != range.second; ++it)
     976                 :            :         {
     977         [ +  - ]:      30545 :           Dwarf_Die& die = it->second;
     978         [ -  + ]:      30545 :           if (sess.verbose > 4)
     979 [ #  # ][ #  # ]:          0 :             clog << _F("function cache %s:%s hit %s", module_name.c_str(),
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
     980         [ #  # ]:          0 :                        cu_name().c_str(), function.c_str()) << endl;  
     981         [ +  - ]:      30545 :           rc = (*callback)(& die, q);
     982         [ -  + ]:      30545 :           if (rc != DWARF_CB_OK) break;
     983                 :            :         }
     984                 :            :     }
     985 [ +  - ][ -  + ]:      67614 :   else if (startswith(function, "_Z"))
     986                 :            :     {
     987                 :            :       // C++ names are mangled starting with a "_Z" prefix.  Most of the time
     988                 :            :       // we can discover the mangled name from a die's MIPS_linkage_name
     989                 :            :       // attribute, so we read that to match against the user's function
     990                 :            :       // pattern.  Note that this isn't perfect, as not all will have that
     991                 :            :       // attribute (notably ctors and dtors), but we do what we can...
     992 [ #  # ][ #  # ]:          0 :       for (it = v->begin(); it != v->end(); ++it)
         [ #  # ][ #  # ]
     993                 :            :         {
     994         [ #  # ]:          0 :           if (pending_interrupts) return DWARF_CB_ABORT;
     995         [ #  # ]:          0 :           Dwarf_Die& die = it->second;
     996                 :          0 :           const char* linkage_name = NULL;
     997 [ #  # ][ #  # ]:          0 :           if ((linkage_name = dwarf_linkage_name (&die))
         [ #  # ][ #  # ]
     998 [ #  # ][ #  # ]:          0 :               && function_name_matches_pattern (linkage_name, function))
         [ #  # ][ #  # ]
                 [ #  # ]
           [ #  #  #  # ]
     999                 :            :             {
    1000         [ #  # ]:          0 :               if (sess.verbose > 4)
    1001 [ #  # ][ #  # ]:          0 :                 clog << _F("function cache %s:%s match %s vs %s", module_name.c_str(),
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
    1002         [ #  # ]:          0 :                            cu_name().c_str(), linkage_name, function.c_str()) << endl;
    1003                 :            : 
    1004         [ #  # ]:          0 :               rc = (*callback)(& die, q);
    1005         [ #  # ]:          0 :               if (rc != DWARF_CB_OK) break;
    1006                 :            :             }
    1007                 :            :         }
    1008                 :            :     }
    1009 [ +  - ][ +  + ]:      67614 :   else if (name_has_wildcard (function))
    1010                 :            :     {
    1011 [ +  - ][ +  - ]:    2815093 :       for (it = v->begin(); it != v->end(); ++it)
         [ +  - ][ +  + ]
    1012                 :            :         {
    1013         [ -  + ]:    2774005 :           if (pending_interrupts) return DWARF_CB_ABORT;
    1014         [ +  - ]:    2774005 :           const string& func_name = it->first;
    1015         [ +  - ]:    2774005 :           Dwarf_Die& die = it->second;
    1016 [ +  - ][ +  + ]:    2774005 :           if (function_name_matches_pattern (func_name, function))
    1017                 :            :             {
    1018         [ -  + ]:     641744 :               if (sess.verbose > 4)
    1019 [ #  # ][ #  # ]:          0 :                 clog << _F("function cache %s:%s match %s vs %s", module_name.c_str(),
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
    1020         [ #  # ]:          0 :                            cu_name().c_str(), func_name.c_str(), function.c_str()) << endl;
    1021                 :            : 
    1022         [ +  - ]:     641744 :               rc = (*callback)(& die, q);
    1023         [ -  + ]:     641744 :               if (rc != DWARF_CB_OK) break;
    1024                 :            :             }
    1025                 :            :         }
    1026                 :            :     }
    1027                 :            :   else // not a linkage name or wildcard and no match in this CU
    1028                 :            :     {
    1029                 :            :       // do nothing
    1030                 :            :     }
    1031                 :      97912 :   return rc;
    1032                 :            : }
    1033                 :            : 
    1034                 :            : 
    1035                 :            : int
    1036                 :      45652 : dwflpp::iterate_single_function (int (* callback)(Dwarf_Die * func, base_query * q),
    1037                 :            :                                  base_query * q, const string& function)
    1038                 :            : {
    1039                 :      45652 :   int rc = DWARF_CB_OK;
    1040         [ -  + ]:      45652 :   assert (module);
    1041                 :            : 
    1042         [ +  - ]:      45652 :   get_module_dwarf(false);
    1043         [ -  + ]:      45652 :   if (!module_dwarf)
    1044                 :          0 :     return rc;
    1045                 :            : 
    1046         [ +  - ]:      45652 :   cu_function_cache_t *v = mod_function_cache[module_dwarf];
    1047         [ +  + ]:      45652 :   if (v == 0)
    1048                 :            :     {
    1049 [ +  - ][ +  - ]:        374 :       v = new cu_function_cache_t;
    1050         [ +  - ]:        374 :       mod_function_cache[module_dwarf] = v;
    1051         [ +  - ]:        374 :       iterate_over_cus (mod_function_caching_callback, v, false);
    1052         [ -  + ]:        374 :       if (sess.verbose > 4)
    1053 [ #  # ][ #  # ]:          0 :         clog << _F("module function cache %s size %zu", module_name.c_str(),
         [ #  # ][ #  # ]
    1054         [ #  # ]:          0 :                    v->size()) << endl;
    1055         [ +  - ]:        374 :       mod_info->update_symtab(v);
    1056                 :            :     }
    1057                 :            : 
    1058         [ +  - ]:      45652 :   cu_function_cache_t::iterator it;
    1059         [ +  - ]:      45652 :   cu_function_cache_range_t range = v->equal_range(function);
    1060         [ +  + ]:      45652 :   if (range.first != range.second)
    1061                 :            :     {
    1062 [ +  - ][ +  + ]:      71777 :       for (it = range.first; it != range.second; ++it)
    1063                 :            :         {
    1064                 :            :           Dwarf_Die cu_mem;
    1065         [ +  - ]:      42049 :           Dwarf_Die& die = it->second;
    1066         [ -  + ]:      42049 :           if (sess.verbose > 4)
    1067 [ #  # ][ #  # ]:          0 :             clog << _F("module function cache %s hit %s", module_name.c_str(),
         [ #  # ][ #  # ]
                 [ #  # ]
    1068         [ #  # ]:          0 :                        function.c_str()) << endl;
    1069                 :            : 
    1070                 :            :           // since we're iterating out of cu-context, we need each focus
    1071 [ +  - ][ +  - ]:      42049 :           focus_on_cu(dwarf_diecu(&die, &cu_mem, NULL, NULL));
    1072                 :            : 
    1073         [ +  - ]:      42049 :           rc = (*callback)(& die, q);
    1074         [ +  - ]:      42049 :           if (rc != DWARF_CB_OK) break;
    1075                 :            :         }
    1076                 :            :     }
    1077                 :            : 
    1078                 :            :   // undo the focus_on_cu
    1079                 :      45652 :   this->cu = NULL;
    1080         [ +  - ]:      45652 :   this->function_name.clear();
    1081                 :      45652 :   this->function = NULL;
    1082                 :            : 
    1083                 :      45652 :   return rc;
    1084                 :            : }
    1085                 :            : 
    1086                 :            : 
    1087                 :            : /* This basically only goes one level down from the compile unit so it
    1088                 :            :  * only picks up top level stuff (i.e. nothing in a lower scope) */
    1089                 :            : int
    1090                 :     276318 : dwflpp::iterate_over_globals (Dwarf_Die *cu_die,
    1091                 :            :                               int (* callback)(Dwarf_Die *, bool,
    1092                 :            :                                                const string&, void *),
    1093                 :            :                               void * data)
    1094                 :            : {
    1095         [ -  + ]:     276318 :   assert (cu_die);
    1096                 :     276319 :   assert (dwarf_tag(cu_die) == DW_TAG_compile_unit
    1097                 :            :           || dwarf_tag(cu_die) == DW_TAG_type_unit
    1098   [ +  +  -  +  :     276319 :           || dwarf_tag(cu_die) == DW_TAG_partial_unit);
                   #  # ]
    1099                 :            : 
    1100                 :            :   // Ignore partial_unit, if they get imported by a real unit, then
    1101                 :            :   // iterate_over_types will traverse them.
    1102         [ -  + ]:     276318 :   if (dwarf_tag(cu_die) == DW_TAG_partial_unit)
    1103                 :          0 :     return DWARF_CB_OK;
    1104                 :            : 
    1105                 :            :   // If this is C++, recurse for any inner types
    1106                 :     276318 :   bool has_inner_types = dwarf_srclang(cu_die) == DW_LANG_C_plus_plus;
    1107                 :            : 
    1108 [ +  - ][ +  - ]:     276318 :   return iterate_over_types(cu_die, has_inner_types, "", callback, data);
                 [ +  - ]
    1109                 :            : }
    1110                 :            : 
    1111                 :            : 
    1112                 :            : int
    1113                 :     286407 : dwflpp::iterate_over_types (Dwarf_Die *top_die,
    1114                 :            :                             bool has_inner_types,
    1115                 :            :                             const string& prefix,
    1116                 :            :                             int (* callback)(Dwarf_Die *, bool,
    1117                 :            :                                              const string&, void *),
    1118                 :            :                             void * data)
    1119                 :            : {
    1120                 :     286407 :   int rc = DWARF_CB_OK;
    1121                 :            :   Dwarf_Die die, import;
    1122                 :            : 
    1123         [ -  + ]:     286407 :   assert (top_die);
    1124                 :            : 
    1125 [ +  - ][ +  + ]:     286407 :   if (dwarf_child(top_die, &die) != 0)
    1126                 :      10964 :     return rc;
    1127                 :            : 
    1128 [ +  - ][ +  + ]:  635857122 :   do
                 [ +  + ]
    1129                 :            :     /* We're only currently looking for named types,
    1130                 :            :      * although other types of declarations exist */
    1131         [ +  - ]:  317928561 :     switch (dwarf_tag(&die))
              [ +  -  + ]
    1132                 :            :       {
    1133                 :            :       case DW_TAG_base_type:
    1134                 :            :       case DW_TAG_enumeration_type:
    1135                 :            :       case DW_TAG_structure_type:
    1136                 :            :       case DW_TAG_class_type:
    1137                 :            :       case DW_TAG_typedef:
    1138                 :            :       case DW_TAG_union_type:
    1139                 :            :       case DW_TAG_namespace:
    1140         [ +  - ]:  108163870 :         rc = (*callback)(&die, has_inner_types, prefix, data);
    1141                 :  108163870 :         break;
    1142                 :            : 
    1143                 :            :       case DW_TAG_imported_unit:
    1144                 :            :         // Follow the imported_unit and iterate over its contents
    1145                 :            :         // (either a partial_unit or a full compile_unit), all its
    1146                 :            :         // children should be treated as if they appear in this place.
    1147 [ #  # ][ #  # ]:          0 :         if (dwarf_attr_die(&die, DW_AT_import, &import))
    1148                 :            :           rc = iterate_over_types(&import, has_inner_types, prefix,
    1149         [ #  # ]:          0 :                                   callback, data);
    1150                 :          0 :         break;
    1151                 :            :       }
    1152         [ +  - ]:  317928561 :   while (rc == DWARF_CB_OK && dwarf_siblingof(&die, &die) == 0);
    1153                 :            : 
    1154                 :     286407 :   return rc;
    1155                 :            : }
    1156                 :            : 
    1157                 :            : 
    1158                 :            : /* For each notes section in the current module call 'callback', use
    1159                 :            :  * 'data' for the notes buffer and pass 'object' back in case
    1160                 :            :  * 'callback' is a method */
    1161                 :            : 
    1162                 :            : int
    1163                 :          3 : dwflpp::iterate_over_notes (void *object, void (*callback)(void *object, int type, const char *data, size_t len))
    1164                 :            : {
    1165                 :            :   Dwarf_Addr bias;
    1166                 :            :   // Note we really want the actual elf file, not the dwarf .debug file.
    1167                 :            :   // Older binutils had a bug where they mangled the SHT_NOTE type during
    1168                 :            :   // --keep-debug.
    1169         [ +  - ]:          3 :   Elf* elf = dwfl_module_getelf (module, &bias);
    1170                 :            :   size_t shstrndx;
    1171 [ +  - ][ -  + ]:          3 :   if (elf_getshdrstrndx (elf, &shstrndx))
    1172         [ #  # ]:          0 :     return elf_errno();
    1173                 :            : 
    1174                 :          3 :   Elf_Scn *scn = NULL;
    1175                 :            : 
    1176         [ +  - ]:          3 :   vector<Dwarf_Die> notes;
    1177                 :            : 
    1178 [ +  - ][ +  + ]:        126 :   while ((scn = elf_nextscn (elf, scn)) != NULL)
    1179                 :            :     {
    1180                 :            :       GElf_Shdr shdr;
    1181 [ +  - ][ -  + ]:        123 :       if (gelf_getshdr (scn, &shdr) == NULL)
    1182                 :          0 :           continue;
    1183         [ +  + ]:        123 :       switch (shdr.sh_type)
    1184                 :            :         {
    1185                 :            :         case SHT_NOTE:
    1186         [ +  + ]:          9 :           if (!(shdr.sh_flags & SHF_ALLOC))
    1187                 :            :             {
    1188         [ +  - ]:          3 :               Elf_Data *data = elf_getdata (scn, NULL);
    1189                 :            :               size_t next;
    1190                 :            :               GElf_Nhdr nhdr;
    1191                 :            :               size_t name_off;
    1192                 :            :               size_t desc_off;
    1193 [ +  - ][ +  + ]:         75 :               for (size_t offset = 0;
    1194                 :            :                    (next = gelf_getnote (data, offset, &nhdr, &name_off, &desc_off)) > 0;
    1195                 :            :                    offset = next)
    1196         [ +  - ]:         72 :                 (*callback) (object, nhdr.n_type, (const char*)((long)(data->d_buf) + (long)desc_off), nhdr.n_descsz);
    1197                 :            :             }
    1198                 :        123 :           break;
    1199                 :            :         }
    1200                 :            :     }
    1201         [ +  - ]:          3 :   return 0;
    1202                 :            : }
    1203                 :            : 
    1204                 :            : 
    1205                 :            : /* For each entry in the .dynamic section in the current module call 'callback'
    1206                 :            :  * returning 'object' in case 'callback' is a method */
    1207                 :            : 
    1208                 :            : void
    1209                 :          2 : dwflpp::iterate_over_libraries (void (*callback)(void *object, const char *arg), void *q)
    1210                 :            : {
    1211         [ +  - ]:          2 :   std::set<std::string> added;
    1212         [ +  - ]:          2 :   string interpreter;
    1213                 :            : 
    1214 [ +  - ][ -  + ]:          2 :   assert (this->module_name.length() != 0);
    1215                 :            : 
    1216                 :            :   Dwarf_Addr bias;
    1217                 :            : //  We cannot use this: dwarf_getelf (dwfl_module_getdwarf (module, &bias))
    1218         [ +  - ]:          2 :   Elf *elf = dwfl_module_getelf (module, &bias);
    1219                 :            : //  elf_getphdrnum (elf, &phnum) is not available in all versions of elfutils
    1220                 :            : //  needs libelf from elfutils 0.144+
    1221                 :          6 :   for (int i = 0; ; i++)
    1222                 :            :     {
    1223                 :            :       GElf_Phdr mem;
    1224                 :            :       GElf_Phdr *phdr;
    1225         [ +  - ]:          6 :       phdr = gelf_getphdr (elf, i, &mem);
    1226         [ +  - ]:          6 :       if (phdr == NULL)
    1227                 :            :         break;
    1228         [ +  + ]:          6 :       if (phdr->p_type == PT_INTERP)
    1229                 :            :         {
    1230                 :            :           size_t maxsize;
    1231         [ +  - ]:          2 :           char *filedata = elf_rawfile (elf, &maxsize);
    1232                 :            : 
    1233 [ +  - ][ +  - ]:          2 :           if (filedata != NULL && phdr->p_offset < maxsize)
    1234         [ +  - ]:          2 :             interpreter = (char*) (filedata + phdr->p_offset);
    1235                 :            :           break;
    1236                 :            :         }
    1237                 :            :     }
    1238                 :            : 
    1239 [ +  - ][ -  + ]:          2 :   if (interpreter.length() == 0)
    1240                 :            :     return;
    1241                 :            :   // If it gets cumbersome to maintain this whitelist, we could just check for
    1242                 :            :   // startswith("/lib/ld") || startswith("/lib64/ld"), and trust that no admin
    1243                 :            :   // would install untrustworthy loaders in those paths.
    1244                 :            :   // See also http://sourceware.org/git/?p=glibc.git;a=blob;f=shlib-versions;hb=HEAD
    1245 [ +  - ][ +  - ]:         18 :   if (interpreter != "/lib/ld.so.1"                     // s390, ppc
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ -  + ]
                 [ -  + ]
    1246         [ +  - ]:          2 :       && interpreter != "/lib/ld64.so.1"                // s390x, ppc64
    1247         [ +  - ]:          2 :       && interpreter != "/lib64/ld64.so.1"
    1248         [ +  - ]:          2 :       && interpreter != "/lib/ld-linux-ia64.so.2"       // ia64
    1249         [ +  - ]:          2 :       && interpreter != "/emul/ia32-linux/lib/ld-linux.so.2"
    1250         [ +  - ]:          2 :       && interpreter != "/lib64/ld-linux-x86-64.so.2"   // x8664
    1251         [ +  - ]:          2 :       && interpreter != "/lib/ld-linux.so.2"            // x86
    1252         [ +  - ]:          2 :       && interpreter != "/lib/ld-linux.so.3"            // arm
    1253         [ +  - ]:          2 :       && interpreter != "/lib/ld-linux-armhf.so.3"      // arm
    1254                 :            :       )
    1255                 :            :     {
    1256                 :          0 :       sess.print_warning (_F("module %s --ldd skipped: unsupported interpreter: %s",
    1257 [ #  # ][ #  # ]:          0 :                                module_name.c_str(), interpreter.c_str()));
         [ #  # ][ #  # ]
                 [ #  # ]
    1258                 :            :       return;
    1259                 :            :     }
    1260                 :            : 
    1261         [ +  - ]:          2 :   vector<string> ldd_command;
    1262 [ +  - ][ +  - ]:          2 :   ldd_command.push_back("/usr/bin/env");
                 [ +  - ]
    1263 [ +  - ][ +  - ]:          2 :   ldd_command.push_back("LD_TRACE_LOADED_OBJECTS=1");
                 [ +  - ]
    1264 [ +  - ][ +  - ]:          2 :   ldd_command.push_back("LD_WARN=yes");
                 [ +  - ]
    1265 [ +  - ][ +  - ]:          2 :   ldd_command.push_back("LD_BIND_NOW=yes");
                 [ +  - ]
    1266         [ +  - ]:          2 :   ldd_command.push_back(interpreter);
    1267         [ +  - ]:          2 :   ldd_command.push_back(module_name);
    1268                 :            : 
    1269                 :            :   FILE *fp;
    1270                 :            :   int child_fd;
    1271         [ +  - ]:          2 :   pid_t child = stap_spawn_piped(sess.verbose, ldd_command, NULL, &child_fd);
    1272 [ +  - ][ -  + ]:          2 :   if (child <= 0 || !(fp = fdopen(child_fd, "r")))
                 [ -  + ]
    1273 [ #  # ][ #  # ]:          0 :     clog << _F("library iteration on %s failed: %s",
         [ #  # ][ #  # ]
    1274         [ #  # ]:          0 :                module_name.c_str(), strerror(errno)) << endl;
    1275                 :            :   else
    1276                 :            :     {
    1277                 :         22 :       while (1) // this parsing loop borrowed from add_unwindsym_ldd
    1278                 :            :         {
    1279                 :            :           char linebuf[256];
    1280                 :         24 :           char *soname = 0;
    1281                 :         24 :           char *shlib = 0;
    1282                 :         24 :           unsigned long int addr = 0;
    1283                 :            : 
    1284         [ +  - ]:         24 :           char *line = fgets (linebuf, 256, fp);
    1285         [ +  + ]:         24 :           if (line == 0) break; // EOF or error
    1286                 :            : 
    1287                 :            : #if __GLIBC__ >2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 7)
    1288                 :            : #define MS_FMT "%ms"
    1289                 :            : #else
    1290                 :            : #define MS_FMT "%as"
    1291                 :            : #endif
    1292                 :            :           // Try soname => shlib (0xaddr)
    1293                 :            :           int nf = sscanf (line, MS_FMT " => " MS_FMT " (0x%lx)",
    1294                 :         22 :               &soname, &shlib, &addr);
    1295 [ +  + ][ -  + ]:         22 :           if (nf != 3 || shlib[0] != '/')
    1296                 :            :             {
    1297                 :            :               // Try shlib (0xaddr)
    1298                 :          2 :               nf = sscanf (line, " " MS_FMT " (0x%lx)", &shlib, &addr);
    1299 [ +  - ][ -  + ]:          2 :               if (nf != 2 || shlib[0] != '/')
    1300                 :          0 :                 continue; // fewer than expected fields, or bad shlib.
    1301                 :            :             }
    1302                 :            : 
    1303 [ +  - ][ +  - ]:         22 :           if (added.find (shlib) == added.end())
         [ +  - ][ +  - ]
                 [ +  - ]
    1304                 :            :             {
    1305         [ +  + ]:         22 :               if (sess.verbose > 2)
    1306                 :            :                 {
    1307 [ +  - ][ +  - ]:         11 :                   clog << _F("Added -d '%s", shlib);
                 [ +  - ]
    1308         [ +  + ]:         11 :                   if (nf == 3)
    1309 [ +  - ][ +  - ]:         10 :                     clog << _F("' due to '%s'", soname);
                 [ +  - ]
    1310                 :            :                   else
    1311         [ +  - ]:          1 :                     clog << "'";
    1312         [ +  - ]:         11 :                   clog << endl;
    1313                 :            :                 }
    1314 [ +  - ][ +  - ]:         22 :               added.insert (shlib);
                 [ +  - ]
    1315                 :            :             }
    1316                 :            : 
    1317                 :         22 :           free (soname);
    1318                 :         22 :           free (shlib);
    1319                 :            :         }
    1320 [ +  - ][ +  - ]:          2 :       if ((fclose(fp) || stap_waitpid(sess.verbose, child)))
         [ +  - ][ -  + ]
                 [ -  + ]
    1321 [ #  # ][ #  # ]:          0 :          sess.print_warning("failed to read libraries from " + module_name + ": " + strerror(errno));
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
    1322                 :            :     }
    1323                 :            : 
    1324 [ +  - ][ +  + ]:         48 :   for (std::set<std::string>::iterator it = added.begin();
    1325         [ +  - ]:         24 :       it != added.end();
    1326                 :            :       it++)
    1327                 :            :     {
    1328         [ +  - ]:         22 :       string modname = *it;
    1329 [ +  - ][ +  - ]:         22 :       (callback) (q, modname.c_str());
    1330 [ +  - ][ +  - ]:         24 :     }
         [ +  - ][ -  + ]
         [ +  - ][ +  - ]
    1331                 :            : }
    1332                 :            : 
    1333                 :            : 
    1334                 :            : /* For each plt section in the current module call 'callback', pass the plt entry
    1335                 :            :  * 'address' and 'name' back, and pass 'object' back in case 'callback' is a method */
    1336                 :            : 
    1337                 :            : int
    1338                 :         13 : dwflpp::iterate_over_plt (void *object, void (*callback)(void *object, const char *name, size_t addr))
    1339                 :            : {
    1340                 :            :   Dwarf_Addr load_addr;
    1341                 :            :   // Note we really want the actual elf file, not the dwarf .debug file.
    1342         [ +  - ]:         13 :   Elf* elf = dwfl_module_getelf (module, &load_addr);
    1343                 :            :   size_t shstrndx;
    1344 [ +  - ][ -  + ]:         13 :   assert (elf_getshdrstrndx (elf, &shstrndx) >= 0);
    1345                 :            : 
    1346                 :            :   // Get the load address
    1347                 :         37 :   for (int i = 0; ; i++)
    1348                 :            :     {
    1349                 :            :       GElf_Phdr mem;
    1350                 :            :       GElf_Phdr *phdr;
    1351         [ +  - ]:         37 :       phdr = gelf_getphdr (elf, i, &mem);
    1352         [ +  - ]:         37 :       if (phdr == NULL)
    1353                 :            :         break;
    1354         [ +  + ]:         37 :       if (phdr->p_type == PT_LOAD)
    1355                 :            :         {
    1356                 :         13 :           load_addr = phdr->p_vaddr;
    1357                 :            :           break;
    1358                 :            :         }
    1359                 :            :     }
    1360                 :            : 
    1361                 :            :   // Get the plt section header
    1362                 :         13 :   Elf_Scn *scn = NULL;
    1363                 :         13 :   GElf_Shdr *plt_shdr = NULL;
    1364                 :            :   GElf_Shdr plt_shdr_mem;
    1365 [ +  - ][ +  - ]:        145 :   while ((scn = elf_nextscn (elf, scn)))
    1366                 :            :     {
    1367         [ +  - ]:        145 :       plt_shdr = gelf_getshdr (scn, &plt_shdr_mem);
    1368         [ -  + ]:        145 :       assert (plt_shdr != NULL);
    1369 [ +  - ][ +  + ]:        145 :       if (strcmp (elf_strptr (elf, shstrndx, plt_shdr->sh_name), ".plt") == 0)
    1370                 :         13 :         break;
    1371                 :            :     }
    1372                 :            :         
    1373                 :            :   // Layout of the plt section
    1374                 :            :   int plt0_entry_size;
    1375                 :            :   int plt_entry_size;
    1376                 :            :   GElf_Ehdr ehdr_mem;
    1377         [ +  - ]:         13 :   GElf_Ehdr* em = gelf_getehdr (elf, &ehdr_mem);
    1378      [ -  -  + ]:         13 :   switch (em->e_machine)
    1379                 :            :   {
    1380                 :          0 :   case EM_386:    plt0_entry_size = 16; plt_entry_size = 16; break;
    1381                 :          0 :   case EM_X86_64: plt0_entry_size = 16; plt_entry_size = 16; break;
    1382                 :            :   case EM_PPC64:
    1383                 :            :   case EM_S390:
    1384                 :            :   case EM_PPC:
    1385                 :            :   default:
    1386 [ +  - ][ +  - ]:         13 :     throw semantic_error(".plt is not supported on this architecture");
    1387                 :            :   }
    1388                 :            : 
    1389                 :          0 :   scn = NULL;
    1390 [ #  # ][ #  # ]:          0 :   while ((scn = elf_nextscn (elf, scn)))
    1391                 :            :     {
    1392                 :            :       GElf_Shdr shdr_mem;
    1393         [ #  # ]:          0 :       GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
    1394                 :          0 :       bool have_rela = false;
    1395                 :          0 :       bool have_rel = false;
    1396                 :            : 
    1397         [ #  # ]:          0 :       if (shdr == NULL)
    1398                 :          0 :         continue;
    1399         [ #  # ]:          0 :       assert (shdr != NULL);
    1400                 :            : 
    1401 [ #  # ][ #  # ]:          0 :       if ((have_rela = (strcmp (elf_strptr (elf, shstrndx, shdr->sh_name), ".rela.plt") == 0))
         [ #  # ][ #  # ]
    1402         [ #  # ]:          0 :           || (have_rel = (strcmp (elf_strptr (elf, shstrndx, shdr->sh_name), ".rel.plt") == 0)))
    1403                 :            :         {
    1404                 :            :           /* Get the data of the section.  */
    1405         [ #  # ]:          0 :           Elf_Data *data = elf_getdata (scn, NULL);
    1406         [ #  # ]:          0 :           assert (data != NULL);
    1407                 :            :           /* Get the symbol table information.  */
    1408         [ #  # ]:          0 :           Elf_Scn *symscn = elf_getscn (elf, shdr->sh_link);
    1409                 :            :           GElf_Shdr symshdr_mem;
    1410         [ #  # ]:          0 :           GElf_Shdr *symshdr = gelf_getshdr (symscn, &symshdr_mem);
    1411         [ #  # ]:          0 :           assert (symshdr != NULL);
    1412         [ #  # ]:          0 :           Elf_Data *symdata = elf_getdata (symscn, NULL);
    1413         [ #  # ]:          0 :           assert (symdata != NULL);
    1414                 :            : 
    1415                 :          0 :           unsigned int nsyms = shdr->sh_size / shdr->sh_entsize;
    1416                 :            :           
    1417         [ #  # ]:          0 :           for (unsigned int cnt = 0; cnt < nsyms; ++cnt)
    1418                 :            :             {
    1419                 :            :               GElf_Ehdr ehdr_mem;
    1420         [ #  # ]:          0 :               GElf_Ehdr* em = gelf_getehdr (elf, &ehdr_mem);
    1421 [ #  # ][ #  # ]:         13 :               if (em == 0) { dwfl_assert ("dwfl_getehdr", dwfl_errno()); }
         [ #  # ][ #  # ]
                 [ #  # ]
    1422                 :            : 
    1423                 :            :               GElf_Rela relamem;
    1424                 :          0 :               GElf_Rela *rela = NULL;
    1425                 :            :               GElf_Rel relmem;
    1426                 :          0 :               GElf_Rel *rel = NULL;
    1427         [ #  # ]:          0 :               if (have_rela)
    1428                 :            :                 {
    1429         [ #  # ]:          0 :                   rela = gelf_getrela (data, cnt, &relamem);
    1430         [ #  # ]:          0 :                   assert (rela != NULL);
    1431                 :            :                 }
    1432         [ #  # ]:          0 :               else if (have_rel)
    1433                 :            :                 {
    1434         [ #  # ]:          0 :                   rel = gelf_getrel (data, cnt, &relmem);
    1435         [ #  # ]:          0 :                   assert (rel != NULL);
    1436                 :            :                 }
    1437                 :            :               GElf_Sym symmem;
    1438                 :            :               Elf32_Word xndx;
    1439                 :          0 :               Elf_Data *xndxdata = NULL;
    1440                 :            :               GElf_Sym *sym =
    1441                 :            :                 gelf_getsymshndx (symdata, xndxdata,
    1442                 :            :                                   GELF_R_SYM (have_rela ? rela->r_info : rel->r_info),
    1443 [ #  # ][ #  # ]:          0 :                                   &symmem, &xndx);
    1444         [ #  # ]:          0 :               assert (sym != NULL);
    1445                 :          0 :               Dwarf_Addr addr = plt_shdr->sh_offset + plt0_entry_size + cnt * plt_entry_size;
    1446                 :            : 
    1447 [ #  # ][ #  # ]:          0 :               if (elf_strptr (elf, symshdr->sh_link, sym->st_name))
    1448 [ #  # ][ #  # ]:          0 :                 (*callback) (object, elf_strptr (elf, symshdr->sh_link, sym->st_name), addr + load_addr);
    1449                 :            :             }
    1450                 :            :           break; // while scn
    1451                 :            :         }
    1452                 :            :     }
    1453                 :          0 :   return 0;
    1454                 :            : }
    1455                 :            : 
    1456                 :            : 
    1457                 :            : // This little test routine represents an unfortunate breakdown in
    1458                 :            : // abstraction between dwflpp (putatively, a layer right on top of
    1459                 :            : // elfutils), and dwarf_query (interpreting a systemtap probe point).
    1460                 :            : // It arises because we sometimes try to fix up slightly-off
    1461                 :            : // .statement() probes (something we find out in fairly low-level).
    1462                 :            : //
    1463                 :            : // An alternative would be to put some more intelligence into query_cu(),
    1464                 :            : // and have it print additional suggestions after finding that
    1465                 :            : // q->dw.iterate_over_srcfile_lines resulted in no new finished_results.
    1466                 :            : 
    1467                 :            : bool
    1468                 :          2 : dwflpp::has_single_line_record (dwarf_query * q, char const * srcfile, int lineno)
    1469                 :            : {
    1470         [ -  + ]:          2 :   if (lineno < 0)
    1471                 :          0 :     return false;
    1472                 :            : 
    1473                 :          2 :   Dwarf_Line **srcsp = NULL;
    1474                 :          2 :   size_t nsrcs = 0;
    1475                 :            : 
    1476                 :            :   dwarf_assert ("dwarf_getsrc_file",
    1477                 :            :                 dwarf_getsrc_file (module_dwarf,
    1478                 :            :                                    srcfile, lineno, 0,
    1479 [ +  - ][ +  - ]:          2 :                                    &srcsp, &nsrcs));
         [ +  - ][ +  - ]
    1480                 :            : 
    1481         [ -  + ]:          2 :   if (nsrcs != 1)
    1482                 :            :     {
    1483         [ #  # ]:          0 :       if (sess.verbose>4)
    1484 [ #  # ][ #  # ]:          0 :         clog << _F("alternative line %d rejected: nsrcs=%zu", lineno, nsrcs) << endl;
         [ #  # ][ #  # ]
    1485                 :          0 :       return false;
    1486                 :            :     }
    1487                 :            : 
    1488                 :            :   // We also try to filter out lines that leave the selected
    1489                 :            :   // functions (if any).
    1490                 :            : 
    1491                 :          2 :   dwarf_line_t line(srcsp[0]);
    1492         [ +  - ]:          2 :   Dwarf_Addr addr = line.addr();
    1493                 :            : 
    1494         [ +  - ]:          2 :   func_info_map_t *filtered_functions = get_filtered_functions(q);
    1495 [ +  - ][ +  - ]:          4 :   for (func_info_map_t::iterator i = filtered_functions->begin();
                 [ +  - ]
    1496         [ +  - ]:          2 :        i != filtered_functions->end(); ++i)
    1497                 :            :     {
    1498 [ +  - ][ +  - ]:          2 :       if (die_has_pc (i->die, addr))
    1499                 :            :         {
    1500         [ -  + ]:          2 :           if (sess.verbose>4)
    1501 [ #  # ][ #  # ]:          0 :             clog << _F("alternative line %d accepted: fn=%s", lineno, i->name.c_str()) << endl;
         [ #  # ][ #  # ]
                 [ #  # ]
    1502                 :          2 :           return true;
    1503                 :            :         }
    1504                 :            :     }
    1505                 :            : 
    1506         [ #  # ]:          0 :   inline_instance_map_t *filtered_inlines = get_filtered_inlines(q);
    1507 [ #  # ][ #  # ]:          0 :   for (inline_instance_map_t::iterator i = filtered_inlines->begin();
                 [ #  # ]
    1508         [ #  # ]:          0 :        i != filtered_inlines->end(); ++i)
    1509                 :            :     {
    1510 [ #  # ][ #  # ]:          0 :       if (die_has_pc (i->die, addr))
    1511                 :            :         {
    1512         [ #  # ]:          0 :           if (sess.verbose>4)
    1513 [ #  # ][ #  # ]:          0 :             clog << _F("alternative line %d accepted: ifn=%s", lineno, i->name.c_str()) << endl;
         [ #  # ][ #  # ]
                 [ #  # ]
    1514                 :          0 :           return true;
    1515                 :            :         }
    1516                 :            :     }
    1517                 :            : 
    1518         [ #  # ]:          0 :   if (sess.verbose>4)
    1519                 :            :     //TRANSLATORS:  given line number leaves (is beyond) given function.
    1520 [ #  # ][ #  # ]:          0 :     clog << _F("alternative line %d rejected: leaves selected fns", lineno) << endl;
         [ #  # ][ #  # ]
    1521                 :          2 :   return false;
    1522                 :            : }
    1523                 :            : 
    1524                 :            : 
    1525                 :            : void
    1526                 :     277032 : dwflpp::iterate_over_srcfile_lines (char const * srcfile,
    1527                 :            :                                     int lines[2],
    1528                 :            :                                     bool need_single_match,
    1529                 :            :                                     enum line_t line_type,
    1530                 :            :                                     void (* callback) (const dwarf_line_t& line,
    1531                 :            :                                                        void * arg),
    1532                 :            :                                     const std::string& func_pattern,
    1533                 :            :                                     void *data)
    1534                 :            : {
    1535                 :     277032 :   Dwarf_Line **srcsp = NULL;
    1536                 :     277032 :   size_t nsrcs = 0;
    1537                 :     277032 :   dwarf_query * q = static_cast<dwarf_query *>(data);
    1538                 :     277032 :   int lineno = lines[0];
    1539                 :     277032 :   auto_free_ref<Dwarf_Line**> free_srcsp(srcsp);
    1540                 :            : 
    1541         [ +  - ]:     277032 :   get_module_dwarf();
    1542         [ +  + ]:     277032 :   if (!this->function)
    1543                 :            :     return;
    1544                 :            : 
    1545         [ +  + ]:        266 :   if (line_type == RELATIVE)
    1546                 :            :     {
    1547                 :            :       Dwarf_Addr addr;
    1548                 :            :       Dwarf_Line *line;
    1549                 :            :       int line_number;
    1550                 :            : 
    1551         [ +  - ]:          5 :       die_entrypc(this->function, &addr);
    1552                 :            : 
    1553         [ +  - ]:          5 :       if (addr != 0)
    1554                 :            :         {
    1555         [ +  - ]:          5 :           line = dwarf_getsrc_die (this->cu, addr);
    1556 [ +  - ][ +  - ]:          5 :           dwarf_assert ("dwarf_getsrc_die", line == NULL);
                 [ +  - ]
    1557 [ +  - ][ +  - ]:          5 :           dwarf_assert ("dwarf_lineno", dwarf_lineno (line, &line_number));
         [ +  - ][ +  - ]
    1558                 :            :         }
    1559 [ #  # ][ #  # ]:          0 :       else if (dwarf_decl_line (this->function, &line_number) != 0)
    1560                 :            :         {
    1561                 :            :           // use DW_AT_decl_line as a fallback method
    1562                 :            :           Dwarf_Attribute type_attr;
    1563                 :            :           Dwarf_Word constant;
    1564 [ #  # ][ #  # ]:          0 :           if (dwarf_attr_integrate (this->function, DW_AT_decl_line, &type_attr))
    1565                 :            :             {
    1566         [ #  # ]:          0 :               dwarf_formudata (&type_attr, &constant);
    1567                 :          0 :               line_number = constant;
    1568                 :            :             }
    1569                 :            :           else
    1570                 :            :             return;
    1571                 :            :         }
    1572                 :          5 :       lineno += line_number;
    1573                 :            :     }
    1574         [ +  + ]:        261 :   else if (line_type == WILDCARD) {
    1575 [ +  - ][ -  + ]:        246 :     if (name_has_wildcard(func_pattern)) /* PR14774: look at whole file if function name is wildcard */
    1576                 :          0 :       lineno = 0;
    1577                 :            :     else
    1578         [ +  - ]:        246 :       function_line (&lineno);
    1579                 :            :   }
    1580         [ -  + ]:         15 :   else if (line_type == RANGE) { /* correct lineno */
    1581                 :            :       int start_lineno;
    1582                 :            : 
    1583 [ #  # ][ #  # ]:          0 :       if (name_has_wildcard(func_pattern)) /* PR10294: wider range like statement("*@foo.c") */
    1584                 :          0 :          start_lineno = lineno;
    1585                 :            :       else
    1586         [ #  # ]:          0 :          function_line (&start_lineno);
    1587         [ #  # ]:          0 :       lineno = lineno < start_lineno ? start_lineno : lineno;
    1588         [ #  # ]:          0 :       if (lineno > lines[1]) { /* invalid line range */
    1589         [ #  # ]:          0 :         stringstream advice;
    1590 [ #  # ][ #  # ]:          0 :         advice << _("Invalid line range (") << lines[0] << "-" << lines[1] << ")";
         [ #  # ][ #  # ]
                 [ #  # ]
    1591         [ #  # ]:          0 :         if (start_lineno > lines[1])
    1592 [ #  # ][ #  # ]:          0 :           advice << _(", the end line number ") << lines[1] << " < " << start_lineno;
         [ #  # ][ #  # ]
    1593 [ #  # ][ #  # ]:          0 :         throw semantic_error (advice.str());
    1594                 :            :        }
    1595                 :            :   }
    1596                 :            : 
    1597                 :            : 
    1598                 :       8586 :   for (int l = lineno; ; l = l + 1)
    1599                 :            :     {
    1600         [ +  - ]:       8586 :       set<int> lines_probed;
    1601         [ +  - ]:       8586 :       pair<set<int>::iterator,bool> line_probed;
    1602                 :       8586 :       int ret = 0;
    1603                 :            : 
    1604         [ +  - ]:       8586 :       assert_no_interrupts();
    1605                 :            : 
    1606                 :       8586 :       nsrcs = 0;
    1607                 :            :       ret = dwarf_getsrc_file (module_dwarf, srcfile, l, 0,
    1608         [ +  - ]:       8586 :                                          &srcsp, &nsrcs);
    1609         [ +  + ]:       8586 :       if (ret != 0) /* tolerate invalid line number */
    1610                 :            :         break;
    1611                 :            : 
    1612 [ +  + ][ -  + ]:       8337 :       if (line_type == WILDCARD || line_type == RANGE)
    1613                 :            :         {
    1614                 :            :           Dwarf_Addr line_addr;
    1615                 :            : 
    1616         [ +  - ]:       8320 :           dwarf_lineno (srcsp [0], &lineno);
    1617                 :            :           /* Maybe lineno will exceed the input end */
    1618 [ -  + ][ #  # ]:       8320 :           if (line_type == RANGE && lineno > lines[1])
    1619                 :            :              break;
    1620         [ +  - ]:       8320 :           line_probed = lines_probed.insert(lineno);
    1621 [ +  + ][ +  - ]:       8320 :           if (lineno != l || line_probed.second == false || nsrcs > 1)
                 [ +  + ]
    1622                 :       7574 :             continue;
    1623         [ +  - ]:        746 :           dwarf_lineaddr (srcsp [0], &line_addr);
    1624 [ +  - ][ -  + ]:        746 :           if (!function_name_matches(func_pattern) && dwarf_haspc (function, line_addr) != 1)
         [ #  # ][ #  # ]
                 [ +  - ]
    1625                 :            :             break;
    1626                 :            :         }
    1627                 :            : 
    1628                 :            :       // NB: Formerly, we used to filter, because:
    1629                 :            : 
    1630                 :            :       // dwarf_getsrc_file gets one *near hits* for line numbers, not
    1631                 :            :       // exact matches.  For example, an existing file but a nonexistent
    1632                 :            :       // line number will be rounded up to the next definition in that
    1633                 :            :       // file.  This may be similar to the GDB breakpoint algorithm, but
    1634                 :            :       // we don't want to be so fuzzy in systemtap land.  So we filter.
    1635                 :            : 
    1636                 :            :       // But we now see the error of our ways, and skip this filtering.
    1637                 :            : 
    1638                 :            :       // XXX: the code also fails to match e.g.  inline function
    1639                 :            :       // definitions when the srcfile is a header file rather than the
    1640                 :            :       // CU name.
    1641                 :            : 
    1642                 :        763 :       size_t remaining_nsrcs = nsrcs;
    1643                 :            : 
    1644 [ +  - ][ +  + ]:        763 :       if (need_single_match && remaining_nsrcs > 1)
    1645                 :            :         {
    1646                 :            :           // We wanted a single line record (a unique address for the
    1647                 :            :           // line) and we got a bunch of line records. We're going to
    1648                 :            :           // skip this probe (throw an exception) but before we throw
    1649                 :            :           // we're going to look around a bit to see if there's a low or
    1650                 :            :           // high line number nearby which *doesn't* have this problem,
    1651                 :            :           // so we can give the user some advice.
    1652                 :            : 
    1653                 :          1 :           int lo_try = -1;
    1654                 :          1 :           int hi_try = -1;
    1655         [ +  + ]:          6 :           for (size_t i = 1; i < 6; ++i)
    1656                 :            :             {
    1657 [ +  + ][ +  - ]:          5 :               if (lo_try == -1 && has_single_line_record(q, srcfile, lineno - i))
         [ +  - ][ +  + ]
    1658                 :          1 :                 lo_try = lineno - i;
    1659                 :            : 
    1660 [ +  + ][ +  - ]:          5 :               if (hi_try == -1 && has_single_line_record(q, srcfile, lineno + i))
         [ +  - ][ +  + ]
    1661                 :          1 :                 hi_try = lineno + i;
    1662                 :            :             }
    1663                 :            : 
    1664         [ +  - ]:          1 :           stringstream advice;
    1665 [ +  - ][ +  - ]:          1 :           advice << _F("multiple addresses for %s:%d [man error::dwarf]", srcfile, lineno);
                 [ +  - ]
    1666 [ -  + ][ #  # ]:          1 :           if (lo_try > 0 || hi_try > 0)
    1667                 :            :             {
    1668                 :            :               //TRANSLATORS: Here we are trying to advise what source file 
    1669                 :            :               //TRANSLATORS: to attempt.
    1670         [ +  - ]:          1 :               advice << _(" (try ");
    1671         [ +  - ]:          1 :               if (lo_try > 0)
    1672 [ +  - ][ +  - ]:          1 :                 advice << srcfile << ":" << lo_try;
                 [ +  - ]
    1673 [ +  - ][ +  - ]:          1 :               if (lo_try > 0 && hi_try > 0)
    1674         [ +  - ]:          1 :                 advice << _(" or ");
    1675         [ +  - ]:          1 :               if (hi_try > 0)
    1676 [ +  - ][ +  - ]:          1 :                 advice << srcfile << ":" << hi_try;
                 [ +  - ]
    1677         [ +  - ]:          1 :               advice << ")";
    1678                 :            :             }
    1679 [ +  - ][ +  - ]:          1 :           throw semantic_error (advice.str());
    1680                 :            :         }
    1681                 :            : 
    1682         [ +  + ]:       1524 :       for (size_t i = 0; i < nsrcs; ++i)
    1683                 :            :         {
    1684         [ +  - ]:        762 :           assert_no_interrupts();
    1685         [ +  - ]:        762 :           if (srcsp [i]) // skip over mismatched lines
    1686         [ +  - ]:        762 :             callback (dwarf_line_t(srcsp[i]), data);
    1687                 :            :         }
    1688                 :            : 
    1689 [ +  + ][ +  + ]:        762 :       if (line_type == ABSOLUTE || line_type == RELATIVE)
    1690                 :            :         break;
    1691 [ -  + ][ #  # ]:        746 :       else if (line_type == RANGE && l == lines[1])
    1692                 :            :         break;
    1693         [ +  - ]:     285352 :     }
              [ +  +  + ]
                 [ +  + ]
    1694                 :            : }
    1695                 :            : 
    1696                 :            : 
    1697                 :            : void
    1698                 :          8 : dwflpp::iterate_over_labels (Dwarf_Die *begin_die,
    1699                 :            :                              const string& sym,
    1700                 :            :                              const string& function,
    1701                 :            :                              dwarf_query *q,
    1702                 :            :                              void (* callback)(const string &,
    1703                 :            :                                                const char *,
    1704                 :            :                                                const char *,
    1705                 :            :                                                int,
    1706                 :            :                                                Dwarf_Die *,
    1707                 :            :                                                Dwarf_Addr,
    1708                 :            :                                                dwarf_query *))
    1709                 :            : {
    1710         [ +  - ]:          8 :   get_module_dwarf();
    1711                 :            : 
    1712                 :            :   Dwarf_Die die, import;
    1713                 :            :   const char *name;
    1714         [ +  - ]:          8 :   int res = dwarf_child (begin_die, &die);
    1715         [ +  - ]:          8 :   if (res != 0)
    1716                 :          8 :     return;  // die without children, bail out.
    1717                 :            : 
    1718         [ +  + ]:         18 :   do
    1719                 :            :     {
    1720         [ +  - ]:         18 :       switch (dwarf_tag(&die))
           [ +  +  -  + ]
    1721                 :            :         {
    1722                 :            :         case DW_TAG_label:
    1723         [ +  - ]:          6 :           name = dwarf_diename (&die);
    1724 [ +  - ][ +  - ]:         30 :           if (name &&
         [ +  - ][ +  - ]
                 [ +  - ]
    1725         [ +  - ]:          6 :               (name == sym
    1726         [ +  - ]:          6 :                || (name_has_wildcard(sym)
    1727 [ +  - ][ +  - ]:         12 :                    && function_name_matches_pattern (name, sym))))
         [ +  - ][ +  - ]
                 [ +  - ]
           [ #  #  #  # ]
    1728                 :            :             {
    1729                 :            :               // Don't try to be smart. Just drop no addr labels.
    1730                 :            :               Dwarf_Addr stmt_addr;
    1731 [ +  - ][ +  - ]:          6 :               if (dwarf_lowpc (&die, &stmt_addr) == 0)
    1732                 :            :                 {
    1733                 :            :                   // Get the file/line number for this label
    1734                 :            :                   int dline;
    1735         [ +  - ]:          6 :                   const char *file = dwarf_decl_file (&die);
    1736         [ +  - ]:          6 :                   dwarf_decl_line (&die, &dline);
    1737                 :            : 
    1738         [ +  - ]:          6 :                   vector<Dwarf_Die> scopes = getscopes_die(&die);
    1739         [ +  - ]:          6 :                   if (scopes.size() > 1)
    1740                 :            :                     {
    1741                 :            :                       Dwarf_Die scope;
    1742 [ +  - ][ -  + ]:          6 :                       if (!inner_die_containing_pc(scopes[1], stmt_addr, scope))
    1743                 :            :                         {
    1744 [ #  # ][ #  # ]:          0 :                           sess.print_warning(_F("label '%s' at address %s (dieoffset: %s) is not "
                 [ #  # ]
    1745                 :            :                                                 "contained by its scope '%s' (dieoffset: %s) -- bad"
    1746                 :            :                                                 " debuginfo? [man error::dwarf]", name, lex_cast_hex(stmt_addr).c_str(),
    1747                 :            :                                                 lex_cast_hex(dwarf_dieoffset(&die)).c_str(),
    1748                 :            :                                                 (dwarf_diename(&scope) ?: "<unknown>"),
    1749 [ #  # ][ #  # ]:          0 :                                                 lex_cast_hex(dwarf_dieoffset(&scope)).c_str()));
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
    1750                 :            :                         }
    1751                 :            :                       callback(function, name, file, dline,
    1752         [ +  - ]:          6 :                                &scope, stmt_addr, q);
    1753         [ +  - ]:          6 :                     }
    1754                 :            :                 }
    1755                 :            :             }
    1756                 :          6 :           break;
    1757                 :            : 
    1758                 :            :         case DW_TAG_subprogram:
    1759                 :            :         case DW_TAG_inlined_subroutine:
    1760                 :            :           // Stay within our filtered function
    1761                 :          1 :           break;
    1762                 :            : 
    1763                 :            :         case DW_TAG_imported_unit:
    1764                 :            :           // Iterate over the children of the imported unit as if they
    1765                 :            :           // were inserted in place.
    1766 [ #  # ][ #  # ]:          0 :           if (dwarf_attr_die(&die, DW_AT_import, &import))
    1767         [ #  # ]:          0 :             iterate_over_labels (&import, sym, function, q, callback);
    1768                 :          0 :           break;
    1769                 :            : 
    1770                 :            :         default:
    1771 [ +  - ][ +  + ]:         11 :           if (dwarf_haschildren (&die))
    1772         [ +  - ]:          2 :             iterate_over_labels (&die, sym, function, q, callback);
    1773                 :         11 :           break;
    1774                 :            :         }
    1775                 :            :     }
    1776         [ +  - ]:         18 :   while (dwarf_siblingof (&die, &die) == 0);
    1777                 :            : }
    1778                 :            : 
    1779                 :            : 
    1780                 :            : void
    1781                 :     121885 : dwflpp::collect_srcfiles_matching (string const & pattern,
    1782                 :            :                                    set<string> & filtered_srcfiles)
    1783                 :            : {
    1784         [ -  + ]:     121885 :   assert (module);
    1785         [ -  + ]:     121885 :   assert (cu);
    1786                 :            : 
    1787                 :            :   size_t nfiles;
    1788                 :            :   Dwarf_Files *srcfiles;
    1789                 :            : 
    1790                 :            :   // PR 5049: implicit * in front of given path pattern.
    1791                 :            :   // NB: fnmatch() is used without FNM_PATHNAME.
    1792 [ +  - ][ +  - ]:     121885 :   string prefixed_pattern = string("*/") + pattern;
                 [ +  - ]
    1793                 :            : 
    1794                 :            :   dwarf_assert ("dwarf_getsrcfiles",
    1795 [ +  - ][ +  - ]:     121885 :                 dwarf_getsrcfiles (cu, &srcfiles, &nfiles));
         [ +  - ][ +  - ]
    1796                 :            :   {
    1797         [ +  + ]:   12067819 :   for (size_t i = 0; i < nfiles; ++i)
    1798                 :            :     {
    1799         [ +  - ]:   11945934 :       char const * fname = dwarf_filesrc (srcfiles, i, NULL, NULL);
    1800 [ +  - ][ +  - ]:   23478485 :       if (fnmatch (pattern.c_str(), fname, 0) == 0 ||
         [ +  + ][ +  + ]
                 [ +  + ]
    1801 [ +  - ][ +  - ]:   11532551 :           fnmatch (prefixed_pattern.c_str(), fname, 0) == 0)
    1802                 :            :         {
    1803 [ +  - ][ +  - ]:     413429 :           filtered_srcfiles.insert (fname);
                 [ +  - ]
    1804         [ -  + ]:     413429 :           if (sess.verbose>2)
    1805 [ #  # ][ #  # ]:          0 :             clog << _F("selected source file '%s'\n", fname);
                 [ #  # ]
    1806                 :            :         }
    1807                 :            :     }
    1808         [ +  - ]:     121885 :   }
    1809                 :     121885 : }
    1810                 :            : 
    1811                 :            : 
    1812                 :            : void
    1813                 :         59 : dwflpp::resolve_prologue_endings (func_info_map_t & funcs)
    1814                 :            : {
    1815                 :            :   // This heuristic attempts to pick the first address that has a
    1816                 :            :   // source line distinct from the function declaration's.  In a
    1817                 :            :   // perfect world, this would be the first statement *past* the
    1818                 :            :   // prologue.
    1819                 :            : 
    1820         [ -  + ]:         59 :   assert(module);
    1821         [ -  + ]:         59 :   assert(cu);
    1822                 :            : 
    1823                 :         59 :   size_t nlines = 0;
    1824                 :         59 :   Dwarf_Lines *lines = NULL;
    1825                 :            : 
    1826                 :            :   /* trouble cases:
    1827                 :            :      malloc do_symlink  in init/initramfs.c    tail-recursive/tiny then no-prologue
    1828                 :            :      sys_get?id         in kernel/timer.c      no-prologue
    1829                 :            :      sys_exit_group                            tail-recursive
    1830                 :            :      {do_,}sys_open                            extra-long-prologue (gcc 3.4)
    1831                 :            :      cpu_to_logical_apicid                     NULL-decl_file
    1832                 :            :    */
    1833                 :            : 
    1834                 :            :   // Fetch all srcline records, sorted by address.
    1835                 :            :   dwarf_assert ("dwarf_getsrclines",
    1836 [ +  - ][ +  - ]:         59 :                 dwarf_getsrclines(cu, &lines, &nlines));
         [ +  - ][ +  - ]
    1837                 :            :   // XXX: free lines[] later, but how?
    1838                 :            : 
    1839 [ +  - ][ +  - ]:      11670 :   for(func_info_map_t::iterator it = funcs.begin(); it != funcs.end(); it++)
         [ +  - ][ +  - ]
                 [ +  + ]
    1840                 :            :     {
    1841                 :            : #if 0 /* someday */
    1842                 :            :       Dwarf_Addr* bkpts = 0;
    1843                 :            :       int n = dwarf_entry_breakpoints (& it->die, & bkpts);
    1844                 :            :       // ...
    1845                 :            :       free (bkpts);
    1846                 :            : #endif
    1847                 :            : 
    1848                 :      11611 :       Dwarf_Addr entrypc = it->entrypc;
    1849                 :            :       Dwarf_Addr highpc; // NB: highpc is exclusive: [entrypc,highpc)
    1850                 :      11611 :       dwfl_assert ("dwarf_highpc", dwarf_highpc (& it->die,
    1851   [ +  -  +  - ]:      23222 :                                                  & highpc));
         [ +  - ][ +  - ]
    1852                 :            : 
    1853         [ +  + ]:      11611 :       if (it->decl_file == 0) it->decl_file = "";
    1854                 :            : 
    1855                 :      11611 :       unsigned entrypc_srcline_idx = 0;
    1856                 :      11611 :       dwarf_line_t entrypc_srcline;
    1857                 :            :       // open-code binary search for exact match
    1858                 :            :       {
    1859                 :      11611 :         unsigned l = 0, h = nlines;
    1860         [ +  - ]:     127967 :         while (l < h)
    1861                 :            :           {
    1862                 :     127967 :             entrypc_srcline_idx = (l + h) / 2;
    1863                 :            :             const dwarf_line_t lr(dwarf_onesrcline(lines,
    1864         [ +  - ]:     127967 :                                                    entrypc_srcline_idx));
    1865         [ +  - ]:     127967 :             Dwarf_Addr addr = lr.addr();
    1866         [ +  + ]:     127967 :             if (addr == entrypc) { entrypc_srcline = lr; break; }
    1867         [ +  - ]:     116356 :             else if (l + 1 == h) { break; } // ran off bottom of tree
    1868         [ +  + ]:     116356 :             else if (addr < entrypc) { l = entrypc_srcline_idx; }
    1869                 :     127967 :             else { h = entrypc_srcline_idx; }
    1870                 :            :           }
    1871                 :            :       }
    1872         [ -  + ]:      11611 :       if (!entrypc_srcline)
    1873                 :            :         {
    1874         [ #  # ]:          0 :           if (sess.verbose > 2)
    1875 [ #  # ][ #  # ]:          0 :             clog << _F("missing entrypc dwarf line record for function '%s'\n",
                 [ #  # ]
    1876         [ #  # ]:          0 :                        it->name.c_str());
    1877                 :            :           // This is probably an inlined function.  We'll end up using
    1878                 :            :           // its lowpc as a probe address.
    1879                 :          0 :           continue;
    1880                 :            :         }
    1881                 :            : 
    1882         [ +  + ]:      11611 :       if (entrypc == 0)
    1883                 :            :         { 
    1884         [ -  + ]:          1 :           if (sess.verbose > 2)
    1885 [ #  # ][ #  # ]:          0 :             clog << _F("null entrypc dwarf line record for function '%s'\n",
                 [ #  # ]
    1886         [ #  # ]:          0 :                        it->name.c_str());
    1887                 :            :           // This is probably an inlined function.  We'll skip this instance;
    1888                 :            :           // it is messed up. 
    1889                 :          1 :           continue;
    1890                 :            :         }
    1891                 :            : 
    1892         [ -  + ]:      11610 :       if (sess.verbose>2)
    1893 [ #  # ][ #  # ]:          0 :         clog << _F("searching for prologue of function '%s' %#" PRIx64 "-%#" PRIx64 
                 [ #  # ]
    1894                 :            :                    "@%s:%d\n", it->name.c_str(), entrypc, highpc, it->decl_file,
    1895         [ #  # ]:          0 :                    it->decl_line);
    1896                 :            : 
    1897                 :            :       // Now we go searching for the first line record that has a
    1898                 :            :       // file/line different from the one in the declaration.
    1899                 :            :       // Normally, this will be the next one.  BUT:
    1900                 :            :       //
    1901                 :            :       // We may have to skip a few because some old compilers plop
    1902                 :            :       // in dummy line records for longer prologues.  If we go too
    1903                 :            :       // far (addr >= highpc), we take the previous one.  Or, it may
    1904                 :            :       // be the first one, if the function had no prologue, and thus
    1905                 :            :       // the entrypc maps to a statement in the body rather than the
    1906                 :            :       // declaration.
    1907                 :            : 
    1908                 :      11610 :       unsigned postprologue_srcline_idx = entrypc_srcline_idx;
    1909                 :      11610 :       bool ranoff_end = false;
    1910         [ +  - ]:      30108 :       while (postprologue_srcline_idx < nlines)
    1911                 :            :         {
    1912         [ +  - ]:      18497 :           dwarf_line_t lr(dwarf_onesrcline(lines, postprologue_srcline_idx));
    1913         [ +  - ]:      18497 :           Dwarf_Addr postprologue_addr = lr.addr();
    1914         [ +  - ]:      18497 :           const char* postprologue_file = lr.linesrc();
    1915         [ +  - ]:      18497 :           int postprologue_lineno = lr.lineno();
    1916                 :            : 
    1917         [ -  + ]:      18497 :           if (sess.verbose>2)
    1918 [ #  # ][ #  # ]:          0 :             clog << _F("checking line record %#" PRIx64 "@%s:%d\n", postprologue_addr,
    1919         [ #  # ]:          0 :                        postprologue_file, postprologue_lineno);
    1920                 :            : 
    1921         [ +  + ]:      18497 :           if (postprologue_addr >= highpc)
    1922                 :            :             {
    1923                 :       1009 :               ranoff_end = true;
    1924                 :       1009 :               postprologue_srcline_idx --;
    1925                 :       1009 :               continue;
    1926                 :            :             }
    1927   [ +  +  +  +  :      46985 :           if (ranoff_end ||
           +  + ][ +  + ]
    1928                 :      16479 :               (strcmp (postprologue_file, it->decl_file) || // We have a winner!
    1929                 :      13018 :                (postprologue_lineno != it->decl_line)))
    1930                 :            :             {
    1931                 :      11610 :               it->prologue_end = postprologue_addr;
    1932                 :            : 
    1933         [ -  + ]:      11610 :               if (sess.verbose>2)
    1934                 :            :                 {
    1935 [ #  # ][ #  # ]:          0 :                   clog << _F("prologue found function '%s'", it->name.c_str());
         [ #  # ][ #  # ]
    1936                 :            :                   // Add a little classification datum
    1937                 :            :                   //TRANSLATORS: Here we're adding some classification datum (ie Prologue Free)
    1938 [ #  # ][ #  # ]:          0 :                   if (postprologue_srcline_idx == entrypc_srcline_idx) clog << _(" (naked)");
    1939                 :            :                   //TRANSLATORS: Here we're adding some classification datum (ie Prologue Free)
    1940 [ #  # ][ #  # ]:          0 :                   if (ranoff_end) clog << _(" (tail-call?)");
    1941 [ #  # ][ #  # ]:          0 :                   clog << " = 0x" << hex << postprologue_addr << dec << "\n";
         [ #  # ][ #  # ]
                 [ #  # ]
    1942                 :            :                 }
    1943                 :            : 
    1944                 :            :               break;
    1945                 :            :             }
    1946                 :            : 
    1947                 :            :           // Let's try the next srcline.
    1948                 :      17488 :           postprologue_srcline_idx ++;
    1949                 :            :         } // loop over srclines
    1950                 :            : 
    1951                 :            :       // if (strlen(it->decl_file) == 0) it->decl_file = NULL;
    1952                 :            : 
    1953                 :            :     } // loop over functions
    1954                 :            : 
    1955                 :            :   // XXX: how to free lines?
    1956                 :         59 : }
    1957                 :            : 
    1958                 :            : 
    1959                 :            : bool
    1960                 :     357761 : dwflpp::function_entrypc (Dwarf_Addr * addr)
    1961                 :            : {
    1962         [ -  + ]:     357761 :   assert (function);
    1963                 :     357761 :   return (dwarf_entrypc (function, addr) == 0);
    1964                 :            : }
    1965                 :            : 
    1966                 :            : 
    1967                 :            : bool
    1968                 :     213601 : dwflpp::die_entrypc (Dwarf_Die * die, Dwarf_Addr * addr)
    1969                 :            : {
    1970                 :     213601 :   int rc = 0;
    1971         [ +  - ]:     213601 :   string lookup_method;
    1972                 :            : 
    1973                 :     213601 :   * addr = 0;
    1974                 :            : 
    1975         [ +  - ]:     213601 :   lookup_method = "dwarf_entrypc";
    1976         [ +  - ]:     213601 :   rc = dwarf_entrypc (die, addr);
    1977                 :            : 
    1978         [ -  + ]:     213601 :   if (rc)
    1979                 :            :     {
    1980         [ #  # ]:          0 :       lookup_method = "dwarf_ranges";
    1981                 :            : 
    1982                 :            :       Dwarf_Addr base;
    1983                 :            :       Dwarf_Addr begin;
    1984                 :            :       Dwarf_Addr end;
    1985         [ #  # ]:          0 :       ptrdiff_t offset = dwarf_ranges (die, 0, &base, &begin, &end);
    1986         [ #  # ]:          0 :       if (offset < 0) rc = -1;
    1987         [ #  # ]:          0 :       else if (offset > 0)
    1988                 :            :         {
    1989                 :          0 :           * addr = begin;
    1990                 :          0 :           rc = 0;
    1991                 :            : 
    1992                 :            :           // Now we need to check that there are no more ranges
    1993                 :            :           // associated with this function, which could conceivably
    1994                 :            :           // happen if a function is inlined, then pieces of it are
    1995                 :            :           // split amongst different conditional branches.  It's not
    1996                 :            :           // obvious which of them to favour.  As a heuristic, we
    1997                 :            :           // pick the beginning of the first range, and ignore the
    1998                 :            :           // others (but with a warning).
    1999                 :            : 
    2000                 :          0 :           unsigned extra = 0;
    2001 [ #  # ][ #  # ]:          0 :           while ((offset = dwarf_ranges (die, offset, &base, &begin, &end)) > 0)
    2002                 :          0 :             extra ++;
    2003         [ #  # ]:          0 :           if (extra)
    2004 [ #  # ][ #  # ]:          0 :             lookup_method += _F(", ignored %s more", lex_cast(extra).c_str());
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
    2005                 :            :         }
    2006                 :            :     }
    2007                 :            : 
    2008                 :            :   // PR10574: reject subprograms where the entrypc address turns out
    2009                 :            :   // to be 0, since they tend to correspond to duplicate-eliminated
    2010                 :            :   // COMDAT copies of C++ functions.
    2011 [ +  - ][ -  + ]:     213601 :   if (rc == 0 && *addr == 0)
    2012                 :            :     {
    2013         [ #  # ]:          0 :       lookup_method += _(" (skip comdat)");
    2014                 :          0 :       rc = 1;
    2015                 :            :     }
    2016                 :            : 
    2017         [ -  + ]:     213601 :   if (sess.verbose > 2)
    2018 [ #  # ][ #  # ]:          0 :     clog << _F("entry-pc lookup (%s dieoffset: %s) = %#" PRIx64 " (rc %d)", lookup_method.c_str(), 
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
    2019         [ #  # ]:          0 :                lex_cast_hex(dwarf_dieoffset(die)).c_str(), *addr, rc) << endl;
    2020                 :            : 
    2021         [ +  - ]:     213601 :   return (rc == 0);
    2022                 :            : }
    2023                 :            : 
    2024                 :            : 
    2025                 :            : void
    2026                 :     357761 : dwflpp::function_die (Dwarf_Die *d)
    2027                 :            : {
    2028         [ -  + ]:     357761 :   assert (function);
    2029                 :     357761 :   *d = *function;
    2030                 :     357761 : }
    2031                 :            : 
    2032                 :            : 
    2033                 :            : void
    2034                 :     571357 : dwflpp::function_file (char const ** c)
    2035                 :            : {
    2036         [ -  + ]:     571357 :   assert (function);
    2037         [ -  + ]:     571357 :   assert (c);
    2038                 :     571357 :   *c = dwarf_decl_file (function);
    2039                 :     571357 : }
    2040                 :            : 
    2041                 :            : 
    2042                 :            : void
    2043                 :     571603 : dwflpp::function_line (int *linep)
    2044                 :            : {
    2045         [ -  + ]:     571603 :   assert (function);
    2046                 :     571603 :   dwarf_decl_line (function, linep);
    2047                 :     571603 : }
    2048                 :            : 
    2049                 :            : 
    2050                 :            : bool
    2051                 :        829 : dwflpp::die_has_pc (Dwarf_Die & die, Dwarf_Addr pc)
    2052                 :            : {
    2053                 :        829 :   int res = dwarf_haspc (&die, pc);
    2054                 :            :   // dwarf_ranges will return -1 if a function die has no DW_AT_ranges
    2055                 :            :   // if (res == -1)
    2056                 :            :   //    dwarf_assert ("dwarf_haspc", res);
    2057                 :        829 :   return res == 1;
    2058                 :            : }
    2059                 :            : 
    2060                 :            : 
    2061                 :            : bool
    2062                 :         46 : dwflpp::inner_die_containing_pc(Dwarf_Die& scope, Dwarf_Addr addr,
    2063                 :            :                                 Dwarf_Die& result)
    2064                 :            : {
    2065                 :         46 :   result = scope;
    2066                 :            : 
    2067                 :            :   // Sometimes we're in a bad scope to begin with -- just let it be.  This can
    2068                 :            :   // happen for example if the compiler outputs a label PC that's just outside
    2069                 :            :   // the lexical scope.  We can't really do anything about that, but variables
    2070                 :            :   // will probably not be accessible in this case.
    2071 [ +  - ][ -  + ]:         46 :   if (!die_has_pc(scope, addr))
    2072                 :          0 :     return false;
    2073                 :            : 
    2074                 :            :   Dwarf_Die child, import;
    2075         [ +  - ]:         46 :   int rc = dwarf_child(&result, &child);
    2076         [ +  + ]:        487 :   while (rc == 0)
    2077                 :            :     {
    2078         [ +  - ]:        441 :       switch (dwarf_tag (&child))
              [ -  +  + ]
    2079                 :            :         {
    2080                 :            :         case DW_TAG_imported_unit:
    2081                 :            :           // The children of the imported unit need to be treated as if
    2082                 :            :           // they are inserted here. So look inside and set result if
    2083                 :            :           // found.
    2084 [ #  # ][ #  # ]:          0 :           if (dwarf_attr_die(&child, DW_AT_import, &import))
    2085                 :            :             {
    2086                 :            :               Dwarf_Die import_result;
    2087 [ #  # ][ #  # ]:          0 :               if (inner_die_containing_pc(import, addr, import_result))
    2088                 :            :                 {
    2089                 :          0 :                   result = import_result;
    2090                 :          0 :                   return true;
    2091                 :            :                 }
    2092                 :            :             }
    2093                 :          0 :           break;
    2094                 :            : 
    2095                 :            :         // lexical tags to recurse within the same starting scope
    2096                 :            :         // NB: this intentionally doesn't cross into inlines!
    2097                 :            :         case DW_TAG_lexical_block:
    2098                 :            :         case DW_TAG_with_stmt:
    2099                 :            :         case DW_TAG_catch_block:
    2100                 :            :         case DW_TAG_try_block:
    2101                 :            :         case DW_TAG_entry_point:
    2102 [ +  - ][ +  + ]:         19 :           if (die_has_pc(child, addr))
    2103                 :            :             {
    2104                 :          5 :               result = child;
    2105         [ +  - ]:          5 :               rc = dwarf_child(&result, &child);
    2106                 :          5 :               continue;
    2107                 :            :             }
    2108                 :            :         }
    2109         [ +  - ]:        436 :       rc = dwarf_siblingof(&child, &child);
    2110                 :            :     }
    2111                 :         46 :   return true;
    2112                 :            : }
    2113                 :            : 
    2114                 :            : 
    2115                 :            : void
    2116                 :        354 : dwflpp::loc2c_error (void *, const char *fmt, ...)
    2117                 :            : {
    2118                 :        354 :   const char *msg = "?";
    2119                 :        354 :   char *tmp = NULL;
    2120                 :            :   int rc;
    2121                 :            :   va_list ap;
    2122                 :        354 :   va_start (ap, fmt);
    2123                 :        354 :   rc = vasprintf (& tmp, fmt, ap);
    2124         [ -  + ]:        354 :   if (rc < 0)
    2125                 :          0 :     msg = "?";
    2126                 :            :   else
    2127                 :        354 :     msg = tmp;
    2128                 :        354 :   va_end (ap);
    2129 [ +  - ][ +  - ]:        354 :   throw semantic_error (msg);
    2130                 :            : }
    2131                 :            : 
    2132                 :            : 
    2133                 :            : // This function generates code used for addressing computations of
    2134                 :            : // target variables.
    2135                 :            : void
    2136                 :        184 : dwflpp::emit_address (struct obstack *pool, Dwarf_Addr address)
    2137                 :            : {
    2138         [ +  - ]:        184 :   int n = dwfl_module_relocations (module);
    2139 [ +  - ][ +  - ]:        184 :   dwfl_assert ("dwfl_module_relocations", n >= 0);
                 [ +  - ]
    2140                 :        184 :   Dwarf_Addr reloc_address = address;
    2141                 :        184 :   const char *secname = "";
    2142         [ +  + ]:        184 :   if (n > 1)
    2143                 :            :     {
    2144         [ +  - ]:          1 :       int i = dwfl_module_relocate_address (module, &reloc_address);
    2145 [ +  - ][ +  - ]:          1 :       dwfl_assert ("dwfl_module_relocate_address", i >= 0);
                 [ +  - ]
    2146         [ +  - ]:          1 :       secname = dwfl_module_relocation_info (module, i, NULL);
    2147                 :            :     }
    2148                 :            : 
    2149         [ -  + ]:        184 :   if (sess.verbose > 2)
    2150                 :            :     {
    2151 [ #  # ][ #  # ]:          0 :       clog << _F("emit dwarf addr %#" PRIx64 " => module %s section %s relocaddr %#" PRIx64,
         [ #  # ][ #  # ]
                 [ #  # ]
    2152                 :            :                  address, module_name.c_str (), (secname ?: "null"),
    2153         [ #  # ]:          0 :                  reloc_address) << endl;
    2154                 :            :     }
    2155                 :            : 
    2156 [ +  + ][ +  + ]:        184 :   if (n > 0 && !(n == 1 && secname == NULL))
                 [ +  - ]
    2157                 :            :    {
    2158 [ +  - ][ +  - ]:        174 :       dwfl_assert ("dwfl_module_relocation_info", secname);
                 [ +  - ]
    2159 [ +  + ][ -  + ]:        348 :       if (n > 1 || secname[0] != '\0')
    2160                 :            :         {
    2161                 :            :           // This gives us the module name, and section name within the
    2162                 :            :           // module, for a kernel module (or other ET_REL module object).
    2163                 :          1 :           obstack_printf (pool, "({ unsigned long addr = 0; ");
    2164                 :            :           obstack_printf (pool, "addr = _stp_kmodule_relocate (\"%s\",\"%s\",%#" PRIx64 "); ",
    2165         [ +  - ]:          1 :                           module_name.c_str(), secname, reloc_address);
    2166                 :          1 :           obstack_printf (pool, "addr; })");
    2167                 :            :         }
    2168 [ +  - ][ +  - ]:        173 :       else if (n == 1 && module_name == TOK_KERNEL && secname[0] == '\0')
         [ +  - ][ +  - ]
                 [ +  - ]
    2169                 :            :         {
    2170                 :            :           // elfutils' way of telling us that this is a relocatable kernel address, which we
    2171                 :            :           // need to treat the same way here as dwarf_query::add_probe_point does: _stext.
    2172                 :        173 :           address -= sess.sym_stext;
    2173                 :        173 :           secname = "_stext";
    2174                 :            :           // Note we "cache" the result here through a static because the
    2175                 :            :           // kernel will never move after being loaded (unlike modules and
    2176                 :            :           // user-space dynamic share libraries).
    2177                 :        173 :           obstack_printf (pool, "({ static unsigned long addr = 0; ");
    2178                 :            :           obstack_printf (pool, "if (addr==0) addr = _stp_kmodule_relocate (\"%s\",\"%s\",%#" PRIx64 "); ",
    2179         [ +  - ]:        173 :                           module_name.c_str(), secname, address); // PR10000 NB: not reloc_address
    2180                 :        173 :           obstack_printf (pool, "addr; })");
    2181                 :            :         }
    2182                 :            :       else
    2183                 :            :         {
    2184         [ #  # ]:          0 :           enable_task_finder (sess);
    2185                 :          0 :           obstack_printf (pool, "({ unsigned long addr = 0; ");
    2186                 :            :           obstack_printf (pool, "addr = _stp_umodule_relocate (\"%s\",%#" PRIx64 ", current); ",
    2187         [ #  # ]:          0 :                           canonicalize_file_name(module_name.c_str()), address);
    2188                 :          0 :           obstack_printf (pool, "addr; })");
    2189                 :            :         }
    2190                 :            :     }
    2191                 :            :   else
    2192                 :         10 :     obstack_printf (pool, "%#" PRIx64 "UL", address); // assume as constant
    2193                 :        184 : }
    2194                 :            : 
    2195                 :            : 
    2196                 :            : void
    2197                 :        184 : dwflpp::loc2c_emit_address (void *arg, struct obstack *pool,
    2198                 :            :                             Dwarf_Addr address)
    2199                 :            : {
    2200                 :        184 :   static_cast<dwflpp *>(arg)->emit_address (pool, address);
    2201                 :        184 : }
    2202                 :            : 
    2203                 :            : 
    2204                 :            : void
    2205                 :       3765 : dwflpp::print_locals(vector<Dwarf_Die>& scopes, ostream &o)
    2206                 :            : {
    2207                 :            :   // XXX Shouldn't this be walking up to outer scopes too?
    2208                 :            : 
    2209                 :       3765 :   print_locals_die(scopes[0], o);
    2210                 :       3765 : }
    2211                 :            : 
    2212                 :            : void
    2213                 :       3765 : dwflpp::print_locals_die(Dwarf_Die& die, ostream &o)
    2214                 :            : {
    2215                 :            :   // Try to get the first child of die.
    2216                 :            :   Dwarf_Die child, import;
    2217 [ +  - ][ +  - ]:       3765 :   if (dwarf_child (&die, &child) == 0)
    2218                 :            :     {
    2219         [ +  + ]:      38405 :       do
    2220                 :            :         {
    2221                 :            :           const char *name;
    2222                 :            :           // Output each sibling's name (that is a variable or
    2223                 :            :           // parameter) to 'o'.
    2224         [ +  - ]:      38405 :           switch (dwarf_tag (&child))
              [ +  -  + ]
    2225                 :            :             {
    2226                 :            :             case DW_TAG_variable:
    2227                 :            :             case DW_TAG_formal_parameter:
    2228         [ +  - ]:      20607 :               name = dwarf_diename (&child);
    2229         [ +  - ]:      20607 :               if (name)
    2230 [ +  - ][ +  - ]:      20607 :                 o << " $" << name;
    2231                 :      20607 :               break;
    2232                 :            :             case DW_TAG_imported_unit:
    2233                 :            :               // Treat the imported unit children as if they are
    2234                 :            :               // children of the given DIE.
    2235 [ #  # ][ #  # ]:          0 :               if (dwarf_attr_die(&child, DW_AT_import, &import))
    2236         [ #  # ]:          0 :                 print_locals_die (import, o);
    2237                 :          0 :               break;
    2238                 :            :             default:
    2239                 :      17798 :               break;
    2240                 :            :             }
    2241                 :            :         }
    2242         [ +  - ]:      38405 :       while (dwarf_siblingof (&child, &child) == 0);
    2243                 :            :     }
    2244                 :       3765 : }
    2245                 :            : 
    2246                 :            : 
    2247                 :            : Dwarf_Attribute *
    2248                 :     186562 : dwflpp::find_variable_and_frame_base (vector<Dwarf_Die>& scopes,
    2249                 :            :                                       Dwarf_Addr pc,
    2250                 :            :                                       string const & local,
    2251                 :            :                                       const target_symbol *e,
    2252                 :            :                                       Dwarf_Die *vardie,
    2253                 :            :                                       Dwarf_Attribute *fb_attr_mem)
    2254                 :            : {
    2255                 :     186562 :   Dwarf_Die *scope_die = &scopes[0];
    2256                 :     186562 :   Dwarf_Attribute *fb_attr = NULL;
    2257                 :            : 
    2258         [ -  + ]:     186562 :   assert (cu);
    2259                 :            : 
    2260                 :     186562 :   int declaring_scope = dwarf_getscopevar (&scopes[0], scopes.size(),
    2261                 :            :                                            local.c_str(),
    2262                 :            :                                            0, NULL, 0, 0,
    2263 [ +  - ][ +  - ]:     186562 :                                            vardie);
    2264         [ +  + ]:     186562 :   if (declaring_scope < 0)
    2265                 :            :     {
    2266         [ +  - ]:       3765 :       stringstream alternatives;
    2267         [ +  - ]:       3765 :       print_locals (scopes, alternatives);
    2268 [ +  - ][ +  - ]:       3765 :       if (e->cu_name == "")
    2269 [ +  - ][ +  - ]:      18825 :         throw semantic_error (_F("unable to find local '%s', [man error::dwarf] dieoffset %s in %s, near pc %s %s %s %s (%s)",
         [ +  - ][ +  - ]
                 [ +  - ]
    2270                 :            :                                  local.c_str(),
    2271                 :            :                                  lex_cast_hex(dwarf_dieoffset(scope_die)).c_str(),
    2272                 :            :                                  module_name.c_str(),
    2273                 :            :                                  lex_cast_hex(pc).c_str(),
    2274                 :            :                                  (scope_die == NULL) ? "" : _("in"),
    2275                 :            :                                  (dwarf_diename(scope_die) ?: "<unknown>"),
    2276                 :            :                                  (dwarf_diename(cu) ?: "<unknown>"),
    2277                 :            :                                  (alternatives.str() == ""
    2278                 :            :                                   ? (_("<no alternatives>"))
    2279                 :            :                                   : (_("alternatives:")
    2280                 :            :                                        + alternatives.str())).c_str()),
    2281 [ +  - ][ +  - ]:      22590 :                               e->tok);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  + ]
         [ +  - ][ -  + ]
         [ #  # ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ -  + ]
           [ #  #  #  # ]
    2282                 :            :       else
    2283 [ #  # ][ #  # ]:          0 :         throw semantic_error (_F("unable to find global '%s', [man error::dwarf] dieoffset %s in %s, %s %s %s (%s)",
         [ #  # ][ #  # ]
    2284                 :            :                                  local.c_str(),
    2285                 :            :                                  lex_cast_hex(dwarf_dieoffset(scope_die)).c_str(),
    2286                 :            :                                  module_name.c_str(),
    2287                 :            :                                  (scope_die == NULL) ? "" : _("in"),
    2288                 :            :                                  (dwarf_diename(scope_die) ?: "<unknown>"),
    2289                 :            :                                  e->cu_name.c_str(),
    2290                 :            :                                  (alternatives.str() == ""
    2291                 :            :                                   ? (_("<no alternatives>"))
    2292                 :            :                                   : (_("alternatives:")
    2293                 :            :                                        + alternatives.str())).c_str()),
    2294 [ #  # ][ #  # ]:       3765 :                               e->tok);
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
           [ #  #  #  # ]
    2295                 :            :     }
    2296                 :            : 
    2297                 :            :   /* Some GCC versions would output duplicate external variables, one
    2298                 :            :      without a location attribute. If so, try to find the other if it
    2299                 :            :      exists in the same scope. See GCC PR51410.  */
    2300                 :            :   Dwarf_Attribute attr_mem;
    2301 [ +  - ][ +  + ]:     367119 :   if (dwarf_attr_integrate (vardie, DW_AT_const_value, &attr_mem) == NULL
         [ +  + ][ +  + ]
         [ +  - ][ +  + ]
    2302         [ +  - ]:     181895 :       && dwarf_attr_integrate (vardie, DW_AT_location, &attr_mem) == NULL
    2303         [ +  - ]:       2423 :       && dwarf_attr_integrate (vardie, DW_AT_external, &attr_mem) != NULL
    2304         [ +  - ]:          4 :       && dwarf_tag(&scopes[declaring_scope]) == DW_TAG_compile_unit)
    2305                 :            :     {
    2306                 :          4 :       Dwarf_Die orig_vardie = *vardie;
    2307                 :          4 :       bool alt_found = false;
    2308 [ +  - ][ +  - ]:          4 :       if (dwarf_child(&scopes[declaring_scope], vardie) == 0)
    2309 [ +  - ][ +  + ]:      10400 :         do
                 [ +  + ]
    2310                 :            :           {
    2311                 :            :             // Note, not handling DW_TAG_imported_unit, assuming GCC
    2312                 :            :             // version is recent enough to not need this workaround if
    2313                 :            :             // we would see an imported unit.
    2314 [ +  - ][ +  + ]:       5545 :             if (dwarf_tag (vardie) == DW_TAG_variable
         [ +  + ][ +  - ]
         [ +  - ][ -  + ]
                 [ -  + ]
    2315 [ +  - ][ +  - ]:        333 :                 && strcmp (dwarf_diename (vardie), local.c_str ()) == 0
    2316         [ +  - ]:          4 :                 && (dwarf_attr_integrate (vardie, DW_AT_external, &attr_mem)
    2317                 :            :                     != NULL)
    2318         [ +  - ]:          4 :                 && ((dwarf_attr_integrate (vardie, DW_AT_const_value, &attr_mem)
    2319                 :            :                      != NULL)
    2320         [ +  - ]:          4 :                     || (dwarf_attr_integrate (vardie, DW_AT_location, &attr_mem)
    2321                 :            :                         != NULL)))
    2322                 :          0 :               alt_found = true;
    2323                 :            :           }
    2324         [ +  - ]:       5200 :         while (!alt_found && dwarf_siblingof(vardie, vardie) == 0);
    2325                 :            : 
    2326         [ +  - ]:          4 :       if (! alt_found)
    2327                 :          4 :         *vardie = orig_vardie;
    2328                 :            :     }
    2329                 :            : 
    2330                 :            :   // Global vars don't need (cannot use) frame base in location descriptor.
    2331 [ +  - ][ +  + ]:     182797 :   if (e->cu_name != "")
    2332                 :          3 :     return NULL;
    2333                 :            : 
    2334                 :            :   /* We start out walking the "lexical scopes" as returned by
    2335                 :            :    * as returned by dwarf_getscopes for the address, starting with the
    2336                 :            :    * declaring_scope that the variable was found in.
    2337                 :            :    */
    2338         [ +  - ]:     182794 :   vector<Dwarf_Die> physcopes, *fbscopes = &scopes;
    2339 [ +  + ][ +  + ]:     732572 :   for (size_t inner = declaring_scope;
                 [ +  + ]
    2340                 :     366286 :        inner < fbscopes->size() && fb_attr == NULL;
    2341                 :            :        ++inner)
    2342                 :            :     {
    2343                 :     183492 :       Dwarf_Die& scope = (*fbscopes)[inner];
    2344         [ +  - ]:     183492 :       switch (dwarf_tag (&scope))
              [ +  +  + ]
    2345                 :            :         {
    2346                 :            :         default:
    2347                 :         49 :           continue;
    2348                 :            :         case DW_TAG_subprogram:
    2349                 :            :         case DW_TAG_entry_point:
    2350                 :            :           fb_attr = dwarf_attr_integrate (&scope,
    2351                 :            :                                           DW_AT_frame_base,
    2352         [ +  - ]:     182765 :                                           fb_attr_mem);
    2353                 :     182765 :           break;
    2354                 :            :         case DW_TAG_inlined_subroutine:
    2355                 :            :           /* Unless we already are going through the "pyshical die tree",
    2356                 :            :            * we now need to start walking the die tree where this
    2357                 :            :            * subroutine is inlined to find the appropriate frame base. */
    2358         [ +  - ]:        678 :            if (declaring_scope != -1)
    2359                 :            :              {
    2360 [ +  - ][ +  - ]:        678 :                physcopes = getscopes_die(&scope);
                 [ +  - ]
    2361 [ +  - ][ -  + ]:        678 :                if (physcopes.empty())
    2362                 :          0 :                  throw semantic_error (_F("unable to get die scopes for '%s' in an inlined subroutine",
    2363 [ #  # ][ #  # ]:          0 :                                           local.c_str()), e->tok);
                 [ #  # ]
    2364                 :        678 :                fbscopes = &physcopes;
    2365                 :        678 :                inner = 0; // zero is current scope, for look will increase.
    2366                 :        678 :                declaring_scope = -1;
    2367                 :            :              }
    2368                 :        678 :           break;
    2369                 :            :         }
    2370                 :            :     }
    2371                 :            : 
    2372         [ +  - ]:     186562 :   return fb_attr;
    2373                 :            : }
    2374                 :            : 
    2375                 :            : 
    2376                 :            : struct location *
    2377                 :     251339 : dwflpp::translate_location(struct obstack *pool,
    2378                 :            :                            Dwarf_Attribute *attr, Dwarf_Die *die,
    2379                 :            :                            Dwarf_Addr pc,
    2380                 :            :                            Dwarf_Attribute *fb_attr,
    2381                 :            :                            struct location **tail,
    2382                 :            :                            const target_symbol *e)
    2383                 :            : {
    2384                 :            : 
    2385                 :            :   /* DW_AT_data_member_location, can be either constant offsets
    2386                 :            :      (struct member fields), or full blown location expressions.  */
    2387                 :            : 
    2388                 :            :   /* There is no location expression, but a constant value instead.  */
    2389 [ +  - ][ +  + ]:     251339 :   if (dwarf_whatattr (attr) == DW_AT_const_value)
    2390                 :            :     {
    2391                 :            :       *tail = c_translate_constant (pool, &loc2c_error, this,
    2392         [ +  - ]:        902 :                                     &loc2c_emit_address, 0, pc, attr);
    2393                 :        902 :       return *tail;
    2394                 :            :     }
    2395                 :            : 
    2396                 :            :   Dwarf_Op *expr;
    2397                 :            :   size_t len;
    2398                 :            : 
    2399                 :            :   /* PR9768: formerly, we added pc+module_bias here.  However, that bias value
    2400                 :            :      is not present in the pc value by the time we get it, so adding it would
    2401                 :            :      result in false negatives of variable reachibility.  In other instances
    2402                 :            :      further below, the c_translate_FOO functions, the module_bias value used
    2403                 :            :      to be passed in, but instead should now be zero for the same reason. */
    2404                 :            : 
    2405                 :            :  retry:
    2406         [ +  - ]:     250437 :   switch (dwarf_getlocation_addr (attr, pc /*+ module_bias*/, &expr, &len, 1))
              [ +  +  + ]
    2407                 :            :     {
    2408                 :            :     case 1:                     /* Should always happen.  */
    2409         [ +  - ]:     224578 :       if (len > 0)
    2410                 :     224578 :         break;
    2411                 :            :       /* Fall through.  */
    2412                 :            : 
    2413                 :            :     case 0:                     /* Shouldn't happen.... but can, e.g. due to PR15123. */
    2414                 :            :       {
    2415         [ +  - ]:      25619 :         Dwarf_Addr pc2 = pr15123_retry_addr (pc, die);
    2416         [ -  + ]:      25619 :         if (pc2 != 0) {
    2417                 :          0 :           pc = pc2;
    2418                 :          0 :           goto retry;
    2419                 :            :         }
    2420                 :            :       }
    2421                 :            : 
    2422                 :            :       /* FALLTHROUGH */
    2423         [ +  - ]:      25619 :       throw semantic_error (_F("not accessible at this address [man error::dwarf] (%s, dieoffset: %s)",
    2424                 :            :                                lex_cast_hex(pc).c_str(), lex_cast_hex(dwarf_dieoffset(die)).c_str()),
    2425 [ +  - ][ +  - ]:      51238 :                                e->tok);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
    2426                 :            : 
    2427                 :            :     default:                    /* Shouldn't happen.  */
    2428                 :            :     case -1:
    2429 [ +  - ][ +  - ]:      25859 :       throw semantic_error (_F("dwarf_getlocation_addr failed [man error::dwarf] , %s", dwarf_errmsg(-1)), e->tok);
                 [ +  - ]
    2430                 :            :     }
    2431                 :            : 
    2432                 :            :   Dwarf_Op *cfa_ops;
    2433                 :            :   // pc is in the dw address space of the current module, which is what
    2434                 :            :   // c_translate_location expects. get_cfa_ops wants the global dwfl address.
    2435                 :            :   // cfa_ops only make sense for locals.
    2436 [ +  - ][ +  + ]:     224578 :   if (e->cu_name == "")
    2437                 :            :     {
    2438                 :     224574 :       Dwarf_Addr addr = pc + module_bias;
    2439         [ +  - ]:     224574 :       cfa_ops = get_cfa_ops (addr);
    2440                 :            :     }
    2441                 :            :   else
    2442                 :          4 :     cfa_ops = NULL;
    2443                 :            : 
    2444                 :            :   return c_translate_location (pool, &loc2c_error, this,
    2445                 :            :                                &loc2c_emit_address,
    2446                 :            :                                1, 0 /* PR9768 */,
    2447         [ +  - ]:     225480 :                                pc, attr, expr, len, tail, fb_attr, cfa_ops);
    2448                 :            : }
    2449                 :            : 
    2450                 :            : 
    2451                 :            : void
    2452                 :       2025 : dwflpp::print_members(Dwarf_Die *vardie, ostream &o, set<string> &dupes)
    2453                 :            : {
    2454         [ +  - ]:       2025 :   const int typetag = dwarf_tag (vardie);
    2455                 :            : 
    2456                 :            :   /* compile and partial unit included for recursion through
    2457                 :            :      imported_unit below. */
    2458 [ +  + ][ +  - ]:       2025 :   if (typetag != DW_TAG_structure_type &&
         [ -  + ][ #  # ]
                 [ #  # ]
    2459                 :            :       typetag != DW_TAG_class_type &&
    2460                 :            :       typetag != DW_TAG_union_type &&
    2461                 :            :       typetag != DW_TAG_compile_unit &&
    2462                 :            :       typetag != DW_TAG_partial_unit)
    2463                 :            :     {
    2464 [ #  # ][ #  # ]:          0 :       o << _F(" Error: %s isn't a struct/class/union", dwarf_type_name(vardie).c_str());
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
    2465                 :            :       return;
    2466                 :            :     }
    2467                 :            : 
    2468                 :            :   // Try to get the first child of vardie.
    2469                 :            :   Dwarf_Die die_mem, import;
    2470                 :       2025 :   Dwarf_Die *die = &die_mem;
    2471         [ +  - ]:       2025 :   switch (dwarf_child (vardie, die))
              [ -  -  + ]
    2472                 :            :     {
    2473                 :            :     case 1:                             // No children.
    2474 [ #  # ][ #  # ]:          0 :       o << _F("%s is empty", dwarf_type_name(vardie).c_str());
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
    2475                 :          0 :       break;
    2476                 :            : 
    2477                 :            :     case -1:                            // Error.
    2478                 :            :     default:                            // Shouldn't happen.
    2479 [ #  # ][ #  # ]:          0 :       o << dwarf_type_name(vardie)
                 [ #  # ]
    2480 [ #  # ][ #  # ]:          0 :         << ": " << dwarf_errmsg (-1);
                 [ #  # ]
    2481                 :          0 :       break;
    2482                 :            : 
    2483                 :            :     case 0:                             // Success.
    2484                 :       2025 :       break;
    2485                 :            :     }
    2486                 :            : 
    2487                 :            :   // Output each sibling's name to 'o'.
    2488         [ +  + ]:      72683 :   do
    2489                 :            :     {
    2490         [ +  - ]:      72683 :       int tag = dwarf_tag(die);
    2491                 :            : 
    2492                 :            :       /* The children of an imported_unit should be treated as members too. */
    2493 [ -  + ][ #  # ]:      72683 :       if (tag == DW_TAG_imported_unit
                 [ -  + ]
    2494         [ #  # ]:          0 :           && dwarf_attr_die(die, DW_AT_import, &import))
    2495         [ #  # ]:          0 :         print_members(&import, o, dupes);
    2496                 :            : 
    2497 [ -  + ][ #  # ]:      72683 :       if (tag != DW_TAG_member && tag != DW_TAG_inheritance)
    2498                 :          0 :         continue;
    2499                 :            : 
    2500         [ +  - ]:      72683 :       const char *member = dwarf_diename (die) ;
    2501                 :            : 
    2502 [ +  - ][ +  + ]:      72683 :       if ( tag == DW_TAG_member && member != NULL )
    2503                 :            :         {
    2504                 :            :           // Only output if this is new, to avoid inheritance dupes.
    2505 [ +  - ][ +  - ]:     144478 :           if (dupes.insert(member).second)
         [ +  - ][ +  - ]
    2506 [ +  - ][ +  - ]:      72239 :             o << " " << member;
    2507                 :            :         }
    2508                 :            :       else
    2509                 :            :         {
    2510                 :            :           Dwarf_Die temp_die;
    2511 [ +  - ][ -  + ]:        444 :           if (!dwarf_attr_die (die, DW_AT_type, &temp_die))
    2512                 :            :             {
    2513 [ #  # ][ #  # ]:          0 :               string source = dwarf_decl_file(die) ?: "<unknown source>";
                 [ #  # ]
    2514                 :          0 :               int line = -1;
    2515         [ #  # ]:          0 :               dwarf_decl_line(die, &line);
    2516 [ #  # ][ #  # ]:          0 :               clog << _F("\n Error in obtaining type attribute for anonymous "
                 [ #  # ]
    2517         [ #  # ]:          0 :                          "member at %s:%d", source.c_str(), line);
    2518         [ #  # ]:          0 :               return;
    2519                 :            :             }
    2520                 :            : 
    2521         [ +  - ]:        444 :           print_members(&temp_die, o, dupes);
    2522                 :            :         }
    2523                 :            : 
    2524                 :            :     }
    2525         [ +  - ]:      72683 :   while (dwarf_siblingof (die, die) == 0);
    2526                 :            : }
    2527                 :            : 
    2528                 :            : 
    2529                 :            : bool
    2530                 :      87689 : dwflpp::find_struct_member(const target_symbol::component& c,
    2531                 :            :                            Dwarf_Die *parentdie,
    2532                 :            :                            Dwarf_Die *memberdie,
    2533                 :            :                            vector<Dwarf_Die>& dies,
    2534                 :            :                            vector<Dwarf_Attribute>& locs)
    2535                 :            : {
    2536                 :            :   Dwarf_Attribute attr;
    2537                 :            :   Dwarf_Die die;
    2538                 :            : 
    2539                 :            :   /* With inheritance, a subclass may mask member names of parent classes, so
    2540                 :            :    * our search among the inheritance tree must be breadth-first rather than
    2541                 :            :    * depth-first (recursive).  The parentdie is still our starting point. */
    2542         [ +  - ]:      87689 :   deque<Dwarf_Die> inheritees(1, *parentdie);
    2543 [ +  - ][ +  - ]:      96309 :   for (; !inheritees.empty(); inheritees.pop_front())
                 [ +  + ]
    2544                 :            :     {
    2545 [ +  - ][ +  - ]:      87689 :       switch (dwarf_child (&inheritees.front(), &die))
              [ +  -  - ]
    2546                 :            :         {
    2547                 :            :         case 0:         /* First child found.  */
    2548                 :      87689 :           break;
    2549                 :            :         case 1:         /* No children.  */
    2550                 :          0 :           continue;
    2551                 :            :         case -1:        /* Error.  */
    2552                 :            :         default:        /* Shouldn't happen */
    2553         [ #  # ]:          0 :           throw semantic_error (dwarf_type_name(&inheritees.front()) + ": "
    2554                 :            :                                 + string (dwarf_errmsg (-1)),
    2555 [ #  # ][ #  # ]:          0 :                                 c.tok);
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
    2556                 :            :         }
    2557                 :            : 
    2558         [ +  + ]:     567619 :       do
    2559                 :            :         {
    2560         [ +  - ]:     646688 :           int tag = dwarf_tag(&die);
    2561                 :            :           /* recurse into imported units as if they are anonymoust structs */
    2562                 :            :           Dwarf_Die import;
    2563 [ -  + ][ #  # ]:     646688 :           if (tag == DW_TAG_imported_unit
         [ #  # ][ +  - ]
    2564         [ #  # ]:          0 :               && dwarf_attr_die(&die, DW_AT_import, &import)
    2565         [ #  # ]:          0 :               && find_struct_member(c, &import, memberdie, dies, locs))
    2566                 :            :             goto success;
    2567                 :            : 
    2568 [ +  + ][ +  - ]:     646688 :           if (tag != DW_TAG_member && tag != DW_TAG_inheritance)
    2569                 :         51 :             continue;
    2570                 :            : 
    2571         [ +  - ]:     646637 :           const char *name = dwarf_diename(&die);
    2572         [ -  + ]:     646637 :           if (tag == DW_TAG_inheritance)
    2573                 :            :             {
    2574                 :            :               /* Remember inheritee for breadth-first search. */
    2575                 :            :               Dwarf_Die inheritee;
    2576 [ #  # ][ #  # ]:          0 :               if (dwarf_attr_die (&die, DW_AT_type, &inheritee))
    2577         [ #  # ]:          0 :                 inheritees.push_back(inheritee);
    2578                 :            :             }
    2579         [ +  + ]:     646637 :           else if (name == NULL)
    2580                 :            :             {
    2581                 :            :               /* Need to recurse for anonymous structs/unions. */
    2582                 :            :               Dwarf_Die subdie;
    2583 [ +  - ][ +  - ]:      25242 :               if (dwarf_attr_die (&die, DW_AT_type, &subdie) &&
         [ +  + ][ +  + ]
    2584         [ +  - ]:      12621 :                   find_struct_member(c, &subdie, memberdie, dies, locs))
    2585                 :            :                 goto success;
    2586                 :            :             }
    2587 [ +  - ][ +  + ]:     634016 :           else if (name == c.member)
    2588                 :            :             {
    2589                 :     646637 :               *memberdie = die;
    2590                 :            :               goto success;
    2591                 :            :             }
    2592                 :            :         }
    2593         [ +  - ]:     567619 :       while (dwarf_siblingof (&die, &die) == 0);
    2594                 :            :     }
    2595                 :            : 
    2596                 :       8620 :   return false;
    2597                 :            : 
    2598                 :            : success:
    2599                 :            :   /* As we unwind the recursion, we need to build the chain of
    2600                 :            :    * locations that got to the final answer. */
    2601 [ +  - ][ +  + ]:      79069 :   if (dwarf_attr_integrate (&die, DW_AT_data_member_location, &attr))
    2602                 :            :     {
    2603 [ +  - ][ +  - ]:      72602 :       dies.insert(dies.begin(), die);
    2604 [ +  - ][ +  - ]:      72602 :       locs.insert(locs.begin(), attr);
    2605                 :            :     }
    2606                 :            : 
    2607                 :            :   /* Union members don't usually have a location,
    2608                 :            :    * but just use the containing union's location.  */
    2609 [ +  - ][ -  + ]:       6467 :   else if (dwarf_tag(parentdie) != DW_TAG_union_type)
    2610                 :          0 :     throw semantic_error (_F("no location for field '%s':%s",
    2611 [ #  # ][ #  # ]:          0 :                              c.member.c_str(), dwarf_errmsg(-1)), c.tok);
         [ #  # ][ #  # ]
    2612                 :            : 
    2613         [ +  - ]:      87689 :   return true;
    2614                 :            : }
    2615                 :            : 
    2616                 :            : 
    2617                 :            : static inline void
    2618                 :     109775 : dwarf_die_type (Dwarf_Die *die, Dwarf_Die *typedie_mem, const token *tok=NULL)
    2619                 :            : {
    2620         [ -  + ]:     109775 :   if (!dwarf_attr_die (die, DW_AT_type, typedie_mem))
    2621 [ #  # ][ #  # ]:          0 :     throw semantic_error (_F("cannot get type of field: %s", dwarf_errmsg(-1)), tok);
                 [ #  # ]
    2622                 :     109775 : }
    2623                 :            : 
    2624                 :            : 
    2625                 :            : void
    2626                 :     188860 : dwflpp::translate_components(struct obstack *pool,
    2627                 :            :                              struct location **tail,
    2628                 :            :                              Dwarf_Addr pc,
    2629                 :            :                              const target_symbol *e,
    2630                 :            :                              Dwarf_Die *vardie,
    2631                 :            :                              Dwarf_Die *typedie,
    2632                 :            :                              unsigned first)
    2633                 :            : {
    2634                 :     188860 :   unsigned i = first;
    2635         [ +  + ]:     298635 :   while (i < e->components.size())
    2636                 :            :     {
    2637                 :     111356 :       const target_symbol::component& c = e->components[i];
    2638                 :            : 
    2639                 :            :       /* XXX: This would be desirable, but we don't get the target_symbol token,
    2640                 :            :          and printing that gives us the file:line number too early anyway. */
    2641                 :            : #if 0
    2642                 :            :       // Emit a marker to note which field is being access-attempted, to give
    2643                 :            :       // better error messages if deref() fails.
    2644                 :            :       string piece = string(...target_symbol token...) + string ("#") + lex_cast(components[i].second);
    2645                 :            :       obstack_printf (pool, "c->last_stmt = %s;", lex_cast_qstring(piece).c_str());
    2646                 :            : #endif
    2647                 :            : 
    2648 [ +  - ][ +  -  :     111356 :       switch (dwarf_tag (typedie))
          +  +  +  -  -  
                      - ]
    2649                 :            :         {
    2650                 :            :         case DW_TAG_typedef:
    2651                 :            :         case DW_TAG_const_type:
    2652                 :            :         case DW_TAG_volatile_type:
    2653                 :            :           /* Just iterate on the referent type.  */
    2654         [ +  - ]:       9000 :           dwarf_die_type (typedie, typedie, c.tok);
    2655                 :       9000 :           break;
    2656                 :            : 
    2657                 :            :         case DW_TAG_reference_type:
    2658                 :            :         case DW_TAG_rvalue_reference_type:
    2659         [ #  # ]:          0 :           if (pool)
    2660         [ #  # ]:          0 :             c_translate_pointer (pool, 1, 0 /* PR9768*/, typedie, tail);
    2661         [ #  # ]:          0 :           dwarf_die_type (typedie, typedie, c.tok);
    2662                 :          0 :           break;
    2663                 :            : 
    2664                 :            :         case DW_TAG_pointer_type:
    2665                 :            :           /* A pointer with no type is a void* -- can't dereference it. */
    2666 [ +  - ][ -  + ]:      26688 :           if (!dwarf_hasattr_integrate (typedie, DW_AT_type))
    2667                 :          0 :             throw semantic_error (_F("invalid access '%s' vs '%s'", lex_cast(c).c_str(),
    2668 [ #  # ][ #  # ]:          0 :                                      dwarf_type_name(typedie).c_str()), c.tok);
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
    2669                 :            : 
    2670         [ +  + ]:      26688 :           if (pool)
    2671         [ +  - ]:      26664 :             c_translate_pointer (pool, 1, 0 /* PR9768*/, typedie, tail);
    2672 [ +  + ][ +  + ]:      26688 :           if (c.type != target_symbol::comp_literal_array_index &&
    2673                 :            :               c.type != target_symbol::comp_expression_array_index)
    2674                 :            :             {
    2675         [ +  - ]:      26654 :               dwarf_die_type (typedie, typedie, c.tok);
    2676                 :      26654 :               break;
    2677                 :            :             }
    2678                 :            :           /* else fall through as an array access */
    2679                 :            : 
    2680                 :            :         case DW_TAG_array_type:
    2681         [ +  + ]:        634 :           if (c.type == target_symbol::comp_literal_array_index)
    2682                 :            :             {
    2683         [ +  + ]:        596 :               if (pool)
    2684                 :            :                 c_translate_array (pool, 1, 0 /* PR9768 */, typedie, tail,
    2685         [ +  - ]:        582 :                                    NULL, c.num_index);
    2686                 :            :             }
    2687         [ +  - ]:         38 :           else if (c.type == target_symbol::comp_expression_array_index)
    2688                 :            :             {
    2689 [ +  - ][ +  - ]:         38 :               string index = "STAP_ARG_index" + lex_cast(i);
                 [ +  - ]
    2690         [ +  + ]:         38 :               if (pool)
    2691                 :            :                 c_translate_array (pool, 1, 0 /* PR9768 */, typedie, tail,
    2692 [ +  - ][ +  - ]:         38 :                                    index.c_str(), 0);
                 [ +  - ]
    2693                 :            :             }
    2694                 :            :           else
    2695                 :          0 :             throw semantic_error (_F("invalid access '%s' for array type",
    2696 [ #  # ][ #  # ]:          0 :                                      lex_cast(c).c_str()), c.tok);
         [ #  # ][ #  # ]
    2697                 :            : 
    2698         [ +  - ]:        634 :           dwarf_die_type (typedie, typedie, c.tok);
    2699                 :        634 :           *vardie = *typedie;
    2700                 :        634 :           ++i;
    2701                 :        634 :           break;
    2702                 :            : 
    2703                 :            :         case DW_TAG_structure_type:
    2704                 :            :         case DW_TAG_union_type:
    2705                 :            :         case DW_TAG_class_type:
    2706         [ -  + ]:      75068 :           if (c.type != target_symbol::comp_struct_member)
    2707                 :          0 :             throw semantic_error (_F("invalid access '%s' for %s",
    2708 [ #  # ][ #  # ]:          0 :                                      lex_cast(c).c_str(), dwarf_type_name(typedie).c_str()));
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
    2709                 :            : 
    2710 [ +  - ][ +  + ]:      75068 :           if (dwarf_hasattr(typedie, DW_AT_declaration))
    2711                 :            :             {
    2712         [ +  - ]:        367 :               Dwarf_Die *tmpdie = declaration_resolve(typedie);
    2713         [ -  + ]:        367 :               if (tmpdie == NULL)
    2714 [ #  # ][ #  # ]:          0 :                 throw semantic_error (_F("unresolved %s", dwarf_type_name(typedie).c_str()), c.tok);
         [ #  # ][ #  # ]
    2715                 :        367 :               *typedie = *tmpdie;
    2716                 :            :             }
    2717                 :            : 
    2718                 :            :             {
    2719         [ +  - ]:      75068 :               vector<Dwarf_Die> dies;
    2720         [ +  - ]:      75068 :               vector<Dwarf_Attribute> locs;
    2721 [ +  - ][ +  + ]:      75068 :               if (!find_struct_member(c, typedie, vardie, dies, locs))
    2722                 :            :                 {
    2723                 :            :                   /* Add a file:line hint for anonymous types */
    2724         [ +  - ]:       1581 :                   string source;
    2725 [ +  - ][ -  + ]:       1581 :                   if (!dwarf_hasattr_integrate(typedie, DW_AT_name))
    2726                 :            :                     {
    2727                 :            :                       int line;
    2728         [ #  # ]:          0 :                       const char *file = dwarf_decl_file(typedie);
    2729 [ #  # ][ #  # ]:          0 :                       if (file && dwarf_decl_line(typedie, &line) == 0)
         [ #  # ][ #  # ]
    2730                 :            :                         source = " (" + string(file) + ":"
    2731 [ #  # ][ #  # ]:          0 :                                  + lex_cast(line) + ")";
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
    2732                 :            :                     }
    2733                 :            : 
    2734         [ +  - ]:       1581 :                   string alternatives;
    2735         [ +  - ]:       1581 :                   stringstream members;
    2736         [ +  - ]:       1581 :                   set<string> member_dupes;
    2737         [ +  - ]:       1581 :                   print_members(typedie, members, member_dupes);
    2738 [ +  - ][ +  - ]:       1581 :                   if (members.str().size() != 0)
         [ +  - ][ +  - ]
    2739 [ +  - ][ +  - ]:       1581 :                     alternatives = " (alternatives:" + members.str() + ")";
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    2740                 :       1581 :                   throw semantic_error(_F("unable to find member '%s' for %s%s%s", c.member.c_str(),
    2741                 :            :                                           dwarf_type_name(typedie).c_str(), source.c_str(),
    2742 [ +  - ][ +  - ]:       1581 :                                           alternatives.c_str()), c.tok);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    2743                 :            :                 }
    2744                 :            : 
    2745         [ +  + ]:     146089 :               for (unsigned j = 0; j < locs.size(); ++j)
    2746         [ +  + ]:      72602 :                 if (pool)
    2747                 :      72546 :                   translate_location (pool, &locs[j], &dies[j],
    2748 [ +  - ][ +  - ]:     147614 :                                       pc, NULL, tail, e);
                 [ +  - ]
    2749                 :            :             }
    2750                 :            : 
    2751         [ +  - ]:      73487 :           dwarf_die_type (vardie, typedie, c.tok);
    2752                 :      73487 :           ++i;
    2753                 :      73487 :           break;
    2754                 :            : 
    2755                 :            :         case DW_TAG_enumeration_type:
    2756                 :            :         case DW_TAG_base_type:
    2757                 :          0 :           throw semantic_error (_F("invalid access '%s' vs. %s", lex_cast(c).c_str(),
    2758 [ #  # ][ #  # ]:          0 :                                    dwarf_type_name(typedie).c_str()), c.tok);
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
    2759                 :            :           break;
    2760                 :            : 
    2761                 :            :         case -1:
    2762 [ #  # ][ #  # ]:          0 :           throw semantic_error (_F("cannot find type: %s", dwarf_errmsg(-1)), c.tok);
                 [ #  # ]
    2763                 :            :           break;
    2764                 :            : 
    2765                 :            :         default:
    2766         [ #  # ]:          0 :           throw semantic_error (_F("%s: unexpected type tag %s", dwarf_type_name(typedie).c_str(),
    2767 [ #  # ][ #  # ]:       1581 :                                    lex_cast(dwarf_tag(typedie)).c_str()), c.tok);
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
    2768                 :            :           break;
    2769                 :            :         }
    2770                 :            :     }
    2771                 :     187279 : }
    2772                 :            : 
    2773                 :            : 
    2774                 :            : void
    2775                 :     339528 : dwflpp::resolve_unqualified_inner_typedie (Dwarf_Die *typedie,
    2776                 :            :                                            Dwarf_Die *innerdie,
    2777                 :            :                                            const target_symbol *e)
    2778                 :            : {
    2779                 :     339528 :   int typetag = dwarf_tag (typedie);
    2780                 :     339528 :   *innerdie = *typedie;
    2781 [ +  + ][ +  + ]:     420620 :   while (typetag == DW_TAG_typedef ||
         [ +  + ][ +  + ]
    2782                 :            :          typetag == DW_TAG_const_type ||
    2783                 :            :          typetag == DW_TAG_volatile_type)
    2784                 :            :     {
    2785         [ +  + ]:      81117 :       if (!dwarf_attr_die (innerdie, DW_AT_type, innerdie))
    2786 [ +  - ][ +  - ]:         25 :         throw semantic_error (_F("cannot get type of pointee: %s", dwarf_errmsg(-1)), e->tok);
                 [ +  - ]
    2787                 :      81092 :       typetag = dwarf_tag (innerdie);
    2788                 :            :     }
    2789                 :     339503 : }
    2790                 :            : 
    2791                 :            : 
    2792                 :            : void
    2793                 :     184810 : dwflpp::translate_final_fetch_or_store (struct obstack *pool,
    2794                 :            :                                         struct location **tail,
    2795                 :            :                                         Dwarf_Addr /*module_bias*/,
    2796                 :            :                                         Dwarf_Die *vardie,
    2797                 :            :                                         Dwarf_Die *start_typedie,
    2798                 :            :                                         bool lvalue,
    2799                 :            :                                         const target_symbol *e,
    2800                 :            :                                         string &,
    2801                 :            :                                         string &,
    2802                 :            :                                         exp_type & ty)
    2803                 :            : {
    2804                 :            :   /* First boil away any qualifiers associated with the type DIE of
    2805                 :            :      the final location to be accessed.  */
    2806                 :            : 
    2807                 :     184810 :   Dwarf_Die typedie_mem, *typedie = &typedie_mem;
    2808         [ +  - ]:     184810 :   resolve_unqualified_inner_typedie (start_typedie, typedie, e);
    2809                 :            : 
    2810                 :            :   /* If we're looking for an address, then we can just provide what
    2811                 :            :      we computed to this point, without using a fetch/store. */
    2812         [ +  + ]:     184810 :   if (e->addressof)
    2813                 :            :     {
    2814         [ -  + ]:        686 :       if (lvalue)
    2815 [ #  # ][ #  # ]:          0 :         throw semantic_error (_("cannot write to member address"), e->tok);
    2816                 :            : 
    2817 [ +  - ][ +  + ]:        686 :       if (dwarf_hasattr_integrate (vardie, DW_AT_bit_offset))
    2818 [ +  - ][ +  - ]:          1 :         throw semantic_error (_("cannot take address of bit-field"), e->tok);
    2819                 :            : 
    2820         [ +  + ]:        685 :       c_translate_addressof (pool, 1, 0, vardie, typedie, tail, "STAP_RETVALUE");
    2821                 :        683 :       ty = pe_long;
    2822                 :     183124 :       return;
    2823                 :            :     }
    2824                 :            : 
    2825                 :            :   /* Then switch behavior depending on the type of fetch/store we
    2826                 :            :      want, and the type and pointer-ness of the final location. */
    2827                 :            : 
    2828         [ +  - ]:     184124 :   int typetag = dwarf_tag (typedie);
    2829   [ -  +  +  +  :     184124 :   switch (typetag)
                      + ]
    2830                 :            :     {
    2831                 :            :     default:
    2832                 :          0 :       throw semantic_error (_F("unsupported type tag %s for %s", lex_cast(typetag).c_str(),
    2833 [ #  # ][ #  # ]:          0 :                                dwarf_type_name(typedie).c_str()), e->tok);
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
    2834                 :            :       break;
    2835                 :            : 
    2836                 :            :     case DW_TAG_structure_type:
    2837                 :            :     case DW_TAG_class_type:
    2838                 :            :     case DW_TAG_union_type:
    2839                 :       1331 :       throw semantic_error (_F("'%s' is being accessed instead of a member",
    2840 [ +  - ][ +  - ]:       1331 :                                dwarf_type_name(typedie).c_str()), e->tok);
         [ +  - ][ +  - ]
    2841                 :            :       break;
    2842                 :            : 
    2843                 :            :     case DW_TAG_base_type:
    2844                 :            : 
    2845                 :            :       // Reject types we can't handle in systemtap
    2846                 :            :       {
    2847                 :            :         Dwarf_Attribute encoding_attr;
    2848                 :      98859 :         Dwarf_Word encoding = (Dwarf_Word) -1;
    2849                 :            :         dwarf_formudata (dwarf_attr_integrate (typedie, DW_AT_encoding, &encoding_attr),
    2850 [ +  - ][ +  - ]:      98859 :                          & encoding);
    2851         [ -  + ]:      98859 :         if (encoding == (Dwarf_Word) -1)
    2852                 :            :           {
    2853                 :            :             // clog << "bad type1 " << encoding << " diestr" << endl;
    2854                 :          0 :             throw semantic_error (_F("unsupported type (mystery encoding %s for %s", lex_cast(encoding).c_str(),
    2855 [ #  # ][ #  # ]:          0 :                                      dwarf_type_name(typedie).c_str()), e->tok);
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
    2856                 :            :           }
    2857                 :            : 
    2858 [ +  - ][ -  + ]:      98859 :         if (encoding == DW_ATE_float
    2859                 :            :             || encoding == DW_ATE_complex_float
    2860                 :            :             /* XXX || many others? */)
    2861                 :            :           {
    2862                 :            :             // clog << "bad type " << encoding << " diestr" << endl;
    2863                 :          0 :             throw semantic_error (_F("unsupported type (encoding %s) for %s", lex_cast(encoding).c_str(),
    2864 [ #  # ][ #  # ]:      98859 :                                      dwarf_type_name(typedie).c_str()), e->tok);
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
    2865                 :            :           }
    2866                 :            :       }
    2867                 :            :       // Fallthrough. enumeration_types are always scalar.
    2868                 :            :     case DW_TAG_enumeration_type:
    2869                 :            : 
    2870                 :      99547 :       ty = pe_long;
    2871         [ +  + ]:      99547 :       if (lvalue)
    2872                 :            :         c_translate_store (pool, 1, 0 /* PR9768 */, vardie, typedie, tail,
    2873         [ +  - ]:         17 :                            "STAP_ARG_value");
    2874                 :            :       else
    2875                 :            :         c_translate_fetch (pool, 1, 0 /* PR9768 */, vardie, typedie, tail,
    2876         [ +  + ]:      99530 :                            "STAP_RETVALUE");
    2877                 :      99195 :       break;
    2878                 :            : 
    2879                 :            :     case DW_TAG_array_type:
    2880                 :            :     case DW_TAG_pointer_type:
    2881                 :            :     case DW_TAG_reference_type:
    2882                 :            :     case DW_TAG_rvalue_reference_type:
    2883                 :            : 
    2884         [ +  + ]:      83246 :         if (lvalue)
    2885                 :            :           {
    2886                 :          1 :             ty = pe_long;
    2887         [ -  + ]:          1 :             if (typetag == DW_TAG_array_type)
    2888 [ #  # ][ #  # ]:          0 :               throw semantic_error (_("cannot write to array address"), e->tok);
    2889 [ +  - ][ -  + ]:          1 :             if (typetag == DW_TAG_reference_type ||
    2890                 :            :                 typetag == DW_TAG_rvalue_reference_type)
    2891 [ #  # ][ #  # ]:       1686 :               throw semantic_error (_("cannot write to reference"), e->tok);
    2892         [ -  + ]:          1 :             assert (typetag == DW_TAG_pointer_type);
    2893                 :            :             c_translate_pointer_store (pool, 1, 0 /* PR9768 */, typedie, tail,
    2894         [ +  - ]:          1 :                                        "STAP_ARG_value");
    2895                 :            :           }
    2896                 :            :         else
    2897                 :            :           {
    2898                 :            :             // We have the pointer: cast it to an integral type via &(*(...))
    2899                 :            : 
    2900                 :            :             // NB: per bug #1187, at one point char*-like types were
    2901                 :            :             // automagically converted here to systemtap string values.
    2902                 :            :             // For several reasons, this was taken back out, leaving
    2903                 :            :             // pointer-to-string "conversion" (copying) to tapset functions.
    2904                 :            : 
    2905                 :      83245 :             ty = pe_long;
    2906         [ +  + ]:      83245 :             if (typetag == DW_TAG_array_type)
    2907         [ +  - ]:        694 :               c_translate_array (pool, 1, 0 /* PR9768 */, typedie, tail, NULL, 0);
    2908                 :            :             else
    2909         [ +  - ]:      82551 :               c_translate_pointer (pool, 1, 0 /* PR9768 */, typedie, tail);
    2910                 :            :             c_translate_addressof (pool, 1, 0 /* PR9768 */, NULL, NULL, tail,
    2911         [ +  - ]:      83245 :                                    "STAP_RETVALUE");
    2912                 :            :           }
    2913                 :     182441 :       break;
    2914                 :            :     }
    2915                 :            : }
    2916                 :            : 
    2917                 :            : 
    2918                 :            : string
    2919                 :     183124 : dwflpp::express_as_string (string prelude,
    2920                 :            :                            string postlude,
    2921                 :            :                            struct location *head)
    2922                 :            : {
    2923                 :     183124 :   size_t bufsz = 0;
    2924                 :     183124 :   char *buf = 0; // NB: it would leak to pre-allocate a buffer here
    2925                 :     183124 :   FILE *memstream = open_memstream (&buf, &bufsz);
    2926         [ -  + ]:     183124 :   assert(memstream);
    2927                 :            : 
    2928         [ +  - ]:     183124 :   fprintf(memstream, "{\n");
    2929 [ +  - ][ +  - ]:     183124 :   fprintf(memstream, "%s", prelude.c_str());
    2930                 :            : 
    2931                 :            :   unsigned int stack_depth;
    2932         [ +  - ]:     183124 :   bool deref = c_emit_location (memstream, head, 1, &stack_depth);
    2933                 :            : 
    2934                 :            :   // Ensure that DWARF keeps loc2c to a "reasonable" stack size
    2935                 :            :   // 32 intptr_t leads to max 256 bytes on the stack
    2936         [ -  + ]:     183124 :   if (stack_depth > 32)
    2937 [ #  # ][ #  # ]:          0 :     throw semantic_error("oversized DWARF stack");
    2938                 :            : 
    2939 [ +  - ][ +  - ]:     183124 :   fprintf(memstream, "%s", postlude.c_str());
    2940         [ +  - ]:     183124 :   fprintf(memstream, "  goto out;\n");
    2941                 :            : 
    2942                 :            :   // dummy use of deref_fault label, to disable warning if deref() not used
    2943         [ +  - ]:     183124 :   fprintf(memstream, "if (0) goto deref_fault;\n");
    2944                 :            : 
    2945                 :            :   // XXX: deref flag not reliable; emit fault label unconditionally
    2946                 :            :   (void) deref;
    2947                 :            :   fprintf(memstream,
    2948                 :            :           "deref_fault:\n"
    2949         [ +  - ]:     183124 :           "  goto out;\n");
    2950         [ +  - ]:     183124 :   fprintf(memstream, "}\n");
    2951                 :            : 
    2952         [ +  - ]:     183124 :   fclose (memstream);
    2953         [ +  - ]:     183124 :   string result(buf);
    2954                 :     183124 :   free (buf);
    2955                 :     183124 :   return result;
    2956                 :            : }
    2957                 :            : 
    2958                 :            : Dwarf_Addr
    2959                 :          4 : dwflpp::vardie_from_symtable (Dwarf_Die *vardie, Dwarf_Addr *addr)
    2960                 :            : {
    2961         [ -  + ]:          4 :   const char *name = dwarf_linkage_name (vardie) ?: dwarf_diename (vardie);
    2962                 :            : 
    2963         [ -  + ]:          4 :   if (sess.verbose > 2)
    2964         [ #  # ]:          0 :     clog << _F("finding symtable address for %s\n", name);
    2965                 :            : 
    2966                 :          4 :   *addr = 0;
    2967                 :          4 :   int syms = dwfl_module_getsymtab (module);
    2968 [ +  - ][ +  - ]:          4 :   dwfl_assert (_("Getting symbols"), syms >= 0);
                 [ +  - ]
    2969                 :            : 
    2970 [ +  + ][ +  - ]:     389985 :   for (int i = 0; *addr == 0 && i < syms; i++)
                 [ +  + ]
    2971                 :            :     {
    2972                 :            :       GElf_Sym sym;
    2973                 :            :       GElf_Word shndxp;
    2974         [ +  - ]:     389981 :       const char *symname = dwfl_module_getsym(module, i, &sym, &shndxp);
    2975 [ +  - ][ +  + ]:     389981 :       if (symname
         [ +  - ][ +  + ]
                 [ +  - ]
    2976                 :     389981 :           && ! strcmp (name, symname)
    2977                 :            :           && sym.st_shndx != SHN_UNDEF
    2978                 :            :           && (GELF_ST_TYPE (sym.st_info) == STT_NOTYPE // PR13284
    2979                 :            :               || GELF_ST_TYPE (sym.st_info) == STT_OBJECT))
    2980                 :          4 :         *addr = sym.st_value;
    2981                 :            :     }
    2982                 :            : 
    2983                 :            :   // Don't relocate for the kernel, or kernel modules we handle those
    2984                 :            :   // specially in emit_address.
    2985 [ +  - ][ -  + ]:          4 :   if (dwfl_module_relocations (module) == 1 && module_name != TOK_KERNEL)
                 [ -  + ]
    2986                 :          0 :     dwfl_module_relocate_address (module, addr);
    2987                 :            : 
    2988         [ -  + ]:          4 :   if (sess.verbose > 2)
    2989         [ #  # ]:          0 :     clog << _F("found %s @%#" PRIx64 "\n", name, *addr);
    2990                 :            : 
    2991                 :          4 :   return *addr;
    2992                 :            : }
    2993                 :            : 
    2994                 :            : string
    2995                 :     184981 : dwflpp::literal_stmt_for_local (vector<Dwarf_Die>& scopes,
    2996                 :            :                                 Dwarf_Addr pc,
    2997                 :            :                                 string const & local,
    2998                 :            :                                 const target_symbol *e,
    2999                 :            :                                 bool lvalue,
    3000                 :            :                                 exp_type & ty)
    3001                 :            : {
    3002                 :            :   Dwarf_Die vardie;
    3003                 :     184981 :   Dwarf_Attribute fb_attr_mem, *fb_attr = NULL;
    3004                 :            : 
    3005                 :            :   fb_attr = find_variable_and_frame_base (scopes, pc, local, e,
    3006         [ +  + ]:     184981 :                                           &vardie, &fb_attr_mem);
    3007                 :            : 
    3008         [ -  + ]:     181216 :   if (sess.verbose>2)
    3009                 :            :     {
    3010 [ #  # ][ #  # ]:          0 :       if (e->cu_name == "")
    3011 [ #  # ][ #  # ]:          0 :         clog << _F("finding location for local '%s' near address %#" PRIx64
                 [ #  # ]
    3012                 :            :                    ", module bias %#" PRIx64 "\n", local.c_str(), pc,
    3013         [ #  # ]:          0 :                    module_bias);
    3014                 :            :       else
    3015 [ #  # ][ #  # ]:          0 :         clog << _F("finding location for global '%s' in CU '%s'\n",
         [ #  # ][ #  # ]
    3016         [ #  # ]:          0 :                    local.c_str(), e->cu_name.c_str());
    3017                 :            :     }
    3018                 :            : 
    3019                 :            : 
    3020                 :            : #define obstack_chunk_alloc malloc
    3021                 :            : #define obstack_chunk_free free
    3022                 :            : 
    3023                 :            :   struct obstack pool;
    3024         [ +  - ]:     181216 :   obstack_init (&pool);
    3025                 :     181216 :   struct location *tail = NULL;
    3026                 :            : 
    3027                 :            :   /* Given $foo->bar->baz[NN], translate the location of foo. */
    3028                 :            : 
    3029                 :            :   struct location *head;
    3030                 :            : 
    3031                 :            :   Dwarf_Attribute attr_mem;
    3032 [ +  - ][ +  + ]:     361530 :   if (dwarf_attr_integrate (&vardie, DW_AT_const_value, &attr_mem) == NULL
         [ +  + ][ +  + ]
    3033         [ +  - ]:     180314 :       && dwarf_attr_integrate (&vardie, DW_AT_location, &attr_mem) == NULL)
    3034                 :            :     {
    3035                 :            :       Dwarf_Op addr_loc;
    3036                 :       2423 :       memset(&addr_loc, 0, sizeof(Dwarf_Op));
    3037                 :       2423 :       addr_loc.atom = DW_OP_addr;
    3038                 :            :       // If it is an external variable try the symbol table. PR10622.
    3039 [ +  - ][ +  + ]:       2427 :       if (dwarf_attr_integrate (&vardie, DW_AT_external, &attr_mem) != NULL
         [ +  - ][ +  + ]
    3040         [ +  - ]:          4 :           && vardie_from_symtable (&vardie, &addr_loc.number) != 0)
    3041                 :            :         {
    3042                 :            :           head = c_translate_location (&pool, &loc2c_error, this,
    3043                 :            :                                        &loc2c_emit_address,
    3044                 :            :                                        1, 0, pc,
    3045         [ +  - ]:          4 :                                        NULL, &addr_loc, 1, &tail, NULL, NULL);
    3046                 :            :         }
    3047                 :            :       else
    3048         [ +  - ]:       2419 :         throw semantic_error (_F("failed to retrieve location attribute for '%s' [man error::dwarf] (dieoffset: %s)",
    3049 [ +  - ][ +  - ]:       4838 :                                  local.c_str(), lex_cast_hex(dwarf_dieoffset(&vardie)).c_str()), e->tok);
         [ +  - ][ +  - ]
                 [ +  - ]
    3050                 :            :     }
    3051                 :            :   else
    3052         [ +  + ]:     178793 :     head = translate_location (&pool, &attr_mem, &vardie, pc, fb_attr, &tail, e);
    3053                 :            : 
    3054                 :            :   /* Translate the ->bar->baz[NN] parts. */
    3055                 :            : 
    3056                 :            :   Dwarf_Die typedie;
    3057 [ +  - ][ -  + ]:     152938 :   if (dwarf_attr_die (&vardie, DW_AT_type, &typedie) == NULL)
    3058 [ #  # ][ #  # ]:          0 :     throw semantic_error(_F("failed to retrieve type attribute for '%s' [man error::dwarf] (dieoffset: %s)", local.c_str(), lex_cast_hex(dwarf_dieoffset(&vardie)).c_str()), e->tok);
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
    3059                 :            : 
    3060         [ +  + ]:     152938 :   translate_components (&pool, &tail, pc, e, &vardie, &typedie);
    3061                 :            : 
    3062                 :            :   /* Translate the assignment part, either
    3063                 :            :      x = $foo->bar->baz[NN]
    3064                 :            :      or
    3065                 :            :      $foo->bar->baz[NN] = x
    3066                 :            :   */
    3067                 :            : 
    3068 [ +  - ][ +  - ]:     152688 :   string prelude, postlude;
    3069                 :            :   translate_final_fetch_or_store (&pool, &tail, module_bias,
    3070                 :            :                                   &vardie, &typedie, lvalue, e,
    3071         [ +  + ]:     152688 :                                   prelude, postlude, ty);
    3072                 :            : 
    3073                 :            :   /* Write the translation to a string. */
    3074 [ +  - ][ +  - ]:     151011 :   string result = express_as_string(prelude, postlude, head);
         [ +  - ][ +  - ]
                 [ +  - ]
    3075 [ -  + ][ #  # ]:     151011 :   obstack_free (&pool, 0);
                 [ +  - ]
    3076 [ +  - ][ +  - ]:     184981 :   return result;
    3077                 :            : }
    3078                 :            : 
    3079                 :            : Dwarf_Die*
    3080                 :       1581 : dwflpp::type_die_for_local (vector<Dwarf_Die>& scopes,
    3081                 :            :                             Dwarf_Addr pc,
    3082                 :            :                             string const & local,
    3083                 :            :                             const target_symbol *e,
    3084                 :            :                             Dwarf_Die *typedie)
    3085                 :            : {
    3086                 :            :   Dwarf_Die vardie;
    3087                 :            :   Dwarf_Attribute attr_mem;
    3088                 :            : 
    3089         [ +  - ]:       1581 :   find_variable_and_frame_base (scopes, pc, local, e, &vardie, &attr_mem);
    3090                 :            : 
    3091 [ +  - ][ -  + ]:       1581 :   if (dwarf_attr_die (&vardie, DW_AT_type, typedie) == NULL)
    3092 [ #  # ][ #  # ]:          0 :     throw semantic_error(_F("failed to retrieve type attribute for '%s' [man error::dwarf]", local.c_str()), e->tok);
                 [ #  # ]
    3093                 :            : 
    3094         [ +  - ]:       1581 :   translate_components (NULL, NULL, pc, e, &vardie, typedie);
    3095                 :       1581 :   return typedie;
    3096                 :            : }
    3097                 :            : 
    3098                 :            : 
    3099                 :            : string
    3100                 :      16240 : dwflpp::literal_stmt_for_return (Dwarf_Die *scope_die,
    3101                 :            :                                  Dwarf_Addr pc,
    3102                 :            :                                  const target_symbol *e,
    3103                 :            :                                  bool lvalue,
    3104                 :            :                                  exp_type & ty)
    3105                 :            : {
    3106         [ -  + ]:      16240 :   if (sess.verbose>2)
    3107 [ #  # ][ #  # ]:          0 :       clog << _F("literal_stmt_for_return: finding return value for %s (%s)\n",
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
    3108         [ #  # ]:          0 :                 (dwarf_diename(scope_die) ?: "<unknown>"), (dwarf_diename(cu) ?: "<unknown>"));
    3109                 :            : 
    3110                 :            :   struct obstack pool;
    3111         [ +  - ]:      16240 :   obstack_init (&pool);
    3112                 :      16240 :   struct location *tail = NULL;
    3113                 :            : 
    3114                 :            :   /* Given $return->bar->baz[NN], translate the location of return. */
    3115                 :            :   const Dwarf_Op *locops;
    3116                 :            :   int nlocops = dwfl_module_return_value_location (module, scope_die,
    3117         [ +  - ]:      16240 :                                                    &locops);
    3118         [ -  + ]:      16240 :   if (nlocops < 0)
    3119                 :            :     {
    3120 [ #  # ][ #  # ]:          0 :       throw semantic_error(_F("failed to retrieve return value location for %s [man error::dwarf] (%s)",
    3121                 :            :                           (dwarf_diename(scope_die) ?: "<unknown>"),
    3122 [ #  # ][ #  # ]:          0 :                           (dwarf_diename(cu) ?: "<unknown>")), e->tok);
         [ #  # ][ #  # ]
    3123                 :            :     }
    3124                 :            :   // the function has no return value (e.g. "void" in C)
    3125         [ +  + ]:      16240 :   else if (nlocops == 0)
    3126                 :            :     {
    3127 [ +  - ][ +  - ]:        464 :       throw semantic_error(_F("function %s (%s) has no return value",
    3128                 :            :                              (dwarf_diename(scope_die) ?: "<unknown>"),
    3129 [ +  - ][ +  - ]:        696 :                              (dwarf_diename(cu) ?: "<unknown>")), e->tok);
         [ +  - ][ +  - ]
    3130                 :            :     }
    3131                 :            : 
    3132                 :            :   struct location  *head = c_translate_location (&pool, &loc2c_error, this,
    3133                 :            :                                                  &loc2c_emit_address,
    3134                 :            :                                                  1, 0 /* PR9768 */,
    3135                 :            :                                                  pc, NULL, locops, nlocops,
    3136         [ +  - ]:      16008 :                                                  &tail, NULL, NULL);
    3137                 :            : 
    3138                 :            :   /* Translate the ->bar->baz[NN] parts. */
    3139                 :            : 
    3140                 :      16008 :   Dwarf_Die vardie = *scope_die, typedie;
    3141 [ +  - ][ -  + ]:      16008 :   if (dwarf_attr_die (&vardie, DW_AT_type, &typedie) == NULL)
    3142 [ #  # ][ #  # ]:          0 :     throw semantic_error(_F("failed to retrieve return value type attribute for %s [man error::dwarf] (%s)",
    3143                 :            :                            (dwarf_diename(&vardie) ?: "<unknown>"),
    3144 [ #  # ][ #  # ]:          0 :                            (dwarf_diename(cu) ?: "<unknown>")), e->tok);
         [ #  # ][ #  # ]
    3145                 :            : 
    3146         [ +  + ]:      16008 :   translate_components (&pool, &tail, pc, e, &vardie, &typedie);
    3147                 :            : 
    3148                 :            :   /* Translate the assignment part, either
    3149                 :            :      x = $return->bar->baz[NN]
    3150                 :            :      or
    3151                 :            :      $return->bar->baz[NN] = x
    3152                 :            :   */
    3153                 :            : 
    3154 [ +  - ][ +  - ]:      16006 :   string prelude, postlude;
    3155                 :            :   translate_final_fetch_or_store (&pool, &tail, module_bias,
    3156                 :            :                                   &vardie, &typedie, lvalue, e,
    3157         [ +  + ]:      16006 :                                   prelude, postlude, ty);
    3158                 :            : 
    3159                 :            :   /* Write the translation to a string. */
    3160 [ +  - ][ +  - ]:      16001 :   string result = express_as_string(prelude, postlude, head);
         [ +  - ][ +  - ]
                 [ +  - ]
    3161 [ -  + ][ #  # ]:      16001 :   obstack_free (&pool, 0);
                 [ +  - ]
    3162 [ +  - ][ +  - ]:      16240 :   return result;
    3163                 :            : }
    3164                 :            : 
    3165                 :            : Dwarf_Die*
    3166                 :          0 : dwflpp::type_die_for_return (Dwarf_Die *scope_die,
    3167                 :            :                              Dwarf_Addr pc,
    3168                 :            :                              const target_symbol *e,
    3169                 :            :                              Dwarf_Die *typedie)
    3170                 :            : {
    3171                 :          0 :   Dwarf_Die vardie = *scope_die;
    3172 [ #  # ][ #  # ]:          0 :   if (dwarf_attr_die (&vardie, DW_AT_type, typedie) == NULL)
    3173 [ #  # ][ #  # ]:          0 :     throw semantic_error(_F("failed to retrieve return value type attribute for %s [man error::dwarf] (%s)",
    3174                 :            :                            (dwarf_diename(&vardie) ?: "<unknown>"),
    3175 [ #  # ][ #  # ]:          0 :                            (dwarf_diename(cu) ?: "<unknown>")), e->tok);
         [ #  # ][ #  # ]
    3176                 :            : 
    3177         [ #  # ]:          0 :   translate_components (NULL, NULL, pc, e, &vardie, typedie);
    3178                 :          0 :   return typedie;
    3179                 :            : }
    3180                 :            : 
    3181                 :            : 
    3182                 :            : string
    3183                 :      17445 : dwflpp::literal_stmt_for_pointer (Dwarf_Die *start_typedie,
    3184                 :            :                                   const target_symbol *e,
    3185                 :            :                                   bool lvalue,
    3186                 :            :                                   exp_type & ty)
    3187                 :            : {
    3188         [ -  + ]:      17445 :   if (sess.verbose>2)
    3189 [ #  # ][ #  # ]:          0 :       clog << _F("literal_stmt_for_pointer: finding value for %s (%s)\n",
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
    3190         [ #  # ]:          0 :                   dwarf_type_name(start_typedie).c_str(), (dwarf_diename(cu) ?: "<unknown>"));
    3191                 :            : 
    3192                 :            :   struct obstack pool;
    3193         [ +  - ]:      17445 :   obstack_init (&pool);
    3194                 :            :   struct location *head = c_translate_argument (&pool, &loc2c_error, this,
    3195                 :            :                                                 &loc2c_emit_address,
    3196         [ +  - ]:      17445 :                                                 1, "STAP_ARG_pointer");
    3197                 :      17445 :   struct location *tail = head;
    3198                 :            : 
    3199                 :            :   /* Translate the ->bar->baz[NN] parts. */
    3200                 :            : 
    3201                 :      17445 :   unsigned first = 0;
    3202                 :      17445 :   Dwarf_Die typedie = *start_typedie, vardie = typedie;
    3203                 :            : 
    3204                 :            :   /* As a special case when typedie is not an array or pointer, we can
    3205                 :            :    * allow array indexing on STAP_ARG_pointer instead (since we do
    3206                 :            :    * know the pointee type and can determine its size).  PR11556. */
    3207                 :            :   const target_symbol::component* c =
    3208 [ +  - ][ +  + ]:      17445 :     e->components.empty() ? NULL : &e->components[0];
    3209 [ +  + ][ +  + ]:      17445 :   if (c && (c->type == target_symbol::comp_literal_array_index ||
                 [ +  + ]
    3210                 :            :             c->type == target_symbol::comp_expression_array_index))
    3211                 :            :     {
    3212         [ +  - ]:        214 :       resolve_unqualified_inner_typedie (&typedie, &typedie, e);
    3213         [ +  - ]:        214 :       int typetag = dwarf_tag (&typedie);
    3214 [ +  - ][ +  - ]:        214 :       if (typetag != DW_TAG_pointer_type &&
    3215                 :            :           typetag != DW_TAG_array_type)
    3216                 :            :         {
    3217         [ +  + ]:        214 :           if (c->type == target_symbol::comp_literal_array_index)
    3218         [ +  - ]:        196 :             c_translate_array_pointer (&pool, 1, &typedie, &tail, NULL, c->num_index);
    3219                 :            :           else
    3220         [ +  - ]:         18 :             c_translate_array_pointer (&pool, 1, &typedie, &tail, "STAP_ARG_index0", 0);
    3221                 :        214 :           ++first;
    3222                 :            :         }
    3223                 :            :     }
    3224                 :            : 
    3225                 :            :   /* Now translate the rest normally. */
    3226                 :            : 
    3227         [ +  + ]:      17445 :   translate_components (&pool, &tail, 0, e, &vardie, &typedie, first);
    3228                 :            : 
    3229                 :            :   /* Translate the assignment part, either
    3230                 :            :      x = (STAP_ARG_pointer)->bar->baz[NN]
    3231                 :            :      or
    3232                 :            :      (STAP_ARG_pointer)->bar->baz[NN] = x
    3233                 :            :   */
    3234                 :            : 
    3235 [ +  - ][ +  - ]:      16116 :   string prelude, postlude;
    3236                 :            :   translate_final_fetch_or_store (&pool, &tail, module_bias,
    3237                 :            :                                   &vardie, &typedie, lvalue, e,
    3238         [ +  + ]:      16116 :                                   prelude, postlude, ty);
    3239                 :            : 
    3240                 :            :   /* Write the translation to a string. */
    3241 [ +  - ][ +  - ]:      16112 :   string result = express_as_string(prelude, postlude, head);
         [ +  - ][ +  - ]
                 [ +  - ]
    3242 [ -  + ][ #  # ]:      16112 :   obstack_free (&pool, 0);
                 [ +  - ]
    3243 [ +  - ][ +  - ]:      17445 :   return result;
    3244                 :            : }
    3245                 :            : 
    3246                 :            : Dwarf_Die*
    3247                 :        888 : dwflpp::type_die_for_pointer (Dwarf_Die *start_typedie,
    3248                 :            :                               const target_symbol *e,
    3249                 :            :                               Dwarf_Die *typedie)
    3250                 :            : {
    3251                 :        888 :   unsigned first = 0;
    3252                 :        888 :   *typedie = *start_typedie;
    3253                 :        888 :   Dwarf_Die vardie = *typedie;
    3254                 :            : 
    3255                 :            :   /* Handle the same PR11556 case as above. */
    3256                 :            :   const target_symbol::component* c =
    3257 [ +  - ][ +  + ]:        888 :     e->components.empty() ? NULL : &e->components[0];
    3258 [ +  + ][ +  - ]:        888 :   if (c && (c->type == target_symbol::comp_literal_array_index ||
                 [ -  + ]
    3259                 :            :             c->type == target_symbol::comp_expression_array_index))
    3260                 :            :     {
    3261         [ #  # ]:          0 :       resolve_unqualified_inner_typedie (typedie, typedie, e);
    3262         [ #  # ]:          0 :       int typetag = dwarf_tag (typedie);
    3263 [ #  # ][ #  # ]:          0 :       if (typetag != DW_TAG_pointer_type &&
    3264                 :            :           typetag != DW_TAG_array_type)
    3265                 :          0 :         ++first;
    3266                 :            :     }
    3267                 :            : 
    3268         [ +  - ]:        888 :   translate_components (NULL, NULL, 0, e, &vardie, typedie, first);
    3269                 :        888 :   return typedie;
    3270                 :            : }
    3271                 :            : 
    3272                 :            : 
    3273                 :            : static bool
    3274                 :     293180 : in_kprobes_function(systemtap_session& sess, Dwarf_Addr addr)
    3275                 :            : {
    3276 [ +  - ][ +  - ]:     293180 :   if (sess.sym_kprobes_text_start != 0 && sess.sym_kprobes_text_end != 0)
    3277                 :            :     {
    3278                 :            :       // If the probe point address is anywhere in the __kprobes
    3279                 :            :       // address range, we can't use this probe point.
    3280 [ +  + ][ +  + ]:     293180 :       if (addr >= sess.sym_kprobes_text_start && addr < sess.sym_kprobes_text_end)
    3281                 :       1407 :         return true;
    3282                 :            :     }
    3283                 :     293180 :   return false;
    3284                 :            : }
    3285                 :            : 
    3286                 :            : 
    3287                 :            : bool
    3288                 :     377321 : dwflpp::blacklisted_p(const string& funcname,
    3289                 :            :                       const string& filename,
    3290                 :            :                       int,
    3291                 :            :                       const string& module,
    3292                 :            :                       Dwarf_Addr addr,
    3293                 :            :                       bool has_return)
    3294                 :            : {
    3295         [ +  + ]:     377321 :   if (!blacklist_enabled)
    3296                 :      11813 :     return false; // no blacklist for userspace
    3297                 :            : 
    3298                 :     365508 :   bool blacklisted = false;
    3299                 :            : 
    3300                 :            :   // check against section blacklist
    3301         [ +  - ]:     365508 :   string section = get_blacklist_section(addr);
    3302                 :            :   // PR6503: modules don't need special init/exit treatment
    3303 [ +  - ][ +  + ]:     365508 :   if (module == TOK_KERNEL && !regexec (&blacklist_section, section.c_str(), 0, NULL, 0))
         [ +  - ][ +  - ]
         [ +  + ][ +  + ]
    3304                 :            :     {
    3305                 :       7836 :       blacklisted = true;
    3306         [ -  + ]:       7836 :       if (sess.verbose>1)
    3307         [ #  # ]:          0 :         clog << _(" init/exit");
    3308                 :            :     }
    3309                 :            : 
    3310                 :            :   // Check for function marked '__kprobes'.
    3311 [ +  - ][ +  + ]:     365508 :   if (module == TOK_KERNEL && in_kprobes_function(sess, addr))
         [ +  + ][ +  + ]
    3312                 :            :     {
    3313                 :       1407 :       blacklisted = true;
    3314         [ -  + ]:       1407 :       if (sess.verbose>1)
    3315         [ #  # ]:          0 :         clog << _(" __kprobes");
    3316                 :            :     }
    3317                 :            : 
    3318                 :            :   // Check probe point against file/function blacklists.
    3319 [ +  - ][ +  - ]:     365508 :   int goodfn = regexec (&blacklist_func, funcname.c_str(), 0, NULL, 0);
    3320         [ +  + ]:     365508 :   if (has_return)
    3321 [ +  + ][ +  - ]:      48066 :     goodfn = goodfn && regexec (&blacklist_func_ret, funcname.c_str(), 0, NULL, 0);
         [ +  - ][ +  + ]
    3322 [ +  - ][ +  - ]:     365508 :   int goodfile = regexec (&blacklist_file, filename.c_str(), 0, NULL, 0);
    3323                 :            : 
    3324 [ +  + ][ +  + ]:     365508 :   if (! (goodfn && goodfile))
    3325                 :            :     {
    3326                 :      40092 :       blacklisted = true;
    3327         [ -  + ]:      40092 :       if (sess.verbose>1)
    3328         [ #  # ]:          0 :         clog << _(" file/function blacklist");
    3329                 :            :     }
    3330                 :            : 
    3331 [ +  + ][ +  + ]:     365508 :   if (sess.guru_mode && blacklisted)
    3332                 :            :     {
    3333                 :          8 :       blacklisted = false;
    3334         [ -  + ]:          8 :       if (sess.verbose>1)
    3335         [ #  # ]:          0 :         clog << _(" - not skipped (guru mode enabled)");
    3336                 :            :     }
    3337                 :            : 
    3338 [ +  + ][ -  + ]:     365508 :   if (blacklisted && sess.verbose>1)
    3339         [ #  # ]:          0 :     clog << _(" - skipped");
    3340                 :            : 
    3341                 :            :   // This probe point is not blacklisted.
    3342         [ +  - ]:     377321 :   return blacklisted;
    3343                 :            : }
    3344                 :            : 
    3345                 :            : 
    3346                 :            : void
    3347                 :       1054 : dwflpp::build_blacklist()
    3348                 :            : {
    3349                 :            :   // We build up the regexps in these strings
    3350                 :            : 
    3351                 :            :   // Add ^ anchors at the front; $ will be added just before regcomp.
    3352                 :            : 
    3353         [ +  - ]:       1054 :   string blfn = "^(";
    3354         [ +  - ]:       1054 :   string blfn_ret = "^(";
    3355         [ +  - ]:       1054 :   string blfile = "^(";
    3356         [ +  - ]:       1054 :   string blsection = "^(";
    3357                 :            : 
    3358         [ +  - ]:       1054 :   blsection += "\\.init\\."; // first alternative, no "|"
    3359         [ +  - ]:       1054 :   blsection += "|\\.exit\\.";
    3360         [ +  - ]:       1054 :   blsection += "|\\.devinit\\.";
    3361         [ +  - ]:       1054 :   blsection += "|\\.devexit\\.";
    3362         [ +  - ]:       1054 :   blsection += "|\\.cpuinit\\.";
    3363         [ +  - ]:       1054 :   blsection += "|\\.cpuexit\\.";
    3364         [ +  - ]:       1054 :   blsection += "|\\.meminit\\.";
    3365         [ +  - ]:       1054 :   blsection += "|\\.memexit\\.";
    3366                 :            : 
    3367                 :            :   /* NOTE all include/asm .h blfile patterns might need "full path"
    3368                 :            :      so prefix those with '.*' - see PR13108 and PR13112. */
    3369         [ +  - ]:       1054 :   blfile += "kernel/kprobes\\.c"; // first alternative, no "|"
    3370         [ +  - ]:       1054 :   blfile += "|arch/.*/kernel/kprobes\\.c";
    3371         [ +  - ]:       1054 :   blfile += "|.*/include/asm/io\\.h";
    3372         [ +  - ]:       1054 :   blfile += "|.*/include/asm/io_64\\.h";
    3373         [ +  - ]:       1054 :   blfile += "|.*/include/asm/bitops\\.h";
    3374         [ +  - ]:       1054 :   blfile += "|drivers/ide/ide-iops\\.c";
    3375                 :            :   // paravirt ops
    3376         [ +  - ]:       1054 :   blfile += "|arch/.*/kernel/paravirt\\.c";
    3377         [ +  - ]:       1054 :   blfile += "|.*/include/asm/paravirt\\.h";
    3378                 :            : 
    3379                 :            :   // XXX: it would be nice if these blacklisted functions were pulled
    3380                 :            :   // in dynamically, instead of being statically defined here.
    3381                 :            :   // Perhaps it could be populated from script files.  A "noprobe
    3382                 :            :   // kernel.function("...")"  construct might do the trick.
    3383                 :            : 
    3384                 :            :   // Most of these are marked __kprobes in newer kernels.  We list
    3385                 :            :   // them here (anyway) so the translator can block them on older
    3386                 :            :   // kernels that don't have the __kprobes function decorator.  This
    3387                 :            :   // also allows detection of problems at translate- rather than
    3388                 :            :   // run-time.
    3389                 :            : 
    3390         [ +  - ]:       1054 :   blfn += "atomic_notifier_call_chain"; // first blfn; no "|"
    3391         [ +  - ]:       1054 :   blfn += "|default_do_nmi";
    3392         [ +  - ]:       1054 :   blfn += "|__die";
    3393         [ +  - ]:       1054 :   blfn += "|die_nmi";
    3394         [ +  - ]:       1054 :   blfn += "|do_debug";
    3395         [ +  - ]:       1054 :   blfn += "|do_general_protection";
    3396         [ +  - ]:       1054 :   blfn += "|do_int3";
    3397         [ +  - ]:       1054 :   blfn += "|do_IRQ";
    3398         [ +  - ]:       1054 :   blfn += "|do_page_fault";
    3399         [ +  - ]:       1054 :   blfn += "|do_sparc64_fault";
    3400         [ +  - ]:       1054 :   blfn += "|do_trap";
    3401         [ +  - ]:       1054 :   blfn += "|dummy_nmi_callback";
    3402         [ +  - ]:       1054 :   blfn += "|flush_icache_range";
    3403         [ +  - ]:       1054 :   blfn += "|ia64_bad_break";
    3404         [ +  - ]:       1054 :   blfn += "|ia64_do_page_fault";
    3405         [ +  - ]:       1054 :   blfn += "|ia64_fault";
    3406         [ +  - ]:       1054 :   blfn += "|io_check_error";
    3407         [ +  - ]:       1054 :   blfn += "|mem_parity_error";
    3408         [ +  - ]:       1054 :   blfn += "|nmi_watchdog_tick";
    3409         [ +  - ]:       1054 :   blfn += "|notifier_call_chain";
    3410         [ +  - ]:       1054 :   blfn += "|oops_begin";
    3411         [ +  - ]:       1054 :   blfn += "|oops_end";
    3412         [ +  - ]:       1054 :   blfn += "|program_check_exception";
    3413         [ +  - ]:       1054 :   blfn += "|single_step_exception";
    3414         [ +  - ]:       1054 :   blfn += "|sync_regs";
    3415         [ +  - ]:       1054 :   blfn += "|unhandled_fault";
    3416         [ +  - ]:       1054 :   blfn += "|unknown_nmi_error";
    3417         [ +  - ]:       1054 :   blfn += "|xen_[gs]et_debugreg";
    3418         [ +  - ]:       1054 :   blfn += "|xen_irq_.*";
    3419         [ +  - ]:       1054 :   blfn += "|xen_.*_fl_direct.*";
    3420         [ +  - ]:       1054 :   blfn += "|check_events";
    3421         [ +  - ]:       1054 :   blfn += "|xen_adjust_exception_frame";
    3422         [ +  - ]:       1054 :   blfn += "|xen_iret.*";
    3423         [ +  - ]:       1054 :   blfn += "|xen_sysret64.*";
    3424         [ +  - ]:       1054 :   blfn += "|test_ti_thread_flag.*";
    3425         [ +  - ]:       1054 :   blfn += "|inat_get_opcode_attribute";
    3426         [ +  - ]:       1054 :   blfn += "|system_call_after_swapgs";
    3427         [ +  - ]:       1054 :   blfn += "|HYPERVISOR_[gs]et_debugreg";
    3428         [ +  - ]:       1054 :   blfn += "|HYPERVISOR_event_channel_op";
    3429         [ +  - ]:       1054 :   blfn += "|hash_64";
    3430         [ +  - ]:       1054 :   blfn += "|hash_ptr";
    3431         [ +  - ]:       1054 :   blfn += "|native_set_pte";
    3432                 :            : 
    3433                 :            :   // Lots of locks
    3434         [ +  - ]:       1054 :   blfn += "|.*raw_.*_lock.*";
    3435         [ +  - ]:       1054 :   blfn += "|.*raw_.*_unlock.*";
    3436         [ +  - ]:       1054 :   blfn += "|.*raw_.*_trylock.*";
    3437         [ +  - ]:       1054 :   blfn += "|.*read_lock.*";
    3438         [ +  - ]:       1054 :   blfn += "|.*read_unlock.*";
    3439         [ +  - ]:       1054 :   blfn += "|.*read_trylock.*";
    3440         [ +  - ]:       1054 :   blfn += "|.*write_lock.*";
    3441         [ +  - ]:       1054 :   blfn += "|.*write_unlock.*";
    3442         [ +  - ]:       1054 :   blfn += "|.*write_trylock.*";
    3443         [ +  - ]:       1054 :   blfn += "|.*write_seqlock.*";
    3444         [ +  - ]:       1054 :   blfn += "|.*write_sequnlock.*";
    3445         [ +  - ]:       1054 :   blfn += "|.*spin_lock.*";
    3446         [ +  - ]:       1054 :   blfn += "|.*spin_unlock.*";
    3447         [ +  - ]:       1054 :   blfn += "|.*spin_trylock.*";
    3448         [ +  - ]:       1054 :   blfn += "|.*spin_is_locked.*";
    3449         [ +  - ]:       1054 :   blfn += "|rwsem_.*lock.*";
    3450         [ +  - ]:       1054 :   blfn += "|.*mutex_.*lock.*";
    3451         [ +  - ]:       1054 :   blfn += "|raw_.*";
    3452                 :            : 
    3453                 :            :   // atomic functions
    3454         [ +  - ]:       1054 :   blfn += "|atomic_.*";
    3455         [ +  - ]:       1054 :   blfn += "|atomic64_.*";
    3456                 :            : 
    3457                 :            :   // few other problematic cases
    3458         [ +  - ]:       1054 :   blfn += "|get_bh";
    3459         [ +  - ]:       1054 :   blfn += "|put_bh";
    3460                 :            : 
    3461                 :            :   // Experimental
    3462         [ +  - ]:       1054 :   blfn += "|.*apic.*|.*APIC.*";
    3463         [ +  - ]:       1054 :   blfn += "|.*softirq.*";
    3464         [ +  - ]:       1054 :   blfn += "|.*IRQ.*";
    3465         [ +  - ]:       1054 :   blfn += "|.*_intr.*";
    3466         [ +  - ]:       1054 :   blfn += "|__delay";
    3467         [ +  - ]:       1054 :   blfn += "|.*kernel_text.*";
    3468         [ +  - ]:       1054 :   blfn += "|get_current";
    3469         [ +  - ]:       1054 :   blfn += "|current_.*";
    3470         [ +  - ]:       1054 :   blfn += "|.*exception_tables.*";
    3471         [ +  - ]:       1054 :   blfn += "|.*setup_rt_frame.*";
    3472                 :            : 
    3473                 :            :   // PR 5759, CONFIG_PREEMPT kernels
    3474         [ +  - ]:       1054 :   blfn += "|.*preempt_count.*";
    3475         [ +  - ]:       1054 :   blfn += "|preempt_schedule";
    3476                 :            : 
    3477                 :            :   // These functions don't return, so return probes would never be recovered
    3478         [ +  - ]:       1054 :   blfn_ret += "do_exit"; // no "|"
    3479         [ +  - ]:       1054 :   blfn_ret += "|sys_exit";
    3480         [ +  - ]:       1054 :   blfn_ret += "|sys_exit_group";
    3481                 :            : 
    3482                 :            :   // __switch_to changes "current" on x86_64 and i686, so return probes
    3483                 :            :   // would cause kernel panic, and it is marked as "__kprobes" on x86_64
    3484 [ +  - ][ -  + ]:       1054 :   if (sess.architecture == "x86_64")
    3485         [ #  # ]:          0 :     blfn += "|__switch_to";
    3486 [ +  - ][ -  + ]:       1054 :   if (sess.architecture == "i686")
    3487         [ #  # ]:          0 :     blfn_ret += "|__switch_to";
    3488                 :            : 
    3489                 :            :   // RHEL6 pre-beta 2.6.32-19.el6
    3490         [ +  - ]:       1054 :   blfn += "|special_mapping_.*";
    3491         [ +  - ]:       1054 :   blfn += "|.*_pte_.*"; // or "|smaps_pte_range";
    3492         [ +  - ]:       1054 :   blfile += "|fs/seq_file\\.c";
    3493                 :            : 
    3494         [ +  - ]:       1054 :   blfn += ")$";
    3495         [ +  - ]:       1054 :   blfn_ret += ")$";
    3496         [ +  - ]:       1054 :   blfile += ")$";
    3497         [ +  - ]:       1054 :   blsection += ")"; // NB: no $, sections match just the beginning
    3498                 :            : 
    3499         [ -  + ]:       1054 :   if (sess.verbose > 2)
    3500                 :            :     {
    3501 [ #  # ][ #  # ]:          0 :       clog << _("blacklist regexps:") << endl;
    3502 [ #  # ][ #  # ]:          0 :       clog << "blfn: " << blfn << endl;
                 [ #  # ]
    3503 [ #  # ][ #  # ]:          0 :       clog << "blfn_ret: " << blfn_ret << endl;
                 [ #  # ]
    3504 [ #  # ][ #  # ]:          0 :       clog << "blfile: " << blfile << endl;
                 [ #  # ]
    3505 [ #  # ][ #  # ]:          0 :       clog << "blsection: " << blsection << endl;
                 [ #  # ]
    3506                 :            :     }
    3507                 :            : 
    3508 [ +  - ][ +  - ]:       1054 :   int rc = regcomp (& blacklist_func, blfn.c_str(), REG_NOSUB|REG_EXTENDED);
    3509 [ -  + ][ #  # ]:       1054 :   if (rc) throw semantic_error (_("blacklist_func regcomp failed"));
                 [ #  # ]
    3510 [ +  - ][ +  - ]:       1054 :   rc = regcomp (& blacklist_func_ret, blfn_ret.c_str(), REG_NOSUB|REG_EXTENDED);
    3511 [ -  + ][ #  # ]:       1054 :   if (rc) throw semantic_error (_("blacklist_func_ret regcomp failed"));
                 [ #  # ]
    3512 [ +  - ][ +  - ]:       1054 :   rc = regcomp (& blacklist_file, blfile.c_str(), REG_NOSUB|REG_EXTENDED);
    3513 [ -  + ][ #  # ]:       1054 :   if (rc) throw semantic_error (_("blacklist_file regcomp failed"));
                 [ #  # ]
    3514 [ +  - ][ +  - ]:       1054 :   rc = regcomp (& blacklist_section, blsection.c_str(), REG_NOSUB|REG_EXTENDED);
    3515 [ -  + ][ #  # ]:       1054 :   if (rc) throw semantic_error (_("blacklist_section regcomp failed"));
                 [ #  # ]
    3516                 :            : 
    3517 [ +  - ][ +  - ]:       1054 :   blacklist_enabled = true;
         [ +  - ][ +  - ]
    3518                 :       1054 : }
    3519                 :            : 
    3520                 :            : 
    3521                 :            : string
    3522                 :     365508 : dwflpp::get_blacklist_section(Dwarf_Addr addr)
    3523                 :            : {
    3524         [ +  - ]:     365508 :   string blacklist_section;
    3525                 :            :   Dwarf_Addr bias;
    3526                 :            :   // We prefer dwfl_module_getdwarf to dwfl_module_getelf here,
    3527                 :            :   // because dwfl_module_getelf can force costly section relocations
    3528                 :            :   // we don't really need, while either will do for this purpose.
    3529 [ +  - ][ +  - ]:     365508 :   Elf* elf = (dwarf_getelf (dwfl_module_getdwarf (module, &bias))
    3530 [ +  - ][ #  # ]:     365508 :               ?: dwfl_module_getelf (module, &bias));
    3531                 :            : 
    3532                 :     365508 :   Dwarf_Addr offset = addr - bias;
    3533         [ +  - ]:     365508 :   if (elf)
    3534                 :            :     {
    3535                 :     365508 :       Elf_Scn* scn = 0;
    3536                 :            :       size_t shstrndx;
    3537 [ +  - ][ +  - ]:     365508 :       dwfl_assert ("getshdrstrndx", elf_getshdrstrndx (elf, &shstrndx));
         [ +  - ][ +  - ]
    3538 [ +  - ][ +  - ]:    1115501 :       while ((scn = elf_nextscn (elf, scn)) != NULL)
    3539                 :            :         {
    3540                 :            :           GElf_Shdr shdr_mem;
    3541         [ +  - ]:     749993 :           GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
    3542         [ -  + ]:     749993 :           if (! shdr)
    3543                 :          0 :             continue; // XXX error?
    3544                 :            : 
    3545         [ +  + ]:     749993 :           if (!(shdr->sh_flags & SHF_ALLOC))
    3546                 :       2191 :             continue;
    3547                 :            : 
    3548                 :     747802 :           GElf_Addr start = shdr->sh_addr;
    3549                 :     747802 :           GElf_Addr end = start + shdr->sh_size;
    3550 [ +  - ][ +  + ]:     747802 :           if (! (offset >= start && offset < end))
    3551                 :     382294 :             continue;
    3552                 :            : 
    3553 [ +  - ][ +  - ]:     749993 :           blacklist_section =  elf_strptr (elf, shstrndx, shdr->sh_name);
    3554                 :            :           break;
    3555                 :            :         }
    3556                 :            :     }
    3557                 :     365508 :   return blacklist_section;
    3558                 :            : }
    3559                 :            : 
    3560                 :            : 
    3561                 :            : /* Find the section named 'section_name'  in the current module
    3562                 :            :  * returning the section header using 'shdr_mem' */
    3563                 :            : 
    3564                 :            : GElf_Shdr *
    3565                 :         23 : dwflpp::get_section(string section_name, GElf_Shdr *shdr_mem, Elf **elf_ret)
    3566                 :            : {
    3567                 :         23 :   GElf_Shdr *shdr = NULL;
    3568                 :            :   Elf* elf;
    3569                 :            :   Dwarf_Addr bias;
    3570                 :            :   size_t shstrndx;
    3571                 :            : 
    3572                 :            :   // Explicitly look in the main elf file first.
    3573         [ +  - ]:         23 :   elf = dwfl_module_getelf (module, &bias);
    3574                 :         23 :   Elf_Scn *probe_scn = NULL;
    3575                 :            : 
    3576 [ +  - ][ +  - ]:         23 :   dwfl_assert ("getshdrstrndx", elf_getshdrstrndx (elf, &shstrndx));
         [ +  - ][ +  - ]
    3577                 :            : 
    3578                 :         23 :   bool have_section = false;
    3579                 :            : 
    3580 [ +  - ][ +  + ]:        822 :   while ((probe_scn = elf_nextscn (elf, probe_scn)))
    3581                 :            :     {
    3582         [ +  - ]:        805 :       shdr = gelf_getshdr (probe_scn, shdr_mem);
    3583         [ -  + ]:        805 :       assert (shdr != NULL);
    3584                 :            : 
    3585 [ +  - ][ +  - ]:        805 :       if (elf_strptr (elf, shstrndx, shdr->sh_name) == section_name)
                 [ +  + ]
    3586                 :            :         {
    3587                 :          6 :           have_section = true;
    3588                 :          6 :           break;
    3589                 :            :         }
    3590                 :            :     }
    3591                 :            : 
    3592                 :            :   // Older versions may put the section in the debuginfo dwarf file,
    3593                 :            :   // so check if it actually exists, if not take a look in the debuginfo file
    3594 [ +  + ][ +  - ]:         23 :   if (! have_section || (have_section && shdr->sh_type == SHT_NOBITS))
                 [ -  + ]
    3595                 :            :     {
    3596 [ +  - ][ +  - ]:         17 :       elf = dwarf_getelf (dwfl_module_getdwarf (module, &bias));
    3597         [ +  + ]:         17 :       if (! elf)
    3598                 :         14 :         return NULL;
    3599 [ +  - ][ +  - ]:          3 :       dwfl_assert ("getshdrstrndx", elf_getshdrstrndx (elf, &shstrndx));
         [ +  - ][ +  - ]
    3600                 :          3 :       probe_scn = NULL;
    3601 [ +  - ][ +  + ]:        126 :       while ((probe_scn = elf_nextscn (elf, probe_scn)))
    3602                 :            :         {
    3603         [ +  - ]:        123 :           shdr = gelf_getshdr (probe_scn, shdr_mem);
    3604 [ +  - ][ +  - ]:        123 :           if (elf_strptr (elf, shstrndx, shdr->sh_name) == section_name)
                 [ -  + ]
    3605                 :            :             {
    3606                 :          0 :               have_section = true;
    3607                 :          0 :               break;
    3608                 :            :             }
    3609                 :            :         }
    3610                 :            :     }
    3611                 :            : 
    3612         [ +  + ]:          9 :   if (!have_section)
    3613                 :          3 :     return NULL;
    3614                 :            : 
    3615         [ -  + ]:          6 :   if (elf_ret)
    3616                 :          0 :     *elf_ret = elf;
    3617                 :         23 :   return shdr;
    3618                 :            : }
    3619                 :            : 
    3620                 :            : 
    3621                 :            : Dwarf_Addr
    3622                 :     377321 : dwflpp::relocate_address(Dwarf_Addr dw_addr, string& reloc_section)
    3623                 :            : {
    3624                 :            :   // PR10273
    3625                 :            :   // libdw address, so adjust for bias gotten from dwfl_module_getdwarf
    3626                 :     377321 :   Dwarf_Addr reloc_addr = dw_addr + module_bias;
    3627         [ -  + ]:     377321 :   if (!module)
    3628                 :            :     {
    3629 [ #  # ][ #  # ]:          0 :       assert(module_name == TOK_KERNEL);
    3630         [ #  # ]:          0 :       reloc_section = "";
    3631                 :            :     }
    3632 [ +  - ][ +  + ]:     377321 :   else if (dwfl_module_relocations (module) > 0)
    3633                 :            :     {
    3634                 :            :       // This is a relocatable module; libdwfl already knows its
    3635                 :            :       // sections, so we can relativize addr.
    3636         [ +  - ]:     365508 :       int idx = dwfl_module_relocate_address (module, &reloc_addr);
    3637         [ +  - ]:     365508 :       const char* r_s = dwfl_module_relocation_info (module, idx, NULL);
    3638         [ +  - ]:     365508 :       if (r_s)
    3639         [ +  - ]:     365508 :         reloc_section = r_s;
    3640                 :            : 
    3641 [ +  - ][ +  + ]:     365508 :       if (reloc_section == "" && dwfl_module_relocations (module) == 1)
         [ +  - ][ +  - ]
                 [ +  + ]
    3642         [ +  - ]:     293180 :           reloc_section = ".dynamic";
    3643                 :            :     }
    3644                 :            :   else
    3645         [ +  - ]:      11813 :     reloc_section = ".absolute";
    3646                 :     377321 :   return reloc_addr;
    3647                 :            : }
    3648                 :            : 
    3649                 :            : /* Returns the call frame address operations for the given program counter
    3650                 :            :  * in the libdw address space.
    3651                 :            :  */
    3652                 :            : Dwarf_Op *
    3653                 :     224574 : dwflpp::get_cfa_ops (Dwarf_Addr pc)
    3654                 :            : {
    3655                 :     224574 :   Dwarf_Op *cfa_ops = NULL;
    3656                 :            : 
    3657         [ -  + ]:     224574 :   if (sess.verbose > 2)
    3658 [ #  # ][ #  # ]:          0 :     clog << "get_cfa_ops @0x" << hex << pc << dec
         [ #  # ][ #  # ]
    3659 [ #  # ][ #  # ]:          0 :          << ", module_start @0x" << hex << module_start << dec << endl;
         [ #  # ][ #  # ]
                 [ #  # ]
    3660                 :            : 
    3661                 :            :   // Try debug_frame first, then fall back on eh_frame.
    3662                 :     224574 :   size_t cfa_nops = 0;
    3663                 :     224574 :   Dwarf_Addr bias = 0;
    3664                 :     224574 :   Dwarf_Frame *frame = NULL;
    3665         [ +  - ]:     224574 :   Dwarf_CFI *cfi = dwfl_module_dwarf_cfi (module, &bias);
    3666         [ +  + ]:     224574 :   if (cfi != NULL)
    3667                 :            :     {
    3668         [ -  + ]:     219914 :       if (sess.verbose > 3)
    3669 [ #  # ][ #  # ]:          0 :         clog << "got dwarf cfi bias: 0x" << hex << bias << dec << endl;
         [ #  # ][ #  # ]
                 [ #  # ]
    3670 [ +  - ][ +  + ]:     219914 :       if (dwarf_cfi_addrframe (cfi, pc - bias, &frame) == 0)
    3671         [ +  - ]:     199093 :         dwarf_frame_cfa (frame, &cfa_ops, &cfa_nops);
    3672         [ -  + ]:      20821 :       else if (sess.verbose > 3)
    3673 [ #  # ][ #  # ]:          0 :         clog << "dwarf_cfi_addrframe failed: " << dwarf_errmsg(-1) << endl;
         [ #  # ][ #  # ]
    3674                 :            :     }
    3675         [ -  + ]:       4660 :   else if (sess.verbose > 3)
    3676 [ #  # ][ #  # ]:          0 :     clog << "dwfl_module_dwarf_cfi failed: " << dwfl_errmsg(-1) << endl;
         [ #  # ][ #  # ]
    3677                 :            : 
    3678         [ +  + ]:     224574 :   if (cfa_ops == NULL)
    3679                 :            :     {
    3680         [ +  - ]:      25481 :       cfi = dwfl_module_eh_cfi (module, &bias);
    3681         [ +  + ]:      25481 :       if (cfi != NULL)
    3682                 :            :         {
    3683         [ -  + ]:         13 :           if (sess.verbose > 3)
    3684 [ #  # ][ #  # ]:          0 :             clog << "got eh cfi bias: 0x" << hex << bias << dec << endl;
         [ #  # ][ #  # ]
                 [ #  # ]
    3685                 :         13 :           Dwarf_Frame *frame = NULL;
    3686 [ +  - ][ -  + ]:         13 :           if (dwarf_cfi_addrframe (cfi, pc - bias, &frame) == 0)
    3687         [ #  # ]:          0 :             dwarf_frame_cfa (frame, &cfa_ops, &cfa_nops);
    3688         [ -  + ]:         13 :           else if (sess.verbose > 3)
    3689 [ #  # ][ #  # ]:         13 :             clog << "dwarf_cfi_addrframe failed: " << dwarf_errmsg(-1) << endl;
         [ #  # ][ #  # ]
    3690                 :            :         }
    3691         [ -  + ]:      25468 :       else if (sess.verbose > 3)
    3692 [ #  # ][ #  # ]:          0 :         clog << "dwfl_module_eh_cfi failed: " << dwfl_errmsg(-1) << endl;
         [ #  # ][ #  # ]
    3693                 :            : 
    3694                 :            :     }
    3695                 :            : 
    3696         [ -  + ]:     224574 :   if (sess.verbose > 2)
    3697                 :            :     {
    3698         [ #  # ]:          0 :       if (cfa_ops == NULL)
    3699 [ #  # ][ #  # ]:          0 :         clog << _("not found cfa") << endl;
    3700                 :            :       else
    3701                 :            :         {
    3702                 :            :           Dwarf_Addr frame_start, frame_end;
    3703                 :            :           bool frame_signalp;
    3704                 :            :           int info = dwarf_frame_info (frame, &frame_start, &frame_end,
    3705         [ #  # ]:          0 :                                        &frame_signalp);
    3706 [ #  # ][ #  # ]:          0 :           clog << _F("found cfa, info: %d [start: %#" PRIx64 ", end: %#" PRIx64 
                 [ #  # ]
    3707         [ #  # ]:          0 :                      ", nops: %zu", info, frame_start, frame_end, cfa_nops) << endl;
    3708                 :            :         }
    3709                 :            :     }
    3710                 :            : 
    3711                 :     224574 :   return cfa_ops;
    3712                 :            : }
    3713                 :            : 
    3714                 :            : int
    3715                 :       1831 : dwflpp::add_module_build_id_to_hash (Dwfl_Module *m,
    3716                 :            :                  void **userdata __attribute__ ((unused)),
    3717                 :            :                  const char *name,
    3718                 :            :                  Dwarf_Addr base,
    3719                 :            :                  void *arg)
    3720                 :            : {
    3721         [ +  - ]:       1831 :    string modname = name;
    3722                 :       1831 :    systemtap_session * s = (systemtap_session *)arg;
    3723         [ -  + ]:       1831 :   if (pending_interrupts)
    3724                 :          0 :     return DWARF_CB_ABORT;
    3725                 :            : 
    3726                 :            :   // Extract the build ID
    3727                 :            :   const unsigned char *bits;
    3728                 :            :   GElf_Addr vaddr;
    3729         [ +  - ]:       1831 :   int bits_length = dwfl_module_build_id(m, &bits, &vaddr);
    3730         [ +  - ]:       1831 :   if(bits_length > 0)
    3731                 :            :     {
    3732                 :            :       // Convert the binary bits to a hex string
    3733         [ +  - ]:       1831 :       string hex = hex_dump(bits, bits_length);
    3734                 :            : 
    3735                 :            :       // Store the build ID in the session
    3736 [ +  - ][ +  - ]:       1831 :       s->build_ids.push_back(hex);
    3737                 :            :     }
    3738                 :            : 
    3739         [ +  - ]:       1831 :   return DWARF_CB_OK;
    3740                 :            : }
    3741                 :            : 
    3742                 :            : 
    3743                 :            : 
    3744                 :            : // Perform PR15123 heuristic for given variable at given address.
    3745                 :            : // Return alternate pc address to do location-list lookup at, or 0 if
    3746                 :            : // inapplicable.
    3747                 :            : //
    3748                 :            : Dwarf_Addr
    3749                 :      25783 : dwflpp::pr15123_retry_addr (Dwarf_Addr pc, Dwarf_Die* die)
    3750                 :            : {
    3751                 :            :   // For PR15123, we'd like to detect the situation where the
    3752                 :            :   // incoming PC may point to a couple-of-byte instruction
    3753                 :            :   // sequence that gcc emits for CFLAGS=-mfentry, and where
    3754                 :            :   // context variables are in fact available throughout, *but* due
    3755                 :            :   // to the bug, the dwarf debuginfo location-list only starts a
    3756                 :            :   // few instructions later.  Prologue searching does not resolve
    3757                 :            :   // this as a line-record is in place at the -mfentry prologue.
    3758                 :            :   //
    3759                 :            :   // Detecting this is complicated because ...
    3760                 :            :   // - we only want to do this if -mfentry was actually used
    3761                 :            :   // - if <pc> points to the a function entry point
    3762                 :            :   // - if the architecture is familiar enough that we can have a
    3763                 :            :   // hard-coded constant to skip over the prologue.
    3764                 :            :   //
    3765                 :            :   // Otherwise, we could give a false-positive - return corrupted data.
    3766                 :            : 
    3767         [ -  + ]:      25783 :   if (getenv ("PR15123_DISABLE"))
    3768                 :          0 :     return 0;
    3769                 :            : 
    3770                 :            :   Dwarf_Die cudie;
    3771                 :            :   Dwarf_Attribute cudie_producer;
    3772         [ +  - ]:      25783 :   dwarf_diecu (die, &cudie, NULL, NULL);
    3773 [ +  - ][ -  + ]:      25783 :   if (! dwarf_attr_integrate(&cudie, DW_AT_producer, &cudie_producer))
    3774                 :          0 :     return 0;
    3775                 :            : 
    3776         [ +  - ]:      25783 :   const char* producer = dwarf_formstring(&cudie_producer);
    3777         [ -  + ]:      25783 :   if (!producer)
    3778                 :          0 :     return 0;
    3779         [ +  - ]:      25783 :   if (! strstr(producer, "-mfentry"))
    3780                 :      25783 :     return 0;
    3781                 :            : 
    3782                 :            :   // Determine if this pc maps to the beginning of a
    3783                 :            :   // real function (not some inlined doppelganger.  This
    3784                 :            :   // is made tricker by this->function may not be
    3785                 :            :   // pointing at the right DIE (say e.g. stap encountered
    3786                 :            :   // the inlined copy first, so was focus_on_function'd).
    3787         [ #  # ]:          0 :   vector<Dwarf_Die> scopes = getscopes(pc);
    3788         [ #  # ]:          0 :   if (scopes.size() == 0)
    3789                 :          0 :     return 0;
    3790                 :            : 
    3791                 :          0 :   Dwarf_Die outer_function_die = scopes[0];
    3792                 :            :   Dwarf_Addr entrypc;
    3793         [ #  # ]:          0 :   die_entrypc(& outer_function_die, &entrypc);
    3794         [ #  # ]:          0 :   if (entrypc != pc) // (will fail on retry, so we won't loop more than once)
    3795                 :          0 :     return 0;
    3796                 :            : 
    3797 [ #  # ][ #  # ]:          0 :   if (sess.architecture == "i386" ||
         [ #  # ][ #  # ]
    3798         [ #  # ]:          0 :       sess.architecture == "x86_64") {
    3799                 :            :     /* pull the trigger */
    3800         [ #  # ]:          0 :     if (sess.verbose > 2)
    3801         [ #  # ]:          0 :       clog << _("retrying variable location-list lookup at address pc+5\n");
    3802                 :          0 :     return pc + 5;
    3803                 :            :   }
    3804                 :            : 
    3805         [ #  # ]:      25783 :   return 0;
    3806 [ +  - ][ +  - ]:       7242 : }
    3807                 :            : 
    3808                 :            : 
    3809                 :            : /* vim: set sw=2 ts=8 cino=>4,n-2,{2,^-2,t0,(0,u0,w1,M1 : */

Generated by: LCOV version 1.9