+2019-11-10 Mark Wielaard <mark@klomp.org>
+
+ * libdwP.h (libdw_unalloc): New define.
+ (libdw_typed_unalloc): Likewise.
+ (__libdw_thread_tail): New function declaration.
+ * libdw_alloc.c (__libdw_thread_tail): New function.
+ * dwarf_getabbrev.c (__libdw_getabbrev): Call libdw_typed_unalloc
+ when reading invalid data or when hash collission detected.
+
2019-10-28 Jonathon Anderson <jma14@rice.edu>
* libdw_alloc.c: Added __libdw_alloc_tail.
/* A duplicate abbrev code at a different offset,
that should never happen. */
invalid:
+ if (! foundit)
+ libdw_typed_unalloc (dbg, Dwarf_Abbrev);
__libdw_seterrno (DWARF_E_INVALID_DWARF);
return NULL;
}
/* Add the entry to the hash table. */
if (cu != NULL && ! foundit)
- (void) Dwarf_Abbrev_Hash_insert (&cu->abbrev_hash, abb->code, abb);
+ if (Dwarf_Abbrev_Hash_insert (&cu->abbrev_hash, abb->code, abb) == -1)
+ {
+ /* The entry was already in the table, remove the one we just
+ created and get the one already inserted. */
+ libdw_typed_unalloc (dbg, Dwarf_Abbrev);
+ abb = Dwarf_Abbrev_Hash_find (&cu->abbrev_hash, code);
+ }
out:
return abb;
#define libdw_typed_alloc(dbg, type) \
libdw_alloc (dbg, type, sizeof (type), 1)
+/* Can only be used to undo the last libdw_alloc. */
+#define libdw_unalloc(dbg, type, tsize, cnt) \
+ ({ struct libdw_memblock *_tail = __libdw_thread_tail (dbg); \
+ size_t _required = (tsize) * (cnt); \
+ /* We cannot know the padding, it is lost. */ \
+ _tail->remaining += _required; }) \
+
+#define libdw_typed_unalloc(dbg, type) \
+ libdw_unalloc (dbg, type, sizeof (type), 1)
+
/* Callback to choose a thread-local memory allocation stack. */
extern struct libdw_memblock *__libdw_alloc_tail (Dwarf* dbg)
__nonnull_attribute__ (1);
+extern struct libdw_memblock *__libdw_thread_tail (Dwarf* dbg)
+ __nonnull_attribute__ (1);
+
/* Callback to allocate more. */
extern void *__libdw_allocate (Dwarf *dbg, size_t minsize, size_t align)
__attribute__ ((__malloc__)) __nonnull_attribute__ (1);
return result;
}
+/* Can only be called after a allocation for this thread has already
+ been done, to possibly undo it. */
+struct libdw_memblock *
+__libdw_thread_tail (Dwarf *dbg)
+{
+ struct libdw_memblock *result;
+ pthread_rwlock_rdlock (&dbg->mem_rwl);
+ result = dbg->mem_tails[thread_id];
+ pthread_rwlock_unlock (&dbg->mem_rwl);
+ return result;
+}
+
void *
__libdw_allocate (Dwarf *dbg, size_t minsize, size_t align)
{