Вход на сайт
SIGFPE / signal
333
05.06.12 18:58
Существует ли возможность в СИ или даже СИ++ выслеживать "arithmetic exceptions" с помощью
signal.h. Сейчас портирую код с HP-UX. Там присутствовала удобная вишка для отлавливания и корректуры всех "arithmetic exceptions".
Т. е. вызывается Exception_Handler автомотически при "UNDERFLOW, OVERFLOW, DIVEDE BY ZERO" и т. д.
Этот Handler переписывает значение переменной - например ноль.
Спасибо за контруктивные советы
signal.h. Сейчас портирую код с HP-UX. Там присутствовала удобная вишка для отлавливания и корректуры всех "arithmetic exceptions".
Т. е. вызывается Exception_Handler автомотически при "UNDERFLOW, OVERFLOW, DIVEDE BY ZERO" и т. д.
Этот Handler переписывает значение переменной - например ноль.
Спасибо за контруктивные советы
NEW 05.06.12 20:45
в ответ evgher 05.06.12 18:58
NEW 07.06.12 14:42
в ответ AlexOtt 05.06.12 20:45
Что-то у меня многое не клеется. Например у нас "инструкция": b1 = b1/0.0 - 1e-300*1e-300 (внизу в дисасемблированном виде),
в которой сразу несколько "FPE". При исполнении этой строки "program counter" должен перейти с адреса main+0x004e: на адрес main+0x007b:
после обработки "exception_handler". Разница между адресами соответствует 31, т. е. надо сделать прыжок в коде примерно таким образом:
При инструкции b1 = b1/0.0 разница адресов соответсвует 15-ти, т. е. это число постоянно меняется.
Существует какая либо возможность узнавать при исполнении программы, когда начинается следующая инструкция?
в которой сразу несколько "FPE". При исполнении этой строки "program counter" должен перейти с адреса main+0x004e: на адрес main+0x007b:
после обработки "exception_handler". Разница между адресами соответствует 31, т. е. надо сделать прыжок в коде примерно таким образом:
При инструкции b1 = b1/0.0 разница адресов соответсвует 15-ти, т. е. это число постоянно меняется.
Существует какая либо возможность узнавать при исполнении программы, когда начинается следующая инструкция?
В ответ на:
void sigfpe_handler(int signo, siginfo_t *si, void *MainContext)
{
ucontext_t *pMainContext = @context von main
ucontext_t *pHandlerContext = @context von handler
switch(si->si_code)
{
case FPE_INTDIV: ....
....
case FPE_FLTDIV: puts("floating point divide by zero");
pMainContext->uc_mcontext.gregs[REG_RIP] +=31;
break;
case FPE_FLTOVF: ....
....
}
swapcontextp(pHandlerContext, pMainContext);
}
[цитата/]
....
[цитата]
143 printf("00: b1: %f; b2: %f\n",b1,b2);
0x00000000004009f6: main+0x0026: cvtss2sd 0xfffffffffffffff8(%rbp),%xmm2
0x00000000004009fb: main+0x002b: cvtss2sd 0xfffffffffffffff4(%rbp),%xmm0
0x0000000000400a00: main+0x0030: movsd %xmm0,%xmm1
0x0000000000400a04: main+0x0034: movsd %xmm2,%xmm0
0x0000000000400a08: main+0x0038: movq $_lib_version+0x1fc,%rdi
0x0000000000400a0f: main+0x003f: movl $0x0000000000000002,%eax
0x0000000000400a14: main+0x0044: call 0x00000000004004cc in PLT [ 0x4004cc, .-0x548 ]
0x0000000000400a19: main+0x0049: movl $0x0000000000000000,%eax
144 b1 = b1/0.0 - 1e-300*1e-300;
0x0000000000400a1e: main+0x004e: cvtss2sd 0xfffffffffffffff8(%rbp),%xmm3
0x0000000000400a23: main+0x0053: divsd _lib_version+0x14,%xmm3
0x0000000000400a2c: main+0x005c: movsd _lib_version+0x1c,%xmm2
0x0000000000400a35: main+0x0065: mulsd _lib_version+0x1c,%xmm2
0x0000000000400a3e: main+0x006e: subsd %xmm2,%xmm3
0x0000000000400a42: main+0x0072: cvtsd2ss %xmm3,%xmm2
0x0000000000400a46: main+0x0076: movss %xmm2,0xfffffffffffffff8(%rbp)
145 printf("01: b1: %f; b2: %f\n",b1,b2);
0x0000000000400a4b: main+0x007b: cvtss2sd 0xfffffffffffffff8(%rbp),%xmm3
0x0000000000400a50: main+0x0080: cvtss2sd 0xfffffffffffffff4(%rbp),%xmm2
0x0000000000400a55: main+0x0085: movsd %xmm2,%xmm1
0x0000000000400a59: main+0x0089: movsd %xmm3,%xmm0
0x0000000000400a5d: main+0x008d: movq $_lib_version+0x214,%rdi
0x0000000000400a64: main+0x0094: movl $0x0000000000000002,%eax
0x0000000000400a69: main+0x0099: call 0x00000000004004cc in PLT [ 0x4004cc, .-0x59d ]
0x0000000000400a6e: main+0x009e: movl $0x0000000000000000,%eax
void sigfpe_handler(int signo, siginfo_t *si, void *MainContext)
{
ucontext_t *pMainContext = @context von main
ucontext_t *pHandlerContext = @context von handler
switch(si->si_code)
{
case FPE_INTDIV: ....
....
case FPE_FLTDIV: puts("floating point divide by zero");
pMainContext->uc_mcontext.gregs[REG_RIP] +=31;
break;
case FPE_FLTOVF: ....
....
}
swapcontextp(pHandlerContext, pMainContext);
}
[цитата/]
....
[цитата]
143 printf("00: b1: %f; b2: %f\n",b1,b2);
0x00000000004009f6: main+0x0026: cvtss2sd 0xfffffffffffffff8(%rbp),%xmm2
0x00000000004009fb: main+0x002b: cvtss2sd 0xfffffffffffffff4(%rbp),%xmm0
0x0000000000400a00: main+0x0030: movsd %xmm0,%xmm1
0x0000000000400a04: main+0x0034: movsd %xmm2,%xmm0
0x0000000000400a08: main+0x0038: movq $_lib_version+0x1fc,%rdi
0x0000000000400a0f: main+0x003f: movl $0x0000000000000002,%eax
0x0000000000400a14: main+0x0044: call 0x00000000004004cc in PLT [ 0x4004cc, .-0x548 ]
0x0000000000400a19: main+0x0049: movl $0x0000000000000000,%eax
144 b1 = b1/0.0 - 1e-300*1e-300;
0x0000000000400a1e: main+0x004e: cvtss2sd 0xfffffffffffffff8(%rbp),%xmm3
0x0000000000400a23: main+0x0053: divsd _lib_version+0x14,%xmm3
0x0000000000400a2c: main+0x005c: movsd _lib_version+0x1c,%xmm2
0x0000000000400a35: main+0x0065: mulsd _lib_version+0x1c,%xmm2
0x0000000000400a3e: main+0x006e: subsd %xmm2,%xmm3
0x0000000000400a42: main+0x0072: cvtsd2ss %xmm3,%xmm2
0x0000000000400a46: main+0x0076: movss %xmm2,0xfffffffffffffff8(%rbp)
145 printf("01: b1: %f; b2: %f\n",b1,b2);
0x0000000000400a4b: main+0x007b: cvtss2sd 0xfffffffffffffff8(%rbp),%xmm3
0x0000000000400a50: main+0x0080: cvtss2sd 0xfffffffffffffff4(%rbp),%xmm2
0x0000000000400a55: main+0x0085: movsd %xmm2,%xmm1
0x0000000000400a59: main+0x0089: movsd %xmm3,%xmm0
0x0000000000400a5d: main+0x008d: movq $_lib_version+0x214,%rdi
0x0000000000400a64: main+0x0094: movl $0x0000000000000002,%eax
0x0000000000400a69: main+0x0099: call 0x00000000004004cc in PLT [ 0x4004cc, .-0x59d ]
0x0000000000400a6e: main+0x009e: movl $0x0000000000000000,%eax
NEW 07.06.12 16:22
в ответ evgher 07.06.12 14:42
ну это сильно зависит от реализации компилятора и уровня оптимизации. В чем заключается задача - пропустить ошибочную конструкцию и просто продолжать работу?
в принципе, надо смотреть мануал на компилятор - мне кажется что у многих были флаги компилятора, которые позволяли отключить генерацию исключений, но я не знаю точно - я лет 10 не работал с расчетными вещами
в принципе, надо смотреть мануал на компилятор - мне кажется что у многих были флаги компилятора, которые позволяли отключить генерацию исключений, но я не знаю точно - я лет 10 не работал с расчетными вещами
NEW 15.06.12 15:31
в ответ AlexOtt 07.06.12 20:01
Вообщим с огромным трудом - почти всё перепробывал и наконец-то в силу имеющих библиотечных рессурсов вышел ожидаемый результат
Длина инструкции в фортране (=4) и Си(=9) разная. Поэтому в зависимости от языка надо правильно определить длину инструкции.
В аналогичном примере тут получается точно выяснить в каком регистре должен быть отложен результат
На нашей ОС структура ucontext выглядит немного по другому: т. е. полей
fpu_fr и fpu_q она не имеет. Чтобы долго не мучатся можно просто переписать
все возможные значения регистров для резултата данных.
Но тут есть одно НО. Я знаю адрес указателя инструкции, но не его значение. Уже всё перепробывал.
Вопрос публике: Wie kann man anhand des Befehlszeigers auf seinen Inhalt zugreifen?
Т. е.: так было бы правильно, но невозможно из-за отсутствия подструктур fpu*.
В ответ на:
sunf95 -ftrap=%all -D_GNU_SOURCE -g -c fpetest.f
suncc -ftrap=%all -D_GNU_SOURCE -g -c handling.c
"handling.c", line 66: warning: implicit function declaration: swapcontext
"handling.c", line 85: warning: left operand of "->" must be pointer to struct/union
"handling.c", line 86: warning: left operand of "->" must be pointer to struct/union
sunf95 -ftrap=%all -D_GNU_SOURCE -g -o test fpetest.o handling.o
ContextSize: 23; Adresse: 0
Div-by-zero:-0.1E+31 / 0.0E+00 = 0.0E+00
Underflow: 0.1E-29 * 0.1E-09 = 0.0E+00
Overflow: 0.1E+31 * 0.1E+31 = 0.0E+00
Invalid: 0.0E+00 / 0.0E+00 = 0.0E+00
sunf95 -ftrap=%all -D_GNU_SOURCE -g -c fpetest.f
suncc -ftrap=%all -D_GNU_SOURCE -g -c handling.c
"handling.c", line 66: warning: implicit function declaration: swapcontext
"handling.c", line 85: warning: left operand of "->" must be pointer to struct/union
"handling.c", line 86: warning: left operand of "->" must be pointer to struct/union
sunf95 -ftrap=%all -D_GNU_SOURCE -g -o test fpetest.o handling.o
ContextSize: 23; Adresse: 0
Div-by-zero:-0.1E+31 / 0.0E+00 = 0.0E+00
Underflow: 0.1E-29 * 0.1E-09 = 0.0E+00
Overflow: 0.1E+31 * 0.1E+31 = 0.0E+00
Invalid: 0.0E+00 / 0.0E+00 = 0.0E+00
Длина инструкции в фортране (=4) и Си(=9) разная. Поэтому в зависимости от языка надо правильно определить длину инструкции.
В аналогичном примере тут получается точно выяснить в каком регистре должен быть отложен результат
В ответ на:
* find out registers rd, rs1, rs2, and opf
*/
fop = ((uc->fpu_q->FQu.fpq.fpq_instr)>>fopshift) &0x1ff;
frd = ((uc->fpu_q->FQu.fpq.fpq_instr)>>frdshift) &0x1f;
frs1= ((uc->fpu_q->FQu.fpq.fpq_instr)>>frs1shift)&0x1f;
frs2= ((uc->fpu_q->FQu.fpq.fpq_instr)>>frs2shift )&0x1f;
/*
* check if both rs1 and rs2 are zero (0/0 case)
*/
i = (uc->fpu_fr.fpu_regs[frs2]&0x7fffffff)|uc->fpu_fr.fpu_regs[frs2+1];
j = (uc->fpu_fr.fpu_regs[frs1]&0x7fffffff)|uc->fpu_fr.fpu_regs[frs1+1];
switch (fop) {
case 0x4e: /* fdivd */
if((i|j) == 0) { /* 0/0 , set rd to be zero_over_zero_value */
uc->fpu_fr.fpu_regs[frd] = defaultValue[0];
uc->fpu_fr.fpu_regs[frd+1] = defaultValue[1];
}
break;
}
* find out registers rd, rs1, rs2, and opf
*/
fop = ((uc->fpu_q->FQu.fpq.fpq_instr)>>fopshift) &0x1ff;
frd = ((uc->fpu_q->FQu.fpq.fpq_instr)>>frdshift) &0x1f;
frs1= ((uc->fpu_q->FQu.fpq.fpq_instr)>>frs1shift)&0x1f;
frs2= ((uc->fpu_q->FQu.fpq.fpq_instr)>>frs2shift )&0x1f;
/*
* check if both rs1 and rs2 are zero (0/0 case)
*/
i = (uc->fpu_fr.fpu_regs[frs2]&0x7fffffff)|uc->fpu_fr.fpu_regs[frs2+1];
j = (uc->fpu_fr.fpu_regs[frs1]&0x7fffffff)|uc->fpu_fr.fpu_regs[frs1+1];
switch (fop) {
case 0x4e: /* fdivd */
if((i|j) == 0) { /* 0/0 , set rd to be zero_over_zero_value */
uc->fpu_fr.fpu_regs[frd] = defaultValue[0];
uc->fpu_fr.fpu_regs[frd+1] = defaultValue[1];
}
break;
}
На нашей ОС структура ucontext выглядит немного по другому: т. е. полей
fpu_fr и fpu_q она не имеет. Чтобы долго не мучатся можно просто переписать
все возможные значения регистров для резултата данных.
В ответ на:
int *defaultValue = (int *) &zero_over_zero_value;
for(int i =0; i < NPREG; i++)
{
(*uc)->_xmm.element[0] = (int)defaultValue[0];
(*uc)->_xmm.element[1] = (int)defaultValue[1];
}
int *defaultValue = (int *) &zero_over_zero_value;
for(int i =0; i < NPREG; i++)
{
(*uc)->_xmm.element[0] = (int)defaultValue[0];
(*uc)->_xmm.element[1] = (int)defaultValue[1];
}
Но тут есть одно НО. Я знаю адрес указателя инструкции, но не его значение. Уже всё перепробывал.
Вопрос публике: Wie kann man anhand des Befehlszeigers auf seinen Inhalt zugreifen?
Т. е.: так было бы правильно, но невозможно из-за отсутствия подструктур fpu*.
В ответ на:
//uc->fpu_q->FQu.fpq.fpq_instr // instruction
frd = ((uc->fpu_q->FQu.fpq.fpq_instr)>>frdshift) &0x1f; // Ergebnisregister
uc->fpu_fr.fpu_regs[frd] = defaultValue[0]; // redifinition of result register
uc->fpu_fr.fpu_regs[frd+1] = defaultValue[1];
//uc->fpu_q->FQu.fpq.fpq_instr // instruction
frd = ((uc->fpu_q->FQu.fpq.fpq_instr)>>frdshift) &0x1f; // Ergebnisregister
uc->fpu_fr.fpu_regs[frd] = defaultValue[0]; // redifinition of result register
uc->fpu_fr.fpu_regs[frd+1] = defaultValue[1];
В ответ на:
context->uc_mcontext.gregs[REG_RIP] // the current instruction pointer (uint32)
//-----> Wie bekomme ich anhand des Zeigers den Inhalt des Befehls?
context->uc_mcontext.gregs[REG_RIP] // the current instruction pointer (uint32)
//-----> Wie bekomme ich anhand des Zeigers den Inhalt des Befehls?
NEW 01.07.12 16:29
в ответ evgher 15.06.12 15:31
IMHO даже не в смысле кодировки, а такой подход к программированию ..как-бы сказать.. нетрадиционной ориентации.
Если уж так хочется приключений, надо читать классику, сиречь Richard W. Stevens "APUE" . Есть такие функции sigsetjmp, siglongjmp, пользуйтесь сколько душе угодно.
А вот это
"Wie kann man anhand des Befehlszeigers auf seinen Inhalt zugreifen?"
уже веселит до колик. Вам надо к не к программистам, а к специалистам по квантовой механике обращаться:)
Я теперь понял, что с таким ПО на аэробусах летать нельзя.
Если уж так хочется приключений, надо читать классику, сиречь Richard W. Stevens "APUE" . Есть такие функции sigsetjmp, siglongjmp, пользуйтесь сколько душе угодно.
А вот это
"Wie kann man anhand des Befehlszeigers auf seinen Inhalt zugreifen?"
уже веселит до колик. Вам надо к не к программистам, а к специалистам по квантовой механике обращаться:)
Я теперь понял, что с таким ПО на аэробусах летать нельзя.