Clean up some code

- Use good ELF technique in cosmo_dlopen()
- Make strerror() conform more to other libc impls
- Introduce __clear_cache() and use it in cosmo_dlopen()
- Remove libc/fmt/fmt.h header (trying to kill off LIBC_FMT)
This commit is contained in:
Justine Tunney 2023-11-16 16:34:53 -08:00
parent 7010a8081e
commit 68c7c9c1e0
No known key found for this signature in database
GPG key ID: BE714B4575D6E328
244 changed files with 378 additions and 588 deletions

View file

@ -16,6 +16,7 @@
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/assert.h"
#include "libc/atomic.h"
#include "libc/calls/calls.h"
#include "libc/calls/struct/sigset.internal.h"
@ -34,8 +35,8 @@
#include "libc/elf/struct/phdr.h"
#include "libc/errno.h"
#include "libc/fmt/itoa.h"
#include "libc/intrin/atomic.h"
#include "libc/intrin/bits.h"
#include "libc/intrin/kprintf.h"
#include "libc/intrin/strace.internal.h"
#include "libc/limits.h"
#include "libc/nt/dll.h"
@ -69,11 +70,6 @@
* @kudos jacereda for figuring out how to do this
*/
#define XNU_RTLD_LAZY 1
#define XNU_RTLD_NOW 2
#define XNU_RTLD_LOCAL 4
#define XNU_RTLD_GLOBAL 8
#define AMD_REXB 0x41
#define AMD_REXW 0x48
#define AMD_MOV_IMM 0xb8
@ -83,11 +79,16 @@
#define ARM_IDX_OFF 21
#define ARM_MOV_NEX 0xf2800000u
#define XNU_RTLD_LAZY 1
#define XNU_RTLD_NOW 2
#define XNU_RTLD_LOCAL 4
#define XNU_RTLD_GLOBAL 8
#define HELPER \
"#include <dlfcn.h>\n\
#include <stdio.h>\n\
#include <stdlib.h>\n\
int main(int argc, char *argv[]) {\n\
int main(int argc, char **argv, char **envp) {\n\
char *ep;\n\
long addr;\n\
if (argc != 2) {\n\
@ -201,7 +202,7 @@ static char *elf_map(int fd, Elf64_Ehdr *ehdr, Elf64_Phdr *phdr, long pagesz,
char *interp_path, size_t interp_size) {
Elf64_Addr maxva = 0;
Elf64_Addr minva = -1;
for (Elf64_Phdr *p = phdr; p < &phdr[ehdr->e_phnum]; p++) {
for (Elf64_Phdr *p = phdr; p < phdr + ehdr->e_phnum; p++) {
if (p->p_type != PT_LOAD) {
continue;
}
@ -227,18 +228,31 @@ static char *elf_map(int fd, Elf64_Ehdr *ehdr, Elf64_Phdr *phdr, long pagesz,
}
continue;
}
int prot = elf2prot(p->p_flags);
Elf64_Addr skew = p->p_vaddr & (pagesz - 1);
Elf64_Off off = p->p_offset - skew;
if (__sys_mmap(base + p->p_vaddr - skew, skew + p->p_filesz, prot,
Elf64_Addr a = p->p_vaddr + p->p_filesz;
Elf64_Addr b = (a + (pagesz - 1)) & -pagesz;
Elf64_Addr c = p->p_vaddr + p->p_memsz;
int prot2 = elf2prot(p->p_flags);
int prot1 = prot2;
if (b > a) {
prot1 |= PROT_WRITE;
prot1 &= ~PROT_EXEC;
}
if (__sys_mmap(base + p->p_vaddr - skew, skew + p->p_filesz, prot1,
MAP_FIXED | MAP_PRIVATE, fd, off, off) == MAP_FAILED) {
return MAP_FAILED;
}
Elf64_Addr fend = (p->p_vaddr + p->p_filesz + (pagesz - 1)) & -pagesz;
Elf64_Addr mend = p->p_vaddr + p->p_memsz;
if (mend > fend && __sys_mmap(base + fend, mend - fend, prot,
MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS, -1,
0, 0) == MAP_FAILED) {
if (b > a) {
bzero(base + a, b - a);
}
if (c > b && __sys_mmap(base + b, c - b, prot2,
MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS, -1, 0,
0) == MAP_FAILED) {
return MAP_FAILED;
}
if (prot1 != prot2 &&
sys_mprotect(base + p->p_vaddr - skew, skew + p->p_filesz, prot2)) {
return MAP_FAILED;
}
}
@ -302,14 +316,14 @@ static dontinline void elf_exec(const char *file, char **envp) {
// get microprocessor page size
long pagesz = getauxval(AT_PAGESZ);
// load executable
// load helper executable into address space
struct Loaded prog;
char interp_path[256] = {0};
if (!elf_load(&prog, file, pagesz, interp_path, sizeof(interp_path))) {
return;
}
// load platform libc
// load platform c library into address space
struct Loaded interp;
if (!elf_load(&interp, interp_path, pagesz, 0, 0)) {
return;
@ -343,6 +357,7 @@ static dontinline void elf_exec(const char *file, char **envp) {
FormatInt64(address_argument, (uintptr_t)foreign_helper);
// push auxiliary values
// these tell the platform libc how to load the executable
*--sp = 0;
unsigned long key, val;
for (av = (Elf64_auxv_t *)__auxv; (key = av->a_type); ++av) {
@ -508,7 +523,8 @@ static void *foreign_thunk_sysv(void *func) {
if (!(p = code = foreign_alloc(36))) return 0; // 16 + 16 + 4 = 36
p = movimm(p, 5, (uintptr_t)func);
p = movimm(p, 10, (uintptr_t)foreign_tramp);
*(uint32_t *)p = 0xd63f0140; // blr x10
*(uint32_t *)p = 0xd61f0140; // br x10
__clear_cache(code, p + 4);
#else
#error "unsupported architecture"
#endif