This is an old revision of the document!
Tema 3 Rusty Loader
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.
mem_length este reprezentata de campul
size
</note>
===== Precizări/recomandări pentru implementare =====
* Implementarea page fault
handler-ului se realizează prin intermediul unei rutine pentru tratarea semnalului SIGSEGV.
* 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 gestiunea memoriei virtuale folosiți funcțiile mmap, munmap și mprotect.
* Pentru interceptarea accesului nevalid la o zonă de memorie va trebui să interceptați semnalul SIGSEGV
folosind apeluri din familia sigaction.
* Veți înregistra un handler în câmpul sa_sigaction
al structurii struct sigaction
.
* Pentru a determina adresa care a generat page fault-ul folosiți câmpul si_addr
din cadrul structurii siginfo_t
.
* Î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 =====
*Cursuri
* Curs 5 - Gestiunea memoriei
* Curs 6 - Memoria virtuală
* Curs 7 - Securitatea memoriei
*Laboratoare
* Laborator 4 - Semnale
* Laborator 5 - Gestiunea memoriei
* Laborator 6 - Memoria virtuală
*Operating System Concepts – Chapter 8 – Main Memory
*Operating System Concepts – Chapter 9 – Virtual Memory
* Formatul fișierelor executabile pe Linux (ELF)