⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 muledebug.cpp

📁 电驴的MAC源代码
💻 CPP
字号:
//// This file is part of the aMule Project.//// Copyright (C) 2005-2008 Mikkel Schubert ( xaignar@users.sourceforge.net )// Copyright (C) 2005-2008 aMule Team ( admin@amule.org / http://www.amule.org )//// Any parts of this program derived from the xMule, lMule or eMule project,// or contributed by third-party developers are copyrighted by their// respective authors.//// This program is free software; you can redistribute it and/or modify// it under the terms of the GNU General Public License as published by// the Free Software Foundation; either version 2 of the License, or// (at your option) any later version.//// This program is distributed in the hope that it will be useful,// but WITHOUT ANY WARRANTY; without even the implied warranty of// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the// GNU General Public License for more details.//// You should have received a copy of the GNU General Public License// along with this program; if not, write to the Free Software// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301, USA//#include <cstdlib>			// Needed for std::abort()#ifdef HAVE_CONFIG_H#	include "config.h"		// Needed for HAVE_CXXABI and HAVE_EXECINFO#endif#include "MuleDebug.h"			// Interface declaration#include "StringFunctions.h"		// Needed for unicode2char#ifdef HAVE_EXECINFO#	include <execinfo.h>#endif#ifdef HAVE_CXXABI#	include <cxxabi.h>#endif#include <wx/thread.h> // Do_not_auto_remove (Old wx < 2.7)#include <wx/utils.h> // Do_not_auto_remove (Old wx < 2.7)#if wxUSE_STACKWALKER && defined(__WXMSW__)	#include <wx/stackwalk.h> // Do_not_auto_remove#elif defined(HAVE_BFD)	#include <ansidecl.h> // Do_not_auto_remove	#include <bfd.h> // Do_not_auto_remove#endif#include <vector>/** * This functions displays a verbose description of  * any unhandled exceptions that occour and then * terminate the program by raising SIGABRT. */void OnUnhandledException(){	// Revert to the original exception handler, to avoid	// infinate recursion, in case something goes wrong in	// this function.	std::set_terminate(std::abort);	#ifdef HAVE_CXXABI	std::type_info *t = __cxxabiv1::__cxa_current_exception_type();	FILE* output = stderr;#else 	FILE* output = stdout;	bool t = true;#endif	if (t) {		int status = -1;		char *dem = 0;#ifdef HAVE_CXXABI		// Note that "name" is the mangled name.		char const *name = t->name();		dem = __cxxabiv1::__cxa_demangle(name, 0, 0, &status);#else		const char* name = "Unknown";#endif		fprintf(output, "\nTerminated after throwing an instance of '%s'\n", (status ? name : dem));		free(dem);		try {			throw;		} catch (const std::exception& e) {			fprintf(output, "\twhat(): %s\n", e.what());		} catch (const CMuleException& e) {			fprintf(output, "\twhat(): %s\n", (const char*)unicode2char(e.what()));		} catch (const wxString& e) {			fprintf(output, "\twhat(): %s\n", (const char*)unicode2char(e));		} catch (...) {			// Unable to retrieve cause of exception		}		fprintf(output, "\tbacktrace:\n%s\n", (const char*)unicode2char(get_backtrace(1)));	}	std::abort();}void InstallMuleExceptionHandler(){	std::set_terminate(OnUnhandledException);}// Make it 1 for getting the file path also#define TOO_VERBOSE_BACKTRACE 0 #if wxUSE_STACKWALKER && defined(__WXMSW__)// Derived class to define the actions to be done on frame print.// I was tempted to name it MuleSkyWalkerclass MuleStackWalker : public wxStackWalker{public:	MuleStackWalker() {};	~MuleStackWalker() {};	void OnStackFrame(const wxStackFrame& frame)	{		wxString btLine = wxString::Format(wxT("[%u] "), frame.GetLevel());		wxString filename = frame.GetName();		if (!filename.IsEmpty()) {			btLine += filename + wxT(" (") +#if TOO_VERBOSE_BACKTRACE			        frame.GetModule()#else				frame.GetModule().AfterLast(wxT('/'))#endif			        + wxT(")");		} else {			btLine += wxString::Format(wxT("0x%lx"), frame.GetAddress());		}		if (frame.HasSourceLocation()) {			btLine += wxT(" at ") +#if TOO_VERBOSE_BACKTRACE			        frame.GetFileName()#else				frame.GetFileName().AfterLast(wxT('/'))#endif			        + wxString::Format(wxT(":%u"),frame.GetLine());		} else {			btLine += wxT(" (Unknown file/line)");		}		//! Contains the entire backtrace		m_trace += btLine + wxT("\n");	}	wxString m_trace;};wxString get_backtrace(unsigned n){	MuleStackWalker walker; // Texas ranger?	walker.Walk(n); // Skip this one and Walk() also!	return walker.m_trace;}#elif defined(__LINUX__)#ifdef HAVE_BFDstatic bfd* s_abfd;static asymbol** s_symbol_list;static bool s_have_backtrace_symbols = false;static const char* s_file_name;static const char* s_function_name;static unsigned int s_line_number;static int s_found;/** read all symbols in the executable into an array* and return the pointer to the array in symbol_list.* Also return the number of actual symbols read* If there's any error, return -1*/static int get_backtrace_symbols(bfd *abfd, asymbol ***symbol_list_ptr){	int vectorsize = bfd_get_symtab_upper_bound(abfd);	if (vectorsize < 0) {		fprintf (stderr, "Error while getting vector size for backtrace symbols : %s",			bfd_errmsg(bfd_get_error()));		return -1;	}	if (vectorsize == 0) {		fprintf (stderr, "Error while getting backtrace symbols : No symbols (%s)",			bfd_errmsg(bfd_get_error()));		return -1;	}	*symbol_list_ptr = (asymbol**)malloc(vectorsize);	if (*symbol_list_ptr == NULL) {		fprintf (stderr, "Error while getting backtrace symbols : Cannot allocate memory");		return -1;	}	vectorsize = bfd_canonicalize_symtab(abfd, *symbol_list_ptr);	if (vectorsize < 0) {		fprintf(stderr, "Error while getting symbol table : %s",			bfd_errmsg(bfd_get_error()));		return -1;	}	return vectorsize;}/** print file, line and function information for address* The info is actually set into global variables. This* function is called from the iterator bfd_map_over_sections**/void init_backtrace_info(){	bfd_init();	s_abfd = bfd_openr("/proc/self/exe", NULL);	if (s_abfd == NULL) {		fprintf(stderr, "Error while opening file for backtrace symbols : %s",			bfd_errmsg(bfd_get_error()));		return;	}	if (!(bfd_check_format_matches(s_abfd, bfd_object, NULL))) {		fprintf (stderr, "Error while init. backtrace symbols : %s",			bfd_errmsg (bfd_get_error ()));		bfd_close(s_abfd);		return;	}	s_have_backtrace_symbols = (get_backtrace_symbols(s_abfd, &s_symbol_list) > 0); }void get_file_line_info(bfd *abfd, asection *section, void* _address){	wxASSERT(s_symbol_list);	if (s_found) {		return;	}	if ((section->flags & SEC_ALLOC) == 0) {		return;	}	bfd_vma vma = bfd_get_section_vma(abfd, section);	unsigned long address = (unsigned long)_address;	if (address < vma) {		return;	}	bfd_size_type size = bfd_section_size(abfd, section);	if (address > (vma + size)) {		return;	}	s_found =  bfd_find_nearest_line(abfd, section, s_symbol_list,		address - vma, &s_file_name, &s_function_name, &s_line_number);}#endif // HAVE_BFDwxString demangle(const wxString& function){#ifdef HAVE_CXXABI	wxString result;		if (function.Mid(0,2) == wxT("_Z")) {		int status;		char *demangled = abi::__cxa_demangle(function.mb_str(), NULL, NULL, &status);				if (!status) {			result = wxConvCurrent->cMB2WX(demangled);		}				if (demangled) {			free(demangled);		}	}		return result;#else	return wxEmptyString;#endif}// Print a stack backtrace if availablewxString get_backtrace(unsigned n){#ifdef HAVE_EXECINFO	// (stkn) create backtrace	void *bt_array[100];	// 100 should be enough ?!?	char **bt_strings;	int num_entries;	if ((num_entries = backtrace(bt_array, 100)) < 0) {		fprintf(stderr, "* Could not generate backtrace\n");		return wxEmptyString;	}	if ((bt_strings = backtrace_symbols(bt_array, num_entries)) == NULL) {		fprintf(stderr, "* Could not get symbol names for backtrace\n");		return wxEmptyString;	}	std::vector<wxString> libname(num_entries);	std::vector<wxString> funcname(num_entries);	std::vector<wxString> address(num_entries);	wxString AllAddresses;		for (int i = 0; i < num_entries; ++i) {		wxString wxBtString = wxConvCurrent->cMB2WX(bt_strings[i]);		int posLPar = wxBtString.Find(wxT('('));		int posRPar = wxBtString.Find(wxT(')'));		int posLBra = wxBtString.Find(wxT('['));		int posRBra = wxBtString.Find(wxT(']'));		bool hasFunction = true;		if (posLPar == -1 || posRPar == -1) {			if (posLBra == -1 || posRBra == -1) {				/* It is important to have exactly num_entries				* addresses in AllAddresses */				AllAddresses += wxT("0x0000000 ");				continue;			}			posLPar = posLBra;			hasFunction = false;		}		/* Library name */		int len = posLPar;		libname[i] = wxBtString.Mid(0, len);		/* Function name */		if (hasFunction) {			int posPlus = wxBtString.Find(wxT('+'), true);			if (posPlus == -1)				posPlus = posRPar;			len = posPlus - posLPar - 1;			funcname[i] = wxBtString.Mid(posLPar + 1, len);			wxString demangled = demangle(funcname[i]);			if (!demangled.IsEmpty()) {				funcname[i] = demangled;			}		}		/* Address */		if ( posLBra == -1 || posRBra == -1) {			address[i] = wxT("0x0000000");		} else {			len = posRBra - posLBra - 1;			address[i] = wxBtString.Mid(posLBra + 1, len);			AllAddresses += address[i] + wxT(" ");		}	}	free(bt_strings);	/* Get line numbers from addresses */	wxArrayString out;	bool hasLineNumberInfo = false;#ifdef HAVE_BFD	if (!s_have_backtrace_symbols) {		init_backtrace_info();		wxASSERT(s_have_backtrace_symbols);	}	for (int i = 0; i < num_entries; ++i) {		s_file_name = NULL;		s_function_name = NULL;		s_line_number = 0;		s_found = false ;		unsigned long addr;		address[i].ToULong(&addr,0); // As it's "0x" prepended, wx will read it as base 16. Hopefully.		bfd_map_over_sections(s_abfd, get_file_line_info, (void*)addr);		if (s_found) {			wxString function = wxConvCurrent->cMB2WX(s_function_name);			wxString demangled = demangle(function);			if (!demangled.IsEmpty()) {				function = demangled;				funcname[i] = demangled;			}			out.Insert(wxConvCurrent->cMB2WX(s_function_name),i*2);			out.Insert(wxConvCurrent->cMB2WX(s_file_name) + wxString::Format(wxT(":%u"), s_line_number),i*2+1);		} else {			out.Insert(wxT("??"),i*2);			out.Insert(wxT("??"),i*2+1);		}	}	hasLineNumberInfo = true;#else	/* !HAVE_BFD */	if (wxThread::IsMain()) {		wxString command;		command << wxT("addr2line -C -f -s -e /proc/") <<		getpid() << wxT("/exe ") << AllAddresses;		// The output of the command is this wxArrayString, in which		// the even elements are the function names, and the odd elements		// are the line numbers.		hasLineNumberInfo = wxExecute(command, out) != -1;	}#endif	/* HAVE_BFD / !HAVE_BFD */	wxString trace;	// Remove 'n+1' first entries (+1 because of this function)	for (int i = n+1; i < num_entries; ++i) {		/* If we have no function name, use the result from addr2line */		if (funcname[i].IsEmpty()) {			if (hasLineNumberInfo) {				funcname[i] = out[2*i];			} else {				funcname[i] = wxT("??");			}		}		wxString btLine;		btLine << wxT("[") << i << wxT("] ") << funcname[i] << wxT(" in ");		/* If addr2line did not find a line number, use bt_string */		if (!hasLineNumberInfo || out[2*i+1].Mid(0,2) == wxT("??")) {			btLine += libname[i] + wxT("[") + address[i] + wxT("]");		} else if (hasLineNumberInfo) {#if TOO_VERBOSE_BACKTRACE			btLine += out[2*i+1];#else			btLine += out[2*i+1].AfterLast(wxT('/'));#endif		} else {			btLine += libname[i];		}				trace += btLine + wxT("\n");	}	return trace;#else /* !HAVE_EXECINFO */	fprintf(stderr, "--== cannot generate backtrace ==--\n\n");	return wxEmptyString;#endif /* HAVE_EXECINFO */}#else	/* !__LINUX__ */wxString get_backtrace(unsigned WXUNUSED(n)){	fprintf(stderr, "--== no BACKTRACE for your platform ==--\n\n");	return wxEmptyString;}#endif /* !__LINUX__ */void print_backtrace(unsigned n){	wxString trace = get_backtrace(n);	// This is because the string is ansi anyway, and the conv classes are very slow	fprintf(stderr, "%s\n", (const char*)unicode2char(trace.c_str()));}// File_checked_for_headers

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -