aboutsummaryrefslogtreecommitdiff
path: root/src/processor
diff options
context:
space:
mode:
Diffstat (limited to 'src/processor')
-rw-r--r--src/processor/network_interface.h62
-rw-r--r--src/processor/network_source_line_protocol.h162
-rw-r--r--src/processor/network_source_line_resolver.cc455
-rw-r--r--src/processor/network_source_line_resolver_server_unittest.cc195
-rw-r--r--src/processor/network_source_line_resolver_unittest.cc535
-rw-r--r--src/processor/network_source_line_server.cc435
-rw-r--r--src/processor/network_source_line_server.h136
-rw-r--r--src/processor/network_source_line_server_unittest.cc963
-rw-r--r--src/processor/source_daemon.cc127
-rw-r--r--src/processor/udp_network.cc187
-rw-r--r--src/processor/udp_network.h73
11 files changed, 0 insertions, 3330 deletions
diff --git a/src/processor/network_interface.h b/src/processor/network_interface.h
deleted file mode 100644
index 3871b4f5..00000000
--- a/src/processor/network_interface.h
+++ /dev/null
@@ -1,62 +0,0 @@
-// Copyright (c) 2010, 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.
-
-// NetworkInterface is an abstract interface for network connections.
-// Its purpose is to make the network portion of certain classes
-// easier to mock for testing. A concrete implementation of this
-// interface can be found in udp_network.h.
-
-#ifndef GOOGLE_BREAKPAD_PROCESSOR_NETWORK_INTERFACE_H_
-#define GOOGLE_BREAKPAD_PROCESSOR_NETWORK_INTERFACE_H_
-namespace google_breakpad {
-
-class NetworkInterface {
- public:
- // Prepare a network connection.
- // If listen is true, prepare the socket to listen for incoming
- // connections.
- // Returns true for success, false for failure.
- virtual bool Init(bool listen) = 0;
-
- // Send length bytes of data to the current address.
- // Returns true for success, false for failure.
- virtual bool Send(const char *data, size_t length) = 0;
-
- // Wait at most timeout milliseconds, returning when data is available or
- // time has expired.
- // Returns true if data is available, false if a timeout or error occurred.
- virtual bool WaitToReceive(int timeout) = 0;
-
- // Read data into buffer. received will contain the number of bytes received.
- // Returns true for success, false for failure.
- virtual bool Receive(char *buffer, size_t buffer_size, ssize_t &received) = 0;
-};
-
-} // namespace google_breakpad
-#endif // GOOGLE_BREAKPAD_PROCESSOR_NETWORK_INTERFACE_H_
diff --git a/src/processor/network_source_line_protocol.h b/src/processor/network_source_line_protocol.h
deleted file mode 100644
index b9744a8a..00000000
--- a/src/processor/network_source_line_protocol.h
+++ /dev/null
@@ -1,162 +0,0 @@
-// Copyright (c) 2010, 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.
-
-// This file contains constants used in the network source line server
-// protocol.
-
-// Brief protocol description:
-//
-// Requests are sent via UDP. All requests begin with a sequence number
-// that is prepended to the response. The sequence number is opaque
-// to the server, it is provided for client tracking of requests.
-//
-// In this file, request and response fields will be described as:
-// <foo:N>, which should be read as "foo, an N byte unsigned integer
-// in network byte order". Strings will be described as <foo:S>.
-//
-// A client request looks like:
-// <seq:2><command:1><command data>
-// Where <seq> is a sequence number as described above, <command>
-// is one of the commands listed below, and <command data> is arbitrary
-// data, defined per-command.
-//
-// A server response looks like:
-// <seq:2><status:1><data>
-// Where <seq> is the same sequence number from the request,
-// <status> is one of the OK or ERROR values defined below,
-// with OK signifying that the request was formatted properly and
-// the response contains data, and ERROR signifying that the request
-// was malformed in some way. <data> is arbitrary data, defined
-// per-command below.
-//
-// Strings are sent as a 2-byte integer encoding the length, followed
-// by <length> bytes.
-//
-// Valid Commands:
-//==================================================
-// <HAS:1><module name:S><debug file:S><debug identifier:S>
-// example: <HAS><0x8>test.dll<0x8>test.pdb<0xA>0123456789
-//
-// Query whether the module with this filename and debug information
-// has been previously loaded.
-//
-// Server Response:
-// <loaded:1>
-// Where <loaded> is one of MODULE_LOADED or MODULE_NOT_LOADED
-//
-//==================================================
-// <LOAD:1><module name:S><debug file:S><debug identifier:S>
-// example: <LOAD><0x8>test.dll<0x8>test.pdb<0xA>0123456789
-//
-// Request that the server find and load symbols for this module.
-//
-// Server Response:
-// <result:1>
-// Where <result> is one of:
-// LOAD_NOT_FOUND
-// - Symbols not found
-// LOAD_INTERRUPT
-// - Processing should be interrupted, symbols may be available later
-// LOAD_FAIL
-// - Found symbols, but failed to load them
-// LOAD_OK
-// - Found and loaded symbols successfully
-//
-//==================================================
-// <GET:1><module name:S><debug file:S><debug identifier:S><module base address:8><instruction address:8>
-// example: <GET><0x8>test.dll<0x8>test.pdb<0x9>0123456789<0x0000000000010000><0x0000000000011A2B>
-//
-// Look up source line info for this module, loaded at this base address,
-// for the code at this instruction address.
-//
-// Server Response:
-// <function:S><func_base:8><source_file:S><source_line:4><source_line_base:8>
-// - As many fields as available are filled in. Fields that are not available
-// will contain an empty string, or a zero for numeric values.
-
-//==================================================
-// <GETSTACKWIN:1><module name:S><debug file:S><debug identifier:S><module base address:8><instruction address:8>
-// example: <GETSTACKWIN><0x8>test.dll<0x8>test.pdb<0x9>0123456789<0x0000000000010000><0x0000000000011A2B>
-//
-// Look up Windows stack frame info for this module, loaded at this base
-// address, for the code at this instruction address.
-//
-// Server Response:
-// <stack:S>
-// The stack info is formatted as in the symbol file format, with
-// "STACK " omitted, as documented at:
-// http://code.google.com/p/google-breakpad/wiki/SymbolFiles
-// If no Windows stack frame info is available, an empty string is returned.
-
-//==================================================
-// <GETSTACKCFI:1><module name:S><debug file:S><debug identifier:S><module base address:8><instruction address:8>
-// example: <GETSTACKCFI><0x8>test.dll<0x8>test.pdb<0x9>0123456789<0x0000000000010000><0x0000000000011A2B>
-//
-// Look up CFI stack frame info for this module, loaded at this base
-// address, for the code at this instruction address.
-//
-// Server Response:
-// <stack:S>
-// The stack info is formatted as in the symbol file format, with
-// "STACK " omitted, as documented at:
-// http://code.google.com/p/google-breakpad/wiki/SymbolFiles
-// If no CFI stack frame info is available, an empty string is returned.
-
-#ifndef GOOGLE_BREAKPAD_PROCESSOR_NETWORK_SOURCE_LINE_PROTOCOL_H_
-#define GOOGLE_BREAKPAD_PROCESSOR_NETWORK_SOURCE_LINE_PROTOCOL_H_
-
-#include "google_breakpad/common/breakpad_types.h"
-
-namespace google_breakpad {
-namespace source_line_protocol {
-
-// Response status codes
-const u_int8_t OK = 1;
-const u_int8_t ERROR = 0;
-
-// Commands
-const u_int8_t HAS = 1;
-const u_int8_t LOAD = 2;
-const u_int8_t GET = 3;
-const u_int8_t GETSTACKWIN = 4;
-const u_int8_t GETSTACKCFI = 5;
-
-// HAS responses
-const u_int8_t MODULE_NOT_LOADED = 0;
-const u_int8_t MODULE_LOADED = 1;
-
-// LOAD responses
-const u_int8_t LOAD_NOT_FOUND = 0;
-const u_int8_t LOAD_INTERRUPT = 1;
-const u_int8_t LOAD_FAIL = 2;
-const u_int8_t LOAD_OK = 3;
-
-} // namespace source_line_protocol
-} // namespace google_breakpad
-#endif // GOOGLE_BREAKPAD_PROCESSOR_NETWORK_SOURCE_LINE_PROTOCOL_H_
diff --git a/src/processor/network_source_line_resolver.cc b/src/processor/network_source_line_resolver.cc
deleted file mode 100644
index 86c939f9..00000000
--- a/src/processor/network_source_line_resolver.cc
+++ /dev/null
@@ -1,455 +0,0 @@
-// Copyright (c) 2010, 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 "google_breakpad/processor/network_source_line_resolver.h"
-
-#include <assert.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <sstream>
-#include <vector>
-
-#include "google_breakpad/processor/stack_frame.h"
-#include "processor/binarystream.h"
-#include "processor/cfi_frame_info.h"
-#include "processor/network_interface.h"
-#include "processor/network_source_line_protocol.h"
-#include "processor/logging.h"
-#include "processor/scoped_ptr.h"
-#include "processor/udp_network.h"
-#include "processor/windows_frame_info.h"
-
-namespace google_breakpad {
-
-using std::string;
-using std::vector;
-using std::dec;
-using std::hex;
-// Style guide forbids "using namespace", so at least shorten it.
-namespace P = source_line_protocol;
-
-NetworkSourceLineResolver::NetworkSourceLineResolver(const string &server,
- unsigned short port,
- int wait_milliseconds)
- : wait_milliseconds_(wait_milliseconds),
- initialized_(false),
- sequence_(0),
- net_(new UDPNetwork(server, port)) {
- if (net_->Init(false))
- initialized_ = true;
-}
-
-NetworkSourceLineResolver::NetworkSourceLineResolver(NetworkInterface *net,
- int wait_milliseconds)
- : wait_milliseconds_(wait_milliseconds),
- initialized_(false),
- sequence_(0),
- net_(net) {
- if (net_ && net->Init(false))
- initialized_ = true;
-}
-
-NetworkSourceLineResolver::~NetworkSourceLineResolver() {
- initialized_ = false;
-}
-
-bool NetworkSourceLineResolver::LoadModule(const CodeModule *module,
- const string &map_file) {
- // Just lie here and say it was loaded. The server always loads
- // symbols immediately when they're found, since clients always
- // will want to load them after finding them anyway. Since this class
- // acts as both the symbol supplier and source line resolver,
- // it's just a little optimization.
- return true;
-}
-
-bool NetworkSourceLineResolver::LoadModuleUsingMapBuffer(
- const CodeModule *module,
- const string &map_buffer) {
- // see above
- return true;
-}
-
-bool NetworkSourceLineResolver::LoadModuleUsingMemoryBuffer(
- const CodeModule *module,
- char *memory_buffer) {
- // see above
- return true;
-}
-
-void NetworkSourceLineResolver::UnloadModule(const CodeModule *module) {
- // no-op
-}
-
-bool NetworkSourceLineResolver::HasModule(const CodeModule *module) {
- if (!initialized_ || !module)
- return false;
-
- // cache seen modules so the network round trip can be skipped
- if (module_cache_.find(module->code_file()) != module_cache_.end())
- return true;
-
- // also cache modules for which symbols aren't found
- if (no_symbols_cache_.find(module->debug_file() + module->debug_identifier())
- != no_symbols_cache_.end())
- return false;
-
- binarystream message;
- message << P::HAS
- << module->code_file()
- << module->debug_file()
- << module->debug_identifier();
- binarystream response;
- bool got_response = SendMessageGetResponse(message, response);
- u_int8_t response_data;
- response >> response_data;
-
- bool found = false;
- if (got_response && !response.eof() && response_data == P::MODULE_LOADED) {
- module_cache_.insert(module->code_file());
- found = true;
- }
- return found;
-}
-
-void NetworkSourceLineResolver::FillSourceLineInfo(
- StackFrame *frame) {
- if (!initialized_)
- return;
-
- // if don't this module isn't loaded, can't fill source line info
- if (!frame->module ||
- module_cache_.find(frame->module->code_file()) == module_cache_.end())
- return;
-
- // if this frame has already been seen, return the cached copy
- if (FindCachedSourceLineInfo(frame)) {
- BPLOG(INFO) << "Using cached source line info";
- return;
- }
-
- binarystream message;
- message << P::GET
- << frame->module->code_file()
- << frame->module->debug_file()
- << frame->module->debug_identifier()
- << frame->module->base_address()
- << frame->instruction;
- binarystream response;
- bool got_response = SendMessageGetResponse(message, response);
- if (!got_response)
- return;
-
- string function_name, source_file;
- u_int32_t source_line;
- u_int64_t function_base, source_line_base;
- response >> function_name >> function_base
- >> source_file >> source_line >> source_line_base;
-
- if (response.eof()) {
- BPLOG(ERROR) << "GET response malformed";
- return;
- } else {
- BPLOG(INFO) << "GET response: " << function_name << " "
- << hex << function_base << " " << source_file << " "
- << dec << source_line << " " << hex
- << source_line_base;
- }
-
- frame->function_name = function_name;
- frame->function_base = function_base;
- frame->source_file_name = source_file;
- frame->source_line = source_line;
- frame->source_line_base = source_line_base;
-
- CacheSourceLineInfo(frame);
-}
-
-WindowsFrameInfo*
-NetworkSourceLineResolver::FindWindowsFrameInfo(const StackFrame *frame) {
- if (!initialized_)
- return NULL;
-
- // if this module isn't loaded, can't get frame info
- if (!frame->module ||
- module_cache_.find(frame->module->code_file()) == module_cache_.end())
- return NULL;
-
- // check the cache first
- string stack_info;
-
- if (FindCachedFrameInfo(frame, kWindowsFrameInfo, &stack_info)) {
- BPLOG(INFO) << "Using cached windows frame info";
- } else {
- binarystream message;
- message << P::GETSTACKWIN
- << frame->module->code_file()
- << frame->module->debug_file()
- << frame->module->debug_identifier()
- << frame->module->base_address()
- << frame->instruction;
- binarystream response;
- if (SendMessageGetResponse(message, response)) {
- response >> stack_info;
- CacheFrameInfo(frame, kWindowsFrameInfo, stack_info);
- }
- }
-
- WindowsFrameInfo *info = NULL;
- if (!stack_info.empty()) {
- int type;
- u_int64_t rva, code_size;
- info = WindowsFrameInfo::ParseFromString(stack_info,
- type,
- rva,
- code_size);
- }
-
- return info;
-}
-
-CFIFrameInfo*
-NetworkSourceLineResolver::FindCFIFrameInfo(const StackFrame *frame)
-{
- if (!initialized_)
- return NULL;
-
- // if this module isn't loaded, can't get frame info
- if (!frame->module ||
- module_cache_.find(frame->module->code_file()) == module_cache_.end())
- return NULL;
-
- string stack_info;
-
- if (FindCachedFrameInfo(frame, kCFIFrameInfo, &stack_info)) {
- BPLOG(INFO) << "Using cached CFI frame info";
- } else {
- binarystream message;
- message << P::GETSTACKCFI
- << frame->module->code_file()
- << frame->module->debug_file()
- << frame->module->debug_identifier()
- << frame->module->base_address()
- << frame->instruction;
- binarystream response;
- if (SendMessageGetResponse(message, response)) {
- response >> stack_info;
- CacheFrameInfo(frame, kCFIFrameInfo, stack_info);
- }
- }
-
- if (!stack_info.empty()) {
- scoped_ptr<CFIFrameInfo> info(new CFIFrameInfo());
- CFIFrameInfoParseHandler handler(info.get());
- CFIRuleParser parser(&handler);
- if (parser.Parse(stack_info))
- return info.release();
- }
-
- return NULL;
-}
-
-SymbolSupplier::SymbolResult
-NetworkSourceLineResolver::GetSymbolFile(const CodeModule *module,
- const SystemInfo *system_info,
- string *symbol_file) {
- BPLOG_IF(ERROR, !symbol_file) << "NetworkSourceLineResolver::GetSymbolFile "
- "requires |symbol_file|";
- assert(symbol_file);
-
- if (!initialized_)
- return NOT_FOUND;
-
- if (no_symbols_cache_.find(module->debug_file() + module->debug_identifier())
- != no_symbols_cache_.end())
- return NOT_FOUND;
-
- binarystream message;
- message << P::LOAD
- << module->code_file()
- << module->debug_file()
- << module->debug_identifier();
- binarystream response;
- bool got_response = SendMessageGetResponse(message, response);
- if (!got_response) {
- // Didn't get a response, which is the same as not having symbols.
- // Don't cache this, though, to force a retry if the client asks for
- // symbols for the same file again.
- return NOT_FOUND;
- }
- u_int8_t response_data;
- response >> response_data;
-
- if (response.eof()) {
- BPLOG(ERROR) << "Malformed LOAD response";
- return NOT_FOUND;
- }
-
- if (response_data == P::LOAD_NOT_FOUND || response_data == P::LOAD_FAIL) {
- // Received NOT or FAIL, symbols not present or failed to load them.
- // Same problem to the client any way you look at it.
- // Cache this module to avoid pointless retry.
- no_symbols_cache_.insert(module->debug_file() + module->debug_identifier());
- return NOT_FOUND;
- } else if (response_data == P::LOAD_INTERRUPT) {
- return INTERRUPT;
- }
-
- // otherwise, OK
- module_cache_.insert(module->code_file());
- *symbol_file = "<loaded on server>";
- return FOUND;
-}
-
-SymbolSupplier::SymbolResult
-NetworkSourceLineResolver::GetSymbolFile(const CodeModule *module,
- const SystemInfo *system_info,
- string *symbol_file,
- string *symbol_data) {
- if(symbol_data)
- symbol_data->clear();
- return GetSymbolFile(module, system_info, symbol_file);
-}
-
-SymbolSupplier::SymbolResult
-NetworkSourceLineResolver::GetCStringSymbolData(
- const CodeModule *module,
- const SystemInfo *system_info,
- string *symbol_file,
- char **symbol_data) {
- if (symbol_data)
- delete *symbol_data;
-
- return GetSymbolFile(module, system_info, symbol_file);
-}
-
-bool NetworkSourceLineResolver::SendMessageGetResponse(
- const binarystream &message,
- binarystream &response) {
- binarystream sequence_stream;
- u_int16_t sent_sequence = sequence_;
- sequence_stream << sequence_;
- ++sequence_;
- string message_string = sequence_stream.str();
- message_string.append(message.str());
- BPLOG(INFO) << "Sending " << message_string.length() << " bytes";
- if (!net_->Send(message_string.c_str(), message_string.length()))
- return false;
-
- bool done = false;
- while (!done) {
- if (!net_->WaitToReceive(wait_milliseconds_))
- return false;
-
- vector<char> buffer(1024);
- ssize_t received_bytes;
- if (!net_->Receive(&buffer[0], buffer.size(), received_bytes))
- return false;
-
- BPLOG(INFO) << "received " << received_bytes << " bytes";
- buffer.resize(received_bytes);
-
- response.str(string(&buffer[0], buffer.size()));
- response.rewind();
- u_int16_t read_sequence;
- u_int8_t status;
- response >> read_sequence >> status;
- if (response.eof()) {
- BPLOG(ERROR) << "malformed response, missing sequence number or status";
- return false;
- }
- if (read_sequence < sent_sequence) // old packet
- continue;
-
- if (read_sequence != sent_sequence) {
- // not expecting this packet, just error
- BPLOG(ERROR) << "error, got sequence number " << read_sequence
- << ", expected " << sent_sequence;
- return false;
- }
-
- // This is the expected packet, so even if it's an error this loop is done
- done = true;
-
- if (status != P::OK) {
- BPLOG(ERROR) << "received an ER response packet";
- return false;
- }
- // the caller will process the rest of response
- }
- return true;
-}
-
-bool NetworkSourceLineResolver::FindCachedSourceLineInfo(StackFrame *frame)
- const
-{
- SourceCache::const_iterator iter =
- source_line_info_cache_.find(frame->instruction);
- if (iter == source_line_info_cache_.end())
- return false;
-
- const StackFrame &f = iter->second;
- frame->function_name = f.function_name;
- frame->function_base = f.function_base;
- frame->source_file_name = f.source_file_name;
- frame->source_line = f.source_line;
- frame->source_line_base = f.source_line_base;
- return true;
-}
-
-bool NetworkSourceLineResolver::FindCachedFrameInfo(
- const StackFrame *frame,
- FrameInfoType type,
- string *info) const
-{
- FrameInfoCache::const_iterator iter =
- frame_info_cache_[type].find(frame->instruction);
- if (iter == frame_info_cache_[type].end())
- return false;
-
- *info = iter->second;
- return true;
-}
-
-void NetworkSourceLineResolver::CacheSourceLineInfo(const StackFrame *frame) {
- StackFrame f(*frame);
- // can't hang onto this pointer, the caller owns it
- f.module = NULL;
- source_line_info_cache_[frame->instruction] = f;
-}
-
-void NetworkSourceLineResolver::CacheFrameInfo(
- const StackFrame *frame,
- FrameInfoType type,
- const string &info) {
- frame_info_cache_[type][frame->instruction] = info;
-}
-
-} // namespace google_breakpad
diff --git a/src/processor/network_source_line_resolver_server_unittest.cc b/src/processor/network_source_line_resolver_server_unittest.cc
deleted file mode 100644
index 0e84536c..00000000
--- a/src/processor/network_source_line_resolver_server_unittest.cc
+++ /dev/null
@@ -1,195 +0,0 @@
-// Copyright (c) 2010, 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.
-
-// Full system test for NetworkSourceLineResolver / NetworkSourceLineServer.
-// Forks a background process to run a NetworkSourceLineServer, then
-// instantiates a MinidumpProcessor with a NetworkSourceLineResolver to
-// connect to the background server and process a minidump.
-
-#include <string>
-
-#include <signal.h>
-#include <sys/wait.h>
-#include <unistd.h>
-
-#include "breakpad_googletest_includes.h"
-#include "google_breakpad/processor/basic_source_line_resolver.h"
-#include "google_breakpad/processor/call_stack.h"
-#include "google_breakpad/processor/minidump_processor.h"
-#include "google_breakpad/processor/process_state.h"
-#include "google_breakpad/processor/network_source_line_resolver.h"
-#include "processor/simple_symbol_supplier.h"
-#include "processor/network_source_line_server.h"
-#include "processor/simple_symbol_supplier.h"
-#include "processor/udp_network.h"
-
-namespace {
-
-using std::string;
-using google_breakpad::BasicSourceLineResolver;
-using google_breakpad::CallStack;
-using google_breakpad::MinidumpProcessor;
-using google_breakpad::NetworkSourceLineResolver;
-using google_breakpad::NetworkSourceLineServer;
-using google_breakpad::ProcessState;
-using google_breakpad::SimpleSymbolSupplier;
-using google_breakpad::UDPNetwork;
-
-static const char *kSystemInfoOS = "Windows NT";
-static const char *kSystemInfoOSShort = "windows";
-static const char *kSystemInfoOSVersion = "5.1.2600 Service Pack 2";
-static const char *kSystemInfoCPU = "x86";
-static const char *kSystemInfoCPUInfo =
- "GenuineIntel family 6 model 13 stepping 8";
-
-bool exitProcess = false;
-
-void signal_handler(int signal) {
- if (signal == SIGINT)
- exitProcess = true;
-}
-
-void RunSourceLineServer(int fd) {
- // Set a signal handler so the parent process
- // can signal this process to end.
- signal(SIGINT, signal_handler);
-
- BasicSourceLineResolver resolver;
- SimpleSymbolSupplier supplier(string(getenv("srcdir") ?
- getenv("srcdir") : ".") +
- "/src/processor/testdata/symbols/");
- UDPNetwork net("localhost",
- 0, // pick a free port
- true); // IPv4 only
-
- NetworkSourceLineServer server(&supplier, &resolver, &net,
- 0); // no source line limit
- unsigned short port = -1;
- bool initialized = server.Initialize();
- if (initialized)
- port = net.port();
-
- // send port number back to parent
- ssize_t written = write(fd, &port, sizeof(port));
- close(fd);
-
- if (!initialized || written != sizeof(port))
- return;
-
- while (!exitProcess) {
- server.RunOnce(100);
- }
-}
-
-TEST(NetworkSourceLineResolverServer, SystemTest) {
- int fds[2];
- ASSERT_EQ(0, pipe(fds));
- // Fork a background process to run the server.
- pid_t pid = fork();
- if (pid == 0) {
- close(fds[0]);
- RunSourceLineServer(fds[1]);
- exit(0);
- }
- ASSERT_NE(-1, pid);
- // Wait for the background process to return info about the port.
- close(fds[1]);
- unsigned short port;
- ssize_t nbytes = read(fds[0], &port, sizeof(port));
- ASSERT_EQ(sizeof(port), nbytes);
- ASSERT_NE(-1, port);
-
- NetworkSourceLineResolver resolver("localhost", port,
- 5000); // wait at most 5 seconds for reply
- MinidumpProcessor processor(&resolver, &resolver);
- // this is all copied from minidump_processor_unittest.cc
- string minidump_file = string(getenv("srcdir") ? getenv("srcdir") : ".") +
- "/src/processor/testdata/minidump2.dmp";
-
- ProcessState state;
- ASSERT_EQ(processor.Process(minidump_file, &state),
- google_breakpad::PROCESS_OK);
- EXPECT_EQ(state.system_info()->os, kSystemInfoOS);
- EXPECT_EQ(state.system_info()->os_short, kSystemInfoOSShort);
- EXPECT_EQ(state.system_info()->os_version, kSystemInfoOSVersion);
- EXPECT_EQ(state.system_info()->cpu, kSystemInfoCPU);
- EXPECT_EQ(state.system_info()->cpu_info, kSystemInfoCPUInfo);
- ASSERT_TRUE(state.crashed());
- EXPECT_EQ(state.crash_reason(), "EXCEPTION_ACCESS_VIOLATION_WRITE");
- EXPECT_EQ(state.crash_address(), 0x45U);
- ASSERT_EQ(state.threads()->size(), size_t(1));
- ASSERT_EQ(state.requesting_thread(), 0);
-
- CallStack *stack = state.threads()->at(0);
- ASSERT_TRUE(stack);
- ASSERT_EQ(stack->frames()->size(), 4U);
-
- // Can now only set non-empty/zero values for function_name, source_file_name
- // and source line on certain platforms (ie. windows), so those are untested.
- ASSERT_TRUE(stack->frames()->at(0)->module);
- EXPECT_EQ(stack->frames()->at(0)->module->base_address(), 0x400000U);
- EXPECT_EQ(stack->frames()->at(0)->module->code_file(), "c:\\test_app.exe");
-
- ASSERT_TRUE(stack->frames()->at(1)->module);
- EXPECT_EQ(stack->frames()->at(1)->module->base_address(), 0x400000U);
- EXPECT_EQ(stack->frames()->at(1)->module->code_file(), "c:\\test_app.exe");
-
- // This comes from the CRT
- ASSERT_TRUE(stack->frames()->at(2)->module);
- EXPECT_EQ(stack->frames()->at(2)->module->base_address(), 0x400000U);
- EXPECT_EQ(stack->frames()->at(2)->module->code_file(), "c:\\test_app.exe");
-
- // OS frame, kernel32.dll
- ASSERT_TRUE(stack->frames()->at(3)->module);
- EXPECT_EQ(stack->frames()->at(3)->module->base_address(), 0x7c800000U);
- EXPECT_EQ(stack->frames()->at(3)->module->code_file(),
- "C:\\WINDOWS\\system32\\kernel32.dll");
-
- ASSERT_EQ(state.modules()->module_count(), 13U);
- ASSERT_TRUE(state.modules()->GetMainModule());
- EXPECT_EQ(state.modules()->GetMainModule()->code_file(), "c:\\test_app.exe");
- EXPECT_FALSE(state.modules()->GetModuleForAddress(0));
- EXPECT_EQ(state.modules()->GetMainModule(),
- state.modules()->GetModuleForAddress(0x400000));
- EXPECT_EQ(state.modules()->GetModuleForAddress(0x7c801234)->debug_file(),
- "kernel32.pdb");
- EXPECT_EQ(state.modules()->GetModuleForAddress(0x77d43210)->version(),
- "5.1.2600.2622");
-
- // Kill background process
- kill(pid, SIGINT);
- ASSERT_EQ(pid, waitpid(pid, NULL, 0));
-}
-
-}
-
-int main(int argc, char *argv[]) {
- ::testing::InitGoogleTest(&argc, argv);
- return RUN_ALL_TESTS();
-}
diff --git a/src/processor/network_source_line_resolver_unittest.cc b/src/processor/network_source_line_resolver_unittest.cc
deleted file mode 100644
index bf0aae78..00000000
--- a/src/processor/network_source_line_resolver_unittest.cc
+++ /dev/null
@@ -1,535 +0,0 @@
-// Copyright (c) 2010, 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.
-
-
-// Unit tests for NetworkSourceLineResolver.
-
-#include <string>
-
-#include "breakpad_googletest_includes.h"
-#include "google_breakpad/processor/network_source_line_resolver.h"
-#include "google_breakpad/processor/stack_frame.h"
-#include "google_breakpad/processor/symbol_supplier.h"
-#include "processor/basic_code_module.h"
-#include "processor/binarystream.h"
-#include "processor/cfi_frame_info.h"
-#include "processor/network_interface.h"
-#include "processor/network_source_line_protocol.h"
-#include "processor/windows_frame_info.h"
-
-namespace google_breakpad {
-class MockNetwork : public NetworkInterface {
- public:
- MockNetwork() {}
-
- MOCK_METHOD1(Init, bool(bool listen));
- MOCK_METHOD2(Send, bool(const char *data, size_t length));
- MOCK_METHOD1(WaitToReceive, bool(int timeout));
- MOCK_METHOD3(Receive, bool(char *buffer, size_t buffer_size,
- ssize_t &received));
-};
-}
-
-namespace {
-using std::string;
-using google_breakpad::binarystream;
-using google_breakpad::BasicCodeModule;
-using google_breakpad::CFIFrameInfo;
-using google_breakpad::MockNetwork;
-using google_breakpad::NetworkSourceLineResolver;
-using google_breakpad::StackFrame;
-using google_breakpad::SymbolSupplier;
-using google_breakpad::WindowsFrameInfo;
-using ::testing::_;
-using ::testing::Invoke;
-using ::testing::Return;
-using namespace google_breakpad::source_line_protocol;
-
-class TestNetworkSourceLineResolver : public ::testing::Test {
-public:
- TestNetworkSourceLineResolver() : resolver(NULL) {}
-
- void SetUp() {
- EXPECT_CALL(net, Init(false)).WillOnce(Return(true));
- resolver = new NetworkSourceLineResolver(&net, 0);
- }
-
- NetworkSourceLineResolver *resolver;
- MockNetwork net;
-};
-
-bool GeneratePositiveHasResponse(char *buffer, size_t buffer_size,
- ssize_t &received) {
- binarystream stream;
- stream << u_int16_t(0) << OK << MODULE_LOADED;
- string s = stream.str();
- received = s.length();
- memcpy(buffer, s.c_str(), s.length());
- return true;
-}
-
-bool GenerateNegativeHasResponse(char *buffer, size_t buffer_size,
- ssize_t &received) {
- binarystream stream;
- stream << u_int16_t(1) << OK << MODULE_NOT_LOADED;
- string s = stream.str();
- received = s.length();
- memcpy(buffer, s.c_str(), s.length());
- return true;
-}
-
-TEST_F(TestNetworkSourceLineResolver, TestHasMessages) {
- EXPECT_CALL(net, Send(_,_))
- .WillOnce(Return(true))
- .WillOnce(Return(true));
- EXPECT_CALL(net, WaitToReceive(0))
- .WillOnce(Return(true))
- .WillOnce(Return(true));
- EXPECT_CALL(net, Receive(_,_,_))
- .WillOnce(Invoke(GeneratePositiveHasResponse))
- .WillOnce(Invoke(GenerateNegativeHasResponse));
- ASSERT_NE(resolver, (NetworkSourceLineResolver*)NULL);
- BasicCodeModule module(0x0, 0x0, "test.dll", "test.pdb", "ABCD", "", "");
- EXPECT_TRUE(resolver->HasModule(&module));
- BasicCodeModule module2(0x0, 0x0, "test2.dll", "test2.pdb", "FFFF", "", "");
- EXPECT_FALSE(resolver->HasModule(&module2));
- // calling again should hit the cache, and not the network
- EXPECT_TRUE(resolver->HasModule(&module));
-}
-
-bool GenerateErrorResponse(char *buffer, size_t buffer_size,
- ssize_t &received) {
- binarystream stream;
- stream << u_int16_t(0) << ERROR;
- string s = stream.str();
- received = s.length();
- memcpy(buffer, s.c_str(), s.length());
- return true;
-}
-
-TEST_F(TestNetworkSourceLineResolver, TestHasErrorResponse) {
- EXPECT_CALL(net, Send(_,_))
- .WillOnce(Return(true));
- EXPECT_CALL(net, WaitToReceive(0))
- .WillOnce(Return(true));
- EXPECT_CALL(net, Receive(_,_,_))
- .WillOnce(Invoke(GenerateErrorResponse));
- ASSERT_NE(resolver, (NetworkSourceLineResolver*)NULL);
- BasicCodeModule module(0x0, 0x0, "test.dll", "test.pdb", "ABCD", "", "");
- // error packet should function as a not found
- EXPECT_FALSE(resolver->HasModule(&module));
-}
-
-// GenerateLoadResponse will generate (LOAD_NOT_FOUND, LOAD_INTERRUPT,
-// LOAD_FAIL, LOAD_OK) in order.
-class LoadHelper {
- public:
- LoadHelper() : response(LOAD_NOT_FOUND), sequence(0) {}
- bool GenerateLoadResponse(char *buffer, size_t buffer_size,
- ssize_t &received) {
- binarystream stream;
- stream << sequence << OK << response;
- string s = stream.str();
- received = s.length();
- memcpy(buffer, s.c_str(), s.length());
- ++sequence;
- ++response;
- return true;
- }
- u_int8_t response;
- u_int16_t sequence;
-};
-
-TEST_F(TestNetworkSourceLineResolver, TestLoadMessages) {
- EXPECT_CALL(net, Send(_,_))
- .Times(4)
- .WillRepeatedly(Return(true));
- EXPECT_CALL(net, WaitToReceive(0))
- .Times(4)
- .WillRepeatedly(Return(true));
- LoadHelper helper;
- EXPECT_CALL(net, Receive(_,_,_))
- .Times(4)
- .WillRepeatedly(Invoke(&helper, &LoadHelper::GenerateLoadResponse));
- ASSERT_NE(resolver, (NetworkSourceLineResolver*)NULL);
- BasicCodeModule module(0x0, 0x0, "test.dll", "test.pdb", "ABCD", "", "");
- string s;
- EXPECT_EQ(SymbolSupplier::NOT_FOUND,
- resolver->GetSymbolFile(&module, NULL, &s));
- BasicCodeModule module2(0x0, 0x0, "test2.dll", "test2.pdb", "FFFF", "", "");
- EXPECT_EQ(SymbolSupplier::INTERRUPT,
- resolver->GetSymbolFile(&module2, NULL, &s));
- BasicCodeModule module3(0x0, 0x0, "test3.dll", "test3.pdb", "0000", "", "");
- // a FAIL result from the network should come back as NOT_FOUND
- EXPECT_EQ(SymbolSupplier::NOT_FOUND,
- resolver->GetSymbolFile(&module3, NULL, &s));
- BasicCodeModule module4(0x0, 0x0, "test4.dll", "test4.pdb", "1010", "", "");
- EXPECT_EQ(SymbolSupplier::FOUND,
- resolver->GetSymbolFile(&module4, NULL, &s));
- // calling this should hit the cache, and not the network
- EXPECT_TRUE(resolver->HasModule(&module4));
-}
-
-TEST_F(TestNetworkSourceLineResolver, TestLoadErrorResponse) {
- EXPECT_CALL(net, Send(_,_))
- .WillOnce(Return(true));
- EXPECT_CALL(net, WaitToReceive(0))
- .WillOnce(Return(true));
- EXPECT_CALL(net, Receive(_,_,_))
- .WillOnce(Invoke(GenerateErrorResponse));
- ASSERT_NE(resolver, (NetworkSourceLineResolver*)NULL);
- BasicCodeModule module(0x0, 0x0, "test.dll", "test.pdb", "ABCD", "", "");
- string s;
- // error packet should function as NOT_FOUND response
- EXPECT_EQ(SymbolSupplier::NOT_FOUND,
- resolver->GetSymbolFile(&module, NULL, &s));
-}
-
-class GetHelper {
- public:
- GetHelper() : sequence(1) {}
- bool GenerateGetResponse(char *buffer, size_t buffer_size,
- ssize_t &received) {
- binarystream stream;
- stream << sequence << OK;
- switch(sequence) {
- case 1:
- // return full info
- stream << string("test()") << u_int64_t(0x1000) << string("test.c")
- << u_int32_t(1) << u_int64_t(0x1010);
- break;
- case 2:
- // return full info
- stream << string("test2()") << u_int64_t(0x2000) << string("test2.c")
- << u_int32_t(2) << u_int64_t(0x2020);
- break;
- case 3:
- // return just function name
- stream << string("test3()") << u_int64_t(0x4000) << string("")
- << u_int32_t(0) << u_int64_t(0);
- break;
- }
- string s = stream.str();
- received = s.length();
- memcpy(buffer, s.c_str(), s.length());
- ++sequence;
- return true;
- }
- u_int16_t sequence;
-};
-
-TEST_F(TestNetworkSourceLineResolver, TestGetMessages) {
- EXPECT_CALL(net, Send(_,_))
- .Times(4)
- .WillRepeatedly(Return(true));
- EXPECT_CALL(net, WaitToReceive(0))
- .Times(4)
- .WillRepeatedly(Return(true));
- GetHelper helper;
- EXPECT_CALL(net, Receive(_,_,_))
- .Times(4)
- .WillOnce(Invoke(GeneratePositiveHasResponse))
- .WillRepeatedly(Invoke(&helper, &GetHelper::GenerateGetResponse));
- BasicCodeModule module(0x0, 0x0, "test.dll", "test.pdb", "ABCD", "", "");
- // The resolver has to think the module is loaded before it will respond
- // to GET requests for that module.
- EXPECT_TRUE(resolver->HasModule(&module));
- StackFrame frame;
- frame.module = &module;
- frame.instruction = 0x1010;
- resolver->FillSourceLineInfo(&frame);
- EXPECT_EQ("test()", frame.function_name);
- EXPECT_EQ(0x1000, frame.function_base);
- EXPECT_EQ("test.c", frame.source_file_name);
- EXPECT_EQ(1, frame.source_line);
- EXPECT_EQ(0x1010, frame.source_line_base);
-
- StackFrame frame2;
- frame2.module = &module;
- frame2.instruction = 0x2020;
- resolver->FillSourceLineInfo(&frame2);
- EXPECT_EQ("test2()", frame2.function_name);
- EXPECT_EQ(0x2000, frame2.function_base);
- EXPECT_EQ("test2.c", frame2.source_file_name);
- EXPECT_EQ(2, frame2.source_line);
- EXPECT_EQ(0x2020, frame2.source_line_base);
-
- StackFrame frame3;
- frame3.module = &module;
- frame3.instruction = 0x4040;
- resolver->FillSourceLineInfo(&frame3);
- EXPECT_EQ("test3()", frame3.function_name);
- EXPECT_EQ(0x4000, frame3.function_base);
- EXPECT_EQ("", frame3.source_file_name);
- EXPECT_EQ(0, frame3.source_line);
- EXPECT_EQ(0, frame3.source_line_base);
-
- // this should come from the cache and not hit the network
- StackFrame frame4;
- frame4.module = &module;
- frame4.instruction = 0x1010;
- resolver->FillSourceLineInfo(&frame4);
- EXPECT_EQ("test()", frame4.function_name);
- EXPECT_EQ(0x1000, frame4.function_base);
- EXPECT_EQ("test.c", frame4.source_file_name);
- EXPECT_EQ(1, frame4.source_line);
- EXPECT_EQ(0x1010, frame4.source_line_base);
-
- // this should also be cached
- StackFrame frame5;
- frame5.module = &module;
- frame5.instruction = 0x4040;
- resolver->FillSourceLineInfo(&frame5);
- EXPECT_EQ("test3()", frame5.function_name);
- EXPECT_EQ(0x4000, frame5.function_base);
- EXPECT_EQ("", frame5.source_file_name);
- EXPECT_EQ(0, frame5.source_line);
- EXPECT_EQ(0, frame5.source_line_base);
-}
-
-class GetStackWinHelper {
- public:
- GetStackWinHelper() : sequence(1) {}
- bool GenerateGetStackWinResponse(char *buffer, size_t buffer_size,
- ssize_t &received) {
- binarystream stream;
- stream << sequence << OK;
- switch(sequence) {
- case 1:
- // return full info including program string
- stream << string("0 0 0 1 2 3 a ff f00 1 x y =");
- break;
- case 2:
- // return full info, no program string
- stream << string("0 0 0 1 2 3 a ff f00 0 1");
- break;
- case 3:
- // return empty string
- stream << string("");
- break;
- }
- string s = stream.str();
- received = s.length();
- memcpy(buffer, s.c_str(), s.length());
- ++sequence;
- return true;
- }
- u_int16_t sequence;
-};
-
-TEST_F(TestNetworkSourceLineResolver, TestGetStackWinMessages) {
- EXPECT_CALL(net, Send(_,_))
- .Times(4)
- .WillRepeatedly(Return(true));
- EXPECT_CALL(net, WaitToReceive(0))
- .Times(4)
- .WillRepeatedly(Return(true));
- GetStackWinHelper helper;
- EXPECT_CALL(net, Receive(_,_,_))
- .Times(4)
- .WillOnce(Invoke(GeneratePositiveHasResponse))
- .WillRepeatedly(Invoke(&helper,
- &GetStackWinHelper::GenerateGetStackWinResponse));
-
- BasicCodeModule module(0x0, 0x0, "test.dll", "test.pdb", "ABCD", "", "");
- // The resolver has to think the module is loaded before it will respond
- // to GETSTACKWIN requests for that module.
- EXPECT_TRUE(resolver->HasModule(&module));
- StackFrame frame;
- frame.module = &module;
- frame.instruction = 0x1010;
- WindowsFrameInfo *info = resolver->FindWindowsFrameInfo(&frame);
- ASSERT_NE((WindowsFrameInfo*)NULL, info);
- EXPECT_EQ(0x1, info->prolog_size);
- EXPECT_EQ(0x2, info->epilog_size);
- EXPECT_EQ(0x3, info->parameter_size);
- EXPECT_EQ(0xa, info->saved_register_size);
- EXPECT_EQ(0xff, info->local_size);
- EXPECT_EQ(0xf00, info->max_stack_size);
- EXPECT_EQ("x y =", info->program_string);
- delete info;
-
- StackFrame frame2;
- frame2.module = &module;
- frame2.instruction = 0x2020;
- info = resolver->FindWindowsFrameInfo(&frame2);
- ASSERT_NE((WindowsFrameInfo*)NULL, info);
- EXPECT_EQ(0x1, info->prolog_size);
- EXPECT_EQ(0x2, info->epilog_size);
- EXPECT_EQ(0x3, info->parameter_size);
- EXPECT_EQ(0xa, info->saved_register_size);
- EXPECT_EQ(0xff, info->local_size);
- EXPECT_EQ(0xf00, info->max_stack_size);
- EXPECT_EQ("", info->program_string);
- EXPECT_EQ(true, info->allocates_base_pointer);
- delete info;
-
- StackFrame frame3;
- frame3.module = &module;
- frame3.instruction = 0x4040;
- info = resolver->FindWindowsFrameInfo(&frame3);
- EXPECT_EQ((WindowsFrameInfo*)NULL, info);
-
- // this should come from the cache and not hit the network
- StackFrame frame4;
- frame4.module = &module;
- frame4.instruction = 0x1010;
- info = resolver->FindWindowsFrameInfo(&frame4);
- ASSERT_NE((WindowsFrameInfo*)NULL, info);
- EXPECT_EQ(0x1, info->prolog_size);
- EXPECT_EQ(0x2, info->epilog_size);
- EXPECT_EQ(0x3, info->parameter_size);
- EXPECT_EQ(0xa, info->saved_register_size);
- EXPECT_EQ(0xff, info->local_size);
- EXPECT_EQ(0xf00, info->max_stack_size);
- EXPECT_EQ("x y =", info->program_string);
- delete info;
-
- // this should also be cached
- StackFrame frame5;
- frame5.module = &module;
- frame5.instruction = 0x4040;
- info = resolver->FindWindowsFrameInfo(&frame5);
- EXPECT_EQ((WindowsFrameInfo*)NULL, info);
-}
-
-class GetStackCFIHelper {
- public:
- GetStackCFIHelper() : sequence(1) {}
- bool GenerateGetStackCFIResponse(char *buffer, size_t buffer_size,
- ssize_t &received) {
- binarystream stream;
- stream << sequence << OK;
- switch(sequence) {
- case 1:
- // return .cfa, .ra, registers
- stream << string(".cfa: 1234 .ra: .cfa 5 + r0: abc xyz r2: 10 10");
- break;
- case 2:
- // return just .cfa
- stream << string(".cfa: xyz");
- break;
- case 3:
- // return empty string
- stream << string("");
- break;
- }
- string s = stream.str();
- received = s.length();
- memcpy(buffer, s.c_str(), s.length());
- ++sequence;
- return true;
- }
- u_int16_t sequence;
-};
-
-TEST_F(TestNetworkSourceLineResolver, TestGetStackCFIMessages) {
- EXPECT_CALL(net, Send(_,_))
- .Times(4)
- .WillRepeatedly(Return(true));
- EXPECT_CALL(net, WaitToReceive(0))
- .Times(4)
- .WillRepeatedly(Return(true));
- GetStackCFIHelper helper;
- EXPECT_CALL(net, Receive(_,_,_))
- .Times(4)
- .WillOnce(Invoke(GeneratePositiveHasResponse))
- .WillRepeatedly(Invoke(&helper,
- &GetStackCFIHelper::GenerateGetStackCFIResponse));
-
- BasicCodeModule module(0x0, 0x0, "test.dll", "test.pdb", "ABCD", "", "");
- // The resolver has to think the module is loaded before it will respond
- // to GETSTACKCFI requests for that module.
- EXPECT_TRUE(resolver->HasModule(&module));
- StackFrame frame;
- frame.module = &module;
- frame.instruction = 0x1010;
- CFIFrameInfo *info = resolver->FindCFIFrameInfo(&frame);
- ASSERT_NE((CFIFrameInfo*)NULL, info);
- // Ostensibly we would check the internal data structure, but
- // we'd have to either mock out some other classes or get internal access,
- // so this is easier.
- EXPECT_EQ(".cfa: 1234 .ra: .cfa 5 + r0: abc xyz r2: 10 10",
- info->Serialize());
- delete info;
-
- StackFrame frame2;
- frame2.module = &module;
- frame2.instruction = 0x2020;
- info = resolver->FindCFIFrameInfo(&frame2);
- ASSERT_NE((CFIFrameInfo*)NULL, info);
- EXPECT_EQ(".cfa: xyz", info->Serialize());
- delete info;
-
- StackFrame frame3;
- frame3.module = &module;
- frame3.instruction = 0x4040;
- info = resolver->FindCFIFrameInfo(&frame3);
- EXPECT_EQ((CFIFrameInfo*)NULL, info);
-
- // this should come from the cache and not hit the network
- StackFrame frame4;
- frame4.module = &module;
- frame4.instruction = 0x1010;
- info = resolver->FindCFIFrameInfo(&frame4);
- ASSERT_NE((CFIFrameInfo*)NULL, info);
- EXPECT_EQ(".cfa: 1234 .ra: .cfa 5 + r0: abc xyz r2: 10 10",
- info->Serialize());
- delete info;
-
- // this should also be cached
- StackFrame frame5;
- frame5.module = &module;
- frame5.instruction = 0x4040;
- info = resolver->FindCFIFrameInfo(&frame5);
- EXPECT_EQ((CFIFrameInfo*)NULL, info);
-}
-
-TEST_F(TestNetworkSourceLineResolver, TestBogusData) {
- EXPECT_FALSE(resolver->HasModule(NULL));
-
- StackFrame frame;
- frame.module = NULL;
- frame.instruction = 0x1000;
- resolver->FillSourceLineInfo(&frame);
- EXPECT_EQ("", frame.function_name);
- EXPECT_EQ(0x0, frame.function_base);
- EXPECT_EQ("", frame.source_file_name);
- EXPECT_EQ(0, frame.source_line);
- EXPECT_EQ(0x0, frame.source_line_base);
-
- EXPECT_EQ((WindowsFrameInfo*)NULL, resolver->FindWindowsFrameInfo(&frame));
-}
-
-} // namespace
-
-int main(int argc, char *argv[]) {
- ::testing::InitGoogleTest(&argc, argv);
- return RUN_ALL_TESTS();
-}
diff --git a/src/processor/network_source_line_server.cc b/src/processor/network_source_line_server.cc
deleted file mode 100644
index 1a6ea31b..00000000
--- a/src/processor/network_source_line_server.cc
+++ /dev/null
@@ -1,435 +0,0 @@
-// Copyright (c) 2010, 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 <arpa/inet.h>
-#include <netinet/in.h>
-#include <string.h>
-#include <sys/socket.h>
-#include <sys/types.h>
-
-#include <algorithm>
-#include <iostream>
-#include <sstream>
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-#include "google_breakpad/processor/code_module.h"
-#include "google_breakpad/processor/stack_frame.h"
-#include "processor/basic_code_module.h"
-#include "processor/binarystream.h"
-#include "processor/cfi_frame_info.h"
-#include "processor/logging.h"
-#include "processor/network_source_line_protocol.h"
-#include "processor/network_source_line_server.h"
-#include "processor/tokenize.h"
-#include "processor/windows_frame_info.h"
-
-namespace google_breakpad {
-
-using std::dec;
-using std::find;
-using std::hex;
-// Style guide forbids "using namespace", so at least shorten it.
-namespace P = source_line_protocol;
-
-bool NetworkSourceLineServer::Initialize() {
- if (net_->Init(true))
- initialized_ = true;
- return initialized_;
-}
-
-bool NetworkSourceLineServer::RunForever() {
- if (!initialized_ && !Initialize())
- return false;
-
- BPLOG(INFO) << "Running forever...";
- while (true) {
- RunOnce(5000);
- }
- // not reached
- return true;
-}
-
-bool NetworkSourceLineServer::RunOnce(int wait_milliseconds) {
- if (!initialized_ && !Initialize())
- return false;
-
- if (!net_->WaitToReceive(wait_milliseconds))
- return false;
- //TODO(ted): loop, processing packets until wait_milliseconds
- // is actually exhausted?
-
- vector<char> buffer(1024);
- ssize_t received_bytes;
- if (!net_->Receive(&buffer[0], buffer.size(), received_bytes))
- return false;
- buffer.resize(received_bytes);
-
- binarystream request(&buffer[0], buffer.size());
- binarystream response;
- if (!HandleRequest(request, response))
- return false;
-
- string response_string = response.str();
- if (!net_->Send(response_string.c_str(), response_string.length()))
- return false;
- return true;
-}
-
-bool NetworkSourceLineServer::HandleRequest(binarystream &request,
- binarystream &response) {
- u_int16_t sequence_number;
- u_int8_t command;
- request >> sequence_number >> command;
- if (request.eof()) {
- BPLOG(ERROR) << "Malformed request, missing sequence number or command";
- return false;
- }
-
- response.rewind();
- response << sequence_number;
- switch(command) {
- case P::HAS:
- HandleHas(request, response);
- break;
- case P::LOAD:
- HandleLoad(request, response);
- break;
- case P::GET:
- HandleGet(request, response);
- break;
- case P::GETSTACKWIN:
- HandleGetStackWin(request, response);
- break;
- case P::GETSTACKCFI:
- HandleGetStackCFI(request, response);
- break;
- default:
- BPLOG(ERROR) << "Unknown command " << int(command);
- response << P::ERROR;
- break;
- }
- return true;
-}
-
-void NetworkSourceLineServer::HandleHas(binarystream &message,
- binarystream &response) {
- string module_name, debug_file, debug_id;
- message >> module_name >> debug_file >> debug_id;
- if (message.eof()) {
- BPLOG(ERROR) << "HAS message malformed";
- response << P::ERROR;
- return;
- }
- BPLOG(INFO) << "Received message HAS " << module_name
- << " " << debug_file
- << " " << debug_id;
- // Need to lie about the module name here, since BasicSourceLineResolver
- // uses only the module name for unique modules, but we want to allow
- // multiple versions of the same named module in here.
- BasicCodeModule module((u_int64_t)0, (u_int64_t)0,
- module_name + "|" + debug_file + "|" + debug_id, "",
- debug_file, debug_id, "");
- u_int8_t data;
- if (resolver_) {
- data = resolver_->HasModule(&module)
- ? P::MODULE_LOADED : P::MODULE_NOT_LOADED;
- } else {
- data = P::MODULE_NOT_LOADED;
- }
- response << P::OK << data;
-}
-
-void NetworkSourceLineServer::HandleLoad(binarystream &message,
- binarystream &response) {
- string module_name, debug_file, debug_id;
- message >> module_name >> debug_file >> debug_id;
- if (message.eof()) {
- BPLOG(ERROR) << "LOAD message malformed";
- response << P::ERROR;
- return;
- }
- BPLOG(INFO) << "Received message LOAD " << module_name
- << " " << debug_file
- << " " << debug_id;
-
- u_int8_t reply;
- // stub out the bare minimum here
- BasicCodeModule module((u_int64_t)0, (u_int64_t)0,
- module_name + "|" + debug_file + "|" + debug_id, "",
- debug_file, debug_id, "");
- if (resolver_->HasModule(&module)) {
- // just short-circuit the rest of this, since it's already loaded
- BPLOG(INFO) << "Got LOAD for already loaded " << module_name;
- UsedModule(module);
- reply = P::LOAD_OK;
- } else {
- BPLOG(INFO) << "Looking up symbols for (" << module_name << ", "
- << debug_file << ", " << debug_id << ")";
- string symbol_data, symbol_file;
- SymbolSupplier::SymbolResult symbol_result;
- if (supplier_) {
- symbol_result = supplier_->GetSymbolFile(&module, NULL,
- &symbol_file, &symbol_data);
- } else {
- symbol_result = SymbolSupplier::NOT_FOUND;
- }
-
- switch (symbol_result) {
- case SymbolSupplier::FOUND: {
- BPLOG(INFO) << "Found symbols for " << module_name;
- reply = P::LOAD_OK;
- // also go ahead and load the symbols while we're here,
- // since the client is just going to ask us to do this right away
- // and we already have |symbol_data| here.
- int numlines = CountNewlines(symbol_data);
- if (!resolver_->LoadModuleUsingMapBuffer(&module,
- symbol_data)) {
- BPLOG(INFO) << "Failed to load symbols for " << module_name;
- reply = P::LOAD_FAIL;
- } else {
- // save some info about this module
- symbol_lines_ += numlines;
- UsedModule(module);
- module_symbol_lines_[module.code_file()] = numlines;
-
- BPLOG(INFO) << "Loaded symbols for " << module_name
- << " (" << dec << numlines << " lines, "
- << symbol_lines_ << " total)";
-
- if (max_symbol_lines_ != 0 && symbol_lines_ > max_symbol_lines_) {
- // try unloading some modules to reclaim memory
- // (but not the one that was just loaded)
- BPLOG(INFO) << "Exceeded limit of " << dec << max_symbol_lines_
- << " symbol lines loaded, trying to unload modules";
- TryUnloadModules(module);
- }
- }
- }
- break;
- case SymbolSupplier::NOT_FOUND:
- BPLOG(INFO) << "Symbols not found for " << module_name;
- reply = P::LOAD_NOT_FOUND;
- break;
- case SymbolSupplier::INTERRUPT:
- BPLOG(INFO) << "Symbol provider returned interrupt for " << module_name;
- reply = P::LOAD_INTERRUPT;
- break;
- }
- }
- response << P::OK << reply;
-}
-
-void NetworkSourceLineServer::HandleGet(binarystream &message,
- binarystream &response) {
- string module_name, debug_file, debug_id;
- u_int64_t module_base, instruction;
- message >> module_name >> debug_file >> debug_id
- >> module_base >> instruction;
- if (message.eof()) {
- BPLOG(ERROR) << "GET message malformed";
- response << P::ERROR;
- return;
- }
-
- BPLOG(INFO) << "Received message GET " << module_name << " "
- << debug_file << " " << debug_id << " "
- << hex << module_base << " " << instruction;
-
- StackFrame frame;
- if (resolver_) {
- BasicCodeModule module(module_base, (u_int64_t)0,
- module_name + "|" + debug_file + "|" + debug_id, "",
- debug_file, debug_id, "");
- frame.module = &module;
- frame.instruction = instruction;
- resolver_->FillSourceLineInfo(&frame);
- UsedModule(module);
- }
-
- response << P::OK << frame.function_name << frame.function_base
- << frame.source_file_name << u_int32_t(frame.source_line)
- << frame.source_line_base;
- BPLOG(INFO) << "Sending GET response: " << frame.function_name << " "
- << hex << frame.function_base << " "
- << frame.source_file_name << " "
- << dec << frame.source_line << " "
- << hex << frame.source_line_base;
-}
-
-void NetworkSourceLineServer::HandleGetStackWin(binarystream &message,
- binarystream &response) {
- string module_name, debug_file, debug_id;
- u_int64_t module_base, instruction;
- message >> module_name >> debug_file >> debug_id
- >> module_base >> instruction;
- if (message.eof()) {
- BPLOG(ERROR) << "GETSTACKWIN message malformed";
- response << P::ERROR;
- return;
- }
-
- BPLOG(INFO) << "Received message GETSTACKWIN " << module_name << " "
- << debug_file << " " << debug_id << " "
- << hex << module_base << " " << instruction;
-
-
- WindowsFrameInfo *frame_info = NULL;
- if (resolver_) {
- StackFrame frame;
- BasicCodeModule module(module_base, (u_int64_t)0,
- module_name + "|" + debug_file + "|" + debug_id, "",
- debug_file, debug_id, "");
- frame.module = &module;
- frame.instruction = instruction;
- frame_info = resolver_->FindWindowsFrameInfo(&frame);
- UsedModule(module);
- }
-
- response << P::OK << FormatWindowsFrameInfo(frame_info);
- BPLOG(INFO) << "Sending GETSTACKWIN response: "
- << FormatWindowsFrameInfo(frame_info);
- delete frame_info;
-}
-
-string NetworkSourceLineServer::FormatWindowsFrameInfo(
- WindowsFrameInfo *frame_info) {
- if (frame_info == NULL)
- return "";
-
- std::ostringstream stream;
- // Put "0" as the type, rva and code size because the client doesn't
- // actually care what these values are, but it's easier to keep the
- // format consistent with the symbol files so the parsing code can be
- // shared.
- stream << "0 0 0 " << hex
- << frame_info->prolog_size << " "
- << frame_info->epilog_size << " "
- << frame_info->parameter_size << " "
- << frame_info->saved_register_size << " "
- << frame_info->local_size << " "
- << frame_info->max_stack_size << " ";
- if (!frame_info->program_string.empty()) {
- stream << 1 << " " << frame_info->program_string;
- } else {
- stream << 0 << " " << frame_info->allocates_base_pointer;
- }
- return stream.str();
-}
-
-void NetworkSourceLineServer::HandleGetStackCFI(binarystream &message,
- binarystream &response) {
- string module_name, debug_file, debug_id;
- u_int64_t module_base, instruction;
- message >> module_name >> debug_file >> debug_id
- >> module_base >> instruction;
- if (message.eof()) {
- BPLOG(ERROR) << "GETSTACKCFI message malformed";
- response << P::ERROR;
- return;
- }
-
- BPLOG(INFO) << "Received message GETSTACKCFI " << module_name << " "
- << debug_file << " " << debug_id << " "
- << hex << module_base << " " << instruction;
-
-
- CFIFrameInfo *frame_info = NULL;
- if (resolver_) {
- StackFrame frame;
- BasicCodeModule module(module_base, (u_int64_t)0,
- module_name + "|" + debug_file + "|" + debug_id, "",
- debug_file, debug_id, "");
- frame.module = &module;
- frame.instruction = instruction;
- frame_info = resolver_->FindCFIFrameInfo(&frame);
- UsedModule(module);
- }
-
- string frame_info_string;
- if (frame_info != NULL)
- frame_info_string = frame_info->Serialize();
- response << P::OK << frame_info_string;
- BPLOG(INFO) << "Sending GETSTACKCFI response: "
- << frame_info_string;
- delete frame_info;
-}
-
-int NetworkSourceLineServer::CountNewlines(const string &str) {
- int count = 0;
- string::const_iterator iter = str.begin();
- while (iter != str.end()) {
- if (*iter == '\n')
- count++;
- iter++;
- }
- return count;
-}
-
-void NetworkSourceLineServer::UsedModule(const CodeModule &module) {
- list<string>::iterator iter = find(modules_used_.begin(),
- modules_used_.end(),
- module.code_file());
- if (iter == modules_used_.end()) {
- modules_used_.push_front(module.code_file());
- } else {
- modules_used_.splice(modules_used_.begin(),
- modules_used_,
- iter);
- }
-}
-
-void NetworkSourceLineServer::TryUnloadModules(
- const CodeModule &just_loaded_module) {
- if (!resolver_)
- return;
-
- while (symbol_lines_ > max_symbol_lines_) {
- // never unload just_loaded_module
- if (modules_used_.back() == just_loaded_module.code_file())
- break;
-
- string module_to_unload = modules_used_.back();
- modules_used_.pop_back();
- BasicCodeModule module(0, 0, module_to_unload, "", "", "", "");
- BPLOG(INFO) << "Unloading module " << module_to_unload;
- resolver_->UnloadModule(&module);
-
- // reduce the symbol line count
- map<string, int>::iterator iter =
- module_symbol_lines_.find(module_to_unload);
- if (iter != module_symbol_lines_.end()) {
- symbol_lines_ -= iter->second;
- module_symbol_lines_.erase(iter);
- }
- }
-}
-
-} // namespace google_breakpad
diff --git a/src/processor/network_source_line_server.h b/src/processor/network_source_line_server.h
deleted file mode 100644
index 6ea4bba8..00000000
--- a/src/processor/network_source_line_server.h
+++ /dev/null
@@ -1,136 +0,0 @@
-// Copyright (c) 2010, 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.
-
-// NetworkSourceLineServer implements a UDP-based network protocol
-// to allow clients to query for source line information.
-//
-// A brief protocol description can be found in network_source_line_protocol.h
-
-#ifndef GOOGLE_BREAKPAD_PROCESSOR_NETWORK_SOURCE_LINE_SERVER_H_
-#define GOOGLE_BREAKPAD_PROCESSOR_NETWORK_SOURCE_LINE_SERVER_H_
-
-#include <list>
-#include <string>
-#include <vector>
-
-#include "google_breakpad/common/breakpad_types.h"
-#include "google_breakpad/processor/basic_source_line_resolver.h"
-#include "google_breakpad/processor/symbol_supplier.h"
-#include "processor/binarystream.h"
-#include "processor/network_interface.h"
-#include "processor/udp_network.h"
-
-namespace google_breakpad {
-
-using std::list;
-using std::string;
-using std::vector;
-
-class NetworkSourceLineServer {
- public:
- explicit NetworkSourceLineServer(SymbolSupplier *supplier,
- SourceLineResolverInterface *resolver,
- unsigned short listen_port,
- bool ip4only,
- const string &listen_address,
- u_int64_t max_symbol_lines)
- : initialized_(false),
- net_(new UDPNetwork(listen_address, listen_port, ip4only)),
- resolver_(resolver),
- supplier_(supplier),
- max_symbol_lines_(max_symbol_lines),
- symbol_lines_(0) {};
-
- NetworkSourceLineServer(SymbolSupplier *supplier,
- SourceLineResolverInterface *resolver,
- NetworkInterface *net,
- u_int64_t max_symbol_lines = 0)
- : initialized_(false),
- net_(net),
- resolver_(resolver),
- supplier_(supplier),
- max_symbol_lines_(max_symbol_lines),
- symbol_lines_(0) {};
-
- // Initialize network connection. Will be called automatically by
- // RunOnce or RunForever if not already initialized.
- // Returns false if network setup fails.
- bool Initialize();
-
- // Run forever serving connections.
- // Returns false only if network setup fails.
- bool RunForever();
-
- // Look for incoming connections and serve them.
- // Wait at most |wait_milliseconds| before returning. Return true
- // if any connections were served, and false otherwise.
- bool RunOnce(int wait_milliseconds);
-
- private:
- bool initialized_;
- NetworkInterface *net_;
- SourceLineResolverInterface *resolver_;
- SymbolSupplier *supplier_;
- // Maximum number of symbol lines to store in memory.
- // The number of lines in a symbol file is used as a rough
- // proxy for memory usage when parsed and loaded. When
- // this limit is surpassed, modules will be unloaded until
- // the sum of currently loaded modules is again lower
- // than this limit.
- const u_int64_t max_symbol_lines_;
- // Current number of symbol lines loaded
- u_int64_t symbol_lines_;
- // List of modules loaded, in most-to-least recently used order
- list<string> modules_used_;
- // Number of symbol lines loaded, per module.
- map<string, int> module_symbol_lines_;
-
- void HandleHas(binarystream &message, binarystream &response);
- void HandleLoad(binarystream &message, binarystream &response);
- void HandleGet(binarystream &message, binarystream &response);
- void HandleGetStackWin(binarystream &message, binarystream &response);
- void HandleGetStackCFI(binarystream &message, binarystream &response);
- string FormatWindowsFrameInfo(WindowsFrameInfo *frame_info);
-
- int CountNewlines(const string &str);
-
- // Move this module to the front of the used list.
- void UsedModule(const CodeModule &module);
- // Try to unload some modules to reclaim memory.
- // Do not unload the module passed in, as this was just loaded.
- void TryUnloadModules(const CodeModule &just_loaded_module);
-
- protected:
- // protected so we can easily unit test it
- bool HandleRequest(binarystream &request, binarystream &response);
-};
-
-} // namespace google_breakpad
-
-#endif // GOOGLE_BREAKPAD_PROCESSOR_NETWORK_SOURCE_LINE_SERVER_H_
diff --git a/src/processor/network_source_line_server_unittest.cc b/src/processor/network_source_line_server_unittest.cc
deleted file mode 100644
index c45f19cc..00000000
--- a/src/processor/network_source_line_server_unittest.cc
+++ /dev/null
@@ -1,963 +0,0 @@
-// Copyright (c) 2010, 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.
-
-// Unit tests for NetworkSourceLineServer.
-
-#include <ios>
-#include <set>
-#include <string>
-
-#include "breakpad_googletest_includes.h"
-#include "google_breakpad/processor/code_module.h"
-#include "google_breakpad/processor/source_line_resolver_interface.h"
-#include "google_breakpad/processor/stack_frame.h"
-#include "google_breakpad/processor/symbol_supplier.h"
-#include "processor/binarystream.h"
-#include "processor/cfi_frame_info.h"
-#include "processor/network_source_line_server.h"
-#include "processor/network_source_line_protocol.h"
-#include "processor/windows_frame_info.h"
-
-namespace {
-using std::ios_base;
-using std::set;
-using std::string;
-using google_breakpad::CFIFrameInfo;
-using google_breakpad::CodeModule;
-using google_breakpad::binarystream;
-using google_breakpad::NetworkInterface;
-using google_breakpad::NetworkSourceLineServer;
-using google_breakpad::SourceLineResolverInterface;
-using google_breakpad::StackFrame;
-using google_breakpad::SymbolSupplier;
-using google_breakpad::SystemInfo;
-using google_breakpad::WindowsFrameInfo;
-using ::testing::_;
-using ::testing::DoAll;
-using ::testing::Invoke;
-using ::testing::Property;
-using ::testing::Return;
-using ::testing::SetArgumentPointee;
-// Style guide forbids "using namespace", so at least shorten it.
-namespace P = google_breakpad::source_line_protocol;
-
-class MockNetwork : public NetworkInterface {
- public:
- MockNetwork() {}
-
- MOCK_METHOD1(Init, bool(bool listen));
- MOCK_METHOD2(Send, bool(const char *data, size_t length));
- MOCK_METHOD1(WaitToReceive, bool(int timeout));
- MOCK_METHOD3(Receive, bool(char *buffer, size_t buffer_size,
- ssize_t &received));
-};
-
-class MockSymbolSupplier : public SymbolSupplier {
-public:
- MockSymbolSupplier() {}
-
- MOCK_METHOD3(GetSymbolFile, SymbolResult(const CodeModule *module,
- const SystemInfo *system_info,
- string *symbol_file));
- MOCK_METHOD4(GetSymbolFile, SymbolResult(const CodeModule *module,
- const SystemInfo *system_info,
- string *symbol_file,
- string *symbol_data));
- MOCK_METHOD4(GetCStringSymbolData, SymbolResult(const CodeModule *module,
- const SystemInfo *system_info,
- string *symbol_file,
- char **symbol_data));
- MOCK_METHOD1(FreeSymbolData, void(const CodeModule *module));
-};
-
-class MockSourceLineResolver : public SourceLineResolverInterface {
- public:
- MockSourceLineResolver() {}
- virtual ~MockSourceLineResolver() {}
-
- MOCK_METHOD2(LoadModule, bool(const CodeModule *module,
- const string &map_file));
- MOCK_METHOD2(LoadModuleUsingMapBuffer, bool(const CodeModule *module,
- const string &map_buffer));
- MOCK_METHOD2(LoadModuleUsingMemoryBuffer, bool(const CodeModule *module,
- char *memory_buffer));
- MOCK_METHOD0(ShouldDeleteMemoryBufferAfterLoadModule, bool());
- MOCK_METHOD1(UnloadModule, void(const CodeModule *module));
- MOCK_METHOD1(HasModule, bool(const CodeModule *module));
- MOCK_METHOD1(FillSourceLineInfo, void(StackFrame *frame));
- MOCK_METHOD1(FindWindowsFrameInfo,
- WindowsFrameInfo*(const StackFrame *frame));
- MOCK_METHOD1(FindCFIFrameInfo,
- CFIFrameInfo*(const StackFrame *frame));
-};
-
-class TestNetworkSourceLineServer : public NetworkSourceLineServer {
- public:
- // Override visibility for testing. It's a lot easier to just
- // call into this method and verify the result than it would be
- // to mock out the calls to the NetworkInterface, even though
- // that would ostensibly be more correct and test the code more
- // thoroughly. Perhaps if someone has time and figures out a
- // clean way to do it this could be changed.
- using NetworkSourceLineServer::HandleRequest;
-
- TestNetworkSourceLineServer(SymbolSupplier *supplier,
- SourceLineResolverInterface *resolver,
- NetworkInterface *net,
- u_int64_t max_symbol_lines = 0)
- : NetworkSourceLineServer(supplier, resolver, net, max_symbol_lines)
-
- {}
-};
-
-class NetworkSourceLineServerTest : public ::testing::Test {
- public:
- MockSymbolSupplier supplier;
- MockSourceLineResolver resolver;
- MockNetwork net;
- TestNetworkSourceLineServer *server;
-
- NetworkSourceLineServerTest() : server(NULL) {}
-
- void SetUp() {
- server = new TestNetworkSourceLineServer(&supplier, &resolver, &net);
- }
-};
-
-TEST_F(NetworkSourceLineServerTest, TestInit) {
- EXPECT_CALL(net, Init(true)).WillOnce(Return(true));
- EXPECT_CALL(net, WaitToReceive(0)).WillOnce(Return(false));
- ASSERT_TRUE(server->Initialize());
- EXPECT_FALSE(server->RunOnce(0));
-}
-
-TEST_F(NetworkSourceLineServerTest, TestMalformedRequest) {
- binarystream request;
- // send a request without a full sequence number
- request << u_int8_t(1);
- binarystream response;
- EXPECT_FALSE(server->HandleRequest(request, response));
- request.rewind();
- // send a request without a command
- request << u_int16_t(1);
- EXPECT_FALSE(server->HandleRequest(request, response));
-}
-
-TEST_F(NetworkSourceLineServerTest, TestUnknownCommand) {
- binarystream request;
- // send a request with an unknown command
- request << u_int16_t(1) << u_int8_t(100);
- binarystream response;
- ASSERT_TRUE(server->HandleRequest(request, response));
- u_int16_t response_sequence;
- u_int8_t response_status;
- response >> response_sequence >> response_status;
- ASSERT_FALSE(response.eof());
- EXPECT_EQ(u_int16_t(1), response_sequence);
- EXPECT_EQ(P::ERROR, int(response_status));
-}
-
-TEST_F(NetworkSourceLineServerTest, TestHasBasic) {
- EXPECT_CALL(resolver, HasModule(_))
- .WillOnce(Return(false))
- .WillOnce(Return(true));
-
- binarystream request;
- const u_int16_t sequence = 0xA0A0;
- // first request should come back as not loaded
- request << sequence << P::HAS << string("test.dll") << string("test.pdb")
- << string("ABCD1234");
- binarystream response;
- ASSERT_TRUE(server->HandleRequest(request, response));
- u_int16_t response_sequence;
- u_int8_t response_status, response_data;
- response >> response_sequence >> response_status >> response_data;
- ASSERT_FALSE(response.eof());
- EXPECT_EQ(sequence, response_sequence);
- EXPECT_EQ(P::OK, int(response_status));
- EXPECT_EQ(P::MODULE_NOT_LOADED, int(response_data));
- // second request should come back as loaded
- binarystream request2;
- request2 << sequence << P::HAS << string("loaded.dll") << string("loaded.pdb")
- << string("ABCD1234");
- ASSERT_TRUE(server->HandleRequest(request2, response));
- response >> response_sequence >> response_status >> response_data;
- ASSERT_FALSE(response.eof());
- EXPECT_EQ(sequence, response_sequence);
- EXPECT_EQ(P::OK, int(response_status));
- EXPECT_EQ(P::MODULE_LOADED, int(response_data));
-}
-
-TEST_F(NetworkSourceLineServerTest, TestMalformedHasRequest) {
- binarystream request;
- // send request with just command, missing all data
- const u_int16_t sequence = 0xA0A0;
- request << sequence << P::HAS;
- binarystream response;
- ASSERT_TRUE(server->HandleRequest(request, response));
- u_int16_t response_sequence;
- u_int8_t response_status;
- response >> response_sequence >> response_status;
- ASSERT_FALSE(response.eof());
- EXPECT_EQ(sequence, response_sequence);
- EXPECT_EQ(P::ERROR, int(response_status));
- // send request with just module name
- binarystream request2;
- request2 << sequence << P::HAS << string("test.dll");
- ASSERT_TRUE(server->HandleRequest(request2, response));
- response >> response_sequence >> response_status;
- ASSERT_FALSE(response.eof());
- EXPECT_EQ(sequence, response_sequence);
- EXPECT_EQ(P::ERROR, int(response_status));
- // send request with module name, debug file, missing debug id
- binarystream request3;
- request3 << sequence << P::HAS << string("test.dll") << string("test.pdb");
- ASSERT_TRUE(server->HandleRequest(request3, response));
- response >> response_sequence >> response_status;
- ASSERT_FALSE(response.eof());
- EXPECT_EQ(sequence, response_sequence);
- EXPECT_EQ(P::ERROR, int(response_status));
-}
-
-TEST_F(NetworkSourceLineServerTest, TestHasLoad) {
- EXPECT_CALL(resolver, HasModule(_))
- .WillOnce(Return(false))
- .WillOnce(Return(false))
- .WillOnce(Return(true));
- EXPECT_CALL(resolver, LoadModuleUsingMapBuffer(_,_))
- .WillOnce(Return(true));
- EXPECT_CALL(supplier, GetSymbolFile(_,_,_,_))
- .WillOnce(Return(SymbolSupplier::FOUND));
-
- // verify that the module is not loaded, with a HAS request
- binarystream request;
- const u_int16_t sequence = 0xA0A0;
- request << sequence << P::HAS << string("found.dll") << string("found.pdb")
- << string("ABCD1234");
- binarystream response;
- ASSERT_TRUE(server->HandleRequest(request, response));
- u_int16_t response_sequence;
- u_int8_t response_status, response_data;
- response >> response_sequence >> response_status >> response_data;
- ASSERT_FALSE(response.eof());
- EXPECT_EQ(sequence, response_sequence);
- EXPECT_EQ(P::OK, int(response_status));
- ASSERT_EQ(P::MODULE_NOT_LOADED, int(response_data));
- // now send a load request for this module
- binarystream request2;
- const u_int16_t sequence2 = 0xB0B0;
- request2 << sequence2 << P::LOAD << string("found.dll") << string("found.pdb")
- << string("ABCD1234");
- ASSERT_TRUE(server->HandleRequest(request2, response));
- response >> response_sequence >> response_status >> response_data;
- ASSERT_FALSE(response.eof());
- EXPECT_EQ(sequence2, response_sequence);
- EXPECT_EQ(P::OK, int(response_status));
- ASSERT_EQ(int(P::LOAD_OK), int(response_data));
- // sending another HAS message should now show it as loaded
- binarystream request3;
- const u_int16_t sequence3 = 0xC0C0;
- request3 << sequence3 << P::HAS << string("found.dll") << string("found.pdb")
- << string("ABCD1234");
- ASSERT_TRUE(server->HandleRequest(request3, response));
- response >> response_sequence >> response_status >> response_data;
- ASSERT_FALSE(response.eof());
- EXPECT_EQ(sequence3, response_sequence);
- EXPECT_EQ(P::OK, int(response_status));
- EXPECT_EQ(P::MODULE_LOADED, int(response_data));
-}
-
-TEST_F(NetworkSourceLineServerTest, TestLoad) {
- EXPECT_CALL(resolver, HasModule(_))
- .Times(3)
- .WillRepeatedly(Return(false));
- EXPECT_CALL(resolver, LoadModuleUsingMapBuffer(_,_))
- .WillOnce(Return(false));
- EXPECT_CALL(supplier, GetSymbolFile(_,_,_,_))
- .WillOnce(Return(SymbolSupplier::NOT_FOUND))
- .WillOnce(Return(SymbolSupplier::INTERRUPT))
- .WillOnce(Return(SymbolSupplier::FOUND));
-
- // notfound.dll should return LOAD_NOT_FOUND
- binarystream request;
- const u_int16_t sequence = 0xA0A0;
- request << sequence << P::LOAD << string("notfound.dll")
- << string("notfound.pdb") << string("ABCD1234");
- binarystream response;
- ASSERT_TRUE(server->HandleRequest(request, response));
- u_int16_t response_sequence;
- u_int8_t response_status, response_data;
- response >> response_sequence >> response_status >> response_data;
- ASSERT_FALSE(response.eof());
- EXPECT_EQ(sequence, response_sequence);
- EXPECT_EQ(P::OK, int(response_status));
- EXPECT_EQ(int(P::LOAD_NOT_FOUND), int(response_data));
- // interrupt.dll should return LOAD_INTERRUPT
- binarystream request2;
- const u_int16_t sequence2 = 0xB0B0;
- request2 << sequence2 << P::LOAD << string("interrupt.dll")
- << string("interrupt.pdb") << string("0000");
- ASSERT_TRUE(server->HandleRequest(request2, response));
- response >> response_sequence >> response_status >> response_data;
- ASSERT_FALSE(response.eof());
- EXPECT_EQ(sequence2, response_sequence);
- EXPECT_EQ(P::OK, int(response_status));
- EXPECT_EQ(int(P::LOAD_INTERRUPT), int(response_data));
- // fail.dll should return LOAD_FAIL
- binarystream request3;
- const u_int16_t sequence3 = 0xC0C0;
- request3 << sequence3 << P::LOAD << string("fail.dll") << string("fail.pdb")
- << string("FFFFFFFF");
- ASSERT_TRUE(server->HandleRequest(request3, response));
- response >> response_sequence >> response_status >> response_data;
- ASSERT_FALSE(response.eof());
- EXPECT_EQ(sequence3, response_sequence);
- EXPECT_EQ(P::OK, int(response_status));
- EXPECT_EQ(int(P::LOAD_FAIL), int(response_data));
-}
-
-TEST_F(NetworkSourceLineServerTest, TestMalformedLoadRequest) {
- binarystream request;
- // send request with just command, missing all data
- const u_int16_t sequence = 0xA0A0;
- request << sequence << P::LOAD;
- binarystream response;
- ASSERT_TRUE(server->HandleRequest(request, response));
- u_int16_t response_sequence;
- u_int8_t response_status;
- response >> response_sequence >> response_status;
- ASSERT_FALSE(response.eof());
- EXPECT_EQ(sequence, response_sequence);
- EXPECT_EQ(P::ERROR, int(response_status));
- // send request with just module name
- binarystream request2;
- request2 << sequence << P::LOAD << string("test.dll");
- ASSERT_TRUE(server->HandleRequest(request2, response));
- response >> response_sequence >> response_status;
- ASSERT_FALSE(response.eof());
- EXPECT_EQ(sequence, response_sequence);
- EXPECT_EQ(P::ERROR, int(response_status));
- // send request with module name, debug file, missing debug id
- binarystream request3;
- request3 << sequence << P::LOAD << string("test.dll") << string("test.pdb");
- ASSERT_TRUE(server->HandleRequest(request3, response));
- response >> response_sequence >> response_status;
- ASSERT_FALSE(response.eof());
- EXPECT_EQ(sequence, response_sequence);
- EXPECT_EQ(P::ERROR, int(response_status));
-}
-
-void FillFullSourceLineInfo(StackFrame *frame) {
- frame->function_name = "function1";
- frame->function_base = 0x1200;
- frame->source_file_name = "function1.cc";
- frame->source_line = 1;
- frame->source_line_base = 0x1230;
-}
-
-void FillPartialSourceLineInfo(StackFrame *frame) {
- frame->function_name = "function2";
- frame->function_base = 0xFFF0;
-}
-
-TEST_F(NetworkSourceLineServerTest, TestGet) {
- EXPECT_CALL(resolver, FillSourceLineInfo(_))
- .WillOnce(Invoke(FillFullSourceLineInfo))
- .WillOnce(Invoke(FillPartialSourceLineInfo));
-
- binarystream request;
- const u_int16_t sequence = 0xA0A0;
- request << sequence << P::GET << string("loaded.dll")
- << string("loaded.pdb") << string("ABCD1234")
- << u_int64_t(0x1000) << u_int64_t(0x1234);
- binarystream response;
- ASSERT_TRUE(server->HandleRequest(request, response));
- u_int16_t response_sequence;
- u_int8_t response_status;
- string function, source_file;
- u_int32_t source_line;
- u_int64_t function_base, source_line_base;
- response >> response_sequence >> response_status >> function
- >> function_base >> source_file >> source_line >> source_line_base;
- ASSERT_FALSE(response.eof());
- EXPECT_EQ(sequence, response_sequence);
- EXPECT_EQ(P::OK, int(response_status));
- EXPECT_EQ("function1", function);
- EXPECT_EQ(0x1200, function_base);
- EXPECT_EQ("function1.cc", source_file);
- EXPECT_EQ(1, source_line);
- EXPECT_EQ(0x1230, source_line_base);
-
- binarystream request2;
- const u_int16_t sequence2 = 0xC0C0;
- request2 << sequence2 << P::GET << string("loaded.dll")
- << string("loaded.pdb") << string("ABCD1234")
- << u_int64_t(0x1000) << u_int64_t(0xFFFF);
- ASSERT_TRUE(server->HandleRequest(request2, response));
- response >> response_sequence >> response_status >> function
- >> function_base >> source_file >> source_line >> source_line_base;
- ASSERT_FALSE(response.eof());
- EXPECT_EQ(sequence2, response_sequence);
- EXPECT_EQ(P::OK, int(response_status));
- EXPECT_EQ("function2", function);
- EXPECT_EQ(0xFFF0, function_base);
- EXPECT_EQ("", source_file);
- EXPECT_EQ(0, source_line);
- EXPECT_EQ(0, source_line_base);
-}
-
-WindowsFrameInfo* GetFullWindowsFrameInfo(const StackFrame *frame) {
- // return frame info with program string
- return new WindowsFrameInfo(1, 2, 3, 0xA, 0xFF, 0xF00,
- true,
- "x y =");
-}
-
-WindowsFrameInfo* GetPartialWindowsFrameInfo(const StackFrame *frame) {
- // return frame info, no program string
- return new WindowsFrameInfo(1, 2, 3, 4, 5, 6, true, "");
-}
-
-TEST_F(NetworkSourceLineServerTest, TestGetStackWin) {
- EXPECT_CALL(resolver, FindWindowsFrameInfo(_))
- .WillOnce(Invoke(GetFullWindowsFrameInfo))
- .WillOnce(Invoke(GetPartialWindowsFrameInfo))
- .WillOnce(Return((WindowsFrameInfo*)NULL));
-
- binarystream request;
- const u_int16_t sequence = 0xA0A0;
- request << sequence << P::GETSTACKWIN << string("loaded.dll")
- << string("loaded.pdb") << string("ABCD1234")
- << u_int64_t(0x1000) << u_int64_t(0x1234);
- binarystream response;
- ASSERT_TRUE(server->HandleRequest(request, response));
- u_int16_t response_sequence;
- u_int8_t response_status;
- string stack_info;
- response >> response_sequence >> response_status
- >> stack_info;
- ASSERT_FALSE(response.eof());
- EXPECT_EQ(sequence, response_sequence);
- EXPECT_EQ(P::OK, int(response_status));
- EXPECT_EQ("0 0 0 1 2 3 a ff f00 1 x y =", stack_info);
-
- binarystream request2;
- const u_int16_t sequence2 = 0xB0B0;
- request2 << sequence2 << P::GETSTACKWIN << string("loaded.dll")
- << string("loaded.pdb") << string("ABCD1234")
- << u_int64_t(0x1000) << u_int64_t(0xABCD);
- ASSERT_TRUE(server->HandleRequest(request2, response));
- response >> response_sequence >> response_status
- >> stack_info;
- ASSERT_FALSE(response.eof());
- EXPECT_EQ(sequence2, response_sequence);
- EXPECT_EQ(P::OK, int(response_status));
- EXPECT_EQ("0 0 0 1 2 3 4 5 6 0 1", stack_info);
-
- binarystream request3;
- const u_int16_t sequence3 = 0xC0C0;
- request3 << sequence3 << P::GETSTACKWIN << string("loaded.dll")
- << string("loaded.pdb") << string("ABCD1234")
- << u_int64_t(0x1000) << u_int64_t(0xFFFF);
- ASSERT_TRUE(server->HandleRequest(request3, response));
- response >> response_sequence >> response_status
- >> stack_info;
- ASSERT_FALSE(response.eof());
- EXPECT_EQ(sequence3, response_sequence);
- EXPECT_EQ(P::OK, int(response_status));
- EXPECT_EQ("", stack_info);
-}
-
-
-CFIFrameInfo* GetCFIFrameInfoJustCFA(const StackFrame *frame) {
- CFIFrameInfo* cfi = new CFIFrameInfo();
- cfi->SetCFARule("12345678");
- return cfi;
-}
-
-CFIFrameInfo* GetCFIFrameInfoCFARA(const StackFrame *frame) {
- CFIFrameInfo* cfi = new CFIFrameInfo();
- cfi->SetCFARule("12345678");
- cfi->SetRARule("abcdefgh");
- return cfi;
-}
-
-CFIFrameInfo* GetCFIFrameInfoLots(const StackFrame *frame) {
- CFIFrameInfo* cfi = new CFIFrameInfo();
- cfi->SetCFARule("12345678");
- cfi->SetRARule("abcdefgh");
- cfi->SetRegisterRule("r0", "foo bar");
- cfi->SetRegisterRule("b0", "123 abc +");
- return cfi;
-}
-
-TEST_F(NetworkSourceLineServerTest, TestGetStackCFI) {
- EXPECT_CALL(resolver, FindCFIFrameInfo(_))
- .WillOnce(Return((CFIFrameInfo*)NULL))
- .WillOnce(Invoke(GetCFIFrameInfoJustCFA))
- .WillOnce(Invoke(GetCFIFrameInfoCFARA))
- .WillOnce(Invoke(GetCFIFrameInfoLots));
-
- binarystream request;
- const u_int16_t sequence = 0xA0A0;
- request << sequence << P::GETSTACKCFI << string("loaded.dll")
- << string("loaded.pdb") << string("ABCD1234")
- << u_int64_t(0x1000) << u_int64_t(0x1234);
- binarystream response;
- ASSERT_TRUE(server->HandleRequest(request, response));
- u_int16_t response_sequence;
- u_int8_t response_status;
- string stack_info;
- response >> response_sequence >> response_status
- >> stack_info;
- ASSERT_FALSE(response.eof());
- EXPECT_EQ(sequence, response_sequence);
- EXPECT_EQ(P::OK, int(response_status));
- EXPECT_EQ("", stack_info);
-
- binarystream request2;
- const u_int16_t sequence2 = 0xB0B0;
- request2 << sequence2 << P::GETSTACKCFI << string("loaded.dll")
- << string("loaded.pdb") << string("ABCD1234")
- << u_int64_t(0x1000) << u_int64_t(0xABCD);
- ASSERT_TRUE(server->HandleRequest(request2, response));
- response >> response_sequence >> response_status
- >> stack_info;
- ASSERT_FALSE(response.eof());
- EXPECT_EQ(sequence2, response_sequence);
- EXPECT_EQ(P::OK, int(response_status));
- EXPECT_EQ(".cfa: 12345678", stack_info);
-
- binarystream request3;
- const u_int16_t sequence3 = 0xC0C0;
- request3 << sequence3 << P::GETSTACKCFI << string("loaded.dll")
- << string("loaded.pdb") << string("ABCD1234")
- << u_int64_t(0x1000) << u_int64_t(0xFFFF);
- ASSERT_TRUE(server->HandleRequest(request3, response));
- response >> response_sequence >> response_status
- >> stack_info;
- ASSERT_FALSE(response.eof());
- EXPECT_EQ(sequence3, response_sequence);
- EXPECT_EQ(P::OK, int(response_status));
- EXPECT_EQ(".cfa: 12345678 .ra: abcdefgh", stack_info);
-
- binarystream request4;
- const u_int16_t sequence4 = 0xD0D0;
- request4 << sequence4 << P::GETSTACKCFI << string("loaded.dll")
- << string("loaded.pdb") << string("ABCD1234")
- << u_int64_t(0x1000) << u_int64_t(0xFFFF);
- ASSERT_TRUE(server->HandleRequest(request4, response));
- response >> response_sequence >> response_status
- >> stack_info;
- ASSERT_FALSE(response.eof());
- EXPECT_EQ(sequence4, response_sequence);
- EXPECT_EQ(P::OK, int(response_status));
- EXPECT_EQ(".cfa: 12345678 .ra: abcdefgh b0: 123 abc + r0: foo bar",
- stack_info);
-}
-
-TEST_F(NetworkSourceLineServerTest, TestMalformedGetRequest) {
- //TODO
-}
-
-TEST(TestMissingMembers, TestServerWithoutSymbolSupplier) {
- // Should provide reasonable responses without a SymbolSupplier
- MockSourceLineResolver resolver;
- MockNetwork net;
- TestNetworkSourceLineServer server(NULL, &resolver, &net);
-
- // All LOAD requests should return LOAD_NOT_FOUND
- binarystream request;
- binarystream response;
- const u_int16_t sequence = 0xB0B0;
- u_int16_t response_sequence;
- u_int8_t response_status, response_data;
- request << sequence << P::LOAD << string("found.dll") << string("found.pdb")
- << string("ABCD1234");
- ASSERT_TRUE(server.HandleRequest(request, response));
- response >> response_sequence >> response_status >> response_data;
- ASSERT_FALSE(response.eof());
- EXPECT_EQ(sequence, response_sequence);
- EXPECT_EQ(P::OK, int(response_status));
- ASSERT_EQ(int(P::LOAD_NOT_FOUND), int(response_data));
-}
-
-TEST(TestMissingMembers, TestServerWithoutResolver) {
- // Should provide reasonable responses without a SourceLineResolver
- MockSymbolSupplier supplier;
- MockNetwork net;
- TestNetworkSourceLineServer server(&supplier, NULL, &net);
-
- // GET requests should return empty info
- binarystream request;
- binarystream response;
- const u_int16_t sequence = 0xA0A0;
- u_int16_t response_sequence;
- u_int8_t response_status;
- request << sequence << P::GET << string("loaded.dll")
- << string("loaded.pdb") << string("ABCD1234")
- << u_int64_t(0x1000) << u_int64_t(0x1234);
- ASSERT_TRUE(server.HandleRequest(request, response));
- string function, source_file;
- u_int32_t source_line;
- u_int64_t function_base, source_line_base;
- response >> response_sequence >> response_status >> function
- >> function_base >> source_file >> source_line >> source_line_base;
- ASSERT_FALSE(response.eof());
- EXPECT_EQ(sequence, response_sequence);
- EXPECT_EQ(P::OK, int(response_status));
- EXPECT_EQ("", function);
- EXPECT_EQ(0x0, function_base);
- EXPECT_EQ("", source_file);
- EXPECT_EQ(0, source_line);
- EXPECT_EQ(0x0, source_line_base);
-
- // GETSTACKWIN requests should return an empty string
- binarystream request2;
- const u_int16_t sequence2 = 0xB0B0;
- request << sequence2 << P::GETSTACKWIN << string("loaded.dll")
- << string("loaded.pdb") << string("ABCD1234")
- << u_int64_t(0x1000) << u_int64_t(0x1234);
- ASSERT_TRUE(server.HandleRequest(request, response));
- string response_string;
- response >> response_sequence >> response_status >> response_string;
- EXPECT_EQ(sequence2, response_sequence);
- EXPECT_EQ(P::OK, int(response_status));
- EXPECT_EQ("", response_string);
-}
-
-class TestModuleManagement : public ::testing::Test {
-public:
- MockSymbolSupplier supplier;
- MockSourceLineResolver resolver;
- MockNetwork net;
- TestNetworkSourceLineServer server;
-
- // Init server with symbol line limit of 25
- TestModuleManagement() : server(&supplier, &resolver, &net, 25) {}
-};
-
-TEST_F(TestModuleManagement, TestModuleUnloading) {
- EXPECT_CALL(supplier, GetSymbolFile(_,_,_,_))
- .Times(3)
- .WillRepeatedly(DoAll(SetArgumentPointee<3>(string("1\n2\n3\n4\n5\n6\n7\n8\n9\n10\n")),
- Return(SymbolSupplier::FOUND)));
- EXPECT_CALL(resolver, HasModule(_))
- .Times(3)
- .WillRepeatedly(Return(false));
- EXPECT_CALL(resolver, LoadModuleUsingMapBuffer(_,_))
- .Times(3)
- .WillRepeatedly(Return(true));
- EXPECT_CALL(resolver, UnloadModule(Property(&CodeModule::code_file,
- string("one.dll|one.pdb|1111"))))
- .Times(1);
-
- // load three modules, each with 10 lines of symbols.
- // the third module will overflow the server's symbol line limit,
- // and should cause the first module to be unloaded.
- binarystream request;
- const u_int16_t sequence = 0x1010;
- request << sequence << P::LOAD << string("one.dll") << string("one.pdb")
- << string("1111");
- binarystream response;
- ASSERT_TRUE(server.HandleRequest(request, response));
- u_int16_t response_sequence;
- u_int8_t response_status, response_data;
- response >> response_sequence >> response_status >> response_data;
- ASSERT_FALSE(response.eof());
- EXPECT_EQ(sequence, response_sequence);
- EXPECT_EQ(P::OK, int(response_status));
- ASSERT_EQ(int(P::LOAD_OK), int(response_data));
-
- binarystream request2;
- const u_int16_t sequence2 = 0x2020;
- request2 << sequence2 << P::LOAD << string("two.dll") << string("two.pdb")
- << string("2222");
- ASSERT_TRUE(server.HandleRequest(request2, response));
- response >> response_sequence >> response_status >> response_data;
- ASSERT_FALSE(response.eof());
- EXPECT_EQ(sequence2, response_sequence);
- EXPECT_EQ(P::OK, int(response_status));
- ASSERT_EQ(int(P::LOAD_OK), int(response_data));
-
- binarystream request3;
- const u_int16_t sequence3 = 0x3030;
- request3 << sequence3 << P::LOAD << string("three.dll") << string("three.pdb")
- << string("3333");
- ASSERT_TRUE(server.HandleRequest(request3, response));
- response >> response_sequence >> response_status >> response_data;
- ASSERT_FALSE(response.eof());
- EXPECT_EQ(sequence3, response_sequence);
- EXPECT_EQ(P::OK, int(response_status));
- ASSERT_EQ(int(P::LOAD_OK), int(response_data));
-}
-
-TEST_F(TestModuleManagement, TestSymbolLimitTooLow) {
- // load module with symbol count > limit,
- // ensure that it doesn't get unloaded even though it's the only module
- EXPECT_CALL(supplier, GetSymbolFile(_,_,_,_))
- .WillOnce(DoAll(SetArgumentPointee<3>(string("1\n2\n3\n4\n5\n6\n7\n8\n9\n10\n11\n12\n13\n14\n15\n16\n17\n18\n19\n20\n21\n22\n23\n24\n25\n26\n")),
- Return(SymbolSupplier::FOUND)));
- EXPECT_CALL(resolver, HasModule(_))
- .WillOnce(Return(false));
- EXPECT_CALL(resolver, LoadModuleUsingMapBuffer(_,_))
- .WillOnce(Return(true));
- EXPECT_CALL(resolver, UnloadModule(_))
- .Times(0);
-
- binarystream request;
- const u_int16_t sequence = 0x1010;
- request << sequence << P::LOAD << string("one.dll") << string("one.pdb")
- << string("1111");
- binarystream response;
- ASSERT_TRUE(server.HandleRequest(request, response));
- u_int16_t response_sequence;
- u_int8_t response_status, response_data;
- response >> response_sequence >> response_status >> response_data;
- ASSERT_FALSE(response.eof());
- EXPECT_EQ(sequence, response_sequence);
- EXPECT_EQ(P::OK, int(response_status));
- ASSERT_EQ(int(P::LOAD_OK), int(response_data));
-}
-
-TEST_F(TestModuleManagement, TestModuleLoadLRU) {
- // load 2 modules, then re-load the first one,
- // then load a third one, causing the second one to be unloaded
- EXPECT_CALL(supplier, GetSymbolFile(_,_,_,_))
- .Times(3)
- .WillRepeatedly(DoAll(SetArgumentPointee<3>(string("1\n2\n3\n4\n5\n6\n7\n8\n9\n10\n")),
- Return(SymbolSupplier::FOUND)));
- EXPECT_CALL(resolver, HasModule(_))
- .WillOnce(Return(false)) // load module 1
- .WillOnce(Return(false)) // load module 2
- .WillOnce(Return(true)) // module 1 already loaded
- .WillOnce(Return(false)); // load module 3
- EXPECT_CALL(resolver, LoadModuleUsingMapBuffer(_,_))
- .Times(3)
- .WillRepeatedly(Return(true));
- EXPECT_CALL(resolver, UnloadModule(Property(&CodeModule::code_file,
- string("two.dll|two.pdb|2222"))))
- .Times(1);
-
- binarystream request;
- const u_int16_t sequence = 0x1010;
- request << sequence << P::LOAD << string("one.dll") << string("one.pdb")
- << string("1111");
- binarystream response;
- ASSERT_TRUE(server.HandleRequest(request, response));
- u_int16_t response_sequence;
- u_int8_t response_status, response_data;
- response >> response_sequence >> response_status >> response_data;
- ASSERT_FALSE(response.eof());
- EXPECT_EQ(sequence, response_sequence);
- EXPECT_EQ(P::OK, int(response_status));
- ASSERT_EQ(int(P::LOAD_OK), int(response_data));
-
- binarystream request2;
- const u_int16_t sequence2 = 0x2020;
- request2 << sequence2 << P::LOAD << string("two.dll") << string("two.pdb")
- << string("2222");
- ASSERT_TRUE(server.HandleRequest(request2, response));
- response >> response_sequence >> response_status >> response_data;
- ASSERT_FALSE(response.eof());
- EXPECT_EQ(sequence2, response_sequence);
- EXPECT_EQ(P::OK, int(response_status));
- ASSERT_EQ(int(P::LOAD_OK), int(response_data));
-
- binarystream request3;
- const u_int16_t sequence3 = 0x3030;
- request3 << sequence3 << P::LOAD << string("one.dll") << string("one.pdb")
- << string("1111");
- ASSERT_TRUE(server.HandleRequest(request3, response));
- response >> response_sequence >> response_status >> response_data;
- ASSERT_FALSE(response.eof());
- EXPECT_EQ(sequence3, response_sequence);
- EXPECT_EQ(P::OK, int(response_status));
- ASSERT_EQ(int(P::LOAD_OK), int(response_data));
-
- binarystream request4;
- const u_int16_t sequence4 = 0x4040;
- request4 << sequence4 << P::LOAD << string("three.dll") << string("three.pdb")
- << string("3333");
- ASSERT_TRUE(server.HandleRequest(request4, response));
- response >> response_sequence >> response_status >> response_data;
- ASSERT_FALSE(response.eof());
- EXPECT_EQ(sequence4, response_sequence);
- EXPECT_EQ(P::OK, int(response_status));
- ASSERT_EQ(int(P::LOAD_OK), int(response_data));
-}
-
-TEST_F(TestModuleManagement, TestModuleGetLRU) {
- // load 2 modules, then issue a GET for the first one,
- // then load a third one, causing the second one to be unloaded
- EXPECT_CALL(supplier, GetSymbolFile(_,_,_,_))
- .Times(3)
- .WillRepeatedly(DoAll(SetArgumentPointee<3>(string("1\n2\n3\n4\n5\n6\n7\n8\n9\n10\n")),
- Return(SymbolSupplier::FOUND)));
- EXPECT_CALL(resolver, HasModule(_))
- .Times(3)
- .WillRepeatedly(Return(false));
- EXPECT_CALL(resolver, LoadModuleUsingMapBuffer(_,_))
- .Times(3)
- .WillRepeatedly(Return(true));
- EXPECT_CALL(resolver, FillSourceLineInfo(_))
- .Times(1);
- EXPECT_CALL(resolver, UnloadModule(Property(&CodeModule::code_file,
- string("two.dll|two.pdb|2222"))))
- .Times(1);
-
- binarystream request;
- const u_int16_t sequence = 0x1010;
- request << sequence << P::LOAD << string("one.dll") << string("one.pdb")
- << string("1111");
- binarystream response;
- ASSERT_TRUE(server.HandleRequest(request, response));
- u_int16_t response_sequence;
- u_int8_t response_status, response_data;
- response >> response_sequence >> response_status >> response_data;
- ASSERT_FALSE(response.eof());
- EXPECT_EQ(sequence, response_sequence);
- EXPECT_EQ(P::OK, int(response_status));
- ASSERT_EQ(int(P::LOAD_OK), int(response_data));
-
- binarystream request2;
- const u_int16_t sequence2 = 0x2020;
- request2 << sequence2 << P::LOAD << string("two.dll") << string("two.pdb")
- << string("2222");
- ASSERT_TRUE(server.HandleRequest(request2, response));
- response >> response_sequence >> response_status >> response_data;
- ASSERT_FALSE(response.eof());
- EXPECT_EQ(sequence2, response_sequence);
- EXPECT_EQ(P::OK, int(response_status));
- ASSERT_EQ(int(P::LOAD_OK), int(response_data));
-
- binarystream request3;
- const u_int16_t sequence3 = 0x3030;
- request3 << sequence3 << P::GET << string("one.dll")
- << string("one.pdb") << string("1111")
- << u_int64_t(0x1000) << u_int64_t(0x1234);
- ASSERT_TRUE(server.HandleRequest(request3, response));
- string function, source_file;
- u_int32_t source_line;
- u_int64_t function_base, source_line_base;
- response >> response_sequence >> response_status >> function
- >> function_base >> source_file >> source_line >> source_line_base;
- ASSERT_FALSE(response.eof());
- EXPECT_EQ(sequence3, response_sequence);
- EXPECT_EQ(P::OK, int(response_status));
- // Don't care about the rest of the response, really.
-
- binarystream request4;
- const u_int16_t sequence4 = 0x4040;
- request4 << sequence4 << P::LOAD << string("three.dll") << string("three.pdb")
- << string("3333");
- ASSERT_TRUE(server.HandleRequest(request4, response));
- response >> response_sequence >> response_status >> response_data;
- ASSERT_FALSE(response.eof());
- EXPECT_EQ(sequence4, response_sequence);
- EXPECT_EQ(P::OK, int(response_status));
- ASSERT_EQ(int(P::LOAD_OK), int(response_data));
-}
-
-TEST_F(TestModuleManagement, TestModuleGetStackWinLRU) {
- // load 2 modules, then issue a GETSTACKWIN for the first one,
- // then load a third one, causing the second one to be unloaded
- EXPECT_CALL(supplier, GetSymbolFile(_,_,_,_))
- .Times(3)
- .WillRepeatedly(DoAll(SetArgumentPointee<3>(string("1\n2\n3\n4\n5\n6\n7\n8\n9\n10\n")),
- Return(SymbolSupplier::FOUND)));
- EXPECT_CALL(resolver, HasModule(_))
- .Times(3)
- .WillRepeatedly(Return(false));
- EXPECT_CALL(resolver, LoadModuleUsingMapBuffer(_,_))
- .Times(3)
- .WillRepeatedly(Return(true));
- EXPECT_CALL(resolver, FindWindowsFrameInfo(_))
- .WillOnce(Return((WindowsFrameInfo*)NULL));
- EXPECT_CALL(resolver, UnloadModule(Property(&CodeModule::code_file,
- string("two.dll|two.pdb|2222"))))
- .Times(1);
-
- binarystream request;
- const u_int16_t sequence = 0x1010;
- request << sequence << P::LOAD << string("one.dll") << string("one.pdb")
- << string("1111");
- binarystream response;
- ASSERT_TRUE(server.HandleRequest(request, response));
- u_int16_t response_sequence;
- u_int8_t response_status, response_data;
- response >> response_sequence >> response_status >> response_data;
- ASSERT_FALSE(response.eof());
- EXPECT_EQ(sequence, response_sequence);
- EXPECT_EQ(P::OK, int(response_status));
- ASSERT_EQ(int(P::LOAD_OK), int(response_data));
-
- binarystream request2;
- const u_int16_t sequence2 = 0x2020;
- request2 << sequence2 << P::LOAD << string("two.dll") << string("two.pdb")
- << string("2222");
- ASSERT_TRUE(server.HandleRequest(request2, response));
- response >> response_sequence >> response_status >> response_data;
- ASSERT_FALSE(response.eof());
- EXPECT_EQ(sequence2, response_sequence);
- EXPECT_EQ(P::OK, int(response_status));
- ASSERT_EQ(int(P::LOAD_OK), int(response_data));
-
- binarystream request3;
- const u_int16_t sequence3 = 0x3030;
- request3 << sequence3 << P::GETSTACKWIN << string("one.dll")
- << string("one.pdb") << string("1111")
- << u_int64_t(0x1000) << u_int64_t(0x1234);
- ASSERT_TRUE(server.HandleRequest(request3, response));
- string stack_info;
- response >> response_sequence >> response_status
- >> stack_info;
- ASSERT_FALSE(response.eof());
- EXPECT_EQ(sequence3, response_sequence);
- EXPECT_EQ(P::OK, int(response_status));
- // Don't care about the rest of the response, really.
-
- binarystream request4;
- const u_int16_t sequence4 = 0x4040;
- request4 << sequence4 << P::LOAD << string("three.dll") << string("three.pdb")
- << string("3333");
- ASSERT_TRUE(server.HandleRequest(request4, response));
- response >> response_sequence >> response_status >> response_data;
- ASSERT_FALSE(response.eof());
- EXPECT_EQ(sequence4, response_sequence);
- EXPECT_EQ(P::OK, int(response_status));
- ASSERT_EQ(int(P::LOAD_OK), int(response_data));
-}
-
-} // namespace
-
-int main(int argc, char *argv[]) {
- ::testing::InitGoogleTest(&argc, argv);
- return RUN_ALL_TESTS();
-}
diff --git a/src/processor/source_daemon.cc b/src/processor/source_daemon.cc
deleted file mode 100644
index f47b1f3f..00000000
--- a/src/processor/source_daemon.cc
+++ /dev/null
@@ -1,127 +0,0 @@
-// Copyright (c) 2010, 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.
-
-// source_daemon.cc: Listen for incoming UDP requests for source line
-// info, load symbol files and respond with source info.
-//
-// Author: Ted Mielczarek
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <string>
-#include <vector>
-
-#include "google_breakpad/processor/basic_source_line_resolver.h"
-#include "processor/logging.h"
-#include "processor/network_source_line_server.h"
-#include "processor/scoped_ptr.h"
-#include "processor/simple_symbol_supplier.h"
-
-using std::string;
-using std::vector;
-using google_breakpad::BasicSourceLineResolver;
-using google_breakpad::NetworkSourceLineServer;
-using google_breakpad::scoped_ptr;
-using google_breakpad::SimpleSymbolSupplier;
-
-void usage(char *progname) {
- printf("Usage: %s [-p port] [-a listen address] "
- "[-m maximum symbol lines to keep in memory] "
- "<symbol paths>\n", progname);
-}
-
-int main(int argc, char **argv) {
- BPLOG_INIT(&argc, &argv);
-
- unsigned short listen_port = 0;
- char listen_address[1024] = "";
- u_int64_t max_symbol_lines = 0;
- int arg;
- while((arg = getopt(argc, argv, "p:a:m:")) != -1) {
- switch(arg) {
- case 'p': {
- int port_arg = atoi(optarg);
- if (port_arg > -1 && port_arg < 65535) {
- listen_port = port_arg;
- } else {
- fprintf(stderr, "Invalid port number for -p!\n");
- usage(argv[0]);
- return 1;
- }
- }
- break;
- case 'a':
- strncpy(listen_address, optarg, sizeof(listen_address));
- break;
- case 'm':
- max_symbol_lines = atoll(optarg);
- break;
- case '?':
- fprintf(stderr, "Option -%c requires an argument\n", (char)optopt);
- usage(argv[0]);
- break;
- default:
- fprintf(stderr, "Unknown option: -%c\n", (char)arg);
- usage(argv[0]);
- return 1;
- }
- }
-
- if (optind >= argc) {
- usage(argv[0]);
- return 1;
- }
-
- vector<string> symbol_paths;
- for (int argi = optind; argi < argc; ++argi)
- symbol_paths.push_back(argv[argi]);
-
- scoped_ptr<SimpleSymbolSupplier> symbol_supplier;
- if (!symbol_paths.empty()) {
- symbol_supplier.reset(new SimpleSymbolSupplier(symbol_paths));
- }
- BasicSourceLineResolver resolver;
-
- NetworkSourceLineServer server(symbol_supplier.get(), &resolver, listen_port,
- // default to IPv4 if no listen address
- // is specified
- listen_address[0] == '\0',
- listen_address,
- max_symbol_lines);
- if (!server.Initialize()) {
- BPLOG(ERROR) << "Failed to initialize server.";
- return 1;
- }
-
- server.RunForever();
- // not reached
- return 0;
-}
diff --git a/src/processor/udp_network.cc b/src/processor/udp_network.cc
deleted file mode 100644
index 0cb911e0..00000000
--- a/src/processor/udp_network.cc
+++ /dev/null
@@ -1,187 +0,0 @@
-// Copyright (c) 2010, 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.
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "processor/udp_network.h"
-
-#include <arpa/inet.h>
-#include <errno.h>
-#include <netdb.h>
-#include <netinet/in.h>
-#include <stdio.h>
-#include <string.h>
-#include <sys/socket.h>
-
-#include <string>
-
-#include "processor/logging.h"
-
-namespace google_breakpad {
-using std::string;
-using std::dec;
-
-UDPNetwork::~UDPNetwork() {
- if (socket_ != -1) {
- close(socket_);
- socket_ = -1;
- }
-}
-
-bool UDPNetwork::Init(bool listen) {
- struct addrinfo hints;
- struct addrinfo *results;
- memset(&hints, 0, sizeof(hints));
- if (ip4only_)
- hints.ai_family = AF_INET;
- else
- // don't care if it's IPv4 or IPv6
- hints.ai_family = AF_UNSPEC;
- // want a UDP socket
- hints.ai_socktype = SOCK_DGRAM;
- if (listen)
- hints.ai_flags = AI_PASSIVE;
-
- const char *hostname = NULL;
- if (!server_.empty())
- hostname = server_.c_str();
- char portname[6];
- sprintf(portname, "%u", port_);
- if (!listen) {
- BPLOG(INFO) << "Initializing network connection to " << server_
- << ":" << dec << port_;
- }
- if (getaddrinfo(hostname, portname, &hints, &results) != 0) {
- BPLOG(ERROR) << "failed to get address info for address " << server_
- << ": " << strerror(errno);
- return false;
- }
- // save the address of the first result.
- //TODO(ted): could support multiple DNS entries, round-robin them for
- // fail-over etc
- memcpy(&address_, results->ai_addr, GET_SA_LEN(results->ai_addr));
-
- socket_ = socket(results->ai_family, results->ai_socktype,
- results->ai_protocol);
- freeaddrinfo(results);
-
- if (socket_ == -1) {
- BPLOG(ERROR) << "failed to create socket: " << strerror(errno);
- return false;
- }
-
- if (listen) {
- char address_string[INET_ADDRSTRLEN];
- void *addr = NULL;
- if (((struct sockaddr*)&address_)->sa_family == AF_INET)
- addr = &((struct sockaddr_in*)&address_)->sin_addr;
- else if (((struct sockaddr*)&address_)->sa_family == AF_INET6)
- addr = &((struct sockaddr_in6*)&address_)->sin6_addr;
- if (inet_ntop(((struct sockaddr*)&address_)->sa_family, addr,
- address_string, sizeof(address_string)) != NULL)
- BPLOG(INFO) << "Listening on address " << address_string;
-
- if (bind(socket_,
- (struct sockaddr *)&address_,
- GET_SA_LEN(address_)) == -1) {
- BPLOG(ERROR) << "Failed to bind socket";
- close(socket_);
- return false;
- }
- socklen_t bound_addr_len = GET_SA_LEN(address_);
- if (getsockname(socket_, (struct sockaddr *)&address_, &bound_addr_len)
- == 0) {
- if (((struct sockaddr*)&address_)->sa_family == AF_INET)
- port_ = ntohs(((struct sockaddr_in*)&address_)->sin_port);
- else if (((struct sockaddr*)&address_)->sa_family == AF_INET6)
- port_ = ntohs(((struct sockaddr_in6*)&address_)->sin6_port);
- }
- BPLOG(INFO) << "Listening on port " << port_;
- }
- return true;
-}
-
-bool UDPNetwork::Send(const char *data, size_t length) {
- int total_sent = 0;
- while (total_sent < length) {
- int bytes_sent = sendto(socket_,
- data + total_sent,
- length - total_sent,
- 0,
- (struct sockaddr *)&address_,
- GET_SA_LEN(address_));
- if (bytes_sent < 0) {
- BPLOG(ERROR) << "error sending message: "
- << strerror(errno) << " (" << errno << ")";
- break;
- }
- total_sent += bytes_sent;
- }
- return total_sent == length;
-}
-
-bool UDPNetwork::WaitToReceive(int wait_time) {
- fd_set readfds;
- FD_ZERO(&readfds);
- FD_SET(socket_, &readfds);
- struct timeval timeout;
-
- timeout.tv_sec = wait_time / 1000;
- timeout.tv_usec = (wait_time % 1000) * 1000;
- int ret = select(socket_+1, &readfds, NULL, NULL, &timeout);
- if (ret == 0) {
- return false;
- } else if (ret == -1) {
- if (errno != EINTR)
- BPLOG(ERROR) << "error in select(): " << strerror(errno);
- return false;
- } else if (!FD_ISSET(socket_, &readfds)) {
- BPLOG(ERROR) << "select returned, but our socket isn't ready?";
- return false;
- }
-
- return true;
-}
-
-bool UDPNetwork::Receive(char *buffer, size_t buffer_size, ssize_t &received) {
- socklen_t fromlen = GET_SA_LEN(address_);
- received = recvfrom(socket_, buffer, buffer_size, 0,
- (struct sockaddr *)&address_,
- &fromlen);
-
- if (received == -1) {
- BPLOG(ERROR) << "Error in recvfrom reading response: "
- << strerror(errno);
- }
- return received != -1;
-}
-
-} // namespace google_breakpad
diff --git a/src/processor/udp_network.h b/src/processor/udp_network.h
deleted file mode 100644
index 6e8488bc..00000000
--- a/src/processor/udp_network.h
+++ /dev/null
@@ -1,73 +0,0 @@
-// Copyright (c) 2010, 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.
-
-// UDPNetwork implements NetworkInterface using UDP sockets.
-
-#ifndef _GOOGLE_BREAKPAD_PROCESSOR_UDP_NETWORK_H_
-#define _GOOGLE_BREAKPAD_PROCESSOR_UDP_NETWORK_H_
-
-#include <sys/socket.h>
-
-#include <string>
-
-#include "processor/network_interface.h"
-
-namespace google_breakpad {
-
-class UDPNetwork : public NetworkInterface {
- public:
- // Initialize a UDP Network socket at this address and port.
- // address can be empty to indicate that any local address is acceptable.
- UDPNetwork(const std::string address,
- unsigned short port,
- bool ip4only = false)
- : server_(address),
- port_(port),
- ip4only_(ip4only),
- socket_(-1) {};
-
- ~UDPNetwork();
-
- virtual bool Init(bool listen);
- virtual bool Send(const char *data, size_t length);
- virtual bool WaitToReceive(int timeout);
- virtual bool Receive(char *buffer, size_t buffer_size, ssize_t &received);
-
- unsigned short port() { return port_; }
-
- private:
- std::string server_;
- unsigned short port_;
- bool ip4only_;
- struct sockaddr_storage address_;
- int socket_;
-};
-
-} // namespace google_breakpad
-#endif // GOOGLE_BREAKPAD_PROCESSOR_UDP_NETWORK_H_