ld.so in -current isn't building right now, due to an undefined reference to _dl_realloc caused by the recent addition of _dl_reallocarray. The following diff implements _dl_realloc, largely copied from the implementation in lib/libc/stdlib/malloc.c.
tested on amd64 Index: malloc.c =================================================================== RCS file: /cvs/src/libexec/ld.so/malloc.c,v retrieving revision 1.1 diff -u -b -w -p -r1.1 malloc.c --- malloc.c 5 Jun 2014 08:39:07 -0000 1.1 +++ malloc.c 24 Jun 2014 08:24:43 -0000 @@ -78,6 +78,12 @@ #define MMAP(sz) _dl_mmap(NULL, (size_t)(sz), PROT_READ | PROT_WRITE, \ MAP_ANON | MAP_PRIVATE, -1, (off_t) 0) +#define MMAPA(a,sz) _dl_mmap((a), (size_t)(sz), PROT_READ | PROT_WRITE, \ + MAP_ANON | MAP_PRIVATE, -1, (off_t) 0) + +#define MQUERY(a, sz) _dl_mquery((a), (size_t)(sz), PROT_READ | PROT_WRITE, \ + MAP_ANON | MAP_PRIVATE | MAP_FIXED, -1, (off_t)0) + #define MMAP_ERROR(p) (_dl_mmap_error(p) ? MAP_FAILED : (p)) struct region_info { @@ -277,6 +283,26 @@ unmap(struct dir_info *d, void *p, size_ wrterror("malloc cache overflow"); } +static void +zapcacheregion(struct dir_info *d, void *p, size_t len) +{ + u_int i; + struct region_info *r; + size_t rsz; + + for (i = 0; i < mopts.malloc_cache; i++) { + r = &d->free_regions[i]; + if (r->p >= p && r->p <= (void *)((char *)p + len)) { + rsz = r->size << MALLOC_PAGESHIFT; + if (_dl_munmap(r->p, rsz)) + wrterror("munmap"); + r->p = NULL; + d->free_regions_size -= r->size; + r->size = 0; + } + } +} + static void * map(struct dir_info *d, size_t sz, int zero_fill) { @@ -987,6 +1013,119 @@ _dl_free(void *ptr) malloc_active--; } +static void * +orealloc(void *p, size_t newsz) +{ + struct region_info *r; + size_t oldsz, goldsz, gnewsz; + void *q; + + if (p == NULL) + return omalloc(newsz, 0); + + r = find(g_pool, p); + if (r == NULL) { + wrterror("bogus pointer (double free?)"); + return NULL; + } + if (newsz >= SIZE_MAX - mopts.malloc_guard - MALLOC_PAGESIZE) + return NULL; + + REALSIZE(oldsz, r); + goldsz = oldsz; + if (oldsz > MALLOC_MAXCHUNK) { + if (oldsz < mopts.malloc_guard) + wrterror("guard size"); + oldsz -= mopts.malloc_guard; + } + + gnewsz = newsz; + if (gnewsz > MALLOC_MAXCHUNK) + gnewsz += mopts.malloc_guard; + + if (newsz > MALLOC_MAXCHUNK && oldsz > MALLOC_MAXCHUNK && p == r->p) { + size_t roldsz = PAGEROUND(goldsz); + size_t rnewsz = PAGEROUND(gnewsz); + + if (rnewsz > roldsz) { + if (!mopts.malloc_guard) { + void *hint = (char *)p + roldsz; + size_t needed = rnewsz - roldsz; + + zapcacheregion(g_pool, hint, needed); + q = MQUERY(hint, needed); + if (q == hint) + q = MMAPA(hint, needed); + else + q = MAP_FAILED; + if (q == hint) { + if (mopts.malloc_junk == 2) + _dl_memset(q, SOME_JUNK, needed); + r->size = newsz; + return p; + } else if (q != MAP_FAILED) { + if (_dl_munmap(q, needed)) + wrterror("munmap"); + } + } + } else if (rnewsz < roldsz) { + if (mopts.malloc_guard) { + if (_dl_mprotect((char *)p + roldsz - + mopts.malloc_guard, mopts.malloc_guard, + PROT_READ | PROT_WRITE)) + wrterror("mprotect"); + if (_dl_mprotect((char *)p + rnewsz - + mopts.malloc_guard, mopts.malloc_guard, + PROT_NONE)) + wrterror("mprotect"); + } + unmap(g_pool, (char *)p + rnewsz, roldsz - rnewsz); + r->size = gnewsz; + return p; + } else { + if (newsz > oldsz && mopts.malloc_junk == 2) + _dl_memset((char *)p + newsz, SOME_JUNK, + rnewsz - mopts.malloc_guard - newsz); + r->size = gnewsz; + return p; + } + } + if (newsz <= oldsz && newsz > oldsz / 2) { + if (mopts.malloc_junk == 2 && newsz > 0) + _dl_memset((char *)p + newsz, SOME_JUNK, oldsz - newsz); + return p; + } else if (newsz != oldsz) { + q = omalloc(newsz, 0); + if (q == NULL) + return NULL; + if (newsz != 0 && oldsz != 0) + _dl_bcopy(q, p, oldsz < newsz ? oldsz : newsz); + ofree(p); + return q; + } else { + return p; + } +} + +void * +_dl_realloc(void *ptr, size_t size) +{ + void *r; + + malloc_func = "realloc():"; + if (g_pool == NULL) { + if (malloc_init() != 0) + return NULL; + } + if (malloc_active++) { + malloc_recurse(); + return NULL; + } + r = orealloc(ptr, size); + + malloc_active--; + return r; +} /* * This is sqrt(SIZE_MAX+1), as s1*s2 <= SIZE_MAX Index: amd64/archdep.h =================================================================== RCS file: /cvs/src/libexec/ld.so/amd64/archdep.h,v retrieving revision 1.5 diff -u -b -w -p -r1.5 archdep.h --- amd64/archdep.h 19 Jan 2014 10:25:45 -0000 1.5 +++ amd64/archdep.h 24 Jun 2014 08:24:43 -0000 @@ -50,6 +50,13 @@ _dl_mmap(void *addr, unsigned int len, u flags, fd, 0, offset)); } +static inline void * +_dl_mquery(void *addr, unsigned int len, unsigned int prot, + unsigned int flags, int fd, off_t offset) +{ + return((void *)_dl__syscall((quad_t)SYS_mquery, addr, len, prot, + flags, fd, 0, offset)); +} static inline void RELOC_REL(Elf64_Rel *r, const Elf64_Sym *s, Elf64_Addr *p, unsigned long v)