DTrace: Revert r249367
The following change from illumos brought caused DTrace to pause in an interactive environment: 3026 libdtrace should set LD_NOLAZYLOAD=1 to help the pid provider This was not detected during testing because it doesn't affect scripts. We shouldn't be changing the environment, especially since the LD_NOLAZYLOAD option doesn't apply to our (GNU) ld. Unfortunately the change from upstream was made in such a way that it is very difficult to separate this change from the others so, at least for now, it's better to just revert everything. Reference: https://www.illumos.org/issues/3026 Reported by: Navdeep Parhar and Mark Johnston
This commit is contained in:
parent
9f08548d20
commit
03836978be
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=249573
@ -23,9 +23,8 @@
|
|||||||
* Copyright 2006 Sun Microsystems, Inc. All rights reserved.
|
* Copyright 2006 Sun Microsystems, Inc. All rights reserved.
|
||||||
* Use is subject to license terms.
|
* Use is subject to license terms.
|
||||||
*/
|
*/
|
||||||
/*
|
|
||||||
* Copyright (c) 2012 by Delphix. All rights reserved.
|
#pragma ident "%Z%%M% %I% %E% SMI"
|
||||||
*/
|
|
||||||
|
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
@ -1410,7 +1409,6 @@ main(int argc, char *argv[])
|
|||||||
(void) dtrace_setopt(g_dtp, "bufsize", "4m");
|
(void) dtrace_setopt(g_dtp, "bufsize", "4m");
|
||||||
(void) dtrace_setopt(g_dtp, "aggsize", "4m");
|
(void) dtrace_setopt(g_dtp, "aggsize", "4m");
|
||||||
#endif
|
#endif
|
||||||
(void) dtrace_setopt(g_dtp, "temporal", "yes");
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If -G is specified, enable -xlink=dynamic and -xunodefs to permit
|
* If -G is specified, enable -xlink=dynamic and -xunodefs to permit
|
||||||
|
@ -583,8 +583,6 @@ if ($opt_x) {
|
|||||||
die "$PNAME: failed to open $PNAME.$$.log: $!\n"
|
die "$PNAME: failed to open $PNAME.$$.log: $!\n"
|
||||||
unless (!$opt_l || open(LOG, ">$PNAME.$$.log"));
|
unless (!$opt_l || open(LOG, ">$PNAME.$$.log"));
|
||||||
|
|
||||||
$ENV{'DTRACE_DEBUG_REGSET'} = 'true';
|
|
||||||
|
|
||||||
if ($opt_g) {
|
if ($opt_g) {
|
||||||
$ENV{'UMEM_DEBUG'} = 'default,verbose';
|
$ENV{'UMEM_DEBUG'} = 'default,verbose';
|
||||||
$ENV{'UMEM_LOGGING'} = 'fail,contents';
|
$ENV{'UMEM_LOGGING'} = 'fail,contents';
|
||||||
|
@ -1,35 +0,0 @@
|
|||||||
/*
|
|
||||||
* CDDL HEADER START
|
|
||||||
*
|
|
||||||
* 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.
|
|
||||||
*
|
|
||||||
* CDDL HEADER END
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Copyright (c) 2012 by Delphix. All rights reserved.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma D option quiet
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Make sure the sizes of compatible keys doesn't affect the sort order.
|
|
||||||
*/
|
|
||||||
|
|
||||||
BEGIN
|
|
||||||
{
|
|
||||||
@[(int)1, 0] = sum(10);
|
|
||||||
@[(uint64_t)2, 0] = sum(20);
|
|
||||||
@[(int)3, 0] = sum(30);
|
|
||||||
@[(uint64_t)4, 0] = sum(40);
|
|
||||||
printa(@);
|
|
||||||
|
|
||||||
exit(0);
|
|
||||||
}
|
|
@ -1,6 +0,0 @@
|
|||||||
|
|
||||||
1 0 10
|
|
||||||
2 0 20
|
|
||||||
3 0 30
|
|
||||||
4 0 40
|
|
||||||
|
|
@ -1,8 +0,0 @@
|
|||||||
The value of i is 6
|
|
||||||
The value of i is 18
|
|
||||||
The value of i is 72
|
|
||||||
The value of i is 25920
|
|
||||||
The value of i is 935761216
|
|
||||||
The value of i is -91738734
|
|
||||||
The value of i is -91738729
|
|
||||||
|
|
@ -1,50 +0,0 @@
|
|||||||
/*
|
|
||||||
* CDDL HEADER START
|
|
||||||
*
|
|
||||||
* 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.
|
|
||||||
*
|
|
||||||
* CDDL HEADER END
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Copyright (c) 2012 by Delphix. All rights reserved.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Test compile-time casting between integer types of different size.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma D option quiet
|
|
||||||
|
|
||||||
int64_t x;
|
|
||||||
|
|
||||||
BEGIN
|
|
||||||
{
|
|
||||||
x = (int32_t)(int16_t)0xfff0;
|
|
||||||
printf("%16x %20d %20u\n", x, x, x);
|
|
||||||
x = (int32_t)(uint16_t)0xfff0;
|
|
||||||
printf("%16x %20d %20u\n", x, x, x);
|
|
||||||
x = (uint32_t)(int16_t)0xfff0;
|
|
||||||
printf("%16x %20d %20u\n", x, x, x);
|
|
||||||
x = (uint32_t)(uint16_t)0xfff0;
|
|
||||||
printf("%16x %20d %20u\n", x, x, x);
|
|
||||||
printf("\n");
|
|
||||||
|
|
||||||
x = (int16_t)(int32_t)0xfff0;
|
|
||||||
printf("%16x %20d %20u\n", x, x, x);
|
|
||||||
x = (int16_t)(uint32_t)0xfff0;
|
|
||||||
printf("%16x %20d %20u\n", x, x, x);
|
|
||||||
x = (uint16_t)(int32_t)0xfff0;
|
|
||||||
printf("%16x %20d %20u\n", x, x, x);
|
|
||||||
x = (uint16_t)(uint32_t)0xfff0;
|
|
||||||
printf("%16x %20d %20u\n", x, x, x);
|
|
||||||
|
|
||||||
exit(0);
|
|
||||||
}
|
|
@ -1,10 +0,0 @@
|
|||||||
fffffffffffffff0 -16 18446744073709551600
|
|
||||||
fff0 65520 65520
|
|
||||||
fffffff0 4294967280 4294967280
|
|
||||||
fff0 65520 65520
|
|
||||||
|
|
||||||
fffffffffffffff0 -16 18446744073709551600
|
|
||||||
fffffffffffffff0 -16 18446744073709551600
|
|
||||||
fff0 65520 65520
|
|
||||||
fff0 65520 65520
|
|
||||||
|
|
@ -0,0 +1,57 @@
|
|||||||
|
/*
|
||||||
|
* CDDL HEADER START
|
||||||
|
*
|
||||||
|
* The contents of this file are subject to the terms of the
|
||||||
|
* Common Development and Distribution License (the "License").
|
||||||
|
* You may not use this file except in compliance with the License.
|
||||||
|
*
|
||||||
|
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
|
||||||
|
* or http://www.opensolaris.org/os/licensing.
|
||||||
|
* See the License for the specific language governing permissions
|
||||||
|
* and limitations under the License.
|
||||||
|
*
|
||||||
|
* When distributing Covered Code, include this CDDL HEADER in each
|
||||||
|
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
|
||||||
|
* If applicable, add the following below this CDDL HEADER, with the
|
||||||
|
* fields enclosed by brackets "[]" replaced with your own identifying
|
||||||
|
* information: Portions Copyright [yyyy] [name of copyright owner]
|
||||||
|
*
|
||||||
|
* CDDL HEADER END
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright 2006 Sun Microsystems, Inc. All rights reserved.
|
||||||
|
* Use is subject to license terms.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma ident "%Z%%M% %I% %E% SMI"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* ASSERTION:
|
||||||
|
* Complex expressions.
|
||||||
|
* Call complex expressions and make sure test succeeds.
|
||||||
|
* Match expected output in tst.complex.d.out
|
||||||
|
*
|
||||||
|
* SECTION: Types, Operators, and Expressions/Arithmetic Operators
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma D option quiet
|
||||||
|
|
||||||
|
BEGIN
|
||||||
|
{
|
||||||
|
i = 0;
|
||||||
|
i = i++ + ++i;
|
||||||
|
printf("The value of i is %d\n", i);
|
||||||
|
i = i-- - --i;
|
||||||
|
printf("The value of i is %d\n", i);
|
||||||
|
i = i-- + ++i;
|
||||||
|
printf("The value of i is %d\n", i);
|
||||||
|
i += i++ + -- i + ++i - ++i * i ;
|
||||||
|
printf("The value of i is %d\n", i);
|
||||||
|
i -= i++ * 3;
|
||||||
|
printf("The value of i is %d\n", i);
|
||||||
|
i = i++/i--+i++-++i-++i;
|
||||||
|
printf("The value of i is %d\n", i);
|
||||||
|
exit (0);
|
||||||
|
}
|
@ -1,36 +0,0 @@
|
|||||||
/*
|
|
||||||
* CDDL HEADER START
|
|
||||||
*
|
|
||||||
* 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.
|
|
||||||
*
|
|
||||||
* CDDL HEADER END
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Copyright (c) 2012 by Delphix. All rights reserved.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Test narrowing at assignment.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma D option quiet
|
|
||||||
|
|
||||||
uint16_t x;
|
|
||||||
uint32_t y;
|
|
||||||
|
|
||||||
BEGIN
|
|
||||||
{
|
|
||||||
x = 0xbeefcafe;
|
|
||||||
y = x;
|
|
||||||
printf("%x", y); /* where's the beef? */
|
|
||||||
|
|
||||||
exit(0);
|
|
||||||
}
|
|
@ -1 +0,0 @@
|
|||||||
cafe
|
|
@ -1,52 +0,0 @@
|
|||||||
/*
|
|
||||||
* CDDL HEADER START
|
|
||||||
*
|
|
||||||
* 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.
|
|
||||||
*
|
|
||||||
* CDDL HEADER END
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Copyright (c) 2012 by Delphix. All rights reserved.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Test execution-time casting between integer types of different size.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma D option quiet
|
|
||||||
|
|
||||||
int64_t x;
|
|
||||||
|
|
||||||
BEGIN
|
|
||||||
{
|
|
||||||
z = 0xfff0;
|
|
||||||
|
|
||||||
x = (int32_t)(int16_t)z;
|
|
||||||
printf("%16x %20d %20u\n", x, x, x);
|
|
||||||
x = (int32_t)(uint16_t)z;
|
|
||||||
printf("%16x %20d %20u\n", x, x, x);
|
|
||||||
x = (uint32_t)(int16_t)z;
|
|
||||||
printf("%16x %20d %20u\n", x, x, x);
|
|
||||||
x = (uint32_t)(uint16_t)z;
|
|
||||||
printf("%16x %20d %20u\n", x, x, x);
|
|
||||||
printf("\n");
|
|
||||||
|
|
||||||
x = (int16_t)(int32_t)z;
|
|
||||||
printf("%16x %20d %20u\n", x, x, x);
|
|
||||||
x = (int16_t)(uint32_t)z;
|
|
||||||
printf("%16x %20d %20u\n", x, x, x);
|
|
||||||
x = (uint16_t)(int32_t)z;
|
|
||||||
printf("%16x %20d %20u\n", x, x, x);
|
|
||||||
x = (uint16_t)(uint32_t)z;
|
|
||||||
printf("%16x %20d %20u\n", x, x, x);
|
|
||||||
|
|
||||||
exit(0);
|
|
||||||
}
|
|
@ -1,10 +0,0 @@
|
|||||||
fffffffffffffff0 -16 18446744073709551600
|
|
||||||
fff0 65520 65520
|
|
||||||
fffffff0 4294967280 4294967280
|
|
||||||
fff0 65520 65520
|
|
||||||
|
|
||||||
fffffffffffffff0 -16 18446744073709551600
|
|
||||||
fffffffffffffff0 -16 18446744073709551600
|
|
||||||
fff0 65520 65520
|
|
||||||
fff0 65520 65520
|
|
||||||
|
|
@ -23,9 +23,8 @@
|
|||||||
* Copyright 2006 Sun Microsystems, Inc. All rights reserved.
|
* Copyright 2006 Sun Microsystems, Inc. All rights reserved.
|
||||||
* Use is subject to license terms.
|
* Use is subject to license terms.
|
||||||
*/
|
*/
|
||||||
/*
|
|
||||||
* Copyright (c) 2012 by Delphix. All rights reserved.
|
#pragma ident "%Z%%M% %I% %E% SMI"
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ASSERTION:
|
* ASSERTION:
|
||||||
@ -38,14 +37,12 @@
|
|||||||
* Options and Tunables/statusrate
|
* Options and Tunables/statusrate
|
||||||
*/
|
*/
|
||||||
/*
|
/*
|
||||||
* This is a brute-force way of testing fill buffers. We assume that
|
* This is a brute-force way of testing fill buffers. We assume that each
|
||||||
* each printf() stores 16 bytes (4x 32-bit words for EPID, timestamp
|
* printf() stores 8 bytes. Because each fill buffer is per-CPU, we must
|
||||||
* lo, timestamp hi, and the variable i). Because each fill buffer is
|
* fill up our buffer in one series of enablings on a single CPU.
|
||||||
* per-CPU, we must fill up our buffer in one series of enablings on a
|
|
||||||
* single CPU.
|
|
||||||
*/
|
*/
|
||||||
#pragma D option bufpolicy=fill
|
#pragma D option bufpolicy=fill
|
||||||
#pragma D option bufsize=128
|
#pragma D option bufsize=64
|
||||||
#pragma D option statusrate=10ms
|
#pragma D option statusrate=10ms
|
||||||
#pragma D option quiet
|
#pragma D option quiet
|
||||||
|
|
||||||
|
@ -23,9 +23,8 @@
|
|||||||
* Copyright 2006 Sun Microsystems, Inc. All rights reserved.
|
* Copyright 2006 Sun Microsystems, Inc. All rights reserved.
|
||||||
* Use is subject to license terms.
|
* Use is subject to license terms.
|
||||||
*/
|
*/
|
||||||
/*
|
|
||||||
* Copyright (c) 2012 by Delphix. All rights reserved.
|
#pragma ident "%Z%%M% %I% %E% SMI"
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ASSERTION:
|
* ASSERTION:
|
||||||
@ -38,20 +37,19 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We make some regrettable assumptions about the implementation in this
|
* We make some regrettable assumptions about the implementation in this test.
|
||||||
* test. First, we assume that each entry for the printf() of an int
|
* First, we assume that each entry for the printf() of an int takes _exactly_
|
||||||
* takes _exactly_ 16 bytes (4 bytes for the EPID, 8 bytes for the
|
* eight bytes (four bytes for the EPID, four bytes for the payload). Second,
|
||||||
* timestamp, 4 bytes for the payload). Second, we assume that by
|
* we assume that by allocating storage for n + 1 records, we will get exactly
|
||||||
* allocating storage for n + 1 records, we will get exactly n. Here is
|
* n. Here is why: the final predicate that evaluates to false will reserve
|
||||||
* why: the final predicate that evaluates to false will reserve space
|
* space that it won't use. This act of reservation will advance the wrapped
|
||||||
* that it won't use. This act of reservation will advance the wrapped
|
* offset. That record won't be subsequently used, but the wrapped offset has
|
||||||
* offset. That record won't be subsequently used, but the wrapped
|
* advanced. (And in this case, that old record is clobbered by the exit()
|
||||||
* offset has advanced. (And in this case, that old record is clobbered
|
* anyway.) Thirdly: we rely on t_cpu/cpu_id. Finally: we rely on being
|
||||||
* by the exit() anyway.) Thirdly: we rely on t_cpu/cpu_id. Finally:
|
* able to run on the CPU that we first ran on.
|
||||||
* we rely on being able to run on the CPU that we first ran on.
|
|
||||||
*/
|
*/
|
||||||
#pragma D option bufpolicy=ring
|
#pragma D option bufpolicy=ring
|
||||||
#pragma D option bufsize=80
|
#pragma D option bufsize=40
|
||||||
#pragma D option quiet
|
#pragma D option quiet
|
||||||
|
|
||||||
int n;
|
int n;
|
||||||
|
@ -1,41 +0,0 @@
|
|||||||
/*
|
|
||||||
* CDDL HEADER START
|
|
||||||
*
|
|
||||||
* 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.
|
|
||||||
*
|
|
||||||
* CDDL HEADER END
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Copyright (c) 2012 by Delphix. All rights reserved.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Compile some code that requires exactly 9 registers. This should run out
|
|
||||||
* of registers.
|
|
||||||
*
|
|
||||||
* Changes to the code generator might cause this test to succeeed in which
|
|
||||||
* case the code should be changed to another sequence that exhausts the
|
|
||||||
* available internal registers.
|
|
||||||
*
|
|
||||||
* Note that this and err.baddif.d should be kept in sync.
|
|
||||||
*/
|
|
||||||
|
|
||||||
BEGIN
|
|
||||||
{
|
|
||||||
a = 4;
|
|
||||||
trace((a + a) * ((a + a) * ((a + a) * ((a + a) * ((a + a) *
|
|
||||||
((a + a) * (a + a)))))));
|
|
||||||
}
|
|
||||||
|
|
||||||
BEGIN
|
|
||||||
{
|
|
||||||
exit(0);
|
|
||||||
}
|
|
@ -1,44 +0,0 @@
|
|||||||
/*
|
|
||||||
* CDDL HEADER START
|
|
||||||
*
|
|
||||||
* 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.
|
|
||||||
*
|
|
||||||
* CDDL HEADER END
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Copyright (c) 2012 by Delphix. All rights reserved.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Compile some code that requires exactly 9 registers. This should generate
|
|
||||||
* invalid DIF because the kernel will flag the fact that we're using more
|
|
||||||
* registers than are available internally.
|
|
||||||
*
|
|
||||||
* Changes to the code generator might cause this test to succeeed in which
|
|
||||||
* case the code should be changed to another sequence that exhausts the
|
|
||||||
* available internal registers.
|
|
||||||
*
|
|
||||||
* Note that this and err.D_NOREG.noreg.d should be kept in sync.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma D option iregs=9
|
|
||||||
|
|
||||||
BEGIN
|
|
||||||
{
|
|
||||||
a = 4;
|
|
||||||
trace((a + a) * ((a + a) * ((a + a) * ((a + a) * ((a + a) *
|
|
||||||
((a + a) * (a + a)))))));
|
|
||||||
}
|
|
||||||
|
|
||||||
BEGIN
|
|
||||||
{
|
|
||||||
exit(0);
|
|
||||||
}
|
|
@ -24,9 +24,7 @@
|
|||||||
# Copyright 2008 Sun Microsystems, Inc. All rights reserved.
|
# Copyright 2008 Sun Microsystems, Inc. All rights reserved.
|
||||||
# Use is subject to license terms.
|
# Use is subject to license terms.
|
||||||
#
|
#
|
||||||
|
# ident "%Z%%M% %I% %E% SMI"
|
||||||
#
|
|
||||||
# Copyright (c) 2012 by Delphix. All rights reserved.
|
|
||||||
#
|
#
|
||||||
|
|
||||||
if [ $# != 1 ]; then
|
if [ $# != 1 ]; then
|
||||||
@ -51,13 +49,13 @@ tick-1s
|
|||||||
tick-1s
|
tick-1s
|
||||||
/(i % 2) == 0/
|
/(i % 2) == 0/
|
||||||
{
|
{
|
||||||
system("dtrace -c date -n 'pid\$target::main:entry' >/dev/null");
|
system("dtrace -c date -ln 'pid\$target::main:entry' >/dev/null");
|
||||||
}
|
}
|
||||||
|
|
||||||
tick-1s
|
tick-1s
|
||||||
/(i % 2) == 1/
|
/(i % 2) == 1/
|
||||||
{
|
{
|
||||||
system("dtrace -c date -n 'pid\$target::main:return' >/dev/null");
|
system("dtrace -c date -ln 'pid\$target::main:return' >/dev/null");
|
||||||
}
|
}
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
|
@ -1,28 +0,0 @@
|
|||||||
/*
|
|
||||||
* CDDL HEADER START
|
|
||||||
*
|
|
||||||
* 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.
|
|
||||||
*
|
|
||||||
* CDDL HEADER END
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Copyright (c) 2012 by Delphix. All rights reserved.
|
|
||||||
*/
|
|
||||||
|
|
||||||
BEGIN
|
|
||||||
{
|
|
||||||
*((int *)alloca(4)) = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
BEGIN
|
|
||||||
{
|
|
||||||
exit(0);
|
|
||||||
}
|
|
@ -1,29 +0,0 @@
|
|||||||
/*
|
|
||||||
* CDDL HEADER START
|
|
||||||
*
|
|
||||||
* 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.
|
|
||||||
*
|
|
||||||
* CDDL HEADER END
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Copyright (c) 2012 by Delphix. All rights reserved.
|
|
||||||
*/
|
|
||||||
|
|
||||||
BEGIN
|
|
||||||
{
|
|
||||||
this->a = alloca(4);
|
|
||||||
*((int *)this->a) = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
BEGIN
|
|
||||||
{
|
|
||||||
exit(0);
|
|
||||||
}
|
|
@ -1,106 +0,0 @@
|
|||||||
#!/bin/ksh -p
|
|
||||||
#
|
|
||||||
# CDDL HEADER START
|
|
||||||
#
|
|
||||||
# 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.
|
|
||||||
#
|
|
||||||
# CDDL HEADER END
|
|
||||||
#
|
|
||||||
|
|
||||||
#
|
|
||||||
# Copyright (c) 2012 by Delphix. All rights reserved.
|
|
||||||
#
|
|
||||||
|
|
||||||
############################################################################
|
|
||||||
# ASSERTION:
|
|
||||||
# temporal option causes output to be sorted
|
|
||||||
#
|
|
||||||
# SECTION: Pragma
|
|
||||||
#
|
|
||||||
# NOTES: The temporal option has no effect on a single-CPU system, so
|
|
||||||
# this needs to be run on a multi-CPU system to effectively test the
|
|
||||||
# temporal option.
|
|
||||||
#
|
|
||||||
############################################################################
|
|
||||||
|
|
||||||
if [ $# != 1 ]; then
|
|
||||||
echo expected one argument: '<'dtrace-path'>'
|
|
||||||
exit 2
|
|
||||||
fi
|
|
||||||
|
|
||||||
dtrace=$1
|
|
||||||
file=/tmp/out.$$
|
|
||||||
|
|
||||||
rm -f $file
|
|
||||||
|
|
||||||
$dtrace -o $file -c 'sleep 3' -s /dev/stdin <<EOF
|
|
||||||
#pragma D option quiet
|
|
||||||
#pragma D option temporal
|
|
||||||
|
|
||||||
BEGIN
|
|
||||||
{
|
|
||||||
@lines = count();
|
|
||||||
printf("0 begin\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
END
|
|
||||||
{
|
|
||||||
/* Bump @lines every time we print a line. */
|
|
||||||
@lines = count();
|
|
||||||
printf("%u end\n", timestamp);
|
|
||||||
@lines = count();
|
|
||||||
printa("99999999999999999 lines %@u\n", @lines);
|
|
||||||
}
|
|
||||||
|
|
||||||
profile-97hz
|
|
||||||
{
|
|
||||||
@lines = count();
|
|
||||||
printf("%u\n", timestamp);
|
|
||||||
}
|
|
||||||
EOF
|
|
||||||
|
|
||||||
status=$?
|
|
||||||
if [ "$status" -ne 0 ]; then
|
|
||||||
echo $tst: dtrace failed
|
|
||||||
exit $status
|
|
||||||
fi
|
|
||||||
|
|
||||||
# dtrace outputs a blank line at the end, which will sort to the beginning,
|
|
||||||
# so use head to remove the blank line.
|
|
||||||
head -n -1 $file > $file.2
|
|
||||||
|
|
||||||
sort -n $file.2 | diff $file.2 -
|
|
||||||
status=$?
|
|
||||||
if [ "$status" -ne 0 ]; then
|
|
||||||
echo $tst: output is not sorted
|
|
||||||
exit $status
|
|
||||||
fi
|
|
||||||
|
|
||||||
head -n 1 $file.2 | grep begin >/dev/null
|
|
||||||
status=$?
|
|
||||||
if [ "$status" -ne 0 ]; then
|
|
||||||
echo $tst: begin probe did not fire
|
|
||||||
exit $status
|
|
||||||
fi
|
|
||||||
|
|
||||||
tail -n 2 $file.2 | grep end >/dev/null
|
|
||||||
status=$?
|
|
||||||
if [ "$status" -ne 0 ]; then
|
|
||||||
echo $tst: end probe did not fire
|
|
||||||
exit $status
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ $(tail -n 1 $file.2 | cut -f3 -d ' ') -ne \
|
|
||||||
$(wc -l $file.2) ]; then
|
|
||||||
echo $tst: incorrect number of lines output
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
exit $status
|
|
@ -1,102 +0,0 @@
|
|||||||
#!/bin/ksh -p
|
|
||||||
#
|
|
||||||
# CDDL HEADER START
|
|
||||||
#
|
|
||||||
# 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.
|
|
||||||
#
|
|
||||||
# CDDL HEADER END
|
|
||||||
#
|
|
||||||
|
|
||||||
#
|
|
||||||
# Copyright (c) 2012 by Delphix. All rights reserved.
|
|
||||||
#
|
|
||||||
|
|
||||||
############################################################################
|
|
||||||
# ASSERTION:
|
|
||||||
# temporal option causes output to be sorted, even when some
|
|
||||||
# buffers are empty
|
|
||||||
#
|
|
||||||
# SECTION: Pragma
|
|
||||||
#
|
|
||||||
# NOTES: The temporal option has no effect on a single-CPU system, so
|
|
||||||
# this needs to be run on a multi-CPU system to effectively test the
|
|
||||||
# temporal option.
|
|
||||||
#
|
|
||||||
############################################################################
|
|
||||||
|
|
||||||
if [ $# != 1 ]; then
|
|
||||||
echo expected one argument: '<'dtrace-path'>'
|
|
||||||
exit 2
|
|
||||||
fi
|
|
||||||
|
|
||||||
dtrace=$1
|
|
||||||
file=/tmp/out.$$
|
|
||||||
|
|
||||||
rm -f $file
|
|
||||||
|
|
||||||
$dtrace -o $file -s /dev/stdin <<EOF
|
|
||||||
#pragma D option quiet
|
|
||||||
#pragma D option destructive
|
|
||||||
#pragma D option temporal
|
|
||||||
#pragma D option switchrate=1000hz
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Use two enablings of the same probe, so that cpu 0 will always
|
|
||||||
* record its data just a little bit before the other cpus.
|
|
||||||
* We don't want to use the chill() action in the same enabling
|
|
||||||
* that we record the timestamp, because chill() causes the
|
|
||||||
* timestamp to be re-read, and thus not match the timestamp
|
|
||||||
* which libdtrace uses to sort the records.
|
|
||||||
*/
|
|
||||||
|
|
||||||
profile-401
|
|
||||||
/cpu == 0/
|
|
||||||
{
|
|
||||||
printf("%d\n", timestamp);
|
|
||||||
}
|
|
||||||
|
|
||||||
profile-401
|
|
||||||
/cpu != 0/
|
|
||||||
{
|
|
||||||
chill(1000); /* one microsecond */
|
|
||||||
}
|
|
||||||
|
|
||||||
profile-401
|
|
||||||
/cpu != 0/
|
|
||||||
{
|
|
||||||
printf("%d\n", timestamp);
|
|
||||||
}
|
|
||||||
|
|
||||||
tick-1s
|
|
||||||
/k++ == 10/
|
|
||||||
{
|
|
||||||
printf("%d\n", timestamp);
|
|
||||||
exit(0);
|
|
||||||
}
|
|
||||||
EOF
|
|
||||||
|
|
||||||
status=$?
|
|
||||||
if [ "$status" -ne 0 ]; then
|
|
||||||
echo $tst: dtrace failed
|
|
||||||
exit $status
|
|
||||||
fi
|
|
||||||
|
|
||||||
# dtrace outputs a blank line at the end, which will sort to the beginning,
|
|
||||||
# so use grep to remove the blank line.
|
|
||||||
head -n -1 $file > $file.2
|
|
||||||
|
|
||||||
sort -n $file.2 | diff $file.2 -
|
|
||||||
status=$?
|
|
||||||
if [ "$status" -ne 0 ]; then
|
|
||||||
echo $tst: output is not sorted
|
|
||||||
exit $status
|
|
||||||
fi
|
|
||||||
|
|
||||||
exit $status
|
|
@ -1,48 +0,0 @@
|
|||||||
/*
|
|
||||||
* CDDL HEADER START
|
|
||||||
*
|
|
||||||
* 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.
|
|
||||||
*
|
|
||||||
* CDDL HEADER END
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Copyright (c) 2012 by Delphix. All rights reserved.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* This test excercises the "remnant" handling of the temporal option.
|
|
||||||
* At the end of one pass of retrieving and printing data from all CPUs,
|
|
||||||
* some unprocessed data will remain, because its timestamp is after the
|
|
||||||
* time covered by all CPUs' buffers. This unprocessed data is
|
|
||||||
* rearranged in a more space-efficient manner. If this is done
|
|
||||||
* incorrectly, an alignment error may occur. To test this, we use a
|
|
||||||
* high-frequency probe so that data will be recorded in subsequent
|
|
||||||
* CPU's buffers after the first CPU's buffer is obtained. The
|
|
||||||
* combination of data traced here (a 8-byte value and a 4-byte value)
|
|
||||||
* is effective to cause alignment problems with an incorrect
|
|
||||||
* implementation.
|
|
||||||
*
|
|
||||||
* This test needs to be run on a multi-CPU system to be effective.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma D option quiet
|
|
||||||
#pragma D option temporal
|
|
||||||
|
|
||||||
profile-4997
|
|
||||||
{
|
|
||||||
printf("%u %u", 1ULL, 2);
|
|
||||||
}
|
|
||||||
|
|
||||||
tick-1
|
|
||||||
/i++ == 10/
|
|
||||||
{
|
|
||||||
exit(0);
|
|
||||||
}
|
|
@ -0,0 +1,197 @@
|
|||||||
|
#
|
||||||
|
# CDDL HEADER START
|
||||||
|
#
|
||||||
|
# The contents of this file are subject to the terms of the
|
||||||
|
# Common Development and Distribution License (the "License").
|
||||||
|
# You may not use this file except in compliance with the License.
|
||||||
|
#
|
||||||
|
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
|
||||||
|
# or http://www.opensolaris.org/os/licensing.
|
||||||
|
# See the License for the specific language governing permissions
|
||||||
|
# and limitations under the License.
|
||||||
|
#
|
||||||
|
# When distributing Covered Code, include this CDDL HEADER in each
|
||||||
|
# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
|
||||||
|
# If applicable, add the following below this CDDL HEADER, with the
|
||||||
|
# fields enclosed by brackets "[]" replaced with your own identifying
|
||||||
|
# information: Portions Copyright [yyyy] [name of copyright owner]
|
||||||
|
#
|
||||||
|
# CDDL HEADER END
|
||||||
|
#
|
||||||
|
|
||||||
|
#
|
||||||
|
# Copyright 2007 Sun Microsystems, Inc. All rights reserved.
|
||||||
|
# Use is subject to license terms.
|
||||||
|
#
|
||||||
|
# ident "%Z%%M% %I% %E% SMI"
|
||||||
|
|
||||||
|
unload()
|
||||||
|
{
|
||||||
|
#
|
||||||
|
# Get the list of services whose processes have USDT probes. Ideally
|
||||||
|
# it would be possible to unload the fasttrap provider while USDT
|
||||||
|
# probes exist -- once that fix is integrated, this hack can go away
|
||||||
|
# We create two lists -- one of regular SMF services and one of legacy
|
||||||
|
# services -- since each must be enabled and disabled using a specific
|
||||||
|
# mechanism.
|
||||||
|
#
|
||||||
|
pids=$(dtrace -l | \
|
||||||
|
perl -ne 'print "$1\n" if (/^\s*\S+\s+\S*\D(\d+)\s+/);' | \
|
||||||
|
sort | uniq | tr '\n' ',')
|
||||||
|
|
||||||
|
ctids=$(ps -p $pids -o ctid | tail +2 | sort | uniq)
|
||||||
|
svcs=
|
||||||
|
lrcs=
|
||||||
|
|
||||||
|
for ct in $ctids
|
||||||
|
do
|
||||||
|
line=$(svcs -o fmri,ctid | grep " $ct\$")
|
||||||
|
svc=$(echo $line | cut -d' ' -f1)
|
||||||
|
|
||||||
|
if [[ $(svcs -Ho STA $svc) == "LRC" ]]; then
|
||||||
|
lrc=$(svcs -Ho SVC $svc | tr _ '?')
|
||||||
|
lrcs="$lrcs $lrc"
|
||||||
|
else
|
||||||
|
svcs="$svcs $svc"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
for svc in $svcs
|
||||||
|
do
|
||||||
|
svcadm disable -ts $svc
|
||||||
|
done
|
||||||
|
|
||||||
|
for lrc in $lrcs
|
||||||
|
do
|
||||||
|
#
|
||||||
|
# Does it seem a little paternalistic that lsvcrun requires
|
||||||
|
# this environment variable to be set? I'd say so...
|
||||||
|
#
|
||||||
|
SMF_RESTARTER=svc:/system/svc/restarter:default \
|
||||||
|
/lib/svc/bin/lsvcrun $lrc stop
|
||||||
|
done
|
||||||
|
|
||||||
|
modunload -i 0
|
||||||
|
modunload -i 0
|
||||||
|
modunload -i 0
|
||||||
|
modinfo | grep dtrace
|
||||||
|
success=$?
|
||||||
|
|
||||||
|
for svc in $svcs
|
||||||
|
do
|
||||||
|
svcadm enable -ts $svc
|
||||||
|
done
|
||||||
|
|
||||||
|
for lrc in $lrcs
|
||||||
|
do
|
||||||
|
SMF_RESTARTER=svc:/system/svc/restarter:default \
|
||||||
|
/lib/svc/bin/lsvcrun $lrc start
|
||||||
|
done
|
||||||
|
|
||||||
|
if [ ! $success ]; then
|
||||||
|
echo $tst: could not unload dtrace
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
script1()
|
||||||
|
{
|
||||||
|
$dtrace -s /dev/stdin <<EOF
|
||||||
|
syscall:::entry
|
||||||
|
/pid != $ppid/
|
||||||
|
{
|
||||||
|
@a[probefunc] = count();
|
||||||
|
}
|
||||||
|
|
||||||
|
tick-1sec
|
||||||
|
/i++ == 5/
|
||||||
|
{
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
EOF
|
||||||
|
}
|
||||||
|
|
||||||
|
script2()
|
||||||
|
{
|
||||||
|
$dtrace -s /dev/stdin <<EOF
|
||||||
|
|
||||||
|
#pragma D option statusrate=1ms
|
||||||
|
|
||||||
|
syscall:::entry
|
||||||
|
/pid == $ppid/
|
||||||
|
{
|
||||||
|
ttl++;
|
||||||
|
}
|
||||||
|
|
||||||
|
tick-1sec
|
||||||
|
/i++ == 5/
|
||||||
|
{
|
||||||
|
exit(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
END
|
||||||
|
/ttl/
|
||||||
|
{
|
||||||
|
printf("success; ttl is %d", ttl);
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
END
|
||||||
|
/ttl == 0/
|
||||||
|
{
|
||||||
|
printf("error -- total should be non-zero");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
EOF
|
||||||
|
}
|
||||||
|
|
||||||
|
if [ $# != 1 ]; then
|
||||||
|
echo expected one argument: '<'dtrace-path'>'
|
||||||
|
exit 2
|
||||||
|
fi
|
||||||
|
|
||||||
|
ppid=$$
|
||||||
|
dtrace=$1
|
||||||
|
|
||||||
|
unload
|
||||||
|
script1 &
|
||||||
|
child=$!
|
||||||
|
|
||||||
|
let waited=0
|
||||||
|
|
||||||
|
while [ "$waited" -lt 5 ]; do
|
||||||
|
seconds=`date +%S`
|
||||||
|
|
||||||
|
if [ "$seconds" -ne "$last" ]; then
|
||||||
|
last=$seconds
|
||||||
|
let waited=waited+1
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
wait $child
|
||||||
|
status=$?
|
||||||
|
|
||||||
|
if [ "$status" -ne 0 ]; then
|
||||||
|
echo $tst: first dtrace failed
|
||||||
|
exit $status
|
||||||
|
fi
|
||||||
|
|
||||||
|
unload
|
||||||
|
script2 &
|
||||||
|
child=$!
|
||||||
|
|
||||||
|
let waited=0
|
||||||
|
|
||||||
|
while [ "$waited" -lt 10 ]; do
|
||||||
|
seconds=`date +%S`
|
||||||
|
|
||||||
|
if [ "$seconds" -ne "$last" ]; then
|
||||||
|
last=$seconds
|
||||||
|
let waited=waited+1
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
wait $child
|
||||||
|
status=$?
|
||||||
|
|
||||||
|
exit $status
|
@ -0,0 +1,29 @@
|
|||||||
|
/*
|
||||||
|
* CDDL HEADER START
|
||||||
|
*
|
||||||
|
* The contents of this file are subject to the terms of the
|
||||||
|
* Common Development and Distribution License (the "License").
|
||||||
|
* You may not use this file except in compliance with the License.
|
||||||
|
*
|
||||||
|
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
|
||||||
|
* or http://www.opensolaris.org/os/licensing.
|
||||||
|
* See the License for the specific language governing permissions
|
||||||
|
* and limitations under the License.
|
||||||
|
*
|
||||||
|
* When distributing Covered Code, include this CDDL HEADER in each
|
||||||
|
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
|
||||||
|
* If applicable, add the following below this CDDL HEADER, with the
|
||||||
|
* fields enclosed by brackets "[]" replaced with your own identifying
|
||||||
|
* information: Portions Copyright [yyyy] [name of copyright owner]
|
||||||
|
*
|
||||||
|
* CDDL HEADER END
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2011 by Delphix. All rights reserved.
|
||||||
|
*/
|
||||||
|
|
||||||
|
BEGIN
|
||||||
|
{
|
||||||
|
print(*curpsinfo);
|
||||||
|
}
|
@ -1,28 +0,0 @@
|
|||||||
/*
|
|
||||||
* CDDL HEADER START
|
|
||||||
*
|
|
||||||
* 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.
|
|
||||||
*
|
|
||||||
* CDDL HEADER END
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Copyright (c) 2012 by Delphix. All rights reserved.
|
|
||||||
*/
|
|
||||||
|
|
||||||
BEGIN
|
|
||||||
{
|
|
||||||
print(*curpsinfo);
|
|
||||||
}
|
|
||||||
|
|
||||||
BEGIN
|
|
||||||
{
|
|
||||||
exit(0);
|
|
||||||
}
|
|
@ -1,42 +0,0 @@
|
|||||||
/*
|
|
||||||
* CDDL HEADER START
|
|
||||||
*
|
|
||||||
* 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.
|
|
||||||
*
|
|
||||||
* CDDL HEADER END
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Copyright (c) 2012 by Delphix. All rights reserved.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma D option quiet
|
|
||||||
|
|
||||||
typedef struct pancakes {
|
|
||||||
int i;
|
|
||||||
string s;
|
|
||||||
timespec_t t;
|
|
||||||
} pancakes_t;
|
|
||||||
|
|
||||||
translator pancakes_t < void *V > {
|
|
||||||
i = 2 * 10;
|
|
||||||
s = strjoin("I like ", "pancakes");
|
|
||||||
t = *(timespec_t *)`dtrace_zero;
|
|
||||||
};
|
|
||||||
|
|
||||||
BEGIN
|
|
||||||
{
|
|
||||||
print(*(xlate < pancakes_t * > ((void *)NULL)));
|
|
||||||
}
|
|
||||||
|
|
||||||
BEGIN
|
|
||||||
{
|
|
||||||
exit(0);
|
|
||||||
}
|
|
@ -1,8 +0,0 @@
|
|||||||
pancakes_t {
|
|
||||||
int i = 0x14
|
|
||||||
string s = [ "I like pancakes" ]
|
|
||||||
timespec_t t = {
|
|
||||||
time_t tv_sec = 0
|
|
||||||
long tv_nsec = 0
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,6 +1,6 @@
|
|||||||
|
|
||||||
-17
|
239
|
||||||
-12817
|
52719
|
||||||
-1867788817
|
-1867788817
|
||||||
1311768467294899695
|
1311768467294899695
|
||||||
|
|
||||||
|
@ -1,38 +0,0 @@
|
|||||||
/*
|
|
||||||
* CDDL HEADER START
|
|
||||||
*
|
|
||||||
* 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.
|
|
||||||
*
|
|
||||||
* CDDL HEADER END
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Copyright (c) 2012 by Delphix. All rights reserved.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Check %d v. %i v. %u.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma D option quiet
|
|
||||||
|
|
||||||
uint16_t x;
|
|
||||||
int16_t y;
|
|
||||||
|
|
||||||
BEGIN
|
|
||||||
{
|
|
||||||
x = 0xffffffff;
|
|
||||||
y = 0xffffffff;
|
|
||||||
|
|
||||||
printf("%d %i %u\n", x, x, x);
|
|
||||||
printf("%d %i %u\n", y, y, y);
|
|
||||||
|
|
||||||
exit(0);
|
|
||||||
}
|
|
@ -1,3 +0,0 @@
|
|||||||
65535 -1 65535
|
|
||||||
-1 -1 65535
|
|
||||||
|
|
@ -24,10 +24,7 @@
|
|||||||
* Use is subject to license terms.
|
* Use is subject to license terms.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
#pragma ident "%Z%%M% %I% %E% SMI"
|
||||||
* Copyright (c) 2012 by Delphix. All rights reserved.
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ASSERTION:
|
* ASSERTION:
|
||||||
@ -38,10 +35,17 @@
|
|||||||
*
|
*
|
||||||
* NOTES: This test behaves differently depending on the values
|
* NOTES: This test behaves differently depending on the values
|
||||||
* assigned to bufsize.
|
* assigned to bufsize.
|
||||||
|
* 1. 0 > bufsize.
|
||||||
|
* 2. 0 == bufsize.
|
||||||
|
* 3. 0 < bufsize <= 7
|
||||||
|
* 4. 8 <= bufsize <= 31
|
||||||
|
* 5. 32 <= bufsize <= 47
|
||||||
|
* 6. 48 <= bufsize <= 71
|
||||||
|
* 7. 72 <= bufsize
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#pragma D option quiet
|
#pragma D option quiet
|
||||||
#pragma D option bufsize=49
|
#pragma D option bufsize=41
|
||||||
|
|
||||||
BEGIN
|
BEGIN
|
||||||
{
|
{
|
||||||
|
@ -24,10 +24,7 @@
|
|||||||
* Use is subject to license terms.
|
* Use is subject to license terms.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
#pragma ident "%Z%%M% %I% %E% SMI"
|
||||||
* Copyright (c) 2012 by Delphix. All rights reserved.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ASSERTION:
|
* ASSERTION:
|
||||||
* Verify the behavior of speculations with changes in specsize.
|
* Verify the behavior of speculations with changes in specsize.
|
||||||
@ -38,7 +35,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#pragma D option quiet
|
#pragma D option quiet
|
||||||
#pragma D option specsize=48
|
#pragma D option specsize=40
|
||||||
|
|
||||||
BEGIN
|
BEGIN
|
||||||
{
|
{
|
||||||
|
@ -1,28 +0,0 @@
|
|||||||
/*
|
|
||||||
* CDDL HEADER START
|
|
||||||
*
|
|
||||||
* 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.
|
|
||||||
*
|
|
||||||
* CDDL HEADER END
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Copyright (c) 2012 by Delphix. All rights reserved.
|
|
||||||
*/
|
|
||||||
|
|
||||||
BEGIN
|
|
||||||
{
|
|
||||||
trace(*curpsinfo);
|
|
||||||
}
|
|
||||||
|
|
||||||
BEGIN
|
|
||||||
{
|
|
||||||
exit(0);
|
|
||||||
}
|
|
@ -0,0 +1,61 @@
|
|||||||
|
/*
|
||||||
|
* CDDL HEADER START
|
||||||
|
*
|
||||||
|
* The contents of this file are subject to the terms of the
|
||||||
|
* Common Development and Distribution License (the "License").
|
||||||
|
* You may not use this file except in compliance with the License.
|
||||||
|
*
|
||||||
|
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
|
||||||
|
* or http://www.opensolaris.org/os/licensing.
|
||||||
|
* See the License for the specific language governing permissions
|
||||||
|
* and limitations under the License.
|
||||||
|
*
|
||||||
|
* When distributing Covered Code, include this CDDL HEADER in each
|
||||||
|
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
|
||||||
|
* If applicable, add the following below this CDDL HEADER, with the
|
||||||
|
* fields enclosed by brackets "[]" replaced with your own identifying
|
||||||
|
* information: Portions Copyright [yyyy] [name of copyright owner]
|
||||||
|
*
|
||||||
|
* CDDL HEADER END
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright 2006 Sun Microsystems, Inc. All rights reserved.
|
||||||
|
* Use is subject to license terms.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma ident "%Z%%M% %I% %E% SMI"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* ASSERTION:
|
||||||
|
* The D inline translation mechanism can be used to facilitate stable
|
||||||
|
* translations.
|
||||||
|
*
|
||||||
|
* SECTION: Translators/ Translator Declarations
|
||||||
|
* SECTION: Translators/ Translate Operator
|
||||||
|
* SECTION: Translators/Stable Translations
|
||||||
|
*
|
||||||
|
* NOTES: Uncomment the pragma that explicitly resets the attributes of
|
||||||
|
* myinfo identifier to Stable/Stable/Common from Private/Private/Unknown.
|
||||||
|
* Run the program with and without the comments as:
|
||||||
|
* /usr/sbin/dtrace -vs man.TestTransStability.d
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma D option quiet
|
||||||
|
|
||||||
|
inline lwpsinfo_t *myinfo = xlate < lwpsinfo_t *> (curthread);
|
||||||
|
|
||||||
|
/*
|
||||||
|
#pragma D attributes Stable/Stable/Common myinfo
|
||||||
|
*/
|
||||||
|
|
||||||
|
BEGIN
|
||||||
|
{
|
||||||
|
trace(myinfo->pr_flag);
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
ERROR
|
||||||
|
{
|
||||||
|
exit(1);
|
||||||
|
}
|
@ -1,62 +0,0 @@
|
|||||||
#
|
|
||||||
# CDDL HEADER START
|
|
||||||
#
|
|
||||||
# The contents of this file are subject to the terms of the
|
|
||||||
# Common Development and Distribution License (the "License").
|
|
||||||
# You may not use this file except in compliance with the License.
|
|
||||||
#
|
|
||||||
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
|
|
||||||
# or http://www.opensolaris.org/os/licensing.
|
|
||||||
# See the License for the specific language governing permissions
|
|
||||||
# and limitations under the License.
|
|
||||||
#
|
|
||||||
# When distributing Covered Code, include this CDDL HEADER in each
|
|
||||||
# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
|
|
||||||
# If applicable, add the following below this CDDL HEADER, with the
|
|
||||||
# fields enclosed by brackets "[]" replaced with your own identifying
|
|
||||||
# information: Portions Copyright [yyyy] [name of copyright owner]
|
|
||||||
#
|
|
||||||
# CDDL HEADER END
|
|
||||||
#
|
|
||||||
|
|
||||||
#
|
|
||||||
# Copyright 2006 Sun Microsystems, Inc. All rights reserved.
|
|
||||||
# Use is subject to license terms.
|
|
||||||
#
|
|
||||||
|
|
||||||
#
|
|
||||||
# Copyright (c) 2012 by Delphix. All rights reserved.
|
|
||||||
#
|
|
||||||
|
|
||||||
#
|
|
||||||
# Test the output for stable translations.
|
|
||||||
#
|
|
||||||
|
|
||||||
if [ $# != 1 ]; then
|
|
||||||
echo expected one argument: '<'dtrace-path'>'
|
|
||||||
exit 2
|
|
||||||
fi
|
|
||||||
|
|
||||||
dtrace=$1
|
|
||||||
|
|
||||||
$dtrace -v -s /dev/stdin <<EOF
|
|
||||||
|
|
||||||
#pragma D option quiet
|
|
||||||
|
|
||||||
inline lwpsinfo_t *myinfo = xlate < lwpsinfo_t *> (curthread);
|
|
||||||
|
|
||||||
#pragma D attributes Stable/Stable/Common myinfo
|
|
||||||
|
|
||||||
BEGIN
|
|
||||||
{
|
|
||||||
this->a = myinfo->pr_flag;
|
|
||||||
exit(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
BEGIN
|
|
||||||
{
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
EOF
|
|
||||||
|
|
||||||
exit $?
|
|
@ -1,14 +0,0 @@
|
|||||||
|
|
||||||
Stability attributes for script /dev/stdin:
|
|
||||||
|
|
||||||
Minimum Probe Description Attributes
|
|
||||||
Identifier Names: Unstable
|
|
||||||
Data Semantics: Unstable
|
|
||||||
Dependency Class: Common
|
|
||||||
|
|
||||||
Minimum Statement Attributes
|
|
||||||
Identifier Names: Stable
|
|
||||||
Data Semantics: Stable
|
|
||||||
Dependency Class: Common
|
|
||||||
|
|
||||||
|
|
@ -1,60 +0,0 @@
|
|||||||
#
|
|
||||||
# CDDL HEADER START
|
|
||||||
#
|
|
||||||
# The contents of this file are subject to the terms of the
|
|
||||||
# Common Development and Distribution License (the "License").
|
|
||||||
# You may not use this file except in compliance with the License.
|
|
||||||
#
|
|
||||||
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
|
|
||||||
# or http://www.opensolaris.org/os/licensing.
|
|
||||||
# See the License for the specific language governing permissions
|
|
||||||
# and limitations under the License.
|
|
||||||
#
|
|
||||||
# When distributing Covered Code, include this CDDL HEADER in each
|
|
||||||
# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
|
|
||||||
# If applicable, add the following below this CDDL HEADER, with the
|
|
||||||
# fields enclosed by brackets "[]" replaced with your own identifying
|
|
||||||
# information: Portions Copyright [yyyy] [name of copyright owner]
|
|
||||||
#
|
|
||||||
# CDDL HEADER END
|
|
||||||
#
|
|
||||||
|
|
||||||
#
|
|
||||||
# Copyright 2006 Sun Microsystems, Inc. All rights reserved.
|
|
||||||
# Use is subject to license terms.
|
|
||||||
#
|
|
||||||
|
|
||||||
#
|
|
||||||
# Copyright (c) 2012 by Delphix. All rights reserved.
|
|
||||||
#
|
|
||||||
|
|
||||||
#
|
|
||||||
# Test the output of unstable translations.
|
|
||||||
#
|
|
||||||
|
|
||||||
if [ $# != 1 ]; then
|
|
||||||
echo expected one argument: '<'dtrace-path'>'
|
|
||||||
exit 2
|
|
||||||
fi
|
|
||||||
|
|
||||||
dtrace=$1
|
|
||||||
|
|
||||||
$dtrace -v -s /dev/stdin <<EOF
|
|
||||||
|
|
||||||
#pragma D option quiet
|
|
||||||
|
|
||||||
inline lwpsinfo_t *myinfo = xlate < lwpsinfo_t *> (curthread);
|
|
||||||
|
|
||||||
BEGIN
|
|
||||||
{
|
|
||||||
this->a = myinfo->pr_flag;
|
|
||||||
exit(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
BEGIN
|
|
||||||
{
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
EOF
|
|
||||||
|
|
||||||
exit $?
|
|
@ -1,14 +0,0 @@
|
|||||||
|
|
||||||
Stability attributes for script /dev/stdin:
|
|
||||||
|
|
||||||
Minimum Probe Description Attributes
|
|
||||||
Identifier Names: Unstable
|
|
||||||
Data Semantics: Unstable
|
|
||||||
Dependency Class: Common
|
|
||||||
|
|
||||||
Minimum Statement Attributes
|
|
||||||
Identifier Names: Private
|
|
||||||
Data Semantics: Private
|
|
||||||
Dependency Class: Unknown
|
|
||||||
|
|
||||||
|
|
@ -26,7 +26,6 @@
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2011, Joyent, Inc. All rights reserved.
|
* Copyright (c) 2011, Joyent, Inc. All rights reserved.
|
||||||
* Copyright (c) 2012 by Delphix. All rights reserved.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
@ -895,14 +894,33 @@ dt_aggregate_valcmp(const void *lhs, const void *rhs)
|
|||||||
caddr_t rdata = rh->dtahe_data.dtada_data;
|
caddr_t rdata = rh->dtahe_data.dtada_data;
|
||||||
dtrace_recdesc_t *lrec, *rrec;
|
dtrace_recdesc_t *lrec, *rrec;
|
||||||
int64_t *laddr, *raddr;
|
int64_t *laddr, *raddr;
|
||||||
int rval;
|
int rval, i;
|
||||||
|
|
||||||
assert(lagg->dtagd_nrecs == ragg->dtagd_nrecs);
|
if ((rval = dt_aggregate_hashcmp(lhs, rhs)) != 0)
|
||||||
|
return (rval);
|
||||||
|
|
||||||
lrec = &lagg->dtagd_rec[lagg->dtagd_nrecs - 1];
|
if (lagg->dtagd_nrecs > ragg->dtagd_nrecs)
|
||||||
rrec = &ragg->dtagd_rec[ragg->dtagd_nrecs - 1];
|
return (DT_GREATERTHAN);
|
||||||
|
|
||||||
assert(lrec->dtrd_action == rrec->dtrd_action);
|
if (lagg->dtagd_nrecs < ragg->dtagd_nrecs)
|
||||||
|
return (DT_LESSTHAN);
|
||||||
|
|
||||||
|
for (i = 0; i < lagg->dtagd_nrecs; i++) {
|
||||||
|
lrec = &lagg->dtagd_rec[i];
|
||||||
|
rrec = &ragg->dtagd_rec[i];
|
||||||
|
|
||||||
|
if (lrec->dtrd_offset < rrec->dtrd_offset)
|
||||||
|
return (DT_LESSTHAN);
|
||||||
|
|
||||||
|
if (lrec->dtrd_offset > rrec->dtrd_offset)
|
||||||
|
return (DT_GREATERTHAN);
|
||||||
|
|
||||||
|
if (lrec->dtrd_action < rrec->dtrd_action)
|
||||||
|
return (DT_LESSTHAN);
|
||||||
|
|
||||||
|
if (lrec->dtrd_action > rrec->dtrd_action)
|
||||||
|
return (DT_GREATERTHAN);
|
||||||
|
}
|
||||||
|
|
||||||
laddr = (int64_t *)(uintptr_t)(ldata + lrec->dtrd_offset);
|
laddr = (int64_t *)(uintptr_t)(ldata + lrec->dtrd_offset);
|
||||||
raddr = (int64_t *)(uintptr_t)(rdata + rrec->dtrd_offset);
|
raddr = (int64_t *)(uintptr_t)(rdata + rrec->dtrd_offset);
|
||||||
|
@ -22,7 +22,7 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||||
* Copyright (c) 2011, Joyent Inc. All rights reserved.
|
* Copyright (c) 2011, Joyent Inc. All rights reserved.
|
||||||
* Copyright (c) 2012 by Delphix. All rights reserved.
|
* Copyright (c) 2011 by Delphix. All rights reserved.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -664,17 +664,15 @@ static void
|
|||||||
dt_action_trace(dtrace_hdl_t *dtp, dt_node_t *dnp, dtrace_stmtdesc_t *sdp)
|
dt_action_trace(dtrace_hdl_t *dtp, dt_node_t *dnp, dtrace_stmtdesc_t *sdp)
|
||||||
{
|
{
|
||||||
dtrace_actdesc_t *ap = dt_stmt_action(dtp, sdp);
|
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";
|
|
||||||
|
|
||||||
if (dt_node_is_void(dnp->dn_args)) {
|
if (dt_node_is_void(dnp->dn_args)) {
|
||||||
dnerror(dnp->dn_args, istrace ? D_TRACE_VOID : D_PRINT_VOID,
|
dnerror(dnp->dn_args, D_TRACE_VOID,
|
||||||
"%s( ) may not be applied to a void expression\n", act);
|
"trace( ) may not be applied to a void expression\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dt_node_resolve(dnp->dn_args, DT_IDENT_XLPTR) != NULL) {
|
if (dt_node_is_dynamic(dnp->dn_args)) {
|
||||||
dnerror(dnp->dn_args, istrace ? D_TRACE_DYN : D_PRINT_DYN,
|
dnerror(dnp->dn_args, D_TRACE_DYN,
|
||||||
"%s( ) may not be applied to a translated pointer\n", act);
|
"trace( ) may not be applied to a dynamic expression\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dnp->dn_args->dn_kind == DT_NODE_AGG) {
|
if (dnp->dn_args->dn_kind == DT_NODE_AGG) {
|
||||||
@ -684,33 +682,50 @@ dt_action_trace(dtrace_hdl_t *dtp, dt_node_t *dnp, dtrace_stmtdesc_t *sdp)
|
|||||||
}
|
}
|
||||||
|
|
||||||
dt_cg(yypcb, dnp->dn_args);
|
dt_cg(yypcb, dnp->dn_args);
|
||||||
|
ap->dtad_difo = dt_as(yypcb);
|
||||||
|
ap->dtad_kind = DTRACEACT_DIFEXPR;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The print() action behaves identically to trace(), except that it
|
* The print() action behaves identically to trace(), except that it stores the
|
||||||
* stores the CTF type of the argument (if present) within the DOF for
|
* CTF type of the argument (if present) within the DOF for the DIFEXPR action.
|
||||||
* the DIFEXPR action. To do this, we set the 'dtsd_strdata' to point
|
* To do this, we set the 'dtsd_strdata' to point to the fully-qualified CTF
|
||||||
* to the fully-qualified CTF type ID for the result of the DIF
|
* type ID for the result of the DIF action. We use the ID instead of the name
|
||||||
* action. We use the ID instead of the name to handles complex types
|
* to handles complex types like arrays and function pointers that can't be
|
||||||
* like arrays and function pointers that can't be resolved by
|
* resolved by ctf_type_lookup(). This is later processed by
|
||||||
* ctf_type_lookup(). This is later processed by dtrace_dof_create()
|
* dtrace_dof_create() and turned into a reference into the string table so
|
||||||
* and turned into a reference into the string table so that we can
|
* that we can get the type information when we process the data after the
|
||||||
* get the type information when we process the data after the fact.
|
* fact.
|
||||||
*/
|
*/
|
||||||
if (dnp->dn_ident->di_id == DT_ACT_PRINT) {
|
static void
|
||||||
|
dt_action_print(dtrace_hdl_t *dtp, dt_node_t *dnp, dtrace_stmtdesc_t *sdp)
|
||||||
|
{
|
||||||
|
dtrace_actdesc_t *ap = dt_stmt_action(dtp, sdp);
|
||||||
dt_node_t *dret;
|
dt_node_t *dret;
|
||||||
size_t n;
|
size_t len;
|
||||||
dt_module_t *dmp;
|
dt_module_t *dmp;
|
||||||
|
|
||||||
|
if (dt_node_is_void(dnp->dn_args)) {
|
||||||
|
dnerror(dnp->dn_args, D_PRINT_VOID,
|
||||||
|
"print( ) may not be applied to a void expression\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dt_node_is_dynamic(dnp->dn_args)) {
|
||||||
|
dnerror(dnp->dn_args, D_PRINT_DYN,
|
||||||
|
"print( ) may not be applied to a dynamic expression\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
dt_cg(yypcb, dnp->dn_args);
|
||||||
|
|
||||||
dret = yypcb->pcb_dret;
|
dret = yypcb->pcb_dret;
|
||||||
dmp = dt_module_lookup_by_ctf(dtp, dret->dn_ctfp);
|
dmp = dt_module_lookup_by_ctf(dtp, dret->dn_ctfp);
|
||||||
|
|
||||||
n = snprintf(NULL, 0, "%s`%ld", dmp->dm_name, dret->dn_type) + 1;
|
len = snprintf(NULL, 0, "%s`%ld", dmp->dm_name, dret->dn_type) + 1;
|
||||||
sdp->dtsd_strdata = dt_alloc(dtp, n);
|
sdp->dtsd_strdata = dt_alloc(dtp, len);
|
||||||
if (sdp->dtsd_strdata == NULL)
|
if (sdp->dtsd_strdata == NULL)
|
||||||
longjmp(yypcb->pcb_jmpbuf, EDT_NOMEM);
|
longjmp(yypcb->pcb_jmpbuf, EDT_NOMEM);
|
||||||
(void) snprintf(sdp->dtsd_strdata, n, "%s`%ld", dmp->dm_name,
|
(void) snprintf(sdp->dtsd_strdata, len, "%s`%ld", dmp->dm_name,
|
||||||
dret->dn_type);
|
dret->dn_type);
|
||||||
}
|
|
||||||
|
|
||||||
ap->dtad_difo = dt_as(yypcb);
|
ap->dtad_difo = dt_as(yypcb);
|
||||||
ap->dtad_kind = DTRACEACT_DIFEXPR;
|
ap->dtad_kind = DTRACEACT_DIFEXPR;
|
||||||
@ -1136,9 +1151,6 @@ dt_compile_fun(dtrace_hdl_t *dtp, dt_node_t *dnp, dtrace_stmtdesc_t *sdp)
|
|||||||
case DT_ACT_PANIC:
|
case DT_ACT_PANIC:
|
||||||
dt_action_panic(dtp, dnp->dn_expr, sdp);
|
dt_action_panic(dtp, dnp->dn_expr, sdp);
|
||||||
break;
|
break;
|
||||||
case DT_ACT_PRINT:
|
|
||||||
dt_action_trace(dtp, dnp->dn_expr, sdp);
|
|
||||||
break;
|
|
||||||
case DT_ACT_PRINTA:
|
case DT_ACT_PRINTA:
|
||||||
dt_action_printa(dtp, dnp->dn_expr, sdp);
|
dt_action_printa(dtp, dnp->dn_expr, sdp);
|
||||||
break;
|
break;
|
||||||
@ -1175,6 +1187,9 @@ dt_compile_fun(dtrace_hdl_t *dtp, dt_node_t *dnp, dtrace_stmtdesc_t *sdp)
|
|||||||
case DT_ACT_TRACE:
|
case DT_ACT_TRACE:
|
||||||
dt_action_trace(dtp, dnp->dn_expr, sdp);
|
dt_action_trace(dtp, dnp->dn_expr, sdp);
|
||||||
break;
|
break;
|
||||||
|
case DT_ACT_PRINT:
|
||||||
|
dt_action_print(dtp, dnp->dn_expr, sdp);
|
||||||
|
break;
|
||||||
case DT_ACT_TRACEMEM:
|
case DT_ACT_TRACEMEM:
|
||||||
dt_action_tracemem(dtp, dnp->dn_expr, sdp);
|
dt_action_tracemem(dtp, dnp->dn_expr, sdp);
|
||||||
break;
|
break;
|
||||||
@ -2550,8 +2565,7 @@ dt_compile(dtrace_hdl_t *dtp, int context, dtrace_probespec_t pspec, void *arg,
|
|||||||
}
|
}
|
||||||
|
|
||||||
out:
|
out:
|
||||||
if (context != DT_CTX_DTYPE && yypcb->pcb_root != NULL &&
|
if (context != DT_CTX_DTYPE && DT_TREEDUMP_PASS(dtp, 3))
|
||||||
DT_TREEDUMP_PASS(dtp, 3))
|
|
||||||
dt_node_printr(yypcb->pcb_root, stderr, 0);
|
dt_node_printr(yypcb->pcb_root, stderr, 0);
|
||||||
|
|
||||||
if (dtp->dt_cdefs_fd != -1 && (ftruncate64(dtp->dt_cdefs_fd, 0) == -1 ||
|
if (dtp->dt_cdefs_fd != -1 && (ftruncate64(dtp->dt_cdefs_fd, 0) == -1 ||
|
||||||
|
@ -19,15 +19,12 @@
|
|||||||
*
|
*
|
||||||
* CDDL HEADER END
|
* CDDL HEADER END
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright 2005 Sun Microsystems, Inc. All rights reserved.
|
* Copyright 2005 Sun Microsystems, Inc. All rights reserved.
|
||||||
* Use is subject to license terms.
|
* Use is subject to license terms.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
#pragma ident "%Z%%M% %I% %E% SMI"
|
||||||
* Copyright (c) 2012 by Delphix. All rights reserved.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/sysmacros.h>
|
#include <sys/sysmacros.h>
|
||||||
@ -196,6 +193,9 @@ dt_cg_ptrsize(dt_node_t *dnp, dt_irlist_t *dlp, dt_regset_t *drp,
|
|||||||
ssize_t size;
|
ssize_t size;
|
||||||
int sreg;
|
int sreg;
|
||||||
|
|
||||||
|
if ((sreg = dt_regset_alloc(drp)) == -1)
|
||||||
|
longjmp(yypcb->pcb_jmpbuf, EDT_NOREG);
|
||||||
|
|
||||||
type = ctf_type_resolve(ctfp, dnp->dn_type);
|
type = ctf_type_resolve(ctfp, dnp->dn_type);
|
||||||
kind = ctf_type_kind(ctfp, type);
|
kind = ctf_type_kind(ctfp, type);
|
||||||
assert(kind == CTF_K_POINTER || kind == CTF_K_ARRAY);
|
assert(kind == CTF_K_POINTER || kind == CTF_K_ARRAY);
|
||||||
@ -212,7 +212,6 @@ dt_cg_ptrsize(dt_node_t *dnp, dt_irlist_t *dlp, dt_regset_t *drp,
|
|||||||
if ((size = ctf_type_size(ctfp, type)) == 1)
|
if ((size = ctf_type_size(ctfp, type)) == 1)
|
||||||
return; /* multiply or divide by one can be omitted */
|
return; /* multiply or divide by one can be omitted */
|
||||||
|
|
||||||
sreg = dt_regset_alloc(drp);
|
|
||||||
dt_cg_setx(dlp, sreg, size);
|
dt_cg_setx(dlp, sreg, size);
|
||||||
instr = DIF_INSTR_FMT(op, dreg, sreg, dreg);
|
instr = DIF_INSTR_FMT(op, dreg, sreg, dreg);
|
||||||
dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));
|
dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));
|
||||||
@ -252,7 +251,9 @@ dt_cg_field_get(dt_node_t *dnp, dt_irlist_t *dlp, dt_regset_t *drp,
|
|||||||
|
|
||||||
assert(dnp->dn_op == DT_TOK_PTR || dnp->dn_op == DT_TOK_DOT);
|
assert(dnp->dn_op == DT_TOK_PTR || dnp->dn_op == DT_TOK_DOT);
|
||||||
r1 = dnp->dn_left->dn_reg;
|
r1 = dnp->dn_left->dn_reg;
|
||||||
r2 = dt_regset_alloc(drp);
|
|
||||||
|
if ((r2 = dt_regset_alloc(drp)) == -1)
|
||||||
|
longjmp(yypcb->pcb_jmpbuf, EDT_NOREG);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* On little-endian architectures, ctm_offset counts from the right so
|
* On little-endian architectures, ctm_offset counts from the right so
|
||||||
@ -355,9 +356,10 @@ dt_cg_field_set(dt_node_t *src, dt_irlist_t *dlp,
|
|||||||
"bits %u\n", m.ctm_offset, m.ctm_type, e.cte_bits);
|
"bits %u\n", m.ctm_offset, m.ctm_type, e.cte_bits);
|
||||||
}
|
}
|
||||||
|
|
||||||
r1 = dt_regset_alloc(drp);
|
if ((r1 = dt_regset_alloc(drp)) == -1 ||
|
||||||
r2 = dt_regset_alloc(drp);
|
(r2 = dt_regset_alloc(drp)) == -1 ||
|
||||||
r3 = dt_regset_alloc(drp);
|
(r3 = dt_regset_alloc(drp)) == -1)
|
||||||
|
longjmp(yypcb->pcb_jmpbuf, EDT_NOREG);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Compute shifts and masks. We need to compute "shift" as the amount
|
* Compute shifts and masks. We need to compute "shift" as the amount
|
||||||
@ -421,7 +423,8 @@ dt_cg_store(dt_node_t *src, dt_irlist_t *dlp, dt_regset_t *drp, dt_node_t *dst)
|
|||||||
size = dt_node_type_size(src);
|
size = dt_node_type_size(src);
|
||||||
|
|
||||||
if (src->dn_flags & DT_NF_REF) {
|
if (src->dn_flags & DT_NF_REF) {
|
||||||
reg = dt_regset_alloc(drp);
|
if ((reg = dt_regset_alloc(drp)) == -1)
|
||||||
|
longjmp(yypcb->pcb_jmpbuf, EDT_NOREG);
|
||||||
dt_cg_setx(dlp, reg, size);
|
dt_cg_setx(dlp, reg, size);
|
||||||
instr = DIF_INSTR_COPYS(src->dn_reg, reg, dst->dn_reg);
|
instr = DIF_INSTR_COPYS(src->dn_reg, reg, dst->dn_reg);
|
||||||
dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));
|
dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));
|
||||||
@ -471,58 +474,30 @@ dt_cg_typecast(const dt_node_t *src, const dt_node_t *dst,
|
|||||||
size_t dstsize = dt_node_type_size(dst);
|
size_t dstsize = dt_node_type_size(dst);
|
||||||
|
|
||||||
dif_instr_t instr;
|
dif_instr_t instr;
|
||||||
int rg;
|
int reg, n;
|
||||||
|
|
||||||
if (!dt_node_is_scalar(dst))
|
if (dt_node_is_scalar(dst) && (dstsize < srcsize ||
|
||||||
return; /* not a scalar */
|
(src->dn_flags & DT_NF_SIGNED) ^ (dst->dn_flags & DT_NF_SIGNED))) {
|
||||||
if (dstsize == srcsize &&
|
if ((reg = dt_regset_alloc(drp)) == -1)
|
||||||
((src->dn_flags ^ dst->dn_flags) & DT_NF_SIGNED) != 0)
|
longjmp(yypcb->pcb_jmpbuf, EDT_NOREG);
|
||||||
return; /* not narrowing or changing signed-ness */
|
|
||||||
if (dstsize > srcsize && (src->dn_flags & DT_NF_SIGNED) == 0)
|
|
||||||
return; /* nothing to do in this case */
|
|
||||||
|
|
||||||
rg = dt_regset_alloc(drp);
|
if (dstsize < srcsize)
|
||||||
|
n = sizeof (uint64_t) * NBBY - dstsize * NBBY;
|
||||||
|
else
|
||||||
|
n = sizeof (uint64_t) * NBBY - srcsize * NBBY;
|
||||||
|
|
||||||
if (dstsize > srcsize) {
|
dt_cg_setx(dlp, reg, n);
|
||||||
int n = sizeof (uint64_t) * NBBY - srcsize * NBBY;
|
|
||||||
int s = (dstsize - srcsize) * NBBY;
|
|
||||||
|
|
||||||
dt_cg_setx(dlp, rg, n);
|
instr = DIF_INSTR_FMT(DIF_OP_SLL,
|
||||||
|
src->dn_reg, reg, dst->dn_reg);
|
||||||
instr = DIF_INSTR_FMT(DIF_OP_SLL, src->dn_reg, rg, dst->dn_reg);
|
|
||||||
dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));
|
|
||||||
|
|
||||||
if ((dst->dn_flags & DT_NF_SIGNED) || n == s) {
|
|
||||||
instr = DIF_INSTR_FMT(DIF_OP_SRA,
|
|
||||||
dst->dn_reg, rg, dst->dn_reg);
|
|
||||||
dt_irlist_append(dlp,
|
|
||||||
dt_cg_node_alloc(DT_LBL_NONE, instr));
|
|
||||||
} else {
|
|
||||||
dt_cg_setx(dlp, rg, s);
|
|
||||||
instr = DIF_INSTR_FMT(DIF_OP_SRA,
|
|
||||||
dst->dn_reg, rg, dst->dn_reg);
|
|
||||||
dt_irlist_append(dlp,
|
|
||||||
dt_cg_node_alloc(DT_LBL_NONE, instr));
|
|
||||||
dt_cg_setx(dlp, rg, n - s);
|
|
||||||
instr = DIF_INSTR_FMT(DIF_OP_SRL,
|
|
||||||
dst->dn_reg, rg, dst->dn_reg);
|
|
||||||
dt_irlist_append(dlp,
|
|
||||||
dt_cg_node_alloc(DT_LBL_NONE, instr));
|
|
||||||
}
|
|
||||||
} else if (dstsize != sizeof (uint64_t)) {
|
|
||||||
int n = sizeof (uint64_t) * NBBY - dstsize * NBBY;
|
|
||||||
|
|
||||||
dt_cg_setx(dlp, rg, n);
|
|
||||||
|
|
||||||
instr = DIF_INSTR_FMT(DIF_OP_SLL, src->dn_reg, rg, dst->dn_reg);
|
|
||||||
dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));
|
dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));
|
||||||
|
|
||||||
instr = DIF_INSTR_FMT((dst->dn_flags & DT_NF_SIGNED) ?
|
instr = DIF_INSTR_FMT((dst->dn_flags & DT_NF_SIGNED) ?
|
||||||
DIF_OP_SRA : DIF_OP_SRL, dst->dn_reg, rg, dst->dn_reg);
|
DIF_OP_SRA : DIF_OP_SRL, dst->dn_reg, reg, dst->dn_reg);
|
||||||
dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));
|
|
||||||
}
|
|
||||||
|
|
||||||
dt_regset_free(drp, rg);
|
dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));
|
||||||
|
dt_regset_free(drp, reg);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -548,7 +523,8 @@ dt_cg_arglist(dt_ident_t *idp, dt_node_t *args,
|
|||||||
for (dnp = args; dnp != NULL; dnp = dnp->dn_list)
|
for (dnp = args; dnp != NULL; dnp = dnp->dn_list)
|
||||||
dt_cg_node(dnp, dlp, drp);
|
dt_cg_node(dnp, dlp, drp);
|
||||||
|
|
||||||
dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, DIF_INSTR_FLUSHTS));
|
dt_irlist_append(dlp,
|
||||||
|
dt_cg_node_alloc(DT_LBL_NONE, DIF_INSTR_FLUSHTS));
|
||||||
|
|
||||||
for (dnp = args; dnp != NULL; dnp = dnp->dn_list, i++) {
|
for (dnp = args; dnp != NULL; dnp = dnp->dn_list, i++) {
|
||||||
dtrace_diftype_t t;
|
dtrace_diftype_t t;
|
||||||
@ -562,18 +538,17 @@ dt_cg_arglist(dt_ident_t *idp, dt_node_t *args,
|
|||||||
dt_cg_typecast(dnp, &isp->dis_args[i], dlp, drp);
|
dt_cg_typecast(dnp, &isp->dis_args[i], dlp, drp);
|
||||||
isp->dis_args[i].dn_reg = -1;
|
isp->dis_args[i].dn_reg = -1;
|
||||||
|
|
||||||
if (t.dtdt_flags & DIF_TF_BYREF) {
|
if (t.dtdt_flags & DIF_TF_BYREF)
|
||||||
op = DIF_OP_PUSHTR;
|
op = DIF_OP_PUSHTR;
|
||||||
if (t.dtdt_size != 0) {
|
else
|
||||||
reg = dt_regset_alloc(drp);
|
|
||||||
dt_cg_setx(dlp, reg, t.dtdt_size);
|
|
||||||
} else {
|
|
||||||
reg = DIF_REG_R0;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
op = DIF_OP_PUSHTV;
|
op = DIF_OP_PUSHTV;
|
||||||
|
|
||||||
|
if (t.dtdt_size != 0) {
|
||||||
|
if ((reg = dt_regset_alloc(drp)) == -1)
|
||||||
|
longjmp(yypcb->pcb_jmpbuf, EDT_NOREG);
|
||||||
|
dt_cg_setx(dlp, reg, t.dtdt_size);
|
||||||
|
} else
|
||||||
reg = DIF_REG_R0;
|
reg = DIF_REG_R0;
|
||||||
}
|
|
||||||
|
|
||||||
instr = DIF_INSTR_PUSHTS(op, t.dtdt_kind, reg, dnp->dn_reg);
|
instr = DIF_INSTR_PUSHTS(op, t.dtdt_kind, reg, dnp->dn_reg);
|
||||||
dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));
|
dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));
|
||||||
@ -654,7 +629,9 @@ dt_cg_prearith_op(dt_node_t *dnp, dt_irlist_t *dlp, dt_regset_t *drp, uint_t op)
|
|||||||
dt_cg_node(dnp->dn_child, dlp, drp);
|
dt_cg_node(dnp->dn_child, dlp, drp);
|
||||||
dnp->dn_reg = dnp->dn_child->dn_reg;
|
dnp->dn_reg = dnp->dn_child->dn_reg;
|
||||||
|
|
||||||
reg = dt_regset_alloc(drp);
|
if ((reg = dt_regset_alloc(drp)) == -1)
|
||||||
|
longjmp(yypcb->pcb_jmpbuf, EDT_NOREG);
|
||||||
|
|
||||||
dt_cg_setx(dlp, reg, size);
|
dt_cg_setx(dlp, reg, size);
|
||||||
|
|
||||||
instr = DIF_INSTR_FMT(op, dnp->dn_reg, reg, dnp->dn_reg);
|
instr = DIF_INSTR_FMT(op, dnp->dn_reg, reg, dnp->dn_reg);
|
||||||
@ -711,7 +688,9 @@ dt_cg_postarith_op(dt_node_t *dnp, dt_irlist_t *dlp,
|
|||||||
dt_cg_node(dnp->dn_child, dlp, drp);
|
dt_cg_node(dnp->dn_child, dlp, drp);
|
||||||
dnp->dn_reg = dnp->dn_child->dn_reg;
|
dnp->dn_reg = dnp->dn_child->dn_reg;
|
||||||
|
|
||||||
nreg = dt_regset_alloc(drp);
|
if ((nreg = dt_regset_alloc(drp)) == -1)
|
||||||
|
longjmp(yypcb->pcb_jmpbuf, EDT_NOREG);
|
||||||
|
|
||||||
dt_cg_setx(dlp, nreg, size);
|
dt_cg_setx(dlp, nreg, size);
|
||||||
instr = DIF_INSTR_FMT(op, dnp->dn_reg, nreg, nreg);
|
instr = DIF_INSTR_FMT(op, dnp->dn_reg, nreg, nreg);
|
||||||
dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));
|
dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));
|
||||||
@ -1029,7 +1008,9 @@ dt_cg_asgn_op(dt_node_t *dnp, dt_irlist_t *dlp, dt_regset_t *drp)
|
|||||||
* set it to the size of our data structure, and then replace
|
* set it to the size of our data structure, and then replace
|
||||||
* it with the result of an allocs of the specified size.
|
* it with the result of an allocs of the specified size.
|
||||||
*/
|
*/
|
||||||
r1 = dt_regset_alloc(drp);
|
if ((r1 = dt_regset_alloc(drp)) == -1)
|
||||||
|
longjmp(yypcb->pcb_jmpbuf, EDT_NOREG);
|
||||||
|
|
||||||
dt_cg_setx(dlp, r1,
|
dt_cg_setx(dlp, r1,
|
||||||
ctf_type_size(dxp->dx_dst_ctfp, dxp->dx_dst_base));
|
ctf_type_size(dxp->dx_dst_ctfp, dxp->dx_dst_base));
|
||||||
|
|
||||||
@ -1073,7 +1054,8 @@ dt_cg_asgn_op(dt_node_t *dnp, dt_irlist_t *dlp, dt_regset_t *drp)
|
|||||||
* and add r1 to it before storing the result.
|
* and add r1 to it before storing the result.
|
||||||
*/
|
*/
|
||||||
if (ctm.ctm_offset != 0) {
|
if (ctm.ctm_offset != 0) {
|
||||||
r2 = dt_regset_alloc(drp);
|
if ((r2 = dt_regset_alloc(drp)) == -1)
|
||||||
|
longjmp(yypcb->pcb_jmpbuf, EDT_NOREG);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Add the member offset rounded down to the
|
* Add the member offset rounded down to the
|
||||||
@ -1160,7 +1142,8 @@ dt_cg_assoc_op(dt_node_t *dnp, dt_irlist_t *dlp, dt_regset_t *drp)
|
|||||||
|
|
||||||
dt_cg_arglist(dnp->dn_ident, dnp->dn_args, dlp, drp);
|
dt_cg_arglist(dnp->dn_ident, dnp->dn_args, dlp, drp);
|
||||||
|
|
||||||
dnp->dn_reg = dt_regset_alloc(drp);
|
if ((dnp->dn_reg = dt_regset_alloc(drp)) == -1)
|
||||||
|
longjmp(yypcb->pcb_jmpbuf, EDT_NOREG);
|
||||||
|
|
||||||
if (dnp->dn_ident->di_flags & DT_IDFLG_TLS)
|
if (dnp->dn_ident->di_flags & DT_IDFLG_TLS)
|
||||||
op = DIF_OP_LDTAA;
|
op = DIF_OP_LDTAA;
|
||||||
@ -1290,7 +1273,9 @@ dt_cg_array_op(dt_node_t *dnp, dt_irlist_t *dlp, dt_regset_t *drp)
|
|||||||
if ((size = dt_node_type_size(dnp)) == sizeof (uint64_t))
|
if ((size = dt_node_type_size(dnp)) == sizeof (uint64_t))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
reg = dt_regset_alloc(drp);
|
if ((reg = dt_regset_alloc(drp)) == -1)
|
||||||
|
longjmp(yypcb->pcb_jmpbuf, EDT_NOREG);
|
||||||
|
|
||||||
assert(size < sizeof (uint64_t));
|
assert(size < sizeof (uint64_t));
|
||||||
n = sizeof (uint64_t) * NBBY - size * NBBY;
|
n = sizeof (uint64_t) * NBBY - size * NBBY;
|
||||||
|
|
||||||
@ -1387,162 +1372,6 @@ dt_cg_func_typeref(dtrace_hdl_t *dtp, dt_node_t *dnp)
|
|||||||
typs->dn_value = ctf_type_size(dtt.dtt_ctfp, dtt.dtt_type);
|
typs->dn_value = ctf_type_size(dtt.dtt_ctfp, dtt.dtt_type);
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef struct dt_xlmemb {
|
|
||||||
dt_ident_t *dtxl_idp; /* translated ident */
|
|
||||||
dt_irlist_t *dtxl_dlp; /* instruction list */
|
|
||||||
dt_regset_t *dtxl_drp; /* register set */
|
|
||||||
int dtxl_sreg; /* location of the translation input */
|
|
||||||
int dtxl_dreg; /* location of our allocated buffer */
|
|
||||||
} dt_xlmemb_t;
|
|
||||||
|
|
||||||
/*ARGSUSED*/
|
|
||||||
static int
|
|
||||||
dt_cg_xlate_member(const char *name, ctf_id_t type, ulong_t off, void *arg)
|
|
||||||
{
|
|
||||||
dt_xlmemb_t *dx = arg;
|
|
||||||
dt_ident_t *idp = dx->dtxl_idp;
|
|
||||||
dt_irlist_t *dlp = dx->dtxl_dlp;
|
|
||||||
dt_regset_t *drp = dx->dtxl_drp;
|
|
||||||
|
|
||||||
dt_node_t *mnp;
|
|
||||||
dt_xlator_t *dxp;
|
|
||||||
|
|
||||||
int reg, treg;
|
|
||||||
uint32_t instr;
|
|
||||||
size_t size;
|
|
||||||
|
|
||||||
/* Generate code for the translation. */
|
|
||||||
dxp = idp->di_data;
|
|
||||||
mnp = dt_xlator_member(dxp, name);
|
|
||||||
|
|
||||||
/* If there's no translator for the given member, skip it. */
|
|
||||||
if (mnp == NULL)
|
|
||||||
return (0);
|
|
||||||
|
|
||||||
dxp->dx_ident->di_flags |= DT_IDFLG_CGREG;
|
|
||||||
dxp->dx_ident->di_id = dx->dtxl_sreg;
|
|
||||||
|
|
||||||
dt_cg_node(mnp->dn_membexpr, dlp, drp);
|
|
||||||
|
|
||||||
dxp->dx_ident->di_flags &= ~DT_IDFLG_CGREG;
|
|
||||||
dxp->dx_ident->di_id = 0;
|
|
||||||
|
|
||||||
treg = mnp->dn_membexpr->dn_reg;
|
|
||||||
|
|
||||||
/* Compute the offset into our buffer and store the result there. */
|
|
||||||
reg = dt_regset_alloc(drp);
|
|
||||||
|
|
||||||
dt_cg_setx(dlp, reg, off / NBBY);
|
|
||||||
instr = DIF_INSTR_FMT(DIF_OP_ADD, dx->dtxl_dreg, reg, reg);
|
|
||||||
dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));
|
|
||||||
|
|
||||||
size = ctf_type_size(mnp->dn_membexpr->dn_ctfp,
|
|
||||||
mnp->dn_membexpr->dn_type);
|
|
||||||
if (dt_node_is_scalar(mnp->dn_membexpr)) {
|
|
||||||
/*
|
|
||||||
* Copying scalars is simple.
|
|
||||||
*/
|
|
||||||
switch (size) {
|
|
||||||
case 1:
|
|
||||||
instr = DIF_INSTR_STORE(DIF_OP_STB, treg, reg);
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
instr = DIF_INSTR_STORE(DIF_OP_STH, treg, reg);
|
|
||||||
break;
|
|
||||||
case 4:
|
|
||||||
instr = DIF_INSTR_STORE(DIF_OP_STW, treg, reg);
|
|
||||||
break;
|
|
||||||
case 8:
|
|
||||||
instr = DIF_INSTR_STORE(DIF_OP_STX, treg, reg);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
xyerror(D_UNKNOWN, "internal error -- unexpected "
|
|
||||||
"size: %lu\n", (ulong_t)size);
|
|
||||||
}
|
|
||||||
|
|
||||||
dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));
|
|
||||||
|
|
||||||
} else if (dt_node_is_string(mnp->dn_membexpr)) {
|
|
||||||
int szreg;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Use the copys instruction for strings.
|
|
||||||
*/
|
|
||||||
szreg = dt_regset_alloc(drp);
|
|
||||||
dt_cg_setx(dlp, szreg, size);
|
|
||||||
instr = DIF_INSTR_COPYS(treg, szreg, reg);
|
|
||||||
dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));
|
|
||||||
dt_regset_free(drp, szreg);
|
|
||||||
} else {
|
|
||||||
int szreg;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* If it's anything else then we'll just bcopy it.
|
|
||||||
*/
|
|
||||||
szreg = dt_regset_alloc(drp);
|
|
||||||
dt_cg_setx(dlp, szreg, size);
|
|
||||||
dt_irlist_append(dlp,
|
|
||||||
dt_cg_node_alloc(DT_LBL_NONE, DIF_INSTR_FLUSHTS));
|
|
||||||
instr = DIF_INSTR_PUSHTS(DIF_OP_PUSHTV, DIF_TYPE_CTF,
|
|
||||||
DIF_REG_R0, treg);
|
|
||||||
dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));
|
|
||||||
instr = DIF_INSTR_PUSHTS(DIF_OP_PUSHTV, DIF_TYPE_CTF,
|
|
||||||
DIF_REG_R0, reg);
|
|
||||||
dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));
|
|
||||||
instr = DIF_INSTR_PUSHTS(DIF_OP_PUSHTV, DIF_TYPE_CTF,
|
|
||||||
DIF_REG_R0, szreg);
|
|
||||||
dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));
|
|
||||||
instr = DIF_INSTR_CALL(DIF_SUBR_BCOPY, szreg);
|
|
||||||
dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));
|
|
||||||
dt_regset_free(drp, szreg);
|
|
||||||
}
|
|
||||||
|
|
||||||
dt_regset_free(drp, reg);
|
|
||||||
dt_regset_free(drp, treg);
|
|
||||||
|
|
||||||
return (0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* If we're expanding a translated type, we create an appropriately sized
|
|
||||||
* buffer with alloca() and then translate each member into it.
|
|
||||||
*/
|
|
||||||
static int
|
|
||||||
dt_cg_xlate_expand(dt_node_t *dnp, dt_ident_t *idp, dt_irlist_t *dlp,
|
|
||||||
dt_regset_t *drp)
|
|
||||||
{
|
|
||||||
dt_xlmemb_t dlm;
|
|
||||||
uint32_t instr;
|
|
||||||
int dreg;
|
|
||||||
size_t size;
|
|
||||||
|
|
||||||
dreg = dt_regset_alloc(drp);
|
|
||||||
size = ctf_type_size(dnp->dn_ident->di_ctfp, dnp->dn_ident->di_type);
|
|
||||||
|
|
||||||
/* Call alloca() to create the buffer. */
|
|
||||||
dt_cg_setx(dlp, dreg, size);
|
|
||||||
|
|
||||||
dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, DIF_INSTR_FLUSHTS));
|
|
||||||
|
|
||||||
instr = DIF_INSTR_PUSHTS(DIF_OP_PUSHTV, DIF_TYPE_CTF, DIF_REG_R0, dreg);
|
|
||||||
dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));
|
|
||||||
|
|
||||||
instr = DIF_INSTR_CALL(DIF_SUBR_ALLOCA, dreg);
|
|
||||||
dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));
|
|
||||||
|
|
||||||
/* Generate the translation for each member. */
|
|
||||||
dlm.dtxl_idp = idp;
|
|
||||||
dlm.dtxl_dlp = dlp;
|
|
||||||
dlm.dtxl_drp = drp;
|
|
||||||
dlm.dtxl_sreg = dnp->dn_reg;
|
|
||||||
dlm.dtxl_dreg = dreg;
|
|
||||||
(void) ctf_member_iter(dnp->dn_ident->di_ctfp,
|
|
||||||
dnp->dn_ident->di_type, dt_cg_xlate_member,
|
|
||||||
&dlm);
|
|
||||||
|
|
||||||
return (dreg);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
dt_cg_node(dt_node_t *dnp, dt_irlist_t *dlp, dt_regset_t *drp)
|
dt_cg_node(dt_node_t *dnp, dt_irlist_t *dlp, dt_regset_t *drp)
|
||||||
{
|
{
|
||||||
@ -1555,6 +1384,7 @@ dt_cg_node(dt_node_t *dnp, dt_irlist_t *dlp, dt_regset_t *drp)
|
|||||||
dt_ident_t *idp;
|
dt_ident_t *idp;
|
||||||
ssize_t stroff;
|
ssize_t stroff;
|
||||||
uint_t op;
|
uint_t op;
|
||||||
|
int reg;
|
||||||
|
|
||||||
switch (dnp->dn_op) {
|
switch (dnp->dn_op) {
|
||||||
case DT_TOK_COMMA:
|
case DT_TOK_COMMA:
|
||||||
@ -1756,16 +1586,7 @@ dt_cg_node(dt_node_t *dnp, dt_irlist_t *dlp, dt_regset_t *drp)
|
|||||||
dt_cg_node(dnp->dn_child, dlp, drp);
|
dt_cg_node(dnp->dn_child, dlp, drp);
|
||||||
dnp->dn_reg = dnp->dn_child->dn_reg;
|
dnp->dn_reg = dnp->dn_child->dn_reg;
|
||||||
|
|
||||||
if (dt_node_is_dynamic(dnp->dn_child)) {
|
if (!(dnp->dn_flags & DT_NF_REF)) {
|
||||||
int reg;
|
|
||||||
idp = dt_node_resolve(dnp->dn_child, DT_IDENT_XLPTR);
|
|
||||||
assert(idp != NULL);
|
|
||||||
reg = dt_cg_xlate_expand(dnp, idp, dlp, drp);
|
|
||||||
|
|
||||||
dt_regset_free(drp, dnp->dn_child->dn_reg);
|
|
||||||
dnp->dn_reg = reg;
|
|
||||||
|
|
||||||
} else if (!(dnp->dn_flags & DT_NF_REF)) {
|
|
||||||
uint_t ubit = dnp->dn_flags & DT_NF_USERLAND;
|
uint_t ubit = dnp->dn_flags & DT_NF_USERLAND;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -1801,7 +1622,10 @@ dt_cg_node(dt_node_t *dnp, dt_irlist_t *dlp, dt_regset_t *drp)
|
|||||||
|
|
||||||
case DT_TOK_SIZEOF: {
|
case DT_TOK_SIZEOF: {
|
||||||
size_t size = dt_node_sizeof(dnp->dn_child);
|
size_t size = dt_node_sizeof(dnp->dn_child);
|
||||||
dnp->dn_reg = dt_regset_alloc(drp);
|
|
||||||
|
if ((dnp->dn_reg = dt_regset_alloc(drp)) == -1)
|
||||||
|
longjmp(yypcb->pcb_jmpbuf, EDT_NOREG);
|
||||||
|
|
||||||
assert(size != 0);
|
assert(size != 0);
|
||||||
dt_cg_setx(dlp, dnp->dn_reg, size);
|
dt_cg_setx(dlp, dnp->dn_reg, size);
|
||||||
break;
|
break;
|
||||||
@ -1826,7 +1650,8 @@ dt_cg_node(dt_node_t *dnp, dt_irlist_t *dlp, dt_regset_t *drp)
|
|||||||
assert(dxp->dx_ident->di_flags & DT_IDFLG_CGREG);
|
assert(dxp->dx_ident->di_flags & DT_IDFLG_CGREG);
|
||||||
assert(dxp->dx_ident->di_id != 0);
|
assert(dxp->dx_ident->di_id != 0);
|
||||||
|
|
||||||
dnp->dn_reg = dt_regset_alloc(drp);
|
if ((dnp->dn_reg = dt_regset_alloc(drp)) == -1)
|
||||||
|
longjmp(yypcb->pcb_jmpbuf, EDT_NOREG);
|
||||||
|
|
||||||
if (dxp->dx_arg == -1) {
|
if (dxp->dx_arg == -1) {
|
||||||
instr = DIF_INSTR_MOV(
|
instr = DIF_INSTR_MOV(
|
||||||
@ -1910,9 +1735,8 @@ dt_cg_node(dt_node_t *dnp, dt_irlist_t *dlp, dt_regset_t *drp)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (m.ctm_offset != 0) {
|
if (m.ctm_offset != 0) {
|
||||||
int reg;
|
if ((reg = dt_regset_alloc(drp)) == -1)
|
||||||
|
longjmp(yypcb->pcb_jmpbuf, EDT_NOREG);
|
||||||
reg = dt_regset_alloc(drp);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If the offset is not aligned on a byte boundary, it
|
* If the offset is not aligned on a byte boundary, it
|
||||||
@ -1958,7 +1782,8 @@ dt_cg_node(dt_node_t *dnp, dt_irlist_t *dlp, dt_regset_t *drp)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case DT_TOK_STRING:
|
case DT_TOK_STRING:
|
||||||
dnp->dn_reg = dt_regset_alloc(drp);
|
if ((dnp->dn_reg = dt_regset_alloc(drp)) == -1)
|
||||||
|
longjmp(yypcb->pcb_jmpbuf, EDT_NOREG);
|
||||||
|
|
||||||
assert(dnp->dn_kind == DT_NODE_STRING);
|
assert(dnp->dn_kind == DT_NODE_STRING);
|
||||||
stroff = dt_strtab_insert(yypcb->pcb_strtab, dnp->dn_string);
|
stroff = dt_strtab_insert(yypcb->pcb_strtab, dnp->dn_string);
|
||||||
@ -1981,7 +1806,8 @@ dt_cg_node(dt_node_t *dnp, dt_irlist_t *dlp, dt_regset_t *drp)
|
|||||||
*/
|
*/
|
||||||
if (dnp->dn_kind == DT_NODE_VAR &&
|
if (dnp->dn_kind == DT_NODE_VAR &&
|
||||||
(dnp->dn_ident->di_flags & DT_IDFLG_CGREG)) {
|
(dnp->dn_ident->di_flags & DT_IDFLG_CGREG)) {
|
||||||
dnp->dn_reg = dt_regset_alloc(drp);
|
if ((dnp->dn_reg = dt_regset_alloc(drp)) == -1)
|
||||||
|
longjmp(yypcb->pcb_jmpbuf, EDT_NOREG);
|
||||||
instr = DIF_INSTR_MOV(dnp->dn_ident->di_id,
|
instr = DIF_INSTR_MOV(dnp->dn_ident->di_id,
|
||||||
dnp->dn_reg);
|
dnp->dn_reg);
|
||||||
dt_irlist_append(dlp,
|
dt_irlist_append(dlp,
|
||||||
@ -2022,9 +1848,11 @@ dt_cg_node(dt_node_t *dnp, dt_irlist_t *dlp, dt_regset_t *drp)
|
|||||||
|
|
||||||
dt_cg_arglist(dnp->dn_ident, dnp->dn_args, dlp, drp);
|
dt_cg_arglist(dnp->dn_ident, dnp->dn_args, dlp, drp);
|
||||||
|
|
||||||
dnp->dn_reg = dt_regset_alloc(drp);
|
if ((dnp->dn_reg = dt_regset_alloc(drp)) == -1)
|
||||||
instr = DIF_INSTR_CALL(dnp->dn_ident->di_id,
|
longjmp(yypcb->pcb_jmpbuf, EDT_NOREG);
|
||||||
dnp->dn_reg);
|
|
||||||
|
instr = DIF_INSTR_CALL(
|
||||||
|
dnp->dn_ident->di_id, dnp->dn_reg);
|
||||||
|
|
||||||
dt_irlist_append(dlp,
|
dt_irlist_append(dlp,
|
||||||
dt_cg_node_alloc(DT_LBL_NONE, instr));
|
dt_cg_node_alloc(DT_LBL_NONE, instr));
|
||||||
@ -2052,7 +1880,8 @@ dt_cg_node(dt_node_t *dnp, dt_irlist_t *dlp, dt_regset_t *drp)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
dnp->dn_reg = dt_regset_alloc(drp);
|
if ((dnp->dn_reg = dt_regset_alloc(drp)) == -1)
|
||||||
|
longjmp(yypcb->pcb_jmpbuf, EDT_NOREG);
|
||||||
|
|
||||||
if (dnp->dn_ident->di_flags & DT_IDFLG_LOCAL)
|
if (dnp->dn_ident->di_flags & DT_IDFLG_LOCAL)
|
||||||
op = DIF_OP_LDLS;
|
op = DIF_OP_LDLS;
|
||||||
@ -2082,7 +1911,9 @@ dt_cg_node(dt_node_t *dnp, dt_irlist_t *dlp, dt_regset_t *drp)
|
|||||||
dtrace_errmsg(dtp, dtrace_errno(dtp)));
|
dtrace_errmsg(dtp, dtrace_errno(dtp)));
|
||||||
}
|
}
|
||||||
|
|
||||||
dnp->dn_reg = dt_regset_alloc(drp);
|
if ((dnp->dn_reg = dt_regset_alloc(drp)) == -1)
|
||||||
|
longjmp(yypcb->pcb_jmpbuf, EDT_NOREG);
|
||||||
|
|
||||||
dt_cg_xsetx(dlp, dnp->dn_ident,
|
dt_cg_xsetx(dlp, dnp->dn_ident,
|
||||||
DT_LBL_NONE, dnp->dn_reg, sym.st_value);
|
DT_LBL_NONE, dnp->dn_reg, sym.st_value);
|
||||||
|
|
||||||
@ -2102,7 +1933,9 @@ dt_cg_node(dt_node_t *dnp, dt_irlist_t *dlp, dt_regset_t *drp)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case DT_TOK_INT:
|
case DT_TOK_INT:
|
||||||
dnp->dn_reg = dt_regset_alloc(drp);
|
if ((dnp->dn_reg = dt_regset_alloc(drp)) == -1)
|
||||||
|
longjmp(yypcb->pcb_jmpbuf, EDT_NOREG);
|
||||||
|
|
||||||
dt_cg_setx(dlp, dnp->dn_reg, dnp->dn_value);
|
dt_cg_setx(dlp, dnp->dn_reg, dnp->dn_value);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -2117,7 +1950,6 @@ dt_cg(dt_pcb_t *pcb, dt_node_t *dnp)
|
|||||||
{
|
{
|
||||||
dif_instr_t instr;
|
dif_instr_t instr;
|
||||||
dt_xlator_t *dxp;
|
dt_xlator_t *dxp;
|
||||||
dt_ident_t *idp;
|
|
||||||
|
|
||||||
if (pcb->pcb_regs == NULL && (pcb->pcb_regs =
|
if (pcb->pcb_regs == NULL && (pcb->pcb_regs =
|
||||||
dt_regset_create(pcb->pcb_hdl->dt_conf.dtc_difintregs)) == NULL)
|
dt_regset_create(pcb->pcb_hdl->dt_conf.dtc_difintregs)) == NULL)
|
||||||
@ -2144,9 +1976,9 @@ dt_cg(dt_pcb_t *pcb, dt_node_t *dnp)
|
|||||||
assert(pcb->pcb_dret == NULL);
|
assert(pcb->pcb_dret == NULL);
|
||||||
pcb->pcb_dret = dnp;
|
pcb->pcb_dret = dnp;
|
||||||
|
|
||||||
if (dt_node_resolve(dnp, DT_IDENT_XLPTR) != NULL) {
|
if (dt_node_is_dynamic(dnp)) {
|
||||||
dnerror(dnp, D_CG_DYN, "expression cannot evaluate to result "
|
dnerror(dnp, D_CG_DYN, "expression cannot evaluate to result "
|
||||||
"of a translated pointer\n");
|
"of dynamic type\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -2162,14 +1994,6 @@ dt_cg(dt_pcb_t *pcb, dt_node_t *dnp)
|
|||||||
}
|
}
|
||||||
|
|
||||||
dt_cg_node(dnp, &pcb->pcb_ir, pcb->pcb_regs);
|
dt_cg_node(dnp, &pcb->pcb_ir, pcb->pcb_regs);
|
||||||
|
|
||||||
if ((idp = dt_node_resolve(dnp, DT_IDENT_XLSOU)) != NULL) {
|
|
||||||
int reg = dt_cg_xlate_expand(dnp, idp,
|
|
||||||
&pcb->pcb_ir, pcb->pcb_regs);
|
|
||||||
dt_regset_free(pcb->pcb_regs, dnp->dn_reg);
|
|
||||||
dnp->dn_reg = reg;
|
|
||||||
}
|
|
||||||
|
|
||||||
instr = DIF_INSTR_RET(dnp->dn_reg);
|
instr = DIF_INSTR_RET(dnp->dn_reg);
|
||||||
dt_regset_free(pcb->pcb_regs, dnp->dn_reg);
|
dt_regset_free(pcb->pcb_regs, dnp->dn_reg);
|
||||||
dt_irlist_append(&pcb->pcb_ir, dt_cg_node_alloc(DT_LBL_NONE, instr));
|
dt_irlist_append(&pcb->pcb_ir, dt_cg_node_alloc(DT_LBL_NONE, instr));
|
||||||
@ -2179,7 +2003,4 @@ dt_cg(dt_pcb_t *pcb, dt_node_t *dnp)
|
|||||||
dxp->dx_ident->di_id = 0;
|
dxp->dx_ident->di_id = 0;
|
||||||
dxp->dx_ident->di_flags &= ~DT_IDFLG_CGREG;
|
dxp->dx_ident->di_flags &= ~DT_IDFLG_CGREG;
|
||||||
}
|
}
|
||||||
|
|
||||||
dt_regset_free(pcb->pcb_regs, 0);
|
|
||||||
dt_regset_assert_free(pcb->pcb_regs);
|
|
||||||
}
|
}
|
||||||
|
@ -25,7 +25,7 @@
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2011, Joyent, Inc. All rights reserved.
|
* Copyright (c) 2011, Joyent, Inc. All rights reserved.
|
||||||
* Copyright (c) 2012 by Delphix. All rights reserved.
|
* Copyright (c) 2011 by Delphix. All rights reserved.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
@ -39,7 +39,6 @@
|
|||||||
#include <alloca.h>
|
#include <alloca.h>
|
||||||
#endif
|
#endif
|
||||||
#include <dt_impl.h>
|
#include <dt_impl.h>
|
||||||
#include <dt_pq.h>
|
|
||||||
#if !defined(sun)
|
#if !defined(sun)
|
||||||
#include <libproc_compat.h>
|
#include <libproc_compat.h>
|
||||||
#endif
|
#endif
|
||||||
@ -444,8 +443,17 @@ dt_flowindent(dtrace_hdl_t *dtp, dtrace_probedata_t *data, dtrace_epid_t last,
|
|||||||
offs += epd->dtepd_size;
|
offs += epd->dtepd_size;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
if (offs >= buf->dtbd_size)
|
if (offs >= buf->dtbd_size) {
|
||||||
|
/*
|
||||||
|
* We're at the end -- maybe. If the oldest
|
||||||
|
* record is non-zero, we need to wrap.
|
||||||
|
*/
|
||||||
|
if (buf->dtbd_oldest != 0) {
|
||||||
|
offs = 0;
|
||||||
|
} else {
|
||||||
goto out;
|
goto out;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
next = *(uint32_t *)((uintptr_t)buf->dtbd_data + offs);
|
next = *(uint32_t *)((uintptr_t)buf->dtbd_data + offs);
|
||||||
|
|
||||||
@ -2006,27 +2014,26 @@ dt_setopt(dtrace_hdl_t *dtp, const dtrace_probedata_t *data,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
dt_consume_cpu(dtrace_hdl_t *dtp, FILE *fp, int cpu,
|
dt_consume_cpu(dtrace_hdl_t *dtp, FILE *fp, int cpu, dtrace_bufdesc_t *buf,
|
||||||
dtrace_bufdesc_t *buf, boolean_t just_one,
|
|
||||||
dtrace_consume_probe_f *efunc, dtrace_consume_rec_f *rfunc, void *arg)
|
dtrace_consume_probe_f *efunc, dtrace_consume_rec_f *rfunc, void *arg)
|
||||||
{
|
{
|
||||||
dtrace_epid_t id;
|
dtrace_epid_t id;
|
||||||
size_t offs;
|
size_t offs, start = buf->dtbd_oldest, end = buf->dtbd_size;
|
||||||
int flow = (dtp->dt_options[DTRACEOPT_FLOWINDENT] != DTRACEOPT_UNSET);
|
int flow = (dtp->dt_options[DTRACEOPT_FLOWINDENT] != DTRACEOPT_UNSET);
|
||||||
int quiet = (dtp->dt_options[DTRACEOPT_QUIET] != DTRACEOPT_UNSET);
|
int quiet = (dtp->dt_options[DTRACEOPT_QUIET] != DTRACEOPT_UNSET);
|
||||||
int rval, i, n;
|
int rval, i, n;
|
||||||
|
dtrace_epid_t last = DTRACE_EPIDNONE;
|
||||||
uint64_t tracememsize = 0;
|
uint64_t tracememsize = 0;
|
||||||
dtrace_probedata_t data;
|
dtrace_probedata_t data;
|
||||||
uint64_t drops;
|
uint64_t drops;
|
||||||
|
caddr_t addr;
|
||||||
|
|
||||||
bzero(&data, sizeof (data));
|
bzero(&data, sizeof (data));
|
||||||
data.dtpda_handle = dtp;
|
data.dtpda_handle = dtp;
|
||||||
data.dtpda_cpu = cpu;
|
data.dtpda_cpu = cpu;
|
||||||
data.dtpda_flow = dtp->dt_flow;
|
|
||||||
data.dtpda_indent = dtp->dt_indent;
|
|
||||||
data.dtpda_prefix = dtp->dt_prefix;
|
|
||||||
|
|
||||||
for (offs = buf->dtbd_oldest; offs < buf->dtbd_size; ) {
|
again:
|
||||||
|
for (offs = start; offs < end; ) {
|
||||||
dtrace_eprobedesc_t *epd;
|
dtrace_eprobedesc_t *epd;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -2061,8 +2068,7 @@ dt_consume_cpu(dtrace_hdl_t *dtp, FILE *fp, int cpu,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (flow)
|
if (flow)
|
||||||
(void) dt_flowindent(dtp, &data, dtp->dt_last_epid,
|
(void) dt_flowindent(dtp, &data, last, buf, offs);
|
||||||
buf, offs);
|
|
||||||
|
|
||||||
rval = (*efunc)(&data, arg);
|
rval = (*efunc)(&data, arg);
|
||||||
|
|
||||||
@ -2081,7 +2087,6 @@ dt_consume_cpu(dtrace_hdl_t *dtp, FILE *fp, int cpu,
|
|||||||
return (dt_set_errno(dtp, EDT_BADRVAL));
|
return (dt_set_errno(dtp, EDT_BADRVAL));
|
||||||
|
|
||||||
for (i = 0; i < epd->dtepd_nrecs; i++) {
|
for (i = 0; i < epd->dtepd_nrecs; i++) {
|
||||||
caddr_t addr;
|
|
||||||
dtrace_recdesc_t *rec = &epd->dtepd_rec[i];
|
dtrace_recdesc_t *rec = &epd->dtepd_rec[i];
|
||||||
dtrace_actkind_t act = rec->dtrd_action;
|
dtrace_actkind_t act = rec->dtrd_action;
|
||||||
|
|
||||||
@ -2453,16 +2458,14 @@ dt_consume_cpu(dtrace_hdl_t *dtp, FILE *fp, int cpu,
|
|||||||
rval = (*rfunc)(&data, NULL, arg);
|
rval = (*rfunc)(&data, NULL, arg);
|
||||||
nextepid:
|
nextepid:
|
||||||
offs += epd->dtepd_size;
|
offs += epd->dtepd_size;
|
||||||
dtp->dt_last_epid = id;
|
last = id;
|
||||||
if (just_one) {
|
|
||||||
buf->dtbd_oldest = offs;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
dtp->dt_flow = data.dtpda_flow;
|
if (buf->dtbd_oldest != 0 && start == buf->dtbd_oldest) {
|
||||||
dtp->dt_indent = data.dtpda_indent;
|
end = buf->dtbd_oldest;
|
||||||
dtp->dt_prefix = data.dtpda_prefix;
|
start = 0;
|
||||||
|
goto again;
|
||||||
|
}
|
||||||
|
|
||||||
if ((drops = buf->dtbd_drops) == 0)
|
if ((drops = buf->dtbd_drops) == 0)
|
||||||
return (0);
|
return (0);
|
||||||
@ -2475,130 +2478,6 @@ dt_consume_cpu(dtrace_hdl_t *dtp, FILE *fp, int cpu,
|
|||||||
return (dt_handle_cpudrop(dtp, cpu, DTRACEDROP_PRINCIPAL, drops));
|
return (dt_handle_cpudrop(dtp, cpu, DTRACEDROP_PRINCIPAL, drops));
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Reduce memory usage by shrinking the buffer if it's no more than half full.
|
|
||||||
* Note, we need to preserve the alignment of the data at dtbd_oldest, which is
|
|
||||||
* only 4-byte aligned.
|
|
||||||
*/
|
|
||||||
static void
|
|
||||||
dt_realloc_buf(dtrace_hdl_t *dtp, dtrace_bufdesc_t *buf, int cursize)
|
|
||||||
{
|
|
||||||
uint64_t used = buf->dtbd_size - buf->dtbd_oldest;
|
|
||||||
if (used < cursize / 2) {
|
|
||||||
int misalign = buf->dtbd_oldest & (sizeof (uint64_t) - 1);
|
|
||||||
char *newdata = dt_alloc(dtp, used + misalign);
|
|
||||||
if (newdata == NULL)
|
|
||||||
return;
|
|
||||||
bzero(newdata, misalign);
|
|
||||||
bcopy(buf->dtbd_data + buf->dtbd_oldest,
|
|
||||||
newdata + misalign, used);
|
|
||||||
dt_free(dtp, buf->dtbd_data);
|
|
||||||
buf->dtbd_oldest = misalign;
|
|
||||||
buf->dtbd_size = used + misalign;
|
|
||||||
buf->dtbd_data = newdata;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* If the ring buffer has wrapped, the data is not in order. Rearrange it
|
|
||||||
* so that it is. Note, we need to preserve the alignment of the data at
|
|
||||||
* dtbd_oldest, which is only 4-byte aligned.
|
|
||||||
*/
|
|
||||||
static int
|
|
||||||
dt_unring_buf(dtrace_hdl_t *dtp, dtrace_bufdesc_t *buf)
|
|
||||||
{
|
|
||||||
int misalign;
|
|
||||||
char *newdata, *ndp;
|
|
||||||
|
|
||||||
if (buf->dtbd_oldest == 0)
|
|
||||||
return (0);
|
|
||||||
|
|
||||||
misalign = buf->dtbd_oldest & (sizeof (uint64_t) - 1);
|
|
||||||
newdata = ndp = dt_alloc(dtp, buf->dtbd_size + misalign);
|
|
||||||
|
|
||||||
if (newdata == NULL)
|
|
||||||
return (-1);
|
|
||||||
|
|
||||||
assert(0 == (buf->dtbd_size & (sizeof (uint64_t) - 1)));
|
|
||||||
|
|
||||||
bzero(ndp, misalign);
|
|
||||||
ndp += misalign;
|
|
||||||
|
|
||||||
bcopy(buf->dtbd_data + buf->dtbd_oldest, ndp,
|
|
||||||
buf->dtbd_size - buf->dtbd_oldest);
|
|
||||||
ndp += buf->dtbd_size - buf->dtbd_oldest;
|
|
||||||
|
|
||||||
bcopy(buf->dtbd_data, ndp, buf->dtbd_oldest);
|
|
||||||
|
|
||||||
dt_free(dtp, buf->dtbd_data);
|
|
||||||
buf->dtbd_oldest = 0;
|
|
||||||
buf->dtbd_data = newdata;
|
|
||||||
buf->dtbd_size += misalign;
|
|
||||||
|
|
||||||
return (0);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
dt_put_buf(dtrace_hdl_t *dtp, dtrace_bufdesc_t *buf)
|
|
||||||
{
|
|
||||||
dt_free(dtp, buf->dtbd_data);
|
|
||||||
dt_free(dtp, buf);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Returns 0 on success, in which case *cbp will be filled in if we retrieved
|
|
||||||
* data, or NULL if there is no data for this CPU.
|
|
||||||
* Returns -1 on failure and sets dt_errno.
|
|
||||||
*/
|
|
||||||
static int
|
|
||||||
dt_get_buf(dtrace_hdl_t *dtp, int cpu, dtrace_bufdesc_t **bufp)
|
|
||||||
{
|
|
||||||
dtrace_optval_t size;
|
|
||||||
dtrace_bufdesc_t *buf = dt_zalloc(dtp, sizeof (*buf));
|
|
||||||
int error;
|
|
||||||
|
|
||||||
if (buf == NULL)
|
|
||||||
return (-1);
|
|
||||||
|
|
||||||
(void) dtrace_getopt(dtp, "bufsize", &size);
|
|
||||||
buf->dtbd_data = dt_alloc(dtp, size);
|
|
||||||
if (buf->dtbd_data == NULL) {
|
|
||||||
dt_free(dtp, buf);
|
|
||||||
return (-1);
|
|
||||||
}
|
|
||||||
buf->dtbd_size = size;
|
|
||||||
buf->dtbd_cpu = cpu;
|
|
||||||
|
|
||||||
#if defined(sun)
|
|
||||||
if (dt_ioctl(dtp, DTRACEIOC_BUFSNAP, buf) == -1) {
|
|
||||||
#else
|
|
||||||
if (dt_ioctl(dtp, DTRACEIOC_BUFSNAP, &buf) == -1) {
|
|
||||||
#endif
|
|
||||||
dt_put_buf(dtp, buf);
|
|
||||||
/*
|
|
||||||
* If we failed with ENOENT, it may be because the
|
|
||||||
* CPU was unconfigured -- this is okay. Any other
|
|
||||||
* error, however, is unexpected.
|
|
||||||
*/
|
|
||||||
if (errno == ENOENT) {
|
|
||||||
*bufp = NULL;
|
|
||||||
return (0);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (dt_set_errno(dtp, errno));
|
|
||||||
}
|
|
||||||
|
|
||||||
error = dt_unring_buf(dtp, buf);
|
|
||||||
if (error != 0) {
|
|
||||||
dt_put_buf(dtp, buf);
|
|
||||||
return (error);
|
|
||||||
}
|
|
||||||
dt_realloc_buf(dtp, buf, size);
|
|
||||||
|
|
||||||
*bufp = buf;
|
|
||||||
return (0);
|
|
||||||
}
|
|
||||||
|
|
||||||
typedef struct dt_begin {
|
typedef struct dt_begin {
|
||||||
dtrace_consume_probe_f *dtbgn_probefunc;
|
dtrace_consume_probe_f *dtbgn_probefunc;
|
||||||
dtrace_consume_rec_f *dtbgn_recfunc;
|
dtrace_consume_rec_f *dtbgn_recfunc;
|
||||||
@ -2611,7 +2490,7 @@ typedef struct dt_begin {
|
|||||||
static int
|
static int
|
||||||
dt_consume_begin_probe(const dtrace_probedata_t *data, void *arg)
|
dt_consume_begin_probe(const dtrace_probedata_t *data, void *arg)
|
||||||
{
|
{
|
||||||
dt_begin_t *begin = arg;
|
dt_begin_t *begin = (dt_begin_t *)arg;
|
||||||
dtrace_probedesc_t *pd = data->dtpda_pdesc;
|
dtrace_probedesc_t *pd = data->dtpda_pdesc;
|
||||||
|
|
||||||
int r1 = (strcmp(pd->dtpd_provider, "dtrace") == 0);
|
int r1 = (strcmp(pd->dtpd_provider, "dtrace") == 0);
|
||||||
@ -2636,7 +2515,7 @@ static int
|
|||||||
dt_consume_begin_record(const dtrace_probedata_t *data,
|
dt_consume_begin_record(const dtrace_probedata_t *data,
|
||||||
const dtrace_recdesc_t *rec, void *arg)
|
const dtrace_recdesc_t *rec, void *arg)
|
||||||
{
|
{
|
||||||
dt_begin_t *begin = arg;
|
dt_begin_t *begin = (dt_begin_t *)arg;
|
||||||
|
|
||||||
return (begin->dtbgn_recfunc(data, rec, begin->dtbgn_arg));
|
return (begin->dtbgn_recfunc(data, rec, begin->dtbgn_arg));
|
||||||
}
|
}
|
||||||
@ -2662,7 +2541,7 @@ dt_consume_begin_error(const dtrace_errdata_t *data, void *arg)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
dt_consume_begin(dtrace_hdl_t *dtp, FILE *fp,
|
dt_consume_begin(dtrace_hdl_t *dtp, FILE *fp, dtrace_bufdesc_t *buf,
|
||||||
dtrace_consume_probe_f *pf, dtrace_consume_rec_f *rf, void *arg)
|
dtrace_consume_probe_f *pf, dtrace_consume_rec_f *rf, void *arg)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
@ -2686,30 +2565,41 @@ dt_consume_begin(dtrace_hdl_t *dtp, FILE *fp,
|
|||||||
* first pass, and that we only process ERROR enablings _not_ induced
|
* first pass, and that we only process ERROR enablings _not_ induced
|
||||||
* by BEGIN enablings in the second pass.
|
* by BEGIN enablings in the second pass.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
dt_begin_t begin;
|
dt_begin_t begin;
|
||||||
processorid_t cpu = dtp->dt_beganon;
|
processorid_t cpu = dtp->dt_beganon;
|
||||||
|
dtrace_bufdesc_t nbuf;
|
||||||
|
#if !defined(sun)
|
||||||
|
dtrace_bufdesc_t *pbuf;
|
||||||
|
#endif
|
||||||
int rval, i;
|
int rval, i;
|
||||||
static int max_ncpus;
|
static int max_ncpus;
|
||||||
dtrace_bufdesc_t *buf;
|
dtrace_optval_t size;
|
||||||
|
|
||||||
dtp->dt_beganon = -1;
|
dtp->dt_beganon = -1;
|
||||||
|
|
||||||
if (dt_get_buf(dtp, cpu, &buf) != 0)
|
#if defined(sun)
|
||||||
return (-1);
|
if (dt_ioctl(dtp, DTRACEIOC_BUFSNAP, buf) == -1) {
|
||||||
if (buf == NULL)
|
#else
|
||||||
|
if (dt_ioctl(dtp, DTRACEIOC_BUFSNAP, &buf) == -1) {
|
||||||
|
#endif
|
||||||
|
/*
|
||||||
|
* We really don't expect this to fail, but it is at least
|
||||||
|
* technically possible for this to fail with ENOENT. In this
|
||||||
|
* case, we just drive on...
|
||||||
|
*/
|
||||||
|
if (errno == ENOENT)
|
||||||
return (0);
|
return (0);
|
||||||
|
|
||||||
|
return (dt_set_errno(dtp, errno));
|
||||||
|
}
|
||||||
|
|
||||||
if (!dtp->dt_stopped || buf->dtbd_cpu != dtp->dt_endedon) {
|
if (!dtp->dt_stopped || buf->dtbd_cpu != dtp->dt_endedon) {
|
||||||
/*
|
/*
|
||||||
* This is the simple case. We're either not stopped, or if
|
* This is the simple case. We're either not stopped, or if
|
||||||
* we are, we actually processed any END probes on another
|
* we are, we actually processed any END probes on another
|
||||||
* CPU. We can simply consume this buffer and return.
|
* CPU. We can simply consume this buffer and return.
|
||||||
*/
|
*/
|
||||||
rval = dt_consume_cpu(dtp, fp, cpu, buf, B_FALSE,
|
return (dt_consume_cpu(dtp, fp, cpu, buf, pf, rf, arg));
|
||||||
pf, rf, arg);
|
|
||||||
dt_put_buf(dtp, buf);
|
|
||||||
return (rval);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
begin.dtbgn_probefunc = pf;
|
begin.dtbgn_probefunc = pf;
|
||||||
@ -2726,41 +2616,61 @@ dt_consume_begin(dtrace_hdl_t *dtp, FILE *fp,
|
|||||||
dtp->dt_errhdlr = dt_consume_begin_error;
|
dtp->dt_errhdlr = dt_consume_begin_error;
|
||||||
dtp->dt_errarg = &begin;
|
dtp->dt_errarg = &begin;
|
||||||
|
|
||||||
rval = dt_consume_cpu(dtp, fp, cpu, buf, B_FALSE,
|
rval = dt_consume_cpu(dtp, fp, cpu, buf, dt_consume_begin_probe,
|
||||||
dt_consume_begin_probe, dt_consume_begin_record, &begin);
|
dt_consume_begin_record, &begin);
|
||||||
|
|
||||||
dtp->dt_errhdlr = begin.dtbgn_errhdlr;
|
dtp->dt_errhdlr = begin.dtbgn_errhdlr;
|
||||||
dtp->dt_errarg = begin.dtbgn_errarg;
|
dtp->dt_errarg = begin.dtbgn_errarg;
|
||||||
|
|
||||||
if (rval != 0) {
|
if (rval != 0)
|
||||||
dt_put_buf(dtp, buf);
|
|
||||||
return (rval);
|
return (rval);
|
||||||
}
|
|
||||||
|
/*
|
||||||
|
* Now allocate a new buffer. We'll use this to deal with every other
|
||||||
|
* CPU.
|
||||||
|
*/
|
||||||
|
bzero(&nbuf, sizeof (dtrace_bufdesc_t));
|
||||||
|
(void) dtrace_getopt(dtp, "bufsize", &size);
|
||||||
|
if ((nbuf.dtbd_data = malloc(size)) == NULL)
|
||||||
|
return (dt_set_errno(dtp, EDT_NOMEM));
|
||||||
|
|
||||||
if (max_ncpus == 0)
|
if (max_ncpus == 0)
|
||||||
max_ncpus = dt_sysconf(dtp, _SC_CPUID_MAX) + 1;
|
max_ncpus = dt_sysconf(dtp, _SC_CPUID_MAX) + 1;
|
||||||
|
|
||||||
for (i = 0; i < max_ncpus; i++) {
|
for (i = 0; i < max_ncpus; i++) {
|
||||||
dtrace_bufdesc_t *nbuf;
|
nbuf.dtbd_cpu = i;
|
||||||
|
|
||||||
if (i == cpu)
|
if (i == cpu)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (dt_get_buf(dtp, i, &nbuf) != 0) {
|
#if defined(sun)
|
||||||
dt_put_buf(dtp, buf);
|
if (dt_ioctl(dtp, DTRACEIOC_BUFSNAP, &nbuf) == -1) {
|
||||||
return (-1);
|
#else
|
||||||
}
|
pbuf = &nbuf;
|
||||||
if (nbuf == NULL)
|
if (dt_ioctl(dtp, DTRACEIOC_BUFSNAP, &pbuf) == -1) {
|
||||||
|
#endif
|
||||||
|
/*
|
||||||
|
* If we failed with ENOENT, it may be because the
|
||||||
|
* CPU was unconfigured -- this is okay. Any other
|
||||||
|
* error, however, is unexpected.
|
||||||
|
*/
|
||||||
|
if (errno == ENOENT)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
rval = dt_consume_cpu(dtp, fp, i, nbuf, B_FALSE,
|
free(nbuf.dtbd_data);
|
||||||
pf, rf, arg);
|
|
||||||
dt_put_buf(dtp, nbuf);
|
return (dt_set_errno(dtp, errno));
|
||||||
if (rval != 0) {
|
}
|
||||||
dt_put_buf(dtp, buf);
|
|
||||||
|
if ((rval = dt_consume_cpu(dtp, fp,
|
||||||
|
i, &nbuf, pf, rf, arg)) != 0) {
|
||||||
|
free(nbuf.dtbd_data);
|
||||||
return (rval);
|
return (rval);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
free(nbuf.dtbd_data);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Okay -- we're done with the other buffers. Now we want to
|
* Okay -- we're done with the other buffers. Now we want to
|
||||||
* reconsume the first buffer -- but this time we're looking for
|
* reconsume the first buffer -- but this time we're looking for
|
||||||
@ -2775,8 +2685,8 @@ dt_consume_begin(dtrace_hdl_t *dtp, FILE *fp,
|
|||||||
dtp->dt_errhdlr = dt_consume_begin_error;
|
dtp->dt_errhdlr = dt_consume_begin_error;
|
||||||
dtp->dt_errarg = &begin;
|
dtp->dt_errarg = &begin;
|
||||||
|
|
||||||
rval = dt_consume_cpu(dtp, fp, cpu, buf, B_FALSE,
|
rval = dt_consume_cpu(dtp, fp, cpu, buf, dt_consume_begin_probe,
|
||||||
dt_consume_begin_probe, dt_consume_begin_record, &begin);
|
dt_consume_begin_record, &begin);
|
||||||
|
|
||||||
dtp->dt_errhdlr = begin.dtbgn_errhdlr;
|
dtp->dt_errhdlr = begin.dtbgn_errhdlr;
|
||||||
dtp->dt_errarg = begin.dtbgn_errarg;
|
dtp->dt_errarg = begin.dtbgn_errarg;
|
||||||
@ -2784,32 +2694,11 @@ dt_consume_begin(dtrace_hdl_t *dtp, FILE *fp,
|
|||||||
return (rval);
|
return (rval);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ARGSUSED */
|
|
||||||
static uint64_t
|
|
||||||
dt_buf_oldest(void *elem, void *arg)
|
|
||||||
{
|
|
||||||
dtrace_bufdesc_t *buf = elem;
|
|
||||||
size_t offs = buf->dtbd_oldest;
|
|
||||||
|
|
||||||
while (offs < buf->dtbd_size) {
|
|
||||||
dtrace_rechdr_t *dtrh =
|
|
||||||
/* LINTED - alignment */
|
|
||||||
(dtrace_rechdr_t *)(buf->dtbd_data + offs);
|
|
||||||
if (dtrh->dtrh_epid == DTRACE_EPIDNONE) {
|
|
||||||
offs += sizeof (dtrace_epid_t);
|
|
||||||
} else {
|
|
||||||
return (DTRACE_RECORD_LOAD_TIMESTAMP(dtrh));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* There are no records left; use the time the buffer was retrieved. */
|
|
||||||
return (buf->dtbd_timestamp);
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
int
|
||||||
dtrace_consume(dtrace_hdl_t *dtp, FILE *fp,
|
dtrace_consume(dtrace_hdl_t *dtp, FILE *fp,
|
||||||
dtrace_consume_probe_f *pf, dtrace_consume_rec_f *rf, void *arg)
|
dtrace_consume_probe_f *pf, dtrace_consume_rec_f *rf, void *arg)
|
||||||
{
|
{
|
||||||
|
dtrace_bufdesc_t *buf = &dtp->dt_buf;
|
||||||
dtrace_optval_t size;
|
dtrace_optval_t size;
|
||||||
static int max_ncpus;
|
static int max_ncpus;
|
||||||
int i, rval;
|
int i, rval;
|
||||||
@ -2837,158 +2726,79 @@ dtrace_consume(dtrace_hdl_t *dtp, FILE *fp,
|
|||||||
if (rf == NULL)
|
if (rf == NULL)
|
||||||
rf = (dtrace_consume_rec_f *)dt_nullrec;
|
rf = (dtrace_consume_rec_f *)dt_nullrec;
|
||||||
|
|
||||||
if (dtp->dt_options[DTRACEOPT_TEMPORAL] == DTRACEOPT_UNSET) {
|
if (buf->dtbd_data == NULL) {
|
||||||
|
(void) dtrace_getopt(dtp, "bufsize", &size);
|
||||||
|
if ((buf->dtbd_data = malloc(size)) == NULL)
|
||||||
|
return (dt_set_errno(dtp, EDT_NOMEM));
|
||||||
|
|
||||||
|
buf->dtbd_size = size;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The output will not be in the order it was traced. Rather,
|
|
||||||
* we will consume all of the data from each CPU's buffer in
|
|
||||||
* turn. We apply special handling for the records from BEGIN
|
|
||||||
* and END probes so that they are consumed first and last,
|
|
||||||
* respectively.
|
|
||||||
*
|
|
||||||
* If we have just begun, we want to first process the CPU that
|
* If we have just begun, we want to first process the CPU that
|
||||||
* executed the BEGIN probe (if any).
|
* executed the BEGIN probe (if any).
|
||||||
*/
|
*/
|
||||||
if (dtp->dt_active && dtp->dt_beganon != -1 &&
|
if (dtp->dt_active && dtp->dt_beganon != -1) {
|
||||||
(rval = dt_consume_begin(dtp, fp, pf, rf, arg)) != 0)
|
buf->dtbd_cpu = dtp->dt_beganon;
|
||||||
|
if ((rval = dt_consume_begin(dtp, fp, buf, pf, rf, arg)) != 0)
|
||||||
return (rval);
|
return (rval);
|
||||||
|
}
|
||||||
|
|
||||||
for (i = 0; i < max_ncpus; i++) {
|
for (i = 0; i < max_ncpus; i++) {
|
||||||
dtrace_bufdesc_t *buf;
|
buf->dtbd_cpu = i;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If we have stopped, we want to process the CPU on
|
* If we have stopped, we want to process the CPU on which the
|
||||||
* which the END probe was processed only _after_ we
|
* END probe was processed only _after_ we have processed
|
||||||
* have processed everything else.
|
* everything else.
|
||||||
*/
|
*/
|
||||||
if (dtp->dt_stopped && (i == dtp->dt_endedon))
|
if (dtp->dt_stopped && (i == dtp->dt_endedon))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (dt_get_buf(dtp, i, &buf) != 0)
|
#if defined(sun)
|
||||||
return (-1);
|
if (dt_ioctl(dtp, DTRACEIOC_BUFSNAP, buf) == -1) {
|
||||||
if (buf == NULL)
|
#else
|
||||||
|
if (dt_ioctl(dtp, DTRACEIOC_BUFSNAP, &buf) == -1) {
|
||||||
|
#endif
|
||||||
|
/*
|
||||||
|
* If we failed with ENOENT, it may be because the
|
||||||
|
* CPU was unconfigured -- this is okay. Any other
|
||||||
|
* error, however, is unexpected.
|
||||||
|
*/
|
||||||
|
if (errno == ENOENT)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
dtp->dt_flow = 0;
|
return (dt_set_errno(dtp, errno));
|
||||||
dtp->dt_indent = 0;
|
}
|
||||||
dtp->dt_prefix = NULL;
|
|
||||||
rval = dt_consume_cpu(dtp, fp, i,
|
if ((rval = dt_consume_cpu(dtp, fp, i, buf, pf, rf, arg)) != 0)
|
||||||
buf, B_FALSE, pf, rf, arg);
|
|
||||||
dt_put_buf(dtp, buf);
|
|
||||||
if (rval != 0)
|
|
||||||
return (rval);
|
return (rval);
|
||||||
}
|
}
|
||||||
if (dtp->dt_stopped) {
|
|
||||||
dtrace_bufdesc_t *buf;
|
|
||||||
|
|
||||||
if (dt_get_buf(dtp, dtp->dt_endedon, &buf) != 0)
|
if (!dtp->dt_stopped)
|
||||||
return (-1);
|
|
||||||
if (buf == NULL)
|
|
||||||
return (0);
|
return (0);
|
||||||
|
|
||||||
rval = dt_consume_cpu(dtp, fp, dtp->dt_endedon,
|
buf->dtbd_cpu = dtp->dt_endedon;
|
||||||
buf, B_FALSE, pf, rf, arg);
|
|
||||||
dt_put_buf(dtp, buf);
|
#if defined(sun)
|
||||||
return (rval);
|
if (dt_ioctl(dtp, DTRACEIOC_BUFSNAP, buf) == -1) {
|
||||||
}
|
#else
|
||||||
} else {
|
if (dt_ioctl(dtp, DTRACEIOC_BUFSNAP, &buf) == -1) {
|
||||||
|
#endif
|
||||||
/*
|
/*
|
||||||
* The output will be in the order it was traced (or for
|
* This _really_ shouldn't fail, but it is strictly speaking
|
||||||
* speculations, when it was committed). We retrieve a buffer
|
* possible for this to return ENOENT if the CPU that called
|
||||||
* from each CPU and put it into a priority queue, which sorts
|
* the END enabling somehow managed to become unconfigured.
|
||||||
* based on the first entry in the buffer. This is sufficient
|
* It's unclear how the user can possibly expect anything
|
||||||
* because entries within a buffer are already sorted.
|
* rational to happen in this case -- the state has been thrown
|
||||||
*
|
* out along with the unconfigured CPU -- so we'll just drive
|
||||||
* We then consume records one at a time, always consuming the
|
* on...
|
||||||
* oldest record, as determined by the priority queue. When
|
|
||||||
* we reach the end of the time covered by these buffers,
|
|
||||||
* we need to stop and retrieve more records on the next pass.
|
|
||||||
* The kernel tells us the time covered by each buffer, in
|
|
||||||
* dtbd_timestamp. The first buffer's timestamp tells us the
|
|
||||||
* time covered by all buffers, as subsequently retrieved
|
|
||||||
* buffers will cover to a more recent time.
|
|
||||||
*/
|
*/
|
||||||
|
if (errno == ENOENT)
|
||||||
uint64_t *drops = alloca(max_ncpus * sizeof (uint64_t));
|
|
||||||
uint64_t first_timestamp = 0;
|
|
||||||
uint_t cookie = 0;
|
|
||||||
dtrace_bufdesc_t *buf;
|
|
||||||
|
|
||||||
bzero(drops, max_ncpus * sizeof (uint64_t));
|
|
||||||
|
|
||||||
if (dtp->dt_bufq == NULL) {
|
|
||||||
dtp->dt_bufq = dt_pq_init(dtp, max_ncpus * 2,
|
|
||||||
dt_buf_oldest, NULL);
|
|
||||||
if (dtp->dt_bufq == NULL) /* ENOMEM */
|
|
||||||
return (-1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Retrieve data from each CPU. */
|
|
||||||
(void) dtrace_getopt(dtp, "bufsize", &size);
|
|
||||||
for (i = 0; i < max_ncpus; i++) {
|
|
||||||
dtrace_bufdesc_t *buf;
|
|
||||||
|
|
||||||
if (dt_get_buf(dtp, i, &buf) != 0)
|
|
||||||
return (-1);
|
|
||||||
if (buf != NULL) {
|
|
||||||
if (first_timestamp == 0)
|
|
||||||
first_timestamp = buf->dtbd_timestamp;
|
|
||||||
assert(buf->dtbd_timestamp >= first_timestamp);
|
|
||||||
|
|
||||||
dt_pq_insert(dtp->dt_bufq, buf);
|
|
||||||
drops[i] = buf->dtbd_drops;
|
|
||||||
buf->dtbd_drops = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Consume records. */
|
|
||||||
for (;;) {
|
|
||||||
dtrace_bufdesc_t *buf = dt_pq_pop(dtp->dt_bufq);
|
|
||||||
uint64_t timestamp;
|
|
||||||
|
|
||||||
if (buf == NULL)
|
|
||||||
break;
|
|
||||||
|
|
||||||
timestamp = dt_buf_oldest(buf, dtp);
|
|
||||||
/* XXX: assert(timestamp >= dtp->dt_last_timestamp); */
|
|
||||||
dtp->dt_last_timestamp = timestamp;
|
|
||||||
|
|
||||||
if (timestamp == buf->dtbd_timestamp) {
|
|
||||||
/*
|
|
||||||
* We've reached the end of the time covered
|
|
||||||
* by this buffer. If this is the oldest
|
|
||||||
* buffer, we must do another pass
|
|
||||||
* to retrieve more data.
|
|
||||||
*/
|
|
||||||
dt_put_buf(dtp, buf);
|
|
||||||
if (timestamp == first_timestamp &&
|
|
||||||
!dtp->dt_stopped)
|
|
||||||
break;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((rval = dt_consume_cpu(dtp, fp,
|
|
||||||
buf->dtbd_cpu, buf, B_TRUE, pf, rf, arg)) != 0)
|
|
||||||
return (rval);
|
|
||||||
dt_pq_insert(dtp->dt_bufq, buf);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Consume drops. */
|
|
||||||
for (i = 0; i < max_ncpus; i++) {
|
|
||||||
if (drops[i] != 0) {
|
|
||||||
int error = dt_handle_cpudrop(dtp, i,
|
|
||||||
DTRACEDROP_PRINCIPAL, drops[i]);
|
|
||||||
if (error != 0)
|
|
||||||
return (error);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Reduce memory usage by re-allocating smaller buffers
|
|
||||||
* for the "remnants".
|
|
||||||
*/
|
|
||||||
while (buf = dt_pq_walk(dtp->dt_bufq, &cookie))
|
|
||||||
dt_realloc_buf(dtp, buf, buf->dtbd_size);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (0);
|
return (0);
|
||||||
|
|
||||||
|
return (dt_set_errno(dtp, errno));
|
||||||
|
}
|
||||||
|
|
||||||
|
return (dt_consume_cpu(dtp, fp, dtp->dt_endedon, buf, pf, rf, arg));
|
||||||
}
|
}
|
||||||
|
@ -19,15 +19,12 @@
|
|||||||
*
|
*
|
||||||
* CDDL HEADER END
|
* CDDL HEADER END
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright 2005 Sun Microsystems, Inc. All rights reserved.
|
* Copyright 2005 Sun Microsystems, Inc. All rights reserved.
|
||||||
* Use is subject to license terms.
|
* Use is subject to license terms.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
#pragma ident "%Z%%M% %I% %E% SMI"
|
||||||
* Copyright (c) 2012 by Delphix. All rights reserved.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <strings.h>
|
#include <strings.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
@ -215,22 +212,12 @@ dt_dis_pushts(const dtrace_difo_t *dp,
|
|||||||
{
|
{
|
||||||
static const char *const tnames[] = { "D type", "string" };
|
static const char *const tnames[] = { "D type", "string" };
|
||||||
uint_t type = DIF_INSTR_TYPE(in);
|
uint_t type = DIF_INSTR_TYPE(in);
|
||||||
const char *pad;
|
|
||||||
|
|
||||||
if (DIF_INSTR_OP(in) == DIF_OP_PUSHTV) {
|
|
||||||
(void) fprintf(fp, "%-4s DT_TYPE(%u), %%r%u",
|
|
||||||
name, type, DIF_INSTR_RS(in));
|
|
||||||
pad = "\t\t";
|
|
||||||
} else {
|
|
||||||
(void) fprintf(fp, "%-4s DT_TYPE(%u), %%r%u, %%r%u",
|
(void) fprintf(fp, "%-4s DT_TYPE(%u), %%r%u, %%r%u",
|
||||||
name, type, DIF_INSTR_R2(in), DIF_INSTR_RS(in));
|
name, type, DIF_INSTR_R2(in), DIF_INSTR_RS(in));
|
||||||
pad = "\t";
|
|
||||||
}
|
|
||||||
|
|
||||||
if (type < sizeof (tnames) / sizeof (tnames[0])) {
|
if (type < sizeof (tnames) / sizeof (tnames[0]))
|
||||||
(void) fprintf(fp, "%s! DT_TYPE(%u) = %s", pad,
|
(void) fprintf(fp, "\t! DT_TYPE(%u) = %s", type, tnames[type]);
|
||||||
type, tnames[type]);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -18,16 +18,11 @@
|
|||||||
*
|
*
|
||||||
* CDDL HEADER END
|
* CDDL HEADER END
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright 2009 Sun Microsystems, Inc. All rights reserved.
|
* Copyright 2009 Sun Microsystems, Inc. All rights reserved.
|
||||||
* Use is subject to license terms.
|
* Use is subject to license terms.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
|
||||||
* Copyright (c) 2012 by Delphix. All rights reserved.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <strings.h>
|
#include <strings.h>
|
||||||
#include <dt_impl.h>
|
#include <dt_impl.h>
|
||||||
@ -42,6 +37,7 @@ static const struct {
|
|||||||
{ EDT_VERSREDUCED, "Requested version conflicts with earlier setting" },
|
{ EDT_VERSREDUCED, "Requested version conflicts with earlier setting" },
|
||||||
{ EDT_CTF, "Unexpected libctf error" },
|
{ EDT_CTF, "Unexpected libctf error" },
|
||||||
{ EDT_COMPILER, "Error in D program compilation" },
|
{ EDT_COMPILER, "Error in D program compilation" },
|
||||||
|
{ EDT_NOREG, "Insufficient registers to generate code" },
|
||||||
{ EDT_NOTUPREG, "Insufficient tuple registers to generate code" },
|
{ EDT_NOTUPREG, "Insufficient tuple registers to generate code" },
|
||||||
{ EDT_NOMEM, "Memory allocation failure" },
|
{ EDT_NOMEM, "Memory allocation failure" },
|
||||||
{ EDT_INT2BIG, "Integer constant table limit exceeded" },
|
{ EDT_INT2BIG, "Integer constant table limit exceeded" },
|
||||||
|
@ -26,7 +26,7 @@
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2011, Joyent, Inc. All rights reserved.
|
* Copyright (c) 2011, Joyent, Inc. All rights reserved.
|
||||||
* Copyright (c) 2012 by Delphix. All rights reserved.
|
* Copyright (c) 2011 by Delphix. All rights reserved.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef _DT_ERRTAGS_H
|
#ifndef _DT_ERRTAGS_H
|
||||||
@ -262,7 +262,6 @@ typedef enum {
|
|||||||
D_LLQUANT_FACTOREVEN, /* llquantize() bad # steps/factor */
|
D_LLQUANT_FACTOREVEN, /* llquantize() bad # steps/factor */
|
||||||
D_LLQUANT_FACTORSMALL, /* llquantize() magnitude too small */
|
D_LLQUANT_FACTORSMALL, /* llquantize() magnitude too small */
|
||||||
D_LLQUANT_MAGTOOBIG, /* llquantize() high mag too large */
|
D_LLQUANT_MAGTOOBIG, /* llquantize() high mag too large */
|
||||||
D_NOREG, /* no available internal registers */
|
|
||||||
D_PRINTM_ADDR, /* printm() memref bad type */
|
D_PRINTM_ADDR, /* printm() memref bad type */
|
||||||
D_PRINTM_SIZE, /* printm() size bad type */
|
D_PRINTM_SIZE, /* printm() size bad type */
|
||||||
D_PRINTT_ADDR, /* printt() typeref bad type */
|
D_PRINTT_ADDR, /* printt() typeref bad type */
|
||||||
|
@ -26,7 +26,7 @@
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2011, Joyent, Inc. All rights reserved.
|
* Copyright (c) 2011, Joyent, Inc. All rights reserved.
|
||||||
* Copyright (c) 2012 by Delphix. All rights reserved.
|
* Copyright (c) 2011 by Delphix. All rights reserved.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef _DT_IMPL_H
|
#ifndef _DT_IMPL_H
|
||||||
@ -64,7 +64,6 @@ extern "C" {
|
|||||||
#include <dt_proc.h>
|
#include <dt_proc.h>
|
||||||
#include <dt_dof.h>
|
#include <dt_dof.h>
|
||||||
#include <dt_pcb.h>
|
#include <dt_pcb.h>
|
||||||
#include <dt_pq.h>
|
|
||||||
|
|
||||||
struct dt_module; /* see below */
|
struct dt_module; /* see below */
|
||||||
struct dt_pfdict; /* see <dt_printf.h> */
|
struct dt_pfdict; /* see <dt_printf.h> */
|
||||||
@ -240,7 +239,6 @@ struct dtrace_hdl {
|
|||||||
uint_t dt_provbuckets; /* number of provider hash buckets */
|
uint_t dt_provbuckets; /* number of provider hash buckets */
|
||||||
uint_t dt_nprovs; /* number of providers in hash and list */
|
uint_t dt_nprovs; /* number of providers in hash and list */
|
||||||
dt_proc_hash_t *dt_procs; /* hash table of grabbed process handles */
|
dt_proc_hash_t *dt_procs; /* hash table of grabbed process handles */
|
||||||
char **dt_proc_env; /* additional environment variables */
|
|
||||||
dt_intdesc_t dt_ints[6]; /* cached integer type descriptions */
|
dt_intdesc_t dt_ints[6]; /* cached integer type descriptions */
|
||||||
ctf_id_t dt_type_func; /* cached CTF identifier for function type */
|
ctf_id_t dt_type_func; /* cached CTF identifier for function type */
|
||||||
ctf_id_t dt_type_fptr; /* cached CTF identifier for function pointer */
|
ctf_id_t dt_type_fptr; /* cached CTF identifier for function pointer */
|
||||||
@ -259,7 +257,7 @@ struct dtrace_hdl {
|
|||||||
int dt_maxstrdata; /* max strdata ID */
|
int dt_maxstrdata; /* max strdata ID */
|
||||||
char **dt_strdata; /* pointer to strdata array */
|
char **dt_strdata; /* pointer to strdata array */
|
||||||
dt_aggregate_t dt_aggregate; /* aggregate */
|
dt_aggregate_t dt_aggregate; /* aggregate */
|
||||||
dt_pq_t *dt_bufq; /* CPU-specific data queue */
|
dtrace_bufdesc_t dt_buf; /* staging buffer */
|
||||||
struct dt_pfdict *dt_pfdict; /* dictionary of printf conversions */
|
struct dt_pfdict *dt_pfdict; /* dictionary of printf conversions */
|
||||||
dt_version_t dt_vmax; /* optional ceiling on program API binding */
|
dt_version_t dt_vmax; /* optional ceiling on program API binding */
|
||||||
dtrace_attribute_t dt_amin; /* optional floor on program attributes */
|
dtrace_attribute_t dt_amin; /* optional floor on program attributes */
|
||||||
@ -328,11 +326,6 @@ struct dtrace_hdl {
|
|||||||
struct utsname dt_uts; /* uname(2) information for system */
|
struct utsname dt_uts; /* uname(2) information for system */
|
||||||
dt_list_t dt_lib_dep; /* scratch linked-list of lib dependencies */
|
dt_list_t dt_lib_dep; /* scratch linked-list of lib dependencies */
|
||||||
dt_list_t dt_lib_dep_sorted; /* dependency sorted library list */
|
dt_list_t dt_lib_dep_sorted; /* dependency sorted library list */
|
||||||
dtrace_flowkind_t dt_flow; /* flow kind */
|
|
||||||
const char *dt_prefix; /* recommended flow prefix */
|
|
||||||
int dt_indent; /* recommended flow indent */
|
|
||||||
dtrace_epid_t dt_last_epid; /* most recently consumed EPID */
|
|
||||||
uint64_t dt_last_timestamp; /* most recently consumed timestamp */
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -468,6 +461,7 @@ enum {
|
|||||||
EDT_VERSREDUCED, /* requested API version has been reduced */
|
EDT_VERSREDUCED, /* requested API version has been reduced */
|
||||||
EDT_CTF, /* libctf called failed (dt_ctferr has more) */
|
EDT_CTF, /* libctf called failed (dt_ctferr has more) */
|
||||||
EDT_COMPILER, /* error in D program compilation */
|
EDT_COMPILER, /* error in D program compilation */
|
||||||
|
EDT_NOREG, /* register allocation failure */
|
||||||
EDT_NOTUPREG, /* tuple register allocation failure */
|
EDT_NOTUPREG, /* tuple register allocation failure */
|
||||||
EDT_NOMEM, /* memory allocation failure */
|
EDT_NOMEM, /* memory allocation failure */
|
||||||
EDT_INT2BIG, /* integer limit exceeded */
|
EDT_INT2BIG, /* integer limit exceeded */
|
||||||
|
@ -22,7 +22,7 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||||
* Copyright (c) 2011, Joyent, Inc. All rights reserved.
|
* Copyright (c) 2011, Joyent, Inc. All rights reserved.
|
||||||
* Copyright (c) 2012 by Delphix. All rights reserved.
|
* Copyright (c) 2011 by Delphix. All rights reserved.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
@ -92,7 +92,7 @@
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* The version number should be increased for every customer visible release
|
* The version number should be increased for every customer visible release
|
||||||
* of DTrace. The major number should be incremented when a fundamental
|
* of Solaris. The major number should be incremented when a fundamental
|
||||||
* change has been made that would affect all consumers, and would reflect
|
* change has been made that would affect all consumers, and would reflect
|
||||||
* sweeping changes to DTrace or the D language. The minor number should be
|
* sweeping changes to DTrace or the D language. The minor number should be
|
||||||
* incremented when a change is introduced that could break scripts that had
|
* incremented when a change is introduced that could break scripts that had
|
||||||
@ -121,9 +121,8 @@
|
|||||||
#define DT_VERS_1_8 DT_VERSION_NUMBER(1, 8, 0)
|
#define DT_VERS_1_8 DT_VERSION_NUMBER(1, 8, 0)
|
||||||
#define DT_VERS_1_8_1 DT_VERSION_NUMBER(1, 8, 1)
|
#define DT_VERS_1_8_1 DT_VERSION_NUMBER(1, 8, 1)
|
||||||
#define DT_VERS_1_9 DT_VERSION_NUMBER(1, 9, 0)
|
#define DT_VERS_1_9 DT_VERSION_NUMBER(1, 9, 0)
|
||||||
#define DT_VERS_1_9_1 DT_VERSION_NUMBER(1, 9, 1)
|
#define DT_VERS_LATEST DT_VERS_1_9
|
||||||
#define DT_VERS_LATEST DT_VERS_1_9_1
|
#define DT_VERS_STRING "Sun D 1.9"
|
||||||
#define DT_VERS_STRING "Sun D 1.9.1"
|
|
||||||
|
|
||||||
const dt_version_t _dtrace_versions[] = {
|
const dt_version_t _dtrace_versions[] = {
|
||||||
DT_VERS_1_0, /* D API 1.0.0 (PSARC 2001/466) Solaris 10 FCS */
|
DT_VERS_1_0, /* D API 1.0.0 (PSARC 2001/466) Solaris 10 FCS */
|
||||||
@ -144,7 +143,6 @@ const dt_version_t _dtrace_versions[] = {
|
|||||||
DT_VERS_1_8, /* D API 1.8 */
|
DT_VERS_1_8, /* D API 1.8 */
|
||||||
DT_VERS_1_8_1, /* D API 1.8.1 */
|
DT_VERS_1_8_1, /* D API 1.8.1 */
|
||||||
DT_VERS_1_9, /* D API 1.9 */
|
DT_VERS_1_9, /* D API 1.9 */
|
||||||
DT_VERS_1_9_1, /* D API 1.9.1 */
|
|
||||||
0
|
0
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -1153,7 +1151,7 @@ dt_vopen(int version, int flags, int *errp,
|
|||||||
dtp->dt_mods = calloc(dtp->dt_modbuckets, sizeof (dt_module_t *));
|
dtp->dt_mods = calloc(dtp->dt_modbuckets, sizeof (dt_module_t *));
|
||||||
dtp->dt_provbuckets = _dtrace_strbuckets;
|
dtp->dt_provbuckets = _dtrace_strbuckets;
|
||||||
dtp->dt_provs = calloc(dtp->dt_provbuckets, sizeof (dt_provider_t *));
|
dtp->dt_provs = calloc(dtp->dt_provbuckets, sizeof (dt_provider_t *));
|
||||||
dt_proc_init(dtp);
|
dt_proc_hash_create(dtp);
|
||||||
dtp->dt_vmax = DT_VERS_LATEST;
|
dtp->dt_vmax = DT_VERS_LATEST;
|
||||||
dtp->dt_cpp_path = strdup(_dtrace_defcpp);
|
dtp->dt_cpp_path = strdup(_dtrace_defcpp);
|
||||||
dtp->dt_cpp_argv = malloc(sizeof (char *));
|
dtp->dt_cpp_argv = malloc(sizeof (char *));
|
||||||
@ -1167,9 +1165,8 @@ dt_vopen(int version, int flags, int *errp,
|
|||||||
(void) uname(&dtp->dt_uts);
|
(void) uname(&dtp->dt_uts);
|
||||||
|
|
||||||
if (dtp->dt_mods == NULL || dtp->dt_provs == NULL ||
|
if (dtp->dt_mods == NULL || dtp->dt_provs == NULL ||
|
||||||
dtp->dt_procs == NULL || dtp->dt_proc_env == NULL ||
|
dtp->dt_procs == NULL || dtp->dt_ld_path == NULL ||
|
||||||
dtp->dt_ld_path == NULL || dtp->dt_cpp_path == NULL ||
|
dtp->dt_cpp_path == NULL || dtp->dt_cpp_argv == NULL)
|
||||||
dtp->dt_cpp_argv == NULL)
|
|
||||||
return (set_open_errno(dtp, errp, EDT_NOMEM));
|
return (set_open_errno(dtp, errp, EDT_NOMEM));
|
||||||
|
|
||||||
for (i = 0; i < DTRACEOPT_MAX; i++)
|
for (i = 0; i < DTRACEOPT_MAX; i++)
|
||||||
@ -1581,7 +1578,7 @@ dtrace_close(dtrace_hdl_t *dtp)
|
|||||||
int i;
|
int i;
|
||||||
|
|
||||||
if (dtp->dt_procs != NULL)
|
if (dtp->dt_procs != NULL)
|
||||||
dt_proc_fini(dtp);
|
dt_proc_hash_destroy(dtp);
|
||||||
|
|
||||||
while ((pgp = dt_list_next(&dtp->dt_programs)) != NULL)
|
while ((pgp = dt_list_next(&dtp->dt_programs)) != NULL)
|
||||||
dt_program_destroy(dtp, pgp);
|
dt_program_destroy(dtp, pgp);
|
||||||
@ -1633,6 +1630,7 @@ dtrace_close(dtrace_hdl_t *dtp)
|
|||||||
dt_strdata_destroy(dtp);
|
dt_strdata_destroy(dtp);
|
||||||
dt_buffered_destroy(dtp);
|
dt_buffered_destroy(dtp);
|
||||||
dt_aggregate_destroy(dtp);
|
dt_aggregate_destroy(dtp);
|
||||||
|
free(dtp->dt_buf.dtbd_data);
|
||||||
dt_pfdict_destroy(dtp);
|
dt_pfdict_destroy(dtp);
|
||||||
dt_provmod_destroy(&dtp->dt_provmod);
|
dt_provmod_destroy(&dtp->dt_provmod);
|
||||||
dt_dof_fini(dtp);
|
dt_dof_fini(dtp);
|
||||||
|
@ -26,10 +26,6 @@
|
|||||||
|
|
||||||
#pragma ident "%Z%%M% %I% %E% SMI"
|
#pragma ident "%Z%%M% %I% %E% SMI"
|
||||||
|
|
||||||
/*
|
|
||||||
* Copyright (c) 2012 by Delphix. All rights reserved.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <sys/resource.h>
|
#include <sys/resource.h>
|
||||||
#include <sys/mman.h>
|
#include <sys/mman.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
@ -372,61 +368,6 @@ dt_opt_pgmax(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
|
|||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
|
||||||
dt_opt_setenv(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
|
|
||||||
{
|
|
||||||
char **p;
|
|
||||||
char *var;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* We can't effectively set environment variables from #pragma lines
|
|
||||||
* since the processes have already been spawned.
|
|
||||||
*/
|
|
||||||
if (dtp->dt_pcb != NULL)
|
|
||||||
return (dt_set_errno(dtp, EDT_BADOPTCTX));
|
|
||||||
|
|
||||||
if (arg == NULL)
|
|
||||||
return (dt_set_errno(dtp, EDT_BADOPTVAL));
|
|
||||||
|
|
||||||
if (!option && strchr(arg, '=') != NULL)
|
|
||||||
return (dt_set_errno(dtp, EDT_BADOPTVAL));
|
|
||||||
|
|
||||||
for (i = 1, p = dtp->dt_proc_env; *p != NULL; i++, p++)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
for (p = dtp->dt_proc_env; *p != NULL; p++) {
|
|
||||||
var = strchr(*p, '=');
|
|
||||||
if (var == NULL)
|
|
||||||
var = *p + strlen(*p);
|
|
||||||
if (strncmp(*p, arg, var - *p) == 0) {
|
|
||||||
dt_free(dtp, *p);
|
|
||||||
*p = dtp->dt_proc_env[i - 1];
|
|
||||||
dtp->dt_proc_env[i - 1] = NULL;
|
|
||||||
i--;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (option) {
|
|
||||||
if ((var = strdup(arg)) == NULL)
|
|
||||||
return (dt_set_errno(dtp, EDT_NOMEM));
|
|
||||||
|
|
||||||
if ((p = dt_alloc(dtp, sizeof (char *) * (i + 1))) == NULL) {
|
|
||||||
dt_free(dtp, var);
|
|
||||||
return (dt_set_errno(dtp, EDT_NOMEM));
|
|
||||||
}
|
|
||||||
|
|
||||||
bcopy(dtp->dt_proc_env, p, sizeof (char *) * i);
|
|
||||||
dt_free(dtp, dtp->dt_proc_env);
|
|
||||||
dtp->dt_proc_env = p;
|
|
||||||
|
|
||||||
dtp->dt_proc_env[i - 1] = var;
|
|
||||||
dtp->dt_proc_env[i] = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*ARGSUSED*/
|
/*ARGSUSED*/
|
||||||
static int
|
static int
|
||||||
dt_opt_stdc(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
|
dt_opt_stdc(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
|
||||||
@ -470,6 +411,7 @@ dt_opt_syslibdir(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
|
|||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*ARGSUSED*/
|
/*ARGSUSED*/
|
||||||
static int
|
static int
|
||||||
dt_opt_tree(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
|
dt_opt_tree(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
|
||||||
@ -970,7 +912,6 @@ static const dt_option_t _dtrace_ctoptions[] = {
|
|||||||
{ "pgmax", dt_opt_pgmax },
|
{ "pgmax", dt_opt_pgmax },
|
||||||
{ "preallocate", dt_opt_preallocate },
|
{ "preallocate", dt_opt_preallocate },
|
||||||
{ "pspec", dt_opt_cflags, DTRACE_C_PSPEC },
|
{ "pspec", dt_opt_cflags, DTRACE_C_PSPEC },
|
||||||
{ "setenv", dt_opt_setenv, 1 },
|
|
||||||
{ "stdc", dt_opt_stdc },
|
{ "stdc", dt_opt_stdc },
|
||||||
{ "strip", dt_opt_dflags, DTRACE_D_STRIP },
|
{ "strip", dt_opt_dflags, DTRACE_D_STRIP },
|
||||||
{ "syslibdir", dt_opt_syslibdir },
|
{ "syslibdir", dt_opt_syslibdir },
|
||||||
@ -979,7 +920,6 @@ static const dt_option_t _dtrace_ctoptions[] = {
|
|||||||
{ "udefs", dt_opt_invcflags, DTRACE_C_UNODEF },
|
{ "udefs", dt_opt_invcflags, DTRACE_C_UNODEF },
|
||||||
{ "undef", dt_opt_cpp_opts, (uintptr_t)"-U" },
|
{ "undef", dt_opt_cpp_opts, (uintptr_t)"-U" },
|
||||||
{ "unodefs", dt_opt_cflags, DTRACE_C_UNODEF },
|
{ "unodefs", dt_opt_cflags, DTRACE_C_UNODEF },
|
||||||
{ "unsetenv", dt_opt_setenv, 0 },
|
|
||||||
{ "verbose", dt_opt_cflags, DTRACE_C_DIFV },
|
{ "verbose", dt_opt_cflags, DTRACE_C_DIFV },
|
||||||
{ "version", dt_opt_version },
|
{ "version", dt_opt_version },
|
||||||
{ "zdefs", dt_opt_cflags, DTRACE_C_ZDEFS },
|
{ "zdefs", dt_opt_cflags, DTRACE_C_ZDEFS },
|
||||||
@ -1007,7 +947,6 @@ static const dt_option_t _dtrace_rtoptions[] = {
|
|||||||
{ "statusrate", dt_opt_rate, DTRACEOPT_STATUSRATE },
|
{ "statusrate", dt_opt_rate, DTRACEOPT_STATUSRATE },
|
||||||
{ "strsize", dt_opt_strsize, DTRACEOPT_STRSIZE },
|
{ "strsize", dt_opt_strsize, DTRACEOPT_STRSIZE },
|
||||||
{ "ustackframes", dt_opt_runtime, DTRACEOPT_USTACKFRAMES },
|
{ "ustackframes", dt_opt_runtime, DTRACEOPT_USTACKFRAMES },
|
||||||
{ "temporal", dt_opt_runtime, DTRACEOPT_TEMPORAL },
|
|
||||||
{ NULL, NULL, 0 }
|
{ NULL, NULL, 0 }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -23,7 +23,6 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2006 Sun Microsystems, Inc. All rights reserved.
|
* Copyright 2006 Sun Microsystems, Inc. All rights reserved.
|
||||||
* Copyright (c) 2011, Joyent Inc. All rights reserved.
|
* Copyright (c) 2011, Joyent Inc. All rights reserved.
|
||||||
* Copyright (c) 2012 by Delphix. All rights reserved.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#pragma ident "%Z%%M% %I% %E% SMI"
|
#pragma ident "%Z%%M% %I% %E% SMI"
|
||||||
@ -97,7 +96,6 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include <sys/param.h>
|
#include <sys/param.h>
|
||||||
#include <sys/sysmacros.h>
|
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
#include <setjmp.h>
|
#include <setjmp.h>
|
||||||
#include <strings.h>
|
#include <strings.h>
|
||||||
@ -1864,38 +1862,6 @@ dt_node_op1(int op, dt_node_t *cp)
|
|||||||
return (dnp);
|
return (dnp);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* If an integer constant is being cast to another integer type, we can
|
|
||||||
* perform the cast as part of integer constant folding in this pass. We must
|
|
||||||
* take action when the integer is being cast to a smaller type or if it is
|
|
||||||
* changing signed-ness. If so, we first shift rp's bits bits high (losing
|
|
||||||
* excess bits if narrowing) and then shift them down with either a logical
|
|
||||||
* shift (unsigned) or arithmetic shift (signed).
|
|
||||||
*/
|
|
||||||
static void
|
|
||||||
dt_cast(dt_node_t *lp, dt_node_t *rp)
|
|
||||||
{
|
|
||||||
size_t srcsize = dt_node_type_size(rp);
|
|
||||||
size_t dstsize = dt_node_type_size(lp);
|
|
||||||
|
|
||||||
if (dstsize < srcsize) {
|
|
||||||
int n = (sizeof (uint64_t) - dstsize) * NBBY;
|
|
||||||
rp->dn_value <<= n;
|
|
||||||
rp->dn_value >>= n;
|
|
||||||
} else if (dstsize > srcsize) {
|
|
||||||
int n = (sizeof (uint64_t) - srcsize) * NBBY;
|
|
||||||
int s = (dstsize - srcsize) * NBBY;
|
|
||||||
|
|
||||||
rp->dn_value <<= n;
|
|
||||||
if (rp->dn_flags & DT_NF_SIGNED) {
|
|
||||||
rp->dn_value = (intmax_t)rp->dn_value >> s;
|
|
||||||
rp->dn_value >>= n - s;
|
|
||||||
} else {
|
|
||||||
rp->dn_value >>= n;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
dt_node_t *
|
dt_node_t *
|
||||||
dt_node_op2(int op, dt_node_t *lp, dt_node_t *rp)
|
dt_node_op2(int op, dt_node_t *lp, dt_node_t *rp)
|
||||||
{
|
{
|
||||||
@ -2045,9 +2011,32 @@ dt_node_op2(int op, dt_node_t *lp, dt_node_t *rp)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If an integer constant is being cast to another integer type, we can
|
||||||
|
* perform the cast as part of integer constant folding in this pass.
|
||||||
|
* We must take action when the integer is being cast to a smaller type
|
||||||
|
* or if it is changing signed-ness. If so, we first shift rp's bits
|
||||||
|
* bits high (losing excess bits if narrowing) and then shift them down
|
||||||
|
* with either a logical shift (unsigned) or arithmetic shift (signed).
|
||||||
|
*/
|
||||||
if (op == DT_TOK_LPAR && rp->dn_kind == DT_NODE_INT &&
|
if (op == DT_TOK_LPAR && rp->dn_kind == DT_NODE_INT &&
|
||||||
dt_node_is_integer(lp)) {
|
dt_node_is_integer(lp)) {
|
||||||
dt_cast(lp, rp);
|
size_t srcsize = dt_node_type_size(rp);
|
||||||
|
size_t dstsize = dt_node_type_size(lp);
|
||||||
|
|
||||||
|
if ((dstsize < srcsize) || ((lp->dn_flags & DT_NF_SIGNED) ^
|
||||||
|
(rp->dn_flags & DT_NF_SIGNED))) {
|
||||||
|
int n = dstsize < srcsize ?
|
||||||
|
(sizeof (uint64_t) * NBBY - dstsize * NBBY) :
|
||||||
|
(sizeof (uint64_t) * NBBY - srcsize * NBBY);
|
||||||
|
|
||||||
|
rp->dn_value <<= n;
|
||||||
|
if (lp->dn_flags & DT_NF_SIGNED)
|
||||||
|
rp->dn_value = (intmax_t)rp->dn_value >> n;
|
||||||
|
else
|
||||||
|
rp->dn_value = rp->dn_value >> n;
|
||||||
|
}
|
||||||
|
|
||||||
dt_node_type_propagate(lp, rp);
|
dt_node_type_propagate(lp, rp);
|
||||||
dt_node_attr_assign(rp, dt_attr_min(lp->dn_attr, rp->dn_attr));
|
dt_node_attr_assign(rp, dt_attr_min(lp->dn_attr, rp->dn_attr));
|
||||||
dt_node_free(lp);
|
dt_node_free(lp);
|
||||||
@ -2906,14 +2895,14 @@ dt_cook_op1(dt_node_t *dnp, uint_t idflags)
|
|||||||
case DT_TOK_DEREF:
|
case DT_TOK_DEREF:
|
||||||
/*
|
/*
|
||||||
* If the deref operator is applied to a translated pointer,
|
* If the deref operator is applied to a translated pointer,
|
||||||
* we set our output type to the output of the translation.
|
* we can just set our output type to the base translation.
|
||||||
*/
|
*/
|
||||||
if ((idp = dt_node_resolve(cp, DT_IDENT_XLPTR)) != NULL) {
|
if ((idp = dt_node_resolve(cp, DT_IDENT_XLPTR)) != NULL) {
|
||||||
dt_xlator_t *dxp = idp->di_data;
|
dt_xlator_t *dxp = idp->di_data;
|
||||||
|
|
||||||
dnp->dn_ident = &dxp->dx_souid;
|
dnp->dn_ident = &dxp->dx_souid;
|
||||||
dt_node_type_assign(dnp,
|
dt_node_type_assign(dnp,
|
||||||
dnp->dn_ident->di_ctfp, dnp->dn_ident->di_type);
|
DT_DYN_CTFP(dtp), DT_DYN_TYPE(dtp));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3089,31 +3078,6 @@ dt_cook_op1(dt_node_t *dnp, uint_t idflags)
|
|||||||
return (dnp);
|
return (dnp);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
|
||||||
dt_assign_common(dt_node_t *dnp)
|
|
||||||
{
|
|
||||||
dt_node_t *lp = dnp->dn_left;
|
|
||||||
dt_node_t *rp = dnp->dn_right;
|
|
||||||
int op = dnp->dn_op;
|
|
||||||
|
|
||||||
if (rp->dn_kind == DT_NODE_INT)
|
|
||||||
dt_cast(lp, rp);
|
|
||||||
|
|
||||||
if (!(lp->dn_flags & DT_NF_LVALUE)) {
|
|
||||||
xyerror(D_OP_LVAL, "operator %s requires modifiable "
|
|
||||||
"lvalue as an operand\n", opstr(op));
|
|
||||||
/* see K&R[A7.17] */
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!(lp->dn_flags & DT_NF_WRITABLE)) {
|
|
||||||
xyerror(D_OP_WRITE, "operator %s can only be applied "
|
|
||||||
"to a writable variable\n", opstr(op));
|
|
||||||
}
|
|
||||||
|
|
||||||
dt_node_type_propagate(lp, dnp); /* see K&R[A7.17] */
|
|
||||||
dt_node_attr_assign(dnp, dt_attr_min(lp->dn_attr, rp->dn_attr));
|
|
||||||
}
|
|
||||||
|
|
||||||
static dt_node_t *
|
static dt_node_t *
|
||||||
dt_cook_op2(dt_node_t *dnp, uint_t idflags)
|
dt_cook_op2(dt_node_t *dnp, uint_t idflags)
|
||||||
{
|
{
|
||||||
@ -3592,7 +3556,19 @@ dt_cook_op2(dt_node_t *dnp, uint_t idflags)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
asgn_common:
|
asgn_common:
|
||||||
dt_assign_common(dnp);
|
if (!(lp->dn_flags & DT_NF_LVALUE)) {
|
||||||
|
xyerror(D_OP_LVAL, "operator %s requires modifiable "
|
||||||
|
"lvalue as an operand\n", opstr(op));
|
||||||
|
/* see K&R[A7.17] */
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(lp->dn_flags & DT_NF_WRITABLE)) {
|
||||||
|
xyerror(D_OP_WRITE, "operator %s can only be applied "
|
||||||
|
"to a writable variable\n", opstr(op));
|
||||||
|
}
|
||||||
|
|
||||||
|
dt_node_type_propagate(lp, dnp); /* see K&R[A7.17] */
|
||||||
|
dt_node_attr_assign(dnp, dt_attr_min(lp->dn_attr, rp->dn_attr));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DT_TOK_PTR:
|
case DT_TOK_PTR:
|
||||||
@ -3897,14 +3873,6 @@ dt_cook_op2(dt_node_t *dnp, uint_t idflags)
|
|||||||
|
|
||||||
dt_node_type_propagate(lp, dnp); /* see K&R[A7.5] */
|
dt_node_type_propagate(lp, dnp); /* see K&R[A7.5] */
|
||||||
dt_node_attr_assign(dnp, dt_attr_min(lp->dn_attr, rp->dn_attr));
|
dt_node_attr_assign(dnp, dt_attr_min(lp->dn_attr, rp->dn_attr));
|
||||||
|
|
||||||
/*
|
|
||||||
* If it's a pointer then should be able to (attempt to)
|
|
||||||
* assign to it.
|
|
||||||
*/
|
|
||||||
if (lkind == CTF_K_POINTER)
|
|
||||||
dnp->dn_flags |= DT_NF_WRITABLE;
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,161 +0,0 @@
|
|||||||
/*
|
|
||||||
* CDDL HEADER START
|
|
||||||
*
|
|
||||||
* 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.
|
|
||||||
*
|
|
||||||
* CDDL HEADER END
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Copyright (c) 2012 by Delphix. All rights reserved.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <dtrace.h>
|
|
||||||
#include <dt_impl.h>
|
|
||||||
#include <dt_pq.h>
|
|
||||||
#include <assert.h>
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Create a new priority queue.
|
|
||||||
*
|
|
||||||
* size is the maximum number of items that will be stored in the priority
|
|
||||||
* queue at one time.
|
|
||||||
*/
|
|
||||||
dt_pq_t *
|
|
||||||
dt_pq_init(dtrace_hdl_t *dtp, uint_t size, dt_pq_value_f value_cb, void *cb_arg)
|
|
||||||
{
|
|
||||||
dt_pq_t *p;
|
|
||||||
assert(size > 1);
|
|
||||||
|
|
||||||
if ((p = dt_zalloc(dtp, sizeof (dt_pq_t))) == NULL)
|
|
||||||
return (NULL);
|
|
||||||
|
|
||||||
p->dtpq_items = dt_zalloc(dtp, size * sizeof (p->dtpq_items[0]));
|
|
||||||
if (p->dtpq_items == NULL) {
|
|
||||||
dt_free(dtp, p);
|
|
||||||
return (NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
p->dtpq_hdl = dtp;
|
|
||||||
p->dtpq_size = size;
|
|
||||||
p->dtpq_last = 1;
|
|
||||||
p->dtpq_value = value_cb;
|
|
||||||
p->dtpq_arg = cb_arg;
|
|
||||||
|
|
||||||
return (p);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
dt_pq_fini(dt_pq_t *p)
|
|
||||||
{
|
|
||||||
dtrace_hdl_t *dtp = p->dtpq_hdl;
|
|
||||||
|
|
||||||
dt_free(dtp, p->dtpq_items);
|
|
||||||
dt_free(dtp, p);
|
|
||||||
}
|
|
||||||
|
|
||||||
static uint64_t
|
|
||||||
dt_pq_getvalue(dt_pq_t *p, uint_t index)
|
|
||||||
{
|
|
||||||
void *item = p->dtpq_items[index];
|
|
||||||
return (p->dtpq_value(item, p->dtpq_arg));
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
dt_pq_insert(dt_pq_t *p, void *item)
|
|
||||||
{
|
|
||||||
uint_t i;
|
|
||||||
|
|
||||||
#if !defined(sun)
|
|
||||||
if (p->dtpq_last >= p->dtpq_size)
|
|
||||||
return;
|
|
||||||
#endif
|
|
||||||
assert(p->dtpq_last < p->dtpq_size);
|
|
||||||
|
|
||||||
i = p->dtpq_last++;
|
|
||||||
p->dtpq_items[i] = item;
|
|
||||||
|
|
||||||
while (i > 1 && dt_pq_getvalue(p, i) < dt_pq_getvalue(p, i / 2)) {
|
|
||||||
void *tmp = p->dtpq_items[i];
|
|
||||||
p->dtpq_items[i] = p->dtpq_items[i / 2];
|
|
||||||
p->dtpq_items[i / 2] = tmp;
|
|
||||||
i /= 2;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Return elements from the priority queue. *cookie should be zero when first
|
|
||||||
* called. Returns NULL when there are no more elements.
|
|
||||||
*/
|
|
||||||
void *
|
|
||||||
dt_pq_walk(dt_pq_t *p, uint_t *cookie)
|
|
||||||
{
|
|
||||||
(*cookie)++;
|
|
||||||
if (*cookie >= p->dtpq_last)
|
|
||||||
return (NULL);
|
|
||||||
|
|
||||||
return (p->dtpq_items[*cookie]);
|
|
||||||
}
|
|
||||||
|
|
||||||
void *
|
|
||||||
dt_pq_pop(dt_pq_t *p)
|
|
||||||
{
|
|
||||||
uint_t i = 1;
|
|
||||||
void *ret;
|
|
||||||
|
|
||||||
assert(p->dtpq_last > 0);
|
|
||||||
|
|
||||||
if (p->dtpq_last == 1)
|
|
||||||
return (NULL);
|
|
||||||
|
|
||||||
ret = p->dtpq_items[1];
|
|
||||||
|
|
||||||
p->dtpq_last--;
|
|
||||||
p->dtpq_items[1] = p->dtpq_items[p->dtpq_last];
|
|
||||||
p->dtpq_items[p->dtpq_last] = NULL;
|
|
||||||
|
|
||||||
for (;;) {
|
|
||||||
uint_t lc = i * 2;
|
|
||||||
uint_t rc = i * 2 + 1;
|
|
||||||
uint_t c;
|
|
||||||
uint64_t v;
|
|
||||||
void *tmp;
|
|
||||||
|
|
||||||
if (lc >= p->dtpq_last)
|
|
||||||
break;
|
|
||||||
|
|
||||||
if (rc >= p->dtpq_last) {
|
|
||||||
c = lc;
|
|
||||||
v = dt_pq_getvalue(p, lc);
|
|
||||||
} else {
|
|
||||||
uint64_t lv = dt_pq_getvalue(p, lc);
|
|
||||||
uint64_t rv = dt_pq_getvalue(p, rc);
|
|
||||||
|
|
||||||
if (lv < rv) {
|
|
||||||
c = lc;
|
|
||||||
v = lv;
|
|
||||||
} else {
|
|
||||||
c = rc;
|
|
||||||
v = rv;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (v >= dt_pq_getvalue(p, i))
|
|
||||||
break;
|
|
||||||
|
|
||||||
tmp = p->dtpq_items[i];
|
|
||||||
p->dtpq_items[i] = p->dtpq_items[c];
|
|
||||||
p->dtpq_items[c] = tmp;
|
|
||||||
|
|
||||||
i = c;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (ret);
|
|
||||||
}
|
|
@ -1,51 +0,0 @@
|
|||||||
/*
|
|
||||||
* CDDL HEADER START
|
|
||||||
*
|
|
||||||
* 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.
|
|
||||||
*
|
|
||||||
* CDDL HEADER END
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Copyright (c) 2012 by Delphix. All rights reserved.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef _DT_PQ_H
|
|
||||||
#define _DT_PQ_H
|
|
||||||
|
|
||||||
#include <dtrace.h>
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
typedef uint64_t (*dt_pq_value_f)(void *, void *);
|
|
||||||
|
|
||||||
typedef struct dt_pq {
|
|
||||||
dtrace_hdl_t *dtpq_hdl; /* dtrace handle */
|
|
||||||
void **dtpq_items; /* array of elements */
|
|
||||||
uint_t dtpq_size; /* count of allocated elements */
|
|
||||||
uint_t dtpq_last; /* next free slot */
|
|
||||||
dt_pq_value_f dtpq_value; /* callback to get the value */
|
|
||||||
void *dtpq_arg; /* callback argument */
|
|
||||||
} dt_pq_t;
|
|
||||||
|
|
||||||
extern dt_pq_t *dt_pq_init(dtrace_hdl_t *, uint_t size, dt_pq_value_f, void *);
|
|
||||||
extern void dt_pq_fini(dt_pq_t *);
|
|
||||||
|
|
||||||
extern void dt_pq_insert(dt_pq_t *, void *);
|
|
||||||
extern void *dt_pq_pop(dt_pq_t *);
|
|
||||||
extern void *dt_pq_walk(dt_pq_t *, uint_t *);
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif /* _DT_PQ_H */
|
|
@ -22,7 +22,6 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||||
* Copyright (c) 2011, Joyent, Inc. All rights reserved.
|
* Copyright (c) 2011, Joyent, Inc. All rights reserved.
|
||||||
* Copyright (c) 2012 by Delphix. All rights reserved.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#if defined(sun)
|
#if defined(sun)
|
||||||
@ -162,7 +161,7 @@ static int
|
|||||||
pfcheck_dint(dt_pfargv_t *pfv, dt_pfargd_t *pfd, dt_node_t *dnp)
|
pfcheck_dint(dt_pfargv_t *pfv, dt_pfargd_t *pfd, dt_node_t *dnp)
|
||||||
{
|
{
|
||||||
if (dnp->dn_flags & DT_NF_SIGNED)
|
if (dnp->dn_flags & DT_NF_SIGNED)
|
||||||
pfd->pfd_fmt[strlen(pfd->pfd_fmt) - 1] = 'i';
|
pfd->pfd_flags |= DT_PFCONV_SIGNED;
|
||||||
else
|
else
|
||||||
pfd->pfd_fmt[strlen(pfd->pfd_fmt) - 1] = 'u';
|
pfd->pfd_fmt[strlen(pfd->pfd_fmt) - 1] = 'u';
|
||||||
|
|
||||||
@ -665,7 +664,7 @@ static const dt_pfconv_t _dtrace_conversions[] = {
|
|||||||
{ "hu", "u", "unsigned short", pfcheck_type, pfprint_uint },
|
{ "hu", "u", "unsigned short", pfcheck_type, pfprint_uint },
|
||||||
{ "hx", "x", "short", pfcheck_xshort, pfprint_uint },
|
{ "hx", "x", "short", pfcheck_xshort, pfprint_uint },
|
||||||
{ "hX", "X", "short", pfcheck_xshort, pfprint_uint },
|
{ "hX", "X", "short", pfcheck_xshort, pfprint_uint },
|
||||||
{ "i", "i", pfproto_xint, pfcheck_xint, pfprint_sint },
|
{ "i", "i", pfproto_xint, pfcheck_dint, pfprint_dint },
|
||||||
{ "I", "s", pfproto_cstr, pfcheck_str, pfprint_inetaddr },
|
{ "I", "s", pfproto_cstr, pfcheck_str, pfprint_inetaddr },
|
||||||
{ "k", "s", "stack", pfcheck_stack, pfprint_stack },
|
{ "k", "s", "stack", pfcheck_stack, pfprint_stack },
|
||||||
{ "lc", "lc", "int", pfcheck_type, pfprint_sint }, /* a.k.a. wint_t */
|
{ "lc", "lc", "int", pfcheck_type, pfprint_sint }, /* a.k.a. wint_t */
|
||||||
|
@ -24,10 +24,6 @@
|
|||||||
* Use is subject to license terms.
|
* Use is subject to license terms.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
|
||||||
* Copyright (c) 2012 by Delphix. All rights reserved.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* DTrace Process Control
|
* DTrace Process Control
|
||||||
*
|
*
|
||||||
@ -507,7 +503,7 @@ dt_proc_control(void *arg)
|
|||||||
dt_proc_control_data_t *datap = arg;
|
dt_proc_control_data_t *datap = arg;
|
||||||
dtrace_hdl_t *dtp = datap->dpcd_hdl;
|
dtrace_hdl_t *dtp = datap->dpcd_hdl;
|
||||||
dt_proc_t *dpr = datap->dpcd_proc;
|
dt_proc_t *dpr = datap->dpcd_proc;
|
||||||
dt_proc_hash_t *dph = dtp->dt_procs;
|
dt_proc_hash_t *dph = dpr->dpr_hdl->dt_procs;
|
||||||
struct ps_prochandle *P = dpr->dpr_proc;
|
struct ps_prochandle *P = dpr->dpr_proc;
|
||||||
int pid = dpr->dpr_pid;
|
int pid = dpr->dpr_pid;
|
||||||
|
|
||||||
@ -968,8 +964,7 @@ dt_proc_create(dtrace_hdl_t *dtp, const char *file, char *const *argv,
|
|||||||
(void) pthread_cond_init(&dpr->dpr_cv, NULL);
|
(void) pthread_cond_init(&dpr->dpr_cv, NULL);
|
||||||
|
|
||||||
#if defined(sun)
|
#if defined(sun)
|
||||||
dpr->dpr_proc = Pxcreate(file, argv, dtp->dt_proc_env, &err, NULL, 0);
|
if ((dpr->dpr_proc = Pcreate(file, argv, &err, NULL, 0)) == NULL) {
|
||||||
if (dpr->dpr_proc == NULL) {
|
|
||||||
#else
|
#else
|
||||||
if ((err = proc_create(file, argv, pcf, child_arg,
|
if ((err = proc_create(file, argv, pcf, child_arg,
|
||||||
&dpr->dpr_proc)) != 0) {
|
&dpr->dpr_proc)) != 0) {
|
||||||
@ -1145,75 +1140,30 @@ dt_proc_unlock(dtrace_hdl_t *dtp, struct ps_prochandle *P)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
dt_proc_init(dtrace_hdl_t *dtp)
|
dt_proc_hash_create(dtrace_hdl_t *dtp)
|
||||||
{
|
{
|
||||||
extern char **environ;
|
|
||||||
static char *envdef[] = {
|
|
||||||
"LD_NOLAZYLOAD=1", /* linker lazy loading hides funcs */
|
|
||||||
NULL
|
|
||||||
};
|
|
||||||
char **p;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
if ((dtp->dt_procs = dt_zalloc(dtp, sizeof (dt_proc_hash_t) +
|
if ((dtp->dt_procs = dt_zalloc(dtp, sizeof (dt_proc_hash_t) +
|
||||||
sizeof (dt_proc_t *) * _dtrace_pidbuckets - 1)) == NULL)
|
sizeof (dt_proc_t *) * _dtrace_pidbuckets - 1)) != NULL) {
|
||||||
return;
|
|
||||||
|
|
||||||
(void) pthread_mutex_init(&dtp->dt_procs->dph_lock, NULL);
|
(void) pthread_mutex_init(&dtp->dt_procs->dph_lock, NULL);
|
||||||
(void) pthread_cond_init(&dtp->dt_procs->dph_cv, NULL);
|
(void) pthread_cond_init(&dtp->dt_procs->dph_cv, NULL);
|
||||||
|
|
||||||
dtp->dt_procs->dph_hashlen = _dtrace_pidbuckets;
|
dtp->dt_procs->dph_hashlen = _dtrace_pidbuckets;
|
||||||
dtp->dt_procs->dph_lrulim = _dtrace_pidlrulim;
|
dtp->dt_procs->dph_lrulim = _dtrace_pidlrulim;
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Count how big our environment needs to be.
|
|
||||||
*/
|
|
||||||
for (i = 1, p = environ; *p != NULL; i++, p++)
|
|
||||||
continue;
|
|
||||||
for (p = envdef; *p != NULL; i++, p++)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if ((dtp->dt_proc_env = dt_zalloc(dtp, sizeof (char *) * i)) == NULL)
|
|
||||||
return;
|
|
||||||
|
|
||||||
for (i = 0, p = environ; *p != NULL; i++, p++) {
|
|
||||||
if ((dtp->dt_proc_env[i] = strdup(*p)) == NULL)
|
|
||||||
goto err;
|
|
||||||
}
|
}
|
||||||
for (p = envdef; *p != NULL; i++, p++) {
|
|
||||||
if ((dtp->dt_proc_env[i] = strdup(*p)) == NULL)
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
|
|
||||||
return;
|
|
||||||
|
|
||||||
err:
|
|
||||||
while (--i != 0) {
|
|
||||||
dt_free(dtp, dtp->dt_proc_env[i]);
|
|
||||||
}
|
|
||||||
dt_free(dtp, dtp->dt_proc_env);
|
|
||||||
dtp->dt_proc_env = NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
dt_proc_fini(dtrace_hdl_t *dtp)
|
dt_proc_hash_destroy(dtrace_hdl_t *dtp)
|
||||||
{
|
{
|
||||||
dt_proc_hash_t *dph = dtp->dt_procs;
|
dt_proc_hash_t *dph = dtp->dt_procs;
|
||||||
dt_proc_t *dpr;
|
dt_proc_t *dpr;
|
||||||
char **p;
|
|
||||||
|
|
||||||
while ((dpr = dt_list_next(&dph->dph_lrulist)) != NULL)
|
while ((dpr = dt_list_next(&dph->dph_lrulist)) != NULL)
|
||||||
dt_proc_destroy(dtp, dpr->dpr_proc);
|
dt_proc_destroy(dtp, dpr->dpr_proc);
|
||||||
|
|
||||||
dtp->dt_procs = NULL;
|
dtp->dt_procs = NULL;
|
||||||
dt_free(dtp, dph);
|
dt_free(dtp, dph);
|
||||||
|
|
||||||
for (p = dtp->dt_proc_env; *p != NULL; p++)
|
|
||||||
dt_free(dtp, *p);
|
|
||||||
|
|
||||||
dt_free(dtp, dtp->dt_proc_env);
|
|
||||||
dtp->dt_proc_env = NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct ps_prochandle *
|
struct ps_prochandle *
|
||||||
|
@ -24,13 +24,11 @@
|
|||||||
* Use is subject to license terms.
|
* Use is subject to license terms.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
|
||||||
* Copyright (c) 2012 by Delphix. All rights reserved.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef _DT_PROC_H
|
#ifndef _DT_PROC_H
|
||||||
#define _DT_PROC_H
|
#define _DT_PROC_H
|
||||||
|
|
||||||
|
#pragma ident "%Z%%M% %I% %E% SMI"
|
||||||
|
|
||||||
#include <libproc.h>
|
#include <libproc.h>
|
||||||
#include <dtrace.h>
|
#include <dtrace.h>
|
||||||
#include <pthread.h>
|
#include <pthread.h>
|
||||||
@ -108,8 +106,8 @@ extern void dt_proc_lock(dtrace_hdl_t *, struct ps_prochandle *);
|
|||||||
extern void dt_proc_unlock(dtrace_hdl_t *, struct ps_prochandle *);
|
extern void dt_proc_unlock(dtrace_hdl_t *, struct ps_prochandle *);
|
||||||
extern dt_proc_t *dt_proc_lookup(dtrace_hdl_t *, struct ps_prochandle *, int);
|
extern dt_proc_t *dt_proc_lookup(dtrace_hdl_t *, struct ps_prochandle *, int);
|
||||||
|
|
||||||
extern void dt_proc_init(dtrace_hdl_t *);
|
extern void dt_proc_hash_create(dtrace_hdl_t *);
|
||||||
extern void dt_proc_fini(dtrace_hdl_t *);
|
extern void dt_proc_hash_destroy(dtrace_hdl_t *);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
@ -19,15 +19,12 @@
|
|||||||
*
|
*
|
||||||
* CDDL HEADER END
|
* CDDL HEADER END
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright 2003 Sun Microsystems, Inc. All rights reserved.
|
* Copyright 2003 Sun Microsystems, Inc. All rights reserved.
|
||||||
* Use is subject to license terms.
|
* Use is subject to license terms.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
#pragma ident "%Z%%M% %I% %E% SMI"
|
||||||
* Copyright (c) 2012 by Delphix. All rights reserved.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/bitmap.h>
|
#include <sys/bitmap.h>
|
||||||
@ -36,19 +33,18 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
#include <dt_regset.h>
|
#include <dt_regset.h>
|
||||||
#include <dt_impl.h>
|
|
||||||
|
|
||||||
dt_regset_t *
|
dt_regset_t *
|
||||||
dt_regset_create(ulong_t nregs)
|
dt_regset_create(ulong_t size)
|
||||||
{
|
{
|
||||||
ulong_t n = BT_BITOUL(nregs);
|
ulong_t n = BT_BITOUL(size + 1); /* + 1 for %r0 */
|
||||||
dt_regset_t *drp = malloc(sizeof (dt_regset_t));
|
dt_regset_t *drp = malloc(sizeof (dt_regset_t));
|
||||||
|
|
||||||
if (drp == NULL)
|
if (drp == NULL)
|
||||||
return (NULL);
|
return (NULL);
|
||||||
|
|
||||||
drp->dr_bitmap = malloc(sizeof (ulong_t) * n);
|
drp->dr_bitmap = malloc(sizeof (ulong_t) * n);
|
||||||
drp->dr_size = nregs;
|
drp->dr_size = size + 1;
|
||||||
|
|
||||||
if (drp->dr_bitmap == NULL) {
|
if (drp->dr_bitmap == NULL) {
|
||||||
dt_regset_destroy(drp);
|
dt_regset_destroy(drp);
|
||||||
@ -72,25 +68,6 @@ dt_regset_reset(dt_regset_t *drp)
|
|||||||
bzero(drp->dr_bitmap, sizeof (ulong_t) * BT_BITOUL(drp->dr_size));
|
bzero(drp->dr_bitmap, sizeof (ulong_t) * BT_BITOUL(drp->dr_size));
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
dt_regset_assert_free(dt_regset_t *drp)
|
|
||||||
{
|
|
||||||
int reg;
|
|
||||||
boolean_t fail = B_FALSE;
|
|
||||||
for (reg = 0; reg < drp->dr_size; reg++) {
|
|
||||||
if (BT_TEST(drp->dr_bitmap, reg) != 0) {
|
|
||||||
dt_dprintf("%%r%d was left allocated\n", reg);
|
|
||||||
fail = B_TRUE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* We set this during dtest runs to check for register leaks.
|
|
||||||
*/
|
|
||||||
if (fail && getenv("DTRACE_DEBUG_REGSET") != NULL)
|
|
||||||
abort();
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
int
|
||||||
dt_regset_alloc(dt_regset_t *drp)
|
dt_regset_alloc(dt_regset_t *drp)
|
||||||
{
|
{
|
||||||
@ -118,15 +95,13 @@ dt_regset_alloc(dt_regset_t *drp)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
xyerror(D_NOREG, "Insufficient registers to generate code");
|
return (-1); /* no available registers */
|
||||||
/*NOTREACHED*/
|
|
||||||
return (-1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
dt_regset_free(dt_regset_t *drp, int reg)
|
dt_regset_free(dt_regset_t *drp, int reg)
|
||||||
{
|
{
|
||||||
assert(reg >= 0 && reg < drp->dr_size);
|
assert(reg > 0 && reg < drp->dr_size);
|
||||||
assert(BT_TEST(drp->dr_bitmap, reg) != 0);
|
assert(BT_TEST(drp->dr_bitmap, reg) != 0);
|
||||||
BT_CLEAR(drp->dr_bitmap, reg);
|
BT_CLEAR(drp->dr_bitmap, reg);
|
||||||
}
|
}
|
||||||
|
@ -19,19 +19,16 @@
|
|||||||
*
|
*
|
||||||
* CDDL HEADER END
|
* CDDL HEADER END
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright 2003 Sun Microsystems, Inc. All rights reserved.
|
* Copyright 2003 Sun Microsystems, Inc. All rights reserved.
|
||||||
* Use is subject to license terms.
|
* Use is subject to license terms.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
|
||||||
* Copyright (c) 2012 by Delphix. All rights reserved.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef _DT_REGSET_H
|
#ifndef _DT_REGSET_H
|
||||||
#define _DT_REGSET_H
|
#define _DT_REGSET_H
|
||||||
|
|
||||||
|
#pragma ident "%Z%%M% %I% %E% SMI"
|
||||||
|
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
@ -48,7 +45,6 @@ extern void dt_regset_destroy(dt_regset_t *);
|
|||||||
extern void dt_regset_reset(dt_regset_t *);
|
extern void dt_regset_reset(dt_regset_t *);
|
||||||
extern int dt_regset_alloc(dt_regset_t *);
|
extern int dt_regset_alloc(dt_regset_t *);
|
||||||
extern void dt_regset_free(dt_regset_t *, int);
|
extern void dt_regset_free(dt_regset_t *, int);
|
||||||
extern void dt_regset_assert_free(dt_regset_t *);
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
@ -21,7 +21,6 @@
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright 2010 Sun Microsystems, Inc. All rights reserved.
|
* Copyright 2010 Sun Microsystems, Inc. All rights reserved.
|
||||||
* Copyright (c) 2012 by Delphix. All rights reserved.
|
|
||||||
* Use is subject to license terms.
|
* Use is subject to license terms.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -618,8 +617,8 @@ dt_printf(dtrace_hdl_t *dtp, FILE *fp, const char *format, ...)
|
|||||||
size_t avail;
|
size_t avail;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Using buffered output is not allowed if a handler has
|
* It's not legal to use buffered ouput if there is not a
|
||||||
* not been installed.
|
* handler for buffered output.
|
||||||
*/
|
*/
|
||||||
if (dtp->dt_bufhdlr == NULL) {
|
if (dtp->dt_bufhdlr == NULL) {
|
||||||
va_end(ap);
|
va_end(ap);
|
||||||
|
@ -24,10 +24,6 @@
|
|||||||
* Use is subject to license terms.
|
* Use is subject to license terms.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
|
||||||
* Copyright (c) 2012 by Delphix. All rights reserved.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
@ -529,8 +525,7 @@ dt_instr_size(uchar_t *instr, dtrace_hdl_t *dtp, pid_t pid, uintptr_t addr,
|
|||||||
* another debugger attached to this process. The original instruction
|
* another debugger attached to this process. The original instruction
|
||||||
* can't be recovered so this must fail.
|
* can't be recovered so this must fail.
|
||||||
*/
|
*/
|
||||||
if (x86dis.d86_len == 1 &&
|
if (x86dis.d86_len == 1 && instr[0] == FASTTRAP_INSTR)
|
||||||
(uchar_t)x86dis.d86_bytes[0] == FASTTRAP_INSTR)
|
|
||||||
return (-1);
|
return (-1);
|
||||||
|
|
||||||
return (x86dis.d86_len);
|
return (x86dis.d86_len);
|
||||||
|
@ -31,7 +31,6 @@ SRCS= dt_aggregate.c \
|
|||||||
dt_parser.c \
|
dt_parser.c \
|
||||||
dt_pcb.c \
|
dt_pcb.c \
|
||||||
dt_pid.c \
|
dt_pid.c \
|
||||||
dt_pq.c \
|
|
||||||
dt_pragma.c \
|
dt_pragma.c \
|
||||||
dt_print.c \
|
dt_print.c \
|
||||||
dt_printf.c \
|
dt_printf.c \
|
||||||
|
@ -23,7 +23,6 @@
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright 2008 Sun Microsystems, Inc. All rights reserved.
|
* Copyright 2008 Sun Microsystems, Inc. All rights reserved.
|
||||||
* Copyright (c) 2012 by Delphix. All rights reserved
|
|
||||||
* Use is subject to license terms.
|
* Use is subject to license terms.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -2346,10 +2345,9 @@ dtrace_speculation_commit(dtrace_state_t *state, processorid_t cpu,
|
|||||||
{
|
{
|
||||||
dtrace_speculation_t *spec;
|
dtrace_speculation_t *spec;
|
||||||
dtrace_buffer_t *src, *dest;
|
dtrace_buffer_t *src, *dest;
|
||||||
uintptr_t daddr, saddr, dlimit, slimit;
|
uintptr_t daddr, saddr, dlimit;
|
||||||
dtrace_speculation_state_t current, new = 0;
|
dtrace_speculation_state_t current, new = 0;
|
||||||
intptr_t offs;
|
intptr_t offs;
|
||||||
uint64_t timestamp;
|
|
||||||
|
|
||||||
if (which == 0)
|
if (which == 0)
|
||||||
return;
|
return;
|
||||||
@ -2425,37 +2423,7 @@ dtrace_speculation_commit(dtrace_state_t *state, processorid_t cpu,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We have sufficient space to copy the speculative buffer into the
|
* We have the space; copy the buffer across. (Note that this is a
|
||||||
* primary buffer. First, modify the speculative buffer, filling
|
|
||||||
* in the timestamp of all entries with the current time. The data
|
|
||||||
* must have the commit() time rather than the time it was traced,
|
|
||||||
* so that all entries in the primary buffer are in timestamp order.
|
|
||||||
*/
|
|
||||||
timestamp = dtrace_gethrtime();
|
|
||||||
saddr = (uintptr_t)src->dtb_tomax;
|
|
||||||
slimit = saddr + src->dtb_offset;
|
|
||||||
while (saddr < slimit) {
|
|
||||||
size_t size;
|
|
||||||
dtrace_rechdr_t *dtrh = (dtrace_rechdr_t *)saddr;
|
|
||||||
|
|
||||||
if (dtrh->dtrh_epid == DTRACE_EPIDNONE) {
|
|
||||||
saddr += sizeof (dtrace_epid_t);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
ASSERT3U(dtrh->dtrh_epid, <=, state->dts_necbs);
|
|
||||||
size = state->dts_ecbs[dtrh->dtrh_epid - 1]->dte_size;
|
|
||||||
|
|
||||||
ASSERT3U(saddr + size, <=, slimit);
|
|
||||||
ASSERT3U(size, >=, sizeof (dtrace_rechdr_t));
|
|
||||||
ASSERT3U(DTRACE_RECORD_LOAD_TIMESTAMP(dtrh), ==, UINT64_MAX);
|
|
||||||
|
|
||||||
DTRACE_RECORD_STORE_TIMESTAMP(dtrh, timestamp);
|
|
||||||
|
|
||||||
saddr += size;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Copy the buffer across. (Note that this is a
|
|
||||||
* highly subobtimal bcopy(); in the unlikely event that this becomes
|
* highly subobtimal bcopy(); in the unlikely event that this becomes
|
||||||
* a serious performance issue, a high-performance DTrace-specific
|
* a serious performance issue, a high-performance DTrace-specific
|
||||||
* bcopy() should obviously be invented.)
|
* bcopy() should obviously be invented.)
|
||||||
@ -6238,7 +6206,7 @@ dtrace_probe(dtrace_id_t id, uintptr_t arg0, uintptr_t arg1,
|
|||||||
if (now - state->dts_alive > dtrace_deadman_timeout) {
|
if (now - state->dts_alive > dtrace_deadman_timeout) {
|
||||||
/*
|
/*
|
||||||
* We seem to be dead. Unless we (a) have kernel
|
* We seem to be dead. Unless we (a) have kernel
|
||||||
* destructive permissions (b) have explicitly enabled
|
* destructive permissions (b) have expicitly enabled
|
||||||
* destructive actions and (c) destructive actions have
|
* destructive actions and (c) destructive actions have
|
||||||
* not been disabled, we're going to transition into
|
* not been disabled, we're going to transition into
|
||||||
* the KILLED state, from which no further processing
|
* the KILLED state, from which no further processing
|
||||||
@ -6266,18 +6234,8 @@ dtrace_probe(dtrace_id_t id, uintptr_t arg0, uintptr_t arg1,
|
|||||||
tomax = buf->dtb_tomax;
|
tomax = buf->dtb_tomax;
|
||||||
ASSERT(tomax != NULL);
|
ASSERT(tomax != NULL);
|
||||||
|
|
||||||
if (ecb->dte_size != 0) {
|
if (ecb->dte_size != 0)
|
||||||
dtrace_rechdr_t dtrh;
|
DTRACE_STORE(uint32_t, tomax, offs, ecb->dte_epid);
|
||||||
if (!(mstate.dtms_present & DTRACE_MSTATE_TIMESTAMP)) {
|
|
||||||
mstate.dtms_timestamp = dtrace_gethrtime();
|
|
||||||
mstate.dtms_present |= DTRACE_MSTATE_TIMESTAMP;
|
|
||||||
}
|
|
||||||
ASSERT3U(ecb->dte_size, >=, sizeof (dtrace_rechdr_t));
|
|
||||||
dtrh.dtrh_epid = ecb->dte_epid;
|
|
||||||
DTRACE_RECORD_STORE_TIMESTAMP(&dtrh,
|
|
||||||
mstate.dtms_timestamp);
|
|
||||||
*((dtrace_rechdr_t *)(tomax + offs)) = dtrh;
|
|
||||||
}
|
|
||||||
|
|
||||||
mstate.dtms_epid = ecb->dte_epid;
|
mstate.dtms_epid = ecb->dte_epid;
|
||||||
mstate.dtms_present |= DTRACE_MSTATE_EPID;
|
mstate.dtms_present |= DTRACE_MSTATE_EPID;
|
||||||
@ -6424,9 +6382,7 @@ dtrace_probe(dtrace_id_t id, uintptr_t arg0, uintptr_t arg1,
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
switch (act->dta_kind) {
|
switch (act->dta_kind) {
|
||||||
case DTRACEACT_SPECULATE: {
|
case DTRACEACT_SPECULATE:
|
||||||
dtrace_rechdr_t *dtrh;
|
|
||||||
|
|
||||||
ASSERT(buf == &state->dts_buffer[cpuid]);
|
ASSERT(buf == &state->dts_buffer[cpuid]);
|
||||||
buf = dtrace_speculation_buffer(state,
|
buf = dtrace_speculation_buffer(state,
|
||||||
cpuid, val);
|
cpuid, val);
|
||||||
@ -6448,24 +6404,11 @@ dtrace_probe(dtrace_id_t id, uintptr_t arg0, uintptr_t arg1,
|
|||||||
tomax = buf->dtb_tomax;
|
tomax = buf->dtb_tomax;
|
||||||
ASSERT(tomax != NULL);
|
ASSERT(tomax != NULL);
|
||||||
|
|
||||||
if (ecb->dte_size == 0)
|
if (ecb->dte_size != 0)
|
||||||
|
DTRACE_STORE(uint32_t, tomax, offs,
|
||||||
|
ecb->dte_epid);
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
ASSERT3U(ecb->dte_size, >=,
|
|
||||||
sizeof (dtrace_rechdr_t));
|
|
||||||
dtrh = ((void *)(tomax + offs));
|
|
||||||
dtrh->dtrh_epid = ecb->dte_epid;
|
|
||||||
/*
|
|
||||||
* When the speculation is committed, all of
|
|
||||||
* the records in the speculative buffer will
|
|
||||||
* have their timestamps set to the commit
|
|
||||||
* time. Until then, it is set to a sentinel
|
|
||||||
* value, for debugability.
|
|
||||||
*/
|
|
||||||
DTRACE_RECORD_STORE_TIMESTAMP(dtrh, UINT64_MAX);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
case DTRACEACT_PRINTM: {
|
case DTRACEACT_PRINTM: {
|
||||||
/* The DIF returns a 'memref'. */
|
/* The DIF returns a 'memref'. */
|
||||||
uintptr_t *memref = (uintptr_t *)(uintptr_t) val;
|
uintptr_t *memref = (uintptr_t *)(uintptr_t) val;
|
||||||
@ -9811,9 +9754,9 @@ dtrace_ecb_add(dtrace_state_t *state, dtrace_probe_t *probe)
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* The default size is the size of the default action: recording
|
* The default size is the size of the default action: recording
|
||||||
* the header.
|
* the epid.
|
||||||
*/
|
*/
|
||||||
ecb->dte_size = ecb->dte_needed = sizeof (dtrace_rechdr_t);
|
ecb->dte_size = ecb->dte_needed = sizeof (dtrace_epid_t);
|
||||||
ecb->dte_alignment = sizeof (dtrace_epid_t);
|
ecb->dte_alignment = sizeof (dtrace_epid_t);
|
||||||
|
|
||||||
epid = state->dts_epid++;
|
epid = state->dts_epid++;
|
||||||
@ -9911,89 +9854,122 @@ dtrace_ecb_enable(dtrace_ecb_t *ecb)
|
|||||||
static void
|
static void
|
||||||
dtrace_ecb_resize(dtrace_ecb_t *ecb)
|
dtrace_ecb_resize(dtrace_ecb_t *ecb)
|
||||||
{
|
{
|
||||||
|
uint32_t maxalign = sizeof (dtrace_epid_t);
|
||||||
|
uint32_t align = sizeof (uint8_t), offs, diff;
|
||||||
dtrace_action_t *act;
|
dtrace_action_t *act;
|
||||||
uint32_t curneeded = UINT32_MAX;
|
int wastuple = 0;
|
||||||
uint32_t aggbase = UINT32_MAX;
|
uint32_t aggbase = UINT32_MAX;
|
||||||
|
dtrace_state_t *state = ecb->dte_state;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If we record anything, we always record the dtrace_rechdr_t. (And
|
* If we record anything, we always record the epid. (And we always
|
||||||
* we always record it first.)
|
* record it first.)
|
||||||
*/
|
*/
|
||||||
ecb->dte_size = sizeof (dtrace_rechdr_t);
|
offs = sizeof (dtrace_epid_t);
|
||||||
ecb->dte_alignment = sizeof (dtrace_epid_t);
|
ecb->dte_size = ecb->dte_needed = sizeof (dtrace_epid_t);
|
||||||
|
|
||||||
for (act = ecb->dte_action; act != NULL; act = act->dta_next) {
|
for (act = ecb->dte_action; act != NULL; act = act->dta_next) {
|
||||||
dtrace_recdesc_t *rec = &act->dta_rec;
|
dtrace_recdesc_t *rec = &act->dta_rec;
|
||||||
ASSERT(rec->dtrd_size > 0 || rec->dtrd_alignment == 1);
|
|
||||||
|
|
||||||
ecb->dte_alignment = MAX(ecb->dte_alignment,
|
if ((align = rec->dtrd_alignment) > maxalign)
|
||||||
rec->dtrd_alignment);
|
maxalign = align;
|
||||||
|
|
||||||
|
if (!wastuple && act->dta_intuple) {
|
||||||
|
/*
|
||||||
|
* This is the first record in a tuple. Align the
|
||||||
|
* offset to be at offset 4 in an 8-byte aligned
|
||||||
|
* block.
|
||||||
|
*/
|
||||||
|
diff = offs + sizeof (dtrace_aggid_t);
|
||||||
|
|
||||||
|
if ((diff = (diff & (sizeof (uint64_t) - 1))))
|
||||||
|
offs += sizeof (uint64_t) - diff;
|
||||||
|
|
||||||
|
aggbase = offs - sizeof (dtrace_aggid_t);
|
||||||
|
ASSERT(!(aggbase & (sizeof (uint64_t) - 1)));
|
||||||
|
}
|
||||||
|
|
||||||
|
/*LINTED*/
|
||||||
|
if (rec->dtrd_size != 0 && (diff = (offs & (align - 1)))) {
|
||||||
|
/*
|
||||||
|
* The current offset is not properly aligned; align it.
|
||||||
|
*/
|
||||||
|
offs += align - diff;
|
||||||
|
}
|
||||||
|
|
||||||
|
rec->dtrd_offset = offs;
|
||||||
|
|
||||||
|
if (offs + rec->dtrd_size > ecb->dte_needed) {
|
||||||
|
ecb->dte_needed = offs + rec->dtrd_size;
|
||||||
|
|
||||||
|
if (ecb->dte_needed > state->dts_needed)
|
||||||
|
state->dts_needed = ecb->dte_needed;
|
||||||
|
}
|
||||||
|
|
||||||
if (DTRACEACT_ISAGG(act->dta_kind)) {
|
if (DTRACEACT_ISAGG(act->dta_kind)) {
|
||||||
dtrace_aggregation_t *agg = (dtrace_aggregation_t *)act;
|
dtrace_aggregation_t *agg = (dtrace_aggregation_t *)act;
|
||||||
|
dtrace_action_t *first = agg->dtag_first, *prev;
|
||||||
|
|
||||||
ASSERT(rec->dtrd_size != 0);
|
ASSERT(rec->dtrd_size != 0 && first != NULL);
|
||||||
ASSERT(agg->dtag_first != NULL);
|
ASSERT(wastuple);
|
||||||
ASSERT(act->dta_prev->dta_intuple);
|
|
||||||
ASSERT(aggbase != UINT32_MAX);
|
ASSERT(aggbase != UINT32_MAX);
|
||||||
ASSERT(curneeded != UINT32_MAX);
|
|
||||||
|
|
||||||
agg->dtag_base = aggbase;
|
agg->dtag_base = aggbase;
|
||||||
|
|
||||||
curneeded = P2ROUNDUP(curneeded, rec->dtrd_alignment);
|
while ((prev = first->dta_prev) != NULL &&
|
||||||
rec->dtrd_offset = curneeded;
|
DTRACEACT_ISAGG(prev->dta_kind)) {
|
||||||
curneeded += rec->dtrd_size;
|
agg = (dtrace_aggregation_t *)prev;
|
||||||
ecb->dte_needed = MAX(ecb->dte_needed, curneeded);
|
first = agg->dtag_first;
|
||||||
|
|
||||||
aggbase = UINT32_MAX;
|
|
||||||
curneeded = UINT32_MAX;
|
|
||||||
} else if (act->dta_intuple) {
|
|
||||||
if (curneeded == UINT32_MAX) {
|
|
||||||
/*
|
|
||||||
* This is the first record in a tuple. Align
|
|
||||||
* curneeded to be at offset 4 in an 8-byte
|
|
||||||
* aligned block.
|
|
||||||
*/
|
|
||||||
ASSERT(act->dta_prev == NULL ||
|
|
||||||
!act->dta_prev->dta_intuple);
|
|
||||||
ASSERT3U(aggbase, ==, UINT32_MAX);
|
|
||||||
curneeded = P2PHASEUP(ecb->dte_size,
|
|
||||||
sizeof (uint64_t), sizeof (dtrace_aggid_t));
|
|
||||||
|
|
||||||
aggbase = curneeded - sizeof (dtrace_aggid_t);
|
|
||||||
ASSERT(IS_P2ALIGNED(aggbase,
|
|
||||||
sizeof (uint64_t)));
|
|
||||||
}
|
}
|
||||||
curneeded = P2ROUNDUP(curneeded, rec->dtrd_alignment);
|
|
||||||
rec->dtrd_offset = curneeded;
|
if (prev != NULL) {
|
||||||
curneeded += rec->dtrd_size;
|
offs = prev->dta_rec.dtrd_offset +
|
||||||
|
prev->dta_rec.dtrd_size;
|
||||||
} else {
|
} else {
|
||||||
/* tuples must be followed by an aggregation */
|
offs = sizeof (dtrace_epid_t);
|
||||||
ASSERT(act->dta_prev == NULL ||
|
|
||||||
!act->dta_prev->dta_intuple);
|
|
||||||
|
|
||||||
ecb->dte_size = P2ROUNDUP(ecb->dte_size,
|
|
||||||
rec->dtrd_alignment);
|
|
||||||
rec->dtrd_offset = ecb->dte_size;
|
|
||||||
ecb->dte_size += rec->dtrd_size;
|
|
||||||
ecb->dte_needed = MAX(ecb->dte_needed, ecb->dte_size);
|
|
||||||
}
|
}
|
||||||
|
wastuple = 0;
|
||||||
|
} else {
|
||||||
|
if (!act->dta_intuple)
|
||||||
|
ecb->dte_size = offs + rec->dtrd_size;
|
||||||
|
|
||||||
|
offs += rec->dtrd_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
wastuple = act->dta_intuple;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((act = ecb->dte_action) != NULL &&
|
if ((act = ecb->dte_action) != NULL &&
|
||||||
!(act->dta_kind == DTRACEACT_SPECULATE && act->dta_next == NULL) &&
|
!(act->dta_kind == DTRACEACT_SPECULATE && act->dta_next == NULL) &&
|
||||||
ecb->dte_size == sizeof (dtrace_rechdr_t)) {
|
ecb->dte_size == sizeof (dtrace_epid_t)) {
|
||||||
/*
|
/*
|
||||||
* If the size is still sizeof (dtrace_rechdr_t), then all
|
* If the size is still sizeof (dtrace_epid_t), then all
|
||||||
* actions store no data; set the size to 0.
|
* actions store no data; set the size to 0.
|
||||||
*/
|
*/
|
||||||
|
ecb->dte_alignment = maxalign;
|
||||||
ecb->dte_size = 0;
|
ecb->dte_size = 0;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If the needed space is still sizeof (dtrace_epid_t), then
|
||||||
|
* all actions need no additional space; set the needed
|
||||||
|
* size to 0.
|
||||||
|
*/
|
||||||
|
if (ecb->dte_needed == sizeof (dtrace_epid_t))
|
||||||
|
ecb->dte_needed = 0;
|
||||||
|
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
ecb->dte_size = P2ROUNDUP(ecb->dte_size, sizeof (dtrace_epid_t));
|
/*
|
||||||
ecb->dte_needed = P2ROUNDUP(ecb->dte_needed, (sizeof (dtrace_epid_t)));
|
* Set our alignment, and make sure that the dte_size and dte_needed
|
||||||
ecb->dte_state->dts_needed = MAX(ecb->dte_state->dts_needed,
|
* are aligned to the size of an EPID.
|
||||||
ecb->dte_needed);
|
*/
|
||||||
|
ecb->dte_alignment = maxalign;
|
||||||
|
ecb->dte_size = (ecb->dte_size + (sizeof (dtrace_epid_t) - 1)) &
|
||||||
|
~(sizeof (dtrace_epid_t) - 1);
|
||||||
|
ecb->dte_needed = (ecb->dte_needed + (sizeof (dtrace_epid_t) - 1)) &
|
||||||
|
~(sizeof (dtrace_epid_t) - 1);
|
||||||
|
ASSERT(ecb->dte_size <= ecb->dte_needed);
|
||||||
}
|
}
|
||||||
|
|
||||||
static dtrace_action_t *
|
static dtrace_action_t *
|
||||||
@ -10373,7 +10349,7 @@ dtrace_ecb_action_add(dtrace_ecb_t *ecb, dtrace_actdesc_t *desc)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case DTRACEACT_SPECULATE:
|
case DTRACEACT_SPECULATE:
|
||||||
if (ecb->dte_size > sizeof (dtrace_rechdr_t))
|
if (ecb->dte_size > sizeof (dtrace_epid_t))
|
||||||
return (EINVAL);
|
return (EINVAL);
|
||||||
|
|
||||||
if (dp == NULL)
|
if (dp == NULL)
|
||||||
@ -10494,7 +10470,7 @@ dtrace_ecb_action_remove(dtrace_ecb_t *ecb)
|
|||||||
|
|
||||||
ecb->dte_action = NULL;
|
ecb->dte_action = NULL;
|
||||||
ecb->dte_action_last = NULL;
|
ecb->dte_action_last = NULL;
|
||||||
ecb->dte_size = 0;
|
ecb->dte_size = sizeof (dtrace_epid_t);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -10763,13 +10739,12 @@ dtrace_buffer_switch(dtrace_buffer_t *buf)
|
|||||||
caddr_t tomax = buf->dtb_tomax;
|
caddr_t tomax = buf->dtb_tomax;
|
||||||
caddr_t xamot = buf->dtb_xamot;
|
caddr_t xamot = buf->dtb_xamot;
|
||||||
dtrace_icookie_t cookie;
|
dtrace_icookie_t cookie;
|
||||||
hrtime_t now;
|
hrtime_t now = dtrace_gethrtime();
|
||||||
|
|
||||||
ASSERT(!(buf->dtb_flags & DTRACEBUF_NOSWITCH));
|
ASSERT(!(buf->dtb_flags & DTRACEBUF_NOSWITCH));
|
||||||
ASSERT(!(buf->dtb_flags & DTRACEBUF_RING));
|
ASSERT(!(buf->dtb_flags & DTRACEBUF_RING));
|
||||||
|
|
||||||
cookie = dtrace_interrupt_disable();
|
cookie = dtrace_interrupt_disable();
|
||||||
now = dtrace_gethrtime();
|
|
||||||
buf->dtb_tomax = xamot;
|
buf->dtb_tomax = xamot;
|
||||||
buf->dtb_xamot = tomax;
|
buf->dtb_xamot = tomax;
|
||||||
buf->dtb_xamot_drops = buf->dtb_drops;
|
buf->dtb_xamot_drops = buf->dtb_drops;
|
||||||
@ -11135,7 +11110,7 @@ dtrace_buffer_reserve(dtrace_buffer_t *buf, size_t needed, size_t align,
|
|||||||
if (epid == DTRACE_EPIDNONE) {
|
if (epid == DTRACE_EPIDNONE) {
|
||||||
size = sizeof (uint32_t);
|
size = sizeof (uint32_t);
|
||||||
} else {
|
} else {
|
||||||
ASSERT3U(epid, <=, state->dts_necbs);
|
ASSERT(epid <= state->dts_necbs);
|
||||||
ASSERT(state->dts_ecbs[epid - 1] != NULL);
|
ASSERT(state->dts_ecbs[epid - 1] != NULL);
|
||||||
|
|
||||||
size = state->dts_ecbs[epid - 1]->dte_size;
|
size = state->dts_ecbs[epid - 1]->dte_size;
|
||||||
@ -16412,7 +16387,6 @@ dtrace_ioctl(dev_t dev, int cmd, intptr_t arg, int md, cred_t *cr, int *rv)
|
|||||||
desc.dtbd_drops = buf->dtb_drops;
|
desc.dtbd_drops = buf->dtb_drops;
|
||||||
desc.dtbd_errors = buf->dtb_errors;
|
desc.dtbd_errors = buf->dtb_errors;
|
||||||
desc.dtbd_oldest = buf->dtb_xamot_offset;
|
desc.dtbd_oldest = buf->dtb_xamot_offset;
|
||||||
desc.dtbd_timestamp = dtrace_gethrtime();
|
|
||||||
|
|
||||||
mutex_exit(&dtrace_lock);
|
mutex_exit(&dtrace_lock);
|
||||||
|
|
||||||
|
@ -26,7 +26,6 @@
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2011, Joyent, Inc. All rights reserved.
|
* Copyright (c) 2011, Joyent, Inc. All rights reserved.
|
||||||
* Copyright (c) 2012 by Delphix. All rights reserved.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef _SYS_DTRACE_H
|
#ifndef _SYS_DTRACE_H
|
||||||
@ -931,10 +930,10 @@ typedef struct dtrace_ecbdesc {
|
|||||||
* DTrace Metadata Description Structures
|
* DTrace Metadata Description Structures
|
||||||
*
|
*
|
||||||
* DTrace separates the trace data stream from the metadata stream. The only
|
* DTrace separates the trace data stream from the metadata stream. The only
|
||||||
* metadata tokens placed in the data stream are the dtrace_rechdr_t (EPID +
|
* metadata tokens placed in the data stream are enabled probe identifiers
|
||||||
* timestamp) or (in the case of aggregations) aggregation identifiers. To
|
* (EPIDs) or (in the case of aggregations) aggregation identifiers. In order
|
||||||
* determine the structure of the data, DTrace consumers pass the token to the
|
* to determine the structure of the data, DTrace consumers pass the token to
|
||||||
* kernel, and receive in return a corresponding description of the enabled
|
* the kernel, and receive in return a corresponding description of the enabled
|
||||||
* probe (via the dtrace_eprobedesc structure) or the aggregation (via the
|
* probe (via the dtrace_eprobedesc structure) or the aggregation (via the
|
||||||
* dtrace_aggdesc structure). Both of these structures are expressed in terms
|
* dtrace_aggdesc structure). Both of these structures are expressed in terms
|
||||||
* of record descriptions (via the dtrace_recdesc structure) that describe the
|
* of record descriptions (via the dtrace_recdesc structure) that describe the
|
||||||
@ -1029,8 +1028,7 @@ typedef struct dtrace_fmtdesc {
|
|||||||
#define DTRACEOPT_AGGSORTREV 24 /* reverse-sort aggregations */
|
#define DTRACEOPT_AGGSORTREV 24 /* reverse-sort aggregations */
|
||||||
#define DTRACEOPT_AGGSORTPOS 25 /* agg. position to sort on */
|
#define DTRACEOPT_AGGSORTPOS 25 /* agg. position to sort on */
|
||||||
#define DTRACEOPT_AGGSORTKEYPOS 26 /* agg. key position to sort on */
|
#define DTRACEOPT_AGGSORTKEYPOS 26 /* agg. key position to sort on */
|
||||||
#define DTRACEOPT_TEMPORAL 27 /* temporally ordered output */
|
#define DTRACEOPT_MAX 27 /* number of options */
|
||||||
#define DTRACEOPT_MAX 28 /* number of options */
|
|
||||||
|
|
||||||
#define DTRACEOPT_UNSET (dtrace_optval_t)-2 /* unset option */
|
#define DTRACEOPT_UNSET (dtrace_optval_t)-2 /* unset option */
|
||||||
|
|
||||||
@ -1050,9 +1048,7 @@ typedef struct dtrace_fmtdesc {
|
|||||||
* where user-level wishes the kernel to snapshot the buffer to (the
|
* where user-level wishes the kernel to snapshot the buffer to (the
|
||||||
* dtbd_data field). The kernel uses the same structure to pass back some
|
* dtbd_data field). The kernel uses the same structure to pass back some
|
||||||
* information regarding the buffer: the size of data actually copied out, the
|
* information regarding the buffer: the size of data actually copied out, the
|
||||||
* number of drops, the number of errors, the offset of the oldest record,
|
* number of drops, the number of errors, and the offset of the oldest record.
|
||||||
* and the time of the snapshot.
|
|
||||||
*
|
|
||||||
* If the buffer policy is a "switch" policy, taking a snapshot of the
|
* If the buffer policy is a "switch" policy, taking a snapshot of the
|
||||||
* principal buffer has the additional effect of switching the active and
|
* principal buffer has the additional effect of switching the active and
|
||||||
* inactive buffers. Taking a snapshot of the aggregation buffer _always_ has
|
* inactive buffers. Taking a snapshot of the aggregation buffer _always_ has
|
||||||
@ -1065,29 +1061,8 @@ typedef struct dtrace_bufdesc {
|
|||||||
uint64_t dtbd_drops; /* number of drops */
|
uint64_t dtbd_drops; /* number of drops */
|
||||||
DTRACE_PTR(char, dtbd_data); /* data */
|
DTRACE_PTR(char, dtbd_data); /* data */
|
||||||
uint64_t dtbd_oldest; /* offset of oldest record */
|
uint64_t dtbd_oldest; /* offset of oldest record */
|
||||||
uint64_t dtbd_timestamp; /* hrtime of snapshot */
|
|
||||||
} dtrace_bufdesc_t;
|
} dtrace_bufdesc_t;
|
||||||
|
|
||||||
/*
|
|
||||||
* Each record in the buffer (dtbd_data) begins with a header that includes
|
|
||||||
* the epid and a timestamp. The timestamp is split into two 4-byte parts
|
|
||||||
* so that we do not require 8-byte alignment.
|
|
||||||
*/
|
|
||||||
typedef struct dtrace_rechdr {
|
|
||||||
dtrace_epid_t dtrh_epid; /* enabled probe id */
|
|
||||||
uint32_t dtrh_timestamp_hi; /* high bits of hrtime_t */
|
|
||||||
uint32_t dtrh_timestamp_lo; /* low bits of hrtime_t */
|
|
||||||
} dtrace_rechdr_t;
|
|
||||||
|
|
||||||
#define DTRACE_RECORD_LOAD_TIMESTAMP(dtrh) \
|
|
||||||
((dtrh)->dtrh_timestamp_lo + \
|
|
||||||
((uint64_t)(dtrh)->dtrh_timestamp_hi << 32))
|
|
||||||
|
|
||||||
#define DTRACE_RECORD_STORE_TIMESTAMP(dtrh, hrtime) { \
|
|
||||||
(dtrh)->dtrh_timestamp_lo = (uint32_t)hrtime; \
|
|
||||||
(dtrh)->dtrh_timestamp_hi = hrtime >> 32; \
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* DTrace Status
|
* DTrace Status
|
||||||
*
|
*
|
||||||
|
@ -23,7 +23,6 @@
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright 2007 Sun Microsystems, Inc. All rights reserved.
|
* Copyright 2007 Sun Microsystems, Inc. All rights reserved.
|
||||||
* Copyright (c) 2012 by Delphix. All rights reserved.
|
|
||||||
* Use is subject to license terms.
|
* Use is subject to license terms.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -210,18 +209,15 @@ typedef struct dtrace_hash {
|
|||||||
* predicate is non-NULL, the DIF object is executed. If the result is
|
* predicate is non-NULL, the DIF object is executed. If the result is
|
||||||
* non-zero, the action list is processed, with each action being executed
|
* non-zero, the action list is processed, with each action being executed
|
||||||
* accordingly. When the action list has been completely executed, processing
|
* accordingly. When the action list has been completely executed, processing
|
||||||
* advances to the next ECB. The ECB abstraction allows disjoint consumers
|
* advances to the next ECB. processing advances to the next ECB. If the
|
||||||
* to multiplex on single probes.
|
* result is non-zero; For each ECB, it first determines the The ECB
|
||||||
*
|
* abstraction allows disjoint consumers to multiplex on single probes.
|
||||||
* Execution of the ECB results in consuming dte_size bytes in the buffer
|
|
||||||
* to record data. During execution, dte_needed bytes must be available in
|
|
||||||
* the buffer. This space is used for both recorded data and tuple data.
|
|
||||||
*/
|
*/
|
||||||
struct dtrace_ecb {
|
struct dtrace_ecb {
|
||||||
dtrace_epid_t dte_epid; /* enabled probe ID */
|
dtrace_epid_t dte_epid; /* enabled probe ID */
|
||||||
uint32_t dte_alignment; /* required alignment */
|
uint32_t dte_alignment; /* required alignment */
|
||||||
size_t dte_needed; /* space needed for execution */
|
size_t dte_needed; /* bytes needed */
|
||||||
size_t dte_size; /* size of recorded payload */
|
size_t dte_size; /* total size of payload */
|
||||||
dtrace_predicate_t *dte_predicate; /* predicate, if any */
|
dtrace_predicate_t *dte_predicate; /* predicate, if any */
|
||||||
dtrace_action_t *dte_action; /* actions, if any */
|
dtrace_action_t *dte_action; /* actions, if any */
|
||||||
dtrace_ecb_t *dte_next; /* next ECB on probe */
|
dtrace_ecb_t *dte_next; /* next ECB on probe */
|
||||||
@ -279,20 +275,17 @@ typedef struct dtrace_aggregation {
|
|||||||
* the EPID, the consumer can determine the data layout. (The data buffer
|
* the EPID, the consumer can determine the data layout. (The data buffer
|
||||||
* layout is shown schematically below.) By assuring that one can determine
|
* layout is shown schematically below.) By assuring that one can determine
|
||||||
* data layout from the EPID, the metadata stream can be separated from the
|
* data layout from the EPID, the metadata stream can be separated from the
|
||||||
* data stream -- simplifying the data stream enormously. The ECB always
|
* data stream -- simplifying the data stream enormously.
|
||||||
* proceeds the recorded data as part of the dtrace_rechdr_t structure that
|
|
||||||
* includes the EPID and a high-resolution timestamp used for output ordering
|
|
||||||
* consistency.
|
|
||||||
*
|
*
|
||||||
* base of data buffer ---> +--------+--------------------+--------+
|
* base of data buffer ---> +------+--------------------+------+
|
||||||
* | rechdr | data | rechdr |
|
* | EPID | data | EPID |
|
||||||
* +--------+------+--------+----+--------+
|
* +------+--------+------+----+------+
|
||||||
* | data | rechdr | data |
|
* | data | EPID | data |
|
||||||
* +---------------+--------+-------------+
|
* +---------------+------+-----------+
|
||||||
* | data, cont. |
|
* | data, cont. |
|
||||||
* +--------+--------------------+--------+
|
* +------+--------------------+------+
|
||||||
* | rechdr | data | |
|
* | EPID | data | |
|
||||||
* +--------+--------------------+ |
|
* +------+--------------------+ |
|
||||||
* | || |
|
* | || |
|
||||||
* | || |
|
* | || |
|
||||||
* | \/ |
|
* | \/ |
|
||||||
@ -302,7 +295,7 @@ typedef struct dtrace_aggregation {
|
|||||||
* . .
|
* . .
|
||||||
* : :
|
* : :
|
||||||
* | |
|
* | |
|
||||||
* limit of data buffer ---> +--------------------------------------+
|
* limit of data buffer ---> +----------------------------------+
|
||||||
*
|
*
|
||||||
* When evaluating an ECB, dtrace_probe() determines if the ECB's needs of the
|
* When evaluating an ECB, dtrace_probe() determines if the ECB's needs of the
|
||||||
* principal buffer (both scratch and payload) exceed the available space. If
|
* principal buffer (both scratch and payload) exceed the available space. If
|
||||||
|
Loading…
Reference in New Issue
Block a user