Неверные номера строк из addr2line

Я пытаюсь найти точную строку вызова в программе на C++. Прямо сейчас я использую эти строки (из справочной страницы backtrace ), чтобы получить трассировку:

  void *bt_buffer[1000];
  char **bt_strings;
  int bt_nptrs = backtrace(bt_buffer, 1000);
  bt_strings = backtrace_symbols(bt_buffer, bt_nptrs);

В строках bt _я нахожу строки вида

./prog() [0x402e42]

Теперь я беру адрес (шестнадцатеричной строки )и передаю ее в addr2line. Иногда это приводит к явно неправильным номерам строк. Интернет-поиск привел меня к этому посту , в котором показано, что

readelf -wl./prog

указывает, где на самом деле находится строка , а точнее, на сколько строк символ переместился на текущую строку.

редактировать:Это происходит, когда я компилирую с -g -O0, т.е. явно без оптимизаций. Компилятор gcc 4.6.3Есть ли еще один флаг компилятора, который я пропустил?

Моя проблема заключается в следующем :Мне нужно это автоматизировать. Мне нужна моя программа, чтобы создать обратную трассировку (done ), извлечь файл (done )и номер строки (fail ).

Я мог бы, конечно, вызвать readelfи проанализировать вывод, но это не совсем подходит, так как вывод отличается от символа к символу в зависимости от того, что именно произошло. Иногда адрес символа находится в одной строке, а информация о смещении строки в следующей строке...

Подводя итог:

Есть ли элегантный способ получить точный номер строки вызова функции в трассировке изнутри программы во время выполнения?

редактировать:пример кода:

#define UNW_LOCAL_ONLY
#include <libunwind.h>
#include <execinfo.h>
#include <iostream>
#include <stdlib.h>

void show_backtrace()
{
  // get current address
  void* p = __builtin_return_address(0);
  std::cout << std::hex << p << std::endl;

  // get callee addresses
  p = __builtin_return_address(1);
  std::cout << std::hex << p << std::endl;

  p = __builtin_return_address(2);
  std::cout << std::hex << p << std::endl;
}

void show_backtrace2()
{
  void *array[10];
  size_t size;
  char **strings;
  int i;

  size = backtrace (array, 10);
  strings = backtrace_symbols ((void *const *)array, size);

  for (i = 0; i < size; i++)
    {
      std::cout << strings[i] << std::endl;
    }

  free (strings);
}

void show_backtrace3 (void)
{
  char name[256];
  unw_cursor_t cursor; unw_context_t uc;
  unw_word_t ip, sp, offp;

  unw_getcontext (&uc);
  unw_init_local (&cursor, &uc);

  while (unw_step(&cursor) > 0)
    {
      char file[256];
      int line = 0;

      name[0] = '\0';
      unw_get_proc_name (&cursor, name, 256, &offp);
      unw_get_reg (&cursor, UNW_REG_IP, &ip);
      unw_get_reg (&cursor, UNW_REG_SP, &sp);

      std::cout << std:: hex << name << " ip = " << (long) ip 
                << ", sp = " << (long) sp << std::endl;
    }
}

void dummy_function2()
{
  show_backtrace();
  show_backtrace2();
  show_backtrace3();
}

void dummy_function1()
{ 
  dummy_function2 (); 
} // line 73

int main(int argc, char **argv)
{
  dummy_function1 ();
  return 0;
}

скомпилировать и запустить:

g++ test_unwind.cc -g -O0 -lunwind  &&./a.out

выход:

0x400edb
0x400ef0
0x400f06
./a.out() [0x400cfb]
./a.out() [0x400ee0]
./a.out() [0x400ef0]
./a.out() [0x400f06]
/lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xed) [0x7f2f044ae76d]
./a.out() [0x400b79]
_Z15dummy_function2v ip = 400ee5, sp = 7fffdb564580
_Z15dummy_function1v ip = 400ef0, sp = 7fffdb564590
main ip = 400f06, sp = 7fffdb5645a0
__libc_start_main ip = 7f2f044ae76d, sp = 7fffdb5645c0
_start ip = 400b79, sp = 7fffdb564680

тестирование напр. 0x400ef0 с выходом addr2line

/path/to/code/test_unwind.cc:73

это правильный файл, но неправильный номер строки. В реальных приложениях номер строки может отличаться на много строк вперед и назад.

редактировать:компиляция с -Sпоказывает, что соответствующей частью является:

.LCFI34:
 .cfi_def_cfa_register 6
 .loc 2 72 0
  call  _Z15dummy_function2v
 .loc 2 73 0
  popq  %rbp

То, что отображается addr2lineи т.п., является обратным адресом, как показано в строке после call. Я хотел бы получить строку «вход», т.е. то, что показано раньше!

23
задан steffen 30 July 2012 в 12:46
поделиться