From 1319e58bafa4041c6db6c35eefa6f0cf1934e6ae Mon Sep 17 00:00:00 2001 From: Gonzo Date: Tue, 24 Jan 2017 18:00:00 +0100 Subject: [PATCH 1/4] pci: Enable missing command flags --- src/hw/pci_device.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/hw/pci_device.cpp b/src/hw/pci_device.cpp index 6cec875c65..d022e78493 100644 --- a/src/hw/pci_device.cpp +++ b/src/hw/pci_device.cpp @@ -38,6 +38,10 @@ #define PCI_HEADER_REG 0x0e #define PCI_BIST_REG 0x0f +#define PCI_COMMAND_IO 0x01 +#define PCI_COMMAND_MEM 0x02 +#define PCI_COMMAND_MASTER 0x04 + namespace hw { static const char* classcodes[] { @@ -150,6 +154,11 @@ namespace hw { PCI_Device::PCI_Device(const uint16_t pci_addr, const uint32_t device_id) : pci_addr_{pci_addr}, device_id_{device_id} { + // set master, mem and io flags + uint32_t cmd = read_dword(PCI_CMD_REG); + cmd |= PCI_COMMAND_MASTER | PCI_COMMAND_MEM | PCI_COMMAND_IO; + write_dword(PCI_CMD_REG, cmd); + //We have device, so probe for details devtype_.reg = read_dword(pci_addr, PCI::CONFIG_CLASS_REV); From 80326dc1b7000741320c054031279b88b6bfb346 Mon Sep 17 00:00:00 2001 From: fwsgonzo Date: Wed, 25 Jan 2017 18:18:01 +0100 Subject: [PATCH 2/4] kernel: Rearrange ELF symbol header, simplify some things --- src/crt/c_abi.c | 43 ++++++++-------- src/kernel/elf.cpp | 116 +++++++++++++++++++++++-------------------- vmbuild/elf_syms.cpp | 27 ++++------ 3 files changed, 93 insertions(+), 93 deletions(-) diff --git a/src/crt/c_abi.c b/src/crt/c_abi.c index 24a5276d9d..3343b04e56 100644 --- a/src/crt/c_abi.c +++ b/src/crt/c_abi.c @@ -24,7 +24,7 @@ #include #include -#define HEAP_ALIGNMENT 16 +#define HEAP_ALIGNMENT 63 caddr_t heap_begin; caddr_t heap_end; @@ -47,28 +47,26 @@ void _init_c_runtime() extern char _end; /// init backtrace functionality - extern void _move_elf_symbols(void*, void*); - extern void _apply_parser_data(void*); - extern int _get_elf_section_size(const void*); - // first measure the size of symbols - int symsize = _get_elf_section_size(&_ELF_SYM_START_); - // estimate somewhere in heap its safe to move them - char* SYM_LOCATION = &_end + 2 * (4096 + symsize); - _move_elf_symbols(&_ELF_SYM_START_, SYM_LOCATION); + extern int _get_elf_section_datasize(const void*); + extern void _move_elf_syms_location(const void*, void*); + // store symbols temporarily in a safe location + char* sym_temp = &_end + + 2*4096 + _get_elf_section_datasize(&_ELF_SYM_START_); + _move_elf_syms_location(&_ELF_SYM_START_, sym_temp); // Initialize .bss section extern char _BSS_START_, _BSS_END_; streamset8(&_BSS_START_, 0, &_BSS_END_ - &_BSS_START_); // Initialize the heap before exceptions - heap_begin = &_end + 0xfff; - // page-align heap, because its not aligned - heap_begin = (char*) ((uintptr_t)heap_begin & ~(uintptr_t) 0xfff); + // cache-align heap, because its not aligned + heap_begin = &_end + 64 + HEAP_ALIGNMENT; + heap_begin = (char*) ((uintptr_t)heap_begin & ~(uintptr_t) HEAP_ALIGNMENT); // heap end tracking, used with sbrk heap_end = heap_begin; - // validate that heap is page aligned + // validate that heap is aligned int validate_heap_alignment = - ((uintptr_t)heap_begin & (uintptr_t) 0xfff) == 0; + ((uintptr_t)heap_begin & (uintptr_t) HEAP_ALIGNMENT) == 0; /// initialize newlib I/O _REENT_INIT_PTR(_REENT); @@ -77,9 +75,13 @@ void _init_c_runtime() stdout = _REENT->_stdout; // stdout == 2 stderr = _REENT->_stderr; // stderr == 3 - // move symbols (again) to heap, before calling global constructors - extern void* _relocate_to_heap(void*); - void* symheap = _relocate_to_heap(SYM_LOCATION); + /// init ELF / backtrace functionality + extern void _elf_relocate_to_heap(); + extern void _init_elf_parser(); + // move ELF symbols into heap + _elf_relocate_to_heap(); + // enable ELF symbols here (before global constructors) + _init_elf_parser(); /// initialize exceptions before we can run constructors extern char __eh_frame_start[]; @@ -91,23 +93,18 @@ void _init_c_runtime() extern void _init(); _init(); - // set ELF symbols location here (after initializing everything else) - _apply_parser_data(symheap); - // sanity checks assert(heap_begin >= &_end); assert(heap_end >= heap_begin); assert(validate_heap_alignment); } -// global/static objects should never be destructed here, so ignore this -void* __dso_handle; - // stack-protector __attribute__((noreturn)) void __stack_chk_fail(void) { panic("Stack protector: Canary modified"); + __builtin_unreachable(); } // old function result system diff --git a/src/kernel/elf.cpp b/src/kernel/elf.cpp index 2f217d2a42..b252645129 100644 --- a/src/kernel/elf.cpp +++ b/src/kernel/elf.cpp @@ -74,10 +74,10 @@ class ElfTables func_offset getsym(Elf32_Addr addr) { // probably just a null pointer with ofs=addr - if (UNLIKELY(addr < 0x7c00)) + if (UNLIKELY(addr < 0x1000)) return {null_stringz, 0, addr}; // definitely in the bootloader - if (UNLIKELY(addr < 0x7e00)) + if (UNLIKELY(addr >= 0x7c00 && addr < 0x7e00)) return {boot_stringz, 0x7c00, addr - 0x7c00}; // resolve manually from symtab auto* sym = getaddr(addr); @@ -87,7 +87,11 @@ class ElfTables auto base = sym->st_value; auto offset = addr - base; // return string name for symbol - return {demangle( sym_name(sym) ), base, offset}; + const char* name = sym_name(sym); + if (name) + return {demangle(name), base, offset}; + else + return {to_hex_string(base), base, offset}; } // function or space not found return {to_hex_string(addr), addr, 0}; @@ -95,9 +99,11 @@ class ElfTables safe_func_offset getsym_safe(Elf32_Addr addr, char* buffer, size_t length) { // probably just a null pointer with ofs=addr - if (addr < 0x7c00) return {null_stringz, 0, addr}; + if (UNLIKELY(addr < 0x1000)) + return {null_stringz, 0, addr}; // definitely in the bootloader - if (addr < 0x7e00) return {boot_stringz, 0x7c00, addr - 0x7c00}; + if (UNLIKELY(addr >= 0x7c00 && addr < 0x7e00)) + return {boot_stringz, 0x7c00, addr - 0x7c00}; // resolve manually from symtab auto* sym = getaddr(addr); if (LIKELY(sym)) { @@ -153,17 +159,13 @@ class ElfTables } std::string demangle(const char* name) const { - if (name[0] == '_') { - int status; - // internally, demangle just returns buf when status is ok - auto* res = __cxa_demangle(name, nullptr, 0, &status); - if (status == 0) { - std::string result(res); - std::free(res); - return result; - } - } - return std::string(name); + char buffer[2048]; + const char* res = demangle_safe(name, buffer, sizeof(buffer)); + assert(strlen(res)); + if (res) + return std::string(res); + else + return std::string(name); } const char* demangle_safe(const char* name, char* buffer, size_t buflen) const { @@ -256,8 +258,8 @@ std::vector Elf::get_functions() void print_backtrace() { - char _symbol_buffer[512]; - char _btrace_buffer[512]; + char _symbol_buffer[1024]; + char _btrace_buffer[1024]; if (Elf::get_strtab() == NULL) { int len = snprintf(_btrace_buffer, sizeof(_btrace_buffer), @@ -343,59 +345,67 @@ void _validate_elf_symbols() } } -struct relocate_header { - SymTab symtab; - StrTab strtab; +static struct relocated_header { + uint32_t entries = 0xFFFF; + uint32_t strsize = 0xFFFF; + Elf32_Sym* syms = nullptr; + + const char* strings() const { + return (char*) &syms[entries]; + } +} relocs; +struct elfsyms_header { + uint32_t symtab_entries; + uint32_t strtab_size; + Elf32_Sym syms[0]; }; +#include extern "C" -int _get_elf_section_size(const void* location) +int _get_elf_section_datasize(const void* location) { - auto& hdr = *(relocate_header*) location; - return sizeof(relocate_header) + hdr.symtab.entries * sizeof(Elf32_Sym) + hdr.strtab.size; + auto& hdr = *(elfsyms_header*) location; + // special case for missing call to elf_syms + if (hdr.symtab_entries == 0) return 0; + return hdr.symtab_entries * sizeof(Elf32_Sym) + hdr.strtab_size; } -#include extern "C" -void _move_elf_symbols(void* old_location, void* new_location) +void _move_elf_syms_location(const void* location, void* new_location) { - int size = _get_elf_section_size(old_location); - // validate locations - if ((char*) new_location >= (char*) old_location && - (char*) new_location + size < (char*) old_location) - { - kprintf("ELF symbol sections are inside each other!\n"); - kprintf("Moving %d from %p -> %p (%p)\n", - size, old_location, new_location, (char*) new_location + size); - assert(0); + int size = _get_elf_section_datasize(location); + // stripped variant + if (size == 0) { + relocs.entries = 0; + relocs.strsize = 0; + return; } - // copy over - memcpy(new_location, old_location, size); + // old header + auto* hdr = (elfsyms_header*) location; // update header - auto* newhdr = (relocate_header*) new_location; - const char* base = ((char*) newhdr) + sizeof(relocate_header); - newhdr->symtab.base = (Elf32_Sym*) base; - newhdr->strtab.base = &base[newhdr->symtab.entries * sizeof(Elf32_Sym)]; + relocs.entries = hdr->symtab_entries; + relocs.strsize = hdr->strtab_size; + relocs.syms = (Elf32_Sym*) new_location; + // copy symbol and string data + memcpy(relocs.syms, hdr->syms, size); } -#if !defined(__MACH__) -#include -#endif extern "C" -void* _relocate_to_heap(void* old_location) +void _elf_relocate_to_heap() { - int total = _get_elf_section_size(old_location); - void* heap_location = malloc(total); - _move_elf_symbols(old_location, heap_location); - return heap_location; + int size = relocs.entries * sizeof(Elf32_Sym) + relocs.strsize; + char* newloc = new char[size]; + // copy syms & update location + memcpy(newloc, relocs.syms, size); + relocs.syms = (Elf32_Sym*) newloc; } +#include extern "C" -void _apply_parser_data(char* location) +void _init_elf_parser() { - if (location) { - auto& hdr = *(relocate_header*) location; + if (relocs.entries) { // apply changes to the symbol parser from custom location - parser.set(hdr.symtab.base, hdr.symtab.entries, hdr.strtab.base); + parser.set(relocs.syms, relocs.entries, relocs.strings()); } else { // symbols and strings are stripped out diff --git a/vmbuild/elf_syms.cpp b/vmbuild/elf_syms.cpp index bda13fc2f4..6cd5d08f92 100644 --- a/vmbuild/elf_syms.cpp +++ b/vmbuild/elf_syms.cpp @@ -15,9 +15,8 @@ static const char* elf_offset(int o) noexcept { return (char*)elf_header_location + o; } -static void prune_elf_symbols(); -static char* pruned_location; -static int pruned_size = 0; +static int prune_elf_symbols(); +static char* pruned_location = nullptr; int main(int argc, const char** args) { @@ -38,7 +37,7 @@ int main(int argc, const char** args) // validate symbols elf_header_location = (decltype(elf_header_location)) fdata; - prune_elf_symbols(); + int pruned_size = prune_elf_symbols(); // write symbols to binary file f = fopen("_elf_symbols.bin", "w"); @@ -58,16 +57,11 @@ struct StrTab { StrTab(char* base, uint32_t size) : base(base), size(size) {} }; -struct relocate_header { - SymTab symtab; - StrTab strtab; -}; struct relocate_header32 { - uint32_t symtab_base; - uint32_t symtab_entries; - uint32_t strtab_base; - uint32_t strtab_size; + uint32_t symtab_entries; + uint32_t strtab_size; + Elf32_Sym syms[0]; }; static int relocate_pruned_sections(char* new_location, SymTab& symtab, StrTab& strtab) @@ -75,7 +69,7 @@ static int relocate_pruned_sections(char* new_location, SymTab& symtab, StrTab& auto& hdr = *(relocate_header32*) new_location; // first prune symbols - auto* symloc = (Elf32_Sym*) (new_location + sizeof(relocate_header32)); + auto* symloc = hdr.syms; size_t symidx = 0; for (size_t i = 0; i < symtab.entries; i++) { @@ -110,7 +104,7 @@ static int relocate_pruned_sections(char* new_location, SymTab& symtab, StrTab& hdr.strtab_size * sizeof(char); } -static void prune_elf_symbols() +static int prune_elf_symbols() { SymTab symtab { nullptr, 0 }; std::vector strtabs; @@ -144,10 +138,9 @@ static void prune_elf_symbols() // allocate worst case, guaranteeing we have enough space pruned_location = new char[sizeof(relocate_header32) + symtab.entries * sizeof(Elf32_Sym) + strtab.size]; - pruned_size = relocate_pruned_sections(pruned_location, symtab, strtab); - return; + return relocate_pruned_sections(pruned_location, symtab, strtab); } // stripped variant pruned_location = new char[sizeof(relocate_header32)]; - pruned_size = sizeof(relocate_header32); + return sizeof(relocate_header32); } From a359cb3d825ca3ac104f4af91ad303759c46e244 Mon Sep 17 00:00:00 2001 From: fwsgonzo Date: Wed, 25 Jan 2017 20:55:24 +0100 Subject: [PATCH 3/4] posix: Add various stubs to signal, mman and a few linux stubs --- api/posix/sys/mman.h | 24 ++++++++++++++++++++---- api/sys/dlfcn.h | 25 +++++++++++++++++++++++++ api/sys/signal.h | 42 ++++++++++++++++++++++++++++++++++++++++++ src/crt/c_abi.c | 11 +++++++++++ src/posix/sys/mman.cpp | 6 ++++++ 5 files changed, 104 insertions(+), 4 deletions(-) create mode 100644 api/sys/dlfcn.h create mode 100644 api/sys/signal.h diff --git a/api/posix/sys/mman.h b/api/posix/sys/mman.h index 23faf6b7ef..25c55d8d81 100644 --- a/api/posix/sys/mman.h +++ b/api/posix/sys/mman.h @@ -24,13 +24,29 @@ extern "C" { #endif #include +#include typedef _off_t off_t; -void *mmap(void* addr, size_t length, - int prot, int flags, - int fd, off_t offset); -int munmap(void* addr, size_t length); +struct posix_typed_mem_info +{ + size_t posix_tmi_length; +}; +int mlock(const void *, size_t); +int mlockall(int); +void *mmap(void *, size_t, int, int, int, off_t); +int mprotect(void *, size_t, int); +int msync(void *, size_t, int); +int munlock(const void *, size_t); +int munlockall(void); +int munmap(void *, size_t); +int posix_madvise(void *, size_t, int); +int posix_mem_offset(const void *__restrict__, size_t, off_t *__restrict__, + size_t *__restrict__, int *__restrict__); +int posix_typed_mem_get_info(int, struct posix_typed_mem_info *); +int posix_typed_mem_open(const char *, int, int); +int shm_open(const char *, int, mode_t); +int shm_unlink(const char *); // Page can be executed. #define PROT_EXEC 0x1 diff --git a/api/sys/dlfcn.h b/api/sys/dlfcn.h new file mode 100644 index 0000000000..49e7ff83a5 --- /dev/null +++ b/api/sys/dlfcn.h @@ -0,0 +1,25 @@ +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +void *dlopen(const char *filename, int flag); +char *dlerror(void); +void *dlsym(void *handle, const char *symbol); +int dlclose(void *handle); + + +#define RTLD_LAZY 1 +#define RTLD_NOW 2 +#define RTLD_GLOBAL 3 +#define RTLD_LOCAL 4 +#define RTLD_NODELETE 6 +#define RTLD_NOLOAD 7 +#define RTLD_DEEPBIND 8 + +#define RTLD_DEFAULT 1 + +#ifdef __cplusplus +} +#endif diff --git a/api/sys/signal.h b/api/sys/signal.h new file mode 100644 index 0000000000..0753636fef --- /dev/null +++ b/api/sys/signal.h @@ -0,0 +1,42 @@ +// This file is a part of the IncludeOS unikernel - www.includeos.org +// +// Copyright 2016 Oslo and Akershus University College of Applied Sciences +// and Alfred Bratterud +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma once +#ifndef SYS_SIGNAL_H +#define SYS_SIGNAL_H + +#ifdef __cplusplus +extern "C" { +#endif + +struct siginfo_t +{ + int si_signo; // Signal number. + int si_code; // Signal code. + + int sa_sigaction; +}; + +#define SA_RESETHAND 666 + +#ifdef __cplusplus +} +#endif + +#include_next + +#endif diff --git a/src/crt/c_abi.c b/src/crt/c_abi.c index 3343b04e56..b1c9b92faa 100644 --- a/src/crt/c_abi.c +++ b/src/crt/c_abi.c @@ -114,6 +114,17 @@ int* __errno_location(void) return &errno; } +#include +int _setjmp(jmp_buf env) +{ + return setjmp(env); +} +// linux strchr variant (NOTE: not completely the same!) +void *__rawmemchr (const void *s, int c) +{ + return strchr((const char*) s, c); +} + /// assert() interface of ISO POSIX (2003) void __assert_fail(const char * assertion, const char * file, unsigned int line, const char * function) { diff --git a/src/posix/sys/mman.cpp b/src/posix/sys/mman.cpp index 12170358f8..5c448fdf06 100644 --- a/src/posix/sys/mman.cpp +++ b/src/posix/sys/mman.cpp @@ -70,3 +70,9 @@ int munmap(void* addr, size_t length) errno = EINVAL; return -1; } + +int mprotect(void *addr, size_t len, int prot) +{ + printf("mprotect %p:%u with flags %#x\n", addr, len, prot); + return 0; +} From 93c2161f732724b6090d197d290256ab510e27db Mon Sep 17 00:00:00 2001 From: fwsgonzo Date: Wed, 25 Jan 2017 23:29:36 +0100 Subject: [PATCH 4/4] posix: Add dlfcn stubs --- src/CMakeLists.txt | 3 +-- src/posix/dlfcn.cpp | 40 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 41 insertions(+), 2 deletions(-) create mode 100644 src/posix/dlfcn.cpp diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index f72abb44fa..0ce7f05af4 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -53,8 +53,7 @@ set(OS_OBJECTS posix/fd.cpp posix/tcp_fd.cpp posix/udp_fd.cpp posix/unistd.cpp posix/fcntl.cpp posix/syslog.cpp posix/sys/socket.cpp posix/sys/select.cpp posix/sys/utsname.cpp posix/sys/mman.cpp posix/arpa/inet.cpp posix/ucontext.cpp posix/ucontext_asm.asm - posix/sys/stat.cpp posix/ftw.cpp - posix/file_fd.cpp + posix/sys/stat.cpp posix/ftw.cpp posix/file_fd.cpp posix/dlfcn.cpp ) add_library(os STATIC ${OS_OBJECTS} apic_boot.o) diff --git a/src/posix/dlfcn.cpp b/src/posix/dlfcn.cpp new file mode 100644 index 0000000000..cb5f1a7b61 --- /dev/null +++ b/src/posix/dlfcn.cpp @@ -0,0 +1,40 @@ +// This file is a part of the IncludeOS unikernel - www.includeos.org +// +// Copyright 2015-2016 Oslo and Akershus University College of Applied Sciences +// and Alfred Bratterud +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include +#include + +void* dlopen(const char *filename, int flag) +{ + printf("dlopen called for %s with flag %#x\n", filename, flag); + return nullptr; +} +char* dlerror(void) +{ + printf("dlerror\n"); + return nullptr; +} +void* dlsym(void*, const char* symbol) +{ + printf("dlsym on %s\n", symbol); + return nullptr; +} +int dlclose(void*) +{ + printf("dlclose\n"); + return 0; +}