8 #include <sys/ptrace.h>
13 /*****************************************************************************/
16 address2bpstruct(Process *proc, void *addr) {
17 debug(DEBUG_FUNCTION, "address2bpstruct(pid=%d, addr=%p)", proc->pid, addr);
18 return dict_find_entry(proc->breakpoints, addr);
22 insert_breakpoint(Process *proc, void *addr,
23 struct library_symbol *libsym) {
26 debug(DEBUG_FUNCTION, "insert_breakpoint(pid=%d, addr=%p, symbol=%s)", proc->pid, addr, libsym ? libsym->name : "NULL");
27 debug(1, "symbol=%s, addr=%p", libsym?libsym->name:"(nil)", addr);
33 libsym->needs_init = 0;
35 sbp = dict_find_entry(proc->breakpoints, addr);
37 sbp = calloc(1, sizeof(Breakpoint));
39 return; /* TODO FIXME XXX: error_mem */
41 dict_enter(proc->breakpoints, addr, sbp);
46 sbp->thumb_mode = proc->thumb_mode;
50 if (sbp->enabled == 1 && proc->pid)
51 enable_breakpoint(proc->pid, sbp);
55 delete_breakpoint(Process *proc, void *addr) {
58 debug(DEBUG_FUNCTION, "delete_breakpoint(pid=%d, addr=%p)", proc->pid, addr);
60 sbp = dict_find_entry(proc->breakpoints, addr);
61 assert(sbp); /* FIXME: remove after debugging has been done. */
62 /* This should only happen on out-of-memory conditions. */
67 if (sbp->enabled == 0)
68 disable_breakpoint(proc->pid, sbp);
69 assert(sbp->enabled >= 0);
73 enable_bp_cb(void *addr, void *sbp, void *proc) {
74 debug(DEBUG_FUNCTION, "enable_bp_cb(pid=%d)", ((Process *)proc)->pid);
75 if (((Breakpoint *)sbp)->enabled) {
76 enable_breakpoint(((Process *)proc)->pid, sbp);
81 enable_all_breakpoints(Process *proc) {
82 debug(DEBUG_FUNCTION, "enable_all_breakpoints(pid=%d)", proc->pid);
83 if (proc->breakpoints_enabled <= 0) {
88 * PPC HACK! (XXX FIXME TODO)
89 * If the dynamic linker hasn't populated the PLT then
90 * dont enable the breakpoints
92 if (options.libcalls) {
93 a = ptrace(PTRACE_PEEKTEXT, proc->pid,
94 sym2addr(proc, proc->list_of_symbols),
101 debug(1, "Enabling breakpoints for pid %u...", proc->pid);
102 if (proc->breakpoints) {
103 dict_apply_to_all(proc->breakpoints, enable_bp_cb,
109 * I'm sure there is a nicer way to do this. We need to
110 * insert breakpoints _after_ the child has been started.
112 struct library_symbol *sym;
113 struct library_symbol *new_sym;
114 sym=proc->list_of_symbols;
116 void *addr= sym2addr(proc,sym);
121 if(dict_find_entry(proc->breakpoints,addr)){
125 debug(2,"inserting bp %p %s",addr,sym->name);
126 new_sym=malloc(sizeof(*new_sym));
127 memcpy(new_sym,sym,sizeof(*new_sym));
128 new_sym->next=proc->list_of_symbols;
129 proc->list_of_symbols=new_sym;
130 insert_breakpoint(proc, addr, new_sym);
136 proc->breakpoints_enabled = 1;
140 disable_bp_cb(void *addr, void *sbp, void *proc) {
141 debug(DEBUG_FUNCTION, "disable_bp_cb(pid=%d)", ((Process *)proc)->pid);
142 if (((Breakpoint *)sbp)->enabled) {
143 disable_breakpoint(((Process *)proc)->pid, sbp);
148 disable_all_breakpoints(Process *proc) {
149 debug(DEBUG_FUNCTION, "disable_all_breakpoints(pid=%d)", proc->pid);
150 if (proc->breakpoints_enabled) {
151 debug(1, "Disabling breakpoints for pid %u...", proc->pid);
152 dict_apply_to_all(proc->breakpoints, disable_bp_cb, proc);
154 proc->breakpoints_enabled = 0;
158 free_bp_cb(void *addr, void *sbp, void *data) {
159 debug(DEBUG_FUNCTION, "free_bp_cb(sbp=%p)", sbp);
165 breakpoints_init(Process *proc) {
166 struct library_symbol *sym;
168 debug(DEBUG_FUNCTION, "breakpoints_init(pid=%d)", proc->pid);
169 if (proc->breakpoints) { /* let's remove that struct */
170 dict_apply_to_all(proc->breakpoints, free_bp_cb, NULL);
171 dict_clear(proc->breakpoints);
172 proc->breakpoints = NULL;
174 proc->breakpoints = dict_init(dict_key2hash_int, dict_key_cmp_int);
176 if (options.libcalls && proc->filename) {
177 /* FIXME: memory leak when called by exec(): */
178 proc->list_of_symbols = read_elf(proc);
180 struct library_symbol **tmp1 = &(proc->list_of_symbols);
182 struct opt_e_t *tmp2 = opt_e;
183 int keep = !opt_e_enable;
186 if (!strcmp((*tmp1)->name, tmp2->name)) {
192 *tmp1 = (*tmp1)->next;
194 tmp1 = &((*tmp1)->next);
199 proc->list_of_symbols = NULL;
201 for (sym = proc->list_of_symbols; sym; sym = sym->next) {
202 /* proc->pid==0 delays enabling. */
203 insert_breakpoint(proc, sym2addr(proc, sym), sym);
205 proc->callstack_depth = 0;
206 proc->breakpoints_enabled = -1;
210 reinitialize_breakpoints(Process *proc) {
211 struct library_symbol *sym;
213 debug(DEBUG_FUNCTION, "reinitialize_breakpoints(pid=%d)", proc->pid);
215 sym = proc->list_of_symbols;
218 if (sym->needs_init) {
219 insert_breakpoint(proc, sym2addr(proc, sym),
221 if (sym->needs_init && !sym->is_weak) {
223 "could not re-initialize breakpoint for \"%s\" in file \"%s\"\n",
224 sym->name, proc->filename);