- split up in libstrong, charon, stroke, testing done
- new leak detective with malloc hook in library - useable, but needs improvements - logger_manager has now a single instance per library - allows use of loggers from any linking prog - a LOT of other things
This commit is contained in:
@@ -15,10 +15,6 @@
|
||||
UTILS_DIR= $(LIB_DIR)utils/
|
||||
|
||||
|
||||
LIB_OBJS+= $(BUILD_DIR)allocator.o
|
||||
$(BUILD_DIR)allocator.o : $(UTILS_DIR)allocator.c $(UTILS_DIR)allocator.h
|
||||
$(CC) $(CFLAGS) -c -o $@ $<
|
||||
|
||||
LIB_OBJS+= $(BUILD_DIR)linked_list.o
|
||||
$(BUILD_DIR)linked_list.o : $(UTILS_DIR)linked_list.c $(UTILS_DIR)linked_list.h
|
||||
$(CC) $(CFLAGS) -c -o $@ $<
|
||||
@@ -46,3 +42,7 @@ $(BUILD_DIR)identification.o : $(UTILS_DIR)identification.c $(UTILS_DIR)identifi
|
||||
LIB_OBJS+= $(BUILD_DIR)host.o
|
||||
$(BUILD_DIR)host.o : $(UTILS_DIR)host.c $(UTILS_DIR)host.h
|
||||
$(CC) $(CFLAGS) -c -o $@ $<
|
||||
|
||||
LIB_OBJS+= $(BUILD_DIR)leak_detective.o
|
||||
$(BUILD_DIR)leak_detective.o : $(UTILS_DIR)leak_detective.c $(UTILS_DIR)leak_detective.h
|
||||
$(CC) $(CFLAGS) -c -o $@ $<
|
||||
@@ -1,445 +0,0 @@
|
||||
/**
|
||||
* @file allocator.c
|
||||
*
|
||||
* @brief Implementation of allocator_t.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2005 Jan Hutter, Martin Willi
|
||||
* Hochschule fuer Technik Rapperswil
|
||||
*
|
||||
* 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. See <http://www.fsf.org/copyleft/gpl.txt>.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
#include <pthread.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <gmp.h>
|
||||
|
||||
#include "allocator.h"
|
||||
|
||||
|
||||
#ifdef LEAK_DETECTIVE
|
||||
|
||||
typedef union memory_hdr_t memory_hdr_t;
|
||||
|
||||
/**
|
||||
* @brief Header of each allocated memory area.
|
||||
*
|
||||
* Ideas stolen from pluto's defs.c.
|
||||
*
|
||||
* Used to detect memory leaks.
|
||||
*/
|
||||
union memory_hdr_t {
|
||||
/**
|
||||
* Informations.
|
||||
*/
|
||||
struct {
|
||||
/**
|
||||
* Filename withing memory was allocated.
|
||||
*/
|
||||
const char *filename;
|
||||
/**
|
||||
* Line number in given file.
|
||||
*/
|
||||
size_t line;
|
||||
/**
|
||||
* Allocated memory size. Needed for reallocation.
|
||||
*/
|
||||
size_t size_of_memory;
|
||||
/**
|
||||
* Link to the previous and next memory area.
|
||||
*/
|
||||
memory_hdr_t *older, *newer;
|
||||
} info;
|
||||
/**
|
||||
* Force maximal alignment ?
|
||||
*
|
||||
*/
|
||||
unsigned long junk;
|
||||
};
|
||||
|
||||
typedef struct private_allocator_t private_allocator_t;
|
||||
|
||||
/**
|
||||
* @brief Private allocator_t object.
|
||||
*
|
||||
* Contains private variables of allocator_t object.
|
||||
*/
|
||||
struct private_allocator_t
|
||||
{
|
||||
/**
|
||||
* Public part of an allocator_t object.
|
||||
*/
|
||||
allocator_t public;
|
||||
|
||||
/**
|
||||
* Global list of allocations.
|
||||
*
|
||||
* Thread-save through mutex.
|
||||
*/
|
||||
memory_hdr_t *allocations;
|
||||
|
||||
/**
|
||||
* Mutex used to make sure, all functions are thread-save.
|
||||
*/
|
||||
pthread_mutex_t mutex;
|
||||
|
||||
/**
|
||||
* Number of allocations done
|
||||
*/
|
||||
u_int32_t allocs;
|
||||
|
||||
/**
|
||||
* Number of frees done
|
||||
*/
|
||||
u_int32_t frees;
|
||||
|
||||
/**
|
||||
* Allocates memory with LEAK_DETECTION and
|
||||
* returns an empty data area filled with zeros.
|
||||
*
|
||||
* @param this private_allocator_t object
|
||||
* @param bytes number of bytes to allocate
|
||||
* @param file filename from which the memory is allocated
|
||||
* @param line line number in specific file
|
||||
* @param use_mutex if FALSE no mutex is used for allocation
|
||||
* @return pointer to allocated memory area
|
||||
*/
|
||||
void * (*allocate_special) (private_allocator_t *this,size_t bytes, char * file,int line, bool use_mutex);
|
||||
};
|
||||
|
||||
/**
|
||||
* Implementation of private_allocator_t.allocate_special.
|
||||
*/
|
||||
static void *allocate_special(private_allocator_t *this,size_t bytes, char * file,int line, bool use_mutex)
|
||||
{
|
||||
memory_hdr_t *allocated_memory = malloc(sizeof(memory_hdr_t) + bytes);
|
||||
|
||||
this->allocs++;
|
||||
|
||||
if (allocated_memory == NULL)
|
||||
{
|
||||
/* TODO LOG this case */
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
if (use_mutex)
|
||||
{
|
||||
pthread_mutex_lock( &(this->mutex));
|
||||
}
|
||||
|
||||
allocated_memory->info.line = line;
|
||||
allocated_memory->info.filename = file;
|
||||
allocated_memory->info.size_of_memory = bytes;
|
||||
allocated_memory->info.older = this->allocations;
|
||||
if (this->allocations != NULL)
|
||||
{
|
||||
this->allocations->info.newer = allocated_memory;
|
||||
}
|
||||
this->allocations = allocated_memory;
|
||||
allocated_memory->info.newer = NULL;
|
||||
|
||||
/* fill memory with zero's */
|
||||
memset(allocated_memory+1, '\0', bytes);
|
||||
if (use_mutex)
|
||||
{
|
||||
pthread_mutex_unlock(&(this->mutex));
|
||||
}
|
||||
|
||||
/* real memory starts after header */
|
||||
return (allocated_memory+1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of allocator_t.allocate.
|
||||
*/
|
||||
static void * allocate(allocator_t *allocator,size_t bytes, char * file,int line)
|
||||
{
|
||||
private_allocator_t *this = (private_allocator_t *) allocator;
|
||||
return (this->allocate_special(this,bytes, file,line,TRUE));
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of allocator_t.allocate_as_chunk.
|
||||
*/
|
||||
static chunk_t allocate_as_chunk(allocator_t *allocator,size_t bytes, char * file,int line)
|
||||
{
|
||||
private_allocator_t *this = (private_allocator_t *) allocator;
|
||||
chunk_t new_chunk;
|
||||
new_chunk.ptr = this->allocate_special(this,bytes, file,line,TRUE);
|
||||
new_chunk.len = (new_chunk.ptr == NULL) ? 0 : bytes;
|
||||
return new_chunk;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of allocator_t.free_pointer.
|
||||
*/
|
||||
static void free_pointer(allocator_t *allocator, void * pointer)
|
||||
{
|
||||
private_allocator_t *this = (private_allocator_t *) allocator;
|
||||
memory_hdr_t *allocated_memory;
|
||||
|
||||
|
||||
if (pointer == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
this->frees++;
|
||||
pthread_mutex_lock( &(this->mutex));
|
||||
allocated_memory = ((memory_hdr_t *)pointer) - 1;
|
||||
|
||||
if (allocated_memory->info.older != NULL)
|
||||
{
|
||||
assert(allocated_memory->info.older->info.newer == allocated_memory);
|
||||
allocated_memory->info.older->info.newer = allocated_memory->info.newer;
|
||||
}
|
||||
if (allocated_memory->info.newer == NULL)
|
||||
{
|
||||
assert(allocated_memory == this->allocations);
|
||||
this->allocations = allocated_memory->info.older;
|
||||
}
|
||||
else
|
||||
{
|
||||
assert(allocated_memory->info.newer->info.older == allocated_memory);
|
||||
allocated_memory->info.newer->info.older = allocated_memory->info.older;
|
||||
}
|
||||
pthread_mutex_unlock(&(this->mutex));
|
||||
free(allocated_memory);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of allocator_t.reallocate.
|
||||
*/
|
||||
static void * reallocate(allocator_t *allocator, void * old, size_t bytes, char * file,int line)
|
||||
{
|
||||
private_allocator_t *this = (private_allocator_t *) allocator;
|
||||
memory_hdr_t *allocated_memory;
|
||||
|
||||
|
||||
pthread_mutex_lock( &(this->mutex));
|
||||
allocated_memory = ((memory_hdr_t *)old) - 1;
|
||||
|
||||
void *new_space = this->allocate_special(this,bytes,file,line,FALSE);
|
||||
|
||||
if (old != NULL)
|
||||
{
|
||||
/* the smaller size is copied to avoid overflows */
|
||||
memcpy(new_space,old,(allocated_memory->info.size_of_memory < bytes) ? allocated_memory->info.size_of_memory : bytes);
|
||||
}
|
||||
pthread_mutex_unlock(&(this->mutex));
|
||||
this->public.free_pointer(&(this->public),old);
|
||||
|
||||
return new_space;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of allocator_t.clone_bytes.
|
||||
*/
|
||||
static void * clone_bytes(allocator_t *allocator,void * to_clone, size_t bytes, char * file, int line)
|
||||
{
|
||||
private_allocator_t *this = (private_allocator_t *) allocator;
|
||||
|
||||
if (to_clone == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
void *new_space = this->allocate_special(this,bytes,file,line,TRUE);
|
||||
|
||||
if (new_space == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
memcpy(new_space,to_clone,bytes);
|
||||
|
||||
return new_space;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of allocator_t.clone_chunk.
|
||||
*/
|
||||
static chunk_t clone_chunk(allocator_t *allocator, chunk_t chunk, char * file, int line)
|
||||
{
|
||||
private_allocator_t *this = (private_allocator_t *) allocator;
|
||||
chunk_t clone = CHUNK_INITIALIZER;
|
||||
|
||||
if (chunk.ptr && chunk.len > 0)
|
||||
{
|
||||
clone.ptr = this->allocate_special(this,chunk.len,file,line,TRUE);
|
||||
clone.len = chunk.len;
|
||||
memcpy(clone.ptr, chunk.ptr, chunk.len);
|
||||
}
|
||||
|
||||
return clone;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of allocator_t.allocator_report_memory_leaks.
|
||||
*/
|
||||
static void allocator_report_memory_leaks(allocator_t *allocator)
|
||||
{
|
||||
private_allocator_t *this = (private_allocator_t *) allocator;
|
||||
memory_hdr_t *p = this->allocations;
|
||||
memory_hdr_t *pprev = NULL;
|
||||
unsigned long n = 0;
|
||||
|
||||
pthread_mutex_lock(&(this->mutex));
|
||||
|
||||
while (p != NULL)
|
||||
{
|
||||
assert(pprev == p->info.newer);
|
||||
pprev = p;
|
||||
p = p->info.older;
|
||||
n++;
|
||||
if (p == NULL || pprev->info.filename != p->info.filename)
|
||||
{
|
||||
if (n != 1)
|
||||
fprintf(stderr,"LEAK: \"%lu * %s, line %d\"\n", n, pprev->info.filename,pprev->info.line);
|
||||
else
|
||||
fprintf(stderr,"LEAK: \"%s, line %d\"\n", pprev->info.filename,pprev->info.line);
|
||||
n = 0;
|
||||
}
|
||||
}
|
||||
pthread_mutex_unlock( &(this->mutex));
|
||||
fprintf(stderr, "Allocator statistics: %d allocs, %d frees\n", this->allocs, this->frees);
|
||||
}
|
||||
|
||||
/**
|
||||
* Only Initiation of allocator object.
|
||||
*
|
||||
* All allocation macros use this object.
|
||||
*/
|
||||
static private_allocator_t allocator = {
|
||||
public: {allocate: allocate,
|
||||
allocate_as_chunk: allocate_as_chunk,
|
||||
free_pointer: free_pointer,
|
||||
reallocate: reallocate,
|
||||
clone_bytes : clone_bytes,
|
||||
clone_chunk : clone_chunk,
|
||||
report_memory_leaks: allocator_report_memory_leaks},
|
||||
allocations: NULL,
|
||||
allocate_special : allocate_special,
|
||||
mutex: PTHREAD_MUTEX_INITIALIZER,
|
||||
allocs: 0,
|
||||
frees: 0
|
||||
};
|
||||
|
||||
|
||||
allocator_t *global_allocator = &(allocator.public);
|
||||
|
||||
/*
|
||||
* Alloc function for gmp.
|
||||
*/
|
||||
void *gmp_alloc(size_t bytes)
|
||||
{
|
||||
return allocator.allocate_special(&allocator, bytes, "[ gmp internal ]", 0 , TRUE);
|
||||
}
|
||||
|
||||
/*
|
||||
* Realloc function for gmp.
|
||||
*/
|
||||
void *gmp_realloc(void *old, size_t old_bytes, size_t new_bytes)
|
||||
{
|
||||
return global_allocator->reallocate(global_allocator, old, new_bytes, "[ gmp internal ]", 0);
|
||||
}
|
||||
/*
|
||||
* Free function for gmp.
|
||||
*/
|
||||
void gmp_free(void *ptr, size_t bytes)
|
||||
{
|
||||
free_pointer(global_allocator, ptr);
|
||||
}
|
||||
|
||||
/*
|
||||
* Described in header
|
||||
*/
|
||||
void allocator_init()
|
||||
{
|
||||
mp_set_memory_functions (gmp_alloc, gmp_realloc, gmp_free);
|
||||
}
|
||||
|
||||
#else /* !LEAK_DETECTION */
|
||||
|
||||
/*
|
||||
* Described in header.
|
||||
*/
|
||||
chunk_t allocator_alloc_as_chunk(size_t bytes)
|
||||
{
|
||||
chunk_t new_chunk;
|
||||
new_chunk.ptr = malloc(bytes);
|
||||
if (new_chunk.ptr == NULL)
|
||||
{
|
||||
exit(-1);
|
||||
}
|
||||
new_chunk.len = bytes;
|
||||
return new_chunk;
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* Described in header.
|
||||
*/
|
||||
void * allocator_realloc(void * old, size_t newsize)
|
||||
{
|
||||
void *data = realloc(old,newsize);
|
||||
return data;
|
||||
}
|
||||
|
||||
/*
|
||||
* Described in header.
|
||||
*/
|
||||
void * allocator_clone_bytes(void * pointer, size_t size)
|
||||
{
|
||||
|
||||
void *data;
|
||||
data = malloc(size);
|
||||
|
||||
if (data == NULL){exit(-1);}
|
||||
memmove(data,pointer,size);
|
||||
|
||||
return (data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Described in header.
|
||||
*/
|
||||
chunk_t allocator_clone_chunk(chunk_t chunk)
|
||||
{
|
||||
chunk_t clone = CHUNK_INITIALIZER;
|
||||
|
||||
if (chunk.ptr && chunk.len > 0)
|
||||
{
|
||||
clone.ptr = malloc(chunk.len);
|
||||
if (clone.ptr == NULL) {exit(-1);}
|
||||
clone.len = chunk.len;
|
||||
memcpy(clone.ptr, chunk.ptr, chunk.len);
|
||||
}
|
||||
|
||||
return clone;
|
||||
}
|
||||
|
||||
/*
|
||||
* Described in header.
|
||||
*/
|
||||
void allocator_free_chunk(chunk_t *chunk)
|
||||
{
|
||||
free(chunk->ptr);
|
||||
chunk->ptr = NULL;
|
||||
chunk->len = 0;
|
||||
}
|
||||
|
||||
#endif /* LEAK_DETECTION */
|
||||
@@ -1,324 +0,0 @@
|
||||
/**
|
||||
* @file allocator.h
|
||||
*
|
||||
* @brief Interface of allocator_t.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2005 Jan Hutter, Martin Willi
|
||||
* Hochschule fuer Technik Rapperswil
|
||||
*
|
||||
* 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. See <http://www.fsf.org/copyleft/gpl.txt>.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef ALLOCATOR_H_
|
||||
#define ALLOCATOR_H_
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stddef.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <types.h>
|
||||
|
||||
|
||||
/**
|
||||
* Macro to allocate a special type.
|
||||
*
|
||||
* @param thing object on which a sizeof is performed
|
||||
* @return pointer to allocated memory
|
||||
*
|
||||
* @ingroup utils
|
||||
*/
|
||||
#define allocator_alloc_thing_as_chunk(thing) (allocator_alloc_as_chunk(sizeof(thing)))
|
||||
|
||||
/**
|
||||
* Macro to allocate a special type as chunk_t.
|
||||
*
|
||||
* @param thing object on which a sizeof is performed
|
||||
* @return chunk_t pointing to allocated memory
|
||||
*
|
||||
* @ingroup utils
|
||||
*/
|
||||
#define allocator_alloc_thing(thing) (allocator_alloc(sizeof(thing)))
|
||||
|
||||
#ifdef LEAK_DETECTIVE
|
||||
|
||||
typedef struct allocator_t allocator_t;
|
||||
|
||||
/**
|
||||
*@brief Allocater object use to detect memory leaks.
|
||||
*
|
||||
* @ingroup utils
|
||||
*/
|
||||
struct allocator_t {
|
||||
|
||||
/**
|
||||
* Allocates memory with LEAK_DETECTION and
|
||||
* returns an empty data area filled with zeros.
|
||||
*
|
||||
* @warning Use this function not directly, only with assigned macros
|
||||
* #allocator_alloc and #allocator_alloc_thing.
|
||||
*
|
||||
* @param this allocator_t object
|
||||
* @param bytes number of bytes to allocate
|
||||
* @param file filename from which the memory is allocated
|
||||
* @param line line number in specific file
|
||||
* @return pointer to allocated memory area
|
||||
*/
|
||||
void * (*allocate) (allocator_t *this,size_t bytes, char * file,int line);
|
||||
|
||||
/**
|
||||
* Allocates memory with LEAK_DETECTION and
|
||||
* returns an chunk pointing to an empy data area filled with zeros.
|
||||
*
|
||||
* @warning Use this function not directly, only with assigned
|
||||
* macros #allocator_alloc_as_chunk and
|
||||
* #allocator_alloc_thing_as_chunk.
|
||||
*
|
||||
* @param this allocator_t object
|
||||
* @param bytes number of bytes to allocate
|
||||
* @param file filename from which the memory is allocated
|
||||
* @param line line number in specific file
|
||||
* @return pointer to allocated memory area
|
||||
*/
|
||||
chunk_t (*allocate_as_chunk) (allocator_t *this,size_t bytes, char * file,int line);
|
||||
|
||||
/**
|
||||
* Reallocates memory with LEAK_DETECTION and
|
||||
* returns an empty data area filled with zeros.
|
||||
*
|
||||
* @warning Use this function not directly, only with assigned macro
|
||||
* #allocator_realloc.
|
||||
*
|
||||
* @param this allocator_t object
|
||||
* @param old pointer to the old data area
|
||||
* @param bytes number of bytes to allocate
|
||||
* @param file filename from which the memory is allocated
|
||||
* @param line line number in specific file
|
||||
* @return pointer to reallocated memory area
|
||||
*/
|
||||
void * (*reallocate) (allocator_t *this,void * old, size_t bytes, char * file, int line);
|
||||
|
||||
/**
|
||||
* Clones memory with LEAK_DETECTION and returns a cloned data area.
|
||||
*
|
||||
* @warning Use this function not directly, only with assigned macro
|
||||
* #allocator_clone_bytes.
|
||||
*
|
||||
* @param this allocator_t object
|
||||
* @param old pointer to the old data area
|
||||
* @param bytes number of bytes to allocate
|
||||
* @param file filename from which the memory is allocated
|
||||
* @param line line number in specific file
|
||||
* @return pointer to reallocated memory area
|
||||
*/
|
||||
void * (*clone_bytes) (allocator_t *this,void * to_clone, size_t bytes, char * file, int line);
|
||||
|
||||
/**
|
||||
* Clones a chunk with LEAK_DETECTION and returns a cloned chunk.
|
||||
*
|
||||
* @warning Use this function not directly, only with assigned macro
|
||||
* #allocator_clone_chunk-
|
||||
*
|
||||
* @param this allocator_t object
|
||||
* @param chunk chunk to clone
|
||||
* @param file filename from which the memory is allocated
|
||||
* @param line line number in specific file
|
||||
* @return pointer to reallocated memory
|
||||
*/
|
||||
chunk_t (*clone_chunk) (allocator_t *this, chunk_t chunk, char * file, int line);
|
||||
|
||||
/**
|
||||
* Frees memory with LEAK_DETECTION.
|
||||
*
|
||||
* @warning Use this function not directly, only with assigned macro
|
||||
* #allocator_free.
|
||||
*
|
||||
* @param this allocator_t object
|
||||
* @param pointer pointer to the data area to free
|
||||
*/
|
||||
void (*free_pointer) (allocator_t *this,void * pointer);
|
||||
|
||||
/**
|
||||
* Report memory leaks to stderr.
|
||||
*
|
||||
* @warning Use this function not directly, only with assigned macro
|
||||
* #report_memory_leaks
|
||||
*
|
||||
* @param this allocator_t object
|
||||
*/
|
||||
void (*report_memory_leaks) (allocator_t *this);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @brief Initialize the allocator.
|
||||
*
|
||||
* Setup the allocator (set allocation functions for libgmp)
|
||||
*/
|
||||
void allocator_init();
|
||||
|
||||
/**
|
||||
* @brief Global allocater_t object.
|
||||
*
|
||||
* Only accessed over macros.
|
||||
*/
|
||||
extern allocator_t *global_allocator;
|
||||
|
||||
|
||||
/**
|
||||
* Macro to allocate some memory.
|
||||
*
|
||||
* See #allocator_t.allocate for description.
|
||||
*
|
||||
* @ingroup utils
|
||||
*/
|
||||
#define allocator_alloc(bytes) (global_allocator->allocate(global_allocator,bytes,__FILE__,__LINE__))
|
||||
|
||||
/**
|
||||
* Macro to allocate some memory for a chunk_t.
|
||||
*
|
||||
* See #allocator_t.allocate_as_chunk for description.
|
||||
*
|
||||
* @ingroup utils
|
||||
*/
|
||||
#define allocator_alloc_as_chunk(bytes) (global_allocator->allocate_as_chunk(global_allocator,bytes,__FILE__,__LINE__))
|
||||
|
||||
/**
|
||||
* Macro to reallocate some memory.
|
||||
*
|
||||
* See #allocator_t.reallocate for description.
|
||||
*
|
||||
* @ingroup utils
|
||||
*/
|
||||
#define allocator_realloc(old,bytes) (global_allocator->reallocate(global_allocator,old,bytes,__FILE__, __LINE__))
|
||||
|
||||
/**
|
||||
* Macro to clone some memory.
|
||||
*
|
||||
* See #allocator_t.*clone_bytes for description.
|
||||
*
|
||||
* @ingroup utils
|
||||
*/
|
||||
#define allocator_clone_bytes(old,bytes) (global_allocator->clone_bytes(global_allocator,old,bytes,__FILE__, __LINE__))
|
||||
|
||||
/**
|
||||
* Macro to clone a chunk and its contents
|
||||
*
|
||||
* See #allocator_t.clone_chunk for description.
|
||||
*
|
||||
* @ingroup utils
|
||||
*/
|
||||
#define allocator_clone_chunk(chunk) (global_allocator->clone_chunk(global_allocator,chunk,__FILE__, __LINE__))
|
||||
|
||||
/**
|
||||
* Macro to free some memory.
|
||||
*
|
||||
* See #allocator_t.free_pointer for description.
|
||||
*
|
||||
* @ingroup utils
|
||||
*/
|
||||
#define allocator_free(pointer) (global_allocator->free_pointer(global_allocator,pointer))
|
||||
|
||||
/**
|
||||
* Macro to free a chunk.
|
||||
*/
|
||||
#define allocator_free_chunk(chunk){ \
|
||||
global_allocator->free_pointer(global_allocator,(chunk)->ptr); \
|
||||
(chunk)->ptr = NULL; \
|
||||
(chunk)->len = 0; \
|
||||
}
|
||||
|
||||
/**
|
||||
* Macro to report memory leaks.
|
||||
*
|
||||
* See #allocator_s.report_memory_leaks for description.
|
||||
*
|
||||
* @ingroup utils
|
||||
*/
|
||||
#define report_memory_leaks(void) (global_allocator->report_memory_leaks(global_allocator))
|
||||
#else
|
||||
|
||||
/**
|
||||
* Macro to allocate some memory.
|
||||
*
|
||||
* @ingroup utils
|
||||
*/
|
||||
#define allocator_alloc(bytes) (malloc(bytes))
|
||||
|
||||
/**
|
||||
* Allocate some memory as chunk.
|
||||
*
|
||||
* @ingroup utils
|
||||
*/
|
||||
chunk_t allocator_alloc_as_chunk(size_t bytes);
|
||||
|
||||
/**
|
||||
* Reallocate some memory.
|
||||
*
|
||||
* @ingroup utils
|
||||
*/
|
||||
void * allocator_realloc(void * old, size_t newsize);
|
||||
|
||||
/**
|
||||
* Free allocated memory.
|
||||
*
|
||||
* @ingroup utils
|
||||
*/
|
||||
#define allocator_free(pointer) (free(pointer))
|
||||
|
||||
/**
|
||||
* Clone bytes.
|
||||
*
|
||||
*
|
||||
* @param pointer pointer to read data from
|
||||
* @param size number of bytes to clone
|
||||
*
|
||||
* @ingroup utils
|
||||
*/
|
||||
void * allocator_clone_bytes(void * pointer, size_t size);
|
||||
|
||||
/**
|
||||
* Clone a chunk and its contents.
|
||||
*
|
||||
*
|
||||
* @param chunk chunk to clone
|
||||
* @return cloned chunk
|
||||
*
|
||||
* @ingroup utils
|
||||
*/
|
||||
chunk_t allocator_clone_chunk(chunk_t chunk);
|
||||
|
||||
/**
|
||||
* Frees memory used by chunk.
|
||||
*
|
||||
* @param chunk pointer of chunk to free
|
||||
*
|
||||
* @ingroup utils
|
||||
*/
|
||||
void allocator_free_chunk(chunk_t *chunk);
|
||||
|
||||
/**
|
||||
* Report memory leaks.
|
||||
*
|
||||
* @ingroup utils
|
||||
*/
|
||||
#define report_memory_leaks() {}
|
||||
|
||||
/**
|
||||
* Initialize the allocator.
|
||||
*
|
||||
* @ingroup utils
|
||||
*/
|
||||
#define allocator_init() {}
|
||||
#endif
|
||||
|
||||
#endif /*ALLOCATOR_H_*/
|
||||
+12
-12
@@ -20,9 +20,9 @@
|
||||
* for more details.
|
||||
*/
|
||||
|
||||
#include "host.h"
|
||||
#include <string.h>
|
||||
|
||||
#include <utils/allocator.h>
|
||||
#include "host.h"
|
||||
|
||||
|
||||
typedef struct private_host_t private_host_t;
|
||||
@@ -114,9 +114,9 @@ static char *get_address(private_host_t *this)
|
||||
/* we need to clone it, since inet_ntoa overwrites
|
||||
* internal buffer on subsequent calls
|
||||
*/
|
||||
allocator_free(this->string);
|
||||
free(this->string);
|
||||
string = inet_ntoa(this->address4.sin_addr);
|
||||
this->string = allocator_alloc(strlen(string)+1);
|
||||
this->string = malloc(strlen(string)+1);
|
||||
strcpy(this->string, string);
|
||||
return this->string;
|
||||
}
|
||||
@@ -139,7 +139,7 @@ static chunk_t get_address_as_chunk(private_host_t *this)
|
||||
case AF_INET:
|
||||
{
|
||||
/* allocate 4 bytes for IPV4 address*/
|
||||
address.ptr = allocator_alloc(4);
|
||||
address.ptr = malloc(4);
|
||||
address.len = 4;
|
||||
memcpy(address.ptr,&(this->address4.sin_addr.s_addr),4);
|
||||
}
|
||||
@@ -196,13 +196,13 @@ static u_int16_t get_port(private_host_t *this)
|
||||
*/
|
||||
static private_host_t *clone(private_host_t *this)
|
||||
{
|
||||
private_host_t *new = allocator_alloc_thing(private_host_t);
|
||||
private_host_t *new = malloc_thing(private_host_t);
|
||||
|
||||
|
||||
memcpy(new, this, sizeof(private_host_t));
|
||||
if (this->string)
|
||||
{
|
||||
new->string = allocator_alloc(strlen(this->string)+1);
|
||||
new->string = malloc(strlen(this->string)+1);
|
||||
strcpy(new->string, this->string);
|
||||
}
|
||||
return new;
|
||||
@@ -254,8 +254,8 @@ static bool equals(private_host_t *this, private_host_t *other)
|
||||
*/
|
||||
static void destroy(private_host_t *this)
|
||||
{
|
||||
allocator_free(this->string);
|
||||
allocator_free(this);
|
||||
free(this->string);
|
||||
free(this);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -263,7 +263,7 @@ static void destroy(private_host_t *this)
|
||||
*/
|
||||
static private_host_t *host_create_empty()
|
||||
{
|
||||
private_host_t *this = allocator_alloc_thing(private_host_t);
|
||||
private_host_t *this = malloc_thing(private_host_t);
|
||||
|
||||
this->public.get_sockaddr = (sockaddr_t* (*) (host_t*))get_sockaddr;
|
||||
this->public.get_sockaddr_len = (socklen_t*(*) (host_t*))get_sockaddr_len;
|
||||
@@ -305,7 +305,7 @@ host_t *host_create(int family, char *address, u_int16_t port)
|
||||
}
|
||||
default:
|
||||
{
|
||||
allocator_free(this);
|
||||
free(this);
|
||||
return NULL;
|
||||
|
||||
}
|
||||
@@ -337,7 +337,7 @@ host_t *host_create_from_chunk(int family, chunk_t address, u_int16_t port)
|
||||
return &(this->public);
|
||||
}
|
||||
}
|
||||
allocator_free(this);
|
||||
free(this);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
@@ -23,11 +23,10 @@
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "identification.h"
|
||||
|
||||
#include <utils/allocator.h>
|
||||
|
||||
/**
|
||||
* String mappings for id_type_t.
|
||||
*/
|
||||
@@ -145,8 +144,8 @@ static identification_t *clone(private_identification_t *this)
|
||||
private_identification_t *clone = identification_create();
|
||||
|
||||
clone->type = this->type;
|
||||
clone->encoded = allocator_clone_chunk(this->encoded);
|
||||
clone->string = allocator_alloc(strlen(this->string) + 1);
|
||||
clone->encoded = chunk_clone(this->encoded);
|
||||
clone->string = malloc(strlen(this->string) + 1);
|
||||
strcpy(clone->string, this->string);
|
||||
|
||||
return &clone->public;
|
||||
@@ -157,9 +156,9 @@ static identification_t *clone(private_identification_t *this)
|
||||
*/
|
||||
static void destroy(private_identification_t *this)
|
||||
{
|
||||
allocator_free(this->string);
|
||||
allocator_free(this->encoded.ptr);
|
||||
allocator_free(this);
|
||||
free(this->string);
|
||||
free(this->encoded.ptr);
|
||||
free(this);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -169,7 +168,7 @@ static void destroy(private_identification_t *this)
|
||||
*/
|
||||
static private_identification_t *identification_create()
|
||||
{
|
||||
private_identification_t *this = allocator_alloc_thing(private_identification_t);
|
||||
private_identification_t *this = malloc_thing(private_identification_t);
|
||||
|
||||
this->public.equals = (bool (*) (identification_t*,identification_t*))equals;
|
||||
this->public.belongs_to = (bool (*) (identification_t*,identification_t*))belongs_to;
|
||||
@@ -200,15 +199,15 @@ identification_t *identification_create_from_string(id_type_t type, char *string
|
||||
{
|
||||
/* convert string */
|
||||
this->encoded.len = 4;
|
||||
this->encoded.ptr = allocator_alloc(this->encoded.len);
|
||||
this->encoded.ptr = malloc(this->encoded.len);
|
||||
if (inet_aton(string, ((struct in_addr*)(this->encoded.ptr))) == 0)
|
||||
{
|
||||
allocator_free(this->encoded.ptr);
|
||||
allocator_free(this);
|
||||
free(this->encoded.ptr);
|
||||
free(this);
|
||||
return NULL;
|
||||
}
|
||||
/* clone string */
|
||||
this->string = allocator_alloc(strlen(string)+1);
|
||||
this->string = malloc(strlen(string)+1);
|
||||
strcpy(this->string, string);
|
||||
return &(this->public);
|
||||
}
|
||||
@@ -221,7 +220,7 @@ identification_t *identification_create_from_string(id_type_t type, char *string
|
||||
default:
|
||||
{
|
||||
/* not supported */
|
||||
allocator_free(this);
|
||||
free(this);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
@@ -235,7 +234,7 @@ identification_t *identification_create_from_encoding(id_type_t type, chunk_t en
|
||||
char *string;
|
||||
private_identification_t *this = identification_create();
|
||||
|
||||
this->encoded = allocator_clone_chunk(encoded);
|
||||
this->encoded = chunk_clone(encoded);
|
||||
|
||||
this->type = type;
|
||||
switch (type)
|
||||
@@ -284,7 +283,7 @@ identification_t *identification_create_from_encoding(id_type_t type, chunk_t en
|
||||
/* build string, must be cloned since
|
||||
* inet_ntoa points to a subsequently
|
||||
* overwritten buffer */
|
||||
this->string = allocator_alloc(strlen(string)+1);
|
||||
this->string = malloc(strlen(string)+1);
|
||||
strcpy(this->string, string);
|
||||
|
||||
return &(this->public);
|
||||
|
||||
@@ -0,0 +1,382 @@
|
||||
/**
|
||||
* @file leak_detective.c
|
||||
*
|
||||
* @brief Implementation of leak_detective_t.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2006 Martin Willi
|
||||
* Hochschule fuer Technik Rapperswil
|
||||
*
|
||||
* 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. See <http://www.fsf.org/copyleft/gpl.txt>.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <stddef.h>
|
||||
#include <pthread.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <malloc.h>
|
||||
#include <execinfo.h>
|
||||
#include <signal.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <dlfcn.h>
|
||||
|
||||
#include "leak_detective.h"
|
||||
|
||||
#include <types.h>
|
||||
|
||||
#ifdef LEAK_DETECTIVE
|
||||
|
||||
/**
|
||||
* Magic value which helps to detect memory corruption
|
||||
*/
|
||||
#define MEMORY_HEADER_MAGIC 0xF1367ADF
|
||||
|
||||
|
||||
static void install_hooks(void);
|
||||
static void uninstall_hooks(void);
|
||||
static void *malloc_hook(size_t, const void *);
|
||||
static void *realloc_hook(void *, size_t, const void *);
|
||||
static void free_hook(void*, const void *);
|
||||
|
||||
typedef struct memory_header_t memory_header_t;
|
||||
|
||||
/**
|
||||
* Header which is prepended to each allocated memory block
|
||||
*/
|
||||
struct memory_header_t {
|
||||
/**
|
||||
* Magci byte which must(!) hold MEMORY_HEADER_MAGIC
|
||||
*/
|
||||
u_int32_t magic;
|
||||
|
||||
/**
|
||||
* Number of bytes following after the header
|
||||
*/
|
||||
size_t bytes;
|
||||
|
||||
/**
|
||||
* Stack frames at the time of allocation
|
||||
*/
|
||||
void *stack_frames[STACK_FRAMES_COUNT];
|
||||
|
||||
/**
|
||||
* Number of stacks frames obtained in stack_frames
|
||||
*/
|
||||
int stack_frame_count;
|
||||
|
||||
/**
|
||||
* Pointer to previous entry in linked list
|
||||
*/
|
||||
memory_header_t *previous;
|
||||
|
||||
/**
|
||||
* Pointer to next entry in linked list
|
||||
*/
|
||||
memory_header_t *next;
|
||||
};
|
||||
|
||||
/**
|
||||
* first mem header is just a dummy to chain
|
||||
* the others on it...
|
||||
*/
|
||||
memory_header_t first_header = {
|
||||
magic: MEMORY_HEADER_MAGIC,
|
||||
bytes: 0,
|
||||
stack_frame_count: 0,
|
||||
previous: NULL,
|
||||
next: NULL
|
||||
};
|
||||
|
||||
/**
|
||||
* standard hooks, used to temparily remove hooking
|
||||
*/
|
||||
void *old_malloc_hook, *old_realloc_hook, *old_free_hook;
|
||||
|
||||
|
||||
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||
|
||||
|
||||
/**
|
||||
* log stack frames queried by backtrace()
|
||||
* TODO: Dump symbols of static functions!!!
|
||||
*/
|
||||
void log_stack_frames(void *stack_frames, int stack_frame_count)
|
||||
{
|
||||
char **strings;
|
||||
size_t i;
|
||||
|
||||
strings = backtrace_symbols (stack_frames, stack_frame_count);
|
||||
|
||||
printf(" dumping %d stack frames.\n", stack_frame_count);
|
||||
|
||||
for (i = 0; i < stack_frame_count; i++)
|
||||
{
|
||||
printf (" %s\n", strings[i]);
|
||||
}
|
||||
free (strings);
|
||||
}
|
||||
|
||||
void (*__malloc_initialize_hook) (void) = install_hooks;
|
||||
|
||||
/**
|
||||
* Installs the malloc hooks, enables leak detection
|
||||
*/
|
||||
void install_hooks()
|
||||
{
|
||||
old_malloc_hook = __malloc_hook;
|
||||
old_realloc_hook = __realloc_hook;
|
||||
old_free_hook = __free_hook;
|
||||
__malloc_hook = malloc_hook;
|
||||
__realloc_hook = realloc_hook;
|
||||
__free_hook = free_hook;
|
||||
}
|
||||
|
||||
/**
|
||||
* Uninstalls the malloc hooks, disables leak detection
|
||||
*/
|
||||
void uninstall_hooks()
|
||||
{
|
||||
__malloc_hook = old_malloc_hook;
|
||||
__free_hook = old_free_hook;
|
||||
}
|
||||
|
||||
/**
|
||||
* Hook function for malloc()
|
||||
*/
|
||||
static void *malloc_hook(size_t bytes, const void *caller)
|
||||
{
|
||||
memory_header_t *hdr;
|
||||
|
||||
pthread_mutex_lock(&mutex);
|
||||
uninstall_hooks();
|
||||
hdr = malloc(bytes + sizeof(memory_header_t));
|
||||
|
||||
hdr->magic = MEMORY_HEADER_MAGIC;
|
||||
hdr->bytes = bytes;
|
||||
hdr->stack_frame_count = backtrace(hdr->stack_frames, STACK_FRAMES_COUNT);
|
||||
|
||||
/* insert at the beginning of the list */
|
||||
hdr->next = first_header.next;
|
||||
if (hdr->next)
|
||||
{
|
||||
hdr->next->previous = hdr;
|
||||
}
|
||||
hdr->previous = &first_header;
|
||||
first_header.next = hdr;
|
||||
install_hooks();
|
||||
pthread_mutex_unlock(&mutex);
|
||||
return hdr + 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Hook function for free()
|
||||
*/
|
||||
static void free_hook(void *ptr, const void *caller)
|
||||
{
|
||||
void *stack_frames[STACK_FRAMES_COUNT];
|
||||
int stack_frame_count;
|
||||
memory_header_t *hdr = ptr - sizeof(memory_header_t);
|
||||
|
||||
/* allow freeing of NULL */
|
||||
if (ptr == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
pthread_mutex_lock(&mutex);
|
||||
if (hdr->magic != MEMORY_HEADER_MAGIC)
|
||||
{
|
||||
pthread_mutex_unlock(&mutex);
|
||||
/* TODO: Since we get a lot of theses from the pthread lib, its deactivated for now... */
|
||||
return;
|
||||
printf("freeing of invalid memory (%p)\n", ptr);
|
||||
stack_frame_count = backtrace(stack_frames, STACK_FRAMES_COUNT);
|
||||
log_stack_frames(stack_frames, stack_frame_count);
|
||||
kill(0, SIGSEGV);
|
||||
return;
|
||||
}
|
||||
/* remove magic from hdr */
|
||||
hdr->magic = 0;
|
||||
|
||||
/* remove item from list */
|
||||
if (hdr->next)
|
||||
{
|
||||
hdr->next->previous = hdr->previous;
|
||||
}
|
||||
hdr->previous->next = hdr->next;
|
||||
|
||||
uninstall_hooks();
|
||||
free(hdr);
|
||||
install_hooks();
|
||||
pthread_mutex_unlock(&mutex);
|
||||
}
|
||||
|
||||
/**
|
||||
* Hook function for realloc()
|
||||
*/
|
||||
static void *realloc_hook(void *old, size_t bytes, const void *caller)
|
||||
{
|
||||
void *new;
|
||||
memory_header_t *hdr = old - sizeof(memory_header_t);
|
||||
void *stack_frames[STACK_FRAMES_COUNT];
|
||||
int stack_frame_count;
|
||||
|
||||
/* allow reallocation of NULL */
|
||||
if (old == NULL)
|
||||
{
|
||||
return malloc_hook(bytes, caller);
|
||||
}
|
||||
if (hdr->magic != MEMORY_HEADER_MAGIC)
|
||||
{
|
||||
printf("reallocation of invalid memory (%p)\n", old);
|
||||
stack_frame_count = backtrace(stack_frames, STACK_FRAMES_COUNT);
|
||||
log_stack_frames(stack_frames, stack_frame_count);
|
||||
kill(0, SIGSEGV);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* malloc and free is done with hooks */
|
||||
new = malloc_hook(bytes, caller);
|
||||
memcpy(new, old, min(bytes, hdr->bytes));
|
||||
free_hook(old, caller);
|
||||
|
||||
return new;
|
||||
}
|
||||
|
||||
/**
|
||||
* Report leaks at library destruction
|
||||
*/
|
||||
void __attribute__ ((destructor)) report_leaks()
|
||||
{
|
||||
memory_header_t *hdr;
|
||||
int leaks = 0;
|
||||
|
||||
for (hdr = first_header.next; hdr != NULL; hdr = hdr->next)
|
||||
{
|
||||
printf("Leak (%d bytes at %p)\n", hdr->bytes, hdr + 1);
|
||||
log_stack_frames(hdr->stack_frames, hdr->stack_frame_count);
|
||||
leaks++;
|
||||
}
|
||||
switch (leaks)
|
||||
{
|
||||
case 0:
|
||||
printf("No leaks detected\n");
|
||||
break;
|
||||
case 1:
|
||||
printf("One leak detected\n");
|
||||
break;
|
||||
default:
|
||||
printf("%d leaks detected\n", leaks);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* The following glibc functions are excluded from leak detection, since
|
||||
* they use static allocated buffers or other ugly allocation hacks.
|
||||
* The Makefile links theses function preferred to their counterparts
|
||||
* in the target lib...
|
||||
* TODO: Generic handling would be nice, with a list of blacklisted
|
||||
* functions.
|
||||
*/
|
||||
|
||||
|
||||
char *inet_ntoa(struct in_addr in)
|
||||
{
|
||||
char *(*_inet_ntoa)(struct in_addr);
|
||||
void *handle;
|
||||
char *result;
|
||||
|
||||
pthread_mutex_lock(&mutex);
|
||||
uninstall_hooks();
|
||||
|
||||
handle = dlopen("libc.so.6", RTLD_LAZY);
|
||||
if (handle == NULL)
|
||||
{
|
||||
kill(0, SIGSEGV);
|
||||
}
|
||||
_inet_ntoa = dlsym(handle, "inet_ntoa");
|
||||
|
||||
if (_inet_ntoa == NULL)
|
||||
{
|
||||
kill(0, SIGSEGV);
|
||||
}
|
||||
result = _inet_ntoa(in);
|
||||
dlclose(handle);
|
||||
install_hooks();
|
||||
pthread_mutex_unlock(&mutex);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
int pthread_create(pthread_t *__restrict __threadp, __const pthread_attr_t *__restrict __attr,
|
||||
void *(*__start_routine) (void *), void *__restrict __arg)
|
||||
{
|
||||
int (*_pthread_create) (pthread_t *__restrict __threadp,
|
||||
__const pthread_attr_t *__restrict __attr,
|
||||
void *(*__start_routine) (void *),
|
||||
void *__restrict __arg);
|
||||
void *handle;
|
||||
int result;
|
||||
|
||||
pthread_mutex_lock(&mutex);
|
||||
uninstall_hooks();
|
||||
|
||||
handle = dlopen("libpthread.so.0", RTLD_LAZY);
|
||||
if (handle == NULL)
|
||||
{
|
||||
kill(0, SIGSEGV);
|
||||
}
|
||||
_pthread_create = dlsym(handle, "pthread_create");
|
||||
|
||||
if (_pthread_create == NULL)
|
||||
{
|
||||
kill(0, SIGSEGV);
|
||||
}
|
||||
result = _pthread_create(__threadp, __attr, __start_routine, __arg);
|
||||
dlclose(handle);
|
||||
install_hooks();
|
||||
pthread_mutex_unlock(&mutex);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
time_t mktime(struct tm *tm)
|
||||
{
|
||||
time_t (*_mktime)(struct tm *tm);
|
||||
time_t result;
|
||||
void *handle;
|
||||
|
||||
pthread_mutex_lock(&mutex);
|
||||
uninstall_hooks();
|
||||
|
||||
handle = dlopen("libc.so.6", RTLD_LAZY);
|
||||
if (handle == NULL)
|
||||
{
|
||||
kill(0, SIGSEGV);
|
||||
}
|
||||
_mktime = dlsym(handle, "mktime");
|
||||
|
||||
if (_mktime == NULL)
|
||||
{
|
||||
kill(0, SIGSEGV);
|
||||
}
|
||||
result = _mktime(tm);
|
||||
dlclose(handle);
|
||||
install_hooks();
|
||||
pthread_mutex_unlock(&mutex);
|
||||
return result;
|
||||
}
|
||||
|
||||
#endif /* LEAK_DETECTION */
|
||||
@@ -0,0 +1,38 @@
|
||||
/**
|
||||
* @file leak_detective.h
|
||||
*
|
||||
* @brief malloc/free hooks to detect leaks.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2006 Martin Willi
|
||||
* Hochschule fuer Technik Rapperswil
|
||||
*
|
||||
* 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. See <http://www.fsf.org/copyleft/gpl.txt>.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef LEAK_DETECTIVE_H_
|
||||
#define LEAK_DETECTIVE_H_
|
||||
|
||||
|
||||
#ifdef LEAK_DETECTIVE
|
||||
|
||||
/**
|
||||
* Max number of stack frames to include in a backtrace.
|
||||
*/
|
||||
#define STACK_FRAMES_COUNT 30
|
||||
|
||||
|
||||
|
||||
|
||||
#endif /* LEAK_DETECTIVE */
|
||||
|
||||
#endif /* LEAK_DETECTIVE_H_ */
|
||||
@@ -24,8 +24,6 @@
|
||||
|
||||
#include "linked_list.h"
|
||||
|
||||
#include <utils/allocator.h>
|
||||
|
||||
|
||||
|
||||
typedef struct linked_list_element_t linked_list_element_t;
|
||||
@@ -69,7 +67,7 @@ struct linked_list_element_t {
|
||||
*/
|
||||
static void linked_list_element_destroy(linked_list_element_t *this)
|
||||
{
|
||||
allocator_free(this);
|
||||
free(this);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -83,7 +81,7 @@ static void linked_list_element_destroy(linked_list_element_t *this)
|
||||
|
||||
linked_list_element_t *linked_list_element_create(void *value)
|
||||
{
|
||||
linked_list_element_t *this = allocator_alloc_thing(linked_list_element_t);
|
||||
linked_list_element_t *this = malloc_thing(linked_list_element_t);
|
||||
|
||||
this->destroy = linked_list_element_destroy;
|
||||
|
||||
@@ -384,7 +382,7 @@ static void insert_after(private_iterator_t * iterator, void *item)
|
||||
*/
|
||||
static void iterator_destroy(private_iterator_t *this)
|
||||
{
|
||||
allocator_free(this);
|
||||
free(this);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -665,7 +663,7 @@ static status_t get_last(private_linked_list_t *this, void **item)
|
||||
*/
|
||||
static iterator_t *create_iterator (private_linked_list_t *linked_list,bool forward)
|
||||
{
|
||||
private_iterator_t *this = allocator_alloc_thing(private_iterator_t);
|
||||
private_iterator_t *this = malloc_thing(private_iterator_t);
|
||||
|
||||
this->public.iterate = (bool (*) (iterator_t *this, void **value)) iterate;
|
||||
this->public.has_next = (bool (*) (iterator_t *this)) iterator_has_next;
|
||||
@@ -696,7 +694,7 @@ static void linked_list_destroy(private_linked_list_t *this)
|
||||
/* values are not destroyed so memory leaks are possible
|
||||
* if list is not empty when deleting */
|
||||
}
|
||||
allocator_free(this);
|
||||
free(this);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -704,7 +702,7 @@ static void linked_list_destroy(private_linked_list_t *this)
|
||||
*/
|
||||
linked_list_t *linked_list_create()
|
||||
{
|
||||
private_linked_list_t *this = allocator_alloc_thing(private_linked_list_t);
|
||||
private_linked_list_t *this = malloc_thing(private_linked_list_t);
|
||||
|
||||
this->public.get_count = (int (*) (linked_list_t *)) get_count;
|
||||
this->public.create_iterator = (iterator_t * (*) (linked_list_t *,bool )) create_iterator;
|
||||
|
||||
@@ -30,7 +30,6 @@
|
||||
#include "logger.h"
|
||||
|
||||
#include <daemon.h>
|
||||
#include <utils/allocator.h>
|
||||
|
||||
/**
|
||||
* Maximum length of a log entry (only used for logger_s.log).
|
||||
@@ -314,8 +313,8 @@ static log_level_t get_level(private_logger_t *this)
|
||||
*/
|
||||
static void destroy(private_logger_t *this)
|
||||
{
|
||||
allocator_free(this->name);
|
||||
allocator_free(this);
|
||||
free(this->name);
|
||||
free(this);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -323,7 +322,7 @@ static void destroy(private_logger_t *this)
|
||||
*/
|
||||
logger_t *logger_create(char *logger_name, log_level_t log_level, bool log_thread_id, FILE * output)
|
||||
{
|
||||
private_logger_t *this = allocator_alloc_thing(private_logger_t);
|
||||
private_logger_t *this = malloc_thing(private_logger_t);
|
||||
|
||||
/* public functions */
|
||||
this->public.log = (void(*)(logger_t*,log_level_t,char*,...))logg;
|
||||
@@ -346,7 +345,7 @@ logger_t *logger_create(char *logger_name, log_level_t log_level, bool log_threa
|
||||
/* private variables */
|
||||
this->level = log_level;
|
||||
this->log_thread_id = log_thread_id;
|
||||
this->name = allocator_alloc(strlen(logger_name) + 1);
|
||||
this->name = malloc(strlen(logger_name) + 1);
|
||||
|
||||
strcpy(this->name,logger_name);
|
||||
this->output = output;
|
||||
|
||||
@@ -38,7 +38,7 @@ typedef enum log_level_t log_level_t;
|
||||
* - levels to specify the detail-level of the log
|
||||
*
|
||||
* Use combinations of these to build detailed loglevels, such
|
||||
* as CONTROL|MORE fore a detailed cotrol level, or
|
||||
* as CONTROL|LEVEL2 fore a detailed cotrol level, or
|
||||
* use RAW to see all raw data dumps (except private).
|
||||
*
|
||||
* @ingroup utils
|
||||
@@ -189,7 +189,7 @@ struct logger_t {
|
||||
* @param log_level or'ed set of log_levels to assign to the new logger_t object
|
||||
* @param log_thread_id TRUE if thread id should also be logged
|
||||
* @param output FILE * if log has to go on a file output, NULL for syslog
|
||||
* @return logger_t object
|
||||
* @return logger_t object
|
||||
*
|
||||
* @ingroup utils
|
||||
*/
|
||||
|
||||
@@ -25,7 +25,6 @@
|
||||
|
||||
#include <daemon.h>
|
||||
#include <definitions.h>
|
||||
#include <utils/allocator.h>
|
||||
#include <utils/linked_list.h>
|
||||
|
||||
/**
|
||||
@@ -54,33 +53,30 @@ mapping_t logger_context_t_mappings[] = {
|
||||
{MAPPING_END, NULL},
|
||||
};
|
||||
|
||||
#define DEFAULT_OUTPUT NULL
|
||||
|
||||
struct {
|
||||
char *name;
|
||||
log_level_t level;
|
||||
bool log_thread_ids;
|
||||
FILE *output;
|
||||
} logger_defaults[] = {
|
||||
{ "PARSR", ERROR|CONTROL|AUDIT|LEVEL0, TRUE, DEFAULT_OUTPUT}, /* PARSER */
|
||||
{ "GNRAT", ERROR|CONTROL|AUDIT|LEVEL0, TRUE, DEFAULT_OUTPUT}, /* GENERATOR */
|
||||
{ "IKESA", ERROR|CONTROL|AUDIT|LEVEL0, TRUE, DEFAULT_OUTPUT}, /* IKE_SA */
|
||||
{ "SAMGR", ERROR|CONTROL|AUDIT|LEVEL0, TRUE, DEFAULT_OUTPUT}, /* IKE_SA_MANAGER */
|
||||
{ "CHDSA", ERROR|CONTROL|AUDIT|LEVEL0, TRUE, DEFAULT_OUTPUT}, /* CHILD_SA */
|
||||
{ "MESSG", ERROR|CONTROL|AUDIT|LEVEL0, TRUE, DEFAULT_OUTPUT}, /* MESSAGE */
|
||||
{ "TPOOL", ERROR|CONTROL|AUDIT|LEVEL0, FALSE, DEFAULT_OUTPUT}, /* THREAD_POOL */
|
||||
{ "WORKR", ERROR|CONTROL|AUDIT|LEVEL0, TRUE, DEFAULT_OUTPUT}, /* WORKER */
|
||||
{ "SCHED", ERROR|CONTROL|AUDIT|LEVEL0, FALSE, DEFAULT_OUTPUT}, /* SCHEDULER */
|
||||
{ "SENDR", ERROR|CONTROL|AUDIT|LEVEL0, FALSE, DEFAULT_OUTPUT}, /* SENDER */
|
||||
{ "RECVR", ERROR|CONTROL|AUDIT|LEVEL0, FALSE, DEFAULT_OUTPUT}, /* RECEIVER */
|
||||
{ "SOCKT", ERROR|CONTROL|AUDIT|LEVEL0, FALSE, DEFAULT_OUTPUT}, /* SOCKET */
|
||||
{ "TESTR", ERROR|CONTROL|AUDIT|LEVEL0, FALSE, DEFAULT_OUTPUT}, /* TESTER */
|
||||
{ "DAEMN", ERROR|CONTROL|AUDIT|LEVEL0, FALSE, DEFAULT_OUTPUT}, /* DAEMON */
|
||||
{ "CONFG", ERROR|CONTROL|AUDIT|LEVEL0, TRUE, DEFAULT_OUTPUT}, /* CONFIG */
|
||||
{ "ENCPL", ERROR|CONTROL|AUDIT|LEVEL0, TRUE, DEFAULT_OUTPUT}, /* ENCRYPTION_PAYLOAD */
|
||||
{ "PAYLD", ERROR|CONTROL|AUDIT|LEVEL0, TRUE, DEFAULT_OUTPUT}, /* PAYLOAD */
|
||||
{ "DERDC", ERROR|CONTROL|AUDIT|LEVEL0, TRUE, DEFAULT_OUTPUT}, /* DER_DECODER */
|
||||
{ "DEREC", ERROR|CONTROL|AUDIT|LEVEL0, TRUE, DEFAULT_OUTPUT}, /* DER_ENCODER */
|
||||
{ "PARSR", ERROR|CONTROL|AUDIT|LEVEL0, TRUE }, /* PARSER */
|
||||
{ "GNRAT", ERROR|CONTROL|AUDIT|LEVEL0, TRUE }, /* GENERATOR */
|
||||
{ "IKESA", ERROR|CONTROL|AUDIT|LEVEL0, TRUE }, /* IKE_SA */
|
||||
{ "SAMGR", ERROR|CONTROL|AUDIT|LEVEL0, TRUE }, /* IKE_SA_MANAGER */
|
||||
{ "CHDSA", ERROR|CONTROL|AUDIT|LEVEL0, TRUE }, /* CHILD_SA */
|
||||
{ "MESSG", ERROR|CONTROL|AUDIT|LEVEL0, TRUE }, /* MESSAGE */
|
||||
{ "TPOOL", ERROR|CONTROL|AUDIT|LEVEL0, FALSE}, /* THREAD_POOL */
|
||||
{ "WORKR", ERROR|CONTROL|AUDIT|LEVEL0, TRUE }, /* WORKER */
|
||||
{ "SCHED", ERROR|CONTROL|AUDIT|LEVEL0, FALSE}, /* SCHEDULER */
|
||||
{ "SENDR", ERROR|CONTROL|AUDIT|LEVEL0, FALSE}, /* SENDER */
|
||||
{ "RECVR", ERROR|CONTROL|AUDIT|LEVEL0, FALSE}, /* RECEIVER */
|
||||
{ "SOCKT", ERROR|CONTROL|AUDIT|LEVEL0, FALSE}, /* SOCKET */
|
||||
{ "TESTR", ERROR|CONTROL|AUDIT|LEVEL0, FALSE}, /* TESTER */
|
||||
{ "DAEMN", ERROR|CONTROL|AUDIT|LEVEL0, FALSE}, /* DAEMON */
|
||||
{ "CONFG", ERROR|CONTROL|AUDIT|LEVEL0, TRUE }, /* CONFIG */
|
||||
{ "ENCPL", ERROR|CONTROL|AUDIT|LEVEL0, TRUE }, /* ENCRYPTION_PAYLOAD */
|
||||
{ "PAYLD", ERROR|CONTROL|AUDIT|LEVEL0, TRUE }, /* PAYLOAD */
|
||||
{ "DERDC", ERROR|CONTROL|AUDIT|LEVEL0, TRUE }, /* DER_DECODER */
|
||||
{ "DEREC", ERROR|CONTROL|AUDIT|LEVEL0, TRUE }, /* DER_ENCODER */
|
||||
};
|
||||
|
||||
|
||||
@@ -99,9 +95,18 @@ struct private_logger_manager_t {
|
||||
* Array of loggers, one for each context
|
||||
*/
|
||||
logger_t *loggers[LOGGER_CONTEXT_ROOF];
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* The one and only instance of the logger manager
|
||||
*/
|
||||
static private_logger_manager_t private_logger_manager;
|
||||
|
||||
/**
|
||||
* Exported pointer for the logger manager
|
||||
*/
|
||||
logger_manager_t *logger_manager = (logger_manager_t *)&private_logger_manager;
|
||||
|
||||
/**
|
||||
* Implementation of logger_manager_t.get_logger.
|
||||
*/
|
||||
@@ -174,39 +179,36 @@ static void set_output(private_logger_manager_t *this, logger_context_t context,
|
||||
|
||||
|
||||
/**
|
||||
* Implementation of logger_manager_t.destroy.
|
||||
* Creates the instance of the logger manager at library startup
|
||||
*/
|
||||
static void destroy(private_logger_manager_t *this)
|
||||
void __attribute__ ((constructor)) logger_manager_create()
|
||||
{
|
||||
int i;
|
||||
|
||||
logger_manager->get_logger = (logger_t *(*)(logger_manager_t*,logger_context_t context))get_logger;
|
||||
logger_manager->get_log_level = (log_level_t (*)(logger_manager_t *, logger_context_t)) get_log_level;
|
||||
logger_manager->enable_log_level = (void (*)(logger_manager_t *, logger_context_t, log_level_t)) enable_log_level;
|
||||
logger_manager->disable_log_level = (void (*)(logger_manager_t *, logger_context_t, log_level_t)) disable_log_level;
|
||||
logger_manager->set_output = (void (*)(logger_manager_t *, logger_context_t, FILE*)) set_output;
|
||||
|
||||
for (i = 0; i < LOGGER_CONTEXT_ROOF; i++)
|
||||
{
|
||||
private_logger_manager.loggers[i] = logger_create(logger_defaults[i].name,
|
||||
logger_defaults[i].level,
|
||||
logger_defaults[i].log_thread_ids,
|
||||
stdout);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Destroy the logger manager at library exit
|
||||
*/
|
||||
void __attribute__ ((destructor)) logger_manager_destroy()
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < LOGGER_CONTEXT_ROOF; i++)
|
||||
{
|
||||
this->loggers[i]->destroy(this->loggers[i]);
|
||||
private_logger_manager.loggers[i]->destroy(private_logger_manager.loggers[i]);
|
||||
}
|
||||
allocator_free(this);
|
||||
}
|
||||
|
||||
/*
|
||||
* Described in header.
|
||||
*/
|
||||
logger_manager_t *logger_manager_create(log_level_t default_log_level)
|
||||
{
|
||||
private_logger_manager_t *this = allocator_alloc_thing(private_logger_manager_t);
|
||||
int i;
|
||||
|
||||
this->public.get_logger = (logger_t *(*)(logger_manager_t*,logger_context_t context))get_logger;
|
||||
this->public.get_log_level = (log_level_t (*)(logger_manager_t *, logger_context_t)) get_log_level;
|
||||
this->public.enable_log_level = (void (*)(logger_manager_t *, logger_context_t, log_level_t)) enable_log_level;
|
||||
this->public.disable_log_level = (void (*)(logger_manager_t *, logger_context_t, log_level_t)) disable_log_level;
|
||||
this->public.set_output = (void (*)(logger_manager_t *, logger_context_t, FILE*)) set_output;
|
||||
this->public.destroy = (void(*)(logger_manager_t*))destroy;
|
||||
|
||||
for (i = 0; i < LOGGER_CONTEXT_ROOF; i++)
|
||||
{
|
||||
this->loggers[i] = logger_create(logger_defaults[i].name, logger_defaults[i].level,
|
||||
logger_defaults[i].log_thread_ids, stdout);//logger_defaults[i].output);
|
||||
}
|
||||
|
||||
return &this->public;
|
||||
}
|
||||
|
||||
|
||||
@@ -68,9 +68,12 @@ typedef struct logger_manager_t logger_manager_t;
|
||||
* The logger manager manages all logger_t object in a list and
|
||||
* allows their manipulation. Via a logger_context_t, the loglevel
|
||||
* of a specific logging type can be adjusted at runtime.
|
||||
* This class differs from others, as it has no constructor or destroy
|
||||
* function. The one and only instance "logger_manager" is created at
|
||||
* library start and destroyed at exit.
|
||||
*
|
||||
* @b Constructors:
|
||||
* - logger_manager_create()
|
||||
* - none, logger_manager is an instance
|
||||
*
|
||||
* @see logger_t
|
||||
*
|
||||
@@ -130,26 +133,11 @@ struct logger_manager_t {
|
||||
* @param log_level logger level to disable
|
||||
*/
|
||||
void (*set_output) (logger_manager_t *this, logger_context_t context, FILE *output);
|
||||
|
||||
/**
|
||||
* @brief Destroys a logger_manager_t object.
|
||||
*
|
||||
* All managed logger_t objects are also destroyed.
|
||||
*
|
||||
* @param this logger_manager_t object
|
||||
*/
|
||||
void (*destroy) (logger_manager_t *this);
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Constructor to create a logger_manager_t object.
|
||||
*
|
||||
* @param default_log_level default log level for all context
|
||||
* @return logger_manager_t object
|
||||
*
|
||||
* @ingroup utils
|
||||
* The single and global instance of the logger_manager
|
||||
*/
|
||||
logger_manager_t *logger_manager_create(log_level_t default_log_level);
|
||||
|
||||
extern logger_manager_t *logger_manager;
|
||||
|
||||
#endif /*LOGGER_MANAGER_H_*/
|
||||
|
||||
@@ -28,7 +28,6 @@
|
||||
|
||||
#include "randomizer.h"
|
||||
|
||||
#include <utils/allocator.h>
|
||||
|
||||
typedef struct private_randomizer_t private_randomizer_t;
|
||||
|
||||
@@ -66,7 +65,7 @@ static status_t get_bytes_from_device(private_randomizer_t *this,bool pseudo_ran
|
||||
size_t got;
|
||||
char * device_name;
|
||||
|
||||
device_name = pseudo_random ? RANDOM_DEVICE : PSEUDO_RANDOM_DEVICE;
|
||||
device_name = pseudo_random ? PSEUDO_RANDOM_DEVICE : RANDOM_DEVICE;
|
||||
|
||||
device = open(device_name, 0);
|
||||
if (device < 0) {
|
||||
@@ -103,11 +102,11 @@ static status_t allocate_random_bytes(private_randomizer_t *this, size_t bytes,
|
||||
{
|
||||
status_t status;
|
||||
chunk->len = bytes;
|
||||
chunk->ptr = allocator_alloc(bytes);
|
||||
chunk->ptr = malloc(bytes);
|
||||
status = this->get_bytes_from_device(this, FALSE, bytes, chunk->ptr);
|
||||
if (status != SUCCESS)
|
||||
{
|
||||
allocator_free(chunk->ptr);
|
||||
free(chunk->ptr);
|
||||
}
|
||||
return status;
|
||||
}
|
||||
@@ -127,11 +126,11 @@ static status_t allocate_pseudo_random_bytes(private_randomizer_t *this, size_t
|
||||
{
|
||||
status_t status;
|
||||
chunk->len = bytes;
|
||||
chunk->ptr = allocator_alloc(bytes);
|
||||
chunk->ptr = malloc(bytes);
|
||||
status = this->get_bytes_from_device(this, TRUE, bytes, chunk->ptr);
|
||||
if (status != SUCCESS)
|
||||
{
|
||||
allocator_free(chunk->ptr);
|
||||
free(chunk->ptr);
|
||||
}
|
||||
return status;
|
||||
}
|
||||
@@ -141,7 +140,7 @@ static status_t allocate_pseudo_random_bytes(private_randomizer_t *this, size_t
|
||||
*/
|
||||
static void destroy(private_randomizer_t *this)
|
||||
{
|
||||
allocator_free(this);
|
||||
free(this);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -149,7 +148,7 @@ static void destroy(private_randomizer_t *this)
|
||||
*/
|
||||
randomizer_t *randomizer_create(void)
|
||||
{
|
||||
private_randomizer_t *this = allocator_alloc_thing(private_randomizer_t);
|
||||
private_randomizer_t *this = malloc_thing(private_randomizer_t);
|
||||
|
||||
/* public functions */
|
||||
this->public.get_random_bytes = (status_t (*) (randomizer_t *,size_t, u_int8_t *)) get_random_bytes;
|
||||
|
||||
@@ -28,7 +28,6 @@
|
||||
|
||||
#include "tester.h"
|
||||
|
||||
#include <utils/allocator.h>
|
||||
#include <utils/linked_list.h>
|
||||
#include <queues/job_queue.h>
|
||||
|
||||
@@ -225,7 +224,7 @@ static void destroy(private_tester_t *tester)
|
||||
{
|
||||
private_tester_t *this = (private_tester_t*) tester;
|
||||
pthread_mutex_destroy(&(this->mutex));
|
||||
allocator_free(this);
|
||||
free(this);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -233,7 +232,7 @@ static void destroy(private_tester_t *tester)
|
||||
*/
|
||||
tester_t *tester_create(FILE *output, bool display_succeeded_asserts)
|
||||
{
|
||||
private_tester_t *this = allocator_alloc_thing(private_tester_t);
|
||||
private_tester_t *this = malloc_thing(private_tester_t);
|
||||
|
||||
/* public functions */
|
||||
this->protected.public.destroy = (void (*) (tester_t *))destroy;
|
||||
|
||||
Reference in New Issue
Block a user