Copy fd_ebpf_link_opts_t *
fd_ebpf_static_link( fd_ebpf_link_opts_t * const opts,
void * const elf,
ulong const elf_sz ) {
# define FD_ELF_REQUIRE(c) do { if( FD_UNLIKELY( !(c) ) ) { FD_LOG_WARNING(( "FAIL: %s", #c )); return NULL; } } while(0)
...
...
for( uint i=0; i < eh->e_shnum; i++ ) {
...
}
FD_ELF_REQUIRE( prog_shndx >=0 );
FD_ELF_REQUIRE( rel_prog_shndx>=0 );
FD_ELF_REQUIRE( symtab_shndx >=0 );
FD_ELF_REQUIRE( strtab_shndx >=0 );
/* Load bytecode */
...
/* Load symbol table */
...
ulong sym_cnt = symtab->sh_size / sizeof(fd_elf64_sym);
fd_elf64_sym const * sym = (fd_elf64_sym *)( (ulong)elf + symtab->sh_offset );
FD_ELF_REQUIRE( sym_cnt <= FD_EBPF_MAX_SYM_CNT );
/* Load string table */
...
ulong rel_cnt = rel_prog->sh_size / sizeof(fd_elf64_rel);
fd_elf64_rel const * rel = (fd_elf64_rel *)( (ulong)elf + rel_prog->sh_offset );
/* Create symbol mapping table */
1. fd_ebpf_known_sym_t sym_mapping[ FD_EBPF_MAX_SYM_CNT ];
/* Walk symbol table */
2. for( ulong i=0; i<sym_cnt; i++ ) {
char const * sym_name = fd_elf_read_cstr( elf, elf_sz, strtab->sh_offset + sym[ i ].st_name, 128UL );
if( !sym_name ) continue;
/* TODO: O(n^2) complexity -- fine for now as factors are small */
for( ulong j=0; j<opts->sym_cnt; j++ ) {
if( 0==strcmp( sym_name, opts->sym[ j ].name ) ) {
sym_mapping[ i ] = (fd_ebpf_known_sym_t) {
.known = 1,
.value = (ulong)(uint)opts->sym[ j ].value
};
}
}
}
/* Apply relocations */
for( ulong i=0; i<rel_cnt; i++ ) {
FD_ELF_REQUIRE( rel[ i ].r_offset < prog->sh_size );
FD_ELF_REQUIRE( rel[ i ].r_offset+8UL <=prog->sh_size );
ulong r_sym = FD_ELF64_R_SYM( rel[ i ].r_info );
ulong r_type = FD_ELF64_R_TYPE( rel[ i ].r_info );
FD_ELF_REQUIRE( r_sym < sym_cnt );
3. ulong S = sym_mapping[ r_sym ].value;
/* TODO another bounds check? */
switch( r_type ) {
case FD_ELF_R_BPF_64_64: {
ulong r_lo_off = prog->sh_offset + rel[ i ].r_offset + 4UL;
ulong r_hi_off = prog->sh_offset + rel[ i ].r_offset + 12UL;
...
FD_STORE( ulong, insn+0, insn0_post );
FD_STORE( ulong, insn+8, insn1_post );
break;
}
default:
FD_LOG_WARNING(( "reloc %lu: Unsupported relocation type %#lx", i, r_type ));
return NULL;
}
}
opts->bpf = (void *)( (ulong)elf + prog->sh_offset );
opts->bpf_sz = fd_ulong_align_dn( prog->sh_size, 8UL );
return opts;
# undef FD_ELF_REQUIRE
}