diff options
| author | Lynx Linden <lynx@lindenlab.com> | 2010-06-07 12:14:13 +0100 | 
|---|---|---|
| committer | Lynx Linden <lynx@lindenlab.com> | 2010-06-07 12:14:13 +0100 | 
| commit | 185cd5d261a4bc6e02f49f40c72d76da4320a881 (patch) | |
| tree | c08ae4afb5e79f6b90bfe085a32b4d3e6e16a070 /indra/newview | |
| parent | eec00a712fff079009ae793d86e27b7f3ab13053 (diff) | |
| parent | edd224dc7b08ad72c0f36c5b0f24912fdf66ab1c (diff) | |
Automated merge with ssh://hg.lindenlab.com/dessie/viewer-public
Diffstat (limited to 'indra/newview')
| -rw-r--r-- | indra/newview/CMakeLists.txt | 65 | ||||
| -rw-r--r-- | indra/newview/app_settings/settings.xml | 11 | ||||
| -rw-r--r-- | indra/newview/generate_breakpad_symbols.py | 130 | ||||
| -rw-r--r-- | indra/newview/llappviewer.cpp | 63 | ||||
| -rw-r--r-- | indra/newview/llappviewer.h | 2 | ||||
| -rw-r--r-- | indra/newview/llappviewerlinux.cpp | 226 | ||||
| -rw-r--r-- | indra/newview/llappviewerlinux.h | 1 | ||||
| -rw-r--r-- | indra/newview/llappviewermacosx.cpp | 37 | ||||
| -rw-r--r-- | indra/newview/llappviewermacosx.h | 1 | ||||
| -rw-r--r-- | indra/newview/llappviewerwin32.cpp | 65 | ||||
| -rw-r--r-- | indra/newview/llappviewerwin32.h | 1 | ||||
| -rw-r--r-- | indra/newview/llstartup.cpp | 1 | ||||
| -rw-r--r-- | indra/newview/llviewermessage.cpp | 4 | ||||
| -rw-r--r-- | indra/newview/llwindebug.cpp | 912 | ||||
| -rw-r--r-- | indra/newview/llwindebug.h | 75 | ||||
| -rwxr-xr-x | indra/newview/viewer_manifest.py | 27 | 
16 files changed, 251 insertions, 1370 deletions
| diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index 7dbe650625..2eff65f46e 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -1066,7 +1066,6 @@ set(viewer_HEADER_FILES      llwearabletype.h      llweb.h      llwind.h -    llwindebug.h      llwlanimator.h      llwldaycycle.h      llwlparammanager.h @@ -1140,12 +1139,10 @@ endif (LINUX)  if (WINDOWS)      list(APPEND viewer_SOURCE_FILES           llappviewerwin32.cpp -         llwindebug.cpp           )      list(APPEND viewer_HEADER_FILES           llappviewerwin32.h -         llwindebug.h           )      # precompiled header configuration @@ -1702,6 +1699,29 @@ if (LINUX)      add_dependencies(package linux-updater-target)      check_message_template(package)    endif (NOT INSTALL) + +  add_custom_command( +    OUTPUT  ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/.${product}.copy_touched +    COMMAND ${PYTHON_EXECUTABLE} +    ARGS +      ${CMAKE_CURRENT_SOURCE_DIR}/viewer_manifest.py +      --arch=${ARCH} +      --actions=copy +      --artwork=${ARTWORK_DIR} +      --build=${CMAKE_CURRENT_BINARY_DIR} +      --buildtype=${CMAKE_BUILD_TYPE} +      --configuration=${CMAKE_CFG_INTDIR} +      --dest=${CMAKE_CURRENT_BINARY_DIR}/packaged +      --grid=${GRID} +      --source=${CMAKE_CURRENT_SOURCE_DIR} +    DEPENDS  +      ${CMAKE_CURRENT_SOURCE_DIR}/viewer_manifest.py +      ${COPY_INPUT_DEPENDENCIES} +    COMMENT "Performing viewer_manifest copy" +    ) +     +  add_custom_target(copy_l_viewer_manifest ALL DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/.${product}.copy_touched)  +  add_dependencies(copy_l_viewer_manifest "${VIEWER_BINARY_NAME}" linux-crash-logger-target linux-updater-target)  endif (LINUX)  if (DARWIN) @@ -1789,6 +1809,45 @@ if (INSTALL)    include(${CMAKE_CURRENT_SOURCE_DIR}/ViewerInstall.cmake)  endif (INSTALL) +if (PACKAGE) +  if (WINDOWS) +    set(VIEWER_DIST_DIR "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}") +    set(VIEWER_SYMBOL_FILE "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/secondlife-symbols-windows.tar.bz2") +    set(VIEWER_EXE_GLOBS "${VIEWER_BINARY_NAME}${CMAKE_EXECUTABLE_SUFFIX} slplugin.exe") +    set(VIEWER_LIB_GLOB "*${CMAKE_SHARED_MODULE_SUFFIX}") +    set(VIEWER_COPY_MANIFEST copy_w_viewer_manifest) +  endif (WINDOWS) +  if (DARWIN) +    set(VIEWER_DIST_DIR "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/${product}.app") +    set(VIEWER_SYMBOL_FILE "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/secondlife-symbols-darwin.tar.bz2") +    set(VIEWER_EXE_GLOBS "'Second Life' SLPlugin") +    set(VIEWER_LIB_GLOB "*.dylib") +  endif (DARWIN) +  if (LINUX) +    set(VIEWER_DIST_DIR "${CMAKE_CURRENT_BINARY_DIR}/packaged") +    set(VIEWER_SYMBOL_FILE "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/secondlife-symbols-linux.tar.bz2") +    set(VIEWER_EXE_GLOBS "do-not-directly-run-secondlife-bin SLPlugin") +    set(VIEWER_LIB_GLOB "*${CMAKE_SHARED_MODULE_SUFFIX}*") +    set(VIEWER_COPY_MANIFEST copy_l_viewer_manifest) +  endif (LINUX) + +  add_custom_command(OUTPUT "${VIEWER_SYMBOL_FILE}" +    COMMAND "${PYTHON_EXECUTABLE}" +    ARGS +      "${CMAKE_CURRENT_SOURCE_DIR}/generate_breakpad_symbols.py" +      "${VIEWER_DIST_DIR}" +      "${VIEWER_EXE_GLOBS}" +      "${VIEWER_LIB_GLOB}" +      "${LIBS_PREBUILT_DIR}/${LL_ARCH_DIR}/bin/dump_syms" +      "${VIEWER_SYMBOL_FILE}" +    DEPENDS generate_breakpad_symbols.py +    VERBATIM +  ) +  add_custom_target(generate_breakpad_symbols ALL DEPENDS "${VIEWER_SYMBOL_FILE}") +  add_dependencies(generate_breakpad_symbols "${VIEWER_BINARY_NAME}" "${VIEWER_COPY_MANIFEST}") +  add_dependencies(package generate_breakpad_symbols) +endif (PACKAGE) +  if (LL_TESTS)    # To add a viewer unit test, just add the test .cpp file below    # This creates a separate test project per file listed. diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index 53af87a870..1c5e2435de 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -1,6 +1,17 @@  <?xml version="1.0" ?>  <llsd>  <map> +	<key>CrashHostUrl</key> +    <map> +      <key>Comment</key> +      <string>A URL pointing to a crash report handler; overrides cluster negotiation to locate crash handler.</string> +      <key>Persist</key> +      <integer>1</integer> +      <key>Type</key> +      <string>String</string> +      <key>Value</key> +      <string /> +    </map>      <key>AFKTimeout</key>      <map>        <key>Comment</key> diff --git a/indra/newview/generate_breakpad_symbols.py b/indra/newview/generate_breakpad_symbols.py new file mode 100644 index 0000000000..d94301d62e --- /dev/null +++ b/indra/newview/generate_breakpad_symbols.py @@ -0,0 +1,130 @@ +#!/usr/bin/env python +# @file generate_breakpad_symbols.py +# @author Brad Kittenbrink <brad@lindenlab.com> +# @brief Simple tool for generating google_breakpad symbol information +#        for the crash reporter. +# +# $LicenseInfo:firstyear=2010&license=viewergpl$ +#  +# Copyright (c) 2010-2010, Linden Research, Inc. +#  +# Second Life Viewer Source Code +# The source code in this file ("Source Code") is provided by Linden Lab +# to you under the terms of the GNU General Public License, version 2.0 +# ("GPL"), unless you have obtained a separate licensing agreement +# ("Other License"), formally executed by you and Linden Lab.  Terms of +# the GPL can be found in doc/GPL-license.txt in this distribution, or +# online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 +#  +# There are special exceptions to the terms and conditions of the GPL as +# it is applied to this Source Code. View the full text of the exception +# in the file doc/FLOSS-exception.txt in this software distribution, or +# online at +# http://secondlifegrid.net/programs/open_source/licensing/flossexception +#  +# By copying, modifying or distributing this software, you acknowledge +# that you have read and understood your obligations described above, +# and agree to abide by those obligations. +#  +# ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO +# WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, +# COMPLETENESS OR PERFORMANCE. +# $/LicenseInfo$ + + +import collections +import fnmatch +import itertools +import operator +import os +import sys +import shlex +import subprocess +import tarfile +import StringIO + +def usage(): +    print >>sys.stderr, "usage: %s viewer_dir viewer_exes libs_suffix dump_syms_tool viewer_symbol_file" % sys.argv[0] + +class MissingModuleError(Exception): +    def __init__(self, modules): +        Exception.__init__(self, "Failed to find required modules: %r" % modules) +        self.modules = modules + +def main(viewer_dir, viewer_exes, libs_suffix, dump_syms_tool, viewer_symbol_file): +    print "generate_breakpad_symbols run with args: %s" % str((viewer_dir, viewer_exes, libs_suffix, dump_syms_tool, viewer_symbol_file)) + +    # split up list of viewer_exes +    # "'Second Life' SLPlugin" becomes ['Second Life', 'SLPlugin'] +    viewer_exes = shlex.split(viewer_exes) + +    found_required = dict([(module, False) for module in viewer_exes]) + +    def matches(f): +        if f in viewer_exes: +            found_required[f] = True +            return True +        return fnmatch.fnmatch(f, libs_suffix) + +    def list_files(): +        for (dirname, subdirs, filenames) in os.walk(viewer_dir): +            #print "scanning '%s' for modules..." % dirname +            for f in itertools.ifilter(matches, filenames): +                yield os.path.join(dirname, f) + +    def dump_module(m): +        print "dumping module '%s' with '%s'..." % (m, dump_syms_tool) +        child = subprocess.Popen([dump_syms_tool, m] , stdout=subprocess.PIPE) +        out, err = child.communicate() +        return (m,child.returncode, out, err) + +    out = tarfile.open(viewer_symbol_file, 'w:bz2') + +    for (filename,status,symbols,err) in itertools.imap(dump_module, list_files()): +        if status == 0: +            module_line = symbols[:symbols.index('\n')] +            module_line = module_line.split() +            hash_id = module_line[3] +            module = ' '.join(module_line[4:]) +            if sys.platform in ['win32', 'cygwin']: +                mod_name = module[:module.rindex('.pdb')] +            else: +                mod_name = module +            symbolfile = StringIO.StringIO(symbols) +            info = tarfile.TarInfo("%(module)s/%(hash_id)s/%(mod_name)s.sym" % dict(module=module, hash_id=hash_id, mod_name=mod_name)) +            info.size = symbolfile.len +            out.addfile(info, symbolfile) +        else: +            print >>sys.stderr, "warning: failed to dump symbols for '%s': %s" % (filename, err) + +    out.close() + +    missing_modules = [m for (m,_) in +        itertools.ifilter(lambda (k,v): not v, found_required.iteritems()) +    ] +    if missing_modules: +        print >> sys.stderr, "failed to generate %s" % viewer_symbol_file +        os.remove(viewer_symbol_file) +        raise MissingModuleError(missing_modules) + +    symbols = tarfile.open(viewer_symbol_file, 'r:bz2') +    tarfile_members = symbols.getnames() +    def match_module_basename(m): +        return os.path.splitext(required_module)[0] == os.path.splitext(os.path.basename(m))[0] +    for required_module in viewer_exes: +        # there must be at least one .sym file in tarfile_members that matches each required module (ignoring file extensions) +        if not reduce(operator.or_, itertools.imap(match_module_basename, tarfile_members)): +            print >> sys.stderr, "failed to find required %s in generated %s" % (required_module, viewer_symbol_file) +            os.remove(viewer_symbol_file) +            raise MissingModuleError([required_module]) + +    print "successfully generated %s including required modules '%s'" % (viewer_symbol_file, viewer_exes) + +    return 0 + +if __name__ == "__main__": +    if len(sys.argv) != 6: +        usage() +        sys.exit(1) +    sys.exit(main(*sys.argv[1:])) + diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index 95084666bb..0e93d3c395 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -103,8 +103,8 @@  // Third party library includes  #include <boost/bind.hpp> +  #if LL_WINDOWS -	#include "llwindebug.h"  #	include <share.h> // For _SH_DENYWR in initMarkerFile  #else  #   include <sys/file.h> // For initMarkerFile support @@ -603,6 +603,11 @@ bool LLAppViewer::init()  	if (!initConfiguration())  		return false; +	// write Google Breakpad minidump files to our log directory +	std::string logdir = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, ""); +	logdir += gDirUtilp->getDirDelimiter(); +	setMiniDumpDir(logdir); +  	// Although initLogging() is the right place to mess with  	// setFatalFunction(), we can't query gSavedSettings until after  	// initConfiguration(). @@ -1243,6 +1248,14 @@ bool LLAppViewer::cleanup()  	// workaround for DEV-35406 crash on shutdown  	LLEventPumps::instance().reset(); +	// remove any old breakpad minidump files from the log directory +	if (! isError()) +	{ +		std::string logdir = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, ""); +		logdir += gDirUtilp->getDirDelimiter(); +		gDirUtilp->deleteFilesInDir(logdir, "*-*-*-*-*.dmp"); +	} +  	// *TODO - generalize this and move DSO wrangling to a helper class -brad  	std::set<struct apr_dso_handle_t *>::const_iterator i;  	for(i = mPlugins.begin(); i != mPlugins.end(); ++i) @@ -2299,17 +2312,7 @@ void LLAppViewer::checkForCrash(void)  {  #if LL_SEND_CRASH_REPORTS -	//*NOTE:Mani The current state of the crash handler has the MacOSX -	// sending all crash reports as freezes, in order to let  -	// the MacOSX CrashRepoter generate stacks before spawning the  -	// SL crash logger. -	// The Linux and Windows clients generate their own stacks and -	// spawn the SL crash logger immediately. This may change in the future.  -#if LL_DARWIN -	if(gLastExecEvent != LAST_EXEC_NORMAL) -#else		  	if (gLastExecEvent == LAST_EXEC_FROZE) -#endif      {          llinfos << "Last execution froze, requesting to send crash report." << llendl;          // @@ -2540,13 +2543,6 @@ void LLAppViewer::writeSystemInfo()  	writeDebugInfo(); // Save out debug_info.log early, in case of crash.  } -void LLAppViewer::handleSyncViewerCrash() -{ -	LLAppViewer* pApp = LLAppViewer::instance(); -	// Call to pure virtual, handled by platform specific llappviewer instance. -	pApp->handleSyncCrashTrace();  -} -  void LLAppViewer::handleViewerCrash()  {  	llinfos << "Handle viewer crash entry." << llendl; @@ -2570,9 +2566,13 @@ void LLAppViewer::handleViewerCrash()  		return;  	}  	pApp->mReportedCrash = TRUE; - -	// Make sure the watchdog gets turned off... -// 	pApp->destroyMainloopTimeout(); // SJB: Bah. This causes the crash handler to hang, not sure why. +	 +	// Insert crash host url (url to post crash log to) if configured. +	std::string crashHostUrl = gSavedSettings.get<std::string>("CrashHostUrl"); +	if(crashHostUrl != "") +	{ +		gDebugInfo["CrashHostUrl"] = crashHostUrl; +	}  	//We already do this in writeSystemInfo(), but we do it again here to make /sure/ we have a version  	//to check against no matter what @@ -2604,6 +2604,12 @@ void LLAppViewer::handleViewerCrash()  	gDebugInfo["FirstLogin"] = (LLSD::Boolean) gAgent.isFirstLogin();  	gDebugInfo["FirstRunThisInstall"] = gSavedSettings.getBOOL("FirstRunThisInstall"); +	char *minidump_file = pApp->getMiniDumpFilename(); +	if(minidump_file && minidump_file[0] != 0) +	{ +		gDebugInfo["MinidumpPath"] = minidump_file; +	} +	  	if(gLogoutInProgress)  	{  		gDebugInfo["LastExecEvent"] = LAST_EXEC_LOGOUT_CRASH; @@ -2681,10 +2687,6 @@ void LLAppViewer::handleViewerCrash()  	LLError::logToFile(""); -// On Mac, we send the report on the next run, since we need macs crash report -// for a stack trace, so we have to let it the app fail. -#if !LL_DARWIN -  	// Remove the marker file, since otherwise we'll spawn a process that'll keep it locked  	if(gDebugInfo["LastExecEvent"].asInteger() == LAST_EXEC_LOGOUT_CRASH)  	{ @@ -2697,8 +2699,6 @@ void LLAppViewer::handleViewerCrash()  	// Call to pure virtual, handled by platform specific llappviewer instance.  	pApp->handleCrashReporting();  - -#endif //!LL_DARWIN  	return;  } @@ -3342,13 +3342,6 @@ void LLAppViewer::badNetworkHandler()  	mPurgeOnExit = TRUE; -#if LL_WINDOWS -	// Generates the minidump. -	LLWinDebug::generateCrashStacks(NULL); -#endif -	LLAppViewer::handleSyncViewerCrash(); -	LLAppViewer::handleViewerCrash(); -  	std::ostringstream message;  	message <<  		"The viewer has detected mangled network data indicative\n" @@ -3361,6 +3354,8 @@ void LLAppViewer::badNetworkHandler()  		"If the problem continues, see the Tech Support FAQ at: \n"  		"www.secondlife.com/support";  	forceDisconnect(message.str()); +	 +	LLApp::instance()->writeMiniDump();  }  // This routine may get called more than once during the shutdown process. diff --git a/indra/newview/llappviewer.h b/indra/newview/llappviewer.h index 5acd6e11c4..0b862a92a1 100644 --- a/indra/newview/llappviewer.h +++ b/indra/newview/llappviewer.h @@ -92,9 +92,7 @@ public:  	virtual bool restoreErrorTrap() = 0; // Require platform specific override to reset error handling mechanism.  	                                     // return false if the error trap needed restoration.  	virtual void handleCrashReporting(bool reportFreeze = false) = 0; // What to do with crash report? -	virtual void handleSyncCrashTrace() = 0; // any low-level crash-prep that has to happen in the context of the crashing thread before the crash report is delivered.  	static void handleViewerCrash(); // Hey! The viewer crashed. Do this, soon. -	static void handleSyncViewerCrash(); // Hey! The viewer crashed. Do this right NOW in the context of the crashing thread.      void checkForCrash();  	// Thread accessors diff --git a/indra/newview/llappviewerlinux.cpp b/indra/newview/llappviewerlinux.cpp index 78b0f7ba83..78afdc8995 100644 --- a/indra/newview/llappviewerlinux.cpp +++ b/indra/newview/llappviewerlinux.cpp @@ -46,23 +46,6 @@  #include <exception> -#if LL_LINUX -# include <dlfcn.h>		// RTLD_LAZY -# include <execinfo.h>  // backtrace - glibc only -#elif LL_SOLARIS -# include <sys/types.h> -# include <unistd.h> -# include <fcntl.h> -# include <ucontext.h> -#endif - -#ifdef LL_ELFBIN -# ifdef __GNUC__ -#  include <cxxabi.h>			// for symbol demangling -# endif -# include "ELFIO/ELFIO.h"		// for better backtraces -#endif -  #if LL_DBUS_ENABLED  # include "llappviewerlinux_api_dbus.h" @@ -86,7 +69,6 @@ static void exceptionTerminateHandler()  	// reinstall default terminate() handler in case we re-terminate.  	if (gOldTerminateHandler) std::set_terminate(gOldTerminateHandler);  	// treat this like a regular viewer crash, with nice stacktrace etc. -	LLAppViewer::handleSyncViewerCrash();  	LLAppViewer::handleViewerCrash();  	// we've probably been killed-off before now, but...  	gOldTerminateHandler(); // call old terminate() handler @@ -109,7 +91,6 @@ int main( int argc, char **argv )  	gOldTerminateHandler = std::set_terminate(exceptionTerminateHandler);  	// install crash handlers  	viewer_app_ptr->setErrorHandler(LLAppViewer::handleViewerCrash); -	viewer_app_ptr->setSyncErrorHandler(LLAppViewer::handleSyncViewerCrash);  	bool ok = viewer_app_ptr->init();  	if(!ok) @@ -138,201 +119,6 @@ int main( int argc, char **argv )  	return 0;  } -#ifdef LL_SOLARIS -static inline BOOL do_basic_glibc_backtrace() -{ -	BOOL success = FALSE; - -	std::string strace_filename = gDirUtilp->getExpandedFilename(LL_PATH_LOGS,"stack_trace.log"); -	llinfos << "Opening stack trace file " << strace_filename << llendl; -	LLFILE* StraceFile = LLFile::fopen(strace_filename, "w"); -	if (!StraceFile) -	{ -		llinfos << "Opening stack trace file " << strace_filename << " failed. Using stderr." << llendl; -		StraceFile = stderr; -	} - -	printstack(fileno(StraceFile)); - -	if (StraceFile != stderr) -		fclose(StraceFile); - -	return success; -} -#else -#define MAX_STACK_TRACE_DEPTH 40 -// This uses glibc's basic built-in stack-trace functions for a not very -// amazing backtrace. -static inline BOOL do_basic_glibc_backtrace() -{ -	void *stackarray[MAX_STACK_TRACE_DEPTH]; -	size_t size; -	char **strings; -	size_t i; -	BOOL success = FALSE; - -	size = backtrace(stackarray, MAX_STACK_TRACE_DEPTH); -	strings = backtrace_symbols(stackarray, size); - -	std::string strace_filename = gDirUtilp->getExpandedFilename(LL_PATH_LOGS,"stack_trace.log"); -	llinfos << "Opening stack trace file " << strace_filename << llendl; -	LLFILE* StraceFile = LLFile::fopen(strace_filename, "w");		// Flawfinder: ignore -        if (!StraceFile) -	{ -		llinfos << "Opening stack trace file " << strace_filename << " failed. Using stderr." << llendl; -		StraceFile = stderr; -	} - -	if (size) -	{ -		for (i = 0; i < size; i++) -		{ -			// the format of the StraceFile is very specific, to allow (kludgy) machine-parsing -			fprintf(StraceFile, "%-3lu ", (unsigned long)i); -			fprintf(StraceFile, "%-32s\t", "unknown"); -			fprintf(StraceFile, "%p ", stackarray[i]); -			fprintf(StraceFile, "%s\n", strings[i]); -		} - -		success = TRUE; -	} -	 -	if (StraceFile != stderr) -		fclose(StraceFile); - -	free (strings); -	return success; -} - -#if LL_ELFBIN -// This uses glibc's basic built-in stack-trace functions together with -// ELFIO's ability to parse the .symtab ELF section for better symbol -// extraction without exporting symbols (which'd cause subtle, fatal bugs). -static inline BOOL do_elfio_glibc_backtrace() -{ -	void *stackarray[MAX_STACK_TRACE_DEPTH]; -	size_t btsize; -	char **strings; -	BOOL success = FALSE; - -	std::string appfilename = gDirUtilp->getExecutablePathAndName(); - -	std::string strace_filename = gDirUtilp->getExpandedFilename(LL_PATH_LOGS,"stack_trace.log"); -	llinfos << "Opening stack trace file " << strace_filename << llendl; -	LLFILE* StraceFile = LLFile::fopen(strace_filename, "w");		// Flawfinder: ignore -        if (!StraceFile) -	{ -		llinfos << "Opening stack trace file " << strace_filename << " failed. Using stderr." << llendl; -		StraceFile = stderr; -	} - -	// get backtrace address list and basic symbol info -	btsize = backtrace(stackarray, MAX_STACK_TRACE_DEPTH); -	strings = backtrace_symbols(stackarray, btsize); - -	// create ELF reader for our app binary -	IELFI* pReader; -	const IELFISection* pSec = NULL; -	IELFISymbolTable* pSymTbl = 0; -	if (ERR_ELFIO_NO_ERROR != ELFIO::GetInstance()->CreateELFI(&pReader) || -	    ERR_ELFIO_NO_ERROR != pReader->Load(appfilename.c_str()) || -	    // find symbol table, create reader-object -	    NULL == (pSec = pReader->GetSection( ".symtab" )) || -	    ERR_ELFIO_NO_ERROR != pReader->CreateSectionReader(IELFI::ELFI_SYMBOL, pSec, (void**)&pSymTbl) ) -	{ -		// Failed to open our binary and read its symbol table somehow -		llinfos << "Could not initialize ELF symbol reading - doing basic backtrace." << llendl; -		if (StraceFile != stderr) -			fclose(StraceFile); -		// note that we may be leaking some of the above ELFIO -		// objects now, but it's expected that we'll be dead soon -		// and we want to tread delicately until we get *some* kind -		// of useful backtrace. -		return do_basic_glibc_backtrace(); -	} - -	// iterate over trace and symtab, looking for plausible symbols -	std::string   name; -	Elf32_Addr    value; -	Elf32_Word    ssize; -	unsigned char bind; -	unsigned char type; -	Elf32_Half    section; -	int nSymNo = pSymTbl->GetSymbolNum(); -	size_t btpos; -	for (btpos = 0; btpos < btsize; ++btpos) -	{ -		// the format of the StraceFile is very specific, to allow (kludgy) machine-parsing -		fprintf(StraceFile, "%-3ld ", (long)btpos); -		int symidx; -		for (symidx = 0; symidx < nSymNo; ++symidx) -		{ -			if (ERR_ELFIO_NO_ERROR == -			    pSymTbl->GetSymbol(symidx, name, value, ssize, -					       bind, type, section)) -			{ -				// check if trace address within symbol range -				if (uintptr_t(stackarray[btpos]) >= value && -				    uintptr_t(stackarray[btpos]) < value+ssize) -				{ -					// symbol is inside viewer -					fprintf(StraceFile, "%-32s\t", "com.secondlife.indra.viewer"); -					fprintf(StraceFile, "%p ", stackarray[btpos]); - -					char *demangled_str = NULL; -					int demangle_result = 1; -					demangled_str = -						abi::__cxa_demangle -						(name.c_str(), NULL, NULL, -						 &demangle_result); -					if (0 == demangle_result && -					    NULL != demangled_str) { -						fprintf(StraceFile, -							"%s", demangled_str); -						free(demangled_str); -					} -					else // failed demangle; print it raw -					{ -						fprintf(StraceFile, -							"%s", name.c_str()); -					} -					// print offset from symbol start -					fprintf(StraceFile, -						" + %lu\n", -						uintptr_t(stackarray[btpos]) - -						value); -					goto got_sym; // early escape -				} -			} -		} -		// Fallback: -		// Didn't find a suitable symbol in the binary - it's probably -		// a symbol in a DSO; use glibc's idea of what it should be. -		fprintf(StraceFile, "%-32s\t", "unknown"); -		fprintf(StraceFile, "%p ", stackarray[btpos]); -		fprintf(StraceFile, "%s\n", strings[btpos]); -	got_sym:; -	} -	 -	if (StraceFile != stderr) -		fclose(StraceFile); - -	pSymTbl->Release(); -	pSec->Release(); -	pReader->Release(); - -	free(strings); - -	llinfos << "Finished generating stack trace." << llendl; - -	success = TRUE; -	return success; -} -#endif // LL_ELFBIN - -#endif // LL_SOLARIS - -  LLAppViewerLinux::LLAppViewerLinux()  {  } @@ -541,16 +327,6 @@ bool LLAppViewerLinux::sendURLToOtherInstance(const std::string& url)  }  #endif // LL_DBUS_ENABLED -void LLAppViewerLinux::handleSyncCrashTrace() -{ -	// This backtrace writes into stack_trace.log -#  if LL_ELFBIN -	do_elfio_glibc_backtrace(); // more useful backtrace -#  else -	do_basic_glibc_backtrace(); // only slightly useful backtrace -#  endif // LL_ELFBIN -} -  void LLAppViewerLinux::handleCrashReporting(bool reportFreeze)  {  	std::string cmd =gDirUtilp->getExecutableDir(); @@ -686,6 +462,8 @@ bool LLAppViewerLinux::beingDebugged()  bool LLAppViewerLinux::initLogging()  {  	// Remove the last stack trace, if any +	// This file is no longer created, since the move to Google Breakpad +	// The code is left here to clean out any old state in the log dir  	std::string old_stack_file =  		gDirUtilp->getExpandedFilename(LL_PATH_LOGS,"stack_trace.log");  	LLFile::remove(old_stack_file); diff --git a/indra/newview/llappviewerlinux.h b/indra/newview/llappviewerlinux.h index 230c0dc24b..b17380d4d8 100644 --- a/indra/newview/llappviewerlinux.h +++ b/indra/newview/llappviewerlinux.h @@ -68,7 +68,6 @@ protected:  	virtual bool restoreErrorTrap();  	virtual void handleCrashReporting(bool reportFreeze); -	virtual void handleSyncCrashTrace();  	virtual bool initLogging();  	virtual bool initParseCommandLine(LLCommandLineParser& clp); diff --git a/indra/newview/llappviewermacosx.cpp b/indra/newview/llappviewermacosx.cpp index 0b5f18c330..1e66e55f3d 100644 --- a/indra/newview/llappviewermacosx.cpp +++ b/indra/newview/llappviewermacosx.cpp @@ -264,11 +264,6 @@ bool LLAppViewerMacOSX::restoreErrorTrap()  	return reset_count == 0;  } -void LLAppViewerMacOSX::handleSyncCrashTrace() -{ -	// do nothing -} -  static OSStatus CarbonEventHandler(EventHandlerCallRef inHandlerCallRef,   								   EventRef inEvent,   								   void* inUserData) @@ -384,38 +379,6 @@ void LLAppViewerMacOSX::handleCrashReporting(bool reportFreeze)  		}  	} - -	if(!reportFreeze) -	{ -		_exit(1); -	} -	 -	// TODO from palmer: Find a better way to handle managing old crash logs -	// when this is a separate imbedable module.  Ideally just sort crash stack -	// logs based on date, and grab the latest one as opposed to deleting them -	// for thoughts on what the module would look like. -	// See: https://wiki.lindenlab.com/wiki/Viewer_Crash_Reporter_Round_4 -	 -	// Remove the crash stack log from previous executions. -	// Since we've started logging a new instance of the app, we can assume  -	// The old crash stack is invalid for the next crash report. -	char path[MAX_PATH];		 -	FSRef folder; -	if(FSFindFolder(kUserDomain, kLogsFolderType, false, &folder) == noErr) -	{ -		// folder is an FSRef to ~/Library/Logs/ -		if(FSRefMakePath(&folder, (UInt8*)&path, sizeof(path)) == noErr) -		{ -			std::string pathname = std::string(path) + std::string("/CrashReporter/"); -			std::string mask = "Second Life*"; -			std::string file_name; -			while(gDirUtilp->getNextFileInDir(pathname, mask, file_name, false)) -			{ -				LLFile::remove(pathname + file_name); -			} -		} -	} -	  }  std::string LLAppViewerMacOSX::generateSerialNumber() diff --git a/indra/newview/llappviewermacosx.h b/indra/newview/llappviewermacosx.h index cbf7e6c209..3d7bb55556 100644 --- a/indra/newview/llappviewermacosx.h +++ b/indra/newview/llappviewermacosx.h @@ -55,7 +55,6 @@ public:  protected:  	virtual bool restoreErrorTrap();  	virtual void handleCrashReporting(bool reportFreeze);  -	virtual void handleSyncCrashTrace();  	std::string generateSerialNumber();  	virtual bool initParseCommandLine(LLCommandLineParser& clp); diff --git a/indra/newview/llappviewerwin32.cpp b/indra/newview/llappviewerwin32.cpp index 60a6d2f072..e3ef04d03d 100644 --- a/indra/newview/llappviewerwin32.cpp +++ b/indra/newview/llappviewerwin32.cpp @@ -57,8 +57,6 @@  #include "llweb.h"  #include "llsecondlifeurls.h" -#include "llwindebug.h" -  #include "llviewernetwork.h"  #include "llmd5.h"  #include "llfindlocale.h" @@ -81,51 +79,6 @@ extern "C" {  const std::string LLAppViewerWin32::sWindowClass = "Second Life"; -LONG WINAPI viewer_windows_exception_handler(struct _EXCEPTION_POINTERS *exception_infop) -{ -    // *NOTE:Mani - this code is stolen from LLApp, where its never actually used. -	//OSMessageBox("Attach Debugger Now", "Error", OSMB_OK); -    // *TODO: Translate the signals/exceptions into cross-platform stuff -	// Windows implementation -    _tprintf( _T("Entering Windows Exception Handler...\n") ); -	llinfos << "Entering Windows Exception Handler..." << llendl; - -	// Make sure the user sees something to indicate that the app crashed. -	LONG retval; - -	if (LLApp::isError()) -	{ -	    _tprintf( _T("Got another fatal signal while in the error handler, die now!\n") ); -		llwarns << "Got another fatal signal while in the error handler, die now!" << llendl; - -		retval = EXCEPTION_EXECUTE_HANDLER; -		return retval; -	} - -	// Generate a minidump if we can. -	// Before we wake the error thread... -	// Which will start the crash reporting. -	LLWinDebug::generateCrashStacks(exception_infop); -	 -	// Flag status to error, so thread_error starts its work -	LLApp::setError(); - -	// Block in the exception handler until the app has stopped -	// This is pretty sketchy, but appears to work just fine -	while (!LLApp::isStopped()) -	{ -		ms_sleep(10); -	} - -	// -	// At this point, we always want to exit the app.  There's no graceful -	// recovery for an unhandled exception. -	//  -	// Just kill the process. -	retval = EXCEPTION_EXECUTE_HANDLER;	 -	return retval; -} -  // Create app mutex creates a unique global windows object.   // If the object can be created it returns true, otherwise  // it returns false. The false result can be used to determine  @@ -191,8 +144,6 @@ int APIENTRY WINMAIN(HINSTANCE hInstance,  	gIconResource = MAKEINTRESOURCE(IDI_LL_ICON);  	LLAppViewerWin32* viewer_app_ptr = new LLAppViewerWin32(lpCmdLine); - -	LLWinDebug::initExceptionHandler(viewer_windows_exception_handler);   	viewer_app_ptr->setErrorHandler(LLAppViewer::handleViewerCrash); @@ -405,12 +356,6 @@ bool LLAppViewerWin32::cleanup()  bool LLAppViewerWin32::initLogging()  { -	// Remove the crash stack log from previous executions. -	// Since we've started logging a new instance of the app, we can assume  -	// *NOTE: This should happen before the we send a 'previous instance froze' -	// crash report, but it must happen after we initialize the DirUtil. -	LLWinDebug::clearCrashStacks(); -  	return LLAppViewer::initLogging();  } @@ -529,13 +474,9 @@ bool LLAppViewerWin32::initParseCommandLine(LLCommandLineParser& clp)  }  bool LLAppViewerWin32::restoreErrorTrap() -{ -	return LLWinDebug::checkExceptionHandler(); -} - -void LLAppViewerWin32::handleSyncCrashTrace() -{ -	// do nothing +{	 +	return true; +	//return LLWinDebug::checkExceptionHandler();  }  void LLAppViewerWin32::handleCrashReporting(bool reportFreeze) diff --git a/indra/newview/llappviewerwin32.h b/indra/newview/llappviewerwin32.h index 13454edeec..52dcc583a4 100644 --- a/indra/newview/llappviewerwin32.h +++ b/indra/newview/llappviewerwin32.h @@ -57,7 +57,6 @@ protected:  	virtual bool restoreErrorTrap();  	virtual void handleCrashReporting(bool reportFreeze);  -	virtual void handleSyncCrashTrace();  	virtual bool sendURLToOtherInstance(const std::string& url); diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp index e51e6363dd..35e86b75e7 100644 --- a/indra/newview/llstartup.cpp +++ b/indra/newview/llstartup.cpp @@ -199,7 +199,6 @@  #include "llstartuplistener.h"  #if LL_WINDOWS -#include "llwindebug.h"  #include "lldxhardware.h"  #endif diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp index 5836aff4e7..41aa80f40d 100644 --- a/indra/newview/llviewermessage.cpp +++ b/indra/newview/llviewermessage.cpp @@ -109,10 +109,6 @@  #include <boost/algorithm/string/split.hpp> //  #include <boost/regex.hpp> -#if LL_WINDOWS // For Windows specific error handler -#include "llwindebug.h"	// For the invalid message handler -#endif -  #include "llnotificationmanager.h" //  #if LL_MSVC diff --git a/indra/newview/llwindebug.cpp b/indra/newview/llwindebug.cpp deleted file mode 100644 index 59bc9dc62b..0000000000 --- a/indra/newview/llwindebug.cpp +++ /dev/null @@ -1,912 +0,0 @@ -/**  - * @file llwindebug.cpp - * @brief Windows debugging functions - * - * $LicenseInfo:firstyear=2004&license=viewergpl$ - *  - * Copyright (c) 2004-2009, Linden Research, Inc. - *  - * Second Life Viewer Source Code - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed by you and Linden Lab.  Terms of - * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 - *  - * There are special exceptions to the terms and conditions of the GPL as - * it is applied to this Source Code. View the full text of the exception - * in the file doc/FLOSS-exception.txt in this software distribution, or - * online at - * http://secondlifegrid.net/programs/open_source/licensing/flossexception - *  - * By copying, modifying or distributing this software, you acknowledge - * that you have read and understood your obligations described above, - * and agree to abide by those obligations. - *  - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. - * $/LicenseInfo$ - */ - -#include "llviewerprecompiledheaders.h" - -#include <tchar.h> -#include <tlhelp32.h> -#include "llwindebug.h" -#include "llviewercontrol.h" -#include "lldir.h" -#include "llsd.h" -#include "llsdserialize.h" - -#pragma warning(disable: 4200)	//nonstandard extension used : zero-sized array in struct/union -#pragma warning(disable: 4100)	//unreferenced formal parameter - - -/* -LLSD Block for Windows Dump Information -<llsd> -  <map> -    <key>Platform</key> -    <string></string> -    <key>Process</key> -    <string></string> -    <key>Module</key> -    <string></string> -    <key>DateModified</key> -    <string></string> -    <key>ExceptionCode</key> -    <string></string> -    <key>ExceptionRead/WriteAddress</key> -    <string></string> -    <key>Instruction</key> -    <string></string> -    <key>Registers</key> -    <map> -      <!-- Continued for all registers --> -      <key>EIP</key> -      <string>...</string> -      <!-- ... --> -    </map> -    <key>Call Stack</key> -    <array> -      <!-- One map per stack frame --> -      <map> -	<key>ModuleName</key> -	<string></string> -	<key>ModuleBaseAddress</key> -	<string></string> -	<key>ModuleOffsetAddress</key> -	<string></string> -	<key>Parameters</key> -	<array> -	  <string></string> -	</array> -      </map> -      <!-- ... --> -    </array> -  </map> -</llsd> - -*/ - - -extern void (*gCrashCallback)(void); - -// based on dbghelp.h -typedef BOOL (WINAPI *MINIDUMPWRITEDUMP)(HANDLE hProcess, DWORD dwPid, HANDLE hFile, MINIDUMP_TYPE DumpType, -									CONST PMINIDUMP_EXCEPTION_INFORMATION ExceptionParam, -									CONST PMINIDUMP_USER_STREAM_INFORMATION UserStreamParam, -									CONST PMINIDUMP_CALLBACK_INFORMATION CallbackParam -									); - -MINIDUMPWRITEDUMP f_mdwp = NULL; - -#undef UNICODE - -static LPTOP_LEVEL_EXCEPTION_FILTER gFilterFunc = NULL; - -HMODULE	hDbgHelp; - -// Tool Help functions. -typedef	HANDLE (WINAPI * CREATE_TOOL_HELP32_SNAPSHOT)(DWORD dwFlags, DWORD th32ProcessID); -typedef	BOOL (WINAPI * MODULE32_FIRST)(HANDLE hSnapshot, LPMODULEENTRY32 lpme); -typedef	BOOL (WINAPI * MODULE32_NEST)(HANDLE hSnapshot, LPMODULEENTRY32 lpme); - -CREATE_TOOL_HELP32_SNAPSHOT	CreateToolhelp32Snapshot_; -MODULE32_FIRST	Module32First_; -MODULE32_NEST	Module32Next_; - -#define	DUMP_SIZE_MAX	8000	//max size of our dump -#define	CALL_TRACE_MAX	((DUMP_SIZE_MAX - 2000) / (MAX_PATH + 40))	//max number of traced calls -#define	NL				L"\r\n"	//new line - - -typedef struct STACK -{ -	STACK *	Ebp; -	PBYTE	Ret_Addr; -	DWORD	Param[0]; -} STACK, * PSTACK; - -BOOL WINAPI Get_Module_By_Ret_Addr(PBYTE Ret_Addr, LPWSTR Module_Name, PBYTE & Module_Addr); -void WINAPI Get_Call_Stack(const EXCEPTION_RECORD* exception_record,  -						   const CONTEXT* context_record,  -						   LLSD& info); - -void printError( CHAR* msg ) -{ -  DWORD eNum; -  TCHAR sysMsg[256]; -  TCHAR* p; - -  eNum = GetLastError( ); -  FormatMessage( FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, -         NULL, eNum, -         MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language -         sysMsg, 256, NULL ); - -  // Trim the end of the line and terminate it with a null -  p = sysMsg; -  while( ( *p > 31 ) || ( *p == 9 ) ) -    ++p; -  do { *p-- = 0; } while( ( p >= sysMsg ) && -                          ( ( *p == '.' ) || ( *p < 33 ) ) ); - -  // Display the message -  printf( "\n  WARNING: %s failed with error %d (%s)", msg, eNum, sysMsg ); -} - -BOOL GetProcessThreadIDs(DWORD process_id, std::vector<DWORD>& thread_ids)  -{  -  HANDLE hThreadSnap = INVALID_HANDLE_VALUE;  -  THREADENTRY32 te32;  -  -  // Take a snapshot of all running threads   -  hThreadSnap = CreateToolhelp32Snapshot( TH32CS_SNAPTHREAD, 0 );  -  if( hThreadSnap == INVALID_HANDLE_VALUE )  -    return( FALSE );  -  -  // Fill in the size of the structure before using it.  -  te32.dwSize = sizeof(THREADENTRY32 );  -  -  // Retrieve information about the first thread, -  // and exit if unsuccessful -  if( !Thread32First( hThreadSnap, &te32 ) )  -  { -    printError( "Thread32First" );  // Show cause of failure -    CloseHandle( hThreadSnap );     // Must clean up the snapshot object! -    return( FALSE ); -  } - -  // Now walk the thread list of the system, -  // and display information about each thread -  // associated with the specified process -  do  -  {  -    if( te32.th32OwnerProcessID == process_id ) -    { -      thread_ids.push_back(te32.th32ThreadID);  -    } -  } while( Thread32Next(hThreadSnap, &te32 ) );  - -//  Don't forget to clean up the snapshot object. -  CloseHandle( hThreadSnap ); -  return( TRUE ); -} - -BOOL GetThreadCallStack(DWORD thread_id, LLSD& info) -{ -    if(GetCurrentThreadId() == thread_id) -    { -        // Early exit for the current thread. -        // Suspending the current thread would be a bad idea. -        // Plus you can't retrieve a valid current thread context. -        return false; -    } - -    HANDLE thread_handle = INVALID_HANDLE_VALUE;  -    thread_handle = OpenThread(THREAD_ALL_ACCESS, FALSE, thread_id); -    if(INVALID_HANDLE_VALUE == thread_handle) -    { -        return FALSE; -    } - -    BOOL result = false; -    if(-1 != SuspendThread(thread_handle)) -    { -        CONTEXT context_struct; -        context_struct.ContextFlags = CONTEXT_FULL; -        if(GetThreadContext(thread_handle, &context_struct)) -        { -            Get_Call_Stack(NULL, &context_struct, info); -            result = true; -        } -        ResumeThread(thread_handle); -    } -    else -    { -        // Couldn't suspend thread. -    } - -    CloseHandle(thread_handle); -    return result; -} - - -//Windows Call Stack Construction idea from  -//http://www.codeproject.com/tools/minidump.asp - -//**************************************************************************************** -BOOL WINAPI Get_Module_By_Ret_Addr(PBYTE Ret_Addr, LPWSTR Module_Name, PBYTE & Module_Addr) -//**************************************************************************************** -// Find module by Ret_Addr (address in the module). -// Return Module_Name (full path) and Module_Addr (start address). -// Return TRUE if found. -{ -	MODULEENTRY32	M = {sizeof(M)}; -	HANDLE	hSnapshot; - -	bool found = false; -	 -	if (CreateToolhelp32Snapshot_) -	{ -		hSnapshot = CreateToolhelp32Snapshot_(TH32CS_SNAPMODULE, 0); -		 -		if ((hSnapshot != INVALID_HANDLE_VALUE) && -			Module32First_(hSnapshot, &M)) -		{ -			do -			{ -				if (DWORD(Ret_Addr - M.modBaseAddr) < M.modBaseSize) -				{ -					lstrcpyn(Module_Name, M.szExePath, MAX_PATH); -					Module_Addr = M.modBaseAddr; -					found = true; -					break; -				} -			} while (Module32Next_(hSnapshot, &M)); -		} - -		CloseHandle(hSnapshot); -	} - -	return found; -} //Get_Module_By_Ret_Addr - -bool has_valid_call_before(PDWORD cur_stack_loc) -{ -	PBYTE p_first_byte = (PBYTE)(*cur_stack_loc - 1); -	PBYTE p_second_byte = (PBYTE)(*cur_stack_loc -2); -	PBYTE p_fifth_byte = (PBYTE)(*cur_stack_loc - 5); -	PBYTE p_sixth_byte = (PBYTE)(*cur_stack_loc - 6); - -	// make sure we can read it -	if(IsBadReadPtr(p_sixth_byte, 6 * sizeof(BYTE))) -	{ -		return false; -	} - -	// check for 9a + 4 bytes -	if(*p_fifth_byte == 0x9A) -	{ -		return true; -	} - -	// Check for E8 + 4 bytes and last byte is 00 or FF -	if(*p_fifth_byte == 0xE8 && (*p_first_byte == 0x00 || *p_first_byte == 0xFF)) -	{ -		return true; -	} -	 -	// the other is six bytes -	if(*p_sixth_byte == 0xFF || *p_second_byte == 0xFF) -	{ -		return true; -	} - -	return false; -} - -PBYTE get_valid_frame(PBYTE esp) -{ -	PDWORD cur_stack_loc = NULL; -	const int max_search = 400; -	WCHAR	module_name[MAX_PATH]; -	PBYTE	module_addr = 0; - -	// round to highest multiple of four -	esp = (esp + (4 - ((int)esp % 4)) % 4); - -	// scroll through stack a few hundred places. -	for (cur_stack_loc = (PDWORD) esp; cur_stack_loc < (PDWORD)esp + max_search; cur_stack_loc += 1) -	{ -		// if you can read the pointer, -		if (IsBadReadPtr(cur_stack_loc, sizeof(PDWORD))) -		{ -			continue; -		} - -		//  check if it's in a module -		if (!Get_Module_By_Ret_Addr((PBYTE)*cur_stack_loc, module_name, module_addr)) -		{ -			continue; -		} - -		// check if the code before the instruction ptr is a call  -		if(!has_valid_call_before(cur_stack_loc)) -		{ -			continue; -		} -		 -		// if these all pass, return that ebp, otherwise continue till we're dead -		return (PBYTE)(cur_stack_loc - 1); -	} - -	return NULL; -} - -bool shouldUseStackWalker(PSTACK Ebp, int max_depth) -{ -	WCHAR	Module_Name[MAX_PATH]; -	PBYTE	Module_Addr = 0; -	int depth = 0; - -	while (depth < max_depth)  -	{ -		if (IsBadReadPtr(Ebp, sizeof(PSTACK)) ||  -			IsBadReadPtr(Ebp->Ebp, sizeof(PSTACK)) || -			Ebp->Ebp < Ebp || -			Ebp->Ebp - Ebp > 0xFFFFFF || -			IsBadCodePtr(FARPROC(Ebp->Ebp->Ret_Addr)) || -			!Get_Module_By_Ret_Addr(Ebp->Ebp->Ret_Addr, Module_Name, Module_Addr)) -		{ -			return true; -		} -		depth++; -		Ebp = Ebp->Ebp; -	} - -	return false; -} - -//****************************************************************** -void WINAPI Get_Call_Stack(const EXCEPTION_RECORD* exception_record,  -						   const CONTEXT* context_record,  -						   LLSD& info) -//****************************************************************** -// Fill Str with call stack info. -// pException can be either GetExceptionInformation() or NULL. -// If pException = NULL - get current call stack. -{ -	LPWSTR	Module_Name = new WCHAR[MAX_PATH]; -	PBYTE	Module_Addr = 0; -	LLSD params; -	PBYTE	Esp = NULL; -	LLSD tmp_info; - -	bool fake_frame = false; -	bool ebp_used = false; -	const int HEURISTIC_MAX_WALK = 20; -	int heuristic_walk_i = 0; -	int Ret_Addr_I = 0; - -	STACK	Stack = {0, 0}; -	PSTACK	Ebp; - -	if (exception_record && context_record)		//fake frame for exception address -	{ -		Stack.Ebp = (PSTACK)(context_record->Ebp); -		Stack.Ret_Addr = (PBYTE)exception_record->ExceptionAddress; -		Ebp = &Stack; -		Esp = (PBYTE) context_record->Esp; -		fake_frame = true; -	} -	else if(context_record) -	{ -        Ebp = (PSTACK)(context_record->Ebp); -		Esp = (PBYTE)(context_record->Esp); -	} -	else -	{ -		Ebp = (PSTACK)&exception_record - 1;	//frame addr of Get_Call_Stack() -		Esp = (PBYTE)&exception_record; - -		// Skip frame of Get_Call_Stack(). -		if (!IsBadReadPtr(Ebp, sizeof(PSTACK))) -			Ebp = Ebp->Ebp;		//caller ebp -	} - -	// Trace CALL_TRACE_MAX calls maximum - not to exceed DUMP_SIZE_MAX. -	// Break trace on wrong stack frame. -	for (Ret_Addr_I = 0; -		heuristic_walk_i < HEURISTIC_MAX_WALK &&  -		Ret_Addr_I < CALL_TRACE_MAX && !IsBadReadPtr(Ebp, sizeof(PSTACK)) && !IsBadCodePtr(FARPROC(Ebp->Ret_Addr)); -		Ret_Addr_I++) -	{ -		// If module with Ebp->Ret_Addr found. -		if (Get_Module_By_Ret_Addr(Ebp->Ret_Addr, Module_Name, Module_Addr)) -		{ -			// Save module's address and full path. -			tmp_info["CallStack"][Ret_Addr_I]["ModuleName"] = ll_convert_wide_to_string(Module_Name); -			tmp_info["CallStack"][Ret_Addr_I]["ModuleAddress"] = (int)Module_Addr; -			tmp_info["CallStack"][Ret_Addr_I]["CallOffset"] = (int)(Ebp->Ret_Addr - Module_Addr); - -			// Save 5 params of the call. We don't know the real number of params. -			if (fake_frame && !Ret_Addr_I)	//fake frame for exception address -				params[0] = "Exception Offset"; -			else if (!IsBadReadPtr(Ebp, sizeof(PSTACK) + 5 * sizeof(DWORD))) -			{ -				for(int j = 0; j < 5; ++j) -				{ -					params[j] = (int)Ebp->Param[j]; -				} -			} -			tmp_info["CallStack"][Ret_Addr_I]["Parameters"] = params; -		} - -		tmp_info["CallStack"][Ret_Addr_I]["ReturnAddress"] = (int)Ebp->Ret_Addr; - -		// get ready for next frame -		// Set ESP to just after return address.  Not the real esp, but just enough after the return address -		if(!fake_frame) { -			Esp = (PBYTE)Ebp + 8; -		}  -		else -		{ -			fake_frame = false; -		} - -		// is next ebp valid? -		// only run if we've never found a good ebp -		// and make sure the one after is valid as well -		if(	!ebp_used &&  -			shouldUseStackWalker(Ebp, 2)) -		{ -			heuristic_walk_i++; -			PBYTE new_ebp = get_valid_frame(Esp); -			if (new_ebp != NULL) -			{ -				Ebp = (PSTACK)new_ebp; -			} -		} -		else -		{ -			ebp_used = true; -			Ebp = Ebp->Ebp; -		} -	} -/* TODO remove or turn this code back on to edit the stack after i see a few raw ones. -Palmer -	// Now go back through and edit out heuristic stacks that could very well be bogus. -	// Leave the top and the last 3 stack chosen by the heuristic, however. -	if(heuristic_walk_i > 2) -	{ -		info["CallStack"][0] = tmp_info["CallStack"][0]; -		std::string ttest = info["CallStack"][0]["ModuleName"]; -		for(int cur_frame = 1;  -			(cur_frame + heuristic_walk_i - 2 < Ret_Addr_I);  -			++cur_frame) -		{ -			// edit out the middle heuristic found frames -			info["CallStack"][cur_frame] = tmp_info["CallStack"][cur_frame + heuristic_walk_i - 2]; -		} -	} -	else -	{ -		info = tmp_info; -	} -*/ -	info = tmp_info; -	info["HeuristicWalkI"] = heuristic_walk_i; -	info["EbpUsed"] = ebp_used; - -} //Get_Call_Stack - -//*********************************** -void WINAPI Get_Version_Str(LLSD& info) -//*********************************** -// Fill Str with Windows version. -{ -	OSVERSIONINFOEX	V = {sizeof(OSVERSIONINFOEX)};	//EX for NT 5.0 and later - -	if (!GetVersionEx((POSVERSIONINFO)&V)) -	{ -		ZeroMemory(&V, sizeof(V)); -		V.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); -		GetVersionEx((POSVERSIONINFO)&V); -	} - -	if (V.dwPlatformId != VER_PLATFORM_WIN32_NT) -		V.dwBuildNumber = LOWORD(V.dwBuildNumber);	//for 9x HIWORD(dwBuildNumber) = 0x04xx - -	info["Platform"] = llformat("Windows:  %d.%d.%d, SP %d.%d, Product Type %d",	//SP - service pack, Product Type - VER_NT_WORKSTATION,... -		V.dwMajorVersion, V.dwMinorVersion, V.dwBuildNumber, V.wServicePackMajor, V.wServicePackMinor, V.wProductType); -} //Get_Version_Str - -//************************************************************* -LLSD WINAPI Get_Exception_Info(PEXCEPTION_POINTERS pException) -//************************************************************* -// Allocate Str[DUMP_SIZE_MAX] and return Str with dump, if !pException - just return call stack in Str. -{ -	LLSD info; -	LPWSTR		Str; -	int			Str_Len; -//	int			i; -	LPWSTR		Module_Name = new WCHAR[MAX_PATH]; -	PBYTE		Module_Addr; -	HANDLE		hFile; -	FILETIME	Last_Write_Time; -	FILETIME	Local_File_Time; -	SYSTEMTIME	T; - -	Str = new WCHAR[DUMP_SIZE_MAX]; -	Str_Len = 0; -	if (!Str) -		return NULL; -	 -	Get_Version_Str(info); -	 -	GetModuleFileName(NULL, Str, MAX_PATH); -	info["Process"] = ll_convert_wide_to_string(Str); -	info["ThreadID"] = (S32)GetCurrentThreadId(); - -	// If exception occurred. -	if (pException) -	{ -		EXCEPTION_RECORD &	E = *pException->ExceptionRecord; -		CONTEXT &			C = *pException->ContextRecord; - -		// If module with E.ExceptionAddress found - save its path and date. -		if (Get_Module_By_Ret_Addr((PBYTE)E.ExceptionAddress, Module_Name, Module_Addr)) -		{ -			info["Module"] = ll_convert_wide_to_string(Module_Name); - -			if ((hFile = CreateFile(Module_Name, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, -				FILE_ATTRIBUTE_NORMAL, NULL)) != INVALID_HANDLE_VALUE) -			{ -				if (GetFileTime(hFile, NULL, NULL, &Last_Write_Time)) -				{ -					FileTimeToLocalFileTime(&Last_Write_Time, &Local_File_Time); -					FileTimeToSystemTime(&Local_File_Time, &T); - -					info["DateModified"] = llformat("%02d/%02d/%d", T.wMonth, T.wDay, T.wYear); -				} -				CloseHandle(hFile); -			} -		} -		else -		{ -			info["ExceptionAddr"] = (int)E.ExceptionAddress; -		} -		 -		info["ExceptionCode"] = (int)E.ExceptionCode; -		 -		/* -		//TODO: Fix this -		if (E.ExceptionCode == EXCEPTION_ACCESS_VIOLATION) -		{ -			// Access violation type - Write/Read. -			LLSD exception_info; -			exception_info["Type"] = E.ExceptionInformation[0] ? "Write" : "Read"; -			exception_info["Address"] = llformat("%08x", E.ExceptionInformation[1]); -			info["Exception Information"] = exception_info; -		} -		*/ - -		 -		// Save instruction that caused exception. -		/* -		std::string str; -		for (i = 0; i < 16; i++) -			str += llformat(" %02X", PBYTE(E.ExceptionAddress)[i]); -		info["Instruction"] = str; -		*/ -		LLSD registers; -		registers["EAX"] = (int)C.Eax; -		registers["EBX"] = (int)C.Ebx; -		registers["ECX"] = (int)C.Ecx; -		registers["EDX"] = (int)C.Edx; -		registers["ESI"] = (int)C.Esi; -		registers["EDI"] = (int)C.Edi; -		registers["ESP"] = (int)C.Esp; -		registers["EBP"] = (int)C.Ebp; -		registers["EIP"] = (int)C.Eip; -		registers["EFlags"] = (int)C.EFlags; -		info["Registers"] = registers; -	} //if (pException) -	 -	// Save call stack info. -	Get_Call_Stack(pException->ExceptionRecord, pException->ContextRecord, info); - -	return info; -} //Get_Exception_Info - -#define UNICODE - - -class LLMemoryReserve { -public: -	LLMemoryReserve(); -	~LLMemoryReserve(); -	void reserve(); -	void release(); -protected: -	unsigned char *mReserve; -	static const size_t MEMORY_RESERVATION_SIZE; -}; - -LLMemoryReserve::LLMemoryReserve() : -	mReserve(NULL) -{ -}; - -LLMemoryReserve::~LLMemoryReserve() -{ -	release(); -} - -// I dunno - this just seemed like a pretty good value. -const size_t LLMemoryReserve::MEMORY_RESERVATION_SIZE = 5 * 1024 * 1024; - -void LLMemoryReserve::reserve() -{ -	if(NULL == mReserve) -		mReserve = new unsigned char[MEMORY_RESERVATION_SIZE]; -}; - -void LLMemoryReserve::release() -{ -	delete [] mReserve; -	mReserve = NULL; -}; - -static LLMemoryReserve gEmergencyMemoryReserve; - -#ifndef _M_IX86 -	#error "The following code only works for x86!" -#endif -LPTOP_LEVEL_EXCEPTION_FILTER WINAPI MyDummySetUnhandledExceptionFilter( -	LPTOP_LEVEL_EXCEPTION_FILTER lpTopLevelExceptionFilter) -{ -	if(lpTopLevelExceptionFilter ==  gFilterFunc) -		return gFilterFunc; - -	llinfos << "Someone tried to set the exception filter. Listing call stack modules" << llendl; -	LLSD cs_info; -	Get_Call_Stack(NULL, NULL, cs_info); -	 -	if(cs_info.has("CallStack") && cs_info["CallStack"].isArray()) -	{ -		LLSD cs = cs_info["CallStack"]; -		for(LLSD::array_iterator i = cs.beginArray();  -			i != cs.endArray();  -			++i) -		{ -			llinfos << "Module: " << (*i)["ModuleName"] << llendl; -		} -	} -	 -	return gFilterFunc; -} - -BOOL PreventSetUnhandledExceptionFilter() -{ -	HMODULE hKernel32 = LoadLibrary(_T("kernel32.dll")); -	if (hKernel32 == NULL)  -		return FALSE; - -	void *pOrgEntry = GetProcAddress(hKernel32, "SetUnhandledExceptionFilter"); -	if(pOrgEntry == NULL)  -		return FALSE; -	 -	unsigned char newJump[ 100 ]; -	DWORD dwOrgEntryAddr = (DWORD)pOrgEntry; -	dwOrgEntryAddr += 5; // add 5 for 5 op-codes for jmp far -	void *pNewFunc = &MyDummySetUnhandledExceptionFilter; -	DWORD dwNewEntryAddr = (DWORD) pNewFunc; -	DWORD dwRelativeAddr = dwNewEntryAddr - dwOrgEntryAddr; - -	newJump[ 0 ] = 0xE9;  // JMP absolute -	memcpy(&newJump[ 1 ], &dwRelativeAddr, sizeof(pNewFunc)); -	SIZE_T bytesWritten; -	BOOL bRet = WriteProcessMemory(GetCurrentProcess(), -	pOrgEntry, newJump, sizeof(pNewFunc) + 1, &bytesWritten); -	return bRet; -} - -// static -void  LLWinDebug::initExceptionHandler(LPTOP_LEVEL_EXCEPTION_FILTER filter_func) -{ - -	static bool s_first_run = true; -	// Load the dbghelp dll now, instead of waiting for the crash. -	// Less potential for stack mangling - -	if (s_first_run) -	{ -		// First, try loading from the directory that the app resides in. -		std::string local_dll_name = gDirUtilp->findFile("dbghelp.dll", gDirUtilp->getWorkingDir(), gDirUtilp->getExecutableDir()); - -		HMODULE hDll = NULL; -		hDll = LoadLibraryA(local_dll_name.c_str()); -		if (!hDll) -		{ -			hDll = LoadLibrary(L"dbghelp.dll"); -		} - -		if (!hDll) -		{ -			LL_WARNS("AppInit") << "Couldn't find dbghelp.dll!" << LL_ENDL; -		} -		else -		{ -			f_mdwp = (MINIDUMPWRITEDUMP) GetProcAddress(hDll, "MiniDumpWriteDump"); - -			if (!f_mdwp) -			{ -				FreeLibrary(hDll); -				hDll = NULL; -			} -		} - -		gEmergencyMemoryReserve.reserve(); - -		s_first_run = false; -	} - -	// Try to get Tool Help library functions. -	HMODULE hKernel32; -	hKernel32 = GetModuleHandle(_T("KERNEL32")); -	CreateToolhelp32Snapshot_ = (CREATE_TOOL_HELP32_SNAPSHOT)GetProcAddress(hKernel32, "CreateToolhelp32Snapshot"); -	Module32First_ = (MODULE32_FIRST)GetProcAddress(hKernel32, "Module32FirstW"); -	Module32Next_ = (MODULE32_NEST)GetProcAddress(hKernel32, "Module32NextW"); - -    LPTOP_LEVEL_EXCEPTION_FILTER prev_filter; -	prev_filter = SetUnhandledExceptionFilter(filter_func); - -	// *REMOVE:Mani -	//PreventSetUnhandledExceptionFilter(); - -	if(prev_filter != gFilterFunc) -	{ -		LL_WARNS("AppInit")  -			<< "Replacing unknown exception (" << (void *)prev_filter << ") with (" << (void *)filter_func << ") !" << LL_ENDL; -	} -	 -	gFilterFunc = filter_func; -} - -bool LLWinDebug::checkExceptionHandler() -{ -	bool ok = true; -	LPTOP_LEVEL_EXCEPTION_FILTER prev_filter; -	prev_filter = SetUnhandledExceptionFilter(gFilterFunc); - -	if (prev_filter != gFilterFunc) -	{ -		LL_WARNS("AppInit") << "Our exception handler (" << (void *)gFilterFunc << ") replaced with " << prev_filter << "!" << LL_ENDL; -		ok = false; -	} - -	if (prev_filter == NULL) -	{ -		ok = FALSE; -		if (gFilterFunc == NULL) -		{ -			LL_WARNS("AppInit") << "Exception handler uninitialized." << LL_ENDL; -		} -		else -		{ -			LL_WARNS("AppInit") << "Our exception handler (" << (void *)gFilterFunc << ") replaced with NULL!" << LL_ENDL; -		} -	} - -	return ok; -} - -void LLWinDebug::writeDumpToFile(MINIDUMP_TYPE type, MINIDUMP_EXCEPTION_INFORMATION *ExInfop, const std::string& filename) -{ -	if(f_mdwp == NULL || gDirUtilp == NULL)  -	{ -		return; -		//write_debug("No way to generate a minidump, no MiniDumpWriteDump function!\n"); -	} -	else -	{ -		std::string dump_path = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, filename); - -		HANDLE hFile = CreateFileA(dump_path.c_str(), -									GENERIC_WRITE, -									FILE_SHARE_WRITE, -									NULL, -									CREATE_ALWAYS, -									FILE_ATTRIBUTE_NORMAL, -									NULL); - -		if (hFile != INVALID_HANDLE_VALUE) -		{ -			// Write the dump, ignoring the return value -			f_mdwp(GetCurrentProcess(), -					GetCurrentProcessId(), -					hFile, -					type, -					ExInfop, -					NULL, -					NULL); - -			CloseHandle(hFile); -		} - -	} -} - -// static -void LLWinDebug::generateCrashStacks(struct _EXCEPTION_POINTERS *exception_infop) -{ -	// *NOTE:Mani - This method is no longer the exception handler. -	// Its called from viewer_windows_exception_handler() and other places. - -	//  -	// Let go of a bunch of reserved memory to give library calls etc -	// a chance to execute normally in the case that we ran out of -	// memory. -	// -	LLSD info; -	std::string dump_path = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, -												"SecondLifeException"); -	std::string log_path = dump_path + ".log"; - -	if (exception_infop) -	{ -		// Since there is exception info... Release the hounds. -		gEmergencyMemoryReserve.release(); - -		if(gSavedSettings.getControl("SaveMinidump").notNull() && gSavedSettings.getBOOL("SaveMinidump")) -		{ -			_MINIDUMP_EXCEPTION_INFORMATION ExInfo; - -			ExInfo.ThreadId = ::GetCurrentThreadId(); -			ExInfo.ExceptionPointers = exception_infop; -			ExInfo.ClientPointers = NULL; - -			writeDumpToFile(MiniDumpNormal, &ExInfo, "SecondLife.dmp"); -			writeDumpToFile((MINIDUMP_TYPE)(MiniDumpWithDataSegs | MiniDumpWithIndirectlyReferencedMemory), &ExInfo, "SecondLifePlus.dmp"); -		} - -		info = Get_Exception_Info(exception_infop); -	} - -	LLSD threads; -    std::vector<DWORD> thread_ids; -    GetProcessThreadIDs(GetCurrentProcessId(), thread_ids); - -    for(std::vector<DWORD>::iterator th_itr = thread_ids.begin();  -                th_itr != thread_ids.end(); -                ++th_itr) -    { -        LLSD thread_info; -        if(*th_itr != GetCurrentThreadId()) -        { -            GetThreadCallStack(*th_itr, thread_info); -        } - -        if(thread_info) -        { -            threads[llformat("ID %d", *th_itr)] = thread_info; -        } -    } - -    info["Threads"] = threads; - -	llofstream out_file(log_path); -	LLSDSerialize::toPrettyXML(info, out_file); -	out_file.close(); -} - -void LLWinDebug::clearCrashStacks() -{ -	LLSD info; -	std::string dump_path = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "SecondLifeException.log"); -	LLFile::remove(dump_path); -} diff --git a/indra/newview/llwindebug.h b/indra/newview/llwindebug.h deleted file mode 100644 index f4a6a2d54d..0000000000 --- a/indra/newview/llwindebug.h +++ /dev/null @@ -1,75 +0,0 @@ -/**  - * @file llwindebug.h - * @brief LLWinDebug class header file - * - * $LicenseInfo:firstyear=2004&license=viewergpl$ - *  - * Copyright (c) 2004-2009, Linden Research, Inc. - *  - * Second Life Viewer Source Code - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed by you and Linden Lab.  Terms of - * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 - *  - * There are special exceptions to the terms and conditions of the GPL as - * it is applied to this Source Code. View the full text of the exception - * in the file doc/FLOSS-exception.txt in this software distribution, or - * online at - * http://secondlifegrid.net/programs/open_source/licensing/flossexception - *  - * By copying, modifying or distributing this software, you acknowledge - * that you have read and understood your obligations described above, - * and agree to abide by those obligations. - *  - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. - * $/LicenseInfo$ - */ - -#ifndef LL_LLWINDEBUG_H -#define LL_LLWINDEBUG_H - -#include "stdtypes.h" -#include <dbghelp.h> - -class LLWinDebug -{ -public: - -	/**  -	* @brief initialize the llwindebug exception filter callback -	*  -	* Hand a windows unhandled exception filter to LLWinDebug -	* This method should only be called to change the -	* exception filter used by llwindebug. -	* -	* Setting filter_func to NULL will clear any custom filters. -	**/ -	static void initExceptionHandler(LPTOP_LEVEL_EXCEPTION_FILTER filter_func); - -	/**  -	* @brief check the status of the exception filter. -	* -	* Resets unhandled exception filter to the filter specified  -	* w/ initExceptionFilter).  -	* Returns false if the exception filter was modified. -	* -	* *NOTE:Mani In the past mozlib has been accused of -	* overriding the exception filter. If the mozlib filter  -	* is required, perhaps we can chain calls from our  -	* filter to mozlib's. -	**/ -	static bool checkExceptionHandler(); - -	static void generateCrashStacks(struct _EXCEPTION_POINTERS *pExceptionInfo = NULL); -	static void clearCrashStacks(); // Delete the crash stack file(s). - -	static void writeDumpToFile(MINIDUMP_TYPE type, MINIDUMP_EXCEPTION_INFORMATION *ExInfop, const std::string& filename); -private: -}; - -#endif // LL_LLWINDEBUG_H diff --git a/indra/newview/viewer_manifest.py b/indra/newview/viewer_manifest.py index 8c089c0b79..8d2525dd26 100755 --- a/indra/newview/viewer_manifest.py +++ b/indra/newview/viewer_manifest.py @@ -41,9 +41,12 @@ from llmanifest import LLManifest, main, proper_windows_path, path_ancestors  class ViewerManifest(LLManifest):      def is_packaging_viewer(self): -        # This is overridden by the WindowsManifest sub-class, -        # which has different behavior if it is not packaging the viewer. -        return True +        # Some commands, files will only be included +        # if we are packaging the viewer on windows. +        # This manifest is also used to copy +        # files during the build (see copy_w_viewer_manifest +        # and copy_l_viewer_manifest targets) +        return 'package' in self.args['actions']      def construct(self):          super(ViewerManifest, self).construct() @@ -175,13 +178,6 @@ class WindowsManifest(ViewerManifest):          else:              return ''.join(self.channel().split()) + '.exe' -    def is_packaging_viewer(self): -        # Some commands, files will only be included -        # if we are packaging the viewer on windows. -        # This manifest is also used to copy -        # files during the build. -        return 'package' in self.args['actions'] -      def test_msvcrt_and_copy_action(self, src, dst):          # This is used to test a dll manifest.          # It is used as a temporary override during the construct method @@ -641,7 +637,9 @@ class DarwinManifest(ViewerManifest):                  if dylibs["llcommon"]:                      for libfile in ("libapr-1.0.3.7.dylib",                                      "libaprutil-1.0.3.8.dylib", -                                    "libexpat.0.5.0.dylib"): +                                    "libexpat.0.5.0.dylib", +                                    "libexception_handler.dylib", +                                    ):                          self.path(os.path.join(libdir, libfile), libfile)                  #libfmodwrapper.dylib @@ -662,7 +660,9 @@ class DarwinManifest(ViewerManifest):                      for libfile in ("libllcommon.dylib",                                      "libapr-1.0.3.7.dylib",                                      "libaprutil-1.0.3.8.dylib", -                                    "libexpat.0.5.0.dylib"): +                                    "libexpat.0.5.0.dylib", +                                    "libexception_handler.dylib", +                                    ):                          target_lib = os.path.join('../../..', libfile)                          self.run_command("ln -sf %(target)r %(link)r" %                                            {'target': target_lib, @@ -893,6 +893,7 @@ class Linux_i686Manifest(LinuxManifest):          if self.prefix("../../libraries/i686-linux/lib_release_client", dst="lib"):              self.path("libapr-1.so.0")              self.path("libaprutil-1.so.0") +            self.path("libbreakpad_client.so.0.0.0", "libbreakpad_client.so.0")              self.path("libdb-4.2.so")              self.path("libcrypto.so.0.9.7")              self.path("libexpat.so.1") @@ -930,7 +931,7 @@ class Linux_i686Manifest(LinuxManifest):                      self.path("libvivoxplatform.so")                      self.end_prefix("lib") -        if self.args['buildtype'].lower() == 'release': +        if self.args['buildtype'].lower() == 'release' and self.is_packaging_viewer():              print "* Going strip-crazy on the packaged binaries, since this is a RELEASE build"              self.run_command("find %(d)r/bin %(d)r/lib -type f | xargs --no-run-if-empty strip -S" % {'d': self.get_dst_prefix()} ) # makes some small assumptions about our packaged dir structure | 
