From b223627d81c083a64f2ccecf2651a18111421280 Mon Sep 17 00:00:00 2001 From: "ted.mielczarek" Date: Thu, 8 Apr 2010 23:06:23 +0000 Subject: provide a network source line resolver + server. r=mark,jimb at http://breakpad.appspot.com/36001 git-svn-id: http://google-breakpad.googlecode.com/svn/trunk@569 4c0a9323-5329-0410-9bdc-e9ce6186880e --- .../processor/basic_source_line_resolver.h | 13 +- .../processor/network_source_line_resolver.h | 168 +++++++++++++++++++++ .../processor/source_line_resolver_interface.h | 24 +-- 3 files changed, 189 insertions(+), 16 deletions(-) create mode 100644 src/google_breakpad/processor/network_source_line_resolver.h (limited to 'src/google_breakpad') diff --git a/src/google_breakpad/processor/basic_source_line_resolver.h b/src/google_breakpad/processor/basic_source_line_resolver.h index 831556b5..fe93f4d2 100644 --- a/src/google_breakpad/processor/basic_source_line_resolver.h +++ b/src/google_breakpad/processor/basic_source_line_resolver.h @@ -53,17 +53,18 @@ class BasicSourceLineResolver : public SourceLineResolverInterface { // Adds a module to this resolver, returning true on success. // The given map_file is read into memory, and its symbols will be // retained until the BasicSourceLineResolver is destroyed. - virtual bool LoadModule(const string &module_name, const string &map_file); + virtual bool LoadModule(const CodeModule *module, const string &map_file); // Exactly the same as above, except the given map_buffer is used // for symbols. - virtual bool LoadModuleUsingMapBuffer(const string &module_name, + virtual bool LoadModuleUsingMapBuffer(const CodeModule *module, const string &map_buffer); - virtual bool HasModule(const string &module_name) const; - virtual void FillSourceLineInfo(StackFrame *frame) const; - virtual WindowsFrameInfo *FindWindowsFrameInfo(const StackFrame *frame) const; - virtual CFIFrameInfo *FindCFIFrameInfo(const StackFrame *frame) const; + void UnloadModule(const CodeModule *module); + virtual bool HasModule(const CodeModule *module); + virtual void FillSourceLineInfo(StackFrame *frame); + virtual WindowsFrameInfo *FindWindowsFrameInfo(const StackFrame *frame); + virtual CFIFrameInfo *FindCFIFrameInfo(const StackFrame *frame); private: template class MemAddrMap; diff --git a/src/google_breakpad/processor/network_source_line_resolver.h b/src/google_breakpad/processor/network_source_line_resolver.h new file mode 100644 index 00000000..f2c7732d --- /dev/null +++ b/src/google_breakpad/processor/network_source_line_resolver.h @@ -0,0 +1,168 @@ +// 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. + +// NetworkSourceLineResolver implements SourceLineResolverInterface and +// SymbolSupplier using a UDP-based network protocol to communicate to a +// server process which handles the lower-level details of loading symbols +// and resolving source info. When used, it must be used simultaneously +// as the SourceLineResolver and SymbolSupplier. +// +// See network_source_line_server.h for a description of the protocol used. +// An implementation of the server side of the protocol is provided there +// as NetworkSourceLineServer. + +#ifndef GOOGLE_BREAKPAD_PROCESSOR_NETWORK_SOURCE_LINE_RESOLVER_H_ +#define GOOGLE_BREAKPAD_PROCESSOR_NETWORK_SOURCE_LINE_RESOLVER_H_ + +#include + +#include +#include + +#include "google_breakpad/common/breakpad_types.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/linked_ptr.h" +#include "processor/network_interface.h" + +namespace google_breakpad { + +using std::string; + +class NetworkSourceLineResolver : public SourceLineResolverInterface, + public SymbolSupplier { + public: + // The server and port to connect to, and the + // maximum time (in milliseconds) to wait for network replies. + NetworkSourceLineResolver(const string &server, + unsigned short port, + int wait_milliseconds); + // The network interface to connect to, and maximum wait time. + NetworkSourceLineResolver(NetworkInterface *net, + int wait_milliseconds); + virtual ~NetworkSourceLineResolver(); + + // SourceLineResolverInterface methods, see source_line_resolver_interface.h + // for more details. + + + // These methods are actually NOOPs in this implementation. + // The server loads modules as a result of the GetSymbolFile call. + // Since we're both the symbol supplier and source line resolver, + // this is an optimization. + virtual bool LoadModule(const CodeModule *module, const string &map_file); + virtual bool LoadModuleUsingMapBuffer(const CodeModule *module, + const string &map_buffer); + + void UnloadModule(const CodeModule *module); + + virtual bool HasModule(const CodeModule *module); + + virtual void FillSourceLineInfo(StackFrame *frame); + virtual WindowsFrameInfo *FindWindowsFrameInfo(const StackFrame *frame); + virtual CFIFrameInfo *FindCFIFrameInfo(const StackFrame *frame); + + // SymbolSupplier methods, see symbol_supplier.h for more details. + // Note that the server will actually load the symbol data + // in response to this request, as an optimization. + virtual SymbolResult GetSymbolFile(const CodeModule *module, + const SystemInfo *system_info, + string *symbol_file); + //FIXME: we'll never return symbol_data here, it doesn't make sense. + // the SymbolSupplier interface should just state that the supplier + // *may* fill in symbol_data if it desires, and clients should + // handle it gracefully either way. + virtual SymbolResult GetSymbolFile(const CodeModule *module, + const SystemInfo *system_info, + string *symbol_file, + string *symbol_data); + + private: + int wait_milliseconds_; + // if false, some part of our network setup failed. + bool initialized_; + // sequence number of the last request we made + u_int16_t sequence_; + NetworkInterface *net_; + // cached list of loaded modules, so we can quickly answer + // HasModule requests for modules we've already queried the + // server about, avoiding another network round-trip. + std::set module_cache_; + // cached list of modules for which we don't have symbols, + // so we can short-circuit that as well. + std::set no_symbols_cache_; + + // Cached list of source line info, to avoid repeated GET requests + // for the same frame. In Multithreaded apps that use the same + // framework across threads, it's pretty common to hit the same + // exact set of frames in multiple threads. + // Data is stored in the cache keyed by instruction pointer + typedef std::map SourceCache; + SourceCache source_line_info_cache_; + + // Cached list of WindowsFrameInfo/CFIFrameInfo, for the same reason. + // Stored as serialized strings to avoid shuffling around pointers. + typedef std::map FrameInfoCache; + + typedef enum { + kWindowsFrameInfo = 0, + kCFIFrameInfo = 1, + } FrameInfoType; + FrameInfoCache frame_info_cache_[2]; + + // Send a message to the server, wait a certain amount of time for a reply. + // Returns true if a response is received, with the response data + // in |response|. + // Returns false if the response times out. + bool SendMessageGetResponse(const binarystream &message, + binarystream &response); + + // See if this stack frame is cached, and fill in the source line info + // if so. + bool FindCachedSourceLineInfo(StackFrame *frame) const; + bool FindCachedFrameInfo(const StackFrame *frame, + FrameInfoType type, + string *info) const; + + // Save this stack frame in the cache + void CacheSourceLineInfo(const StackFrame *frame); + void CacheFrameInfo(const StackFrame *frame, + FrameInfoType type, + const string &info); + + // Disallow unwanted copy ctor and assignment operator + NetworkSourceLineResolver(const NetworkSourceLineResolver&); + void operator=(const NetworkSourceLineResolver&); +}; + +} // namespace google_breakpad + +#endif // GOOGLE_BREAKPAD_PROCESSOR_NETWORK_SOURCE_LINE_RESOLVER_H_ diff --git a/src/google_breakpad/processor/source_line_resolver_interface.h b/src/google_breakpad/processor/source_line_resolver_interface.h index a7ec9b7f..fa45d75f 100644 --- a/src/google_breakpad/processor/source_line_resolver_interface.h +++ b/src/google_breakpad/processor/source_line_resolver_interface.h @@ -36,6 +36,7 @@ #include #include "google_breakpad/common/breakpad_types.h" +#include "google_breakpad/processor/code_module.h" namespace google_breakpad { @@ -53,37 +54,40 @@ class SourceLineResolverInterface { // Adds a module to this resolver, returning true on success. // - // module_name may be an arbitrary string. Typically, it will be the - // filename of the module, optionally with version identifiers. + // module should have at least the code_file, debug_file, + // and debug_identifier members populated. // // map_file should contain line/address mappings for this module. - virtual bool LoadModule(const string &module_name, + virtual bool LoadModule(const CodeModule *module, const string &map_file) = 0; // Same as above, but takes the contents of a pre-read map buffer - virtual bool LoadModuleUsingMapBuffer(const string &module_name, + virtual bool LoadModuleUsingMapBuffer(const CodeModule *module, const string &map_buffer) = 0; - // Returns true if a module with the given name has been loaded. - virtual bool HasModule(const string &module_name) const = 0; + // Request that the specified module be unloaded from this resolver. + // A resolver may choose to ignore such a request. + virtual void UnloadModule(const CodeModule *module) = 0; + + // Returns true if the module has been loaded. + virtual bool HasModule(const CodeModule *module) = 0; // Fills in the function_base, function_name, source_file_name, // and source_line fields of the StackFrame. The instruction and // module_name fields must already be filled in. - virtual void FillSourceLineInfo(StackFrame *frame) const = 0; + virtual void FillSourceLineInfo(StackFrame *frame) = 0; // If Windows stack walking information is available covering // FRAME's instruction address, return a WindowsFrameInfo structure // describing it. If the information is not available, returns NULL. // A NULL return value does not indicate an error. The caller takes // ownership of any returned WindowsFrameInfo object. - virtual WindowsFrameInfo *FindWindowsFrameInfo(const StackFrame *frame) - const = 0; + virtual WindowsFrameInfo *FindWindowsFrameInfo(const StackFrame *frame) = 0; // If CFI stack walking information is available covering ADDRESS, // return a CFIFrameInfo structure describing it. If the information // is not available, return NULL. The caller takes ownership of any // returned CFIFrameInfo object. - virtual CFIFrameInfo *FindCFIFrameInfo(const StackFrame *frame) const = 0; + virtual CFIFrameInfo *FindCFIFrameInfo(const StackFrame *frame) = 0; protected: // SourceLineResolverInterface cannot be instantiated except by subclasses -- cgit v1.2.1