📄 reloc.c
字号:
/* *---------------------------------------------------------------------- * T-Kernel / Standard Extension * * Copyright (C) 2006 by Ken Sakamura. All rights reserved. * T-Kernel / Standard Extension is distributed * under the T-License for T-Kernel / Standard Extension. *---------------------------------------------------------------------- * * Version: 1.00.00 * Released by T-Engine Forum(http://www.t-engine.org) at 2006/8/11. * *---------------------------------------------------------------------- *//* * @(#)reloc.c (solib) * * Shared object(SO)support library * Relocation relation */#include <string.h>#include "../../so.h"Inline void lazy_relocsection( DLInfo *dlp, Elf32_Rela *rela, UW size );Inline ER relocate( DLInfo *dlp, UW lazy );LOCAL ER relocsection( DLInfo *dlp, Elf32_Rela *rela, UW size );#define TSD_RLO_GOT_1 1#define TSD_RLO_GOT_2 2/* * 1 section relocation and symbol link */LOCAL ER relocsection( DLInfo *dlp, Elf32_Rela *rela, UW size ){ Elf32_Rela *end = rela + (size / sizeof(Elf32_Rela)); W ldofs = dlp->ldofs; UB *strtab = dlp->strtab; Elf32_Sym *symtab = dlp->symtab; Elf32_Sym *sym; UB *name; UW type, symno; UW *wp, val, tmp; ER err; UW *uwp; for ( ; rela < end; rela++ ) { type = ELF32_R_TYPE(rela->r_info); wp = (UW*)((UB *)(rela->r_offset) + ldofs); switch ( type ) { case R_SH_NONE: continue; case R_SH_RELATIVE: if (rela->r_addend != 0) { *wp = (UW)((UW*)ldofs + rela->r_addend); } else { *wp += (UW)ldofs; } continue; default: /* nothing to do */ break; } symno = ELF32_R_SYM(rela->r_info); /* Symbol value acquisition (link of symbol) */ name = strtab + symtab[symno].st_name; val = __so_resolve(dlp, name, type, &sym); /* The undefined symbol excepting "weak" attribute is error */ if ( (sym == NULL) && (ELF32_ST_BIND(symtab[symno].st_info) != STB_WEAK) ) { SYSLOG((LOG_ERR, "solib: %s is not defined", name)); err = E_REC; goto err_ret; } /* Relocation */ switch ( type ) { case R_SH_JMP_SLOT: /* Store the symbol value */ uwp = (UW*)((UB *)(rela->r_offset) + ldofs); *uwp = val; break; case R_SH_COPY: if ( sym == NULL ) { err = E_REC; goto err_ret; } if ( sym->st_size > symtab[symno].st_size ) { err = E_REC; goto err_ret; } memcpy(wp, (VP)val, sym->st_size); break; case R_SH_GOT32: case R_SH_DIR32: tmp = val + (UW)rela->r_addend; if ( *wp != tmp ) { *wp = tmp; } break; case R_SH_REL32: tmp = (UW)((UW *)(val + (UW)rela->r_addend) - wp); if (*wp != tmp) { *wp = tmp; } break; case R_SH_GLOB_DAT: tmp = (UW)((UW*)val + rela->r_addend); if (*wp != tmp) { *wp = tmp; } break; default: SYSLOG((LOG_ERR, "solib: unsupported relocation type (%d)", type)); err = E_REC; goto err_ret; } } return E_OK;err_ret: DEBUG_PRINT(("relocsection err = %d\n", err)); return err;}/* * Relocation of 1 section (only) */Inline void lazy_relocsection( DLInfo *dlp, Elf32_Rela *rela, UW size ){ Elf32_Rela *end = rela + (size / sizeof(Elf32_Rela)); W ldofs = dlp->ldofs; UW *uwp; for ( ; rela < end; rela++ ) { /* Everything should be R_SH_JMP_SLOT */ uwp = (UW*)((UB *)(rela->r_offset) + ldofs); *uwp += (UW)ldofs; }}/* * Relocation of 1 object */Inline ER relocate( DLInfo *dlp, UW lazy ){ ER err; if (dlp->got != NULL) { /* Register the runtime resolver for sequential link of symbol */ dlp->got[TSD_RLO_GOT_1] = dlp; dlp->got[TSD_RLO_GOT_2] = (VP)__so_runtime_resolve; } /* DT_RELA relocation and symbol link */ err = relocsection(dlp, dlp->relatab, dlp->relasz); if ( err < E_OK ) { goto err_ret; } if ( (lazy == 0U) || (__so_LazyMode == 0) ) { /* DT_PLTREL relocation and symbol link */ err = relocsection(dlp, (Elf32_Rela *)dlp->jreltab, dlp->jrelsz); if ( err < E_OK ) { goto err_ret; } } else { /* DT_PLTREL relocation only */ lazy_relocsection(dlp, (Elf32_Rela *)dlp->jreltab, dlp->jrelsz); } dlp->relocated = TRUE; return E_OK;err_ret: DEBUG_PRINT(("relocate err = %d\n", err)); return err;}/* * Relocation of the entire load object */EXPORT ER __so_relocate( DLInfo *loader, UW lazy ){ QUEUE *q; DLInfo *dlp; ER err; /* Relocation is done in order of the latest loading */ q = &__dlInfo.q; do { dlp = (DLInfo*)(q = q->prev); if ( dlp->relocated != 0 ) { continue; } err = relocate(dlp, lazy); if ( err < E_OK ) { goto err_ret; } } while ( q != &loader->q ); return E_OK;err_ret: DEBUG_PRINT(("__so_relocate err = %d\n", err)); return err;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -