Как узнать, произошло прерывание или исключение?

Тема в разделе "WASM.OS.DEVEL", создана пользователем 10110111, 13 авг 2007.

  1. 10110111

    10110111 New Member

    Публикаций:
    0
    Регистрация:
    13 июл 2006
    Сообщения:
    319
    Адрес:
    Санкт-Петербург
    Как можно узнать, вызван ли обработчик прерывания инструкцией int XX или же это исключение? Главная проблема при этом, что неизвестно, считывать ли код ошибки для проверки предыдущей инструкции через CS:EIP-2 и FLAGS (на случай V86) на равенство 0xCD.
     
  2. wasm_test

    wasm_test wasm test user

    Публикаций:
    0
    Регистрация:
    24 ноя 2006
    Сообщения:
    5.582
    посмотреть байты CS:[EIP-2] на равенство опкоду команды INT xx
     
  3. 10110111

    10110111 New Member

    Публикаций:
    0
    Регистрация:
    13 июл 2006
    Сообщения:
    319
    Адрес:
    Санкт-Петербург
    Не пойдёт, я ж написал, неизвестно, надо ли читать [esp+0] или [esp+4] для получения EIP, так как при исключении может push'аться код ошибки
     
  4. wasm_test

    wasm_test wasm test user

    Публикаций:
    0
    Регистрация:
    24 ноя 2006
    Сообщения:
    5.582
    ой не заметил =)
    ну у некоторых исключений нет кода ошибки - раз.
    два - код ошибки вроде не больше байта, поэтому можно проверить по маске FFFFFF00 двойное слово ss:[esp]
     
  5. rei3er

    rei3er maxim

    Публикаций:
    0
    Регистрация:
    15 янв 2007
    Сообщения:
    917
    Адрес:
    minsk
    Great
    вообще-то код ошибки 32 бита (может быть 16 бит, если разрядность шлюза - 16 бит)
    10110111
    имхо, однозначного 100-процентного решения нет
     
  6. 0136

    0136 New Member

    Публикаций:
    0
    Регистрация:
    19 апр 2007
    Сообщения:
    112
    ectb 100% rewenie !
     
  7. rei3er

    rei3er maxim

    Публикаций:
    0
    Регистрация:
    15 янв 2007
    Сообщения:
    917
    Адрес:
    minsk
    0136
    ну выкладывай
     
  8. Mika0x65

    Mika0x65 New Member

    Публикаций:
    0
    Регистрация:
    30 июл 2005
    Сообщения:
    1.384
    А код какого кольца может содержать в себе 'int XX'? Если не нулевого, то можно выставить DPL шлюза прерывания в 0, и тогда остальные кольца просто не смогут побеспокоить обаботчик.
     
  9. k3internal

    k3internal New Member

    Публикаций:
    0
    Регистрация:
    11 янв 2007
    Сообщения:
    607
    10110111
    Уточни какое прерывание для начала. #GP ? #UD ?
     
  10. wasm_test

    wasm_test wasm test user

    Публикаций:
    0
    Регистрация:
    24 ноя 2006
    Сообщения:
    5.582
    Можно просто для каждого исключения свой обработчик засандалить, который вынет или не вынет из стека код ошибки и проанализирует EIP из стека. конечно если вызов был прямой EIP будет косой, т.к. код ошибки выталкивать не надо было, там где он есть при реальном исключении.. можно проверить старшую часть EIP на равенство регистру флагов (т.к. его младшее слово попадет туда, если вытолкнуть из стека лишний дворд, которым был eip) с учетом того, как они могли измениться до кода проверки..
    Ну или хз вообще :)

    Типа такого:

    ; Прерывание XX с кодом ошибки
    SomeException_XX_WithErrorCode:
    pop eax ; извлекаем код ошибки
    pushf ; сохраняем флаги для сравнения
    pop ebx
    cmp [esp+2], ebx ; лежит ли по esp+2 регистр флагов? если да - прерывание было ложным
    je false_exception
    ...

    Если нет кода ошибки тогда хз.. Хотел сравнить cs:[eip] на равенство cd xx, но там вроде бы при исключении сохраняется адрес текущией инструкции.. а при int'е - следующей. Так что непонятно что сравнивать.. [eip] или [eip-2]
     
  11. rei3er

    rei3er maxim

    Публикаций:
    0
    Регистрация:
    15 янв 2007
    Сообщения:
    917
    Адрес:
    minsk
    исключение может быть не типа
    FAULT
    например #BP
    а если старшее слово EIP + значение CS в точности дадут значение EFLAGS?
    ситуация, конечно, маловероятная, но все же
     
  12. 10110111

    10110111 New Member

    Публикаций:
    0
    Регистрация:
    13 июл 2006
    Сообщения:
    319
    Адрес:
    Санкт-Петербург
    Mika0x65
    Кольцо любое. Кроме того - смогут ли приложения R3 вызывать _исключения_, если DPL==0?

    k3internal
    Прерывание любое, возвращающее код ошибки.

    Great
    Конечно, [eip-2] - только здесь что-либо может быть равным CD XX.

    rei3er
    А при появлении будем долго думать, отчего же система упала )) ведь ошибка невоспроизводимая.

    Есть идея решить через шлюз задачи. Тогда в обработчике можно будет у предыдущей задачи смотреть [CS:EIP-2], с ним сравнивать. В принципе, можно даже тогда и не проверять состояние предыдущей задачи - просто сравнивать esp задачи обработчика с эталоном, и в случае обнаружения отсутствия ошибки предпринимать соответствующие действия. Но единственная проблема остается: если в этот момент или в обработчике произойдет еще одно исключение или прерывание, то будет Triple Fault...: #GP->#GP->Reset#GP из-за флага NT. Или я чего-то недопонял с этим флагом?..
     
  13. rei3er

    rei3er maxim

    Публикаций:
    0
    Регистрация:
    15 янв 2007
    Сообщения:
    917
    Адрес:
    minsk
    всю IDT патчить будешь что-ли?
    тогда можно проще, без шлюза задачи
     
  14. wasm_test

    wasm_test wasm test user

    Публикаций:
    0
    Регистрация:
    24 ноя 2006
    Сообщения:
    5.582
    10110111
    jmp @f
    int 14
    @@: mov dword ptr [0], eax

    сгенерирует исключение #PF (при условии отсутствия памяти по вирт адресу 0), но все таки [eip-2] будет равен cd 14, как будто прерывание сгенерировано насильно
     
  15. 10110111

    10110111 New Member

    Публикаций:
    0
    Регистрация:
    13 июл 2006
    Сообщения:
    319
    Адрес:
    Санкт-Петербург
    Это не для патча - для своей ОСи.
    Как?
    Great
    Не додумал =) Тогда действительно проще через шлюз задачи.
     
  16. rei3er

    rei3er maxim

    Публикаций:
    0
    Регистрация:
    15 янв 2007
    Сообщения:
    917
    Адрес:
    minsk
    для всех шлюзов, через которые вызываются обработчики исключений, установить DPL = 0
    и не использовать int XX, где XX = 0...31 :derisive:
     
  17. 10110111

    10110111 New Member

    Публикаций:
    0
    Регистрация:
    13 июл 2006
    Сообщения:
    319
    Адрес:
    Санкт-Петербург
    Было бы хорошо, если бы не обстоятельство: надо обеспечивать прерывания в V86, причем не используя VME.
     
  18. rei3er

    rei3er maxim

    Публикаций:
    0
    Регистрация:
    15 янв 2007
    Сообщения:
    917
    Адрес:
    minsk
    для этого нужно поставить IOPL поставить < 3 в V86 задаче
    любая инструкция int XX будет генерировать исключение #GP с кодом ошибки
    смотрим EFLAGS в стеке, если VM установлен, значит причина #GP, одна из инструкций int XX, sti, cli, pushf, popf или iret
    далее берем EIP из стека и анализируем инструкцию, которая привела к исключению
    это первый вариант
    второй вариант, использовать Software Interrupt Redirection Bit Map в TSS
    (только надо предварительно заполнить IVT (линейные адреса 0x000-0x400))
     
  19. 10110111

    10110111 New Member

    Публикаций:
    0
    Регистрация:
    13 июл 2006
    Сообщения:
    319
    Адрес:
    Санкт-Петербург
    За первый вариант спасибо. Второй требует VME.
     
  20. k3internal

    k3internal New Member

    Публикаций:
    0
    Регистрация:
    11 янв 2007
    Сообщения:
    607
    10110111

    Вообще ты странно вопрос ставиш. Каждое прерывание обрабатывается по своему и о своим правилам. О том что генерит данный инт легко узнать из интелловских мануалов. Помоему господа кг/ам.