• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * This file is part of ltrace.
3  * Copyright (C) 2006,2007,2011,2012,2013,2014 Petr Machata, Red Hat Inc.
4  * Copyright (C) 2009 Juan Cespedes
5  * Copyright (C) 1998,2001,2002,2003,2007,2008,2009 Juan Cespedes
6  * Copyright (C) 2006 Ian Wienand
7  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License as
10  * published by the Free Software Foundation; either version 2 of the
11  * License, or (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful, but
14  * WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
21  * 02110-1301 USA
22  */
23 
24 #include "config.h"
25 
26 #include <assert.h>
27 #include <errno.h>
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <string.h>
31 
32 #ifdef __powerpc__
33 #include <sys/ptrace.h>
34 #endif
35 
36 #include "backend.h"
37 #include "breakpoint.h"
38 #include "debug.h"
39 #include "library.h"
40 #include "ltrace-elf.h"
41 #include "proc.h"
42 
43 #ifndef ARCH_HAVE_TRANSLATE_ADDRESS
44 int
arch_translate_address_dyn(struct process * proc,arch_addr_t addr,arch_addr_t * ret)45 arch_translate_address_dyn(struct process *proc,
46 		       arch_addr_t addr, arch_addr_t *ret)
47 {
48 	*ret = addr;
49 	return 0;
50 }
51 
52 struct ltelf;
53 int
arch_translate_address(struct ltelf * lte,arch_addr_t addr,arch_addr_t * ret)54 arch_translate_address(struct ltelf *lte,
55 		       arch_addr_t addr, arch_addr_t *ret)
56 {
57 	*ret = addr;
58 	return 0;
59 }
60 #endif
61 
62 void
breakpoint_on_hit(struct breakpoint * bp,struct process * proc)63 breakpoint_on_hit(struct breakpoint *bp, struct process *proc)
64 {
65 	assert(bp != NULL);
66 	if (bp->cbs != NULL && bp->cbs->on_hit != NULL)
67 		(bp->cbs->on_hit)(bp, proc);
68 }
69 
70 void
breakpoint_on_continue(struct breakpoint * bp,struct process * proc)71 breakpoint_on_continue(struct breakpoint *bp, struct process *proc)
72 {
73 	assert(bp != NULL);
74 	if (bp->cbs != NULL && bp->cbs->on_continue != NULL)
75 		(bp->cbs->on_continue)(bp, proc);
76 	else
77 		continue_after_breakpoint(proc, bp);
78 }
79 
80 void
breakpoint_on_retract(struct breakpoint * bp,struct process * proc)81 breakpoint_on_retract(struct breakpoint *bp, struct process *proc)
82 {
83 	assert(bp != NULL);
84 	if (bp->cbs != NULL && bp->cbs->on_retract != NULL)
85 		(bp->cbs->on_retract)(bp, proc);
86 }
87 
88 void
breakpoint_on_install(struct breakpoint * bp,struct process * proc)89 breakpoint_on_install(struct breakpoint *bp, struct process *proc)
90 {
91 	assert(bp != NULL);
92 	if (bp->cbs != NULL && bp->cbs->on_install != NULL)
93 		(bp->cbs->on_install)(bp, proc);
94 }
95 
96 int
breakpoint_get_return_bp(struct breakpoint ** ret,struct breakpoint * bp,struct process * proc)97 breakpoint_get_return_bp(struct breakpoint **ret,
98 			 struct breakpoint *bp, struct process *proc)
99 {
100 	assert(bp != NULL);
101 	if (bp->cbs != NULL && bp->cbs->get_return_bp != NULL)
102 		return (bp->cbs->get_return_bp)(ret, bp, proc);
103 
104 	if ((*ret = create_default_return_bp(proc)) == NULL)
105 		return -1;
106 
107 	return 0;
108 }
109 
110 /*****************************************************************************/
111 
112 struct breakpoint *
address2bpstruct(struct process * proc,arch_addr_t addr)113 address2bpstruct(struct process *proc, arch_addr_t addr)
114 {
115 	assert(proc != NULL);
116 	assert(proc->breakpoints != NULL);
117 	assert(proc->leader == proc);
118 	debug(DEBUG_FUNCTION, "address2bpstruct(pid=%d, addr=%p)", proc->pid, addr);
119 
120 	struct breakpoint *found;
121 	if (DICT_FIND_VAL(proc->breakpoints, &addr, &found) < 0)
122 		return NULL;
123 	return found;
124 }
125 
126 #ifndef OS_HAVE_BREAKPOINT_DATA
127 int
os_breakpoint_init(struct process * proc,struct breakpoint * sbp)128 os_breakpoint_init(struct process *proc, struct breakpoint *sbp)
129 {
130 	return 0;
131 }
132 
133 void
os_breakpoint_destroy(struct breakpoint * sbp)134 os_breakpoint_destroy(struct breakpoint *sbp)
135 {
136 }
137 
138 int
os_breakpoint_clone(struct breakpoint * retp,struct breakpoint * sbp)139 os_breakpoint_clone(struct breakpoint *retp, struct breakpoint *sbp)
140 {
141 	return 0;
142 }
143 #endif
144 
145 #ifndef ARCH_HAVE_BREAKPOINT_DATA
146 int
arch_breakpoint_init(struct process * proc,struct breakpoint * sbp)147 arch_breakpoint_init(struct process *proc, struct breakpoint *sbp)
148 {
149 	return 0;
150 }
151 
152 void
arch_breakpoint_destroy(struct breakpoint * sbp)153 arch_breakpoint_destroy(struct breakpoint *sbp)
154 {
155 }
156 
157 int
arch_breakpoint_clone(struct breakpoint * retp,struct breakpoint * sbp)158 arch_breakpoint_clone(struct breakpoint *retp, struct breakpoint *sbp)
159 {
160 	return 0;
161 }
162 #endif
163 
164 static void
breakpoint_init_base(struct breakpoint * bp,arch_addr_t addr,struct library_symbol * libsym)165 breakpoint_init_base(struct breakpoint *bp,
166 		     arch_addr_t addr, struct library_symbol *libsym)
167 {
168 	bp->cbs = NULL;
169 	bp->addr = addr;
170 	memset(bp->orig_value, 0, sizeof(bp->orig_value));
171 	bp->enabled = 0;
172 	bp->libsym = libsym;
173 }
174 
175 /* On second thought, I don't think we need PROC.  All the translation
176  * (arch_translate_address in particular) should be doable using
177  * static lookups of various sections in the ELF file.  We shouldn't
178  * need process for anything.  */
179 int
breakpoint_init(struct breakpoint * bp,struct process * proc,arch_addr_t addr,struct library_symbol * libsym)180 breakpoint_init(struct breakpoint *bp, struct process *proc,
181 		arch_addr_t addr, struct library_symbol *libsym)
182 {
183 	breakpoint_init_base(bp, addr, libsym);
184 	if (os_breakpoint_init(proc, bp) < 0)
185 		return -1;
186 	if (arch_breakpoint_init(proc, bp) < 0) {
187 		os_breakpoint_destroy(bp);
188 		return -1;
189 	}
190 	return 0;
191 }
192 
193 void
breakpoint_set_callbacks(struct breakpoint * bp,struct bp_callbacks * cbs)194 breakpoint_set_callbacks(struct breakpoint *bp, struct bp_callbacks *cbs)
195 {
196 	if (bp->cbs != NULL)
197 		assert(bp->cbs == NULL);
198 	bp->cbs = cbs;
199 }
200 
201 void
breakpoint_destroy(struct breakpoint * bp)202 breakpoint_destroy(struct breakpoint *bp)
203 {
204 	if (bp == NULL)
205 		return;
206 	arch_breakpoint_destroy(bp);
207 	os_breakpoint_destroy(bp);
208 }
209 
210 int
breakpoint_clone(struct breakpoint * retp,struct process * new_proc,struct breakpoint * bp)211 breakpoint_clone(struct breakpoint *retp, struct process *new_proc,
212 		 struct breakpoint *bp)
213 {
214 	struct library_symbol *libsym = NULL;
215 	if (bp->libsym != NULL) {
216 		int rc = proc_find_symbol(new_proc, bp->libsym, NULL, &libsym);
217 		assert(rc == 0);
218 	}
219 
220 	breakpoint_init_base(retp, bp->addr, libsym);
221 	memcpy(retp->orig_value, bp->orig_value, sizeof(bp->orig_value));
222 	retp->enabled = bp->enabled;
223 	if (os_breakpoint_clone(retp, bp) < 0)
224 		return -1;
225 	if (arch_breakpoint_clone(retp, bp) < 0) {
226 		os_breakpoint_destroy(retp);
227 		return -1;
228 	}
229 	breakpoint_set_callbacks(retp, bp->cbs);
230 	return 0;
231 }
232 
233 int
breakpoint_turn_on(struct breakpoint * bp,struct process * proc)234 breakpoint_turn_on(struct breakpoint *bp, struct process *proc)
235 {
236 	bp->enabled++;
237 	if (bp->enabled == 1) {
238 		assert(proc->pid != 0);
239 		enable_breakpoint(proc, bp);
240 		breakpoint_on_install(bp, proc);
241 	}
242 	return 0;
243 }
244 
245 int
breakpoint_turn_off(struct breakpoint * bp,struct process * proc)246 breakpoint_turn_off(struct breakpoint *bp, struct process *proc)
247 {
248 	bp->enabled--;
249 	if (bp->enabled == 0)
250 		disable_breakpoint(proc, bp);
251 	assert(bp->enabled >= 0);
252 	return 0;
253 }
254 
255 struct breakpoint *
create_default_return_bp(struct process * proc)256 create_default_return_bp(struct process *proc)
257 {
258 	struct breakpoint *bp = malloc(sizeof *bp);
259 	arch_addr_t return_addr = get_return_addr(proc, proc->stack_pointer);
260 	if (return_addr == 0 || bp == NULL
261 	    || breakpoint_init(bp, proc, return_addr, NULL) < 0) {
262 		free(bp);
263 		return NULL;
264 	}
265 	return bp;
266 }
267 
268 struct breakpoint *
insert_breakpoint_at(struct process * proc,arch_addr_t addr,struct library_symbol * libsym)269 insert_breakpoint_at(struct process *proc, arch_addr_t addr,
270 		     struct library_symbol *libsym)
271 {
272 	debug(DEBUG_FUNCTION,
273 	      "insert_breakpoint_at(pid=%d, addr=%p, symbol=%s)",
274 	      proc->pid, addr, libsym ? libsym->name : "NULL");
275 
276 	assert(addr != 0);
277 
278 	struct breakpoint *bp = malloc(sizeof *bp);
279 	if (bp == NULL || breakpoint_init(bp, proc, addr, libsym) < 0) {
280 		free(bp);
281 		return NULL;
282 	}
283 
284 	/* N.B. (and XXX): BP->addr might differ from ADDR.  On ARM
285 	 * this is a real possibility.  The problem here is that to
286 	 * create a return breakpoint ltrace calls get_return_addr and
287 	 * then insert_breakpoint_at.  So get_return_addr needs to
288 	 * encode all the information necessary for breakpoint_init
289 	 * into the address itself, so ADDR is potentially
290 	 * mangled.  */
291 
292 	struct breakpoint *tmp = insert_breakpoint(proc, bp);
293 	if (tmp != bp) {
294 		breakpoint_destroy(bp);
295 		free(bp);
296 	}
297 	return tmp;
298 }
299 
300 struct breakpoint *
insert_breakpoint(struct process * proc,struct breakpoint * bp)301 insert_breakpoint(struct process *proc, struct breakpoint *bp)
302 {
303 	/* Only the group leader should be getting the breakpoints and
304 	 * thus have ->breakpoint initialized.  */
305 	struct process *leader = proc->leader;
306 	assert(leader != NULL);
307 	assert(leader->breakpoints != NULL);
308 
309 	/* XXX what we need to do instead is have a list of
310 	 * breakpoints that are enabled at this address.  The
311 	 * following works if every breakpoint is the same and there's
312 	 * no extra data, but that doesn't hold anymore.  For now it
313 	 * will suffice, about the only realistic case where we need
314 	 * to have more than one breakpoint per address is return from
315 	 * a recursive library call.  */
316 	struct breakpoint *ext_bp = bp;
317 	if (DICT_FIND_VAL(leader->breakpoints, &bp->addr, &ext_bp) != 0) {
318 		if (proc_add_breakpoint(leader, bp) < 0)
319 			return NULL;
320 		ext_bp = bp;
321 	}
322 
323 	if (breakpoint_turn_on(ext_bp, proc) < 0) {
324 		if (ext_bp != bp)
325 			proc_remove_breakpoint(leader, bp);
326 		return NULL;
327 	}
328 
329 	return ext_bp;
330 }
331 
332 void
delete_breakpoint_at(struct process * proc,arch_addr_t addr)333 delete_breakpoint_at(struct process *proc, arch_addr_t addr)
334 {
335 	debug(DEBUG_FUNCTION, "delete_breakpoint_at(pid=%d, addr=%p)",
336 	      proc->pid, addr);
337 
338 	struct process *leader = proc->leader;
339 	assert(leader != NULL);
340 
341 	struct breakpoint *bp = NULL;
342 	DICT_FIND_VAL(leader->breakpoints, &addr, &bp);
343 	assert(bp != NULL);
344 
345 	if (delete_breakpoint(proc, bp) < 0) {
346 		fprintf(stderr, "Couldn't turn off the breakpoint %s@%p\n",
347 			breakpoint_name(bp), bp->addr);
348 	}
349 }
350 
351 int
delete_breakpoint(struct process * proc,struct breakpoint * bp)352 delete_breakpoint(struct process *proc, struct breakpoint *bp)
353 {
354 	struct process *leader = proc->leader;
355 	assert(leader != NULL);
356 
357 	if (breakpoint_turn_off(bp, proc) < 0)
358 		return -1;
359 
360 	if (bp->enabled == 0) {
361 		proc_remove_breakpoint(leader, bp);
362 		breakpoint_destroy(bp);
363 		free(bp);
364 	}
365 
366 	return 0;
367 }
368 
369 const char *
breakpoint_name(const struct breakpoint * bp)370 breakpoint_name(const struct breakpoint *bp)
371 {
372 	assert(bp != NULL);
373 	return bp->libsym != NULL ? bp->libsym->name : NULL;
374 }
375 
376 struct library *
breakpoint_library(const struct breakpoint * bp)377 breakpoint_library(const struct breakpoint *bp)
378 {
379 	assert(bp != NULL);
380 	return bp->libsym != NULL ? bp->libsym->lib : NULL;
381 }
382 
383 static enum callback_status
disable_bp_cb(arch_addr_t * addr,struct breakpoint ** bpp,void * data)384 disable_bp_cb(arch_addr_t *addr, struct breakpoint **bpp, void *data)
385 {
386 	struct process *proc = data;
387 	debug(DEBUG_FUNCTION, "disable_bp_cb(pid=%d)", proc->pid);
388 	if ((*bpp)->enabled)
389 		disable_breakpoint(proc, *bpp);
390 	return CBS_CONT;
391 }
392 
393 void
disable_all_breakpoints(struct process * proc)394 disable_all_breakpoints(struct process *proc)
395 {
396 	debug(DEBUG_FUNCTION, "disable_all_breakpoints(pid=%d)", proc->pid);
397 	assert(proc->leader == proc);
398 	DICT_EACH(proc->breakpoints, arch_addr_t, struct breakpoint *,
399 		  NULL, disable_bp_cb, proc);
400 }
401 
402 static void
entry_breakpoint_on_hit(struct breakpoint * bp,struct process * proc)403 entry_breakpoint_on_hit(struct breakpoint *bp, struct process *proc)
404 {
405 	if (proc == NULL || proc->leader == NULL)
406 		return;
407 	delete_breakpoint_at(proc, bp->addr);
408 	process_hit_start(proc);
409 }
410 
411 int
entry_breakpoint_init(struct process * proc,struct breakpoint * bp,arch_addr_t addr,struct library * lib)412 entry_breakpoint_init(struct process *proc,
413 		      struct breakpoint *bp, arch_addr_t addr,
414 		      struct library *lib)
415 {
416 	assert(addr != 0);
417 	int err = breakpoint_init(bp, proc, addr, NULL);
418 	if (err < 0)
419 		return err;
420 
421 	static struct bp_callbacks entry_callbacks = {
422 		.on_hit = entry_breakpoint_on_hit,
423 	};
424 	bp->cbs = &entry_callbacks;
425 	return 0;
426 }
427 
428 int
breakpoints_init(struct process * proc)429 breakpoints_init(struct process *proc)
430 {
431 	debug(DEBUG_FUNCTION, "breakpoints_init(pid=%d)", proc->pid);
432 
433 	/* XXX breakpoint dictionary should be initialized
434 	 * outside.  Here we just put in breakpoints.  */
435 	assert(proc->breakpoints != NULL);
436 
437 	/* Only the thread group leader should hold the breakpoints.  */
438 	assert(proc->leader == proc);
439 
440 	/* N.B. the following used to be conditional on this, and
441 	 * maybe it still needs to be.  */
442 	assert(proc->filename != NULL);
443 
444 	struct library *lib = ltelf_read_main_binary(proc, proc->filename);
445 	struct breakpoint *entry_bp = NULL;
446 	int bp_state = 0;
447 	int result = -1;
448 	switch ((int)(lib != NULL)) {
449 	fail:
450 		switch (bp_state) {
451 		case 2:
452 			proc_remove_library(proc, lib);
453 			proc_remove_breakpoint(proc, entry_bp);
454 		case 1:
455 			breakpoint_destroy(entry_bp);
456 		}
457 		library_destroy(lib);
458 		free(entry_bp);
459 	case 0:
460 		return result;
461 	}
462 
463 	entry_bp = malloc(sizeof(*entry_bp));
464 	if (entry_bp == NULL
465 	    || (entry_breakpoint_init(proc, entry_bp,
466 				      lib->entry, lib)) < 0) {
467 		fprintf(stderr,
468 			"Couldn't initialize entry breakpoint for PID %d.\n"
469 			"Some tracing events may be missed.\n", proc->pid);
470 		free(entry_bp);
471 
472 	} else {
473 		++bp_state;
474 
475 		if ((result = proc_add_breakpoint(proc, entry_bp)) < 0)
476 			goto fail;
477 		++bp_state;
478 
479 		if ((result = breakpoint_turn_on(entry_bp, proc)) < 0)
480 			goto fail;
481 	}
482 	proc_add_library(proc, lib);
483 
484 	proc->callstack_depth = 0;
485 	return 0;
486 }
487