ld.so: fix build on macOS
This commit is contained in:
parent
33499036e4
commit
b9f0f8cbd1
97
src/loader.c
97
src/loader.c
@ -35,7 +35,11 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
#if defined(__APPLE__)
|
||||||
|
# include <mach-o/loader.h>
|
||||||
|
#elif defined(__ELF__)
|
||||||
# include <elf.h>
|
# include <elf.h>
|
||||||
|
#endif
|
||||||
#include "loader.h"
|
#include "loader.h"
|
||||||
|
|
||||||
#ifndef PROGNAME_LOADER
|
#ifndef PROGNAME_LOADER
|
||||||
@ -46,9 +50,9 @@
|
|||||||
/* Loader */
|
/* Loader */
|
||||||
/* private */
|
/* private */
|
||||||
/* prototypes */
|
/* 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 */
|
/* public */
|
||||||
@ -58,14 +62,6 @@ extern char ** environ;
|
|||||||
|
|
||||||
/* functions */
|
/* functions */
|
||||||
/* loader */
|
/* 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 loader(char const * filename, int argc, char * argv[])
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
@ -73,12 +69,24 @@ int loader(char const * filename, int argc, char * argv[])
|
|||||||
|
|
||||||
if((fd = open(filename, O_RDONLY)) < 0)
|
if((fd = open(filename, O_RDONLY)) < 0)
|
||||||
return _error(2, "%s: %s", filename, strerror(errno));
|
return _error(2, "%s: %s", filename, strerror(errno));
|
||||||
ret = _loader_do(fd, filename, argc, argv);
|
ret = _loader_elf(fd, filename, argc, argv);
|
||||||
close(fd);
|
close(fd);
|
||||||
return ret;
|
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;
|
int ret;
|
||||||
Elf_Ehdr ehdr;
|
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))
|
if(ehdr.e_ehsize != sizeof(ehdr))
|
||||||
return _error(2, "%s: %s", filename,
|
return _error(2, "%s: %s", filename,
|
||||||
"Invalid or unsupported ELF file");
|
"Invalid or unsupported ELF file");
|
||||||
if((ret = _do_phdr(fd, filename, &ehdr, &entrypoint)) != 0
|
if((ret = _elf_phdr(fd, filename, &ehdr, &entrypoint)) != 0
|
||||||
|| (ret = _do_shdr(fd, filename, &ehdr)) != 0)
|
|| (ret = _elf_shdr(fd, filename, &ehdr)) != 0)
|
||||||
return ret;
|
return ret;
|
||||||
if(entrypoint == NULL)
|
if(entrypoint == NULL)
|
||||||
return _error(2, "%s: %s", filename, "Entrypoint not set");
|
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;
|
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)
|
void ** entrypoint)
|
||||||
{
|
{
|
||||||
Elf_Phdr phdr;
|
Elf_Phdr phdr;
|
||||||
@ -144,28 +152,17 @@ static int _do_phdr(int fd, char const * filename, Elf_Ehdr * ehdr,
|
|||||||
# endif
|
# endif
|
||||||
if(phdr.p_type != PT_LOAD)
|
if(phdr.p_type != PT_LOAD)
|
||||||
continue;
|
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(phdr.p_filesz == 0)
|
||||||
{
|
{
|
||||||
#if 0
|
|
||||||
addr = NULL;
|
|
||||||
#endif
|
|
||||||
flags |= MAP_ANON;
|
flags |= MAP_ANON;
|
||||||
prot = _prot(phdr.p_flags);
|
prot = _elf_prot(phdr.p_flags);
|
||||||
f = -1;
|
f = -1;
|
||||||
offset = 0;
|
offset = 0;
|
||||||
}
|
}
|
||||||
else if(phdr.p_filesz == phdr.p_memsz)
|
else if(phdr.p_filesz == phdr.p_memsz)
|
||||||
{
|
{
|
||||||
#if 0
|
|
||||||
addr = (void *)phdr.p_vaddr;
|
|
||||||
#endif
|
|
||||||
flags |= MAP_FILE;
|
flags |= MAP_FILE;
|
||||||
prot = _prot(phdr.p_flags);
|
|
||||||
#if 0
|
|
||||||
if(phdr.p_vaddr != 0)
|
|
||||||
flags |= MAP_TRYFIXED;
|
|
||||||
#endif
|
|
||||||
if(prot & PROT_WRITE)
|
if(prot & PROT_WRITE)
|
||||||
flags |= MAP_PRIVATE;
|
flags |= MAP_PRIVATE;
|
||||||
f = fd;
|
f = fd;
|
||||||
@ -199,7 +196,7 @@ static int _do_phdr(int fd, char const * filename, Elf_Ehdr * ehdr,
|
|||||||
strerror(errno));
|
strerror(errno));
|
||||||
memset(&addr[phdr.p_filesz], 0,
|
memset(&addr[phdr.p_filesz], 0,
|
||||||
phdr.p_memsz - phdr.p_filesz);
|
phdr.p_memsz - phdr.p_filesz);
|
||||||
prot = _prot(phdr.p_flags);
|
prot = _elf_prot(phdr.p_flags);
|
||||||
# ifdef DEBUG
|
# ifdef DEBUG
|
||||||
fprintf(stderr, "DEBUG: mprotect(%p, %lu, %d)\n",
|
fprintf(stderr, "DEBUG: mprotect(%p, %lu, %d)\n",
|
||||||
addr, (unsigned long)phdr.p_memsz, prot);
|
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;
|
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;
|
size_t i = 0;
|
||||||
|
|
||||||
@ -248,7 +245,17 @@ static size_t _do_phdr_align_bits(unsigned long align)
|
|||||||
return 0;
|
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;
|
int ret;
|
||||||
Elf_Shdr shdr;
|
Elf_Shdr shdr;
|
||||||
@ -281,7 +288,7 @@ static int _do_shdr(int fd, char const * filename, Elf_Ehdr * ehdr)
|
|||||||
# endif
|
# endif
|
||||||
if(shdr.sh_type == SHT_REL
|
if(shdr.sh_type == SHT_REL
|
||||||
|| shdr.sh_type == SHT_RELA)
|
|| shdr.sh_type == SHT_RELA)
|
||||||
ret = _do_shdr_rela(fd, filename, &shdr,
|
ret = _elf_shdr_rela(fd, filename, &shdr,
|
||||||
shdr.sh_entsize);
|
shdr.sh_entsize);
|
||||||
else
|
else
|
||||||
continue;
|
continue;
|
||||||
@ -294,7 +301,7 @@ static int _do_shdr(int fd, char const * filename, Elf_Ehdr * ehdr)
|
|||||||
return 0;
|
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)
|
size_t entsize)
|
||||||
{
|
{
|
||||||
Elf_Rela rela;
|
Elf_Rela rela;
|
||||||
@ -339,10 +346,18 @@ static int _do_shdr_rela(int fd, char const * filename, Elf_Shdr * shdr,
|
|||||||
}
|
}
|
||||||
return 0;
|
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 */
|
/* error */
|
||||||
static int _error(int code, char const * format, ...)
|
static int _error(int code, char const * format, ...)
|
||||||
{
|
{
|
||||||
@ -355,15 +370,3 @@ static int _error(int code, char const * format, ...)
|
|||||||
fputs("\n", stderr);
|
fputs("\n", stderr);
|
||||||
return code;
|
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;
|
|
||||||
}
|
|
||||||
|
@ -6,8 +6,8 @@ asflags=$(CPPFLAGS) $(CFLAGS)
|
|||||||
cppflags_force=
|
cppflags_force=
|
||||||
cflags_force=-g
|
cflags_force=-g
|
||||||
cflags=-W -Wall -O2 -fPIE -D_FORTIFY_SOURCE=2 -fstack-protector
|
cflags=-W -Wall -O2 -fPIE -D_FORTIFY_SOURCE=2 -fstack-protector
|
||||||
ldflags_force=-static
|
ldflags_force=
|
||||||
ldflags=-pie -Wl,-z,relro -Wl,-z,now
|
ldflags=-static -pie -Wl,-z,relro -Wl,-z,now
|
||||||
dist=Makefile,loader.h
|
dist=Makefile,loader.h
|
||||||
mode=amd64-debug
|
mode=amd64-debug
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user