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

📄 openbsd_malloc_linux.c

📁 关于tor匿名通信的源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
/* Version 1.83 for Linux.
 * Compilation: gcc -shared -fPIC -O2 OpenBSD_malloc_Linux.c -o malloc.so
 * Launching: LD_PRELOAD=/path/to/malloc.so firefox
 */

/*	$OpenBSD: malloc.c,v 1.83 2006/05/14 19:53:40 otto Exp $	*/

/*
 * ----------------------------------------------------------------------------
 * "THE BEER-WARE LICENSE" (Revision 42):
 * <phk@FreeBSD.ORG> wrote this file.  As long as you retain this notice you
 * can do whatever you want with this stuff. If we meet some day, and you think
 * this stuff is worth it, you can buy me a beer in return.   Poul-Henning Kamp
 * ----------------------------------------------------------------------------
 */

/*
 * Defining MALLOC_EXTRA_SANITY will enable extra checks which are
 * related to internal conditions and consistency in malloc.c. This has
 * a noticeable runtime performance hit, and generally will not do you
 * any good unless you fiddle with the internals of malloc or want
 * to catch random pointer corruption as early as possible.
 */
#ifndef	MALLOC_EXTRA_SANITY
#undef	MALLOC_EXTRA_SANITY
#endif

/*
 * Defining MALLOC_STATS will enable you to call malloc_dump() and set
 * the [dD] options in the MALLOC_OPTIONS environment variable.
 * It has no run-time performance hit, but does pull in stdio...
 */
#ifndef	MALLOC_STATS
#undef	MALLOC_STATS
#endif

/*
 * What to use for Junk.  This is the byte value we use to fill with
 * when the 'J' option is enabled.
 */
#define SOME_JUNK	0xd0	/* as in "Duh" :-) */

#include <sys/types.h>
#include <sys/time.h>
#include <sys/resource.h>
#include <sys/param.h>
#include <sys/mman.h>
#include <sys/uio.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <limits.h>
#include <errno.h>
#include <err.h>
/* For SIZE_T_MAX */
#include "torint.h"

//#include "thread_private.h"

/*
 * The basic parameters you can tweak.
 *
 * malloc_pageshift	pagesize = 1 << malloc_pageshift
 *			It's probably best if this is the native
 *			page size, but it shouldn't have to be.
 *
 * malloc_minsize	minimum size of an allocation in bytes.
 *			If this is too small it's too much work
 *			to manage them.  This is also the smallest
 *			unit of alignment used for the storage
 *			returned by malloc/realloc.
 *
 */

static int align = 0;
static size_t g_alignment = 0;

extern int __libc_enable_secure;

static int issetugid(void)
{
	if (__libc_enable_secure) return 1;
	if (getuid() != geteuid()) return 1;
	if (getgid() != getegid()) return 1;
	return 0;
}

#define PGSHIFT 12
#define MADV_FREE MADV_DONTNEED
#include <pthread.h>
static pthread_mutex_t gen_mutex = PTHREAD_MUTEX_INITIALIZER;

#define _MALLOC_LOCK_INIT() {;}
#define _MALLOC_LOCK() {pthread_mutex_lock(&gen_mutex);}
#define _MALLOC_UNLOCK() {pthread_mutex_unlock(&gen_mutex);}

#if defined(__sparc__) || defined(__alpha__)
#define	malloc_pageshift	13U
#endif
#if defined(__ia64__)
#define	malloc_pageshift	14U
#endif

#ifndef malloc_pageshift
#define malloc_pageshift	(PGSHIFT)
#endif

/*
 * No user serviceable parts behind this point.
 *
 * This structure describes a page worth of chunks.
 */
struct pginfo {
	struct pginfo	*next;	/* next on the free list */
	void		*page;	/* Pointer to the page */
	u_short		size;	/* size of this page's chunks */
	u_short		shift;	/* How far to shift for this size chunks */
	u_short		free;	/* How many free chunks */
	u_short		total;	/* How many chunk */
	u_long		bits[1];/* Which chunks are free */
};

/* How many bits per u_long in the bitmap */
#define	MALLOC_BITS	(NBBY * sizeof(u_long))

/*
 * This structure describes a number of free pages.
 */
struct pgfree {
	struct pgfree	*next;	/* next run of free pages */
	struct pgfree	*prev;	/* prev run of free pages */
	void		*page;	/* pointer to free pages */
	void		*pdir;	/* pointer to the base page's dir */
	size_t		size;	/* number of bytes free */
};

