tinycc-devel
[Top][All Lists]
Advanced

[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 */
 /* ------------------------------------------------------------- */



reply via email to

[Prev in Thread] Current Thread [Next in Thread]