#pragma ident "@(#)dt_isadep.c 1.14 06/02/22 SMI"
#if defined(__ppc__) || defined(__ppc64__)
#include <stdlib.h>
#include <assert.h>
#include <errno.h>
#include <string.h>
#include <libgen.h>
#include <dt_impl.h>
#include <dt_pid.h>
#include "decode.h"
#include "Scanalyzer.h"
#include "sym.h"
#include "misc.h"
#include "core.h"
static
uint8_t probeable[256] = {0, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
int
dt_pid_create_entry_probe(struct ps_prochandle *P, dtrace_hdl_t *dtp,
fasttrap_probe_spec_t *ftp, const GElf_Sym *symp)
{
#if defined(__APPLE__)
ftp->ftps_probe_type = DTFTP_ENTRY;
ftp->ftps_pc = symp->st_value; #endif
ftp->ftps_size = (size_t)symp->st_size;
ftp->ftps_noffs = 1;
ftp->ftps_offs[0] = 0;
#if defined(__APPLE__)
uint8_t *text;
char dmodel = Pstatus(P)->pr_dmodel;
if ((text = calloc(1, symp->st_size + 4)) == NULL) {
dt_dprintf("mr sparkle: malloc() failed\n");
return (DT_PROC_ERR);
}
if (Pread(P, text, symp->st_size, symp->st_value) != symp->st_size) {
dt_dprintf("mr sparkle: Pread() failed\n");
free(text);
return (DT_PROC_ERR);
}
uint8_t *isnflgs = InvokeScanalyzer(dmodel == PR_MODEL_LP64, _dtrace_scanalyzer, symp->st_value, symp->st_size, (uint32_t *)text, ftp->ftps_mod, ftp->ftps_func);
if(isnflgs == (uint8_t *)0) {
dt_dprintf("scanalyzer found no exectable instructions\n");
free(text);
return (-1);
}
if((isnflgs[0] & 15) == isRsvn) {
dt_dprintf("entry point is an unprobeable reservation type instruction\n");
free(isnflgs);
free(text);
return (0);
}
if(!probeable[isnflgs[0]]) {
dt_dprintf("entry point is an unprobeable instruction\n");
free(isnflgs);
free(text);
return (0);
}
free(isnflgs);
free(text);
#endif
if (ioctl(dtp->dt_ftfd, FASTTRAPIOC_MAKEPROBE, ftp) != 0) {
dt_dprintf("fasttrap probe creation ioctl failed: %s\n",
strerror(errno));
return (dt_set_errno(dtp, errno));
}
return (1);
}
int
dt_pid_create_return_probe(struct ps_prochandle *P, dtrace_hdl_t *dtp,
fasttrap_probe_spec_t *ftp, const GElf_Sym *symp, uint64_t *stret)
{
uint8_t *text;
ulong_t i;
char dmodel = Pstatus(P)->pr_dmodel;
if ((text = calloc(1, symp->st_size + 4)) == NULL) {
dt_dprintf("mr sparkle: malloc() failed\n");
return (DT_PROC_ERR);
}
if (Pread(P, text, symp->st_size, symp->st_value) != symp->st_size) {
dt_dprintf("mr sparkle: Pread() failed\n");
free(text);
return (DT_PROC_ERR);
}
ftp->ftps_size = (size_t)symp->st_size;
ftp->ftps_noffs = 0;
#if defined(__APPLE__)
ftp->ftps_probe_type = DTFTP_RETURN;
ftp->ftps_pc = symp->st_value;
uint8_t *isnflgs = InvokeScanalyzer(dmodel == PR_MODEL_LP64, _dtrace_scanalyzer, symp->st_value, symp->st_size, (uint32_t *)text, ftp->ftps_mod, ftp->ftps_func);
if(isnflgs == NULL) {
dt_dprintf("scanalyzer found no exectable instructions\n");
free(text);
return (-1);
}
int32_t icnt = (ftp->ftps_size + 3) / 4;
for(i = 0; i < icnt; i++) {
if((isnflgs[i] & isnExit)) {
if (probeable[isnflgs[i]]) {
dt_dprintf("return at offset 0x%x\n", (i << 2));
ftp->ftps_offs[ftp->ftps_noffs++] = (i << 2);
} else {
dt_dprintf("return at offset 0x%x is an unprobeable instruction\n", (i << 2));
}
}
}
free(isnflgs);
#endif
free(text);
if (ftp->ftps_noffs > 0) {
if (ioctl(dtp->dt_ftfd, FASTTRAPIOC_MAKEPROBE, ftp) != 0) {
dt_dprintf("fasttrap probe creation ioctl failed: %s\n",
strerror(errno));
return (dt_set_errno(dtp, errno));
}
}
return (ftp->ftps_noffs);
}
int
dt_pid_create_offset_probe(struct ps_prochandle *P, dtrace_hdl_t *dtp,
fasttrap_probe_spec_t *ftp, const GElf_Sym *symp, ulong_t off)
{
#if defined(__APPLE__)
if (off & 0x3)
return DT_PROC_ALIGN;
ftp->ftps_probe_type = DTFTP_OFFSETS;
ftp->ftps_pc = symp->st_value;
#endif
ftp->ftps_size = (size_t)symp->st_size;
ftp->ftps_noffs = 1;
if (strcmp("-", ftp->ftps_func) == 0) {
ftp->ftps_offs[0] = off;
} else {
uint8_t *text;
ulong_t i;
char dmodel = Pstatus(P)->pr_dmodel;
if ((text = malloc(symp->st_size)) == NULL) {
dt_dprintf("mr sparkle: malloc() failed\n");
return (DT_PROC_ERR);
}
if (Pread(P, text, symp->st_size, symp->st_value) !=
symp->st_size) {
dt_dprintf("mr sparkle: Pread() failed\n");
free(text);
return (DT_PROC_ERR);
}
#if defined(__APPLE__)
uint8_t *isnflgs = InvokeScanalyzer(dmodel == PR_MODEL_LP64, _dtrace_scanalyzer, symp->st_value, symp->st_size, (uint32_t *)text, ftp->ftps_mod, ftp->ftps_func);
if(isnflgs == NULL) {
dt_dprintf("scanalyzer found no executable instructions\n");
free(text);
return (-1);
}
uint32_t icnt = (ftp->ftps_size + 3) / 4;
for(i = 0; i < icnt; i++) {
if((isnflgs[i] & 15) == isRsvn) {
dt_dprintf("instruction at offset 0x%x is a reservation type, skipping this function\n", i * 4);
free(isnflgs);
free(text);
return 0;
}
}
if(probeable[isnflgs[off / 4]]) {
ftp->ftps_offs[0] = off;
} else {
dt_dprintf("instruction at offset 0x%lx is not probeable\n", off);
free(isnflgs);
free(text);
return 0;
}
free(isnflgs);
#endif
free(text);
}
if (ioctl(dtp->dt_ftfd, FASTTRAPIOC_MAKEPROBE, ftp) != 0) {
dt_dprintf("fasttrap probe creation ioctl failed: %s\n",
strerror(errno));
return (dt_set_errno(dtp, errno));
}
return (1);
}
int
dt_pid_create_glob_offset_probes(struct ps_prochandle *P, dtrace_hdl_t *dtp,
fasttrap_probe_spec_t *ftp, const GElf_Sym *symp, const char *pattern)
{
uint8_t *text;
ulong_t i, end;
char dmodel = Pstatus(P)->pr_dmodel;
if ((text = malloc(symp->st_size)) == NULL) {
dt_dprintf("mr sparkle: malloc() failed\n");
return (DT_PROC_ERR);
}
if (Pread(P, text, symp->st_size, symp->st_value) != symp->st_size) {
dt_dprintf("mr sparkle: Pread() failed\n");
free(text);
return (DT_PROC_ERR);
}
#if defined(__APPLE__)
ftp->ftps_probe_type = DTFTP_OFFSETS;
ftp->ftps_pc = symp->st_value;
#endif
ftp->ftps_size = (size_t)symp->st_size;
ftp->ftps_noffs = 0;
#if defined(__APPLE__)
uint8_t *isnflgs = InvokeScanalyzer(dmodel == PR_MODEL_LP64, _dtrace_scanalyzer, symp->st_value, symp->st_size, (uint32_t *)text, ftp->ftps_mod, ftp->ftps_func);
if(isnflgs == NULL) {
dt_dprintf("scanalyzer found no executable instructions\n");
free(text);
return (-1);
}
uint32_t icnt = (ftp->ftps_size + 3) / 4;
for(i = 0; i < icnt; i++) {
if((isnflgs[i] & 15) == isRsvn) {
dt_dprintf("instruction at offset 0x%x is a reservation type, skipping this function\n", i * 4);
free(isnflgs);
free(text);
return 0;
}
}
end = ftp->ftps_size;
if (strcmp("*", pattern) == 0) {
for (i = 0; i < end; i += 4) {
if (probeable[isnflgs[i / 4]]) {
ftp->ftps_offs[ftp->ftps_noffs++] = i;
} else {
dt_dprintf("instruction at offset 0x%lx is not probeable\n", i);
}
}
} else {
char name[sizeof (i) * 2 + 1];
for (i = 0; i < end; i += 4) {
(void) snprintf(name, sizeof (name), "%x", i);
if (gmatch(name, pattern)) {
if (probeable[isnflgs[i / 4]]) {
ftp->ftps_offs[ftp->ftps_noffs++] = i;
} else {
dt_dprintf("instruction at offset 0x%lx is not probeable\n", i);
}
}
}
}
free(isnflgs);
#endif
free(text);
if (ftp->ftps_noffs > 0) {
if (ioctl(dtp->dt_ftfd, FASTTRAPIOC_MAKEPROBE, ftp) != 0) {
dt_dprintf("fasttrap probe creation ioctl failed: %s\n",
strerror(errno));
return (dt_set_errno(dtp, errno));
}
}
return (ftp->ftps_noffs);
}
#endif // __ppc__ || __ppc64__