Browse Source

simplify/shrink relocation processing in dynamic linker stage 1

the outer-loop approach made sense when we were also processing
DT_JMPREL, which might be in REL or RELA form, to avoid major code
duplication. commit 09db855b35 removed
processing of DT_JMPREL, and in the remaining two tables, the format
(REL or RELA) is known by the name of the table. simply writing two
versions of the loop results in smaller and simpler code.
master
Rich Felker 11 years ago
parent
commit
0e0e49421f
  1. 40
      src/ldso/dlstart.c

40
src/ldso/dlstart.c

@ -56,30 +56,22 @@ void _dlstart_c(size_t *sp, size_t *dynv)
for (i=0; i<local_cnt; i++) got[i] += (size_t)base; for (i=0; i<local_cnt; i++) got[i] += (size_t)base;
} }
/* The use of the reloc_info structure and nested loops is a trick size_t *rel, rel_size;
* to work around the fact that we can't necessarily make function
* calls yet. Each struct in the array serves like the arguments rel = (void *)(base+dyn[DT_REL]);
* to a function call. */ rel_size = dyn[DT_RELSZ];
struct { for (; rel_size; rel+=2, rel_size-=2*sizeof(size_t)) {
void *rel; if (!IS_RELATIVE(rel[1])) continue;
size_t size; size_t *rel_addr = (void *)(base + rel[0]);
size_t stride; *rel_addr += (size_t)base;
} reloc_info[] = { }
{ base+dyn[DT_REL], dyn[DT_RELSZ], 2 },
{ base+dyn[DT_RELA], dyn[DT_RELASZ], 3 }, rel = (void *)(base+dyn[DT_RELA]);
{ 0, 0, 0 } rel_size = dyn[DT_RELASZ];
}; for (; rel_size; rel+=3, rel_size-=3*sizeof(size_t)) {
if (!IS_RELATIVE(rel[1])) continue;
for (i=0; reloc_info[i].stride; i++) { size_t *rel_addr = (void *)(base + rel[0]);
size_t *rel = reloc_info[i].rel; *rel_addr = (size_t)base + rel[2];
size_t rel_size = reloc_info[i].size;
size_t stride = reloc_info[i].stride;
for (; rel_size; rel+=stride, rel_size-=stride*sizeof(size_t)) {
if (!IS_RELATIVE(rel[1])) continue;
size_t *rel_addr = (void *)(base + rel[0]);
size_t addend = stride==3 ? rel[2] : *rel_addr;
*rel_addr = (size_t)base + addend;
}
} }
const char *strings = (void *)(base + dyn[DT_STRTAB]); const char *strings = (void *)(base + dyn[DT_STRTAB]);

Loading…
Cancel
Save