Modifications made to
loader.cfrom Assignment 1
find_segment()loader_cleanup()my_handler()load_and_run_elf()
my_handler()load_and_run_elf()
Both members contributed to:
- Error handling
- Bug fixing
-
The codebase is well documented using:
- Comments
- Appropriate variable names
- Meaningful function names
The loader:
-
Reads the ELF file using:
- File descriptors
lseek()read()
-
Stores:
- ELF Header (
EHDR) - Program Header Table (
PHDR) entries
- ELF Header (
for later use.
Instead of:
- Allocating memory beforehand
- Copying all segment data immediately
the loader directly:
- Typecasts
e_entryfrom the ELF header into the_start()function. - Calls
_start()directly.
When _start() begins execution:
- The program attempts to access virtual memory addresses that are not yet mapped.
- This causes a page fault.
- The operating system raises:
SIGSEGVThe signal handler:
- Receives the
SIGSEGVsignal. - Uses:
siginfo_t* infoto retrieve the faulty memory address.
The loader iterates through the Program Header Table to:
- Find the segment containing the faulty address.
If no matching segment is found:
- The fault is treated as a genuine segmentation fault.
- The loader cannot handle it.
If the segment is found:
Using the phdr entries, the loader determines:
- Start of the segment
- End of the segment
- Start address of the page containing the faulting address
- Page fault count is incremented by 1.
The loader maps:
- One page (
4 KB) using:
mmap()The required segment data is copied into memory using:
lseek()read()
p_memsz > p_fileszThis indicates the presence of:
.bsssection- Uninitialized data
The extra memory region is zero-initialized using:
memset()Internal fragmentation is updated using:
(size of page - size of segment)
- A full 4 KB page is always allocated.
- Some segments may occupy less than one page.
- Total page allocations are incremented by 1 for every mapped page.
After handling the page fault:
-
Execution resumes from the
_start()function. -
The process continues:
- Until termination
- Or until another page fault occurs
Upon completion:
- The return value of
_start()is printed. - Required statistics are displayed.
- Cleanup functions are executed.
- Iterates through Program Header Table entries.
- Finds the segment containing the faulting virtual address.
- Used by the signal handler during page fault resolution.
Handles:
SIGSEGVpage faults
- Determine faulting address
- Identify corresponding ELF segment
- Allocate and map required page
- Copy segment data into memory
- Resume execution
- Frees allocated resources.
- Closes file descriptors.
- Cleans up loader state before termination.
Program starts
↓
Read ELF headers
↓
Call _start() directly
↓
Page fault occurs (SIGSEGV)
↓
Signal handler invoked
↓
Find corresponding segment
↓
Map required page using mmap()
↓
Load page contents from ELF file
↓
Resume execution
↓
Repeat on future page faults
↓
Program terminates
open()read()lseek()mmap()memset()signal()sigaction()
- Lazy loading of ELF segments
- Demand paging simulation
- Page fault handling using signals
- Dynamic page allocation
- Internal fragmentation tracking
- Page allocation statistics
- Efficient memory usage
-
Unlike Assignment 1, segments are not preloaded entirely into memory.
-
Pages are loaded only when accessed.
-
The implementation mimics:
- Demand paging
- Lazy loading mechanisms used in modern operating systems.
-
SIGSEGVis intentionally used as a mechanism for page fault handling. -
Memory allocation occurs page-by-page instead of segment-by-segment