summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog37
-rw-r--r--HACKING3
-rw-r--r--Makefile.am1
-rw-r--r--configure.in2
-rw-r--r--tools/.cvsignore2
-rw-r--r--tools/Makefile.am5
-rw-r--r--tools/README3
-rw-r--r--tools/leak-checker/.cvsignore2
-rw-r--r--tools/leak-checker/Makefile.am38
-rw-r--r--tools/leak-checker/nautilus-leak-checker-stubs.h78
-rw-r--r--tools/leak-checker/nautilus-leak-checker.c1077
-rw-r--r--tools/leak-checker/nautilus-leak-checker.h54
-rw-r--r--tools/leak-checker/nautilus-leak-hash-table.c533
-rw-r--r--tools/leak-checker/nautilus-leak-hash-table.h63
-rw-r--r--tools/leak-checker/nautilus-leak-symbol-lookup.c294
-rw-r--r--tools/leak-checker/nautilus-leak-symbol-lookup.h34
-rw-r--r--tools/profiler/Makefile14
-rw-r--r--tools/profiler/funcsummary.C154
-rw-r--r--tools/profiler/funcsummary.h89
-rw-r--r--tools/profiler/machine-profile.S46
-rw-r--r--tools/profiler/machine-profile.h34
-rw-r--r--tools/profiler/machine-profileP.h69
-rw-r--r--tools/profiler/nautilus-leak-symbol-lookup.C301
-rw-r--r--tools/profiler/nautilus-leak-symbol-lookup.h9
-rw-r--r--tools/profiler/profile.C457
-rw-r--r--tools/profiler/profile.h100
-rw-r--r--tools/profiler/profileP.h44
-rw-r--r--tools/profiler/profiledata.C310
-rw-r--r--tools/profiler/profiledata.h277
-rw-r--r--tools/profiler/symbol-table.h67
-rw-r--r--tools/profiler/test.cpp79
-rw-r--r--tools/profiler/totaltime.C34
-rw-r--r--tools/profiler/totaltime.h48
33 files changed, 43 insertions, 4315 deletions
diff --git a/ChangeLog b/ChangeLog
index 035bf2924..37069f0d7 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,40 @@
+2000-09-29 Ramiro Estrugo <ramiro@eazel.com>
+
+ * Makefile.am:
+ * configure.in:
+ * HACKING:
+ * tools/.cvsignore:
+ * tools/Makefile.am:
+ * tools/README:
+ * tools/leak-checker/.cvsignore:
+ * tools/leak-checker/Makefile.am:
+ * tools/leak-checker/nautilus-leak-checker-stubs.h:
+ * tools/leak-checker/nautilus-leak-checker.c:
+ * tools/leak-checker/nautilus-leak-checker.h:
+ * tools/leak-checker/nautilus-leak-hash-table.c:
+ * tools/leak-checker/nautilus-leak-hash-table.h:
+ * tools/leak-checker/nautilus-leak-symbol-lookup.c:
+ * tools/leak-checker/nautilus-leak-symbol-lookup.h:
+ * tools/profiler/Makefile:
+ * tools/profiler/funcsummary.C:
+ * tools/profiler/funcsummary.h:
+ * tools/profiler/machine-profile.S:
+ * tools/profiler/machine-profile.h:
+ * tools/profiler/machine-profileP.h:
+ * tools/profiler/nautilus-leak-symbol-lookup.C:
+ * tools/profiler/nautilus-leak-symbol-lookup.h:
+ * tools/profiler/profile.C:
+ * tools/profiler/profile.h:
+ * tools/profiler/profileP.h:
+ * tools/profiler/profiledata.C:
+ * tools/profiler/profiledata.h:
+ * tools/profiler/symbol-table.h:
+ * tools/profiler/test.cpp:
+ * tools/profiler/totaltime.C:
+ * tools/profiler/totaltime.h:
+ Moved the leak-checker and profiler tools to their own gnome cvs
+ module.
+
2000-09-29 Robey Pointer <robey@eazel.com>
* nautilus-installer/src/bootstrap-background.xpm:
diff --git a/HACKING b/HACKING
index 91a6568db..e9889fab9 100644
--- a/HACKING
+++ b/HACKING
@@ -32,6 +32,9 @@ read other relevant documents in the docs directory too.
2: Using the leak checker
=========================
+The leak checker is built as part of the eazel-tools gnome module.
+Build that first before you continue.
+
Nautilus is set up to use the libleakcheck.so leak checking
library. To use it, run Nautilus with LD_PRELOAD set to the path to
the installed libleakcheck.so library. For example, if you are using a
diff --git a/Makefile.am b/Makefile.am
index 3549bbfe7..272198898 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -15,7 +15,6 @@ SUBDIRS = \
po \
src \
test \
- tools \
$(NULL)
EXTRA_DIST= \
diff --git a/configure.in b/configure.in
index 08069e3cc..ba7c6be97 100644
--- a/configure.in
+++ b/configure.in
@@ -604,8 +604,6 @@ components/loser/sidebar/Makefile
components/tree/Makefile
helper-utilities/Makefile
helper-utilities/authenticate/Makefile
-tools/Makefile
-tools/leak-checker/Makefile
po/Makefile.in
intl/Makefile
test/Makefile
diff --git a/tools/.cvsignore b/tools/.cvsignore
deleted file mode 100644
index 282522db0..000000000
--- a/tools/.cvsignore
+++ /dev/null
@@ -1,2 +0,0 @@
-Makefile
-Makefile.in
diff --git a/tools/Makefile.am b/tools/Makefile.am
deleted file mode 100644
index 24696f70d..000000000
--- a/tools/Makefile.am
+++ /dev/null
@@ -1,5 +0,0 @@
-NULL=
-
-SUBDIRS = \
- leak-checker \
- $(NULL)
diff --git a/tools/README b/tools/README
new file mode 100644
index 000000000..addc4410b
--- /dev/null
+++ b/tools/README
@@ -0,0 +1,3 @@
+The leak-checker and profiler have been moved to their own gnome cvs
+module: eazel-tools. Please look there.
+
diff --git a/tools/leak-checker/.cvsignore b/tools/leak-checker/.cvsignore
deleted file mode 100644
index 3dda72986..000000000
--- a/tools/leak-checker/.cvsignore
+++ /dev/null
@@ -1,2 +0,0 @@
-Makefile.in
-Makefile
diff --git a/tools/leak-checker/Makefile.am b/tools/leak-checker/Makefile.am
deleted file mode 100644
index 7ca280253..000000000
--- a/tools/leak-checker/Makefile.am
+++ /dev/null
@@ -1,38 +0,0 @@
-NULL=
-
-INCLUDES =\
- -I$(top_srcdir) \
- -I$(top_builddir) \
- -I$(top_builddir)/libnautilus \
- $(BONOBO_CFLAGS) \
- $(OAF_CFLAGS) \
- $(GCONF_CFLAGS) \
- $(GNOMEUI_CFLAGS) \
- $(VFS_CFLAGS) \
- $(XML_CFLAGS) \
- -DVERSION="\"$(VERSION)\"" \
- -DGNOMELOCALEDIR=\""$(datadir)/locale"\" \
- $(NULL)
-
-# for now just hardcode a plain old link line, someday someone can
-#figure out what the magic password is to make libtool do this cleanly
-
-all: libleakcheck.so
-CLEANFILES += libleakcheck.so
-
-libleakcheck.so: nautilus-leak-checker.c nautilus-leak-hash-table.c nautilus-leak-symbol-lookup.c
- gcc $(srcdir)/nautilus-leak-checker.c $(srcdir)/nautilus-leak-hash-table.c \
- $(srcdir)/nautilus-leak-symbol-lookup.c \
- -Wall -o $@ -shared $(GLIB_CFLAGS) $(GLIB_LIBS) -lpthread -ldl -Wl,-Bstatic -lbfd -liberty -Wl,-Bdynamic
-
-# to include them in "make dist"
-EXTRA_DIST = nautilus-leak-checker.c nautilus-leak-hash-table.c nautilus-leak-symbol-lookup.c \
- nautilus-leak-checker-stubs.h nautilus-leak-hash-table.h nautilus-leak-checker.h nautilus-leak-symbol-lookup.h
-
-leakcheck_DATA = libleakcheck.so
-leakcheckdir= $(DESTDIR)$(libdir)
-
-leakchecktest: nautilus-leak-checker.c nautilus-leak-hash-table.c nautilus-leak-symbol-lookup.c
- gcc $(srcdir)/nautilus-leak-checker.c $(srcdir)/nautilus-leak-hash-table.c \
- $(srcdir)/nautilus-leak-symbol-lookup.c \
- -Wall -o $@ -DLEAK_CHECK_TESTING $(GLIB_CFLAGS) $(GLIB_LIBS) -lpthread -ldl -Wl,-Bstatic -lbfd -liberty -Wl,-Bdynamic
diff --git a/tools/leak-checker/nautilus-leak-checker-stubs.h b/tools/leak-checker/nautilus-leak-checker-stubs.h
deleted file mode 100644
index 8f175dfda..000000000
--- a/tools/leak-checker/nautilus-leak-checker-stubs.h
+++ /dev/null
@@ -1,78 +0,0 @@
-/* nautilus-leak-checker-stubs.h - simple leak checking library
- Virtual File System Library
-
- Copyright (C) 2000 Eazel
-
- The Gnome Library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public License as
- published by the Free Software Foundation; either version 2 of the
- License, or (at your option) any later version.
-
- The Gnome Library 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
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with the Gnome Library; see the file COPYING.LIB. If not,
- write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- Boston, MA 02111-1307, USA.
-
- Author: Pavel Cisler <pavel@eazel.com>
- based on MemProf by Owen Taylor, <otaylor@redhat.com>
-*/
-
-#ifndef LEAK_CHECKER_STUBS_H
-#define LEAK_CHECKER_STUBS_H
-
-
-extern void *(* real_malloc) (size_t size);
-extern void *(* real_memalign) (size_t boundary, size_t size);
-extern void *(* real_realloc) (void *ptr, size_t size);
-extern void *(* real_calloc) (void *ptr, size_t size);
-extern void (*real_free) (void *ptr);
-
-
-void *__libc_malloc (size_t size);
-void *__libc_memalign (size_t boundary, size_t size);
-void *__libc_calloc (size_t count, size_t size);
-void *__libc_realloc (void *ptr, size_t size);
-void __libc_free (void *ptr);
-
-/* Records the context of an allocation.
- * We could add pid, allocation time, etc. if needed.
- */
-typedef struct {
- /* pointer returned by malloc/realloc */
- void *block;
-
- /* allocated size */
- size_t size;
-
- /* NULL-terminated array of return addresses */
- void **stack_crawl;
-} NautilusLeakAllocationRecord;
-
-void nautilus_leak_allocation_record_finalize
- (NautilusLeakAllocationRecord *record);
-void nautilus_leak_allocation_record_free (NautilusLeakAllocationRecord *record);
-void nautilus_leak_allocation_record_init (NautilusLeakAllocationRecord *record,
- void *block,
- size_t initial_size,
- void **stack_crawl,
- int max_depth);
-NautilusLeakAllocationRecord *nautilus_leak_allocation_record_copy
- (const NautilusLeakAllocationRecord *record);
-
-int nautilus_leak_stack_crawl_compare (void **stack_crawl1,
- void **stack_crawl2,
- int levels);
-
-/* Hash table entry. */
-struct NautilusHashEntry {
- int next;
- NautilusLeakAllocationRecord data;
-};
-
-
-#endif \ No newline at end of file
diff --git a/tools/leak-checker/nautilus-leak-checker.c b/tools/leak-checker/nautilus-leak-checker.c
deleted file mode 100644
index 8cebf520e..000000000
--- a/tools/leak-checker/nautilus-leak-checker.c
+++ /dev/null
@@ -1,1077 +0,0 @@
-/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
-
-/* nautilus-leak-checker.c - simple leak checking library
- Virtual File System Library
-
- Copyright (C) 2000 Eazel
-
- The Gnome Library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public License as
- published by the Free Software Foundation; either version 2 of the
- License, or (at your option) any later version.
-
- The Gnome Library 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
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with the Gnome Library; see the file COPYING.LIB. If not,
- write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- Boston, MA 02111-1307, USA.
-
- Author: Pavel Cisler <pavel@eazel.com>
- based on MemProf by Owen Taylor, <otaylor@redhat.com>
-*/
-
-#include "nautilus-leak-checker.h"
-/* included first, defines following switch*/
-
-#if LEAK_CHECKER
-
-#include <malloc.h>
-#include <dlfcn.h>
-#include <malloc.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "nautilus-leak-checker-stubs.h"
-#include "nautilus-leak-hash-table.h"
-#include "nautilus-leak-symbol-lookup.h"
-
-/* this is the maximum number of stack crawl levels we can capture */
-enum {
- TRACE_ARRAY_MAX = 512
-};
-
-static volatile gboolean nautilus_leak_hooks_initialized;
-static volatile gboolean nautilus_leak_initializing_hooks;
-static volatile gboolean nautilus_leak_check_leaks;
-
-void *(* real_malloc) (size_t size);
-void *(* real_memalign) (size_t boundary, size_t size);
-void *(* real_realloc) (void *ptr, size_t size);
-void *(* real_calloc) (void *ptr, size_t size);
-void (* real_free) (void *ptr);
-int (* real_start_main) (int (*main) (int, char **, char **), int argc,
- char **argv, void (*init) (void), void (*fini) (void),
- void (*rtld_fini) (void), void *stack_end);
-
-/* We clean up on exit, but not all libraries do so.
- * For ones that don't, list tell-tale stack crawl function names.
- */
-static const char * const known_leakers[] = {
- "ConfigServer_remove_listener", /* gconf */
- "XSupportsLocale",
- "__bindtextdomain",
- "__pthread_initialize_manager",
- "__textdomain",
- "_gnome_config_get_bool_with_default",
- "_nl_find_domain",
- "bonobo_init",
- "client_parse_func", /* gnome-libs */
- "client_save_yourself_callback", /* gnome-libs */
- "g_18n_get_language_list",
- "g_data_initialize",
- "g_data_set_internal", /* no easy way to make it not cache blocks */
- "g_dataset_id_set_data_full", /* no easy way to make it not cache blocks */
- "g_get_any_init",
- "g_hash_node_new",
- "g_log_set_handler",
- "g_main_add_poll_unlocked", /* no easy way to make it not cache blocks */
- "g_quark_new",
- "g_thread_init",
- "gconf_postinit",
- "gdk_atom_intern",
- "gdk_pixbuf_load_module",
- "gnome_add_gtk_arg_callback",
- "gnome_client_init",
- "gnome_i18n_get_language_list",
- "gnome_init_cb",
- "gnome_stock_pixmap",
- "gnome_stock_pixmap_change",
- "gnome_stock_pixmap_register",
- "gnome_stock_pixmap_widget",
- "gnome_vfs_add_module_to_hash_table",
- "gnome_vfs_application_registry_init",
- "gnome_vfs_backend_loadinit",
- "gnome_vfs_i18n_get_language_list",
- "gnome_vfs_init",
- "gnomelib_init",
- "gtk_init",
- "gtk_item_factory_add_foreign",
- "gtk_rc_get_style",
- "gtk_rc_init",
- "gtk_rc_parse",
- "gtk_rc_style_init",
- "gtk_type_class_init",
- "gtk_type_init",
- "gtk_type_register_enum",
- "gtk_type_register_flags",
- "gtk_type_unique",
- "gtk_widget_queue_draw_data", /* no easy way to make it not cache blocks */
- "load_module",
- "mbtowc",
- "oaf_existing_set",
- "oaf_init",
- "pthread_initialize",
- "register_client", /* gconf */
- "setlocale",
- "stock_pixmaps", /* gnome-libs */
- "try_to_contact_server", /* gconf */
- "tzset_internal",
-};
-
-static const char *app_path;
-
-void
-nautilus_leak_allocation_record_init (NautilusLeakAllocationRecord *record,
- void *block, size_t initial_size, void **stack_crawl, int max_depth)
-{
- int stack_depth, index;
-
- record->block = block;
- record->size = initial_size;
-
- for (index = 0; index < max_depth; index++) {
- if (stack_crawl[index] == NULL)
- break;
- }
-
- stack_depth = index;
-
- /* call real_malloc to avoid recursion and messing up results */
- record->stack_crawl = real_malloc ((stack_depth + 1) * sizeof(void *));
- memcpy (record->stack_crawl, stack_crawl, stack_depth * sizeof(void *));
- record->stack_crawl[stack_depth] = NULL;
-}
-
-NautilusLeakAllocationRecord *
-nautilus_leak_allocation_record_copy (const NautilusLeakAllocationRecord *record)
-{
- int stack_depth, index;
- NautilusLeakAllocationRecord *result;
-
- result = real_malloc (sizeof(*result));
-
- result->block = record->block;
- result->size = record->size;
-
- for (index = 0; ; index++) {
- if (record->stack_crawl[index] == NULL)
- break;
- }
- stack_depth = index;
- result->stack_crawl = real_malloc ((stack_depth + 1) * sizeof(void *));
- memcpy (result->stack_crawl, record->stack_crawl, (stack_depth + 1) * sizeof(void *));
-
- return result;
-}
-
-void
-nautilus_leak_allocation_record_finalize (NautilusLeakAllocationRecord *record)
-{
- /* call real_free to avoid recursion and messing up results */
- real_free (record->stack_crawl);
-}
-
-void
-nautilus_leak_allocation_record_free (NautilusLeakAllocationRecord *record)
-{
- /* call real_free to avoid recursion and messing up results */
- real_free (record->stack_crawl);
- real_free (record);
-}
-
-/* return a strcmp-like result to be used in sort funcitons */
-int
-nautilus_leak_stack_crawl_compare (void **stack_crawl1, void **stack_crawl2, int levels)
-{
- int index;
- for (index = 0; index < levels; index++) {
- if (stack_crawl1 [index] == NULL && stack_crawl2 [index] == NULL) {
- return 0;
- }
-
- if (stack_crawl1 [index] < stack_crawl2 [index]) {
- return -1;
- } else if (stack_crawl1 [index] > stack_crawl2 [index]) {
- return 1;
- }
- }
-
- return 0;
-}
-
-static void
-nautilus_leak_initialize (void)
-{
- /* Locate the original malloc calls. The dlsym calls
- * will allocate memory when doing lookups. We use a special
- * trick to deal with the fact that real_malloc is not set up
- * yet while we are doing the first dlsym -- see malloc.
- */
- real_malloc = dlsym (RTLD_NEXT, "__libc_malloc");
- real_realloc = dlsym (RTLD_NEXT, "__libc_realloc");
- real_free = dlsym (RTLD_NEXT, "__libc_free");
- real_memalign = dlsym (RTLD_NEXT, "__libc_memalign");
- real_calloc = dlsym (RTLD_NEXT, "__libc_calloc");
- real_start_main = dlsym (RTLD_NEXT, "__libc_start_main");
-
- nautilus_leak_hooks_initialized = TRUE;
- nautilus_leak_check_leaks = TRUE;
-}
-
-typedef struct StackFrame StackFrame;
-
-struct StackFrame {
- StackFrame *next_frame;
- void *return_address;
- /* first argument is here */
-};
-
-static void
-get_stack_trace (void **trace_array, int trace_array_max)
-{
- int index;
- const StackFrame *stack_frame;
-
- /* point to the stack frame pointer, two words before the
- * address of the first argument
- */
- stack_frame = (const StackFrame *)((void **)&trace_array - 2);
-
-
- /* Record stack frames; skip first two in the malloc calls. */
- for (index = -2; index < trace_array_max; index++) {
- if (index >= 0) {
- /* Return address is the next pointer after
- * stack frame.
- */
- trace_array [index] = stack_frame->return_address;
- }
- stack_frame = stack_frame->next_frame;
- if (stack_frame == NULL) {
- break;
- }
- }
- if (index < trace_array_max) {
- trace_array [index] = NULL;
- }
-}
-
-/* Figure out if one of the malloc calls is reentering itself.
- * There seems no cleaner way to handle this -- we want to override
- * malloc calls at the __libc_* level.
- * The malloc hooks recurse when initializing themselves.
- * When this happens we need a reliable way to tell that a recursion is
- * underway so as to not record the corresponding malloc call twice
- */
-static gboolean
-detect_reentry (void *parent_caller)
-{
- int count;
- const StackFrame *stack_frame;
-
- stack_frame = (const StackFrame *)((void **)&parent_caller - 2);
- stack_frame = stack_frame->next_frame;
-
- for (count = 0; count < 7; count++) {
- /* See if we return address on the stack
- * that is near the parent_caller -- the start address
- * of the calling function.
- * We are using two arbitrary numbers here - 5 should be a "deep enough"
- * check to detect the recursion, 0x40 bytes should be a large enough distance
- * from the start of the malloc call to the point where the old malloc call is
- * being called.
- * FIXME bugzilla.eazel.com 2467:
- * The value 0x40 works well only with certain function sizes, optimization levels,
- * etc. need a more robust way of doing this. One way might be adding stuffing into the
- * __libc_* calls that is never executed but makes the funcitons longer. We could
- * then up the value without the danger of hitting the next function
- */
- if (stack_frame->return_address >= parent_caller
- && stack_frame->return_address < (void *)((char *)parent_caller + 0x40)) {
- /* printf("detected reentry at level %d\n", count); */
- return TRUE;
- }
- stack_frame = stack_frame->next_frame;
- if (stack_frame == NULL) {
- break;
- }
- }
- return FALSE;
-}
-
-static pthread_mutex_t nautilus_leak_hash_table_mutex = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP;
-static NautilusLeakHashTable *nautilus_leak_hash_table;
-
-static void
-nautilus_leak_record_malloc (void *ptr, size_t size)
-{
- void *trace_array [TRACE_ARRAY_MAX];
- NautilusHashEntry *element;
-
- /* printf("new block %p, %d\n", ptr, size); */
-
- if (!nautilus_leak_check_leaks)
- return;
-
- get_stack_trace (trace_array, TRACE_ARRAY_MAX);
-
- pthread_mutex_lock (&nautilus_leak_hash_table_mutex);
-
- if (nautilus_leak_hash_table == NULL) {
- nautilus_leak_hash_table = nautilus_leak_hash_table_new (10 * 1024);
- }
- if (nautilus_leak_hash_table_find (nautilus_leak_hash_table, (gulong)ptr) != NULL) {
- printf("*** block %p appears to already be allocated "
- "- someone must have sneaked a free past us\n", ptr);
- nautilus_leak_hash_table_remove (nautilus_leak_hash_table, (gulong)ptr);
- }
- /* insert a new item into the hash table, using the block address as the key */
- element = nautilus_leak_hash_table_add (nautilus_leak_hash_table, (gulong)ptr);
-
- /* fill out the new allocated element */
- nautilus_leak_allocation_record_init (&element->data, ptr, size, trace_array, TRACE_ARRAY_MAX);
-
- pthread_mutex_unlock (&nautilus_leak_hash_table_mutex);
-}
-
-static void
-nautilus_leak_record_realloc (void *old_ptr, void *new_ptr, size_t size)
-{
- void *trace_array [TRACE_ARRAY_MAX];
- NautilusHashEntry *element;
-
- /* printf("reallocing block %p, %d was %p\n", new_ptr, size, old_ptr); */
-
- if (!nautilus_leak_check_leaks)
- return;
-
- get_stack_trace (trace_array, TRACE_ARRAY_MAX);
-
- pthread_mutex_lock (&nautilus_leak_hash_table_mutex);
-
- /* must have hash table by now */
- g_assert (nautilus_leak_hash_table != NULL);
- /* must have seen the block already */
- element = nautilus_leak_hash_table_find (nautilus_leak_hash_table, (gulong)old_ptr);
- if (element == NULL) {
- printf("*** we haven't seen block %p yet "
- "- someone must have sneaked a malloc past us\n", old_ptr);
- } else {
- nautilus_leak_hash_table_remove (nautilus_leak_hash_table, (gulong)old_ptr);
- }
-
- /* shouldn't have this block yet */
- if (nautilus_leak_hash_table_find (nautilus_leak_hash_table, (gulong)new_ptr) != NULL) {
- printf("*** block %p appears to already be allocated "
- "- someone must have sneaked a free past us\n", new_ptr);
- nautilus_leak_hash_table_remove (nautilus_leak_hash_table, (gulong)new_ptr);
- }
-
- /* insert a new item into the hash table, using the block address as the key */
- element = nautilus_leak_hash_table_add (nautilus_leak_hash_table, (gulong)new_ptr);
-
- /* Fill out the new allocated element.
- * This way the last call to relloc will be the stack crawl that shows up in the
- * final balance.
- */
- nautilus_leak_allocation_record_init (&element->data, new_ptr, size, trace_array,
- TRACE_ARRAY_MAX);
-
- pthread_mutex_unlock (&nautilus_leak_hash_table_mutex);
-}
-
-static void
-nautilus_leak_record_free (void *ptr)
-{
- NautilusHashEntry *element;
- /* printf("freeing block %p\n", ptr); */
- if (!nautilus_leak_check_leaks)
- return;
-
- pthread_mutex_lock (&nautilus_leak_hash_table_mutex);
-
- /* must have hash table by now */
- g_assert (nautilus_leak_hash_table != NULL);
- /* must have seen the block already */
- element = nautilus_leak_hash_table_find (nautilus_leak_hash_table, (gulong)ptr);
- if (element == NULL) {
- printf("*** we haven't seen block %p yet "
- "- someone must have sneaked a malloc past us\n", ptr);
- } else {
- nautilus_leak_hash_table_remove (nautilus_leak_hash_table, (gulong)ptr);
- }
- pthread_mutex_unlock (&nautilus_leak_hash_table_mutex);
-
-}
-
-static void
-nautilus_leak_initialize_if_needed (void)
-{
- if (nautilus_leak_hooks_initialized)
- return;
-
- if (nautilus_leak_initializing_hooks)
- /* guard against reentrancy */
- return;
-
- nautilus_leak_initializing_hooks = TRUE;
- nautilus_leak_initialize ();
- nautilus_leak_initializing_hooks = FALSE;
-}
-
-/* we are overlaying the original __libc_malloc */
-enum {
- STARTUP_FALLBACK_MEMORY_SIZE = 1024
-};
-
-static int startup_fallback_memory_index = 0;
-static char startup_fallback_memory [STARTUP_FALLBACK_MEMORY_SIZE];
-
-/* If our malloc hook is not installed yet - for instance when we are being
- * called from the initialize_if_needed routine. We have to fall back on
- * returning a chunk of static memory to carry us through the initialization.
- */
-static void *
-allocate_temporary_fallback_memory (ssize_t size)
-{
- void *result;
-
- /* align to natural word boundary */
- size = (size + sizeof(void *) - 1 ) & ~(sizeof(void *) - 1);
- if (size + startup_fallback_memory_index
- > STARTUP_FALLBACK_MEMORY_SIZE) {
- g_warning ("trying to allocate to much space during startup");
- return NULL;
- }
- result = &startup_fallback_memory [startup_fallback_memory_index];
- startup_fallback_memory_index += size;
-
- return result;
-}
-
-void *
-__libc_malloc (size_t size)
-{
- void *result;
-
- nautilus_leak_initialize_if_needed ();
-
- if (real_malloc == NULL) {
- return allocate_temporary_fallback_memory (size);
- }
-
- result = (*real_malloc) (size);
-
- if (result != NULL) {
- if (detect_reentry(&__libc_malloc)
- || detect_reentry(&__libc_realloc)
- || detect_reentry(&__libc_memalign)) {
- /* printf("avoiding reentry in __libc_malloc, block %p\n", result); */
- } else {
- nautilus_leak_record_malloc (result, size);
- }
- }
-
- return result;
-}
-
-void *
-__libc_memalign (size_t boundary, size_t size)
-{
- void *result;
-
- nautilus_leak_initialize_if_needed ();
- result = (*real_memalign) (boundary, size);
-
- if (result != NULL) {
- if (detect_reentry(&__libc_memalign)) {
- /* printf("avoiding reentry in __libc_memalign, block %p\n", result); */
- } else {
- nautilus_leak_record_malloc (result, size);
- }
- }
-
- return result;
-}
-
-/* We are implementing __libc_calloc by calling __libc_malloc and memset
- * instead of calling real_calloc for a reason. dlsym calls
- * calloc and this way we prevent recursion during initialization.
- * If we didn't do this, we would have to teach __libc_calloc to use
- * fallback startup memory like __libc_malloc does.
- */
-void *
-__libc_calloc (size_t count, size_t size)
-{
- size_t total;
- void *result;
-
- total = count * size;
- nautilus_leak_initialize_if_needed ();
- result = __libc_malloc (total);
-
- if (result != NULL) {
- memset (result, 0, total);
- }
-
- return result;
-}
-
-void *
-__libc_realloc (void *ptr, size_t size)
-{
- void *result;
- nautilus_leak_initialize_if_needed ();
- result = (*real_realloc) (ptr, size);
-
- if (detect_reentry(&__libc_realloc)) {
- /* printf("avoiding reentry in __libc_realloc, block %p, old block %p\n",
- result, ptr); */
- } else {
- if (result != NULL && ptr == NULL) {
- /* we are allocating a new block */
- nautilus_leak_record_malloc (result, size);
- } else {
- nautilus_leak_record_realloc (ptr, result, size);
- }
- }
- return result;
-}
-
-void
-__libc_free (void *ptr)
-{
- nautilus_leak_initialize_if_needed ();
-
- if (ptr > (void *)&startup_fallback_memory[0]
- && ptr < (void *)&startup_fallback_memory[STARTUP_FALLBACK_MEMORY_SIZE]) {
- /* this is a temporary startup fallback block, don't do anything
- * with it
- */
- return;
- }
- if (ptr != NULL) {
- if (detect_reentry(&__libc_realloc)) {
- /* printf("avoiding reentry in __libc_free, block %p\n", ptr); */
- } else {
- nautilus_leak_record_free (ptr);
- }
- }
-
- (real_free) (ptr);
-}
-
-static void
-print_leaks_at_exit (void)
-{
- /* If leak checking, dump all the outstanding allocations just before exiting. */
- nautilus_leak_print_leaks (8, 15, 100, TRUE);
-}
-
-int
-__libc_start_main (int (*main) (int, char **, char **), int argc,
- char **argv, void (*init) (void), void (*fini) (void),
- void (*rtld_fini) (void), void *stack_end)
-{
- g_atexit (print_leaks_at_exit);
-
- nautilus_leak_initialize_if_needed ();
-
- nautilus_leak_checker_init (argv[0]);
-
- return real_start_main (main, argc, argv, init, fini, rtld_fini, stack_end);
-}
-
-/* We try to keep a lot of code in between __libc_free and malloc to make
- * the reentry detection that depends on call address proximity work.
- */
-
-typedef struct {
- int count;
- unsigned long size;
-} LeakTotals;
-
-typedef struct {
- int max_count;
- int counter;
- int stack_print_depth;
- int stack_match_depth;
-} PrintOneLeakParams;
-
-/* we don't care if printf, etc. allocates (as long as it doesn't leak)
- * because by now we have a snapshot of the leaks at the time of
- * calling nautilus_leak_print_leaks
- */
-
-static gboolean
-total_one_leak (NautilusLeakTableEntry *entry, gpointer callback_data)
-{
- LeakTotals *totals;
-
- totals = (LeakTotals *) callback_data;
-
- totals->count += entry->count;
- totals->size += entry->total_size;
- return TRUE;
-}
-
-static GHashTable *
-create_bad_names_hash_table (void)
-{
- GHashTable *table;
- int i;
-
- table = g_hash_table_new (g_str_hash,
- g_str_equal);
- for (i = 0; i < (sizeof (known_leakers) / sizeof (known_leakers[0])); i++) {
- g_hash_table_insert (table,
- (char *) known_leakers[i],
- (char *) known_leakers[i]);
- }
- return table;
-}
-
-static gboolean
-is_stack_crawl_good (const NautilusLeakAllocationRecord *record, gpointer callback_data)
-{
- int i;
- char *name;
- GHashTable *bad_names;
-
- bad_names = (GHashTable *) callback_data;
- for (i = 0; record->stack_crawl[i] != NULL; i++) {
- name = nautilus_leak_get_function_name (app_path, record->stack_crawl[i]);
- if (g_hash_table_lookup (bad_names, name) != NULL) {
- g_free (name);
- return FALSE;
- }
- g_free (name);
- }
- return TRUE;
-}
-
-static gboolean
-print_one_leak (NautilusLeakTableEntry *entry, void *context)
-{
- int index;
- PrintOneLeakParams *params = (PrintOneLeakParams *)context;
-
- printf("----------------- total_size %ld count %d -------------------\n",
- (long)entry->total_size, entry->count);
-
- for (index = 0; index < params->stack_print_depth; index++) {
- /* only print stack_grouping worth of stack crawl -
- * beyond that different blocks may have different addresses
- * and we would be printing a lie
- */
- if (entry->sample_allocation->stack_crawl[index] == NULL)
- break;
- printf(" %c ", (entry->count > 1 && index >= params->stack_match_depth) ? '?' : ' ');
-
- nautilus_leak_print_symbol_address (app_path,
- entry->sample_allocation->stack_crawl[index]);
- }
-
- /* only print max_counter groups */
- return params->counter++ < params->max_count;
-}
-
-void
-nautilus_leak_print_leaks (int stack_grouping_depth, int stack_print_depth,
- int max_count, gboolean sort_by_count)
-{
- NautilusLeakHashTable *hash_table;
- NautilusLeakTable *leak_table;
- GHashTable *bad_names;
- LeakTotals leak_totals;
- PrintOneLeakParams each_context;
-
- pthread_mutex_lock (&nautilus_leak_hash_table_mutex);
- /* must have hash table by now */
- g_assert (nautilus_leak_hash_table != NULL);
- hash_table = nautilus_leak_hash_table;
- nautilus_leak_hash_table = NULL;
- nautilus_leak_check_leaks = FALSE;
- pthread_mutex_unlock (&nautilus_leak_hash_table_mutex);
-
- /* Filter out stack crawls that we want to ignore. */
- bad_names = create_bad_names_hash_table ();
- nautilus_leak_hash_table_filter (hash_table,
- is_stack_crawl_good,
- bad_names);
- g_hash_table_destroy (bad_names);
-
- /* Build a leak table by grouping blocks with the same
- * stack crawls (<stack_grouping_depth> levels considered)
- * from the allocated block hash table.
- */
- leak_table = nautilus_leak_table_new (hash_table, stack_grouping_depth);
- nautilus_leak_hash_table_free (hash_table);
-
- /* sort the leak table */
- if (sort_by_count) {
- nautilus_leak_table_sort_by_count (leak_table);
- } else {
- nautilus_leak_table_sort_by_size (leak_table);
- }
-
- /* we have a sorted table of all the leakers, we can print it out. */
-
- leak_totals.count = 0;
- leak_totals.size = 0;
- nautilus_leak_table_each_item (leak_table, total_one_leak, &leak_totals);
-
- printf ("The leak checker found %d outstanding allocations for %lu bytes total at exit time.\n",
- leak_totals.count, leak_totals.size);
- printf ("Here is a report with stack trace match depth %d:\n", stack_grouping_depth);
-
- each_context.counter = 0;
- each_context.max_count = max_count;
- each_context.stack_print_depth = stack_print_depth;
- each_context.stack_match_depth = stack_grouping_depth;
- nautilus_leak_table_each_item (leak_table, print_one_leak, &each_context);
-
- /* we are done with it, free the leak table */
- nautilus_leak_table_free (leak_table);
-
- /* we are done with it, clean up cached up data used by the symbol lookup */
- nautilus_leak_print_symbol_cleanup ();
-}
-
-void
-nautilus_leak_checker_init (const char *path)
-{
- /* we should get rid of this and find another way to find our
- * binary's name
- */
- printf ("Setting up the leak checker for %s\n", path);
- app_path = path;
-}
-
-void *
-malloc (size_t size)
-{
- return __libc_malloc (size);
-}
-
-void *
-realloc (void *ptr, size_t size)
-{
- return __libc_realloc (ptr, size);
-}
-
-void *
-memalign (size_t boundary, size_t size)
-{
- return __libc_memalign (boundary, size);
-}
-
-void *
-calloc (size_t nmemb, size_t size)
-{
- return __libc_calloc (nmemb, size);
-}
-
-void
-free (void *ptr)
-{
- __libc_free (ptr);
-}
-
-/* Version that frees right away instead of keeping a pool. */
-GList *
-g_list_alloc (void)
-{
- return g_new0 (GList, 1);
-}
-
-/* Version that frees right away instead of keeping a pool. */
-void
-g_list_free (GList *list)
-{
- GList *node, *next;
-
- node = list;
- while (node != NULL) {
- next = node->next;
- g_free (node);
- node = next;
- }
-}
-
-/* Version that uses normal allocation, not mem. chunks. */
-void
-g_list_free_1 (GList *list)
-{
- g_free (list);
-}
-
-/* Version that frees right away instead of keeping a pool. */
-GSList *
-g_slist_alloc (void)
-{
- return g_new0 (GSList, 1);
-}
-
-/* Version that frees right away instead of keeping a pool. */
-void
-g_slist_free (GSList *list)
-{
- GSList *node, *next;
-
- node = list;
- while (node != NULL) {
- next = node->next;
- g_free (node);
- node = next;
- }
-}
-
-/* Version that uses normal allocation, not mem. chunks. */
-void
-g_slist_free_1 (GSList *list)
-{
- g_free (list);
-}
-
-/* Version that frees right away instead of keeping a pool. */
-GNode *
-g_node_new (gpointer data)
-{
- GNode *node;
-
- node = g_new0 (GNode, 1);
- node->data = data;
- return node;
-}
-
-/* Version that frees right away instead of keeping a pool. */
-static void
-g_nodes_free (GNode *root)
-{
- GNode *node, *next;
-
- node = root;
- while (node != NULL) {
- next = node->next;
- g_nodes_free (node->children);
- g_free (node);
- node = next;
- }
-}
-
-/* Version that frees right away instead of keeping a pool. */
-void
-g_node_destroy (GNode *root)
-{
- g_return_if_fail (root != NULL);
-
- if (!G_NODE_IS_ROOT (root)) {
- g_node_unlink (root);
- }
-
- g_nodes_free (root);
-}
-
-/* Header on each chunk-allocated block. */
-typedef struct BlockHeader BlockHeader;
-struct BlockHeader {
- BlockHeader *next;
- BlockHeader *prev;
-};
-
-/* Our version of GMemChunk. */
-struct _GMemChunk {
- gint atom_size;
- BlockHeader head;
-};
-
-/* Version that uses malloc and doesn't bother with chunking. */
-GMemChunk *
-g_mem_chunk_new (gchar *name,
- gint atom_size,
- gulong area_size,
- gint type)
-{
- GMemChunk *mem_chunk;
-
- mem_chunk = g_new0 (GMemChunk, 1);
- mem_chunk->atom_size = atom_size;
- mem_chunk->head.next = &mem_chunk->head;
- mem_chunk->head.prev = &mem_chunk->head;
- return mem_chunk;
-}
-
-/* Version that uses malloc and doesn't bother with chunking. */
-void
-g_mem_chunk_destroy (GMemChunk *mem_chunk)
-{
- g_mem_chunk_reset (mem_chunk);
- g_free (mem_chunk);
-}
-
-/* Version that uses malloc and doesn't bother with chunking. */
-gpointer
-g_mem_chunk_alloc (GMemChunk *mem_chunk)
-{
- BlockHeader *header, *next;
-
- header = g_malloc (sizeof (BlockHeader) + mem_chunk->atom_size);
- next = mem_chunk->head.next;
- header->next = next;
- header->prev = &mem_chunk->head;
- mem_chunk->head.next = header;
- next->prev = header;
- return header + 1;
-}
-
-/* Version that uses malloc and doesn't bother with chunking. */
-gpointer
-g_mem_chunk_alloc0 (GMemChunk *mem_chunk)
-{
- gpointer block;
-
- block = g_mem_chunk_alloc (mem_chunk);
- memset (block, 0, mem_chunk->atom_size);
- return block;
-}
-
-/* Version that uses malloc and doesn't bother with chunking. */
-void
-g_mem_chunk_free (GMemChunk *mem_chunk,
- gpointer mem)
-{
- BlockHeader *header;
-
- header = ((BlockHeader *) mem) - 1;
- header->next->prev = header->prev;
- header->prev->next = header->next;
- g_free (header);
-}
-
-/* Version that uses malloc and doesn't bother with chunking. */
-void
-g_mem_chunk_clean (GMemChunk *mem_chunk)
-{
-}
-
-/* Version that uses malloc and doesn't bother with chunking. */
-void
-g_mem_chunk_reset (GMemChunk *mem_chunk)
-{
- while (mem_chunk->head.next != &mem_chunk->head) {
- g_mem_chunk_free (mem_chunk, mem_chunk->head.next + 1);
- }
-}
-
-/* Version that uses malloc and doesn't bother with chunking. */
-void
-g_mem_chunk_print (GMemChunk *mem_chunk)
-{
-}
-
-#endif /* LEAK_CHECKER */
-
-#ifdef LEAK_CHECK_TESTING
-/* normally disabled */
-
-static void
-allocate_lots (int count)
-{
- GList *list;
- GList *p;
-
- list = NULL;
- for (; count > 0; count--) {
- list = g_list_prepend (list, g_malloc (rand() % 256));
- list = g_list_prepend (list, NULL);
- }
- for (p = list; p != NULL; p = p->next) {
- g_free (p->data);
- p->data = NULL;
- }
- g_list_free (list);
-}
-
-
-static void
-leak_mem2 (void)
-{
- int i;
- for (i = 0; i < 40; i++) {
- g_strdup("bla");
- }
- allocate_lots (1280);
-}
-
-static void
-leak_mem (void)
-{
- int i;
- for (i = 0; i < 1010; i++) {
- malloc(13);
- }
- leak_mem2();
- allocate_lots (200);
-}
-
-
-int
-main (int argc, char **argv)
-{
- void *non_leak;
- void *leak;
- int i;
-
- non_leak = g_malloc(100);
- leak = g_malloc(200);
- g_assert(non_leak != NULL);
- non_leak = g_realloc(non_leak, 1000);
- g_assert(non_leak != NULL);
- non_leak = g_realloc(non_leak, 10000);
- leak = g_malloc(200);
- non_leak = g_realloc(non_leak, 100000);
- leak = g_malloc(200);
- g_assert(non_leak != NULL);
- g_free(non_leak);
-
- non_leak = calloc(1, 100);
- g_assert(non_leak != NULL);
- g_free(non_leak);
- leak = g_malloc(200);
-
- non_leak = memalign(16, 100);
- g_assert(non_leak != NULL);
- g_free(non_leak);
- leak = g_malloc(200);
- leak = memalign(16, 100);
- leak = memalign(16, 100);
- leak = memalign(16, 100);
- leak = memalign(16, 100);
- leak = memalign(16, 100);
- leak = memalign(16, 100);
-
- for (i = 0; i < 13; i++) {
- leak = malloc(13);
- }
-
- leak_mem();
- leak_mem2();
-
- allocate_lots (1);
- for (i = 0; i < 100; i++) {
- allocate_lots(rand() % 40);
- }
- printf("done\n");
- nautilus_leak_print_leaks (6, 12, 100, TRUE);
-
- return 0;
-}
-
-
-#endif
diff --git a/tools/leak-checker/nautilus-leak-checker.h b/tools/leak-checker/nautilus-leak-checker.h
deleted file mode 100644
index b58a633dd..000000000
--- a/tools/leak-checker/nautilus-leak-checker.h
+++ /dev/null
@@ -1,54 +0,0 @@
-/* nautilus-leak-checker.h - simple leak checking library
- Virtual File System Library
-
- Copyright (C) 2000 Eazel
-
- The Gnome Library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public License as
- published by the Free Software Foundation; either version 2 of the
- License, or (at your option) any later version.
-
- The Gnome Library 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
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with the Gnome Library; see the file COPYING.LIB. If not,
- write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- Boston, MA 02111-1307, USA.
-
- Author: Pavel Cisler <pavel@eazel.com>
- based on MemProf by Owen Taylor, <otaylor@redhat.com>
-*/
-
-#ifndef LEAK_CHECKER_H
-#define LEAK_CHECKER_H
-
-#define LEAK_CHECKER 1
-
-#if LEAK_CHECKER
-
-#define __USE_GNU
-#define _GNU_SOURCE
-/* need this for dlsym */
-#include <pthread.h>
-#include <glib.h>
-
-/* This is a leakchecker simpler than MemProf - it tracks all the outstanding
- * allocations and allows you print a total when your app quits. It doesn't actually
- * try to identify leaks like MemProf does. The entire leakchecker machinery runs
- * in the same process as the target app and shares the same heap for it's data
- * structures.
- */
-
-extern void nautilus_leak_checker_init (const char *app_path);
-
-extern void nautilus_leak_print_leaks (int stack_grouping_depth,
- int stack_print_depth,
- int max_count,
- gboolean sort_by_count);
-
-#endif
-
-#endif
diff --git a/tools/leak-checker/nautilus-leak-hash-table.c b/tools/leak-checker/nautilus-leak-hash-table.c
deleted file mode 100644
index c2cba26dd..000000000
--- a/tools/leak-checker/nautilus-leak-hash-table.c
+++ /dev/null
@@ -1,533 +0,0 @@
-/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
-
-/* nautilus-leak-hash-table.c - hash table for a leak checking library
- Virtual File System Library
-
- Copyright (C) 2000 Eazel
-
- The Gnome Library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public License as
- published by the Free Software Foundation; either version 2 of the
- License, or (at your option) any later version.
-
- The Gnome Library 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
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with the Gnome Library; see the file COPYING.LIB. If not,
- write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- Boston, MA 02111-1307, USA.
-
- Author: Pavel Cisler <pavel@eazel.com>
-*/
-
-#include "nautilus-leak-checker.h"
-/* included first, defines following switch*/
-#if LEAK_CHECKER
-
-#include <glib.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "nautilus-leak-checker-stubs.h"
-#include "nautilus-leak-hash-table.h"
-
-/* We have our own hash table here mainly to allow avoiding calls to
- * malloc and realloc that would cause reentry
- */
-
-static void
-nautilus_leak_hash_element_finalize (NautilusHashEntry *element)
-{
- nautilus_leak_allocation_record_finalize (&element->data);
- memset (element, 0, sizeof(NautilusHashEntry));
-}
-
-static unsigned long
-nautilus_leak_hash_element_hash (NautilusHashEntry *element)
-{
- return (unsigned long)element->data.block;
-}
-
-static gboolean
-nautilus_leak_hash_element_match (NautilusHashEntry *element, unsigned long key)
-{
- return (unsigned long)element->data.block == key;
-}
-
-/* NautilusHashEntries are allocated inside a NautilusHashEntryVector.
- * NautilusHashEntryVector keeps a linked list of deleted entries.
- */
-typedef struct {
- NautilusHashEntry *data;
- size_t size;
- int next_free;
- int next_deleted;
-} NautilusHashEntryVector;
-
-static void
-nautilus_leak_hash_element_vector_inititalize (NautilusHashEntryVector *vector, size_t initial_size)
-{
- int index;
-
- vector->data = (NautilusHashEntry *)real_malloc(initial_size * sizeof(NautilusHashEntry));
- if (vector->data == NULL) {
- g_warning ("leak checker out of memory");
- abort();
- }
- memset (vector->data, 0, initial_size * sizeof(NautilusHashEntry));
- for (index = initial_size - 1; index >= 0; index --) {
- vector->data[index].next = -1;
- }
-
- vector->size = initial_size;
- vector->next_free = 0;
- vector->next_deleted = -1;
-}
-
-static void
-nautilus_leak_hash_element_vector_finalize (NautilusHashEntryVector *vector)
-{
- int index;
- for (index = 0; index < vector->size; index++) {
- nautilus_leak_hash_element_finalize (&vector->data[index]);
- }
- real_free (vector->data);
-}
-
-static NautilusHashEntry *
-nautilus_leak_hash_element_vector_at (NautilusHashEntryVector *vector, int index)
-{
- return &vector->data[index];
-}
-
-enum {
- HASH_ELEMENT_VECTOR_GROW_CHUNK = 1024
-};
-
-static int
-nautilus_leak_hash_element_vector_add (NautilusHashEntryVector *vector)
-{
- int index;
- NautilusHashEntry *new_element;
- size_t new_size;
- NautilusHashEntry *new_data;
-
- if (vector->next_deleted >= 0) {
- /* Reuse a previously deleted item. */
- index = vector->next_deleted;
- vector->next_deleted = nautilus_leak_hash_element_vector_at (vector, index)->next;
- } else if (vector->next_free >= vector->size - 1) {
- /* We need grow the vector because it cannot fit more entries. */
- new_size = vector->size + HASH_ELEMENT_VECTOR_GROW_CHUNK;
- new_data = (NautilusHashEntry *)real_malloc(new_size * sizeof(NautilusHashEntry));
- if (new_data == NULL) {
- g_warning ("leak checker out of memory");
- abort();
- }
- /* FIXME bugzilla.eazel.com 2469: only clean the unused part */
- memset (new_data, 0, new_size * sizeof(NautilusHashEntry));
-
- /* copy all the existing items over*/
- memcpy (new_data, vector->data, vector->size * sizeof(NautilusHashEntry));
- /* delete the old array */
- real_free (vector->data);
- vector->data = new_data;
- vector->size = new_size;
- index = vector->next_free;
- ++vector->next_free;
- } else {
- /* Just take the next free item. */
- index = vector->next_free;
- ++vector->next_free;
- }
-
- /* Initialize the new element to an empty state. */
- new_element = nautilus_leak_hash_element_vector_at (vector, index);
- memset (new_element, 0, sizeof(NautilusHashEntry));
- new_element->next = -1;
-
- return index;
-}
-
-static void
-nautilus_leak_hash_element_vector_remove (NautilusHashEntryVector *vector, int index)
-{
- /* free the data */
- nautilus_leak_hash_element_finalize (&vector->data[index]);
-
- /* insert item as first into deleted item list */
- nautilus_leak_hash_element_vector_at (vector, index)->next = vector->next_deleted;
- vector->next_deleted = index;
-}
-
-struct NautilusLeakHashTable {
- size_t array_size;
- int *hash_array;
- NautilusHashEntryVector element_vector;
-};
-
-/* These primes are close to 2^n numbers for optimal hashing performance
- * and near-2^n size.
- */
-long nautilus_leak_hash_table_primes [] = {
- 509, 1021, 2039, 4093, 8191, 16381, 32749, 65521, 131071, 262139,
- 524287, 1048573, 2097143, 4194301, 8388593, 16777213, 33554393, 67108859,
- 134217689, 268435399, 536870909, 1073741789, 2147483647, 0
-};
-
-
-static size_t
-nautilus_leak_hash_table_optimal_size (size_t size)
-{
- int index;
- for (index = 0; ; index++) {
- if (!nautilus_leak_hash_table_primes [index] || nautilus_leak_hash_table_primes [index] >= size) {
- return nautilus_leak_hash_table_primes [index];
- }
- }
-
- return 0;
-}
-
-static void
-nautilus_leak_hash_table_initialize (NautilusLeakHashTable *table, size_t initial_size)
-{
- /* calculate the size of the bucket array */
- table->array_size = nautilus_leak_hash_table_optimal_size (initial_size);
-
- /* allocate the element array */
- nautilus_leak_hash_element_vector_inititalize (&table->element_vector, table->array_size * 5);
-
- /* allocate the bucket array */
- table->hash_array = (int *)real_malloc (table->array_size * sizeof(int));
-
- /* initialize the to empty state */
- memset (table->hash_array, -1, table->array_size * sizeof(int));
-}
-
-static void
-nautilus_leak_hash_table_finalize (NautilusLeakHashTable *table)
-{
- nautilus_leak_hash_element_vector_finalize (&table->element_vector);
- real_free (table->hash_array);
-}
-
-NautilusLeakHashTable *
-nautilus_leak_hash_table_new (size_t initial_size)
-{
- NautilusLeakHashTable *new_table;
- new_table = real_malloc (sizeof(NautilusLeakHashTable));
- nautilus_leak_hash_table_initialize (new_table, initial_size);
-
- return new_table;
-}
-
-void
-nautilus_leak_hash_table_free (NautilusLeakHashTable *hash_table)
-{
- nautilus_leak_hash_table_finalize (hash_table);
- real_free (hash_table);
-}
-
-static unsigned long
-nautilus_leak_hash_table_hash (NautilusLeakHashTable *table, unsigned long seed)
-{
- return (seed >> 2) % table->array_size;
-}
-
-NautilusHashEntry *
-nautilus_leak_hash_table_find (NautilusLeakHashTable *table, unsigned long key)
-{
- int index;
- NautilusHashEntry *result;
-
- for (index = table->hash_array [nautilus_leak_hash_table_hash (table, key)]; index >= 0;) {
- result = nautilus_leak_hash_element_vector_at (&table->element_vector, index);
- if (nautilus_leak_hash_element_match (result, key)) {
- return result;
- }
- index = result->next;
- }
-
- return NULL;
-}
-
-NautilusHashEntry *
-nautilus_leak_hash_table_add (NautilusLeakHashTable *table, unsigned long key)
-{
- int new_index;
- NautilusHashEntry *result;
- unsigned long hash;
-
- /* calculate the index of the bucket */
- hash = nautilus_leak_hash_table_hash (table, key);
-
- /* allocate space for new item in element vector */
- new_index = nautilus_leak_hash_element_vector_add (&table->element_vector);
- result = nautilus_leak_hash_element_vector_at (&table->element_vector, new_index);
-
- /* insert new item first in the list for bucket <hash> */
- result->next = table->hash_array[hash];
- table->hash_array[hash] = new_index;
-
- return result;
-}
-
-static void
-nautilus_leak_hash_table_remove_element (NautilusLeakHashTable *table, NautilusHashEntry *element)
-{
- unsigned long hash;
- int next;
- int index;
- NautilusHashEntry *tmp_element;
-
- /* find the bucket */
- hash = nautilus_leak_hash_table_hash (table, nautilus_leak_hash_element_hash (element));
- next = table->hash_array[hash];
-
- g_assert (next >= 0);
-
- /* try to match bucket list head */
- if (nautilus_leak_hash_element_vector_at (&table->element_vector, next) == element) {
- table->hash_array[hash] = element->next;
- nautilus_leak_hash_element_vector_remove (&table->element_vector, next);
- return;
- }
-
- for (index = next; index >= 0; ) {
- /* look for an existing match in table */
- next = nautilus_leak_hash_element_vector_at (&table->element_vector, index)->next;
- if (next < 0) {
- g_assert (!"should not be here");
- return;
- }
-
- tmp_element = nautilus_leak_hash_element_vector_at (&table->element_vector, index);
- if (nautilus_leak_hash_element_vector_at (&table->element_vector, next) == element) {
- nautilus_leak_hash_element_vector_at (&table->element_vector, index)->next = element->next;
- nautilus_leak_hash_element_vector_remove (&table->element_vector, next);
- return;
- }
- index = next;
- }
-}
-
-gboolean
-nautilus_leak_hash_table_remove (NautilusLeakHashTable *table, unsigned long key)
-{
- NautilusHashEntry *element;
-
- element = nautilus_leak_hash_table_find (table, key);
- if (element != NULL) {
- /* FIXME bugzilla.eazel.com 2470:
- * this could be faster if we just found the element
- * here and deleted it.
- */
- nautilus_leak_hash_table_remove_element (table, element);
-
- return TRUE;
- }
- return FALSE;
-}
-
-void
-nautilus_leak_hash_table_filter (NautilusLeakHashTable *table,
- NautilusLeakHashTableFilterFunction function,
- gpointer callback_data)
-{
- NautilusHashEntry *entry;
- int i;
-
- for (i = 0; i < table->element_vector.size; i++) {
- /* traverse the hash table element vector */
- entry = nautilus_leak_hash_element_vector_at (&table->element_vector, i);
- if (entry->data.stack_crawl != NULL) {
- if (!(* function) (&entry->data, callback_data)) {
- entry->data.stack_crawl = NULL;
- }
- }
- }
-}
-
-struct NautilusLeakTable {
- size_t size;
- NautilusLeakTableEntry *data;
-};
-
-static NautilusLeakTableEntry *
-nautilus_leak_table_new_entry_at (NautilusLeakTable *table, int index)
-{
- /* Allocate a new slot. Avoid using real_realloc here because
- * it ends up calling our version of __libc_malloc and messes up
- * the leak table
- */
- NautilusLeakTableEntry *new_table = (NautilusLeakTableEntry *) real_malloc
- ((table->size + 1) * sizeof (NautilusLeakTableEntry));
-
- if (new_table == NULL) {
- g_warning ("Ran out of memory while allocating leak checker structures");
- abort ();
- }
-
- /* finish what realloc would have done if we could call it */
- memcpy (new_table, table->data, (table->size) * sizeof (NautilusLeakTableEntry));
- real_free (table->data);
- table->data = new_table;
-
- /* move the items over by one to make room for new item */
- if (index < table->size) {
- memmove (&table->data[index + 1],
- &table->data[index],
- (table->size - index) * sizeof (NautilusLeakTableEntry));
- }
-
- table->size++;
-
- return &table->data[index];
-}
-
-static void
-nautilus_leak_table_add_entry (NautilusLeakTable *table, NautilusHashEntry *entry, int stack_grouping_depth)
-{
- int r, l;
- int resulting_index;
- int compare_result;
-
- /* do a binary lookup of the item */
- r = table->size - 1;
- resulting_index = 0;
- compare_result = 0;
-
- for (l = 0; l <= r; ) {
- resulting_index = (l + r) / 2;
-
- compare_result = nautilus_leak_stack_crawl_compare (
- table->data[resulting_index].sample_allocation->stack_crawl,
- entry->data.stack_crawl,
- stack_grouping_depth);
-
- if (compare_result > 0) {
- r = resulting_index - 1;
- } else if (compare_result < 0) {
- l = resulting_index + 1;
- } else {
- break;
- }
- }
-
- if (compare_result < 0) {
- resulting_index++;
- }
-
- if (compare_result == 0 && resulting_index < table->size) {
- /* we already have a match, just bump up the count and size */
- table->data[resulting_index].count++;
- table->data[resulting_index].total_size += entry->data.size;
- return;
- }
-
- nautilus_leak_table_new_entry_at (table, resulting_index);
- table->data[resulting_index].count = 1;
- table->data[resulting_index].total_size = entry->data.size;
- table->data[resulting_index].sample_allocation = nautilus_leak_allocation_record_copy (&entry->data);
-}
-
-NautilusLeakTable *
-nautilus_leak_table_new (NautilusLeakHashTable *hash_table, int stack_grouping_depth)
-{
- NautilusLeakTable *result;
- NautilusHashEntry *nautilus_leak_hash_table_entry;
- int index;
-
- result = real_malloc (sizeof(NautilusLeakTable));
- result->size = 0;
- result->data = NULL;
-
- for (index = 0; index < hash_table->element_vector.size; index++) {
- /* traverse the hash table element vector */
- nautilus_leak_hash_table_entry = nautilus_leak_hash_element_vector_at (&hash_table->element_vector, index);
- if (nautilus_leak_hash_table_entry->data.stack_crawl != NULL) {
- nautilus_leak_table_add_entry (result, nautilus_leak_hash_table_entry, stack_grouping_depth);
- }
- }
-
- return result;
-}
-
-void
-nautilus_leak_table_free (NautilusLeakTable *leak_table)
-{
- int index;
- if (leak_table != NULL) {
- for (index = 0; index < leak_table->size; index++) {
- nautilus_leak_allocation_record_free(leak_table->data[index].sample_allocation);
- }
- real_free (leak_table->data);
- }
-
- real_free (leak_table);
-}
-
-static int
-sort_by_count (const void *entry1, const void *entry2)
-{
- int result;
-
- result = ((NautilusLeakTableEntry *)entry2)->count
- - ((NautilusLeakTableEntry *)entry1)->count;
-
- if (result == 0) {
- /* match, secondary sort order by size */
- return ((NautilusLeakTableEntry *)entry2)->total_size
- - ((NautilusLeakTableEntry *)entry1)->total_size;
- }
- return result;
-}
-
-void
-nautilus_leak_table_sort_by_count (NautilusLeakTable *leak_table)
-{
- qsort (leak_table->data, leak_table->size,
- sizeof(NautilusLeakTableEntry), sort_by_count);
-}
-
-static int
-sort_by_size (const void *entry1, const void *entry2)
-{
- int result;
-
- result = ((NautilusLeakTableEntry *)entry2)->total_size
- - ((NautilusLeakTableEntry *)entry1)->total_size;
-
- if (result == 0) {
- /* match, secondary sort order by count */
- return ((NautilusLeakTableEntry *)entry2)->count
- - ((NautilusLeakTableEntry *)entry1)->count;
- }
- return result;
-}
-
-void
-nautilus_leak_table_sort_by_size (NautilusLeakTable *leak_table)
-{
- qsort (leak_table->data, leak_table->size,
- sizeof (NautilusLeakTableEntry), sort_by_size);
-}
-
-void
-nautilus_leak_table_each_item (NautilusLeakTable *leak_table, NautilusEachLeakTableFunction function,
- void *context)
-{
- int index;
- for (index = 0; index < leak_table->size; index++) {
- if (!function (&leak_table->data[index], context)) {
- /* break early */
- return;
- }
- }
-}
-
-#endif
diff --git a/tools/leak-checker/nautilus-leak-hash-table.h b/tools/leak-checker/nautilus-leak-hash-table.h
deleted file mode 100644
index 2de2aeb58..000000000
--- a/tools/leak-checker/nautilus-leak-hash-table.h
+++ /dev/null
@@ -1,63 +0,0 @@
-/* nautilus-leak-hash-table.h - hash table for a leak checking library
- Virtual File System Library
-
- Copyright (C) 2000 Eazel
-
- The Gnome Library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public License as
- published by the Free Software Foundation; either version 2 of the
- License, or (at your option) any later version.
-
- The Gnome Library 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
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with the Gnome Library; see the file COPYING.LIB. If not,
- write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- Boston, MA 02111-1307, USA.
-
- Author: Pavel Cisler <pavel@eazel.com>
-*/
-
-#ifndef NAUTILUS_LEAK_HASH_TABLE_H
-#define NAUTILUS_LEAK_HASH_TABLE_H
-
-typedef struct NautilusLeakHashTable NautilusLeakHashTable;
-typedef struct NautilusHashEntry NautilusHashEntry;
-
-typedef gboolean (* NautilusLeakHashTableFilterFunction) (const NautilusLeakAllocationRecord *record, gpointer callback_data);
-
-NautilusLeakHashTable *nautilus_leak_hash_table_new (size_t initial_size);
-void nautilus_leak_hash_table_free (NautilusLeakHashTable *hash_table);
-gboolean nautilus_leak_hash_table_remove (NautilusLeakHashTable *table,
- unsigned long key);
-NautilusHashEntry * nautilus_leak_hash_table_add (NautilusLeakHashTable *table,
- unsigned long key);
-NautilusHashEntry * nautilus_leak_hash_table_find (NautilusLeakHashTable *table,
- unsigned long key);
-void nautilus_leak_hash_table_filter (NautilusLeakHashTable *table,
- NautilusLeakHashTableFilterFunction function,
- gpointer callback_data);
-
-
-typedef struct {
- int count;
- size_t total_size;
- NautilusLeakAllocationRecord *sample_allocation;
-} NautilusLeakTableEntry;
-
-typedef struct NautilusLeakTable NautilusLeakTable;
-typedef gboolean (* NautilusEachLeakTableFunction) (NautilusLeakTableEntry *entry, void *context);
-
-NautilusLeakTable *nautilus_leak_table_new (NautilusLeakHashTable *hash_table,
- int stack_grouping_depth);
-void nautilus_leak_table_free (NautilusLeakTable *leak_table);
-void nautilus_leak_table_sort_by_count (NautilusLeakTable *leak_table);
-void nautilus_leak_table_sort_by_size (NautilusLeakTable *leak_table);
-void nautilus_leak_table_each_item (NautilusLeakTable *leak_table,
- NautilusEachLeakTableFunction function,
- void *context);
-
-#endif /* NAUTILUS_LEAK_HASH_TABLE_H */
diff --git a/tools/leak-checker/nautilus-leak-symbol-lookup.c b/tools/leak-checker/nautilus-leak-symbol-lookup.c
deleted file mode 100644
index 5f73f91bc..000000000
--- a/tools/leak-checker/nautilus-leak-symbol-lookup.c
+++ /dev/null
@@ -1,294 +0,0 @@
-/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
-
-/* nautilus-leak-symbol-lookup.c - symbol lookup for a leak checking library
- Virtual File System Library
-
- Copyright (C) 2000 Eazel
-
- The Gnome Library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public License as
- published by the Free Software Foundation; either version 2 of the
- License, or (at your option) any later version.
-
- The Gnome Library 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
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with the Gnome Library; see the file COPYING.LIB. If not,
- write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- Boston, MA 02111-1307, USA.
-
- Author: Pavel Cisler <pavel@eazel.com>
- based on MemProf by Owen Taylor, <otaylor@redhat.com>
-*/
-
-#define _GNU_SOURCE
- /* need this for dladdr */
-
-#include "nautilus-leak-symbol-lookup.h"
-
-#include <bfd.h>
-#include <dlfcn.h>
-#include <glib.h>
-#include <stdio.h>
-#include <malloc.h>
-#include <unistd.h>
-#include <sys/stat.h>
-
-
-static GList *symbol_table_list;
-
-typedef struct {
- char *path;
- bfd *abfd;
- asymbol **symbol_table;
- asection *text_section;
- unsigned long start;
- unsigned long end;
-} NautilusLeakSymbolLookupMap;
-
-static gboolean
-nautilus_leak_find_symbol_in_map (const NautilusLeakSymbolLookupMap *map,
- unsigned long address, char **function_name, char **source_file_name,
- unsigned int *line)
-{
- const char *file;
- const char *function;
-
- address -= map->start;
- address -= map->text_section->vma;
-
- if (address < 0 || address > map->text_section->_cooked_size) {
- /* not a valid address range for this binary */
- return FALSE;
- }
-
- if (!bfd_find_nearest_line (map->abfd, map->text_section, map->symbol_table,
- address,
- &file, &function, line)) {
- printf ("error looking up address in binary %s\n", map->path);
- return FALSE;
- }
- if (file == NULL || function == NULL) {
- return FALSE;
- }
-
- *function_name = g_strdup (function);
- *source_file_name = g_strdup (file);
-
- return TRUE;
-}
-
-static void
-nautilus_leak_symbol_map_get_offsets (NautilusLeakSymbolLookupMap *map)
-{
- gchar buffer[1024];
- FILE *in;
- gchar perms[26];
- gchar file[256];
- unsigned long start, end;
- guint major, minor;
- ino_t inode;
- struct stat library_stat;
- struct stat entry_stat;
- int count;
-
- /* find the library we are looking for in the proc directories
- * to find out at which addresses it is mapped
- */
- snprintf (buffer, 1023, "/proc/%d/maps", getpid());
- in = fopen (buffer, "r");
-
- if (stat (map->path, &library_stat) != 0) {
- /* we will use st_ino and st_dev to do a file match */
- return;
- }
-
- while (fgets(buffer, 1023, in)) {
- gulong tmp;
-
- count = sscanf (buffer, "%lx-%lx %15s %*x %u:%u %lu %255s",
- &start, &end, perms, &major, &minor, &tmp, file);
- inode = tmp;
-
- if (count >= 6 && strcmp (perms, "r-xp") == 0) {
- if (stat (file, &entry_stat) != 0) {
- break;
- }
- /* check if this is the library we are loading */
- if (library_stat.st_ino == entry_stat.st_ino
- && library_stat.st_dev == entry_stat.st_dev) {
- map->start = start;
- map->end = end;
-
- break;
- }
- }
- }
- fclose (in);
-}
-
-static NautilusLeakSymbolLookupMap *
-nautilus_leak_symbol_map_load (const char *binary_path, gboolean executable)
-{
- NautilusLeakSymbolLookupMap *map;
- char *target = NULL;
- size_t storage_needed;
- int number_of_symbols;
-
- map = g_new0 (NautilusLeakSymbolLookupMap, 1);
-
- map->abfd = bfd_openr (binary_path, target);
-
- if (map->abfd == NULL) {
- fprintf (stderr, "%s: ", binary_path);
- bfd_perror (binary_path);
- return NULL;
- }
-
- if (!bfd_check_format (map->abfd, bfd_object)) {
- fprintf (stderr, "%s is not an object file\n", binary_path);
- bfd_close (map->abfd);
- return NULL;
- }
-
- /* Use the ".text" section. */
- map->text_section = bfd_get_section_by_name (map->abfd, ".text");
-
- /* Read the symbol table. */
- storage_needed = bfd_get_symtab_upper_bound (map->abfd);
- if (storage_needed == 0) {
- fprintf (stderr, "no symbols\n");
- bfd_close (map->abfd);
- return NULL;
- }
- map->symbol_table = (asymbol **)g_malloc (storage_needed);
- if (map->symbol_table == NULL) {
- fprintf (stderr, "no memory allocating symbol table\n");
- bfd_close (map->abfd);
- return NULL;
- }
- number_of_symbols = bfd_canonicalize_symtab (map->abfd, map->symbol_table);
- map->path = g_strdup (binary_path);
-
- if (!executable) {
- nautilus_leak_symbol_map_get_offsets (map);
- }
- symbol_table_list = g_list_append (symbol_table_list, map);
-
- return map;
-}
-
-static NautilusLeakSymbolLookupMap *
-nautilus_leak_symbol_map_load_if_needed (const char *binary_path, gboolean executable)
-{
- GList *p;
- NautilusLeakSymbolLookupMap *map;
-
- for (p = symbol_table_list; p != NULL; p = p->next) {
- map = p->data;
- if (strcmp (map->path, binary_path) == 0)
- /* no need to load the symbols, already got the map */
- return map;
- }
- return nautilus_leak_symbol_map_load (binary_path, executable);
-}
-
-void
-nautilus_leak_print_symbol_cleanup (void)
-{
- /* free the cached symbol tables */
- GList *p;
- NautilusLeakSymbolLookupMap *map;
-
- for (p = symbol_table_list; p != NULL; p = p->next) {
- map = p->data;
- bfd_close (map->abfd);
- g_free (map->symbol_table);
- g_free (map->path);
-
- g_free (map);
- }
-
- g_list_free (symbol_table_list);
- symbol_table_list = NULL;
-}
-
-static gboolean
-nautilus_leak_find_symbol_address (void *address, char **function_name, char **source_file_name,
- int *line)
-{
- GList *p;
- NautilusLeakSymbolLookupMap *map;
- Dl_info info;
-
- if (dladdr (address, &info) != 0) {
- /* We know the function name and the binary it lives in, now try to find
- * the function and the offset.
- */
- map = nautilus_leak_symbol_map_load_if_needed (info.dli_fname, false);
- if (map != NULL
- && nautilus_leak_find_symbol_in_map (map, (long)address,
- function_name, source_file_name, line)) {
- return TRUE;
- }
- /* just return the function name and the library binary path */
- *function_name = g_strdup (info.dli_sname);
- *source_file_name = g_strdup (info.dli_fname);
- *line = -1;
- return TRUE;
- } else {
- /* Usually dladdr will succeed, it seems to only fail for
- * address lookups for functions in the main binary.
- */
- for (p = symbol_table_list; p != NULL; p = p->next) {
- map = p->data;
- if (nautilus_leak_find_symbol_in_map (map, (long)address, function_name,
- source_file_name, (unsigned int *)line))
- return TRUE;
- }
- }
-
- return FALSE;
-}
-
-void
-nautilus_leak_print_symbol_address (const char *app_path, void *address)
-{
- char *function_name;
- char *source_file_name;
- int line;
-
- nautilus_leak_symbol_map_load_if_needed (app_path, true);
-
- if (nautilus_leak_find_symbol_address (address, &function_name, &source_file_name, &line)) {
- if (line >= 0) {
- printf("%10p %-30s %s:%d\n", address, function_name, source_file_name, line);
- } else {
- printf("%10p %-30s in library %s\n", address, function_name, source_file_name);
- }
- g_free (function_name);
- g_free (source_file_name);
- } else {
- printf("%p (unknown function)\n", address);
- }
-}
-
-char *
-nautilus_leak_get_function_name (const char *app_path, void *address)
-{
- char *function_name;
- char *source_file_name;
- int line;
-
- nautilus_leak_symbol_map_load_if_needed (app_path, true);
-
- if (nautilus_leak_find_symbol_address (address, &function_name, &source_file_name, &line)) {
- g_free (source_file_name);
- return function_name;
- } else {
- return NULL;
- }
-}
diff --git a/tools/leak-checker/nautilus-leak-symbol-lookup.h b/tools/leak-checker/nautilus-leak-symbol-lookup.h
deleted file mode 100644
index 05afe9941..000000000
--- a/tools/leak-checker/nautilus-leak-symbol-lookup.h
+++ /dev/null
@@ -1,34 +0,0 @@
-/* nautilus-leak-symbol-lookup.h - symbol lookup for a leak checking library
- Virtual File System Library
-
- Copyright (C) 2000 Eazel
-
- The Gnome Library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public License as
- published by the Free Software Foundation; either version 2 of the
- License, or (at your option) any later version.
-
- The Gnome Library 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
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with the Gnome Library; see the file COPYING.LIB. If not,
- write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- Boston, MA 02111-1307, USA.
-
- Author: Pavel Cisler <pavel@eazel.com>
- based on MemProf by Owen Taylor, <otaylor@redhat.com>
-*/
-
-#ifndef NAUTILUS_LEAK_SYMBOL_LOOKUP_H
-#define NAUTILUS_LEAK_SYMBOL_LOOKUP_H
-
-void nautilus_leak_print_symbol_address (const char *app_path,
- void *address);
-char *nautilus_leak_get_function_name (const char *app_path,
- void *address);
-void nautilus_leak_print_symbol_cleanup (void);
-
-#endif /* NAUTILUS_LEAK_SYMBOL_LOOKUP_H */
diff --git a/tools/profiler/Makefile b/tools/profiler/Makefile
deleted file mode 100644
index f5935a601..000000000
--- a/tools/profiler/Makefile
+++ /dev/null
@@ -1,14 +0,0 @@
-
-# temporary hardcoded makefile to get things going
-
-SOURCES := profile.C profiledata.C totaltime.C machine-profile.S funcsummary.C nautilus-leak-symbol-lookup.C
-HEADERS := profile.h profiledata.h totaltime.h symbol-table.h funcsummary.h nautilus-leak-symbol-lookup.h profileP.h machine-profileP.h machine-profile.h
-
-LIBS := -lpthread -lglib -ldl -Wl,-Bstatic -lbfd -liberty -Wl,-Bdynamic
-
-libprofiler.so: $(SOURCES) $(HEADERS)
- g++ -g -W -Wall -I/gnome/include -I/gnome/include/glib-1.2 -I/gnome/lib/glib/include -L/gnome/lib $(SOURCES) $(LIBS) -shared -o libprofiler.so
-
-test: test.cpp
- g++ -DTEST_LIB -g -O0 -finstrument-functions test.cpp -shared -o libtest.so
- g++ -g -O0 -finstrument-functions test.cpp -L. -ltest -lprofiler -lpthread -o test \ No newline at end of file
diff --git a/tools/profiler/funcsummary.C b/tools/profiler/funcsummary.C
deleted file mode 100644
index 778fffe08..000000000
--- a/tools/profiler/funcsummary.C
+++ /dev/null
@@ -1,154 +0,0 @@
-/*
- * Cprof profiler tool
- * (C) Copyright 1999-2000 Corel Corporation
- *
- * 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 2 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, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#include "funcsummary.h"
-
-#include <vector>
-#include <algorithm>
-#include <utility>
-#include <iomanip>
-#include <cstdio>
-
-using namespace std;
-
-inline bool
-FuncSummary::sort_func_percent(const FuncData &left, const FuncData &right)
-{
- return right.func_pct < left.func_pct;
-}
-
-inline bool
-FuncSummary::sort_func_calls(const FuncData &left, const FuncData &right)
-{
- return right.count < left.count;
-}
-
-inline bool
-FuncSummary::sort_func_children_percent(const FuncData &left, const FuncData &right)
-{
- return right.func_children_pct < left.func_children_pct;
-}
-
-FuncSummary::FuncSummary(const ProfileData &data, const SymbolTable &_syms,
- sort_order _order, profctr_t total_time)
- : syms(_syms), order(_order)
-{
- time_factor = data.frequency() / 1000;
-
- MyArcVisitor visitor(*this);
- data.VisitArcs(&visitor);
-
- for (function_map_t::iterator i = function_map.begin();
- i != function_map.end(); ++i) {
- i->second.func_pct = (double)i->second.func_time / total_time * 100;
- i->second.func_children_pct = (double)i->second.func_children_time / total_time * 100;
- }
-}
-
-FuncSummary::~FuncSummary()
-{
-}
-
-const char FuncSummary::header[] =
- "Function Name calls func% func(ms) f+c% f+c(ms)\n";
-//wait_reply 19078 51.731 4074 51.737 4074
-
-
-void
-FuncSummary::Output(ostream &os)
-{
- typedef std::vector<FuncData> function_list_t;
- function_list_t func_list;
-
- func_list.reserve(function_map.size());
-
- for (function_map_t::const_iterator i = function_map.begin();
- i != function_map.end(); ++i)
- func_list.push_back(i->second);
-
- switch (order) {
- case sort_func:
- sort(func_list.begin(), func_list.end(), sort_func_percent);
- break;
-
- case sort_child:
- sort(func_list.begin(), func_list.end(), sort_func_children_percent);
- break;
-
- case sort_calls:
- sort(func_list.begin(), func_list.end(), sort_func_calls);
- break;
- }
-
- os << header;
-
- for (function_list_t::const_iterator i = func_list.begin();
- i != func_list.end(); ++i) {
- char buf[256];
-
- if (i->func_pct == 0 || i->count == 0)
- continue;
-
- snprintf(buf, sizeof(buf)/sizeof(buf[0]),
- "%-47s %9ld %#7.3f %9lld %7.3f %9lld\n", i->name.c_str(),
- (long)i->count, i->func_pct, i->func_time / time_factor,
- i->func_children_pct, i->func_children_time / time_factor);
-
- os << buf;
- }
-}
-
-FuncSummary::FuncData &FuncSummary::get_func(codeptr_t func)
-{
- string name;
- syms.LookupExact(func, name);
-
- function_map_t::iterator i = function_map.find(name);
- if (i != function_map.end())
- return i->second;
-
- FuncData f;
- f.name = name;
- f.func_time = 0;
- f.func_children_time = 0;
- f.func_pct = 0;
- f.func_children_pct = 0;
- f.count = 0;
-
- return function_map.insert(make_pair(name, f)).first->second;
-}
-
-void FuncSummary::MyArcVisitor::visit(const ProfileData::ArcData &a)
-{
- FuncData &from = outer.get_func(a.fromfunc);
- FuncData &to = outer.get_func(a.tofunc);
-
- to.count += a.count;
-
- to.func_time += a.time;
- to.func_children_time += a.time;
-
- if (from.func_time > 0)
- from.func_time -= a.time;
-}
-
-
-FuncSummary::MyArcVisitor::~MyArcVisitor()
-{
-}
diff --git a/tools/profiler/funcsummary.h b/tools/profiler/funcsummary.h
deleted file mode 100644
index da6ccb4f2..000000000
--- a/tools/profiler/funcsummary.h
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- * Cprof profiler tool
- * (C) Copyright 1999-2000 Corel Corporation
- *
- * 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 2 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, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#ifndef FUNCSUMMARY_H_INCLUDED
-#define FUNCSUMMARY_H_INCLUDED
-
-#include <iostream>
-#include <string>
-#include <map>
-
-#include "profiledata.h"
-#include "symbol-table.h"
-
-class FuncSummary
-{
-public:
- enum sort_order {
- sort_func,
- sort_child,
- sort_calls
- };
-
- FuncSummary(const ProfileData &data, const SymbolTable &syms,
- sort_order order, profctr_t total_time);
- ~FuncSummary();
-
- void Output(std::ostream &os);
-
-private:
- struct FuncData {
- string name;
- profctr_t func_time, func_children_time;
- double func_pct, func_children_pct;
- size_t count;
- };
-
- typedef std::map<std::string, FuncData> function_map_t;
-
- const SymbolTable &syms;
- function_map_t function_map;
-
- FuncData &get_func(codeptr_t);
-
- struct MyArcVisitor;
- friend struct MyArcVisitor;
- struct MyArcVisitor : ProfileData::ArcVisitor {
- explicit MyArcVisitor(FuncSummary &_outer) : outer(_outer) { }
- virtual ~MyArcVisitor();
- virtual void visit(const ProfileData::ArcData &a);
-
- private:
- FuncSummary &outer;
- };
-
- profctr_t time_factor;
-
- static const char header[];
-
- sort_order order;
-
- static inline bool sort_func_percent(const FuncData &left,
- const FuncData &right);
- static inline bool sort_func_calls(const FuncData &left,
- const FuncData &right);
- static inline bool sort_func_children_percent(const FuncData &left,
- const FuncData &right);
-
- // unimplemented
- FuncSummary(const FuncSummary &);
- void operator = (const FuncSummary &);
-};
-
-#endif
diff --git a/tools/profiler/machine-profile.S b/tools/profiler/machine-profile.S
deleted file mode 100644
index 9f2b044cb..000000000
--- a/tools/profiler/machine-profile.S
+++ /dev/null
@@ -1,46 +0,0 @@
-/* Copyright (C) 2000 Corel Corporation */
- .globl __menter
- .globl __mexit
-
-.text
- .align 4
- .type __menter,@function
-__menter:
- pushl %eax
- pushl %ecx
- pushl %edx
-
- pushl 16(%esp)
-
- call __menter_internal
-
- popl %edx
- popl %ecx
- popl %eax
-
- ret
-1:
- .size __menter, 1b-__menter
-
- .align 4
- .type __mexit,@function
-__mexit:
- pushl %eax
- pushl %ecx
- pushl %edx
-
- call __mexit_internal
-
- popl %edx
- popl %ecx
- popl %eax
- ret
-1:
- .size __mexit, 1b-__mexit
-
-/* gcc-2.95.2 outputs calls to these functions */
- .globl __cyg_profile_func_enter
- .set __cyg_profile_func_enter, __menter
-
- .globl __cyg_profile_func_exit
- .set __cyg_profile_func_exit, __mexit
diff --git a/tools/profiler/machine-profile.h b/tools/profiler/machine-profile.h
deleted file mode 100644
index 6556c1cdf..000000000
--- a/tools/profiler/machine-profile.h
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Cprof profiler tool
- * (C) Copyright 1999-2000 Corel Corporation
- *
- * 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 2 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, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-/* Public, machine-dependent definitions */
-
-#ifndef MACHINE_PROFILE_H_INCLUDED
-#define MACHINE_PROFILE_H_INCLUDED
-
-#include <stdint.h>
-
-/* An integer large enough to hold a data or function pointer. */
-typedef uintptr_t codeptr_t;
-
-/* An arithmetic used to represent both absolute times
- * and (non-negative) deltas. */
-typedef unsigned long long profctr_t;
-
-#endif
diff --git a/tools/profiler/machine-profileP.h b/tools/profiler/machine-profileP.h
deleted file mode 100644
index d6ea397d8..000000000
--- a/tools/profiler/machine-profileP.h
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * Cprof profiler tool
- * (C) Copyright 1999-2000 Corel Corporation
- *
- * 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 2 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, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#ifndef MACHINE_PROFILE_PRIVATE_H_INCLUDED
-#define MACHINE_PROFILE_PRIVATE_H_INCLUDED
-
-#include "machine-profile.h"
-
-extern "C" {
- void __attribute((__stdcall__)) __menter_internal (codeptr_t func);
- void __attribute((__stdcall__)) __mexit_internal (void);
-}
-/* Note that we don't issue a serialising instruction (e.g. cpuid)
- * before reading the counter. Since we are profiling entire functions,
- * it doesn't matter.
- * Don't use this to determine how many cycles a single instruction takes.
- */
-#define get_timestamp(t) \
- do \
- { \
- __asm__ __volatile__("pushl %%ebx\n" \
- "cpuid\n" \
- "popl %%ebx\n" \
- "rdtsc" \
- : "=A" (t) : : "cx"); \
- } while (0)
-
-#define update_arc_time(arc_time, delta) \
- do { (arc_time) += (delta); } while (0)
-
-static inline size_t atomic_inc(volatile size_t *x)
-{
- size_t result;
- __asm__("lock; xaddl %1, %0"
- : "=m" (*x), "=rm" (result)
- : "1" (1));
-
- return result;
-}
-
-static inline int compare_and_swap(void **dest, void *old, void *_new)
-{
- char ret;
- unsigned long readval;
-
- __asm__("lock; cmpxchgl %3, %1; sete %0"
- : "=q" (ret), "=m" (*dest), "=a" (readval)
- : "r" (_new), "m" (*dest), "a" (old));
-
- return ret;
-}
-
-#endif
diff --git a/tools/profiler/nautilus-leak-symbol-lookup.C b/tools/profiler/nautilus-leak-symbol-lookup.C
deleted file mode 100644
index 02120bae9..000000000
--- a/tools/profiler/nautilus-leak-symbol-lookup.C
+++ /dev/null
@@ -1,301 +0,0 @@
-/* nautilus-leak-symbol-lookup.C - symbol lookup for a leak checking and profiling
- library
-
- Copyright (C) 2000 Eazel
-
- The Gnome Library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public License as
- published by the Free Software Foundation; either version 2 of the
- License, or (at your option) any later version.
-
- The Gnome Library 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
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with the Gnome Library; see the file COPYING.LIB. If not,
- write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- Boston, MA 02111-1307, USA.
-
- Author: Pavel Cisler <pavel@eazel.com>
-*/
-
-/* Copied from the leakchecker with a few minor tweaks.
- * FIXME: need to consolidate this with the leakchecker version and
- * only have one copy for both
- */
-#define _GNU_SOURCE
- /* need this for dladdr */
-
-#include "nautilus-leak-symbol-lookup.h"
-
-#include <bfd.h>
-#include <dlfcn.h>
-#include <glib.h>
-#include <stdio.h>
-#include <malloc.h>
-#include <unistd.h>
-#include <sys/stat.h>
-
-
-static GList *symbol_table_list;
-
-typedef struct {
- char *path;
- bfd *abfd;
- asymbol **symbol_table;
- asection *text_section;
- unsigned long start;
- unsigned long end;
-} NautilusLeakSymbolLookupMap;
-
-static gboolean
-nautilus_leak_find_symbol_in_map (const NautilusLeakSymbolLookupMap *map,
- unsigned long address, char **function_name, char **source_file_name,
- unsigned int *line)
-{
- const char *file;
- const char *function;
-
- address -= map->start;
- address -= map->text_section->vma;
-
- if (address > map->text_section->_cooked_size) {
- /* not a valid address range for this binary */
- return FALSE;
- }
-
- if (!bfd_find_nearest_line (map->abfd, map->text_section, map->symbol_table,
- address,
- &file, &function, line)) {
- printf ("error looking up address in binary %s\n", map->path);
- return FALSE;
- }
- if (file == NULL || function == NULL) {
- return FALSE;
- }
-
- *function_name = g_strdup (function);
- *source_file_name = g_strdup (file);
-
- return TRUE;
-}
-
-static void
-nautilus_leak_symbol_map_get_offsets (NautilusLeakSymbolLookupMap *map)
-{
- gchar buffer[1024];
- FILE *in;
- gchar perms[26];
- gchar file[256];
- unsigned long start, end;
- guint major, minor;
- ino_t inode;
- struct stat library_stat;
- struct stat entry_stat;
- int count;
-
- /* find the library we are looking for in the proc directories
- * to find out at which addresses it is mapped
- */
- snprintf (buffer, 1023, "/proc/%d/maps", getpid());
- in = fopen (buffer, "r");
-
- if (stat (map->path, &library_stat) != 0) {
- /* we will use st_ino and st_dev to do a file match */
- return;
- }
-
- while (fgets(buffer, 1023, in)) {
- gulong tmp;
-
- count = sscanf (buffer, "%lx-%lx %15s %*x %u:%u %lu %255s",
- &start, &end, perms, &major, &minor, &tmp, file);
- inode = tmp;
-
- if (count >= 6 && strcmp (perms, "r-xp") == 0) {
- if (stat (file, &entry_stat) != 0) {
- break;
- }
- /* check if this is the library we are loading */
- if (library_stat.st_ino == entry_stat.st_ino
- && library_stat.st_dev == entry_stat.st_dev) {
- map->start = start;
- map->end = end;
-
- break;
- }
- }
- }
- fclose (in);
-}
-
-static NautilusLeakSymbolLookupMap *
-nautilus_leak_symbol_map_load (const char *binary_path, gboolean executable)
-{
- NautilusLeakSymbolLookupMap *map;
- char *target = NULL;
- size_t storage_needed;
- int number_of_symbols;
-
- map = g_new0 (NautilusLeakSymbolLookupMap, 1);
-
- map->abfd = bfd_openr (binary_path, target);
-
- if (map->abfd == NULL) {
- fprintf (stderr, "%s: ", binary_path);
- bfd_perror (binary_path);
- return NULL;
- }
-
- if (!bfd_check_format (map->abfd, bfd_object)) {
- fprintf (stderr, "%s is not an object file\n", binary_path);
- bfd_close (map->abfd);
- return NULL;
- }
-
- /* Use the ".text" section. */
- map->text_section = bfd_get_section_by_name (map->abfd, ".text");
-
- /* Read the symbol table. */
- storage_needed = bfd_get_symtab_upper_bound (map->abfd);
- if (storage_needed == 0) {
- fprintf (stderr, "no symbols\n");
- bfd_close (map->abfd);
- return NULL;
- }
- map->symbol_table = (asymbol **)g_malloc (storage_needed);
- if (map->symbol_table == NULL) {
- fprintf (stderr, "no memory allocating symbol table\n");
- bfd_close (map->abfd);
- return NULL;
- }
- number_of_symbols = bfd_canonicalize_symtab (map->abfd, map->symbol_table);
- map->path = g_strdup (binary_path);
-
- if (!executable) {
- nautilus_leak_symbol_map_get_offsets (map);
- }
- symbol_table_list = g_list_append (symbol_table_list, map);
-
- return map;
-}
-
-static NautilusLeakSymbolLookupMap *
-nautilus_leak_symbol_map_load_if_needed (const char *binary_path, gboolean executable)
-{
- GList *p;
- NautilusLeakSymbolLookupMap *map;
-
- for (p = symbol_table_list; p != NULL; p = p->next) {
- map = (NautilusLeakSymbolLookupMap *)p->data;
- if (strcmp (map->path, binary_path) == 0)
- /* no need to load the symbols, already got the map */
- return map;
- }
- return nautilus_leak_symbol_map_load (binary_path, executable);
-}
-
-void
-nautilus_leak_print_symbol_cleanup (void)
-{
- /* free the cached symbol tables */
- GList *p;
- NautilusLeakSymbolLookupMap *map;
-
- for (p = symbol_table_list; p != NULL; p = p->next) {
- map = (NautilusLeakSymbolLookupMap *)p->data;
- bfd_close (map->abfd);
- g_free (map->symbol_table);
- g_free (map->path);
-
- g_free (map);
- }
-
- g_list_free (symbol_table_list);
- symbol_table_list = NULL;
-}
-
-static gboolean
-nautilus_leak_find_symbol_address (void *address, char **function_name, char **source_file_name,
- int *line)
-{
- GList *p;
- NautilusLeakSymbolLookupMap *map;
- Dl_info info;
-
- if (dladdr (address, &info) != 0) {
- /* We know the function name and the binary it lives in, now try to find
- * the function and the offset.
- */
- map = nautilus_leak_symbol_map_load_if_needed (info.dli_fname, false);
-
- /* temporarily force a dladdr-only lookup.
- * should make the bfd symbol lookup work.
- */
- if (map != NULL
- && nautilus_leak_find_symbol_in_map (map, (long)address,
- function_name, source_file_name, (unsigned int *)line)) {
- return TRUE;
- }
- /* just return the function name and the library binary path */
- *function_name = g_strdup (info.dli_sname);
- *source_file_name = g_strdup (info.dli_fname);
- *line = -1;
- return TRUE;
- } else {
- /* Usually dladdr will succeed, it seems to only fail for
- * address lookups for functions in the main binary.
- */
- for (p = symbol_table_list; p != NULL; p = p->next) {
- map = (NautilusLeakSymbolLookupMap *)p->data;
- if (nautilus_leak_find_symbol_in_map (map, (long)address, function_name,
- source_file_name, (unsigned int *)line))
- return TRUE;
- }
- }
-
- return FALSE;
-}
-
-void
-get_function_at_address (const char *app_path, void *address, string &result)
-{
- char *function_name;
- char *source_file_name;
- int line;
-
- nautilus_leak_symbol_map_load_if_needed (app_path, true);
-
- if (nautilus_leak_find_symbol_address (address, &function_name, &source_file_name, &line)) {
- result = function_name;
-
- g_free (function_name);
- g_free (source_file_name);
- } else {
- result = "unknown function";
- }
-}
-
-void
-nautilus_leak_print_symbol_address (const char *app_path, void *address)
-{
- char *function_name;
- char *source_file_name;
- int line;
-
- nautilus_leak_symbol_map_load_if_needed (app_path, true);
-
- if (nautilus_leak_find_symbol_address (address, &function_name, &source_file_name, &line)) {
- if (line >= 0) {
- printf("%10p %-30s %s:%d\n", address, function_name, source_file_name, line);
- } else {
- printf("%10p %-30s in library %s\n", address, function_name, source_file_name);
- }
- g_free (function_name);
- g_free (source_file_name);
- } else {
- printf("%p (unknown function)\n", address);
- }
-}
diff --git a/tools/profiler/nautilus-leak-symbol-lookup.h b/tools/profiler/nautilus-leak-symbol-lookup.h
deleted file mode 100644
index 698adf868..000000000
--- a/tools/profiler/nautilus-leak-symbol-lookup.h
+++ /dev/null
@@ -1,9 +0,0 @@
-#ifndef NAUTILUS_LEAK_SYMBOL_LOOKUP__
-#define NAUTILUS_LEAK_SYMBOL_LOOKUP__
-
-#include <string>
-
-void nautilus_leak_print_symbol_address (const char *app_path, void *address);
-void get_function_at_address (const char *app_path, void *address, string &result);
-
-#endif
diff --git a/tools/profiler/profile.C b/tools/profiler/profile.C
deleted file mode 100644
index a54162be9..000000000
--- a/tools/profiler/profile.C
+++ /dev/null
@@ -1,457 +0,0 @@
-/*
- * Cprof profiler tool
- * (C) Copyright 1999-2000 Corel Corporation
- * Copyright (C) 2000 Eazel
- *
- * 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 2 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, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * adapted for shared library support:
- * Pavel Cisler <pavel@eazel.com>
- */
-
-#define _XOPEN_SOURCE 500 /* for pwrite */
-
-/* Define to whatever is needed to declare a stdcall function. */
-#define STDCALL __attribute__((__stdcall__))
-
-/* Define to whatever prefix is used on pthread calls. */
-#define PTHREAD_PREFIX pthread_
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <assert.h>
-#include <signal.h>
-#include <limits.h>
-#include <errno.h>
-
-#include <sys/mman.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <sys/time.h>
-#include <sys/sendfile.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <pthread.h>
-
-#include "profileP.h"
-#include "machine-profileP.h"
-#include "profiledata.h"
-#include "totaltime.h"
-#include "funcsummary.h"
-#include "symbol-table.h"
-
-/************************************************************************/
-
-static enum mstatus status = mstatus_on;
-
-static size_t maplen;
-
-static profile_header *header;
-
-static arc *arc_table;
-
-static pthread_key_t prof_key;
-
-static int dev_zero_fd;
-
-static thread_prof *threads;
-
-static int profile_map_fd;
-
-static size_t thread_maplen;
-
-static const char CPROF_STACK_SIZE[] = "CPROF_STACK_SIZE";
-static const char CPROF_ARC_TABLE_SIZE[] = "CPROF_ARC_TABLE_SIZE";
-static const char CPROF_DUMP_PREFIX[] = "CPROF_DUMP_PREFIX";
-
-static size_t stack_size;
-static size_t arc_table_size;
-static char *dump_prefix;
-
-/************************************************************************/
-
-static void profile_exit();
-static inline arc *allocate_arc(volatile thread_prof *thread, codeptr_t to);
-
-/* Temporarily installed during determine_frequency():
- * sigsuspend() does not wake up for SIG_IGN signals. */
-static void
-alarm_handler(int)
-{
-}
-
-
-/* Determine (and return) the number of profctr_t ticks per second. */
-static profctr_t
-determine_frequency()
-{
- itimerval delay, oldtimer;
- timeval tbefore, tafter;
- profctr_t before, after, delta;
- double elapsed;
- void (*old_alarm_handler)(int);
- sigset_t sigs;
-
- /* We steal the SIGALRM handler as well as ITIMER_REAL. This is very
- * rude, but unavoidable. */
-
- old_alarm_handler = signal(SIGALRM, alarm_handler);
-
- sigfillset(&sigs);
- sigdelset(&sigs, SIGALRM);
- sigdelset(&sigs, SIGKILL); /* we aren't allowed to block these */
- sigdelset(&sigs, SIGSTOP);
-
- /* Set this to whatever you want: we use gettimeofday to determine
- * how much time has actually elapsed. */
- delay.it_interval.tv_sec = 0;
- delay.it_interval.tv_usec = 0;
- delay.it_value.tv_sec = 0;
- delay.it_value.tv_usec = 1000000;
-
- setitimer(ITIMER_REAL, &delay, &oldtimer);
-
- get_timestamp(before);
- gettimeofday(&tbefore, NULL);
-
- sigsuspend(&sigs);
-
- get_timestamp(after);
- gettimeofday(&tafter, NULL);
-
- /* In seconds */
- elapsed = tafter.tv_sec - tbefore.tv_sec
- + (tafter.tv_usec - tbefore.tv_usec) / 1000000.0;
-
- delta = after - before;
-
- signal(SIGALRM, old_alarm_handler);
- setitimer(ITIMER_REAL, &oldtimer, &delay);
-
- return (profctr_t)(delta / elapsed);
-}
-
-static unsigned long
-getenv_ul(const char *name, unsigned long defult)
-{
- char *value, *endptr;
- unsigned long ret;
-
- value = getenv(name);
- if (value == NULL || value[0] == '\0')
- return defult;
-
- ret = strtoul(value, &endptr, 10);
- if (*endptr != '\0' || (ret == ULONG_MAX && errno == ERANGE))
- return defult;
-
- return ret;
-}
-
-static char *
-getenv_str(const char *name, const char *defult, int empty_ok)
-{
- const char *value = getenv(name);
- if (!value || (value[0] == '\0' && !empty_ok))
- value = defult;
-
- return strdup(value);
-}
-
-static void
-load_environment()
-{
- stack_size = getenv_ul(CPROF_STACK_SIZE, STACK_SIZE);
- arc_table_size = getenv_ul(CPROF_ARC_TABLE_SIZE, ARC_TABLE_SIZE);
- dump_prefix = getenv_str(CPROF_DUMP_PREFIX, "cmon.out", 0);
-}
-
-static void
-prof_init()
-{
- load_environment();
-
- maplen = getpagesize() + arc_table_size * sizeof(arc);
- thread_maplen = stack_size * sizeof(stack_entry);
-
- if (pthread_key_create(&prof_key, NULL) != 0)
- abort ();
-
- if (atexit(profile_exit) == -1)
- abort ();
-
- threads = NULL;
-
- dev_zero_fd = open("/dev/zero", O_RDWR);
- if (dev_zero_fd == -1)
- abort ();
-
- profile_map_fd = open(dump_prefix, O_RDWR | O_CREAT | O_NOCTTY | O_TRUNC, 0664);
-
- if (profile_map_fd == -1)
- abort ();
-
- ftruncate(profile_map_fd, maplen);
-
- header = (profile_header *)mmap(NULL, maplen, PROT_READ | PROT_WRITE, MAP_SHARED,
- profile_map_fd, 0);
- if (header == (profile_header *)-1)
- abort ();
-
- arc_table = (arc *)((char *)header + getpagesize());
-
- header->magic = CPROF_MAGIC;
- gettimeofday(&header->start_time, NULL);
- header->frequency = determine_frequency();
- header->num_arcs = arc_table_size;
- header->stack_size = stack_size;
- header->arc_table_addr = (uintptr_t)arc_table;
- header->valid_arcs = 0;
- header->num_threads = 0;
-
- mmap(arc_table + arc_table_size, getpagesize(), PROT_NONE,
- MAP_FIXED | MAP_PRIVATE, dev_zero_fd, 0);
-
-}
-
-static void
-prof_init_if_needed()
-{
- static pthread_once_t once_control = PTHREAD_ONCE_INIT;
- pthread_once(&once_control, prof_init);
-}
-
-
-static thread_prof *
-new_thread_profile()
-{
- prof_init_if_needed();
-
- size_t thread_num = atomic_inc(&header->num_threads);
- off_t mapoff = maplen + thread_num * thread_maplen;
-
- /* We have to extend the file so that it is large enough to hold
- * our additional mapping. Normally we'd use ftruncate, but that
- * causes concurrency problems: we might accidently shorten the file. */
- char c = 0;
- pwrite(profile_map_fd, &c, 1, mapoff + thread_maplen - 1);
-
- thread_prof *thread = (thread_prof *)mmap(NULL,
- stack_size * sizeof(stack_entry),
- PROT_READ | PROT_WRITE, MAP_SHARED, profile_map_fd, mapoff);
-
- if (thread == (thread_prof *)-1)
- abort();
-
- /* watch the alignment of stacktop. It's ok in 32-bit systems. */
- thread->stacktop
- = (stack_entry *)((char *)thread + sizeof(thread_prof));
-
- thread->root_arc = allocate_arc(thread, (codeptr_t)NULL);
-
- thread->root_arc->next = NULL;
- thread->root_arc->func_and_children = 0;
- thread->root_arc->count = 0;
- thread->root_arc->chain = NULL;
-
- /* Now we have to push a toplevel stack entry, since the rest of
- * menter will look at stacktop->current_arc */
- thread->stacktop->current_arc = thread->root_arc;
- get_timestamp(thread->stacktop->entry_timestamp);
-
- thread->pid = getpid();
-
- pthread_setspecific(prof_key, thread);
-
- /* Put us on the linked list of threads. */
- for (;;) {
- thread_prof *threads_head = threads;
- thread->next = threads_head;
- if (compare_and_swap((void **)&threads, threads_head, thread))
- break;
- }
-
- return thread;
-}
-
-static inline arc *
-allocate_arc(volatile thread_prof *, codeptr_t to)
-{
- arc *result = arc_table + atomic_inc(&header->valid_arcs);
-
- result->to = to;
-
- assert(result->func_and_children == 0);
- assert(result->count == 0);
- assert(result->chain == NULL);
-
- return result;
-}
-
-static inline arc *
-find_arc(volatile thread_prof *thread, arc *from, codeptr_t to)
-{
- for (arc *chain = from->chain; chain != NULL; chain = chain->next)
- if (chain->to == (codeptr_t)to)
- return chain;
-
-
- /* So allocate a new arc, and put it on the head of the chain. */
- arc *newarc = allocate_arc(thread, to);
- newarc->next = from->chain;
- from->chain = newarc;
-
- return newarc;
-}
-
-static inline thread_prof *
-get_thread_profile()
-{
- thread_prof *thread = (thread_prof *)pthread_getspecific(prof_key);
-
- if (!thread)
- thread = new_thread_profile();
- return thread;
-}
-
-static codeptr_t
-resolve_shared_library_address (codeptr_t address)
-{
- // Detect if we have an actual routine address or an address of a GOT.
- // If the latter is the case, follow the address to our routine.
- // This only works after the library has been loaded and relocated.
- const unsigned char *byte_stream = (const unsigned char *)address;
- if (byte_stream[0] == 0xff && byte_stream[1] == 0x25) {
- // jmp * - get the real routine address at the
- // jump destination
- const codeptr_t *indirect_location = *(const codeptr_t **)(byte_stream + 2);
- return *indirect_location;
- }
- return address;
-}
-
-extern "C" void __attribute((__stdcall__))
-__menter_internal (codeptr_t func)
-{
- func = resolve_shared_library_address (func);
- volatile thread_prof *thread = get_thread_profile();
- volatile stack_entry *stacktop = thread->stacktop;
- arc *current_arc = find_arc(thread, stacktop->current_arc, func);
-
- stacktop++;
-
- /* Dodge a signal race: We can't bump thread->stacktop until current_arc
- * is there or a signal handler will pass a bogus arc to find_arc. */
- stacktop->current_arc = current_arc;
- thread->stacktop++; /* should be atomic */
- /* And if a signal came in before thread->stacktop++, it will have
- * overwritten stacktop->current_arc, so put it back. */
- stacktop->current_arc = current_arc;
-
- get_timestamp(stacktop->entry_timestamp);
-
- if (status == mstatus_on)
- current_arc->count++;
-
-}
-
-extern "C" void __attribute((__stdcall__))
-__mexit_internal (void)
-{
- thread_prof *thread = get_thread_profile();
- volatile stack_entry *stacktop = thread->stacktop;
- arc *current_arc = stacktop->current_arc;
-
- if (status == mstatus_on) {
- /* We have to decrement thread->stacktop before reading the timestamp,
- * so that any signals that happen after we read the timestamp get
- * changed against our parent. Note that we have to read the
- * entry_timestamp before decrementing thread->stacktop or a signal
- * might overwrite it.
- */
- profctr_t entry_timestamp = stacktop->entry_timestamp;
- profctr_t delta;
-
- thread->stacktop--; /* should be atomic */
- get_timestamp(delta);
-
- delta -= entry_timestamp;
- update_arc_time(current_arc->func_and_children, delta);
- } else
- thread->stacktop--; /* should be atomic */
-}
-
-void
-profile_on()
-{
- status = mstatus_on;
-}
-
-void
-profile_off()
-{
- status = mstatus_off;
-}
-
-/* Due to the evil stride, this is not going to be very fast. */
-void
-profile_reset()
-{
- mstatus oldstatus = status;
- status = mstatus_off;
-
- const arc *end = arc_table + header->valid_arcs;
- for (arc *a = arc_table; a < end; a++) {
- a->func_and_children = 0;
- a->count = 0;
- }
-
- status = oldstatus;
-}
-
-static void
-profile_dump()
-{
- try {
- FuncSummary::sort_order order = FuncSummary::sort_func;
- ProfileData profile(profile_map_fd);
- SymbolTable symbols("/gnome/bin/nautilus");
- TotalTime tt(profile);
-
- FuncSummary fs(profile, symbols, order, tt.total_time());
- fs.Output(cout);
-
-// GprofStack gs(profile, symbols);
-// gs.Output(cout);
-
-// CallStack cs(profile, symbols);
-// cs.Output(cout);
- } catch (const exception &e) {
- cerr << e.what() << '\n';
- }
- catch (...) {
- cerr << "Unknown exception\n";
- }
- close (profile_map_fd);
- unlink (dump_prefix);
-}
-
-static void
-profile_exit()
-{
- profile_dump();
- printf("profiler done\n");
-}
diff --git a/tools/profiler/profile.h b/tools/profiler/profile.h
deleted file mode 100644
index 199361ebc..000000000
--- a/tools/profiler/profile.h
+++ /dev/null
@@ -1,100 +0,0 @@
-/*
- * Cprof profiler tool
- * (C) Copyright 1999-2000 Corel Corporation
- * Copyright (C) 2000 Eazel
- *
- * 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 2 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, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * adapted for shared library support:
- * Pavel Cisler <pavel@eazel.com>
- */
-
-/* Public definitions for the profiler. */
-
-#ifndef PROFILE_H_INCLUDED
-#define PROFILE_H_INCLUDED
-
-#include <stdint.h>
-
-#include <sys/types.h>
-#include <sys/time.h>
-#include <unistd.h>
-
-#include "machine-profile.h"
-
-enum { CPROF_MAGIC = 0x4e4f4d43 };
-
-struct profile_header
-{
- uint32_t magic; /* expect CPROF_MAGIC */
- struct timeval start_time; /* time at which the run started */
- struct timeval end_time; /* time at which the run was saved */
-
- profctr_t frequency; /* counts per second */
-
- size_t num_arcs; /* number of arcs (size of arc table) */
- size_t stack_size; /* size of each thread's stack */
-
- size_t valid_arcs; /* number of used arcs
- * arcs are used from the start of the table */
- uintptr_t arc_table_addr; /* virtual address of the arc table */
-
- size_t num_threads; /* number of threads */
-};
-
-struct arc
-{
- /* FROM is implicit: each arc is on a linked list that belongs
- * to an arc who's TO is our FROM. */
-
- codeptr_t to; /* The destination of this arc. */
- struct arc *next; /* The next node in our FROM's linked list. */
-
- profctr_t func_and_children; /* Exit - Enter delta */
- size_t count; /* number of times this arc has been traversed */
- struct arc *chain; /* arcs called from the destination of this arc */
-};
-
-struct stack_entry
-{
- struct arc *current_arc;
- profctr_t entry_timestamp;
-};
-
-struct thread_prof
-{
- /* Our stack goes upwards through memory. */
- struct stack_entry *stacktop;
-
- struct arc *root_arc;
-
- struct thread_prof *next;
-
- pid_t pid;
-};
-
-/* Profiling defaults to on.
- * profile_on and profile_off just do the obvious thing. They don't save or
- * reset counters.
- *
- * profile_reset resets all the counters and elapsed times to 0.
- * profile_save saves the profiling data to the file named
- */
-extern void profile_on(void);
-extern void profile_off(void);
-extern void profile_reset(void);
-extern int profile_save(const char *prefix);
-
-#endif
diff --git a/tools/profiler/profileP.h b/tools/profiler/profileP.h
deleted file mode 100644
index 5459acbf9..000000000
--- a/tools/profiler/profileP.h
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Cprof profiler tool
- * (C) Copyright 1999-2000 Corel Corporation
- *
- * 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 2 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, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#ifndef PROFILE_PRIVATE_H_INCLUDED
-#define PROFILE_PRIVATE_H_INCLUDED
-
-#include "profile.h"
-
-#define ARC_TABLE_SIZE (16 * 1024 * 1024) /* global */
-#define STACK_SIZE 1024 /* 12k per-thread */
-/* And we put the thread_prof structure onto the stack. */
-
-enum mstatus
-{
- mstatus_on = 0,
- mstatus_off,
- mstatus_error
-};
-
-#ifndef INLINE1
-#define INLINE1 inline
-#endif
-
-#ifndef INLINE2
-#define INLINE2 inline
-#endif
-
-#endif
diff --git a/tools/profiler/profiledata.C b/tools/profiler/profiledata.C
deleted file mode 100644
index 8bfb50e47..000000000
--- a/tools/profiler/profiledata.C
+++ /dev/null
@@ -1,310 +0,0 @@
-/*
- * Cprof profiler tool
- * (C) Copyright 1999-2000 Corel Corporation
- *
- * 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 2 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, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#include "profiledata.h"
-
-#include <stack>
-#include <stdexcept>
-#include <cerrno>
-#include <cstring>
-
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <sys/mman.h>
-#include <unistd.h>
-#include <fcntl.h>
-
-using namespace std;
-
-namespace
-{
- template <class T, class U>
- inline T round_up(T t, U u)
- {
- return (t + u - 1) & -u;
- }
-
- static void check_result_failure(void)
- {
- throw runtime_error(strerror(errno));
- }
-
- static inline void check_result(int res)
- {
- if (res == -1)
- check_result_failure();
- }
-}
-
-void ProfileData::assert_valid_arc_data_ptr(const struct ArcData *p)
- const throw()
-{
- uintptr_t pu = reinterpret_cast<uintptr_t>(p);
- uintptr_t arc_table_u = reinterpret_cast<uintptr_t>(arc_table);
-
- assert(p == NULL
- || (pu >= arc_table_u
- && pu < arc_table_u + header->valid_arcs * sizeof(ArcData)));
-}
-
-inline size_t ProfileData::arc_index(const struct arc *a) const throw()
-{
- assert(map_arc_table != NULL);
- return a - reinterpret_cast<const struct arc *>(arc_table_addr);
-}
-
-inline ProfileData::ArcData *ProfileData::xlate_arc(const struct arc *a) const
- throw()
-{
- assert(arc_table != NULL);
-
- return (a == NULL) ? NULL : (arc_table + arc_index(a));
-}
-
-inline const struct thread_prof *ProfileData::get_thread(size_t i) const
- throw()
-{
- assert(map_threads != NULL);
- assert(i < header->num_threads);
-
- const struct thread_prof *result = reinterpret_cast<const struct thread_prof *>(reinterpret_cast<uintptr_t>(map_threads) + i * header->stack_size * sizeof(struct stack_entry));
-
- assert(static_cast<const void *>(result) < static_cast<char *>(map) + maplen);
-
- return result;
-}
-
-ProfileData::ProfileData(const char *filename)
-{
- map_profile(filename);
- try {
- load_header();
- load_threads();
- load_arcs();
- } catch (...) {
- unmap_profile();
- throw;
- }
- unmap_profile();
-}
-
-ProfileData::ProfileData(int file_descriptor)
-{
- map_profile(file_descriptor);
- try {
- load_header();
- load_threads();
- load_arcs();
- } catch (...) {
- unmap_profile();
- throw;
- }
- unmap_profile();
-}
-
-void ProfileData::map_profile(int file_descriptor)
-{
- check_result(file_descriptor);
-
- struct stat buf;
- check_result(fstat(file_descriptor, &buf));
-
- maplen = buf.st_size;
- map = mmap(NULL, maplen, PROT_READ, MAP_PRIVATE, file_descriptor, 0);
-
- uintptr_t mapaddr = reinterpret_cast<uintptr_t>(map);
-
- map_header = static_cast<profile_header *>(map);
- map_arc_table = reinterpret_cast<arc *>(mapaddr + getpagesize());
-
- map_threads = reinterpret_cast<thread_prof *>(mapaddr + getpagesize() + map_header->num_arcs * sizeof(struct arc));
-
- arc_table_addr = map_header->arc_table_addr;
-}
-
-void ProfileData::map_profile(const char *filename)
-{
- int fd = open(filename, O_RDONLY | O_NOCTTY);
- check_result(fd);
-
- map_profile(fd);
- close(fd);
-}
-
-void ProfileData::unmap_profile(void)
-{
- munmap(map, maplen);
-
- map = NULL;
- map_header = NULL;
- map_arc_table = NULL;
- map_threads = NULL;
- arc_table_addr = 0;
-}
-
-void ProfileData::load_header(void)
-{
- header = new profile_header;
- *header = *map_header;
-}
-
-void ProfileData::load_threads(void)
-{
- assert(header != NULL);
- assert(map_threads != NULL);
-
- // We can't really do much as the arc_table has not been created yet.
- ThreadData td;
- td.root_arc = NULL;
-
- threads.resize(header->num_threads, td);
-}
-
-// Both implementations do the same thing, but the second uses an
-// explicit stack to avoid recursion.
-#if 1
-void ProfileData::update_arc_children(ArcData &a)
-{
- for (ArcData *c = a.tochain; c != NULL; c = c->next_sibling) {
- assert(arc_table <= c && c < arc_table + header->valid_arcs);
-
- c->from = &a;
- c->fromfunc = a.tofunc;
- update_arc_children(*c);
- }
-
- // If we never return from a function, we never assign it a F+D
- // time. Fake one by adding up the F+D time for all its children.
- if (a.time == 0)
- for (ArcData *c = a.tochain; c != NULL; c = c->next_sibling)
- a.time += c->time;
-
-}
-#else
-void ProfileData::update_arc_children(ArcData &a)
-{
- typedef stack<ArcData *> arcdata_stack_t;
- arcdata_stack_t stack;
-
- stack.push(&a);
-
- while (!stack.empty()) {
- ArcData *a = stack.top();
- stack.pop();
-
- for (ArcData *c = a->tochain; c != NULL; c = c->next_sibling) {
- assert(arc_table <= c && c < arc_table + header->valid_arcs);
-
- c->from = a;
- c->fromfunc = a->tofunc;
- stack.push(c);
- }
- }
-}
-#endif
-
-// Solely for debugging convenience.
-static void *g_arc_table;
-static void *g_arc_table_end;
-
-void ProfileData::load_arcs(void)
-{
- size_t narcs = header->valid_arcs;
- arc_table = new ArcData[narcs];
-
- g_arc_table = arc_table;
- g_arc_table_end = arc_table + narcs;
-
- for (size_t i=0; i < narcs; i++) {
- arc_table[i].from = NULL;
- arc_table[i].tochain = xlate_arc(map_arc_table[i].chain);
- arc_table[i].count = map_arc_table[i].count;
- arc_table[i].time = map_arc_table[i].func_and_children;
- arc_table[i].next_sibling = xlate_arc(map_arc_table[i].next);
-
- arc_table[i].fromfunc = (codeptr_t)NULL;
- arc_table[i].tofunc = map_arc_table[i].to;
- }
-
-#ifndef NDEBUG
- for (size_t i=0; i < narcs; i++) {
- assert_valid_arc_data_ptr(arc_table[i].tochain);
- assert_valid_arc_data_ptr(arc_table[i].next_sibling);
- }
-#endif
-
- // Now fill in the missing ArcData fields by following the child chains.
- for (size_t i=0; i < header->num_threads; i++)
- threads[i].root_arc = xlate_arc(get_thread(i)->root_arc);
-
-
- if (header->num_threads > 0) {
- for (size_t i=0; i < header->num_threads - 1; i++)
- threads[i].root_arc->next_sibling = threads[i+1].root_arc;
-
- threads[header->num_threads-1].root_arc->next_sibling = NULL;
- }
-
- for (size_t i=0; i < header->num_threads; i++) {
- update_arc_children(*threads[i].root_arc);
- }
-}
-
-ProfileData::~ProfileData()
-{
- delete header;
- delete[] arc_table;
-}
-
-void
-ProfileData::VisitArcs(ArcVisitor *v) const
-{
- for (threads_const_iterator i = threads.begin(); i != threads.end(); i++)
- VisitArc(v, *i->root_arc);
-}
-
-// This is done in depth-first order, and is defined to always be this way.
-void
-ProfileData::VisitArc(ArcVisitor *v, const ArcData &a) const
-{
- assert(&a != NULL);
- assert_valid_arc_data_ptr(&a);
-
- typedef stack<const ArcData *> arcdata_stack_t;
- arcdata_stack_t stack;
-
- stack.push(&a);
-
- while (!stack.empty()) {
- const ArcData *a = stack.top();
- stack.pop();
-
- assert(a != NULL);
- assert_valid_arc_data_ptr(a);
-
- v->visit(*a);
-
- for (ArcData *c = a->tochain; c != NULL; c = c->next_sibling) {
- assert(c != NULL);
- assert_valid_arc_data_ptr(c);
-
- stack.push(c);
- }
- }
-}
diff --git a/tools/profiler/profiledata.h b/tools/profiler/profiledata.h
deleted file mode 100644
index 16be54b9d..000000000
--- a/tools/profiler/profiledata.h
+++ /dev/null
@@ -1,277 +0,0 @@
-/*
- * Cprof profiler tool
- * (C) Copyright 1999-2000 Corel Corporation
- *
- * 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 2 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, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#ifndef PROFILEDATA_H_INCLUDED
-#define PROFILEDATA_H_INCLUDED
-
-#include <string>
-#include <vector>
-#include <iterator>
-
-#include <stdint.h>
-
-#include <sys/types.h>
-#include <unistd.h>
-
-#include "profile.h"
-
-class ProfileData
-{
-public:
- explicit ProfileData(int file_descriptor);
- explicit ProfileData(const char *filename);
- virtual ~ProfileData();
-
- // These report real-word absolute time and can be used to identify
- // the run. If you save multiple times during the same run, they will
- // have the same start_time, but different end_times.
- inline timeval start_time() const;
- inline timeval end_time() const;
-
- inline profctr_t total_time() const;
-
- inline profctr_t frequency() const;
-
- // really valid_arcs, but the outside world shouldn't know that
- // unused arcs exist at all
- inline size_t num_arcs() const;
-
- struct ArcData {
- ArcData *from, *tochain;
- codeptr_t fromfunc, tofunc;
- size_t count;
- profctr_t time;
- ArcData *next_sibling;
- };
-
- struct ThreadData {
- ArcData *root_arc;
- };
-
- struct ArcVisitor {
- virtual void visit(const ArcData &a) = 0;
- };
-
- void VisitArcs(ArcVisitor *v) const;
-
- struct const_arc_iterator;
- struct arc_iterator {
- // SGI STL does not include struct iterator :(
- typedef forward_iterator_tag iterator_category;
- typedef const ArcData value_type;
- typedef ptrdiff_t difference_type;
- typedef value_type *pointer;
- typedef value_type &reference;
-
- friend struct const_arc_iterator;
- friend class ProfileData;
- friend bool operator == (const arc_iterator &, const arc_iterator &);
-
- arc_iterator() { }
- arc_iterator(const arc_iterator &i) : p(i.p) { }
- arc_iterator &operator = (const arc_iterator &i)
- {
- p = i.p;
- return *this;
- }
-
- reference operator *() const throw() { return *p; }
- pointer operator ->() const throw() { return p; }
-
- arc_iterator &operator ++ () throw()
- { p = p->next_sibling; return *this; }
- arc_iterator operator ++ (int) throw()
- {
- arc_iterator temp(*this);
- p = p->next_sibling;
- return temp;
- }
-
- private:
- explicit arc_iterator(ArcData *_p) : p(_p) { }
- static inline arc_iterator end()
- { return arc_iterator(NULL); }
-
- pointer p;
- };
-
- struct const_arc_iterator {
- // SGI STL does not include struct iterator :(
- typedef forward_iterator_tag iterator_category;
- typedef const ArcData value_type;
- typedef ptrdiff_t difference_type;
- typedef value_type *pointer;
- typedef value_type &reference;
-
- friend class ProfileData;
- friend bool operator == (const const_arc_iterator &,
- const const_arc_iterator &);
-
- const_arc_iterator() throw() { }
- const_arc_iterator(const arc_iterator &i) throw() : p(i.p) { }
- const_arc_iterator(const const_arc_iterator &i) throw() : p(i.p) { }
-
- const_arc_iterator &operator = (const arc_iterator &i) throw()
- {
- p = i.p;
- return *this;
- }
- const_arc_iterator &operator = (const const_arc_iterator &i) throw()
- {
- p = i.p;
- return *this;
- }
-
- reference operator *() const throw() { return *p; }
- pointer operator ->() const throw() { return p; }
-
- const_arc_iterator &operator ++ () throw()
- { p = p->next_sibling; return *this; }
- const_arc_iterator operator ++ (int) throw()
- {
- const_arc_iterator temp(*this);
- p = p->next_sibling;
- return temp;
- }
-
- private:
- explicit const_arc_iterator(const ArcData *_p) throw() : p(_p) { }
- static inline const arc_iterator end() throw()
- { return arc_iterator(NULL); }
-
- pointer p;
- };
-
- inline const_arc_iterator begin_children(const ArcData &a) const throw();
- inline const_arc_iterator end_children(const ArcData &a) const throw();
-
- inline const_arc_iterator begin_roots() const throw();
- inline const_arc_iterator end_roots() const throw();
-
-private:
- void VisitArc(ArcVisitor *v, const ArcData &a) const;
-
- void assert_valid_arc_data_ptr(const ArcData *p) const throw();
- inline size_t arc_index(const struct arc *a) const throw();
- inline ArcData *xlate_arc(const struct arc *a) const throw();
- inline const struct thread_prof *get_thread(size_t i) const throw();
-
- void map_profile(const char *filename);
- void map_profile(int file_descriptor);
- void unmap_profile();
-
- void load_header();
- void load_threads();
- void load_arcs();
- void update_arc_children(ArcData &a);
-
- // These are only valid while the map is active. (i.e. during the ctor)
- void *map; // Mmaped cmon.out.
- const profile_header *map_header; // profiler_header in map
- const arc *map_arc_table; // arc table in map
- const thread_prof *map_threads; // first thread in map
- size_t maplen; // length of entire map
- uintptr_t arc_table_addr; // VA of arc table in profiled program
-
- profile_header *header;
- ArcData *arc_table;
- typedef std::vector<ThreadData> threads_list_t;
- typedef threads_list_t::iterator threads_iterator;
- typedef threads_list_t::const_iterator threads_const_iterator;
- threads_list_t threads;
-
- profctr_t m_total_time;
-
- // unimplemented
- ProfileData(const ProfileData &);
- void operator = (const ProfileData &);
-};
-
-inline timeval
-ProfileData::start_time() const
-{
- return header->start_time;
-}
-
-inline timeval
-ProfileData::end_time() const
-{
- return header->end_time;
-}
-
-inline profctr_t
-ProfileData::total_time() const
-{
- return m_total_time;
-}
-
-inline profctr_t
-ProfileData::frequency() const
-{
- return header->frequency;
-}
-
-inline size_t
-ProfileData::num_arcs() const
-{
- return header->valid_arcs;
-}
-
-inline ProfileData::const_arc_iterator
-ProfileData::begin_children(const ArcData &a) const throw()
-{
- return const_arc_iterator(a.tochain);
-}
-
-inline ProfileData::const_arc_iterator
-ProfileData::end_children(const ArcData &) const throw()
-{
- return const_arc_iterator::end();
-}
-
-inline ProfileData::const_arc_iterator
-ProfileData::end_roots()
- const throw()
-{
- return const_arc_iterator::end();
-}
-
-inline ProfileData::const_arc_iterator
-ProfileData::begin_roots()
- const throw()
-{
- return (header->num_threads > 0)
- ? const_arc_iterator(threads[0].root_arc)
- : end_roots();
-}
-
-inline bool
-operator == (const ProfileData::arc_iterator &left,
- const ProfileData::arc_iterator &right)
-{
- return left.p == right.p;
-}
-
-inline bool
-operator == (const ProfileData::const_arc_iterator &left,
- const ProfileData::const_arc_iterator &right)
-{
- return left.p == right.p;
-}
-#endif
diff --git a/tools/profiler/symbol-table.h b/tools/profiler/symbol-table.h
deleted file mode 100644
index 99631f5c5..000000000
--- a/tools/profiler/symbol-table.h
+++ /dev/null
@@ -1,67 +0,0 @@
-/* symbol-table.h - symbol lookup for a leak checking and profiling
- library
-
- Copyright (C) 2000 Eazel
-
- The Gnome Library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public License as
- published by the Free Software Foundation; either version 2 of the
- License, or (at your option) any later version.
-
- The Gnome Library 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
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with the Gnome Library; see the file COPYING.LIB. If not,
- write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- Boston, MA 02111-1307, USA.
-
- Author: Pavel Cisler <pavel@eazel.com>
-*/
-
-#ifndef SYMBOL_TABLE__
-#define SYMBOL_TABLE__
-
-#include <string>
-#include <stdio.h>
-#include "nautilus-leak-symbol-lookup.h"
-
-#include "profile.h"
-
-class SymbolTable {
-public:
- SymbolTable(const char *app_path)
- : app_path(app_path)
- {}
- ~SymbolTable()
- {}
-
- void Lookup (codeptr_t address, string &name) const
- {
- name = "";
-
-#if 1
- char buffer[256];
- sprintf(buffer, "x/i 0x%x ", address);
- name = buffer;
-#endif
-
- string function_name;
- get_function_at_address (app_path.c_str(),
- (void *)address, function_name);
- name += function_name;
- }
-
- void LookupExact (codeptr_t address, string &name) const
- {
- // for now
- Lookup(address, name);
- }
-
-private:
- string app_path;
-};
-
-#endif
diff --git a/tools/profiler/test.cpp b/tools/profiler/test.cpp
deleted file mode 100644
index baf5c1fb9..000000000
--- a/tools/profiler/test.cpp
+++ /dev/null
@@ -1,79 +0,0 @@
-#include <stdio.h>
-#include <unistd.h>
-
-void libcall2(void);
-void libcall1(void);
-void libcall(void);
-void xlibcall(void);
-
-#ifdef TEST_LIB
-
-
-void
-libcall2(void)
-{
- xlibcall();
- printf("-\n");
-}
-
-void
-libcall1(void)
-{
- libcall2();
-}
-
-void
-libcall(void)
-{
- libcall1();
-}
-
-void
-xlibcall(void)
-{
-}
-
-#else
-
-static int
-a()
-{
- libcall();
-}
-
-static int
-b()
-{
- for (int i = 0; i < 10; i++)
- a();
-}
-
-static int
-c()
-{
- for (int i = 0; i < 10; i++) {
- a();
- b();
- }
-}
-
-static int
-d()
-{
- libcall();
- for (int i = 0; i < 10; i++) {
- a();
- b();
- c();
- }
-}
-
-int
-main()
-{
- xlibcall();
- //d();
- printf("test done\n");
-}
-
-#endif \ No newline at end of file
diff --git a/tools/profiler/totaltime.C b/tools/profiler/totaltime.C
deleted file mode 100644
index 725f9e367..000000000
--- a/tools/profiler/totaltime.C
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Cprof profiler tool
- * (C) Copyright 1999-2000 Corel Corporation
- *
- * 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 2 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, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#include "totaltime.h"
-
-TotalTime::~TotalTime()
-{
-}
-
-void TotalTime::CountTotalTime(const ProfileData &data)
-{
- m_total_time = 0;
- for (ProfileData::const_arc_iterator i = data.begin_roots();
- i != data.end_roots(); ++i)
- {
- m_total_time += i->time;
- }
-}
diff --git a/tools/profiler/totaltime.h b/tools/profiler/totaltime.h
deleted file mode 100644
index fcc7e0305..000000000
--- a/tools/profiler/totaltime.h
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Cprof profiler tool
- * (C) Copyright 1999-2000 Corel Corporation
- *
- * 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 2 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, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#ifndef TOTALTIME_H_INCLUDED
-#define TOTALTIME_H_INCLUDED
-
-#include "profiledata.h"
-
-class TotalTime
-{
-public:
- explicit TotalTime(const ProfileData &data) { CountTotalTime(data); }
- virtual ~TotalTime();
-
- inline profctr_t total_time(void) const;
-
-private:
- profctr_t m_total_time;
-
- void CountTotalTime(const ProfileData &data);
-
- // unimplemented
- TotalTime(const TotalTime &);
- void operator = (const TotalTime &);
-};
-
-inline profctr_t TotalTime::total_time(void) const
-{
- return m_total_time;
-}
-
-#endif