Ejemplo n.º 1
0
static void
stapkp_add_missed(struct stap_dwarf_probe *sdp)
{
   if (sdp->return_p) {

      struct kretprobe *krp = &sdp->kprobe->u.krp;

      atomic_add(krp->nmissed, skipped_count());
#ifdef STP_TIMING
      if (krp->nmissed)
         _stp_warn ("Skipped due to missed kretprobe/1 on '%s': %d\n",
                    sdp->probe->pp, krp->nmissed);
#endif

      atomic_add(krp->kp.nmissed, skipped_count());
#ifdef STP_TIMING
      if (krp->kp.nmissed)
         _stp_warn ("Skipped due to missed kretprobe/2 on '%s': %lu\n",
                    sdp->probe->pp, krp->kp.nmissed);
#endif

   } else {

      struct kprobe *kp = &sdp->kprobe->u.kp;

      atomic_add (kp->nmissed, skipped_count());
#ifdef STP_TIMING
      if (kp->nmissed)
         _stp_warn ("Skipped due to missed kprobe on '%s': %lu\n",
                    sdp->probe->pp, kp->nmissed);
#endif
   }
}
Ejemplo n.º 2
0
static int
stapkp_init(struct stap_kprobe_probe *probes,
            size_t nprobes)
{
    size_t i;

#ifdef STAPCONF_KALLSYMS_ON_EACH_SYMBOL
    // If we have any symbol_name+offset probes, we need to try to
    // convert those into address-based probes.
    size_t probe_max = 0;
    for (i = 0; i < nprobes; i++) {
        struct stap_kprobe_probe *skp = &probes[i];

        if (! skp->symbol_name)
            continue;
        ++probe_max;
    }
    if (probe_max > 0) {
        // Here we're going to try to convert any symbol_name+offset
        // probes into address probes.
        struct stapkp_symbol_data sd;
        dbug_stapkp("looking up %lu probes\n", probe_max);
        sd.probes = probes;
        sd.nprobes = nprobes;
        sd.probe_max = probe_max;
        sd.modname = NULL;
        preempt_disable();
        kallsyms_on_each_symbol(stapkp_symbol_callback, &sd);
        preempt_enable();
        dbug_stapkp("found %lu probes\n", sd.probe_max);
    }
#endif

    for (i = 0; i < nprobes; i++) {
        struct stap_kprobe_probe *skp = &probes[i];
        int rc = 0;

        rc = stapkp_register_probe(skp);
        if (rc == 1) // failed to relocate addr?
            continue; // don't fuss about it, module probably not loaded

        // NB: We keep going even if a probe failed to register (PR6749). We only
        // warn about it if it wasn't optional and isn't in a module.
        if (rc && !skp->optional_p
                && ((skp->module == NULL) || skp->module[0] == '\0'
                    || strcmp(skp->module, "kernel") == 0)) {
            if (skp->symbol_name)
                _stp_warn("probe %s (%s+%u) registration error (rc %d)",
                          skp->probe->pp, skp->symbol_name, skp->offset, rc);
            else
                _stp_warn("probe %s (address 0x%lx) registration error (rc %d)",
                          skp->probe->pp, stapkp_relocate_addr(skp), rc);
        }
    }

    return 0;
}
Ejemplo n.º 3
0
/* Validate user module based on build-id (if present) */
static int _stp_usermodule_check(struct task_struct *tsk, const char *path_name, unsigned long addr)
{
  struct _stp_module *m = NULL;
  unsigned long notes_addr;
  unsigned i, j;
  unsigned char practice_id_bits[MAXSTRINGLEN];
  unsigned long vm_end = 0;

#ifdef STP_NO_BUILDID_CHECK
  return 0;
#endif

  for (i = 0; i < _stp_num_modules; i++)
    {
      m = _stp_modules[i];
      if (strcmp(path_name, _stp_modules[i]->path) != 0)
	continue;
      if (m->build_id_len > 0) {
	int ret, build_id_len;

	notes_addr = addr + m->build_id_offset /* + m->module_base */;

        dbug_sym(1, "build-id validation [%d %s] address=%#lx build_id_offset=%#lx\n",
                 tsk->pid, m->path, addr, m->build_id_offset);

	if (notes_addr <= addr) {
	  _stp_warn ("build-id address %lx < base %lx\n", notes_addr, addr);
	  continue;
	}
	return _stp_build_id_check (m, notes_addr, tsk);
      }
    }

  return 0;
}
Ejemplo n.º 4
0
/* Iterate over _stp_modules, looking for a kernel module of given
   name.  Run build-id checking for it.  Return 0 on ok. */
