/* cache the address, ELF header is available only during module load */ if (!pltsec->plt_ent)
pltsec->plt_ent = (struct plt_entries *)pltsec->plt->sh_addr;
plt = pltsec->plt_ent;
prealloc_fixed(pltsec, plt);
for (idx = 0; idx < ARRAY_SIZE(fixed_plts); ++idx) if (plt->lit[idx] == val) return (u32)&plt->ldr[idx];
idx = 0; /* * Look for an existing entry pointing to 'val'. Given that the * relocations are sorted, this will be the last entry we allocated. * (if one exists).
*/ if (pltsec->plt_count > 0) {
plt += (pltsec->plt_count - 1) / PLT_ENT_COUNT;
idx = (pltsec->plt_count - 1) % PLT_ENT_COUNT;
if (plt->lit[idx] == val) return (u32)&plt->ldr[idx];
staticint cmp_rel(constvoid *a, constvoid *b)
{ const Elf32_Rel *x = a, *y = b; int i;
/* sort by type and symbol index */
i = cmp_3way(ELF32_R_TYPE(x->r_info), ELF32_R_TYPE(y->r_info)); if (i == 0)
i = cmp_3way(ELF32_R_SYM(x->r_info), ELF32_R_SYM(y->r_info)); return i;
}
/* * Do a bitwise compare on the raw addend rather than fully decoding * the offset and doing an arithmetic comparison. * Note that a zero-addend jump/call relocation is encoded taking the * PC bias into account, i.e., -8 for ARM and -4 for Thumb2.
*/ switch (ELF32_R_TYPE(rel->r_info)) {
u16 upper, lower;
case R_ARM_THM_CALL: case R_ARM_THM_JUMP24:
upper = __mem_to_opcode_thumb16(((u16 *)tval)[0]);
lower = __mem_to_opcode_thumb16(((u16 *)tval)[1]);
/* * Entries are sorted by type and symbol index. That means that, * if a duplicate entry exists, it must be in the preceding * slot.
*/ if (!num) returnfalse;
/* Count how many PLT entries we may need */ staticunsignedint count_plts(const Elf32_Sym *syms, Elf32_Addr base, const Elf32_Rel *rel, int num, Elf32_Word dstidx)
{ unsignedint ret = 0; const Elf32_Sym *s; int i;
for (i = 0; i < num; i++) { switch (ELF32_R_TYPE(rel[i].r_info)) { case R_ARM_CALL: case R_ARM_PC24: case R_ARM_JUMP24: case R_ARM_THM_CALL: case R_ARM_THM_JUMP24: /* * We only have to consider branch targets that resolve * to symbols that are defined in a different section. * This is not simply a heuristic, it is a fundamental * limitation, since there is no guaranteed way to emit * PLT entries sufficiently close to the branch if the * section size exceeds the range of a branch * instruction. So ignore relocations against defined * symbols if they live in the same section as the * relocation target.
*/
s = syms + ELF32_R_SYM(rel[i].r_info); if (s->st_shndx == dstidx) break;
/* * Jump relocations with non-zero addends against * undefined symbols are supported by the ELF spec, but * do not occur in practice (e.g., 'jump n bytes past * the entry point of undefined function symbol f'). * So we need to support them, but there is no need to * take them into consideration when trying to optimize * this code. So let's only check for duplicates when * the addend is zero. (Note that calls into the core * module via init PLT entries could involve section * relative symbol references with non-zero addends, for * which we may end up emitting duplicates, but the init * PLT is released along with the rest of the .init * region as soon as module loading completes.)
*/ if (!is_zero_addend_relocation(base, rel + i) ||
!duplicate_rel(base, rel, i))
ret++;
}
} return ret;
}
/* * To store the PLTs, we expand the .text section for core module code * and for initialization code.
*/ for (s = sechdrs; s < sechdrs_end; ++s) { if (strcmp(".plt", secstrings + s->sh_name) == 0)
mod->arch.core.plt = s; elseif (strcmp(".init.plt", secstrings + s->sh_name) == 0)
mod->arch.init.plt = s; elseif (s->sh_type == SHT_SYMTAB)
syms = (Elf32_Sym *)s->sh_addr;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.