Concetti Chiave
- Durante una chiamata a funzione, il caller posiziona argomenti e indirizzo di ritorno sullo stack, e il callee salva variabili locali e registri.
- Il callee esegue le istruzioni e, al termine, restituisce il controllo al caller ripristinando lo stato dei registri e liberando lo stack.
- Gli argomenti sono passati da destra a sinistra, facilitando la gestione delle funzioni variadiche con il primo argomento in cima allo stack.
- Il caller gestisce il ripristino dello stack, aumentando la dimensione dell'eseguibile, ma consentendo la gestione di funzioni variadiche.
- Problemi comuni includono stack overflow e stack buffer overflow, quest'ultimo sfruttabile per attacchi informatici mediante sovrascrittura di indirizzi di ritorno.
Gestione dello stack
Quando avviene una chiamata a funzione accade:
- il caller posiziona gli argomenti da passare alla funzione chiamata calee sullo stack o in determinati registri della CPU
- il caller salva l’indirizzo di ritorno sullo stack
- il caller passa il controllo al callee
- il callee salva le variabili locali sullo stack
- il callee salva il contenuto di alcuni registri nello stack, da ripristinare al termine della chiamata
- il callee esegue le istruzioni
Al termine dell’esecuzione:
- il callee posiziona il valore di ritorno nei registri del processore o altri spazi di memoria
- il callee ripristina lo stato dei registri salvati sullo stack
- gli argomenti vengono rimossi dallo stack e viene aggiornato lo stack pointer
- il controllo passa al caller
Gli argomenti sono passati da destra a sinistra:
- perciò il primo argomento è in cima allo stack
- permette di gestire le funzioni variadiche
Il caller ripristina lo stack dopo la chiamata:
- la dimensione dell’eseguibile aumenta, dato che il ripristino dello stack avviene per ogni chiamata a funzione
- si possono gestire le chiamate a funzioni variadiche, per questo tipo di funzioni solo il caller e a conoscenza del numero di argomenti da passare mentre il callee potrebbe non esserlo
Problemi nella gestione dello stack:
- stack overflow: la dimensione della memoria condivisa da heap e stack e fissata al momento dell’avvio del programma, se viene richiesta troppa memoria nello stack, c’e uno stack overflow, che solitamente causa il crash di u programma (es. funzioni ricorsive profonde, variabili ingombranti)
- Stack buffer overflow: il programma scrive dati sul record di attivazione al di fuori dello spazio riservato ad essi. Succede solitamente per distrazioni del programmatore e dall’uso delle funzioni di libreria che non eseguono i controlli di sicurezza sulle dimensioni dei dati, queste falle vengono sfruttare per attacchi informatici (vengono sovrascritti indirizzi di ritorno nel record di attivazione per
eseguire il codice malevolo).
Domande da interrogazione
- Come vengono gestiti gli argomenti e il controllo durante una chiamata a funzione?
- Quali sono i problemi comuni nella gestione dello stack?
- Perché la gestione dello stack è importante per le funzioni variadiche?
Gli argomenti vengono posizionati sullo stack o in registri specifici, l'indirizzo di ritorno viene salvato sullo stack, e il controllo passa dal caller al callee, che salva le variabili locali e i registri necessari.
I problemi comuni includono lo stack overflow, causato da richieste eccessive di memoria, e lo stack buffer overflow, che avviene quando i dati vengono scritti oltre lo spazio riservato, spesso sfruttato per attacchi informatici.
La gestione dello stack è cruciale per le funzioni variadiche perché solo il caller conosce il numero di argomenti da passare, mentre il callee potrebbe non saperlo, richiedendo un ripristino accurato dello stack dopo la chiamata.