From dea474dfd5e92878f774738e8a49084ceb9b7757 Mon Sep 17 00:00:00 2001 From: Andreas Kling Date: Mon, 12 Nov 2018 13:25:16 +0100 Subject: [PATCH] Make loading /bin/bash ~250x faster. The ELF loader was doing huge amounts of unnecessary work. Got rid of the "export symbols" and relocation passes since we don't need them. They were useful things when bringing up the ELF loading code. Also added a simple TSC-based Stopwatch RAII thingy to help debug performance issues. --- ELFLoader/ELFImage.cpp | 4 +++ ELFLoader/ELFImage.h | 11 +++++++ ELFLoader/ELFLoader.cpp | 72 +++++++++++++++++++---------------------- ELFLoader/ELFLoader.h | 3 -- Kernel/i386.h | 33 +++++++++++++++++++ 5 files changed, 82 insertions(+), 41 deletions(-) diff --git a/ELFLoader/ELFImage.cpp b/ELFLoader/ELFImage.cpp index ef812141843ce3..e7d75740664ba0 100644 --- a/ELFLoader/ELFImage.cpp +++ b/ELFLoader/ELFImage.cpp @@ -107,11 +107,13 @@ bool ELFImage::parse() } } +#ifdef SUPPORT_RELOCATIONS // Then create a name-to-index map. for (unsigned i = 0; i < section_count(); ++i) { auto& section = this->section(i); m_sections.set(section.name(), move(i)); } +#endif return true; } @@ -172,6 +174,7 @@ const ELFImage::ProgramHeader ELFImage::program_header(unsigned index) const return ProgramHeader(*this, index); } +#ifdef SUPPORT_RELOCATIONS const ELFImage::Relocation ELFImage::RelocationSection::relocation(unsigned index) const { ASSERT(index < relocation_count()); @@ -204,4 +207,5 @@ const ELFImage::Section ELFImage::lookupSection(const char* name) const return section((*it).value); return section(0); } +#endif diff --git a/ELFLoader/ELFImage.h b/ELFLoader/ELFImage.h index a38fb5c359832b..24bf890a3bafbf 100644 --- a/ELFLoader/ELFImage.h +++ b/ELFLoader/ELFImage.h @@ -88,7 +88,12 @@ class ELFImage { dword address() const { return m_section_header.sh_addr; } const char* raw_data() const { return m_image.raw_data(m_section_header.sh_offset); } bool is_undefined() const { return m_section_index == SHN_UNDEF; } +#ifdef SUPPORT_RELOCATIONS const RelocationSection relocations() const; +#endif + dword flags() const { return m_section_header.sh_flags; } + bool is_writable() const { return flags() & SHF_WRITE; } + bool is_executable() const { return flags() & PF_X; } protected: friend class RelocationSection; @@ -97,6 +102,7 @@ class ELFImage { unsigned m_section_index; }; +#ifdef SUPPORT_RELOCATIONS class RelocationSection : public Section { public: RelocationSection(const Section& section) @@ -127,6 +133,7 @@ class ELFImage { const ELFImage& m_image; const Elf32_Rel& m_rel; }; +#endif unsigned symbol_count() const; unsigned section_count() const; @@ -159,7 +166,9 @@ class ELFImage { const char* section_index_to_string(unsigned index); const byte* m_buffer { nullptr }; +#ifdef SUPPORT_RELOCATIONS HashMap m_sections; +#endif bool m_valid { false }; unsigned m_symbol_table_section_index { 0 }; unsigned m_string_table_section_index { 0 }; @@ -184,6 +193,7 @@ inline void ELFImage::for_each_section_of_type(unsigned type, F func) const } } +#ifdef SUPPORT_RELOCATIONS template inline void ELFImage::RelocationSection::for_each_relocation(F func) const { @@ -192,6 +202,7 @@ inline void ELFImage::RelocationSection::for_each_relocation(F func) const break; } } +#endif template inline void ELFImage::for_each_symbol(F func) const diff --git a/ELFLoader/ELFLoader.cpp b/ELFLoader/ELFLoader.cpp index b7b206a0668ca4..324e2dff4bdec2 100644 --- a/ELFLoader/ELFLoader.cpp +++ b/ELFLoader/ELFLoader.cpp @@ -2,6 +2,7 @@ #include //#define ELFLOADER_DEBUG +//#define SUPPORT_RELOCATIONS ELFLoader::ELFLoader(const byte* buffer) : m_image(buffer) @@ -22,9 +23,10 @@ bool ELFLoader::load() if (!layout()) return false; - export_symbols(); +#ifdef SUPPORT_RELOCATIONS if (!perform_relocations()) return false; +#endif return true; } @@ -49,7 +51,7 @@ bool ELFLoader::layout() } }); - m_image.for_each_section_of_type(SHT_PROGBITS, [this] (const ELFImage::Section& section) { + m_image.for_each_section_of_type(SHT_PROGBITS, [] (const ELFImage::Section& section) { #ifdef ELFLOADER_DEBUG kprintf("ELFLoader: Copying progbits section: %s\n", section.name()); #endif @@ -62,11 +64,15 @@ bool ELFLoader::layout() #endif return true; } - memcpy(ptr, section.raw_data(), section.size()); + // If this section isn't writable, it's already mmapped. + if (section.is_writable()) + memcpy(ptr, section.raw_data(), section.size()); +#ifdef SUPPORT_RELOCATIONS m_sections.set(section.name(), move(ptr)); +#endif return true; }); - m_image.for_each_section_of_type(SHT_NOBITS, [this, &failed] (const ELFImage::Section& section) { + m_image.for_each_section_of_type(SHT_NOBITS, [&failed] (const ELFImage::Section& section) { #ifdef ELFLOADER_DEBUG kprintf("ELFLoader: Copying nobits section: %s\n", section.name()); #endif @@ -79,19 +85,24 @@ bool ELFLoader::layout() return false; } memset(ptr, 0, section.size()); +#ifdef SUPPORT_RELOCATIONS m_sections.set(section.name(), move(ptr)); +#endif return true; }); return !failed; } +#ifdef SUPPORT_RELOCATIONS void* ELFLoader::lookup(const ELFImage::Symbol& symbol) { if (symbol.section().is_undefined()) return symbol_ptr(symbol.name()); return area_for_section(symbol.section()) + symbol.value(); } +#endif +#ifdef SUPPORT_RELOCATIONS char* ELFLoader::area_for_section(const ELFImage::Section& section) { return area_for_section_name(section.name()); @@ -104,7 +115,9 @@ char* ELFLoader::area_for_section_name(const char* name) ASSERT_NOT_REACHED(); return nullptr; } +#endif +#ifdef SUPPORT_RELOCATIONS bool ELFLoader::perform_relocations() { #ifdef ELFLOADER_DEBUG @@ -166,39 +179,27 @@ bool ELFLoader::perform_relocations() }); return !failed; } +#endif -void ELFLoader::export_symbols() +char* ELFLoader::symbol_ptr(const char* name) { + char* found_ptr = nullptr; m_image.for_each_symbol([&] (const ELFImage::Symbol symbol) { -#ifdef ELFLOADER_DEBUG - kprintf("symbol: %u, type=%u, name=%s, section=%u\n", symbol.index(), symbol.type(), symbol.name(), symbol.sectionIndex()); -#endif - if (symbol.type() == STT_FUNC) { - char* ptr; - if (m_image.is_executable()) - ptr = (char*)symbol.value(); - else if (m_image.is_relocatable()) - ptr = area_for_section(symbol.section()) + symbol.value(); - else - ASSERT_NOT_REACHED(); - add_symbol(symbol.name(), ptr, symbol.size()); - } - // FIXME: What about other symbol types? - return true; + if (symbol.type() != STT_FUNC) + return true; + if (strcmp(symbol.name(), name)) + return true; + if (m_image.is_executable()) + found_ptr = (char*)symbol.value(); +#ifdef SUPPORT_RELOCATIONS + else if (m_image.is_relocatable()) + found_ptr = area_for_section(symbol.section()) + symbol.value(); +#endif + else + ASSERT_NOT_REACHED(); + return false; }); -} - -char* ELFLoader::symbol_ptr(const char* name) -{ - if (auto it = m_symbols.find(name); it != m_symbols.end()) { - auto& symbol = (*it).value; -#ifdef EXECSPACE_DEBUG - kprintf("[ELFLoader] symbol_ptr(%s) dump:\n", name); - disassemble(symbol.ptr, symbol.size); -#endif - return symbol.ptr; - } - return nullptr; + return found_ptr; } bool ELFLoader::allocate_section(LinearAddress laddr, size_t size, size_t alignment, bool is_readable, bool is_writable) @@ -216,8 +217,3 @@ bool ELFLoader::map_section(LinearAddress laddr, size_t size, size_t alignment, ksprintf(namebuf, "elf-map-%s%s", is_readable ? "r" : "", is_writable ? "w" : ""); return map_section_hook(laddr, size, alignment, offset_in_image, is_readable, is_writable, namebuf); } - -void ELFLoader::add_symbol(String&& name, char* ptr, unsigned size) -{ - m_symbols.set(move(name), { ptr, size }); -} diff --git a/ELFLoader/ELFLoader.h b/ELFLoader/ELFLoader.h index 5e2749717618b5..b364ce7299cf8f 100644 --- a/ELFLoader/ELFLoader.h +++ b/ELFLoader/ELFLoader.h @@ -15,14 +15,12 @@ class ELFLoader { Function alloc_section_hook; Function map_section_hook; char* symbol_ptr(const char* name); - void add_symbol(String&& name, char* ptr, unsigned size); bool allocate_section(LinearAddress, size_t, size_t alignment, bool is_readable, bool is_writable); bool map_section(LinearAddress, size_t, size_t alignment, size_t offset_in_image, bool is_readable, bool is_writable); private: bool layout(); bool perform_relocations(); - void export_symbols(); void* lookup(const ELFImage::Symbol&); char* area_for_section(const ELFImage::Section&); char* area_for_section_name(const char*); @@ -40,7 +38,6 @@ class ELFLoader { }; ELFImage m_image; - HashMap m_symbols; HashMap m_sections; }; diff --git a/Kernel/i386.h b/Kernel/i386.h index 0eaae76ce013d1..b4c64b62470bcf 100644 --- a/Kernel/i386.h +++ b/Kernel/i386.h @@ -1,6 +1,7 @@ #pragma once #include "types.h" +#include "kprintf.h" #define PAGE_SIZE 4096 #define PAGE_MASK 0xfffff000 @@ -218,3 +219,35 @@ class CPUID { dword m_ecx { 0xffffffff }; dword m_edx { 0xffffffff }; }; + +inline void read_tsc(dword& lsw, dword& msw) +{ + asm volatile("rdtsc":"=d"(msw),"=a"(lsw)); +} + +struct Stopwatch { +public: + Stopwatch(const char* name) + : m_name(name) + { + read_tsc(m_start_lsw, m_start_msw); + } + + ~Stopwatch() + { + dword end_lsw; + dword end_msw; + read_tsc(end_lsw, end_msw); + if (m_start_msw != end_msw) { + dbgprintf("differing msw's\n"); + asm volatile("cli;hlt"); + } + dword diff = end_lsw - m_start_lsw; + dbgprintf("Stopwatch(%s): %u ticks\n", m_name, diff); + } + +private: + const char* m_name { nullptr }; + dword m_start_lsw { 0 }; + dword m_start_msw { 0 }; +};