/*
 * Magic values to put in the page_directory
 */
#define MALLOC_NOT_MINE	((struct pginfo*) 0)
#define MALLOC_FREE	((struct pginfo*) 1)
#define MALLOC_FIRST	((struct pginfo*) 2)
#define MALLOC_FOLLOW	((struct pginfo*) 3)
#define MALLOC_MAGIC	((struct pginfo*) 4)

#ifndef malloc_minsize
#define malloc_minsize			16UL
#endif

#if !defined(malloc_pagesize)
#define malloc_pagesize			(1UL<<malloc_pageshift)
#endif

#if ((1UL<<malloc_pageshift) != malloc_pagesize)
#error	"(1UL<<malloc_pageshift) != malloc_pagesize"
#endif

#ifndef malloc_maxsize
#define malloc_maxsize			((malloc_pagesize)>>1)
#endif

/* A mask for the offset inside a page. */
#define malloc_pagemask	((malloc_pagesize)-1)

#define	pageround(foo)	(((foo) + (malloc_pagemask)) & ~malloc_pagemask)
#define	ptr2index(foo)	(((u_long)(foo) >> malloc_pageshift)+malloc_pageshift)
#define	index2ptr(idx)	((void*)(((idx)-malloc_pageshift)<<malloc_pageshift))

/* Set when initialization has been done */
static unsigned int	malloc_started;

/* Number of free pages we cache */
static unsigned int	malloc_cache = 16;

/* Structure used for linking discrete directory pages. */
struct pdinfo {
	struct pginfo	**base;
	struct pdinfo	*prev;
	struct pdinfo	*next;
	u_long		dirnum;
};
static struct pdinfo *last_dir;	/* Caches to the last and previous */
static struct pdinfo *prev_dir;	/* referenced directory pages. */

static size_t	pdi_off;
static u_long	pdi_mod;
#define	PD_IDX(num)	((num) / (malloc_pagesize/sizeof(struct pginfo *)))
#define	PD_OFF(num)	((num) & ((malloc_pagesize/sizeof(struct pginfo *))-1))
#define	PI_IDX(index)	((index) / pdi_mod)
#define	PI_OFF(index)	((index) % pdi_mod)

/* The last index in the page directory we care about */
static u_long	last_index;

/* Pointer to page directory. Allocated "as if with" malloc */
static struct pginfo **page_dir;

/* Free pages line up here */
static struct pgfree free_list;

/* Abort(), user doesn't handle problems. */
static int	malloc_abort = 2;

/* Are we trying to die ? */
static int	suicide;

#ifdef MALLOC_STATS
/* dump statistics */
static int	malloc_stats;
#endif

/* avoid outputting warnings? */
static int	malloc_silent;

/* always realloc ? */
static int	malloc_realloc;

/* mprotect free pages PROT_NONE? */
static int	malloc_freeprot;

/* use guard pages after allocations? */
static size_t	malloc_guard = 0;
static size_t	malloc_guarded;
/* align pointers to end of page? */
static int	malloc_ptrguard;

static int	malloc_hint = 1;

/* xmalloc behaviour ? */
static int	malloc_xmalloc;

/* zero fill ? */
static int	malloc_zero;

/* junk fill ? */
static int	malloc_junk;

#ifdef __FreeBSD__
/* utrace ? */
static int	malloc_utrace;

struct ut {
	void		*p;
	size_t		s;
	void		*r;
};

void		utrace(struct ut *, int);

#define UTRACE(a, b, c) \
	if (malloc_utrace) \
		{struct ut u; u.p=a; u.s = b; u.r=c; utrace(&u, sizeof u);}
#else				/* !__FreeBSD__ */
#define UTRACE(a,b,c)
#endif

/* Status of malloc. */
static int	malloc_active;

/* Allocated memory. */
static size_t	malloc_used;

/* My last break. */
static caddr_t	malloc_brk;

/* One location cache for free-list holders. */
static struct pgfree *px;

/* Compile-time options. */
char		*malloc_options;

/* Name of the current public function. */
static char	*malloc_func;

#define MMAP(size) \
	mmap((void *)0, (size), PROT_READ|PROT_WRITE, MAP_ANON|MAP_PRIVATE, \
	    -1, (off_t)0)

