From e45dae9d3b119226e946d2d0c557c2ed8ba054bd Mon Sep 17 00:00:00 2001 From: Danny Robson Date: Mon, 19 Oct 2020 07:52:36 +1000 Subject: [PATCH] initial import --- recipes/breakpad/all/conandata.yml | 27 + recipes/breakpad/all/conanfile.py | 87 + ...01-Remove-local-copy-of-curl-headers.patch | 3760 +++++++++++++++++ ...dump_upload-and-sym_upload-with-curl.patch | 218 + ...pload-and-sym_upload-for-all-targets.patch | 85 + ...DWARF-in-PECOFF-as-used-by-Cygwin-an.patch | 2217 ++++++++++ ...uilding-minidump-processor-for-MinGW.patch | 183 + ...ild-PECOFF-DWARF-dump_syms-for-MinGW.patch | 139 + ...ent-library-and-upload-tools-for-Min.patch | 98 + ...to-allow-gyp-to-generate-Makefiles-o.patch | 43 + ...ted-Makefile-to-build-crash_generati.patch | 165 + ...debug_file-to-the-code_file-basename.patch | 94 + ...x-Windows-client-unit-tests-with-gcc.patch | 147 + .../all/patches/0012-Add-symsrv_convert.patch | 187 + ...bug-id-of-all-zeros-when-no-CV-recor.patch | 69 + ...USE_MINGW_ANSI_STDIO-for-MinGW-build.patch | 32 + ...Provide-a-working-strtok_r-for-MinGW.patch | 319 ++ ...hesizing-a-debug-id-from-version-and.patch | 62 + ...name-of-the-info-entry-containing-up.patch | 29 + ...-a-missing-r-in-crash_generation_app.patch | 30 + .../0019-Disable-DwpReader-for-MinGW.patch | 106 + ...-Use-allocator_traits-rather-than-al.patch | 30 + ...-handler-to-DwarfCUToModule-construc.patch | 25 + ...breakpad-client-library-if-a-MINGW_H.patch | 69 + ...3-Enable-minimalist-build-signatures.patch | 28 + ...seudo-build-ID-generation-for-PECOFF.patch | 27 + ...ngs-use-the-wide-versions-of-Windows.patch | 208 + ...version-workaround-GCC10-codegen-bug.patch | 27 + recipes/libcurl/all/conandata.yml | 38 + recipes/libcurl/all/conanfile.py | 564 +++ ...H2.cmake-add-libssh2-as-possible-nam.patch | 16 + recipes/libcurl/config.yml | 19 + requirements.txt | 1 + 33 files changed, 9149 insertions(+) create mode 100644 recipes/breakpad/all/conandata.yml create mode 100644 recipes/breakpad/all/conanfile.py create mode 100644 recipes/breakpad/all/patches/0001-Remove-local-copy-of-curl-headers.patch create mode 100644 recipes/breakpad/all/patches/0002-Link-minidump_upload-and-sym_upload-with-curl.patch create mode 100644 recipes/breakpad/all/patches/0003-Build-minidump_upload-and-sym_upload-for-all-targets.patch create mode 100644 recipes/breakpad/all/patches/0004-Add-support-for-DWARF-in-PECOFF-as-used-by-Cygwin-an.patch create mode 100644 recipes/breakpad/all/patches/0005-Fix-building-minidump-processor-for-MinGW.patch create mode 100644 recipes/breakpad/all/patches/0006-Build-PECOFF-DWARF-dump_syms-for-MinGW.patch create mode 100644 recipes/breakpad/all/patches/0007-Fix-building-client-library-and-upload-tools-for-Min.patch create mode 100644 recipes/breakpad/all/patches/0008-Fix-common.gypi-to-allow-gyp-to-generate-Makefiles-o.patch create mode 100644 recipes/breakpad/all/patches/0009-Teach-gyp-generated-Makefile-to-build-crash_generati.patch create mode 100644 recipes/breakpad/all/patches/0010-Default-debug_file-to-the-code_file-basename.patch create mode 100644 recipes/breakpad/all/patches/0011-Fix-Windows-client-unit-tests-with-gcc.patch create mode 100644 recipes/breakpad/all/patches/0012-Add-symsrv_convert.patch create mode 100644 recipes/breakpad/all/patches/0013-Use-a-default-debug-id-of-all-zeros-when-no-CV-recor.patch create mode 100644 recipes/breakpad/all/patches/0014-Use-__USE_MINGW_ANSI_STDIO-for-MinGW-build.patch create mode 100644 recipes/breakpad/all/patches/0015-Provide-a-working-strtok_r-for-MinGW.patch create mode 100644 recipes/breakpad/all/patches/0016-Fallback-to-synthesizing-a-debug-id-from-version-and.patch create mode 100644 recipes/breakpad/all/patches/0017-Fix-typo-in-the-name-of-the-info-entry-containing-up.patch create mode 100644 recipes/breakpad/all/patches/0018-Fix-a-missing-r-in-crash_generation_app.patch create mode 100644 recipes/breakpad/all/patches/0019-Disable-DwpReader-for-MinGW.patch create mode 100644 recipes/breakpad/all/patches/0020-memory_allocator-Use-allocator_traits-rather-than-al.patch create mode 100644 recipes/breakpad/all/patches/0021-Add-a-null-range-handler-to-DwarfCUToModule-construc.patch create mode 100644 recipes/breakpad/all/patches/0022-Build-a-minimal-breakpad-client-library-if-a-MINGW_H.patch create mode 100644 recipes/breakpad/all/patches/0023-Enable-minimalist-build-signatures.patch create mode 100644 recipes/breakpad/all/patches/0024-Disable-the-pseudo-build-ID-generation-for-PECOFF.patch create mode 100644 recipes/breakpad/all/patches/0025-Ensure-wide-strings-use-the-wide-versions-of-Windows.patch create mode 100644 recipes/breakpad/all/patches/0026-string_conversion-workaround-GCC10-codegen-bug.patch create mode 100644 recipes/libcurl/all/conandata.yml create mode 100644 recipes/libcurl/all/conanfile.py create mode 100644 recipes/libcurl/all/patches/001-Update-FindLibSSH2.cmake-add-libssh2-as-possible-nam.patch create mode 100644 recipes/libcurl/config.yml create mode 100644 requirements.txt diff --git a/recipes/breakpad/all/conandata.yml b/recipes/breakpad/all/conandata.yml new file mode 100644 index 0000000..44491eb --- /dev/null +++ b/recipes/breakpad/all/conandata.yml @@ -0,0 +1,27 @@ +patches: + - "patches/0001-Remove-local-copy-of-curl-headers.patch" + - "patches/0002-Link-minidump_upload-and-sym_upload-with-curl.patch" + - "patches/0003-Build-minidump_upload-and-sym_upload-for-all-targets.patch" + - "patches/0004-Add-support-for-DWARF-in-PECOFF-as-used-by-Cygwin-an.patch" + - "patches/0005-Fix-building-minidump-processor-for-MinGW.patch" + - "patches/0006-Build-PECOFF-DWARF-dump_syms-for-MinGW.patch" + - "patches/0007-Fix-building-client-library-and-upload-tools-for-Min.patch" + - "patches/0008-Fix-common.gypi-to-allow-gyp-to-generate-Makefiles-o.patch" + - "patches/0009-Teach-gyp-generated-Makefile-to-build-crash_generati.patch" + - "patches/0010-Default-debug_file-to-the-code_file-basename.patch" + - "patches/0011-Fix-Windows-client-unit-tests-with-gcc.patch" + - "patches/0012-Add-symsrv_convert.patch" + - "patches/0013-Use-a-default-debug-id-of-all-zeros-when-no-CV-recor.patch" + - "patches/0014-Use-__USE_MINGW_ANSI_STDIO-for-MinGW-build.patch" + - "patches/0015-Provide-a-working-strtok_r-for-MinGW.patch" + - "patches/0016-Fallback-to-synthesizing-a-debug-id-from-version-and.patch" + - "patches/0017-Fix-typo-in-the-name-of-the-info-entry-containing-up.patch" + - "patches/0018-Fix-a-missing-r-in-crash_generation_app.patch" + - "patches/0019-Disable-DwpReader-for-MinGW.patch" + - "patches/0020-memory_allocator-Use-allocator_traits-rather-than-al.patch" + - "patches/0021-Add-a-null-range-handler-to-DwarfCUToModule-construc.patch" + - "patches/0022-Build-a-minimal-breakpad-client-library-if-a-MINGW_H.patch" + - "patches/0023-Enable-minimalist-build-signatures.patch" + - "patches/0024-Disable-the-pseudo-build-ID-generation-for-PECOFF.patch" + - "patches/0025-Ensure-wide-strings-use-the-wide-versions-of-Windows.patch" + - "patches/0026-string_conversion-workaround-GCC10-codegen-bug.patch" diff --git a/recipes/breakpad/all/conanfile.py b/recipes/breakpad/all/conanfile.py new file mode 100644 index 0000000..d1852d7 --- /dev/null +++ b/recipes/breakpad/all/conanfile.py @@ -0,0 +1,87 @@ +from conans import ConanFile, AutoToolsBuildEnvironment, tools +from conans.errors import ConanInvalidConfiguration + +import os +import sys + +class BreakpadConan(ConanFile): + name = "breakpad" + version = "64" + #license = "" + author = "Danny Robson danny@nerdcruft.net" + #url = "" + #description = "" + #topics = ("", "", "") + settings = "os", "compiler", "build_type", "arch" + #options = {"shared": [True, False]} + #default_options = {"shared": False} + requires = 'libcurl/7.71.0' + exports_sources = ["patches/*"] + build_requires = "autoconf/2.69" + + def source(self): + tools.unzip("/home/danny/src/conan/dist/breakpad.tar.xz") + + #self.run("git clone https://chromium.googlesource.com/breakpad/breakpad") + #with tools.chdir("breakpad"): + # self.run(f"git checkout db1cda26539c711c3da7ed4d410dfe8190e89b8f") + # self.run("mkdir src/third_party/ -p") + # with tools.chdir("src/third_party/"): + # self.run("git clone https://chromium.googlesource.com/linux-syscall-support/ lss") + + + def _stdlib_args(self): + lookup = { + 'gcc': { + 'libstdc++': '', + 'libstdc++11': '', + }, + 'clang': { + 'libstdc++': '-stdlib=libstdc++', + 'libstdc++11': '-stdlib=libstdc++', + 'libc++': '-stdlib=libc++', + }, + } + + compiler = lookup.get(self.settings.compiler.value, None) + if compiler is None: + raise ConanInvalidConfiguration(f"Unhandled compiler: {compiler}") + + arg = compiler.get(self.settings.compiler.libcxx.value, None) + if arg is None: + raise ConanInvalidConfiguration(f"Unhandled stdlib: {self.settings.compiler.libcxx.value}") + + return arg + + def build(self): + for patch in self.conan_data["patches"]: + print(f"Patching: {patch}") + tools.patch( + base_path="breakpad", + patch_file=patch, + strip=0, + fuzz=False + ) + + with tools.chdir('./breakpad'): + self.run("autoreconf -fiv", run_environment=True) + + stdlib = self._stdlib_args() + if stdlib is None: + raise ConanInvalidConfiguration ("Unable to determine stdlib flags for compiler") + + autotools = AutoToolsBuildEnvironment(self) + env_build_vars = autotools.vars + env_build_vars['CFLAGS'] = f'-Wno-error {stdlib}' + env_build_vars['CXXFLAGS'] = f'-Wno-error {stdlib}' + autotools.configure(vars=env_build_vars) + autotools.make(vars=env_build_vars) + + def package(self): + with tools.chdir('./breakpad'): + autotools = AutoToolsBuildEnvironment(self) + autotools.install() + + def package_info(self): + self.cpp_info.libs = ["breakpad_client"] + self.cpp_info.includedirs.append(os.path.join("include", "breakpad")) diff --git a/recipes/breakpad/all/patches/0001-Remove-local-copy-of-curl-headers.patch b/recipes/breakpad/all/patches/0001-Remove-local-copy-of-curl-headers.patch new file mode 100644 index 0000000..423b359 --- /dev/null +++ b/recipes/breakpad/all/patches/0001-Remove-local-copy-of-curl-headers.patch @@ -0,0 +1,3760 @@ +From b0dbb7bc07e3921ff27044cc5b52639d7c1aca3a Mon Sep 17 00:00:00 2001 +From: Jon Turney +Date: Sat, 12 Jul 2014 14:09:03 +0100 +Subject: [PATCH 01/19] Remove local copy of curl headers + +This reverts commit d9d863e153d12532fc85bd8b44bc47f079ed064c (svn r732) +This reverts commit 68e380d5a73a0d657693f166fbcb1dd77027766b (svn r829) + +v2: +Add libcurl-dev to packages needed on travis +Also remove curl headers from EXTRA_DIST +Don't include curl/types.h doesn't exist anymore and has been deprecated +since 2004 + +Signed-off-by: Jon Turney +--- + .travis.yml | 1 + + Makefile.am | 11 - + src/common/linux/http_upload.cc | 3 +- + src/common/linux/libcurl_wrapper.cc | 2 + + src/common/linux/libcurl_wrapper.h | 2 +- + src/third_party/curl/curl.h | 1936 -------------------------- + src/third_party/curl/curlbuild.h | 203 --- + src/third_party/curl/curlrules.h | 249 ---- + src/third_party/curl/curlver.h | 70 - + src/third_party/curl/easy.h | 103 -- + src/third_party/curl/mprintf.h | 82 -- + src/third_party/curl/multi.h | 346 ----- + src/third_party/curl/stdcheaders.h | 34 - + src/third_party/curl/typecheck-gcc.h | 551 -------- + src/third_party/curl/types.h | 1 - + 15 files changed, 6 insertions(+), 3588 deletions(-) + delete mode 100644 src/third_party/curl/curl.h + delete mode 100644 src/third_party/curl/curlbuild.h + delete mode 100644 src/third_party/curl/curlrules.h + delete mode 100644 src/third_party/curl/curlver.h + delete mode 100644 src/third_party/curl/easy.h + delete mode 100644 src/third_party/curl/mprintf.h + delete mode 100644 src/third_party/curl/multi.h + delete mode 100644 src/third_party/curl/stdcheaders.h + delete mode 100644 src/third_party/curl/typecheck-gcc.h + delete mode 100644 src/third_party/curl/types.h + +diff --git a/.travis.yml b/.travis.yml +index 628362d2..3edad8c3 100644 +--- a/.travis.yml ++++ b/.travis.yml +@@ -12,6 +12,7 @@ addons: + - clang + - gcc-4.8 + - g++-4.8 ++ - libcurl4-openssl-dev + + env: + global: +diff --git a/Makefile.am b/Makefile.am +index 59788766..dcef735d 100644 +--- a/Makefile.am ++++ b/Makefile.am +@@ -1500,17 +1500,6 @@ EXTRA_DIST = \ + src/testing/googlemock/src/gmock-matchers.cc \ + src/testing/googlemock/src/gmock-spec-builders.cc \ + src/testing/googlemock/src/gmock_main.cc \ +- src/third_party/curl/COPYING \ +- src/third_party/curl/curlbuild.h \ +- src/third_party/curl/curl.h \ +- src/third_party/curl/curlrules.h \ +- src/third_party/curl/curlver.h \ +- src/third_party/curl/easy.h \ +- src/third_party/curl/mprintf.h \ +- src/third_party/curl/multi.h \ +- src/third_party/curl/stdcheaders.h \ +- src/third_party/curl/typecheck-gcc.h \ +- src/third_party/curl/types.h \ + src/third_party/mac_headers/architecture/byte_order.h \ + src/third_party/mac_headers/i386/_types.h \ + src/third_party/mac_headers/mach/boolean.h \ +diff --git a/src/common/linux/http_upload.cc b/src/common/linux/http_upload.cc +index 702526af..c62b0cf0 100644 +--- a/src/common/linux/http_upload.cc ++++ b/src/common/linux/http_upload.cc +@@ -31,7 +31,8 @@ + + #include + #include +-#include "third_party/curl/curl.h" ++#include ++#include + + namespace { + +diff --git a/src/common/linux/libcurl_wrapper.cc b/src/common/linux/libcurl_wrapper.cc +index fd4e34cd..9fbfce66 100644 +--- a/src/common/linux/libcurl_wrapper.cc ++++ b/src/common/linux/libcurl_wrapper.cc +@@ -27,6 +27,8 @@ + // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + ++#include ++#include + #include + + #include +diff --git a/src/common/linux/libcurl_wrapper.h b/src/common/linux/libcurl_wrapper.h +index 25905ad8..21fb07cd 100644 +--- a/src/common/linux/libcurl_wrapper.h ++++ b/src/common/linux/libcurl_wrapper.h +@@ -32,12 +32,12 @@ + + #ifndef COMMON_LINUX_LIBCURL_WRAPPER_H_ + #define COMMON_LINUX_LIBCURL_WRAPPER_H_ ++#include + + #include + #include + + #include "common/using_std_string.h" +-#include "third_party/curl/curl.h" + + namespace google_breakpad { + class LibcurlWrapper { +diff --git a/src/third_party/curl/curl.h b/src/third_party/curl/curl.h +deleted file mode 100644 +index 0d80936f..00000000 +--- a/src/third_party/curl/curl.h ++++ /dev/null +@@ -1,1936 +0,0 @@ +-#ifndef __CURL_CURL_H +-#define __CURL_CURL_H +-/*************************************************************************** +- * _ _ ____ _ +- * Project ___| | | | _ \| | +- * / __| | | | |_) | | +- * | (__| |_| | _ <| |___ +- * \___|\___/|_| \_\_____| +- * +- * Copyright (C) 1998 - 2009, Daniel Stenberg, , et al. +- * +- * This software is licensed as described in the file COPYING, which +- * you should have received as part of this distribution. The terms +- * are also available at http://curl.haxx.se/docs/copyright.html. +- * +- * You may opt to use, copy, modify, merge, publish, distribute and/or sell +- * copies of the Software, and permit persons to whom the Software is +- * furnished to do so, under the terms of the COPYING file. +- * +- * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY +- * KIND, either express or implied. +- * +- * $Id: curl.h,v 1.396 2009-10-16 13:30:31 yangtse Exp $ +- ***************************************************************************/ +- +-/* +- * If you have libcurl problems, all docs and details are found here: +- * http://curl.haxx.se/libcurl/ +- * +- * curl-library mailing list subscription and unsubscription web interface: +- * http://cool.haxx.se/mailman/listinfo/curl-library/ +- */ +- +-/* +- * Leading 'curl' path on the 'curlbuild.h' include statement is +- * required to properly allow building outside of the source tree, +- * due to the fact that in this case 'curlbuild.h' is generated in +- * a subdirectory of the build tree while 'curl.h actually remains +- * in a subdirectory of the source tree. +- */ +- +-#include "third_party/curl/curlver.h" /* libcurl version defines */ +-#include "third_party/curl/curlbuild.h" /* libcurl build definitions */ +-#include "third_party/curl/curlrules.h" /* libcurl rules enforcement */ +- +-/* +- * Define WIN32 when build target is Win32 API +- */ +- +-#if (defined(_WIN32) || defined(__WIN32__)) && \ +- !defined(WIN32) && !defined(__SYMBIAN32__) +-#define WIN32 +-#endif +- +-#include +-#include +- +-/* The include stuff here below is mainly for time_t! */ +-#include +-#include +- +-#if defined(WIN32) && !defined(_WIN32_WCE) && !defined(__GNUC__) && \ +- !defined(__CYGWIN__) || defined(__MINGW32__) +-#if !(defined(_WINSOCKAPI_) || defined(_WINSOCK_H)) +-/* The check above prevents the winsock2 inclusion if winsock.h already was +- included, since they can't co-exist without problems */ +-#include +-#include +-#endif +-#else +- +-/* HP-UX systems version 9, 10 and 11 lack sys/select.h and so does oldish +- libc5-based Linux systems. Only include it on system that are known to +- require it! */ +-#if defined(_AIX) || defined(__NOVELL_LIBC__) || defined(__NetBSD__) || \ +- defined(__minix) || defined(__SYMBIAN32__) || defined(__INTEGRITY) || \ +- defined(__ANDROID__) +-#include +-#endif +- +-#ifndef _WIN32_WCE +-#include +-#endif +-#if !defined(WIN32) && !defined(__WATCOMC__) && !defined(__VXWORKS__) +-#include +-#endif +-#include +-#endif +- +-#ifdef __BEOS__ +-#include +-#endif +- +-#ifdef __cplusplus +-extern "C" { +-#endif +- +-typedef void CURL; +- +-/* +- * Decorate exportable functions for Win32 and Symbian OS DLL linking. +- * This avoids using a .def file for building libcurl.dll. +- */ +-#if (defined(WIN32) || defined(_WIN32) || defined(__SYMBIAN32__)) && \ +- !defined(CURL_STATICLIB) +-#if defined(BUILDING_LIBCURL) +-#define CURL_EXTERN __declspec(dllexport) +-#else +-#define CURL_EXTERN __declspec(dllimport) +-#endif +-#else +- +-#ifdef CURL_HIDDEN_SYMBOLS +-/* +- * This definition is used to make external definitions visible in the +- * shared library when symbols are hidden by default. It makes no +- * difference when compiling applications whether this is set or not, +- * only when compiling the library. +- */ +-#define CURL_EXTERN CURL_EXTERN_SYMBOL +-#else +-#define CURL_EXTERN +-#endif +-#endif +- +-#ifndef curl_socket_typedef +-/* socket typedef */ +-#ifdef WIN32 +-typedef SOCKET curl_socket_t; +-#define CURL_SOCKET_BAD INVALID_SOCKET +-#else +-typedef int curl_socket_t; +-#define CURL_SOCKET_BAD -1 +-#endif +-#define curl_socket_typedef +-#endif /* curl_socket_typedef */ +- +-struct curl_httppost { +- struct curl_httppost *next; /* next entry in the list */ +- char *name; /* pointer to allocated name */ +- long namelength; /* length of name length */ +- char *contents; /* pointer to allocated data contents */ +- long contentslength; /* length of contents field */ +- char *buffer; /* pointer to allocated buffer contents */ +- long bufferlength; /* length of buffer field */ +- char *contenttype; /* Content-Type */ +- struct curl_slist* contentheader; /* list of extra headers for this form */ +- struct curl_httppost *more; /* if one field name has more than one +- file, this link should link to following +- files */ +- long flags; /* as defined below */ +-#define HTTPPOST_FILENAME (1<<0) /* specified content is a file name */ +-#define HTTPPOST_READFILE (1<<1) /* specified content is a file name */ +-#define HTTPPOST_PTRNAME (1<<2) /* name is only stored pointer +- do not free in formfree */ +-#define HTTPPOST_PTRCONTENTS (1<<3) /* contents is only stored pointer +- do not free in formfree */ +-#define HTTPPOST_BUFFER (1<<4) /* upload file from buffer */ +-#define HTTPPOST_PTRBUFFER (1<<5) /* upload file from pointer contents */ +-#define HTTPPOST_CALLBACK (1<<6) /* upload file contents by using the +- regular read callback to get the data +- and pass the given pointer as custom +- pointer */ +- +- char *showfilename; /* The file name to show. If not set, the +- actual file name will be used (if this +- is a file part) */ +- void *userp; /* custom pointer used for +- HTTPPOST_CALLBACK posts */ +-}; +- +-typedef int (*curl_progress_callback)(void *clientp, +- double dltotal, +- double dlnow, +- double ultotal, +- double ulnow); +- +-#ifndef CURL_MAX_WRITE_SIZE +- /* Tests have proven that 20K is a very bad buffer size for uploads on +- Windows, while 16K for some odd reason performed a lot better. +- We do the ifndef check to allow this value to easier be changed at build +- time for those who feel adventurous. */ +-#define CURL_MAX_WRITE_SIZE 16384 +-#endif +- +-#ifndef CURL_MAX_HTTP_HEADER +-/* The only reason to have a max limit for this is to avoid the risk of a bad +- server feeding libcurl with a never-ending header that will cause reallocs +- infinitely */ +-#define CURL_MAX_HTTP_HEADER (100*1024) +-#endif +- +- +-/* This is a magic return code for the write callback that, when returned, +- will signal libcurl to pause receiving on the current transfer. */ +-#define CURL_WRITEFUNC_PAUSE 0x10000001 +-typedef size_t (*curl_write_callback)(char *buffer, +- size_t size, +- size_t nitems, +- void *outstream); +- +-/* These are the return codes for the seek callbacks */ +-#define CURL_SEEKFUNC_OK 0 +-#define CURL_SEEKFUNC_FAIL 1 /* fail the entire transfer */ +-#define CURL_SEEKFUNC_CANTSEEK 2 /* tell libcurl seeking can't be done, so +- libcurl might try other means instead */ +-typedef int (*curl_seek_callback)(void *instream, +- curl_off_t offset, +- int origin); /* 'whence' */ +- +-/* This is a return code for the read callback that, when returned, will +- signal libcurl to immediately abort the current transfer. */ +-#define CURL_READFUNC_ABORT 0x10000000 +-/* This is a return code for the read callback that, when returned, will +- signal libcurl to pause sending data on the current transfer. */ +-#define CURL_READFUNC_PAUSE 0x10000001 +- +-typedef size_t (*curl_read_callback)(char *buffer, +- size_t size, +- size_t nitems, +- void *instream); +- +-typedef enum { +- CURLSOCKTYPE_IPCXN, /* socket created for a specific IP connection */ +- CURLSOCKTYPE_LAST /* never use */ +-} curlsocktype; +- +-typedef int (*curl_sockopt_callback)(void *clientp, +- curl_socket_t curlfd, +- curlsocktype purpose); +- +-struct curl_sockaddr { +- int family; +- int socktype; +- int protocol; +- unsigned int addrlen; /* addrlen was a socklen_t type before 7.18.0 but it +- turned really ugly and painful on the systems that +- lack this type */ +- struct sockaddr addr; +-}; +- +-typedef curl_socket_t +-(*curl_opensocket_callback)(void *clientp, +- curlsocktype purpose, +- struct curl_sockaddr *address); +- +-#ifndef CURL_NO_OLDIES +- /* not used since 7.10.8, will be removed in a future release */ +-typedef int (*curl_passwd_callback)(void *clientp, +- const char *prompt, +- char *buffer, +- int buflen); +-#endif +- +-typedef enum { +- CURLIOE_OK, /* I/O operation successful */ +- CURLIOE_UNKNOWNCMD, /* command was unknown to callback */ +- CURLIOE_FAILRESTART, /* failed to restart the read */ +- CURLIOE_LAST /* never use */ +-} curlioerr; +- +-typedef enum { +- CURLIOCMD_NOP, /* no operation */ +- CURLIOCMD_RESTARTREAD, /* restart the read stream from start */ +- CURLIOCMD_LAST /* never use */ +-} curliocmd; +- +-typedef curlioerr (*curl_ioctl_callback)(CURL *handle, +- int cmd, +- void *clientp); +- +-/* +- * The following typedef's are signatures of malloc, free, realloc, strdup and +- * calloc respectively. Function pointers of these types can be passed to the +- * curl_global_init_mem() function to set user defined memory management +- * callback routines. +- */ +-typedef void *(*curl_malloc_callback)(size_t size); +-typedef void (*curl_free_callback)(void *ptr); +-typedef void *(*curl_realloc_callback)(void *ptr, size_t size); +-typedef char *(*curl_strdup_callback)(const char *str); +-typedef void *(*curl_calloc_callback)(size_t nmemb, size_t size); +- +-/* the kind of data that is passed to information_callback*/ +-typedef enum { +- CURLINFO_TEXT = 0, +- CURLINFO_HEADER_IN, /* 1 */ +- CURLINFO_HEADER_OUT, /* 2 */ +- CURLINFO_DATA_IN, /* 3 */ +- CURLINFO_DATA_OUT, /* 4 */ +- CURLINFO_SSL_DATA_IN, /* 5 */ +- CURLINFO_SSL_DATA_OUT, /* 6 */ +- CURLINFO_END +-} curl_infotype; +- +-typedef int (*curl_debug_callback) +- (CURL *handle, /* the handle/transfer this concerns */ +- curl_infotype type, /* what kind of data */ +- char *data, /* points to the data */ +- size_t size, /* size of the data pointed to */ +- void *userptr); /* whatever the user please */ +- +-/* All possible error codes from all sorts of curl functions. Future versions +- may return other values, stay prepared. +- +- Always add new return codes last. Never *EVER* remove any. The return +- codes must remain the same! +- */ +- +-typedef enum { +- CURLE_OK = 0, +- CURLE_UNSUPPORTED_PROTOCOL, /* 1 */ +- CURLE_FAILED_INIT, /* 2 */ +- CURLE_URL_MALFORMAT, /* 3 */ +- CURLE_OBSOLETE4, /* 4 - NOT USED */ +- CURLE_COULDNT_RESOLVE_PROXY, /* 5 */ +- CURLE_COULDNT_RESOLVE_HOST, /* 6 */ +- CURLE_COULDNT_CONNECT, /* 7 */ +- CURLE_FTP_WEIRD_SERVER_REPLY, /* 8 */ +- CURLE_REMOTE_ACCESS_DENIED, /* 9 a service was denied by the server +- due to lack of access - when login fails +- this is not returned. */ +- CURLE_OBSOLETE10, /* 10 - NOT USED */ +- CURLE_FTP_WEIRD_PASS_REPLY, /* 11 */ +- CURLE_OBSOLETE12, /* 12 - NOT USED */ +- CURLE_FTP_WEIRD_PASV_REPLY, /* 13 */ +- CURLE_FTP_WEIRD_227_FORMAT, /* 14 */ +- CURLE_FTP_CANT_GET_HOST, /* 15 */ +- CURLE_OBSOLETE16, /* 16 - NOT USED */ +- CURLE_FTP_COULDNT_SET_TYPE, /* 17 */ +- CURLE_PARTIAL_FILE, /* 18 */ +- CURLE_FTP_COULDNT_RETR_FILE, /* 19 */ +- CURLE_OBSOLETE20, /* 20 - NOT USED */ +- CURLE_QUOTE_ERROR, /* 21 - quote command failure */ +- CURLE_HTTP_RETURNED_ERROR, /* 22 */ +- CURLE_WRITE_ERROR, /* 23 */ +- CURLE_OBSOLETE24, /* 24 - NOT USED */ +- CURLE_UPLOAD_FAILED, /* 25 - failed upload "command" */ +- CURLE_READ_ERROR, /* 26 - couldn't open/read from file */ +- CURLE_OUT_OF_MEMORY, /* 27 */ +- /* Note: CURLE_OUT_OF_MEMORY may sometimes indicate a conversion error +- instead of a memory allocation error if CURL_DOES_CONVERSIONS +- is defined +- */ +- CURLE_OPERATION_TIMEDOUT, /* 28 - the timeout time was reached */ +- CURLE_OBSOLETE29, /* 29 - NOT USED */ +- CURLE_FTP_PORT_FAILED, /* 30 - FTP PORT operation failed */ +- CURLE_FTP_COULDNT_USE_REST, /* 31 - the REST command failed */ +- CURLE_OBSOLETE32, /* 32 - NOT USED */ +- CURLE_RANGE_ERROR, /* 33 - RANGE "command" didn't work */ +- CURLE_HTTP_POST_ERROR, /* 34 */ +- CURLE_SSL_CONNECT_ERROR, /* 35 - wrong when connecting with SSL */ +- CURLE_BAD_DOWNLOAD_RESUME, /* 36 - couldn't resume download */ +- CURLE_FILE_COULDNT_READ_FILE, /* 37 */ +- CURLE_LDAP_CANNOT_BIND, /* 38 */ +- CURLE_LDAP_SEARCH_FAILED, /* 39 */ +- CURLE_OBSOLETE40, /* 40 - NOT USED */ +- CURLE_FUNCTION_NOT_FOUND, /* 41 */ +- CURLE_ABORTED_BY_CALLBACK, /* 42 */ +- CURLE_BAD_FUNCTION_ARGUMENT, /* 43 */ +- CURLE_OBSOLETE44, /* 44 - NOT USED */ +- CURLE_INTERFACE_FAILED, /* 45 - CURLOPT_INTERFACE failed */ +- CURLE_OBSOLETE46, /* 46 - NOT USED */ +- CURLE_TOO_MANY_REDIRECTS , /* 47 - catch endless re-direct loops */ +- CURLE_UNKNOWN_TELNET_OPTION, /* 48 - User specified an unknown option */ +- CURLE_TELNET_OPTION_SYNTAX , /* 49 - Malformed telnet option */ +- CURLE_OBSOLETE50, /* 50 - NOT USED */ +- CURLE_PEER_FAILED_VERIFICATION, /* 51 - peer's certificate or fingerprint +- wasn't verified fine */ +- CURLE_GOT_NOTHING, /* 52 - when this is a specific error */ +- CURLE_SSL_ENGINE_NOTFOUND, /* 53 - SSL crypto engine not found */ +- CURLE_SSL_ENGINE_SETFAILED, /* 54 - can not set SSL crypto engine as +- default */ +- CURLE_SEND_ERROR, /* 55 - failed sending network data */ +- CURLE_RECV_ERROR, /* 56 - failure in receiving network data */ +- CURLE_OBSOLETE57, /* 57 - NOT IN USE */ +- CURLE_SSL_CERTPROBLEM, /* 58 - problem with the local certificate */ +- CURLE_SSL_CIPHER, /* 59 - couldn't use specified cipher */ +- CURLE_SSL_CACERT, /* 60 - problem with the CA cert (path?) */ +- CURLE_BAD_CONTENT_ENCODING, /* 61 - Unrecognized transfer encoding */ +- CURLE_LDAP_INVALID_URL, /* 62 - Invalid LDAP URL */ +- CURLE_FILESIZE_EXCEEDED, /* 63 - Maximum file size exceeded */ +- CURLE_USE_SSL_FAILED, /* 64 - Requested FTP SSL level failed */ +- CURLE_SEND_FAIL_REWIND, /* 65 - Sending the data requires a rewind +- that failed */ +- CURLE_SSL_ENGINE_INITFAILED, /* 66 - failed to initialise ENGINE */ +- CURLE_LOGIN_DENIED, /* 67 - user, password or similar was not +- accepted and we failed to login */ +- CURLE_TFTP_NOTFOUND, /* 68 - file not found on server */ +- CURLE_TFTP_PERM, /* 69 - permission problem on server */ +- CURLE_REMOTE_DISK_FULL, /* 70 - out of disk space on server */ +- CURLE_TFTP_ILLEGAL, /* 71 - Illegal TFTP operation */ +- CURLE_TFTP_UNKNOWNID, /* 72 - Unknown transfer ID */ +- CURLE_REMOTE_FILE_EXISTS, /* 73 - File already exists */ +- CURLE_TFTP_NOSUCHUSER, /* 74 - No such user */ +- CURLE_CONV_FAILED, /* 75 - conversion failed */ +- CURLE_CONV_REQD, /* 76 - caller must register conversion +- callbacks using curl_easy_setopt options +- CURLOPT_CONV_FROM_NETWORK_FUNCTION, +- CURLOPT_CONV_TO_NETWORK_FUNCTION, and +- CURLOPT_CONV_FROM_UTF8_FUNCTION */ +- CURLE_SSL_CACERT_BADFILE, /* 77 - could not load CACERT file, missing +- or wrong format */ +- CURLE_REMOTE_FILE_NOT_FOUND, /* 78 - remote file not found */ +- CURLE_SSH, /* 79 - error from the SSH layer, somewhat +- generic so the error message will be of +- interest when this has happened */ +- +- CURLE_SSL_SHUTDOWN_FAILED, /* 80 - Failed to shut down the SSL +- connection */ +- CURLE_AGAIN, /* 81 - socket is not ready for send/recv, +- wait till it's ready and try again (Added +- in 7.18.2) */ +- CURLE_SSL_CRL_BADFILE, /* 82 - could not load CRL file, missing or +- wrong format (Added in 7.19.0) */ +- CURLE_SSL_ISSUER_ERROR, /* 83 - Issuer check failed. (Added in +- 7.19.0) */ +- CURL_LAST /* never use! */ +-} CURLcode; +- +-#ifndef CURL_NO_OLDIES /* define this to test if your app builds with all +- the obsolete stuff removed! */ +- +-/* Backwards compatibility with older names */ +- +-/* The following were added in 7.17.1 */ +-/* These are scheduled to disappear by 2009 */ +-#define CURLE_SSL_PEER_CERTIFICATE CURLE_PEER_FAILED_VERIFICATION +- +-/* The following were added in 7.17.0 */ +-/* These are scheduled to disappear by 2009 */ +-#define CURLE_OBSOLETE CURLE_OBSOLETE50 /* noone should be using this! */ +-#define CURLE_BAD_PASSWORD_ENTERED CURLE_OBSOLETE46 +-#define CURLE_BAD_CALLING_ORDER CURLE_OBSOLETE44 +-#define CURLE_FTP_USER_PASSWORD_INCORRECT CURLE_OBSOLETE10 +-#define CURLE_FTP_CANT_RECONNECT CURLE_OBSOLETE16 +-#define CURLE_FTP_COULDNT_GET_SIZE CURLE_OBSOLETE32 +-#define CURLE_FTP_COULDNT_SET_ASCII CURLE_OBSOLETE29 +-#define CURLE_FTP_WEIRD_USER_REPLY CURLE_OBSOLETE12 +-#define CURLE_FTP_WRITE_ERROR CURLE_OBSOLETE20 +-#define CURLE_LIBRARY_NOT_FOUND CURLE_OBSOLETE40 +-#define CURLE_MALFORMAT_USER CURLE_OBSOLETE24 +-#define CURLE_SHARE_IN_USE CURLE_OBSOLETE57 +-#define CURLE_URL_MALFORMAT_USER CURLE_OBSOLETE4 +- +-#define CURLE_FTP_ACCESS_DENIED CURLE_REMOTE_ACCESS_DENIED +-#define CURLE_FTP_COULDNT_SET_BINARY CURLE_FTP_COULDNT_SET_TYPE +-#define CURLE_FTP_QUOTE_ERROR CURLE_QUOTE_ERROR +-#define CURLE_TFTP_DISKFULL CURLE_REMOTE_DISK_FULL +-#define CURLE_TFTP_EXISTS CURLE_REMOTE_FILE_EXISTS +-#define CURLE_HTTP_RANGE_ERROR CURLE_RANGE_ERROR +-#define CURLE_FTP_SSL_FAILED CURLE_USE_SSL_FAILED +- +-/* The following were added earlier */ +- +-#define CURLE_OPERATION_TIMEOUTED CURLE_OPERATION_TIMEDOUT +- +-#define CURLE_HTTP_NOT_FOUND CURLE_HTTP_RETURNED_ERROR +-#define CURLE_HTTP_PORT_FAILED CURLE_INTERFACE_FAILED +-#define CURLE_FTP_COULDNT_STOR_FILE CURLE_UPLOAD_FAILED +- +-#define CURLE_FTP_PARTIAL_FILE CURLE_PARTIAL_FILE +-#define CURLE_FTP_BAD_DOWNLOAD_RESUME CURLE_BAD_DOWNLOAD_RESUME +- +-/* This was the error code 50 in 7.7.3 and a few earlier versions, this +- is no longer used by libcurl but is instead #defined here only to not +- make programs break */ +-#define CURLE_ALREADY_COMPLETE 99999 +- +-#endif /*!CURL_NO_OLDIES*/ +- +-/* This prototype applies to all conversion callbacks */ +-typedef CURLcode (*curl_conv_callback)(char *buffer, size_t length); +- +-typedef CURLcode (*curl_ssl_ctx_callback)(CURL *curl, /* easy handle */ +- void *ssl_ctx, /* actually an +- OpenSSL SSL_CTX */ +- void *userptr); +- +-typedef enum { +- CURLPROXY_HTTP = 0, /* added in 7.10, new in 7.19.4 default is to use +- CONNECT HTTP/1.1 */ +- CURLPROXY_HTTP_1_0 = 1, /* added in 7.19.4, force to use CONNECT +- HTTP/1.0 */ +- CURLPROXY_SOCKS4 = 4, /* support added in 7.15.2, enum existed already +- in 7.10 */ +- CURLPROXY_SOCKS5 = 5, /* added in 7.10 */ +- CURLPROXY_SOCKS4A = 6, /* added in 7.18.0 */ +- CURLPROXY_SOCKS5_HOSTNAME = 7 /* Use the SOCKS5 protocol but pass along the +- host name rather than the IP address. added +- in 7.18.0 */ +-} curl_proxytype; /* this enum was added in 7.10 */ +- +-#define CURLAUTH_NONE 0 /* nothing */ +-#define CURLAUTH_BASIC (1<<0) /* Basic (default) */ +-#define CURLAUTH_DIGEST (1<<1) /* Digest */ +-#define CURLAUTH_GSSNEGOTIATE (1<<2) /* GSS-Negotiate */ +-#define CURLAUTH_NTLM (1<<3) /* NTLM */ +-#define CURLAUTH_DIGEST_IE (1<<4) /* Digest with IE flavour */ +-#define CURLAUTH_ANY (~CURLAUTH_DIGEST_IE) /* all fine types set */ +-#define CURLAUTH_ANYSAFE (~(CURLAUTH_BASIC|CURLAUTH_DIGEST_IE)) +- +-#define CURLSSH_AUTH_ANY ~0 /* all types supported by the server */ +-#define CURLSSH_AUTH_NONE 0 /* none allowed, silly but complete */ +-#define CURLSSH_AUTH_PUBLICKEY (1<<0) /* public/private key files */ +-#define CURLSSH_AUTH_PASSWORD (1<<1) /* password */ +-#define CURLSSH_AUTH_HOST (1<<2) /* host key files */ +-#define CURLSSH_AUTH_KEYBOARD (1<<3) /* keyboard interactive */ +-#define CURLSSH_AUTH_DEFAULT CURLSSH_AUTH_ANY +- +-#define CURL_ERROR_SIZE 256 +- +-struct curl_khkey { +- const char *key; /* points to a zero-terminated string encoded with base64 +- if len is zero, otherwise to the "raw" data */ +- size_t len; +- enum type { +- CURLKHTYPE_UNKNOWN, +- CURLKHTYPE_RSA1, +- CURLKHTYPE_RSA, +- CURLKHTYPE_DSS +- } keytype; +-}; +- +-/* this is the set of return values expected from the curl_sshkeycallback +- callback */ +-enum curl_khstat { +- CURLKHSTAT_FINE_ADD_TO_FILE, +- CURLKHSTAT_FINE, +- CURLKHSTAT_REJECT, /* reject the connection, return an error */ +- CURLKHSTAT_DEFER, /* do not accept it, but we can't answer right now so +- this causes a CURLE_DEFER error but otherwise the +- connection will be left intact etc */ +- CURLKHSTAT_LAST /* not for use, only a marker for last-in-list */ +-}; +- +-/* this is the set of status codes pass in to the callback */ +-enum curl_khmatch { +- CURLKHMATCH_OK, /* match */ +- CURLKHMATCH_MISMATCH, /* host found, key mismatch! */ +- CURLKHMATCH_MISSING, /* no matching host/key found */ +- CURLKHMATCH_LAST /* not for use, only a marker for last-in-list */ +-}; +- +-typedef int +- (*curl_sshkeycallback) (CURL *easy, /* easy handle */ +- const struct curl_khkey *knownkey, /* known */ +- const struct curl_khkey *foundkey, /* found */ +- enum curl_khmatch, /* libcurl's view on the keys */ +- void *clientp); /* custom pointer passed from app */ +- +-/* parameter for the CURLOPT_USE_SSL option */ +-typedef enum { +- CURLUSESSL_NONE, /* do not attempt to use SSL */ +- CURLUSESSL_TRY, /* try using SSL, proceed anyway otherwise */ +- CURLUSESSL_CONTROL, /* SSL for the control connection or fail */ +- CURLUSESSL_ALL, /* SSL for all communication or fail */ +- CURLUSESSL_LAST /* not an option, never use */ +-} curl_usessl; +- +-#ifndef CURL_NO_OLDIES /* define this to test if your app builds with all +- the obsolete stuff removed! */ +- +-/* Backwards compatibility with older names */ +-/* These are scheduled to disappear by 2009 */ +- +-#define CURLFTPSSL_NONE CURLUSESSL_NONE +-#define CURLFTPSSL_TRY CURLUSESSL_TRY +-#define CURLFTPSSL_CONTROL CURLUSESSL_CONTROL +-#define CURLFTPSSL_ALL CURLUSESSL_ALL +-#define CURLFTPSSL_LAST CURLUSESSL_LAST +-#define curl_ftpssl curl_usessl +-#endif /*!CURL_NO_OLDIES*/ +- +-/* parameter for the CURLOPT_FTP_SSL_CCC option */ +-typedef enum { +- CURLFTPSSL_CCC_NONE, /* do not send CCC */ +- CURLFTPSSL_CCC_PASSIVE, /* Let the server initiate the shutdown */ +- CURLFTPSSL_CCC_ACTIVE, /* Initiate the shutdown */ +- CURLFTPSSL_CCC_LAST /* not an option, never use */ +-} curl_ftpccc; +- +-/* parameter for the CURLOPT_FTPSSLAUTH option */ +-typedef enum { +- CURLFTPAUTH_DEFAULT, /* let libcurl decide */ +- CURLFTPAUTH_SSL, /* use "AUTH SSL" */ +- CURLFTPAUTH_TLS, /* use "AUTH TLS" */ +- CURLFTPAUTH_LAST /* not an option, never use */ +-} curl_ftpauth; +- +-/* parameter for the CURLOPT_FTP_CREATE_MISSING_DIRS option */ +-typedef enum { +- CURLFTP_CREATE_DIR_NONE, /* do NOT create missing dirs! */ +- CURLFTP_CREATE_DIR, /* (FTP/SFTP) if CWD fails, try MKD and then CWD +- again if MKD succeeded, for SFTP this does +- similar magic */ +- CURLFTP_CREATE_DIR_RETRY, /* (FTP only) if CWD fails, try MKD and then CWD +- again even if MKD failed! */ +- CURLFTP_CREATE_DIR_LAST /* not an option, never use */ +-} curl_ftpcreatedir; +- +-/* parameter for the CURLOPT_FTP_FILEMETHOD option */ +-typedef enum { +- CURLFTPMETHOD_DEFAULT, /* let libcurl pick */ +- CURLFTPMETHOD_MULTICWD, /* single CWD operation for each path part */ +- CURLFTPMETHOD_NOCWD, /* no CWD at all */ +- CURLFTPMETHOD_SINGLECWD, /* one CWD to full dir, then work on file */ +- CURLFTPMETHOD_LAST /* not an option, never use */ +-} curl_ftpmethod; +- +-/* CURLPROTO_ defines are for the CURLOPT_*PROTOCOLS options */ +-#define CURLPROTO_HTTP (1<<0) +-#define CURLPROTO_HTTPS (1<<1) +-#define CURLPROTO_FTP (1<<2) +-#define CURLPROTO_FTPS (1<<3) +-#define CURLPROTO_SCP (1<<4) +-#define CURLPROTO_SFTP (1<<5) +-#define CURLPROTO_TELNET (1<<6) +-#define CURLPROTO_LDAP (1<<7) +-#define CURLPROTO_LDAPS (1<<8) +-#define CURLPROTO_DICT (1<<9) +-#define CURLPROTO_FILE (1<<10) +-#define CURLPROTO_TFTP (1<<11) +-#define CURLPROTO_ALL (~0) /* enable everything */ +- +-/* long may be 32 or 64 bits, but we should never depend on anything else +- but 32 */ +-#define CURLOPTTYPE_LONG 0 +-#define CURLOPTTYPE_OBJECTPOINT 10000 +-#define CURLOPTTYPE_FUNCTIONPOINT 20000 +-#define CURLOPTTYPE_OFF_T 30000 +- +-/* name is uppercase CURLOPT_, +- type is one of the defined CURLOPTTYPE_ +- number is unique identifier */ +-#ifdef CINIT +-#undef CINIT +-#endif +- +-#ifdef CURL_ISOCPP +-#define CINIT(name,type,number) CURLOPT_ ## name = CURLOPTTYPE_ ## type + number +-#else +-/* The macro "##" is ISO C, we assume pre-ISO C doesn't support it. */ +-#define LONG CURLOPTTYPE_LONG +-#define OBJECTPOINT CURLOPTTYPE_OBJECTPOINT +-#define FUNCTIONPOINT CURLOPTTYPE_FUNCTIONPOINT +-#define OFF_T CURLOPTTYPE_OFF_T +-#define CINIT(name,type,number) CURLOPT_/**/name = type + number +-#endif +- +-/* +- * This macro-mania below setups the CURLOPT_[what] enum, to be used with +- * curl_easy_setopt(). The first argument in the CINIT() macro is the [what] +- * word. +- */ +- +-typedef enum { +- /* This is the FILE * or void * the regular output should be written to. */ +- CINIT(FILE, OBJECTPOINT, 1), +- +- /* The full URL to get/put */ +- CINIT(URL, OBJECTPOINT, 2), +- +- /* Port number to connect to, if other than default. */ +- CINIT(PORT, LONG, 3), +- +- /* Name of proxy to use. */ +- CINIT(PROXY, OBJECTPOINT, 4), +- +- /* "name:password" to use when fetching. */ +- CINIT(USERPWD, OBJECTPOINT, 5), +- +- /* "name:password" to use with proxy. */ +- CINIT(PROXYUSERPWD, OBJECTPOINT, 6), +- +- /* Range to get, specified as an ASCII string. */ +- CINIT(RANGE, OBJECTPOINT, 7), +- +- /* not used */ +- +- /* Specified file stream to upload from (use as input): */ +- CINIT(INFILE, OBJECTPOINT, 9), +- +- /* Buffer to receive error messages in, must be at least CURL_ERROR_SIZE +- * bytes big. If this is not used, error messages go to stderr instead: */ +- CINIT(ERRORBUFFER, OBJECTPOINT, 10), +- +- /* Function that will be called to store the output (instead of fwrite). The +- * parameters will use fwrite() syntax, make sure to follow them. */ +- CINIT(WRITEFUNCTION, FUNCTIONPOINT, 11), +- +- /* Function that will be called to read the input (instead of fread). The +- * parameters will use fread() syntax, make sure to follow them. */ +- CINIT(READFUNCTION, FUNCTIONPOINT, 12), +- +- /* Time-out the read operation after this amount of seconds */ +- CINIT(TIMEOUT, LONG, 13), +- +- /* If the CURLOPT_INFILE is used, this can be used to inform libcurl about +- * how large the file being sent really is. That allows better error +- * checking and better verifies that the upload was successful. -1 means +- * unknown size. +- * +- * For large file support, there is also a _LARGE version of the key +- * which takes an off_t type, allowing platforms with larger off_t +- * sizes to handle larger files. See below for INFILESIZE_LARGE. +- */ +- CINIT(INFILESIZE, LONG, 14), +- +- /* POST static input fields. */ +- CINIT(POSTFIELDS, OBJECTPOINT, 15), +- +- /* Set the referrer page (needed by some CGIs) */ +- CINIT(REFERER, OBJECTPOINT, 16), +- +- /* Set the FTP PORT string (interface name, named or numerical IP address) +- Use i.e '-' to use default address. */ +- CINIT(FTPPORT, OBJECTPOINT, 17), +- +- /* Set the User-Agent string (examined by some CGIs) */ +- CINIT(USERAGENT, OBJECTPOINT, 18), +- +- /* If the download receives less than "low speed limit" bytes/second +- * during "low speed time" seconds, the operations is aborted. +- * You could i.e if you have a pretty high speed connection, abort if +- * it is less than 2000 bytes/sec during 20 seconds. +- */ +- +- /* Set the "low speed limit" */ +- CINIT(LOW_SPEED_LIMIT, LONG, 19), +- +- /* Set the "low speed time" */ +- CINIT(LOW_SPEED_TIME, LONG, 20), +- +- /* Set the continuation offset. +- * +- * Note there is also a _LARGE version of this key which uses +- * off_t types, allowing for large file offsets on platforms which +- * use larger-than-32-bit off_t's. Look below for RESUME_FROM_LARGE. +- */ +- CINIT(RESUME_FROM, LONG, 21), +- +- /* Set cookie in request: */ +- CINIT(COOKIE, OBJECTPOINT, 22), +- +- /* This points to a linked list of headers, struct curl_slist kind */ +- CINIT(HTTPHEADER, OBJECTPOINT, 23), +- +- /* This points to a linked list of post entries, struct curl_httppost */ +- CINIT(HTTPPOST, OBJECTPOINT, 24), +- +- /* name of the file keeping your private SSL-certificate */ +- CINIT(SSLCERT, OBJECTPOINT, 25), +- +- /* password for the SSL or SSH private key */ +- CINIT(KEYPASSWD, OBJECTPOINT, 26), +- +- /* send TYPE parameter? */ +- CINIT(CRLF, LONG, 27), +- +- /* send linked-list of QUOTE commands */ +- CINIT(QUOTE, OBJECTPOINT, 28), +- +- /* send FILE * or void * to store headers to, if you use a callback it +- is simply passed to the callback unmodified */ +- CINIT(WRITEHEADER, OBJECTPOINT, 29), +- +- /* point to a file to read the initial cookies from, also enables +- "cookie awareness" */ +- CINIT(COOKIEFILE, OBJECTPOINT, 31), +- +- /* What version to specifically try to use. +- See CURL_SSLVERSION defines below. */ +- CINIT(SSLVERSION, LONG, 32), +- +- /* What kind of HTTP time condition to use, see defines */ +- CINIT(TIMECONDITION, LONG, 33), +- +- /* Time to use with the above condition. Specified in number of seconds +- since 1 Jan 1970 */ +- CINIT(TIMEVALUE, LONG, 34), +- +- /* 35 = OBSOLETE */ +- +- /* Custom request, for customizing the get command like +- HTTP: DELETE, TRACE and others +- FTP: to use a different list command +- */ +- CINIT(CUSTOMREQUEST, OBJECTPOINT, 36), +- +- /* HTTP request, for odd commands like DELETE, TRACE and others */ +- CINIT(STDERR, OBJECTPOINT, 37), +- +- /* 38 is not used */ +- +- /* send linked-list of post-transfer QUOTE commands */ +- CINIT(POSTQUOTE, OBJECTPOINT, 39), +- +- /* Pass a pointer to string of the output using full variable-replacement +- as described elsewhere. */ +- CINIT(WRITEINFO, OBJECTPOINT, 40), +- +- CINIT(VERBOSE, LONG, 41), /* talk a lot */ +- CINIT(HEADER, LONG, 42), /* throw the header out too */ +- CINIT(NOPROGRESS, LONG, 43), /* shut off the progress meter */ +- CINIT(NOBODY, LONG, 44), /* use HEAD to get http document */ +- CINIT(FAILONERROR, LONG, 45), /* no output on http error codes >= 300 */ +- CINIT(UPLOAD, LONG, 46), /* this is an upload */ +- CINIT(POST, LONG, 47), /* HTTP POST method */ +- CINIT(DIRLISTONLY, LONG, 48), /* return bare names when listing directories */ +- +- CINIT(APPEND, LONG, 50), /* Append instead of overwrite on upload! */ +- +- /* Specify whether to read the user+password from the .netrc or the URL. +- * This must be one of the CURL_NETRC_* enums below. */ +- CINIT(NETRC, LONG, 51), +- +- CINIT(FOLLOWLOCATION, LONG, 52), /* use Location: Luke! */ +- +- CINIT(TRANSFERTEXT, LONG, 53), /* transfer data in text/ASCII format */ +- CINIT(PUT, LONG, 54), /* HTTP PUT */ +- +- /* 55 = OBSOLETE */ +- +- /* Function that will be called instead of the internal progress display +- * function. This function should be defined as the curl_progress_callback +- * prototype defines. */ +- CINIT(PROGRESSFUNCTION, FUNCTIONPOINT, 56), +- +- /* Data passed to the progress callback */ +- CINIT(PROGRESSDATA, OBJECTPOINT, 57), +- +- /* We want the referrer field set automatically when following locations */ +- CINIT(AUTOREFERER, LONG, 58), +- +- /* Port of the proxy, can be set in the proxy string as well with: +- "[host]:[port]" */ +- CINIT(PROXYPORT, LONG, 59), +- +- /* size of the POST input data, if strlen() is not good to use */ +- CINIT(POSTFIELDSIZE, LONG, 60), +- +- /* tunnel non-http operations through a HTTP proxy */ +- CINIT(HTTPPROXYTUNNEL, LONG, 61), +- +- /* Set the interface string to use as outgoing network interface */ +- CINIT(INTERFACE, OBJECTPOINT, 62), +- +- /* Set the krb4/5 security level, this also enables krb4/5 awareness. This +- * is a string, 'clear', 'safe', 'confidential' or 'private'. If the string +- * is set but doesn't match one of these, 'private' will be used. */ +- CINIT(KRBLEVEL, OBJECTPOINT, 63), +- +- /* Set if we should verify the peer in ssl handshake, set 1 to verify. */ +- CINIT(SSL_VERIFYPEER, LONG, 64), +- +- /* The CApath or CAfile used to validate the peer certificate +- this option is used only if SSL_VERIFYPEER is true */ +- CINIT(CAINFO, OBJECTPOINT, 65), +- +- /* 66 = OBSOLETE */ +- /* 67 = OBSOLETE */ +- +- /* Maximum number of http redirects to follow */ +- CINIT(MAXREDIRS, LONG, 68), +- +- /* Pass a long set to 1 to get the date of the requested document (if +- possible)! Pass a zero to shut it off. */ +- CINIT(FILETIME, LONG, 69), +- +- /* This points to a linked list of telnet options */ +- CINIT(TELNETOPTIONS, OBJECTPOINT, 70), +- +- /* Max amount of cached alive connections */ +- CINIT(MAXCONNECTS, LONG, 71), +- +- /* What policy to use when closing connections when the cache is filled +- up */ +- CINIT(CLOSEPOLICY, LONG, 72), +- +- /* 73 = OBSOLETE */ +- +- /* Set to explicitly use a new connection for the upcoming transfer. +- Do not use this unless you're absolutely sure of this, as it makes the +- operation slower and is less friendly for the network. */ +- CINIT(FRESH_CONNECT, LONG, 74), +- +- /* Set to explicitly forbid the upcoming transfer's connection to be re-used +- when done. Do not use this unless you're absolutely sure of this, as it +- makes the operation slower and is less friendly for the network. */ +- CINIT(FORBID_REUSE, LONG, 75), +- +- /* Set to a file name that contains random data for libcurl to use to +- seed the random engine when doing SSL connects. */ +- CINIT(RANDOM_FILE, OBJECTPOINT, 76), +- +- /* Set to the Entropy Gathering Daemon socket pathname */ +- CINIT(EGDSOCKET, OBJECTPOINT, 77), +- +- /* Time-out connect operations after this amount of seconds, if connects +- are OK within this time, then fine... This only aborts the connect +- phase. [Only works on unix-style/SIGALRM operating systems] */ +- CINIT(CONNECTTIMEOUT, LONG, 78), +- +- /* Function that will be called to store headers (instead of fwrite). The +- * parameters will use fwrite() syntax, make sure to follow them. */ +- CINIT(HEADERFUNCTION, FUNCTIONPOINT, 79), +- +- /* Set this to force the HTTP request to get back to GET. Only really usable +- if POST, PUT or a custom request have been used first. +- */ +- CINIT(HTTPGET, LONG, 80), +- +- /* Set if we should verify the Common name from the peer certificate in ssl +- * handshake, set 1 to check existence, 2 to ensure that it matches the +- * provided hostname. */ +- CINIT(SSL_VERIFYHOST, LONG, 81), +- +- /* Specify which file name to write all known cookies in after completed +- operation. Set file name to "-" (dash) to make it go to stdout. */ +- CINIT(COOKIEJAR, OBJECTPOINT, 82), +- +- /* Specify which SSL ciphers to use */ +- CINIT(SSL_CIPHER_LIST, OBJECTPOINT, 83), +- +- /* Specify which HTTP version to use! This must be set to one of the +- CURL_HTTP_VERSION* enums set below. */ +- CINIT(HTTP_VERSION, LONG, 84), +- +- /* Specifically switch on or off the FTP engine's use of the EPSV command. By +- default, that one will always be attempted before the more traditional +- PASV command. */ +- CINIT(FTP_USE_EPSV, LONG, 85), +- +- /* type of the file keeping your SSL-certificate ("DER", "PEM", "ENG") */ +- CINIT(SSLCERTTYPE, OBJECTPOINT, 86), +- +- /* name of the file keeping your private SSL-key */ +- CINIT(SSLKEY, OBJECTPOINT, 87), +- +- /* type of the file keeping your private SSL-key ("DER", "PEM", "ENG") */ +- CINIT(SSLKEYTYPE, OBJECTPOINT, 88), +- +- /* crypto engine for the SSL-sub system */ +- CINIT(SSLENGINE, OBJECTPOINT, 89), +- +- /* set the crypto engine for the SSL-sub system as default +- the param has no meaning... +- */ +- CINIT(SSLENGINE_DEFAULT, LONG, 90), +- +- /* Non-zero value means to use the global dns cache */ +- CINIT(DNS_USE_GLOBAL_CACHE, LONG, 91), /* To become OBSOLETE soon */ +- +- /* DNS cache timeout */ +- CINIT(DNS_CACHE_TIMEOUT, LONG, 92), +- +- /* send linked-list of pre-transfer QUOTE commands */ +- CINIT(PREQUOTE, OBJECTPOINT, 93), +- +- /* set the debug function */ +- CINIT(DEBUGFUNCTION, FUNCTIONPOINT, 94), +- +- /* set the data for the debug function */ +- CINIT(DEBUGDATA, OBJECTPOINT, 95), +- +- /* mark this as start of a cookie session */ +- CINIT(COOKIESESSION, LONG, 96), +- +- /* The CApath directory used to validate the peer certificate +- this option is used only if SSL_VERIFYPEER is true */ +- CINIT(CAPATH, OBJECTPOINT, 97), +- +- /* Instruct libcurl to use a smaller receive buffer */ +- CINIT(BUFFERSIZE, LONG, 98), +- +- /* Instruct libcurl to not use any signal/alarm handlers, even when using +- timeouts. This option is useful for multi-threaded applications. +- See libcurl-the-guide for more background information. */ +- CINIT(NOSIGNAL, LONG, 99), +- +- /* Provide a CURLShare for mutexing non-ts data */ +- CINIT(SHARE, OBJECTPOINT, 100), +- +- /* indicates type of proxy. accepted values are CURLPROXY_HTTP (default), +- CURLPROXY_SOCKS4, CURLPROXY_SOCKS4A and CURLPROXY_SOCKS5. */ +- CINIT(PROXYTYPE, LONG, 101), +- +- /* Set the Accept-Encoding string. Use this to tell a server you would like +- the response to be compressed. */ +- CINIT(ENCODING, OBJECTPOINT, 102), +- +- /* Set pointer to private data */ +- CINIT(PRIVATE, OBJECTPOINT, 103), +- +- /* Set aliases for HTTP 200 in the HTTP Response header */ +- CINIT(HTTP200ALIASES, OBJECTPOINT, 104), +- +- /* Continue to send authentication (user+password) when following locations, +- even when hostname changed. This can potentially send off the name +- and password to whatever host the server decides. */ +- CINIT(UNRESTRICTED_AUTH, LONG, 105), +- +- /* Specifically switch on or off the FTP engine's use of the EPRT command ( it +- also disables the LPRT attempt). By default, those ones will always be +- attempted before the good old traditional PORT command. */ +- CINIT(FTP_USE_EPRT, LONG, 106), +- +- /* Set this to a bitmask value to enable the particular authentications +- methods you like. Use this in combination with CURLOPT_USERPWD. +- Note that setting multiple bits may cause extra network round-trips. */ +- CINIT(HTTPAUTH, LONG, 107), +- +- /* Set the ssl context callback function, currently only for OpenSSL ssl_ctx +- in second argument. The function must be matching the +- curl_ssl_ctx_callback proto. */ +- CINIT(SSL_CTX_FUNCTION, FUNCTIONPOINT, 108), +- +- /* Set the userdata for the ssl context callback function's third +- argument */ +- CINIT(SSL_CTX_DATA, OBJECTPOINT, 109), +- +- /* FTP Option that causes missing dirs to be created on the remote server. +- In 7.19.4 we introduced the convenience enums for this option using the +- CURLFTP_CREATE_DIR prefix. +- */ +- CINIT(FTP_CREATE_MISSING_DIRS, LONG, 110), +- +- /* Set this to a bitmask value to enable the particular authentications +- methods you like. Use this in combination with CURLOPT_PROXYUSERPWD. +- Note that setting multiple bits may cause extra network round-trips. */ +- CINIT(PROXYAUTH, LONG, 111), +- +- /* FTP option that changes the timeout, in seconds, associated with +- getting a response. This is different from transfer timeout time and +- essentially places a demand on the FTP server to acknowledge commands +- in a timely manner. */ +- CINIT(FTP_RESPONSE_TIMEOUT, LONG, 112), +- +- /* Set this option to one of the CURL_IPRESOLVE_* defines (see below) to +- tell libcurl to resolve names to those IP versions only. This only has +- affect on systems with support for more than one, i.e IPv4 _and_ IPv6. */ +- CINIT(IPRESOLVE, LONG, 113), +- +- /* Set this option to limit the size of a file that will be downloaded from +- an HTTP or FTP server. +- +- Note there is also _LARGE version which adds large file support for +- platforms which have larger off_t sizes. See MAXFILESIZE_LARGE below. */ +- CINIT(MAXFILESIZE, LONG, 114), +- +- /* See the comment for INFILESIZE above, but in short, specifies +- * the size of the file being uploaded. -1 means unknown. +- */ +- CINIT(INFILESIZE_LARGE, OFF_T, 115), +- +- /* Sets the continuation offset. There is also a LONG version of this; +- * look above for RESUME_FROM. +- */ +- CINIT(RESUME_FROM_LARGE, OFF_T, 116), +- +- /* Sets the maximum size of data that will be downloaded from +- * an HTTP or FTP server. See MAXFILESIZE above for the LONG version. +- */ +- CINIT(MAXFILESIZE_LARGE, OFF_T, 117), +- +- /* Set this option to the file name of your .netrc file you want libcurl +- to parse (using the CURLOPT_NETRC option). If not set, libcurl will do +- a poor attempt to find the user's home directory and check for a .netrc +- file in there. */ +- CINIT(NETRC_FILE, OBJECTPOINT, 118), +- +- /* Enable SSL/TLS for FTP, pick one of: +- CURLFTPSSL_TRY - try using SSL, proceed anyway otherwise +- CURLFTPSSL_CONTROL - SSL for the control connection or fail +- CURLFTPSSL_ALL - SSL for all communication or fail +- */ +- CINIT(USE_SSL, LONG, 119), +- +- /* The _LARGE version of the standard POSTFIELDSIZE option */ +- CINIT(POSTFIELDSIZE_LARGE, OFF_T, 120), +- +- /* Enable/disable the TCP Nagle algorithm */ +- CINIT(TCP_NODELAY, LONG, 121), +- +- /* 122 OBSOLETE, used in 7.12.3. Gone in 7.13.0 */ +- /* 123 OBSOLETE. Gone in 7.16.0 */ +- /* 124 OBSOLETE, used in 7.12.3. Gone in 7.13.0 */ +- /* 125 OBSOLETE, used in 7.12.3. Gone in 7.13.0 */ +- /* 126 OBSOLETE, used in 7.12.3. Gone in 7.13.0 */ +- /* 127 OBSOLETE. Gone in 7.16.0 */ +- /* 128 OBSOLETE. Gone in 7.16.0 */ +- +- /* When FTP over SSL/TLS is selected (with CURLOPT_USE_SSL), this option +- can be used to change libcurl's default action which is to first try +- "AUTH SSL" and then "AUTH TLS" in this order, and proceed when a OK +- response has been received. +- +- Available parameters are: +- CURLFTPAUTH_DEFAULT - let libcurl decide +- CURLFTPAUTH_SSL - try "AUTH SSL" first, then TLS +- CURLFTPAUTH_TLS - try "AUTH TLS" first, then SSL +- */ +- CINIT(FTPSSLAUTH, LONG, 129), +- +- CINIT(IOCTLFUNCTION, FUNCTIONPOINT, 130), +- CINIT(IOCTLDATA, OBJECTPOINT, 131), +- +- /* 132 OBSOLETE. Gone in 7.16.0 */ +- /* 133 OBSOLETE. Gone in 7.16.0 */ +- +- /* zero terminated string for pass on to the FTP server when asked for +- "account" info */ +- CINIT(FTP_ACCOUNT, OBJECTPOINT, 134), +- +- /* feed cookies into cookie engine */ +- CINIT(COOKIELIST, OBJECTPOINT, 135), +- +- /* ignore Content-Length */ +- CINIT(IGNORE_CONTENT_LENGTH, LONG, 136), +- +- /* Set to non-zero to skip the IP address received in a 227 PASV FTP server +- response. Typically used for FTP-SSL purposes but is not restricted to +- that. libcurl will then instead use the same IP address it used for the +- control connection. */ +- CINIT(FTP_SKIP_PASV_IP, LONG, 137), +- +- /* Select "file method" to use when doing FTP, see the curl_ftpmethod +- above. */ +- CINIT(FTP_FILEMETHOD, LONG, 138), +- +- /* Local port number to bind the socket to */ +- CINIT(LOCALPORT, LONG, 139), +- +- /* Number of ports to try, including the first one set with LOCALPORT. +- Thus, setting it to 1 will make no additional attempts but the first. +- */ +- CINIT(LOCALPORTRANGE, LONG, 140), +- +- /* no transfer, set up connection and let application use the socket by +- extracting it with CURLINFO_LASTSOCKET */ +- CINIT(CONNECT_ONLY, LONG, 141), +- +- /* Function that will be called to convert from the +- network encoding (instead of using the iconv calls in libcurl) */ +- CINIT(CONV_FROM_NETWORK_FUNCTION, FUNCTIONPOINT, 142), +- +- /* Function that will be called to convert to the +- network encoding (instead of using the iconv calls in libcurl) */ +- CINIT(CONV_TO_NETWORK_FUNCTION, FUNCTIONPOINT, 143), +- +- /* Function that will be called to convert from UTF8 +- (instead of using the iconv calls in libcurl) +- Note that this is used only for SSL certificate processing */ +- CINIT(CONV_FROM_UTF8_FUNCTION, FUNCTIONPOINT, 144), +- +- /* if the connection proceeds too quickly then need to slow it down */ +- /* limit-rate: maximum number of bytes per second to send or receive */ +- CINIT(MAX_SEND_SPEED_LARGE, OFF_T, 145), +- CINIT(MAX_RECV_SPEED_LARGE, OFF_T, 146), +- +- /* Pointer to command string to send if USER/PASS fails. */ +- CINIT(FTP_ALTERNATIVE_TO_USER, OBJECTPOINT, 147), +- +- /* callback function for setting socket options */ +- CINIT(SOCKOPTFUNCTION, FUNCTIONPOINT, 148), +- CINIT(SOCKOPTDATA, OBJECTPOINT, 149), +- +- /* set to 0 to disable session ID re-use for this transfer, default is +- enabled (== 1) */ +- CINIT(SSL_SESSIONID_CACHE, LONG, 150), +- +- /* allowed SSH authentication methods */ +- CINIT(SSH_AUTH_TYPES, LONG, 151), +- +- /* Used by scp/sftp to do public/private key authentication */ +- CINIT(SSH_PUBLIC_KEYFILE, OBJECTPOINT, 152), +- CINIT(SSH_PRIVATE_KEYFILE, OBJECTPOINT, 153), +- +- /* Send CCC (Clear Command Channel) after authentication */ +- CINIT(FTP_SSL_CCC, LONG, 154), +- +- /* Same as TIMEOUT and CONNECTTIMEOUT, but with ms resolution */ +- CINIT(TIMEOUT_MS, LONG, 155), +- CINIT(CONNECTTIMEOUT_MS, LONG, 156), +- +- /* set to zero to disable the libcurl's decoding and thus pass the raw body +- data to the application even when it is encoded/compressed */ +- CINIT(HTTP_TRANSFER_DECODING, LONG, 157), +- CINIT(HTTP_CONTENT_DECODING, LONG, 158), +- +- /* Permission used when creating new files and directories on the remote +- server for protocols that support it, SFTP/SCP/FILE */ +- CINIT(NEW_FILE_PERMS, LONG, 159), +- CINIT(NEW_DIRECTORY_PERMS, LONG, 160), +- +- /* Set the behaviour of POST when redirecting. Values must be set to one +- of CURL_REDIR* defines below. This used to be called CURLOPT_POST301 */ +- CINIT(POSTREDIR, LONG, 161), +- +- /* used by scp/sftp to verify the host's public key */ +- CINIT(SSH_HOST_PUBLIC_KEY_MD5, OBJECTPOINT, 162), +- +- /* Callback function for opening socket (instead of socket(2)). Optionally, +- callback is able change the address or refuse to connect returning +- CURL_SOCKET_BAD. The callback should have type +- curl_opensocket_callback */ +- CINIT(OPENSOCKETFUNCTION, FUNCTIONPOINT, 163), +- CINIT(OPENSOCKETDATA, OBJECTPOINT, 164), +- +- /* POST volatile input fields. */ +- CINIT(COPYPOSTFIELDS, OBJECTPOINT, 165), +- +- /* set transfer mode (;type=) when doing FTP via an HTTP proxy */ +- CINIT(PROXY_TRANSFER_MODE, LONG, 166), +- +- /* Callback function for seeking in the input stream */ +- CINIT(SEEKFUNCTION, FUNCTIONPOINT, 167), +- CINIT(SEEKDATA, OBJECTPOINT, 168), +- +- /* CRL file */ +- CINIT(CRLFILE, OBJECTPOINT, 169), +- +- /* Issuer certificate */ +- CINIT(ISSUERCERT, OBJECTPOINT, 170), +- +- /* (IPv6) Address scope */ +- CINIT(ADDRESS_SCOPE, LONG, 171), +- +- /* Collect certificate chain info and allow it to get retrievable with +- CURLINFO_CERTINFO after the transfer is complete. (Unfortunately) only +- working with OpenSSL-powered builds. */ +- CINIT(CERTINFO, LONG, 172), +- +- /* "name" and "pwd" to use when fetching. */ +- CINIT(USERNAME, OBJECTPOINT, 173), +- CINIT(PASSWORD, OBJECTPOINT, 174), +- +- /* "name" and "pwd" to use with Proxy when fetching. */ +- CINIT(PROXYUSERNAME, OBJECTPOINT, 175), +- CINIT(PROXYPASSWORD, OBJECTPOINT, 176), +- +- /* Comma separated list of hostnames defining no-proxy zones. These should +- match both hostnames directly, and hostnames within a domain. For +- example, local.com will match local.com and www.local.com, but NOT +- notlocal.com or www.notlocal.com. For compatibility with other +- implementations of this, .local.com will be considered to be the same as +- local.com. A single * is the only valid wildcard, and effectively +- disables the use of proxy. */ +- CINIT(NOPROXY, OBJECTPOINT, 177), +- +- /* block size for TFTP transfers */ +- CINIT(TFTP_BLKSIZE, LONG, 178), +- +- /* Socks Service */ +- CINIT(SOCKS5_GSSAPI_SERVICE, OBJECTPOINT, 179), +- +- /* Socks Service */ +- CINIT(SOCKS5_GSSAPI_NEC, LONG, 180), +- +- /* set the bitmask for the protocols that are allowed to be used for the +- transfer, which thus helps the app which takes URLs from users or other +- external inputs and want to restrict what protocol(s) to deal +- with. Defaults to CURLPROTO_ALL. */ +- CINIT(PROTOCOLS, LONG, 181), +- +- /* set the bitmask for the protocols that libcurl is allowed to follow to, +- as a subset of the CURLOPT_PROTOCOLS ones. That means the protocol needs +- to be set in both bitmasks to be allowed to get redirected to. Defaults +- to all protocols except FILE and SCP. */ +- CINIT(REDIR_PROTOCOLS, LONG, 182), +- +- /* set the SSH knownhost file name to use */ +- CINIT(SSH_KNOWNHOSTS, OBJECTPOINT, 183), +- +- /* set the SSH host key callback, must point to a curl_sshkeycallback +- function */ +- CINIT(SSH_KEYFUNCTION, FUNCTIONPOINT, 184), +- +- /* set the SSH host key callback custom pointer */ +- CINIT(SSH_KEYDATA, OBJECTPOINT, 185), +- +- CURLOPT_LASTENTRY /* the last unused */ +-} CURLoption; +- +-#ifndef CURL_NO_OLDIES /* define this to test if your app builds with all +- the obsolete stuff removed! */ +- +-/* Backwards compatibility with older names */ +-/* These are scheduled to disappear by 2011 */ +- +-/* This was added in version 7.19.1 */ +-#define CURLOPT_POST301 CURLOPT_POSTREDIR +- +-/* These are scheduled to disappear by 2009 */ +- +-/* The following were added in 7.17.0 */ +-#define CURLOPT_SSLKEYPASSWD CURLOPT_KEYPASSWD +-#define CURLOPT_FTPAPPEND CURLOPT_APPEND +-#define CURLOPT_FTPLISTONLY CURLOPT_DIRLISTONLY +-#define CURLOPT_FTP_SSL CURLOPT_USE_SSL +- +-/* The following were added earlier */ +- +-#define CURLOPT_SSLCERTPASSWD CURLOPT_KEYPASSWD +-#define CURLOPT_KRB4LEVEL CURLOPT_KRBLEVEL +- +-#else +-/* This is set if CURL_NO_OLDIES is defined at compile-time */ +-#undef CURLOPT_DNS_USE_GLOBAL_CACHE /* soon obsolete */ +-#endif +- +- +- /* Below here follows defines for the CURLOPT_IPRESOLVE option. If a host +- name resolves addresses using more than one IP protocol version, this +- option might be handy to force libcurl to use a specific IP version. */ +-#define CURL_IPRESOLVE_WHATEVER 0 /* default, resolves addresses to all IP +- versions that your system allows */ +-#define CURL_IPRESOLVE_V4 1 /* resolve to ipv4 addresses */ +-#define CURL_IPRESOLVE_V6 2 /* resolve to ipv6 addresses */ +- +- /* three convenient "aliases" that follow the name scheme better */ +-#define CURLOPT_WRITEDATA CURLOPT_FILE +-#define CURLOPT_READDATA CURLOPT_INFILE +-#define CURLOPT_HEADERDATA CURLOPT_WRITEHEADER +- +- /* These enums are for use with the CURLOPT_HTTP_VERSION option. */ +-enum { +- CURL_HTTP_VERSION_NONE, /* setting this means we don't care, and that we'd +- like the library to choose the best possible +- for us! */ +- CURL_HTTP_VERSION_1_0, /* please use HTTP 1.0 in the request */ +- CURL_HTTP_VERSION_1_1, /* please use HTTP 1.1 in the request */ +- +- CURL_HTTP_VERSION_LAST /* *ILLEGAL* http version */ +-}; +- +- /* These enums are for use with the CURLOPT_NETRC option. */ +-enum CURL_NETRC_OPTION { +- CURL_NETRC_IGNORED, /* The .netrc will never be read. +- * This is the default. */ +- CURL_NETRC_OPTIONAL, /* A user:password in the URL will be preferred +- * to one in the .netrc. */ +- CURL_NETRC_REQUIRED, /* A user:password in the URL will be ignored. +- * Unless one is set programmatically, the .netrc +- * will be queried. */ +- CURL_NETRC_LAST +-}; +- +-enum { +- CURL_SSLVERSION_DEFAULT, +- CURL_SSLVERSION_TLSv1, +- CURL_SSLVERSION_SSLv2, +- CURL_SSLVERSION_SSLv3, +- +- CURL_SSLVERSION_LAST /* never use, keep last */ +-}; +- +-/* symbols to use with CURLOPT_POSTREDIR. +- CURL_REDIR_POST_301 and CURL_REDIR_POST_302 can be bitwise ORed so that +- CURL_REDIR_POST_301 | CURL_REDIR_POST_302 == CURL_REDIR_POST_ALL */ +- +-#define CURL_REDIR_GET_ALL 0 +-#define CURL_REDIR_POST_301 1 +-#define CURL_REDIR_POST_302 2 +-#define CURL_REDIR_POST_ALL (CURL_REDIR_POST_301|CURL_REDIR_POST_302) +- +-typedef enum { +- CURL_TIMECOND_NONE, +- +- CURL_TIMECOND_IFMODSINCE, +- CURL_TIMECOND_IFUNMODSINCE, +- CURL_TIMECOND_LASTMOD, +- +- CURL_TIMECOND_LAST +-} curl_TimeCond; +- +- +-/* curl_strequal() and curl_strnequal() are subject for removal in a future +- libcurl, see lib/README.curlx for details */ +-CURL_EXTERN int (curl_strequal)(const char *s1, const char *s2); +-CURL_EXTERN int (curl_strnequal)(const char *s1, const char *s2, size_t n); +- +-/* name is uppercase CURLFORM_ */ +-#ifdef CFINIT +-#undef CFINIT +-#endif +- +-#ifdef CURL_ISOCPP +-#define CFINIT(name) CURLFORM_ ## name +-#else +-/* The macro "##" is ISO C, we assume pre-ISO C doesn't support it. */ +-#define CFINIT(name) CURLFORM_/**/name +-#endif +- +-typedef enum { +- CFINIT(NOTHING), /********* the first one is unused ************/ +- +- /* */ +- CFINIT(COPYNAME), +- CFINIT(PTRNAME), +- CFINIT(NAMELENGTH), +- CFINIT(COPYCONTENTS), +- CFINIT(PTRCONTENTS), +- CFINIT(CONTENTSLENGTH), +- CFINIT(FILECONTENT), +- CFINIT(ARRAY), +- CFINIT(OBSOLETE), +- CFINIT(FILE), +- +- CFINIT(BUFFER), +- CFINIT(BUFFERPTR), +- CFINIT(BUFFERLENGTH), +- +- CFINIT(CONTENTTYPE), +- CFINIT(CONTENTHEADER), +- CFINIT(FILENAME), +- CFINIT(END), +- CFINIT(OBSOLETE2), +- +- CFINIT(STREAM), +- +- CURLFORM_LASTENTRY /* the last unused */ +-} CURLformoption; +- +-#undef CFINIT /* done */ +- +-/* structure to be used as parameter for CURLFORM_ARRAY */ +-struct curl_forms { +- CURLformoption option; +- const char *value; +-}; +- +-/* use this for multipart formpost building */ +-/* Returns code for curl_formadd() +- * +- * Returns: +- * CURL_FORMADD_OK on success +- * CURL_FORMADD_MEMORY if the FormInfo allocation fails +- * CURL_FORMADD_OPTION_TWICE if one option is given twice for one Form +- * CURL_FORMADD_NULL if a null pointer was given for a char +- * CURL_FORMADD_MEMORY if the allocation of a FormInfo struct failed +- * CURL_FORMADD_UNKNOWN_OPTION if an unknown option was used +- * CURL_FORMADD_INCOMPLETE if the some FormInfo is not complete (or error) +- * CURL_FORMADD_MEMORY if a curl_httppost struct cannot be allocated +- * CURL_FORMADD_MEMORY if some allocation for string copying failed. +- * CURL_FORMADD_ILLEGAL_ARRAY if an illegal option is used in an array +- * +- ***************************************************************************/ +-typedef enum { +- CURL_FORMADD_OK, /* first, no error */ +- +- CURL_FORMADD_MEMORY, +- CURL_FORMADD_OPTION_TWICE, +- CURL_FORMADD_NULL, +- CURL_FORMADD_UNKNOWN_OPTION, +- CURL_FORMADD_INCOMPLETE, +- CURL_FORMADD_ILLEGAL_ARRAY, +- CURL_FORMADD_DISABLED, /* libcurl was built with this disabled */ +- +- CURL_FORMADD_LAST /* last */ +-} CURLFORMcode; +- +-/* +- * NAME curl_formadd() +- * +- * DESCRIPTION +- * +- * Pretty advanced function for building multi-part formposts. Each invoke +- * adds one part that together construct a full post. Then use +- * CURLOPT_HTTPPOST to send it off to libcurl. +- */ +-CURL_EXTERN CURLFORMcode curl_formadd(struct curl_httppost **httppost, +- struct curl_httppost **last_post, +- ...); +- +-/* +- * callback function for curl_formget() +- * The void *arg pointer will be the one passed as second argument to +- * curl_formget(). +- * The character buffer passed to it must not be freed. +- * Should return the buffer length passed to it as the argument "len" on +- * success. +- */ +-typedef size_t (*curl_formget_callback)(void *arg, const char *buf, size_t len); +- +-/* +- * NAME curl_formget() +- * +- * DESCRIPTION +- * +- * Serialize a curl_httppost struct built with curl_formadd(). +- * Accepts a void pointer as second argument which will be passed to +- * the curl_formget_callback function. +- * Returns 0 on success. +- */ +-CURL_EXTERN int curl_formget(struct curl_httppost *form, void *arg, +- curl_formget_callback append); +-/* +- * NAME curl_formfree() +- * +- * DESCRIPTION +- * +- * Free a multipart formpost previously built with curl_formadd(). +- */ +-CURL_EXTERN void curl_formfree(struct curl_httppost *form); +- +-/* +- * NAME curl_getenv() +- * +- * DESCRIPTION +- * +- * Returns a malloc()'ed string that MUST be curl_free()ed after usage is +- * complete. DEPRECATED - see lib/README.curlx +- */ +-CURL_EXTERN char *curl_getenv(const char *variable); +- +-/* +- * NAME curl_version() +- * +- * DESCRIPTION +- * +- * Returns a static ascii string of the libcurl version. +- */ +-CURL_EXTERN char *curl_version(void); +- +-/* +- * NAME curl_easy_escape() +- * +- * DESCRIPTION +- * +- * Escapes URL strings (converts all letters consider illegal in URLs to their +- * %XX versions). This function returns a new allocated string or NULL if an +- * error occurred. +- */ +-CURL_EXTERN char *curl_easy_escape(CURL *handle, +- const char *string, +- int length); +- +-/* the previous version: */ +-CURL_EXTERN char *curl_escape(const char *string, +- int length); +- +- +-/* +- * NAME curl_easy_unescape() +- * +- * DESCRIPTION +- * +- * Unescapes URL encoding in strings (converts all %XX codes to their 8bit +- * versions). This function returns a new allocated string or NULL if an error +- * occurred. +- * Conversion Note: On non-ASCII platforms the ASCII %XX codes are +- * converted into the host encoding. +- */ +-CURL_EXTERN char *curl_easy_unescape(CURL *handle, +- const char *string, +- int length, +- int *outlength); +- +-/* the previous version */ +-CURL_EXTERN char *curl_unescape(const char *string, +- int length); +- +-/* +- * NAME curl_free() +- * +- * DESCRIPTION +- * +- * Provided for de-allocation in the same translation unit that did the +- * allocation. Added in libcurl 7.10 +- */ +-CURL_EXTERN void curl_free(void *p); +- +-/* +- * NAME curl_global_init() +- * +- * DESCRIPTION +- * +- * curl_global_init() should be invoked exactly once for each application that +- * uses libcurl and before any call of other libcurl functions. +- * +- * This function is not thread-safe! +- */ +-CURL_EXTERN CURLcode curl_global_init(long flags); +- +-/* +- * NAME curl_global_init_mem() +- * +- * DESCRIPTION +- * +- * curl_global_init() or curl_global_init_mem() should be invoked exactly once +- * for each application that uses libcurl. This function can be used to +- * initialize libcurl and set user defined memory management callback +- * functions. Users can implement memory management routines to check for +- * memory leaks, check for mis-use of the curl library etc. User registered +- * callback routines with be invoked by this library instead of the system +- * memory management routines like malloc, free etc. +- */ +-CURL_EXTERN CURLcode curl_global_init_mem(long flags, +- curl_malloc_callback m, +- curl_free_callback f, +- curl_realloc_callback r, +- curl_strdup_callback s, +- curl_calloc_callback c); +- +-/* +- * NAME curl_global_cleanup() +- * +- * DESCRIPTION +- * +- * curl_global_cleanup() should be invoked exactly once for each application +- * that uses libcurl +- */ +-CURL_EXTERN void curl_global_cleanup(void); +- +-/* linked-list structure for the CURLOPT_QUOTE option (and other) */ +-struct curl_slist { +- char *data; +- struct curl_slist *next; +-}; +- +-/* +- * NAME curl_slist_append() +- * +- * DESCRIPTION +- * +- * Appends a string to a linked list. If no list exists, it will be created +- * first. Returns the new list, after appending. +- */ +-CURL_EXTERN struct curl_slist *curl_slist_append(struct curl_slist *, +- const char *); +- +-/* +- * NAME curl_slist_free_all() +- * +- * DESCRIPTION +- * +- * free a previously built curl_slist. +- */ +-CURL_EXTERN void curl_slist_free_all(struct curl_slist *); +- +-/* +- * NAME curl_getdate() +- * +- * DESCRIPTION +- * +- * Returns the time, in seconds since 1 Jan 1970 of the time string given in +- * the first argument. The time argument in the second parameter is unused +- * and should be set to NULL. +- */ +-CURL_EXTERN time_t curl_getdate(const char *p, const time_t *unused); +- +-/* info about the certificate chain, only for OpenSSL builds. Asked +- for with CURLOPT_CERTINFO / CURLINFO_CERTINFO */ +-struct curl_certinfo { +- int num_of_certs; /* number of certificates with information */ +- struct curl_slist **certinfo; /* for each index in this array, there's a +- linked list with textual information in the +- format "name: value" */ +-}; +- +-#define CURLINFO_STRING 0x100000 +-#define CURLINFO_LONG 0x200000 +-#define CURLINFO_DOUBLE 0x300000 +-#define CURLINFO_SLIST 0x400000 +-#define CURLINFO_MASK 0x0fffff +-#define CURLINFO_TYPEMASK 0xf00000 +- +-typedef enum { +- CURLINFO_NONE, /* first, never use this */ +- CURLINFO_EFFECTIVE_URL = CURLINFO_STRING + 1, +- CURLINFO_RESPONSE_CODE = CURLINFO_LONG + 2, +- CURLINFO_TOTAL_TIME = CURLINFO_DOUBLE + 3, +- CURLINFO_NAMELOOKUP_TIME = CURLINFO_DOUBLE + 4, +- CURLINFO_CONNECT_TIME = CURLINFO_DOUBLE + 5, +- CURLINFO_PRETRANSFER_TIME = CURLINFO_DOUBLE + 6, +- CURLINFO_SIZE_UPLOAD = CURLINFO_DOUBLE + 7, +- CURLINFO_SIZE_DOWNLOAD = CURLINFO_DOUBLE + 8, +- CURLINFO_SPEED_DOWNLOAD = CURLINFO_DOUBLE + 9, +- CURLINFO_SPEED_UPLOAD = CURLINFO_DOUBLE + 10, +- CURLINFO_HEADER_SIZE = CURLINFO_LONG + 11, +- CURLINFO_REQUEST_SIZE = CURLINFO_LONG + 12, +- CURLINFO_SSL_VERIFYRESULT = CURLINFO_LONG + 13, +- CURLINFO_FILETIME = CURLINFO_LONG + 14, +- CURLINFO_CONTENT_LENGTH_DOWNLOAD = CURLINFO_DOUBLE + 15, +- CURLINFO_CONTENT_LENGTH_UPLOAD = CURLINFO_DOUBLE + 16, +- CURLINFO_STARTTRANSFER_TIME = CURLINFO_DOUBLE + 17, +- CURLINFO_CONTENT_TYPE = CURLINFO_STRING + 18, +- CURLINFO_REDIRECT_TIME = CURLINFO_DOUBLE + 19, +- CURLINFO_REDIRECT_COUNT = CURLINFO_LONG + 20, +- CURLINFO_PRIVATE = CURLINFO_STRING + 21, +- CURLINFO_HTTP_CONNECTCODE = CURLINFO_LONG + 22, +- CURLINFO_HTTPAUTH_AVAIL = CURLINFO_LONG + 23, +- CURLINFO_PROXYAUTH_AVAIL = CURLINFO_LONG + 24, +- CURLINFO_OS_ERRNO = CURLINFO_LONG + 25, +- CURLINFO_NUM_CONNECTS = CURLINFO_LONG + 26, +- CURLINFO_SSL_ENGINES = CURLINFO_SLIST + 27, +- CURLINFO_COOKIELIST = CURLINFO_SLIST + 28, +- CURLINFO_LASTSOCKET = CURLINFO_LONG + 29, +- CURLINFO_FTP_ENTRY_PATH = CURLINFO_STRING + 30, +- CURLINFO_REDIRECT_URL = CURLINFO_STRING + 31, +- CURLINFO_PRIMARY_IP = CURLINFO_STRING + 32, +- CURLINFO_APPCONNECT_TIME = CURLINFO_DOUBLE + 33, +- CURLINFO_CERTINFO = CURLINFO_SLIST + 34, +- CURLINFO_CONDITION_UNMET = CURLINFO_LONG + 35, +- /* Fill in new entries below here! */ +- +- CURLINFO_LASTONE = 35 +-} CURLINFO; +- +-/* CURLINFO_RESPONSE_CODE is the new name for the option previously known as +- CURLINFO_HTTP_CODE */ +-#define CURLINFO_HTTP_CODE CURLINFO_RESPONSE_CODE +- +-typedef enum { +- CURLCLOSEPOLICY_NONE, /* first, never use this */ +- +- CURLCLOSEPOLICY_OLDEST, +- CURLCLOSEPOLICY_LEAST_RECENTLY_USED, +- CURLCLOSEPOLICY_LEAST_TRAFFIC, +- CURLCLOSEPOLICY_SLOWEST, +- CURLCLOSEPOLICY_CALLBACK, +- +- CURLCLOSEPOLICY_LAST /* last, never use this */ +-} curl_closepolicy; +- +-#define CURL_GLOBAL_SSL (1<<0) +-#define CURL_GLOBAL_WIN32 (1<<1) +-#define CURL_GLOBAL_ALL (CURL_GLOBAL_SSL|CURL_GLOBAL_WIN32) +-#define CURL_GLOBAL_NOTHING 0 +-#define CURL_GLOBAL_DEFAULT CURL_GLOBAL_ALL +- +- +-/***************************************************************************** +- * Setup defines, protos etc for the sharing stuff. +- */ +- +-/* Different data locks for a single share */ +-typedef enum { +- CURL_LOCK_DATA_NONE = 0, +- /* CURL_LOCK_DATA_SHARE is used internally to say that +- * the locking is just made to change the internal state of the share +- * itself. +- */ +- CURL_LOCK_DATA_SHARE, +- CURL_LOCK_DATA_COOKIE, +- CURL_LOCK_DATA_DNS, +- CURL_LOCK_DATA_SSL_SESSION, +- CURL_LOCK_DATA_CONNECT, +- CURL_LOCK_DATA_LAST +-} curl_lock_data; +- +-/* Different lock access types */ +-typedef enum { +- CURL_LOCK_ACCESS_NONE = 0, /* unspecified action */ +- CURL_LOCK_ACCESS_SHARED = 1, /* for read perhaps */ +- CURL_LOCK_ACCESS_SINGLE = 2, /* for write perhaps */ +- CURL_LOCK_ACCESS_LAST /* never use */ +-} curl_lock_access; +- +-typedef void (*curl_lock_function)(CURL *handle, +- curl_lock_data data, +- curl_lock_access locktype, +- void *userptr); +-typedef void (*curl_unlock_function)(CURL *handle, +- curl_lock_data data, +- void *userptr); +- +-typedef void CURLSH; +- +-typedef enum { +- CURLSHE_OK, /* all is fine */ +- CURLSHE_BAD_OPTION, /* 1 */ +- CURLSHE_IN_USE, /* 2 */ +- CURLSHE_INVALID, /* 3 */ +- CURLSHE_NOMEM, /* out of memory */ +- CURLSHE_LAST /* never use */ +-} CURLSHcode; +- +-typedef enum { +- CURLSHOPT_NONE, /* don't use */ +- CURLSHOPT_SHARE, /* specify a data type to share */ +- CURLSHOPT_UNSHARE, /* specify which data type to stop sharing */ +- CURLSHOPT_LOCKFUNC, /* pass in a 'curl_lock_function' pointer */ +- CURLSHOPT_UNLOCKFUNC, /* pass in a 'curl_unlock_function' pointer */ +- CURLSHOPT_USERDATA, /* pass in a user data pointer used in the lock/unlock +- callback functions */ +- CURLSHOPT_LAST /* never use */ +-} CURLSHoption; +- +-CURL_EXTERN CURLSH *curl_share_init(void); +-CURL_EXTERN CURLSHcode curl_share_setopt(CURLSH *, CURLSHoption option, ...); +-CURL_EXTERN CURLSHcode curl_share_cleanup(CURLSH *); +- +-/**************************************************************************** +- * Structures for querying information about the curl library at runtime. +- */ +- +-typedef enum { +- CURLVERSION_FIRST, +- CURLVERSION_SECOND, +- CURLVERSION_THIRD, +- CURLVERSION_FOURTH, +- CURLVERSION_LAST /* never actually use this */ +-} CURLversion; +- +-/* The 'CURLVERSION_NOW' is the symbolic name meant to be used by +- basically all programs ever that want to get version information. It is +- meant to be a built-in version number for what kind of struct the caller +- expects. If the struct ever changes, we redefine the NOW to another enum +- from above. */ +-#define CURLVERSION_NOW CURLVERSION_FOURTH +- +-typedef struct { +- CURLversion age; /* age of the returned struct */ +- const char *version; /* LIBCURL_VERSION */ +- unsigned int version_num; /* LIBCURL_VERSION_NUM */ +- const char *host; /* OS/host/cpu/machine when configured */ +- int features; /* bitmask, see defines below */ +- const char *ssl_version; /* human readable string */ +- long ssl_version_num; /* not used anymore, always 0 */ +- const char *libz_version; /* human readable string */ +- /* protocols is terminated by an entry with a NULL protoname */ +- const char * const *protocols; +- +- /* The fields below this were added in CURLVERSION_SECOND */ +- const char *ares; +- int ares_num; +- +- /* This field was added in CURLVERSION_THIRD */ +- const char *libidn; +- +- /* These field were added in CURLVERSION_FOURTH */ +- +- /* Same as '_libiconv_version' if built with HAVE_ICONV */ +- int iconv_ver_num; +- +- const char *libssh_version; /* human readable string */ +- +-} curl_version_info_data; +- +-#define CURL_VERSION_IPV6 (1<<0) /* IPv6-enabled */ +-#define CURL_VERSION_KERBEROS4 (1<<1) /* kerberos auth is supported */ +-#define CURL_VERSION_SSL (1<<2) /* SSL options are present */ +-#define CURL_VERSION_LIBZ (1<<3) /* libz features are present */ +-#define CURL_VERSION_NTLM (1<<4) /* NTLM auth is supported */ +-#define CURL_VERSION_GSSNEGOTIATE (1<<5) /* Negotiate auth support */ +-#define CURL_VERSION_DEBUG (1<<6) /* built with debug capabilities */ +-#define CURL_VERSION_ASYNCHDNS (1<<7) /* asynchronous dns resolves */ +-#define CURL_VERSION_SPNEGO (1<<8) /* SPNEGO auth */ +-#define CURL_VERSION_LARGEFILE (1<<9) /* supports files bigger than 2GB */ +-#define CURL_VERSION_IDN (1<<10) /* International Domain Names support */ +-#define CURL_VERSION_SSPI (1<<11) /* SSPI is supported */ +-#define CURL_VERSION_CONV (1<<12) /* character conversions supported */ +-#define CURL_VERSION_CURLDEBUG (1<<13) /* debug memory tracking supported */ +- +-/* +- * NAME curl_version_info() +- * +- * DESCRIPTION +- * +- * This function returns a pointer to a static copy of the version info +- * struct. See above. +- */ +-CURL_EXTERN curl_version_info_data *curl_version_info(CURLversion); +- +-/* +- * NAME curl_easy_strerror() +- * +- * DESCRIPTION +- * +- * The curl_easy_strerror function may be used to turn a CURLcode value +- * into the equivalent human readable error string. This is useful +- * for printing meaningful error messages. +- */ +-CURL_EXTERN const char *curl_easy_strerror(CURLcode); +- +-/* +- * NAME curl_share_strerror() +- * +- * DESCRIPTION +- * +- * The curl_share_strerror function may be used to turn a CURLSHcode value +- * into the equivalent human readable error string. This is useful +- * for printing meaningful error messages. +- */ +-CURL_EXTERN const char *curl_share_strerror(CURLSHcode); +- +-/* +- * NAME curl_easy_pause() +- * +- * DESCRIPTION +- * +- * The curl_easy_pause function pauses or unpauses transfers. Select the new +- * state by setting the bitmask, use the convenience defines below. +- * +- */ +-CURL_EXTERN CURLcode curl_easy_pause(CURL *handle, int bitmask); +- +-#define CURLPAUSE_RECV (1<<0) +-#define CURLPAUSE_RECV_CONT (0) +- +-#define CURLPAUSE_SEND (1<<2) +-#define CURLPAUSE_SEND_CONT (0) +- +-#define CURLPAUSE_ALL (CURLPAUSE_RECV|CURLPAUSE_SEND) +-#define CURLPAUSE_CONT (CURLPAUSE_RECV_CONT|CURLPAUSE_SEND_CONT) +- +-#ifdef __cplusplus +-} +-#endif +- +-/* unfortunately, the easy.h and multi.h include files need options and info +- stuff before they can be included! */ +-#include "easy.h" /* nothing in curl is fun without the easy stuff */ +-#include "multi.h" +- +-/* the typechecker doesn't work in C++ (yet) */ +-#if defined(__GNUC__) && defined(__GNUC_MINOR__) && \ +- ((__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3)) && \ +- !defined(__cplusplus) && !defined(CURL_DISABLE_TYPECHECK) +-#include "typecheck-gcc.h" +-#else +-#if defined(__STDC__) && (__STDC__ >= 1) +-/* This preprocessor magic that replaces a call with the exact same call is +- only done to make sure application authors pass exactly three arguments +- to these functions. */ +-#define curl_easy_setopt(handle,opt,param) curl_easy_setopt(handle,opt,param) +-#define curl_easy_getinfo(handle,info,arg) curl_easy_getinfo(handle,info,arg) +-#define curl_share_setopt(share,opt,param) curl_share_setopt(share,opt,param) +-#define curl_multi_setopt(handle,opt,param) curl_multi_setopt(handle,opt,param) +-#endif /* __STDC__ >= 1 */ +-#endif /* gcc >= 4.3 && !__cplusplus */ +- +-#endif /* __CURL_CURL_H */ +diff --git a/src/third_party/curl/curlbuild.h b/src/third_party/curl/curlbuild.h +deleted file mode 100644 +index 595df4e4..00000000 +--- a/src/third_party/curl/curlbuild.h ++++ /dev/null +@@ -1,203 +0,0 @@ +-/* include/curl/curlbuild.h. Generated from curlbuild.h.in by configure. */ +-#ifndef __CURL_CURLBUILD_H +-#define __CURL_CURLBUILD_H +-/*************************************************************************** +- * _ _ ____ _ +- * Project ___| | | | _ \| | +- * / __| | | | |_) | | +- * | (__| |_| | _ <| |___ +- * \___|\___/|_| \_\_____| +- * +- * Copyright (C) 1998 - 2009, Daniel Stenberg, , et al. +- * +- * This software is licensed as described in the file COPYING, which +- * you should have received as part of this distribution. The terms +- * are also available at http://curl.haxx.se/docs/copyright.html. +- * +- * You may opt to use, copy, modify, merge, publish, distribute and/or sell +- * copies of the Software, and permit persons to whom the Software is +- * furnished to do so, under the terms of the COPYING file. +- * +- * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY +- * KIND, either express or implied. +- * +- * $Id: curlbuild.h.in,v 1.8 2009-04-29 15:15:38 yangtse Exp $ +- ***************************************************************************/ +- +-/* ================================================================ */ +-/* NOTES FOR CONFIGURE CAPABLE SYSTEMS */ +-/* ================================================================ */ +- +-/* +- * NOTE 1: +- * ------- +- * +- * Nothing in this file is intended to be modified or adjusted by the +- * curl library user nor by the curl library builder. +- * +- * If you think that something actually needs to be changed, adjusted +- * or fixed in this file, then, report it on the libcurl development +- * mailing list: http://cool.haxx.se/mailman/listinfo/curl-library/ +- * +- * This header file shall only export symbols which are 'curl' or 'CURL' +- * prefixed, otherwise public name space would be polluted. +- * +- * NOTE 2: +- * ------- +- * +- * Right now you might be staring at file include/curl/curlbuild.h.in or +- * at file include/curl/curlbuild.h, this is due to the following reason: +- * +- * On systems capable of running the configure script, the configure process +- * will overwrite the distributed include/curl/curlbuild.h file with one that +- * is suitable and specific to the library being configured and built, which +- * is generated from the include/curl/curlbuild.h.in template file. +- * +- */ +- +-/* ================================================================ */ +-/* DEFINITION OF THESE SYMBOLS SHALL NOT TAKE PLACE ANYWHERE ELSE */ +-/* ================================================================ */ +- +-#ifdef CURL_SIZEOF_LONG +-# error "CURL_SIZEOF_LONG shall not be defined except in curlbuild.h" +- Error Compilation_aborted_CURL_SIZEOF_LONG_already_defined +-#endif +- +-#ifdef CURL_TYPEOF_CURL_SOCKLEN_T +-# error "CURL_TYPEOF_CURL_SOCKLEN_T shall not be defined except in curlbuild.h" +- Error Compilation_aborted_CURL_TYPEOF_CURL_SOCKLEN_T_already_defined +-#endif +- +-#ifdef CURL_SIZEOF_CURL_SOCKLEN_T +-# error "CURL_SIZEOF_CURL_SOCKLEN_T shall not be defined except in curlbuild.h" +- Error Compilation_aborted_CURL_SIZEOF_CURL_SOCKLEN_T_already_defined +-#endif +- +-#ifdef CURL_TYPEOF_CURL_OFF_T +-# error "CURL_TYPEOF_CURL_OFF_T shall not be defined except in curlbuild.h" +- Error Compilation_aborted_CURL_TYPEOF_CURL_OFF_T_already_defined +-#endif +- +-#ifdef CURL_FORMAT_CURL_OFF_T +-# error "CURL_FORMAT_CURL_OFF_T shall not be defined except in curlbuild.h" +- Error Compilation_aborted_CURL_FORMAT_CURL_OFF_T_already_defined +-#endif +- +-#ifdef CURL_FORMAT_CURL_OFF_TU +-# error "CURL_FORMAT_CURL_OFF_TU shall not be defined except in curlbuild.h" +- Error Compilation_aborted_CURL_FORMAT_CURL_OFF_TU_already_defined +-#endif +- +-#ifdef CURL_FORMAT_OFF_T +-# error "CURL_FORMAT_OFF_T shall not be defined except in curlbuild.h" +- Error Compilation_aborted_CURL_FORMAT_OFF_T_already_defined +-#endif +- +-#ifdef CURL_SIZEOF_CURL_OFF_T +-# error "CURL_SIZEOF_CURL_OFF_T shall not be defined except in curlbuild.h" +- Error Compilation_aborted_CURL_SIZEOF_CURL_OFF_T_already_defined +-#endif +- +-#ifdef CURL_SUFFIX_CURL_OFF_T +-# error "CURL_SUFFIX_CURL_OFF_T shall not be defined except in curlbuild.h" +- Error Compilation_aborted_CURL_SUFFIX_CURL_OFF_T_already_defined +-#endif +- +-#ifdef CURL_SUFFIX_CURL_OFF_TU +-# error "CURL_SUFFIX_CURL_OFF_TU shall not be defined except in curlbuild.h" +- Error Compilation_aborted_CURL_SUFFIX_CURL_OFF_TU_already_defined +-#endif +- +-/* ================================================================ */ +-/* EXTERNAL INTERFACE SETTINGS FOR CONFIGURE CAPABLE SYSTEMS ONLY */ +-/* ================================================================ */ +- +-/* Configure process defines this to 1 when it finds out that system */ +-/* header file ws2tcpip.h must be included by the external interface. */ +-/* #undef CURL_PULL_WS2TCPIP_H */ +-#ifdef CURL_PULL_WS2TCPIP_H +-# ifndef WIN32_LEAN_AND_MEAN +-# define WIN32_LEAN_AND_MEAN +-# endif +-# include +-# include +-# include +-#endif +- +-/* Configure process defines this to 1 when it finds out that system */ +-/* header file sys/types.h must be included by the external interface. */ +-#define CURL_PULL_SYS_TYPES_H 1 +-#ifdef CURL_PULL_SYS_TYPES_H +-# include +-#endif +- +-/* Configure process defines this to 1 when it finds out that system */ +-/* header file stdint.h must be included by the external interface. */ +-/* #undef CURL_PULL_STDINT_H */ +-#ifdef CURL_PULL_STDINT_H +-# include +-#endif +- +-/* Configure process defines this to 1 when it finds out that system */ +-/* header file inttypes.h must be included by the external interface. */ +-/* #undef CURL_PULL_INTTYPES_H */ +-#ifdef CURL_PULL_INTTYPES_H +-# include +-#endif +- +-/* Configure process defines this to 1 when it finds out that system */ +-/* header file sys/socket.h must be included by the external interface. */ +-#define CURL_PULL_SYS_SOCKET_H 1 +-#ifdef CURL_PULL_SYS_SOCKET_H +-# include +-#endif +- +-/* The size of `long', as computed by sizeof. */ +-#if defined(_M_X64) || (defined(__x86_64__) && !defined(__ILP32__)) || \ +- defined(__aarch64__) || (defined(__mips__) && _MIPS_SIM == _ABI64) || \ +- defined(__powerpc64__) || defined(__s390x__) || defined(__LP64__) +-#define CURL_SIZEOF_LONG 8 +-#else +-#define CURL_SIZEOF_LONG 4 +-#endif +- +-/* Integral data type used for curl_socklen_t. */ +-#define CURL_TYPEOF_CURL_SOCKLEN_T socklen_t +- +-/* The size of `curl_socklen_t', as computed by sizeof. */ +-#define CURL_SIZEOF_CURL_SOCKLEN_T 4 +- +-/* Data type definition of curl_socklen_t. */ +-typedef CURL_TYPEOF_CURL_SOCKLEN_T curl_socklen_t; +- +-/* Signed integral data type used for curl_off_t. */ +-#if defined(_M_X64) || (defined(__x86_64__) && !defined(__ILP32__)) || \ +- defined(__aarch64__) +-#define CURL_TYPEOF_CURL_OFF_T long +-#else +-#define CURL_TYPEOF_CURL_OFF_T int64_t +-#endif +- +-/* Data type definition of curl_off_t. */ +-typedef CURL_TYPEOF_CURL_OFF_T curl_off_t; +- +-/* curl_off_t formatting string directive without "%" conversion specifier. */ +-#define CURL_FORMAT_CURL_OFF_T "ld" +- +-/* unsigned curl_off_t formatting string without "%" conversion specifier. */ +-#define CURL_FORMAT_CURL_OFF_TU "lu" +- +-/* curl_off_t formatting string directive with "%" conversion specifier. */ +-#define CURL_FORMAT_OFF_T "%ld" +- +-/* The size of `curl_off_t', as computed by sizeof. */ +-#define CURL_SIZEOF_CURL_OFF_T 8 +- +-/* curl_off_t constant suffix. */ +-#define CURL_SUFFIX_CURL_OFF_T L +- +-/* unsigned curl_off_t constant suffix. */ +-#define CURL_SUFFIX_CURL_OFF_TU UL +- +-#endif /* __CURL_CURLBUILD_H */ +diff --git a/src/third_party/curl/curlrules.h b/src/third_party/curl/curlrules.h +deleted file mode 100644 +index abac4397..00000000 +--- a/src/third_party/curl/curlrules.h ++++ /dev/null +@@ -1,249 +0,0 @@ +-#ifndef __CURL_CURLRULES_H +-#define __CURL_CURLRULES_H +-/*************************************************************************** +- * _ _ ____ _ +- * Project ___| | | | _ \| | +- * / __| | | | |_) | | +- * | (__| |_| | _ <| |___ +- * \___|\___/|_| \_\_____| +- * +- * Copyright (C) 1998 - 2009, Daniel Stenberg, , et al. +- * +- * This software is licensed as described in the file COPYING, which +- * you should have received as part of this distribution. The terms +- * are also available at http://curl.haxx.se/docs/copyright.html. +- * +- * You may opt to use, copy, modify, merge, publish, distribute and/or sell +- * copies of the Software, and permit persons to whom the Software is +- * furnished to do so, under the terms of the COPYING file. +- * +- * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY +- * KIND, either express or implied. +- * +- * $Id: curlrules.h,v 1.7 2009-10-27 16:56:20 yangtse Exp $ +- ***************************************************************************/ +- +-/* ================================================================ */ +-/* COMPILE TIME SANITY CHECKS */ +-/* ================================================================ */ +- +-/* +- * NOTE 1: +- * ------- +- * +- * All checks done in this file are intentionally placed in a public +- * header file which is pulled by curl/curl.h when an application is +- * being built using an already built libcurl library. Additionally +- * this file is also included and used when building the library. +- * +- * If compilation fails on this file it is certainly sure that the +- * problem is elsewhere. It could be a problem in the curlbuild.h +- * header file, or simply that you are using different compilation +- * settings than those used to build the library. +- * +- * Nothing in this file is intended to be modified or adjusted by the +- * curl library user nor by the curl library builder. +- * +- * Do not deactivate any check, these are done to make sure that the +- * library is properly built and used. +- * +- * You can find further help on the libcurl development mailing list: +- * http://cool.haxx.se/mailman/listinfo/curl-library/ +- * +- * NOTE 2 +- * ------ +- * +- * Some of the following compile time checks are based on the fact +- * that the dimension of a constant array can not be a negative one. +- * In this way if the compile time verification fails, the compilation +- * will fail issuing an error. The error description wording is compiler +- * dependent but it will be quite similar to one of the following: +- * +- * "negative subscript or subscript is too large" +- * "array must have at least one element" +- * "-1 is an illegal array size" +- * "size of array is negative" +- * +- * If you are building an application which tries to use an already +- * built libcurl library and you are getting this kind of errors on +- * this file, it is a clear indication that there is a mismatch between +- * how the library was built and how you are trying to use it for your +- * application. Your already compiled or binary library provider is the +- * only one who can give you the details you need to properly use it. +- */ +- +-/* +- * Verify that some macros are actually defined. +- */ +- +-#ifndef CURL_SIZEOF_LONG +-# error "CURL_SIZEOF_LONG definition is missing!" +- Error Compilation_aborted_CURL_SIZEOF_LONG_is_missing +-#endif +- +-#ifndef CURL_TYPEOF_CURL_SOCKLEN_T +-# error "CURL_TYPEOF_CURL_SOCKLEN_T definition is missing!" +- Error Compilation_aborted_CURL_TYPEOF_CURL_SOCKLEN_T_is_missing +-#endif +- +-#ifndef CURL_SIZEOF_CURL_SOCKLEN_T +-# error "CURL_SIZEOF_CURL_SOCKLEN_T definition is missing!" +- Error Compilation_aborted_CURL_SIZEOF_CURL_SOCKLEN_T_is_missing +-#endif +- +-#ifndef CURL_TYPEOF_CURL_OFF_T +-# error "CURL_TYPEOF_CURL_OFF_T definition is missing!" +- Error Compilation_aborted_CURL_TYPEOF_CURL_OFF_T_is_missing +-#endif +- +-#ifndef CURL_FORMAT_CURL_OFF_T +-# error "CURL_FORMAT_CURL_OFF_T definition is missing!" +- Error Compilation_aborted_CURL_FORMAT_CURL_OFF_T_is_missing +-#endif +- +-#ifndef CURL_FORMAT_CURL_OFF_TU +-# error "CURL_FORMAT_CURL_OFF_TU definition is missing!" +- Error Compilation_aborted_CURL_FORMAT_CURL_OFF_TU_is_missing +-#endif +- +-#ifndef CURL_FORMAT_OFF_T +-# error "CURL_FORMAT_OFF_T definition is missing!" +- Error Compilation_aborted_CURL_FORMAT_OFF_T_is_missing +-#endif +- +-#ifndef CURL_SIZEOF_CURL_OFF_T +-# error "CURL_SIZEOF_CURL_OFF_T definition is missing!" +- Error Compilation_aborted_CURL_SIZEOF_CURL_OFF_T_is_missing +-#endif +- +-#ifndef CURL_SUFFIX_CURL_OFF_T +-# error "CURL_SUFFIX_CURL_OFF_T definition is missing!" +- Error Compilation_aborted_CURL_SUFFIX_CURL_OFF_T_is_missing +-#endif +- +-#ifndef CURL_SUFFIX_CURL_OFF_TU +-# error "CURL_SUFFIX_CURL_OFF_TU definition is missing!" +- Error Compilation_aborted_CURL_SUFFIX_CURL_OFF_TU_is_missing +-#endif +- +-/* +- * Macros private to this header file. +- */ +- +-#define CurlchkszEQ(t, s) sizeof(t) == s ? 1 : -1 +- +-#define CurlchkszGE(t1, t2) sizeof(t1) >= sizeof(t2) ? 1 : -1 +- +-/* +- * Verify that the size previously defined and expected for long +- * is the same as the one reported by sizeof() at compile time. +- */ +- +-typedef char +- __curl_rule_01__ +- [CurlchkszEQ(long, CURL_SIZEOF_LONG)]; +- +-/* +- * Verify that the size previously defined and expected for +- * curl_off_t is actually the the same as the one reported +- * by sizeof() at compile time. +- */ +- +-typedef char +- __curl_rule_02__ +- [CurlchkszEQ(curl_off_t, CURL_SIZEOF_CURL_OFF_T)]; +- +-/* +- * Verify at compile time that the size of curl_off_t as reported +- * by sizeof() is greater or equal than the one reported for long +- * for the current compilation. +- */ +- +-typedef char +- __curl_rule_03__ +- [CurlchkszGE(curl_off_t, long)]; +- +-/* +- * Verify that the size previously defined and expected for +- * curl_socklen_t is actually the the same as the one reported +- * by sizeof() at compile time. +- */ +- +-typedef char +- __curl_rule_04__ +- [CurlchkszEQ(curl_socklen_t, CURL_SIZEOF_CURL_SOCKLEN_T)]; +- +-/* +- * Verify at compile time that the size of curl_socklen_t as reported +- * by sizeof() is greater or equal than the one reported for int for +- * the current compilation. +- */ +- +-typedef char +- __curl_rule_05__ +- [CurlchkszGE(curl_socklen_t, int)]; +- +-/* ================================================================ */ +-/* EXTERNALLY AND INTERNALLY VISIBLE DEFINITIONS */ +-/* ================================================================ */ +- +-/* +- * CURL_ISOCPP and CURL_OFF_T_C definitions are done here in order to allow +- * these to be visible and exported by the external libcurl interface API, +- * while also making them visible to the library internals, simply including +- * setup.h, without actually needing to include curl.h internally. +- * If some day this section would grow big enough, all this should be moved +- * to its own header file. +- */ +- +-/* +- * Figure out if we can use the ## preprocessor operator, which is supported +- * by ISO/ANSI C and C++. Some compilers support it without setting __STDC__ +- * or __cplusplus so we need to carefully check for them too. +- */ +- +-#if defined(__STDC__) || defined(_MSC_VER) || defined(__cplusplus) || \ +- defined(__HP_aCC) || defined(__BORLANDC__) || defined(__LCC__) || \ +- defined(__POCC__) || defined(__SALFORDC__) || defined(__HIGHC__) || \ +- defined(__ILEC400__) +- /* This compiler is believed to have an ISO compatible preprocessor */ +-#define CURL_ISOCPP +-#else +- /* This compiler is believed NOT to have an ISO compatible preprocessor */ +-#undef CURL_ISOCPP +-#endif +- +-/* +- * Macros for minimum-width signed and unsigned curl_off_t integer constants. +- */ +- +-#ifdef CURL_ISOCPP +-# define __CURL_OFF_T_C_HELPER2(Val,Suffix) Val ## Suffix +-#else +-# define __CURL_OFF_T_C_HELPER2(Val,Suffix) Val/**/Suffix +-#endif +-#define __CURL_OFF_T_C_HELPER1(Val,Suffix) __CURL_OFF_T_C_HELPER2(Val,Suffix) +-#define CURL_OFF_T_C(Val) __CURL_OFF_T_C_HELPER1(Val,CURL_SUFFIX_CURL_OFF_T) +-#define CURL_OFF_TU_C(Val) __CURL_OFF_T_C_HELPER1(Val,CURL_SUFFIX_CURL_OFF_TU) +- +-/* +- * Get rid of macros private to this header file. +- */ +- +-#undef CurlchkszEQ +-#undef CurlchkszGE +- +-/* +- * Get rid of macros not intended to exist beyond this point. +- */ +- +-#undef CURL_PULL_WS2TCPIP_H +-#undef CURL_PULL_SYS_TYPES_H +-#undef CURL_PULL_SYS_SOCKET_H +-#undef CURL_PULL_STDINT_H +-#undef CURL_PULL_INTTYPES_H +- +-#undef CURL_TYPEOF_CURL_SOCKLEN_T +-#undef CURL_TYPEOF_CURL_OFF_T +- +-#endif /* __CURL_CURLRULES_H */ +diff --git a/src/third_party/curl/curlver.h b/src/third_party/curl/curlver.h +deleted file mode 100644 +index afa85c15..00000000 +--- a/src/third_party/curl/curlver.h ++++ /dev/null +@@ -1,70 +0,0 @@ +-#ifndef __CURL_CURLVER_H +-#define __CURL_CURLVER_H +-/*************************************************************************** +- * _ _ ____ _ +- * Project ___| | | | _ \| | +- * / __| | | | |_) | | +- * | (__| |_| | _ <| |___ +- * \___|\___/|_| \_\_____| +- * +- * Copyright (C) 1998 - 2009, Daniel Stenberg, , et al. +- * +- * This software is licensed as described in the file COPYING, which +- * you should have received as part of this distribution. The terms +- * are also available at http://curl.haxx.se/docs/copyright.html. +- * +- * You may opt to use, copy, modify, merge, publish, distribute and/or sell +- * copies of the Software, and permit persons to whom the Software is +- * furnished to do so, under the terms of the COPYING file. +- * +- * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY +- * KIND, either express or implied. +- * +- * $Id: curlver.h,v 1.48 2009-08-12 11:24:52 bagder Exp $ +- ***************************************************************************/ +- +-/* This header file contains nothing but libcurl version info, generated by +- a script at release-time. This was made its own header file in 7.11.2 */ +- +-/* This is the global package copyright */ +-#define LIBCURL_COPYRIGHT "1996 - 2009 Daniel Stenberg, ." +- +-/* This is the version number of the libcurl package from which this header +- file origins: */ +-#define LIBCURL_VERSION "7.19.7" +- +-/* The numeric version number is also available "in parts" by using these +- defines: */ +-#define LIBCURL_VERSION_MAJOR 7 +-#define LIBCURL_VERSION_MINOR 19 +-#define LIBCURL_VERSION_PATCH 7 +- +-/* This is the numeric version of the libcurl version number, meant for easier +- parsing and comparions by programs. The LIBCURL_VERSION_NUM define will +- always follow this syntax: +- +- 0xXXYYZZ +- +- Where XX, YY and ZZ are the main version, release and patch numbers in +- hexadecimal (using 8 bits each). All three numbers are always represented +- using two digits. 1.2 would appear as "0x010200" while version 9.11.7 +- appears as "0x090b07". +- +- This 6-digit (24 bits) hexadecimal number does not show pre-release number, +- and it is always a greater number in a more recent release. It makes +- comparisons with greater than and less than work. +-*/ +-#define LIBCURL_VERSION_NUM 0x071307 +- +-/* +- * This is the date and time when the full source package was created. The +- * timestamp is not stored in CVS, as the timestamp is properly set in the +- * tarballs by the maketgz script. +- * +- * The format of the date should follow this template: +- * +- * "Mon Feb 12 11:35:33 UTC 2007" +- */ +-#define LIBCURL_TIMESTAMP "Wed Nov 4 12:34:59 UTC 2009" +- +-#endif /* __CURL_CURLVER_H */ +diff --git a/src/third_party/curl/easy.h b/src/third_party/curl/easy.h +deleted file mode 100644 +index 40449c3e..00000000 +--- a/src/third_party/curl/easy.h ++++ /dev/null +@@ -1,103 +0,0 @@ +-#ifndef __CURL_EASY_H +-#define __CURL_EASY_H +-/*************************************************************************** +- * _ _ ____ _ +- * Project ___| | | | _ \| | +- * / __| | | | |_) | | +- * | (__| |_| | _ <| |___ +- * \___|\___/|_| \_\_____| +- * +- * Copyright (C) 1998 - 2008, Daniel Stenberg, , et al. +- * +- * This software is licensed as described in the file COPYING, which +- * you should have received as part of this distribution. The terms +- * are also available at http://curl.haxx.se/docs/copyright.html. +- * +- * You may opt to use, copy, modify, merge, publish, distribute and/or sell +- * copies of the Software, and permit persons to whom the Software is +- * furnished to do so, under the terms of the COPYING file. +- * +- * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY +- * KIND, either express or implied. +- * +- * $Id: easy.h,v 1.14 2008-05-12 21:43:28 bagder Exp $ +- ***************************************************************************/ +-#ifdef __cplusplus +-extern "C" { +-#endif +- +-CURL_EXTERN CURL *curl_easy_init(void); +-CURL_EXTERN CURLcode curl_easy_setopt(CURL *curl, CURLoption option, ...); +-CURL_EXTERN CURLcode curl_easy_perform(CURL *curl); +-CURL_EXTERN void curl_easy_cleanup(CURL *curl); +- +-/* +- * NAME curl_easy_getinfo() +- * +- * DESCRIPTION +- * +- * Request internal information from the curl session with this function. The +- * third argument MUST be a pointer to a long, a pointer to a char * or a +- * pointer to a double (as the documentation describes elsewhere). The data +- * pointed to will be filled in accordingly and can be relied upon only if the +- * function returns CURLE_OK. This function is intended to get used *AFTER* a +- * performed transfer, all results from this function are undefined until the +- * transfer is completed. +- */ +-CURL_EXTERN CURLcode curl_easy_getinfo(CURL *curl, CURLINFO info, ...); +- +- +-/* +- * NAME curl_easy_duphandle() +- * +- * DESCRIPTION +- * +- * Creates a new curl session handle with the same options set for the handle +- * passed in. Duplicating a handle could only be a matter of cloning data and +- * options, internal state info and things like persistant connections cannot +- * be transfered. It is useful in multithreaded applications when you can run +- * curl_easy_duphandle() for each new thread to avoid a series of identical +- * curl_easy_setopt() invokes in every thread. +- */ +-CURL_EXTERN CURL* curl_easy_duphandle(CURL *curl); +- +-/* +- * NAME curl_easy_reset() +- * +- * DESCRIPTION +- * +- * Re-initializes a CURL handle to the default values. This puts back the +- * handle to the same state as it was in when it was just created. +- * +- * It does keep: live connections, the Session ID cache, the DNS cache and the +- * cookies. +- */ +-CURL_EXTERN void curl_easy_reset(CURL *curl); +- +-/* +- * NAME curl_easy_recv() +- * +- * DESCRIPTION +- * +- * Receives data from the connected socket. Use after successful +- * curl_easy_perform() with CURLOPT_CONNECT_ONLY option. +- */ +-CURL_EXTERN CURLcode curl_easy_recv(CURL *curl, void *buffer, size_t buflen, +- size_t *n); +- +-/* +- * NAME curl_easy_send() +- * +- * DESCRIPTION +- * +- * Sends data over the connected socket. Use after successful +- * curl_easy_perform() with CURLOPT_CONNECT_ONLY option. +- */ +-CURL_EXTERN CURLcode curl_easy_send(CURL *curl, const void *buffer, +- size_t buflen, size_t *n); +- +-#ifdef __cplusplus +-} +-#endif +- +-#endif +diff --git a/src/third_party/curl/mprintf.h b/src/third_party/curl/mprintf.h +deleted file mode 100644 +index d7202de1..00000000 +--- a/src/third_party/curl/mprintf.h ++++ /dev/null +@@ -1,82 +0,0 @@ +-#ifndef __CURL_MPRINTF_H +-#define __CURL_MPRINTF_H +-/*************************************************************************** +- * _ _ ____ _ +- * Project ___| | | | _ \| | +- * / __| | | | |_) | | +- * | (__| |_| | _ <| |___ +- * \___|\___/|_| \_\_____| +- * +- * Copyright (C) 1998 - 2006, Daniel Stenberg, , et al. +- * +- * This software is licensed as described in the file COPYING, which +- * you should have received as part of this distribution. The terms +- * are also available at http://curl.haxx.se/docs/copyright.html. +- * +- * You may opt to use, copy, modify, merge, publish, distribute and/or sell +- * copies of the Software, and permit persons to whom the Software is +- * furnished to do so, under the terms of the COPYING file. +- * +- * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY +- * KIND, either express or implied. +- * +- * $Id: mprintf.h,v 1.16 2008-05-20 10:21:50 patrickm Exp $ +- ***************************************************************************/ +- +-#include +-#include /* needed for FILE */ +- +-#include "curl.h" +- +-#ifdef __cplusplus +-extern "C" { +-#endif +- +-CURL_EXTERN int curl_mprintf(const char *format, ...); +-CURL_EXTERN int curl_mfprintf(FILE *fd, const char *format, ...); +-CURL_EXTERN int curl_msprintf(char *buffer, const char *format, ...); +-CURL_EXTERN int curl_msnprintf(char *buffer, size_t maxlength, +- const char *format, ...); +-CURL_EXTERN int curl_mvprintf(const char *format, va_list args); +-CURL_EXTERN int curl_mvfprintf(FILE *fd, const char *format, va_list args); +-CURL_EXTERN int curl_mvsprintf(char *buffer, const char *format, va_list args); +-CURL_EXTERN int curl_mvsnprintf(char *buffer, size_t maxlength, +- const char *format, va_list args); +-CURL_EXTERN char *curl_maprintf(const char *format, ...); +-CURL_EXTERN char *curl_mvaprintf(const char *format, va_list args); +- +-#ifdef _MPRINTF_REPLACE +-# undef printf +-# undef fprintf +-# undef sprintf +-# undef vsprintf +-# undef snprintf +-# undef vprintf +-# undef vfprintf +-# undef vsnprintf +-# undef aprintf +-# undef vaprintf +-# define printf curl_mprintf +-# define fprintf curl_mfprintf +-#ifdef CURLDEBUG +-/* When built with CURLDEBUG we define away the sprintf() functions since we +- don't want internal code to be using them */ +-# define sprintf sprintf_was_used +-# define vsprintf vsprintf_was_used +-#else +-# define sprintf curl_msprintf +-# define vsprintf curl_mvsprintf +-#endif +-# define snprintf curl_msnprintf +-# define vprintf curl_mvprintf +-# define vfprintf curl_mvfprintf +-# define vsnprintf curl_mvsnprintf +-# define aprintf curl_maprintf +-# define vaprintf curl_mvaprintf +-#endif +- +-#ifdef __cplusplus +-} +-#endif +- +-#endif /* __CURL_MPRINTF_H */ +diff --git a/src/third_party/curl/multi.h b/src/third_party/curl/multi.h +deleted file mode 100644 +index 153f7721..00000000 +--- a/src/third_party/curl/multi.h ++++ /dev/null +@@ -1,346 +0,0 @@ +-#ifndef __CURL_MULTI_H +-#define __CURL_MULTI_H +-/*************************************************************************** +- * _ _ ____ _ +- * Project ___| | | | _ \| | +- * / __| | | | |_) | | +- * | (__| |_| | _ <| |___ +- * \___|\___/|_| \_\_____| +- * +- * Copyright (C) 1998 - 2007, Daniel Stenberg, , et al. +- * +- * This software is licensed as described in the file COPYING, which +- * you should have received as part of this distribution. The terms +- * are also available at http://curl.haxx.se/docs/copyright.html. +- * +- * You may opt to use, copy, modify, merge, publish, distribute and/or sell +- * copies of the Software, and permit persons to whom the Software is +- * furnished to do so, under the terms of the COPYING file. +- * +- * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY +- * KIND, either express or implied. +- * +- * $Id: multi.h,v 1.45 2008-05-20 10:21:50 patrickm Exp $ +- ***************************************************************************/ +-/* +- This is an "external" header file. Don't give away any internals here! +- +- GOALS +- +- o Enable a "pull" interface. The application that uses libcurl decides where +- and when to ask libcurl to get/send data. +- +- o Enable multiple simultaneous transfers in the same thread without making it +- complicated for the application. +- +- o Enable the application to select() on its own file descriptors and curl's +- file descriptors simultaneous easily. +- +-*/ +- +-/* +- * This header file should not really need to include "curl.h" since curl.h +- * itself includes this file and we expect user applications to do #include +- * without the need for especially including multi.h. +- * +- * For some reason we added this include here at one point, and rather than to +- * break existing (wrongly written) libcurl applications, we leave it as-is +- * but with this warning attached. +- */ +-#include "curl.h" +- +-#ifdef __cplusplus +-extern "C" { +-#endif +- +-typedef void CURLM; +- +-typedef enum { +- CURLM_CALL_MULTI_PERFORM = -1, /* please call curl_multi_perform() or +- curl_multi_socket*() soon */ +- CURLM_OK, +- CURLM_BAD_HANDLE, /* the passed-in handle is not a valid CURLM handle */ +- CURLM_BAD_EASY_HANDLE, /* an easy handle was not good/valid */ +- CURLM_OUT_OF_MEMORY, /* if you ever get this, you're in deep sh*t */ +- CURLM_INTERNAL_ERROR, /* this is a libcurl bug */ +- CURLM_BAD_SOCKET, /* the passed in socket argument did not match */ +- CURLM_UNKNOWN_OPTION, /* curl_multi_setopt() with unsupported option */ +- CURLM_LAST +-} CURLMcode; +- +-/* just to make code nicer when using curl_multi_socket() you can now check +- for CURLM_CALL_MULTI_SOCKET too in the same style it works for +- curl_multi_perform() and CURLM_CALL_MULTI_PERFORM */ +-#define CURLM_CALL_MULTI_SOCKET CURLM_CALL_MULTI_PERFORM +- +-typedef enum { +- CURLMSG_NONE, /* first, not used */ +- CURLMSG_DONE, /* This easy handle has completed. 'result' contains +- the CURLcode of the transfer */ +- CURLMSG_LAST /* last, not used */ +-} CURLMSG; +- +-struct CURLMsg { +- CURLMSG msg; /* what this message means */ +- CURL *easy_handle; /* the handle it concerns */ +- union { +- void *whatever; /* message-specific data */ +- CURLcode result; /* return code for transfer */ +- } data; +-}; +-typedef struct CURLMsg CURLMsg; +- +-/* +- * Name: curl_multi_init() +- * +- * Desc: inititalize multi-style curl usage +- * +- * Returns: a new CURLM handle to use in all 'curl_multi' functions. +- */ +-CURL_EXTERN CURLM *curl_multi_init(void); +- +-/* +- * Name: curl_multi_add_handle() +- * +- * Desc: add a standard curl handle to the multi stack +- * +- * Returns: CURLMcode type, general multi error code. +- */ +-CURL_EXTERN CURLMcode curl_multi_add_handle(CURLM *multi_handle, +- CURL *curl_handle); +- +- /* +- * Name: curl_multi_remove_handle() +- * +- * Desc: removes a curl handle from the multi stack again +- * +- * Returns: CURLMcode type, general multi error code. +- */ +-CURL_EXTERN CURLMcode curl_multi_remove_handle(CURLM *multi_handle, +- CURL *curl_handle); +- +- /* +- * Name: curl_multi_fdset() +- * +- * Desc: Ask curl for its fd_set sets. The app can use these to select() or +- * poll() on. We want curl_multi_perform() called as soon as one of +- * them are ready. +- * +- * Returns: CURLMcode type, general multi error code. +- */ +-CURL_EXTERN CURLMcode curl_multi_fdset(CURLM *multi_handle, +- fd_set *read_fd_set, +- fd_set *write_fd_set, +- fd_set *exc_fd_set, +- int *max_fd); +- +- /* +- * Name: curl_multi_perform() +- * +- * Desc: When the app thinks there's data available for curl it calls this +- * function to read/write whatever there is right now. This returns +- * as soon as the reads and writes are done. This function does not +- * require that there actually is data available for reading or that +- * data can be written, it can be called just in case. It returns +- * the number of handles that still transfer data in the second +- * argument's integer-pointer. +- * +- * Returns: CURLMcode type, general multi error code. *NOTE* that this only +- * returns errors etc regarding the whole multi stack. There might +- * still have occurred problems on invidual transfers even when this +- * returns OK. +- */ +-CURL_EXTERN CURLMcode curl_multi_perform(CURLM *multi_handle, +- int *running_handles); +- +- /* +- * Name: curl_multi_cleanup() +- * +- * Desc: Cleans up and removes a whole multi stack. It does not free or +- * touch any individual easy handles in any way. We need to define +- * in what state those handles will be if this function is called +- * in the middle of a transfer. +- * +- * Returns: CURLMcode type, general multi error code. +- */ +-CURL_EXTERN CURLMcode curl_multi_cleanup(CURLM *multi_handle); +- +-/* +- * Name: curl_multi_info_read() +- * +- * Desc: Ask the multi handle if there's any messages/informationals from +- * the individual transfers. Messages include informationals such as +- * error code from the transfer or just the fact that a transfer is +- * completed. More details on these should be written down as well. +- * +- * Repeated calls to this function will return a new struct each +- * time, until a special "end of msgs" struct is returned as a signal +- * that there is no more to get at this point. +- * +- * The data the returned pointer points to will not survive calling +- * curl_multi_cleanup(). +- * +- * The 'CURLMsg' struct is meant to be very simple and only contain +- * very basic informations. If more involved information is wanted, +- * we will provide the particular "transfer handle" in that struct +- * and that should/could/would be used in subsequent +- * curl_easy_getinfo() calls (or similar). The point being that we +- * must never expose complex structs to applications, as then we'll +- * undoubtably get backwards compatibility problems in the future. +- * +- * Returns: A pointer to a filled-in struct, or NULL if it failed or ran out +- * of structs. It also writes the number of messages left in the +- * queue (after this read) in the integer the second argument points +- * to. +- */ +-CURL_EXTERN CURLMsg *curl_multi_info_read(CURLM *multi_handle, +- int *msgs_in_queue); +- +-/* +- * Name: curl_multi_strerror() +- * +- * Desc: The curl_multi_strerror function may be used to turn a CURLMcode +- * value into the equivalent human readable error string. This is +- * useful for printing meaningful error messages. +- * +- * Returns: A pointer to a zero-terminated error message. +- */ +-CURL_EXTERN const char *curl_multi_strerror(CURLMcode); +- +-/* +- * Name: curl_multi_socket() and +- * curl_multi_socket_all() +- * +- * Desc: An alternative version of curl_multi_perform() that allows the +- * application to pass in one of the file descriptors that have been +- * detected to have "action" on them and let libcurl perform. +- * See man page for details. +- */ +-#define CURL_POLL_NONE 0 +-#define CURL_POLL_IN 1 +-#define CURL_POLL_OUT 2 +-#define CURL_POLL_INOUT 3 +-#define CURL_POLL_REMOVE 4 +- +-#define CURL_SOCKET_TIMEOUT CURL_SOCKET_BAD +- +-#define CURL_CSELECT_IN 0x01 +-#define CURL_CSELECT_OUT 0x02 +-#define CURL_CSELECT_ERR 0x04 +- +-typedef int (*curl_socket_callback)(CURL *easy, /* easy handle */ +- curl_socket_t s, /* socket */ +- int what, /* see above */ +- void *userp, /* private callback +- pointer */ +- void *socketp); /* private socket +- pointer */ +-/* +- * Name: curl_multi_timer_callback +- * +- * Desc: Called by libcurl whenever the library detects a change in the +- * maximum number of milliseconds the app is allowed to wait before +- * curl_multi_socket() or curl_multi_perform() must be called +- * (to allow libcurl's timed events to take place). +- * +- * Returns: The callback should return zero. +- */ +-typedef int (*curl_multi_timer_callback)(CURLM *multi, /* multi handle */ +- long timeout_ms, /* see above */ +- void *userp); /* private callback +- pointer */ +- +-CURL_EXTERN CURLMcode curl_multi_socket(CURLM *multi_handle, curl_socket_t s, +- int *running_handles); +- +-CURL_EXTERN CURLMcode curl_multi_socket_action(CURLM *multi_handle, +- curl_socket_t s, +- int ev_bitmask, +- int *running_handles); +- +-CURL_EXTERN CURLMcode curl_multi_socket_all(CURLM *multi_handle, +- int *running_handles); +- +-#ifndef CURL_ALLOW_OLD_MULTI_SOCKET +-/* This macro below was added in 7.16.3 to push users who recompile to use +- the new curl_multi_socket_action() instead of the old curl_multi_socket() +-*/ +-#define curl_multi_socket(x,y,z) curl_multi_socket_action(x,y,0,z) +-#endif +- +-/* +- * Name: curl_multi_timeout() +- * +- * Desc: Returns the maximum number of milliseconds the app is allowed to +- * wait before curl_multi_socket() or curl_multi_perform() must be +- * called (to allow libcurl's timed events to take place). +- * +- * Returns: CURLM error code. +- */ +-CURL_EXTERN CURLMcode curl_multi_timeout(CURLM *multi_handle, +- long *milliseconds); +- +-#undef CINIT /* re-using the same name as in curl.h */ +- +-#ifdef CURL_ISOCPP +-#define CINIT(name,type,num) CURLMOPT_ ## name = CURLOPTTYPE_ ## type + num +-#else +-/* The macro "##" is ISO C, we assume pre-ISO C doesn't support it. */ +-#define LONG CURLOPTTYPE_LONG +-#define OBJECTPOINT CURLOPTTYPE_OBJECTPOINT +-#define FUNCTIONPOINT CURLOPTTYPE_FUNCTIONPOINT +-#define OFF_T CURLOPTTYPE_OFF_T +-#define CINIT(name,type,number) CURLMOPT_/**/name = type + number +-#endif +- +-typedef enum { +- /* This is the socket callback function pointer */ +- CINIT(SOCKETFUNCTION, FUNCTIONPOINT, 1), +- +- /* This is the argument passed to the socket callback */ +- CINIT(SOCKETDATA, OBJECTPOINT, 2), +- +- /* set to 1 to enable pipelining for this multi handle */ +- CINIT(PIPELINING, LONG, 3), +- +- /* This is the timer callback function pointer */ +- CINIT(TIMERFUNCTION, FUNCTIONPOINT, 4), +- +- /* This is the argument passed to the timer callback */ +- CINIT(TIMERDATA, OBJECTPOINT, 5), +- +- /* maximum number of entries in the connection cache */ +- CINIT(MAXCONNECTS, LONG, 6), +- +- CURLMOPT_LASTENTRY /* the last unused */ +-} CURLMoption; +- +- +-/* +- * Name: curl_multi_setopt() +- * +- * Desc: Sets options for the multi handle. +- * +- * Returns: CURLM error code. +- */ +-CURL_EXTERN CURLMcode curl_multi_setopt(CURLM *multi_handle, +- CURLMoption option, ...); +- +- +-/* +- * Name: curl_multi_assign() +- * +- * Desc: This function sets an association in the multi handle between the +- * given socket and a private pointer of the application. This is +- * (only) useful for curl_multi_socket uses. +- * +- * Returns: CURLM error code. +- */ +-CURL_EXTERN CURLMcode curl_multi_assign(CURLM *multi_handle, +- curl_socket_t sockfd, void *sockp); +- +-#ifdef __cplusplus +-} /* end of extern "C" */ +-#endif +- +-#endif +diff --git a/src/third_party/curl/stdcheaders.h b/src/third_party/curl/stdcheaders.h +deleted file mode 100644 +index f739d7f9..00000000 +--- a/src/third_party/curl/stdcheaders.h ++++ /dev/null +@@ -1,34 +0,0 @@ +-#ifndef __STDC_HEADERS_H +-#define __STDC_HEADERS_H +-/*************************************************************************** +- * _ _ ____ _ +- * Project ___| | | | _ \| | +- * / __| | | | |_) | | +- * | (__| |_| | _ <| |___ +- * \___|\___/|_| \_\_____| +- * +- * Copyright (C) 1998 - 2009, Daniel Stenberg, , et al. +- * +- * This software is licensed as described in the file COPYING, which +- * you should have received as part of this distribution. The terms +- * are also available at http://curl.haxx.se/docs/copyright.html. +- * +- * You may opt to use, copy, modify, merge, publish, distribute and/or sell +- * copies of the Software, and permit persons to whom the Software is +- * furnished to do so, under the terms of the COPYING file. +- * +- * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY +- * KIND, either express or implied. +- * +- * $Id: stdcheaders.h,v 1.9 2009-05-18 12:25:45 yangtse Exp $ +- ***************************************************************************/ +- +-#include +- +-size_t fread (void *, size_t, size_t, FILE *); +-size_t fwrite (const void *, size_t, size_t, FILE *); +- +-int strcasecmp(const char *, const char *); +-int strncasecmp(const char *, const char *, size_t); +- +-#endif +diff --git a/src/third_party/curl/typecheck-gcc.h b/src/third_party/curl/typecheck-gcc.h +deleted file mode 100644 +index 97883058..00000000 +--- a/src/third_party/curl/typecheck-gcc.h ++++ /dev/null +@@ -1,551 +0,0 @@ +-#ifndef __CURL_TYPECHECK_GCC_H +-#define __CURL_TYPECHECK_GCC_H +-/*************************************************************************** +- * _ _ ____ _ +- * Project ___| | | | _ \| | +- * / __| | | | |_) | | +- * | (__| |_| | _ <| |___ +- * \___|\___/|_| \_\_____| +- * +- * Copyright (C) 1998 - 2009, Daniel Stenberg, , et al. +- * +- * This software is licensed as described in the file COPYING, which +- * you should have received as part of this distribution. The terms +- * are also available at http://curl.haxx.se/docs/copyright.html. +- * +- * You may opt to use, copy, modify, merge, publish, distribute and/or sell +- * copies of the Software, and permit persons to whom the Software is +- * furnished to do so, under the terms of the COPYING file. +- * +- * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY +- * KIND, either express or implied. +- * +- * $Id: typecheck-gcc.h,v 1.9 2009-01-25 23:26:31 bagder Exp $ +- ***************************************************************************/ +- +-/* wraps curl_easy_setopt() with typechecking */ +- +-/* To add a new kind of warning, add an +- * if(_curl_is_sometype_option(_curl_opt) && ! _curl_is_sometype(value)) +- * _curl_easy_setopt_err_sometype(); +- * block and define _curl_is_sometype_option, _curl_is_sometype and +- * _curl_easy_setopt_err_sometype below +- * +- * To add an option that uses the same type as an existing option, you'll just +- * need to extend the appropriate _curl_*_option macro +- */ +-#define curl_easy_setopt(handle, option, value) \ +-__extension__ ({ \ +- __typeof__ (option) _curl_opt = option; \ +- if (__builtin_constant_p(_curl_opt)) { \ +- if (_curl_is_long_option(_curl_opt) && !_curl_is_long(value)) \ +- _curl_easy_setopt_err_long(); \ +- if (_curl_is_off_t_option(_curl_opt) && !_curl_is_off_t(value)) \ +- _curl_easy_setopt_err_curl_off_t(); \ +- if (_curl_is_string_option(_curl_opt) && !_curl_is_string(value)) \ +- _curl_easy_setopt_err_string(); \ +- if (_curl_is_write_cb_option(_curl_opt) && !_curl_is_write_cb(value)) \ +- _curl_easy_setopt_err_write_callback(); \ +- if ((_curl_opt) == CURLOPT_READFUNCTION && !_curl_is_read_cb(value)) \ +- _curl_easy_setopt_err_read_cb(); \ +- if ((_curl_opt) == CURLOPT_IOCTLFUNCTION && !_curl_is_ioctl_cb(value)) \ +- _curl_easy_setopt_err_ioctl_cb(); \ +- if ((_curl_opt) == CURLOPT_SOCKOPTFUNCTION && !_curl_is_sockopt_cb(value))\ +- _curl_easy_setopt_err_sockopt_cb(); \ +- if ((_curl_opt) == CURLOPT_OPENSOCKETFUNCTION && \ +- !_curl_is_opensocket_cb(value)) \ +- _curl_easy_setopt_err_opensocket_cb(); \ +- if ((_curl_opt) == CURLOPT_PROGRESSFUNCTION && \ +- !_curl_is_progress_cb(value)) \ +- _curl_easy_setopt_err_progress_cb(); \ +- if ((_curl_opt) == CURLOPT_DEBUGFUNCTION && !_curl_is_debug_cb(value)) \ +- _curl_easy_setopt_err_debug_cb(); \ +- if ((_curl_opt) == CURLOPT_SSL_CTX_FUNCTION && \ +- !_curl_is_ssl_ctx_cb(value)) \ +- _curl_easy_setopt_err_ssl_ctx_cb(); \ +- if (_curl_is_conv_cb_option(_curl_opt) && !_curl_is_conv_cb(value)) \ +- _curl_easy_setopt_err_conv_cb(); \ +- if ((_curl_opt) == CURLOPT_SEEKFUNCTION && !_curl_is_seek_cb(value)) \ +- _curl_easy_setopt_err_seek_cb(); \ +- if (_curl_is_cb_data_option(_curl_opt) && !_curl_is_cb_data(value)) \ +- _curl_easy_setopt_err_cb_data(); \ +- if ((_curl_opt) == CURLOPT_ERRORBUFFER && !_curl_is_error_buffer(value)) \ +- _curl_easy_setopt_err_error_buffer(); \ +- if ((_curl_opt) == CURLOPT_STDERR && !_curl_is_FILE(value)) \ +- _curl_easy_setopt_err_FILE(); \ +- if (_curl_is_postfields_option(_curl_opt) && !_curl_is_postfields(value)) \ +- _curl_easy_setopt_err_postfields(); \ +- if ((_curl_opt) == CURLOPT_HTTPPOST && \ +- !_curl_is_arr((value), struct curl_httppost)) \ +- _curl_easy_setopt_err_curl_httpost(); \ +- if (_curl_is_slist_option(_curl_opt) && \ +- !_curl_is_arr((value), struct curl_slist)) \ +- _curl_easy_setopt_err_curl_slist(); \ +- if ((_curl_opt) == CURLOPT_SHARE && !_curl_is_ptr((value), CURLSH)) \ +- _curl_easy_setopt_err_CURLSH(); \ +- } \ +- curl_easy_setopt(handle, _curl_opt, value); \ +-}) +- +-/* wraps curl_easy_getinfo() with typechecking */ +-/* FIXME: don't allow const pointers */ +-#define curl_easy_getinfo(handle, info, arg) \ +-__extension__ ({ \ +- __typeof__ (info) _curl_info = info; \ +- if (__builtin_constant_p(_curl_info)) { \ +- if (_curl_is_string_info(_curl_info) && !_curl_is_arr((arg), char *)) \ +- _curl_easy_getinfo_err_string(); \ +- if (_curl_is_long_info(_curl_info) && !_curl_is_arr((arg), long)) \ +- _curl_easy_getinfo_err_long(); \ +- if (_curl_is_double_info(_curl_info) && !_curl_is_arr((arg), double)) \ +- _curl_easy_getinfo_err_double(); \ +- if (_curl_is_slist_info(_curl_info) && \ +- !_curl_is_arr((arg), struct curl_slist *)) \ +- _curl_easy_getinfo_err_curl_slist(); \ +- } \ +- curl_easy_getinfo(handle, _curl_info, arg); \ +-}) +- +-/* TODO: typechecking for curl_share_setopt() and curl_multi_setopt(), +- * for now just make sure that the functions are called with three +- * arguments +- */ +-#define curl_share_setopt(share,opt,param) curl_share_setopt(share,opt,param) +-#define curl_multi_setopt(handle,opt,param) curl_multi_setopt(handle,opt,param) +- +- +-/* the actual warnings, triggered by calling the _curl_easy_setopt_err* +- * functions */ +- +-/* To define a new warning, use _CURL_WARNING(identifier, "message") */ +-#define _CURL_WARNING(id, message) \ +- static void __attribute__((warning(message))) __attribute__((unused)) \ +- __attribute__((noinline)) id(void) { __asm__(""); } +- +-_CURL_WARNING(_curl_easy_setopt_err_long, +- "curl_easy_setopt expects a long argument for this option") +-_CURL_WARNING(_curl_easy_setopt_err_curl_off_t, +- "curl_easy_setopt expects a curl_off_t argument for this option") +-_CURL_WARNING(_curl_easy_setopt_err_string, +- "curl_easy_setopt expects a string (char* or char[]) argument for this option" +- ) +-_CURL_WARNING(_curl_easy_setopt_err_write_callback, +- "curl_easy_setopt expects a curl_write_callback argument for this option") +-_CURL_WARNING(_curl_easy_setopt_err_read_cb, +- "curl_easy_setopt expects a curl_read_callback argument for this option") +-_CURL_WARNING(_curl_easy_setopt_err_ioctl_cb, +- "curl_easy_setopt expects a curl_ioctl_callback argument for this option") +-_CURL_WARNING(_curl_easy_setopt_err_sockopt_cb, +- "curl_easy_setopt expects a curl_sockopt_callback argument for this option") +-_CURL_WARNING(_curl_easy_setopt_err_opensocket_cb, +- "curl_easy_setopt expects a curl_opensocket_callback argument for this option" +- ) +-_CURL_WARNING(_curl_easy_setopt_err_progress_cb, +- "curl_easy_setopt expects a curl_progress_callback argument for this option") +-_CURL_WARNING(_curl_easy_setopt_err_debug_cb, +- "curl_easy_setopt expects a curl_debug_callback argument for this option") +-_CURL_WARNING(_curl_easy_setopt_err_ssl_ctx_cb, +- "curl_easy_setopt expects a curl_ssl_ctx_callback argument for this option") +-_CURL_WARNING(_curl_easy_setopt_err_conv_cb, +- "curl_easy_setopt expects a curl_conv_callback argument for this option") +-_CURL_WARNING(_curl_easy_setopt_err_seek_cb, +- "curl_easy_setopt expects a curl_seek_callback argument for this option") +-_CURL_WARNING(_curl_easy_setopt_err_cb_data, +- "curl_easy_setopt expects a private data pointer as argument for this option") +-_CURL_WARNING(_curl_easy_setopt_err_error_buffer, +- "curl_easy_setopt expects a char buffer of CURL_ERROR_SIZE as argument for this option") +-_CURL_WARNING(_curl_easy_setopt_err_FILE, +- "curl_easy_setopt expects a FILE* argument for this option") +-_CURL_WARNING(_curl_easy_setopt_err_postfields, +- "curl_easy_setopt expects a void* or char* argument for this option") +-_CURL_WARNING(_curl_easy_setopt_err_curl_httpost, +- "curl_easy_setopt expects a struct curl_httppost* argument for this option") +-_CURL_WARNING(_curl_easy_setopt_err_curl_slist, +- "curl_easy_setopt expects a struct curl_slist* argument for this option") +-_CURL_WARNING(_curl_easy_setopt_err_CURLSH, +- "curl_easy_setopt expects a CURLSH* argument for this option") +- +-_CURL_WARNING(_curl_easy_getinfo_err_string, +- "curl_easy_getinfo expects a pointer to char * for this info") +-_CURL_WARNING(_curl_easy_getinfo_err_long, +- "curl_easy_getinfo expects a pointer to long for this info") +-_CURL_WARNING(_curl_easy_getinfo_err_double, +- "curl_easy_getinfo expects a pointer to double for this info") +-_CURL_WARNING(_curl_easy_getinfo_err_curl_slist, +- "curl_easy_getinfo expects a pointer to struct curl_slist * for this info") +- +-/* groups of curl_easy_setops options that take the same type of argument */ +- +-/* To add a new option to one of the groups, just add +- * (option) == CURLOPT_SOMETHING +- * to the or-expression. If the option takes a long or curl_off_t, you don't +- * have to do anything +- */ +- +-/* evaluates to true if option takes a long argument */ +-#define _curl_is_long_option(option) \ +- (0 < (option) && (option) < CURLOPTTYPE_OBJECTPOINT) +- +-#define _curl_is_off_t_option(option) \ +- ((option) > CURLOPTTYPE_OFF_T) +- +-/* evaluates to true if option takes a char* argument */ +-#define _curl_is_string_option(option) \ +- ((option) == CURLOPT_URL || \ +- (option) == CURLOPT_PROXY || \ +- (option) == CURLOPT_INTERFACE || \ +- (option) == CURLOPT_NETRC_FILE || \ +- (option) == CURLOPT_USERPWD || \ +- (option) == CURLOPT_USERNAME || \ +- (option) == CURLOPT_PASSWORD || \ +- (option) == CURLOPT_PROXYUSERPWD || \ +- (option) == CURLOPT_PROXYUSERNAME || \ +- (option) == CURLOPT_PROXYPASSWORD || \ +- (option) == CURLOPT_NOPROXY || \ +- (option) == CURLOPT_ENCODING || \ +- (option) == CURLOPT_REFERER || \ +- (option) == CURLOPT_USERAGENT || \ +- (option) == CURLOPT_COOKIE || \ +- (option) == CURLOPT_COOKIEFILE || \ +- (option) == CURLOPT_COOKIEJAR || \ +- (option) == CURLOPT_COOKIELIST || \ +- (option) == CURLOPT_FTPPORT || \ +- (option) == CURLOPT_FTP_ALTERNATIVE_TO_USER || \ +- (option) == CURLOPT_FTP_ACCOUNT || \ +- (option) == CURLOPT_RANGE || \ +- (option) == CURLOPT_CUSTOMREQUEST || \ +- (option) == CURLOPT_SSLCERT || \ +- (option) == CURLOPT_SSLCERTTYPE || \ +- (option) == CURLOPT_SSLKEY || \ +- (option) == CURLOPT_SSLKEYTYPE || \ +- (option) == CURLOPT_KEYPASSWD || \ +- (option) == CURLOPT_SSLENGINE || \ +- (option) == CURLOPT_CAINFO || \ +- (option) == CURLOPT_CAPATH || \ +- (option) == CURLOPT_RANDOM_FILE || \ +- (option) == CURLOPT_EGDSOCKET || \ +- (option) == CURLOPT_SSL_CIPHER_LIST || \ +- (option) == CURLOPT_KRBLEVEL || \ +- (option) == CURLOPT_SSH_HOST_PUBLIC_KEY_MD5 || \ +- (option) == CURLOPT_SSH_PUBLIC_KEYFILE || \ +- (option) == CURLOPT_SSH_PRIVATE_KEYFILE || \ +- (option) == CURLOPT_CRLFILE || \ +- (option) == CURLOPT_ISSUERCERT || \ +- 0) +- +-/* evaluates to true if option takes a curl_write_callback argument */ +-#define _curl_is_write_cb_option(option) \ +- ((option) == CURLOPT_HEADERFUNCTION || \ +- (option) == CURLOPT_WRITEFUNCTION) +- +-/* evaluates to true if option takes a curl_conv_callback argument */ +-#define _curl_is_conv_cb_option(option) \ +- ((option) == CURLOPT_CONV_TO_NETWORK_FUNCTION || \ +- (option) == CURLOPT_CONV_FROM_NETWORK_FUNCTION || \ +- (option) == CURLOPT_CONV_FROM_UTF8_FUNCTION) +- +-/* evaluates to true if option takes a data argument to pass to a callback */ +-#define _curl_is_cb_data_option(option) \ +- ((option) == CURLOPT_WRITEDATA || \ +- (option) == CURLOPT_READDATA || \ +- (option) == CURLOPT_IOCTLDATA || \ +- (option) == CURLOPT_SOCKOPTDATA || \ +- (option) == CURLOPT_OPENSOCKETDATA || \ +- (option) == CURLOPT_PROGRESSDATA || \ +- (option) == CURLOPT_WRITEHEADER || \ +- (option) == CURLOPT_DEBUGDATA || \ +- (option) == CURLOPT_SSL_CTX_DATA || \ +- (option) == CURLOPT_SEEKDATA || \ +- (option) == CURLOPT_PRIVATE || \ +- 0) +- +-/* evaluates to true if option takes a POST data argument (void* or char*) */ +-#define _curl_is_postfields_option(option) \ +- ((option) == CURLOPT_POSTFIELDS || \ +- (option) == CURLOPT_COPYPOSTFIELDS || \ +- 0) +- +-/* evaluates to true if option takes a struct curl_slist * argument */ +-#define _curl_is_slist_option(option) \ +- ((option) == CURLOPT_HTTPHEADER || \ +- (option) == CURLOPT_HTTP200ALIASES || \ +- (option) == CURLOPT_QUOTE || \ +- (option) == CURLOPT_POSTQUOTE || \ +- (option) == CURLOPT_PREQUOTE || \ +- (option) == CURLOPT_TELNETOPTIONS || \ +- 0) +- +-/* groups of curl_easy_getinfo infos that take the same type of argument */ +- +-/* evaluates to true if info expects a pointer to char * argument */ +-#define _curl_is_string_info(info) \ +- (CURLINFO_STRING < (info) && (info) < CURLINFO_LONG) +- +-/* evaluates to true if info expects a pointer to long argument */ +-#define _curl_is_long_info(info) \ +- (CURLINFO_LONG < (info) && (info) < CURLINFO_DOUBLE) +- +-/* evaluates to true if info expects a pointer to double argument */ +-#define _curl_is_double_info(info) \ +- (CURLINFO_DOUBLE < (info) && (info) < CURLINFO_SLIST) +- +-/* true if info expects a pointer to struct curl_slist * argument */ +-#define _curl_is_slist_info(info) \ +- (CURLINFO_SLIST < (info)) +- +- +-/* typecheck helpers -- check whether given expression has requested type*/ +- +-/* For pointers, you can use the _curl_is_ptr/_curl_is_arr macros, +- * otherwise define a new macro. Search for __builtin_types_compatible_p +- * in the GCC manual. +- * NOTE: these macros MUST NOT EVALUATE their arguments! The argument is +- * the actual expression passed to the curl_easy_setopt macro. This +- * means that you can only apply the sizeof and __typeof__ operators, no +- * == or whatsoever. +- */ +- +-/* XXX: should evaluate to true iff expr is a pointer */ +-#define _curl_is_any_ptr(expr) \ +- (sizeof(expr) == sizeof(void*)) +- +-/* evaluates to true if expr is NULL */ +-/* XXX: must not evaluate expr, so this check is not accurate */ +-#define _curl_is_NULL(expr) \ +- (__builtin_types_compatible_p(__typeof__(expr), __typeof__(NULL))) +- +-/* evaluates to true if expr is type*, const type* or NULL */ +-#define _curl_is_ptr(expr, type) \ +- (_curl_is_NULL(expr) || \ +- __builtin_types_compatible_p(__typeof__(expr), type *) || \ +- __builtin_types_compatible_p(__typeof__(expr), const type *)) +- +-/* evaluates to true if expr is one of type[], type*, NULL or const type* */ +-#define _curl_is_arr(expr, type) \ +- (_curl_is_ptr((expr), type) || \ +- __builtin_types_compatible_p(__typeof__(expr), type [])) +- +-/* evaluates to true if expr is a string */ +-#define _curl_is_string(expr) \ +- (_curl_is_arr((expr), char) || \ +- _curl_is_arr((expr), signed char) || \ +- _curl_is_arr((expr), unsigned char)) +- +-/* evaluates to true if expr is a long (no matter the signedness) +- * XXX: for now, int is also accepted (and therefore short and char, which +- * are promoted to int when passed to a variadic function) */ +-#define _curl_is_long(expr) \ +- (__builtin_types_compatible_p(__typeof__(expr), long) || \ +- __builtin_types_compatible_p(__typeof__(expr), signed long) || \ +- __builtin_types_compatible_p(__typeof__(expr), unsigned long) || \ +- __builtin_types_compatible_p(__typeof__(expr), int) || \ +- __builtin_types_compatible_p(__typeof__(expr), signed int) || \ +- __builtin_types_compatible_p(__typeof__(expr), unsigned int) || \ +- __builtin_types_compatible_p(__typeof__(expr), short) || \ +- __builtin_types_compatible_p(__typeof__(expr), signed short) || \ +- __builtin_types_compatible_p(__typeof__(expr), unsigned short) || \ +- __builtin_types_compatible_p(__typeof__(expr), char) || \ +- __builtin_types_compatible_p(__typeof__(expr), signed char) || \ +- __builtin_types_compatible_p(__typeof__(expr), unsigned char)) +- +-/* evaluates to true if expr is of type curl_off_t */ +-#define _curl_is_off_t(expr) \ +- (__builtin_types_compatible_p(__typeof__(expr), curl_off_t)) +- +-/* evaluates to true if expr is abuffer suitable for CURLOPT_ERRORBUFFER */ +-/* XXX: also check size of an char[] array? */ +-#define _curl_is_error_buffer(expr) \ +- (__builtin_types_compatible_p(__typeof__(expr), char *) || \ +- __builtin_types_compatible_p(__typeof__(expr), char[])) +- +-/* evaluates to true if expr is of type (const) void* or (const) FILE* */ +-#if 0 +-#define _curl_is_cb_data(expr) \ +- (_curl_is_ptr((expr), void) || \ +- _curl_is_ptr((expr), FILE)) +-#else /* be less strict */ +-#define _curl_is_cb_data(expr) \ +- _curl_is_any_ptr(expr) +-#endif +- +-/* evaluates to true if expr is of type FILE* */ +-#define _curl_is_FILE(expr) \ +- (__builtin_types_compatible_p(__typeof__(expr), FILE *)) +- +-/* evaluates to true if expr can be passed as POST data (void* or char*) */ +-#define _curl_is_postfields(expr) \ +- (_curl_is_ptr((expr), void) || \ +- _curl_is_arr((expr), char)) +- +-/* FIXME: the whole callback checking is messy... +- * The idea is to tolerate char vs. void and const vs. not const +- * pointers in arguments at least +- */ +-/* helper: __builtin_types_compatible_p distinguishes between functions and +- * function pointers, hide it */ +-#define _curl_callback_compatible(func, type) \ +- (__builtin_types_compatible_p(__typeof__(func), type) || \ +- __builtin_types_compatible_p(__typeof__(func), type*)) +- +-/* evaluates to true if expr is of type curl_read_callback or "similar" */ +-#define _curl_is_read_cb(expr) \ +- (_curl_is_NULL(expr) || \ +- __builtin_types_compatible_p(__typeof__(expr), __typeof__(fread)) || \ +- __builtin_types_compatible_p(__typeof__(expr), curl_read_callback) || \ +- _curl_callback_compatible((expr), _curl_read_callback1) || \ +- _curl_callback_compatible((expr), _curl_read_callback2) || \ +- _curl_callback_compatible((expr), _curl_read_callback3) || \ +- _curl_callback_compatible((expr), _curl_read_callback4) || \ +- _curl_callback_compatible((expr), _curl_read_callback5) || \ +- _curl_callback_compatible((expr), _curl_read_callback6)) +-typedef size_t (_curl_read_callback1)(char *, size_t, size_t, void*); +-typedef size_t (_curl_read_callback2)(char *, size_t, size_t, const void*); +-typedef size_t (_curl_read_callback3)(char *, size_t, size_t, FILE*); +-typedef size_t (_curl_read_callback4)(void *, size_t, size_t, void*); +-typedef size_t (_curl_read_callback5)(void *, size_t, size_t, const void*); +-typedef size_t (_curl_read_callback6)(void *, size_t, size_t, FILE*); +- +-/* evaluates to true if expr is of type curl_write_callback or "similar" */ +-#define _curl_is_write_cb(expr) \ +- (_curl_is_read_cb(expr) || \ +- __builtin_types_compatible_p(__typeof__(expr), __typeof__(fwrite)) || \ +- __builtin_types_compatible_p(__typeof__(expr), curl_write_callback) || \ +- _curl_callback_compatible((expr), _curl_write_callback1) || \ +- _curl_callback_compatible((expr), _curl_write_callback2) || \ +- _curl_callback_compatible((expr), _curl_write_callback3) || \ +- _curl_callback_compatible((expr), _curl_write_callback4) || \ +- _curl_callback_compatible((expr), _curl_write_callback5) || \ +- _curl_callback_compatible((expr), _curl_write_callback6)) +-typedef size_t (_curl_write_callback1)(const char *, size_t, size_t, void*); +-typedef size_t (_curl_write_callback2)(const char *, size_t, size_t, +- const void*); +-typedef size_t (_curl_write_callback3)(const char *, size_t, size_t, FILE*); +-typedef size_t (_curl_write_callback4)(const void *, size_t, size_t, void*); +-typedef size_t (_curl_write_callback5)(const void *, size_t, size_t, +- const void*); +-typedef size_t (_curl_write_callback6)(const void *, size_t, size_t, FILE*); +- +-/* evaluates to true if expr is of type curl_ioctl_callback or "similar" */ +-#define _curl_is_ioctl_cb(expr) \ +- (_curl_is_NULL(expr) || \ +- __builtin_types_compatible_p(__typeof__(expr), curl_ioctl_callback) || \ +- _curl_callback_compatible((expr), _curl_ioctl_callback1) || \ +- _curl_callback_compatible((expr), _curl_ioctl_callback2) || \ +- _curl_callback_compatible((expr), _curl_ioctl_callback3) || \ +- _curl_callback_compatible((expr), _curl_ioctl_callback4)) +-typedef curlioerr (_curl_ioctl_callback1)(CURL *, int, void*); +-typedef curlioerr (_curl_ioctl_callback2)(CURL *, int, const void*); +-typedef curlioerr (_curl_ioctl_callback3)(CURL *, curliocmd, void*); +-typedef curlioerr (_curl_ioctl_callback4)(CURL *, curliocmd, const void*); +- +-/* evaluates to true if expr is of type curl_sockopt_callback or "similar" */ +-#define _curl_is_sockopt_cb(expr) \ +- (_curl_is_NULL(expr) || \ +- __builtin_types_compatible_p(__typeof__(expr), curl_sockopt_callback) || \ +- _curl_callback_compatible((expr), _curl_sockopt_callback1) || \ +- _curl_callback_compatible((expr), _curl_sockopt_callback2)) +-typedef int (_curl_sockopt_callback1)(void *, curl_socket_t, curlsocktype); +-typedef int (_curl_sockopt_callback2)(const void *, curl_socket_t, +- curlsocktype); +- +-/* evaluates to true if expr is of type curl_opensocket_callback or "similar" */ +-#define _curl_is_opensocket_cb(expr) \ +- (_curl_is_NULL(expr) || \ +- __builtin_types_compatible_p(__typeof__(expr), curl_opensocket_callback) ||\ +- _curl_callback_compatible((expr), _curl_opensocket_callback1) || \ +- _curl_callback_compatible((expr), _curl_opensocket_callback2) || \ +- _curl_callback_compatible((expr), _curl_opensocket_callback3) || \ +- _curl_callback_compatible((expr), _curl_opensocket_callback4)) +-typedef curl_socket_t (_curl_opensocket_callback1) +- (void *, curlsocktype, struct curl_sockaddr *); +-typedef curl_socket_t (_curl_opensocket_callback2) +- (void *, curlsocktype, const struct curl_sockaddr *); +-typedef curl_socket_t (_curl_opensocket_callback3) +- (const void *, curlsocktype, struct curl_sockaddr *); +-typedef curl_socket_t (_curl_opensocket_callback4) +- (const void *, curlsocktype, const struct curl_sockaddr *); +- +-/* evaluates to true if expr is of type curl_progress_callback or "similar" */ +-#define _curl_is_progress_cb(expr) \ +- (_curl_is_NULL(expr) || \ +- __builtin_types_compatible_p(__typeof__(expr), curl_progress_callback) || \ +- _curl_callback_compatible((expr), _curl_progress_callback1) || \ +- _curl_callback_compatible((expr), _curl_progress_callback2)) +-typedef int (_curl_progress_callback1)(void *, +- double, double, double, double); +-typedef int (_curl_progress_callback2)(const void *, +- double, double, double, double); +- +-/* evaluates to true if expr is of type curl_debug_callback or "similar" */ +-#define _curl_is_debug_cb(expr) \ +- (_curl_is_NULL(expr) || \ +- __builtin_types_compatible_p(__typeof__(expr), curl_debug_callback) || \ +- _curl_callback_compatible((expr), _curl_debug_callback1) || \ +- _curl_callback_compatible((expr), _curl_debug_callback2) || \ +- _curl_callback_compatible((expr), _curl_debug_callback3) || \ +- _curl_callback_compatible((expr), _curl_debug_callback4)) +-typedef int (_curl_debug_callback1) (CURL *, +- curl_infotype, char *, size_t, void *); +-typedef int (_curl_debug_callback2) (CURL *, +- curl_infotype, char *, size_t, const void *); +-typedef int (_curl_debug_callback3) (CURL *, +- curl_infotype, const char *, size_t, void *); +-typedef int (_curl_debug_callback4) (CURL *, +- curl_infotype, const char *, size_t, const void *); +- +-/* evaluates to true if expr is of type curl_ssl_ctx_callback or "similar" */ +-/* this is getting even messier... */ +-#define _curl_is_ssl_ctx_cb(expr) \ +- (_curl_is_NULL(expr) || \ +- __builtin_types_compatible_p(__typeof__(expr), curl_ssl_ctx_callback) || \ +- _curl_callback_compatible((expr), _curl_ssl_ctx_callback1) || \ +- _curl_callback_compatible((expr), _curl_ssl_ctx_callback2) || \ +- _curl_callback_compatible((expr), _curl_ssl_ctx_callback3) || \ +- _curl_callback_compatible((expr), _curl_ssl_ctx_callback4) || \ +- _curl_callback_compatible((expr), _curl_ssl_ctx_callback5) || \ +- _curl_callback_compatible((expr), _curl_ssl_ctx_callback6) || \ +- _curl_callback_compatible((expr), _curl_ssl_ctx_callback7) || \ +- _curl_callback_compatible((expr), _curl_ssl_ctx_callback8)) +-typedef CURLcode (_curl_ssl_ctx_callback1)(CURL *, void *, void *); +-typedef CURLcode (_curl_ssl_ctx_callback2)(CURL *, void *, const void *); +-typedef CURLcode (_curl_ssl_ctx_callback3)(CURL *, const void *, void *); +-typedef CURLcode (_curl_ssl_ctx_callback4)(CURL *, const void *, const void *); +-#ifdef HEADER_SSL_H +-/* hack: if we included OpenSSL's ssl.h, we know about SSL_CTX +- * this will of course break if we're included before OpenSSL headers... +- */ +-typedef CURLcode (_curl_ssl_ctx_callback5)(CURL *, SSL_CTX, void *); +-typedef CURLcode (_curl_ssl_ctx_callback6)(CURL *, SSL_CTX, const void *); +-typedef CURLcode (_curl_ssl_ctx_callback7)(CURL *, const SSL_CTX, void *); +-typedef CURLcode (_curl_ssl_ctx_callback8)(CURL *, const SSL_CTX, const void *); +-#else +-typedef _curl_ssl_ctx_callback1 _curl_ssl_ctx_callback5; +-typedef _curl_ssl_ctx_callback1 _curl_ssl_ctx_callback6; +-typedef _curl_ssl_ctx_callback1 _curl_ssl_ctx_callback7; +-typedef _curl_ssl_ctx_callback1 _curl_ssl_ctx_callback8; +-#endif +- +-/* evaluates to true if expr is of type curl_conv_callback or "similar" */ +-#define _curl_is_conv_cb(expr) \ +- (_curl_is_NULL(expr) || \ +- __builtin_types_compatible_p(__typeof__(expr), curl_conv_callback) || \ +- _curl_callback_compatible((expr), _curl_conv_callback1) || \ +- _curl_callback_compatible((expr), _curl_conv_callback2) || \ +- _curl_callback_compatible((expr), _curl_conv_callback3) || \ +- _curl_callback_compatible((expr), _curl_conv_callback4)) +-typedef CURLcode (*_curl_conv_callback1)(char *, size_t length); +-typedef CURLcode (*_curl_conv_callback2)(const char *, size_t length); +-typedef CURLcode (*_curl_conv_callback3)(void *, size_t length); +-typedef CURLcode (*_curl_conv_callback4)(const void *, size_t length); +- +-/* evaluates to true if expr is of type curl_seek_callback or "similar" */ +-#define _curl_is_seek_cb(expr) \ +- (_curl_is_NULL(expr) || \ +- __builtin_types_compatible_p(__typeof__(expr), curl_seek_callback) || \ +- _curl_callback_compatible((expr), _curl_seek_callback1) || \ +- _curl_callback_compatible((expr), _curl_seek_callback2)) +-typedef CURLcode (*_curl_seek_callback1)(void *, curl_off_t, int); +-typedef CURLcode (*_curl_seek_callback2)(const void *, curl_off_t, int); +- +- +-#endif /* __CURL_TYPECHECK_GCC_H */ +diff --git a/src/third_party/curl/types.h b/src/third_party/curl/types.h +deleted file mode 100644 +index d37d6ae9..00000000 +--- a/src/third_party/curl/types.h ++++ /dev/null +@@ -1 +0,0 @@ +-/* not used */ +-- +2.28.0 + diff --git a/recipes/breakpad/all/patches/0002-Link-minidump_upload-and-sym_upload-with-curl.patch b/recipes/breakpad/all/patches/0002-Link-minidump_upload-and-sym_upload-with-curl.patch new file mode 100644 index 0000000..312e048 --- /dev/null +++ b/recipes/breakpad/all/patches/0002-Link-minidump_upload-and-sym_upload-with-curl.patch @@ -0,0 +1,218 @@ +From b1d502ae57e6ef3538318e72fc925f28b4e1b48a Mon Sep 17 00:00:00 2001 +From: Jon Turney +Date: Sat, 5 Mar 2016 12:48:05 +0000 +Subject: [PATCH 02/19] 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 +--- + 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 dcef735d..904a9a77 100644 +--- a/Makefile.am ++++ b/Makefile.am +@@ -610,7 +610,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 \ +@@ -618,7 +618,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 +-#include + #include + #include + +@@ -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::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(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.28.0 + diff --git a/recipes/breakpad/all/patches/0003-Build-minidump_upload-and-sym_upload-for-all-targets.patch b/recipes/breakpad/all/patches/0003-Build-minidump_upload-and-sym_upload-for-all-targets.patch new file mode 100644 index 0000000..368f744 --- /dev/null +++ b/recipes/breakpad/all/patches/0003-Build-minidump_upload-and-sym_upload-for-all-targets.patch @@ -0,0 +1,85 @@ +From d37f518ac236ce68927177cad84bf153c66ffc3f Mon Sep 17 00:00:00 2001 +From: Jon Turney +Date: Sat, 5 Mar 2016 12:56:22 +0000 +Subject: [PATCH 03/19] Build minidump_upload and sym_upload for all targets + +minidump_upload and sym_upload should probably move from src/tools/linux/ to +a new src/tools/common/, and move linux/http_upload.{cc,.h} up to +src/common/ from src/common/linux/ ? + +Signed-off-by: Jon Turney +--- + Makefile.am | 36 ++++++++++++++++++++---------------- + 1 file changed, 20 insertions(+), 16 deletions(-) + +diff --git a/Makefile.am b/Makefile.am +index 904a9a77..ea82edcd 100644 +--- a/Makefile.am ++++ b/Makefile.am +@@ -346,6 +346,12 @@ bin_PROGRAMS += \ + src/processor/minidump_stackwalk + endif !DISABLE_PROCESSOR + ++if !DISABLE_TOOLS ++bin_PROGRAMS += \ ++ src/tools/linux/symupload/minidump_upload \ ++ src/tools/linux/symupload/sym_upload ++endif ++ + if LINUX_HOST + EXTRA_PROGRAMS += \ + src/client/linux/linux_dumper_unittest_helper +@@ -356,9 +362,7 @@ if !DISABLE_TOOLS + bin_PROGRAMS += \ + src/tools/linux/core2md/core2md \ + src/tools/linux/dump_syms/dump_syms \ +- src/tools/linux/md2core/minidump-2-core \ +- src/tools/linux/symupload/minidump_upload \ +- src/tools/linux/symupload/sym_upload ++ src/tools/linux/md2core/minidump-2-core + if X86_HOST + bin_PROGRAMS += \ + src/tools/mac/dump_syms/dump_syms_mac +@@ -456,6 +460,19 @@ LOG_DRIVER = $(top_srcdir)/autotools/test-driver + endif !TESTS_AS_ROOT + endif !ANDROID_HOST + ++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 = -lcurl ++ ++src_tools_linux_symupload_sym_upload_SOURCES = \ ++ src/common/linux/http_upload.cc \ ++ src/common/linux/http_upload.h \ ++ 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 = -lcurl ++ + if LINUX_HOST + src_client_linux_linux_dumper_unittest_helper_SOURCES = \ + src/client/linux/minidump_writer/linux_dumper_unittest_helper.cc +@@ -607,19 +624,6 @@ src_tools_linux_md2core_minidump_2_core_SOURCES = \ + src/tools/linux/md2core/minidump-2-core.cc \ + src/tools/linux/md2core/minidump_memory_range.h + +-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 = -lcurl +- +-src_tools_linux_symupload_sym_upload_SOURCES = \ +- src/common/linux/http_upload.cc \ +- src/common/linux/http_upload.h \ +- 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 = -lcurl +- + src_tools_mac_dump_syms_dump_syms_mac_SOURCES = \ + src/common/dwarf_cfi_to_module.cc \ + src/common/dwarf_cu_to_module.cc \ +-- +2.28.0 + diff --git a/recipes/breakpad/all/patches/0004-Add-support-for-DWARF-in-PECOFF-as-used-by-Cygwin-an.patch b/recipes/breakpad/all/patches/0004-Add-support-for-DWARF-in-PECOFF-as-used-by-Cygwin-an.patch new file mode 100644 index 0000000..7bfa2ad --- /dev/null +++ b/recipes/breakpad/all/patches/0004-Add-support-for-DWARF-in-PECOFF-as-used-by-Cygwin-an.patch @@ -0,0 +1,2217 @@ +From 663cc2bf819d810b818cd16cbea6e7b2dbaaa812 Mon Sep 17 00:00:00 2001 +From: Jon Turney +Date: Tue, 4 Feb 2014 00:57:13 +0000 +Subject: [PATCH 04/19] Add support for DWARF in PECOFF as used by Cygwin and + MinGW + +For cygwin and mingw targets, build a dump_syms tool which can read DWARF +symbols contained in a PE/COFF executable. + +I felt bad about making another copy of dump_symbols.cc, so this one has the +beginnings of being parameterized by an image file reader class, so we can apply +it to a pecoff-format image file reading class + +Write pecoff format image file reading class which +- knows how to read PE32 and PE32+ image files +- makes PECOFF file id by fetching from a CV record or by hashing +- can read PECOFF exports as a fallback if there is no DWARF information + +v2: +Don't include arpa/inet.h on MinGW + +v3: +Use AM_CPPFLAGS for NO_STABS_SUPPORT + +v4: +Fixes for -Werror=sign-compare errors arising due to signedness of size_t +Update use of Module::Extern() for change in r1415 +Fix EOT fallback to match reality rather than PE/COFF spec. + +v5: +Add needed include of winsock.h for htons etc. + +v6: +Update for char -> uint8_t changes in commit bc44efdc + +v7: +Update for "Add debug fission support" changes + +What's this? We now build elf_reader.cc into our COFF symbols dumping tool? +But why is that? Because dwarf2reader now contains an entirely separate ELF +reader, for reading .dwo/.dwp files... + +Signed-off-by: Jon Turney +--- + Makefile.am | 30 + + configure.ac | 5 + + src/common/pecoff/dump_symbols-inl.h | 705 ++++++++++++++++++ + src/common/pecoff/dump_symbols.cc | 90 +++ + src/common/pecoff/dump_symbols.h | 80 ++ + src/common/pecoff/pecoff.h | 262 +++++++ + src/common/pecoff/pecoff_file_id.cc | 83 +++ + src/common/pecoff/pecoff_file_id.h | 52 ++ + src/common/pecoff/pecoffutils.cc | 494 ++++++++++++ + src/common/pecoff/pecoffutils.h | 167 +++++ + .../windows/dump_syms_dwarf/dump_syms.cc | 88 +++ + 11 files changed, 2056 insertions(+) + create mode 100644 src/common/pecoff/dump_symbols-inl.h + create mode 100644 src/common/pecoff/dump_symbols.cc + create mode 100644 src/common/pecoff/dump_symbols.h + create mode 100644 src/common/pecoff/pecoff.h + create mode 100644 src/common/pecoff/pecoff_file_id.cc + create mode 100644 src/common/pecoff/pecoff_file_id.h + create mode 100644 src/common/pecoff/pecoffutils.cc + create mode 100644 src/common/pecoff/pecoffutils.h + create mode 100644 src/tools/windows/dump_syms_dwarf/dump_syms.cc + +diff --git a/Makefile.am b/Makefile.am +index ea82edcd..0f6388f1 100644 +--- a/Makefile.am ++++ b/Makefile.am +@@ -51,6 +51,11 @@ AM_CFLAGS += -fPIC + AM_CXXFLAGS += -fPIC + endif + ++if WINDOWS_HOST ++# don't have stab.h, don't build stabs support ++AM_CPPFLAGS += -DNO_STABS_SUPPORT ++endif ++ + # Specify include paths for ac macros + ACLOCAL_AMFLAGS = -I m4 + +@@ -370,6 +375,12 @@ endif + endif + endif LINUX_HOST + ++if WINDOWS_HOST ++if !DISABLE_TOOLS ++bin_PROGRAMS += \ ++ src/tools/windows/dump_syms_dwarf/dump_syms ++endif ++endif + + ## Tests + if !DISABLE_PROCESSOR +@@ -782,6 +793,25 @@ src_tools_linux_md2core_minidump_2_core_unittest_LDADD = \ + + endif LINUX_HOST + ++if WINDOWS_HOST ++if !DISABLE_TOOLS ++src_tools_windows_dump_syms_dwarf_dump_syms_SOURCES = \ ++ src/common/dwarf_cfi_to_module.cc \ ++ src/common/dwarf_cu_to_module.cc \ ++ src/common/dwarf_line_to_module.cc \ ++ src/common/language.cc \ ++ src/common/module.cc \ ++ src/common/dwarf/bytereader.cc \ ++ src/common/dwarf/dwarf2diehandler.cc \ ++ src/common/dwarf/dwarf2reader.cc \ ++ src/common/dwarf/elf_reader.cc \ ++ src/common/pecoff/dump_symbols.cc \ ++ src/common/pecoff/pecoffutils.cc \ ++ src/common/pecoff/pecoff_file_id.cc \ ++ src/tools/windows/dump_syms_dwarf/dump_syms.cc ++endif ++endif ++ + if !DISABLE_PROCESSOR + src_processor_address_map_unittest_SOURCES = \ + src/processor/address_map_unittest.cc +diff --git a/configure.ac b/configure.ac +index 492d0903..63b32bdd 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -110,8 +110,13 @@ case $host in + *-*-linux* | *-android* ) + LINUX_HOST=true + ;; ++ *-*-cygwin* ) ++ WINDOWS_HOST=true ++ ;; + esac ++ + AM_CONDITIONAL(LINUX_HOST, test x$LINUX_HOST = xtrue) ++AM_CONDITIONAL(WINDOWS_HOST, test x$WINDOWS_HOST = xtrue) + + # Only use Android support headers when compiling for Android + case $host in +diff --git a/src/common/pecoff/dump_symbols-inl.h b/src/common/pecoff/dump_symbols-inl.h +new file mode 100644 +index 00000000..23955f6a +--- /dev/null ++++ b/src/common/pecoff/dump_symbols-inl.h +@@ -0,0 +1,705 @@ ++// Copyright (c) 2011 Google Inc. ++// All rights reserved. ++// ++// Redistribution and use in source and binary forms, with or without ++// modification, are permitted provided that the following conditions are ++// met: ++// ++// * Redistributions of source code must retain the above copyright ++// notice, this list of conditions and the following disclaimer. ++// * Redistributions in binary form must reproduce the above ++// copyright notice, this list of conditions and the following disclaimer ++// in the documentation and/or other materials provided with the ++// distribution. ++// * Neither the name of Google Inc. nor the names of its ++// contributors may be used to endorse or promote products derived from ++// this software without specific prior written permission. ++// ++// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ++// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ++// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ++// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ++// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ++// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ++// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ++// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ++// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ++// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++ ++// dump_symbols-inl.h: implement google_breakpad::WriteSymbolFile: ++// Find all the debugging info in a file and dump it as a Breakpad symbol file. ++ ++#ifndef COMMON_PECOFF_DUMP_SYMBOLS_INL_H ++#define COMMON_PECOFF_DUMP_SYMBOLS_INL_H ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++ ++#include "common/dwarf/bytereader-inl.h" ++#include "common/dwarf/dwarf2diehandler.h" ++#include "common/dwarf_cfi_to_module.h" ++#include "common/dwarf_cu_to_module.h" ++#include "common/dwarf_line_to_module.h" ++#include "common/module.h" ++#include "common/scoped_ptr.h" ++#ifndef NO_STABS_SUPPORT ++#include "common/stabs_reader.h" ++#include "common/stabs_to_module.h" ++#endif ++#include "common/using_std_string.h" ++ ++// This namespace contains helper functions. ++namespace { ++ ++using google_breakpad::DumpOptions; ++using google_breakpad::DwarfCFIToModule; ++using google_breakpad::DwarfCUToModule; ++using google_breakpad::DwarfLineToModule; ++using google_breakpad::Module; ++#ifndef NO_STABS_SUPPORT ++using google_breakpad::StabsToModule; ++#endif ++using google_breakpad::scoped_ptr; ++ ++// ++// FDWrapper ++// ++// Wrapper class to make sure opened file is closed. ++// ++class FDWrapper { ++ public: ++ explicit FDWrapper(int fd) : ++ fd_(fd) {} ++ ~FDWrapper() { ++ if (fd_ != -1) ++ close(fd_); ++ } ++ int get() { ++ return fd_; ++ } ++ int release() { ++ int fd = fd_; ++ fd_ = -1; ++ return fd; ++ } ++ private: ++ int fd_; ++}; ++ ++// ++// MmapWrapper ++// ++// Wrapper class to make sure mapped regions are unmapped. ++// ++class MmapWrapper { ++ public: ++ MmapWrapper() : is_set_(false) {} ++ ~MmapWrapper() { ++ if (is_set_ && base_ != NULL) { ++ assert(size_ > 0); ++ munmap(base_, size_); ++ } ++ } ++ void set(void *mapped_address, size_t mapped_size) { ++ is_set_ = true; ++ base_ = mapped_address; ++ size_ = mapped_size; ++ } ++ void release() { ++ assert(is_set_); ++ is_set_ = false; ++ base_ = NULL; ++ size_ = 0; ++ } ++ ++ private: ++ bool is_set_; ++ void *base_; ++ size_t size_; ++}; ++ ++#ifndef NO_STABS_SUPPORT ++template ++bool LoadStabs(const typename ObjectFileReader::ObjectFileBase header, ++ const typename ObjectFileReader::Section stab_section, ++ const typename ObjectFileReader::Section stabstr_section, ++ const bool big_endian, ++ Module* module) { ++ // A callback object to handle data from the STABS reader. ++ StabsToModule handler(module); ++ // Find the addresses of the STABS data, and create a STABS reader object. ++ // On Linux, STABS entries always have 32-bit values, regardless of the ++ // address size of the architecture whose code they're describing, and ++ // the strings are always "unitized". ++ const uint8_t* stabs = ObjectFileReader::GetSectionPointer(header, ++ stab_section); ++ const uint8_t* stabstr = ObjectFileReader::GetSectionPointer(header, ++ stabstr_section); ++ google_breakpad::StabsReader reader(stabs, ++ ObjectFileReader::GetSectionSize(header, stab_section), ++ stabstr, ++ ObjectFileReader::GetSectionSize(header, stabstr_section), ++ big_endian, 4, true, &handler); ++ // Read the STABS data, and do post-processing. ++ if (!reader.Process()) ++ return false; ++ handler.Finalize(); ++ return true; ++} ++#endif // NO_STABS_SUPPORT ++ ++// A line-to-module loader that accepts line number info parsed by ++// dwarf2reader::LineInfo and populates a Module and a line vector ++// with the results. ++class DumperLineToModule: public DwarfCUToModule::LineToModuleHandler { ++ public: ++ // Create a line-to-module converter using BYTE_READER. ++ explicit DumperLineToModule(dwarf2reader::ByteReader *byte_reader) ++ : byte_reader_(byte_reader) { } ++ void StartCompilationUnit(const string& compilation_dir) { ++ compilation_dir_ = compilation_dir; ++ } ++ void ReadProgram(const uint8_t *program, uint64 length, ++ Module *module, std::vector *lines) { ++ DwarfLineToModule handler(module, compilation_dir_, lines); ++ dwarf2reader::LineInfo parser(program, length, byte_reader_, &handler); ++ parser.Start(); ++ } ++ private: ++ string compilation_dir_; ++ dwarf2reader::ByteReader *byte_reader_; ++}; ++ ++template ++bool LoadDwarf(const string& dwarf_filename, ++ const typename ObjectFileReader::ObjectFileBase header, ++ const bool big_endian, ++ bool handle_inter_cu_refs, ++ Module* module) { ++ typedef typename ObjectFileReader::Section Shdr; ++ ++ const dwarf2reader::Endianness endianness = big_endian ? ++ dwarf2reader::ENDIANNESS_BIG : dwarf2reader::ENDIANNESS_LITTLE; ++ dwarf2reader::ByteReader byte_reader(endianness); ++ ++ // Construct a context for this file. ++ DwarfCUToModule::FileContext file_context(dwarf_filename, ++ module, ++ handle_inter_cu_refs); ++ ++ // Build a map of the file's sections. ++ int num_sections = ObjectFileReader::GetNumberOfSections(header); ++ for (int i = 0; i < num_sections; ++i) { ++ const Shdr section = ObjectFileReader::FindSectionByIndex(header, i); ++ string name = ObjectFileReader::GetSectionName(header, section); ++ const uint8_t* contents = reinterpret_cast(ObjectFileReader::GetSectionPointer(header, section)); ++ file_context.AddSectionToSectionMap(name, contents, ++ ObjectFileReader::GetSectionSize(header, section)); ++ } ++ ++ // Parse all the compilation units in the .debug_info section. ++ DumperLineToModule line_to_module(&byte_reader); ++ dwarf2reader::SectionMap::const_iterator debug_info_entry = ++ file_context.section_map().find(".debug_info"); ++ assert(debug_info_entry != file_context.section_map().end()); ++ const std::pair& debug_info_section = ++ debug_info_entry->second; ++ // This should never have been called if the file doesn't have a ++ // .debug_info section. ++ assert(debug_info_section.first); ++ uint64 debug_info_length = debug_info_section.second; ++ for (uint64 offset = 0; offset < debug_info_length;) { ++ // Make a handler for the root DIE that populates MODULE with the ++ // data that was found. ++ DwarfCUToModule::WarningReporter reporter(dwarf_filename, offset); ++ DwarfCUToModule root_handler(&file_context, &line_to_module, &reporter); ++ // Make a Dwarf2Handler that drives the DIEHandler. ++ dwarf2reader::DIEDispatcher die_dispatcher(&root_handler); ++ // Make a DWARF parser for the compilation unit at OFFSET. ++ dwarf2reader::CompilationUnit reader(dwarf_filename, ++ file_context.section_map(), ++ offset, ++ &byte_reader, ++ &die_dispatcher); ++ // Process the entire compilation unit; get the offset of the next. ++ offset += reader.Start(); ++ } ++ return true; ++} ++ ++// Fill REGISTER_NAMES with the register names appropriate to the ++// machine architecture, indexed by the register ++// numbers used in DWARF call frame information. Return true on ++// success, or false if HEADER's machine architecture is not ++// supported. ++bool DwarfCFIRegisterNames(const char *architecture, ++ std::vector* register_names) { ++ if (strcmp(architecture, "x86" ) == 0) ++ *register_names = DwarfCFIToModule::RegisterNames::I386(); ++ else if (strcmp(architecture, "arm" ) == 0) ++ *register_names = DwarfCFIToModule::RegisterNames::ARM(); ++ else if (strcmp(architecture, "mips" ) == 0) ++ *register_names = DwarfCFIToModule::RegisterNames::MIPS(); ++ else if (strcmp(architecture, "x86_64" ) == 0) ++ *register_names = DwarfCFIToModule::RegisterNames::X86_64(); ++ else ++ return false; ++ ++ return true; ++} ++ ++template ++bool LoadDwarfCFI(const string& dwarf_filename, ++ const typename ObjectFileReader::ObjectFileBase header, ++ const char* section_name, ++ const typename ObjectFileReader::Section section, ++ const bool eh_frame, ++ const typename ObjectFileReader::Section got_section, ++ const typename ObjectFileReader::Section text_section, ++ const bool big_endian, ++ Module* module) { ++ // Find the appropriate set of register names for this file's ++ // architecture. ++ const char *architecture = ObjectFileReader::Architecture(header); ++ std::vector register_names; ++ if (!DwarfCFIRegisterNames(architecture, ®ister_names)) { ++ return false; ++ } ++ ++ const dwarf2reader::Endianness endianness = big_endian ? ++ dwarf2reader::ENDIANNESS_BIG : dwarf2reader::ENDIANNESS_LITTLE; ++ ++ // Find the call frame information and its size. ++ const uint8_t* cfi = reinterpret_cast(ObjectFileReader::GetSectionPointer(header, section)); ++ size_t cfi_size = ObjectFileReader::GetSectionSize(header, section); ++ ++ // Plug together the parser, handler, and their entourages. ++ DwarfCFIToModule::Reporter module_reporter(dwarf_filename, section_name); ++ DwarfCFIToModule handler(module, register_names, &module_reporter); ++ dwarf2reader::ByteReader byte_reader(endianness); ++ ++ byte_reader.SetAddressSize(ObjectFileReader::kAddrSize); ++ ++ // Provide the base addresses for .eh_frame encoded pointers, if ++ // possible. ++ byte_reader.SetCFIDataBase(ObjectFileReader::GetSectionRVA(header, section) + ++ ObjectFileReader::GetLoadingAddress(header), ++ cfi); ++ if (got_section) ++ byte_reader.SetDataBase(ObjectFileReader::GetSectionRVA(header, got_section) + ++ ObjectFileReader::GetLoadingAddress(header)); ++ if (text_section) ++ byte_reader.SetTextBase(ObjectFileReader::GetSectionRVA(header, text_section) + ++ ObjectFileReader::GetLoadingAddress(header)); ++ ++ dwarf2reader::CallFrameInfo::Reporter dwarf_reporter(dwarf_filename, ++ section_name); ++ dwarf2reader::CallFrameInfo parser(cfi, cfi_size, ++ &byte_reader, &handler, &dwarf_reporter, ++ eh_frame); ++ parser.Start(); ++ return true; ++} ++ ++bool LoadFile(const string& obj_file, MmapWrapper* map_wrapper, ++ const void** header) { ++ int obj_fd = open(obj_file.c_str(), O_RDONLY); ++ if (obj_fd < 0) { ++ fprintf(stderr, "Failed to open file '%s': %s\n", ++ obj_file.c_str(), strerror(errno)); ++ return false; ++ } ++ FDWrapper obj_fd_wrapper(obj_fd); ++ struct stat st; ++ if (fstat(obj_fd, &st) != 0 && st.st_size <= 0) { ++ fprintf(stderr, "Unable to fstat file '%s': %s\n", ++ obj_file.c_str(), strerror(errno)); ++ return false; ++ } ++ void *obj_base = mmap(NULL, st.st_size, ++ PROT_READ | PROT_WRITE, MAP_PRIVATE, obj_fd, 0); ++ if (obj_base == MAP_FAILED) { ++ fprintf(stderr, "Failed to mmap file '%s': %s\n", ++ obj_file.c_str(), strerror(errno)); ++ return false; ++ } ++ map_wrapper->set(obj_base, st.st_size); ++ *header = obj_base; ++ return true; ++} ++ ++// Read the .gnu_debuglink and get the debug file name. If anything goes ++// wrong, return an empty string. ++template ++string ReadDebugLink(const char* debuglink, ++ size_t debuglink_size, ++ const string& obj_file, ++ const std::vector& debug_dirs) { ++ size_t debuglink_len = strlen(debuglink) + 5; // '\0' + CRC32. ++ debuglink_len = 4 * ((debuglink_len + 3) / 4); // Round to nearest 4 bytes. ++ ++ // Sanity check. ++ if (debuglink_len != debuglink_size) { ++ fprintf(stderr, "Mismatched .gnu_debuglink string / section size: " ++ "%zx %zx\n", debuglink_len, debuglink_size); ++ return ""; ++ } ++ ++ bool found = false; ++ int debuglink_fd = -1; ++ string debuglink_path; ++ std::vector::const_iterator it; ++ for (it = debug_dirs.begin(); it < debug_dirs.end(); ++it) { ++ const string& debug_dir = *it; ++ debuglink_path = debug_dir + "/" + debuglink; ++ debuglink_fd = open(debuglink_path.c_str(), O_RDONLY); ++ if (debuglink_fd >= 0) { ++ found = true; ++ break; ++ } ++ } ++ ++ if (!found) { ++ fprintf(stderr, "Failed to find debug file for '%s' after trying:\n", ++ obj_file.c_str()); ++ for (it = debug_dirs.begin(); it < debug_dirs.end(); ++it) { ++ const string debug_dir = *it; ++ fprintf(stderr, " %s/%s\n", debug_dir.c_str(), debuglink); ++ } ++ return ""; ++ } ++ ++ FDWrapper debuglink_fd_wrapper(debuglink_fd); ++ // TODO(thestig) check the CRC-32 at the end of the .gnu_debuglink ++ // section. ++ ++ return debuglink_path; ++} ++ ++// ++// LoadSymbolsInfo ++// ++// Holds the state between the two calls to LoadSymbols() in case it's necessary ++// to follow the .gnu_debuglink section and load debug information from a ++// different file. ++// ++template ++class LoadSymbolsInfo { ++ public: ++ typedef typename ObjectFileReader::Addr Addr; ++ ++ explicit LoadSymbolsInfo(const std::vector& dbg_dirs) : ++ debug_dirs_(dbg_dirs), ++ has_loading_addr_(false) {} ++ ++ // Keeps track of which sections have been loaded so sections don't ++ // accidentally get loaded twice from two different files. ++ void LoadedSection(const string §ion) { ++ if (loaded_sections_.count(section) == 0) { ++ loaded_sections_.insert(section); ++ } else { ++ fprintf(stderr, "Section %s has already been loaded.\n", ++ section.c_str()); ++ } ++ } ++ ++ // The file and linked debug file are expected to have the same preferred ++ // loading address. ++ void set_loading_addr(Addr addr, const string &filename) { ++ if (!has_loading_addr_) { ++ loading_addr_ = addr; ++ loaded_file_ = filename; ++ return; ++ } ++ ++ if (addr != loading_addr_) { ++ fprintf(stderr, ++ "file '%s' and debug file '%s' " ++ "have different load addresses.\n", ++ loaded_file_.c_str(), filename.c_str()); ++ assert(false); ++ } ++ } ++ ++ // Setters and getters ++ const std::vector& debug_dirs() const { ++ return debug_dirs_; ++ } ++ ++ string debuglink_file() const { ++ return debuglink_file_; ++ } ++ void set_debuglink_file(string file) { ++ debuglink_file_ = file; ++ } ++ ++ private: ++ const std::vector& debug_dirs_; // Directories in which to ++ // search for the debug file. ++ ++ string debuglink_file_; // Full path to the debug file. ++ ++ bool has_loading_addr_; // Indicate if LOADING_ADDR_ is valid. ++ ++ Addr loading_addr_; // Saves the preferred loading address from the ++ // first call to LoadSymbols(). ++ ++ string loaded_file_; // Name of the file loaded from the first call to ++ // LoadSymbols(). ++ ++ std::set loaded_sections_; // Tracks the Loaded sections ++ // between calls to LoadSymbols(). ++}; ++ ++template ++bool LoadSymbols(const string& obj_file, ++ const bool big_endian, ++ const typename ObjectFileReader::ObjectFileBase header, ++ const bool read_gnu_debug_link, ++ LoadSymbolsInfo* info, ++ const DumpOptions& options, ++ Module* module) { ++ typedef typename ObjectFileReader::Addr Addr; ++ typedef typename ObjectFileReader::Section Shdr; ++ ++ Addr loading_addr = ObjectFileReader::GetLoadingAddress(header); ++ module->SetLoadAddress(loading_addr); ++ info->set_loading_addr(loading_addr, obj_file); ++ ++ bool found_debug_info_section = false; ++ bool found_usable_info = false; ++ ++ if (options.symbol_data != ONLY_CFI) { ++#ifndef NO_STABS_SUPPORT ++ // Look for STABS debugging information, and load it if present. ++ const Shdr stab_section = ++ ObjectFileReader::FindSectionByName(".stab", header); ++ if (stab_section) { ++ const Shdr stabstr_section = ObjectFileReader::FindLinkedSection(header, stab_section); ++ if (stabstr_section) { ++ found_debug_info_section = true; ++ found_usable_info = true; ++ info->LoadedSection(".stab"); ++ if (!LoadStabs(header, stab_section, stabstr_section, ++ big_endian, module)) { ++ fprintf(stderr, "%s: \".stab\" section found, but failed to load" ++ " STABS debugging information\n", obj_file.c_str()); ++ } ++ } ++ } ++#endif // NO_STABS_SUPPORT ++ ++ // Look for DWARF debugging information, and load it if present. ++ const Shdr dwarf_section = ++ ObjectFileReader::FindSectionByName(".debug_info", header); ++ if (dwarf_section) { ++ found_debug_info_section = true; ++ found_usable_info = true; ++ info->LoadedSection(".debug_info"); ++ if (!LoadDwarf(obj_file, header, big_endian, ++ options.handle_inter_cu_refs, module)) { ++ fprintf(stderr, "%s: \".debug_info\" section found, but failed to load " ++ "DWARF debugging information\n", obj_file.c_str()); ++ } ++ } ++ } ++ ++ if (options.symbol_data != NO_CFI) { ++ // Dwarf Call Frame Information (CFI) is actually independent from ++ // the other DWARF debugging information, and can be used alone. ++ const Shdr dwarf_cfi_section = ++ ObjectFileReader::FindSectionByName(".debug_frame", header); ++ if (dwarf_cfi_section) { ++ // Ignore the return value of this function; even without call frame ++ // information, the other debugging information could be perfectly ++ // useful. ++ info->LoadedSection(".debug_frame"); ++ bool result = ++ LoadDwarfCFI(obj_file, header, ".debug_frame", ++ dwarf_cfi_section, false, 0, 0, big_endian, ++ module); ++ found_usable_info = found_usable_info || result; ++ } ++ ++ // Linux C++ exception handling information can also provide ++ // unwinding data. ++ const Shdr eh_frame_section = ++ ObjectFileReader::FindSectionByName(".eh_frame", header); ++ if (eh_frame_section) { ++ // Pointers in .eh_frame data may be relative to the base addresses of ++ // certain sections. Provide those sections if present. ++ const Shdr got_section = ++ ObjectFileReader::FindSectionByName(".got", header); ++ const Shdr text_section = ++ ObjectFileReader::FindSectionByName(".text", header); ++ info->LoadedSection(".eh_frame"); ++ // As above, ignore the return value of this function. ++ bool result = ++ LoadDwarfCFI(obj_file, header, ".eh_frame", ++ eh_frame_section, true, ++ got_section, text_section, big_endian, module); ++ found_usable_info = found_usable_info || result; ++ } ++ } ++ ++ if (!found_debug_info_section) { ++ fprintf(stderr, "%s: file contains no debugging information" ++ " (no \".stab\" or \".debug_info\" sections)\n", ++ obj_file.c_str()); ++ ++ // Failed, but maybe there's a .gnu_debuglink section? ++ if (read_gnu_debug_link) { ++ const Shdr gnu_debuglink_section ++ = ObjectFileReader::FindSectionByName(".gnu_debuglink", header); ++ if (gnu_debuglink_section) { ++ if (!info->debug_dirs().empty()) { ++ const char* debuglink_contents = reinterpret_cast ++ (ObjectFileReader::GetSectionPointer(header, gnu_debuglink_section)); ++ string debuglink_file ++ = ReadDebugLink(debuglink_contents, ++ ObjectFileReader::GetSectionSize(header, gnu_debuglink_section), ++ obj_file, info->debug_dirs()); ++ info->set_debuglink_file(debuglink_file); ++ } else { ++ fprintf(stderr, ".gnu_debuglink section found in '%s', " ++ "but no debug path specified.\n", obj_file.c_str()); ++ } ++ } else { ++ fprintf(stderr, "%s does not contain a .gnu_debuglink section.\n", ++ obj_file.c_str()); ++ } ++ } else { ++ if (options.symbol_data != ONLY_CFI) { ++ // The caller doesn't want to consult .gnu_debuglink. ++ // See if there are export symbols available. ++ bool result = ObjectFileReader::ExportedSymbolsToModule(header, module); ++ found_usable_info = found_usable_info || result; ++ } ++ ++ // Return true if some usable information was found, since ++ // the caller doesn't want to use .gnu_debuglink. ++ return found_usable_info; ++ } ++ ++ // No debug info was found, let the user try again with .gnu_debuglink ++ // if present. ++ return false; ++ } ++ ++ return true; ++} ++ ++// Return the non-directory portion of FILENAME: the portion after the ++// last slash, or the whole filename if there are no slashes. ++string BaseFileName(const string &filename) { ++ // Lots of copies! basename's behavior is less than ideal. ++ char *c_filename = strdup(filename.c_str()); ++ string base = basename(c_filename); ++ free(c_filename); ++ return base; ++} ++ ++template ++bool ReadSymbolDataFromObjectFile( ++ const typename ObjectFileReader::ObjectFileBase header, ++ const string& obj_filename, ++ const std::vector& debug_dirs, ++ const DumpOptions& options, ++ Module** out_module) { ++ ++ *out_module = NULL; ++ ++ string identifier = ObjectFileReader::FileIdentifierFromMappedFile(header); ++ if (identifier.empty()) { ++ fprintf(stderr, "%s: unable to generate file identifier\n", ++ obj_filename.c_str()); ++ return false; ++ } ++ ++ const char *architecture = ObjectFileReader::Architecture(header); ++ if (!architecture) { ++ return false; ++ } ++ ++ // Figure out what endianness this file is. ++ bool big_endian; ++ if (!ObjectFileReader::Endianness(header, &big_endian)) ++ return false; ++ ++ string name = BaseFileName(obj_filename); ++ string os = "windows"; ++ string id = identifier; ++ ++ LoadSymbolsInfo info(debug_dirs); ++ scoped_ptr module(new Module(name, os, architecture, id)); ++ if (!LoadSymbols(obj_filename, big_endian, header, ++ !debug_dirs.empty(), &info, ++ options, module.get())) { ++ const string debuglink_file = info.debuglink_file(); ++ if (debuglink_file.empty()) ++ return false; ++ ++ // Load debuglink file. ++ fprintf(stderr, "Found debugging info in %s\n", debuglink_file.c_str()); ++ MmapWrapper debug_map_wrapper; ++ typename ObjectFileReader::ObjectFileBase debug_header = NULL; ++ if (!LoadFile(debuglink_file, &debug_map_wrapper, ++ reinterpret_cast(&debug_header))) ++ return false; ++ ++ if (!ObjectFileReader::IsValid(debug_header)) { ++ fprintf(stderr, "Not a valid file: %s\n", debuglink_file.c_str()); ++ return false; ++ } ++ ++ // Sanity checks to make sure everything matches up. ++ const char *debug_architecture = ++ ObjectFileReader::Architecture(debug_header); ++ if (!debug_architecture) { ++ return false; ++ } ++ if (strcmp(architecture, debug_architecture)) { ++ fprintf(stderr, "%s with machine architecture %s does not match " ++ "%s with architecture %s\n", ++ debuglink_file.c_str(), debug_architecture, ++ obj_filename.c_str(), architecture); ++ return false; ++ } ++ ++ bool debug_big_endian; ++ if (!ObjectFileReader::Endianness(debug_header, &debug_big_endian)) ++ return false; ++ if (debug_big_endian != big_endian) { ++ fprintf(stderr, "%s and %s does not match in endianness\n", ++ obj_filename.c_str(), debuglink_file.c_str()); ++ return false; ++ } ++ ++ if (!LoadSymbols(debuglink_file, debug_big_endian, ++ debug_header, false, &info, ++ options, module.get())) { ++ return false; ++ } ++ } ++ ++ *out_module = module.release(); ++ return true; ++} ++ ++} // namespace ++ ++#endif // COMMON_PECOFF_DUMP_SYMBOLS_INL_H +diff --git a/src/common/pecoff/dump_symbols.cc b/src/common/pecoff/dump_symbols.cc +new file mode 100644 +index 00000000..47be9408 +--- /dev/null ++++ b/src/common/pecoff/dump_symbols.cc +@@ -0,0 +1,90 @@ ++// Copyright (c) 2011 Google Inc. ++// All rights reserved. ++// ++// Redistribution and use in source and binary forms, with or without ++// modification, are permitted provided that the following conditions are ++// met: ++// ++// * Redistributions of source code must retain the above copyright ++// notice, this list of conditions and the following disclaimer. ++// * Redistributions in binary form must reproduce the above ++// copyright notice, this list of conditions and the following disclaimer ++// in the documentation and/or other materials provided with the ++// distribution. ++// * Neither the name of Google Inc. nor the names of its ++// contributors may be used to endorse or promote products derived from ++// this software without specific prior written permission. ++// ++// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ++// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ++// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ++// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ++// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ++// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ++// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ++// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ++// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ++// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++ ++#include "common/pecoff/dump_symbols.h" ++ ++#include "common/pecoff/pecoffutils.h" ++#include "common/pecoff/dump_symbols-inl.h" ++ ++namespace google_breakpad { ++ ++// Not explicitly exported, but not static so it can be used in unit tests. ++bool ReadSymbolDataInternal(const uint8_t* obj_file, ++ const string& obj_filename, ++ const std::vector& debug_dirs, ++ const DumpOptions& options, ++ Module** module) { ++ if (!IsValidPeCoff(obj_file)) { ++ fprintf(stderr, "Not a valid PE/COFF file: %s\n", obj_filename.c_str()); ++ return false; ++ } ++ ++ int peclass = PeCoffClass(obj_file); ++ if (peclass == PE32) { ++ return ReadSymbolDataFromObjectFile( ++ reinterpret_cast(obj_file), obj_filename, debug_dirs, ++ options, module); ++ } ++ if (peclass == PE32PLUS) { ++ return ReadSymbolDataFromObjectFile( ++ reinterpret_cast(obj_file), obj_filename, debug_dirs, ++ options, module); ++ } ++ ++ return false; ++} ++ ++bool WriteSymbolFile(const string &obj_file, ++ const std::vector& debug_dirs, ++ const DumpOptions& options, ++ std::ostream &sym_stream) { ++ Module* module; ++ if (!ReadSymbolData(obj_file, debug_dirs, options, &module)) ++ return false; ++ ++ bool result = module->Write(sym_stream, options.symbol_data); ++ delete module; ++ return result; ++} ++ ++bool ReadSymbolData(const string& obj_file, ++ const std::vector& debug_dirs, ++ const DumpOptions& options, ++ Module** module) { ++ MmapWrapper map_wrapper; ++ const void* pe_header = NULL; ++ ++ if (!LoadFile(obj_file, &map_wrapper, &pe_header)) ++ return false; ++ ++ return ReadSymbolDataInternal(reinterpret_cast(pe_header), ++ obj_file, debug_dirs, options, module); ++} ++ ++} // namespace google_breakpad +diff --git a/src/common/pecoff/dump_symbols.h b/src/common/pecoff/dump_symbols.h +new file mode 100644 +index 00000000..675a4895 +--- /dev/null ++++ b/src/common/pecoff/dump_symbols.h +@@ -0,0 +1,80 @@ ++// -*- mode: c++ -*- ++ ++// Copyright (c) 2011, Google Inc. ++// All rights reserved. ++// ++// Redistribution and use in source and binary forms, with or without ++// modification, are permitted provided that the following conditions are ++// met: ++// ++// * Redistributions of source code must retain the above copyright ++// notice, this list of conditions and the following disclaimer. ++// * Redistributions in binary form must reproduce the above ++// copyright notice, this list of conditions and the following disclaimer ++// in the documentation and/or other materials provided with the ++// distribution. ++// * Neither the name of Google Inc. nor the names of its ++// contributors may be used to endorse or promote products derived from ++// this software without specific prior written permission. ++// ++// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ++// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ++// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ++// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ++// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ++// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ++// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ++// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ++// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ++// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++ ++// dump_symbols.h: Read debugging information from a PECOFF file, and write ++// it out as a Breakpad symbol file. ++ ++#ifndef COMMON_PECOFF_DUMP_SYMBOLS_H__ ++#define COMMON_PECOFF_DUMP_SYMBOLS_H__ ++ ++#include ++#include ++#include ++ ++#include "common/symbol_data.h" ++#include "common/using_std_string.h" ++ ++namespace google_breakpad { ++ ++class Module; ++ ++struct DumpOptions { ++ DumpOptions(SymbolData symbol_data, bool handle_inter_cu_refs) ++ : symbol_data(symbol_data), ++ handle_inter_cu_refs(handle_inter_cu_refs) { ++ } ++ ++ SymbolData symbol_data; ++ bool handle_inter_cu_refs; ++}; ++ ++// Find all the debugging information in OBJ_FILE, an PECOFF executable ++// or shared library, and write it to SYM_STREAM in the Breakpad symbol ++// file format. ++// If OBJ_FILE has been stripped but contains a .gnu_debuglink section, ++// then look for the debug file in DEBUG_DIRS. ++// SYMBOL_DATA allows limiting the type of symbol data written. ++bool WriteSymbolFile(const string &obj_file, ++ const std::vector& debug_dirs, ++ const DumpOptions& options, ++ std::ostream &sym_stream); ++ ++// As above, but simply return the debugging information in MODULE ++// instead of writing it to a stream. The caller owns the resulting ++// Module object and must delete it when finished. ++bool ReadSymbolData(const string& obj_file, ++ const std::vector& debug_dirs, ++ const DumpOptions& options, ++ Module** module); ++ ++} // namespace google_breakpad ++ ++#endif // COMMON_PECOFF_DUMP_SYMBOLS_H__ +diff --git a/src/common/pecoff/pecoff.h b/src/common/pecoff/pecoff.h +new file mode 100644 +index 00000000..9ac32ef3 +--- /dev/null ++++ b/src/common/pecoff/pecoff.h +@@ -0,0 +1,262 @@ ++// Copyright (c) 2014 Google Inc. ++// All rights reserved. ++// ++// Redistribution and use in source and binary forms, with or without ++// modification, are permitted provided that the following conditions are ++// met: ++// ++// * Redistributions of source code must retain the above copyright ++// notice, this list of conditions and the following disclaimer. ++// * Redistributions in binary form must reproduce the above ++// copyright notice, this list of conditions and the following disclaimer ++// in the documentation and/or other materials provided with the ++// distribution. ++// * Neither the name of Google Inc. nor the names of its ++// contributors may be used to endorse or promote products derived from ++// this software without specific prior written permission. ++// ++// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ++// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ++// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ++// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ++// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ++// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ++// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ++// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ++// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ++// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++ ++// pecoff.h: PECOFF file format ++// ++ ++#ifndef COMMON_PECOFF_PECOFF_H__ ++#define COMMON_PECOFF_PECOFF_H__ ++ ++#include ++ ++#define IMAGE_FILE_HEADER_OFFSET 0x3c ++ ++#define IMAGE_FILE_MAGIC 0x00004550 // "PE\0\0" ++ ++#define IMAGE_FILE_MACHINE_UNKNOWN 0x0000 ++#define IMAGE_FILE_MACHINE_ALPHA 0x0184 ++#define IMAGE_FILE_MACHINE_ALPHA64 0x0284 ++#define IMAGE_FILE_MACHINE_AM33 0x01d3 ++#define IMAGE_FILE_MACHINE_AMD64 0x8664 ++#define IMAGE_FILE_MACHINE_ARM 0x01c0 ++#define IMAGE_FILE_MACHINE_ARMV7 0x01c4 ++#define IMAGE_FILE_MACHINE_CEE 0xc0ee ++#define IMAGE_FILE_MACHINE_CEF 0x0cef ++#define IMAGE_FILE_MACHINE_EBC 0x0ebc ++#define IMAGE_FILE_MACHINE_I386 0x014c ++#define IMAGE_FILE_MACHINE_IA64 0x0200 ++#define IMAGE_FILE_MACHINE_M32R 0x9041 ++#define IMAGE_FILE_MACHINE_M68K 0x0268 ++#define IMAGE_FILE_MACHINE_MIPS16 0x0266 ++#define IMAGE_FILE_MACHINE_MIPSFPU 0x0366 ++#define IMAGE_FILE_MACHINE_MIPSFPU16 0x0466 ++#define IMAGE_FILE_MACHINE_POWERPC 0x01f0 ++#define IMAGE_FILE_MACHINE_POWERPCFP 0x01f1 ++#define IMAGE_FILE_MACHINE_R10000 0x0168 ++#define IMAGE_FILE_MACHINE_R3000 0x0162 ++#define IMAGE_FILE_MACHINE_R4000 0x0166 ++#define IMAGE_FILE_MACHINE_SH3 0x01a2 ++#define IMAGE_FILE_MACHINE_SH3DSP 0x01a3 ++#define IMAGE_FILE_MACHINE_SH3E 0x01a4 ++#define IMAGE_FILE_MACHINE_SH4 0x01a6 ++#define IMAGE_FILE_MACHINE_SH5 0x01a8 ++#define IMAGE_FILE_MACHINE_THUMB 0x01c2 ++#define IMAGE_FILE_MACHINE_TRICORE 0x0520 ++#define IMAGE_FILE_MACHINE_WCEMIPSV2 0x0169 ++#define IMAGE_FILE_MACHINE_AMD64 0x8664 ++ ++struct PeHeader { ++ uint32_t mMagic; // IMAGE_FILE_MAGIC ++ uint16_t mMachine; // IMAGE_FILE_MACHINE_* values ++ uint16_t mNumberOfSections; ++ uint32_t mTimeDateStamp; ++ uint32_t mPointerToSymbolTable; ++ uint32_t mNumberOfSymbols; ++ uint16_t mSizeOfOptionalHeader; ++ uint16_t mCharacteristics; ++}; ++ ++enum PeMagic { ++ PE32 = 0x010b, // 32 bit ++ PE32PLUS = 0x020b, // 64 bit address space, 2GB image size limit ++}; ++ ++struct PeDataDirectory { ++ uint32_t mVirtualAddress; ++ uint32_t mSize; ++}; ++ ++struct Pe32OptionalHeader { ++ uint16_t mMagic; // PeMagic ++ uint8_t mMajorLinkerVersion; ++ uint8_t mMinorLinkerVersion; ++ uint32_t mSizeOfCode; ++ uint32_t mSizeOfInitializedData; ++ uint32_t mSizeOfUninitializedData; ++ uint32_t mAddressOfEntryPoint; ++ uint32_t mBaseOfCode; ++ uint32_t mBaseOfData; ++ uint32_t mImageBase; ++ uint32_t mSectionAlignment; ++ uint32_t mFileAlignment; ++ uint16_t mMajorOperatingSystemVersion; ++ uint16_t mMinorOperatingSystemVersion; ++ uint16_t mMajorImageVersion; ++ uint16_t mMinorImageVersion; ++ uint16_t mMajorSubsystemVersion; ++ uint16_t mMinorSubsystemVersion; ++ uint32_t mWin32VersionValue; ++ uint32_t mSizeOfImage; ++ uint32_t mSizeOfHeaders; ++ uint32_t mCheckSum; ++ uint16_t mSubsystem; ++ uint16_t mDllCharacteristics; ++ uint32_t mSizeOfStackReserve; ++ uint32_t mSizeOfStackCommit; ++ uint32_t mSizeOfHeapReserve; ++ uint32_t mSizeOfHeapCommit; ++ uint32_t mLoaderFlags; ++ uint32_t mNumberOfRvaAndSizes; ++ PeDataDirectory mDataDirectory[0]; ++}; ++ ++struct Pe32PlusOptionalHeader { ++ uint16_t mMagic; // PeMagic ++ uint8_t mMajorLinkerVersion; ++ uint8_t mMinorLinkerVersion; ++ uint32_t mSizeOfCode; ++ uint32_t mSizeOfInitializedData; ++ uint32_t mSizeOfUninitializedData; ++ uint32_t mAddressOfEntryPoint; ++ uint32_t mBaseOfCode; ++ uint64_t mImageBase; ++ uint32_t mSectionAlignment; ++ uint32_t mFileAlignment; ++ uint16_t mMajorOperatingSystemVersion; ++ uint16_t mMinorOperatingSystemVersion; ++ uint16_t mMajorImageVersion; ++ uint16_t mMinorImageVersion; ++ uint16_t mMajorSubsystemVersion; ++ uint16_t mMinorSubsystemVersion; ++ uint32_t mWin32VersionValue; ++ uint32_t mSizeOfImage; ++ uint32_t mSizeOfHeaders; ++ uint32_t mCheckSum; ++ uint16_t mSubsystem; ++ uint16_t mDllCharacteristics; ++ uint64_t mSizeOfStackReserve; ++ uint64_t mSizeOfStackCommit; ++ uint64_t mSizeOfHeapReserve; ++ uint64_t mSizeOfHeapCommit; ++ uint32_t mLoaderFlags; ++ uint32_t mNumberOfRvaAndSizes; ++ PeDataDirectory mDataDirectory[0]; ++}; ++ ++#define PE_EXPORT_TABLE 0 ++#define PE_IMPORT_TABLE 1 ++#define PE_RESOURCE_TABLE 2 ++#define PE_EXCEPTION_TABLE 3 ++#define PE_CERTIFICATE_TABLE 4 ++#define PE_BASE_RELOCATION_TABLE 5 ++#define PE_DEBUG_DATA 6 ++#define PE_ARCHITECTURE 7 ++#define PE_GLOBAL_PTR 8 ++#define PE_TLS_TABLE 9 ++#define PE_LOAD_CONFIG_TABLE 10 ++#define PE_BOUND_IMPORT_TABLE 11 ++#define PE_IMPORT_ADDRESS_TABLE 12 ++#define PE_DELAY_IMPORT_DESCRIPTOR 13 ++#define PE_CLR_RUNTIME_HEADER 14 ++ ++struct PeDebugDirectory { ++ uint32_t mCharacteristics; ++ uint32_t mTimeDateStamp; ++ uint16_t mMajorVersion; ++ uint16_t mMinorVersion; ++ uint32_t mType; ++ uint32_t mSizeOfData; ++ uint32_t mAddressOfRawData; ++ uint32_t mPointerToRawData; ++}; ++ ++#define IMAGE_DEBUG_TYPE_UNKNOWN 0 ++#define IMAGE_DEBUG_TYPE_COFF 1 ++#define IMAGE_DEBUG_TYPE_CODEVIEW 2 ++#define IMAGE_DEBUG_TYPE_FPO 3 ++#define IMAGE_DEBUG_TYPE_MISC 4 ++#define IMAGE_DEBUG_TYPE_EXCEPTION 5 ++#define IMAGE_DEBUG_TYPE_FIXUP 6 ++#define IMAGE_DEBUG_TYPE_OMAP_TO_SRC 7 ++#define IMAGE_DEBUG_TYPE_OMAP_FROM_SRC 8 ++#define IMAGE_DEBUG_TYPE_BORLAND 9 ++#define IMAGE_DEBUG_TYPE_RESERVED10 10 ++#define IMAGE_DEBUG_TYPE_CLSID 11 ++ ++struct CvInfoPbd70 ++{ ++ uint32_t mCvSignature; ++ uint8_t mSignature[16]; ++ uint32_t mAge; ++ uint8_t mPdbFileName[]; ++}; ++ ++#define CODEVIEW_PDB70_CVSIGNATURE 0x53445352 // "RSDS" ++#define CODEVIEW_PDB20_CVSIGNATURE 0x3031424e // "NB10" ++#define CODEVIEW_CV50_CVSIGNATURE 0x3131424e // "NB11" ++#define CODEVIEW_CV41_CVSIGNATURE 0x3930424e // “NB09" ++ ++struct PeSectionHeader { ++ char mName[8]; ++ union { ++ uint32_t mPhysicalAddress; ++ uint32_t mVirtualSize; ++ } ; ++ uint32_t mVirtualAddress; ++ uint32_t mSizeOfRawData; ++ uint32_t mPointerToRawData; ++ uint32_t mPointerToRelocations; ++ uint32_t mPointerToLinenumbers; ++ uint16_t mNumberOfRelocations; ++ uint16_t mNumberOfLinenumbers; ++ uint32_t mCharacteristics; ++}; ++ ++struct __attribute__ ((__packed__)) PeSymbol ++{ ++ union { ++ char mName[8]; // Symbol Name ++ struct { ++ uint32_t mFirst4Bytes; ++ uint32_t mSecond4Bytes; ++ }; ++ }; ++ ++ uint32_t mValue; // Value of Symbol ++ uint16_t mScNum; // Section Number ++ uint16_t mType; // Symbol Type ++ uint8_t mSClass; // Storage Class ++ uint8_t mNumAux; // Auxiliary Count ++}; ++ ++struct PeExportTable { ++ uint32_t mFlags; ++ uint32_t mTimeDateStamp; ++ uint16_t mMajorVersion; ++ uint16_t mMinorVErsion; ++ uint32_t mNameRVA; ++ uint32_t mOrdinalBase; ++ uint32_t mAddressTableEntries; ++ uint32_t mNumberofNamePointers; ++ uint32_t mExportAddressTableRVA; ++ uint32_t mNamePointerRVA; ++ uint32_t mOrdinalTableRVA; ++}; ++ ++#endif// COMMON_PECOFF_PECOFF_H__ +diff --git a/src/common/pecoff/pecoff_file_id.cc b/src/common/pecoff/pecoff_file_id.cc +new file mode 100644 +index 00000000..47c2763f +--- /dev/null ++++ b/src/common/pecoff/pecoff_file_id.cc +@@ -0,0 +1,83 @@ ++// Copyright (c) 2006, Google Inc. ++// All rights reserved. ++// ++// Redistribution and use in source and binary forms, with or without ++// modification, are permitted provided that the following conditions are ++// met: ++// ++// * Redistributions of source code must retain the above copyright ++// notice, this list of conditions and the following disclaimer. ++// * Redistributions in binary form must reproduce the above ++// copyright notice, this list of conditions and the following disclaimer ++// in the documentation and/or other materials provided with the ++// distribution. ++// * Neither the name of Google Inc. nor the names of its ++// contributors may be used to endorse or promote products derived from ++// this software without specific prior written permission. ++// ++// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ++// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ++// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ++// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ++// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ++// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ++// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ++// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ++// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ++// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++// ++// pecoff_file_id.cc: Return a unique identifier for a file ++// ++ ++#include "common/pecoff/pecoff_file_id.h" ++ ++#include "common/pecoff/pecoffutils.h" ++ ++namespace google_breakpad { ++ ++// Attempt to locate a CodeView build-id section in a PECOFF binary ++// and copy as many bytes of it as will fit into |identifier|. ++static bool FindPeCoffBuildID(const uint8_t* mapped_base, ++ uint8_t identifier[kMDGUIDSize], ++ uint32_t *age) { ++ int peclass = PeCoffClass(mapped_base); ++ if (peclass == PE32) ++ return PeCoffClass32::GetBuildID(mapped_base, identifier, age); ++ if (peclass == PE32PLUS) ++ return PeCoffClass64::GetBuildID(mapped_base, identifier, age); ++ ++ return false; ++} ++ ++// Attempt to locate the .text section of a binary and generate ++// a simple hash by XORing the first page worth of bytes into |identifier|. ++static bool HashPeCoffTextSection(const uint8_t* mapped_base, ++ uint8_t identifier[kMDGUIDSize]) { ++ int peclass = PeCoffClass(mapped_base); ++ if (peclass == PE32) ++ return PeCoffClass32::HashTextSection(mapped_base, identifier); ++ if (peclass == PE32PLUS) ++ return PeCoffClass64::HashTextSection(mapped_base, identifier); ++ ++ return false; ++} ++ ++bool PeCoffFileID::PeCoffFileIdentifierFromMappedFile(const void* base, ++ uint8_t identifier[kMDGUIDSize], ++ uint32_t *age) { ++ *age = 0; ++ ++ // Look for a build id first. ++ if (FindPeCoffBuildID(reinterpret_cast(base), identifier, ++ age)) ++ return true; ++ ++ // Fall back on hashing the first page of the text section. ++ // (This is of questionable value as the Windows Minidump writer doesn't have ++ // this feature) ++ return HashPeCoffTextSection(reinterpret_cast(base), ++ identifier); ++} ++ ++} // namespace google_breakpad +diff --git a/src/common/pecoff/pecoff_file_id.h b/src/common/pecoff/pecoff_file_id.h +new file mode 100644 +index 00000000..fd2ea103 +--- /dev/null ++++ b/src/common/pecoff/pecoff_file_id.h +@@ -0,0 +1,52 @@ ++// Copyright (c) 2006, Google Inc. ++// All rights reserved. ++// ++// Redistribution and use in source and binary forms, with or without ++// modification, are permitted provided that the following conditions are ++// met: ++// ++// * Redistributions of source code must retain the above copyright ++// notice, this list of conditions and the following disclaimer. ++// * Redistributions in binary form must reproduce the above ++// copyright notice, this list of conditions and the following disclaimer ++// in the documentation and/or other materials provided with the ++// distribution. ++// * Neither the name of Google Inc. nor the names of its ++// contributors may be used to endorse or promote products derived from ++// this software without specific prior written permission. ++// ++// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ++// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ++// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ++// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ++// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ++// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ++// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ++// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ++// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ++// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++// ++// pecoff_file_id.h: Return a unique identifier for a file ++// ++ ++#ifndef COMMON_PECOFF_PECOFF_FILE_ID_H__ ++#define COMMON_PECOFF_PECOFF_FILE_ID_H__ ++ ++#include ++#include ++ ++namespace google_breakpad { ++ ++static const size_t kMDGUIDSize = 16; ++ ++class PeCoffFileID { ++ public: ++ static bool PeCoffFileIdentifierFromMappedFile(const void* base, ++ uint8_t identifier[kMDGUIDSize], ++ uint32_t* age); ++}; ++ ++} // namespace google_breakpad ++ ++#endif // COMMON_PECOFF_PECOFF_FILE_ID_H__ +diff --git a/src/common/pecoff/pecoffutils.cc b/src/common/pecoff/pecoffutils.cc +new file mode 100644 +index 00000000..f097cc61 +--- /dev/null ++++ b/src/common/pecoff/pecoffutils.cc +@@ -0,0 +1,494 @@ ++// Copyright (c) 2014 Google Inc. ++// All rights reserved. ++// ++// Redistribution and use in source and binary forms, with or without ++// modification, are permitted provided that the following conditions are ++// met: ++// ++// * Redistributions of source code must retain the above copyright ++// notice, this list of conditions and the following disclaimer. ++// * Redistributions in binary form must reproduce the above ++// copyright notice, this list of conditions and the following disclaimer ++// in the documentation and/or other materials provided with the ++// distribution. ++// * Neither the name of Google Inc. nor the names of its ++// contributors may be used to endorse or promote products derived from ++// this software without specific prior written permission. ++// ++// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ++// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ++// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ++// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ++// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ++// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ++// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ++// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ++// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ++// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++ ++// pecoffutils.c: Utilities for dealing with PECOFF files ++// ++ ++#include "common/pecoff/pecoffutils.h" ++ ++#include ++#include ++#include ++ ++#ifndef _WIN32 ++#include ++#else ++#include ++#endif ++ ++namespace google_breakpad { ++ ++bool IsValidPeCoff(const uint8_t* obj_base) { ++ // at offset 0x3c, find the offset to PE signature ++ const uint32_t* peOffsetPtr = reinterpret_cast(obj_base + ++ IMAGE_FILE_HEADER_OFFSET); ++ ++ // TODO: ideally we want to check that the offset is less than the size of the ++ // mapped file, but we don't have that information at the moment ++ // ++ // if (*peOffsetPtr > size) return FALSE; ++ ++ // check PE signature ++ const PeHeader* peHeader = reinterpret_cast(obj_base+*peOffsetPtr); ++ if (peHeader->mMagic != IMAGE_FILE_MAGIC) ++ return false; ++ ++ return true; ++} ++ ++int PeCoffClass(const uint8_t* obj_base) { ++ const uint32_t* peOffsetPtr = reinterpret_cast(obj_base + ++ IMAGE_FILE_HEADER_OFFSET); ++ const PeHeader* peHeader = reinterpret_cast(obj_base+*peOffsetPtr); ++ const uint16_t* peOptionalHeader = reinterpret_cast ++ (reinterpret_cast(peHeader) + sizeof(PeHeader)); ++ ++ // We need to read the magic before we know if this a Pe32OptionalHeader or ++ // Pe32PlusOptionalHeader, so we don't use those types here. ++ return *peOptionalHeader; ++} ++ ++// ++// Header information ++// ++ ++template ++const char* PeCoffObjectFileReader::Architecture( ++ ObjectFileBase obj_base) { ++ const PeHeader* peHeader = GetHeader(obj_base); ++ uint16_t arch = peHeader->mMachine; ++ switch (arch) { ++ case IMAGE_FILE_MACHINE_I386: ++ return "x86"; ++ case IMAGE_FILE_MACHINE_ARM: ++ return "arm"; ++ case IMAGE_FILE_MACHINE_MIPS16: ++ case IMAGE_FILE_MACHINE_MIPSFPU: ++ case IMAGE_FILE_MACHINE_MIPSFPU16: ++ case IMAGE_FILE_MACHINE_WCEMIPSV2: ++ return "mips"; ++ case IMAGE_FILE_MACHINE_POWERPC: ++ case IMAGE_FILE_MACHINE_POWERPCFP: ++ return "ppc"; ++ case IMAGE_FILE_MACHINE_AMD64: ++ return "x86_64"; ++ default: ++ fprintf(stderr, "unrecognized machine architecture: %d\n", ++ peHeader->mMachine); ++ return NULL; ++ } ++} ++ ++template ++bool PeCoffObjectFileReader::Endianness( ++ ObjectFileBase obj_base, ++ bool* big_endian) { ++ // TODO: Not sure what big-endian PECOFF looks like: characteristics flag ++ // IMAGE_FILE_BYTES_REVERSED_HI and/or certain machine types are big-endian ++ *big_endian = false; ++ return true; ++} ++ ++template ++typename PeCoffObjectFileReader::Addr ++PeCoffObjectFileReader::GetLoadingAddress( ++ ObjectFileBase obj_base) { ++ const PeOptionalHeader* peOptionalHeader = GetOptionalHeader(obj_base); ++ return peOptionalHeader->mImageBase; ++} ++ ++// ++// Section enumeration and location ++// ++ ++template ++int PeCoffObjectFileReader::GetNumberOfSections( ++ ObjectFileBase obj_base) { ++ const PeHeader* peHeader = GetHeader(obj_base); ++ return peHeader->mNumberOfSections; ++} ++ ++template ++const typename PeCoffObjectFileReader::Section ++PeCoffObjectFileReader::FindSectionByIndex( ++ ObjectFileBase obj_base, int i) { ++ const PeSectionHeader* section_table = GetSectionTable(obj_base); ++ return reinterpret_cast(&(section_table[i])); ++} ++ ++template ++const typename PeCoffObjectFileReader::Section ++PeCoffObjectFileReader::FindSectionByName( ++ const char* section_name, ObjectFileBase obj_base) { ++ const PeHeader* peHeader = GetHeader(obj_base); ++ const PeSectionHeader* section_table = GetSectionTable(obj_base); ++ const char* string_table = GetStringTable(obj_base); ++ uint32_t string_table_length = *(reinterpret_cast(string_table)); ++ ++ for (int s = 0; s < peHeader->mNumberOfSections; s++) { ++ const char* name = section_table[s].mName; ++ ++ // look up long section names in string table ++ if (name[0] == '/') { ++ unsigned int offset = ::strtoul(section_table[s].mName+1, NULL, 10); ++ ++ if (offset > string_table_length) ++ fprintf(stderr, "section name offset %d exceeds string table length", ++ offset); ++ else ++ name = string_table + offset; ++ } ++ ++ if (::strcmp(section_name, name) == 0) { ++ return reinterpret_cast(&(section_table[s])); ++ } ++ } ++ ++ // nothing found ++ return NULL; ++} ++ ++// ++// Section information ++// ++ ++template ++const uint8_t* ++PeCoffObjectFileReader::GetSectionPointer( ++ ObjectFileBase obj_base, Section section) { ++ return reinterpret_cast(obj_base) + reinterpret_cast(section)->mPointerToRawData; ++} ++ ++template ++typename PeCoffObjectFileReader::Offset ++PeCoffObjectFileReader::GetSectionSize( ++ ObjectFileBase obj_base, Section section) { ++ ++ // There are mSizeOfRawData bytes of data for the section in the mapped image ++ // file. Return mVirtualSize if it's smaller. ++ // This doesn't handle the case where mVirtualSize is larger and the section ++ // should be zero padded, because we have nowhere to do that. ++ if ((reinterpret_cast(section)->mVirtualSize) < ++ (reinterpret_cast(section)->mSizeOfRawData)) ++ return reinterpret_cast(section)->mVirtualSize; ++ ++ return reinterpret_cast(section)->mSizeOfRawData; ++} ++ ++template ++typename PeCoffObjectFileReader::Offset ++PeCoffObjectFileReader::GetSectionRVA( ++ ObjectFileBase obj_base, Section section) { ++ return reinterpret_cast(section)->mVirtualAddress; ++} ++ ++template ++const char* PeCoffObjectFileReader::GetSectionName( ++ ObjectFileBase obj_base,Section section) { ++ const char* string_table = GetStringTable(obj_base); ++ uint32_t string_table_length = *(reinterpret_cast(string_table)); ++ const char* name = reinterpret_cast(section)->mName; ++ ++ // look up long section names in string table ++ if (name[0] == '/') { ++ unsigned int offset = ::strtoul(name+1, NULL, 10); ++ ++ if (offset > string_table_length) ++ fprintf(stderr, "section name offset %d exceeds string table length", ++ offset); ++ else ++ name = string_table + offset; ++ } ++ ++ return name; ++} ++ ++// ++// ++// ++ ++template ++bool PeCoffObjectFileReader::ExportedSymbolsToModule( ++ ObjectFileBase obj_base, Module* module) { ++ // locate the export table, if present ++ const PeDataDirectory* data_directory_export_entry = GetDataDirectoryEntry(obj_base, PE_EXPORT_TABLE); ++ if (data_directory_export_entry && data_directory_export_entry->mSize != 0) { ++ const PeExportTable* export_table = reinterpret_cast(ConvertRVAToPointer(obj_base, data_directory_export_entry->mVirtualAddress)); ++ const uint32_t* eat = reinterpret_cast(ConvertRVAToPointer(obj_base, export_table->mExportAddressTableRVA)); ++ const uint32_t* enpt = reinterpret_cast(ConvertRVAToPointer(obj_base, export_table->mNamePointerRVA)); ++ const uint16_t* eot = reinterpret_cast(ConvertRVAToPointer(obj_base, export_table->mOrdinalTableRVA)); ++ ++ // process the export name pointer table ++ for (uint32_t i = 0; i < export_table->mNumberofNamePointers; i++) { ++ // look up the name for the export ++ uint32_t export_name_rva = enpt[i]; ++ if (export_name_rva == 0) ++ continue; ++ const char* export_name = reinterpret_cast(ConvertRVAToPointer(obj_base, export_name_rva)); ++ ++ // get the corresponding ordinal ++ // (the PE/COFF specification seems to claim that EOT entries are not ++ // biased by ordinalbase, but that doesn't seem to match reality...) ++ uint16_t export_ordinal = eot[i] + export_table->mOrdinalBase; ++ if ((export_ordinal < export_table->mOrdinalBase) || ++ (export_ordinal >= (export_table->mOrdinalBase + export_table->mAddressTableEntries))) { ++ fprintf(stderr, "exported ordinal %d out of range for EAT!\n", export_ordinal); ++ continue; ++ } ++ ++ // find the corresponding export address table entry ++ uint32_t eat_index = export_ordinal - export_table->mOrdinalBase; ++ uint32_t export_rva = eat[eat_index]; ++ ++ // if the export's address lies inside the export table, it's a forwarded ++ // export, which we can ignore ++ if ((export_rva >= data_directory_export_entry->mVirtualAddress) && ++ (export_rva < (data_directory_export_entry->mVirtualAddress + data_directory_export_entry->mSize))) ++ continue; ++ ++ Module::Extern* ext = new Module::Extern(export_rva + GetLoadingAddress(obj_base)); ++ ext->name = export_name; ++ module->AddExtern(ext); ++ } ++ ++ return true; ++ } ++ ++ // report if a COFF symbol table exists, but we don't use it (yet) ++ // According to the PECOFF spec. COFF debugging information is deprecated. ++ // We don't know of any tools which produce that and don't produce DWARF or ++ // MS CodeView debug information. ++ const PeHeader* peHeader = GetHeader(obj_base); ++ if (peHeader->mPointerToSymbolTable) { ++ fprintf(stderr, "COFF debug symbols present but are not implemented\n"); ++ } ++ ++ return false; ++} ++ ++template ++string ++PeCoffObjectFileReader::FileIdentifierFromMappedFile( ++ ObjectFileBase obj_file) { ++ uint8_t identifier[kMDGUIDSize]; ++ uint32_t age; ++ ++ if (!PeCoffFileID::PeCoffFileIdentifierFromMappedFile(obj_file, identifier, &age)) ++ return ""; ++ ++ // Endian-ness swap to match dump processor expectation. ++ uint8_t identifier_swapped[kMDGUIDSize]; ++ memcpy(identifier_swapped, identifier, kMDGUIDSize); ++ uint32_t* data1 = reinterpret_cast(identifier_swapped); ++ *data1 = htonl(*data1); ++ uint16_t* data2 = reinterpret_cast(identifier_swapped + 4); ++ *data2 = htons(*data2); ++ uint16_t* data3 = reinterpret_cast(identifier_swapped + 6); ++ *data3 = htons(*data3); ++ ++ // Format the file identifier in IDENTIFIER as a UUID with the ++ // dashes removed. ++ char identifier_str[40]; ++ int buffer_idx = 0; ++ for (unsigned int idx = 0; idx < kMDGUIDSize; ++idx) { ++ int hi = (identifier_swapped[idx] >> 4) & 0x0F; ++ int lo = (identifier_swapped[idx]) & 0x0F; ++ ++ identifier_str[buffer_idx++] = (hi >= 10) ? 'A' + hi - 10 : '0' + hi; ++ identifier_str[buffer_idx++] = (lo >= 10) ? 'A' + lo - 10 : '0' + lo; ++ } ++ identifier_str[buffer_idx] = 0; ++ string id = identifier_str; ++ ++ // Append age ++ char age_string[9]; ++ snprintf(age_string, sizeof(age_string) / sizeof(age_string[0]), "%X", age); ++ id += age_string; ++ ++ return id; ++} ++ ++// ++// Helper functions for PeCoffFileID ++// ++ ++template ++bool PeCoffObjectFileReader::GetBuildID( ++ ObjectFileBase obj_base, ++ uint8_t identifier[kMDGUIDSize], ++ uint32_t* age) { ++ // locate the debug directory, if present ++ const PeDataDirectory* data_directory_debug_entry = GetDataDirectoryEntry(obj_base, PE_DEBUG_DATA); ++ if (!data_directory_debug_entry) ++ return false; ++ ++ uint32_t debug_directory_size = data_directory_debug_entry->mSize; ++ if (debug_directory_size == 0) ++ return false; ++ ++ const PeDebugDirectory* debug_directory = reinterpret_cast(ConvertRVAToPointer(obj_base, data_directory_debug_entry->mVirtualAddress)); ++ if (debug_directory == NULL) { ++ fprintf(stderr, "No section containing the debug directory VMA could be found\n"); ++ return false; ++ } ++ ++ // search the debug directory for a codeview entry ++ for (unsigned int i = 0; i < debug_directory_size/sizeof(PeDebugDirectory); i++) { ++ if (debug_directory[i].mType == IMAGE_DEBUG_TYPE_CODEVIEW) { ++ // interpret the codeview record to get build-id ++ const CvInfoPbd70* codeview_record = reinterpret_cast ++ (obj_base + debug_directory[i].mPointerToRawData); ++ if ((codeview_record->mCvSignature) == CODEVIEW_PDB70_CVSIGNATURE) { ++ memcpy(identifier, codeview_record->mSignature, kMDGUIDSize); ++ *age = codeview_record->mAge; ++ return true; ++ } else { ++ fprintf(stderr, "Unhandled codeview signature %x\n", ++ codeview_record->mCvSignature); ++ } ++ } ++ } ++ ++ fprintf(stderr, "No codeview entry in debug directory\n"); ++ return false; ++} ++ ++template ++bool PeCoffObjectFileReader::HashTextSection( ++ ObjectFileBase obj_base, ++ uint8_t identifier[kMDGUIDSize]) { ++ Section text_section; ++ Offset text_size; ++ ++ if (!(text_section = FindSectionByName(".text", obj_base)) || ++ ((text_size = GetSectionSize(obj_base, text_section)) == 0)) ++ return false; ++ ++ memset(identifier, 0, kMDGUIDSize); ++ const uint8_t* ptr = GetSectionPointer(obj_base, text_section); ++ const uint8_t* ptr_end = ptr + std::min(text_size, 4096U); ++ while (ptr < ptr_end) { ++ for (unsigned i = 0; i < kMDGUIDSize; i++) ++ identifier[i] ^= ptr[i]; ++ ptr += kMDGUIDSize; ++ } ++ return true; ++} ++ ++// ++// Private implementation helper functions ++// ++ ++template ++const PeHeader* PeCoffObjectFileReader::GetHeader( ++ ObjectFileBase obj_base) { ++ const uint32_t* peOffsetPtr = reinterpret_cast(obj_base + ++ IMAGE_FILE_HEADER_OFFSET); ++ const PeHeader* peHeader = reinterpret_cast(obj_base+*peOffsetPtr); ++ return peHeader; ++} ++ ++template ++const typename PeCoffObjectFileReader::PeOptionalHeader* ++PeCoffObjectFileReader::GetOptionalHeader( ++ ObjectFileBase obj_base) { ++ const PeHeader* peHeader = GetHeader(obj_base); ++ PeOptionalHeader* peOptionalHeader = (PeOptionalHeader*) ((uint32_t*)peHeader + 6); ++ return peOptionalHeader; ++} ++ ++template ++const PeSectionHeader* ++PeCoffObjectFileReader::GetSectionTable( ++ ObjectFileBase obj_base) { ++ const PeHeader* peHeader = GetHeader(obj_base); ++ const PeOptionalHeader* peOptionalHeader = GetOptionalHeader(obj_base); ++ ++ // section table immediately follows optional header ++ const PeSectionHeader* section_table = reinterpret_cast ++ (reinterpret_cast(peOptionalHeader) + peHeader->mSizeOfOptionalHeader); ++ return section_table; ++} ++ ++template ++const char* PeCoffObjectFileReader::GetStringTable( ++ ObjectFileBase obj_base) { ++ const PeHeader* peHeader = GetHeader(obj_base); ++ ++ // string table immediately follows symbol table ++ uint32_t string_table_offset = peHeader->mPointerToSymbolTable + peHeader->mNumberOfSymbols*sizeof(PeSymbol); ++ const char* string_table = reinterpret_cast(obj_base) + string_table_offset; ++ return string_table; ++} ++ ++template ++const PeDataDirectory* ++PeCoffObjectFileReader::GetDataDirectoryEntry( ++ ObjectFileBase obj_base, unsigned int entry) { ++ const PeOptionalHeader* peOptionalHeader = GetOptionalHeader(obj_base); ++ ++ // the data directory immediately follows the optional header ++ const PeDataDirectory* data_directory = reinterpret_cast(&peOptionalHeader->mDataDirectory[0]); ++ uint32_t data_directory_size = peOptionalHeader->mNumberOfRvaAndSizes; ++ ++ // locate the required directory entry, if present ++ if (data_directory_size < entry) ++ return NULL; ++ ++ return &data_directory[entry]; ++} ++ ++template ++const uint8_t* ++PeCoffObjectFileReader::ConvertRVAToPointer( ++ ObjectFileBase obj_base, ++ Offset rva) { ++ // find which section contains the rva to compute it's mapped address ++ const PeSectionHeader* section_table = GetSectionTable(obj_base); ++ for (int s = 0; s < GetNumberOfSections(obj_base); s++) { ++ const PeSectionHeader* section = &(section_table[s]); ++ ++ if ((rva >= section->mVirtualAddress) && ++ (rva < (section->mVirtualAddress + section->mSizeOfRawData))) ++ { ++ uint32_t offset = rva - section->mVirtualAddress; ++ const uint8_t* pointer = GetSectionPointer(obj_base, (Section)section) + offset; ++ return pointer; ++ } ++ } ++ ++ fprintf(stderr, "No section could be found containing RVA %x\n", rva); ++ return NULL; ++} ++ ++// instantiation of templated classes ++template class PeCoffObjectFileReader; ++template class PeCoffObjectFileReader; ++ ++} +diff --git a/src/common/pecoff/pecoffutils.h b/src/common/pecoff/pecoffutils.h +new file mode 100644 +index 00000000..3e2d7b34 +--- /dev/null ++++ b/src/common/pecoff/pecoffutils.h +@@ -0,0 +1,167 @@ ++// Copyright (c) 2014 Google Inc. ++// All rights reserved. ++// ++// Redistribution and use in source and binary forms, with or without ++// modification, are permitted provided that the following conditions are ++// met: ++// ++// * Redistributions of source code must retain the above copyright ++// notice, this list of conditions and the following disclaimer. ++// * Redistributions in binary form must reproduce the above ++// copyright notice, this list of conditions and the following disclaimer ++// in the documentation and/or other materials provided with the ++// distribution. ++// * Neither the name of Google Inc. nor the names of its ++// contributors may be used to endorse or promote products derived from ++// this software without specific prior written permission. ++// ++// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ++// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ++// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ++// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ++// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ++// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ++// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ++// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ++// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ++// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++ ++// pecoffutils.h: Utilities for dealing with PECOFF files ++// ++ ++#ifndef COMMON_PECOFF_PECOFFUTILS_H__ ++#define COMMON_PECOFF_PECOFFUTILS_H__ ++ ++#include "common/pecoff/pecoff.h" ++#include "common/pecoff/pecoff_file_id.h" ++#include "common/module.h" ++ ++namespace google_breakpad { ++ ++bool IsValidPeCoff(const uint8_t* obj_file); ++int PeCoffClass(const uint8_t* obj_file); ++ ++class PeCoffClass32Traits { ++ public: ++ typedef uint32_t Addr; ++ typedef Pe32OptionalHeader PeOptionalHeader; ++ static const int kClass = PE32; ++ static const size_t kAddrSize = 4; ++}; ++ ++class PeCoffClass64Traits { ++ public: ++ typedef uint64_t Addr; ++ typedef Pe32PlusOptionalHeader PeOptionalHeader; ++ static const int kClass = PE32PLUS; ++ static const size_t kAddrSize = 8; ++}; ++// Offset isn't part of the traits as although PE32+ uses 64-bit address space, ++// it still uses 32-bit RVAs and offsets ++ ++template ++class PeCoffObjectFileReader { ++ public: ++ typedef const uint8_t* ObjectFileBase; ++ typedef const uint8_t* Section; ++ typedef uint32_t Offset; ++ typedef typename PeCoffClassTraits::Addr Addr; ++ static const int kClass = PeCoffClassTraits::kClass; ++ static const size_t kAddrSize = PeCoffClassTraits::kAddrSize; ++ ++ static bool IsValid(ObjectFileBase obj_file) { ++ return IsValidPeCoff(obj_file); ++ }; ++ ++ // ++ // Header information ++ // ++ ++ // Return the breakpad symbol file identifier for the architecture ++ static const char* Architecture(ObjectFileBase obj_base); ++ ++ // Get the endianness. If it's invalid, return false. ++ static bool Endianness(ObjectFileBase obj_base, bool* big_endian); ++ ++ // Find the preferred loading address of the binary. ++ static Addr GetLoadingAddress(ObjectFileBase obj_base); ++ ++ // ++ // Section enumeration and location ++ // ++ ++ static int GetNumberOfSections(ObjectFileBase obj_base); ++ static const Section FindSectionByIndex(ObjectFileBase obj_base, int i); ++ // Attempt to find a section named |section_name| ++ static const Section FindSectionByName(const char* section_name, ++ ObjectFileBase obj_base); ++ ++ // ++ // Section information ++ // ++ ++ // Convert a section into a pointer to the mapped address in the current ++ // process. ++ static const uint8_t* GetSectionPointer(ObjectFileBase obj_base, ++ Section section); ++ ++ // Get the size of a section ++ static Offset GetSectionSize(ObjectFileBase obj_base, Section section); ++ ++ // Get relative virtual address (RVA) of a section ++ static Offset GetSectionRVA(ObjectFileBase obj_base, Section section); ++ ++ // Get name of a section ++ static const char* GetSectionName(ObjectFileBase obj_base,Section section); ++ ++ // Find any linked section ++ static const Section FindLinkedSection(ObjectFileBase obj_base, ++ Section section) { ++ return 0; // PECOFF doesn't have the concept of linked sections ++ } ++ ++ // ++ // ++ // ++ ++ // Load symbols from the object file's exported symbol table ++ static bool ExportedSymbolsToModule(ObjectFileBase obj_base, Module* module); ++ ++ // Return the identifier for the file mapped into memory. ++ // Return an empty string if the identifier could not be created ++ // for the file. ++ static string FileIdentifierFromMappedFile(ObjectFileBase obj_base); ++ ++ // ++ // Helpers for PeCoffFileID ++ // ++ ++ // Get the build-id ++ static bool GetBuildID(ObjectFileBase obj_base, ++ uint8_t identifier[kMDGUIDSize], uint32_t* age); ++ // Hash the text section ++ static bool HashTextSection(ObjectFileBase obj_base, ++ uint8_t identifier[kMDGUIDSize]); ++ ++ private: ++ typedef typename PeCoffClassTraits::PeOptionalHeader PeOptionalHeader; ++ ++ // ++ // Private implementation helper functions ++ // ++ static const PeHeader* GetHeader(ObjectFileBase obj_base); ++ static const PeOptionalHeader* GetOptionalHeader(ObjectFileBase obj_base); ++ static const PeSectionHeader* GetSectionTable(ObjectFileBase obj_base); ++ static const char* GetStringTable(ObjectFileBase obj_base); ++ static const PeDataDirectory* GetDataDirectoryEntry(ObjectFileBase obj_base, ++ unsigned int entry); ++ static const uint8_t* ConvertRVAToPointer(ObjectFileBase obj_base, Offset rva); ++}; ++ ++class PeCoffClass32 : public PeCoffObjectFileReader { }; ++class PeCoffClass64 : public PeCoffObjectFileReader { }; ++ ++} // namespace google_breakpad ++ ++#endif // COMMON_PECOFF_PECOFFUTILS_H__ +diff --git a/src/tools/windows/dump_syms_dwarf/dump_syms.cc b/src/tools/windows/dump_syms_dwarf/dump_syms.cc +new file mode 100644 +index 00000000..2d7f70a6 +--- /dev/null ++++ b/src/tools/windows/dump_syms_dwarf/dump_syms.cc +@@ -0,0 +1,88 @@ ++// Copyright (c) 2011, Google Inc. ++// All rights reserved. ++// ++// Redistribution and use in source and binary forms, with or without ++// modification, are permitted provided that the following conditions are ++// met: ++// ++// * Redistributions of source code must retain the above copyright ++// notice, this list of conditions and the following disclaimer. ++// * Redistributions in binary form must reproduce the above ++// copyright notice, this list of conditions and the following disclaimer ++// in the documentation and/or other materials provided with the ++// distribution. ++// * Neither the name of Google Inc. nor the names of its ++// contributors may be used to endorse or promote products derived from ++// this software without specific prior written permission. ++// ++// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ++// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ++// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ++// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ++// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ++// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ++// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ++// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ++// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ++// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++ ++#include ++ ++#include ++#include ++#include ++#include ++ ++#include "common/pecoff/dump_symbols.h" ++ ++using google_breakpad::WriteSymbolFile; ++ ++int usage(const char* self) { ++ fprintf(stderr, "Usage: %s [OPTION] " ++ "[directories-for-debug-file]\n\n", self); ++ fprintf(stderr, "Options:\n"); ++ fprintf(stderr, " -c Do not generate CFI section\n"); ++ fprintf(stderr, " -r Do not handle inter-compilation unit references\n"); ++ return 1; ++} ++ ++int main(int argc, char **argv) { ++ if (argc < 2) ++ return usage(argv[0]); ++ ++ bool cfi = true; ++ bool handle_inter_cu_refs = true; ++ int arg_index = 1; ++ while (arg_index < argc && strlen(argv[arg_index]) > 0 && ++ argv[arg_index][0] == '-') { ++ if (strcmp("-c", argv[arg_index]) == 0) { ++ cfi = false; ++ } else if (strcmp("-r", argv[arg_index]) == 0) { ++ handle_inter_cu_refs = false; ++ } else { ++ return usage(argv[0]); ++ } ++ ++arg_index; ++ } ++ if (arg_index == argc) ++ return usage(argv[0]); ++ ++ const char* binary; ++ std::vector debug_dirs; ++ binary = argv[arg_index]; ++ for (int debug_dir_index = arg_index + 1; ++ debug_dir_index < argc; ++ ++debug_dir_index) { ++ debug_dirs.push_back(argv[debug_dir_index]); ++ } ++ ++ SymbolData symbol_data = cfi ? ALL_SYMBOL_DATA : NO_CFI; ++ google_breakpad::DumpOptions options(symbol_data, handle_inter_cu_refs); ++ if (!WriteSymbolFile(binary, debug_dirs, options, std::cout)) { ++ fprintf(stderr, "Failed to write symbol file.\n"); ++ return 1; ++ } ++ ++ return 0; ++} +-- +2.28.0 + diff --git a/recipes/breakpad/all/patches/0005-Fix-building-minidump-processor-for-MinGW.patch b/recipes/breakpad/all/patches/0005-Fix-building-minidump-processor-for-MinGW.patch new file mode 100644 index 0000000..1a71333 --- /dev/null +++ b/recipes/breakpad/all/patches/0005-Fix-building-minidump-processor-for-MinGW.patch @@ -0,0 +1,183 @@ +From e3a6eefeef6d7873fee61a37ef38f34caf5c3d1c Mon Sep 17 00:00:00 2001 +From: Jon Turney +Date: Fri, 11 Jul 2014 23:37:02 +0100 +Subject: [PATCH 05/19] Fix building minidump processor for MinGW + +- Link minidump_stackwalk, minidump_dump, microdump_stackwalk with +PTHREAD_LIBS as pthread_cancel is used + +- Link minidump_stackwalk, microdump_stackwalk, binarystream_unittest with +ws2_32 as ntoh functions are used + +- _s function variants should only be used if _MSC_VER, use _r variants with +MinGW (and define _POSIX_C_SOURCE to ensure they are prototyped) + + - Don't try to build upload tools, dump_syms_dwarf for MinGW + +(Part of https://breakpad.appspot.com/548002 was commited as svn r1399 to +fix breakpad client compilation for MinGW + +This is mainly the configure.ac and Makefile.am changes left over from +https://breakpad.appspot.com/548002/ with a bit of updating, to fix building +of the minidump processor library and tools for MinGW) + +v2: +Use _POSIX_C_SOURCE not _POSIX to enable *_r() prototypes in headers + +The headers seem to have changed so localtime_r() prototype is now guarded +by _POSIX_C_SOURCE + +This seems right anyhow as _POSIX_C_SOURCE is what SUS defines, whereas I +think _POSIX is some left-over Interix thing? + +v3: +Drop _snprintf fix, now dealt with centrally and correctly since 48673cdb + +Signed-off-by: Jon Turney +--- + Makefile.am | 20 +++++++++++++++++--- + configure.ac | 6 ++++++ + src/processor/logging.cc | 2 +- + src/processor/minidump.cc | 2 +- + 4 files changed, 25 insertions(+), 5 deletions(-) + +diff --git a/Makefile.am b/Makefile.am +index 0f6388f1..f3b1fc6c 100644 +--- a/Makefile.am ++++ b/Makefile.am +@@ -56,6 +56,11 @@ if WINDOWS_HOST + AM_CPPFLAGS += -DNO_STABS_SUPPORT + endif + ++if MINGW_HOST ++SOCKET_LIBS = -lws2_32 ++AM_CPPFLAGS += -D_POSIX_C_SOURCE ++endif ++ + # Specify include paths for ac macros + ACLOCAL_AMFLAGS = -I m4 + +@@ -351,11 +356,13 @@ bin_PROGRAMS += \ + src/processor/minidump_stackwalk + endif !DISABLE_PROCESSOR + ++if !MINGW_HOST + if !DISABLE_TOOLS + bin_PROGRAMS += \ + src/tools/linux/symupload/minidump_upload \ + src/tools/linux/symupload/sym_upload + endif ++endif + + if LINUX_HOST + EXTRA_PROGRAMS += \ +@@ -376,11 +383,13 @@ endif + endif LINUX_HOST + + if WINDOWS_HOST ++if !MINGW_HOST + if !DISABLE_TOOLS + bin_PROGRAMS += \ + src/tools/windows/dump_syms_dwarf/dump_syms + endif + endif ++endif + + ## Tests + if !DISABLE_PROCESSOR +@@ -794,6 +803,7 @@ src_tools_linux_md2core_minidump_2_core_unittest_LDADD = \ + endif LINUX_HOST + + if WINDOWS_HOST ++if !MINGW_HOST + if !DISABLE_TOOLS + src_tools_windows_dump_syms_dwarf_dump_syms_SOURCES = \ + src/common/dwarf_cfi_to_module.cc \ +@@ -811,6 +821,7 @@ src_tools_windows_dump_syms_dwarf_dump_syms_SOURCES = \ + src/tools/windows/dump_syms_dwarf/dump_syms.cc + endif + endif ++endif + + if !DISABLE_PROCESSOR + src_processor_address_map_unittest_SOURCES = \ +@@ -1250,7 +1261,8 @@ src_processor_minidump_dump_LDADD = \ + src/processor/logging.o \ + src/processor/minidump.o \ + src/processor/pathname_stripper.o \ +- src/processor/proc_maps_linux.o ++ src/processor/proc_maps_linux.o \ ++ $(PTHREAD_CFLAGS) $(PTHREAD_LIBS) + + src_processor_microdump_stackwalk_SOURCES = \ + src/processor/microdump_stackwalk.cc +@@ -1285,7 +1297,8 @@ src_processor_microdump_stackwalk_LDADD = \ + src/processor/stackwalker_sparc.o \ + src/processor/stackwalker_x86.o \ + src/processor/tokenize.o \ +- src/third_party/libdisasm/libdisasm.a ++ src/third_party/libdisasm/libdisasm.a \ ++ $(PTHREAD_CFLAGS) $(PTHREAD_LIBS) $(SOCKET_LIBS) + + src_processor_minidump_stackwalk_SOURCES = \ + src/processor/minidump_stackwalk.cc +@@ -1325,7 +1338,8 @@ src_processor_minidump_stackwalk_LDADD = \ + src/processor/stackwalker_x86.o \ + src/processor/symbolic_constants_win.o \ + src/processor/tokenize.o \ +- src/third_party/libdisasm/libdisasm.a ++ src/third_party/libdisasm/libdisasm.a \ ++ $(PTHREAD_CFLAGS) $(PTHREAD_LIBS) $(SOCKET_LIBS) + + endif !DISABLE_PROCESSOR + +diff --git a/configure.ac b/configure.ac +index 63b32bdd..e50d2c22 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -113,10 +113,16 @@ case $host in + *-*-cygwin* ) + WINDOWS_HOST=true + ;; ++ *-*-mingw* ) ++ WINDOWS_HOST=true ++ MINGW_HOST=true ++ ;; + esac + + AM_CONDITIONAL(LINUX_HOST, test x$LINUX_HOST = xtrue) ++# WINDOWS_HOST means MINGW or CYGWIN + AM_CONDITIONAL(WINDOWS_HOST, test x$WINDOWS_HOST = xtrue) ++AM_CONDITIONAL(MINGW_HOST, test x$MINGW_HOST = xtrue) + + # Only use Android support headers when compiling for Android + case $host in +diff --git a/src/processor/logging.cc b/src/processor/logging.cc +index d59175a7..96772eb1 100644 +--- a/src/processor/logging.cc ++++ b/src/processor/logging.cc +@@ -53,7 +53,7 @@ LogStream::LogStream(std::ostream &stream, Severity severity, + time_t clock; + time(&clock); + struct tm tm_struct; +-#ifdef _WIN32 ++#ifdef _MSC_VER + localtime_s(&tm_struct, &clock); + #else + localtime_r(&clock, &tm_struct); +diff --git a/src/processor/minidump.cc b/src/processor/minidump.cc +index 78faf77a..f6b31db5 100644 +--- a/src/processor/minidump.cc ++++ b/src/processor/minidump.cc +@@ -387,7 +387,7 @@ void PrintValueOrInvalid(bool valid, + // Converts a time_t to a string showing the time in UTC. + string TimeTToUTCString(time_t tt) { + struct tm timestruct; +-#ifdef _WIN32 ++#ifdef _MSC_VER + gmtime_s(×truct, &tt); + #else + gmtime_r(&tt, ×truct); +-- +2.28.0 + diff --git a/recipes/breakpad/all/patches/0006-Build-PECOFF-DWARF-dump_syms-for-MinGW.patch b/recipes/breakpad/all/patches/0006-Build-PECOFF-DWARF-dump_syms-for-MinGW.patch new file mode 100644 index 0000000..258d6f4 --- /dev/null +++ b/recipes/breakpad/all/patches/0006-Build-PECOFF-DWARF-dump_syms-for-MinGW.patch @@ -0,0 +1,139 @@ +From 4d138502a2b015a076c77df3d8bfce40bc865e49 Mon Sep 17 00:00:00 2001 +From: Jon Turney +Date: Wed, 5 Feb 2014 13:44:01 +0000 +Subject: [PATCH 06/19] Build PECOFF/DWARF dump_syms for MinGW + +- Substitute MapViewOfFile() for mmap() +- Link dump_syms_dwarf with ws2_32 as ntoh functions are used + +v2: +Add needed include of windows.h + +Signed-off-by: Jon Turney +--- + Makefile.am | 6 ++--- + src/common/pecoff/dump_symbols-inl.h | 40 +++++++++++++++++++++++----- + 2 files changed, 36 insertions(+), 10 deletions(-) + +diff --git a/Makefile.am b/Makefile.am +index f3b1fc6c..712a2fd5 100644 +--- a/Makefile.am ++++ b/Makefile.am +@@ -383,13 +383,11 @@ endif + endif LINUX_HOST + + if WINDOWS_HOST +-if !MINGW_HOST + if !DISABLE_TOOLS + bin_PROGRAMS += \ + src/tools/windows/dump_syms_dwarf/dump_syms + endif + endif +-endif + + ## Tests + if !DISABLE_PROCESSOR +@@ -803,7 +801,6 @@ src_tools_linux_md2core_minidump_2_core_unittest_LDADD = \ + endif LINUX_HOST + + if WINDOWS_HOST +-if !MINGW_HOST + if !DISABLE_TOOLS + src_tools_windows_dump_syms_dwarf_dump_syms_SOURCES = \ + src/common/dwarf_cfi_to_module.cc \ +@@ -819,7 +816,8 @@ src_tools_windows_dump_syms_dwarf_dump_syms_SOURCES = \ + src/common/pecoff/pecoffutils.cc \ + src/common/pecoff/pecoff_file_id.cc \ + src/tools/windows/dump_syms_dwarf/dump_syms.cc +-endif ++src_tools_windows_dump_syms_dwarf_dump_syms_LDADD = \ ++ $(SOCKET_LIBS) + endif + endif + +diff --git a/src/common/pecoff/dump_symbols-inl.h b/src/common/pecoff/dump_symbols-inl.h +index 23955f6a..661097d2 100644 +--- a/src/common/pecoff/dump_symbols-inl.h ++++ b/src/common/pecoff/dump_symbols-inl.h +@@ -39,7 +39,11 @@ + #include + #include + #include ++#ifndef _WIN32 + #include ++#else ++#include ++#endif + #include + #include + #include +@@ -111,13 +115,37 @@ class MmapWrapper { + ~MmapWrapper() { + if (is_set_ && base_ != NULL) { + assert(size_ > 0); ++#ifndef _WIN32 + munmap(base_, size_); ++#else ++ UnmapViewOfFile(base_); ++ CloseHandle(hMap_); ++#endif + } + } +- void set(void *mapped_address, size_t mapped_size) { ++ void *set(int obj_fd, size_t mapped_size) { ++#ifndef _WIN32 ++ void *mapped_address = mmap(NULL, mapped_size, ++ PROT_READ | PROT_WRITE, MAP_PRIVATE, obj_fd, 0); ++ if (mapped_address == MAP_FAILED) ++ return NULL; ++#else ++ HANDLE h = (HANDLE)_get_osfhandle(obj_fd); ++ hMap_ = CreateFileMapping(h, NULL, PAGE_READONLY,0, 0, NULL); ++ // XXX: should also use SEC_IMAGE_NO_EXECUTE on Windows 6.2 or later ++ if (!hMap_) { ++ return NULL; ++ } ++ void *mapped_address = MapViewOfFile(hMap_, FILE_MAP_READ, 0, 0, 0); ++ if (!mapped_address) { ++ CloseHandle(hMap_); ++ return NULL; ++ } ++#endif + is_set_ = true; + base_ = mapped_address; + size_ = mapped_size; ++ return mapped_address; + } + void release() { + assert(is_set_); +@@ -130,6 +158,9 @@ class MmapWrapper { + bool is_set_; + void *base_; + size_t size_; ++#ifdef _WIN32 ++ HANDLE hMap_; ++#endif + }; + + #ifndef NO_STABS_SUPPORT +@@ -330,15 +361,12 @@ bool LoadFile(const string& obj_file, MmapWrapper* map_wrapper, + obj_file.c_str(), strerror(errno)); + return false; + } +- void *obj_base = mmap(NULL, st.st_size, +- PROT_READ | PROT_WRITE, MAP_PRIVATE, obj_fd, 0); +- if (obj_base == MAP_FAILED) { ++ *header = map_wrapper->set(obj_fd, st.st_size); ++ if (!(*header)) { + fprintf(stderr, "Failed to mmap file '%s': %s\n", + obj_file.c_str(), strerror(errno)); + return false; + } +- map_wrapper->set(obj_base, st.st_size); +- *header = obj_base; + return true; + } + +-- +2.28.0 + diff --git a/recipes/breakpad/all/patches/0007-Fix-building-client-library-and-upload-tools-for-Min.patch b/recipes/breakpad/all/patches/0007-Fix-building-client-library-and-upload-tools-for-Min.patch new file mode 100644 index 0000000..1e46f9b --- /dev/null +++ b/recipes/breakpad/all/patches/0007-Fix-building-client-library-and-upload-tools-for-Min.patch @@ -0,0 +1,98 @@ +From 31dd92c4c1934894b9aef2c85075c539ad5fc104 Mon Sep 17 00:00:00 2001 +From: Jon Turney +Date: Thu, 8 Oct 2015 02:11:41 +0100 +Subject: [PATCH 07/19] Fix building client library and upload tools for MinGW + +This is the rest of https://breakpad.appspot.com/548002/, brought up to date + +v2: +Refine MinGW changes in HTTPUpload::GetFileContents so it closes file after use + +v3: +For consistency, write conditionals in terms of _MSC_VER, not __MINGW32__ + +v4: +Use fd rather than FILE * in HTTPUpload::GetFileContents + +It appears that constructing a stdio_filebuf from a FILE * does a fflush(0), +which has been seen to occasionally fail EBADF (on at least W7 x64). + +Both of these things seem like they might be bugs + +Workaround for the moment by constructing stdio_filebuf from a fd instead. + +v5: +Drop HTTPUpload::GetFileContents() changes as upstream now uses WideTOMBCP() +Drop changes to avoid stdext::checked_array_iterator, as upstream + +Signed-off-by: Jon Turney +--- + Makefile.am | 2 -- + src/client/windows/crash_generation/client_info.cc | 4 ++++ + .../tests/crash_generation_app/crash_generation_app.cc | 6 ++++++ + 3 files changed, 10 insertions(+), 2 deletions(-) + +diff --git a/Makefile.am b/Makefile.am +index 712a2fd5..0eddd5ec 100644 +--- a/Makefile.am ++++ b/Makefile.am +@@ -356,13 +356,11 @@ bin_PROGRAMS += \ + src/processor/minidump_stackwalk + endif !DISABLE_PROCESSOR + +-if !MINGW_HOST + if !DISABLE_TOOLS + bin_PROGRAMS += \ + src/tools/linux/symupload/minidump_upload \ + src/tools/linux/symupload/sym_upload + endif +-endif + + if LINUX_HOST + EXTRA_PROGRAMS += \ +diff --git a/src/client/windows/crash_generation/client_info.cc b/src/client/windows/crash_generation/client_info.cc +index ed312638..30a48db0 100644 +--- a/src/client/windows/crash_generation/client_info.cc ++++ b/src/client/windows/crash_generation/client_info.cc +@@ -176,7 +176,11 @@ void ClientInfo::SetProcessUptime() { + + // Convert it to a string. + wchar_t* value = custom_info_entries_.get()[custom_client_info_.count].value; ++#ifdef _MSC_VER + _i64tow_s(delay, value, CustomInfoEntry::kValueMaxLength, 10); ++#else ++ _i64tow(delay, value, 10); ++#endif + } + + bool ClientInfo::PopulateCustomInfo() { +diff --git a/src/client/windows/tests/crash_generation_app/crash_generation_app.cc b/src/client/windows/tests/crash_generation_app/crash_generation_app.cc +index 0d837e52..52736768 100644 +--- a/src/client/windows/tests/crash_generation_app/crash_generation_app.cc ++++ b/src/client/windows/tests/crash_generation_app/crash_generation_app.cc +@@ -42,6 +42,10 @@ + + #include "client/windows/tests/crash_generation_app/abstract_class.h" + ++#ifndef _MSC_VER ++#define swprintf_s swprintf ++#endif ++ + namespace google_breakpad { + + const int kMaxLoadString = 100; +@@ -480,9 +484,11 @@ int APIENTRY _tWinMain(HINSTANCE instance, + CustomClientInfo custom_info = {kCustomInfoEntries, kCustomInfoCount}; + + CrashServerStart(); ++#ifdef _MSC_VER + // This is needed for CRT to not show dialog for invalid param + // failures and instead let the code handle it. + _CrtSetReportMode(_CRT_ASSERT, 0); ++#endif + handler = new ExceptionHandler(L"C:\\dumps\\", + NULL, + google_breakpad::ShowDumpResults, +-- +2.28.0 + diff --git a/recipes/breakpad/all/patches/0008-Fix-common.gypi-to-allow-gyp-to-generate-Makefiles-o.patch b/recipes/breakpad/all/patches/0008-Fix-common.gypi-to-allow-gyp-to-generate-Makefiles-o.patch new file mode 100644 index 0000000..c55fb29 --- /dev/null +++ b/recipes/breakpad/all/patches/0008-Fix-common.gypi-to-allow-gyp-to-generate-Makefiles-o.patch @@ -0,0 +1,43 @@ +From 556a68e03ba5995bd6857b49e77d05610cced6f8 Mon Sep 17 00:00:00 2001 +From: Jon Turney +Date: Thu, 13 Feb 2014 01:06:51 +0000 +Subject: [PATCH 08/19] Fix common.gypi to allow gyp to generate Makefiles on + Windows + +The MSVS_VERSION variable does not exist unless we are using the MSVS generator + +Signed-off-by: Jon Turney +--- + src/build/common.gypi | 8 ++++++-- + 1 file changed, 6 insertions(+), 2 deletions(-) + +diff --git a/src/build/common.gypi b/src/build/common.gypi +index 29990c65..6af4be67 100644 +--- a/src/build/common.gypi ++++ b/src/build/common.gypi +@@ -206,9 +206,9 @@ + # Whether to use multiple cores to compile with visual studio. This is + # optional because it sometimes causes corruption on VS 2005. + # It is on by default on VS 2008 and off on VS 2005. +- ['OS=="win"', { ++ ['"<(GENERATOR)" == "msvs"', { + 'conditions': [ +- ['MSVS_VERSION=="2005"', { ++ [ 'MSVS_VERSION=="2005"', { + 'msvs_multi_core_compile%': 0, + },{ + 'msvs_multi_core_compile%': 1, +@@ -225,6 +225,10 @@ + # Native Client loader for 64-bit Windows. + 'NACL_WIN64', + ], ++ }, ++ { ++ # XXX: because value is used below... ++ 'msvs_multi_core_compile%': 0, + }], + ], + +-- +2.28.0 + diff --git a/recipes/breakpad/all/patches/0009-Teach-gyp-generated-Makefile-to-build-crash_generati.patch b/recipes/breakpad/all/patches/0009-Teach-gyp-generated-Makefile-to-build-crash_generati.patch new file mode 100644 index 0000000..7d7ff6d --- /dev/null +++ b/recipes/breakpad/all/patches/0009-Teach-gyp-generated-Makefile-to-build-crash_generati.patch @@ -0,0 +1,165 @@ +From c2929728b60c9d5051acbce095d44da946cc080f Mon Sep 17 00:00:00 2001 +From: Jon Turney +Date: Mon, 10 Feb 2014 18:12:14 +0000 +Subject: [PATCH 09/19] Teach gyp generated Makefile to build + crash_generation_app correctly + +- Use linker flag for Windows subsystem +- Use linker flag for unicode +- Add rule for compiling windows resources, using $RC to name the resource compiler +- Rename crash_generation_app.rc to avoid a clash in corresponding .o names + +Also +- Fix linking of unit test when built using gyp generated Makefile by providing +needed library + +XXX: We need to arrange for the gyp Makefile generator to set +CXXFLAGS="-DUNICODE -D_UNICODE" somewhere when generating for Windows. This is +already done in generated MSVS projects. + +Signed-off-by: Jon Turney +--- + .../crash_generation_app.gyp | 29 ++++++++++++++++--- + .../{crash_generation_app.rc => resource.rc} | 13 ++++----- + src/client/windows/unittests/client_tests.gyp | 12 ++++++-- + 3 files changed, 41 insertions(+), 13 deletions(-) + rename src/client/windows/tests/crash_generation_app/{crash_generation_app.rc => resource.rc} (96%) + +diff --git a/src/client/windows/tests/crash_generation_app/crash_generation_app.gyp b/src/client/windows/tests/crash_generation_app/crash_generation_app.gyp +index 3ce307da..774f6004 100644 +--- a/src/client/windows/tests/crash_generation_app/crash_generation_app.gyp ++++ b/src/client/windows/tests/crash_generation_app/crash_generation_app.gyp +@@ -40,19 +40,40 @@ + 'crash_generation_app.cc', + 'crash_generation_app.h', + 'crash_generation_app.ico', +- 'crash_generation_app.rc', ++ 'resource.rc', + 'resource.h', + 'small.ico', + ], +- 'libraries': [ +- 'user32.lib', +- ], + 'dependencies': [ + '../../breakpad_client.gyp:common', + '../../crash_generation/crash_generation.gyp:crash_generation_server', + '../../crash_generation/crash_generation.gyp:crash_generation_client', + '../../handler/exception_handler.gyp:exception_handler', + ], ++ 'conditions': [ ++ [ '"<(GENERATOR)" == "make"', { ++ 'ldflags': [ ++ '-Wl,--subsystem=2', '-municode' ++ ], ++ 'rules': [ ++ { 'rule_name': 'windres', ++ 'extension': 'rc', ++ 'inputs' : [ ], ++ 'outputs' : [ '$(builddir)/<(RULE_INPUT_ROOT).o' ], ++ 'action' : [ '$(RC)', '--input=<(RULE_INPUT_PATH)', '--output=$(builddir)/<(RULE_INPUT_ROOT).o', '--input-format=rc', '--output-format=coff', '-v', '--use-temp-file' ], ++ 'message' : 'Compiling Windows resources', ++ 'process_outputs_as_sources' : 1, ++ }, ++ ], ++ } ++ ], ++ [ '"<(GENERATOR)" == "msvs"', { ++ 'libraries': [ ++ 'user32.lib', ++ ], ++ } ++ ] ++ ], + 'msvs_settings': { + 'VCLinkerTool': { + 'SubSystem': '2', # Windows Subsystem as opposed to a console app +diff --git a/src/client/windows/tests/crash_generation_app/crash_generation_app.rc b/src/client/windows/tests/crash_generation_app/resource.rc +similarity index 96% +rename from src/client/windows/tests/crash_generation_app/crash_generation_app.rc +rename to src/client/windows/tests/crash_generation_app/resource.rc +index a362562b..6c7e8b63 100644 +--- a/src/client/windows/tests/crash_generation_app/crash_generation_app.rc ++++ b/src/client/windows/tests/crash_generation_app/resource.rc +@@ -38,7 +38,7 @@ IDI_SMALL ICON "small.ico" + // Menu + // + +-IDC_CRASHGENERATIONAPP MENU ++IDC_CRASHGENERATIONAPP MENU + BEGIN + POPUP "&File" + BEGIN +@@ -64,7 +64,7 @@ END + // Accelerator + // + +-IDC_CRASHGENERATIONAPP ACCELERATORS ++IDC_CRASHGENERATIONAPP ACCELERATORS + BEGIN + "?", IDM_ABOUT, ASCII, ALT + "/", IDM_ABOUT, ASCII, ALT +@@ -94,12 +94,12 @@ END + // TEXTINCLUDE + // + +-1 TEXTINCLUDE ++1 TEXTINCLUDE + BEGIN + "resource.h\0" + END + +-2 TEXTINCLUDE ++2 TEXTINCLUDE + BEGIN + "#define APSTUDIO_HIDDEN_SYMBOLS\r\n" + "#include ""windows.h""\r\n" +@@ -107,7 +107,7 @@ BEGIN + "\0" + END + +-3 TEXTINCLUDE ++3 TEXTINCLUDE + BEGIN + "\r\n" + "\0" +@@ -121,7 +121,7 @@ END + // String Table + // + +-STRINGTABLE ++STRINGTABLE + BEGIN + IDS_APP_TITLE "CrashGenerationApp" + IDC_CRASHGENERATIONAPP "CRASHGENERATIONAPP" +@@ -141,4 +141,3 @@ END + + ///////////////////////////////////////////////////////////////////////////// + #endif // not APSTUDIO_INVOKED +- +diff --git a/src/client/windows/unittests/client_tests.gyp b/src/client/windows/unittests/client_tests.gyp +index 768f8fd8..87caf8d6 100644 +--- a/src/client/windows/unittests/client_tests.gyp ++++ b/src/client/windows/unittests/client_tests.gyp +@@ -51,8 +51,16 @@ + '../crash_generation/crash_generation.gyp:crash_generation_server', + '../crash_generation/crash_generation.gyp:crash_generation_client', + '../handler/exception_handler.gyp:exception_handler', +- 'processor_bits', +- ] ++ 'processor_bits', ++ ], ++ 'conditions': [ ++ [ '"<(GENERATOR)" == "make"', { ++ 'libraries': [ ++ '-ldbghelp', '-lversion', '-lpthread', ++ ], ++ }, ++ ], ++ ], + }, + { + 'target_name': 'processor_bits', +-- +2.28.0 + diff --git a/recipes/breakpad/all/patches/0010-Default-debug_file-to-the-code_file-basename.patch b/recipes/breakpad/all/patches/0010-Default-debug_file-to-the-code_file-basename.patch new file mode 100644 index 0000000..0616d70 --- /dev/null +++ b/recipes/breakpad/all/patches/0010-Default-debug_file-to-the-code_file-basename.patch @@ -0,0 +1,94 @@ +From 21428ac6a1c9c2c0c6d682b2cec8b974864283c0 Mon Sep 17 00:00:00 2001 +From: Jon Turney +Date: Fri, 7 Feb 2014 23:03:10 +0000 +Subject: [PATCH 10/19] Default debug_file to the code_file basename + +Strip any path from code_file, and use that as debug_file if one isn't recorded +in the codeview record. + +The current implementation of 'ld --build-id' doesn't write a pdbfilename in the +codeview record, not least because we don't have such a thing. + +The minidump processor requires both debug_file and debug_identifier (the +build-id) to locate the symbol file. + +v2: +Correctly make debug-file a basename when code-file has a windows-style path +Fix by Ivan Gubarev + +v3: +Fix a test which expects the previous behaviour + +v4: +Fix new tests which expect the previous behaviour + +Signed-off-by: Jon Turney +--- + src/processor/minidump.cc | 14 ++++++++++++++ + src/processor/minidump_unittest.cc | 4 ++-- + src/processor/testdata/minidump2.dump.out | 2 +- + 3 files changed, 17 insertions(+), 3 deletions(-) + +diff --git a/src/processor/minidump.cc b/src/processor/minidump.cc +index f6b31db5..f802210e 100644 +--- a/src/processor/minidump.cc ++++ b/src/processor/minidump.cc +@@ -2144,6 +2144,20 @@ string MinidumpModule::debug_file() const { + } + } + ++ // Manufacture debug-file from code-file ++ if (file.empty()) { ++ file = code_file(); ++ ++ BPLOG(INFO) << "Generated debug_file '" << file << "' from code_file '" << *name_ << "'"; ++ } ++ ++ // This may be a windows-style pathname, so find the basename considering both ++ // forward and back-slashes. ++ const size_t last_slash_idx = file.find_last_of("\\/"); ++ if (std::string::npos != last_slash_idx) { ++ file.erase(0, last_slash_idx + 1); ++ } ++ + // Relatively common case + BPLOG_IF(INFO, file.empty()) << "MinidumpModule could not determine " + "debug_file for " << *name_; +diff --git a/src/processor/minidump_unittest.cc b/src/processor/minidump_unittest.cc +index 036d03f1..35091396 100644 +--- a/src/processor/minidump_unittest.cc ++++ b/src/processor/minidump_unittest.cc +@@ -100,7 +100,7 @@ TEST_F(MinidumpTest, TestMinidumpFromFile) { + const MinidumpModule *md_module = md_module_list->GetModuleAtIndex(0); + ASSERT_TRUE(md_module != NULL); + ASSERT_EQ("c:\\test_app.exe", md_module->code_file()); +- ASSERT_EQ("c:\\test_app.pdb", md_module->debug_file()); ++ ASSERT_EQ("test_app.pdb", md_module->debug_file()); + ASSERT_EQ("45D35F6C2d000", md_module->code_identifier()); + ASSERT_EQ("5A9832E5287241C1838ED98914E9B7FF1", md_module->debug_identifier()); + } +@@ -519,7 +519,7 @@ TEST(Dump, OneModule) { + ASSERT_EQ(0xa90206ca83eb2852ULL, md_module->base_address()); + ASSERT_EQ(0xada542bd, md_module->size()); + ASSERT_EQ("single module", md_module->code_file()); +- ASSERT_EQ("c:\\foo\\file.pdb", md_module->debug_file()); ++ ASSERT_EQ("file.pdb", md_module->debug_file()); + // time_date_stamp and size_of_image concatenated + ASSERT_EQ("B1054D2Aada542bd", md_module->code_identifier()); + ASSERT_EQ("ABCD1234F00DBEEF01020304050607081", md_module->debug_identifier()); +diff --git a/src/processor/testdata/minidump2.dump.out b/src/processor/testdata/minidump2.dump.out +index 8585c89b..e8140fec 100644 +--- a/src/processor/testdata/minidump2.dump.out ++++ b/src/processor/testdata/minidump2.dump.out +@@ -207,7 +207,7 @@ MDRawModule + (cv_record).age = 1 + (cv_record).pdb_file_name = "c:\test_app.pdb" + (misc_record) = (null) +- (debug_file) = "c:\test_app.pdb" ++ (debug_file) = "test_app.pdb" + (debug_identifier) = "5A9832E5287241C1838ED98914E9B7FF1" + (version) = "" + +-- +2.28.0 + diff --git a/recipes/breakpad/all/patches/0011-Fix-Windows-client-unit-tests-with-gcc.patch b/recipes/breakpad/all/patches/0011-Fix-Windows-client-unit-tests-with-gcc.patch new file mode 100644 index 0000000..01b6880 --- /dev/null +++ b/recipes/breakpad/all/patches/0011-Fix-Windows-client-unit-tests-with-gcc.patch @@ -0,0 +1,147 @@ +From 036f9b82792f073f97d36cac71855a5f8a064f0d Mon Sep 17 00:00:00 2001 +From: Jon Turney +Date: Tue, 11 Feb 2014 23:48:28 +0000 +Subject: [PATCH 11/19] Fix Windows client unit-tests with gcc + +- MinGW doesn't have _CrtSetReportMode + +- Trying to call PureVirtual() on a base class object give a linker error + +Use more elaborate contortions to write a pure virtual call that gcc doesn't +spot at compile-time, to provoke a run-time failure (copied from +crash_generation_app) + +Signed-off-by: Jon Turney +--- + .../unittests/exception_handler_death_test.cc | 28 +++++++++++++------ + .../unittests/exception_handler_test.cc | 28 +++++++++++++------ + 2 files changed, 38 insertions(+), 18 deletions(-) + +diff --git a/src/client/windows/unittests/exception_handler_death_test.cc b/src/client/windows/unittests/exception_handler_death_test.cc +index 5ef9e64d..530f05d8 100644 +--- a/src/client/windows/unittests/exception_handler_death_test.cc ++++ b/src/client/windows/unittests/exception_handler_death_test.cc +@@ -242,29 +242,37 @@ TEST_F(ExceptionHandlerDeathTest, InvalidParameterTest) { + ExceptionHandler handler(temp_path_, NULL, NULL, NULL, + ExceptionHandler::HANDLER_INVALID_PARAMETER); + ++#ifdef _MSC_VER + // Disable the message box for assertions + _CrtSetReportMode(_CRT_ASSERT, 0); ++#endif + + // Call with a bad argument. The invalid parameter will be swallowed + // and a dump will be generated, the process will exit(0). + ASSERT_EXIT(printf(NULL), ::testing::ExitedWithCode(0), ""); + } + ++struct PureVirtualCall; + + struct PureVirtualCallBase { +- PureVirtualCallBase() { +- // We have to reinterpret so the linker doesn't get confused because the +- // method isn't defined. +- reinterpret_cast(this)->PureFunction(); +- } +- virtual ~PureVirtualCallBase() {} +- virtual void PureFunction() const = 0; ++ PureVirtualCallBase(PureVirtualCall* derived) : derived_(derived) {} ++ virtual ~PureVirtualCallBase(); ++ virtual void DoSomething() = 0; ++ ++ private: ++ PureVirtualCall* derived_; + }; ++ + struct PureVirtualCall : public PureVirtualCallBase { +- PureVirtualCall() { PureFunction(); } +- virtual void PureFunction() const {} ++ PureVirtualCall() : PureVirtualCallBase(this) {} ++ virtual void DoSomething() {} + }; + ++PureVirtualCallBase:: ~PureVirtualCallBase() ++{ ++ derived_->DoSomething(); ++} ++ + void ExceptionHandlerDeathTest::DoCrashPureVirtualCall() { + PureVirtualCall instance; + } +@@ -276,8 +284,10 @@ TEST_F(ExceptionHandlerDeathTest, PureVirtualCallTest) { + ExceptionHandler handler(temp_path_, NULL, NULL, NULL, + ExceptionHandler::HANDLER_PURECALL); + ++#ifdef _MSC_VER + // Disable the message box for assertions + _CrtSetReportMode(_CRT_ASSERT, 0); ++#endif + + // Calls a pure virtual function. + EXPECT_EXIT(DoCrashPureVirtualCall(), ::testing::ExitedWithCode(0), ""); +diff --git a/src/client/windows/unittests/exception_handler_test.cc b/src/client/windows/unittests/exception_handler_test.cc +index a4ce12a8..0f5801b1 100644 +--- a/src/client/windows/unittests/exception_handler_test.cc ++++ b/src/client/windows/unittests/exception_handler_test.cc +@@ -180,8 +180,10 @@ void ExceptionHandlerTest::DoCrashInvalidParameter() { + google_breakpad::ExceptionHandler::HANDLER_INVALID_PARAMETER, + kFullDumpType, kPipeName, NULL); + ++#ifdef _MSC_VER + // Disable the message box for assertions + _CrtSetReportMode(_CRT_ASSERT, 0); ++#endif + + // Although this is executing in the child process of the death test, + // if it's not true we'll still get an error rather than the crash +@@ -190,21 +192,27 @@ void ExceptionHandlerTest::DoCrashInvalidParameter() { + printf(NULL); + } + ++struct PureVirtualCall; + + struct PureVirtualCallBase { +- PureVirtualCallBase() { +- // We have to reinterpret so the linker doesn't get confused because the +- // method isn't defined. +- reinterpret_cast(this)->PureFunction(); +- } +- virtual ~PureVirtualCallBase() {} +- virtual void PureFunction() const = 0; ++ PureVirtualCallBase(PureVirtualCall* derived) : derived_(derived) {} ++ virtual ~PureVirtualCallBase(); ++ virtual void DoSomething() = 0; ++ ++ private: ++ PureVirtualCall* derived_; + }; ++ + struct PureVirtualCall : public PureVirtualCallBase { +- PureVirtualCall() { PureFunction(); } +- virtual void PureFunction() const {} ++ PureVirtualCall() : PureVirtualCallBase(this) {} ++ virtual void DoSomething() {} + }; + ++PureVirtualCallBase:: ~PureVirtualCallBase() ++{ ++ derived_->DoSomething(); ++} ++ + void ExceptionHandlerTest::DoCrashPureVirtualCall() { + google_breakpad::ExceptionHandler *exc = + new google_breakpad::ExceptionHandler( +@@ -212,8 +220,10 @@ void ExceptionHandlerTest::DoCrashPureVirtualCall() { + google_breakpad::ExceptionHandler::HANDLER_PURECALL, + kFullDumpType, kPipeName, NULL); + ++#ifdef _MSC_VER + // Disable the message box for assertions + _CrtSetReportMode(_CRT_ASSERT, 0); ++#endif + + // Although this is executing in the child process of the death test, + // if it's not true we'll still get an error rather than the crash +-- +2.28.0 + diff --git a/recipes/breakpad/all/patches/0012-Add-symsrv_convert.patch b/recipes/breakpad/all/patches/0012-Add-symsrv_convert.patch new file mode 100644 index 0000000..5a3f2ee --- /dev/null +++ b/recipes/breakpad/all/patches/0012-Add-symsrv_convert.patch @@ -0,0 +1,187 @@ +From 2fb8571457a3e9a8f7c434ba197eb66f2ec959da Mon Sep 17 00:00:00 2001 +From: Jon Turney +Date: Sun, 3 Aug 2014 23:44:28 +0100 +Subject: [PATCH 12/19] Add symsrv_convert + +- Add symsrv_convert from http://hg.mozilla.org/users/tmielczarek_mozilla.com/fetch-win32-symbols/ +- Add building symsrv_convert to .gyp file +- Fix compilation with MSVS 2013 +- NOMINMAX should not be needed as that comes from target_defaults + +v2: +Update symsrv_convert.cc for +MSSymbolServerConverter::LocateAndConvertSymbolFile() changes + +This has been needed for a few years... + +Signed-off-by: Jon Turney +--- + src/common/windows/common_windows.gyp | 2 +- + src/common/windows/pdb_source_line_writer.cc | 6 ++ + .../converter/ms_symbol_server_converter.cc | 2 +- + .../converter/ms_symbol_server_converter.gyp | 13 ++++ + .../converter/ms_symbol_server_converter.h | 4 +- + src/tools/windows/converter/symsrv_convert.cc | 61 +++++++++++++++++++ + 6 files changed, 84 insertions(+), 4 deletions(-) + mode change 100644 => 100755 src/common/windows/pdb_source_line_writer.cc + mode change 100644 => 100755 src/tools/windows/converter/ms_symbol_server_converter.cc + mode change 100644 => 100755 src/tools/windows/converter/ms_symbol_server_converter.h + create mode 100644 src/tools/windows/converter/symsrv_convert.cc + +diff --git a/src/common/windows/common_windows.gyp b/src/common/windows/common_windows.gyp +index 5f7594b1..ec42cade 100644 +--- a/src/common/windows/common_windows.gyp ++++ b/src/common/windows/common_windows.gyp +@@ -37,7 +37,7 @@ + 'all_dependent_settings': { + 'include_dirs': [ + '<(DEPTH)', +- '$(VSInstallDir)/DIA SDK/include', ++ '"$(VSInstallDir)/DIA SDK/include"', + ], + 'msvs_settings': { + 'VCLinkerTool': { +diff --git a/src/common/windows/pdb_source_line_writer.cc b/src/common/windows/pdb_source_line_writer.cc +old mode 100644 +new mode 100755 +index 4030a2e9..a3622d3d +--- a/src/common/windows/pdb_source_line_writer.cc ++++ b/src/common/windows/pdb_source_line_writer.cc +@@ -27,6 +27,12 @@ + // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + ++// We don't want windows.h to define the macro max() which collides with ++// std::numeric_limits::max() ++#ifndef NOMINMAX ++#define NOMINMAX ++#endif ++ + #include "common/windows/pdb_source_line_writer.h" + + #include +diff --git a/src/tools/windows/converter/ms_symbol_server_converter.cc b/src/tools/windows/converter/ms_symbol_server_converter.cc +old mode 100644 +new mode 100755 +index 2b40faee..f1cef404 +--- a/src/tools/windows/converter/ms_symbol_server_converter.cc ++++ b/src/tools/windows/converter/ms_symbol_server_converter.cc +@@ -478,7 +478,7 @@ BOOL CALLBACK MSSymbolServerConverter::SymCallback(HANDLE process, + + // static + BOOL CALLBACK MSSymbolServerConverter::SymFindFileInPathCallback( +- const char *filename, void *context) { ++ PCSTR filename, PVOID context) { + // FALSE ends the search, indicating that the located symbol file is + // satisfactory. + return FALSE; +diff --git a/src/tools/windows/converter/ms_symbol_server_converter.gyp b/src/tools/windows/converter/ms_symbol_server_converter.gyp +index 57ec7906..d84be5c2 100644 +--- a/src/tools/windows/converter/ms_symbol_server_converter.gyp ++++ b/src/tools/windows/converter/ms_symbol_server_converter.gyp +@@ -42,5 +42,18 @@ + '../../../common/windows/common_windows.gyp:common_windows_lib', + ], + }, ++ { ++ 'target_name': 'symsrv_convert', ++ 'type': 'executable', ++ 'dependencies': [ ++ 'ms_symbol_server_converter' ++ ], ++ 'sources' : [ ++ 'symsrv_convert.cc', ++ ], ++ 'include_dirs': [ ++ '<(DEPTH)', ++ ], ++ } + ], + } +diff --git a/src/tools/windows/converter/ms_symbol_server_converter.h b/src/tools/windows/converter/ms_symbol_server_converter.h +old mode 100644 +new mode 100755 +index 401f7c34..6d06cc7e +--- a/src/tools/windows/converter/ms_symbol_server_converter.h ++++ b/src/tools/windows/converter/ms_symbol_server_converter.h +@@ -215,8 +215,8 @@ class MSSymbolServerConverter { + // SymFindFileInPath actually seems to accept NULL for a callback function + // and behave properly for our needs in that case, but the documentation + // doesn't mention it, so this little callback is provided. +- static BOOL CALLBACK SymFindFileInPathCallback(const char *filename, +- void *context); ++ static BOOL CALLBACK SymFindFileInPathCallback(PCSTR filename, ++ PVOID context); + + // The search path used by SymSrv, built based on the arguments to the + // constructor. +diff --git a/src/tools/windows/converter/symsrv_convert.cc b/src/tools/windows/converter/symsrv_convert.cc +new file mode 100644 +index 00000000..4c2a21df +--- /dev/null ++++ b/src/tools/windows/converter/symsrv_convert.cc +@@ -0,0 +1,61 @@ ++#include ++#include ++#include ++ ++#include "tools/windows/converter/ms_symbol_server_converter.h" ++ ++using std::string; ++using std::vector; ++using google_breakpad::MissingSymbolInfo; ++using google_breakpad::MSSymbolServerConverter; ++ ++int main(int argc, char *argv[]) ++{ ++ if (argc < 5) { ++ fprintf(stderr, "Usage: %s \n ", argv[0]); ++ return 1; ++ } ++ ++ MissingSymbolInfo missing_info; ++ missing_info.debug_file = argv[3]; ++ missing_info.debug_identifier = argv[4]; ++ ++ MSSymbolServerConverter converter(argv[2], vector(1, argv[1])); ++ string converted_file; ++ ++ MSSymbolServerConverter::LocateResult result = ++ converter.LocateAndConvertSymbolFile(missing_info, ++ false, ++ false, ++ &converted_file, ++ NULL, ++ NULL); ++ printf("%s: ", argv[3]); ++ int return_code; ++ switch(result) { ++ case MSSymbolServerConverter::LOCATE_SUCCESS: ++ printf("converted: %s\n", converted_file.c_str()); ++ return_code = 0; ++ break; ++ ++ case MSSymbolServerConverter::LOCATE_RETRY: ++ printf("try again later\n"); ++ return_code = 1; ++ break; ++ ++ case MSSymbolServerConverter::LOCATE_FAILURE: ++ case MSSymbolServerConverter::LOCATE_NOT_FOUND: ++ printf("failed to locate symbols\n"); ++ return_code = 2; ++ break; ++ ++ default: ++ // ??? ++ return_code = 3; ++ break; ++ } ++ fflush(stdout); ++ fflush(stderr); ++ ++ return return_code; ++} +-- +2.28.0 + diff --git a/recipes/breakpad/all/patches/0013-Use-a-default-debug-id-of-all-zeros-when-no-CV-recor.patch b/recipes/breakpad/all/patches/0013-Use-a-default-debug-id-of-all-zeros-when-no-CV-recor.patch new file mode 100644 index 0000000..28b85bf --- /dev/null +++ b/recipes/breakpad/all/patches/0013-Use-a-default-debug-id-of-all-zeros-when-no-CV-recor.patch @@ -0,0 +1,69 @@ +From 8beaee224cf0c2379d3f684123533b6e01006bbb Mon Sep 17 00:00:00 2001 +From: Jon Turney +Date: Sat, 22 Feb 2014 15:59:22 +0000 +Subject: [PATCH 13/19] Use a default debug-id of all zeros when no CV record + is present + +This lets us do something slightly useful with current binaries +which are produced without a CV record, but there is no guarantee +that the actually match. + +Signed-off-by: Jon Turney +--- + src/common/pecoff/pecoff_file_id.cc | 8 ++++++++ + src/processor/minidump.cc | 8 ++++++++ + 2 files changed, 16 insertions(+) + +diff --git a/src/common/pecoff/pecoff_file_id.cc b/src/common/pecoff/pecoff_file_id.cc +index 47c2763f..04563c86 100644 +--- a/src/common/pecoff/pecoff_file_id.cc ++++ b/src/common/pecoff/pecoff_file_id.cc +@@ -32,6 +32,7 @@ + + #include "common/pecoff/pecoff_file_id.h" + ++#include + #include "common/pecoff/pecoffutils.h" + + namespace google_breakpad { +@@ -73,11 +74,18 @@ bool PeCoffFileID::PeCoffFileIdentifierFromMappedFile(const void* base, + age)) + return true; + ++#if 1 ++ // XXX: Fallback to a default debug_identifier. ++ memset(identifier, 0, kMDGUIDSize); ++ *age = 0; ++ return true; ++#else + // Fall back on hashing the first page of the text section. + // (This is of questionable value as the Windows Minidump writer doesn't have + // this feature) + return HashPeCoffTextSection(reinterpret_cast(base), + identifier); ++#endif + } + + } // namespace google_breakpad +diff --git a/src/processor/minidump.cc b/src/processor/minidump.cc +index f802210e..1b08ba3f 100644 +--- a/src/processor/minidump.cc ++++ b/src/processor/minidump.cc +@@ -2248,6 +2248,14 @@ string MinidumpModule::debug_identifier() const { + + // TODO(mmentovai): on the Mac, provide fallbacks as in code_identifier(). + ++ // XXX: PE generated with gcc don't currently have CV records, so the Windows ++ // minidumper can't record any identifier information, so there's no useful ++ // identifier for us to match with. Fallback to a default debug_identifier. ++ if (identifier.empty()) ++ { ++ identifier = "000000000000000000000000000000000"; ++ } ++ + // Relatively common case + BPLOG_IF(INFO, identifier.empty()) << "MinidumpModule could not determine " + "debug_identifier for " << *name_; +-- +2.28.0 + diff --git a/recipes/breakpad/all/patches/0014-Use-__USE_MINGW_ANSI_STDIO-for-MinGW-build.patch b/recipes/breakpad/all/patches/0014-Use-__USE_MINGW_ANSI_STDIO-for-MinGW-build.patch new file mode 100644 index 0000000..6a40d2f --- /dev/null +++ b/recipes/breakpad/all/patches/0014-Use-__USE_MINGW_ANSI_STDIO-for-MinGW-build.patch @@ -0,0 +1,32 @@ +From 0a7193eae04791c157328b7cdf0214d707ef3c1d Mon Sep 17 00:00:00 2001 +From: Jon Turney +Date: Wed, 9 Apr 2014 21:14:07 +0100 +Subject: [PATCH 14/19] Use __USE_MINGW_ANSI_STDIO for MinGW build + +Use __USE_MINGW_ANSI_STDIO for ANSI C99 compatible implementation of printf() +and friends on MinGW + +Perhaps we don't need this, if all the printf formats used are in the subset +supported by MSVCRT, but it's easier to turn this on than audit every +single format string... + +Signed-off-by: Jon Turney +--- + Makefile.am | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/Makefile.am b/Makefile.am +index 0eddd5ec..7f81a982 100644 +--- a/Makefile.am ++++ b/Makefile.am +@@ -59,6 +59,7 @@ endif + if MINGW_HOST + SOCKET_LIBS = -lws2_32 + AM_CPPFLAGS += -D_POSIX_C_SOURCE ++AM_CPPFLAGS += -D__USE_MINGW_ANSI_STDIO + endif + + # Specify include paths for ac macros +-- +2.28.0 + diff --git a/recipes/breakpad/all/patches/0015-Provide-a-working-strtok_r-for-MinGW.patch b/recipes/breakpad/all/patches/0015-Provide-a-working-strtok_r-for-MinGW.patch new file mode 100644 index 0000000..3e55399 --- /dev/null +++ b/recipes/breakpad/all/patches/0015-Provide-a-working-strtok_r-for-MinGW.patch @@ -0,0 +1,319 @@ +From affeb8008a27b55a5b096cc77a6431baf7e51ecf Mon Sep 17 00:00:00 2001 +From: Jon Turney +Date: Wed, 9 Apr 2014 23:49:03 +0100 +Subject: [PATCH 15/19] Provide a working strtok_r for MinGW + +Prior to mingW-w64 3.3.0, strtok_r was a macro using strtok, which causes the +processor to not work, as re-entrancy is required + +v2: +Link various unit tests with @LIBOBJS@ for strtok_r + +Signed-off-by: Jon Turney +--- + Makefile.am | 28 +++---- + compat/strtok_r.c | 85 +++++++++++++++++++++ + configure.ac | 3 + + src/processor/basic_source_line_resolver.cc | 4 + + src/processor/cfi_frame_info.cc | 6 +- + src/processor/tokenize.cc | 6 +- + 6 files changed, 116 insertions(+), 16 deletions(-) + create mode 100644 compat/strtok_r.c + +diff --git a/Makefile.am b/Makefile.am +index 7f81a982..b6fd0682 100644 +--- a/Makefile.am ++++ b/Makefile.am +@@ -839,7 +839,7 @@ src_processor_basic_source_line_resolver_unittest_LDADD = \ + src/processor/source_line_resolver_base.o \ + src/processor/tokenize.o \ + $(TEST_LIBS) \ +- $(PTHREAD_CFLAGS) $(PTHREAD_LIBS) ++ $(PTHREAD_CFLAGS) $(PTHREAD_LIBS) @LIBOBJS@ + + src_processor_cfi_frame_info_unittest_SOURCES = \ + src/processor/cfi_frame_info_unittest.cc +@@ -848,7 +848,7 @@ src_processor_cfi_frame_info_unittest_LDADD = \ + src/processor/logging.o \ + src/processor/pathname_stripper.o \ + $(TEST_LIBS) \ +- $(PTHREAD_CFLAGS) $(PTHREAD_LIBS) ++ $(PTHREAD_CFLAGS) $(PTHREAD_LIBS) @LIBOBJS@ + src_processor_cfi_frame_info_unittest_CPPFLAGS = \ + $(AM_CPPFLAGS) $(TEST_CFLAGS) + +@@ -898,7 +898,7 @@ src_processor_exploitability_unittest_LDADD = \ + src/processor/tokenize.o \ + src/third_party/libdisasm/libdisasm.a \ + $(TEST_LIBS) \ +- $(PTHREAD_CFLAGS) $(PTHREAD_LIBS) ++ $(PTHREAD_CFLAGS) $(PTHREAD_LIBS) @LIBOBJS@ + + src_processor_disassembler_x86_unittest_SOURCES = \ + src/processor/disassembler_x86_unittest.cc +@@ -925,7 +925,7 @@ src_processor_fast_source_line_resolver_unittest_LDADD = \ + src/processor/source_line_resolver_base.o \ + src/processor/tokenize.o \ + $(TEST_LIBS) \ +- $(PTHREAD_CFLAGS) $(PTHREAD_LIBS) ++ $(PTHREAD_CFLAGS) $(PTHREAD_LIBS) @LIBOBJS@ + + src_processor_map_serializers_unittest_SOURCES = \ + src/processor/map_serializers_unittest.cc +@@ -969,7 +969,7 @@ src_processor_microdump_processor_unittest_LDADD = \ + src/processor/stackwalker_x86.o \ + src/processor/tokenize.o \ + $(TEST_LIBS) \ +- $(PTHREAD_CFLAGS) $(PTHREAD_LIBS) ++ $(PTHREAD_CFLAGS) $(PTHREAD_LIBS) @LIBOBJS@ + + src_processor_minidump_processor_unittest_SOURCES = \ + src/processor/minidump_processor_unittest.cc +@@ -1010,7 +1010,7 @@ src_processor_minidump_processor_unittest_LDADD = \ + src/processor/tokenize.o \ + src/third_party/libdisasm/libdisasm.a \ + $(TEST_LIBS) \ +- $(PTHREAD_CFLAGS) $(PTHREAD_LIBS) ++ $(PTHREAD_CFLAGS) $(PTHREAD_LIBS) @LIBOBJS@ + + src_processor_minidump_unittest_SOURCES = \ + src/common/test_assembler.cc \ +@@ -1158,7 +1158,7 @@ src_processor_stackwalker_amd64_unittest_SOURCES = \ + src_processor_stackwalker_amd64_unittest_LDADD = \ + src/libbreakpad.a \ + $(TEST_LIBS) \ +- $(PTHREAD_CFLAGS) $(PTHREAD_LIBS) ++ $(PTHREAD_CFLAGS) $(PTHREAD_LIBS) @LIBOBJS@ + src_processor_stackwalker_amd64_unittest_CPPFLAGS = \ + $(AM_CPPFLAGS) $(TEST_CFLAGS) + +@@ -1168,7 +1168,7 @@ src_processor_stackwalker_arm_unittest_SOURCES = \ + src_processor_stackwalker_arm_unittest_LDADD = \ + src/libbreakpad.a \ + $(TEST_LIBS) \ +- $(PTHREAD_CFLAGS) $(PTHREAD_LIBS) ++ $(PTHREAD_CFLAGS) $(PTHREAD_LIBS) @LIBOBJS@ + src_processor_stackwalker_arm_unittest_CPPFLAGS = \ + $(AM_CPPFLAGS) $(TEST_CFLAGS) + +@@ -1178,7 +1178,7 @@ src_processor_stackwalker_arm64_unittest_SOURCES = \ + src_processor_stackwalker_arm64_unittest_LDADD = \ + src/libbreakpad.a \ + $(TEST_LIBS) \ +- $(PTHREAD_CFLAGS) $(PTHREAD_LIBS) ++ $(PTHREAD_CFLAGS) $(PTHREAD_LIBS) @LIBOBJS@ + src_processor_stackwalker_arm64_unittest_CPPFLAGS = \ + $(AM_CPPFLAGS) $(TEST_CFLAGS) + +@@ -1188,7 +1188,7 @@ src_processor_stackwalker_address_list_unittest_SOURCES = \ + src_processor_stackwalker_address_list_unittest_LDADD = \ + src/libbreakpad.a \ + $(TEST_LIBS) \ +- $(PTHREAD_CFLAGS) $(PTHREAD_LIBS) ++ $(PTHREAD_CFLAGS) $(PTHREAD_LIBS) @LIBOBJS@ + src_processor_stackwalker_address_list_unittest_CPPFLAGS = \ + $(AM_CPPFLAGS) $(TEST_CFLAGS) + +@@ -1198,7 +1198,7 @@ src_processor_stackwalker_mips_unittest_SOURCES = \ + src_processor_stackwalker_mips_unittest_LDADD = \ + src/libbreakpad.a \ + $(TEST_LIBS) \ +- $(PTHREAD_CFLAGS) $(PTHREAD_LIBS) ++ $(PTHREAD_CFLAGS) $(PTHREAD_LIBS) @LIBOBJS@ + src_processor_stackwalker_mips_unittest_CPPFLAGS = \ + $(AM_CPPFLAGS) $(TEST_CFLAGS) + +@@ -1218,7 +1218,7 @@ src_processor_stackwalker_x86_unittest_SOURCES = \ + src_processor_stackwalker_x86_unittest_LDADD = \ + src/libbreakpad.a \ + $(TEST_LIBS) \ +- $(PTHREAD_CFLAGS) $(PTHREAD_LIBS) ++ $(PTHREAD_CFLAGS) $(PTHREAD_LIBS) @LIBOBJS@ + src_processor_stackwalker_x86_unittest_CPPFLAGS = \ + $(AM_CPPFLAGS) $(TEST_CFLAGS) + +@@ -1295,7 +1295,7 @@ src_processor_microdump_stackwalk_LDADD = \ + src/processor/stackwalker_x86.o \ + src/processor/tokenize.o \ + src/third_party/libdisasm/libdisasm.a \ +- $(PTHREAD_CFLAGS) $(PTHREAD_LIBS) $(SOCKET_LIBS) ++ $(PTHREAD_CFLAGS) $(PTHREAD_LIBS) $(SOCKET_LIBS) @LIBOBJS@ + + src_processor_minidump_stackwalk_SOURCES = \ + src/processor/minidump_stackwalk.cc +@@ -1336,7 +1336,7 @@ src_processor_minidump_stackwalk_LDADD = \ + src/processor/symbolic_constants_win.o \ + src/processor/tokenize.o \ + src/third_party/libdisasm/libdisasm.a \ +- $(PTHREAD_CFLAGS) $(PTHREAD_LIBS) $(SOCKET_LIBS) ++ $(PTHREAD_CFLAGS) $(PTHREAD_LIBS) $(SOCKET_LIBS) @LIBOBJS@ + + endif !DISABLE_PROCESSOR + +diff --git a/compat/strtok_r.c b/compat/strtok_r.c +new file mode 100644 +index 00000000..ec7b6379 +--- /dev/null ++++ b/compat/strtok_r.c +@@ -0,0 +1,85 @@ ++/*- ++ * Copyright (c) 1998 Softweyr LLC. All rights reserved. ++ * ++ * strtok_r, from Berkeley strtok ++ * Oct 13, 1998 by Wes Peters ++ * ++ * Copyright (c) 1988, 1993 ++ * The Regents of the University of California. All rights reserved. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * 1. Redistributions of source code must retain the above copyright ++ * notices, this list of conditions and the following disclaimer. ++ * 2. Redistributions in binary form must reproduce the above copyright ++ * notices, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * 3. All advertising materials mentioning features or use of this software ++ * must display the following acknowledgement: ++ * This product includes software developed by Softweyr LLC, the ++ * University of California, Berkeley, and its contributors. ++ * 4. Neither the name of the University nor the names of its contributors ++ * may be used to endorse or promote products derived from this software ++ * without specific prior written permission. ++ * ++ * THIS SOFTWARE IS PROVIDED BY SOFTWEYR LLC, THE REGENTS AND CONTRIBUTORS ++ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A ++ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SOFTWEYR LLC, THE ++ * REGENTS, OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED ++ * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR ++ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF ++ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING ++ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS ++ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++ */ ++ ++#include ++ ++char * ++strtok_r(char *s, const char *delim, char **last) ++{ ++ char *spanp, *tok; ++ int c, sc; ++ ++ if (s == NULL && (s = *last) == NULL) ++ return (NULL); ++ ++ /* ++ * Skip (span) leading delimiters (s += strspn(s, delim), sort of). ++ */ ++cont: ++ c = *s++; ++ for (spanp = (char *)delim; (sc = *spanp++) != 0;) { ++ if (c == sc) ++ goto cont; ++ } ++ ++ if (c == 0) { /* no non-delimiter characters */ ++ *last = NULL; ++ return (NULL); ++ } ++ tok = s - 1; ++ ++ /* ++ * Scan token (scan for delimiters: s += strcspn(s, delim), sort of). ++ * Note that delim must have one NUL; we stop if we see that, too. ++ */ ++ for (;;) { ++ c = *s++; ++ spanp = (char *)delim; ++ do { ++ if ((sc = *spanp++) == c) { ++ if (c == 0) ++ s = NULL; ++ else ++ s[-1] = '\0'; ++ *last = s; ++ return (tok); ++ } ++ } while (sc != 0); ++ } ++ /* NOTREACHED */ ++} +diff --git a/configure.ac b/configure.ac +index e50d2c22..10028aaa 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -77,6 +77,9 @@ AC_CHECK_FUNCS([arc4random getrandom]) + + AX_CXX_COMPILE_STDCXX(11, noext, mandatory) + ++AC_CONFIG_LIBOBJ_DIR([compat]) ++AC_REPLACE_FUNCS([strtok_r]) ++ + dnl Test supported warning flags. + WARN_CXXFLAGS= + dnl This warning flag is used by clang. Its default behavior is to warn when +diff --git a/src/processor/basic_source_line_resolver.cc b/src/processor/basic_source_line_resolver.cc +index c4aa949c..c4fcbffa 100644 +--- a/src/processor/basic_source_line_resolver.cc ++++ b/src/processor/basic_source_line_resolver.cc +@@ -49,6 +49,10 @@ + + #include "processor/tokenize.h" + ++#ifndef HAVE_STRTOK_R ++extern "C" char *strtok_r(char *, const char *, char **); ++#endif ++ + using std::map; + using std::vector; + using std::make_pair; +diff --git a/src/processor/cfi_frame_info.cc b/src/processor/cfi_frame_info.cc +index 0c4af7ba..dd2b438b 100644 +--- a/src/processor/cfi_frame_info.cc ++++ b/src/processor/cfi_frame_info.cc +@@ -41,12 +41,16 @@ + #include "common/scoped_ptr.h" + #include "processor/postfix_evaluator-inl.h" + +-namespace google_breakpad { ++#ifndef HAVE_STRTOK_R ++extern "C" char *strtok_r(char *, const char *, char **); ++#endif + + #ifdef _MSC_VER + #define strtok_r strtok_s + #endif + ++namespace google_breakpad { ++ + template + bool CFIFrameInfo::FindCallerRegs(const RegisterValueMap ®isters, + const MemoryRegion &memory, +diff --git a/src/processor/tokenize.cc b/src/processor/tokenize.cc +index 8fce87a2..e6213ac3 100644 +--- a/src/processor/tokenize.cc ++++ b/src/processor/tokenize.cc +@@ -34,12 +34,16 @@ + + #include "common/using_std_string.h" + +-namespace google_breakpad { ++#ifndef HAVE_STRTOK_R ++extern "C" char *strtok_r(char *, const char *, char **); ++#endif + + #ifdef _MSC_VER + #define strtok_r strtok_s + #endif + ++namespace google_breakpad { ++ + using std::vector; + + bool Tokenize(char *line, +-- +2.28.0 + diff --git a/recipes/breakpad/all/patches/0016-Fallback-to-synthesizing-a-debug-id-from-version-and.patch b/recipes/breakpad/all/patches/0016-Fallback-to-synthesizing-a-debug-id-from-version-and.patch new file mode 100644 index 0000000..dca16d7 --- /dev/null +++ b/recipes/breakpad/all/patches/0016-Fallback-to-synthesizing-a-debug-id-from-version-and.patch @@ -0,0 +1,62 @@ +From a1af0549d928135538c0577c991d1ab675ea8533 Mon Sep 17 00:00:00 2001 +From: Jon Turney +Date: Thu, 16 Oct 2014 00:53:55 +0100 +Subject: [PATCH 16/19] Fallback to synthesizing a debug-id from version and + architecture, if possible + +Based on an idea by Ivan Gubarev + +Ideally there would be a similar change in PeCoffFileIdentifierFromMappedFile(), +but that is not written yet... + +Signed-off-by: Jon Turney +--- + src/processor/minidump.cc | 32 +++++++++++++++++++++++++++++--- + 1 file changed, 29 insertions(+), 3 deletions(-) + +diff --git a/src/processor/minidump.cc b/src/processor/minidump.cc +index 1b08ba3f..7d1c5327 100644 +--- a/src/processor/minidump.cc ++++ b/src/processor/minidump.cc +@@ -2248,9 +2248,35 @@ string MinidumpModule::debug_identifier() const { + + // TODO(mmentovai): on the Mac, provide fallbacks as in code_identifier(). + +- // XXX: PE generated with gcc don't currently have CV records, so the Windows +- // minidumper can't record any identifier information, so there's no useful +- // identifier for us to match with. Fallback to a default debug_identifier. ++ // If possible, synthesize a debug_identifier from the version and ++ // architecture. ++ if (identifier.empty()) { ++ std::string ver = version(); ++ if (ver.compare("") != 0) { ++ identifier = ""; ++ for (std::string::const_iterator i = ver.begin(); i != ver.end(); i++) { ++ if (isxdigit(*i)) { ++ identifier += *i; ++ } ++ } ++ ++ MinidumpSystemInfo *minidump_system_info = minidump_->GetSystemInfo(); ++ if (minidump_system_info) { ++ std::string cpu = minidump_system_info->GetCPU(); ++ for (std::string::const_iterator i = cpu.begin(); i != cpu.end(); i++) { ++ char ashex[4]; ++ snprintf(ashex, sizeof(ashex), "%02x", *i); ++ identifier += ashex; ++ } ++ } ++ ++ while (identifier.size() < 33) { ++ identifier += "0"; ++ } ++ } ++ } ++ ++ // Fallback to a default debug_identifier + if (identifier.empty()) + { + identifier = "000000000000000000000000000000000"; +-- +2.28.0 + diff --git a/recipes/breakpad/all/patches/0017-Fix-typo-in-the-name-of-the-info-entry-containing-up.patch b/recipes/breakpad/all/patches/0017-Fix-typo-in-the-name-of-the-info-entry-containing-up.patch new file mode 100644 index 0000000..7da9fc6 --- /dev/null +++ b/recipes/breakpad/all/patches/0017-Fix-typo-in-the-name-of-the-info-entry-containing-up.patch @@ -0,0 +1,29 @@ +From 6e326b03f319739b630dcf6d897ed4563086b808 Mon Sep 17 00:00:00 2001 +From: Jon Turney +Date: Wed, 19 Nov 2014 11:22:53 +0000 +Subject: [PATCH 17/19] Fix typo in the name of the info entry containing + uptime + +I'm assuming this is a typo, although it's been this way since it was added in r280 + +Signed-off-by: Jon Turney +--- + src/client/windows/crash_generation/client_info.cc | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/client/windows/crash_generation/client_info.cc b/src/client/windows/crash_generation/client_info.cc +index 30a48db0..fb293628 100644 +--- a/src/client/windows/crash_generation/client_info.cc ++++ b/src/client/windows/crash_generation/client_info.cc +@@ -30,7 +30,7 @@ + #include "client/windows/crash_generation/client_info.h" + #include "client/windows/common/ipc_protocol.h" + +-static const wchar_t kCustomInfoProcessUptimeName[] = L"ptime"; ++static const wchar_t kCustomInfoProcessUptimeName[] = L"uptime"; + static const size_t kMaxCustomInfoEntries = 4096; + + namespace google_breakpad { +-- +2.28.0 + diff --git a/recipes/breakpad/all/patches/0018-Fix-a-missing-r-in-crash_generation_app.patch b/recipes/breakpad/all/patches/0018-Fix-a-missing-r-in-crash_generation_app.patch new file mode 100644 index 0000000..44f998b --- /dev/null +++ b/recipes/breakpad/all/patches/0018-Fix-a-missing-r-in-crash_generation_app.patch @@ -0,0 +1,30 @@ +From 7b5f274d2029ae6bb63789ab026ac2e2eb3cdf77 Mon Sep 17 00:00:00 2001 +From: Jon Turney +Date: Wed, 19 Nov 2014 11:29:44 +0000 +Subject: [PATCH 18/19] Fix a missing \r in crash_generation_app + +Fix a missing \r in crash_generation_app + +I thought this made a difference, but it doesn't seem to... + +Signed-off-by: Jon Turney +--- + .../windows/tests/crash_generation_app/crash_generation_app.cc | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/client/windows/tests/crash_generation_app/crash_generation_app.cc b/src/client/windows/tests/crash_generation_app/crash_generation_app.cc +index 52736768..93457277 100644 +--- a/src/client/windows/tests/crash_generation_app/crash_generation_app.cc ++++ b/src/client/windows/tests/crash_generation_app/crash_generation_app.cc +@@ -254,7 +254,7 @@ static void ShowClientCrashed(void* context, + line[0] = _T('\0'); + result = swprintf_s(line, + kMaximumLineLength, +- L"%s\n", ++ L"%s\r\n", + str_line.c_str()); + if (result == -1) { + delete[] line; +-- +2.28.0 + diff --git a/recipes/breakpad/all/patches/0019-Disable-DwpReader-for-MinGW.patch b/recipes/breakpad/all/patches/0019-Disable-DwpReader-for-MinGW.patch new file mode 100644 index 0000000..cc793da --- /dev/null +++ b/recipes/breakpad/all/patches/0019-Disable-DwpReader-for-MinGW.patch @@ -0,0 +1,106 @@ +From 7559a2927de29db9765d3ab744490b1cf4500d1f Mon Sep 17 00:00:00 2001 +From: Jon Turney +Date: Fri, 17 Nov 2017 17:14:32 +0000 +Subject: [PATCH 19/19] Disable DwpReader for MinGW + +elf_reader.cc uses mmap(), which isn't available + +Perhaps we could change to using MmapWrapper(), which I've already fixed for +Windows, but this code isn't doing anything for us anyhow + +Signed-off-by: Jon Turney +--- + Makefile.am | 1 - + src/common/dwarf/dwarf2reader.cc | 12 +++++++++++- + src/common/dwarf/dwarf2reader.h | 2 ++ + 3 files changed, 13 insertions(+), 2 deletions(-) + +diff --git a/Makefile.am b/Makefile.am +index b6fd0682..703cba7a 100644 +--- a/Makefile.am ++++ b/Makefile.am +@@ -810,7 +810,6 @@ src_tools_windows_dump_syms_dwarf_dump_syms_SOURCES = \ + src/common/dwarf/bytereader.cc \ + src/common/dwarf/dwarf2diehandler.cc \ + src/common/dwarf/dwarf2reader.cc \ +- src/common/dwarf/elf_reader.cc \ + src/common/pecoff/dump_symbols.cc \ + src/common/pecoff/pecoffutils.cc \ + src/common/pecoff/pecoff_file_id.cc \ +diff --git a/src/common/dwarf/dwarf2reader.cc b/src/common/dwarf/dwarf2reader.cc +index 27f3a83e..a6914a64 100644 +--- a/src/common/dwarf/dwarf2reader.cc ++++ b/src/common/dwarf/dwarf2reader.cc +@@ -64,7 +64,11 @@ CompilationUnit::CompilationUnit(const string& path, + is_split_dwarf_(false), dwo_id_(0), dwo_name_(), + skeleton_dwo_id_(0), ranges_base_(0), addr_base_(0), + have_checked_for_dwp_(false), dwp_path_(), +- dwp_byte_reader_(), dwp_reader_() {} ++ dwp_byte_reader_() ++#ifdef DWPREADER_WANTED ++ , dwp_reader_() ++#endif ++{} + + // Initialize a compilation unit from a .dwo or .dwp file. + // In this case, we need the .debug_addr section from the +@@ -346,6 +350,7 @@ uint64 CompilationUnit::Start() { + // Now that we have our abbreviations, start processing DIE's. + ProcessDIEs(); + ++#ifdef DWPREADER_WANTED + // If this is a skeleton compilation unit generated with split DWARF, + // and the client needs the full debug info, we need to find the full + // compilation unit in a .dwo or .dwp file. +@@ -353,6 +358,7 @@ uint64 CompilationUnit::Start() { + && dwo_name_ != NULL + && handler_->NeedSplitDebugInfo()) + ProcessSplitDwarf(); ++#endif + + return ourlength; + } +@@ -610,6 +616,7 @@ inline int GetElfWidth(const ElfReader& elf) { + return 0; + } + ++#ifdef DWPREADER_WANTED + void CompilationUnit::ProcessSplitDwarf() { + struct stat statbuf; + if (!have_checked_for_dwp_) { +@@ -694,7 +701,9 @@ void CompilationUnit::ReadDebugSectionsFromDwo(ElfReader* elf_reader, + section_size))); + } + } ++#endif + ++#ifdef DWPREADER_WANTED + DwpReader::DwpReader(const ByteReader& byte_reader, ElfReader* elf_reader) + : elf_reader_(elf_reader), byte_reader_(byte_reader), + cu_index_(NULL), cu_index_size_(0), string_buffer_(NULL), +@@ -900,6 +909,7 @@ uint32 DwpReader::LookupCUv2(uint64 dwo_id) { + } + return index; + } ++#endif + + LineInfo::LineInfo(const uint8_t *buffer, uint64 buffer_length, + ByteReader* reader, LineInfoHandler* handler): +diff --git a/src/common/dwarf/dwarf2reader.h b/src/common/dwarf/dwarf2reader.h +index cf3ba3cd..e77c2258 100644 +--- a/src/common/dwarf/dwarf2reader.h ++++ b/src/common/dwarf/dwarf2reader.h +@@ -586,8 +586,10 @@ class CompilationUnit { + // ByteReader for the DWP file. + std::unique_ptr dwp_byte_reader_; + ++#ifdef DWPREADER_WANTED + // DWP reader. + std::unique_ptr dwp_reader_; ++#endif + }; + + // A Reader for a .dwp file. Supports the fetching of DWARF debug +-- +2.28.0 + diff --git a/recipes/breakpad/all/patches/0020-memory_allocator-Use-allocator_traits-rather-than-al.patch b/recipes/breakpad/all/patches/0020-memory_allocator-Use-allocator_traits-rather-than-al.patch new file mode 100644 index 0000000..22d34a7 --- /dev/null +++ b/recipes/breakpad/all/patches/0020-memory_allocator-Use-allocator_traits-rather-than-al.patch @@ -0,0 +1,30 @@ +From 835ce1297e3825484729fa4a065c7854ac5758a4 Mon Sep 17 00:00:00 2001 +From: Danny Robson +Date: Mon, 17 Feb 2020 14:35:30 +1100 +Subject: [PATCH 5/6] memory_allocator: Use allocator_traits rather than + allocator + +allocator::pointer has been removed in C++20. The appropriate mechanism +is now allocator_traits::pointer. +--- + src/common/memory_allocator.h | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/src/common/memory_allocator.h b/src/common/memory_allocator.h +index a3159ea4..b1d4d7be 100644 +--- a/src/common/memory_allocator.h ++++ b/src/common/memory_allocator.h +@@ -161,8 +161,8 @@ class PageAllocator { + // Wrapper to use with STL containers + template + struct PageStdAllocator : public std::allocator { +- typedef typename std::allocator::pointer pointer; +- typedef typename std::allocator::size_type size_type; ++ typedef typename std::allocator_traits>::pointer pointer; ++ typedef typename std::allocator_traits>::size_type size_type; + + explicit PageStdAllocator(PageAllocator& allocator) : allocator_(allocator), + stackdata_(NULL), +-- +2.28.0 + diff --git a/recipes/breakpad/all/patches/0021-Add-a-null-range-handler-to-DwarfCUToModule-construc.patch b/recipes/breakpad/all/patches/0021-Add-a-null-range-handler-to-DwarfCUToModule-construc.patch new file mode 100644 index 0000000..c3155ad --- /dev/null +++ b/recipes/breakpad/all/patches/0021-Add-a-null-range-handler-to-DwarfCUToModule-construc.patch @@ -0,0 +1,25 @@ +From 31cbc302a737e5cb8459d9b1fb67342a83bbd6b4 Mon Sep 17 00:00:00 2001 +From: Danny Robson +Date: Wed, 30 Oct 2019 10:09:48 +1100 +Subject: [PATCH 1/7] Add a null range-handler to DwarfCUToModule constructor + +--- + src/common/pecoff/dump_symbols-inl.h | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/common/pecoff/dump_symbols-inl.h b/src/common/pecoff/dump_symbols-inl.h +index 661097d2..ef4136b7 100644 +--- a/src/common/pecoff/dump_symbols-inl.h ++++ b/src/common/pecoff/dump_symbols-inl.h +@@ -257,7 +257,7 @@ bool LoadDwarf(const string& dwarf_filename, + // Make a handler for the root DIE that populates MODULE with the + // data that was found. + DwarfCUToModule::WarningReporter reporter(dwarf_filename, offset); +- DwarfCUToModule root_handler(&file_context, &line_to_module, &reporter); ++ DwarfCUToModule root_handler(&file_context, &line_to_module, nullptr, &reporter); + // Make a Dwarf2Handler that drives the DIEHandler. + dwarf2reader::DIEDispatcher die_dispatcher(&root_handler); + // Make a DWARF parser for the compilation unit at OFFSET. +-- +2.28.0 + diff --git a/recipes/breakpad/all/patches/0022-Build-a-minimal-breakpad-client-library-if-a-MINGW_H.patch b/recipes/breakpad/all/patches/0022-Build-a-minimal-breakpad-client-library-if-a-MINGW_H.patch new file mode 100644 index 0000000..4bd4a3f --- /dev/null +++ b/recipes/breakpad/all/patches/0022-Build-a-minimal-breakpad-client-library-if-a-MINGW_H.patch @@ -0,0 +1,69 @@ +From 5fa811d42c78154290f17e261ce9e8be16911c93 Mon Sep 17 00:00:00 2001 +From: Danny Robson +Date: Thu, 31 Oct 2019 10:44:50 +1100 +Subject: [PATCH 3/7] Build a minimal breakpad-client library if a MINGW_HOST + is detected. + +--- + Makefile.am | 38 ++++++++++++++++++++++++++++++++++++++ + 1 file changed, 38 insertions(+) + +diff --git a/Makefile.am b/Makefile.am +index 83fb5173..e9eecad5 100644 +--- a/Makefile.am ++++ b/Makefile.am +@@ -100,6 +100,21 @@ includecldir = $(includedir)/$(PACKAGE)/common/linux + includecl_HEADERS = $(top_srcdir)/src/common/linux/*.h + endif + ++if MINGW_HOST ++includeclhdir = $(includedir)/$(PACKAGE)/client/windows/handler ++includeclh_HEADERS = $(top_srcdir)/src/client/windows/handler/*.h ++ ++includeclcdir = $(includedir)/$(PACKAGE)/client/windows/crash_generation ++includeclc_HEADERS = $(top_srcdir)/src/client/windows/crash_generation/*.h ++ ++includeclccdir = $(includedir)/$(PACKAGE)/client/windows/common ++includeclcc_HEADERS = $(top_srcdir)/src/client/windows/common/*.h ++ ++includecldir = $(includedir)/$(PACKAGE)/common/windows ++includecl_HEADERS = $(top_srcdir)/src/common/windows/*.h ++ ++endif ++ + includegbcdir = $(includedir)/$(PACKAGE)/google_breakpad/common + includegbc_HEADERS = $(top_srcdir)/src/google_breakpad/common/*.h + +@@ -203,6 +218,29 @@ src_client_linux_libbreakpad_client_a_SOURCES += \ + endif + endif LINUX_HOST + ++if MINGW_HOST ++lib_LIBRARIES += src/client/windows/libbreakpad_client.a ++pkgconfig_DATA += breakpad-client.pc ++ ++src_client_windows_libbreakpad_client_a_SOURCES = \ ++ src/common/windows/guid_string.cc \ ++ src/common/windows/guid_string.h \ ++ src/client/windows/common/auto_critical_section.h \ ++ src/client/windows/common/ipc_protocol.h \ ++ src/client/windows/crash_generation/client_info.cc \ ++ src/client/windows/crash_generation/client_info.h \ ++ src/client/windows/crash_generation/crash_generation_client.cc \ ++ src/client/windows/crash_generation/crash_generation_client.h \ ++ src/client/windows/crash_generation/crash_generation_server.cc \ ++ src/client/windows/crash_generation/crash_generation_server.h \ ++ src/client/windows/crash_generation/minidump_generator.cc \ ++ src/client/windows/crash_generation/minidump_generator.h \ ++ src/client/windows/handler/exception_handler.cc \ ++ src/client/windows/handler/exception_handler.h \ ++ src/client/windows/sender/crash_report_sender.cc \ ++ src/client/windows/sender/crash_report_sender.h ++endif ++ + if !DISABLE_PROCESSOR + src_libbreakpad_a_SOURCES = \ + src/google_breakpad/common/breakpad_types.h \ +-- +2.28.0 + diff --git a/recipes/breakpad/all/patches/0023-Enable-minimalist-build-signatures.patch b/recipes/breakpad/all/patches/0023-Enable-minimalist-build-signatures.patch new file mode 100644 index 0000000..84d26c9 --- /dev/null +++ b/recipes/breakpad/all/patches/0023-Enable-minimalist-build-signatures.patch @@ -0,0 +1,28 @@ +From d717a0f9175d15c26e9d4e7cd1f6b77fd114a1f1 Mon Sep 17 00:00:00 2001 +From: Danny Robson +Date: Thu, 31 Oct 2019 10:45:14 +1100 +Subject: [PATCH 4/7] Enable minimalist build signatures + +Any minimisation of signature collisions makes managing collections of +symbol files substantially easier. The default of '0' is unworkable when +actually deployed. +--- + src/common/pecoff/pecoff_file_id.cc | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/common/pecoff/pecoff_file_id.cc b/src/common/pecoff/pecoff_file_id.cc +index 04563c86..a8a9c2f5 100644 +--- a/src/common/pecoff/pecoff_file_id.cc ++++ b/src/common/pecoff/pecoff_file_id.cc +@@ -74,7 +74,7 @@ bool PeCoffFileID::PeCoffFileIdentifierFromMappedFile(const void* base, + age)) + return true; + +-#if 1 ++#if 0 + // XXX: Fallback to a default debug_identifier. + memset(identifier, 0, kMDGUIDSize); + *age = 0; +-- +2.28.0 + diff --git a/recipes/breakpad/all/patches/0024-Disable-the-pseudo-build-ID-generation-for-PECOFF.patch b/recipes/breakpad/all/patches/0024-Disable-the-pseudo-build-ID-generation-for-PECOFF.patch new file mode 100644 index 0000000..108bed8 --- /dev/null +++ b/recipes/breakpad/all/patches/0024-Disable-the-pseudo-build-ID-generation-for-PECOFF.patch @@ -0,0 +1,27 @@ +From 66de6a75c0ee8f8df2840879522d0aee6d34e2b1 Mon Sep 17 00:00:00 2001 +From: Danny Robson +Date: Fri, 1 Nov 2019 11:11:37 +1100 +Subject: [PATCH 5/7] Disable the pseudo-build ID generation for PECOFF + +It should be clearer when the build-id isn't picked up. Using zeros is +far easier to detect than failing down to a faked ID. +--- + src/common/pecoff/pecoff_file_id.cc | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/common/pecoff/pecoff_file_id.cc b/src/common/pecoff/pecoff_file_id.cc +index a8a9c2f5..04563c86 100644 +--- a/src/common/pecoff/pecoff_file_id.cc ++++ b/src/common/pecoff/pecoff_file_id.cc +@@ -74,7 +74,7 @@ bool PeCoffFileID::PeCoffFileIdentifierFromMappedFile(const void* base, + age)) + return true; + +-#if 0 ++#if 1 + // XXX: Fallback to a default debug_identifier. + memset(identifier, 0, kMDGUIDSize); + *age = 0; +-- +2.28.0 + diff --git a/recipes/breakpad/all/patches/0025-Ensure-wide-strings-use-the-wide-versions-of-Windows.patch b/recipes/breakpad/all/patches/0025-Ensure-wide-strings-use-the-wide-versions-of-Windows.patch new file mode 100644 index 0000000..67ab4d7 --- /dev/null +++ b/recipes/breakpad/all/patches/0025-Ensure-wide-strings-use-the-wide-versions-of-Windows.patch @@ -0,0 +1,208 @@ +From dee30faf8a5386b18b6c4368f83cddb3e82b8246 Mon Sep 17 00:00:00 2001 +From: Danny Robson +Date: Thu, 31 Oct 2019 10:41:51 +1100 +Subject: [PATCH 2/7] Ensure wide strings use the wide versions of Windows + syscalls + +This aids cross compilation under MinGW. Otherwise we encounter wide +type conversion errors when it defaults to the ANSI variants of each +syscall. + +There is probably a build flag that dynamically switches these calls, +but usage of wide strings is hard coded in a few places already so +these fixes are necessary regardless. +--- + .../crash_generation_client.cc | 24 ++++++------- + .../crash_generation_server.cc | 16 ++++----- + .../crash_generation/minidump_generator.cc | 34 +++++++++---------- + .../windows/handler/exception_handler.cc | 18 +++++----- + 4 files changed, 46 insertions(+), 46 deletions(-) + +diff --git a/src/client/windows/crash_generation/crash_generation_client.cc b/src/client/windows/crash_generation/crash_generation_client.cc +index 3ba5d4e4..b33ecb24 100644 +--- a/src/client/windows/crash_generation/crash_generation_client.cc ++++ b/src/client/windows/crash_generation/crash_generation_client.cc +@@ -280,13 +280,13 @@ HANDLE CrashGenerationClient::ConnectToPipe(const wchar_t* pipe_name, + } + + for (int i = 0; i < kPipeConnectMaxAttempts; ++i) { +- HANDLE pipe = CreateFile(pipe_name, +- pipe_access, +- 0, +- NULL, +- OPEN_EXISTING, +- flags_attrs, +- NULL); ++ HANDLE pipe = CreateFileW(pipe_name, ++ pipe_access, ++ 0, ++ NULL, ++ OPEN_EXISTING, ++ flags_attrs, ++ NULL); + if (pipe != INVALID_HANDLE_VALUE) { + return pipe; + } +@@ -298,7 +298,7 @@ HANDLE CrashGenerationClient::ConnectToPipe(const wchar_t* pipe_name, + } + + // Cannot continue retrying if wait on pipe fails. +- if (!WaitNamedPipe(pipe_name, kPipeBusyWaitTimeoutMs)) { ++ if (!WaitNamedPipeW(pipe_name, kPipeBusyWaitTimeoutMs)) { + break; + } + } +@@ -376,9 +376,9 @@ bool CrashGenerationClient::SignalCrashEventAndWait() { + HANDLE CrashGenerationClient::DuplicatePipeToClientProcess(const wchar_t* pipe_name, + HANDLE hProcess) { + for (int i = 0; i < kPipeConnectMaxAttempts; ++i) { +- HANDLE local_pipe = CreateFile(pipe_name, kPipeDesiredAccess, +- 0, NULL, OPEN_EXISTING, +- kPipeFlagsAndAttributes, NULL); ++ HANDLE local_pipe = CreateFileW(pipe_name, kPipeDesiredAccess, ++ 0, NULL, OPEN_EXISTING, ++ kPipeFlagsAndAttributes, NULL); + if (local_pipe != INVALID_HANDLE_VALUE) { + HANDLE remotePipe = INVALID_HANDLE_VALUE; + if (DuplicateHandle(GetCurrentProcess(), local_pipe, +@@ -395,7 +395,7 @@ HANDLE CrashGenerationClient::DuplicatePipeToClientProcess(const wchar_t* pipe_n + return INVALID_HANDLE_VALUE; + } + +- if (!WaitNamedPipe(pipe_name, kPipeBusyWaitTimeoutMs)) { ++ if (!WaitNamedPipeW(pipe_name, kPipeBusyWaitTimeoutMs)) { + return INVALID_HANDLE_VALUE; + } + } +diff --git a/src/client/windows/crash_generation/crash_generation_server.cc b/src/client/windows/crash_generation/crash_generation_server.cc +index 0af213ba..619ced43 100644 +--- a/src/client/windows/crash_generation/crash_generation_server.cc ++++ b/src/client/windows/crash_generation/crash_generation_server.cc +@@ -239,14 +239,14 @@ bool CrashGenerationServer::Start() { + return false; + } + +- pipe_ = CreateNamedPipe(pipe_name_.c_str(), +- kPipeAttr, +- kPipeMode, +- 1, +- kOutBufferSize, +- kInBufferSize, +- 0, +- pipe_sec_attrs_); ++ pipe_ = CreateNamedPipeW(pipe_name_.c_str(), ++ kPipeAttr, ++ kPipeMode, ++ 1, ++ kOutBufferSize, ++ kInBufferSize, ++ 0, ++ pipe_sec_attrs_); + if (pipe_ == INVALID_HANDLE_VALUE) { + return false; + } +diff --git a/src/client/windows/crash_generation/minidump_generator.cc b/src/client/windows/crash_generation/minidump_generator.cc +index 573c2786..f274e502 100644 +--- a/src/client/windows/crash_generation/minidump_generator.cc ++++ b/src/client/windows/crash_generation/minidump_generator.cc +@@ -468,13 +468,13 @@ bool MinidumpGenerator::GenerateDumpFile(wstring* dump_path) { + return false; + } + +- dump_file_ = CreateFile(dump_file_path.c_str(), +- GENERIC_WRITE, +- 0, +- NULL, +- CREATE_NEW, +- FILE_ATTRIBUTE_NORMAL, +- NULL); ++ dump_file_ = CreateFileW(dump_file_path.c_str(), ++ GENERIC_WRITE, ++ 0, ++ NULL, ++ CREATE_NEW, ++ FILE_ATTRIBUTE_NORMAL, ++ NULL); + if (dump_file_ == INVALID_HANDLE_VALUE) { + return false; + } +@@ -501,15 +501,15 @@ bool MinidumpGenerator::GenerateFullDumpFile(wstring* full_dump_path) { + return false; + } + full_dump_file_path.resize(full_dump_file_path.size() - 4); // strip .dmp +- full_dump_file_path.append(TEXT("-full.dmp")); +- +- full_dump_file_ = CreateFile(full_dump_file_path.c_str(), +- GENERIC_WRITE, +- 0, +- NULL, +- CREATE_NEW, +- FILE_ATTRIBUTE_NORMAL, +- NULL); ++ full_dump_file_path.append(TEXT(L"-full.dmp")); ++ ++ full_dump_file_ = CreateFileW(full_dump_file_path.c_str(), ++ GENERIC_WRITE, ++ 0, ++ NULL, ++ CREATE_NEW, ++ FILE_ATTRIBUTE_NORMAL, ++ NULL); + if (full_dump_file_ == INVALID_HANDLE_VALUE) { + return false; + } +@@ -576,7 +576,7 @@ bool MinidumpGenerator::GenerateDumpFilePath(wstring* file_path) { + + wstring id_str = GUIDString::GUIDToWString(&uuid_); + +- *file_path = dump_path_ + TEXT("\\") + id_str + TEXT(".dmp"); ++ *file_path = dump_path_ + TEXT(L"\\") + id_str + TEXT(L".dmp"); + return true; + } + +diff --git a/src/client/windows/handler/exception_handler.cc b/src/client/windows/handler/exception_handler.cc +index ad45b200..99783ad0 100644 +--- a/src/client/windows/handler/exception_handler.cc ++++ b/src/client/windows/handler/exception_handler.cc +@@ -226,7 +226,7 @@ void ExceptionHandler::Initialize( + assert(handler_thread_ != NULL); + } + +- dbghelp_module_ = LoadLibrary(L"dbghelp.dll"); ++ dbghelp_module_ = LoadLibraryW(L"dbghelp.dll"); + if (dbghelp_module_) { + minidump_write_dump_ = reinterpret_cast( + GetProcAddress(dbghelp_module_, "MiniDumpWriteDump")); +@@ -235,7 +235,7 @@ void ExceptionHandler::Initialize( + // Load this library dynamically to not affect existing projects. Most + // projects don't link against this directly, it's usually dynamically + // loaded by dependent code. +- rpcrt4_module_ = LoadLibrary(L"rpcrt4.dll"); ++ rpcrt4_module_ = LoadLibraryW(L"rpcrt4.dll"); + if (rpcrt4_module_) { + uuid_create_ = reinterpret_cast( + GetProcAddress(rpcrt4_module_, "UuidCreate")); +@@ -917,13 +917,13 @@ bool ExceptionHandler::WriteMinidumpWithExceptionForProcess( + bool write_requester_stream) { + bool success = false; + if (minidump_write_dump_) { +- HANDLE dump_file = CreateFile(next_minidump_path_c_, +- GENERIC_WRITE, +- 0, // no sharing +- NULL, +- CREATE_NEW, // fail if exists +- FILE_ATTRIBUTE_NORMAL, +- NULL); ++ HANDLE dump_file = CreateFileW(next_minidump_path_c_, ++ GENERIC_WRITE, ++ 0, // no sharing ++ NULL, ++ CREATE_NEW, // fail if exists ++ FILE_ATTRIBUTE_NORMAL, ++ NULL); + if (dump_file != INVALID_HANDLE_VALUE) { + MINIDUMP_EXCEPTION_INFORMATION except_info; + except_info.ThreadId = requesting_thread_id; +-- +2.28.0 + diff --git a/recipes/breakpad/all/patches/0026-string_conversion-workaround-GCC10-codegen-bug.patch b/recipes/breakpad/all/patches/0026-string_conversion-workaround-GCC10-codegen-bug.patch new file mode 100644 index 0000000..bcadd08 --- /dev/null +++ b/recipes/breakpad/all/patches/0026-string_conversion-workaround-GCC10-codegen-bug.patch @@ -0,0 +1,27 @@ +From 61f9afe7d83da074a72f563e419bffa9d3948154 Mon Sep 17 00:00:00 2001 +From: Danny Robson +Date: Mon, 17 Feb 2020 14:38:43 +1100 +Subject: [PATCH 7/7] string_conversion: workaround GCC10 codegen bug + +--- + src/common/string_conversion.cc | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/src/common/string_conversion.cc b/src/common/string_conversion.cc +index 11d60a36..bcc54576 100644 +--- a/src/common/string_conversion.cc ++++ b/src/common/string_conversion.cc +@@ -115,7 +115,9 @@ void UTF32ToUTF16Char(wchar_t in, uint16_t out[2]) { + } + + static inline uint16_t Swap(uint16_t value) { +- return (value >> 8) | static_cast(value << 8); ++ // HACK: Use addition rather than bitwise-or to workaround an internal ++ // compiler bug in AST generator for left-rotate under GCC-10_pre. ++ return (value >> 8u) + static_cast(value << 8u); + } + + string UTF16ToUTF8(const vector &in, bool swap) { +-- +2.28.0 + diff --git a/recipes/libcurl/all/conandata.yml b/recipes/libcurl/all/conandata.yml new file mode 100644 index 0000000..fccd69f --- /dev/null +++ b/recipes/libcurl/all/conandata.yml @@ -0,0 +1,38 @@ +sources: + "7.72.0": + sha256: d4d5899a3868fbb6ae1856c3e55a32ce35913de3956d1973caccd37bd0174fa2 + url: https://curl.haxx.se/download/curl-7.72.0.tar.gz + "7.71.1": + sha256: 59ef1f73070de67b87032c72ee6037cedae71dcb1d7ef2d7f59487704aec069d + url: https://curl.haxx.se/download/curl-7.71.1.tar.gz + "7.71.0": + sha256: 62b2b1acee40c4de5a4913e27a4b4194813cf2b7815b73febec7ae53054646ca + url: https://curl.haxx.se/download/curl-7.71.0.tar.gz + "7.70.0": + sha256: ca2feeb8ef13368ce5d5e5849a5fd5e2dd4755fecf7d8f0cc94000a4206fb8e7 + url: https://curl.haxx.se/download/curl-7.70.0.tar.gz + "7.69.1": + sha256: 01ae0c123dee45b01bbaef94c0bc00ed2aec89cb2ee0fd598e0d302a6b5e0a98 + url: https://curl.haxx.se/download/curl-7.69.1.tar.gz + "7.68.0": + sha256: 1dd7604e418b0b9a9077f62f763f6684c1b092a7bc17e3f354b8ad5c964d7358 + url: https://curl.haxx.se/download/curl-7.68.0.tar.gz + "7.67.0": + sha256: 52af3361cf806330b88b4fe6f483b6844209d47ae196ac46da4de59bb361ab02 + url: https://curl.haxx.se/download/curl-7.67.0.tar.gz + "7.66.0": + sha256: d0393da38ac74ffac67313072d7fe75b1fa1010eb5987f63f349b024a36b7ffb + url: https://curl.haxx.se/download/curl-7.66.0.tar.gz + "7.64.1": + sha256: 432d3f466644b9416bc5b649d344116a753aeaa520c8beaf024a90cba9d3d35d + url: https://curl.haxx.se/download/curl-7.64.1.tar.gz +patches: + "7.67.0": + - patch_file: "patches/001-Update-FindLibSSH2.cmake-add-libssh2-as-possible-nam.patch" + base_path: "source_subfolder" + "7.66.0": + - patch_file: "patches/001-Update-FindLibSSH2.cmake-add-libssh2-as-possible-nam.patch" + base_path: "source_subfolder" + "7.64.1": + - patch_file: "patches/001-Update-FindLibSSH2.cmake-add-libssh2-as-possible-nam.patch" + base_path: "source_subfolder" diff --git a/recipes/libcurl/all/conanfile.py b/recipes/libcurl/all/conanfile.py new file mode 100644 index 0000000..d9b971a --- /dev/null +++ b/recipes/libcurl/all/conanfile.py @@ -0,0 +1,564 @@ +import glob +import os +import re +from conans import ConanFile, AutoToolsBuildEnvironment, RunEnvironment, CMake, tools +from conans.errors import ConanInvalidConfiguration + + +class LibcurlConan(ConanFile): + name = "libcurl" + + description = "command line tool and library for transferring data with URLs" + topics = ("conan", "curl", "libcurl", "data-transfer") + url = "https://github.com/conan-io/conan-center-index" + homepage = "https://curl.haxx.se" + license = "MIT" + exports_sources = ["lib_Makefile_add.am", "CMakeLists.txt", "patches/*"] + generators = "cmake", "cmake_find_package_multi", "pkg_config" + + settings = "os", "arch", "compiler", "build_type" + options = {"shared": [True, False], + "fPIC": [True, False], + "with_ssl": [False, "openssl", "wolfssl", "schannel", "darwinssl"], + "with_openssl": [True, False], + "with_wolfssl": [True, False], + "with_winssl": [True, False], + "darwin_ssl": [True, False], + "with_ldap": [True, False], + "with_libssh2": [True, False], + "with_libidn": [True, False], + "with_librtmp": [True, False], + "with_libmetalink": [True, False], + "with_libpsl": [True, False], + "with_largemaxwritesize": [True, False], + "with_nghttp2": [True, False], + "with_zlib": [True, False], + "with_brotli": [True, False] + } + default_options = {"shared": False, + "fPIC": True, + "with_ssl": "openssl", + "with_openssl": True, # deprecated + "with_wolfssl": False, # deprecated + "with_winssl": False, # deprecated + "darwin_ssl": True, # deprecated + "with_ldap": False, + "with_libssh2": False, + "with_libidn": False, + "with_librtmp": False, + "with_libmetalink": False, + "with_libpsl": False, + "with_largemaxwritesize": False, + "with_nghttp2": False, + "with_zlib": True, + "with_brotli": False + } + + _autotools = None + _autotools_vars = None + _cmake = None + + @property + def _source_subfolder(self): + return "source_subfolder" + + @property + def _build_subfolder(self): + return "build_subfolder" + + @property + def _is_mingw(self): + return self.settings.os == "Windows" and self.settings.compiler != "Visual Studio" + + @property + def _is_win_x_android(self): + return self.settings.os == "Android" and tools.os_info.is_windows + + @property + def _is_using_cmake_build(self): + return self.settings.compiler == "Visual Studio" or self._is_win_x_android + + def config_options(self): + if self.settings.os == "Windows": + del self.options.fPIC + # Default options + if tools.is_apple_os(self.settings.os): + self.options.with_ssl = "darwinssl" + self.options.with_openssl = False + self.options.with_wolfssl = False + self.options.with_winssl = False + self.options.darwin_ssl = True + else: + self.options.with_ssl = "openssl" + self.options.with_openssl = True + self.options.with_wolfssl = False + self.options.with_winssl = False + self.options.darwin_ssl = False + + def configure(self): + if self.options.shared: + del self.options.fPIC + del self.settings.compiler.libcxx + del self.settings.compiler.cppstd + + # Deprecated options + # =============================== + self.output.warn("with_openssl, with_winssl, darwin_ssl and with_wolfssl options are deprecated. Use with_ssl option instead.") + if tools.is_apple_os(self.settings.os) and self.options.with_ssl == "darwinssl": + if self.options.darwin_ssl: + self.options.with_ssl = "darwinssl" + elif self.options.with_openssl: + self.options.with_ssl = "openssl" + elif self.options.with_wolfssl: + self.options.with_ssl = "wolfssl" + else: + self.options.with_ssl = False + if not tools.is_apple_os(self.settings.os) and self.options.with_ssl == "openssl": + if self.settings.os == "Windows" and self.options.with_winssl: + self.options.with_ssl = "schannel" + elif self.options.with_openssl: + self.options.with_ssl = "openssl" + elif self.options.with_wolfssl: + self.options.with_ssl = "wolfssl" + else: + self.options.with_ssl = False + del self.options.with_openssl + del self.options.with_winssl + del self.options.darwin_ssl + del self.options.with_wolfssl + # =============================== + + if self.options.with_ssl == "schannel" and self.settings.os != "Windows": + raise ConanInvalidConfiguration("schannel only suppported on Windows.") + if self.options.with_ssl == "darwinssl" and not tools.is_apple_os(self.settings.os): + raise ConanInvalidConfiguration("darwinssl only suppported on Apple like OS (Macos, iOS, watchOS or tvOS).") + if self.options.with_ssl == "wolfssl" and self._is_using_cmake_build and tools.Version(self.version) < "7.70.0": + raise ConanInvalidConfiguration("Before 7.70.0, libcurl has no wolfssl support for Visual Studio or \"Windows to Android cross compilation\"") + + # These options are not used in CMake build yet + if self._is_using_cmake_build: + del self.options.with_libidn + del self.options.with_librtmp + del self.options.with_libmetalink + del self.options.with_libpsl + + def requirements(self): + if self.options.with_ssl == "openssl": + self.requires("openssl/1.1.1g") + elif self.options.with_ssl == "wolfssl": + self.requires("wolfssl/4.4.0") + if self.options.with_nghttp2: + self.requires("libnghttp2/1.40.0") + if self.options.with_libssh2: + self.requires("libssh2/1.9.0") + if self.options.with_zlib: + self.requires("zlib/1.2.11") + if self.options.with_brotli: + self.requires("brotli/1.0.7") + + def build_requirements(self): + if self._is_mingw and tools.os_info.is_windows and not tools.get_env("CONAN_BASH_PATH") and \ + tools.os_info.detect_windows_subsystem() != "msys2": + self.build_requires("msys2/20200517") + elif self._is_win_x_android: + self.build_requires("ninja/1.10.0") + elif not tools.os_info.is_windows: + self.build_requires("libtool/2.4.6") + + def source(self): + tools.get(**self.conan_data["sources"][self.version]) + os.rename("curl-%s" % self.version, self._source_subfolder) + tools.download("https://curl.haxx.se/ca/cacert.pem", "cacert.pem", verify=True) + + def imports(self): + # Copy shared libraries for dependencies to fix DYLD_LIBRARY_PATH problems + # + # Configure script creates conftest that cannot execute without shared openssl binaries. + # Ways to solve the problem: + # 1. set *LD_LIBRARY_PATH (works with Linux with RunEnvironment + # but does not work on OS X 10.11 with SIP) + # 2. copying dylib's to the build directory (fortunately works on OS X) + if self.settings.os == "Macos": + self.copy("*.dylib*", dst=self._source_subfolder, keep_path=False) + + def build(self): + self._patch_sources() + self._patch_misc_files() + if self._is_using_cmake_build: + self._build_with_cmake() + else: + self._build_with_autotools() + + def _patch_sources(self): + for patch in self.conan_data.get("patches", {}).get(self.version, []): + tools.patch(**patch) + + def _patch_misc_files(self): + if self.options.with_largemaxwritesize: + tools.replace_in_file(os.path.join(self._source_subfolder, "include", "curl", "curl.h"), + "define CURL_MAX_WRITE_SIZE 16384", + "define CURL_MAX_WRITE_SIZE 10485760") + + # https://github.com/curl/curl/issues/2835 + # for additional info, see this comment https://github.com/conan-io/conan-center-index/pull/1008#discussion_r386122685 + if self.settings.compiler == "apple-clang" and self.settings.compiler.version == "9.1": + if self.options.with_ssl == "darwinssl": + tools.replace_in_file(os.path.join(self._source_subfolder, "lib", "vtls", "sectransp.c"), + "#define CURL_BUILD_MAC_10_13 MAC_OS_X_VERSION_MAX_ALLOWED >= 101300", + "#define CURL_BUILD_MAC_10_13 0") + + def _get_configure_command_args(self): + params = [] + params.append("--without-libidn2" if not self.options.with_libidn else "--with-libidn2") + params.append("--without-librtmp" if not self.options.with_librtmp else "--with-librtmp") + params.append("--without-libmetalink" if not self.options.with_libmetalink else "--with-libmetalink") + params.append("--without-libpsl" if not self.options.with_libpsl else "--with-libpsl") + + if self.options.with_ssl == "openssl": + params.append("--with-ssl={}".format(tools.unix_path(self.deps_cpp_info["openssl"].rootpath))) + elif self.options.with_ssl == "wolfssl": + params.append("--with-wolfssl={}".format(tools.unix_path(self.deps_cpp_info["wolfssl"].rootpath))) + params.append("--without-ssl") + elif self.options.with_ssl == "schannel": + params.append("--with-schannel") + params.append("--without-ssl") + elif self.options.with_ssl == "darwinssl": + params.append("--with-darwinssl") + params.append("--without-ssl") + else: + params.append("--without-ssl") + + if self.options.with_libssh2: + params.append("--with-libssh2={}".format(tools.unix_path(self.deps_cpp_info["libssh2"].lib_paths[0]))) + else: + params.append("--without-libssh2") + + if self.options.with_nghttp2: + params.append("--with-nghttp2={}".format(tools.unix_path(self.deps_cpp_info["libnghttp2"].rootpath))) + else: + params.append("--without-nghttp2") + + if self.options.with_zlib: + params.append("--with-zlib={}".format(tools.unix_path(self.deps_cpp_info["zlib"].lib_paths[0]))) + else: + params.append("--without-zlib") + + params.append("--with-brotli" if self.options.with_brotli else "--without-brotli") + + if not self.options.shared: + params.append("--disable-shared") + params.append("--enable-static") + else: + params.append("--enable-shared") + params.append("--disable-static") + + if not self.options.with_ldap: + params.append("--disable-ldap") + + if self.settings.build_type == "Debug": + params.append("--enable-debug") + + # Cross building flags + if tools.cross_building(self.settings): + if self.settings.os == "Linux" and "arm" in self.settings.arch: + params.append("--host=%s" % self._get_linux_arm_host()) + elif self.settings.os == "iOS": + params.append("--enable-threaded-resolver") + params.append("--disable-verbose") + elif self.settings.os == "Android": + pass # this just works, conan is great! + + return params + + def _get_linux_arm_host(self): + arch = None + if self.settings.os == "Linux": + arch = "arm-linux-gnu" + # aarch64 could be added by user + if "aarch64" in self.settings.arch: + arch = "aarch64-linux-gnu" + elif "arm" in self.settings.arch and "hf" in self.settings.arch: + arch = "arm-linux-gnueabihf" + elif "arm" in self.settings.arch and self._arm_version(str(self.settings.arch)) > 4: + arch = "arm-linux-gnueabi" + return arch + + # TODO, this should be a inner fuction of _get_linux_arm_host since it is only used from there + # it should not polute the class namespace, since there are iOS and Android arm aritectures also + def _arm_version(self, arch): + version = None + match = re.match(r"arm\w*(\d)", arch) + if match: + version = int(match.group(1)) + return version + + def _patch_mingw_files(self): + if not self._is_mingw: + return + # patch autotools files + # for mingw builds - do not compile curl tool, just library + # linking errors are much harder to fix than to exclude curl tool + tools.replace_in_file("Makefile.am", + "SUBDIRS = lib src", + "SUBDIRS = lib") + + tools.replace_in_file("Makefile.am", + "include src/Makefile.inc", + "") + + # patch for zlib naming in mingw + # when cross-building, the name is correct + if not tools.cross_building(self.settings): + tools.replace_in_file("configure.ac", + "-lz ", + "-lzlib ") + + # patch for openssl extras in mingw + if self.options.with_ssl == "openssl": + tools.replace_in_file("configure", + "-lcrypto ", + "-lcrypto -lcrypt32 ") + + if self.options.shared: + # patch for shared mingw build + tools.replace_in_file(os.path.join("lib", "Makefile.am"), + "noinst_LTLIBRARIES = libcurlu.la", + "") + tools.replace_in_file(os.path.join("lib", "Makefile.am"), + "noinst_LTLIBRARIES =", + "") + tools.replace_in_file(os.path.join("lib", "Makefile.am"), + "lib_LTLIBRARIES = libcurl.la", + "noinst_LTLIBRARIES = libcurl.la") + # add directives to build dll + # used only for native mingw-make + if not tools.cross_building(self.settings): + added_content = tools.load(os.path.join(self.source_folder, "lib_Makefile_add.am")) + tools.save(os.path.join("lib", "Makefile.am"), added_content, append=True) + + def _build_with_autotools(self): + with tools.chdir(self._source_subfolder): + # autoreconf + self.run("./buildconf", win_bash=tools.os_info.is_windows, run_environment=True) + + # fix generated autotools files on alle to have relocateable binaries + if tools.is_apple_os(self.settings.os): + tools.replace_in_file("configure", "-install_name \\$rpath/", "-install_name ") + + self.run("chmod +x configure") + + env_run = RunEnvironment(self) + # run configure with *LD_LIBRARY_PATH env vars it allows to pick up shared openssl + self.output.info("Run vars: " + repr(env_run.vars)) + with tools.environment_append(env_run.vars): + autotools, autotools_vars = self._configure_autotools() + autotools.make(vars=autotools_vars) + + def _configure_autotools_vars(self): + autotools_vars = self._autotools.vars + # tweaks for mingw + if self._is_mingw: + autotools_vars["RCFLAGS"] = "-O COFF" + if self.settings.arch == "x86": + autotools_vars["RCFLAGS"] += " --target=pe-i386" + else: + autotools_vars["RCFLAGS"] += " --target=pe-x86-64" + + del autotools_vars["LIBS"] + self.output.info("Autotools env vars: " + repr(autotools_vars)) + + if tools.cross_building(self.settings): + if self.settings.os == "iOS": + iphoneos = tools.apple_sdk_name(self.settings) + ios_dev_target = str(self.settings.os.version).split(".")[0] + + env_cppflags = tools.get_env("CPPFLAGS", "") + socket_flags = " -DHAVE_SOCKET -DHAVE_FCNTL_O_NONBLOCK" + if self.settings.arch in ["x86", "x86_64"]: + autotools_vars["CPPFLAGS"] = "-D__IPHONE_OS_VERSION_MIN_REQUIRED={}0000 {} {}".format( + ios_dev_target, socket_flags , env_cppflags) + elif self.settings.arch in ["armv7", "armv7s", "armv8"]: + autotools_vars["CPPFLAGS"] = "{} {}".format(socket_flags, env_cppflags) + else: + raise ConanInvalidConfiguration("Unsuported iOS arch {}".format(self.settings.arch)) + + cc = tools.XCRun(self.settings, iphoneos).cc + sysroot = "-isysroot {}".format(tools.XCRun(self.settings, iphoneos).sdk_path) + + if self.settings.arch == "armv8": + configure_arch = "arm64" + configure_host = "arm" #unused, autodetected + else: + configure_arch = self.settings.arch + configure_host = self.settings.arch #unused, autodetected + + + arch_flag = "-arch {}".format(configure_arch) + ios_min_version = tools.apple_deployment_target_flag(self.settings.os, self.settings.os.version) + extra_flag = "-Werror=partial-availability" + + # if we debug, maybe add a -gdwarf-2 , but why would we want that? + + autotools_vars["CC"] = cc + autotools_vars["IPHONEOS_DEPLOYMENT_TARGET"] = ios_dev_target + env_cflags = tools.get_env("CFLAGS", "") + autotools_vars["CFLAGS"] = "{} {} {} {}".format( + sysroot, arch_flag, ios_min_version, env_cflags + ) + + if self.options.with_ssl == "openssl": + openssl_path = self.deps_cpp_info["openssl"].rootpath + openssl_libdir = self.deps_cpp_info["openssl"].libdirs[0] + autotools_vars["LDFLAGS"] = "{} {} -L{}/{}".format(arch_flag, sysroot, openssl_path, openssl_libdir) + elif self.options.with_ssl == "wolfssl": + wolfssl_path = self.deps_cpp_info["wolfssl"].rootpath + wolfssl_libdir = self.deps_cpp_info["wolfssl"].libdirs[0] + autotools_vars["LDFLAGS"] = "{} {} -L{}/{}".format(arch_flag, sysroot, wolfssl_path, wolfssl_libdir) + else: + autotools_vars["LDFLAGS"] = "{} {}".format(arch_flag, sysroot) + + elif self.settings.os == "Android": + # nothing do to at the moment, this seems to just work + pass + + return autotools_vars + + def _configure_autotools(self): + if self._autotools and self._autotools_vars: + return self._autotools, self._autotools_vars + + self._autotools = AutoToolsBuildEnvironment(self, win_bash=tools.os_info.is_windows) + + if self.settings.os != "Windows": + self._autotools.fpic = self.options.get_safe("fPIC", True) + + self._autotools_vars = self._configure_autotools_vars() + + # tweaks for mingw + if self._is_mingw: + # patch autotools files + self._patch_mingw_files() + + self._autotools.defines.append("_AMD64_") + + configure_args = self._get_configure_command_args() + + if self.settings.os == "iOS" and self.settings.arch == "x86_64": + # please do not autodetect --build for the iOS simulator, thanks! + self._autotools.configure(vars=self._autotools_vars, args=configure_args, build=False) + else: + self._autotools.configure(vars=self._autotools_vars, args=configure_args) + + return self._autotools, self._autotools_vars + + def _configure_cmake(self): + if self._cmake: + return self._cmake + if self._is_win_x_android: + self._cmake = CMake(self, generator="Ninja") + else: + self._cmake = CMake(self) + self._cmake.definitions["BUILD_TESTING"] = False + self._cmake.definitions["BUILD_CURL_EXE"] = False + self._cmake.definitions["CURL_DISABLE_LDAP"] = not self.options.with_ldap + self._cmake.definitions["BUILD_SHARED_LIBS"] = self.options.shared + self._cmake.definitions["CURL_STATICLIB"] = not self.options.shared + self._cmake.definitions["CMAKE_DEBUG_POSTFIX"] = "" + self._cmake.definitions["CMAKE_USE_SCHANNEL"] = self.options.with_ssl == "schannel" + self._cmake.definitions["CMAKE_USE_OPENSSL"] = self.options.with_ssl == "openssl" + if tools.Version(self.version) >= "7.70.0": + self._cmake.definitions["CMAKE_USE_WOLFSSL"] = self.options.with_ssl == "wolfssl" + self._cmake.definitions["USE_NGHTTP2"] = self.options.with_nghttp2 + self._cmake.definitions["CURL_ZLIB"] = self.options.with_zlib + self._cmake.definitions["CURL_BROTLI"] = self.options.with_brotli + self._cmake.definitions["CMAKE_USE_LIBSSH2"] = self.options.with_libssh2 + self._cmake.configure(build_folder=self._build_subfolder) + return self._cmake + + def _build_with_cmake(self): + # patch cmake files + with tools.chdir(self._source_subfolder): + tools.replace_in_file("CMakeLists.txt", + "include(CurlSymbolHiding)", + "") + + cmake = self._configure_cmake() + cmake.build() + + def package(self): + self.copy("COPYING", dst="licenses", src=self._source_subfolder) + self.copy("cacert.pem", dst="res") + if self._is_using_cmake_build: + cmake = self._configure_cmake() + cmake.install() + tools.rmdir(os.path.join(self.package_folder, "lib", "cmake")) + else: + env_run = RunEnvironment(self) + with tools.environment_append(env_run.vars): + with tools.chdir(self._source_subfolder): + autotools, autotools_vars = self._configure_autotools() + autotools.install(vars=autotools_vars) + tools.rmdir(os.path.join(self.package_folder, "share")) + for la_file in glob.glob(os.path.join(self.package_folder, "lib", "*.la")): + os.remove(la_file) + if self._is_mingw and self.options.shared: + # Handle only mingw libs + self.copy(pattern="*.dll", dst="bin", keep_path=False) + self.copy(pattern="*.dll.a", dst="lib", keep_path=False) + self.copy(pattern="*.lib", dst="lib", keep_path=False) + tools.rmdir(os.path.join(self.package_folder, "lib", "pkgconfig")) + + def package_info(self): + self.cpp_info.names["cmake_find_package"] = "CURL" + self.cpp_info.names["cmake_find_package_multi"] = "CURL" + self.cpp_info.names["pkg_config"] = "libcurl" + self.cpp_info.components["curl"].names["cmake_find_package"] = "libcurl" + self.cpp_info.components["curl"].names["cmake_find_package_multi"] = "libcurl" + self.cpp_info.components["curl"].names["pkg_config"] = "libcurl" + + if self.settings.compiler == "Visual Studio": + self.cpp_info.components["curl"].libs = ["libcurl_imp"] if self.options.shared else ["libcurl"] + else: + self.cpp_info.components["curl"].libs = ["curl"] + if self.settings.os == "Linux": + if self.options.with_libidn: + self.cpp_info.components["curl"].libs.append("idn") + if self.options.with_librtmp: + self.cpp_info.components["curl"].libs.append("rtmp") + + if self.settings.os == "Linux": + self.cpp_info.components["curl"].system_libs = ["rt", "pthread"] + elif self.settings.os == "Windows": + # used on Windows for VS build, native and cross mingw build + self.cpp_info.components["curl"].system_libs = ["ws2_32"] + if self.options.with_ldap: + self.cpp_info.components["curl"].system_libs.append("wldap32") + if self.options.with_ssl == "schannel": + self.cpp_info.components["curl"].system_libs.append("Crypt32") + elif self.settings.os == "Macos": + if self.options.with_ldap: + self.cpp_info.components["curl"].system_libs.append("ldap") + if self.options.with_ssl == "darwinssl": + self.cpp_info.components["curl"].frameworks.extend(["Cocoa", "Security"]) + + if self._is_mingw: + # provide pthread for dependent packages + self.cpp_info.components["curl"].cflags.append("-pthread") + self.cpp_info.components["curl"].exelinkflags.append("-pthread") + self.cpp_info.components["curl"].sharedlinkflags.append("-pthread") + + if not self.options.shared: + self.cpp_info.components["curl"].defines.append("CURL_STATICLIB=1") + + if self.options.with_ssl == "openssl": + self.cpp_info.components["curl"].requires.append("openssl::openssl") + if self.options.with_ssl == "wolfssl": + self.cpp_info.components["curl"].requires.append("wolfssl::wolfssl") + if self.options.with_nghttp2: + self.cpp_info.components["curl"].requires.append("libnghttp2::libnghttp2") + if self.options.with_libssh2: + self.cpp_info.components["curl"].requires.append("libssh2::libssh2") + if self.options.with_zlib: + self.cpp_info.components["curl"].requires.append("zlib::zlib") + if self.options.with_brotli: + self.cpp_info.components["curl"].requires.append("brotli::brotli") diff --git a/recipes/libcurl/all/patches/001-Update-FindLibSSH2.cmake-add-libssh2-as-possible-nam.patch b/recipes/libcurl/all/patches/001-Update-FindLibSSH2.cmake-add-libssh2-as-possible-nam.patch new file mode 100644 index 0000000..6d1ed18 --- /dev/null +++ b/recipes/libcurl/all/patches/001-Update-FindLibSSH2.cmake-add-libssh2-as-possible-nam.patch @@ -0,0 +1,16 @@ +diff --git a/CMake/FindLibSSH2.cmake b/CMake/FindLibSSH2.cmake +index 84822dba7..0d6219425 100644 +--- a/CMake/FindLibSSH2.cmake ++++ b/CMake/FindLibSSH2.cmake +@@ -12,7 +12,7 @@ endif() + find_path(LIBSSH2_INCLUDE_DIR libssh2.h + ) + +-find_library(LIBSSH2_LIBRARY NAMES ssh2 ++find_library(LIBSSH2_LIBRARY NAMES ssh2 libssh2 + ) + + if(LIBSSH2_INCLUDE_DIR) +-- +2.24.0.windows.2 + diff --git a/recipes/libcurl/config.yml b/recipes/libcurl/config.yml new file mode 100644 index 0000000..1723cac --- /dev/null +++ b/recipes/libcurl/config.yml @@ -0,0 +1,19 @@ +versions: + "7.72.0": + folder: all + "7.71.1": + folder: all + "7.71.0": + folder: all + "7.70.0": + folder: all + "7.69.1": + folder: all + "7.68.0": + folder: all + "7.67.0": + folder: all + "7.66.0": + folder: all + "7.64.1": + folder: all diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..77d8d38 --- /dev/null +++ b/requirements.txt @@ -0,0 +1 @@ +conan