Tema 4 Rustyloader
Date limite:
Le 30 mai, 23h59
Note:
2 points de la note
Lien:
Devoir 4
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 afisa pe stderr (2) lista de segmente ale fisierului executabil
Va afisa pe stderr (2) base address pentru fisierul executabil (adresa de memorie minima la care se incarca segmente)
Va afisa pe stderr (2) entry point address
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.
Segments
# address size offset length flags
0 0x8048000 1012 0x0 1012 r-x
1 0x804a000 8192 0x1000 8192 rw-
Entry point 8048120
Base address 8048000
Alinierea campurilor se face cu TAB (\t). Daca alinierea nu este buna, adaugati doua caratere TAB.
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