static int _stp_kmodule_check (const char *name)
{
  struct _stp_module *m = NULL;
  unsigned long notes_addr, base_addr;
  unsigned i,j;

#ifdef STP_NO_BUILDID_CHECK
  return 0;
#endif

  for (i = 0; i < _stp_num_modules; i++)
    {
      m = _stp_modules[i];
      if (strcmp (name, m->name)) continue;

      if (m->build_id_len > 0 && m->notes_sect != 0) {
          dbug_sym(1, "build-id validation [%s]\n", m->name);

          /* notes end address */
          notes_addr = m->notes_sect + m->build_id_offset;
          base_addr = m->notes_sect;

          if (notes_addr <= base_addr) { /* shouldn't happen */
              _stp_warn ("build-id address %lx < base %lx\n",
                  notes_addr, base_addr);
              continue;
          }
          return _stp_build_id_check (m, notes_addr, NULL);
      } /* end checking */
    } /* end loop */

  return 0; /* name not found */
}
Ejemplo n.º 5
0
static void _stp_handle_start(struct _stp_msg_start *st)
{
	int handle_startup;

	mutex_lock(&_stp_transport_mutex);
	handle_startup = (! _stp_start_called && ! _stp_exit_called);
	_stp_start_called = 1;
	mutex_unlock(&_stp_transport_mutex);
	
	if (handle_startup) {
		dbug_trans(1, "stp_handle_start\n");

#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,23) // linux commit #5f4352fb
#if LINUX_VERSION_CODE <  KERNEL_VERSION(2,6,29) // linux commit #9be260a6
#ifdef STAPCONF_VM_AREA
		{ /* PR9740: workaround for kernel valloc bug. */
                  /* PR14611: not required except within above kernel range. */
			void *dummy;
#ifdef STAPCONF_VM_AREA_PTE
			dummy = alloc_vm_area (PAGE_SIZE, NULL);
#else
			dummy = alloc_vm_area (PAGE_SIZE);
#endif
			free_vm_area (dummy);
		}
#endif
#endif
#endif

		_stp_target = st->target;
		st->res = systemtap_module_init();
		if (st->res == 0)
			_stp_probes_started = 1;

                /* Register the module notifier. */
                if (!_stp_module_notifier_active) {
                        int rc = register_module_notifier(& _stp_module_notifier_nb);
                        if (rc == 0)
                                _stp_module_notifier_active = 1;
                        else
                                _stp_warn ("Cannot register module notifier (%d)\n", rc);
                }

		/* Called from the user context in response to a proc
		   file write (in _stp_ctl_write_cmd), so may notify
		   the reader directly. */
		_stp_ctl_send_notify(STP_START, st, sizeof(*st));

		/* Register the panic notifier. */
#if STP_TRANSPORT_VERSION == 2
		atomic_notifier_chain_register(&panic_notifier_list, &_stp_module_panic_notifier_nb);
#endif
	}
}
Ejemplo n.º 6
0
static int _stp_stat_calc_buckets(int stop, int start, int interval)
{
	int buckets;

	if (interval == 0) {
		_stp_warn("histogram: interval cannot be zero.\n");
		return 0;
	}

	/* don't forget buckets for underflow and overflow */
	buckets = (stop - start) / interval + 3;

	if (buckets > STP_MAX_BUCKETS || buckets < 3) {
		_stp_warn("histogram: Number of buckets must be between 1 and %d\n"
			  "Number_of_buckets = (stop - start) / interval.\n"
			  "Please adjust your start, stop, and interval values.\n",
			  STP_MAX_BUCKETS-2);
		return 0;
	}
	return buckets;
}
Ejemplo n.º 7
0
/* Validate all-modules + kernel based on build-id (if present).
*  The completed case is the following combination:
*	   Debuginfo 		 Module			         Kernel	
* 			   X				X
* 	has build-id/not	unloaded		      has build-id/not	
*				loaded && (has build-id/not)  
*
*  NB: build-id exists only if ld>=2.18 and kernel>= 2.6.23
*/
static int _stp_module_check(void)
{
  struct _stp_module *m = NULL;
  unsigned long notes_addr, base_addr;
  unsigned i,j;
  int rc = 0;

#ifdef STP_NO_BUILDID_CHECK
  return 0;
#endif

  for (i = 0; i < _stp_num_modules; i++)
    {
      m = _stp_modules[i];

      if (m->build_id_len > 0 && m->notes_sect != 0) {
          dbug_sym(1, "build-id validation [%s]\n", m->name); /* kernel only */

          /* skip userspace program */
          if (m->name[0] != '/') continue;

          /* notes end address */
          if (!strcmp(m->name, "kernel")) {
              notes_addr = _stp_kmodule_relocate("kernel",
                  "_stext", m->build_id_offset);
              base_addr = _stp_kmodule_relocate("kernel",
                  "_stext", 0);
          } else {
              notes_addr = m->notes_sect + m->build_id_offset;
              base_addr = m->notes_sect;
          }

          if (notes_addr <= base_addr) { /* shouldn't happen */
              _stp_warn ("build-id address %lx <= base %lx\n",
                  notes_addr, base_addr);
              continue;
          }

          rc |=  _stp_build_id_check (m, notes_addr, NULL);
      } /* end checking */
    } /* end loop */

  return rc;
}
Ejemplo n.º 8
0
/* Validate user module based on build-id (if present) */
static int _stp_usermodule_check(struct task_struct *tsk, const char *path_name, unsigned long addr)
{
  struct _stp_module *m = NULL;
  unsigned long notes_addr;
  unsigned i, j;
  unsigned char practice_id_bits[MAXSTRINGLEN];
  unsigned long vm_end = 0;

#ifdef STP_NO_BUILDID_CHECK
  return 0;
#endif

  WARN_ON(!path_name || path_name[0]!='/'); // user-space only

  for (i = 0; i < _stp_num_modules; i++)
    {
      m = _stp_modules[i];

      /* PR16406 must be unique userspace name (/-prefixed path); it's also in m->name */
      if (strcmp(path_name, m->path) != 0) continue;

      if (m->build_id_len > 0) {
	int ret, build_id_len;

	notes_addr = addr + m->build_id_offset /* + m->module_base */;

        dbug_sym(1, "build-id validation [%d %s] address=%#lx build_id_offset=%#lx\n",
                 tsk->pid, m->path, addr, m->build_id_offset);

	if (notes_addr <= addr) {
	  _stp_warn ("build-id address %lx < base %lx\n", notes_addr, addr);
	  continue;
	}
	return _stp_build_id_check (m, notes_addr, tsk);
      }
    }

  return 0; /* not found */
}
Ejemplo n.º 9
0
/* Iterate over _stp_modules, looking for a kernel module of given
   name.  Run build-id checking for it.  Return 0 on ok. */
