LCOV - code coverage report
Current view: top level - mnt/wasteland/wcohen/systemtap_write/systemtap - tapsets.cxx (source / functions) Hit Total Coverage
Test: stap.info Lines: 3758 4808 78.2 %
Date: 2013-03-08 Functions: 214 290 73.8 %
Branches: 4947 13238 37.4 %

           Branch data     Line data    Source code
       1                 :            : // tapset resolution
       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 "config.h"
      12                 :            : #include "staptree.h"
      13                 :            : #include "elaborate.h"
      14                 :            : #include "tapsets.h"
      15                 :            : #include "task_finder.h"
      16                 :            : #include "tapset-dynprobe.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 "dwflpp.h"
      25                 :            : #include "setupdwfl.h"
      26                 :            : #include <gelf.h>
      27                 :            : 
      28                 :            : #include "sdt_types.h"
      29                 :            : 
      30                 :            : #include <cstdlib>
      31                 :            : #include <algorithm>
      32                 :            : #include <deque>
      33                 :            : #include <iostream>
      34                 :            : #include <fstream>
      35                 :            : #include <map>
      36                 :            : #include <set>
      37                 :            : #include <sstream>
      38                 :            : #include <stdexcept>
      39                 :            : #include <vector>
      40                 :            : #include <cstdarg>
      41                 :            : #include <cassert>
      42                 :            : #include <iomanip>
      43                 :            : #include <cerrno>
      44                 :            : 
      45                 :            : extern "C" {
      46                 :            : #include <fcntl.h>
      47                 :            : #include <elfutils/libdwfl.h>
      48                 :            : #include <elfutils/libdw.h>
      49                 :            : #include <dwarf.h>
      50                 :            : #include <elf.h>
      51                 :            : #include <obstack.h>
      52                 :            : #include <glob.h>
      53                 :            : #include <fnmatch.h>
      54                 :            : #include <stdio.h>
      55                 :            : #include <sys/types.h>
      56                 :            : #include <sys/stat.h>
      57                 :            : #include <math.h>
      58                 :            : #include <regex.h>
      59                 :            : #include <unistd.h>
      60                 :            : #include <wordexp.h>
      61                 :            : 
      62                 :            : #define __STDC_FORMAT_MACROS
      63                 :            : #include <inttypes.h>
      64                 :            : }
      65                 :            : 
      66                 :            : 
      67                 :            : using namespace std;
      68                 :            : using namespace __gnu_cxx;
      69                 :            : 
      70                 :            : 
      71                 :            : 
      72                 :            : // ------------------------------------------------------------------------
      73                 :            : 
      74                 :            : string
      75                 :      16766 : common_probe_init (derived_probe* p)
      76                 :            : {
      77         [ -  + ]:      16766 :   assert(p->session_index != (unsigned)-1);
      78 [ +  - ][ +  - ]:      16766 :   return "(&stap_probes[" + lex_cast(p->session_index) + "])";
                 [ +  - ]
      79                 :            : }
      80                 :            : 
      81                 :            : 
      82                 :            : void
      83                 :       1937 : common_probe_entryfn_prologue (systemtap_session& s,
      84                 :            :                                string statestr, string probe,
      85                 :            :                                string probe_type, bool overload_processing)
      86                 :            : {
      87         [ -  + ]:       1937 :   if (s.runtime_usermode_p())
      88                 :          0 :     s.op->newline() << "int _stp_saved_errno = errno;";
      89                 :       1937 :   s.op->newline() << "#ifdef STP_ALIBI";
      90                 :       1937 :   s.op->newline() << "atomic_inc(probe_alibi(" << probe << "->index));";
      91                 :       1937 :   s.op->newline() << "#else";
      92                 :            : 
      93                 :       1937 :   s.op->newline() << "struct context* __restrict__ c;";
      94                 :       1937 :   s.op->newline() << "#if !INTERRUPTIBLE";
      95                 :       1937 :   s.op->newline() << "unsigned long flags;";
      96                 :       1937 :   s.op->newline() << "#endif";
      97                 :            : 
      98                 :       1937 :   s.op->newline() << "#ifdef STP_TIMING";
      99                 :       1937 :   s.op->newline() << "Stat stat = probe_timing(" << probe << "->index);";
     100                 :       1937 :   s.op->newline() << "#endif";
     101 [ +  + ][ +  - ]:       1937 :   if (overload_processing && !s.runtime_usermode_p())
                 [ +  + ]
     102                 :       1448 :     s.op->newline() << "#if defined(STP_TIMING) || defined(STP_OVERLOAD)";
     103                 :            :   else
     104                 :        489 :     s.op->newline() << "#ifdef STP_TIMING";
     105                 :            : 
     106         [ +  - ]:       1937 :   if (! s.runtime_usermode_p())
     107                 :       1937 :     s.op->newline() << "cycles_t cycles_atstart = get_cycles ();";
     108                 :            :   else
     109                 :            :     {
     110                 :          0 :     s.op->newline() << "struct timespec timespec_atstart;";
     111                 :          0 :     s.op->newline() << "(void)clock_gettime(CLOCK_MONOTONIC_RAW, &timespec_atstart);";
     112                 :            :     }
     113                 :       1937 :   s.op->newline() << "#endif";
     114                 :            : 
     115                 :       1937 :   s.op->newline() << "#if INTERRUPTIBLE";
     116                 :       1937 :   s.op->newline() << "preempt_disable ();";
     117                 :       1937 :   s.op->newline() << "#else";
     118                 :       1937 :   s.op->newline() << "local_irq_save (flags);";
     119                 :       1937 :   s.op->newline() << "#endif";
     120                 :            : 
     121         [ +  - ]:       1937 :   if (! s.runtime_usermode_p())
     122                 :            :     {
     123                 :            :       // Check for enough free enough stack space
     124                 :       1937 :       s.op->newline() << "if (unlikely ((((unsigned long) (& c)) & (THREAD_SIZE-1))"; // free space
     125                 :       1937 :       s.op->newline(1) << "< (MINSTACKSPACE + sizeof (struct thread_info)))) {"; // needed space
     126                 :            :       // XXX: may need porting to platforms where task_struct is not
     127                 :            :       // at bottom of kernel stack NB: see also
     128                 :            :       // CONFIG_DEBUG_STACKOVERFLOW
     129                 :       1937 :       s.op->newline() << "atomic_inc (skipped_count());";
     130                 :       1937 :       s.op->newline() << "#ifdef STP_TIMING";
     131                 :       1937 :       s.op->newline() << "atomic_inc (skipped_count_lowstack());";
     132                 :       1937 :       s.op->newline() << "#endif";
     133                 :       1937 :       s.op->newline() << "goto probe_epilogue;";
     134                 :       1937 :       s.op->newline(-1) << "}";
     135                 :            :     }
     136                 :            : 
     137                 :       1937 :   s.op->newline() << "if (atomic_read (session_state()) != " << statestr << ")";
     138                 :       1937 :   s.op->newline(1) << "goto probe_epilogue;";
     139                 :       1937 :   s.op->indent(-1);
     140                 :            : 
     141                 :       1937 :   s.op->newline() << "c = _stp_runtime_entryfn_get_context();";
     142         [ -  + ]:       1937 :   if (s.runtime_usermode_p())
     143                 :            :     {
     144                 :          0 :       s.op->newline() << "if (!c) {";
     145                 :          0 :       s.op->newline(1) << "#if !INTERRUPTIBLE";
     146                 :          0 :       s.op->newline() << "atomic_inc (skipped_count());";
     147                 :          0 :       s.op->newline() << "#endif";
     148                 :          0 :       s.op->newline() << "#ifdef STP_TIMING";
     149                 :          0 :       s.op->newline() << "atomic_inc (skipped_count_reentrant());";
     150                 :          0 :       s.op->newline() << "#ifdef DEBUG_REENTRANCY";
     151                 :          0 :       s.op->newline() << "_stp_warn (\"Skipped %s\\n\", " << probe << "->pp);";
     152                 :          0 :       s.op->newline() << "#endif";
     153                 :          0 :       s.op->newline() << "#endif";
     154                 :          0 :       s.op->newline() << "goto probe_epilogue;";
     155                 :          0 :       s.op->newline(-1) << "}";
     156                 :            :     }
     157                 :            : 
     158                 :       1937 :   s.op->newline() << "if (atomic_inc_return (& c->busy) != 1) {";
     159                 :       1937 :   s.op->newline(1) << "#if !INTERRUPTIBLE";
     160                 :       1937 :   s.op->newline() << "atomic_inc (skipped_count());";
     161                 :       1937 :   s.op->newline() << "#endif";
     162                 :       1937 :   s.op->newline() << "#ifdef STP_TIMING";
     163                 :       1937 :   s.op->newline() << "atomic_inc (skipped_count_reentrant());";
     164                 :       1937 :   s.op->newline() << "#ifdef DEBUG_REENTRANCY";
     165                 :       1937 :   s.op->newline() << "_stp_warn (\"Skipped %s due to %s residency on cpu %u\\n\", "
     166                 :       1937 :                << probe << "->pp, c->probe_point ?: \"?\", smp_processor_id());";
     167                 :            :   // NB: There is a conceivable race condition here with reading
     168                 :            :   // c->probe_point, knowing that this other probe is sort of running.
     169                 :            :   // However, in reality, it's interrupted.  Plus even if it were able
     170                 :            :   // to somehow start again, and stop before we read c->probe_point,
     171                 :            :   // at least we have that   ?: "?"  bit in there to avoid a NULL deref.
     172                 :       1937 :   s.op->newline() << "#endif";
     173                 :       1937 :   s.op->newline() << "#endif";
     174                 :       1937 :   s.op->newline() << "atomic_dec (& c->busy);";
     175                 :       1937 :   s.op->newline() << "goto probe_epilogue;";
     176                 :       1937 :   s.op->newline(-1) << "}";
     177                 :       1937 :   s.op->newline();
     178                 :       1937 :   s.op->newline() << "c->last_stmt = 0;";
     179                 :       1937 :   s.op->newline() << "c->last_error = 0;";
     180                 :       1937 :   s.op->newline() << "c->nesting = -1;"; // NB: PR10516 packs locals[] tighter
     181                 :       1937 :   s.op->newline() << "c->uregs = 0;";
     182                 :       1937 :   s.op->newline() << "c->kregs = 0;";
     183                 :       1937 :   s.op->newline() << "#if defined __ia64__";
     184                 :       1937 :   s.op->newline() << "c->unwaddr = 0;";
     185                 :       1937 :   s.op->newline() << "#endif";
     186         [ -  + ]:       1937 :   if (s.runtime_usermode_p())
     187                 :          0 :     s.op->newline() << "c->probe_index = " << probe << "->index;";
     188                 :       1937 :   s.op->newline() << "c->probe_point = " << probe << "->pp;";
     189                 :       1937 :   s.op->newline() << "#ifdef STP_NEED_PROBE_NAME";
     190                 :       1937 :   s.op->newline() << "c->probe_name = " << probe << "->pn;";
     191                 :       1937 :   s.op->newline() << "#endif";
     192                 :       1937 :   s.op->newline() << "c->probe_type = " << probe_type << ";";
     193                 :            :   // reset Individual Probe State union
     194                 :       1937 :   s.op->newline() << "memset(&c->ips, 0, sizeof(c->ips));";
     195                 :       1937 :   s.op->newline() << "c->user_mode_p = 0; c->full_uregs_p = 0;";
     196                 :       1937 :   s.op->newline() << "#ifdef STAP_NEED_REGPARM"; // i386 or x86_64 register.stp
     197                 :       1937 :   s.op->newline() << "c->regparm = 0;";
     198                 :       1937 :   s.op->newline() << "#endif";
     199                 :            : 
     200         [ +  + ]:       1937 :   if(!s.suppress_time_limits){
     201                 :       1936 :     s.op->newline() << "#if INTERRUPTIBLE";
     202                 :       1936 :     s.op->newline() << "c->actionremaining = MAXACTION_INTERRUPTIBLE;";
     203                 :       1936 :     s.op->newline() << "#else";
     204                 :       1936 :     s.op->newline() << "c->actionremaining = MAXACTION;";
     205                 :       1936 :     s.op->newline() << "#endif";
     206                 :            :   }
     207                 :            :   // NB: The following would actually be incorrect.
     208                 :            :   // That's because cycles_sum/cycles_base values are supposed to survive
     209                 :            :   // between consecutive probes.  Periodically (STP_OVERLOAD_INTERVAL
     210                 :            :   // cycles), the values will be reset.
     211                 :            :   /*
     212                 :            :   s.op->newline() << "#ifdef STP_OVERLOAD";
     213                 :            :   s.op->newline() << "c->cycles_sum = 0;";
     214                 :            :   s.op->newline() << "c->cycles_base = 0;";
     215                 :            :   s.op->newline() << "#endif";
     216                 :            :   */
     217                 :            : 
     218                 :       1937 :   s.op->newline() << "#if defined(STP_NEED_UNWIND_DATA)";
     219                 :       1937 :   s.op->newline() << "c->uwcache_user.state = uwcache_uninitialized;";
     220                 :       1937 :   s.op->newline() << "c->uwcache_kernel.state = uwcache_uninitialized;";
     221                 :       1937 :   s.op->newline() << "#endif";
     222                 :       1937 : }
     223                 :            : 
     224                 :            : 
     225                 :            : void
     226                 :       1937 : common_probe_entryfn_epilogue (systemtap_session& s,
     227                 :            :                                bool overload_processing)
     228                 :            : {
     229 [ +  + ][ +  - ]:       1937 :   if (overload_processing && !s.runtime_usermode_p())
                 [ +  + ]
     230                 :       1448 :     s.op->newline() << "#if defined(STP_TIMING) || defined(STP_OVERLOAD)";
     231                 :            :   else
     232                 :        489 :     s.op->newline() << "#ifdef STP_TIMING";
     233                 :       1937 :   s.op->newline() << "{";
     234                 :       1937 :   s.op->indent(1);
     235         [ +  - ]:       1937 :   if (! s.runtime_usermode_p())
     236                 :            :     {
     237                 :       1937 :       s.op->newline() << "cycles_t cycles_atend = get_cycles ();";
     238                 :            :       // NB: we truncate cycles counts to 32 bits.  Perhaps it should be
     239                 :            :       // fewer, if the hardware counter rolls over really quickly.  We
     240                 :            :       // handle 32-bit wraparound here.
     241                 :       1937 :       s.op->newline() << "int32_t cycles_elapsed = ((int32_t)cycles_atend > (int32_t)cycles_atstart)";
     242                 :       1937 :       s.op->newline(1) << "? ((int32_t)cycles_atend - (int32_t)cycles_atstart)";
     243                 :       1937 :       s.op->newline() << ": (~(int32_t)0) - (int32_t)cycles_atstart + (int32_t)cycles_atend + 1;";
     244                 :       1937 :       s.op->indent(-1);
     245                 :            :     }
     246                 :            :   else
     247                 :            :     {
     248                 :          0 :       s.op->newline() << "struct timespec timespec_atend, timespec_elapsed;";
     249                 :          0 :       s.op->newline() << "long cycles_elapsed;";
     250                 :          0 :       s.op->newline() << "(void)clock_gettime(CLOCK_MONOTONIC_RAW, &timespec_atend);";
     251                 :          0 :       s.op->newline() << "_stp_timespec_sub(&timespec_atend, &timespec_atstart, &timespec_elapsed);";
     252                 :            :       // 'cycles_elapsed' is really elapsed nanoseconds
     253                 :          0 :       s.op->newline() << "cycles_elapsed = (timespec_elapsed.tv_sec * NSEC_PER_SEC) + timespec_elapsed.tv_nsec;";
     254                 :            :     }
     255                 :            : 
     256                 :       1937 :   s.op->newline() << "#ifdef STP_TIMING";
     257                 :       1937 :   s.op->newline() << "if (likely (stat)) _stp_stat_add(stat, cycles_elapsed);";
     258                 :       1937 :   s.op->newline() << "#endif";
     259                 :            : 
     260 [ +  + ][ +  - ]:       1937 :   if (overload_processing && !s.runtime_usermode_p())
                 [ +  + ]
     261                 :            :     {
     262                 :       1448 :       s.op->newline() << "#ifdef STP_OVERLOAD";
     263                 :       1448 :       s.op->newline() << "{";
     264                 :            :       // If the cycle count has wrapped (cycles_atend > cycles_base),
     265                 :            :       // let's go ahead and pretend the interval has been reached.
     266                 :            :       // This should reset cycles_base and cycles_sum.
     267                 :       1448 :       s.op->newline(1) << "cycles_t interval = (cycles_atend > c->cycles_base)";
     268                 :       1448 :       s.op->newline(1) << "? (cycles_atend - c->cycles_base)";
     269                 :       1448 :       s.op->newline() << ": (STP_OVERLOAD_INTERVAL + 1);";
     270                 :       1448 :       s.op->newline(-1) << "c->cycles_sum += cycles_elapsed;";
     271                 :            : 
     272                 :            :       // If we've spent more than STP_OVERLOAD_THRESHOLD cycles in a
     273                 :            :       // probe during the last STP_OVERLOAD_INTERVAL cycles, the probe
     274                 :            :       // has overloaded the system and we need to quit.
     275                 :            :       // NB: this is not suppressible via --suppress-runtime-errors,
     276                 :            :       // because this is a system safety metric that we cannot trust
     277                 :            :       // unprivileged users to override.
     278                 :       1448 :       s.op->newline() << "if (interval > STP_OVERLOAD_INTERVAL) {";
     279                 :       1448 :       s.op->newline(1) << "if (c->cycles_sum > STP_OVERLOAD_THRESHOLD) {";
     280                 :       1448 :       s.op->newline(1) << "_stp_error (\"probe overhead exceeded threshold\");";
     281                 :       1448 :       s.op->newline() << "atomic_set (session_state(), STAP_SESSION_ERROR);";
     282                 :       1448 :       s.op->newline() << "atomic_inc (error_count());";
     283                 :       1448 :       s.op->newline(-1) << "}";
     284                 :            : 
     285                 :       1448 :       s.op->newline() << "c->cycles_base = cycles_atend;";
     286                 :       1448 :       s.op->newline() << "c->cycles_sum = 0;";
     287                 :       1448 :       s.op->newline(-1) << "}";
     288                 :       1448 :       s.op->newline(-1) << "}";
     289                 :       1448 :       s.op->newline() << "#endif";
     290                 :            :     }
     291                 :            : 
     292                 :       1937 :   s.op->newline(-1) << "}";
     293                 :       1937 :   s.op->newline() << "#endif";
     294                 :            : 
     295                 :       1937 :   s.op->newline() << "c->probe_point = 0;"; // vacated
     296                 :       1937 :   s.op->newline() << "#ifdef STP_NEED_PROBE_NAME";
     297                 :       1937 :   s.op->newline() << "c->probe_name = 0;";
     298                 :       1937 :   s.op->newline() << "#endif";
     299                 :       1937 :   s.op->newline() << "c->probe_type = 0;";
     300                 :            : 
     301                 :            : 
     302                 :       1937 :   s.op->newline() << "if (unlikely (c->last_error && c->last_error[0])) {";
     303                 :       1937 :   s.op->indent(1);
     304         [ +  + ]:       1937 :   if (s.suppress_handler_errors) // PR 13306
     305                 :            :     { 
     306                 :          6 :       s.op->newline() << "atomic_inc (error_count());";
     307                 :            :     }
     308                 :            :   else
     309                 :            :     {
     310                 :       1931 :       s.op->newline() << "if (c->last_stmt != NULL)";
     311                 :       1931 :       s.op->newline(1) << "_stp_softerror (\"%s near %s\", c->last_error, c->last_stmt);";
     312                 :       1931 :       s.op->newline(-1) << "else";
     313                 :       1931 :       s.op->newline(1) << "_stp_softerror (\"%s\", c->last_error);";
     314                 :       1931 :       s.op->indent(-1);
     315                 :       1931 :       s.op->newline() << "atomic_inc (error_count());";
     316                 :       1931 :       s.op->newline() << "if (atomic_read (error_count()) > MAXERRORS) {";
     317                 :       1931 :       s.op->newline(1) << "atomic_set (session_state(), STAP_SESSION_ERROR);";
     318                 :       1931 :       s.op->newline() << "_stp_exit ();";
     319                 :       1931 :       s.op->newline(-1) << "}";
     320                 :            :     }
     321                 :            : 
     322                 :       1937 :   s.op->newline(-1) << "}";
     323                 :            : 
     324                 :            : 
     325                 :       1937 :   s.op->newline() << "atomic_dec (&c->busy);";
     326                 :            : 
     327                 :       1937 :   s.op->newline(-1) << "probe_epilogue:"; // context is free
     328                 :       1937 :   s.op->indent(1);
     329                 :            : 
     330                 :       1937 :   s.op->newline() << "_stp_runtime_entryfn_put_context();";
     331         [ +  + ]:       1937 :   if (! s.suppress_handler_errors) // PR 13306
     332                 :            :     {
     333                 :            :       // Check for excessive skip counts.
     334                 :       1931 :       s.op->newline() << "if (unlikely (atomic_read (skipped_count()) > MAXSKIPPED)) {";
     335                 :       1931 :       s.op->newline(1) << "if (unlikely (pseudo_atomic_cmpxchg(session_state(), STAP_SESSION_RUNNING, STAP_SESSION_ERROR) == STAP_SESSION_RUNNING))";
     336                 :       1931 :       s.op->newline() << "_stp_error (\"Skipped too many probes, check MAXSKIPPED or try again with stap -t for more details.\");";
     337                 :       1931 :       s.op->newline(-1) << "}";
     338                 :            :     }
     339                 :            : 
     340                 :       1937 :   s.op->newline() << "#if INTERRUPTIBLE";
     341                 :       1937 :   s.op->newline() << "preempt_enable_no_resched ();";
     342                 :       1937 :   s.op->newline() << "#else";
     343                 :       1937 :   s.op->newline() << "local_irq_restore (flags);";
     344                 :       1937 :   s.op->newline() << "#endif";
     345                 :            : 
     346                 :       1937 :   s.op->newline() << "#endif // STP_ALIBI";
     347         [ -  + ]:       1937 :   if (s.runtime_usermode_p())
     348                 :          0 :     s.op->newline() << "errno = _stp_saved_errno;";
     349                 :       1937 : }
     350                 :            : 
     351                 :            : 
     352                 :            : // ------------------------------------------------------------------------
     353                 :            : 
     354                 :            : // ------------------------------------------------------------------------
     355                 :            : //  Dwarf derived probes.  "We apologize for the inconvience."
     356                 :            : // ------------------------------------------------------------------------
     357                 :            : 
     358         [ +  - ]:       2414 : static const string TOK_KERNEL("kernel");
     359         [ +  - ]:       2414 : static const string TOK_MODULE("module");
     360         [ +  - ]:       2414 : static const string TOK_FUNCTION("function");
     361         [ +  - ]:       2414 : static const string TOK_INLINE("inline");
     362         [ +  - ]:       2414 : static const string TOK_CALL("call");
     363         [ +  - ]:       2414 : static const string TOK_EXPORTED("exported");
     364         [ +  - ]:       2414 : static const string TOK_RETURN("return");
     365         [ +  - ]:       2414 : static const string TOK_MAXACTIVE("maxactive");
     366         [ +  - ]:       2414 : static const string TOK_STATEMENT("statement");
     367         [ +  - ]:       2414 : static const string TOK_ABSOLUTE("absolute");
     368         [ +  - ]:       2414 : static const string TOK_PROCESS("process");
     369         [ +  - ]:       2414 : static const string TOK_PROVIDER("provider");
     370         [ +  - ]:       2414 : static const string TOK_MARK("mark");
     371         [ +  - ]:       2414 : static const string TOK_TRACE("trace");
     372         [ +  - ]:       2414 : static const string TOK_LABEL("label");
     373         [ +  - ]:       2414 : static const string TOK_LIBRARY("library");
     374         [ +  - ]:       2414 : static const string TOK_PLT("plt");
     375                 :            : 
     376                 :            : static int query_cu (Dwarf_Die * cudie, void * arg);
     377                 :            : static void query_addr(Dwarf_Addr addr, dwarf_query *q);
     378                 :            : 
     379                 :            : // Can we handle this query with just symbol-table info?
     380                 :            : enum dbinfo_reqt
     381                 :            : {
     382                 :            :   dbr_unknown,
     383                 :            :   dbr_none,             // kernel.statement(NUM).absolute
     384                 :            :   dbr_need_symtab,      // can get by with symbol table if there's no dwarf
     385                 :            :   dbr_need_dwarf
     386                 :            : };
     387                 :            : 
     388                 :            : 
     389                 :            : struct base_query; // forward decls
     390                 :            : struct dwarf_query;
     391                 :            : struct dwflpp;
     392                 :            : struct symbol_table;
     393                 :            : 
     394                 :            : 
     395                 :            : struct
     396                 :            : symbol_table
     397                 :            : {
     398                 :            :   module_info *mod_info;        // associated module
     399                 :            :   map<string, func_info*> map_by_name;
     400                 :            :   multimap<Dwarf_Addr, func_info*> map_by_addr;
     401                 :            :   typedef multimap<Dwarf_Addr, func_info*>::iterator iterator_t;
     402                 :            :   typedef pair<iterator_t, iterator_t> range_t;
     403                 :            : #ifdef __powerpc__
     404                 :            :   GElf_Word opd_section;
     405                 :            : #endif
     406                 :            :   void add_symbol(const char *name, bool weak, bool descriptor,
     407                 :            :                   Dwarf_Addr addr, Dwarf_Addr *high_addr);
     408                 :            :   enum info_status read_symbols(FILE *f, const string& path);
     409                 :            :   enum info_status read_from_elf_file(const string& path,
     410                 :            :                                       systemtap_session &sess);
     411                 :            :   enum info_status read_from_text_file(const string& path,
     412                 :            :                                        systemtap_session &sess);
     413                 :            :   enum info_status get_from_elf();
     414                 :            :   void prepare_section_rejection(Dwfl_Module *mod);
     415                 :            :   bool reject_section(GElf_Word section);
     416                 :            :   void purge_syscall_stubs();
     417                 :            :   func_info *lookup_symbol(const string& name);
     418                 :            :   Dwarf_Addr lookup_symbol_address(const string& name);
     419                 :            :   func_info *get_func_containing_address(Dwarf_Addr addr);
     420                 :            :   func_info *get_first_func();
     421                 :            : 
     422         [ +  - ]:        749 :   symbol_table(module_info *mi) : mod_info(mi) {}
     423                 :            :   ~symbol_table();
     424                 :            : };
     425                 :            : 
     426                 :     363250 : static bool null_die(Dwarf_Die *die)
     427                 :            : {
     428                 :            :   static Dwarf_Die null;
     429 [ +  + ][ -  + ]:     363250 :   return (!die || !memcmp(die, &null, sizeof(null)));
     430                 :            : }
     431                 :            : 
     432                 :            : 
     433                 :            : enum
     434                 :            : function_spec_type
     435                 :            :   {
     436                 :            :     function_alone,
     437                 :            :     function_and_file,
     438                 :            :     function_file_and_line
     439                 :            :   };
     440                 :            : 
     441                 :            : 
     442                 :            : struct dwarf_builder;
     443                 :            : struct dwarf_var_expanding_visitor;
     444                 :            : 
     445                 :            : 
     446                 :            : // XXX: This class is a candidate for subclassing to separate
     447                 :            : // the relocation vs non-relocation variants.  Likewise for
     448                 :            : // kprobe vs kretprobe variants.
     449                 :            : 
     450 [ #  # ][ #  # ]:          0 : struct dwarf_derived_probe: public derived_probe
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
     451                 :            : {
     452                 :            :   dwarf_derived_probe (const string& function,
     453                 :            :                        const string& filename,
     454                 :            :                        int line,
     455                 :            :                        const string& module,
     456                 :            :                        const string& section,
     457                 :            :                        Dwarf_Addr dwfl_addr,
     458                 :            :                        Dwarf_Addr addr,
     459                 :            :                        dwarf_query & q,
     460                 :            :                        Dwarf_Die* scope_die);
     461                 :            : 
     462                 :            :   string module;
     463                 :            :   string section;
     464                 :            :   Dwarf_Addr addr;
     465                 :            :   string path;
     466                 :            :   bool has_process;
     467                 :            :   bool has_return;
     468                 :            :   bool has_maxactive;
     469                 :            :   bool has_library;
     470                 :            :   long maxactive_val;
     471                 :            :   // dwarf_derived_probe_group::emit_module_decls uses this to emit sdt kprobe definition
     472                 :            :   string user_path;
     473                 :            :   string user_lib;
     474                 :            :   bool access_vars;
     475                 :            : 
     476                 :            :   unsigned saved_longs, saved_strings;
     477                 :            :   dwarf_derived_probe* entry_handler;
     478                 :            : 
     479                 :            :   void printsig (std::ostream &o) const;
     480                 :            :   virtual void join_group (systemtap_session& s);
     481                 :            :   void emit_probe_local_init(systemtap_session& s, translator_output * o);
     482                 :            :   void getargs(std::list<std::string> &arg_set) const;
     483                 :            : 
     484                 :            :   void emit_privilege_assertion (translator_output*);
     485                 :            :   void print_dupe_stamp(ostream& o);
     486                 :            : 
     487                 :            :   // Pattern registration helpers.
     488                 :            :   static void register_statement_variants(match_node * root,
     489                 :            :                                           dwarf_builder * dw,
     490                 :            :                                           privilege_t privilege);
     491                 :            :   static void register_function_variants(match_node * root,
     492                 :            :                                          dwarf_builder * dw,
     493                 :            :                                          privilege_t privilege);
     494                 :            :   static void register_function_and_statement_variants(systemtap_session& s,
     495                 :            :                                                        match_node * root,
     496                 :            :                                                        dwarf_builder * dw,
     497                 :            :                                                        privilege_t privilege);
     498                 :            :   static void register_sdt_variants(systemtap_session& s,
     499                 :            :                                     match_node * root,
     500                 :            :                                     dwarf_builder * dw);
     501                 :            :   static void register_plt_variants(systemtap_session& s,
     502                 :            :                                     match_node * root,
     503                 :            :                                     dwarf_builder * dw);
     504                 :            :   static void register_patterns(systemtap_session& s);
     505                 :            : 
     506                 :            : protected:
     507                 :          1 :   dwarf_derived_probe(probe *base,
     508                 :            :                       probe_point *location,
     509                 :            :                       Dwarf_Addr addr,
     510                 :            :                       bool has_return):
     511                 :            :     derived_probe(base, location), addr(addr), has_process(0),
     512                 :            :     has_return(has_return), has_maxactive(0), has_library(0),
     513                 :            :     maxactive_val(0), access_vars(false), saved_longs(0),
     514 [ +  - ][ +  - ]:          1 :     saved_strings(0), entry_handler(0)
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
     515                 :          1 :   {}
     516                 :            : 
     517                 :            : private:
     518                 :            :   list<string> args;
     519                 :            :   void saveargs(dwarf_query& q, Dwarf_Die* scope_die, Dwarf_Addr dwfl_addr);
     520                 :            : };
     521                 :            : 
     522                 :            : 
     523 [ #  # ][ #  # ]:          0 : struct uprobe_derived_probe: public dwarf_derived_probe
     524                 :            : {
     525                 :            :   int pid; // 0 => unrestricted
     526                 :            : 
     527                 :      11862 :   uprobe_derived_probe (const string& function,
     528                 :            :                         const string& filename,
     529                 :            :                         int line,
     530                 :            :                         const string& module,
     531                 :            :                         const string& section,
     532                 :            :                         Dwarf_Addr dwfl_addr,
     533                 :            :                         Dwarf_Addr addr,
     534                 :            :                         dwarf_query & q,
     535                 :            :                         Dwarf_Die* scope_die):
     536                 :            :     dwarf_derived_probe(function, filename, line, module, section,
     537         [ +  - ]:      11862 :                         dwfl_addr, addr, q, scope_die), pid(0)
     538                 :      11860 :   {}
     539                 :            : 
     540                 :            :   // alternate constructor for process(PID).statement(ADDR).absolute
     541                 :          1 :   uprobe_derived_probe (probe *base,
     542                 :            :                         probe_point *location,
     543                 :            :                         int pid,
     544                 :            :                         Dwarf_Addr addr,
     545                 :            :                         bool has_return):
     546         [ +  - ]:          1 :     dwarf_derived_probe(base, location, addr, has_return), pid(pid)
     547                 :          1 :   {}
     548                 :            : 
     549                 :            :   void join_group (systemtap_session& s);
     550                 :            : 
     551                 :            :   void emit_privilege_assertion (translator_output*);
     552                 :         12 :   void print_dupe_stamp(ostream& o) { print_dupe_stamp_unprivileged_process_owner (o); }
     553                 :            :   void getargs(std::list<std::string> &arg_set) const;
     554                 :            :   void saveargs(int nargs);
     555                 :            : private:
     556                 :            :   list<string> args;
     557                 :            : };
     558                 :            : 
     559 [ #  # ][ #  # ]:          0 : struct dwarf_derived_probe_group: public derived_probe_group
     560                 :            : {
     561                 :            : private:
     562                 :            :   multimap<string,dwarf_derived_probe*> probes_by_module;
     563                 :            :   typedef multimap<string,dwarf_derived_probe*>::iterator p_b_m_iterator;
     564                 :            : 
     565                 :            : public:
     566         [ +  - ]:        385 :   dwarf_derived_probe_group() {}
     567                 :            :   void enroll (dwarf_derived_probe* probe);
     568                 :            :   void emit_module_decls (systemtap_session& s);
     569                 :            :   void emit_module_init (systemtap_session& s);
     570                 :            :   void emit_module_refresh (systemtap_session& s);
     571                 :            :   void emit_module_exit (systemtap_session& s);
     572                 :            : };
     573                 :            : 
     574                 :            : 
     575                 :            : // Helper struct to thread through the dwfl callbacks.
     576                 :            : struct base_query
     577                 :            : {
     578                 :            :   base_query(dwflpp & dw, literal_map_t const & params);
     579                 :            :   base_query(dwflpp & dw, const string & module_val);
     580 [ +  - ][ +  - ]:      56863 :   virtual ~base_query() {}
                 [ -  + ]
     581                 :            : 
     582                 :            :   systemtap_session & sess;
     583                 :            :   dwflpp & dw;
     584                 :            : 
     585                 :            :   // Parameter extractors.
     586                 :            :   static bool has_null_param(literal_map_t const & params,
     587                 :            :                              string const & k);
     588                 :            :   static bool get_string_param(literal_map_t const & params,
     589                 :            :                                string const & k, string & v);
     590                 :            :   static bool get_number_param(literal_map_t const & params,
     591                 :            :                                string const & k, long & v);
     592                 :            :   static bool get_number_param(literal_map_t const & params,
     593                 :            :                                string const & k, Dwarf_Addr & v);
     594                 :            :   static void query_library_callback (void *object, const char *data);
     595                 :            :   static void query_plt_callback (void *object, const char *link, size_t addr);
     596                 :            :   virtual void query_library (const char *data) = 0;
     597                 :            :   virtual void query_plt (const char *link, size_t addr) = 0;
     598                 :            : 
     599                 :            : 
     600                 :            :   // Extracted parameters.
     601                 :            :   bool has_kernel;
     602                 :            :   bool has_module;
     603                 :            :   bool has_process;
     604                 :            :   bool has_library;
     605                 :            :   bool has_plt;
     606                 :            :   bool has_statement;
     607                 :            :   string module_val; // has_kernel => module_val = "kernel"
     608                 :            :   string path;       // executable path if module is a .so
     609                 :            :   string plt_val;    // has_plt => plt wildcard
     610                 :            : 
     611                 :            :   virtual void handle_query_module() = 0;
     612                 :            : };
     613                 :            : 
     614                 :            : 
     615                 :      46934 : base_query::base_query(dwflpp & dw, literal_map_t const & params):
     616 [ +  - ][ +  - ]:      46934 :   sess(dw.sess), dw(dw), has_library(false), has_plt(false), has_statement(false)
     617                 :            : {
     618         [ +  - ]:      46934 :   has_kernel = has_null_param (params, TOK_KERNEL);
     619         [ +  + ]:      46934 :   if (has_kernel)
     620         [ +  - ]:      44799 :     module_val = "kernel";
     621                 :            : 
     622         [ +  - ]:      46934 :   has_module = get_string_param (params, TOK_MODULE, module_val);
     623         [ +  + ]:      46934 :   if (has_module)
     624                 :       1999 :     has_process = false;
     625                 :            :   else
     626                 :            :     {
     627         [ +  - ]:      44935 :       string library_name;
     628                 :            :       long statement_num_val;
     629         [ +  - ]:      44935 :       has_process = get_string_param(params, TOK_PROCESS, module_val);
     630         [ +  - ]:      44935 :       has_library = get_string_param (params, TOK_LIBRARY, library_name);
     631 [ +  - ][ +  + ]:      44935 :       if ((has_plt = has_null_param (params, TOK_PLT)))
     632         [ +  - ]:         14 :         plt_val = "*";
     633         [ +  - ]:      44921 :       else has_plt = get_string_param (params, TOK_PLT, plt_val);
     634         [ +  + ]:      44935 :       if (has_plt)
     635                 :         14 :         sess.consult_symtab = true;
     636         [ +  - ]:      44935 :       has_statement = get_number_param(params, TOK_STATEMENT, statement_num_val);
     637                 :            : 
     638         [ +  + ]:      44935 :       if (has_process)
     639 [ +  - ][ +  - ]:        136 :         module_val = find_executable (module_val, sess.sysroot, sess.sysenv);
         [ +  - ][ +  - ]
                 [ +  - ]
     640         [ +  + ]:      44935 :       if (has_library)
     641                 :            :         {
     642 [ +  - ][ +  + ]:         12 :           if (! contains_glob_chars (library_name))
     643                 :            :             {
     644 [ +  - ][ +  - ]:         11 :               path = path_remove_sysroot(sess, module_val);
                 [ +  - ]
     645                 :            :               module_val = find_executable (library_name, sess.sysroot,
     646 [ +  - ][ +  - ]:         11 :                                             sess.sysenv, "LD_LIBRARY_PATH");
         [ +  - ][ +  - ]
                 [ +  - ]
     647 [ +  - ][ -  + ]:         11 :               if (module_val.find('/') == string::npos)
     648                 :            :                 {
     649                 :            :                   // We didn't find library_name so use iterate_over_libraries
     650         [ #  # ]:          0 :                   module_val = path;
     651         [ #  # ]:          0 :                   path = library_name;
     652                 :            :                 }
     653                 :            :             }
     654                 :            :           else
     655         [ +  - ]:          1 :             path = library_name;
     656         [ +  - ]:      44935 :         }
     657                 :            :     }
     658                 :            : 
     659 [ +  + ][ +  + ]:      46934 :   assert (has_kernel || has_process || has_module);
                 [ -  + ]
     660                 :      46934 : }
     661                 :            : 
     662                 :       9929 : base_query::base_query(dwflpp & dw, const string & module_val)
     663                 :            :   : sess(dw.sess), dw(dw), has_library(false), has_plt(false), has_statement(false),
     664 [ +  - ][ +  - ]:       9929 :     module_val(module_val)
     665                 :            : {
     666                 :            :   // NB: This uses '/' to distinguish between kernel modules and userspace,
     667                 :            :   // which means that userspace modules won't get any PATH searching.
     668 [ +  - ][ +  + ]:       9929 :   if (module_val.find('/') == string::npos)
     669                 :            :     {
     670         [ +  - ]:       5291 :       has_kernel = (module_val == TOK_KERNEL);
     671                 :       5291 :       has_module = !has_kernel;
     672                 :       5291 :       has_process = false;
     673                 :            :     }
     674                 :            :   else
     675                 :            :     {
     676                 :       4638 :       has_kernel = has_module = false;
     677                 :       4638 :       has_process = true;
     678                 :            :     }
     679                 :       9929 : }
     680                 :            : 
     681                 :            : bool
     682                 :     326459 : base_query::has_null_param(literal_map_t const & params,
     683                 :            :                            string const & k)
     684                 :            : {
     685                 :     326459 :   return derived_probe_builder::has_null_param(params, k);
     686                 :            : }
     687                 :            : 
     688                 :            : 
     689                 :            : bool
     690                 :     322511 : base_query::get_string_param(literal_map_t const & params,
     691                 :            :                              string const & k, string & v)
     692                 :            : {
     693                 :     322511 :   return derived_probe_builder::get_param (params, k, v);
     694                 :            : }
     695                 :            : 
     696                 :            : 
     697                 :            : bool
     698                 :      91853 : base_query::get_number_param(literal_map_t const & params,
     699                 :            :                              string const & k, long & v)
     700                 :            : {
     701                 :            :   int64_t value;
     702         [ +  - ]:      91853 :   bool present = derived_probe_builder::get_param (params, k, value);
     703                 :      91853 :   v = (long) value;
     704                 :      91853 :   return present;
     705                 :            : }
     706                 :            : 
     707                 :            : 
     708                 :            : bool
     709                 :      93836 : base_query::get_number_param(literal_map_t const & params,
     710                 :            :                              string const & k, Dwarf_Addr & v)
     711                 :            : {
     712                 :            :   int64_t value;
     713         [ +  - ]:      93836 :   bool present = derived_probe_builder::get_param (params, k, value);
     714                 :      93836 :   v = (Dwarf_Addr) value;
     715                 :      93836 :   return present;
     716                 :            : }
     717                 :            : 
     718 [ +  - ][ +  - ]:      46918 : struct dwarf_query : public base_query
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ -  + ]
     719                 :            : {
     720                 :            :   dwarf_query(probe * base_probe,
     721                 :            :               probe_point * base_loc,
     722                 :            :               dwflpp & dw,
     723                 :            :               literal_map_t const & params,
     724                 :            :               vector<derived_probe *> & results,
     725                 :            :               const string user_path,
     726                 :            :               const string user_lib);
     727                 :            : 
     728                 :            :   vector<derived_probe *> & results;
     729                 :            :   set<string> inlined_non_returnable; // function names
     730                 :            :   probe * base_probe;
     731                 :            :   probe_point * base_loc;
     732                 :            :   string user_path;
     733                 :            :   string user_lib;
     734                 :            : 
     735                 :            :   virtual void handle_query_module();
     736                 :            :   void query_module_dwarf();
     737                 :            :   void query_module_symtab();
     738                 :            :   void query_library (const char *data);
     739                 :            :   void query_plt (const char *entry, size_t addr);
     740                 :            : 
     741                 :            :   void add_probe_point(string const & funcname,
     742                 :            :                        char const * filename,
     743                 :            :                        int line,
     744                 :            :                        Dwarf_Die *scope_die,
     745                 :            :                        Dwarf_Addr addr);
     746                 :            : 
     747                 :            :   // Track addresses we've already seen in a given module
     748                 :            :   set<Dwarf_Addr> alias_dupes;
     749                 :            : 
     750                 :            :   // Track inlines we've already seen as well
     751                 :            :   // NB: this can't be compared just by entrypc, as inlines can overlap
     752                 :            :   set<inline_instance_info> inline_dupes;
     753                 :            : 
     754                 :            :   // Extracted parameters.
     755                 :            :   string function_val;
     756                 :            : 
     757                 :            :   bool has_function_str;
     758                 :            :   bool has_statement_str;
     759                 :            :   bool has_function_num;
     760                 :            :   bool has_statement_num;
     761                 :            :   string statement_str_val;
     762                 :            :   string function_str_val;
     763                 :            :   Dwarf_Addr statement_num_val;
     764                 :            :   Dwarf_Addr function_num_val;
     765                 :            : 
     766                 :            :   bool has_call;
     767                 :            :   bool has_exported;
     768                 :            :   bool has_inline;
     769                 :            :   bool has_return;
     770                 :            : 
     771                 :            :   bool has_maxactive;
     772                 :            :   long maxactive_val;
     773                 :            : 
     774                 :            :   bool has_label;
     775                 :            :   string label_val;
     776                 :            : 
     777                 :            :   bool has_relative;
     778                 :            :   long relative_val;
     779                 :            : 
     780                 :            :   bool has_absolute;
     781                 :            : 
     782                 :            :   bool has_mark;
     783                 :            : 
     784                 :            :   enum dbinfo_reqt dbinfo_reqt;
     785                 :            :   enum dbinfo_reqt assess_dbinfo_reqt();
     786                 :            : 
     787                 :            :   void parse_function_spec(const string & spec);
     788                 :            :   function_spec_type spec_type;
     789                 :            :   vector<string> scopes;
     790                 :            :   string function;
     791                 :            :   string file;
     792                 :            :   line_t line_type;
     793                 :            :   int line[2];
     794                 :            :   bool query_done;      // Found exact match
     795                 :            : 
     796                 :            :   set<string> filtered_srcfiles;
     797                 :            : 
     798                 :            :   // Map official entrypc -> func_info object
     799                 :            :   inline_instance_map_t filtered_inlines;
     800                 :            :   func_info_map_t filtered_functions;
     801                 :            :   bool choose_next_line;
     802                 :            :   Dwarf_Addr entrypc_for_next_line;
     803                 :            : 
     804                 :            :   void query_module_functions ();
     805                 :            : };
     806                 :            : 
     807                 :            : 
     808                 :            : static void delete_session_module_cache (systemtap_session& s); // forward decl
     809                 :            : 
     810                 :            : 
     811                 :            : struct dwarf_builder: public derived_probe_builder
     812                 :            : {
     813                 :            :   map <string,dwflpp*> kern_dw; /* NB: key string could be a wildcard */
     814                 :            :   map <string,dwflpp*> user_dw;
     815                 :            :   string user_path;
     816                 :            :   string user_lib;
     817 [ +  - ][ +  - ]:       1218 :   dwarf_builder() {}
         [ +  - ][ +  - ]
     818                 :            : 
     819                 :      56123 :   dwflpp *get_kern_dw(systemtap_session& sess, const string& module)
     820                 :            :   {
     821         [ +  + ]:      56123 :     if (kern_dw[module] == 0)
     822         [ +  + ]:        972 :       kern_dw[module] = new dwflpp(sess, module, true); // might throw
     823                 :      56121 :     return kern_dw[module];
     824                 :            :   }
     825                 :            : 
     826                 :         78 :   dwflpp *get_user_dw(systemtap_session& sess, const string& module)
     827                 :            :   {
     828         [ +  + ]:         78 :     if (user_dw[module] == 0)
     829         [ +  - ]:         67 :       user_dw[module] = new dwflpp(sess, module, false); // might throw
     830                 :         78 :     return user_dw[module];
     831                 :            :   }
     832                 :            : 
     833                 :            :   /* NB: not virtual, so can be called from dtor too: */
     834                 :     123060 :   void dwarf_build_no_more (bool)
     835                 :            :   {
     836                 :     123060 :     delete_map(kern_dw);
     837                 :     123060 :     delete_map(user_dw);
     838                 :     123060 :   }
     839                 :            : 
     840                 :     123060 :   void build_no_more (systemtap_session &s)
     841                 :            :   {
     842                 :     123060 :     dwarf_build_no_more (s.verbose > 3);
     843                 :     123060 :     delete_session_module_cache (s);
     844                 :     123060 :   }
     845                 :            : 
     846                 :          0 :   ~dwarf_builder()
     847                 :          0 :   {
     848         [ #  # ]:          0 :     dwarf_build_no_more (false);
     849 [ #  # ][ #  # ]:          0 :   }
         [ #  # ][ #  # ]
                 [ #  # ]
     850                 :            : 
     851                 :            :   virtual void build(systemtap_session & sess,
     852                 :            :                      probe * base,
     853                 :            :                      probe_point * location,
     854                 :            :                      literal_map_t const & parameters,
     855                 :            :                      vector<derived_probe *> & finished_results);
     856                 :            : };
     857                 :            : 
     858                 :            : 
     859                 :      46918 : dwarf_query::dwarf_query(probe * base_probe,
     860                 :            :                          probe_point * base_loc,
     861                 :            :                          dwflpp & dw,
     862                 :            :                          literal_map_t const & params,
     863                 :            :                          vector<derived_probe *> & results,
     864                 :            :                          const string user_path,
     865                 :            :                          const string user_lib)
     866                 :            :   : base_query(dw, params), results(results),
     867                 :            :     base_probe(base_probe), base_loc(base_loc),
     868                 :            :     user_path(user_path), user_lib(user_lib), has_relative(false),
     869 [ +  - ][ +  - ]:      46918 :     relative_val(0), choose_next_line(false), entrypc_for_next_line(0)
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
     870                 :            : {
     871                 :            :   // Reduce the query to more reasonable semantic values (booleans,
     872                 :            :   // extracted strings, numbers, etc).
     873         [ +  - ]:      46918 :   has_function_str = get_string_param(params, TOK_FUNCTION, function_str_val);
     874         [ +  - ]:      46918 :   has_function_num = get_number_param(params, TOK_FUNCTION, function_num_val);
     875                 :            : 
     876         [ +  - ]:      46918 :   has_statement_str = get_string_param(params, TOK_STATEMENT, statement_str_val);
     877         [ +  - ]:      46918 :   has_statement_num = get_number_param(params, TOK_STATEMENT, statement_num_val);
     878                 :            : 
     879         [ +  - ]:      46918 :   has_label = get_string_param(params, TOK_LABEL, label_val);
     880                 :            : 
     881         [ +  - ]:      46918 :   has_call = has_null_param(params, TOK_CALL);
     882         [ +  - ]:      46918 :   has_exported = has_null_param(params, TOK_EXPORTED);
     883         [ +  - ]:      46918 :   has_inline = has_null_param(params, TOK_INLINE);
     884         [ +  - ]:      46918 :   has_return = has_null_param(params, TOK_RETURN);
     885         [ +  - ]:      46918 :   has_maxactive = get_number_param(params, TOK_MAXACTIVE, maxactive_val);
     886         [ +  - ]:      46918 :   has_absolute = has_null_param(params, TOK_ABSOLUTE);
     887                 :      46918 :   has_mark = false;
     888                 :            : 
     889         [ +  + ]:      46918 :   if (has_function_str)
     890         [ +  - ]:      46799 :     parse_function_spec(function_str_val);
     891         [ +  + ]:        119 :   else if (has_statement_str)
     892         [ +  - ]:         27 :     parse_function_spec(statement_str_val);
     893                 :            : 
     894                 :      46918 :   dbinfo_reqt = assess_dbinfo_reqt();
     895                 :      46918 :   query_done = false;
     896                 :      46918 : }
     897                 :            : 
     898                 :            : 
     899                 :            : func_info_map_t *
     900                 :          2 : get_filtered_functions(dwarf_query *q)
     901                 :            : {
     902                 :          2 :   return &q->filtered_functions;
     903                 :            : }
     904                 :            : 
     905                 :            : 
     906                 :            : inline_instance_map_t *
     907                 :          0 : get_filtered_inlines(dwarf_query *q)
     908                 :            : {
     909                 :          0 :   return &q->filtered_inlines;
     910                 :            : }
     911                 :            : 
     912                 :            : 
     913                 :            : void
     914                 :      46693 : dwarf_query::query_module_dwarf()
     915                 :            : {
     916 [ +  - ][ +  + ]:      46693 :   if (has_function_num || has_statement_num)
     917                 :            :     {
     918                 :            :       // If we have module("foo").function(0xbeef) or
     919                 :            :       // module("foo").statement(0xbeef), the address is relative
     920                 :            :       // to the start of the module, so we seek the function
     921                 :            :       // number plus the module's bias.
     922                 :            :       Dwarf_Addr addr = has_function_num ?
     923         [ -  + ]:         25 :         function_num_val : statement_num_val;
     924                 :            : 
     925                 :            :       // These are raw addresses, we need to know what the elf_bias
     926                 :            :       // is to feed it to libdwfl based functions.
     927                 :            :       Dwarf_Addr elf_bias;
     928         [ +  - ]:         25 :       Elf *elf = dwfl_module_getelf (dw.module, &elf_bias);
     929         [ -  + ]:         25 :       assert(elf);
     930                 :         25 :       addr += elf_bias;
     931         [ +  - ]:         25 :       query_addr(addr, this);
     932                 :            :     }
     933                 :            :   else
     934                 :            :     {
     935                 :            :       // Otherwise if we have a function("foo") or statement("foo")
     936                 :            :       // specifier, we have to scan over all the CUs looking for
     937                 :            :       // the function(s) in question
     938 [ +  + ][ -  + ]:      46668 :       assert(has_function_str || has_statement_str);
     939                 :            : 
     940                 :            :       // For simple cases, no wildcard and no source:line, we can do a very
     941                 :            :       // quick function lookup in a module-wide cache.
     942   [ +  +  +  +  :     138894 :       if (spec_type == function_alone &&
           +  - ][ +  + ]
     943                 :      46574 :           !dw.name_has_wildcard(function) &&
     944                 :      45652 :           !startswith(function, "_Z"))
     945                 :      45652 :         query_module_functions();
     946                 :            :       else
     947                 :       1016 :         dw.iterate_over_cus(&query_cu, this, false);
     948                 :            :     }
     949                 :      46693 : }
     950                 :            : 
     951                 :            : static void query_func_info (Dwarf_Addr entrypc, func_info & fi,
     952                 :            :                                                         dwarf_query * q);
     953                 :            : 
     954                 :            : void
     955                 :          0 : dwarf_query::query_module_symtab()
     956                 :            : {
     957                 :            :   // Get the symbol table if it's necessary, sufficient, and not already got.
     958         [ #  # ]:          0 :   if (dbinfo_reqt == dbr_need_dwarf)
     959                 :          0 :     return;
     960                 :            : 
     961                 :          0 :   module_info *mi = dw.mod_info;
     962         [ #  # ]:          0 :   if (dbinfo_reqt == dbr_need_symtab)
     963                 :            :     {
     964         [ #  # ]:          0 :       if (mi->symtab_status == info_unknown)
     965                 :          0 :         mi->get_symtab(this);
     966         [ #  # ]:          0 :       if (mi->symtab_status == info_absent)
     967                 :          0 :         return;
     968                 :            :     }
     969                 :            : 
     970                 :          0 :   func_info *fi = NULL;
     971                 :          0 :   symbol_table *sym_table = mi->sym_table;
     972                 :            : 
     973         [ #  # ]:          0 :   if (has_function_str)
     974                 :            :     {
     975                 :            :       // Per dwarf_query::assess_dbinfo_reqt()...
     976         [ #  # ]:          0 :       assert(spec_type == function_alone);
     977         [ #  # ]:          0 :       if (dw.name_has_wildcard(function_str_val))
     978                 :            :         {
     979                 :            :           // Until we augment the blacklist sufficently...
     980 [ #  # ][ #  # ]:          0 :           if (function_str_val.find_first_not_of("*?") == string::npos)
     981                 :            :             {
     982                 :            :               // e.g., kernel.function("*")
     983 [ #  # ][ #  # ]:          0 :               cerr << _F("Error: Pattern '%s' matches every single "
         [ #  # ][ #  # ]
     984                 :            :                          "instruction address in the symbol table,\n"
     985         [ #  # ]:          0 :                          "some of which aren't even functions.\n", function_str_val.c_str()) << endl;
     986                 :            :               return;
     987                 :            :             }
     988                 :          0 :           symbol_table::iterator_t iter;
     989 [ #  # ][ #  # ]:          0 :           for (iter = sym_table->map_by_addr.begin();
     990         [ #  # ]:          0 :                iter != sym_table->map_by_addr.end();
     991                 :            :                ++iter)
     992                 :            :             {
     993         [ #  # ]:          0 :               fi = iter->second;
     994         [ #  # ]:          0 :               if (!null_die(&fi->die))
     995                 :          0 :                 continue;       // already handled in query_module_dwarf()
     996 [ #  # ][ #  # ]:          0 :               if (dw.function_name_matches_pattern(fi->name, function_str_val))
     997         [ #  # ]:          0 :                 query_func_info(fi->addr, *fi, this);
     998                 :            :             }
     999                 :            :         }
    1000                 :            :       else
    1001                 :            :         {
    1002                 :          0 :           fi = sym_table->lookup_symbol(function_str_val);
    1003 [ #  # ][ #  # ]:          0 :           if (fi && !fi->descriptor && null_die(&fi->die))
         [ #  # ][ #  # ]
    1004                 :          0 :             query_func_info(fi->addr, *fi, this);
    1005                 :            :         }
    1006                 :            :     }
    1007                 :            :   else
    1008                 :            :     {
    1009 [ #  # ][ #  # ]:          0 :       assert(has_function_num || has_statement_num);
    1010                 :            :       // Find the "function" in which the indicated address resides.
    1011                 :            :       Dwarf_Addr addr =
    1012         [ #  # ]:          0 :                 (has_function_num ? function_num_val : statement_num_val);
    1013         [ #  # ]:          0 :       if (has_plt)
    1014                 :            :         {
    1015                 :            :           // Use the raw address from the .plt
    1016                 :          0 :           fi = sym_table->get_first_func();
    1017                 :          0 :           fi->addr = addr;
    1018                 :            :         }
    1019                 :            :       else
    1020                 :          0 :         fi = sym_table->get_func_containing_address(addr);
    1021                 :            : 
    1022         [ #  # ]:          0 :       if (!fi)
    1023                 :            :         {
    1024                 :          0 :           sess.print_warning(_F("address %#" PRIx64 " out of range for module %s",
    1025         [ #  # ]:          0 :                   addr, dw.module_name.c_str()));
    1026                 :          0 :           return;
    1027                 :            :         }
    1028         [ #  # ]:          0 :       if (!null_die(&fi->die))
    1029                 :            :         {
    1030                 :            :           // addr looks like it's in the compilation unit containing
    1031                 :            :           // the indicated function, but query_module_dwarf() didn't
    1032                 :            :           // match addr to any compilation unit, so addr must be
    1033                 :            :           // above that cu's address range.
    1034                 :          0 :           sess.print_warning(_F("address %#" PRIx64 " maps to no known compilation unit in module %s",
    1035         [ #  # ]:          0 :                        addr, dw.module_name.c_str()));
    1036                 :          0 :           return;
    1037                 :            :         }
    1038                 :          0 :       query_func_info(fi->addr, *fi, this);
    1039                 :            :     }
    1040                 :            : }
    1041                 :            : 
    1042                 :            : void
    1043                 :      46701 : dwarf_query::handle_query_module()
    1044                 :            : {
    1045 [ +  + ][ +  - ]:      46701 :   bool report = dbinfo_reqt == dbr_need_dwarf || !sess.consult_symtab;
    1046                 :      46701 :   dw.get_module_dwarf(false, report);
    1047                 :            : 
    1048                 :            :   // prebuild the symbol table to resolve aliases
    1049                 :      46701 :   dw.mod_info->get_symtab(this);
    1050                 :            : 
    1051                 :            :   // reset the dupe-checking for each new module
    1052                 :      46701 :   alias_dupes.clear();
    1053                 :      46701 :   inline_dupes.clear();
    1054                 :            : 
    1055         [ +  + ]:      46701 :   if (dw.mod_info->dwarf_status == info_present)
    1056                 :      46693 :     query_module_dwarf();
    1057                 :            : 
    1058                 :            :   // Consult the symbol table if we haven't found all we're looking for.
    1059                 :            :   // asm functions can show up in the symbol table but not in dwarf.
    1060 [ -  + ][ #  # ]:      46701 :   if (sess.consult_symtab && !query_done)
    1061                 :          0 :     query_module_symtab();
    1062                 :      46701 : }
    1063                 :            : 
    1064                 :            : 
    1065                 :            : void
    1066                 :      46826 : dwarf_query::parse_function_spec(const string & spec)
    1067                 :            : {
    1068                 :      46826 :   line_type = ABSOLUTE;
    1069                 :      46826 :   line[0] = line[1] = 0;
    1070                 :            : 
    1071                 :            :   size_t src_pos, line_pos, dash_pos, scope_pos;
    1072                 :            : 
    1073                 :            :   // look for named scopes
    1074                 :      46826 :   scope_pos = spec.rfind("::");
    1075         [ -  + ]:      46826 :   if (scope_pos != string::npos)
    1076                 :            :     {
    1077         [ #  # ]:          0 :       tokenize_cxx(spec.substr(0, scope_pos), scopes);
    1078                 :          0 :       scope_pos += 2;
    1079                 :            :     }
    1080                 :            :   else
    1081                 :      46826 :     scope_pos = 0;
    1082                 :            : 
    1083                 :            :   // look for a source separator
    1084                 :      46826 :   src_pos = spec.find('@', scope_pos);
    1085         [ +  + ]:      46826 :   if (src_pos == string::npos)
    1086                 :            :     {
    1087         [ +  - ]:      46721 :       function = spec.substr(scope_pos);
    1088                 :      46721 :       spec_type = function_alone;
    1089                 :            :     }
    1090                 :            :   else
    1091                 :            :     {
    1092         [ +  - ]:        105 :       function = spec.substr(scope_pos, src_pos - scope_pos);
    1093                 :            : 
    1094                 :            :       // look for a line-number separator
    1095                 :        105 :       line_pos = spec.find_first_of(":+", src_pos);
    1096         [ +  + ]:        105 :       if (line_pos == string::npos)
    1097                 :            :         {
    1098         [ +  - ]:         82 :           file = spec.substr(src_pos + 1);
    1099                 :         82 :           spec_type = function_and_file;
    1100                 :            :         }
    1101                 :            :       else
    1102                 :            :         {
    1103         [ +  - ]:         23 :           file = spec.substr(src_pos + 1, line_pos - src_pos - 1);
    1104                 :            : 
    1105                 :            :           // classify the line spec
    1106                 :         23 :           spec_type = function_file_and_line;
    1107         [ +  + ]:         23 :           if (spec[line_pos] == '+')
    1108                 :          5 :             line_type = RELATIVE;
    1109   [ +  +  +  - ]:         24 :           else if (spec[line_pos + 1] == '*' &&
                 [ +  + ]
    1110                 :          6 :                    spec.length() == line_pos + 2)
    1111                 :          6 :             line_type = WILDCARD;
    1112                 :            :           else
    1113                 :         12 :             line_type = ABSOLUTE;
    1114                 :            : 
    1115         [ +  + ]:         23 :           if (line_type != WILDCARD)
    1116                 :            :             try
    1117                 :            :               {
    1118                 :            :                 // try to parse either N or N-M
    1119         [ +  - ]:         17 :                 dash_pos = spec.find('-', line_pos + 1);
    1120         [ +  - ]:         17 :                 if (dash_pos == string::npos)
    1121 [ +  - ][ +  - ]:         17 :                   line[0] = line[1] = lex_cast<int>(spec.substr(line_pos + 1));
                 [ +  - ]
    1122                 :            :                 else
    1123                 :            :                   {
    1124                 :          0 :                     line_type = RANGE;
    1125                 :            :                     line[0] = lex_cast<int>(spec.substr(line_pos + 1,
    1126 [ #  # ][ #  # ]:          0 :                                                         dash_pos - line_pos - 1));
                 [ #  # ]
    1127 [ #  # ][ #  # ]:          0 :                     line[1] = lex_cast<int>(spec.substr(dash_pos + 1));
         [ #  # ][ #  # ]
    1128                 :            :                   }
    1129                 :            :               }
    1130                 :            :             catch (runtime_error & exn)
    1131                 :            :               {
    1132                 :            :                 goto bad;
    1133                 :            :               }
    1134                 :            :         }
    1135                 :            :     }
    1136                 :            : 
    1137         [ +  - ]:      46931 :   if (function.empty() ||
           [ +  +  -  + ]
                 [ -  + ]
    1138                 :        105 :       (spec_type != function_alone && file.empty()))
    1139                 :          0 :     goto bad;
    1140                 :            : 
    1141         [ -  + ]:      46826 :   if (sess.verbose > 2)
    1142                 :            :     {
    1143                 :            :       //clog << "parsed '" << spec << "'";
    1144         [ #  # ]:          0 :       clog << _F("parse '%s'", spec.c_str());
    1145                 :            : 
    1146         [ #  # ]:          0 :       if (!scopes.empty())
    1147                 :          0 :         clog << ", scope '" << scopes[0] << "'";
    1148         [ #  # ]:          0 :       for (unsigned i = 1; i < scopes.size(); ++i)
    1149                 :          0 :         clog << "::'" << scopes[i] << "'";
    1150                 :            : 
    1151                 :          0 :       clog << ", func '" << function << "'";
    1152                 :            : 
    1153         [ #  # ]:          0 :       if (spec_type != function_alone)
    1154                 :          0 :         clog << ", file '" << file << "'";
    1155                 :            : 
    1156         [ #  # ]:          0 :       if (spec_type == function_file_and_line)
    1157                 :            :         {
    1158                 :          0 :           clog << ", line ";
    1159   [ #  #  #  #  :          0 :           switch (line_type)
                      # ]
    1160                 :            :             {
    1161                 :            :             case ABSOLUTE:
    1162                 :          0 :               clog << line[0];
    1163                 :          0 :               break;
    1164                 :            : 
    1165                 :            :             case RELATIVE:
    1166                 :          0 :               clog << "+" << line[0];
    1167                 :          0 :               break;
    1168                 :            : 
    1169                 :            :             case RANGE:
    1170                 :          0 :               clog << line[0] << " - " << line[1];
    1171                 :          0 :               break;
    1172                 :            : 
    1173                 :            :             case WILDCARD:
    1174                 :          0 :               clog << "*";
    1175                 :          0 :               break;
    1176                 :            :             }
    1177                 :            :         }
    1178                 :            : 
    1179                 :          0 :       clog << endl;
    1180                 :            :     }
    1181                 :            : 
    1182                 :      46826 :   return;
    1183                 :            : 
    1184                 :            : bad:
    1185                 :          0 :   throw semantic_error(_F("malformed specification '%s'", spec.c_str()),
    1186 [ #  # ][ #  # ]:          0 :                        base_probe->tok);
                 [ #  # ]
    1187                 :            : }
    1188                 :            : 
    1189                 :      12257 : string path_remove_sysroot(const systemtap_session& sess, const string& path)
    1190                 :            : {
    1191                 :            :   size_t pos;
    1192                 :      12257 :   string retval = path;
    1193 [ +  - ][ -  + ]:      12257 :   if (!sess.sysroot.empty() &&
         [ #  # ][ #  # ]
                 [ -  + ]
    1194                 :          0 :       (pos = retval.find(sess.sysroot)) != string::npos)
    1195 [ #  # ][ #  # ]:          0 :     retval.replace(pos, sess.sysroot.length(), "/");
    1196                 :      12257 :   return retval;
    1197                 :            : }
    1198                 :            : 
    1199                 :            : void
    1200                 :     377321 : dwarf_query::add_probe_point(const string& dw_funcname,
    1201                 :            :                              const char* filename,
    1202                 :            :                              int line,
    1203                 :            :                              Dwarf_Die* scope_die,
    1204                 :            :                              Dwarf_Addr addr)
    1205                 :            : {
    1206         [ +  - ]:     377321 :   string reloc_section; // base section for relocation purposes
    1207                 :            :   Dwarf_Addr reloc_addr; // relocated
    1208                 :     377321 :   const string& module = dw.module_name; // "kernel" or other
    1209         [ +  - ]:     377321 :   string funcname = dw_funcname;
    1210                 :            : 
    1211         [ -  + ]:     377321 :   assert (! has_absolute); // already handled in dwarf_builder::build()
    1212                 :            : 
    1213         [ +  - ]:     377321 :   if (!has_plt)
    1214         [ +  - ]:     377321 :     reloc_addr = dw.relocate_address(addr, reloc_section);
    1215                 :            :   else
    1216                 :            :     {
    1217                 :            :       // Set the reloc_section but use the plt entry for reloc_addr
    1218         [ #  # ]:          0 :       dw.relocate_address(addr, reloc_section);
    1219                 :          0 :       reloc_addr = addr;
    1220                 :            :     }
    1221                 :            : 
    1222                 :            :   // If we originally used the linkage name, then let's call it that way
    1223                 :            :   const char* linkage_name;
    1224 [ +  - ][ +  - ]:     377321 :   if (scope_die && startswith (this->function, "_Z")
         [ -  + ][ #  # ]
         [ #  # ][ -  + ]
    1225                 :            :       && (linkage_name = dwarf_linkage_name (scope_die)))
    1226         [ #  # ]:          0 :     funcname = linkage_name;
    1227                 :            : 
    1228         [ +  + ]:     377321 :   if (sess.verbose > 1)
    1229                 :            :     {
    1230 [ +  - ][ +  - ]:        296 :       clog << _("probe ") << funcname << "@" << filename << ":" << line;
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
    1231 [ +  - ][ +  - ]:        296 :       if (string(module) == TOK_KERNEL)
         [ +  - ][ +  - ]
    1232         [ +  - ]:        296 :         clog << _(" kernel");
    1233         [ #  # ]:          0 :       else if (has_module)
    1234 [ #  # ][ #  # ]:          0 :         clog << _(" module=") << module;
    1235         [ #  # ]:          0 :       else if (has_process)
    1236 [ #  # ][ #  # ]:          0 :         clog << _(" process=") << module;
    1237 [ +  - ][ +  - ]:        296 :       if (reloc_section != "") clog << " reloc=" << reloc_section;
         [ +  - ][ +  - ]
    1238 [ +  - ][ +  - ]:        296 :       clog << " pc=0x" << hex << addr << dec;
         [ +  - ][ +  - ]
    1239                 :            :     }
    1240                 :            : 
    1241                 :            :   bool bad = dw.blacklisted_p (funcname, filename, line, module,
    1242 [ +  - ][ +  - ]:     377321 :                                addr, has_return);
                 [ +  - ]
    1243         [ +  + ]:     377321 :   if (sess.verbose > 1)
    1244         [ +  - ]:        296 :     clog << endl;
    1245                 :            : 
    1246 [ +  - ][ +  + ]:     377321 :   if (module == TOK_KERNEL)
    1247                 :            :     {
    1248                 :            :       // PR 4224: adapt to relocatable kernel by subtracting the _stext address here.
    1249                 :     293180 :       reloc_addr = addr - sess.sym_stext;
    1250         [ +  - ]:     293180 :       reloc_section = "_stext"; // a message to runtime's _stp_module_relocate
    1251                 :            :     }
    1252                 :            : 
    1253         [ +  + ]:     377321 :   if (! bad)
    1254                 :            :     {
    1255         [ +  - ]:     328888 :       sess.unwindsym_modules.insert (module);
    1256                 :            : 
    1257         [ +  + ]:     328888 :       if (has_process)
    1258                 :            :         {
    1259         [ +  - ]:      11813 :           string module_tgt = path_remove_sysroot(sess, module);
    1260                 :            :           results.push_back (new uprobe_derived_probe(funcname, filename, line,
    1261                 :            :                                                       module_tgt, reloc_section, addr, reloc_addr,
    1262 [ +  - ][ +  - ]:      11813 :                                                       *this, scope_die));
         [ +  + ][ +  - ]
         [ +  - ][ +  - ]
    1263                 :            :         }
    1264                 :            :       else
    1265                 :            :         {
    1266 [ +  + ][ -  + ]:     317075 :           assert (has_kernel || has_module);
    1267                 :            :           results.push_back (new dwarf_derived_probe(funcname, filename, line,
    1268                 :            :                                                      module, reloc_section, addr, reloc_addr,
    1269 [ +  - ][ +  - ]:     317075 :                                                      *this, scope_die));
         [ +  + ][ +  - ]
                 [ +  - ]
    1270                 :            :         }
    1271 [ +  - ][ +  - ]:     377321 :     }
    1272                 :     377313 : }
    1273                 :            : 
    1274                 :            : enum dbinfo_reqt
    1275                 :      46918 : dwarf_query::assess_dbinfo_reqt()
    1276                 :            : {
    1277         [ +  + ]:      46918 :   if (has_absolute)
    1278                 :            :     {
    1279                 :            :       // kernel.statement(NUM).absolute
    1280                 :          5 :       return dbr_none;
    1281                 :            :     }
    1282         [ +  + ]:      46913 :   if (has_inline)
    1283                 :            :     {
    1284                 :            :       // kernel.function("f").inline or module("m").function("f").inline
    1285                 :        226 :       return dbr_need_dwarf;
    1286                 :            :     }
    1287 [ +  + ][ +  + ]:      46687 :   if (has_function_str && spec_type == function_alone)
    1288                 :            :     {
    1289                 :            :       // kernel.function("f") or module("m").function("f")
    1290                 :      46494 :       return dbr_need_symtab;
    1291                 :            :     }
    1292         [ +  + ]:        193 :   if (has_statement_num)
    1293                 :            :     {
    1294                 :            :       // kernel.statement(NUM) or module("m").statement(NUM)
    1295                 :            :       // Technically, all we need is the module offset (or _stext, for
    1296                 :            :       // the kernel).  But for that we need either the ELF file or (for
    1297                 :            :       // _stext) the symbol table.  In either case, the symbol table
    1298                 :            :       // is available, and that allows us to map the NUM (address)
    1299                 :            :       // to a function, which is goodness.
    1300                 :         73 :       return dbr_need_symtab;
    1301                 :            :     }
    1302         [ -  + ]:        120 :   if (has_function_num)
    1303                 :            :     {
    1304                 :            :       // kernel.function(NUM) or module("m").function(NUM)
    1305                 :            :       // Need the symbol table so we can back up from NUM to the
    1306                 :            :       // start of the function.
    1307                 :          0 :       return dbr_need_symtab;
    1308                 :            :     }
    1309                 :            :   // Symbol table tells us nothing about source files or line numbers.
    1310                 :      46918 :   return dbr_need_dwarf;
    1311                 :            : }
    1312                 :            : 
    1313                 :            : 
    1314                 :            : // The critical determining factor when interpreting a pattern
    1315                 :            : // string is, perhaps surprisingly: "presence of a lineno". The
    1316                 :            : // presence of a lineno changes the search strategy completely.
    1317                 :            : //
    1318                 :            : // Compare the two cases:
    1319                 :            : //
    1320                 :            : //   1. {statement,function}(foo@file.c:lineno)
    1321                 :            : //      - find the files matching file.c
    1322                 :            : //      - in each file, find the functions matching foo
    1323                 :            : //      - query the file for line records matching lineno
    1324                 :            : //      - iterate over the line records,
    1325                 :            : //        - and iterate over the functions,
    1326                 :            : //          - if(haspc(function.DIE, line.addr))
    1327                 :            : //            - if looking for statements: probe(lineno.addr)
    1328                 :            : //            - if looking for functions: probe(function.{entrypc,return,etc.})
    1329                 :            : //
    1330                 :            : //   2. {statement,function}(foo@file.c)
    1331                 :            : //      - find the files matching file.c
    1332                 :            : //      - in each file, find the functions matching foo
    1333                 :            : //        - probe(function.{entrypc,return,etc.})
    1334                 :            : //
    1335                 :            : // Thus the first decision we make is based on the presence of a
    1336                 :            : // lineno, and we enter entirely different sets of callbacks
    1337                 :            : // depending on that decision.
    1338                 :            : //
    1339                 :            : // Note that the first case is a generalization fo the second, in that
    1340                 :            : // we could theoretically search through line records for matching
    1341                 :            : // file names (a "table scan" in rdbms lingo).  Luckily, file names
    1342                 :            : // are already cached elsewhere, so we can do an "index scan" as an
    1343                 :            : // optimization.
    1344                 :            : 
    1345                 :            : static void
    1346                 :     377321 : query_statement (string const & func,
    1347                 :            :                  char const * file,
    1348                 :            :                  int line,
    1349                 :            :                  Dwarf_Die *scope_die,
    1350                 :            :                  Dwarf_Addr stmt_addr,
    1351                 :            :                  dwarf_query * q)
    1352                 :            : {
    1353                 :            :   try
    1354                 :            :     {
    1355                 :            :       q->add_probe_point(func, file ? file : "",
    1356 [ +  - ][ +  + ]:     377321 :                          line, scope_die, stmt_addr);
    1357                 :            :     }
    1358         [ -  + ]:         16 :   catch (const semantic_error& e)
    1359                 :            :     {
    1360         [ -  + ]:          8 :       q->sess.print_error (e);
    1361                 :            :     }
    1362                 :     377321 : }
    1363                 :            : 
    1364                 :            : static void
    1365                 :         25 : query_addr(Dwarf_Addr addr, dwarf_query *q)
    1366                 :            : {
    1367                 :         25 :   dwflpp &dw = q->dw;
    1368                 :            : 
    1369         [ -  + ]:         25 :   if (q->sess.verbose > 2)
    1370 [ #  # ][ #  # ]:          0 :     clog << "query_addr 0x" << hex << addr << dec << endl;
         [ #  # ][ #  # ]
                 [ #  # ]
    1371                 :            : 
    1372                 :            :   // First pick which CU contains this address
    1373         [ +  - ]:         25 :   Dwarf_Die* cudie = dw.query_cu_containing_address(addr);
    1374         [ +  - ]:         25 :   if (!cudie) // address could be wildly out of range
    1375                 :            :     return;
    1376         [ +  - ]:         25 :   dw.focus_on_cu(cudie);
    1377                 :            : 
    1378                 :            :   // Now compensate for the dw bias
    1379                 :         25 :   addr -= dw.module_bias;
    1380                 :            : 
    1381                 :            :   // Per PR5787, we look up the scope die even for
    1382                 :            :   // statement_num's, for blacklist sensitivity and $var
    1383                 :            :   // resolution purposes.
    1384                 :            : 
    1385                 :            :   // Find the scopes containing this address
    1386         [ +  - ]:         25 :   vector<Dwarf_Die> scopes = dw.getscopes(addr);
    1387 [ +  - ][ -  + ]:         25 :   if (scopes.empty())
    1388                 :            :     return;
    1389                 :            : 
    1390                 :            :   // Look for the innermost containing function
    1391                 :         25 :   Dwarf_Die *fnscope = NULL;
    1392         [ +  - ]:         49 :   for (size_t i = 0; i < scopes.size(); ++i)
    1393                 :            :     {
    1394         [ +  - ]:         49 :       int tag = dwarf_tag(&scopes[i]);
    1395 [ +  + ][ -  + ]:         49 :       if ((tag == DW_TAG_subprogram && !q->has_inline) ||
         [ -  + ][ #  # ]
         [ #  # ][ #  # ]
    1396                 :            :           (tag == DW_TAG_inlined_subroutine &&
    1397                 :          0 :            !q->has_call && !q->has_return && !q->has_exported))
    1398                 :            :         {
    1399                 :         25 :           fnscope = &scopes[i];
    1400                 :         25 :           break;
    1401                 :            :         }
    1402                 :            :     }
    1403         [ -  + ]:         25 :   if (!fnscope)
    1404                 :            :     return;
    1405         [ +  - ]:         25 :   dw.focus_on_function(fnscope);
    1406                 :            : 
    1407         [ -  + ]:         25 :   Dwarf_Die *scope = q->has_function_num ? fnscope : &scopes[0];
    1408                 :            : 
    1409         [ +  - ]:         25 :   const char *file = dwarf_decl_file(fnscope);
    1410                 :            :   int line;
    1411         [ +  - ]:         25 :   dwarf_decl_line(fnscope, &line);
    1412                 :            : 
    1413                 :            :   // Function probes should reset the addr to the function entry
    1414                 :            :   // and possibly perform prologue searching
    1415         [ -  + ]:         25 :   if (q->has_function_num)
    1416                 :            :     {
    1417         [ #  # ]:          0 :       dw.die_entrypc(fnscope, &addr);
    1418 [ #  # ][ #  # ]:          0 :       if (dwarf_tag(fnscope) == DW_TAG_subprogram &&
         [ #  # ][ #  # ]
                 [ #  # ]
    1419                 :            :           (q->sess.prologue_searching || q->has_process)) // PR 6871
    1420                 :            :         {
    1421         [ #  # ]:          0 :           func_info func;
    1422                 :          0 :           func.die = *fnscope;
    1423         [ #  # ]:          0 :           func.name = dw.function_name;
    1424                 :          0 :           func.decl_file = file;
    1425                 :          0 :           func.decl_line = line;
    1426                 :          0 :           func.entrypc = addr;
    1427                 :            : 
    1428         [ #  # ]:          0 :           func_info_map_t funcs(1, func);
    1429         [ #  # ]:          0 :           dw.resolve_prologue_endings (funcs);
    1430         [ #  # ]:          0 :           if (q->has_return) // PR13200
    1431                 :            :             {
    1432         [ #  # ]:          0 :               if (q->sess.verbose > 2)
    1433 [ #  # ][ #  # ]:          0 :                 clog << "ignoring prologue for .return probes" << endl;
    1434                 :            :             }
    1435                 :            :           else
    1436                 :            :             {
    1437         [ #  # ]:          0 :               if (funcs[0].prologue_end)
    1438                 :          0 :                 addr = funcs[0].prologue_end;
    1439 [ #  # ][ #  # ]:          0 :             }
    1440                 :            :         }
    1441                 :            :     }
    1442                 :            :   else
    1443                 :            :     {
    1444         [ +  - ]:         25 :       dwarf_line_t address_line(dwarf_getsrc_die(cudie, addr));
    1445         [ +  - ]:         25 :       if (address_line)
    1446                 :            :         {
    1447         [ +  - ]:         25 :           file = address_line.linesrc();
    1448         [ +  - ]:         25 :           line = address_line.lineno();
    1449                 :            :         }
    1450                 :            : 
    1451                 :            :       // Verify that a raw address matches the beginning of a
    1452                 :            :       // statement. This is a somewhat lame check that the address
    1453                 :            :       // is at the start of an assembly instruction.  Mark probes are in the
    1454                 :            :       // middle of a macro and thus not strictly at a statement beginning.
    1455                 :            :       // Guru mode may override this check.
    1456 [ +  + ][ +  - ]:         25 :       if (!q->has_mark && (!address_line || address_line.addr() != addr))
         [ +  - ][ -  + ]
                 [ -  + ]
    1457                 :            :         {
    1458         [ #  # ]:          0 :           stringstream msg;
    1459 [ #  # ][ #  # ]:          0 :           msg << _F("address %#" PRIx64 " does not match the beginning of a statement",
    1460         [ #  # ]:          0 :                     addr);
    1461         [ #  # ]:          0 :           if (address_line)
    1462 [ #  # ][ #  # ]:          0 :             msg << _F(" (try %#" PRIx64 ")", address_line.addr());
         [ #  # ][ #  # ]
    1463                 :            :           else
    1464 [ #  # ][ #  # ]:          0 :             msg << _F(" (no line info found for '%s', in module '%s')",
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
    1465         [ #  # ]:          0 :                       dw.cu_name().c_str(), dw.module_name.c_str());
    1466         [ #  # ]:          0 :           if (! q->sess.guru_mode)
    1467 [ #  # ][ #  # ]:          0 :             throw semantic_error(msg.str());
    1468                 :            :           else
    1469 [ #  # ][ #  # ]:         25 :            q->sess.print_warning(msg.str());
         [ #  # ][ #  # ]
    1470                 :            :         }
    1471                 :            :     }
    1472                 :            : 
    1473                 :            :   // Build a probe at this point
    1474 [ +  - ][ +  - ]:         25 :   query_statement(dw.function_name, file, line, scope, addr, q);
                 [ +  - ]
    1475                 :            : }
    1476                 :            : 
    1477                 :            : static void
    1478                 :          6 : query_label (string const & func,
    1479                 :            :              char const * label,
    1480                 :            :              char const * file,
    1481                 :            :              int line,
    1482                 :            :              Dwarf_Die *scope_die,
    1483                 :            :              Dwarf_Addr stmt_addr,
    1484                 :            :              dwarf_query * q)
    1485                 :            : {
    1486 [ +  - ][ -  + ]:          6 :   assert (q->has_statement_str || q->has_function_str);
    1487                 :            : 
    1488                 :          6 :   size_t i = q->results.size();
    1489                 :            : 
    1490                 :            :   // weed out functions whose decl_file isn't one of
    1491                 :            :   // the source files that we actually care about
    1492 [ -  + ][ #  # ]:         12 :   if (q->spec_type != function_alone &&
                 [ +  - ]
    1493 [ #  # ][ #  # ]:          6 :       q->filtered_srcfiles.count(file) == 0)
         [ -  + ][ #  # ]
                 [ -  + ]
           [ #  #  #  # ]
    1494                 :          6 :     return;
    1495                 :            : 
    1496         [ +  - ]:          6 :   query_statement(func, file, line, scope_die, stmt_addr, q);
    1497                 :            : 
    1498                 :            :   // after the fact, insert the label back into the derivation chain
    1499                 :            :   probe_point::component* ppc =
    1500 [ +  - ][ +  - ]:          6 :     new probe_point::component(TOK_LABEL, new literal_string (label));
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
    1501         [ +  + ]:         12 :   for (; i < q->results.size(); ++i)
    1502                 :            :     {
    1503                 :          6 :       derived_probe* p = q->results[i];
    1504 [ +  - ][ +  - ]:          6 :       probe_point* pp = new probe_point(*p->locations[0]);
    1505         [ +  - ]:          6 :       pp->components.push_back (ppc);
    1506         [ +  - ]:          6 :       p->base = p->base->create_alias(p->locations[0], pp);
    1507                 :            :     }
    1508                 :            : }
    1509                 :            : 
    1510                 :            : static void
    1511                 :     213465 : query_inline_instance_info (inline_instance_info & ii,
    1512                 :            :                             dwarf_query * q)
    1513                 :            : {
    1514                 :            :   try
    1515                 :            :     {
    1516         [ -  + ]:     213465 :       assert (! q->has_return); // checked by caller already
    1517         [ -  + ]:     213465 :       if (q->sess.verbose>2)
    1518 [ #  # ][ #  # ]:          0 :         clog << _F("querying entrypc %#" PRIx64 " of instance of inline '%s'\n",
                 [ #  # ]
    1519         [ #  # ]:          0 :                    ii.entrypc, ii.name.c_str());
    1520                 :            :       query_statement (ii.name, ii.decl_file, ii.decl_line,
    1521         [ +  - ]:     213465 :                        &ii.die, ii.entrypc, q);
    1522                 :            :     }
    1523         [ #  # ]:            :   catch (semantic_error &e)
    1524                 :            :     {
    1525         [ #  # ]:            :       q->sess.print_error (e);
    1526                 :            :     }
    1527                 :     213465 : }
    1528                 :            : 
    1529                 :            : static void
    1530                 :     163785 : query_func_info (Dwarf_Addr entrypc,
    1531                 :            :                  func_info & fi,
    1532                 :            :                  dwarf_query * q)
    1533                 :            : {
    1534                 :            :   try
    1535                 :            :     {
    1536         [ +  + ]:     163785 :       if (q->has_return)
    1537                 :            :         {
    1538                 :            :           // NB. dwarf_derived_probe::emit_registrations will emit a
    1539                 :            :           // kretprobe based on the entrypc in this case.
    1540 [ +  + ][ +  - ]:      48067 :           if (fi.prologue_end != 0 && q->has_return) // PR13200
    1541                 :            :             {
    1542         [ -  + ]:          1 :               if (q->sess.verbose > 2)
    1543 [ #  # ][ #  # ]:          0 :                 clog << "ignoring prologue for .return probes" << endl;
    1544                 :            :             }
    1545                 :            :           query_statement (fi.name, fi.decl_file, fi.decl_line,
    1546         [ +  - ]:      48067 :                            &fi.die, entrypc, q);
    1547                 :            :         }
    1548                 :            :       else
    1549                 :            :         {
    1550         [ +  + ]:     115718 :           if (fi.prologue_end != 0)
    1551                 :            :             {
    1552                 :            :               query_statement (fi.name, fi.decl_file, fi.decl_line,
    1553         [ +  - ]:      11604 :                                &fi.die, fi.prologue_end, q);
    1554                 :            :             }
    1555                 :            :           else
    1556                 :            :             {
    1557                 :            :               query_statement (fi.name, fi.decl_file, fi.decl_line,
    1558         [ +  - ]:     104114 :                                &fi.die, entrypc, q);
    1559                 :            :             }
    1560                 :            :         }
    1561                 :            :     }
    1562         [ #  # ]:            :   catch (semantic_error &e)
    1563                 :            :     {
    1564         [ #  # ]:            :       q->sess.print_error (e);
    1565                 :            :     }
    1566                 :     163785 : }
    1567                 :            : 
    1568                 :            : 
    1569                 :            : static void
    1570                 :          0 : query_srcfile_label (const dwarf_line_t& line, void * arg)
    1571                 :            : {
    1572                 :          0 :   dwarf_query * q = static_cast<dwarf_query *>(arg);
    1573                 :            : 
    1574                 :          0 :   Dwarf_Addr addr = line.addr();
    1575                 :            : 
    1576 [ #  # ][ #  # ]:          0 :   for (func_info_map_t::iterator i = q->filtered_functions.begin();
                 [ #  # ]
    1577         [ #  # ]:          0 :        i != q->filtered_functions.end(); ++i)
    1578 [ #  # ][ #  # ]:          0 :     if (q->dw.die_has_pc (i->die, addr))
    1579                 :          0 :       q->dw.iterate_over_labels (&i->die, q->label_val, i->name,
    1580         [ #  # ]:          0 :                                  q, query_label);
    1581                 :            : 
    1582 [ #  # ][ #  # ]:          0 :   for (inline_instance_map_t::iterator i = q->filtered_inlines.begin();
                 [ #  # ]
    1583         [ #  # ]:          0 :        i != q->filtered_inlines.end(); ++i)
    1584 [ #  # ][ #  # ]:          0 :     if (q->dw.die_has_pc (i->die, addr))
    1585                 :          0 :       q->dw.iterate_over_labels (&i->die, q->label_val, i->name,
    1586         [ #  # ]:          0 :                                  q, query_label);
    1587                 :          0 : }
    1588                 :            : 
    1589                 :            : static void
    1590                 :        762 : query_srcfile_line (const dwarf_line_t& line, void * arg)
    1591                 :            : {
    1592                 :        762 :   dwarf_query * q = static_cast<dwarf_query *>(arg);
    1593                 :            : 
    1594                 :        762 :   Dwarf_Addr addr = line.addr();
    1595                 :            : 
    1596                 :        762 :   int lineno = line.lineno();
    1597                 :            : 
    1598 [ +  - ][ +  - ]:       3046 :   for (func_info_map_t::iterator i = q->filtered_functions.begin();
                 [ +  + ]
    1599         [ +  - ]:       1523 :        i != q->filtered_functions.end(); ++i)
    1600                 :            :     {
    1601 [ +  - ][ +  + ]:        761 :       if (q->dw.die_has_pc (i->die, addr))
    1602                 :            :         {
    1603         [ -  + ]:         39 :           if (q->sess.verbose>3)
    1604         [ #  # ]:          0 :             clog << _("function DIE lands on srcfile\n");
    1605         [ +  - ]:         39 :           if (q->has_statement_str)
    1606                 :            :             {
    1607                 :            :               Dwarf_Die scope;
    1608         [ +  - ]:         39 :               q->dw.inner_die_containing_pc(i->die, addr, scope);
    1609                 :         39 :               query_statement (i->name, i->decl_file,
    1610                 :            :                                lineno, // NB: not q->line !
    1611         [ +  - ]:         39 :                                &scope, addr, q);
    1612                 :            :             }
    1613                 :            :           else
    1614         [ #  # ]:          0 :             query_func_info (i->entrypc, *i, q);
    1615                 :            :         }
    1616                 :            :     }
    1617                 :            : 
    1618 [ +  - ][ +  + ]:       1526 :   for (inline_instance_map_t::iterator i
    1619         [ +  - ]:        762 :          = q->filtered_inlines.begin();
    1620         [ +  - ]:        763 :        i != q->filtered_inlines.end(); ++i)
    1621                 :            :     {
    1622 [ +  - ][ +  - ]:          1 :       if (q->dw.die_has_pc (i->die, addr))
    1623                 :            :         {
    1624         [ -  + ]:          1 :           if (q->sess.verbose>3)
    1625         [ #  # ]:          0 :             clog << _("inline instance DIE lands on srcfile\n");
    1626         [ +  - ]:          1 :           if (q->has_statement_str)
    1627                 :            :             {
    1628                 :            :               Dwarf_Die scope;
    1629         [ +  - ]:          1 :               q->dw.inner_die_containing_pc(i->die, addr, scope);
    1630                 :          1 :               query_statement (i->name, i->decl_file,
    1631         [ +  - ]:          1 :                                q->line[0], &scope, addr, q);
    1632                 :            :             }
    1633                 :            :           else
    1634         [ #  # ]:          0 :             query_inline_instance_info (*i, q);
    1635                 :            :         }
    1636                 :            :     }
    1637                 :        762 : }
    1638                 :            : 
    1639                 :            : 
    1640                 :            : bool
    1641                 :    4600251 : inline_instance_info::operator<(const inline_instance_info& other) const
    1642                 :            : {
    1643         [ +  + ]:    4600251 :   if (entrypc != other.entrypc)
    1644                 :    4503032 :     return entrypc < other.entrypc;
    1645                 :            : 
    1646         [ +  + ]:      97219 :   if (decl_line != other.decl_line)
    1647                 :      97069 :     return decl_line < other.decl_line;
    1648                 :            : 
    1649                 :        150 :   int cmp = name.compare(other.name);
    1650         [ +  + ]:        150 :   if (!cmp)
    1651                 :         44 :     cmp = strcmp(decl_file, other.decl_file);
    1652                 :    4600251 :   return cmp < 0;
    1653                 :            : }
    1654                 :            : 
    1655                 :            : 
    1656                 :            : static int
    1657                 :     213596 : query_dwarf_inline_instance (Dwarf_Die * die, void * arg)
    1658                 :            : {
    1659                 :     213596 :   dwarf_query * q = static_cast<dwarf_query *>(arg);
    1660 [ +  + ][ -  + ]:     213596 :   assert (q->has_statement_str || q->has_function_str);
    1661 [ +  - ][ +  - ]:     213596 :   assert (!q->has_call && !q->has_return && !q->has_exported);
                 [ -  + ]
    1662                 :            : 
    1663                 :            :   try
    1664                 :            :     {
    1665         [ -  + ]:     213596 :       if (q->sess.verbose>2)
    1666 [ #  # ][ #  # ]:          0 :         clog << _F("selected inline instance of %s\n", q->dw.function_name.c_str());
         [ #  # ][ #  # ]
    1667                 :            : 
    1668                 :            :       Dwarf_Addr entrypc;
    1669 [ +  - ][ +  - ]:     213596 :       if (q->dw.die_entrypc (die, &entrypc))
    1670                 :            :         {
    1671         [ +  - ]:     213596 :           inline_instance_info inl;
    1672                 :     213596 :           inl.die = *die;
    1673         [ +  - ]:     213596 :           inl.name = q->dw.function_name;
    1674                 :     213596 :           inl.entrypc = entrypc;
    1675         [ +  - ]:     213596 :           q->dw.function_file (&inl.decl_file);
    1676         [ +  - ]:     213596 :           q->dw.function_line (&inl.decl_line);
    1677                 :            : 
    1678                 :            :           // make sure that this inline hasn't already
    1679                 :            :           // been matched from a different CU
    1680 [ +  - ][ +  + ]:     213596 :           if (q->inline_dupes.insert(inl).second)
    1681 [ +  - ][ +  - ]:     213596 :             q->filtered_inlines.push_back(inl);
    1682                 :            :         }
    1683                 :     213596 :       return DWARF_CB_OK;
    1684                 :            :     }
    1685         [ #  # ]:            :   catch (const semantic_error& e)
    1686                 :            :     {
    1687         [ #  # ]:            :       q->sess.print_error (e);
    1688                 :            :       return DWARF_CB_ABORT;
    1689                 :            :     }
    1690                 :            : }
    1691                 :            : 
    1692                 :            : static int
    1693                 :     712413 : query_dwarf_func (Dwarf_Die * func, base_query * bq)
    1694                 :            : {
    1695                 :     712413 :   dwarf_query * q = static_cast<dwarf_query *>(bq);
    1696 [ +  + ][ -  + ]:     712413 :   assert (q->has_statement_str || q->has_function_str);
    1697                 :            : 
    1698                 :            :   // weed out functions whose decl_file isn't one of
    1699                 :            :   // the source files that we actually care about
    1700 [ +  + ][ +  + ]:    1449143 :   if (q->spec_type != function_alone &&
                 [ +  + ]
    1701 [ +  - ][ +  + ]:     736730 :       q->filtered_srcfiles.count(dwarf_decl_file(func)?:"") == 0)
         [ +  - ][ +  - ]
         [ +  + ][ +  - ]
                 [ +  + ]
           [ #  #  #  # ]
    1702                 :      16330 :     return DWARF_CB_OK;
    1703                 :            : 
    1704                 :            :   try
    1705                 :            :     {
    1706         [ +  - ]:     696083 :       q->dw.focus_on_function (func);
    1707                 :            : 
    1708 [ +  - ][ -  + ]:     696083 :       if (!q->dw.function_scope_matches(q->scopes))
    1709                 :          0 :         return DWARF_CB_OK;
    1710                 :            : 
    1711                 :            :       // make sure that this function address hasn't
    1712                 :            :       // already been matched under an aliased name
    1713                 :            :       Dwarf_Addr addr;
    1714 [ +  - ][ +  + ]:    2067863 :       if (!q->dw.func_is_inline() &&
         [ +  + ][ +  + ]
                 [ +  + ]
    1715         [ +  - ]:     440806 :           dwarf_entrypc(func, &addr) == 0 &&
    1716 [ +  - ][ +  + ]:     930974 :           !q->alias_dupes.insert(addr).second)
                 [ #  # ]
    1717                 :       9705 :         return DWARF_CB_OK;
    1718                 :            : 
    1719 [ +  - ][ +  + ]:     686378 :       if (q->dw.func_is_inline () && (! q->has_call) && (! q->has_return) && (! q->has_exported))
         [ +  + ][ +  + ]
         [ +  + ][ +  + ]
    1720                 :            :         {
    1721         [ -  + ]:     111376 :           if (q->sess.verbose>3)
    1722 [ #  # ][ #  # ]:          0 :             clog << _F("checking instances of inline %s\n", q->dw.function_name.c_str());
         [ #  # ][ #  # ]
    1723         [ +  - ]:     111376 :           q->dw.iterate_over_inline_instances (query_dwarf_inline_instance, q);
    1724                 :            :         }
    1725 [ +  - ][ +  + ]:     575002 :       else if (q->dw.func_is_inline () && (q->has_return)) // PR 11553
         [ +  + ][ +  + ]
    1726                 :            :         {
    1727         [ +  - ]:      53731 :           q->inlined_non_returnable.insert (q->dw.function_name);
    1728                 :            :         }
    1729 [ +  - ][ +  + ]:     521271 :       else if (!q->dw.func_is_inline () && (! q->has_inline))
         [ +  + ][ +  + ]
    1730                 :            :         {
    1731 [ +  + ][ +  - ]:     357767 :           if (q->has_exported && !q->dw.func_is_exported ())
         [ +  + ][ +  + ]
    1732                 :          6 :             return DWARF_CB_OK;
    1733         [ -  + ]:     357761 :           if (q->sess.verbose>2)
    1734 [ #  # ][ #  # ]:          0 :             clog << _F("selected function %s\n", q->dw.function_name.c_str());
         [ #  # ][ #  # ]
    1735                 :            : 
    1736         [ +  - ]:     357761 :           func_info func;
    1737         [ +  - ]:     357761 :           q->dw.function_die (&func.die);
    1738         [ +  - ]:     357761 :           func.name = q->dw.function_name;
    1739         [ +  - ]:     357761 :           q->dw.function_file (&func.decl_file);
    1740         [ +  - ]:     357761 :           q->dw.function_line (&func.decl_line);
    1741                 :            : 
    1742                 :            :           Dwarf_Addr entrypc;
    1743 [ +  - ][ +  + ]:     357761 :           if (q->dw.function_entrypc (&entrypc))
    1744                 :            :             {
    1745                 :     193477 :               func.entrypc = entrypc;
    1746         [ +  - ]:     193477 :               q->filtered_functions.push_back (func);
    1747         [ +  - ]:     357761 :             }
    1748                 :            :           /* else this function is fully inlined, just ignore it */
    1749                 :            :         }
    1750                 :     712413 :       return DWARF_CB_OK;
    1751                 :            :     }
    1752         [ #  # ]:            :   catch (const semantic_error& e)
    1753                 :            :     {
    1754         [ #  # ]:            :       q->sess.print_error (e);
    1755                 :            :       return DWARF_CB_ABORT;
    1756                 :            :     }
    1757                 :            : }
    1758                 :            : 
    1759                 :            : static int
    1760                 :     191698 : query_cu (Dwarf_Die * cudie, void * arg)
    1761                 :            : {
    1762                 :     191698 :   dwarf_query * q = static_cast<dwarf_query *>(arg);
    1763 [ +  + ][ -  + ]:     191698 :   assert (q->has_statement_str || q->has_function_str);
    1764                 :            : 
    1765         [ -  + ]:     191698 :   if (pending_interrupts) return DWARF_CB_ABORT;
    1766                 :            : 
    1767                 :            :   try
    1768                 :            :     {
    1769         [ +  - ]:     191698 :       q->dw.focus_on_cu (cudie);
    1770                 :            : 
    1771                 :            :       if (false && q->sess.verbose>2)
    1772                 :            :         clog << _F("focused on CU '%s', in module '%s'\n",
    1773                 :            :                    q->dw.cu_name().c_str(), q->dw.module_name.c_str());
    1774                 :            : 
    1775         [ +  - ]:     191698 :       q->filtered_srcfiles.clear();
    1776         [ +  - ]:     191698 :       q->filtered_functions.clear();
    1777         [ +  - ]:     191698 :       q->filtered_inlines.clear();
    1778                 :            : 
    1779                 :            :       // In this path, we find "abstract functions", record
    1780                 :            :       // information about them, and then (depending on lineno
    1781                 :            :       // matching) possibly emit one or more of the function's
    1782                 :            :       // associated addresses. Unfortunately the control of this
    1783                 :            :       // cannot easily be turned inside out.
    1784                 :            : 
    1785         [ +  + ]:     191698 :       if (q->spec_type != function_alone)
    1786                 :            :         {
    1787                 :            :           // If we have a pattern string with a filename, we need
    1788                 :            :           // to elaborate the srcfile mask in question first.
    1789         [ +  - ]:     121885 :           q->dw.collect_srcfiles_matching (q->file, q->filtered_srcfiles);
    1790                 :            : 
    1791                 :            :           // If we have a file pattern and *no* srcfile matches, there's
    1792                 :            :           // no need to look further into this CU, so skip.
    1793 [ +  - ][ +  + ]:     121885 :           if (q->filtered_srcfiles.empty())
    1794                 :     116874 :             return DWARF_CB_OK;
    1795                 :            :         }
    1796                 :            : 
    1797                 :            :       // Pick up [entrypc, name, DIE] tuples for all the functions
    1798                 :            :       // matching the query, and fill in the prologue endings of them
    1799                 :            :       // all in a single pass.
    1800         [ +  - ]:      74824 :       int rc = q->dw.iterate_over_functions (query_dwarf_func, q, q->function);
    1801         [ -  + ]:      74824 :       if (rc != DWARF_CB_OK)
    1802                 :          0 :         q->query_done = true;
    1803                 :            : 
    1804 [ +  + ][ +  + ]:      74824 :       if ((q->sess.prologue_searching || q->has_process) // PR 6871
                 [ +  + ]
    1805                 :         65 :           && !q->has_statement_str) // PR 2608
    1806 [ +  - ][ +  + ]:         60 :         if (! q->filtered_functions.empty())
    1807         [ +  - ]:         59 :           q->dw.resolve_prologue_endings (q->filtered_functions);
    1808                 :            :       // NB: we could skip the resolve_prologue_endings() call here for has_return case (PR13200),
    1809                 :            :       // but don't have to.  We can resolve the prologue, just not actually use it in query_addr().
    1810                 :            : 
    1811         [ +  + ]:      74824 :       if (q->spec_type == function_file_and_line)
    1812                 :            :         {
    1813                 :            :           // .statement(...:NN) often gets mixed up with .function(...:NN)
    1814         [ -  + ]:       2847 :           if (q->has_function_str)
    1815                 :          0 :             q->sess.print_warning (_("For probing a particular line, use a "
    1816                 :            :                                    ".statement() probe, not .function()"), 
    1817 [ #  # ][ #  # ]:          1 :                                    q->base_probe->tok);
                 [ #  # ]
    1818                 :            : 
    1819                 :            :           // If we have a pattern string with target *line*, we
    1820                 :            :           // have to look at lines in all the matched srcfiles.
    1821                 :            :           void (* callback) (const dwarf_line_t&, void*) =
    1822         [ -  + ]:       2847 :             q->has_label ? query_srcfile_label : query_srcfile_line;
    1823 [ +  - ][ +  + ]:     559756 :           for (set<string>::const_iterator i = q->filtered_srcfiles.begin();
    1824         [ +  - ]:     279878 :                i != q->filtered_srcfiles.end(); ++i)
    1825                 :            :             q->dw.iterate_over_srcfile_lines (i->c_str(), q->line, q->has_statement_str,
    1826 [ +  - ][ +  - ]:     277032 :                                               q->line_type, callback, q->function, q);
                 [ +  + ]
    1827                 :            :         }
    1828         [ +  + ]:      71977 :       else if (q->has_label)
    1829                 :            :         {
    1830 [ +  - ][ +  - ]:         16 :           for (func_info_map_t::iterator i = q->filtered_functions.begin();
                 [ +  + ]
    1831         [ +  - ]:          8 :                i != q->filtered_functions.end(); ++i)
    1832                 :          5 :             q->dw.iterate_over_labels (&i->die, q->label_val, i->name,
    1833         [ +  - ]:          5 :                                        q, query_label);
    1834                 :            : 
    1835 [ +  - ][ +  - ]:          8 :           for (inline_instance_map_t::iterator i = q->filtered_inlines.begin();
                 [ +  + ]
    1836         [ +  - ]:          4 :                i != q->filtered_inlines.end(); ++i)
    1837                 :          1 :             q->dw.iterate_over_labels (&i->die, q->label_val, i->name,
    1838         [ +  - ]:          1 :                                        q, query_label);
    1839                 :            :         }
    1840                 :            :       else
    1841                 :            :         {
    1842                 :            :           // Otherwise, simply probe all resolved functions.
    1843 [ +  - ][ +  - ]:     471518 :           for (func_info_map_t::iterator i = q->filtered_functions.begin();
                 [ +  + ]
    1844         [ +  - ]:     235759 :                i != q->filtered_functions.end(); ++i)
    1845         [ +  - ]:     163785 :             query_func_info (i->entrypc, *i, q);
    1846                 :            : 
    1847                 :            :           // And all inline instances (if we're not excluding inlines with ".call")
    1848         [ +  + ]:      71974 :           if (! q->has_call)
    1849 [ +  - ][ +  + ]:     490156 :             for (inline_instance_map_t::iterator i
    1850 [ +  - ][ +  - ]:     276691 :                    = q->filtered_inlines.begin(); i != q->filtered_inlines.end(); ++i)
    1851         [ +  - ]:     213465 :               query_inline_instance_info (*i, q);
    1852                 :            :         }
    1853                 :     191698 :       return DWARF_CB_OK;
    1854                 :            :     }
    1855         [ -  + ]:          2 :   catch (const semantic_error& e)
    1856                 :            :     {
    1857         [ -  + ]:          1 :       q->sess.print_error (e);
    1858                 :          1 :       return DWARF_CB_ABORT;
    1859                 :            :     }
    1860                 :            : }
    1861                 :            : 
    1862                 :            : 
    1863                 :            : void
    1864                 :      45652 : dwarf_query::query_module_functions ()
    1865                 :            : {
    1866                 :            :   try
    1867                 :            :     {
    1868         [ +  - ]:      45652 :       filtered_srcfiles.clear();
    1869         [ +  - ]:      45652 :       filtered_functions.clear();
    1870         [ +  - ]:      45652 :       filtered_inlines.clear();
    1871                 :            : 
    1872                 :            :       // Collect all module functions so we know which CUs are interesting
    1873         [ +  - ]:      45652 :       int rc = dw.iterate_single_function(query_dwarf_func, this, function);
    1874         [ -  + ]:      45652 :       if (rc != DWARF_CB_OK)
    1875                 :            :         {
    1876                 :          0 :           query_done = true;
    1877                 :      45652 :           return;
    1878                 :            :         }
    1879                 :            : 
    1880         [ +  - ]:      45652 :       set<void*> used_cus; // by cu->addr
    1881         [ +  - ]:      45652 :       vector<Dwarf_Die> cus;
    1882                 :            :       Dwarf_Die cu_mem;
    1883                 :            : 
    1884 [ +  - ][ +  - ]:     150634 :       for (func_info_map_t::iterator i = filtered_functions.begin();
                 [ +  + ]
    1885         [ +  - ]:      75317 :            i != filtered_functions.end(); ++i)
    1886 [ +  - ][ +  - ]:      29665 :         if (dwarf_diecu(&i->die, &cu_mem, NULL, NULL) &&
         [ +  - ][ +  - ]
                 [ +  - ]
           [ +  -  #  # ]
    1887                 :            :             used_cus.insert(cu_mem.addr).second)
    1888         [ +  - ]:      29665 :           cus.push_back(cu_mem);
    1889                 :            : 
    1890 [ +  - ][ +  - ]:      91518 :       for (inline_instance_map_t::iterator i = filtered_inlines.begin();
                 [ +  + ]
    1891         [ +  - ]:      45759 :            i != filtered_inlines.end(); ++i)
    1892 [ +  - ][ +  - ]:        107 :         if (dwarf_diecu(&i->die, &cu_mem, NULL, NULL) &&
         [ +  - ][ +  + ]
                 [ +  - ]
           [ +  +  #  # ]
    1893                 :            :             used_cus.insert(cu_mem.addr).second)
    1894         [ +  - ]:         19 :           cus.push_back(cu_mem);
    1895                 :            : 
    1896                 :            :       // Reset the dupes since we didn't actually collect them the first time
    1897         [ +  - ]:      45652 :       alias_dupes.clear();
    1898         [ +  - ]:      45652 :       inline_dupes.clear();
    1899                 :            : 
    1900                 :            :       // Run the query again on the individual CUs
    1901 [ +  - ][ +  - ]:      75336 :       for (vector<Dwarf_Die>::iterator i = cus.begin(); i != cus.end(); ++i)
         [ +  - ][ +  + ]
    1902 [ +  - ][ +  - ]:      75336 :         query_cu(&*i, this);
                 [ +  - ]
    1903                 :            :     }
    1904         [ #  # ]:            :   catch (const semantic_error& e)
    1905                 :            :     {
    1906         [ #  # ]:            :       sess.print_error (e);
    1907                 :            :     }
    1908                 :            : }
    1909                 :            : 
    1910                 :            : 
    1911                 :            : static void
    1912                 :      79148 : validate_module_elf (Dwfl_Module *mod, const char *name,  base_query *q)
    1913                 :            : {
    1914                 :            :   // Validate the machine code in this elf file against the
    1915                 :            :   // session machine.  This is important, in case the wrong kind
    1916                 :            :   // of debuginfo is being automagically processed by elfutils.
    1917                 :            :   // While we can tell i686 apart from x86-64, unfortunately
    1918                 :            :   // we can't help confusing i586 vs i686 (both EM_386).
    1919                 :            : 
    1920                 :            :   Dwarf_Addr bias;
    1921                 :            :   // We prefer dwfl_module_getdwarf to dwfl_module_getelf here,
    1922                 :            :   // because dwfl_module_getelf can force costly section relocations
    1923                 :            :   // we don't really need, while either will do for this purpose.
    1924 [ +  - ][ +  - ]:      79148 :   Elf* elf = (dwarf_getelf (dwfl_module_getdwarf (mod, &bias))
    1925 [ +  + ][ +  - ]:      79148 :                   ?: dwfl_module_getelf (mod, &bias));
    1926                 :            : 
    1927                 :            :   GElf_Ehdr ehdr_mem;
    1928         [ +  - ]:      79148 :   GElf_Ehdr* em = gelf_getehdr (elf, &ehdr_mem);
    1929 [ -  + ][ #  # ]:      79148 :   if (em == 0) { dwfl_assert ("dwfl_getehdr", dwfl_errno()); }
         [ #  # ][ #  # ]
                 [ #  # ]
    1930         [ -  + ]:      79148 :   assert(em);
    1931                 :      79148 :   int elf_machine = em->e_machine;
    1932                 :      79148 :   const char* debug_filename = "";
    1933                 :      79148 :   const char* main_filename = "";
    1934                 :            :   (void) dwfl_module_info (mod, NULL, NULL,
    1935                 :            :                                NULL, NULL, NULL,
    1936                 :            :                                & main_filename,
    1937         [ +  - ]:      79148 :                                & debug_filename);
    1938                 :      79148 :   const string& sess_machine = q->sess.architecture;
    1939                 :            : 
    1940         [ +  - ]:      79148 :   string expect_machine; // to match sess.machine (i.e., kernel machine)
    1941         [ +  - ]:      79148 :   string expect_machine2;
    1942                 :            : 
    1943                 :            :   // NB: See also the 'uname -m' squashing done in main.cxx.
    1944   [ -  -  -  -  :      79148 :   switch (elf_machine)
                -  +  - ]
    1945                 :            :     {
    1946                 :            :       // x86 and ppc are bi-architecture; a 64-bit kernel
    1947                 :            :       // can normally run either 32-bit or 64-bit *userspace*.
    1948                 :            :     case EM_386:
    1949         [ #  # ]:          0 :       expect_machine = "i?86";
    1950         [ #  # ]:          0 :       if (! q->has_process) break; // 32-bit kernel/module
    1951                 :            :       /* FALLSTHROUGH */
    1952                 :            :     case EM_X86_64:
    1953         [ #  # ]:          0 :       expect_machine2 = "x86_64";
    1954                 :          0 :       break;
    1955                 :            :     case EM_PPC:
    1956                 :            :     case EM_PPC64:
    1957         [ #  # ]:          0 :       expect_machine = "powerpc";
    1958                 :          0 :       break;
    1959         [ #  # ]:          0 :     case EM_S390: expect_machine = "s390"; break;
    1960         [ #  # ]:          0 :     case EM_IA_64: expect_machine = "ia64"; break;
    1961         [ +  - ]:      79148 :     case EM_ARM: expect_machine = "arm*"; break;
    1962                 :            :       // XXX: fill in some more of these
    1963         [ #  # ]:          0 :     default: expect_machine = "?"; break;
    1964                 :            :     }
    1965                 :            : 
    1966         [ +  - ]:      79148 :   if (! debug_filename) debug_filename = main_filename;
    1967         [ -  + ]:      79148 :   if (! debug_filename) debug_filename = name;
    1968                 :            : 
    1969 [ +  - ][ +  - ]:      79148 :   if (fnmatch (expect_machine.c_str(), sess_machine.c_str(), 0) != 0 &&
         [ +  - ][ -  + ]
         [ #  # ][ -  + ]
    1970 [ #  # ][ #  # ]:          0 :       fnmatch (expect_machine2.c_str(), sess_machine.c_str(), 0) != 0)
                 [ #  # ]
    1971                 :            :     {
    1972         [ #  # ]:          0 :       stringstream msg;
    1973 [ #  # ][ #  # ]:          0 :       msg << _F("ELF machine %s|%s (code %d) mismatch with target %s in '%s'",
         [ #  # ][ #  # ]
                 [ #  # ]
    1974                 :            :                 expect_machine.c_str(), expect_machine2.c_str(), elf_machine,
    1975         [ #  # ]:          0 :                 sess_machine.c_str(), debug_filename);
    1976 [ #  # ][ #  # ]:          0 :       throw semantic_error(msg.str ());
    1977                 :            :     }
    1978                 :            : 
    1979         [ +  + ]:      79148 :   if (q->sess.verbose>1)
    1980 [ +  - ][ +  - ]:       7214 :     clog << _F("focused on module '%s' = [%#" PRIx64 "-%#" PRIx64 ", bias %#" PRIx64 
         [ +  - ][ +  - ]
                 [ +  - ]
    1981                 :            :                " file %s ELF machine %s|%s (code %d)\n",
    1982                 :            :                q->dw.module_name.c_str(), q->dw.module_start, q->dw.module_end,
    1983                 :            :                q->dw.module_bias, debug_filename, expect_machine.c_str(),
    1984 [ +  - ][ +  - ]:      82755 :                expect_machine2.c_str(), elf_machine);
                 [ +  - ]
    1985                 :      79148 : }
    1986                 :            : 
    1987                 :            : 
    1988                 :            : 
    1989                 :            : static Dwarf_Addr
    1990                 :       1515 : lookup_symbol_address (Dwfl_Module *m, const char* wanted)
    1991                 :            : {
    1992                 :       1515 :   int syments = dwfl_module_getsymtab(m);
    1993         [ -  + ]:       1515 :   assert(syments);
    1994         [ +  + ]:  147493692 :   for (int i = 1; i < syments; ++i)
    1995                 :            :     {
    1996                 :            :       GElf_Sym sym;
    1997         [ +  - ]:  147493548 :       const char *name = dwfl_module_getsym(m, i, &sym, NULL);
    1998 [ +  - ][ +  + ]:  147493548 :       if (name != NULL && strcmp(name, wanted) == 0)
    1999                 :       1371 :         return sym.st_value;
    2000                 :            :     }
    2001                 :            : 
    2002                 :       1515 :   return 0;
    2003                 :            : }
    2004                 :            : 
    2005                 :            : 
    2006                 :            : 
    2007                 :            : static int
    2008                 :      85119 : query_module (Dwfl_Module *mod,
    2009                 :            :               void **,
    2010                 :            :               const char *name,
    2011                 :            :               Dwarf_Addr addr,
    2012                 :            :               void *arg)
    2013                 :            : {
    2014                 :      85119 :   base_query *q = static_cast<base_query *>(arg);
    2015                 :            : 
    2016                 :            :   try
    2017                 :            :     {
    2018 [ +  - ][ +  - ]:      85119 :       module_info* mi = q->sess.module_cache->cache[name];
                 [ +  - ]
    2019         [ +  + ]:      85119 :       if (mi == 0)
    2020                 :            :         {
    2021 [ +  - ][ +  - ]:       4646 :           mi = q->sess.module_cache->cache[name] = new module_info(name);
         [ +  - ][ +  - ]
                 [ +  - ]
    2022                 :            : 
    2023                 :       4646 :           mi->mod = mod;
    2024                 :       4646 :           mi->addr = addr;
    2025                 :            : 
    2026                 :       4646 :           const char* debug_filename = "";
    2027                 :       4646 :           const char* main_filename = "";
    2028                 :            :           (void) dwfl_module_info (mod, NULL, NULL,
    2029                 :            :                                    NULL, NULL, NULL,
    2030                 :            :                                    & main_filename,
    2031         [ +  - ]:       4646 :                                    & debug_filename);
    2032                 :            : 
    2033 [ +  - ][ +  - ]:       4646 :           if (debug_filename || main_filename)
    2034                 :            :             {
    2035 [ -  + ][ +  - ]:       4646 :               mi->elf_path = debug_filename ?: main_filename;
    2036                 :            :             }
    2037 [ #  # ][ #  # ]:          0 :           else if (name == TOK_KERNEL)
    2038                 :            :             {
    2039                 :       4646 :               mi->dwarf_status = info_absent;
    2040                 :            :             }
    2041                 :            :         }
    2042                 :            :       // OK, enough of that module_info caching business.
    2043                 :            : 
    2044         [ +  - ]:      85119 :       q->dw.focus_on_module(mod, mi);
    2045                 :            : 
    2046                 :            :       // If we have enough information in the pattern to skip a module and
    2047                 :            :       // the module does not match that information, return early.
    2048 [ +  - ][ +  + ]:      85119 :       if (!q->dw.module_name_matches(q->module_val))
    2049         [ -  + ]:       5373 :         return pending_interrupts ? DWARF_CB_ABORT : DWARF_CB_OK;
    2050                 :            : 
    2051                 :            :       // Don't allow module("*kernel*") type expressions to match the
    2052                 :            :       // elfutils module "kernel", which we refer to in the probe
    2053                 :            :       // point syntax exclusively as "kernel.*".
    2054 [ +  - ][ +  + ]:      79746 :       if (q->dw.module_name == TOK_KERNEL && ! q->has_kernel)
         [ +  + ][ +  + ]
    2055         [ -  + ]:        598 :         return pending_interrupts ? DWARF_CB_ABORT : DWARF_CB_OK;
    2056                 :            : 
    2057         [ +  - ]:      79148 :       if (mod)
    2058         [ +  - ]:      79148 :         validate_module_elf(mod, name, q);
    2059                 :            :       else
    2060         [ #  # ]:          0 :         assert(q->has_kernel);   // and no vmlinux to examine
    2061                 :            : 
    2062         [ -  + ]:      79148 :       if (q->sess.verbose>2)
    2063 [ #  # ][ #  # ]:          0 :         cerr << _F("focused on module '%s'\n", q->dw.module_name.c_str());
         [ #  # ][ #  # ]
    2064                 :            : 
    2065                 :            : 
    2066                 :            :       // Collect a few kernel addresses.  XXX: these belong better
    2067                 :            :       // to the sess.module_info["kernel"] struct.
    2068 [ +  - ][ +  + ]:      79148 :       if (q->dw.module_name == TOK_KERNEL)
    2069                 :            :         {
    2070         [ +  + ]:      48653 :           if (! q->sess.sym_kprobes_text_start)
    2071         [ +  - ]:        457 :             q->sess.sym_kprobes_text_start = lookup_symbol_address (mod, "__kprobes_text_start");
    2072         [ +  + ]:      48653 :           if (! q->sess.sym_kprobes_text_end)
    2073         [ +  - ]:        457 :             q->sess.sym_kprobes_text_end = lookup_symbol_address (mod, "__kprobes_text_end");
    2074         [ +  + ]:      48653 :           if (! q->sess.sym_stext)
    2075         [ +  - ]:        457 :             q->sess.sym_stext = lookup_symbol_address (mod, "_stext");
    2076                 :            :         }
    2077                 :            : 
    2078                 :            :       // We either have a wildcard or an unresolved library
    2079 [ +  + ][ +  - ]:      79159 :       if (q->has_library && (contains_glob_chars (q->path)
         [ +  + ][ -  + ]
                 [ +  + ]
    2080         [ +  - ]:         11 :                              || q->path.find('/') == string::npos))
    2081                 :            :         // handle .library(GLOB)
    2082         [ +  - ]:          1 :         q->dw.iterate_over_libraries (&q->query_library_callback, q);
    2083                 :            :       // .plt is translated to .plt.statement(N).  We only want to iterate for the
    2084                 :            :       // .plt case
    2085 [ +  + ][ +  - ]:      79147 :       else if (q->has_plt && ! q->has_statement)
    2086         [ -  + ]:         13 :         q->dw.iterate_over_plt (q, &q->query_plt_callback);
    2087                 :            :       else
    2088                 :            :         // search the module for matches of the probe point.
    2089         [ +  - ]:      79134 :         q->handle_query_module();
    2090                 :            : 
    2091                 :            :       // If we know that there will be no more matches, abort early.
    2092 [ +  - ][ +  + ]:      79135 :       if (q->dw.module_name_final_match(q->module_val) || pending_interrupts)
         [ -  + ][ +  + ]
    2093                 :      55155 :         return DWARF_CB_ABORT;
    2094                 :            :       else
    2095                 :      85119 :         return DWARF_CB_OK;
    2096                 :            :     }
    2097         [ -  + ]:         26 :   catch (const semantic_error& e)
    2098                 :            :     {
    2099         [ -  + ]:         13 :       q->sess.print_error (e);
    2100                 :         13 :       return DWARF_CB_ABORT;
    2101                 :            :     }
    2102                 :            : }
    2103                 :            : 
    2104                 :            : 
    2105                 :            : void
    2106                 :         11 : base_query::query_library_callback (void *q, const char *data)
    2107                 :            : {
    2108                 :         11 :   base_query *me = (base_query*)q;
    2109                 :         11 :   me->query_library (data);
    2110                 :         11 : }
    2111                 :            : 
    2112                 :            : 
    2113                 :            : void
    2114                 :         11 : query_one_library (const char *library, dwflpp & dw,
    2115                 :            :     const string user_lib, probe * base_probe, probe_point *base_loc,
    2116                 :            :     vector<derived_probe *> & results)
    2117                 :            : {
    2118 [ +  - ][ +  - ]:         11 :   if (dw.function_name_matches_pattern(library, "*" + user_lib))
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
    2119                 :            :     {
    2120                 :            :       string library_path = find_executable (library, "", dw.sess.sysenv,
    2121 [ +  - ][ +  - ]:         11 :                                              "LD_LIBRARY_PATH");
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    2122 [ +  - ][ +  - ]:         11 :       probe_point* specific_loc = new probe_point(*base_loc);
    2123                 :         11 :       specific_loc->optional = true;
    2124         [ +  - ]:         11 :       vector<probe_point::component*> derived_comps;
    2125                 :            : 
    2126                 :         11 :       vector<probe_point::component*>::iterator it;
    2127 [ +  - ][ +  - ]:         88 :       for (it = specific_loc->components.begin();
                 [ +  + ]
    2128         [ +  - ]:         44 :           it != specific_loc->components.end(); ++it)
    2129 [ +  - ][ +  + ]:         33 :         if ((*it)->functor == TOK_LIBRARY)
    2130                 :            :           derived_comps.push_back(new probe_point::component(TOK_LIBRARY,
    2131 [ +  - ][ +  - ]:         11 :               new literal_string(library_path)));
         [ +  - ][ +  - ]
                 [ +  - ]
    2132                 :            :         else
    2133         [ +  - ]:         22 :           derived_comps.push_back(*it);
    2134 [ +  - ][ +  - ]:         11 :       probe_point* derived_loc = new probe_point(*specific_loc);
    2135         [ +  - ]:         11 :       derived_loc->components = derived_comps;
    2136         [ +  - ]:         11 :       probe *new_base = base_probe->create_alias(derived_loc, specific_loc);
    2137         [ +  - ]:         11 :       derive_probes(dw.sess, new_base, results);
    2138         [ -  + ]:         11 :       if (dw.sess.verbose > 2)
    2139 [ #  # ][ #  # ]:         11 :         clog << _("module=") << library_path;
         [ +  - ][ +  - ]
    2140                 :            :     }
    2141                 :         11 : }
    2142                 :            : 
    2143                 :            : 
    2144                 :            : void
    2145                 :         11 : dwarf_query::query_library (const char *library)
    2146                 :            : {
    2147         [ +  - ]:         11 :   query_one_library (library, dw, user_lib, base_probe, base_loc, results);
    2148                 :         11 : }
    2149                 :            : 
    2150         [ #  # ]:          0 : struct plt_expanding_visitor: public var_expanding_visitor
    2151                 :            : {
    2152                 :          0 :   plt_expanding_visitor(const string & entry):
    2153                 :          0 :     entry (entry)
    2154                 :            :   {
    2155                 :          0 :   }
    2156                 :            :   const string & entry;
    2157                 :            : 
    2158                 :            :   void visit_target_symbol (target_symbol* e);
    2159                 :            : };
    2160                 :            : 
    2161                 :            : 
    2162                 :            : void
    2163                 :          0 : base_query::query_plt_callback (void *q, const char *entry, size_t address)
    2164                 :            : {
    2165                 :          0 :   base_query *me = (base_query*)q;
    2166 [ #  # ][ #  # ]:          0 :   if (me->dw.function_name_matches_pattern (entry, me->plt_val))
         [ #  # ][ #  # ]
    2167                 :          0 :     me->query_plt (entry, address);
    2168                 :          0 : }
    2169                 :            : 
    2170                 :            : 
    2171                 :            : void
    2172                 :          0 : query_one_plt (const char *entry, long addr, dwflpp & dw,
    2173                 :            :     probe * base_probe, probe_point *base_loc,
    2174                 :            :     vector<derived_probe *> & results)
    2175                 :            : {
    2176 [ #  # ][ #  # ]:          0 :       probe_point* specific_loc = new probe_point(*base_loc);
    2177                 :          0 :       specific_loc->optional = true;
    2178         [ #  # ]:          0 :       vector<probe_point::component*> derived_comps;
    2179                 :            : 
    2180         [ #  # ]:          0 :       if (dw.sess.verbose > 2)
    2181 [ #  # ][ #  # ]:          0 :         clog << _F("plt entry=%s\n", entry);
                 [ #  # ]
    2182                 :            : 
    2183                 :            :       // query_module_symtab requires .plt to recognize that it can set the probe at
    2184                 :            :       // a plt entry so we convert process.plt to process.plt.statement
    2185                 :          0 :       vector<probe_point::component*>::iterator it;
    2186 [ #  # ][ #  # ]:          0 :       for (it = specific_loc->components.begin();
                 [ #  # ]
    2187         [ #  # ]:          0 :           it != specific_loc->components.end(); ++it)
    2188 [ #  # ][ #  # ]:          0 :         if ((*it)->functor == TOK_PLT)
    2189                 :            :           {
    2190         [ #  # ]:          0 :             derived_comps.push_back(*it);
    2191                 :            :             derived_comps.push_back(new probe_point::component(TOK_STATEMENT,
    2192 [ #  # ][ #  # ]:          0 :                 new literal_number(addr)));
         [ #  # ][ #  # ]
                 [ #  # ]
    2193                 :            :           }
    2194                 :            :         else
    2195         [ #  # ]:          0 :           derived_comps.push_back(*it);
    2196 [ #  # ][ #  # ]:          0 :       probe_point* derived_loc = new probe_point(*specific_loc);
    2197         [ #  # ]:          0 :       derived_loc->components = derived_comps;
    2198         [ #  # ]:          0 :       probe *new_base = base_probe->create_alias(derived_loc, specific_loc);
    2199         [ #  # ]:          0 :       string e = string(entry);
    2200         [ #  # ]:          0 :       plt_expanding_visitor pltv (e);
    2201         [ #  # ]:          0 :       pltv.replace (new_base->body);
    2202 [ #  # ][ #  # ]:          0 :       derive_probes(dw.sess, new_base, results);
         [ #  # ][ #  # ]
    2203                 :          0 : }
    2204                 :            : 
    2205                 :            : 
    2206                 :            : void
    2207                 :          0 : dwarf_query::query_plt (const char *entry, size_t address)
    2208                 :            : {
    2209                 :          0 :   query_one_plt (entry, address, dw, base_probe, base_loc, results);
    2210                 :          0 : }
    2211                 :            : 
    2212                 :            : // This would more naturally fit into elaborate.cxx:semantic_pass_symbols,
    2213                 :            : // but the needed declaration for module_cache is not available there.
    2214                 :            : // Nor for that matter in session.cxx.  Only in this CU is that field ever
    2215                 :            : // set (in query_module() above), so we clean it up here too.
    2216                 :            : static void
    2217                 :     124278 : delete_session_module_cache (systemtap_session& s)
    2218                 :            : {
    2219         [ +  + ]:     124278 :   if (s.module_cache) {
    2220         [ -  + ]:        643 :     if (s.verbose > 3)
    2221                 :          0 :       clog << _("deleting module_cache") << endl;
    2222         [ +  - ]:        643 :     delete s.module_cache;
    2223                 :        643 :     s.module_cache = 0;
    2224                 :            :   }
    2225                 :     124278 : }
    2226                 :            : 
    2227                 :            : 
    2228 [ +  - ][ +  - ]:     330173 : struct dwarf_var_expanding_visitor: public var_expanding_visitor
         [ +  - ][ -  + ]
    2229                 :            : {
    2230                 :            :   dwarf_query & q;
    2231                 :            :   Dwarf_Die *scope_die;
    2232                 :            :   Dwarf_Addr addr;
    2233                 :            :   block *add_block;
    2234                 :            :   block *add_call_probe; // synthesized from .return probes with saved $vars
    2235                 :            :   // NB: tids are not always collected in add_block & add_call_probe, because
    2236                 :            :   // gen_kretprobe_saved_return doesn't need them.  Thus we need these extra
    2237                 :            :   // *_tid bools for gen_mapped_saved_return to tell what's there.
    2238                 :            :   bool add_block_tid, add_call_probe_tid;
    2239                 :            :   unsigned saved_longs, saved_strings; // data saved within kretprobes
    2240                 :            :   map<std::string, expression *> return_ts_map;
    2241                 :            :   vector<Dwarf_Die> scopes;
    2242                 :            :   // probe counter name -> pointer of associated probe
    2243                 :            :   std::set<derived_probe*> perf_counter_refs;
    2244                 :            :   bool visited;
    2245                 :            : 
    2246                 :     330173 :   dwarf_var_expanding_visitor(dwarf_query & q, Dwarf_Die *sd, Dwarf_Addr a):
    2247                 :            :     q(q), scope_die(sd), addr(a), add_block(NULL), add_call_probe(NULL),
    2248                 :            :     add_block_tid(false), add_call_probe_tid(false),
    2249 [ +  - ][ +  - ]:     330173 :     saved_longs(0), saved_strings(0), visited(false) {}
                 [ +  - ]
    2250                 :            :   expression* gen_mapped_saved_return(expression* e, const string& name);
    2251                 :            :   expression* gen_kretprobe_saved_return(expression* e);
    2252                 :            :   void visit_target_symbol_saved_return (target_symbol* e);
    2253                 :            :   void visit_target_symbol_context (target_symbol* e);
    2254                 :            :   void visit_target_symbol (target_symbol* e);
    2255                 :            :   void visit_cast_op (cast_op* e);
    2256                 :            :   void visit_entry_op (entry_op* e);
    2257                 :            :   void visit_perf_op (perf_op* e);
    2258                 :            : private:
    2259                 :            :   vector<Dwarf_Die>& getcuscope(target_symbol *e);
    2260                 :            :   vector<Dwarf_Die>& getscopes(target_symbol *e);
    2261                 :            : };
    2262                 :            : 
    2263                 :            : 
    2264                 :            : unsigned var_expanding_visitor::tick = 0;
    2265                 :            : 
    2266                 :            : 
    2267 [ +  - ][ +  - ]:     354775 : var_expanding_visitor::var_expanding_visitor (): op()
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    2268                 :            : {
    2269                 :            :   // FIXME: for the time being, by default we only support plain '$foo
    2270                 :            :   // = bar', not '+=' or any other op= variant. This is fixable, but a
    2271                 :            :   // bit ugly.
    2272                 :            :   //
    2273                 :            :   // If derived classes desire to add additional operator support, add
    2274                 :            :   // new operators to this list in the derived class constructor.
    2275 [ +  - ][ +  - ]:     354775 :   valid_ops.insert ("=");
                 [ +  - ]
    2276                 :     354775 : }
    2277                 :            : 
    2278                 :            : 
    2279                 :            : bool
    2280                 :     613658 : var_expanding_visitor::rewrite_lvalue(const token* tok, const std::string& eop,
    2281                 :            :                                       expression*& lvalue, expression*& rvalue)
    2282                 :            : {
    2283                 :            :   // Our job would normally be to require() the left and right sides
    2284                 :            :   // into a new assignment. What we're doing is slightly trickier:
    2285                 :            :   // we're pushing a functioncall** onto a stack, and if our left
    2286                 :            :   // child sets the functioncall* for that value, we're going to
    2287                 :            :   // assume our left child was a target symbol -- transformed into a
    2288                 :            :   // set_target_foo(value) call, and it wants to take our right child
    2289                 :            :   // as the argument "value".
    2290                 :            :   //
    2291                 :            :   // This is why some people claim that languages with
    2292                 :            :   // constructor-decomposing case expressions have a leg up on
    2293                 :            :   // visitors.
    2294                 :            : 
    2295                 :     613658 :   functioncall *fcall = NULL;
    2296                 :            : 
    2297                 :            :   // Let visit_target_symbol know what operator it should handle.
    2298                 :     613658 :   const string* old_op = op;
    2299                 :     613658 :   op = &eop;
    2300                 :            : 
    2301         [ +  - ]:     613658 :   target_symbol_setter_functioncalls.push (&fcall);
    2302         [ +  + ]:     613658 :   replace (lvalue);
    2303         [ +  - ]:     613657 :   target_symbol_setter_functioncalls.pop ();
    2304         [ +  + ]:     613657 :   replace (rvalue);
    2305                 :            : 
    2306                 :     613655 :   op = old_op;
    2307                 :            : 
    2308         [ +  + ]:     613655 :   if (fcall != NULL)
    2309                 :            :     {
    2310                 :            :       // Our left child is informing us that it was a target variable
    2311                 :            :       // and it has been replaced with a set_target_foo() function
    2312                 :            :       // call; we are going to provide that function call -- with the
    2313                 :            :       // right child spliced in as sole argument -- in place of
    2314                 :            :       // ourselves, in the var expansion we're in the middle of making.
    2315                 :            : 
    2316 [ +  - ][ +  - ]:         56 :       if (valid_ops.find (eop) == valid_ops.end ())
                 [ +  + ]
    2317                 :            :         {
    2318                 :            :           // Build up a list of supported operators.
    2319         [ +  - ]:          4 :           string ops;
    2320                 :          4 :           std::set<string>::iterator i;
    2321                 :          4 :           int valid_ops_size = 0;
    2322 [ +  - ][ +  - ]:          8 :           for (i = valid_ops.begin(); i != valid_ops.end(); i++)
                 [ +  + ]
    2323                 :            :           {
    2324 [ +  - ][ +  - ]:          4 :             ops += " " + *i + ",";
         [ +  - ][ +  - ]
                 [ +  - ]
    2325                 :          4 :             valid_ops_size++;
    2326                 :            :           }
    2327 [ +  - ][ +  - ]:          4 :           ops.resize(ops.size() - 1);   // chop off the last ','
    2328                 :            : 
    2329                 :            :           // Throw the error.
    2330                 :          4 :           throw semantic_error (_F(ngettext("Only the following assign operator is implemented on target variables: %s",
    2331                 :            :                                             "Only the following assign operators are implemented on target variables: %s",
    2332 [ +  - ][ +  - ]:         11 :                                            valid_ops_size), ops.c_str()), tok);
                 [ +  - ]
    2333                 :            : 
    2334                 :            :         }
    2335                 :            : 
    2336         [ -  + ]:         52 :       assert (lvalue == fcall);
    2337         [ +  - ]:         52 :       if (rvalue)
    2338         [ +  - ]:         52 :         fcall->args.push_back (rvalue);
    2339         [ +  - ]:         52 :       provide (fcall);
    2340                 :         52 :       return true;
    2341                 :            :     }
    2342                 :            :   else
    2343                 :     613651 :     return false;
    2344                 :            : }
    2345                 :            : 
    2346                 :            : 
    2347                 :            : void
    2348                 :     519808 : var_expanding_visitor::visit_assignment (assignment* e)
    2349                 :            : {
    2350         [ +  + ]:     519808 :   if (!rewrite_lvalue (e->tok, e->op, e->left, e->right))
    2351                 :     519753 :     provide (e);
    2352                 :     519805 : }
    2353                 :            : 
    2354                 :            : 
    2355                 :            : void
    2356                 :       3562 : var_expanding_visitor::visit_pre_crement (pre_crement* e)
    2357                 :            : {
    2358                 :       3562 :   expression *dummy = NULL;
    2359 [ +  + ][ +  - ]:       3562 :   if (!rewrite_lvalue (e->tok, e->op, e->operand, dummy))
    2360         [ +  - ]:       3560 :     provide (e);
    2361                 :       3562 : }
    2362                 :            : 
    2363                 :            : 
    2364                 :            : void
    2365                 :      85807 : var_expanding_visitor::visit_post_crement (post_crement* e)
    2366                 :            : {
    2367                 :      85807 :   expression *dummy = NULL;
    2368 [ +  + ][ +  - ]:      85807 :   if (!rewrite_lvalue (e->tok, e->op, e->operand, dummy))
    2369         [ +  - ]:      85806 :     provide (e);
    2370                 :      85807 : }
    2371                 :            : 
    2372                 :            : 
    2373                 :            : void
    2374                 :       4481 : var_expanding_visitor::visit_delete_statement (delete_statement* s)
    2375                 :            : {
    2376         [ +  - ]:       4481 :   string fakeop = "delete";
    2377                 :       4481 :   expression *dummy = NULL;
    2378 [ +  + ][ +  - ]:       4481 :   if (!rewrite_lvalue (s->tok, fakeop, s->value, dummy))
    2379 [ +  - ][ +  - ]:       4481 :     provide (s);
    2380                 :       4480 : }
    2381                 :            : 
    2382                 :            : 
    2383                 :            : void
    2384                 :       6588 : var_expanding_visitor::visit_defined_op (defined_op* e)
    2385                 :            : {
    2386                 :       6588 :   bool resolved = true;
    2387                 :            : 
    2388                 :       6588 :   defined_ops.push (e);
    2389                 :            :   try {
    2390                 :            :     // NB: provide<>/require<> are NOT typesafe.  So even though a defined_op is
    2391                 :            :     // defined with a target_symbol* operand, a subsidiary call may attempt to
    2392                 :            :     // rewrite it to a general expression* instead, and require<> happily
    2393                 :            :     // casts to/from void*, causing possible memory corruption.  We use
    2394                 :            :     // expression* here, being the general case of rewritten $variable.
    2395                 :       6588 :     expression *foo1 = e->operand;
    2396         [ +  - ]:       6588 :     foo1 = require (foo1);
    2397                 :            : 
    2398                 :            :     // NB: Formerly, we had some curious cases to consider here, depending on what
    2399                 :            :     // various visit_target_symbol() implementations do for successful or
    2400                 :            :     // erroneous resolutions.  Some would signal a visit_target_symbol failure
    2401                 :            :     // with an exception, with a set flag within the target_symbol, or nothing
    2402                 :            :     // at all.
    2403                 :            :     //
    2404                 :            :     // Now, failures always have to be signalled with a
    2405                 :            :     // saved_conversion_error being chained to the target_symbol.
    2406                 :            :     // Successes have to result in an attempted rewrite of the
    2407                 :            :     // target_symbol (via provide()).
    2408                 :            :     //
    2409                 :            :     // Edna Mode: "no capes".  fche: "no exceptions".
    2410                 :            : 
    2411                 :            :     // dwarf stuff: success: rewrites to a function; failure: retains target_symbol, sets saved_conversion_error
    2412                 :            :     //
    2413                 :            :     // sdt-kprobes sdt.h: success: string or functioncall; failure: semantic_error
    2414                 :            :     //
    2415                 :            :     // sdt-uprobes: success: string or no op; failure: no op; expect derived/synthetic
    2416                 :            :     //              dwarf probe to take care of it.
    2417                 :            :     //              But this is rather unhelpful.  So we rig the sdt_var_expanding_visitor
    2418                 :            :     //              to pass through @defined() to the synthetic dwarf probe.
    2419                 :            :     //
    2420                 :            :     // utrace: success: rewrites to function; failure: semantic_error
    2421                 :            :     //
    2422                 :            :     // procfs: success: rewrites to function; failure: semantic_error
    2423                 :            : 
    2424         [ -  + ]:       6588 :     target_symbol* foo2 = dynamic_cast<target_symbol*> (foo1);
    2425 [ +  + ][ +  + ]:       6588 :     if (foo2 && foo2->saved_conversion_error) // failing
    2426                 :       2455 :       resolved = false;
    2427         [ +  + ]:       4133 :     else if (foo2) // unresolved but not marked failing
    2428                 :            :       {
    2429                 :            :         // There are some visitors that won't touch certain target_symbols,
    2430                 :            :         // e.g. dwarf_var_expanding_visitor won't resolve @cast.  We should
    2431                 :            :         // leave it for now so some other visitor can have a chance.
    2432                 :         14 :         e->operand = foo2;
    2433         [ +  - ]:         14 :         provide (e);
    2434         [ #  # ]:       6588 :         return;
    2435                 :            :       }
    2436                 :            :     else // resolved, rewritten to some other expression type
    2437                 :       4119 :       resolved = true;
    2438                 :            :   } catch (const semantic_error& e) {
    2439                 :            :     assert (0); // should not happen
    2440                 :            :   }
    2441                 :       6574 :   defined_ops.pop ();
    2442                 :            : 
    2443 [ +  + ][ +  - ]:       6574 :   literal_number* ln = new literal_number (resolved ? 1 : 0);
    2444                 :       6574 :   ln->tok = e->tok;
    2445                 :       6574 :   provide (ln);
    2446                 :            : }
    2447                 :            : 
    2448                 :            : 
    2449                 :            : struct dwarf_pretty_print
    2450                 :            : {
    2451                 :       1581 :   dwarf_pretty_print (dwflpp& dw, vector<Dwarf_Die>& scopes, Dwarf_Addr pc,
    2452                 :            :                       const string& local, bool userspace_p,
    2453                 :            :                       const target_symbol& e):
    2454                 :            :     dw(dw), local(local), scopes(scopes), pc(pc), pointer(NULL),
    2455         [ +  - ]:       1581 :     userspace_p(userspace_p), deref_p(true)
    2456                 :            :   {
    2457         [ +  - ]:       1581 :     init_ts (e);
    2458         [ +  - ]:       1581 :     dw.type_die_for_local (scopes, pc, local, ts, &base_type);
    2459                 :       1581 :   }
    2460                 :            : 
    2461                 :          0 :   dwarf_pretty_print (dwflpp& dw, Dwarf_Die *scope_die, Dwarf_Addr pc,
    2462                 :            :                       bool userspace_p, const target_symbol& e):
    2463                 :            :     dw(dw), scopes(1, *scope_die), pc(pc), pointer(NULL),
    2464         [ #  # ]:          0 :     userspace_p(userspace_p), deref_p(true)
    2465                 :            :   {
    2466         [ #  # ]:          0 :     init_ts (e);
    2467         [ #  # ]:          0 :     dw.type_die_for_return (&scopes[0], pc, ts, &base_type);
    2468                 :          0 :   }
    2469                 :            : 
    2470                 :        888 :   dwarf_pretty_print (dwflpp& dw, Dwarf_Die *type_die, expression* pointer,
    2471                 :            :                       bool deref_p, bool userspace_p, const target_symbol& e):
    2472                 :            :     dw(dw), pc(0), pointer(pointer), pointer_type(*type_die),
    2473         [ +  - ]:        888 :     userspace_p(userspace_p), deref_p(deref_p)
    2474                 :            :   {
    2475         [ +  - ]:        888 :     init_ts (e);
    2476         [ +  - ]:        888 :     dw.type_die_for_pointer (type_die, ts, &base_type);
    2477                 :        888 :   }
    2478                 :            : 
    2479                 :            :   functioncall* expand ();
    2480 [ +  - ][ +  - ]:       2469 :   ~dwarf_pretty_print () { delete ts; }
                 [ +  - ]
    2481                 :            : 
    2482                 :            : private:
    2483                 :            :   dwflpp& dw;
    2484                 :            :   target_symbol* ts;
    2485                 :            :   bool print_full;
    2486                 :            :   Dwarf_Die base_type;
    2487                 :            : 
    2488                 :            :   string local;
    2489                 :            :   vector<Dwarf_Die> scopes;
    2490                 :            :   Dwarf_Addr pc;
    2491                 :            : 
    2492                 :            :   expression* pointer;
    2493                 :            :   Dwarf_Die pointer_type;
    2494                 :            : 
    2495                 :            :   const bool userspace_p, deref_p;
    2496                 :            : 
    2497                 :            :   void recurse (Dwarf_Die* type, target_symbol* e,
    2498                 :            :                 print_format* pf, bool top=false);
    2499                 :            :   void recurse_bitfield (Dwarf_Die* type, target_symbol* e,
    2500                 :            :                          print_format* pf);
    2501                 :            :   void recurse_base (Dwarf_Die* type, target_symbol* e,
    2502                 :            :                      print_format* pf);
    2503                 :            :   void recurse_array (Dwarf_Die* type, target_symbol* e,
    2504                 :            :                       print_format* pf, bool top);
    2505                 :            :   void recurse_pointer (Dwarf_Die* type, target_symbol* e,
    2506                 :            :                         print_format* pf, bool top);
    2507                 :            :   void recurse_struct (Dwarf_Die* type, target_symbol* e,
    2508                 :            :                        print_format* pf, bool top);
    2509                 :            :   void recurse_struct_members (Dwarf_Die* type, target_symbol* e,
    2510                 :            :                                print_format* pf, int& count);
    2511                 :            :   bool print_chars (Dwarf_Die* type, target_symbol* e, print_format* pf);
    2512                 :            : 
    2513                 :            :   void init_ts (const target_symbol& e);
    2514                 :            :   expression* deref (target_symbol* e);
    2515                 :            :   bool push_deref (print_format* pf, const string& fmt, target_symbol* e);
    2516                 :            : };
    2517                 :            : 
    2518                 :            : 
    2519                 :            : void
    2520                 :       2469 : dwarf_pretty_print::init_ts (const target_symbol& e)
    2521                 :            : {
    2522                 :            :   // Work with a new target_symbol so we can modify arguments
    2523         [ +  - ]:       2469 :   ts = new target_symbol (e);
    2524                 :            : 
    2525         [ -  + ]:       2469 :   if (ts->addressof)
    2526 [ #  # ][ #  # ]:          0 :     throw semantic_error(_("cannot take address of pretty-printed variable"), ts->tok);
    2527                 :            : 
    2528   [ +  -  -  + ]:       4938 :   if (ts->components.empty() ||
                 [ -  + ]
    2529                 :       2469 :       ts->components.back().type != target_symbol::comp_pretty_print)
    2530 [ #  # ][ #  # ]:          0 :     throw semantic_error(_("invalid target_symbol for pretty-print"), ts->tok);
    2531                 :       2469 :   print_full = ts->components.back().member.length() > 1;
    2532                 :       2469 :   ts->components.pop_back();
    2533                 :       2469 : }
    2534                 :            : 
    2535                 :            : 
    2536                 :            : functioncall*
    2537                 :       2469 : dwarf_pretty_print::expand ()
    2538                 :            : {
    2539                 :            :   static unsigned tick = 0;
    2540                 :            : 
    2541                 :            :   // function pretty_print_X([pointer], [arg1, arg2, ...]) {
    2542                 :            :   //   try {
    2543                 :            :   //     return sprintf("{.foo=...}", (ts)->foo, ...)
    2544                 :            :   //   } catch {
    2545                 :            :   //     return "ERROR"
    2546                 :            :   //   }
    2547                 :            :   // }
    2548                 :            : 
    2549                 :            :   // Create the function decl and call.
    2550                 :            : 
    2551         [ +  - ]:       2469 :   functiondecl *fdecl = new functiondecl;
    2552                 :       2469 :   fdecl->tok = ts->tok;
    2553                 :       2469 :   fdecl->synthetic = true;
    2554 [ +  - ][ +  - ]:       2469 :   fdecl->name = "_dwarf_pretty_print_" + lex_cast(tick++);
         [ +  - ][ +  - ]
                 [ +  - ]
    2555                 :       2469 :   fdecl->type = pe_string;
    2556                 :            : 
    2557         [ +  - ]:       2469 :   functioncall* fcall = new functioncall;
    2558                 :       2469 :   fcall->tok = ts->tok;
    2559                 :       2469 :   fcall->function = fdecl->name;
    2560                 :       2469 :   fcall->type = pe_string;
    2561                 :            : 
    2562                 :            :   // If there's a <pointer>, replace it with a new var and make that
    2563                 :            :   // the first function argument.
    2564         [ +  + ]:       2469 :   if (pointer)
    2565                 :            :     {
    2566 [ +  - ][ +  - ]:        888 :       vardecl *v = new vardecl;
    2567                 :        888 :       v->type = pe_long;
    2568         [ +  - ]:        888 :       v->name = "pointer";
    2569                 :        888 :       v->tok = ts->tok;
    2570         [ +  - ]:        888 :       fdecl->formal_args.push_back (v);
    2571         [ +  - ]:        888 :       fcall->args.push_back (pointer);
    2572                 :            : 
    2573 [ +  - ][ +  - ]:        888 :       symbol* sym = new symbol;
    2574                 :        888 :       sym->tok = ts->tok;
    2575         [ +  - ]:        888 :       sym->name = v->name;
    2576                 :        888 :       pointer = sym;
    2577                 :            :     }
    2578                 :            : 
    2579                 :            :   // For each expression argument, replace it with a function argument.
    2580         [ +  + ]:       2553 :   for (unsigned i = 0; i < ts->components.size(); ++i)
    2581         [ +  + ]:         84 :     if (ts->components[i].type == target_symbol::comp_expression_array_index)
    2582                 :            :       {
    2583 [ +  - ][ +  - ]:         14 :         vardecl *v = new vardecl;
    2584                 :         14 :         v->type = pe_long;
    2585 [ +  - ][ +  - ]:         14 :         v->name = "index" + lex_cast(i);
         [ +  - ][ +  - ]
                 [ +  - ]
    2586                 :         14 :         v->tok = ts->tok;
    2587         [ +  - ]:         14 :         fdecl->formal_args.push_back (v);
    2588         [ +  - ]:         14 :         fcall->args.push_back (ts->components[i].expr_index);
    2589                 :            : 
    2590 [ +  - ][ +  - ]:         14 :         symbol* sym = new symbol;
    2591                 :         14 :         sym->tok = ts->tok;
    2592         [ +  - ]:         14 :         sym->name = v->name;
    2593                 :         14 :         ts->components[i].expr_index = sym;
    2594                 :            :       }
    2595                 :            : 
    2596                 :            :   // Create the return sprintf.
    2597         [ +  - ]:       2469 :   token* pf_tok = new token(*ts->tok);
    2598                 :       2469 :   pf_tok->content = "sprintf";
    2599                 :       2469 :   print_format* pf = print_format::create(pf_tok);
    2600         [ +  - ]:       2469 :   return_statement* rs = new return_statement;
    2601                 :       2469 :   rs->tok = ts->tok;
    2602                 :       2469 :   rs->value = pf;
    2603                 :            : 
    2604                 :            :   // Recurse into the actual values.
    2605                 :       2469 :   recurse (&base_type, ts, pf, true);
    2606         [ +  - ]:       2469 :   pf->components = print_format::string_to_components(pf->raw_components);
    2607                 :            : 
    2608                 :            :   // Create the try-catch net
    2609         [ +  - ]:       2469 :   try_block* tb = new try_block;
    2610                 :       2469 :   tb->tok = ts->tok;
    2611                 :       2469 :   tb->try_block = rs;
    2612                 :       2469 :   tb->catch_error_var = 0;
    2613         [ +  - ]:       2469 :   return_statement* rs2 = new return_statement;
    2614                 :       2469 :   rs2->tok = ts->tok;
    2615 [ +  - ][ +  - ]:       2469 :   rs2->value = new literal_string ("ERROR");
         [ +  - ][ +  - ]
    2616                 :       2469 :   rs2->value->tok = ts->tok;
    2617                 :       2469 :   tb->catch_block = rs2;
    2618                 :       2469 :   fdecl->body = tb;
    2619                 :            : 
    2620                 :       2469 :   fdecl->join (dw.sess);
    2621                 :       2469 :   return fcall;
    2622                 :            : }
    2623                 :            : 
    2624                 :            : 
    2625                 :            : void
    2626                 :      47399 : dwarf_pretty_print::recurse (Dwarf_Die* start_type, target_symbol* e,
    2627                 :            :                              print_format* pf, bool top)
    2628                 :            : {
    2629                 :            :   Dwarf_Die type;
    2630         [ +  - ]:      47399 :   dw.resolve_unqualified_inner_typedie (start_type, &type, e);
    2631                 :            : 
    2632 [ +  - ][ -  +  :      47399 :   switch (dwarf_tag(&type))
             +  +  +  + ]
    2633                 :            :     {
    2634                 :            :     default:
    2635                 :            :       // XXX need a warning?
    2636                 :            :       // throw semantic_error ("unsupported type (tag " + lex_cast(dwarf_tag(&type))
    2637                 :            :       //                       + ") for " + dwarf_type_name(&type), e->tok);
    2638         [ #  # ]:          0 :       pf->raw_components.append("?");
    2639                 :          0 :       break;
    2640                 :            : 
    2641                 :            :     case DW_TAG_enumeration_type:
    2642                 :            :     case DW_TAG_base_type:
    2643         [ +  - ]:      19373 :       recurse_base (&type, e, pf);
    2644                 :      19373 :       break;
    2645                 :            : 
    2646                 :            :     case DW_TAG_array_type:
    2647         [ +  - ]:        416 :       recurse_array (&type, e, pf, top);
    2648                 :        416 :       break;
    2649                 :            : 
    2650                 :            :     case DW_TAG_pointer_type:
    2651                 :            :     case DW_TAG_reference_type:
    2652                 :            :     case DW_TAG_rvalue_reference_type:
    2653         [ +  - ]:      14063 :       recurse_pointer (&type, e, pf, top);
    2654                 :      14063 :       break;
    2655                 :            : 
    2656                 :            :     case DW_TAG_subroutine_type:
    2657 [ +  - ][ +  - ]:         46 :       push_deref (pf, "<function>:%p", e);
                 [ +  - ]
    2658                 :         46 :       break;
    2659                 :            : 
    2660                 :            :     case DW_TAG_union_type:
    2661                 :            :     case DW_TAG_structure_type:
    2662                 :            :     case DW_TAG_class_type:
    2663         [ +  - ]:      13501 :       recurse_struct (&type, e, pf, top);
    2664                 :      13501 :       break;
    2665                 :            :     }
    2666                 :      47399 : }
    2667                 :            : 
    2668                 :            : 
    2669                 :            : // Bit fields are handled as a special-case combination of recurse() and
    2670                 :            : // recurse_base(), only called from recurse_struct_members().  The main
    2671                 :            : // difference is that the value is always printed numerically, even if the
    2672                 :            : // underlying type is a char.
    2673                 :            : void
    2674                 :        421 : dwarf_pretty_print::recurse_bitfield (Dwarf_Die* start_type, target_symbol* e,
    2675                 :            :                                       print_format* pf)
    2676                 :            : {
    2677                 :            :   Dwarf_Die type;
    2678         [ +  - ]:        421 :   dw.resolve_unqualified_inner_typedie (start_type, &type, e);
    2679                 :            : 
    2680         [ +  - ]:        421 :   int tag = dwarf_tag(&type);
    2681 [ -  + ][ #  # ]:        421 :   if (tag != DW_TAG_base_type && tag != DW_TAG_enumeration_type)
    2682                 :            :     {
    2683                 :            :       // XXX need a warning?
    2684                 :            :       // throw semantic_error ("unsupported bitfield type (tag " + lex_cast(tag)
    2685                 :            :       //                       + ") for " + dwarf_type_name(&type), e->tok);
    2686         [ #  # ]:          0 :       pf->raw_components.append("?");
    2687                 :        421 :       return;
    2688                 :            :     }
    2689                 :            : 
    2690                 :            :   Dwarf_Attribute attr;
    2691                 :        421 :   Dwarf_Word encoding = (Dwarf_Word) -1;
    2692                 :            :   dwarf_formudata (dwarf_attr_integrate (&type, DW_AT_encoding, &attr),
    2693 [ +  - ][ +  - ]:        421 :                    &encoding);
    2694      [ -  +  + ]:        421 :   switch (encoding)
    2695                 :            :     {
    2696                 :            :     case DW_ATE_float:
    2697                 :            :     case DW_ATE_complex_float:
    2698                 :            :       // XXX need a warning?
    2699                 :            :       // throw semantic_error ("unsupported bitfield type (encoding " + lex_cast(encoding)
    2700                 :            :       //                       + ") for " + dwarf_type_name(&type), e->tok);
    2701         [ #  # ]:          0 :       pf->raw_components.append("?");
    2702                 :          0 :       break;
    2703                 :            : 
    2704                 :            :     case DW_ATE_unsigned:
    2705                 :            :     case DW_ATE_unsigned_char:
    2706 [ +  - ][ +  - ]:        391 :       push_deref (pf, "%u", e);
                 [ +  - ]
    2707                 :        391 :       break;
    2708                 :            : 
    2709                 :            :     case DW_ATE_signed:
    2710                 :            :     case DW_ATE_signed_char:
    2711                 :            :     default:
    2712 [ +  - ][ +  - ]:         30 :       push_deref (pf, "%i", e);
                 [ +  - ]
    2713                 :        421 :       break;
    2714                 :            :     }
    2715                 :            : }
    2716                 :            : 
    2717                 :            : 
    2718                 :            : void
    2719                 :      19373 : dwarf_pretty_print::recurse_base (Dwarf_Die* type, target_symbol* e,
    2720                 :            :                                   print_format* pf)
    2721                 :            : {
    2722                 :            :   Dwarf_Attribute attr;
    2723                 :      19373 :   Dwarf_Word encoding = (Dwarf_Word) -1;
    2724                 :            :   dwarf_formudata (dwarf_attr_integrate (type, DW_AT_encoding, &attr),
    2725 [ +  - ][ +  - ]:      19373 :                    &encoding);
    2726   [ -  +  +  + ]:      19373 :   switch (encoding)
    2727                 :            :     {
    2728                 :            :     case DW_ATE_float:
    2729                 :            :     case DW_ATE_complex_float:
    2730                 :            :       // XXX need a warning?
    2731                 :            :       // throw semantic_error ("unsupported type (encoding " + lex_cast(encoding)
    2732                 :            :       //                       + ") for " + dwarf_type_name(type), e->tok);
    2733         [ #  # ]:          0 :       pf->raw_components.append("?");
    2734                 :          0 :       break;
    2735                 :            : 
    2736                 :            :     case DW_ATE_UTF: // XXX need to add unicode to _stp_vsprint_char
    2737                 :            :     case DW_ATE_signed_char:
    2738                 :            :     case DW_ATE_unsigned_char:
    2739                 :            :       // Use escapes to make sure that non-printable characters
    2740                 :            :       // don't interrupt our stream (especially '\0' values).
    2741 [ +  - ][ +  - ]:        215 :       push_deref (pf, "'%#c'", e);
                 [ +  - ]
    2742                 :        215 :       break;
    2743                 :            : 
    2744                 :            :     case DW_ATE_unsigned:
    2745 [ +  - ][ +  - ]:      13015 :       push_deref (pf, "%u", e);
                 [ +  - ]
    2746                 :      13015 :       break;
    2747                 :            : 
    2748                 :            :     case DW_ATE_signed:
    2749                 :            :     default:
    2750 [ +  - ][ +  - ]:       6143 :       push_deref (pf, "%i", e);
                 [ +  - ]
    2751                 :       6143 :       break;
    2752                 :            :     }
    2753                 :      19373 : }
    2754                 :            : 
    2755                 :            : 
    2756                 :            : void
    2757                 :        416 : dwarf_pretty_print::recurse_array (Dwarf_Die* type, target_symbol* e,
    2758                 :            :                                    print_format* pf, bool top)
    2759                 :            : {
    2760 [ +  + ][ +  + ]:        416 :   if (!top && !print_full)
    2761                 :            :     {
    2762         [ +  - ]:          2 :       pf->raw_components.append("[...]");
    2763                 :            :       return;
    2764                 :            :     }
    2765                 :            : 
    2766                 :            :   Dwarf_Die childtype;
    2767         [ +  - ]:        414 :   dwarf_attr_die (type, DW_AT_type, &childtype);
    2768                 :            : 
    2769 [ +  - ][ +  + ]:        414 :   if (print_chars (&childtype, e, pf))
    2770                 :            :     return;
    2771                 :            : 
    2772         [ +  - ]:        217 :   pf->raw_components.append("[");
    2773                 :            : 
    2774                 :            :   // We print the array up to the first 5 elements.
    2775                 :            :   // XXX how can we determine the array size?
    2776                 :            :   // ... for now, just print the first element
    2777                 :            :   // NB: limit to 32 args; see PR10750 and c_unparser::visit_print_format.
    2778                 :        217 :   unsigned i, size = 1;
    2779 [ +  + ][ +  - ]:        434 :   for (i=0; i < size && i < 5 && pf->args.size() < 32; ++i)
         [ +  - ][ +  + ]
    2780                 :            :     {
    2781         [ -  + ]:        217 :       if (i > 0)
    2782         [ #  # ]:          0 :         pf->raw_components.append(", ");
    2783 [ +  - ][ +  - ]:        217 :       target_symbol* e2 = new target_symbol(*e);
    2784 [ +  - ][ +  - ]:        217 :       e2->components.push_back (target_symbol::component(e->tok, i));
                 [ +  - ]
    2785         [ +  - ]:        217 :       recurse (&childtype, e2, pf);
    2786                 :            :     }
    2787                 :            :   if (i < size || 1/*XXX until real size is known */)
    2788         [ +  - ]:        217 :     pf->raw_components.append(", ...");
    2789         [ +  - ]:        416 :   pf->raw_components.append("]");
    2790                 :            : }
    2791                 :            : 
    2792                 :            : 
    2793                 :            : void
    2794                 :      14063 : dwarf_pretty_print::recurse_pointer (Dwarf_Die* type, target_symbol* e,
    2795                 :            :                                      print_format* pf, bool top)
    2796                 :            : {
    2797                 :            :   // We chase to top-level pointers, but leave the rest alone
    2798                 :      14063 :   bool void_p = true;
    2799                 :            :   Dwarf_Die pointee;
    2800 [ +  - ][ +  + ]:      14063 :   if (dwarf_attr_die (type, DW_AT_type, &pointee))
    2801                 :            :     {
    2802                 :            :       try
    2803                 :            :         {
    2804         [ +  + ]:      12005 :           dw.resolve_unqualified_inner_typedie (&pointee, &pointee, e);
    2805                 :      11980 :           void_p = false;
    2806                 :            :         }
    2807                 :         25 :       catch (const semantic_error&) {}
    2808                 :            :     }
    2809                 :            : 
    2810         [ +  + ]:      14063 :   if (!void_p)
    2811                 :            :     {
    2812 [ +  - ][ +  + ]:      11980 :       if (print_chars (&pointee, e, pf))
    2813                 :            :         return;
    2814                 :            : 
    2815         [ +  + ]:      11388 :       if (top)
    2816                 :            :         {
    2817         [ +  - ]:       1159 :           recurse (&pointee, e, pf, top);
    2818                 :            :           return;
    2819                 :            :         }
    2820                 :            :     }
    2821                 :            : 
    2822 [ +  - ][ +  - ]:      14088 :   push_deref (pf, "%p", e);
         [ +  - ][ -  + ]
    2823                 :            : }
    2824                 :            : 
    2825                 :            : 
    2826                 :            : void
    2827                 :      13501 : dwarf_pretty_print::recurse_struct (Dwarf_Die* type, target_symbol* e,
    2828                 :            :                                     print_format* pf, bool top)
    2829                 :            : {
    2830 [ +  - ][ +  + ]:      13501 :   if (dwarf_hasattr(type, DW_AT_declaration))
    2831                 :            :     {
    2832         [ +  - ]:        103 :       Dwarf_Die *resolved = dw.declaration_resolve(type);
    2833         [ +  + ]:        103 :       if (!resolved)
    2834                 :            :         {
    2835                 :            :           // could be an error, but for now just stub it
    2836                 :            :           // throw semantic_error ("unresolved " + dwarf_type_name(type), e->tok);
    2837         [ +  - ]:         80 :           pf->raw_components.append("{...}");
    2838                 :      13501 :           return;
    2839                 :            :         }
    2840                 :         23 :       type = resolved;
    2841                 :            :     }
    2842                 :            : 
    2843                 :      13421 :   int count = 0;
    2844         [ +  - ]:      13421 :   pf->raw_components.append("{");
    2845 [ +  + ][ +  + ]:      13421 :   if (top || print_full)
    2846         [ +  - ]:      13318 :     recurse_struct_members (type, e, pf, count);
    2847                 :            :   else
    2848         [ +  - ]:        103 :     pf->raw_components.append("...");
    2849         [ +  - ]:      13501 :   pf->raw_components.append("}");
    2850                 :            : }
    2851                 :            : 
    2852                 :            : 
    2853                 :            : void
    2854                 :      13318 : dwarf_pretty_print::recurse_struct_members (Dwarf_Die* type, target_symbol* e,
    2855                 :            :                                             print_format* pf, int& count)
    2856                 :            : {
    2857                 :            :   /* With inheritance, a subclass may mask member names of parent classes, so
    2858                 :            :    * our search among the inheritance tree must be breadth-first rather than
    2859                 :            :    * depth-first (recursive).  The type die is still our starting point.  When
    2860                 :            :    * we encounter a masked name, just skip it. */
    2861         [ +  - ]:      13318 :   set<string> dupes;
    2862         [ +  - ]:      13318 :   deque<Dwarf_Die> inheritees(1, *type);
    2863 [ +  - ][ +  - ]:      26636 :   for (; !inheritees.empty(); inheritees.pop_front())
                 [ +  + ]
    2864                 :            :     {
    2865                 :            :       Dwarf_Die child, childtype, import;
    2866 [ +  - ][ +  - ]:      13318 :       if (dwarf_child (&inheritees.front(), &child) == 0)
                 [ +  + ]
    2867         [ +  + ]:      45342 :         do
    2868                 :            :           {
    2869                 :      45342 :             target_symbol* e2 = e;
    2870                 :            : 
    2871                 :            :             // skip static members
    2872 [ +  - ][ +  + ]:      45342 :             if (dwarf_hasattr(&child, DW_AT_declaration))
    2873                 :         30 :               continue;
    2874                 :            : 
    2875         [ +  - ]:      45312 :             int tag = dwarf_tag (&child);
    2876                 :            : 
    2877                 :            :             /* Pretend imported units contain members by recursing into
    2878                 :            :                struct_member printing with the same count. */
    2879 [ -  + ][ #  # ]:      45312 :             if (tag == DW_TAG_imported_unit
                 [ -  + ]
    2880         [ #  # ]:          0 :                 && dwarf_attr_die (&child, DW_AT_import, &import))
    2881         [ #  # ]:          0 :               recurse_struct_members (&import, e2, pf, count);
    2882                 :            : 
    2883 [ -  + ][ #  # ]:      45312 :             if (tag != DW_TAG_member && tag != DW_TAG_inheritance)
    2884                 :          0 :               continue;
    2885                 :            : 
    2886         [ +  - ]:      45312 :             dwarf_attr_die (&child, DW_AT_type, &childtype);
    2887                 :            : 
    2888         [ -  + ]:      45312 :             if (tag == DW_TAG_inheritance)
    2889                 :            :               {
    2890         [ #  # ]:          0 :                 inheritees.push_back(childtype);
    2891                 :          0 :                 continue;
    2892                 :            :               }
    2893                 :            : 
    2894         [ +  - ]:      45312 :             int childtag = dwarf_tag (&childtype);
    2895         [ +  - ]:      45312 :             const char *member = dwarf_diename (&child);
    2896                 :            : 
    2897                 :            :             // "_vptr.foo" members are C++ virtual function tables,
    2898                 :            :             // which (generally?) aren't interesting for users.
    2899 [ +  + ][ +  - ]:      45312 :             if (member && startswith(member, "_vptr."))
         [ +  - ][ -  + ]
         [ +  + ][ +  - ]
         [ +  + ][ -  +  
             #  #  #  # ]
    2900                 :          0 :               continue;
    2901                 :            : 
    2902                 :            :             // skip inheritance-masked duplicates
    2903 [ +  + ][ +  - ]:      45312 :             if (member && !dupes.insert(member).second)
         [ +  - ][ -  + ]
         [ +  + ][ +  + ]
         [ +  - ][ +  + ]
           [ -  +  #  #  
             #  #  #  # ]
    2904                 :          0 :               continue;
    2905                 :            : 
    2906         [ +  + ]:      45312 :             if (++count > 1)
    2907         [ +  - ]:      32006 :               pf->raw_components.append(", ");
    2908                 :            : 
    2909                 :            :             // NB: limit to 32 args; see PR10750 and c_unparser::visit_print_format.
    2910         [ +  + ]:      45312 :             if (pf->args.size() >= 32)
    2911                 :            :               {
    2912         [ +  - ]:       1337 :                 pf->raw_components.append("...");
    2913                 :       1337 :                 break;
    2914                 :            :               }
    2915                 :            : 
    2916         [ +  + ]:      43975 :             if (member)
    2917                 :            :               {
    2918         [ +  - ]:      42378 :                 pf->raw_components.append(".");
    2919         [ +  - ]:      42378 :                 pf->raw_components.append(member);
    2920                 :            : 
    2921 [ +  - ][ +  - ]:      42378 :                 e2 = new target_symbol(*e);
    2922 [ +  - ][ +  - ]:      42378 :                 e2->components.push_back (target_symbol::component(e->tok, member));
         [ +  - ][ +  - ]
                 [ +  - ]
    2923                 :            :               }
    2924         [ +  + ]:       1597 :             else if (childtag == DW_TAG_union_type)
    2925         [ +  - ]:       1451 :               pf->raw_components.append("<union>");
    2926         [ +  - ]:        146 :             else if (childtag == DW_TAG_structure_type)
    2927         [ +  - ]:        146 :               pf->raw_components.append("<class>");
    2928         [ #  # ]:          0 :             else if (childtag == DW_TAG_class_type)
    2929         [ #  # ]:          0 :               pf->raw_components.append("<struct>");
    2930         [ +  - ]:      43975 :             pf->raw_components.append("=");
    2931                 :            : 
    2932 [ +  - ][ +  + ]:      43975 :             if (dwarf_hasattr_integrate (&child, DW_AT_bit_offset))
    2933         [ +  - ]:        421 :               recurse_bitfield (&childtype, e2, pf);
    2934                 :            :             else
    2935         [ +  - ]:      43554 :               recurse (&childtype, e2, pf);
    2936                 :            :           }
    2937         [ +  - ]:      44005 :         while (dwarf_siblingof (&child, &child) == 0);
    2938 [ +  - ][ +  - ]:      13318 :     }
    2939                 :      13318 : }
    2940                 :            : 
    2941                 :            : 
    2942                 :            : bool
    2943                 :      12394 : dwarf_pretty_print::print_chars (Dwarf_Die* start_type, target_symbol* e,
    2944                 :            :                                  print_format* pf)
    2945                 :            : {
    2946                 :            :   Dwarf_Die type;
    2947         [ +  - ]:      12394 :   dw.resolve_unqualified_inner_typedie (start_type, &type, e);
    2948                 :            : 
    2949                 :            :   Dwarf_Attribute attr;
    2950                 :      12394 :   Dwarf_Word encoding = (Dwarf_Word) -1;
    2951                 :            :   dwarf_formudata (dwarf_attr_integrate (&type, DW_AT_encoding, &attr),
    2952 [ +  - ][ +  - ]:      12394 :                    &encoding);
    2953         [ +  + ]:      12394 :   switch (encoding)
    2954                 :            :     {
    2955                 :            :     case DW_ATE_UTF:
    2956                 :            :     case DW_ATE_signed_char:
    2957                 :            :     case DW_ATE_unsigned_char:
    2958                 :        789 :       break;
    2959                 :            :     default:
    2960                 :      11605 :       return false;
    2961                 :            :     }
    2962                 :            : 
    2963 [ +  + ][ +  - ]:        789 :   string function = userspace_p ? "user_string2" : "kernel_string2";
    2964                 :        789 :   Dwarf_Word size = (Dwarf_Word) -1;
    2965 [ +  - ][ +  - ]:        789 :   dwarf_formudata (dwarf_attr_integrate (&type, DW_AT_byte_size, &attr), &size);
    2966   [ +  +  +  - ]:        789 :   switch (size)
    2967                 :            :     {
    2968                 :            :     case 1:
    2969                 :        787 :       break;
    2970                 :            :     case 2:
    2971         [ +  - ]:          1 :       function += "_utf16";
    2972                 :          1 :       break;
    2973                 :            :     case 4:
    2974         [ +  - ]:          1 :       function += "_utf32";
    2975                 :          1 :       break;
    2976                 :            :     default:
    2977                 :          0 :       return false;
    2978                 :            :     }
    2979                 :            : 
    2980 [ +  - ][ +  - ]:        789 :   if (push_deref (pf, "\"%s\"", e))
         [ +  - ][ +  - ]
    2981                 :            :     {
    2982                 :            :       // steal the last arg for a string access
    2983 [ +  - ][ -  + ]:        789 :       assert (!pf->args.empty());
    2984 [ +  - ][ +  - ]:        789 :       functioncall* fcall = new functioncall;
    2985                 :        789 :       fcall->tok = e->tok;
    2986         [ +  - ]:        789 :       fcall->function = function;
    2987 [ +  - ][ +  - ]:        789 :       fcall->args.push_back (pf->args.back());
    2988 [ +  - ][ +  - ]:        789 :       expression *err_msg = new literal_string ("<unknown>");
         [ +  - ][ +  - ]
    2989                 :        789 :       err_msg->tok = e->tok;
    2990         [ +  - ]:        789 :       fcall->args.push_back (err_msg);
    2991         [ +  - ]:        789 :       pf->args.back() = fcall;
    2992                 :            :     }
    2993         [ +  - ]:      12394 :   return true;
    2994                 :            : }
    2995                 :            : 
    2996                 :            : // PR10601: adapt to kernel-vs-userspace loc2c-runtime
    2997 [ +  - ][ +  - ]:       2414 : static const string EMBEDDED_FETCH_DEREF_KERNEL = string("\n")
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    2998                 :            :   + "#define fetch_register k_fetch_register\n"
    2999                 :            :   + "#define store_register k_store_register\n"
    3000                 :            :   + "#define deref kderef\n"
    3001                 :            :   + "#define store_deref store_kderef\n";
    3002                 :            : 
    3003 [ +  - ][ +  - ]:       2414 : static const string EMBEDDED_FETCH_DEREF_USER = string("\n")
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    3004                 :            :   + "#define fetch_register u_fetch_register\n"
    3005                 :            :   + "#define store_register u_store_register\n"
    3006                 :            :   + "#define deref uderef\n"
    3007                 :            :   + "#define store_deref store_uderef\n";
    3008                 :            : 
    3009                 :            : #define EMBEDDED_FETCH_DEREF(U) \
    3010                 :            :   (U ? EMBEDDED_FETCH_DEREF_USER : EMBEDDED_FETCH_DEREF_KERNEL)
    3011                 :            : 
    3012 [ +  - ][ +  - ]:       2414 : static const string EMBEDDED_FETCH_DEREF_DONE = string("\n")
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    3013                 :            :   + "#undef fetch_register\n"
    3014                 :            :   + "#undef store_register\n"
    3015                 :            :   + "#undef deref\n"
    3016                 :            :   + "#undef store_deref\n";
    3017                 :            : 
    3018                 :            : static functioncall*
    3019                 :     183124 : synthetic_embedded_deref_call(systemtap_session& session,
    3020                 :            :                               const string& function_name,
    3021                 :            :                               const string& function_code,
    3022                 :            :                               exp_type function_type,
    3023                 :            :                               bool userspace_p,
    3024                 :            :                               bool lvalue_p,
    3025                 :            :                               target_symbol* e,
    3026                 :            :                               expression* pointer=NULL)
    3027                 :            : {
    3028                 :            :   // Synthesize a functiondecl for the given embedded code string.
    3029         [ +  - ]:     183124 :   functiondecl *fdecl = new functiondecl;
    3030                 :     183124 :   fdecl->synthetic = true;
    3031                 :     183124 :   fdecl->tok = e->tok;
    3032                 :     183124 :   fdecl->name = function_name;
    3033                 :     183124 :   fdecl->type = function_type;
    3034                 :            : 
    3035         [ +  - ]:     183124 :   embeddedcode *ec = new embeddedcode;
    3036                 :     183124 :   ec->tok = e->tok;
    3037                 :     183124 :   ec->code += "/* unprivileged */";
    3038         [ +  + ]:     183124 :   if (! lvalue_p)
    3039                 :     183106 :     ec->code += "/* pure */";
    3040         [ +  + ]:     183124 :   ec->code += EMBEDDED_FETCH_DEREF(userspace_p);
    3041                 :     183124 :   ec->code += function_code;
    3042                 :     183124 :   ec->code += EMBEDDED_FETCH_DEREF_DONE;
    3043                 :     183124 :   fdecl->body = ec;
    3044                 :            : 
    3045                 :            :   // Synthesize a functioncall.
    3046         [ +  - ]:     183124 :   functioncall* fcall = new functioncall;
    3047                 :     183124 :   fcall->tok = e->tok;
    3048                 :     183124 :   fcall->function = fdecl->name;
    3049                 :     183124 :   fcall->type = fdecl->type;
    3050                 :            : 
    3051                 :            :   // If this code snippet uses a precomputed pointer,
    3052                 :            :   // pass that as the first argument.
    3053         [ +  + ]:     183124 :   if (pointer)
    3054                 :            :     {
    3055 [ +  - ][ +  - ]:      16112 :       vardecl *v = new vardecl;
    3056                 :      16112 :       v->type = pe_long;
    3057         [ +  - ]:      16112 :       v->name = "pointer";
    3058                 :      16112 :       v->tok = e->tok;
    3059         [ +  - ]:      16112 :       fdecl->formal_args.push_back(v);
    3060         [ +  - ]:      16112 :       fcall->args.push_back(pointer);
    3061                 :            :     }
    3062                 :            : 
    3063                 :            :   // Any non-literal indexes need to be passed as arguments too.
    3064         [ +  + ]:     257079 :   for (unsigned i = 0; i < e->components.size(); ++i)
    3065         [ +  + ]:      73955 :     if (e->components[i].type == target_symbol::comp_expression_array_index)
    3066                 :            :       {
    3067 [ +  - ][ +  - ]:         42 :         vardecl *v = new vardecl;
    3068                 :         42 :         v->type = pe_long;
    3069 [ +  - ][ +  - ]:         42 :         v->name = "index" + lex_cast(i);
         [ +  - ][ +  - ]
                 [ +  - ]
    3070                 :         42 :         v->tok = e->tok;
    3071         [ +  - ]:         42 :         fdecl->formal_args.push_back(v);
    3072         [ +  - ]:         42 :         fcall->args.push_back(e->components[i].expr_index);
    3073                 :            :       }
    3074                 :            : 
    3075                 :            :   // If this code snippet is assigning to an lvalue,
    3076                 :            :   // add a final argument for the rvalue.
    3077         [ +  + ]:     183124 :   if (lvalue_p)
    3078                 :            :     {
    3079                 :            :       // Modify the fdecl so it carries a single pe_long formal
    3080                 :            :       // argument called "value".
    3081                 :            : 
    3082                 :            :       // FIXME: For the time being we only support setting target
    3083                 :            :       // variables which have base types; these are 'pe_long' in
    3084                 :            :       // stap's type vocabulary.  Strings and pointers might be
    3085                 :            :       // reasonable, some day, but not today.
    3086                 :            : 
    3087 [ +  - ][ +  - ]:         18 :       vardecl *v = new vardecl;
    3088                 :         18 :       v->type = pe_long;
    3089         [ +  - ]:         18 :       v->name = "value";
    3090                 :         18 :       v->tok = e->tok;
    3091         [ +  - ]:         18 :       fdecl->formal_args.push_back(v);
    3092                 :            :       // NB: We don't know the value for fcall argument yet.
    3093                 :            :       // (see target_symbol_setter_functioncalls)
    3094                 :            :     }
    3095                 :            : 
    3096                 :            :   // Add the synthesized decl to the session, and return the call.
    3097                 :     183124 :   fdecl->join (session);
    3098                 :     183124 :   return fcall;
    3099                 :            : }
    3100                 :            : 
    3101                 :            : expression*
    3102                 :      32941 : dwarf_pretty_print::deref (target_symbol* e)
    3103                 :            : {
    3104                 :            :   static unsigned tick = 0;
    3105                 :            : 
    3106         [ +  + ]:      32941 :   if (!deref_p)
    3107                 :            :     {
    3108 [ +  - ][ +  - ]:        442 :       assert (pointer && e->components.empty());
                 [ -  + ]
    3109                 :        442 :       return pointer;
    3110                 :            :     }
    3111                 :            : 
    3112                 :      32499 :   bool lvalue_p = false;
    3113 [ +  - ][ +  - ]:      32499 :   string name = "_dwarf_pretty_print_deref_" + lex_cast(tick++);
                 [ +  - ]
    3114                 :            : 
    3115         [ +  - ]:      32499 :   string code;
    3116                 :      32499 :   exp_type type = pe_long;
    3117         [ +  + ]:      32499 :   if (pointer)
    3118 [ +  - ][ +  - ]:       8596 :     code = dw.literal_stmt_for_pointer (&pointer_type, e, false, type);
                 [ +  - ]
    3119 [ +  - ][ +  - ]:      23903 :   else if (!local.empty())
    3120 [ +  + ][ +  - ]:      23903 :     code = dw.literal_stmt_for_local (scopes, pc, local, e, false, type);
                 [ +  - ]
    3121                 :            :   else
    3122 [ #  # ][ #  # ]:          0 :     code = dw.literal_stmt_for_return (&scopes[0], pc, e, false, type);
                 [ #  # ]
    3123                 :            : 
    3124                 :            :   return synthetic_embedded_deref_call(dw.sess, name, code, type,
    3125 [ +  - ][ +  - ]:      32941 :                                        userspace_p, lvalue_p, e, pointer);
                 [ +  - ]
    3126                 :            : }
    3127                 :            : 
    3128                 :            : 
    3129                 :            : bool
    3130                 :      32941 : dwarf_pretty_print::push_deref (print_format* pf, const string& fmt,
    3131                 :            :                                 target_symbol* e)
    3132                 :            : {
    3133                 :      32941 :   expression* e2 = NULL;
    3134                 :            :   try
    3135                 :            :     {
    3136         [ +  + ]:      32941 :       e2 = deref (e);
    3137                 :            :     }
    3138         [ -  + ]:        298 :   catch (const semantic_error&)
    3139                 :            :     {
    3140         [ -  + ]:        149 :       pf->raw_components.append ("?");
    3141                 :        149 :       return false;
    3142                 :            :     }
    3143         [ +  - ]:      32792 :   pf->raw_components.append (fmt);
    3144         [ +  - ]:      32792 :   pf->args.push_back (e2);
    3145                 :      32941 :   return true;
    3146                 :            : }
    3147                 :            : 
    3148                 :            : 
    3149                 :            : void
    3150                 :       1554 : dwarf_var_expanding_visitor::visit_target_symbol_saved_return (target_symbol* e)
    3151                 :            : {
    3152                 :            :   // Get the full name of the target symbol.
    3153         [ +  - ]:       1554 :   stringstream ts_name_stream;
    3154         [ +  - ]:       1554 :   e->print(ts_name_stream);
    3155         [ +  - ]:       1554 :   string ts_name = ts_name_stream.str();
    3156                 :            : 
    3157                 :            :   // Check and make sure we haven't already seen this target
    3158                 :            :   // variable in this return probe.  If we have, just return our
    3159                 :            :   // last replacement.
    3160         [ +  - ]:       1554 :   map<string, expression *>::iterator i = return_ts_map.find(ts_name);
    3161 [ +  - ][ +  + ]:       1554 :   if (i != return_ts_map.end())
    3162                 :            :     {
    3163 [ +  - ][ +  - ]:        420 :       provide (i->second);
    3164                 :            :       return;
    3165                 :            :     }
    3166                 :            : 
    3167                 :            :   // Attempt the expansion directly first, so if there's a problem with the
    3168                 :            :   // variable we won't have a bogus entry probe lying around.  Like in
    3169                 :            :   // saveargs(), we pretend for a moment that we're not in a .return.
    3170                 :       1134 :   bool saved_has_return = q.has_return;
    3171                 :       1134 :   q.has_return = false;
    3172                 :       1134 :   expression *repl = e;
    3173         [ +  - ]:       1134 :   replace (repl);
    3174                 :       1134 :   q.has_return = saved_has_return;
    3175         [ -  + ]:       1134 :   target_symbol* n = dynamic_cast<target_symbol*>(repl);
    3176 [ +  + ][ +  - ]:       1134 :   if (n && n->saved_conversion_error)
    3177                 :            :     {
    3178         [ +  - ]:         44 :       provide (repl);
    3179                 :            :       return;
    3180                 :            :     }
    3181                 :            : 
    3182                 :            :   expression *exp;
    3183   [ +  -  +  - ]:       2180 :   if (!q.has_process &&
                 [ +  - ]
    3184         [ +  - ]:       1090 :       strverscmp(q.sess.kernel_base_release.c_str(), "2.6.25") >= 0)
    3185         [ +  - ]:       1090 :     exp = gen_kretprobe_saved_return(repl);
    3186                 :            :   else
    3187 [ #  # ][ #  # ]:          0 :     exp = gen_mapped_saved_return(repl, e->sym_name());
                 [ #  # ]
    3188                 :            : 
    3189                 :            :   // Provide the variable to our parent so it can be used as a
    3190                 :            :   // substitute for the target symbol.
    3191         [ +  - ]:       1090 :   provide (exp);
    3192                 :            : 
    3193                 :            :   // Remember this replacement since we might be able to reuse
    3194                 :            :   // it later if the same return probe references this target
    3195                 :            :   // symbol again.
    3196 [ +  - ][ +  - ]:       1554 :   return_ts_map[ts_name] = exp;
         [ +  + ][ +  - ]
                 [ +  + ]
    3197                 :            : }
    3198                 :            : 
    3199                 :            : static expression*
    3200                 :       1093 : gen_mapped_saved_return(systemtap_session &sess, expression* e,
    3201                 :            :                         const string& name,
    3202                 :            :                         block *& add_block, bool& add_block_tid,
    3203                 :            :                         block *& add_call_probe, bool& add_call_probe_tid)
    3204                 :            : {
    3205                 :            :   static unsigned tick = 0;
    3206                 :            : 
    3207                 :            :   // We've got to do several things here to handle target
    3208                 :            :   // variables in return probes.
    3209                 :            : 
    3210                 :            :   // (1) Synthesize two global arrays.  One is the cache of the
    3211                 :            :   // target variable and the other contains a thread specific
    3212                 :            :   // nesting level counter.  The arrays will look like
    3213                 :            :   // this:
    3214                 :            :   //
    3215                 :            :   //   _entry_tvar_{name}_{num}
    3216                 :            :   //   _entry_tvar_{name}_{num}_ctr
    3217                 :            : 
    3218                 :            :   string aname = (string("_entry_tvar_")
    3219                 :            :                   + name
    3220 [ +  - ][ +  - ]:       1093 :                   + "_" + lex_cast(tick++));
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    3221 [ +  - ][ +  - ]:       1093 :   vardecl* vd = new vardecl;
    3222         [ +  - ]:       1093 :   vd->name = aname;
    3223                 :       1093 :   vd->tok = e->tok;
    3224         [ +  - ]:       1093 :   sess.globals.push_back (vd);
    3225                 :            : 
    3226         [ +  - ]:       1093 :   string ctrname = aname + "_ctr";
    3227 [ +  - ][ +  - ]:       1093 :   vd = new vardecl;
    3228         [ +  - ]:       1093 :   vd->name = ctrname;
    3229                 :       1093 :   vd->tok = e->tok;
    3230         [ +  - ]:       1093 :   sess.globals.push_back (vd);
    3231                 :            : 
    3232                 :            :   // (2) Create a new code block we're going to insert at the
    3233                 :            :   // beginning of this probe to get the cached value into a
    3234                 :            :   // temporary variable.  We'll replace the target variable
    3235                 :            :   // reference with the temporary variable reference.  The code
    3236                 :            :   // will look like this:
    3237                 :            :   //
    3238                 :            :   //   _entry_tvar_tid = tid()
    3239                 :            :   //   _entry_tvar_{name}_{num}_tmp
    3240                 :            :   //       = _entry_tvar_{name}_{num}[_entry_tvar_tid,
    3241                 :            :   //                    _entry_tvar_{name}_{num}_ctr[_entry_tvar_tid]]
    3242                 :            :   //   delete _entry_tvar_{name}_{num}[_entry_tvar_tid,
    3243                 :            :   //                    _entry_tvar_{name}_{num}_ctr[_entry_tvar_tid]--]
    3244                 :            :   //   if (! _entry_tvar_{name}_{num}_ctr[_entry_tvar_tid])
    3245                 :            :   //       delete _entry_tvar_{name}_{num}_ctr[_entry_tvar_tid]
    3246                 :            : 
    3247                 :            :   // (2a) Synthesize the tid temporary expression, which will look
    3248                 :            :   // like this:
    3249                 :            :   //
    3250                 :            :   //   _entry_tvar_tid = tid()
    3251 [ +  - ][ +  - ]:       1093 :   symbol* tidsym = new symbol;
    3252 [ +  - ][ +  - ]:       1093 :   tidsym->name = string("_entry_tvar_tid");
                 [ +  - ]
    3253                 :       1093 :   tidsym->tok = e->tok;
    3254                 :            : 
    3255         [ +  + ]:       1093 :   if (add_block == NULL)
    3256                 :            :     {
    3257 [ +  - ][ +  - ]:        949 :       add_block = new block;
    3258                 :        949 :       add_block->tok = e->tok;
    3259                 :            :     }
    3260                 :            : 
    3261         [ +  + ]:       1093 :   if (!add_block_tid)
    3262                 :            :     {
    3263                 :            :       // Synthesize a functioncall to grab the thread id.
    3264 [ +  - ][ +  - ]:        949 :       functioncall* fc = new functioncall;
    3265                 :        949 :       fc->tok = e->tok;
    3266 [ +  - ][ +  - ]:        949 :       fc->function = string("tid");
                 [ +  - ]
    3267                 :            : 
    3268                 :            :       // Assign the tid to '_entry_tvar_tid'.
    3269 [ +  - ][ +  - ]:        949 :       assignment* a = new assignment;
    3270                 :        949 :       a->tok = e->tok;
    3271         [ +  - ]:        949 :       a->op = "=";
    3272                 :        949 :       a->left = tidsym;
    3273                 :        949 :       a->right = fc;
    3274                 :            : 
    3275 [ +  - ][ +  - ]:        949 :       expr_statement* es = new expr_statement;
    3276                 :        949 :       es->tok = e->tok;
    3277                 :        949 :       es->value = a;
    3278         [ +  - ]:        949 :       add_block->statements.push_back (es);
    3279                 :        949 :       add_block_tid = true;
    3280                 :            :     }
    3281                 :            : 
    3282                 :            :   // (2b) Synthesize an array reference and assign it to a
    3283                 :            :   // temporary variable (that we'll use as replacement for the
    3284                 :            :   // target variable reference).  It will look like this:
    3285                 :            :   //
    3286                 :            :   //   _entry_tvar_{name}_{num}_tmp
    3287                 :            :   //       = _entry_tvar_{name}_{num}[_entry_tvar_tid,
    3288                 :            :   //                    _entry_tvar_{name}_{num}_ctr[_entry_tvar_tid]]
    3289                 :            : 
    3290 [ +  - ][ +  - ]:       1093 :   arrayindex* ai_tvar_base = new arrayindex;
    3291                 :       1093 :   ai_tvar_base->tok = e->tok;
    3292                 :            : 
    3293 [ +  - ][ +  - ]:       1093 :   symbol* sym = new symbol;
    3294         [ +  - ]:       1093 :   sym->name = aname;
    3295                 :       1093 :   sym->tok = e->tok;
    3296                 :       1093 :   ai_tvar_base->base = sym;
    3297                 :            : 
    3298         [ +  - ]:       1093 :   ai_tvar_base->indexes.push_back(tidsym);
    3299                 :            : 
    3300                 :            :   // We need to create a copy of the array index in its current
    3301                 :            :   // state so we can have 2 variants of it (the original and one
    3302                 :            :   // that post-decrements the second index).
    3303 [ +  - ][ +  - ]:       1093 :   arrayindex* ai_tvar = new arrayindex;
    3304 [ +  - ][ +  - ]:       1093 :   arrayindex* ai_tvar_postdec = new arrayindex;
    3305         [ +  - ]:       1093 :   *ai_tvar = *ai_tvar_base;
    3306         [ +  - ]:       1093 :   *ai_tvar_postdec = *ai_tvar_base;
    3307                 :            : 
    3308                 :            :   // Synthesize the
    3309                 :            :   // "_entry_tvar_{name}_{num}_ctr[_entry_tvar_tid]" used as the
    3310                 :            :   // second index into the array.
    3311 [ +  - ][ +  - ]:       1093 :   arrayindex* ai_ctr = new arrayindex;
    3312                 :       1093 :   ai_ctr->tok = e->tok;
    3313                 :            : 
    3314 [ +  - ][ +  - ]:       1093 :   sym = new symbol;
    3315         [ +  - ]:       1093 :   sym->name = ctrname;
    3316                 :       1093 :   sym->tok = e->tok;
    3317                 :       1093 :   ai_ctr->base = sym;
    3318         [ +  - ]:       1093 :   ai_ctr->indexes.push_back(tidsym);
    3319         [ +  - ]:       1093 :   ai_tvar->indexes.push_back(ai_ctr);
    3320                 :            : 
    3321 [ +  - ][ +  - ]:       1093 :   symbol* tmpsym = new symbol;
    3322 [ +  - ][ +  - ]:       1093 :   tmpsym->name = aname + "_tmp";
                 [ +  - ]
    3323                 :       1093 :   tmpsym->tok = e->tok;
    3324                 :            : 
    3325 [ +  - ][ +  - ]:       1093 :   assignment* a = new assignment;
    3326                 :       1093 :   a->tok = e->tok;
    3327         [ +  - ]:       1093 :   a->op = "=";
    3328                 :       1093 :   a->left = tmpsym;
    3329                 :       1093 :   a->right = ai_tvar;
    3330                 :            : 
    3331 [ +  - ][ +  - ]:       1093 :   expr_statement* es = new expr_statement;
    3332                 :       1093 :   es->tok = e->tok;
    3333                 :       1093 :   es->value = a;
    3334                 :            : 
    3335         [ +  - ]:       1093 :   add_block->statements.push_back (es);
    3336                 :            : 
    3337                 :            :   // (2c) Add a post-decrement to the second array index and
    3338                 :            :   // delete the array value.  It will look like this:
    3339                 :            :   //
    3340                 :            :   //   delete _entry_tvar_{name}_{num}[_entry_tvar_tid,
    3341                 :            :   //                    _entry_tvar_{name}_{num}_ctr[_entry_tvar_tid]--]
    3342                 :            : 
    3343 [ +  - ][ +  - ]:       1093 :   post_crement* pc = new post_crement;
    3344                 :       1093 :   pc->tok = e->tok;
    3345         [ +  - ]:       1093 :   pc->op = "--";
    3346                 :       1093 :   pc->operand = ai_ctr;
    3347         [ +  - ]:       1093 :   ai_tvar_postdec->indexes.push_back(pc);
    3348                 :            : 
    3349 [ +  - ][ +  - ]:       1093 :   delete_statement* ds = new delete_statement;
    3350                 :       1093 :   ds->tok = e->tok;
    3351                 :       1093 :   ds->value = ai_tvar_postdec;
    3352                 :            : 
    3353         [ +  - ]:       1093 :   add_block->statements.push_back (ds);
    3354                 :            : 
    3355                 :            :   // (2d) Delete the counter value if it is 0.  It will look like
    3356                 :            :   // this:
    3357                 :            :   //   if (! _entry_tvar_{name}_{num}_ctr[_entry_tvar_tid])
    3358                 :            :   //       delete _entry_tvar_{name}_{num}_ctr[_entry_tvar_tid]
    3359                 :            : 
    3360 [ +  - ][ +  - ]:       1093 :   ds = new delete_statement;
    3361                 :       1093 :   ds->tok = e->tok;
    3362                 :       1093 :   ds->value = ai_ctr;
    3363                 :            : 
    3364 [ +  - ][ +  - ]:       1093 :   unary_expression *ue = new unary_expression;
    3365                 :       1093 :   ue->tok = e->tok;
    3366         [ +  - ]:       1093 :   ue->op = "!";
    3367                 :       1093 :   ue->operand = ai_ctr;
    3368                 :            : 
    3369 [ +  - ][ +  - ]:       1093 :   if_statement *ifs = new if_statement;
    3370                 :       1093 :   ifs->tok = e->tok;
    3371                 :       1093 :   ifs->condition = ue;
    3372                 :       1093 :   ifs->thenblock = ds;
    3373                 :       1093 :   ifs->elseblock = NULL;
    3374                 :            : 
    3375         [ +  - ]:       1093 :   add_block->statements.push_back (ifs);
    3376                 :            : 
    3377                 :            :   // (3) We need an entry probe that saves the value for us in the
    3378                 :            :   // global array we created.  Create the entry probe, which will
    3379                 :            :   // look like this:
    3380                 :            :   //
    3381                 :            :   //   probe kernel.function("{function}").call {
    3382                 :            :   //     _entry_tvar_tid = tid()
    3383                 :            :   //     _entry_tvar_{name}_{num}[_entry_tvar_tid,
    3384                 :            :   //                       ++_entry_tvar_{name}_{num}_ctr[_entry_tvar_tid]]
    3385                 :            :   //       = ${param}
    3386                 :            :   //   }
    3387                 :            : 
    3388         [ +  + ]:       1093 :   if (add_call_probe == NULL)
    3389                 :            :     {
    3390 [ +  - ][ +  - ]:        939 :       add_call_probe = new block;
    3391                 :        939 :       add_call_probe->tok = e->tok;
    3392                 :            :     }
    3393                 :            : 
    3394         [ +  + ]:       1093 :   if (!add_call_probe_tid)
    3395                 :            :     {
    3396                 :            :       // Synthesize a functioncall to grab the thread id.
    3397 [ +  - ][ +  - ]:        949 :       functioncall* fc = new functioncall;
    3398                 :        949 :       fc->tok = e->tok;
    3399 [ +  - ][ +  - ]:        949 :       fc->function = string("tid");
                 [ +  - ]
    3400                 :            : 
    3401                 :            :       // Assign the tid to '_entry_tvar_tid'.
    3402 [ +  - ][ +  - ]:        949 :       assignment* a = new assignment;
    3403                 :        949 :       a->tok = e->tok;
    3404         [ +  - ]:        949 :       a->op = "=";
    3405                 :        949 :       a->left = tidsym;
    3406                 :        949 :       a->right = fc;
    3407                 :            : 
    3408 [ +  - ][ +  - ]:        949 :       expr_statement* es = new expr_statement;
    3409                 :        949 :       es->tok = e->tok;
    3410                 :        949 :       es->value = a;
    3411 [ +  - ][ +  - ]:        949 :       add_call_probe = new block(add_call_probe, es);
    3412                 :        949 :       add_call_probe_tid = true;
    3413                 :            :     }
    3414                 :            : 
    3415                 :            :   // Save the value, like this:
    3416                 :            :   //     _entry_tvar_{name}_{num}[_entry_tvar_tid,
    3417                 :            :   //                       ++_entry_tvar_{name}_{num}_ctr[_entry_tvar_tid]]
    3418                 :            :   //       = ${param}
    3419 [ +  - ][ +  - ]:       1093 :   arrayindex* ai_tvar_preinc = new arrayindex;
    3420         [ +  - ]:       1093 :   *ai_tvar_preinc = *ai_tvar_base;
    3421                 :            : 
    3422 [ +  - ][ +  - ]:       1093 :   pre_crement* preinc = new pre_crement;
    3423                 :       1093 :   preinc->tok = e->tok;
    3424         [ +  - ]:       1093 :   preinc->op = "++";
    3425                 :       1093 :   preinc->operand = ai_ctr;
    3426         [ +  - ]:       1093 :   ai_tvar_preinc->indexes.push_back(preinc);
    3427                 :            : 
    3428 [ +  - ][ +  - ]:       1093 :   a = new assignment;
    3429                 :       1093 :   a->tok = e->tok;
    3430         [ +  - ]:       1093 :   a->op = "=";
    3431                 :       1093 :   a->left = ai_tvar_preinc;
    3432                 :       1093 :   a->right = e;
    3433                 :            : 
    3434 [ +  - ][ +  - ]:       1093 :   es = new expr_statement;
    3435                 :       1093 :   es->tok = e->tok;
    3436                 :       1093 :   es->value = a;
    3437                 :            : 
    3438 [ +  - ][ +  - ]:       1093 :   add_call_probe = new block(add_call_probe, es);
    3439                 :            : 
    3440                 :            :   // (4) Provide the '_entry_tvar_{name}_{num}_tmp' variable to
    3441                 :            :   // our parent so it can be used as a substitute for the target
    3442                 :            :   // symbol.
    3443 [ +  - ][ +  - ]:       1093 :   delete ai_tvar_base;
    3444 [ +  - ][ +  - ]:       1093 :   return tmpsym;
    3445                 :            : }
    3446                 :            : 
    3447                 :            : 
    3448                 :            : expression*
    3449                 :        695 : dwarf_var_expanding_visitor::gen_mapped_saved_return(expression* e,
    3450                 :            :                                                      const string& name)
    3451                 :            : {
    3452                 :            :     return ::gen_mapped_saved_return(q.sess, e, name, add_block,
    3453                 :            :                                      add_block_tid, add_call_probe,
    3454                 :        695 :                                      add_call_probe_tid);
    3455                 :            : }
    3456                 :            : 
    3457                 :            : 
    3458                 :            : expression*
    3459                 :       1090 : dwarf_var_expanding_visitor::gen_kretprobe_saved_return(expression* e)
    3460                 :            : {
    3461                 :            :   // The code for this is simple.
    3462                 :            :   //
    3463                 :            :   // .call:
    3464                 :            :   //   _set_kretprobe_long(index, $value)
    3465                 :            :   //
    3466                 :            :   // .return:
    3467                 :            :   //   _get_kretprobe_long(index)
    3468                 :            :   //
    3469                 :            :   // (or s/long/string/ for things like $$parms)
    3470                 :            : 
    3471                 :            :   unsigned index;
    3472 [ +  - ][ +  - ]:       1090 :   string setfn, getfn;
    3473                 :            : 
    3474                 :            :   // We need the caller to predetermine the type of the expression!
    3475      [ +  +  - ]:       1090 :   switch (e->type)
    3476                 :            :     {
    3477                 :            :     case pe_string:
    3478                 :          4 :       index = saved_strings++;
    3479         [ +  - ]:          4 :       setfn = "_set_kretprobe_string";
    3480         [ +  - ]:          4 :       getfn = "_get_kretprobe_string";
    3481                 :          4 :       break;
    3482                 :            :     case pe_long:
    3483                 :       1086 :       index = saved_longs++;
    3484         [ +  - ]:       1086 :       setfn = "_set_kretprobe_long";
    3485         [ +  - ]:       1086 :       getfn = "_get_kretprobe_long";
    3486                 :       1086 :       break;
    3487                 :            :     default:
    3488 [ #  # ][ #  # ]:          0 :       throw semantic_error(_("unknown type to save in kretprobe"), e->tok);
    3489                 :            :     }
    3490                 :            : 
    3491                 :            :   // Create the entry code
    3492                 :            :   //   _set_kretprobe_{long|string}(index, $value)
    3493                 :            : 
    3494         [ +  + ]:       1090 :   if (add_call_probe == NULL)
    3495                 :            :     {
    3496 [ +  - ][ +  - ]:        602 :       add_call_probe = new block;
    3497                 :        602 :       add_call_probe->tok = e->tok;
    3498                 :            :     }
    3499                 :            : 
    3500 [ +  - ][ +  - ]:       1090 :   functioncall* set_fc = new functioncall;
    3501                 :       1090 :   set_fc->tok = e->tok;
    3502         [ +  - ]:       1090 :   set_fc->function = setfn;
    3503 [ +  - ][ +  - ]:       1090 :   set_fc->args.push_back(new literal_number(index));
                 [ +  - ]
    3504         [ +  - ]:       1090 :   set_fc->args.back()->tok = e->tok;
    3505         [ +  - ]:       1090 :   set_fc->args.push_back(e);
    3506                 :            : 
    3507 [ +  - ][ +  - ]:       1090 :   expr_statement* set_es = new expr_statement;
    3508                 :       1090 :   set_es->tok = e->tok;
    3509                 :       1090 :   set_es->value = set_fc;
    3510                 :            : 
    3511         [ +  - ]:       1090 :   add_call_probe->statements.push_back(set_es);
    3512                 :            : 
    3513                 :            :   // Create the return code
    3514                 :            :   //   _get_kretprobe_{long|string}(index)
    3515                 :            : 
    3516 [ +  - ][ +  - ]:       1090 :   functioncall* get_fc = new functioncall;
    3517                 :       1090 :   get_fc->tok = e->tok;
    3518         [ +  - ]:       1090 :   get_fc->function = getfn;
    3519 [ +  - ][ +  - ]:       1090 :   get_fc->args.push_back(new literal_number(index));
                 [ +  - ]
    3520         [ +  - ]:       1090 :   get_fc->args.back()->tok = e->tok;
    3521                 :            : 
    3522 [ +  - ][ +  - ]:       1090 :   return get_fc;
    3523                 :            : }
    3524                 :            : 
    3525                 :            : 
    3526                 :            : void
    3527                 :      21248 : dwarf_var_expanding_visitor::visit_target_symbol_context (target_symbol* e)
    3528                 :            : {
    3529         [ +  - ]:      21248 :   if (null_die(scope_die))
    3530                 :      21248 :     return;
    3531                 :            : 
    3532 [ +  - ][ +  - ]:      21248 :   target_symbol *tsym = new target_symbol(*e);
    3533                 :            : 
    3534         [ +  - ]:      21248 :   bool pretty = (!e->components.empty() &&
    3535 [ +  + ][ +  - ]:      21248 :                  e->components[0].type == target_symbol::comp_pretty_print);
    3536 [ +  + ][ +  - ]:      21248 :   string format = pretty ? "=%s" : "=%#x";
    3537                 :            : 
    3538                 :            :   // Convert $$parms to sprintf of a list of parms and active local vars
    3539                 :            :   // which we recursively evaluate
    3540                 :            : 
    3541                 :            :   // NB: we synthesize a new token here rather than reusing
    3542                 :            :   // e->tok, because print_format::print likes to use
    3543                 :            :   // its tok->content.
    3544 [ +  - ][ +  - ]:      21248 :   token* pf_tok = new token(*e->tok);
    3545                 :      21248 :   pf_tok->type = tok_identifier;
    3546         [ +  - ]:      21248 :   pf_tok->content = "sprintf";
    3547                 :            : 
    3548         [ +  - ]:      21248 :   print_format* pf = print_format::create(pf_tok);
    3549                 :            : 
    3550 [ +  + ][ +  - ]:      21248 :   if (q.has_return && (e->name == "$$return"))
         [ +  - ][ +  + ]
    3551                 :            :     {
    3552         [ +  - ]:       1213 :       tsym->name = "$return";
    3553                 :            : 
    3554                 :            :       // Ignore any variable that isn't accessible.
    3555                 :       1213 :       tsym->saved_conversion_error = 0;
    3556                 :       1213 :       expression *texp = tsym;
    3557         [ +  - ]:       1213 :       replace (texp); // NB: throws nothing ...
    3558         [ +  + ]:       1213 :       if (tsym->saved_conversion_error) // ... but this is how we know it happened.
    3559                 :            :         {
    3560                 :            : 
    3561                 :            :         }
    3562                 :            :       else
    3563                 :            :         {
    3564         [ +  - ]:       1009 :           pf->raw_components += "return";
    3565         [ +  - ]:       1009 :           pf->raw_components += format;
    3566         [ +  - ]:       1213 :           pf->args.push_back(texp);
    3567                 :            :         }
    3568                 :            :     }
    3569                 :            :   else
    3570                 :            :     {
    3571                 :            :       // non-.return probe: support $$parms, $$vars, $$locals
    3572                 :      20035 :       bool first = true;
    3573                 :            :       Dwarf_Die result;
    3574         [ +  - ]:      20035 :       vector<Dwarf_Die> scopes = q.dw.getscopes(scope_die);
    3575         [ +  - ]:      40078 :       for (unsigned i = 0; i < scopes.size(); ++i)
    3576                 :            :         {
    3577 [ +  - ][ +  + ]:      40078 :           if (dwarf_tag(&scopes[i]) == DW_TAG_compile_unit)
    3578                 :      20035 :             break; // we don't want file-level variables
    3579 [ +  - ][ +  + ]:      20043 :           if (dwarf_child (&scopes[i], &result) == 0)
    3580         [ +  + ]:     170424 :             do
    3581                 :            :               {
    3582         [ +  - ]:     170424 :                 switch (dwarf_tag (&result))
              [ +  +  + ]
    3583                 :            :                   {
    3584                 :            :                   case DW_TAG_variable:
    3585 [ +  - ][ +  + ]:      43456 :                     if (e->name == "$$parms")
    3586                 :       2714 :                       continue;
    3587                 :      40742 :                     break;
    3588                 :            :                   case DW_TAG_formal_parameter:
    3589 [ +  - ][ +  + ]:      43112 :                     if (e->name == "$$locals")
    3590                 :          6 :                       continue;
    3591                 :      43106 :                     break;
    3592                 :            : 
    3593                 :            :                   default:
    3594                 :      83856 :                     continue;
    3595                 :            :                   }
    3596                 :            : 
    3597         [ +  - ]:      83848 :                 const char *diename = dwarf_diename (&result);
    3598         [ +  + ]:      83848 :                 if (! diename) continue;
    3599                 :            : 
    3600         [ +  + ]:      83837 :                 if (! first)
    3601         [ +  - ]:      64297 :                   pf->raw_components += " ";
    3602         [ +  - ]:      83837 :                 pf->raw_components += diename;
    3603                 :      83837 :                 first = false;
    3604                 :            : 
    3605                 :            :                 // Write a placeholder for ugly aggregates
    3606                 :            :                 Dwarf_Die type;
    3607 [ +  + ][ +  - ]:      83837 :                 if (!pretty && dwarf_attr_die(&result, DW_AT_type, &type))
         [ +  - ][ +  + ]
    3608                 :            :                   {
    3609         [ +  - ]:      82285 :                     q.dw.resolve_unqualified_inner_typedie(&type, &type, e);
    3610         [ +  - ]:      82285 :                     switch (dwarf_tag(&type))
              [ +  +  + ]
    3611                 :            :                       {
    3612                 :            :                       case DW_TAG_union_type:
    3613                 :            :                       case DW_TAG_structure_type:
    3614                 :            :                       case DW_TAG_class_type:
    3615         [ +  - ]:       2591 :                         pf->raw_components += "={...}";
    3616                 :       2591 :                         continue;
    3617                 :            : 
    3618                 :            :                       case DW_TAG_array_type:
    3619         [ +  - ]:       1705 :                         pf->raw_components += "=[...]";
    3620                 :       1705 :                         continue;
    3621                 :            :                       }
    3622                 :            :                   }
    3623                 :            : 
    3624         [ +  - ]:      79541 :                 tsym->name = "$";
    3625         [ +  - ]:      79541 :                 tsym->name += diename;
    3626                 :            : 
    3627                 :            :                 // Ignore any variable that isn't accessible.
    3628                 :      79541 :                 tsym->saved_conversion_error = 0;
    3629                 :      79541 :                 expression *texp = tsym;
    3630         [ +  - ]:      79541 :                 replace (texp); // NB: throws nothing ...
    3631         [ +  + ]:      79541 :                 if (tsym->saved_conversion_error) // ... but this is how we know it happened.
    3632                 :            :                   {
    3633         [ -  + ]:      28089 :                     if (q.sess.verbose>2)
    3634                 :            :                       {
    3635         [ #  # ]:          0 :                         for (const semantic_error *c = tsym->saved_conversion_error;
    3636                 :            :                              c != 0;
    3637                 :            :                              c = c->chain) {
    3638 [ #  # ][ #  # ]:          0 :                             clog << _("variable location problem [man error::dwarf]: ") << c->what() << endl;
                 [ #  # ]
    3639                 :            :                         }
    3640                 :            :                       }
    3641                 :            : 
    3642         [ +  - ]:      28089 :                     pf->raw_components += "=?";
    3643                 :            :                   }
    3644                 :            :                 else
    3645                 :            :                   {
    3646         [ +  - ]:      51452 :                     pf->raw_components += format;
    3647         [ +  - ]:     170424 :                     pf->args.push_back(texp);
    3648                 :            :                   }
    3649                 :            :               }
    3650         [ +  - ]:     170424 :             while (dwarf_siblingof (&result, &result) == 0);
    3651         [ +  - ]:      20035 :         }
    3652                 :            :     }
    3653                 :            : 
    3654 [ +  - ][ +  - ]:      21248 :   pf->components = print_format::string_to_components(pf->raw_components);
                 [ +  - ]
    3655                 :      21248 :   pf->type = pe_string;
    3656 [ +  - ][ +  - ]:      21248 :   provide (pf);
    3657                 :            : }
    3658                 :            : 
    3659                 :            : 
    3660                 :            : void
    3661                 :     201702 : dwarf_var_expanding_visitor::visit_target_symbol (target_symbol *e)
    3662                 :            : {
    3663                 :     605107 :   assert(e->name.size() > 0
    3664                 :            :          && ((e->name[0] == '$' && e->target_name == "")
    3665   [ +  -  +  +  :     605107 :               || (e->name == "@var" && e->target_name != "")));
          -  +  +  -  -  
                      + ]
    3666                 :     201702 :   visited = true;
    3667 [ +  + ][ +  + ]:     201702 :   bool defined_being_checked = (defined_ops.size() > 0 && (defined_ops.top()->operand == e));
    3668                 :            :   // In this mode, we avoid hiding errors or generating extra code such as for .return saved $vars
    3669                 :            : 
    3670                 :            :   try
    3671                 :            :     {
    3672         [ +  - ]:     201702 :       bool lvalue = is_active_lvalue(e);
    3673 [ +  + ][ +  + ]:     201702 :       if (lvalue && !q.sess.guru_mode)
    3674 [ +  - ][ +  - ]:          1 :         throw semantic_error(_("write to target variable not permitted; need stap -g"), e->tok);
    3675                 :            : 
    3676                 :            :       // XXX: process $context vars should be writable
    3677                 :            : 
    3678                 :            :       // See if we need to generate a new probe to save/access function
    3679                 :            :       // parameters from a return probe.  PR 1382.
    3680 [ +  + ][ +  + ]:     223428 :       if (q.has_return
         [ +  + ][ +  + ]
                 [ +  + ]
    3681                 :      19365 :           && !defined_being_checked
    3682         [ +  - ]:      18960 :           && e->name != "$return" // not the special return-value variable handled below
    3683         [ +  - ]:       2767 :           && e->name != "$$return") // nor the other special variable handled below
    3684                 :            :         {
    3685         [ -  + ]:       1554 :           if (lvalue)
    3686 [ #  # ][ #  # ]:          0 :             throw semantic_error(_("write to target variable not permitted in .return probes"), e->tok);
    3687         [ +  - ]:       1554 :           visit_target_symbol_saved_return(e);
    3688                 :            :           return;
    3689                 :            :         }
    3690                 :            : 
    3691 [ +  - ][ +  + ]:     217958 :       if (e->name == "$$vars" || e->name == "$$parms" || e->name == "$$locals"
         [ +  - ][ +  + ]
         [ +  - ][ +  + ]
         [ +  + ][ +  + ]
                 [ +  + ]
    3692         [ +  - ]:      17811 :           || (q.has_return && (e->name == "$$return")))
    3693                 :            :         {
    3694         [ -  + ]:      21248 :           if (lvalue)
    3695 [ #  # ][ #  # ]:          0 :             throw semantic_error(_("cannot write to context variable"), e->tok);
    3696                 :            : 
    3697         [ -  + ]:      21248 :           if (e->addressof)
    3698 [ #  # ][ #  # ]:          0 :             throw semantic_error(_("cannot take address of context variable"), e->tok);
    3699                 :            : 
    3700 [ +  - ][ +  - ]:      21248 :           e->assert_no_components("dwarf", true);
                 [ +  - ]
    3701                 :            : 
    3702         [ +  - ]:      21248 :           visit_target_symbol_context(e);
    3703                 :            :           return;
    3704                 :            :         }
    3705                 :            : 
    3706 [ +  - ][ +  + ]:     182716 :       if (!e->components.empty() &&
         [ +  + ][ +  + ]
    3707         [ +  - ]:       3817 :           e->components.back().type == target_symbol::comp_pretty_print)
    3708                 :            :         {
    3709         [ -  + ]:       1581 :           if (lvalue)
    3710 [ #  # ][ #  # ]:          0 :             throw semantic_error(_("cannot write to pretty-printed variable"), e->tok);
    3711                 :            : 
    3712 [ -  + ][ #  # ]:       1581 :           if (q.has_return && (e->name == "$return"))
         [ #  # ][ -  + ]
    3713                 :            :             {
    3714                 :            :               dwarf_pretty_print dpp (q.dw, scope_die, addr,
    3715         [ #  # ]:          0 :                                       q.has_process, *e);
    3716 [ #  # ][ #  # ]:          0 :               dpp.expand()->visit(this);
                 [ #  # ]
    3717                 :            :             }
    3718                 :            :           else
    3719                 :            :             {
    3720         [ +  - ]:       1581 :               dwarf_pretty_print dpp (q.dw, getscopes(e), addr,
    3721                 :            :                                       e->sym_name(),
    3722 [ +  - ][ +  - ]:       1581 :                                       q.has_process, *e);
                 [ +  - ]
    3723 [ +  - ][ +  - ]:       1581 :               dpp.expand()->visit(this);
                 [ +  - ]
    3724                 :            :             }
    3725                 :            :           return;
    3726                 :            :         }
    3727                 :            : 
    3728                 :     177318 :       bool userspace_p = q.has_process;
    3729                 :            :       string fname = (string(lvalue ? "_dwarf_tvar_set" : "_dwarf_tvar_get")
    3730                 :            :                       + "_" + e->sym_name()
    3731 [ +  + ][ +  - ]:     177318 :                       + "_" + lex_cast(tick++));
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
    3732                 :            : 
    3733                 :            : 
    3734                 :     177318 :       exp_type type = pe_long;
    3735         [ +  - ]:     177318 :       string code;
    3736 [ +  + ][ +  - ]:     177318 :       if (q.has_return && (e->name == "$return"))
         [ +  + ][ +  + ]
    3737 [ +  + ][ +  - ]:      16240 :         code = q.dw.literal_stmt_for_return (scope_die, addr, e, lvalue, type);
                 [ +  - ]
    3738                 :            :       else
    3739         [ +  - ]:     161078 :         code = q.dw.literal_stmt_for_local (getscopes(e), addr, e->sym_name(),
    3740 [ +  - ][ +  + ]:     161078 :                                             e, lvalue, type);
         [ +  - ][ +  - ]
                 [ +  - ]
    3741                 :            : 
    3742                 :            :       functioncall* n = synthetic_embedded_deref_call(q.sess, fname, code, type,
    3743         [ +  - ]:     143258 :                                                       userspace_p, lvalue, e);
    3744                 :            : 
    3745         [ +  + ]:     143258 :       if (lvalue)
    3746                 :            :         {
    3747                 :            :           // Provide the functioncall to our parent, so that it can be
    3748                 :            :           // used to substitute for the assignment node immediately above
    3749                 :            :           // us.
    3750 [ +  - ][ -  + ]:         16 :           assert(!target_symbol_setter_functioncalls.empty());
    3751         [ +  - ]:         16 :           *(target_symbol_setter_functioncalls.top()) = n;
    3752                 :            :         }
    3753                 :            : 
    3754                 :            :       // Revisit the functioncall so arguments can be expanded.
    3755 [ +  - ][ +  - ]:     235763 :       n->visit (this);
                 [ +  - ]
    3756                 :            :     }
    3757         [ -  + ]:      68122 :   catch (const semantic_error& er)
    3758                 :            :     {
    3759                 :            :       // We suppress this error message, and pass the unresolved
    3760                 :            :       // target_symbol to the next pass.  We hope that this value ends
    3761                 :            :       // up not being referenced after all, so it can be optimized out
    3762                 :            :       // quietly.
    3763         [ -  + ]:      34061 :       e->chain (er);
    3764         [ -  + ]:      34061 :       provide (e);
    3765                 :            :     }
    3766                 :            : }
    3767                 :            : 
    3768                 :            : 
    3769                 :            : void
    3770                 :        391 : dwarf_var_expanding_visitor::visit_cast_op (cast_op *e)
    3771                 :            : {
    3772                 :            :   // Fill in our current module context if needed
    3773         [ +  + ]:        391 :   if (e->module.empty())
    3774                 :        347 :     e->module = q.dw.module_name;
    3775                 :            : 
    3776                 :        391 :   var_expanding_visitor::visit_cast_op(e);
    3777                 :        391 : }
    3778                 :            : 
    3779                 :            : 
    3780                 :            : void
    3781                 :        696 : dwarf_var_expanding_visitor::visit_entry_op (entry_op *e)
    3782                 :            : {
    3783                 :        696 :   expression *repl = e;
    3784         [ +  + ]:        696 :   if (q.has_return)
    3785                 :            :     {
    3786                 :            :       // expand the operand as if it weren't a return probe
    3787                 :        695 :       q.has_return = false;
    3788                 :        695 :       replace (e->operand);
    3789                 :        695 :       q.has_return = true;
    3790                 :            : 
    3791                 :            :       // XXX it would be nice to use gen_kretprobe_saved_return when available,
    3792                 :            :       // but it requires knowing the types already, which is problematic for
    3793                 :            :       // arbitrary expressons.
    3794 [ +  - ][ +  - ]:        695 :       repl = gen_mapped_saved_return (e->operand, "entry");
                 [ +  - ]
    3795                 :            :     }
    3796                 :        696 :   provide (repl);
    3797                 :        696 : }
    3798                 :            : 
    3799                 :            : void
    3800                 :          5 : dwarf_var_expanding_visitor::visit_perf_op (perf_op *e)
    3801                 :            : {
    3802 [ +  - ][ +  - ]:          5 :   token* t = new token;
    3803         [ +  - ]:          5 :   string e_lit_val = e->operand->value;
    3804                 :            :   
    3805                 :          5 :   t->location = e->tok->location;
    3806                 :          5 :   t->type = tok_identifier;
    3807         [ +  - ]:          5 :   t->content = e_lit_val;
    3808                 :            : 
    3809 [ +  - ][ +  - ]:          5 :   add_block = new block;
    3810                 :            : 
    3811                 :          5 :   systemtap_session &s = this->q.sess;
    3812                 :          5 :   map<string, pair<string,derived_probe*> >::iterator it;
    3813                 :            :   // Find the associated perf.counter probe
    3814 [ +  - ][ +  + ]:         14 :   for (it=s.perf_counters.begin();
    3815         [ +  - ]:          7 :        it != s.perf_counters.end();
    3816                 :            :        it++)
    3817 [ +  - ][ +  + ]:          5 :     if ((*it).first == e_lit_val)
    3818                 :            :       {
    3819                 :            :         // if perf .function("name") omitted, then set it to this process name
    3820 [ +  - ][ +  + ]:          4 :         if ((*it).second.first.length() == 0)
    3821         [ +  - ]:          1 :           ((*it).second).first = this->q.user_path;
    3822 [ +  - ][ +  + ]:          4 :         if (((*it).second).first == this->q.user_path)
    3823                 :          3 :           break;
    3824                 :            :       }
    3825                 :            : 
    3826 [ +  - ][ +  + ]:          5 :   if (it != s.perf_counters.end())
    3827                 :            :     {
    3828         [ +  - ]:          3 :       perf_counter_refs.insert((*it).second.second);
    3829                 :            :       // __perf_read_N is assigned in the probe prologue
    3830 [ +  - ][ +  - ]:          3 :       symbol* sym = new symbol;
    3831                 :          3 :       sym->tok = t;
    3832 [ +  - ][ +  - ]:          3 :       sym->name = "__perf_read_" + (*it).first;
                 [ +  - ]
    3833         [ +  - ]:          3 :       provide (sym);
    3834                 :            :     }
    3835                 :            :   else
    3836 [ +  - ][ +  - ]:          5 :     throw semantic_error(_F("perf counter '%s' not defined", e_lit_val.c_str()));
         [ +  - ][ +  - ]
    3837                 :          3 : }
    3838                 :            : 
    3839                 :            : vector<Dwarf_Die>&
    3840                 :          1 : dwarf_var_expanding_visitor::getcuscope(target_symbol *e)
    3841                 :            : {
    3842                 :          1 :   Dwarf_Off cu_off = 0;
    3843                 :          1 :   const char *cu_name = NULL;
    3844                 :            : 
    3845 [ +  - ][ +  - ]:          1 :   string prefixed_srcfile = string("*/") + e->cu_name;
                 [ +  - ]
    3846                 :            : 
    3847                 :          1 :   Dwarf_Off off = 0;
    3848                 :            :   size_t cuhl;
    3849                 :            :   Dwarf_Off noff;
    3850                 :            :   Dwarf_Off module_bias;
    3851         [ +  - ]:          1 :   Dwarf *dw = dwfl_module_getdwarf(q.dw.module, &module_bias);
    3852 [ +  - ][ +  - ]:        134 :   while (dwarf_nextcu (dw, off, &noff, &cuhl, NULL, NULL, NULL) == 0)
    3853                 :            :     {
    3854                 :            :       Dwarf_Die die_mem;
    3855                 :            :       Dwarf_Die *die;
    3856         [ +  - ]:        134 :       die = dwarf_offdie (dw, off + cuhl, &die_mem);
    3857                 :            : 
    3858                 :            :       /* We are not interested in partial units. */
    3859 [ +  - ][ +  - ]:        134 :       if (dwarf_tag (die) == DW_TAG_compile_unit)
    3860                 :            :         {
    3861         [ +  - ]:        134 :           const char *die_name = dwarf_diename (die);
    3862 [ +  - ][ +  + ]:        134 :           if (strcmp (die_name, e->cu_name.c_str()) == 0) // Perfect match.
    3863                 :            :             {
    3864                 :          1 :               cu_name = die_name;
    3865                 :          1 :               cu_off = off + cuhl;
    3866                 :            :               break;
    3867                 :            :             }
    3868                 :            : 
    3869 [ +  - ][ +  - ]:        133 :           if (fnmatch(prefixed_srcfile.c_str(), die_name, 0) == 0)
                 [ +  + ]
    3870 [ -  + ][ #  # ]:          1 :             if (cu_name == NULL || strlen (die_name) < strlen (cu_name))
    3871                 :            :               {
    3872                 :          1 :                 cu_name = die_name;
    3873                 :          1 :                 cu_off = off + cuhl;
    3874                 :            :               }
    3875                 :            :         }
    3876                 :        133 :       off = noff;
    3877                 :            :     }
    3878                 :            : 
    3879         [ -  + ]:          1 :   if (cu_name == NULL)
    3880                 :            :     throw semantic_error ("unable to find CU '" + e->cu_name + "'"
    3881                 :            :                           + " while searching for '" + e->target_name + "'",
    3882 [ #  # ][ #  # ]:          0 :                           e->tok);
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
    3883                 :            : 
    3884 [ +  - ][ +  - ]:          1 :   vector<Dwarf_Die> *cu_scope = new vector<Dwarf_Die>;
    3885                 :            :   Dwarf_Die cu_die;
    3886         [ +  - ]:          1 :   dwarf_offdie (dw, cu_off, &cu_die);
    3887         [ +  - ]:          1 :   cu_scope->push_back(cu_die);
    3888         [ +  - ]:          1 :   return *cu_scope;
    3889                 :            : }
    3890                 :            : 
    3891                 :            : vector<Dwarf_Die>&
    3892                 :     162659 : dwarf_var_expanding_visitor::getscopes(target_symbol *e)
    3893                 :            : {
    3894                 :            :   // "static globals" can only be found in the top-level CU.
    3895 [ +  + ][ +  - ]:     162659 :   if (e->name == "@var" && e->cu_name != "")
                 [ +  + ]
    3896                 :          1 :     return this->getcuscope(e);
    3897                 :            : 
    3898         [ +  + ]:     162658 :   if (scopes.empty())
    3899                 :            :     {
    3900         [ +  - ]:      34526 :       if(scope_die != NULL)
    3901         [ +  - ]:      34526 :         scopes = q.dw.getscopes(scope_die);
    3902         [ -  + ]:      34526 :       if (scopes.empty())
    3903                 :            :         //throw semantic_error (_F("unable to find any scopes containing %d", addr), e->tok);
    3904                 :            :         //                        ((scope_die == NULL) ? "" : (string (" in ") + (dwarf_diename(scope_die) ?: "<unknown>") + "(" + (dwarf_diename(q.dw.cu) ?: "<unknown>") ")" ))
    3905                 :            :         throw semantic_error ("unable to find any scopes containing "
    3906                 :            :                               + lex_cast_hex(addr)
    3907                 :            :                               + ((scope_die == NULL) ? ""
    3908                 :            :                                  : (string (" in ")
    3909         [ #  # ]:          0 :                                     + (dwarf_diename(scope_die) ?: "<unknown>")
    3910         [ #  # ]:          0 :                                     + "(" + (dwarf_diename(q.dw.cu) ?: "<unknown>")
    3911                 :            :                                     + ")"))
    3912                 :            :                               + " while searching for local '"
    3913                 :            :                               + e->sym_name() + "'",
    3914 [ #  # ][ #  # ]:          0 :                               e->tok);
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  #  
          #  #  #  #  #  
             #  #  #  #  
                      # ]
    3915                 :            :     }
    3916                 :     162659 :   return scopes;
    3917                 :            : }
    3918                 :            : 
    3919                 :            : 
    3920         [ #  # ]:          0 : struct dwarf_cast_expanding_visitor: public var_expanding_visitor
    3921                 :            : {
    3922                 :            :   systemtap_session& s;
    3923                 :            :   dwarf_builder& db;
    3924                 :            : 
    3925                 :       1218 :   dwarf_cast_expanding_visitor(systemtap_session& s, dwarf_builder& db):
    3926                 :       1218 :     s(s), db(db) {}
    3927                 :            :   void visit_cast_op (cast_op* e);
    3928                 :            :   void filter_special_modules(string& module);
    3929                 :            : };
    3930                 :            : 
    3931                 :            : 
    3932         [ -  + ]:       9337 : struct dwarf_cast_query : public base_query
    3933                 :            : {
    3934                 :            :   cast_op& e;
    3935                 :            :   const bool lvalue;
    3936                 :            :   const bool userspace_p;
    3937                 :            :   functioncall*& result;
    3938                 :            : 
    3939                 :       9337 :   dwarf_cast_query(dwflpp& dw, const string& module, cast_op& e, bool lvalue,
    3940                 :            :                    const bool userspace_p, functioncall*& result):
    3941                 :            :     base_query(dw, module), e(e), lvalue(lvalue),
    3942                 :       9337 :     userspace_p(userspace_p), result(result) {}
    3943                 :            : 
    3944                 :            :   void handle_query_module();
    3945                 :          0 :   void query_library (const char *) {}
    3946                 :          0 :   void query_plt (const char *entry, size_t addr) {}
    3947                 :            : };
    3948                 :            : 
    3949                 :            : 
    3950                 :            : void
    3951                 :       9335 : dwarf_cast_query::handle_query_module()
    3952                 :            : {
    3953                 :            :   static unsigned tick = 0;
    3954                 :            : 
    3955         [ +  - ]:       9335 :   if (result)
    3956                 :            :     return;
    3957                 :            : 
    3958                 :            :   // look for the type in any CU
    3959                 :       9335 :   Dwarf_Die* type_die = NULL;
    3960 [ +  - ][ -  + ]:       9335 :   if (startswith(e.type_name, "class "))
    3961                 :            :     {
    3962                 :            :       // normalize to match dwflpp::global_alias_caching_callback
    3963 [ #  # ][ #  # ]:          0 :       string struct_name = "struct " + e.type_name.substr(6);
                 [ #  # ]
    3964 [ #  # ][ #  # ]:          0 :       type_die = dw.declaration_resolve_other_cus(struct_name);
    3965                 :            :     }
    3966                 :            :   else
    3967         [ +  - ]:       9335 :     type_die = dw.declaration_resolve_other_cus(e.type_name);
    3968                 :            : 
    3969                 :            :   // NB: We now index the types as "struct name"/"union name"/etc. instead of
    3970                 :            :   // just "name".  But since we didn't require users to be explicit before, and
    3971                 :            :   // actually sort of discouraged it, we must be flexible now.  So if a lookup
    3972                 :            :   // fails with a bare name, try augmenting it.
    3973 [ +  + ][ +  - ]:      45647 :   if (!type_die &&
         [ +  - ][ +  - ]
         [ +  - ][ +  + ]
    3974         [ +  - ]:       9078 :       !startswith(e.type_name, "class ") &&
    3975         [ +  - ]:       9078 :       !startswith(e.type_name, "struct ") &&
    3976         [ +  - ]:       9078 :       !startswith(e.type_name, "union ") &&
    3977         [ +  - ]:       9078 :       !startswith(e.type_name, "enum "))
    3978                 :            :     {
    3979 [ +  - ][ +  - ]:       9078 :       type_die = dw.declaration_resolve_other_cus("struct " + e.type_name);
                 [ +  - ]
    3980         [ +  + ]:       9078 :       if (!type_die)
    3981 [ +  - ][ +  - ]:        797 :         type_die = dw.declaration_resolve_other_cus("union " + e.type_name);
                 [ +  - ]
    3982         [ +  + ]:       9078 :       if (!type_die)
    3983 [ +  - ][ +  - ]:        797 :         type_die = dw.declaration_resolve_other_cus("enum " + e.type_name);
                 [ +  - ]
    3984                 :            :     }
    3985                 :            : 
    3986         [ +  + ]:       9335 :   if (!type_die)
    3987                 :            :     return;
    3988                 :            : 
    3989         [ +  - ]:       8538 :   string code;
    3990                 :       8538 :   exp_type type = pe_long;
    3991                 :            : 
    3992                 :            :   try
    3993                 :            :     {
    3994                 :            :       Dwarf_Die cu_mem;
    3995 [ +  - ][ +  - ]:       8538 :       dw.focus_on_cu(dwarf_diecu(type_die, &cu_mem, NULL, NULL));
    3996                 :            : 
    3997 [ +  - ][ +  - ]:      17076 :       if (!e.components.empty() &&
         [ +  + ][ +  + ]
    3998         [ +  - ]:       8538 :           e.components.back().type == target_symbol::comp_pretty_print)
    3999                 :            :         {
    4000         [ -  + ]:         24 :           if (lvalue)
    4001 [ #  # ][ #  # ]:          0 :             throw semantic_error(_("cannot write to pretty-printed variable"), e.tok);
    4002                 :            : 
    4003         [ +  - ]:         24 :           dwarf_pretty_print dpp(dw, type_die, e.operand, true, userspace_p, e);
    4004         [ +  - ]:         24 :           result = dpp.expand();
    4005         [ +  - ]:         24 :           return;
    4006                 :            :         }
    4007                 :            : 
    4008 [ +  + ][ +  - ]:       8514 :       code = dw.literal_stmt_for_pointer (type_die, &e, lvalue, type);
                 [ +  - ]
    4009                 :            :     }
    4010         [ -  + ]:       2578 :   catch (const semantic_error& er)
    4011                 :            :     {
    4012                 :            :       // NB: we can have multiple errors, since a @cast
    4013                 :            :       // may be attempted using several different modules:
    4014                 :            :       //     @cast(ptr, "type", "module1:module2:...")
    4015         [ -  + ]:       1289 :       e.chain (er);
    4016                 :            :     }
    4017                 :            : 
    4018 [ +  - ][ +  + ]:       8514 :   if (code.empty())
    4019                 :            :     return;
    4020                 :            : 
    4021                 :            :   string fname = (string(lvalue ? "_dwarf_cast_set" : "_dwarf_cast_get")
    4022                 :            :                   + "_" + e.sym_name()
    4023 [ +  + ][ +  - ]:       7225 :                   + "_" + lex_cast(tick++));
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
    4024                 :            : 
    4025                 :            :   result = synthetic_embedded_deref_call(dw.sess, fname, code, type,
    4026 [ +  - ][ +  - ]:       9335 :                                          userspace_p, lvalue, &e, e.operand);
         [ +  - ][ +  + ]
    4027                 :            : }
    4028                 :            : 
    4029                 :            : 
    4030                 :       9337 : void dwarf_cast_expanding_visitor::filter_special_modules(string& module)
    4031                 :            : {
    4032                 :            :   // look for "<path/to/header>" or "kernel<path/to/header>"
    4033                 :            :   // for those cases, build a module including that header
    4034   [ +  +  +  +  :      18589 :   if (module[module.size() - 1] == '>' &&
           +  - ][ +  + ]
    4035                 :       9252 :       (module[0] == '<' || startswith(module, "kernel<")))
    4036                 :            :     {
    4037         [ +  - ]:       4628 :       string cached_module;
    4038         [ +  - ]:       4628 :       if (s.use_cache)
    4039                 :            :         {
    4040                 :            :           // see if the cached module exists
    4041 [ +  - ][ +  - ]:       4628 :           cached_module = find_typequery_hash(s, module);
                 [ +  - ]
    4042 [ +  - ][ +  - ]:       4628 :           if (!cached_module.empty() && !s.poison_cache)
         [ +  - ][ +  - ]
    4043                 :            :             {
    4044 [ +  - ][ +  - ]:       4628 :               int fd = open(cached_module.c_str(), O_RDONLY);
    4045         [ +  + ]:       4628 :               if (fd != -1)
    4046                 :            :                 {
    4047         [ -  + ]:       4618 :                   if (s.verbose > 2)
    4048                 :            :                     //TRANSLATORS: Here we're using a cached module.
    4049 [ #  # ][ #  # ]:          0 :                     clog << _("Pass 2: using cached ") << cached_module << endl;
                 [ #  # ]
    4050         [ +  - ]:       4618 :                   module = cached_module;
    4051         [ +  - ]:       4618 :                   close(fd);
    4052                 :       9337 :                   return;
    4053                 :            :                 }
    4054                 :            :             }
    4055                 :            :         }
    4056                 :            : 
    4057                 :            :       // no cached module, time to make it
    4058 [ +  - ][ +  - ]:         10 :       if (make_typequery(s, module) == 0)
    4059                 :            :         {
    4060                 :            :           // try to save typequery in the cache
    4061         [ +  - ]:         10 :           if (s.use_cache)
    4062         [ +  - ]:         10 :             copy_file(module, cached_module, s.verbose > 2);
    4063 [ +  - ][ +  + ]:       4628 :         }
    4064                 :            :     }
    4065                 :            : }
    4066                 :            : 
    4067                 :            : 
    4068                 :       8504 : void dwarf_cast_expanding_visitor::visit_cast_op (cast_op* e)
    4069                 :            : {
    4070         [ +  - ]:       8504 :   bool lvalue = is_active_lvalue(e);
    4071 [ +  + ][ -  + ]:       8504 :   if (lvalue && !s.guru_mode)
    4072 [ #  # ][ #  # ]:          0 :     throw semantic_error(_("write to @cast context variable not permitted; need stap -g"), e->tok);
    4073                 :            : 
    4074 [ +  - ][ +  + ]:       8504 :   if (e->module.empty())
    4075         [ +  - ]:       1865 :     e->module = "kernel"; // "*" may also be reasonable to search all kernel modules
    4076                 :            : 
    4077                 :       8504 :   functioncall* result = NULL;
    4078                 :            : 
    4079                 :            :   // split the module string by ':' for alternatives
    4080         [ +  - ]:       8504 :   vector<string> modules;
    4081 [ +  - ][ +  - ]:       8504 :   tokenize(e->module, modules, ":");
                 [ +  - ]
    4082                 :       8504 :   bool userspace_p=false; // PR10601
    4083 [ +  + ][ +  + ]:      17841 :   for (unsigned i = 0; !result && i < modules.size(); ++i)
                 [ +  + ]
    4084                 :            :     {
    4085                 :       9337 :       string& module = modules[i];
    4086         [ +  - ]:       9337 :       filter_special_modules(module);
    4087                 :            : 
    4088                 :            :       // NB: This uses '/' to distinguish between kernel modules and userspace,
    4089                 :            :       // which means that userspace modules won't get any PATH searching.
    4090                 :            :       dwflpp* dw;
    4091                 :            :       try
    4092                 :            :         {
    4093         [ +  - ]:       9337 :           userspace_p=is_user_module (module);
    4094         [ +  + ]:       9337 :           if (! userspace_p)
    4095                 :            :             {
    4096                 :            :               // kernel or kernel module target
    4097         [ +  - ]:       9323 :               dw = db.get_kern_dw(s, module);
    4098                 :            :             }
    4099                 :            :           else
    4100                 :            :             {
    4101 [ +  - ][ +  - ]:         14 :               module = find_executable (module, "", s.sysenv); // canonicalize it
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ #  # ]
    4102         [ +  - ]:         14 :               dw = db.get_user_dw(s, module);
    4103                 :            :             }
    4104                 :            :         }
    4105                 :            :       catch (const semantic_error& er)
    4106                 :            :         {
    4107                 :            :           /* ignore and go to the next module */
    4108                 :            :           continue;
    4109                 :            :         }
    4110                 :            : 
    4111         [ +  - ]:       9337 :       dwarf_cast_query q (*dw, module, *e, lvalue, userspace_p, result);
    4112         [ +  - ]:       9337 :       dw->iterate_over_modules(&query_module, &q);
    4113         [ +  - ]:       9337 :     }
    4114                 :            : 
    4115         [ +  + ]:       8504 :   if (!result)
    4116                 :            :     {
    4117                 :            :       // We pass the unresolved cast_op to the next pass, and hope
    4118                 :            :       // that this value ends up not being referenced after all, so
    4119                 :            :       // it can be optimized out quietly.
    4120         [ +  - ]:       1255 :       provide (e);
    4121                 :       8504 :       return;
    4122                 :            :     }
    4123                 :            : 
    4124         [ +  + ]:       7249 :   if (lvalue)
    4125                 :            :     {
    4126                 :            :       // Provide the functioncall to our parent, so that it can be
    4127                 :            :       // used to substitute for the assignment node immediately above
    4128                 :            :       // us.
    4129 [ +  - ][ -  + ]:          2 :       assert(!target_symbol_setter_functioncalls.empty());
    4130         [ +  - ]:          2 :       *(target_symbol_setter_functioncalls.top()) = result;
    4131                 :            :     }
    4132                 :            : 
    4133 [ +  - ][ +  - ]:       8504 :   result->visit (this);
                 [ +  + ]
    4134                 :            : }
    4135                 :            : 
    4136                 :            : 
    4137                 :            : void
    4138                 :     317149 : dwarf_derived_probe::printsig (ostream& o) const
    4139                 :            : {
    4140                 :            :   // Instead of just printing the plain locations, we add a PC value
    4141                 :            :   // as a comment as a way of telling e.g. apart multiple inlined
    4142                 :            :   // function instances.  This is distinct from the verbose/clog
    4143                 :            :   // output, since this part goes into the cache hash calculations.
    4144                 :     317149 :   sole_location()->print (o);
    4145                 :     317149 :   o << " /* pc=" << section << "+0x" << hex << addr << dec << " */";
    4146                 :     317149 :   printsig_nested (o);
    4147                 :     317149 : }
    4148                 :            : 
    4149                 :            : 
    4150                 :            : 
    4151                 :            : void
    4152                 :     318359 : dwarf_derived_probe::join_group (systemtap_session& s)
    4153                 :            : {
    4154                 :            :   // skip probes which are paired entry-handlers
    4155 [ +  + ][ +  + ]:     318359 :   if (!has_return && (saved_longs || saved_strings))
                 [ +  + ]
    4156                 :     318359 :     return;
    4157                 :            : 
    4158         [ +  + ]:     317756 :   if (! s.dwarf_derived_probes)
    4159         [ +  - ]:        385 :     s.dwarf_derived_probes = new dwarf_derived_probe_group ();
    4160                 :     317756 :   s.dwarf_derived_probes->enroll (this);
    4161                 :            : }
    4162                 :            : 
    4163                 :            : 
    4164                 :            : static bool
    4165                 :      11891 : kernel_supports_inode_uprobes(systemtap_session& s)
    4166                 :            : {
    4167                 :            :   // The arch-supports is new to the builtin inode-uprobes, so it makes a
    4168                 :            :   // reasonable indicator of the new API.  Else we'll need an autoconf...
    4169                 :            :   // see also buildrun.cxx:kernel_built_uprobs()
    4170 [ +  - ][ +  - ]:      23782 :   return (s.kernel_config["CONFIG_ARCH_SUPPORTS_UPROBES"] == "y"
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
           [ #  #  #  # ]
    4171 [ -  + ][ #  # ]:      23782 :           && s.kernel_config["CONFIG_UPROBES"] == "y");
         [ #  # ][ #  # ]
         [ #  # ][ -  + ]
         [ #  # ][ -  + ]
           [ #  #  #  # ]
    4172                 :            : }
    4173                 :            : 
    4174                 :            : 
    4175                 :            : static bool
    4176                 :          0 : kernel_supports_inode_uretprobes(systemtap_session& s)
    4177                 :            : {
    4178                 :            :   // We need inode-uprobes first, then look for uretprobe_register either as a
    4179                 :            :   // real export or in the list possibly accessible by kallsyms.
    4180         [ #  # ]:          0 :   return kernel_supports_inode_uprobes(s) &&
    4181 [ #  # ][ #  # ]:          0 :     (s.kernel_exports.count("uretprobe_register") > 0 ||
         [ #  # ][ #  # ]
                 [ #  # ]
           [ #  #  #  # ]
    4182 [ #  # ][ #  # ]:          0 :      s.kernel_functions.count("uretprobe_register") > 0);
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
           [ #  #  #  # ]
    4183                 :            : }
    4184                 :            : 
    4185                 :            : 
    4186                 :            : void
    4187                 :         84 : check_process_probe_kernel_support(systemtap_session& s)
    4188                 :            : {
    4189                 :            :   // If we've got utrace, we're good to go.
    4190 [ +  - ][ +  - ]:         84 :   if (s.kernel_config["CONFIG_UTRACE"] == "y")
         [ +  - ][ +  - ]
                 [ -  + ]
    4191                 :          0 :     return;
    4192                 :            : 
    4193                 :            :   // We don't have utrace.  For process probes that aren't
    4194                 :            :   // uprobes-based, we just need the task_finder.  The task_finder
    4195                 :            :   // needs CONFIG_TRACEPOINTS and specific tracepoints.  There is a
    4196                 :            :   // specific autoconf test for its needs.
    4197                 :            :   //
    4198                 :            :   // We'll just require CONFIG_TRACEPOINTS here as a quick-and-dirty
    4199                 :            :   // approximation.
    4200 [ +  + ][ +  - ]:         84 :   if (! s.need_uprobes && s.kernel_config["CONFIG_TRACEPOINTS"] == "y")
         [ +  - ][ +  - ]
         [ +  - ][ +  + ]
         [ +  - ][ +  + ]
           [ +  +  #  #  
                   #  # ]
    4201                 :         82 :     return;
    4202                 :            : 
    4203                 :            :   // For uprobes-based process probes, we need the task_finder plus
    4204                 :            :   // the builtin inode-uprobes.
    4205 [ +  - ][ +  - ]:          8 :   if (s.need_uprobes
         [ -  + ][ -  + ]
    4206 [ +  - ][ +  - ]:          4 :       && s.kernel_config["CONFIG_TRACEPOINTS"] == "y"
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
           [ #  #  #  # ]
    4207         [ +  - ]:          2 :       && kernel_supports_inode_uprobes(s))
    4208                 :          0 :     return;
    4209                 :            : 
    4210 [ +  - ][ +  - ]:         84 :   throw semantic_error (_("process probes not available without kernel CONFIG_UTRACE or CONFIG_TRACEPOINTS/CONFIG_ARCH_SUPPORTS_UPROBES/CONFIG_UPROBES"));
    4211                 :            : }
    4212                 :            : 
    4213                 :            : 
    4214                 :     330227 : dwarf_derived_probe::dwarf_derived_probe(const string& funcname,
    4215                 :            :                                          const string& filename,
    4216                 :            :                                          int line,
    4217                 :            :                                          // module & section specify a relocation
    4218                 :            :                                          // base for <addr>, unless section==""
    4219                 :            :                                          // (equivalently module=="kernel")
    4220                 :            :                                          const string& module,
    4221                 :            :                                          const string& section,
    4222                 :            :                                          // NB: dwfl_addr is the virtualized
    4223                 :            :                                          // address for this symbol.
    4224                 :            :                                          Dwarf_Addr dwfl_addr,
    4225                 :            :                                          // addr is the section-offset for
    4226                 :            :                                          // actual relocation.
    4227                 :            :                                          Dwarf_Addr addr,
    4228                 :            :                                          dwarf_query& q,
    4229                 :            :                                          Dwarf_Die* scope_die /* may be null */)
    4230                 :            :   : derived_probe (q.base_probe, q.base_loc, true /* .components soon rewritten */ ),
    4231                 :            :     module (module), section (section), addr (addr),
    4232                 :            :     path (q.path),
    4233                 :            :     has_process (q.has_process),
    4234                 :            :     has_return (q.has_return),
    4235                 :            :     has_maxactive (q.has_maxactive),
    4236                 :            :     has_library (q.has_library),
    4237                 :            :     maxactive_val (q.maxactive_val),
    4238                 :            :     user_path (q.user_path),
    4239                 :            :     user_lib (q.user_lib),
    4240                 :            :     access_vars(false),
    4241                 :            :     saved_longs(0), saved_strings(0),
    4242 [ +  - ][ +  - ]:     330227 :     entry_handler(0)
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
    4243                 :            : {
    4244 [ +  - ][ -  + ]:     330227 :   if (user_lib.size() != 0)
    4245                 :          0 :     has_library = true;
    4246                 :            : 
    4247         [ +  + ]:     330227 :   if (q.has_process)
    4248                 :            :     {
    4249                 :            :       // We may receive probes on two types of ELF objects: ET_EXEC or ET_DYN.
    4250                 :            :       // ET_EXEC ones need no further relocation on the addr(==dwfl_addr), whereas
    4251                 :            :       // ET_DYN ones do (addr += run-time mmap base address).  We tell these apart
    4252                 :            :       // by the incoming section value (".absolute" vs. ".dynamic").
    4253                 :            :       // XXX Assert invariants here too?
    4254                 :            : 
    4255                 :            :       // inode-uprobes needs an offset rather than an absolute VM address.
    4256                 :            :       // ditto for userspace runtimes (dyninst)
    4257 [ +  - ][ +  - ]:      11862 :       if ((kernel_supports_inode_uprobes(q.dw.sess) || q.dw.sess.runtime_usermode_p()) &&
         [ -  + ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ -  + ]
    4258         [ #  # ]:          0 :           section == ".absolute" && addr == dwfl_addr &&
    4259                 :            :           addr >= q.dw.module_start && addr < q.dw.module_end)
    4260                 :          0 :         this->addr = addr - q.dw.module_start;
    4261                 :            :     }
    4262                 :            :   else
    4263                 :            :     {
    4264                 :            :       // Assert kernel relocation invariants
    4265 [ +  - ][ +  + ]:     318365 :       if (section == "" && dwfl_addr != addr) // addr should be absolute
         [ -  + ][ -  + ]
    4266 [ #  # ][ #  # ]:          0 :         throw semantic_error (_("missing relocation basis"), tok);
    4267 [ +  - ][ +  + ]:     318365 :       if (section != "" && dwfl_addr == addr) // addr should be an offset
         [ -  + ][ -  + ]
    4268 [ #  # ][ #  # ]:          0 :         throw semantic_error (_("inconsistent relocation address"), tok);
    4269                 :            :     }
    4270                 :            : 
    4271                 :            :   // XXX: hack for strange g++/gcc's
    4272                 :            : #ifndef USHRT_MAX
    4273                 :            : #define USHRT_MAX 32767
    4274                 :            : #endif
    4275                 :            : 
    4276                 :            :   // Range limit maxactive() value
    4277 [ +  + ][ +  + ]:     330227 :   if (has_maxactive && (maxactive_val < 0 || maxactive_val > USHRT_MAX))
                 [ +  + ]
    4278                 :          2 :     throw semantic_error (_F("maxactive value out of range [0,%s]",
    4279 [ +  - ][ +  - ]:          2 :                           lex_cast(USHRT_MAX).c_str()), q.base_loc->components.front()->tok);
         [ +  - ][ +  - ]
                 [ +  - ]
    4280                 :            : 
    4281                 :            :   // Expand target variables in the probe body
    4282         [ +  + ]:     330225 :   if (!null_die(scope_die))
    4283                 :            :     {
    4284                 :            :       // XXX: user-space deref's for q.has_process!
    4285         [ +  - ]:     330173 :       dwarf_var_expanding_visitor v (q, scope_die, dwfl_addr);
    4286         [ +  + ]:     330173 :       v.replace (this->body);
    4287                 :            : 
    4288                 :            :       // Propagate perf.counters so we can emit later
    4289         [ +  - ]:     330167 :       this->perf_counter_refs = v.perf_counter_refs;
    4290                 :            :       // Emit local var used to save the perf counter read value
    4291                 :     330167 :       std::set<derived_probe*>::iterator pcii;
    4292 [ +  - ][ +  + ]:     660340 :       for (pcii = v.perf_counter_refs.begin();
    4293         [ +  - ]:     330170 :            pcii != v.perf_counter_refs.end(); pcii++)
    4294                 :            :         {
    4295                 :          3 :           map<string, pair<string,derived_probe*> >::iterator it;
    4296                 :            :           // Find the associated perf counter probe
    4297 [ +  - ][ +  - ]:          6 :           for (it=q.sess.perf_counters.begin() ;
    4298         [ +  - ]:          3 :                it != q.sess.perf_counters.end();
    4299                 :            :                it++)
    4300         [ +  - ]:          3 :             if ((*it).second.second == (*pcii))
    4301                 :          3 :               break;
    4302 [ +  - ][ +  - ]:          3 :           vardecl* vd = new vardecl;
    4303 [ +  - ][ +  - ]:          3 :           vd->name = "__perf_read_" + (*it).first;
                 [ +  - ]
    4304                 :          3 :           vd->tok = this->tok;
    4305         [ +  - ]:          3 :           vd->set_arity(0, this->tok);
    4306                 :          3 :           vd->type = pe_long;
    4307                 :          3 :           vd->synthetic = true;
    4308         [ +  - ]:          3 :           this->locals.push_back (vd);
    4309                 :            :         }
    4310                 :            : 
    4311                 :            : 
    4312         [ +  + ]:     330167 :       if (!q.has_process)
    4313                 :     318355 :         access_vars = v.visited;
    4314                 :            : 
    4315                 :            :       // If during target-variable-expanding the probe, we added a new block
    4316                 :            :       // of code, add it to the start of the probe.
    4317         [ +  + ]:     330167 :       if (v.add_block)
    4318 [ +  - ][ +  - ]:        698 :         this->body = new block(v.add_block, this->body);
    4319                 :            : 
    4320                 :            :       // If when target-variable-expanding the probe, we need to synthesize a
    4321                 :            :       // sibling function-entry probe.  We don't go through the whole probe derivation
    4322                 :            :       // business (PR10642) that could lead to wildcard/alias resolution, or for that
    4323                 :            :       // dwarf-induced duplication.
    4324         [ +  + ]:     330167 :       if (v.add_call_probe)
    4325                 :            :         {
    4326 [ +  - ][ -  + ]:       1287 :           assert (q.has_return && !q.has_call);
    4327                 :            : 
    4328                 :            :           // We temporarily replace q.base_probe.
    4329                 :       1287 :           statement* old_body = q.base_probe->body;
    4330                 :       1287 :           q.base_probe->body = v.add_call_probe;
    4331                 :       1287 :           q.has_return = false;
    4332                 :       1287 :           q.has_call = true;
    4333                 :            : 
    4334         [ +  + ]:       1287 :           if (q.has_process)
    4335                 :            :             entry_handler = new uprobe_derived_probe (funcname, filename, line,
    4336                 :            :                                                       module, section, dwfl_addr,
    4337 [ +  - ][ +  - ]:          1 :                                                       addr, q, scope_die);
    4338                 :            :           else
    4339                 :            :             entry_handler = new dwarf_derived_probe (funcname, filename, line,
    4340                 :            :                                                      module, section, dwfl_addr,
    4341 [ +  - ][ +  - ]:       1286 :                                                      addr, q, scope_die);
    4342                 :            : 
    4343                 :       1287 :           saved_longs = entry_handler->saved_longs = v.saved_longs;
    4344                 :       1287 :           saved_strings = entry_handler->saved_strings = v.saved_strings;
    4345                 :            : 
    4346         [ +  - ]:       1287 :           q.results.push_back (entry_handler);
    4347                 :            : 
    4348                 :       1287 :           q.has_return = true;
    4349                 :       1287 :           q.has_call = false;
    4350                 :       1287 :           q.base_probe->body = old_body;
    4351                 :            :         }
    4352                 :            :       // Save the local variables for listing mode
    4353         [ +  + ]:     330167 :       if (q.sess.listing_mode_vars)
    4354 [ +  - ][ +  - ]:     330173 :          saveargs(q, scope_die, dwfl_addr);
    4355                 :            :     }
    4356                 :            :   // else - null scope_die - $target variables will produce an error during translate phase
    4357                 :            : 
    4358                 :            :   // PR10820: null scope die, local variables aren't accessible, not necessary to invoke saveargs
    4359                 :            : 
    4360                 :            :   // Reset the sole element of the "locations" vector as a
    4361                 :            :   // "reverse-engineered" form of the incoming (q.base_loc) probe
    4362                 :            :   // point.  This allows a user to see what function / file / line
    4363                 :            :   // number any particular match of the wildcards.
    4364                 :            : 
    4365         [ +  - ]:     330219 :   vector<probe_point::component*> comps;
    4366         [ +  + ]:     330219 :   if (q.has_kernel)
    4367 [ +  - ][ +  - ]:     252452 :     comps.push_back (new probe_point::component(TOK_KERNEL));
                 [ +  - ]
    4368         [ +  + ]:      77767 :   else if(q.has_module)
    4369 [ +  - ][ +  - ]:      65907 :     comps.push_back (new probe_point::component(TOK_MODULE, new literal_string(module)));
         [ +  - ][ +  - ]
                 [ +  - ]
    4370         [ +  - ]:      11860 :   else if(q.has_process)
    4371 [ +  - ][ +  - ]:      11860 :     comps.push_back (new probe_point::component(TOK_PROCESS, new literal_string(module)));
         [ +  - ][ +  - ]
                 [ +  - ]
    4372                 :            :   else
    4373                 :          0 :     assert (0);
    4374                 :            : 
    4375         [ +  - ]:     330219 :   string fn_or_stmt;
    4376 [ +  + ][ -  + ]:     330219 :   if (q.has_function_str || q.has_function_num)
    4377         [ +  - ]:     330099 :     fn_or_stmt = "function";
    4378                 :            :   else
    4379         [ +  - ]:        120 :     fn_or_stmt = "statement";
    4380                 :            : 
    4381 [ +  + ][ +  + ]:     330219 :   if (q.has_function_str || q.has_statement_str)
    4382                 :            :       {
    4383         [ +  - ]:     330142 :         string retro_name = funcname;
    4384 [ +  - ][ +  + ]:     330142 :         if (filename != "")
    4385                 :            :           {
    4386 [ +  - ][ +  - ]:     330034 :             retro_name += ("@" + string (filename));
         [ +  - ][ +  - ]
                 [ +  - ]
    4387         [ +  - ]:     330034 :             if (line > 0)
    4388 [ +  - ][ +  - ]:     330034 :               retro_name += (":" + lex_cast (line));
         [ +  - ][ +  - ]
                 [ +  - ]
    4389                 :            :           }
    4390                 :            :         comps.push_back
    4391                 :            :           (new probe_point::component
    4392 [ +  - ][ +  - ]:     330142 :            (fn_or_stmt, new literal_string (retro_name)));
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
    4393                 :            :       }
    4394 [ +  - ][ +  - ]:         77 :   else if (q.has_function_num || q.has_statement_num)
    4395                 :            :     {
    4396                 :            :       Dwarf_Addr retro_addr;
    4397         [ -  + ]:         77 :       if (q.has_function_num)
    4398                 :          0 :         retro_addr = q.function_num_val;
    4399                 :            :       else
    4400                 :         77 :         retro_addr = q.statement_num_val;
    4401                 :            :       comps.push_back (new probe_point::component
    4402                 :            :                        (fn_or_stmt,
    4403 [ +  - ][ +  - ]:         77 :                         new literal_number(retro_addr, true)));
         [ +  - ][ +  - ]
                 [ +  - ]
    4404                 :            : 
    4405         [ +  + ]:         77 :       if (q.has_absolute)
    4406 [ +  - ][ +  - ]:          4 :         comps.push_back (new probe_point::component (TOK_ABSOLUTE));
                 [ +  - ]
    4407                 :            :     }
    4408                 :            : 
    4409         [ +  + ]:     330219 :   if (q.has_call)
    4410 [ +  - ][ +  - ]:      69128 :       comps.push_back (new probe_point::component(TOK_CALL));
                 [ +  - ]
    4411         [ +  + ]:     330219 :   if (q.has_exported)
    4412 [ +  - ][ +  - ]:          9 :       comps.push_back (new probe_point::component(TOK_EXPORTED));
                 [ +  - ]
    4413         [ +  + ]:     330219 :   if (q.has_inline)
    4414 [ +  - ][ +  - ]:      85621 :       comps.push_back (new probe_point::component(TOK_INLINE));
                 [ +  - ]
    4415         [ +  + ]:     330219 :   if (has_return)
    4416 [ +  - ][ +  - ]:      46476 :     comps.push_back (new probe_point::component(TOK_RETURN));
                 [ +  - ]
    4417         [ +  + ]:     330219 :   if (has_maxactive)
    4418                 :            :     comps.push_back (new probe_point::component
    4419 [ +  - ][ +  - ]:         16 :                      (TOK_MAXACTIVE, new literal_number(maxactive_val)));
         [ +  - ][ +  - ]
                 [ +  - ]
    4420                 :            : 
    4421                 :            :   // Overwrite it.
    4422 [ +  - ][ +  - ]:     330227 :   this->sole_location()->components = comps;
         [ +  - ][ +  - ]
    4423                 :     330227 : }
    4424                 :            : 
    4425                 :            : 
    4426                 :            : void
    4427                 :      11777 : dwarf_derived_probe::saveargs(dwarf_query& q, Dwarf_Die* scope_die,
    4428                 :            :                               Dwarf_Addr dwfl_addr)
    4429                 :            : {
    4430         [ +  - ]:      11777 :   if (null_die(scope_die))
    4431                 :      11777 :     return;
    4432                 :            : 
    4433                 :      11777 :   bool verbose = q.sess.verbose > 2;
    4434                 :            : 
    4435         [ -  + ]:      11777 :   if (verbose)
    4436 [ #  # ][ #  # ]:          0 :     clog << _F("saveargs: examining '%s' (dieoffset: %#" PRIx64 ")\n", (dwarf_diename(scope_die)?: "unknown"), dwarf_dieoffset(scope_die));
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
    4437                 :            : 
    4438         [ -  + ]:      11777 :   if (has_return)
    4439                 :            :     {
    4440                 :            :       /* Only save the return value if it has a type. */
    4441         [ #  # ]:          0 :       string type_name;
    4442                 :            :       Dwarf_Die type_die;
    4443 [ #  # ][ #  # ]:          0 :       if (dwarf_attr_die (scope_die, DW_AT_type, &type_die) &&
         [ #  # ][ #  # ]
    4444         [ #  # ]:          0 :           dwarf_type_name(&type_die, type_name))
    4445 [ #  # ][ #  # ]:          0 :         args.push_back("$return:"+type_name);
                 [ #  # ]
    4446                 :            : 
    4447         [ #  # ]:          0 :       else if (verbose)
    4448 [ #  # ][ #  # ]:          0 :         clog << _F("saveargs: failed to retrieve type name for return value (dieoffset: %s)\n",
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
    4449 [ #  # ][ #  # ]:          0 :                    lex_cast_hex(dwarf_dieoffset(scope_die)).c_str());
    4450                 :            :     }
    4451                 :            : 
    4452                 :            :   Dwarf_Die arg;
    4453         [ +  - ]:      11777 :   vector<Dwarf_Die> scopes = q.dw.getscopes(scope_die);
    4454         [ +  - ]:      23556 :   for (unsigned i = 0; i < scopes.size(); ++i)
    4455                 :            :     {
    4456 [ +  - ][ +  + ]:      23556 :       if (dwarf_tag(&scopes[i]) == DW_TAG_compile_unit)
    4457                 :      11777 :         break; // we don't want file-level variables
    4458 [ +  - ][ +  + ]:      11779 :       if (dwarf_child (&scopes[i], &arg) == 0)
    4459         [ +  + ]:      27887 :         do
    4460                 :            :           {
    4461 [ +  - ][ +  + ]:      27887 :             switch (dwarf_tag (&arg))
    4462                 :            :               {
    4463                 :            :               case DW_TAG_variable:
    4464                 :            :               case DW_TAG_formal_parameter:
    4465                 :      21681 :                 break;
    4466                 :            : 
    4467                 :            :               default:
    4468                 :       6206 :                 continue;
    4469                 :            :               }
    4470                 :            : 
    4471                 :            :             /* Ignore this local if it has no name. */
    4472         [ +  - ]:      21681 :             const char *arg_name = dwarf_diename (&arg);
    4473         [ +  + ]:      21681 :             if (!arg_name)
    4474                 :            :               {
    4475         [ -  + ]:        948 :                 if (verbose)
    4476 [ #  # ][ #  # ]:          0 :                   clog << _F("saveargs: failed to retrieve name for local (dieoffset: %s)\n",
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
    4477         [ #  # ]:          0 :                              lex_cast_hex(dwarf_dieoffset(&arg)).c_str());
    4478                 :        948 :                 continue;
    4479                 :            :               }
    4480                 :            : 
    4481         [ -  + ]:      20733 :             if (verbose)
    4482 [ #  # ][ #  # ]:          0 :               clog << _F("saveargs: finding location for local '%s' (dieoffset: %s)\n",
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
    4483         [ #  # ]:          0 :                          arg_name, lex_cast_hex(dwarf_dieoffset(&arg)).c_str());
    4484                 :            : 
    4485                 :            :             /* Ignore this local if it has no location (or not at this PC). */
    4486                 :            :             /* NB: It still may not be directly accessible, e.g. if it is an
    4487                 :            :              * aggregate type, implicit_pointer, etc., but the user can later
    4488                 :            :              * figure out how to access the interesting parts. */
    4489                 :            : 
    4490                 :            :             /* XXX: Perhaps saveargs() / listings-mode should work by synthesizing
    4491                 :            :              * several synthetic
    4492                 :            :              *     probe foo { $var }
    4493                 :            :              * probes, testing them for overall resolvability.
    4494                 :            :              */
    4495                 :            : 
    4496                 :            :             Dwarf_Attribute attr_mem;
    4497 [ +  - ][ +  + ]:      20733 :             if (!dwarf_attr_integrate (&arg, DW_AT_const_value, &attr_mem))
    4498                 :            :               {
    4499                 :            :                 Dwarf_Op *expr;
    4500                 :            :                 size_t len;
    4501 [ +  - ][ +  + ]:      20731 :                 if (!dwarf_attr_integrate (&arg, DW_AT_location, &attr_mem))
    4502                 :            :                   {
    4503         [ -  + ]:         44 :                     if (verbose)
    4504 [ #  # ][ #  # ]:          0 :                       clog << _F("saveargs: failed to resolve the location for local '%s' (dieoffset: %s)\n",
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
    4505         [ #  # ]:          0 :                                   arg_name, lex_cast_hex(dwarf_dieoffset(&arg)).c_str());
    4506                 :         44 :                     continue;
    4507                 :            :                   }
    4508         [ +  + ]:      20687 :                 else if (!(dwarf_getlocation_addr(&attr_mem, dwfl_addr, &expr,
    4509 [ +  - ][ +  + ]:      20687 :                                                   &len, 1) == 1 && len > 0))
                 [ -  + ]
    4510                 :            :                   {
    4511         [ +  - ]:        164 :                     Dwarf_Addr dwfl_addr2 = q.dw.pr15123_retry_addr (dwfl_addr, & arg);
    4512 [ -  + ][ #  # ]:        164 :                     if (!dwfl_addr2 || (!(dwarf_getlocation_addr(&attr_mem, dwfl_addr2, &expr,
                 [ +  - ]
    4513 [ #  # ][ #  # ]:          0 :                                                                  &len, 1) == 1 && len > 0))) {
    4514         [ -  + ]:        164 :                       if (verbose)
    4515 [ #  # ][ #  # ]:          0 :                         clog << _F("saveargs: local '%s' (dieoffset: %s) is not available at this address (%s)\n",
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
    4516         [ #  # ]:          0 :                                    arg_name, lex_cast_hex(dwarf_dieoffset(&arg)).c_str(), lex_cast_hex(dwfl_addr).c_str());
    4517                 :      20731 :                       continue;
    4518                 :            :                     }
    4519                 :            :                   }
    4520                 :            :               }
    4521                 :            : 
    4522                 :            :             /* Ignore this local if it has no type. */
    4523         [ +  - ]:      20525 :             string type_name;
    4524                 :            :             Dwarf_Die type_die;
    4525 [ +  - ][ +  - ]:      41050 :             if (!dwarf_attr_die (&arg, DW_AT_type, &type_die) ||
         [ -  + ][ -  + ]
    4526         [ +  - ]:      20525 :                 !dwarf_type_name(&type_die, type_name))
    4527                 :            :               {
    4528         [ #  # ]:          0 :                 if (verbose)
    4529 [ #  # ][ #  # ]:          0 :                   clog << _F("saveargs: failed to retrieve type name for local '%s' (dieoffset: %s)\n",
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
    4530         [ #  # ]:          0 :                              arg_name, lex_cast_hex(dwarf_dieoffset(&arg)).c_str());
    4531                 :          0 :                 continue;
    4532                 :            :               }
    4533                 :            : 
    4534                 :            :             /* This local looks good -- save it! */
    4535 [ +  - ][ +  - ]:      27887 :             args.push_back("$"+string(arg_name)+":"+type_name);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    4536                 :            :           }
    4537         [ +  - ]:      27887 :         while (dwarf_siblingof (&arg, &arg) == 0);
    4538         [ +  - ]:      11777 :     }
    4539                 :            : }
    4540                 :            : 
    4541                 :            : 
    4542                 :            : void
    4543                 :      11825 : dwarf_derived_probe::getargs(std::list<std::string> &arg_set) const
    4544                 :            : {
    4545                 :      11825 :   arg_set.insert(arg_set.end(), args.begin(), args.end());
    4546                 :      11825 : }
    4547                 :            : 
    4548                 :            : 
    4549                 :            : void
    4550                 :       6169 : dwarf_derived_probe::emit_privilege_assertion (translator_output* o)
    4551                 :            : {
    4552         [ -  + ]:       6169 :   if (has_process)
    4553                 :            :     {
    4554                 :            :       // These probes are allowed for unprivileged users, but only in the
    4555                 :            :       // context of processes which they own.
    4556                 :          0 :       emit_process_owner_assertion (o);
    4557                 :       6169 :       return;
    4558                 :            :     }
    4559                 :            : 
    4560                 :            :   // Other probes must contain the default assertion which aborts
    4561                 :            :   // if executed by an unprivileged user.
    4562                 :       6169 :   derived_probe::emit_privilege_assertion (o);
    4563                 :            : }
    4564                 :            : 
    4565                 :            : 
    4566                 :            : void
    4567                 :      25760 : dwarf_derived_probe::print_dupe_stamp(ostream& o)
    4568                 :            : {
    4569         [ -  + ]:      25760 :   if (has_process)
    4570                 :            :     {
    4571                 :            :       // These probes are allowed for unprivileged users, but only in the
    4572                 :            :       // context of processes which they own.
    4573                 :          0 :       print_dupe_stamp_unprivileged_process_owner (o);
    4574                 :      25760 :       return;
    4575                 :            :     }
    4576                 :            : 
    4577                 :            :   // Other probes must contain the default dupe stamp
    4578                 :      25760 :   derived_probe::print_dupe_stamp (o);
    4579                 :            : }
    4580                 :            : 
    4581                 :            : 
    4582                 :            : void
    4583                 :      14616 : dwarf_derived_probe::register_statement_variants(match_node * root,
    4584                 :            :                                                  dwarf_builder * dw,
    4585                 :            :                                                  privilege_t privilege)
    4586                 :            : {
    4587                 :            :   root
    4588                 :            :     ->bind_privilege(privilege)
    4589                 :      14616 :     ->bind(dw);
    4590                 :      14616 : }
    4591                 :            : 
    4592                 :            : void
    4593                 :      14616 : dwarf_derived_probe::register_function_variants(match_node * root,
    4594                 :            :                                                 dwarf_builder * dw,
    4595                 :            :                                                 privilege_t privilege)
    4596                 :            : {
    4597                 :            :   root
    4598                 :            :     ->bind_privilege(privilege)
    4599                 :      14616 :     ->bind(dw);
    4600                 :            :   root->bind(TOK_CALL)
    4601                 :            :     ->bind_privilege(privilege)
    4602                 :      14616 :     ->bind(dw);
    4603                 :            :   root->bind(TOK_EXPORTED)
    4604                 :            :     ->bind_privilege(privilege)
    4605                 :      14616 :     ->bind(dw);
    4606                 :            :   root->bind(TOK_RETURN)
    4607                 :            :     ->bind_privilege(privilege)
    4608                 :      14616 :     ->bind(dw);
    4609                 :            : 
    4610                 :            :   // For process probes / uprobes, .maxactive() is unused.
    4611         [ +  + ]:      14616 :   if (! pr_contains (privilege, pr_stapusr))
    4612                 :            :     {
    4613                 :            :       root->bind(TOK_RETURN)
    4614                 :       4872 :         ->bind_num(TOK_MAXACTIVE)->bind(dw);
    4615                 :            :     }
    4616                 :      14616 : }
    4617                 :            : 
    4618                 :            : void
    4619                 :       7308 : dwarf_derived_probe::register_function_and_statement_variants(
    4620                 :            :   systemtap_session& s,
    4621                 :            :   match_node * root,
    4622                 :            :   dwarf_builder * dw,
    4623                 :            :   privilege_t privilege
    4624                 :            : )
    4625                 :            : {
    4626                 :            :   // Here we match 4 forms:
    4627                 :            :   //
    4628                 :            :   // .function("foo")
    4629                 :            :   // .function(0xdeadbeef)
    4630                 :            :   // .statement("foo")
    4631                 :            :   // .statement(0xdeadbeef)
    4632                 :            : 
    4633                 :       7308 :   match_node *fv_root = root->bind_str(TOK_FUNCTION);
    4634                 :       7308 :   register_function_variants(fv_root, dw, privilege);
    4635                 :            :   // ROOT.function("STRING") always gets the .inline and .label variants.
    4636                 :            :   fv_root->bind(TOK_INLINE)
    4637                 :            :     ->bind_privilege(privilege)
    4638                 :       7308 :     ->bind(dw);
    4639                 :            :   fv_root->bind_str(TOK_LABEL)
    4640                 :            :     ->bind_privilege(privilege)
    4641                 :       7308 :     ->bind(dw);
    4642                 :            : 
    4643                 :       7308 :   fv_root = root->bind_num(TOK_FUNCTION);
    4644                 :       7308 :   register_function_variants(fv_root, dw, privilege);
    4645                 :            :   // ROOT.function(NUMBER).inline is deprecated in release 1.7 and removed thereafter.
    4646         [ +  + ]:       7308 :   if (strverscmp(s.compatible.c_str(), "1.7") <= 0)
    4647                 :            :     {
    4648                 :            :       fv_root->bind(TOK_INLINE)
    4649                 :            :         ->bind_privilege(privilege)
    4650                 :         42 :         ->bind(dw);
    4651                 :            :     }
    4652                 :            : 
    4653                 :       7308 :   register_statement_variants(root->bind_str(TOK_STATEMENT), dw, privilege);
    4654                 :       7308 :   register_statement_variants(root->bind_num(TOK_STATEMENT), dw, privilege);
    4655                 :       7308 : }
    4656                 :            : 
    4657                 :            : void
    4658                 :       4872 : dwarf_derived_probe::register_sdt_variants(systemtap_session& s,
    4659                 :            :                                            match_node * root,
    4660                 :            :                                            dwarf_builder * dw)
    4661                 :            : {
    4662                 :            :   root->bind_str(TOK_MARK)
    4663                 :            :     ->bind_privilege(pr_all)
    4664                 :       4872 :     ->bind(dw);
    4665                 :            :   root->bind_str(TOK_PROVIDER)->bind_str(TOK_MARK)
    4666                 :            :     ->bind_privilege(pr_all)
    4667                 :       4872 :     ->bind(dw);
    4668                 :       4872 : }
    4669                 :            : 
    4670                 :            : void
    4671                 :       4872 : dwarf_derived_probe::register_plt_variants(systemtap_session& s,
    4672                 :            :                                            match_node * root,
    4673                 :            :                                            dwarf_builder * dw)
    4674                 :            : {
    4675                 :            :   root->bind(TOK_PLT)
    4676                 :            :     ->bind_privilege(pr_all)
    4677                 :       4872 :     ->bind(dw);
    4678                 :            :   root->bind_str(TOK_PLT)
    4679                 :            :     ->bind_privilege(pr_all)
    4680                 :       4872 :     ->bind(dw);
    4681                 :            :   root->bind(TOK_PLT)->bind_num(TOK_STATEMENT)
    4682                 :            :     ->bind_privilege(pr_all)
    4683                 :       4872 :     ->bind(dw);
    4684                 :            :   root->bind_str(TOK_PLT)->bind_num(TOK_STATEMENT)
    4685                 :            :     ->bind_privilege(pr_all)
    4686                 :       4872 :     ->bind(dw);
    4687                 :       4872 : }
    4688                 :            : 
    4689                 :            : void
    4690                 :       1218 : dwarf_derived_probe::register_patterns(systemtap_session& s)
    4691                 :            : {
    4692                 :       1218 :   match_node* root = s.pattern_root;
    4693 [ +  - ][ +  - ]:       1218 :   dwarf_builder *dw = new dwarf_builder();
    4694                 :            : 
    4695 [ +  - ][ +  - ]:       1218 :   update_visitor *filter = new dwarf_cast_expanding_visitor(s, *dw);
    4696         [ +  - ]:       1218 :   s.code_filters.push_back(filter);
    4697                 :            : 
    4698 [ +  - ][ +  - ]:       1218 :   register_function_and_statement_variants(s, root->bind(TOK_KERNEL), dw, pr_privileged);
    4699 [ +  - ][ +  - ]:       1218 :   register_function_and_statement_variants(s, root->bind_str(TOK_MODULE), dw, pr_privileged);
    4700                 :            :   root->bind(TOK_KERNEL)->bind_num(TOK_STATEMENT)->bind(TOK_ABSOLUTE)
    4701 [ +  - ][ +  - ]:       1218 :     ->bind(dw);
         [ +  - ][ +  - ]
    4702                 :            : 
    4703                 :            :   match_node* uprobes[] = {
    4704         [ +  - ]:       1218 :       root->bind(TOK_PROCESS),
    4705         [ +  - ]:       1218 :       root->bind_str(TOK_PROCESS),
    4706 [ +  - ][ +  - ]:       1218 :       root->bind(TOK_PROCESS)->bind_str(TOK_LIBRARY),
    4707 [ +  - ][ +  - ]:       1218 :       root->bind_str(TOK_PROCESS)->bind_str(TOK_LIBRARY),
    4708                 :       4872 :   };
    4709         [ +  + ]:       6090 :   for (size_t i = 0; i < sizeof(uprobes) / sizeof(*uprobes); ++i)
    4710                 :            :     {
    4711         [ +  - ]:       4872 :       register_function_and_statement_variants(s, uprobes[i], dw, pr_all);
    4712         [ +  - ]:       4872 :       register_sdt_variants(s, uprobes[i], dw);
    4713         [ +  - ]:       4872 :       register_plt_variants(s, uprobes[i], dw);
    4714                 :            :     }
    4715                 :       1218 : }
    4716                 :            : 
    4717                 :            : void
    4718                 :       6175 : dwarf_derived_probe::emit_probe_local_init(systemtap_session& s, translator_output * o)
    4719                 :            : {
    4720                 :       6175 :   std::set<derived_probe*>::iterator pcii;
    4721 [ +  - ][ +  + ]:      12352 :   for (pcii = perf_counter_refs.begin();
    4722         [ +  - ]:       6176 :        pcii != perf_counter_refs.end();
    4723                 :            :        pcii++)
    4724                 :            :     {
    4725                 :          1 :       map<string, pair<string,derived_probe*> >::iterator it;
    4726                 :            :       // Find the associated perf.counter probe
    4727                 :          1 :       unsigned i = 0;
    4728 [ +  - ][ +  - ]:          2 :       for (it=s.perf_counters.begin() ;
    4729         [ +  - ]:          1 :            it != s.perf_counters.end();
    4730                 :            :            it++, i++)
    4731         [ +  - ]:          1 :         if ((*it).second.second == (*pcii))
    4732                 :          1 :           break;
    4733                 :            :       // place the perf counter read so it precedes stp_lock_probe
    4734         [ +  - ]:          1 :       o->newline() << "l->l___perf_read_" + (*it).first
    4735                 :            :         + " = (((int64_t) (_stp_perf_read(smp_processor_id(),"
    4736 [ +  - ][ +  - ]:          1 :         + lex_cast(i) + "))));";
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    4737                 :            :     }
    4738                 :            :   
    4739         [ +  + ]:       6175 :   if (access_vars)
    4740                 :            :     {
    4741                 :            :       // if accessing $variables, emit bsp cache setup for speeding up
    4742 [ +  - ][ +  - ]:       5161 :       o->newline() << "#if defined __ia64__";
    4743 [ +  - ][ +  - ]:       5161 :       o->newline() << "bspcache(c->unwaddr, c->kregs);";
    4744 [ +  - ][ +  - ]:       5161 :       o->newline() << "#endif";
    4745                 :            :     }
    4746                 :       6175 : }
    4747                 :            : 
    4748                 :            : // ------------------------------------------------------------------------
    4749                 :            : 
    4750                 :            : void
    4751                 :     317756 : dwarf_derived_probe_group::enroll (dwarf_derived_probe* p)
    4752                 :            : {
    4753 [ +  - ][ +  - ]:     317756 :   probes_by_module.insert (make_pair (p->module, p));
         [ +  - ][ +  - ]
                 [ +  - ]
    4754                 :            : 
    4755                 :            :   // XXX: probes put at the same address should all share a
    4756                 :            :   // single kprobe/kretprobe, and have their handlers executed
    4757                 :            :   // sequentially.
    4758                 :     317756 : }
    4759                 :            : 
    4760                 :            : void
    4761                 :        207 : dwarf_derived_probe_group::emit_module_decls (systemtap_session& s)
    4762                 :            : {
    4763 [ +  - ][ +  - ]:        414 :   if (probes_by_module.empty()) return;
    4764                 :            : 
    4765 [ +  - ][ +  - ]:        207 :   s.op->newline() << "/* ---- dwarf probes ---- */";
    4766                 :            : 
    4767                 :            :   // Warn of misconfigured kernels
    4768 [ +  - ][ +  - ]:        207 :   s.op->newline() << "#if ! defined(CONFIG_KPROBES)";
    4769 [ +  - ][ +  - ]:        207 :   s.op->newline() << "#error \"Need CONFIG_KPROBES!\"";
    4770 [ +  - ][ +  - ]:        207 :   s.op->newline() << "#endif";
    4771         [ +  - ]:        207 :   s.op->newline();
    4772                 :            : 
    4773 [ +  - ][ +  - ]:        207 :   s.op->newline() << "#ifndef KRETACTIVE";
    4774 [ +  - ][ +  - ]:        207 :   s.op->newline() << "#define KRETACTIVE (max(15,6*(int)num_possible_cpus()))";
    4775 [ +  - ][ +  - ]:        207 :   s.op->newline() << "#endif";
    4776                 :            : 
    4777                 :            :   // Forward decls
    4778 [ +  - ][ +  - ]:        207 :   s.op->newline() << "#include \"linux/kprobes-common.h\"";
    4779                 :            : 
    4780                 :            :   // Forward declare the master entry functions
    4781 [ +  - ][ +  - ]:        207 :   s.op->newline() << "static int enter_kprobe_probe (struct kprobe *inst,";
    4782 [ +  - ][ +  - ]:        207 :   s.op->line() << " struct pt_regs *regs);";
    4783 [ +  - ][ +  - ]:        207 :   s.op->newline() << "static int enter_kretprobe_probe (struct kretprobe_instance *inst,";
    4784 [ +  - ][ +  - ]:        207 :   s.op->line() << " struct pt_regs *regs);";
    4785                 :            : 
    4786                 :            :   // Emit an array of kprobe/kretprobe pointers
    4787 [ +  - ][ +  - ]:        207 :   s.op->newline() << "#if defined(STAPCONF_UNREGISTER_KPROBES)";
    4788 [ +  - ][ +  - ]:        207 :   s.op->newline() << "static void * stap_unreg_kprobes[" << probes_by_module.size() << "];";
         [ +  - ][ +  - ]
                 [ +  - ]
    4789 [ +  - ][ +  - ]:        207 :   s.op->newline() << "#endif";
    4790                 :            : 
    4791                 :            :   // Emit the actual probe list.
    4792                 :            : 
    4793                 :            :   // NB: we used to plop a union { struct kprobe; struct kretprobe } into
    4794                 :            :   // struct stap_dwarf_probe, but it being initialized data makes it add
    4795                 :            :   // hundreds of bytes of padding per stap_dwarf_probe.  (PR5673)
    4796 [ +  - ][ +  - ]:        207 :   s.op->newline() << "static struct stap_dwarf_kprobe stap_dwarf_kprobes[" << probes_by_module.size() << "];";
         [ +  - ][ +  - ]
                 [ +  - ]
    4797                 :            :   // NB: bss!
    4798                 :            : 
    4799 [ +  - ][ +  - ]:        207 :   s.op->newline() << "static struct stap_dwarf_probe {";
    4800 [ +  - ][ +  - ]:        207 :   s.op->newline(1) << "const unsigned return_p:1;";
    4801 [ +  - ][ +  - ]:        207 :   s.op->newline() << "const unsigned maxactive_p:1;";
    4802 [ +  - ][ +  - ]:        207 :   s.op->newline() << "const unsigned optional_p:1;";
    4803 [ +  - ][ +  - ]:        207 :   s.op->newline() << "unsigned registered_p:1;";
    4804 [ +  - ][ +  - ]:        207 :   s.op->newline() << "const unsigned short maxactive_val;";
    4805                 :            : 
    4806                 :            :   // data saved in the kretprobe_instance packet
    4807 [ +  - ][ +  - ]:        207 :   s.op->newline() << "const unsigned short saved_longs;";
    4808 [ +  - ][ +  - ]:        207 :   s.op->newline() << "const unsigned short saved_strings;";
    4809                 :            : 
    4810                 :            :   // Let's find some stats for the embedded strings.  Maybe they
    4811                 :            :   // are small and uniform enough to justify putting char[MAX]'s into
    4812                 :            :   // the array instead of relocated char*'s.
    4813                 :        207 :   size_t module_name_max = 0, section_name_max = 0;
    4814                 :        207 :   size_t module_name_tot = 0, section_name_tot = 0;
    4815         [ +  - ]:        207 :   size_t all_name_cnt = probes_by_module.size(); // for average
    4816 [ +  - ][ +  - ]:      12879 :   for (p_b_m_iterator it = probes_by_module.begin(); it != probes_by_module.end(); it++)
                 [ +  + ]
    4817                 :            :     {
    4818         [ +  - ]:      12672 :       dwarf_derived_probe* p = it->second;
    4819                 :            : #define DOIT(var,expr) do {                             \
    4820                 :            :         size_t var##_size = (expr) + 1;                 \
    4821                 :            :         var##_max = max (var##_max, var##_size);        \
    4822                 :            :         var##_tot += var##_size; } while (0)
    4823         [ +  - ]:      12672 :       DOIT(module_name, p->module.size());
    4824         [ +  - ]:      12672 :       DOIT(section_name, p->section.size());
    4825                 :            : #undef DOIT
    4826                 :            :     }
    4827                 :            : 
    4828                 :            :   // Decide whether it's worthwhile to use char[] or char* by comparing
    4829                 :            :   // the amount of average waste (max - avg) to the relocation data size
    4830                 :            :   // (3 native long words).
    4831                 :            : #define CALCIT(var)                                                     \
    4832                 :            :   if ((var##_name_max-(var##_name_tot/all_name_cnt)) < (3 * sizeof(void*))) \
    4833                 :            :     {                                                                   \
    4834                 :            :       s.op->newline() << "const char " << #var << "[" << var##_name_max << "];"; \
    4835                 :            :       if (s.verbose > 2) clog << "stap_dwarf_probe " << #var            \
    4836                 :            :                               << "[" << var##_name_max << "]" << endl;  \
    4837                 :            :     }                                                                   \
    4838                 :            :   else                                                                  \
    4839                 :            :     {                                                                   \
    4840                 :            :       s.op->newline() << "const char * const " << #var << ";";                 \
    4841                 :            :       if (s.verbose > 2) clog << "stap_dwarf_probe *" << #var << endl;  \
    4842                 :            :     }
    4843                 :            : 
    4844 [ +  - ][ +  - ]:        207 :   CALCIT(module);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ -  + ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
    4845 [ +  - ][ +  - ]:        207 :   CALCIT(section);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ -  + ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
    4846                 :            : #undef CALCIT
    4847                 :            : 
    4848 [ +  - ][ +  - ]:        207 :   s.op->newline() << "const unsigned long address;";
    4849 [ +  - ][ +  - ]:        207 :   s.op->newline() << "const struct stap_probe * const probe;";
    4850 [ +  - ][ +  - ]:        207 :   s.op->newline() << "const struct stap_probe * const entry_probe;";
    4851 [ +  - ][ +  - ]:        207 :   s.op->newline(-1) << "} stap_dwarf_probes[] = {";
    4852         [ +  - ]:        207 :   s.op->indent(1);
    4853                 :            : 
    4854 [ +  - ][ +  - ]:      12879 :   for (p_b_m_iterator it = probes_by_module.begin(); it != probes_by_module.end(); it++)
                 [ +  + ]
    4855                 :            :     {
    4856         [ +  - ]:      12672 :       dwarf_derived_probe* p = it->second;
    4857 [ +  - ][ +  - ]:      12672 :       s.op->newline() << "{";
    4858         [ +  + ]:      12672 :       if (p->has_return)
    4859 [ +  - ][ +  - ]:       4082 :         s.op->line() << " .return_p=1,";
    4860         [ +  + ]:      12672 :       if (p->has_maxactive)
    4861                 :            :         {
    4862 [ +  - ][ +  - ]:         13 :           s.op->line() << " .maxactive_p=1,";
    4863 [ +  - ][ -  + ]:         13 :           assert (p->maxactive_val >= 0 && p->maxactive_val <= USHRT_MAX);
    4864 [ +  - ][ +  - ]:         13 :           s.op->line() << " .maxactive_val=" << p->maxactive_val << ",";
         [ +  - ][ +  - ]
    4865                 :            :         }
    4866 [ +  + ][ -  + ]:      12672 :       if (p->saved_longs || p->saved_strings)
    4867                 :            :         {
    4868         [ +  - ]:        208 :           if (p->saved_longs)
    4869 [ +  - ][ +  - ]:        208 :             s.op->line() << " .saved_longs=" << p->saved_longs << ",";
         [ +  - ][ +  - ]
    4870         [ +  + ]:        208 :           if (p->saved_strings)
    4871 [ +  - ][ +  - ]:          1 :             s.op->line() << " .saved_strings=" << p->saved_strings << ",";
         [ +  - ][ +  - ]
    4872         [ +  - ]:        208 :           if (p->entry_handler)
    4873 [ +  - ][ +  - ]:        208 :             s.op->line() << " .entry_probe=" << common_probe_init (p->entry_handler) << ",";
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
    4874                 :            :         }
    4875         [ +  + ]:      12672 :       if (p->locations[0]->optional)
    4876 [ +  - ][ +  - ]:       4089 :         s.op->line() << " .optional_p=1,";
    4877 [ +  - ][ +  - ]:      12672 :       s.op->line() << " .address=(unsigned long)0x" << hex << p->addr << dec << "ULL,";
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
    4878 [ +  - ][ +  - ]:      12672 :       s.op->line() << " .module=\"" << p->module << "\",";
         [ +  - ][ +  - ]
    4879 [ +  - ][ +  - ]:      12672 :       s.op->line() << " .section=\"" << p->section << "\",";
         [ +  - ][ +  - ]
    4880 [ +  - ][ +  - ]:      12672 :       s.op->line() << " .probe=" << common_probe_init (p) << ",";
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
    4881 [ +  - ][ +  - ]:      12672 :       s.op->line() << " },";
    4882                 :            :     }
    4883                 :            : 
    4884 [ +  - ][ +  - ]:        207 :   s.op->newline(-1) << "};";
    4885                 :            : 
    4886                 :            :   // Emit the kprobes callback function
    4887         [ +  - ]:        207 :   s.op->newline();
    4888 [ +  - ][ +  - ]:        207 :   s.op->newline() << "static int enter_kprobe_probe (struct kprobe *inst,";
    4889 [ +  - ][ +  - ]:        207 :   s.op->line() << " struct pt_regs *regs) {";
    4890                 :            :   // NB: as of PR5673, the kprobe|kretprobe union struct is in BSS
    4891 [ +  - ][ +  - ]:        207 :   s.op->newline(1) << "int kprobe_idx = ((uintptr_t)inst-(uintptr_t)stap_dwarf_kprobes)/sizeof(struct stap_dwarf_kprobe);";
    4892                 :            :   // Check that the index is plausible
    4893 [ +  - ][ +  - ]:        207 :   s.op->newline() << "struct stap_dwarf_probe *sdp = &stap_dwarf_probes[";
    4894 [ +  - ][ +  - ]:        207 :   s.op->line() << "((kprobe_idx >= 0 && kprobe_idx < " << probes_by_module.size() << ")?";
         [ +  - ][ +  - ]
                 [ +  - ]
    4895 [ +  - ][ +  - ]:        207 :   s.op->line() << "kprobe_idx:0)"; // NB: at least we avoid memory corruption
    4896                 :            :   // XXX: it would be nice to give a more verbose error though; BUG_ON later?
    4897 [ +  - ][ +  - ]:        207 :   s.op->line() << "];";
    4898                 :            :   common_probe_entryfn_prologue (s, "STAP_SESSION_RUNNING", "sdp->probe",
    4899 [ +  - ][ +  - ]:        207 :                                  "stp_probe_type_kprobe");
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    4900 [ +  - ][ +  - ]:        207 :   s.op->newline() << "c->kregs = regs;";
    4901                 :            : 
    4902                 :            :   // Make it look like the IP is set as it wouldn't have been replaced
    4903                 :            :   // by a breakpoint instruction when calling real probe handler. Reset
    4904                 :            :   // IP regs on return, so we don't confuse kprobes. PR10458
    4905 [ +  - ][ +  - ]:        207 :   s.op->newline() << "{";
    4906         [ +  - ]:        207 :   s.op->indent(1);
    4907 [ +  - ][ +  - ]:        207 :   s.op->newline() << "unsigned long kprobes_ip = REG_IP(c->kregs);";
    4908 [ +  - ][ +  - ]:        207 :   s.op->newline() << "SET_REG_IP(regs, (unsigned long) inst->addr);";
    4909 [ +  - ][ +  - ]:        207 :   s.op->newline() << "(*sdp->probe->ph) (c);";
    4910 [ +  - ][ +  - ]:        207 :   s.op->newline() << "SET_REG_IP(regs, kprobes_ip);";
    4911 [ +  - ][ +  - ]:        207 :   s.op->newline(-1) << "}";
    4912                 :            : 
    4913         [ +  - ]:        207 :   common_probe_entryfn_epilogue (s, true);
    4914 [ +  - ][ +  - ]:        207 :   s.op->newline() << "return 0;";
    4915 [ +  - ][ +  - ]:        207 :   s.op->newline(-1) << "}";
    4916                 :            : 
    4917                 :            :   // Same for kretprobes
    4918         [ +  - ]:        207 :   s.op->newline();
    4919 [ +  - ][ +  - ]:        207 :   s.op->newline() << "static int enter_kretprobe_common (struct kretprobe_instance *inst,";
    4920 [ +  - ][ +  - ]:        207 :   s.op->line() << " struct pt_regs *regs, int entry) {";
    4921 [ +  - ][ +  - ]:        207 :   s.op->newline(1) << "struct kretprobe *krp = inst->rp;";
    4922                 :            : 
    4923                 :            :   // NB: as of PR5673, the kprobe|kretprobe union struct is in BSS
    4924 [ +  - ][ +  - ]:        207 :   s.op->newline() << "int kprobe_idx = ((uintptr_t)krp-(uintptr_t)stap_dwarf_kprobes)/sizeof(struct stap_dwarf_kprobe);";
    4925                 :            :   // Check that the index is plausible
    4926 [ +  - ][ +  - ]:        207 :   s.op->newline() << "struct stap_dwarf_probe *sdp = &stap_dwarf_probes[";
    4927 [ +  - ][ +  - ]:        207 :   s.op->line() << "((kprobe_idx >= 0 && kprobe_idx < " << probes_by_module.size() << ")?";
         [ +  - ][ +  - ]
                 [ +  - ]
    4928 [ +  - ][ +  - ]:        207 :   s.op->line() << "kprobe_idx:0)"; // NB: at least we avoid memory corruption
    4929                 :            :   // XXX: it would be nice to give a more verbose error though; BUG_ON later?
    4930 [ +  - ][ +  - ]:        207 :   s.op->line() << "];";
    4931                 :            : 
    4932 [ +  - ][ +  - ]:        207 :   s.op->newline() << "const struct stap_probe *sp = entry ? sdp->entry_probe : sdp->probe;";
    4933 [ +  - ][ +  - ]:        207 :   s.op->newline() << "if (sp) {";
    4934         [ +  - ]:        207 :   s.op->indent(1);
    4935                 :            :   common_probe_entryfn_prologue (s, "STAP_SESSION_RUNNING", "sp",
    4936 [ +  - ][ +  - ]:        207 :                                  "stp_probe_type_kretprobe");
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    4937 [ +  - ][ +  - ]:        207 :   s.op->newline() << "c->kregs = regs;";
    4938                 :            : 
    4939                 :            :   // for assisting runtime's backtrace logic and accessing kretprobe data packets
    4940 [ +  - ][ +  - ]:        207 :   s.op->newline() << "c->ips.krp.pi = inst;";
    4941 [ +  - ][ +  - ]:        207 :   s.op->newline() << "c->ips.krp.pi_longs = sdp->saved_longs;";
    4942                 :            : 
    4943                 :            :   // Make it look like the IP is set as it wouldn't have been replaced
    4944                 :            :   // by a breakpoint instruction when calling real probe handler. Reset
    4945                 :            :   // IP regs on return, so we don't confuse kprobes. PR10458
    4946 [ +  - ][ +  - ]:        207 :   s.op->newline() << "{";
    4947 [ +  - ][ +  - ]:        207 :   s.op->newline(1) << "unsigned long kprobes_ip = REG_IP(c->kregs);";
    4948 [ +  - ][ +  - ]:        207 :   s.op->newline() << "if (entry)";
    4949 [ +  - ][ +  - ]:        207 :   s.op->newline(1) << "SET_REG_IP(regs, (unsigned long) inst->rp->kp.addr);";
    4950 [ +  - ][ +  - ]:        207 :   s.op->newline(-1) << "else";
    4951 [ +  - ][ +  - ]:        207 :   s.op->newline(1) << "SET_REG_IP(regs, (unsigned long)inst->ret_addr);";
    4952 [ +  - ][ +  - ]:        207 :   s.op->newline(-1) << "(sp->ph) (c);";
    4953 [ +  - ][ +  - ]:        207 :   s.op->newline() << "SET_REG_IP(regs, kprobes_ip);";
    4954 [ +  - ][ +  - ]:        207 :   s.op->newline(-1) << "}";
    4955                 :            : 
    4956         [ +  - ]:        207 :   common_probe_entryfn_epilogue (s, true);
    4957 [ +  - ][ +  - ]:        207 :   s.op->newline(-1) << "}";
    4958 [ +  - ][ +  - ]:        207 :   s.op->newline() << "return 0;";
    4959 [ +  - ][ +  - ]:        207 :   s.op->newline(-1) << "}";
    4960                 :            : 
    4961         [ +  - ]:        207 :   s.op->newline();
    4962 [ +  - ][ +  - ]:        207 :   s.op->newline() << "static int enter_kretprobe_probe (struct kretprobe_instance *inst,";
    4963 [ +  - ][ +  - ]:        207 :   s.op->line() << " struct pt_regs *regs) {";
    4964 [ +  - ][ +  - ]:        207 :   s.op->newline(1) << "return enter_kretprobe_common(inst, regs, 0);";
    4965 [ +  - ][ +  - ]:        207 :   s.op->newline(-1) << "}";
    4966                 :            : 
    4967         [ +  - ]:        207 :   s.op->newline();
    4968 [ +  - ][ +  - ]:        207 :   s.op->newline() << "static int enter_kretprobe_entry_probe (struct kretprobe_instance *inst,";
    4969 [ +  - ][ +  - ]:        207 :   s.op->line() << " struct pt_regs *regs) {";
    4970 [ +  - ][ +  - ]:        207 :   s.op->newline(1) << "return enter_kretprobe_common(inst, regs, 1);";
    4971 [ +  - ][ +  - ]:        207 :   s.op->newline(-1) << "}";
    4972                 :            : 
    4973         [ +  - ]:        207 :   s.op->newline();
    4974                 :            : }
    4975                 :            : 
    4976                 :            : 
    4977                 :            : void
    4978                 :        207 : dwarf_derived_probe_group::emit_module_init (systemtap_session& s)
    4979                 :            : {
    4980                 :        207 :   s.op->newline() << "for (i=0; i<" << probes_by_module.size() << "; i++) {";
    4981                 :        207 :   s.op->newline(1) << "struct stap_dwarf_probe *sdp = & stap_dwarf_probes[i];";
    4982                 :        207 :   s.op->newline() << "struct stap_dwarf_kprobe *kp = & stap_dwarf_kprobes[i];";
    4983                 :        207 :   s.op->newline() << "unsigned long relocated_addr = _stp_kmodule_relocate (sdp->module, sdp->section, sdp->address);";
    4984                 :        207 :   s.op->newline() << "if (relocated_addr == 0) continue;"; // quietly; assume module is absent
    4985                 :        207 :   s.op->newline() << "probe_point = sdp->probe->pp;"; // for error messages
    4986                 :        207 :   s.op->newline() << "if (sdp->return_p) {";
    4987                 :        207 :   s.op->newline(1) << "kp->u.krp.kp.addr = (void *) relocated_addr;";
    4988                 :        207 :   s.op->newline() << "if (sdp->maxactive_p) {";
    4989                 :        207 :   s.op->newline(1) << "kp->u.krp.maxactive = sdp->maxactive_val;";
    4990                 :        207 :   s.op->newline(-1) << "} else {";
    4991                 :        207 :   s.op->newline(1) << "kp->u.krp.maxactive = KRETACTIVE;";
    4992                 :        207 :   s.op->newline(-1) << "}";
    4993                 :        207 :   s.op->newline() << "kp->u.krp.handler = &enter_kretprobe_probe;";
    4994                 :        207 :   s.op->newline() << "#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,25)";
    4995                 :        207 :   s.op->newline() << "if (sdp->entry_probe) {";
    4996                 :        207 :   s.op->newline(1) << "kp->u.krp.entry_handler = &enter_kretprobe_entry_probe;";
    4997                 :        207 :   s.op->newline() << "kp->u.krp.data_size = sdp->saved_longs * sizeof(int64_t) + ";
    4998                 :        207 :   s.op->newline() << "                      sdp->saved_strings * MAXSTRINGLEN;";
    4999                 :        207 :   s.op->newline(-1) << "}";
    5000                 :        207 :   s.op->newline() << "#endif";
    5001                 :            :   // to ensure safeness of bspcache, always use aggr_kprobe on ia64
    5002                 :        207 :   s.op->newline() << "#ifdef __ia64__";
    5003                 :        207 :   s.op->newline() << "kp->dummy.addr = kp->u.krp.kp.addr;";
    5004                 :        207 :   s.op->newline() << "kp->dummy.pre_handler = NULL;";
    5005                 :        207 :   s.op->newline() << "rc = register_kprobe (& kp->dummy);";
    5006                 :        207 :   s.op->newline() << "if (rc == 0) {";
    5007                 :        207 :   s.op->newline(1) << "rc = register_kretprobe (& kp->u.krp);";
    5008                 :        207 :   s.op->newline() << "if (rc != 0)";
    5009                 :        207 :   s.op->newline(1) << "unregister_kprobe (& kp->dummy);";
    5010                 :        207 :   s.op->newline(-2) << "}";
    5011                 :        207 :   s.op->newline() << "#else";
    5012                 :        207 :   s.op->newline() << "rc = register_kretprobe (& kp->u.krp);";
    5013                 :        207 :   s.op->newline() << "#endif";
    5014                 :        207 :   s.op->newline(-1) << "} else {";
    5015                 :            :   // to ensure safeness of bspcache, always use aggr_kprobe on ia64
    5016                 :        207 :   s.op->newline(1) << "kp->u.kp.addr = (void *) relocated_addr;";
    5017                 :        207 :   s.op->newline() << "kp->u.kp.pre_handler = &enter_kprobe_probe;";
    5018                 :        207 :   s.op->newline() << "#ifdef __ia64__";
    5019                 :        207 :   s.op->newline() << "kp->dummy.addr = kp->u.kp.addr;";
    5020                 :        207 :   s.op->newline() << "kp->dummy.pre_handler = NULL;";
    5021                 :        207 :   s.op->newline() << "rc = register_kprobe (& kp->dummy);";
    5022                 :        207 :   s.op->newline() << "if (rc == 0) {";
    5023                 :        207 :   s.op->newline(1) << "rc = register_kprobe (& kp->u.kp);";
    5024                 :        207 :   s.op->newline() << "if (rc != 0)";
    5025                 :        207 :   s.op->newline(1) << "unregister_kprobe (& kp->dummy);";
    5026                 :        207 :   s.op->newline(-2) << "}";
    5027                 :        207 :   s.op->newline() << "#else";
    5028                 :        207 :   s.op->newline() << "rc = register_kprobe (& kp->u.kp);";
    5029                 :        207 :   s.op->newline() << "#endif";
    5030                 :        207 :   s.op->newline(-1) << "}";
    5031                 :        207 :   s.op->newline() << "if (rc) {"; // PR6749: tolerate a failed register_*probe.
    5032                 :        207 :   s.op->newline(1) << "sdp->registered_p = 0;";
    5033                 :        207 :   s.op->newline() << "if (!sdp->optional_p)";
    5034                 :        207 :   s.op->newline(1) << "_stp_warn (\"probe %s (address 0x%lx) registration error (rc %d)\", probe_point, (unsigned long) relocated_addr, rc);";
    5035                 :        207 :   s.op->newline(-1) << "rc = 0;"; // continue with other probes
    5036                 :            :   // XXX: shall we increment numskipped?
    5037                 :        207 :   s.op->newline(-1) << "}";
    5038                 :            : 
    5039                 :            : #if 0 /* pre PR 6749; XXX consider making an option */
    5040                 :            :   s.op->newline(1) << "for (j=i-1; j>=0; j--) {"; // partial rollback
    5041                 :            :   s.op->newline(1) << "struct stap_dwarf_probe *sdp2 = & stap_dwarf_probes[j];";
    5042                 :            :   s.op->newline() << "struct stap_dwarf_kprobe *kp2 = & stap_dwarf_kprobes[j];";
    5043                 :            :   s.op->newline() << "if (sdp2->return_p) unregister_kretprobe (&kp2->u.krp);";
    5044                 :            :   s.op->newline() << "else unregister_kprobe (&kp2->u.kp);";
    5045                 :            :   s.op->newline() << "#ifdef __ia64__";
    5046                 :            :   s.op->newline() << "unregister_kprobe (&kp2->dummy);";
    5047                 :            :   s.op->newline() << "#endif";
    5048                 :            :   // NB: we don't have to clear sdp2->registered_p, since the module_exit code is
    5049                 :            :   // not run for this early-abort case.
    5050                 :            :   s.op->newline(-1) << "}";
    5051                 :            :   s.op->newline() << "break;"; // don't attempt to register any more probes
    5052                 :            :   s.op->newline(-1) << "}";
    5053                 :            : #endif
    5054                 :            : 
    5055                 :        207 :   s.op->newline() << "else sdp->registered_p = 1;";
    5056                 :        207 :   s.op->newline(-1) << "}"; // for loop
    5057                 :        207 : }
    5058                 :            : 
    5059                 :            : 
    5060                 :            : void
    5061                 :        207 : dwarf_derived_probe_group::emit_module_refresh (systemtap_session& s)
    5062                 :            : {
    5063                 :        207 :   s.op->newline() << "for (i=0; i<" << probes_by_module.size() << "; i++) {";
    5064                 :        207 :   s.op->newline(1) << "struct stap_dwarf_probe *sdp = & stap_dwarf_probes[i];";
    5065                 :        207 :   s.op->newline() << "struct stap_dwarf_kprobe *kp = & stap_dwarf_kprobes[i];";
    5066                 :        207 :   s.op->newline() << "unsigned long relocated_addr = _stp_kmodule_relocate (sdp->module, sdp->section, sdp->address);";
    5067                 :        207 :   s.op->newline() << "int rc;";
    5068                 :            : 
    5069                 :            :   // new module arrived?
    5070                 :        207 :   s.op->newline() << "if (sdp->registered_p == 0 && relocated_addr != 0) {";
    5071                 :        207 :   s.op->newline(1) << "if (sdp->return_p) {";
    5072                 :        207 :   s.op->newline(1) << "kp->u.krp.kp.addr = (void *) relocated_addr;";
    5073                 :        207 :   s.op->newline() << "if (sdp->maxactive_p) {";
    5074                 :        207 :   s.op->newline(1) << "kp->u.krp.maxactive = sdp->maxactive_val;";
    5075                 :        207 :   s.op->newline(-1) << "} else {";
    5076                 :        207 :   s.op->newline(1) << "kp->u.krp.maxactive = KRETACTIVE;";
    5077                 :        207 :   s.op->newline(-1) << "}";
    5078                 :        207 :   s.op->newline() << "kp->u.krp.handler = &enter_kretprobe_probe;";
    5079                 :        207 :   s.op->newline() << "#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,25)";
    5080                 :        207 :   s.op->newline() << "if (sdp->entry_probe) {";
    5081                 :        207 :   s.op->newline(1) << "kp->u.krp.entry_handler = &enter_kretprobe_entry_probe;";
    5082                 :        207 :   s.op->newline() << "kp->u.krp.data_size = sdp->saved_longs * sizeof(int64_t) + ";
    5083                 :        207 :   s.op->newline() << "                      sdp->saved_strings * MAXSTRINGLEN;";
    5084                 :        207 :   s.op->newline(-1) << "}";
    5085                 :        207 :   s.op->newline() << "#endif";
    5086                 :            :   // to ensure safeness of bspcache, always use aggr_kprobe on ia64
    5087                 :        207 :   s.op->newline() << "#ifdef __ia64__";
    5088                 :        207 :   s.op->newline() << "kp->dummy.addr = kp->u.krp.kp.addr;";
    5089                 :        207 :   s.op->newline() << "kp->dummy.pre_handler = NULL;";
    5090                 :        207 :   s.op->newline() << "rc = register_kprobe (& kp->dummy);";
    5091                 :        207 :   s.op->newline() << "if (rc == 0) {";
    5092                 :        207 :   s.op->newline(1) << "rc = register_kretprobe (& kp->u.krp);";
    5093                 :        207 :   s.op->newline() << "if (rc != 0)";
    5094                 :        207 :   s.op->newline(1) << "unregister_kprobe (& kp->dummy);";
    5095                 :        207 :   s.op->newline(-2) << "}";
    5096                 :        207 :   s.op->newline() << "#else";
    5097                 :        207 :   s.op->newline() << "rc = register_kretprobe (& kp->u.krp);";
    5098                 :        207 :   s.op->newline() << "#endif";
    5099                 :        207 :   s.op->newline(-1) << "} else {";
    5100                 :            :   // to ensure safeness of bspcache, always use aggr_kprobe on ia64
    5101                 :        207 :   s.op->newline(1) << "kp->u.kp.addr = (void *) relocated_addr;";
    5102                 :        207 :   s.op->newline() << "kp->u.kp.pre_handler = &enter_kprobe_probe;";
    5103                 :        207 :   s.op->newline() << "#ifdef __ia64__";
    5104                 :        207 :   s.op->newline() << "kp->dummy.addr = kp->u.kp.addr;";
    5105                 :        207 :   s.op->newline() << "kp->dummy.pre_handler = NULL;";
    5106                 :        207 :   s.op->newline() << "rc = register_kprobe (& kp->dummy);";
    5107                 :        207 :   s.op->newline() << "if (rc == 0) {";
    5108                 :        207 :   s.op->newline(1) << "rc = register_kprobe (& kp->u.kp);";
    5109                 :        207 :   s.op->newline() << "if (rc != 0)";
    5110                 :        207 :   s.op->newline(1) << "unregister_kprobe (& kp->dummy);";
    5111                 :        207 :   s.op->newline(-2) << "}";
    5112                 :        207 :   s.op->newline() << "#else";
    5113                 :        207 :   s.op->newline() << "rc = register_kprobe (& kp->u.kp);";
    5114                 :        207 :   s.op->newline() << "#endif";
    5115                 :        207 :   s.op->newline(-1) << "}";
    5116                 :        207 :   s.op->newline() << "if (rc == 0) sdp->registered_p = 1;";
    5117                 :            : 
    5118                 :            :   // old module disappeared?
    5119                 :        207 :   s.op->newline(-1) << "} else if (sdp->registered_p == 1 && relocated_addr == 0) {";
    5120                 :        207 :   s.op->newline(1) << "if (sdp->return_p) {";
    5121                 :        207 :   s.op->newline(1) << "unregister_kretprobe (&kp->u.krp);";
    5122                 :        207 :   s.op->newline() << "atomic_add (kp->u.krp.nmissed, skipped_count());";
    5123                 :        207 :   s.op->newline() << "#ifdef STP_TIMING";
    5124                 :        207 :   s.op->newline() << "if (kp->u.krp.nmissed)";
    5125                 :        207 :   s.op->newline(1) << "_stp_warn (\"Skipped due to missed kretprobe/1 on '%s': %d\\n\", sdp->probe->pp, kp->u.krp.nmissed);";
    5126                 :        207 :   s.op->newline(-1) << "#endif";
    5127                 :        207 :   s.op->newline() << "atomic_add (kp->u.krp.kp.nmissed, skipped_count());";
    5128                 :        207 :   s.op->newline() << "#ifdef STP_TIMING";
    5129                 :        207 :   s.op->newline() << "if (kp->u.krp.kp.nmissed)";
    5130                 :        207 :   s.op->newline(1) << "_stp_warn (\"Skipped due to missed kretprobe/2 on '%s': %lu\\n\", sdp->probe->pp, kp->u.krp.kp.nmissed);";
    5131                 :        207 :   s.op->newline(-1) << "#endif";
    5132                 :        207 :   s.op->newline(-1) << "} else {";
    5133                 :        207 :   s.op->newline(1) << "unregister_kprobe (&kp->u.kp);";
    5134                 :        207 :   s.op->newline() << "atomic_add (kp->u.kp.nmissed, skipped_count());";
    5135                 :        207 :   s.op->newline() << "#ifdef STP_TIMING";
    5136                 :        207 :   s.op->newline() << "if (kp->u.kp.nmissed)";
    5137                 :        207 :   s.op->newline(1) << "_stp_warn (\"Skipped due to missed kprobe on '%s': %lu\\n\", sdp->probe->pp, kp->u.kp.nmissed);";
    5138                 :        207 :   s.op->newline(-1) << "#endif";
    5139                 :        207 :   s.op->newline(-1) << "}";
    5140                 :        207 :   s.op->newline() << "#if defined(__ia64__)";
    5141                 :        207 :   s.op->newline() << "unregister_kprobe (&kp->dummy);";
    5142                 :        207 :   s.op->newline() << "#endif";
    5143                 :        207 :   s.op->newline() << "sdp->registered_p = 0;";
    5144                 :        207 :   s.op->newline(-1) << "}";
    5145                 :            : 
    5146                 :        207 :   s.op->newline(-1) << "}"; // for loop
    5147                 :        207 : }
    5148                 :            : 
    5149                 :            : 
    5150                 :            : 
    5151                 :            : 
    5152                 :            : void
    5153                 :        284 : dwarf_derived_probe_group::emit_module_exit (systemtap_session& s)
    5154                 :            : {
    5155                 :            :   //Unregister kprobes by batch interfaces.
    5156                 :        284 :   s.op->newline() << "#if defined(STAPCONF_UNREGISTER_KPROBES)";
    5157                 :        284 :   s.op->newline() << "j = 0;";
    5158                 :        284 :   s.op->newline() << "for (i=0; i<" << probes_by_module.size() << "; i++) {";
    5159                 :        284 :   s.op->newline(1) << "struct stap_dwarf_probe *sdp = & stap_dwarf_probes[i];";
    5160                 :        284 :   s.op->newline() << "struct stap_dwarf_kprobe *kp = & stap_dwarf_kprobes[i];";
    5161                 :        284 :   s.op->newline() << "if (! sdp->registered_p) continue;";
    5162                 :        284 :   s.op->newline() << "if (!sdp->return_p)";
    5163                 :        284 :   s.op->newline(1) << "stap_unreg_kprobes[j++] = &kp->u.kp;";
    5164                 :        284 :   s.op->newline(-2) << "}";
    5165                 :        284 :   s.op->newline() << "unregister_kprobes((struct kprobe **)stap_unreg_kprobes, j);";
    5166                 :        284 :   s.op->newline() << "j = 0;";
    5167                 :        284 :   s.op->newline() << "for (i=0; i<" << probes_by_module.size() << "; i++) {";
    5168                 :        284 :   s.op->newline(1) << "struct stap_dwarf_probe *sdp = & stap_dwarf_probes[i];";
    5169                 :        284 :   s.op->newline() << "struct stap_dwarf_kprobe *kp = & stap_dwarf_kprobes[i];";
    5170                 :        284 :   s.op->newline() << "if (! sdp->registered_p) continue;";
    5171                 :        284 :   s.op->newline() << "if (sdp->return_p)";
    5172                 :        284 :   s.op->newline(1) << "stap_unreg_kprobes[j++] = &kp->u.krp;";
    5173                 :        284 :   s.op->newline(-2) << "}";
    5174                 :        284 :   s.op->newline() << "unregister_kretprobes((struct kretprobe **)stap_unreg_kprobes, j);";
    5175                 :        284 :   s.op->newline() << "#ifdef __ia64__";
    5176                 :        284 :   s.op->newline() << "j = 0;";
    5177                 :        284 :   s.op->newline() << "for (i=0; i<" << probes_by_module.size() << "; i++) {";
    5178                 :        284 :   s.op->newline(1) << "struct stap_dwarf_probe *sdp = & stap_dwarf_probes[i];";
    5179                 :        284 :   s.op->newline() << "struct stap_dwarf_kprobe *kp = & stap_dwarf_kprobes[i];";
    5180                 :        284 :   s.op->newline() << "if (! sdp->registered_p) continue;";
    5181                 :        284 :   s.op->newline() << "stap_unreg_kprobes[j++] = &kp->dummy;";
    5182                 :        284 :   s.op->newline(-1) << "}";
    5183                 :        284 :   s.op->newline() << "unregister_kprobes((struct kprobe **)stap_unreg_kprobes, j);";
    5184                 :        284 :   s.op->newline() << "#endif";
    5185                 :        284 :   s.op->newline() << "#endif";
    5186                 :            : 
    5187                 :        284 :   s.op->newline() << "for (i=0; i<" << probes_by_module.size() << "; i++) {";
    5188                 :        284 :   s.op->newline(1) << "struct stap_dwarf_probe *sdp = & stap_dwarf_probes[i];";
    5189                 :        284 :   s.op->newline() << "struct stap_dwarf_kprobe *kp = & stap_dwarf_kprobes[i];";
    5190                 :        284 :   s.op->newline() << "if (! sdp->registered_p) continue;";
    5191                 :        284 :   s.op->newline() << "if (sdp->return_p) {";
    5192                 :        284 :   s.op->newline() << "#if !defined(STAPCONF_UNREGISTER_KPROBES)";
    5193                 :        284 :   s.op->newline(1) << "unregister_kretprobe (&kp->u.krp);";
    5194                 :        284 :   s.op->newline() << "#endif";
    5195                 :        284 :   s.op->newline() << "atomic_add (kp->u.krp.nmissed, skipped_count());";
    5196                 :        284 :   s.op->newline() << "#ifdef STP_TIMING";
    5197                 :        284 :   s.op->newline() << "if (kp->u.krp.nmissed)";
    5198                 :        284 :   s.op->newline(1) << "_stp_warn (\"Skipped due to missed kretprobe/1 on '%s': %d\\n\", sdp->probe->pp, kp->u.krp.nmissed);";
    5199                 :        284 :   s.op->newline(-1) << "#endif";
    5200                 :        284 :   s.op->newline() << "atomic_add (kp->u.krp.kp.nmissed, skipped_count());";
    5201                 :        284 :   s.op->newline() << "#ifdef STP_TIMING";
    5202                 :        284 :   s.op->newline() << "if (kp->u.krp.kp.nmissed)";
    5203                 :        284 :   s.op->newline(1) << "_stp_warn (\"Skipped due to missed kretprobe/2 on '%s': %lu\\n\", sdp->probe->pp, kp->u.krp.kp.nmissed);";
    5204                 :        284 :   s.op->newline(-1) << "#endif";
    5205                 :        284 :   s.op->newline(-1) << "} else {";
    5206                 :        284 :   s.op->newline() << "#if !defined(STAPCONF_UNREGISTER_KPROBES)";
    5207                 :        284 :   s.op->newline(1) << "unregister_kprobe (&kp->u.kp);";
    5208                 :        284 :   s.op->newline() << "#endif";
    5209                 :        284 :   s.op->newline() << "atomic_add (kp->u.kp.nmissed, skipped_count());";
    5210                 :        284 :   s.op->newline() << "#ifdef STP_TIMING";
    5211                 :        284 :   s.op->newline() << "if (kp->u.kp.nmissed)";
    5212                 :        284 :   s.op->newline(1) << "_stp_warn (\"Skipped due to missed kprobe on '%s': %lu\\n\", sdp->probe->pp, kp->u.kp.nmissed);";
    5213                 :        284 :   s.op->newline(-1) << "#endif";
    5214                 :        284 :   s.op->newline(-1) << "}";
    5215                 :        284 :   s.op->newline() << "#if !defined(STAPCONF_UNREGISTER_KPROBES) && defined(__ia64__)";
    5216                 :        284 :   s.op->newline() << "unregister_kprobe (&kp->dummy);";
    5217                 :        284 :   s.op->newline() << "#endif";
    5218                 :        284 :   s.op->newline() << "sdp->registered_p = 0;";
    5219                 :        284 :   s.op->newline(-1) << "}";
    5220                 :        284 : }
    5221                 :            : 
    5222                 :         72 : static void sdt_v3_tokenize(const string& str, vector<string>& tokens)
    5223                 :            : {
    5224                 :            :   string::size_type pos;
    5225                 :         72 :   string::size_type lastPos = str.find_first_not_of(" ", 0);
    5226                 :         72 :   string::size_type nextAt = str.find("@", lastPos);
    5227                 :            : 
    5228         [ -  + ]:         72 :   if (nextAt == string::npos)
    5229                 :            :     {
    5230                 :            :       // PR13934: Assembly probes are not forced to use the N@OP form.
    5231                 :            :       // In this case, N is inferred to be the native word size.  Since we
    5232                 :            :       // don't have a nice delimiter, just split it on spaces.  SDT-asm authors
    5233                 :            :       // then must not put any spaces in arguments, to avoid ambiguity.
    5234 [ #  # ][ #  # ]:          0 :       tokenize(str, tokens, " ");
                 [ #  # ]
    5235                 :         72 :       return;
    5236                 :            :     }
    5237                 :            : 
    5238         [ +  + ]:        159 :   while (lastPos != string::npos)
    5239                 :            :    {
    5240                 :         87 :      pos = nextAt + 1;
    5241                 :         87 :      nextAt = str.find("@", pos);
    5242         [ +  + ]:         87 :      if (nextAt == string::npos)
    5243                 :         72 :        pos = string::npos;
    5244                 :            :      else
    5245                 :         15 :        pos = str.rfind(" ", nextAt);
    5246                 :            : 
    5247         [ +  - ]:         87 :      tokens.push_back(str.substr(lastPos, pos - lastPos));
    5248                 :         87 :      lastPos = str.find_first_not_of(" ", pos);
    5249                 :            :    }
    5250                 :            : }
    5251                 :            : 
    5252                 :            : 
    5253 [ +  - ][ +  - ]:         72 : struct sdt_uprobe_var_expanding_visitor: public var_expanding_visitor
                 [ -  + ]
    5254                 :            : {
    5255                 :            :   enum regwidths {QI, QIh, HI, SI, DI};
    5256                 :         72 :   sdt_uprobe_var_expanding_visitor(systemtap_session& s,
    5257                 :            :                                    int elf_machine,
    5258                 :            :                                    const string & process_name,
    5259                 :            :                                    const string & provider_name,
    5260                 :            :                                    const string & probe_name,
    5261                 :            :                                    stap_sdt_probe_type probe_type,
    5262                 :            :                                    const string & arg_string,
    5263                 :            :                                    int ac):
    5264                 :            :     session (s), elf_machine (elf_machine), process_name (process_name),
    5265                 :            :     provider_name (provider_name), probe_name (probe_name),
    5266 [ +  - ][ +  - ]:         72 :     probe_type (probe_type), arg_count ((unsigned) ac)
    5267                 :            :   {
    5268                 :            :     /* Register name mapping table depends on the elf machine of this particular
    5269                 :            :        probe target process/file, not upon the host.  So we can't just
    5270                 :            :        #ifdef _i686_ etc. */
    5271                 :            : 
    5272                 :            : #define DRI(name,num,width)  dwarf_regs[name]=make_pair(num,width)
    5273         [ -  + ]:         72 :     if (elf_machine == EM_X86_64) {
    5274 [ #  # ][ #  # ]:          0 :       DRI ("%rax", 0, DI); DRI ("%eax", 0, SI); DRI ("%ax", 0, HI); 
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
    5275 [ #  # ][ #  # ]:          0 :          DRI ("%al", 0, QI); DRI ("%ah", 0, QIh); 
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
    5276 [ #  # ][ #  # ]:          0 :       DRI ("%rdx", 1, DI); DRI ("%edx", 1, SI); DRI ("%dx", 1, HI);
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
    5277 [ #  # ][ #  # ]:          0 :          DRI ("%dl", 1, QI); DRI ("%dh", 1, QIh);
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
    5278 [ #  # ][ #  # ]:          0 :       DRI ("%rcx", 2, DI); DRI ("%ecx", 2, SI); DRI ("%cx", 2, HI);
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
    5279 [ #  # ][ #  # ]:          0 :          DRI ("%cl", 2, QI); DRI ("%ch", 2, QIh);
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
    5280 [ #  # ][ #  # ]:          0 :       DRI ("%rbx", 3, DI); DRI ("%ebx", 3, SI); DRI ("%bx", 3, HI);
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
    5281 [ #  # ][ #  # ]:          0 :          DRI ("%bl", 3, QI); DRI ("%bh", 3, QIh); 
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
    5282 [ #  # ][ #  # ]:          0 :       DRI ("%rsi", 4, DI); DRI ("%esi", 4, SI); DRI ("%si", 4, HI); 
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
    5283 [ #  # ][ #  # ]:          0 :          DRI ("%sil", 4, QI);
         [ #  # ][ #  # ]
    5284 [ #  # ][ #  # ]:          0 :       DRI ("%rdi", 5, DI); DRI ("%edi", 5, SI); DRI ("%di", 5, HI);
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
    5285 [ #  # ][ #  # ]:          0 :          DRI ("%dil", 5, QI);
         [ #  # ][ #  # ]
    5286 [ #  # ][ #  # ]:          0 :       DRI ("%rbp", 6, DI); DRI ("%ebp", 6, SI); DRI ("%bp", 6, HI);
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
    5287 [ #  # ][ #  # ]:          0 :          DRI ("%bpl", 6, QI);
         [ #  # ][ #  # ]
    5288 [ #  # ][ #  # ]:          0 :       DRI ("%rsp", 7, DI); DRI ("%esp", 7, SI); DRI ("%sp", 7, HI);
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
    5289 [ #  # ][ #  # ]:          0 :          DRI ("%spl", 7, QI);
         [ #  # ][ #  # ]
    5290 [ #  # ][ #  # ]:          0 :       DRI ("%r8", 8, DI); DRI ("%r8d", 8, SI); DRI ("%r8w", 8, HI);
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
    5291 [ #  # ][ #  # ]:          0 :          DRI ("%r8b", 8, QI);
         [ #  # ][ #  # ]
    5292 [ #  # ][ #  # ]:          0 :       DRI ("%r9", 9, DI); DRI ("%r9d", 9, SI); DRI ("%r9w", 9, HI);
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
    5293 [ #  # ][ #  # ]:          0 :          DRI ("%r9b", 9, QI);
         [ #  # ][ #  # ]
    5294 [ #  # ][ #  # ]:          0 :       DRI ("%r10", 10, DI); DRI ("%r10d", 10, SI); DRI ("%r10w", 10, HI);
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
    5295 [ #  # ][ #  # ]:          0 :          DRI ("%r10b", 10, QI);
         [ #  # ][ #  # ]
    5296 [ #  # ][ #  # ]:          0 :       DRI ("%r11", 11, DI); DRI ("%r11d", 11, SI); DRI ("%r11w", 11, HI);
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
    5297 [ #  # ][ #  # ]:          0 :          DRI ("%r11b", 11, QI);
         [ #  # ][ #  # ]
    5298 [ #  # ][ #  # ]:          0 :       DRI ("%r12", 12, DI); DRI ("%r12d", 12, SI); DRI ("%r12w", 12, HI);
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
    5299 [ #  # ][ #  # ]:          0 :          DRI ("%r12b", 12, QI);
         [ #  # ][ #  # ]
    5300 [ #  # ][ #  # ]:          0 :       DRI ("%r13", 13, DI); DRI ("%r13d", 13, SI); DRI ("%r13w", 13, HI);
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
    5301 [ #  # ][ #  # ]:          0 :          DRI ("%r13b", 13, QI);
         [ #  # ][ #  # ]
    5302 [ #  # ][ #  # ]:          0 :       DRI ("%r14", 14, DI); DRI ("%r14d", 14, SI); DRI ("%r14w", 14, HI);
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
    5303 [ #  # ][ #  # ]:          0 :          DRI ("%r14b", 14, QI);
         [ #  # ][ #  # ]
    5304 [ #  # ][ #  # ]:          0 :       DRI ("%r15", 15, DI); DRI ("%r15d", 15, SI); DRI ("%r15w", 15, HI);
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
    5305 [ #  # ][ #  # ]:          0 :          DRI ("%r15b", 15, QI);
         [ #  # ][ #  # ]
    5306         [ -  + ]:         72 :     } else if (elf_machine == EM_386) {
    5307 [ #  # ][ #  # ]:          0 :       DRI ("%eax", 0, SI); DRI ("%ax", 0, HI); DRI ("%al", 0, QI);
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
    5308 [ #  # ][ #  # ]:          0 :          DRI ("%ah", 0, QIh);
         [ #  # ][ #  # ]
    5309 [ #  # ][ #  # ]:          0 :       DRI ("%ecx", 1, SI); DRI ("%cx", 1, HI); DRI ("%cl", 1, QI);
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
    5310 [ #  # ][ #  # ]:          0 :          DRI ("%ch", 1, QIh);
         [ #  # ][ #  # ]
    5311 [ #  # ][ #  # ]:          0 :       DRI ("%edx", 2, SI); DRI ("%dx", 2, HI); DRI ("%dl", 2, QI);
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
    5312 [ #  # ][ #  # ]:          0 :          DRI ("%dh", 2, QIh);
         [ #  # ][ #  # ]
    5313 [ #  # ][ #  # ]:          0 :       DRI ("%ebx", 3, SI); DRI ("%bx", 3, HI); DRI ("%bl", 3, QI);
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
    5314 [ #  # ][ #  # ]:          0 :          DRI ("%bh", 3, QIh);
         [ #  # ][ #  # ]
    5315 [ #  # ][ #  # ]:          0 :       DRI ("%esp", 4, SI); DRI ("%sp", 4, HI); 
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
    5316 [ #  # ][ #  # ]:          0 :       DRI ("%ebp", 5, SI); DRI ("%bp", 5, HI);
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
    5317 [ #  # ][ #  # ]:          0 :       DRI ("%esi", 6, SI); DRI ("%si", 6, HI); DRI ("%sil", 6, QI);
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
    5318 [ #  # ][ #  # ]:          0 :       DRI ("%edi", 7, SI); DRI ("%di", 7, HI); DRI ("%dil", 7, QI);
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
    5319 [ +  - ][ -  + ]:         72 :     } else if (elf_machine == EM_PPC || elf_machine == EM_PPC64) {
    5320 [ #  # ][ #  # ]:          0 :       DRI ("%r0", 0, DI);
         [ #  # ][ #  # ]
    5321 [ #  # ][ #  # ]:          0 :       DRI ("%r1", 1, DI);
         [ #  # ][ #  # ]
    5322 [ #  # ][ #  # ]:          0 :       DRI ("%r2", 2, DI);
         [ #  # ][ #  # ]
    5323 [ #  # ][ #  # ]:          0 :       DRI ("%r3", 3, DI);
         [ #  # ][ #  # ]
    5324 [ #  # ][ #  # ]:          0 :       DRI ("%r4", 4, DI);
         [ #  # ][ #  # ]
    5325 [ #  # ][ #  # ]:          0 :       DRI ("%r5", 5, DI);
         [ #  # ][ #  # ]
    5326 [ #  # ][ #  # ]:          0 :       DRI ("%r6", 6, DI);
         [ #  # ][ #  # ]
    5327 [ #  # ][ #  # ]:          0 :       DRI ("%r7", 7, DI);
         [ #  # ][ #  # ]
    5328 [ #  # ][ #  # ]:          0 :       DRI ("%r8", 8, DI);
         [ #  # ][ #  # ]
    5329 [ #  # ][ #  # ]:          0 :       DRI ("%r9", 9, DI);
         [ #  # ][ #  # ]
    5330 [ #  # ][ #  # ]:          0 :       DRI ("%r10", 10, DI);
         [ #  # ][ #  # ]
    5331 [ #  # ][ #  # ]:          0 :       DRI ("%r11", 11, DI);
         [ #  # ][ #  # ]
    5332 [ #  # ][ #  # ]:          0 :       DRI ("%r12", 12, DI);
         [ #  # ][ #  # ]
    5333 [ #  # ][ #  # ]:          0 :       DRI ("%r13", 13, DI);
         [ #  # ][ #  # ]
    5334 [ #  # ][ #  # ]:          0 :       DRI ("%r14", 14, DI);
         [ #  # ][ #  # ]
    5335 [ #  # ][ #  # ]:          0 :       DRI ("%r15", 15, DI);
         [ #  # ][ #  # ]
    5336 [ #  # ][ #  # ]:          0 :       DRI ("%r16", 16, DI);
         [ #  # ][ #  # ]
    5337 [ #  # ][ #  # ]:          0 :       DRI ("%r17", 17, DI);
         [ #  # ][ #  # ]
    5338 [ #  # ][ #  # ]:          0 :       DRI ("%r18", 18, DI);
         [ #  # ][ #  # ]
    5339 [ #  # ][ #  # ]:          0 :       DRI ("%r19", 19, DI);
         [ #  # ][ #  # ]
    5340 [ #  # ][ #  # ]:          0 :       DRI ("%r20", 20, DI);
         [ #  # ][ #  # ]
    5341 [ #  # ][ #  # ]:          0 :       DRI ("%r21", 21, DI);
         [ #  # ][ #  # ]
    5342 [ #  # ][ #  # ]:          0 :       DRI ("%r22", 22, DI);
         [ #  # ][ #  # ]
    5343 [ #  # ][ #  # ]:          0 :       DRI ("%r23", 23, DI);
         [ #  # ][ #  # ]
    5344 [ #  # ][ #  # ]:          0 :       DRI ("%r24", 24, DI);
         [ #  # ][ #  # ]
    5345 [ #  # ][ #  # ]:          0 :       DRI ("%r25", 25, DI);
         [ #  # ][ #  # ]
    5346 [ #  # ][ #  # ]:          0 :       DRI ("%r26", 26, DI);
         [ #  # ][ #  # ]
    5347 [ #  # ][ #  # ]:          0 :       DRI ("%r27", 27, DI);
         [ #  # ][ #  # ]
    5348 [ #  # ][ #  # ]:          0 :       DRI ("%r28", 28, DI);
         [ #  # ][ #  # ]
    5349 [ #  # ][ #  # ]:          0 :       DRI ("%r29", 29, DI);
         [ #  # ][ #  # ]
    5350 [ #  # ][ #  # ]:          0 :       DRI ("%r30", 30, DI);
         [ #  # ][ #  # ]
    5351 [ #  # ][ #  # ]:          0 :       DRI ("%r31", 31, DI);
         [ #  # ][ #  # ]
    5352                 :            :       // PR11821: unadorned register "names" without -mregnames
    5353 [ #  # ][ #  # ]:          0 :       DRI ("0", 0, DI);
         [ #  # ][ #  # ]
    5354 [ #  # ][ #  # ]:          0 :       DRI ("1", 1, DI);
         [ #  # ][ #  # ]
    5355 [ #  # ][ #  # ]:          0 :       DRI ("2", 2, DI);
         [ #  # ][ #  # ]
    5356 [ #  # ][ #  # ]:          0 :       DRI ("3", 3, DI);
         [ #  # ][ #  # ]
    5357 [ #  # ][ #  # ]:          0 :       DRI ("4", 4, DI);
         [ #  # ][ #  # ]
    5358 [ #  # ][ #  # ]:          0 :       DRI ("5", 5, DI);
         [ #  # ][ #  # ]
    5359 [ #  # ][ #  # ]:          0 :       DRI ("6", 6, DI);
         [ #  # ][ #  # ]
    5360 [ #  # ][ #  # ]:          0 :       DRI ("7", 7, DI);
         [ #  # ][ #  # ]
    5361 [ #  # ][ #  # ]:          0 :       DRI ("8", 8, DI);
         [ #  # ][ #  # ]
    5362 [ #  # ][ #  # ]:          0 :       DRI ("9", 9, DI);
         [ #  # ][ #  # ]
    5363 [ #  # ][ #  # ]:          0 :       DRI ("10", 10, DI);
         [ #  # ][ #  # ]
    5364 [ #  # ][ #  # ]:          0 :       DRI ("11", 11, DI);
         [ #  # ][ #  # ]
    5365 [ #  # ][ #  # ]:          0 :       DRI ("12", 12, DI);
         [ #  # ][ #  # ]
    5366 [ #  # ][ #  # ]:          0 :       DRI ("13", 13, DI);
         [ #  # ][ #  # ]
    5367 [ #  # ][ #  # ]:          0 :       DRI ("14", 14, DI);
         [ #  # ][ #  # ]
    5368 [ #  # ][ #  # ]:          0 :       DRI ("15", 15, DI);
         [ #  # ][ #  # ]
    5369 [ #  # ][ #  # ]:          0 :       DRI ("16", 16, DI);
         [ #  # ][ #  # ]
    5370 [ #  # ][ #  # ]:          0 :       DRI ("17", 17, DI);
         [ #  # ][ #  # ]
    5371 [ #  # ][ #  # ]:          0 :       DRI ("18", 18, DI);
         [ #  # ][ #  # ]
    5372 [ #  # ][ #  # ]:          0 :       DRI ("19", 19, DI);
         [ #  # ][ #  # ]
    5373 [ #  # ][ #  # ]:          0 :       DRI ("20", 20, DI);
         [ #  # ][ #  # ]
    5374 [ #  # ][ #  # ]:          0 :       DRI ("21", 21, DI);
         [ #  # ][ #  # ]
    5375 [ #  # ][ #  # ]:          0 :       DRI ("22", 22, DI);
         [ #  # ][ #  # ]
    5376 [ #  # ][ #  # ]:          0 :       DRI ("23", 23, DI);
         [ #  # ][ #  # ]
    5377 [ #  # ][ #  # ]:          0 :       DRI ("24", 24, DI);
         [ #  # ][ #  # ]
    5378 [ #  # ][ #  # ]:          0 :       DRI ("25", 25, DI);
         [ #  # ][ #  # ]
    5379 [ #  # ][ #  # ]:          0 :       DRI ("26", 26, DI);
         [ #  # ][ #  # ]
    5380 [ #  # ][ #  # ]:          0 :       DRI ("27", 27, DI);
         [ #  # ][ #  # ]
    5381 [ #  # ][ #  # ]:          0 :       DRI ("28", 28, DI);
         [ #  # ][ #  # ]
    5382 [ #  # ][ #  # ]:          0 :       DRI ("29", 29, DI);
         [ #  # ][ #  # ]
    5383 [ #  # ][ #  # ]:          0 :       DRI ("30", 30, DI);
         [ #  # ][ #  # ]
    5384 [ #  # ][ #  # ]:          0 :       DRI ("31", 31, DI);
         [ #  # ][ #  # ]
    5385         [ -  + ]:         72 :     } else if (elf_machine == EM_S390) {
    5386 [ #  # ][ #  # ]:          0 :       DRI ("%r0", 0, DI);
         [ #  # ][ #  # ]
    5387 [ #  # ][ #  # ]:          0 :       DRI ("%r1", 1, DI);
         [ #  # ][ #  # ]
    5388 [ #  # ][ #  # ]:          0 :       DRI ("%r2", 2, DI);
         [ #  # ][ #  # ]
    5389 [ #  # ][ #  # ]:          0 :       DRI ("%r3", 3, DI);
         [ #  # ][ #  # ]
    5390 [ #  # ][ #  # ]:          0 :       DRI ("%r4", 4, DI);
         [ #  # ][ #  # ]
    5391 [ #  # ][ #  # ]:          0 :       DRI ("%r5", 5, DI);
         [ #  # ][ #  # ]
    5392 [ #  # ][ #  # ]:          0 :       DRI ("%r6", 6, DI);
         [ #  # ][ #  # ]
    5393 [ #  # ][ #  # ]:          0 :       DRI ("%r7", 7, DI);
         [ #  # ][ #  # ]
    5394 [ #  # ][ #  # ]:          0 :       DRI ("%r8", 8, DI);
         [ #  # ][ #  # ]
    5395 [ #  # ][ #  # ]:          0 :       DRI ("%r9", 9, DI);
         [ #  # ][ #  # ]
    5396 [ #  # ][ #  # ]:          0 :       DRI ("%r10", 10, DI);
         [ #  # ][ #  # ]
    5397 [ #  # ][ #  # ]:          0 :       DRI ("%r11", 11, DI);
         [ #  # ][ #  # ]
    5398 [ #  # ][ #  # ]:          0 :       DRI ("%r12", 12, DI);
         [ #  # ][ #  # ]
    5399 [ #  # ][ #  # ]:          0 :       DRI ("%r13", 13, DI);
         [ #  # ][ #  # ]
    5400 [ #  # ][ #  # ]:          0 :       DRI ("%r14", 14, DI);
         [ #  # ][ #  # ]
    5401 [ #  # ][ #  # ]:          0 :       DRI ("%r15", 15, DI);
         [ #  # ][ #  # ]
    5402         [ +  - ]:         72 :     } else if (elf_machine == EM_ARM) {
    5403 [ +  - ][ +  - ]:         72 :       DRI ("r0", 0, SI);
         [ +  - ][ +  - ]
    5404 [ +  - ][ +  - ]:         72 :       DRI ("r1", 1, SI);
         [ +  - ][ +  - ]
    5405 [ +  - ][ +  - ]:         72 :       DRI ("r2", 2, SI);
         [ +  - ][ +  - ]
    5406 [ +  - ][ +  - ]:         72 :       DRI ("r3", 3, SI);
         [ +  - ][ +  - ]
    5407 [ +  - ][ +  - ]:         72 :       DRI ("r4", 4, SI);
         [ +  - ][ +  - ]
    5408 [ +  - ][ +  - ]:         72 :       DRI ("r5", 5, SI);
         [ +  - ][ +  - ]
    5409 [ +  - ][ +  - ]:         72 :       DRI ("r6", 6, SI);
         [ +  - ][ +  - ]
    5410 [ +  - ][ +  - ]:         72 :       DRI ("r7", 7, SI);
         [ +  - ][ +  - ]
    5411 [ +  - ][ +  - ]:         72 :       DRI ("r8", 8, SI);
         [ +  - ][ +  - ]
    5412 [ +  - ][ +  - ]:         72 :       DRI ("r9", 9, SI);
         [ +  - ][ +  - ]
    5413 [ +  - ][ +  - ]:         72 :       DRI ("sl", 10, SI);
         [ +  - ][ +  - ]
    5414 [ +  - ][ +  - ]:         72 :       DRI ("fp", 11, SI);
         [ +  - ][ +  - ]
    5415 [ +  - ][ +  - ]:         72 :       DRI ("ip", 12, SI);
         [ +  - ][ +  - ]
    5416 [ +  - ][ +  - ]:         72 :       DRI ("sp", 13, SI);
         [ +  - ][ +  - ]
    5417 [ +  - ][ +  - ]:         72 :       DRI ("lr", 14, SI);
         [ +  - ][ +  - ]
    5418 [ +  - ][ +  - ]:         72 :       DRI ("pc", 15, SI);
         [ +  - ][ +  - ]
    5419                 :          0 :     } else if (arg_count) {
    5420                 :            :       /* permit this case; just fall back to dwarf */
    5421                 :            :     }
    5422                 :            : #undef DRI
    5423                 :            : 
    5424                 :         72 :     need_debug_info = false;
    5425         [ +  - ]:         72 :     if (probe_type == uprobe3_type)
    5426                 :            :       {
    5427         [ +  - ]:         72 :         sdt_v3_tokenize(arg_string, arg_tokens);
    5428         [ -  + ]:         72 :         assert(arg_count <= 12);
    5429                 :            :       }
    5430                 :            :     else
    5431                 :            :       {
    5432 [ #  # ][ #  # ]:          0 :         tokenize(arg_string, arg_tokens, " ");
                 [ #  # ]
    5433         [ #  # ]:          0 :         assert(arg_count <= 10);
    5434                 :            :       }
    5435                 :         72 :   }
    5436                 :            : 
    5437                 :            :   systemtap_session& session;
    5438                 :            :   int elf_machine;
    5439                 :            :   const string & process_name;
    5440                 :            :   const string & provider_name;
    5441                 :            :   const string & probe_name;
    5442                 :            :   stap_sdt_probe_type probe_type;
    5443                 :            :   unsigned arg_count;
    5444                 :            :   vector<string> arg_tokens;
    5445                 :            :   map<string, pair<unsigned,int> > dwarf_regs;
    5446                 :            :   bool need_debug_info;
    5447                 :            : 
    5448                 :            :   void visit_target_symbol (target_symbol* e);
    5449                 :            :   void visit_target_symbol_arg (target_symbol* e);
    5450                 :            :   void visit_target_symbol_context (target_symbol* e);
    5451                 :            :   void visit_cast_op (cast_op* e);
    5452                 :            : };
    5453                 :            : 
    5454                 :            : 
    5455                 :            : void
    5456                 :          0 : sdt_uprobe_var_expanding_visitor::visit_target_symbol_context (target_symbol* e)
    5457                 :            : {
    5458         [ #  # ]:          0 :   if (e->addressof)
    5459 [ #  # ][ #  # ]:          0 :     throw semantic_error(_("cannot take address of context variable"), e->tok);
    5460                 :            : 
    5461         [ #  # ]:          0 :   if (e->name == "$$name")
    5462                 :            :     {
    5463         [ #  # ]:          0 :       literal_string *myname = new literal_string (probe_name);
    5464                 :          0 :       myname->tok = e->tok;
    5465                 :          0 :       provide(myname);
    5466                 :          0 :       return;
    5467                 :            :     }
    5468                 :            : 
    5469         [ #  # ]:          0 :   else if (e->name == "$$provider")
    5470                 :            :     {
    5471         [ #  # ]:          0 :       literal_string *myname = new literal_string (provider_name);
    5472                 :          0 :       myname->tok = e->tok;
    5473                 :          0 :       provide(myname);
    5474                 :          0 :       return;
    5475                 :            :     }
    5476                 :            : 
    5477 [ #  # ][ #  # ]:          0 :   else if (e->name == "$$vars" || e->name == "$$parms")
                 [ #  # ]
    5478                 :            :     {
    5479 [ #  # ][ #  # ]:          0 :       e->assert_no_components("sdt", true);
                 [ #  # ]
    5480                 :            : 
    5481                 :            :       // Convert $$vars to sprintf of a list of vars which we recursively evaluate
    5482                 :            :       // NB: we synthesize a new token here rather than reusing
    5483                 :            :       // e->tok, because print_format::print likes to use
    5484                 :            :       // its tok->content.
    5485         [ #  # ]:          0 :       token* pf_tok = new token(*e->tok);
    5486                 :          0 :       pf_tok->content = "sprintf";
    5487                 :            : 
    5488                 :          0 :       print_format* pf = print_format::create(pf_tok);
    5489                 :            : 
    5490         [ #  # ]:          0 :       for (unsigned i = 1; i <= arg_count; ++i)
    5491                 :            :         {
    5492         [ #  # ]:          0 :           if (i > 1)
    5493         [ #  # ]:          0 :             pf->raw_components += " ";
    5494 [ #  # ][ #  # ]:          0 :           target_symbol *tsym = new target_symbol;
    5495                 :          0 :           tsym->tok = e->tok;
    5496 [ #  # ][ #  # ]:          0 :           tsym->name = "$arg" + lex_cast(i);
         [ #  # ][ #  # ]
                 [ #  # ]
    5497         [ #  # ]:          0 :           pf->raw_components += tsym->name;
    5498         [ #  # ]:          0 :           tsym->components = e->components;
    5499                 :            : 
    5500         [ #  # ]:          0 :           expression *texp = require<expression> (tsym);
    5501         [ #  # ]:          0 :           if (!e->components.empty() &&
           [ #  #  #  # ]
                 [ #  # ]
    5502                 :          0 :               e->components[0].type == target_symbol::comp_pretty_print)
    5503         [ #  # ]:          0 :             pf->raw_components += "=%s";
    5504                 :            :           else
    5505         [ #  # ]:          0 :             pf->raw_components += "=%#x";
    5506         [ #  # ]:          0 :           pf->args.push_back(texp);
    5507                 :            :         }
    5508                 :            : 
    5509         [ #  # ]:          0 :       pf->components = print_format::string_to_components(pf->raw_components);
    5510                 :          0 :       provide (pf);
    5511                 :            :     }
    5512                 :            :   else
    5513                 :          0 :     assert(0); // shouldn't get here
    5514                 :            : }
    5515                 :            : 
    5516                 :            : 
    5517                 :            : void
    5518                 :         72 : sdt_uprobe_var_expanding_visitor::visit_target_symbol_arg (target_symbol *e)
    5519                 :            : {
    5520                 :            :   try
    5521                 :            :     {
    5522                 :         72 :       unsigned argno = 0; // the N in $argN
    5523                 :            :       try
    5524                 :            :         {
    5525 [ +  - ][ +  + ]:         72 :           if (startswith(e->name, "$arg"))
    5526 [ +  - ][ +  - ]:         48 :             argno = lex_cast<unsigned>(e->name.substr(4));
         [ +  - ][ #  # ]
    5527                 :            :         }
    5528                 :            :       catch (const runtime_error& f) // non-integral $arg suffix: e.g. $argKKKSDF
    5529                 :            :         {
    5530                 :            :           argno = 0;
    5531                 :            :         }
    5532                 :            : 
    5533 [ +  - ][ +  + ]:         72 :       if (arg_count == 0 || // a sdt.h variant without .probe-stored arg_count
                 [ -  + ]
    5534                 :            :           argno < 1 || argno > arg_count) // a $argN with out-of-range N
    5535                 :            :         {
    5536                 :            :           // NB: Either
    5537                 :            :           // 1) uprobe1_type $argN or $FOO (we don't know the arg_count)
    5538                 :            :           // 2) uprobe2_type $FOO (no probe args)
    5539                 :            :           // both of which get resolved later.
    5540                 :            :           // Throw it now, and it might be resolved by DWARF later.
    5541                 :         24 :           need_debug_info = true;
    5542 [ +  - ][ +  - ]:         24 :           throw semantic_error(_("target-symbol requires debuginfo"), e->tok);
    5543                 :            :         }
    5544                 :            : 
    5545         [ -  + ]:         48 :       assert (arg_tokens.size() >= argno);
    5546         [ +  - ]:         48 :       string asmarg = arg_tokens[argno-1];   // $arg1 => arg_tokens[0]
    5547                 :            : 
    5548                 :            :       // Now we try to parse this thing, which is an assembler operand
    5549                 :            :       // expression.  If we can't, we warn, back down to need_debug_info
    5550                 :            :       // and hope for the best.  Here is the syntax for a few architectures.
    5551                 :            :       // Note that the power iN syntax is only for V3 sdt.h; gcc emits the i.
    5552                 :            :       //
    5553                 :            :       //      literal   reg     reg     reg +   base+index*size+offset
    5554                 :            :       //                      indirect offset
    5555                 :            :       // x86    $N      %rR     (%rR)   N(%rR)  O(%bR,%iR,S)
    5556                 :            :       // power  iN      R       (R)     N(R)
    5557                 :            :       // ia64   N       rR      [r16]   
    5558                 :            :       // s390   N       %rR     0(rR)   N(r15)
    5559                 :            :       // arm    #N      rR      [rR]    [rR, #N]
    5560                 :            : 
    5561                 :         48 :       expression* argexpr = 0; // filled in in case of successful parse
    5562                 :            : 
    5563         [ +  - ]:         48 :       string percent_regnames;
    5564         [ +  - ]:         48 :       string regnames;
    5565         [ +  - ]:         48 :       vector<string> matches;
    5566                 :            :       long precision;
    5567                 :            :       int rc;
    5568                 :            : 
    5569                 :            :       // Parse the leading length
    5570                 :            : 
    5571 [ +  - ][ +  - ]:         48 :       if (asmarg.find('@') != string::npos)
    5572                 :            :         {
    5573 [ +  - ][ +  - ]:         48 :           precision = lex_cast<int>(asmarg.substr(0, asmarg.find('@')));
         [ +  - ][ +  - ]
    5574 [ +  - ][ +  - ]:         48 :           asmarg = asmarg.substr(asmarg.find('@')+1);
         [ +  - ][ +  - ]
    5575                 :            :         }
    5576                 :            :       else
    5577                 :            :         {
    5578                 :            :           // V1/V2 do not have precision field so default to signed long
    5579                 :            :           // V3 asm does not have precision field so default to unsigned long
    5580         [ #  # ]:          0 :           if (probe_type == uprobe3_type)
    5581                 :          0 :             precision = sizeof(long); // this is an asm probe
    5582                 :            :           else
    5583                 :          0 :             precision = -sizeof(long);
    5584                 :            :         }
    5585                 :            : 
    5586                 :            :       // test for a numeric literal.
    5587                 :            :       // Only accept (signed) decimals throughout. XXX
    5588                 :            : 
    5589                 :            :       // PR11821.  NB: on powerpc, literals are not prefixed with $,
    5590                 :            :       // so this regex does not match.  But that's OK, since without
    5591                 :            :       // -mregnames, we can't tell them apart from register numbers
    5592                 :            :       // anyway.  With -mregnames, we could, if gcc somehow
    5593                 :            :       // communicated to us the presence of that option, but alas it
    5594                 :            :       // doesn't.  http://gcc.gnu.org/PR44995.
    5595 [ +  - ][ +  - ]:         48 :       rc = regexp_match (asmarg, "^[i\\$#][-]?[0-9][0-9]*$", matches);
         [ +  - ][ #  # ]
    5596         [ -  + ]:         48 :       if (! rc)
    5597                 :            :         {
    5598         [ #  # ]:          0 :           string sn = matches[0].substr(1);
    5599                 :            :           int64_t n;
    5600                 :            :           try
    5601                 :            :             {
    5602                 :            :               // We have to pay attention to the size & sign, as gcc sometimes
    5603                 :            :               // propagates constants that don't quite match, like a negative
    5604                 :            :               // value to fill an unsigned type.
    5605   [ #  #  #  #  :          0 :               switch (precision)
             #  #  #  # ]
    5606                 :            :                 {
    5607         [ #  # ]:          0 :                 case -1: n = lex_cast<  int8_t>(sn); break;
    5608         [ #  # ]:          0 :                 case  1: n = lex_cast< uint8_t>(sn); break;
    5609         [ #  # ]:          0 :                 case -2: n = lex_cast< int16_t>(sn); break;
    5610         [ #  # ]:          0 :                 case  2: n = lex_cast<uint16_t>(sn); break;
    5611         [ #  # ]:          0 :                 case -4: n = lex_cast< int32_t>(sn); break;
    5612         [ #  # ]:          0 :                 case  4: n = lex_cast<uint32_t>(sn); break;
    5613                 :            :                 default:
    5614         [ #  # ]:          0 :                 case -8: n = lex_cast< int64_t>(sn); break;
    5615         [ #  # ]:          0 :                 case  8: n = lex_cast<uint64_t>(sn); break;
    5616                 :            :                 }
    5617                 :            :             }
    5618                 :            :           catch (std::runtime_error&)
    5619                 :            :             {
    5620                 :            :               goto not_matched;
    5621                 :            :             }
    5622 [ #  # ][ #  # ]:          0 :           literal_number* ln = new literal_number(n);
    5623                 :          0 :           ln->tok = e->tok;
    5624                 :          0 :           argexpr = ln;
    5625 [ #  # ][ #  # ]:          0 :           goto matched;
    5626                 :            :         }
    5627                 :            : 
    5628 [ +  - ][ -  + ]:         48 :       if (dwarf_regs.empty())
    5629                 :          0 :         goto not_matched;
    5630                 :            :       
    5631                 :            :       // Build regex pieces out of the known dwarf_regs.  We keep two separate
    5632                 :            :       // lists: ones with the % prefix (and thus unambigiuous even despite PR11821),
    5633                 :            :       // and ones with no prefix (and thus only usable in unambiguous contexts).
    5634 [ +  - ][ +  - ]:        816 :       for (map<string,pair<unsigned,int> >::iterator ri = dwarf_regs.begin(); ri != dwarf_regs.end(); ri++)
                 [ +  + ]
    5635                 :            :         {
    5636 [ +  - ][ +  - ]:        768 :           string regname = ri->first;
    5637 [ +  - ][ -  + ]:        768 :           assert (regname != "");
    5638 [ +  - ][ +  - ]:        768 :           regnames += string("|")+regname;
         [ +  - ][ +  - ]
                 [ +  - ]
    5639 [ +  - ][ -  + ]:        768 :           if (regname[0]=='%')
    5640 [ #  # ][ #  # ]:          0 :             percent_regnames += string("|")+regname;
         [ #  # ][ #  # ]
                 [ #  # ]
    5641         [ +  - ]:        768 :         }
    5642                 :            :       // clip off leading |
    5643 [ +  - ][ +  - ]:         48 :       regnames = regnames.substr(1);
                 [ +  - ]
    5644 [ +  - ][ -  + ]:         48 :       if (percent_regnames != "")
    5645 [ #  # ][ #  # ]:          0 :           percent_regnames = percent_regnames.substr(1);
                 [ #  # ]
    5646                 :            : 
    5647                 :            :       // test for REGISTER
    5648                 :            :       // NB: Because PR11821, we must use percent_regnames here.
    5649 [ +  - ][ +  - ]:         48 :       if (elf_machine == EM_PPC || elf_machine == EM_PPC64 || elf_machine == EM_ARM)
                 [ +  - ]
    5650 [ +  - ][ +  - ]:         48 :         rc = regexp_match (asmarg, string("^(")+regnames+string(")$"), matches);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    5651                 :            :       else
    5652 [ #  # ][ #  # ]:          0 :         rc = regexp_match (asmarg, string("^(")+percent_regnames+string(")$"), matches);
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
    5653         [ +  + ]:         48 :       if (! rc)
    5654                 :            :         {
    5655         [ +  - ]:         12 :           string regname = matches[1];
    5656         [ +  - ]:         12 :           map<string,pair<unsigned,int> >::iterator ri = dwarf_regs.find (regname);
    5657 [ +  - ][ +  - ]:         12 :           if (ri != dwarf_regs.end()) // known register
    5658                 :            :             {
    5659 [ +  - ][ +  - ]:         12 :               embedded_expr *get_arg1 = new embedded_expr;
    5660         [ +  - ]:         12 :               string width_adjust;
    5661 [ +  - ][ -  -  :         12 :               switch (ri->second.second)
                -  +  - ]
    5662                 :            :                 {
    5663         [ #  # ]:          0 :                 case QI: width_adjust = ") & 0xff)"; break;
    5664         [ #  # ]:          0 :                 case QIh: width_adjust = ">>8) & 0xff)"; break;
    5665                 :            :                 case HI:
    5666                 :            :                   // preserve 16 bit register signness
    5667         [ #  # ]:          0 :                   width_adjust = ") & 0xffff)";
    5668         [ #  # ]:          0 :                   if (precision < 0)
    5669         [ #  # ]:          0 :                     width_adjust += " << 48 >> 48";
    5670                 :          0 :                   break;
    5671                 :            :                 case SI:
    5672                 :            :                   // preserve 32 bit register signness
    5673         [ +  - ]:         12 :                   width_adjust = ") & 0xffffffff)";
    5674         [ -  + ]:         12 :                   if (precision < 0)
    5675         [ #  # ]:          0 :                     width_adjust += " << 32 >> 32";
    5676                 :         12 :                   break;
    5677         [ #  # ]:          0 :                 default: width_adjust = "))";
    5678                 :            :                 }
    5679         [ +  - ]:         12 :               string type = "";
    5680         [ +  - ]:         12 :               if (probe_type == uprobe3_type)
    5681                 :            :                 type = (precision < 0
    5682 [ -  + ][ +  - ]:         12 :                         ? "(int" : "(uint") + lex_cast(abs(precision) * 8) + "_t)";
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
    5683 [ +  - ][ +  - ]:         12 :               type = type + "((";
                 [ +  - ]
    5684                 :         12 :               get_arg1->tok = e->tok;
    5685                 :            :               get_arg1->code = string("/* unprivileged */ /* pure */")
    5686                 :            :                 + string(" ((int64_t)") + type
    5687         [ +  - ]:         12 :                 + (is_user_module (process_name)
    5688                 :            :                    ? string("u_fetch_register(")
    5689                 :            :                    : string("k_fetch_register("))
    5690         [ +  - ]:         12 :                 + lex_cast(dwarf_regs[regname].first) + string("))")
    5691 [ +  - ][ +  - ]:         36 :                 + width_adjust;
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ #  # ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ -  + ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
           [ #  #  #  # ]
    5692                 :         12 :               argexpr = get_arg1;
    5693 [ +  - ][ +  - ]:         12 :               goto matched;
    5694 [ +  - ][ -  + ]:         12 :             }
    5695                 :            :           // invalid register name, fall through
    5696                 :            :         }
    5697                 :            : 
    5698                 :            :       int reg, offset1;
    5699                 :            :       // test for OFFSET(REGISTER) where OFFSET is +-N+-N+-N
    5700                 :            :       // NB: Despite PR11821, we can use regnames here, since the parentheses
    5701                 :            :       // make things unambiguous. (Note: gdb/stap-probe.c also parses this)
    5702                 :            :       // On ARM test for [REGISTER, OFFSET]
    5703         [ +  - ]:         36 :      if (elf_machine == EM_ARM)
    5704                 :            :        {
    5705 [ +  - ][ +  - ]:         36 :          rc = regexp_match (asmarg, string("^\\[(")+regnames+string("), #([+-]?[0-9]+)([+-][0-9]*)?([+-][0-9]*)?\\]$"), matches);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    5706                 :         36 :          reg = 1;
    5707                 :         36 :          offset1 = 2;
    5708                 :            :        }
    5709                 :            :      else
    5710                 :            :        {
    5711 [ #  # ][ #  # ]:          0 :          rc = regexp_match (asmarg, string("^([+-]?[0-9]*)([+-][0-9]*)?([+-][0-9]*)?[(](")+regnames+string(")[)]$"), matches);
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
    5712                 :          0 :          reg = 4;
    5713                 :          0 :          offset1 = 1;
    5714                 :            :        }
    5715         [ +  - ]:         36 :       if (! rc)
    5716                 :            :         {
    5717         [ +  - ]:         36 :           string regname;
    5718                 :         36 :           int64_t disp = 0;
    5719 [ +  - ][ +  - ]:         36 :           if (matches[reg].length())
    5720         [ +  - ]:         36 :             regname = matches[reg];
    5721 [ +  - ][ +  - ]:         36 :           if (dwarf_regs.find (regname) == dwarf_regs.end())
         [ -  + ][ #  # ]
    5722                 :            :             goto not_matched;
    5723                 :            : 
    5724         [ +  + ]:        144 :           for (int i=offset1; i <= (offset1 + 2); i++)
    5725 [ +  - ][ +  + ]:        108 :             if (matches[i].length())
    5726                 :            :               try
    5727                 :            :                 {
    5728         [ +  - ]:         36 :                   disp += lex_cast<int64_t>(matches[i]); // should decode positive/negative hex/decimal
    5729                 :            :                 }
    5730                 :            :                 catch (const runtime_error& f) // unparseable offset
    5731                 :            :                   {
    5732                 :            :                     goto not_matched; // can't just 'break' out of
    5733                 :            :                                       // this case or use a sentinel
    5734                 :            :                                       // value, unfortunately
    5735                 :            :                   }
    5736                 :            : 
    5737                 :            :                   // synthesize user_long(%{fetch_register(R)%} + D)
    5738 [ +  - ][ +  - ]:         36 :                   embedded_expr *get_arg1 = new embedded_expr;
    5739                 :         36 :                   get_arg1->tok = e->tok;
    5740                 :            :                   get_arg1->code = string("/* unprivileged */ /* pure */")
    5741         [ +  - ]:         36 :                     + (is_user_module (process_name)
    5742                 :            :                        ? string("u_fetch_register(")
    5743                 :            :                        : string("k_fetch_register("))
    5744 [ +  - ][ +  - ]:         72 :                     + lex_cast(dwarf_regs[regname].first) + string(")");
         [ +  - ][ #  # ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ -  + ]
         [ +  - ][ +  - ]
           [ #  #  #  # ]
    5745                 :            :                   // XXX: may we ever need to cast that to a narrower type?
    5746                 :            : 
    5747 [ +  - ][ +  - ]:         36 :                   literal_number* inc = new literal_number(disp);
    5748                 :         36 :                   inc->tok = e->tok;
    5749                 :            : 
    5750 [ +  - ][ +  - ]:         36 :                   binary_expression *be = new binary_expression;
    5751                 :         36 :                   be->tok = e->tok;
    5752                 :         36 :                   be->left = get_arg1;
    5753         [ +  - ]:         36 :                   be->op = "+";
    5754                 :         36 :                   be->right = inc;
    5755                 :            : 
    5756 [ +  - ][ +  - ]:         36 :                   functioncall *fc = new functioncall;
    5757   [ -  -  -  +  :         36 :                   switch (precision)
                +  -  - ]
    5758                 :            :                     {
    5759                 :            :                     case 1: case -1:
    5760         [ #  # ]:          0 :                       fc->function = "user_int8"; break;
    5761                 :            :                     case 2:
    5762         [ #  # ]:          0 :                       fc->function = "user_uint16"; break;
    5763                 :            :                     case -2:
    5764         [ #  # ]:          0 :                       fc->function = "user_int16"; break;
    5765                 :            :                     case 4:
    5766         [ +  - ]:         32 :                       fc->function = "user_uint32"; break;
    5767                 :            :                     case -4:
    5768         [ +  - ]:          4 :                       fc->function = "user_int32"; break;
    5769                 :            :                     case 8: case -8:
    5770         [ #  # ]:          0 :                       fc->function = "user_int64"; break;
    5771         [ #  # ]:          0 :                     default: fc->function = "user_long";
    5772                 :            :                     }
    5773                 :         36 :                   fc->tok = e->tok;
    5774         [ +  - ]:         36 :                   fc->args.push_back(be);
    5775                 :            : 
    5776                 :         36 :                   argexpr = fc;
    5777 [ +  - ][ -  + ]:         36 :                   goto matched;
    5778                 :            :                 }
    5779                 :            : 
    5780                 :            :       // test for OFFSET(BASE_REGISTER,INDEX_REGISTER[,SCALE]) where OFFSET is +-N+-N+-N
    5781                 :            :       // NB: Despite PR11821, we can use regnames here, since the parentheses
    5782                 :            :       // make things unambiguous. (Note: gdb/stap-probe.c also parses this)
    5783 [ #  # ][ #  # ]:          0 :       rc = regexp_match (asmarg, string("^([+-]?[0-9]*)([+-][0-9]*)?([+-][0-9]*)?[(](")+regnames+string("),(")+regnames+string(")(,[1248])?[)]$"), matches);
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
    5784         [ #  # ]:          0 :       if (! rc)
    5785                 :            :         {
    5786         [ #  # ]:          0 :           string baseregname;
    5787         [ #  # ]:          0 :           string indexregname;
    5788                 :          0 :           int64_t disp = 0;
    5789                 :          0 :           short scale = 1;
    5790                 :            : 
    5791 [ #  # ][ #  # ]:          0 :           if (matches[6].length())
    5792                 :            :             try
    5793                 :            :               {
    5794 [ #  # ][ #  # ]:          0 :                 scale = lex_cast<short>(matches[6].substr(1)); // NB: skip the comma!
         [ #  # ][ #  # ]
    5795                 :            :                 // We could verify that scale is one of 1,2,4,8,
    5796                 :            :                 // but it doesn't really matter.  An erroneous
    5797                 :            :                 // address merely results in run-time errors.
    5798                 :            :         }
    5799                 :            :             catch (const runtime_error &f) // unparseable scale
    5800                 :            :               {
    5801                 :            :                   goto not_matched;
    5802                 :            :               }
    5803                 :            : 
    5804 [ #  # ][ #  # ]:          0 :           if (matches[4].length())
    5805         [ #  # ]:          0 :             baseregname = matches[4];
    5806 [ #  # ][ #  # ]:          0 :           if (dwarf_regs.find (baseregname) == dwarf_regs.end())
                 [ #  # ]
    5807                 :            :             goto not_matched;
    5808                 :            : 
    5809 [ #  # ][ #  # ]:          0 :           if (matches[5].length())
    5810         [ #  # ]:          0 :             indexregname = matches[5];
    5811 [ #  # ][ #  # ]:          0 :           if (dwarf_regs.find (indexregname) == dwarf_regs.end())
         [ #  # ][ #  # ]
    5812                 :            :             goto not_matched;
    5813                 :            : 
    5814         [ #  # ]:          0 :           for (int i = 1; i <= 3; i++) // up to three OFFSET terms
    5815 [ #  # ][ #  # ]:          0 :             if (matches[i].length())
    5816                 :            :               try
    5817                 :            :                 {
    5818         [ #  # ]:          0 :                   disp += lex_cast<int64_t>(matches[i]); // should decode positive/negative hex/decimal
    5819                 :            :                 }
    5820                 :            :               catch (const runtime_error& f) // unparseable offset
    5821                 :            :                 {
    5822                 :            :                   goto not_matched; // can't just 'break' out of
    5823                 :            :                   // this case or use a sentinel
    5824                 :            :                   // value, unfortunately
    5825                 :            :                 }
    5826                 :            : 
    5827                 :            :           // synthesize user_long(%{fetch_register(R1)+fetch_register(R2)*N%} + D)
    5828                 :            : 
    5829 [ #  # ][ #  # ]:          0 :           embedded_expr *get_arg1 = new embedded_expr;
    5830         [ #  # ]:          0 :           string regfn = is_user_module (process_name)
    5831                 :            :             ? string("u_fetch_register")
    5832 [ #  # ][ #  # ]:          0 :             : string("k_fetch_register"); // NB: in practice sdt.h probes are for userspace only
         [ #  # ][ #  # ]
                 [ #  # ]
           [ #  #  #  # ]
    5833                 :            : 
    5834                 :          0 :           get_arg1->tok = e->tok;
    5835                 :            :           get_arg1->code = string("/* unprivileged */ /* pure */")
    5836         [ #  # ]:          0 :             + regfn + string("(")+lex_cast(dwarf_regs[baseregname].first)+string(")")
    5837                 :            :             + string("+(")
    5838         [ #  # ]:          0 :             + regfn + string("(")+lex_cast(dwarf_regs[indexregname].first)+string(")")
    5839                 :            :             + string("*")
    5840                 :            :             + lex_cast(scale)
    5841 [ #  # ][ #  # ]:          0 :             + string(")");
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
    5842                 :            : 
    5843                 :            :           // NB: could plop this +DISPLACEMENT bit into the embedded-c expression too
    5844 [ #  # ][ #  # ]:          0 :           literal_number* inc = new literal_number(disp);
    5845                 :          0 :           inc->tok = e->tok;
    5846                 :            : 
    5847 [ #  # ][ #  # ]:          0 :           binary_expression *be = new binary_expression;
    5848                 :          0 :           be->tok = e->tok;
    5849                 :          0 :           be->left = get_arg1;
    5850         [ #  # ]:          0 :           be->op = "+";
    5851                 :          0 :           be->right = inc;
    5852                 :            : 
    5853 [ #  # ][ #  # ]:          0 :           functioncall *fc = new functioncall;
    5854   [ #  #  #  #  :          0 :           switch (precision)
                #  #  # ]
    5855                 :            :             {
    5856                 :            :             case 1: case -1:
    5857         [ #  # ]:          0 :               fc->function = "user_int8"; break;
    5858                 :            :             case 2:
    5859         [ #  # ]:          0 :               fc->function = "user_uint16"; break;
    5860                 :            :             case -2:
    5861         [ #  # ]:          0 :               fc->function = "user_int16"; break;
    5862                 :            :             case 4:
    5863         [ #  # ]:          0 :               fc->function = "user_uint32"; break;
    5864                 :            :             case -4:
    5865         [ #  # ]:          0 :               fc->function = "user_int32"; break;
    5866                 :            :             case 8: case -8:
    5867         [ #  # ]:          0 :               fc->function = "user_int64"; break;
    5868         [ #  # ]:          0 :             default: fc->function = "user_long";
    5869                 :            :             }
    5870                 :          0 :           fc->tok = e->tok;
    5871         [ #  # ]:          0 :           fc->args.push_back(be);
    5872                 :            : 
    5873                 :          0 :           argexpr = fc;
    5874 [ #  # ][ #  # ]:          0 :           goto matched;
         [ #  # ][ #  # ]
                 [ #  # ]
    5875                 :            :         }
    5876                 :            : 
    5877                 :            : 
    5878                 :            :     not_matched:
    5879                 :            :       // The asmarg operand was not recognized.  Back down to dwarf.
    5880         [ #  # ]:          0 :       if (! session.suppress_warnings)
    5881                 :            :         {
    5882         [ #  # ]:          0 :           if (probe_type == UPROBE3_TYPE)
    5883 [ #  # ][ #  # ]:          0 :             session.print_warning (_F("Can't parse SDT_V3 operand '%s'", asmarg.c_str()), e->tok);
         [ #  # ][ #  # ]
    5884                 :            :           else // must be *PROBE2; others don't get asm operands
    5885                 :          0 :             session.print_warning (_F("Downgrading SDT_V2 probe argument to dwarf, can't parse '%s'", 
    5886 [ #  # ][ #  # ]:          0 :                                       asmarg.c_str()), e->tok);
         [ #  # ][ #  # ]
    5887                 :            :         }
    5888         [ #  # ]:          0 :       assert (argexpr == 0);
    5889                 :          0 :       need_debug_info = true;
    5890 [ #  # ][ #  # ]:          0 :       throw semantic_error(_("SDT asm not understood, requires debuginfo"), e->tok);
    5891                 :            : 
    5892                 :            :     matched:
    5893         [ -  + ]:         48 :       assert (argexpr != 0);
    5894                 :            : 
    5895         [ -  + ]:         48 :       if (session.verbose > 2)
    5896                 :            :         //TRANSLATORS: We're mapping the operand to a new expression*.
    5897 [ #  # ][ #  # ]:          0 :         clog << _F("mapped asm operand %s to ", asmarg.c_str()) << *argexpr << endl;
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
    5898                 :            : 
    5899 [ +  - ][ +  - ]:         48 :       if (e->components.empty()) // We have a scalar
    5900                 :            :         {
    5901         [ -  + ]:         48 :           if (e->addressof)
    5902 [ #  # ][ #  # ]:          0 :             throw semantic_error(_("cannot take address of sdt variable"), e->tok);
    5903         [ +  - ]:         48 :           provide (argexpr);
    5904                 :            :           return;
    5905                 :            :         }
    5906                 :            :       else  // $var->foo
    5907                 :            :         {
    5908 [ #  # ][ #  # ]:          0 :           cast_op *cast = new cast_op;
    5909         [ #  # ]:          0 :           cast->name = "@cast";
    5910                 :          0 :           cast->tok = e->tok;
    5911                 :          0 :           cast->operand = argexpr;
    5912         [ #  # ]:          0 :           cast->components = e->components;
    5913 [ #  # ][ #  # ]:          0 :           cast->type_name = probe_name + "_arg" + lex_cast(argno);
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
    5914         [ #  # ]:          0 :           cast->module = process_name;
    5915         [ #  # ]:          0 :           cast->visit(this);
    5916                 :            :           return;
    5917 [ +  - ][ +  - ]:         96 :         }
         [ +  - ][ +  - ]
    5918                 :            : 
    5919                 :            :       /* NOTREACHED */
    5920                 :            :     }
    5921         [ -  + ]:         48 :   catch (const semantic_error &er)
    5922                 :            :     {
    5923         [ -  + ]:         24 :       e->chain (er);
    5924         [ -  + ]:         24 :       provide (e);
    5925                 :            :     }
    5926                 :            : }
    5927                 :            : 
    5928                 :            : 
    5929                 :            : void
    5930                 :         72 : sdt_uprobe_var_expanding_visitor::visit_target_symbol (target_symbol* e)
    5931                 :            : {
    5932                 :            :   try
    5933                 :            :     {
    5934 [ +  - ][ +  - ]:        216 :       assert(e->name.size() > 0
         [ +  - ][ #  # ]
                 [ #  # ]
    5935                 :            :              && ((e->name[0] == '$' && e->target_name == "")
    5936 [ +  - ][ +  - ]:        216 :                  || (e->name == "@var" && e->target_name != "")));
         [ -  + ][ #  # ]
                 [ #  # ]
    5937                 :            : 
    5938 [ +  - ][ +  - ]:         72 :       if (e->name == "$$name" || e->name == "$$provider" || e->name == "$$parms" || e->name == "$$vars")
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ -  + ]
                 [ -  + ]
    5939         [ #  # ]:          0 :         visit_target_symbol_context (e);
    5940                 :            :       else
    5941         [ +  - ]:         72 :         visit_target_symbol_arg (e);
    5942                 :            :     }
    5943         [ #  # ]:            :   catch (const semantic_error &er)
    5944                 :            :     {
    5945         [ #  # ]:            :       e->chain (er);
    5946         [ #  # ]:            :       provide (e);
    5947                 :            :     }
    5948                 :         72 : }
    5949                 :            : 
    5950                 :            : 
    5951                 :            : void
    5952                 :          0 : sdt_uprobe_var_expanding_visitor::visit_cast_op (cast_op* e)
    5953                 :            : {
    5954                 :            :   // Fill in our current module context if needed
    5955         [ #  # ]:          0 :   if (e->module.empty())
    5956                 :          0 :     e->module = process_name;
    5957                 :            : 
    5958                 :          0 :   var_expanding_visitor::visit_cast_op(e);
    5959                 :          0 : }
    5960                 :            : 
    5961                 :            : 
    5962                 :            : void
    5963                 :          0 : plt_expanding_visitor::visit_target_symbol (target_symbol *e)
    5964                 :            : {
    5965                 :            :   try
    5966                 :            :     {
    5967 [ #  # ][ #  # ]:          0 :       if (e->name == "$$name")
    5968                 :            :         {
    5969 [ #  # ][ #  # ]:          0 :           literal_string *myname = new literal_string (entry);
    5970                 :          0 :           myname->tok = e->tok;
    5971         [ #  # ]:          0 :           provide(myname);
    5972                 :          0 :           return;
    5973                 :            :         }
    5974                 :            : 
    5975                 :            :       // variable not found -> throw a semantic error
    5976                 :            :       // (only to be caught right away, but this may be more complex later...)
    5977         [ #  # ]:          0 :       string alternatives = "$$name";
    5978                 :          0 :       throw semantic_error(_F("unable to find plt variable '%s' (alternatives: %s)",
    5979 [ #  # ][ #  # ]:          0 :                               e->name.c_str(), alternatives.c_str()), e->tok);
         [ #  # ][ #  # ]
    5980                 :            :     }
    5981         [ #  # ]:            :   catch (const semantic_error &er)
    5982                 :            :     {
    5983         [ #  # ]:            :       e->chain (er);
    5984         [ #  # ]:            :       provide (e);
    5985                 :            :     }
    5986                 :            : }
    5987                 :            : 
    5988                 :            : 
    5989 [ +  - ][ +  - ]:         16 : struct sdt_query : public base_query
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ -  + ]
    5990                 :            : {
    5991                 :            :   sdt_query(probe * base_probe, probe_point * base_loc,
    5992                 :            :             dwflpp & dw, literal_map_t const & params,
    5993                 :            :             vector<derived_probe *> & results, const string user_lib);
    5994                 :            : 
    5995                 :            :   void query_library (const char *data);
    5996                 :          0 :   void query_plt (const char *entry, size_t addr) {}
    5997                 :            :   void handle_query_module();
    5998                 :            : 
    5999                 :            : private:
    6000                 :            :   stap_sdt_probe_type probe_type;
    6001                 :            :   enum { probe_section=0, note_section=1, unknown_section=-1 } probe_loc;
    6002                 :            :   probe * base_probe;
    6003                 :            :   probe_point * base_loc;
    6004                 :            :   literal_map_t const & params;
    6005                 :            :   vector<derived_probe *> & results;
    6006                 :            :   string pp_mark;
    6007                 :            :   string pp_provider;
    6008                 :            :   string user_lib;
    6009                 :            : 
    6010                 :            :   set<string> probes_handled;
    6011                 :            : 
    6012                 :            :   Elf_Data *pdata;
    6013                 :            :   size_t probe_scn_offset;
    6014                 :            :   size_t probe_scn_addr;
    6015                 :            :   uint64_t arg_count;
    6016                 :            :   GElf_Addr base;
    6017                 :            :   GElf_Addr pc;
    6018                 :            :   string arg_string;
    6019                 :            :   string probe_name;
    6020                 :            :   string provider_name;
    6021                 :            :   GElf_Addr semaphore_load_offset;
    6022                 :            :   Dwarf_Addr semaphore;
    6023                 :            : 
    6024                 :            :   bool init_probe_scn();
    6025                 :            :   bool get_next_probe();
    6026                 :            :   void iterate_over_probe_entries();
    6027                 :            :   void handle_probe_entry();
    6028                 :            : 
    6029                 :            :   static void setup_note_probe_entry_callback (void *object, int type, const char *data, size_t len);
    6030                 :            :   void setup_note_probe_entry (int type, const char *data, size_t len);
    6031                 :            : 
    6032                 :            :   void convert_probe(probe *base);
    6033                 :            :   void record_semaphore(vector<derived_probe *> & results, unsigned start);
    6034                 :            :   probe* convert_location();
    6035 [ +  - ][ +  - ]:         72 :   bool have_uprobe() {return probe_type == uprobe1_type || probe_type == uprobe2_type || probe_type == uprobe3_type;}
                 [ +  - ]
    6036                 :         72 :   bool have_debuginfo_uprobe(bool need_debug_info)
    6037                 :            :   {return probe_type == uprobe1_type
    6038                 :            :       || ((probe_type == uprobe2_type || probe_type == uprobe3_type)
    6039 [ +  - ][ +  - ]:         72 :           && need_debug_info);}
         [ +  - ][ +  + ]
    6040 [ +  - ][ +  - ]:         72 :   bool have_debuginfoless_uprobe() {return probe_type == uprobe2_type || probe_type == uprobe3_type;}
    6041                 :            : };
    6042                 :            : 
    6043                 :            : 
    6044                 :         16 : sdt_query::sdt_query(probe * base_probe, probe_point * base_loc,
    6045                 :            :                      dwflpp & dw, literal_map_t const & params,
    6046                 :            :                      vector<derived_probe *> & results, const string user_lib):
    6047                 :            :   base_query(dw, params), probe_type(unknown_probe_type),
    6048                 :            :   probe_loc(unknown_section), base_probe(base_probe),
    6049                 :            :   base_loc(base_loc), params(params), results(results), user_lib(user_lib),
    6050                 :            :   probe_scn_offset(0), probe_scn_addr(0), arg_count(0), base(0), pc(0),
    6051 [ +  - ][ +  - ]:         16 :   semaphore_load_offset(0), semaphore(0)
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    6052                 :            : {
    6053 [ +  - ][ -  + ]:         16 :   assert(get_string_param(params, TOK_MARK, pp_mark));
    6054         [ +  - ]:         16 :   get_string_param(params, TOK_PROVIDER, pp_provider); // pp_provider == "" -> unspecified
    6055                 :            : 
    6056                 :            :   // PR10245: permit usage of dtrace-y "-" separator in marker name;
    6057                 :            :   // map it to double-underscores.
    6058                 :         16 :   size_t pos = 0;
    6059                 :          6 :   while (1) // there may be more than one
    6060                 :            :     {
    6061         [ +  - ]:         22 :       size_t i = pp_mark.find("-", pos);
    6062         [ +  + ]:         22 :       if (i == string::npos) break;
    6063         [ +  - ]:          6 :       pp_mark.replace (i, 1, "__");
    6064                 :          6 :       pos = i+1; // resume searching after the inserted __
    6065                 :            :     }
    6066                 :            : 
    6067                 :            :   // XXX: same for pp_provider?
    6068                 :         16 : }
    6069                 :            : 
    6070                 :            : 
    6071                 :            : void
    6072                 :         72 : sdt_query::handle_probe_entry()
    6073                 :            : {
    6074 [ -  + ][ #  # ]:        144 :   if (! have_uprobe()
                 [ +  - ]
    6075 [ #  # ][ -  + ]:         72 :       && !probes_handled.insert(probe_name).second)
                 [ #  # ]
    6076                 :         72 :     return;
    6077                 :            : 
    6078         [ -  + ]:         72 :   if (sess.verbose > 3)
    6079                 :            :     {
    6080                 :            :       //TRANSLATORS: Describing what probe type (kprobe or uprobe) the probe 
    6081                 :            :       //TRANSLATORS: is matched to.
    6082 [ #  # ][ #  # ]:          0 :       clog << _F("matched probe_name %s probe type ", probe_name.c_str());
         [ #  # ][ #  # ]
    6083   [ #  #  #  # ]:          0 :       switch (probe_type)
    6084                 :            :         {
    6085                 :            :         case uprobe1_type:
    6086 [ #  # ][ #  # ]:          0 :           clog << "uprobe1 at 0x" << hex << pc << dec << endl;
         [ #  # ][ #  # ]
                 [ #  # ]
    6087                 :          0 :           break;
    6088                 :            :         case uprobe2_type:
    6089 [ #  # ][ #  # ]:          0 :           clog << "uprobe2 at 0x" << hex << pc << dec << endl;
         [ #  # ][ #  # ]
                 [ #  # ]
    6090                 :          0 :           break;
    6091                 :            :         case uprobe3_type:
    6092 [ #  # ][ #  # ]:          0 :           clog << "uprobe3 at 0x" << hex << pc << dec << endl;
         [ #  # ][ #  # ]
                 [ #  # ]
    6093                 :          0 :           break;
    6094                 :            :         default:
    6095 [ #  # ][ #  # ]:          0 :           clog << "unknown!" << endl;
    6096                 :          0 :           break;
    6097                 :            :         }
    6098                 :            :     }
    6099                 :            : 
    6100                 :            :   // Extend the derivation chain
    6101         [ +  - ]:         72 :   probe *new_base = convert_location();
    6102                 :         72 :   probe_point *new_location = new_base->locations[0];
    6103                 :            : 
    6104                 :         72 :   bool need_debug_info = false;
    6105                 :            : 
    6106                 :            :   // We could get the Elf* from either dwarf_getelf(dwfl_module_getdwarf(...))
    6107                 :            :   // or dwfl_module_getelf(...).  We only need it for the machine type, which
    6108                 :            :   // should be the same.  The bias is used for relocating debuginfoless probes,
    6109                 :            :   // though, so that must come from the possibly-prelinked ELF file, not DWARF.
    6110                 :            :   Dwarf_Addr bias;
    6111         [ +  - ]:         72 :   Elf* elf = dwfl_module_getelf (dw.mod_info->mod, &bias);
    6112                 :            : 
    6113                 :            :   /* Figure out the architecture of this particular ELF file.  The
    6114                 :            :      dwarfless register-name mappings depend on it. */
    6115                 :            :   GElf_Ehdr ehdr_mem;
    6116         [ +  - ]:         72 :   GElf_Ehdr* em = gelf_getehdr (elf, &ehdr_mem);
    6117 [ -  + ][ #  # ]:         72 :   if (em == 0) { dwfl_assert ("dwfl_getehdr", dwfl_errno()); }
         [ #  # ][ #  # ]
                 [ #  # ]
    6118         [ -  + ]:         72 :   assert(em);
    6119                 :         72 :   int elf_machine = em->e_machine;
    6120                 :            :   sdt_uprobe_var_expanding_visitor svv (sess, elf_machine, module_val,
    6121                 :            :                                         provider_name, probe_name,
    6122         [ +  - ]:         72 :                                         probe_type, arg_string, arg_count);
    6123         [ +  - ]:         72 :   svv.replace (new_base->body);
    6124                 :         72 :   need_debug_info = svv.need_debug_info;
    6125                 :            : 
    6126                 :            :   // XXX: why not derive_probes() in the uprobes case too?
    6127         [ +  - ]:         72 :   literal_map_t params;
    6128         [ +  + ]:        216 :   for (unsigned i = 0; i < new_location->components.size(); ++i)
    6129                 :            :    {
    6130                 :        144 :       probe_point::component *c = new_location->components[i];
    6131         [ +  - ]:        144 :       params[c->functor] = c->arg;
    6132                 :            :    }
    6133                 :            : 
    6134                 :         72 :   unsigned prior_results_size = results.size();
    6135 [ +  - ][ +  - ]:         72 :   dwarf_query q(new_base, new_location, dw, params, results, "", "");
         [ +  - ][ +  - ]
                 [ +  - ]
    6136                 :         72 :   q.has_mark = true; // enables mid-statement probing
    6137                 :            : 
    6138                 :            :   // V1 probes always need dwarf info
    6139                 :            :   // V2+ probes need dwarf info in case of a variable reference
    6140         [ +  + ]:         72 :   if (have_debuginfo_uprobe(need_debug_info))
    6141         [ +  - ]:         24 :     dw.iterate_over_modules(&query_module, &q);
    6142                 :            : 
    6143                 :            :   // For V2+ probes, if variable references weren't used or failed (PR14369),
    6144                 :            :   // then try with the more direct approach.  Unresolved $vars might still
    6145                 :            :   // cause their own error, but this gives them a chance to be optimized out.
    6146 [ +  - ][ +  + ]:         72 :   if (have_debuginfoless_uprobe() && results.size() == prior_results_size)
                 [ +  + ]
    6147                 :            :     {
    6148         [ +  - ]:         48 :       string section;
    6149                 :         48 :       Dwarf_Addr reloc_addr = q.statement_num_val + bias;
    6150 [ +  - ][ -  + ]:         48 :       if (dwfl_module_relocations (q.dw.mod_info->mod) > 0)
    6151                 :            :         {
    6152         [ #  # ]:          0 :           dwfl_module_relocate_address (q.dw.mod_info->mod, &reloc_addr);
    6153         [ #  # ]:          0 :           section = ".dynamic";
    6154                 :            :         }
    6155                 :            :       else
    6156         [ +  - ]:         48 :         section = ".absolute";
    6157                 :            : 
    6158                 :            :       uprobe_derived_probe* p =
    6159                 :            :         new uprobe_derived_probe ("", "", 0,
    6160                 :            :                                   path_remove_sysroot(sess,q.module_val),
    6161                 :            :                                   section,
    6162 [ +  - ][ +  - ]:         48 :                                   q.statement_num_val, reloc_addr, q, 0);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
    6163         [ +  - ]:         48 :       p->saveargs (arg_count);
    6164 [ +  - ][ +  - ]:         48 :       results.push_back (p);
    6165                 :            :     }
    6166         [ +  - ]:         72 :   sess.unwindsym_modules.insert (dw.module_name);
    6167 [ +  - ][ +  - ]:         72 :   record_semaphore(results, prior_results_size);
         [ +  - ][ +  - ]
    6168                 :            : }
    6169                 :            : 
    6170                 :            : 
    6171                 :            : void
    6172                 :         10 : sdt_query::handle_query_module()
    6173                 :            : {
    6174         [ +  + ]:         10 :   if (!init_probe_scn())
    6175                 :         10 :     return;
    6176                 :            : 
    6177         [ -  + ]:          3 :   if (sess.verbose > 3)
    6178                 :          0 :     clog << "TOK_MARK: " << pp_mark << " TOK_PROVIDER: " << pp_provider << endl;
    6179                 :            : 
    6180         [ +  - ]:          3 :   if (probe_loc == note_section)
    6181                 :            :     {
    6182                 :            :       GElf_Shdr shdr_mem;
    6183 [ +  - ][ +  - ]:          3 :       GElf_Shdr *shdr = dw.get_section (".stapsdt.base", &shdr_mem);
                 [ +  - ]
    6184                 :            : 
    6185                 :            :       // The 'base' lets us adjust the hardcoded addresses in notes for prelink
    6186                 :            :       // effects.  The 'semaphore_load_offset' accounts for the difference in
    6187                 :            :       // load addresses between text and data, so the semaphore can be
    6188                 :            :       // converted to a file offset if needed.
    6189         [ +  - ]:          3 :       if (shdr)
    6190                 :            :         {
    6191                 :          3 :           base = shdr->sh_addr;
    6192                 :          3 :           GElf_Addr base_offset = shdr->sh_offset;
    6193 [ +  - ][ +  - ]:          3 :           shdr = dw.get_section (".probes", &shdr_mem);
                 [ +  - ]
    6194         [ -  + ]:          3 :           if (shdr)
    6195                 :            :             semaphore_load_offset =
    6196                 :          0 :               (shdr->sh_addr - shdr->sh_offset) - (base - base_offset);
    6197                 :            :         }
    6198                 :            :       else
    6199                 :          0 :         base = semaphore_load_offset = 0;
    6200                 :            : 
    6201         [ +  - ]:          3 :       dw.iterate_over_notes ((void*) this, &sdt_query::setup_note_probe_entry_callback);
    6202                 :            :     }
    6203         [ #  # ]:          0 :   else if (probe_loc == probe_section)
    6204                 :          0 :     iterate_over_probe_entries ();
    6205                 :            : }
    6206                 :            : 
    6207                 :            : 
    6208                 :            : bool
    6209                 :         10 : sdt_query::init_probe_scn()
    6210                 :            : {
    6211                 :            :   Elf* elf;
    6212                 :            :   GElf_Shdr shdr_mem;
    6213                 :            : 
    6214 [ +  - ][ +  - ]:         10 :   GElf_Shdr *shdr = dw.get_section (".note.stapsdt", &shdr_mem);
                 [ +  - ]
    6215         [ +  + ]:         10 :   if (shdr)
    6216                 :            :     {
    6217                 :          3 :       probe_loc = note_section;
    6218                 :          3 :       return true;
    6219                 :            :     }
    6220                 :            : 
    6221 [ +  - ][ +  - ]:          7 :   shdr = dw.get_section (".probes", &shdr_mem, &elf);
                 [ +  - ]
    6222         [ -  + ]:          7 :   if (shdr)
    6223                 :            :     {
    6224         [ #  # ]:          0 :       pdata = elf_getdata_rawchunk (elf, shdr->sh_offset, shdr->sh_size, ELF_T_BYTE);
    6225                 :          0 :       probe_scn_offset = 0;
    6226                 :          0 :       probe_scn_addr = shdr->sh_addr;
    6227         [ #  # ]:          0 :       assert (pdata != NULL);
    6228         [ #  # ]:          0 :       if (sess.verbose > 4)
    6229 [ #  # ][ #  # ]:          0 :         clog << "got .probes elf scn_addr@0x" << probe_scn_addr << ", size: "
                 [ #  # ]
    6230 [ #  # ][ #  # ]:          0 :              << pdata->d_size << endl;
    6231                 :          0 :       probe_loc = probe_section;
    6232                 :          0 :       return true;
    6233                 :            :     }
    6234                 :            :   else
    6235                 :         10 :     return false;
    6236                 :            : }
    6237                 :            : 
    6238                 :            : void
    6239                 :         72 : sdt_query::setup_note_probe_entry_callback (void *object, int type, const char *data, size_t len)
    6240                 :            : {
    6241                 :         72 :   sdt_query *me = (sdt_query*)object;
    6242                 :         72 :   me->setup_note_probe_entry (type, data, len);
    6243                 :         72 : }
    6244                 :            : 
    6245                 :            : 
    6246                 :            : void
    6247                 :         72 : sdt_query::setup_note_probe_entry (int type, const char *data, size_t len)
    6248                 :            : {
    6249                 :            :   //  if (nhdr.n_namesz == sizeof _SDT_NOTE_NAME
    6250                 :            :   //      && !memcmp (data->d_buf + name_off,
    6251                 :            :   //              _SDT_NOTE_NAME, sizeof _SDT_NOTE_NAME))
    6252                 :            : 
    6253                 :            :   // probes are in the .note.stapsdt section
    6254                 :            : #define _SDT_NOTE_TYPE 3
    6255         [ +  - ]:         72 :   if (type != _SDT_NOTE_TYPE)
    6256                 :            :     return;
    6257                 :            : 
    6258                 :            :   union
    6259                 :            :   {
    6260                 :            :     Elf64_Addr a64[3];
    6261                 :            :     Elf32_Addr a32[3];
    6262                 :            :   } buf;
    6263                 :            :   Dwarf_Addr bias;
    6264         [ +  - ]:         72 :   Elf* elf = (dwfl_module_getelf (dw.mod_info->mod, &bias));
    6265                 :            :   Elf_Data dst =
    6266                 :            :     {
    6267                 :            :       &buf, ELF_T_ADDR, EV_CURRENT,
    6268         [ +  - ]:         72 :       gelf_fsize (elf, ELF_T_ADDR, 3, EV_CURRENT), 0, 0
    6269                 :        144 :     };
    6270         [ -  + ]:         72 :   assert (dst.d_size <= sizeof buf);
    6271                 :            : 
    6272         [ +  - ]:         72 :   if (len < dst.d_size + 3)
    6273                 :            :     return;
    6274                 :            : 
    6275                 :            :   Elf_Data src =
    6276                 :            :     {
    6277                 :            :       (void *) data, ELF_T_ADDR, EV_CURRENT,
    6278                 :            :       dst.d_size, 0, 0
    6279                 :         72 :     };
    6280                 :            : 
    6281         [ -  + ]:         72 :   if (gelf_xlatetom (elf, &dst, &src,
    6282 [ +  - ][ +  - ]:         72 :                       elf_getident (elf, NULL)[EI_DATA]) == NULL)
    6283 [ #  # ][ #  # ]:          0 :     printf ("gelf_xlatetom: %s", elf_errmsg (-1));
    6284                 :            : 
    6285                 :         72 :   probe_type = uprobe3_type;
    6286                 :         72 :   const char * provider = data + dst.d_size;
    6287                 :            : 
    6288                 :         72 :   const char *name = (const char*)memchr (provider, '\0', data + len - provider);
    6289         [ +  - ]:         72 :   if(name++ == NULL)
    6290                 :            :     return;
    6291                 :            : 
    6292                 :         72 :   const char *args = (const char*)memchr (name, '\0', data + len - name);
    6293 [ +  - ][ -  + ]:         72 :   if (args++ == NULL || memchr (args, '\0', data + len - name) != data + len - 1)
                 [ +  - ]
    6294                 :            :     return;
    6295                 :            : 
    6296         [ +  - ]:         72 :   provider_name = provider;
    6297         [ +  - ]:         72 :   probe_name = name;
    6298         [ +  - ]:         72 :   arg_string = args;
    6299                 :            : 
    6300                 :            :   // Did we find a matching probe?
    6301 [ +  - ][ +  - ]:        144 :   if (! (dw.function_name_matches_pattern (probe_name, pp_mark)
    6302         [ +  - ]:         72 :          && ((pp_provider == "")
    6303 [ +  - ][ -  + ]:        144 :              || dw.function_name_matches_pattern (provider_name, pp_provider))))
         [ #  # ][ #  # ]
    6304                 :            :     return;
    6305                 :            : 
    6306                 :            :   // PR13934: Assembly probes are not forced to use the N@OP form.
    6307                 :            :   // If we have '@' then great, else count based on space-delimiters.
    6308 [ +  - ][ +  - ]:         72 :   arg_count = count(arg_string.begin(), arg_string.end(), '@');
                 [ +  - ]
    6309 [ -  + ][ #  # ]:         72 :   if (!arg_count && !arg_string.empty())
         [ #  # ][ -  + ]
    6310 [ #  # ][ #  # ]:          0 :     arg_count = 1 + count(arg_string.begin(), arg_string.end(), ' ');
                 [ #  # ]
    6311                 :            : 
    6312                 :            :   GElf_Addr base_ref;
    6313 [ +  - ][ +  - ]:         72 :   if (gelf_getclass (elf) == ELFCLASS32)
    6314                 :            :     {
    6315                 :         72 :       pc = buf.a32[0];
    6316                 :         72 :       base_ref = buf.a32[1];
    6317                 :         72 :       semaphore = buf.a32[2];
    6318                 :            :     }
    6319                 :            :   else
    6320                 :            :     {
    6321                 :          0 :       pc = buf.a64[0];
    6322                 :          0 :       base_ref = buf.a64[1];
    6323                 :          0 :       semaphore = buf.a64[2];
    6324                 :            :     }
    6325                 :            : 
    6326                 :         72 :   semaphore += base - base_ref;
    6327                 :         72 :   pc += base - base_ref;
    6328                 :            : 
    6329                 :            :   // The semaphore also needs the ELF bias added now, so
    6330                 :            :   // record_semaphore can properly relocate it later.
    6331                 :         72 :   semaphore += bias;
    6332                 :            : 
    6333         [ -  + ]:         72 :   if (sess.verbose > 4)
    6334 [ #  # ][ #  # ]:          0 :     clog << _F(" saw .note.stapsdt %s%s ", probe_name.c_str(), (provider_name != "" ? _(" (provider ")+provider_name+") " : "").c_str()) << "@0x" << hex << pc << dec << endl;
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
           [ #  #  #  # ]
    6335                 :            : 
    6336         [ +  - ]:         72 :   handle_probe_entry();
    6337                 :            : }
    6338                 :            : 
    6339                 :            : 
    6340                 :            : void
    6341                 :          0 : sdt_query::iterate_over_probe_entries()
    6342                 :            : {
    6343                 :            :   // probes are in the .probe section
    6344         [ #  # ]:          0 :   while (probe_scn_offset < pdata->d_size)
    6345                 :            :     {
    6346                 :          0 :       stap_sdt_probe_entry_v1 *pbe_v1 = (stap_sdt_probe_entry_v1 *) ((char*)pdata->d_buf + probe_scn_offset);
    6347                 :          0 :       stap_sdt_probe_entry_v2 *pbe_v2 = (stap_sdt_probe_entry_v2 *) ((char*)pdata->d_buf + probe_scn_offset);
    6348                 :          0 :       probe_type = (stap_sdt_probe_type)(pbe_v1->type_a);
    6349         [ #  # ]:          0 :       if (! have_uprobe())
    6350                 :            :         {
    6351                 :            :           // Unless this is a mangled .probes section, this happens
    6352                 :            :           // because the name of the probe comes first, followed by
    6353                 :            :           // the sentinel.
    6354         [ #  # ]:          0 :           if (sess.verbose > 5)
    6355 [ #  # ][ #  # ]:          0 :             clog << _F("got unknown probe_type : 0x%x", probe_type) << endl;
    6356                 :          0 :           probe_scn_offset += sizeof(__uint32_t);
    6357                 :          0 :           continue;
    6358                 :            :         }
    6359         [ #  # ]:          0 :       if ((long)pbe_v1 % sizeof(__uint64_t)) // we have stap_sdt_probe_entry_v1.type_b
    6360                 :            :         {
    6361                 :          0 :           pbe_v1 = (stap_sdt_probe_entry_v1*)((char*)pbe_v1 - sizeof(__uint32_t));
    6362         [ #  # ]:          0 :           if (pbe_v1->type_b != uprobe1_type)
    6363                 :          0 :             continue;
    6364                 :            :         }
    6365                 :            : 
    6366         [ #  # ]:          0 :       if (probe_type == uprobe1_type)
    6367                 :            :         {
    6368         [ #  # ]:          0 :           if (pbe_v1->name == 0) // No name possibly means we have a .so with a relocation
    6369                 :          0 :             return;
    6370                 :          0 :           semaphore = 0;
    6371                 :          0 :           probe_name = (char*)((char*)pdata->d_buf + pbe_v1->name - (char*)probe_scn_addr);
    6372                 :          0 :           provider_name = ""; // unknown
    6373                 :          0 :           pc = pbe_v1->arg;
    6374                 :          0 :           arg_count = 0;
    6375                 :          0 :           probe_scn_offset += sizeof (stap_sdt_probe_entry_v1);
    6376                 :            :         }
    6377         [ #  # ]:          0 :       else if (probe_type == uprobe2_type)
    6378                 :            :         {
    6379         [ #  # ]:          0 :           if (pbe_v2->name == 0) // No name possibly means we have a .so with a relocation
    6380                 :          0 :             return;
    6381                 :          0 :           semaphore = pbe_v2->semaphore;
    6382                 :          0 :           probe_name = (char*)((char*)pdata->d_buf + pbe_v2->name - (char*)probe_scn_addr);
    6383                 :          0 :           provider_name = (char*)((char*)pdata->d_buf + pbe_v2->provider - (char*)probe_scn_addr);
    6384                 :          0 :           arg_count = pbe_v2->arg_count;
    6385                 :          0 :           pc = pbe_v2->pc;
    6386         [ #  # ]:          0 :           if (pbe_v2->arg_string)
    6387                 :          0 :             arg_string = (char*)((char*)pdata->d_buf + pbe_v2->arg_string - (char*)probe_scn_addr);
    6388                 :            :           // skip over pbe_v2, probe_name text and provider text
    6389                 :          0 :           probe_scn_offset = ((long)(pbe_v2->name) - (long)(probe_scn_addr)) + probe_name.length();
    6390                 :          0 :           probe_scn_offset += sizeof (__uint32_t) - probe_scn_offset % sizeof (__uint32_t);
    6391                 :            :         }
    6392         [ #  # ]:          0 :       if (sess.verbose > 4)
    6393 [ #  # ][ #  # ]:          0 :         clog << _("saw .probes ") << probe_name << (provider_name != "" ? _(" (provider ")+provider_name+") " : "")
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
           [ #  #  #  # ]
    6394 [ #  # ][ #  # ]:          0 :              << "@0x" << hex << pc << dec << endl;
         [ #  # ][ #  # ]
                 [ #  # ]
    6395                 :            : 
    6396   [ #  #  #  #  :          0 :       if (dw.function_name_matches_pattern (probe_name, pp_mark)
           #  # ][ #  # ]
    6397                 :          0 :           && ((pp_provider == "") || dw.function_name_matches_pattern (provider_name, pp_provider)))
    6398                 :          0 :         handle_probe_entry ();
    6399                 :            :     }
    6400                 :            : }
    6401                 :            : 
    6402                 :            : 
    6403                 :            : void
    6404                 :         72 : sdt_query::record_semaphore (vector<derived_probe *> & results, unsigned start)
    6405                 :            : {
    6406         [ +  + ]:        216 :   for (unsigned i=0; i<2; i++) {
    6407                 :            :     // prefer with-provider symbol; look without provider prefix for backward compatibility only
    6408 [ +  + ][ +  - ]:        144 :     string semaphore = (i==0 ? (provider_name+"_") : "") + probe_name + "_semaphore";
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  + ]
                 [ #  # ]
    6409                 :            :     // XXX: multiple addresses?
    6410         [ -  + ]:        144 :     if (sess.verbose > 2)
    6411 [ #  # ][ #  # ]:          0 :       clog << _F("looking for semaphore symbol %s ", semaphore.c_str());
         [ #  # ][ #  # ]
    6412                 :            : 
    6413                 :            :     Dwarf_Addr addr;
    6414         [ -  + ]:        144 :     if (this->semaphore)
    6415                 :          0 :       addr = this->semaphore;
    6416                 :            :     else
    6417 [ +  - ][ +  - ]:        144 :       addr  = lookup_symbol_address(dw.module, semaphore.c_str());
    6418         [ -  + ]:        144 :     if (addr)
    6419                 :            :       {
    6420 [ #  # ][ #  # ]:          0 :         if (dwfl_module_relocations (dw.module) > 0)
    6421         [ #  # ]:          0 :           dwfl_module_relocate_address (dw.module, &addr);
    6422                 :            :         // XXX: relocation basis?
    6423                 :            : 
    6424                 :            :         // Dyninst needs the *file*-based offset for semaphores,
    6425                 :            :         // so subtract the difference in load addresses between .text and .probes
    6426         [ #  # ]:          0 :         if (dw.sess.runtime_usermode_p())
    6427                 :          0 :           addr -= semaphore_load_offset;
    6428                 :            : 
    6429         [ #  # ]:          0 :         for (unsigned i = start; i < results.size(); ++i)
    6430                 :          0 :           results[i]->sdt_semaphore_addr = addr;
    6431         [ #  # ]:          0 :         if (sess.verbose > 2)
    6432 [ #  # ][ #  # ]:          0 :           clog << _(", found at 0x") << hex << addr << dec << endl;
         [ #  # ][ #  # ]
                 [ #  # ]
    6433                 :         72 :         return;
    6434                 :            :       }
    6435                 :            :     else
    6436         [ -  + ]:        144 :       if (sess.verbose > 2)
    6437 [ #  # ][ #  # ]:        144 :         clog << _(", not found") << endl;
    6438 [ +  - ][ +  - ]:        144 :   }
    6439                 :            : }
    6440                 :            : 
    6441                 :            : 
    6442                 :            : void
    6443                 :          0 : sdt_query::convert_probe (probe *base)
    6444                 :            : {
    6445         [ #  # ]:          0 :   block *b = new block;
    6446                 :          0 :   b->tok = base->body->tok;
    6447                 :            : 
    6448                 :            :   // Generate: if (arg1 != mark("label")) next;
    6449         [ #  # ]:          0 :   functioncall *fc = new functioncall;
    6450                 :          0 :   fc->function = "ulong_arg";
    6451                 :          0 :   fc->tok = b->tok;
    6452         [ #  # ]:          0 :   literal_number* num = new literal_number(1);
    6453                 :          0 :   num->tok = b->tok;
    6454         [ #  # ]:          0 :   fc->args.push_back(num);
    6455                 :            : 
    6456         [ #  # ]:          0 :   functioncall *fcus = new functioncall;
    6457                 :          0 :   fcus->function = "user_string";
    6458                 :          0 :   fcus->type = pe_string;
    6459                 :          0 :   fcus->tok = b->tok;
    6460         [ #  # ]:          0 :   fcus->args.push_back(fc);
    6461                 :            : 
    6462         [ #  # ]:          0 :   if_statement *is = new if_statement;
    6463         [ #  # ]:          0 :   is->thenblock = new next_statement;
    6464                 :          0 :   is->elseblock = NULL;
    6465                 :          0 :   is->tok = b->tok;
    6466                 :          0 :   is->thenblock->tok = b->tok;
    6467         [ #  # ]:          0 :   comparison *be = new comparison;
    6468                 :          0 :   be->op = "!=";
    6469                 :          0 :   be->tok = b->tok;
    6470                 :          0 :   be->left = fcus;
    6471         [ #  # ]:          0 :   be->right = new literal_string(probe_name);
    6472                 :          0 :   be->right->tok = b->tok;
    6473                 :          0 :   is->condition = be;
    6474         [ #  # ]:          0 :   b->statements.push_back(is);
    6475                 :            : 
    6476                 :            :   // Now replace the body
    6477                 :          0 :   b->statements.push_back(base->body);
    6478                 :          0 :   base->body = b;
    6479                 :          0 : }
    6480                 :            : 
    6481                 :            : 
    6482                 :            : probe*
    6483                 :         72 : sdt_query::convert_location ()
    6484                 :            : {
    6485 [ +  - ][ +  - ]:         72 :   probe_point* specific_loc = new probe_point(*base_loc);
    6486         [ +  - ]:         72 :   vector<probe_point::component*> derived_comps;
    6487                 :            : 
    6488                 :         72 :   vector<probe_point::component*>::iterator it;
    6489 [ +  - ][ +  - ]:        432 :   for (it = specific_loc->components.begin();
                 [ +  + ]
    6490         [ +  - ]:        216 :        it != specific_loc->components.end(); ++it)
    6491 [ +  - ][ +  + ]:        144 :     if ((*it)->functor == TOK_PROCESS)
    6492                 :            :       {
    6493                 :            :         // copy the process name
    6494         [ +  - ]:         72 :         derived_comps.push_back(*it);
    6495                 :            :       }
    6496 [ +  - ][ -  + ]:         72 :     else if ((*it)->functor == TOK_LIBRARY)
    6497                 :            :       {
    6498                 :            :         // copy the library name for process probes
    6499         [ #  # ]:          0 :         derived_comps.push_back(*it);
    6500                 :            :       }
    6501 [ +  - ][ -  + ]:         72 :     else if ((*it)->functor == TOK_PROVIDER)
    6502                 :            :       {
    6503                 :            :         // replace the possibly wildcarded arg with the specific provider name
    6504                 :          0 :         *it = new probe_point::component(TOK_PROVIDER,
    6505 [ #  # ][ #  # ]:          0 :                                          new literal_string(provider_name));
         [ #  # ][ #  # ]
    6506                 :            :       }
    6507 [ +  - ][ +  - ]:         72 :     else if ((*it)->functor == TOK_MARK)
    6508                 :            :       {
    6509                 :            :         // replace the possibly wildcarded arg with the specific marker name
    6510                 :         72 :         *it = new probe_point::component(TOK_MARK,
    6511 [ +  - ][ +  - ]:         72 :                                          new literal_string(probe_name));
         [ +  - ][ +  - ]
    6512                 :            : 
    6513         [ -  + ]:         72 :         if (sess.verbose > 3)
    6514   [ #  #  #  # ]:          0 :           switch (probe_type)
    6515                 :            :             {
    6516                 :            :             case uprobe1_type:
    6517         [ #  # ]:          0 :               clog << _("probe_type == uprobe1, use statement addr: 0x")
    6518 [ #  # ][ #  # ]:          0 :                    << hex << pc << dec << endl;
         [ #  # ][ #  # ]
    6519                 :          0 :               break;
    6520                 :            :             case uprobe2_type:
    6521         [ #  # ]:          0 :               clog << _("probe_type == uprobe2, use statement addr: 0x")
    6522 [ #  # ][ #  # ]:          0 :                    << hex << pc << dec << endl;
         [ #  # ][ #  # ]
    6523                 :          0 :             break;
    6524                 :            :             case uprobe3_type:
    6525         [ #  # ]:          0 :               clog << _("probe_type == uprobe3, use statement addr: 0x")
    6526 [ #  # ][ #  # ]:          0 :                    << hex << pc << dec << endl;
         [ #  # ][ #  # ]
    6527                 :          0 :               break;
    6528                 :            :             default:
    6529 [ #  # ][ #  # ]:          0 :               clog << _F("probe_type == use_uprobe_no_dwarf, use label name: _stapprobe1_%s",
         [ #  # ][ #  # ]
    6530         [ #  # ]:          0 :                          pp_mark.c_str()) << endl;
    6531                 :            :           }
    6532                 :            : 
    6533         [ +  - ]:         72 :         switch (probe_type)
    6534                 :            :           {
    6535                 :            :           case uprobe1_type:
    6536                 :            :           case uprobe2_type:
    6537                 :            :           case uprobe3_type:
    6538                 :            :             // process("executable").statement(probe_arg)
    6539                 :            :             derived_comps.push_back
    6540                 :            :               (new probe_point::component(TOK_STATEMENT,
    6541 [ +  - ][ +  - ]:         72 :                                           new literal_number(pc, true)));
         [ +  - ][ +  - ]
                 [ +  - ]
    6542                 :         72 :             break;
    6543                 :            : 
    6544                 :            :           default: // deprecated
    6545                 :            :             // process("executable").function("*").label("_stapprobe1_MARK_NAME")
    6546                 :            :             derived_comps.push_back
    6547                 :            :               (new probe_point::component(TOK_FUNCTION,
    6548 [ #  # ][ #  # ]:          0 :                                           new literal_string("*")));
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
    6549                 :            :             derived_comps.push_back
    6550                 :            :               (new probe_point::component(TOK_LABEL,
    6551 [ #  # ][ #  # ]:          0 :                                           new literal_string("_stapprobe1_" + pp_mark)));
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
    6552                 :         72 :             break;
    6553                 :            :           }
    6554                 :            :       }
    6555                 :            : 
    6556 [ +  - ][ +  - ]:         72 :   probe_point* derived_loc = new probe_point(*specific_loc);
    6557         [ +  - ]:         72 :   derived_loc->components = derived_comps;
    6558 [ +  - ][ +  - ]:         72 :   return base_probe->create_alias(derived_loc, specific_loc);
    6559                 :            : }
    6560                 :            : 
    6561                 :            : 
    6562                 :            : void
    6563                 :          0 : sdt_query::query_library (const char *library)
    6564                 :            : {
    6565         [ #  # ]:          0 :     query_one_library (library, dw, user_lib, base_probe, base_loc, results);
    6566                 :          0 : }
    6567                 :            : 
    6568                 :            : 
    6569                 :            : void
    6570                 :      46880 : dwarf_builder::build(systemtap_session & sess,
    6571                 :            :                      probe * base,
    6572                 :            :                      probe_point * location,
    6573                 :            :                      literal_map_t const & parameters,
    6574                 :            :                      vector<derived_probe *> & finished_results)
    6575                 :            : {
    6576                 :            :   // NB: the kernel/user dwlfpp objects are long-lived.
    6577                 :            :   // XXX: but they should be per-session, as this builder object
    6578                 :            :   // may be reused if we try to cross-instrument multiple targets.
    6579                 :            : 
    6580                 :      46880 :   dwflpp* dw = 0;
    6581         [ +  - ]:      46880 :   literal_map_t filled_parameters = parameters;
    6582                 :            : 
    6583         [ +  - ]:      46880 :   string module_name;
    6584 [ +  - ][ +  + ]:      46880 :   if (has_null_param (parameters, TOK_KERNEL))
    6585                 :            :     {
    6586 [ +  - ][ +  + ]:      44801 :       dw = get_kern_dw(sess, "kernel");
                 [ +  - ]
    6587                 :            :     }
    6588 [ +  - ][ +  + ]:       2079 :   else if (get_param (parameters, TOK_MODULE, module_name))
    6589                 :            :     {
    6590                 :       1999 :       size_t dash_pos = 0;
    6591 [ +  - ][ +  + ]:       2011 :       while((dash_pos=module_name.find('-'))!=string::npos)
    6592         [ +  - ]:         12 :         module_name.replace(int(dash_pos),1,"_");
    6593 [ +  - ][ +  - ]:       1999 :       filled_parameters[TOK_MODULE] = new literal_string(module_name);
                 [ +  - ]
    6594                 :            :       // NB: glob patterns get expanded later, during the offline
    6595                 :            :       // elfutils module listing.
    6596         [ +  - ]:       1999 :       dw = get_kern_dw(sess, module_name);
    6597                 :            :     }
    6598 [ +  - ][ +  + ]:         80 :   else if (get_param (parameters, TOK_PROCESS, module_name) || has_null_param(parameters, TOK_PROCESS))
         [ +  - ][ +  - ]
                 [ +  - ]
    6599                 :            :       {
    6600 [ +  - ][ +  - ]:         80 :       module_name = sess.sysroot + module_name;
                 [ +  - ]
    6601 [ +  - ][ +  + ]:         80 :       if(has_null_param(filled_parameters, TOK_PROCESS))
    6602                 :            :         {
    6603                 :            :           wordexp_t words;
    6604 [ +  - ][ +  - ]:          6 :           int rc = wordexp(sess.cmd.c_str(), &words, WRDE_NOCMD|WRDE_UNDEF);
    6605 [ +  - ][ +  + ]:          6 :           if(rc || words.we_wordc <= 0)
    6606 [ +  - ][ +  - ]:          1 :             throw semantic_error(_("unspecified process probe is invalid without a -c COMMAND"));
    6607 [ +  - ][ +  - ]:          5 :           module_name = sess.sysroot + words.we_wordv[0];
                 [ +  - ]
    6608 [ +  - ][ +  - ]:          5 :           filled_parameters[TOK_PROCESS] = new literal_string(module_name);// this needs to be used in place of the blank map
                 [ +  - ]
    6609                 :            :           // in the case of TOK_MARK we need to modify locations as well
    6610         [ +  - ]:         10 :           if(location->components[0]->functor==TOK_PROCESS &&
           [ +  -  +  - ]
                 [ +  - ]
    6611                 :          5 :             location->components[0]->arg == 0)
    6612 [ +  - ][ +  - ]:          6 :             location->components[0]->arg = new literal_string(module_name);
    6613                 :          5 :           wordfree (& words);
    6614                 :            :         } 
    6615                 :            : 
    6616                 :            :       // PR6456  process("/bin/*")  glob handling
    6617 [ +  - ][ +  + ]:         79 :       if (contains_glob_chars (module_name))
    6618                 :            :         {
    6619                 :            :           // Expand glob via rewriting the probe-point process("....")
    6620                 :            :           // parameter, asserted to be the first one.
    6621                 :            : 
    6622         [ -  + ]:         12 :           assert (location->components.size() > 0);
    6623 [ +  - ][ -  + ]:         12 :           assert (location->components[0]->functor == TOK_PROCESS);
    6624         [ -  + ]:         12 :           assert (location->components[0]->arg);
    6625         [ -  + ]:         12 :           literal_string* lit = dynamic_cast<literal_string*>(location->components[0]->arg);
    6626         [ -  + ]:         12 :           assert (lit);
    6627                 :            : 
    6628                 :            :           // Evaluate glob here, and call derive_probes recursively with each match.
    6629                 :            :           glob_t the_blob;
    6630         [ +  - ]:         12 :           int rc = glob (module_name.c_str(), 0, NULL, & the_blob);
    6631         [ -  + ]:         12 :           if (rc)
    6632 [ #  # ][ #  # ]:          0 :             throw semantic_error (_F("glob %s error (%s)", module_name.c_str(), lex_cast(rc).c_str() ));
         [ #  # ][ #  # ]
                 [ #  # ]
    6633         [ +  + ]:         29 :           for (unsigned i = 0; i < the_blob.gl_pathc; ++i)
    6634                 :            :             {
    6635         [ +  - ]:         17 :               assert_no_interrupts();
    6636                 :            : 
    6637                 :         17 :               const char* globbed = the_blob.gl_pathv[i];
    6638                 :            :               struct stat st;
    6639                 :            : 
    6640   [ +  +  +  - ]:         31 :               if (access (globbed, X_OK) == 0
         [ +  - ][ +  + ]
    6641                 :         14 :                   && stat (globbed, &st) == 0
    6642                 :            :                   && S_ISREG (st.st_mode)) // see find_executable()
    6643                 :            :                 {
    6644                 :            :                   // Need to call canonicalize here, in order to path-expand
    6645                 :            :                   // patterns like process("stap*").  Otherwise it may go through
    6646                 :            :                   // to the next round of expansion as ("stap"), leading to a $PATH
    6647                 :            :                   // search that's not consistent with the glob search already done.
    6648                 :            : 
    6649                 :         14 :                   char *cf = canonicalize_file_name (globbed);
    6650         [ +  - ]:         14 :                   if (cf) globbed = cf;
    6651                 :            : 
    6652                 :            :                   // synthesize a new probe_point, with the glob-expanded string
    6653 [ +  - ][ +  - ]:         14 :                   probe_point *pp = new probe_point (*location);
    6654                 :            :                   // PR13338: quote results to prevent recursion
    6655 [ +  - ][ +  - ]:         14 :                   string eglobbed = escape_glob_chars (globbed);
                 [ +  - ]
    6656                 :            : 
    6657         [ +  + ]:         14 :                   if (sess.verbose > 1)
    6658 [ +  - ][ +  - ]:          6 :                     clog << _F("Expanded process(\"%s\") to process(\"%s\")",
         [ +  - ][ +  - ]
                 [ +  - ]
    6659         [ +  - ]:          3 :                                module_name.c_str(), eglobbed.c_str()) << endl;
    6660         [ +  - ]:         14 :                   string eglobbed_tgt = path_remove_sysroot(sess, eglobbed);
    6661                 :            : 
    6662                 :            :                   probe_point::component* ppc = new probe_point::component (TOK_PROCESS,
    6663 [ +  - ][ +  - ]:         14 :                                                     new literal_string (eglobbed_tgt));
         [ +  - ][ +  - ]
    6664                 :         14 :                   ppc->tok = location->components[0]->tok; // overwrite [0] slot, pattern matched above
    6665                 :         14 :                   pp->components[0] = ppc;
    6666                 :            : 
    6667 [ +  - ][ +  - ]:         14 :                   probe* new_probe = new probe (*base, pp);
    6668                 :            : 
    6669                 :            :                   // We override "optional = true" here, as if the
    6670                 :            :                   // wildcarded probe point was given a "?" suffix.
    6671                 :            : 
    6672                 :            :                   // This is because wildcard probes will be expected
    6673                 :            :                   // by users to apply only to some subset of the
    6674                 :            :                   // matching binaries, in the sense of "any", rather
    6675                 :            :                   // than "all", sort of similarly how
    6676                 :            :                   // module("*").function("...") patterns work.
    6677                 :            : 
    6678                 :            :                   derive_probes (sess, new_probe, finished_results,
    6679 [ +  - ][ +  - ]:         14 :                                  true /* NB: not location->optional */ );
                 [ +  - ]
    6680                 :            :                 }
    6681                 :            :             }
    6682                 :            : 
    6683                 :         12 :           globfree (& the_blob);
    6684                 :            :           return; // avoid falling through
    6685                 :            :         }
    6686                 :            : 
    6687                 :            :       // PR13338: unquote glob results
    6688 [ +  - ][ +  - ]:         67 :       module_name = unescape_glob_chars (module_name);
                 [ +  - ]
    6689 [ +  - ][ +  - ]:         67 :       user_path = find_executable (module_name, "", sess.sysenv); // canonicalize it
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    6690                 :            : 
    6691                 :            :       // if the executable starts with "#!", we look for the interpreter of the script
    6692                 :            :       {
    6693 [ +  - ][ +  - ]:         67 :          ifstream script_file (user_path.c_str () );
    6694                 :            : 
    6695 [ +  - ][ +  + ]:         67 :          if (script_file.good ())
    6696                 :            :          {
    6697         [ +  - ]:         60 :            string line;
    6698                 :            : 
    6699         [ +  - ]:         60 :            getline (script_file, line);
    6700                 :            : 
    6701 [ +  - ][ +  + ]:         60 :            if (line.compare (0, 2, "#!") == 0)
    6702                 :            :            {
    6703         [ +  - ]:          1 :               string path_head = line.substr(2);
    6704                 :            : 
    6705                 :            :               // remove white spaces at the beginning of the string
    6706         [ +  - ]:          1 :               size_t p2 = path_head.find_first_not_of(" \t");
    6707                 :            : 
    6708         [ +  - ]:          1 :               if (p2 != string::npos)
    6709                 :            :               {
    6710         [ +  - ]:          1 :                 string path = path_head.substr(p2);
    6711                 :            : 
    6712                 :            :                 // remove white spaces at the end of the string
    6713         [ +  - ]:          1 :                 p2 = path.find_last_not_of(" \t\n");
    6714         [ +  - ]:          1 :                 if (string::npos != p2)
    6715         [ +  - ]:          1 :                   path.erase(p2+1);
    6716                 :            : 
    6717                 :            :                 // handle "#!/usr/bin/env" redirect
    6718                 :          1 :                 size_t offset = 0;
    6719 [ +  - ][ -  + ]:          1 :                 if (path.compare(0, sizeof("/bin/env")-1, "/bin/env") == 0)
    6720                 :            :                 {
    6721                 :          0 :                   offset = sizeof("/bin/env")-1;
    6722                 :            :                 }
    6723 [ +  - ][ -  + ]:          1 :                 else if (path.compare(0, sizeof("/usr/bin/env")-1, "/usr/bin/env") == 0)
    6724                 :            :                 {
    6725                 :          0 :                   offset = sizeof("/usr/bin/env")-1;
    6726                 :            :                 }
    6727                 :            : 
    6728         [ -  + ]:          1 :                 if (offset != 0)
    6729                 :            :                 {
    6730         [ #  # ]:          0 :                     size_t p3 = path.find_first_not_of(" \t", offset);
    6731                 :            : 
    6732         [ #  # ]:          0 :                     if (p3 != string::npos)
    6733                 :            :                     {
    6734         [ #  # ]:          0 :                        string env_path = path.substr(p3);
    6735                 :            :                        user_path = find_executable (env_path, sess.sysroot,
    6736 [ #  # ][ #  # ]:          0 :                                                     sess.sysenv);
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
    6737                 :            :                     }
    6738                 :            :                 }
    6739                 :            :                 else
    6740                 :            :                 {
    6741 [ +  - ][ +  - ]:          1 :                   user_path = find_executable (path, sess.sysroot, sess.sysenv);
         [ +  - ][ +  - ]
                 [ +  - ]
    6742                 :            :                 }
    6743                 :            : 
    6744                 :            :                 struct stat st;
    6745                 :            : 
    6746         [ +  - ]:          2 :                 if (access (user_path.c_str(), X_OK) == 0
           [ +  -  +  - ]
         [ +  - ][ +  - ]
    6747         [ +  - ]:          1 :                   && stat (user_path.c_str(), &st) == 0
    6748                 :            :                   && S_ISREG (st.st_mode)) // see find_executable()
    6749                 :            :                 {
    6750         [ -  + ]:          1 :                   if (sess.verbose > 1)
    6751 [ #  # ][ #  # ]:          0 :                     clog << _F("Expanded process(\"%s\") to process(\"%s\")",
         [ #  # ][ #  # ]
                 [ #  # ]
    6752         [ #  # ]:          0 :                                module_name.c_str(), user_path.c_str()) << endl;
    6753                 :            : 
    6754         [ -  + ]:          1 :                   assert (location->components.size() > 0);
    6755 [ +  - ][ -  + ]:          1 :                   assert (location->components[0]->functor == TOK_PROCESS);
    6756         [ -  + ]:          1 :                   assert (location->components[0]->arg);
    6757         [ -  + ]:          1 :                   literal_string* lit = dynamic_cast<literal_string*>(location->components[0]->arg);
    6758         [ -  + ]:          1 :                   assert (lit);
    6759                 :            : 
    6760                 :            :                   // synthesize a new probe_point, with the expanded string
    6761 [ +  - ][ +  - ]:          1 :                   probe_point *pp = new probe_point (*location);
    6762         [ +  - ]:          1 :                   string user_path_tgt = path_remove_sysroot(sess, user_path);
    6763                 :            :                   probe_point::component* ppc = new probe_point::component (TOK_PROCESS,
    6764 [ +  - ][ +  - ]:          1 :                                                                             new literal_string (user_path_tgt.c_str()));
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    6765                 :          1 :                   ppc->tok = location->components[0]->tok; // overwrite [0] slot, pattern matched above
    6766                 :          1 :                   pp->components[0] = ppc;
    6767                 :            : 
    6768 [ +  - ][ +  - ]:          1 :                   probe* new_probe = new probe (*base, pp);
    6769                 :            : 
    6770         [ +  - ]:          1 :                   derive_probes (sess, new_probe, finished_results);
    6771                 :            : 
    6772         [ +  - ]:          1 :                   script_file.close();
    6773         [ +  - ]:          1 :                   return;
    6774 [ +  - ][ -  + ]:          1 :                 }
    6775 [ +  - ][ -  + ]:         60 :               }
    6776 [ +  - ][ +  + ]:         60 :            }
    6777                 :            :          }
    6778 [ +  - ][ +  - ]:         67 :          script_file.close();
                 [ +  + ]
    6779                 :            :       }
    6780                 :            : 
    6781 [ +  - ][ +  + ]:         91 :       if (get_param (parameters, TOK_LIBRARY, user_lib)
         [ +  - ][ +  + ]
                 [ +  + ]
    6782 [ +  - ][ +  - ]:         24 :           && user_lib.length() && ! contains_glob_chars (user_lib))
    6783                 :            :         {
    6784                 :            :           module_name = find_executable (user_lib, sess.sysroot, sess.sysenv,
    6785 [ +  - ][ +  - ]:         11 :                                          "LD_LIBRARY_PATH");
         [ +  - ][ +  - ]
                 [ +  - ]
    6786 [ +  - ][ -  + ]:         11 :           if (module_name.find('/') == string::npos)
    6787                 :            :             // We didn't find user_lib so use iterate_over_libraries
    6788         [ #  # ]:          0 :             module_name = user_path;
    6789                 :            :         }
    6790                 :            :       else
    6791         [ +  - ]:         55 :         module_name = user_path; // canonicalize it
    6792                 :            : 
    6793                 :            :       // uretprobes aren't available everywhere
    6794 [ +  - ][ +  + ]:         66 :       if (has_null_param(parameters, TOK_RETURN) && !sess.runtime_usermode_p())
         [ +  - ][ +  + ]
    6795                 :            :         {
    6796 [ +  - ][ -  + ]:          1 :           if (kernel_supports_inode_uprobes(sess) &&
         [ #  # ][ -  + ]
    6797         [ #  # ]:          0 :               !kernel_supports_inode_uretprobes(sess))
    6798                 :            :             throw semantic_error
    6799 [ #  # ][ #  # ]:          0 :               (_("process return probes not available [man error::inode-uprobes]"));
    6800                 :            :         }
    6801                 :            : 
    6802                 :            :       // There is a similar check in pass 4 (buildrun), but it is
    6803                 :            :       // needed here too to make sure alternatives for optional
    6804                 :            :       // (? or !) process probes are disposed and/or alternatives
    6805                 :            :       // are selected.
    6806         [ +  - ]:         66 :       if (!sess.runtime_usermode_p())
    6807         [ +  + ]:         66 :         check_process_probe_kernel_support(sess);
    6808                 :            : 
    6809                 :            :       // user-space target; we use one dwflpp instance per module name
    6810                 :            :       // (= program or shared library)
    6811         [ +  - ]:         64 :       dw = get_user_dw(sess, module_name);
    6812                 :            :     }
    6813                 :            : 
    6814         [ -  + ]:      46862 :   if (sess.verbose > 3)
    6815 [ #  # ][ #  # ]:          0 :     clog << _F("dwarf_builder::build for %s", module_name.c_str()) << endl;
         [ #  # ][ #  # ]
                 [ #  # ]
    6816                 :            : 
    6817         [ +  - ]:      46862 :   string dummy_mark_name; // NB: PR10245: dummy value, need not substitute - => __
    6818 [ +  - ][ +  + ]:      46862 :   if (get_param(parameters, TOK_MARK, dummy_mark_name))
    6819                 :            :     {
    6820         [ -  + ]:         16 :       assert(dw);
    6821 [ +  - ][ +  - ]:         16 :       sdt_query sdtq(base, location, *dw, filled_parameters, finished_results, user_lib);
                 [ +  - ]
    6822         [ +  - ]:         16 :       dw->iterate_over_modules(&query_module, &sdtq);
    6823         [ +  - ]:         16 :       return;
    6824                 :            :     }
    6825                 :            : 
    6826                 :      46846 :   unsigned results_pre = finished_results.size();
    6827 [ +  - ][ +  - ]:      46846 :   dwarf_query q(base, location, *dw, filled_parameters, finished_results, user_path, user_lib);
         [ +  - ][ +  - ]
                 [ +  - ]
    6828                 :            : 
    6829                 :            :   // XXX: kernel.statement.absolute is a special case that requires no
    6830                 :            :   // dwfl processing.  This code should be in a separate builder.
    6831 [ +  + ][ +  + ]:      46846 :   if (q.has_kernel && q.has_absolute)
    6832                 :            :     {
    6833                 :            :       // assert guru mode for absolute probes
    6834         [ +  + ]:          5 :       if (! q.base_probe->privileged)
    6835                 :            :         {
    6836                 :          1 :           throw semantic_error (_("absolute statement probe in unprivileged script; need stap -g"),
    6837 [ +  - ][ +  - ]:          1 :                                 q.base_probe->tok);
    6838                 :            :         }
    6839                 :            : 
    6840                 :            :       // For kernel.statement(NUM).absolute probe points, we bypass
    6841                 :            :       // all the debuginfo stuff: We just wire up a
    6842                 :            :       // dwarf_derived_probe right here and now.
    6843                 :            :       dwarf_derived_probe* p =
    6844                 :            :         new dwarf_derived_probe ("", "", 0, "kernel", "",
    6845                 :            :                                  q.statement_num_val, q.statement_num_val,
    6846 [ +  - ][ +  - ]:          4 :                                  q, 0);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
    6847         [ +  - ]:          4 :       finished_results.push_back (p);
    6848 [ +  - ][ +  - ]:          4 :       sess.unwindsym_modules.insert ("kernel");
                 [ +  - ]
    6849                 :            :       return;
    6850                 :            :     }
    6851                 :            : 
    6852         [ +  - ]:      46841 :   dw->iterate_over_modules(&query_module, &q);
    6853                 :            : 
    6854                 :            : 
    6855                 :            :   // PR11553 special processing: .return probes requested, but
    6856                 :            :   // some inlined function instances matched.
    6857         [ +  - ]:      46841 :   unsigned i_n_r = q.inlined_non_returnable.size();
    6858                 :      46841 :   unsigned results_post = finished_results.size();
    6859         [ +  + ]:      46841 :   if (i_n_r > 0)
    6860                 :            :     {
    6861 [ +  + ][ +  + ]:        138 :       if ((results_pre == results_post) && (! sess.suppress_warnings)) // no matches; issue warning
    6862                 :            :         {
    6863         [ +  - ]:          6 :           string quicklist;
    6864 [ +  - ][ +  + ]:         24 :           for (set<string>::iterator it = q.inlined_non_returnable.begin();
    6865         [ +  - ]:         12 :                it != q.inlined_non_returnable.end();
    6866                 :            :                it++)
    6867                 :            :             {
    6868 [ +  - ][ +  - ]:          6 :               quicklist += " " + (*it);
                 [ +  - ]
    6869 [ +  - ][ -  + ]:          6 :               if (quicklist.size() > 80) // heuristic, don't make an overlong report line
    6870                 :            :                 {
    6871         [ #  # ]:          0 :                   quicklist += " ...";
    6872                 :          0 :                   break;
    6873                 :            :                 }
    6874                 :            :             }
    6875                 :            : 
    6876         [ +  - ]:          6 :           sess.print_warning (_F(ngettext("cannot probe .return of %u inlined function %s",
    6877                 :            :                                           "cannot probe .return of %u inlined functions %s",
    6878 [ +  - ][ +  - ]:          6 :                                            quicklist.size()), i_n_r, quicklist.c_str()));
         [ +  - ][ +  - ]
                 [ +  - ]
    6879                 :            :           // There will be also a "no matches" semantic error generated.
    6880                 :            :         }
    6881         [ -  + ]:        138 :       if (sess.verbose > 1)
    6882 [ #  # ][ #  # ]:          0 :         clog << _F(ngettext("skipped .return probe of %u inlined function",
                 [ #  # ]
    6883         [ #  # ]:          0 :                             "skipped .return probe of %u inlined functions", i_n_r), i_n_r) << endl;
    6884 [ +  - ][ -  + ]:        138 :       if ((sess.verbose > 3) || (sess.verbose > 2 && results_pre == results_post)) // issue details with high verbosity
                 [ #  # ]
    6885                 :            :         {
    6886 [ #  # ][ #  # ]:          0 :           for (set<string>::iterator it = q.inlined_non_returnable.begin();
    6887         [ #  # ]:          0 :                it != q.inlined_non_returnable.end();
    6888                 :            :                it++)
    6889 [ #  # ][ #  # ]:          0 :             clog << (*it) << " ";
    6890         [ #  # ]:      46841 :           clog << endl;
    6891                 :            :         }
    6892 [ +  - ][ +  + ]:      46880 :     } // i_n_r > 0
         [ +  - ][ +  + ]
         [ +  - ][ +  + ]
         [ +  - ][ +  + ]
    6893                 :            : }
    6894                 :            : 
    6895                 :       2247 : symbol_table::~symbol_table()
    6896                 :            : {
    6897         [ +  - ]:        749 :   delete_map(map_by_addr);
    6898         [ +  - ]:        749 : }
    6899                 :            : 
    6900                 :            : void
    6901                 :   10062711 : symbol_table::add_symbol(const char *name, bool weak, bool descriptor,
    6902                 :            :                          Dwarf_Addr addr, Dwarf_Addr */*high_addr*/)
    6903                 :            : {
    6904                 :            : #ifdef __powerpc__
    6905                 :            :   // Map ".sys_foo" to "sys_foo".
    6906                 :            :   if (name[0] == '.')
    6907                 :            :     name++;
    6908                 :            : #endif
    6909         [ +  - ]:   10062711 :   func_info *fi = new func_info();
    6910                 :   10062711 :   fi->addr = addr;
    6911                 :   10062711 :   fi->name = name;
    6912                 :   10062711 :   fi->weak = weak;
    6913                 :   10062711 :   fi->descriptor = descriptor;
    6914                 :   10062711 :   map_by_name[fi->name] = fi;
    6915                 :            :   // TODO: Use a multimap in case there are multiple static
    6916                 :            :   // functions with the same name?
    6917         [ +  - ]:   10062711 :   map_by_addr.insert(make_pair(addr, fi));
    6918                 :   10062711 : }
    6919                 :            : 
    6920                 :            : enum info_status
    6921                 :          0 : symbol_table::read_symbols(FILE *f, const string& path)
    6922                 :            : {
    6923                 :            :   // Based on do_kernel_symbols() in runtime/staprun/symbols.c
    6924                 :            :   int ret;
    6925                 :          0 :   char *name = 0;
    6926                 :          0 :   char *mod = 0;
    6927                 :            :   char type;
    6928                 :            :   unsigned long long addr;
    6929                 :          0 :   Dwarf_Addr high_addr = 0;
    6930                 :          0 :   int line = 0;
    6931                 :            : 
    6932                 :            : #if __GLIBC__ >2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 7)
    6933                 :            : #define MS_FMT "%ms"
    6934                 :            : #else
    6935                 :            : #define MS_FMT "%as"
    6936                 :            : #endif
    6937                 :            :   // %ms (newer than %as) mallocs space for the string and stores its address.
    6938 [ #  # ][ #  # ]:          0 :   while ((ret = fscanf(f, "%llx %c " MS_FMT " [" MS_FMT, &addr, &type, &name, &mod)) > 0)
    6939                 :            :     {
    6940                 :          0 :       auto_free free_name(name);
    6941                 :          0 :       auto_free free_mod(mod);
    6942                 :          0 :       line++;
    6943         [ #  # ]:          0 :       if (ret < 3)
    6944                 :            :         {
    6945 [ #  # ][ #  # ]:          0 :           cerr << _F("Symbol table error: Line %d of symbol list from %s is not in correct format: address type name [module]\n",
                 [ #  # ]
    6946         [ #  # ]:          0 :                      line, path.c_str());
    6947                 :            :           // Caller should delete symbol_table object.
    6948                 :          0 :           return info_absent;
    6949                 :            :         }
    6950         [ #  # ]:          0 :       else if (ret > 3)
    6951                 :            :         {
    6952                 :            :           // Modules are loaded above the kernel, so if we're getting
    6953                 :            :           // modules, we're done.
    6954                 :            :           break;
    6955                 :            :         }
    6956 [ #  # ][ #  # ]:          0 :       if (type == 'T' || type == 't' || type == 'W')
                 [ #  # ]
    6957         [ #  # ]:          0 :         add_symbol(name, (type == 'W'), false, (Dwarf_Addr) addr, &high_addr);
    6958      [ #  #  # ]:          0 :     }
              [ #  #  # ]
    6959                 :            : 
    6960 [ #  # ][ #  # ]:          0 :   if (map_by_addr.size() < 1)
    6961                 :            :     {
    6962 [ #  # ][ #  # ]:          0 :       cerr << _F("Symbol table error: %s contains no function symbols.\n",
         [ #  # ][ #  # ]
    6963         [ #  # ]:          0 :                  path.c_str()) << endl;
    6964                 :          0 :       return info_absent;
    6965                 :            :     }
    6966                 :          0 :   return info_present;
    6967                 :            : }
    6968                 :            : 
    6969                 :            : // NB: This currently unused.  We use get_from_elf() instead because
    6970                 :            : // that gives us raw addresses -- which we need for modules -- whereas
    6971                 :            : // nm provides the address relative to the beginning of the section.
    6972                 :            : enum info_status
    6973                 :          0 : symbol_table::read_from_elf_file(const string &path,
    6974                 :            :                                  systemtap_session &sess)
    6975                 :            : {
    6976         [ #  # ]:          0 :   vector<string> cmd;
    6977 [ #  # ][ #  # ]:          0 :   cmd.push_back("/usr/bin/nm");
                 [ #  # ]
    6978 [ #  # ][ #  # ]:          0 :   cmd.push_back("-n");
                 [ #  # ]
    6979 [ #  # ][ #  # ]:          0 :   cmd.push_back("--defined-only");
                 [ #  # ]
    6980 [ #  # ][ #  # ]:          0 :   cmd.push_back("path");
                 [ #  # ]
    6981                 :            : 
    6982                 :            :   FILE *f;
    6983                 :            :   int child_fd;
    6984         [ #  # ]:          0 :   pid_t child = stap_spawn_piped(sess.verbose, cmd, NULL, &child_fd);
    6985 [ #  # ][ #  # ]:          0 :   if (child <= 0 || !(f = fdopen(child_fd, "r")))
                 [ #  # ]
    6986                 :            :     {
    6987                 :            :       // nm failures are detected by stap_waitpid
    6988 [ #  # ][ #  # ]:          0 :       cerr << _F("Internal error reading symbol table from %s -- %s\n",
                 [ #  # ]
    6989         [ #  # ]:          0 :                  path.c_str(), strerror(errno));
    6990                 :          0 :       return info_absent;
    6991                 :            :     }
    6992         [ #  # ]:          0 :   enum info_status status = read_symbols(f, path);
    6993 [ #  # ][ #  # ]:          0 :   if (fclose(f) || stap_waitpid(sess.verbose, child))
         [ #  # ][ #  # ]
                 [ #  # ]
    6994                 :            :     {
    6995         [ #  # ]:          0 :       if (status == info_present)
    6996 [ #  # ][ #  # ]:          0 :         sess.print_warning("nm cannot read symbol table from " + path);
                 [ #  # ]
    6997                 :          0 :       return info_absent;
    6998                 :            :     }
    6999         [ #  # ]:          0 :   return status;
    7000                 :            : }
    7001                 :            : 
    7002                 :            : enum info_status
    7003                 :          0 : symbol_table::read_from_text_file(const string& path,
    7004                 :            :                                   systemtap_session &sess)
    7005                 :            : {
    7006                 :          0 :   FILE *f = fopen(path.c_str(), "r");
    7007         [ #  # ]:          0 :   if (!f)
    7008                 :            :     {
    7009 [ #  # ][ #  # ]:          0 :       sess.print_warning("cannot read symbol table from " + path + " -- " + strerror(errno));
         [ #  # ][ #  # ]
                 [ #  # ]
    7010                 :          0 :       return info_absent;
    7011                 :            :     }
    7012                 :          0 :   enum info_status status = read_symbols(f, path);
    7013                 :          0 :   (void) fclose(f);
    7014                 :          0 :   return status;
    7015                 :            : }
    7016                 :            : 
    7017                 :            : void
    7018                 :        749 : symbol_table::prepare_section_rejection(Dwfl_Module *mod __attribute__ ((unused)))
    7019                 :            : {
    7020                 :            : #ifdef __powerpc__
    7021                 :            :   /*
    7022                 :            :    * The .opd section contains function descriptors that can look
    7023                 :            :    * just like function entry points.  For example, there's a function
    7024                 :            :    * descriptor called "do_exit" that links to the entry point ".do_exit".
    7025                 :            :    * Reject all symbols in .opd.
    7026                 :            :    */
    7027                 :            :   opd_section = SHN_UNDEF;
    7028                 :            :   Dwarf_Addr bias;
    7029                 :            :   Elf* elf = (dwarf_getelf (dwfl_module_getdwarf (mod, &bias))
    7030                 :            :                                     ?: dwfl_module_getelf (mod, &bias));
    7031                 :            :   Elf_Scn* scn = 0;
    7032                 :            :   size_t shstrndx;
    7033                 :            : 
    7034                 :            :   if (!elf)
    7035                 :            :     return;
    7036                 :            :   if (elf_getshdrstrndx (elf, &shstrndx) != 0)
    7037                 :            :     return;
    7038                 :            :   while ((scn = elf_nextscn(elf, scn)) != NULL)
    7039                 :            :     {
    7040                 :            :       GElf_Shdr shdr_mem;
    7041                 :            :       GElf_Shdr *shdr = gelf_getshdr(scn, &shdr_mem);
    7042                 :            :       if (!shdr)
    7043                 :            :         continue;
    7044                 :            :       const char *name = elf_strptr(elf, shstrndx, shdr->sh_name);
    7045                 :            :       if (!strcmp(name, ".opd"))
    7046                 :            :         {
    7047                 :            :           opd_section = elf_ndxscn(scn);
    7048                 :            :           return;
    7049                 :            :         }
    7050                 :            :     }
    7051                 :            : #endif
    7052                 :        749 : }
    7053                 :            : 
    7054                 :            : bool
    7055                 :   10062711 : symbol_table::reject_section(GElf_Word section)
    7056                 :            : {
    7057         [ +  + ]:   10062711 :   if (section == SHN_UNDEF)
    7058                 :       3302 :     return true;
    7059                 :            : #ifdef __powerpc__
    7060                 :            :   if (section == opd_section)
    7061                 :            :     return true;
    7062                 :            : #endif
    7063                 :   10062711 :   return false;
    7064                 :            : }
    7065                 :            : 
    7066                 :            : enum info_status
    7067                 :        749 : symbol_table::get_from_elf()
    7068                 :            : {
    7069                 :        749 :   Dwarf_Addr high_addr = 0;
    7070                 :        749 :   Dwfl_Module *mod = mod_info->mod;
    7071         [ +  - ]:        749 :   int syments = dwfl_module_getsymtab(mod);
    7072         [ -  + ]:        749 :   assert(syments);
    7073                 :        749 :   prepare_section_rejection(mod);
    7074         [ +  + ]:   42915607 :   for (int i = 1; i < syments; ++i)
    7075                 :            :     {
    7076                 :            :       GElf_Sym sym;
    7077                 :            :       GElf_Word section;
    7078         [ +  - ]:   42914858 :       const char *name = dwfl_module_getsym(mod, i, &sym, &section);
    7079 [ +  - ][ +  + ]:   42914858 :       if (name && GELF_ST_TYPE(sym.st_info) == STT_FUNC)
    7080                 :            :         add_symbol(name, (GELF_ST_BIND(sym.st_info) == STB_WEAK),
    7081         [ +  - ]:   10062711 :                    reject_section(section), sym.st_value, &high_addr);
    7082                 :            :     }
    7083                 :        749 :   return info_present;
    7084                 :            : }
    7085                 :            : 
    7086                 :            : func_info *
    7087                 :          0 : symbol_table::get_func_containing_address(Dwarf_Addr addr)
    7088                 :            : {
    7089         [ #  # ]:          0 :   iterator_t iter = map_by_addr.upper_bound(addr);
    7090 [ #  # ][ #  # ]:          0 :   if (iter == map_by_addr.begin())
    7091                 :          0 :     return NULL;
    7092                 :            :   else
    7093         [ #  # ]:          0 :     return (--iter)->second;
    7094                 :            : }
    7095                 :            : 
    7096                 :            : func_info *
    7097                 :          0 : symbol_table::get_first_func()
    7098                 :            : {
    7099         [ #  # ]:          0 :   iterator_t iter = map_by_addr.begin();
    7100         [ #  # ]:          0 :   return (iter)->second;
    7101                 :            : }
    7102                 :            : 
    7103                 :            : func_info *
    7104                 :   20903500 : symbol_table::lookup_symbol(const string& name)
    7105                 :            : {
    7106         [ +  - ]:   20903500 :   map<string, func_info*>::iterator i = map_by_name.find(name);
    7107 [ +  - ][ +  + ]:   20903500 :   if (i == map_by_name.end())
    7108                 :     238454 :     return NULL;
    7109         [ +  - ]:   20903500 :   return i->second;
    7110                 :            : }
    7111                 :            : 
    7112                 :            : Dwarf_Addr
    7113                 :        400 : symbol_table::lookup_symbol_address(const string& name)
    7114                 :            : {
    7115                 :        400 :   func_info *fi = lookup_symbol(name);
    7116         [ +  - ]:        400 :   if (fi)
    7117                 :        400 :     return fi->addr;
    7118                 :        400 :   return 0;
    7119                 :            : }
    7120                 :            : 
    7121                 :            : // This is the kernel symbol table.  The kernel macro cond_syscall creates
    7122                 :            : // a weak symbol for each system call and maps it to sys_ni_syscall.
    7123                 :            : // For system calls not implemented elsewhere, this weak symbol shows up
    7124                 :            : // in the kernel symbol table.  Following the precedent of dwarfful stap,
    7125                 :            : // we refuse to consider such symbols.  Here we delete them from our
    7126                 :            : // symbol table.
    7127                 :            : // TODO: Consider generalizing this and/or making it part of blacklist
    7128                 :            : // processing.
    7129                 :            : void
    7130                 :        400 : symbol_table::purge_syscall_stubs()
    7131                 :            : {
    7132 [ +  - ][ +  - ]:        400 :   Dwarf_Addr stub_addr = lookup_symbol_address("sys_ni_syscall");
                 [ +  - ]
    7133         [ +  - ]:        400 :   if (stub_addr == 0)
    7134                 :        400 :     return;
    7135         [ +  - ]:        400 :   range_t purge_range = map_by_addr.equal_range(stub_addr);
    7136         [ +  + ]:      28800 :   for (iterator_t iter = purge_range.first;
    7137                 :            :        iter != purge_range.second;
    7138                 :            :        )
    7139                 :            :     {
    7140         [ +  - ]:      28400 :       func_info *fi = iter->second;
    7141 [ +  + ][ +  - ]:      28400 :       if (fi->weak && fi->name != "sys_ni_syscall")
         [ +  - ][ +  + ]
    7142                 :            :         {
    7143         [ +  - ]:      28000 :           map_by_name.erase(fi->name);
    7144         [ +  - ]:      28000 :           map_by_addr.erase(iter++);
    7145 [ +  - ][ +  - ]:      28000 :           delete fi;
    7146                 :            :         }
    7147                 :            :       else
    7148                 :        400 :         iter++;
    7149                 :            :     }
    7150                 :            : }
    7151                 :            : 
    7152                 :            : void
    7153                 :      46701 : module_info::get_symtab(dwarf_query *q)
    7154                 :            : {
    7155         [ +  + ]:      46701 :   if (symtab_status != info_unknown)
    7156                 :      45952 :     return;
    7157                 :            : 
    7158         [ +  - ]:        749 :   sym_table = new symbol_table(this);
    7159         [ +  - ]:        749 :   if (!elf_path.empty())
    7160                 :            :     {
    7161                 :        749 :       symtab_status = sym_table->get_from_elf();
    7162                 :            :     }
    7163                 :            :   else
    7164                 :            :     {
    7165         [ #  # ]:          0 :       assert(name == TOK_KERNEL);
    7166                 :          0 :       symtab_status = info_absent;
    7167                 :          0 :       cerr << _("Error: Cannot find vmlinux.") << endl;;
    7168                 :            :     }
    7169         [ -  + ]:        749 :   if (symtab_status == info_absent)
    7170                 :            :     {
    7171         [ #  # ]:          0 :       delete sym_table;
    7172                 :          0 :       sym_table = NULL;
    7173                 :          0 :       return;
    7174                 :            :     }
    7175                 :            : 
    7176         [ +  + ]:        749 :   if (name == TOK_KERNEL)
    7177                 :      46701 :     sym_table->purge_syscall_stubs();
    7178                 :            : }
    7179                 :            : 
    7180                 :            : // update_symtab reconciles data between the elf symbol table and the dwarf
    7181                 :            : // function enumeration.  It updates the symbol table entries with the dwarf
    7182                 :            : // die that describes the function, which also signals to query_module_symtab
    7183                 :            : // that a statement probe isn't needed.  In return, it also adds aliases to the
    7184                 :            : // function table for names that share the same addr/die.
    7185                 :            : void
    7186                 :      44573 : module_info::update_symtab(cu_function_cache_t *funcs)
    7187                 :            : {
    7188         [ +  + ]:      44573 :   if (!sym_table)
    7189                 :      44573 :     return;
    7190                 :            : 
    7191         [ +  - ]:      41297 :   cu_function_cache_t new_funcs;
    7192                 :            : 
    7193 [ +  - ][ +  - ]:   72398544 :   for (cu_function_cache_t::iterator func = funcs->begin();
                 [ +  + ]
    7194         [ +  - ]:   36199272 :        func != funcs->end(); func++)
    7195                 :            :     {
    7196                 :            :       // optimization: inlines will never be in the symbol table
    7197 [ +  - ][ +  - ]:   36157975 :       if (dwarf_func_inline(&func->second) != 0)
                 [ +  + ]
    7198                 :   15254875 :         continue;
    7199                 :            : 
    7200                 :            :       // XXX We may want to make additional efforts to match mangled elf names
    7201                 :            :       // to dwarf too.  MIPS_linkage_name can help, but that's sometimes
    7202                 :            :       // missing, so we may also need to try matching by address.  See also the
    7203                 :            :       // notes about _Z in dwflpp::iterate_over_functions().
    7204                 :            : 
    7205 [ +  - ][ +  - ]:   20903100 :       func_info *fi = sym_table->lookup_symbol(func->first);
    7206         [ +  + ]:   20903100 :       if (!fi)
    7207                 :     238454 :         continue;
    7208                 :            : 
    7209                 :            :       // iterate over all functions at the same address
    7210         [ +  - ]:   20664646 :       symbol_table::range_t er = sym_table->map_by_addr.equal_range(fi->addr);
    7211         [ +  + ]:   56882623 :       for (symbol_table::iterator_t it = er.first; it != er.second; ++it)
    7212                 :            :         {
    7213                 :            :           // update this function with the dwarf die
    7214 [ +  - ][ +  - ]:   20724648 :           it->second->die = func->second;
    7215                 :            : 
    7216                 :            :           // if this function is a new alias, then
    7217                 :            :           // save it to merge into the function cache
    7218 [ +  - ][ +  + ]:   20724648 :           if (it->second != fi)
    7219 [ +  - ][ +  - ]:      60002 :             new_funcs.insert(make_pair(it->second->name, it->second->die));
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    7220                 :            :         }
    7221                 :            :     }
    7222                 :            : 
    7223                 :            :   // add all discovered aliases back into the function cache
    7224                 :            :   // NB: this won't replace any names that dwarf may have already found
    7225 [ +  - ][ +  - ]:      44573 :   funcs->insert(new_funcs.begin(), new_funcs.end());
         [ +  - ][ +  - ]
    7226                 :            : }
    7227                 :            : 
    7228                 :       9292 : module_info::~module_info()
    7229                 :            : {
    7230         [ +  + ]:       4646 :   if (sym_table)
    7231 [ +  - ][ +  - ]:        749 :     delete sym_table;
    7232                 :       4646 : }
    7233                 :            : 
    7234                 :            : // ------------------------------------------------------------------------
    7235                 :            : // user-space probes
    7236                 :            : // ------------------------------------------------------------------------
    7237                 :            : 
    7238                 :            : 
    7239         [ #  # ]:         27 : struct uprobe_derived_probe_group: public generic_dpg<uprobe_derived_probe>
    7240                 :            : {
    7241                 :            : private:
    7242                 :         12 :   string make_pbm_key (uprobe_derived_probe* p) {
    7243 [ +  - ][ +  - ]:         12 :     return p->path + "|" + p->module + "|" + p->section + "|" + lex_cast(p->pid);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    7244                 :            :   }
    7245                 :            : 
    7246                 :            :   void emit_module_maxuprobes (systemtap_session& s);
    7247                 :            : 
    7248                 :            :   // Using our own utrace-based uprobes
    7249                 :            :   void emit_module_utrace_decls (systemtap_session& s);
    7250                 :            :   void emit_module_utrace_init (systemtap_session& s);
    7251                 :            :   void emit_module_utrace_exit (systemtap_session& s);
    7252                 :            : 
    7253                 :            :   // Using the upstream inode-based uprobes
    7254                 :            :   void emit_module_inode_decls (systemtap_session& s);
    7255                 :            :   void emit_module_inode_init (systemtap_session& s);
    7256                 :            :   void emit_module_inode_exit (systemtap_session& s);
    7257                 :            : 
    7258                 :            :   // Using the dyninst backend (via stapdyn)
    7259                 :            :   void emit_module_dyninst_decls (systemtap_session& s);
    7260                 :            :   void emit_module_dyninst_init (systemtap_session& s);
    7261                 :            :   void emit_module_dyninst_exit (systemtap_session& s);
    7262                 :            : 
    7263                 :            : public:
    7264                 :            :   void emit_module_decls (systemtap_session& s);
    7265                 :            :   void emit_module_init (systemtap_session& s);
    7266                 :            :   void emit_module_exit (systemtap_session& s);
    7267                 :            : };
    7268                 :            : 
    7269                 :            : 
    7270                 :            : void
    7271                 :      11861 : uprobe_derived_probe::join_group (systemtap_session& s)
    7272                 :            : {
    7273         [ +  + ]:      11861 :   if (! s.uprobe_derived_probes)
    7274         [ +  - ]:         27 :     s.uprobe_derived_probes = new uprobe_derived_probe_group ();
    7275                 :      11861 :   s.uprobe_derived_probes->enroll (this);
    7276         [ -  + ]:      11861 :   if (s.runtime_usermode_p())
    7277                 :          0 :     enable_dynprobes(s);
    7278                 :            :   else
    7279                 :      11861 :     enable_task_finder(s);
    7280                 :            : 
    7281                 :            :   // Ask buildrun.cxx to build extra module if needed, and
    7282                 :            :   // signal staprun to load that module.  If we're using the builtin
    7283                 :            :   // inode-uprobes, we still need to know that it is required.
    7284                 :      11861 :   s.need_uprobes = true;
    7285                 :      11861 : }
    7286                 :            : 
    7287                 :            : 
    7288                 :            : void
    7289                 :      11819 : uprobe_derived_probe::getargs(std::list<std::string> &arg_set) const
    7290                 :            : {
    7291                 :      11819 :   dwarf_derived_probe::getargs(arg_set);
    7292                 :      11819 :   arg_set.insert(arg_set.end(), args.begin(), args.end());
    7293                 :      11819 : }
    7294                 :            : 
    7295                 :            : 
    7296                 :            : void
    7297                 :         48 : uprobe_derived_probe::saveargs(int nargs)
    7298                 :            : {
    7299         [ +  + ]:        106 :   for (int i = 1; i <= nargs; i++)
    7300 [ +  - ][ +  - ]:         58 :     args.push_back("$arg" + lex_cast (i) + ":long");
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    7301                 :         48 : }
    7302                 :            : 
    7303                 :            : 
    7304                 :            : void
    7305                 :          6 : uprobe_derived_probe::emit_privilege_assertion (translator_output* o)
    7306                 :            : {
    7307                 :            :   // These probes are allowed for unprivileged users, but only in the
    7308                 :            :   // context of processes which they own.
    7309                 :          6 :   emit_process_owner_assertion (o);
    7310                 :          6 : }
    7311                 :            : 
    7312                 :            : 
    7313         [ #  # ]:          0 : struct uprobe_builder: public derived_probe_builder
    7314                 :            : {
    7315                 :       2436 :   uprobe_builder() {}
    7316                 :          1 :   virtual void build(systemtap_session & sess,
    7317                 :            :                      probe * base,
    7318                 :            :                      probe_point * location,
    7319                 :            :                      literal_map_t const & parameters,
    7320                 :            :                      vector<derived_probe *> & finished_results)
    7321                 :            :   {
    7322                 :            :     int64_t process, address;
    7323                 :            : 
    7324 [ +  - ][ -  + ]:          1 :     if (kernel_supports_inode_uprobes(sess))
    7325 [ #  # ][ #  # ]:          0 :       throw semantic_error (_("absolute process probes not available [man error::inode-uprobes]"));
    7326                 :            : 
    7327         [ +  - ]:          1 :     bool b1 = get_param (parameters, TOK_PROCESS, process);
    7328                 :            :     (void) b1;
    7329         [ +  - ]:          1 :     bool b2 = get_param (parameters, TOK_STATEMENT, address);
    7330                 :            :     (void) b2;
    7331         [ +  - ]:          1 :     bool rr = has_null_param (parameters, TOK_RETURN);
    7332 [ +  - ][ -  + ]:          1 :     assert (b1 && b2); // by pattern_root construction
    7333                 :            : 
    7334 [ +  - ][ +  - ]:          1 :     finished_results.push_back(new uprobe_derived_probe(base, location, process, address, rr));
                 [ +  - ]
    7335                 :          1 :   }
    7336                 :            : };
    7337                 :            : 
    7338                 :            : 
    7339                 :            : void
    7340                 :          6 : uprobe_derived_probe_group::emit_module_maxuprobes (systemtap_session& s)
    7341                 :            : {
    7342                 :            :   // We'll probably need at least this many:
    7343                 :          6 :   unsigned minuprobes = probes.size();
    7344                 :            :   // .. but we don't want so many that .bss is inflated (PR10507):
    7345                 :          6 :   unsigned uprobesize = 64;
    7346                 :          6 :   unsigned maxuprobesmem = 10*1024*1024; // 10 MB
    7347                 :          6 :   unsigned maxuprobes = maxuprobesmem / uprobesize;
    7348                 :            : 
    7349                 :            :   // Let's choose a value on the geometric middle.  This should end up
    7350                 :            :   // between minuprobes and maxuprobes.  It's OK if this number turns
    7351                 :            :   // out to be < minuprobes or > maxuprobes.  At worst, we get a
    7352                 :            :   // run-time error of one kind (too few: missed uprobe registrations)
    7353                 :            :   // or another (too many: vmalloc errors at module load time).
    7354                 :          6 :   unsigned default_maxuprobes = (unsigned)sqrt((double)minuprobes * (double)maxuprobes);
    7355                 :            : 
    7356                 :          6 :   s.op->newline() << "#ifndef MAXUPROBES";
    7357                 :          6 :   s.op->newline() << "#define MAXUPROBES " << default_maxuprobes;
    7358                 :          6 :   s.op->newline() << "#endif";
    7359                 :          6 : }
    7360                 :            : 
    7361                 :            : 
    7362                 :            : void
    7363                 :          6 : uprobe_derived_probe_group::emit_module_utrace_decls (systemtap_session& s)
    7364                 :            : {
    7365 [ +  - ][ +  - ]:         12 :   if (probes.empty()) return;
    7366 [ +  - ][ +  - ]:          6 :   s.op->newline() << "/* ---- utrace uprobes ---- */";
    7367                 :            :   // If uprobes isn't in the kernel, pull it in from the runtime.
    7368                 :            : 
    7369 [ +  - ][ +  - ]:          6 :   s.op->newline() << "#if defined(CONFIG_UPROBES) || defined(CONFIG_UPROBES_MODULE)";
    7370 [ +  - ][ +  - ]:          6 :   s.op->newline() << "#include <linux/uprobes.h>";
    7371 [ +  - ][ +  - ]:          6 :   s.op->newline() << "#else";
    7372 [ +  - ][ +  - ]:          6 :   s.op->newline() << "#include \"linux/uprobes/uprobes.h\"";
    7373 [ +  - ][ +  - ]:          6 :   s.op->newline() << "#endif";
    7374 [ +  - ][ +  - ]:          6 :   s.op->newline() << "#ifndef UPROBES_API_VERSION";
    7375 [ +  - ][ +  - ]:          6 :   s.op->newline() << "#define UPROBES_API_VERSION 1";
    7376 [ +  - ][ +  - ]:          6 :   s.op->newline() << "#endif";
    7377                 :            : 
    7378         [ +  - ]:          6 :   emit_module_maxuprobes (s);
    7379                 :            : 
    7380                 :            :   // Forward decls
    7381 [ +  - ][ +  - ]:          6 :   s.op->newline() << "#include \"linux/uprobes-common.h\"";
    7382                 :            : 
    7383                 :            :   // In .bss, the shared pool of uprobe/uretprobe structs.  These are
    7384                 :            :   // too big to embed in the initialized .data stap_uprobe_spec array.
    7385                 :            :   // XXX: consider a slab cache or somesuch for stap_uprobes
    7386 [ +  - ][ +  - ]:          6 :   s.op->newline() << "static struct stap_uprobe stap_uprobes [MAXUPROBES];";
    7387 [ +  - ][ +  - ]:          6 :   s.op->newline() << "static DEFINE_MUTEX(stap_uprobes_lock);"; // protects against concurrent registration/unregistration
    7388                 :            : 
    7389         [ +  - ]:          6 :   s.op->assert_0_indent();
    7390                 :            : 
    7391                 :            :   // Assign task-finder numbers as we build up the stap_uprobe_tf table.
    7392                 :            :   // This means we process probes[] in two passes.
    7393         [ +  - ]:          6 :   map <string,unsigned> module_index;
    7394                 :          6 :   unsigned module_index_ctr = 0;
    7395                 :            : 
    7396                 :            :   // not const since embedded task_finder_target struct changes
    7397 [ +  - ][ +  - ]:          6 :   s.op->newline() << "static struct stap_uprobe_tf stap_uprobe_finders[] = {";
    7398         [ +  - ]:          6 :   s.op->indent(1);
    7399         [ +  + ]:         12 :   for (unsigned i=0; i<probes.size(); i++)
    7400                 :            :     {
    7401                 :          6 :       uprobe_derived_probe *p = probes[i];
    7402         [ +  - ]:          6 :       string pbmkey = make_pbm_key (p);
    7403 [ +  - ][ +  - ]:          6 :       if (module_index.find (pbmkey) == module_index.end())
                 [ +  - ]
    7404                 :            :         {
    7405         [ +  - ]:          6 :           module_index[pbmkey] = module_index_ctr++;
    7406                 :            : 
    7407 [ +  - ][ +  - ]:          6 :           s.op->newline() << "{";
    7408                 :            :           // NB: it's essential that make_pbm_key() use all of and
    7409                 :            :           // only the same fields as we're about to emit.
    7410 [ +  - ][ +  - ]:          6 :           s.op->line() << " .finder={";
    7411 [ +  - ][ +  - ]:          6 :           s.op->line() << "  .purpose=\"uprobes\",";
    7412         [ -  + ]:          6 :           if (p->pid != 0)
    7413 [ #  # ][ #  # ]:          0 :             s.op->line() << " .pid=" << p->pid << ",";
         [ #  # ][ #  # ]
    7414                 :            : 
    7415 [ +  - ][ +  + ]:          6 :           if (p->section == "") // .statement(addr).absolute
    7416 [ +  - ][ +  - ]:          1 :             s.op->line() << " .callback=&stap_uprobe_process_found,";
    7417 [ +  - ][ +  - ]:          5 :           else if (p->section == ".absolute") // proxy for ET_EXEC -> exec()'d program
    7418                 :            :             {
    7419 [ +  - ][ +  - ]:          5 :               s.op->line() << " .procname=" << lex_cast_qstring(p->module) << ",";
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
    7420 [ +  - ][ +  - ]:          5 :               s.op->line() << " .callback=&stap_uprobe_process_found,";
    7421                 :            :             }
    7422 [ #  # ][ #  # ]:          0 :           else if (p->section != ".absolute") // ET_DYN
    7423                 :            :             {
    7424         [ #  # ]:          0 :               if (p->has_library)
    7425 [ #  # ][ #  # ]:          0 :                 s.op->line() << " .procname=\"" << p->path << "\", ";
         [ #  # ][ #  # ]
    7426 [ #  # ][ #  # ]:          0 :               s.op->line() << " .mmap_callback=&stap_uprobe_mmap_found, ";
    7427 [ #  # ][ #  # ]:          0 :               s.op->line() << " .munmap_callback=&stap_uprobe_munmap_found, ";
    7428 [ #  # ][ #  # ]:          0 :               s.op->line() << " .callback=&stap_uprobe_process_munmap,";
    7429                 :            :             }
    7430 [ +  - ][ +  - ]:          6 :           s.op->line() << " },";
    7431 [ +  - ][ +  + ]:          6 :           if (p->module != "")
    7432 [ +  - ][ +  - ]:          5 :             s.op->line() << " .pathname=" << lex_cast_qstring(p->module) << ", ";
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
    7433 [ +  - ][ +  - ]:          6 :           s.op->line() << " },";
    7434                 :            :         }
    7435                 :            :       else
    7436                 :            :         { } // skip it in this pass, already have a suitable stap_uprobe_tf slot for it.
    7437         [ +  - ]:          6 :     }
    7438 [ +  - ][ +  - ]:          6 :   s.op->newline(-1) << "};";
    7439                 :            : 
    7440         [ +  - ]:          6 :   s.op->assert_0_indent();
    7441                 :            : 
    7442                 :            :   unsigned pci;
    7443         [ +  + ]:         12 :   for (pci=0; pci<probes.size(); pci++)
    7444                 :            :     {
    7445                 :            :       // List of perf counters used by each probe
    7446                 :            :       // This list is an index into struct stap_perf_probe,
    7447                 :          6 :       uprobe_derived_probe *p = probes[pci];
    7448                 :          6 :       std::set<derived_probe*>::iterator pcii;
    7449 [ +  - ][ +  - ]:          6 :       s.op->newline() << "long perf_counters_" + lex_cast(pci) + "[] = {";
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
    7450 [ +  - ][ +  + ]:         14 :       for (pcii = p->perf_counter_refs.begin();
    7451         [ +  - ]:          7 :            pcii != p->perf_counter_refs.end(); pcii++)
    7452                 :            :         {
    7453                 :          1 :           map<string, pair<string,derived_probe*> >::iterator it;
    7454                 :          1 :           unsigned i = 0;
    7455                 :            :           // Find the associated perf.counter probe
    7456 [ +  - ][ +  - ]:          2 :           for (it=s.perf_counters.begin() ;
    7457         [ +  - ]:          1 :                it != s.perf_counters.end(); it++, i++)
    7458         [ +  - ]:          1 :             if ((*it).second.second == (*pcii))
    7459                 :          1 :               break;
    7460 [ +  - ][ +  - ]:          1 :           s.op->line() << lex_cast(i) << ", ";
         [ +  - ][ +  - ]
                 [ +  - ]
    7461                 :            :         }
    7462 [ +  - ][ +  - ]:          6 :       s.op->newline() << "};";
    7463                 :            :     }
    7464                 :            : 
    7465                 :            :    // NB: read-only structure
    7466 [ +  - ][ +  - ]:          6 :   s.op->newline() << "static const struct stap_uprobe_spec stap_uprobe_specs [] = {";
    7467         [ +  - ]:          6 :   s.op->indent(1);
    7468         [ +  + ]:         12 :   for (unsigned i =0; i<probes.size(); i++)
    7469                 :            :     {
    7470                 :          6 :       uprobe_derived_probe* p = probes[i];
    7471 [ +  - ][ +  - ]:          6 :       s.op->newline() << "{";
    7472         [ +  - ]:          6 :       string key = make_pbm_key (p);
    7473         [ +  - ]:          6 :       unsigned value = module_index[key];
    7474         [ -  + ]:          6 :       if (value != 0)
    7475 [ #  # ][ #  # ]:          0 :         s.op->line() << " .tfi=" << value << ",";
         [ #  # ][ #  # ]
    7476 [ +  - ][ +  - ]:          6 :       s.op->line() << " .address=(unsigned long)0x" << hex << p->addr << dec << "ULL,";
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
    7477 [ +  - ][ +  - ]:          6 :       s.op->line() << " .probe=" << common_probe_init (p) << ",";
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
    7478                 :            : 
    7479         [ -  + ]:          6 :       if (p->sdt_semaphore_addr != 0)
    7480 [ #  # ][ #  # ]:          0 :         s.op->line() << " .sdt_sem_offset=(unsigned long)0x"
    7481 [ #  # ][ #  # ]:          0 :                      << hex << p->sdt_semaphore_addr << dec << "ULL,";
         [ #  # ][ #  # ]
    7482                 :            : 
    7483                 :            :       // XXX: don't bother emit if array is empty
    7484 [ +  - ][ +  - ]:          6 :       s.op->line() << " .perf_counters_dim=ARRAY_SIZE(perf_counters_" << lex_cast(i) << "),";
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
    7485                 :            :       // List of perf counters used by a probe from above
    7486 [ +  - ][ +  - ]:          6 :       s.op->line() << " .perf_counters=perf_counters_" + lex_cast(i) + ",";
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
    7487                 :            : 
    7488         [ -  + ]:          6 :       if (p->has_return)
    7489 [ #  # ][ #  # ]:          0 :         s.op->line() << " .return_p=1,";
    7490 [ +  - ][ +  - ]:          6 :       s.op->line() << " },";
    7491         [ +  - ]:          6 :     }
    7492 [ +  - ][ +  - ]:          6 :   s.op->newline(-1) << "};";
    7493                 :            : 
    7494         [ +  - ]:          6 :   s.op->assert_0_indent();
    7495                 :            : 
    7496 [ +  - ][ +  - ]:          6 :   s.op->newline() << "static void enter_uprobe_probe (struct uprobe *inst, struct pt_regs *regs) {";
    7497 [ +  - ][ +  - ]:          6 :   s.op->newline(1) << "struct stap_uprobe *sup = container_of(inst, struct stap_uprobe, up);";
    7498 [ +  - ][ +  - ]:          6 :   s.op->newline() << "const struct stap_uprobe_spec *sups = &stap_uprobe_specs [sup->spec_index];";
    7499                 :            :   common_probe_entryfn_prologue (s, "STAP_SESSION_RUNNING", "sups->probe",
    7500 [ +  - ][ +  - ]:          6 :                                  "stp_probe_type_uprobe");
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    7501 [ +  - ][ +  - ]:          6 :   s.op->newline() << "if (sup->spec_index < 0 || "
    7502 [ +  - ][ +  - ]:          6 :                   << "sup->spec_index >= " << probes.size() << ") {";
                 [ +  - ]
    7503 [ +  - ][ +  - ]:          6 :   s.op->newline(1) << "_stp_error (\"bad spec_index %d (max " << probes.size()
                 [ +  - ]
    7504         [ +  - ]:          6 :                    << "): %s\", sup->spec_index, c->probe_point);";
    7505 [ +  - ][ +  - ]:          6 :   s.op->newline() << "atomic_dec (&c->busy);";
    7506 [ +  - ][ +  - ]:          6 :   s.op->newline() << "goto probe_epilogue;";
    7507 [ +  - ][ +  - ]:          6 :   s.op->newline(-1) << "}";
    7508 [ +  - ][ +  - ]:          6 :   s.op->newline() << "c->uregs = regs;";
    7509 [ +  - ][ +  - ]:          6 :   s.op->newline() << "c->user_mode_p = 1;";
    7510                 :            : 
    7511                 :            :   // Make it look like the IP is set as it would in the actual user
    7512                 :            :   // task when calling real probe handler. Reset IP regs on return, so
    7513                 :            :   // we don't confuse uprobes. PR10458
    7514 [ +  - ][ +  - ]:          6 :   s.op->newline() << "{";
    7515         [ +  - ]:          6 :   s.op->indent(1);
    7516 [ +  - ][ +  - ]:          6 :   s.op->newline() << "unsigned long uprobes_ip = REG_IP(c->uregs);";
    7517 [ +  - ][ +  - ]:          6 :   s.op->newline() << "SET_REG_IP(regs, inst->vaddr);";
    7518 [ +  - ][ +  - ]:          6 :   s.op->newline() << "(*sups->probe->ph) (c);";
    7519 [ +  - ][ +  - ]:          6 :   s.op->newline() << "SET_REG_IP(regs, uprobes_ip);";
    7520 [ +  - ][ +  - ]:          6 :   s.op->newline(-1) << "}";
    7521                 :            : 
    7522         [ +  - ]:          6 :   common_probe_entryfn_epilogue (s, true);
    7523 [ +  - ][ +  - ]:          6 :   s.op->newline(-1) << "}";
    7524                 :            : 
    7525 [ +  - ][ +  - ]:          6 :   s.op->newline() << "static void enter_uretprobe_probe (struct uretprobe_instance *inst, struct pt_regs *regs) {";
    7526 [ +  - ][ +  - ]:          6 :   s.op->newline(1) << "struct stap_uprobe *sup = container_of(inst->rp, struct stap_uprobe, urp);";
    7527 [ +  - ][ +  - ]:          6 :   s.op->newline() << "const struct stap_uprobe_spec *sups = &stap_uprobe_specs [sup->spec_index];";
    7528                 :            :   common_probe_entryfn_prologue (s, "STAP_SESSION_RUNNING", "sups->probe",
    7529 [ +  - ][ +  - ]:          6 :                                  "stp_probe_type_uretprobe");
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    7530 [ +  - ][ +  - ]:          6 :   s.op->newline() << "c->ips.ri = inst;";
    7531 [ +  - ][ +  - ]:          6 :   s.op->newline() << "if (sup->spec_index < 0 || "
    7532 [ +  - ][ +  - ]:          6 :                   << "sup->spec_index >= " << probes.size() << ") {";
                 [ +  - ]
    7533 [ +  - ][ +  - ]:          6 :   s.op->newline(1) << "_stp_error (\"bad spec_index %d (max " << probes.size()
                 [ +  - ]
    7534         [ +  - ]:          6 :                    << "): %s\", sup->spec_index, c->probe_point);";
    7535 [ +  - ][ +  - ]:          6 :   s.op->newline() << "atomic_dec (&c->busy);";
    7536 [ +  - ][ +  - ]:          6 :   s.op->newline() << "goto probe_epilogue;";
    7537 [ +  - ][ +  - ]:          6 :   s.op->newline(-1) << "}";
    7538                 :            : 
    7539 [ +  - ][ +  - ]:          6 :   s.op->newline() << "c->uregs = regs;";
    7540 [ +  - ][ +  - ]:          6 :   s.op->newline() << "c->user_mode_p = 1;";
    7541                 :            : 
    7542                 :            :   // Make it look like the IP is set as it would in the actual user
    7543                 :            :   // task when calling real probe handler. Reset IP regs on return, so
    7544                 :            :   // we don't confuse uprobes. PR10458
    7545 [ +  - ][ +  - ]:          6 :   s.op->newline() << "{";
    7546         [ +  - ]:          6 :   s.op->indent(1);
    7547 [ +  - ][ +  - ]:          6 :   s.op->newline() << "unsigned long uprobes_ip = REG_IP(c->uregs);";
    7548 [ +  - ][ +  - ]:          6 :   s.op->newline() << "SET_REG_IP(regs, inst->ret_addr);";
    7549 [ +  - ][ +  - ]:          6 :   s.op->newline() << "(*sups->probe->ph) (c);";
    7550 [ +  - ][ +  - ]:          6 :   s.op->newline() << "SET_REG_IP(regs, uprobes_ip);";
    7551 [ +  - ][ +  - ]:          6 :   s.op->newline(-1) << "}";
    7552                 :            : 
    7553         [ +  - ]:          6 :   common_probe_entryfn_epilogue (s, true);
    7554 [ +  - ][ +  - ]:          6 :   s.op->newline(-1) << "}";
    7555                 :            : 
    7556         [ +  - ]:          6 :   s.op->newline();
    7557 [ +  - ][ +  - ]:          6 :   s.op->newline() << "#include \"linux/uprobes-common.c\"";
    7558 [ +  - ][ +  - ]:          6 :   s.op->newline();
    7559                 :            : }
    7560                 :            : 
    7561                 :            : 
    7562                 :            : void
    7563                 :          6 : uprobe_derived_probe_group::emit_module_utrace_init (systemtap_session& s)
    7564                 :            : {
    7565         [ -  + ]:         12 :   if (probes.empty()) return;
    7566                 :            : 
    7567                 :          6 :   s.op->newline() << "/* ---- utrace uprobes ---- */";
    7568                 :            : 
    7569                 :          6 :   s.op->newline() << "for (j=0; j<MAXUPROBES; j++) {";
    7570                 :          6 :   s.op->newline(1) << "struct stap_uprobe *sup = & stap_uprobes[j];";
    7571                 :          6 :   s.op->newline() << "sup->spec_index = -1;"; // free slot
    7572                 :            :   // NB: we assume the rest of the struct (specificaly, sup->up) is
    7573                 :            :   // initialized to zero.  This is so that we can use
    7574                 :            :   // sup->up->kdata = NULL for "really free!"  PR 6829.
    7575                 :          6 :   s.op->newline(-1) << "}";
    7576                 :          6 :   s.op->newline() << "mutex_init (& stap_uprobes_lock);";
    7577                 :            : 
    7578                 :            :   // Set up the task_finders
    7579                 :          6 :   s.op->newline() << "for (i=0; i<sizeof(stap_uprobe_finders)/sizeof(stap_uprobe_finders[0]); i++) {";
    7580                 :          6 :   s.op->newline(1) << "struct stap_uprobe_tf *stf = & stap_uprobe_finders[i];";
    7581                 :          6 :   s.op->newline() << "probe_point = stf->pathname;"; // for error messages; XXX: would prefer pp() or something better
    7582                 :          6 :   s.op->newline() << "rc = stap_register_task_finder_target (& stf->finder);";
    7583                 :            : 
    7584                 :            :   // NB: if (rc), there is no need (XXX: nor any way) to clean up any
    7585                 :            :   // finders already registered, since mere registration does not
    7586                 :            :   // cause any utrace or memory allocation actions.  That happens only
    7587                 :            :   // later, once the task finder engine starts running.  So, for a
    7588                 :            :   // partial initialization requiring unwind, we need do nothing.
    7589                 :          6 :   s.op->newline() << "if (rc) break;";
    7590                 :            : 
    7591                 :          6 :   s.op->newline(-1) << "}";
    7592                 :            : }
    7593                 :            : 
    7594                 :            : 
    7595                 :            : void
    7596                 :         13 : uprobe_derived_probe_group::emit_module_utrace_exit (systemtap_session& s)
    7597                 :            : {
    7598         [ -  + ]:         26 :   if (probes.empty()) return;
    7599                 :         13 :   s.op->newline() << "/* ---- utrace uprobes ---- */";
    7600                 :            : 
    7601                 :            :   // NB: there is no stap_unregister_task_finder_target call;
    7602                 :            :   // important stuff like utrace cleanups are done by
    7603                 :            :   // __stp_task_finder_cleanup() via stap_stop_task_finder().
    7604                 :            :   //
    7605                 :            :   // This function blocks until all callbacks are completed, so there
    7606                 :            :   // is supposed to be no possibility of any registration-related code starting
    7607                 :            :   // to run in parallel with our shutdown here.  So we don't need to protect the
    7608                 :            :   // stap_uprobes[] array with the mutex.
    7609                 :            : 
    7610                 :         13 :   s.op->newline() << "for (j=0; j<MAXUPROBES; j++) {";
    7611                 :         13 :   s.op->newline(1) << "struct stap_uprobe *sup = & stap_uprobes[j];";
    7612                 :         13 :   s.op->newline() << "const struct stap_uprobe_spec *sups = &stap_uprobe_specs [sup->spec_index];";
    7613                 :         13 :   s.op->newline() << "if (sup->spec_index < 0) continue;"; // free slot
    7614                 :            : 
    7615                 :            :   // PR10655: decrement that ENABLED semaphore
    7616                 :         13 :   s.op->newline() << "if (sup->sdt_sem_address) {";
    7617                 :         13 :   s.op->newline(1) << "unsigned short sdt_semaphore;"; // NB: fixed size
    7618                 :         13 :   s.op->newline() << "pid_t pid = (sups->return_p ? sup->urp.u.pid : sup->up.pid);";
    7619                 :         13 :   s.op->newline() << "struct task_struct *tsk;";
    7620                 :         13 :   s.op->newline() << "rcu_read_lock();";
    7621                 :            : 
    7622                 :            :   // Do a pid->task_struct* lookup.  For 2.6.24+, this code assumes
    7623                 :            :   // that the pid is always in the global namespace, not in any
    7624                 :            :   // private namespace.
    7625                 :         13 :   s.op->newline() << "#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24)";
    7626                 :            :   // We'd like to call find_task_by_pid_ns() here, but it isn't
    7627                 :            :   // exported.  So, we call what it calls...
    7628                 :         13 :   s.op->newline() << "  tsk = pid_task(find_pid_ns(pid, &init_pid_ns), PIDTYPE_PID);";
    7629                 :         13 :   s.op->newline() << "#else";
    7630                 :         13 :   s.op->newline() << "  tsk = find_task_by_pid (pid);";
    7631                 :         13 :   s.op->newline() << "#endif /* 2.6.24 */";
    7632                 :            : 
    7633                 :         13 :   s.op->newline() << "if (tsk) {"; // just in case the thing exited while we weren't watching
    7634                 :         13 :   s.op->newline(1) << "if (__access_process_vm_noflush(tsk, sup->sdt_sem_address, &sdt_semaphore, sizeof(sdt_semaphore), 0)) {";
    7635                 :         13 :   s.op->newline(1) << "sdt_semaphore --;";
    7636                 :         13 :   s.op->newline() << "#ifdef DEBUG_UPROBES";
    7637                 :         13 :   s.op->newline() << "_stp_dbug (__FUNCTION__,__LINE__, \"-semaphore %#x @ %#lx\\n\", sdt_semaphore, sup->sdt_sem_address);";
    7638                 :         13 :   s.op->newline() << "#endif";
    7639                 :         13 :   s.op->newline() << "__access_process_vm_noflush(tsk, sup->sdt_sem_address, &sdt_semaphore, sizeof(sdt_semaphore), 1);";
    7640                 :         13 :   s.op->newline(-1) << "}";
    7641                 :            :   // XXX: need to analyze possibility of race condition
    7642                 :         13 :   s.op->newline(-1) << "}";
    7643                 :         13 :   s.op->newline() << "rcu_read_unlock();";
    7644                 :         13 :   s.op->newline(-1) << "}";
    7645                 :            : 
    7646                 :         13 :   s.op->newline() << "if (sups->return_p) {";
    7647                 :         13 :   s.op->newline(1) << "#ifdef DEBUG_UPROBES";
    7648                 :         13 :   s.op->newline() << "_stp_dbug (__FUNCTION__,__LINE__, \"-uretprobe spec %d index %d pid %d addr %p\\n\", sup->spec_index, j, sup->up.pid, (void*) sup->up.vaddr);";
    7649                 :         13 :   s.op->newline() << "#endif";
    7650                 :            :   // NB: PR6829 does not change that we still need to unregister at
    7651                 :            :   // *this* time -- when the script as a whole exits.
    7652                 :         13 :   s.op->newline() << "unregister_uretprobe (& sup->urp);";
    7653                 :         13 :   s.op->newline(-1) << "} else {";
    7654                 :         13 :   s.op->newline(1) << "#ifdef DEBUG_UPROBES";
    7655                 :         13 :   s.op->newline() << "_stp_dbug (__FUNCTION__,__LINE__, \"-uprobe spec %d index %d pid %d addr %p\\n\", sup->spec_index, j, sup->up.pid, (void*) sup->up.vaddr);";
    7656                 :         13 :   s.op->newline() << "#endif";
    7657                 :         13 :   s.op->newline() << "unregister_uprobe (& sup->up);";
    7658                 :         13 :   s.op->newline(-1) << "}";
    7659                 :            : 
    7660                 :         13 :   s.op->newline() << "sup->spec_index = -1;";
    7661                 :            : 
    7662                 :            :   // XXX: uprobe missed counts?
    7663                 :            : 
    7664                 :         13 :   s.op->newline(-1) << "}";
    7665                 :            : 
    7666                 :         13 :   s.op->newline() << "mutex_destroy (& stap_uprobes_lock);";
    7667                 :            : }
    7668                 :            : 
    7669                 :            : 
    7670                 :            : void
    7671                 :          0 : uprobe_derived_probe_group::emit_module_inode_decls (systemtap_session& s)
    7672                 :            : {
    7673 [ #  # ][ #  # ]:          0 :   if (probes.empty()) return;
    7674 [ #  # ][ #  # ]:          0 :   s.op->newline() << "/* ---- inode uprobes ---- */";
    7675         [ #  # ]:          0 :   emit_module_maxuprobes (s);
    7676 [ #  # ][ #  # ]:          0 :   s.op->newline() << "#include \"linux/uprobes-inode.c\"";
    7677                 :            : 
    7678                 :            :   // Write the probe handler.
    7679 [ #  # ][ #  # ]:          0 :   s.op->newline() << "static int stapiu_probe_handler "
    7680         [ #  # ]:          0 :                   << "(struct stapiu_consumer *sup, struct pt_regs *regs) {";
    7681         [ #  # ]:          0 :   s.op->newline(1);
    7682                 :            :   common_probe_entryfn_prologue (s, "STAP_SESSION_RUNNING", "sup->probe",
    7683 [ #  # ][ #  # ]:          0 :                                  "stp_probe_type_uprobe");
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
    7684 [ #  # ][ #  # ]:          0 :   s.op->newline() << "c->uregs = regs;";
    7685 [ #  # ][ #  # ]:          0 :   s.op->newline() << "c->user_mode_p = 1;";
    7686                 :            :   // NB: IP is already set by stapiu_probe_prehandler in uprobes-inode.c
    7687 [ #  # ][ #  # ]:          0 :   s.op->newline() << "(*sup->probe->ph) (c);";
    7688                 :            : 
    7689         [ #  # ]:          0 :   common_probe_entryfn_epilogue (s, true);
    7690 [ #  # ][ #  # ]:          0 :   s.op->newline() << "return 0;";
    7691 [ #  # ][ #  # ]:          0 :   s.op->newline(-1) << "}";
    7692         [ #  # ]:          0 :   s.op->assert_0_indent();
    7693                 :            : 
    7694                 :            :   // Index of all the modules for which we need inodes.
    7695         [ #  # ]:          0 :   map<string, unsigned> module_index;
    7696                 :          0 :   unsigned module_index_ctr = 0;
    7697                 :            : 
    7698                 :            :   // Discover and declare targets for each unique path.
    7699 [ #  # ][ #  # ]:          0 :   s.op->newline() << "static struct stapiu_target "
    7700         [ #  # ]:          0 :                   << "stap_inode_uprobe_targets[] = {";
    7701         [ #  # ]:          0 :   s.op->indent(1);
    7702         [ #  # ]:          0 :   for (unsigned i=0; i<probes.size(); i++)
    7703                 :            :     {
    7704                 :          0 :       uprobe_derived_probe *p = probes[i];
    7705         [ #  # ]:          0 :       const string key = make_pbm_key(p);
    7706 [ #  # ][ #  # ]:          0 :       if (module_index.find (key) == module_index.end())
                 [ #  # ]
    7707                 :            :         {
    7708         [ #  # ]:          0 :           module_index[key] = module_index_ctr++;
    7709 [ #  # ][ #  # ]:          0 :           s.op->newline() << "{";
    7710 [ #  # ][ #  # ]:          0 :           s.op->line() << " .finder={";
    7711 [ #  # ][ #  # ]:          0 :           s.op->line() << "  .purpose=\"inode-uprobes\",";          
    7712         [ #  # ]:          0 :           if (p->pid != 0)
    7713 [ #  # ][ #  # ]:          0 :             s.op->line() << " .pid=" << p->pid << ",";
         [ #  # ][ #  # ]
    7714                 :            : 
    7715 [ #  # ][ #  # ]:          0 :           if (p->section == "") // .statement(addr).absolute  XXX?
    7716 [ #  # ][ #  # ]:          0 :             s.op->line() << " .callback=&stapiu_process_found,";
    7717 [ #  # ][ #  # ]:          0 :           else if (p->section == ".absolute") // proxy for ET_EXEC -> exec()'d program
    7718                 :            :             {
    7719 [ #  # ][ #  # ]:          0 :               s.op->line() << " .procname=" << lex_cast_qstring(p->module) << ",";
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
    7720 [ #  # ][ #  # ]:          0 :               s.op->line() << " .callback=&stapiu_process_found,";
    7721                 :            :             }
    7722 [ #  # ][ #  # ]:          0 :           else if (p->section != ".absolute") // ET_DYN
    7723                 :            :             {
    7724         [ #  # ]:          0 :               if (p->has_library)
    7725 [ #  # ][ #  # ]:          0 :                 s.op->line() << " .procname=\"" << p->path << "\", ";
         [ #  # ][ #  # ]
    7726 [ #  # ][ #  # ]:          0 :               s.op->line() << " .mmap_callback=&stapiu_mmap_found, ";
    7727 [ #  # ][ #  # ]:          0 :               s.op->line() << " .munmap_callback=&stapiu_munmap_found, ";
    7728 [ #  # ][ #  # ]:          0 :               s.op->line() << " .callback=&stapiu_process_munmap,";
    7729                 :            :             }
    7730 [ #  # ][ #  # ]:          0 :           s.op->line() << " },";
    7731 [ #  # ][ #  # ]:          0 :           s.op->line() << " .filename=" << lex_cast_qstring(p->module) << ",";
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
    7732 [ #  # ][ #  # ]:          0 :           s.op->line() << " },";
    7733                 :            :         }
    7734         [ #  # ]:          0 :     }
    7735 [ #  # ][ #  # ]:          0 :   s.op->newline(-1) << "};";
    7736         [ #  # ]:          0 :   s.op->assert_0_indent();
    7737                 :            : 
    7738                 :            :   // Declare the actual probes.
    7739                 :            :   unsigned pci;
    7740         [ #  # ]:          0 :   for (pci=0; pci<probes.size(); pci++)
    7741                 :            :     {
    7742                 :            :       // List of perf counters used by each probe
    7743                 :            :       // This list is an index into struct stap_perf_probe,
    7744                 :          0 :       uprobe_derived_probe *p = probes[pci];
    7745                 :          0 :       std::set<derived_probe*>::iterator pcii;
    7746 [ #  # ][ #  # ]:          0 :       s.op->newline() << "long perf_counters_" + lex_cast(pci) + "[] = {";
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
    7747 [ #  # ][ #  # ]:          0 :       for (pcii = p->perf_counter_refs.begin();
    7748         [ #  # ]:          0 :            pcii != p->perf_counter_refs.end(); pcii++)
    7749                 :            :         {
    7750                 :          0 :           map<string, pair<string,derived_probe*> >::iterator it;
    7751                 :          0 :           unsigned i = 0;
    7752                 :            :           // Find the associated perf.counter probe
    7753 [ #  # ][ #  # ]:          0 :           for (it=s.perf_counters.begin() ;
    7754         [ #  # ]:          0 :                it != s.perf_counters.end(); it++, i++)
    7755         [ #  # ]:          0 :             if ((*it).second.second == (*pcii))
    7756                 :          0 :               break;
    7757 [ #  # ][ #  # ]:          0 :           s.op->line() << lex_cast(i) << ", ";
         [ #  # ][ #  # ]
                 [ #  # ]
    7758                 :            :         }
    7759 [ #  # ][ #  # ]:          0 :       s.op->newline() << "};";
    7760                 :            :     }
    7761                 :            : 
    7762 [ #  # ][ #  # ]:          0 :   s.op->newline() << "static struct stapiu_consumer "
    7763         [ #  # ]:          0 :                   << "stap_inode_uprobe_consumers[] = {";
    7764         [ #  # ]:          0 :   s.op->indent(1);
    7765         [ #  # ]:          0 :   for (unsigned i=0; i<probes.size(); i++)
    7766                 :            :     {
    7767                 :          0 :       uprobe_derived_probe *p = probes[i];
    7768 [ #  # ][ #  # ]:          0 :       unsigned index = module_index[make_pbm_key(p)];
                 [ #  # ]
    7769 [ #  # ][ #  # ]:          0 :       s.op->newline() << "{";
    7770         [ #  # ]:          0 :       if (p->has_return)
    7771 [ #  # ][ #  # ]:          0 :         s.op->line() << " .return_p=1,";
    7772 [ #  # ][ #  # ]:          0 :       s.op->line() << " .target=&stap_inode_uprobe_targets[" << index << "],";
         [ #  # ][ #  # ]
    7773 [ #  # ][ #  # ]:          0 :       s.op->line() << " .offset=(loff_t)0x" << hex << p->addr << dec << "ULL,";
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
    7774         [ #  # ]:          0 :       if (p->sdt_semaphore_addr)
    7775 [ #  # ][ #  # ]:          0 :         s.op->line() << " .sdt_sem_offset=(loff_t)0x"
    7776 [ #  # ][ #  # ]:          0 :                      << hex << p->sdt_semaphore_addr << dec << "ULL,";
         [ #  # ][ #  # ]
    7777                 :            :       // XXX: don't bother emit if array is empty
    7778 [ #  # ][ #  # ]:          0 :       s.op->line() << " .perf_counters_dim=ARRAY_SIZE(perf_counters_" << lex_cast(i) << "),";
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
    7779                 :            :       // List of perf counters used by a probe from above
    7780 [ #  # ][ #  # ]:          0 :       s.op->line() << " .perf_counters=perf_counters_" + lex_cast(i) + ",";
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
    7781 [ #  # ][ #  # ]:          0 :       s.op->line() << " .probe=" << common_probe_init (p) << ",";
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
    7782 [ #  # ][ #  # ]:          0 :       s.op->line() << " },";
    7783                 :            :     }
    7784 [ #  # ][ #  # ]:          0 :   s.op->newline(-1) << "};";
    7785 [ #  # ][ #  # ]:          0 :   s.op->assert_0_indent();
    7786                 :            : }
    7787                 :            : 
    7788                 :            : 
    7789                 :            : void
    7790                 :          0 : uprobe_derived_probe_group::emit_module_inode_init (systemtap_session& s)
    7791                 :            : {
    7792         [ #  # ]:          0 :   if (probes.empty()) return;
    7793                 :          0 :   s.op->newline() << "/* ---- inode uprobes ---- */";
    7794                 :            :   // Let stapiu_init() handle reporting errors by setting probe_point
    7795                 :            :   // to NULL.
    7796                 :          0 :   s.op->newline() << "probe_point = NULL;";
    7797                 :          0 :   s.op->newline() << "rc = stapiu_init ("
    7798                 :          0 :                   << "stap_inode_uprobe_targets, "
    7799                 :          0 :                   << "ARRAY_SIZE(stap_inode_uprobe_targets), "
    7800                 :          0 :                   << "stap_inode_uprobe_consumers, "
    7801                 :          0 :                   << "ARRAY_SIZE(stap_inode_uprobe_consumers));";
    7802                 :            : }
    7803                 :            : 
    7804                 :            : 
    7805                 :            : void
    7806                 :          0 : uprobe_derived_probe_group::emit_module_inode_exit (systemtap_session& s)
    7807                 :            : {
    7808         [ #  # ]:          0 :   if (probes.empty()) return;
    7809                 :          0 :   s.op->newline() << "/* ---- inode uprobes ---- */";
    7810                 :          0 :   s.op->newline() << "stapiu_exit ("
    7811                 :          0 :                   << "stap_inode_uprobe_targets, "
    7812                 :          0 :                   << "ARRAY_SIZE(stap_inode_uprobe_targets), "
    7813                 :          0 :                   << "stap_inode_uprobe_consumers, "
    7814                 :          0 :                   << "ARRAY_SIZE(stap_inode_uprobe_consumers));";
    7815                 :            : }
    7816                 :            : 
    7817                 :            : 
    7818                 :            : void
    7819                 :          0 : uprobe_derived_probe_group::emit_module_dyninst_decls (systemtap_session& s)
    7820                 :            : {
    7821         [ #  # ]:          0 :   if (probes.empty()) return;
    7822                 :          0 :   s.op->newline() << "/* ---- dyninst uprobes ---- */";
    7823                 :          0 :   emit_module_maxuprobes (s);
    7824                 :          0 :   s.op->newline() << "#include \"dyninst/uprobes.h\"";
    7825                 :            : 
    7826                 :            :   // Let the dynprobe_derived_probe_group handle outputting targets
    7827                 :            :   // and probes. This allows us to merge different types of probes.
    7828                 :          0 :   s.op->newline() << "static struct stapdu_probe stapdu_probes[];";
    7829         [ #  # ]:          0 :   for (unsigned i = 0; i < probes.size(); i++)
    7830                 :            :     {
    7831                 :          0 :       uprobe_derived_probe *p = probes[i];
    7832                 :            : 
    7833                 :            :       dynprobe_add_uprobe(s, p->module, p->addr, p->sdt_semaphore_addr,
    7834                 :            :                           (p->has_return ? "STAPDYN_PROBE_FLAG_RETURN" : "0"),
    7835 [ #  # ][ #  # ]:          0 :                           common_probe_init(p));
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
    7836                 :            :     }
    7837                 :            :   // loc2c-generated code assumes pt_regs are available, so use this to make
    7838                 :            :   // sure we always have *something* for it to dereference...
    7839                 :          0 :   s.op->newline() << "static struct pt_regs stapdu_dummy_uregs;";
    7840                 :            : 
    7841                 :            :   // Write the probe handler.
    7842                 :            :   // NB: not static, so dyninst can find it
    7843                 :          0 :   s.op->newline() << "int enter_dyninst_uprobe "
    7844                 :          0 :                   << "(uint64_t index, struct pt_regs *regs) {";
    7845                 :          0 :   s.op->newline(1) << "struct stapdu_probe *sup = &stapdu_probes[index];";
    7846                 :            :   common_probe_entryfn_prologue (s, "STAP_SESSION_RUNNING", "sup->probe",
    7847 [ #  # ][ #  # ]:          0 :                                  "stp_probe_type_uprobe");
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
    7848                 :          0 :   s.op->newline() << "c->uregs = regs ?: &stapdu_dummy_uregs;";
    7849                 :          0 :   s.op->newline() << "c->user_mode_p = 1;";
    7850                 :            :   // XXX: once we have regs, check how dyninst sets the IP
    7851                 :            :   // XXX: the way that dyninst rewrites stuff is probably going to be
    7852                 :            :   // ...  very confusing to our backtracer (at least if we stay in process)
    7853                 :          0 :   s.op->newline() << "(*sup->probe->ph) (c);";
    7854                 :          0 :   common_probe_entryfn_epilogue (s, true);
    7855                 :          0 :   s.op->newline() << "return 0;";
    7856                 :          0 :   s.op->newline(-1) << "}";
    7857                 :          0 :   s.op->assert_0_indent();
    7858                 :            : }
    7859                 :            : 
    7860                 :            : 
    7861                 :            : void
    7862                 :          0 : uprobe_derived_probe_group::emit_module_dyninst_init (systemtap_session& s)
    7863                 :            : {
    7864         [ #  # ]:          0 :   if (probes.empty()) return;
    7865                 :            : 
    7866                 :            :   /* stapdyn handles the dirty work via dyninst */
    7867                 :          0 :   s.op->newline() << "/* ---- dyninst uprobes ---- */";
    7868                 :          0 :   s.op->newline() << "/* this section left intentionally blank */";
    7869                 :            : }
    7870                 :            : 
    7871                 :            : 
    7872                 :            : void
    7873                 :          0 : uprobe_derived_probe_group::emit_module_dyninst_exit (systemtap_session& s)
    7874                 :            : {
    7875         [ #  # ]:          0 :   if (probes.empty()) return;
    7876                 :            : 
    7877                 :            :   /* stapdyn handles the dirty work via dyninst */
    7878                 :          0 :   s.op->newline() << "/* ---- dyninst uprobes ---- */";
    7879                 :          0 :   s.op->newline() << "/* this section left intentionally blank */";
    7880                 :            : }
    7881                 :            : 
    7882                 :            : 
    7883                 :            : void
    7884                 :          6 : uprobe_derived_probe_group::emit_module_decls (systemtap_session& s)
    7885                 :            : {
    7886         [ -  + ]:          6 :   if (s.runtime_usermode_p())
    7887                 :          0 :     emit_module_dyninst_decls (s);
    7888         [ -  + ]:          6 :   else if (kernel_supports_inode_uprobes (s))
    7889                 :          0 :     emit_module_inode_decls (s);
    7890                 :            :   else
    7891                 :          6 :     emit_module_utrace_decls (s);
    7892                 :          6 : }
    7893                 :            : 
    7894                 :            : 
    7895                 :            : void
    7896                 :          6 : uprobe_derived_probe_group::emit_module_init (systemtap_session& s)
    7897                 :            : {
    7898         [ -  + ]:          6 :   if (s.runtime_usermode_p())
    7899                 :          0 :     emit_module_dyninst_init (s);
    7900         [ -  + ]:          6 :   else if (kernel_supports_inode_uprobes (s))
    7901                 :          0 :     emit_module_inode_init (s);
    7902                 :            :   else
    7903                 :          6 :     emit_module_utrace_init (s);
    7904                 :          6 : }
    7905                 :            : 
    7906                 :            : 
    7907                 :            : void
    7908                 :         13 : uprobe_derived_probe_group::emit_module_exit (systemtap_session& s)
    7909                 :            : {
    7910         [ -  + ]:         13 :   if (s.runtime_usermode_p())
    7911                 :          0 :     emit_module_dyninst_exit (s);
    7912         [ -  + ]:         13 :   else if (kernel_supports_inode_uprobes (s))
    7913                 :          0 :     emit_module_inode_exit (s);
    7914                 :            :   else
    7915                 :         13 :     emit_module_utrace_exit (s);
    7916                 :         13 : }
    7917                 :            : 
    7918                 :            : 
    7919                 :            : // ------------------------------------------------------------------------
    7920                 :            : // Kprobe derived probes
    7921                 :            : // ------------------------------------------------------------------------
    7922                 :            : 
    7923         [ +  - ]:       2414 : static const string TOK_KPROBE("kprobe");
    7924                 :            : 
    7925 [ #  # ][ #  # ]:          0 : struct kprobe_derived_probe: public derived_probe
         [ #  # ][ #  # ]
    7926                 :            : {
    7927                 :            :   kprobe_derived_probe (systemtap_session& sess,
    7928                 :            :                         vector<derived_probe *> & results,
    7929                 :            :                         probe *base,
    7930                 :            :                         probe_point *location,
    7931                 :            :                         const string& name,
    7932                 :            :                         int64_t stmt_addr,
    7933                 :            :                         bool has_return,
    7934                 :            :                         bool has_statement,
    7935                 :            :                         bool has_maxactive,
    7936                 :            :                         bool has_path,
    7937                 :            :                         bool has_library,
    7938                 :            :                         long maxactive_val,
    7939                 :            :                         const string& path,
    7940                 :            :                         const string& library
    7941                 :            :                         );
    7942                 :            :   string symbol_name;
    7943                 :            :   Dwarf_Addr addr;
    7944                 :            :   bool has_return;
    7945                 :            :   bool has_statement;
    7946                 :            :   bool has_maxactive;
    7947                 :            :   bool has_path;
    7948                 :            :   bool has_library;
    7949                 :            :   long maxactive_val;
    7950                 :            :   string path;
    7951                 :            :   string library;
    7952                 :            :   bool access_var;
    7953                 :            :   void printsig (std::ostream &o) const;
    7954                 :            :   void join_group (systemtap_session& s);
    7955                 :            : };
    7956                 :            : 
    7957 [ #  # ][ #  # ]:         52 : struct kprobe_derived_probe_group: public derived_probe_group
                 [ +  - ]
    7958                 :            : {
    7959                 :            : private:
    7960                 :            :   multimap<string,kprobe_derived_probe*> probes_by_module;
    7961                 :            :   typedef multimap<string,kprobe_derived_probe*>::iterator p_b_m_iterator;
    7962                 :            : 
    7963                 :            : public:
    7964                 :            :   void enroll (kprobe_derived_probe* probe);
    7965                 :            :   void emit_module_decls (systemtap_session& s);
    7966                 :            :   void emit_module_init (systemtap_session& s);
    7967                 :            :   void emit_module_exit (systemtap_session& s);
    7968                 :            : };
    7969                 :            : 
    7970         [ -  + ]:      21299 : struct kprobe_var_expanding_visitor: public var_expanding_visitor
    7971                 :            : {
    7972                 :            :   systemtap_session& sess;
    7973                 :            :   block *add_block;
    7974                 :            :   block *add_call_probe; // synthesized from .return probes with saved $vars
    7975                 :            :   bool add_block_tid, add_call_probe_tid;
    7976                 :            :   bool has_return;
    7977                 :            : 
    7978                 :      21299 :   kprobe_var_expanding_visitor(systemtap_session& sess, bool has_return):
    7979                 :            :     sess(sess), add_block(NULL), add_call_probe(NULL),
    7980                 :            :     add_block_tid(false), add_call_probe_tid(false),
    7981                 :      21299 :     has_return(has_return) {}
    7982                 :            : 
    7983                 :            :   void visit_entry_op (entry_op* e);
    7984                 :            : };
    7985                 :            : 
    7986                 :            : 
    7987                 :      21299 : kprobe_derived_probe::kprobe_derived_probe (systemtap_session& sess,
    7988                 :            :                                             vector<derived_probe *> & results,
    7989                 :            :                                             probe *base,
    7990                 :            :                                             probe_point *location,
    7991                 :            :                                             const string& name,
    7992                 :            :                                             int64_t stmt_addr,
    7993                 :            :                                             bool has_return,
    7994                 :            :                                             bool has_statement,
    7995                 :            :                                             bool has_maxactive,
    7996                 :            :                                             bool has_path,
    7997                 :            :                                             bool has_library,
    7998                 :            :                                             long maxactive_val,
    7999                 :            :                                             const string& path,
    8000                 :            :                                             const string& library
    8001                 :            :                                             ):
    8002                 :            :   derived_probe (base, location, true /* .components soon rewritten */ ),
    8003                 :            :   symbol_name (name), addr (stmt_addr),
    8004                 :            :   has_return (has_return), has_statement (has_statement),
    8005                 :            :   has_maxactive (has_maxactive), has_path (has_path),
    8006                 :            :   has_library (has_library),
    8007                 :            :   maxactive_val (maxactive_val),
    8008 [ +  - ][ +  - ]:      21299 :   path (path), library (library)
                 [ +  - ]
    8009                 :            : {
    8010                 :      21299 :   this->tok = base->tok;
    8011                 :      21299 :   this->access_var = false;
    8012                 :            : 
    8013                 :            : #ifndef USHRT_MAX
    8014                 :            : #define USHRT_MAX 32767
    8015                 :            : #endif
    8016                 :            : 
    8017                 :            :   // Expansion of $target variables in the probe body produces an error during
    8018                 :            :   // translate phase, since we're not using debuginfo
    8019                 :            : 
    8020         [ +  - ]:      21299 :   vector<probe_point::component*> comps;
    8021 [ +  - ][ +  - ]:      21299 :   comps.push_back (new probe_point::component(TOK_KPROBE));
                 [ +  - ]
    8022                 :            : 
    8023         [ +  + ]:      21299 :   if (has_statement)
    8024                 :            :     {
    8025                 :            :       comps.push_back (new probe_point::component(TOK_STATEMENT,
    8026 [ +  - ][ +  - ]:          2 :                                                   new literal_number(addr, true)));
         [ +  - ][ +  - ]
                 [ +  - ]
    8027 [ +  - ][ +  - ]:          2 :       comps.push_back (new probe_point::component(TOK_ABSOLUTE));
                 [ +  - ]
    8028                 :            :     }
    8029                 :            :   else
    8030                 :            :     {
    8031         [ +  - ]:      21297 :       size_t pos = name.find(':');
    8032         [ -  + ]:      21297 :       if (pos != string::npos)
    8033                 :            :         {
    8034         [ #  # ]:          0 :           string module = name.substr(0, pos);
    8035         [ #  # ]:          0 :           string function = name.substr(pos + 1);
    8036 [ #  # ][ #  # ]:          0 :           comps.push_back (new probe_point::component(TOK_MODULE, new literal_string(module)));
         [ #  # ][ #  # ]
                 [ #  # ]
    8037 [ #  # ][ #  # ]:          0 :           comps.push_back (new probe_point::component(TOK_FUNCTION, new literal_string(function)));
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
    8038                 :            :         }
    8039                 :            :       else
    8040 [ +  - ][ +  - ]:      21297 :         comps.push_back (new probe_point::component(TOK_FUNCTION, new literal_string(name)));
         [ +  - ][ +  - ]
                 [ +  - ]
    8041                 :            :     }
    8042                 :            : 
    8043         [ +  + ]:      21299 :   if (has_return)
    8044 [ +  - ][ +  - ]:      10484 :     comps.push_back (new probe_point::component(TOK_RETURN));
                 [ +  - ]
    8045         [ +  + ]:      21299 :   if (has_maxactive)
    8046 [ +  - ][ +  - ]:          1 :     comps.push_back (new probe_point::component(TOK_MAXACTIVE, new literal_number(maxactive_val)));
         [ +  - ][ +  - ]
                 [ +  - ]
    8047                 :            : 
    8048         [ +  - ]:      21299 :   kprobe_var_expanding_visitor v (sess, has_return);
    8049         [ +  - ]:      21299 :   v.replace (this->body);
    8050                 :            : 
    8051                 :            :   // If during target-variable-expanding the probe, we added a new block
    8052                 :            :   // of code, add it to the start of the probe.
    8053         [ +  + ]:      21299 :   if (v.add_block)
    8054 [ +  - ][ +  - ]:        254 :     this->body = new block(v.add_block, this->body);
    8055                 :            : 
    8056                 :            :   // If when target-variable-expanding the probe, we need to
    8057                 :            :   // synthesize a sibling function-entry probe.  We don't go through
    8058                 :            :   // the whole probe derivation business (PR10642) that could lead to
    8059                 :            :   // wildcard/alias resolution, or for that dwarf-induced duplication.
    8060         [ +  + ]:      21299 :   if (v.add_call_probe)
    8061                 :            :     {
    8062         [ -  + ]:        254 :       assert (has_return);
    8063                 :            : 
    8064                 :            :       // We temporarily replace base.
    8065                 :        254 :       statement* old_body = base->body;
    8066                 :        254 :       base->body = v.add_call_probe;
    8067                 :            : 
    8068                 :            :       derived_probe *entry_handler
    8069                 :            :         = new kprobe_derived_probe (sess, results, base, location, name, 0,
    8070                 :            :                                     false, has_statement, has_maxactive,
    8071                 :            :                                     has_path, has_library, maxactive_val,
    8072 [ +  - ][ +  - ]:        254 :                                     path, library);
    8073         [ +  - ]:        254 :       results.push_back (entry_handler);
    8074                 :            : 
    8075                 :        254 :       base->body = old_body;
    8076                 :            :     }
    8077                 :            : 
    8078 [ +  - ][ +  - ]:      21299 :   this->sole_location()->components = comps;
         [ +  - ][ +  - ]
    8079                 :      21299 : }
    8080                 :            : 
    8081                 :      20708 : void kprobe_derived_probe::printsig (ostream& o) const
    8082                 :            : {
    8083                 :      20708 :   sole_location()->print (o);
    8084                 :      20708 :   o << " /* " << " name = " << symbol_name << "*/";
    8085                 :      20708 :   printsig_nested (o);
    8086                 :      20708 : }
    8087                 :            : 
    8088                 :      21299 : void kprobe_derived_probe::join_group (systemtap_session& s)
    8089                 :            : {
    8090                 :            : 
    8091         [ +  + ]:      21299 :   if (! s.kprobe_derived_probes)
    8092         [ +  - ]:         52 :         s.kprobe_derived_probes = new kprobe_derived_probe_group ();
    8093                 :      21299 :   s.kprobe_derived_probes->enroll (this);
    8094                 :            : 
    8095                 :      21299 : }
    8096                 :            : 
    8097                 :      21299 : void kprobe_derived_probe_group::enroll (kprobe_derived_probe* p)
    8098                 :            : {
    8099 [ +  - ][ +  - ]:      21299 :   probes_by_module.insert (make_pair (p->symbol_name, p));
         [ +  - ][ +  - ]
                 [ +  - ]
    8100                 :            :   // probes of same symbol should share single kprobe/kretprobe
    8101                 :      21299 : }
    8102                 :            : 
    8103                 :            : void
    8104                 :         12 : kprobe_derived_probe_group::emit_module_decls (systemtap_session& s)
    8105                 :            : {
    8106 [ +  - ][ +  - ]:         24 :   if (probes_by_module.empty()) return;
    8107                 :            : 
    8108 [ +  - ][ +  - ]:         12 :   s.op->newline() << "/* ---- kprobe-based probes ---- */";
    8109                 :            : 
    8110                 :            :   // Warn of misconfigured kernels
    8111 [ +  - ][ +  - ]:         12 :   s.op->newline() << "#if ! defined(CONFIG_KPROBES)";
    8112 [ +  - ][ +  - ]:         12 :   s.op->newline() << "#error \"Need CONFIG_KPROBES!\"";
    8113 [ +  - ][ +  - ]:         12 :   s.op->newline() << "#endif";
    8114         [ +  - ]:         12 :   s.op->newline();
    8115                 :            : 
    8116 [ +  - ][ +  - ]:         12 :   s.op->newline() << "#ifndef KRETACTIVE";
    8117 [ +  - ][ +  - ]:         12 :   s.op->newline() << "#define KRETACTIVE (max(15,6*(int)num_possible_cpus()))";
    8118 [ +  - ][ +  - ]:         12 :   s.op->newline() << "#endif";
    8119                 :            : 
    8120                 :            :   // Forward declare the master entry functions
    8121 [ +  - ][ +  - ]:         12 :   s.op->newline() << "static int enter_kprobe2_probe (struct kprobe *inst,";
    8122 [ +  - ][ +  - ]:         12 :   s.op->line() << " struct pt_regs *regs);";
    8123 [ +  - ][ +  - ]:         12 :   s.op->newline() << "static int enter_kretprobe2_probe (struct kretprobe_instance *inst,";
    8124 [ +  - ][ +  - ]:         12 :   s.op->line() << " struct pt_regs *regs);";
    8125                 :            : 
    8126                 :            :   // Emit an array of kprobe/kretprobe pointers
    8127 [ +  - ][ +  - ]:         12 :   s.op->newline() << "#if defined(STAPCONF_UNREGISTER_KPROBES)";
    8128 [ +  - ][ +  - ]:         12 :   s.op->newline() << "static void * stap_unreg_kprobes2[" << probes_by_module.size() << "];";
         [ +  - ][ +  - ]
                 [ +  - ]
    8129 [ +  - ][ +  - ]:         12 :   s.op->newline() << "#endif";
    8130                 :            : 
    8131                 :            :   // Emit the actual probe list.
    8132                 :            : 
    8133 [ +  - ][ +  - ]:         12 :   s.op->newline() << "static struct stap_dwarfless_kprobe {";
    8134 [ +  - ][ +  - ]:         12 :   s.op->newline(1) << "union { struct kprobe kp; struct kretprobe krp; } u;";
    8135 [ +  - ][ +  - ]:         12 :   s.op->newline() << "#ifdef __ia64__";
    8136 [ +  - ][ +  - ]:         12 :   s.op->newline() << "struct kprobe dummy;";
    8137 [ +  - ][ +  - ]:         12 :   s.op->newline() << "#endif";
    8138 [ +  - ][ +  - ]:         12 :   s.op->newline(-1) << "} stap_dwarfless_kprobes[" << probes_by_module.size() << "];";
         [ +  - ][ +  - ]
                 [ +  - ]
    8139                 :            :   // NB: bss!
    8140                 :            : 
    8141 [ +  - ][ +  - ]:         12 :   s.op->newline() << "static struct stap_dwarfless_probe {";
    8142 [ +  - ][ +  - ]:         12 :   s.op->newline(1) << "const unsigned return_p:1;";
    8143 [ +  - ][ +  - ]:         12 :   s.op->newline() << "const unsigned maxactive_p:1;";
    8144 [ +  - ][ +  - ]:         12 :   s.op->newline() << "const unsigned optional_p:1;";
    8145 [ +  - ][ +  - ]:         12 :   s.op->newline() << "unsigned registered_p:1;";
    8146 [ +  - ][ +  - ]:         12 :   s.op->newline() << "const unsigned short maxactive_val;";
    8147                 :            : 
    8148                 :            :   // Function Names are mostly small and uniform enough to justify putting
    8149                 :            :   // char[MAX]'s into  the array instead of relocated char*'s.
    8150                 :            : 
    8151                 :         12 :   size_t symbol_string_name_max = 0;
    8152                 :         12 :   size_t symbol_string_name_tot = 0;
    8153 [ +  - ][ +  - ]:       1211 :   for (p_b_m_iterator it = probes_by_module.begin(); it != probes_by_module.end(); it++)
                 [ +  + ]
    8154                 :            :     {
    8155         [ +  - ]:       1199 :       kprobe_derived_probe* p = it->second;
    8156                 :            : #define DOIT(var,expr) do {                             \
    8157                 :            :         size_t var##_size = (expr) + 1;                 \
    8158                 :            :         var##_max = max (var##_max, var##_size);        \
    8159                 :            :         var##_tot += var##_size; } while (0)
    8160         [ +  - ]:       1199 :       DOIT(symbol_string_name, p->symbol_name.size());
    8161                 :            : #undef DOIT
    8162                 :            :     }
    8163                 :            : 
    8164                 :            : #define CALCIT(var)                                                     \
    8165                 :            :         s.op->newline() << "const char " << #var << "[" << var##_name_max << "] ;";
    8166                 :            : 
    8167 [ +  - ][ +  - ]:         12 :   CALCIT(symbol_string);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
    8168                 :            : #undef CALCIT
    8169                 :            : 
    8170 [ +  - ][ +  - ]:         12 :   s.op->newline() << "unsigned long address;";
    8171 [ +  - ][ +  - ]:         12 :   s.op->newline() << "const struct stap_probe * const probe;";
    8172 [ +  - ][ +  - ]:         12 :   s.op->newline(-1) << "} stap_dwarfless_probes[] = {";
    8173         [ +  - ]:         12 :   s.op->indent(1);
    8174                 :            : 
    8175 [ +  - ][ +  - ]:       1211 :   for (p_b_m_iterator it = probes_by_module.begin(); it != probes_by_module.end(); it++)
                 [ +  + ]
    8176                 :            :     {
    8177         [ +  - ]:       1199 :       kprobe_derived_probe* p = it->second;
    8178 [ +  - ][ +  - ]:       1199 :       s.op->newline() << "{";
    8179         [ +  + ]:       1199 :       if (p->has_return)
    8180 [ +  - ][ +  - ]:        589 :         s.op->line() << " .return_p=1,";
    8181                 :            : 
    8182         [ +  + ]:       1199 :       if (p->has_maxactive)
    8183                 :            :         {
    8184 [ +  - ][ +  - ]:          1 :           s.op->line() << " .maxactive_p=1,";
    8185 [ +  - ][ -  + ]:          1 :           assert (p->maxactive_val >= 0 && p->maxactive_val <= USHRT_MAX);
    8186 [ +  - ][ +  - ]:          1 :           s.op->line() << " .maxactive_val=" << p->maxactive_val << ",";
         [ +  - ][ +  - ]
    8187                 :            :         }
    8188                 :            : 
    8189         [ +  + ]:       1199 :       if (p->locations[0]->optional)
    8190 [ +  - ][ +  - ]:       1151 :         s.op->line() << " .optional_p=1,";
    8191                 :            : 
    8192         [ +  + ]:       1199 :       if (p->has_statement)
    8193 [ +  - ][ +  - ]:          2 :         s.op->line() << " .address=(unsigned long)0x" << hex << p->addr << dec << "ULL,";
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
    8194                 :            :       else
    8195 [ +  - ][ +  - ]:       1197 :         s.op->line() << " .symbol_string=\"" << p->symbol_name << "\",";
         [ +  - ][ +  - ]
    8196                 :            : 
    8197 [ +  - ][ +  - ]:       1199 :       s.op->line() << " .probe=" << common_probe_init (p) << ",";
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
    8198 [ +  - ][ +  - ]:       1199 :       s.op->line() << " },";
    8199                 :            :     }
    8200                 :            : 
    8201 [ +  - ][ +  - ]:         12 :   s.op->newline(-1) << "};";
    8202                 :            : 
    8203                 :            :   // Emit the kprobes callback function
    8204         [ +  - ]:         12 :   s.op->newline();
    8205 [ +  - ][ +  - ]:         12 :   s.op->newline() << "static int enter_kprobe2_probe (struct kprobe *inst,";
    8206 [ +  - ][ +  - ]:         12 :   s.op->line() << " struct pt_regs *regs) {";
    8207                 :            :   // NB: as of PR5673, the kprobe|kretprobe union struct is in BSS
    8208 [ +  - ][ +  - ]:         12 :   s.op->newline(1) << "int kprobe_idx = ((uintptr_t)inst-(uintptr_t)stap_dwarfless_kprobes)/sizeof(struct stap_dwarfless_kprobe);";
    8209                 :            :   // Check that the index is plausible
    8210 [ +  - ][ +  - ]:         12 :   s.op->newline() << "struct stap_dwarfless_probe *sdp = &stap_dwarfless_probes[";
    8211 [ +  - ][ +  - ]:         12 :   s.op->line() << "((kprobe_idx >= 0 && kprobe_idx < " << probes_by_module.size() << ")?";
         [ +  - ][ +  - ]
                 [ +  - ]
    8212 [ +  - ][ +  - ]:         12 :   s.op->line() << "kprobe_idx:0)"; // NB: at least we avoid memory corruption
    8213                 :            :   // XXX: it would be nice to give a more verbose error though; BUG_ON later?
    8214 [ +  - ][ +  - ]:         12 :   s.op->line() << "];";
    8215                 :            :   common_probe_entryfn_prologue (s, "STAP_SESSION_RUNNING", "sdp->probe",
    8216 [ +  - ][ +  - ]:         12 :                                  "stp_probe_type_kprobe");
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    8217 [ +  - ][ +  - ]:         12 :   s.op->newline() << "c->kregs = regs;";
    8218                 :            : 
    8219                 :            :   // Make it look like the IP is set as it wouldn't have been replaced
    8220                 :            :   // by a breakpoint instruction when calling real probe handler. Reset
    8221                 :            :   // IP regs on return, so we don't confuse kprobes. PR10458
    8222 [ +  - ][ +  - ]:         12 :   s.op->newline() << "{";
    8223         [ +  - ]:         12 :   s.op->indent(1);
    8224 [ +  - ][ +  - ]:         12 :   s.op->newline() << "unsigned long kprobes_ip = REG_IP(c->kregs);";
    8225 [ +  - ][ +  - ]:         12 :   s.op->newline() << "SET_REG_IP(regs, (unsigned long) inst->addr);";
    8226 [ +  - ][ +  - ]:         12 :   s.op->newline() << "(*sdp->probe->ph) (c);";
    8227 [ +  - ][ +  - ]:         12 :   s.op->newline() << "SET_REG_IP(regs, kprobes_ip);";
    8228 [ +  - ][ +  - ]:         12 :   s.op->newline(-1) << "}";
    8229                 :            : 
    8230         [ +  - ]:         12 :   common_probe_entryfn_epilogue (s, true);
    8231 [ +  - ][ +  - ]:         12 :   s.op->newline() << "return 0;";
    8232 [ +  - ][ +  - ]:         12 :   s.op->newline(-1) << "}";
    8233                 :            : 
    8234                 :            :   // Same for kretprobes
    8235         [ +  - ]:         12 :   s.op->newline();
    8236 [ +  - ][ +  - ]:         12 :   s.op->newline() << "static int enter_kretprobe2_probe (struct kretprobe_instance *inst,";
    8237 [ +  - ][ +  - ]:         12 :   s.op->line() << " struct pt_regs *regs) {";
    8238 [ +  - ][ +  - ]:         12 :   s.op->newline(1) << "struct kretprobe *krp = inst->rp;";
    8239                 :            : 
    8240                 :            :   // NB: as of PR5673, the kprobe|kretprobe union struct is in BSS
    8241 [ +  - ][ +  - ]:         12 :   s.op->newline() << "int kprobe_idx = ((uintptr_t)krp-(uintptr_t)stap_dwarfless_kprobes)/sizeof(struct stap_dwarfless_kprobe);";
    8242                 :            :   // Check that the index is plausible
    8243 [ +  - ][ +  - ]:         12 :   s.op->newline() << "struct stap_dwarfless_probe *sdp = &stap_dwarfless_probes[";
    8244 [ +  - ][ +  - ]:         12 :   s.op->line() << "((kprobe_idx >= 0 && kprobe_idx < " << probes_by_module.size() << ")?";
         [ +  - ][ +  - ]
                 [ +  - ]
    8245 [ +  - ][ +  - ]:         12 :   s.op->line() << "kprobe_idx:0)"; // NB: at least we avoid memory corruption
    8246                 :            :   // XXX: it would be nice to give a more verbose error though; BUG_ON later?
    8247 [ +  - ][ +  - ]:         12 :   s.op->line() << "];";
    8248                 :            : 
    8249                 :            :   common_probe_entryfn_prologue (s, "STAP_SESSION_RUNNING", "sdp->probe",
    8250 [ +  - ][ +  - ]:         12 :                                  "stp_probe_type_kretprobe");
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    8251 [ +  - ][ +  - ]:         12 :   s.op->newline() << "c->kregs = regs;";
    8252 [ +  - ][ +  - ]:         12 :   s.op->newline() << "c->ips.krp.pi = inst;"; // for assisting runtime's backtrace logic
    8253                 :            : 
    8254                 :            :   // Make it look like the IP is set as it wouldn't have been replaced
    8255                 :            :   // by a breakpoint instruction when calling real probe handler. Reset
    8256                 :            :   // IP regs on return, so we don't confuse kprobes. PR10458
    8257 [ +  - ][ +  - ]:         12 :   s.op->newline() << "{";
    8258         [ +  - ]:         12 :   s.op->indent(1);
    8259 [ +  - ][ +  - ]:         12 :   s.op->newline() << "unsigned long kprobes_ip = REG_IP(c->kregs);";
    8260 [ +  - ][ +  - ]:         12 :   s.op->newline() << "SET_REG_IP(regs, (unsigned long) inst->rp->kp.addr);";
    8261 [ +  - ][ +  - ]:         12 :   s.op->newline() << "(*sdp->probe->ph) (c);";
    8262 [ +  - ][ +  - ]:         12 :   s.op->newline() << "SET_REG_IP(regs, kprobes_ip);";
    8263 [ +  - ][ +  - ]:         12 :   s.op->newline(-1) << "}";
    8264                 :            : 
    8265         [ +  - ]:         12 :   common_probe_entryfn_epilogue (s, true);
    8266 [ +  - ][ +  - ]:         12 :   s.op->newline() << "return 0;";
    8267 [ +  - ][ +  - ]:         12 :   s.op->newline(-1) << "}";
    8268                 :            : 
    8269 [ +  - ][ +  - ]:         12 :   s.op->newline() << "#ifdef STAPCONF_KALLSYMS_ON_EACH_SYMBOL";
    8270 [ +  - ][ +  - ]:         12 :   s.op->newline() << "static int kprobe_resolve(void *data, const char *name,";
    8271 [ +  - ][ +  - ]:         12 :   s.op->newline() << "                          struct module *owner,";
    8272 [ +  - ][ +  - ]:         12 :   s.op->newline() << "                          unsigned long val) {";
    8273 [ +  - ][ +  - ]:         12 :   s.op->newline(1) << "int i;";
    8274 [ +  - ][ +  - ]:         12 :   s.op->newline() << "int *p = (int *) data;";
    8275 [ +  - ][ +  - ]:         12 :   s.op->newline() << "for (i=0; i<" << probes_by_module.size()
         [ +  - ][ +  - ]
    8276         [ +  - ]:         12 :                   << " && *p > 0; i++) {";
    8277 [ +  - ][ +  - ]:         12 :   s.op->newline(1) << "struct stap_dwarfless_probe *sdp = & stap_dwarfless_probes[i];";
    8278 [ +  - ][ +  - ]:         12 :   s.op->newline() << "if (! sdp->address)";
    8279 [ +  - ][ +  - ]:         12 :   s.op->newline(1) << "if (strcmp(sdp->symbol_string, name) == 0) {";
    8280 [ +  - ][ +  - ]:         12 :   s.op->newline(1) << "sdp->address = val;";
    8281 [ +  - ][ +  - ]:         12 :   s.op->newline() << "(*p)--;";
    8282 [ +  - ][ +  - ]:         12 :   s.op->newline(-1) << "}";
    8283 [ +  - ][ +  - ]:         12 :   s.op->newline(-2) << "}";
    8284 [ +  - ][ +  - ]:         12 :   s.op->newline() << "return (p > 0) ? 0 : -1;";
    8285 [ +  - ][ +  - ]:         12 :   s.op->newline(-1) << "}";
    8286 [ +  - ][ +  - ]:         12 :   s.op->newline() << "#endif";
    8287                 :            : }
    8288                 :            : 
    8289                 :            : 
    8290                 :            : void
    8291                 :         12 : kprobe_derived_probe_group::emit_module_init (systemtap_session& s)
    8292                 :            : {
    8293                 :         12 :   s.op->newline() << "#ifdef STAPCONF_KALLSYMS_ON_EACH_SYMBOL";
    8294                 :         12 :   s.op->newline() << "{";
    8295                 :         12 :   s.op->newline(1) << "int p = 0;";
    8296                 :         12 :   s.op->newline() << "for (i = 0; i < " << probes_by_module.size() << "; i++) {";
    8297                 :         12 :   s.op->newline(1) << "struct stap_dwarfless_probe *sdp = & stap_dwarfless_probes[i];";
    8298                 :         12 :   s.op->newline() << "if (! sdp->address)";
    8299                 :         12 :   s.op->newline(1) << "p++;";
    8300                 :         12 :   s.op->newline(-2) << "}";
    8301                 :         12 :   s.op->newline() << "kallsyms_on_each_symbol(kprobe_resolve, &p);";
    8302                 :         12 :   s.op->newline(-1) << "}";
    8303                 :         12 :   s.op->newline() << "#endif";
    8304                 :            : 
    8305                 :         12 :   s.op->newline() << "for (i=0; i<" << probes_by_module.size() << "; i++) {";
    8306                 :         12 :   s.op->newline(1) << "struct stap_dwarfless_probe *sdp = & stap_dwarfless_probes[i];";
    8307                 :         12 :   s.op->newline() << "struct stap_dwarfless_kprobe *kp = & stap_dwarfless_kprobes[i];";
    8308                 :         12 :   s.op->newline() << "void *addr = (void *) sdp->address;";
    8309                 :         12 :   s.op->newline() << "const char *symbol_name = addr ? NULL : sdp->symbol_string;";
    8310                 :            : 
    8311                 :         12 :   s.op->newline() << "#ifdef STAPCONF_KALLSYMS_ON_EACH_SYMBOL";
    8312                 :         12 :   s.op->newline() << "if (! addr) {";
    8313                 :         12 :   s.op->newline(1) << "sdp->registered_p = 0;";
    8314                 :         12 :   s.op->newline() << "if (!sdp->optional_p)";
    8315                 :         12 :   s.op->newline(1) << "_stp_warn (\"probe %s registration error (symbol not found)\", probe_point);";
    8316                 :         12 :   s.op->newline(-1) << "continue;";
    8317                 :         12 :   s.op->newline(-1) << "}";
    8318                 :         12 :   s.op->newline() << "#endif";
    8319                 :            : 
    8320                 :         12 :   s.op->newline() << "probe_point = sdp->probe->pp;"; // for error messages
    8321                 :         12 :   s.op->newline() << "if (sdp->return_p) {";
    8322                 :         12 :   s.op->newline(1) << "kp->u.krp.kp.addr = addr;";
    8323                 :         12 :   s.op->newline() << "#ifdef STAPCONF_KPROBE_SYMBOL_NAME";
    8324                 :         12 :   s.op->newline() << "kp->u.krp.kp.symbol_name = (char *) symbol_name;";
    8325                 :         12 :   s.op->newline() << "#endif";
    8326                 :         12 :   s.op->newline() << "if (sdp->maxactive_p) {";
    8327                 :         12 :   s.op->newline(1) << "kp->u.krp.maxactive = sdp->maxactive_val;";
    8328                 :         12 :   s.op->newline(-1) << "} else {";
    8329                 :         12 :   s.op->newline(1) << "kp->u.krp.maxactive = KRETACTIVE;";
    8330                 :         12 :   s.op->newline(-1) << "}";
    8331                 :         12 :   s.op->newline() << "kp->u.krp.handler = &enter_kretprobe2_probe;";
    8332                 :            :   // to ensure safeness of bspcache, always use aggr_kprobe on ia64
    8333                 :         12 :   s.op->newline() << "#ifdef __ia64__";
    8334                 :         12 :   s.op->newline() << "kp->dummy.addr = kp->u.krp.kp.addr;";
    8335                 :         12 :   s.op->newline() << "#ifdef STAPCONF_KPROBE_SYMBOL_NAME";
    8336                 :         12 :   s.op->newline() << "kp->dummy.symbol_name = kp->u.krp.kp.symbol_name;";
    8337                 :         12 :   s.op->newline() << "#endif";
    8338                 :         12 :   s.op->newline() << "kp->dummy.pre_handler = NULL;";
    8339                 :         12 :   s.op->newline() << "rc = register_kprobe (& kp->dummy);";
    8340                 :         12 :   s.op->newline() << "if (rc == 0) {";
    8341                 :         12 :   s.op->newline(1) << "rc = register_kretprobe (& kp->u.krp);";
    8342                 :         12 :   s.op->newline() << "if (rc != 0)";
    8343                 :         12 :   s.op->newline(1) << "unregister_kprobe (& kp->dummy);";
    8344                 :         12 :   s.op->newline(-2) << "}";
    8345                 :         12 :   s.op->newline() << "#else";
    8346                 :         12 :   s.op->newline() << "rc = register_kretprobe (& kp->u.krp);";
    8347                 :         12 :   s.op->newline() << "#endif";
    8348                 :         12 :   s.op->newline(-1) << "} else {";
    8349                 :            :   // to ensure safeness of bspcache, always use aggr_kprobe on ia64
    8350                 :         12 :   s.op->newline(1) << "kp->u.kp.addr = addr;";
    8351                 :         12 :   s.op->newline() << "#ifdef STAPCONF_KPROBE_SYMBOL_NAME";
    8352                 :         12 :   s.op->newline() << "kp->u.kp.symbol_name = (char *) symbol_name;";
    8353                 :         12 :   s.op->newline() << "#endif";
    8354                 :         12 :   s.op->newline() << "kp->u.kp.pre_handler = &enter_kprobe2_probe;";
    8355                 :         12 :   s.op->newline() << "#ifdef __ia64__";
    8356                 :         12 :   s.op->newline() << "kp->dummy.pre_handler = NULL;";
    8357                 :         12 :   s.op->newline() << "kp->dummy.addr = kp->u.kp.addr;";
    8358                 :         12 :   s.op->newline() << "#ifdef STAPCONF_KPROBE_SYMBOL_NAME";
    8359                 :         12 :   s.op->newline() << "kp->dummy.symbol_name = kp->u.kp.symbol_name;";
    8360                 :         12 :   s.op->newline() << "#endif";
    8361                 :         12 :   s.op->newline() << "rc = register_kprobe (& kp->dummy);";
    8362                 :         12 :   s.op->newline() << "if (rc == 0) {";
    8363                 :         12 :   s.op->newline(1) << "rc = register_kprobe (& kp->u.kp);";
    8364                 :         12 :   s.op->newline() << "if (rc != 0)";
    8365                 :         12 :   s.op->newline(1) << "unregister_kprobe (& kp->dummy);";
    8366                 :         12 :   s.op->newline(-2) << "}";
    8367                 :         12 :   s.op->newline() << "#else";
    8368                 :         12 :   s.op->newline() << "rc = register_kprobe (& kp->u.kp);";
    8369                 :         12 :   s.op->newline() << "#endif";
    8370                 :         12 :   s.op->newline(-1) << "}";
    8371                 :         12 :   s.op->newline() << "if (rc) {"; // PR6749: tolerate a failed register_*probe.
    8372                 :         12 :   s.op->newline(1) << "sdp->registered_p = 0;";
    8373                 :         12 :   s.op->newline() << "if (!sdp->optional_p)";
    8374                 :         12 :   s.op->newline(1) << "_stp_warn (\"probe %s (address 0x%lx) registration error (rc %d)\", probe_point, (unsigned long) addr, rc);";
    8375                 :         12 :   s.op->newline(-1) << "rc = 0;"; // continue with other probes
    8376                 :            :   // XXX: shall we increment numskipped?
    8377                 :         12 :   s.op->newline(-1) << "}";
    8378                 :            : 
    8379                 :         12 :   s.op->newline() << "else sdp->registered_p = 1;";
    8380                 :         12 :   s.op->newline(-1) << "}"; // for loop
    8381                 :         12 : }
    8382                 :            : 
    8383                 :            : 
    8384                 :            : void
    8385                 :         16 : kprobe_derived_probe_group::emit_module_exit (systemtap_session& s)
    8386                 :            : {
    8387                 :            :   //Unregister kprobes by batch interfaces.
    8388                 :         16 :   s.op->newline() << "#if defined(STAPCONF_UNREGISTER_KPROBES)";
    8389                 :         16 :   s.op->newline() << "j = 0;";
    8390                 :         16 :   s.op->newline() << "for (i=0; i<" << probes_by_module.size() << "; i++) {";
    8391                 :         16 :   s.op->newline(1) << "struct stap_dwarfless_probe *sdp = & stap_dwarfless_probes[i];";
    8392                 :         16 :   s.op->newline() << "struct stap_dwarfless_kprobe *kp = & stap_dwarfless_kprobes[i];";
    8393                 :         16 :   s.op->newline() << "if (! sdp->registered_p) continue;";
    8394                 :         16 :   s.op->newline() << "if (!sdp->return_p)";
    8395                 :         16 :   s.op->newline(1) << "stap_unreg_kprobes2[j++] = &kp->u.kp;";
    8396                 :         16 :   s.op->newline(-2) << "}";
    8397                 :         16 :   s.op->newline() << "unregister_kprobes((struct kprobe **)stap_unreg_kprobes2, j);";
    8398                 :         16 :   s.op->newline() << "j = 0;";
    8399                 :         16 :   s.op->newline() << "for (i=0; i<" << probes_by_module.size() << "; i++) {";
    8400                 :         16 :   s.op->newline(1) << "struct stap_dwarfless_probe *sdp = & stap_dwarfless_probes[i];";
    8401                 :         16 :   s.op->newline() << "struct stap_dwarfless_kprobe *kp = & stap_dwarfless_kprobes[i];";
    8402                 :         16 :   s.op->newline() << "if (! sdp->registered_p) continue;";
    8403                 :         16 :   s.op->newline() << "if (sdp->return_p)";
    8404                 :         16 :   s.op->newline(1) << "stap_unreg_kprobes2[j++] = &kp->u.krp;";
    8405                 :         16 :   s.op->newline(-2) << "}";
    8406                 :         16 :   s.op->newline() << "unregister_kretprobes((struct kretprobe **)stap_unreg_kprobes2, j);";
    8407                 :         16 :   s.op->newline() << "#ifdef __ia64__";
    8408                 :         16 :   s.op->newline() << "j = 0;";
    8409                 :         16 :   s.op->newline() << "for (i=0; i<" << probes_by_module.size() << "; i++) {";
    8410                 :         16 :   s.op->newline(1) << "struct stap_dwarfless_probe *sdp = & stap_dwarfless_probes[i];";
    8411                 :         16 :   s.op->newline() << "struct stap_dwarfless_kprobe *kp = & stap_dwarfless_kprobes[i];";
    8412                 :         16 :   s.op->newline() << "if (! sdp->registered_p) continue;";
    8413                 :         16 :   s.op->newline() << "stap_unreg_kprobes2[j++] = &kp->dummy;";
    8414                 :         16 :   s.op->newline(-1) << "}";
    8415                 :         16 :   s.op->newline() << "unregister_kprobes((struct kprobe **)stap_unreg_kprobes2, j);";
    8416                 :         16 :   s.op->newline() << "#endif";
    8417                 :         16 :   s.op->newline() << "#endif";
    8418                 :            : 
    8419                 :         16 :   s.op->newline() << "for (i=0; i<" << probes_by_module.size() << "; i++) {";
    8420                 :         16 :   s.op->newline(1) << "struct stap_dwarfless_probe *sdp = & stap_dwarfless_probes[i];";
    8421                 :         16 :   s.op->newline() << "struct stap_dwarfless_kprobe *kp = & stap_dwarfless_kprobes[i];";
    8422                 :         16 :   s.op->newline() << "if (! sdp->registered_p) continue;";
    8423                 :         16 :   s.op->newline() << "if (sdp->return_p) {";
    8424                 :         16 :   s.op->newline() << "#if !defined(STAPCONF_UNREGISTER_KPROBES)";
    8425                 :         16 :   s.op->newline(1) << "unregister_kretprobe (&kp->u.krp);";
    8426                 :         16 :   s.op->newline() << "#endif";
    8427                 :         16 :   s.op->newline() << "atomic_add (kp->u.krp.nmissed, skipped_count());";
    8428                 :         16 :   s.op->newline() << "#ifdef STP_TIMING";
    8429                 :         16 :   s.op->newline() << "if (kp->u.krp.nmissed)";
    8430                 :         16 :   s.op->newline(1) << "_stp_warn (\"Skipped due to missed kretprobe/1 on '%s': %d\\n\", sdp->probe->pp, kp->u.krp.nmissed);";
    8431                 :         16 :   s.op->newline(-1) << "#endif";
    8432                 :         16 :   s.op->newline() << "atomic_add (kp->u.krp.kp.nmissed, skipped_count());";
    8433                 :         16 :   s.op->newline() << "#ifdef STP_TIMING";
    8434                 :         16 :   s.op->newline() << "if (kp->u.krp.kp.nmissed)";
    8435                 :         16 :   s.op->newline(1) << "_stp_warn (\"Skipped due to missed kretprobe/2 on '%s': %lu\\n\", sdp->probe->pp, kp->u.krp.kp.nmissed);";
    8436                 :         16 :   s.op->newline(-1) << "#endif";
    8437                 :         16 :   s.op->newline(-1) << "} else {";
    8438                 :         16 :   s.op->newline() << "#if !defined(STAPCONF_UNREGISTER_KPROBES)";
    8439                 :         16 :   s.op->newline(1) << "unregister_kprobe (&kp->u.kp);";
    8440                 :         16 :   s.op->newline() << "#endif";
    8441                 :         16 :   s.op->newline() << "atomic_add (kp->u.kp.nmissed, skipped_count());";
    8442                 :         16 :   s.op->newline() << "#ifdef STP_TIMING";
    8443                 :         16 :   s.op->newline() << "if (kp->u.kp.nmissed)";
    8444                 :         16 :   s.op->newline(1) << "_stp_warn (\"Skipped due to missed kprobe on '%s': %lu\\n\", sdp->probe->pp, kp->u.kp.nmissed);";
    8445                 :         16 :   s.op->newline(-1) << "#endif";
    8446                 :         16 :   s.op->newline(-1) << "}";
    8447                 :         16 :   s.op->newline() << "#if !defined(STAPCONF_UNREGISTER_KPROBES) && defined(__ia64__)";
    8448                 :         16 :   s.op->newline() << "unregister_kprobe (&kp->dummy);";
    8449                 :         16 :   s.op->newline() << "#endif";
    8450                 :         16 :   s.op->newline() << "sdp->registered_p = 0;";
    8451                 :         16 :   s.op->newline(-1) << "}";
    8452                 :         16 : }
    8453                 :            : 
    8454         [ #  # ]:          0 : struct kprobe_builder: public derived_probe_builder
    8455                 :            : {
    8456                 :            : public:
    8457                 :      10962 :   kprobe_builder() {}
    8458                 :            : 
    8459                 :      10962 :   void build_no_more (systemtap_session &s) {}
    8460                 :            : 
    8461                 :            :   virtual void build(systemtap_session & sess,
    8462                 :            :                      probe * base,
    8463                 :            :                      probe_point * location,
    8464                 :            :                      literal_map_t const & parameters,
    8465                 :            :                      vector<derived_probe *> & finished_results);
    8466                 :            : };
    8467                 :            : 
    8468                 :            : 
    8469                 :            : void
    8470                 :      31417 : kprobe_builder::build(systemtap_session & sess,
    8471                 :            :                       probe * base,
    8472                 :            :                       probe_point * location,
    8473                 :            :                       literal_map_t const & parameters,
    8474                 :            :                       vector<derived_probe *> & finished_results)
    8475                 :            : {
    8476 [ +  - ][ +  - ]:      31417 :   string function_string_val, module_string_val;
    8477 [ +  - ][ +  - ]:      31417 :   string path, library, path_tgt, library_tgt;
         [ +  - ][ +  - ]
    8478                 :      31417 :   int64_t statement_num_val = 0, maxactive_val = 0;
    8479                 :            :   bool has_function_str, has_module_str, has_statement_num;
    8480                 :            :   bool has_absolute, has_return, has_maxactive;
    8481                 :            :   bool has_path, has_library;
    8482                 :            : 
    8483         [ +  - ]:      31417 :   has_function_str = get_param(parameters, TOK_FUNCTION, function_string_val);
    8484         [ +  - ]:      31417 :   has_module_str = get_param(parameters, TOK_MODULE, module_string_val);
    8485         [ +  - ]:      31417 :   has_return = has_null_param (parameters, TOK_RETURN);
    8486         [ +  - ]:      31417 :   has_maxactive = get_param(parameters, TOK_MAXACTIVE, maxactive_val);
    8487         [ +  - ]:      31417 :   has_statement_num = get_param(parameters, TOK_STATEMENT, statement_num_val);
    8488         [ +  - ]:      31417 :   has_absolute = has_null_param (parameters, TOK_ABSOLUTE);
    8489         [ +  - ]:      31417 :   has_path = get_param (parameters, TOK_PROCESS, path);
    8490         [ +  - ]:      31417 :   has_library = get_param (parameters, TOK_LIBRARY, library);
    8491                 :            : 
    8492         [ -  + ]:      31417 :   if (has_path)
    8493                 :            :     {
    8494 [ #  # ][ #  # ]:          0 :       path = find_executable (path, sess.sysroot, sess.sysenv);
         [ #  # ][ #  # ]
                 [ #  # ]
    8495 [ #  # ][ #  # ]:          0 :       path_tgt = path_remove_sysroot(sess, path);
                 [ #  # ]
    8496                 :            :     }
    8497         [ -  + ]:      31417 :   if (has_library)
    8498                 :            :     {
    8499                 :            :       library = find_executable (library, sess.sysroot, sess.sysenv,
    8500 [ #  # ][ #  # ]:          0 :                                  "LD_LIBRARY_PATH");
         [ #  # ][ #  # ]
                 [ #  # ]
    8501 [ #  # ][ #  # ]:          0 :       library_tgt = path_remove_sysroot(sess, library);
                 [ #  # ]
    8502                 :            :     }
    8503                 :            : 
    8504         [ +  + ]:      31417 :   if (has_function_str)
    8505                 :            :     {
    8506         [ -  + ]:      31415 :       if (has_module_str)
    8507                 :            :         {
    8508 [ #  # ][ #  # ]:          0 :           function_string_val = module_string_val + ":" + function_string_val;
         [ #  # ][ #  # ]
                 [ #  # ]
    8509                 :            :           derived_probe *dp
    8510                 :            :             = new kprobe_derived_probe (sess, finished_results, base,
    8511                 :            :                                         location, function_string_val,
    8512                 :            :                                         0, has_return, has_statement_num,
    8513                 :            :                                         has_maxactive, has_path, has_library,
    8514 [ #  # ][ #  # ]:          0 :                                         maxactive_val, path_tgt, library_tgt);
    8515         [ #  # ]:          0 :           finished_results.push_back (dp);
    8516                 :            :         }
    8517                 :            :       else
    8518                 :            :         {
    8519         [ +  - ]:      31415 :           vector<string> matches;
    8520                 :            : 
    8521                 :            :           // Simple names can be found directly
    8522 [ +  - ][ +  - ]:      31415 :           if (function_string_val.find_first_of("*?[") == string::npos)
    8523                 :            :             {
    8524 [ +  - ][ +  + ]:      31415 :               if (sess.kernel_functions.count(function_string_val))
    8525         [ +  - ]:      21043 :                 matches.push_back(function_string_val);
    8526                 :            :             }
    8527                 :            :           else // Search function name list for matching names
    8528                 :            :             {
    8529 [ #  # ][ #  # ]:          0 :               for (set<string>::const_iterator it = sess.kernel_functions.begin();
    8530         [ #  # ]:          0 :                    it != sess.kernel_functions.end(); it++)
    8531                 :            :                 // fnmatch returns zero for matching.
    8532 [ #  # ][ #  # ]:          0 :                 if (fnmatch(function_string_val.c_str(), it->c_str(), 0) == 0)
         [ #  # ][ #  # ]
                 [ #  # ]
    8533         [ #  # ]:          0 :                   matches.push_back(*it);
    8534                 :            :             }
    8535                 :            : 
    8536 [ +  - ][ +  - ]:     104916 :           for (vector<string>::const_iterator it = matches.begin();
         [ +  - ][ +  - ]
                 [ +  + ]
    8537         [ +  - ]:      52458 :                it != matches.end(); it++)
    8538                 :            :             {
    8539                 :            :               derived_probe *dp
    8540                 :            :                 = new kprobe_derived_probe (sess, finished_results, base,
    8541                 :            :                                             location, *it, 0, has_return,
    8542                 :            :                                             has_statement_num,
    8543                 :            :                                             has_maxactive, has_path,
    8544                 :            :                                             has_library, maxactive_val,
    8545 [ +  - ][ +  - ]:      21043 :                                             path_tgt, library_tgt);
    8546         [ +  - ]:      21043 :               finished_results.push_back (dp);
    8547         [ +  - ]:      31415 :             }
    8548                 :            :         }
    8549                 :            :     }
    8550                 :            :   else
    8551                 :            :     {
    8552                 :            :       // assert guru mode for absolute probes
    8553 [ +  - ][ +  - ]:          2 :       if ( has_statement_num && has_absolute && !base->privileged )
                 [ -  + ]
    8554 [ #  # ][ #  # ]:          0 :         throw semantic_error (_("absolute statement probe in unprivileged script; need stap -g"), base->tok);
    8555                 :            : 
    8556                 :            :       finished_results.push_back (new kprobe_derived_probe (sess,
    8557                 :            :                                                             finished_results,
    8558                 :            :                                                             base,
    8559                 :            :                                                             location, "",
    8560                 :            :                                                             statement_num_val,
    8561                 :            :                                                             has_return,
    8562                 :            :                                                             has_statement_num,
    8563                 :            :                                                             has_maxactive,
    8564                 :            :                                                             has_path,
    8565                 :            :                                                             has_library,
    8566                 :            :                                                             maxactive_val,
    8567                 :            :                                                             path_tgt,
    8568 [ +  - ][ +  - ]:          2 :                                                             library_tgt));
         [ +  - ][ +  - ]
                 [ +  - ]
    8569 [ +  - ][ +  - ]:      31417 :     }
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
    8570                 :      31417 : }
    8571                 :            : 
    8572                 :            : 
    8573                 :            : void
    8574                 :        399 : kprobe_var_expanding_visitor::visit_entry_op (entry_op *e)
    8575                 :            : {
    8576                 :        399 :   expression *repl = e;
    8577                 :            : 
    8578         [ +  + ]:        399 :   if (has_return)
    8579                 :            :     {
    8580                 :            :       // expand the operand as if it weren't a return probe
    8581                 :        398 :       has_return = false;
    8582                 :        398 :       replace (e->operand);
    8583                 :        398 :       has_return = true;
    8584                 :            : 
    8585                 :            :       // XXX it would be nice to use gen_kretprobe_saved_return when
    8586                 :            :       // available, but it requires knowing the types already, which is
    8587                 :            :       // problematic for arbitrary expressons.
    8588                 :            :       repl = gen_mapped_saved_return (sess, e->operand, "entry",
    8589                 :            :                                       add_block, add_block_tid,
    8590 [ +  - ][ +  - ]:        398 :                                       add_call_probe, add_call_probe_tid);
                 [ +  - ]
    8591                 :            :     }
    8592                 :        399 :   provide (repl);
    8593                 :        399 : }
    8594                 :            : 
    8595                 :            : 
    8596                 :            : // ------------------------------------------------------------------------
    8597                 :            : //  Hardware breakpoint based probes.
    8598                 :            : // ------------------------------------------------------------------------
    8599                 :            : 
    8600         [ +  - ]:       2414 : static const string TOK_HWBKPT("data");
    8601         [ +  - ]:       2414 : static const string TOK_HWBKPT_WRITE("write");
    8602         [ +  - ]:       2414 : static const string TOK_HWBKPT_RW("rw");
    8603         [ +  - ]:       2414 : static const string TOK_LENGTH("length");
    8604                 :            : 
    8605                 :            : #define HWBKPT_READ 0
    8606                 :            : #define HWBKPT_WRITE 1
    8607                 :            : #define HWBKPT_RW 2
    8608 [ #  # ][ #  # ]:          0 : struct hwbkpt_derived_probe: public derived_probe
    8609                 :            : {
    8610                 :            :   hwbkpt_derived_probe (probe *base,
    8611                 :            :                         probe_point *location,
    8612                 :            :                         uint64_t addr,
    8613                 :            :                         string symname,
    8614                 :            :                         unsigned int len,
    8615                 :            :                         bool has_only_read_access,
    8616                 :            :                         bool has_only_write_access,
    8617                 :            :                         bool has_rw_access
    8618                 :            :                         );
    8619                 :            :   Dwarf_Addr hwbkpt_addr;
    8620                 :            :   string symbol_name;
    8621                 :            :   unsigned int hwbkpt_access,hwbkpt_len;
    8622                 :            : 
    8623                 :            :   void printsig (std::ostream &o) const;
    8624                 :            :   void join_group (systemtap_session& s);
    8625                 :            : };
    8626                 :            : 
    8627 [ #  # ][ #  # ]:          3 : struct hwbkpt_derived_probe_group: public derived_probe_group
                 [ +  - ]
    8628                 :            : {
    8629                 :            : private:
    8630                 :            :   vector<hwbkpt_derived_probe*> hwbkpt_probes;
    8631                 :            : 
    8632                 :            : public:
    8633                 :            :   void enroll (hwbkpt_derived_probe* probe, systemtap_session& s);
    8634                 :            :   void emit_module_decls (systemtap_session& s);
    8635                 :            :   void emit_module_init (systemtap_session& s);
    8636                 :            :   void emit_module_exit (systemtap_session& s);
    8637                 :            : };
    8638                 :            : 
    8639                 :          4 : hwbkpt_derived_probe::hwbkpt_derived_probe (probe *base,
    8640                 :            :                                             probe_point *location,
    8641                 :            :                                             uint64_t addr,
    8642                 :            :                                             string symname,
    8643                 :            :                                             unsigned int len,
    8644                 :            :                                             bool has_only_read_access,
    8645                 :            :                                             bool has_only_write_access,
    8646                 :            :                                             bool):
    8647                 :            :   derived_probe (base, location, true /* .components soon rewritten */ ),
    8648                 :            :   hwbkpt_addr (addr),
    8649                 :            :   symbol_name (symname),
    8650         [ +  - ]:          4 :   hwbkpt_len (len)
    8651                 :            : {
    8652                 :          4 :   this->tok = base->tok;
    8653                 :            : 
    8654         [ +  - ]:          4 :   vector<probe_point::component*> comps;
    8655 [ +  - ][ +  - ]:          4 :   comps.push_back (new probe_point::component(TOK_KERNEL));
                 [ +  - ]
    8656                 :            : 
    8657         [ -  + ]:          4 :   if (hwbkpt_addr)
    8658                 :            :     comps.push_back (new probe_point::component (TOK_HWBKPT,
    8659 [ #  # ][ #  # ]:          0 :                                                  new literal_number(hwbkpt_addr, true)));
         [ #  # ][ #  # ]
                 [ #  # ]
    8660 [ +  - ][ +  - ]:          4 :   else if (symbol_name.size())
    8661 [ +  - ][ +  - ]:          4 :     comps.push_back (new probe_point::component (TOK_HWBKPT, new literal_string(symbol_name)));
         [ +  - ][ +  - ]
                 [ +  - ]
    8662                 :            : 
    8663 [ +  - ][ +  - ]:          4 :   comps.push_back (new probe_point::component (TOK_LENGTH, new literal_number(hwbkpt_len)));
         [ +  - ][ +  - ]
                 [ +  - ]
    8664                 :            : 
    8665         [ -  + ]:          4 :   if (has_only_read_access)
    8666                 :          0 :     this->hwbkpt_access = HWBKPT_READ ;
    8667                 :            : //TODO add code for comps.push_back for read, since this flag is not for x86
    8668                 :            : 
    8669                 :            :   else
    8670                 :            :     {
    8671         [ +  + ]:          4 :       if (has_only_write_access)
    8672                 :            :         {
    8673                 :          1 :           this->hwbkpt_access = HWBKPT_WRITE ;
    8674 [ +  - ][ +  - ]:          1 :           comps.push_back (new probe_point::component(TOK_HWBKPT_WRITE));
                 [ +  - ]
    8675                 :            :         }
    8676                 :            :       else
    8677                 :            :         {
    8678                 :          3 :           this->hwbkpt_access = HWBKPT_RW ;
    8679 [ +  - ][ +  - ]:          3 :           comps.push_back (new probe_point::component(TOK_HWBKPT_RW));
                 [ +  - ]
    8680                 :            :         }
    8681                 :            :     }
    8682                 :            : 
    8683 [ +  - ][ +  - ]:          4 :   this->sole_location()->components = comps;
                 [ +  - ]
    8684                 :          4 : }
    8685                 :            : 
    8686                 :          4 : void hwbkpt_derived_probe::printsig (ostream& o) const
    8687                 :            : {
    8688                 :          4 :   sole_location()->print (o);
    8689                 :          4 :   printsig_nested (o);
    8690                 :          4 : }
    8691                 :            : 
    8692                 :          4 : void hwbkpt_derived_probe::join_group (systemtap_session& s)
    8693                 :            : {
    8694         [ +  + ]:          4 :   if (! s.hwbkpt_derived_probes)
    8695         [ +  - ]:          3 :     s.hwbkpt_derived_probes = new hwbkpt_derived_probe_group ();
    8696                 :          4 :   s.hwbkpt_derived_probes->enroll (this, s);
    8697                 :          4 : }
    8698                 :            : 
    8699                 :          4 : void hwbkpt_derived_probe_group::enroll (hwbkpt_derived_probe* p, systemtap_session& s)
    8700                 :            : {
    8701                 :          4 :   hwbkpt_probes.push_back (p);
    8702                 :            : 
    8703                 :          4 :   unsigned max_hwbkpt_probes_by_arch = 0;
    8704 [ +  - ][ -  + ]:          4 :   if (s.architecture == "i386" || s.architecture == "x86_64")
                 [ -  + ]
    8705                 :          0 :     max_hwbkpt_probes_by_arch = 4;
    8706         [ -  + ]:          4 :   else if (s.architecture == "s390")
    8707                 :          0 :     max_hwbkpt_probes_by_arch = 1;
    8708                 :            : 
    8709         [ +  - ]:          4 :   if (hwbkpt_probes.size() >= max_hwbkpt_probes_by_arch)
    8710                 :          4 :     s.print_warning (_F("Too many hardware breakpoint probes requested for %s (%zu vs. %u)",
    8711         [ +  - ]:          4 :                           s.architecture.c_str(), hwbkpt_probes.size(), max_hwbkpt_probes_by_arch));
    8712                 :          4 : }
    8713                 :            : 
    8714                 :            : void
    8715                 :          2 : hwbkpt_derived_probe_group::emit_module_decls (systemtap_session& s)
    8716                 :            : {
    8717         [ -  + ]:          4 :   if (hwbkpt_probes.empty()) return;
    8718                 :            : 
    8719                 :          2 :   s.op->newline() << "/* ---- hwbkpt-based probes ---- */";
    8720                 :            : 
    8721                 :          2 :   s.op->newline() << "#include <linux/perf_event.h>";
    8722                 :          2 :   s.op->newline() << "#include <linux/hw_breakpoint.h>";
    8723                 :          2 :   s.op->newline();
    8724                 :            : 
    8725                 :            :   // Forward declare the master entry functions
    8726                 :          2 :   s.op->newline() << "static int enter_hwbkpt_probe (struct perf_event *bp,";
    8727                 :          2 :   s.op->line() << " int nmi,";
    8728                 :          2 :   s.op->line() << " struct perf_sample_data *data,";
    8729                 :          2 :   s.op->line() << " struct pt_regs *regs);";
    8730                 :            : 
    8731                 :            :   // Emit the actual probe list.
    8732                 :            : 
    8733                 :          2 :   s.op->newline() << "static struct perf_event_attr ";
    8734                 :          2 :   s.op->newline() << "stap_hwbkpt_probe_array[" << hwbkpt_probes.size() << "];";
    8735                 :            : 
    8736                 :          2 :   s.op->newline() << "static struct perf_event **";
    8737                 :          2 :   s.op->newline() << "stap_hwbkpt_ret_array[" << hwbkpt_probes.size() << "];";
    8738                 :          2 :   s.op->newline() << "static struct stap_hwbkpt_probe {";
    8739                 :          2 :   s.op->newline() << "int registered_p:1;";
    8740                 :            : // registered_p =  0 signifies a probe that is unregistered (or failed)
    8741                 :            : // registered_p =  1 signifies a probe that got registered successfully
    8742                 :            : 
    8743                 :            :   // Symbol Names are mostly small and uniform enough
    8744                 :            :   // to justify putting const char*.
    8745                 :          2 :   s.op->newline() << "const char * const symbol;";
    8746                 :            : 
    8747                 :          2 :   s.op->newline() << "const unsigned long address;";
    8748                 :          2 :   s.op->newline() << "uint8_t atype;";
    8749                 :          2 :   s.op->newline() << "unsigned int len;";
    8750                 :          2 :   s.op->newline() << "const struct stap_probe * const probe;";
    8751                 :          2 :   s.op->newline() << "} stap_hwbkpt_probes[] = {";
    8752                 :          2 :   s.op->indent(1);
    8753                 :            : 
    8754         [ +  + ]:          5 :   for (unsigned int it = 0; it < hwbkpt_probes.size(); it++)
    8755                 :            :     {
    8756                 :          3 :       hwbkpt_derived_probe* p = hwbkpt_probes.at(it);
    8757                 :          3 :       s.op->newline() << "{";
    8758         [ +  - ]:          3 :       if (p->symbol_name.size())
    8759                 :          3 :       s.op->line() << " .address=(unsigned long)0x0" << "ULL,";
    8760                 :            :       else
    8761                 :          0 :       s.op->line() << " .address=(unsigned long)0x" << hex << p->hwbkpt_addr << dec << "ULL,";
    8762   [ -  +  +  - ]:          3 :       switch(p->hwbkpt_access){
    8763                 :            :       case HWBKPT_READ:
    8764                 :          0 :                 s.op->line() << " .atype=HW_BREAKPOINT_R ,";
    8765                 :          0 :                 break;
    8766                 :            :       case HWBKPT_WRITE:
    8767                 :          1 :                 s.op->line() << " .atype=HW_BREAKPOINT_W ,";
    8768                 :          1 :                 break;
    8769                 :            :       case HWBKPT_RW:
    8770                 :          2 :                 s.op->line() << " .atype=HW_BREAKPOINT_R|HW_BREAKPOINT_W ,";
    8771                 :          2 :                 break;
    8772                 :            :         };
    8773                 :          3 :       s.op->line() << " .len=" << p->hwbkpt_len << ",";
    8774 [ +  - ][ +  - ]:          3 :       s.op->line() << " .probe=" << common_probe_init (p) << ",";
    8775                 :          3 :       s.op->line() << " .symbol=\"" << p->symbol_name << "\",";
    8776                 :          3 :       s.op->line() << " },";
    8777                 :            :     }
    8778                 :          2 :   s.op->newline(-1) << "};";
    8779                 :            : 
    8780                 :            :   // Emit the hwbkpt callback function
    8781                 :          2 :   s.op->newline() ;
    8782                 :          2 :   s.op->newline() << "static int enter_hwbkpt_probe (struct perf_event *bp,";
    8783                 :          2 :   s.op->line() << " int nmi,";
    8784                 :          2 :   s.op->line() << " struct perf_sample_data *data,";
    8785                 :          2 :   s.op->line() << " struct pt_regs *regs) {";
    8786                 :          2 :   s.op->newline(1) << "unsigned int i;";
    8787                 :          2 :   s.op->newline() << "if (bp->attr.type != PERF_TYPE_BREAKPOINT) return -1;";
    8788                 :          2 :   s.op->newline() << "for (i=0; i<" << hwbkpt_probes.size() << "; i++) {";
    8789                 :          2 :   s.op->newline(1) << "struct perf_event_attr *hp = & stap_hwbkpt_probe_array[i];";
    8790                 :            :   // XXX: why not match stap_hwbkpt_ret_array[i] against bp instead?
    8791                 :          2 :   s.op->newline() << "if (bp->attr.bp_addr==hp->bp_addr && bp->attr.bp_type==hp->bp_type && bp->attr.bp_len==hp->bp_len) {";
    8792                 :          2 :   s.op->newline(1) << "struct stap_hwbkpt_probe *sdp = &stap_hwbkpt_probes[i];";
    8793                 :            :   common_probe_entryfn_prologue (s, "STAP_SESSION_RUNNING", "sdp->probe",
    8794 [ +  - ][ +  - ]:          2 :                                  "stp_probe_type_hwbkpt");
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    8795                 :          2 :   s.op->newline() << "if (user_mode(regs)) {";
    8796                 :          2 :   s.op->newline(1)<< "c->user_mode_p = 1;";
    8797                 :          2 :   s.op->newline() << "c->uregs = regs;";
    8798                 :          2 :   s.op->newline(-1) << "} else {";
    8799                 :          2 :   s.op->newline(1) << "c->kregs = regs;";
    8800                 :          2 :   s.op->newline(-1) << "}";
    8801                 :          2 :   s.op->newline() << "(*sdp->probe->ph) (c);";
    8802                 :          2 :   common_probe_entryfn_epilogue (s, true);
    8803                 :          2 :   s.op->newline(-1) << "}";
    8804                 :          2 :   s.op->newline(-1) << "}";
    8805                 :          2 :   s.op->newline() << "return 0;";
    8806                 :          2 :   s.op->newline(-1) << "}";
    8807                 :            : }
    8808                 :            : 
    8809                 :            : void
    8810                 :          2 : hwbkpt_derived_probe_group::emit_module_init (systemtap_session& s)
    8811                 :            : {
    8812                 :          2 :   s.op->newline() << "for (i=0; i<" << hwbkpt_probes.size() << "; i++) {";
    8813                 :          2 :   s.op->newline(1) << "struct stap_hwbkpt_probe *sdp = & stap_hwbkpt_probes[i];";
    8814                 :          2 :   s.op->newline() << "struct perf_event_attr *hp = & stap_hwbkpt_probe_array[i];";
    8815                 :          2 :   s.op->newline() << "void *addr = (void *) sdp->address;";
    8816                 :          2 :   s.op->newline() << "const char *hwbkpt_symbol_name = addr ? NULL : sdp->symbol;";
    8817                 :          2 :   s.op->newline() << "hw_breakpoint_init(hp);";
    8818                 :          2 :   s.op->newline() << "if (addr)";
    8819                 :          2 :   s.op->newline(1) << "hp->bp_addr = (unsigned long) addr;";
    8820                 :          2 :   s.op->newline(-1) << "else { ";
    8821                 :          2 :   s.op->newline(1) << "hp->bp_addr = kallsyms_lookup_name(hwbkpt_symbol_name);";
    8822                 :          2 :   s.op->newline() << "if (!hp->bp_addr) { ";
    8823                 :          2 :   s.op->newline(1) << "_stp_warn(\"Probe %s registration skipped: invalid symbol %s \",sdp->probe->pp,hwbkpt_symbol_name);";
    8824                 :          2 :   s.op->newline() << "continue;";
    8825                 :          2 :   s.op->newline(-1) << "}";
    8826                 :          2 :   s.op->newline(-1) << "}";
    8827                 :          2 :   s.op->newline() << "hp->bp_type = sdp->atype;";
    8828                 :            : 
    8829                 :            :   // On x86 & x86-64, hp->bp_len is not just a number but a macro/enum (!?!).
    8830 [ +  - ][ -  + ]:          2 :   if (s.architecture == "i386" || s.architecture == "x86_64" )
                 [ -  + ]
    8831                 :            :     {
    8832                 :          0 :       s.op->newline() << "switch(sdp->len) {";
    8833                 :          0 :       s.op->newline() << "case 1:";
    8834                 :          0 :       s.op->newline(1) << "hp->bp_len = HW_BREAKPOINT_LEN_1;";
    8835                 :          0 :       s.op->newline() << "break;";
    8836                 :          0 :       s.op->newline(-1) << "case 2:";
    8837                 :          0 :       s.op->newline(1) << "hp->bp_len = HW_BREAKPOINT_LEN_2;";
    8838                 :          0 :       s.op->newline() << "break;";
    8839                 :          0 :       s.op->newline(-1) << "case 3:";
    8840                 :          0 :       s.op->newline() << "case 4:";
    8841                 :          0 :       s.op->newline(1) << "hp->bp_len = HW_BREAKPOINT_LEN_4;";
    8842                 :          0 :       s.op->newline() << "break;";
    8843                 :          0 :       s.op->newline(-1) << "case 5:";
    8844                 :          0 :       s.op->newline() << "case 6:";
    8845                 :          0 :       s.op->newline() << "case 7:";
    8846                 :          0 :       s.op->newline() << "case 8:";
    8847                 :          0 :       s.op->newline() << "default:"; // XXX: could instead reject
    8848                 :          0 :       s.op->newline(1) << "hp->bp_len = HW_BREAKPOINT_LEN_8;";
    8849                 :          0 :       s.op->newline() << "break;";
    8850                 :          0 :       s.op->newline(-1) << "}";
    8851                 :            :     }
    8852                 :            :   else // other architectures presumed straightforward
    8853                 :          2 :     s.op->newline() << "hp->bp_len = sdp->len;";
    8854                 :            : 
    8855                 :          2 :   s.op->newline() << "probe_point = sdp->probe->pp;"; // for error messages
    8856                 :          2 :   s.op->newline() << "#ifdef STAPCONF_HW_BREAKPOINT_CONTEXT";
    8857                 :          2 :   s.op->newline() << "stap_hwbkpt_ret_array[i] = register_wide_hw_breakpoint(hp, (void *)&enter_hwbkpt_probe, NULL);";
    8858                 :          2 :   s.op->newline() << "#else";
    8859                 :          2 :   s.op->newline() << "stap_hwbkpt_ret_array[i] = register_wide_hw_breakpoint(hp, (void *)&enter_hwbkpt_probe);";
    8860                 :          2 :   s.op->newline() << "#endif";
    8861                 :          2 :   s.op->newline() << "rc = 0;";
    8862                 :          2 :   s.op->newline() << "if (IS_ERR(stap_hwbkpt_ret_array[i])) {";
    8863                 :          2 :   s.op->newline(1) << "rc = PTR_ERR(stap_hwbkpt_ret_array[i]);";
    8864                 :          2 :   s.op->newline() << "stap_hwbkpt_ret_array[i] = 0;";
    8865                 :          2 :   s.op->newline(-1) << "}";
    8866                 :          2 :   s.op->newline() << "if (rc) {";
    8867                 :          2 :   s.op->newline(1) << "_stp_warn(\"Hwbkpt probe %s: registration error %d, addr %p, name %s\", probe_point, rc, addr, hwbkpt_symbol_name);";
    8868                 :          2 :   s.op->newline() << "sdp->registered_p = 0;";
    8869                 :          2 :   s.op->newline(-1) << "}";
    8870                 :          2 :   s.op->newline() << " else sdp->registered_p = 1;";
    8871                 :          2 :   s.op->newline(-1) << "}"; // for loop
    8872                 :          2 : }
    8873                 :            : 
    8874                 :            : void
    8875                 :          2 : hwbkpt_derived_probe_group::emit_module_exit (systemtap_session& s)
    8876                 :            : {
    8877                 :            :   //Unregister hwbkpt probes.
    8878                 :          2 :   s.op->newline() << "for (i=0; i<" << hwbkpt_probes.size() << "; i++) {";
    8879                 :          2 :   s.op->newline(1) << "struct stap_hwbkpt_probe *sdp = & stap_hwbkpt_probes[i];";
    8880                 :          2 :   s.op->newline() << "if (sdp->registered_p == 0) continue;";
    8881                 :          2 :   s.op->newline() << "unregister_wide_hw_breakpoint(stap_hwbkpt_ret_array[i]);";
    8882                 :          2 :   s.op->newline() << "sdp->registered_p = 0;";
    8883                 :          2 :   s.op->newline(-1) << "}";
    8884                 :          2 : }
    8885                 :            : 
    8886         [ #  # ]:          0 : struct hwbkpt_builder: public derived_probe_builder
    8887                 :            : {
    8888                 :       7308 :   hwbkpt_builder() {}
    8889                 :            :   virtual void build(systemtap_session & sess,
    8890                 :            :                      probe * base,
    8891                 :            :                      probe_point * location,
    8892                 :            :                      literal_map_t const & parameters,
    8893                 :            :                      vector<derived_probe *> & finished_results);
    8894                 :            : };
    8895                 :            : 
    8896                 :            : void
    8897                 :          4 : hwbkpt_builder::build(systemtap_session & sess,
    8898                 :            :                       probe * base,
    8899                 :            :                       probe_point * location,
    8900                 :            :                       literal_map_t const & parameters,
    8901                 :            :                       vector<derived_probe *> & finished_results)
    8902                 :            : {
    8903         [ +  - ]:          4 :   string symbol_str_val;
    8904                 :            :   int64_t hwbkpt_address, len;
    8905                 :            :   bool has_addr, has_symbol_str, has_write, has_rw, has_len;
    8906                 :            : 
    8907 [ +  - ][ +  - ]:          4 :   if (! (sess.kernel_config["CONFIG_PERF_EVENTS"] == string("y")))
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ -  + ]
    8908                 :          0 :       throw semantic_error (_("CONFIG_PERF_EVENTS not available on this kernel"),
    8909 [ #  # ][ #  # ]:          0 :                             location->components[0]->tok);
    8910 [ +  - ][ +  - ]:          4 :   if (! (sess.kernel_config["CONFIG_HAVE_HW_BREAKPOINT"] == string("y")))
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ -  + ]
    8911                 :          0 :       throw semantic_error (_("CONFIG_HAVE_HW_BREAKPOINT not available on this kernel"),
    8912 [ #  # ][ #  # ]:          0 :                             location->components[0]->tok);
    8913                 :            : 
    8914         [ +  - ]:          4 :   has_addr = get_param (parameters, TOK_HWBKPT, hwbkpt_address);
    8915         [ +  - ]:          4 :   has_symbol_str = get_param (parameters, TOK_HWBKPT, symbol_str_val);
    8916         [ +  - ]:          4 :   has_len = get_param (parameters, TOK_LENGTH, len);
    8917 [ +  - ][ +  - ]:          4 :   has_write = (parameters.find(TOK_HWBKPT_WRITE) != parameters.end());
    8918 [ +  - ][ +  - ]:          4 :   has_rw = (parameters.find(TOK_HWBKPT_RW) != parameters.end());
    8919                 :            : 
    8920         [ +  - ]:          4 :   if (!has_len)
    8921                 :          4 :         len = 1;
    8922                 :            : 
    8923         [ -  + ]:          4 :   if (has_addr)
    8924                 :            :       finished_results.push_back (new hwbkpt_derived_probe (base,
    8925                 :            :                                                             location,
    8926                 :            :                                                             hwbkpt_address,
    8927                 :            :                                                             "",len,0,
    8928                 :            :                                                             has_write,
    8929 [ #  # ][ #  # ]:          0 :                                                             has_rw));
         [ #  # ][ #  # ]
                 [ #  # ]
    8930         [ +  - ]:          4 :   else if (has_symbol_str)
    8931                 :            :       finished_results.push_back (new hwbkpt_derived_probe (base,
    8932                 :            :                                                             location,
    8933                 :            :                                                             0,
    8934                 :            :                                                             symbol_str_val,len,0,
    8935                 :            :                                                             has_write,
    8936 [ +  - ][ +  - ]:          4 :                                                             has_rw));
         [ +  - ][ +  - ]
                 [ +  - ]
    8937                 :            :   else
    8938         [ +  - ]:          4 :     assert (0);
    8939                 :          4 : }
    8940                 :            : 
    8941                 :            : // ------------------------------------------------------------------------
    8942                 :            : // statically inserted kernel-tracepoint derived probes
    8943                 :            : // ------------------------------------------------------------------------
    8944                 :            : 
    8945 [ +  - ][ +  - ]:      16720 : struct tracepoint_arg
         [ +  - ][ +  - ]
    8946                 :            : {
    8947                 :            :   string name, c_type, typecast;
    8948                 :            :   bool usable, used, isptr;
    8949                 :            :   Dwarf_Die type_die;
    8950 [ +  - ][ +  - ]:       4732 :   tracepoint_arg(): usable(false), used(false), isptr(false) {}
    8951                 :            : };
    8952                 :            : 
    8953 [ #  # ][ #  # ]:          0 : struct tracepoint_derived_probe: public derived_probe
         [ #  # ][ #  # ]
    8954                 :            : {
    8955                 :            :   tracepoint_derived_probe (systemtap_session& s,
    8956                 :            :                             dwflpp& dw, Dwarf_Die& func_die,
    8957                 :            :                             const string& tracepoint_name,
    8958                 :            :                             probe* base_probe, probe_point* location);
    8959                 :            : 
    8960                 :            :   systemtap_session& sess;
    8961                 :            :   string tracepoint_name, header;
    8962                 :            :   vector <struct tracepoint_arg> args;
    8963                 :            : 
    8964                 :            :   void build_args(dwflpp& dw, Dwarf_Die& func_die);
    8965                 :            :   void getargs (std::list<std::string> &arg_set) const;
    8966                 :            :   void join_group (systemtap_session& s);
    8967                 :            :   void print_dupe_stamp(ostream& o);
    8968                 :            : };
    8969                 :            : 
    8970                 :            : 
    8971         [ #  # ]:         77 : struct tracepoint_derived_probe_group: public generic_dpg<tracepoint_derived_probe>
    8972                 :            : {
    8973                 :            :   void emit_module_decls (systemtap_session& s);
    8974                 :            :   void emit_module_init (systemtap_session& s);
    8975                 :            :   void emit_module_exit (systemtap_session& s);
    8976                 :            : };
    8977                 :            : 
    8978                 :            : 
    8979         [ -  + ]:       1925 : struct tracepoint_var_expanding_visitor: public var_expanding_visitor
    8980                 :            : {
    8981                 :       1925 :   tracepoint_var_expanding_visitor(dwflpp& dw, const string& probe_name,
    8982                 :            :                                    vector <struct tracepoint_arg>& args):
    8983                 :       1925 :     dw (dw), probe_name (probe_name), args (args) {}
    8984                 :            :   dwflpp& dw;
    8985                 :            :   const string& probe_name;
    8986                 :            :   vector <struct tracepoint_arg>& args;
    8987                 :            : 
    8988                 :            :   void visit_target_symbol (target_symbol* e);
    8989                 :            :   void visit_target_symbol_arg (target_symbol* e);
    8990                 :            :   void visit_target_symbol_context (target_symbol* e);
    8991                 :            : };
    8992                 :            : 
    8993                 :            : 
    8994                 :            : void
    8995                 :       6073 : tracepoint_var_expanding_visitor::visit_target_symbol_arg (target_symbol* e)
    8996                 :            : {
    8997         [ +  - ]:       6073 :   string argname = e->sym_name();
    8998                 :            : 
    8999                 :            :   // search for a tracepoint parameter matching this name
    9000                 :       6073 :   tracepoint_arg *arg = NULL;
    9001         [ +  + ]:      13589 :   for (unsigned i = 0; i < args.size(); ++i)
    9002 [ +  - ][ +  - ]:      12790 :     if (args[i].usable && args[i].name == argname)
         [ +  + ][ +  + ]
    9003                 :            :       {
    9004                 :       5274 :         arg = &args[i];
    9005                 :       5274 :         arg->used = true;
    9006                 :       5274 :         break;
    9007                 :            :       }
    9008                 :            : 
    9009         [ +  + ]:       6073 :   if (arg == NULL)
    9010                 :            :     {
    9011         [ +  - ]:        799 :       stringstream alternatives;
    9012         [ +  + ]:       2731 :       for (unsigned i = 0; i < args.size(); ++i)
    9013 [ +  - ][ +  - ]:       1932 :         alternatives << " $" << args[i].name;
    9014         [ +  - ]:        799 :       alternatives << " $$name $$parms $$vars";
    9015                 :            : 
    9016                 :            :       // We hope that this value ends up not being referenced after all, so it
    9017                 :            :       // can be optimized out quietly.
    9018                 :        799 :       throw semantic_error(_F("unable to find tracepoint variable '%s' (alternatives: %s)",
    9019 [ +  - ][ +  - ]:        799 :                               e->name.c_str(), alternatives.str().c_str()), e->tok);
         [ +  - ][ +  - ]
                 [ +  - ]
    9020                 :            :       // NB: we can have multiple errors, since a target variable
    9021                 :            :       // may be expanded in several different contexts:
    9022                 :            :       //     trace ("*") { $foo->bar }
    9023                 :            :     }
    9024                 :            : 
    9025                 :            :   // make sure we're not dereferencing base types
    9026         [ +  + ]:       5274 :   if (!arg->isptr)
    9027 [ +  - ][ +  - ]:       2392 :     e->assert_no_components("tracepoint", true);
                 [ +  - ]
    9028                 :            : 
    9029                 :            :   // we can only write to dereferenced fields, and only if guru mode is on
    9030         [ +  - ]:       5274 :   bool lvalue = is_active_lvalue(e);
    9031 [ -  + ][ #  # ]:       5274 :   if (lvalue && (!dw.sess.guru_mode || e->components.empty()))
         [ #  # ][ #  # ]
                 [ -  + ]
    9032 [ #  # ][ #  # ]:          0 :     throw semantic_error(_F("write to tracepoint variable '%s' not permitted; need stap -g", e->name.c_str()), e->tok);
                 [ #  # ]
    9033                 :            : 
    9034                 :            :   // XXX: if a struct/union arg is passed by value, then writing to its fields
    9035                 :            :   // is also meaningless until you dereference past a pointer member.  It's
    9036                 :            :   // harder to detect and prevent that though...
    9037                 :            : 
    9038 [ +  - ][ +  + ]:       5274 :   if (e->components.empty())
    9039                 :            :     {
    9040         [ -  + ]:       4075 :       if (e->addressof)
    9041 [ #  # ][ #  # ]:          0 :         throw semantic_error(_("cannot take address of tracepoint variable"), e->tok);
    9042                 :            : 
    9043                 :            :       // Just grab the value from the probe locals
    9044 [ +  - ][ +  - ]:       4075 :       symbol* sym = new symbol;
    9045                 :       4075 :       sym->tok = e->tok;
    9046 [ +  - ][ +  - ]:       4075 :       sym->name = "__tracepoint_arg_" + arg->name;
                 [ +  - ]
    9047         [ +  - ]:       4075 :       provide (sym);
    9048                 :            :     }
    9049                 :            :   else
    9050                 :            :     {
    9051                 :            :       // make a copy of the original as a bare target symbol for the tracepoint
    9052                 :            :       // value, which will be passed into the dwarf dereferencing code
    9053         [ +  - ]:       1199 :       target_symbol* e2 = deep_copy_visitor::deep_copy(e);
    9054         [ +  - ]:       1199 :       e2->components.clear();
    9055                 :            : 
    9056 [ +  - ][ +  + ]:       1199 :       if (e->components.back().type == target_symbol::comp_pretty_print)
    9057                 :            :         {
    9058         [ -  + ]:        864 :           if (lvalue)
    9059 [ #  # ][ #  # ]:          0 :             throw semantic_error(_("cannot write to pretty-printed variable"), e->tok);
    9060                 :            : 
    9061         [ +  - ]:        864 :           dwarf_pretty_print dpp(dw, &arg->type_die, e2, arg->isptr, false, *e);
    9062 [ +  - ][ +  - ]:        864 :           dpp.expand()->visit (this);
    9063         [ +  - ]:       6094 :           return;
    9064                 :            :         }
    9065                 :            : 
    9066                 :        335 :       bool userspace_p = false;
    9067                 :            :       string fname = (string(lvalue ? "_tracepoint_tvar_set" : "_tracepoint_tvar_get")
    9068                 :            :                       + "_" + e->sym_name()
    9069 [ -  + ][ +  - ]:        335 :                       + "_" + lex_cast(tick++));
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
    9070                 :            : 
    9071                 :        335 :       exp_type type = pe_long;
    9072         [ +  + ]:        335 :       string code = dw.literal_stmt_for_pointer (&arg->type_die, e, lvalue, type);
    9073                 :            : 
    9074                 :            :       functioncall* n = synthetic_embedded_deref_call(dw.sess, fname, code, type,
    9075         [ +  - ]:        291 :                                                       userspace_p, lvalue, e, e2);
    9076                 :            : 
    9077         [ -  + ]:        291 :       if (lvalue)
    9078                 :            :         {
    9079                 :            :           // Provide the functioncall to our parent, so that it can be
    9080                 :            :           // used to substitute for the assignment node immediately above
    9081                 :            :           // us.
    9082 [ #  # ][ #  # ]:          0 :           assert(!target_symbol_setter_functioncalls.empty());
    9083         [ #  # ]:          0 :           *(target_symbol_setter_functioncalls.top()) = n;
    9084                 :            :         }
    9085                 :            : 
    9086                 :            :       // Revisit the functioncall so arguments can be expanded.
    9087 [ +  - ][ +  - ]:       4410 :       n->visit (this);
                 [ +  - ]
    9088 [ +  - ][ +  + ]:       6073 :     }
    9089                 :            : }
    9090                 :            : 
    9091                 :            : 
    9092                 :            : void
    9093                 :       2050 : tracepoint_var_expanding_visitor::visit_target_symbol_context (target_symbol* e)
    9094                 :            : {
    9095         [ -  + ]:       2050 :   if (e->addressof)
    9096 [ #  # ][ #  # ]:          0 :     throw semantic_error(_("cannot take address of context variable"), e->tok);
    9097                 :            : 
    9098         [ -  + ]:       2050 :   if (is_active_lvalue (e))
    9099 [ #  # ][ #  # ]:          0 :     throw semantic_error(_F("write to tracepoint '%s' not permitted", e->name.c_str()), e->tok);
                 [ #  # ]
    9100                 :            : 
    9101         [ +  + ]:       2050 :   if (e->name == "$$name")
    9102                 :            :     {
    9103 [ +  - ][ +  - ]:        682 :       e->assert_no_components("tracepoint");
                 [ +  - ]
    9104                 :            : 
    9105                 :            :       // Synthesize an embedded expression.
    9106         [ +  - ]:        682 :       embedded_expr *expr = new embedded_expr;
    9107                 :        682 :       expr->tok = e->tok;
    9108                 :            :       expr->code = string("/* string */ /* pure */ ")
    9109 [ +  - ][ +  - ]:        682 :         + string("c->ips.tracepoint_name ? c->ips.tracepoint_name : \"\"");
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    9110                 :        682 :       provide (expr);
    9111                 :            :     }
    9112 [ +  + ][ +  - ]:       1368 :   else if (e->name == "$$vars" || e->name == "$$parms")
                 [ +  - ]
    9113                 :            :     {
    9114 [ +  - ][ +  - ]:       1368 :       e->assert_no_components("tracepoint", true);
                 [ +  - ]
    9115                 :            : 
    9116         [ +  - ]:       1368 :       token* pf_tok = new token(*e->tok);
    9117                 :       1368 :       pf_tok->content = "sprintf";
    9118                 :            : 
    9119                 :       1368 :       print_format* pf = print_format::create(pf_tok);
    9120                 :            : 
    9121         [ +  + ]:       4728 :       for (unsigned i = 0; i < args.size(); ++i)
    9122                 :            :         {
    9123         [ -  + ]:       3360 :           if (!args[i].usable)
    9124                 :          0 :             continue;
    9125         [ +  + ]:       3360 :           if (i > 0)
    9126         [ +  - ]:       1992 :             pf->raw_components += " ";
    9127         [ +  - ]:       3360 :           pf->raw_components += args[i].name;
    9128 [ +  - ][ +  - ]:       3360 :           target_symbol *tsym = new target_symbol;
    9129                 :       3360 :           tsym->tok = e->tok;
    9130 [ +  - ][ +  - ]:       3360 :           tsym->name = "$" + args[i].name;
                 [ +  - ]
    9131         [ +  - ]:       3360 :           tsym->components = e->components;
    9132                 :            : 
    9133                 :            :           // every variable should always be accessible!
    9134                 :       3360 :           tsym->saved_conversion_error = 0;
    9135         [ +  - ]:       3360 :           expression *texp = require<expression> (tsym); // NB: throws nothing ...
    9136         [ -  + ]:       3360 :           if (tsym->saved_conversion_error) // ... but this is how we know it happened.
    9137                 :            :             {
    9138         [ #  # ]:          0 :               if (dw.sess.verbose>2)
    9139         [ #  # ]:          0 :                 for (const semantic_error *c = tsym->saved_conversion_error;
    9140                 :            :                      c != 0; c = c->chain)
    9141 [ #  # ][ #  # ]:          0 :                   clog << _("variable location problem [man error::dwarf]: ") << c->what() << endl;
                 [ #  # ]
    9142         [ #  # ]:          0 :               pf->raw_components += "=?";
    9143                 :          0 :               continue;
    9144                 :            :             }
    9145                 :            : 
    9146         [ +  - ]:       4206 :           if (!e->components.empty() &&
           [ +  +  +  - ]
                 [ +  + ]
    9147                 :        846 :               e->components[0].type == target_symbol::comp_pretty_print)
    9148         [ +  - ]:        846 :             pf->raw_components += "=%s";
    9149                 :            :           else
    9150 [ +  + ][ +  - ]:       2514 :             pf->raw_components += args[i].isptr ? "=%p" : "=%#x";
    9151         [ +  - ]:       3360 :           pf->args.push_back(texp);
    9152                 :            :         }
    9153                 :            : 
    9154         [ +  - ]:       1368 :       pf->components = print_format::string_to_components(pf->raw_components);
    9155                 :       1368 :       provide (pf);
    9156                 :            :     }
    9157                 :            :   else
    9158                 :          0 :     assert(0); // shouldn't get here
    9159                 :       2050 : }
    9160                 :            : 
    9161                 :            : void
    9162                 :       8123 : tracepoint_var_expanding_visitor::visit_target_symbol (target_symbol* e)
    9163                 :            : {
    9164                 :            :   try
    9165                 :            :     {
    9166 [ +  - ][ +  - ]:      24369 :       assert(e->name.size() > 0
         [ +  - ][ #  # ]
                 [ #  # ]
    9167                 :            :              && ((e->name[0] == '$' && e->target_name == "")
    9168 [ +  - ][ +  - ]:      24369 :                  || (e->name == "@var" && e->target_name != "")));
         [ -  + ][ #  # ]
                 [ #  # ]
    9169                 :            : 
    9170 [ +  - ][ +  + ]:       8123 :       if (e->name == "$$name" || e->name == "$$parms" || e->name == "$$vars")
         [ +  - ][ +  + ]
         [ +  - ][ +  + ]
                 [ +  + ]
    9171         [ +  - ]:       2050 :         visit_target_symbol_context (e);
    9172 [ +  - ][ -  + ]:       6073 :       else if (e->name == "@var")
    9173 [ #  # ][ #  # ]:          0 :         throw semantic_error(_("cannot use @var DWARF variables in tracepoints"), e->tok);
    9174                 :            :       else
    9175         [ +  + ]:       6073 :         visit_target_symbol_arg (e);
    9176                 :            :     }
    9177         [ -  + ]:       1686 :   catch (const semantic_error &er)
    9178                 :            :     {
    9179         [ -  + ]:        843 :       e->chain (er);
    9180         [ -  + ]:        843 :       provide (e);
    9181                 :            :     }
    9182                 :       8123 : }
    9183                 :            : 
    9184                 :            : 
    9185                 :            : 
    9186                 :       1925 : tracepoint_derived_probe::tracepoint_derived_probe (systemtap_session& s,
    9187                 :            :                                                     dwflpp& dw, Dwarf_Die& func_die,
    9188                 :            :                                                     const string& tracepoint_name,
    9189                 :            :                                                     probe* base, probe_point* loc):
    9190                 :            :   derived_probe (base, loc, true /* .components soon rewritten */),
    9191 [ +  - ][ +  - ]:       1925 :   sess (s), tracepoint_name (tracepoint_name)
                 [ +  - ]
    9192                 :            : {
    9193                 :            :   // create synthetic probe point name; preserve condition
    9194         [ +  - ]:       1925 :   vector<probe_point::component*> comps;
    9195 [ +  - ][ +  - ]:       1925 :   comps.push_back (new probe_point::component (TOK_KERNEL));
                 [ +  - ]
    9196 [ +  - ][ +  - ]:       1925 :   comps.push_back (new probe_point::component (TOK_TRACE, new literal_string (tracepoint_name)));
         [ +  - ][ +  - ]
                 [ +  - ]
    9197 [ +  - ][ +  - ]:       1925 :   this->sole_location()->components = comps;
    9198                 :            : 
    9199                 :            :   // fill out the available arguments in this tracepoint
    9200         [ +  - ]:       1925 :   build_args(dw, func_die);
    9201                 :            : 
    9202                 :            :   // determine which header defined this tracepoint
    9203 [ +  - ][ +  - ]:       1925 :   string decl_file = dwarf_decl_file(&func_die);
    9204         [ +  - ]:       1925 :   header = decl_file; 
    9205                 :            : 
    9206                 :            : #if 0 /* This convention is not enforced. */
    9207                 :            :   size_t header_pos = decl_file.rfind("trace/");
    9208                 :            :   if (header_pos == string::npos)
    9209                 :            :     throw semantic_error ("cannot parse header location for tracepoint '"
    9210                 :            :                                   + tracepoint_name + "' in '"
    9211                 :            :                                   + decl_file + "'");
    9212                 :            :   header = decl_file.substr(header_pos);
    9213                 :            : #endif
    9214                 :            : 
    9215                 :            :   // tracepoints from FOO_event_types.h should really be included from FOO.h
    9216                 :            :   // XXX can dwarf tell us the include hierarchy?  it would be better to
    9217                 :            :   // ... walk up to see which one was directly included by tracequery.c
    9218                 :            :   // XXX: see also PR9993.
    9219         [ +  - ]:       1925 :   size_t header_pos = header.find("_event_types");
    9220         [ -  + ]:       1925 :   if (header_pos != string::npos)
    9221         [ #  # ]:          0 :     header.erase(header_pos, 12);
    9222                 :            : 
    9223                 :            :   // Now expand the local variables in the probe body
    9224         [ +  - ]:       1925 :   tracepoint_var_expanding_visitor v (dw, name, args);
    9225         [ +  - ]:       1925 :   v.replace (this->body);
    9226         [ +  + ]:       6657 :   for (unsigned i = 0; i < args.size(); i++)
    9227         [ +  + ]:       4732 :     if (args[i].used)
    9228                 :            :       {
    9229 [ +  - ][ +  - ]:       2788 :         vardecl* v = new vardecl;
    9230 [ +  - ][ +  - ]:       2788 :         v->name = "__tracepoint_arg_" + args[i].name;
                 [ +  - ]
    9231                 :       2788 :         v->tok = this->tok;
    9232         [ +  - ]:       2788 :         v->set_arity(0, this->tok);
    9233                 :       2788 :         v->type = pe_long;
    9234                 :       2788 :         v->synthetic = true;
    9235         [ +  - ]:       2788 :         this->locals.push_back (v);
    9236                 :            :       }
    9237                 :            : 
    9238         [ -  + ]:       1925 :   if (sess.verbose > 2)
    9239 [ #  # ][ #  # ]:       1925 :     clog << "tracepoint-based " << name << " tracepoint='" << tracepoint_name << "'" << endl;
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ +  - ][ +  - ]
                 [ +  - ]
    9240                 :       1925 : }
    9241                 :            : 
    9242                 :            : 
    9243                 :            : static bool
    9244                 :       5654 : resolve_tracepoint_arg_type(tracepoint_arg& arg)
    9245                 :            : {
    9246                 :            :   Dwarf_Die type;
    9247 [ +  - ][ +  +  :       5654 :   switch (dwarf_tag(&arg.type_die))
                +  -  - ]
    9248                 :            :     {
    9249                 :            :     case DW_TAG_typedef:
    9250                 :            :     case DW_TAG_const_type:
    9251                 :            :     case DW_TAG_volatile_type:
    9252                 :            :       // iterate on the referent type
    9253         [ +  - ]:        922 :       return (dwarf_attr_die(&arg.type_die, DW_AT_type, &arg.type_die)
    9254 [ +  - ][ +  - ]:        922 :               && resolve_tracepoint_arg_type(arg));
                 [ +  - ]
    9255                 :            :     case DW_TAG_base_type:
    9256                 :            :     case DW_TAG_enumeration_type:
    9257                 :            :       // base types will simply be treated as script longs
    9258                 :       2347 :       arg.isptr = false;
    9259                 :       2347 :       return true;
    9260                 :            :     case DW_TAG_pointer_type:
    9261                 :            :       // pointers can be treated as script longs,
    9262                 :            :       // and if we know their type, they can also be dereferenced
    9263                 :       2385 :       type = arg.type_die;
    9264 [ +  - ][ +  + ]:       2785 :       while (dwarf_attr_die(&arg.type_die, DW_AT_type, &arg.type_die))
    9265                 :            :         {
    9266                 :            :           // It still might be a non-type, e.g. const void,
    9267                 :            :           // so we need to strip away all qualifiers.
    9268         [ +  - ]:       2712 :           int tag = dwarf_tag(&arg.type_die);
    9269 [ +  + ][ +  + ]:       2712 :           if (tag != DW_TAG_typedef &&
                 [ +  - ]
    9270                 :            :               tag != DW_TAG_const_type &&
    9271                 :            :               tag != DW_TAG_volatile_type)
    9272                 :            :             {
    9273                 :       2312 :               arg.isptr = true;
    9274                 :       2312 :               break;
    9275                 :            :             }
    9276                 :            :         }
    9277         [ +  + ]:       2385 :       if (!arg.isptr)
    9278                 :         73 :         arg.type_die = type;
    9279         [ +  - ]:       2385 :       arg.typecast = "(intptr_t)";
    9280                 :       2385 :       return true;
    9281                 :            :     case DW_TAG_structure_type:
    9282                 :            :     case DW_TAG_union_type:
    9283                 :            :       // for structs/unions which are passed by value, we turn it into
    9284                 :            :       // a pointer that can be dereferenced.
    9285                 :          0 :       arg.isptr = true;
    9286         [ #  # ]:          0 :       arg.typecast = "(intptr_t)&";
    9287                 :          0 :       return true;
    9288                 :            :     default:
    9289                 :            :       // should we consider other types too?
    9290                 :       5654 :       return false;
    9291                 :            :     }
    9292                 :            : }
    9293                 :            : 
    9294                 :            : 
    9295                 :            : void
    9296                 :       1925 : tracepoint_derived_probe::build_args(dwflpp&, Dwarf_Die& func_die)
    9297                 :            : {
    9298                 :            :   Dwarf_Die arg;
    9299 [ +  - ][ +  - ]:       1925 :   if (dwarf_child(&func_die, &arg) == 0)
    9300         [ +  + ]:       4732 :     do
    9301 [ +  - ][ +  - ]:       4732 :       if (dwarf_tag(&arg) == DW_TAG_formal_parameter)
    9302                 :            :         {
    9303                 :            :           // build a tracepoint_arg for this parameter
    9304         [ +  - ]:       4732 :           tracepoint_arg tparg;
    9305 [ +  - ][ +  - ]:       4732 :           tparg.name = dwarf_diename(&arg);
    9306                 :            : 
    9307                 :            :           // read the type of this parameter
    9308 [ +  - ][ +  - ]:       9464 :           if (!dwarf_attr_die (&arg, DW_AT_type, &tparg.type_die)
         [ -  + ][ -  + ]
    9309         [ +  - ]:       4732 :               || !dwarf_type_name(&tparg.type_die, tparg.c_type))
    9310                 :          0 :             throw semantic_error (_F("cannot get type of parameter '%s' of tracepoint '%s'",
    9311 [ #  # ][ #  # ]:          0 :                                      tparg.name.c_str(), tracepoint_name.c_str()));
         [ #  # ][ #  # ]
    9312                 :            : 
    9313         [ +  - ]:       4732 :           tparg.usable = resolve_tracepoint_arg_type(tparg);
    9314         [ +  - ]:       4732 :           args.push_back(tparg);
    9315         [ -  + ]:       4732 :           if (sess.verbose > 4)
    9316 [ #  # ][ #  # ]:          0 :             clog << _F("found parameter for tracepoint '%s': type:'%s' name:'%s' %s",
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
    9317                 :            :                        tracepoint_name.c_str(), tparg.c_type.c_str(), tparg.name.c_str(),
    9318 [ #  # ][ +  - ]:       4732 :                        tparg.usable ? "ok" : "unavailable") << endl;
    9319                 :            :         }
    9320         [ +  - ]:       4732 :     while (dwarf_siblingof(&arg, &arg) == 0);
    9321                 :       1925 : }
    9322                 :            : 
    9323                 :            : void
    9324                 :          0 : tracepoint_derived_probe::getargs(std::list<std::string> &arg_set) const
    9325                 :            : {
    9326         [ #  # ]:          0 :   for (unsigned i = 0; i < args.size(); ++i)
    9327         [ #  # ]:          0 :     if (args[i].usable)
    9328 [ #  # ][ #  # ]:          0 :       arg_set.push_back("$"+args[i].name+":"+args[i].c_type);
         [ #  # ][ #  # ]
                 [ #  # ]
    9329                 :          0 : }
    9330                 :            : 
    9331                 :            : void
    9332                 :       1925 : tracepoint_derived_probe::join_group (systemtap_session& s)
    9333                 :            : {
    9334         [ +  + ]:       1925 :   if (! s.tracepoint_derived_probes)
    9335         [ +  - ]:         77 :     s.tracepoint_derived_probes = new tracepoint_derived_probe_group ();
    9336                 :       1925 :   s.tracepoint_derived_probes->enroll (this);
    9337                 :       1925 : }
    9338                 :            : 
    9339                 :            : 
    9340                 :            : void
    9341                 :       1712 : tracepoint_derived_probe::print_dupe_stamp(ostream& o)
    9342                 :            : {
    9343         [ +  + ]:       5862 :   for (unsigned i = 0; i < args.size(); i++)
    9344         [ +  + ]:       4150 :     if (args[i].used)
    9345                 :       3750 :       o << "__tracepoint_arg_" << args[i].name << endl;
    9346                 :       1712 : }
    9347                 :            : 
    9348                 :            : 
    9349                 :        160 : static vector<string> tracepoint_extra_decls (systemtap_session& s, const string& header)
    9350                 :            : {
    9351                 :        160 :   vector<string> they_live;
    9352                 :            :   // PR 9993
    9353                 :            :   // XXX: may need this to be configurable
    9354 [ +  - ][ +  - ]:        160 :   they_live.push_back ("#include <linux/skbuff.h>");
                 [ +  - ]
    9355                 :            : 
    9356                 :            :   // PR11649: conditional extra header
    9357                 :            :   // for kvm tracepoints in 2.6.33ish
    9358 [ +  - ][ +  - ]:        160 :   if (s.kernel_config["CONFIG_KVM"] != string("")) {
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ -  + ]
    9359 [ #  # ][ #  # ]:          0 :     they_live.push_back ("#include <linux/kvm_host.h>");
                 [ #  # ]
    9360                 :            :   }
    9361                 :            : 
    9362 [ +  - ][ +  + ]:        160 :   if (header.find("xfs") != string::npos && s.kernel_config["CONFIG_XFS_FS"] != string("")) {
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ -  + ][ +  + ]
         [ +  - ][ +  + ]
         [ +  + ][ +  - ]
         [ +  + ][ -  +  
          #  #  #  #  #  
                #  #  # ]
    9363 [ #  # ][ #  # ]:          0 :     they_live.push_back ("#define XFS_BIG_BLKNOS 1");
                 [ #  # ]
    9364 [ #  # ][ #  # ]:          0 :     if (s.kernel_source_tree != "")
    9365 [ #  # ][ #  # ]:          0 :       they_live.push_back ("#include \"fs/xfs/xfs_types.h\""); // in kernel-source tree
                 [ #  # ]
    9366 [ #  # ][ #  # ]:          0 :     they_live.push_back ("struct xfs_mount;");
                 [ #  # ]
    9367 [ #  # ][ #  # ]:          0 :     they_live.push_back ("struct xfs_inode;");
                 [ #  # ]
    9368 [ #  # ][ #  # ]:          0 :     they_live.push_back ("struct xfs_buf;");
                 [ #  # ]
    9369 [ #  # ][ #  # ]:          0 :     they_live.push_back ("struct xfs_bmbt_irec;");
                 [ #  # ]
    9370 [ #  # ][ #  # ]:          0 :     they_live.push_back ("struct xfs_trans;");
                 [ #  # ]
    9371                 :            :   }
    9372                 :            : 
    9373 [ +  - ][ -  + ]:        160 :   if (header.find("nfs") != string::npos && s.kernel_config["CONFIG_NFSD"] != string("")) {
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ -  + ]
         [ #  # ][ -  + ]
         [ -  + ][ #  # ]
         [ -  + ][ -  +  
          #  #  #  #  #  
                #  #  # ]
    9374 [ #  # ][ #  # ]:          0 :     they_live.push_back ("struct rpc_task;");
                 [ #  # ]
    9375                 :            :   }
    9376                 :            :   // RHEL6.3
    9377 [ +  - ][ +  + ]:        160 :   if (header.find("rpc") != string::npos && s.kernel_config["CONFIG_NFSD"] != string("")) {
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ -  + ][ +  + ]
         [ +  - ][ +  + ]
         [ +  + ][ +  - ]
         [ +  + ][ -  +  
          #  #  #  #  #  
                #  #  # ]
    9378 [ #  # ][ #  # ]:          0 :     they_live.push_back ("struct rpc_clnt;");
                 [ #  # ]
    9379 [ #  # ][ #  # ]:          0 :     they_live.push_back ("struct rpc_wait_queue;");
                 [ #  # ]
    9380                 :            :   }
    9381                 :            : 
    9382 [ +  - ][ +  - ]:        160 :   they_live.push_back ("#include <asm/cputime.h>");
                 [ +  - ]
    9383                 :            : 
    9384                 :            :   // linux 3.0
    9385 [ +  - ][ +  - ]:        160 :   they_live.push_back ("struct cpu_workqueue_struct;");
                 [ +  - ]
    9386                 :            : 
    9387 [ +  - ][ +  + ]:        160 :   if (header.find("ext4") != string::npos && s.kernel_config["CONFIG_EXT4_FS"] != string(""))
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  + ]
         [ +  - ][ +  + ]
         [ +  + ][ +  - ]
         [ +  + ][ +  +  
          #  #  #  #  #  
                #  #  # ]
    9388 [ +  - ][ +  - ]:          3 :     if (s.kernel_source_tree != "")
    9389 [ +  - ][ +  - ]:          3 :       they_live.push_back ("#include \"fs/ext4/ext4.h\""); // in kernel-source tree
                 [ +  - ]
    9390                 :            : 
    9391 [ +  - ][ +  + ]:        160 :   if (header.find("ext3") != string::npos && s.kernel_config["CONFIG_EXT3_FS"] != string(""))
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  + ]
         [ +  - ][ +  + ]
         [ +  + ][ +  - ]
         [ +  + ][ +  +  
          #  #  #  #  #  
                #  #  # ]
    9392 [ +  - ][ +  - ]:          1 :     they_live.push_back ("struct ext3_reserve_window_node;");
                 [ +  - ]
    9393                 :            : 
    9394                 :        160 :   return they_live;
    9395                 :            : }
    9396                 :            : 
    9397                 :            : 
    9398                 :            : void
    9399                 :         40 : tracepoint_derived_probe_group::emit_module_decls (systemtap_session& s)
    9400                 :            : {
    9401 [ +  - ][ +  - ]:         40 :   if (probes.empty())
    9402                 :         40 :     return;
    9403                 :            : 
    9404 [ +  - ][ +  - ]:         40 :   s.op->newline() << "/* ---- tracepoint probes ---- */";
    9405         [ +  - ]:         40 :   s.op->newline();
    9406                 :            : 
    9407                 :            : 
    9408                 :            :   // We create a MODULE_aux_N.c file for each tracepoint header, to allow them
    9409                 :            :   // to be separately compiled.  That's because kernel tracepoint headers sometimes
    9410                 :            :   // conflict.  PR13155.
    9411                 :            : 
    9412         [ +  - ]:         40 :   map<string,translator_output*> per_header_aux;
    9413                 :            :   // GC NB: the translator_output* structs are owned/retained by the systemtap_session.
    9414                 :            : 
    9415         [ +  + ]:        896 :   for (unsigned i = 0; i < probes.size(); ++i)
    9416                 :            :     {
    9417                 :        856 :       tracepoint_derived_probe *p = probes[i];
    9418         [ +  - ]:        856 :       string header = p->header;
    9419                 :            : 
    9420                 :            :       // We cache the auxiliary output files on a per-header basis.  We don't
    9421                 :            :       // need one aux file per tracepoint, only one per tracepoint-header.
    9422         [ +  - ]:        856 :       translator_output *tpop = per_header_aux[header];
    9423         [ +  + ]:        856 :       if (tpop == 0)
    9424                 :            :         {
    9425         [ +  - ]:        110 :           tpop = s.op_create_auxiliary();
    9426         [ +  - ]:        110 :           per_header_aux[header] = tpop;
    9427                 :            : 
    9428                 :            :           // PR9993: Add extra headers to work around undeclared types in individual
    9429                 :            :           // include/trace/foo.h files
    9430         [ +  - ]:        110 :           const vector<string>& extra_decls = tracepoint_extra_decls (s, header);
    9431         [ +  + ]:        442 :           for (unsigned z=0; z<extra_decls.size(); z++)
    9432 [ +  - ][ +  - ]:        332 :             tpop->newline() << extra_decls[z] << "\n";
                 [ +  - ]
    9433                 :            : 
    9434                 :            :           // strip include/ substring, the same way as done in get_tracequery_module()
    9435         [ +  - ]:        110 :           size_t root_pos = header.rfind("include/");
    9436 [ +  - ][ +  - ]:        110 :           header = ((root_pos != string::npos) ? header.substr(root_pos + 8) : header);
         [ #  # ][ +  - ]
                 [ +  - ]
    9437                 :            : 
    9438 [ +  - ][ +  - ]:        110 :           tpop->newline() << "#include <linux/tracepoint.h>" << endl;
                 [ +  - ]
    9439 [ +  - ][ +  - ]:        110 :           tpop->newline() << "#include <" << header << ">";
         [ +  - ][ +  - ]
    9440                 :            : 
    9441                 :            :           // Starting in 2.6.35, at the same time NOARGS was added, the callback
    9442                 :            :           // always has a void* as the first parameter. PR11599
    9443 [ +  - ][ +  - ]:        110 :           tpop->newline() << "#ifdef DECLARE_TRACE_NOARGS";
    9444 [ +  - ][ +  - ]:        110 :           tpop->newline() << "#define STAP_TP_DATA   , NULL";
    9445 [ +  - ][ +  - ]:        110 :           tpop->newline() << "#define STAP_TP_PROTO  void *cb_data"
    9446         [ +  - ]:        110 :                           << " __attribute__ ((unused))";
    9447 [ +  - ][ +  - ]:        110 :           if (!p->args.empty())
    9448 [ +  - ][ +  - ]:        110 :             tpop->line() << ",";
    9449 [ +  - ][ +  - ]:        110 :           tpop->newline() << "#else";
    9450 [ +  - ][ +  - ]:        110 :           tpop->newline() << "#define STAP_TP_DATA";
    9451 [ +  - ][ +  - ]:        110 :           tpop->newline() << "#define STAP_TP_PROTO";
    9452 [ +  - ][ -  + ]:        110 :           if (p->args.empty())
    9453 [ #  # ][ #  # ]:          0 :             tpop->line() << " void";
    9454 [ +  - ][ +  - ]:        110 :           tpop->newline() << "#endif";
    9455                 :            : 
    9456 [ +  - ][ +  - ]:        110 :           tpop->newline() << "#define intptr_t long";
                 [ +  - ]
    9457                 :            :         }
    9458                 :            : 
    9459                 :            :       // collect the args that are actually in use
    9460         [ +  - ]:        856 :       vector<const tracepoint_arg*> used_args;
    9461         [ +  + ]:       2931 :       for (unsigned j = 0; j < p->args.size(); ++j)
    9462         [ +  + ]:       2075 :         if (p->args[j].used)
    9463         [ +  - ]:       1875 :           used_args.push_back(&p->args[j]);
    9464                 :            : 
    9465                 :            :       // forward-declare the generated-side tracepoint callback
    9466 [ +  - ][ +  - ]:        856 :       tpop->newline() << "void enter_real_tracepoint_probe_" << i << "(";
         [ +  - ][ +  - ]
    9467         [ +  - ]:        856 :       tpop->indent(2);
    9468 [ +  - ][ +  + ]:        856 :       if (used_args.empty())
    9469 [ +  - ][ +  - ]:         82 :         tpop->line() << "void";
    9470         [ +  + ]:       2731 :       for (unsigned j = 0; j < used_args.size(); ++j)
    9471                 :            :         {
    9472         [ +  + ]:       1875 :           if (j > 0)
    9473 [ +  - ][ +  - ]:       1101 :             tpop->line() << ", ";
    9474 [ +  - ][ +  - ]:       1875 :           tpop->line() << "int64_t";
    9475                 :            :         }
    9476 [ +  - ][ +  - ]:        856 :       tpop->line() << ");";
    9477         [ +  - ]:        856 :       tpop->indent(-2);
    9478                 :            : 
    9479                 :            :       // define the generated-side tracepoint callback - in the main translator-output
    9480 [ +  - ][ +  - ]:        856 :       s.op->newline() << "void enter_real_tracepoint_probe_" << i << "(";
         [ +  - ][ +  - ]
    9481         [ +  - ]:        856 :       s.op->indent(2);
    9482 [ +  - ][ +  + ]:        856 :       if (used_args.empty())
    9483 [ +  - ][ +  - ]:         82 :         s.op->newline() << "void";
    9484         [ +  + ]:       2731 :       for (unsigned j = 0; j < used_args.size(); ++j)
    9485                 :            :         {
    9486         [ +  + ]:       1875 :           if (j > 0)
    9487 [ +  - ][ +  - ]:       1101 :             s.op->line() << ", ";
    9488 [ +  - ][ +  - ]:       1875 :           s.op->newline() << "int64_t __tracepoint_arg_" << used_args[j]->name;
                 [ +  - ]
    9489                 :            :         }
    9490 [ +  - ][ +  - ]:        856 :       s.op->newline() << ")";
    9491 [ +  - ][ +  - ]:        856 :       s.op->newline(-2) << "{";
    9492 [ +  - ][ +  - ]:        856 :       s.op->newline(1) << "const struct stap_probe * const probe = "
    9493 [ +  - ][ +  - ]:        856 :                        << common_probe_init (p) << ";";
         [ +  - ][ +  - ]
    9494                 :            :       common_probe_entryfn_prologue (s, "STAP_SESSION_RUNNING", "probe",
    9495 [ +  - ][ +  - ]:        856 :                                      "stp_probe_type_tracepoint");
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    9496 [ +  - ][ +  - ]:        856 :       s.op->newline() << "c->ips.tracepoint_name = "
    9497 [ +  - ][ +  - ]:       1712 :                       << lex_cast_qstring (p->tracepoint_name)
                 [ +  - ]
    9498         [ +  - ]:        856 :                       << ";";
    9499         [ +  + ]:       2731 :       for (unsigned j = 0; j < used_args.size(); ++j)
    9500                 :            :         {
    9501 [ +  - ][ +  - ]:       1875 :           s.op->newline() << "c->probe_locals." << p->name
                 [ +  - ]
    9502 [ +  - ][ +  - ]:       3750 :                           << "." + s.up->c_localname("__tracepoint_arg_" + used_args[j]->name)
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    9503 [ +  - ][ +  - ]:       1875 :                           << " = __tracepoint_arg_" << used_args[j]->name << ";";
                 [ +  - ]
    9504                 :            :         }
    9505 [ +  - ][ +  - ]:        856 :       s.op->newline() << "(*probe->ph) (c);";
    9506         [ +  - ]:        856 :       common_probe_entryfn_epilogue (s, true);
    9507 [ +  - ][ +  - ]:        856 :       s.op->newline(-1) << "}";
    9508                 :            : 
    9509                 :            :       // define the real tracepoint callback function
    9510 [ +  - ][ +  - ]:        856 :       tpop->newline() << "static void enter_tracepoint_probe_" << i << "(";
         [ +  - ][ +  - ]
    9511 [ +  - ][ +  - ]:        856 :       tpop->newline(2) << "STAP_TP_PROTO";
    9512         [ +  + ]:       2931 :       for (unsigned j = 0; j < p->args.size(); ++j)
    9513                 :            :         {
    9514         [ +  + ]:       2075 :           if (j > 0)
    9515 [ +  - ][ +  - ]:       1219 :             tpop->line() << ", ";
    9516 [ +  - ][ +  - ]:       2075 :           tpop->newline() << p->args[j].c_type << " __tracepoint_arg_" << p->args[j].name;
         [ +  - ][ +  - ]
    9517                 :            :         }
    9518 [ +  - ][ +  - ]:        856 :       tpop->newline() << ")";
    9519 [ +  - ][ +  - ]:        856 :       tpop->newline(-2) << "{";
    9520 [ +  - ][ +  - ]:        856 :       tpop->newline(1) << "enter_real_tracepoint_probe_" << i << "(";
         [ +  - ][ +  - ]
    9521         [ +  - ]:        856 :       tpop->indent(2);
    9522         [ +  + ]:       2731 :       for (unsigned j = 0; j < used_args.size(); ++j)
    9523                 :            :         {
    9524         [ +  + ]:       1875 :           if (j > 0)
    9525 [ +  - ][ +  - ]:       1101 :             tpop->line() << ", ";
    9526 [ +  - ][ +  - ]:       1875 :           tpop->newline() << "(int64_t)" << used_args[j]->typecast
                 [ +  - ]
    9527 [ +  - ][ +  - ]:       1875 :                           << "__tracepoint_arg_" << used_args[j]->name;
    9528                 :            :         }
    9529 [ +  - ][ +  - ]:        856 :       tpop->newline() << ");";
    9530 [ +  - ][ +  - ]:        856 :       tpop->newline(-3) << "}";
    9531                 :            : 
    9532                 :            : 
    9533                 :            :       // emit normalized registration functions
    9534 [ +  - ][ +  - ]:        856 :       tpop->newline() << "int register_tracepoint_probe_" << i << "(void) {";
         [ +  - ][ +  - ]
    9535 [ +  - ][ +  - ]:        856 :       tpop->newline(1) << "return register_trace_" << p->tracepoint_name
                 [ +  - ]
    9536 [ +  - ][ +  - ]:        856 :                        << "(enter_tracepoint_probe_" << i << " STAP_TP_DATA);";
                 [ +  - ]
    9537 [ +  - ][ +  - ]:        856 :       tpop->newline(-1) << "}";
    9538                 :            : 
    9539                 :            :       // NB: we're not prepared to deal with unreg failures.  However, failures
    9540                 :            :       // can only occur if the tracepoint doesn't exist (yet?), or if we
    9541                 :            :       // weren't even registered.  The former should be OKed by the initial
    9542                 :            :       // registration call, and the latter is safe to ignore.
    9543 [ +  - ][ +  - ]:        856 :       tpop->newline() << "void unregister_tracepoint_probe_" << i << "(void) {";
         [ +  - ][ +  - ]
    9544 [ +  - ][ +  - ]:        856 :       tpop->newline(1) << "(void) unregister_trace_" << p->tracepoint_name
                 [ +  - ]
    9545 [ +  - ][ +  - ]:        856 :                        << "(enter_tracepoint_probe_" << i << " STAP_TP_DATA);";
                 [ +  - ]
    9546 [ +  - ][ +  - ]:        856 :       tpop->newline(-1) << "}";
    9547         [ +  - ]:        856 :       tpop->newline();
    9548                 :            : 
    9549                 :            :       // declare normalized registration functions
    9550 [ +  - ][ +  - ]:        856 :       s.op->newline() << "int register_tracepoint_probe_" << i << "(void);";
         [ +  - ][ +  - ]
    9551 [ +  - ][ +  - ]:        856 :       s.op->newline() << "void unregister_tracepoint_probe_" << i << "(void);";
         [ +  - ][ +  - ]
    9552                 :            : 
    9553         [ +  - ]:        856 :       tpop->assert_0_indent();
    9554 [ +  - ][ +  - ]:        856 :     }
    9555                 :            : 
    9556                 :            :   // emit an array of registration functions for easy init/shutdown
    9557 [ +  - ][ +  - ]:         40 :   s.op->newline() << "static struct stap_tracepoint_probe {";
    9558 [ +  - ][ +  - ]:         40 :   s.op->newline(1) << "int (*reg)(void);";
    9559 [ +  - ][ +  - ]:         40 :   s.op->newline(0) << "void (*unreg)(void);";
    9560 [ +  - ][ +  - ]:         40 :   s.op->newline(-1) << "} stap_tracepoint_probes[] = {";
    9561         [ +  - ]:         40 :   s.op->indent(1);
    9562         [ +  + ]:        896 :   for (unsigned i = 0; i < probes.size(); ++i)
    9563                 :            :     {
    9564 [ +  - ][ +  - ]:        856 :       s.op->newline () << "{";
    9565 [ +  - ][ +  - ]:        856 :       s.op->line() << " .reg=&register_tracepoint_probe_" << i << ",";
         [ +  - ][ +  - ]
    9566 [ +  - ][ +  - ]:        856 :       s.op->line() << " .unreg=&unregister_tracepoint_probe_" << i;
                 [ +  - ]
    9567 [ +  - ][ +  - ]:        856 :       s.op->line() << " },";
    9568                 :            :     }
    9569 [ +  - ][ +  - ]:         40 :   s.op->newline(-1) << "};";
    9570 [ +  - ][ +  - ]:         40 :   s.op->newline();
    9571                 :            : }
    9572                 :            : 
    9573                 :            : 
    9574                 :            : void
    9575                 :         40 : tracepoint_derived_probe_group::emit_module_init (systemtap_session &s)
    9576                 :            : {
    9577         [ -  + ]:         40 :   if (probes.size () == 0)
    9578                 :         40 :     return;
    9579                 :            : 
    9580                 :         40 :   s.op->newline() << "/* init tracepoint probes */";
    9581                 :         40 :   s.op->newline() << "for (i=0; i<" << probes.size() << "; i++) {";
    9582                 :         40 :   s.op->newline(1) << "rc = stap_tracepoint_probes[i].reg();";
    9583                 :         40 :   s.op->newline() << "if (rc) {";
    9584                 :         40 :   s.op->newline(1) << "for (j=i-1; j>=0; j--)"; // partial rollback
    9585                 :         40 :   s.op->newline(1) << "stap_tracepoint_probes[j].unreg();";
    9586                 :         40 :   s.op->newline(-1) << "break;"; // don't attempt to register any more probes
    9587                 :         40 :   s.op->newline(-1) << "}";
    9588                 :         40 :   s.op->newline(-1) << "}";
    9589                 :            : 
    9590                 :            :   // This would be technically proper (on those autoconf-detectable
    9591                 :            :   // kernels that include this function in tracepoint.h), however we
    9592                 :            :   // already make several calls to synchronze_sched() during our
    9593                 :            :   // shutdown processes.
    9594                 :            : 
    9595                 :            :   // s.op->newline() << "if (rc)";
    9596                 :            :   // s.op->newline(1) << "tracepoint_synchronize_unregister();";
    9597                 :            :   // s.op->indent(-1);
    9598                 :            : }
    9599                 :            : 
    9600                 :            : 
    9601                 :            : void
    9602                 :         50 : tracepoint_derived_probe_group::emit_module_exit (systemtap_session& s)
    9603                 :            : {
    9604         [ -  + ]:         50 :   if (probes.empty())
    9605                 :         50 :     return;
    9606                 :            : 
    9607                 :         50 :   s.op->newline() << "/* deregister tracepoint probes */";
    9608                 :         50 :   s.op->newline() << "for (i=0; i<" << probes.size() << "; i++)";
    9609                 :         50 :   s.op->newline(1) << "stap_tracepoint_probes[i].unreg();";
    9610                 :         50 :   s.op->indent(-1);
    9611                 :            : 
    9612                 :            :   // Not necessary: see above.
    9613                 :            : 
    9614                 :            :   // s.op->newline() << "tracepoint_synchronize_unregister();";
    9615                 :            : }
    9616                 :            : 
    9617                 :            : 
    9618 [ +  - ][ -  + ]:        592 : struct tracepoint_query : public base_query
    9619                 :            : {
    9620                 :        592 :   tracepoint_query(dwflpp & dw, const string & tracepoint,
    9621                 :            :                    probe * base_probe, probe_point * base_loc,
    9622                 :            :                    vector<derived_probe *> & results):
    9623                 :            :     base_query(dw, "*"), tracepoint(tracepoint),
    9624                 :            :     base_probe(base_probe), base_loc(base_loc),
    9625 [ +  - ][ +  - ]:        592 :     results(results) {}
         [ +  - ][ +  - ]
    9626                 :            : 
    9627                 :            :   const string& tracepoint;
    9628                 :            : 
    9629                 :            :   probe * base_probe;
    9630                 :            :   probe_point * base_loc;
    9631                 :            :   vector<derived_probe *> & results;
    9632                 :            :   set<string> probed_names;
    9633                 :            : 
    9634                 :            :   void handle_query_module();
    9635                 :            :   int handle_query_cu(Dwarf_Die * cudie);
    9636                 :            :   int handle_query_func(Dwarf_Die * func);
    9637                 :          0 :   void query_library (const char *) {}
    9638                 :          0 :   void query_plt (const char *entry, size_t addr) {}
    9639                 :            : 
    9640                 :            :   static int tracepoint_query_cu (Dwarf_Die * cudie, void * arg);
    9641                 :            :   static int tracepoint_query_func (Dwarf_Die * func, base_query * query);
    9642                 :            : };
    9643                 :            : 
    9644                 :            : 
    9645                 :            : void
    9646                 :      23088 : tracepoint_query::handle_query_module()
    9647                 :            : {
    9648                 :            :   // look for the tracepoints in each CU
    9649                 :      23088 :   dw.iterate_over_cus(tracepoint_query_cu, this, false);
    9650                 :      23088 : }
    9651                 :            : 
    9652                 :            : 
    9653                 :            : int
    9654                 :      23088 : tracepoint_query::handle_query_cu(Dwarf_Die * cudie)
    9655                 :            : {
    9656         [ +  - ]:      23088 :   dw.focus_on_cu (cudie);
    9657                 :            : 
    9658                 :            :   // look at each function to see if it's a tracepoint
    9659         [ +  - ]:      23088 :   string function = "stapprobe_" + tracepoint;
    9660 [ +  - ][ +  - ]:      23088 :   return dw.iterate_over_functions (tracepoint_query_func, this, function);
    9661                 :            : }
    9662                 :            : 
    9663                 :            : 
    9664                 :            : int
    9665                 :       1925 : tracepoint_query::handle_query_func(Dwarf_Die * func)
    9666                 :            : {
    9667         [ +  - ]:       1925 :   dw.focus_on_function (func);
    9668                 :            : 
    9669 [ +  - ][ -  + ]:       1925 :   assert(startswith(dw.function_name, "stapprobe_"));
    9670         [ +  - ]:       1925 :   string tracepoint_instance = dw.function_name.substr(10);
    9671                 :            : 
    9672                 :            :   // check for duplicates -- sometimes tracepoint headers may be indirectly
    9673                 :            :   // included in more than one of our tracequery modules.
    9674 [ +  - ][ -  + ]:       1925 :   if (!probed_names.insert(tracepoint_instance).second)
    9675                 :          0 :     return DWARF_CB_OK;
    9676                 :            : 
    9677                 :            :   derived_probe *dp = new tracepoint_derived_probe (dw.sess, dw, *func,
    9678                 :            :                                                     tracepoint_instance,
    9679 [ +  - ][ +  - ]:       1925 :                                                     base_probe, base_loc);
    9680         [ +  - ]:       1925 :   results.push_back (dp);
    9681         [ +  - ]:       1925 :   return DWARF_CB_OK;
    9682                 :            : }
    9683                 :            : 
    9684                 :            : 
    9685                 :            : int
    9686                 :      23088 : tracepoint_query::tracepoint_query_cu (Dwarf_Die * cudie, void * arg)
    9687                 :            : {
    9688                 :      23088 :   tracepoint_query * q = static_cast<tracepoint_query *>(arg);
    9689         [ -  + ]:      23088 :   if (pending_interrupts) return DWARF_CB_ABORT;
    9690                 :      23088 :   return q->handle_query_cu(cudie);
    9691                 :            : }
    9692                 :            : 
    9693                 :            : 
    9694                 :            : int
    9695                 :       1925 : tracepoint_query::tracepoint_query_func (Dwarf_Die * func, base_query * query)
    9696                 :            : {
    9697                 :       1925 :   tracepoint_query * q = static_cast<tracepoint_query *>(query);
    9698         [ -  + ]:       1925 :   if (pending_interrupts) return DWARF_CB_ABORT;
    9699                 :       1925 :   return q->handle_query_func(func);
    9700                 :            : }
    9701                 :            : 
    9702                 :            : 
    9703                 :            : struct tracepoint_builder: public derived_probe_builder
    9704                 :            : {
    9705                 :            : private:
    9706                 :            :   dwflpp *dw;
    9707                 :            :   bool init_dw(systemtap_session& s);
    9708                 :            :   void get_tracequery_modules(systemtap_session& s,
    9709                 :            :                               const vector<string>& headers,
    9710                 :            :                               vector<string>& modules);
    9711                 :            : 
    9712                 :            : public:
    9713                 :            : 
    9714                 :       1218 :   tracepoint_builder(): dw(0) {}
    9715 [ #  # ][ #  # ]:          0 :   ~tracepoint_builder() { delete dw; }
                 [ #  # ]
    9716                 :            : 
    9717                 :       1218 :   void build_no_more (systemtap_session& s)
    9718                 :            :   {
    9719 [ +  + ][ -  + ]:       1218 :     if (dw && s.verbose > 3)
    9720                 :          0 :       clog << _("tracepoint_builder releasing dwflpp") << endl;
    9721         [ +  + ]:       1218 :     delete dw;
    9722                 :       1218 :     dw = NULL;
    9723                 :            : 
    9724                 :       1218 :     delete_session_module_cache (s);
    9725                 :       1218 :   }
    9726                 :            : 
    9727                 :            :   void build(systemtap_session& s,
    9728                 :            :              probe *base, probe_point *location,
    9729                 :            :              literal_map_t const& parameters,
    9730                 :            :              vector<derived_probe*>& finished_results);
    9731                 :            : };
    9732                 :            : 
    9733                 :            : 
    9734                 :            : 
    9735                 :            : // Create (or cache) one or more tracequery .o modules, based upon the
    9736                 :            : // tracepoint-related header files given.  Return the generated or cached
    9737                 :            : // modules[].
    9738                 :            : 
    9739                 :            : void
    9740                 :         84 : tracepoint_builder::get_tracequery_modules(systemtap_session& s,
    9741                 :            :                                            const vector<string>& headers,
    9742                 :            :                                            vector<string>& modules)
    9743                 :            : {
    9744         [ -  + ]:         84 :   if (s.verbose > 2)
    9745                 :            :     {
    9746 [ #  # ][ #  # ]:          0 :       clog << _F("Pass 2: getting a tracepoint query for %zu headers: ", headers.size()) << endl;
         [ #  # ][ #  # ]
    9747         [ #  # ]:          0 :       for (size_t i = 0; i < headers.size(); ++i)
    9748 [ #  # ][ #  # ]:          0 :         clog << "  " << headers[i] << endl;
                 [ #  # ]
    9749                 :            :     }
    9750                 :            : 
    9751         [ +  - ]:         84 :   map<string,string> headers_cache_obj;  // header name -> cache/.../tracequery_hash.o file name
    9752                 :            :   // Map the headers to cache .o names.  Note that this has side-effects of
    9753                 :            :   // creating the $SYSTEMTAP_DIR/.cache/XX/... directory and the hash-log file,
    9754                 :            :   // so we prefer not to repeat this.
    9755         [ +  - ]:         84 :   vector<string> uncached_headers;
    9756         [ +  + ]:       4284 :   for (size_t i=0; i<headers.size(); i++)
    9757 [ +  - ][ +  - ]:       4200 :     headers_cache_obj[headers[i]] = find_tracequery_hash(s, headers[i]);
         [ +  - ][ +  - ]
    9758                 :            : 
    9759                 :            :   // They may be in the cache already.
    9760 [ +  - ][ +  - ]:         84 :   if (s.use_cache && !s.poison_cache)
    9761         [ +  + ]:       4284 :     for (size_t i=0; i<headers.size(); i++)
    9762                 :            :       {
    9763                 :            :         // see if the cached module exists
    9764         [ +  - ]:       4200 :         const string& tracequery_path = headers_cache_obj[headers[i]];
    9765 [ +  - ][ +  - ]:       4200 :         if (!tracequery_path.empty() && file_exists(tracequery_path))
         [ +  - ][ +  + ]
                 [ +  + ]
    9766                 :            :           {
    9767         [ -  + ]:       4150 :             if (s.verbose > 2)
    9768 [ #  # ][ #  # ]:          0 :               clog << _F("Pass 2: using cached %s", tracequery_path.c_str()) << endl;
         [ #  # ][ #  # ]
                 [ #  # ]
    9769                 :            : 
    9770                 :            :             // an empty file is a cached failure
    9771 [ +  - ][ +  + ]:       4150 :             if (get_file_size(tracequery_path) > 0)
    9772         [ +  - ]:       3237 :               modules.push_back (tracequery_path);
    9773                 :            :           }
    9774                 :            :         else
    9775         [ +  - ]:         50 :           uncached_headers.push_back(headers[i]);
    9776                 :         84 :       }
    9777                 :            :   else
    9778         [ #  # ]:          0 :     uncached_headers = headers;
    9779                 :            : 
    9780                 :            :   // If we have nothing left to search for, quit
    9781 [ +  - ][ +  + ]:        168 :   if (uncached_headers.empty()) return;
    9782                 :            : 
    9783         [ +  - ]:          1 :   map<string,string> headers_tracequery_src; // header -> C-source code mapping
    9784                 :            : 
    9785                 :            :   // We could query several subsets of headers[] to make this go
    9786                 :            :   // faster, but let's KISS and do one at a time.
    9787         [ +  + ]:         51 :   for (size_t i=0; i<uncached_headers.size(); i++)
    9788                 :            :     {
    9789                 :         50 :       const string& header = uncached_headers[i];
    9790                 :            : 
    9791                 :            :       // create a tracequery source file
    9792         [ +  - ]:         50 :       ostringstream osrc;
    9793                 :            : 
    9794                 :            :       // PR9993: Add extra headers to work around undeclared types in individual
    9795                 :            :       // include/trace/foo.h files
    9796         [ +  - ]:         50 :       vector<string> short_decls = tracepoint_extra_decls(s, header);
    9797                 :            : 
    9798                 :            :       // add each requested tracepoint header
    9799         [ +  - ]:         50 :       size_t root_pos = header.rfind("include/");
    9800                 :            :       short_decls.push_back(string("#include <") +
    9801                 :            :                             ((root_pos != string::npos) ? header.substr(root_pos + 8) : header) +
    9802 [ +  - ][ +  + ]:         50 :                             string(">"));
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    9803                 :            : 
    9804 [ +  - ][ +  - ]:         50 :       osrc << "#ifdef CONFIG_TRACEPOINTS" << endl;
    9805 [ +  - ][ +  - ]:         50 :       osrc << "#include <linux/tracepoint.h>" << endl;
    9806                 :            : 
    9807                 :            :       // the kernel has changed this naming a few times, previously TPPROTO,
    9808                 :            :       // TP_PROTO, TPARGS, TP_ARGS, etc.  so let's just dupe the latest.
    9809 [ +  - ][ +  - ]:         50 :       osrc << "#ifndef PARAMS" << endl;
    9810 [ +  - ][ +  - ]:         50 :       osrc << "#define PARAMS(args...) args" << endl;
    9811 [ +  - ][ +  - ]:         50 :       osrc << "#endif" << endl;
    9812                 :            : 
    9813                 :            :       // override DECLARE_TRACE to synthesize probe functions for us
    9814 [ +  - ][ +  - ]:         50 :       osrc << "#undef DECLARE_TRACE" << endl;
    9815 [ +  - ][ +  - ]:         50 :       osrc << "#define DECLARE_TRACE(name, proto, args) \\" << endl;
    9816 [ +  - ][ +  - ]:         50 :       osrc << "  void stapprobe_##name(proto) {}" << endl;
    9817                 :            : 
    9818                 :            :       // 2.6.35 added the NOARGS variant, but it's the same for us
    9819 [ +  - ][ +  - ]:         50 :       osrc << "#undef DECLARE_TRACE_NOARGS" << endl;
    9820 [ +  - ][ +  - ]:         50 :       osrc << "#define DECLARE_TRACE_NOARGS(name) \\" << endl;
    9821 [ +  - ][ +  - ]:         50 :       osrc << "  DECLARE_TRACE(name, void, )" << endl;
    9822                 :            : 
    9823                 :            :       // 2.6.38 added the CONDITION variant, which can also just redirect
    9824 [ +  - ][ +  - ]:         50 :       osrc << "#undef DECLARE_TRACE_CONDITION" << endl;
    9825 [ +  - ][ +  - ]:         50 :       osrc << "#define DECLARE_TRACE_CONDITION(name, proto, args, cond) \\" << endl;
    9826 [ +  - ][ +  - ]:         50 :       osrc << "  DECLARE_TRACE(name, PARAMS(proto), PARAMS(args))" << endl;
    9827                 :            : 
    9828                 :            :       // older tracepoints used DEFINE_TRACE, so redirect that too
    9829 [ +  - ][ +  - ]:         50 :       osrc << "#undef DEFINE_TRACE" << endl;
    9830 [ +  - ][ +  - ]:         50 :       osrc << "#define DEFINE_TRACE(name, proto, args) \\" << endl;
    9831 [ +  - ][ +  - ]:         50 :       osrc << "  DECLARE_TRACE(name, PARAMS(proto), PARAMS(args))" << endl;
    9832                 :            : 
    9833                 :            :       // add the specified decls/#includes
    9834         [ +  + ]:        252 :       for (unsigned z=0; z<short_decls.size(); z++)
    9835         [ +  - ]:        202 :         osrc << "#undef TRACE_INCLUDE_FILE\n"
    9836         [ +  - ]:        202 :              << "#undef TRACE_INCLUDE_PATH\n"
    9837 [ +  - ][ +  - ]:        202 :              << short_decls[z] << "\n";
    9838                 :            : 
    9839                 :            :       // finish up the module source
    9840 [ +  - ][ +  - ]:         50 :       osrc << "#endif /* CONFIG_TRACEPOINTS */" << endl;
    9841                 :            : 
    9842                 :            :       // save the source file away
    9843 [ +  - ][ +  - ]:         50 :       headers_tracequery_src[header] = osrc.str();
         [ +  - ][ +  - ]
    9844 [ +  - ][ +  - ]:         50 :     }
    9845                 :            : 
    9846                 :            :   // now build them all together
    9847         [ +  - ]:          1 :   map<string,string> tracequery_objs = make_tracequeries(s, headers_tracequery_src);
    9848                 :            : 
    9849                 :            :   // now plop them into the cache
    9850         [ +  - ]:          1 :   if (s.use_cache)
    9851         [ +  + ]:         51 :     for (size_t i=0; i<uncached_headers.size(); i++)
    9852                 :            :       {
    9853                 :         50 :         const string& header = uncached_headers[i];
    9854         [ +  - ]:         50 :         const string& tracequery_obj = tracequery_objs[header];
    9855         [ +  - ]:         50 :         const string& tracequery_path = headers_cache_obj[header];
    9856 [ +  - ][ +  - ]:         50 :         if (tracequery_obj !="" && file_exists(tracequery_obj))
         [ +  - ][ +  + ]
                 [ +  + ]
    9857                 :            :           {
    9858         [ +  - ]:         39 :             copy_file(tracequery_obj, tracequery_path, s.verbose > 2);
    9859         [ +  - ]:         39 :             modules.push_back (tracequery_path);
    9860                 :            :           }
    9861                 :            :         else
    9862                 :            :           // cache an empty file for failures
    9863 [ +  - ][ +  - ]:         11 :           copy_file("/dev/null", tracequery_path, s.verbose > 2);
                 [ +  - ]
    9864 [ +  - ][ +  - ]:         84 :       }
         [ +  - ][ +  + ]
         [ +  - ][ +  + ]
    9865                 :            : }
    9866                 :            : 
    9867                 :            : 
    9868                 :            : 
    9869                 :            : bool
    9870                 :        592 : tracepoint_builder::init_dw(systemtap_session& s)
    9871                 :            : {
    9872         [ +  + ]:        592 :   if (dw != NULL)
    9873                 :        508 :     return true;
    9874                 :            : 
    9875         [ +  - ]:         84 :   vector<string> tracequery_modules;
    9876         [ +  - ]:         84 :   vector<string> system_headers;
    9877                 :            : 
    9878                 :            :   glob_t trace_glob;
    9879                 :            : 
    9880                 :            :   // find kernel_source_tree
    9881 [ +  - ][ +  - ]:         84 :   if (s.kernel_source_tree == "")
    9882                 :            :     {
    9883                 :            :       unsigned found;
    9884 [ +  - ][ +  - ]:         84 :       DwflPtr dwfl_ptr = setup_dwfl_kernel ("kernel", &found, s);
                 [ +  - ]
    9885                 :         84 :       Dwfl *dwfl = dwfl_ptr.get()->dwfl;
    9886         [ +  - ]:         84 :       if (found)
    9887                 :            :         {
    9888                 :         84 :           Dwarf_Die *cudie = 0;
    9889                 :            :           Dwarf_Addr bias;
    9890 [ +  - ][ +  - ]:        168 :           while ((cudie = dwfl_nextcu (dwfl, cudie, &bias)) != NULL)
    9891                 :            :             {
    9892         [ +  - ]:         84 :               assert_no_interrupts();
    9893                 :            :               Dwarf_Attribute attr;
    9894 [ +  - ][ +  - ]:         84 :               const char* name = dwarf_formstring (dwarf_attr (cudie, DW_AT_comp_dir, &attr));
    9895         [ +  - ]:         84 :               if (name) 
    9896                 :            :                 {
    9897         [ -  + ]:         84 :                   if (s.verbose > 2)
    9898 [ #  # ][ #  # ]:          0 :                     clog << _F("Located kernel source tree (DW_AT_comp_dir) at '%s'", name) << endl;
         [ #  # ][ #  # ]
    9899                 :            : 
    9900         [ +  - ]:         84 :                   s.kernel_source_tree = name;
    9901                 :            :                   break; // skip others; modern Kbuild uses same comp_dir for them all
    9902                 :            :                 }
    9903                 :            :             }
    9904         [ +  - ]:         84 :         }
    9905                 :            :     }
    9906                 :            : 
    9907                 :            :   // prefixes
    9908         [ +  - ]:         84 :   vector<string> glob_prefixes;
    9909         [ +  - ]:         84 :   glob_prefixes.push_back (s.kernel_build_tree);
    9910 [ +  - ][ +  - ]:         84 :   if (s.kernel_source_tree != "")
    9911         [ +  - ]:         84 :     glob_prefixes.push_back (s.kernel_source_tree);
    9912                 :            : 
    9913                 :            :   // suffixes
    9914         [ +  - ]:         84 :   vector<string> glob_suffixes;
    9915 [ +  - ][ +  - ]:         84 :   glob_suffixes.push_back("include/trace/events/*.h");
                 [ +  - ]
    9916 [ +  - ][ +  - ]:         84 :   glob_suffixes.push_back("include/trace/*.h");
                 [ +  - ]
    9917 [ +  - ][ +  - ]:         84 :   glob_suffixes.push_back("arch/x86/kvm/*trace.h");
                 [ +  - ]
    9918 [ +  - ][ +  - ]:         84 :   glob_suffixes.push_back("fs/xfs/linux-*/xfs_tr*.h");
                 [ +  - ]
    9919 [ +  - ][ +  - ]:         84 :   glob_suffixes.push_back("fs/xfs/xfs_trace*.h");
                 [ +  - ]
    9920                 :            : 
    9921                 :            :   // compute cartesian product
    9922         [ +  - ]:         84 :   vector<string> globs;
    9923         [ +  + ]:        252 :   for (unsigned i=0; i<glob_prefixes.size(); i++)
    9924         [ +  + ]:       1008 :     for (unsigned j=0; j<glob_suffixes.size(); j++)
    9925 [ +  - ][ +  - ]:        840 :       globs.push_back (glob_prefixes[i]+string("/")+glob_suffixes[j]);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    9926                 :            : 
    9927         [ +  - ]:         84 :   set<string> duped_headers;
    9928         [ +  + ]:        924 :   for (unsigned z = 0; z < globs.size(); z++)
    9929                 :            :     {
    9930         [ +  - ]:        840 :       string glob_str = globs[z];
    9931         [ -  + ]:        840 :       if (s.verbose > 3)
    9932 [ #  # ][ #  # ]:          0 :         clog << _("Checking tracepoint glob ") << glob_str << endl;
                 [ #  # ]
    9933                 :            : 
    9934         [ +  - ]:        840 :       int r = glob(glob_str.c_str(), 0, NULL, &trace_glob);
    9935 [ +  - ][ -  + ]:        840 :       if (r == GLOB_NOSPACE || r == GLOB_ABORTED)
    9936 [ #  # ][ #  # ]:          0 :         throw runtime_error("Error globbing tracepoint");
    9937                 :            : 
    9938         [ +  + ]:       9072 :       for (unsigned i = 0; i < trace_glob.gl_pathc; ++i)
    9939                 :            :         {
    9940         [ +  - ]:       8232 :           string header(trace_glob.gl_pathv[i]);
    9941                 :            : 
    9942                 :            :           // filter out a few known "internal-only" headers
    9943 [ +  - ][ +  + ]:      32088 :           if (endswith(header, "/define_trace.h") ||
         [ +  + ][ +  - ]
         [ -  + ][ +  + ]
    9944         [ +  - ]:       8064 :               endswith(header, "/ftrace.h")       ||
    9945         [ +  - ]:       7896 :               endswith(header, "/trace_events.h") ||
    9946         [ +  - ]:       7896 :               endswith(header, "_event_types.h"))
    9947                 :        336 :             continue;
    9948                 :            : 
    9949                 :            :           // skip identical headers from the build and source trees.
    9950         [ +  - ]:       7896 :           size_t root_pos = header.rfind("include/");
    9951 [ +  + ][ +  + ]:      23184 :           if (root_pos != string::npos &&
                 [ +  + ]
    9952 [ +  - ][ +  - ]:      15288 :               !duped_headers.insert(header.substr(root_pos + 8)).second)
         [ +  + ][ +  + ]
                 [ +  - ]
           [ #  #  #  # ]
    9953                 :       3696 :             continue;
    9954                 :            : 
    9955         [ +  - ]:       4200 :           system_headers.push_back(header);
    9956 [ +  - ][ +  + ]:       8232 :         }
    9957                 :        840 :       globfree(&trace_glob);
    9958         [ +  - ]:        840 :     }
    9959                 :            : 
    9960                 :            :   // Build tracequery modules
    9961         [ +  - ]:         84 :   get_tracequery_modules(s, system_headers, tracequery_modules);
    9962                 :            : 
    9963                 :            :   // TODO: consider other sources of tracepoint headers too, like from
    9964                 :            :   // a command-line parameter or some environment or .systemtaprc
    9965                 :            : 
    9966 [ +  - ][ +  - ]:         84 :   dw = new dwflpp(s, tracequery_modules, true);
    9967 [ +  - ][ +  - ]:        592 :   return true;
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
    9968                 :            : }
    9969                 :            : 
    9970                 :            : void
    9971                 :        592 : tracepoint_builder::build(systemtap_session& s,
    9972                 :            :                           probe *base, probe_point *location,
    9973                 :            :                           literal_map_t const& parameters,
    9974                 :            :                           vector<derived_probe*>& finished_results)
    9975                 :            : {
    9976 [ +  - ][ +  - ]:        592 :   if (!init_dw(s))
    9977                 :        592 :     return;
    9978                 :            : 
    9979         [ +  - ]:        592 :   string tracepoint;
    9980 [ +  - ][ -  + ]:        592 :   assert(get_param (parameters, TOK_TRACE, tracepoint));
    9981                 :            : 
    9982         [ +  - ]:        592 :   tracepoint_query q(*dw, tracepoint, base, location, finished_results);
    9983 [ +  - ][ +  - ]:        592 :   dw->iterate_over_modules(&query_module, &q);
                 [ +  - ]
    9984                 :            : }
    9985                 :            : 
    9986                 :            : 
    9987                 :            : // ------------------------------------------------------------------------
    9988                 :            : //  Standard tapset registry.
    9989                 :            : // ------------------------------------------------------------------------
    9990                 :            : 
    9991                 :            : void
    9992                 :       1218 : register_standard_tapsets(systemtap_session & s)
    9993                 :            : {
    9994                 :       1218 :   register_tapset_been(s);
    9995                 :       1218 :   register_tapset_itrace(s);
    9996                 :       1218 :   register_tapset_mark(s);
    9997                 :       1218 :   register_tapset_procfs(s);
    9998                 :       1218 :   register_tapset_timers(s);
    9999                 :       1218 :   register_tapset_netfilter(s);
   10000                 :       1218 :   register_tapset_utrace(s);
   10001                 :            : 
   10002                 :            :   // dwarf-based kprobe/uprobe parts
   10003                 :       1218 :   dwarf_derived_probe::register_patterns(s);
   10004                 :            : 
   10005                 :            :   // XXX: user-space starter set
   10006                 :            :   s.pattern_root->bind_num(TOK_PROCESS)
   10007                 :            :     ->bind_num(TOK_STATEMENT)->bind(TOK_ABSOLUTE)
   10008                 :            :     ->bind_privilege(pr_all)
   10009                 :       1218 :     ->bind(new uprobe_builder ());
   10010                 :            :   s.pattern_root->bind_num(TOK_PROCESS)
   10011                 :            :     ->bind_num(TOK_STATEMENT)->bind(TOK_ABSOLUTE)->bind(TOK_RETURN)
   10012                 :            :     ->bind_privilege(pr_all)
   10013                 :       1218 :     ->bind(new uprobe_builder ());
   10014                 :            : 
   10015                 :            :   // kernel tracepoint probes
   10016                 :            :   s.pattern_root->bind(TOK_KERNEL)->bind_str(TOK_TRACE)
   10017                 :       1218 :     ->bind(new tracepoint_builder());
   10018                 :            : 
   10019                 :            :   // Kprobe based probe
   10020                 :            :   s.pattern_root->bind(TOK_KPROBE)->bind_str(TOK_FUNCTION)
   10021                 :       1218 :      ->bind(new kprobe_builder());
   10022                 :            :   s.pattern_root->bind(TOK_KPROBE)->bind_str(TOK_FUNCTION)->bind(TOK_CALL)
   10023                 :       1218 :      ->bind(new kprobe_builder());
   10024                 :            :   s.pattern_root->bind(TOK_KPROBE)->bind_str(TOK_MODULE)
   10025                 :       1218 :      ->bind_str(TOK_FUNCTION)->bind(new kprobe_builder());
   10026                 :            :   s.pattern_root->bind(TOK_KPROBE)->bind_str(TOK_MODULE)
   10027                 :       1218 :      ->bind_str(TOK_FUNCTION)->bind(TOK_CALL)->bind(new kprobe_builder());
   10028                 :            :   s.pattern_root->bind(TOK_KPROBE)->bind_str(TOK_FUNCTION)->bind(TOK_RETURN)
   10029                 :       1218 :      ->bind(new kprobe_builder());
   10030                 :            :   s.pattern_root->bind(TOK_KPROBE)->bind_str(TOK_FUNCTION)->bind(TOK_RETURN)
   10031                 :       1218 :      ->bind_num(TOK_MAXACTIVE)->bind(new kprobe_builder());
   10032                 :            :   s.pattern_root->bind(TOK_KPROBE)->bind_str(TOK_MODULE)
   10033                 :       1218 :      ->bind_str(TOK_FUNCTION)->bind(TOK_RETURN)->bind(new kprobe_builder());
   10034                 :            :   s.pattern_root->bind(TOK_KPROBE)->bind_str(TOK_MODULE)
   10035                 :            :      ->bind_str(TOK_FUNCTION)->bind(TOK_RETURN)
   10036                 :       1218 :      ->bind_num(TOK_MAXACTIVE)->bind(new kprobe_builder());
   10037                 :            :   s.pattern_root->bind(TOK_KPROBE)->bind_num(TOK_STATEMENT)
   10038                 :       1218 :       ->bind(TOK_ABSOLUTE)->bind(new kprobe_builder());
   10039                 :            : 
   10040                 :            :   //Hwbkpt based probe
   10041                 :            :   // NB: we formerly registered the probe point types only if the kernel configuration
   10042                 :            :   // allowed it.  However, we get better error messages if we allow probes to resolve.
   10043                 :            :   s.pattern_root->bind(TOK_KERNEL)->bind_num(TOK_HWBKPT)
   10044                 :       1218 :     ->bind(TOK_HWBKPT_WRITE)->bind(new hwbkpt_builder());
   10045                 :            :   s.pattern_root->bind(TOK_KERNEL)->bind_str(TOK_HWBKPT)
   10046                 :       1218 :     ->bind(TOK_HWBKPT_WRITE)->bind(new hwbkpt_builder());
   10047                 :            :   s.pattern_root->bind(TOK_KERNEL)->bind_num(TOK_HWBKPT)
   10048                 :       1218 :     ->bind(TOK_HWBKPT_RW)->bind(new hwbkpt_builder());
   10049                 :            :   s.pattern_root->bind(TOK_KERNEL)->bind_str(TOK_HWBKPT)
   10050                 :       1218 :     ->bind(TOK_HWBKPT_RW)->bind(new hwbkpt_builder());
   10051                 :            :   s.pattern_root->bind(TOK_KERNEL)->bind_num(TOK_HWBKPT)
   10052                 :       1218 :     ->bind_num(TOK_LENGTH)->bind(TOK_HWBKPT_WRITE)->bind(new hwbkpt_builder());
   10053                 :            :   s.pattern_root->bind(TOK_KERNEL)->bind_num(TOK_HWBKPT)
   10054                 :       1218 :     ->bind_num(TOK_LENGTH)->bind(TOK_HWBKPT_RW)->bind(new hwbkpt_builder());
   10055                 :            :   // length supported with address only, not symbol names
   10056                 :            : 
   10057                 :            :   //perf event based probe
   10058                 :       1218 :   register_tapset_perf(s);
   10059                 :       1218 : }
   10060                 :            : 
   10061                 :            : 
   10062                 :            : vector<derived_probe_group*>
   10063                 :       1932 : all_session_groups(systemtap_session& s)
   10064                 :            : {
   10065                 :       1932 :   vector<derived_probe_group*> g;
   10066                 :            : 
   10067                 :            : #define DOONE(x) \
   10068                 :            :   if (s. x##_derived_probes) \
   10069                 :            :     g.push_back ((derived_probe_group*)(s. x##_derived_probes))
   10070                 :            : 
   10071                 :            :   // Note that order *is* important here.  We want to make sure we
   10072                 :            :   // register (actually run) begin probes before any other probe type
   10073                 :            :   // is run.  Similarly, when unregistering probes, we want to
   10074                 :            :   // unregister (actually run) end probes after every other probe type
   10075                 :            :   // has be unregistered.  To do the latter,
   10076                 :            :   // c_unparser::emit_module_exit() will run this list backwards.
   10077 [ +  + ][ +  - ]:       1932 :   DOONE(be);
   10078 [ +  + ][ +  - ]:       1932 :   DOONE(dwarf);
   10079 [ +  + ][ +  - ]:       1932 :   DOONE(uprobe);
   10080 [ +  + ][ +  - ]:       1932 :   DOONE(timer);
   10081 [ +  + ][ +  - ]:       1932 :   DOONE(profile);
   10082 [ -  + ][ #  # ]:       1932 :   DOONE(mark);
   10083 [ +  + ][ +  - ]:       1932 :   DOONE(tracepoint);
   10084 [ +  + ][ +  - ]:       1932 :   DOONE(kprobe);
   10085 [ +  + ][ +  - ]:       1932 :   DOONE(hwbkpt);
   10086 [ +  + ][ +  - ]:       1932 :   DOONE(perf);
   10087 [ +  + ][ +  - ]:       1932 :   DOONE(hrtimer);
   10088 [ +  + ][ +  - ]:       1932 :   DOONE(procfs);
   10089 [ +  + ][ +  - ]:       1932 :   DOONE(netfilter);
   10090                 :            : 
   10091                 :            :   // Another "order is important" item.  We want to make sure we
   10092                 :            :   // "register" the dummy task_finder probe group after all probe
   10093                 :            :   // groups that use the task_finder.
   10094 [ +  + ][ +  - ]:       1932 :   DOONE(utrace);
   10095 [ -  + ][ #  # ]:       1932 :   DOONE(itrace);
   10096 [ -  + ][ #  # ]:       1932 :   DOONE(dynprobe);
   10097 [ +  + ][ +  - ]:       1932 :   DOONE(task_finder);
   10098                 :            : #undef DOONE
   10099                 :       1932 :   return g;
   10100 [ +  - ][ +  - ]:       7242 : }
   10101                 :            : 
   10102                 :            : /* vim: set sw=2 ts=8 cino=>4,n-2,{2,^-2,t0,(0,u0,w1,M1 : */

Generated by: LCOV version 1.9