File: isadep_dispatch.c

package info (click to toggle)
dtrace 2.0.5-1
  • links: PTS
  • area: main
  • in suites: sid
  • size: 24,408 kB
  • sloc: ansic: 61,247; sh: 17,997; asm: 1,717; lex: 947; awk: 754; yacc: 695; perl: 37; sed: 17; makefile: 15
file content (143 lines) | stat: -rw-r--r-- 3,456 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
/*
 * ISA-dependent dispatch code.
 */

/*
 * Oracle Linux DTrace.
 * Copyright (c) 2013, 2020, Oracle and/or its affiliates. All rights reserved.
 * Licensed under the Universal Permissive License v 1.0 as shown at
 * http://oss.oracle.com/licenses/upl.
 */

#include <inttypes.h>
#include <errno.h>
#include <elf.h>
#include <sys/ptrace.h>

#include "Pcontrol.h"
#include "libproc.h"
#include "platform.h"

/*
 * Generate types for an ISA dispatch function.
 */
#define ISADEP_TYPES(ret, ...) \
	typedef ret dispatch_fun_t(__VA_ARGS__)

/*
 * Generate the body of an ISA dispatch function.
 */
#define ISADEP_BODY(ret, ...) do {					\
	dispatch_fun_t *dispatch_fun;					\
									\
	dispatch_fun = (dispatch_fun_t *)search_dispatch(P, dispatch);	\
    									\
	if (dispatch_fun == NULL) {					\
		_dprintf("%s: no ISA match for %s-bit process for ELF machine " \
		    "%i\n", __func__, P->elf64?"64":"32", P->elf_machine); \
		errno = ENOEXEC;					\
		return (ret)-1;						\
	}								\
									\
	return dispatch_fun(__VA_ARGS__);				\
	} while (0)

/*
 * General function dispatch table for ISA-specific functions.  A separate
 * instance of this (with different prototypes for func) exists for every
 * ISA-specific function.
 */

typedef void dispatch_fun_t(void);

typedef struct isa_dispatch {
	int elf64;
	int elf_machine;
	dispatch_fun_t *fun;
} isa_dispatch_t;

/*
 * Search a dispatch table.  The function pointer returned must be cast to the
 * correct prototype.
 */
static dispatch_fun_t *
search_dispatch(struct ps_prochandle *P, isa_dispatch_t *dispatch)
{
	isa_dispatch_t *search;

	for (search = dispatch; search->elf_machine != 0; search++) {
		if (search->elf64 == P->elf64 &&
		    search->elf_machine == P->elf_machine)
			return search->fun;
	}

	return NULL;
}

/*
 * Read the first argument of the function at which the process P is
 * halted, which must be a pointer.
 *
 * On error, -1 cast to a uintptr_t is returned, and errno is set.
 */
uintptr_t
Pread_first_arg(struct ps_prochandle *P)
{
#define WANT_FIRST_ARG_DISPATCH
#include "isadep.h"
#undef WANT_FIRST_ARG_DISPATCH

	ISADEP_TYPES(uintptr_t, struct ps_prochandle *);
	ISADEP_BODY(uintptr_t, P);
}

/*
 * Determine the instruction pointer address at which the process P is stopped.
 * An -ESRCH may be considered "acceptable fallout".
 *
 * Returns 0 (no breakpoint), an address, or -1 on error.  (We assume that an
 * address one from the top of the address space is an unlikely instruction
 * pointer value.)
 */
uintptr_t
Pget_bkpt_ip(struct ps_prochandle *P, int expect_esrch)
{
#define WANT_GET_BKPT_IP
#include "isadep.h"
#undef WANT_GET_BKPT_IP

	ISADEP_TYPES(uintptr_t, struct ps_prochandle *, int);
	ISADEP_BODY(uintptr_t, P, expect_esrch);
}

/*
 * Reset the instruction pointer address at which the process P is stopped.
 */
long
Preset_bkpt_ip(struct ps_prochandle *P, uintptr_t addr)
{
#define WANT_RESET_BKPT_IP
#include "isadep.h"
#undef WANT_RESET_BKPT_IP

	ISADEP_TYPES(long, struct ps_prochandle *, uintptr_t);
	ISADEP_BODY(long, P, addr);
}

#ifdef NEED_SOFTWARE_SINGLESTEP
/*
 * Get the next instruction pointer after this breakpoint.  Generally only
 * implemented (and only needed) on platforms without hardware singlestepping.
 */
uintptr_t
Pget_next_ip(struct ps_prochandle *P)
{
#define WANT_GET_NEXT_IP
#include "isadep.h"
#undef WANT_GET_NEXT_IP

	ISADEP_TYPES(uintptr_t, struct ps_prochandle *);
	ISADEP_BODY(uintptr_t, P);
}

#endif