build: drop legacy v2 service and simplify build system

This removes -Dagent and just uses -Dtools as it only affects sysprof-cli
and sysprof-agent. We still need to patch sysprof-cli for recent changes
as we did for sysprof-agent though.

Additionally, we haven't used the v2 service in forever, so drop that as
I can't imagine anyone has been using it.
This commit is contained in:
Christian Hergert
2023-07-17 15:11:10 -07:00
parent 72be6491b6
commit 1fba250444
19 changed files with 22 additions and 980 deletions

View File

@ -108,7 +108,6 @@ libsysprof_analyze_static = static_library(
libsysprof_analyze_private_sources,
include_directories: [include_directories('.'),
ipc_include_dirs,
libsysprof_capture_include_dirs],
dependencies: libsysprof_analyze_deps,
gnu_symbol_visibility: 'hidden',

View File

@ -77,7 +77,6 @@ libsysprof_profile_static = static_library(
mapped_ring_buffer_sources),
include_directories: [include_directories('.'),
ipc_include_dirs,
libsysprof_capture_include_dirs],
dependencies: libsysprof_profile_deps,
gnu_symbol_visibility: 'hidden',

View File

@ -15,18 +15,11 @@ if install_service_files
'org.gnome.Sysprof2.xml',
'org.gnome.Sysprof3.Profiler.xml',
'org.gnome.Sysprof3.Service.xml',
'org.gnome.Sysprof.Agent.xml'
],
install_dir: join_paths(datadir, 'dbus-1/interfaces'),
)
endif
ipc_include_dirs = include_directories('.')
stackstash_sources = files('stackstash.c')
helpers_sources = files('helpers.c')
if need_libsysprof_capture
subdir('libsysprof-capture')
endif
@ -43,9 +36,12 @@ endif
if get_option('sysprofd') == 'bundled'
subdir('sysprofd')
endif
if get_option('gtk')
subdir('sysprof')
endif
if get_option('agent')
if get_option('tools')
subdir('sysprof-agent')
subdir('sysprof-cli')
endif

View File

@ -23,3 +23,7 @@ sysprof_agent = executable('sysprof-agent', sysprof_agent_sources,
install_dir: get_option('bindir'),
install: true,
)
install_data(['org.gnome.Sysprof.Agent.xml'],
install_dir: join_paths(datadir, 'dbus-1/interfaces'),
)

View File

View File

