Couldn't figure out how to build the leakchecker shared library with

2000-06-13  Pavel Cisler  <pavel@eazel.com>

	* test/Makefile.am:
	Couldn't figure out how to build the leakchecker shared library
	with libtool, added a simple link rule instead.

	* test/nautilus-leak-symbol-lookup.c:
	(nautilus_leak_find_symbol_in_map),
	(nautilus_leak_symbol_map_get_offsets),
	(nautilus_leak_symbol_map_load),
	(nautilus_leak_symbol_map_load_if_needed),
	(nautilus_leak_find_symbol_address),
	(nautilus_leak_print_symbol_address):
	Redo symbol lookup to work better in some cases.

	* test/nautilus-leak-checker.c: (allocate_lots), (leak_mem2),
	(leak_mem), (main):
	tweaks to testing code.
This commit is contained in:
Pavel Cisler 2000-06-14 05:20:04 +00:00 committed by Pavel Cisler
parent bd52afb29f
commit 858e160f9c
4 changed files with 156 additions and 81 deletions

View file

@ -1,3 +1,23 @@
2000-06-13 Pavel Cisler <pavel@eazel.com>
* test/Makefile.am:
Couldn't figure out how to build the leakchecker shared library
with libtool, added a simple link rule instead.
* test/nautilus-leak-symbol-lookup.c:
(nautilus_leak_find_symbol_in_map),
(nautilus_leak_symbol_map_get_offsets),
(nautilus_leak_symbol_map_load),
(nautilus_leak_symbol_map_load_if_needed),
(nautilus_leak_find_symbol_address),
(nautilus_leak_print_symbol_address):
Redid symbol lookup to work better in some cases where dladdr
would not give us the right function.
* test/nautilus-leak-checker.c: (allocate_lots), (leak_mem2),
(leak_mem), (main):
tweaks to testing code.
2000-06-13 Rebecca Schulman <rebecka@eazel.com>
Initial changes to implement search architecture.

View file

@ -1,6 +1,6 @@
NULL=
lib_LTLIBRARIES = libleakcheck.la
#lib_LTLIBRARIES = libleakcheck.la
INCLUDES =\
-I$(top_srcdir) \
@ -40,32 +40,37 @@ test_nautilus_mime_actions_SOURCES = test-nautilus-mime-actions.c
test_nautilus_mime_actions_set_SOURCES = test-nautilus-mime-actions-set.c
libleakcheck_la_SOURCES = \
nautilus-leak-checker.c \
nautilus-leak-checker.h \
nautilus-leak-checker-stubs.h \
nautilus-leak-hash-table.c \
nautilus-leak-hash-table.h \
nautilus-leak-symbol-lookup.c \
nautilus-leak-symbol-lookup.h \
$(NULL)
# we need to link libbfd and liberty statically
# this is currently broken because of libtool dumbness
# LIBLEAKCHECK_STATIC_LIBS = "-Wl,-Bstatic -lbfd -liberty -Wl,-Bdynamic"
libleakcheck_la_LDFLAGS = -module -avoid-version $(LIBLEAKCHECK_STATIC_LIBS)
libleakcheck_la_LIBADD = -ldl
#libleakcheck_la_SOURCES = \
# nautilus-leak-checker.c \
# nautilus-leak-checker.h \
# nautilus-leak-checker-stubs.h \
# nautilus-leak-hash-table.c \
# nautilus-leak-hash-table.h \
# nautilus-leak-symbol-lookup.c \
# nautilus-leak-symbol-lookup.h \
# $(NULL)
EXTRA_DIST = \
test-nautilus-mime-actions.c \
$(NULL)
# the link rule is here so we can remove -rpath $(libdir)
# however -
# if we leave -rpath $(libdir) here, libtool refuses to link with -liberty
# if we dont, .libs/libleakcheck.lai doesn't get generated and make install fails
# the libtool way of building libleakcheck.so is totally broken, libtool cannot
# build an .so with statically linked -liberty
libleakcheck.la: $(libleakcheck_la_OBJECTS) $(libleakcheck_la_DEPENDENCIES)
$(LINK) -rpath $(libdir) $(libleakcheck_la_LDFLAGS) $(libleakcheck_la_OBJECTS) $(libleakcheck_la_LIBADD) $(LIBS)
# LIBLEAKCHECK_STATIC_LIBS = "-Wl,-Bstatic -lbfd -liberty -Wl,-Bdynamic"
#libleakcheck_la_LDFLAGS = -module -avoid-version $(LIBLEAKCHECK_STATIC_LIBS)
#libleakcheck_la_LIBADD = -ldl
# libleakcheck.la: $(libleakcheck_la_OBJECTS) $(libleakcheck_la_DEPENDENCIES)
# $(LINK) -rpath $(libdir) $(libleakcheck_la_LDFLAGS) $(libleakcheck_la_OBJECTS) $(libleakcheck_la_LIBADD) $(LIBS)
# 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
libleakcheck.so: nautilus-leak-checker.c nautilus-leak-hash-table.c nautilus-leak-symbol-lookup.c
gcc nautilus-leak-checker.c nautilus-leak-hash-table.c nautilus-leak-symbol-lookup.c -Wall -o $@ -shared -I/gnome/include -I/gnome/lib/glib/include -L/gnome/lib -lglib -lpthread -ldl -Wl,-Bstatic -lbfd -liberty -Wl,-Bdynamic
install: libleakcheck.so
cp -f libleakcheck.so $(DESTDIR)$(libdir)

View file

@ -599,91 +599,94 @@ nautilus_leak_checker_init (const char *path)
/* normally disabled */
static void
allocate_lots(int count)
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, g_malloc (rand() % 256));
list = g_list_prepend (list, NULL);
}
for (p = list; p != NULL; p = p->next) {
g_free (p->data);
// g_free (p->data);
p->data = NULL;
}
g_list_free (list);
}
static void
leak_mem2(void)
leak_mem2 (void)
{
int i;
for (i = 0; i < 40; i++) {
g_strdup("bla");
// g_strdup("bla");
}
allocate_lots (128);
// allocate_lots (1280);
}
static void
leak_mem(void)
leak_mem (void)
{
int i;
for (i = 0; i < 1010; i++) {
malloc(13);
// malloc(13);
}
leak_mem2();
allocate_lots (200);
// allocate_lots (200);
}
int
main (int argc, char **argv)
{
void *non_leak;
void *leak;
// void *non_leak;
// void *leak;
int i;
nautilus_leak_checker_init (*argv);
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 = 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 = 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);
// 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 = malloc(13);
}
leak_mem();
leak_mem2();
for (i = 0; i < 100; i++) {
allocate_lots(rand() % 40);
}
allocate_lots (1);
// for (i = 0; i < 100; i++) {
// allocate_lots(rand() % 40);
// }
printf("done\n");
nautilus_leak_print_leaks (6, 12, 20, TRUE);

View file

@ -22,7 +22,7 @@
based on MemProf by Owen Taylor, <otaylor@redhat.com>
*/
#define _GNU_SOURCE
#define _GNU_SOURCE
/* need this for dladdr */
#include "nautilus-leak-symbol-lookup.h"
@ -43,17 +43,19 @@ typedef struct {
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, unsigned long offset, const char *known_function_name)
unsigned int *line)
{
const char *file;
const char *function;
address -= offset;
address -= map->start;
address -= map->text_section->vma;
if (address < 0 || address > map->text_section->_cooked_size) {
@ -68,18 +70,61 @@ nautilus_leak_find_symbol_in_map (const NautilusLeakSymbolLookupMap *map,
return FALSE;
}
if (known_function_name != NULL &&
strcmp (function, known_function_name) != 0) {
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];
guint64 start, end;
guint major, minor;
guint64 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)) {
count = sscanf (buffer, "%Lx-%Lx %15s %*x %u:%u %Lu %255s",
&start, &end, perms, &major, &minor, &inode, file);
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 = (unsigned long)start;
map->end = (unsigned long)end;
break;
}
}
}
fclose (in);
}
static NautilusLeakSymbolLookupMap *
nautilus_leak_symbol_map_load (const char *binary_path)
nautilus_leak_symbol_map_load (const char *binary_path, gboolean executable)
{
NautilusLeakSymbolLookupMap *map;
char *target = NULL;
@ -120,14 +165,17 @@ nautilus_leak_symbol_map_load (const char *binary_path)
}
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)
nautilus_leak_symbol_map_load_if_needed (const char *binary_path, gboolean executable)
{
GList *p;
NautilusLeakSymbolLookupMap *map;
@ -138,7 +186,7 @@ nautilus_leak_symbol_map_load_if_needed (const char *binary_path)
/* no need to load the symbols, already got the map */
return map;
}
return nautilus_leak_symbol_map_load (binary_path);
return nautilus_leak_symbol_map_load (binary_path, executable);
}
void
@ -173,11 +221,10 @@ nautilus_leak_find_symbol_address (void *address, char **function_name, char **s
/* 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);
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,
(unsigned long)info.dli_fbase, info.dli_sname)) {
function_name, source_file_name, line)) {
return TRUE;
}
/* just return the function name and the library binary path */
@ -192,7 +239,7 @@ nautilus_leak_find_symbol_address (void *address, char **function_name, char **s
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, 0, NULL))
source_file_name, (unsigned int *)line))
return TRUE;
}
}
@ -207,7 +254,7 @@ nautilus_leak_print_symbol_address (const char *app_path, void *address)
char *source_file_name;
int line;
nautilus_leak_symbol_map_load_if_needed (app_path);
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) {