/*
 * Necessary function declarations.
 */
static void	*imalloc(size_t size);
static void	ifree(void *ptr);
static void	*irealloc(void *ptr, size_t size);
static void	*malloc_bytes(size_t size);

/*
 * Function for page directory lookup.
 */
static int
pdir_lookup(u_long index, struct pdinfo ** pdi)
{
	struct pdinfo	*spi;
	u_long		pidx = PI_IDX(index);

	if (last_dir != NULL && PD_IDX(last_dir->dirnum) == pidx)
		*pdi = last_dir;
	else if (prev_dir != NULL && PD_IDX(prev_dir->dirnum) == pidx)
		*pdi = prev_dir;
	else if (last_dir != NULL && prev_dir != NULL) {
		if ((PD_IDX(last_dir->dirnum) > pidx) ?
		    (PD_IDX(last_dir->dirnum) - pidx) :
		    (pidx - PD_IDX(last_dir->dirnum))
		    < (PD_IDX(prev_dir->dirnum) > pidx) ?
		    (PD_IDX(prev_dir->dirnum) - pidx) :
		    (pidx - PD_IDX(prev_dir->dirnum)))
			*pdi = last_dir;
		else
			*pdi = prev_dir;

		if (PD_IDX((*pdi)->dirnum) > pidx) {
			for (spi = (*pdi)->prev;
			    spi != NULL && PD_IDX(spi->dirnum) > pidx;
			    spi = spi->prev)
				*pdi = spi;
			if (spi != NULL)
				*pdi = spi;
		} else
			for (spi = (*pdi)->next;
			    spi != NULL && PD_IDX(spi->dirnum) <= pidx;
			    spi = spi->next)
				*pdi = spi;
	} else {
		*pdi = (struct pdinfo *) ((caddr_t) page_dir + pdi_off);
		for (spi = *pdi;
		    spi != NULL && PD_IDX(spi->dirnum) <= pidx;
		    spi = spi->next)
			*pdi = spi;
	}

	return ((PD_IDX((*pdi)->dirnum) == pidx) ? 0 :
	    (PD_IDX((*pdi)->dirnum) > pidx) ? 1 : -1);
}

