1 /* -*- mode: C; c-file-style: "linux" -*- */
3 /* MemProf -- memory profiler and leak detector
4 * Copyright 1999, 2000, 2001, Red Hat, Inc.
5 * Copyright 2002, Kristian Rietveld
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
30 #include <sys/types.h>
31 #include <sys/socket.h>
34 #include <sys/sysmacros.h>
36 #include <glib-object.h>
38 #include "memintercept.h"
42 #include <glib/gi18n.h>
49 static guint process_signals
[LAST_SIGNAL
] = { 0 };
51 static void mp_process_class_init (MPProcessClass
*class);
52 static void mp_process_init (MPProcess
*process
);
53 static void mp_process_finalize (GObject
*object
);
54 static void process_reinit (MPProcess
*process
);
56 #define MP_PAGE_SIZE 4096
58 /* Code to keep a queue of commands read
66 queue_compare (gconstpointer a
, gconstpointer b
)
68 const Command
*commanda
= a
;
69 const Command
*commandb
= b
;
71 return (commanda
->info
.any
.seqno
< commandb
->info
.any
.seqno
? -1 :
72 (commanda
->info
.any
.seqno
> commandb
->info
.any
.seqno
? 1 : 0));
76 queue_command (MPProcess
*process
, MIInfo
*info
, StackNode
*stack
)
78 Command
*command
= g_new (Command
, 1);
79 command
->info
= *info
;
80 command
->stack
= stack
;
82 process
->command_queue
= g_list_insert_sorted (process
->command_queue
, command
, queue_compare
);
86 unqueue_command (MPProcess
*process
, MIInfo
*info
, StackNode
**stack
)
88 Command
*command
= process
->command_queue
->data
;
91 if (command
->info
.any
.seqno
== process
->seqno
) {
92 *stack
= command
->stack
;
93 *info
= command
->info
;
95 tmp_list
= process
->command_queue
;
96 process
->command_queue
= g_list_remove_link (process
->command_queue
, tmp_list
);
98 g_list_free_1 (tmp_list
);
105 /************************************************************
107 ************************************************************/
110 block_unref (Block
*block
)
113 if (block
->refcount
== 0)
117 /************************************************************
118 * Code to map addresses to object files
119 ************************************************************/
127 prepare_map (Map
*map
)
129 g_return_if_fail (!map
->prepared
);
131 map
->binfile
= bin_file_new (map
->name
);
133 map
->prepared
= TRUE
;
137 process_read_maps (MPProcess
*process
)
142 snprintf (buffer
, 1023, "/proc/%d/maps", process
->pid
);
144 in
= fopen (buffer
, "r");
146 if (process
->map_list
) {
147 g_list_foreach (process
->map_list
, (GFunc
)g_free
, NULL
);
148 g_list_free (process
->map_list
);
150 process
->map_list
= NULL
;
153 while (fgets(buffer
, 1023, in
)) {
162 buffer
, "%lx-%lx %*15s %lx %*x:%*x %lu %255s",
163 &start
, &end
, &offset
, &inode
, file
);
168 map
= g_new (Map
, 1);
169 map
->prepared
= FALSE
;
171 map
->size
= end
- start
;
173 map
->offset
= offset
;
175 map
->name
= g_strdup (file
);
177 process
->map_list
= g_list_prepend (process
->map_list
, map
);
185 real_locate_map (MPProcess
*process
, guint addr
)
187 GList
*tmp_list
= process
->map_list
;
191 Map
*tmp_map
= tmp_list
->data
;
193 if ((addr
>= tmp_map
->start
) &&
194 (addr
< tmp_map
->start
+ tmp_map
->size
))
197 tmp_list
= tmp_list
->next
;
204 locate_map (MPProcess
*process
, guint addr
)
206 Map
*map
= real_locate_map (process
, addr
);
209 gpointer page_addr
= (gpointer
) (addr
- addr
% MP_PAGE_SIZE
);
210 if (g_list_find (process
->bad_pages
, page_addr
))
213 process_read_maps (process
);
215 map
= real_locate_map (process
, addr
);
218 process
->bad_pages
= g_list_prepend (process
->bad_pages
, page_addr
);
230 process_locate_symbol (MPProcess
*process
, gsize addr
)
232 Map
*map
= locate_map (process
, addr
);
233 const BinSymbol
*symbol
;
236 return "<unknown map>";
241 symbol
= bin_file_lookup_symbol (map
->binfile
, addr
);
243 return bin_symbol_get_name (map
->binfile
, symbol
);
247 * The string assigned to functionname is owned/shared
248 * by the system and must not be freed.
251 process_find_line (MPProcess
*process
, void *address
,
252 const char **filename
, char **functionname
,
255 const char *s
= process_locate_symbol (process
, GPOINTER_TO_SIZE (address
));
260 *functionname
= (char*)s
;
268 process_dump_stack (MPProcess
*process
, FILE *out
, StackNode
*stack
)
270 for (; stack
!= NULL
; stack
= stack
->parent
)
272 const char *filename
;
276 if (process_find_line (process
, stack
->address
,
277 &filename
, &functionname
, &line
)) {
279 fprintf(out
, "\t%s(): %s:%u\n", functionname
, filename
, line
);
281 fprintf(out
, "\t%s()\n", functionname
);
283 fprintf(out
, "\t[%p]\n", stack
->address
);
289 process_map_sections (Map
*map
, SectionFunc func
, gpointer user_data
)
291 /* FIXME: this should be reinstated */
297 for (section
= map
->abfd
->sections
; section
; section
= section
->next
) {
298 if (strcmp (section
->name
, ".bss") == 0 ||
299 strcmp (section
->name
, ".data") == 0) {
300 void *addr
= (void *)section
->vma
;
304 /* bfd_section_size() gives 0 for old versions of binutils, so peek
305 * into the internals instead. :-(
307 (*func
) (addr
, bfd_section_size (map
->abfd
, section
), user_data
);
308 // (*func) (addr, section->_cooked_size, user_data);
315 process_sections (MPProcess
*process
, SectionFunc func
, gpointer user_data
)
319 process_read_maps (process
);
321 tmp_list
= process
->map_list
;
324 Map
*map
= tmp_list
->data
;
329 process_map_sections (map
, func
, user_data
);
330 tmp_list
= tmp_list
->next
;
334 /************************************************************
335 * Communication with subprocess
336 ************************************************************/
339 get_block_table (MPProcess
*process
)
341 if (!process
->block_table
)
342 process
->block_table
= g_hash_table_new (g_direct_hash
, NULL
);
344 return process
->block_table
;
349 process_free_block (gpointer key
, gpointer value
, gpointer data
)
355 process_duplicate_block (gpointer key
, gpointer value
, gpointer data
)
357 GHashTable
*new_table
= data
;
358 Block
*block
= value
;
362 g_hash_table_insert (new_table
, key
, value
);
366 process_duplicate (MPProcess
*process
)
368 MPProcess
*new_process
= process_new (process
->server
);
370 if (process
->block_table
) {
371 GHashTable
*new_block_table
= get_block_table(new_process
);
373 g_hash_table_foreach (process
->block_table
,
374 process_duplicate_block
,
378 new_process
->bytes_used
= process
->bytes_used
;
379 new_process
->n_allocations
= process
->n_allocations
;
380 new_process
->seqno
= process
->seqno
;
382 new_process
->parent
= process
;
388 process_reinit (MPProcess
*process
)
390 process_stop_input (process
);
392 if (process
->input_channel
) {
393 g_io_channel_unref (process
->input_channel
);
394 process
->input_channel
= NULL
;
397 process
->bytes_used
= 0;
398 process
->n_allocations
= 0;
401 if (process
->map_list
) {
402 g_list_foreach (process
->map_list
, (GFunc
)g_free
, NULL
);
403 g_list_free (process
->map_list
);
405 process
->map_list
= NULL
;
408 if (process
->bad_pages
) {
409 g_list_free (process
->bad_pages
);
410 process
->bad_pages
= NULL
;
413 if (process
->block_table
) {
414 g_hash_table_foreach (process
->block_table
, process_free_block
, NULL
);
415 g_hash_table_destroy (process
->block_table
);
416 process
->block_table
= NULL
;
419 if (process
->stack_stash
) {
420 stack_stash_unref (process
->stack_stash
);
421 process
->stack_stash
= NULL
;
425 process
->command_queue
= NULL
;
429 get_stack_stash (MPProcess
*process
)
431 if (!process
->stack_stash
)
432 process
->stack_stash
= stack_stash_new (NULL
);
434 return process
->stack_stash
;
438 process_exec_reset (MPProcess
*process
)
440 process_reinit (process
);
441 g_signal_emit_by_name (process
, "reset");
445 process_command (MPProcess
*process
, MIInfo
*info
, StackNode
*stack
)
447 GHashTable
*block_table
;
450 if (info
->any
.seqno
!= process
->seqno
) {
451 queue_command (process
, info
, stack
);
459 switch (info
->operation
) {
464 g_assert_not_reached ();
468 /* Handled before, ignore */
472 info
->alloc
.old_ptr
= NULL
;
473 info
->alloc
.new_ptr
= (void *)process
->seqno
;
474 info
->alloc
.size
= 1;
477 default: /* MALLOC / REALLOC / FREE */
478 block_table
= get_block_table (process
);
480 if (info
->alloc
.old_ptr
!= NULL
) {
481 block
= g_hash_table_lookup (block_table
, info
->alloc
.old_ptr
);
483 g_warning ("Block %p not found (pid=%d)!\n", info
->alloc
.old_ptr
, process
->pid
);
484 process_dump_stack (process
, stderr
, stack
);
487 g_hash_table_remove (block_table
, info
->alloc
.old_ptr
);
488 process
->bytes_used
-= block
->size
;
491 process
->n_allocations
--;
495 /* We need to lookup before inserting, because realloc() can call malloc(), so we
496 * see the same block twice. The same problem comes upduring malloc initialization
497 * where __libc_malloc() is called twice for the same block. We could optimize
498 * things a bit by using g_hash_table_new_full() to catch the replacement when
499 * it happens and free the old block, but that would make keeping track of
500 * process->n_allocations/bytes_used a little difficult.
503 if (info
->alloc
.new_ptr
&& !g_hash_table_lookup (block_table
, info
->alloc
.new_ptr
)) {
504 block
= g_new (Block
, 1);
508 block
->addr
= info
->alloc
.new_ptr
;
509 block
->size
= info
->alloc
.size
;
510 block
->stack
= stack
;
512 process
->n_allocations
++;
513 process
->bytes_used
+= info
->alloc
.size
;
515 g_hash_table_insert (block_table
, info
->alloc
.new_ptr
, block
);
519 while (process
->command_queue
&& unqueue_command (process
, info
, &stack
))
520 process_command (process
, info
, stack
);
524 input_func (GIOChannel
*source
,
525 GIOCondition condition
,
530 MPProcess
*input_process
= data
;
531 MPProcess
*process
= NULL
;
534 memset (&info
, 0, sizeof (info
));
537 if (g_io_channel_get_flags(source
) & G_IO_FLAG_IS_READABLE
)
538 g_io_channel_read_chars (source
, (char *)&info
, sizeof(info
), &count
, NULL
);
541 g_io_channel_unref (input_process
->input_channel
);
542 input_process
->input_channel
= NULL
;
544 mp_server_remove_process (input_process
->server
, input_process
);
545 process_set_status (input_process
, MP_PROCESS_DEFUNCT
);
549 StackNode
*stack
= NULL
;
551 // fprintf (stderr, "Read size %d op 0x%x\n", count, info.operation);
553 if (info
.operation
== MI_MALLOC
||
554 info
.operation
== MI_REALLOC
||
555 info
.operation
== MI_FREE
||
556 info
.operation
== MI_TIME
) {
557 void **stack_buffer
= NULL
;
558 StackStash
*stash
= get_stack_stash (input_process
);
560 g_assert (count
>= sizeof (MIInfoAlloc
));
562 stack_buffer
= g_alloca (sizeof (void *) * info
.alloc
.stack_size
);
563 g_io_channel_read_chars (source
, (char *)stack_buffer
, sizeof(void *) * info
.alloc
.stack_size
, &count
, NULL
);
564 stack
= stack_stash_add_trace (stash
, stack_buffer
, info
.alloc
.stack_size
, -1);
566 } else if (info
.operation
== MI_EXIT
) {
567 process_set_status (input_process
, MP_PROCESS_EXITING
);
568 if (input_process
->clone_of
)
569 process_detach (input_process
);
572 process
= input_process
;
573 while (process
->clone_of
)
574 process
= process
->clone_of
;
576 process_command (process
, &info
, stack
);
579 /* if (info.any.pid != input_process->pid)
580 g_warning ("Ow! Ow! Ow: %d %d %d!", info.any.pid, input_process->pid, g_io_channel_unix_get_fd (input_process->input_channel)); */
583 } while (info
.operation
!= MI_EXIT
&& (g_io_channel_get_buffer_condition(source
) & G_IO_IN
));
589 process_stop_input (MPProcess
*process
)
591 g_return_if_fail (process
!= NULL
);
593 if (process
->input_tag
) {
594 g_source_remove (process
->input_tag
);
595 process
->input_tag
= 0;
600 process_start_input (MPProcess
*process
)
602 g_return_if_fail (process
!= NULL
);
604 if (!process
->input_tag
&& process
->input_channel
)
605 process
->input_tag
= g_io_add_watch_full (process
->input_channel
,
607 G_IO_IN
| G_IO_PRI
| G_IO_ERR
| G_IO_HUP
| G_IO_NVAL
,
608 input_func
, process
, NULL
);
612 process_clear_input (MPProcess
*process
)
614 g_return_if_fail (process
!= NULL
);
616 process
->bytes_used
= 0;
617 process
->n_allocations
= 0;
619 if (process
->map_list
) {
620 g_list_foreach (process
->map_list
, (GFunc
)g_free
, NULL
);
621 g_list_free (process
->map_list
);
623 process
->map_list
= NULL
;
626 if (process
->bad_pages
) {
627 g_list_free (process
->bad_pages
);
628 process
->bad_pages
= NULL
;
631 if (process
->block_table
) {
632 g_hash_table_foreach (process
->block_table
, process_free_block
, NULL
);
633 g_hash_table_destroy (process
->block_table
);
634 process
->block_table
= NULL
;
637 if (process
->stack_stash
) {
638 stack_stash_unref (process
->stack_stash
);
639 process
->stack_stash
= NULL
;
644 process_find_exec (char **args
)
648 if (g_file_test(args
[0], G_FILE_TEST_EXISTS
)) {
649 if (!g_path_is_absolute (args
[0]))
650 return g_strconcat ("./", args
[0], NULL
);
652 return g_strdup (args
[0]);
656 char *pathenv
= getenv ("PATH");
659 paths
= g_strsplit (pathenv
, ":", -1);
660 for (i
=0; paths
[i
]; i
++) {
661 path
= g_build_filename (paths
[i
], args
[0], NULL
);
662 if (g_file_test (path
, G_FILE_TEST_EXISTS
))
678 process_parse_exec (const char *exec_string
)
680 return g_strsplit (exec_string
, " ", -1);
684 mp_process_get_type (void)
686 static GType process_type
= 0;
689 static const GTypeInfo process_info
= {
690 sizeof (MPProcessClass
),
691 (GBaseInitFunc
) NULL
,
692 (GBaseFinalizeFunc
) NULL
,
693 (GClassInitFunc
) mp_process_class_init
,
694 NULL
, /* class_finalize */
695 NULL
, /* class_data */
698 (GInstanceInitFunc
) mp_process_init
701 process_type
= g_type_register_static (G_TYPE_OBJECT
,
710 mp_process_class_init (MPProcessClass
*class)
712 static gboolean initialized
= FALSE
;
714 GObjectClass
*o_class
= G_OBJECT_CLASS (class);
716 o_class
->finalize
= mp_process_finalize
;
719 process_signals
[STATUS_CHANGED
] =
720 g_signal_new ("status_changed",
723 G_STRUCT_OFFSET (MPProcessClass
, status_changed
),
725 g_cclosure_marshal_VOID__VOID
,
728 process_signals
[RESET
] =
729 g_signal_new ("reset",
732 G_STRUCT_OFFSET (MPProcessClass
, reset
),
734 g_cclosure_marshal_VOID__VOID
,
742 mp_process_init (MPProcess
*process
)
744 process
->status
= MP_PROCESS_INIT
;
746 process
->clone_of
= NULL
;
748 process
->bytes_used
= 0;
749 process
->n_allocations
= 0;
750 process
->block_table
= NULL
;
751 process
->stack_stash
= NULL
;
753 process
->program_name
= NULL
;
754 process
->input_channel
= NULL
;
758 process
->command_queue
= NULL
;
760 process
->follow_fork
= FALSE
;
761 process
->follow_exec
= FALSE
;
763 g_object_ref (G_OBJECT (process
));
767 mp_process_finalize (GObject
*object
)
769 MPProcess
*process
= MP_PROCESS (object
);
771 process_reinit (process
);
773 g_free (process
->program_name
);
778 process_new (MPServer
*server
)
782 process
= g_object_new (MP_TYPE_PROCESS
, NULL
);
784 process
->server
= server
;
790 process_set_follow_fork (MPProcess
*process
,
791 gboolean follow_fork
)
793 process
->follow_fork
= follow_fork
;
797 process_set_follow_exec (MPProcess
*process
,
798 gboolean follow_exec
)
800 process
->follow_exec
= follow_exec
;
804 process_run (MPProcess
*process
, const char *path
, char **args
)
806 process
->program_name
= g_strdup (path
);
809 process
->pid
= mp_server_instrument (process
->server
, path
, args
);
810 mp_server_add_process (process
->server
, process
);
812 process_set_status (process
, MP_PROCESS_STARTING
);
814 process_start_input (process
);
818 process_get_clones (MPProcess
*process
)
820 return mp_server_get_process_clones (process
->server
, process
);
824 process_set_status (MPProcess
*process
, MPProcessStatus status
)
826 if (process
->status
!= status
) {
827 process
->status
= status
;
828 g_signal_emit_by_name (process
, "status_changed", NULL
);
833 process_get_status_text (MPProcess
*process
)
837 switch (process
->status
) {
838 case MP_PROCESS_INIT
:
839 status
= _("Initial");
841 case MP_PROCESS_STARTING
:
842 status
= _("Starting");
844 case MP_PROCESS_RUNNING
:
845 status
= _("Running");
847 case MP_PROCESS_EXITING
:
848 status
= _("Exiting");
850 case MP_PROCESS_DEFUNCT
:
851 status
= _("Defunct");
853 case MP_PROCESS_DETACHED
:
854 status
= _("Defunct");
858 return g_strdup (status
);
862 process_get_cmdline (MPProcess
*process
)
870 if (process
->status
== MP_PROCESS_DEFUNCT
)
871 return g_strdup ("");
873 fname
= g_strdup_printf ("/proc/%d/cmdline", process
->pid
);
874 in
= fopen (fname
, "r");
876 g_warning ("Can't open %s\n", fname
);
877 return g_strdup ("");
881 if (getline (&tmp
, &n
, in
) == -1)
882 result
= g_strdup ("");
884 result
= g_strdup (tmp
);
894 process_detach (MPProcess
*process
)
898 if (process
->status
!= MP_PROCESS_DEFUNCT
) {
899 int fd
= g_io_channel_unix_get_fd (process
->input_channel
);
901 if (process
->status
== MP_PROCESS_EXITING
) {
903 ret
= write (fd
, &response
, 1);
905 g_io_channel_shutdown (process
->input_channel
, TRUE
, NULL
);
906 process_set_status (process
, MP_PROCESS_DETACHED
);
912 process_kill (MPProcess
*process
)
914 if (process
->status
== MP_PROCESS_EXITING
) {
915 process_detach (process
);
916 } else if (process
->status
!= MP_PROCESS_DEFUNCT
&&
917 process
->status
!= MP_PROCESS_INIT
) {
918 kill (process
->pid
, SIGTERM
);
923 MPProcessBlockForeachFunc foreach_func
;
928 block_table_foreach_func (gpointer key
,
932 BlockForeachInfo
*info
= data
;
934 info
->foreach_func (value
, info
->data
);
938 process_block_foreach (MPProcess
*process
,
939 MPProcessBlockForeachFunc foreach_func
,
942 GHashTable
*block_table
= get_block_table (process
);
943 BlockForeachInfo info
;
945 info
.foreach_func
= foreach_func
;
948 g_hash_table_foreach (block_table
, block_table_foreach_func
, &info
);
952 symbol_equal (gconstpointer s1
, gconstpointer s2
)
958 symbol_hash (gconstpointer s
)
960 const char *symbol
= s
;
962 return g_str_hash (symbol
);
966 symbol_copy (const char *orig
)
971 return (char *) orig
;
975 symbol_free (char *symbol
)