@ -26,8 +26,8 @@ LOG_MODULE_DECLARE(llext, CONFIG_LLEXT_LOG_LEVEL);
# define SYM_NAME_OR_SLID(name, slid) name
# define SYM_NAME_OR_SLID(name, slid) name
# endif
# endif
__weak int arch_elf_relocate ( elf_rela_t * rel , uintptr_t loc ,
__weak int arch_elf_relocate ( struct llext_loader * ldr , struct llext * ext , elf_rela_t * rel ,
uintptr_t sym_base_addr , const char * sym_name , uintptr_t load_bias )
const elf_shdr_t * shdr )
{
{
return - ENOTSUP ;
return - ENOTSUP ;
}
}
@ -142,22 +142,31 @@ static const void *llext_find_extension_sym(const char *sym_name, struct llext *
return se . addr ;
return se . addr ;
}
}
/**
/*
* @ brief Determine address of a symbol .
* Read the symbol entry corresponding to a relocation from the binary .
*
*/
* @ param ext llext extension
int llext_read_symbol ( struct llext_loader * ldr , struct llext * ext , const elf_rela_t * rel ,
* @ param ldr llext loader
elf_sym_t * sym )
* @ param link_addr ( output ) resolved address
{
* @ param rel relocation entry
int ret ;
* @ param sym symbol entry
* @ param name symbol name
ret = llext_seek ( ldr , ldr - > sects [ LLEXT_MEM_SYMTAB ] . sh_offset
* @ param shdr section header
+ ELF_R_SYM ( rel - > r_info ) * sizeof ( elf_sym_t ) ) ;
*
if ( ret ! = 0 ) {
* @ return 0 for OK , negative for error
return ret ;
}
ret = llext_read ( ldr , sym , sizeof ( elf_sym_t ) ) ;
return ret ;
}
/*
* Determine address of a symbol .
*/
*/
static int llext_lookup_symbol ( struct llext * ext , struct llext_loader * ldr , uintptr_t * link_addr ,
int llext_lookup_symbol ( struct llext_loader * ldr , struct llext * ext , uintptr_t * link_addr ,
const elf_rela_t * rel , const elf_sym_t * sym , const char * name ,
const elf_rela_t * rel , const elf_sym_t * sym , const char * name ,
const elf_shdr_t * shdr )
const elf_shdr_t * shdr )
{
{
if ( ELF_R_SYM ( rel - > r_info ) = = 0 ) {
if ( ELF_R_SYM ( rel - > r_info ) = = 0 ) {
/*
/*
@ -219,7 +228,6 @@ static int llext_lookup_symbol(struct llext *ext, struct llext_loader *ldr, uint
return 0 ;
return 0 ;
}
}
static void llext_link_plt ( struct llext_loader * ldr , struct llext * ext , elf_shdr_t * shdr ,
static void llext_link_plt ( struct llext_loader * ldr , struct llext * ext , elf_shdr_t * shdr ,
const struct llext_load_param * ldr_parm , elf_shdr_t * tgt )
const struct llext_load_param * ldr_parm , elf_shdr_t * tgt )
{
{
@ -359,7 +367,6 @@ int llext_link(struct llext_loader *ldr, struct llext *ext, const struct llext_l
{
{
uintptr_t sect_base = 0 ;
uintptr_t sect_base = 0 ;
elf_rela_t rel ;
elf_rela_t rel ;
elf_sym_t sym ;
elf_word rel_cnt = 0 ;
elf_word rel_cnt = 0 ;
const char * name ;
const char * name ;
int i , ret ;
int i , ret ;
@ -446,7 +453,7 @@ int llext_link(struct llext_loader *ldr, struct llext *ext, const struct llext_l
return - ENOEXEC ;
return - ENOEXEC ;
}
}
sect_base = ( uintptr_t ) llext_loaded_sect_ptr ( ldr , ext , shdr - > sh_info ) ;
sect_base = ( uintptr_t ) llext_loaded_sect_ptr ( ldr , ext , shdr - > sh_info ) ;
for ( int j = 0 ; j < rel_cnt ; j + + ) {
for ( int j = 0 ; j < rel_cnt ; j + + ) {
/* get each relocation entry */
/* get each relocation entry */
@ -460,47 +467,49 @@ int llext_link(struct llext_loader *ldr, struct llext *ext, const struct llext_l
return ret ;
return ret ;
}
}
/* get corresponding symbol */
# ifdef CONFIG_LLEXT_LOG_LEVEL
ret = llext_seek ( ldr , ldr - > sects [ LLEXT_MEM_SYMTAB ] . sh_offset
if ( CONFIG_LLEXT_LOG_LEVEL > = LOG_LEVEL_INF ) {
+ ELF_R_SYM ( rel . r_info ) * sizeof ( elf_sym_t ) ) ;
uintptr_t link_addr ;
if ( ret ! = 0 ) {
uintptr_t op_loc =
return ret ;
llext_get_reloc_instruction_location ( ldr , ext ,
}
shdr - > sh_info ,
& rel ) ;
ret = llext_read ( ldr , & sym , sizeof ( elf_sym_t ) ) ;
elf_sym_t sym ;
if ( ret ! = 0 ) {
return ret ;
}
name = llext_string ( ldr , ext , LLEXT_MEM_STRTAB , sym . st_name ) ;
ret = llext_read_symbol ( ldr , ext , & rel , & sym ) ;
LOG_DBG ( " relocation %d:%d info 0x%zx (type %zd, sym %zd) offset %zd "
if ( ret ! = 0 ) {
" sym_name %s sym_type %d sym_bind %d sym_ndx %d " ,
return ret ;
i , j , ( size_t ) rel . r_info , ( size_t ) ELF_R_TYPE ( rel . r_info ) ,
}
( size_t ) ELF_R_SYM ( rel . r_info ) , ( size_t ) rel . r_offset ,
name , ELF_ST_TYPE ( sym . st_info ) ,
ELF_ST_BIND ( sym . st_info ) , sym . st_shndx ) ;
uintptr_t link_addr , op_loc ;
name = llext_symbol_name ( ldr , ext , & sym ) ;
op_loc = sect_base + rel . r_offset ;
ret = llext_lookup_symbol ( ldr , ext , & link_addr , & rel , & sym , name ,
shdr ) ;
ret = llext_lookup_symbol ( ext , ldr , & link_addr , & rel , & sym , name , shdr ) ;
if ( ret ! = 0 ) {
LOG_ERR ( " Could not find symbol %s! " , name ) ;
return ret ;
}
if ( ret ! = 0 ) {
LOG_DBG ( " relocation %d:%d info 0x%zx (type %zd, sym %zd) offset %zd "
LOG_ERR ( " Failed to lookup symbol in rela section %d entry %d! " , i ,
" sym_name %s sym_type %d sym_bind %d sym_ndx %d " ,
j ) ;
i , j , ( size_t ) rel . r_info , ( size_t ) ELF_R_TYPE ( rel . r_info ) ,
return ret ;
( size_t ) ELF_R_SYM ( rel . r_info ) , ( size_t ) rel . r_offset ,
name , ELF_ST_TYPE ( sym . st_info ) ,
ELF_ST_BIND ( sym . st_info ) , sym . st_shndx ) ;
LOG_INF ( " writing relocation symbol %s type %zd sym %zd at addr "
" 0x%lx addr 0x%lx " ,
name , ( size_t ) ELF_R_TYPE ( rel . r_info ) ,
( size_t ) ELF_R_SYM ( rel . r_info ) ,
op_loc , link_addr ) ;
}
}
# endif /* CONFIG_LLEXT_LOG_LEVEL */
LOG_INF ( " writing relocation symbol %s type %zd sym %zd at addr 0x%lx "
" addr 0x%lx " ,
name , ( size_t ) ELF_R_TYPE ( rel . r_info ) , ( size_t ) ELF_R_SYM ( rel . r_info ) ,
op_loc , link_addr ) ;
/* relocation */
/* relocation */
ret = arch_elf_relocate ( & rel , op_loc , link_addr , name ,
ret = arch_elf_relocate ( ldr , ext , & rel , shdr ) ;
( uintptr_t ) ext - > mem [ LLEXT_MEM_TEXT ] ) ;
if ( ret ! = 0 ) {
if ( ret ! = 0 ) {
return ret ;
return ret ;
}
}