ld.so: fix build on macOS

This commit is contained in:
Pierre Pronchery 2021-10-10 19:37:46 +02:00
parent 33499036e4
commit b9f0f8cbd1
2 changed files with 71 additions and 68 deletions

View File

@ -35,7 +35,11 @@
#include <stdio.h>
#include <string.h>
#include <errno.h>
#if defined(__APPLE__)
# include <mach-o/loader.h>
#elif defined(__ELF__)
# include <elf.h>
#endif
#include "loader.h"
#ifndef PROGNAME_LOADER
@ -46,9 +50,9 @@
/* Loader */
/* private */
/* prototypes */
static int _error(int code, char const * format, ...);
static int _loader_elf(int fd, char const * filename, int argc, char * argv[]);
static int _prot(int flags);
static int _error(int code, char const * format, ...);
/* public */
@ -58,14 +62,6 @@ extern char ** environ;
/* functions */
/* loader */
static int _loader_do(int fd, char const * filename, int argc, char * argv[]);
static int _do_phdr(int fd, char const * filename, Elf_Ehdr * ehdr,
void ** entrypoint);
static size_t _do_phdr_align_bits(unsigned long align);
static int _do_shdr(int fd, char const * filename, Elf_Ehdr * ehdr);
static int _do_shdr_rela(int fd, char const * filename, Elf_Shdr * shdr,
size_t entsize);
int loader(char const * filename, int argc, char * argv[])
{
int ret;
@ -73,12 +69,24 @@ int loader(char const * filename, int argc, char * argv[])
if((fd = open(filename, O_RDONLY)) < 0)
return _error(2, "%s: %s", filename, strerror(errno));
ret = _loader_do(fd, filename, argc, argv);
ret = _loader_elf(fd, filename, argc, argv);
close(fd);
return ret;
}
static int _loader_do(int fd, char const * filename, int argc, char * argv[])
/* private */
/* functions */
#if defined(__ELF__)
static int _elf_phdr(int fd, char const * filename, Elf_Ehdr * ehdr,
void ** entrypoint);
static size_t _elf_phdr_align_bits(unsigned long align);
static int _elf_prot(int flags);
static int _elf_shdr(int fd, char const * filename, Elf_Ehdr * ehdr);
static int _elf_shdr_rela(int fd, char const * filename, Elf_Shdr * shdr,
size_t entsize);
static int _loader_elf(int fd, char const * filename, int argc, char * argv[])
{
int ret;
Elf_Ehdr ehdr;
@ -95,8 +103,8 @@ static int _loader_do(int fd, char const * filename, int argc, char * argv[])
if(ehdr.e_ehsize != sizeof(ehdr))
return _error(2, "%s: %s", filename,
"Invalid or unsupported ELF file");
if((ret = _do_phdr(fd, filename, &ehdr, &entrypoint)) != 0
|| (ret = _do_shdr(fd, filename, &ehdr)) != 0)
if((ret = _elf_phdr(fd, filename, &ehdr, &entrypoint)) != 0
|| (ret = _elf_shdr(fd, filename, &ehdr)) != 0)
return ret;
if(entrypoint == NULL)
return _error(2, "%s: %s", filename, "Entrypoint not set");
@ -109,7 +117,7 @@ static int _loader_do(int fd, char const * filename, int argc, char * argv[])
return 0;
}
static int _do_phdr(int fd, char const * filename, Elf_Ehdr * ehdr,
static int _elf_phdr(int fd, char const * filename, Elf_Ehdr * ehdr,
void ** entrypoint)
{
Elf_Phdr phdr;
@ -144,28 +152,17 @@ static int _do_phdr(int fd, char const * filename, Elf_Ehdr * ehdr,
# endif
if(phdr.p_type != PT_LOAD)
continue;
flags = MAP_ALIGNED(_do_phdr_align_bits(phdr.p_align));
flags = MAP_ALIGNED(_elf_phdr_align_bits(phdr.p_align));
if(phdr.p_filesz == 0)
{
#if 0
addr = NULL;
#endif
flags |= MAP_ANON;
prot = _prot(phdr.p_flags);
prot = _elf_prot(phdr.p_flags);
f = -1;
offset = 0;
}
else if(phdr.p_filesz == phdr.p_memsz)
{
#if 0
addr = (void *)phdr.p_vaddr;
#endif
flags |= MAP_FILE;
prot = _prot(phdr.p_flags);
#if 0
if(phdr.p_vaddr != 0)
flags |= MAP_TRYFIXED;
#endif
if(prot & PROT_WRITE)
flags |= MAP_PRIVATE;
f = fd;
@ -199,7 +196,7 @@ static int _do_phdr(int fd, char const * filename, Elf_Ehdr * ehdr,
strerror(errno));
memset(&addr[phdr.p_filesz], 0,
phdr.p_memsz - phdr.p_filesz);
prot = _prot(phdr.p_flags);
prot = _elf_prot(phdr.p_flags);
# ifdef DEBUG
fprintf(stderr, "DEBUG: mprotect(%p, %lu, %d)\n",
addr, (unsigned long)phdr.p_memsz, prot);
@ -230,7 +227,7 @@ static int _do_phdr(int fd, char const * filename, Elf_Ehdr * ehdr,
return 0;
}
static size_t _do_phdr_align_bits(unsigned long align)
static size_t _elf_phdr_align_bits(unsigned long align)
{
size_t i = 0;
@ -248,7 +245,17 @@ static size_t _do_phdr_align_bits(unsigned long align)
return 0;
}
static int _do_shdr(int fd, char const * filename, Elf_Ehdr * ehdr)
static int _elf_prot(int flags)
{
int ret = PROT_NONE;
ret |= (flags & PF_R) ? PROT_READ : 0;
ret |= (flags & PF_W) ? PROT_WRITE : 0;
ret |= (flags & PF_X) ? PROT_EXEC : 0;
return ret;
}
static int _elf_shdr(int fd, char const * filename, Elf_Ehdr * ehdr)
{
int ret;
Elf_Shdr shdr;
@ -281,7 +288,7 @@ static int _do_shdr(int fd, char const * filename, Elf_Ehdr * ehdr)
# endif
if(shdr.sh_type == SHT_REL
|| shdr.sh_type == SHT_RELA)
ret = _do_shdr_rela(fd, filename, &shdr,
ret = _elf_shdr_rela(fd, filename, &shdr,
shdr.sh_entsize);
else
continue;
@ -294,7 +301,7 @@ static int _do_shdr(int fd, char const * filename, Elf_Ehdr * ehdr)
return 0;
}
static int _do_shdr_rela(int fd, char const * filename, Elf_Shdr * shdr,
static int _elf_shdr_rela(int fd, char const * filename, Elf_Shdr * shdr,
size_t entsize)
{
Elf_Rela rela;
@ -339,10 +346,18 @@ static int _do_shdr_rela(int fd, char const * filename, Elf_Shdr * shdr,
}
return 0;
}
#else
static int _loader_elf(int fd, char const * filename, int argc, char * argv[])
{
(void) fd;
(void) argc;
(void) argv;
return _error(1, "%s: %s", filename, "Unsupported file format");
}
#endif
/* private */
/* functions */
/* error */
static int _error(int code, char const * format, ...)
{
@ -355,15 +370,3 @@ static int _error(int code, char const * format, ...)
fputs("\n", stderr);
return code;
}
/* prot */
static int _prot(int flags)
{
int ret = PROT_NONE;
ret |= (flags & PF_R) ? PROT_READ : 0;
ret |= (flags & PF_W) ? PROT_WRITE : 0;
ret |= (flags & PF_X) ? PROT_EXEC : 0;
return ret;
}

View File

@ -6,8 +6,8 @@ asflags=$(CPPFLAGS) $(CFLAGS)
cppflags_force=
cflags_force=-g
cflags=-W -Wall -O2 -fPIE -D_FORTIFY_SOURCE=2 -fstack-protector
ldflags_force=-static
ldflags=-pie -Wl,-z,relro -Wl,-z,now
ldflags_force=
ldflags=-static -pie -Wl,-z,relro -Wl,-z,now
dist=Makefile,loader.h
mode=amd64-debug