MFV illumos
4474 DTrace Userland CTF Support 4475 DTrace userland Keyword 4476 DTrace tests should be better citizens 4479 pid provider types 4480 dof emulation is missing checks MFC after: 2 weeks
This commit is contained in:
commit
8c0e49065f
@ -25,6 +25,7 @@
|
||||
*/
|
||||
/*
|
||||
* Copyright (c) 2012 by Delphix. All rights reserved.
|
||||
* Copyright (c) 2013, Joyent, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
@ -513,6 +514,7 @@ static void
|
||||
print_probe_info(const dtrace_probeinfo_t *p)
|
||||
{
|
||||
char buf[BUFSIZ];
|
||||
char *user;
|
||||
int i;
|
||||
|
||||
oprintf("\n\tProbe Description Attributes\n");
|
||||
@ -536,10 +538,14 @@ print_probe_info(const dtrace_probeinfo_t *p)
|
||||
oprintf("\n\tArgument Types\n");
|
||||
|
||||
for (i = 0; i < p->dtp_argc; i++) {
|
||||
if (p->dtp_argv[i].dtt_flags & DTT_FL_USER)
|
||||
user = "userland ";
|
||||
else
|
||||
user = "";
|
||||
if (ctf_type_name(p->dtp_argv[i].dtt_ctfp,
|
||||
p->dtp_argv[i].dtt_type, buf, sizeof (buf)) == NULL)
|
||||
(void) strlcpy(buf, "(unknown)", sizeof (buf));
|
||||
oprintf("\t\targs[%d]: %s\n", i, buf);
|
||||
oprintf("\t\targs[%d]: %s%s\n", i, user, buf);
|
||||
}
|
||||
|
||||
if (p->dtp_argc == 0)
|
||||
|
@ -0,0 +1,21 @@
|
||||
/*
|
||||
* This file and its contents are supplied under the terms of the
|
||||
* Common Development and Distribution License ("CDDL"), version 1.0.
|
||||
* You may only use this file in accordance with the terms of version
|
||||
* 1.0 of the CDDL.
|
||||
*
|
||||
* A full copy of the text of the CDDL should have accompanied this
|
||||
* source. A copy of the CDDL is also available via the Internet at
|
||||
* http://www.illumos.org/license/CDDL.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 2013 Joyent, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#pragma D option quiet
|
||||
|
||||
BEGIN
|
||||
{
|
||||
trace((pidfoo`int)0);
|
||||
}
|
@ -0,0 +1,21 @@
|
||||
/*
|
||||
* This file and its contents are supplied under the terms of the
|
||||
* Common Development and Distribution License ("CDDL"), version 1.0.
|
||||
* You may only use this file in accordance with the terms of version
|
||||
* 1.0 of the CDDL.
|
||||
*
|
||||
* A full copy of the text of the CDDL should have accompanied this
|
||||
* source. A copy of the CDDL is also available via the Internet at
|
||||
* http://www.illumos.org/license/CDDL.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 2013 Joyent, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#pragma D option quiet
|
||||
|
||||
BEGIN
|
||||
{
|
||||
trace((pid8foo`int)0);
|
||||
}
|
@ -0,0 +1,21 @@
|
||||
/*
|
||||
* This file and its contents are supplied under the terms of the
|
||||
* Common Development and Distribution License ("CDDL"), version 1.0.
|
||||
* You may only use this file in accordance with the terms of version
|
||||
* 1.0 of the CDDL.
|
||||
*
|
||||
* A full copy of the text of the CDDL should have accompanied this
|
||||
* source. A copy of the CDDL is also available via the Internet at
|
||||
* http://www.illumos.org/license/CDDL.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 2013 Joyent, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#pragma D option quiet
|
||||
|
||||
BEGIN
|
||||
{
|
||||
trace((pid0`int)0);
|
||||
}
|
@ -0,0 +1,34 @@
|
||||
#! /usr/bin/ksh
|
||||
#
|
||||
#
|
||||
# This file and its contents are supplied under the terms of the
|
||||
# Common Development and Distribution License ("CDDL"), version 1.0.
|
||||
# You may only use this file in accordance with the terms of version
|
||||
# 1.0 of the CDDL.
|
||||
#
|
||||
# A full copy of the text of the CDDL should have accompanied this
|
||||
# source. A copy of the CDDL is also available via the Internet at
|
||||
# http://www.illumos.org/license/CDDL.
|
||||
#
|
||||
|
||||
#
|
||||
# Copyright (c) 2013 Joyent, Inc. All rights reserved.
|
||||
#
|
||||
|
||||
#
|
||||
# While it's hard to be completely certain that a type of the name we want
|
||||
# doesn't exist, we're going to try to pick a name which is rather unique.
|
||||
#
|
||||
|
||||
if [ $# != 1 ]; then
|
||||
echo expected one argument: '<'dtrace-path'>'
|
||||
exit 2
|
||||
fi
|
||||
|
||||
dtrace=$1
|
||||
t="season_8_mountain_of_madness_t"
|
||||
pid=$$
|
||||
|
||||
rc=`$dtrace -n "BEGIN{ trace(pid$pid`$t)0); }"`
|
||||
|
||||
exit $rc
|
@ -0,0 +1,35 @@
|
||||
#! /usr/bin/ksh
|
||||
#
|
||||
#
|
||||
# This file and its contents are supplied under the terms of the
|
||||
# Common Development and Distribution License ("CDDL"), version 1.0.
|
||||
# You may only use this file in accordance with the terms of version
|
||||
# 1.0 of the CDDL.
|
||||
#
|
||||
# A full copy of the text of the CDDL should have accompanied this
|
||||
# source. A copy of the CDDL is also available via the Internet at
|
||||
# http://www.illumos.org/license/CDDL.
|
||||
#
|
||||
|
||||
#
|
||||
# Copyright (c) 2013 Joyent, Inc. All rights reserved.
|
||||
#
|
||||
|
||||
#
|
||||
# While it's hard to be completely certain that a type of the name we want
|
||||
# doesn't exist, we're going to try to pick a name which is rather
|
||||
# unique. This time we're also going to use the pid$target alias.
|
||||
#
|
||||
|
||||
if [ $# != 1 ]; then
|
||||
echo expected one argument: '<'dtrace-path'>'
|
||||
exit 2
|
||||
fi
|
||||
|
||||
dtrace=$1
|
||||
t="season_8_mountain_of_madness_t"
|
||||
pid=$$
|
||||
|
||||
rc=`$dtrace -n "BEGIN{ trace(pid`$t)0); }"` -p $pid
|
||||
|
||||
exit $rc
|
@ -0,0 +1,90 @@
|
||||
#! /usr/bin/ksh
|
||||
#
|
||||
#
|
||||
# This file and its contents are supplied under the terms of the
|
||||
# Common Development and Distribution License ("CDDL"), version 1.0.
|
||||
# You may only use this file in accordance with the terms of version
|
||||
# 1.0 of the CDDL.
|
||||
#
|
||||
# A full copy of the text of the CDDL should have accompanied this
|
||||
# source. A copy of the CDDL is also available via the Internet at
|
||||
# http://www.illumos.org/license/CDDL.
|
||||
#
|
||||
|
||||
#
|
||||
# Copyright (c) 2013 Joyent, Inc. All rights reserved.
|
||||
#
|
||||
|
||||
#
|
||||
# This test is purposefully using a 64-bit DTrace and thus 64-bit types
|
||||
# when compared with a 32-bit process. This test uses the userland
|
||||
# keyword and so the implicit copyin should access illegal memory and
|
||||
# thus exit.
|
||||
#
|
||||
|
||||
if [ $# != 1 ]; then
|
||||
echo expected one argument: '<'dtrace-path'>'
|
||||
exit 2
|
||||
fi
|
||||
|
||||
dtrace=$1
|
||||
t="zelda_info_t"
|
||||
exe="tst.chasestrings.exe"
|
||||
|
||||
elfdump "./$exe" | grep -q '.SUNW_ctf'
|
||||
if [[ $? -ne 0 ]]; then
|
||||
echo "CTF does not exist in $exe, that's a bug" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
./$exe &
|
||||
pid=$!
|
||||
|
||||
$dtrace -64 -qs /dev/stdin <<EOF
|
||||
typedef struct info {
|
||||
char *zi_gamename;
|
||||
int zi_ndungeons;
|
||||
char *zi_villain;
|
||||
int zi_haszelda;
|
||||
} info_t;
|
||||
|
||||
pid$pid::has_princess:entry
|
||||
/next == 0/
|
||||
{
|
||||
this->t = (userland info_t *)arg0;
|
||||
printf("game: %s, dungeon: %d, villain: %s, zelda: %d\n",
|
||||
stringof(this->t->zi_gamename), this->t->zi_ndungeons,
|
||||
stringof(this->t->zi_villain), this->t->zi_haszelda);
|
||||
next = 1;
|
||||
}
|
||||
|
||||
pid$pid::has_dungeons:entry
|
||||
/next == 1/
|
||||
{
|
||||
this->t = (userland info_t *)arg0;
|
||||
printf("game: %s, dungeon: %d, villain: %s, zelda: %d\n",
|
||||
stringof(this->t->zi_gamename), this->t->zi_ndungeons,
|
||||
stringof(this->t->zi_villain), this->t->zi_haszelda);
|
||||
next = 2;
|
||||
}
|
||||
|
||||
pid$pid::has_villain:entry
|
||||
/next == 2/
|
||||
{
|
||||
this->t = (userland info_t *)arg0;
|
||||
printf("game: %s, dungeon: %d, villain: %s, zelda: %d\n",
|
||||
stringof(this->t->zi_gamename), this->t->zi_ndungeons,
|
||||
stringof(this->t->zi_villain), this->t->zi_haszelda);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
ERROR
|
||||
{
|
||||
exit(1);
|
||||
}
|
||||
EOF
|
||||
rc=$?
|
||||
|
||||
kill -9 $pid
|
||||
|
||||
exit $rc
|
@ -0,0 +1,46 @@
|
||||
/*
|
||||
* This file and its contents are supplied under the terms of the
|
||||
* Common Development and Distribution License ("CDDL"), version 1.0.
|
||||
* You may only use this file in accordance with the terms of version
|
||||
* 1.0 of the CDDL.
|
||||
*
|
||||
* A full copy of the text of the CDDL should have accompanied this
|
||||
* source. A copy of the CDDL is also available via the Internet at
|
||||
* http://www.illumos.org/license/CDDL.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright 2013 (c) Joyent, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This test tries to make sure that we have CTF data for a type that only this
|
||||
* binary would reasonably have. In this case, the
|
||||
* season_7_lisa_the_vegetarian_t.
|
||||
*/
|
||||
#include <unistd.h>
|
||||
|
||||
typedef struct season_7_lisa_the_vegetarian {
|
||||
int fr_salad;
|
||||
} season_7_lisa_the_vegetarian_t;
|
||||
|
||||
int
|
||||
sleeper(season_7_lisa_the_vegetarian_t *lp)
|
||||
{
|
||||
for (;;) {
|
||||
sleep(lp->fr_salad);
|
||||
}
|
||||
/*NOTREACHED*/
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
main(void)
|
||||
{
|
||||
season_7_lisa_the_vegetarian_t l;
|
||||
l.fr_salad = 100;
|
||||
|
||||
sleeper(&l);
|
||||
|
||||
return (0);
|
||||
}
|
@ -0,0 +1,44 @@
|
||||
#! /usr/bin/ksh
|
||||
#
|
||||
#
|
||||
# This file and its contents are supplied under the terms of the
|
||||
# Common Development and Distribution License ("CDDL"), version 1.0.
|
||||
# You may only use this file in accordance with the terms of version
|
||||
# 1.0 of the CDDL.
|
||||
#
|
||||
# A full copy of the text of the CDDL should have accompanied this
|
||||
# source. A copy of the CDDL is also available via the Internet at
|
||||
# http://www.illumos.org/license/CDDL.
|
||||
#
|
||||
|
||||
#
|
||||
# Copyright (c) 2013 Joyent, Inc. All rights reserved.
|
||||
#
|
||||
|
||||
#
|
||||
# Lookup a type that is inside a.out.
|
||||
#
|
||||
|
||||
if [ $# != 1 ]; then
|
||||
echo expected one argument: '<'dtrace-path'>'
|
||||
exit 2
|
||||
fi
|
||||
|
||||
dtrace=$1
|
||||
t="season_7_lisa_the_vegetrian_t *"
|
||||
exe="tst.aouttype.exe"
|
||||
|
||||
elfdump "./$exe" | grep -q '.SUNW_ctf'
|
||||
if [[ $? -ne 0 ]]; then
|
||||
echo "CTF does not exist in $exe, that's a bug" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
./$exe &
|
||||
pid=$!
|
||||
|
||||
rc=`$dtrace -n "BEGIN{ trace((pid$pid\`$t)0); exit(0); }"`
|
||||
|
||||
kill -9 $pid
|
||||
|
||||
exit $rc
|
@ -0,0 +1,79 @@
|
||||
/*
|
||||
* This file and its contents are supplied under the terms of the
|
||||
* Common Development and Distribution License ("CDDL"), version 1.0.
|
||||
* You may only use this file in accordance with the terms of version
|
||||
* 1.0 of the CDDL.
|
||||
*
|
||||
* A full copy of the text of the CDDL should have accompanied this
|
||||
* source. A copy of the CDDL is also available via the Internet at
|
||||
* http://www.illumos.org/license/CDDL.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright 2013 (c) Joyent, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This test takes data from the current binary which is basically running in a
|
||||
* loop between two functions and our goal is to have two unique types that they
|
||||
* contain which we can print.
|
||||
*/
|
||||
|
||||
#include <unistd.h>
|
||||
|
||||
typedef struct zelda_info {
|
||||
char *zi_gamename;
|
||||
int zi_ndungeons;
|
||||
char *zi_villain;
|
||||
int zi_haszelda;
|
||||
} zelda_info_t;
|
||||
|
||||
static int
|
||||
has_princess(zelda_info_t *z)
|
||||
{
|
||||
return (z->zi_haszelda);
|
||||
}
|
||||
|
||||
static int
|
||||
has_dungeons(zelda_info_t *z)
|
||||
{
|
||||
return (z->zi_ndungeons != 0);
|
||||
}
|
||||
|
||||
static const char *
|
||||
has_villain(zelda_info_t *z)
|
||||
{
|
||||
return (z->zi_villain);
|
||||
}
|
||||
|
||||
int
|
||||
main(void)
|
||||
{
|
||||
zelda_info_t oot;
|
||||
zelda_info_t la;
|
||||
zelda_info_t lttp;
|
||||
|
||||
oot.zi_gamename = "Ocarina of Time";
|
||||
oot.zi_ndungeons = 10;
|
||||
oot.zi_villain = "Ganondorf";
|
||||
oot.zi_haszelda = 1;
|
||||
|
||||
la.zi_gamename = "Link's Awakening";
|
||||
la.zi_ndungeons = 9;
|
||||
la.zi_villain = "Nightmare";
|
||||
la.zi_haszelda = 0;
|
||||
|
||||
lttp.zi_gamename = "A Link to the Past";
|
||||
lttp.zi_ndungeons = 12;
|
||||
lttp.zi_villain = "Ganon";
|
||||
lttp.zi_haszelda = 1;
|
||||
|
||||
for (;;) {
|
||||
(void) has_princess(&oot);
|
||||
(void) has_dungeons(&la);
|
||||
(void) has_villain(<tp);
|
||||
sleep(1);
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
@ -0,0 +1,76 @@
|
||||
#! /usr/bin/ksh
|
||||
#
|
||||
#
|
||||
# This file and its contents are supplied under the terms of the
|
||||
# Common Development and Distribution License ("CDDL"), version 1.0.
|
||||
# You may only use this file in accordance with the terms of version
|
||||
# 1.0 of the CDDL.
|
||||
#
|
||||
# A full copy of the text of the CDDL should have accompanied this
|
||||
# source. A copy of the CDDL is also available via the Internet at
|
||||
# http://www.illumos.org/license/CDDL.
|
||||
#
|
||||
|
||||
#
|
||||
# Copyright (c) 2013 Joyent, Inc. All rights reserved.
|
||||
#
|
||||
|
||||
#
|
||||
# This test is checking that we can read members and that pointers inside
|
||||
# members point to valid data that is intelligible, eg. strings.
|
||||
#
|
||||
|
||||
if [ $# != 1 ]; then
|
||||
echo expected one argument: '<'dtrace-path'>'
|
||||
exit 2
|
||||
fi
|
||||
|
||||
dtrace=$1
|
||||
t="zelda_info_t"
|
||||
exe="tst.chasestrings.exe"
|
||||
|
||||
elfdump "./$exe" | grep -q '.SUNW_ctf'
|
||||
if [[ $? -ne 0 ]]; then
|
||||
echo "CTF does not exist in $exe, that's a bug" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
./$exe &
|
||||
pid=$!
|
||||
|
||||
$dtrace -qs /dev/stdin <<EOF
|
||||
pid$pid::has_princess:entry
|
||||
/next == 0/
|
||||
{
|
||||
this->t = (pid$pid\`$t *)(copyin(arg0, sizeof (pid$pid\`$t)));
|
||||
printf("game: %s, dungeon: %d, villain: %s, zelda: %d\n",
|
||||
copyinstr((uintptr_t)this->t->zi_gamename), this->t->zi_ndungeons,
|
||||
copyinstr((uintptr_t)this->t->zi_villain), this->t->zi_haszelda);
|
||||
next = 1;
|
||||
}
|
||||
|
||||
pid$pid::has_dungeons:entry
|
||||
/next == 1/
|
||||
{
|
||||
this->t = (pid$pid\`$t *)(copyin(arg0, sizeof (pid$pid\`$t)));
|
||||
printf("game: %s, dungeon: %d, villain: %s, zelda: %d\n",
|
||||
copyinstr((uintptr_t)this->t->zi_gamename), this->t->zi_ndungeons,
|
||||
copyinstr((uintptr_t)this->t->zi_villain), this->t->zi_haszelda);
|
||||
next = 2;
|
||||
}
|
||||
|
||||
pid$pid::has_villain:entry
|
||||
/next == 2/
|
||||
{
|
||||
this->t = (pid$pid\`$t *)(copyin(arg0, sizeof (pid$pid\`$t)));
|
||||
printf("game: %s, dungeon: %d, villain: %s, zelda: %d\n",
|
||||
copyinstr((uintptr_t)this->t->zi_gamename), this->t->zi_ndungeons,
|
||||
copyinstr((uintptr_t)this->t->zi_villain), this->t->zi_haszelda);
|
||||
exit(0);
|
||||
}
|
||||
EOF
|
||||
rc=$?
|
||||
|
||||
kill -9 $pid
|
||||
|
||||
exit $rc
|
@ -0,0 +1,4 @@
|
||||
game: Ocarina of Time, dungeon: 10, villain: Ganondorf, zelda: 1
|
||||
game: Link's Awakening, dungeon: 9, villain: Nightmare, zelda: 0
|
||||
game: A Link to the Past, dungeon: 12, villain: Ganon, zelda: 1
|
||||
|
@ -0,0 +1,29 @@
|
||||
/*
|
||||
* This file and its contents are supplied under the terms of the
|
||||
* Common Development and Distribution License ("CDDL"), version 1.0.
|
||||
* You may only use this file in accordance with the terms of version
|
||||
* 1.0 of the CDDL.
|
||||
*
|
||||
* A full copy of the text of the CDDL should have accompanied this
|
||||
* source. A copy of the CDDL is also available via the Internet at
|
||||
* http://www.illumos.org/license/CDDL.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright 2013 (c) Joyent, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
/*
|
||||
* We're linked against libc which has types, though we do not.
|
||||
*/
|
||||
#include <unistd.h>
|
||||
|
||||
int
|
||||
main(void)
|
||||
{
|
||||
for (;;) {
|
||||
sleep(1000);
|
||||
}
|
||||
/*NOTREACHED*/
|
||||
return (0);
|
||||
}
|
@ -0,0 +1,45 @@
|
||||
#! /usr/bin/ksh
|
||||
#
|
||||
#
|
||||
# This file and its contents are supplied under the terms of the
|
||||
# Common Development and Distribution License ("CDDL"), version 1.0.
|
||||
# You may only use this file in accordance with the terms of version
|
||||
# 1.0 of the CDDL.
|
||||
#
|
||||
# A full copy of the text of the CDDL should have accompanied this
|
||||
# source. A copy of the CDDL is also available via the Internet at
|
||||
# http://www.illumos.org/license/CDDL.
|
||||
#
|
||||
|
||||
#
|
||||
# Copyright (c) 2013 Joyent, Inc. All rights reserved.
|
||||
#
|
||||
|
||||
#
|
||||
# Here we want to make sure that the program in question does not have ctf data
|
||||
# in its a.out; however, we can get types out of a linked libc.
|
||||
#
|
||||
|
||||
if [ $# != 1 ]; then
|
||||
echo expected one argument: '<'dtrace-path'>'
|
||||
exit 2
|
||||
fi
|
||||
|
||||
dtrace=$1
|
||||
t="int"
|
||||
exe="tst.libtype.exe"
|
||||
|
||||
elfdump "./$exe" | grep -q '.SUNW_ctf'
|
||||
if [[ $? -eq 0 ]]; then
|
||||
echo "CTF exists in $exe, that's a bug" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
./$exe &
|
||||
pid=$!
|
||||
|
||||
rc=`$dtrace -n "BEGIN{ trace((pid$pid\`$t)0); exit(0); }"`
|
||||
|
||||
kill -9 $pid
|
||||
|
||||
exit $rc
|
@ -0,0 +1,44 @@
|
||||
#! /usr/bin/ksh
|
||||
#
|
||||
#
|
||||
# This file and its contents are supplied under the terms of the
|
||||
# Common Development and Distribution License ("CDDL"), version 1.0.
|
||||
# You may only use this file in accordance with the terms of version
|
||||
# 1.0 of the CDDL.
|
||||
#
|
||||
# A full copy of the text of the CDDL should have accompanied this
|
||||
# source. A copy of the CDDL is also available via the Internet at
|
||||
# http://www.illumos.org/license/CDDL.
|
||||
#
|
||||
|
||||
#
|
||||
# Copyright (c) 2013 Joyent, Inc. All rights reserved.
|
||||
#
|
||||
|
||||
#
|
||||
# We should be able to see both strstr from libc and from ld on an
|
||||
# alternate linkmap.
|
||||
#
|
||||
|
||||
if [ $# != 1 ]; then
|
||||
echo expected one argument: '<'dtrace-path'>'
|
||||
exit 2
|
||||
fi
|
||||
|
||||
dtrace=$1
|
||||
|
||||
$dtrace -q -p $$ -s /dev/stdin <<EOF
|
||||
pid\$target:LM1\`ld.so.1:strstr:entry,
|
||||
pid\$target:libc.so.1:strstr:entry
|
||||
{
|
||||
exit (0);
|
||||
}
|
||||
|
||||
BEGIN
|
||||
{
|
||||
exit (0);
|
||||
}
|
||||
EOF
|
||||
rc=$?
|
||||
|
||||
exit $rc
|
@ -0,0 +1,69 @@
|
||||
#! /usr/bin/ksh
|
||||
#
|
||||
#
|
||||
# This file and its contents are supplied under the terms of the
|
||||
# Common Development and Distribution License ("CDDL"), version 1.0.
|
||||
# You may only use this file in accordance with the terms of version
|
||||
# 1.0 of the CDDL.
|
||||
#
|
||||
# A full copy of the text of the CDDL should have accompanied this
|
||||
# source. A copy of the CDDL is also available via the Internet at
|
||||
# http://www.illumos.org/license/CDDL.
|
||||
#
|
||||
|
||||
#
|
||||
# Copyright (c) 2013 Joyent, Inc. All rights reserved.
|
||||
#
|
||||
|
||||
#
|
||||
# Use print() on userland CTF types and verify we get the data we expect.
|
||||
#
|
||||
|
||||
if [ $# != 1 ]; then
|
||||
echo expected one argument: '<'dtrace-path'>'
|
||||
exit 2
|
||||
fi
|
||||
|
||||
dtrace=$1
|
||||
t="final_fantasy_info_t"
|
||||
exe="tst.printtype.exe"
|
||||
|
||||
elfdump "./$exe" | grep -q '.SUNW_ctf'
|
||||
if [[ $? -ne 0 ]]; then
|
||||
echo "CTF does not exist in $exe, that's a bug" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
./$exe &
|
||||
pid=$!
|
||||
|
||||
$dtrace -qs /dev/stdin <<EOF
|
||||
pid$pid::ff_getgameid:entry
|
||||
/next == 0/
|
||||
{
|
||||
print(*args[0]);
|
||||
printf("\n");
|
||||
next = 1;
|
||||
}
|
||||
|
||||
pid$pid::ff_getpartysize:entry
|
||||
/next == 1/
|
||||
{
|
||||
print(*args[0]);
|
||||
printf("\n");
|
||||
next = 2;
|
||||
}
|
||||
|
||||
pid$pid::ff_getsummons:entry
|
||||
/next == 2/
|
||||
{
|
||||
print(*args[0]);
|
||||
printf("\n");
|
||||
exit(0);
|
||||
}
|
||||
EOF
|
||||
rc=$?
|
||||
|
||||
kill -9 $pid
|
||||
|
||||
exit $rc
|
@ -0,0 +1,70 @@
|
||||
#! /usr/bin/ksh
|
||||
#
|
||||
#
|
||||
# This file and its contents are supplied under the terms of the
|
||||
# Common Development and Distribution License ("CDDL"), version 1.0.
|
||||
# You may only use this file in accordance with the terms of version
|
||||
# 1.0 of the CDDL.
|
||||
#
|
||||
# A full copy of the text of the CDDL should have accompanied this
|
||||
# source. A copy of the CDDL is also available via the Internet at
|
||||
# http://www.illumos.org/license/CDDL.
|
||||
#
|
||||
|
||||
#
|
||||
# Copyright (c) 2013 Joyent, Inc. All rights reserved.
|
||||
#
|
||||
|
||||
#
|
||||
# Use print() on userland CTF types and verify we get the data we
|
||||
# expect. This time, use $target to make sure that path works correctly.
|
||||
#
|
||||
|
||||
if [ $# != 1 ]; then
|
||||
echo expected one argument: '<'dtrace-path'>'
|
||||
exit 2
|
||||
fi
|
||||
|
||||
dtrace=$1
|
||||
t="final_fantasy_info_t"
|
||||
exe="tst.printtype.exe"
|
||||
|
||||
elfdump "./$exe" | grep -q '.SUNW_ctf'
|
||||
if [[ $? -ne 0 ]]; then
|
||||
echo "CTF does not exist in $exe, that's a bug" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
./$exe &
|
||||
pid=$!
|
||||
|
||||
$dtrace -p $pid -qs /dev/stdin <<EOF
|
||||
pid\$target::ff_getgameid:entry
|
||||
/next == 0/
|
||||
{
|
||||
print(*args[0]);
|
||||
printf("\n");
|
||||
next = 1;
|
||||
}
|
||||
|
||||
pid\$target::ff_getpartysize:entry
|
||||
/next == 1/
|
||||
{
|
||||
print(*args[0]);
|
||||
printf("\n");
|
||||
next = 2;
|
||||
}
|
||||
|
||||
pid\$target::ff_getsummons:entry
|
||||
/next == 2/
|
||||
{
|
||||
print(*args[0]);
|
||||
printf("\n");
|
||||
exit(0);
|
||||
}
|
||||
EOF
|
||||
rc=$?
|
||||
|
||||
kill -9 $pid
|
||||
|
||||
exit $rc
|
@ -0,0 +1,72 @@
|
||||
/*
|
||||
* This file and its contents are supplied under the terms of the
|
||||
* Common Development and Distribution License ("CDDL"), version 1.0.
|
||||
* You may only use this file in accordance with the terms of version
|
||||
* 1.0 of the CDDL.
|
||||
*
|
||||
* A full copy of the text of the CDDL should have accompanied this
|
||||
* source. A copy of the CDDL is also available via the Internet at
|
||||
* http://www.illumos.org/license/CDDL.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright 2013 (c) Joyent, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
/*
|
||||
* The point of this is to use print() on various functions to make sure that we
|
||||
* can print basic structures. Note that we purposefully are making sure that
|
||||
* there are no pointers here.
|
||||
*/
|
||||
#include <unistd.h>
|
||||
|
||||
typedef struct final_fantasy_info {
|
||||
int ff_gameid;
|
||||
int ff_partysize;
|
||||
int ff_hassummons;
|
||||
} final_fantasy_info_t;
|
||||
|
||||
static int
|
||||
ff_getgameid(final_fantasy_info_t *f)
|
||||
{
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
ff_getpartysize(final_fantasy_info_t *f)
|
||||
{
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
ff_getsummons(final_fantasy_info_t *f)
|
||||
{
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
main(void)
|
||||
{
|
||||
final_fantasy_info_t ffiii, ffx, ffi;
|
||||
|
||||
ffi.ff_gameid = 1;
|
||||
ffi.ff_partysize = 4;
|
||||
ffi.ff_hassummons = 0;
|
||||
|
||||
ffiii.ff_gameid = 6;
|
||||
ffiii.ff_partysize = 4;
|
||||
ffiii.ff_hassummons = 1;
|
||||
|
||||
ffx.ff_gameid = 10;
|
||||
ffx.ff_partysize = 3;
|
||||
ffx.ff_hassummons = 1;
|
||||
|
||||
for (;;) {
|
||||
ff_getgameid(&ffi);
|
||||
ff_getpartysize(&ffx);
|
||||
ff_getsummons(&ffiii);
|
||||
sleep(1);
|
||||
}
|
||||
/*NOTREACHED*/
|
||||
return (0);
|
||||
}
|
@ -0,0 +1,69 @@
|
||||
#! /usr/bin/ksh
|
||||
#
|
||||
#
|
||||
# This file and its contents are supplied under the terms of the
|
||||
# Common Development and Distribution License ("CDDL"), version 1.0.
|
||||
# You may only use this file in accordance with the terms of version
|
||||
# 1.0 of the CDDL.
|
||||
#
|
||||
# A full copy of the text of the CDDL should have accompanied this
|
||||
# source. A copy of the CDDL is also available via the Internet at
|
||||
# http://www.illumos.org/license/CDDL.
|
||||
#
|
||||
|
||||
#
|
||||
# Copyright (c) 2013 Joyent, Inc. All rights reserved.
|
||||
#
|
||||
|
||||
#
|
||||
# Use print() on userland CTF types and verify we get the data we expect.
|
||||
#
|
||||
|
||||
if [ $# != 1 ]; then
|
||||
echo expected one argument: '<'dtrace-path'>'
|
||||
exit 2
|
||||
fi
|
||||
|
||||
dtrace=$1
|
||||
t="final_fantasy_info_t"
|
||||
exe="tst.printtype.exe"
|
||||
|
||||
elfdump "./$exe" | grep -q '.SUNW_ctf'
|
||||
if [[ $? -ne 0 ]]; then
|
||||
echo "CTF does not exist in $exe, that's a bug" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
./$exe &
|
||||
pid=$!
|
||||
|
||||
$dtrace -qs /dev/stdin <<EOF
|
||||
pid$pid::ff_getgameid:entry
|
||||
/next == 0/
|
||||
{
|
||||
print(*(pid$pid\`$t *)(copyin(arg0, sizeof (pid$pid\`$t))));
|
||||
printf("\n");
|
||||
next = 1;
|
||||
}
|
||||
|
||||
pid$pid::ff_getpartysize:entry
|
||||
/next == 1/
|
||||
{
|
||||
print(*(pid$pid\`$t *)(copyin(arg0, sizeof (pid$pid\`$t))));
|
||||
printf("\n");
|
||||
next = 2;
|
||||
}
|
||||
|
||||
pid$pid::ff_getsummons:entry
|
||||
/next == 2/
|
||||
{
|
||||
print(*(pid$pid\`$t *)(copyin(arg0, sizeof (pid$pid\`$t))));
|
||||
printf("\n");
|
||||
exit(0);
|
||||
}
|
||||
EOF
|
||||
rc=$?
|
||||
|
||||
kill -9 $pid
|
||||
|
||||
exit $rc
|
@ -0,0 +1,16 @@
|
||||
final_fantasy_info_t {
|
||||
int ff_gameid = 0x1
|
||||
int ff_partysize = 0x4
|
||||
int ff_hassummons = 0
|
||||
}
|
||||
final_fantasy_info_t {
|
||||
int ff_gameid = 0xa
|
||||
int ff_partysize = 0x3
|
||||
int ff_hassummons = 0x1
|
||||
}
|
||||
final_fantasy_info_t {
|
||||
int ff_gameid = 0x6
|
||||
int ff_partysize = 0x4
|
||||
int ff_hassummons = 0x1
|
||||
}
|
||||
|
@ -0,0 +1,70 @@
|
||||
#! /usr/bin/ksh
|
||||
#
|
||||
#
|
||||
# This file and its contents are supplied under the terms of the
|
||||
# Common Development and Distribution License ("CDDL"), version 1.0.
|
||||
# You may only use this file in accordance with the terms of version
|
||||
# 1.0 of the CDDL.
|
||||
#
|
||||
# A full copy of the text of the CDDL should have accompanied this
|
||||
# source. A copy of the CDDL is also available via the Internet at
|
||||
# http://www.illumos.org/license/CDDL.
|
||||
#
|
||||
|
||||
#
|
||||
# Copyright (c) 2013 Joyent, Inc. All rights reserved.
|
||||
#
|
||||
|
||||
#
|
||||
# Use print() on userland CTF types and verify we get the data we
|
||||
# expect. Use the pid` alias for $target.
|
||||
#
|
||||
|
||||
if [ $# != 1 ]; then
|
||||
echo expected one argument: '<'dtrace-path'>'
|
||||
exit 2
|
||||
fi
|
||||
|
||||
dtrace=$1
|
||||
t="final_fantasy_info_t"
|
||||
exe="tst.printtype.exe"
|
||||
|
||||
elfdump "./$exe" | grep -q '.SUNW_ctf'
|
||||
if [[ $? -ne 0 ]]; then
|
||||
echo "CTF does not exist in $exe, that's a bug" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
./$exe &
|
||||
pid=$!
|
||||
|
||||
$dtrace -p $pid -qs /dev/stdin <<EOF
|
||||
pid\$target::ff_getgameid:entry
|
||||
/next == 0/
|
||||
{
|
||||
print(*(pid\`$t *)(copyin(arg0, sizeof (pid\`$t))));
|
||||
printf("\n");
|
||||
next = 1;
|
||||
}
|
||||
|
||||
pid\$target::ff_getpartysize:entry
|
||||
/next == 1/
|
||||
{
|
||||
print(*(pid\`$t *)(copyin(arg0, sizeof (pid\`$t))));
|
||||
printf("\n");
|
||||
next = 2;
|
||||
}
|
||||
|
||||
pid\$target::ff_getsummons:entry
|
||||
/next == 2/
|
||||
{
|
||||
print(*(pid\`$t *)(copyin(arg0, sizeof (pid\`$t))));
|
||||
printf("\n");
|
||||
exit(0);
|
||||
}
|
||||
EOF
|
||||
rc=$?
|
||||
|
||||
kill -9 $pid
|
||||
|
||||
exit $rc
|
@ -0,0 +1,83 @@
|
||||
#! /usr/bin/ksh
|
||||
#
|
||||
#
|
||||
# This file and its contents are supplied under the terms of the
|
||||
# Common Development and Distribution License ("CDDL"), version 1.0.
|
||||
# You may only use this file in accordance with the terms of version
|
||||
# 1.0 of the CDDL.
|
||||
#
|
||||
# A full copy of the text of the CDDL should have accompanied this
|
||||
# source. A copy of the CDDL is also available via the Internet at
|
||||
# http://www.illumos.org/license/CDDL.
|
||||
#
|
||||
|
||||
#
|
||||
# Copyright (c) 2013 Joyent, Inc. All rights reserved.
|
||||
#
|
||||
|
||||
#
|
||||
# Simple test that if we manually use the userland keyword that it
|
||||
# works.
|
||||
#
|
||||
|
||||
if [ $# != 1 ]; then
|
||||
echo expected one argument: '<'dtrace-path'>'
|
||||
exit 2
|
||||
fi
|
||||
|
||||
dtrace=$1
|
||||
t="zelda_info_t"
|
||||
exe="tst.chasestrings.exe"
|
||||
|
||||
elfdump "./$exe" | grep -q '.SUNW_ctf'
|
||||
if [[ $? -ne 0 ]]; then
|
||||
echo "CTF does not exist in $exe, that's a bug" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
./$exe &
|
||||
pid=$!
|
||||
|
||||
$dtrace -32 -qs /dev/stdin <<EOF
|
||||
typedef struct info {
|
||||
char *zi_gamename;
|
||||
int zi_ndungeons;
|
||||
char *zi_villain;
|
||||
int zi_haszelda;
|
||||
} info_t;
|
||||
|
||||
pid$pid::has_princess:entry
|
||||
/next == 0/
|
||||
{
|
||||
this->t = (userland info_t *)arg0;
|
||||
printf("game: %s, dungeon: %d, villain: %s, zelda: %d\n",
|
||||
stringof(this->t->zi_gamename), this->t->zi_ndungeons,
|
||||
stringof(this->t->zi_villain), this->t->zi_haszelda);
|
||||
next = 1;
|
||||
}
|
||||
|
||||
pid$pid::has_dungeons:entry
|
||||
/next == 1/
|
||||
{
|
||||
this->t = (userland info_t *)arg0;
|
||||
printf("game: %s, dungeon: %d, villain: %s, zelda: %d\n",
|
||||
stringof(this->t->zi_gamename), this->t->zi_ndungeons,
|
||||
stringof(this->t->zi_villain), this->t->zi_haszelda);
|
||||
next = 2;
|
||||
}
|
||||
|
||||
pid$pid::has_villain:entry
|
||||
/next == 2/
|
||||
{
|
||||
this->t = (userland info_t *)arg0;
|
||||
printf("game: %s, dungeon: %d, villain: %s, zelda: %d\n",
|
||||
stringof(this->t->zi_gamename), this->t->zi_ndungeons,
|
||||
stringof(this->t->zi_villain), this->t->zi_haszelda);
|
||||
exit(0);
|
||||
}
|
||||
EOF
|
||||
rc=$?
|
||||
|
||||
kill -9 $pid
|
||||
|
||||
exit $rc
|
@ -0,0 +1,4 @@
|
||||
game: Ocarina of Time, dungeon: 10, villain: Ganondorf, zelda: 1
|
||||
game: Link's Awakening, dungeon: 9, villain: Nightmare, zelda: 0
|
||||
game: A Link to the Past, dungeon: 12, villain: Ganon, zelda: 1
|
||||
|
@ -0,0 +1,72 @@
|
||||
#! /usr/bin/ksh
|
||||
#
|
||||
#
|
||||
# This file and its contents are supplied under the terms of the
|
||||
# Common Development and Distribution License ("CDDL"), version 1.0.
|
||||
# You may only use this file in accordance with the terms of version
|
||||
# 1.0 of the CDDL.
|
||||
#
|
||||
# A full copy of the text of the CDDL should have accompanied this
|
||||
# source. A copy of the CDDL is also available via the Internet at
|
||||
# http://www.illumos.org/license/CDDL.
|
||||
#
|
||||
|
||||
#
|
||||
# Copyright (c) 2013 Joyent, Inc. All rights reserved.
|
||||
#
|
||||
|
||||
#
|
||||
# This test is checking that we can read members and that pointers inside
|
||||
# members point to valid data that is intelligible, eg. strings.
|
||||
#
|
||||
|
||||
if [ $# != 1 ]; then
|
||||
echo expected one argument: '<'dtrace-path'>'
|
||||
exit 2
|
||||
fi
|
||||
|
||||
dtrace=$1
|
||||
exe="tst.chasestrings.exe"
|
||||
|
||||
elfdump "./$exe" | grep -q '.SUNW_ctf'
|
||||
if [[ $? -ne 0 ]]; then
|
||||
echo "CTF does not exist in $exe, that's a bug" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
./$exe &
|
||||
pid=$!
|
||||
|
||||
$dtrace -qs /dev/stdin <<EOF
|
||||
pid$pid::has_princess:entry
|
||||
/next == 0/
|
||||
{
|
||||
printf("game: %s, dungeon: %d, villain: %s, zelda: %d\n",
|
||||
stringof(args[0]->zi_gamename), args[0]->zi_ndungeons,
|
||||
stringof(args[0]->zi_villain), args[0]->zi_haszelda);
|
||||
next = 1;
|
||||
}
|
||||
|
||||
pid$pid::has_dungeons:entry
|
||||
/next == 1/
|
||||
{
|
||||
printf("game: %s, dungeon: %d, villain: %s, zelda: %d\n",
|
||||
stringof(args[0]->zi_gamename), args[0]->zi_ndungeons,
|
||||
stringof(args[0]->zi_villain), args[0]->zi_haszelda);
|
||||
next = 2;
|
||||
}
|
||||
|
||||
pid$pid::has_villain:entry
|
||||
/next == 2/
|
||||
{
|
||||
printf("game: %s, dungeon: %d, villain: %s, zelda: %d\n",
|
||||
stringof(args[0]->zi_gamename), args[0]->zi_ndungeons,
|
||||
stringof(args[0]->zi_villain), args[0]->zi_haszelda);
|
||||
exit(0);
|
||||
}
|
||||
EOF
|
||||
rc=$?
|
||||
|
||||
kill -9 $pid
|
||||
|
||||
exit $rc
|
@ -0,0 +1,4 @@
|
||||
game: Ocarina of Time, dungeon: 10, villain: Ganondorf, zelda: 1
|
||||
game: Link's Awakening, dungeon: 9, villain: Nightmare, zelda: 0
|
||||
game: A Link to the Past, dungeon: 12, villain: Ganon, zelda: 1
|
||||
|
@ -25,7 +25,7 @@
|
||||
* Use is subject to license terms.
|
||||
*/
|
||||
/*
|
||||
* Copyright (c) 2012, Joyent, Inc. All rights reserved.
|
||||
* Copyright (c) 2013, Joyent, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <ctf_impl.h>
|
||||
@ -787,6 +787,92 @@ ctf_bufopen(const ctf_sect_t *ctfsect, const ctf_sect_t *symsect,
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Dupliate a ctf_file_t and its underlying section information into a new
|
||||
* container. This works by copying the three ctf_sect_t's of the original
|
||||
* container if they exist and passing those into ctf_bufopen. To copy those, we
|
||||
* mmap anonymous memory with ctf_data_alloc and bcopy the data across. It's not
|
||||
* the cheapest thing, but it's what we've got.
|
||||
*/
|
||||
ctf_file_t *
|
||||
ctf_dup(ctf_file_t *ofp)
|
||||
{
|
||||
ctf_file_t *fp;
|
||||
ctf_sect_t ctfsect, symsect, strsect;
|
||||
ctf_sect_t *ctp, *symp, *strp;
|
||||
void *cbuf, *symbuf, *strbuf;
|
||||
int err;
|
||||
|
||||
cbuf = symbuf = strbuf = NULL;
|
||||
/*
|
||||
* The ctfsect isn't allowed to not exist, but the symbol and string
|
||||
* section might not. We only need to copy the data of the section, not
|
||||
* the name, as ctf_bufopen will take care of that.
|
||||
*/
|
||||
bcopy(&ofp->ctf_data, &ctfsect, sizeof (ctf_sect_t));
|
||||
cbuf = ctf_data_alloc(ctfsect.cts_size);
|
||||
if (cbuf == NULL) {
|
||||
(void) ctf_set_errno(ofp, ECTF_MMAP);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
bcopy(ctfsect.cts_data, cbuf, ctfsect.cts_size);
|
||||
ctf_data_protect(cbuf, ctfsect.cts_size);
|
||||
ctfsect.cts_data = cbuf;
|
||||
ctfsect.cts_offset = 0;
|
||||
ctp = &ctfsect;
|
||||
|
||||
if (ofp->ctf_symtab.cts_data != NULL) {
|
||||
bcopy(&ofp->ctf_symtab, &symsect, sizeof (ctf_sect_t));
|
||||
symbuf = ctf_data_alloc(symsect.cts_size);
|
||||
if (symbuf == NULL) {
|
||||
(void) ctf_set_errno(ofp, ECTF_MMAP);
|
||||
goto err;
|
||||
}
|
||||
bcopy(symsect.cts_data, symbuf, symsect.cts_size);
|
||||
ctf_data_protect(symbuf, symsect.cts_size);
|
||||
symsect.cts_data = symbuf;
|
||||
symsect.cts_offset = 0;
|
||||
symp = &symsect;
|
||||
} else {
|
||||
symp = NULL;
|
||||
}
|
||||
|
||||
if (ofp->ctf_strtab.cts_data != NULL) {
|
||||
bcopy(&ofp->ctf_strtab, &strsect, sizeof (ctf_sect_t));
|
||||
strbuf = ctf_data_alloc(strsect.cts_size);
|
||||
if (strbuf == NULL) {
|
||||
(void) ctf_set_errno(ofp, ECTF_MMAP);
|
||||
goto err;
|
||||
}
|
||||
bcopy(strsect.cts_data, strbuf, strsect.cts_size);
|
||||
ctf_data_protect(strbuf, strsect.cts_size);
|
||||
strsect.cts_data = strbuf;
|
||||
strsect.cts_offset = 0;
|
||||
strp = &strsect;
|
||||
} else {
|
||||
strp = NULL;
|
||||
}
|
||||
|
||||
fp = ctf_bufopen(ctp, symp, strp, &err);
|
||||
if (fp == NULL) {
|
||||
(void) ctf_set_errno(ofp, err);
|
||||
goto err;
|
||||
}
|
||||
|
||||
fp->ctf_flags |= LCTF_MMAP;
|
||||
|
||||
return (fp);
|
||||
|
||||
err:
|
||||
ctf_data_free(cbuf, ctfsect.cts_size);
|
||||
if (symbuf != NULL)
|
||||
ctf_data_free(symbuf, symsect.cts_size);
|
||||
if (strbuf != NULL)
|
||||
ctf_data_free(strbuf, strsect.cts_size);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Close the specified CTF container and free associated data structures. Note
|
||||
* that ctf_close() is a reference counted operation: if the specified file is
|
||||
|
@ -25,8 +25,6 @@
|
||||
* Use is subject to license terms.
|
||||
*/
|
||||
|
||||
#pragma ident "%Z%%M% %I% %E% SMI"
|
||||
|
||||
#include <ctf_impl.h>
|
||||
|
||||
ssize_t
|
||||
@ -199,8 +197,9 @@ ctf_type_resolve(ctf_file_t *fp, ctf_id_t type)
|
||||
* Lookup the given type ID and print a string name for it into buf. Return
|
||||
* the actual number of bytes (not including \0) needed to format the name.
|
||||
*/
|
||||
ssize_t
|
||||
ctf_type_lname(ctf_file_t *fp, ctf_id_t type, char *buf, size_t len)
|
||||
static ssize_t
|
||||
ctf_type_qlname(ctf_file_t *fp, ctf_id_t type, char *buf, size_t len,
|
||||
const char *qname)
|
||||
{
|
||||
ctf_decl_t cd;
|
||||
ctf_decl_node_t *cdp;
|
||||
@ -255,6 +254,8 @@ ctf_type_lname(ctf_file_t *fp, ctf_id_t type, char *buf, size_t len)
|
||||
case CTF_K_INTEGER:
|
||||
case CTF_K_FLOAT:
|
||||
case CTF_K_TYPEDEF:
|
||||
if (qname != NULL)
|
||||
ctf_decl_sprintf(&cd, "%s`", qname);
|
||||
ctf_decl_sprintf(&cd, "%s", name);
|
||||
break;
|
||||
case CTF_K_POINTER:
|
||||
@ -268,13 +269,22 @@ ctf_type_lname(ctf_file_t *fp, ctf_id_t type, char *buf, size_t len)
|
||||
break;
|
||||
case CTF_K_STRUCT:
|
||||
case CTF_K_FORWARD:
|
||||
ctf_decl_sprintf(&cd, "struct %s", name);
|
||||
ctf_decl_sprintf(&cd, "struct ");
|
||||
if (qname != NULL)
|
||||
ctf_decl_sprintf(&cd, "%s`", qname);
|
||||
ctf_decl_sprintf(&cd, "%s", name);
|
||||
break;
|
||||
case CTF_K_UNION:
|
||||
ctf_decl_sprintf(&cd, "union %s", name);
|
||||
ctf_decl_sprintf(&cd, "union ");
|
||||
if (qname != NULL)
|
||||
ctf_decl_sprintf(&cd, "%s`", qname);
|
||||
ctf_decl_sprintf(&cd, "%s", name);
|
||||
break;
|
||||
case CTF_K_ENUM:
|
||||
ctf_decl_sprintf(&cd, "enum %s", name);
|
||||
ctf_decl_sprintf(&cd, "enum ");
|
||||
if (qname != NULL)
|
||||
ctf_decl_sprintf(&cd, "%s`", qname);
|
||||
ctf_decl_sprintf(&cd, "%s", name);
|
||||
break;
|
||||
case CTF_K_VOLATILE:
|
||||
ctf_decl_sprintf(&cd, "volatile");
|
||||
@ -301,6 +311,12 @@ ctf_type_lname(ctf_file_t *fp, ctf_id_t type, char *buf, size_t len)
|
||||
return (cd.cd_len);
|
||||
}
|
||||
|
||||
ssize_t
|
||||
ctf_type_lname(ctf_file_t *fp, ctf_id_t type, char *buf, size_t len)
|
||||
{
|
||||
return (ctf_type_qlname(fp, type, buf, len, NULL));
|
||||
}
|
||||
|
||||
/*
|
||||
* Lookup the given type ID and print a string name for it into buf. If buf
|
||||
* is too small, return NULL: the ECTF_NAMELEN error is set on 'fp' for us.
|
||||
@ -308,10 +324,19 @@ ctf_type_lname(ctf_file_t *fp, ctf_id_t type, char *buf, size_t len)
|
||||
char *
|
||||
ctf_type_name(ctf_file_t *fp, ctf_id_t type, char *buf, size_t len)
|
||||
{
|
||||
ssize_t rv = ctf_type_lname(fp, type, buf, len);
|
||||
ssize_t rv = ctf_type_qlname(fp, type, buf, len, NULL);
|
||||
return (rv >= 0 && rv < len ? buf : NULL);
|
||||
}
|
||||
|
||||
char *
|
||||
ctf_type_qname(ctf_file_t *fp, ctf_id_t type, char *buf, size_t len,
|
||||
const char *qname)
|
||||
{
|
||||
ssize_t rv = ctf_type_qlname(fp, type, buf, len, qname);
|
||||
return (rv >= 0 && rv < len ? buf : NULL);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Resolve the type down to a base type node, and then return the size
|
||||
* of the type storage in bytes.
|
||||
|
@ -23,8 +23,10 @@
|
||||
* Copyright 2005 Sun Microsystems, Inc. All rights reserved.
|
||||
* Use is subject to license terms.
|
||||
*/
|
||||
|
||||
#pragma ident "%Z%%M% %I% %E% SMI"
|
||||
/*
|
||||
* Copyright (c) 2013 by Delphix. All rights reserved.
|
||||
* Copyright (c) 2013 Joyent, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <strings.h>
|
||||
@ -125,7 +127,7 @@ dt_copyvar(dt_idhash_t *dhp, dt_ident_t *idp, void *data)
|
||||
dvp->dtdv_flags |= DIFV_F_MOD;
|
||||
|
||||
bzero(&dn, sizeof (dn));
|
||||
dt_node_type_assign(&dn, idp->di_ctfp, idp->di_type);
|
||||
dt_node_type_assign(&dn, idp->di_ctfp, idp->di_type, B_FALSE);
|
||||
dt_node_diftype(pcb->pcb_hdl, &dn, &dvp->dtdv_type);
|
||||
|
||||
idp->di_flags &= ~(DT_IDFLG_DIFR | DT_IDFLG_DIFW);
|
||||
|
@ -21,7 +21,7 @@
|
||||
|
||||
/*
|
||||
* Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2011, Joyent Inc. All rights reserved.
|
||||
* Copyright (c) 2013, Joyent Inc. All rights reserved.
|
||||
* Copyright (c) 2012 by Delphix. All rights reserved.
|
||||
*/
|
||||
|
||||
@ -663,6 +663,8 @@ dt_action_printflike(dtrace_hdl_t *dtp, dt_node_t *dnp, dtrace_stmtdesc_t *sdp,
|
||||
static void
|
||||
dt_action_trace(dtrace_hdl_t *dtp, dt_node_t *dnp, dtrace_stmtdesc_t *sdp)
|
||||
{
|
||||
int ctflib;
|
||||
|
||||
dtrace_actdesc_t *ap = dt_stmt_action(dtp, sdp);
|
||||
boolean_t istrace = (dnp->dn_ident->di_id == DT_ACT_TRACE);
|
||||
const char *act = istrace ? "trace" : "print";
|
||||
@ -694,7 +696,10 @@ dt_action_trace(dtrace_hdl_t *dtp, dt_node_t *dnp, dtrace_stmtdesc_t *sdp)
|
||||
* like arrays and function pointers that can't be resolved by
|
||||
* ctf_type_lookup(). This is later processed by dtrace_dof_create()
|
||||
* and turned into a reference into the string table so that we can
|
||||
* get the type information when we process the data after the fact.
|
||||
* get the type information when we process the data after the fact. In
|
||||
* the case where we are referring to userland CTF data, we also need to
|
||||
* to identify which ctf container in question we care about and encode
|
||||
* that within the name.
|
||||
*/
|
||||
if (dnp->dn_ident->di_id == DT_ACT_PRINT) {
|
||||
dt_node_t *dret;
|
||||
@ -705,11 +710,27 @@ dt_action_trace(dtrace_hdl_t *dtp, dt_node_t *dnp, dtrace_stmtdesc_t *sdp)
|
||||
dmp = dt_module_lookup_by_ctf(dtp, dret->dn_ctfp);
|
||||
|
||||
n = snprintf(NULL, 0, "%s`%ld", dmp->dm_name, dret->dn_type) + 1;
|
||||
if (dmp->dm_pid != 0) {
|
||||
ctflib = dt_module_getlibid(dtp, dmp, dret->dn_ctfp);
|
||||
assert(ctflib >= 0);
|
||||
n = snprintf(NULL, 0, "%s`%d`%ld", dmp->dm_name,
|
||||
ctflib, dret->dn_type) + 1;
|
||||
} else {
|
||||
n = snprintf(NULL, 0, "%s`%ld", dmp->dm_name,
|
||||
dret->dn_type) + 1;
|
||||
}
|
||||
sdp->dtsd_strdata = dt_alloc(dtp, n);
|
||||
if (sdp->dtsd_strdata == NULL)
|
||||
longjmp(yypcb->pcb_jmpbuf, EDT_NOMEM);
|
||||
(void) snprintf(sdp->dtsd_strdata, n, "%s`%ld", dmp->dm_name,
|
||||
dret->dn_type);
|
||||
if (dmp->dm_pid != 0) {
|
||||
(void) snprintf(sdp->dtsd_strdata, n, "%s`%d`%ld",
|
||||
dmp->dm_name, ctflib, dret->dn_type);
|
||||
} else {
|
||||
(void) snprintf(sdp->dtsd_strdata, n, "%s`%ld",
|
||||
dmp->dm_name, dret->dn_type);
|
||||
}
|
||||
}
|
||||
|
||||
ap->dtad_difo = dt_as(yypcb);
|
||||
|
@ -21,7 +21,8 @@
|
||||
*/
|
||||
/*
|
||||
* Copyright 2005 Sun Microsystems, Inc. All rights reserved.
|
||||
* Copyright (c) 2012 by Delphix. All rights reserved.
|
||||
* Copyright (c) 2013 by Delphix. All rights reserved.
|
||||
* Copyright (c) 2013 Joyent, Inc. All rights reserved.
|
||||
* Use is subject to license terms.
|
||||
*/
|
||||
|
||||
@ -779,7 +780,7 @@ dt_decl_enumerator(char *s, dt_node_t *dnp)
|
||||
yyintdecimal = 0;
|
||||
|
||||
dnp = dt_node_int(value);
|
||||
dt_node_type_assign(dnp, dsp->ds_ctfp, dsp->ds_type);
|
||||
dt_node_type_assign(dnp, dsp->ds_ctfp, dsp->ds_type, B_FALSE);
|
||||
|
||||
if ((inp = malloc(sizeof (dt_idnode_t))) == NULL)
|
||||
longjmp(yypcb->pcb_jmpbuf, EDT_NOMEM);
|
||||
@ -821,6 +822,8 @@ dt_decl_type(dt_decl_t *ddp, dtrace_typeinfo_t *tip)
|
||||
char *name;
|
||||
int rv;
|
||||
|
||||
tip->dtt_flags = 0;
|
||||
|
||||
/*
|
||||
* Based on our current #include depth and decl stack depth, determine
|
||||
* which dynamic CTF module and scope to use when adding any new types.
|
||||
@ -828,6 +831,9 @@ dt_decl_type(dt_decl_t *ddp, dtrace_typeinfo_t *tip)
|
||||
dmp = yypcb->pcb_idepth ? dtp->dt_cdefs : dtp->dt_ddefs;
|
||||
flag = yypcb->pcb_dstack.ds_next ? CTF_ADD_NONROOT : CTF_ADD_ROOT;
|
||||
|
||||
if (ddp->dd_attr & DT_DA_USER)
|
||||
tip->dtt_flags = DTT_FL_USER;
|
||||
|
||||
/*
|
||||
* If we have already cached a CTF type for this decl, then we just
|
||||
* return the type information for the cached type.
|
||||
|
@ -23,12 +23,14 @@
|
||||
* Copyright 2005 Sun Microsystems, Inc. All rights reserved.
|
||||
* Use is subject to license terms.
|
||||
*/
|
||||
/*
|
||||
* Copyright (c) 2013 by Delphix. All rights reserved.
|
||||
* Copyright (c) 2013 Joyent, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef _DT_DECL_H
|
||||
#define _DT_DECL_H
|
||||
|
||||
#pragma ident "%Z%%M% %I% %E% SMI"
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <libctf.h>
|
||||
#include <dtrace.h>
|
||||
@ -59,6 +61,7 @@ typedef struct dt_decl {
|
||||
#define DT_DA_RESTRICT 0x0040 /* qualify type as restrict */
|
||||
#define DT_DA_VOLATILE 0x0080 /* qualify type as volatile */
|
||||
#define DT_DA_PAREN 0x0100 /* parenthesis tag */
|
||||
#define DT_DA_USER 0x0200 /* user-land type specifier */
|
||||
|
||||
typedef enum dt_dclass {
|
||||
DT_DC_DEFAULT, /* no storage class specified */
|
||||
|
@ -26,7 +26,8 @@
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 2012 by Delphix. All rights reserved.
|
||||
* Copyright (c) 2013 by Delphix. All rights reserved.
|
||||
* Copyright (c) 2013 Joyent, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <strings.h>
|
||||
@ -312,9 +313,10 @@ dt_dis_typestr(const dtrace_diftype_t *t, char *buf, size_t len)
|
||||
(void) snprintf(ckind, sizeof (ckind), "0x%x", t->dtdt_ckind);
|
||||
}
|
||||
|
||||
if (t->dtdt_flags & DIF_TF_BYREF) {
|
||||
(void) snprintf(buf, len, "%s (%s) by ref (size %lu)",
|
||||
kind, ckind, (ulong_t)t->dtdt_size);
|
||||
if (t->dtdt_flags & (DIF_TF_BYREF | DIF_TF_BYUREF)) {
|
||||
(void) snprintf(buf, len, "%s (%s) by %sref (size %lu)",
|
||||
kind, ckind, (t->dtdt_flags & DIF_TF_BYUREF) ? "user " : "",
|
||||
(ulong_t)t->dtdt_size);
|
||||
} else {
|
||||
(void) snprintf(buf, len, "%s (%s) (size %lu)",
|
||||
kind, ckind, (ulong_t)t->dtdt_size);
|
||||
|
@ -111,7 +111,8 @@ static const struct {
|
||||
{ EDT_BADAGGVAR, "Invalid aggregation variable identifier" },
|
||||
{ EDT_OVERSION, "Client requested deprecated version of library" },
|
||||
{ EDT_ENABLING_ERR, "Failed to enable probe" },
|
||||
{ EDT_NOPROBES, "No probe sites found for declared provider" }
|
||||
{ EDT_NOPROBES, "No probe sites found for declared provider" },
|
||||
{ EDT_CANTLOAD, "Failed to load module" },
|
||||
};
|
||||
|
||||
static const int _dt_nerr = sizeof (_dt_errlist) / sizeof (_dt_errlist[0]);
|
||||
|
@ -23,8 +23,10 @@
|
||||
* Copyright 2006 Sun Microsystems, Inc. All rights reserved.
|
||||
* Use is subject to license terms.
|
||||
*/
|
||||
|
||||
#pragma ident "%Z%%M% %I% %E% SMI"
|
||||
/*
|
||||
* Copyright (c) 2013 by Delphix. All rights reserved.
|
||||
* Copyright (c) 2013, Joyent, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <dt_impl.h>
|
||||
|
||||
@ -102,6 +104,7 @@
|
||||
%token DT_KEY_TYPEDEF
|
||||
%token DT_KEY_UNION
|
||||
%token DT_KEY_UNSIGNED
|
||||
%token DT_KEY_USERLAND
|
||||
%token DT_KEY_VOID
|
||||
%token DT_KEY_VOLATILE
|
||||
%token DT_KEY_WHILE
|
||||
@ -633,6 +636,7 @@ type_specifier: DT_KEY_VOID { $$ = dt_decl_spec(CTF_K_INTEGER, DUP("void")); }
|
||||
| DT_KEY_DOUBLE { $$ = dt_decl_spec(CTF_K_FLOAT, DUP("double")); }
|
||||
| DT_KEY_SIGNED { $$ = dt_decl_attr(DT_DA_SIGNED); }
|
||||
| DT_KEY_UNSIGNED { $$ = dt_decl_attr(DT_DA_UNSIGNED); }
|
||||
| DT_KEY_USERLAND { $$ = dt_decl_attr(DT_DA_USER); }
|
||||
| DT_KEY_STRING {
|
||||
$$ = dt_decl_spec(CTF_K_TYPEDEF, DUP("string"));
|
||||
}
|
||||
|
@ -22,6 +22,8 @@
|
||||
/*
|
||||
* Copyright 2007 Sun Microsystems, Inc. All rights reserved.
|
||||
* Use is subject to license terms.
|
||||
* Copyright (c) 2013 by Delphix. All rights reserved.
|
||||
* Copyright (c) 2013 Joyent, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#pragma ident "%Z%%M% %I% %E% SMI"
|
||||
@ -104,7 +106,7 @@ dt_idcook_sign(dt_node_t *dnp, dt_ident_t *idp,
|
||||
}
|
||||
}
|
||||
|
||||
dt_node_type_assign(dnp, idp->di_ctfp, idp->di_type);
|
||||
dt_node_type_assign(dnp, idp->di_ctfp, idp->di_type, B_FALSE);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -163,7 +165,7 @@ dt_idcook_assc(dt_node_t *dnp, dt_ident_t *idp, int argc, dt_node_t *args)
|
||||
if (argc != 0)
|
||||
isp->dis_args[argc - 1].dn_list = NULL;
|
||||
|
||||
dt_node_type_assign(dnp, idp->di_ctfp, idp->di_type);
|
||||
dt_node_type_assign(dnp, idp->di_ctfp, idp->di_type, B_FALSE);
|
||||
|
||||
} else {
|
||||
dt_idcook_sign(dnp, idp, argc, args,
|
||||
@ -304,7 +306,7 @@ dt_idcook_func(dt_node_t *dnp, dt_ident_t *idp, int argc, dt_node_t *args)
|
||||
}
|
||||
|
||||
dt_node_type_assign(&isp->dis_args[i],
|
||||
dtt.dtt_ctfp, dtt.dtt_type);
|
||||
dtt.dtt_ctfp, dtt.dtt_type, B_FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
@ -391,7 +393,9 @@ dt_idcook_args(dt_node_t *dnp, dt_ident_t *idp, int argc, dt_node_t *ap)
|
||||
|
||||
dt_node_type_assign(dnp,
|
||||
prp->pr_argv[ap->dn_value].dtt_ctfp,
|
||||
prp->pr_argv[ap->dn_value].dtt_type);
|
||||
prp->pr_argv[ap->dn_value].dtt_type,
|
||||
prp->pr_argv[ap->dn_value].dtt_flags & DTT_FL_USER ?
|
||||
B_TRUE : B_FALSE);
|
||||
|
||||
} else if ((dxp = dt_xlator_lookup(dtp,
|
||||
nnp, xnp, DT_XLATE_FUZZY)) != NULL || (
|
||||
@ -419,7 +423,8 @@ dt_idcook_args(dt_node_t *dnp, dt_ident_t *idp, int argc, dt_node_t *ap)
|
||||
dnp->dn_ident->di_ctfp = xidp->di_ctfp;
|
||||
dnp->dn_ident->di_type = xidp->di_type;
|
||||
|
||||
dt_node_type_assign(dnp, DT_DYN_CTFP(dtp), DT_DYN_TYPE(dtp));
|
||||
dt_node_type_assign(dnp, DT_DYN_CTFP(dtp), DT_DYN_TYPE(dtp),
|
||||
B_FALSE);
|
||||
|
||||
} else {
|
||||
xyerror(D_ARGS_XLATOR, "translator for %s[%lld] from %s to %s "
|
||||
@ -465,7 +470,7 @@ dt_idcook_regs(dt_node_t *dnp, dt_ident_t *idp, int argc, dt_node_t *ap)
|
||||
idp->di_ctfp = dtt.dtt_ctfp;
|
||||
idp->di_type = dtt.dtt_type;
|
||||
|
||||
dt_node_type_assign(dnp, idp->di_ctfp, idp->di_type);
|
||||
dt_node_type_assign(dnp, idp->di_ctfp, idp->di_type, B_FALSE);
|
||||
}
|
||||
|
||||
/*ARGSUSED*/
|
||||
@ -487,7 +492,7 @@ dt_idcook_type(dt_node_t *dnp, dt_ident_t *idp, int argc, dt_node_t *args)
|
||||
idp->di_type = dtt.dtt_type;
|
||||
}
|
||||
|
||||
dt_node_type_assign(dnp, idp->di_ctfp, idp->di_type);
|
||||
dt_node_type_assign(dnp, idp->di_ctfp, idp->di_type, B_FALSE);
|
||||
}
|
||||
|
||||
/*ARGSUSED*/
|
||||
@ -495,7 +500,7 @@ static void
|
||||
dt_idcook_thaw(dt_node_t *dnp, dt_ident_t *idp, int argc, dt_node_t *args)
|
||||
{
|
||||
if (idp->di_ctfp != NULL && idp->di_type != CTF_ERR)
|
||||
dt_node_type_assign(dnp, idp->di_ctfp, idp->di_type);
|
||||
dt_node_type_assign(dnp, idp->di_ctfp, idp->di_type, B_FALSE);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -146,6 +146,10 @@ typedef struct dt_module {
|
||||
caddr_t dm_reloc_offset; /* Symbol relocation offset. */
|
||||
uintptr_t *dm_sec_offsets;
|
||||
#endif
|
||||
pid_t dm_pid; /* pid for this module */
|
||||
uint_t dm_nctflibs; /* number of ctf children libraries */
|
||||
ctf_file_t **dm_libctfp; /* process library ctf pointers */
|
||||
char **dm_libctfn; /* names of process ctf containers */
|
||||
} dt_module_t;
|
||||
|
||||
#define DT_DM_LOADED 0x1 /* module symbol and type data is loaded */
|
||||
@ -536,7 +540,8 @@ enum {
|
||||
EDT_BADAGGVAR, /* invalid aggregation variable identifier */
|
||||
EDT_OVERSION, /* client is requesting deprecated version */
|
||||
EDT_ENABLING_ERR, /* failed to enable probe */
|
||||
EDT_NOPROBES /* no probes sites for declared provider */
|
||||
EDT_NOPROBES, /* no probes sites for declared provider */
|
||||
EDT_CANTLOAD /* failed to load a module */
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -23,6 +23,10 @@
|
||||
/*
|
||||
* Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||
*/
|
||||
/*
|
||||
* Copyright (c) 2013 by Delphix. All rights reserved.
|
||||
* Copyright (c) 2013, Joyent, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
@ -93,13 +97,17 @@ static void unput(int);
|
||||
%}
|
||||
|
||||
%e 1500 /* maximum nodes */
|
||||
%p 3700 /* maximum positions */
|
||||
%p 4900 /* maximum positions */
|
||||
%n 600 /* maximum states */
|
||||
%a 3000 /* maximum transitions */
|
||||
|
||||
%s S0 S1 S2 S3 S4
|
||||
|
||||
RGX_AGG "@"[a-zA-Z_][0-9a-zA-Z_]*
|
||||
RGX_PSPEC [-$:a-zA-Z_.?*\\\[\]!][-$:0-9a-zA-Z_.`?*\\\[\]!]*
|
||||
RGX_ALTIDENT [a-zA-Z_][0-9a-zA-Z_]*
|
||||
RGX_LMID LM[0-9a-fA-F]+`
|
||||
RGX_MOD_IDENT [a-zA-Z_`][0-9a-z.A-Z_`]*`
|
||||
RGX_IDENT [a-zA-Z_`][0-9a-zA-Z_`]*
|
||||
RGX_INT ([0-9]+|0[xX][0-9A-Fa-f]+)[uU]?[lL]?[lL]?
|
||||
RGX_FP ([0-9]+("."?)[0-9]*|"."[0-9]+)((e|E)("+"|-)?[0-9]+)?[fFlL]?
|
||||
@ -169,6 +177,7 @@ if (yypcb->pcb_token != 0) {
|
||||
<S0>typedef return (DT_KEY_TYPEDEF);
|
||||
<S0>union return (DT_KEY_UNION);
|
||||
<S0>unsigned return (DT_KEY_UNSIGNED);
|
||||
<S0>userland return (DT_KEY_USERLAND);
|
||||
<S0>void return (DT_KEY_VOID);
|
||||
<S0>volatile return (DT_KEY_VOLATILE);
|
||||
<S0>while return (DT_KEY_WHILE);
|
||||
@ -347,7 +356,9 @@ if (yypcb->pcb_token != 0) {
|
||||
return (DT_TOK_INT);
|
||||
}
|
||||
|
||||
<S0>{RGX_IDENT} {
|
||||
<S0>{RGX_IDENT} |
|
||||
<S0>{RGX_MOD_IDENT}{RGX_IDENT} |
|
||||
<S0>{RGX_MOD_IDENT} {
|
||||
return (id_or_type(yytext));
|
||||
}
|
||||
|
||||
|
@ -22,6 +22,9 @@
|
||||
/*
|
||||
* Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||
*/
|
||||
/*
|
||||
* Copyright (c) 2013, Joyent, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#if defined(sun)
|
||||
@ -50,6 +53,7 @@
|
||||
#include <dirent.h>
|
||||
#if !defined(sun)
|
||||
#include <fcntl.h>
|
||||
#include <libproc_compat.h>
|
||||
#endif
|
||||
|
||||
#include <dt_strtab.h>
|
||||
@ -462,6 +466,9 @@ static const dt_modops_t dt_modops_64 = {
|
||||
dt_module_t *
|
||||
dt_module_create(dtrace_hdl_t *dtp, const char *name)
|
||||
{
|
||||
long pid;
|
||||
char *eptr;
|
||||
dt_ident_t *idp;
|
||||
uint_t h = dt_strtab_hash(name, NULL) % dtp->dt_modbuckets;
|
||||
dt_module_t *dmp;
|
||||
|
||||
@ -485,6 +492,32 @@ dt_module_create(dtrace_hdl_t *dtp, const char *name)
|
||||
else
|
||||
dmp->dm_ops = &dt_modops_32;
|
||||
|
||||
/*
|
||||
* Modules for userland processes are special. They always refer to a
|
||||
* specific process and have a copy of their CTF data from a specific
|
||||
* instant in time. Any dt_module_t that begins with 'pid' is a module
|
||||
* for a specific process, much like how any probe description that
|
||||
* begins with 'pid' is special. pid123 refers to process 123. A module
|
||||
* that is just 'pid' refers specifically to pid$target. This is
|
||||
* generally done as D does not currently allow for macros to be
|
||||
* evaluated when working with types.
|
||||
*/
|
||||
if (strncmp(dmp->dm_name, "pid", 3) == 0) {
|
||||
errno = 0;
|
||||
if (dmp->dm_name[3] == '\0') {
|
||||
idp = dt_idhash_lookup(dtp->dt_macros, "target");
|
||||
if (idp != NULL && idp->di_id != 0)
|
||||
dmp->dm_pid = idp->di_id;
|
||||
} else {
|
||||
pid = strtol(dmp->dm_name + 3, &eptr, 10);
|
||||
if (errno == 0 && *eptr == '\0')
|
||||
dmp->dm_pid = (pid_t)pid;
|
||||
else
|
||||
dt_dprintf("encountered malformed pid "
|
||||
"module: %s\n", dmp->dm_name);
|
||||
}
|
||||
}
|
||||
|
||||
return (dmp);
|
||||
}
|
||||
|
||||
@ -554,12 +587,169 @@ dt_module_load_sect(dtrace_hdl_t *dtp, dt_module_t *dmp, ctf_sect_t *ctsp)
|
||||
return (0);
|
||||
}
|
||||
|
||||
typedef struct dt_module_cb_arg {
|
||||
struct ps_prochandle *dpa_proc;
|
||||
dtrace_hdl_t *dpa_dtp;
|
||||
dt_module_t *dpa_dmp;
|
||||
uint_t dpa_count;
|
||||
} dt_module_cb_arg_t;
|
||||
|
||||
/* ARGSUSED */
|
||||
static int
|
||||
dt_module_load_proc_count(void *arg, const prmap_t *prmap, const char *obj)
|
||||
{
|
||||
ctf_file_t *fp;
|
||||
dt_module_cb_arg_t *dcp = arg;
|
||||
|
||||
/* Try to grab a ctf container if it exists */
|
||||
fp = Pname_to_ctf(dcp->dpa_proc, obj);
|
||||
if (fp != NULL)
|
||||
dcp->dpa_count++;
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* ARGSUSED */
|
||||
static int
|
||||
dt_module_load_proc_build(void *arg, const prmap_t *prmap, const char *obj)
|
||||
{
|
||||
ctf_file_t *fp;
|
||||
char buf[MAXPATHLEN], *p;
|
||||
dt_module_cb_arg_t *dcp = arg;
|
||||
int count = dcp->dpa_count;
|
||||
Lmid_t lmid;
|
||||
|
||||
fp = Pname_to_ctf(dcp->dpa_proc, obj);
|
||||
if (fp == NULL)
|
||||
return (0);
|
||||
fp = ctf_dup(fp);
|
||||
if (fp == NULL)
|
||||
return (0);
|
||||
dcp->dpa_dmp->dm_libctfp[count] = fp;
|
||||
/*
|
||||
* While it'd be nice to simply use objname here, because of our prior
|
||||
* actions we'll always get a resolved object name to its on disk file.
|
||||
* Like the pid provider, we need to tell a bit of a lie here. The type
|
||||
* that the user thinks of is in terms of the libraries they requested,
|
||||
* eg. libc.so.1, they don't care about the fact that it's
|
||||
* libc_hwcap.so.1.
|
||||
*/
|
||||
(void) Pobjname(dcp->dpa_proc, prmap->pr_vaddr, buf, sizeof (buf));
|
||||
if ((p = strrchr(buf, '/')) == NULL)
|
||||
p = buf;
|
||||
else
|
||||
p++;
|
||||
|
||||
/*
|
||||
* If for some reason we can't find a link map id for this module, which
|
||||
* would be really quite weird. We instead just say the link map id is
|
||||
* zero.
|
||||
*/
|
||||
if (Plmid(dcp->dpa_proc, prmap->pr_vaddr, &lmid) != 0)
|
||||
lmid = 0;
|
||||
|
||||
if (lmid == 0)
|
||||
dcp->dpa_dmp->dm_libctfn[count] = strdup(p);
|
||||
else
|
||||
(void) asprintf(&dcp->dpa_dmp->dm_libctfn[count],
|
||||
"LM%x`%s", lmid, p);
|
||||
if (dcp->dpa_dmp->dm_libctfn[count] == NULL)
|
||||
return (1);
|
||||
ctf_setspecific(fp, dcp->dpa_dmp);
|
||||
dcp->dpa_count++;
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* We've been asked to load data that belongs to another process. As such we're
|
||||
* going to pgrab it at this instant, load everything that we might ever care
|
||||
* about, and then drive on. The reason for this is that the process that we're
|
||||
* interested in might be changing. As long as we have grabbed it, then this
|
||||
* can't be a problem for us.
|
||||
*
|
||||
* For now, we're actually going to punt on most things and just try to get CTF
|
||||
* data, nothing else. Basically this is only useful as a source of type
|
||||
* information, we can't go and do the stacktrace lookups, etc.
|
||||
*/
|
||||
static int
|
||||
dt_module_load_proc(dtrace_hdl_t *dtp, dt_module_t *dmp)
|
||||
{
|
||||
struct ps_prochandle *p;
|
||||
dt_module_cb_arg_t arg;
|
||||
|
||||
/*
|
||||
* Note that on success we do not release this hold. We must hold this
|
||||
* for our life time.
|
||||
*/
|
||||
p = dt_proc_grab(dtp, dmp->dm_pid, 0, PGRAB_RDONLY | PGRAB_FORCE);
|
||||
if (p == NULL) {
|
||||
dt_dprintf("failed to grab pid: %d\n", (int)dmp->dm_pid);
|
||||
return (dt_set_errno(dtp, EDT_CANTLOAD));
|
||||
}
|
||||
dt_proc_lock(dtp, p);
|
||||
|
||||
arg.dpa_proc = p;
|
||||
arg.dpa_dtp = dtp;
|
||||
arg.dpa_dmp = dmp;
|
||||
arg.dpa_count = 0;
|
||||
if (Pobject_iter_resolved(p, dt_module_load_proc_count, &arg) != 0) {
|
||||
dt_dprintf("failed to iterate objects\n");
|
||||
dt_proc_release(dtp, p);
|
||||
return (dt_set_errno(dtp, EDT_CANTLOAD));
|
||||
}
|
||||
|
||||
if (arg.dpa_count == 0) {
|
||||
dt_dprintf("no ctf data present\n");
|
||||
dt_proc_unlock(dtp, p);
|
||||
dt_proc_release(dtp, p);
|
||||
return (dt_set_errno(dtp, EDT_CANTLOAD));
|
||||
}
|
||||
|
||||
dmp->dm_libctfp = malloc(sizeof (ctf_file_t *) * arg.dpa_count);
|
||||
if (dmp->dm_libctfp == NULL) {
|
||||
dt_proc_unlock(dtp, p);
|
||||
dt_proc_release(dtp, p);
|
||||
return (dt_set_errno(dtp, EDT_NOMEM));
|
||||
}
|
||||
bzero(dmp->dm_libctfp, sizeof (ctf_file_t *) * arg.dpa_count);
|
||||
|
||||
dmp->dm_libctfn = malloc(sizeof (char *) * arg.dpa_count);
|
||||
if (dmp->dm_libctfn == NULL) {
|
||||
free(dmp->dm_libctfp);
|
||||
dt_proc_unlock(dtp, p);
|
||||
dt_proc_release(dtp, p);
|
||||
return (dt_set_errno(dtp, EDT_NOMEM));
|
||||
}
|
||||
bzero(dmp->dm_libctfn, sizeof (char *) * arg.dpa_count);
|
||||
|
||||
dmp->dm_nctflibs = arg.dpa_count;
|
||||
|
||||
arg.dpa_count = 0;
|
||||
if (Pobject_iter_resolved(p, dt_module_load_proc_build, &arg) != 0) {
|
||||
dt_proc_unlock(dtp, p);
|
||||
dt_module_unload(dtp, dmp);
|
||||
dt_proc_release(dtp, p);
|
||||
return (dt_set_errno(dtp, EDT_CANTLOAD));
|
||||
}
|
||||
assert(arg.dpa_count == dmp->dm_nctflibs);
|
||||
dt_dprintf("loaded %d ctf modules for pid %d\n", arg.dpa_count,
|
||||
(int)dmp->dm_pid);
|
||||
|
||||
dt_proc_unlock(dtp, p);
|
||||
dt_proc_release(dtp, p);
|
||||
dmp->dm_flags |= DT_DM_LOADED;
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
dt_module_load(dtrace_hdl_t *dtp, dt_module_t *dmp)
|
||||
{
|
||||
if (dmp->dm_flags & DT_DM_LOADED)
|
||||
return (0); /* module is already loaded */
|
||||
|
||||
if (dmp->dm_pid != 0)
|
||||
return (dt_module_load_proc(dtp, dmp));
|
||||
|
||||
dmp->dm_ctdata.cts_name = ".SUNW_ctf";
|
||||
dmp->dm_ctdata.cts_type = SHT_PROGBITS;
|
||||
dmp->dm_ctdata.cts_flags = 0;
|
||||
@ -645,6 +835,14 @@ dt_module_load(dtrace_hdl_t *dtp, dt_module_t *dmp)
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
dt_module_hasctf(dtrace_hdl_t *dtp, dt_module_t *dmp)
|
||||
{
|
||||
if (dmp->dm_pid != 0 && dmp->dm_nctflibs > 0)
|
||||
return (1);
|
||||
return (dt_module_getctf(dtp, dmp) != NULL);
|
||||
}
|
||||
|
||||
ctf_file_t *
|
||||
dt_module_getctf(dtrace_hdl_t *dtp, dt_module_t *dmp)
|
||||
{
|
||||
@ -718,6 +916,8 @@ dt_module_getctf(dtrace_hdl_t *dtp, dt_module_t *dmp)
|
||||
void
|
||||
dt_module_unload(dtrace_hdl_t *dtp, dt_module_t *dmp)
|
||||
{
|
||||
int i;
|
||||
|
||||
ctf_close(dmp->dm_ctfp);
|
||||
dmp->dm_ctfp = NULL;
|
||||
|
||||
@ -733,6 +933,17 @@ dt_module_unload(dtrace_hdl_t *dtp, dt_module_t *dmp)
|
||||
}
|
||||
#endif
|
||||
|
||||
if (dmp->dm_libctfp != NULL) {
|
||||
for (i = 0; i < dmp->dm_nctflibs; i++) {
|
||||
ctf_close(dmp->dm_libctfp[i]);
|
||||
free(dmp->dm_libctfn[i]);
|
||||
}
|
||||
free(dmp->dm_libctfp);
|
||||
free(dmp->dm_libctfn);
|
||||
dmp->dm_libctfp = NULL;
|
||||
dmp->dm_nctflibs = 0;
|
||||
}
|
||||
|
||||
bzero(&dmp->dm_ctdata, sizeof (ctf_sect_t));
|
||||
bzero(&dmp->dm_symtab, sizeof (ctf_sect_t));
|
||||
bzero(&dmp->dm_strtab, sizeof (ctf_sect_t));
|
||||
@ -778,6 +989,8 @@ dt_module_unload(dtrace_hdl_t *dtp, dt_module_t *dmp)
|
||||
(void) elf_end(dmp->dm_elf);
|
||||
dmp->dm_elf = NULL;
|
||||
|
||||
dmp->dm_pid = 0;
|
||||
|
||||
dmp->dm_flags &= ~DT_DM_LOADED;
|
||||
}
|
||||
|
||||
@ -866,6 +1079,34 @@ dt_module_modelname(dt_module_t *dmp)
|
||||
return ("32-bit");
|
||||
}
|
||||
|
||||
/* ARGSUSED */
|
||||
int
|
||||
dt_module_getlibid(dtrace_hdl_t *dtp, dt_module_t *dmp, const ctf_file_t *fp)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < dmp->dm_nctflibs; i++) {
|
||||
if (dmp->dm_libctfp[i] == fp)
|
||||
return (i);
|
||||
}
|
||||
|
||||
return (-1);
|
||||
}
|
||||
|
||||
/* ARGSUSED */
|
||||
ctf_file_t *
|
||||
dt_module_getctflib(dtrace_hdl_t *dtp, dt_module_t *dmp, const char *name)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < dmp->dm_nctflibs; i++) {
|
||||
if (strcmp(dmp->dm_libctfn[i], name) == 0)
|
||||
return (dmp->dm_libctfp[i]);
|
||||
}
|
||||
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Update our module cache by adding an entry for the specified module 'name'.
|
||||
* We create the dt_module_t and populate it using /system/object/<name>/.
|
||||
@ -1294,8 +1535,10 @@ dtrace_lookup_by_type(dtrace_hdl_t *dtp, const char *object, const char *name,
|
||||
dt_module_t *dmp;
|
||||
int found = 0;
|
||||
ctf_id_t id;
|
||||
uint_t n;
|
||||
uint_t n, i;
|
||||
int justone;
|
||||
ctf_file_t *fp;
|
||||
char *buf, *p, *q;
|
||||
|
||||
uint_t mask = 0; /* mask of dt_module flags to match */
|
||||
uint_t bits = 0; /* flag bits that must be present */
|
||||
@ -1310,7 +1553,6 @@ dtrace_lookup_by_type(dtrace_hdl_t *dtp, const char *object, const char *name,
|
||||
return (-1); /* dt_errno is set for us */
|
||||
n = 1;
|
||||
justone = 1;
|
||||
|
||||
} else {
|
||||
if (object == DTRACE_OBJ_KMODS)
|
||||
mask = bits = DT_DM_KERNEL;
|
||||
@ -1334,7 +1576,7 @@ dtrace_lookup_by_type(dtrace_hdl_t *dtp, const char *object, const char *name,
|
||||
* module. If our search was scoped to only one module then
|
||||
* return immediately leaving dt_errno unmodified.
|
||||
*/
|
||||
if (dt_module_getctf(dtp, dmp) == NULL) {
|
||||
if (dt_module_hasctf(dtp, dmp) == 0) {
|
||||
if (justone)
|
||||
return (-1);
|
||||
continue;
|
||||
@ -1346,13 +1588,38 @@ dtrace_lookup_by_type(dtrace_hdl_t *dtp, const char *object, const char *name,
|
||||
* 'tip' and keep going in the hope that we will locate the
|
||||
* underlying structure definition. Otherwise just return.
|
||||
*/
|
||||
if ((id = ctf_lookup_by_name(dmp->dm_ctfp, name)) != CTF_ERR) {
|
||||
if (dmp->dm_pid == 0) {
|
||||
id = ctf_lookup_by_name(dmp->dm_ctfp, name);
|
||||
fp = dmp->dm_ctfp;
|
||||
} else {
|
||||
if ((p = strchr(name, '`')) != NULL) {
|
||||
buf = strdup(name);
|
||||
if (buf == NULL)
|
||||
return (dt_set_errno(dtp, EDT_NOMEM));
|
||||
p = strchr(buf, '`');
|
||||
if ((q = strchr(p + 1, '`')) != NULL)
|
||||
p = q;
|
||||
*p = '\0';
|
||||
fp = dt_module_getctflib(dtp, dmp, buf);
|
||||
if (fp == NULL || (id = ctf_lookup_by_name(fp,
|
||||
p + 1)) == CTF_ERR)
|
||||
id = CTF_ERR;
|
||||
free(buf);
|
||||
} else {
|
||||
for (i = 0; i < dmp->dm_nctflibs; i++) {
|
||||
fp = dmp->dm_libctfp[i];
|
||||
id = ctf_lookup_by_name(fp, name);
|
||||
if (id != CTF_ERR)
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (id != CTF_ERR) {
|
||||
tip->dtt_object = dmp->dm_name;
|
||||
tip->dtt_ctfp = dmp->dm_ctfp;
|
||||
tip->dtt_ctfp = fp;
|
||||
tip->dtt_type = id;
|
||||
|
||||
if (ctf_type_kind(dmp->dm_ctfp, ctf_type_resolve(
|
||||
dmp->dm_ctfp, id)) != CTF_K_FORWARD)
|
||||
if (ctf_type_kind(fp, ctf_type_resolve(fp, id)) !=
|
||||
CTF_K_FORWARD)
|
||||
return (0);
|
||||
|
||||
found++;
|
||||
@ -1374,6 +1641,7 @@ dtrace_symbol_type(dtrace_hdl_t *dtp, const GElf_Sym *symp,
|
||||
tip->dtt_object = NULL;
|
||||
tip->dtt_ctfp = NULL;
|
||||
tip->dtt_type = CTF_ERR;
|
||||
tip->dtt_flags = 0;
|
||||
|
||||
if ((dmp = dt_module_lookup_by_name(dtp, sip->dts_object)) == NULL)
|
||||
return (dt_set_errno(dtp, EDT_NOMOD));
|
||||
|
@ -23,12 +23,13 @@
|
||||
* Copyright 2004 Sun Microsystems, Inc. All rights reserved.
|
||||
* Use is subject to license terms.
|
||||
*/
|
||||
/*
|
||||
* Copyright (c) 2013, Joyent, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef _DT_MODULE_H
|
||||
#define _DT_MODULE_H
|
||||
|
||||
#pragma ident "%Z%%M% %I% %E% SMI"
|
||||
|
||||
#include <dt_impl.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
@ -43,11 +44,16 @@ extern void dt_module_destroy(dtrace_hdl_t *, dt_module_t *);
|
||||
extern dt_module_t *dt_module_lookup_by_name(dtrace_hdl_t *, const char *);
|
||||
extern dt_module_t *dt_module_lookup_by_ctf(dtrace_hdl_t *, ctf_file_t *);
|
||||
|
||||
extern int dt_module_hasctf(dtrace_hdl_t *, dt_module_t *);
|
||||
extern ctf_file_t *dt_module_getctf(dtrace_hdl_t *, dt_module_t *);
|
||||
extern dt_ident_t *dt_module_extern(dtrace_hdl_t *, dt_module_t *,
|
||||
const char *, const dtrace_typeinfo_t *);
|
||||
|
||||
extern const char *dt_module_modelname(dt_module_t *);
|
||||
extern int dt_module_getlibid(dtrace_hdl_t *, dt_module_t *,
|
||||
const ctf_file_t *);
|
||||
extern ctf_file_t *dt_module_getctflib(dtrace_hdl_t *, dt_module_t *,
|
||||
const char *);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
@ -21,7 +21,7 @@
|
||||
|
||||
/*
|
||||
* Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2012, Joyent, Inc. All rights reserved.
|
||||
* Copyright (c) 2013, Joyent, Inc. All rights reserved.
|
||||
* Copyright (c) 2012 by Delphix. All rights reserved.
|
||||
*/
|
||||
|
||||
@ -124,8 +124,9 @@
|
||||
#define DT_VERS_1_9_1 DT_VERSION_NUMBER(1, 9, 1)
|
||||
#define DT_VERS_1_10 DT_VERSION_NUMBER(1, 10, 0)
|
||||
#define DT_VERS_1_11 DT_VERSION_NUMBER(1, 11, 0)
|
||||
#define DT_VERS_LATEST DT_VERS_1_11
|
||||
#define DT_VERS_STRING "Sun D 1.11"
|
||||
#define DT_VERS_1_12 DT_VERSION_NUMBER(1, 12, 0)
|
||||
#define DT_VERS_LATEST DT_VERS_1_12
|
||||
#define DT_VERS_STRING "Sun D 1.12"
|
||||
|
||||
const dt_version_t _dtrace_versions[] = {
|
||||
DT_VERS_1_0, /* D API 1.0.0 (PSARC 2001/466) Solaris 10 FCS */
|
||||
@ -149,6 +150,7 @@ const dt_version_t _dtrace_versions[] = {
|
||||
DT_VERS_1_9_1, /* D API 1.9.1 */
|
||||
DT_VERS_1_10, /* D API 1.10 */
|
||||
DT_VERS_1_11, /* D API 1.11 */
|
||||
DT_VERS_1_12, /* D API 1.12 */
|
||||
0
|
||||
};
|
||||
|
||||
|
@ -22,8 +22,8 @@
|
||||
|
||||
/*
|
||||
* Copyright 2006 Sun Microsystems, Inc. All rights reserved.
|
||||
* Copyright (c) 2011, Joyent Inc. All rights reserved.
|
||||
* Copyright (c) 2012 by Delphix. All rights reserved.
|
||||
* Copyright (c) 2013, Joyent Inc. All rights reserved.
|
||||
* Copyright (c) 2013 by Delphix. All rights reserved.
|
||||
*/
|
||||
|
||||
#pragma ident "%Z%%M% %I% %E% SMI"
|
||||
@ -197,7 +197,7 @@ dt_type_lookup(const char *s, dtrace_typeinfo_t *tip)
|
||||
{
|
||||
static const char delimiters[] = " \t\n\r\v\f*`";
|
||||
dtrace_hdl_t *dtp = yypcb->pcb_hdl;
|
||||
const char *p, *q, *end, *obj;
|
||||
const char *p, *q, *r, *end, *obj;
|
||||
|
||||
for (p = s, end = s + strlen(s); *p != '\0'; p = q) {
|
||||
while (isspace(*p))
|
||||
@ -225,8 +225,23 @@ dt_type_lookup(const char *s, dtrace_typeinfo_t *tip)
|
||||
bcopy(s, type, (size_t)(p - s));
|
||||
bcopy(q + 1, type + (size_t)(p - s), strlen(q + 1) + 1);
|
||||
|
||||
if (strchr(q + 1, '`') != NULL)
|
||||
return (dt_set_errno(dtp, EDT_BADSCOPE));
|
||||
/*
|
||||
* There may be at most three delimeters. The second
|
||||
* delimeter is usually used to distinguish the type
|
||||
* within a given module, however, there could be a link
|
||||
* map id on the scene in which case that delimeter
|
||||
* would be the third. We determine presence of the lmid
|
||||
* if it rouglhly meets the from LM[0-9]
|
||||
*/
|
||||
if ((r = strchr(q + 1, '`')) != NULL &&
|
||||
((r = strchr(r + 1, '`')) != NULL)) {
|
||||
if (strchr(r + 1, '`') != NULL)
|
||||
return (dt_set_errno(dtp,
|
||||
EDT_BADSCOPE));
|
||||
if (q[1] != 'L' || q[2] != 'M')
|
||||
return (dt_set_errno(dtp,
|
||||
EDT_BADSCOPE));
|
||||
}
|
||||
|
||||
return (dtrace_lookup_by_type(dtp, object, type, tip));
|
||||
}
|
||||
@ -256,6 +271,7 @@ dt_type_pointer(dtrace_typeinfo_t *tip)
|
||||
ctf_file_t *ctfp = tip->dtt_ctfp;
|
||||
ctf_id_t type = tip->dtt_type;
|
||||
ctf_id_t base = ctf_type_resolve(ctfp, type);
|
||||
uint_t bflags = tip->dtt_flags;
|
||||
|
||||
dt_module_t *dmp;
|
||||
ctf_id_t ptr;
|
||||
@ -287,6 +303,7 @@ dt_type_pointer(dtrace_typeinfo_t *tip)
|
||||
tip->dtt_object = dmp->dm_name;
|
||||
tip->dtt_ctfp = dmp->dm_ctfp;
|
||||
tip->dtt_type = ptr;
|
||||
tip->dtt_flags = bflags;
|
||||
|
||||
return (0);
|
||||
}
|
||||
@ -390,7 +407,7 @@ void
|
||||
dt_node_promote(dt_node_t *lp, dt_node_t *rp, dt_node_t *dnp)
|
||||
{
|
||||
dt_type_promote(lp, rp, &dnp->dn_ctfp, &dnp->dn_type);
|
||||
dt_node_type_assign(dnp, dnp->dn_ctfp, dnp->dn_type);
|
||||
dt_node_type_assign(dnp, dnp->dn_ctfp, dnp->dn_type, B_FALSE);
|
||||
dt_node_attr_assign(dnp, dt_attr_min(lp->dn_attr, rp->dn_attr));
|
||||
}
|
||||
|
||||
@ -659,7 +676,8 @@ dt_node_attr_assign(dt_node_t *dnp, dtrace_attribute_t attr)
|
||||
}
|
||||
|
||||
void
|
||||
dt_node_type_assign(dt_node_t *dnp, ctf_file_t *fp, ctf_id_t type)
|
||||
dt_node_type_assign(dt_node_t *dnp, ctf_file_t *fp, ctf_id_t type,
|
||||
boolean_t user)
|
||||
{
|
||||
ctf_id_t base = ctf_type_resolve(fp, type);
|
||||
uint_t kind = ctf_type_kind(fp, base);
|
||||
@ -691,6 +709,9 @@ dt_node_type_assign(dt_node_t *dnp, ctf_file_t *fp, ctf_id_t type)
|
||||
type == DT_DYN_TYPE(yypcb->pcb_hdl))
|
||||
dnp->dn_flags |= DT_NF_REF;
|
||||
|
||||
if (user)
|
||||
dnp->dn_flags |= DT_NF_USERLAND;
|
||||
|
||||
dnp->dn_flags |= DT_NF_COOKED;
|
||||
dnp->dn_ctfp = fp;
|
||||
dnp->dn_type = type;
|
||||
@ -728,6 +749,7 @@ size_t
|
||||
dt_node_type_size(const dt_node_t *dnp)
|
||||
{
|
||||
ctf_id_t base;
|
||||
dtrace_hdl_t *dtp = yypcb->pcb_hdl;
|
||||
|
||||
if (dnp->dn_kind == DT_NODE_STRING)
|
||||
return (strlen(dnp->dn_string) + 1);
|
||||
@ -740,6 +762,20 @@ dt_node_type_size(const dt_node_t *dnp)
|
||||
if (ctf_type_kind(dnp->dn_ctfp, base) == CTF_K_FORWARD)
|
||||
return (0);
|
||||
|
||||
/*
|
||||
* Here we have a 32-bit user pointer that is being used with a 64-bit
|
||||
* kernel. When we're using it and its tagged as a userland reference --
|
||||
* then we need to keep it as a 32-bit pointer. However, if we are
|
||||
* referring to it as a kernel address, eg. being used after a copyin()
|
||||
* then we need to make sure that we actually return the kernel's size
|
||||
* of a pointer, 8 bytes.
|
||||
*/
|
||||
if (ctf_type_kind(dnp->dn_ctfp, base) == CTF_K_POINTER &&
|
||||
ctf_getmodel(dnp->dn_ctfp) == CTF_MODEL_ILP32 &&
|
||||
!(dnp->dn_flags & DT_NF_USERLAND) &&
|
||||
dtp->dt_conf.dtc_ctfmodel == CTF_MODEL_LP64)
|
||||
return (8);
|
||||
|
||||
return (ctf_type_size(dnp->dn_ctfp, dnp->dn_type));
|
||||
}
|
||||
|
||||
@ -1226,7 +1262,7 @@ dt_node_int(uintmax_t value)
|
||||
if (value <= dtp->dt_ints[i].did_limit) {
|
||||
dt_node_type_assign(dnp,
|
||||
dtp->dt_ints[i].did_ctfp,
|
||||
dtp->dt_ints[i].did_type);
|
||||
dtp->dt_ints[i].did_type, B_FALSE);
|
||||
|
||||
/*
|
||||
* If a prefix character is present in macro text, add
|
||||
@ -1261,7 +1297,7 @@ dt_node_string(char *string)
|
||||
dnp = dt_node_alloc(DT_NODE_STRING);
|
||||
dnp->dn_op = DT_TOK_STRING;
|
||||
dnp->dn_string = string;
|
||||
dt_node_type_assign(dnp, DT_STR_CTFP(dtp), DT_STR_TYPE(dtp));
|
||||
dt_node_type_assign(dnp, DT_STR_CTFP(dtp), DT_STR_TYPE(dtp), B_FALSE);
|
||||
|
||||
return (dnp);
|
||||
}
|
||||
@ -1337,7 +1373,8 @@ dt_node_type(dt_decl_t *ddp)
|
||||
dnp = dt_node_alloc(DT_NODE_TYPE);
|
||||
dnp->dn_op = DT_TOK_IDENT;
|
||||
dnp->dn_string = name;
|
||||
dt_node_type_assign(dnp, dtt.dtt_ctfp, dtt.dtt_type);
|
||||
|
||||
dt_node_type_assign(dnp, dtt.dtt_ctfp, dtt.dtt_type, dtt.dtt_flags);
|
||||
|
||||
if (dtt.dtt_ctfp == dtp->dt_cdefs->dm_ctfp ||
|
||||
dtt.dtt_ctfp == dtp->dt_ddefs->dm_ctfp)
|
||||
@ -1581,7 +1618,8 @@ dt_node_decl(void)
|
||||
bzero(&idn, sizeof (dt_node_t));
|
||||
|
||||
if (idp != NULL && idp->di_type != CTF_ERR)
|
||||
dt_node_type_assign(&idn, idp->di_ctfp, idp->di_type);
|
||||
dt_node_type_assign(&idn, idp->di_ctfp, idp->di_type,
|
||||
B_FALSE);
|
||||
else if (idp != NULL)
|
||||
(void) dt_ident_cook(&idn, idp, NULL);
|
||||
|
||||
@ -1791,7 +1829,7 @@ dt_node_offsetof(dt_decl_t *ddp, char *s)
|
||||
}
|
||||
|
||||
bzero(&dn, sizeof (dn));
|
||||
dt_node_type_assign(&dn, dtt.dtt_ctfp, ctm.ctm_type);
|
||||
dt_node_type_assign(&dn, dtt.dtt_ctfp, ctm.ctm_type, B_FALSE);
|
||||
|
||||
if (dn.dn_flags & DT_NF_BITFIELD) {
|
||||
xyerror(D_OFFSETOF_BITFIELD,
|
||||
@ -1847,7 +1885,8 @@ dt_node_op1(int op, dt_node_t *cp)
|
||||
}
|
||||
|
||||
dt_node_type_assign(cp, dtp->dt_ddefs->dm_ctfp,
|
||||
ctf_lookup_by_name(dtp->dt_ddefs->dm_ctfp, "size_t"));
|
||||
ctf_lookup_by_name(dtp->dt_ddefs->dm_ctfp, "size_t"),
|
||||
B_FALSE);
|
||||
|
||||
cp->dn_kind = DT_NODE_INT;
|
||||
cp->dn_op = DT_TOK_INT;
|
||||
@ -1925,17 +1964,17 @@ dt_node_op2(int op, dt_node_t *lp, dt_node_t *rp)
|
||||
case DT_TOK_LOR:
|
||||
dnp->dn_value = l || r;
|
||||
dt_node_type_assign(dnp,
|
||||
DT_INT_CTFP(dtp), DT_INT_TYPE(dtp));
|
||||
DT_INT_CTFP(dtp), DT_INT_TYPE(dtp), B_FALSE);
|
||||
break;
|
||||
case DT_TOK_LXOR:
|
||||
dnp->dn_value = (l != 0) ^ (r != 0);
|
||||
dt_node_type_assign(dnp,
|
||||
DT_INT_CTFP(dtp), DT_INT_TYPE(dtp));
|
||||
DT_INT_CTFP(dtp), DT_INT_TYPE(dtp), B_FALSE);
|
||||
break;
|
||||
case DT_TOK_LAND:
|
||||
dnp->dn_value = l && r;
|
||||
dt_node_type_assign(dnp,
|
||||
DT_INT_CTFP(dtp), DT_INT_TYPE(dtp));
|
||||
DT_INT_CTFP(dtp), DT_INT_TYPE(dtp), B_FALSE);
|
||||
break;
|
||||
case DT_TOK_BOR:
|
||||
dnp->dn_value = l | r;
|
||||
@ -1952,12 +1991,12 @@ dt_node_op2(int op, dt_node_t *lp, dt_node_t *rp)
|
||||
case DT_TOK_EQU:
|
||||
dnp->dn_value = l == r;
|
||||
dt_node_type_assign(dnp,
|
||||
DT_INT_CTFP(dtp), DT_INT_TYPE(dtp));
|
||||
DT_INT_CTFP(dtp), DT_INT_TYPE(dtp), B_FALSE);
|
||||
break;
|
||||
case DT_TOK_NEQ:
|
||||
dnp->dn_value = l != r;
|
||||
dt_node_type_assign(dnp,
|
||||
DT_INT_CTFP(dtp), DT_INT_TYPE(dtp));
|
||||
DT_INT_CTFP(dtp), DT_INT_TYPE(dtp), B_FALSE);
|
||||
break;
|
||||
case DT_TOK_LT:
|
||||
dt_node_promote(lp, rp, dnp);
|
||||
@ -1966,7 +2005,7 @@ dt_node_op2(int op, dt_node_t *lp, dt_node_t *rp)
|
||||
else
|
||||
dnp->dn_value = l < r;
|
||||
dt_node_type_assign(dnp,
|
||||
DT_INT_CTFP(dtp), DT_INT_TYPE(dtp));
|
||||
DT_INT_CTFP(dtp), DT_INT_TYPE(dtp), B_FALSE);
|
||||
break;
|
||||
case DT_TOK_LE:
|
||||
dt_node_promote(lp, rp, dnp);
|
||||
@ -1975,7 +2014,7 @@ dt_node_op2(int op, dt_node_t *lp, dt_node_t *rp)
|
||||
else
|
||||
dnp->dn_value = l <= r;
|
||||
dt_node_type_assign(dnp,
|
||||
DT_INT_CTFP(dtp), DT_INT_TYPE(dtp));
|
||||
DT_INT_CTFP(dtp), DT_INT_TYPE(dtp), B_FALSE);
|
||||
break;
|
||||
case DT_TOK_GT:
|
||||
dt_node_promote(lp, rp, dnp);
|
||||
@ -1984,7 +2023,7 @@ dt_node_op2(int op, dt_node_t *lp, dt_node_t *rp)
|
||||
else
|
||||
dnp->dn_value = l > r;
|
||||
dt_node_type_assign(dnp,
|
||||
DT_INT_CTFP(dtp), DT_INT_TYPE(dtp));
|
||||
DT_INT_CTFP(dtp), DT_INT_TYPE(dtp), B_FALSE);
|
||||
break;
|
||||
case DT_TOK_GE:
|
||||
dt_node_promote(lp, rp, dnp);
|
||||
@ -1993,7 +2032,7 @@ dt_node_op2(int op, dt_node_t *lp, dt_node_t *rp)
|
||||
else
|
||||
dnp->dn_value = l >= r;
|
||||
dt_node_type_assign(dnp,
|
||||
DT_INT_CTFP(dtp), DT_INT_TYPE(dtp));
|
||||
DT_INT_CTFP(dtp), DT_INT_TYPE(dtp), B_FALSE);
|
||||
break;
|
||||
case DT_TOK_LSH:
|
||||
dnp->dn_value = l << r;
|
||||
@ -2234,7 +2273,7 @@ dt_node_inline(dt_node_t *expr)
|
||||
* until we have successfully cooked the right-hand expression, below.
|
||||
*/
|
||||
dnp = dt_node_alloc(DT_NODE_INLINE);
|
||||
dt_node_type_assign(dnp, dtt.dtt_ctfp, dtt.dtt_type);
|
||||
dt_node_type_assign(dnp, dtt.dtt_ctfp, dtt.dtt_type, B_FALSE);
|
||||
dt_node_attr_assign(dnp, _dtrace_defattr);
|
||||
|
||||
if (dt_node_is_void(dnp)) {
|
||||
@ -2389,7 +2428,8 @@ dt_node_member(dt_decl_t *ddp, char *name, dt_node_t *expr)
|
||||
dnp->dn_membexpr = expr;
|
||||
|
||||
if (ddp != NULL)
|
||||
dt_node_type_assign(dnp, dtt.dtt_ctfp, dtt.dtt_type);
|
||||
dt_node_type_assign(dnp, dtt.dtt_ctfp, dtt.dtt_type,
|
||||
dtt.dtt_flags);
|
||||
|
||||
return (dnp);
|
||||
}
|
||||
@ -2420,10 +2460,10 @@ dt_node_xlator(dt_decl_t *ddp, dt_decl_t *sdp, char *name, dt_node_t *members)
|
||||
}
|
||||
|
||||
bzero(&sn, sizeof (sn));
|
||||
dt_node_type_assign(&sn, src.dtt_ctfp, src.dtt_type);
|
||||
dt_node_type_assign(&sn, src.dtt_ctfp, src.dtt_type, B_FALSE);
|
||||
|
||||
bzero(&dn, sizeof (dn));
|
||||
dt_node_type_assign(&dn, dst.dtt_ctfp, dst.dtt_type);
|
||||
dt_node_type_assign(&dn, dst.dtt_ctfp, dst.dtt_type, B_FALSE);
|
||||
|
||||
if (dt_xlator_lookup(dtp, &sn, &dn, DT_XLATE_EXACT) != NULL) {
|
||||
xyerror(D_XLATE_REDECL,
|
||||
@ -2669,7 +2709,7 @@ dt_xcook_ident(dt_node_t *dnp, dt_idhash_t *dhp, uint_t idkind, int create)
|
||||
attr = dt_ident_cook(dnp, idp, NULL);
|
||||
else {
|
||||
dt_node_type_assign(dnp,
|
||||
DT_DYN_CTFP(dtp), DT_DYN_TYPE(dtp));
|
||||
DT_DYN_CTFP(dtp), DT_DYN_TYPE(dtp), B_FALSE);
|
||||
attr = idp->di_attr;
|
||||
}
|
||||
|
||||
@ -2745,7 +2785,8 @@ dt_xcook_ident(dt_node_t *dnp, dt_idhash_t *dhp, uint_t idkind, int create)
|
||||
dnp->dn_ident = idp;
|
||||
dnp->dn_flags |= DT_NF_LVALUE;
|
||||
|
||||
dt_node_type_assign(dnp, dtt.dtt_ctfp, dtt.dtt_type);
|
||||
dt_node_type_assign(dnp, dtt.dtt_ctfp, dtt.dtt_type,
|
||||
dtt.dtt_flags);
|
||||
dt_node_attr_assign(dnp, _dtrace_symattr);
|
||||
|
||||
if (uref) {
|
||||
@ -2793,7 +2834,7 @@ dt_xcook_ident(dt_node_t *dnp, dt_idhash_t *dhp, uint_t idkind, int create)
|
||||
attr = dt_ident_cook(dnp, idp, NULL);
|
||||
else {
|
||||
dt_node_type_assign(dnp,
|
||||
DT_DYN_CTFP(dtp), DT_DYN_TYPE(dtp));
|
||||
DT_DYN_CTFP(dtp), DT_DYN_TYPE(dtp), B_FALSE);
|
||||
attr = idp->di_attr;
|
||||
}
|
||||
|
||||
@ -2896,7 +2937,8 @@ dt_cook_op1(dt_node_t *dnp, uint_t idflags)
|
||||
xyerror(D_TYPE_ERR, "failed to lookup int64_t\n");
|
||||
|
||||
dt_ident_type_assign(cp->dn_ident, dtt.dtt_ctfp, dtt.dtt_type);
|
||||
dt_node_type_assign(cp, dtt.dtt_ctfp, dtt.dtt_type);
|
||||
dt_node_type_assign(cp, dtt.dtt_ctfp, dtt.dtt_type,
|
||||
dtt.dtt_flags);
|
||||
}
|
||||
|
||||
if (cp->dn_kind == DT_NODE_VAR)
|
||||
@ -2913,7 +2955,8 @@ dt_cook_op1(dt_node_t *dnp, uint_t idflags)
|
||||
|
||||
dnp->dn_ident = &dxp->dx_souid;
|
||||
dt_node_type_assign(dnp,
|
||||
dnp->dn_ident->di_ctfp, dnp->dn_ident->di_type);
|
||||
dnp->dn_ident->di_ctfp, dnp->dn_ident->di_type,
|
||||
cp->dn_flags & DT_NF_USERLAND);
|
||||
break;
|
||||
}
|
||||
|
||||
@ -2933,7 +2976,8 @@ dt_cook_op1(dt_node_t *dnp, uint_t idflags)
|
||||
"cannot dereference non-pointer type\n");
|
||||
}
|
||||
|
||||
dt_node_type_assign(dnp, cp->dn_ctfp, type);
|
||||
dt_node_type_assign(dnp, cp->dn_ctfp, type,
|
||||
cp->dn_flags & DT_NF_USERLAND);
|
||||
base = ctf_type_resolve(cp->dn_ctfp, type);
|
||||
kind = ctf_type_kind(cp->dn_ctfp, base);
|
||||
|
||||
@ -2990,7 +3034,8 @@ dt_cook_op1(dt_node_t *dnp, uint_t idflags)
|
||||
xyerror(D_OP_SCALAR, "operator %s requires an operand "
|
||||
"of scalar type\n", opstr(dnp->dn_op));
|
||||
}
|
||||
dt_node_type_assign(dnp, DT_INT_CTFP(dtp), DT_INT_TYPE(dtp));
|
||||
dt_node_type_assign(dnp, DT_INT_CTFP(dtp), DT_INT_TYPE(dtp),
|
||||
B_FALSE);
|
||||
break;
|
||||
|
||||
case DT_TOK_ADDROF:
|
||||
@ -3023,10 +3068,8 @@ dt_cook_op1(dt_node_t *dnp, uint_t idflags)
|
||||
dt_node_type_name(cp, n, sizeof (n)));
|
||||
}
|
||||
|
||||
dt_node_type_assign(dnp, dtt.dtt_ctfp, dtt.dtt_type);
|
||||
|
||||
if (cp->dn_flags & DT_NF_USERLAND)
|
||||
dnp->dn_flags |= DT_NF_USERLAND;
|
||||
dt_node_type_assign(dnp, dtt.dtt_ctfp, dtt.dtt_type,
|
||||
cp->dn_flags & DT_NF_USERLAND);
|
||||
break;
|
||||
|
||||
case DT_TOK_SIZEOF:
|
||||
@ -3041,7 +3084,8 @@ dt_cook_op1(dt_node_t *dnp, uint_t idflags)
|
||||
}
|
||||
|
||||
dt_node_type_assign(dnp, dtp->dt_ddefs->dm_ctfp,
|
||||
ctf_lookup_by_name(dtp->dt_ddefs->dm_ctfp, "size_t"));
|
||||
ctf_lookup_by_name(dtp->dt_ddefs->dm_ctfp, "size_t"),
|
||||
B_FALSE);
|
||||
break;
|
||||
|
||||
case DT_TOK_STRINGOF:
|
||||
@ -3051,7 +3095,8 @@ dt_cook_op1(dt_node_t *dnp, uint_t idflags)
|
||||
"cannot apply stringof to a value of type %s\n",
|
||||
dt_node_type_name(cp, n, sizeof (n)));
|
||||
}
|
||||
dt_node_type_assign(dnp, DT_STR_CTFP(dtp), DT_STR_TYPE(dtp));
|
||||
dt_node_type_assign(dnp, DT_STR_CTFP(dtp), DT_STR_TYPE(dtp),
|
||||
cp->dn_flags & DT_NF_USERLAND);
|
||||
break;
|
||||
|
||||
case DT_TOK_PREINC:
|
||||
@ -3244,7 +3289,8 @@ dt_cook_op2(dt_node_t *dnp, uint_t idflags)
|
||||
"of scalar type\n", opstr(op));
|
||||
}
|
||||
|
||||
dt_node_type_assign(dnp, DT_INT_CTFP(dtp), DT_INT_TYPE(dtp));
|
||||
dt_node_type_assign(dnp, DT_INT_CTFP(dtp), DT_INT_TYPE(dtp),
|
||||
B_FALSE);
|
||||
dt_node_attr_assign(dnp, dt_attr_min(lp->dn_attr, rp->dn_attr));
|
||||
break;
|
||||
|
||||
@ -3288,7 +3334,8 @@ dt_cook_op2(dt_node_t *dnp, uint_t idflags)
|
||||
rp->dn_op = DT_TOK_INT;
|
||||
rp->dn_value = (intmax_t)val;
|
||||
|
||||
dt_node_type_assign(rp, lp->dn_ctfp, lp->dn_type);
|
||||
dt_node_type_assign(rp, lp->dn_ctfp, lp->dn_type,
|
||||
B_FALSE);
|
||||
dt_node_attr_assign(rp, _dtrace_symattr);
|
||||
}
|
||||
|
||||
@ -3320,7 +3367,8 @@ dt_cook_op2(dt_node_t *dnp, uint_t idflags)
|
||||
dt_node_type_name(rp, n2, sizeof (n2)));
|
||||
}
|
||||
|
||||
dt_node_type_assign(dnp, DT_INT_CTFP(dtp), DT_INT_TYPE(dtp));
|
||||
dt_node_type_assign(dnp, DT_INT_CTFP(dtp), DT_INT_TYPE(dtp),
|
||||
B_FALSE);
|
||||
dt_node_attr_assign(dnp, dt_attr_min(lp->dn_attr, rp->dn_attr));
|
||||
break;
|
||||
|
||||
@ -3368,7 +3416,7 @@ dt_cook_op2(dt_node_t *dnp, uint_t idflags)
|
||||
dt_node_type_name(rp, n2, sizeof (n2)));
|
||||
}
|
||||
|
||||
dt_node_type_assign(dnp, ctfp, type);
|
||||
dt_node_type_assign(dnp, ctfp, type, B_FALSE);
|
||||
dt_node_attr_assign(dnp, dt_attr_min(lp->dn_attr, rp->dn_attr));
|
||||
|
||||
if (uref)
|
||||
@ -3509,7 +3557,7 @@ dt_cook_op2(dt_node_t *dnp, uint_t idflags)
|
||||
*/
|
||||
if (lp->dn_kind == DT_NODE_VAR &&
|
||||
dt_ident_unref(lp->dn_ident)) {
|
||||
dt_node_type_assign(lp, ctfp, type);
|
||||
dt_node_type_assign(lp, ctfp, type, B_FALSE);
|
||||
dt_ident_type_assign(lp->dn_ident, ctfp, type);
|
||||
|
||||
if (uref) {
|
||||
@ -3723,7 +3771,7 @@ dt_cook_op2(dt_node_t *dnp, uint_t idflags)
|
||||
type = ctf_type_resolve(ctfp, m.ctm_type);
|
||||
kind = ctf_type_kind(ctfp, type);
|
||||
|
||||
dt_node_type_assign(dnp, ctfp, m.ctm_type);
|
||||
dt_node_type_assign(dnp, ctfp, m.ctm_type, B_FALSE);
|
||||
dt_node_attr_assign(dnp, lp->dn_attr);
|
||||
|
||||
if (op == DT_TOK_PTR && (kind != CTF_K_ARRAY ||
|
||||
@ -3849,7 +3897,8 @@ dt_cook_op2(dt_node_t *dnp, uint_t idflags)
|
||||
}
|
||||
|
||||
dnp->dn_ident = dt_xlator_ident(dxp, lp->dn_ctfp, lp->dn_type);
|
||||
dt_node_type_assign(dnp, DT_DYN_CTFP(dtp), DT_DYN_TYPE(dtp));
|
||||
dt_node_type_assign(dnp, DT_DYN_CTFP(dtp), DT_DYN_TYPE(dtp),
|
||||
B_FALSE);
|
||||
dt_node_attr_assign(dnp,
|
||||
dt_attr_min(rp->dn_attr, dnp->dn_ident->di_attr));
|
||||
break;
|
||||
@ -4014,7 +4063,7 @@ dt_cook_op3(dt_node_t *dnp, uint_t idflags)
|
||||
"used in a conditional context\n");
|
||||
}
|
||||
|
||||
dt_node_type_assign(dnp, ctfp, type);
|
||||
dt_node_type_assign(dnp, ctfp, type, B_FALSE);
|
||||
dt_node_attr_assign(dnp, dt_attr_min(dnp->dn_expr->dn_attr,
|
||||
dt_attr_min(lp->dn_attr, rp->dn_attr)));
|
||||
|
||||
@ -4047,7 +4096,8 @@ dt_cook_aggregation(dt_node_t *dnp, uint_t idflags)
|
||||
dt_node_attr_assign(dnp, dt_ident_cook(dnp,
|
||||
dnp->dn_ident, &dnp->dn_aggtup));
|
||||
} else {
|
||||
dt_node_type_assign(dnp, DT_DYN_CTFP(dtp), DT_DYN_TYPE(dtp));
|
||||
dt_node_type_assign(dnp, DT_DYN_CTFP(dtp), DT_DYN_TYPE(dtp),
|
||||
B_FALSE);
|
||||
dt_node_attr_assign(dnp, dnp->dn_ident->di_attr);
|
||||
}
|
||||
|
||||
@ -4249,7 +4299,8 @@ dt_cook_xlator(dt_node_t *dnp, uint_t idflags)
|
||||
}
|
||||
|
||||
(void) dt_node_cook(mnp, DT_IDFLG_REF);
|
||||
dt_node_type_assign(mnp, dxp->dx_dst_ctfp, ctm.ctm_type);
|
||||
dt_node_type_assign(mnp, dxp->dx_dst_ctfp, ctm.ctm_type,
|
||||
B_FALSE);
|
||||
attr = dt_attr_min(attr, mnp->dn_attr);
|
||||
|
||||
if (dt_node_is_argcompat(mnp, mnp->dn_membexpr) == 0) {
|
||||
@ -4268,7 +4319,7 @@ dt_cook_xlator(dt_node_t *dnp, uint_t idflags)
|
||||
dxp->dx_souid.di_attr = attr;
|
||||
dxp->dx_ptrid.di_attr = attr;
|
||||
|
||||
dt_node_type_assign(dnp, DT_DYN_CTFP(dtp), DT_DYN_TYPE(dtp));
|
||||
dt_node_type_assign(dnp, DT_DYN_CTFP(dtp), DT_DYN_TYPE(dtp), B_FALSE);
|
||||
dt_node_attr_assign(dnp, _dtrace_defattr);
|
||||
|
||||
return (dnp);
|
||||
@ -4561,7 +4612,9 @@ dt_node_diftype(dtrace_hdl_t *dtp, const dt_node_t *dnp, dtrace_diftype_t *tp)
|
||||
ctf_type_resolve(dnp->dn_ctfp, dnp->dn_type));
|
||||
}
|
||||
|
||||
tp->dtdt_flags = (dnp->dn_flags & DT_NF_REF) ? DIF_TF_BYREF : 0;
|
||||
tp->dtdt_flags = (dnp->dn_flags & DT_NF_REF) ?
|
||||
(dnp->dn_flags & DT_NF_USERLAND) ? DIF_TF_BYUREF :
|
||||
DIF_TF_BYREF : 0;
|
||||
tp->dtdt_pad = 0;
|
||||
tp->dtdt_size = ctf_type_size(dnp->dn_ctfp, dnp->dn_type);
|
||||
}
|
||||
|
@ -22,12 +22,14 @@
|
||||
* Copyright 2007 Sun Microsystems, Inc. All rights reserved.
|
||||
* Use is subject to license terms.
|
||||
*/
|
||||
/*
|
||||
* Copyright (c) 2013 by Delphix. All rights reserved.
|
||||
* Copyright (c) 2013 Joyent, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef _DT_PARSER_H
|
||||
#define _DT_PARSER_H
|
||||
|
||||
#pragma ident "%Z%%M% %I% %E% SMI"
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/dtrace.h>
|
||||
|
||||
@ -223,7 +225,7 @@ extern void dt_node_list_free(dt_node_t **);
|
||||
extern void dt_node_link_free(dt_node_t **);
|
||||
|
||||
extern void dt_node_attr_assign(dt_node_t *, dtrace_attribute_t);
|
||||
extern void dt_node_type_assign(dt_node_t *, ctf_file_t *, ctf_id_t);
|
||||
extern void dt_node_type_assign(dt_node_t *, ctf_file_t *, ctf_id_t, boolean_t);
|
||||
extern void dt_node_type_propagate(const dt_node_t *, dt_node_t *);
|
||||
extern const char *dt_node_type_name(const dt_node_t *, char *, size_t);
|
||||
extern size_t dt_node_type_size(const dt_node_t *);
|
||||
|
@ -23,6 +23,9 @@
|
||||
* Copyright 2010 Sun Microsystems, Inc. All rights reserved.
|
||||
* Use is subject to license terms.
|
||||
*/
|
||||
/*
|
||||
* Copyright (c) 2013, Joyent, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <strings.h>
|
||||
@ -35,6 +38,7 @@
|
||||
#endif
|
||||
#include <libgen.h>
|
||||
#include <stddef.h>
|
||||
#include <sys/sysmacros.h>
|
||||
|
||||
#include <dt_impl.h>
|
||||
#include <dt_program.h>
|
||||
@ -43,6 +47,7 @@
|
||||
#if !defined(sun)
|
||||
#include <libproc_compat.h>
|
||||
#endif
|
||||
#include <dt_module.h>
|
||||
|
||||
typedef struct dt_pid_probe {
|
||||
dtrace_hdl_t *dpp_dtp;
|
||||
@ -827,3 +832,170 @@ dt_pid_create_probes_module(dtrace_hdl_t *dtp, dt_proc_t *dpr)
|
||||
|
||||
return (ret);
|
||||
}
|
||||
|
||||
/*
|
||||
* libdtrace has a backroom deal with us to ask us for type information on
|
||||
* behalf of pid provider probes when fasttrap doesn't return any type
|
||||
* information. Instead we'll look up the module and see if there is type
|
||||
* information available. However, if there is no type information available due
|
||||
* to a lack of CTF data, then we want to make sure that DTrace still carries on
|
||||
* in face of that. As such we don't have a meaningful exit code about failure.
|
||||
* We emit information about why we failed to the dtrace debug log so someone
|
||||
* can figure it out by asking nicely for DTRACE_DEBUG.
|
||||
*/
|
||||
void
|
||||
dt_pid_get_types(dtrace_hdl_t *dtp, const dtrace_probedesc_t *pdp,
|
||||
dtrace_argdesc_t *adp, int *nargs)
|
||||
{
|
||||
dt_module_t *dmp;
|
||||
ctf_file_t *fp;
|
||||
ctf_funcinfo_t f;
|
||||
ctf_id_t argv[32];
|
||||
GElf_Sym sym;
|
||||
#if defined(sun)
|
||||
prsyminfo_t si;
|
||||
#else
|
||||
void *si;
|
||||
#endif
|
||||
struct ps_prochandle *p;
|
||||
int i, args;
|
||||
char buf[DTRACE_ARGTYPELEN];
|
||||
const char *mptr;
|
||||
char *eptr;
|
||||
int ret = 0;
|
||||
int argc = sizeof (argv) / sizeof (ctf_id_t);
|
||||
Lmid_t lmid;
|
||||
|
||||
/* Set up a potential outcome */
|
||||
args = *nargs;
|
||||
*nargs = 0;
|
||||
|
||||
/*
|
||||
* If we don't have an entry or return probe then we can just stop right
|
||||
* now as we don't have arguments for offset probes.
|
||||
*/
|
||||
if (strcmp(pdp->dtpd_name, "entry") != 0 &&
|
||||
strcmp(pdp->dtpd_name, "return") != 0)
|
||||
return;
|
||||
|
||||
dmp = dt_module_create(dtp, pdp->dtpd_provider);
|
||||
if (dmp == NULL) {
|
||||
dt_dprintf("failed to find module for %s\n",
|
||||
pdp->dtpd_provider);
|
||||
return;
|
||||
}
|
||||
if (dt_module_load(dtp, dmp) != 0) {
|
||||
dt_dprintf("failed to load module for %s\n",
|
||||
pdp->dtpd_provider);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* We may be working with a module that doesn't have ctf. If that's the
|
||||
* case then we just return now and move on with life.
|
||||
*/
|
||||
fp = dt_module_getctflib(dtp, dmp, pdp->dtpd_mod);
|
||||
if (fp == NULL) {
|
||||
dt_dprintf("no ctf container for %s\n",
|
||||
pdp->dtpd_mod);
|
||||
return;
|
||||
}
|
||||
p = dt_proc_grab(dtp, dmp->dm_pid, 0, PGRAB_RDONLY | PGRAB_FORCE);
|
||||
if (p == NULL) {
|
||||
dt_dprintf("failed to grab pid\n");
|
||||
return;
|
||||
}
|
||||
dt_proc_lock(dtp, p);
|
||||
|
||||
/*
|
||||
* Check to see if the D module has a link map ID and separate that out
|
||||
* for properly interrogating libproc.
|
||||
*/
|
||||
if ((mptr = strchr(pdp->dtpd_mod, '`')) != NULL) {
|
||||
if (strlen(pdp->dtpd_mod) < 3) {
|
||||
dt_dprintf("found weird modname with linkmap, "
|
||||
"aborting: %s\n", pdp->dtpd_mod);
|
||||
goto out;
|
||||
}
|
||||
if (pdp->dtpd_mod[0] != 'L' || pdp->dtpd_mod[1] != 'M') {
|
||||
dt_dprintf("missing leading 'LM', "
|
||||
"aborting: %s\n", pdp->dtpd_mod);
|
||||
goto out;
|
||||
}
|
||||
errno = 0;
|
||||
lmid = strtol(pdp->dtpd_mod + 2, &eptr, 16);
|
||||
if (errno == ERANGE || eptr != mptr) {
|
||||
dt_dprintf("failed to parse out lmid, aborting: %s\n",
|
||||
pdp->dtpd_mod);
|
||||
goto out;
|
||||
}
|
||||
mptr++;
|
||||
} else {
|
||||
mptr = pdp->dtpd_mod;
|
||||
lmid = 0;
|
||||
}
|
||||
|
||||
if (Pxlookup_by_name(p, lmid, mptr, pdp->dtpd_func,
|
||||
&sym, &si) != 0) {
|
||||
dt_dprintf("failed to find function %s in %s`%s\n",
|
||||
pdp->dtpd_func, pdp->dtpd_provider, pdp->dtpd_mod);
|
||||
goto out;
|
||||
}
|
||||
#if defined(sun)
|
||||
if (ctf_func_info(fp, si.prs_id, &f) == CTF_ERR) {
|
||||
dt_dprintf("failed to get ctf information for %s in %s`%s\n",
|
||||
pdp->dtpd_func, pdp->dtpd_provider, pdp->dtpd_mod);
|
||||
goto out;
|
||||
}
|
||||
#endif
|
||||
|
||||
(void) snprintf(buf, sizeof (buf), "%s`%s", pdp->dtpd_provider,
|
||||
pdp->dtpd_mod);
|
||||
|
||||
if (strcmp(pdp->dtpd_name, "return") == 0) {
|
||||
if (args < 2)
|
||||
goto out;
|
||||
|
||||
bzero(adp, sizeof (dtrace_argdesc_t));
|
||||
adp->dtargd_ndx = 0;
|
||||
adp->dtargd_id = pdp->dtpd_id;
|
||||
adp->dtargd_mapping = adp->dtargd_ndx;
|
||||
/*
|
||||
* We explicitly leave out the library here, we only care that
|
||||
* it is some int. We are assuming that there is no ctf
|
||||
* container in here that is lying about what an int is.
|
||||
*/
|
||||
(void) snprintf(adp->dtargd_native, DTRACE_ARGTYPELEN,
|
||||
"user %s`%s", pdp->dtpd_provider, "int");
|
||||
adp++;
|
||||
bzero(adp, sizeof (dtrace_argdesc_t));
|
||||
adp->dtargd_ndx = 1;
|
||||
adp->dtargd_id = pdp->dtpd_id;
|
||||
adp->dtargd_mapping = adp->dtargd_ndx;
|
||||
ret = snprintf(adp->dtargd_native, DTRACE_ARGTYPELEN,
|
||||
"userland ");
|
||||
(void) ctf_type_qname(fp, f.ctc_return, adp->dtargd_native +
|
||||
ret, DTRACE_ARGTYPELEN - ret, buf);
|
||||
*nargs = 2;
|
||||
#if defined(sun)
|
||||
} else {
|
||||
if (ctf_func_args(fp, si.prs_id, argc, argv) == CTF_ERR)
|
||||
goto out;
|
||||
|
||||
*nargs = MIN(args, f.ctc_argc);
|
||||
for (i = 0; i < *nargs; i++, adp++) {
|
||||
bzero(adp, sizeof (dtrace_argdesc_t));
|
||||
adp->dtargd_ndx = i;
|
||||
adp->dtargd_id = pdp->dtpd_id;
|
||||
adp->dtargd_mapping = adp->dtargd_ndx;
|
||||
ret = snprintf(adp->dtargd_native, DTRACE_ARGTYPELEN,
|
||||
"userland ");
|
||||
(void) ctf_type_qname(fp, argv[i], adp->dtargd_native +
|
||||
ret, DTRACE_ARGTYPELEN - ret, buf);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
out:
|
||||
dt_proc_unlock(dtp, p);
|
||||
dt_proc_release(dtp, p);
|
||||
}
|
||||
|
@ -24,12 +24,13 @@
|
||||
* Copyright 2006 Sun Microsystems, Inc. All rights reserved.
|
||||
* Use is subject to license terms.
|
||||
*/
|
||||
/*
|
||||
* Copyright (c) 2013, Joyent, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef _DT_PID_H
|
||||
#define _DT_PID_H
|
||||
|
||||
#pragma ident "%Z%%M% %I% %E% SMI"
|
||||
|
||||
#include <libproc.h>
|
||||
#include <sys/fasttrap.h>
|
||||
#include <dt_impl.h>
|
||||
@ -57,6 +58,9 @@ extern int dt_pid_create_offset_probe(struct ps_prochandle *, dtrace_hdl_t *,
|
||||
extern int dt_pid_create_glob_offset_probes(struct ps_prochandle *,
|
||||
dtrace_hdl_t *, fasttrap_probe_spec_t *, const GElf_Sym *, const char *);
|
||||
|
||||
extern void dt_pid_get_types(dtrace_hdl_t *, const dtrace_probedesc_t *,
|
||||
dtrace_argdesc_t *, int *);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
@ -647,12 +647,16 @@ dtrace_print(dtrace_hdl_t *dtp, FILE *fp, const char *typename,
|
||||
dt_printarg_t pa;
|
||||
ctf_id_t id;
|
||||
dt_module_t *dmp;
|
||||
ctf_file_t *ctfp;
|
||||
int libid;
|
||||
|
||||
/*
|
||||
* Split the fully-qualified type ID (module`id). This should
|
||||
* always be the format, but if for some reason we don't find the
|
||||
* expected value, return 0 to fall back to the generic trace()
|
||||
* behavior.
|
||||
* behavior. In the case of userland CTF modules this will actually be
|
||||
* of the format (module`lib`id). This is due to the fact that those
|
||||
* modules have multiple CTF containers which `lib` identifies.
|
||||
*/
|
||||
for (s = typename; *s != '\0' && *s != '`'; s++)
|
||||
;
|
||||
@ -663,6 +667,20 @@ dtrace_print(dtrace_hdl_t *dtp, FILE *fp, const char *typename,
|
||||
object = alloca(s - typename + 1);
|
||||
bcopy(typename, object, s - typename);
|
||||
object[s - typename] = '\0';
|
||||
dmp = dt_module_lookup_by_name(dtp, object);
|
||||
if (dmp == NULL)
|
||||
return (0);
|
||||
|
||||
if (dmp->dm_pid != 0) {
|
||||
libid = atoi(s + 1);
|
||||
s = strchr(s + 1, '`');
|
||||
if (s == NULL || libid > dmp->dm_nctflibs)
|
||||
return (0);
|
||||
ctfp = dmp->dm_libctfp[libid];
|
||||
} else {
|
||||
ctfp = dt_module_getctf(dtp, dmp);
|
||||
}
|
||||
|
||||
id = atoi(s + 1);
|
||||
|
||||
/*
|
||||
@ -670,16 +688,13 @@ dtrace_print(dtrace_hdl_t *dtp, FILE *fp, const char *typename,
|
||||
* wrong and we can't resolve the ID, bail out and let trace() do the
|
||||
* work.
|
||||
*/
|
||||
dmp = dt_module_lookup_by_name(dtp, object);
|
||||
if (dmp == NULL || ctf_type_kind(dt_module_getctf(dtp, dmp),
|
||||
id) == CTF_ERR) {
|
||||
if (ctfp == NULL || ctf_type_kind(ctfp, id) == CTF_ERR)
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* setup the print structure and kick off the main print routine */
|
||||
pa.pa_dtp = dtp;
|
||||
pa.pa_addr = addr;
|
||||
pa.pa_ctfp = dt_module_getctf(dtp, dmp);
|
||||
pa.pa_ctfp = ctfp;
|
||||
pa.pa_nest = 0;
|
||||
pa.pa_depth = 0;
|
||||
pa.pa_file = fp;
|
||||
|
@ -21,8 +21,8 @@
|
||||
|
||||
/*
|
||||
* Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2011, Joyent, Inc. All rights reserved.
|
||||
* Copyright (c) 2012 by Delphix. All rights reserved.
|
||||
* Copyright (c) 2013, Joyent, Inc. All rights reserved.
|
||||
* Copyright (c) 2013 by Delphix. All rights reserved.
|
||||
*/
|
||||
|
||||
#if defined(sun)
|
||||
@ -1075,7 +1075,7 @@ dt_printf_validate(dt_pfargv_t *pfv, uint_t flags,
|
||||
xyerror(D_TYPE_ERR, "failed to lookup agg type %s\n", aggtype);
|
||||
|
||||
bzero(&aggnode, sizeof (aggnode));
|
||||
dt_node_type_assign(&aggnode, dtt.dtt_ctfp, dtt.dtt_type);
|
||||
dt_node_type_assign(&aggnode, dtt.dtt_ctfp, dtt.dtt_type, B_FALSE);
|
||||
|
||||
for (i = 0, j = 0; i < pfv->pfv_argc; i++, pfd = pfd->pfd_next) {
|
||||
const dt_pfconv_t *pfc = pfd->pfd_conv;
|
||||
|
@ -23,8 +23,9 @@
|
||||
* Copyright 2006 Sun Microsystems, Inc. All rights reserved.
|
||||
* Use is subject to license terms.
|
||||
*/
|
||||
|
||||
#pragma ident "%Z%%M% %I% %E% SMI"
|
||||
/*
|
||||
* Copyright (c) 2013, Joyent, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#if defined(sun)
|
||||
@ -45,6 +46,8 @@
|
||||
#include <dt_module.h>
|
||||
#include <dt_string.h>
|
||||
#include <dt_list.h>
|
||||
#include <dt_pid.h>
|
||||
#include <dtrace.h>
|
||||
|
||||
static dt_provider_t *
|
||||
dt_provider_insert(dtrace_hdl_t *dtp, dt_provider_t *pvp, uint_t h)
|
||||
@ -272,6 +275,21 @@ dt_probe_discover(dt_provider_t *pvp, const dtrace_probedesc_t *pdp)
|
||||
xc = i;
|
||||
nc++;
|
||||
|
||||
/*
|
||||
* The pid provider believes in giving the kernel a break. No reason to
|
||||
* give the kernel all the ctf containers that we're keeping ourselves
|
||||
* just to get it back from it. So if we're coming from a pid provider
|
||||
* probe and the kernel gave us no argument information we'll get some
|
||||
* here. If for some crazy reason the kernel knows about our userland
|
||||
* types then we just ignore this.
|
||||
*/
|
||||
if (xc == 0 && nc == 0 &&
|
||||
strncmp(pvp->pv_desc.dtvd_name, "pid", 3) == 0) {
|
||||
nc = adc;
|
||||
dt_pid_get_types(dtp, pdp, adv, &nc);
|
||||
xc = nc;
|
||||
}
|
||||
|
||||
/*
|
||||
* Now that we have discovered the number of native and translated
|
||||
* arguments from the argument descriptions, allocate a new probe ident
|
||||
@ -318,7 +336,8 @@ dt_probe_discover(dt_provider_t *pvp, const dtrace_probedesc_t *pdp)
|
||||
dtt.dtt_type = CTF_ERR;
|
||||
} else {
|
||||
dt_node_type_assign(prp->pr_nargv[adp->dtargd_mapping],
|
||||
dtt.dtt_ctfp, dtt.dtt_type);
|
||||
dtt.dtt_ctfp, dtt.dtt_type,
|
||||
dtt.dtt_flags & DTT_FL_USER ? B_TRUE : B_FALSE);
|
||||
}
|
||||
|
||||
if (dtt.dtt_type != CTF_ERR && (adp->dtargd_xlate[0] == '\0' ||
|
||||
@ -337,7 +356,7 @@ dt_probe_discover(dt_provider_t *pvp, const dtrace_probedesc_t *pdp)
|
||||
dtt.dtt_type = CTF_ERR;
|
||||
} else {
|
||||
dt_node_type_assign(prp->pr_xargv[i],
|
||||
dtt.dtt_ctfp, dtt.dtt_type);
|
||||
dtt.dtt_ctfp, dtt.dtt_type, B_FALSE);
|
||||
}
|
||||
|
||||
prp->pr_mapping[i] = adp->dtargd_mapping;
|
||||
@ -638,7 +657,7 @@ dt_probe_tag(dt_probe_t *prp, uint_t argn, dt_node_t *dnp)
|
||||
bzero(dnp, sizeof (dt_node_t));
|
||||
dnp->dn_kind = DT_NODE_TYPE;
|
||||
|
||||
dt_node_type_assign(dnp, dtt.dtt_ctfp, dtt.dtt_type);
|
||||
dt_node_type_assign(dnp, dtt.dtt_ctfp, dtt.dtt_type, B_FALSE);
|
||||
dt_node_attr_assign(dnp, _dtrace_defattr);
|
||||
|
||||
return (dnp);
|
||||
|
@ -23,8 +23,10 @@
|
||||
* Copyright 2005 Sun Microsystems, Inc. All rights reserved.
|
||||
* Use is subject to license terms.
|
||||
*/
|
||||
|
||||
#pragma ident "%Z%%M% %I% %E% SMI"
|
||||
/*
|
||||
* Copyright (c) 2013 by Delphix. All rights reserved.
|
||||
* Copyright (c) 2013 Joyent, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <strings.h>
|
||||
#include <assert.h>
|
||||
@ -69,7 +71,7 @@ dt_xlator_create_member(const char *name, ctf_id_t type, ulong_t off, void *arg)
|
||||
enp->dn_op = DT_TOK_XLATE;
|
||||
enp->dn_xlator = dxp;
|
||||
enp->dn_xmember = mnp;
|
||||
dt_node_type_assign(enp, dxp->dx_dst_ctfp, type);
|
||||
dt_node_type_assign(enp, dxp->dx_dst_ctfp, type, B_FALSE);
|
||||
|
||||
/*
|
||||
* For the member itself, we use a DT_NODE_MEMBER as usual with the
|
||||
@ -83,7 +85,7 @@ dt_xlator_create_member(const char *name, ctf_id_t type, ulong_t off, void *arg)
|
||||
|
||||
mnp->dn_membname = strdup(name);
|
||||
mnp->dn_membexpr = enp;
|
||||
dt_node_type_assign(mnp, dxp->dx_dst_ctfp, type);
|
||||
dt_node_type_assign(mnp, dxp->dx_dst_ctfp, type, B_FALSE);
|
||||
|
||||
if (mnp->dn_membname == NULL)
|
||||
return (dt_set_errno(dtp, EDT_NOMEM));
|
||||
@ -318,7 +320,8 @@ dt_xlator_lookup(dtrace_hdl_t *dtp, dt_node_t *src, dt_node_t *dst, int flags)
|
||||
|
||||
for (dxp = dt_list_next(&dtp->dt_xlators); dxp != NULL;
|
||||
dxp = dt_list_next(dxp)) {
|
||||
dt_node_type_assign(&xn, dxp->dx_src_ctfp, dxp->dx_src_type);
|
||||
dt_node_type_assign(&xn, dxp->dx_src_ctfp, dxp->dx_src_type,
|
||||
B_FALSE);
|
||||
if (ctf_type_compat(dxp->dx_dst_ctfp, dxp->dx_dst_base,
|
||||
dst_ctfp, dst_base) && dt_node_is_argcompat(src, &xn))
|
||||
goto out;
|
||||
|
@ -25,7 +25,8 @@
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 2011, Joyent, Inc. All rights reserved.
|
||||
* Copyright (c) 2013 by Delphix. All rights reserved.
|
||||
* Copyright (c) 2013, Joyent, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef _DTRACE_H
|
||||
@ -495,8 +496,11 @@ typedef struct dtrace_typeinfo {
|
||||
const char *dtt_object; /* object containing type */
|
||||
ctf_file_t *dtt_ctfp; /* CTF container handle */
|
||||
ctf_id_t dtt_type; /* CTF type identifier */
|
||||
uint_t dtt_flags; /* Misc. flags */
|
||||
} dtrace_typeinfo_t;
|
||||
|
||||
#define DTT_FL_USER 0x1 /* user type */
|
||||
|
||||
extern int dtrace_lookup_by_type(dtrace_hdl_t *, const char *, const char *,
|
||||
dtrace_typeinfo_t *);
|
||||
|
||||
|
@ -6039,32 +6039,46 @@ dtrace_dif_emulate(dtrace_difo_t *difo, dtrace_mstate_t *mstate,
|
||||
regs[rd] = dtrace_load64(regs[r1]);
|
||||
break;
|
||||
case DIF_OP_ULDSB:
|
||||
DTRACE_CPUFLAG_SET(CPU_DTRACE_NOFAULT);
|
||||
regs[rd] = (int8_t)
|
||||
dtrace_fuword8((void *)(uintptr_t)regs[r1]);
|
||||
DTRACE_CPUFLAG_CLEAR(CPU_DTRACE_NOFAULT);
|
||||
break;
|
||||
case DIF_OP_ULDSH:
|
||||
DTRACE_CPUFLAG_SET(CPU_DTRACE_NOFAULT);
|
||||
regs[rd] = (int16_t)
|
||||
dtrace_fuword16((void *)(uintptr_t)regs[r1]);
|
||||
DTRACE_CPUFLAG_CLEAR(CPU_DTRACE_NOFAULT);
|
||||
break;
|
||||
case DIF_OP_ULDSW:
|
||||
DTRACE_CPUFLAG_SET(CPU_DTRACE_NOFAULT);
|
||||
regs[rd] = (int32_t)
|
||||
dtrace_fuword32((void *)(uintptr_t)regs[r1]);
|
||||
DTRACE_CPUFLAG_CLEAR(CPU_DTRACE_NOFAULT);
|
||||
break;
|
||||
case DIF_OP_ULDUB:
|
||||
DTRACE_CPUFLAG_SET(CPU_DTRACE_NOFAULT);
|
||||
regs[rd] =
|
||||
dtrace_fuword8((void *)(uintptr_t)regs[r1]);
|
||||
DTRACE_CPUFLAG_CLEAR(CPU_DTRACE_NOFAULT);
|
||||
break;
|
||||
case DIF_OP_ULDUH:
|
||||
DTRACE_CPUFLAG_SET(CPU_DTRACE_NOFAULT);
|
||||
regs[rd] =
|
||||
dtrace_fuword16((void *)(uintptr_t)regs[r1]);
|
||||
DTRACE_CPUFLAG_CLEAR(CPU_DTRACE_NOFAULT);
|
||||
break;
|
||||
case DIF_OP_ULDUW:
|
||||
DTRACE_CPUFLAG_SET(CPU_DTRACE_NOFAULT);
|
||||
regs[rd] =
|
||||
dtrace_fuword32((void *)(uintptr_t)regs[r1]);
|
||||
DTRACE_CPUFLAG_CLEAR(CPU_DTRACE_NOFAULT);
|
||||
break;
|
||||
case DIF_OP_ULDX:
|
||||
DTRACE_CPUFLAG_SET(CPU_DTRACE_NOFAULT);
|
||||
regs[rd] =
|
||||
dtrace_fuword64((void *)(uintptr_t)regs[r1]);
|
||||
DTRACE_CPUFLAG_CLEAR(CPU_DTRACE_NOFAULT);
|
||||
break;
|
||||
case DIF_OP_RET:
|
||||
rval = regs[rd];
|
||||
@ -6746,7 +6760,7 @@ dtrace_action_chill(dtrace_mstate_t *mstate, hrtime_t val)
|
||||
if (dtrace_destructive_disallow)
|
||||
return;
|
||||
|
||||
flags = (volatile uint16_t *)&cpu_core[cpu->cpu_id].cpuc_dtrace_flags;
|
||||
flags = (volatile uint16_t *)&cpu_core[curcpu].cpuc_dtrace_flags;
|
||||
|
||||
now = dtrace_gethrtime();
|
||||
|
||||
@ -6894,6 +6908,63 @@ dtrace_action_ustack(dtrace_mstate_t *mstate, dtrace_state_t *state,
|
||||
mstate->dtms_scratch_ptr = old;
|
||||
}
|
||||
|
||||
static void
|
||||
dtrace_store_by_ref(dtrace_difo_t *dp, caddr_t tomax, size_t size,
|
||||
size_t *valoffsp, uint64_t *valp, uint64_t end, int intuple, int dtkind)
|
||||
{
|
||||
volatile uint16_t *flags;
|
||||
uint64_t val = *valp;
|
||||
size_t valoffs = *valoffsp;
|
||||
|
||||
flags = (volatile uint16_t *)&cpu_core[curcpu].cpuc_dtrace_flags;
|
||||
ASSERT(dtkind == DIF_TF_BYREF || dtkind == DIF_TF_BYUREF);
|
||||
|
||||
/*
|
||||
* If this is a string, we're going to only load until we find the zero
|
||||
* byte -- after which we'll store zero bytes.
|
||||
*/
|
||||
if (dp->dtdo_rtype.dtdt_kind == DIF_TYPE_STRING) {
|
||||
char c = '\0' + 1;
|
||||
size_t s;
|
||||
|
||||
for (s = 0; s < size; s++) {
|
||||
if (c != '\0' && dtkind == DIF_TF_BYREF) {
|
||||
c = dtrace_load8(val++);
|
||||
} else if (c != '\0' && dtkind == DIF_TF_BYUREF) {
|
||||
DTRACE_CPUFLAG_SET(CPU_DTRACE_NOFAULT);
|
||||
c = dtrace_fuword8((void *)(uintptr_t)val++);
|
||||
DTRACE_CPUFLAG_CLEAR(CPU_DTRACE_NOFAULT);
|
||||
if (*flags & CPU_DTRACE_FAULT)
|
||||
break;
|
||||
}
|
||||
|
||||
DTRACE_STORE(uint8_t, tomax, valoffs++, c);
|
||||
|
||||
if (c == '\0' && intuple)
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
uint8_t c;
|
||||
while (valoffs < end) {
|
||||
if (dtkind == DIF_TF_BYREF) {
|
||||
c = dtrace_load8(val++);
|
||||
} else if (dtkind == DIF_TF_BYUREF) {
|
||||
DTRACE_CPUFLAG_SET(CPU_DTRACE_NOFAULT);
|
||||
c = dtrace_fuword8((void *)(uintptr_t)val++);
|
||||
DTRACE_CPUFLAG_CLEAR(CPU_DTRACE_NOFAULT);
|
||||
if (*flags & CPU_DTRACE_FAULT)
|
||||
break;
|
||||
}
|
||||
|
||||
DTRACE_STORE(uint8_t, tomax,
|
||||
valoffs++, c);
|
||||
}
|
||||
}
|
||||
|
||||
*valp = val;
|
||||
*valoffsp = valoffs;
|
||||
}
|
||||
|
||||
/*
|
||||
* If you're looking for the epicenter of DTrace, you just found it. This
|
||||
* is the function called by the provider to fire a probe -- from which all
|
||||
@ -7531,7 +7602,8 @@ dtrace_probe(dtrace_id_t id, uintptr_t arg0, uintptr_t arg1,
|
||||
ASSERT(0);
|
||||
}
|
||||
|
||||
if (dp->dtdo_rtype.dtdt_flags & DIF_TF_BYREF) {
|
||||
if (dp->dtdo_rtype.dtdt_flags & DIF_TF_BYREF ||
|
||||
dp->dtdo_rtype.dtdt_flags & DIF_TF_BYUREF) {
|
||||
uintptr_t end = valoffs + size;
|
||||
|
||||
if (tracememsize != 0 &&
|
||||
@ -7540,40 +7612,15 @@ dtrace_probe(dtrace_id_t id, uintptr_t arg0, uintptr_t arg1,
|
||||
tracememsize = 0;
|
||||
}
|
||||
|
||||
if (!dtrace_vcanload((void *)(uintptr_t)val,
|
||||
if (dp->dtdo_rtype.dtdt_flags & DIF_TF_BYREF &&
|
||||
!dtrace_vcanload((void *)(uintptr_t)val,
|
||||
&dp->dtdo_rtype, &mstate, vstate))
|
||||
continue;
|
||||
|
||||
/*
|
||||
* If this is a string, we're going to only
|
||||
* load until we find the zero byte -- after
|
||||
* which we'll store zero bytes.
|
||||
*/
|
||||
if (dp->dtdo_rtype.dtdt_kind ==
|
||||
DIF_TYPE_STRING) {
|
||||
char c = '\0' + 1;
|
||||
int intuple = act->dta_intuple;
|
||||
size_t s;
|
||||
|
||||
for (s = 0; s < size; s++) {
|
||||
if (c != '\0')
|
||||
c = dtrace_load8(val++);
|
||||
|
||||
DTRACE_STORE(uint8_t, tomax,
|
||||
valoffs++, c);
|
||||
|
||||
if (c == '\0' && intuple)
|
||||
break;
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
while (valoffs < end) {
|
||||
DTRACE_STORE(uint8_t, tomax, valoffs++,
|
||||
dtrace_load8(val++));
|
||||
}
|
||||
|
||||
dtrace_store_by_ref(dp, tomax, size, &valoffs,
|
||||
&val, end, act->dta_intuple,
|
||||
dp->dtdo_rtype.dtdt_flags & DIF_TF_BYREF ?
|
||||
DIF_TF_BYREF: DIF_TF_BYUREF);
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -9714,7 +9761,7 @@ dtrace_difo_validate(dtrace_difo_t *dp, dtrace_vstate_t *vstate, uint_t nregs,
|
||||
"expected 'ret' as last DIF instruction\n");
|
||||
}
|
||||
|
||||
if (!(dp->dtdo_rtype.dtdt_flags & DIF_TF_BYREF)) {
|
||||
if (!(dp->dtdo_rtype.dtdt_flags & (DIF_TF_BYREF | DIF_TF_BYUREF))) {
|
||||
/*
|
||||
* If we're not returning by reference, the size must be either
|
||||
* 0 or the size of one of the base types.
|
||||
|
@ -24,7 +24,7 @@
|
||||
* Use is subject to license terms.
|
||||
*/
|
||||
/*
|
||||
* Copyright (c) 2012, Joyent, Inc. All rights reserved.
|
||||
* Copyright (c) 2013, Joyent, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
/*
|
||||
@ -155,6 +155,7 @@ extern ctf_file_t *ctf_bufopen(const ctf_sect_t *, const ctf_sect_t *,
|
||||
extern ctf_file_t *ctf_fdopen(int, int *);
|
||||
extern ctf_file_t *ctf_open(const char *, int *);
|
||||
extern ctf_file_t *ctf_create(int *);
|
||||
extern ctf_file_t *ctf_dup(ctf_file_t *);
|
||||
extern void ctf_close(ctf_file_t *);
|
||||
|
||||
extern ctf_file_t *ctf_parent_file(ctf_file_t *);
|
||||
@ -180,6 +181,8 @@ extern ctf_id_t ctf_lookup_by_symbol(ctf_file_t *, ulong_t);
|
||||
extern ctf_id_t ctf_type_resolve(ctf_file_t *, ctf_id_t);
|
||||
extern ssize_t ctf_type_lname(ctf_file_t *, ctf_id_t, char *, size_t);
|
||||
extern char *ctf_type_name(ctf_file_t *, ctf_id_t, char *, size_t);
|
||||
extern char *ctf_type_qname(ctf_file_t *, ctf_id_t, char *, size_t,
|
||||
const char *);
|
||||
extern ssize_t ctf_type_size(ctf_file_t *, ctf_id_t);
|
||||
extern ssize_t ctf_type_align(ctf_file_t *, ctf_id_t);
|
||||
extern int ctf_type_kind(ctf_file_t *, ctf_id_t);
|
||||
|
@ -25,8 +25,8 @@
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 2012, Joyent, Inc. All rights reserved.
|
||||
* Copyright (c) 2012 by Delphix. All rights reserved.
|
||||
* Copyright (c) 2013, Joyent, Inc. All rights reserved.
|
||||
* Copyright (c) 2013 by Delphix. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef _SYS_DTRACE_H
|
||||
@ -377,6 +377,7 @@ typedef struct dtrace_diftype {
|
||||
#define DIF_TYPE_STRING 1 /* type is a D string */
|
||||
|
||||
#define DIF_TF_BYREF 0x1 /* type is passed by reference */
|
||||
#define DIF_TF_BYUREF 0x2 /* user type is passed by reference */
|
||||
|
||||
/*
|
||||
* A DTrace Intermediate Format variable record is used to describe each of the
|
||||
|
Loading…
Reference in New Issue
Block a user