📄 malloc.c
字号:
bdesc->freeptr = *((void **) (((char *)retval)+sizeof(struct hdr_start)));
#else
bdesc->freeptr = *((void **) retval);
#endif
bdesc->refcnt++;
restore_flags(flags); /* OK, we're safe again */
#ifdef CONFIG_DEBUG_MALLOC
{
struct hdr_start *hd;
struct hdr_end *he;
hd = (struct hdr_start *) retval;
retval = hd+1;
len -= sizeof(struct hdr_start)+sizeof(struct hdr_end);
if(hd->magic != DEB_MAGIC_FREE && hd->magic != DEB_MAGIC_FREED) {
printk("DEB_MALLOC allocating %s block 0x%x (head 0x%x) from %s:%d, magic %x\n",
(hd->magic == DEB_MAGIC_ALLOC) ? "nonfree" : "trashed",
retval,hd,deb_file,deb_line,hd->magic);
return NULL;
}
if(len > hd->size || len > bdir->size-sizeof(struct hdr_start)-sizeof(struct hdr_end)) {
printk("DEB_MALLOC got %x:%x-byte block, wanted %x, from %s:%d, last %s:%d\n",
hd->size,bdir->size,len,hd->file,hd->line,deb_file,deb_line);
return NULL;
}
{
unsigned char *x = (unsigned char *) retval;
unsigned short pos = 4;
x += pos;
while(pos < hd->size) {
if(*x++ != 0xF8) {
printk("DEB_MALLOC used 0x%x:%x(%x) while free, from %s:%d\n",
retval,pos,hd->size,hd->file,hd->line);
return NULL;
}
pos++;
}
}
he = (struct hdr_end *)(((char *)retval)+hd->size);
if(he->magic != DEB_MAGIC_END) {
printk("DEB_MALLOC overran 0x%x:%d while free, from %s:%d\n",retval,hd->size,hd->file,hd->line);
}
memset(retval, 0xf0, len);
he = (struct hdr_end *)(((char *)retval)+len);
hd->file = hd->ok_file = deb_file;
hd->line = hd->ok_line = deb_line;
hd->size = len;
hd->magic = DEB_MAGIC_ALLOC;
he->magic = DEB_MAGIC_END;
}
#endif
return retval;
too_large:
/* This should be changed for sizes > 1 page. */
printk("kmalloc called with impossibly large argument (%d)\n", len);
return NULL;
}
#ifdef CONFIG_DEBUG_MALLOC
void deb_kcheck_s(const char *deb_file, unsigned short deb_line,
void *obj, int size)
{
struct hdr_start *hd;
struct hdr_end *he;
if (!obj)
return;
hd = (struct hdr_start *) obj;
hd--;
if(hd->magic != DEB_MAGIC_ALLOC) {
if(hd->magic == DEB_MAGIC_FREE) {
printk("DEB_MALLOC Using free block of 0x%x at %s:%d, by %s:%d, wasOK %s:%d\n",
obj,deb_file,deb_line,hd->file,hd->line,hd->ok_file,hd->ok_line);
/* For any other condition it is either superfluous or dangerous to print something. */
hd->magic = DEB_MAGIC_FREED;
}
return;
}
if(hd->size != size) {
if(size != 0) {
printk("DEB_MALLOC size for 0x%x given as %d, stored %d, at %s:%d, wasOK %s:%d\n",
obj,size,hd->size,deb_file,deb_line,hd->ok_file,hd->ok_line);
}
size = hd->size;
}
he = (struct hdr_end *)(((char *)obj)+size);
if(he->magic != DEB_MAGIC_END) {
printk("DEB_MALLOC overran block 0x%x:%d, at %s:%d, wasOK %s:%d\n",
obj,hd->size,deb_file,deb_line,hd->ok_file,hd->ok_line);
hd->magic = DEB_MAGIC_USED;
return;
}
hd->ok_file = deb_file;
hd->ok_line = deb_line;
}
#endif
/*
* Here is the kfree routine. If you know the size of the object that you
* are freeing, then kfree_s() will use that information to speed up the
* search for the bucket descriptor.
*
* We will #define a macro so that "kfree(x)" is becomes "kfree_s(x, 0)"
*/
#ifdef CONFIG_DEBUG_MALLOC
void deb_kfree_s(const char *deb_file, unsigned short deb_line,
void *obj, int size)
#else
void kfree_s(void *obj, int size)
#endif
{
unsigned long flags;
void *page;
struct _bucket_dir *bdir;
struct bucket_desc *bdesc, *prev;
if (!obj)
return;
#ifdef CONFIG_DEBUG_MALLOC
{
struct hdr_start *hd;
struct hdr_end *he;
hd = (struct hdr_start *) obj;
hd--;
if(hd->magic == DEB_MAGIC_FREE) {
printk("DEB_MALLOC dup free of 0x%x at %s:%d by %s:%d, wasOK %s:%d\n",
obj,deb_file,deb_line,hd->file,hd->line,hd->ok_file,hd->ok_line);
return;
}
if(hd->size != size) {
if(size != 0) {
if(hd->magic != DEB_MAGIC_USED)
printk("DEB_MALLOC size for 0x%x given as %d, stored %d, at %s:%d, wasOK %s:%d\n",
obj,size,hd->size,deb_file,deb_line,hd->ok_file,hd->ok_line);
}
size = hd->size;
}
he = (struct hdr_end *)(((char *)obj)+size);
if(he->magic != DEB_MAGIC_END) {
if(hd->magic != DEB_MAGIC_USED)
printk("DEB_MALLOC overran block 0x%x:%d, at %s:%d, from %s:%d, wasOK %s:%d\n",
obj,hd->size,deb_file,deb_line,hd->file,hd->line,hd->ok_file,hd->ok_line);
}
size += sizeof(struct hdr_start)+sizeof(struct hdr_end);
}
#endif
save_flags(flags);
/* Calculate what page this object lives in */
page = (void *) ((unsigned long) obj & PAGE_MASK);
/* Now search the buckets looking for that page */
for (bdir = bucket_dir; bdir->size; bdir++) {
prev = 0;
/* If size is zero then this conditional is always true */
if (bdir->size >= size) {
/* We have to turn off interrupts here because
we are descending the chain. If something
changes it in the middle we could suddenly
find ourselves descending the free list.
I think this would only cause a memory
leak, but better safe than sorry. */
cli(); /* To avoid race conditions */
for (bdesc = bdir->chain; bdesc; bdesc = bdesc->next) {
if (bdesc->page == page)
goto found;
prev = bdesc;
}
}
}
restore_flags(flags);
printk("Bad address passed to kernel kfree_s(%p, %d)\n",obj, size);
#ifdef CONFIG_DEBUG_MALLOC
printk("Offending code: %s:%d\n",deb_file,deb_line);
#else
printk("Offending eip: %08x\n",((unsigned long *) &obj)[-1]);
#endif
return;
found:
/* interrupts are off here. */
#ifdef CONFIG_DEBUG_MALLOC
{
struct hdr_start *hd;
struct hdr_end *he;
hd = (struct hdr_start *) obj;
hd--;
hd->file = deb_file;
hd->line = deb_line;
hd->magic = DEB_MAGIC_FREE;
hd->size = bdir->size-sizeof(struct hdr_start)-sizeof(struct hdr_end);
he = (struct hdr_end *)(((char *)obj)+hd->size);
memset(obj, 0xf8, hd->size);
he->magic = DEB_MAGIC_END;
*((void **)obj) = bdesc->freeptr;
obj = hd;
}
#else
*((void **)obj) = bdesc->freeptr;
#endif
bdesc->freeptr = obj;
bdesc->refcnt--;
if (bdesc->refcnt == 0) {
/*
* We need to make sure that prev is still accurate. It
* may not be, if someone rudely interrupted us....
*/
if ((prev && (prev->next != bdesc)) ||
(!prev && (bdir->chain != bdesc)))
for (prev = bdir->chain; prev; prev = prev->next)
if (prev->next == bdesc)
break;
if (prev)
prev->next = bdesc->next;
else {
if (bdir->chain != bdesc)
panic("kmalloc bucket chains corrupted");
bdir->chain = bdesc->next;
}
bdesc->next = free_bucket_desc;
free_bucket_desc = bdesc;
free_page((unsigned long) bdesc->page);
}
restore_flags(flags);
return;
}
#ifdef CONFIG_DEBUG_MALLOC
int get_malloc(char *buffer)
{
int len = 0;
int i;
unsigned long flags;
void *page;
struct _bucket_dir *bdir;
struct bucket_desc *bdesc;
save_flags(flags);
cli(); /* To avoid race conditions */
for (bdir = bucket_dir; bdir->size; bdir++) {
for (bdesc = bdir->chain; bdesc; bdesc = bdesc->next) {
page = bdesc->page;
for (i=PAGE_SIZE/bdir->size; i > 0 ; i--) {
struct hdr_start *hd;
hd = (struct hdr_start *)page;
if(hd->magic == DEB_MAGIC_ALLOC) {
if(len > PAGE_SIZE-80) {
restore_flags(flags);
len += sprintf(buffer+len,"...\n");
return len;
}
len += sprintf(buffer+len,"%08x:%03x %s:%d %s:%d\n",
(long)(page+sizeof(struct hdr_start)),hd->size,hd->file,hd->line,hd->ok_file,hd->ok_line);
}
page += bdir->size;
}
}
}
restore_flags(flags);
return len;
}
#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -