Можно ли использовать addr2line с приложением, скомпилированным с аргументами оптимизации выпуска?

Так что у меня есть след

Exit with signal 11 at 2013-12-28_14:28:58.000000
/opt/s3ds/App(_Z7handlers+0x52) [0x5de322]
/lib/libc.so.6(+0x32230) [0x7f6ab9b3a230]
/opt/s3ds/App(_ZN17Service17Controller5frameERKf+0x505) [0x5a6b85]
/opt/s3ds/App(_ZN17Service15Cloud10updateEf+0x1de) [0x58642e]
/opt/s3ds/App(_ZN17Manager6updateEf+0x21b) [0x59194b]
/opt/s3ds/App(_ZN7Manager3runEv+0xd2) [0x604fa2]
/opt/s3ds/App() [0x62bfea]
/lib/libpthread.so.0(+0x68ca) [0x7f6abb0048ca]
/lib/libc.so.6(clone+0x6d) [0x7f6ab9bd7b6d]

Я скомпилировал свое приложение со следующими аргументами:

            -std=c++11 -fpermissive -m64 -g -rdynamic -mtune=native -flto -O3

Так что это сборка релиза с минимальной отладочной информацией.

Интересно, возможно ли использовать addr2line для получения любого номера строки из такой оптимизированной сборки?

Я старался пример, показанный здесь пока я получаю ??:0 лайк:

$ addr2line -e ./App 0x62bfea
??:0

для всех адресов в [], Я знаю, что функции в этом следе от Service::Controller::frame вплоть до Manager::run (и, вероятно, даже эта лямбда /opt/s3ds/App() [0x62bfea]) должен быть в коде моего приложения (не в какой-то библиотеке).

Так возможно ли получить номера строк для производственного оптимизированного кода? Есть ли дополнительные компиляторы, необходимые для их получения?

1

Решение

Это может быть возможно, но это может не стоить много.

Вы должны понимать, что сама цель оптимизации это к изменить код сделать это лучше (по метрике); и изменение означает, что результирующий код не может быть осмысленно сопоставлен с исходным кодом впоследствии.

Некоторые примеры:

  • Устранение мертвого кода и тому подобное удалит существующий код, это в основном повлияет на попытку разместить точку останова на заданной исходной строке, поскольку для этой строки может не быть кода
  • Устранение общих подвыражений создаст новые временные переменные неожиданно вычислять подвыражение только один раз; эти подвыражения могли первоначально появиться в нескольких выражениях, разбросанных по всему исходному коду, поэтому новые инструкции принадлежат нескольким строкам … или вообще ни одного
  • Инвариантный Подъем или Поворот Цикла изменит порядок вычисления выражений по сравнению с исходным исходным кодом, так что вы можете увидеть код, выполняемый в строке 3, затем 6, затем 4, 5, 7 …
  • Развертывание цикла будет копировать / вставлять тело цикла несколько раз

И, конечно же, это местный к функции, вы также должны учитывать

  • Функция Inlining скопирует и вставит тело функции на сайте вызова
  • Функция слияния возьмет две разные функции и удалит одну из них, перенаправляя свои вызовы другой (потому что они, конечно, ведут себя одинаково)

После всего этого, имеет ли смысл пытаться рассуждать с точки зрения исходного кода? Нет, не совсем. И, конечно, я даже не учел тот факт, что все эти преобразования произошли в Промежуточном представлении и что окончательный выпуск кода ассемблера еще более усложнит ситуацию (Снижение прочности, да!).

Честно говоря, даже если addr2line дает вам какую-то строку, я бы сомневался в ее результате … и тогда какой смысл спрашивать в первую очередь?

2

Другие решения

Я не уверен. Обычно rdynamic Переключатель должен быть достаточным, когда функция является частью вашего собственного кода (что, кажется, имеет место в вашем примере)

Вы пытались скомпилировать с -fno-inline-functions -fno-inline-functions-called-once -fno-optimize-sibling-calls? Это полезно при профилировании оптимизированной программы. Может быть, это также поможет решить вашу проблему.

(Примечание: вызов addr2line с -C switch активирует деманглинг, что рекомендуется, так как вы используете C ++.)

2