|
|
| Посл.отвђт | Сообщенiе |
|
|
Дата: Апр 16, 2004 03:00:31 volodya Лестно :-) Осталось только учредить компанию. А имел ли право компилятор так поступать, можно развить дискуссию. Только дождемся вечера 8-) |
|
|
Дата: Апр 16, 2004 03:14:18 ушло минут 20, хотя можно быстрее, (см reversing :) ) зато разобрал все :) |
|
|
Дата: Апр 16, 2004 06:20:46 Funbit В разборе есть ошибки. См. письмо. В главном не ошибся, в мелочах напортачил. |
|
|
Дата: Апр 16, 2004 11:56:00 2Володя: хм. на реверсинге у RElf'a, такая же как и у меня точка зрения по поводу начала for(;;). Один в один. (он на пару команд выше, чем то, где идет непосредственный loop) |
|
|
Дата: Апр 16, 2004 17:14:34 volodya исправился :) |
|
|
Дата: Апр 16, 2004 18:09:30 Ну что ж. Коль я открыл эту тему, то и время собирать камни. Итак. Народу участвовало много и мне очень приятно, что заинтересовалось столь большое количество людей. Отдельное спасибо dragon. Самый лучший результат (со слов, понятное дело, однако я склонен доверять этим словам) показал Harmer - 3 минуты. Потом Relf - 4 минуты на полное реверсирование. (это ребята с reversing.net - старый сайт и сильные участники). Все остальные уложились минут в 15-20 на причину + еще минут 15 на полное реверсирование, включая определение границ for(;;). Однако в последнем случае мнения всех разошлись. Сразу скажу, что с Relf я не согласен. Начнем с начала :) Все участники асболютно правы, называя причиной tmp = tmp->next Ассемблерная строчка находится примерно за 3 секунды. Причина сбоя - память не доступна для чтения. Процесс соотнесения ассемблерного кода с сишной строчкой у каждого участника занял разное количество времени. Теперь давайте посмотрим на границы for(;;). Еще раз взглянем на сишный код:
for (;;)
{
break;
continue;
continue;
continue;
continue;
continue;
return; //#1
}
return; //#2
Видно, что есть один-единственный break, тут же выбрасывающий нас из for(;;) прямо на return #2. Если внимательно посмотреть ассемблерный код, видно, что на роль этого break тянет ТОЛЬКО ОДИН jcc - c015b787: 0f 84 a1 00 00 00 je c015b82e <d_lookup+0x10e> (кстати, до него есть js, но он никаким боком к for(;;) не относится - система многопроцессорная, поэтому это spin_lock). Итак, с break мы определились. Но есть еще одна вещь. Рассмотрим все continue. c015b79a: 0f 85 82 00 00 00 jne c015b822 <d_lookup+0x102> c015b7a7: 75 79 jne c015b822 <d_lookup+0x102> c015b7ce: eb 52 jmp c015b822 <d_lookup+0x102> c015b7d7: 75 49 jne c015b822 <d_lookup+0x102> c015b7ef: 75 31 jne c015b822 <d_lookup+0x102> c015b822: 3b 2c 24 cmp (%esp,1),%ebp c015b825: 8d 5d f0 lea 0xfffffff0(%ebp),%ebx c015b828: 0f 85 62 ff ff ff jne c015b790 <d_lookup+0x70> Т.е. видно, что имеем пять переходов к одной метке, и jne на этой метке и ведет НА НАЧАЛО for(;;). Следовательно, for(;;) начинается с c015b790, а вовсе не с c015b782, как утверждает (хе, ну, сами знаете кто утверждает). Как это выглядит на уровне C-кода? А вот тут уже непоняток чуть больше. Очевидно, struct dentry * dentry = list_entry(tmp, struct dentry, d_hash); более не располагается на должном месте, она была перенесена. Далее, if (tmp==head) break, вероятно, ВСТРЕЧАЕТСЯ ДВАЖДЫ: c015b782: 39 d5 cmp %edx,%ebp c015b784: 8d 5d f0 lea 0xfffffff0(%ebp),%ebx и тут: c015b822: 3b 2c 24 cmp (%esp,1),%ebp c015b825: 8d 5d f0 lea 0xfffffff0(%ebp),%ebx c015b828: 0f 85 62 ff ff ff jne c015b790 <d_lookup+0x70> Теперь прерываюсь на какое-то время и жду пинков в свой адрес или посыпаний головы пеплом :) |
|
|
Дата: Апр 16, 2004 18:38:57 Дождались разрешения, можно писать :) struct dentry * dentry = list_entry(tmp, struct dentry, d_hash); По моему скромному и наверняка ошибочному мнению, struct dentry не может быть переменной, а может быть только типом данных. Значит, list_entry не может быть функцией, зато вполне может быть макросом. А что делает этот макрос, никто не знает, поэтому при неполном анализе его можно игнорировать :) Что же касается полного анализа, на него я забил еще в самом начале, когда увидел shr $0x5,%edx. Да и обилие глобальных переменных меня тоже сильно смутило - в сишном коде я смог заметить только одну, а в асмовом штук пять. P.S. Сорри, что не подписал письмо с результатом - так "разогнался", что даже при написании письма торопился, и даже оговорок в письме наделал - пришлось еще одно письмо вдогонку отправлять :-D |
|
|
Дата: Апр 16, 2004 18:43:05 гм... перечитал еще раз "окончательный результат", и понял, что я ни при анализе не заметил, ни сейчас не могу понять, откуда известно, что "память недоступна для чтения"? По смыслу понятно, что так и должно быть, только вот винда обычно код исключения пишет, а здесь в дампе я ничего похожего не заметил... |
|
|
Дата: Апр 16, 2004 18:54:03 А что делает этот макрос, никто не знает Ехали-ехали, приехали :) #define list_entry(ptr, type, member) \ ((type *)((char *)(ptr)-(unsigned long)(&((type *)0)->member))) |
|
|
Дата: Апр 16, 2004 19:29:21 Вот теперь посыпаю голову пеплом :( Зря я слово "никто" написал. Я не знаю. Что, кстати, мне не сильно помешало в данной задаче :) Да, вот только я сделал поиск по vc98\include и по Microsoft SDK\include - они тоже не знают... Сделал поиск в /usr/include, потом в / - тоже пусто. Ну, не совсем пусто, часто встречаются вещи типа list_entry le, но это явно не то. Поискал в ISO-стандартах C и C++ - тоже нет таких вещей. То ли я искать не умею, то ли это не такая уж и элементарная вещь... Скажи хоть, что цитируешь? P.S. Кстати, если посмотреть на твой макрос, то можно сделать вывод, что это и есть та штуковина, которая встречается дважды, а именно lea 0xfffffff0(%ebp),%ebx. |
|
|
Дата: Апр 16, 2004 19:33:58 Цитирую я сорцы ядра Linux как легко догадаться, глядя на дамп. У меня вопрос к аудитории. Господа, порча поинтера отнюдь не тривиальна. Простой проверкой, типа if(tmp) tmp = tmp->next или еще как-нибудь в этом же духе тут явно не обойтись :) Мне вот очень любопытно было бы обсудить возможные меры противодействия и возможные меры отладки. В винде есть IsBadxxxPtr, что хорошо. Есть Soft-Ice с его bpm, которую можно поставить на этот поинтер и, потеряв пару дней, разобраться, кто его нагло перетирает и почему так, а вот как это дело можно подолбать в линуксе? Вводить нечто вроде CRC в структуры? |
|
|
Дата: Апр 16, 2004 20:27:19 хотел бы немножко поспорить с началом цикла for(;;) мой вариант, c015b782, который признался неверным :) хочу отметить, что адрес этот я написал с сознанием того, что сам цикл (именно луп кусок) начинался с c015b790. дело в том, что все равно ведь этот кусок относится к for циклу, т.к. если мы гипотетически уберем его из С исходника и скомпилируем, то получим тот же asm код (если конечно компилятор не выкинет часть из-за оптимизаций..), кроме куска: c015b782-c015b82e (с нижним краем могу ошибаться..) ну, в общем, вы меня поняли :) |
|
|
Дата: Апр 16, 2004 20:29:04 Еще раз повторяю, что я не могу что-то признать или не признать верным или неверным. Просто потому, что точного ответа не имею и сам. Я могу ПОЛАГАТЬ с той или иной степенью уверенности. :) |
|
|
Дата: Апр 16, 2004 20:49:04 возлагаем это на работодателя :) что, кстати, он думает по этому поводу ? :) |
|
|
Дата: Апр 16, 2004 20:51:35 Хе, ты что, подумал, что это я на работу нанимаюсь? На хрен мне это не надо сейчас. Во-первых, есть у меня уже работа, а во вторых, хочу вообще не работать :))) |
|
Powered by miniBB 1.6 © 2001-2002
Время загрузки страницы (сек.): 0.046 |