dwfl_frame.c frame_unwind.c dwfl_frame_pc.c \
linux-pid-attach.c linux-core-attach.c dwfl_frame_regs.c \
dwfl_process_tracker.c dwfl_process_tracker_find_elf.c \
+ dwfl_process_tracker_elftab.c libdwfl_next_prime.c \
gzip.c debuginfod-client.c
if BZLIB
/* Cache file->elf in Dwfl_Process_Tracker if available: */
if (mod->dwfl->tracker != NULL && file->name != NULL)
{
- dwfltracker_elftab_ent *ent = __libdwfl_process_tracker_elftab_find (mod->dwfl->tracker, file->name, false/* should_resize */);
+ dwfltracker_elf_info *ent = dwfltracker_elftab_find (&mod->dwfl->tracker->elftab, elf_hash(file->name));
if (ent != NULL)
{
/* assert(ent->elf == NULL || ent->elf == file->elf); */ /* TODO(PRERELEASE): Guard against redundant/leaked Elf *. */
- assert(ent->fd == file->fd); /* TODO(PRERELEASE): Guard against redundant open. */
+ /* assert(ent->fd == file->fd); */ /* TODO(PRERELEASE): Guard against redundant open. */
ent->elf = file->elf;
}
}
#include "libdwflP.h"
#define HTAB_DEFAULT_SIZE 1021
-extern size_t next_prime (size_t); /* XXX from libeu.a lib/next_prime.c */
Dwfl_Process_Tracker *dwfl_process_tracker_begin (const Dwfl_Callbacks *callbacks)
{
return tracker;
}
- /* XXX based on lib/dynamicsizehash.* *_init */
- tracker->elftab_size = HTAB_DEFAULT_SIZE;
- tracker->elftab_filled = 0;
- tracker->elftab = calloc ((tracker->elftab_size + 1), sizeof(tracker->elftab[0]));
+ dwfltracker_elftab_init (&tracker->elftab, HTAB_DEFAULT_SIZE);
tracker->callbacks = callbacks;
return tracker;
if (tracker == NULL)
return;
- for (unsigned idx = 1; idx < tracker->elftab_size; idx++)
+ /* HACK to allow iteration of dynamicsizehash_concurrent. */
+ /* XXX Based on lib/dynamicsizehash_concurrent.c free(). */
+ pthread_rwlock_destroy(&tracker->elftab.resize_rwl);
+ for (size_t idx = 1; idx <= tracker->elftab.size; idx++)
{
- dwfltracker_elftab_ent *t = &tracker->elftab[idx];
- if (!DWFL_ELFTAB_ENT_USED(t))
+ dwfltracker_elftab_ent *ent = &tracker->elftab.table[idx];
+ if (ent->hashval == 0)
continue;
+ dwfltracker_elf_info *t = (dwfltracker_elf_info *) atomic_load_explicit (&ent->val_ptr,
+ memory_order_relaxed);
+ free(t->module_name);
if (t->fd >= 0)
close(t->fd);
- free(t->module_name);
- elf_end(t->elf);
+ if (t->elf != NULL)
+ elf_end(t->elf);
+ free(t); /* TODO: Check necessity. */
}
- free(tracker->elftab);
+ free (tracker->elftab.table);
/* TODO: Call dwfl_end for each Dwfl connected to this tracker. */
free (tracker);
}
-/* XXX based on lib/dynamicsizehash.* insert_entry_2 */
-bool
-__libdwfl_process_tracker_elftab_resize (Dwfl_Process_Tracker *tracker)
-{
- ssize_t old_size = tracker->elftab_size;
- dwfltracker_elftab_ent *oldtab = tracker->elftab;
- tracker->elftab_size = next_prime (tracker->elftab_size * 2);
- tracker->elftab = calloc ((tracker->elftab_size + 1), sizeof(tracker->elftab[0]));
- if (tracker->elftab == NULL)
- {
- tracker->elftab_size = old_size;
- tracker->elftab = oldtab;
- return false;
- }
- tracker->elftab_filled = 0;
- /* Transfer the old entries to the new table. */
- for (ssize_t idx = 1; idx <= old_size; ++idx)
- if (DWFL_ELFTAB_ENT_USED(&oldtab[idx]))
- {
- dwfltracker_elftab_ent *ent0 = &oldtab[idx];
- dwfltracker_elftab_ent *ent1 = __libdwfl_process_tracker_elftab_find(tracker, ent0->module_name, false/* should_resize */);
- assert (ent1 != NULL);
- memcpy (ent1, ent0, sizeof(dwfltracker_elftab_ent));
- }
- free(oldtab);
- return true;
-}
-
-/* TODO: Hashing is tentative, consider direct use of lib/dynamicsizehash_concurrent.c for this. */
-ssize_t
-djb2_hash (const char *str)
-{
- unsigned long hash = 5381;
- int c;
-
- while ((c = *str++))
- hash = ((hash << 5) + hash) ^ c; /* hash * 33 XOR c */
-
- ssize_t shash = (ssize_t)hash;
- if (shash < 0) shash = -shash;
- return shash;
-}
-
-/* XXX based on lib/dynamicsizehash.* *_find */
-dwfltracker_elftab_ent *
-__libdwfl_process_tracker_elftab_find (Dwfl_Process_Tracker *tracker,
- const char *module_name,
- bool should_resize)
-{
- dwfltracker_elftab_ent *htab = tracker->elftab;
- ssize_t hval = djb2_hash(module_name);
- ssize_t idx = 1 + (hval < tracker->elftab_size ? hval : hval % tracker->elftab_size);
-
- if (!DWFL_ELFTAB_ENT_USED(&htab[idx]))
- goto found;
- if (strcmp(htab[idx].module_name, module_name) == 0)
- goto found;
-
- int64_t hash = 1 + hval % (tracker->elftab_size - 2);
- do
- {
- if (idx <= hash)
- idx = tracker->elftab_size + idx - hash;
- else
- idx -= hash;
-
- if (!DWFL_ELFTAB_ENT_USED(&htab[idx]))
- goto found;
- if (strcmp(htab[idx].module_name, module_name) == 0)
- goto found;
- }
- while (true);
-
- found:
- if (!DWFL_ELFTAB_ENT_USED(&htab[idx]))
- {
- if (100 * tracker->elftab_filled > 90 * tracker->elftab_size)
- {
- if (!should_resize || !__libdwfl_process_tracker_elftab_resize (tracker))
- return NULL;
- }
- /* XXX Caller is responsible for setting module_name,
- calling __libdwfl_process_tracker_elftab_mark_used;
- not guaranteed that caller will want to do this. */
- }
- return &htab[idx];
-}
-
-void
-__libdwfl_process_tracker_elftab_mark_used (Dwfl_Process_Tracker *tracker,
- const dwfltracker_elftab_ent *ent)
-{
- assert(DWFL_ELFTAB_ENT_USED(ent));
- tracker->elftab_filled ++;
-}
--- /dev/null
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <string.h>
+
+#include <libdwflP.h>
+
+/* Definitions for the Elf table. */
+#define TYPE dwfltracker_elf_info *
+#define NAME dwfltracker_elftab
+#define ITERATE 1
+/* TODO: Need REVERSE? */
+#define REVERSE 1
+#define COMPARE(a, b) \
+ strcmp ((a)->module_name, (b)->module_name)
+
+#define next_prime __libdwfl_next_prime
+extern size_t next_prime (size_t) attribute_hidden;
+
+#include "../lib/dynamicsizehash_concurrent.c"
+/* TODO: Need to share this definition with dwfl_process_tracker_dwfltab -- move to libdwfl_next_prime.c */
--- /dev/null
+#ifndef DWFL_PROCESS_TRACKER_ELFTAB_H
+#define DWFL_PROCESS_TRACKER_ELFTAB_H 1
+
+/* Definitions for the Elf table. */
+#define TYPE dwfltracker_elf_info *
+#define NAME dwfltracker_elftab
+#define ITERATE 1
+#define COMPARE(a, b) \
+ strcmp ((a)->module_name, (b)->module_name)
+#include <dynamicsizehash_concurrent.h>
+
+#endif
/* TODO(WIP): Do we need to handle if elfp is already set?? */
assert (*elfp == NULL);
Dwfl_Process_Tracker *tracker = mod->dwfl->tracker;
- dwfltracker_elftab_ent *ent = NULL;
+ dwfltracker_elf_info *ent = NULL;
int rc;
struct stat sb;
if (tracker != NULL)
{
- ent = __libdwfl_process_tracker_elftab_find(tracker, module_name,
- true/*should_resize*/);
- /* TODO: Also reopen the file when module_name set but fd not set? */
- if (DWFL_ELFTAB_ENT_USED(ent))
+ unsigned long int hval = elf_hash(module_name);
+ ent = dwfltracker_elftab_find(&tracker->elftab, hval);
+ if (ent != NULL)
{
+ /* TODO: Also reopen the file when module_name set but fd not set? */
rc = fstat(ent->fd, &sb);
if (rc < 0 || ent->dev != sb.st_dev || ent->ino != sb.st_ino
|| ent->last_mtime != sb.st_mtime)
- ent = NULL; /* file modified, fall back to uncached behaviour */
+ ent = NULL; /* file modified, fall back to uncached behaviour */
else
{
*elfp = ent->elf;
*file_name = strdup(ent->module_name);
- return ent->fd;
}
}
- else if (ent->module_name == NULL)
+ else
{
- /* TODO: For multithreaded access, we mark used here rather
- than after the dwfl_linux_proc_find_elf() call. Need to
- add appropriate locking. */
+ ent = calloc (1, sizeof (dwfltracker_elf_info));
ent->module_name = strdup(module_name);
- __libdwfl_process_tracker_elftab_mark_used(tracker, ent);
+ if (dwfltracker_elftab_insert(&tracker->elftab, hval, ent) != 0)
+ {
+ free(ent->module_name);
+ free(ent);
+ ent = NULL; /* fall back to uncached behaviour */
+ /* TODO(WIP): Could goto and repeat the find operation? */
+ }
}
}
/* XXX fd < 0 implies elf_from_remote_memory, uses base, not cacheable */
if (tracker != NULL && ent != NULL && fd >= 0 && *file_name != NULL)
{
+ /* TODO(WIP): *elfp may be NULL here, need to be populated later. */
ent->elf = *elfp;
ent->fd = fd;
rc = fstat(fd, &sb);
extern int __libdwfl_canon_error (Dwfl_Error) internal_function;
extern void __libdwfl_seterrno (Dwfl_Error) internal_function;
-#define DWFL_ELFTAB_ENT_USED(e) ((e)->module_name != NULL)
+/* Hash table for Elf *. */
typedef struct
{
char *module_name; /* dwfltracker_elftab_ent is used iff non-NULL. */
dev_t dev;
ino_t ino;
time_t last_mtime;
-} dwfltracker_elftab_ent;
+} dwfltracker_elf_info;
+#include "dwfl_process_tracker_elftab.h"
struct Dwfl_Process_Tracker
{
const Dwfl_Callbacks *callbacks;
/* Table of cached Elf * including fd, path, fstat info. */
- ssize_t elftab_size;
- ssize_t elftab_filled;
- dwfltracker_elftab_ent *elftab;
+ dwfltracker_elftab elftab;
};
-/* Find the location for an existing or new MODULE_NAME and return a
- dwfl_tracker_elftab_ent * for it. If MODULE_NAME is not found
- and SHOULD_RESIZE is set, expand the table as necessary to make
- room for the new entry. Otherwise, return NULL if MODULE_NAME is
- not found. */
-dwfltracker_elftab_ent *
-__libdwfl_process_tracker_elftab_find (Dwfl_Process_Tracker *tracker,
- const char *module_name,
- bool should_resize);
-
-/* After populating a dwfltracker_elftab_ent with data, update the
- elftab_filled stats to properly mark the entry as used. */
-void
-__libdwfl_process_tracker_elftab_mark_used (Dwfl_Process_Tracker *tracker,
- const dwfltracker_elftab_ent *ent);
/* Resources we might keep for the user about the core file that the
Dwfl might have been created from. Can currently only be set
--- /dev/null
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#define next_prime attribute_hidden __libdwfl_next_prime
+#include "../lib/next_prime.c"