Table of Contents

Loader de Executabile

  • Deadline: 24.11.2022, ora 23:55

Obiectivele temei

Recomandări

Enunț

Să se implementeze sub forma unei biblioteci partajate/dinamice 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:

Interfața bibliotecii

Interfața de utilizare a bibliotecii loader-ului este prezentată în cadrul fișierul header loader.h. Acesta conține funcții de inițializare a loaderului(so_init_loader) și de executare a binarului (so_execute).

loader.h
/* initializes the loader */
int so_init_loader(void);
 
/* runs an executable specified in the path */
int so_execute(char *path, char *argv[]);

Interfața parser

Pentru a ușura realizarea temei, vă punem la dispoziție în scheletul de cod un parser pentru ELF (Linux).

exec_parser.h
typedef struct so_seg {
    /* virtual address */
    uintptr_t vaddr;
    /* size inside the executable file */
    unsigned int file_size;
    /* size in memory (can be larger than file_size) */
    unsigned int mem_size;
    /* offset in file */
    unsigned int offset;
    /* permissions */
    unsigned int perm;
    /* custom data */
    void *data;
} so_seg_t;
 
typedef struct so_exec {
    /* base adress */
    uintptr_t base_addr;
    /* address of entry point */
    uintptr_t entry;
    /* number of segments */
    int segments_no;
    /* array of segments */
    so_seg_t *segments;
} so_exec_t;
 
/* parse an executable file */
so_exec_t *so_parse_exec(char *path);
 
/*
 * start an executable file, previously parsed in a so_exec_t structure
 * (jumps to the executable's entry point)
 */
void so_start_exec(so_exec_t *exec, char *argv[]);

Interfața de parser pune la dispoziție două funcții:

Structurile folosit de interfață sunt:

În imaginea de mai jos aveți o reprezentare grafică a unui segment.

Precizări/recomandări pentru implementare

Precizări

#include <signal.h>
...
 
/* SIGUSR2 handler */
static void usr2_handler(int signum) {
    /* actions that should be taken when the signal signum is received */
    ...
}
 
int main(void) {
    struct sigaction sa;
 
    memset(&sa, 0, sizeof(sa));
 
    sa.sa_flags   = SA_RESETHAND;   /* restore handler to previous state */
    sa.sa_handler = usr2_handler;
    sigaction(SIGSEGV, &sa, NULL);
 
    return 0;
}

Testare

Înainte de a uploada tema, asigurați-vă că implementarea voastră trece testele pe mașina virtuală de linux. Dacă apar probleme în rezultatele testelor, acestea se vor reproduce și pe vmchecker sau pe orice alt mediu de testare solicitat.

Depunctări

Resurse de suport

FAQ

Suport, întrebări și clarificări

Pentru întrebări sau nelămuriri legate de temă folosiți forumul temei.

Orice intrebare pe forum trebuie să conțină o descriere cât mai clară a eventualei probleme. Întrebări de forma: “Nu merge X. De ce?” fără o descriere mai amănunțită vor primi un răspuns mai greu. Înainte să postați o întrebare pe forum citiți și celelalte întrebări(dacă există) pentru a vedea dacă întrebarea voastră a fost deja adresată sub o altă formă(în cazul în care răspunsul din partea echipei vine mai greu este mai rapid să căutați voi deja printre întrebările existente).

ATENȚIE să nu postați imagini cu părți din soluția voastră pe forumul pus la dispoziție sau orice alt canal public de comunicație. Dacă veți face acest lucru, vă asumați răspunderea dacă veți primi copiat pe temă.