Люди, помогите. Замучался уже.
Работаю в MS VC++6.
Нужно в версии "release" с оптимизацией получить:
— список вызовов функций и их названия;
— номер последней выполненной строки программы;
— список загруженных модулей.
Все это нужно для локализации места ошибки после возникновения исключения (Structured Exceprion и C++).
Все, что мог — перепробовал. Топики на этом форуме перечитал. интернет обшарил. Пробовал использовать BugslayerUtil — не работает (точнее работает, но выдает только адреса и параметры, а остальную информацию — нет). Смотрел исходники, но, не смог найти причину.
AfxDumpSteck — не выдает функций моего приложения и номер строки.
Пробовал StackWalk — ничего не выходит.
Такое ощущение, что я что-то недопонимаю или не так делаю. Или что-то нужно правильно проинициализировать, прежде чем получить нужную мне информацию.
В общем, если кто знает, как мне помочь, помогите, пожалуйста. А то я на этом скончаюсь скоро.
Заранее благодарен, Александр.
26.11.03 14:14: Перенесено модератором из 'C/C++' — ПК
Здравствуйте, Вы писали:
> Работаю в MS VC++6. > Нужно в версии "release" с оптимизацией получить: > — список вызовов функций и их названия; <...> > Все, что мог — перепробовал.
Включить генерацию Debug Info не забыл?
Posted via RSDN NNTP Server 1.7 "Bedlam"
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
Здравствуйте, Павел Кузнецов, Вы писали:
ПК>Здравствуйте, Вы писали:
>> Работаю в MS VC++6. >> Нужно в версии "release" с оптимизацией получить: >> — список вызовов функций и их названия; <...> >> Все, что мог — перепробовал.
ПК>Включить генерацию Debug Info не забыл?
Здравствуйте, Pavel Dvorkin, Вы писали:
PD>Привет!
PD>lav03 wrote: >> >> ПК>Включить генерацию Debug Info не забыл? >> >> Нет,стоит.
PD>А Program Database ?
PD>-- PD>С наилучшими пожеланиями PD> Дворкин Павел
Здравствуйте, Pavel Dvorkin, Вы писали:
PD>Привет!
PD>lav03 wrote: >> >> ПК>Включить генерацию Debug Info не забыл? >> >> Нет,стоит.
PD>А Program Database ?
PD>-- PD>С наилучшими пожеланиями PD> Дворкин Павел
Здравствуйте, Pavel Dvorkin, Вы писали:
PD>Привет!
PD>lav03 wrote: >> >> А где же моя CTestErrDlg::OnButton1()
PD>А вообще-то файл .pdb есть в release версии ?
PD>-- PD>С наилучшими пожеланиями PD> Дворкин Павел
Есть.
Может какие-то директивы компилятора нужно добавить? Такое ощущение, что AfxDumpStack не всю инфу вкуривает. А тогда зачем она, такая дорогая, нужна? В МСДН ничего не написано ни про дополнительную инициализацию, ни про опции компиллета для этой функции. В дебаг-версии тоже самое примерно получается. Н понимаю
lav03 wrote: > > Здравствуйте, Pavel Dvorkin, Вы писали:
> Может какие-то директивы компилятора нужно добавить? Такое ощущение, что AfxDumpStack не всю инфу вкуривает. А тогда зачем она, такая дорогая, нужна? В МСДН ничего не написано ни про дополнительную инициализацию, ни про опции компиллета для этой функции. В дебаг-версии тоже самое примерно получается. Н понимаю
Я сейчас проверил у себя. Значит, так
Под VC6 Debug выдается Error 126 — (module not found, если это
GetLastError). После этого дамп, но без моих имен.
Под VC6 Release выдается одна строчка, не моя
Под VC7 Debug все замечательно.
Под VC7 Release тоже все прекрасно.
ИМХО что-то связано с imghelp.dll. Как бы мне ее VC7 не переписал при
установке.
Здравствуйте, Pavel Dvorkin, Вы писали:
PD>Привет!
PD>lav03 wrote: >> >> Здравствуйте, Pavel Dvorkin, Вы писали:
>> Может какие-то директивы компилятора нужно добавить? Такое ощущение, что AfxDumpStack не всю инфу вкуривает. А тогда зачем она, такая дорогая, нужна? В МСДН ничего не написано ни про дополнительную инициализацию, ни про опции компиллета для этой функции. В дебаг-версии тоже самое примерно получается. Н понимаю
PD>Я сейчас проверил у себя. Значит, так
PD>Под VC6 Debug выдается Error 126 — (module not found, если это PD>GetLastError). После этого дамп, но без моих имен. PD>Под VC6 Release выдается одна строчка, не моя PD>Под VC7 Debug все замечательно. PD>Под VC7 Release тоже все прекрасно.
PD>ИМХО что-то связано с imghelp.dll. Как бы мне ее VC7 не переписал при PD>установке.
Точно! У меня тоже VC7 стоит. Я чейчас проверил — на VC7 работает. Это что же тогда получается, мне сосвоей программой нужно и imghelp.dll от VC7 распространять? А если я ее подменю, другие проги, юзающие старые версии, отъедут?
PD>-- PD>С наилучшими пожеланиями PD> Дворкин Павел
Здравствуйте, lav03, Вы писали:
L>Здравствуйте, Pavel Dvorkin, Вы писали:
PD>>Привет!
PD>>lav03 wrote: >>> >>> Здравствуйте, Pavel Dvorkin, Вы писали:
>>> Может какие-то директивы компилятора нужно добавить? Такое ощущение, что AfxDumpStack не всю инфу вкуривает. А тогда зачем она, такая дорогая, нужна? В МСДН ничего не написано ни про дополнительную инициализацию, ни про опции компиллета для этой функции. В дебаг-версии тоже самое примерно получается. Н понимаю
PD>>Я сейчас проверил у себя. Значит, так
PD>>Под VC6 Debug выдается Error 126 — (module not found, если это PD>>GetLastError). После этого дамп, но без моих имен. PD>>Под VC6 Release выдается одна строчка, не моя PD>>Под VC7 Debug все замечательно. PD>>Под VC7 Release тоже все прекрасно.
PD>>ИМХО что-то связано с imghelp.dll. Как бы мне ее VC7 не переписал при PD>>установке.
L>Точно! У меня тоже VC7 стоит. Я чейчас проверил — на VC7 работает. Это что же тогда получается, мне сосвоей программой нужно и imghelp.dll от VC7 распространять? А если я ее подменю, другие проги, юзающие старые версии, отъедут?
На другом компе поробовал запустить программу — получил скудное содержание стека. Подсунул свою imagehelp.dll — тот же результат. Не работает.
PD>>-- PD>>С наилучшими пожеланиями PD>> Дворкин Павел
Hello, lav03!
You wrote on Wed, 26 Nov 2003 14:45:19 GMT:
PD>>> ИМХО что-то связано с imghelp.dll. Как бы мне ее VC7 не переписал при PD>>> установке.
L>> Точно! У меня тоже VC7 стоит. Я чейчас проверил — на VC7 работает. Это L>> что же тогда получается, мне сосвоей программой нужно и imghelp.dll от L>> VC7 распространять? А если я ее подменю, другие проги, юзающие старые L>> версии, отъедут?
l> На другом компе поробовал запустить программу — получил скудное l> содержание стека. Подсунул свою imagehelp.dll — тот же результат. Не l> работает.
А зачем тебе имена функций на компьютере клиента? Достаточно транслировать адреса в логические, а имена функций брать из map-файла на своей машине (ну, при этом, правда, придется хранить map-файлы и pdb для всех версий программы — зато pdb никому отдавать не придется). Или без map-файла — сразу бинарник+pdb в IDA грузить.
Best regards,
Sergey.
Posted via RSDN NNTP Server 1.8 beta
Одним из 33 полных кавалеров ордена "За заслуги перед Отечеством" является Геннадий Хазанов.
Здравствуйте, Sergey, Вы писали:
S>А зачем тебе имена функций на компьютере клиента? Достаточно транслировать адреса в логические, а имена функций брать из map-файла на своей машине (ну, при этом, правда, придется хранить map-файлы и pdb для всех версий программы — зато pdb никому отдавать не придется). Или без map-файла — сразу бинарник+pdb в IDA грузить.
S>Best regards, S> Sergey.
Дело в том, что на другой машине она мне вообще не выдает даже адреса моей функции OnButton1.
lav03 wrote: > > Здравствуйте, Pavel Dvorkin, Вы писали: > PD>ИМХО что-то связано с imghelp.dll. Как бы мне ее VC7 не переписал при > PD>установке. > > Точно! У меня тоже VC7 стоит. Я чейчас проверил — на VC7 работает. Это что же тогда получается, мне сосвоей программой нужно и imghelp.dll от VC7 распространять? А если я ее подменю, другие проги, юзающие старые версии, отъедут?
Хуже. imghelp.dll не есть re-distributable .
Но вообще-то ИМХО нужно просто правильную версию сунуть в каталог, где
EXE. По общим правилам поиск сначала идет в этом каталоге, а потом в
system32 (см. LoadLibrary). Насколько я помню, к well-known dll она не
относится (а вообще-то проверь)
Здравствуйте, Pavel Dvorkin, Вы писали:
PD>Привет!
PD>lav03 wrote: >> >> Здравствуйте, Pavel Dvorkin, Вы писали: >> PD>ИМХО что-то связано с imghelp.dll. Как бы мне ее VC7 не переписал при >> PD>установке. >> >> Точно! У меня тоже VC7 стоит. Я чейчас проверил — на VC7 работает. Это что же тогда получается, мне сосвоей программой нужно и imghelp.dll от VC7 распространять? А если я ее подменю, другие проги, юзающие старые версии, отъедут?
PD>Хуже. imghelp.dll не есть re-distributable .
PD>Но вообще-то ИМХО нужно просто правильную версию сунуть в каталог, где PD>EXE. По общим правилам поиск сначала идет в этом каталоге, а потом в PD>system32 (см. LoadLibrary). Насколько я помню, к well-known dll она не PD>относится (а вообще-то проверь)
PD>-- PD>С наилучшими пожеланиями PD> Дворкин Павел
Сунул. Не работает.
Вот гадость какая. Вся идея рушится. А так хотелось сделать хорошо.
Уверен, что именно ту, что нужно сунул ?
Эта библиотека записывается в system32 при инсталляции VC (ИМХО). Я бы
на твоем месте поискал бы ее в system32 машины, на которой VC7 никогда
не ставился.
Работало же оно в конце концов до того, как VC7 на свет появился.
AfxDump.. ИМХО еще в 4.2 была, а то и раньше.
Ха! Я понял. AfxDumpStack() без файла .pdb не работает (точнеее работает, но не так). Прчем, интересно получается.
Если я имею .pdb, я получу примерно такой дамп:
где foo — моя функция, где произошло, в данном случае структурнре, исключение, а CEhsTerminalErrHandler::HandleStructuredException() и CEhsTerminalErrHandler::MakeStructuredExceptionReport() вызываются из foo() для обработки исключения.
Если же программа не находит .pdb файл, дамп содержит меньше строк. А самое обидное, что в нем нет адресов функций:
0040157F: \SUPERPUPS\Guest\1\ErrHndlTest.exe! CEhsTerminalErrHandler::HandleStructuredException + 31 bytes
0040195D: \SUPERPUPS\Guest\1\ErrHndlTest.exe! foo + 349 bytes
Причем, такая фича имеет место, если AfxDumpStack() вызвана в теле ф-ции
CEhsTerminalErrHandler::MakeStructuredExceptionReport().
Но, если AfxDumpStack() вызвать непосредственно из foo, то строки
0040157F: \SUPERPUPS\Guest\1\ErrHndlTest.exe! <no symbol>
0040195D: \SUPERPUPS\Guest\1\ErrHndlTest.exe! <no symbol>
соотсет-щие ф-циям CEhsTerminalErrHandler::HandleStructuredException() и foo() появятся.
AfxDumpStack() использует API для "прогулок по стеку". Может там и есть где-то ошибка, но, посмотрев исходник, почитав описания ф-ций и различных структур, ей испольуемых, для меня работа со стеком с помощью API не стала много прозрачней. По крайней мере ошибку в исходнике я не в состоянии найти.
Распространять .pdb я не хочу. Как же мне тогда получить правильный список вызовов функций? Может через ассемблер в стек залезть? Не подскажет ли кто, где можно почитать о том, как получить информацию из стека с помощью ассемблера, где что там жранится и как его правильно просматривать. А уж получив адреса я по .map файлу смогу названия функций определить.
lav03 wrote: > > Здравствуйте, Pavel Dvorkin, Вы писали: > > Ха! Я понял. AfxDumpStack() без файла .pdb не работает
Именно так. Я полагал, что ты это знаешь.
> > Распространять .pdb я не хочу. Как же мне тогда получить правильный список вызовов функций?
Никак. Как говорил один литературный герой, "при наличии отсутствия".
Именно в .pdb (можно еще в .dbg, но я не знаю, как их делать) и лежит
вся требуемая информация.
>Может через ассемблер в стек залезть? Не подскажет ли кто, где можно почитать о том, как получить информацию из стека с помощью ассемблера, где что там жранится и как его правильно просматривать. А уж получив адреса я по .map файлу смогу названия функций определить.
Хм, а чем тебе map файл лучше pdb ?
А насчет того, что хранится в стеке — ответ прост. Адреса возвратов,
локальные переменные, фактические парметры и фреймы SEH. В стековом
порядке
Hello, lav03!
You wrote on Fri, 28 Nov 2003 11:09:21 GMT:
l> Распространять .pdb я не хочу. Как же мне тогда получить правильный l> список вызовов функций? Может через ассемблер в стек залезть? Не l> подскажет ли кто, где можно почитать о том, как получить информацию из l> стека с помощью ассемблера, где что там жранится и как его правильно l> просматривать. А уж получив адреса я по .map файлу смогу названия l> функций определить.
В общем-то, без pdb полноценно гулять по стеку, имхо, невозможно. Метод гуляния по стеку без pdb очень простой — предполагается, что компилятор в начале каждой функции генерирует некоторый пролог, формирующий так называемый stack frame:
push ebp
move ebp, esp
sub esp, local_vars_size
Соответственно, и сделать дамп стека не представляет особого труда (пример из какой-то статьи Питрека, хотя я его вроде под свои цели чуть-чуть переделывал):
void CCrashHandler::IntelStackWalk(PCONTEXT pContext)
{
_tprintf( _T("\r\nCall stack:\r\n") );
_tprintf( _T("Address Frame Logical addr Module\r\n") );
DWORD pc = pContext->Eip;
PDWORD pFrame, pPrevFrame;
pFrame = (PDWORD)pContext->Ebp;
do
{
TCHAR szModule[MAX_PATH] = _T("");
DWORD section = 0, offset = 0;
GetLogicalAddress((PVOID)pc, szModule, sizeof(szModule), section, offset);
_tprintf(_T("%08X %08X %04X:%08X %s\r\n"), pc, pFrame, section, offset, szModule);
pc = pFrame[1];
pPrevFrame = pFrame;
pFrame = (PDWORD)pFrame[0]; // precede to next higher frame on stack
if ((DWORD)pFrame & 3) // Frame pointer must be aligned on a
break; // DWORD boundary. Bail if not so.
if (pFrame <= pPrevFrame)
break;
// Can two DWORDs be read from the supposed frame address?
if (IsBadReadPtr(pFrame, sizeof(PVOID)*2))
break;
} while (1);
}
Однако все так здорово ровно до тех пор, пока компилятор не пользуется т.н. FPO — оптимизацию (Frame-Pointer Omission). Через код без кадров стека так просто не погуляешь, так что придется быть готовым к тому, что не всегда удастся сделать полноценный дамп стека (для увеличиния вероятности успеха можно выключить FPO при компиляции (опция /Oy- после опций оптимизации)), или использовать pdb (лучше ее слегка почикать с помощью /PDBSTRIPPED, если у тебя VC 7).
Best regards,
Sergey.
Posted via RSDN NNTP Server 1.8 beta
Одним из 33 полных кавалеров ордена "За заслуги перед Отечеством" является Геннадий Хазанов.