From b0cd5238238ec4a169402418c6914822c6c46c21 Mon Sep 17 00:00:00 2001
From: Jon Turney <jon.turney@dronecode.org.uk>
Date: Sat, 5 Mar 2016 12:48:05 +0000
Subject: [PATCH 03/29] Link minidump_upload and sym_upload with curl

Don't link with -ldl and use dlopen to use libcurl.so, but just link with
libcurl

This has the advantage of not needing to know the precise name of the curl
shared object on every platform...

This effectively reverts commit 68b4798e

See also https://bugs.chromium.org/p/google-breakpad/issues/detail?id=225

XXX: Perhaps retaining linking with -dl and just teaching it the name of
curl shared object on Cygwin would be more upstreamable, although the
reasons for solving the bug above like this are obscure to me ...

Signed-off-by: Jon Turney <jon.turney@dronecode.org.uk>
---
 Makefile.am                     |   4 +-
 src/common/linux/http_upload.cc | 101 ++++++++--------------------------------
 2 files changed, 21 insertions(+), 84 deletions(-)

diff --git a/Makefile.am b/Makefile.am
index 6f009196..f0939b8c 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -601,7 +601,7 @@ src_tools_linux_md2core_minidump_2_core_SOURCES = \
 src_tools_linux_symupload_minidump_upload_SOURCES = \
 	src/common/linux/http_upload.cc \
 	src/tools/linux/symupload/minidump_upload.cc
-src_tools_linux_symupload_minidump_upload_LDADD = -ldl
+src_tools_linux_symupload_minidump_upload_LDADD = -lcurl
 
 src_tools_linux_symupload_sym_upload_SOURCES = \
 	src/common/linux/http_upload.cc \
@@ -609,7 +609,7 @@ src_tools_linux_symupload_sym_upload_SOURCES = \
 	src/common/linux/symbol_upload.cc \
 	src/common/linux/symbol_upload.h \
 	src/tools/linux/symupload/sym_upload.cc
-src_tools_linux_symupload_sym_upload_LDADD = -ldl
+src_tools_linux_symupload_sym_upload_LDADD = -lcurl
 
 src_tools_mac_dump_syms_dump_syms_mac_SOURCES = \
 	src/common/dwarf_cfi_to_module.cc \
diff --git a/src/common/linux/http_upload.cc b/src/common/linux/http_upload.cc
index c62b0cf0..3d215810 100644
--- a/src/common/linux/http_upload.cc
+++ b/src/common/linux/http_upload.cc
@@ -30,7 +30,6 @@
 #include "common/linux/http_upload.h"
 
 #include <assert.h>
-#include <dlfcn.h>
 #include <curl/curl.h>
 #include <curl/easy.h>
 
@@ -70,52 +69,13 @@ bool HTTPUpload::SendRequest(const string &url,
   if (!CheckParameters(parameters))
     return false;
 
-  // We may have been linked statically; if curl_easy_init is in the
-  // current binary, no need to search for a dynamic version.
-  void* curl_lib = dlopen(NULL, RTLD_NOW);
-  if (!CheckCurlLib(curl_lib)) {
-    fprintf(stderr,
-            "Failed to open curl lib from binary, use libcurl.so instead\n");
-    dlerror();  // Clear dlerror before attempting to open libraries.
-    dlclose(curl_lib);
-    curl_lib = NULL;
-  }
-  if (!curl_lib) {
-    curl_lib = dlopen("libcurl.so", RTLD_NOW);
-  }
-  if (!curl_lib) {
-    if (error_description != NULL)
-      *error_description = dlerror();
-    curl_lib = dlopen("libcurl.so.4", RTLD_NOW);
-  }
-  if (!curl_lib) {
-    // Debian gives libcurl a different name when it is built against GnuTLS
-    // instead of OpenSSL.
-    curl_lib = dlopen("libcurl-gnutls.so.4", RTLD_NOW);
-  }
-  if (!curl_lib) {
-    curl_lib = dlopen("libcurl.so.3", RTLD_NOW);
-  }
-  if (!curl_lib) {
-    return false;
-  }
-
-  CURL* (*curl_easy_init)(void);
-  *(void**) (&curl_easy_init) = dlsym(curl_lib, "curl_easy_init");
-  CURL *curl = (*curl_easy_init)();
+  CURL *curl = curl_easy_init();
   if (error_description != NULL)
     *error_description = "No Error";
 
-  if (!curl) {
-    dlclose(curl_lib);
-    return false;
-  }
-
   CURLcode err_code = CURLE_OK;
-  CURLcode (*curl_easy_setopt)(CURL *, CURLoption, ...);
-  *(void**) (&curl_easy_setopt) = dlsym(curl_lib, "curl_easy_setopt");
-  (*curl_easy_setopt)(curl, CURLOPT_URL, url.c_str());
-  (*curl_easy_setopt)(curl, CURLOPT_USERAGENT, kUserAgent);
+  curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
+  curl_easy_setopt(curl, CURLOPT_USERAGENT, kUserAgent);
   // Support multithread by disabling timeout handling, would get SIGSEGV with
   // Curl_resolv_timeout in stack trace otherwise.
   // See https://curl.haxx.se/libcurl/c/threadsafe.html
@@ -132,83 +92,60 @@ bool HTTPUpload::SendRequest(const string &url,
   struct curl_httppost *formpost = NULL;
   struct curl_httppost *lastptr = NULL;
   // Add form data.
-  CURLFORMcode (*curl_formadd)(struct curl_httppost **, struct curl_httppost **, ...);
-  *(void**) (&curl_formadd) = dlsym(curl_lib, "curl_formadd");
   map<string, string>::const_iterator iter = parameters.begin();
   for (; iter != parameters.end(); ++iter)
-    (*curl_formadd)(&formpost, &lastptr,
+    curl_formadd(&formpost, &lastptr,
                  CURLFORM_COPYNAME, iter->first.c_str(),
                  CURLFORM_COPYCONTENTS, iter->second.c_str(),
                  CURLFORM_END);
 
   // Add form files.
   for (iter = files.begin(); iter != files.end(); ++iter) {
-    (*curl_formadd)(&formpost, &lastptr,
+    curl_formadd(&formpost, &lastptr,
                  CURLFORM_COPYNAME, iter->first.c_str(),
                  CURLFORM_FILE, iter->second.c_str(),
                  CURLFORM_END);
   }
 
-  (*curl_easy_setopt)(curl, CURLOPT_HTTPPOST, formpost);
+  curl_easy_setopt(curl, CURLOPT_HTTPPOST, formpost);
 
   // Disable 100-continue header.
   struct curl_slist *headerlist = NULL;
   char buf[] = "Expect:";
-  struct curl_slist* (*curl_slist_append)(struct curl_slist *, const char *);
-  *(void**) (&curl_slist_append) = dlsym(curl_lib, "curl_slist_append");
-  headerlist = (*curl_slist_append)(headerlist, buf);
-  (*curl_easy_setopt)(curl, CURLOPT_HTTPHEADER, headerlist);
+  headerlist = curl_slist_append(headerlist, buf);
+  curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headerlist);
 
   if (response_body != NULL) {
-    (*curl_easy_setopt)(curl, CURLOPT_WRITEFUNCTION, WriteCallback);
-    (*curl_easy_setopt)(curl, CURLOPT_WRITEDATA,
+    curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallback);
+    curl_easy_setopt(curl, CURLOPT_WRITEDATA,
                      reinterpret_cast<void *>(response_body));
   }
 
   // Fail if 400+ is returned from the web server.
-  (*curl_easy_setopt)(curl, CURLOPT_FAILONERROR, 1);
+  curl_easy_setopt(curl, CURLOPT_FAILONERROR, 1);
 
-  CURLcode (*curl_easy_perform)(CURL *);
-  *(void**) (&curl_easy_perform) = dlsym(curl_lib, "curl_easy_perform");
-  err_code = (*curl_easy_perform)(curl);
+  err_code = curl_easy_perform(curl);
   if (response_code != NULL) {
-    CURLcode (*curl_easy_getinfo)(CURL *, CURLINFO, ...);
-    *(void**) (&curl_easy_getinfo) = dlsym(curl_lib, "curl_easy_getinfo");
-    (*curl_easy_getinfo)(curl, CURLINFO_RESPONSE_CODE, response_code);
+    curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, response_code);
   }
-  const char* (*curl_easy_strerror)(CURLcode);
-  *(void**) (&curl_easy_strerror) = dlsym(curl_lib, "curl_easy_strerror");
 #ifndef NDEBUG
   if (err_code != CURLE_OK)
     fprintf(stderr, "Failed to send http request to %s, error: %s\n",
             url.c_str(),
-            (*curl_easy_strerror)(err_code));
+            curl_easy_strerror(err_code));
 #endif
   if (error_description != NULL)
-    *error_description = (*curl_easy_strerror)(err_code);
+    *error_description = curl_easy_strerror(err_code);
 
-  void (*curl_easy_cleanup)(CURL *);
-  *(void**) (&curl_easy_cleanup) = dlsym(curl_lib, "curl_easy_cleanup");
-  (*curl_easy_cleanup)(curl);
+  curl_easy_cleanup(curl);
   if (formpost != NULL) {
-    void (*curl_formfree)(struct curl_httppost *);
-    *(void**) (&curl_formfree) = dlsym(curl_lib, "curl_formfree");
-    (*curl_formfree)(formpost);
+    curl_formfree(formpost);
   }
   if (headerlist != NULL) {
-    void (*curl_slist_free_all)(struct curl_slist *);
-    *(void**) (&curl_slist_free_all) = dlsym(curl_lib, "curl_slist_free_all");
-    (*curl_slist_free_all)(headerlist);
+    curl_slist_free_all(headerlist);
   }
-  dlclose(curl_lib);
-  return err_code == CURLE_OK;
-}
 
-// static
-bool HTTPUpload::CheckCurlLib(void* curl_lib) {
-  return curl_lib &&
-      dlsym(curl_lib, "curl_easy_init") &&
-      dlsym(curl_lib, "curl_easy_setopt");
+  return err_code == CURLE_OK;
 }
 
 // static
-- 
2.15.0

