Login
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
in Antwort evgher 05.06.12 18:58
NEW 07.06.12 14:42
in Antwort 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
in Antwort evgher 07.06.12 14:42
ну это сильно зависит от реализации компилятора и уровня оптимизации. В чем заключается задача - пропустить ошибочную конструкцию и просто продолжать работу?
в принципе, надо смотреть мануал на компилятор - мне кажется что у многих были флаги компилятора, которые позволяли отключить генерацию исключений, но я не знаю точно - я лет 10 не работал с расчетными вещами
в принципе, надо смотреть мануал на компилятор - мне кажется что у многих были флаги компилятора, которые позволяли отключить генерацию исключений, но я не знаю точно - я лет 10 не работал с расчетными вещами
NEW 07.06.12 18:43
in Antwort AlexOtt 07.06.12 16:22
Задача заключается в том, чтобы при каждой неправильной "Floating point operation" на "Stack" для ошибочной операции заходило значение 0,0.
И вычесление продолжалось дальше. Т. е.
b = 1.0/0.0 + 10.0 должно равняться 10.0
И вычесление продолжалось дальше. Т. е.
b = 1.0/0.0 + 10.0 должно равняться 10.0
NEW 07.06.12 19:24
in Antwort evgher 07.06.12 18:43
Напиши выражение с разбивкой, выделив деление с присвоением в отдельный оператор и контролируй его выполнение. Разбираться с нюансами работы со стеком для каждой среды, модели и транслятора - ну его нафиг...
NEW 07.06.12 20:01
in Antwort evgher 07.06.12 18:43
посмотрите на ключи со словом math со страницы http://gcc.gnu.org/onlinedocs/gcc-3.4.6/gcc/Optimize-Options.html и http://gcc.gnu.org/wiki/FloatingPointMath
NEW 07.06.12 20:57
in Antwort Murr 07.06.12 19:24
Речь идёт о примерно от 40000 до 100000 строк кода. Причём код этот реализует вычисления для аэробуса по методу "FEM".
Так что разбивать слишком долго придётся)))
Так что разбивать слишком долго придётся)))
NEW 15.06.12 15:31
in Antwort 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 15.06.12 19:52
in Antwort evgher 15.06.12 15:31
я бы все-таки не парил себе мозги, а поискал бы имеющиеся библиотеки в которых есть такая функциональность. ни за что не поверю, что таких библиотек нет - в том же CERN должны такие вещи быть
NEW 01.07.12 16:29
in Antwort 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?"
уже веселит до колик. Вам надо к не к программистам, а к специалистам по квантовой механике обращаться:)
Я теперь понял, что с таким ПО на аэробусах летать нельзя.
NEW 04.07.12 16:02
in Antwort ThorV 01.07.12 16:29
Проблема уже почти решена. Нащёт полётов на аэробусе.
Не один самолёт не имеет разрешение выйте в эксплуатацию не пройдя расчётов именно
вот этой программы. Писали её не программисты а очень умные люди. К сожалению не информатики.
Не один самолёт не имеет разрешение выйте в эксплуатацию не пройдя расчётов именно
вот этой программы. Писали её не программисты а очень умные люди. К сожалению не информатики.