Exemplo n.º 1
0
/* Return (user) module in which the the given addr falls.  Returns
   NULL when no module can be found that contains the addr.  Fills in
   vm_start (addr where module is mapped in) and (base) name of module
   when given.  Note that user modules always have exactly one section
   (.dynamic or .absolute). */
static struct _stp_module *_stp_umod_lookup(unsigned long addr,
					    struct task_struct *task,
					    const char **name,
					    unsigned long *vm_start,
					    unsigned long *vm_end)
{
  void *user = NULL;
#ifdef CONFIG_COMPAT
        /* Handle 32bit signed values in 64bit longs, chop off top bits. */
        if (test_tsk_thread_flag(task, TIF_32BIT))
          addr &= ((compat_ulong_t) ~0);
#endif
  if (stap_find_vma_map_info(task->group_leader, addr,
			     vm_start, vm_end, name, &user) == 0)
    if (user != NULL)
      {
	struct _stp_module *m = (struct _stp_module *)user;
	dbug_sym(1, "found module %s at 0x%lx\n", m->path,
		 vm_start ? *vm_start : 0);
	return m;
      }
  return NULL;
}
Exemplo n.º 2
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) ? (char *)dentry->d_name.name
			    : NULL);
        
        if (path == NULL || *path == '\0') /* unknown? */
                path = (char *)name; /* we'll copy this soon, in ..._add_vma_... */

	dbug_task_vma(1,
		  "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);
	// 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)
	    && stap_find_vma_map_info(tsk, addr, NULL, NULL, NULL, NULL) != 0) {
		for (i = 0; i < _stp_num_modules; i++) {
			if (strcmp(path, _stp_modules[i]->path) == 0)
			{
			  unsigned long vm_start = 0;
			  unsigned long vm_end = 0;
			  dbug_task_vma(1,
				    "vm_cb: matched path %s to module (sec: %s)\n",
				    path, _stp_modules[i]->sections[0].name);
			  module = _stp_modules[i];
			  /* Make sure we really don't know about this module
			     yet.  If we do know, we might want to extend
			     the coverage. */
			  res = stap_find_vma_map_info_user(tsk->group_leader,
							    module,
							    &vm_start, &vm_end,
							    NULL);
			  if (res == -ESRCH)
			    res = stap_add_vma_map_info(tsk->group_leader,
						        addr, addr + length,
						        path, module);
			  else if (res == 0 && vm_end + 1 == addr)
			    res = stap_extend_vma_map_info(tsk->group_leader,
							   vm_start,
							   addr + length);
			  /* VMA entries are allocated dynamically, this is fine,
			   * since we are in a task_finder callback, which is in
			   * user context. */
			  if (res != 0) {
				_stp_error ("Couldn't register module '%s' for pid %d (%d)\n", _stp_modules[i]->path, tsk->group_leader->pid, res);
			  }
			  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, path, NULL);
		    dbug_task_vma(1,
			      "registered '%s' for %d (res:%d) [%lx-%lx]\n",
			      path, tsk->group_leader->pid,
			      res, addr, addr + length);
		  }

	} else if (path != NULL) {
		// Once registered, we may want to extend an earlier
		// registered region. A segment might be mapped with
		// different flags for different offsets. If so we want
		// to record the extended range so we can address more
		// precisely to module names and symbols.
		res = stap_extend_vma_map_info(tsk->group_leader,
					       addr, addr + length);
		dbug_task_vma(1,
			  "extended '%s' for %d (res:%d) [%lx-%lx]\n",
			  path, tsk->group_leader->pid,
			  res, addr, addr + length);
	}
	return 0;
}