🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

5 total messages Started by Borneq Fri, 11 Dec 2015 07:44
Jak są zaimplementowane wyjątki ?
#307943
Author: Borneq
Date: Fri, 11 Dec 2015 07:44
91 lines
3174 bytes
Kiedyś na tej grupie (w 2012 roku) był przykład z C implementującymi 
wyjątki za pomocą setjmp/longjmp:
#include <setjmp.h>
#define finally else

/* Typy wyjątków */

#define DivisionByZero 1
#define MemoryAllocError 2
jmp_buf ex_buffer;
int ex_status;
#include <stdio.h>

int calc(int w)
{
          if(w%2)
          {
                  return 0;
          } else
          {
                  longjmp(ex_buffer, DivisionByZero);
          }
}

int main(int argc, char* argv[])
{
          int w = 2;
          if ((ex_status = setjmp(ex_buffer)) == 0)
          {
                  printf("Zwrócono %d\n", calc(w));
          } else if (ex_status == DivisionByZero)
          {
                  printf("Chwycono wyjątek\n");
          }
          return 0;
}

Ograniczeniem jest to, że chwyta tylko wysłane wyjątki, a nie wyjątki 
maszynowe jak błąd dzielenia czy pamięci.
A jak gcc sobie radzi?
int main (void)
{
   int n=5;
   int d=0;
   int g;
   try
   {
     g = n/d;
     throw "";
   }
   catch(...)
   {
   g=0;
   }
   return 0;
}
generuje :
.LC0:
         .string ""
main:
         push    rbp
         mov     rbp, rsp
         sub     rsp, 16
         mov     DWORD PTR [rbp-4], 5
         mov     DWORD PTR [rbp-8], 0
         mov     eax, DWORD PTR [rbp-4]
         cdq
         idiv    DWORD PTR [rbp-8]
         mov     DWORD PTR [rbp-12], eax
         mov     edi, 8
         call    __cxa_allocate_exception
         mov     QWORD PTR [rax], OFFSET FLAT:.LC0
         mov     edx, 0
         mov     esi, OFFSET FLAT:typeinfo for char const*
         mov     rdi, rax
         call    __cxa_throw
         mov     rdi, rax
         call    __cxa_begin_catch
         mov     DWORD PTR [rbp-12], 0
         call    __cxa_end_catch
         mov     eax, 0
         leave
         ret

Link do gcc.godbolt.org: https://goo.gl/0J8TUn
Tu po prostu zamiast skoków używa wywołań funkcji 
__cxa_allocate_exception,__cxa_throw,__cxa_begin_catch,__cxa_end_catch
Trzeba by się przypatrzyć ich wnętrzu.
Ale uwaga - gdy w .c nie było throw, wtedy nie ma obsługi wyjątku mimo 
dzielenia. Czyżby gcc nie potrafił obsługiwać tego typu wyjątków? Co się 
stanie, gdy jednak będzie błąd dzielenia?
Re: Jak są zaimplementowane wyjątki ?
#307944
Author: Wiktor S.
Date: Fri, 11 Dec 2015 19:51
125 lines
3669 bytes
> Ale uwaga - gdy w .c nie było throw, wtedy nie ma obsługi wyjątku mimo
> dzielenia. Czyżby gcc nie potrafił obsługiwać tego typu wyjątków? Co
> się stanie, gdy jednak będzie błąd dzielenia?

Nie wiem jak GCC.
Wiem za to, że Visual C++ ma obsługę wyjątków SEH (Structured Exception 
Handling), która pozwala na łapanie wyjątków systemowych i sprzętowych.

-------------------

/* to jest C */

#include <stdio.h>
#include <windows.h>

int dziel(int a, int b)
{
    __try
    {
        return a/b;
    }
    __except(GetExceptionCode() == EXCEPTION_INT_DIVIDE_BY_ZERO)
    {
        return 0;
    }
}

int main()
{
    printf("%d\n", dziel(5,0));
}

-------------------

