diff options
-rw-r--r-- | ChangeLog | 8 | ||||
-rw-r--r-- | library.c | 11 | ||||
-rw-r--r-- | library.h | 19 | ||||
-rw-r--r-- | proc.c | 48 | ||||
-rw-r--r-- | proc.h | 8 |
5 files changed, 80 insertions, 14 deletions
@@ -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. @@ -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); @@ -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; @@ -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)); } @@ -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, |