aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog8
-rw-r--r--library.c11
-rw-r--r--library.h19
-rw-r--r--proc.c48
-rw-r--r--proc.h8
5 files changed, 80 insertions, 14 deletions
diff --git a/ChangeLog b/ChangeLog
index 79837ae..198ef4d 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,11 @@
+2012-09-27 Petr Machata <pmachata@redhat.com>
+
+ * library.h (struct library_symbol.latent): New field.
+ (struct library_symbol.delayed): Likewise.
+ * library.c (private_library_symbol_init): Take arguments to
+ initialize the two.
+ (library_symbol_init, library_symbol_clone): Update callers.
+
2012-09-26 Petr Machata <pmachata@redhat.com>
* ltrace-elf.h (default_elf_add_plt_entry): Drop.
diff --git a/library.c b/library.c
index cbd4a35..c2ba169 100644
--- a/library.c
+++ b/library.c
@@ -113,13 +113,16 @@ static void
private_library_symbol_init(struct library_symbol *libsym,
arch_addr_t addr,
const char *name, int own_name,
- enum toplt type_of_plt)
+ enum toplt type_of_plt,
+ int latent, int delayed)
{
libsym->next = NULL;
libsym->lib = NULL;
libsym->plt_type = type_of_plt;
libsym->name = name;
libsym->own_name = own_name;
+ libsym->latent = latent;
+ libsym->delayed = delayed;
libsym->enter_addr = (void *)(uintptr_t)addr;
}
@@ -134,7 +137,8 @@ library_symbol_init(struct library_symbol *libsym,
arch_addr_t addr, const char *name, int own_name,
enum toplt type_of_plt)
{
- private_library_symbol_init(libsym, addr, name, own_name, type_of_plt);
+ private_library_symbol_init(libsym, addr, name, own_name,
+ type_of_plt, 0, 0);
/* If arch init fails, we've already set libsym->name and
* own_name. But we return failure, and the client code isn't
@@ -159,7 +163,8 @@ library_symbol_clone(struct library_symbol *retp, struct library_symbol *libsym)
return -1;
private_library_symbol_init(retp, libsym->enter_addr,
- name, libsym->own_name, libsym->plt_type);
+ name, libsym->own_name, libsym->plt_type,
+ libsym->latent, libsym->delayed);
if (arch_library_symbol_clone(retp, libsym) < 0) {
private_library_symbol_destroy(retp);
diff --git a/library.h b/library.h
index d764da9..21dc96a 100644
--- a/library.h
+++ b/library.h
@@ -45,7 +45,21 @@ struct library_symbol {
const char *name;
arch_addr_t enter_addr;
enum toplt plt_type;
- char own_name;
+ int own_name : 1;
+
+ /* This is relevant for PLT symbols. Latent PLT symbols are
+ * those that don't match any of the -e rules, but that might
+ * potentially become active if a library implementing them
+ * appears that matches a -l rule. Ltrace core is responsible
+ * for clearing latent flag. */
+ int latent : 1;
+
+ /* Delayed symbols are those for which a breakpoint shouldn't
+ * be enabled yet. They are similar to latent symbols, but
+ * backend is responsible for clearing the delayed flag. See
+ * proc_activate_delayed_symbol. */
+ int delayed : 1;
+
struct arch_library_symbol_data arch;
};
@@ -112,7 +126,8 @@ struct library {
/* Address of PT_DYNAMIC segment. */
arch_addr_t dyn_addr;
- /* Symbols associated with the library. */
+ /* Symbols associated with the library. This includes a
+ * symbols that don't have a breakpoint attached (yet). */
struct library_symbol *symbols;
const char *soname;
diff --git a/proc.c b/proc.c
index 99bf31b..eb3e552 100644
--- a/proc.c
+++ b/proc.c
@@ -629,11 +629,10 @@ destroy_event_handler(Process * proc)
proc->event_handler = NULL;
}
-static enum callback_status
-breakpoint_for_symbol(struct library_symbol *libsym, void *data)
+static int
+breakpoint_for_symbol(struct library_symbol *libsym, struct Process *proc)
{
arch_addr_t bp_addr;
- struct Process *proc = data;
assert(proc->leader == proc);
bp_addr = sym2addr(proc, libsym);
@@ -644,11 +643,16 @@ breakpoint_for_symbol(struct library_symbol *libsym, void *data)
*
* Allow the backend to add these into the process representation
* but don't put breakpoints at this point. Let the backend fix that
- * up later. */
+ * up later.
+ *
+ * XXX This should be changed to delayed symbols. */
if (bp_addr == 0 && libsym->plt_type == LS_TOPLT_GOTONLY) {
/* Don't add breakpoints yet. */
return CBS_CONT;
}
+ /* Don't enable latent or delayed symbols. */
+ if (libsym->latent || libsym->delayed)
+ return 0;
/* If there is an artificial breakpoint on the same address,
* its libsym will be NULL, and we can smuggle our libsym
@@ -667,7 +671,7 @@ breakpoint_for_symbol(struct library_symbol *libsym, void *data)
if (bp != NULL) {
assert(bp->libsym == NULL);
bp->libsym = libsym;
- return CBS_CONT;
+ return 0;
}
bp = malloc(sizeof(*bp));
@@ -675,7 +679,7 @@ breakpoint_for_symbol(struct library_symbol *libsym, void *data)
|| breakpoint_init(bp, proc, bp_addr, libsym) < 0) {
fail:
free(bp);
- return CBS_FAIL;
+ return -1;
}
if (proc_add_breakpoint(proc, bp) < 0) {
breakpoint_destroy(bp);
@@ -688,7 +692,31 @@ breakpoint_for_symbol(struct library_symbol *libsym, void *data)
goto fail;
}
- return CBS_CONT;
+ return 0;
+}
+
+static enum callback_status
+cb_breakpoint_for_symbol(struct library_symbol *libsym, void *data)
+{
+ return breakpoint_for_symbol(libsym, data) < 0 ? CBS_FAIL : CBS_CONT;
+}
+
+static int
+proc_activate_latent_symbol(struct Process *proc,
+ struct library_symbol *libsym)
+{
+ assert(libsym->latent);
+ libsym->latent = 0;
+ return breakpoint_for_symbol(libsym, proc);
+}
+
+int
+proc_activate_delayed_symbol(struct Process *proc,
+ struct library_symbol *libsym)
+{
+ assert(libsym->delayed);
+ libsym->delayed = 0;
+ return breakpoint_for_symbol(libsym, proc);
}
void
@@ -700,10 +728,12 @@ proc_add_library(struct Process *proc, struct library *lib)
debug(DEBUG_PROCESS, "added library %s@%p (%s) to %d",
lib->soname, lib->base, lib->pathname, proc->pid);
+ /* Insert breakpoints for all active (non-latent) symbols. */
struct library_symbol *libsym = NULL;
- while ((libsym = library_each_symbol(lib, libsym, breakpoint_for_symbol,
+ while ((libsym = library_each_symbol(lib, libsym,
+ cb_breakpoint_for_symbol,
proc)) != NULL)
- fprintf(stderr, "couldn't insert breakpoint for %s to %d: %s",
+ fprintf(stderr, "Couldn't insert breakpoint for %s to %d: %s.",
libsym->name, proc->pid, strerror(errno));
}
diff --git a/proc.h b/proc.h
index b61e420..9864e1b 100644
--- a/proc.h
+++ b/proc.h
@@ -206,6 +206,14 @@ void proc_add_library(struct Process *proc, struct library *lib);
* was found and unlinked, otherwise returns a negative value. */
int proc_remove_library(struct Process *proc, struct library *lib);
+/* Clear a delayed flag. If a symbol is neither latent, nor delayed,
+ * a breakpoint is inserted for it. Returns 0 if the activation was
+ * successful or a negative value if it failed. Note that if a symbol
+ * is both latent and delayed, this will not enable the corresponding
+ * breakpoint. */
+int proc_activate_delayed_symbol(struct Process *proc,
+ struct library_symbol *libsym);
+
/* Iterate through the libraries of PROC. See callback.h for notes on
* iteration interfaces. */
struct library *proc_each_library(struct Process *proc, struct library *start,