The ELF loader now uses program headers and not section headers.

This commit is contained in:
Jonas 'Sortie' Termansen 2011-08-23 17:46:13 +02:00
parent b705bf27a1
commit 4898343e2f
2 changed files with 51 additions and 56 deletions

View File

@ -26,8 +26,9 @@
#include <libmaxsi/memory.h> #include <libmaxsi/memory.h>
#include "elf.h" #include "elf.h"
#include "memorymanagement.h" #include "memorymanagement.h"
#include "panic.h"
#include "log.h" // DEBUG using namespace Maxsi;
namespace Sortix namespace Sortix
{ {
@ -44,69 +45,41 @@ namespace Sortix
addr_t entry = header->entry; addr_t entry = header->entry;
// Find the location of the first section header. // Find the location of the program headers.
addr_t shtbloffset = header->sectionheaderoffset; addr_t phtbloffset = header->programheaderoffset;
addr_t shtblpos = ((addr_t) file) + shtbloffset; if ( filelen < phtbloffset ) { return 0; }
size_t shsize = header->sectionheaderentrysize; addr_t phtblpos = ((addr_t) file) + phtbloffset;
size_t phsize = header->programheaderentrysize;
const ProgramHeader32* phtbl = (const ProgramHeader32*) phtblpos;
// Validate that all sections are present. // Validate that all program headers are present.
uint16_t numsections = header->numsectionheaderentries; uint16_t numprogheaders = header->numprogramheaderentries;
size_t neededfilelen = shtbloffset + numsections * shsize; size_t neededfilelen = phtbloffset + numprogheaders * phsize;
if ( filelen < neededfilelen ) { return 0; } if ( filelen < neededfilelen ) { return 0; }
addr_t memlower = SIZE_MAX; // Create all the segments in the final process.
addr_t memupper = 0; // TODO: Handle errors on bad/malicious input or out-of-mem!
for ( uint16_t i = 0; i < numprogheaders; i++ )
// Valid all the data we need is in the file.
for ( uint16_t i = 0; i < numsections; i++ )
{ {
addr_t shoffset = i * shsize; const ProgramHeader32* pht = &(phtbl[i]);
addr_t shpos = shtblpos + shoffset; if ( pht->type != PT_LOAD ) { continue; }
const SectionHeader32* sh = (const SectionHeader32*) shpos; addr_t virtualaddr = pht->virtualaddr;
if ( sh->addr == 0 ) { continue; } addr_t mapto = Page::AlignDown(virtualaddr);
if ( sh->type == SHT_PROGBITS ) addr_t mapbytes = virtualaddr - mapto + pht->memorysize;
{ ASSERT(pht->offset % pht->align == virtualaddr % pht->align);
size_t sectionendsat = sh->offset + sh->size; ASSERT(pht->offset + pht->filesize < filelen);
if ( filelen < sectionendsat ) { return 0; } ASSERT(pht->filesize <= pht->memorysize);
}
if ( sh->type == SHT_PROGBITS || sh->type == SHT_NOBITS )
{
if ( sh->addr < memlower ) { memlower = sh->addr; }
if ( memupper < sh->addr + sh->size ) { memupper = sh->addr + sh->size; }
}
}
if ( memupper < memlower ) { return entry; } if ( !VirtualMemory::MapRangeUser(mapto, mapbytes) )
// HACK: For now just put it in the same continious block. This is
// very wasteful and not very intelligent.
addr_t mapto = Page::AlignDown(memlower);
addr_t mapbytes = memupper - mapto;
// TODO: Validate that we actually may map here!
if ( !VirtualMemory::MapRangeUser(mapto, mapbytes) )
{
return 0;
}
// Create all the sections in the final process.
for ( uint16_t i = 0; i < numsections; i++ )
{
addr_t shoffset = i * shsize;
addr_t shpos = shtblpos + shoffset;
const SectionHeader32* sh = (const SectionHeader32*) shpos;
if ( sh->type != SHT_PROGBITS && sh->type != SHT_NOBITS )
{ {
continue; PanicF("Could not user-map at %p and %zu bytes onwards", mapto, mapbytes);
} }
if ( sh->addr == 0 ) { continue; } // Copy as much data as possible and memset the rest to 0.
byte* memdest = (byte*) virtualaddr;
if ( sh->type == SHT_PROGBITS ) byte* memsource = (byte*) ( (addr_t)file + pht->offset);
{ Memory::Copy(memdest, memsource, pht->filesize);
void* memdest = (void*) sh->addr; Memory::Set(memdest + pht->filesize, 0, pht->memorysize - pht->filesize);
void* memsource = (void*) ( ((addr_t) file) + sh->offset );
Maxsi::Memory::Copy(memdest, memsource, sh->size);
}
} }
// MEMORY LEAK: There is no system in place to delete the sections // MEMORY LEAK: There is no system in place to delete the sections

View File

@ -93,6 +93,28 @@ namespace Sortix
const uint32_t SHT_LOUSER = 0x80000000; const uint32_t SHT_LOUSER = 0x80000000;
const uint32_t SHT_HIUSER = 0xffffffff; const uint32_t SHT_HIUSER = 0xffffffff;
struct ProgramHeader32
{
uint32_t type;
uint32_t offset;
uint32_t virtualaddr;
uint32_t physicaladdr;
uint32_t filesize;
uint32_t memorysize;
uint32_t flags;
uint32_t align;
};
const uint32_t PT_NULL = 0;
const uint32_t PT_LOAD = 1;
const uint32_t PT_DYNAMIC = 2;
const uint32_t PT_INTERP = 3;
const uint32_t PT_NOTE = 4;
const uint32_t PT_SHLIB = 5;
const uint32_t PT_PHDR = 6;
const uint32_t PT_LOPROC = 0x70000000;
const uint32_t PT_HIPROC = 0x7FFFFFFF;
// Reads the elf file into the current address space and returns the // Reads the elf file into the current address space and returns the
// entry address of the program, or 0 upon failure. // entry address of the program, or 0 upon failure.
addr_t Construct(const void* file, size_t filelen); addr_t Construct(const void* file, size_t filelen);