Any ways to get addr2line working with DMD? works fine with GDC

ryuukk_ ryuukk.dev at gmail.com
Tue Mar 21 22:26:39 UTC 2023


I found what was the issue!! https://stackoverflow.com/a/63856113

> The 0x55XXXXXXXXXX address you got is most likely the memory 
> address of the function after the EXE is loaded from disk. 
> addr2line only recognizes VMA addresses like the ones that you 
> got from disassembling with objdump.


It now works, using the code that was provided in that answer!

Now i can catch segfaults and get a precise location in my code 
without fuss!

Hopefully it is as easy with windows..


```D
extern (C) void main()
{
     signal(SIGSEGV, &handler);
     signal(SIGUSR1, &handler);

     test();
}

void test()
{
     int* a;

     *a = 1;
}
```

```
-------------------------------------------------------------------+
Received signal SIGSEGV (11)
-------------------------------------------------------------------+
executable: /mnt/c/tmp/backtrace/app
backtrace: 6
/mnt/c/tmp/backtrace/app.d:25 void app.test()+0xe
/mnt/c/tmp/backtrace/app.d:19 main+0x2b
??:0 __libc_start_main+0xf3
??:? _start+0x2e
```



Here is the fullcode so far (needs cleanup and, selective imports 
to keep track of what's really neded):

```D
import core.stdc.signal : SIGSEGV, SIGFPE, SIGILL, SIGABRT, 
signal;
import core.stdc.stdlib : free, exit;
import core.stdc.string : strlen, memcpy;
import core.stdc.stdio : fprintf, stderr, printf, sprintf, fgets, 
fclose, FILE;
import core.sys.posix.unistd : STDERR_FILENO, readlink;
import core.sys.posix.signal : SIGUSR1;
import core.sys.posix.stdio : popen, pclose;
import core.sys.linux.execinfo : backtrace, backtrace_symbols;
import core.sys.linux.dlfcn : dladdr, dladdr1, Dl_info, 
RTLD_DL_LINKMAP;
import core.sys.linux.link : link_map;


extern (C) void main()
{
     signal(SIGSEGV, &handler);
     signal(SIGUSR1, &handler);

     test();
}

void test()
{
     int* a;

     *a = 1;
}

extern (C) void handler(int sig) nothrow @nogc
{
     enum MAX_DEPTH = 6;

     string signal_string;
     switch (sig)
     {
     case SIGSEGV:
         signal_string = "SIGSEGV";
         break;
     case SIGFPE:
         signal_string = "SIGFPE";
         break;
     case SIGILL:
         signal_string = "SIGILL";
         break;
     case SIGABRT:
         signal_string = "SIGABRT";
         break;
     default:
         signal_string = "unknown";
         break;
     }


     fprintf(stderr, 
"-------------------------------------------------------------------+\r\n");
     fprintf(stderr, "Received signal %s (%d)\r\n", 
signal_string.ptr, sig);
     fprintf(stderr, 
"-------------------------------------------------------------------+\r\n");

     void*[MAX_DEPTH] trace;
     int stack_depth = backtrace(&trace[0], MAX_DEPTH);
     char** strings = backtrace_symbols(&trace[0], stack_depth);

     enum BUF_SIZE = 1024;
     char[BUF_SIZE] syscom = 0;
     char[BUF_SIZE] my_exe = 0;
     char[BUF_SIZE] output = 0;

     readlink("/proc/self/exe", &my_exe[0], BUF_SIZE);

     printf("executable: %s\n", &my_exe[0]);
     printf("backtrace: %i\n", stack_depth);

     for (auto i = 2; i < stack_depth; ++i)
     {
         auto line = strings[i];
         auto len = strlen(line);
         bool insideParenthesis;
         int startParenthesis;
         int endParenthesis;
         for (int j = 0; j < len; j++)
         {
             // ()
             if (!insideParenthesis && line[j] == '(')
             {
                 insideParenthesis = true;
                 startParenthesis = j + 1;
             }
             else if (insideParenthesis && line[j] == ')')
             {
                 insideParenthesis = false;
                 endParenthesis = j;
             }
         }
         auto addr = convert_to_vma(cast(size_t) trace[i]);
         FILE* fp;

         auto locLen = sprintf(&syscom[0], "addr2line -e %s %p | 
ddemangle", &my_exe[0], addr);
         fp = popen(&syscom[0], "r");

         auto loc = fgets(&output[0], output.length, fp);
         fclose(fp);

         // printf("loc: %s\n", loc);

         auto getLen = strlen(output.ptr);

         char[256] func = 0;
         memcpy(func.ptr, &line[startParenthesis], (endParenthesis 
- startParenthesis));
         sprintf(&syscom[0], "echo '%s' | ddemangle", func.ptr);
         fp = popen(&syscom[0], "r");

         output[getLen - 1] = ' '; // strip new line
         auto locD = fgets(&output[getLen], 
cast(int)(output.length - getLen), fp);
         fclose(fp);

         printf("%s", output.ptr);
     }
     exit(-1);
}

size_t convert_to_vma(size_t addr) nothrow @nogc
{
     Dl_info info;
     link_map* link_map;
     dladdr1(cast(void*) addr, &info, cast(void**)&link_map, 
RTLD_DL_LINKMAP);
     return addr - link_map.l_addr;
}

```


More information about the Digitalmars-d-learn mailing list