aboutsummaryrefslogtreecommitdiff
path: root/src/processor/network_source_line_resolver.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/processor/network_source_line_resolver.cc')
-rw-r--r--src/processor/network_source_line_resolver.cc455
1 files changed, 0 insertions, 455 deletions
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