остановка трассировки в регистре листьев (lr) - PullRequest
1 голос
/ 24 июня 2011

Часто я вижу трассировки стека ARM (читай: трассировки стека Android NDK), оканчивающиеся указателем lr, например:

      #00  pc 001c6c20  /data/data/com.audia.dev.qt/lib/libQtGui.so
      #01  lr 80a356cc  /data/data/com.audia.dev.rta/lib/librta.so

Я знаю, что lr означает link register наARM и другие архитектуры, и это быстрый способ сохранить обратный адрес, но я не понимаю, почему он всегда кажется бесполезным.В этом примере 80a356cc не может быть сопоставлен с каким-либо кодом с использованием addr2line или gdb.

Есть ли способ получить дополнительную информацию?В любом случае, почему трассировка должна останавливаться на адресе lr?

Ответы [ 2 ]

2 голосов
/ 27 июня 2011

Наткнулся на ответ наконец.Я просто должен был быть более наблюдательным.Посмотрите на следующую короткую трассировку стека и информацию, которая следует за ней:

         #00  pc 000099d6  /system/lib/libandroid.so
         #01  lr 80b6c17c  /data/data/com.audia.dev.rta/lib/librta.so

code around pc:
a9d899b4 bf00bd0e 2102b507 aa016d43 28004798 
a9d899c4 9801bfa8 bf00bd0e 460eb573 93004615 
a9d899d4 6d842105 462b4632 200047a0 bf00bd7c 
a9d899e4 b100b510 f7fe3808 2800edf4 f04fbf14 
a9d899f4 200030ff bf00bd10 b097b5f0 4614af01 

code around lr:
80b6c15c e51b3078 e5933038 e5932024 e51b302c 
80b6c16c e1a00002 e3a01000 e3a02000 ebfeee5c 
80b6c17c e1a03000 e50b303c e51b303c e1a03fa3 
80b6c18c e6ef3073 e3530000 0a000005 e59f34fc 
80b6c19c e08f3003 e1a00003 e51b103c ebfeebe6 

Теперь адрес lr по-прежнему является 80xxxxxx адресом, который нам не нужен.

Адрес, который он печатает с pc, равен 000099d6, но посмотрите на следующий раздел, code around pc.Первый столбец представляет собой список адресов (вы можете сказать по факту, что он увеличивается каждый раз на 16). Ни один из этих адресов не выглядит как адрес pc, если только вы не отрежете первые 16 бит.Затем вы заметите, что a9d899d4 должен соответствовать 000099d4, а код, где остановилась программа, находится в двух байтах от этого.

Похоже, что трассировка стека Android "обрезана" в первых 2байт адреса pc для меня, но по какой-то причине он не делает этого для адресов в листовом регистре.Что приводит нас к решению:

Короче говоря, я смог отрубить первые 16 бит от адреса 80b6c17c, чтобы сделать его 0000c17c, и пока что это имееткаждый раз, когда я могу найти с помощью gdb или addr2line, мне дают правильный кодовый адрес.( edit: Я обнаружил, что на самом деле это обычно первые 12 бит или первые 3 шестнадцатеричных цифры. Вы можете сами решить это, посмотрев на трассировку стекавывод, как я описал выше.) Я могу подтвердить, что это также правильный кодовый код .Это определенно сделало отладку намного проще!

1 голос
/ 25 июня 2011

Есть ли у вас вся информация отладки (-g3)?

Gcc любит использовать lr в качестве обычного регистра.Помните, что неконечная функция выглядит как

push {lr}
; .. setup args here etc.
bl foo  ; call a function foo
; .. work with function results
pop {pc}

Как только она помещает lr в стек, компилятор может использовать ее почти свободно - lr будет перезаписываться только вызовами функций.Так что вполне вероятно, что в lr.

есть какое-то промежуточное значение. Это должно быть указано в отладочной информации, которую генерирует компилятор, чтобы дать отладчику понять, что вместо этого он должен смотреть на значение стека.lr.

...