VirtualBox

source: vbox/trunk/src/VBox/ExtPacks/VBoxDTrace/VBoxDTraceWrapper.cpp@ 107044

Last change on this file since 107044 was 106061, checked in by vboxsync, 2 months ago

Copyright year updates by scm.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 7.7 KB
Line 
1/* $Id: VBoxDTraceWrapper.cpp 106061 2024-09-16 14:03:52Z vboxsync $ */
2/** @file
3 * VBoxDTrace - Wrapper that selects the right dtrace implemetation and adds
4 * our library to the search path.
5 */
6
7/*
8 * Copyright (C) 2016-2024 Oracle and/or its affiliates.
9 *
10 * This file is part of VirtualBox base platform packages, as
11 * available from http://www.virtualbox.org.
12 *
13 * The contents of this file are subject to the terms of the Common
14 * Development and Distribution License Version 1.0 (CDDL) only, as it
15 * comes in the "COPYING.CDDL" file of the VirtualBox distribution.
16 *
17 * SPDX-License-Identifier: CDDL-1.0
18 */
19
20
21/*********************************************************************************************************************************
22* Header Files *
23*********************************************************************************************************************************/
24#include <iprt/buildconfig.h>
25#include <iprt/env.h>
26#include <iprt/file.h>
27#include <iprt/initterm.h>
28#include <iprt/ldr.h>
29#include <iprt/message.h>
30#include <iprt/path.h>
31#include <iprt/process.h>
32#include <iprt/string.h>
33
34#include <VBox/sup.h>
35
36#include "../../Main/include/ExtPackUtil.h"
37
38
39/*********************************************************************************************************************************
40* Defined Constants And Macros *
41*********************************************************************************************************************************/
42/** The VBoxDTrace extension pack name. */
43#define VBOX_EXTPACK_VBOXDTRACE_NAME "Oracle VBoxDTrace Extension Pack"
44/** The mangled version of VBOX_EXTPACK_VBOXDTRACE_NAME (also in Config.kmk). */
45#define VBOX_EXTPACK_VBOXDTRACE_MANGLED_NAME "Oracle_VBoxDTrace_Extension_Pack"
46
47
48/*********************************************************************************************************************************
49* Structures and Typedefs *
50*********************************************************************************************************************************/
51/** The main function of VBoxDTrace.so/dylib/dll. */
52typedef int (RTCALL *PFNVBOXDTRACEMAIN)(int argc, char **argv);
53
54
55int main(int argc, char **argv)
56{
57 /*
58 * Init IPRT.
59 */
60 int rc = RTR3InitExe(argc, &argv, 0);
61 if (RT_FAILURE(rc))
62 return RTMsgInitFailure(rc);
63
64 /*
65 * Locate a native DTrace command binary.
66 */
67 bool fIsNativeDTrace = false;
68 char szDTraceCmd[RTPATH_MAX];
69 szDTraceCmd[0] = '\0';
70
71#if defined(RT_OS_DARWIN) || defined(RT_OS_FREEBSD) || defined(RT_OS_LINUX) || defined(RT_OS_SOLARIS)
72 /*
73 * 1. Try native first on platforms where it's applicable.
74 */
75 static const char * const s_apszNativeDTrace[] =
76 {
77 "/usr/sbin/dtrace",
78 "/sbin/dtrace",
79 "/usr/bin/dtrace",
80 "/bin/dtrace",
81 "/usr/local/sbin/dtrace",
82 "/usr/local/bin/dtrace"
83 };
84 if (!RTEnvExist("VBOX_DTRACE_NO_NATIVE"))
85 for (uint32_t i = 0; i < RT_ELEMENTS(s_apszNativeDTrace); i++)
86 if (RTFileExists(s_apszNativeDTrace[i]))
87 {
88 fIsNativeDTrace = true;
89 strcpy(szDTraceCmd, s_apszNativeDTrace[i]);
90# ifdef RT_OS_LINUX
91 /** @todo Warn if the dtrace modules haven't been loaded or vboxdrv isn't
92 * compiled against them. */
93# endif
94 break;
95 }
96 if (szDTraceCmd[0] == '\0')
97#endif
98 {
99 /*
100 * 2. VBoxDTrace extension pack installed?
101 *
102 * Note! We cannot use the COM API here because this program is usually
103 * run thru sudo or directly as root, even if the target
104 * VirtualBox process is running as regular user. This is due to
105 * the privileges required to run dtrace scripts on a host.
106 */
107 rc = RTPathAppPrivateArch(szDTraceCmd, sizeof(szDTraceCmd));
108 if (RT_SUCCESS(rc))
109 rc = RTPathAppend(szDTraceCmd, sizeof(szDTraceCmd),
110 VBOX_EXTPACK_INSTALL_DIR RTPATH_SLASH_STR VBOX_EXTPACK_VBOXDTRACE_MANGLED_NAME);
111 if (RT_SUCCESS(rc))
112 rc = RTPathAppend(szDTraceCmd, sizeof(szDTraceCmd), RTBldCfgTargetDotArch());
113 if (RT_SUCCESS(rc))
114 rc = RTPathAppend(szDTraceCmd, sizeof(szDTraceCmd), "VBoxDTraceCmd");
115 if (RT_SUCCESS(rc))
116 rc = RTStrCat(szDTraceCmd, sizeof(szDTraceCmd), RTLdrGetSuff());
117 if (RT_FAILURE(rc))
118 return RTMsgErrorExit(RTEXITCODE_FAILURE, "Error constructing extension pack path: %Rrc", rc);
119 if (!RTFileExists(szDTraceCmd))
120 return RTMsgErrorExit(RTEXITCODE_FAILURE,
121 "Unable to find a DTrace implementation. VBoxDTrace Extension Pack installed?");
122 fIsNativeDTrace = false;
123 }
124
125
126 /*
127 * Construct a new command line that includes our libary.
128 */
129 char szDTraceLibDir[RTPATH_MAX];
130 rc = RTPathAppPrivateNoArch(szDTraceLibDir, sizeof(szDTraceLibDir));
131 if (RT_SUCCESS(rc))
132 rc = RTPathAppend(szDTraceLibDir, sizeof(szDTraceLibDir), "dtrace" RTPATH_SLASH_STR "lib");
133 if (RT_SUCCESS(rc))
134 rc = RTPathAppend(szDTraceLibDir, sizeof(szDTraceLibDir), RTBldCfgTargetArch());
135 if (RT_FAILURE(rc))
136 return RTMsgErrorExit(RTEXITCODE_FAILURE, "Error constructing dtrace library path for VBox: %Rrc", rc);
137
138 char **papszArgs = (char **)RTMemAlloc((argc + 3) * sizeof(char *));
139 if (!papszArgs)
140 return RTMsgErrorExit(RTEXITCODE_FAILURE, "No memory for argument list.");
141
142 int cArgs = 1;
143 papszArgs[0] = fIsNativeDTrace ? szDTraceCmd : argv[0];
144 if (argc > 1)
145 {
146 papszArgs[cArgs++] = (char *)"-L";
147 papszArgs[cArgs++] = szDTraceLibDir;
148 }
149 for (int i = 1; i < argc; i++)
150 papszArgs[cArgs++] = argv[i];
151 papszArgs[cArgs] = NULL;
152 Assert(cArgs <= argc + 3);
153
154
155 /*
156 * The native DTrace we execute as a sub-process and wait for.
157 */
158 RTEXITCODE rcExit;
159 if (fIsNativeDTrace)
160 {
161 RTPROCESS hProc;
162 rc = RTProcCreate(szDTraceCmd, papszArgs, RTENV_DEFAULT, 0, &hProc);
163 if (RT_SUCCESS(rc))
164 {
165 RTPROCSTATUS Status;
166 rc = RTProcWait(hProc, RTPROCWAIT_FLAGS_BLOCK, &Status);
167 if (RT_SUCCESS(rc))
168 {
169 if (Status.enmReason == RTPROCEXITREASON_NORMAL)
170 rcExit = (RTEXITCODE)Status.iStatus;
171 else
172 rcExit = RTEXITCODE_FAILURE;
173 }
174 else
175 rcExit = RTMsgErrorExit(RTEXITCODE_FAILURE, "Error waiting for child process: %Rrc", rc);
176 }
177 else
178 rcExit = RTMsgErrorExit(RTEXITCODE_FAILURE, "Error executing '%s': %Rrc", szDTraceCmd, rc);
179 }
180 /*
181 * While the VBoxDTrace we load and call the main function of.
182 */
183 else
184 {
185 RTERRINFOSTATIC ErrInfo;
186 RTLDRMOD hMod;
187 rc = SUPR3HardenedLdrLoadPlugIn(szDTraceCmd, &hMod, RTErrInfoInitStatic(&ErrInfo));
188 if (RT_SUCCESS(rc))
189 {
190 PFNVBOXDTRACEMAIN pfnVBoxDTraceMain;
191 rc = RTLdrGetSymbol(hMod, "VBoxDTraceMain", (void **)&pfnVBoxDTraceMain);
192 if (RT_SUCCESS(rc))
193 rcExit = (RTEXITCODE)pfnVBoxDTraceMain(cArgs, papszArgs);
194 else
195 rcExit = RTMsgErrorExit(RTEXITCODE_FAILURE, "Error locating 'VBoxDTraceMain' in '%s': %Rrc", szDTraceCmd, rc);
196 }
197 else
198 rcExit = RTMsgErrorExit(RTEXITCODE_FAILURE, "Error loading '%s': %Rrc (%s)", szDTraceCmd, rc, ErrInfo.szMsg);
199 }
200 return rcExit;
201}
202
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette