aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/client/windows/sender/crash_report_sender.cc226
-rw-r--r--src/client/windows/sender/crash_report_sender.h30
-rw-r--r--src/client/windows/sender/crash_report_sender.vcproj8
-rw-r--r--src/common/windows/http_upload.cc271
-rw-r--r--src/common/windows/http_upload.h101
-rw-r--r--src/common/windows/pdb_source_line_writer.cc (renamed from src/tools/windows/dump_syms/pdb_source_line_writer.cc)44
-rw-r--r--src/common/windows/pdb_source_line_writer.h (renamed from src/tools/windows/dump_syms/pdb_source_line_writer.h)22
-rw-r--r--src/tools/windows/dump_syms/dump_syms.cc7
-rw-r--r--src/tools/windows/dump_syms/dump_syms.vcproj412
-rw-r--r--src/tools/windows/symupload/symupload.cc180
-rwxr-xr-xsrc/tools/windows/symupload/symupload.vcproj215
11 files changed, 1046 insertions, 470 deletions
diff --git a/src/client/windows/sender/crash_report_sender.cc b/src/client/windows/sender/crash_report_sender.cc
index 16c26c2b..2a4f8250 100644
--- a/src/client/windows/sender/crash_report_sender.cc
+++ b/src/client/windows/sender/crash_report_sender.cc
@@ -27,238 +27,18 @@
// (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 <assert.h>
-#include <windows.h>
-#include <wininet.h>
-
-#include <fstream>
-
#include "client/windows/sender/crash_report_sender.h"
+#include "common/windows/http_upload.h"
namespace google_airbag {
-using std::ifstream;
-using std::ios;
-
-static const wchar_t kUserAgent[] = L"Airbag/1.0 (Windows)";
-
-// Helper class which closes an internet handle when it goes away
-class CrashReportSender::AutoInternetHandle {
- public:
- explicit AutoInternetHandle(HINTERNET handle) : handle_(handle) {}
- ~AutoInternetHandle() {
- if (handle_) {
- InternetCloseHandle(handle_);
- }
- }
-
- HINTERNET get() { return handle_; }
-
- private:
- HINTERNET handle_;
-};
-
// static
bool CrashReportSender::SendCrashReport(
const wstring &url, const map<wstring, wstring> &parameters,
const wstring &dump_file_name) {
- // TODO(bryner): support non-ASCII parameter names
- if (!CheckParameters(parameters)) {
- return false;
- }
-
- // Break up the URL and make sure we can handle it
- wchar_t scheme[16], host[256], path[256];
- URL_COMPONENTS components;
- memset(&components, 0, sizeof(components));
- components.dwStructSize = sizeof(components);
- components.lpszScheme = scheme;
- components.dwSchemeLength = sizeof(scheme);
- components.lpszHostName = host;
- components.dwHostNameLength = sizeof(host);
- components.lpszUrlPath = path;
- components.dwUrlPathLength = sizeof(path);
- if (!InternetCrackUrl(url.c_str(), static_cast<DWORD>(url.size()),
- 0, &components)) {
- return false;
- }
- if (wcscmp(scheme, L"http") != 0) {
- return false;
- }
-
- AutoInternetHandle internet(InternetOpen(kUserAgent,
- INTERNET_OPEN_TYPE_DIRECT,
- NULL, // proxy name
- NULL, // proxy bypass
- 0)); // flags
- if (!internet.get()) {
- return false;
- }
-
- AutoInternetHandle connection(InternetConnect(internet.get(),
- host,
- components.nPort,
- NULL, // user name
- NULL, // password
- INTERNET_SERVICE_HTTP,
- 0, // flags
- NULL)); // context
- if (!connection.get()) {
- return false;
- }
-
- AutoInternetHandle request(HttpOpenRequest(connection.get(),
- L"POST",
- path,
- NULL, // version
- NULL, // referer
- NULL, // agent type
- 0, // flags
- NULL)); // context
- if (!request.get()) {
- return false;
- }
-
- wstring boundary = GenerateMultipartBoundary();
- wstring content_type_header = GenerateRequestHeader(boundary);
- HttpAddRequestHeaders(request.get(),
- content_type_header.c_str(),
- -1, HTTP_ADDREQ_FLAG_ADD);
-
- string request_body;
- GenerateRequestBody(parameters, dump_file_name, boundary, &request_body);
-
- // The explicit comparison to TRUE avoids a warning (C4800).
- return (HttpSendRequest(request.get(), NULL, 0,
- const_cast<char *>(request_body.data()),
- static_cast<DWORD>(request_body.size())) == TRUE);
-}
-
-// static
-wstring CrashReportSender::GenerateMultipartBoundary() {
- // The boundary has 27 '-' characters followed by 16 hex digits
- static const wchar_t kBoundaryPrefix[] = L"---------------------------";
- static const int kBoundaryLength = 27 + 16 + 1;
-
- // Generate some random numbers to fill out the boundary
- int r0 = rand();
- int r1 = rand();
-
- wchar_t temp[kBoundaryLength];
- swprintf_s(temp, kBoundaryLength, L"%s%08X%08X", kBoundaryPrefix, r0, r1);
- return wstring(temp);
-}
-
-// static
-wstring CrashReportSender::GenerateRequestHeader(const wstring &boundary) {
- wstring header = L"Content-Type: multipart/form-data; boundary=";
- header += boundary;
- return header;
-}
-
-// static
-bool CrashReportSender::GenerateRequestBody(
- const map<wstring, wstring> &parameters,
- const wstring &minidump_filename, const wstring &boundary,
- string *request_body) {
- vector<char> contents;
- GetFileContents(minidump_filename, &contents);
- if (contents.empty()) {
- return false;
- }
-
- string boundary_str = WideToUTF8(boundary);
- if (boundary_str.empty()) {
- return false;
- }
-
- request_body->clear();
-
- // Append each of the parameter pairs as a form-data part
- for (map<wstring, wstring>::const_iterator pos = parameters.begin();
- pos != parameters.end(); ++pos) {
- request_body->append("--" + boundary_str + "\r\n");
- request_body->append("Content-Disposition: form-data; name=\"" +
- WideToUTF8(pos->first) + "\"\r\n\r\n" +
- WideToUTF8(pos->second) + "\r\n");
- }
-
- // Now append the minidump file as a binary (octet-stream) part
- string filename_utf8 = WideToUTF8(minidump_filename);
- if (filename_utf8.empty()) {
- return false;
- }
-
- request_body->append("--" + boundary_str + "\r\n");
- request_body->append("Content-Disposition: form-data; "
- "name=\"upload_file_minidump\"; "
- "filename=\"" + filename_utf8 + "\"\r\n");
- request_body->append("Content-Type: application/octet-stream\r\n");
- request_body->append("\r\n");
-
- request_body->append(&(contents[0]), contents.size());
- request_body->append("\r\n");
- request_body->append("--" + boundary_str + "--\r\n");
- return true;
-}
-// static
-void CrashReportSender::GetFileContents(const wstring &filename,
- vector<char> *contents) {
- ifstream file;
- file.open(filename.c_str(), ios::binary);
- if (file.is_open()) {
- file.seekg(0, ios::end);
- int length = file.tellg();
- contents->resize(length);
- file.seekg(0, ios::beg);
- file.read(&((*contents)[0]), length);
- file.close();
- } else {
- contents->clear();
- }
-}
-
-// static
-string CrashReportSender::WideToUTF8(const wstring &wide) {
- if (wide.length() == 0) {
- return string();
- }
-
- // compute the length of the buffer we'll need
- int charcount = WideCharToMultiByte(CP_UTF8, 0, wide.c_str(), -1,
- NULL, 0, NULL, NULL);
- if (charcount == 0) {
- return string();
- }
-
- // convert
- char *buf = new char[charcount];
- WideCharToMultiByte(CP_UTF8, 0, wide.c_str(), -1, buf, charcount,
- NULL, NULL);
-
- string result(buf);
- delete[] buf;
- return result;
-}
-
-// static
-bool CrashReportSender::CheckParameters(
- const map<wstring, wstring> &parameters) {
- for (map<wstring, wstring>::const_iterator pos = parameters.begin();
- pos != parameters.end(); ++pos) {
- const wstring &str = pos->first;
- if (str.size() == 0) {
- return false; // disallow empty parameter names
- }
- for (unsigned int i = 0; i < str.size(); ++i) {
- wchar_t c = str[i];
- if (c < 32 || c == '"' || c > 127) {
- return false;
- }
- }
- }
- return true;
+ return HTTPUpload::SendRequest(url, parameters, dump_file_name,
+ L"upload_file_minidump");
}
} // namespace google_airbag
diff --git a/src/client/windows/sender/crash_report_sender.h b/src/client/windows/sender/crash_report_sender.h
index 52bec788..39267243 100644
--- a/src/client/windows/sender/crash_report_sender.h
+++ b/src/client/windows/sender/crash_report_sender.h
@@ -40,14 +40,11 @@
#include <string>
#include <map>
-#include <vector>
namespace google_airbag {
-using std::string;
using std::wstring;
using std::map;
-using std::vector;
class CrashReportSender {
public:
@@ -62,33 +59,6 @@ class CrashReportSender {
const wstring &dump_file_name);
private:
- class AutoInternetHandle;
-
- // Generates a new multipart boundary for a POST request
- static wstring GenerateMultipartBoundary();
-
- // Generates a HTTP request header for a multipart form submit.
- static wstring GenerateRequestHeader(const wstring &boundary);
-
- // Given a set of parameters and a minidump file name,
- // generates a multipart request body string with these parameters
- // and minidump contents. Returns true on success.
- static bool GenerateRequestBody(const map<wstring, wstring> &parameters,
- const wstring &minidump_filename,
- const wstring &boundary,
- string *request_body);
-
- // Fills the supplied vector with the contents of filename.
- static void GetFileContents(const wstring &filename, vector<char> *contents);
-
- // Converts a UTF16 string to UTF8.
- static string WideToUTF8(const wstring &wide);
-
- // Checks that the given list of parameters has only printable
- // ASCII characters in the parameter name, and does not contain
- // any quote (") characters. Returns true if so.
- static bool CheckParameters(const map<wstring, wstring> &parameters);
-
// No instances of this class should be created.
// Disallow all constructors, destructors, and operator=.
CrashReportSender();
diff --git a/src/client/windows/sender/crash_report_sender.vcproj b/src/client/windows/sender/crash_report_sender.vcproj
index eabb76ce..fc131ef5 100644
--- a/src/client/windows/sender/crash_report_sender.vcproj
+++ b/src/client/windows/sender/crash_report_sender.vcproj
@@ -276,6 +276,10 @@
RelativePath=".\crash_report_sender.cc"
>
</File>
+ <File
+ RelativePath="..\..\..\common\windows\http_upload.cc"
+ >
+ </File>
</Filter>
<Filter
Name="Header Files"
@@ -286,6 +290,10 @@
RelativePath=".\crash_report_sender.h"
>
</File>
+ <File
+ RelativePath="..\..\..\common\windows\http_upload.h"
+ >
+ </File>
</Filter>
<Filter
Name="Resource Files"
diff --git a/src/common/windows/http_upload.cc b/src/common/windows/http_upload.cc
new file mode 100644
index 00000000..52bf46b3
--- /dev/null
+++ b/src/common/windows/http_upload.cc
@@ -0,0 +1,271 @@
+// 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.
+
+#include <assert.h>
+#include <windows.h>
+#include <wininet.h>
+
+#include <fstream>
+
+#include "common/windows/http_upload.h"
+
+namespace google_airbag {
+
+using std::ifstream;
+using std::ios;
+
+static const wchar_t kUserAgent[] = L"Airbag/1.0 (Windows)";
+
+// Helper class which closes an internet handle when it goes away
+class HTTPUpload::AutoInternetHandle {
+ public:
+ explicit AutoInternetHandle(HINTERNET handle) : handle_(handle) {}
+ ~AutoInternetHandle() {
+ if (handle_) {
+ InternetCloseHandle(handle_);
+ }
+ }
+
+ HINTERNET get() { return handle_; }
+
+ private:
+ HINTERNET handle_;
+};
+
+// static
+bool HTTPUpload::SendRequest(const wstring &url,
+ const map<wstring, wstring> &parameters,
+ const wstring &upload_file,
+ const wstring &file_part_name) {
+ // TODO(bryner): support non-ASCII parameter names
+ if (!CheckParameters(parameters)) {
+ return false;
+ }
+
+ // Break up the URL and make sure we can handle it
+ wchar_t scheme[16], host[256], path[256];
+ URL_COMPONENTS components;
+ memset(&components, 0, sizeof(components));
+ components.dwStructSize = sizeof(components);
+ components.lpszScheme = scheme;
+ components.dwSchemeLength = sizeof(scheme);
+ components.lpszHostName = host;
+ components.dwHostNameLength = sizeof(host);
+ components.lpszUrlPath = path;
+ components.dwUrlPathLength = sizeof(path);
+ if (!InternetCrackUrl(url.c_str(), static_cast<DWORD>(url.size()),
+ 0, &components)) {
+ return false;
+ }
+ if (wcscmp(scheme, L"http") != 0) {
+ return false;
+ }
+
+ AutoInternetHandle internet(InternetOpen(kUserAgent,
+ INTERNET_OPEN_TYPE_DIRECT,
+ NULL, // proxy name
+ NULL, // proxy bypass
+ 0)); // flags
+ if (!internet.get()) {
+ return false;
+ }
+
+ AutoInternetHandle connection(InternetConnect(internet.get(),
+ host,
+ components.nPort,
+ NULL, // user name
+ NULL, // password
+ INTERNET_SERVICE_HTTP,
+ 0, // flags
+ NULL)); // context
+ if (!connection.get()) {
+ return false;
+ }
+
+ AutoInternetHandle request(HttpOpenRequest(connection.get(),
+ L"POST",
+ path,
+ NULL, // version
+ NULL, // referer
+ NULL, // agent type
+ 0, // flags
+ NULL)); // context
+ if (!request.get()) {
+ return false;
+ }
+
+ wstring boundary = GenerateMultipartBoundary();
+ wstring content_type_header = GenerateRequestHeader(boundary);
+ HttpAddRequestHeaders(request.get(),
+ content_type_header.c_str(),
+ -1, HTTP_ADDREQ_FLAG_ADD);
+
+ string request_body;
+ GenerateRequestBody(parameters, upload_file,
+ file_part_name, boundary, &request_body);
+
+ // The explicit comparison to TRUE avoids a warning (C4800).
+ return (HttpSendRequest(request.get(), NULL, 0,
+ const_cast<char *>(request_body.data()),
+ static_cast<DWORD>(request_body.size())) == TRUE);
+}
+
+// static
+wstring HTTPUpload::GenerateMultipartBoundary() {
+ // The boundary has 27 '-' characters followed by 16 hex digits
+ static const wchar_t kBoundaryPrefix[] = L"---------------------------";
+ static const int kBoundaryLength = 27 + 16 + 1;
+
+ // Generate some random numbers to fill out the boundary
+ int r0 = rand();
+ int r1 = rand();
+
+ wchar_t temp[kBoundaryLength];
+ swprintf_s(temp, kBoundaryLength, L"%s%08X%08X", kBoundaryPrefix, r0, r1);
+ return wstring(temp);
+}
+
+// static
+wstring HTTPUpload::GenerateRequestHeader(const wstring &boundary) {
+ wstring header = L"Content-Type: multipart/form-data; boundary=";
+ header += boundary;
+ return header;
+}
+
+// static
+bool HTTPUpload::GenerateRequestBody(const map<wstring, wstring> &parameters,
+ const wstring &upload_file,
+ const wstring &file_part_name,
+ const wstring &boundary,
+ string *request_body) {
+ vector<char> contents;
+ GetFileContents(upload_file, &contents);
+ if (contents.empty()) {
+ return false;
+ }
+
+ string boundary_str = WideToUTF8(boundary);
+ if (boundary_str.empty()) {
+ return false;
+ }
+
+ request_body->clear();
+
+ // Append each of the parameter pairs as a form-data part
+ for (map<wstring, wstring>::const_iterator pos = parameters.begin();
+ pos != parameters.end(); ++pos) {
+ request_body->append("--" + boundary_str + "\r\n");
+ request_body->append("Content-Disposition: form-data; name=\"" +
+ WideToUTF8(pos->first) + "\"\r\n\r\n" +
+ WideToUTF8(pos->second) + "\r\n");
+ }
+
+ // Now append the upload file as a binary (octet-stream) part
+ string filename_utf8 = WideToUTF8(upload_file);
+ if (filename_utf8.empty()) {
+ return false;
+ }
+
+ string file_part_name_utf8 = WideToUTF8(file_part_name);
+ if (file_part_name_utf8.empty()) {
+ return false;
+ }
+
+ request_body->append("--" + boundary_str + "\r\n");
+ request_body->append("Content-Disposition: form-data; "
+ "name=\"" + file_part_name_utf8 + "\"; "
+ "filename=\"" + filename_utf8 + "\"\r\n");
+ request_body->append("Content-Type: application/octet-stream\r\n");
+ request_body->append("\r\n");
+
+ request_body->append(&(contents[0]), contents.size());
+ request_body->append("\r\n");
+ request_body->append("--" + boundary_str + "--\r\n");
+ return true;
+}
+
+// static
+void HTTPUpload::GetFileContents(const wstring &filename,
+ vector<char> *contents) {
+ ifstream file;
+ file.open(filename.c_str(), ios::binary);
+ if (file.is_open()) {
+ file.seekg(0, ios::end);
+ int length = file.tellg();
+ contents->resize(length);
+ file.seekg(0, ios::beg);
+ file.read(&((*contents)[0]), length);
+ file.close();
+ } else {
+ contents->clear();
+ }
+}
+
+// static
+string HTTPUpload::WideToUTF8(const wstring &wide) {
+ if (wide.length() == 0) {
+ return string();
+ }
+
+ // compute the length of the buffer we'll need
+ int charcount = WideCharToMultiByte(CP_UTF8, 0, wide.c_str(), -1,
+ NULL, 0, NULL, NULL);
+ if (charcount == 0) {
+ return string();
+ }
+
+ // convert
+ char *buf = new char[charcount];
+ WideCharToMultiByte(CP_UTF8, 0, wide.c_str(), -1, buf, charcount,
+ NULL, NULL);
+
+ string result(buf);
+ delete[] buf;
+ return result;
+}
+
+// static
+bool HTTPUpload::CheckParameters(const map<wstring, wstring> &parameters) {
+ for (map<wstring, wstring>::const_iterator pos = parameters.begin();
+ pos != parameters.end(); ++pos) {
+ const wstring &str = pos->first;
+ if (str.size() == 0) {
+ return false; // disallow empty parameter names
+ }
+ for (unsigned int i = 0; i < str.size(); ++i) {
+ wchar_t c = str[i];
+ if (c < 32 || c == '"' || c > 127) {
+ return false;
+ }
+ }
+ }
+ return true;
+}
+
+} // namespace google_airbag
diff --git a/src/common/windows/http_upload.h b/src/common/windows/http_upload.h
new file mode 100644
index 00000000..4ce581ea
--- /dev/null
+++ b/src/common/windows/http_upload.h
@@ -0,0 +1,101 @@
+// 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.
+
+// HTTPUpload provides a "nice" API to send a multipart HTTP POST
+// request using wininet. It currently supports requests that contain
+// a set of string parameters (key/value pairs), and a file to upload.
+
+#ifndef COMMON_WINDOWS_HTTP_UPLOAD_H__
+#define COMMON_WINDOWS_HTTP_UPLOAD_H__
+
+#include <string>
+#include <map>
+#include <vector>
+namespace google_airbag {
+
+using std::string;
+using std::wstring;
+using std::map;
+using std::vector;
+
+class HTTPUpload {
+ public:
+ // Sends the given set of parameters, along with the contents of
+ // upload_file, as a multipart POST request to the given URL.
+ // file_part_name contains the name of the file part of the request
+ // (i.e. it corresponds to the name= attribute on an <input type="file">.
+ // Parameter names must contain only printable ASCII characters,
+ // and may not contain a quote (") character.
+ // Only HTTP URLs are currently supported. Returns true on success.
+ // TODO(bryner): we should expose the response to the caller.
+ static bool SendRequest(const wstring &url,
+ const map<wstring, wstring> &parameters,
+ const wstring &upload_file,
+ const wstring &file_part_name);
+
+ private:
+ class AutoInternetHandle;
+
+ // Generates a new multipart boundary for a POST request
+ static wstring GenerateMultipartBoundary();
+
+ // Generates a HTTP request header for a multipart form submit.
+ static wstring GenerateRequestHeader(const wstring &boundary);
+
+ // Given a set of parameters, an upload filename, and a file part name,
+ // generates a multipart request body string with these parameters
+ // and minidump contents. Returns true on success.
+ static bool GenerateRequestBody(const map<wstring, wstring> &parameters,
+ const wstring &upload_file,
+ const wstring &file_part_name,
+ const wstring &boundary,
+ string *request_body);
+
+ // Fills the supplied vector with the contents of filename.
+ static void GetFileContents(const wstring &filename, vector<char> *contents);
+
+ // Converts a UTF16 string to UTF8.
+ static string WideToUTF8(const wstring &wide);
+
+ // Checks that the given list of parameters has only printable
+ // ASCII characters in the parameter name, and does not contain
+ // any quote (") characters. Returns true if so.
+ static bool CheckParameters(const map<wstring, wstring> &parameters);
+
+ // No instances of this class should be created.
+ // Disallow all constructors, destructors, and operator=.
+ HTTPUpload();
+ explicit HTTPUpload(const HTTPUpload &);
+ void operator=(const HTTPUpload &);
+ ~HTTPUpload();
+};
+
+} // namespace google_airbag
+
+#endif // COMMON_WINDOWS_HTTP_UPLOAD_H__
diff --git a/src/tools/windows/dump_syms/pdb_source_line_writer.cc b/src/common/windows/pdb_source_line_writer.cc
index 18b5d9ce..b6fe15fe 100644
--- a/src/tools/windows/dump_syms/pdb_source_line_writer.cc
+++ b/src/common/windows/pdb_source_line_writer.cc
@@ -30,7 +30,7 @@
#include <stdio.h>
#include <atlbase.h>
#include <dia2.h>
-#include "pdb_source_line_writer.h"
+#include "common/windows/pdb_source_line_writer.h"
namespace google_airbag {
@@ -40,7 +40,7 @@ PDBSourceLineWriter::PDBSourceLineWriter() : output_(NULL) {
PDBSourceLineWriter::~PDBSourceLineWriter() {
}
-bool PDBSourceLineWriter::Open(const wstring &pdb_file) {
+bool PDBSourceLineWriter::Open(const wstring &file, FileFormat format) {
Close();
if (FAILED(CoInitialize(NULL))) {
@@ -55,9 +55,22 @@ bool PDBSourceLineWriter::Open(const wstring &pdb_file) {
return false;
}
- if (FAILED(data_source->loadDataFromPdb(pdb_file.c_str()))) {
- fprintf(stderr, "loadDataFromPdb failed\n");
- return false;
+ switch (format) {
+ case PDB_FILE:
+ if (FAILED(data_source->loadDataFromPdb(file.c_str()))) {
+ fprintf(stderr, "loadDataFromPdb failed\n");
+ return false;
+ }
+ break;
+ case EXE_FILE:
+ if (FAILED(data_source->loadDataForExe(file.c_str(), NULL, NULL))) {
+ fprintf(stderr, "loadDataForExe failed\n");
+ return false;
+ }
+ break;
+ default:
+ fprintf(stderr, "Unknown file format\n");
+ return false;
}
if (FAILED(data_source->openSession(&session_))) {
@@ -310,4 +323,25 @@ void PDBSourceLineWriter::Close() {
session_.Release();
}
+wstring PDBSourceLineWriter::GetModuleGUID() {
+ CComPtr<IDiaSymbol> global;
+ if (FAILED(session_->get_globalScope(&global))) {
+ return L"";
+ }
+
+ GUID guid;
+ if (FAILED(global->get_guid(&guid))) {
+ return L"";
+ }
+
+ wchar_t guid_buf[37];
+ _snwprintf_s(guid_buf, sizeof(guid_buf)/sizeof(wchar_t), _TRUNCATE,
+ L"%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x\n",
+ guid.Data1, guid.Data2, guid.Data3,
+ guid.Data4[0], guid.Data4[1], guid.Data4[2],
+ guid.Data4[3], guid.Data4[4], guid.Data4[5],
+ guid.Data4[6], guid.Data4[7]);
+ return guid_buf;
+}
+
} // namespace google_airbag
diff --git a/src/tools/windows/dump_syms/pdb_source_line_writer.h b/src/common/windows/pdb_source_line_writer.h
index c6c6563a..c4ce489f 100644
--- a/src/tools/windows/dump_syms/pdb_source_line_writer.h
+++ b/src/common/windows/pdb_source_line_writer.h
@@ -46,12 +46,24 @@ using std::wstring;
class PDBSourceLineWriter {
public:
+ enum FileFormat {
+ PDB_FILE, // a .pdb file containing debug symbols
+ EXE_FILE, // a .exe or .dll file
+ };
+
explicit PDBSourceLineWriter();
~PDBSourceLineWriter();
- // Opens the given pdb file. If there is already a pdb file open,
- // it is automatically closed. Returns true on success.
- bool Open(const wstring &pdb_file);
+ // Opens the given file. For executable files, the corresponding pdb
+ // file must be available; Open will be if it is not.
+ // If there is already a pdb file open, it is automatically closed.
+ // Returns true on success.
+ bool Open(const wstring &file, FileFormat format);
+
+ // Locates the pdb file for the given executable (exe or dll) file,
+ // and opens it. If there is already a pdb file open, it is automatically
+ // closed. Returns true on success.
+ bool OpenExecutable(const wstring &exe_file);
// Writes a map file from the current pdb file to the given file stream.
// Returns true on success.
@@ -60,6 +72,10 @@ class PDBSourceLineWriter {
// Closes the current pdb file and its associated resources.
void Close();
+ // Returns the GUID for the module, as a string,
+ // e.g. "11111111-2222-3333-4444-555555555555".
+ wstring GetModuleGUID();
+
private:
// Outputs the line/address pairs for each line in the enumerator.
// Returns true on success.
diff --git a/src/tools/windows/dump_syms/dump_syms.cc b/src/tools/windows/dump_syms/dump_syms.cc
index c2fa90c2..ca63c2c4 100644
--- a/src/tools/windows/dump_syms/dump_syms.cc
+++ b/src/tools/windows/dump_syms/dump_syms.cc
@@ -32,9 +32,10 @@
#include <stdio.h>
#include <string>
-#include "pdb_source_line_writer.h"
+#include "common/windows/pdb_source_line_writer.h"
using std::wstring;
+using google_airbag::PDBSourceLineWriter;
int main(int argc, char **argv) {
if (argc < 2) {
@@ -48,8 +49,8 @@ int main(int argc, char **argv) {
return 1;
}
- google_airbag::PDBSourceLineWriter writer;
- if (!writer.Open(wstring(filename))) {
+ PDBSourceLineWriter writer;
+ if (!writer.Open(wstring(filename), PDBSourceLineWriter::PDB_FILE)) {
fprintf(stderr, "Open failed\n");
return 1;
}
diff --git a/src/tools/windows/dump_syms/dump_syms.vcproj b/src/tools/windows/dump_syms/dump_syms.vcproj
index 2b42adea..19682d6e 100644
--- a/src/tools/windows/dump_syms/dump_syms.vcproj
+++ b/src/tools/windows/dump_syms/dump_syms.vcproj
@@ -1,206 +1,206 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<VisualStudioProject
- ProjectType="Visual C++"
- Version="8.00"
- Name="dump_syms"
- ProjectGUID="{792E1530-E2C5-4289-992E-317BA30E9D9F}"
- RootNamespace="dumpsyms"
- Keyword="Win32Proj"
- >
- <Platforms>
- <Platform
- Name="Win32"
- />
- </Platforms>
- <ToolFiles>
- </ToolFiles>
- <Configurations>
- <Configuration
- Name="Debug|Win32"
- OutputDirectory="Debug"
- IntermediateDirectory="Debug"
- ConfigurationType="1"
- >
- <Tool
- Name="VCPreBuildEventTool"
- />
- <Tool
- Name="VCCustomBuildTool"
- />
- <Tool
- Name="VCXMLDataGeneratorTool"
- />
- <Tool
- Name="VCWebServiceProxyGeneratorTool"
- />
- <Tool
- Name="VCMIDLTool"
- />
- <Tool
- Name="VCCLCompilerTool"
- Optimization="0"
- AdditionalIncludeDirectories="&quot;$(VSInstallDir)\DIA SDK\include&quot;"
- PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE;"
- MinimalRebuild="true"
- BasicRuntimeChecks="3"
- RuntimeLibrary="3"
- UsePrecompiledHeader="0"
- WarningLevel="3"
- Detect64BitPortabilityProblems="true"
- DebugInformationFormat="4"
- />
- <Tool
- Name="VCManagedResourceCompilerTool"
- />
- <Tool
- Name="VCResourceCompilerTool"
- />
- <Tool
- Name="VCPreLinkEventTool"
- />
- <Tool
- Name="VCLinkerTool"
- AdditionalDependencies="&quot;$(VSInstallDir)\DIA SDK\lib\diaguids.lib&quot;"
- LinkIncremental="2"
- GenerateDebugInformation="true"
- SubSystem="1"
- TargetMachine="1"
- />
- <Tool
- Name="VCALinkTool"
- />
- <Tool
- Name="VCManifestTool"
- />
- <Tool
- Name="VCXDCMakeTool"
- />
- <Tool
- Name="VCBscMakeTool"
- />
- <Tool
- Name="VCFxCopTool"
- />
- <Tool
- Name="VCAppVerifierTool"
- />
- <Tool
- Name="VCWebDeploymentTool"
- />
- <Tool
- Name="VCPostBuildEventTool"
- />
- </Configuration>
- <Configuration
- Name="Release|Win32"
- OutputDirectory="Release"
- IntermediateDirectory="Release"
- ConfigurationType="1"
- >
- <Tool
- Name="VCPreBuildEventTool"
- />
- <Tool
- Name="VCCustomBuildTool"
- />
- <Tool
- Name="VCXMLDataGeneratorTool"
- />
- <Tool
- Name="VCWebServiceProxyGeneratorTool"
- />
- <Tool
- Name="VCMIDLTool"
- />
- <Tool
- Name="VCCLCompilerTool"
- AdditionalIncludeDirectories="&quot;$(VSInstallDir)\DIA SDK\include&quot;"
- PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE;"
- RuntimeLibrary="2"
- UsePrecompiledHeader="0"
- WarningLevel="3"
- Detect64BitPortabilityProblems="true"
- DebugInformationFormat="3"
- />
- <Tool
- Name="VCManagedResourceCompilerTool"
- />
- <Tool
- Name="VCResourceCompilerTool"
- />
- <Tool
- Name="VCPreLinkEventTool"
- />
- <Tool
- Name="VCLinkerTool"
- AdditionalDependencies="&quot;$(VSInstallDir)\DIA SDK\lib\diaguids.lib&quot;"
- LinkIncremental="2"
- GenerateDebugInformation="true"
- SubSystem="1"
- OptimizeReferences="2"
- EnableCOMDATFolding="2"
- TargetMachine="1"
- />
- <Tool
- Name="VCALinkTool"
- />
- <Tool
- Name="VCManifestTool"
- />
- <Tool
- Name="VCXDCMakeTool"
- />
- <Tool
- Name="VCBscMakeTool"
- />
- <Tool
- Name="VCFxCopTool"
- />
- <Tool
- Name="VCAppVerifierTool"
- />
- <Tool
- Name="VCWebDeploymentTool"
- />
- <Tool
- Name="VCPostBuildEventTool"
- />
- </Configuration>
- </Configurations>
- <References>
- </References>
- <Files>
- <Filter
- Name="Header Files"
- Filter="h;hpp;hxx;hm;inl;inc;xsd"
- UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
- >
- <File
- RelativePath=".\pdb_source_line_writer.h"
- >
- </File>
- </Filter>
- <Filter
- Name="Resource Files"
- Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx"
- UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
- >
- </Filter>
- <Filter
- Name="Source Files"
- Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
- UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
- >
- <File
- RelativePath=".\dump_syms.cc"
- >
- </File>
- <File
- RelativePath=".\pdb_source_line_writer.cc"
- >
- </File>
- </Filter>
- </Files>
- <Globals>
- </Globals>
-</VisualStudioProject>
+<?xml version="1.0" encoding="UTF-8"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="8.00"
+ Name="dump_syms"
+ ProjectGUID="{792E1530-E2C5-4289-992E-317BA30E9D9F}"
+ RootNamespace="dumpsyms"
+ Keyword="Win32Proj"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="Debug"
+ IntermediateDirectory="Debug"
+ ConfigurationType="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="&quot;$(VSInstallDir)\DIA SDK\include&quot;;..\..\.."
+ PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE;"
+ MinimalRebuild="true"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="3"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="true"
+ DebugInformationFormat="4"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="&quot;$(VSInstallDir)\DIA SDK\lib\diaguids.lib&quot;"
+ LinkIncremental="2"
+ GenerateDebugInformation="true"
+ SubSystem="1"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory="Release"
+ IntermediateDirectory="Release"
+ ConfigurationType="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories="&quot;$(VSInstallDir)\DIA SDK\include&quot;;..\..\.."
+ PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE;"
+ RuntimeLibrary="2"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="true"
+ DebugInformationFormat="3"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="&quot;$(VSInstallDir)\DIA SDK\lib\diaguids.lib&quot;"
+ LinkIncremental="2"
+ GenerateDebugInformation="true"
+ SubSystem="1"
+ OptimizeReferences="2"
+ EnableCOMDATFolding="2"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Header Files"
+ Filter="h;hpp;hxx;hm;inl;inc;xsd"
+ UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
+ >
+ <File
+ RelativePath="..\..\..\common\windows\pdb_source_line_writer.h"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Resource Files"
+ Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx"
+ UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
+ >
+ </Filter>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
+ UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
+ >
+ <File
+ RelativePath=".\dump_syms.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\common\windows\pdb_source_line_writer.cc"
+ >
+ </File>
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/src/tools/windows/symupload/symupload.cc b/src/tools/windows/symupload/symupload.cc
new file mode 100644
index 00000000..7b530d0f
--- /dev/null
+++ b/src/tools/windows/symupload/symupload.cc
@@ -0,0 +1,180 @@
+// 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.
+
+// Tool to upload an exe/dll and its associated symbols to an HTTP server.
+// The PDB file is located automatically, using the path embedded in the
+// executable. The upload is sent as a multipart/form-data POST request,
+// with the following parameters:
+// module: the name of the module, e.g. app.exe
+// ver: the file version of the module, e.g. 1.2.3.4
+// guid: the GUID string embedded in the module pdb,
+// e.g. 11111111-2222-3333-4444-555555555555
+// symbol_file: the airbag-format symbol file
+
+#include <windows.h>
+#include <wininet.h>
+#include <dbghelp.h>
+
+#include <cstdio>
+#include <vector>
+#include <string>
+#include <map>
+
+#include "common/windows/pdb_source_line_writer.h"
+#include "common/windows/http_upload.h"
+
+using std::string;
+using std::wstring;
+using std::vector;
+using std::map;
+using google_airbag::HTTPUpload;
+using google_airbag::PDBSourceLineWriter;
+
+// Extracts the file version information for the given filename,
+// as a string, for example, "1.2.3.4". Returns true on success.
+static bool GetFileVersionString(const wchar_t *filename, wstring *version) {
+ DWORD handle;
+ DWORD version_size = GetFileVersionInfoSize(filename, &handle);
+ if (version_size < sizeof(VS_FIXEDFILEINFO)) {
+ return false;
+ }
+
+ vector<char> version_info(version_size);
+ if (!GetFileVersionInfo(filename, handle, version_size, &version_info[0])) {
+ return false;
+ }
+
+ void *file_info_buffer = NULL;
+ unsigned int file_info_length;
+ if (!VerQueryValue(&version_info[0], L"\\",
+ &file_info_buffer, &file_info_length)) {
+ return false;
+ }
+
+ // The maximum value of each version component is 65535 (0xffff),
+ // so the max length is 24, including the terminating null.
+ wchar_t ver_string[24];
+ VS_FIXEDFILEINFO *file_info =
+ reinterpret_cast<VS_FIXEDFILEINFO*>(file_info_buffer);
+ _snwprintf_s(ver_string, sizeof(ver_string) / sizeof(wchar_t), _TRUNCATE,
+ L"%d.%d.%d.%d",
+ file_info->dwFileVersionMS >> 16,
+ file_info->dwFileVersionMS & 0xffff,
+ file_info->dwFileVersionLS >> 16,
+ file_info->dwFileVersionLS & 0xffff);
+ *version = ver_string;
+ return true;
+}
+
+// Creates a new temporary file and writes the symbol data from the given
+// exe/dll file to it. Returns the path to the temp file in temp_file_path,
+// and the unique identifier (GUID) for the pdb in module_guid.
+static bool DumpSymbolsToTempFile(const wchar_t *exe_file,
+ wstring *temp_file_path,
+ wstring *module_guid) {
+ google_airbag::PDBSourceLineWriter writer;
+ if (!writer.Open(exe_file, PDBSourceLineWriter::EXE_FILE)) {
+ return false;
+ }
+
+ wchar_t temp_path[_MAX_PATH];
+ if (GetTempPath(_MAX_PATH, temp_path) == 0) {
+ return false;
+ }
+
+ wchar_t temp_filename[_MAX_PATH];
+ if (GetTempFileName(temp_path, L"sym", 0, temp_filename) == 0) {
+ return false;
+ }
+
+ FILE *temp_file = NULL;
+ if (_wfopen_s(&temp_file, temp_filename, L"w") != 0) {
+ return false;
+ }
+
+ bool success = writer.WriteMap(temp_file);
+ fclose(temp_file);
+ if (!success) {
+ _wunlink(temp_filename);
+ return false;
+ }
+
+ *temp_file_path = temp_filename;
+ *module_guid = writer.GetModuleGUID();
+ return true;
+}
+
+// Returns the base name of a file, e.g. strips off the path.
+static wstring GetBaseName(const wstring &filename) {
+ wstring base_name(filename);
+ size_t slash_pos = base_name.find_last_of(L"/\\");
+ if (slash_pos != string::npos) {
+ base_name.erase(0, slash_pos + 1);
+ }
+ return base_name;
+}
+
+int wmain(int argc, wchar_t *argv[]) {
+ if (argc < 3) {
+ wprintf(L"Usage: %s file.[exe|dll] <symbol upload URL>\n", argv[0]);
+ return 0;
+ }
+ const wchar_t *module = argv[1], *url = argv[2];
+ wstring module_basename = GetBaseName(module);
+
+ wstring file_version;
+ if (!GetFileVersionString(module, &file_version)) {
+ fwprintf(stderr, L"Could not get file version for %s\n", module);
+ return 1;
+ }
+
+ wstring symbol_file, module_guid;
+ if (!DumpSymbolsToTempFile(module, &symbol_file, &module_guid)) {
+ fwprintf(stderr, L"Could not get symbol data from %s\n", module);
+ return 1;
+ }
+
+ map<wstring, wstring> parameters;
+ parameters[L"module"] = module_basename;
+ parameters[L"version"] = file_version;
+ parameters[L"guid"] = module_guid;
+
+ bool success = HTTPUpload::SendRequest(url, parameters,
+ symbol_file, L"symbol_file");
+ _wunlink(symbol_file.c_str());
+
+ if (!success) {
+ fwprintf(stderr, L"Symbol file upload failed\n");
+ return 1;
+ }
+
+ wprintf(L"Uploaded symbols for %s/%s/%s\n",
+ module_basename.c_str(), file_version.c_str(), module_guid.c_str());
+ return 0;
+}
diff --git a/src/tools/windows/symupload/symupload.vcproj b/src/tools/windows/symupload/symupload.vcproj
new file mode 100755
index 00000000..63b731c1
--- /dev/null
+++ b/src/tools/windows/symupload/symupload.vcproj
@@ -0,0 +1,215 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="8.00"
+ Name="symupload"
+ ProjectGUID="{E156ED87-9DE9-47C8-94EC-A5A9CDD65E18}"
+ Keyword="Win32Proj"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="Debug"
+ IntermediateDirectory="Debug"
+ ConfigurationType="1"
+ CharacterSet="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="&quot;$(VSInstallDir)\DIA SDK\include&quot;;..\..\.."
+ PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE;"
+ MinimalRebuild="true"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="3"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="true"
+ DebugInformationFormat="4"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="&quot;$(VSInstallDir)\DIA SDK\lib\diaguids.lib&quot; wininet.lib version.lib"
+ LinkIncremental="2"
+ GenerateDebugInformation="true"
+ SubSystem="1"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory="Release"
+ IntermediateDirectory="Release"
+ ConfigurationType="1"
+ CharacterSet="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories="&quot;$(VSInstallDir)\DIA SDK\include&quot;;..\..\.."
+ PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE;"
+ RuntimeLibrary="2"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="true"
+ DebugInformationFormat="3"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="&quot;$(VSInstallDir)\DIA SDK\lib\diaguids.lib&quot; wininet.lib version.lib"
+ LinkIncremental="2"
+ GenerateDebugInformation="true"
+ SubSystem="1"
+ OptimizeReferences="2"
+ EnableCOMDATFolding="2"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Header Files"
+ Filter="h;hpp;hxx;hm;inl;inc;xsd"
+ UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
+ >
+ <File
+ RelativePath="..\..\..\common\windows\http_upload.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\common\windows\pdb_source_line_writer.h"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Resource Files"
+ Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx"
+ UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
+ >
+ </Filter>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
+ UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
+ >
+ <File
+ RelativePath="..\..\..\common\windows\http_upload.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\common\windows\pdb_source_line_writer.cc"
+ >
+ </File>
+ <File
+ RelativePath=".\symupload.cc"
+ >
+ </File>
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>