summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFrank Ch. Eigler <fche@redhat.com>2019-08-10 12:39:42 -0400
committerFrank Ch. Eigler <fche@redhat.com>2019-09-03 11:57:37 -0400
commit480eb624411306278a24b2201f56978029d29255 (patch)
tree899f708f8819ae19d54953bed550ad2aeb9ed3ea
parent8949feb2ce3f9a14658f5e7893dca3196eb966d1 (diff)
downloadelfutils-480eb624411306278a24b2201f56978029d29255.tar.gz
dbgserver: snap
- support more specific posix error codes from dbgserver-find lookups - accept presence or absence of traling slash in DBGSERVER_URL - be able to run dbgserver-find.sh tests in check and installcheck mode - run installcheck tests in dbgserver proper, by adding argp to dbgserver-find.c
-rw-r--r--dbgserver/Makefile.am19
-rw-r--r--dbgserver/dbgserver-client.c38
-rw-r--r--dbgserver/dbgserver-find.c53
-rw-r--r--dbgserver/dbgserver.cxx10
-rwxr-xr-xtests/run-dbgserver-find.sh22
5 files changed, 116 insertions, 26 deletions
diff --git a/dbgserver/Makefile.am b/dbgserver/Makefile.am
index 0e239bcd..35d9387c 100644
--- a/dbgserver/Makefile.am
+++ b/dbgserver/Makefile.am
@@ -62,7 +62,7 @@ man1_MANS = dbgserver-find.1
dbgserver_LDADD = $(libdw) $(libelf) $(libeu) $(libdbgserver) $(libmicrohttpd_LIBS) $(libcurl_LIBS) $(sqlite3_LIBS) $(libarchive_LIBS) -lpthread -ldl
dbgserver_find_SOURCES = dbgserver-find.c
-dbgserver_find_LDADD = $(libdbgserver)
+dbgserver_find_LDADD = $(libeu) $(libdbgserver)
noinst_LIBRARIES = libdbgserver.a
noinst_LIBRARIES += libdbgserver_pic.a
@@ -100,3 +100,20 @@ uninstall: uninstall-am
EXTRA_DIST = libdbgserver.map dbgserver.8 dbgserver-find.1
MOSTLYCLEANFILES = $(am_libdbgserver_pic_a_OBJECTS) libdbgserver.so.$(VERSION)
CLEANFILES += $(am_libdbgserver_pic_a_OBJECTS) libdbgserver.so
+
+# automake std-options override: arrange to pass LD_LIBRARY_PATH
+installcheck-binPROGRAMS: $(bin_PROGRAMS)
+ bad=0; pid=$$$$; list="$(bin_PROGRAMS)"; for p in $$list; do \
+ case ' $(AM_INSTALLCHECK_STD_OPTIONS_EXEMPT) ' in \
+ *" $$p "* | *" $(srcdir)/$$p "*) continue;; \
+ esac; \
+ f=`echo "$$p" | \
+ sed 's,^.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/'`; \
+ for opt in --help --version; do \
+ if LD_LIBRARY_PATH=$(DESTDIR)$(libdir) \
+ $(DESTDIR)$(bindir)/$$f $$opt > c$${pid}_.out 2> c$${pid}_.err \
+ && test -n "`cat c$${pid}_.out`" \
+ && test -z "`cat c$${pid}_.err`"; then :; \
+ else echo "$$f does not support $$opt" 1>&2; bad=1; fi; \
+ done; \
+ done; rm -f c$${pid}_.???; exit $$bad
diff --git a/dbgserver/dbgserver-client.c b/dbgserver/dbgserver-client.c
index 60fe7bfa..07ff6076 100644
--- a/dbgserver/dbgserver-client.c
+++ b/dbgserver/dbgserver-client.c
@@ -341,10 +341,20 @@ dbgserver_query_server (const unsigned char *build_id_bytes,
{
/* query servers until we find the target or run out of urls to try. */
char url[PATH_MAX];
- if (filename) // starts with /
- snprintf(url, PATH_MAX, "%s/buildid/%s/%s%s", server_url, build_id, type, filename);
+
+ /* Tolerate both http://foo:999 and http://foo:999/ forms */
+ char *slashbuildid;
+ if (strlen(server_url) > 1 && server_url[strlen(server_url)-1] == '/')
+ slashbuildid = "buildid";
+ else
+ slashbuildid = "/buildid";
+
+ if (filename) /* must start with / */
+ snprintf(url, PATH_MAX, "%s%s/%s/%s%s", server_url,
+ slashbuildid, build_id, type, filename);
else
- snprintf(url, PATH_MAX, "%s/buildid/%s/%s", server_url, build_id, type);
+ snprintf(url, PATH_MAX, "%s%s/%s/%s", server_url,
+ slashbuildid, build_id, type);
curl_easy_reset(session);
curl_easy_setopt(session, CURLOPT_URL, url);
@@ -355,6 +365,7 @@ dbgserver_query_server (const unsigned char *build_id_bytes,
curl_easy_setopt(session, CURLOPT_TIMEOUT, (long) server_timeout);
curl_easy_setopt(session, CURLOPT_FILETIME, (long) 1);
curl_easy_setopt(session, CURLOPT_FOLLOWLOCATION, (long) 1);
+ curl_easy_setopt(session, CURLOPT_FAILONERROR, (long) 1);
curl_easy_setopt(session, CURLOPT_AUTOREFERER, (long) 1);
curl_easy_setopt(session, CURLOPT_ACCEPT_ENCODING, "");
curl_easy_setopt(session, CURLOPT_USERAGENT, (void*) PACKAGE_STRING);
@@ -362,6 +373,21 @@ dbgserver_query_server (const unsigned char *build_id_bytes,
CURLcode curl_res = curl_easy_perform(session);
if (curl_res != CURLE_OK)
{
+ /* curl_easy_getinfo(session, CURLINFO_OS_ERRNO ...) would be nice if it worked. */
+ switch (curl_res) /* map CURL error numbers to approximate libc errnos */
+ {
+ case CURLE_COULDNT_RESOLVE_HOST: rc = -EHOSTUNREACH; break; // no NXDOMAIN
+ case CURLE_URL_MALFORMAT: rc = -EINVAL; break;
+ case CURLE_COULDNT_CONNECT: rc = -ECONNREFUSED; break;
+ case CURLE_REMOTE_ACCESS_DENIED: rc = -EACCES; break;
+ case CURLE_WRITE_ERROR: rc = -EIO; break;
+ case CURLE_OUT_OF_MEMORY: rc = -ENOMEM; break;
+ case CURLE_TOO_MANY_REDIRECTS: rc = -EMLINK; break;
+ case CURLE_SEND_ERROR: rc = -ECONNRESET; break;
+ case CURLE_RECV_ERROR: rc = -ECONNRESET; break;
+ default: rc = -ENOENT; break;
+ }
+
server_url = strtok_r(NULL, url_delim,&strtok_saveptr);
continue; /* fail over to next server */
}
@@ -404,8 +430,10 @@ dbgserver_query_server (const unsigned char *build_id_bytes,
return fd;
}
-/* fell through - out of alternative servers */
- rc = -ENOENT;
+ /* fell through - out of alternative servers */
+ /* prefer to preserve the last rc set from curl OS_ERRNO */
+ if (rc == 0)
+ rc = -ENOENT;
/* error exits */
out2:
diff --git a/dbgserver/dbgserver-find.c b/dbgserver/dbgserver-find.c
index caa053d4..ea31c288 100644
--- a/dbgserver/dbgserver-find.c
+++ b/dbgserver/dbgserver-find.c
@@ -28,46 +28,71 @@
not, see <http://www.gnu.org/licenses/>. */
#include "config.h"
+#include "printversion.h"
#include "dbgserver-client.h"
#include <errno.h>
#include <stdio.h>
#include <string.h>
+#include <argp.h>
+
+
+/* Name and version of program. */
+ARGP_PROGRAM_VERSION_HOOK_DEF = print_version;
+
+/* Bug report address. */
+ARGP_PROGRAM_BUG_ADDRESS_DEF = PACKAGE_BUGREPORT;
+
+/* Short description of program. */
+static const char doc[] = N_("Request debuginfo-related content from dbgservers.");
+
+/* Strings for arguments in help texts. */
+static const char args_doc[] = N_("debuginfo BUILDID\n"
+ "executable BUILDID\n"
+ "source BUILDID /FILENAME");
+
+/* Data structure to communicate with argp functions. */
+static struct argp argp =
+ {
+ NULL, NULL, args_doc, doc, NULL, NULL, NULL
+ };
+
int
main(int argc, char** argv)
{
- if (argc < 3 || argc > 4)
+ int remaining;
+ (void) argp_parse (&argp, argc, argv, ARGP_IN_ORDER|ARGP_NO_ARGS, &remaining, NULL);
+
+ if (remaining+1 == argc) /* at least two non-option words */
{
- fprintf(stderr, "%s (%s) %s\n", argv[0], PACKAGE_NAME, PACKAGE_VERSION);
- fprintf(stderr, "Usage: %s debuginfo BUILDID\n", argv[0]);
- fprintf(stderr, " %s executable BUILDID\n", argv[0]);
- fprintf(stderr, " %s source BUILDID /FILENAME\n", argv[0]);
+ argp_help (&argp, stderr, ARGP_HELP_USAGE, argv[0]);
return 1;
}
-
+
int rc;
char *cache_name;
/* Check whether FILETYPE is valid and call the appropriate
dbgserver_find_* function. If FILETYPE is "source"
then ensure a FILENAME was also supplied as an argument. */
- if (strcmp(argv[1], "debuginfo") == 0)
- rc = dbgserver_find_debuginfo((unsigned char *)argv[2], 0, &cache_name);
- else if (strcmp(argv[1], "executable") == 0)
- rc = dbgserver_find_executable((unsigned char *)argv[2], 0, &cache_name);
- else if (strcmp(argv[1], "source") == 0)
+ if (strcmp(argv[remaining], "debuginfo") == 0)
+ rc = dbgserver_find_debuginfo((unsigned char *)argv[remaining+1], 0, &cache_name);
+ else if (strcmp(argv[remaining], "executable") == 0)
+ rc = dbgserver_find_executable((unsigned char *)argv[remaining+1], 0, &cache_name);
+ else if (strcmp(argv[remaining], "source") == 0)
{
- if (argc != 4 || argv[3][0] != '/')
+ if (remaining+2 == argc || argv[3][0] != '/')
{
fprintf(stderr, "If FILETYPE is \"source\" then absolute /FILENAME must be given\n");
return 1;
}
- rc = dbgserver_find_source((unsigned char *)argv[2], 0, argv[3], &cache_name);
+ rc = dbgserver_find_source((unsigned char *)argv[remaining+1], 0,
+ argv[remaining+2], &cache_name);
}
else
{
- fprintf(stderr, "Invalid filetype\n");
+ argp_help (&argp, stderr, ARGP_HELP_USAGE, argv[0]);
return 1;
}
diff --git a/dbgserver/dbgserver.cxx b/dbgserver/dbgserver.cxx
index 4b852aee..582b0c21 100644
--- a/dbgserver/dbgserver.cxx
+++ b/dbgserver/dbgserver.cxx
@@ -31,7 +31,10 @@
#include "config.h"
#endif
+extern "C" {
#include "printversion.h"
+}
+
#include "dbgserver-client.h"
#include <dwarf.h>
@@ -206,7 +209,7 @@ static const char DBGSERVER_SQLITE_DDL[] =
/* Name and version of program. */
-/* ARGP_PROGRAM_VERSION_HOOK_DEF = print_version; */
+/* ARGP_PROGRAM_VERSION_HOOK_DEF = print_version; */ // not this simple for C++
/* Bug report address. */
ARGP_PROGRAM_BUG_ADDRESS_DEF = PACKAGE_BUGREPORT;
@@ -1808,6 +1811,7 @@ main (int argc, char *argv[])
/* Parse and process arguments. */
int remaining;
+ argp_program_version_hook = print_version; // this works
(void) argp_parse (&argp, argc, argv, ARGP_IN_ORDER|ARGP_NO_ARGS, &remaining, NULL);
if (remaining != argc)
error (EXIT_FAILURE, 0,
@@ -1934,6 +1938,10 @@ main (int argc, char *argv[])
<< (d4 != NULL ? "IPv4 " : "")
<< (d6 != NULL ? "IPv6 " : "")
<< "port=" << http_port << endl;
+
+ const char* du = getenv("DBGSERVER_URLS");
+ if (du && du[0] != '\0') // set to non-empty string?
+ obatched(clog) << "Upstream dbgservers: " << du << endl;
/* Trivial main loop! */
while (! interrupted)
diff --git a/tests/run-dbgserver-find.sh b/tests/run-dbgserver-find.sh
index bd3a75a6..b1549396 100755
--- a/tests/run-dbgserver-find.sh
+++ b/tests/run-dbgserver-find.sh
@@ -30,18 +30,30 @@ while true; do
ss -atn | fgrep ":$PORT" || break
done
-../../dbgserver/dbgserver -vvv -d $DB -F $PWD -p $PORT &
+set -x
+
+# We want to run dbgserver in the background. We also want to start
+# it with the same check/installcheck-sensitive LD_LIBRARY_PATH stuff
+# that the testrun alias sets. But: we if we just use
+# testrun .../dbgserver
+# it runs in a subshell, with different pid, so not helpful.
+#
+# So we gather the LD_LIBRARY_PATH with this cunning trick:
+
+ldpath=`testrun sh -c 'echo $LD_LIBRARY_PATH'`
+env LD_LIBRARY_PATH=$ldpath ${abs_builddir}/../dbgserver/dbgserver -vvv -d $DB -F $PWD -p $PORT &
PID=$!
-trap 'kill $PID || true; rm -f $DB' 0 1 5 9 15
sleep 5
+tempfiles .dbgserver_*
-export DBGSERVER_URLS=http://localhost:$PORT # XXX: no / at end; dbgserver rejects extra /
+export DBGSERVER_URLS=http://localhost:$PORT/ # or without trailing /
# Test whether the server is able to fetch the file from the local dbgserver.
testrun ${abs_builddir}/dbgserver_build_id_find -e testfile-dbgserver.exec $EXPECT_PASS
-kill $PID
-rm $DB
+kill -INT $PID
+sleep 5
+tempfiles .dbgserver_*
# Run the test again without the server running. The target file should
# be found in the cache.