Undefined symbol in ld.so

classic Classic list List threaded Threaded
4 messages Options
Reply | Threaded
Open this post in threaded view
|

Undefined symbol in ld.so

William Orr-2
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)

Reply | Threaded
Open this post in threaded view
|

Re: Undefined symbol in ld.so

Nigel Taylor-3
On 06/24/14 09:30, William Orr wrote:
> 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

There are issues with some CVS mirrors because of cvsync/commitid's, one
of those is issue is failure to update malloc.c, the current version is
1.3, you have version 1.1 your CVS source tree being incorrect is the
issue. Try a different CVS mirror or wait until issues have been fixed.

$ cvs log malloc.c

RCS file: /cvs/src/libexec/ld.so/malloc.c,v
Working file: malloc.c
head: 1.3
branch:
locks: strict
access list:
symbolic names:
keyword substitution: kv
total revisions: 3;     selected revisions: 3
description:
----------------------------
revision 1.3
date: 2014/06/21 08:00:23;  author: otto;  state: Exp;  lines: +47 -1;
commitid: wh9FTpEgwThWVeqE;
Move to a non-zeroing _dl_malloc, a _dl_calloc and _dl_reallocarry and
fix _dl_strdup to return NULL instead of crash; ok deraadt@
----------------------------
revision 1.2
date: 2014/06/15 06:48:30;  author: otto;  state: Exp;  lines: +2 -2;
commitid: zG8TjRrBxXrN0x6O;
move to a smaller rbytes buffer; ok miod@ deraadt@
----------------------------
revision 1.1
date: 2014/06/05 08:39:07;  author: otto;  state: Exp;  commitid:
PovK1yhVqujrpswl;
Move to (slightly stripped) version of libc malloc; ok deraadt@
=============================================================================



>
> 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)
>
> .
>

Reply | Threaded
Open this post in threaded view
|

Re: Undefined symbol in ld.so

Otto Moerbeek
In reply to this post by William Orr-2
On Tue, Jun 24, 2014 at 01:30:55AM -0700, William Orr wrote:

> 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.

There are cvssync problems. The code in curent compiles fine.

        -Otto

>
> 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)

Reply | Threaded
Open this post in threaded view
|

Re: Undefined symbol in ld.so

William Orr-2
Whoops! Sorry for the confusion; disregard.

On Jun 24, 2014, at 3:31 AM, Otto Moerbeek <[hidden email]> wrote:

> On Tue, Jun 24, 2014 at 01:30:55AM -0700, William Orr wrote:
>
>> 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.
>
> There are cvssync problems. The code in curent compiles fine.
>
> -Otto
>
>>
>> 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)


signature.asc (817 bytes) Download Attachment