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; }
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; }