On Thu, Dec 5, 2013 at 7:32 AM, Jakub Jelinek <ja...@redhat.com> wrote: > > I'm trying to understand how the backtrace_vector_* APIs are meant to work > and used, but at least for alloc.c don't see how it can work properly: > > Both backtrace_vector_grow and backtrace_vector_release use > base = realloc (vec->base, alc); > or > vec->base = realloc (vec->base, vec->size); > (note, in the latter case it is even a memory leak if realloc fails), > but that assumes that that vec->base has been returned by malloc/realloc > etc. But, > void > backtrace_vector_finish (struct backtrace_state *state ATTRIBUTE_UNUSED, > struct backtrace_vector *vec) > { > vec->base = (char *) vec->base + vec->size; > vec->size = 0; > } > will change vec->base so that it no longer is an address returned by > malloc/realloc, so next time you call backtrace_vector_grow, if it will > actually need to reallocate anything, it will crash in realloc or silently > misbehave. If this works properly in mmap.c implementation, perhaps > backtrace_vector_finish in alloc.c should just backtrace_vector_release > and memset (*vec, 0, sizeof (*vec)); ?
You're quite right. That was dumb. Thanks for noticing. Fixed with this patch. Committed to mainline and 4.8 branch. Ian 2013-12-05 Ian Lance Taylor <i...@google.com> * alloc.c (backtrace_vector_finish): Add error_callback and data parameters. Call backtrace_vector_release. Return address base. * mmap.c (backtrace_vector_finish): Add error_callback and data parameters. Return address base. * dwarf.c (read_function_info): Get new address base from backtrace_vector_finish. * internal.h (backtrace_vector_finish): Update declaration.
Index: dwarf.c =================================================================== --- dwarf.c (revision 205711) +++ dwarf.c (working copy) @@ -2535,19 +2535,23 @@ read_function_info (struct backtrace_sta if (pfvec->count == 0) return; - addrs = (struct function_addrs *) pfvec->vec.base; addrs_count = pfvec->count; if (fvec == NULL) { if (!backtrace_vector_release (state, &lvec.vec, error_callback, data)) return; + addrs = (struct function_addrs *) pfvec->vec.base; } else { /* Finish this list of addresses, but leave the remaining space in the vector available for the next function unit. */ - backtrace_vector_finish (state, &fvec->vec); + addrs = ((struct function_addrs *) + backtrace_vector_finish (state, &fvec->vec, + error_callback, data)); + if (addrs == NULL) + return; fvec->count = 0; } Index: internal.h =================================================================== --- internal.h (revision 205711) +++ internal.h (working copy) @@ -233,13 +233,17 @@ extern void *backtrace_vector_grow (stru struct backtrace_vector *vec); /* Finish the current allocation on VEC. Prepare to start a new - allocation. The finished allocation will never be freed. */ + allocation. The finished allocation will never be freed. Returns + a pointer to the base of the finished entries, or NULL on + failure. */ -extern void backtrace_vector_finish (struct backtrace_state *state, - struct backtrace_vector *vec); +extern void* backtrace_vector_finish (struct backtrace_state *state, + struct backtrace_vector *vec, + backtrace_error_callback error_callback, + void *data); -/* Release any extra space allocated for VEC. Returns 1 on success, 0 - on failure. */ +/* Release any extra space allocated for VEC. This may change + VEC->base. Returns 1 on success, 0 on failure. */ extern int backtrace_vector_release (struct backtrace_state *state, struct backtrace_vector *vec, Index: mmap.c =================================================================== --- mmap.c (revision 205711) +++ mmap.c (working copy) @@ -230,12 +230,19 @@ backtrace_vector_grow (struct backtrace_ /* Finish the current allocation on VEC. */ -void -backtrace_vector_finish (struct backtrace_state *state ATTRIBUTE_UNUSED, - struct backtrace_vector *vec) +void * +backtrace_vector_finish ( + struct backtrace_state *state ATTRIBUTE_UNUSED, + struct backtrace_vector *vec, + backtrace_error_callback error_callback ATTRIBUTE_UNUSED, + void *data ATTRIBUTE_UNUSED) { + void *ret; + + ret = vec->base; vec->base = (char *) vec->base + vec->size; vec->size = 0; + return ret; } /* Release any extra space allocated for VEC. */ Index: alloc.c =================================================================== --- alloc.c (revision 205711) +++ alloc.c (working copy) @@ -113,12 +113,24 @@ backtrace_vector_grow (struct backtrace_ /* Finish the current allocation on VEC. */ -void -backtrace_vector_finish (struct backtrace_state *state ATTRIBUTE_UNUSED, - struct backtrace_vector *vec) +void * +backtrace_vector_finish (struct backtrace_state *state, + struct backtrace_vector *vec, + backtrace_error_callback error_callback, + void *data) { - vec->base = (char *) vec->base + vec->size; + void *ret; + + /* With this allocator we call realloc in backtrace_vector_grow, + which means we can't easily reuse the memory here. So just + release it. */ + if (!backtrace_vector_release (state, vec, error_callback, data)) + return NULL; + ret = vec->base; + vec->base = NULL; vec->size = 0; + vec->alc = 0; + return ret; } /* Release any extra space allocated for VEC. */