Следующие разделы посвящены просмотру и редактированию исходных файлов с помощью программы adb.
В программе adb предусмотрено несколько команд, позволяющих
выводить на экран команды и данные из конкретной программы, а также данные из
указанного файла. Они перечислены ниже:
Показать адрес | Адрес [, Число ] =Формат |
Показать команду | Адрес [, Число ] ?Формат |
Показать значение переменной | Адрес [, Число ] / Формат |
В этом формате символы и переменные имеют следующее значение:
Адрес | Расположение команды или элемента данных. |
Число | Количество выдаваемых элементов. |
Формат | Вид элемента на экране. |
= | Выдает адрес элемента. |
? | Выдает команду в текстовом сегменте. |
/ | Выдает значение переменной. |
В программе adb адреса представляют собой 32-разрядные значения,
указывающие на конкретные адреса памяти. Адреса могут быть представлены
в следующем виде:
Абсолютный адрес | 32-разрядная величина, представляемая 8-значным шестнадцатеричным числом или его эквивалентом в другой системе счисления. |
Имя функции | Расположение (адрес) функции или переменной, определенной в программе, может быть представлено ее именем (идентификатором) в программе. |
Точка входа | Точка входа в процедуру представляется именем процедуры, перед которым
стоит . (точка). Например, ссылка на адрес начала функции
main обозначается следующим образом:
.main |
Смещение | Для обозначения адресов других точек в программе можно указывать их
смещение относительно точки входа в программу. Например, запись адреса
команды, отстоящей на 4 байта от точки входа в main, выглядит
следующим образом:
.main+4 |
Для просмотра адресов в заданном формате предназначена команда = (знак равенства). С помощью этой команды можно просматривать адреса команд и данных (в более простой форме), а также результаты вычисления арифметических выражений. Например, команда
main=an
выдает адрес функции main:
10000370:
В следующем примере приведена команда, которая выдает десятичное значение суммы внутренней переменной b и шестнадцатеричного числа 0x2000:
<b+0x2000=D 268443648
Если задано число, то одно и то же значение повторяется указанное число раз. Следующий пример содержит команду, с помощью которой дважды выводится значение функции main, а затем результат выполнения этой функции:
main,2=x 370 370
Если адрес не указан, то используется текущий адрес. После однократного выполнения указанной выше команды (устанавливающей адрес main в качестве текущего), следующая команда выполняет то же действие:
,2=x 370 370
Если формат не указан, то программа adb будет использовать последний применявшийся формат. Например, если вводится следующая последовательность команд, то и main, и one выдаются в шестнадцатеричном формате:
main=x 370 one= 33c
Для трассировки всех активных функций предназначена команда $c. Эта команда показывает список всех вызванных функций, которые еще не вернули управление вызвавшей их процедуре. Кроме того, она выдает список адресов, из которых были вызваны функции, и список переданных в них аргументов. Например, следующая последовательность команд задает точку прерывания по адресу функции .f+2 в программе adbsamp2. Точка прерывания вызывает команду $c. Программа запускается, доходит до точки прерывания, а затем выдает данные обратной трассировки вызванных функций C:
.f+2:b$c :r adbsamp2:running .f(0,0) .main+26 .main(0,0,0) start+fa breakpoint f+2: tgte r2,r2
По умолчанию команда $c показывает все вызовы. Если требуется только часть вызовов, укажите нужное число вызовов. Например, следующая команда будет показывать только одну активную функцию в предыдущей точке прерывания:
,1$c
.f(0,0) .main+26
Формат - это буква или символ, определяющие способ представления
данных на экране. Ниже перечислены наиболее распространенные
форматы:
Буква | Формат |
a | Текущий символьный адрес |
b | Один байт в восьмеричном представлении (показывает данные, связанные с командами, либо старший или младший байт регистра) |
c | Один байт в символьном виде (переменные типа char) |
d | Полуслово в десятичном представлении (короткий тип) |
D | Полное слово в десятичном представлении (длинный тип) |
i | Машинные команды в мнемоническом формате |
n | Новая строка |
o | Полуслово в восьмеричном представлении (короткий тип) |
O | Полное слово в восьмеричном представлении (длинный тип) |
r | Пробел |
s | Строка символов, заканчивающаяся символом NULL (массивы переменных типа char, заканчивающиеся символом NULL) |
t | Горизонтальная табуляция |
u | Полуслово как целое без знака (короткий тип) |
x | Полуслово в шестнадцатеричном представлении (короткий тип) |
X | Полное слово в шестнадцатеричном представлении (длинный тип) |
Ниже приведены результаты
выполнения некоторых команд, применявшихся с программой
adbsamp:
Команда | Результат |
main=o | 1560 |
main=O | 4000001560 |
main=d | 880 |
main=D | 536871792 |
main=x | 370 |
main=X | 20000370 |
main=u | 880 |
Можно указывать как один, так и несколько форматов. Для того чтобы сделать данные на экране более удобными для чтения, вы можете указывать форматы a, n, r и t в сочетании с другими форматами.
С помощью команд ?m и /m можно изменять значения в карте распределения памяти. См. раздел Программа отладки adb - справочная информация. Команды присваивают указанные значения соответствующим записям карты. Формат команд:
[,число] ?m b1 e1 f1 [,число] /m b1 e1 f2
В следующем примере показан результат применения этих команд к схеме распределения памяти, выданной командой $m в предыдущем примере:
,0?m 10000100 10000470 0 /m 100 100 100 $m [0] : ?map : 'adbsamp3' b1 = 0x10000100, e1 = 10000470, f1 = 0 b2 = 0x20000600, e2 = 0x2002c8a4, f2 = 0x600 [1] : ?map : 'shr.o' в библиотеке '/usr/ccs/lib/libc.a' b1 = 0xd00d6200, e1 = 0xd01397bf, f1 = 0xd00defbc b2 = 0x20000600, e2 = 0x2002beb8, f2 = 0x4a36c [-] : /map : '-' b1 = 100, e1 = 100, f1 = 100 b2 = 0, e2 = 0, f2 = 0
Для того чтобы изменить значения сегментов данных, добавьте после / или ? звездочку (*).
,0?*m 20000270 20000374 270 /*m 200 200 200 $m [0] : ?map : 'adbsamp3' b1 = 0x10000100, e1 = 10000470, f1 = 0 b2 = 0x20000270, e2 = 0x20000374, f2 = 0x270 [1] : ?map : 'shr.o' в библиотеке '/usr/ccs/lib/libc.a' b1 = 0xd00d6200, e1 = 0xd01397bf, f1 = 0xd00defbc b2 = 0x20000600, e2 = 0x2002beb8, f2 = 0x4a36c [-] : /map : '-' b1 = 100, e1 = 100, f1 = 100 b2 = 0, e2 = 0, f2 = 0
Запустив программу adb с флагом -w и воспользовавшись командами w и W (Программа отладки adb - справочная информация), можно корректировать и изменять любые файлы, включая исполняемые двоичные файлы.
Для поиска значений в файле служат команды l и L. См. раздел Программа отладки adb - справочная информация. Формат команд:
?l Значение
или
/lЗначение
Программа начинает поиск с текущего адреса и ищет указанное Значение. Команда l предназначена для поиска 2-байтовых значений, команда L - 4-байтовых.
Команда ?l начинает поиск с текущего адреса и продолжает его до первого совпадения или до конца файла. Если значение найдено, то его адрес становится текущим адресом. Например, следующая команда ищет первое вхождение символа f в файле adbsamp2:
?l .f. write+a2
В данном примере значение найдено по адресу .write+a2, который стал текущим.
Для внесения изменений в файл служат команды w и W. См. раздел Программа отладки adb - справочная информация. Формат команд:
[ Адрес ] ?wЗначение
Здесь Адрес - это адрес значения, которое вы хотите изменить, а Значение - новое значение. Команда w предназначена для записи 2-байтовых значений, команда W - 4-байтовых. Например, следующие команды изменяют слово "This" на "The":
?l .Th. ?W .The.
Команда W изменяет все четыре символа.
Вы можете вносить изменения в программу даже во время ее выполнения. Если для запуска программы вы использовали команду :r с точкой прерывания, то последующее выполнение команд w приведет к тому, что программа adb будет корректировать не файл, а программу в памяти. Эта команда предназначена для внесения изменений в данные программы во время ее выполнения, например, для временной корректировки флагов и переменных.
При запуске программа adb автоматически создает набор своих
собственных переменных. Эти переменные содержат адреса и размеры
различных частей программного файла (см. приведенную ниже
таблицу):
Переменная | Содержание |
---|---|
0 | Последнее напечатанное значение |
1 | Последний блок смещения в источнике инструкций |
2 | Предыдущее значение переменной 1 |
9 | Счетчик в последней команде $< или $<<. |
b | Базовый адрес сегмента данных |
d | Размер сегмента данных |
e | Адрес входа программы |
m | Сигнатура |
s | Размер сегмента стека |
t | Размер текстового сегмента |
Программа adb читает программный файл и ищет значения этих переменных. Если обнаруживается, что файл не программный, то adb оставляет значения неопределенными.
Для просмотра значений, присваиваемых программой adb этим переменным, служит команда $v . Дополнительные сведения об этом приведены в разделе Программа отладки adb - справочная информация. Эта команда выдает список имен переменных и их значений в текущем формате. В списке содержатся только те переменные, значение которых не равно нулю (0). Кроме того, если переменная имеет ненулевое значение сегмента, то ее значение выдается как адрес, иначе - как число. В следующем примере показаны результаты применения этой команды к программе adbsamp:
$v
Variables
0 = undefined
1 = undefined
2 = undefined
9 = undefined
b = 10000000
d = 130
e = 10000038
m = 108
t = 298
Текущее значение переменной программы adb можно указать в выражении, задав имя переменной со знаком < (меньше) перед ним. В следующем примере выдается текущее значение переменной b:
<b=X
10000000
Вы можете создавать свои собственные переменные или изменять значения существующих переменных, присваивая им значения с помощью знака > (больше). Формат:
Выражение > Имя_переменной
где Выражение - это значение, присваиваемое переменной, а Имя_переменной - это переменная, которой присваивается значение. Параметр Имя_переменной должен состоять из одной буквы. Например, команда
0x2000>b
присваивает шестнадцатеричное значение 0x2000 переменной b. Для того чтобы убедиться, что присвоение выполнено, можно просмотреть содержимое b:
<b=X
2000
В программе adb есть две переменные, которые отслеживают последний адрес, применявшийся командой, и последний адрес, введенный в команде. Переменная . (точка) содержит последний адрес, применявшийся командой (он также называется текущим адресом). Последний адрес, введенный в команде, хранится в переменной " (двойная кавычка). Переменная . и " обычно содержат один и тот же адрес, за исключением случаев применения таких неявных команд, как символ новой строки и символ вставки (^). Эти символы автоматически увеличивают и уменьшают значение переменной . , но оставляют неизменной значение переменной " .
Обе переменные, . и ", могут использоваться в любых выражениях. Указывать знак < (меньше) не требуется. Ниже приведен пример команд для выдачи значений этих переменных в начале отладки программы adbsamp (Пример программы adb: adbsamp).
.= 0. = 0
Для просмотра значений всех внешних переменных в программе adb предназначена команда $e (Программа отладки adb - справочная информация) . Внешними называются переменные пользовательской программы, имеющие глобальную область действия или определенные вне всех функций, а также переменные, определенные в библиотечных процедурах, используемых программой, и все внешние переменные общих библиотек.
Команда $e позволяет получить список всех имеющихся переменных и их значений. В каждой строке вывода команды указывается имя переменной и его значение (если оно есть). Если команда вводится с параметром Число, то печатаются только внешние переменные, связанные с этим файлом.
В следующем примере иллюстрируется установка точки прерывания, вызывающей команду $e, и приводятся результаты выполнения этой команды при запуске программы adbsamp2 (Пример программы adb: adbsamp2) (не забудьте удалить другие точки прерывания, которые могли быть установлены ранее):
.f+2:b,0$e :r adbsamp2:running _errno: 0 _environ: 3fffe6bc __NLinit: 10000238 _main: 100001ea _exit: 1000028c _fcnt: 0 _loop_count: 1 _f: 100001b4 _NLgetfile: 10000280 _write: 100002e0 __NLinit__X: 10000238 _NLgetfile__X: 10000280 __cleanup: 100002bc __exit: 100002c8 _exit__X: 1000028c __cleanup__X: 100002bc breakpoint .f+2: st r2,1c(r1)
Программа adb подготавливает набор таблиц для сегментов текста и данных, с помощью которых она обращается к элементам, выводимым на экран по вашему запросу. Для просмотра содержимого этих таблиц адресов служит команда $m. Дополнительные сведения об этом приведены в разделе Программа отладки adb - справочная информация. Команда выдает таблицы для всех сегментов программы, используя информацию либо из программного файла и файла дампа, либо непосредственно из памяти.
Команда $m выдает примерно следующую информацию:
$m [0] : ?map : 'adbsamp3' b1 = 0x10000200, e1 = 0x10001839, f1 = 0x10000200 b2 = 0x2002c604, e2 = 0x2002c8a4, f2 = 0x600 [1] : ?map : 'shr.o' в библиотеке 'lib/libc.a' b1 = 0xd00d6200, e1 = 0xd013976f, f1 = 0xd00defbc b2 = 0x20000600, e2 = 0x2002bcb8, f2 = 0x4a36c [-] : /map : '-' b1 = 0x0000000, e1 = 0x00000000, f1 = 0x00000000 b2 = 0x0000000, e2 = 0x00000000, f2 = 0x00000000
Здесь показаны параметры распределения адресов памяти для сегментов текста ( b1, e1 и f1) и данных (b2, e2 и f2) для двух файлов, применяемых программой adb. Данные значения относятся только к приведенному примеру программы adbsamp3. Второй набор значений таблицы соответствует используемому файлу дампа. Так как на самом деле никакой файл дампа не используется, вместо имени файла указан символ - (тире).
Значение в квадратных скобках может использоваться в качестве параметра Число в командах ?e и ?m.
Применение выражений в программе adb