From e6f7be2f4f56b17abebdb71c7959e617c2275413 Mon Sep 17 00:00:00 2001 From: Matt Staveley-Taylor Date: Thu, 24 Oct 2024 14:48:56 +0200 Subject: [PATCH] meta: add clang-format --- .clang-format | 222 ++++++++ .github/workflows/formatting.yml | 14 + .pre-commit-config.yaml | 14 + README.md | 4 + options/rtld/generic/linker.cpp | 858 +++++++++++++++++-------------- 5 files changed, 725 insertions(+), 387 deletions(-) create mode 100644 .clang-format create mode 100644 .github/workflows/formatting.yml create mode 100644 .pre-commit-config.yaml diff --git a/.clang-format b/.clang-format new file mode 100644 index 000000000..ca73da6ba --- /dev/null +++ b/.clang-format @@ -0,0 +1,222 @@ +--- +# commented out settings are not available in current host-llvm-toolchain but +# could still prove useful +Language: Cpp + +# I don't see any stable default for this, lets just hope LLVM is sane enough +BasedOnStyle: LLVM + +# private: should line up with struct +AccessModifierOffset: -8 + +# alignment is mostly problematic since it requires modifying multiple lines on +# a change to keep things aligned... +AlignArrayOfStructures: None +AlignConsecutiveAssignments: false +AlignConsecutiveBitFields: false +AlignConsecutiveMacros: false +AlignConsecutiveDeclarations: false +AlignTrailingComments: false + +AlignAfterOpenBracket: DontAlign +# ... and right-align backslashes on the ends of macro lines, to preserve the +# validity of the macro while still keeping a constant column reserved for +# backslashes. +AlignEscapedNewlines: Right +# aligning operations also looks decent, in a single statement +AlignOperands: AlignAfterOperator + +# prevent squashing args onto one line +AllowAllArgumentsOnNextLine: false +# prevent squashing arguments in declarations onto one line +AllowAllParametersOfDeclarationOnNextLine: false +# don't merge multiple statements into one line +AllowShortBlocksOnASingleLine: Never +AllowShortCaseLabelsOnASingleLine: false +AllowShortEnumsOnASingleLine: false +AllowShortIfStatementsOnASingleLine: Never +AllowShortLoopsOnASingleLine: false +# ... unless they're empty or class members, or small lambdas as args +AllowShortFunctionsOnASingleLine: Empty +AllowShortLambdasOnASingleLine: Inline + +AlwaysBreakAfterReturnType: None +AlwaysBreakBeforeMultilineStrings: true +AlwaysBreakTemplateDeclarations: Yes + +# no need to squash arguments +BinPackArguments: false +BinPackParameters: false + +# we currently use ``type name : width;'' +BitFieldColonSpacing: Both + +BreakBeforeInlineASMColon: OnlyMultiline +# start lines with operators, but don't break before the assignments +BreakBeforeBinaryOperators: NonAssignment +# we never break before braces +BreakBeforeBraces: Attach +# in general, prefer to start lines with commas, question marks, etc. +# especially for commas (in initializer lists for instance), doing it like this +# means adding and removing new entries doesn't impact unrelated entries +BreakBeforeConceptDeclarations: true +BreakBeforeTernaryOperators: true +BreakConstructorInitializers: AfterColon +BreakInheritanceList: BeforeComma + +# text being greppable is nice in languages that lack stack traces +BreakStringLiterals: false + +# it's observable and well-known that long lines are hard to read; due to the +# C++ "nesting nature" being more aggressive than C, and us using 8column tabs +# for measurement, 100 should be a safe bet +ColumnLimit: 120 +# namespace A { namespace B { ... would be silly to do in new c++ versions +CompactNamespaces: false + +# same level as class name +ConstructorInitializerIndentWidth: 8 +# one tab +ContinuationIndentWidth: 8 +# we treat braced lists like function calls, rather than blocks +Cpp11BracedListStyle: true + +# no need to guess, be consistent instead +DeriveLineEnding: false +UseCRLF: False +DerivePointerAlignment: false + +# no need for extra lines after private: +EmptyLineAfterAccessModifier: Never + +# allow grouping empty modifier blocks +EmptyLineBeforeAccessModifier: LogicalBlock +# consistent rather than guessed +ExperimentalAutoDetectBinPacking: False + +# ``namespace A {} // namespace A'' comments +FixNamespaceComments: true + +IncludeBlocks: Regroup +IncludeCategories: + - Regex: '".*.hpp"' + Priority: 0 + - Regex: '<(arch|async|bragi|core|frg|helix|protocols)/.*>' + Priority: 1 + - Regex: '<.*\.(h|hpp)>' + Priority: 2 + - Regex: '.*' + Priority: 3 +IncludeIsMainRegex: $ + +# same indent as struct/class +# (not sure what the relation with AccessModifierOffset is) +IndentAccessModifiers: false + +# switch(x) { +# case 1: { +# f(); +# } break; +# } +IndentCaseBlocks: false +IndentCaseLabels: false + +# same as namespaces +IndentExternBlock: NoIndent + +# glue to start of lines +IndentGotoLabels: false + +# add visual indentation to preprocessor blocks +IndentPPDirectives: AfterHash +IndentRequiresClause: false + +# indent by a tab character, and also use tabs for ContinuationIndentWidth +UseTab: ForContinuationAndIndentation +IndentWidth: 8 + +# if there's a need to break a function declaration after a type, don't indent +# the function name +IndentWrappedFunctionNames: false + +# InsertBraces: true + +InsertNewlineAtEOF: true + +# not sure whether this is ever useful +KeepEmptyLinesAtTheStartOfBlocks: false + +# indent bodies relative to the outer scope +LambdaBodyIndentation: OuterScope + +# at most one empty line at a time +MaxEmptyLinesToKeep: 1 + +# no indentation, no matter the level +# XXX: should we do inner only? since, for nested namespaces, we can already +# use A::B::C syntax, that could help distinguish anonymous namespaces inside +# other namespaces? +NamespaceIndentation: None + +# if initializers can't fit, break them into the next line and give each a line +PackConstructorInitializers: NextLine + +# ``T *tptr; T &tref;'', always +PointerAlignment: Right +ReferenceAlignment: Pointer + +# we put qualifiers on the west, the order is +# impacts-linking-and-optimization, impacts-optimization, type +QualifierAlignment: Custom +QualifierOrder: [constexpr, inline, static, const, volatile, restrict, type] + +# allow long comments to be reflowed +ReflowComments: true + +# keep braces around +RemoveBracesLLVM: false + +# RequiresClausePosition: OwnLine + +# give definitions blocks +SeparateDefinitionBlocks: Always + +# always add namespace comments +ShortNamespaceLines: 0 + +# sort headers without case sensitivity +SortIncludes: CaseInsensitive + +# sort using declarations +SortUsingDeclarations: true + +# self explanatory +SpaceAfterCStyleCast: true +SpaceAfterLogicalNot: false +SpaceAfterTemplateKeyword: false +SpaceAroundPointerQualifiers: Default +SpaceBeforeAssignmentOperators: true +SpaceBeforeCaseColon: false +SpaceBeforeCpp11BracedList: true +SpaceBeforeCtorInitializerColon: true +SpaceBeforeInheritanceColon: true +SpaceBeforeParens: Never +SpaceBeforeRangeBasedForLoopColon: true +SpaceBeforeSquareBrackets: false +SpaceInEmptyBlock: false +SpaceInEmptyParentheses: false +SpacesBeforeTrailingComments: 2 +SpacesInAngles: false +SpacesInCStyleCastParentheses: false +SpacesInConditionalStatement: false +SpacesInLineCommentPrefix: + Minimum: 1 + Maximum: -1 +SpacesInParentheses: false +SpacesInSquareBrackets: false +Standard: Latest + +# count tabs as eight columns +# (this does not affect editors in any way) +TabWidth: 8 +... diff --git a/.github/workflows/formatting.yml b/.github/workflows/formatting.yml new file mode 100644 index 000000000..329868c67 --- /dev/null +++ b/.github/workflows/formatting.yml @@ -0,0 +1,14 @@ +name: pre-commit + +on: [push, merge_group, pull_request] + +jobs: + pre-commit: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-python@v3 + - name: Install clang-format + run: | + pip install clang-format + - uses: pre-commit/action@v3.0.1 diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 000000000..624aa4dc2 --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,14 @@ +fail_fast: false +repos: + - repo: https://github.com/pocc/pre-commit-hooks + rev: 336fdd7c3cab698ead0b1c95157b9e74d3906b62 + hooks: + - id: clang-format + additional_dependencies: [clang-format] + args: ["-i"] + exclude: > + (?x)^( + options/ansi/musl-generic-math/.*| + options/ansi/generic/complex/.*| + options/posix/musl-generic-regex/.* + ) diff --git a/README.md b/README.md index 12db9505b..c459f9fa0 100644 --- a/README.md +++ b/README.md @@ -49,6 +49,10 @@ The type of library to be built (static, shared, or both) is controlled by meson We also support building with `-Db_sanitize=undefined` to use UBSan inside mlibc. Note that this does not enable UBSan for external applications which link against `libc.so`, but it can be useful during development to detect internal bugs (e.g when adding new sysdeps). +## Running pre-commit hooks + +To format your code before submitting a PR, you should install [`pre-commit`](https://pre-commit.com/). Then do `pre-commit install` to install the git hook which runs each time you commit. Alternatively, you can do `pre-commit run -a` to manually format all files. + ## Running Tests The `mlibc` test suite can be run under a Linux host. To do this, first install a set of kernel headers (as described [here](https://docs.kernel.org/kbuild/headers_install.html)), then run from the project root: diff --git a/options/rtld/generic/linker.cpp b/options/rtld/generic/linker.cpp index ec11f1b92..dc15530bc 100644 --- a/options/rtld/generic/linker.cpp +++ b/options/rtld/generic/linker.cpp @@ -4,22 +4,22 @@ // keep a list of optional generic relocation types enum { - R_OFFSET = (uintptr_t) -1, + R_OFFSET = (uintptr_t) -1, }; +#include "elf.hpp" +#include "linker.hpp" #include #include + +#include +#include #include #include -#include #include +#include #include -#include -#include - -#include "elf.hpp" -#include "linker.hpp" #if !MLIBC_MMAP_ALLOCATE_DSO uintptr_t libraryBase = 0x41000000; @@ -51,7 +51,8 @@ constexpr inline ptrdiff_t tlsOffsetFromTp = -0x7000; extern DebugInterface globalDebugInterface; extern uintptr_t __stack_chk_guard; -extern frg::manual_box> libraryPaths; +extern frg::manual_box> + libraryPaths; extern frg::manual_box> preloads; #if MLIBC_STATIC_BUILD @@ -82,8 +83,7 @@ bool tryReadExactly(int fd, void *data, size_t length) { size_t offset = 0; while(offset < length) { ssize_t chunk; - if(mlibc::sys_read(fd, reinterpret_cast(data) + offset, - length - offset, &chunk)) + if(mlibc::sys_read(fd, reinterpret_cast(data) + offset, length - offset, &chunk)) return false; __ensure(chunk > 0); offset += chunk; @@ -105,18 +105,24 @@ uintptr_t alignUp(uintptr_t address, size_t align) { // ObjectRepository // -------------------------------------------------------- -ObjectRepository::ObjectRepository() -: loadedObjects{getAllocator()}, - _nameMap{frg::hash{}, getAllocator()}, - _destructQueue{getAllocator()} {} +ObjectRepository::ObjectRepository() : + loadedObjects {getAllocator()}, + _nameMap {frg::hash {}, getAllocator()}, + _destructQueue {getAllocator()} {} SharedObject *ObjectRepository::injectObjectFromDts(frg::string_view name, - frg::string path, uintptr_t base_address, - elf_dyn *dynamic, uint64_t rts) { + frg::string path, + uintptr_t base_address, + elf_dyn *dynamic, + uint64_t rts) { __ensure(!findLoadedObject(name)); auto object = frg::construct(getAllocator(), - name.data(), std::move(path), false, globalScope.get(), rts); + name.data(), + std::move(path), + false, + globalScope.get(), + rts); object->baseAddress = base_address; object->dynamic = dynamic; _parseDynamic(object); @@ -128,13 +134,20 @@ SharedObject *ObjectRepository::injectObjectFromDts(frg::string_view name, } SharedObject *ObjectRepository::injectObjectFromPhdrs(frg::string_view name, - frg::string path, void *phdr_pointer, - size_t phdr_entry_size, size_t num_phdrs, void *entry_pointer, - uint64_t rts) { + frg::string path, + void *phdr_pointer, + size_t phdr_entry_size, + size_t num_phdrs, + void *entry_pointer, + uint64_t rts) { __ensure(!findLoadedObject(name)); auto object = frg::construct(getAllocator(), - name.data(), std::move(path), true, globalScope.get(), rts); + name.data(), + std::move(path), + true, + globalScope.get(), + rts); _fetchFromPhdrs(object, phdr_pointer, phdr_entry_size, num_phdrs, entry_pointer); _parseDynamic(object); @@ -145,24 +158,29 @@ SharedObject *ObjectRepository::injectObjectFromPhdrs(frg::string_view name, } SharedObject *ObjectRepository::injectStaticObject(frg::string_view name, - frg::string path, void *phdr_pointer, - size_t phdr_entry_size, size_t num_phdrs, void *entry_pointer, - uint64_t rts) { + frg::string path, + void *phdr_pointer, + size_t phdr_entry_size, + size_t num_phdrs, + void *entry_pointer, + uint64_t rts) { __ensure(!findLoadedObject(name)); auto object = frg::construct(getAllocator(), - name.data(), std::move(path), true, globalScope.get(), rts); + name.data(), + std::move(path), + true, + globalScope.get(), + rts); _fetchFromPhdrs(object, phdr_pointer, phdr_entry_size, num_phdrs, entry_pointer); #if MLIBC_STATIC_BUILD - object->initArray = reinterpret_cast(__init_array_start); - object->initArraySize = static_cast((uintptr_t)__init_array_end - - (uintptr_t)__init_array_start); - object->finiArray = reinterpret_cast(__fini_array_start); - object->finiArraySize = static_cast((uintptr_t)__fini_array_end - - (uintptr_t)__fini_array_start); - object->preInitArray = reinterpret_cast(__preinit_array_start); - object->preInitArraySize = static_cast((uintptr_t)__preinit_array_end - - (uintptr_t)__preinit_array_start); + object->initArray = reinterpret_cast(__init_array_start); + object->initArraySize = static_cast((uintptr_t) __init_array_end - (uintptr_t) __init_array_start); + object->finiArray = reinterpret_cast(__fini_array_start); + object->finiArraySize = static_cast((uintptr_t) __fini_array_end - (uintptr_t) __fini_array_start); + object->preInitArray = reinterpret_cast(__preinit_array_start); + object->preInitArraySize = + static_cast((uintptr_t) __preinit_array_end - (uintptr_t) __preinit_array_start); #endif _addLoadedObject(object); @@ -171,11 +189,14 @@ SharedObject *ObjectRepository::injectStaticObject(frg::string_view name, } frg::expected ObjectRepository::requestObjectWithName(frg::string_view name, - SharedObject *origin, Scope *localScope, bool createScope, uint64_t rts) { - if (auto obj = findLoadedObject(name)) + SharedObject *origin, + Scope *localScope, + bool createScope, + uint64_t rts) { + if(auto obj = findLoadedObject(name)) return obj; - auto tryToOpen = [&] (const char *path) { + auto tryToOpen = [&](const char *path) { int fd; if(auto x = mlibc::sys_open(path, O_RDONLY, 0, &fd); x) { return -1; @@ -185,71 +206,72 @@ frg::expected ObjectRepository::requestObjectWithNa // TODO(arsen): this process can probably undergo heavy optimization, by // preprocessing the rpath only once on parse - auto processRpath = [&] (frg::string_view path) { - frg::string sPath { getAllocator() }; - if (path.starts_with("$ORIGIN")) { + auto processRpath = [&](frg::string_view path) { + frg::string sPath {getAllocator()}; + if(path.starts_with("$ORIGIN")) { frg::string_view dirname = origin->path; auto lastsl = dirname.find_last('/'); - if (lastsl != size_t(-1)) { + if(lastsl != size_t(-1)) { dirname = dirname.sub_string(0, lastsl); } else { dirname = "."; } - sPath = frg::string{ getAllocator(), dirname }; + sPath = frg::string {getAllocator(), dirname}; sPath += path.sub_string(7, path.size() - 7); } else { - sPath = frg::string{ getAllocator(), path }; + sPath = frg::string {getAllocator(), path}; } - if (sPath[sPath.size() - 1] != '/') { + if(sPath[sPath.size() - 1] != '/') { sPath += '/'; } sPath += name; - if (logRpath) + if(logRpath) mlibc::infoLogger() << "rtld: trying in rpath " << sPath << frg::endlog; int fd = tryToOpen(sPath.data()); - if (logRpath && fd >= 0) + if(logRpath && fd >= 0) mlibc::infoLogger() << "rtld: found in rpath" << frg::endlog; - return frg::tuple { fd, std::move(sPath) }; + return frg::tuple {fd, std::move(sPath)}; }; - frg::string chosenPath { getAllocator() }; + frg::string chosenPath {getAllocator()}; int fd = -1; - if (origin && origin->runPath) { + if(origin && origin->runPath) { size_t start = 0; size_t idx = 0; - frg::string_view rpath { origin->runPath }; - auto next = [&] () { + frg::string_view rpath {origin->runPath}; + auto next = [&]() { idx = rpath.find_first(':', start); - if (idx == (size_t)-1) + if(idx == (size_t) -1) idx = rpath.size(); }; - for (next(); idx < rpath.size(); next()) { + for(next(); idx < rpath.size(); next()) { auto path = rpath.sub_string(start, idx - start); start = idx + 1; auto [fd_, fullPath] = processRpath(path); - if (fd_ != -1) { + if(fd_ != -1) { fd = fd_; chosenPath = std::move(fullPath); break; } } - if (fd == -1) { + if(fd == -1) { auto path = rpath.sub_string(start, rpath.size() - start); auto [fd_, fullPath] = processRpath(path); - if (fd_ != -1) { + if(fd_ != -1) { fd = fd_; chosenPath = std::move(fullPath); } } - } else if (logRpath) { + } else if(logRpath) { mlibc::infoLogger() << "rtld: no rpath set for object" << frg::endlog; } for(size_t i = 0; i < libraryPaths->size() && fd == -1; i++) { auto ldPath = (*libraryPaths)[i]; - auto path = frg::string{getAllocator(), ldPath} + '/' + name; + auto path = frg::string {getAllocator(), ldPath} + '/' + name; if(logLdPath) - mlibc::infoLogger() << "rtld: Trying to load " << name << " from ldpath " << ldPath << "/" << frg::endlog; + mlibc::infoLogger() + << "rtld: Trying to load " << name << " from ldpath " << ldPath << "/" << frg::endlog; fd = tryToOpen(path.data()); if(fd >= 0) { chosenPath = std::move(path); @@ -259,7 +281,7 @@ frg::expected ObjectRepository::requestObjectWithNa if(fd == -1) return LinkerError::notFound; - if (createScope) { + if(createScope) { __ensure(localScope == nullptr); // TODO: Free this when the scope is no longer needed. @@ -269,7 +291,11 @@ frg::expected ObjectRepository::requestObjectWithNa __ensure(localScope != nullptr); auto object = frg::construct(getAllocator(), - name.data(), std::move(chosenPath), false, localScope, rts); + name.data(), + std::move(chosenPath), + false, + localScope, + rts); auto result = _fetchFromFile(object, fd); closeOrDie(fd); @@ -286,18 +312,18 @@ frg::expected ObjectRepository::requestObjectWithNa return object; } -frg::expected ObjectRepository::requestObjectAtPath(frg::string_view path, - Scope *localScope, bool createScope, uint64_t rts) { +frg::expected +ObjectRepository::requestObjectAtPath(frg::string_view path, Scope *localScope, bool createScope, uint64_t rts) { // TODO: Support SONAME correctly. auto lastSlash = path.find_last('/') + 1; auto name = path; - if (!lastSlash) { + if(!lastSlash) { name = name.sub_string(lastSlash, path.size() - lastSlash); } - if (auto obj = findLoadedObject(name)) + if(auto obj = findLoadedObject(name)) return obj; - if (createScope) { + if(createScope) { __ensure(localScope == nullptr); // TODO: Free this when the scope is no longer needed. @@ -306,8 +332,7 @@ frg::expected ObjectRepository::requestObjectAtPath __ensure(localScope != nullptr); - auto object = frg::construct(getAllocator(), - name.data(), path.data(), false, localScope, rts); + auto object = frg::construct(getAllocator(), name.data(), path.data(), false, localScope, rts); frg::string no_prefix(getAllocator(), path); @@ -334,14 +359,14 @@ frg::expected ObjectRepository::requestObjectAtPath SharedObject *ObjectRepository::findCaller(void *addr) { uintptr_t target = reinterpret_cast(addr); - for (auto [name, object] : _nameMap) { + for(auto [name, object] : _nameMap) { // Search all PT_LOAD segments for the specified address. for(size_t j = 0; j < object->phdrCount; j++) { - auto phdr = (elf_phdr *)((uintptr_t)object->phdrPointer + j * object->phdrEntrySize); - if (phdr->p_type == PT_LOAD) { + auto phdr = (elf_phdr *) ((uintptr_t) object->phdrPointer + j * object->phdrEntrySize); + if(phdr->p_type == PT_LOAD) { uintptr_t start = object->baseAddress + phdr->p_vaddr; uintptr_t end = start + phdr->p_memsz; - if (start <= target && target < end) + if(start <= target && target < end) return object; } } @@ -352,12 +377,12 @@ SharedObject *ObjectRepository::findCaller(void *addr) { SharedObject *ObjectRepository::findLoadedObject(frg::string_view name) { auto it = _nameMap.get(name); - if (it) + if(it) return *it; - for (auto object : loadedObjects) { + for(auto object : loadedObjects) { // See if any object has a matching SONAME. - if (object->soName && name == object->soName) + if(object->soName && name == object->soName) return object; } @@ -372,7 +397,7 @@ void ObjectRepository::addObjectToDestructQueue(SharedObject *object) { void doDestruct(SharedObject *object); void ObjectRepository::destructObjects() { - while (_destructQueue.size() > 0) { + while(_destructQueue.size() > 0) { auto top = _destructQueue.top(); doDestruct(top); _destructQueue.pop(); @@ -383,8 +408,11 @@ void ObjectRepository::destructObjects() { // ObjectRepository: Fetching methods. // -------------------------------------------------------- -void ObjectRepository::_fetchFromPhdrs(SharedObject *object, void *phdr_pointer, - size_t phdr_entry_size, size_t phdr_count, void *entry_pointer) { +void ObjectRepository::_fetchFromPhdrs(SharedObject *object, + void *phdr_pointer, + size_t phdr_entry_size, + size_t phdr_count, + void *entry_pointer) { __ensure(object->isMainObject); object->phdrPointer = phdr_pointer; object->phdrEntrySize = phdr_entry_size; @@ -400,15 +428,15 @@ void ObjectRepository::_fetchFromPhdrs(SharedObject *object, void *phdr_pointer, // segments are already mapped, so we just have to find the dynamic section for(size_t i = 0; i < phdr_count; i++) { - auto phdr = (elf_phdr *)((uintptr_t)phdr_pointer + i * phdr_entry_size); + auto phdr = (elf_phdr *) ((uintptr_t) phdr_pointer + i * phdr_entry_size); switch(phdr->p_type) { case PT_PHDR: // Determine the executable's base address (in the PIE case) by comparing // the PHDR segment's load address against it's address in the ELF file. object->baseAddress = reinterpret_cast(phdr_pointer) - phdr->p_vaddr; if(verbose) - mlibc::infoLogger() << "rtld: Executable is loaded at " - << (void *)object->baseAddress << frg::endlog; + mlibc::infoLogger() << "rtld: Executable is loaded at " << (void *) object->baseAddress + << frg::endlog; break; case PT_DYNAMIC: dynamic_offset = phdr->p_vaddr; @@ -420,24 +448,22 @@ void ObjectRepository::_fetchFromPhdrs(SharedObject *object, void *phdr_pointer, tls_offset = phdr->p_vaddr; break; case PT_INTERP: - object->interpreterPath = frg::string{ - (char*)(object->baseAddress + phdr->p_vaddr), - getAllocator() - }; + object->interpreterPath = + frg::string {(char *) (object->baseAddress + phdr->p_vaddr), + getAllocator()}; } break; default: - //FIXME warn about unknown phdrs + // FIXME warn about unknown phdrs break; } } if(dynamic_offset) - object->dynamic = (elf_dyn *)(object->baseAddress + *dynamic_offset); + object->dynamic = (elf_dyn *) (object->baseAddress + *dynamic_offset); if(tls_offset) - object->tlsImagePtr = (void *)(object->baseAddress + *tls_offset); + object->tlsImagePtr = (void *) (object->baseAddress + *tls_offset); } - frg::expected ObjectRepository::_fetchFromFile(SharedObject *object, int fd) { __ensure(!object->isMainObject); @@ -446,19 +472,15 @@ frg::expected ObjectRepository::_fetchFromFile(SharedObject * if(!tryReadExactly(fd, &ehdr, sizeof(elf_ehdr))) return LinkerError::fileTooShort; - if(ehdr.e_ident[0] != 0x7F - || ehdr.e_ident[1] != 'E' - || ehdr.e_ident[2] != 'L' - || ehdr.e_ident[3] != 'F') + if(ehdr.e_ident[0] != 0x7F || ehdr.e_ident[1] != 'E' || ehdr.e_ident[2] != 'L' || ehdr.e_ident[3] != 'F') return LinkerError::notElf; - if((ehdr.e_type != ET_EXEC && ehdr.e_type != ET_DYN) - || ehdr.e_machine != ELF_MACHINE - || ehdr.e_ident[EI_CLASS] != ELF_CLASS) + if((ehdr.e_type != ET_EXEC && ehdr.e_type != ET_DYN) || ehdr.e_machine != ELF_MACHINE + || ehdr.e_ident[EI_CLASS] != ELF_CLASS) return LinkerError::wrongElfType; // read the elf program headers - auto phdr_buffer = (char *)getAllocator().allocate(ehdr.e_phnum * ehdr.e_phentsize); + auto phdr_buffer = (char *) getAllocator().allocate(ehdr.e_phnum * ehdr.e_phentsize); if(!phdr_buffer) return LinkerError::outOfMemory; @@ -480,7 +502,7 @@ frg::expected ObjectRepository::_fetchFromFile(SharedObject * uintptr_t highest_address = 0; for(int i = 0; i < ehdr.e_phnum; i++) { - auto phdr = (elf_phdr *)(phdr_buffer + i * ehdr.e_phentsize); + auto phdr = (elf_phdr *) (phdr_buffer + i * ehdr.e_phentsize); if(phdr->p_type != PT_LOAD) continue; @@ -497,14 +519,17 @@ frg::expected ObjectRepository::_fetchFromFile(SharedObject * #if MLIBC_MMAP_ALLOCATE_DSO void *mappedAddr = nullptr; - if (mlibc::sys_vm_map(nullptr, - highest_address - object->baseAddress, PROT_NONE, - MAP_PRIVATE | MAP_ANONYMOUS, -1, 0, &mappedAddr)) { - mlibc::infoLogger() << "sys_vm_map failed when allocating address space for DSO \"" - << object->name << "\"" - << ", base " << (void *)object->baseAddress - << ", requested " << (highest_address - object->baseAddress) << " bytes" - << frg::endlog; + if(mlibc::sys_vm_map(nullptr, + highest_address - object->baseAddress, + PROT_NONE, + MAP_PRIVATE | MAP_ANONYMOUS, + -1, + 0, + &mappedAddr)) { + mlibc::infoLogger() << "sys_vm_map failed when allocating address space for DSO \"" << object->name + << "\"" + << ", base " << (void *) object->baseAddress << ", requested " + << (highest_address - object->baseAddress) << " bytes" << frg::endlog; getAllocator().deallocate(phdr_buffer, ehdr.e_phnum * ehdr.e_phentsize); return LinkerError::outOfMemory; } @@ -516,13 +541,13 @@ frg::expected ObjectRepository::_fetchFromFile(SharedObject * #endif if(verbose || logBaseAddresses) - mlibc::infoLogger() << "rtld: Loading " << object->name - << " at " << (void *)object->baseAddress << frg::endlog; + mlibc::infoLogger() << "rtld: Loading " << object->name << " at " << (void *) object->baseAddress + << frg::endlog; // Load all segments. constexpr size_t pageSize = 0x1000; for(int i = 0; i < ehdr.e_phnum; i++) { - auto phdr = (elf_phdr *)(phdr_buffer + i * ehdr.e_phentsize); + auto phdr = (elf_phdr *) (phdr_buffer + i * ehdr.e_phentsize); if(phdr->p_type == PT_LOAD) { size_t misalign = phdr->p_vaddr & (pageSize - 1); @@ -546,64 +571,71 @@ frg::expected ObjectRepository::_fetchFromFile(SharedObject * if(phdr->p_flags & PF_X) prot |= PROT_EXEC; - #if MLIBC_MAP_DSO_SEGMENTS - void *map_pointer; - if(mlibc::sys_vm_map(reinterpret_cast(map_address), - backed_map_size, prot | PROT_WRITE, - MAP_PRIVATE | MAP_FIXED, fd, phdr->p_offset - misalign, &map_pointer)) - __ensure(!"sys_vm_map failed"); - if(total_map_size > backed_map_size) - if(mlibc::sys_vm_map(reinterpret_cast(map_address + backed_map_size), - total_map_size - backed_map_size, prot | PROT_WRITE, - MAP_PRIVATE | MAP_FIXED | MAP_ANONYMOUS, -1, 0, &map_pointer)) - __ensure(!"sys_vm_map failed"); - - if(mlibc::sys_vm_readahead) - if(mlibc::sys_vm_readahead(reinterpret_cast(map_address), - backed_map_size)) - mlibc::infoLogger() << "mlibc: sys_vm_readahead() failed in ld.so" - << frg::endlog; - - // Clear the trailing area at the end of the backed mapping. - // We do not clear the leading area; programs are not supposed to access it. - memset(reinterpret_cast(map_address + misalign + phdr->p_filesz), - 0, phdr->p_memsz - phdr->p_filesz); - #else - (void)backed_map_size; - - void *map_pointer; - if(mlibc::sys_vm_map(reinterpret_cast(map_address), - total_map_size, prot | PROT_WRITE, - MAP_PRIVATE | MAP_FIXED | MAP_ANONYMOUS, -1, 0, &map_pointer)) +#if MLIBC_MAP_DSO_SEGMENTS + void *map_pointer; + if(mlibc::sys_vm_map(reinterpret_cast(map_address), + backed_map_size, + prot | PROT_WRITE, + MAP_PRIVATE | MAP_FIXED, + fd, + phdr->p_offset - misalign, + &map_pointer)) + __ensure(!"sys_vm_map failed"); + if(total_map_size > backed_map_size) + if(mlibc::sys_vm_map(reinterpret_cast(map_address + backed_map_size), + total_map_size - backed_map_size, + prot | PROT_WRITE, + MAP_PRIVATE | MAP_FIXED | MAP_ANONYMOUS, + -1, + 0, + &map_pointer)) __ensure(!"sys_vm_map failed"); - __ensure(trySeek(fd, phdr->p_offset)); - __ensure(tryReadExactly(fd, reinterpret_cast(map_address) + misalign, - phdr->p_filesz)); - #endif + if(mlibc::sys_vm_readahead) + if(mlibc::sys_vm_readahead(reinterpret_cast(map_address), backed_map_size)) + mlibc::infoLogger() + << "mlibc: sys_vm_readahead() failed in ld.so" << frg::endlog; + + // Clear the trailing area at the end of the backed mapping. + // We do not clear the leading area; programs are not supposed to access it. + memset(reinterpret_cast(map_address + misalign + phdr->p_filesz), + 0, + phdr->p_memsz - phdr->p_filesz); +#else + (void) backed_map_size; + + void *map_pointer; + if(mlibc::sys_vm_map(reinterpret_cast(map_address), + total_map_size, + prot | PROT_WRITE, + MAP_PRIVATE | MAP_FIXED | MAP_ANONYMOUS, + -1, + 0, + &map_pointer)) + __ensure(!"sys_vm_map failed"); + + __ensure(trySeek(fd, phdr->p_offset)); + __ensure(tryReadExactly(fd, reinterpret_cast(map_address) + misalign, phdr->p_filesz)); +#endif // Take care of removing superfluous permissions. if(mlibc::sys_vm_protect && ((prot & PROT_WRITE) == 0)) if(mlibc::sys_vm_protect(map_pointer, total_map_size, prot)) mlibc::infoLogger() << "mlibc: sys_vm_protect() failed in ld.so" << frg::endlog; - }else if(phdr->p_type == PT_TLS) { + } else if(phdr->p_type == PT_TLS) { object->tlsSegmentSize = phdr->p_memsz; object->tlsAlignment = phdr->p_align; object->tlsImageSize = phdr->p_filesz; - object->tlsImagePtr = (void *)(object->baseAddress + phdr->p_vaddr); - }else if(phdr->p_type == PT_DYNAMIC) { - object->dynamic = (elf_dyn *)(object->baseAddress + phdr->p_vaddr); - }else if(phdr->p_type == PT_INTERP - || phdr->p_type == PT_PHDR - || phdr->p_type == PT_NOTE - || phdr->p_type == PT_RISCV_ATTRIBUTES - || phdr->p_type == PT_GNU_EH_FRAME - || phdr->p_type == PT_GNU_RELRO - || phdr->p_type == PT_GNU_STACK - || phdr->p_type == PT_GNU_PROPERTY) { + object->tlsImagePtr = (void *) (object->baseAddress + phdr->p_vaddr); + } else if(phdr->p_type == PT_DYNAMIC) { + object->dynamic = (elf_dyn *) (object->baseAddress + phdr->p_vaddr); + } else if(phdr->p_type == PT_INTERP || phdr->p_type == PT_PHDR || phdr->p_type == PT_NOTE + || phdr->p_type == PT_RISCV_ATTRIBUTES || phdr->p_type == PT_GNU_EH_FRAME + || phdr->p_type == PT_GNU_RELRO || phdr->p_type == PT_GNU_STACK + || phdr->p_type == PT_GNU_PROPERTY) { // ignore the phdr - }else{ - mlibc::panicLogger() << "Unexpected PHDR type 0x" - << frg::hex_fmt(phdr->p_type) << " in DSO " << object->name << frg::endlog; + } else { + mlibc::panicLogger() << "Unexpected PHDR type 0x" << frg::hex_fmt(phdr->p_type) << " in DSO " + << object->name << frg::endlog; } } @@ -616,8 +648,8 @@ frg::expected ObjectRepository::_fetchFromFile(SharedObject * void ObjectRepository::_parseDynamic(SharedObject *object) { if(!object->dynamic) - mlibc::infoLogger() << "ldso: Object '" << object->name - << "' does not have a dynamic section" << frg::endlog; + mlibc::infoLogger() << "ldso: Object '" << object->name << "' does not have a dynamic section" + << frg::endlog; __ensure(object->dynamic); // Fix up these offsets to addresses after the loop, since the @@ -643,7 +675,7 @@ void ObjectRepository::_parseDynamic(SharedObject *object) { object->stringTableOffset = dynamic->d_un.d_ptr; break; case DT_STRSZ: - break; // we don't need the size of the string table + break; // we don't need the size of the string table case DT_SYMTAB: object->symbolTableOffset = dynamic->d_un.d_ptr; break; @@ -652,8 +684,7 @@ void ObjectRepository::_parseDynamic(SharedObject *object) { break; // handle lazy relocation table case DT_PLTGOT: - object->globalOffsetTable = (void **)(object->baseAddress - + dynamic->d_un.d_ptr); + object->globalOffsetTable = (void **) (object->baseAddress + dynamic->d_un.d_ptr); break; case DT_JMPREL: object->lazyRelocTableOffset = dynamic->d_un.d_ptr; @@ -664,7 +695,7 @@ void ObjectRepository::_parseDynamic(SharedObject *object) { case DT_PLTREL: if(dynamic->d_un.d_val == DT_RELA) { object->lazyExplicitAddend = true; - }else{ + } else { __ensure(dynamic->d_un.d_val == DT_REL); object->lazyExplicitAddend = false; } @@ -693,9 +724,9 @@ void ObjectRepository::_parseDynamic(SharedObject *object) { mlibc::panicLogger() << "\e[31mrtld: DF_TEXTREL is unimplemented" << frg::endlog; #endif if(dynamic->d_un.d_val & ~ignored) - mlibc::infoLogger() << "\e[31mrtld: DT_FLAGS(" << frg::hex_fmt{dynamic->d_un.d_val & ~ignored} - << ") is not implemented correctly!\e[39m" - << frg::endlog; + mlibc::infoLogger() + << "\e[31mrtld: DT_FLAGS(" << frg::hex_fmt {dynamic->d_un.d_val & ~ignored} + << ") is not implemented correctly!\e[39m" << frg::endlog; } break; case DT_FLAGS_1: if(dynamic->d_un.d_val & DF_1_NOW) @@ -704,12 +735,11 @@ void ObjectRepository::_parseDynamic(SharedObject *object) { // The DF_1_NODELETE flag has a similar effect to RTLD_NODELETE, both of which we // ignore because we don't implement dlclose(). if(dynamic->d_un.d_val & ~(DF_1_NOW | DF_1_PIE | DF_1_NODELETE)) - mlibc::infoLogger() << "\e[31mrtld: DT_FLAGS_1(" << frg::hex_fmt{dynamic->d_un.d_val} - << ") is not implemented correctly!\e[39m" - << frg::endlog; + mlibc::infoLogger() << "\e[31mrtld: DT_FLAGS_1(" << frg::hex_fmt {dynamic->d_un.d_val} + << ") is not implemented correctly!\e[39m" << frg::endlog; break; case DT_RPATH: - if (runpath_found) { + if(runpath_found) { /* Ignore RPATH if RUNPATH was present. */ break; } @@ -720,19 +750,19 @@ void ObjectRepository::_parseDynamic(SharedObject *object) { break; case DT_INIT: if(dynamic->d_un.d_ptr != 0) - object->initPtr = (InitFuncPtr)(object->baseAddress + dynamic->d_un.d_ptr); + object->initPtr = (InitFuncPtr) (object->baseAddress + dynamic->d_un.d_ptr); break; case DT_FINI: if(dynamic->d_un.d_ptr != 0) - object->finiPtr = (InitFuncPtr)(object->baseAddress + dynamic->d_un.d_ptr); + object->finiPtr = (InitFuncPtr) (object->baseAddress + dynamic->d_un.d_ptr); break; case DT_INIT_ARRAY: if(dynamic->d_un.d_ptr != 0) - object->initArray = (InitFuncPtr *)(object->baseAddress + dynamic->d_un.d_ptr); + object->initArray = (InitFuncPtr *) (object->baseAddress + dynamic->d_un.d_ptr); break; case DT_FINI_ARRAY: if(dynamic->d_un.d_ptr != 0) - object->finiArray = (InitFuncPtr *)(object->baseAddress + dynamic->d_un.d_ptr); + object->finiArray = (InitFuncPtr *) (object->baseAddress + dynamic->d_un.d_ptr); break; case DT_INIT_ARRAYSZ: object->initArraySize = dynamic->d_un.d_val; @@ -744,7 +774,7 @@ void ObjectRepository::_parseDynamic(SharedObject *object) { if(dynamic->d_un.d_ptr != 0) { // Only the main object is allowed pre-initializers. __ensure(object->isMainObject); - object->preInitArray = (InitFuncPtr *)(object->baseAddress + dynamic->d_un.d_ptr); + object->preInitArray = (InitFuncPtr *) (object->baseAddress + dynamic->d_un.d_ptr); } break; case DT_PREINIT_ARRAYSZ: @@ -763,44 +793,54 @@ void ObjectRepository::_parseDynamic(SharedObject *object) { soname_offset = dynamic->d_un.d_val; break; // ignore unimportant tags - case DT_NEEDED: // we handle this later - case DT_RELA: case DT_RELASZ: case DT_RELAENT: case DT_RELACOUNT: - case DT_REL: case DT_RELSZ: case DT_RELENT: case DT_RELCOUNT: - case DT_RELR: case DT_RELRSZ: case DT_RELRENT: + case DT_NEEDED: // we handle this later + case DT_RELA: + case DT_RELASZ: + case DT_RELAENT: + case DT_RELACOUNT: + case DT_REL: + case DT_RELSZ: + case DT_RELENT: + case DT_RELCOUNT: + case DT_RELR: + case DT_RELRSZ: + case DT_RELRENT: case DT_VERSYM: - case DT_VERDEF: case DT_VERDEFNUM: - case DT_VERNEED: case DT_VERNEEDNUM: + case DT_VERDEF: + case DT_VERDEFNUM: + case DT_VERNEED: + case DT_VERNEEDNUM: #ifdef __riscv - case DT_TEXTREL: // Work around https://sourceware.org/bugzilla/show_bug.cgi?id=24673. + case DT_TEXTREL: // Work around https://sourceware.org/bugzilla/show_bug.cgi?id=24673. #endif break; - case DT_TLSDESC_PLT: case DT_TLSDESC_GOT: + case DT_TLSDESC_PLT: + case DT_TLSDESC_GOT: break; default: // Ignore unknown entries in the os-specific area as we don't use them. if(dynamic->d_tag < DT_LOOS || dynamic->d_tag > DT_HIOS) { - mlibc::panicLogger() << "Unexpected dynamic entry " - << (void *)dynamic->d_tag << " in object" << frg::endlog; + mlibc::panicLogger() << "Unexpected dynamic entry " << (void *) dynamic->d_tag + << " in object" << frg::endlog; } } } if(runpath_offset) { - object->runPath = reinterpret_cast(object->baseAddress - + object->stringTableOffset + *runpath_offset); + object->runPath = reinterpret_cast( + object->baseAddress + object->stringTableOffset + *runpath_offset); } if(soname_offset) { - object->soName = reinterpret_cast(object->baseAddress - + object->stringTableOffset + *soname_offset); + object->soName = reinterpret_cast( + object->baseAddress + object->stringTableOffset + *soname_offset); } } -void ObjectRepository::_discoverDependencies(SharedObject *object, - Scope *localScope, uint64_t rts) { +void ObjectRepository::_discoverDependencies(SharedObject *object, Scope *localScope, uint64_t rts) { if(object->isMainObject) { for(auto preload : *preloads) { frg::expected libraryResult; - if (preload.find_first('/') == size_t(-1)) { + if(preload.find_first('/') == size_t(-1)) { libraryResult = requestObjectWithName(preload, object, globalScope.get(), false, 1); } else { libraryResult = requestObjectAtPath(preload, globalScope.get(), false, 1); @@ -821,11 +861,10 @@ void ObjectRepository::_discoverDependencies(SharedObject *object, if(dynamic->d_tag != DT_NEEDED) continue; - const char *library_str = (const char *)(object->baseAddress - + object->stringTableOffset + dynamic->d_un.d_val); + const char *library_str = + (const char *) (object->baseAddress + object->stringTableOffset + dynamic->d_un.d_val); - auto library = requestObjectWithName(frg::string_view{library_str}, - object, localScope, false, rts); + auto library = requestObjectWithName(frg::string_view {library_str}, object, localScope, false, rts); if(!library) mlibc::panicLogger() << "Could not satisfy dependency " << library_str << frg::endlog; object->dependencies.push(library.value()); @@ -841,58 +880,89 @@ void ObjectRepository::_addLoadedObject(SharedObject *object) { // SharedObject // -------------------------------------------------------- -SharedObject::SharedObject(const char *name, frg::string path, - bool is_main_object, Scope *local_scope, uint64_t object_rts) - : name(name, getAllocator()), path(std::move(path)), - interpreterPath(getAllocator()), soName(nullptr), - isMainObject(is_main_object), objectRts(object_rts), inLinkMap(false), - baseAddress(0), localScope(local_scope), dynamic(nullptr), - globalOffsetTable(nullptr), entry(nullptr), tlsSegmentSize(0), - tlsAlignment(0), tlsImageSize(0), tlsImagePtr(nullptr), - tlsInitialized(false), hashTableOffset(0), symbolTableOffset(0), - stringTableOffset(0), lazyRelocTableOffset(0), lazyTableSize(0), - lazyExplicitAddend(false), symbolicResolution(false), - eagerBinding(false), haveStaticTls(false), - dependencies(getAllocator()), tlsModel(TlsModel::null), - tlsOffset(0), globalRts(0), wasLinked(false), - scheduledForInit(false), onInitStack(false), - wasInitialized(false) { } - -SharedObject::SharedObject(const char *name, const char *path, - bool is_main_object, Scope *localScope, uint64_t object_rts) - : SharedObject(name, - frg::string { path, getAllocator() }, - is_main_object, localScope, object_rts) {} +SharedObject::SharedObject(const char *name, + frg::string path, + bool is_main_object, + Scope *local_scope, + uint64_t object_rts) : + name(name, getAllocator()), + path(std::move(path)), + interpreterPath(getAllocator()), + soName(nullptr), + isMainObject(is_main_object), + objectRts(object_rts), + inLinkMap(false), + baseAddress(0), + localScope(local_scope), + dynamic(nullptr), + globalOffsetTable(nullptr), + entry(nullptr), + tlsSegmentSize(0), + tlsAlignment(0), + tlsImageSize(0), + tlsImagePtr(nullptr), + tlsInitialized(false), + hashTableOffset(0), + symbolTableOffset(0), + stringTableOffset(0), + lazyRelocTableOffset(0), + lazyTableSize(0), + lazyExplicitAddend(false), + symbolicResolution(false), + eagerBinding(false), + haveStaticTls(false), + dependencies(getAllocator()), + tlsModel(TlsModel::null), + tlsOffset(0), + globalRts(0), + wasLinked(false), + scheduledForInit(false), + onInitStack(false), + wasInitialized(false) {} + +SharedObject::SharedObject(const char *name, + const char *path, + bool is_main_object, + Scope *localScope, + uint64_t object_rts) : + SharedObject(name, + frg::string {path, getAllocator()}, + is_main_object, + localScope, + object_rts) {} void processLateRelocation(Relocation rel) { // resolve the symbol if there is a symbol frg::optional p; if(rel.symbol_index()) { - auto symbol = (elf_sym *)(rel.object()->baseAddress + rel.object()->symbolTableOffset - + rel.symbol_index() * sizeof(elf_sym)); + auto symbol = (elf_sym *) (rel.object()->baseAddress + rel.object()->symbolTableOffset + + rel.symbol_index() * sizeof(elf_sym)); ObjectSymbol r(rel.object(), symbol); - p = Scope::resolveGlobalOrLocal(*globalScope, rel.object()->localScope, - r.getString(), rel.object()->objectRts, Scope::resolveCopy); + p = Scope::resolveGlobalOrLocal(*globalScope, + rel.object()->localScope, + r.getString(), + rel.object()->objectRts, + Scope::resolveCopy); } switch(rel.type()) { case R_COPY: __ensure(p); - memcpy(rel.destination(), (void *)p->virtualAddress(), p->symbol()->st_size); + memcpy(rel.destination(), (void *) p->virtualAddress(), p->symbol()->st_size); break; // TODO: R_IRELATIVE also exists on other architectures but will likely need a different implementation. #if defined(__x86_64__) || defined(__i386__) case R_IRELATIVE: { uintptr_t addr = rel.object()->baseAddress + rel.addend_rel(); - auto* fn = reinterpret_cast(addr); + auto *fn = reinterpret_cast(addr); rel.relocate(fn()); } break; #elif defined(__aarch64__) case R_IRELATIVE: { uintptr_t addr = rel.object()->baseAddress + rel.addend_rel(); - auto* fn = reinterpret_cast(addr); + auto *fn = reinterpret_cast(addr); // TODO: the function should get passed AT_HWCAP value. rel.relocate(fn(0)); } break; @@ -937,17 +1007,17 @@ void processLateRelocations(SharedObject *object) { if(rela_offset && rela_length) { for(size_t offset = 0; offset < *rela_length; offset += sizeof(elf_rela)) { - auto reloc = (elf_rela *)(object->baseAddress + *rela_offset + offset); + auto reloc = (elf_rela *) (object->baseAddress + *rela_offset + offset); auto r = Relocation(object, reloc); processLateRelocation(r); } } else if(rel_offset && rel_length) { for(size_t offset = 0; offset < *rel_length; offset += sizeof(elf_rel)) { - auto reloc = (elf_rel *)(object->baseAddress + *rel_offset + offset); + auto reloc = (elf_rel *) (object->baseAddress + *rel_offset + offset); auto r = Relocation(object, reloc); processLateRelocation(r); } - }else{ + } else { __ensure(!rela_offset && !rela_length); __ensure(!rel_offset && !rel_length); } @@ -1003,8 +1073,7 @@ void doDestruct(SharedObject *object) { // RuntimeTlsMap // -------------------------------------------------------- -RuntimeTlsMap::RuntimeTlsMap() -: initialPtr{0}, initialLimit{0}, indices{getAllocator()} { } +RuntimeTlsMap::RuntimeTlsMap() : initialPtr {0}, initialLimit {0}, indices {getAllocator()} {} void initTlsObjects(Tcb *tcb, const frg::vector &objects, bool checkInitialized) { // Initialize TLS segments that follow the static model. @@ -1016,19 +1085,19 @@ void initTlsObjects(Tcb *tcb, const frg::vector char *tcb_ptr = reinterpret_cast(tcb); auto tls_ptr = tcb_ptr + object->tlsOffset; - if constexpr (tlsAboveTp) { + if constexpr(tlsAboveTp) { tls_ptr += sizeof(Tcb); } memset(tls_ptr, 0, object->tlsSegmentSize); memcpy(tls_ptr, object->tlsImagePtr, object->tlsImageSize); - if (verbose) { - mlibc::infoLogger() << "rtld: wrote tls image at " << (void *)tls_ptr - << ", size = 0x" << frg::hex_fmt{object->tlsSegmentSize} << frg::endlog; + if(verbose) { + mlibc::infoLogger() << "rtld: wrote tls image at " << (void *) tls_ptr << ", size = 0x" + << frg::hex_fmt {object->tlsSegmentSize} << frg::endlog; } - if (checkInitialized) + if(checkInitialized) object->tlsInitialized = true; } } @@ -1045,14 +1114,14 @@ Tcb *allocateTcb() { memset(reinterpret_cast(allocation), 0, allocSize); uintptr_t tlsAddress, tcbAddress; - if constexpr (tlsAboveTp) { + if constexpr(tlsAboveTp) { // Here we must satisfy two requirements of the TCB and the TLS data: // 1. One should follow the other immediately in memory. We do this so that // we can simply add or subtract sizeof(Tcb) to obtain the address of the other. // 2. Both should be sufficiently aligned. // To do this, we will fix whichever address has stricter alignment requirements, and // derive the other from it. - if (tlsMaxAlignment > alignof(Tcb)) { + if(tlsMaxAlignment > alignof(Tcb)) { tlsAddress = alignUp(allocation + sizeof(Tcb), tlsMaxAlignment); tcbAddress = tlsAddress - sizeof(Tcb); } else { @@ -1068,14 +1137,14 @@ Tcb *allocateTcb() { } __ensure((tcbAddress & (alignof(Tcb) - 1)) == 0); - if (verbose) { - mlibc::infoLogger() << "rtld: tcb allocated at " << (void *)tcbAddress - << ", size = 0x" << frg::hex_fmt{sizeof(Tcb)} << frg::endlog; - mlibc::infoLogger() << "rtld: tls allocated at " << (void *)tlsAddress - << ", size = 0x" << frg::hex_fmt{tlsInitialSize} << frg::endlog; + if(verbose) { + mlibc::infoLogger() << "rtld: tcb allocated at " << (void *) tcbAddress << ", size = 0x" + << frg::hex_fmt {sizeof(Tcb)} << frg::endlog; + mlibc::infoLogger() << "rtld: tls allocated at " << (void *) tlsAddress << ", size = 0x" + << frg::hex_fmt {tlsInitialSize} << frg::endlog; } - Tcb *tcb_ptr = new ((char *)tcbAddress) Tcb; + Tcb *tcb_ptr = new((char *) tcbAddress) Tcb; tcb_ptr->selfPointer = tcb_ptr; tcb_ptr->stackCanary = __stack_chk_guard; @@ -1092,7 +1161,7 @@ Tcb *allocateTcb() { if(object->tlsModel != TlsModel::initial) continue; - if constexpr (tlsAboveTp) { + if constexpr(tlsAboveTp) { tcb_ptr->dtvPointers[i] = reinterpret_cast(tcb_ptr) + sizeof(Tcb) + object->tlsOffset; } else { tcb_ptr->dtvPointers[i] = reinterpret_cast(tcb_ptr) + object->tlsOffset; @@ -1126,37 +1195,35 @@ void *accessDtv(SharedObject *object) { memcpy(buffer, object->tlsImagePtr, object->tlsImageSize); tcb_ptr->dtvPointers[object->tlsIndex] = buffer; - if (verbose) { - mlibc::infoLogger() << "rtld: accessDtv wrote tls image at " << buffer - << ", size = 0x" << frg::hex_fmt{object->tlsSegmentSize} << frg::endlog; + if(verbose) { + mlibc::infoLogger() << "rtld: accessDtv wrote tls image at " << buffer << ", size = 0x" + << frg::hex_fmt {object->tlsSegmentSize} << frg::endlog; } } - return (void *)((char *)tcb_ptr->dtvPointers[object->tlsIndex] + TLS_DTV_OFFSET); + return (void *) ((char *) tcb_ptr->dtvPointers[object->tlsIndex] + TLS_DTV_OFFSET); } void *tryAccessDtv(SharedObject *object) { Tcb *tcb_ptr = mlibc::get_current_tcb(); - if (object->tlsIndex >= tcb_ptr->dtvSize) + if(object->tlsIndex >= tcb_ptr->dtvSize) return nullptr; - if (!tcb_ptr->dtvPointers[object->tlsIndex]) + if(!tcb_ptr->dtvPointers[object->tlsIndex]) return nullptr; - return (void *)((char *)tcb_ptr->dtvPointers[object->tlsIndex] + TLS_DTV_OFFSET); + return (void *) ((char *) tcb_ptr->dtvPointers[object->tlsIndex] + TLS_DTV_OFFSET); } // -------------------------------------------------------- // ObjectSymbol // -------------------------------------------------------- -ObjectSymbol::ObjectSymbol(SharedObject *object, const elf_sym *symbol) -: _object(object), _symbol(symbol) { } +ObjectSymbol::ObjectSymbol(SharedObject *object, const elf_sym *symbol) : _object(object), _symbol(symbol) {} const char *ObjectSymbol::getString() { __ensure(_symbol->st_name != 0); - return (const char *)(_object->baseAddress - + _object->stringTableOffset + _symbol->st_name); + return (const char *) (_object->baseAddress + _object->stringTableOffset + _symbol->st_name); } uintptr_t ObjectSymbol::virtualAddress() { @@ -1174,7 +1241,7 @@ uint32_t elf64Hash(frg::string_view string) { uint32_t h = 0, g; for(size_t i = 0; i < string.size(); ++i) { - h = (h << 4) + (uint32_t)string[i]; + h = (h << 4) + (uint32_t) string[i]; g = h & 0xF0000000; if(g) h ^= g >> 24; @@ -1185,16 +1252,16 @@ uint32_t elf64Hash(frg::string_view string) { } uint32_t gnuHash(frg::string_view string) { - uint32_t h = 5381; + uint32_t h = 5381; for(size_t i = 0; i < string.size(); ++i) - h = (h << 5) + h + string[i]; - return h; + h = (h << 5) + h + string[i]; + return h; } // TODO: move this to some namespace or class? frg::optional resolveInObject(SharedObject *object, frg::string_view string) { // Checks if the symbol can be used to satisfy the dependency. - auto eligible = [&] (ObjectSymbol cand) { + auto eligible = [&](ObjectSymbol cand) { if(cand.symbol()->st_shndx == SHN_UNDEF) return false; @@ -1205,23 +1272,24 @@ frg::optional resolveInObject(SharedObject *object, frg::string_vi return true; }; - if (object->hashStyle == HashStyle::systemV) { - auto hash_table = (Elf64_Word *)(object->baseAddress + object->hashTableOffset); + if(object->hashStyle == HashStyle::systemV) { + auto hash_table = (Elf64_Word *) (object->baseAddress + object->hashTableOffset); Elf64_Word num_buckets = hash_table[0]; auto bucket = elf64Hash(string) % num_buckets; auto index = hash_table[2 + bucket]; while(index != 0) { - ObjectSymbol cand{object, (elf_sym *)(object->baseAddress - + object->symbolTableOffset + index * sizeof(elf_sym))}; - if(eligible(cand) && frg::string_view{cand.getString()} == string) + ObjectSymbol cand {object, + (elf_sym *) (object->baseAddress + object->symbolTableOffset + + index * sizeof(elf_sym))}; + if(eligible(cand) && frg::string_view {cand.getString()} == string) return cand; index = hash_table[2 + num_buckets + index]; } - return frg::optional{}; - }else{ + return frg::optional {}; + } else { __ensure(object->hashStyle == HashStyle::gnu); struct GnuTable { @@ -1231,15 +1299,13 @@ frg::optional resolveInObject(SharedObject *object, frg::string_vi uint32_t bloomShift; }; - auto hash_table = reinterpret_cast(object->baseAddress - + object->hashTableOffset); - auto buckets = reinterpret_cast(object->baseAddress - + object->hashTableOffset + sizeof(GnuTable) - + hash_table->bloomSize * sizeof(elf_addr)); - auto chains = reinterpret_cast(object->baseAddress - + object->hashTableOffset + sizeof(GnuTable) - + hash_table->bloomSize * sizeof(elf_addr) - + hash_table->nBuckets * sizeof(uint32_t)); + auto hash_table = reinterpret_cast(object->baseAddress + object->hashTableOffset); + auto buckets = reinterpret_cast(object->baseAddress + object->hashTableOffset + + sizeof(GnuTable) + + hash_table->bloomSize * sizeof(elf_addr)); + auto chains = reinterpret_cast( + object->baseAddress + object->hashTableOffset + sizeof(GnuTable) + + hash_table->bloomSize * sizeof(elf_addr) + hash_table->nBuckets * sizeof(uint32_t)); // TODO: Use the bloom filter. @@ -1248,41 +1314,41 @@ frg::optional resolveInObject(SharedObject *object, frg::string_vi auto index = buckets[hash % hash_table->nBuckets]; if(!index) - return frg::optional{}; + return frg::optional {}; while(true) { // chains[] contains an array of hashes, parallel to the symbol table. auto chash = chains[index - hash_table->symbolOffset]; - if ((chash & ~1) == (hash & ~1)) { - ObjectSymbol cand{object, (elf_sym *)(object->baseAddress - + object->symbolTableOffset + index * sizeof(elf_sym))}; - if(eligible(cand) && frg::string_view{cand.getString()} == string) + if((chash & ~1) == (hash & ~1)) { + ObjectSymbol cand {object, + (elf_sym *) (object->baseAddress + object->symbolTableOffset + + index * sizeof(elf_sym))}; + if(eligible(cand) && frg::string_view {cand.getString()} == string) return cand; } // If we hit the end of the chain, the symbol is not present. if(chash & 1) - return frg::optional{}; + return frg::optional {}; index++; } } } -frg::optional Scope::_resolveNext(frg::string_view string, - SharedObject *target) { +frg::optional Scope::_resolveNext(frg::string_view string, SharedObject *target) { // Skip objects until we find the target, and only look for symbols after that. size_t i; - for (i = 0; i < _objects.size(); i++) { - if (_objects[i] == target) + for(i = 0; i < _objects.size(); i++) { + if(_objects[i] == target) break; } - if (i == _objects.size()) { + if(i == _objects.size()) { mlibc::infoLogger() << "rtld: object passed to Scope::resolveAfter was not found" << frg::endlog; return frg::optional(); } - for (i = i + 1; i < _objects.size(); i++) { + for(i = i + 1; i < _objects.size(); i++) { if(_objects[i]->isMainObject) continue; @@ -1294,13 +1360,12 @@ frg::optional Scope::_resolveNext(frg::string_view string, return frg::optional(); } -Scope::Scope(bool isGlobal) -: isGlobal{isGlobal}, _objects(getAllocator()) { } +Scope::Scope(bool isGlobal) : isGlobal {isGlobal}, _objects(getAllocator()) {} void Scope::appendObject(SharedObject *object) { // Don't insert duplicates. - for (auto obj : _objects) { - if (obj == object) + for(auto obj : _objects) { + if(obj == object) return; } @@ -1308,15 +1373,18 @@ void Scope::appendObject(SharedObject *object) { } frg::optional Scope::resolveGlobalOrLocal(Scope &globalScope, - Scope *localScope, frg::string_view string, uint64_t skipRts, ResolveFlags flags) { + Scope *localScope, + frg::string_view string, + uint64_t skipRts, + ResolveFlags flags) { auto sym = globalScope.resolveSymbol(string, skipRts, flags | skipGlobalAfterRts); if(!sym && localScope) sym = localScope->resolveSymbol(string, skipRts, flags | skipGlobalAfterRts); return sym; } -frg::optional Scope::resolveGlobalOrLocalNext(Scope &globalScope, - Scope *localScope, frg::string_view string, SharedObject *origin) { +frg::optional +Scope::resolveGlobalOrLocalNext(Scope &globalScope, Scope *localScope, frg::string_view string, SharedObject *origin) { auto sym = globalScope._resolveNext(string, origin); if(!sym && localScope) { sym = localScope->_resolveNext(string, origin); @@ -1325,9 +1393,8 @@ frg::optional Scope::resolveGlobalOrLocalNext(Scope &globalScope, } // TODO: let this return uintptr_t -frg::optional Scope::resolveSymbol(frg::string_view string, - uint64_t skipRts, ResolveFlags flags) { - for (auto object : _objects) { +frg::optional Scope::resolveSymbol(frg::string_view string, uint64_t skipRts, ResolveFlags flags) { + for(auto object : _objects) { if((flags & resolveCopy) && object->isMainObject) continue; if((flags & skipGlobalAfterRts) && object->globalRts > skipRts) { @@ -1352,17 +1419,21 @@ frg::optional Scope::resolveSymbol(frg::string_view string, // Loader // -------------------------------------------------------- -Loader::Loader(Scope *scope, SharedObject *mainExecutable, bool is_initial_link, uint64_t rts) -: _mainExecutable{mainExecutable}, _loadScope{scope}, _isInitialLink{is_initial_link}, - _linkRts{rts}, _linkBfs{getAllocator()}, _initQueue{getAllocator()} { } +Loader::Loader(Scope *scope, SharedObject *mainExecutable, bool is_initial_link, uint64_t rts) : + _mainExecutable {mainExecutable}, + _loadScope {scope}, + _isInitialLink {is_initial_link}, + _linkRts {rts}, + _linkBfs {getAllocator()}, + _initQueue {getAllocator()} {} void Loader::_buildLinkBfs(SharedObject *root) { __ensure(_linkBfs.size() == 0); struct Token {}; - using Set = frg::hash_map, MemoryAllocator>; - Set set{frg::hash{}, getAllocator()}; + + using Set = frg::hash_map, MemoryAllocator>; + Set set {frg::hash {}, getAllocator()}; _linkBfs.push(root); // Loop over indices (not iterators) here: We are adding elements in the loop! @@ -1377,13 +1448,13 @@ void Loader::_buildLinkBfs(SharedObject *root) { __ensure((current->tlsAlignment & (current->tlsAlignment - 1)) == 0); - if (_isInitialLink && current->tlsAlignment > tlsMaxAlignment) { + if(_isInitialLink && current->tlsAlignment > tlsMaxAlignment) { tlsMaxAlignment = current->tlsAlignment; } - for (auto dep : current->dependencies) { - if (!set.get(dep)) { - set.insert(dep, Token{}); + for(auto dep : current->dependencies) { + if(!set.get(dep)) { + set.insert(dep, Token {}); _linkBfs.push(dep); } } @@ -1396,7 +1467,7 @@ void Loader::linkObjects(SharedObject *root) { // Promote objects to the desired scope. for(auto object : _linkBfs) { - if (object->globalRts == 0 && _loadScope->isGlobal) + if(object->globalRts == 0 && _loadScope->isGlobal) object->globalRts = _linkRts; _loadScope->appendObject(object); @@ -1418,8 +1489,8 @@ void Loader::linkObjects(SharedObject *root) { // TODO: Support this. if(object->symbolicResolution) - mlibc::infoLogger() << "\e[31mrtld: DT_SYMBOLIC is not implemented correctly!\e[39m" - << frg::endlog; + mlibc::infoLogger() + << "\e[31mrtld: DT_SYMBOLIC is not implemented correctly!\e[39m" << frg::endlog; _processStaticRelocations(object); _processLazyRelocations(object); @@ -1446,7 +1517,7 @@ void Loader::linkObjects(SharedObject *root) { if(object->inLinkMap) continue; - auto linkMap = reinterpret_cast(globalDebugInterface.head); + auto linkMap = reinterpret_cast(globalDebugInterface.head); object->linkMap.prev = linkMap; object->linkMap.next = linkMap->next; @@ -1477,7 +1548,7 @@ void Loader::_buildTlsMaps() { object->tlsModel = TlsModel::initial; - if constexpr (tlsAboveTp) { + if constexpr(tlsAboveTp) { size_t misalign = runtimeTlsMap->initialPtr & (object->tlsAlignment - 1); if(misalign) runtimeTlsMap->initialPtr += object->tlsAlignment - misalign; @@ -1495,15 +1566,15 @@ void Loader::_buildTlsMaps() { } if(verbose) - mlibc::infoLogger() << "rtld: TLS of " << object->name - << " mapped to 0x" << frg::hex_fmt{object->tlsOffset} - << ", size: " << object->tlsSegmentSize - << ", alignment: " << object->tlsAlignment << frg::endlog; + mlibc::infoLogger() + << "rtld: TLS of " << object->name << " mapped to 0x" + << frg::hex_fmt {object->tlsOffset} << ", size: " << object->tlsSegmentSize + << ", alignment: " << object->tlsAlignment << frg::endlog; } // Reserve some additional space for future libraries. runtimeTlsMap->initialLimit = runtimeTlsMap->initialPtr + 64; - }else{ + } else { for(auto object : _linkBfs) { if(object->tlsModel != TlsModel::null) continue; @@ -1519,7 +1590,7 @@ void Loader::_buildTlsMaps() { if(object->haveStaticTls) { object->tlsModel = TlsModel::initial; - if constexpr (tlsAboveTp) { + if constexpr(tlsAboveTp) { size_t misalign = runtimeTlsMap->initialPtr & (object->tlsAlignment - 1); if(misalign) runtimeTlsMap->initialPtr += object->tlsAlignment - misalign; @@ -1537,15 +1608,16 @@ void Loader::_buildTlsMaps() { } if(runtimeTlsMap->initialPtr > runtimeTlsMap->initialLimit) - mlibc::panicLogger() << "rtld: Static TLS space exhausted while while" - " allocating TLS for " << object->name << frg::endlog; + mlibc::panicLogger() << "rtld: Static TLS space exhausted while while" + " allocating TLS for " + << object->name << frg::endlog; if(verbose) - mlibc::infoLogger() << "rtld: TLS of " << object->name - << " mapped to 0x" << frg::hex_fmt{object->tlsOffset} - << ", size: " << object->tlsSegmentSize - << ", alignment: " << object->tlsAlignment << frg::endlog; - }else{ + mlibc::infoLogger() << "rtld: TLS of " << object->name << " mapped to 0x" + << frg::hex_fmt {object->tlsOffset} + << ", size: " << object->tlsSegmentSize + << ", alignment: " << object->tlsAlignment << frg::endlog; + } else { object->tlsModel = TlsModel::dynamic; } } @@ -1555,8 +1627,8 @@ void Loader::_buildTlsMaps() { void Loader::initObjects(ObjectRepository *repository) { initTlsObjects(mlibc::get_current_tcb(), _linkBfs, true); - if (_mainExecutable && _mainExecutable->preInitArray) { - if (verbose) + if(_mainExecutable && _mainExecutable->preInitArray) { + if(verbose) mlibc::infoLogger() << "rtld: Running DT_PREINIT_ARRAY functions" << frg::endlog; __ensure(_mainExecutable->isMainObject); @@ -1607,20 +1679,23 @@ void Loader::_processRelocations(Relocation &rel) { // resolve the symbol if there is a symbol frg::optional p; if(rel.symbol_index()) { - auto symbol = (elf_sym *)(rel.object()->baseAddress + rel.object()->symbolTableOffset - + rel.symbol_index() * sizeof(elf_sym)); + auto symbol = (elf_sym *) (rel.object()->baseAddress + rel.object()->symbolTableOffset + + rel.symbol_index() * sizeof(elf_sym)); ObjectSymbol r(rel.object(), symbol); - p = Scope::resolveGlobalOrLocal(*globalScope, rel.object()->localScope, - r.getString(), rel.object()->objectRts, 0); + p = Scope::resolveGlobalOrLocal(*globalScope, + rel.object()->localScope, + r.getString(), + rel.object()->objectRts, + 0); if(!p) { if(ELF_ST_BIND(symbol->st_info) != STB_WEAK) - mlibc::panicLogger() << "Unresolved load-time symbol " - << r.getString() << " in object " << rel.object()->name << frg::endlog; + mlibc::panicLogger() << "Unresolved load-time symbol " << r.getString() << " in object " + << rel.object()->name << frg::endlog; if(verbose) - mlibc::infoLogger() << "rtld: Unresolved weak load-time symbol " - << r.getString() << " in object " << rel.object()->name << frg::endlog; + mlibc::infoLogger() << "rtld: Unresolved weak load-time symbol " << r.getString() + << " in object " << rel.object()->name << frg::endlog; } } @@ -1663,10 +1738,10 @@ void Loader::_processRelocations(Relocation &rel) { if(rel.symbol_index()) { __ensure(p); rel.relocate(elf_addr(p->object())); - }else{ + } else { if(stillSlightlyVerbose) mlibc::infoLogger() << "rtld: Warning: TLS_DTPMOD64 with no symbol in object " - << rel.object()->name << frg::endlog; + << rel.object()->name << frg::endlog; rel.relocate(elf_addr(rel.object())); } } break; @@ -1682,20 +1757,21 @@ void Loader::_processRelocations(Relocation &rel) { if(rel.symbol_index()) { __ensure(p); if(p->object()->tlsModel != TlsModel::initial) - mlibc::panicLogger() << "rtld: In object " << rel.object()->name - << ": Static TLS relocation to symbol " << p->getString() - << " in dynamically loaded object " - << p->object()->name << frg::endlog; + mlibc::panicLogger() + << "rtld: In object " << rel.object()->name + << ": Static TLS relocation to symbol " << p->getString() + << " in dynamically loaded object " << p->object()->name << frg::endlog; off += p->symbol()->st_value; tls_offset = p->object()->tlsOffset; - }else{ + } else { if(stillSlightlyVerbose) mlibc::infoLogger() << "rtld: Warning: TPOFF64 with no symbol" - " in object " << rel.object()->name << frg::endlog; + " in object " + << rel.object()->name << frg::endlog; if(rel.object()->tlsModel != TlsModel::initial) mlibc::panicLogger() << "rtld: In object " << rel.object()->name - << ": Static TLS relocation to dynamically loaded object " - << rel.object()->name << frg::endlog; + << ": Static TLS relocation to dynamically loaded object " + << rel.object()->name << frg::endlog; tls_offset = rel.object()->tlsOffset; } @@ -1703,8 +1779,7 @@ void Loader::_processRelocations(Relocation &rel) { rel.relocate(off); } break; default: - mlibc::panicLogger() << "Unexpected relocation type " - << (void *) rel.type() << frg::endlog; + mlibc::panicLogger() << "Unexpected relocation type " << (void *) rel.type() << frg::endlog; } } @@ -1756,16 +1831,16 @@ void Loader::_processStaticRelocations(SharedObject *object) { __ensure(!rel_offset && !rel_length); for(size_t offset = 0; offset < *rela_length; offset += sizeof(elf_rela)) { - auto reloc = (elf_rela *)(object->baseAddress + *rela_offset + offset); + auto reloc = (elf_rela *) (object->baseAddress + *rela_offset + offset); auto r = Relocation(object, reloc); _processRelocations(r); } - }else if(rel_offset && rel_length) { + } else if(rel_offset && rel_length) { __ensure(!rela_offset && !rela_length); for(size_t offset = 0; offset < *rel_length; offset += sizeof(elf_rel)) { - auto reloc = (elf_rel *)(object->baseAddress + *rel_offset + offset); + auto reloc = (elf_rel *) (object->baseAddress + *rel_offset + offset); auto r = Relocation(object, reloc); _processRelocations(r); @@ -1776,18 +1851,18 @@ void Loader::_processStaticRelocations(SharedObject *object) { elf_addr *addr = nullptr; for(size_t offset = 0; offset < *relr_length; offset += sizeof(elf_relr)) { - auto entry = *(elf_relr *)(object->baseAddress + *relr_offset + offset); + auto entry = *(elf_relr *) (object->baseAddress + *relr_offset + offset); // Even entry indicates the beginning address. if(!(entry & 1)) { - addr = (elf_addr *)(object->baseAddress + entry); + addr = (elf_addr *) (object->baseAddress + entry); __ensure(addr); *addr++ += object->baseAddress; - }else { + } else { // Odd entry indicates entry is a bitmap of the subsequent locations to be relocated. - // The first bit of an entry is always a marker about whether the entry is an address or a bitmap, - // discard it. + // The first bit of an entry is always a marker about whether the entry is an address or + // a bitmap, discard it. entry >>= 1; for(int i = 0; entry; ++i) { @@ -1816,7 +1891,7 @@ void Loader::_processLazyRelocations(SharedObject *object) { return; } object->globalOffsetTable[1] = object; - object->globalOffsetTable[2] = (void *)&pltRelocateStub; + object->globalOffsetTable[2] = (void *) &pltRelocateStub; if(!object->lazyTableSize) return; @@ -1833,47 +1908,53 @@ void Loader::_processLazyRelocations(SharedObject *object) { uintptr_t addend [[maybe_unused]] = 0; if(*object->lazyExplicitAddend) { - auto reloc = (elf_rela *)(object->baseAddress + object->lazyRelocTableOffset + offset); + auto reloc = (elf_rela *) (object->baseAddress + object->lazyRelocTableOffset + offset); type = ELF_R_TYPE(reloc->r_info); symbol_index = ELF_R_SYM(reloc->r_info); rel_addr = object->baseAddress + reloc->r_offset; addend = reloc->r_addend; } else { - auto reloc = (elf_rel *)(object->baseAddress + object->lazyRelocTableOffset + offset); + auto reloc = (elf_rel *) (object->baseAddress + object->lazyRelocTableOffset + offset); type = ELF_R_TYPE(reloc->r_info); symbol_index = ELF_R_SYM(reloc->r_info); rel_addr = object->baseAddress + reloc->r_offset; } - switch (type) { + switch(type) { case R_JUMP_SLOT: if(eagerBinding) { - auto symbol = (elf_sym *)(object->baseAddress + object->symbolTableOffset - + symbol_index * sizeof(elf_sym)); + auto symbol = (elf_sym *) (object->baseAddress + object->symbolTableOffset + + symbol_index * sizeof(elf_sym)); ObjectSymbol r(object, symbol); - auto p = Scope::resolveGlobalOrLocal(*globalScope, object->localScope, r.getString(), object->objectRts, 0); + auto p = Scope::resolveGlobalOrLocal(*globalScope, + object->localScope, + r.getString(), + object->objectRts, + 0); if(!p) { if(ELF_ST_BIND(symbol->st_info) != STB_WEAK) - mlibc::panicLogger() << "rtld: Unresolved JUMP_SLOT symbol " - << r.getString() << " in object " << object->name << frg::endlog; + mlibc::panicLogger() + << "rtld: Unresolved JUMP_SLOT symbol " << r.getString() + << " in object " << object->name << frg::endlog; if(verbose) - mlibc::infoLogger() << "rtld: Unresolved weak JUMP_SLOT symbol " - << r.getString() << " in object " << object->name << frg::endlog; - *((uintptr_t *)rel_addr) = 0; - }else{ - *((uintptr_t *)rel_addr) = p->virtualAddress(); + mlibc::infoLogger() + << "rtld: Unresolved weak JUMP_SLOT symbol " << r.getString() + << " in object " << object->name << frg::endlog; + *((uintptr_t *) rel_addr) = 0; + } else { + *((uintptr_t *) rel_addr) = p->virtualAddress(); } - }else{ - *((uintptr_t *)rel_addr) += object->baseAddress; + } else { + *((uintptr_t *) rel_addr) += object->baseAddress; } break; #if defined(__x86_64__) case R_X86_64_IRELATIVE: { auto ptr = object->baseAddress + addend; auto target = reinterpret_cast(ptr)(); - *((uintptr_t *)rel_addr) = target; + *((uintptr_t *) rel_addr) = target; break; } #endif @@ -1883,19 +1964,23 @@ void Loader::_processLazyRelocations(SharedObject *object) { size_t symValue = 0; SharedObject *target = nullptr; - if (symbol_index) { - auto symbol = (elf_sym *)(object->baseAddress + object->symbolTableOffset - + symbol_index * sizeof(elf_sym)); + if(symbol_index) { + auto symbol = (elf_sym *) (object->baseAddress + object->symbolTableOffset + + symbol_index * sizeof(elf_sym)); ObjectSymbol r(object, symbol); - auto p = Scope::resolveGlobalOrLocal(*globalScope, object->localScope, r.getString(), object->objectRts, 0); + auto p = Scope::resolveGlobalOrLocal(*globalScope, + object->localScope, + r.getString(), + object->objectRts, + 0); - if (!p) { + if(!p) { __ensure(ELF_ST_BIND(symbol->st_info) != STB_WEAK); - mlibc::panicLogger() << "rtld: Unresolved TLSDESC for symbol " - << r.getString() << " in object " << object->name << frg::endlog; + mlibc::panicLogger() << "rtld: Unresolved TLSDESC for symbol " << r.getString() + << " in object " << object->name << frg::endlog; } else { target = p->object(); - if (p->symbol()) + if(p->symbol()) symValue = p->symbol()->st_value; } } else { @@ -1904,10 +1989,10 @@ void Loader::_processLazyRelocations(SharedObject *object) { __ensure(target); - if (target->tlsModel == TlsModel::initial) { - ((uint64_t *)rel_addr)[0] = reinterpret_cast(&__mlibcTlsdescStatic); + if(target->tlsModel == TlsModel::initial) { + ((uint64_t *) rel_addr)[0] = reinterpret_cast(&__mlibcTlsdescStatic); uint64_t value = symValue + target->tlsOffset + tlsOffsetFromTp + addend; - ((uint64_t *)rel_addr)[1] = value; + ((uint64_t *) rel_addr)[1] = value; } else { struct TlsdescData { uintptr_t tlsIndex; @@ -1924,8 +2009,8 @@ void Loader::_processLazyRelocations(SharedObject *object) { data->tlsIndex = target->tlsIndex; data->addend = symValue + addend; - ((uint64_t *)rel_addr)[0] = reinterpret_cast(&__mlibcTlsdescDynamic); - ((uint64_t *)rel_addr)[1] = reinterpret_cast(data); + ((uint64_t *) rel_addr)[0] = reinterpret_cast(&__mlibcTlsdescDynamic); + ((uint64_t *) rel_addr)[1] = reinterpret_cast(data); } } break; #endif @@ -1935,4 +2020,3 @@ void Loader::_processLazyRelocations(SharedObject *object) { } } } -