Handle ELF notes during program load.

This commit is contained in:
Jonas 'Sortie' Termansen 2014-02-17 20:56:19 +01:00
parent 86dc1c849e
commit fdcfb1f2da
4 changed files with 128 additions and 8 deletions

View File

@ -1,6 +1,6 @@
/*******************************************************************************
Copyright(C) Jonas 'Sortie' Termansen 2011, 2012, 2013.
Copyright(C) Jonas 'Sortie' Termansen 2011, 2012, 2013, 2014.
This file is part of Sortix.
@ -31,6 +31,7 @@
#include <stdlib.h>
#include <string.h>
#include <sortix/elf-note.h>
#include <sortix/mman.h>
#include <sortix/kernel/kernel.h>
@ -48,7 +49,8 @@ namespace ELF {
// headers may vary depending on the ELF header and that using a simple
// table indexation isn't enough.
addr_t Construct32(Process* process, const uint8_t* file, size_t filelen)
addr_t Construct32(Process* process, const uint8_t* file, size_t filelen,
Auxiliary* aux)
{
if ( filelen < sizeof(Header32) )
return 0;
@ -88,6 +90,38 @@ addr_t Construct32(Process* process, const uint8_t* file, size_t filelen)
for ( uint16_t i = 0; i < numprogheaders; i++ )
{
const ProgramHeader32* pht = &(phtbl[i]);
if ( pht->type == PT_TLS )
{
aux->tls_file_offset = pht->offset;
aux->tls_file_size = pht->filesize;
aux->tls_mem_size = pht->memorysize;
aux->tls_mem_align = pht->align;
continue;
}
if ( pht->type == PT_NOTE )
{
uintptr_t notes_addr = (uintptr_t) file + pht->offset;
size_t notes_offset = 0;
while ( notes_offset < pht->filesize )
{
uintptr_t note = notes_addr + notes_offset;
uint32_t namesz = *(uint32_t*) (note + 0);
uint32_t descsz = *(uint32_t*) (note + 4);
uint32_t type = *(uint32_t*) (note + 8);
uint32_t namesz_aligned = -(-namesz & ~(4U - 1));
uint32_t descsz_aligned = -(-descsz & ~(4U - 1));
size_t note_size = 12 + namesz_aligned + descsz_aligned;
notes_offset += note_size;
const char* name = (const char*) (note + 12);
uintptr_t desc = note + 12 + namesz_aligned;
if ( strcmp(name, "Sortix") == 0 )
{
(void) desc;
(void) type;
}
}
continue;
}
if ( pht->type != PT_LOAD )
continue;
addr_t virtualaddr = pht->virtualaddr;
@ -210,12 +244,14 @@ addr_t Construct32(Process* process, const uint8_t* file, size_t filelen)
return entry;
}
addr_t Construct64(Process* process, const uint8_t* file, size_t filelen)
addr_t Construct64(Process* process, const uint8_t* file, size_t filelen,
Auxiliary* aux)
{
#if !defined(__x86_64__)
(void) process;
(void) file;
(void) filelen;
(void) aux;
return errno = ENOEXEC, 0;
#else
if ( filelen < sizeof(Header64) )
@ -256,6 +292,38 @@ addr_t Construct64(Process* process, const uint8_t* file, size_t filelen)
for ( uint16_t i = 0; i < numprogheaders; i++ )
{
const ProgramHeader64* pht = &(phtbl[i]);
if ( pht->type == PT_TLS )
{
aux->tls_file_offset = pht->offset;
aux->tls_file_size = pht->filesize;
aux->tls_mem_size = pht->memorysize;
aux->tls_mem_align = pht->align;
continue;
}
if ( pht->type == PT_NOTE )
{
uintptr_t notes_addr = (uintptr_t) file + pht->offset;
size_t notes_offset = 0;
while ( notes_offset < pht->filesize )
{
uintptr_t note = notes_addr + notes_offset;
uint32_t namesz = *(uint32_t*) (note + 0);
uint32_t descsz = *(uint32_t*) (note + 4);
uint32_t type = *(uint32_t*) (note + 8);
uint32_t namesz_aligned = -(-namesz & ~(4U - 1));
uint32_t descsz_aligned = -(-descsz & ~(4U - 1));
size_t note_size = 12 + namesz_aligned + descsz_aligned;
notes_offset += note_size;
const char* name = (const char*) (note + 12);
uintptr_t desc = note + 12 + namesz_aligned;
if ( strcmp(name, "Sortix") == 0 )
{
(void) desc;
(void) type;
}
}
continue;
}
if ( pht->type != PT_LOAD )
continue;
addr_t virtualaddr = pht->virtualaddr;
@ -379,7 +447,8 @@ addr_t Construct64(Process* process, const uint8_t* file, size_t filelen)
#endif
}
addr_t Construct(Process* process, const void* file, size_t filelen)
addr_t Construct(Process* process, const void* file, size_t filelen,
Auxiliary* aux)
{
if ( filelen < sizeof(Header) )
return errno = ENOEXEC, 0;
@ -390,10 +459,12 @@ addr_t Construct(Process* process, const void* file, size_t filelen)
header->magic[2] == 'L' && header->magic[3] == 'F' ) )
return errno = ENOEXEC, 0;
memset(aux, 0, sizeof(*aux));
switch ( header->fileclass )
{
case CLASS32: return Construct32(process, (const uint8_t*) file, filelen);
case CLASS64: return Construct64(process, (const uint8_t*) file, filelen);
case CLASS32: return Construct32(process, (const uint8_t*) file, filelen, aux);
case CLASS64: return Construct64(process, (const uint8_t*) file, filelen, aux);
default:
return 0;
}

View File

@ -25,12 +25,23 @@
#ifndef SORTIX_ELF_H
#define SORTIX_ELF_H
#include <stddef.h>
#include <stdint.h>
namespace Sortix {
class Process;
namespace ELF {
struct Auxiliary
{
size_t tls_file_offset;
size_t tls_file_size;
size_t tls_mem_size;
size_t tls_mem_align;
};
struct Header
{
unsigned char magic[4];
@ -159,6 +170,7 @@ 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_TLS = 7;
const uint32_t PT_LOPROC = 0x70000000;
const uint32_t PT_HIPROC = 0x7FFFFFFF;
@ -188,7 +200,8 @@ struct Symbol64
// Reads the elf file into the current address space and returns the entry
// address of the program, or 0 upon failure.
addr_t Construct(Process* process, const void* file, size_t filelen);
addr_t Construct(Process* process, const void* file, size_t filelen,
Auxiliary* aux);
} // namespace ELF
} // namespace Sortix

View File

@ -0,0 +1,34 @@
/*******************************************************************************
Copyright(C) Jonas 'Sortie' Termansen 2014.
This file is part of Sortix.
Sortix is free software: you can redistribute it and/or modify it under the
terms of the GNU General Public License as published by the Free Software
Foundation, either version 3 of the License, or (at your option) any later
version.
Sortix is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
details.
You should have received a copy of the GNU General Public License along with
Sortix. If not, see <http://www.gnu.org/licenses/>.
sortix/elf-note.h
Declares type constants for the Sortix ELF notes.
*******************************************************************************/
#ifndef INCLUDE_SORTIX_ELF_NOTE_H
#define INCLUDE_SORTIX_ELF_NOTE_H
#include <sys/cdefs.h>
__BEGIN_DECLS
__END_DECLS
#endif

View File

@ -747,7 +747,9 @@ int Process::Execute(const char* programname, const uint8_t* program,
if ( !programname_clone )
return -1;
addr_t entry = ELF::Construct(CurrentProcess(), program, programsize);
ELF::Auxiliary aux;
addr_t entry = ELF::Construct(CurrentProcess(), program, programsize, &aux);
if ( !entry ) { delete[] programname_clone; return -1; }
delete[] program_image_path;