setvbuf: minor comment typo fix
[musl] / ldso / dynlink.c
index 9bf6924..63e7b81 100644 (file)
@@ -158,10 +158,26 @@ static void *laddr(const struct dso *p, size_t v)
        for (j=0; v-p->loadmap->segs[j].p_vaddr >= p->loadmap->segs[j].p_memsz; j++);
        return (void *)(v - p->loadmap->segs[j].p_vaddr + p->loadmap->segs[j].addr);
 }
+static void *laddr_pg(const struct dso *p, size_t v)
+{
+       size_t j=0;
+       size_t pgsz = PAGE_SIZE;
+       if (!p->loadmap) return p->base + v;
+       for (j=0; ; j++) {
+               size_t a = p->loadmap->segs[j].p_vaddr;
+               size_t b = a + p->loadmap->segs[j].p_memsz;
+               a &= -pgsz;
+               b += pgsz-1;
+               b &= -pgsz;
+               if (v-a<b-a) break;
+       }
+       return (void *)(v - p->loadmap->segs[j].p_vaddr + p->loadmap->segs[j].addr);
+}
 #define fpaddr(p, v) ((void (*)())&(struct funcdesc){ \
        laddr(p, v), (p)->got })
 #else
 #define laddr(p, v) (void *)((p)->base + (v))
+#define laddr_pg(p, v) laddr(p, v)
 #define fpaddr(p, v) ((void (*)())laddr(p, v))
 #endif
 
@@ -476,23 +492,16 @@ static void redo_lazy_relocs()
 /* A huge hack: to make up for the wastefulness of shared libraries
  * needing at least a page of dirty memory even if they have no global
  * data, we reclaim the gaps at the beginning and end of writable maps
- * and "donate" them to the heap by setting up minimal malloc
- * structures and then freeing them. */
+ * and "donate" them to the heap. */
 
 static void reclaim(struct dso *dso, size_t start, size_t end)
 {
-       size_t *a, *z;
+       void __malloc_donate(char *, char *);
        if (start >= dso->relro_start && start < dso->relro_end) start = dso->relro_end;
        if (end   >= dso->relro_start && end   < dso->relro_end) end = dso->relro_start;
-       start = start + 6*sizeof(size_t)-1 & -4*sizeof(size_t);
-       end = (end & -4*sizeof(size_t)) - 2*sizeof(size_t);
-       if (start>end || end-start < 4*sizeof(size_t)) return;
-       a = laddr(dso, start);
-       z = laddr(dso, end);
-       a[-2] = 1;
-       a[-1] = z[0] = end-start + 2*sizeof(size_t) | 1;
-       z[1] = 1;
-       free(a);
+       if (start >= end) return;
+       char *base = laddr_pg(dso, start);
+       __malloc_donate(base, base+(end-start));
 }
 
 static void reclaim_gaps(struct dso *dso)
@@ -500,7 +509,6 @@ static void reclaim_gaps(struct dso *dso)
        Phdr *ph = dso->phdr;
        size_t phcnt = dso->phnum;
 
-       if (DL_FDPIC) return; // FIXME
        for (; phcnt--; ph=(void *)((char *)ph+dso->phentsize)) {
                if (ph->p_type!=PT_LOAD) continue;
                if ((ph->p_flags&(PF_R|PF_W))!=(PF_R|PF_W)) continue;