⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 process.c

📁 memprof source code, linux
💻 C
📖 第 1 页 / 共 2 页
字号:
/* -*- mode: C; c-file-style: "linux" -*- *//* MemProf -- memory profiler and leak detector * Copyright 1999, 2000, 2001, Red Hat, Inc. * Copyright 2002, Kristian Rietveld * * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *//*====*/#define _GNU_SOURCE#include <stdio.h>#include <stdlib.h>#include <errno.h>#include <signal.h>#include <string.h>#include <sys/types.h>#include <sys/socket.h>#include <sys/stat.h>#include <sys/wait.h>#include <sys/sysmacros.h>#include <glib-object.h>#include <libgnome/libgnome.h>#include "memintercept.h"#include "memprof.h"#include "process.h"#include "server.h"enum {	STATUS_CHANGED,	RESET,	LAST_SIGNAL};static guint process_signals[LAST_SIGNAL] = { 0 };static void mp_process_class_init (MPProcessClass *class);static void mp_process_init (MPProcess *process);static void mp_process_finalize (GObject *object);static void process_reinit (MPProcess *process);#define MP_PAGE_SIZE 4096/* Code to keep a queue of commands read */typedef struct {	MIInfo info;	StackElement *stack;} Command;static gintqueue_compare (gconstpointer a, gconstpointer b){	const Command *commanda = a;	const Command *commandb = b;	return (commanda->info.any.seqno < commandb->info.any.seqno ? -1 :		(commanda->info.any.seqno > commandb->info.any.seqno  ? 1 : 0));}static voidqueue_command (MPProcess *process, MIInfo *info, StackElement *stack){	Command *command = g_new (Command, 1);	command->info = *info;	command->stack = stack;	process->command_queue = g_list_insert_sorted (process->command_queue, command, queue_compare);}static gbooleanunqueue_command (MPProcess *process, MIInfo *info, StackElement **stack){	Command *command = process->command_queue->data;	GList *tmp_list;		if (command->info.any.seqno == process->seqno) {		*stack = command->stack;		*info = command->info;		tmp_list = process->command_queue;		process->command_queue = g_list_remove_link (process->command_queue, tmp_list);		g_free (command);		g_list_free_1 (tmp_list);		return TRUE;	} else		return FALSE;}/************************************************************ * Block Manipulation ************************************************************/static voidblock_unref (Block *block){	block->refcount--;	if (block->refcount == 0)		g_free (block);} /************************************************************ * Code to map addresses to object files ************************************************************/static gintcompare_address (const void *symbol1, const void *symbol2){	return (((Symbol *)symbol1)->addr < ((Symbol *)symbol2)->addr) ?		-1 : ((((Symbol *)symbol1)->addr == ((Symbol *)symbol2)->addr) ?		      0 : 1);}voidprepare_map (Map *map){	GArray *result;	Symbol symbol;	int i;	g_return_if_fail (!map->prepared);  	map->prepared = TRUE;	read_bfd (map);  	if (map->syms) {		result = g_array_new (FALSE, FALSE, sizeof(Symbol));		for (i = 0; i < map->symcount; i++) {			if (map->syms[i]->flags & BSF_FUNCTION)	{				symbol.addr = bfd_asymbol_value(map->syms[i]);				symbol.size = 0;				symbol.name = demangle (map, bfd_asymbol_name(map->syms[i]));	      				g_array_append_vals (result, &symbol, 1);			}		}		/* Sort the symbols by address */      		qsort (result->data, result->len, sizeof(Symbol), compare_address);  		map->symbols =result;	}}static voidprocess_read_maps (MPProcess *process){	gchar buffer[1024];	FILE *in;	gchar perms[26];	gchar file[256];	guint start, end, major, minor, inode;  	snprintf (buffer, 1023, "/proc/%d/maps", process->pid);	in = fopen (buffer, "r");	if (process->map_list) {		g_list_foreach (process->map_list, (GFunc)g_free, NULL);		g_list_free (process->map_list);      		process->map_list = NULL;	}	while (fgets(buffer, 1023, in)) {		int count = sscanf (buffer, "%x-%x %15s %*x %u:%u %u %255s",				    &start, &end, perms, &major, &minor, &inode, file);		if (count >= 6)	{			if (strcmp (perms, "r-xp") == 0) {				Map *map;				dev_t device = makedev(major, minor);				map = g_new (Map, 1);				map->prepared = FALSE;				map->addr = start;				map->size = end - start;				if (count == 7)					map->name = g_strdup (file);				else					map->name = locate_inode (device, inode);				map->abfd = NULL;				map->section = NULL;				map->symbols = NULL;				map->syms = NULL;				map->symcount = 0;				map->do_offset = TRUE;				if (map->name) {					struct stat stat1, stat2;					char *progname = g_strdup_printf ("/proc/%d/exe", process->pid);		  					if (stat (map->name, &stat1) != 0)						g_warning ("Cannot stat %s: %s\n", map->name,							   g_strerror (errno));					else						if (stat (progname, &stat2) != 0)							g_warning ("Cannot stat %s: %s\n", process->program_name,								   g_strerror (errno));						else							map->do_offset = !(stat1.st_ino == stat2.st_ino &&									   stat1.st_dev == stat2.st_dev);					g_free (progname);				}				process->map_list = g_list_prepend (process->map_list, map);			}		}	}	fclose (in);}static Map *real_locate_map (MPProcess *process, guint addr){	GList *tmp_list = process->map_list;	while (tmp_list)	{		Map *tmp_map = tmp_list->data;      		if ((addr >= tmp_map->addr) &&		    (addr < tmp_map->addr + tmp_map->size))			return tmp_map;      		tmp_list = tmp_list->next;	}	return NULL;}Map *locate_map (MPProcess *process, guint addr){	Map *map = real_locate_map (process, addr);	if (!map)	{		gpointer page_addr = (gpointer) (addr - addr % MP_PAGE_SIZE);		if (g_list_find (process->bad_pages, page_addr))			return NULL;		process_read_maps (process);		map = real_locate_map (process, addr);		if (!map) {			process->bad_pages = g_list_prepend (process->bad_pages, page_addr);			return NULL;		}	}	if (!map->prepared)		prepare_map (map);	return map;}Symbol *process_locate_symbol (MPProcess *process, guint addr){	Symbol *data;	Map *map;  	guint first, middle, last;	map = locate_map (process, addr);	if (!map)		return NULL;	if (!map->symbols || (map->symbols->len == 0))		return NULL;  	if (map->do_offset)		addr -= map->addr;	first = 0;	last = map->symbols->len - 1;	middle = last;	data = (Symbol *)map->symbols->data;	if (addr < data[last].addr) {		/* Invariant: data[first].addr <= val < data[last].addr */		while (first < last - 1) {			middle = (first + last) / 2;			if (addr < data[middle].addr) 				last = middle;			else				first = middle;		}		/* Size is not included in generic bfd data, so we		 * ignore it for now. (It is ELF specific)		 */		return &data[first];#if 0		if (addr < data[first].addr + data[first].size)			return &data[first];		else			return NULL;#endif	}	else	{		return &data[last];#if 0		if (addr < data[last].addr + data[last].size)			return &data[last];		else			return NULL;#endif	}}gboolean process_find_line (MPProcess *process, void *address,		   const char **filename, char **functionname,		   unsigned int *line){	Map *map = locate_map (process, (guint)address);	if (map) {		bfd_vma addr = (bfd_vma)address;		if (map->do_offset)			addr -= map->addr;		return find_line (map, addr, filename, functionname, line);	}	else		return FALSE;}voidprocess_dump_stack (MPProcess *process, FILE *out, StackElement *stack){	for (; !STACK_ELEMENT_IS_ROOT (stack); stack = stack->parent)	{		const char *filename;		char *functionname;		unsigned int line;      		if (process_find_line (process, stack->address,				       &filename, &functionname, &line)) {			if (filename)				fprintf(out, "\t%s(): %s:%u\n", functionname, filename, line);			else				fprintf(out, "\t%s()\n", functionname);			free (functionname);		} else			fprintf(out, "\t[%p]\n", stack->address);	}}void process_sections (MPProcess *process, SectionFunc func, gpointer user_data){	GList *tmp_list;	process_read_maps (process);	tmp_list = process->map_list;	while (tmp_list) {		Map *map = tmp_list->data;		if (!map->prepared)			prepare_map (map);		process_map_sections (map, func, user_data);		tmp_list = tmp_list->next;	}}/************************************************************ * Communication with subprocess ************************************************************/static voidprocess_free_block (gpointer key, gpointer value, gpointer data){	block_unref (value);}static voidprocess_duplicate_block (gpointer key, gpointer value, gpointer data){	GHashTable *new_table = data;	Block *block = value;	block->refcount++;	g_hash_table_insert (new_table, key, value);}MPProcess *process_duplicate (MPProcess *process){	MPProcess *new_process = process_new (process->server);	g_hash_table_foreach (process->block_table,			      process_duplicate_block,			      new_process->block_table);	new_process->bytes_used = process->bytes_used;	new_process->n_allocations = process->n_allocations;	new_process->seqno = process->seqno;	new_process->parent = process;	return new_process;}static voidprocess_reinit (MPProcess *process){	process_stop_input (process);	if (process->input_channel) {		g_io_channel_unref (process->input_channel);		process->input_channel = NULL;	}	process->bytes_used = 0;	process->n_allocations = 0;	process->seqno = 0;	if (process->map_list) {		g_list_foreach (process->map_list, (GFunc)g_free, NULL);		g_list_free (process->map_list);      		process->map_list = NULL;	}	if (process->bad_pages) {		g_list_free (process->bad_pages);		process->bad_pages = NULL;	}	if (process->block_table) {		g_hash_table_foreach (process->block_table, process_free_block, NULL);		g_hash_table_destroy (process->block_table);		process->block_table = NULL;	}	if (process->stack_stash) {		stack_stash_free (process->stack_stash);		process->stack_stash = NULL;	}	/* FIXME: leak */	process->command_queue = NULL;}static GHashTable *get_block_table (MPProcess *process){	if (!process->block_table)		process->block_table = g_hash_table_new (g_direct_hash, NULL);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -