Skip to content

Commit

Permalink
* add macos support; no VMA filtering
Browse files Browse the repository at this point in the history
* add macos REL sample
  • Loading branch information
blu committed Sep 11, 2021
1 parent e9aba33 commit 8c2b0ec
Show file tree
Hide file tree
Showing 9 changed files with 224 additions and 60 deletions.
31 changes: 16 additions & 15 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -5,30 +5,31 @@ CXXFLAGS += -std=c++11 -Ofast -fno-exceptions -fno-rtti -DNDEBUG -DPAGE_SIZE=$(s
LDFLAGS += -lelf
ASFLAGS += --strip-local-absolute
# Optional test objects built by target ALL
REL := test_rodata.o \
test_data.o \
test_bss.o \
test_cross_0.o \
test_cross_1.o \
test_bounce.o \
test_bounce_neon.o \
test_bounce_neon_aosoa.o \
test_bounce_neon_aosoa_bg.o \
test_bounce_data_aosoa_alt_0.o \
test_bounce_data_aosoa_alt_1.o \
test_bounce_data_aosoa_alt_2.o \
test_bounce_data_aosoa_alt_3.o
REL := test_text.o \
test_rodata.o \
test_data.o \
test_bss.o \
test_cross_0.o \
test_cross_1.o \
test_bounce.o \
test_bounce_neon.o \
test_bounce_neon_aosoa.o \
test_bounce_neon_aosoa_bg.o \
test_bounce_data_aosoa_alt_0.o \
test_bounce_data_aosoa_alt_1.o \
test_bounce_data_aosoa_alt_2.o \
test_bounce_data_aosoa_alt_3.o

OBJ := $(addsuffix .o, $(basename $(filter %.s %.c %.cpp, $(SRC))))

$(TARGET): $(OBJ)
$(CC) $^ $(LDFLAGS) -o $(TARGET)

reloc.o: reloc.c vma.h
reloc.o: reloc.c vma.h char_ptr_arr.h

reloc_add_aarch64.o: reloc_add_aarch64.c insn.h

vma.o: vma.cpp vma.h
vma.o: vma.cpp vma.h char_ptr_arr.h

test_bounce.o: test_bounce.s
$(AS) $(ASFLAGS) --defsym FB_DIM_X=$(shell tput cols) --defsym FB_DIM_Y=$(shell tput lines) --defsym FRAMES=1024 -o $@ $^
Expand Down
21 changes: 21 additions & 0 deletions Makefile.macos
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
SRC := reloc.c reloc_add_aarch64.c insn.h
TARGET := elvenrel
CFLAGS += -std=gnu11 -Ofast -DNDEBUG -DPAGE_SIZE=$(shell getconf PAGE_SIZE) -fno-stack-protector -fPIC -I/opt/homebrew/include
LDFLAGS += /opt/homebrew/lib/libelf.a
ASFLAGS += --target=aarch64-none-linux-gnu
# Optional test objects built by target ALL
REL := test_text_macos.o

OBJ := $(addsuffix .o, $(basename $(filter %.s %.c %.cpp, $(SRC))))

$(TARGET): $(OBJ)
$(CC) $^ $(LDFLAGS) -o $(TARGET)

reloc.o: reloc.c char_ptr_arr.h

reloc_add_aarch64.o: reloc_add_aarch64.c insn.h

all: $(TARGET) $(REL)

clean:
rm -f $(TARGET) $(OBJ) $(REL)
12 changes: 8 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
## elvenrel

Elven Relativism -- relocation and execution of aarch64 ELF relocatable objects (REL)
Elven Relativism -- relocation and execution of aarch64 ELF relocatable objects (REL) on Linux and macOS.

Program loads a multitude of ELF REL files, resolves all relocations (currently only SHT_RELA) and if symbol `_start` in some section `.text` is found, passes control to the former.

## Details

* RELs loaded in the order specified on the command line; all relocations in a given REL performed at its loading time.
* Missing-symbol (SHN_UNDEF) resolution via reverse-direction search among the preceding RELs; first-match deterministic.
* Support for RO sections `.rodata` and `.text`; every other type of section is RW; `.bss` addressing may take HI21/LO12.
* Address-space sanitation -- disposing of pre-existing VMAs (*VMA filtering*) via string matching to VMA backing path.
* Support for RO sections `.rodata` and `.text`; every other type of section is RW.
* Address-space sanitation (linux-only) -- disposing of pre-existing VMAs (*VMA filtering*) via string matching to VMA backing path.

## ToDo

Expand All @@ -24,10 +24,14 @@ Files used, with or without modifications, from external repositories:
linux.org/ arch/arm64/kernel/module.c -> reloc_add_aarch64.c
linux.org/ arch/arm64/lib/strlen.S -> strlen_linux.s

## Building
## Building: linux

$ make all

## Building: macos

$ make -f Makefile.macos all

## Usage

```sh
Expand Down
10 changes: 10 additions & 0 deletions char_ptr_arr.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
#ifndef __char_ptr_arr_H__
#include <stddef.h>

struct char_ptr_arr_t {
size_t count;
char **arr;
};

#endif /* __char_ptr_arr_H__ */

96 changes: 61 additions & 35 deletions reloc.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,11 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#if __APPLE__ != 0
#include <libelf/libelf.h>
#else
#include <libelf.h>
#endif
#include <fcntl.h>
#include <stddef.h>
#include <stdint.h>
Expand All @@ -16,7 +20,23 @@
#include <sys/stat.h>
#include <sys/mman.h>

#if __APPLE__ != 0
#include "char_ptr_arr.h"
#else
#include "vma.h"
#endif

#if __APPLE__ != 0
#ifndef EM_AARCH64
#define EM_AARCH64 183
#endif

#ifndef MAP_POPULATE
#define MAP_POPULATE 0
#endif

typedef Elf64_Half Elf64_Section;
#endif

int apply_relocate_add(Elf64_Shdr **sechdrs,
unsigned int symsec,
Expand Down Expand Up @@ -63,12 +83,12 @@ const char *str_from_st_type(uint8_t x)
return "STT_TLS";
case STT_NUM:
return "STT_NUM";
#if 0
case STT_LOOS:
return "STT_LOOS";
#endif
#if 0
case STT_GNU_IFUNC:
return "STT_GNU_IFUNC";
#endif
case STT_HIOS:
return "STT_HIOS";
case STT_LOPROC:
Expand All @@ -90,12 +110,12 @@ const char *str_from_st_bind(uint8_t x)
return "STB_WEAK";
case STB_NUM:
return "STB_NUM";
#if 0
case STB_LOOS:
return "STB_LOOS";
#endif
#if 0
case STB_GNU_UNIQUE:
return "STB_GNU_UNIQUE";
#endif
case STB_HIOS:
return "STB_HIOS";
case STB_LOPROC:
Expand Down Expand Up @@ -253,14 +273,14 @@ static int
_load_elf_file_details(
Elf *elf,
ElfDetails *ret_details,
ptrdiff_t diff_exec)
void *rawdata_rw,
void *rawdata_ro)
{
ElfDetails details;
char *ehdr_ident;
Elf64_Ehdr *ehdr64;
Elf64_Shdr *shdr64;
Elf_Scn *scn;
Elf_Data *data;
const char *scn_name;
Elf64_Shdr **section_list;
size_t scn_idx, n_elf_scns;
Expand Down Expand Up @@ -434,33 +454,26 @@ static int
}
}

/* Resolve the vaddr and size of ELF section data */
if ((data = elf_getdata(scn, 0)) != NULL) {
if (shdr64->sh_size != data->d_size) {
return -1;
}
/* Ignore empty sections */
if (data->d_size != 0) {
/* Section .bss does not have file backing */
if (scn_idx == bss_idx) {
const int prot_rw = PROT_READ | PROT_WRITE;
const int flag_priv_anon = MAP_PRIVATE | MAP_ANONYMOUS | MAP_POPULATE;

void *p = mmap(NULL, data->d_size, prot_rw, flag_priv_anon, -1, 0);

if (p == MAP_FAILED) {
fprintf(stderr, "error: cannot mmap bss\n");
return -1;
}
/* Resolve the vaddr of non-empty ELF section data */
if (shdr64->sh_size != 0) {
/* Section .bss does not have file backing */
if (scn_idx == bss_idx) {
const int prot_rw = PROT_READ | PROT_WRITE;
const int flag_priv_anon = MAP_PRIVATE | MAP_ANONYMOUS | MAP_POPULATE;

shdr64->sh_addr = (Elf64_Addr)p;
} else {
shdr64->sh_addr = (Elf64_Addr)data->d_buf;
void *p = mmap(NULL, shdr64->sh_size, prot_rw, flag_priv_anon, -1, 0);

if (scn_idx == text_idx ||
scn_idx == rodata_idx) {
shdr64->sh_addr += diff_exec;
}
if (p == MAP_FAILED) {
fprintf(stderr, "error: cannot mmap bss\n");
return -1;
}

shdr64->sh_addr = (Elf64_Addr)p;
} else {
if (scn_idx == text_idx || scn_idx == rodata_idx) {
shdr64->sh_addr = (Elf64_Addr)(rawdata_ro + shdr64->sh_offset);
} else {
shdr64->sh_addr = (Elf64_Addr)(rawdata_rw + shdr64->sh_offset);
}
}
}
Expand Down Expand Up @@ -509,16 +522,21 @@ static int
relocate_elf_load_cu(
Elf *elf,
void **start,
ptrdiff_t diff_exec,
void *rawdata_rw,
void *rawdata_ro,
int flag_quiet)
{
ElfDetails details = NULL;
Elf64_Sym *symtab;
uint64 n_symbols, i;
int rc;

if (!elf || !start || !rawdata_rw || !rawdata_ro) {
return -1;
}

/* Load ELF file section and symbol tables */
rc = _load_elf_file_details(elf, &details, diff_exec);
rc = _load_elf_file_details(elf, &details, rawdata_rw, rawdata_ro);
if (rc)
goto term;

Expand Down Expand Up @@ -554,7 +572,7 @@ static int
}

if (!flag_quiet) {
printf("%2ld: %016lx %-13s %-14s %-17s %s\n",
printf("%2lu: %016lx %-13s %-14s %-17s %s\n",
i,
symtab->st_value,
str_from_st_type(ELF64_ST_TYPE(symtab->st_info)),
Expand Down Expand Up @@ -591,15 +609,19 @@ static int
static void print_usage(char **argv)
{
printf("usage: %s <elf_rel_file> [<elf_rel_file>] ..\n"
#if __APPLE__ == 0
"\t--filter <string> : filter file mappings containing the specified string\n"
#endif
"\t--quiet : suppress all reports\n"
"\t--help : this message\n", argv[0]);
}

int main(int argc, char **argv)
{
size_t areas_capacity = 0, objs_capacity = 0;
#if __APPLE__ == 0
struct char_ptr_arr_t areas = { .count = 0, .arr = NULL };
#endif
struct char_ptr_arr_t objs = { .count = 0, .arr = NULL };
Elf *prev_elf = NULL;
void *start = NULL;
Expand All @@ -622,6 +644,7 @@ int main(int argc, char **argv)
continue;
}

#if __APPLE__ == 0
if (!strcmp(argv[i], "--filter")) {
if (++i == argc) {
print_usage(argv);
Expand All @@ -634,6 +657,7 @@ int main(int argc, char **argv)
continue;
}

#endif
/* Unprefixed arg must be a file */
if (objs.count == objs_capacity) {
objs.arr = (char **)realloc(objs.arr, objs_capacity = (objs_capacity + 1) * 2);
Expand Down Expand Up @@ -698,7 +722,7 @@ int main(int argc, char **argv)
ehdr64->e_entry = (Elf64_Addr)prev_elf;
prev_elf = elf;

if (relocate_elf_load_cu(elf, &start, q - p, flag_quiet)) {
if (relocate_elf_load_cu(elf, &start, p, q, flag_quiet)) {
fprintf(stderr, "error: cannot relocate_elf_load_cu\n");
return -1;
}
Expand All @@ -709,9 +733,11 @@ int main(int argc, char **argv)
}
}

#if __linux__ != 0
if (areas.count && areas.arr != NULL)
vma_process(&areas, flag_quiet);

#endif
if (start != NULL)
((void (*)(void))start)();

Expand Down
Loading

0 comments on commit 8c2b0ec

Please sign in to comment.