Update sortix/elf.cpp to current coding conventions.
This commit is contained in:
parent
2525de507c
commit
b84d9d26d0
458
sortix/elf.cpp
458
sortix/elf.cpp
|
@ -1,6 +1,6 @@
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
|
|
||||||
Copyright(C) Jonas 'Sortie' Termansen 2011.
|
Copyright(C) Jonas 'Sortie' Termansen 2011, 2012, 2013.
|
||||||
|
|
||||||
This file is part of Sortix.
|
This file is part of Sortix.
|
||||||
|
|
||||||
|
@ -22,232 +22,248 @@
|
||||||
|
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
|
|
||||||
#include <sortix/kernel/platform.h>
|
#include <sys/types.h>
|
||||||
#include <sortix/mman.h>
|
|
||||||
#include <sortix/kernel/process.h>
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdint.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include "elf.h"
|
|
||||||
|
#include <sortix/mman.h>
|
||||||
|
|
||||||
|
#include <sortix/kernel/platform.h>
|
||||||
#include <sortix/kernel/memorymanagement.h>
|
#include <sortix/kernel/memorymanagement.h>
|
||||||
#include <sortix/kernel/panic.h>
|
#include <sortix/kernel/process.h>
|
||||||
|
|
||||||
namespace Sortix
|
#include "elf.h"
|
||||||
|
|
||||||
|
namespace Sortix {
|
||||||
|
namespace ELF {
|
||||||
|
|
||||||
|
static int ToProgramSectionType(int flags)
|
||||||
{
|
{
|
||||||
namespace ELF
|
switch ( flags & (PF_X | PF_R | PF_W) )
|
||||||
{
|
{
|
||||||
int ToProgramSectionType(int flags)
|
case 0:
|
||||||
{
|
return SEG_NONE;
|
||||||
switch ( flags & (PF_X | PF_R | PF_W) )
|
case PF_X:
|
||||||
{
|
case PF_X | PF_R:
|
||||||
case 0:
|
case PF_X | PF_W:
|
||||||
return SEG_NONE;
|
case PF_X | PF_R | PF_W:
|
||||||
case PF_X:
|
return SEG_TEXT;
|
||||||
case PF_X | PF_R:
|
case PF_R:
|
||||||
case PF_X | PF_W:
|
case PF_W:
|
||||||
case PF_X | PF_R | PF_W:
|
case PF_R | PF_W:
|
||||||
return SEG_TEXT;
|
default:
|
||||||
case PF_R:
|
return SEG_DATA;
|
||||||
case PF_W:
|
|
||||||
case PF_R | PF_W:
|
|
||||||
default:
|
|
||||||
return SEG_DATA;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
addr_t Construct32(Process* process, const void* file, size_t filelen)
|
|
||||||
{
|
|
||||||
if ( filelen < sizeof(Header32) ) { return 0; }
|
|
||||||
const Header32* header = (const Header32*) file;
|
|
||||||
|
|
||||||
// Check for little endian.
|
|
||||||
if ( header->dataencoding != DATA2LSB ) { return 0; }
|
|
||||||
if ( header->version != CURRENTVERSION ) { return 0; }
|
|
||||||
|
|
||||||
addr_t entry = header->entry;
|
|
||||||
|
|
||||||
// Find the location of the program headers.
|
|
||||||
addr_t phtbloffset = header->programheaderoffset;
|
|
||||||
if ( filelen < phtbloffset ) { return 0; }
|
|
||||||
addr_t phtblpos = ((addr_t) file) + phtbloffset;
|
|
||||||
size_t phsize = header->programheaderentrysize;
|
|
||||||
const ProgramHeader32* phtbl = (const ProgramHeader32*) phtblpos;
|
|
||||||
|
|
||||||
// Validate that all program headers are present.
|
|
||||||
uint16_t numprogheaders = header->numprogramheaderentries;
|
|
||||||
size_t neededfilelen = phtbloffset + numprogheaders * phsize;
|
|
||||||
if ( filelen < neededfilelen ) { return 0; }
|
|
||||||
|
|
||||||
// Prepare the process for execution (clean up address space, etc.)
|
|
||||||
process->ResetForExecute();
|
|
||||||
|
|
||||||
// Flush the TLB such that no stale information from the last
|
|
||||||
// address space is used when creating the new one.
|
|
||||||
Memory::Flush();
|
|
||||||
|
|
||||||
// Create all the segments in the final process.
|
|
||||||
// TODO: Handle errors on bad/malicious input or out-of-mem!
|
|
||||||
for ( uint16_t i = 0; i < numprogheaders; i++ )
|
|
||||||
{
|
|
||||||
const ProgramHeader32* pht = &(phtbl[i]);
|
|
||||||
if ( pht->type != PT_LOAD ) { continue; }
|
|
||||||
addr_t virtualaddr = pht->virtualaddr;
|
|
||||||
addr_t mapto = Page::AlignDown(virtualaddr);
|
|
||||||
addr_t mapbytes = virtualaddr - mapto + pht->memorysize;
|
|
||||||
assert(pht->offset % pht->align == virtualaddr % pht->align);
|
|
||||||
assert(pht->offset + pht->filesize < filelen);
|
|
||||||
assert(pht->filesize <= pht->memorysize);
|
|
||||||
|
|
||||||
ProcessSegment* segment = new ProcessSegment;
|
|
||||||
if ( segment == NULL ) { return 0; }
|
|
||||||
segment->position = mapto;
|
|
||||||
segment->size = Page::AlignUp(mapbytes);
|
|
||||||
segment->type = ToProgramSectionType(pht->flags);
|
|
||||||
|
|
||||||
int prot = PROT_FORK | PROT_KREAD | PROT_KWRITE;
|
|
||||||
if ( pht->flags & PF_X ) { prot |= PROT_EXEC; }
|
|
||||||
if ( pht->flags & PF_R ) { prot |= PROT_READ; }
|
|
||||||
if ( pht->flags & PF_W ) { prot |= PROT_WRITE; }
|
|
||||||
|
|
||||||
if ( segment->Intersects(process->segments) )
|
|
||||||
{
|
|
||||||
delete segment;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( !Memory::MapRange(mapto, mapbytes, prot))
|
|
||||||
{
|
|
||||||
// TODO: Memory leak of segment?
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Insert our newly allocated memory into the processes segment
|
|
||||||
// list such that it can be reclaimed later.
|
|
||||||
if ( process->segments ) { process->segments->prev = segment; }
|
|
||||||
segment->next = process->segments;
|
|
||||||
process->segments = segment;
|
|
||||||
|
|
||||||
// Copy as much data as possible and memset the rest to 0.
|
|
||||||
uint8_t* memdest = (uint8_t*) virtualaddr;
|
|
||||||
uint8_t* memsource = (uint8_t*) ( ((addr_t)file) + pht->offset);
|
|
||||||
memcpy(memdest, memsource, pht->filesize);
|
|
||||||
memset(memdest + pht->filesize, 0, pht->memorysize - pht->filesize);
|
|
||||||
}
|
|
||||||
|
|
||||||
return entry;
|
|
||||||
}
|
|
||||||
|
|
||||||
addr_t Construct64(Process* process, const void* file, size_t filelen)
|
|
||||||
{
|
|
||||||
#ifndef PLATFORM_X64
|
|
||||||
(void) process;
|
|
||||||
(void) file;
|
|
||||||
(void) filelen;
|
|
||||||
errno = ENOEXEC;
|
|
||||||
return 0;
|
|
||||||
#else
|
|
||||||
if ( filelen < sizeof(Header64) ) { return 0; }
|
|
||||||
const Header64* header = (const Header64*) file;
|
|
||||||
|
|
||||||
// Check for little endian.
|
|
||||||
if ( header->dataencoding != DATA2LSB ) { return 0; }
|
|
||||||
if ( header->version != CURRENTVERSION ) { return 0; }
|
|
||||||
|
|
||||||
addr_t entry = header->entry;
|
|
||||||
|
|
||||||
// Find the location of the program headers.
|
|
||||||
addr_t phtbloffset = header->programheaderoffset;
|
|
||||||
if ( filelen < phtbloffset ) { return 0; }
|
|
||||||
addr_t phtblpos = ((addr_t) file) + phtbloffset;
|
|
||||||
size_t phsize = header->programheaderentrysize;
|
|
||||||
const ProgramHeader64* phtbl = (const ProgramHeader64*) phtblpos;
|
|
||||||
|
|
||||||
// Validate that all program headers are present.
|
|
||||||
uint16_t numprogheaders = header->numprogramheaderentries;
|
|
||||||
size_t neededfilelen = phtbloffset + numprogheaders * phsize;
|
|
||||||
if ( filelen < neededfilelen ) { return 0; }
|
|
||||||
|
|
||||||
// Prepare the process for execution (clean up address space, etc.)
|
|
||||||
process->ResetForExecute();
|
|
||||||
|
|
||||||
// Flush the TLB such that no stale information from the last
|
|
||||||
// address space is used when creating the new one.
|
|
||||||
Memory::Flush();
|
|
||||||
|
|
||||||
// Create all the segments in the final process.
|
|
||||||
// TODO: Handle errors on bad/malicious input or out-of-mem!
|
|
||||||
for ( uint16_t i = 0; i < numprogheaders; i++ )
|
|
||||||
{
|
|
||||||
const ProgramHeader64* pht = &(phtbl[i]);
|
|
||||||
if ( pht->type != PT_LOAD ) { continue; }
|
|
||||||
addr_t virtualaddr = pht->virtualaddr;
|
|
||||||
addr_t mapto = Page::AlignDown(virtualaddr);
|
|
||||||
addr_t mapbytes = virtualaddr - mapto + pht->memorysize;
|
|
||||||
assert(pht->offset % pht->align == virtualaddr % pht->align);
|
|
||||||
assert(pht->offset + pht->filesize < filelen);
|
|
||||||
assert(pht->filesize <= pht->memorysize);
|
|
||||||
|
|
||||||
ProcessSegment* segment = new ProcessSegment;
|
|
||||||
if ( segment == NULL ) { return 0; }
|
|
||||||
segment->position = mapto;
|
|
||||||
segment->size = Page::AlignUp(mapbytes);
|
|
||||||
segment->type = ToProgramSectionType(pht->flags);
|
|
||||||
|
|
||||||
int prot = PROT_FORK | PROT_KREAD | PROT_KWRITE;
|
|
||||||
if ( pht->flags & PF_X ) { prot |= PROT_EXEC; }
|
|
||||||
if ( pht->flags & PF_R ) { prot |= PROT_READ; }
|
|
||||||
if ( pht->flags & PF_W ) { prot |= PROT_WRITE; }
|
|
||||||
|
|
||||||
if ( segment->Intersects(process->segments) )
|
|
||||||
{
|
|
||||||
delete segment;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( !Memory::MapRange(mapto, mapbytes, prot))
|
|
||||||
{
|
|
||||||
// TODO: Memory leak of segment?
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Insert our newly allocated memory into the processes segment
|
|
||||||
// list such that it can be reclaimed later.
|
|
||||||
if ( process->segments ) { process->segments->prev = segment; }
|
|
||||||
segment->next = process->segments;
|
|
||||||
process->segments = segment;
|
|
||||||
|
|
||||||
// Copy as much data as possible and memset the rest to 0.
|
|
||||||
uint8_t* memdest = (uint8_t*) virtualaddr;
|
|
||||||
uint8_t* memsource = (uint8_t*) ( ((addr_t)file) + pht->offset);
|
|
||||||
memcpy(memdest, memsource, pht->filesize);
|
|
||||||
memset(memdest + pht->filesize, 0, pht->memorysize - pht->filesize);
|
|
||||||
}
|
|
||||||
|
|
||||||
return entry;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
addr_t Construct(Process* process, const void* file, size_t filelen)
|
|
||||||
{
|
|
||||||
if ( filelen < sizeof(Header) ) { errno = ENOEXEC; return 0; }
|
|
||||||
const Header* header = (const Header*) file;
|
|
||||||
|
|
||||||
if ( !(header->magic[0] == 0x7F && header->magic[1] == 'E' &&
|
|
||||||
header->magic[2] == 'L' && header->magic[3] == 'F' ) )
|
|
||||||
{
|
|
||||||
errno = ENOEXEC;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch ( header->fileclass )
|
|
||||||
{
|
|
||||||
case CLASS32:
|
|
||||||
return Construct32(process, file, filelen);
|
|
||||||
case CLASS64:
|
|
||||||
return Construct64(process, file, filelen);
|
|
||||||
default:
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
addr_t Construct32(Process* process, const void* file, size_t filelen)
|
||||||
|
{
|
||||||
|
if ( filelen < sizeof(Header32) )
|
||||||
|
return 0;
|
||||||
|
const Header32* header = (const Header32*) file;
|
||||||
|
|
||||||
|
// Check for little endian.
|
||||||
|
if ( header->dataencoding != DATA2LSB )
|
||||||
|
return 0;
|
||||||
|
if ( header->version != CURRENTVERSION )
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
addr_t entry = header->entry;
|
||||||
|
|
||||||
|
// Find the location of the program headers.
|
||||||
|
addr_t phtbloffset = header->programheaderoffset;
|
||||||
|
if ( filelen < phtbloffset )
|
||||||
|
return 0;
|
||||||
|
addr_t phtblpos = ((addr_t) file) + phtbloffset;
|
||||||
|
size_t phsize = header->programheaderentrysize;
|
||||||
|
const ProgramHeader32* phtbl = (const ProgramHeader32*) phtblpos;
|
||||||
|
|
||||||
|
// Validate that all program headers are present.
|
||||||
|
uint16_t numprogheaders = header->numprogramheaderentries;
|
||||||
|
size_t neededfilelen = phtbloffset + numprogheaders * phsize;
|
||||||
|
if ( filelen < neededfilelen )
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
// Prepare the process for execution (clean up address space, etc.)
|
||||||
|
process->ResetForExecute();
|
||||||
|
|
||||||
|
// Flush the TLB such that no stale information from the last
|
||||||
|
// address space is used when creating the new one.
|
||||||
|
Memory::Flush();
|
||||||
|
|
||||||
|
// Create all the segments in the final process.
|
||||||
|
// TODO: Handle errors on bad/malicious input or out-of-mem!
|
||||||
|
for ( uint16_t i = 0; i < numprogheaders; i++ )
|
||||||
|
{
|
||||||
|
const ProgramHeader32* pht = &(phtbl[i]);
|
||||||
|
if ( pht->type != PT_LOAD )
|
||||||
|
continue;
|
||||||
|
addr_t virtualaddr = pht->virtualaddr;
|
||||||
|
addr_t mapto = Page::AlignDown(virtualaddr);
|
||||||
|
addr_t mapbytes = virtualaddr - mapto + pht->memorysize;
|
||||||
|
assert(pht->offset % pht->align == virtualaddr % pht->align);
|
||||||
|
assert(pht->offset + pht->filesize < filelen);
|
||||||
|
assert(pht->filesize <= pht->memorysize);
|
||||||
|
|
||||||
|
ProcessSegment* segment = new ProcessSegment;
|
||||||
|
if ( segment == NULL )
|
||||||
|
return 0;
|
||||||
|
segment->position = mapto;
|
||||||
|
segment->size = Page::AlignUp(mapbytes);
|
||||||
|
segment->type = ToProgramSectionType(pht->flags);
|
||||||
|
|
||||||
|
int prot = PROT_FORK | PROT_KREAD | PROT_KWRITE;
|
||||||
|
if ( pht->flags & PF_X ) { prot |= PROT_EXEC; }
|
||||||
|
if ( pht->flags & PF_R ) { prot |= PROT_READ; }
|
||||||
|
if ( pht->flags & PF_W ) { prot |= PROT_WRITE; }
|
||||||
|
|
||||||
|
if ( segment->Intersects(process->segments) )
|
||||||
|
{
|
||||||
|
delete segment;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( !Memory::MapRange(mapto, mapbytes, prot) )
|
||||||
|
// TODO: Memory leak of segment?
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
// Insert our newly allocated memory into the processes segment
|
||||||
|
// list such that it can be reclaimed later.
|
||||||
|
if ( process->segments )
|
||||||
|
process->segments->prev = segment;
|
||||||
|
segment->next = process->segments;
|
||||||
|
process->segments = segment;
|
||||||
|
|
||||||
|
// Copy as much data as possible and memset the rest to 0.
|
||||||
|
uint8_t* memdest = (uint8_t*) virtualaddr;
|
||||||
|
uint8_t* memsource = (uint8_t*) (((addr_t)file) + pht->offset);
|
||||||
|
memcpy(memdest, memsource, pht->filesize);
|
||||||
|
memset(memdest + pht->filesize, 0, pht->memorysize - pht->filesize);
|
||||||
|
}
|
||||||
|
|
||||||
|
return entry;
|
||||||
|
}
|
||||||
|
|
||||||
|
addr_t Construct64(Process* process, const void* file, size_t filelen)
|
||||||
|
{
|
||||||
|
#ifndef PLATFORM_X64
|
||||||
|
(void) process;
|
||||||
|
(void) file;
|
||||||
|
(void) filelen;
|
||||||
|
return errno = ENOEXEC, 0;
|
||||||
|
#else
|
||||||
|
if ( filelen < sizeof(Header64) )
|
||||||
|
return 0;
|
||||||
|
const Header64* header = (const Header64*) file;
|
||||||
|
|
||||||
|
// Check for little endian.
|
||||||
|
if ( header->dataencoding != DATA2LSB )
|
||||||
|
return 0;
|
||||||
|
if ( header->version != CURRENTVERSION )
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
addr_t entry = header->entry;
|
||||||
|
|
||||||
|
// Find the location of the program headers.
|
||||||
|
addr_t phtbloffset = header->programheaderoffset;
|
||||||
|
if ( filelen < phtbloffset )
|
||||||
|
return 0;
|
||||||
|
addr_t phtblpos = ((addr_t) file) + phtbloffset;
|
||||||
|
size_t phsize = header->programheaderentrysize;
|
||||||
|
const ProgramHeader64* phtbl = (const ProgramHeader64*) phtblpos;
|
||||||
|
|
||||||
|
// Validate that all program headers are present.
|
||||||
|
uint16_t numprogheaders = header->numprogramheaderentries;
|
||||||
|
size_t neededfilelen = phtbloffset + numprogheaders * phsize;
|
||||||
|
if ( filelen < neededfilelen )
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
// Prepare the process for execution (clean up address space, etc.)
|
||||||
|
process->ResetForExecute();
|
||||||
|
|
||||||
|
// Flush the TLB such that no stale information from the last
|
||||||
|
// address space is used when creating the new one.
|
||||||
|
Memory::Flush();
|
||||||
|
|
||||||
|
// Create all the segments in the final process.
|
||||||
|
// TODO: Handle errors on bad/malicious input or out-of-mem!
|
||||||
|
for ( uint16_t i = 0; i < numprogheaders; i++ )
|
||||||
|
{
|
||||||
|
const ProgramHeader64* pht = &(phtbl[i]);
|
||||||
|
if ( pht->type != PT_LOAD )
|
||||||
|
continue;
|
||||||
|
addr_t virtualaddr = pht->virtualaddr;
|
||||||
|
addr_t mapto = Page::AlignDown(virtualaddr);
|
||||||
|
addr_t mapbytes = virtualaddr - mapto + pht->memorysize;
|
||||||
|
assert(pht->offset % pht->align == virtualaddr % pht->align);
|
||||||
|
assert(pht->offset + pht->filesize < filelen);
|
||||||
|
assert(pht->filesize <= pht->memorysize);
|
||||||
|
|
||||||
|
ProcessSegment* segment = new ProcessSegment;
|
||||||
|
if ( segment == NULL )
|
||||||
|
return 0;
|
||||||
|
segment->position = mapto;
|
||||||
|
segment->size = Page::AlignUp(mapbytes);
|
||||||
|
segment->type = ToProgramSectionType(pht->flags);
|
||||||
|
|
||||||
|
int prot = PROT_FORK | PROT_KREAD | PROT_KWRITE;
|
||||||
|
if ( pht->flags & PF_X ) { prot |= PROT_EXEC; }
|
||||||
|
if ( pht->flags & PF_R ) { prot |= PROT_READ; }
|
||||||
|
if ( pht->flags & PF_W ) { prot |= PROT_WRITE; }
|
||||||
|
|
||||||
|
if ( segment->Intersects(process->segments) )
|
||||||
|
{
|
||||||
|
delete segment;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( !Memory::MapRange(mapto, mapbytes, prot) )
|
||||||
|
{
|
||||||
|
// TODO: Memory leak of segment?
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Insert our newly allocated memory into the processes segment
|
||||||
|
// list such that it can be reclaimed later.
|
||||||
|
if ( process->segments )
|
||||||
|
process->segments->prev = segment;
|
||||||
|
segment->next = process->segments;
|
||||||
|
process->segments = segment;
|
||||||
|
|
||||||
|
// Copy as much data as possible and memset the rest to 0.
|
||||||
|
uint8_t* memdest = (uint8_t*) virtualaddr;
|
||||||
|
uint8_t* memsource = (uint8_t*) (((addr_t)file) + pht->offset);
|
||||||
|
memcpy(memdest, memsource, pht->filesize);
|
||||||
|
memset(memdest + pht->filesize, 0, pht->memorysize - pht->filesize);
|
||||||
|
}
|
||||||
|
|
||||||
|
return entry;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
addr_t Construct(Process* process, const void* file, size_t filelen)
|
||||||
|
{
|
||||||
|
if ( filelen < sizeof(Header) )
|
||||||
|
return errno = ENOEXEC, 0;
|
||||||
|
|
||||||
|
const Header* header = (const Header*) file;
|
||||||
|
|
||||||
|
if ( !(header->magic[0] == 0x7F && header->magic[1] == 'E' &&
|
||||||
|
header->magic[2] == 'L' && header->magic[3] == 'F' ) )
|
||||||
|
return errno = ENOEXEC, 0;
|
||||||
|
|
||||||
|
switch ( header->fileclass )
|
||||||
|
{
|
||||||
|
case CLASS32: return Construct32(process, file, filelen);
|
||||||
|
case CLASS64: return Construct64(process, file, filelen);
|
||||||
|
default:
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace ELF
|
||||||
|
} // namespace Sortix
|
||||||
|
|
305
sortix/elf.h
305
sortix/elf.h
|
@ -1,6 +1,6 @@
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
|
|
||||||
Copyright(C) Jonas 'Sortie' Termansen 2011.
|
Copyright(C) Jonas 'Sortie' Termansen 2011, 2012, 2013.
|
||||||
|
|
||||||
This file is part of Sortix.
|
This file is part of Sortix.
|
||||||
|
|
||||||
|
@ -25,171 +25,172 @@
|
||||||
#ifndef SORTIX_ELF_H
|
#ifndef SORTIX_ELF_H
|
||||||
#define SORTIX_ELF_H
|
#define SORTIX_ELF_H
|
||||||
|
|
||||||
namespace Sortix
|
namespace Sortix {
|
||||||
|
|
||||||
|
class Process;
|
||||||
|
|
||||||
|
namespace ELF {
|
||||||
|
|
||||||
|
struct Header
|
||||||
{
|
{
|
||||||
class Process;
|
unsigned char magic[4];
|
||||||
|
unsigned char fileclass;
|
||||||
|
unsigned char dataencoding;
|
||||||
|
unsigned char version;
|
||||||
|
unsigned char osabi;
|
||||||
|
unsigned char abiversion;
|
||||||
|
unsigned char padding[7];
|
||||||
|
};
|
||||||
|
|
||||||
namespace ELF
|
const unsigned char CLASSNONE = 0;
|
||||||
{
|
const unsigned char CLASS32 = 1;
|
||||||
struct Header
|
const unsigned char CLASS64 = 2;
|
||||||
{
|
const unsigned char DATA2LSB = 1;
|
||||||
unsigned char magic[4];
|
const unsigned char DATA2MSB = 2;
|
||||||
unsigned char fileclass;
|
const unsigned char CURRENTVERSION = 1;
|
||||||
unsigned char dataencoding;
|
|
||||||
unsigned char version;
|
|
||||||
unsigned char osabi;
|
|
||||||
unsigned char abiversion;
|
|
||||||
unsigned char padding[7];
|
|
||||||
};
|
|
||||||
|
|
||||||
const unsigned char CLASSNONE = 0;
|
struct Header32 : public Header
|
||||||
const unsigned char CLASS32 = 1;
|
{
|
||||||
const unsigned char CLASS64 = 2;
|
uint16_t type;
|
||||||
const unsigned char DATA2LSB = 1;
|
uint16_t machine;
|
||||||
const unsigned char DATA2MSB = 2;
|
uint32_t version;
|
||||||
const unsigned char CURRENTVERSION = 1;
|
uint32_t entry;
|
||||||
|
uint32_t programheaderoffset;
|
||||||
|
uint32_t sectionheaderoffset;
|
||||||
|
uint32_t flags;
|
||||||
|
uint16_t elfheadersize;
|
||||||
|
uint16_t programheaderentrysize;
|
||||||
|
uint16_t numprogramheaderentries;
|
||||||
|
uint16_t sectionheaderentrysize;
|
||||||
|
uint16_t numsectionheaderentries;
|
||||||
|
uint16_t sectionheaderstringindex;
|
||||||
|
};
|
||||||
|
|
||||||
struct Header32 : public Header
|
struct Header64 : public Header
|
||||||
{
|
{
|
||||||
uint16_t type;
|
uint16_t type;
|
||||||
uint16_t machine;
|
uint16_t machine;
|
||||||
uint32_t version;
|
uint32_t version;
|
||||||
uint32_t entry;
|
uint64_t entry;
|
||||||
uint32_t programheaderoffset;
|
uint64_t programheaderoffset;
|
||||||
uint32_t sectionheaderoffset;
|
uint64_t sectionheaderoffset;
|
||||||
uint32_t flags;
|
uint32_t flags;
|
||||||
uint16_t elfheadersize;
|
uint16_t elfheadersize;
|
||||||
uint16_t programheaderentrysize;
|
uint16_t programheaderentrysize;
|
||||||
uint16_t numprogramheaderentries;
|
uint16_t numprogramheaderentries;
|
||||||
uint16_t sectionheaderentrysize;
|
uint16_t sectionheaderentrysize;
|
||||||
uint16_t numsectionheaderentries;
|
uint16_t numsectionheaderentries;
|
||||||
uint16_t sectionheaderstringindex;
|
uint16_t sectionheaderstringindex;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Header64 : public Header
|
struct SectionHeader32
|
||||||
{
|
{
|
||||||
uint16_t type;
|
uint32_t name;
|
||||||
uint16_t machine;
|
uint32_t type;
|
||||||
uint32_t version;
|
uint32_t flags;
|
||||||
uint64_t entry;
|
uint32_t addr;
|
||||||
uint64_t programheaderoffset;
|
uint32_t offset;
|
||||||
uint64_t sectionheaderoffset;
|
uint32_t size;
|
||||||
uint32_t flags;
|
uint32_t link;
|
||||||
uint16_t elfheadersize;
|
uint32_t info;
|
||||||
uint16_t programheaderentrysize;
|
uint32_t addralign;
|
||||||
uint16_t numprogramheaderentries;
|
uint32_t entsize;
|
||||||
uint16_t sectionheaderentrysize;
|
};
|
||||||
uint16_t numsectionheaderentries;
|
|
||||||
uint16_t sectionheaderstringindex;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct SectionHeader32
|
struct SectionHeader64
|
||||||
{
|
{
|
||||||
uint32_t name;
|
uint32_t name;
|
||||||
uint32_t type;
|
uint32_t type;
|
||||||
uint32_t flags;
|
uint64_t flags;
|
||||||
uint32_t addr;
|
uint64_t addr;
|
||||||
uint32_t offset;
|
uint64_t offset;
|
||||||
uint32_t size;
|
uint64_t size;
|
||||||
uint32_t link;
|
uint32_t link;
|
||||||
uint32_t info;
|
uint32_t info;
|
||||||
uint32_t addralign;
|
uint64_t addralign;
|
||||||
uint32_t entsize;
|
uint64_t entsize;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct SectionHeader64
|
const uint32_t SHT_NULL = 0;
|
||||||
{
|
const uint32_t SHT_PROGBITS = 1;
|
||||||
uint32_t name;
|
const uint32_t SHT_SYMTAB = 2;
|
||||||
uint32_t type;
|
const uint32_t SHT_STRTAB = 3;
|
||||||
uint64_t flags;
|
const uint32_t SHT_RELA = 4;
|
||||||
uint64_t addr;
|
const uint32_t SHT_HASH = 5;
|
||||||
uint64_t offset;
|
const uint32_t SHT_DYNAMIC = 6;
|
||||||
uint64_t size;
|
const uint32_t SHT_NOTE = 7;
|
||||||
uint32_t link;
|
const uint32_t SHT_NOBITS = 8;
|
||||||
uint32_t info;
|
const uint32_t SHT_REL = 9;
|
||||||
uint64_t addralign;
|
const uint32_t SHT_SHLIB = 10;
|
||||||
uint64_t entsize;
|
const uint32_t SHT_DYNSYM = 11;
|
||||||
};
|
const uint32_t SHT_LOPROC = 0x70000000;
|
||||||
|
const uint32_t SHT_HIPROC = 0x7fffffff;
|
||||||
|
const uint32_t SHT_LOUSER = 0x80000000;
|
||||||
|
const uint32_t SHT_HIUSER = 0xffffffff;
|
||||||
|
|
||||||
const uint32_t SHT_NULL = 0;
|
struct ProgramHeader32
|
||||||
const uint32_t SHT_PROGBITS = 1;
|
{
|
||||||
const uint32_t SHT_SYMTAB = 2;
|
uint32_t type;
|
||||||
const uint32_t SHT_STRTAB = 3;
|
uint32_t offset;
|
||||||
const uint32_t SHT_RELA = 4;
|
uint32_t virtualaddr;
|
||||||
const uint32_t SHT_HASH = 5;
|
uint32_t physicaladdr;
|
||||||
const uint32_t SHT_DYNAMIC = 6;
|
uint32_t filesize;
|
||||||
const uint32_t SHT_NOTE = 7;
|
uint32_t memorysize;
|
||||||
const uint32_t SHT_NOBITS = 8;
|
uint32_t flags;
|
||||||
const uint32_t SHT_REL = 9;
|
uint32_t align;
|
||||||
const uint32_t SHT_SHLIB = 10;
|
};
|
||||||
const uint32_t SHT_DYNSYM = 11;
|
|
||||||
const uint32_t SHT_LOPROC = 0x70000000;
|
|
||||||
const uint32_t SHT_HIPROC = 0x7fffffff;
|
|
||||||
const uint32_t SHT_LOUSER = 0x80000000;
|
|
||||||
const uint32_t SHT_HIUSER = 0xffffffff;
|
|
||||||
|
|
||||||
struct ProgramHeader32
|
struct ProgramHeader64
|
||||||
{
|
{
|
||||||
uint32_t type;
|
uint32_t type;
|
||||||
uint32_t offset;
|
uint32_t flags;
|
||||||
uint32_t virtualaddr;
|
uint64_t offset;
|
||||||
uint32_t physicaladdr;
|
uint64_t virtualaddr;
|
||||||
uint32_t filesize;
|
uint64_t physicaladdr;
|
||||||
uint32_t memorysize;
|
uint64_t filesize;
|
||||||
uint32_t flags;
|
uint64_t memorysize;
|
||||||
uint32_t align;
|
uint64_t align;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ProgramHeader64
|
const uint32_t PT_NULL = 0;
|
||||||
{
|
const uint32_t PT_LOAD = 1;
|
||||||
uint32_t type;
|
const uint32_t PT_DYNAMIC = 2;
|
||||||
uint32_t flags;
|
const uint32_t PT_INTERP = 3;
|
||||||
uint64_t offset;
|
const uint32_t PT_NOTE = 4;
|
||||||
uint64_t virtualaddr;
|
const uint32_t PT_SHLIB = 5;
|
||||||
uint64_t physicaladdr;
|
const uint32_t PT_PHDR = 6;
|
||||||
uint64_t filesize;
|
const uint32_t PT_LOPROC = 0x70000000;
|
||||||
uint64_t memorysize;
|
const uint32_t PT_HIPROC = 0x7FFFFFFF;
|
||||||
uint64_t align;
|
|
||||||
};
|
|
||||||
|
|
||||||
const uint32_t PT_NULL = 0;
|
const uint32_t PF_X = 1 << 0;
|
||||||
const uint32_t PT_LOAD = 1;
|
const uint32_t PF_W = 1 << 1;
|
||||||
const uint32_t PT_DYNAMIC = 2;
|
const uint32_t PF_R = 1 << 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;
|
|
||||||
|
|
||||||
const uint32_t PF_X = (1<<0);
|
struct Symbol32
|
||||||
const uint32_t PF_W = (1<<1);
|
{
|
||||||
const uint32_t PF_R = (1<<2);
|
uint32_t st_name;
|
||||||
|
uint32_t st_value;
|
||||||
|
uint32_t st_size;
|
||||||
|
uint8_t st_info;
|
||||||
|
uint8_t st_other;
|
||||||
|
uint16_t st_shndx;
|
||||||
|
};
|
||||||
|
|
||||||
struct Symbol32
|
struct Symbol64
|
||||||
{
|
{
|
||||||
uint32_t st_name;
|
uint32_t st_name;
|
||||||
uint32_t st_value;
|
uint8_t st_info;
|
||||||
uint32_t st_size;
|
uint8_t st_other;
|
||||||
uint8_t st_info;
|
uint16_t st_shndx;
|
||||||
uint8_t st_other;
|
uint64_t st_value;
|
||||||
uint16_t st_shndx;
|
uint64_t st_size;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Symbol64
|
// Reads the elf file into the current address space and returns the entry
|
||||||
{
|
// address of the program, or 0 upon failure.
|
||||||
uint32_t st_name;
|
addr_t Construct(Process* process, const void* file, size_t filelen);
|
||||||
uint8_t st_info;
|
|
||||||
uint8_t st_other;
|
|
||||||
uint16_t st_shndx;
|
|
||||||
uint64_t st_value;
|
|
||||||
uint64_t st_size;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Reads the elf file into the current address space and returns the
|
} // namespace ELF
|
||||||
// entry address of the program, or 0 upon failure.
|
} // namespace Sortix
|
||||||
addr_t Construct(Process* process, const void* file, size_t filelen);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in New Issue