From fdcfb1f2da516e1f3a280d24dc24fa308e6619ea Mon Sep 17 00:00:00 2001 From: Jonas 'Sortie' Termansen Date: Mon, 17 Feb 2014 20:56:19 +0100 Subject: [PATCH] Handle ELF notes during program load. --- kernel/elf.cpp | 83 +++++++++++++++++++++++++++++--- kernel/elf.h | 15 +++++- kernel/include/sortix/elf-note.h | 34 +++++++++++++ kernel/process.cpp | 4 +- 4 files changed, 128 insertions(+), 8 deletions(-) create mode 100644 kernel/include/sortix/elf-note.h diff --git a/kernel/elf.cpp b/kernel/elf.cpp index 51c9ae64..5c6acca7 100644 --- a/kernel/elf.cpp +++ b/kernel/elf.cpp @@ -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 #include +#include #include #include @@ -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; } diff --git a/kernel/elf.h b/kernel/elf.h index b3710495..4448c6ec 100644 --- a/kernel/elf.h +++ b/kernel/elf.h @@ -25,12 +25,23 @@ #ifndef SORTIX_ELF_H #define SORTIX_ELF_H +#include +#include + 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 diff --git a/kernel/include/sortix/elf-note.h b/kernel/include/sortix/elf-note.h new file mode 100644 index 00000000..6d11a46f --- /dev/null +++ b/kernel/include/sortix/elf-note.h @@ -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 . + + 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 + +__BEGIN_DECLS + +__END_DECLS + +#endif diff --git a/kernel/process.cpp b/kernel/process.cpp index 87ad1bce..a37e9bc9 100644 --- a/kernel/process.cpp +++ b/kernel/process.cpp @@ -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;