#ifdef MALLOC_STATS
void
malloc_dump(int fd)
{
	char		buf[1024];
	struct pginfo	**pd;
	struct pgfree	*pf;
	struct pdinfo	*pi;
	u_long		j;

	pd = page_dir;
	pi = (struct pdinfo *) ((caddr_t) pd + pdi_off);

	/* print out all the pages */
	for (j = 0; j <= last_index;) {
		snprintf(buf, sizeof buf, "%08lx %5lu ", j << malloc_pageshift, j);
		write(fd, buf, strlen(buf));
		if (pd[PI_OFF(j)] == MALLOC_NOT_MINE) {
			for (j++; j <= last_index && pd[PI_OFF(j)] == MALLOC_NOT_MINE;) {
				if (!PI_OFF(++j)) {
					if ((pi = pi->next) == NULL ||
					    PD_IDX(pi->dirnum) != PI_IDX(j))
						break;
					pd = pi->base;
					j += pdi_mod;
				}
			}
			j--;
			snprintf(buf, sizeof buf, ".. %5lu not mine\n", j);
			write(fd, buf, strlen(buf));
		} else if (pd[PI_OFF(j)] == MALLOC_FREE) {
			for (j++; j <= last_index && pd[PI_OFF(j)] == MALLOC_FREE;) {
				if (!PI_OFF(++j)) {
					if ((pi = pi->next) == NULL ||
					    PD_IDX(pi->dirnum) != PI_IDX(j))
						break;
					pd = pi->base;
					j += pdi_mod;
				}
			}
			j--;
			snprintf(buf, sizeof buf, ".. %5lu free\n", j);
			write(fd, buf, strlen(buf));
		} else if (pd[PI_OFF(j)] == MALLOC_FIRST) {
			for (j++; j <= last_index && pd[PI_OFF(j)] == MALLOC_FOLLOW;) {
				if (!PI_OFF(++j)) {
					if ((pi = pi->next) == NULL ||
					    PD_IDX(pi->dirnum) != PI_IDX(j))
						break;
					pd = pi->base;
					j += pdi_mod;
				}
			}
			j--;
			snprintf(buf, sizeof buf, ".. %5lu in use\n", j);
			write(fd, buf, strlen(buf));
		} else if (pd[PI_OFF(j)] < MALLOC_MAGIC) {
			snprintf(buf, sizeof buf, "(%p)\n", pd[PI_OFF(j)]);
			write(fd, buf, strlen(buf));
		} else {
			snprintf(buf, sizeof buf, "%p %d (of %d) x %d @ %p --> %p\n",
			    pd[PI_OFF(j)], pd[PI_OFF(j)]->free,
			    pd[PI_OFF(j)]->total, pd[PI_OFF(j)]->size,
			    pd[PI_OFF(j)]->page, pd[PI_OFF(j)]->next);
			write(fd, buf, strlen(buf));
		}
		if (!PI_OFF(++j)) {
			if ((pi = pi->next) == NULL)
				break;
			pd = pi->base;
			j += (1 + PD_IDX(pi->dirnum) - PI_IDX(j)) * pdi_mod;
		}
	}

	for (pf = free_list.next; pf; pf = pf->next) {
		snprintf(buf, sizeof buf, "Free: @%p [%p...%p[ %ld ->%p <-%p\n",
		    pf, pf->page, (char *)pf->page + pf->size,
		    pf->size, pf->prev, pf->next);
		write(fd, buf, strlen(buf));
		if (pf == pf->next) {
			snprintf(buf, sizeof buf, "Free_list loops\n");
			write(fd, buf, strlen(buf));
			break;
		}
	}

	/* print out various info */
	snprintf(buf, sizeof buf, "Minsize\t%lu\n", malloc_minsize);
	write(fd, buf, strlen(buf));
	snprintf(buf, sizeof buf, "Maxsize\t%lu\n", malloc_maxsize);
	write(fd, buf, strlen(buf));
	snprintf(buf, sizeof buf, "Pagesize\t%lu\n", malloc_pagesize);
	write(fd, buf, strlen(buf));
	snprintf(buf, sizeof buf, "Pageshift\t%u\n", malloc_pageshift);
	write(fd, buf, strlen(buf));
	snprintf(buf, sizeof buf, "In use\t%lu\n", (u_long) malloc_used);
	write(fd, buf, strlen(buf));
	snprintf(buf, sizeof buf, "Guarded\t%lu\n", (u_long) malloc_guarded);
	write(fd, buf, strlen(buf));
}
#endif /* MALLOC_STATS */

extern char	*__progname;

static void
wrterror(char *p)
{
	char		*q = " error: ";
	struct iovec	iov[5];

	iov[0].iov_base = __progname;
	iov[0].iov_len = strlen(__progname);
	iov[1].iov_base = malloc_func;
	iov[1].iov_len = strlen(malloc_func);
	iov[2].iov_base = q;
	iov[2].iov_len = strlen(q);
	iov[3].iov_base = p;
	iov[3].iov_len = strlen(p);
	iov[4].iov_base = "\n";
	iov[4].iov_len = 1;
	writev(STDERR_FILENO, iov, 5);

	suicide = 1;
#ifdef MALLOC_STATS
	if (malloc_stats)
		malloc_dump(STDERR_FILENO);
#endif /* MALLOC_STATS */
	malloc_active--;
	if (malloc_abort)
		abort();
}

static void
wrtwarning(char *p)
{
	char		*q = " warning: ";
	struct iovec	iov[5];

	if (malloc_abort)
		wrterror(p);
	else if (malloc_silent)
		return;

	iov[0].iov_base = __progname;
	iov[0].iov_len = strlen(__progname);
	iov[1].iov_base = malloc_func;
	iov[1].iov_len = strlen(malloc_func);
	iov[2].iov_base = q;
	iov[2].iov_len = strlen(q);
	iov[3].iov_base = p;
	iov[3].iov_len = strlen(p);
	iov[4].iov_base = "\n";
	iov[4].iov_len = 1;
	
	writev(STDERR_FILENO, iov, 5);
}

#ifdef MALLOC_STATS
static void
malloc_exit(void)
{
	char	*q = "malloc() warning: Couldn't dump stats\n";
	int	save_errno = errno, fd;

	fd = open("malloc.out", O_RDWR|O_APPEND);
	if (fd != -1) {
		malloc_dump(fd);
		close(fd);
	} else
		write(STDERR_FILENO, q, strlen(q));
	errno = save_errno;
}

⌨️ 快捷键说明

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