[DTrace-devel] [PATCH] Refactor the versioning handling system

Kris Van Hees kris.van.hees at oracle.com
Fri Feb 28 03:09:59 UTC 2025


DTrace was handlings versioning data in multiple locations, causing
common mistakes in not consistently updating versions in allplaces.
By consolidating all versioning data in dt_version.h a single file
need to be updated (as far as the source tree is concerned) when a
new version is introduced.

For building, the GNUmakefile and dtrace.spec files will also need
to be updated with the new version number.

Signed-off-by: Kris Van Hees <kris.van.hees at oracle.com>
---
 libdtrace/Build        |   1 +
 libdtrace/dt_impl.h    |  48 ++++++++-----------
 libdtrace/dt_open.c    |  19 --------
 libdtrace/dt_subr.c    |  80 --------------------------------
 libdtrace/dt_version.c |  93 +++++++++++++++++++++++++++++++++++++
 libdtrace/dt_version.h | 102 ++++++++++++++++++++++++++++-------------
 6 files changed, 181 insertions(+), 162 deletions(-)
 create mode 100644 libdtrace/dt_version.c

diff --git a/libdtrace/Build b/libdtrace/Build
index 51e0f078..57804f55 100644
--- a/libdtrace/Build
+++ b/libdtrace/Build
@@ -70,6 +70,7 @@ libdtrace-build_SOURCES = dt_aggregate.c \
 			  dt_strtab.c \
 			  dt_subr.c \
 			  dt_symtab.c \
+			  dt_version.c \
 			  dt_work.c \
 			  dt_xlator.c
 
diff --git a/libdtrace/dt_impl.h b/libdtrace/dt_impl.h
index 68fb8ec5..60e9b0c9 100644
--- a/libdtrace/dt_impl.h
+++ b/libdtrace/dt_impl.h
@@ -256,8 +256,6 @@ typedef struct dt_percpu_drops {
  */
 #define DT_MAX_NSPECS 16		/* sanity upper bound on speculations */
 
-typedef uint32_t dt_version_t;		/* encoded version (see below) */
-
 struct dtrace_hdl {
 	const dtrace_vector_t *dt_vector; /* library vector, if vectored open */
 	void *dt_varg;	/* vector argument, if vectored open */
@@ -645,6 +643,24 @@ enum {
 	EDT_PRINT,		/* missing or corrupt print() record */
 };
 
+/*
+ * Stability definitions
+ *
+ * These #defines are used in the tables of identifiers below to fill in the
+ * attribute fields associated with each identifier.  The DT_ATTR_* macros are
+ * a convenience to permit more concise declarations of common attributes such
+ * as Stable/Stable/Common.
+ *
+ * Refer to the Solaris Dynamic Tracing Guide Stability chapter respectively
+ * for an explanation of these DTrace features and their values.
+ */
+#define DT_ATTR_STABCMN { DTRACE_STABILITY_STABLE, \
+	DTRACE_STABILITY_STABLE, DTRACE_CLASS_COMMON }
+
+#define DT_ATTR_EVOLCMN { DTRACE_STABILITY_EVOLVING, \
+	DTRACE_STABILITY_EVOLVING, DTRACE_CLASS_COMMON \
+}
+
 /*
  * Interfaces for parsing and comparing DTrace attribute tuples, which describe
  * stability and architectural binding information.
@@ -654,31 +670,6 @@ extern dtrace_attribute_t dt_attr_max(dtrace_attribute_t, dtrace_attribute_t);
 extern char *dt_attr_str(dtrace_attribute_t, char *, size_t);
 extern int dt_attr_cmp(dtrace_attribute_t, dtrace_attribute_t);
 
-/*
- * Interfaces for parsing and handling DTrace version strings.  Version binding
- * is a feature of the D compiler that is handled completely independently of
- * the DTrace kernel infrastructure, so the definitions are here in libdtrace.
- * Version strings are compiled into an encoded uint32_t which can be compared
- * using C comparison operators.  Version definitions are found in dt_open.c.
- */
-#define	DT_VERSION_STRMAX	16	/* enough for "255.4095.4095\0" */
-#define	DT_VERSION_MAJMAX	0xFF	/* maximum major version number */
-#define	DT_VERSION_MINMAX	0xFFF	/* maximum minor version number */
-#define	DT_VERSION_MICMAX	0xFFF	/* maximum micro version number */
-
-#define	DT_VERSION_NUMBER(M, m, u) \
-	((((M) & 0xFF) << 24) | (((m) & 0xFFF) << 12) | ((u) & 0xFFF))
-
-#define	DT_VERSION_MAJOR(v)	(((v) & 0xFF000000) >> 24)
-#define	DT_VERSION_MINOR(v)	(((v) & 0x00FFF000) >> 12)
-#define	DT_VERSION_MICRO(v)	((v) & 0x00000FFF)
-
-extern char *dt_version_num2str(dt_version_t, char *, size_t);
-extern int dt_version_str2num(const char *, dt_version_t *);
-extern int dt_version_defined(dt_version_t);
-
-extern int dt_str2kver(const char *, dt_version_t *);
-
 extern uint32_t dt_gen_hval(const char *, uint32_t, size_t);
 
 /*
@@ -816,9 +807,6 @@ extern const dtrace_attribute_t _dtrace_typattr; /* type ref attributes */
 extern const dtrace_attribute_t _dtrace_prvattr; /* provider attributes */
 extern const dtrace_pattr_t _dtrace_prvdesc;	 /* provider attribute bundle */
 
-extern const dt_version_t _dtrace_versions[];	 /* array of valid versions */
-extern const char *const _dtrace_version;	 /* current version string */
-
 extern int _dtrace_strbuckets;		/* number of hash buckets for strings */
 extern uint_t _dtrace_stkindent;	/* default indent for stack/ustack */
 extern uint_t _dtrace_pidbuckets;	/* number of hash buckets for pids */
diff --git a/libdtrace/dt_open.c b/libdtrace/dt_open.c
index 51c056b2..72c138ce 100644
--- a/libdtrace/dt_open.c
+++ b/libdtrace/dt_open.c
@@ -42,25 +42,6 @@
 #include <dt_peb.h>
 #include <dt_pid.h>
 
-const dt_version_t _dtrace_versions[] = {
-	DT_VERS_1_0,	/* D API 1.0.0 (PSARC 2001/466) Solaris 10 FCS */
-	DT_VERS_1_1,	/* D API 1.1.0 Solaris Express 6/05 */
-	DT_VERS_1_2,	/* D API 1.2.0 Solaris 10 Update 1 */
-	DT_VERS_1_2_1,	/* D API 1.2.1 Solaris Express 4/06 */
-	DT_VERS_1_2_2,	/* D API 1.2.2 Solaris Express 6/06 */
-	DT_VERS_1_3,	/* D API 1.3 Solaris Express 10/06 */
-	DT_VERS_1_4,	/* D API 1.4 Solaris Express 2/07 */
-	DT_VERS_1_4_1,	/* D API 1.4.1 Solaris Express 4/07 */
-	DT_VERS_1_5,	/* D API 1.5 Solaris Express 7/07 */
-	DT_VERS_1_6,	/* D API 1.6 */
-	DT_VERS_1_6_1,	/* D API 1.6.1 */
-	DT_VERS_1_6_2,	/* D API 1.6.2 */
-	DT_VERS_1_6_3,	/* D API 1.6.3 */
-	DT_VERS_1_6_4,	/* D API 1.6.4 */
-	DT_VERS_2_0,	/* D API 2.0 */
-	0
-};
-
 /*
  * Table of global identifiers.  This is used to populate the global identifier
  * hash when a new dtrace client open occurs.  For more info see dt_ident.h.
diff --git a/libdtrace/dt_subr.c b/libdtrace/dt_subr.c
index d5dca164..40b66c7d 100644
--- a/libdtrace/dt_subr.c
+++ b/libdtrace/dt_subr.c
@@ -369,58 +369,6 @@ dt_attr_str(dtrace_attribute_t a, char *buf, size_t len)
 	return buf;
 }
 
-char *
-dt_version_num2str(dt_version_t v, char *buf, size_t len)
-{
-	uint_t M = DT_VERSION_MAJOR(v);
-	uint_t m = DT_VERSION_MINOR(v);
-	uint_t u = DT_VERSION_MICRO(v);
-
-	if (u == 0)
-		snprintf(buf, len, "%u.%u", M, m);
-	else
-		snprintf(buf, len, "%u.%u.%u", M, m, u);
-
-	return buf;
-}
-
-int
-dt_version_str2num(const char *s, dt_version_t *vp)
-{
-	int i = 0, n[3] = { 0, 0, 0 };
-	char c;
-
-	while ((c = *s++) != '\0') {
-		if (isdigit(c))
-			n[i] = n[i] * 10 + c - '0';
-		else if (c != '.' || i++ >= sizeof(n) / sizeof(n[0]) - 1)
-			return -1;
-	}
-
-	if (n[0] > DT_VERSION_MAJMAX ||
-	    n[1] > DT_VERSION_MINMAX ||
-	    n[2] > DT_VERSION_MICMAX)
-		return -1;
-
-	if (vp != NULL)
-		*vp = DT_VERSION_NUMBER(n[0], n[1], n[2]);
-
-	return 0;
-}
-
-int
-dt_version_defined(dt_version_t v)
-{
-	int i;
-
-	for (i = 0; _dtrace_versions[i] != 0; i++) {
-		if (_dtrace_versions[i] == v)
-			return 1;
-	}
-
-	return 0;
-}
-
 char *
 dt_cpp_add_arg(dtrace_hdl_t *dtp, const char *str)
 {
@@ -949,34 +897,6 @@ dtrace_uaddr2str(dtrace_hdl_t *dtp, pid_t pid, uint64_t addr, char *str,
 	return dt_string2str(c, str, nbytes);
 }
 
-/*
- * The function converts string representation of kernel version
- * into the dt_version_t type.
- */
-int
-dt_str2kver(const char *kverstr, dt_version_t *vp)
-{
-	int		kv1, kv2, kv3;
-	int		rval;
-
-	rval = sscanf(kverstr, "%d.%d.%d", &kv1, &kv2, &kv3);
-
-	switch (rval) {
-	case 2:
-		kv3 = 0;
-		break;
-	case 3:
-		break;
-	default:
-		return -1;
-	}
-
-	if (vp)
-		*vp = DT_VERSION_NUMBER(kv1, kv2, kv3);
-
-	return 0;
-}
-
 /*
  * Compute a 32-bit hash value for a memory block of given size.
  */
diff --git a/libdtrace/dt_version.c b/libdtrace/dt_version.c
new file mode 100644
index 00000000..e9ac88be
--- /dev/null
+++ b/libdtrace/dt_version.c
@@ -0,0 +1,93 @@
+/*
+ * Oracle Linux DTrace.
+ * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved.
+ * Licensed under the Universal Permissive License v 1.0 as shown at
+ * http://oss.oracle.com/licenses/upl.
+ */
+
+#include <stdio.h>
+#include <ctype.h>
+
+#include <dt_impl.h>
+
+const dt_version_t _dtrace_versions[] = DTRACE_VERSIONS;
+
+char *
+dt_version_num2str(dt_version_t v, char *buf, size_t len)
+{
+	uint_t	M = DT_VERSION_MAJOR(v);
+	uint_t	m = DT_VERSION_MINOR(v);
+	uint_t	u = DT_VERSION_MICRO(v);
+
+	if (u == 0)
+		snprintf(buf, len, "%u.%u", M, m);
+	else
+		snprintf(buf, len, "%u.%u.%u", M, m, u);
+
+	return buf;
+}
+
+int
+dt_version_str2num(const char *s, dt_version_t *vp)
+{
+	int	i = 0, n[3] = { 0, 0, 0 };
+	char	c;
+
+	while ((c = *s++) != '\0') {
+		if (isdigit(c))
+			n[i] = n[i] * 10 + c - '0';
+		else if (c != '.' || i++ >= ARRAY_SIZE(n) - 1)
+			return -1;
+	}
+
+	if (n[0] > DT_VERSION_MAJMAX ||
+	    n[1] > DT_VERSION_MINMAX ||
+	    n[2] > DT_VERSION_MICMAX)
+		return -1;
+
+	if (vp != NULL)
+		*vp = DT_VERSION_NUMBER(n[0], n[1], n[2]);
+
+	return 0;
+}
+
+int
+dt_version_defined(dt_version_t v)
+{
+	int	i;
+
+	for (i = 0; i < ARRAY_SIZE(_dtrace_versions); i++) {
+		if (_dtrace_versions[i] == v)
+			return 1;
+	}
+
+	return 0;
+}
+
+/*
+ * Convert a string representation of a kernel version string into the
+ * a dt_version_t value.
+ */
+int
+dt_str2kver(const char *kverstr, dt_version_t *vp)
+{
+	int	kv1, kv2, kv3;
+	int	rval;
+
+	rval = sscanf(kverstr, "%d.%d.%d", &kv1, &kv2, &kv3);
+
+	switch (rval) {
+	case 2:
+		kv3 = 0;
+		break;
+	case 3:
+		break;
+	default:
+		return -1;
+	}
+
+	if (vp)
+		*vp = DT_VERSION_NUMBER(kv1, kv2, kv3);
+
+	return 0;
+}
diff --git a/libdtrace/dt_version.h b/libdtrace/dt_version.h
index 3fd1b3d1..967e22cc 100644
--- a/libdtrace/dt_version.h
+++ b/libdtrace/dt_version.h
@@ -15,24 +15,6 @@ extern "C" {
 #include <dt_ident.h>
 #include <dt_git_version.h>
 
-/*
- * Stability definitions
- *
- * These #defines are used in the tables of identifiers below to fill in the
- * attribute fields associated with each identifier.  The DT_ATTR_* macros are
- * a convenience to permit more concise declarations of common attributes such
- * as Stable/Stable/Common.
- *
- * Refer to the Solaris Dynamic Tracing Guide Stability chapter respectively
- * for an explanation of these DTrace features and their values.
- */
-#define DT_ATTR_STABCMN { DTRACE_STABILITY_STABLE, \
-	DTRACE_STABILITY_STABLE, DTRACE_CLASS_COMMON }
-
-#define DT_ATTR_EVOLCMN { DTRACE_STABILITY_EVOLVING, \
-	DTRACE_STABILITY_EVOLVING, DTRACE_CLASS_COMMON \
-}
-
 /*
  * Versioning definitions
  *
@@ -46,9 +28,11 @@ extern "C" {
  * Refer to the Solaris Dynamic Tracing Guide Versioning chapter for an
  * explanation of these DTrace features and their values.
  *
- * You must update DT_VERS_LATEST and DT_VERS_STRING when adding a new version,
- * and then add the new version to the _dtrace_versions[] array declared in
- * dt_open.c..
+ * When adding a new version:
+ *  - Add a new DT_VERS_* macro
+ *  - Add the new DT_VERS_* macro at the end of the DTRACE_VERSIONS macro
+ *  - Set DT_VERS_LATEST to the new DT_VERS_*
+ *  - Update DT_VERS_STRING to reflect the new version
  *
  * NOTE: Although the DTrace versioning scheme supports the labeling and
  *       introduction of incompatible changes (e.g. dropping an interface in a
@@ -57,16 +41,18 @@ extern "C" {
  *       we ever need to provide divergent interfaces, this will need work.
  *
  * The version number should be increased for every customer visible release
- * of Solaris. The major number should be incremented when a fundamental
- * 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
- * incremented when a change is introduced that could break scripts that had
- * previously worked; for example, adding a new built-in variable could break
- * a script which was already using that identifier. The micro number should
- * be changed when introducing functionality changes or major bug fixes that
- * do not affect backward compatibility -- this is merely to make capabilities
- * easily determined from the version number. Minor bugs do not require any
- * modification to the version number.
+ * of Linux.
+ *  - The major number should be incremented when a fundamental 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 incremented when a change is introduced that
+ *    could break scripts that had previously worked; for example, adding a new
+ *    built-in variable could break a script which was already using that
+ *    identifier.
+ *  - The micro number should be changed when introducing functionality changes
+ *    or major bug fixes that do not affect backward compatibility -- this is
+ *    merely to make capabilities easily determined from the version number.
+ *    Minor bugs do not require any modification to the version number.
  */
 #define	DT_VERS_1_0	DT_VERSION_NUMBER(1, 0, 0)
 #define	DT_VERS_1_1	DT_VERSION_NUMBER(1, 1, 0)
@@ -84,9 +70,59 @@ extern "C" {
 #define	DT_VERS_1_6_4	DT_VERSION_NUMBER(1, 6, 4)
 #define	DT_VERS_2_0	DT_VERSION_NUMBER(2, 0, 0)
 #define	DT_VERS_2_0_1	DT_VERSION_NUMBER(2, 0, 1)
+#define	DT_VERS_2_0_2	DT_VERSION_NUMBER(2, 0, 2)
+
+#define DTRACE_VERSIONS	{ \
+	DT_VERS_1_1,	/* D API 1.1.0 Solaris Express 6/05 */ \
+	DT_VERS_1_2,	/* D API 1.2.0 Solaris 10 Update 1 */ \
+	DT_VERS_1_2_1,	/* D API 1.2.1 Solaris Express 4/06 */ \
+	DT_VERS_1_2_2,	/* D API 1.2.2 Solaris Express 6/06 */ \
+	DT_VERS_1_3,	/* D API 1.3 Solaris Express 10/06 */ \
+	DT_VERS_1_4,	/* D API 1.4 Solaris Express 2/07 */ \
+	DT_VERS_1_4_1,	/* D API 1.4.1 Solaris Express 4/07 */ \
+	DT_VERS_1_5,	/* D API 1.5 Solaris Express 7/07 */ \
+	DT_VERS_1_6,	/* D API 1.6 */ \
+	DT_VERS_1_6_1,	/* D API 1.6.1 */ \
+	DT_VERS_1_6_2,	/* D API 1.6.2 */ \
+	DT_VERS_1_6_3,	/* D API 1.6.3 */ \
+	DT_VERS_1_6_4,	/* D API 1.6.4 */ \
+	DT_VERS_2_0,	/* D API 2.0 */ \
+	DT_VERS_2_0_1,	/* D API 2.0.1 */ \
+	DT_VERS_2_0_2,	/* D API 2.0.2 */ \
+}
+
+#define	DT_VERS_LATEST	DT_VERS_2_0_2
+#define	DT_VERS_STRING	"Oracle D 2.0.2"
+
+/*
+ * Interfaces for parsing and handling DTrace version strings.  Version binding
+ * is a feature of the D compiler that is handled completely independently of
+ * the DTrace kernel infrastructure, so the definitions are here in libdtrace.
+ * Version strings are compiled into an encoded uint32_t which can be compared
+ * using C comparison operators.
+ */
+#define	DT_VERSION_STRMAX	16	/* enough for "255.4095.4095\0" */
+#define	DT_VERSION_MAJMAX	0xFF	/* maximum major version number */
+#define	DT_VERSION_MINMAX	0xFFF	/* maximum minor version number */
+#define	DT_VERSION_MICMAX	0xFFF	/* maximum micro version number */
+
+#define	DT_VERSION_NUMBER(M, m, u) \
+	((((M) & 0xFF) << 24) | (((m) & 0xFFF) << 12) | ((u) & 0xFFF))
+
+#define	DT_VERSION_MAJOR(v)	(((v) & 0xFF000000) >> 24)
+#define	DT_VERSION_MINOR(v)	(((v) & 0x00FFF000) >> 12)
+#define	DT_VERSION_MICRO(v)	((v) & 0x00000FFF)
+
+typedef uint32_t dt_version_t;
+
+extern const dt_version_t _dtrace_versions[];
+extern const char *const _dtrace_version;
+
+extern char *dt_version_num2str(dt_version_t, char *, size_t);
+extern int dt_version_str2num(const char *, dt_version_t *);
+extern int dt_version_defined(dt_version_t);
 
-#define	DT_VERS_LATEST	DT_VERS_2_0_1
-#define	DT_VERS_STRING	"Oracle D 2.0"
+extern int dt_str2kver(const char *, dt_version_t *);
 
 #ifdef  __cplusplus
 }
-- 
2.45.2




More information about the DTrace-devel mailing list