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
|