예제 #1
0
파일: breakpoints.c 프로젝트: 5py/ltrace
int
breakpoints_init(struct process *proc)
{
	debug(DEBUG_FUNCTION, "breakpoints_init(pid=%d)", proc->pid);

	/* XXX breakpoint dictionary should be initialized
	 * outside.  Here we just put in breakpoints.  */
	assert(proc->breakpoints != NULL);

	/* Only the thread group leader should hold the breakpoints.  */
	assert(proc->leader == proc);

	/* N.B. the following used to be conditional on this, and
	 * maybe it still needs to be.  */
	assert(proc->filename != NULL);

	struct library *lib = ltelf_read_main_binary(proc, proc->filename);
	struct entry_breakpoint *entry_bp = NULL;
	int bp_state = 0;
	int result = -1;
	switch ((int)(lib != NULL)) {
	fail:
		switch (bp_state) {
		case 2:
			proc_remove_library(proc, lib);
			proc_remove_breakpoint(proc, &entry_bp->super);
		case 1:
			breakpoint_destroy(&entry_bp->super);
		}
		library_destroy(lib);
		free(entry_bp);
	case 0:
		return result;
	}

	entry_bp = malloc(sizeof(*entry_bp));
	if (entry_bp == NULL
	    || (entry_breakpoint_init(proc, entry_bp,
				      lib->entry, lib)) < 0) {
		fprintf(stderr,
			"Couldn't initialize entry breakpoint for PID %d.\n"
			"Some tracing events may be missed.\n", proc->pid);
		free(entry_bp);

	} else {
		++bp_state;

		if ((result = proc_add_breakpoint(proc, &entry_bp->super)) < 0)
			goto fail;
		++bp_state;

		if ((result = breakpoint_turn_on(&entry_bp->super, proc)) < 0)
			goto fail;
	}
	proc_add_library(proc, lib);

	proc->callstack_depth = 0;
	return 0;
}
예제 #2
0
파일: proc.c 프로젝트: mer-tools/ltrace
static void
private_process_destroy(struct Process *proc, int was_exec)
{
	/* Pop remaining stack elements.  */
	while (proc->callstack_depth > 0) {
		/* When this is called just before a process is
		 * destroyed, the breakpoints should either have been
		 * retracted by now, or were killed by exec.  In any
		 * case, it's safe to pretend that there are no
		 * breakpoints associated with the stack elements, so
		 * that stack_pop doesn't attempt to destroy them.  */
		size_t i = proc->callstack_depth - 1;
		if (!proc->callstack[i].is_syscall)
			proc->callstack[i].return_addr = 0;

		callstack_pop(proc);
	}

	if (!was_exec)
		free(proc->filename);

	/* Libraries and symbols.  This is only relevant in
	 * leader.  */
	struct library *lib;
	for (lib = proc->libraries; lib != NULL; ) {
		struct library *next = lib->next;
		library_destroy(lib);
		free(lib);
		lib = next;
	}
	proc->libraries = NULL;

	/* Breakpoints.  */
	if (proc->breakpoints != NULL) {
		proc_each_breakpoint(proc, NULL, destroy_breakpoint_cb, NULL);
		dict_clear(proc->breakpoints);
		proc->breakpoints = NULL;
	}

	destroy_unwind(proc);
}
예제 #3
0
static void
crawl_linkmap(struct Process *proc, struct lt_r_debug_64 *dbg)
{
	debug (DEBUG_FUNCTION, "crawl_linkmap()");

	if (!dbg || !dbg->r_map) {
		debug(2, "Debug structure or it's linkmap are NULL!");
		return;
	}

	/* XXX The double cast should be removed when
	 * arch_addr_t becomes integral type.  */
	arch_addr_t addr = (arch_addr_t)(uintptr_t)dbg->r_map;

	while (addr != 0) {
		struct lt_link_map_64 rlm = {};
		if (lm_fetcher(proc)(proc, addr, &rlm) < 0) {
			debug(2, "Unable to read link map");
			return;
		}

		arch_addr_t key = addr;
		/* XXX The double cast should be removed when
		 * arch_addr_t becomes integral type.  */
		addr = (arch_addr_t)(uintptr_t)rlm.l_next;
		if (rlm.l_name == 0) {
			debug(2, "Name of mapped library is NULL");
			return;
		}

		char lib_name[BUFSIZ];
		/* XXX The double cast should be removed when
		 * arch_addr_t becomes integral type.  */
		umovebytes(proc, (arch_addr_t)(uintptr_t)rlm.l_name,
			   lib_name, sizeof(lib_name));

		/* Library name can be an empty string, in which case
		 * the entry represents either the main binary, or a
		 * VDSO.  Unfortunately we can't rely on that, as in
		 * recent glibc, that entry is initialized to VDSO
		 * SONAME.
		 *
		 * It's not clear how to detect VDSO in this case.  We
		 * can't assume that l_name of real DSOs will be
		 * either absolute or relative (for LD_LIBRARY_PATH=:
		 * it will be neither).  We can't compare l_addr with
		 * AT_SYSINFO_EHDR either, as l_addr is bias (which
		 * also means it's not unique, and therefore useless
		 * for this).  We could load VDSO from process image
		 * and at least compare actual SONAMEs.  For now, this
		 * kludge is about the best that we can do.  */
		if (*lib_name == 0
		    || strcmp(lib_name, "linux-vdso.so.1") == 0
		    || strcmp(lib_name, "linux-gate.so.1") == 0
		    || strcmp(lib_name, "linux-vdso32.so.1") == 0
		    || strcmp(lib_name, "linux-vdso64.so.1") == 0)
			continue;

		/* Do we have that library already?  */
		if (proc_each_library(proc, NULL, library_with_key_cb, &key))
			continue;

		struct library *lib = malloc(sizeof(*lib));
		if (lib == NULL) {
		fail:
			if (lib != NULL)
				library_destroy(lib);
			fprintf(stderr, "Couldn't load ELF object %s: %s\n",
				lib_name, strerror(errno));
			continue;
		}
		library_init(lib, LT_LIBTYPE_DSO);

		if (ltelf_read_library(lib, proc, lib_name, rlm.l_addr) < 0)
			goto fail;

		lib->key = key;
		proc_add_library(proc, lib);
	}
	return;
}
예제 #4
0
파일: proc.c 프로젝트: mer-tools/ltrace
int
process_clone(struct Process *retp, struct Process *proc, pid_t pid)
{
	if (process_bare_init(retp, proc->filename, pid, 0) < 0) {
	fail1:
		fprintf(stderr, "failed to clone process %d->%d : %s\n",
			proc->pid, pid, strerror(errno));
		return -1;
	}

	retp->tracesysgood = proc->tracesysgood;
	retp->e_machine = proc->e_machine;
	retp->e_class = proc->e_class;

	/* For non-leader processes, that's all we need to do.  */
	if (retp->leader != retp)
		return 0;

	/* Clone symbols first so that we can clone and relink
	 * breakpoints.  */
	struct library *lib;
	struct library **nlibp = &retp->libraries;
	for (lib = proc->leader->libraries; lib != NULL; lib = lib->next) {
		*nlibp = malloc(sizeof(**nlibp));
		if (*nlibp == NULL
		    || library_clone(*nlibp, lib) < 0) {
		fail2:
			process_bare_destroy(retp, 0);

			/* Error when cloning.  Unroll what was done.  */
			for (lib = retp->libraries; lib != NULL; ) {
				struct library *next = lib->next;
				library_destroy(lib);
				free(lib);
				lib = next;
			}
			goto fail1;
		}

		nlibp = &(*nlibp)->next;
	}

	/* Now clone breakpoints.  Symbol relinking is done in
	 * clone_single_bp.  */
	struct clone_single_bp_data data = {
		.old_proc = proc,
		.new_proc = retp,
		.error = 0,
	};
	dict_apply_to_all(proc->leader->breakpoints, &clone_single_bp, &data);
	if (data.error < 0)
		goto fail2;

	/* And finally the call stack.  */
	/* XXX clearly the callstack handling should be moved to a
	 * separate module and this whole business extracted to
	 * callstack_clone, or callstack_element_clone.  */
	memcpy(retp->callstack, proc->callstack, sizeof(retp->callstack));
	retp->callstack_depth = proc->callstack_depth;

	size_t i;
	for (i = 0; i < retp->callstack_depth; ++i) {
		struct callstack_element *elem = &retp->callstack[i];
		struct fetch_context *ctx = elem->fetch_context;
		if (ctx != NULL) {
			struct fetch_context *nctx = fetch_arg_clone(retp, ctx);
			if (nctx == NULL) {
				size_t j;
			fail3:
				for (j = 0; j < i; ++j) {
					nctx = elem->fetch_context;
					fetch_arg_done(nctx);
					elem->fetch_context = NULL;
				}
				goto fail2;
			}
			elem->fetch_context = nctx;
		}

		struct value_dict *args = elem->arguments;
		if (args != NULL) {
			struct value_dict *nargs = malloc(sizeof(*nargs));
			if (nargs == NULL
			    || val_dict_clone(nargs, args) < 0) {
				size_t j;
				for (j = 0; j < i; ++j) {
					nargs = elem->arguments;
					val_dict_destroy(nargs);
					free(nargs);
					elem->arguments = NULL;
				}

				/* Pretend that this round went well,
				 * so that fail3 frees I-th
				 * fetch_context.  */
				++i;
				goto fail3;
			}
			elem->arguments = nargs;
		}

		/* If it's not a syscall, we need to find the
		 * corresponding library symbol in the cloned
		 * library.  */
		if (!elem->is_syscall && elem->c_un.libfunc != NULL) {
			struct library_symbol *libfunc = elem->c_un.libfunc;
			int rc = proc_find_symbol(retp, libfunc,
						  NULL, &elem->c_un.libfunc);
			assert(rc == 0);
		}
	}

	/* At this point, retp is fully initialized, except for OS and
	 * arch parts, and we can call private_process_destroy.  */
	if (os_process_clone(retp, proc) < 0) {
		private_process_destroy(retp, 0);
		return -1;
	}
	if (arch_process_clone(retp, proc) < 0) {
		os_process_destroy(retp);
		private_process_destroy(retp, 0);
		return -1;
	}

	return 0;
}

static int
open_one_pid(pid_t pid)
{
	Process *proc;
	char *filename;
	debug(DEBUG_PROCESS, "open_one_pid(pid=%d)", pid);

	/* Get the filename first.  Should the trace_pid fail, we can
	 * easily free it, untracing is more work.  */
	if ((filename = pid2name(pid)) == NULL
	    || trace_pid(pid) < 0) {
	fail:
		free(filename);
		return -1;
	}

	proc = open_program(filename, pid);
	if (proc == NULL)
		goto fail;
	free(filename);
	trace_set_options(proc);

	return 0;
}
예제 #5
0
int main(char *argv[],int argc) {
  mc_init();
  el_bool stop = el_false;
  
  hre_t re_load = hre_compile("^load(&play)?\\s+(.*)$","i");
  hre_t re_play = hre_compile("^play$","i");
  hre_t re_pause = hre_compile("^pause$","i");
  hre_t re_next = hre_compile("^next$","i");
  hre_t re_previous = hre_compile("^prev(ious)?$","i");
  hre_t re_track = hre_compile("^track\\s+([0-9]+)$","i");
  hre_t re_quhit = hre_compile("^quit$","i");
  hre_t re_seek = hre_compile("^seek\\s([0-9]+([.][0-9]+)?)$","i");
  hre_t re_quit = hre_compile("^quit$","i");
  hre_t re_repeat = hre_compile("^repeat\\s+(off|list|track)$","i");
  hre_t re_again = hre_compile("^again$","i");
  hre_t re_scan = hre_compile("^scan\\s+(.*)$","i");
  
  file_info_t *history_file = mc_take_over(file_info_new_home(".btb_playlist"));
  printf("history file: %s\n", file_info_absolute_path(history_file));
  printf("history file: %s\n", file_info_path(history_file));
  if (file_info_exists(history_file)) {
    read_history(file_info_absolute_path(history_file));
  }
  
  i18n_set_language("nl");
  printf(_("Starting btb_playlist\n"));

  playlist_player_t *player = playlist_player_new();

  while (!stop) {
    char* line = readln(">", player);
    hre_trim(line);
    if (hre_has_match(re_quit, line)) {
      stop = el_true;
    } else if (hre_has_match(re_load, line)) {
      hre_matches m = hre_match(re_load, line);
      hre_match_t *mplay = hre_matches_get(m, 1);
      hre_match_t *match = hre_matches_get(m, 2);
      char* file = mc_strdup(hre_match_str(match));
      char* play = mc_strdup(hre_match_str(mplay));
      hre_matches_destroy(m);
      printf("loading '%s', '%s'\n", file, play);
      file_info_t *info = file_info_new(file);
      if (file_info_exists(info)) {
        if (file_info_is_file(info)) {
          if (file_info_can_read(info)) {
            const char *mediafile = NULL;
            track_array array;
            if (strcasecmp(file_info_ext(info),"cue") == 0) {
              array = tracks_from_cue(file_info_absolute_path(info));
              track_t* t = track_array_get(array, 0);
            } else {
              array = tracks_from_media(file_info_absolute_path(info));
            }
            playlist_t* pl = playlist_new("playlist");
            int i;
            for(i=0; i < track_array_count(array); ++i) {
              playlist_append(pl, track_array_get(array, i));
            }
            playlist_player_set_playlist(player, pl);
            track_array_destroy(array);
          }
        }
      }
      file_info_destroy(info);      
      if (strcasecmp(play,"&play")==0) { playlist_player_play(player); }
      mc_free(file);
      mc_free(play);
    } else if (hre_has_match(re_play, line)) {
      playlist_player_play(player);
    } else if (hre_has_match(re_pause, line)) {
      playlist_player_pause(player);
    } else if (hre_has_match(re_seek, line)) {
      hre_matches m = hre_match(re_seek, line);
      hre_match_t* match = hre_matches_get(m, 1);
      char* position = mc_strdup(hre_match_str(match));
      hre_matches_destroy(m);
      double s = atof(position);
      int ms = s * 1000;
      mc_free(position);
      playlist_player_seek(player, ms); 
    } else if (hre_has_match(re_next, line)) {
      playlist_player_next(player);
    } else if (hre_has_match(re_previous, line)) {
      playlist_player_previous(player);
    } else if (hre_has_match(re_track, line)) {
      hre_matches m = hre_match(re_track, line);
      hre_match_t* match = hre_matches_get(m, 1);
      char* nr = mc_strdup(hre_match_str(match));
      hre_matches_destroy(m);
      int index = atoi(nr);
      mc_free(nr);
      printf("setting track %d\n",index);
      playlist_player_set_track(player, index);
    } else if (hre_has_match(re_repeat, line)) {
      hre_matches m = hre_match(re_repeat, line);
      hre_match_t* match = hre_matches_get(m, 1);
      if (strcasecmp(hre_match_str(match),"track") == 0) {
        playlist_player_set_repeat(player, PLP_TRACK_REPEAT);
      } else if (strcasecmp(hre_match_str(match),"list") == 0) {
        playlist_player_set_repeat(player, PLP_LIST_REPEAT);
      } else {
        playlist_player_set_repeat(player, PLP_NO_REPEAT);
      }
      hre_matches_destroy(m);
    } else if (hre_has_match(re_again, line)) {
      playlist_player_again(player);
    } else if (hre_has_match(re_scan, line)) {
      hre_matches m = hre_match(re_scan, line);
      hre_match_t* match = hre_matches_get(m, 1);
      printf("scanning %s\n", hre_match_str(match));
      library_t* library = library_new();
      printf("calling scan_library\n");
      //scan_library(library, hre_match_str(match), library_cb);
      printf("\n");
      printf("library: %d tracks\n", library_count(library));
      printf("done scanning, destroying library\n");
      library_destroy(library);
      printf("library destroyed\n");
      hre_matches_destroy(m);
      printf("matches destroyed\n");
    }
    
    mc_free(line);
  }

  playlist_player_destroy(player);
  
  printf("%d\n",write_history(file_info_absolute_path(history_file)));
  
  file_info_destroy(history_file);
  hre_destroy(re_load);
  hre_destroy(re_play);
  hre_destroy(re_pause);
  hre_destroy(re_quit);
  hre_destroy(re_seek);
  hre_destroy(re_track);
  hre_destroy(re_next);
  hre_destroy(re_previous);
  hre_destroy(re_again);
  hre_destroy(re_repeat);
  hre_destroy(re_scan);
  
  return 0;
}
int
library_clone(struct library *retp, struct library *lib)
{
	const char *soname = NULL;
	const char *pathname;

	/* Make lifetimes of strings stored at original independent of
	 * those at the clone.  */
	if (strdup_if(&soname, lib->soname, lib->own_soname) < 0
	    || strdup_if(&pathname, lib->pathname, lib->own_pathname) < 0) {
		if (lib->own_soname)
			free((char *)soname);
		return -1;
	}

	private_library_init(retp, lib->type);
	library_set_soname(retp, soname, lib->own_soname);
	library_set_pathname(retp, pathname, lib->own_pathname);

	retp->key = lib->key;

	/* Clone symbols.  */
	{
		struct library_symbol *it;
		struct library_symbol **nsymp = &retp->symbols;
		for (it = lib->symbols; it != NULL; it = it->next) {
			*nsymp = malloc(sizeof(**nsymp));
			if (*nsymp == NULL
			    || library_symbol_clone(*nsymp, it) < 0) {
				free(*nsymp);
				*nsymp = NULL;
			fail:
				/* Release what we managed to allocate.  */
				library_destroy(retp);
				return -1;
			}

			(*nsymp)->lib = retp;
			nsymp = &(*nsymp)->next;
		}
		*nsymp = NULL;
	}

	/* Clone exported names.  */
	{
		struct library_exported_name *it;
		struct library_exported_name **nnamep = &retp->exported_names;
		for (it = lib->exported_names; it != NULL; it = it->next) {
			*nnamep = malloc(sizeof(**nnamep));
			if (*nnamep == NULL
			    || library_exported_name_clone(*nnamep, it) < 0) {
				free(*nnamep);
				goto fail;
			}
			nnamep = &(*nnamep)->next;
		}
		*nnamep = NULL;
	}

	if (os_library_clone(retp, lib) < 0)
		goto fail;

	if (arch_library_clone(retp, lib) < 0) {
		os_library_destroy(retp);
		goto fail;
	}

	return 0;
}