fix some symbol resolution issues in dynamic linker

1. search was wrongly beginning with lib itself rather than dso head
2. inconsistent resolution of function pointers for functions in plt
This commit is contained in:
Rich Felker 2011-06-25 22:36:21 -04:00
parent 1a3ff4f909
commit 32de61e81a
3 changed files with 6 additions and 4 deletions

View File

@ -4,6 +4,7 @@
#define ETC_LDSO_PATH "/etc/ld-musl-i386.path" #define ETC_LDSO_PATH "/etc/ld-musl-i386.path"
#define IS_COPY(x) ((x)==R_386_COPY) #define IS_COPY(x) ((x)==R_386_COPY)
#define IS_PLT(x) ((x)==R_386_JMP_SLOT)
static inline void do_single_reloc(size_t *reloc_addr, int type, size_t sym_val, size_t sym_size, unsigned char *base_addr, size_t addend) static inline void do_single_reloc(size_t *reloc_addr, int type, size_t sym_val, size_t sym_size, unsigned char *base_addr, size_t addend)
{ {

View File

@ -5,6 +5,7 @@
#define ETC_LDSO_PATH "/etc/ld-musl-x86_64.path" #define ETC_LDSO_PATH "/etc/ld-musl-x86_64.path"
#define IS_COPY(x) ((x)==R_X86_64_COPY) #define IS_COPY(x) ((x)==R_X86_64_COPY)
#define IS_PLT(x) ((x)==R_X86_64_JUMP_SLOT)
static inline void do_single_reloc(size_t *reloc_addr, int type, size_t sym_val, size_t sym_size, unsigned char *base_addr, size_t addend) static inline void do_single_reloc(size_t *reloc_addr, int type, size_t sym_val, size_t sym_size, unsigned char *base_addr, size_t addend)
{ {

View File

@ -114,7 +114,7 @@ static void do_relocs(unsigned char *base, size_t *rel, size_t rel_size, size_t
sym = syms + sym_index; sym = syms + sym_index;
name = strings + sym->st_name; name = strings + sym->st_name;
ctx = IS_COPY(type) ? dso->next : dso; ctx = IS_COPY(type) ? dso->next : dso;
sym_val = (size_t)find_sym(ctx, name, 1); sym_val = (size_t)find_sym(ctx, name, IS_PLT(type));
sym_size = sym->st_size; sym_size = sym->st_size;
} }
do_single_reloc(reloc_addr, type, sym_val, sym_size, base, rel[2]); do_single_reloc(reloc_addr, type, sym_val, sym_size, base, rel[2]);
@ -335,11 +335,11 @@ static void reloc_all(struct dso *p)
if (p->relocated) continue; if (p->relocated) continue;
decode_vec(p->dynv, dyn, DYN_CNT); decode_vec(p->dynv, dyn, DYN_CNT);
do_relocs(p->base, (void *)(p->base+dyn[DT_JMPREL]), dyn[DT_PLTRELSZ], do_relocs(p->base, (void *)(p->base+dyn[DT_JMPREL]), dyn[DT_PLTRELSZ],
2+(dyn[DT_PLTREL]==DT_RELA), p->syms, p->strings, p); 2+(dyn[DT_PLTREL]==DT_RELA), p->syms, p->strings, head);
do_relocs(p->base, (void *)(p->base+dyn[DT_REL]), dyn[DT_RELSZ], do_relocs(p->base, (void *)(p->base+dyn[DT_REL]), dyn[DT_RELSZ],
2, p->syms, p->strings, p); 2, p->syms, p->strings, head);
do_relocs(p->base, (void *)(p->base+dyn[DT_RELA]), dyn[DT_RELASZ], do_relocs(p->base, (void *)(p->base+dyn[DT_RELA]), dyn[DT_RELASZ],
3, p->syms, p->strings, p); 3, p->syms, p->strings, head);
p->relocated = 1; p->relocated = 1;
} }
} }