@ -1,218 +0,0 @@
/* ipc-legacy-impl.c
*
* Copyright 2019 Christian Hergert <chergert@redhat.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* SPDX-License-Identifier: GPL-3.0-or-later
*/
#define G_LOG_DOMAIN "ipc-legacy-impl"
#include "config.h"
#include <errno.h>
#include <fcntl.h>
#include <gio/gunixfdlist.h>
#include <polkit/polkit.h>
#include <string.h>
#include <sys/syscall.h>
#include <time.h>
#include <unistd.h>
#include "../libsysprof/sysprof-kallsyms.h"
#include "helpers.h"
#include "ipc-legacy-impl.h"
struct _IpcLegacyImpl
{
IpcLegacySysprof2Skeleton parent;
};
enum {
ACTIVITY,
N_SIGNALS
};
static guint signals [N_SIGNALS];
static gboolean
ipc_legacy_impl_handle_perf_event_open (IpcLegacySysprof2 *service,
GDBusMethodInvocation *invocation,
GUnixFDList *fd_list,
GVariant *options,
gint32 pid,
gint32 cpu,
guint64 flags)
{
gint out_fd = -1;
gint handle;
g_assert (IPC_IS_LEGACY_IMPL (service));
g_assert (G_IS_DBUS_METHOD_INVOCATION (invocation));
g_message ("LEGACY: PerfEventOpen(pid=%d, cpu=%d)", pid, cpu);
errno = 0;
if (!helpers_perf_event_open (options, pid, cpu, -1, flags, &out_fd))
{
g_dbus_method_invocation_return_error (g_steal_pointer (&invocation),
G_DBUS_ERROR,
G_DBUS_ERROR_FAILED,
"Failed to create perf counter: %s",
g_strerror (errno));
}
else
{
g_autoptr(GUnixFDList) out_fd_list = g_unix_fd_list_new ();
g_autoptr(GError) error = NULL;
if (-1 == (handle = g_unix_fd_list_append (out_fd_list, out_fd, &error)))
{
g_dbus_method_invocation_return_error (g_steal_pointer (&invocation),
G_DBUS_ERROR,
G_DBUS_ERROR_LIMITS_EXCEEDED,
"Failed to create file-descriptor for reply");
}
else
{
ipc_legacy_sysprof2_complete_perf_event_open (service,
g_steal_pointer (&invocation),
out_fd_list,
g_variant_new ("h", handle));
}
}
if (out_fd != -1)
close (out_fd);
return TRUE;
}
static gboolean
ipc_legacy_impl_handle_get_kernal_symbols (IpcLegacySysprof2 *service,
GDBusMethodInvocation *invocation)
{
g_autoptr(SysprofKallsyms) kallsyms = NULL;
GVariantBuilder builder;
const gchar *name;
guint64 addr;
guint8 type;
g_assert (IPC_IS_LEGACY_IMPL (service));
g_assert (G_IS_DBUS_METHOD_INVOCATION (invocation));
g_message ("LEGACY: GetKernelSymbols()");
if (!(kallsyms = sysprof_kallsyms_new ("/proc/kallsyms")))
{
g_dbus_method_invocation_return_error (g_steal_pointer (&invocation),
G_DBUS_ERROR,
G_DBUS_ERROR_FAILED,
"Failed to create parse kallsyms");
return TRUE;
}
g_variant_builder_init (&builder, G_VARIANT_TYPE ("a(tys)"));
while (sysprof_kallsyms_next (kallsyms, &name, &addr, &type))
g_variant_builder_add (&builder, "(tys)", addr, type, name);
ipc_legacy_sysprof2_complete_get_kernel_symbols (service,
g_steal_pointer (&invocation),
g_variant_builder_end (&builder));
return TRUE;
}
static gboolean
ipc_legacy_impl_g_authorize_method (GDBusInterfaceSkeleton *skeleton,
GDBusMethodInvocation *invocation)
{
PolkitAuthorizationResult *res = NULL;
PolkitAuthority *authority = NULL;
PolkitSubject *subject = NULL;
const gchar *peer_name;
gboolean ret = TRUE;
g_assert (IPC_IS_LEGACY_IMPL (skeleton));
g_assert (G_IS_DBUS_METHOD_INVOCATION (invocation));
g_signal_emit (skeleton, signals [ACTIVITY], 0);
peer_name = g_dbus_method_invocation_get_sender (invocation);
if (!(authority = polkit_authority_get_sync (NULL, NULL)) ||
!(subject = polkit_system_bus_name_new (peer_name)) ||
!(res = polkit_authority_check_authorization_sync (authority,
POLKIT_SUBJECT (subject),
"org.gnome.sysprof3.profile",
NULL,
POLKIT_CHECK_AUTHORIZATION_FLAGS_ALLOW_USER_INTERACTION,
NULL,
NULL)) ||
!polkit_authorization_result_get_is_authorized (res))
{
g_dbus_method_invocation_return_error (g_steal_pointer (&invocation),
G_DBUS_ERROR,
G_DBUS_ERROR_ACCESS_DENIED,
"Not authorized to make request");
ret = FALSE;
}
g_clear_object (&authority);
g_clear_object (&subject);
g_clear_object (&res);
return ret;
}
static void
sysprof2_iface_init (IpcLegacySysprof2Iface *iface)
{
iface->handle_perf_event_open = ipc_legacy_impl_handle_perf_event_open;
iface->handle_get_kernel_symbols = ipc_legacy_impl_handle_get_kernal_symbols;
}
G_DEFINE_TYPE_WITH_CODE (IpcLegacyImpl, ipc_legacy_impl, IPC_LEGACY_TYPE_SYSPROF2_SKELETON,
G_IMPLEMENT_INTERFACE (IPC_LEGACY_TYPE_SYSPROF2, sysprof2_iface_init))
static void
ipc_legacy_impl_class_init (IpcLegacyImplClass *klass)
{
GDBusInterfaceSkeletonClass *skeleton_class = G_DBUS_INTERFACE_SKELETON_CLASS (klass);
skeleton_class->g_authorize_method = ipc_legacy_impl_g_authorize_method;
signals [ACTIVITY] =
g_signal_new ("activity",
G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_LAST,
0,
NULL, NULL,
NULL,
G_TYPE_NONE, 0);
}
static void
ipc_legacy_impl_init (IpcLegacyImpl *self)
{
g_dbus_interface_skeleton_set_flags (G_DBUS_INTERFACE_SKELETON (self),
G_DBUS_INTERFACE_SKELETON_FLAGS_HANDLE_METHOD_INVOCATIONS_IN_THREAD);
}
IpcLegacySysprof2 *
ipc_legacy_impl_new (void)
{
return g_object_new (IPC_TYPE_LEGACY_IMPL, NULL);
}

View File

@ -1,33 +0,0 @@
/* ipc-legacy-impl.h
*
* Copyright 2019 Christian Hergert <chergert@redhat.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* SPDX-License-Identifier: GPL-3.0-or-later
*/
#pragma once
#include "ipc-legacy.h"
G_BEGIN_DECLS
#define IPC_TYPE_LEGACY_IMPL (ipc_legacy_impl_get_type())
G_DECLARE_FINAL_TYPE (IpcLegacyImpl, ipc_legacy_impl, IPC, LEGACY_IMPL, IpcLegacySysprof2Skeleton)
IpcLegacySysprof2 *ipc_legacy_impl_new (void);
G_END_DECLS

View File

@ -1,12 +1,21 @@
ipc_profiler_src = gnome.gdbus_codegen('ipc-profiler',
sources: '../org.gnome.Sysprof3.Profiler.xml',
interface_prefix: 'org.gnome.Sysprof3.',
namespace: 'Ipc',
)
ipc_service_src = gnome.gdbus_codegen('ipc-service',
sources: '../org.gnome.Sysprof3.Service.xml',
interface_prefix: 'org.gnome.Sysprof3.',
namespace: 'Ipc',
)
sysprofd_sources = [
'../libsysprof/sysprof-kallsyms.c',
'sysprofd.c',
'ipc-legacy-impl.c',
'ipc-rapl-profiler.c',
'ipc-service-impl.c',
'sysprof-turbostat.c',
helpers_sources,
ipc_legacy_src,
'helpers.c',
ipc_profiler_src,
ipc_service_src,
]
@ -26,7 +35,7 @@ sysprofd = executable('sysprofd', sysprofd_sources,
install: true,
install_dir: pkglibexecdir,
pie: true,
include_directories: [include_directories('.'), ipc_include_dirs],
include_directories: [include_directories('.')],
)
sysprofdconf = configuration_data()
@ -69,28 +78,3 @@ i18n.merge_file(
install: true,
install_dir: join_paths(datadir, 'polkit-1/actions'),
)
#
# For org.gnome.Sysprof2 Compatibility
#
configure_file(
input: 'org.gnome.Sysprof2.service.in',
output: 'org.gnome.Sysprof2.service',
configuration: sysprofdconf,
install_dir: join_paths(datadir, 'dbus-1/system-services'),
)
configure_file(
input: 'org.gnome.Sysprof2.conf.in',
output: 'org.gnome.Sysprof2.conf',
configuration: sysprofdconf,
install_dir: join_paths(datadir, 'dbus-1/system.d'),
)
configure_file(
input: 'sysprof2.service.in',
output: 'sysprof2.service',
configuration: sysprofdconf,
install_dir: systemdunitdir,
)

View File

@ -1,19 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE busconfig PUBLIC
"-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN"
"http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
<busconfig>
<!-- Only root can own the service -->
<policy user="root">
<allow own="org.gnome.Sysprof2"/>
<allow send_destination="org.gnome.Sysprof2"/>
<allow receive_sender="org.gnome.Sysprof2"/>
</policy>
<!-- Anyone can send messages to the owner of org.gnome.Sysprof2 -->
<policy context="default">
<allow send_destination="org.gnome.Sysprof2"/>
<allow receive_sender="org.gnome.Sysprof2"/>
</policy>
</busconfig>

View File

@ -1,5 +0,0 @@
[D-BUS Service]
Name=org.gnome.Sysprof2
Exec=@sysprofdprivdir@/sysprofd
User=root
SystemdService=sysprof2.service

View File

@ -1,8 +0,0 @@
[Unit]
Description=Sysprof Daemon
[Service]
Type=dbus
BusName=org.gnome.Sysprof2
ExecStart=@sysprofdprivdir@/sysprofd

View File

@ -26,10 +26,8 @@
#include <stdlib.h>
#include <sysprof-capture.h>
#include "ipc-legacy.h"
#include "ipc-service.h"
#include "ipc-legacy-impl.h"
#include "ipc-rapl-profiler.h"
#include "ipc-service-impl.h"
@ -127,18 +125,15 @@ main (gint argc,
if ((bus = g_bus_get_sync (bus_type, NULL, &error)))
{
g_autoptr(IpcLegacySysprof2) v2_service = ipc_legacy_impl_new ();
g_autoptr(IpcProfiler) rapl = ipc_rapl_profiler_new ();
g_autoptr(IpcService) v3_service = ipc_service_impl_new ();
g_signal_connect (v3_service, "activity", G_CALLBACK (activity_cb), NULL);
g_signal_connect (v2_service, "activity", G_CALLBACK (activity_cb), NULL);
g_signal_connect (rapl, "activity", G_CALLBACK (activity_cb), NULL);
activity_cb (NULL, NULL);
if (g_dbus_interface_skeleton_export (G_DBUS_INTERFACE_SKELETON (v3_service), bus, V3_PATH, &error) &&
g_dbus_interface_skeleton_export (G_DBUS_INTERFACE_SKELETON (v2_service), bus, V2_PATH, &error) &&
g_dbus_interface_skeleton_export (G_DBUS_INTERFACE_SKELETON (rapl), bus, RAPL_PATH, &error))
{
for (guint i = 0; i < G_N_ELEMENTS (bus_names); i++)

View File

@ -1,6 +0,0 @@
#sysprof_cli = executable('sysprof-cli', 'sysprof-cli.c',
# dependencies: [libsysprof_static_dep, polkit_dep, polkit_agent_dep],
# c_args: tools_cflags,
# install_dir: get_option('bindir'),
# install: true,
#)

View File

@ -1,445 +0,0 @@
/* sysprof-dump.c
*
* Copyright 2016-2019 Christian Hergert <chergert@redhat.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* SPDX-License-Identifier: GPL-3.0-or-later
*/
#include "config.h"
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <glib-object.h>
#include <sysprof-capture.h>
#include <sysprof.h>
static gboolean list_files = FALSE;
static gboolean resolve = FALSE;
static const GOptionEntry main_entries[] = {
{ "list-files", 'l', 0, G_OPTION_ARG_NONE, &list_files, "List files within the capture" },
{ "resolve", 'r', 0, G_OPTION_ARG_NONE, &resolve, "Resolve symbols" },
{ 0 }
};
static char *
symbolize (GPtrArray *resolvers,
const SysprofCaptureFrame *frame,
SysprofAddressContext *context,
SysprofAddress address)
{
SysprofAddressContext last_context = *context;
if (sysprof_address_is_context_switch (address, context))
return g_strdup (sysprof_address_context_to_string (last_context));
if (last_context == SYSPROF_ADDRESS_CONTEXT_NONE)
last_context = SYSPROF_ADDRESS_CONTEXT_USER;
for (guint j = 0; j < resolvers->len; j++)
{
SysprofSymbolResolver *resolver = g_ptr_array_index (resolvers, j);
GQuark tag = 0;
char *str;
str = sysprof_symbol_resolver_resolve_with_context (resolver, frame->time, frame->pid, last_context, address, &tag);
if (str != NULL)
return str;
}
return g_strdup ("??");
}
gint
main (gint argc,
gchar *argv[])
{
g_autoptr(GOptionContext) option_context = g_option_context_new ("- dump capture data");
g_autoptr(GPtrArray) resolvers = NULL;
g_autoptr(GError) error = NULL;
SysprofCaptureReader *reader;
SysprofCaptureFrameType type;
GHashTable *ctrtypes;
gint64 begin_time;
gint64 end_time;
g_option_context_add_main_entries (option_context, main_entries, NULL);
if (!g_option_context_parse (option_context, &argc, &argv, &error))
{
g_printerr ("%s\n", error->message);
return EXIT_FAILURE;
}
if (argc != 2)
{
g_printerr ("usage: %s FILENAME\n", argv[0]);
return EXIT_FAILURE;
}
if ((reader = sysprof_capture_reader_new (argv[1])) == NULL)
{
int errsv = errno;
g_printerr ("%s\n", g_strerror (errsv));
return EXIT_FAILURE;
}
if (list_files)
{
g_autofree const gchar **files = sysprof_capture_reader_list_files (reader);
for (gsize i = 0; files[i]; i++)
g_print ("%s\n", files[i]);
return EXIT_SUCCESS;
}
resolvers = g_ptr_array_new_with_free_func (g_object_unref);
if (resolve)
{
g_ptr_array_add (resolvers, sysprof_capture_symbol_resolver_new ());
g_ptr_array_add (resolvers, sysprof_kernel_symbol_resolver_new ());
g_ptr_array_add (resolvers, sysprof_elf_symbol_resolver_new ());
for (guint i = 0; i < resolvers->len; i++)
{
sysprof_symbol_resolver_load (g_ptr_array_index (resolvers, i), reader);
sysprof_capture_reader_reset (reader);
}
}
ctrtypes = g_hash_table_new (NULL, NULL);
begin_time = sysprof_capture_reader_get_start_time (reader);
#define SET_CTR_TYPE(i,t) g_hash_table_insert(ctrtypes, GINT_TO_POINTER(i), GINT_TO_POINTER(t))
#define GET_CTR_TYPE(i) GPOINTER_TO_INT(g_hash_table_lookup(ctrtypes, GINT_TO_POINTER(i)))
begin_time = sysprof_capture_reader_get_start_time (reader);
end_time = sysprof_capture_reader_get_end_time (reader);
g_print ("Capture Time Range: %" G_GUINT64_FORMAT " to %" G_GUINT64_FORMAT " (%lf)\n",
begin_time, end_time, (end_time - begin_time) / (gdouble)SYSPROF_NSEC_PER_SEC);
while (sysprof_capture_reader_peek_type (reader, &type))
{
switch (type)
{
case SYSPROF_CAPTURE_FRAME_EXIT:
{
const SysprofCaptureExit *ex = sysprof_capture_reader_read_exit (reader);
if (ex == NULL)
return EXIT_FAILURE;
g_print ("EXIT: pid=%d\n", ex->frame.pid);
break;
}
case SYSPROF_CAPTURE_FRAME_FORK:
{
const SysprofCaptureFork *fk = sysprof_capture_reader_read_fork (reader);
if (fk == NULL)
return EXIT_FAILURE;
g_print ("FORK: pid=%d child_pid=%d\n", fk->frame.pid, fk->child_pid);
break;
}
case SYSPROF_CAPTURE_FRAME_OVERLAY:
{
const SysprofCaptureOverlay *pr = sysprof_capture_reader_read_overlay (reader);
const char *src = pr->data;
const char *dst = &pr->data[pr->src_len+1];
if (pr == NULL)
return EXIT_FAILURE;
g_print ("OVERLAY: pid=%d layer=%u src=%s dst=%s\n", pr->frame.pid, pr->layer, src, dst);
break;
}
case SYSPROF_CAPTURE_FRAME_JITMAP:
{
const SysprofCaptureJitmap *jitmap = sysprof_capture_reader_read_jitmap (reader);
SysprofCaptureJitmapIter iter;
SysprofCaptureAddress addr;
const gchar *str;
if (jitmap == NULL)
return EXIT_FAILURE;
g_print ("JITMAP:\n");
sysprof_capture_jitmap_iter_init (&iter, jitmap);
while (sysprof_capture_jitmap_iter_next (&iter, &addr, &str))
g_print (" " SYSPROF_CAPTURE_ADDRESS_FORMAT " : %s\n", addr, str);
break;
}
case SYSPROF_CAPTURE_FRAME_LOG:
{
const SysprofCaptureLog *log = sysprof_capture_reader_read_log (reader);
gdouble ptime = (log->frame.time - begin_time) / (gdouble)SYSPROF_NSEC_PER_SEC;
g_print ("LOG: pid=%d time=%" G_GINT64_FORMAT " (%lf)\n"
" severity = %d\n"
" domain = %s\n"
" message = %s\n",
log->frame.pid, log->frame.time, ptime,
log->severity, log->domain, log->message);
break;
}
case SYSPROF_CAPTURE_FRAME_MAP:
{
const SysprofCaptureMap *map = sysprof_capture_reader_read_map (reader);
g_print ("MAP: pid=%d time=%" G_GINT64_FORMAT "\n"
" start = %" G_GUINT64_FORMAT "\n"
" end = %" G_GUINT64_FORMAT "\n"
" offset = %" G_GUINT64_FORMAT "\n"
" inode = %" G_GUINT64_FORMAT "\n"
" filename = %s\n",
map->frame.pid, map->frame.time,
map->start, map->end, map->offset, map->inode, map->filename);
break;
}
case SYSPROF_CAPTURE_FRAME_FILE_CHUNK:
{
const SysprofCaptureFileChunk *file_chunk = sysprof_capture_reader_read_file (reader);
gdouble ptime = (file_chunk->frame.time - begin_time) / (gdouble)SYSPROF_NSEC_PER_SEC;
g_print ("FILE_CHUNK: pid=%d time=%" G_GINT64_FORMAT " (%lf)\n"
" path = %s\n"
" is_last = %d\n"
" bytes = %d\n",
file_chunk->frame.pid, file_chunk->frame.time, ptime,
file_chunk->path, file_chunk->is_last, file_chunk->len);
break;
}
case SYSPROF_CAPTURE_FRAME_MARK:
{
const SysprofCaptureMark *mark = sysprof_capture_reader_read_mark (reader);
gdouble ptime = (mark->frame.time - begin_time) / (gdouble)SYSPROF_NSEC_PER_SEC;
g_print ("MARK: pid=%d time=%" G_GINT64_FORMAT " (%lf)\n"
" group = %s\n"
" name = %s\n"
" duration = %" G_GUINT64_FORMAT "\n"
" message = %s\n",
mark->frame.pid, mark->frame.time, ptime,
mark->group, mark->name, mark->duration, mark->message);
break;
}
case SYSPROF_CAPTURE_FRAME_METADATA:
{
const SysprofCaptureMetadata *metadata = sysprof_capture_reader_read_metadata (reader);
gdouble ptime = (metadata->frame.time - begin_time) / (gdouble)SYSPROF_NSEC_PER_SEC;
g_print ("METADATA: pid=%d time=%" G_GINT64_FORMAT " (%lf)\n"
" id = %s\n"
"\"\"\"\n%s\n\"\"\"\n",
metadata->frame.pid, metadata->frame.time, ptime,
metadata->id, metadata->metadata);
break;
}
case SYSPROF_CAPTURE_FRAME_PROCESS:
{
const SysprofCaptureProcess *pr = sysprof_capture_reader_read_process (reader);
if (pr == NULL)
perror ("Failed to read process");
g_print ("PROCESS: pid=%d cmdline=%s time=%" G_GINT64_FORMAT "\n", pr->frame.pid, pr->cmdline, pr->frame.time);
break;
}
case SYSPROF_CAPTURE_FRAME_SAMPLE:
{
const SysprofCaptureSample *s = sysprof_capture_reader_read_sample (reader);
gdouble ptime = (s->frame.time - begin_time) / (gdouble)SYSPROF_NSEC_PER_SEC;
SysprofAddressContext context = SYSPROF_ADDRESS_CONTEXT_NONE;
g_print ("SAMPLE: pid=%d tid=%d time=%" G_GINT64_FORMAT " (%lf)\n",
s->frame.pid, s->tid, s->frame.time, ptime);
for (guint i = 0; i < s->n_addrs; i++)
{
if (resolve)
{
g_autofree char *name = symbolize (resolvers, &s->frame, &context, s->addrs[i]);
g_print (" " SYSPROF_CAPTURE_ADDRESS_FORMAT " (%s)\n", s->addrs[i], name);
}
else
{
g_print (" " SYSPROF_CAPTURE_ADDRESS_FORMAT "\n", s->addrs[i]);
}
}
break;
}
case SYSPROF_CAPTURE_FRAME_TRACE:
{
const SysprofCaptureTrace *s = sysprof_capture_reader_read_trace (reader);
gdouble ptime = (s->frame.time - begin_time) / (gdouble)SYSPROF_NSEC_PER_SEC;
SysprofAddressContext context = SYSPROF_ADDRESS_CONTEXT_NONE;
g_print ("TRACE: pid=%d tid=%d time=%" G_GINT64_FORMAT " (%lf) %s\n",
s->frame.pid, s->tid, s->frame.time, ptime,
s->entering ? "ENTER" : "EXIT");
for (guint i = 0; i < s->n_addrs; i++)
{
if (resolve)
{
g_autofree char *name = symbolize (resolvers, &s->frame, &context, s->addrs[i]);
g_print (" " SYSPROF_CAPTURE_ADDRESS_FORMAT " (%s)\n", s->addrs[i], name);
}
else
{
g_print (" " SYSPROF_CAPTURE_ADDRESS_FORMAT "\n", s->addrs[i]);
}
}
break;
}
case SYSPROF_CAPTURE_FRAME_TIMESTAMP:
{
const SysprofCaptureTimestamp *ts = sysprof_capture_reader_read_timestamp (reader);
g_print ("TIMESTAMP: pid=%d time=%" G_GINT64_FORMAT "\n", ts->frame.pid, ts->frame.time);
break;
}
case SYSPROF_CAPTURE_FRAME_CTRDEF:
{
const SysprofCaptureCounterDefine *def = sysprof_capture_reader_read_counter_define (reader);
gdouble ptime = (def->frame.time - begin_time) / (gdouble)SYSPROF_NSEC_PER_SEC;
guint i;
g_print ("NEW COUNTERS: pid=%d time=%" G_GINT64_FORMAT " (%lf)\n", def->frame.pid, def->frame.time, ptime);
for (i = 0; i < def->n_counters; i++)
{
const SysprofCaptureCounter *ctr = &def->counters[i];
SET_CTR_TYPE (ctr->id, ctr->type);
g_print (" COUNTER(%03d<%s>): %s\n"
" %s\n"
" %s\n"
"\n",
ctr->id,
ctr->type == SYSPROF_CAPTURE_COUNTER_INT64 ? "i64" : "f64",
ctr->category,
ctr->name,
ctr->description);
}
}
break;
case SYSPROF_CAPTURE_FRAME_CTRSET:
{
const SysprofCaptureCounterSet *set = sysprof_capture_reader_read_counter_set (reader);
gdouble ptime = (set->frame.time - begin_time) / (gdouble)SYSPROF_NSEC_PER_SEC;
guint i;
g_print ("SET COUNTERS: pid=%d time=%" G_GINT64_FORMAT " (%lf)\n", set->frame.pid, set->frame.time, ptime);
for (i = 0; i < set->n_values; i++)
{
const SysprofCaptureCounterValues *values = &set->values[i];
guint j;
for (j = 0; j < G_N_ELEMENTS (values->ids); j++)
{
if (values->ids[j])
{
if (GET_CTR_TYPE (values->ids[j]) == SYSPROF_CAPTURE_COUNTER_INT64)
g_print (" COUNTER(%d): %" G_GINT64_FORMAT "\n",
values->ids[j],
values->values[j].v64);
else if (GET_CTR_TYPE (values->ids[j]) == SYSPROF_CAPTURE_COUNTER_DOUBLE)
g_print (" COUNTER(%d): %lf\n",
values->ids[j],
values->values[j].vdbl);
}
}
}
}
break;
case SYSPROF_CAPTURE_FRAME_ALLOCATION:
{
const SysprofCaptureAllocation *ev = sysprof_capture_reader_read_allocation (reader);
gdouble ptime = (ev->frame.time - begin_time) / (gdouble)SYSPROF_NSEC_PER_SEC;
SysprofAddressContext context = SYSPROF_ADDRESS_CONTEXT_NONE;
g_print ("%s: pid=%d tid=%d addr=0x%" G_GINT64_MODIFIER "x size=%" G_GINT64_FORMAT " time=%" G_GINT64_FORMAT " (%lf)\n",
ev->alloc_size > 0 ? "ALLOC" : "FREE",
ev->frame.pid, ev->tid,
ev->alloc_addr, ev->alloc_size,
ev->frame.time, ptime);
for (guint i = 0; i < ev->n_addrs; i++)
{
if (resolve)
{
g_autofree char *name = symbolize (resolvers, &ev->frame, &context, ev->addrs[i]);
g_print (" " SYSPROF_CAPTURE_ADDRESS_FORMAT " (%s)\n", ev->addrs[i], name);
}
else
{
g_print (" " SYSPROF_CAPTURE_ADDRESS_FORMAT "\n", ev->addrs[i]);
}
}
}
break;
default:
g_print ("Skipping unknown frame type: (%d): ", type);
if (!sysprof_capture_reader_skip (reader))
{
g_print ("Failed\n");
return EXIT_FAILURE;
}
g_print ("Success\n");
break;
}
}
return EXIT_SUCCESS;
}

View File

@ -1,197 +0,0 @@
/* sysprof-profiler-ctl.c
*
* Copyright 2019 Christian Hergert <chergert@redhat.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* SPDX-License-Identifier: GPL-3.0-or-later
*/
#define G_LOG_DOMAIN "sysprof-profiler-ctl"
#include "config.h"
#include <fcntl.h>
#include <glib-unix.h>
#include <glib/gi18n.h>
#include <glib/gstdio.h>
#include <gio/gunixfdlist.h>
#include <stdlib.h>
#include <gio/gio.h>
#include <unistd.h>
#include "ipc-profiler.h"
static gboolean opt_force;
static gboolean opt_system;
static gboolean opt_session;
static gchar *opt_address;
static gchar *opt_dest;
static gchar *opt_object_path;
static gint opt_timeout = -1;
static const GOptionEntry main_entries[] = {
{ "system", 'y', 0, G_OPTION_ARG_NONE, &opt_system, N_("Connect to the system bus") },
{ "session", 'e', 0, G_OPTION_ARG_NONE, &opt_session, N_("Connect to the session bus") },
{ "address", 'a', 0, G_OPTION_ARG_STRING, &opt_address, N_("Connect to the given D-Bus address") },
{ "dest", 'd', 0, G_OPTION_ARG_STRING, &opt_dest, N_("Destination D-Bus name to invoke method on") },
{ "object-path", 'o', 0, G_OPTION_ARG_STRING, &opt_object_path, N_("Object path to invoke method on"), N_("/org/gnome/Sysprof3/Profiler") },
{ "timeout", 't', 0, G_OPTION_ARG_INT, &opt_timeout, N_("Timeout in seconds") },
{ "force", 'f', 0, G_OPTION_ARG_NONE, &opt_force, N_("Overwrite FILENAME if it exists") },
{ 0 }
};
static gboolean
handle_sigint (gpointer data)
{
GMainLoop *main_loop = data;
g_printerr ("\nSIGINT received, stopping profiler.\n");
g_main_loop_quit (main_loop);
return G_SOURCE_REMOVE;
}
gint
main (gint argc,
gchar *argv[])
{
g_autoptr(GOptionContext) context = NULL;
g_autoptr(GDBusConnection) bus = NULL;
g_autoptr(GUnixFDList) fd_list = NULL;
g_autoptr(GVariant) reply = NULL;
g_autoptr(GError) error = NULL;
g_autoptr(GMainLoop) main_loop = NULL;
g_autofree gchar *filename = NULL;
guint flags = O_RDWR;
gint fd;
gint handle;
context = g_option_context_new (_("--dest=BUS_NAME [FILENAME] - connect to an embedded sysprof profiler"));
g_option_context_add_main_entries (context, main_entries, GETTEXT_PACKAGE);
if (!g_option_context_parse (context, &argc, &argv, &error))
{
g_printerr ("%s\n", error->message);
return EXIT_FAILURE;
}
if (opt_dest == NULL)
{
g_printerr ("--dest= must contain a peer bus name on the D-Bus.\n");
return EXIT_FAILURE;
}
if ((opt_system && opt_session) ||
(opt_address && (opt_system || opt_session)))
{
g_printerr ("Only one of --system --session or --address may be specified.");
return EXIT_FAILURE;
}
if (!opt_address && !opt_session && !opt_system)
opt_session = TRUE;
main_loop = g_main_loop_new (NULL, FALSE);
g_unix_signal_add (SIGINT, handle_sigint, main_loop);
if (opt_session)
bus = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, &error);
else if (opt_system)
bus = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, &error);
else
bus = g_dbus_connection_new_for_address_sync (opt_address,
G_DBUS_CONNECTION_FLAGS_MESSAGE_BUS_CONNECTION,
NULL,
NULL,
&error);
if (bus == NULL)
{
g_printerr ("Failed to connect to D-Bus: %s\n", error->message);
return EXIT_FAILURE;
}
filename = (argc == 1) ? g_strdup_printf ("sysprof.%d.syscap", getpid ())
: g_strdup (argv[1]);
if (!opt_force)
flags |= O_CREAT;
if (-1 == (fd = g_open (filename, flags, 0644)))
{
g_printerr ("Failed to open file \"%s\". Try --force.\n", filename);
return EXIT_FAILURE;
}
fd_list = g_unix_fd_list_new ();
handle = g_unix_fd_list_append (fd_list, fd, &error);
close (fd);
fd = -1;
if (handle == -1)
{
g_printerr ("Failed to build FD list for peer.\n");
g_unlink (filename);
return EXIT_FAILURE;
}
reply = g_dbus_connection_call_with_unix_fd_list_sync (bus,
opt_dest,
opt_object_path,
"org.gnome.Sysprof3.Profiler",
"Start",
g_variant_new ("(a{sv}h)", NULL, handle),
G_VARIANT_TYPE ("()"),
G_DBUS_CALL_FLAGS_ALLOW_INTERACTIVE_AUTHORIZATION,
opt_timeout,
fd_list,
NULL,
NULL,
&error);
if (error != NULL)
{
g_printerr ("Failed to start profiler: %s\n", error->message);
g_unlink (filename);
return EXIT_FAILURE;
}
g_printerr ("Profiler capturing to file \"%s\"\n", filename);
g_clear_pointer (&reply, g_variant_unref);
g_main_loop_run (main_loop);
reply = g_dbus_connection_call_sync (bus,
opt_dest,
opt_object_path,
"org.gnome.Sysprof3.Profiler",
"Stop",
g_variant_new ("()"),
NULL,
G_DBUS_CALL_FLAGS_NONE,
opt_timeout,
NULL,
&error);
if (error != NULL)
{
g_printerr ("Failed to stop profiler: %s\n", error->message);
return EXIT_FAILURE;
}
g_printerr ("Profiler stopped.\n");
return EXIT_SUCCESS;
}