mirror of
https://github.com/varun-r-mallya/sysprof.git
synced 2025-12-31 20:36:25 +00:00
libsysprof-analyze: make SysprofDocumentSymbols private
This instead moves to a public API on the document to symbolize now that we've gotten much of the necessary bits private in loading the document. This commit ensures that we only do loading via the loader now (and removes the incorrect use from the tests so they too go through the loader). We check for NoSymbolizer in document symbols so that we can skip any decoding. That keeps various use cases fast where you don't want to waste time on symbolizing if you don't need to look at symbols. There is plenty more we can do to batch decode symbols with some more API changes, but that will come after we have kernel/userland decoding integrated from this library. We may still want to get all symbols into a single symbol cache, but given that we have address ranges associated with them, that may not be very useful beyond the hashtable to pid-specific cache we have now. If symbols were shared between processes, that'd make more sense, but we aren't doing that (albeit strings are shared between symbol instances to reduce that overhead).
This commit is contained in:
@ -14,7 +14,6 @@ libsysprof_analyze_public_sources = [
|
||||
'sysprof-document-mmap.c',
|
||||
'sysprof-document-process.c',
|
||||
'sysprof-document-sample.c',
|
||||
'sysprof-document-symbols.c',
|
||||
'sysprof-document-traceable.c',
|
||||
'sysprof-kallsyms-symbolizer.c',
|
||||
'sysprof-multi-symbolizer.c',
|
||||
@ -26,6 +25,7 @@ libsysprof_analyze_public_sources = [
|
||||
libsysprof_analyze_private_sources = [
|
||||
'sysprof-address-layout.c',
|
||||
'sysprof-document-bitset-index.c',
|
||||
'sysprof-document-symbols.c',
|
||||
'sysprof-mount.c',
|
||||
'sysprof-mount-device.c',
|
||||
'sysprof-mount-namespace.c',
|
||||
@ -51,7 +51,6 @@ libsysprof_analyze_public_headers = [
|
||||
'sysprof-document-mmap.h',
|
||||
'sysprof-document-process.h',
|
||||
'sysprof-document-sample.h',
|
||||
'sysprof-document-symbols.h',
|
||||
'sysprof-document-traceable.h',
|
||||
'sysprof-mount.h',
|
||||
'sysprof-kallsyms-symbolizer.h',
|
||||
|
||||
@ -40,7 +40,6 @@ G_BEGIN_DECLS
|
||||
# include "sysprof-document-mmap.h"
|
||||
# include "sysprof-document-process.h"
|
||||
# include "sysprof-document-sample.h"
|
||||
# include "sysprof-document-symbols.h"
|
||||
# include "sysprof-document-traceable.h"
|
||||
# include "sysprof-mount.h"
|
||||
# include "sysprof-kallsyms-symbolizer.h"
|
||||
|
||||
@ -20,8 +20,13 @@
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "sysprof-bundled-symbolizer.h"
|
||||
#include "sysprof-document-loader.h"
|
||||
#include "sysprof-document-private.h"
|
||||
#include "sysprof-multi-symbolizer.h"
|
||||
|
||||
struct _SysprofDocumentLoader
|
||||
{
|
||||
@ -45,6 +50,105 @@ G_DEFINE_FINAL_TYPE (SysprofDocumentLoader, sysprof_document_loader, G_TYPE_OBJE
|
||||
|
||||
static GParamSpec *properties [N_PROPS];
|
||||
|
||||
static void
|
||||
mapped_file_by_filename (GTask *task,
|
||||
gpointer source_object,
|
||||
gpointer task_data,
|
||||
GCancellable *cancellable)
|
||||
{
|
||||
g_autoptr(GError) error = NULL;
|
||||
g_autoptr(GMappedFile) mapped_file = g_mapped_file_new (task_data, FALSE, &error);
|
||||
|
||||
if (mapped_file != NULL)
|
||||
g_task_return_pointer (task,
|
||||
g_steal_pointer (&mapped_file),
|
||||
(GDestroyNotify)g_mapped_file_unref);
|
||||
else
|
||||
g_task_return_error (task, g_steal_pointer (&error));
|
||||
}
|
||||
|
||||
static void
|
||||
mapped_file_new_async (const char *filename,
|
||||
GCancellable *cancellable,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data)
|
||||
{
|
||||
g_autoptr(GTask) task = g_task_new (NULL, cancellable, callback, user_data);
|
||||
g_task_set_task_data (task, g_strdup (filename), g_free);
|
||||
g_task_run_in_thread (task, mapped_file_by_filename);
|
||||
}
|
||||
|
||||
static void
|
||||
mapped_file_by_fd (GTask *task,
|
||||
gpointer source_object,
|
||||
gpointer task_data,
|
||||
GCancellable *cancellable)
|
||||
{
|
||||
g_autoptr(GError) error = NULL;
|
||||
g_autoptr(GMappedFile) mapped_file = g_mapped_file_new_from_fd (GPOINTER_TO_INT (task_data), FALSE, &error);
|
||||
|
||||
if (mapped_file != NULL)
|
||||
g_task_return_pointer (task,
|
||||
g_steal_pointer (&mapped_file),
|
||||
(GDestroyNotify)g_mapped_file_unref);
|
||||
else
|
||||
g_task_return_error (task, g_steal_pointer (&error));
|
||||
}
|
||||
|
||||
static void
|
||||
close_fd (gpointer data)
|
||||
{
|
||||
int fd = GPOINTER_TO_INT (data);
|
||||
close (fd);
|
||||
}
|
||||
|
||||
static void
|
||||
mapped_file_new_from_fd_async (int fd,
|
||||
GCancellable *cancellable,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data)
|
||||
{
|
||||
g_autoptr(GTask) task = NULL;
|
||||
int copy_fd;
|
||||
|
||||
task = g_task_new (NULL, cancellable, callback, user_data);
|
||||
|
||||
if (-1 == (copy_fd = dup (fd)))
|
||||
{
|
||||
int errsv = errno;
|
||||
g_task_return_new_error (task,
|
||||
G_IO_ERROR,
|
||||
g_io_error_from_errno (errsv),
|
||||
"%s",
|
||||
g_strerror (errsv));
|
||||
return;
|
||||
}
|
||||
|
||||
g_task_set_task_data (task, GINT_TO_POINTER (copy_fd), close_fd);
|
||||
g_task_run_in_thread (task, mapped_file_by_fd);
|
||||
}
|
||||
|
||||
static GMappedFile *
|
||||
mapped_file_new_finish (GAsyncResult *result,
|
||||
GError **error)
|
||||
{
|
||||
return g_task_propagate_pointer (G_TASK (result), error);
|
||||
}
|
||||
|
||||
static void
|
||||
set_default_symbolizer (SysprofDocumentLoader *self)
|
||||
{
|
||||
g_autoptr(SysprofMultiSymbolizer) multi = NULL;
|
||||
|
||||
g_assert (SYSPROF_IS_DOCUMENT_LOADER (self));
|
||||
|
||||
g_clear_object (&self->symbolizer);
|
||||
|
||||
multi = sysprof_multi_symbolizer_new ();
|
||||
sysprof_multi_symbolizer_take (multi, sysprof_bundled_symbolizer_new ());
|
||||
self->symbolizer = SYSPROF_SYMBOLIZER (g_steal_pointer (&multi));
|
||||
}
|
||||
|
||||
static void
|
||||
sysprof_document_loader_finalize (GObject *object)
|
||||
{
|
||||
@ -140,6 +244,8 @@ static void
|
||||
sysprof_document_loader_init (SysprofDocumentLoader *self)
|
||||
{
|
||||
self->fd = -1;
|
||||
|
||||
set_default_symbolizer (self);
|
||||
}
|
||||
|
||||
SysprofDocumentLoader *
|
||||
@ -210,7 +316,11 @@ sysprof_document_loader_set_symbolizer (SysprofDocumentLoader *self,
|
||||
g_return_if_fail (SYSPROF_IS_DOCUMENT_LOADER (self));
|
||||
|
||||
if (g_set_object (&self->symbolizer, symbolizer))
|
||||
g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_SYMBOLIZER]);
|
||||
{
|
||||
if (self->symbolizer == NULL)
|
||||
set_default_symbolizer (self);
|
||||
g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_SYMBOLIZER]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -249,12 +359,11 @@ sysprof_document_loader_get_message (SysprofDocumentLoader *self)
|
||||
}
|
||||
|
||||
static void
|
||||
sysprof_document_loader_load_cb (GObject *object,
|
||||
GAsyncResult *result,
|
||||
gpointer user_data)
|
||||
sysprof_document_loader_load_symbols_cb (GObject *object,
|
||||
GAsyncResult *result,
|
||||
gpointer user_data)
|
||||
{
|
||||
SysprofDocument *document = (SysprofDocument *)object;
|
||||
g_autoptr(SysprofDocumentSymbols) symbols = NULL;
|
||||
g_autoptr(GError) error = NULL;
|
||||
g_autoptr(GTask) task = user_data;
|
||||
|
||||
@ -262,12 +371,61 @@ sysprof_document_loader_load_cb (GObject *object,
|
||||
g_assert (G_IS_ASYNC_RESULT (result));
|
||||
g_assert (G_IS_TASK (task));
|
||||
|
||||
if (!(symbols = _sysprof_document_symbolize_finish (document, result, &error)))
|
||||
if (!_sysprof_document_symbolize_finish (document, result, &error))
|
||||
g_task_return_error (task, g_steal_pointer (&error));
|
||||
else
|
||||
g_task_return_pointer (task, g_object_ref (document), g_object_unref);
|
||||
}
|
||||
|
||||
static void
|
||||
sysprof_document_loader_load_document_cb (GObject *object,
|
||||
GAsyncResult *result,
|
||||
gpointer user_data)
|
||||
{
|
||||
g_autoptr(SysprofDocument) document = NULL;
|
||||
g_autoptr(GError) error = NULL;
|
||||
g_autoptr(GTask) task = user_data;
|
||||
SysprofSymbolizer *symbolizer;
|
||||
|
||||
g_assert (G_IS_ASYNC_RESULT (result));
|
||||
g_assert (G_IS_TASK (task));
|
||||
|
||||
symbolizer = g_task_get_task_data (task);
|
||||
|
||||
g_assert (symbolizer != NULL);
|
||||
g_assert (SYSPROF_IS_SYMBOLIZER (symbolizer));
|
||||
|
||||
if (!(document = _sysprof_document_new_finish (result, &error)))
|
||||
g_task_return_error (task, g_steal_pointer (&error));
|
||||
else
|
||||
_sysprof_document_symbolize_async (document,
|
||||
symbolizer,
|
||||
g_task_get_cancellable (task),
|
||||
sysprof_document_loader_load_symbols_cb,
|
||||
g_object_ref (task));
|
||||
}
|
||||
|
||||
static void
|
||||
sysprof_document_loader_load_mapped_file_cb (GObject *object,
|
||||
GAsyncResult *result,
|
||||
gpointer user_data)
|
||||
{
|
||||
g_autoptr(GMappedFile) mapped_file = NULL;
|
||||
g_autoptr(GError) error = NULL;
|
||||
g_autoptr(GTask) task = user_data;
|
||||
|
||||
g_assert (G_IS_ASYNC_RESULT (result));
|
||||
g_assert (G_IS_TASK (task));
|
||||
|
||||
if (!(mapped_file = mapped_file_new_finish (result, &error)))
|
||||
g_task_return_error (task, g_steal_pointer (&error));
|
||||
else
|
||||
_sysprof_document_new_async (mapped_file,
|
||||
g_task_get_cancellable (task),
|
||||
sysprof_document_loader_load_document_cb,
|
||||
g_object_ref (task));
|
||||
}
|
||||
|
||||
/**
|
||||
* sysprof_document_loader_load_async:
|
||||
* @self: a #SysprofDocumentLoader
|
||||
@ -285,43 +443,29 @@ sysprof_document_loader_load_async (SysprofDocumentLoader *self,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data)
|
||||
{
|
||||
g_autoptr(SysprofDocument) document = NULL;
|
||||
g_autoptr(SysprofSymbolizer) symbolizer = NULL;
|
||||
g_autoptr(GMappedFile) mapped_file = NULL;
|
||||
g_autoptr(GError) error = NULL;
|
||||
g_autoptr(GTask) task = NULL;
|
||||
|
||||
g_return_if_fail (SYSPROF_IS_DOCUMENT_LOADER (self));
|
||||
g_return_if_fail (!cancellable || G_IS_CANCELLABLE (cancellable));
|
||||
g_return_if_fail (self->filename != NULL || self->fd != -1);
|
||||
|
||||
task = g_task_new (self, cancellable, callback, user_data);
|
||||
g_task_set_task_data (task, g_object_ref (self->symbolizer), g_object_unref);
|
||||
g_task_set_source_tag (task, sysprof_document_loader_load_async);
|
||||
|
||||
if (self->fd == -1 && self->filename == NULL)
|
||||
{
|
||||
g_task_return_new_error (task,
|
||||
G_IO_ERROR,
|
||||
G_IO_ERROR_FAILED,
|
||||
"SysprofDocumentLoader disposition must have fd or filename set");
|
||||
return;
|
||||
}
|
||||
|
||||
if (self->fd != -1)
|
||||
document = _sysprof_document_new_from_fd (self->fd, &error);
|
||||
else if (self->filename != NULL)
|
||||
document = _sysprof_document_new (self->filename, &error);
|
||||
mapped_file_new_from_fd_async (self->fd,
|
||||
cancellable,
|
||||
sysprof_document_loader_load_mapped_file_cb,
|
||||
g_steal_pointer (&task));
|
||||
else
|
||||
g_assert_not_reached ();
|
||||
|
||||
/* TODO: This will probably get renamed to load_async as we want
|
||||
* to always have a symbolizer for loading. Additionally, the
|
||||
* document will deal with caches directly instead of the symbols
|
||||
* object.
|
||||
*/
|
||||
|
||||
_sysprof_document_symbolize_async (document,
|
||||
self->symbolizer,
|
||||
cancellable,
|
||||
sysprof_document_loader_load_cb,
|
||||
g_steal_pointer (&task));
|
||||
mapped_file_new_async (self->filename,
|
||||
cancellable,
|
||||
sysprof_document_loader_load_mapped_file_cb,
|
||||
g_steal_pointer (&task));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -23,24 +23,27 @@
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
#include "sysprof-document.h"
|
||||
#include "sysprof-symbolizer.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
SysprofDocument *_sysprof_document_new (const char *filename,
|
||||
GError **error);
|
||||
SysprofDocument *_sysprof_document_new_from_fd (int capture_fd,
|
||||
GError **error);
|
||||
void _sysprof_document_symbolize_async (SysprofDocument *self,
|
||||
SysprofSymbolizer *symbolizer,
|
||||
GCancellable *cancellable,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data);
|
||||
SysprofDocumentSymbols *_sysprof_document_symbolize_finish (SysprofDocument *self,
|
||||
GAsyncResult *result,
|
||||
GError **error);
|
||||
gboolean _sysprof_document_is_native (SysprofDocument *self);
|
||||
char *_sysprof_document_ref_string (SysprofDocument *self,
|
||||
const char *name);
|
||||
GtkBitset *_sysprof_document_traceables (SysprofDocument *self);
|
||||
void _sysprof_document_new_async (GMappedFile *mapped_file,
|
||||
GCancellable *cancellable,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data);
|
||||
SysprofDocument *_sysprof_document_new_finish (GAsyncResult *result,
|
||||
GError **error);
|
||||
void _sysprof_document_symbolize_async (SysprofDocument *self,
|
||||
SysprofSymbolizer *symbolizer,
|
||||
GCancellable *cancellable,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data);
|
||||
gboolean _sysprof_document_symbolize_finish (SysprofDocument *self,
|
||||
GAsyncResult *result,
|
||||
GError **error);
|
||||
gboolean _sysprof_document_is_native (SysprofDocument *self);
|
||||
char *_sysprof_document_ref_string (SysprofDocument *self,
|
||||
const char *name);
|
||||
GtkBitset *_sysprof_document_traceables (SysprofDocument *self);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
@ -21,19 +21,28 @@
|
||||
#pragma once
|
||||
|
||||
#include "sysprof-document.h"
|
||||
#include "sysprof-document-symbols.h"
|
||||
#include "sysprof-process-info-private.h"
|
||||
#include "sysprof-symbolizer.h"
|
||||
#include "sysprof-symbol.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
void _sysprof_document_symbols_new (SysprofDocument *document,
|
||||
SysprofStrings *strings,
|
||||
SysprofSymbolizer *symbolizer,
|
||||
GHashTable *pid_to_process_info,
|
||||
GCancellable *cancellable,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data);
|
||||
SysprofDocumentSymbols *_sysprof_document_symbols_new_finish (GAsyncResult *result,
|
||||
GError **error);
|
||||
#define SYSPROF_TYPE_DOCUMENT_SYMBOLS (sysprof_document_symbols_get_type())
|
||||
|
||||
G_DECLARE_FINAL_TYPE (SysprofDocumentSymbols, sysprof_document_symbols, SYSPROF, DOCUMENT_SYMBOLS, GObject)
|
||||
|
||||
void _sysprof_document_symbols_new (SysprofDocument *document,
|
||||
SysprofStrings *strings,
|
||||
SysprofSymbolizer *symbolizer,
|
||||
GHashTable *pid_to_process_info,
|
||||
GCancellable *cancellable,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data);
|
||||
SysprofDocumentSymbols *_sysprof_document_symbols_new_finish (GAsyncResult *result,
|
||||
GError **error);
|
||||
SysprofSymbol *_sysprof_document_symbols_lookup (SysprofDocumentSymbols *symbols,
|
||||
int pid,
|
||||
SysprofAddressContext context,
|
||||
SysprofAddress address);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
@ -25,6 +25,7 @@
|
||||
#include "sysprof-document-symbols-private.h"
|
||||
#include "sysprof-document-traceable.h"
|
||||
#include "sysprof-mount-namespace-private.h"
|
||||
#include "sysprof-no-symbolizer.h"
|
||||
#include "sysprof-symbol-private.h"
|
||||
#include "sysprof-symbol-cache-private.h"
|
||||
#include "sysprof-symbolizer-private.h"
|
||||
@ -175,7 +176,8 @@ sysprof_document_symbols_worker (GTask *task,
|
||||
}
|
||||
|
||||
/* Walk through the available traceables which need symbols extracted */
|
||||
if (gtk_bitset_iter_init_first (&iter, bitset, &i))
|
||||
if (!SYSPROF_IS_NO_SYMBOLIZER (state->symbolizer) &&
|
||||
gtk_bitset_iter_init_first (&iter, bitset, &i))
|
||||
{
|
||||
do
|
||||
{
|
||||
@ -243,7 +245,7 @@ _sysprof_document_symbols_new_finish (GAsyncResult *result,
|
||||
}
|
||||
|
||||
/**
|
||||
* sysprof_document_symbols_lookup:
|
||||
* _sysprof_document_symbols_lookup:
|
||||
* @self: a #SysprofDocumentSymbols
|
||||
* @pid: the process identifier
|
||||
* @context: the #SysprofAddressContext for the address
|
||||
@ -254,10 +256,10 @@ _sysprof_document_symbols_new_finish (GAsyncResult *result,
|
||||
* Returns: (transfer none) (nullable): a #SysprofSymbol or %NULL
|
||||
*/
|
||||
SysprofSymbol *
|
||||
sysprof_document_symbols_lookup (SysprofDocumentSymbols *self,
|
||||
int pid,
|
||||
SysprofAddressContext context,
|
||||
SysprofAddress address)
|
||||
_sysprof_document_symbols_lookup (SysprofDocumentSymbols *self,
|
||||
int pid,
|
||||
SysprofAddressContext context,
|
||||
SysprofAddress address)
|
||||
{
|
||||
SysprofAddressContext new_context;
|
||||
SysprofProcessInfo *process_info;
|
||||
|
||||
@ -1,43 +0,0 @@
|
||||
/*
|
||||
* sysprof-document-symbols.h
|
||||
*
|
||||
* Copyright 2023 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 <glib-object.h>
|
||||
|
||||
#include <sysprof-capture.h>
|
||||
|
||||
#include "sysprof-symbol.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define SYSPROF_TYPE_DOCUMENT_SYMBOLS (sysprof_document_symbols_get_type())
|
||||
|
||||
SYSPROF_AVAILABLE_IN_ALL
|
||||
G_DECLARE_FINAL_TYPE (SysprofDocumentSymbols, sysprof_document_symbols, SYSPROF, DOCUMENT_SYMBOLS, GObject)
|
||||
|
||||
SYSPROF_AVAILABLE_IN_ALL
|
||||
SysprofSymbol *sysprof_document_symbols_lookup (SysprofDocumentSymbols *symbols,
|
||||
int pid,
|
||||
SysprofAddressContext context,
|
||||
SysprofAddress address);
|
||||
|
||||
G_END_DECLS
|
||||
@ -63,6 +63,8 @@ struct _SysprofDocument
|
||||
|
||||
SysprofMountNamespace *mount_namespace;
|
||||
|
||||
SysprofDocumentSymbols *symbols;
|
||||
|
||||
SysprofCaptureFileHeader header;
|
||||
guint needs_swap : 1;
|
||||
};
|
||||
@ -197,6 +199,7 @@ sysprof_document_finalize (GObject *object)
|
||||
g_clear_pointer (&self->pids, gtk_bitset_unref);
|
||||
|
||||
g_clear_object (&self->mount_namespace);
|
||||
g_clear_object (&self->symbols);
|
||||
|
||||
g_clear_pointer (&self->files_first_position, g_hash_table_unref);
|
||||
|
||||
@ -390,26 +393,34 @@ sysprof_document_load_mountinfos (SysprofDocument *self)
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
sysprof_document_load (SysprofDocument *self,
|
||||
int capture_fd,
|
||||
GError **error)
|
||||
static void
|
||||
sysprof_document_load_worker (GTask *task,
|
||||
gpointer source_object,
|
||||
gpointer task_data,
|
||||
GCancellable *cancellable)
|
||||
{
|
||||
g_autoptr(SysprofDocument) self = NULL;
|
||||
g_autoptr(GHashTable) files = NULL;
|
||||
GMappedFile *mapped_file = task_data;
|
||||
goffset pos;
|
||||
gsize len;
|
||||
|
||||
g_assert (SYSPROF_IS_DOCUMENT (self));
|
||||
g_assert (capture_fd > -1);
|
||||
g_assert (source_object == NULL);
|
||||
g_assert (mapped_file != NULL);
|
||||
|
||||
if (!(self->mapped_file = g_mapped_file_new_from_fd (capture_fd, FALSE, error)))
|
||||
return FALSE;
|
||||
|
||||
self->base = (const guint8 *)g_mapped_file_get_contents (self->mapped_file);
|
||||
len = g_mapped_file_get_length (self->mapped_file);
|
||||
self = g_object_new (SYSPROF_TYPE_DOCUMENT, NULL);
|
||||
self->mapped_file = g_mapped_file_ref (mapped_file);
|
||||
self->base = (const guint8 *)g_mapped_file_get_contents (mapped_file);
|
||||
len = g_mapped_file_get_length (mapped_file);
|
||||
|
||||
if (len < sizeof self->header)
|
||||
return FALSE;
|
||||
{
|
||||
g_task_return_new_error (task,
|
||||
G_IO_ERROR,
|
||||
G_IO_ERROR_INVALID_DATA,
|
||||
"File header too short");
|
||||
return;
|
||||
}
|
||||
|
||||
/* Keep a copy of our header */
|
||||
memcpy (&self->header, self->base, sizeof self->header);
|
||||
@ -479,77 +490,39 @@ sysprof_document_load (SysprofDocument *self,
|
||||
sysprof_document_load_mountinfos (self);
|
||||
sysprof_document_load_memory_maps (self);
|
||||
|
||||
return TRUE;
|
||||
g_task_return_pointer (task, g_steal_pointer (&self), g_object_unref);
|
||||
}
|
||||
|
||||
/**
|
||||
* _sysprof_document_new_from_fd:
|
||||
* @capture_fd: a file-descriptor to be mapped
|
||||
* @error: a location for a #GError, or %NULL
|
||||
*
|
||||
* Creates a new memory map using @capture_fd to read the underlying
|
||||
* Sysprof capture.
|
||||
*
|
||||
* No ownership of @capture_fd is transferred, and the caller may close
|
||||
* @capture_fd after calling this function.
|
||||
*
|
||||
* Returns: A #SysprofDocument if successful; otherwise %NULL
|
||||
* and @error is set.
|
||||
*/
|
||||
SysprofDocument *
|
||||
_sysprof_document_new_from_fd (int capture_fd,
|
||||
GError **error)
|
||||
void
|
||||
_sysprof_document_new_async (GMappedFile *mapped_file,
|
||||
GCancellable *cancellable,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data)
|
||||
{
|
||||
g_autoptr(SysprofDocument) self = NULL;
|
||||
g_autoptr(GTask) task = NULL;
|
||||
|
||||
g_return_val_if_fail (capture_fd > -1, NULL);
|
||||
g_return_if_fail (mapped_file != NULL);
|
||||
g_return_if_fail (!cancellable || G_IS_CANCELLABLE (cancellable));
|
||||
|
||||
self = g_object_new (SYSPROF_TYPE_DOCUMENT, NULL);
|
||||
|
||||
if (!sysprof_document_load (self, capture_fd, error))
|
||||
return NULL;
|
||||
|
||||
return g_steal_pointer (&self);
|
||||
task = g_task_new (NULL, cancellable, callback, user_data);
|
||||
g_task_set_source_tag (task, _sysprof_document_new_async);
|
||||
g_task_set_task_data (task,
|
||||
g_mapped_file_ref (mapped_file),
|
||||
(GDestroyNotify)g_mapped_file_unref);
|
||||
g_task_run_in_thread (task, sysprof_document_load_worker);
|
||||
}
|
||||
|
||||
/**
|
||||
* sysprof_document_new:
|
||||
* @filename: a path to a capture file
|
||||
* @error: location for a #GError, or %NULL
|
||||
*
|
||||
* Similar to sysprof_document_new_from_fd() but opens the file found
|
||||
* at @filename as a #GMappedFile.
|
||||
*
|
||||
* Returns: a #SysprofDocument if successful; otherwise %NULL
|
||||
* and @error is set.
|
||||
*
|
||||
* Since: 45.0
|
||||
*/
|
||||
SysprofDocument *
|
||||
_sysprof_document_new (const char *filename,
|
||||
GError **error)
|
||||
_sysprof_document_new_finish (GAsyncResult *result,
|
||||
GError **error)
|
||||
{
|
||||
g_autoptr(SysprofDocument) self = NULL;
|
||||
g_autofd int capture_fd = -1;
|
||||
SysprofDocument *ret;
|
||||
|
||||
g_return_val_if_fail (filename != NULL, NULL);
|
||||
g_return_val_if_fail (G_IS_TASK (result), NULL);
|
||||
ret = g_task_propagate_pointer (G_TASK (result), error);
|
||||
g_return_val_if_fail (!ret || SYSPROF_IS_DOCUMENT (ret), NULL);
|
||||
|
||||
if (-1 == (capture_fd = g_open (filename, O_RDONLY|O_CLOEXEC, 0)))
|
||||
{
|
||||
int errsv = errno;
|
||||
g_set_error (error,
|
||||
G_FILE_ERROR,
|
||||
g_file_error_from_errno (errsv),
|
||||
"%s", g_strerror (errsv));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
self = g_object_new (SYSPROF_TYPE_DOCUMENT, NULL);
|
||||
|
||||
if (!sysprof_document_load (self, capture_fd, error))
|
||||
return NULL;
|
||||
|
||||
return g_steal_pointer (&self);
|
||||
return ret;
|
||||
}
|
||||
|
||||
char *
|
||||
@ -569,14 +542,25 @@ sysprof_document_symbolize_symbols_cb (GObject *object,
|
||||
g_autoptr(SysprofDocumentSymbols) symbols = NULL;
|
||||
g_autoptr(GTask) task = user_data;
|
||||
g_autoptr(GError) error = NULL;
|
||||
SysprofDocument *self;
|
||||
|
||||
g_assert (G_IS_ASYNC_RESULT (result));
|
||||
g_assert (G_IS_TASK (task));
|
||||
|
||||
if ((symbols = _sysprof_document_symbols_new_finish (result, &error)))
|
||||
g_task_return_pointer (task, g_steal_pointer (&symbols), g_object_unref);
|
||||
else
|
||||
g_task_return_error (task, g_steal_pointer (&error));
|
||||
if (!(symbols = _sysprof_document_symbols_new_finish (result, &error)))
|
||||
{
|
||||
g_task_return_error (task, g_steal_pointer (&error));
|
||||
return;
|
||||
}
|
||||
|
||||
self = g_task_get_source_object (task);
|
||||
|
||||
g_assert (self != NULL);
|
||||
g_assert (SYSPROF_IS_DOCUMENT (self));
|
||||
|
||||
g_set_object (&self->symbols, symbols);
|
||||
|
||||
g_task_return_boolean (task, TRUE);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -635,17 +619,17 @@ _sysprof_document_symbolize_async (SysprofDocument *self,
|
||||
g_steal_pointer (&task));
|
||||
}
|
||||
|
||||
SysprofDocumentSymbols *
|
||||
gboolean
|
||||
_sysprof_document_symbolize_finish (SysprofDocument *self,
|
||||
GAsyncResult *result,
|
||||
GError **error)
|
||||
{
|
||||
g_return_val_if_fail (SYSPROF_IS_DOCUMENT (self), NULL);
|
||||
g_return_val_if_fail (G_IS_TASK (result), NULL);
|
||||
g_return_val_if_fail (g_task_is_valid (result, self), NULL);
|
||||
g_return_val_if_fail (g_task_get_source_tag (G_TASK (result)) == _sysprof_document_symbolize_async, NULL);
|
||||
g_return_val_if_fail (SYSPROF_IS_DOCUMENT (self), FALSE);
|
||||
g_return_val_if_fail (G_IS_TASK (result), FALSE);
|
||||
g_return_val_if_fail (g_task_is_valid (result, self), FALSE);
|
||||
g_return_val_if_fail (g_task_get_source_tag (G_TASK (result)) == _sysprof_document_symbolize_async, FALSE);
|
||||
|
||||
return g_task_propagate_pointer (G_TASK (result), error);
|
||||
return g_task_propagate_boolean (G_TASK (result), error);
|
||||
}
|
||||
|
||||
gboolean
|
||||
@ -796,3 +780,51 @@ sysprof_document_list_processes (SysprofDocument *self)
|
||||
|
||||
return _sysprof_document_bitset_index_new (G_LIST_MODEL (self), self->processes);
|
||||
}
|
||||
|
||||
/**
|
||||
* sysprof_document_symbolize_traceable: (skip)
|
||||
* @self: a #SysprofDocument
|
||||
* @traceable: the traceable to extract symbols for
|
||||
* @symbols: an array to store #SysprofSymbols
|
||||
* @n_symbols: the number of elements in @symbols
|
||||
*
|
||||
* Batch symbolizing of a traceable.
|
||||
*
|
||||
* No ownership is transfered into @symbols and may be cheaply
|
||||
* discarded if using the stack for storage.
|
||||
*
|
||||
* Returns: The number of symbols or NULL set in @symbols.
|
||||
*/
|
||||
guint
|
||||
sysprof_document_symbolize_traceable (SysprofDocument *self,
|
||||
SysprofDocumentTraceable *traceable,
|
||||
SysprofSymbol **symbols,
|
||||
guint n_symbols)
|
||||
{
|
||||
SysprofAddressContext last_context = SYSPROF_ADDRESS_CONTEXT_NONE;
|
||||
SysprofAddress *addresses;
|
||||
guint n_addresses;
|
||||
int pid;
|
||||
|
||||
g_return_val_if_fail (SYSPROF_IS_DOCUMENT (self), 0);
|
||||
g_return_val_if_fail (SYSPROF_IS_DOCUMENT_TRACEABLE (traceable), 0);
|
||||
|
||||
if (n_symbols == 0 || symbols == NULL)
|
||||
return 0;
|
||||
|
||||
pid = sysprof_document_frame_get_pid (SYSPROF_DOCUMENT_FRAME (traceable));
|
||||
addresses = g_alloca (sizeof (SysprofAddress) * n_symbols);
|
||||
n_addresses = sysprof_document_traceable_get_stack_addresses (traceable, addresses, n_symbols);
|
||||
|
||||
for (guint i = 0; i < n_addresses; i++)
|
||||
{
|
||||
SysprofAddressContext context;
|
||||
|
||||
symbols[i] = _sysprof_document_symbols_lookup (self->symbols, pid, last_context, addresses[i]);
|
||||
|
||||
if (sysprof_address_is_context_switch (addresses[i], &context))
|
||||
last_context = context;
|
||||
}
|
||||
|
||||
return n_addresses;
|
||||
}
|
||||
|
||||
@ -25,8 +25,8 @@
|
||||
#include <sysprof-capture.h>
|
||||
|
||||
#include "sysprof-document-file.h"
|
||||
#include "sysprof-document-symbols.h"
|
||||
#include "sysprof-symbolizer.h"
|
||||
#include "sysprof-document-traceable.h"
|
||||
#include "sysprof-symbol.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
@ -36,13 +36,18 @@ SYSPROF_AVAILABLE_IN_ALL
|
||||
G_DECLARE_FINAL_TYPE (SysprofDocument, sysprof_document, SYSPROF, DOCUMENT, GObject)
|
||||
|
||||
SYSPROF_AVAILABLE_IN_ALL
|
||||
SysprofDocumentFile *sysprof_document_lookup_file (SysprofDocument *self,
|
||||
const char *path);
|
||||
SysprofDocumentFile *sysprof_document_lookup_file (SysprofDocument *self,
|
||||
const char *path);
|
||||
SYSPROF_AVAILABLE_IN_ALL
|
||||
GListModel *sysprof_document_list_files (SysprofDocument *self);
|
||||
GListModel *sysprof_document_list_files (SysprofDocument *self);
|
||||
SYSPROF_AVAILABLE_IN_ALL
|
||||
GListModel *sysprof_document_list_traceables (SysprofDocument *self);
|
||||
GListModel *sysprof_document_list_traceables (SysprofDocument *self);
|
||||
SYSPROF_AVAILABLE_IN_ALL
|
||||
GListModel *sysprof_document_list_processes (SysprofDocument *self);
|
||||
GListModel *sysprof_document_list_processes (SysprofDocument *self);
|
||||
SYSPROF_AVAILABLE_IN_ALL
|
||||
guint sysprof_document_symbolize_traceable (SysprofDocument *self,
|
||||
SysprofDocumentTraceable *traceable,
|
||||
SysprofSymbol **symbols,
|
||||
guint n_symbols);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
@ -181,8 +181,8 @@ sysprof_multi_symbolizer_new (void)
|
||||
* that will be queried when @self is queried for symbols.
|
||||
*/
|
||||
void
|
||||
sysprof_multi_symbolizer_add (SysprofMultiSymbolizer *self,
|
||||
SysprofSymbolizer *symbolizer)
|
||||
sysprof_multi_symbolizer_take (SysprofMultiSymbolizer *self,
|
||||
SysprofSymbolizer *symbolizer)
|
||||
{
|
||||
g_return_if_fail (SYSPROF_IS_MULTI_SYMBOLIZER (self));
|
||||
g_return_if_fail (SYSPROF_IS_SYMBOLIZER (symbolizer));
|
||||
|
||||
@ -37,7 +37,7 @@ GType sysprof_multi_symbolizer_get_type (void) G_GNUC_CONST;
|
||||
SYSPROF_AVAILABLE_IN_ALL
|
||||
SysprofMultiSymbolizer *sysprof_multi_symbolizer_new (void);
|
||||
SYSPROF_AVAILABLE_IN_ALL
|
||||
void sysprof_multi_symbolizer_add (SysprofMultiSymbolizer *self,
|
||||
void sysprof_multi_symbolizer_take (SysprofMultiSymbolizer *self,
|
||||
SysprofSymbolizer *symbolizer);
|
||||
|
||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC (SysprofMultiSymbolizer, g_object_unref)
|
||||
|
||||
@ -21,12 +21,18 @@
|
||||
#include "config.h"
|
||||
|
||||
#include "sysprof-no-symbolizer.h"
|
||||
#include "sysprof-symbolizer-private.h"
|
||||
|
||||
struct _SysprofNoSymbolizer
|
||||
{
|
||||
SysprofSymbolizer parent_instance;
|
||||
};
|
||||
|
||||
struct _SysprofNoSymbolizerClass
|
||||
{
|
||||
SysprofSymbolizerClass parent_class;
|
||||
};
|
||||
|
||||
G_DEFINE_FINAL_TYPE (SysprofNoSymbolizer, sysprof_no_symbolizer, SYSPROF_TYPE_SYMBOLIZER)
|
||||
|
||||
static SysprofSymbol *
|
||||
@ -51,8 +57,20 @@ sysprof_no_symbolizer_init (SysprofNoSymbolizer *self)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* sysprof_no_symbolizer_get:
|
||||
*
|
||||
* Gets a #SysprofSymbolizer that will never symbolize.
|
||||
*
|
||||
* Returns: (transfer none): a #SysprofSymbolizer
|
||||
*/
|
||||
SysprofSymbolizer *
|
||||
sysprof_no_symbolizer_new (void)
|
||||
sysprof_no_symbolizer_get (void)
|
||||
{
|
||||
return g_object_new (SYSPROF_TYPE_NO_SYMBOLIZER, NULL);
|
||||
static SysprofSymbolizer *instance;
|
||||
|
||||
if (g_once_init_enter (&instance))
|
||||
g_once_init_leave (&instance, g_object_new (SYSPROF_TYPE_NO_SYMBOLIZER, NULL));
|
||||
|
||||
return instance;
|
||||
}
|
||||
|
||||
@ -20,18 +20,23 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <glib-object.h>
|
||||
|
||||
#include "sysprof-symbolizer.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define SYSPROF_TYPE_NO_SYMBOLIZER (sysprof_no_symbolizer_get_type())
|
||||
#define SYSPROF_TYPE_NO_SYMBOLIZER (sysprof_no_symbolizer_get_type())
|
||||
#define SYSPROF_IS_NO_SYMBOLIZER(obj) G_TYPE_CHECK_INSTANCE_TYPE(obj, SYSPROF_TYPE_NO_SYMBOLIZER)
|
||||
#define SYSPROF_NO_SYMBOLIZER(obj) G_TYPE_CHECK_INSTANCE_CAST(obj, SYSPROF_TYPE_NO_SYMBOLIZER, SysprofNoSymbolizer)
|
||||
#define SYSPROF_NO_SYMBOLIZER_CLASS(klass) G_TYPE_CHECK_CLASS_CAST(klass, SYSPROF_TYPE_NO_SYMBOLIZER, SysprofNoSymbolizerClass)
|
||||
|
||||
typedef struct _SysprofNoSymbolizer SysprofNoSymbolizer;
|
||||
typedef struct _SysprofNoSymbolizerClass SysprofNoSymbolizerClass;
|
||||
|
||||
SYSPROF_AVAILABLE_IN_ALL
|
||||
G_DECLARE_DERIVABLE_TYPE (SysprofNoSymbolizer, sysprof_no_symbolizer, SYSPROF, NO_SYMBOLIZER, SysprofSymbolizer)
|
||||
|
||||
GType sysprof_no_symbolizer_get_type (void) G_GNUC_CONST;
|
||||
SYSPROF_AVAILABLE_IN_ALL
|
||||
SysprofSymbolizer *sysprof_no_symbolizer_new (void);
|
||||
SysprofSymbolizer *sysprof_no_symbolizer_get (void);
|
||||
|
||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC (SysprofNoSymbolizer, g_object_unref)
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
@ -9,9 +9,10 @@ int
|
||||
main (int argc,
|
||||
char *argv[])
|
||||
{
|
||||
SysprofDocument *document;
|
||||
g_autoptr(SysprofDocumentLoader) loader = NULL;
|
||||
g_autoptr(SysprofDocument) document = NULL;
|
||||
g_autoptr(GError) error = NULL;
|
||||
const char *filename;
|
||||
GError *error = NULL;
|
||||
guint n_items;
|
||||
|
||||
sysprof_clock_init ();
|
||||
@ -24,7 +25,10 @@ main (int argc,
|
||||
|
||||
filename = argv[1];
|
||||
|
||||
if (!(document = _sysprof_document_new (filename, &error)))
|
||||
loader = sysprof_document_loader_new (filename);
|
||||
sysprof_document_loader_set_symbolizer (loader, sysprof_no_symbolizer_get ());
|
||||
|
||||
if (!(document = sysprof_document_loader_load (loader, NULL, &error)))
|
||||
{
|
||||
g_printerr ("Failed to load %s: %s\n",
|
||||
filename, error->message);
|
||||
@ -88,7 +92,5 @@ main (int argc,
|
||||
|
||||
g_printerr ("%u frames\n", n_items);
|
||||
|
||||
g_clear_object (&document);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -26,6 +26,7 @@ int
|
||||
main (int argc,
|
||||
char *argv[])
|
||||
{
|
||||
g_autoptr(SysprofDocumentLoader) loader = NULL;
|
||||
g_autoptr(SysprofDocument) document = NULL;
|
||||
g_autoptr(GListModel) files = NULL;
|
||||
g_autoptr(GError) error = NULL;
|
||||
@ -37,7 +38,10 @@ main (int argc,
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!(document = _sysprof_document_new (argv[1], &error)))
|
||||
loader = sysprof_document_loader_new (argv[1]);
|
||||
sysprof_document_loader_set_symbolizer (loader, sysprof_no_symbolizer_get ());
|
||||
|
||||
if (!(document = sysprof_document_loader_load (loader, NULL, &error)))
|
||||
{
|
||||
g_printerr ("Failed to open capture: %s\n", error->message);
|
||||
return 1;
|
||||
|
||||
@ -26,6 +26,7 @@ int
|
||||
main (int argc,
|
||||
char *argv[])
|
||||
{
|
||||
g_autoptr(SysprofDocumentLoader) loader = NULL;
|
||||
g_autoptr(SysprofDocument) document = NULL;
|
||||
g_autoptr(GListModel) processes = NULL;
|
||||
g_autoptr(GError) error = NULL;
|
||||
@ -37,7 +38,10 @@ main (int argc,
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!(document = _sysprof_document_new (argv[1], &error)))
|
||||
loader = sysprof_document_loader_new (argv[1]);
|
||||
sysprof_document_loader_set_symbolizer (loader, sysprof_no_symbolizer_get ());
|
||||
|
||||
if (!(document = sysprof_document_loader_load (loader, NULL, &error)))
|
||||
{
|
||||
g_printerr ("Failed to open capture: %s\n", error->message);
|
||||
return 1;
|
||||
|
||||
@ -26,6 +26,7 @@ int
|
||||
main (int argc,
|
||||
char *argv[])
|
||||
{
|
||||
g_autoptr(SysprofDocumentLoader) loader = NULL;
|
||||
g_autoptr(SysprofDocumentFile) file = NULL;
|
||||
g_autoptr(SysprofDocument) document = NULL;
|
||||
g_autoptr(GListModel) files = NULL;
|
||||
@ -38,7 +39,10 @@ main (int argc,
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!(document = _sysprof_document_new (argv[1], &error)))
|
||||
loader = sysprof_document_loader_new (argv[1]);
|
||||
sysprof_document_loader_set_symbolizer (loader, sysprof_no_symbolizer_get ());
|
||||
|
||||
if (!(document = sysprof_document_loader_load (loader, NULL, &error)))
|
||||
{
|
||||
g_printerr ("Failed to open capture: %s\n", error->message);
|
||||
return 1;
|
||||
|
||||
@ -7,63 +7,88 @@
|
||||
static GMainLoop *main_loop;
|
||||
|
||||
static void
|
||||
symbolize_cb (GObject *object,
|
||||
GAsyncResult *result,
|
||||
gpointer user_data)
|
||||
load_cb (GObject *object,
|
||||
GAsyncResult *result,
|
||||
gpointer user_data)
|
||||
{
|
||||
SysprofDocument *document = (SysprofDocument *)object;
|
||||
g_autoptr(SysprofDocumentSymbols) symbols = NULL;
|
||||
SysprofDocumentLoader *loader = (SysprofDocumentLoader *)object;
|
||||
g_autoptr(SysprofDocument) document = NULL;
|
||||
g_autoptr(GListModel) traceables = NULL;
|
||||
g_autoptr(GError) error = NULL;
|
||||
SysprofAddress addresses[128];
|
||||
g_autoptr(GString) str = NULL;
|
||||
SysprofSymbol *symbols[128];
|
||||
guint n_symbols;
|
||||
guint n_items;
|
||||
|
||||
g_assert (SYSPROF_IS_DOCUMENT (document));
|
||||
g_assert (SYSPROF_IS_DOCUMENT_LOADER (loader));
|
||||
g_assert (G_IS_ASYNC_RESULT (result));
|
||||
|
||||
if (!(symbols = _sysprof_document_symbolize_finish (document, result, &error)))
|
||||
g_error ("Failed to symbolize: %s", error->message);
|
||||
if (!(document = sysprof_document_loader_load_finish (loader, result, &error)))
|
||||
g_error ("Failed to load document: %s", error->message);
|
||||
|
||||
traceables = sysprof_document_list_traceables (document);
|
||||
n_items = g_list_model_get_n_items (traceables);
|
||||
|
||||
str = g_string_new ("");
|
||||
|
||||
for (guint i = 0; i < n_items; i++)
|
||||
{
|
||||
g_autoptr(SysprofDocumentTraceable) traceable = g_list_model_get_item (traceables, i);
|
||||
SysprofAddressContext last_context;
|
||||
guint depth;
|
||||
int pid;
|
||||
|
||||
str->len = 0;
|
||||
str->str[0] = 0;
|
||||
|
||||
g_assert (traceable != NULL);
|
||||
g_assert (SYSPROF_IS_DOCUMENT_TRACEABLE (traceable));
|
||||
|
||||
last_context = SYSPROF_ADDRESS_CONTEXT_NONE;
|
||||
pid = sysprof_document_frame_get_pid (SYSPROF_DOCUMENT_FRAME (traceable));
|
||||
depth = sysprof_document_traceable_get_stack_addresses (traceable, addresses, G_N_ELEMENTS (addresses));
|
||||
n_symbols = sysprof_document_symbolize_traceable (document,
|
||||
traceable,
|
||||
symbols,
|
||||
G_N_ELEMENTS (symbols));
|
||||
|
||||
g_print ("%s depth=%u pid=%u\n",
|
||||
G_OBJECT_TYPE_NAME (traceable), depth, pid);
|
||||
G_OBJECT_TYPE_NAME (traceable),
|
||||
n_symbols,
|
||||
sysprof_document_frame_get_pid (SYSPROF_DOCUMENT_FRAME (traceable)));
|
||||
|
||||
for (guint j = 0; j < depth; j++)
|
||||
for (guint j = 0; j < n_symbols; j++)
|
||||
{
|
||||
SysprofAddress address = addresses[j];
|
||||
SysprofSymbol *symbol = sysprof_document_symbols_lookup (symbols, pid, last_context, address);
|
||||
SysprofAddressContext context;
|
||||
|
||||
if (sysprof_address_is_context_switch (address, &context))
|
||||
last_context = context;
|
||||
SysprofSymbol *symbol = symbols[j];
|
||||
const char *name;
|
||||
const char *path;
|
||||
const char *nick;
|
||||
|
||||
if (symbol != NULL)
|
||||
g_print (" %02d: %p: %s [%s]\n",
|
||||
j,
|
||||
GSIZE_TO_POINTER (address),
|
||||
sysprof_symbol_get_name (symbol),
|
||||
sysprof_symbol_get_binary_path (symbol) ?: "<unresolved>");
|
||||
{
|
||||
name = sysprof_symbol_get_name (symbol);
|
||||
path = sysprof_symbol_get_binary_path (symbol);
|
||||
nick = sysprof_symbol_get_binary_nick (symbol);
|
||||
}
|
||||
else
|
||||
g_print (" %02d: %p:\n", j, GSIZE_TO_POINTER (address));
|
||||
{
|
||||
name = path = nick = NULL;
|
||||
}
|
||||
|
||||
g_string_append_printf (str,
|
||||
" %02d: 0x%"G_GINT64_MODIFIER"x:",
|
||||
j,
|
||||
sysprof_document_traceable_get_stack_address (traceable, j));
|
||||
|
||||
if (name)
|
||||
g_string_append_printf (str, " %s", name);
|
||||
|
||||
if (path)
|
||||
g_string_append_printf (str, " [%s]", path);
|
||||
|
||||
if (nick)
|
||||
g_string_append_printf (str, " (%s)", nick);
|
||||
|
||||
g_string_append_c (str, '\n');
|
||||
}
|
||||
|
||||
g_print (" ================\n");
|
||||
g_string_append (str, " ================\n");
|
||||
|
||||
write (STDOUT_FILENO, str->str, str->len);
|
||||
}
|
||||
|
||||
g_print ("Document symbolized\n");
|
||||
@ -75,10 +100,8 @@ int
|
||||
main (int argc,
|
||||
char *argv[])
|
||||
{
|
||||
g_autoptr(SysprofDocument) document = NULL;
|
||||
g_autoptr(SysprofMultiSymbolizer) multi = NULL;
|
||||
g_autoptr(SysprofDocumentLoader) loader = NULL;
|
||||
g_autoptr(GError) error = NULL;
|
||||
const char *filename;
|
||||
|
||||
main_loop = g_main_loop_new (NULL, FALSE);
|
||||
|
||||
@ -88,23 +111,8 @@ main (int argc,
|
||||
return 1;
|
||||
}
|
||||
|
||||
filename = argv[1];
|
||||
|
||||
if (!(document = _sysprof_document_new (filename, &error)))
|
||||
{
|
||||
g_printerr ("Failed to load document: %s\n", error->message);
|
||||
return 1;
|
||||
}
|
||||
|
||||
multi = sysprof_multi_symbolizer_new ();
|
||||
sysprof_multi_symbolizer_add (multi, sysprof_bundled_symbolizer_new ());
|
||||
|
||||
_sysprof_document_symbolize_async (document,
|
||||
SYSPROF_SYMBOLIZER (multi),
|
||||
NULL,
|
||||
symbolize_cb,
|
||||
NULL);
|
||||
|
||||
loader = sysprof_document_loader_new (argv[1]);
|
||||
sysprof_document_loader_load_async (loader, NULL, load_cb, NULL);
|
||||
g_main_loop_run (main_loop);
|
||||
|
||||
return 0;
|
||||
|
||||
Reference in New Issue
Block a user