[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [Tinycc-devel] getting debug info for stack dumps
From: |
grischka |
Subject: |
Re: [Tinycc-devel] getting debug info for stack dumps |
Date: |
Fri, 25 May 2018 15:11:25 +0200 |
User-agent: |
Thunderbird 2.0.0.23 (Windows/20090812) |
Yakov wrote:
... All I need is the nice
stack dump done by the compiled program itself (with the original language
file names and line numbers).
I did have some patch that enables backtraces, just as with tcc -g -run,
except not for -run but for standalone executables instead.
The code to access the stab sections at runtime is win32 specific though.
-- gr
Thank you
Yash
>From dfbfa24f6370b8d4038d3fe886ca047c69a381ed Mon Sep 17 00:00:00 2001
From: grischka <grischka>
Date: Wed, 15 Sep 2010 13:43:54 +0200
Subject: tccrun: enable standalone backtrace
Tested on win32. Detailed recipe:
1) Create tccbt.dll from tccrun.c
$ tcc -v tccrun.c -o tccbt.dll -shared \
-D CONFIG_TCC_BACKTRACE_ONLY -D LIBTCC_AS_DLL
2) In your program, initalize from main(). For example:
/* ------------------------------------------------------------- */
/* test.c */
void xxx()
{
*(void**)0 = 0;
}
int main(int argc, char **argv)
{
void tcc_set_exception_handler(void *mainfunc);
tcc_set_exception_handler(main);
xxx();
return 0;
}
/* ------------------------------------------------------------- */
3) Compile with -g and link with that dll, like:
$ tcc -v -g test.c -L. -ltccbt
5) Run the program and get backtraces on runtime errors:
$ ./test
Runtime error: access violation
test.c:3: at 0040100F xxx()
test.c:12: by 00401034 main()
6) Note: The unwind code is naive, so it will not work across
system callbacks and such (e.g. from a window procedure)
diff --git a/tccrun.c b/tccrun.c
index 9360164..a623895 100644
--- a/tccrun.c
+++ b/tccrun.c
@@ -42,6 +42,9 @@ ST_DATA void *rt_prog_main;
static int rt_get_caller_pc(addr_t *paddr, ucontext_t *uc, int level);
static void rt_error(ucontext_t *uc, const char *fmt, ...);
static void set_exception_handler(void);
+#ifdef _WIN32
+static int win32_lookup_module(addr_t wanted_pc, Stab_Sym** pstab, int
*pstabl, char **pstr);
+#endif
#endif
static void set_pages_executable(void *ptr, unsigned long length);
@@ -52,6 +55,25 @@ static void *win64_add_function_table(TCCState *s1);
static void win64_del_function_table(void *);
#endif
+/* ------------------------------------------------------------- */
+#ifdef CONFIG_TCC_BACKTRACE_ONLY
+ST_DATA Section *symtab_section, *strtab_section;
+ST_DATA Section *stab_section, *stabstr_section;
+PUB_FUNC char *pstrcpy(char *buf, int buf_size, const char *s)
+{
+ int l = strlen(s);
+ if (l >= buf_size)
+ l = buf_size - 1;
+ memcpy(buf, s, l);
+ buf[l] = 0;
+ return buf;
+}
+LIBTCCAPI void tcc_set_exception_handler(void *prog_main)
+{
+ set_exception_handler();
+ rt_prog_main = prog_main;
+}
+#else
/* ------------------------------------------------------------- */
/* Do all relocations (needed before using tcc_get_symbol())
Returns -1 on error. */
@@ -326,6 +348,7 @@ static void win64_del_function_table(void *p)
#endif
/* ------------------------------------------------------------- */
+#endif /* CONFIG_TCC_BACKTRACE_ONLY */
#ifdef CONFIG_TCC_BACKTRACE
ST_FUNC void tcc_set_num_callers(int n)
@@ -353,6 +376,10 @@ static addr_t rt_printline(addr_t wanted_pc, const char
*msg)
stab_str = (char *) stabstr_section->data;
}
+#ifdef _WIN32
+ win32_lookup_module (wanted_pc, &stab_sym, &stab_len, &stab_str);
+#endif
+
func_name[0] = '\0';
func_addr = 0;
incl_index = 0;
@@ -788,6 +815,74 @@ static int rt_get_caller_pc(addr_t *paddr, CONTEXT *uc,
int level)
return 0;
}
+static int win32_lookup_module (addr_t wanted_pc, Stab_Sym** pstab, int
*pstabl, char **pstr)
+{
+ HMODULE hMod[256];
+ DWORD cbNeeded, cb = sizeof hMod;
+ int j, k;
+
+ static HMODULE psapi;
+ static BOOL (WINAPI*pEnumProcessModules)(HANDLE, HMODULE *, DWORD,
LPDWORD);
+ if (NULL == psapi) {
+ psapi = LoadLibrary("psapi");
+ if (psapi)
+ *(FARPROC*)&pEnumProcessModules = GetProcAddress(psapi,
"EnumProcessModules");
+ }
+ if (NULL == pEnumProcessModules)
+ return -1;
+ if (!pEnumProcessModules(GetCurrentProcess(), hMod, cb, &cbNeeded))
+ return -1;
+ if (cbNeeded < cb)
+ cb = cbNeeded;
+
+ for (j = 0, k = cb / sizeof hMod[0]; j < k; ++j) {
+ IMAGE_DOS_HEADER *dh = (IMAGE_DOS_HEADER*)hMod[j];
+ DWORD *sig = (DWORD*)((char*)dh + dh->e_lfanew);
+ IMAGE_FILE_HEADER *ih = (IMAGE_FILE_HEADER*)(sig + 1);
+ IMAGE_OPTIONAL_HEADER *oh = (IMAGE_OPTIONAL_HEADER*)(ih + 1);
+ IMAGE_SECTION_HEADER *sh = (IMAGE_SECTION_HEADER*)(oh + 1);
+ char *str;
+ Stab_Sym *stab;
+ int stabl, f, i;
+
+ if ((addr_t)dh > wanted_pc || dh->e_magic != 0x5A4D || *sig !=
IMAGE_NT_SIGNATURE)
+ continue;
+ str = NULL, stab = NULL, stabl = f = 0;
+ redo:
+ for (i = 0; i < ih->NumberOfSections; ++i) {
+ IMAGE_SECTION_HEADER *s = sh + i;
+ addr_t t = s->VirtualAddress + (addr_t)dh;
+ unsigned l = s->Misc.VirtualSize;
+ unsigned c = s->Characteristics;
+ unsigned char *p = s->Name;
+ if (0 == f) {
+ if (0 == (c & IMAGE_SCN_MEM_EXECUTE))
+ continue;
+ if (wanted_pc >= t && wanted_pc < t + l) {
+ f = 1;
+ goto redo;
+ }
+ } else {
+ if (0 == (c & IMAGE_SCN_MEM_READ))
+ continue;
+ if (0 == memcmp(p, ".stab\0\0\0", 8))
+ stab = (Stab_Sym *)t, stabl = l;
+ if (0 == memcmp(p, ".stabstr", 8))
+ str = (char*)t;
+ if (stab && str) {
+ *pstab = stab;
+ *pstabl = stabl;
+ *pstr = str;
+ return 0;
+ }
+ }
+ }
+ if (f)
+ break;
+ }
+ return -1;
+}
+
#endif /* _WIN32 */
#endif /* CONFIG_TCC_BACKTRACE */
/* ------------------------------------------------------------- */