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;
}

```

Reply via email to