static int _stp_kmodule_check (const char *name)
{
  struct _stp_module *m = NULL;
  unsigned long notes_addr, base_addr;
  unsigned i,j;

#ifdef STP_NO_BUILDID_CHECK
  return 0;
#endif

  WARN_ON(!name || name[0]=='/'); // non-userspace only

  for (i = 0; i < _stp_num_modules; i++)
    {
      m = _stp_modules[i];

      /* PR16406 must be unique kernel module name (non-/-prefixed path) */
      if (strcmp (name, m->name)) continue;

      if (m->build_id_len > 0 && m->notes_sect != 0) {
          dbug_sym(1, "build-id validation [%s]\n", m->name);

          /* notes end address */
          notes_addr = m->notes_sect + m->build_id_offset;
          base_addr = m->notes_sect;

          if (notes_addr <= base_addr) { /* shouldn't happen */
              _stp_warn ("build-id address %lx < base %lx\n",
                  notes_addr, base_addr);
              continue;
          }
          return _stp_build_id_check (m, notes_addr, NULL);
      } /* end checking */
    } /* end loop */

  return 0; /* not found */
}
Ejemplo n.º 10
0
static int
stapkp_init(struct stap_dwarf_probe *probes,
            size_t nprobes)
{
   size_t i;
   for (i = 0; i < nprobes; i++) {

      struct stap_dwarf_probe *sdp = &probes[i];
      int rc = 0;

      rc = stapkp_register_probe(sdp);
      if (rc == 1) // failed to relocate addr?
         continue; // don't fuss about it, module probably not loaded

      // NB: We keep going even if a probe failed to register (PR6749). We only
      // warn about it if it wasn't optional.
      if (rc && !sdp->optional_p) {
         _stp_warn("probe %s (address 0x%lx) registration error (rc %d)",
                   sdp->probe->pp, stapkp_relocate_addr(sdp), rc);
      }
   }

   return 0;
}
Ejemplo n.º 11
0
static int _stp_build_id_check (struct _stp_module *m,
				unsigned long notes_addr,
				struct task_struct *tsk)
{
  int j;

