Трассировка стека отчетов изнутри библиотеки (статическая или динамическая)C++

Программы на C++. Форум разработчиков
Ответить
Anonymous
 Трассировка стека отчетов изнутри библиотеки (статическая или динамическая)

Сообщение Anonymous »

Давайте рассмотрим упрощенный пример (см. исходный код внизу вопроса)

Код: Выделить всё

g++ -g -O0 -fPIC -c ./doit.cpp -o doit.o

ar rv libdoit.a doit.o
g++ -g -O0 main.cpp -L. -Wl,--whole-archive -ldoit -Wl,--no-whole-archive -o static
rm libdoit.a
./static

g++ -shared -o libdoit.so doit.o
g++ -g -O0 main.cpp -L. -ldoit -o dynamic -Wl,-rpath=.
./dynamic
При запуске в системе Linux (в моем случае Debian 12) результат

Код: Выделить всё

+ g++ -g -O0 -fPIC -c ./doit.cpp -o doit.o
+ ar rv libdoit.a doit.o
ar: creating libdoit.a
a - doit.o
+ g++ -g -O0 main.cpp -L. -Wl,--whole-archive -ldoit -Wl,--no-whole-archive -o static
+ rm libdoit.a
+ ./static
========== Stack Trace ==========
#0  0x55bb788ea1b2    + 0x0  (./static)
#1  0x55bb788ea1be    + 0x0  (./static)
#2  0x55bb788ea1a2    + 0x0  (./static)
#3  0x7f074891224a    + 0x0  (/lib/x86_64-linux-gnu/libc.so.6)
#4  0x7f0748912305  __libc_start_main  + 0x85  (/lib/x86_64-linux-gnu/libc.so.6)
#5  0x55bb788ea0d1    + 0x0  (./static)
====================================
+ g++ -shared -o libdoit.so doit.o
+ g++ -g -O0 main.cpp -L. -ldoit -o dynamic -Wl,-rpath=.
+ ./dynamic
========== Stack Trace ==========
#0  0x7f86d2324182    + 0x0  (./libdoit.so)
#1  0x7f86d232418e  doit()  + 0x9  (./libdoit.so)
#2  0x55afae550142    + 0x0  (./dynamic)
#3  0x7f86d216124a    + 0x0  (/lib/x86_64-linux-gnu/libc.so.6)
#4  0x7f86d2161305  __libc_start_main  + 0x85  (/lib/x86_64-linux-gnu/libc.so.6)
#5  0x55afae550071    + 0x0  (./dynamic)
====================================
Вопросы
  • Почему статически связанный исполняемый файл не отображает детали трассировки стека изнутри архива? Сначала я подумал, что это связано с тем, что для связывания исполняемого файла на самом деле не нужен символ Internal_doit(), поэтому он удаляется. Однако добавление -Wl,--whole-archive не устранило проблему.
  • Почему динамически связанный исполняемый файл не отображает детали трассировки стека для кадра Internal_doit()? Код создан с использованием -O0, поэтому оптимизаций быть не должно.
Исходный код
  • main.cpp

    Код: Выделить всё

    #include "doit.h"
    int main()
    {
    doit();
    return 0;
    }
    
  • doit.h

    Код: Выделить всё

    #pragma once
    void doit();
    
  • doit.cpp

    Код: Выделить всё

    #include "doit.h"
    
    #include 
    #include 
    #include 
    #include 
    #include        // __cxa_demangle
    #include         // dladdr
    #include      // backtrace, backtrace_symbols
    
    inline void PrintCurrentThreadStack()
    {
    const int maxFrames = 64;
    const int framesToSkip = 0;
    void* addrs[512];
    int captured = backtrace(addrs, maxFrames);
    
    std::printf("========== Stack Trace ==========\n");
    for (int i = 0; i < captured; ++i) {
    if (i < (framesToSkip + 1)) continue;
    void* addr = addrs[i];
    Dl_info info;
    std::memset(&info, 0, sizeof(info));
    const char* moduleName = "";
    const char* symName    = "";
    const void* symAddr    = nullptr;
    if (dladdr(addr, &info)) {
    if (info.dli_fname) moduleName = info.dli_fname;
    if (info.dli_sname) symName = info.dli_sname;
    symAddr = info.dli_saddr;
    }
    int status = 0;
    char* demangled = abi::__cxa_demangle(symName, nullptr, nullptr, &status);
    const char* prettyName = (status == 0 && demangled) ? demangled : symName;
    std::uintptr_t off = 0;
    if (symAddr) {
    off = reinterpret_cast(addr) - reinterpret_cast(symAddr);
    }
    
    std::printf("#%-2d %p  %s  + 0x%zx  (%s)\n",
    i - (framesToSkip + 1),
    addr,
    prettyName ? prettyName : "",
    off,
    moduleName ? moduleName : "");
    
    if (demangled) std::free(demangled);
    }
    std::printf("====================================\n");
    }
    static void internal_doit()
    {
    PrintCurrentThreadStack();
    }
    void doit()
    {
    internal_doit();
    }
    


Подробнее здесь: https://stackoverflow.com/questions/798 ... vs-dynamic
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «C++»