Files
QNX/lib/malloc/dbg/bt.c
2025-08-20 19:02:58 +08:00

134 lines
3.6 KiB
C

/*
* $QNXtpLicenseC:
* Copyright 2007, QNX Software Systems. All Rights Reserved.
*
* You must obtain a written license from and pay applicable license fees to QNX
* Software Systems before you may reproduce, modify or distribute this software,
* or any work that includes all or part of this software. Free development
* licenses are available for evaluation and non-commercial purposes. For more
* information visit http://licensing.qnx.com or email licensing@qnx.com.
*
* This file may contain contributions from others. Please review this entire
* file for other proprietary rights or license notices, as well as the QNX
* Development Suite License Guide at http://licensing.qnx.com/license-guide/
* for other information.
* $
*/
#include <stdlib.h>
#include <sys/types.h>
#include <sys/storage.h>
#include "context.h"
ulong_t bt_stack_from = 0;
#ifdef GET_REGFP
static int
thr_stksegment(stack_t *stkseg) {
if (stkseg) {
ulong_t base = (ulong_t)__tls();
stkseg->ss_sp = (void *)base; /* hack! */
stkseg->ss_size = (ulong_t)((char *)base - (char *)__tls()->__stackaddr);
return 0;
}
return -1;
}
static int
get_traceback(void **buffer, int size, int starting_line) {
ucontext_t uc;
void *ip = NULL;
long *fp = NULL;
ulong_t stacklo, stackhi;
int i, found;
//if (_argv == NULL) return; /* don't try to traceback inside ldd */
if (size <= 0) {
return 0;
}
uc.uc_mcontext.cpu.ebp = _ebp();
//uc.uc_mcontext.cpu.eip = starting_line;
thr_stksegment((void *)&uc.uc_stack);
uc.uc_stack.ss_flags = 0;
stacklo = (ulong_t)uc.uc_stack.ss_sp - uc.uc_stack.ss_size;
stackhi = (ulong_t)uc.uc_stack.ss_sp;
/*
* Find the correct frame on the stack
*/
for (found = (starting_line == 0), i = 0, fp = (long *)GET_REGFP(&uc.uc_mcontext.cpu);
fp != NULL && i < size; fp = GET_FRAME_PREVIOUS(fp)) {
if ((ulong_t)fp < stacklo || (ulong_t)fp > stackhi) {
break;
}
if (bt_stack_from!=0 && (ulong_t)fp < bt_stack_from) {
continue;
}
ip = (void *)GET_FRAME_RETURN_ADDRESS(fp);
if (ip == NULL) {
break;
}
if (!found) {
if (starting_line == (int)ip) {
found = 1;
}
}
if (found && buffer) {
buffer[i++] = ip;
}
}
/*
* if we did not found the starting point do it again
*/
if (!found) {
i=0;
if (buffer) {
// stack trace should start with given address
if (starting_line!=0)
buffer[i++] = starting_line;
}
for (fp = (long *)GET_REGFP(&uc.uc_mcontext.cpu);
fp != NULL && i < size; fp = GET_FRAME_PREVIOUS(fp)) {
if ((ulong_t)fp < stacklo || (ulong_t)fp > stackhi) {
break;
}
if (bt_stack_from!=0 && (ulong_t)fp < bt_stack_from) {
continue;
}
ip = (void *)GET_FRAME_RETURN_ADDRESS(fp);
if (ip == NULL) {
break;
}
if (buffer) {
buffer[i++] = ip;
}
}
}
return i;
}
#else
static int
get_traceback(void **buffer, int size, int starting_line) {
return 0;
}
#endif
/*
* Function int backtrace(void **buffer, int size)
* Place the information in buffer.
* Return value is the number of entries in buffer at most "size"
*/
int
backtrace(void **buffer, int size, int starting_line) {
return get_traceback(buffer, size, starting_line);
}