-
-
Save sorear/f17038387b871ff0a16c74a85d987c05 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff --git a/ldso/dynlink.c b/ldso/dynlink.c | |
index 324aa859..91d91e1c 100644 | |
--- a/ldso/dynlink.c | |
+++ b/ldso/dynlink.c | |
@@ -379,6 +379,17 @@ nomatch: | |
return (struct symdef){ 0 }; | |
} | |
+static size_t get_leb128(unsigned char **buf, size_t sleb_uleb) | |
+{ | |
+ size_t tmp = 0, shift = 0, byte; | |
+ do { | |
+ byte = *(*buf)++; | |
+ tmp += (byte - 128*(byte >= sleb_uleb)) << shift; | |
+ shift += 7; | |
+ } while (byte < 128); | |
+ return tmp; | |
+} | |
+ | |
static void do_relocs(struct dso *dso, size_t *rel, size_t rel_size, size_t stride) | |
{ | |
unsigned char *base = dso->base; | |
@@ -394,6 +405,8 @@ static void do_relocs(struct dso *dso, size_t *rel, size_t rel_size, size_t stri | |
size_t sym_val; | |
size_t tls_val; | |
size_t addend; | |
+ size_t offset_shift, rel_head; | |
+ unsigned char *relp; | |
int skip_relative = 0, reuse_addends = 0, save_slot = 0; | |
if (dso == &ldso) { | |
@@ -403,28 +416,53 @@ static void do_relocs(struct dso *dso, size_t *rel, size_t rel_size, size_t stri | |
skip_relative = 1; | |
} | |
+#ifndef DL_FDPIC | |
+ if (!stride) { | |
+ sym_index = addend = type = 0; | |
+ reloc_addr = laddr(dso, 0); | |
+ relp = (unsigned char*)rel; | |
+ rel_size = get_leb128(&relp, 128); | |
+ offset_shift = rel_size & 3; | |
+ rel_size >>= 2; | |
+ } | |
+#endif | |
+ | |
for (; rel_size; rel+=stride, rel_size-=stride*sizeof(size_t)) { | |
- if (skip_relative && IS_RELATIVE(rel[1], dso->syms)) continue; | |
- type = R_TYPE(rel[1]); | |
- if (type == REL_NONE) continue; | |
- reloc_addr = laddr(dso, rel[0]); | |
- | |
- if (stride > 2) { | |
- addend = rel[2]; | |
- } else if (type==REL_GOT || type==REL_PLT|| type==REL_COPY) { | |
- addend = 0; | |
- } else if (reuse_addends) { | |
- /* Save original addend in stage 2 where the dso | |
- * chain consists of just ldso; otherwise read back | |
- * saved addend since the inline one was clobbered. */ | |
- if (head==&ldso) | |
- saved_addends[save_slot] = *reloc_addr; | |
- addend = saved_addends[save_slot++]; | |
+#ifndef DL_FDPIC | |
+ if (!stride) { | |
+ rel_head = *relp++; | |
+ reloc_addr += rel_head >> (3 - offset_shift); | |
+ if (rel_head & 128) += (get_leb128(&relp, 128) - 128) << (5 + offset_shift); | |
+ if (rel_head & 1) sym_index += get_leb128(&relp, 64); | |
+ if (rel_head & 2) type += get_leb128(&relp, 64); | |
+ if (rel_head & 4) addend += get_leb128(&relp, 64); | |
+ rel_size--; | |
} else { | |
- addend = *reloc_addr; | |
- } | |
+#endif | |
+ if (skip_relative && IS_RELATIVE(rel[1], dso->syms)) continue; | |
+ type = R_TYPE(rel[1]); | |
+ if (type == REL_NONE) continue; | |
+ reloc_addr = laddr(dso, rel[0]); | |
+ | |
+ if (stride > 2) { | |
+ addend = rel[2]; | |
+ } else if (type==REL_GOT || type==REL_PLT|| type==REL_COPY) { | |
+ addend = 0; | |
+ } else if (reuse_addends) { | |
+ /* Save original addend in stage 2 where the dso | |
+ * chain consists of just ldso; otherwise read back | |
+ * saved addend since the inline one was clobbered. */ | |
+ if (head==&ldso) | |
+ saved_addends[save_slot] = *reloc_addr; | |
+ addend = saved_addends[save_slot++]; | |
+ } else { | |
+ addend = *reloc_addr; | |
+ } | |
- sym_index = R_SYM(rel[1]); | |
+ sym_index = R_SYM(rel[1]); | |
+#ifndef DL_FDPIC | |
+ } | |
+#endif | |
if (sym_index) { | |
sym = syms + sym_index; | |
name = strings + sym->st_name; | |
@@ -1421,6 +1459,8 @@ static void reloc_all(struct dso *p) | |
do_relocs(p, laddr(p, dyn[DT_RELA]), dyn[DT_RELASZ], 3); | |
if (!DL_FDPIC) | |
do_relr_relocs(p, laddr(p, dyn[DT_RELR]), dyn[DT_RELRSZ]); | |
+ if (dyn[DT_CRELSZ]) | |
+ do_relocs(p, laddr(p, dyn[DT_CREL]), 0, 0); | |
if (head != &ldso && p->relro_start != p->relro_end) { | |
long ret = __syscall(SYS_mprotect, laddr(p, p->relro_start), | |
@@ -2083,7 +2123,8 @@ static void prepare_lazy(struct dso *p) | |
search_vec(p->dynv, &flags1, DT_FLAGS_1); | |
if (dyn[DT_BIND_NOW] || (dyn[DT_FLAGS] & DF_BIND_NOW) || (flags1 & DF_1_NOW)) | |
return; | |
- n = dyn[DT_RELSZ]/2 + dyn[DT_RELASZ]/3 + dyn[DT_PLTRELSZ]/2 + 1; | |
+ n = dyn[DT_RELSZ]/2 + dyn[DT_RELASZ]/3 + dyn[DT_PLTRELSZ]/2 + dyn[DT_CRELSZ] + 1; | |
+ | |
if (NEED_MIPS_GOT_RELOCS) { | |
size_t j=0; search_vec(p->dynv, &j, DT_MIPS_GOTSYM); | |
size_t i=0; search_vec(p->dynv, &i, DT_MIPS_SYMTABNO); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment