summaryrefslogtreecommitdiff
path: root/sysdeps/linux-gnu/proc.c
diff options
context:
space:
mode:
Diffstat (limited to 'sysdeps/linux-gnu/proc.c')
-rw-r--r--sysdeps/linux-gnu/proc.c126
1 files changed, 70 insertions, 56 deletions
diff --git a/sysdeps/linux-gnu/proc.c b/sysdeps/linux-gnu/proc.c
index 5adfb16..953fd86 100644
--- a/sysdeps/linux-gnu/proc.c
+++ b/sysdeps/linux-gnu/proc.c
@@ -1,6 +1,6 @@
/*
* This file is part of ltrace.
- * Copyright (C) 2011,2012 Petr Machata, Red Hat Inc.
+ * Copyright (C) 2011,2012,2013 Petr Machata, Red Hat Inc.
* Copyright (C) 2010 Zachary T Welch, CodeSourcery
* Copyright (C) 2010 Joe Damato
* Copyright (C) 1998,2008,2009 Juan Cespedes
@@ -177,44 +177,46 @@ process_status_cb(const char *line, const char *prefix, void *data)
} while (0)
switch (c) {
- case 'Z': RETURN(ps_zombie);
- case 't': RETURN(ps_tracing_stop);
+ case 'Z': RETURN(PS_ZOMBIE);
+ case 't': RETURN(PS_TRACING_STOP);
case 'T':
/* This can be either "T (stopped)" or, for older
* kernels, "T (tracing stop)". */
if (!strcmp(status, "T (stopped)\n"))
- RETURN(ps_stop);
+ RETURN(PS_STOP);
else if (!strcmp(status, "T (tracing stop)\n"))
- RETURN(ps_tracing_stop);
+ RETURN(PS_TRACING_STOP);
else {
fprintf(stderr, "Unknown process status: %s",
status);
- RETURN(ps_stop); /* Some sort of stop
+ RETURN(PS_STOP); /* Some sort of stop
* anyway. */
}
case 'D':
- case 'S': RETURN(ps_sleeping);
+ case 'S': RETURN(PS_SLEEPING);
}
- RETURN(ps_other);
+ RETURN(PS_OTHER);
#undef RETURN
}
enum process_status
process_status(pid_t pid)
{
- enum process_status ret = ps_invalid;
+ enum process_status ret = PS_INVALID;
FILE * file = open_status_file(pid);
if (file != NULL) {
each_line_starting(file, "State:\t", &process_status_cb, &ret);
fclose(file);
- if (ret == ps_invalid)
- fprintf(stderr, "process_status %d: %s", pid,
- strerror(errno));
- } else
+ if (ret == PS_INVALID)
+ fprintf(stderr,
+ "Couldn't determine status of process %d: %s\n",
+ pid, strerror(errno));
+ } else {
/* If the file is not present, the process presumably
* exited already. */
- ret = ps_zombie;
+ ret = PS_ZOMBIE;
+ }
return ret;
}
@@ -231,7 +233,7 @@ int
process_tasks(pid_t pid, pid_t **ret_tasks, size_t *ret_n)
{
PROC_PID_FILE(fn, "/proc/%d/task", pid);
- DIR * d = opendir(fn);
+ DIR *d = opendir(fn);
if (d == NULL)
return -1;
@@ -243,7 +245,9 @@ process_tasks(pid_t pid, pid_t **ret_tasks, size_t *ret_n)
struct dirent entry;
struct dirent *result;
if (readdir_r(d, &entry, &result) != 0) {
+ fail:
free(tasks);
+ closedir(d);
return -1;
}
if (result == NULL)
@@ -254,14 +258,11 @@ process_tasks(pid_t pid, pid_t **ret_tasks, size_t *ret_n)
alloc = alloc > 0 ? (2 * alloc) : 8;
pid_t *ntasks = realloc(tasks,
sizeof(*tasks) * alloc);
- if (ntasks == NULL) {
- free(tasks);
- return -1;
- }
+ if (ntasks == NULL)
+ goto fail;
tasks = ntasks;
}
- if (n >= alloc)
- abort();
+ assert(n < alloc);
tasks[n++] = npid;
}
}
@@ -279,7 +280,7 @@ process_tasks(pid_t pid, pid_t **ret_tasks, size_t *ret_n)
* ABI object, as theorized about somewhere on pmachata/revamp
* branch. */
static void *
-select_32_64(struct Process *proc, void *p32, void *p64)
+select_32_64(struct process *proc, void *p32, void *p64)
{
if (sizeof(long) == 4 || proc->mask_32bit)
return p32;
@@ -288,7 +289,7 @@ select_32_64(struct Process *proc, void *p32, void *p64)
}
static int
-fetch_dyn64(struct Process *proc, arch_addr_t *addr, Elf64_Dyn *ret)
+fetch_dyn64(struct process *proc, arch_addr_t *addr, Elf64_Dyn *ret)
{
if (umovebytes(proc, *addr, ret, sizeof(*ret)) != sizeof(*ret))
return -1;
@@ -297,7 +298,7 @@ fetch_dyn64(struct Process *proc, arch_addr_t *addr, Elf64_Dyn *ret)
}
static int
-fetch_dyn32(struct Process *proc, arch_addr_t *addr, Elf64_Dyn *ret)
+fetch_dyn32(struct process *proc, arch_addr_t *addr, Elf64_Dyn *ret)
{
Elf32_Dyn dyn;
if (umovebytes(proc, *addr, &dyn, sizeof(dyn)) != sizeof(dyn))
@@ -311,14 +312,14 @@ fetch_dyn32(struct Process *proc, arch_addr_t *addr, Elf64_Dyn *ret)
}
static int (*
-dyn_fetcher(struct Process *proc))(struct Process *,
+dyn_fetcher(struct process *proc))(struct process *,
arch_addr_t *, Elf64_Dyn *)
{
return select_32_64(proc, fetch_dyn32, fetch_dyn64);
}
int
-proc_find_dynamic_entry_addr(struct Process *proc, arch_addr_t src_addr,
+proc_find_dynamic_entry_addr(struct process *proc, arch_addr_t src_addr,
int d_tag, arch_addr_t *ret)
{
debug(DEBUG_FUNCTION, "find_dynamic_entry()");
@@ -364,7 +365,7 @@ struct lt_link_map_32 LT_LINK_MAP(32);
struct lt_link_map_64 LT_LINK_MAP(64);
static int
-fetch_lm64(struct Process *proc, arch_addr_t addr,
+fetch_lm64(struct process *proc, arch_addr_t addr,
struct lt_link_map_64 *ret)
{
if (umovebytes(proc, addr, ret, sizeof(*ret)) != sizeof(*ret))
@@ -373,7 +374,7 @@ fetch_lm64(struct Process *proc, arch_addr_t addr,
}
static int
-fetch_lm32(struct Process *proc, arch_addr_t addr,
+fetch_lm32(struct process *proc, arch_addr_t addr,
struct lt_link_map_64 *ret)
{
struct lt_link_map_32 lm;
@@ -390,7 +391,7 @@ fetch_lm32(struct Process *proc, arch_addr_t addr,
}
static int (*
-lm_fetcher(struct Process *proc))(struct Process *,
+lm_fetcher(struct process *proc))(struct process *,
arch_addr_t, struct lt_link_map_64 *)
{
return select_32_64(proc, fetch_lm32, fetch_lm64);
@@ -410,7 +411,7 @@ struct lt_r_debug_32 LT_R_DEBUG(32);
struct lt_r_debug_64 LT_R_DEBUG(64);
static int
-fetch_rd64(struct Process *proc, arch_addr_t addr,
+fetch_rd64(struct process *proc, arch_addr_t addr,
struct lt_r_debug_64 *ret)
{
if (umovebytes(proc, addr, ret, sizeof(*ret)) != sizeof(*ret))
@@ -419,7 +420,7 @@ fetch_rd64(struct Process *proc, arch_addr_t addr,
}
static int
-fetch_rd32(struct Process *proc, arch_addr_t addr,
+fetch_rd32(struct process *proc, arch_addr_t addr,
struct lt_r_debug_64 *ret)
{
struct lt_r_debug_32 rd;
@@ -436,7 +437,7 @@ fetch_rd32(struct Process *proc, arch_addr_t addr,
}
static int (*
-rdebug_fetcher(struct Process *proc))(struct Process *,
+rdebug_fetcher(struct process *proc))(struct process *,
arch_addr_t, struct lt_r_debug_64 *)
{
return select_32_64(proc, fetch_rd32, fetch_rd64);
@@ -463,13 +464,13 @@ fetch_auxv32_entry(int fd, Elf64_auxv_t *ret)
}
static int (*
-auxv_fetcher(struct Process *proc))(int, Elf64_auxv_t *)
+auxv_fetcher(struct process *proc))(int, Elf64_auxv_t *)
{
return select_32_64(proc, fetch_auxv32_entry, fetch_auxv64_entry);
}
static void
-crawl_linkmap(struct Process *proc, struct lt_r_debug_64 *dbg)
+crawl_linkmap(struct process *proc, struct lt_r_debug_64 *dbg)
{
debug (DEBUG_FUNCTION, "crawl_linkmap()");
@@ -483,7 +484,7 @@ crawl_linkmap(struct Process *proc, struct lt_r_debug_64 *dbg)
arch_addr_t addr = (arch_addr_t)(uintptr_t)dbg->r_map;
while (addr != 0) {
- struct lt_link_map_64 rlm;
+ struct lt_link_map_64 rlm = {};
if (lm_fetcher(proc)(proc, addr, &rlm) < 0) {
debug(2, "Unable to read link map");
return;
@@ -533,17 +534,20 @@ crawl_linkmap(struct Process *proc, struct lt_r_debug_64 *dbg)
struct library *lib = malloc(sizeof(*lib));
if (lib == NULL) {
fail:
- if (lib != NULL)
- library_destroy(lib);
+ free(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)
+ if (library_init(lib, LT_LIBTYPE_DSO) < 0)
goto fail;
+ if (ltelf_read_library(lib, proc, lib_name, rlm.l_addr) < 0) {
+ library_destroy(lib);
+ goto fail;
+ }
+
lib->key = key;
proc_add_library(proc, lib);
}
@@ -551,7 +555,7 @@ crawl_linkmap(struct Process *proc, struct lt_r_debug_64 *dbg)
}
static int
-load_debug_struct(struct Process *proc, struct lt_r_debug_64 *ret)
+load_debug_struct(struct process *proc, struct lt_r_debug_64 *ret)
{
debug(DEBUG_FUNCTION, "load_debug_struct");
@@ -564,7 +568,7 @@ load_debug_struct(struct Process *proc, struct lt_r_debug_64 *ret)
}
static void
-rdebug_bp_on_hit(struct breakpoint *bp, struct Process *proc)
+rdebug_bp_on_hit(struct breakpoint *bp, struct process *proc)
{
debug(DEBUG_FUNCTION, "arch_check_dbg");
@@ -595,7 +599,7 @@ rdebug_bp_on_hit(struct breakpoint *bp, struct Process *proc)
#ifndef ARCH_HAVE_FIND_DL_DEBUG
int
-arch_find_dl_debug(struct Process *proc, arch_addr_t dyn_addr,
+arch_find_dl_debug(struct process *proc, arch_addr_t dyn_addr,
arch_addr_t *ret)
{
return proc_find_dynamic_entry_addr(proc, dyn_addr, DT_DEBUG, ret);
@@ -603,7 +607,7 @@ arch_find_dl_debug(struct Process *proc, arch_addr_t dyn_addr,
#endif
int
-linkmap_init(struct Process *proc, arch_addr_t dyn_addr)
+linkmap_init(struct process *proc, arch_addr_t dyn_addr)
{
debug(DEBUG_FUNCTION, "linkmap_init(%d, dyn_addr=%p)", proc->pid, dyn_addr);
@@ -619,19 +623,29 @@ linkmap_init(struct Process *proc, arch_addr_t dyn_addr)
return status;
}
+ crawl_linkmap(proc, &rdbg);
+
/* XXX The double cast should be removed when
* arch_addr_t becomes integral type. */
arch_addr_t addr = (arch_addr_t)(uintptr_t)rdbg.r_brk;
if (arch_translate_address_dyn(proc, addr, &addr) < 0)
return -1;
- struct breakpoint *rdebug_bp = insert_breakpoint(proc, addr, NULL);
- static struct bp_callbacks rdebug_callbacks = {
- .on_hit = rdebug_bp_on_hit,
- };
- rdebug_bp->cbs = &rdebug_callbacks;
-
- crawl_linkmap(proc, &rdbg);
+ struct breakpoint *rdebug_bp = insert_breakpoint_at(proc, addr, NULL);
+ if (rdebug_bp == NULL) {
+ /* This is not fatal, the tracing can continue with
+ * reduced functionality. */
+ fprintf(stderr,
+ "Couldn't insert _r_debug breakpoint to %d: %s.\n"
+ "As a result of that, ltrace will not be able to "
+ "detect and trace\nnewly-loaded libraries.\n",
+ proc->pid, strerror(errno));
+ } else {
+ static struct bp_callbacks rdebug_callbacks = {
+ .on_hit = rdebug_bp_on_hit,
+ };
+ rdebug_bp->cbs = &rdebug_callbacks;
+ }
return 0;
}
@@ -648,13 +662,13 @@ task_kill (pid_t pid, int sig)
}
void
-process_removed(struct Process *proc)
+process_removed(struct process *proc)
{
delete_events_for(proc);
}
int
-process_get_entry(struct Process *proc,
+process_get_entry(struct process *proc,
arch_addr_t *entryp,
arch_addr_t *interp_biasp)
{
@@ -706,7 +720,7 @@ process_get_entry(struct Process *proc,
}
int
-os_process_init(struct Process *proc)
+os_process_init(struct process *proc)
{
proc->os.debug_addr = 0;
proc->os.debug_state = 0;
@@ -714,19 +728,19 @@ os_process_init(struct Process *proc)
}
void
-os_process_destroy(struct Process *proc)
+os_process_destroy(struct process *proc)
{
}
int
-os_process_clone(struct Process *retp, struct Process *proc)
+os_process_clone(struct process *retp, struct process *proc)
{
retp->os = proc->os;
return 0;
}
int
-os_process_exec(struct Process *proc)
+os_process_exec(struct process *proc)
{
return 0;
}