Replaced the temporary storage used in the kernel debug command parser. We now
have a simple dedicated heap for the kernel debugger with stacked allocation pools (deleting a pool frees all memory allocated in it). The heap should eventually be used for all commands that need temporary storage too large for the stack instead of each using its own static buffer. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@30949 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -18,6 +18,9 @@
|
|||||||
// benaphore-style.
|
// benaphore-style.
|
||||||
#define KDEBUG KDEBUG_LEVEL_2
|
#define KDEBUG KDEBUG_LEVEL_2
|
||||||
|
|
||||||
|
// Size of the heap used by the kernel debugger.
|
||||||
|
#define KDEBUG_HEAP (64 * 1024)
|
||||||
|
|
||||||
// Set to 0 to disable support for kernel breakpoints.
|
// Set to 0 to disable support for kernel breakpoints.
|
||||||
#define KERNEL_BREAKPOINTS 1
|
#define KERNEL_BREAKPOINTS 1
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,71 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2009, Ingo Weinhold, [email protected]
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
#ifndef _KERNEL_DEBUG_HEAP_H
|
||||||
|
#define _KERNEL_DEBUG_HEAP_H
|
||||||
|
|
||||||
|
#include <debug.h>
|
||||||
|
|
||||||
|
|
||||||
|
struct DebugAllocPool;
|
||||||
|
typedef struct DebugAllocPool debug_alloc_pool;
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
debug_alloc_pool* create_debug_alloc_pool();
|
||||||
|
void delete_debug_alloc_pool(debug_alloc_pool* pool);
|
||||||
|
void* debug_malloc(size_t size);
|
||||||
|
void debug_free(void* address);
|
||||||
|
void debug_heap_init();
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
|
||||||
|
struct kdebug_alloc_t {};
|
||||||
|
extern const kdebug_alloc_t kdebug_alloc;
|
||||||
|
|
||||||
|
inline void*
|
||||||
|
operator new(size_t size, const kdebug_alloc_t&) throw()
|
||||||
|
{
|
||||||
|
return debug_malloc(size);
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace DebugAlloc {
|
||||||
|
template<typename Type>
|
||||||
|
inline void
|
||||||
|
destroy(Type* object)
|
||||||
|
{
|
||||||
|
if (object != NULL) {
|
||||||
|
object->~Type();
|
||||||
|
debug_free(object);
|
||||||
|
// NOTE: Doesn't work for multiple inheritence!
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct DebugAllocPoolScope {
|
||||||
|
DebugAllocPoolScope()
|
||||||
|
{
|
||||||
|
fPool = create_debug_alloc_pool();
|
||||||
|
}
|
||||||
|
|
||||||
|
~DebugAllocPoolScope()
|
||||||
|
{
|
||||||
|
delete_debug_alloc_pool(fPool);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
DebugAllocPool* fPool;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // __cplusplus
|
||||||
|
|
||||||
|
#endif /* _KERNEL_DEBUG_HEAP_H */
|
||||||
@@ -10,6 +10,7 @@ KernelMergeObject kernel_debug.o :
|
|||||||
debug.cpp
|
debug.cpp
|
||||||
debug_builtin_commands.cpp
|
debug_builtin_commands.cpp
|
||||||
debug_commands.cpp
|
debug_commands.cpp
|
||||||
|
debug_heap.cpp
|
||||||
debug_paranoia.cpp
|
debug_paranoia.cpp
|
||||||
debug_parser.cpp
|
debug_parser.cpp
|
||||||
debug_variables.cpp
|
debug_variables.cpp
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2008, Ingo Weinhold, [email protected].
|
* Copyright 2008-2009, Ingo Weinhold, [email protected].
|
||||||
* Copyright 2002-2008, Axel Dörfler, [email protected].
|
* Copyright 2002-2008, Axel Dörfler, [email protected].
|
||||||
* Distributed under the terms of the MIT License.
|
* Distributed under the terms of the MIT License.
|
||||||
*
|
*
|
||||||
@@ -13,6 +13,7 @@
|
|||||||
|
|
||||||
#include <cpu.h>
|
#include <cpu.h>
|
||||||
#include <debug.h>
|
#include <debug.h>
|
||||||
|
#include <debug_heap.h>
|
||||||
#include <debug_paranoia.h>
|
#include <debug_paranoia.h>
|
||||||
#include <driver_settings.h>
|
#include <driver_settings.h>
|
||||||
#include <frame_buffer_console.h>
|
#include <frame_buffer_console.h>
|
||||||
@@ -665,6 +666,8 @@ kernel_debugger_loop(void)
|
|||||||
int32 previousCPU = sDebuggerOnCPU;
|
int32 previousCPU = sDebuggerOnCPU;
|
||||||
sDebuggerOnCPU = smp_get_current_cpu();
|
sDebuggerOnCPU = smp_get_current_cpu();
|
||||||
|
|
||||||
|
DebugAllocPool* allocPool = create_debug_alloc_pool();
|
||||||
|
|
||||||
kprintf("Welcome to Kernel Debugging Land...\n");
|
kprintf("Welcome to Kernel Debugging Land...\n");
|
||||||
|
|
||||||
if (struct thread* thread = thread_get_current_thread()) {
|
if (struct thread* thread = thread_get_current_thread()) {
|
||||||
@@ -721,6 +724,8 @@ kernel_debugger_loop(void)
|
|||||||
sCurrentLine = 0;
|
sCurrentLine = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
delete_debug_alloc_pool(allocPool);
|
||||||
|
|
||||||
sDebuggerOnCPU = previousCPU;
|
sDebuggerOnCPU = previousCPU;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1210,6 +1215,7 @@ debug_init_post_vm(kernel_args* args)
|
|||||||
|
|
||||||
debug_builtin_commands_init();
|
debug_builtin_commands_init();
|
||||||
|
|
||||||
|
debug_heap_init();
|
||||||
debug_variables_init();
|
debug_variables_init();
|
||||||
frame_buffer_console_init(args);
|
frame_buffer_console_init(args);
|
||||||
arch_debug_console_init_settings(args);
|
arch_debug_console_init_settings(args);
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2008, Ingo Weinhold, ingo_weinhold@gmx.de
|
* Copyright 2008-2009, Ingo Weinhold, ingo_weinhold@gmx.de
|
||||||
* Copyright 2002-2008, Axel Dörfler, axeld@pinc-software.de
|
* Copyright 2002-2008, Axel Dörfler, axeld@pinc-software.de
|
||||||
* Distributed under the terms of the MIT License.
|
* Distributed under the terms of the MIT License.
|
||||||
*
|
*
|
||||||
@@ -16,6 +16,7 @@
|
|||||||
#include <KernelExport.h>
|
#include <KernelExport.h>
|
||||||
|
|
||||||
#include <debug.h>
|
#include <debug.h>
|
||||||
|
#include <debug_heap.h>
|
||||||
#include <lock.h>
|
#include <lock.h>
|
||||||
#include <thread.h>
|
#include <thread.h>
|
||||||
#include <util/AutoLock.h>
|
#include <util/AutoLock.h>
|
||||||
@@ -273,6 +274,9 @@ invoke_debugger_command(struct debugger_command *command, int argc, char** argv)
|
|||||||
// replace argv[0] with the actual command name
|
// replace argv[0] with the actual command name
|
||||||
argv[0] = (char *)command->name;
|
argv[0] = (char *)command->name;
|
||||||
|
|
||||||
|
DebugAllocPoolScope allocPoolScope;
|
||||||
|
// Will automatically clean up all allocations the command leaves over.
|
||||||
|
|
||||||
// Invoking the command directly might be useful when debugging debugger
|
// Invoking the command directly might be useful when debugging debugger
|
||||||
// commands.
|
// commands.
|
||||||
if (gInvokeCommandDirectly)
|
if (gInvokeCommandDirectly)
|
||||||
|
|||||||
@@ -0,0 +1,302 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <debug_heap.h>
|
||||||
|
|
||||||
|
#include <new>
|
||||||
|
|
||||||
|
#include <util/AutoLock.h>
|
||||||
|
|
||||||
|
|
||||||
|
#define INITIAL_HEAP_SIZE B_PAGE_SIZE
|
||||||
|
|
||||||
|
static char sInitialHeap[INITIAL_HEAP_SIZE];
|
||||||
|
static void* sHeapBase = sInitialHeap;
|
||||||
|
static size_t sHeapSize = INITIAL_HEAP_SIZE;
|
||||||
|
|
||||||
|
const kdebug_alloc_t kdebug_alloc = {};
|
||||||
|
|
||||||
|
|
||||||
|
struct allocation_header {
|
||||||
|
uint32 size : 31; // size in allocation_header units
|
||||||
|
bool free : 1;
|
||||||
|
uint32 previous;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct free_entry : allocation_header {
|
||||||
|
uint32 previous_free;
|
||||||
|
uint32 next_free;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
struct DebugAllocPool {
|
||||||
|
void Init(void* heap, size_t heapSize)
|
||||||
|
{
|
||||||
|
fParent = NULL;
|
||||||
|
fChild = NULL;
|
||||||
|
|
||||||
|
uint32 size = heapSize / 8;
|
||||||
|
fBase = (allocation_header*)heap - 1;
|
||||||
|
fEnd = size + 1;
|
||||||
|
fFirstFree = 0;
|
||||||
|
fLastFree = 0;
|
||||||
|
|
||||||
|
// add free entry spanning the whole area
|
||||||
|
fBase[1].size = size - 1;
|
||||||
|
fBase[1].previous = 0;
|
||||||
|
_InsertFreeEntry(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
DebugAllocPool* CreateChildPool()
|
||||||
|
{
|
||||||
|
// do we already have a child pool?
|
||||||
|
if (fChild != NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
// create the pool object
|
||||||
|
DebugAllocPool* pool
|
||||||
|
= (DebugAllocPool*)Allocate(sizeof(DebugAllocPool));
|
||||||
|
if (pool == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
// do we have enough free space?
|
||||||
|
if (fLastFree == 0 || fBase[fLastFree].size < 2) {
|
||||||
|
Free(pool);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
allocation_header* header = &fBase[fLastFree];
|
||||||
|
_RemoveFreeEntry(fLastFree);
|
||||||
|
|
||||||
|
pool->Init(header + 1, header->size * 8);
|
||||||
|
pool->fParent = this;
|
||||||
|
|
||||||
|
return fChild = pool;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Destroy()
|
||||||
|
{
|
||||||
|
if (fParent != NULL) {
|
||||||
|
fParent->fChild = NULL;
|
||||||
|
fParent->Free(fBase + 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DebugAllocPool* Parent() const
|
||||||
|
{
|
||||||
|
return fParent;
|
||||||
|
}
|
||||||
|
|
||||||
|
void* Allocate(size_t size)
|
||||||
|
{
|
||||||
|
size = (size + 7) / 8;
|
||||||
|
uint32 index = fFirstFree;
|
||||||
|
while (index != 0 && fBase[index].size < size)
|
||||||
|
index = ((free_entry*)&fBase[index])->next_free;
|
||||||
|
|
||||||
|
if (index == 0)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
_RemoveFreeEntry(index);
|
||||||
|
|
||||||
|
// if the entry is big enough, we split it
|
||||||
|
if (fBase[index].size - size >= 2) {
|
||||||
|
uint32 next = index + 1 + size;
|
||||||
|
uint32 nextNext = index + 1 + fBase[index].size;
|
||||||
|
fBase[next].size = fBase[index].size - size - 1;
|
||||||
|
fBase[next].previous = index;
|
||||||
|
fBase[index].size = size;
|
||||||
|
_InsertFreeEntry(next);
|
||||||
|
|
||||||
|
if (nextNext < fEnd)
|
||||||
|
fBase[nextNext].previous = next;
|
||||||
|
}
|
||||||
|
|
||||||
|
return &fBase[index + 1];
|
||||||
|
}
|
||||||
|
|
||||||
|
void Free(void* address)
|
||||||
|
{
|
||||||
|
// check address
|
||||||
|
if (((addr_t)address & 7) != 0 || address <= fBase + 1
|
||||||
|
|| address >= fBase + fEnd) {
|
||||||
|
kprintf("DebugAllocator::Free(%p): bad address\n", address);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// get header
|
||||||
|
allocation_header* header = (allocation_header*)address - 1;
|
||||||
|
uint32 index = header - fBase;
|
||||||
|
if (header->free) {
|
||||||
|
kprintf("DebugAllocator::Free(%p): double free\n", address);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32 next = index + 1 + header->size;
|
||||||
|
|
||||||
|
// join with previous, if possible
|
||||||
|
if (index > 1 && fBase[header->previous].free) {
|
||||||
|
uint32 previous = header->previous;
|
||||||
|
_RemoveFreeEntry(previous);
|
||||||
|
|
||||||
|
fBase[previous].size += 1 + header->size;
|
||||||
|
fBase[next].previous = previous;
|
||||||
|
|
||||||
|
index = previous;
|
||||||
|
header = fBase + index;
|
||||||
|
}
|
||||||
|
|
||||||
|
// join with next, if possible
|
||||||
|
if (next < fEnd && fBase[next].free) {
|
||||||
|
_RemoveFreeEntry(next);
|
||||||
|
|
||||||
|
header->size += 1 + fBase[next].size;
|
||||||
|
|
||||||
|
uint32 nextNext = index + 1 + header->size;
|
||||||
|
if (nextNext < fEnd)
|
||||||
|
fBase[nextNext].previous = index;
|
||||||
|
}
|
||||||
|
|
||||||
|
_InsertFreeEntry(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
void _InsertFreeEntry(uint32 index)
|
||||||
|
{
|
||||||
|
// find the insertion point -- list is sorted by ascending size
|
||||||
|
uint32 size = fBase[index].size;
|
||||||
|
uint32 next = fFirstFree;
|
||||||
|
while (next != 0 && size > fBase[next].size)
|
||||||
|
next = ((free_entry*)&fBase[next])->next_free;
|
||||||
|
|
||||||
|
// insert
|
||||||
|
uint32 previous;
|
||||||
|
if (next != 0) {
|
||||||
|
previous = ((free_entry*)&fBase[next])->previous_free;
|
||||||
|
((free_entry*)&fBase[next])->previous_free = index;
|
||||||
|
} else {
|
||||||
|
previous = fLastFree;
|
||||||
|
fLastFree = index;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (previous != 0)
|
||||||
|
((free_entry*)&fBase[previous])->next_free = index;
|
||||||
|
else
|
||||||
|
fFirstFree = index;
|
||||||
|
|
||||||
|
((free_entry*)&fBase[index])->previous_free = previous;
|
||||||
|
((free_entry*)&fBase[index])->next_free = next;
|
||||||
|
|
||||||
|
fBase[index].free = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void _RemoveFreeEntry(uint32 index)
|
||||||
|
{
|
||||||
|
uint32 previous = ((free_entry*)&fBase[index])->previous_free;
|
||||||
|
uint32 next = ((free_entry*)&fBase[index])->next_free;
|
||||||
|
|
||||||
|
if (previous != 0)
|
||||||
|
((free_entry*)&fBase[previous])->next_free = next;
|
||||||
|
else
|
||||||
|
fFirstFree = next;
|
||||||
|
|
||||||
|
if (next != 0)
|
||||||
|
((free_entry*)&fBase[next])->previous_free = previous;
|
||||||
|
else
|
||||||
|
fLastFree = previous;
|
||||||
|
|
||||||
|
fBase[index].free = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
DebugAllocPool* fParent;
|
||||||
|
DebugAllocPool* fChild;
|
||||||
|
allocation_header* fBase; // actually base - 1, so that index 0 is
|
||||||
|
// invalid
|
||||||
|
uint32 fEnd;
|
||||||
|
uint32 fFirstFree;
|
||||||
|
uint32 fLastFree;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
static DebugAllocPool* sCurrentPool;
|
||||||
|
static DebugAllocPool sInitialPool;
|
||||||
|
|
||||||
|
|
||||||
|
debug_alloc_pool*
|
||||||
|
create_debug_alloc_pool()
|
||||||
|
{
|
||||||
|
if (sCurrentPool == NULL) {
|
||||||
|
sInitialPool.Init(sHeapBase, sHeapSize);
|
||||||
|
sCurrentPool = &sInitialPool;
|
||||||
|
return sCurrentPool;
|
||||||
|
}
|
||||||
|
|
||||||
|
DebugAllocPool* pool = sCurrentPool->CreateChildPool();
|
||||||
|
if (pool == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
sCurrentPool = pool;
|
||||||
|
return sCurrentPool;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
delete_debug_alloc_pool(debug_alloc_pool* pool)
|
||||||
|
{
|
||||||
|
if (pool == NULL || sCurrentPool == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// find the pool in the hierarchy
|
||||||
|
DebugAllocPool* otherPool = sCurrentPool;
|
||||||
|
while (otherPool != NULL && otherPool != pool)
|
||||||
|
otherPool = otherPool->Parent();
|
||||||
|
|
||||||
|
if (otherPool == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// destroy the pool
|
||||||
|
sCurrentPool = pool->Parent();
|
||||||
|
pool->Destroy();
|
||||||
|
|
||||||
|
if (pool != &sInitialPool)
|
||||||
|
debug_free(pool);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void*
|
||||||
|
debug_malloc(size_t size)
|
||||||
|
{
|
||||||
|
if (sCurrentPool == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
return sCurrentPool->Allocate(size);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
debug_free(void* address)
|
||||||
|
{
|
||||||
|
if (address != NULL && sCurrentPool != NULL)
|
||||||
|
sCurrentPool->Free(address);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
debug_heap_init()
|
||||||
|
{
|
||||||
|
// create the heap area
|
||||||
|
void* base;
|
||||||
|
area_id area = create_area("kdebug heap", (void**)&base,
|
||||||
|
B_ANY_KERNEL_ADDRESS, KDEBUG_HEAP, B_FULL_LOCK,
|
||||||
|
B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA);
|
||||||
|
if (area < 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// switch from the small static buffer to the area
|
||||||
|
InterruptsLocker locker;
|
||||||
|
sHeapBase = base;
|
||||||
|
sHeapSize = KDEBUG_HEAP;
|
||||||
|
}
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2008, Ingo Weinhold, ingo_weinhold@gmx.de
|
* Copyright 2008-2009, Ingo Weinhold, ingo_weinhold@gmx.de
|
||||||
* Copyright 2006, Stephan Aßmus, superstippi@gmx.de
|
* Copyright 2006, Stephan Aßmus, superstippi@gmx.de
|
||||||
* Distributed under the terms of the MIT License.
|
* Distributed under the terms of the MIT License.
|
||||||
*/
|
*/
|
||||||
@@ -14,6 +14,8 @@
|
|||||||
|
|
||||||
#include <KernelExport.h>
|
#include <KernelExport.h>
|
||||||
|
|
||||||
|
#include <debug_heap.h>
|
||||||
|
|
||||||
#include "debug_commands.h"
|
#include "debug_commands.h"
|
||||||
#include "debug_variables.h"
|
#include "debug_variables.h"
|
||||||
|
|
||||||
@@ -46,7 +48,6 @@ static const int kMaxTokenLength = 128;
|
|||||||
static const int kJumpBufferCount = 10;
|
static const int kJumpBufferCount = 10;
|
||||||
|
|
||||||
static const int kMaxArgumentCount = 64;
|
static const int kMaxArgumentCount = 64;
|
||||||
static const size_t kTemporaryStorageSize = 10240;
|
|
||||||
|
|
||||||
static jmp_buf sJumpBuffers[kJumpBufferCount];
|
static jmp_buf sJumpBuffers[kJumpBufferCount];
|
||||||
static int sNextJumpBufferIndex = 0;
|
static int sNextJumpBufferIndex = 0;
|
||||||
@@ -57,10 +58,6 @@ static int sExceptionPosition;
|
|||||||
static char sTempBuffer[128];
|
static char sTempBuffer[128];
|
||||||
// for composing debug output etc.
|
// for composing debug output etc.
|
||||||
|
|
||||||
// temporary storage for command argument vectors and the arguments itself
|
|
||||||
static uint8 sTemporaryStorage[kTemporaryStorageSize];
|
|
||||||
static size_t sTemporaryStorageUsed = 0;
|
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
TOKEN_ASSIGN_FLAG = 0x100,
|
TOKEN_ASSIGN_FLAG = 0x100,
|
||||||
TOKEN_FLAGS = TOKEN_ASSIGN_FLAG,
|
TOKEN_FLAGS = TOKEN_ASSIGN_FLAG,
|
||||||
@@ -143,44 +140,16 @@ parse_exception(const char* message, int32 position)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// #pragma mark - temporary storage
|
|
||||||
|
|
||||||
|
|
||||||
static void*
|
static void*
|
||||||
allocate_temp_storage(size_t size)
|
checked_malloc(size_t size)
|
||||||
{
|
{
|
||||||
// 8 byte align
|
void* address = debug_malloc(size);
|
||||||
size = (size + 7) & ~7;
|
if (address == NULL) {
|
||||||
|
parse_exception("out of memory for command execution", -1);
|
||||||
if (sTemporaryStorageUsed + size > kTemporaryStorageSize) {
|
|
||||||
parse_exception("out of temporary storage for command execution", -1);
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void* buffer = sTemporaryStorage + sTemporaryStorageUsed;
|
return address;
|
||||||
sTemporaryStorageUsed += size;
|
|
||||||
|
|
||||||
return buffer;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void
|
|
||||||
free_temp_storage(void* _buffer)
|
|
||||||
{
|
|
||||||
uint8* buffer = (uint8*)_buffer;
|
|
||||||
|
|
||||||
if (buffer == NULL)
|
|
||||||
return;
|
|
||||||
|
|
||||||
// must be freed in the reverse allocation order
|
|
||||||
if (buffer < sTemporaryStorage
|
|
||||||
|| buffer > sTemporaryStorage + sTemporaryStorageUsed) {
|
|
||||||
panic("Invalid pointer passed to free_temp_storage(): %p, temp "
|
|
||||||
"storage base: %p", buffer, sTemporaryStorage);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
sTemporaryStorageUsed = buffer - sTemporaryStorage;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -750,7 +719,7 @@ ExpressionParser::_ParseExpression(bool expectAssignment)
|
|||||||
uint64
|
uint64
|
||||||
ExpressionParser::_ParseCommandPipe(int& returnCode)
|
ExpressionParser::_ParseCommandPipe(int& returnCode)
|
||||||
{
|
{
|
||||||
debugger_command_pipe* pipe = (debugger_command_pipe*)allocate_temp_storage(
|
debugger_command_pipe* pipe = (debugger_command_pipe*)checked_malloc(
|
||||||
sizeof(debugger_command_pipe));
|
sizeof(debugger_command_pipe));
|
||||||
|
|
||||||
pipe->segment_count = 0;
|
pipe->segment_count = 0;
|
||||||
@@ -773,7 +742,7 @@ ExpressionParser::_ParseCommandPipe(int& returnCode)
|
|||||||
// invoke the pipe
|
// invoke the pipe
|
||||||
returnCode = invoke_debugger_command_pipe(pipe);
|
returnCode = invoke_debugger_command_pipe(pipe);
|
||||||
|
|
||||||
free_temp_storage(pipe);
|
debug_free(pipe);
|
||||||
|
|
||||||
return get_debug_variable("_", 0);
|
return get_debug_variable("_", 0);
|
||||||
}
|
}
|
||||||
@@ -806,8 +775,7 @@ ExpressionParser::_ParseCommand(debugger_command_pipe_segment& segment)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// allocate temporary buffer for the argument vector
|
// allocate temporary buffer for the argument vector
|
||||||
char** argv = (char**)allocate_temp_storage(
|
char** argv = (char**)checked_malloc(kMaxArgumentCount * sizeof(char*));
|
||||||
kMaxArgumentCount * sizeof(char*));
|
|
||||||
int argc = 0;
|
int argc = 0;
|
||||||
argv[argc++] = (char*)command->name;
|
argv[argc++] = (char*)command->name;
|
||||||
|
|
||||||
@@ -955,7 +923,7 @@ ExpressionParser::_AddArgument(int& argc, char** argv, const char* argument,
|
|||||||
if (length < 0)
|
if (length < 0)
|
||||||
length = strlen(argument);
|
length = strlen(argument);
|
||||||
length++;
|
length++;
|
||||||
char* buffer = (char*)allocate_temp_storage(length);
|
char* buffer = (char*)checked_malloc(length);
|
||||||
strlcpy(buffer, argument, length);
|
strlcpy(buffer, argument, length);
|
||||||
|
|
||||||
argv[argc++] = buffer;
|
argv[argc++] = buffer;
|
||||||
@@ -1169,9 +1137,8 @@ evaluate_debug_expression(const char* expression, uint64* _result, bool silent)
|
|||||||
|
|
||||||
bool success;
|
bool success;
|
||||||
uint64 result;
|
uint64 result;
|
||||||
void* temporaryStorageMark = allocate_temp_storage(0);
|
DebugAllocPoolScope allocPoolScope;
|
||||||
// get a temporary storage mark, so we can cleanup everything that
|
// Will clean up all allocations when we return.
|
||||||
// is allocated during the evaluation
|
|
||||||
|
|
||||||
if (setjmp(sJumpBuffers[sNextJumpBufferIndex++]) == 0) {
|
if (setjmp(sJumpBuffers[sNextJumpBufferIndex++]) == 0) {
|
||||||
result = ExpressionParser().EvaluateExpression(expression);
|
result = ExpressionParser().EvaluateExpression(expression);
|
||||||
@@ -1190,9 +1157,6 @@ evaluate_debug_expression(const char* expression, uint64* _result, bool silent)
|
|||||||
|
|
||||||
sNextJumpBufferIndex--;
|
sNextJumpBufferIndex--;
|
||||||
|
|
||||||
// cleanup temp allocations
|
|
||||||
free_temp_storage(temporaryStorageMark);
|
|
||||||
|
|
||||||
if (success && _result != NULL)
|
if (success && _result != NULL)
|
||||||
*_result = result;
|
*_result = result;
|
||||||
|
|
||||||
@@ -1210,9 +1174,8 @@ evaluate_debug_command(const char* commandLine)
|
|||||||
}
|
}
|
||||||
|
|
||||||
int returnCode = 0;
|
int returnCode = 0;
|
||||||
void* temporaryStorageMark = allocate_temp_storage(0);
|
DebugAllocPoolScope allocPoolScope;
|
||||||
// get a temporary storage mark, so we can cleanup everything that
|
// Will clean up all allocations when we return.
|
||||||
// is allocated during the evaluation
|
|
||||||
|
|
||||||
if (setjmp(sJumpBuffers[sNextJumpBufferIndex++]) == 0) {
|
if (setjmp(sJumpBuffers[sNextJumpBufferIndex++]) == 0) {
|
||||||
ExpressionParser().EvaluateCommand(commandLine, returnCode);
|
ExpressionParser().EvaluateCommand(commandLine, returnCode);
|
||||||
@@ -1226,9 +1189,6 @@ evaluate_debug_command(const char* commandLine)
|
|||||||
|
|
||||||
sNextJumpBufferIndex--;
|
sNextJumpBufferIndex--;
|
||||||
|
|
||||||
// cleanup temp allocations
|
|
||||||
free_temp_storage(temporaryStorageMark);
|
|
||||||
|
|
||||||
return returnCode;
|
return returnCode;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1244,9 +1204,8 @@ parse_next_debug_command_argument(const char** expressionString, char* buffer,
|
|||||||
}
|
}
|
||||||
|
|
||||||
status_t error;
|
status_t error;
|
||||||
void* temporaryStorageMark = allocate_temp_storage(0);
|
DebugAllocPoolScope allocPoolScope;
|
||||||
// get a temporary storage mark, so we can cleanup everything that
|
// Will clean up all allocations when we return.
|
||||||
// is allocated during the evaluation
|
|
||||||
|
|
||||||
if (setjmp(sJumpBuffers[sNextJumpBufferIndex++]) == 0) {
|
if (setjmp(sJumpBuffers[sNextJumpBufferIndex++]) == 0) {
|
||||||
error = ExpressionParser().ParseNextCommandArgument(expressionString,
|
error = ExpressionParser().ParseNextCommandArgument(expressionString,
|
||||||
@@ -1262,8 +1221,5 @@ parse_next_debug_command_argument(const char** expressionString, char* buffer,
|
|||||||
|
|
||||||
sNextJumpBufferIndex--;
|
sNextJumpBufferIndex--;
|
||||||
|
|
||||||
// cleanup temp allocations
|
|
||||||
free_temp_storage(temporaryStorageMark);
|
|
||||||
|
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user