__sehtable$_dziel DD 0fffffffeH
    DD 00H
    DD 0ffffffd8H
    DD 00H
    DD 0fffffffeH
    DD FLAT:$LN5@dziel
    DD FLAT:$LN6@dziel


...


    __$SEHRec$ = -24   ; size = 24
    _a$ = 8            ; size = 4
    _b$ = 12           ; size = 4

_dziel PROC
; Line 5
    push ebp
    mov ebp, esp
    push -2     ; fffffffeH
    push OFFSET __sehtable$_dziel
    push OFFSET __except_handler4
    mov eax, DWORD PTR fs:0
    push eax
    sub esp, 8
    push ebx
    push esi
    push edi
    mov eax, DWORD PTR ___security_cookie
    xor DWORD PTR __$SEHRec$[ebp+16], eax
    xor eax, ebp
    push eax
    lea eax, DWORD PTR __$SEHRec$[ebp+8]
    mov DWORD PTR fs:0, eax
    mov DWORD PTR __$SEHRec$[ebp], esp
; Line 6
    mov DWORD PTR __$SEHRec$[ebp+20], 0
; Line 8
    mov eax, DWORD PTR _a$[ebp]
    cdq
    idiv DWORD PTR _b$[ebp]
    mov DWORD PTR __$SEHRec$[ebp+20], -2 ; fffffffeH
; Line 14
    mov ecx, DWORD PTR __$SEHRec$[ebp+8]
    mov DWORD PTR fs:0, ecx
    pop ecx
    pop edi
    pop esi
    pop ebx
    mov esp, ebp
    pop ebp
    ret 0
$LN5@dziel:
; Line 10
    mov eax, DWORD PTR __$SEHRec$[ebp+4]
    mov ecx, DWORD PTR [eax]
    mov eax, DWORD PTR [ecx]
    xor edx, edx
    cmp eax, -1073741676   ; c0000094H
    sete dl
    mov eax, edx
$LN7@dziel:
    ret 0
$LN6@dziel:
    mov esp, DWORD PTR __$SEHRec$[ebp]
; Line 12
    mov DWORD PTR __$SEHRec$[ebp+20], -2 ; fffffffeH
    xor eax, eax
; Line 14
    mov ecx, DWORD PTR __$SEHRec$[ebp+8]
    mov DWORD PTR fs:0, ecx
    pop ecx
    pop edi
    pop esi
    pop ebx
    mov esp, ebp
    pop ebp
    ret 0
_dziel ENDP

-------------------

Uch... dużo tego. Nie analizowałem dokładnie. Wygląda na to że pod 
"magicznym" adresem fs:0 umieszczany jest wskaźnik na strukturę zawierającą 
m.in. adresy callbacków - funkcji sprawdzającej czy wyjątek ma być obsłużony 
i samego handlera.
Callbacki wywoływane są przez system operacyjny.

-- 
Wiktor S.
Re: Jak są zaimplementowane wyjątki ?
#307945
Author: Wojciech Muła
Date: Sat, 12 Dec 2015 06:24
66 lines
3160 bytes
On Friday, December 11, 2015 at 8:43:54 AM UTC+1, Borneq wrote:
> Trzeba by się przypatrzyć ich wnętrzu.

Możesz zacząć od tego:
https://monoinfinito.wordpress.com/series/exception-handling-in-c/

Widziałem kiedyś dobrą prezentację pokazującą szczegóły, ale nie potrafię
jej teraz znaleźć. W każdym razie kluczowa fraza to "0-overhead exceptions".

> Ale uwaga - gdy w .c nie było throw, wtedy nie ma obsługi wyjątku mimo 
> dzielenia. Czyżby gcc nie potrafił obsługiwać tego typu wyjątków?

Nie, bo to są wyjątki sprzętowe. Które np. na unixach są konwertowane
na sygnały (a sygnały to Zło(TM)).

> Co się stanie, gdy jednak będzie błąd dzielenia?

Program się mniej lub bardziej elegancko wyłoży.

