Skip to content

Commit

Permalink
adding support for clang relocations
Browse files Browse the repository at this point in the history
Added support for clang function and string relocations, these show as up as
R_BPF_64_64 and R_BPF_64_32 in *-readelf relocations. Support for nosetests elf
tests is still TBD.

Signed-off-by: Ray Kinsella <mdr@ashroe.eu>
  • Loading branch information
mdr78 committed Jul 13, 2022
1 parent 5c11221 commit 3f28fd2
Show file tree
Hide file tree
Showing 3 changed files with 62 additions and 16 deletions.
2 changes: 2 additions & 0 deletions vm/ubpf_int.h
Expand Up @@ -30,6 +30,8 @@ struct ubpf_vm {
ubpf_jit_fn jitted;
size_t jitted_size;
ext_func *ext_funcs;
void *rodata;
size_t rodata_size;
const char **ext_func_names;
bool bounds_check_enabled;
int (*error_printf)(FILE* stream, const char* format, ...);
Expand Down
75 changes: 59 additions & 16 deletions vm/ubpf_loader.c
Expand Up @@ -16,6 +16,7 @@

#include <ubpf_config.h>

#include <stdint.h>
#define _GNU_SOURCE
#include <stdio.h>
#include <string.h>
Expand Down Expand Up @@ -149,6 +150,18 @@ ubpf_load_elf(struct ubpf_vm *vm, const void *elf, size_t elf_size, char **errms

struct section *text = &sections[text_shndx];

/* Find first read-only data section */
struct section *rodata = 0;
int rodata_shndx = 0;
for (i = 0; i < ehdr->e_shnum; i++) {
const Elf64_Shdr *shdr = sections[i].shdr;
if (shdr->sh_type == SHT_PROGBITS &&
shdr->sh_flags == (SHF_ALLOC | SHF_STRINGS | SHF_MERGE)) {
rodata_shndx = i;
break;
}
}

/* May need to modify text for relocations, so make a copy */
text_copy = malloc(text->size);
if (!text_copy) {
Expand All @@ -157,6 +170,19 @@ ubpf_load_elf(struct ubpf_vm *vm, const void *elf, size_t elf_size, char **errms
}
memcpy(text_copy, text->data, text->size);

/* if we found rodata, we need to copy the strings out */
if (rodata_shndx) {
rodata = &sections[rodata_shndx];

vm->rodata = malloc(rodata->size);
if (!vm->rodata) {
*errmsg = ubpf_error("failed to allocate memory");
goto error;
}
memcpy(vm->rodata, rodata->data, rodata->size);
vm->rodata_size = rodata->size;
}

/* Process each relocation section */
for (i = 0; i < ehdr->e_shnum; i++) {
struct section *rel = &sections[i];
Expand Down Expand Up @@ -188,39 +214,56 @@ ubpf_load_elf(struct ubpf_vm *vm, const void *elf, size_t elf_size, char **errms
int j;
for (j = 0; j < rel->size/sizeof(Elf64_Rel); j++) {
const Elf64_Rel *r = &rs[j];

if (ELF64_R_TYPE(r->r_info) != 2) {
*errmsg = ubpf_error("bad relocation type %u", ELF64_R_TYPE(r->r_info));
goto error;
uint8_t type = ELF64_R_TYPE(r->r_info);

/* must be R_BPF_64_32 or R_BPF_64_64 */
if (!(type == 0xA ||
type == 0x1 ||
type == 0x2)) {
*errmsg = ubpf_error("bad relocation type %u", type);
goto error;
}

uint32_t sym_idx = ELF64_R_SYM(r->r_info);
if (sym_idx >= num_syms) {
*errmsg = ubpf_error("bad symbol index");
goto error;
*errmsg = ubpf_error("bad symbol index");
goto error;
}

const Elf64_Sym *sym = &syms[sym_idx];

if (sym->st_name >= strtab->size) {
*errmsg = ubpf_error("bad symbol name");
goto error;
*errmsg = ubpf_error("bad symbol name");
goto error;
}

const char *sym_name = strings + sym->st_name;
if (type == 0xA || type == 0x2) {
const char *sym_name = strings + sym->st_name;

if (r->r_offset + 8 > text->size) {
if (r->r_offset + 8 > text->size) {
*errmsg = ubpf_error("bad relocation offset");
goto error;
}

unsigned int imm = ubpf_lookup_registered_function(vm, sym_name);
if (imm == -1) {
}
unsigned int imm = ubpf_lookup_registered_function(vm, sym_name);
if (imm == -1) {
*errmsg = ubpf_error("function '%s' not found", sym_name);
goto error;
}
}

*(uint32_t *)(text_copy + r->r_offset + 4) = imm;
*(uint32_t *)(text_copy + r->r_offset + 4) = imm;
} else {
uintptr_t imm = (uintptr_t)vm->rodata + sym->st_value;

if (!vm->rodata || vm->rodata_size < sym->st_value) {
*errmsg = ubpf_error("bad relocation offset");
goto error;
}

*(uint32_t *)(text_copy + r->r_offset + 4) = /* instr + 1 */
(imm & 0xFFFFFFFF);
*(uint32_t *)(text_copy + r->r_offset + 12) = /* instr + 1 */
((imm >> 32) & 0xFFFFFFFF);
}
}
}

Expand Down
1 change: 1 addition & 0 deletions vm/ubpf_vm.c
Expand Up @@ -90,6 +90,7 @@ ubpf_destroy(struct ubpf_vm *vm)
ubpf_unload_code(vm);
free(vm->ext_funcs);
free(vm->ext_func_names);
free(vm->rodata);
free(vm);
}

Expand Down

0 comments on commit 3f28fd2

Please sign in to comment.