summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--debuginfod/ChangeLog16
-rw-r--r--debuginfod/debuginfod-client.c134
-rw-r--r--debuginfod/debuginfod-find.c4
-rw-r--r--debuginfod/debuginfod.h3
-rw-r--r--debuginfod/libdebuginfod.map5
-rw-r--r--doc/ChangeLog7
-rw-r--r--doc/debuginfod_find_debuginfo.317
7 files changed, 174 insertions, 12 deletions
diff --git a/debuginfod/ChangeLog b/debuginfod/ChangeLog
index b3c81285..bd4dbf40 100644
--- a/debuginfod/ChangeLog
+++ b/debuginfod/ChangeLog
@@ -1,3 +1,19 @@
+2020-11-11 Mark Wielaard <mark@klomp.org>
+
+ * debuginfod-client.c (debuginfod_set_verbose_fd): New function.
+ (struct debuginfod_client): Add verbose_fd.
+ (struct handle_data): Add errbuf.
+ (debuginfod_query_server): Produce verbose output when
+ debuginfod_client verbose_fd is set. Only clear old data and set
+ default_headers when any work is done. Always goto out when setting
+ rc to an error value. Use CURLOPT_ERRORBUFFER to get more error
+ output when verbose output is requested.
+ * debuginfod.h (DEBUGINFOD_VERBOSE_ENV_VAR): New.
+ (debuginfod_set_verbose_fd): Added.
+ * debuginfod-find.c (parse_opt): Set debuginfod_set_verbose_fd on -v.
+ * bdebuginfod.map (ELFUTILS_0.183): New section, add
+ debuginfod_set_verbose_fd.
+
2020-11-21 Mark Wielaard <mark@klomp.org>
* debuginfod.cxx (handle_root): New function.
diff --git a/debuginfod/debuginfod-client.c b/debuginfod/debuginfod-client.c
index ce1d819b..2bf1543a 100644
--- a/debuginfod/debuginfod-client.c
+++ b/debuginfod/debuginfod-client.c
@@ -56,6 +56,7 @@ int debuginfod_find_source (debuginfod_client *c, const unsigned char *b,
int s, const char *f, char **p) { return -ENOSYS; }
void debuginfod_set_progressfn(debuginfod_client *c,
debuginfod_progressfn_t fn) { }
+void debuginfod_set_verbose_fd(debuginfod_client *c, int fd) { }
void debuginfod_set_user_data (debuginfod_client *c, void *d) { }
void* debuginfod_get_user_data (debuginfod_client *c) { return NULL; }
const char* debuginfod_get_url (debuginfod_client *c) { return NULL; }
@@ -115,6 +116,9 @@ struct debuginfod_client
debuginfod_end needs to terminate. */
int default_progressfn_printed_p;
+ /* File descriptor to output any verbose messages if > 0. */
+ int verbose_fd;
+
/* Can contain all other context, like cache_path, server_urls,
timeout or other info gotten from environment variables, the
handle data, etc. So those don't have to be reparsed and
@@ -158,6 +162,9 @@ struct handle_data
/* URL queried by this handle. */
char url[PATH_MAX];
+ /* error buffer for this handle. */
+ char errbuf[CURL_ERROR_SIZE];
+
/* This handle. */
CURL *handle;
@@ -498,28 +505,51 @@ debuginfod_query_server (debuginfod_client *c,
char *target_cache_tmppath = NULL;
char suffix[PATH_MAX + 1]; /* +1 for zero terminator. */
char build_id_bytes[MAX_BUILD_ID_BYTES * 2 + 1];
+ int vfd = c->verbose_fd;
int rc;
- /* Clear the obsolete URL from a previous _find operation. */
- free (c->url);
- c->url = NULL;
-
- add_default_headers(c);
+ if (vfd >= 0)
+ {
+ dprintf (vfd, "debuginfod_find_%s ", type);
+ if (build_id_len == 0) /* expect clean hexadecimal */
+ dprintf (vfd, "%s", (const char *) build_id);
+ else
+ for (int i = 0; i < build_id_len; i++)
+ dprintf (vfd, "%02x", build_id[i]);
+ if (filename != NULL)
+ dprintf (vfd, " %s\n", filename);
+ dprintf (vfd, "\n");
+ }
/* Is there any server we can query? If not, don't do any work,
just return with ENOSYS. Don't even access the cache. */
urls_envvar = getenv(server_urls_envvar);
+ if (vfd >= 0)
+ dprintf (vfd, "server urls \"%s\"\n",
+ urls_envvar != NULL ? urls_envvar : "");
if (urls_envvar == NULL || urls_envvar[0] == '\0')
{
rc = -ENOSYS;
goto out;
}
+ /* Clear the obsolete URL from a previous _find operation. */
+ free (c->url);
+ c->url = NULL;
+
+ add_default_headers(c);
+
/* Copy lowercase hex representation of build_id into buf. */
+ if (vfd >= 0)
+ dprintf (vfd, "checking build-id\n");
if ((build_id_len >= MAX_BUILD_ID_BYTES) ||
(build_id_len == 0 &&
strlen ((const char *) build_id) > MAX_BUILD_ID_BYTES*2))
- return -EINVAL;
+ {
+ rc = -EINVAL;
+ goto out;
+ }
+
if (build_id_len == 0) /* expect clean hexadecimal */
strcpy (build_id_bytes, (const char *) build_id);
else
@@ -528,8 +558,13 @@ debuginfod_query_server (debuginfod_client *c,
if (filename != NULL)
{
+ if (vfd >= 0)
+ dprintf (vfd, "checking filename\n");
if (filename[0] != '/') // must start with /
- return -EINVAL;
+ {
+ rc = -EINVAL;
+ goto out;
+ }
/* copy the filename to suffix, s,/,#,g */
unsigned q = 0;
@@ -559,6 +594,9 @@ debuginfod_query_server (debuginfod_client *c,
else
suffix[0] = '\0';
+ if (suffix[0] != '\0' && vfd >= 0)
+ dprintf (vfd, "suffix %s\n", suffix);
+
/* set paths needed to perform the query
example format
@@ -630,6 +668,10 @@ debuginfod_query_server (debuginfod_client *c,
/* XXX combine these */
xalloc_str (interval_path, "%s/%s", cache_path, cache_clean_interval_filename);
xalloc_str (maxage_path, "%s/%s", cache_path, cache_max_unused_age_filename);
+
+ if (vfd >= 0)
+ dprintf (vfd, "checking cache dir %s\n", cache_path);
+
rc = debuginfod_init_cache(cache_path, interval_path, maxage_path);
if (rc != 0)
goto out;
@@ -653,6 +695,9 @@ debuginfod_query_server (debuginfod_client *c,
if (timeout_envvar != NULL)
timeout = atoi (timeout_envvar);
+ if (vfd >= 0)
+ dprintf (vfd, "using timeout %ld\n", timeout);
+
/* make a copy of the envvar so it can be safely modified. */
server_urls = strdup(urls_envvar);
if (server_urls == NULL)
@@ -719,6 +764,9 @@ debuginfod_query_server (debuginfod_client *c,
/* Initialize each handle. */
for (int i = 0; i < num_urls && server_url != NULL; i++)
{
+ if (vfd >= 0)
+ dprintf (vfd, "init server %d %s\n", i, server_url);
+
data[i].fd = fd;
data[i].target_handle = &target_handle;
data[i].handle = curl_easy_init();
@@ -745,7 +793,12 @@ debuginfod_query_server (debuginfod_client *c,
snprintf(data[i].url, PATH_MAX, "%s%s/%s/%s", server_url,
slashbuildid, build_id_bytes, type);
+ if (vfd >= 0)
+ dprintf (vfd, "url %d %s\n", i, data[i].url);
+
curl_easy_setopt(data[i].handle, CURLOPT_URL, data[i].url);
+ if (vfd >= 0)
+ curl_easy_setopt(data[i].handle, CURLOPT_ERRORBUFFER, data[i].errbuf);
curl_easy_setopt(data[i].handle,
CURLOPT_WRITEFUNCTION,
debuginfod_write_callback);
@@ -778,8 +831,12 @@ debuginfod_query_server (debuginfod_client *c,
}
/* Query servers in parallel. */
+ if (vfd >= 0)
+ dprintf (vfd, "query %d urls in parallel\n", num_urls);
int still_running;
long loops = 0;
+ int committed_to = -1;
+ bool verbose_reported = false;
do
{
/* Wait 1 second, the minimum DEBUGINFOD_TIMEOUT. */
@@ -787,9 +844,23 @@ debuginfod_query_server (debuginfod_client *c,
/* If the target file has been found, abort the other queries. */
if (target_handle != NULL)
- for (int i = 0; i < num_urls; i++)
- if (data[i].handle != target_handle)
- curl_multi_remove_handle(curlm, data[i].handle);
+ {
+ for (int i = 0; i < num_urls; i++)
+ if (data[i].handle != target_handle)
+ curl_multi_remove_handle(curlm, data[i].handle);
+ else
+ committed_to = i;
+ }
+
+ if (vfd >= 0 && !verbose_reported && committed_to >= 0)
+ {
+ bool pnl = (c->default_progressfn_printed_p && vfd == STDERR_FILENO);
+ dprintf (vfd, "%scommitted to url %d\n", pnl ? "\n" : "",
+ committed_to);
+ if (pnl)
+ c->default_progressfn_printed_p = 0;
+ verbose_reported = true;
+ }
CURLMcode curlm_res = curl_multi_perform(curlm, &still_running);
if (curlm_res != CURLM_OK)
@@ -863,6 +934,23 @@ debuginfod_query_server (debuginfod_client *c,
msg = curl_multi_info_read(curlm, &num_msg);
if (msg != NULL && msg->msg == CURLMSG_DONE)
{
+ if (vfd >= 0)
+ {
+ bool pnl = (c->default_progressfn_printed_p
+ && vfd == STDERR_FILENO);
+ dprintf (vfd, "%sserver response %s\n", pnl ? "\n" : "",
+ curl_easy_strerror (msg->data.result));
+ if (pnl)
+ c->default_progressfn_printed_p = 0;
+ for (int i = 0; i < num_urls; i++)
+ if (msg->easy_handle == data[i].handle)
+ {
+ if (strlen (data[i].errbuf) > 0)
+ dprintf (vfd, "url %d %s\n", i, data[i].errbuf);
+ break;
+ }
+ }
+
if (msg->data.result != CURLE_OK)
{
/* Unsucessful query, determine error code. */
@@ -946,6 +1034,14 @@ debuginfod_query_server (debuginfod_client *c,
if (verified_handle == NULL)
goto out1;
+ if (vfd >= 0)
+ {
+ bool pnl = c->default_progressfn_printed_p && vfd == STDERR_FILENO;
+ dprintf (vfd, "%sgot file from server\n", pnl ? "\n" : "");
+ if (pnl)
+ c->default_progressfn_printed_p = 0;
+ }
+
/* we've got one!!!! */
time_t mtime;
CURLcode curl_res = curl_easy_getinfo(verified_handle, CURLINFO_FILETIME, (void*) &mtime);
@@ -1005,6 +1101,14 @@ debuginfod_query_server (debuginfod_client *c,
if (c->default_progressfn_printed_p)
dprintf(STDERR_FILENO, "\n");
+ if (vfd >= 0)
+ {
+ if (rc < 0)
+ dprintf (vfd, "not found %s (err=%d)\n", strerror (-rc), rc);
+ else
+ dprintf (vfd, "found %s (fd=%d)\n", target_cache_path, rc);
+ }
+
free (cache_path);
free (maxage_path);
free (interval_path);
@@ -1027,6 +1131,10 @@ debuginfod_begin (void)
{
if (getenv(DEBUGINFOD_PROGRESS_ENV_VAR))
client->progressfn = default_progressfn;
+ if (getenv(DEBUGINFOD_VERBOSE_ENV_VAR))
+ client->verbose_fd = STDERR_FILENO;
+ else
+ client->verbose_fd = -1;
}
return client;
}
@@ -1125,6 +1233,12 @@ debuginfod_set_progressfn(debuginfod_client *client,
client->progressfn = fn;
}
+void
+debuginfod_set_verbose_fd(debuginfod_client *client, int fd)
+{
+ client->verbose_fd = fd;
+}
+
/* NB: these are thread-unsafe. */
__attribute__((constructor)) attribute_hidden void libdebuginfod_ctor(void)
diff --git a/debuginfod/debuginfod-find.c b/debuginfod/debuginfod-find.c
index 5f9bccc3..3e8ab203 100644
--- a/debuginfod/debuginfod-find.c
+++ b/debuginfod/debuginfod-find.c
@@ -98,7 +98,9 @@ static error_t parse_opt (int key, char *arg, struct argp_state *state)
switch (key)
{
case 'v': verbose++;
- debuginfod_set_progressfn (client, & progressfn); break;
+ debuginfod_set_progressfn (client, & progressfn);
+ debuginfod_set_verbose_fd (client, STDERR_FILENO);
+ break;
default: return ARGP_ERR_UNKNOWN;
}
return 0;
diff --git a/debuginfod/debuginfod.h b/debuginfod/debuginfod.h
index 8d90838b..4ee86ce9 100644
--- a/debuginfod/debuginfod.h
+++ b/debuginfod/debuginfod.h
@@ -34,6 +34,7 @@
#define DEBUGINFOD_CACHE_PATH_ENV_VAR "DEBUGINFOD_CACHE_PATH"
#define DEBUGINFOD_TIMEOUT_ENV_VAR "DEBUGINFOD_TIMEOUT"
#define DEBUGINFOD_PROGRESS_ENV_VAR "DEBUGINFOD_PROGRESS"
+#define DEBUGINFOD_VERBOSE_ENV_VAR "DEBUGINFOD_VERBOSE"
/* Handle for debuginfod-client connection. */
typedef struct debuginfod_client debuginfod_client;
@@ -75,6 +76,8 @@ typedef int (*debuginfod_progressfn_t)(debuginfod_client *c, long a, long b);
void debuginfod_set_progressfn(debuginfod_client *c,
debuginfod_progressfn_t fn);
+void debuginfod_set_verbose_fd(debuginfod_client *c, int fd);
+
/* Set the user parameter. */
void debuginfod_set_user_data (debuginfod_client *client, void *value);
diff --git a/debuginfod/libdebuginfod.map b/debuginfod/libdebuginfod.map
index b8edfb01..7d2f5882 100644
--- a/debuginfod/libdebuginfod.map
+++ b/debuginfod/libdebuginfod.map
@@ -14,4 +14,7 @@ ELFUTILS_0.179 {
debuginfod_get_user_data;
debuginfod_get_url;
debuginfod_add_http_header;
-};
+} ELFUTILS_0.178;
+ELFUTILS_0.183 {
+ debuginfod_set_verbose_fd;
+} ELFUTILS_0.179;
diff --git a/doc/ChangeLog b/doc/ChangeLog
index 8c33f174..fdf352e7 100644
--- a/doc/ChangeLog
+++ b/doc/ChangeLog
@@ -1,3 +1,10 @@
+2020-11-11 Mark Wielaard <mark@klomp.org>
+
+ * debuginfod_find_debuginfo.3: Document debuginfod_set_verbose_fd
+ and DEBUGINFOD_VERBOSE.
+ * debuginfod_set_verbose_fd.3: New redirect to
+ debuginfod_find_debuginfo.3
+
2020-10-29 Frank Ch. Eigler <fche@redhat.com>
PR26775
diff --git a/doc/debuginfod_find_debuginfo.3 b/doc/debuginfod_find_debuginfo.3
index eec04e5e..3c6d52f5 100644
--- a/doc/debuginfod_find_debuginfo.3
+++ b/doc/debuginfod_find_debuginfo.3
@@ -50,6 +50,8 @@ OPTIONAL FUNCTIONS
.BI " long a, long b);"
.BI "void debuginfod_set_progressfn(debuginfod_client *" client ","
.BI " debuginfod_progressfn_t " progressfn ");"
+.BI "void debuginfod_set_verbose_fd(debuginfod_client *" client ","
+.BI " int " fd ");"
.BI "void debuginfod_set_user_data(debuginfod_client *" client ","
.BI " void *" data ");"
.BI "void* debuginfod_get_user_data(debuginfod_client *" client ");"
@@ -143,6 +145,15 @@ continue the work, or any other value to stop work as soon as
possible. Consequently, the \fBdebuginfod_find_*\fP() function will
likely return with an error, but might still succeed.
+.SS "VERBOSE OUTPUT"
+
+The \fBdebuginfod_find_*\fP() functions may use several techniques
+to retrieve the requested files, through the cache or through one
+or multiple servers or file URLs. To show how a query is handled hte
+.BR debuginfod_set_verbose_fd ()
+can be used to set a particular file descriptor on which verbose
+output is given about the query steps and eventual errors encountered.
+
.SS "USER DATA POINTER"
A single \fIvoid *\fP pointer associated with the connection handle
@@ -236,6 +247,12 @@ progress message periodically to stderr. The default is no progress
function output.
.TP 21
+.B DEBUGINFOD_VERBOSE
+This environment variable governs the default file descriptor for
+verbose output. If set, and if a verbose fd is not explicitly set,
+then the verbose output will be produced on STDERR_FILENO.
+
+.TP 21
.B DEBUGINFOD_CACHE_PATH
This environment variable governs the location of the cache where
downloaded files are kept. It is cleaned periodically as this