Отладка приложений

       

Определение диапазонов исходного кода


Читатель, вероятно, не очень удивится тому, что здесь снова используется символьная машина DBGHELP.DLL (подробнее она описана в главе 4). Я полагал, что ее функции, работающие с именами исходных файлов и номерами строк исходного кода, позволят отыскивать адреса первой и последней строк рабочих кодов конкретного исходного файла (эту пару адресов я и называю диапазоном адресов). Вооружившись диапазоном адресов и методикой, которая обсуждалась в главе 12, можно было бы подключить функцию OutputDebugString и по адресу возврата определить, находится ли она в диапазоне адресов того исходного файла, из которого пользователь хочет получать предложения трассировки. Хотя этот подход теоретически довольно прост, но для его практической реализации мне пришлось изрядно потрудиться.

Не существует специальной API-функции, которая перечисляет диапазоны адресов исходных файлов, но я полагал, что смог бы обойтись функцией перечисления символов SymEnumerateSymbols. С помощью этой функции Я хотел извлечь первый символ, затем (находясь уже внутри собственной функции перечисления символов) переместиться обратно к началу исходного файла (с помощью функции SymGetLinePrev) и затем перейти к его концу с помощью функции symGetLineNext. В случае простых тестов функция SymEnumerateSymbols работала великолепно, но когда я провел аналогичное тестирование программы GENLIMODS.EXE, то заметил, что диапазоны исходного кода, полученные с помощью SymEnumerateSymbols, не соответствовали тому, что показывал дизассемблер при тестировании GENLIMODS.EXE. Казалось, что при моей методике пропускаются целые секции исходного файла.

Когда я вручную вычислил диапазоны, они получились похожими на перечисленные в табл. 14.1. Проблема возникала из-за того, что функции SymGetLineNext И SymGetLinePrev перечисляют только смежные (непрерывные) диапазоны. Из табл 14.1 видно, что исходные файлы со встроенными (inline) функциями находятся между первой и второй частями GENLIMODS.CPP. Я быстро понял, что это не ошибка, а скорее следствие работы компилятора.
Непонимание наблюдалось с моей стороны: я сосредотачивал свое внимание на исходном файле, когда на самом деле нужно было в первую очередь думать о диапазонах адресов.

Таблица 14.1. Примеры диапазонов адресов GENLIMODS.EXE

Начало



Конец

Исходный файл

0x00401900

0x0040 1A8A

COMMANDLINE.CPP

0x00401000

Ox00402F1F

GENLIMODS.CPP

0x00403450

0x00403774

RESSTRING.H

0x00403700

0x00403700

GENLIMODS.H

0x00403060

Ox004040F9

SYMBOLENGINE.H

0x00404690

Ox004046AC

GENLIMODS.CPP

0x00407080

Ox0040852E

LOMFILE.CPP

0x00409050

Ox0040A532

READIGNOREFILES.CPP

Ox0040C800

0x00400894

VERBOSE.CPP





Содержание раздела