1#include "dynlink.h" 2#include "relr.h" 3#include "libc.h" 4#include <zircon/compiler.h> 5#include <stdatomic.h> 6#include <stddef.h> 7 8#ifdef __clang__ 9// TODO(mcgrathr): Really we want to compile just this file without 10// -fsanitize-coverage, but this works around the issue for now. 11__asm__(".weakref __sanitizer_cov_trace_pc_guard, _dlstart_sancov_dummy"); 12__asm__(".pushsection .text._dlstart_sancov_dummy,\"ax\",%progbits\n" 13 ".local _dlstart_sancov_dummy\n" 14 ".type _dlstart_sancov_dummy,%function\n" 15 "_dlstart_sancov_dummy: ret\n" 16 ".size _dlstart_sancov_dummy, . - _dlstart_sancov_dummy\n" 17 ".popsection"); 18#endif 19 20__LOCAL __NO_SAFESTACK NO_ASAN dl_start_return_t _dl_start(void* start_arg, 21 void* vdso) { 22 ElfW(Addr) base = (uintptr_t)__ehdr_start; 23 const ElfW(Rel)* rel = NULL; 24 const ElfW(Rela)* rela = NULL; 25 const ElfW(Addr)* relr = NULL; 26 size_t relcount = 0, relacount = 0, relrsz = 0; 27 28 // We rely on having been linked with -z combreloc so we get 29 // the DT_REL(A)COUNT tag and relocs are sorted with all the 30 // R_*_RELATIVE cases first. 31 32 for (const ElfW(Dyn)* d = _DYNAMIC; d->d_tag != DT_NULL; ++d) { 33 switch (d->d_tag) { 34 case DT_REL: 35 rel = (const void*)(base + d->d_un.d_ptr); 36 break; 37 case DT_RELA: 38 rela = (const void*)(base + d->d_un.d_ptr); 39 break; 40 case DT_RELR: 41 relr = (const void*)(base + d->d_un.d_ptr); 42 break; 43 case DT_RELCOUNT: 44 relcount = d->d_un.d_val; 45 break; 46 case DT_RELACOUNT: 47 relacount = d->d_un.d_val; 48 break; 49 case DT_RELRSZ: 50 relrsz = d->d_un.d_val; 51 break; 52 case DT_RELRENT: 53 if (d->d_un.d_val != sizeof(relr[0])) { 54 __builtin_trap(); 55 } 56 break; 57 } 58 } 59 60 for (size_t i = 0; i < relcount; ++i) { 61 ElfW(Addr)* addr = (uintptr_t*)(base + rel[i].r_offset); 62 // Invariant (no asserts here): R_TYPE(rel[i].r_info) == REL_RELATIVE 63 *addr += base; 64 } 65 66 for (size_t i = 0; i < relacount; ++i) { 67 ElfW(Addr)* addr = (uintptr_t*)(base + rela[i].r_offset); 68 // Invariant (no asserts here): R_TYPE(rela[i].r_info) == REL_RELATIVE 69 *addr = base + rela[i].r_addend; 70 } 71 72 apply_relr(base, relr, relrsz); 73 74 // Make sure all the relocations have landed before calling __dls2, 75 // which relies on them. 76 atomic_signal_fence(memory_order_seq_cst); 77 78 return __dls2(start_arg, vdso); 79} 80