#ios #xcode #debugging #gdb #assembly
#iOS #xcode #отладка #gdb #сборка
Вопрос:
Мое приложение для iOS построено с использованием компилятора Apple LLVM 3.0 в режиме Thumb. Для armv7 я почти уверен, что на самом деле это Thumb-2.
Я переопределяю две мои самые трудоемкие функции в коде сборки ARM. Вызывающие эти функции — Thumb, поэтому я использую Thumb для выполнения инструкций по взаимодействию ARM для переключения на ARM в прологе моих функций, поэтому у меня есть доступ к более богатому набору команд ARM и большему количеству регистров. При выходе из функции я использую взаимодействие ARM с Thumb, чтобы вернуться в режим ARM.
Разборка GDB верна для кода Thumb, но когда я нахожусь в режиме ARM, он разбирает инструкции ARM, как если бы каждая из них была парой совершенно бессмысленных инструкций Thumb. Есть ли какой-нибудь способ, которым я могу сказать GDB переключиться на разборку ARM, а затем, вернувшись к Thumb code, использовать Thumb disassembler?
Google не помогает. По-видимому, есть другие форки GDB, которые могут это сделать, но я не нашел способа сделать это с помощью GDB.
LLDB, по-видимому, поддерживает отладку ARM, но она еще не работает на устройствах iOS в Xcode 4.2. Когда я выбираю отладчик LLDB в Product -> Edit Scheme, затем устанавливаю точку останова в своем коде, мое приложение зависает, не достигнув точки останова.
Прошло много времени с тех пор, как я делал какую-либо сборку любого рода, поэтому я обновляю соглашения о вызовах ARM, реализуя функции, которые принимают различные параметры и возвращают различные типы результатов как в C, так и в ARM-сборке. Функции lower_case — это C, а функции camelCase — это сборка. Я вызываю abiTest самым первым из main () и использую assert (), чтобы убедиться, что он возвращает YES
BOOL abiTest( void )
{
void_no_args();
VoidNoArgs();
if ( 42 != int_no_args() )
return NO;
if ( 42 != IntNoArgs() )
return NO;
return YES;
}
Вот исходный код для IntNoArgs. .thumb_func — это директива для компоновщика. Мои исследования, похоже, указывают на то, что это нужно даже для функций ARM, если смешивать два типа кода
.globl _IntNoArgs
.align 1
.code 16
.thumb_func _IntNoArgs
_IntNoArgs:
@ int IntNoArgs( void );
.loc 1 __LINE__ 0
adr r0, Larm1 @ Larm1 is a PC-relative address. r0's low bit will be cleared
bx r0 @ Switch to ARM mode then branch to Larm1. That's the next instruction
.align 2
.code 32
Larm1:
stmfd sp!, { r7, lr }
mov r0, #42
ldmfd sp!, { r7, lr }
bx lr
Вот как GDB разбирает _IntNoArgs. Первые две строки верны, остальные полностью неверны
0x000172c8 < 0000> add r0, pc, #0 (adr r0, 0x172cc <VoidNoArgs 4>)
0x000172ca < 0002> bx r0
0x000172cc < 0004> lsls r0, r0
0x000172ce < 0006> stmdb sp!, {r1, r3, r5}
0x000172d2 < 0010> b.n 0x17a16
0x000172d4 < 0012> lsls r0, r0
0x000172d6 < 0014> ldmia.w sp!, {r1, r2, r3, r4, r8, r9, r10, r11, r12, sp, lr, pc}
На этом разборка останавливается, потому что инструкция ldmia.w, похоже, вводит новое значение в программный счетчик после извлечения его из стека, тем самым возвращаясь из подпрограммы. После того, как я перейду к этой инструкции с помощью «si», откроется панель разборки:
0x000172d8 < 0016> vrhadd.u16 d14, d14, d31
Инструкция si всегда выполняет правильные действия, продвигая только одну инструкцию, независимо от того, находимся ли мы в режиме Thumb или ARM. Итак, GDB должен знать текущую архитектуру набора команд, просто дизассемблер не получает эту информацию.
В одном из регистров ARM есть бит, который указывает текущий режим. Некоторые форки GDB имеют возможность использовать значение этого бита при определении того, какой ISA дизассемблировать, но, по-видимому, это не относится к GDB в Xcode 4.2.
В GDB Xcode есть команда «set arm disassembler» и соответствующая ей «show arm disassembler», которая выглядит так, как будто это помогло бы, но это не так. Это, по-видимому, предназначено для поддержки других вариантов ARM, отличных от того, что используют устройства iOS.
«установить резервный режим» может быть установлен на arm, thumb или auto в других форках GDB, но не в Xcodes. То же самое для «установить дизассемблер-вкус».
Чего бы мне ДЕЙСТВИТЕЛЬНО ОЧЕНЬ хотелось, так это машинного отладчика, который работал бы точно так же, как MacsBug в классической Mac OS. Хотя GDB обычно способна выполнять отладку на ассемблере, она совершенно не подходит для этой цели. На самом деле это не чья-то вина, потому что он предназначен для отладки исходного кода. Хороший отладчик сборки предназначен для того, чтобы делать это таким образом с нуля.
Комментарии:
1. Почему это было перенесено сюда из programmers.stackexchange.com ? Я не жалуюсь, но мне кажется, что плата программиста была более подходящей для этого вопроса.
2. Похоже, что это ошибка в отладчике, и вы должны сообщить об этом Apple по bugreport.apple.com .
3. Грэм, хорошая идея, вроде. Я только что попытался, но не смог исправить ошибку # 10420051. К сожалению, не удалось отправить мою форму. Хотя Radar выдал мне номер ошибки, ошибка на самом деле не была введена, насколько я могу судить. Мне посоветовали сообщить о проблеме с радаром в devbugs@apple.com, что я только что сделал. Я подожду, получу ли я какой-либо ответ, а также дам системным администраторам Apple шанс исправить все, что не так, а затем повторно отправить ошибку.
Ответ №1:
В руководстве по вызову функций ABI указано, что переключение между режимом ARM и Thumb может быть выполнено только на границах функций в iOS. Убедитесь, что ваши функции доступны только для ARM или Thumb, и отладчик будет работать нормально.