  for (j = 0; j < m->build_id_len; j++) {
    /* Use set_fs / get_user to access conceivably invalid addresses.
     * If loc2c-runtime.h were more easily usable, a deref() loop
     * could do it too. */
    mm_segment_t oldfs = get_fs();
    int rc;
    unsigned char theory, practice = 0;

#ifdef STAPCONF_PROBE_KERNEL
    if (!tsk) {
      theory = m->build_id_bits[j];
      set_fs(KERNEL_DS);
      rc = probe_kernel_read(&practice, (void*)(notes_addr + j), 1);
    }
    else
#endif
    {
      theory = m->build_id_bits[j];
      set_fs (tsk ? USER_DS : KERNEL_DS);

      /*
       * Why check CONFIG_UTRACE here? If we're using real in-kernel
       * utrace, we can always just call get_user() (since we're
       * either reading kernel memory or tsk == current).
       *
       * Since we're only reading here, we can call
       * __access_process_vm_noflush(), which only calls things that
       * are exported.
       */
#ifdef CONFIG_UTRACE
      rc = get_user(practice, ((unsigned char*)(void*)(notes_addr + j)));
#else
      if (!tsk || tsk == current) {
	rc = get_user(practice, ((unsigned char*)(void*)(notes_addr + j)));
      }
      else {
	rc = (__access_process_vm_noflush(tsk, (notes_addr + j), &practice,
					  1, 0) != 1);
      }
#endif
    }
    set_fs(oldfs);

    if (rc || (theory != practice)) {
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27)
      _stp_error ("Build-id mismatch [man error::buildid]: \"%s\" byte %d (0x%02x vs 0x%02x) address %#lx rc %d\n",
		  m->path, j, theory, practice, notes_addr, rc);
      return 1;
#else
      /* This branch is a surrogate for kernels affected by Fedora bug
       * #465873. */
      _stp_warn (KERN_WARNING
		 "Build-id mismatch [man error::buildid]: \"%s\" byte %d (0x%02x vs 0x%02x) rc %d\n",
		 m->path, j, theory, practice, rc);
#endif
      break;
    } /* end mismatch */
  } /* end per-byte check loop */
  return 0;
}
Ejemplo n.º 12
0
static int stap_uprobe_change_plus (struct task_struct *tsk, unsigned long relocation, unsigned long length, const struct stap_uprobe_tf *stf, unsigned long offset, unsigned long vm_flags) {
  int tfi = (stf - stap_uprobe_finders);
  int spec_index;
  /* iterate over stap_uprobe_spec[] that use this same stap_uprobe_tf */
  for (spec_index=0; spec_index<sizeof(stap_uprobe_specs)/sizeof(stap_uprobe_specs[0]); spec_index++) {
    int handled_p = 0;
    int slotted_p = 0;
    const struct stap_uprobe_spec *sups = &stap_uprobe_specs [spec_index];
    struct stap_uprobe *sup;
    pid_t sdt_sem_pid;
    int rc = 0;
    int i;
    int pci;
    
    if (likely(sups->tfi != tfi)) continue;
    /* skip probes with an address beyond this map event; should not 
       happen unless a shlib/exec got mmapped in weirdly piecemeal */
    if (likely((vm_flags & VM_EXEC) && sups->address >= length)) continue;

    /* Found a uprobe_spec for this stap_uprobe_tf.  Need to lock the
       stap_uprobes[] array to allocate a free spot, but then we can
       unlock and do the register_*probe subsequently. */

    mutex_lock (& stap_uprobes_lock);
    for (i=0; i<MAXUPROBES; i++) { /* XXX: slow linear search */
      sup = & stap_uprobes[i];

      /* register new uprobe
	 We make two passes for semaphores;
	 see stap_uprobe_change_semaphore_plus */
 
      if (sup->spec_index < 0 || (sups->sdt_sem_offset && vm_flags & VM_WRITE && sup->spec_index == spec_index)) {
        #if (UPROBES_API_VERSION < 2)
	/* See PR6829 comment. */
        if (sup->spec_index == -1 && sup->up.kdata != NULL) continue;
        else if (sup->spec_index == -2 && sup->urp.u.kdata != NULL) continue;
        #endif
        sup->spec_index = spec_index;
        slotted_p = 1;
        break;
      }
    }
    mutex_unlock (& stap_uprobes_lock);
    #ifdef DEBUG_UPROBES
    _stp_dbug(__FUNCTION__,__LINE__, "+uprobe spec %d idx %d process %s[%d] addr %p pp %s\n", spec_index, (slotted_p ? i : -1), tsk->comm, tsk->tgid, (void*)(relocation+sups->address), sups->probe->pp);
    #endif

    /* NB: check for user-module build-id only if we have a pathname
       at all; for a process(PID#).* probe, we may not.  If at some
       point we map process(PID#) to process("/proc/PID#/exe"), we'll
       get a pathname. */
    if (stf->pathname)
            if ((rc = _stp_usermodule_check(tsk, stf->pathname, relocation)))
                    return rc;

    /* Here, slotted_p implies that `i' points to the single
       stap_uprobes[] element that has been slotted in for registration
       or unregistration processing.  !slotted_p implies that the table
       was full (registration; MAXUPROBES) or that no matching entry was
       found (unregistration; should not happen). */

    sdt_sem_pid = (sups->return_p ? sup->urp.u.pid : sup->up.pid);
    if (sups->sdt_sem_offset && (sdt_sem_pid != tsk->tgid || sup->sdt_sem_address == 0)) {
      /* If the probe is in an ET_EXEC binary, then the sdt_sem_offset already
       * is a real address.  But stap_uprobe_process_found calls us in this
       * case with relocation=offset=0, so we don't have to worry about it.  */
      sup->sdt_sem_address = (relocation - offset) + sups->sdt_sem_offset;
    } /* sdt_sem_offset */

    for (pci=0; pci < sups->perf_counters_dim; pci++) {
	if ((sups->perf_counters)[pci] > -1)
	  _stp_perf_read_init ((sups->perf_counters)[pci], tsk);
      }

    if (slotted_p) {
      struct stap_uprobe *sup = & stap_uprobes[i];
      if (sups->return_p) {
        sup->urp.u.pid = tsk->tgid;
        sup->urp.u.vaddr = relocation + sups->address;
        sup->urp.handler = &enter_uretprobe_probe;
        rc = register_uretprobe (& sup->urp);
      } else {
        sup->up.pid = tsk->tgid;
        sup->up.vaddr = relocation + sups->address;
        sup->up.handler = &enter_uprobe_probe;
        rc = register_uprobe (& sup->up);
      }

      /* The u*probe failed to register.  However, if we got EEXIST,
       * that means that the u*probe is already there, so just ignore
       * the error.  This could happen if CLONE_THREAD or CLONE_VM was
       * used. */
      if (rc != 0 && rc != -EEXIST) {
        _stp_warn ("u*probe failed %s[%d] '%s' addr %p rc %d\n", tsk->comm, tsk->tgid, sups->probe->pp, (void*)(relocation + sups->address), rc);
	/* NB: we need to release this slot,
	   so we need to borrow the mutex temporarily. */
        mutex_lock (& stap_uprobes_lock);
        sup->spec_index = -1;
	sup->sdt_sem_address = 0;
        mutex_unlock (& stap_uprobes_lock);
      } else {
        handled_p = 1;
      }
    }
    /* NB: handled_p implies slotted_p */
    if (unlikely (! handled_p)) {
      #ifdef STP_TIMING
      atomic_inc (skipped_count_uprobe_reg());
      #endif
      /* NB: duplicates common_entryfn_epilogue,
	 but then this is not a probe entry fn epilogue. */
#ifndef STAP_SUPPRESS_HANDLER_ERRORS
      if (unlikely (atomic_inc_return (skipped_count()) > MAXSKIPPED)) {
        if (unlikely (pseudo_atomic_cmpxchg(session_state(), STAP_SESSION_RUNNING, STAP_SESSION_ERROR) == STAP_SESSION_RUNNING))
          _stp_error ("Skipped too many probes, check MAXSKIPPED or try again with stap -t for more details.");
      }
#endif
    }
  }  /* close iteration over stap_uprobe_spec[] */
  return 0; /* XXX: or rc? */
}
Ejemplo n.º 13
0
static int stap_uprobe_change_plus (struct task_struct *tsk, unsigned long relocation, unsigned long length, const struct stap_uprobe_tf *stf, unsigned long offset, unsigned long vm_flags) {
  int tfi = (stf - stap_uprobe_finders);
  int spec_index;
  /* iterate over stap_uprobe_spec[] that use this same stap_uprobe_tf */
  for (spec_index=0; spec_index<sizeof(stap_uprobe_specs)/sizeof(stap_uprobe_specs[0]); spec_index++) {
    int handled_p = 0;
    int slotted_p = 0;
    const struct stap_uprobe_spec *sups = &stap_uprobe_specs [spec_index];
    struct stap_uprobe *sup;
    pid_t sdt_sem_pid;
    int rc = 0;
    int i;
    if (likely(sups->tfi != tfi)) continue;
    /* skip probes with an address beyond this map event; should not 
       happen unless a shlib/exec got mmapped in weirdly piecemeal */
    if (likely((vm_flags & VM_EXEC) && sups->address >= length)) continue;

    /* Found a uprobe_spec for this stap_uprobe_tf.  Need to lock the
       stap_uprobes[] array to allocate a free spot, but then we can
       unlock and do the register_*probe subsequently. */

    mutex_lock (& stap_uprobes_lock);
    for (i=0; i<MAXUPROBES; i++) { /* XXX: slow linear search */
      sup = & stap_uprobes[i];

      /* register new uprobe
	 We make two passes for semaphores;
	 see _stap_uprobe_change_semaphore_plus */
 
      if (sup->spec_index < 0 || (sups->sdt_sem_offset && vm_flags & VM_WRITE && sup->spec_index == spec_index)) {
        #if (UPROBES_API_VERSION < 2)
	/* See PR6829 comment. */
        if (sup->spec_index == -1 && sup->up.kdata != NULL) continue;
        else if (sup->spec_index == -2 && sup->urp.u.kdata != NULL) continue;
        #endif
        sup->spec_index = spec_index;
        slotted_p = 1;
        break;
      }
    }
    mutex_unlock (& stap_uprobes_lock);
    #ifdef DEBUG_UPROBES
    _stp_dbug(__FUNCTION__,__LINE__, "+uprobe spec %d idx %d process %s[%d] addr %p pp %s\n", spec_index, (slotted_p ? i : -1), tsk->comm, tsk->tgid, (void*)(relocation+sups->address), sups->probe.pp);
    #endif

    /* Here, slotted_p implies that `i' points to the single
       stap_uprobes[] element that has been slotted in for registration
       or unregistration processing.  !slotted_p implies that the table
       was full (registration; MAXUPROBES) or that no matching entry was
       found (unregistration; should not happen). */

    sdt_sem_pid = (sups->return_p ? sup->urp.u.pid : sup->up.pid);
    if (sups->sdt_sem_offset && (sdt_sem_pid != tsk->tgid || sup->sdt_sem_address == 0)) {
      /* If the probe is in the executable itself, the offset *is* the address. */
      if (vm_flags & VM_EXECUTABLE) {
        sup->sdt_sem_address = relocation + sups->sdt_sem_offset;
      }
      else {
        sup->sdt_sem_address = (relocation - offset) + sups->sdt_sem_offset;
      }
    } /* sdt_sem_offset */
    if (slotted_p) {
      struct stap_uprobe *sup = & stap_uprobes[i];
      if (sups->return_p) {
        sup->urp.u.pid = tsk->tgid;
        sup->urp.u.vaddr = relocation + sups->address;
        sup->urp.handler = &enter_uretprobe_probe;
        rc = register_uretprobe (& sup->urp);
      } else {
        sup->up.pid = tsk->tgid;
        sup->up.vaddr = relocation + sups->address;
        sup->up.handler = &enter_uprobe_probe;
        rc = register_uprobe (& sup->up);
      }
      if (rc) { /* failed to register */
        _stp_warn ("u*probe failed %s[%d] '%s' addr %p rc %d\n", tsk->comm, tsk->tgid, sups->probe.pp, (void*)(relocation + sups->address), rc);
	/* NB: we need to release this slot,
	   so we need to borrow the mutex temporarily. */
        mutex_lock (& stap_uprobes_lock);
        sup->spec_index = -1;
        mutex_unlock (& stap_uprobes_lock);
      } else {
        handled_p = 1;
      }
    }
    /* NB: handled_p implies slotted_p */
    if (unlikely (! handled_p)) {
      #ifdef STP_TIMING
      atomic_inc (& skipped_count_uprobe_reg);
      #endif
      /* NB: duplicates common_entryfn_epilogue,
	 but then this is not a probe entry fn epilogue. */
      if (unlikely (atomic_inc_return (& skipped_count) > MAXSKIPPED)) {
        if (unlikely (pseudo_atomic_cmpxchg(& session_state, STAP_SESSION_RUNNING, STAP_SESSION_ERROR) == STAP_SESSION_RUNNING))
        _stp_error ("Skipped too many probes, check MAXSKIPPED or try again with stap -t for more details.");
      }
    }
  }  /* close iteration over stap_uprobe_spec[] */
  return 0; /* XXX: or rc? */
}
Ejemplo n.º 14
0
/* when someone does /sbin/rmmod on a loaded systemtap module. */
static void _stp_cleanup_and_exit(int send_exit)
{
	int handle_exit;
	int start_finished;

	mutex_lock(&_stp_transport_mutex);
	handle_exit = (_stp_start_called && ! _stp_exit_called);
	_stp_exit_called = 1;
	mutex_unlock(&_stp_transport_mutex);

	/* Note, we can be sure that the startup sequence has finished
           if handle_exit is true because it depends on _stp_start_called
	   being set to true. _stp_start_called can only be set to true
	   in _stp_handle_start() in response to a _STP_START message on
	   the control channel. Only one writer can have the control
	   channel open at a time, so the whole startup sequence in
	   _stp_handle_start() has to be completed before another message
	   can be send.  _stp_cleanup_and_exit() can only be called through
	   either a _STP_EXIT message, which cannot arrive while _STP_START
	   is still being handled, or when the module is unloaded. The
	   module can only be unloaded when there are no more users that
	   keep the control channel open.  */
	if (handle_exit) {
		int failures;

	        /* Unregister the module notifier. */
	        if (_stp_module_notifier_active) {
	                _stp_module_notifier_active = 0;
	                (void) unregister_module_notifier(& _stp_module_notifier_nb);
	                /* -ENOENT is possible, if we were not already registered */
	        }

                dbug_trans(1, "cleanup_and_exit (%d)\n", send_exit);
		_stp_exit_flag = 1;

		if (_stp_probes_started) {
			dbug_trans(1, "calling systemtap_module_exit\n");
			/* tell the stap-generated code to unload its probes, etc */
			systemtap_module_exit();
			dbug_trans(1, "done with systemtap_module_exit\n");
		}

		failures = atomic_read(&_stp_transport_failures);
		if (failures)
			_stp_warn("There were %d transport failures.\n", failures);

		dbug_trans(1, "*** calling _stp_transport_data_fs_stop ***\n");
		_stp_transport_data_fs_stop();

		dbug_trans(1, "ctl_send STP_EXIT\n");
		if (send_exit) {
			/* send_exit is only set to one if called from
			   _stp_ctl_write_cmd() in response to a write
			   to the proc cmd file, so in user context. It
			   is safe to immediately notify the reader.  */
			_stp_ctl_send_notify(STP_EXIT, NULL, 0);
		}
		dbug_trans(1, "done with ctl_send STP_EXIT\n");

		/* Unregister the panic notifier. */
#if STP_TRANSPORT_VERSION == 2
		atomic_notifier_chain_unregister(&panic_notifier_list, &_stp_module_panic_notifier_nb);
#endif
	}
}
Ejemplo n.º 15
0
/* mmap callback, will match new vma with _stp_module or register vma name. */
static int _stp_vma_mmap_cb(struct stap_task_finder_target *tgt,
			    struct task_struct *tsk,
			    char *path, struct dentry *dentry,
			    unsigned long addr,
			    unsigned long length,
			    unsigned long offset,
			    unsigned long vm_flags)
{
	int i, res;
	struct _stp_module *module = NULL;
	const char *name = (dentry != NULL) ? dentry->d_name.name : NULL;

#ifdef DEBUG_TASK_FINDER_VMA
	_stp_dbug(__FUNCTION__, __LINE__,
		  "mmap_cb: tsk %d:%d path %s, addr 0x%08lx, length 0x%08lx, offset 0x%lx, flags 0x%lx\n",
		  tsk->pid, tsk->tgid, path, addr, length, offset, vm_flags);
#endif
	// We are only interested in the first load of the whole module that
	// is executable. We register whether or not we know the module,
	// so we can later lookup the name given an address for this task.
	if (path != NULL && offset == 0 && (vm_flags & VM_EXEC)) {
		for (i = 0; i < _stp_num_modules; i++) {
			if (strcmp(path, _stp_modules[i]->path) == 0)
			{
#ifdef DEBUG_TASK_FINDER_VMA
			  _stp_dbug(__FUNCTION__, __LINE__,
				    "vm_cb: matched path %s to module (sec: %s)\n",
				    path, _stp_modules[i]->sections[0].name);
#endif
			  module = _stp_modules[i];
			  /* XXX We really only need to register .dynamic
			     sections, but .absolute exes are also necessary
			     atm. */
			  res = stap_add_vma_map_info(tsk->group_leader,
						      addr, addr + length,
						      name, module);
			  /* Warn, but don't error out. */
			  if (res != 0)
				_stp_warn ("Couldn't register module '%s' for pid %d\n", _stp_modules[i]->path, tsk->group_leader->pid);
			  return 0;
			}
		}

		/* None of the tracked modules matched, register without,
		 * to make sure we can lookup the name later. Ignore errors,
		 * we will just report unknown when asked and tables were
		 * full. Restrict to target process when given to preserve
		 * vma_map entry slots. */
		if (_stp_target == 0
		    || _stp_target == tsk->group_leader->pid)
		  {
		    res = stap_add_vma_map_info(tsk->group_leader, addr,
						addr + length, name, NULL);
#ifdef DEBUG_TASK_FINDER_VMA
		    _stp_dbug(__FUNCTION__, __LINE__,
			      "registered '%s' for %d (res:%d)\n",
			      name, tsk->group_leader->pid,
			      res);
#endif
		  }

	}
	return 0;
}