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
44int
45arch_translate_address_dyn(struct process *proc,
46		       arch_addr_t addr, arch_addr_t *ret)
47{
48	*ret = addr;
49	return 0;
50}
51
52struct ltelf;
53int
54arch_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
62void
63breakpoint_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
70void
71breakpoint_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
80void
81breakpoint_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
88void
89breakpoint_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
96int
97breakpoint_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
112struct breakpoint *
113address2bpstruct(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
127int
128os_breakpoint_init(struct process *proc, struct breakpoint *sbp)
129{
130	return 0;
131}
132
133void
134os_breakpoint_destroy(struct breakpoint *sbp)
135{
136}
137
138int
139os_breakpoint_clone(struct breakpoint *retp, struct breakpoint *sbp)
140{
141	return 0;
142}
143#endif
144
145#ifndef ARCH_HAVE_BREAKPOINT_DATA
146int
147arch_breakpoint_init(struct process *proc, struct breakpoint *sbp)
148{
149	return 0;
150}
151
152void
153arch_breakpoint_destroy(struct breakpoint *sbp)
154{
155}
156
157int
158arch_breakpoint_clone(struct breakpoint *retp, struct breakpoint *sbp)
159{
160	return 0;
161}
162#endif
163
164static void
165breakpoint_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.  */
179int
180breakpoint_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
193void
194breakpoint_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
201void
202breakpoint_destroy(struct breakpoint *bp)
203{
204	if (bp == NULL)
205		return;
206	arch_breakpoint_destroy(bp);
207	os_breakpoint_destroy(bp);
208}
209
210int
211breakpoint_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
233int
234breakpoint_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
245int
246breakpoint_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
255struct breakpoint *
256create_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
268struct breakpoint *
269insert_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
300struct breakpoint *
301insert_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
332void
333delete_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
351int
352delete_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
369const char *
370breakpoint_name(const struct breakpoint *bp)
371{
372	assert(bp != NULL);
373	return bp->libsym != NULL ? bp->libsym->name : NULL;
374}
375
376struct library *
377breakpoint_library(const struct breakpoint *bp)
378{
379	assert(bp != NULL);
380	return bp->libsym != NULL ? bp->libsym->lib : NULL;
381}
382
383static enum callback_status
384disable_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
393void
394disable_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
402static void
403entry_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
411int
412entry_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
428int
429breakpoints_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