A smart ELF loader written in C that loads and executes ELF binaries using demand paging — memory for a program's segments is allocated lazily, only when the program actually accesses it, rather than all upfront. This mirrors how real operating systems handle program loading efficiently.
Built as part of my Operating Systems coursework, extending a basic ELF loader to handle page faults and on-demand memory allocation.
A basic loader copies all segments into memory before running the program. This smart loader instead:
- Loads lazily — segments are not pre-loaded into memory
- Catches page faults — when the program accesses an unmapped address, a
SIGSEGVhandler triggers - Allocates on demand — the handler maps in exactly the page(s) needed at that moment
- Resumes execution — the program continues as if the memory was always there
- Reports statistics — tracks total page faults and allocated pages to show the efficiency gain
- Language: C
- Core OS concepts: demand paging, page faults, signal handling, virtual memory, ELF format
- System calls:
mmap,mprotect, signal handling (SIGSEGVviasigaction) - Build: Makefile-based
- GCC and
make - A Linux/Unix environment
# Clone the repository
git clone https://github.com/Goyamjain06/OS_projectttt.git
cd OS_projectttt
# Build using the Makefile
make
# Run the smart loader on a sample ELF binary
./simplesmartloader sum.elfThe loader executes the binary and reports page-fault statistics (number of page faults, pages allocated, internal fragmentation).
.
├── loader.c # Core smart loader: ELF parsing + page-fault handler
├── loader.h # Loader interface and data structures
├── simplesmartloader # Compiled loader executable
├── fib.c / sum.c # Sample programs (source)
├── sum.elf / sum.o # Compiled test binaries
└── Makefile # Build configuration
When the loader starts a program, it does not copy the segments into memory. Instead it registers a SIGSEGV signal handler. As soon as the program tries to access an address that isn't mapped yet, the CPU raises a page fault, the handler runs, and it uses mmap to map in just the page containing that address — loading the corresponding chunk of the ELF segment. Control then returns to the faulting instruction, which now succeeds. Over the run, the loader counts how many page faults occurred and how much memory was actually needed.
- How demand paging saves memory by loading pages only when accessed
- Writing a
SIGSEGVhandler to intercept and resolve page faults - Using
mmapfor fine-grained, page-aligned memory allocation - The trade-off between page-fault overhead and memory efficiency
- [Add your own line — e.g. debugging alignment issues, measuring fragmentation]
- Support for multiple loadable segments with different permissions
- Page eviction / replacement policy
- Detailed per-segment fault statistics