2022-05-24 14:06:29 -04:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								/*
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  backward . hpp 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  Copyright  2013  Google  Inc .  All  Rights  Reserved . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  Permission  is  hereby  granted ,  free  of  charge ,  to  any  person  obtaining  a  copy 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  of  this  software  and  associated  documentation  files  ( the  " Software " ) ,  to  deal 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  in  the  Software  without  restriction ,  including  without  limitation  the  rights 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  to  use ,  copy ,  modify ,  merge ,  publish ,  distribute ,  sublicense ,  and / or  sell 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  copies  of  the  Software ,  and  to  permit  persons  to  whom  the  Software  is 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  furnished  to  do  so ,  subject  to  the  following  conditions : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  The  above  copyright  notice  and  this  permission  notice  shall  be  included  in 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  all  copies  or  substantial  portions  of  the  Software . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  THE  SOFTWARE  IS  PROVIDED  " AS IS " ,  WITHOUT  WARRANTY  OF  ANY  KIND ,  EXPRESS  OR 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  IMPLIED ,  INCLUDING  BUT  NOT  LIMITED  TO  THE  WARRANTIES  OF  MERCHANTABILITY , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  FITNESS  FOR  A  PARTICULAR  PURPOSE  AND  NONINFRINGEMENT .  IN  NO  EVENT  SHALL  THE 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  AUTHORS  OR  COPYRIGHT  HOLDERS  BE  LIABLE  FOR  ANY  CLAIM ,  DAMAGES  OR  OTHER 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  LIABILITY ,  WHETHER  IN  AN  ACTION  OF  CONTRACT ,  TORT  OR  OTHERWISE ,  ARISING  FROM , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  OUT  OF  OR  IN  CONNECTION  WITH  THE  SOFTWARE  OR  THE  USE  OR  OTHER  DEALINGS  IN  THE 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  SOFTWARE . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# ifndef H_6B9572DA_A64B_49E6_B234_051480991C89 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# define H_6B9572DA_A64B_49E6_B234_051480991C89 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# ifndef __cplusplus 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# error "It's not going to compile without a C++ compiler..." 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# endif 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# if defined(BACKWARD_CXX11) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# elif defined(BACKWARD_CXX98) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# else 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# if __cplusplus >= 201103L || (defined(_MSC_VER) && _MSC_VER >= 1800) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# define BACKWARD_CXX11 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# define BACKWARD_ATLEAST_CXX11 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# define BACKWARD_ATLEAST_CXX98 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# if __cplusplus >= 201703L || (defined(_MSVC_LANG) && _MSVC_LANG >= 201703L) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# define BACKWARD_ATLEAST_CXX17 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# endif 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# else 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# define BACKWARD_CXX98 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# define BACKWARD_ATLEAST_CXX98 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# endif 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# endif 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// You can define one of the following (or leave it to the auto-detection):
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// #define BACKWARD_SYSTEM_LINUX
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//	- specialization for linux
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// #define BACKWARD_SYSTEM_DARWIN
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//	- specialization for Mac OS X 10.5 and later.
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// #define BACKWARD_SYSTEM_WINDOWS
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//  - specialization for Windows (Clang 9 and MSVC2017)
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// #define BACKWARD_SYSTEM_UNKNOWN
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//	- placebo implementation, does nothing.
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# if defined(BACKWARD_SYSTEM_LINUX) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# elif defined(BACKWARD_SYSTEM_DARWIN) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# elif defined(BACKWARD_SYSTEM_UNKNOWN) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# elif defined(BACKWARD_SYSTEM_WINDOWS) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# else 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# if defined(__linux) || defined(__linux__) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# define BACKWARD_SYSTEM_LINUX 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# elif defined(__APPLE__) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# define BACKWARD_SYSTEM_DARWIN 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# elif defined(_WIN32) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# define BACKWARD_SYSTEM_WINDOWS 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# else 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# define BACKWARD_SYSTEM_UNKNOWN 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# endif 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# endif 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# define NOINLINE __attribute__((noinline)) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# include  <algorithm> 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# include  <cctype> 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# include  <cstdio> 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# include  <cstdlib> 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# include  <cstring> 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# include  <fstream> 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# include  <iomanip> 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# include  <iostream> 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# include  <limits> 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# include  <new> 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# include  <sstream> 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# include  <streambuf> 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# include  <string> 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# include  <vector> 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# include  <exception> 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# include  <iterator> 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# if defined(BACKWARD_SYSTEM_LINUX) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// On linux, backtrace can back-trace or "walk" the stack using the following
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// libraries:
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// #define BACKWARD_HAS_UNWIND 1
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//  - unwind comes from libgcc, but I saw an equivalent inside clang itself.
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//  - with unwind, the stacktrace is as accurate as it can possibly be, since
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//  this is used by the C++ runtine in gcc/clang for stack unwinding on
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//  exception.
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//  - normally libgcc is already linked to your program by default.
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// #define BACKWARD_HAS_LIBUNWIND 1
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//  - libunwind provides, in some cases, a more accurate stacktrace as it knows
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//  to decode signal handler frames and lets us edit the context registers when
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//  unwinding, allowing stack traces over bad function references.
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// #define BACKWARD_HAS_BACKTRACE == 1
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//  - backtrace seems to be a little bit more portable than libunwind, but on
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//  linux, it uses unwind anyway, but abstract away a tiny information that is
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//  sadly really important in order to get perfectly accurate stack traces.
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//  - backtrace is part of the (e)glib library.
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// The default is:
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// #define BACKWARD_HAS_UNWIND == 1
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// Note that only one of the define should be set to 1 at a time.
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# if BACKWARD_HAS_UNWIND == 1 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# elif BACKWARD_HAS_LIBUNWIND == 1 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# elif BACKWARD_HAS_BACKTRACE == 1 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# else 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# undef BACKWARD_HAS_UNWIND 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# define BACKWARD_HAS_UNWIND 1 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# undef BACKWARD_HAS_LIBUNWIND 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# define BACKWARD_HAS_LIBUNWIND 0 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# undef BACKWARD_HAS_BACKTRACE 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# define BACKWARD_HAS_BACKTRACE 0 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# endif 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// On linux, backward can extract detailed information about a stack trace
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// using one of the following libraries:
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// #define BACKWARD_HAS_DW 1
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//  - libdw gives you the most juicy details out of your stack traces:
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//    - object filename
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//    - function name
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//    - source filename
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//    - line and column numbers
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//    - source code snippet (assuming the file is accessible)
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//    - variable names (if not optimized out)
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//    - variable values (not supported by backward-cpp)
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//  - You need to link with the lib "dw":
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//    - apt-get install libdw-dev
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//    - g++/clang++ -ldw ...
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// #define BACKWARD_HAS_BFD 1
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//  - With libbfd, you get a fair amount of details:
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//    - object filename
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//    - function name
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//    - source filename
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//    - line numbers
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//    - source code snippet (assuming the file is accessible)
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//  - You need to link with the lib "bfd":
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//    - apt-get install binutils-dev
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//    - g++/clang++ -lbfd ...
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// #define BACKWARD_HAS_DWARF 1
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//  - libdwarf gives you the most juicy details out of your stack traces:
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//    - object filename
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//    - function name
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//    - source filename
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//    - line and column numbers
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//    - source code snippet (assuming the file is accessible)
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//    - variable names (if not optimized out)
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//    - variable values (not supported by backward-cpp)
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//  - You need to link with the lib "dwarf":
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//    - apt-get install libdwarf-dev
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//    - g++/clang++ -ldwarf ...
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// #define BACKWARD_HAS_BACKTRACE_SYMBOL 1
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//  - backtrace provides minimal details for a stack trace:
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//    - object filename
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//    - function name
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//  - backtrace is part of the (e)glib library.
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// The default is:
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// #define BACKWARD_HAS_BACKTRACE_SYMBOL == 1
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// Note that only one of the define should be set to 1 at a time.
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# if BACKWARD_HAS_DW == 1 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# elif BACKWARD_HAS_BFD == 1 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# elif BACKWARD_HAS_DWARF == 1 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# elif BACKWARD_HAS_BACKTRACE_SYMBOL == 1 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# else 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# undef BACKWARD_HAS_DW 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# define BACKWARD_HAS_DW 0 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# undef BACKWARD_HAS_BFD 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# define BACKWARD_HAS_BFD 0 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# undef BACKWARD_HAS_DWARF 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# define BACKWARD_HAS_DWARF 0 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# undef BACKWARD_HAS_BACKTRACE_SYMBOL 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# define BACKWARD_HAS_BACKTRACE_SYMBOL 1 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# endif 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# include  <cxxabi.h> 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# include  <fcntl.h> 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# ifdef __ANDROID__ 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//		Old Android API levels define _Unwind_Ptr in both link.h and
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// unwind.h 		Rename the one in link.h as we are not going to be using
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// it
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# define _Unwind_Ptr _Unwind_Ptr_Custom 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# include  <link.h> 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# undef _Unwind_Ptr 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# else 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# include  <link.h> 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# endif 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# if defined(__ppc__) || defined(__powerpc) || defined(__powerpc__) ||        \ 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    defined ( __POWERPC__ ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// Linux kernel header required for the struct pt_regs definition
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// to access the NIP (Next Instruction Pointer) register value
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# include  <asm/ptrace.h> 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# endif 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# include  <signal.h> 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# include  <sys/stat.h> 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# include  <syscall.h> 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# include  <unistd.h> 
  
						 
					
						
							
								
									
										
										
										
											2022-07-14 23:17:05 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								// https://github.com/tildearrow/furnace/issues/588
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# ifndef _GNU_SOURCE 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# define _GNU_SOURCE 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# include  <dlfcn.h> 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# undef _GNU_SOURCE 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# else 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# include  <dlfcn.h> 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# endif 
  
						 
					
						
							
								
									
										
										
										
											2022-05-24 14:06:29 -04:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# if BACKWARD_HAS_BFD == 1 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//              NOTE: defining PACKAGE{,_VERSION} is required before including
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//                    bfd.h on some platforms, see also:
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//                    https://sourceware.org/bugzilla/show_bug.cgi?id=14243
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# ifndef PACKAGE 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# define PACKAGE 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# endif 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# ifndef PACKAGE_VERSION 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# define PACKAGE_VERSION 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# endif 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# include  <bfd.h> 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# endif 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# if BACKWARD_HAS_DW == 1 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# include  <dwarf.h> 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# include  <elfutils/libdw.h> 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# include  <elfutils/libdwfl.h> 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# endif 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# if BACKWARD_HAS_DWARF == 1 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# include  <algorithm> 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# include  <dwarf.h> 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# include  <libdwarf.h> 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# include  <libelf.h> 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# include  <map> 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# endif 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# if (BACKWARD_HAS_BACKTRACE == 1) || (BACKWARD_HAS_BACKTRACE_SYMBOL == 1) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// then we shall rely on backtrace
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# include  <execinfo.h> 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# endif 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# endif  // defined(BACKWARD_SYSTEM_LINUX)
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# if defined(BACKWARD_SYSTEM_DARWIN) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// On Darwin, backtrace can back-trace or "walk" the stack using the following
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// libraries:
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// #define BACKWARD_HAS_UNWIND 1
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//  - unwind comes from libgcc, but I saw an equivalent inside clang itself.
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//  - with unwind, the stacktrace is as accurate as it can possibly be, since
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//  this is used by the C++ runtine in gcc/clang for stack unwinding on
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//  exception.
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//  - normally libgcc is already linked to your program by default.
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// #define BACKWARD_HAS_LIBUNWIND 1
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//  - libunwind comes from clang, which implements an API compatible version.
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//  - libunwind provides, in some cases, a more accurate stacktrace as it knows
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//  to decode signal handler frames and lets us edit the context registers when
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//  unwinding, allowing stack traces over bad function references.
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// #define BACKWARD_HAS_BACKTRACE == 1
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//  - backtrace is available by default, though it does not produce as much
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//  information as another library might.
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// The default is:
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// #define BACKWARD_HAS_UNWIND == 1
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// Note that only one of the define should be set to 1 at a time.
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# if BACKWARD_HAS_UNWIND == 1 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# elif BACKWARD_HAS_BACKTRACE == 1 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# elif BACKWARD_HAS_LIBUNWIND == 1 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# else 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# undef BACKWARD_HAS_UNWIND 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# define BACKWARD_HAS_UNWIND 1 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# undef BACKWARD_HAS_BACKTRACE 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# define BACKWARD_HAS_BACKTRACE 0 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# undef BACKWARD_HAS_LIBUNWIND 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# define BACKWARD_HAS_LIBUNWIND 0 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# endif 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// On Darwin, backward can extract detailed information about a stack trace
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// using one of the following libraries:
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// #define BACKWARD_HAS_BACKTRACE_SYMBOL 1
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//  - backtrace provides minimal details for a stack trace:
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//    - object filename
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//    - function name
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// The default is:
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// #define BACKWARD_HAS_BACKTRACE_SYMBOL == 1
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# if BACKWARD_HAS_BACKTRACE_SYMBOL == 1 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# else 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# undef BACKWARD_HAS_BACKTRACE_SYMBOL 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# define BACKWARD_HAS_BACKTRACE_SYMBOL 1 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# endif 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# include  <cxxabi.h> 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# include  <fcntl.h> 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# include  <pthread.h> 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# include  <signal.h> 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# include  <sys/stat.h> 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# include  <unistd.h> 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# if (BACKWARD_HAS_BACKTRACE == 1) || (BACKWARD_HAS_BACKTRACE_SYMBOL == 1) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# include  <execinfo.h> 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# endif 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# endif  // defined(BACKWARD_SYSTEM_DARWIN)
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# if defined(BACKWARD_SYSTEM_WINDOWS) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# include  <condition_variable> 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# include  <mutex> 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# include  <thread> 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# include  <basetsd.h> 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# ifdef _WIN64 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								typedef  SSIZE_T  ssize_t ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# else 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								typedef  int  ssize_t ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# endif 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# ifndef NOMINMAX 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# define NOMINMAX 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# endif 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# include  <windows.h> 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# include  <winnt.h> 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# include  <psapi.h> 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# include  <signal.h> 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# ifndef __clang__ 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# undef NOINLINE 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# define NOINLINE __declspec(noinline) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# endif 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# ifdef _MSC_VER 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# pragma comment(lib, "psapi.lib") 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# pragma comment(lib, "dbghelp.lib") 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# endif 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// Comment / packing is from stackoverflow:
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// https://stackoverflow.com/questions/6205981/windows-c-stack-trace-from-a-running-app/28276227#28276227
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// Some versions of imagehlp.dll lack the proper packing directives themselves
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// so we need to do it.
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# pragma pack(push, before_imagehlp, 8) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# include  <imagehlp.h> 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# pragma pack(pop, before_imagehlp) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// TODO maybe these should be undefined somewhere else?
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# undef BACKWARD_HAS_UNWIND 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# undef BACKWARD_HAS_BACKTRACE 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# if BACKWARD_HAS_PDB_SYMBOL == 1 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# else 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# undef BACKWARD_HAS_PDB_SYMBOL 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# define BACKWARD_HAS_PDB_SYMBOL 1 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# endif 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# endif 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# if BACKWARD_HAS_UNWIND == 1 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# include  <unwind.h> 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// while gcc's unwind.h defines something like that:
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//  extern _Unwind_Ptr _Unwind_GetIP (struct _Unwind_Context *);
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//  extern _Unwind_Ptr _Unwind_GetIPInfo (struct _Unwind_Context *, int *);
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// clang's unwind.h defines something like this:
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//  uintptr_t _Unwind_GetIP(struct _Unwind_Context* __context);
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// Even if the _Unwind_GetIPInfo can be linked to, it is not declared, worse we
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// cannot just redeclare it because clang's unwind.h doesn't define _Unwind_Ptr
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// anyway.
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// Luckily we can play on the fact that the guard macros have a different name:
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# ifdef __CLANG_UNWIND_H 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// In fact, this function still comes from libgcc (on my different linux boxes,
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// clang links against libgcc).
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# include  <inttypes.h> 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								extern  " C "  uintptr_t  _Unwind_GetIPInfo ( _Unwind_Context  * ,  int  * ) ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# endif 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# endif  // BACKWARD_HAS_UNWIND == 1
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# if BACKWARD_HAS_LIBUNWIND == 1 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# define UNW_LOCAL_ONLY 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# include  <libunwind.h> 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# endif  // BACKWARD_HAS_LIBUNWIND == 1
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# ifdef BACKWARD_ATLEAST_CXX11 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# include  <unordered_map> 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# include  <utility>   // for std::swap
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								namespace  backward  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								namespace  details  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								template  < typename  K ,  typename  V >  struct  hashtable  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  typedef  std : : unordered_map < K ,  V >  type ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								} ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								using  std : : move ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  // namespace details
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  // namespace backward
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# else  // NOT BACKWARD_ATLEAST_CXX11
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# define nullptr NULL 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# define override 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# include  <map> 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								namespace  backward  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								namespace  details  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								template  < typename  K ,  typename  V >  struct  hashtable  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  typedef  std : : map < K ,  V >  type ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								} ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								template  < typename  T >  const  T  & move ( const  T  & v )  {  return  v ;  }  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								template  < typename  T >  T  & move ( T  & v )  {  return  v ;  }  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  // namespace details
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  // namespace backward
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# endif  // BACKWARD_ATLEAST_CXX11
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								namespace  backward  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								namespace  details  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# if defined(BACKWARD_SYSTEM_WINDOWS) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								const  char  kBackwardPathDelimiter [ ]  =  " ; " ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# else 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								const  char  kBackwardPathDelimiter [ ]  =  " : " ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# endif 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  // namespace details
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  // namespace backward
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								namespace  backward  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								namespace  system_tag  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								struct  linux_tag ;  // seems that I cannot call that "linux" because the name
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// is already defined... so I am adding _tag everywhere.
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								struct  darwin_tag ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								struct  windows_tag ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								struct  unknown_tag ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# if defined(BACKWARD_SYSTEM_LINUX) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								typedef  linux_tag  current_tag ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# elif defined(BACKWARD_SYSTEM_DARWIN) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								typedef  darwin_tag  current_tag ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# elif defined(BACKWARD_SYSTEM_WINDOWS) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								typedef  windows_tag  current_tag ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# elif defined(BACKWARD_SYSTEM_UNKNOWN) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								typedef  unknown_tag  current_tag ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# else 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# error "May I please get my system defines?" 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# endif 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  // namespace system_tag
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								namespace  trace_resolver_tag  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# if defined(BACKWARD_SYSTEM_LINUX) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								struct  libdw ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								struct  libbfd ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								struct  libdwarf ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								struct  backtrace_symbol ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# if BACKWARD_HAS_DW == 1 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								typedef  libdw  current ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# elif BACKWARD_HAS_BFD == 1 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								typedef  libbfd  current ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# elif BACKWARD_HAS_DWARF == 1 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								typedef  libdwarf  current ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# elif BACKWARD_HAS_BACKTRACE_SYMBOL == 1 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								typedef  backtrace_symbol  current ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# else 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# error "You shall not pass, until you know what you want." 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# endif 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# elif defined(BACKWARD_SYSTEM_DARWIN) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								struct  backtrace_symbol ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# if BACKWARD_HAS_BACKTRACE_SYMBOL == 1 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								typedef  backtrace_symbol  current ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# else 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# error "You shall not pass, until you know what you want." 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# endif 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# elif defined(BACKWARD_SYSTEM_WINDOWS) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								struct  pdb_symbol ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# if BACKWARD_HAS_PDB_SYMBOL == 1 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								typedef  pdb_symbol  current ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# else 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# error "You shall not pass, until you know what you want." 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# endif 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# endif 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  // namespace trace_resolver_tag
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								namespace  details  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								template  < typename  T >  struct  rm_ptr  {  typedef  T  type ;  } ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								template  < typename  T >  struct  rm_ptr < T  * >  {  typedef  T  type ;  } ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								template  < typename  T >  struct  rm_ptr < const  T  * >  {  typedef  const  T  type ;  } ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								template  < typename  R ,  typename  T ,  R  ( * F ) ( T ) >  struct  deleter  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  template  < typename  U >  void  operator ( ) ( U  & ptr )  const  {  ( * F ) ( ptr ) ;  } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								} ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								template  < typename  T >  struct  default_delete  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  void  operator ( ) ( T  & ptr )  const  {  delete  ptr ;  } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								} ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								template  < typename  T ,  typename  Deleter  =  deleter < void ,  void  * ,  & : : free >  >  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								class  handle  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  struct  dummy ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  T  _val ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  bool  _empty ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# ifdef BACKWARD_ATLEAST_CXX11 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  handle ( const  handle  & )  =  delete ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  handle  & operator = ( const  handle  & )  =  delete ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# endif 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								public :  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  ~ handle ( )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( ! _empty )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      Deleter ( ) ( _val ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  explicit  handle ( )  :  _val ( ) ,  _empty ( true )  { } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  explicit  handle ( T  val )  :  _val ( val ) ,  _empty ( false )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( ! _val ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      _empty  =  true ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# ifdef BACKWARD_ATLEAST_CXX11 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  handle ( handle  & & from )  :  _empty ( true )  {  swap ( from ) ;  } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  handle  & operator = ( handle  & & from )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    swap ( from ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    return  * this ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# else 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  explicit  handle ( const  handle  & from )  :  _empty ( true )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // some sort of poor man's move semantic.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    swap ( const_cast < handle  & > ( from ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  handle  & operator = ( const  handle  & from )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // some sort of poor man's move semantic.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    swap ( const_cast < handle  & > ( from ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    return  * this ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# endif 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  void  reset ( T  new_val )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    handle  tmp ( new_val ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    swap ( tmp ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  void  update ( T  new_val )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    _val  =  new_val ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    _empty  =  ! static_cast < bool > ( new_val ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  operator  const  dummy  * ( )  const  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( _empty )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      return  nullptr ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    return  reinterpret_cast < const  dummy  * > ( _val ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  T  get ( )  {  return  _val ;  } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  T  release ( )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    _empty  =  true ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    return  _val ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  void  swap ( handle  & b )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    using  std : : swap ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    swap ( b . _val ,  _val ) ;      // can throw, we are safe here.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    swap ( b . _empty ,  _empty ) ;  // should not throw: if you cannot swap two
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // bools without throwing... It's a lost cause anyway!
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  T  & operator - > ( )  {  return  _val ;  } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  const  T  & operator - > ( )  const  {  return  _val ;  } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  typedef  typename  rm_ptr < T > : : type  & ref_t ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  typedef  const  typename  rm_ptr < T > : : type  & const_ref_t ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  ref_t  operator * ( )  {  return  * _val ;  } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  const_ref_t  operator * ( )  const  {  return  * _val ;  } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  ref_t  operator [ ] ( size_t  idx )  {  return  _val [ idx ] ;  } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  // Watch out, we've got a badass over here
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  T  * operator & ( )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    _empty  =  false ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    return  & _val ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								} ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// Default demangler implementation (do nothing).
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								template  < typename  TAG >  struct  demangler_impl  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  static  std : : string  demangle ( const  char  * funcname )  {  return  funcname ;  } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								} ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# if defined(BACKWARD_SYSTEM_LINUX) || defined(BACKWARD_SYSTEM_DARWIN) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								template  < >  struct  demangler_impl < system_tag : : current_tag >  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  demangler_impl ( )  :  _demangle_buffer_length ( 0 )  { } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  std : : string  demangle ( const  char  * funcname )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    using  namespace  details ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    char  * result  =  abi : : __cxa_demangle ( funcname ,  _demangle_buffer . get ( ) , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                                       & _demangle_buffer_length ,  nullptr ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( result )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      _demangle_buffer . update ( result ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      return  result ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    return  funcname ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								private :  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  details : : handle < char  * >  _demangle_buffer ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  size_t  _demangle_buffer_length ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								} ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# endif  // BACKWARD_SYSTEM_LINUX || BACKWARD_SYSTEM_DARWIN
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								struct  demangler  :  public  demangler_impl < system_tag : : current_tag >  { } ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// Split a string on the platform's PATH delimiter.  Example: if delimiter
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// is ":" then:
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//   ""              --> []
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//   ":"             --> ["",""]
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//   "::"            --> ["","",""]
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//   "/a/b/c"        --> ["/a/b/c"]
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//   "/a/b/c:/d/e/f" --> ["/a/b/c","/d/e/f"]
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//   etc.
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								inline  std : : vector < std : : string >  split_source_prefixes ( const  std : : string  & s )  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  std : : vector < std : : string >  out ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  size_t  last  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  size_t  next  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  size_t  delimiter_size  =  sizeof ( kBackwardPathDelimiter )  -  1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  while  ( ( next  =  s . find ( kBackwardPathDelimiter ,  last ) )  ! =  std : : string : : npos )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    out . push_back ( s . substr ( last ,  next  -  last ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    last  =  next  +  delimiter_size ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  if  ( last  < =  s . length ( ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    out . push_back ( s . substr ( last ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  return  out ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  // namespace details
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/*************** A TRACE ***************/  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								struct  Trace  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  void  * addr ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  size_t  idx ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  Trace ( )  :  addr ( nullptr ) ,  idx ( 0 )  { } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  explicit  Trace ( void  * _addr ,  size_t  _idx )  :  addr ( _addr ) ,  idx ( _idx )  { } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								} ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								struct  ResolvedTrace  :  public  Trace  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  struct  SourceLoc  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    std : : string  function ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    std : : string  filename ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    unsigned  line ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    unsigned  col ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    SourceLoc ( )  :  line ( 0 ) ,  col ( 0 )  { } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    bool  operator = = ( const  SourceLoc  & b )  const  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      return  function  = =  b . function  & &  filename  = =  b . filename  & & 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								             line  = =  b . line  & &  col  = =  b . col ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    bool  operator ! = ( const  SourceLoc  & b )  const  {  return  ! ( * this  = =  b ) ;  } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  } ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  // In which binary object this trace is located.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  std : : string  object_filename ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  // The function in the object that contain the trace. This is not the same
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  // as source.function which can be an function inlined in object_function.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  std : : string  object_function ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  // The source location of this trace. It is possible for filename to be
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  // empty and for line/col to be invalid (value 0) if this information
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  // couldn't be deduced, for example if there is no debug information in the
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  // binary object.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  SourceLoc  source ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  // An optionals list of "inliners". All the successive sources location
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  // from where the source location of the trace (the attribute right above)
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  // is inlined. It is especially useful when you compiled with optimization.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  typedef  std : : vector < SourceLoc >  source_locs_t ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  source_locs_t  inliners ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  ResolvedTrace ( )  :  Trace ( )  { } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  ResolvedTrace ( const  Trace  & mini_trace )  :  Trace ( mini_trace )  { } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								} ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/*************** STACK TRACE ***************/  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// default implemention.
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								template  < typename  TAG >  class  StackTraceImpl  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								public :  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  size_t  size ( )  const  {  return  0 ;  } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  Trace  operator [ ] ( size_t )  const  {  return  Trace ( ) ;  } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  size_t  load_here ( size_t  =  0 )  {  return  0 ;  } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  size_t  load_from ( void  * ,  size_t  =  0 ,  void  *  =  nullptr ,  void  *  =  nullptr )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    return  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  size_t  thread_id ( )  const  {  return  0 ;  } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  void  skip_n_firsts ( size_t )  { } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								} ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								class  StackTraceImplBase  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								public :  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  StackTraceImplBase ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      :  _thread_id ( 0 ) ,  _skip ( 0 ) ,  _context ( nullptr ) ,  _error_addr ( nullptr )  { } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  size_t  thread_id ( )  const  {  return  _thread_id ;  } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  void  skip_n_firsts ( size_t  n )  {  _skip  =  n ;  } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								protected :  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  void  load_thread_info ( )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# ifdef BACKWARD_SYSTEM_LINUX 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# ifndef __ANDROID__ 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    _thread_id  =  static_cast < size_t > ( syscall ( SYS_gettid ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# else 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    _thread_id  =  static_cast < size_t > ( gettid ( ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# endif 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( _thread_id  = =  static_cast < size_t > ( getpid ( ) ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      // If the thread is the main one, let's hide that.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      // I like to keep little secret sometimes.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      _thread_id  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# elif defined(BACKWARD_SYSTEM_DARWIN) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    _thread_id  =  reinterpret_cast < size_t > ( pthread_self ( ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( pthread_main_np ( )  = =  1 )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      // If the thread is the main one, let's hide that.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      _thread_id  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# endif 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  void  set_context ( void  * context )  {  _context  =  context ;  } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  void  * context ( )  const  {  return  _context ;  } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  void  set_error_addr ( void  * error_addr )  {  _error_addr  =  error_addr ;  } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  void  * error_addr ( )  const  {  return  _error_addr ;  } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  size_t  skip_n_firsts ( )  const  {  return  _skip ;  } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								private :  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  size_t  _thread_id ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  size_t  _skip ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  void  * _context ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  void  * _error_addr ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								} ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								class  StackTraceImplHolder  :  public  StackTraceImplBase  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								public :  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  size_t  size ( )  const  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    return  ( _stacktrace . size ( )  > =  skip_n_firsts ( ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								               ?  _stacktrace . size ( )  -  skip_n_firsts ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								               :  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  Trace  operator [ ] ( size_t  idx )  const  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( idx  > =  size ( ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      return  Trace ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    return  Trace ( _stacktrace [ idx  +  skip_n_firsts ( ) ] ,  idx ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  void  * const  * begin ( )  const  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( size ( ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      return  & _stacktrace [ skip_n_firsts ( ) ] ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    return  nullptr ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								protected :  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  std : : vector < void  * >  _stacktrace ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								} ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# if BACKWARD_HAS_UNWIND == 1 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								namespace  details  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								template  < typename  F >  class  Unwinder  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								public :  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  size_t  operator ( ) ( F  & f ,  size_t  depth )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    _f  =  & f ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    _index  =  - 1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    _depth  =  depth ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    _Unwind_Backtrace ( & this - > backtrace_trampoline ,  this ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    return  static_cast < size_t > ( _index ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								private :  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  F  * _f ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  ssize_t  _index ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  size_t  _depth ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  static  _Unwind_Reason_Code  backtrace_trampoline ( _Unwind_Context  * ctx , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                                                  void  * self )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    return  ( static_cast < Unwinder  * > ( self ) ) - > backtrace ( ctx ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  _Unwind_Reason_Code  backtrace ( _Unwind_Context  * ctx )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( _index  > =  0  & &  static_cast < size_t > ( _index )  > =  _depth ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      return  _URC_END_OF_STACK ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    int  ip_before_instruction  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    uintptr_t  ip  =  _Unwind_GetIPInfo ( ctx ,  & ip_before_instruction ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( ! ip_before_instruction )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      // calculating 0-1 for unsigned, looks like a possible bug to sanitiziers,
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      // so let's do it explicitly:
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      if  ( ip  = =  0 )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        ip  =  std : : numeric_limits < uintptr_t > : : max ( ) ;  // set it to 0xffff... (as
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                                                    // from casting 0-1)
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      }  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        ip  - =  1 ;  // else just normally decrement it (no overflow/underflow will
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                 // happen)
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( _index  > =  0 )  {  // ignore first frame.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      ( * _f ) ( static_cast < size_t > ( _index ) ,  reinterpret_cast < void  * > ( ip ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    _index  + =  1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    return  _URC_NO_REASON ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								} ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								template  < typename  F >  size_t  unwind ( F  f ,  size_t  depth )  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  Unwinder < F >  unwinder ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  return  unwinder ( f ,  depth ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  // namespace details
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								template  < >  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								class  StackTraceImpl < system_tag : : current_tag >  :  public  StackTraceImplHolder  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								public :  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  NOINLINE 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  size_t  load_here ( size_t  depth  =  32 ,  void  * context  =  nullptr , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                   void  * error_addr  =  nullptr )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    load_thread_info ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    set_context ( context ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    set_error_addr ( error_addr ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( depth  = =  0 )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      return  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    _stacktrace . resize ( depth ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    size_t  trace_cnt  =  details : : unwind ( callback ( * this ) ,  depth ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    _stacktrace . resize ( trace_cnt ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    skip_n_firsts ( 0 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    return  size ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  size_t  load_from ( void  * addr ,  size_t  depth  =  32 ,  void  * context  =  nullptr , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                   void  * error_addr  =  nullptr )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    load_here ( depth  +  8 ,  context ,  error_addr ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    for  ( size_t  i  =  0 ;  i  <  _stacktrace . size ( ) ;  + + i )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      if  ( _stacktrace [ i ]  = =  addr )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        skip_n_firsts ( i ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    _stacktrace . resize ( std : : min ( _stacktrace . size ( ) ,  skip_n_firsts ( )  +  depth ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    return  size ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								private :  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  struct  callback  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    StackTraceImpl  & self ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    callback ( StackTraceImpl  & _self )  :  self ( _self )  { } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    void  operator ( ) ( size_t  idx ,  void  * addr )  {  self . _stacktrace [ idx ]  =  addr ;  } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  } ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								} ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# elif BACKWARD_HAS_LIBUNWIND == 1 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								template  < >  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								class  StackTraceImpl < system_tag : : current_tag >  :  public  StackTraceImplHolder  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								public :  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  __attribute__ ( ( noinline ) )  size_t  load_here ( size_t  depth  =  32 , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                                             void  * _context  =  nullptr , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                                             void  * _error_addr  =  nullptr )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    set_context ( _context ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    set_error_addr ( _error_addr ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    load_thread_info ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( depth  = =  0 )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      return  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    _stacktrace . resize ( depth  +  1 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    int  result  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    unw_context_t  ctx ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    size_t  index  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // Add the tail call. If the Instruction Pointer is the crash address it
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // means we got a bad function pointer dereference, so we "unwind" the
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // bad pointer manually by using the return address pointed to by the
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // Stack Pointer as the Instruction Pointer and letting libunwind do
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // the rest
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( context ( ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      ucontext_t  * uctx  =  reinterpret_cast < ucontext_t  * > ( context ( ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# ifdef REG_RIP          // x86_64
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      if  ( uctx - > uc_mcontext . gregs [ REG_RIP ]  = = 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          reinterpret_cast < greg_t > ( error_addr ( ) ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        uctx - > uc_mcontext . gregs [ REG_RIP ]  = 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            * reinterpret_cast < size_t  * > ( uctx - > uc_mcontext . gregs [ REG_RSP ] ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      _stacktrace [ index ]  = 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          reinterpret_cast < void  * > ( uctx - > uc_mcontext . gregs [ REG_RIP ] ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      + + index ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      ctx  =  * reinterpret_cast < unw_context_t  * > ( uctx ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# elif defined(REG_EIP)  // x86_32
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      if  ( uctx - > uc_mcontext . gregs [ REG_EIP ]  = = 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          reinterpret_cast < greg_t > ( error_addr ( ) ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        uctx - > uc_mcontext . gregs [ REG_EIP ]  = 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            * reinterpret_cast < size_t  * > ( uctx - > uc_mcontext . gregs [ REG_ESP ] ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      _stacktrace [ index ]  = 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          reinterpret_cast < void  * > ( uctx - > uc_mcontext . gregs [ REG_EIP ] ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      + + index ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      ctx  =  * reinterpret_cast < unw_context_t  * > ( uctx ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# elif defined(__arm__) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      // libunwind uses its own context type for ARM unwinding.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      // Copy the registers from the signal handler's context so we can
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      // unwind
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      unw_getcontext ( & ctx ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      ctx . regs [ UNW_ARM_R0 ]  =  uctx - > uc_mcontext . arm_r0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      ctx . regs [ UNW_ARM_R1 ]  =  uctx - > uc_mcontext . arm_r1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      ctx . regs [ UNW_ARM_R2 ]  =  uctx - > uc_mcontext . arm_r2 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      ctx . regs [ UNW_ARM_R3 ]  =  uctx - > uc_mcontext . arm_r3 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      ctx . regs [ UNW_ARM_R4 ]  =  uctx - > uc_mcontext . arm_r4 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      ctx . regs [ UNW_ARM_R5 ]  =  uctx - > uc_mcontext . arm_r5 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      ctx . regs [ UNW_ARM_R6 ]  =  uctx - > uc_mcontext . arm_r6 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      ctx . regs [ UNW_ARM_R7 ]  =  uctx - > uc_mcontext . arm_r7 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      ctx . regs [ UNW_ARM_R8 ]  =  uctx - > uc_mcontext . arm_r8 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      ctx . regs [ UNW_ARM_R9 ]  =  uctx - > uc_mcontext . arm_r9 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      ctx . regs [ UNW_ARM_R10 ]  =  uctx - > uc_mcontext . arm_r10 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      ctx . regs [ UNW_ARM_R11 ]  =  uctx - > uc_mcontext . arm_fp ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      ctx . regs [ UNW_ARM_R12 ]  =  uctx - > uc_mcontext . arm_ip ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      ctx . regs [ UNW_ARM_R13 ]  =  uctx - > uc_mcontext . arm_sp ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      ctx . regs [ UNW_ARM_R14 ]  =  uctx - > uc_mcontext . arm_lr ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      ctx . regs [ UNW_ARM_R15 ]  =  uctx - > uc_mcontext . arm_pc ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      // If we have crashed in the PC use the LR instead, as this was
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      // a bad function dereference
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      if  ( reinterpret_cast < unsigned  long > ( error_addr ( ) )  = = 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          uctx - > uc_mcontext . arm_pc )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        ctx . regs [ UNW_ARM_R15 ]  = 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            uctx - > uc_mcontext . arm_lr  -  sizeof ( unsigned  long ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      _stacktrace [ index ]  =  reinterpret_cast < void  * > ( ctx . regs [ UNW_ARM_R15 ] ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      + + index ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# elif defined(__APPLE__) && defined(__x86_64__) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      unw_getcontext ( & ctx ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      // OS X's implementation of libunwind uses its own context object
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      // so we need to convert the passed context to libunwind's format
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      // (information about the data layout taken from unw_getcontext.s
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      // in Apple's libunwind source
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      ctx . data [ 0 ]  =  uctx - > uc_mcontext - > __ss . __rax ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      ctx . data [ 1 ]  =  uctx - > uc_mcontext - > __ss . __rbx ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      ctx . data [ 2 ]  =  uctx - > uc_mcontext - > __ss . __rcx ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      ctx . data [ 3 ]  =  uctx - > uc_mcontext - > __ss . __rdx ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      ctx . data [ 4 ]  =  uctx - > uc_mcontext - > __ss . __rdi ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      ctx . data [ 5 ]  =  uctx - > uc_mcontext - > __ss . __rsi ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      ctx . data [ 6 ]  =  uctx - > uc_mcontext - > __ss . __rbp ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      ctx . data [ 7 ]  =  uctx - > uc_mcontext - > __ss . __rsp ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      ctx . data [ 8 ]  =  uctx - > uc_mcontext - > __ss . __r8 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      ctx . data [ 9 ]  =  uctx - > uc_mcontext - > __ss . __r9 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      ctx . data [ 10 ]  =  uctx - > uc_mcontext - > __ss . __r10 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      ctx . data [ 11 ]  =  uctx - > uc_mcontext - > __ss . __r11 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      ctx . data [ 12 ]  =  uctx - > uc_mcontext - > __ss . __r12 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      ctx . data [ 13 ]  =  uctx - > uc_mcontext - > __ss . __r13 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      ctx . data [ 14 ]  =  uctx - > uc_mcontext - > __ss . __r14 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      ctx . data [ 15 ]  =  uctx - > uc_mcontext - > __ss . __r15 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      ctx . data [ 16 ]  =  uctx - > uc_mcontext - > __ss . __rip ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      // If the IP is the same as the crash address we have a bad function
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      // dereference The caller's address is pointed to by %rsp, so we
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      // dereference that value and set it to be the next frame's IP.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      if  ( uctx - > uc_mcontext - > __ss . __rip  = = 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          reinterpret_cast < __uint64_t > ( error_addr ( ) ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        ctx . data [ 16 ]  = 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            * reinterpret_cast < __uint64_t  * > ( uctx - > uc_mcontext - > __ss . __rsp ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      _stacktrace [ index ]  =  reinterpret_cast < void  * > ( ctx . data [ 16 ] ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      + + index ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# elif defined(__APPLE__) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      unw_getcontext ( & ctx ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          // TODO: Convert the ucontext_t to libunwind's unw_context_t like
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          // we do in 64 bits
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          if  ( ctx . uc_mcontext - > __ss . __eip  = = 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								              reinterpret_cast < greg_t > ( error_addr ( ) ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        ctx . uc_mcontext - > __ss . __eip  =  ctx . uc_mcontext - > __ss . __esp ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      _stacktrace [ index ]  = 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          reinterpret_cast < void  * > ( ctx . uc_mcontext - > __ss . __eip ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      + + index ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# endif 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    unw_cursor_t  cursor ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( context ( ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# if defined(UNW_INIT_SIGNAL_FRAME) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      result  =  unw_init_local2 ( & cursor ,  & ctx ,  UNW_INIT_SIGNAL_FRAME ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# else 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      result  =  unw_init_local ( & cursor ,  & ctx ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# endif 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    }  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      unw_getcontext ( & ctx ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      result  =  unw_init_local ( & cursor ,  & ctx ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( result  ! =  0 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      return  1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    unw_word_t  ip  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    while  ( index  < =  depth  & &  unw_step ( & cursor )  >  0 )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      result  =  unw_get_reg ( & cursor ,  UNW_REG_IP ,  & ip ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      if  ( result  = =  0 )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        _stacktrace [ index ]  =  reinterpret_cast < void  * > ( - - ip ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        + + index ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    - - index ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    _stacktrace . resize ( index  +  1 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    skip_n_firsts ( 0 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    return  size ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  size_t  load_from ( void  * addr ,  size_t  depth  =  32 ,  void  * context  =  nullptr , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                   void  * error_addr  =  nullptr )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    load_here ( depth  +  8 ,  context ,  error_addr ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    for  ( size_t  i  =  0 ;  i  <  _stacktrace . size ( ) ;  + + i )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      if  ( _stacktrace [ i ]  = =  addr )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        skip_n_firsts ( i ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        _stacktrace [ i ]  =  ( void  * ) ( ( uintptr_t ) _stacktrace [ i ] ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    _stacktrace . resize ( std : : min ( _stacktrace . size ( ) ,  skip_n_firsts ( )  +  depth ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    return  size ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								} ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# elif defined(BACKWARD_HAS_BACKTRACE) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								template  < >  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								class  StackTraceImpl < system_tag : : current_tag >  :  public  StackTraceImplHolder  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								public :  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  NOINLINE 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  size_t  load_here ( size_t  depth  =  32 ,  void  * context  =  nullptr , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                   void  * error_addr  =  nullptr )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    set_context ( context ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    set_error_addr ( error_addr ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    load_thread_info ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( depth  = =  0 )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      return  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    _stacktrace . resize ( depth  +  1 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    size_t  trace_cnt  =  backtrace ( & _stacktrace [ 0 ] ,  _stacktrace . size ( ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    _stacktrace . resize ( trace_cnt ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    skip_n_firsts ( 1 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    return  size ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  size_t  load_from ( void  * addr ,  size_t  depth  =  32 ,  void  * context  =  nullptr , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                   void  * error_addr  =  nullptr )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    load_here ( depth  +  8 ,  context ,  error_addr ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    for  ( size_t  i  =  0 ;  i  <  _stacktrace . size ( ) ;  + + i )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      if  ( _stacktrace [ i ]  = =  addr )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        skip_n_firsts ( i ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        _stacktrace [ i ]  =  ( void  * ) ( ( uintptr_t ) _stacktrace [ i ]  +  1 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    _stacktrace . resize ( std : : min ( _stacktrace . size ( ) ,  skip_n_firsts ( )  +  depth ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    return  size ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								} ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# elif defined(BACKWARD_SYSTEM_WINDOWS) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								template  < >  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								class  StackTraceImpl < system_tag : : current_tag >  :  public  StackTraceImplHolder  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								public :  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  // We have to load the machine type from the image info
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  // So we first initialize the resolver, and it tells us this info
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  void  set_machine_type ( DWORD  machine_type )  {  machine_type_  =  machine_type ;  } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  void  set_context ( CONTEXT  * ctx )  {  ctx_  =  ctx ;  } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  void  set_thread_handle ( HANDLE  handle )  {  thd_  =  handle ;  } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  NOINLINE 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  size_t  load_here ( size_t  depth  =  32 ,  void  * context  =  nullptr , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                   void  * error_addr  =  nullptr )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    set_context ( static_cast < CONTEXT * > ( context ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    set_error_addr ( error_addr ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    CONTEXT  localCtx ;  // used when no context is provided
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( depth  = =  0 )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      return  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( ! ctx_ )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      ctx_  =  & localCtx ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      RtlCaptureContext ( ctx_ ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( ! thd_ )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      thd_  =  GetCurrentThread ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    HANDLE  process  =  GetCurrentProcess ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    STACKFRAME64  s ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    memset ( & s ,  0 ,  sizeof ( STACKFRAME64 ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // TODO: 32 bit context capture
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    s . AddrStack . Mode  =  AddrModeFlat ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    s . AddrFrame . Mode  =  AddrModeFlat ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    s . AddrPC . Mode  =  AddrModeFlat ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# ifdef _M_X64 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    s . AddrPC . Offset  =  ctx_ - > Rip ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    s . AddrStack . Offset  =  ctx_ - > Rsp ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    s . AddrFrame . Offset  =  ctx_ - > Rbp ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# else 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    s . AddrPC . Offset  =  ctx_ - > Eip ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    s . AddrStack . Offset  =  ctx_ - > Esp ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    s . AddrFrame . Offset  =  ctx_ - > Ebp ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# endif 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( ! machine_type_ )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# ifdef _M_X64 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      machine_type_  =  IMAGE_FILE_MACHINE_AMD64 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# else 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      machine_type_  =  IMAGE_FILE_MACHINE_I386 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# endif 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    for  ( ; ; )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      // NOTE: this only works if PDBs are already loaded!
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      SetLastError ( 0 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      if  ( ! StackWalk64 ( machine_type_ ,  process ,  thd_ ,  & s ,  ctx_ ,  NULL , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                       SymFunctionTableAccess64 ,  SymGetModuleBase64 ,  NULL ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      if  ( s . AddrReturn . Offset  = =  0 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      _stacktrace . push_back ( reinterpret_cast < void  * > ( s . AddrPC . Offset ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      if  ( size ( )  > =  depth ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    return  size ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  size_t  load_from ( void  * addr ,  size_t  depth  =  32 ,  void  * context  =  nullptr , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                   void  * error_addr  =  nullptr )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    load_here ( depth  +  8 ,  context ,  error_addr ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    for  ( size_t  i  =  0 ;  i  <  _stacktrace . size ( ) ;  + + i )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      if  ( _stacktrace [ i ]  = =  addr )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        skip_n_firsts ( i ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    _stacktrace . resize ( std : : min ( _stacktrace . size ( ) ,  skip_n_firsts ( )  +  depth ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    return  size ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								private :  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  DWORD  machine_type_  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  HANDLE  thd_  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  CONTEXT  * ctx_  =  nullptr ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								} ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# endif 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								class  StackTrace  :  public  StackTraceImpl < system_tag : : current_tag >  { } ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/*************** TRACE RESOLVER ***************/  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								class  TraceResolverImplBase  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								public :  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  virtual  ~ TraceResolverImplBase ( )  { } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  virtual  void  load_addresses ( void  * const * addresses ,  int  address_count )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    ( void ) addresses ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    ( void ) address_count ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  template  < class  ST >  void  load_stacktrace ( ST  & st )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    load_addresses ( st . begin ( ) ,  static_cast < int > ( st . size ( ) ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  virtual  ResolvedTrace  resolve ( ResolvedTrace  t )  {  return  t ;  } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								protected :  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  std : : string  demangle ( const  char  * funcname )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    return  _demangler . demangle ( funcname ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								private :  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  details : : demangler  _demangler ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								} ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								template  < typename  TAG >  class  TraceResolverImpl ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# ifdef BACKWARD_SYSTEM_UNKNOWN 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								template  < >  class  TraceResolverImpl < system_tag : : unknown_tag >  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    :  public  TraceResolverImplBase  { } ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# endif 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# ifdef BACKWARD_SYSTEM_LINUX 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								class  TraceResolverLinuxBase  :  public  TraceResolverImplBase  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								public :  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  TraceResolverLinuxBase ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      :  argv0_ ( get_argv0 ( ) ) ,  exec_path_ ( read_symlink ( " /proc/self/exe " ) )  { } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  std : : string  resolve_exec_path ( Dl_info  & symbol_info )  const  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // mutates symbol_info.dli_fname to be filename to open and returns filename
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // to display
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( symbol_info . dli_fname  = =  argv0_ )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      // dladdr returns argv[0] in dli_fname for symbols contained in
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      // the main executable, which is not a valid path if the
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      // executable was found by a search of the PATH environment
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      // variable; In that case, we actually open /proc/self/exe, which
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      // is always the actual executable (even if it was deleted/replaced!)
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      // but display the path that /proc/self/exe links to.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      // However, this right away reduces probability of successful symbol
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      // resolution, because libbfd may try to find *.debug files in the
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      // same dir, in case symbols are stripped. As a result, it may try
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      // to find a file /proc/self/<exe_name>.debug, which obviously does
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      // not exist. /proc/self/exe is a last resort. First load attempt
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      // should go for the original executable file path.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      symbol_info . dli_fname  =  " /proc/self/exe " ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      return  exec_path_ ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    }  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      return  symbol_info . dli_fname ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								private :  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  std : : string  argv0_ ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  std : : string  exec_path_ ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  static  std : : string  get_argv0 ( )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    std : : string  argv0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    std : : ifstream  ifs ( " /proc/self/cmdline " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    std : : getline ( ifs ,  argv0 ,  ' \0 ' ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    return  argv0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  static  std : : string  read_symlink ( std : : string  const  & symlink_path )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    std : : string  path ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    path . resize ( 100 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    while  ( true )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      ssize_t  len  = 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          : : readlink ( symlink_path . c_str ( ) ,  & * path . begin ( ) ,  path . size ( ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      if  ( len  <  0 )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return  " " ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      if  ( static_cast < size_t > ( len )  = =  path . size ( ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        path . resize ( path . size ( )  *  2 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      }  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        path . resize ( static_cast < std : : string : : size_type > ( len ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    return  path ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								} ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								template  < typename  STACKTRACE_TAG >  class  TraceResolverLinuxImpl ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# if BACKWARD_HAS_BACKTRACE_SYMBOL == 1 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								template  < >  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								class  TraceResolverLinuxImpl < trace_resolver_tag : : backtrace_symbol >  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    :  public  TraceResolverLinuxBase  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								public :  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  void  load_addresses ( void  * const * addresses ,  int  address_count )  override  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( address_count  = =  0 )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      return ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    _symbols . reset ( backtrace_symbols ( addresses ,  address_count ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  ResolvedTrace  resolve ( ResolvedTrace  trace )  override  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    char  * filename  =  _symbols [ trace . idx ] ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    char  * funcname  =  filename ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    while  ( * funcname  & &  * funcname  ! =  ' ( ' )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      funcname  + =  1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    trace . object_filename . assign ( filename , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                                 funcname ) ;  // ok even if funcname is the ending
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                                            // \0 (then we assign entire string)
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( * funcname )  {  // if it's not end of string (e.g. from last frame ip==0)
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      funcname  + =  1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      char  * funcname_end  =  funcname ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      while  ( * funcname_end  & &  * funcname_end  ! =  ' ) '  & &  * funcname_end  ! =  ' + ' )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        funcname_end  + =  1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      * funcname_end  =  ' \0 ' ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      trace . object_function  =  this - > demangle ( funcname ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      trace . source . function  =  trace . object_function ;  // we cannot do better.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    return  trace ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								private :  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  details : : handle < char  * * >  _symbols ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								} ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# endif  // BACKWARD_HAS_BACKTRACE_SYMBOL == 1
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# if BACKWARD_HAS_BFD == 1 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								template  < >  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								class  TraceResolverLinuxImpl < trace_resolver_tag : : libbfd >  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    :  public  TraceResolverLinuxBase  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								public :  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  TraceResolverLinuxImpl ( )  :  _bfd_loaded ( false )  { } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  ResolvedTrace  resolve ( ResolvedTrace  trace )  override  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    Dl_info  symbol_info ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // trace.addr is a virtual address in memory pointing to some code.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // Let's try to find from which loaded object it comes from.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // The loaded object can be yourself btw.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( ! dladdr ( trace . addr ,  & symbol_info ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      return  trace ;  // dat broken trace...
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // Now we get in symbol_info:
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // .dli_fname:
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    //		pathname of the shared object that contains the address.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // .dli_fbase:
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    //		where the object is loaded in memory.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // .dli_sname:
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    //		the name of the nearest symbol to trace.addr, we expect a
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    //		function name.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // .dli_saddr:
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    //		the exact address corresponding to .dli_sname.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( symbol_info . dli_sname )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      trace . object_function  =  demangle ( symbol_info . dli_sname ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( ! symbol_info . dli_fname )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      return  trace ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    trace . object_filename  =  resolve_exec_path ( symbol_info ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    bfd_fileobject  * fobj ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // Before rushing to resolution need to ensure the executable
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // file still can be used. For that compare inode numbers of
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // what is stored by the executable's file path, and in the
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // dli_fname, which not necessarily equals to the executable.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // It can be a shared library, or /proc/self/exe, and in the
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // latter case has drawbacks. See the exec path resolution for
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // details. In short - the dli object should be used only as
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // the last resort.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // If inode numbers are equal, it is known dli_fname and the
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // executable file are the same. This is guaranteed by Linux,
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // because if the executable file is changed/deleted, it will
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // be done in a new inode. The old file will be preserved in
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // /proc/self/exe, and may even have inode 0. The latter can
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // happen if the inode was actually reused, and the file was
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // kept only in the main memory.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    //
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    struct  stat  obj_stat ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    struct  stat  dli_stat ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( stat ( trace . object_filename . c_str ( ) ,  & obj_stat )  = =  0  & & 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        stat ( symbol_info . dli_fname ,  & dli_stat )  = =  0  & & 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        obj_stat . st_ino  = =  dli_stat . st_ino )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      // The executable file, and the shared object containing the
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      // address are the same file. Safe to use the original path.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      // this is preferable. Libbfd will search for stripped debug
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      // symbols in the same directory.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      fobj  =  load_object_with_bfd ( trace . object_filename ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    }  else { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      // The original object file was *deleted*! The only hope is
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      // that the debug symbols are either inside the shared
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      // object file, or are in the same directory, and this is
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      // not /proc/self/exe.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      fobj  =  nullptr ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( fobj  = =  nullptr  | |  ! fobj - > handle )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      fobj  =  load_object_with_bfd ( symbol_info . dli_fname ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      if  ( ! fobj - > handle )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return  trace ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    find_sym_result  * details_selected ;  // to be filled.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // trace.addr is the next instruction to be executed after returning
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // from the nested stack frame. In C++ this usually relate to the next
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // statement right after the function call that leaded to a new stack
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // frame. This is not usually what you want to see when printing out a
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // stacktrace...
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    find_sym_result  details_call_site  = 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        find_symbol_details ( fobj ,  trace . addr ,  symbol_info . dli_fbase ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    details_selected  =  & details_call_site ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# if BACKWARD_HAS_UNWIND == 0 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // ...this is why we also try to resolve the symbol that is right
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // before the return address. If we are lucky enough, we will get the
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // line of the function that was called. But if the code is optimized,
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // we might get something absolutely not related since the compiler
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // can reschedule the return address with inline functions and
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // tail-call optimisation (among other things that I don't even know
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // or cannot even dream about with my tiny limited brain).
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    find_sym_result  details_adjusted_call_site  =  find_symbol_details ( 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        fobj ,  ( void  * ) ( uintptr_t ( trace . addr )  -  1 ) ,  symbol_info . dli_fbase ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // In debug mode, we should always get the right thing(TM).
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( details_call_site . found  & &  details_adjusted_call_site . found )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      // Ok, we assume that details_adjusted_call_site is a better estimation.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      details_selected  =  & details_adjusted_call_site ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      trace . addr  =  ( void  * ) ( uintptr_t ( trace . addr )  -  1 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( details_selected  = =  & details_call_site  & &  details_call_site . found )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      // we have to re-resolve the symbol in order to reset some
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      // internal state in BFD... so we can call backtrace_inliners
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      // thereafter...
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      details_call_site  = 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          find_symbol_details ( fobj ,  trace . addr ,  symbol_info . dli_fbase ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# endif  // BACKWARD_HAS_UNWIND
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( details_selected - > found )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      if  ( details_selected - > filename )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        trace . source . filename  =  details_selected - > filename ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      trace . source . line  =  details_selected - > line ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      if  ( details_selected - > funcname )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        // this time we get the name of the function where the code is
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        // located, instead of the function were the address is
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        // located. In short, if the code was inlined, we get the
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        // function correspoding to the code. Else we already got in
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        // trace.function.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        trace . source . function  =  demangle ( details_selected - > funcname ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if  ( ! symbol_info . dli_sname )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          // for the case dladdr failed to find the symbol name of
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          // the function, we might as well try to put something
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          // here.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          trace . object_function  =  trace . source . function ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      // Maybe the source of the trace got inlined inside the function
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      // (trace.source.function). Let's see if we can get all the inlined
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      // calls along the way up to the initial call site.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      trace . inliners  =  backtrace_inliners ( fobj ,  * details_selected ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								#if 0 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if  ( trace . inliners . size ( )  = =  0 )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												// Maybe the trace was not inlined... or maybe it was and we
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												// are lacking the debug information. Let's try to make the
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												// world better and see if we can get the line number of the
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												// function (trace.source.function) now.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												//
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												// We will get the location of where the function start (to be
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												// exact: the first instruction that really start the
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												// function), not where the name of the function is defined.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												// This can be quite far away from the name of the function
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												// btw.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												//
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												// If the source of the function is the same as the source of
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												// the trace, we cannot say if the trace was really inlined or
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												// not.  However, if the filename of the source is different
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												// between the function and the trace... we can declare it as
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												// an inliner.  This is not 100% accurate, but better than
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												// nothing.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												if  ( symbol_info . dli_saddr )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													find_sym_result  details  =  find_symbol_details ( fobj , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
															symbol_info . dli_saddr , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
															symbol_info . dli_fbase ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													if  ( details . found )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
														ResolvedTrace : : SourceLoc  diy_inliner ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
														diy_inliner . line  =  details . line ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
														if  ( details . filename )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
															diy_inliner . filename  =  details . filename ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
														} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
														if  ( details . funcname )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
															diy_inliner . function  =  demangle ( details . funcname ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
														}  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
															diy_inliner . function  =  trace . source . function ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
														} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
														if  ( diy_inliner  ! =  trace . source )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
															trace . inliners . push_back ( diy_inliner ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
														} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
													} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# endif 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    return  trace ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								private :  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  bool  _bfd_loaded ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  typedef  details : : handle < bfd  * , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                          details : : deleter < bfd_boolean ,  bfd  * ,  & bfd_close >  > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      bfd_handle_t ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  typedef  details : : handle < asymbol  * * >  bfd_symtab_t ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  struct  bfd_fileobject  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    bfd_handle_t  handle ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    bfd_vma  base_addr ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    bfd_symtab_t  symtab ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    bfd_symtab_t  dynamic_symtab ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  } ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  typedef  details : : hashtable < std : : string ,  bfd_fileobject > : : type  fobj_bfd_map_t ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  fobj_bfd_map_t  _fobj_bfd_map ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  bfd_fileobject  * load_object_with_bfd ( const  std : : string  & filename_object )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    using  namespace  details ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( ! _bfd_loaded )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      using  namespace  details ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      bfd_init ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      _bfd_loaded  =  true ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    fobj_bfd_map_t : : iterator  it  =  _fobj_bfd_map . find ( filename_object ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( it  ! =  _fobj_bfd_map . end ( ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      return  & it - > second ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // this new object is empty for now.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    bfd_fileobject  * r  =  & _fobj_bfd_map [ filename_object ] ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // we do the work temporary in this one;
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    bfd_handle_t  bfd_handle ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    int  fd  =  open ( filename_object . c_str ( ) ,  O_RDONLY ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    bfd_handle . reset ( bfd_fdopenr ( filename_object . c_str ( ) ,  " default " ,  fd ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( ! bfd_handle )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      close ( fd ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      return  r ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( ! bfd_check_format ( bfd_handle . get ( ) ,  bfd_object ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      return  r ;  // not an object? You lose.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( ( bfd_get_file_flags ( bfd_handle . get ( ) )  &  HAS_SYMS )  = =  0 )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      return  r ;  // that's what happen when you forget to compile in debug.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    ssize_t  symtab_storage_size  =  bfd_get_symtab_upper_bound ( bfd_handle . get ( ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    ssize_t  dyn_symtab_storage_size  = 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        bfd_get_dynamic_symtab_upper_bound ( bfd_handle . get ( ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( symtab_storage_size  < =  0  & &  dyn_symtab_storage_size  < =  0 )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      return  r ;  // weird, is the file is corrupted?
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    bfd_symtab_t  symtab ,  dynamic_symtab ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    ssize_t  symcount  =  0 ,  dyn_symcount  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( symtab_storage_size  >  0 )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      symtab . reset ( static_cast < bfd_symbol  * * > ( 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          malloc ( static_cast < size_t > ( symtab_storage_size ) ) ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      symcount  =  bfd_canonicalize_symtab ( bfd_handle . get ( ) ,  symtab . get ( ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( dyn_symtab_storage_size  >  0 )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      dynamic_symtab . reset ( static_cast < bfd_symbol  * * > ( 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          malloc ( static_cast < size_t > ( dyn_symtab_storage_size ) ) ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      dyn_symcount  =  bfd_canonicalize_dynamic_symtab ( bfd_handle . get ( ) , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                                                     dynamic_symtab . get ( ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( symcount  < =  0  & &  dyn_symcount  < =  0 )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      return  r ;  // damned, that's a stripped file that you got there!
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    r - > handle  =  move ( bfd_handle ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    r - > symtab  =  move ( symtab ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    r - > dynamic_symtab  =  move ( dynamic_symtab ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    return  r ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  struct  find_sym_result  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    bool  found ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    const  char  * filename ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    const  char  * funcname ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    unsigned  int  line ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  } ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  struct  find_sym_context  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    TraceResolverLinuxImpl  * self ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    bfd_fileobject  * fobj ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    void  * addr ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    void  * base_addr ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    find_sym_result  result ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  } ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  find_sym_result  find_symbol_details ( bfd_fileobject  * fobj ,  void  * addr , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                                      void  * base_addr )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    find_sym_context  context ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    context . self  =  this ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    context . fobj  =  fobj ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    context . addr  =  addr ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    context . base_addr  =  base_addr ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    context . result . found  =  false ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    bfd_map_over_sections ( fobj - > handle . get ( ) ,  & find_in_section_trampoline , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                          static_cast < void  * > ( & context ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    return  context . result ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  static  void  find_in_section_trampoline ( bfd  * ,  asection  * section ,  void  * data )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    find_sym_context  * context  =  static_cast < find_sym_context  * > ( data ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    context - > self - > find_in_section ( 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        reinterpret_cast < bfd_vma > ( context - > addr ) , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        reinterpret_cast < bfd_vma > ( context - > base_addr ) ,  context - > fobj ,  section , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        context - > result ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  void  find_in_section ( bfd_vma  addr ,  bfd_vma  base_addr ,  bfd_fileobject  * fobj , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                       asection  * section ,  find_sym_result  & result )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( result . found ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      return ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# ifdef bfd_get_section_flags 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( ( bfd_get_section_flags ( fobj - > handle . get ( ) ,  section )  &  SEC_ALLOC )  = =  0 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# else 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( ( bfd_section_flags ( section )  &  SEC_ALLOC )  = =  0 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# endif 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      return ;  // a debug section is never loaded automatically.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# ifdef bfd_get_section_vma 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    bfd_vma  sec_addr  =  bfd_get_section_vma ( fobj - > handle . get ( ) ,  section ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# else 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    bfd_vma  sec_addr  =  bfd_section_vma ( section ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# endif 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# ifdef bfd_get_section_size 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    bfd_size_type  size  =  bfd_get_section_size ( section ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# else 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    bfd_size_type  size  =  bfd_section_size ( section ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# endif 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // are we in the boundaries of the section?
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( addr  <  sec_addr  | |  addr  > =  sec_addr  +  size )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      addr  - =  base_addr ;  // oups, a relocated object, lets try again...
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      if  ( addr  <  sec_addr  | |  addr  > =  sec_addr  +  size )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# if defined(__clang__) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# pragma clang diagnostic push 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# pragma clang diagnostic ignored "-Wzero-as-null-pointer-constant" 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# endif 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( ! result . found  & &  fobj - > symtab )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      result . found  =  bfd_find_nearest_line ( 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          fobj - > handle . get ( ) ,  section ,  fobj - > symtab . get ( ) ,  addr  -  sec_addr , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          & result . filename ,  & result . funcname ,  & result . line ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( ! result . found  & &  fobj - > dynamic_symtab )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      result . found  =  bfd_find_nearest_line ( 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          fobj - > handle . get ( ) ,  section ,  fobj - > dynamic_symtab . get ( ) , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          addr  -  sec_addr ,  & result . filename ,  & result . funcname ,  & result . line ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# if defined(__clang__) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# pragma clang diagnostic pop 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# endif 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  ResolvedTrace : : source_locs_t 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  backtrace_inliners ( bfd_fileobject  * fobj ,  find_sym_result  previous_result )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // This function can be called ONLY after a SUCCESSFUL call to
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // find_symbol_details. The state is global to the bfd_handle.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    ResolvedTrace : : source_locs_t  results ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    while  ( previous_result . found )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      find_sym_result  result ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      result . found  =  bfd_find_inliner_info ( fobj - > handle . get ( ) ,  & result . filename , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                                           & result . funcname ,  & result . line ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      if  ( result 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								              . found )  /* and not (
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                            cstrings_eq ( previous_result . filename , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                         result . filename )  and 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                         cstrings_eq ( previous_result . funcname ,  result . funcname ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                            and  result . line  = =  previous_result . line 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                            ) )  */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        ResolvedTrace : : SourceLoc  src_loc ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        src_loc . line  =  result . line ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if  ( result . filename )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          src_loc . filename  =  result . filename ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if  ( result . funcname )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          src_loc . function  =  demangle ( result . funcname ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        results . push_back ( src_loc ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      previous_result  =  result ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    return  results ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  bool  cstrings_eq ( const  char  * a ,  const  char  * b )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( ! a  | |  ! b )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      return  false ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    return  strcmp ( a ,  b )  = =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								} ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# endif  // BACKWARD_HAS_BFD == 1
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# if BACKWARD_HAS_DW == 1 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								template  < >  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								class  TraceResolverLinuxImpl < trace_resolver_tag : : libdw >  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    :  public  TraceResolverLinuxBase  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								public :  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  TraceResolverLinuxImpl ( )  :  _dwfl_handle_initialized ( false )  { } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  ResolvedTrace  resolve ( ResolvedTrace  trace )  override  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    using  namespace  details ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    Dwarf_Addr  trace_addr  =  ( Dwarf_Addr ) trace . addr ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( ! _dwfl_handle_initialized )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      // initialize dwfl...
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      _dwfl_cb . reset ( new  Dwfl_Callbacks ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      _dwfl_cb - > find_elf  =  & dwfl_linux_proc_find_elf ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      _dwfl_cb - > find_debuginfo  =  & dwfl_standard_find_debuginfo ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      _dwfl_cb - > debuginfo_path  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      _dwfl_handle . reset ( dwfl_begin ( _dwfl_cb . get ( ) ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      _dwfl_handle_initialized  =  true ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      if  ( ! _dwfl_handle )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return  trace ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      // ...from the current process.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      dwfl_report_begin ( _dwfl_handle . get ( ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      int  r  =  dwfl_linux_proc_report ( _dwfl_handle . get ( ) ,  getpid ( ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      dwfl_report_end ( _dwfl_handle . get ( ) ,  NULL ,  NULL ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      if  ( r  <  0 )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return  trace ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( ! _dwfl_handle )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      return  trace ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // find the module (binary object) that contains the trace's address.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // This is not using any debug information, but the addresses ranges of
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // all the currently loaded binary object.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    Dwfl_Module  * mod  =  dwfl_addrmodule ( _dwfl_handle . get ( ) ,  trace_addr ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( mod )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      // now that we found it, lets get the name of it, this will be the
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      // full path to the running binary or one of the loaded library.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      const  char  * module_name  =  dwfl_module_info ( mod ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      if  ( module_name )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        trace . object_filename  =  module_name ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      // We also look after the name of the symbol, equal or before this
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      // address. This is found by walking the symtab. We should get the
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      // symbol corresponding to the function (mangled) containing the
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      // address. If the code corresponding to the address was inlined,
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      // this is the name of the out-most inliner function.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      const  char  * sym_name  =  dwfl_module_addrname ( mod ,  trace_addr ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      if  ( sym_name )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        trace . object_function  =  demangle ( sym_name ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // now let's get serious, and find out the source location (file and
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // line number) of the address.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // This function will look in .debug_aranges for the address and map it
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // to the location of the compilation unit DIE in .debug_info and
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // return it.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    Dwarf_Addr  mod_bias  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    Dwarf_Die  * cudie  =  dwfl_module_addrdie ( mod ,  trace_addr ,  & mod_bias ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# if 1 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( ! cudie )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      // Sadly clang does not generate the section .debug_aranges, thus
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      // dwfl_module_addrdie will fail early. Clang doesn't either set
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      // the lowpc/highpc/range info for every compilation unit.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      //
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      // So in order to save the world:
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      // for every compilation unit, we will iterate over every single
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      // DIEs. Normally functions should have a lowpc/highpc/range, which
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      // we will use to infer the compilation unit.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      // note that this is probably badly inefficient.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      while  ( ( cudie  =  dwfl_module_nextcu ( mod ,  cudie ,  & mod_bias ) ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        Dwarf_Die  die_mem ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        Dwarf_Die  * fundie  = 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            find_fundie_by_pc ( cudie ,  trace_addr  -  mod_bias ,  & die_mem ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if  ( fundie )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# endif 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//#define BACKWARD_I_DO_NOT_RECOMMEND_TO_ENABLE_THIS_HORRIBLE_PIECE_OF_CODE
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# ifdef BACKWARD_I_DO_NOT_RECOMMEND_TO_ENABLE_THIS_HORRIBLE_PIECE_OF_CODE 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( ! cudie )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      // If it's still not enough, lets dive deeper in the shit, and try
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      // to save the world again: for every compilation unit, we will
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      // load the corresponding .debug_line section, and see if we can
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      // find our address in it.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      Dwarf_Addr  cfi_bias ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      Dwarf_CFI  * cfi_cache  =  dwfl_module_eh_cfi ( mod ,  & cfi_bias ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      Dwarf_Addr  bias ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      while  ( ( cudie  =  dwfl_module_nextcu ( mod ,  cudie ,  & bias ) ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if  ( dwarf_getsrc_die ( cudie ,  trace_addr  -  bias ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          // ...but if we get a match, it might be a false positive
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          // because our (address - bias) might as well be valid in a
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          // different compilation unit. So we throw our last card on
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          // the table and lookup for the address into the .eh_frame
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          // section.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          handle < Dwarf_Frame  * >  frame ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          dwarf_cfi_addrframe ( cfi_cache ,  trace_addr  -  cfi_bias ,  & frame ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          if  ( frame )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# endif 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( ! cudie )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      return  trace ;  // this time we lost the game :/
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // Now that we have a compilation unit DIE, this function will be able
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // to load the corresponding section in .debug_line (if not already
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // loaded) and hopefully find the source location mapped to our
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // address.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    Dwarf_Line  * srcloc  =  dwarf_getsrc_die ( cudie ,  trace_addr  -  mod_bias ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( srcloc )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      const  char  * srcfile  =  dwarf_linesrc ( srcloc ,  0 ,  0 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      if  ( srcfile )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        trace . source . filename  =  srcfile ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      int  line  =  0 ,  col  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      dwarf_lineno ( srcloc ,  & line ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      dwarf_linecol ( srcloc ,  & col ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      trace . source . line  =  line ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      trace . source . col  =  col ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    deep_first_search_by_pc ( cudie ,  trace_addr  -  mod_bias , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                            inliners_search_cb ( trace ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( trace . source . function . size ( )  = =  0 )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      // fallback.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      trace . source . function  =  trace . object_function ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    return  trace ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								private :  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  typedef  details : : handle < Dwfl  * ,  details : : deleter < void ,  Dwfl  * ,  & dwfl_end >  > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      dwfl_handle_t ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  details : : handle < Dwfl_Callbacks  * ,  details : : default_delete < Dwfl_Callbacks  * >  > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      _dwfl_cb ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  dwfl_handle_t  _dwfl_handle ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  bool  _dwfl_handle_initialized ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  // defined here because in C++98, template function cannot take locally
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  // defined types... grrr.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  struct  inliners_search_cb  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    void  operator ( ) ( Dwarf_Die  * die )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      switch  ( dwarf_tag ( die ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        const  char  * name ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      case  DW_TAG_subprogram : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if  ( ( name  =  dwarf_diename ( die ) ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          trace . source . function  =  name ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      case  DW_TAG_inlined_subroutine : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        ResolvedTrace : : SourceLoc  sloc ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        Dwarf_Attribute  attr_mem ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if  ( ( name  =  dwarf_diename ( die ) ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          sloc . function  =  name ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if  ( ( name  =  die_call_file ( die ) ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          sloc . filename  =  name ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        Dwarf_Word  line  =  0 ,  col  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        dwarf_formudata ( dwarf_attr ( die ,  DW_AT_call_line ,  & attr_mem ) ,  & line ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        dwarf_formudata ( dwarf_attr ( die ,  DW_AT_call_column ,  & attr_mem ) ,  & col ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        sloc . line  =  ( unsigned ) line ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        sloc . col  =  ( unsigned ) col ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        trace . inliners . push_back ( sloc ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      } ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    ResolvedTrace  & trace ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    inliners_search_cb ( ResolvedTrace  & t )  :  trace ( t )  { } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  } ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  static  bool  die_has_pc ( Dwarf_Die  * die ,  Dwarf_Addr  pc )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    Dwarf_Addr  low ,  high ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // continuous range
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( dwarf_hasattr ( die ,  DW_AT_low_pc )  & &  dwarf_hasattr ( die ,  DW_AT_high_pc ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      if  ( dwarf_lowpc ( die ,  & low )  ! =  0 )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return  false ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      if  ( dwarf_highpc ( die ,  & high )  ! =  0 )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        Dwarf_Attribute  attr_mem ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        Dwarf_Attribute  * attr  =  dwarf_attr ( die ,  DW_AT_high_pc ,  & attr_mem ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        Dwarf_Word  value ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if  ( dwarf_formudata ( attr ,  & value )  ! =  0 )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          return  false ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        high  =  low  +  value ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      return  pc  > =  low  & &  pc  <  high ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // non-continuous range.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    Dwarf_Addr  base ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    ptrdiff_t  offset  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    while  ( ( offset  =  dwarf_ranges ( die ,  offset ,  & base ,  & low ,  & high ) )  >  0 )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      if  ( pc  > =  low  & &  pc  <  high )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return  true ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    return  false ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  static  Dwarf_Die  * find_fundie_by_pc ( Dwarf_Die  * parent_die ,  Dwarf_Addr  pc , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                                      Dwarf_Die  * result )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( dwarf_child ( parent_die ,  result )  ! =  0 )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      return  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    Dwarf_Die  * die  =  result ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    do  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      switch  ( dwarf_tag ( die ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      case  DW_TAG_subprogram : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      case  DW_TAG_inlined_subroutine : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if  ( die_has_pc ( die ,  pc ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          return  result ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      } ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      bool  declaration  =  false ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      Dwarf_Attribute  attr_mem ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      dwarf_formflag ( dwarf_attr ( die ,  DW_AT_declaration ,  & attr_mem ) , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                     & declaration ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      if  ( ! declaration )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        // let's be curious and look deeper in the tree,
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        // function are not necessarily at the first level, but
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        // might be nested inside a namespace, structure etc.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        Dwarf_Die  die_mem ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        Dwarf_Die  * indie  =  find_fundie_by_pc ( die ,  pc ,  & die_mem ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if  ( indie )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          * result  =  die_mem ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          return  result ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    }  while  ( dwarf_siblingof ( die ,  result )  = =  0 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    return  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  template  < typename  CB > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  static  bool  deep_first_search_by_pc ( Dwarf_Die  * parent_die ,  Dwarf_Addr  pc , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                                      CB  cb )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    Dwarf_Die  die_mem ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( dwarf_child ( parent_die ,  & die_mem )  ! =  0 )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      return  false ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    bool  branch_has_pc  =  false ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    Dwarf_Die  * die  =  & die_mem ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    do  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      bool  declaration  =  false ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      Dwarf_Attribute  attr_mem ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      dwarf_formflag ( dwarf_attr ( die ,  DW_AT_declaration ,  & attr_mem ) , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                     & declaration ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      if  ( ! declaration )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        // let's be curious and look deeper in the tree, function are
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        // not necessarily at the first level, but might be nested
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        // inside a namespace, structure, a function, an inlined
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        // function etc.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        branch_has_pc  =  deep_first_search_by_pc ( die ,  pc ,  cb ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      if  ( ! branch_has_pc )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        branch_has_pc  =  die_has_pc ( die ,  pc ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      if  ( branch_has_pc )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        cb ( die ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    }  while  ( dwarf_siblingof ( die ,  & die_mem )  = =  0 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    return  branch_has_pc ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  static  const  char  * die_call_file ( Dwarf_Die  * die )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    Dwarf_Attribute  attr_mem ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    Dwarf_Word  file_idx  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    dwarf_formudata ( dwarf_attr ( die ,  DW_AT_call_file ,  & attr_mem ) ,  & file_idx ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( file_idx  = =  0 )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      return  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    Dwarf_Die  die_mem ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    Dwarf_Die  * cudie  =  dwarf_diecu ( die ,  & die_mem ,  0 ,  0 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( ! cudie )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      return  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    Dwarf_Files  * files  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    size_t  nfiles ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    dwarf_getsrcfiles ( cudie ,  & files ,  & nfiles ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( ! files )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      return  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    return  dwarf_filesrc ( files ,  file_idx ,  0 ,  0 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								} ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# endif  // BACKWARD_HAS_DW == 1
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# if BACKWARD_HAS_DWARF == 1 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								template  < >  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								class  TraceResolverLinuxImpl < trace_resolver_tag : : libdwarf >  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    :  public  TraceResolverLinuxBase  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								public :  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  TraceResolverLinuxImpl ( )  :  _dwarf_loaded ( false )  { } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  ResolvedTrace  resolve ( ResolvedTrace  trace )  override  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // trace.addr is a virtual address in memory pointing to some code.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // Let's try to find from which loaded object it comes from.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // The loaded object can be yourself btw.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    Dl_info  symbol_info ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    int  dladdr_result  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# if defined(__GLIBC__) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    link_map  * link_map ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // We request the link map so we can get information about offsets
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    dladdr_result  = 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        dladdr1 ( trace . addr ,  & symbol_info ,  reinterpret_cast < void  * * > ( & link_map ) , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                RTLD_DL_LINKMAP ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# else 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // Android doesn't have dladdr1. Don't use the linker map.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    dladdr_result  =  dladdr ( trace . addr ,  & symbol_info ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# endif 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( ! dladdr_result )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      return  trace ;  // dat broken trace...
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // Now we get in symbol_info:
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // .dli_fname:
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    //      pathname of the shared object that contains the address.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // .dli_fbase:
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    //      where the object is loaded in memory.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // .dli_sname:
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    //      the name of the nearest symbol to trace.addr, we expect a
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    //      function name.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // .dli_saddr:
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    //      the exact address corresponding to .dli_sname.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    //
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // And in link_map:
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // .l_addr:
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    //      difference between the address in the ELF file and the address
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    //      in memory
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // l_name:
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    //      absolute pathname where the object was found
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( symbol_info . dli_sname )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      trace . object_function  =  demangle ( symbol_info . dli_sname ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( ! symbol_info . dli_fname )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      return  trace ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    trace . object_filename  =  resolve_exec_path ( symbol_info ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    dwarf_fileobject  & fobj  =  load_object_with_dwarf ( symbol_info . dli_fname ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( ! fobj . dwarf_handle )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      return  trace ;  // sad, we couldn't load the object :(
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# if defined(__GLIBC__) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // Convert the address to a module relative one by looking at
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // the module's loading address in the link map
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    Dwarf_Addr  address  =  reinterpret_cast < uintptr_t > ( trace . addr )  - 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                         reinterpret_cast < uintptr_t > ( link_map - > l_addr ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# else 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    Dwarf_Addr  address  =  reinterpret_cast < uintptr_t > ( trace . addr ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# endif 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( trace . object_function . empty ( ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      symbol_cache_t : : iterator  it  =  fobj . symbol_cache . lower_bound ( address ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      if  ( it  ! =  fobj . symbol_cache . end ( ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if  ( it - > first  ! =  address )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          if  ( it  ! =  fobj . symbol_cache . begin ( ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            - - it ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        trace . object_function  =  demangle ( it - > second . c_str ( ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // Get the Compilation Unit DIE for the address
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    Dwarf_Die  die  =  find_die ( fobj ,  address ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( ! die )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      return  trace ;  // this time we lost the game :/
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // libdwarf doesn't give us direct access to its objects, it always
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // allocates a copy for the caller. We keep that copy alive in a cache
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // and we deallocate it later when it's no longer required.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    die_cache_entry  & die_object  =  get_die_cache ( fobj ,  die ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( die_object . isEmpty ( ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      return  trace ;  // We have no line section for this DIE
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    die_linemap_t : : iterator  it  =  die_object . line_section . lower_bound ( address ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( it  ! =  die_object . line_section . end ( ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      if  ( it - > first  ! =  address )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if  ( it  = =  die_object . line_section . begin ( ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          // If we are on the first item of the line section
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          // but the address does not match it means that
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          // the address is below the range of the DIE. Give up.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          return  trace ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        }  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          - - it ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    }  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      return  trace ;  // We didn't find the address.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // Get the Dwarf_Line that the address points to and call libdwarf
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // to get source file, line and column info.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    Dwarf_Line  line  =  die_object . line_buffer [ it - > second ] ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    Dwarf_Error  error  =  DW_DLE_NE ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    char  * filename ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( dwarf_linesrc ( line ,  & filename ,  & error )  = =  DW_DLV_OK )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      trace . source . filename  =  std : : string ( filename ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      dwarf_dealloc ( fobj . dwarf_handle . get ( ) ,  filename ,  DW_DLA_STRING ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    Dwarf_Unsigned  number  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( dwarf_lineno ( line ,  & number ,  & error )  = =  DW_DLV_OK )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      trace . source . line  =  number ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    }  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      trace . source . line  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( dwarf_lineoff_b ( line ,  & number ,  & error )  = =  DW_DLV_OK )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      trace . source . col  =  number ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    }  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      trace . source . col  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    std : : vector < std : : string >  namespace_stack ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    deep_first_search_by_pc ( fobj ,  die ,  address ,  namespace_stack , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                            inliners_search_cb ( trace ,  fobj ,  die ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    dwarf_dealloc ( fobj . dwarf_handle . get ( ) ,  die ,  DW_DLA_DIE ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    return  trace ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								public :  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  static  int  close_dwarf ( Dwarf_Debug  dwarf )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    return  dwarf_finish ( dwarf ,  NULL ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								private :  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  bool  _dwarf_loaded ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  typedef  details : : handle < int ,  details : : deleter < int ,  int ,  & : : close >  > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      dwarf_file_t ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  typedef  details : : handle < Elf  * ,  details : : deleter < int ,  Elf  * ,  & elf_end >  > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      dwarf_elf_t ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  typedef  details : : handle < Dwarf_Debug , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                          details : : deleter < int ,  Dwarf_Debug ,  & close_dwarf >  > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      dwarf_handle_t ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  typedef  std : : map < Dwarf_Addr ,  int >  die_linemap_t ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  typedef  std : : map < Dwarf_Off ,  Dwarf_Off >  die_specmap_t ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  struct  die_cache_entry  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    die_specmap_t  spec_section ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    die_linemap_t  line_section ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    Dwarf_Line  * line_buffer ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    Dwarf_Signed  line_count ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    Dwarf_Line_Context  line_context ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    inline  bool  isEmpty ( )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      return  line_buffer  = =  NULL  | |  line_count  = =  0  | |  line_context  = =  NULL  | | 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								             line_section . empty ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    die_cache_entry ( )  :  line_buffer ( 0 ) ,  line_count ( 0 ) ,  line_context ( 0 )  { } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    ~ die_cache_entry ( )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      if  ( line_context )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        dwarf_srclines_dealloc_b ( line_context ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  } ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  typedef  std : : map < Dwarf_Off ,  die_cache_entry >  die_cache_t ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  typedef  std : : map < uintptr_t ,  std : : string >  symbol_cache_t ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  struct  dwarf_fileobject  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    dwarf_file_t  file_handle ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    dwarf_elf_t  elf_handle ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    dwarf_handle_t  dwarf_handle ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    symbol_cache_t  symbol_cache ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // Die cache
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    die_cache_t  die_cache ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    die_cache_entry  * current_cu ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  } ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  typedef  details : : hashtable < std : : string ,  dwarf_fileobject > : : type 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      fobj_dwarf_map_t ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  fobj_dwarf_map_t  _fobj_dwarf_map ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  static  bool  cstrings_eq ( const  char  * a ,  const  char  * b )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( ! a  | |  ! b )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      return  false ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    return  strcmp ( a ,  b )  = =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  dwarf_fileobject  & load_object_with_dwarf ( const  std : : string  & filename_object )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( ! _dwarf_loaded )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      // Set the ELF library operating version
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      // If that fails there's nothing we can do
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      _dwarf_loaded  =  elf_version ( EV_CURRENT )  ! =  EV_NONE ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    fobj_dwarf_map_t : : iterator  it  =  _fobj_dwarf_map . find ( filename_object ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( it  ! =  _fobj_dwarf_map . end ( ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      return  it - > second ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // this new object is empty for now
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    dwarf_fileobject  & r  =  _fobj_dwarf_map [ filename_object ] ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    dwarf_file_t  file_handle ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    file_handle . reset ( open ( filename_object . c_str ( ) ,  O_RDONLY ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( file_handle . get ( )  <  0 )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      return  r ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // Try to get an ELF handle. We need to read the ELF sections
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // because we want to see if there is a .gnu_debuglink section
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // that points to a split debug file
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    dwarf_elf_t  elf_handle ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    elf_handle . reset ( elf_begin ( file_handle . get ( ) ,  ELF_C_READ ,  NULL ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( ! elf_handle )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      return  r ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    const  char  * e_ident  =  elf_getident ( elf_handle . get ( ) ,  0 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( ! e_ident )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      return  r ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // Get the number of sections
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // We use the new APIs as elf_getshnum is deprecated
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    size_t  shdrnum  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( elf_getshdrnum ( elf_handle . get ( ) ,  & shdrnum )  = =  - 1 )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      return  r ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // Get the index to the string section
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    size_t  shdrstrndx  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( elf_getshdrstrndx ( elf_handle . get ( ) ,  & shdrstrndx )  = =  - 1 )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      return  r ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    std : : string  debuglink ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // Iterate through the ELF sections to try to get a gnu_debuglink
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // note and also to cache the symbol table.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // We go the preprocessor way to avoid having to create templated
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // classes or using gelf (which might throw a compiler error if 64 bit
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // is not supported
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# define ELF_GET_DATA(ARCH)                                                     \ 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  Elf_Scn  * elf_section  =  0 ;                                                     \
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  Elf_Data  * elf_data  =  0 ;                                                       \
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  Elf # # ARCH # # _Shdr  * section_header  =  0 ;                                         \
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  Elf_Scn  * symbol_section  =  0 ;                                                  \
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  size_t  symbol_count  =  0 ;                                                      \
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  size_t  symbol_strings  =  0 ;                                                    \
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  Elf # # ARCH # # _Sym  * symbol  =  0 ;                                                  \
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  const  char  * section_name  =  0 ;                                                 \
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                                                                               \
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  while  ( ( elf_section  =  elf_nextscn ( elf_handle . get ( ) ,  elf_section ) )  ! =  NULL )  {  \
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    section_header  =  elf # # ARCH # # _getshdr ( elf_section ) ;                          \
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( section_header  = =  NULL )  {                                               \
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      return  r ;                                                                 \
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    }                                                                           \
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                                                                               \
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( ( section_name  =  elf_strptr ( elf_handle . get ( ) ,  shdrstrndx ,                \
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                                   section_header - > sh_name ) )  = =  NULL )  {         \
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      return  r ;                                                                 \
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    }                                                                           \
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                                                                               \
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( cstrings_eq ( section_name ,  " .gnu_debuglink " ) )  {                          \
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      elf_data  =  elf_getdata ( elf_section ,  NULL ) ;                                \
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      if  ( elf_data  & &  elf_data - > d_size  >  0 )  {                                   \
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        debuglink  =                                                             \
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            std : : string ( reinterpret_cast < const  char  * > ( elf_data - > d_buf ) ) ;       \
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      }                                                                         \
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    }                                                                           \
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                                                                               \
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    switch  ( section_header - > sh_type )  {                                          \
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    case  SHT_SYMTAB :                                                            \
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      symbol_section  =  elf_section ;                                             \
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      symbol_count  =  section_header - > sh_size  /  section_header - > sh_entsize ;      \
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      symbol_strings  =  section_header - > sh_link ;                                 \
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      break ;                                                                    \
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                                                                               \
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    /* We use .dynsyms as a last resort, we prefer .symtab */                   \
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    case  SHT_DYNSYM :                                                            \
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      if  ( ! symbol_section )  {                                                    \
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        symbol_section  =  elf_section ;                                           \
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        symbol_count  =  section_header - > sh_size  /  section_header - > sh_entsize ;    \
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        symbol_strings  =  section_header - > sh_link ;                               \
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      }                                                                         \
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      break ;                                                                    \
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    }                                                                           \
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  }                                                                             \
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                                                                               \
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  if  ( symbol_section  & &  symbol_count  & &  symbol_strings )  {                       \
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    elf_data  =  elf_getdata ( symbol_section ,  NULL ) ;                               \
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    symbol  =  reinterpret_cast < Elf # # ARCH # # _Sym  * > ( elf_data - > d_buf ) ;              \
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    for  ( size_t  i  =  0 ;  i  <  symbol_count ;  + + i )  {                                 \
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      int  type  =  ELF # # ARCH # # _ST_TYPE ( symbol - > st_info ) ;                          \
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      if  ( type  = =  STT_FUNC  & &  symbol - > st_value  >  0 )  {                           \
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        r . symbol_cache [ symbol - > st_value ]  =  std : : string (                         \
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            elf_strptr ( elf_handle . get ( ) ,  symbol_strings ,  symbol - > st_name ) ) ;     \
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      }                                                                         \
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      + + symbol ;                                                                 \
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    }                                                                           \
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( e_ident [ EI_CLASS ]  = =  ELFCLASS32 )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      ELF_GET_DATA ( 32 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    }  else  if  ( e_ident [ EI_CLASS ]  = =  ELFCLASS64 )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      // libelf might have been built without 64 bit support
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# if __LIBELF64 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      ELF_GET_DATA ( 64 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# endif 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( ! debuglink . empty ( ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      // We have a debuglink section! Open an elf instance on that
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      // file instead. If we can't open the file, then return
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      // the elf handle we had already opened.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      dwarf_file_t  debuglink_file ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      debuglink_file . reset ( open ( debuglink . c_str ( ) ,  O_RDONLY ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      if  ( debuglink_file . get ( )  >  0 )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        dwarf_elf_t  debuglink_elf ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        debuglink_elf . reset ( elf_begin ( debuglink_file . get ( ) ,  ELF_C_READ ,  NULL ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        // If we have a valid elf handle, return the new elf handle
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        // and file handle and discard the original ones
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if  ( debuglink_elf )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          elf_handle  =  move ( debuglink_elf ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          file_handle  =  move ( debuglink_file ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // Ok, we have a valid ELF handle, let's try to get debug symbols
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    Dwarf_Debug  dwarf_debug ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    Dwarf_Error  error  =  DW_DLE_NE ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    dwarf_handle_t  dwarf_handle ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    int  dwarf_result  =  dwarf_elf_init ( elf_handle . get ( ) ,  DW_DLC_READ ,  NULL ,  NULL , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                                      & dwarf_debug ,  & error ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // We don't do any special handling for DW_DLV_NO_ENTRY specially.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // If we get an error, or the file doesn't have debug information
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // we just return.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( dwarf_result  ! =  DW_DLV_OK )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      return  r ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    dwarf_handle . reset ( dwarf_debug ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    r . file_handle  =  move ( file_handle ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    r . elf_handle  =  move ( elf_handle ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    r . dwarf_handle  =  move ( dwarf_handle ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    return  r ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  die_cache_entry  & get_die_cache ( dwarf_fileobject  & fobj ,  Dwarf_Die  die )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    Dwarf_Error  error  =  DW_DLE_NE ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // Get the die offset, we use it as the cache key
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    Dwarf_Off  die_offset ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( dwarf_dieoffset ( die ,  & die_offset ,  & error )  ! =  DW_DLV_OK )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      die_offset  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    die_cache_t : : iterator  it  =  fobj . die_cache . find ( die_offset ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( it  ! =  fobj . die_cache . end ( ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      fobj . current_cu  =  & it - > second ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      return  it - > second ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    die_cache_entry  & de  =  fobj . die_cache [ die_offset ] ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    fobj . current_cu  =  & de ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    Dwarf_Addr  line_addr ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    Dwarf_Small  table_count ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // The addresses in the line section are not fully sorted (they might
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // be sorted by block of code belonging to the same file), which makes
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // it necessary to do so before searching is possible.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    //
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // As libdwarf allocates a copy of everything, let's get the contents
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // of the line section and keep it around. We also create a map of
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // program counter to line table indices so we can search by address
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // and get the line buffer index.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    //
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // To make things more difficult, the same address can span more than
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // one line, so we need to keep the index pointing to the first line
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // by using insert instead of the map's [ operator.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // Get the line context for the DIE
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( dwarf_srclines_b ( die ,  0 ,  & table_count ,  & de . line_context ,  & error )  = = 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        DW_DLV_OK )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      // Get the source lines for this line context, to be deallocated
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      // later
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      if  ( dwarf_srclines_from_linecontext ( de . line_context ,  & de . line_buffer , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                                          & de . line_count , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                                          & error )  = =  DW_DLV_OK )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        // Add all the addresses to our map
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        for  ( int  i  =  0 ;  i  <  de . line_count ;  i + + )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          if  ( dwarf_lineaddr ( de . line_buffer [ i ] ,  & line_addr ,  & error )  ! = 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								              DW_DLV_OK )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            line_addr  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          de . line_section . insert ( std : : pair < Dwarf_Addr ,  int > ( line_addr ,  i ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // For each CU, cache the function DIEs that contain the
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // DW_AT_specification attribute. When building with -g3 the function
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // DIEs are separated in declaration and specification, with the
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // declaration containing only the name and parameters and the
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // specification the low/high pc and other compiler attributes.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    //
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // We cache those specifications so we don't skip over the declarations,
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // because they have no pc, and we can do namespace resolution for
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // DWARF function names.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    Dwarf_Debug  dwarf  =  fobj . dwarf_handle . get ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    Dwarf_Die  current_die  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( dwarf_child ( die ,  & current_die ,  & error )  = =  DW_DLV_OK )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      for  ( ; ; )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        Dwarf_Die  sibling_die  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        Dwarf_Half  tag_value ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        dwarf_tag ( current_die ,  & tag_value ,  & error ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if  ( tag_value  = =  DW_TAG_subprogram  | | 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            tag_value  = =  DW_TAG_inlined_subroutine )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          Dwarf_Bool  has_attr  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          if  ( dwarf_hasattr ( current_die ,  DW_AT_specification ,  & has_attr , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                            & error )  = =  DW_DLV_OK )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            if  ( has_attr )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								              Dwarf_Attribute  attr_mem ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								              if  ( dwarf_attr ( current_die ,  DW_AT_specification ,  & attr_mem , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                             & error )  = =  DW_DLV_OK )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                Dwarf_Off  spec_offset  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                if  ( dwarf_formref ( attr_mem ,  & spec_offset ,  & error )  = = 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    DW_DLV_OK )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                  Dwarf_Off  spec_die_offset ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                  if  ( dwarf_dieoffset ( current_die ,  & spec_die_offset ,  & error )  = = 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                      DW_DLV_OK )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    de . spec_section [ spec_offset ]  =  spec_die_offset ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                  } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								              } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								              dwarf_dealloc ( dwarf ,  attr_mem ,  DW_DLA_ATTR ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        int  result  =  dwarf_siblingof ( dwarf ,  current_die ,  & sibling_die ,  & error ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if  ( result  = =  DW_DLV_ERROR )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        }  else  if  ( result  = =  DW_DLV_NO_ENTRY )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if  ( current_die  ! =  die )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          dwarf_dealloc ( dwarf ,  current_die ,  DW_DLA_DIE ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          current_die  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        current_die  =  sibling_die ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    return  de ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  static  Dwarf_Die  get_referenced_die ( Dwarf_Debug  dwarf ,  Dwarf_Die  die , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                                      Dwarf_Half  attr ,  bool  global )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    Dwarf_Error  error  =  DW_DLE_NE ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    Dwarf_Attribute  attr_mem ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    Dwarf_Die  found_die  =  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( dwarf_attr ( die ,  attr ,  & attr_mem ,  & error )  = =  DW_DLV_OK )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      Dwarf_Off  offset ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      int  result  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      if  ( global )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        result  =  dwarf_global_formref ( attr_mem ,  & offset ,  & error ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      }  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        result  =  dwarf_formref ( attr_mem ,  & offset ,  & error ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      if  ( result  = =  DW_DLV_OK )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if  ( dwarf_offdie ( dwarf ,  offset ,  & found_die ,  & error )  ! =  DW_DLV_OK )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          found_die  =  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      dwarf_dealloc ( dwarf ,  attr_mem ,  DW_DLA_ATTR ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    return  found_die ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  static  std : : string  get_referenced_die_name ( Dwarf_Debug  dwarf ,  Dwarf_Die  die , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                                             Dwarf_Half  attr ,  bool  global )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    Dwarf_Error  error  =  DW_DLE_NE ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    std : : string  value ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    Dwarf_Die  found_die  =  get_referenced_die ( dwarf ,  die ,  attr ,  global ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( found_die )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      char  * name ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      if  ( dwarf_diename ( found_die ,  & name ,  & error )  = =  DW_DLV_OK )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if  ( name )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          value  =  std : : string ( name ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        dwarf_dealloc ( dwarf ,  name ,  DW_DLA_STRING ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      dwarf_dealloc ( dwarf ,  found_die ,  DW_DLA_DIE ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    return  value ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  // Returns a spec DIE linked to the passed one. The caller should
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  // deallocate the DIE
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  static  Dwarf_Die  get_spec_die ( dwarf_fileobject  & fobj ,  Dwarf_Die  die )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    Dwarf_Debug  dwarf  =  fobj . dwarf_handle . get ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    Dwarf_Error  error  =  DW_DLE_NE ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    Dwarf_Off  die_offset ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( fobj . current_cu  & & 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        dwarf_die_CU_offset ( die ,  & die_offset ,  & error )  = =  DW_DLV_OK )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      die_specmap_t : : iterator  it  = 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          fobj . current_cu - > spec_section . find ( die_offset ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      // If we have a DIE that completes the current one, check if
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      // that one has the pc we are looking for
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      if  ( it  ! =  fobj . current_cu - > spec_section . end ( ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        Dwarf_Die  spec_die  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if  ( dwarf_offdie ( dwarf ,  it - > second ,  & spec_die ,  & error )  = =  DW_DLV_OK )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          return  spec_die ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // Maybe we have an abstract origin DIE with the function information?
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    return  get_referenced_die ( fobj . dwarf_handle . get ( ) ,  die , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                              DW_AT_abstract_origin ,  true ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  static  bool  die_has_pc ( dwarf_fileobject  & fobj ,  Dwarf_Die  die ,  Dwarf_Addr  pc )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    Dwarf_Addr  low_pc  =  0 ,  high_pc  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    Dwarf_Half  high_pc_form  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    Dwarf_Form_Class  return_class ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    Dwarf_Error  error  =  DW_DLE_NE ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    Dwarf_Debug  dwarf  =  fobj . dwarf_handle . get ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    bool  has_lowpc  =  false ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    bool  has_highpc  =  false ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    bool  has_ranges  =  false ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( dwarf_lowpc ( die ,  & low_pc ,  & error )  = =  DW_DLV_OK )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      // If we have a low_pc check if there is a high pc.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      // If we don't have a high pc this might mean we have a base
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      // address for the ranges list or just an address.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      has_lowpc  =  true ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      if  ( dwarf_highpc_b ( die ,  & high_pc ,  & high_pc_form ,  & return_class ,  & error )  = = 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          DW_DLV_OK )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        // We do have a high pc. In DWARF 4+ this is an offset from the
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        // low pc, but in earlier versions it's an absolute address.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        has_highpc  =  true ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        // In DWARF 2/3 this would be a DW_FORM_CLASS_ADDRESS
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if  ( return_class  = =  DW_FORM_CLASS_CONSTANT )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          high_pc  =  low_pc  +  high_pc ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        // We have low and high pc, check if our address
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        // is in that range
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return  pc  > =  low_pc  & &  pc  <  high_pc ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    }  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      // Reset the low_pc, in case dwarf_lowpc failing set it to some
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      // undefined value.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      low_pc  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // Check if DW_AT_ranges is present and search for the PC in the
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // returned ranges list. We always add the low_pc, as it not set it will
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // be 0, in case we had a DW_AT_low_pc and DW_AT_ranges pair
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    bool  result  =  false ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    Dwarf_Attribute  attr ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( dwarf_attr ( die ,  DW_AT_ranges ,  & attr ,  & error )  = =  DW_DLV_OK )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      Dwarf_Off  offset ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      if  ( dwarf_global_formref ( attr ,  & offset ,  & error )  = =  DW_DLV_OK )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        Dwarf_Ranges  * ranges ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        Dwarf_Signed  ranges_count  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        Dwarf_Unsigned  byte_count  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if  ( dwarf_get_ranges_a ( dwarf ,  offset ,  die ,  & ranges ,  & ranges_count , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                               & byte_count ,  & error )  = =  DW_DLV_OK )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          has_ranges  =  ranges_count  ! =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          for  ( int  i  =  0 ;  i  <  ranges_count ;  i + + )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            if  ( ranges [ i ] . dwr_addr1  ! =  0  & & 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                pc  > =  ranges [ i ] . dwr_addr1  +  low_pc  & & 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                pc  <  ranges [ i ] . dwr_addr2  +  low_pc )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								              result  =  true ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								              break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          dwarf_ranges_dealloc ( dwarf ,  ranges ,  ranges_count ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // Last attempt. We might have a single address set as low_pc.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( ! result  & &  low_pc  ! =  0  & &  pc  = =  low_pc )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      result  =  true ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // If we don't have lowpc, highpc and ranges maybe this DIE is a
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // declaration that relies on a DW_AT_specification DIE that happens
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // later. Use the specification cache we filled when we loaded this CU.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( ! result  & &  ( ! has_lowpc  & &  ! has_highpc  & &  ! has_ranges ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      Dwarf_Die  spec_die  =  get_spec_die ( fobj ,  die ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      if  ( spec_die )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        result  =  die_has_pc ( fobj ,  spec_die ,  pc ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        dwarf_dealloc ( dwarf ,  spec_die ,  DW_DLA_DIE ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    return  result ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  static  void  get_type ( Dwarf_Debug  dwarf ,  Dwarf_Die  die ,  std : : string  & type )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    Dwarf_Error  error  =  DW_DLE_NE ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    Dwarf_Die  child  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( dwarf_child ( die ,  & child ,  & error )  = =  DW_DLV_OK )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      get_type ( dwarf ,  child ,  type ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( child )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      type . insert ( 0 ,  " :: " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      dwarf_dealloc ( dwarf ,  child ,  DW_DLA_DIE ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    char  * name ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( dwarf_diename ( die ,  & name ,  & error )  = =  DW_DLV_OK )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      type . insert ( 0 ,  std : : string ( name ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      dwarf_dealloc ( dwarf ,  name ,  DW_DLA_STRING ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    }  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      type . insert ( 0 ,  " <unknown> " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  static  std : : string  get_type_by_signature ( Dwarf_Debug  dwarf ,  Dwarf_Die  die )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    Dwarf_Error  error  =  DW_DLE_NE ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    Dwarf_Sig8  signature ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    Dwarf_Bool  has_attr  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( dwarf_hasattr ( die ,  DW_AT_signature ,  & has_attr ,  & error )  = =  DW_DLV_OK )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      if  ( has_attr )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        Dwarf_Attribute  attr_mem ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if  ( dwarf_attr ( die ,  DW_AT_signature ,  & attr_mem ,  & error )  = =  DW_DLV_OK )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          if  ( dwarf_formsig8 ( attr_mem ,  & signature ,  & error )  ! =  DW_DLV_OK )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            return  std : : string ( " <no type signature> " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        dwarf_dealloc ( dwarf ,  attr_mem ,  DW_DLA_ATTR ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    Dwarf_Unsigned  next_cu_header ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    Dwarf_Sig8  tu_signature ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    std : : string  result ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    bool  found  =  false ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    while  ( dwarf_next_cu_header_d ( dwarf ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  & tu_signature ,  0 , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                                  & next_cu_header ,  0 ,  & error )  = =  DW_DLV_OK )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      if  ( strncmp ( signature . signature ,  tu_signature . signature ,  8 )  = =  0 )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        Dwarf_Die  type_cu_die  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if  ( dwarf_siblingof_b ( dwarf ,  0 ,  0 ,  & type_cu_die ,  & error )  = =  DW_DLV_OK )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          Dwarf_Die  child_die  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          if  ( dwarf_child ( type_cu_die ,  & child_die ,  & error )  = =  DW_DLV_OK )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            get_type ( dwarf ,  child_die ,  result ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            found  =  ! result . empty ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            dwarf_dealloc ( dwarf ,  child_die ,  DW_DLA_DIE ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          dwarf_dealloc ( dwarf ,  type_cu_die ,  DW_DLA_DIE ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( found )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      while  ( dwarf_next_cu_header_d ( dwarf ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                                    & next_cu_header ,  0 ,  & error )  = =  DW_DLV_OK )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        // Reset the cu header state. Unfortunately, libdwarf's
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        // next_cu_header API keeps its own iterator per Dwarf_Debug
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        // that can't be reset. We need to keep fetching elements until
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        // the end.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    }  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      // If we couldn't resolve the type just print out the signature
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      std : : ostringstream  string_stream ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      string_stream  < <  " <0x "  < <  std : : hex  < <  std : : setfill ( ' 0 ' ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      for  ( int  i  =  0 ;  i  <  8 ;  + + i )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        string_stream  < <  std : : setw ( 2 )  < <  std : : hex 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                      < <  ( int ) ( unsigned  char ) ( signature . signature [ i ] ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      string_stream  < <  " > " ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      result  =  string_stream . str ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    return  result ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  struct  type_context_t  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    bool  is_const ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    bool  is_typedef ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    bool  has_type ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    bool  has_name ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    std : : string  text ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    type_context_t ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        :  is_const ( false ) ,  is_typedef ( false ) ,  has_type ( false ) ,  has_name ( false )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  } ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  // Types are resolved from right to left: we get the variable name first
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  // and then all specifiers (like const or pointer) in a chain of DW_AT_type
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  // DIEs. Call this function recursively until we get a complete type
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  // string.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  static  void  set_parameter_string ( dwarf_fileobject  & fobj ,  Dwarf_Die  die , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                                   type_context_t  & context )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    char  * name ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    Dwarf_Error  error  =  DW_DLE_NE ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // typedefs contain also the base type, so we skip it and only
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // print the typedef name
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( ! context . is_typedef )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      if  ( dwarf_diename ( die ,  & name ,  & error )  = =  DW_DLV_OK )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if  ( ! context . text . empty ( ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          context . text . insert ( 0 ,  "   " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        context . text . insert ( 0 ,  std : : string ( name ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        dwarf_dealloc ( fobj . dwarf_handle . get ( ) ,  name ,  DW_DLA_STRING ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    }  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      context . is_typedef  =  false ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      context . has_type  =  true ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      if  ( context . is_const )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        context . text . insert ( 0 ,  " const  " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        context . is_const  =  false ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    bool  next_type_is_const  =  false ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    bool  is_keyword  =  true ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    Dwarf_Half  tag  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    Dwarf_Bool  has_attr  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( dwarf_tag ( die ,  & tag ,  & error )  = =  DW_DLV_OK )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      switch  ( tag )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      case  DW_TAG_structure_type : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      case  DW_TAG_union_type : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      case  DW_TAG_class_type : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      case  DW_TAG_enumeration_type : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        context . has_type  =  true ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if  ( dwarf_hasattr ( die ,  DW_AT_signature ,  & has_attr ,  & error )  = = 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            DW_DLV_OK )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          // If we have a signature it means the type is defined
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          // in .debug_types, so we need to load the DIE pointed
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          // at by the signature and resolve it
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          if  ( has_attr )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            std : : string  type  = 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                get_type_by_signature ( fobj . dwarf_handle . get ( ) ,  die ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            if  ( context . is_const ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								              type . insert ( 0 ,  " const  " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            if  ( ! context . text . empty ( ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								              context . text . insert ( 0 ,  "   " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            context . text . insert ( 0 ,  type ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          // Treat enums like typedefs, and skip printing its
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          // base type
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          context . is_typedef  =  ( tag  = =  DW_TAG_enumeration_type ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      case  DW_TAG_const_type : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        next_type_is_const  =  true ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      case  DW_TAG_pointer_type : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        context . text . insert ( 0 ,  " * " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      case  DW_TAG_reference_type : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        context . text . insert ( 0 ,  " & " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      case  DW_TAG_restrict_type : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        context . text . insert ( 0 ,  " restrict  " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      case  DW_TAG_rvalue_reference_type : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        context . text . insert ( 0 ,  " && " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      case  DW_TAG_volatile_type : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        context . text . insert ( 0 ,  " volatile  " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      case  DW_TAG_typedef : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        // Propagate the const-ness to the next type
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        // as typedefs are linked to its base type
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        next_type_is_const  =  context . is_const ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        context . is_typedef  =  true ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        context . has_type  =  true ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      case  DW_TAG_base_type : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        context . has_type  =  true ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      case  DW_TAG_formal_parameter : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        context . has_name  =  true ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      default : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        is_keyword  =  false ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( ! is_keyword  & &  context . is_const )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      context . text . insert ( 0 ,  " const  " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    context . is_const  =  next_type_is_const ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    Dwarf_Die  ref  = 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        get_referenced_die ( fobj . dwarf_handle . get ( ) ,  die ,  DW_AT_type ,  true ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( ref )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      set_parameter_string ( fobj ,  ref ,  context ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      dwarf_dealloc ( fobj . dwarf_handle . get ( ) ,  ref ,  DW_DLA_DIE ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( ! context . has_type  & &  context . has_name )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      context . text . insert ( 0 ,  " void  " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      context . has_type  =  true ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  // Resolve the function return type and parameters
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  static  void  set_function_parameters ( std : : string  & function_name , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                                      std : : vector < std : : string >  & ns , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                                      dwarf_fileobject  & fobj ,  Dwarf_Die  die )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    Dwarf_Debug  dwarf  =  fobj . dwarf_handle . get ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    Dwarf_Error  error  =  DW_DLE_NE ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    Dwarf_Die  current_die  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    std : : string  parameters ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    bool  has_spec  =  true ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // Check if we have a spec DIE. If we do we use it as it contains
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // more information, like parameter names.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    Dwarf_Die  spec_die  =  get_spec_die ( fobj ,  die ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( ! spec_die )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      has_spec  =  false ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      spec_die  =  die ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    std : : vector < std : : string > : : const_iterator  it  =  ns . begin ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    std : : string  ns_name ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    for  ( it  =  ns . begin ( ) ;  it  <  ns . end ( ) ;  + + it )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      ns_name . append ( * it ) . append ( " :: " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( ! ns_name . empty ( ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      function_name . insert ( 0 ,  ns_name ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // See if we have a function return type. It can be either on the
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // current die or in its spec one (usually true for inlined functions)
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    std : : string  return_type  = 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        get_referenced_die_name ( dwarf ,  die ,  DW_AT_type ,  true ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( return_type . empty ( ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      return_type  =  get_referenced_die_name ( dwarf ,  spec_die ,  DW_AT_type ,  true ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( ! return_type . empty ( ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      return_type . append ( "   " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      function_name . insert ( 0 ,  return_type ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( dwarf_child ( spec_die ,  & current_die ,  & error )  = =  DW_DLV_OK )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      for  ( ; ; )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        Dwarf_Die  sibling_die  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        Dwarf_Half  tag_value ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        dwarf_tag ( current_die ,  & tag_value ,  & error ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if  ( tag_value  = =  DW_TAG_formal_parameter )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          // Ignore artificial (ie, compiler generated) parameters
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          bool  is_artificial  =  false ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          Dwarf_Attribute  attr_mem ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          if  ( dwarf_attr ( current_die ,  DW_AT_artificial ,  & attr_mem ,  & error )  = = 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								              DW_DLV_OK )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            Dwarf_Bool  flag  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            if  ( dwarf_formflag ( attr_mem ,  & flag ,  & error )  = =  DW_DLV_OK )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								              is_artificial  =  flag  ! =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            dwarf_dealloc ( dwarf ,  attr_mem ,  DW_DLA_ATTR ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          if  ( ! is_artificial )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            type_context_t  context ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            set_parameter_string ( fobj ,  current_die ,  context ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            if  ( parameters . empty ( ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								              parameters . append ( " ( " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            }  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								              parameters . append ( " ,  " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            parameters . append ( context . text ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        int  result  =  dwarf_siblingof ( dwarf ,  current_die ,  & sibling_die ,  & error ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if  ( result  = =  DW_DLV_ERROR )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        }  else  if  ( result  = =  DW_DLV_NO_ENTRY )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if  ( current_die  ! =  die )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          dwarf_dealloc ( dwarf ,  current_die ,  DW_DLA_DIE ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          current_die  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        current_die  =  sibling_die ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( parameters . empty ( ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      parameters  =  " ( " ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    parameters . append ( " ) " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // If we got a spec DIE we need to deallocate it
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( has_spec ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      dwarf_dealloc ( dwarf ,  spec_die ,  DW_DLA_DIE ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    function_name . append ( parameters ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  // defined here because in C++98, template function cannot take locally
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  // defined types... grrr.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  struct  inliners_search_cb  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    void  operator ( ) ( Dwarf_Die  die ,  std : : vector < std : : string >  & ns )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      Dwarf_Error  error  =  DW_DLE_NE ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      Dwarf_Half  tag_value ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      Dwarf_Attribute  attr_mem ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      Dwarf_Debug  dwarf  =  fobj . dwarf_handle . get ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      dwarf_tag ( die ,  & tag_value ,  & error ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      switch  ( tag_value )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        char  * name ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      case  DW_TAG_subprogram : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if  ( ! trace . source . function . empty ( ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if  ( dwarf_diename ( die ,  & name ,  & error )  = =  DW_DLV_OK )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          trace . source . function  =  std : : string ( name ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          dwarf_dealloc ( dwarf ,  name ,  DW_DLA_STRING ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        }  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          // We don't have a function name in this DIE.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          // Check if there is a referenced non-defining
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          // declaration.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          trace . source . function  = 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								              get_referenced_die_name ( dwarf ,  die ,  DW_AT_abstract_origin ,  true ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          if  ( trace . source . function . empty ( ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            trace . source . function  = 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                get_referenced_die_name ( dwarf ,  die ,  DW_AT_specification ,  true ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        // Append the function parameters, if available
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        set_function_parameters ( trace . source . function ,  ns ,  fobj ,  die ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        // If the object function name is empty, it's possible that
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        // there is no dynamic symbol table (maybe the executable
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        // was stripped or not built with -rdynamic). See if we have
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        // a DWARF linkage name to use instead. We try both
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        // linkage_name and MIPS_linkage_name because the MIPS tag
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        // was the unofficial one until it was adopted in DWARF4.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        // Old gcc versions generate MIPS_linkage_name
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if  ( trace . object_function . empty ( ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          details : : demangler  demangler ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          if  ( dwarf_attr ( die ,  DW_AT_linkage_name ,  & attr_mem ,  & error )  ! = 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								              DW_DLV_OK )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            if  ( dwarf_attr ( die ,  DW_AT_MIPS_linkage_name ,  & attr_mem ,  & error )  ! = 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                DW_DLV_OK )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								              break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          char  * linkage ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          if  ( dwarf_formstring ( attr_mem ,  & linkage ,  & error )  = =  DW_DLV_OK )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            trace . object_function  =  demangler . demangle ( linkage ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            dwarf_dealloc ( dwarf ,  linkage ,  DW_DLA_STRING ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          dwarf_dealloc ( dwarf ,  attr_mem ,  DW_DLA_ATTR ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      case  DW_TAG_inlined_subroutine : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        ResolvedTrace : : SourceLoc  sloc ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if  ( dwarf_diename ( die ,  & name ,  & error )  = =  DW_DLV_OK )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          sloc . function  =  std : : string ( name ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          dwarf_dealloc ( dwarf ,  name ,  DW_DLA_STRING ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        }  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          // We don't have a name for this inlined DIE, it could
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          // be that there is an abstract origin instead.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          // Get the DW_AT_abstract_origin value, which is a
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          // reference to the source DIE and try to get its name
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          sloc . function  = 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								              get_referenced_die_name ( dwarf ,  die ,  DW_AT_abstract_origin ,  true ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        set_function_parameters ( sloc . function ,  ns ,  fobj ,  die ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        std : : string  file  =  die_call_file ( dwarf ,  die ,  cu_die ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if  ( ! file . empty ( ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          sloc . filename  =  file ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        Dwarf_Unsigned  number  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if  ( dwarf_attr ( die ,  DW_AT_call_line ,  & attr_mem ,  & error )  = =  DW_DLV_OK )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          if  ( dwarf_formudata ( attr_mem ,  & number ,  & error )  = =  DW_DLV_OK )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            sloc . line  =  number ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          dwarf_dealloc ( dwarf ,  attr_mem ,  DW_DLA_ATTR ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if  ( dwarf_attr ( die ,  DW_AT_call_column ,  & attr_mem ,  & error )  = = 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            DW_DLV_OK )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          if  ( dwarf_formudata ( attr_mem ,  & number ,  & error )  = =  DW_DLV_OK )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            sloc . col  =  number ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          dwarf_dealloc ( dwarf ,  attr_mem ,  DW_DLA_ATTR ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        trace . inliners . push_back ( sloc ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      } ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    ResolvedTrace  & trace ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    dwarf_fileobject  & fobj ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    Dwarf_Die  cu_die ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    inliners_search_cb ( ResolvedTrace  & t ,  dwarf_fileobject  & f ,  Dwarf_Die  c ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        :  trace ( t ) ,  fobj ( f ) ,  cu_die ( c )  { } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  } ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  static  Dwarf_Die  find_fundie_by_pc ( dwarf_fileobject  & fobj , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                                     Dwarf_Die  parent_die ,  Dwarf_Addr  pc , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                                     Dwarf_Die  result )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    Dwarf_Die  current_die  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    Dwarf_Error  error  =  DW_DLE_NE ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    Dwarf_Debug  dwarf  =  fobj . dwarf_handle . get ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( dwarf_child ( parent_die ,  & current_die ,  & error )  ! =  DW_DLV_OK )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      return  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    for  ( ; ; )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      Dwarf_Die  sibling_die  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      Dwarf_Half  tag_value ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      dwarf_tag ( current_die ,  & tag_value ,  & error ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      switch  ( tag_value )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      case  DW_TAG_subprogram : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      case  DW_TAG_inlined_subroutine : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if  ( die_has_pc ( fobj ,  current_die ,  pc ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          return  current_die ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      } ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      bool  declaration  =  false ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      Dwarf_Attribute  attr_mem ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      if  ( dwarf_attr ( current_die ,  DW_AT_declaration ,  & attr_mem ,  & error )  = = 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          DW_DLV_OK )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        Dwarf_Bool  flag  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if  ( dwarf_formflag ( attr_mem ,  & flag ,  & error )  = =  DW_DLV_OK )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          declaration  =  flag  ! =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        dwarf_dealloc ( dwarf ,  attr_mem ,  DW_DLA_ATTR ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      if  ( ! declaration )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        // let's be curious and look deeper in the tree, functions are
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        // not necessarily at the first level, but might be nested
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        // inside a namespace, structure, a function, an inlined
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        // function etc.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        Dwarf_Die  die_mem  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        Dwarf_Die  indie  =  find_fundie_by_pc ( fobj ,  current_die ,  pc ,  die_mem ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if  ( indie )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          result  =  die_mem ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          return  result ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      int  res  =  dwarf_siblingof ( dwarf ,  current_die ,  & sibling_die ,  & error ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      if  ( res  = =  DW_DLV_ERROR )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      }  else  if  ( res  = =  DW_DLV_NO_ENTRY )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      if  ( current_die  ! =  parent_die )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        dwarf_dealloc ( dwarf ,  current_die ,  DW_DLA_DIE ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        current_die  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      current_die  =  sibling_die ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    return  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  template  < typename  CB > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  static  bool  deep_first_search_by_pc ( dwarf_fileobject  & fobj , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                                      Dwarf_Die  parent_die ,  Dwarf_Addr  pc , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                                      std : : vector < std : : string >  & ns ,  CB  cb )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    Dwarf_Die  current_die  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    Dwarf_Debug  dwarf  =  fobj . dwarf_handle . get ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    Dwarf_Error  error  =  DW_DLE_NE ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( dwarf_child ( parent_die ,  & current_die ,  & error )  ! =  DW_DLV_OK )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      return  false ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    bool  branch_has_pc  =  false ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    bool  has_namespace  =  false ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    for  ( ; ; )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      Dwarf_Die  sibling_die  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      Dwarf_Half  tag ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      if  ( dwarf_tag ( current_die ,  & tag ,  & error )  = =  DW_DLV_OK )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if  ( tag  = =  DW_TAG_namespace  | |  tag  = =  DW_TAG_class_type )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          char  * ns_name  =  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          if  ( dwarf_diename ( current_die ,  & ns_name ,  & error )  = =  DW_DLV_OK )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            if  ( ns_name )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								              ns . push_back ( std : : string ( ns_name ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            }  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								              ns . push_back ( " <unknown> " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            dwarf_dealloc ( dwarf ,  ns_name ,  DW_DLA_STRING ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          }  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            ns . push_back ( " <unknown> " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          has_namespace  =  true ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      bool  declaration  =  false ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      Dwarf_Attribute  attr_mem ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      if  ( tag  ! =  DW_TAG_class_type  & & 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          dwarf_attr ( current_die ,  DW_AT_declaration ,  & attr_mem ,  & error )  = = 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								              DW_DLV_OK )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        Dwarf_Bool  flag  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if  ( dwarf_formflag ( attr_mem ,  & flag ,  & error )  = =  DW_DLV_OK )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          declaration  =  flag  ! =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        dwarf_dealloc ( dwarf ,  attr_mem ,  DW_DLA_ATTR ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      if  ( ! declaration )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        // let's be curious and look deeper in the tree, function are
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        // not necessarily at the first level, but might be nested
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        // inside a namespace, structure, a function, an inlined
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        // function etc.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        branch_has_pc  =  deep_first_search_by_pc ( fobj ,  current_die ,  pc ,  ns ,  cb ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      if  ( ! branch_has_pc )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        branch_has_pc  =  die_has_pc ( fobj ,  current_die ,  pc ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      if  ( branch_has_pc )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        cb ( current_die ,  ns ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      int  result  =  dwarf_siblingof ( dwarf ,  current_die ,  & sibling_die ,  & error ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      if  ( result  = =  DW_DLV_ERROR )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return  false ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      }  else  if  ( result  = =  DW_DLV_NO_ENTRY )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      if  ( current_die  ! =  parent_die )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        dwarf_dealloc ( dwarf ,  current_die ,  DW_DLA_DIE ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        current_die  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      if  ( has_namespace )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        has_namespace  =  false ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        ns . pop_back ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      current_die  =  sibling_die ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( has_namespace )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      ns . pop_back ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    return  branch_has_pc ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  static  std : : string  die_call_file ( Dwarf_Debug  dwarf ,  Dwarf_Die  die , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                                   Dwarf_Die  cu_die )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    Dwarf_Attribute  attr_mem ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    Dwarf_Error  error  =  DW_DLE_NE ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    Dwarf_Unsigned  file_index ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    std : : string  file ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( dwarf_attr ( die ,  DW_AT_call_file ,  & attr_mem ,  & error )  = =  DW_DLV_OK )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      if  ( dwarf_formudata ( attr_mem ,  & file_index ,  & error )  ! =  DW_DLV_OK )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        file_index  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      dwarf_dealloc ( dwarf ,  attr_mem ,  DW_DLA_ATTR ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      if  ( file_index  = =  0 )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return  file ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      char  * * srcfiles  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      Dwarf_Signed  file_count  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      if  ( dwarf_srcfiles ( cu_die ,  & srcfiles ,  & file_count ,  & error )  = =  DW_DLV_OK )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if  ( file_count  >  0  & &  file_index  < =  static_cast < Dwarf_Unsigned > ( file_count ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          file  =  std : : string ( srcfiles [ file_index  -  1 ] ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        // Deallocate all strings!
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        for  ( int  i  =  0 ;  i  <  file_count ;  + + i )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          dwarf_dealloc ( dwarf ,  srcfiles [ i ] ,  DW_DLA_STRING ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        dwarf_dealloc ( dwarf ,  srcfiles ,  DW_DLA_LIST ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    return  file ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  Dwarf_Die  find_die ( dwarf_fileobject  & fobj ,  Dwarf_Addr  addr )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // Let's get to work! First see if we have a debug_aranges section so
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // we can speed up the search
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    Dwarf_Debug  dwarf  =  fobj . dwarf_handle . get ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    Dwarf_Error  error  =  DW_DLE_NE ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    Dwarf_Arange  * aranges ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    Dwarf_Signed  arange_count ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    Dwarf_Die  returnDie ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    bool  found  =  false ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( dwarf_get_aranges ( dwarf ,  & aranges ,  & arange_count ,  & error )  ! = 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        DW_DLV_OK )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      aranges  =  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( aranges )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      // We have aranges. Get the one where our address is.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      Dwarf_Arange  arange ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      if  ( dwarf_get_arange ( aranges ,  arange_count ,  addr ,  & arange ,  & error )  = = 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          DW_DLV_OK )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        // We found our address. Get the compilation-unit DIE offset
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        // represented by the given address range.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        Dwarf_Off  cu_die_offset ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if  ( dwarf_get_cu_die_offset ( arange ,  & cu_die_offset ,  & error )  = = 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            DW_DLV_OK )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          // Get the DIE at the offset returned by the aranges search.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          // We set is_info to 1 to specify that the offset is from
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          // the .debug_info section (and not .debug_types)
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          int  dwarf_result  = 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								              dwarf_offdie_b ( dwarf ,  cu_die_offset ,  1 ,  & returnDie ,  & error ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          found  =  dwarf_result  = =  DW_DLV_OK ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        dwarf_dealloc ( dwarf ,  arange ,  DW_DLA_ARANGE ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( found ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      return  returnDie ;  // The caller is responsible for freeing the die
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // The search for aranges failed. Try to find our address by scanning
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // all compilation units.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    Dwarf_Unsigned  next_cu_header ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    Dwarf_Half  tag  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    returnDie  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    while  ( ! found  & & 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								           dwarf_next_cu_header_d ( dwarf ,  1 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                                  & next_cu_header ,  0 ,  & error )  = =  DW_DLV_OK )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      if  ( returnDie ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        dwarf_dealloc ( dwarf ,  returnDie ,  DW_DLA_DIE ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      if  ( dwarf_siblingof ( dwarf ,  0 ,  & returnDie ,  & error )  = =  DW_DLV_OK )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if  ( ( dwarf_tag ( returnDie ,  & tag ,  & error )  = =  DW_DLV_OK )  & & 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            tag  = =  DW_TAG_compile_unit )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          if  ( die_has_pc ( fobj ,  returnDie ,  addr ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            found  =  true ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( found )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      while  ( dwarf_next_cu_header_d ( dwarf ,  1 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                                    & next_cu_header ,  0 ,  & error )  = =  DW_DLV_OK )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        // Reset the cu header state. Libdwarf's next_cu_header API
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        // keeps its own iterator per Dwarf_Debug that can't be reset.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        // We need to keep fetching elements until the end.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( found ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      return  returnDie ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // We couldn't find any compilation units with ranges or a high/low pc.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // Try again by looking at all DIEs in all compilation units.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    Dwarf_Die  cudie ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    while  ( dwarf_next_cu_header_d ( dwarf ,  1 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                                  & next_cu_header ,  0 ,  & error )  = =  DW_DLV_OK )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      if  ( dwarf_siblingof ( dwarf ,  0 ,  & cudie ,  & error )  = =  DW_DLV_OK )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        Dwarf_Die  die_mem  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        Dwarf_Die  resultDie  =  find_fundie_by_pc ( fobj ,  cudie ,  addr ,  die_mem ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if  ( resultDie )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          found  =  true ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( found )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      while  ( dwarf_next_cu_header_d ( dwarf ,  1 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                                    & next_cu_header ,  0 ,  & error )  = =  DW_DLV_OK )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        // Reset the cu header state. Libdwarf's next_cu_header API
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        // keeps its own iterator per Dwarf_Debug that can't be reset.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        // We need to keep fetching elements until the end.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( found ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      return  cudie ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // We failed.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    return  NULL ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								} ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# endif  // BACKWARD_HAS_DWARF == 1
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								template  < >  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								class  TraceResolverImpl < system_tag : : linux_tag >  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    :  public  TraceResolverLinuxImpl < trace_resolver_tag : : current >  { } ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# endif  // BACKWARD_SYSTEM_LINUX
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# ifdef BACKWARD_SYSTEM_DARWIN 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								template  < typename  STACKTRACE_TAG >  class  TraceResolverDarwinImpl ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								template  < >  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								class  TraceResolverDarwinImpl < trace_resolver_tag : : backtrace_symbol >  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    :  public  TraceResolverImplBase  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								public :  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  void  load_addresses ( void  * const * addresses ,  int  address_count )  override  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( address_count  = =  0 )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      return ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    _symbols . reset ( backtrace_symbols ( addresses ,  address_count ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  ResolvedTrace  resolve ( ResolvedTrace  trace )  override  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // parse:
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // <n>  <file>  <addr>  <mangled-name> + <offset>
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    char  * filename  =  _symbols [ trace . idx ] ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // skip "<n>  "
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    while  ( * filename  & &  * filename  ! =  '   ' ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      filename + + ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    while  ( * filename  = =  '   ' ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      filename + + ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // find start of <mangled-name> from end (<file> may contain a space)
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    char  * p  =  filename  +  strlen ( filename )  -  1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // skip to start of " + <offset>"
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    while  ( p  >  filename  & &  * p  ! =  '   ' ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      p - - ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    while  ( p  >  filename  & &  * p  = =  '   ' ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      p - - ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    while  ( p  >  filename  & &  * p  ! =  '   ' ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      p - - ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    while  ( p  >  filename  & &  * p  = =  '   ' ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      p - - ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    char  * funcname_end  =  p  +  1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // skip to start of "<manged-name>"
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    while  ( p  >  filename  & &  * p  ! =  '   ' ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      p - - ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    char  * funcname  =  p  +  1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // skip to start of "  <addr>  "
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    while  ( p  >  filename  & &  * p  = =  '   ' ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      p - - ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    while  ( p  >  filename  & &  * p  ! =  '   ' ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      p - - ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    while  ( p  >  filename  & &  * p  = =  '   ' ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      p - - ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // skip "<file>", handling the case where it contains a
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    char  * filename_end  =  p  +  1 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( p  = =  filename )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      // something went wrong, give up
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      filename_end  =  filename  +  strlen ( filename ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      funcname  =  filename_end ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    trace . object_filename . assign ( 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        filename ,  filename_end ) ;  // ok even if filename_end is the ending \0
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                                 // (then we assign entire string)
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( * funcname )  {  // if it's not end of string
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      * funcname_end  =  ' \0 ' ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      trace . object_function  =  this - > demangle ( funcname ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      trace . object_function  + =  "   " ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      trace . object_function  + =  ( funcname_end  +  1 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      trace . source . function  =  trace . object_function ;  // we cannot do better.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    return  trace ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								private :  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  details : : handle < char  * * >  _symbols ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								} ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								template  < >  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								class  TraceResolverImpl < system_tag : : darwin_tag >  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    :  public  TraceResolverDarwinImpl < trace_resolver_tag : : current >  { } ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# endif  // BACKWARD_SYSTEM_DARWIN
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# ifdef BACKWARD_SYSTEM_WINDOWS 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// Load all symbol info
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// Based on:
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// https://stackoverflow.com/questions/6205981/windows-c-stack-trace-from-a-running-app/28276227#28276227
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								struct  module_data  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  std : : string  image_name ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  std : : string  module_name ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  void  * base_address ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  DWORD  load_size ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								} ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								class  get_mod_info  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  HANDLE  process ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  static  const  int  buffer_length  =  4096 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								public :  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  get_mod_info ( HANDLE  h )  :  process ( h )  { } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  module_data  operator ( ) ( HMODULE  module )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    module_data  ret ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    char  temp [ buffer_length ] ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    MODULEINFO  mi ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    GetModuleInformation ( process ,  module ,  & mi ,  sizeof ( mi ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    ret . base_address  =  mi . lpBaseOfDll ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    ret . load_size  =  mi . SizeOfImage ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    GetModuleFileNameExA ( process ,  module ,  temp ,  sizeof ( temp ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    ret . image_name  =  temp ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    GetModuleBaseNameA ( process ,  module ,  temp ,  sizeof ( temp ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    ret . module_name  =  temp ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    std : : vector < char >  img ( ret . image_name . begin ( ) ,  ret . image_name . end ( ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    std : : vector < char >  mod ( ret . module_name . begin ( ) ,  ret . module_name . end ( ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    SymLoadModule64 ( process ,  0 ,  & img [ 0 ] ,  & mod [ 0 ] ,  ( DWORD64 ) ret . base_address , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    ret . load_size ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    return  ret ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								} ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								template  < >  class  TraceResolverImpl < system_tag : : windows_tag >  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    :  public  TraceResolverImplBase  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								public :  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  TraceResolverImpl ( )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    HANDLE  process  =  GetCurrentProcess ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    std : : vector < module_data >  modules ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    DWORD  cbNeeded ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    std : : vector < HMODULE >  module_handles ( 1 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    SymInitialize ( process ,  NULL ,  false ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    DWORD  symOptions  =  SymGetOptions ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    symOptions  | =  SYMOPT_LOAD_LINES  |  SYMOPT_UNDNAME ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    SymSetOptions ( symOptions ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    EnumProcessModules ( process ,  & module_handles [ 0 ] , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                       module_handles . size ( )  *  sizeof ( HMODULE ) ,  & cbNeeded ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    module_handles . resize ( cbNeeded  /  sizeof ( HMODULE ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    EnumProcessModules ( process ,  & module_handles [ 0 ] , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                       module_handles . size ( )  *  sizeof ( HMODULE ) ,  & cbNeeded ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    std : : transform ( module_handles . begin ( ) ,  module_handles . end ( ) , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                   std : : back_inserter ( modules ) ,  get_mod_info ( process ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    void  * base  =  modules [ 0 ] . base_address ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    IMAGE_NT_HEADERS  * h  =  ImageNtHeader ( base ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    image_type  =  h - > FileHeader . Machine ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  static  const  int  max_sym_len  =  255 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  struct  symbol_t  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    SYMBOL_INFO  sym ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    char  buffer [ max_sym_len ] ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  }  sym ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  DWORD64  displacement ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  ResolvedTrace  resolve ( ResolvedTrace  t )  override  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    HANDLE  process  =  GetCurrentProcess ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    char  name [ 256 ] ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    memset ( & sym ,  0 ,  sizeof ( sym ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    sym . sym . SizeOfStruct  =  sizeof ( SYMBOL_INFO ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    sym . sym . MaxNameLen  =  max_sym_len ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( ! SymFromAddr ( process ,  ( ULONG64 ) t . addr ,  & displacement ,  & sym . sym ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      // TODO:  error handling everywhere
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      char *  lpMsgBuf ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      DWORD  dw  =  GetLastError ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      if  ( FormatMessageA ( FORMAT_MESSAGE_ALLOCATE_BUFFER  | 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                             FORMAT_MESSAGE_FROM_SYSTEM  | 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                             FORMAT_MESSAGE_IGNORE_INSERTS , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                         NULL ,  dw ,  MAKELANGID ( LANG_NEUTRAL ,  SUBLANG_DEFAULT ) , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                         ( char * ) & lpMsgBuf ,  0 ,  NULL ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        std : : fprintf ( stderr ,  " %s \n " ,  lpMsgBuf ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        LocalFree ( lpMsgBuf ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      // abort();
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    UnDecorateSymbolName ( sym . sym . Name ,  ( PSTR ) name ,  256 ,  UNDNAME_COMPLETE ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    DWORD  offset  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    IMAGEHLP_LINE  line ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( SymGetLineFromAddr ( process ,  ( ULONG64 ) t . addr ,  & offset ,  & line ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      t . object_filename  =  line . FileName ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      t . source . filename  =  line . FileName ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      t . source . line  =  line . LineNumber ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      t . source . col  =  offset ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    t . source . function  =  name ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    t . object_filename  =  " " ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    t . object_function  =  name ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    return  t ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  DWORD  machine_type ( )  const  {  return  image_type ;  } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								private :  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  DWORD  image_type ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								} ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# endif 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								class  TraceResolver  :  public  TraceResolverImpl < system_tag : : current_tag >  { } ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/*************** CODE SNIPPET ***************/  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								class  SourceFile  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								public :  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  typedef  std : : vector < std : : pair < unsigned ,  std : : string >  >  lines_t ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  SourceFile ( )  { } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  SourceFile ( const  std : : string  & path )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // 1. If BACKWARD_CXX_SOURCE_PREFIXES is set then assume it contains
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    //    a colon-separated list of path prefixes.  Try prepending each
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    //    to the given path until a valid file is found.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    const  std : : vector < std : : string >  & prefixes  =  get_paths_from_env_variable ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    for  ( size_t  i  =  0 ;  i  <  prefixes . size ( ) ;  + + i )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      // Double slashes (//) should not be a problem.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      std : : string  new_path  =  prefixes [ i ]  +  ' / '  +  path ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      _file . reset ( new  std : : ifstream ( new_path . c_str ( ) ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      if  ( is_open ( ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        break ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // 2. If no valid file found then fallback to opening the path as-is.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( ! _file  | |  ! is_open ( ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      _file . reset ( new  std : : ifstream ( path . c_str ( ) ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  bool  is_open ( )  const  {  return  _file - > is_open ( ) ;  } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  lines_t  & get_lines ( unsigned  line_start ,  unsigned  line_count ,  lines_t  & lines )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    using  namespace  std ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // This function make uses of the dumbest algo ever:
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    //	1) seek(0)
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    //	2) read lines one by one and discard until line_start
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    //	3) read line one by one until line_start + line_count
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    //
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // If you are getting snippets many time from the same file, it is
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // somewhat a waste of CPU, feel free to benchmark and propose a
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // better solution ;)
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    _file - > clear ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    _file - > seekg ( 0 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    string  line ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    unsigned  line_idx ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    for  ( line_idx  =  1 ;  line_idx  <  line_start ;  + + line_idx )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      std : : getline ( * _file ,  line ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      if  ( ! * _file )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return  lines ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // think of it like a lambda in C++98 ;)
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // but look, I will reuse it two times!
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // What a good boy am I.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    struct  isspace  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      bool  operator ( ) ( char  c )  {  return  std : : isspace ( c ) ;  } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    bool  started  =  false ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    for  ( ;  line_idx  <  line_start  +  line_count ;  + + line_idx )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      getline ( * _file ,  line ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      if  ( ! * _file )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return  lines ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      if  ( ! started )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if  ( std : : find_if ( line . begin ( ) ,  line . end ( ) ,  not_isspace ( ) )  = =  line . end ( ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          continue ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        started  =  true ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      lines . push_back ( make_pair ( line_idx ,  line ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    lines . erase ( 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        std : : find_if ( lines . rbegin ( ) ,  lines . rend ( ) ,  not_isempty ( ) ) . base ( ) , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        lines . end ( ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    return  lines ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  lines_t  get_lines ( unsigned  line_start ,  unsigned  line_count )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    lines_t  lines ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    return  get_lines ( line_start ,  line_count ,  lines ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  // there is no find_if_not in C++98, lets do something crappy to
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  // workaround.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  struct  not_isspace  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    bool  operator ( ) ( char  c )  {  return  ! std : : isspace ( c ) ;  } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  } ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  // and define this one here because C++98 is not happy with local defined
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  // struct passed to template functions, fuuuu.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  struct  not_isempty  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    bool  operator ( ) ( const  lines_t : : value_type  & p )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      return  ! ( std : : find_if ( p . second . begin ( ) ,  p . second . end ( ) ,  not_isspace ( ) )  = = 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								               p . second . end ( ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  } ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  void  swap ( SourceFile  & b )  {  _file . swap ( b . _file ) ;  } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# ifdef BACKWARD_ATLEAST_CXX11 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  SourceFile ( SourceFile  & & from )  :  _file ( nullptr )  {  swap ( from ) ;  } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  SourceFile  & operator = ( SourceFile  & & from )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    swap ( from ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    return  * this ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# else 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  explicit  SourceFile ( const  SourceFile  & from )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // some sort of poor man's move semantic.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    swap ( const_cast < SourceFile  & > ( from ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  SourceFile  & operator = ( const  SourceFile  & from )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // some sort of poor man's move semantic.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    swap ( const_cast < SourceFile  & > ( from ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    return  * this ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# endif 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								private :  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  details : : handle < std : : ifstream  * ,  details : : default_delete < std : : ifstream  * >  > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      _file ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  std : : vector < std : : string >  get_paths_from_env_variable_impl ( )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    std : : vector < std : : string >  paths ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    const  char  * prefixes_str  =  std : : getenv ( " BACKWARD_CXX_SOURCE_PREFIXES " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( prefixes_str  & &  prefixes_str [ 0 ] )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      paths  =  details : : split_source_prefixes ( prefixes_str ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    return  paths ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  const  std : : vector < std : : string >  & get_paths_from_env_variable ( )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    static  std : : vector < std : : string >  paths  =  get_paths_from_env_variable_impl ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    return  paths ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# ifdef BACKWARD_ATLEAST_CXX11 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  SourceFile ( const  SourceFile  & )  =  delete ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  SourceFile  & operator = ( const  SourceFile  & )  =  delete ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# endif 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								} ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								class  SnippetFactory  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								public :  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  typedef  SourceFile : : lines_t  lines_t ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  lines_t  get_snippet ( const  std : : string  & filename ,  unsigned  line_start , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                      unsigned  context_size )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    SourceFile  & src_file  =  get_src_file ( filename ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    unsigned  start  =  line_start  -  context_size  /  2 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    return  src_file . get_lines ( start ,  context_size ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  lines_t  get_combined_snippet ( const  std : : string  & filename_a ,  unsigned  line_a , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                               const  std : : string  & filename_b ,  unsigned  line_b , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                               unsigned  context_size )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    SourceFile  & src_file_a  =  get_src_file ( filename_a ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    SourceFile  & src_file_b  =  get_src_file ( filename_b ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    lines_t  lines  = 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        src_file_a . get_lines ( line_a  -  context_size  /  4 ,  context_size  /  2 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    src_file_b . get_lines ( line_b  -  context_size  /  4 ,  context_size  /  2 ,  lines ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    return  lines ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  lines_t  get_coalesced_snippet ( const  std : : string  & filename ,  unsigned  line_a , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                                unsigned  line_b ,  unsigned  context_size )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    SourceFile  & src_file  =  get_src_file ( filename ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    using  std : : max ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    using  std : : min ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    unsigned  a  =  min ( line_a ,  line_b ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    unsigned  b  =  max ( line_a ,  line_b ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( ( b  -  a )  <  ( context_size  /  3 ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      return  src_file . get_lines ( ( a  +  b  -  context_size  +  1 )  /  2 ,  context_size ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    lines_t  lines  =  src_file . get_lines ( a  -  context_size  /  4 ,  context_size  /  2 ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    src_file . get_lines ( b  -  context_size  /  4 ,  context_size  /  2 ,  lines ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    return  lines ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								private :  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  typedef  details : : hashtable < std : : string ,  SourceFile > : : type  src_files_t ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  src_files_t  _src_files ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  SourceFile  & get_src_file ( const  std : : string  & filename )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    src_files_t : : iterator  it  =  _src_files . find ( filename ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( it  ! =  _src_files . end ( ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      return  it - > second ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    SourceFile  & new_src_file  =  _src_files [ filename ] ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    new_src_file  =  SourceFile ( filename ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    return  new_src_file ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								} ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/*************** PRINTER ***************/  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								namespace  ColorMode  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								enum  type  {  automatic ,  never ,  always  } ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								class  cfile_streambuf  :  public  std : : streambuf  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								public :  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  cfile_streambuf ( FILE  * _sink )  :  sink ( _sink )  { } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  int_type  underflow ( )  override  {  return  traits_type : : eof ( ) ;  } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  int_type  overflow ( int_type  ch )  override  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( traits_type : : not_eof ( ch )  & &  fputc ( ch ,  sink )  ! =  EOF )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      return  ch ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    return  traits_type : : eof ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  std : : streamsize  xsputn ( const  char_type  * s ,  std : : streamsize  count )  override  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    return  static_cast < std : : streamsize > ( 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        fwrite ( s ,  sizeof  * s ,  static_cast < size_t > ( count ) ,  sink ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# ifdef BACKWARD_ATLEAST_CXX11 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								public :  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  cfile_streambuf ( const  cfile_streambuf  & )  =  delete ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  cfile_streambuf  & operator = ( const  cfile_streambuf  & )  =  delete ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# else 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								private :  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  cfile_streambuf ( const  cfile_streambuf  & ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  cfile_streambuf  & operator = ( const  cfile_streambuf  & ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# endif 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								private :  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  FILE  * sink ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  std : : vector < char >  buffer ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								} ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# ifdef BACKWARD_SYSTEM_LINUX 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								namespace  Color  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								enum  type  {  yellow  =  33 ,  purple  =  35 ,  reset  =  39  } ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  // namespace Color
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								class  Colorize  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								public :  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  Colorize ( std : : ostream  & os )  :  _os ( os ) ,  _reset ( false ) ,  _enabled ( false )  { } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  void  activate ( ColorMode : : type  mode )  {  _enabled  =  mode  = =  ColorMode : : always ;  } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  void  activate ( ColorMode : : type  mode ,  FILE  * fp )  {  activate ( mode ,  fileno ( fp ) ) ;  } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  void  set_color ( Color : : type  ccode )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( ! _enabled ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      return ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // I assume that the terminal can handle basic colors. Seriously I
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // don't want to deal with all the termcap shit.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    _os  < <  " \033 [ "  < <  static_cast < int > ( ccode )  < <  " m " ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    _reset  =  ( ccode  ! =  Color : : reset ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  ~ Colorize ( )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( _reset )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      set_color ( Color : : reset ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								private :  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  void  activate ( ColorMode : : type  mode ,  int  fd )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    activate ( mode  = =  ColorMode : : automatic  & &  isatty ( fd )  ?  ColorMode : : always 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                                                        :  mode ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  std : : ostream  & _os ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  bool  _reset ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  bool  _enabled ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								} ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# else  // ndef BACKWARD_SYSTEM_LINUX
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								namespace  Color  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								enum  type  {  yellow  =  0 ,  purple  =  0 ,  reset  =  0  } ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  // namespace Color
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								class  Colorize  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								public :  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  Colorize ( std : : ostream  & )  { } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  void  activate ( ColorMode : : type )  { } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  void  activate ( ColorMode : : type ,  FILE  * )  { } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  void  set_color ( Color : : type )  { } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								} ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# endif  // BACKWARD_SYSTEM_LINUX
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								class  Printer  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								public :  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  bool  snippet ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  ColorMode : : type  color_mode ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  bool  address ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  bool  object ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  int  inliner_context_size ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  int  trace_context_size ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  Printer ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      :  snippet ( true ) ,  color_mode ( ColorMode : : automatic ) ,  address ( false ) , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        object ( false ) ,  inliner_context_size ( 5 ) ,  trace_context_size ( 7 )  { } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  template  < typename  ST >  FILE  * print ( ST  & st ,  FILE  * fp  =  stderr )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    cfile_streambuf  obuf ( fp ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    std : : ostream  os ( & obuf ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    Colorize  colorize ( os ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    colorize . activate ( color_mode ,  fp ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    print_stacktrace ( st ,  os ,  colorize ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    return  fp ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  template  < typename  ST >  std : : ostream  & print ( ST  & st ,  std : : ostream  & os )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    Colorize  colorize ( os ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    colorize . activate ( color_mode ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    print_stacktrace ( st ,  os ,  colorize ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    return  os ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  template  < typename  IT > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  FILE  * print ( IT  begin ,  IT  end ,  FILE  * fp  =  stderr ,  size_t  thread_id  =  0 )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    cfile_streambuf  obuf ( fp ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    std : : ostream  os ( & obuf ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    Colorize  colorize ( os ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    colorize . activate ( color_mode ,  fp ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    print_stacktrace ( begin ,  end ,  os ,  thread_id ,  colorize ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    return  fp ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  template  < typename  IT > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  std : : ostream  & print ( IT  begin ,  IT  end ,  std : : ostream  & os , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                      size_t  thread_id  =  0 )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    Colorize  colorize ( os ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    colorize . activate ( color_mode ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    print_stacktrace ( begin ,  end ,  os ,  thread_id ,  colorize ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    return  os ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  TraceResolver  const  & resolver ( )  const  {  return  _resolver ;  } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								private :  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  TraceResolver  _resolver ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  SnippetFactory  _snippets ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  template  < typename  ST > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  void  print_stacktrace ( ST  & st ,  std : : ostream  & os ,  Colorize  & colorize )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    print_header ( os ,  st . thread_id ( ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    _resolver . load_stacktrace ( st ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    for  ( size_t  trace_idx  =  st . size ( ) ;  trace_idx  >  0 ;  - - trace_idx )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      print_trace ( os ,  _resolver . resolve ( st [ trace_idx  -  1 ] ) ,  colorize ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  template  < typename  IT > 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  void  print_stacktrace ( IT  begin ,  IT  end ,  std : : ostream  & os ,  size_t  thread_id , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                        Colorize  & colorize )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    print_header ( os ,  thread_id ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    for  ( ;  begin  ! =  end ;  + + begin )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      print_trace ( os ,  * begin ,  colorize ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  void  print_header ( std : : ostream  & os ,  size_t  thread_id )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    os  < <  " Stack trace (most recent call last) " ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( thread_id )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      os  < <  "  in thread  "  < <  thread_id ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    os  < <  " : \n " ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  void  print_trace ( std : : ostream  & os ,  const  ResolvedTrace  & trace , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                   Colorize  & colorize )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    os  < <  " # "  < <  std : : left  < <  std : : setw ( 2 )  < <  trace . idx  < <  std : : right ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    bool  already_indented  =  true ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( ! trace . source . filename . size ( )  | |  object )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      os  < <  "    Object  \" "  < <  trace . object_filename  < <  " \" , at  "  < <  trace . addr 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								         < <  " , in  "  < <  trace . object_function  < <  " \n " ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      already_indented  =  false ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    for  ( size_t  inliner_idx  =  trace . inliners . size ( ) ;  inliner_idx  >  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								         - - inliner_idx )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      if  ( ! already_indented )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        os  < <  "     " ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      const  ResolvedTrace : : SourceLoc  & inliner_loc  = 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          trace . inliners [ inliner_idx  -  1 ] ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      print_source_loc ( os ,  "  |  " ,  inliner_loc ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      if  ( snippet )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        print_snippet ( os ,  "     |  " ,  inliner_loc ,  colorize ,  Color : : purple , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                      inliner_context_size ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      already_indented  =  false ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( trace . source . filename . size ( ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      if  ( ! already_indented )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        os  < <  "     " ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      print_source_loc ( os ,  "     " ,  trace . source ,  trace . addr ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      if  ( snippet )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        print_snippet ( os ,  "        " ,  trace . source ,  colorize ,  Color : : yellow , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                      trace_context_size ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  void  print_snippet ( std : : ostream  & os ,  const  char  * indent , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                     const  ResolvedTrace : : SourceLoc  & source_loc , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                     Colorize  & colorize ,  Color : : type  color_code , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                     int  context_size )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    using  namespace  std ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    typedef  SnippetFactory : : lines_t  lines_t ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    lines_t  lines  =  _snippets . get_snippet ( source_loc . filename ,  source_loc . line , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                                          static_cast < unsigned > ( context_size ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    for  ( lines_t : : const_iterator  it  =  lines . begin ( ) ;  it  ! =  lines . end ( ) ;  + + it )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      if  ( it - > first  = =  source_loc . line )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        colorize . set_color ( color_code ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        os  < <  indent  < <  " > " ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      }  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        os  < <  indent  < <  "   " ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      os  < <  std : : setw ( 4 )  < <  it - > first  < <  " :  "  < <  it - > second  < <  " \n " ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      if  ( it - > first  = =  source_loc . line )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        colorize . set_color ( Color : : reset ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  void  print_source_loc ( std : : ostream  & os ,  const  char  * indent , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                        const  ResolvedTrace : : SourceLoc  & source_loc , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                        void  * addr  =  nullptr )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    os  < <  indent  < <  " Source  \" "  < <  source_loc . filename  < <  " \" , line  " 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								       < <  source_loc . line  < <  " , in  "  < <  source_loc . function ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( address  & &  addr  ! =  nullptr )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      os  < <  "  [ "  < <  addr  < <  " ] " ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    os  < <  " \n " ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								} ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								/*************** SIGNALS HANDLING ***************/  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# if defined(BACKWARD_SYSTEM_LINUX) || defined(BACKWARD_SYSTEM_DARWIN) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								class  SignalHandling  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								public :  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  static  std : : vector < int >  make_default_signals ( )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    const  int  posix_signals [ ]  =  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      // Signals for which the default action is "Core".
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      SIGABRT ,  // Abort signal from abort(3)
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      SIGBUS ,   // Bus error (bad memory access)
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      SIGFPE ,   // Floating point exception
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      SIGILL ,   // Illegal Instruction
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      SIGIOT ,   // IOT trap. A synonym for SIGABRT
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      SIGQUIT ,  // Quit from keyboard
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      SIGSEGV ,  // Invalid memory reference
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      SIGSYS ,   // Bad argument to routine (SVr4)
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      SIGTRAP ,  // Trace/breakpoint trap
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      SIGXCPU ,  // CPU time limit exceeded (4.2BSD)
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      SIGXFSZ ,  // File size limit exceeded (4.2BSD)
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# if defined(BACKWARD_SYSTEM_DARWIN) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      SIGEMT ,  // emulation instruction executed
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# endif 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    return  std : : vector < int > ( posix_signals , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                            posix_signals  + 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                                sizeof  posix_signals  /  sizeof  posix_signals [ 0 ] ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  SignalHandling ( const  std : : vector < int >  & posix_signals  =  make_default_signals ( ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      :  _loaded ( false )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    bool  success  =  true ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    const  size_t  stack_size  =  1024  *  1024  *  8 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    _stack_content . reset ( static_cast < char  * > ( malloc ( stack_size ) ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( _stack_content )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      stack_t  ss ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      ss . ss_sp  =  _stack_content . get ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      ss . ss_size  =  stack_size ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      ss . ss_flags  =  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      if  ( sigaltstack ( & ss ,  nullptr )  <  0 )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        success  =  false ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    }  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      success  =  false ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    for  ( size_t  i  =  0 ;  i  <  posix_signals . size ( ) ;  + + i )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      struct  sigaction  action ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      memset ( & action ,  0 ,  sizeof  action ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      action . sa_flags  = 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          static_cast < int > ( SA_SIGINFO  |  SA_ONSTACK  |  SA_NODEFER  |  SA_RESETHAND ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      sigfillset ( & action . sa_mask ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      sigdelset ( & action . sa_mask ,  posix_signals [ i ] ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# if defined(__clang__) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# pragma clang diagnostic push 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# pragma clang diagnostic ignored "-Wdisabled-macro-expansion" 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# endif 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      action . sa_sigaction  =  & sig_handler ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# if defined(__clang__) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# pragma clang diagnostic pop 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# endif 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      int  r  =  sigaction ( posix_signals [ i ] ,  & action ,  nullptr ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      if  ( r  <  0 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        success  =  false ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    _loaded  =  success ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  bool  loaded ( )  const  {  return  _loaded ;  } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  static  void  handleSignal ( int ,  siginfo_t  * info ,  void  * _ctx )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    ucontext_t  * uctx  =  static_cast < ucontext_t  * > ( _ctx ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    StackTrace  st ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    void  * error_addr  =  nullptr ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# ifdef REG_RIP  // x86_64
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    error_addr  =  reinterpret_cast < void  * > ( uctx - > uc_mcontext . gregs [ REG_RIP ] ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# elif defined(REG_EIP)  // x86_32
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    error_addr  =  reinterpret_cast < void  * > ( uctx - > uc_mcontext . gregs [ REG_EIP ] ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# elif defined(__arm__) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    error_addr  =  reinterpret_cast < void  * > ( uctx - > uc_mcontext . arm_pc ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# elif defined(__aarch64__) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    # if defined(__APPLE__) 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      error_addr  =  reinterpret_cast < void  * > ( uctx - > uc_mcontext - > __ss . __pc ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    # else 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      error_addr  =  reinterpret_cast < void  * > ( uctx - > uc_mcontext . pc ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    # endif 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# elif defined(__mips__) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    error_addr  =  reinterpret_cast < void  * > ( 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        reinterpret_cast < struct  sigcontext  * > ( & uctx - > uc_mcontext ) - > sc_pc ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# elif defined(__ppc__) || defined(__powerpc) || defined(__powerpc__) ||        \ 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    defined ( __POWERPC__ ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    error_addr  =  reinterpret_cast < void  * > ( uctx - > uc_mcontext . regs - > nip ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# elif defined(__riscv) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    error_addr  =  reinterpret_cast < void  * > ( uctx - > uc_mcontext . __gregs [ REG_PC ] ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# elif defined(__s390x__) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    error_addr  =  reinterpret_cast < void  * > ( uctx - > uc_mcontext . psw . addr ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# elif defined(__APPLE__) && defined(__x86_64__) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    error_addr  =  reinterpret_cast < void  * > ( uctx - > uc_mcontext - > __ss . __rip ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# elif defined(__APPLE__) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    error_addr  =  reinterpret_cast < void  * > ( uctx - > uc_mcontext - > __ss . __eip ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# else 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# warning ": /  sorry, ain't know no nothing none not of your architecture!" 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# endif 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( error_addr )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      st . load_from ( error_addr ,  32 ,  reinterpret_cast < void  * > ( uctx ) , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                   info - > si_addr ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    }  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      st . load_here ( 32 ,  reinterpret_cast < void  * > ( uctx ) ,  info - > si_addr ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2022-05-28 23:45:59 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								# ifdef _WIN32 
  
						 
					
						
							
								
									
										
										
										
											2022-05-29 01:44:17 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    MessageBox ( NULL , " Error " , " Furnace has crashed! please report this to the issue tracker immediately: \r \n https://github.com/tildearrow/furnace/issues/new \r \n \r \n a file called furnace_crash.txt will be created in your user directory. \r \n this will be important for locating the origin of the crash. " , MB_OK | MB_ICONERROR ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2022-05-28 23:45:59 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    std : : string  crashLocation ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    char *  userProfile = getenv ( " USERPROFILE " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( userProfile = = NULL )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      crashLocation = " C: \\ furnace_crash.txt " ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    }  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      crashLocation = userProfile ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      crashLocation + = " \\ furnace_crash.txt " ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    FILE *  crashDump = fopen ( crashLocation . c_str ( ) , " w " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# else 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    FILE *  crashDump = fopen ( " /tmp/furnace_crash.txt " , " w " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# endif 
  
						 
					
						
							
								
									
										
										
										
											2022-05-24 14:23:23 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2022-05-24 14:06:29 -04:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								    Printer  printer ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    printer . address  =  true ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    printer . print ( st ,  stderr ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2022-05-24 14:23:23 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    if  ( crashDump ! = NULL )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      Printer  printer ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      printer . address  =  true ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      printer . print ( st ,  crashDump ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      fclose ( crashDump ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2022-05-28 23:45:59 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    }  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# ifdef _WIN32 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      std : : string  str ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      Printer  failedPrinter ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      failedPrinter . address  =  true ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      failedPrinter . print ( st ,  str ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      str + = " \r \n could not open furnace_crash.txt! \r \n please take a screenshot of this error message box! " ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      fprintf ( stderr , " NOTICE: could not open furnace_crash.txt! \n " ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2022-05-29 01:44:17 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								      MessageBox ( NULL , " Error " , str . c_str ( ) , MB_OK | MB_ICONERROR ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2022-05-28 23:45:59 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								# endif 
  
						 
					
						
							
								
									
										
										
										
											2022-05-24 14:23:23 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2022-05-24 14:06:29 -04:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								# if (defined(_XOPEN_SOURCE) && _XOPEN_SOURCE >= 700) || \ 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    ( defined ( _POSIX_C_SOURCE )  & &  _POSIX_C_SOURCE  > =  200809L ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    psiginfo ( info ,  nullptr ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# else 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    ( void ) info ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# endif 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								private :  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  details : : handle < char  * >  _stack_content ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  bool  _loaded ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# ifdef __GNUC__ 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  __attribute__ ( ( noreturn ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# endif 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  static  void 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  sig_handler ( int  signo ,  siginfo_t  * info ,  void  * _ctx )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    handleSignal ( signo ,  info ,  _ctx ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // try to forward the signal.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    raise ( info - > si_signo ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // terminate the process immediately.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    puts ( " watf? exit " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    _exit ( EXIT_FAILURE ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								} ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# endif  // BACKWARD_SYSTEM_LINUX || BACKWARD_SYSTEM_DARWIN
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# ifdef BACKWARD_SYSTEM_WINDOWS 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								class  SignalHandling  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								public :  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  SignalHandling ( const  std : : vector < int >  &  =  std : : vector < int > ( ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      :  reporter_thread_ ( [ ] ( )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          /* We handle crashes in a utility thread:
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            backward  structures  and  some  Windows  functions  called  here 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            need  stack  space ,  which  we  do  not  have  when  we  encounter  a 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            stack  overflow . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            To  support  reporting  stack  traces  during  a  stack  overflow , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            we  create  a  utility  thread  at  startup ,  which  waits  until  a 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            crash  happens  or  the  program  exits  normally .  */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            std : : unique_lock < std : : mutex >  lk ( mtx ( ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            cv ( ) . wait ( lk ,  [ ]  {  return  crashed ( )  ! =  crash_status : : running ;  } ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          if  ( crashed ( )  = =  crash_status : : crashed )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            handle_stacktrace ( skip_recs ( ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            std : : unique_lock < std : : mutex >  lk ( mtx ( ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            crashed ( )  =  crash_status : : ending ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          cv ( ) . notify_one ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        } )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    SetUnhandledExceptionFilter ( crash_handler ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    signal ( SIGABRT ,  signal_handler ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2022-05-24 23:15:43 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								# ifdef _MSC_VER 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // TODO: fix for MinGW
 
							 
						 
					
						
							
								
									
										
										
										
											2022-05-24 14:06:29 -04:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								    _set_abort_behavior ( 0 ,  _WRITE_ABORT_MSG  |  _CALL_REPORTFAULT ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2022-05-24 23:15:43 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								# endif 
  
						 
					
						
							
								
									
										
										
										
											2022-05-24 14:06:29 -04:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    std : : set_terminate ( & terminator ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# ifndef BACKWARD_ATLEAST_CXX17 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    std : : set_unexpected ( & terminator ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# endif 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    _set_purecall_handler ( & terminator ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    _set_invalid_parameter_handler ( & invalid_parameter_handler ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  bool  loaded ( )  const  {  return  true ;  } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  ~ SignalHandling ( )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      std : : unique_lock < std : : mutex >  lk ( mtx ( ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      crashed ( )  =  crash_status : : normal_exit ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    cv ( ) . notify_one ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    reporter_thread_ . join ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								private :  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  static  CONTEXT  * ctx ( )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    static  CONTEXT  data ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    return  & data ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  enum  class  crash_status  {  running ,  crashed ,  normal_exit ,  ending  } ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  static  crash_status  & crashed ( )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    static  crash_status  data ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    return  data ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  static  std : : mutex  & mtx ( )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    static  std : : mutex  data ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    return  data ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  static  std : : condition_variable  & cv ( )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    static  std : : condition_variable  data ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    return  data ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  static  HANDLE  & thread_handle ( )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    static  HANDLE  handle ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    return  handle ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  std : : thread  reporter_thread_ ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  // TODO: how not to hardcode these?
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  static  const  constexpr  int  signal_skip_recs  = 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# ifdef __clang__ 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      // With clang, RtlCaptureContext also captures the stack frame of the
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      // current function Below that, there ar 3 internal Windows functions
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      4 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# else 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      // With MSVC cl, RtlCaptureContext misses the stack frame of the current
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      // function The first entries during StackWalk are the 3 internal Windows
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      // functions
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      3 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# endif 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  static  int  & skip_recs ( )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    static  int  data ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    return  data ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  static  inline  void  terminator ( )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    crash_handler ( signal_skip_recs ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    abort ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  static  inline  void  signal_handler ( int )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    crash_handler ( signal_skip_recs ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    abort ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  static  inline  void  __cdecl  invalid_parameter_handler ( const  wchar_t  * , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                                                       const  wchar_t  * , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                                                       const  wchar_t  * , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                                                       unsigned  int , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                                                       uintptr_t )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    crash_handler ( signal_skip_recs ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    abort ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  NOINLINE  static  LONG  WINAPI  crash_handler ( EXCEPTION_POINTERS  * info )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // The exception info supplies a trace from exactly where the issue was,
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // no need to skip records
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    crash_handler ( 0 ,  info - > ContextRecord ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    return  EXCEPTION_CONTINUE_SEARCH ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  NOINLINE  static  void  crash_handler ( int  skip ,  CONTEXT  * ct  =  nullptr )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( ct  = =  nullptr )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      RtlCaptureContext ( ctx ( ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    }  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      memcpy ( ctx ( ) ,  ct ,  sizeof ( CONTEXT ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    DuplicateHandle ( GetCurrentProcess ( ) ,  GetCurrentThread ( ) , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    GetCurrentProcess ( ) ,  & thread_handle ( ) ,  0 ,  FALSE , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    DUPLICATE_SAME_ACCESS ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    skip_recs ( )  =  skip ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      std : : unique_lock < std : : mutex >  lk ( mtx ( ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      crashed ( )  =  crash_status : : crashed ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    cv ( ) . notify_one ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      std : : unique_lock < std : : mutex >  lk ( mtx ( ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      cv ( ) . wait ( lk ,  [ ]  {  return  crashed ( )  ! =  crash_status : : crashed ;  } ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  static  void  handle_stacktrace ( int  skip_frames  =  0 )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // printer creates the TraceResolver, which can supply us a machine type
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // for stack walking. Without this, StackTrace can only guess using some
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // macros.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // StackTrace also requires that the PDBs are already loaded, which is done
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // in the constructor of TraceResolver
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    Printer  printer ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    StackTrace  st ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    st . set_machine_type ( printer . resolver ( ) . machine_type ( ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    st . set_thread_handle ( thread_handle ( ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    st . load_here ( 32  +  skip_frames ,  ctx ( ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    st . skip_n_firsts ( skip_frames ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    printer . address  =  true ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    printer . print ( st ,  std : : cerr ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2022-05-29 01:48:19 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# ifdef _WIN32 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    MessageBox ( NULL , " Furnace has crashed! please report this to the issue tracker immediately: \r \n https://github.com/tildearrow/furnace/issues/new \r \n \r \n a file called furnace_crash.txt will be created in your user directory. \r \n this will be important for locating the origin of the crash. " , " Error " , MB_OK | MB_ICONERROR ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    std : : string  crashLocation ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    char *  userProfile = getenv ( " USERPROFILE " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( userProfile = = NULL )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      crashLocation = " furnace_crash.txt " ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    }  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      crashLocation = userProfile ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      crashLocation + = " \\ furnace_crash.txt " ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    FILE *  crashDump = fopen ( crashLocation . c_str ( ) , " w " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# else 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    FILE *  crashDump = fopen ( " /tmp/furnace_crash.txt " , " w " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# endif 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( crashDump ! = NULL )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      Printer  printer ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      printer . address  =  true ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      printer . print ( st ,  crashDump ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      fclose ( crashDump ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    }  else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# ifdef _WIN32 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      std : : string  str ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      //Printer failedPrinter;
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      //failedPrinter.address = true;
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      //failedPrinter.print(st, str);
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      str + = " \r \n could not open furnace_crash.txt! \r \n please take a screenshot of this error message box! " ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      fprintf ( stderr , " NOTICE: could not open furnace_crash.txt! \n " ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      MessageBox ( NULL , str . c_str ( ) , " Error " , MB_OK | MB_ICONERROR ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# endif 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
									
										
										
										
											2022-05-24 14:06:29 -04:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								  } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								} ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# endif  // BACKWARD_SYSTEM_WINDOWS
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# ifdef BACKWARD_SYSTEM_UNKNOWN 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								class  SignalHandling  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								public :  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  SignalHandling ( const  std : : vector < int >  &  =  std : : vector < int > ( ) )  { } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  bool  init ( )  {  return  false ;  } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  bool  loaded ( )  {  return  false ;  } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								} ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# endif  // BACKWARD_SYSTEM_UNKNOWN
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  // namespace backward
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								# endif  /* H_GUARD */