xref: /aosp_15_r20/external/musl/android/ldso_trampoline.cpp (revision c9945492fdd68bbe62686c5b452b4dc1be3f8453)
1*c9945492SAndroid Build Coastguard Worker /*
2*c9945492SAndroid Build Coastguard Worker  * Copyright (C) 2021 The Android Open Source Project
3*c9945492SAndroid Build Coastguard Worker  * All rights reserved.
4*c9945492SAndroid Build Coastguard Worker  *
5*c9945492SAndroid Build Coastguard Worker  * Redistribution and use in source and binary forms, with or without
6*c9945492SAndroid Build Coastguard Worker  * modification, are permitted provided that the following conditions
7*c9945492SAndroid Build Coastguard Worker  * are met:
8*c9945492SAndroid Build Coastguard Worker  *  * Redistributions of source code must retain the above copyright
9*c9945492SAndroid Build Coastguard Worker  *    notice, this list of conditions and the following disclaimer.
10*c9945492SAndroid Build Coastguard Worker  *  * Redistributions in binary form must reproduce the above copyright
11*c9945492SAndroid Build Coastguard Worker  *    notice, this list of conditions and the following disclaimer in
12*c9945492SAndroid Build Coastguard Worker  *    the documentation and/or other materials provided with the
13*c9945492SAndroid Build Coastguard Worker  *    distribution.
14*c9945492SAndroid Build Coastguard Worker  *
15*c9945492SAndroid Build Coastguard Worker  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
16*c9945492SAndroid Build Coastguard Worker  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
17*c9945492SAndroid Build Coastguard Worker  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
18*c9945492SAndroid Build Coastguard Worker  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
19*c9945492SAndroid Build Coastguard Worker  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
20*c9945492SAndroid Build Coastguard Worker  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
21*c9945492SAndroid Build Coastguard Worker  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
22*c9945492SAndroid Build Coastguard Worker  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
23*c9945492SAndroid Build Coastguard Worker  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24*c9945492SAndroid Build Coastguard Worker  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
25*c9945492SAndroid Build Coastguard Worker  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26*c9945492SAndroid Build Coastguard Worker  * SUCH DAMAGE.
27*c9945492SAndroid Build Coastguard Worker  */
28*c9945492SAndroid Build Coastguard Worker 
29*c9945492SAndroid Build Coastguard Worker #define START "__dlwrap__start"
30*c9945492SAndroid Build Coastguard Worker 
31*c9945492SAndroid Build Coastguard Worker #include "crt_arch.h"
32*c9945492SAndroid Build Coastguard Worker 
33*c9945492SAndroid Build Coastguard Worker #include <elf.h>
34*c9945492SAndroid Build Coastguard Worker #include <link.h>
35*c9945492SAndroid Build Coastguard Worker #include "reloc.h"
36*c9945492SAndroid Build Coastguard Worker 
37*c9945492SAndroid Build Coastguard Worker #define AUX_CNT 32
38*c9945492SAndroid Build Coastguard Worker 
39*c9945492SAndroid Build Coastguard Worker #include "ldso_trampoline_phdr.h"
40*c9945492SAndroid Build Coastguard Worker 
41*c9945492SAndroid Build Coastguard Worker // The location of the embedded linker in the executable.
42*c9945492SAndroid Build Coastguard Worker // Hidden visibility is used to get a pc-relative reference instead
43*c9945492SAndroid Build Coastguard Worker // of a GOT reference, which isn't available when this code runs.
44*c9945492SAndroid Build Coastguard Worker __attribute__((visibility("hidden"))) extern const char __dlwrap_linker;
45*c9945492SAndroid Build Coastguard Worker __attribute__((visibility("hidden"))) extern const char __dlwrap_linker_end;
46*c9945492SAndroid Build Coastguard Worker 
47*c9945492SAndroid Build Coastguard Worker // The real entry point of the binary to use after linker bootstrapping.
48*c9945492SAndroid Build Coastguard Worker __attribute__((visibility("hidden"))) extern "C" void _start();
49*c9945492SAndroid Build Coastguard Worker 
50*c9945492SAndroid Build Coastguard Worker // Allocate some R/W memory to store a copy of the program headers.
51*c9945492SAndroid Build Coastguard Worker static ElfW(Phdr) phdr_copy[64];
52*c9945492SAndroid Build Coastguard Worker 
get_auxv(size_t * auxv,size_t entry)53*c9945492SAndroid Build Coastguard Worker static size_t get_auxv(size_t* auxv, size_t entry) {
54*c9945492SAndroid Build Coastguard Worker   for (size_t i = 0; auxv[i]; i += 2)
55*c9945492SAndroid Build Coastguard Worker     if (auxv[i] == entry) return auxv[i + 1];
56*c9945492SAndroid Build Coastguard Worker   return 0;
57*c9945492SAndroid Build Coastguard Worker }
58*c9945492SAndroid Build Coastguard Worker 
set_auxv(size_t * auxv,size_t entry,size_t value)59*c9945492SAndroid Build Coastguard Worker static void set_auxv(size_t* auxv, size_t entry, size_t value) {
60*c9945492SAndroid Build Coastguard Worker   for (size_t i = 0; auxv[i]; i += 2) {
61*c9945492SAndroid Build Coastguard Worker     if (auxv[i] == entry) {
62*c9945492SAndroid Build Coastguard Worker       auxv[i + 1] = value;
63*c9945492SAndroid Build Coastguard Worker       return;
64*c9945492SAndroid Build Coastguard Worker     }
65*c9945492SAndroid Build Coastguard Worker   }
66*c9945492SAndroid Build Coastguard Worker   __builtin_trap();
67*c9945492SAndroid Build Coastguard Worker }
68*c9945492SAndroid Build Coastguard Worker 
69*c9945492SAndroid Build Coastguard Worker /*
70*c9945492SAndroid Build Coastguard Worker  * This is the entry point for the linker wrapper, which finds
71*c9945492SAndroid Build Coastguard Worker  * the real linker, then bootstraps into it.
72*c9945492SAndroid Build Coastguard Worker  */
__dlwrap__start_c(size_t * sp)73*c9945492SAndroid Build Coastguard Worker extern "C" void __dlwrap__start_c(size_t* sp) {
74*c9945492SAndroid Build Coastguard Worker   size_t i, aux[AUX_CNT];
75*c9945492SAndroid Build Coastguard Worker 
76*c9945492SAndroid Build Coastguard Worker   int argc = *sp;
77*c9945492SAndroid Build Coastguard Worker   char** argv = reinterpret_cast<char**>(sp + 1);
78*c9945492SAndroid Build Coastguard Worker 
79*c9945492SAndroid Build Coastguard Worker   for (i = argc + 1; argv[i]; i++)
80*c9945492SAndroid Build Coastguard Worker     ;
81*c9945492SAndroid Build Coastguard Worker   size_t* auxv = reinterpret_cast<size_t*>(argv + i + 1);
82*c9945492SAndroid Build Coastguard Worker 
83*c9945492SAndroid Build Coastguard Worker   for (i = 0; i < AUX_CNT; i++) aux[i] = 0;
84*c9945492SAndroid Build Coastguard Worker   for (i = 0; auxv[i]; i += 2)
85*c9945492SAndroid Build Coastguard Worker     if (auxv[i] < AUX_CNT) aux[auxv[i]] = auxv[i + 1];
86*c9945492SAndroid Build Coastguard Worker 
87*c9945492SAndroid Build Coastguard Worker   ElfW(Phdr)* phdr = reinterpret_cast<ElfW(Phdr)*>(get_auxv(auxv, AT_PHDR));
88*c9945492SAndroid Build Coastguard Worker   size_t phdr_count = get_auxv(auxv, AT_PHNUM);
89*c9945492SAndroid Build Coastguard Worker   ElfW(Addr) load_bias = get_elf_load_bias_from_phdr(phdr, phdr_count);
90*c9945492SAndroid Build Coastguard Worker 
91*c9945492SAndroid Build Coastguard Worker   ElfW(Addr) linker_addr = reinterpret_cast<ElfW(Addr)>(&__dlwrap_linker);
92*c9945492SAndroid Build Coastguard Worker   ElfW(Addr) linker_size = static_cast<ElfW(Addr)>(&__dlwrap_linker_end - &__dlwrap_linker);
93*c9945492SAndroid Build Coastguard Worker   ElfW(Addr) linker_vaddr = linker_addr - load_bias;
94*c9945492SAndroid Build Coastguard Worker   ElfW(Addr) linker_entry_offset = reinterpret_cast<ElfW(Ehdr)*>(linker_addr)->e_entry;
95*c9945492SAndroid Build Coastguard Worker 
96*c9945492SAndroid Build Coastguard Worker   // Make a copy of the ELF program headers that does not contain the load
97*c9945492SAndroid Build Coastguard Worker   // segments for the embedded linker.  The embedded linker contains its
98*c9945492SAndroid Build Coastguard Worker   // own copy of its load segments, which causes problems if musl uses
99*c9945492SAndroid Build Coastguard Worker   // both sets of load segments when donating unused space to the heap.
100*c9945492SAndroid Build Coastguard Worker   if (phdr_count > sizeof(phdr_copy) / sizeof(phdr_copy[0])) __builtin_trap();
101*c9945492SAndroid Build Coastguard Worker   copy_phdr(phdr, phdr_copy, phdr_count, load_bias);
102*c9945492SAndroid Build Coastguard Worker   phdr_trim_embedded_linker(phdr_copy, phdr_count, linker_vaddr, linker_vaddr + linker_size);
103*c9945492SAndroid Build Coastguard Worker 
104*c9945492SAndroid Build Coastguard Worker   // Set AT_BASE to the embedded linker
105*c9945492SAndroid Build Coastguard Worker   set_auxv(auxv, AT_BASE, linker_addr);
106*c9945492SAndroid Build Coastguard Worker   // Set AT_ENTRY to the proper entry point
107*c9945492SAndroid Build Coastguard Worker   set_auxv(auxv, AT_ENTRY, reinterpret_cast<ElfW(Addr)>(&_start));
108*c9945492SAndroid Build Coastguard Worker   // Set AT_PHDR to the copied program headers
109*c9945492SAndroid Build Coastguard Worker   set_auxv(auxv, AT_PHDR, reinterpret_cast<ElfW(Addr)>(&phdr_copy));
110*c9945492SAndroid Build Coastguard Worker 
111*c9945492SAndroid Build Coastguard Worker   // Jump to linker entry point
112*c9945492SAndroid Build Coastguard Worker   CRTJMP(linker_addr + linker_entry_offset, sp);
113*c9945492SAndroid Build Coastguard Worker }
114