This is an old revision of the document!
Tema 3 Rusty Loader
Date limite:
Le 10 mai, 23h59
Note:
2 points de la note
Lien:
Devoir 3
Télécharger en retard:
2 points / jour (maximum 4 jours)
Obiectivele temei
Recomandări
Enunț
Să se implementeze un loader de fișiere executabile în format ELF pentru Linux. Loader-ul va încărca fișierul executabil în memorie pagină cu pagină, folosind un mecanism de tipul demand paging - o pagină va fi încărcată doar în momentul în care este nevoie de ea. Pentru simplitate, loader-ul va rula doar executabile statice - care nu sunt link-ate cu biblioteci partajate/dinamice.
Pentru a rula un fișier executabil, loader-ul va executa următorii pași:
Își va inițializa structurile interne.
Va parsa fișierul binar - pentru a face asta aveți la dispozitie biblioteca
object.
Va rula prima instrucțiune a executabilului (entry point-ul).
Va detecta fiecare acces la o pagină nemapată, și va verifica din ce segment al executabilului face parte.
dacă nu se găsește într-un segment, înseamnă că este un acces invalid la memorie – programul iese cu eroarea -200;
dacă page fault-ul este generat într-o pagină deja mapată, atunci se încearcă un acces la memorie nepermis (segmentul respectiv nu are permisiunile necesare) – la fel, programul iese cu eroarea -200;
dacă pagina se găsește într-un segment, și ea încă nu a fost încă mapată, atunci se mapează la adresa aferentă, cu permisiunile acelui segment;
Veți folosi funcțiile
mmap (varianta
rust.
Pagina trebuie mapată fix la adresa indicată în cadrul segmentului.
Biblioteca object
Biblioteca object va pune la dispozitie un parser pentru fisiere binare (ELF in Linux). Aveti nevoie de lista de segmente (File).
În imaginea de mai jos aveți o reprezentare grafică a unui segment.
Precizări/recomandări pentru implementare
-
Pentru a implementa logica de demand paging trebuie să interceptați page fault-urile produse în momentul unui acces nevalid la o zonă de memorie. La interceptarea page fault-urilor, tratați-o corespunzător, în funcție de segmentul din care face parte:
dacă nu este într-un segment cunoscut, rulați handler-ul default;
dacă este într-o pagină ne-mapată, mapați-o în memorie, apoi copiați din segmentul din fișier datele;
dacă este într-o pagină deja mapată, rulați handler-ul default (întrucât este un acces ne-permis la memorie);
Paginile din două segmente diferite nu se pot suprapune.
Dimensiunea unui segment nu este aliniată la nivel de pagină; memoria care nu face parte dintr-un segment nu trebuie tratată în niciun fel – comportamentul unui acces în cadrul acelei zone este nedefinit.
Precizări
-
Pentru interceptarea accesului nevalid la o zonă de memorie va trebui să interceptați semnalul
SIGSEGV
folosind apeluri din familia
sigaction.
În momentul în care este accesată o pagină nouă din cadrul unui segment, mapați pagina în care s-a generat page fault-ul, folosind MAP_FIXED
, apoi copiați în pagină datele din executabil
Resurse de suport