BTW, kilka lat temu przysłałem na tę grupę program zamieniający sygnał
na wyjątek C++, ale... to jest brzydkie i nie wiem nawet czemu działa. :)
Wrzucam jako ciekawostkę, można dodać do kategorii "perwersje".

---start---
#include <signal.h>
#include <setjmp.h>
#include <stdio.h>

jmp_buf toplevel;

void sigsegv(int dummy) {
	longjmp(toplevel, 1);
}

void bug(char* cantread) {
	char a = cantread[0xfffffff];
}

class SegmentationFault { };

int main(int argc, char* argv[]) {

	if (signal(SIGSEGV, sigsegv) == SIG_ERR) {
		return 2;
	}
	try {
		if (!setjmp(toplevel)) {
			puts("Próba wykonania niebezpiecznego kodu");
			bug((char*)0xffffffff);
			puts("Uff, powiod³o siê");
		}
		else {
			throw SegmentationFault();
		}
	}
	catch (SegmentationFault& s) {
		puts("*** Segmentation Fault ***");
		return 1;
	}

	puts("Ok!");
	return 0;
}
---end---

w.
Re: Jak są zaimplementowane wyjątki ?
#307946
Author: Matt D.
Date: Mon, 14 Dec 2015 14:50
23 lines
1738 bytes
To dosc szeroki temat:

Specyfikacja:
https://mentorembedded.github.io/cxx-abi/abi-eh.html

Opis:
http://llvm.org/docs/ExceptionHandling.html
http://blog.kevmod.com/2014/05/digging-into-exception-handling/
https://monoinfinito.wordpress.com/series/exception-handling-in-c/
http://www.deadp0rk.com/2013/09/22/base_abi/
http://www.deadp0rk.com/2013/09/27/c-exception-handling-level-ii-abi/

StackOverflow:
https://stackoverflow.com/questions/16597350/what-is-an-exception-handling-personality-function
https://stackoverflow.com/questions/20027156/llvm-exception-handling-implementation

Zob. tez:
https://mentorembedded.github.io/cxx-abi/exceptions.pdf
https://github.com/MentorEmbedded/cxx-abi/blob/master/MIPSCompactEH.pdf

Pozdrawiam,

Matt
Re: Jak są zaimplementowane wyjątki ?
#307947
Author: Borneq
Date: Mon, 14 Aug 2017 06:25
25 lines
2034 bytes
W dniu 14.12.2015 o 15:50, Matt D. pisze:
> Specyfikacja:
> https://mentorembedded.github.io/cxx-abi/abi-eh.html
> 
> Opis:
> http://llvm.org/docs/ExceptionHandling.html
> http://blog.kevmod.com/2014/05/digging-into-exception-handling/
> https://monoinfinito.wordpress.com/series/exception-handling-in-c/
> http://www.deadp0rk.com/2013/09/22/base_abi/
> http://www.deadp0rk.com/2013/09/27/c-exception-handling-level-ii-abi/
> 
> StackOverflow:
> https://stackoverflow.com/questions/16597350/what-is-an-exception-handling-personality-function 
> 
> https://stackoverflow.com/questions/20027156/llvm-exception-handling-implementation 
> 
> 
> Zob. tez:
> https://mentorembedded.github.io/cxx-abi/exceptions.pdf
> https://github.com/MentorEmbedded/cxx-abi/blob/master/MIPSCompactEH.pdf

Dzięki Matt. Jeśli chodzi o SEH, mają tę zaletę że również wyłapują 
sprzętowe błędy, nie tylko dzielenie przez zero, ale zapis pod zły 
adres, zamiast tylko działać na wyjątkach generowanych przez throw. Wada 
- wymagane wspomaganie systemu, brak przenośności.
Thread Navigation

This is a paginated view of messages in the thread with full content displayed inline.

Messages are displayed in chronological order, with the original post highlighted in green.

Use pagination controls to navigate through all messages in large threads.

Back to All Threads