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:
rpaulo 2014-06-26 23:21:11 +00:00
commit 8c0e49065f
52 changed files with 2057 additions and 163 deletions

View File

@ -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)

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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);
}

View File

@ -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

View File

@ -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(&lttp);
sleep(1);
}
return (0);
}

View File

@ -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

View File

@ -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

View File

@ -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);
}

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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);
}

View File

@ -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

View File

@ -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
}

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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.

View File

@ -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);

View File

@ -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);

View File

@ -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.

View File

@ -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 */

View File

@ -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);

View File

@ -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]);

View File

@ -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"));
}

View File

@ -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

View File

@ -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 */
};
/*

View File

@ -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));
}

View File

@ -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));

View File

@ -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
}

View File

@ -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
};

View File

@ -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);
}

View File

@ -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 *);

View File

@ -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);
}

View File

@ -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

View File

@ -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;

View File

@ -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;

View File

@ -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);

View File

@ -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;

View File

@ -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 *);

View File

@ -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.

View File

@ -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);

View File

@ -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