It might depend on which target you’re using. The GFortran backtrace functionality depends on libbacktrace, which might not work on all targets. On Ubuntu 16.04 x86_64 for the code
program bt
use iso_fortran_env
implicit none
real(real64) :: a, b = -1
a = sqrt(b)
print *, a
end program bt
when compiling with
gfortran -g -ffpe-trap=invalid bt.f90
I get
Program received signal SIGFPE: Floating-point exception - erroneous arithmetic operation.
Backtrace for this error:
#0 0x7F08C38E8E08
#1 0x7F08C38E7F90
#2 0x7F08C35384AF
#3 0x4007F9 in MAIN__ at bt.f90:5
zsh: floating point exception ./a.out
where on stack frame #3 you can see that the error occurs on line 5 in bt.f90.
Now, what are the stuff on stack frames #0-#2? Well, they are the backtracing functionality in libgfortran, the GFortran runtime library. libbacktrace for one reason or another cannot resolve symbols in a dynamic library. If I link it statically:
gfortran -g -static -ffpe-trap=invalid bt.f90
I get
Program received signal SIGFPE: Floating-point exception - erroneous arithmetic operation.
Backtrace for this error:
#0 0x40139E in _gfortrani_backtrace
#1 0x400D00 in _gfortrani_backtrace_handler
#2 0x439B2F in gsignal
#3 0x400C01 in MAIN__ at bt.f90:5
zsh: floating point exception ./a.out
[NOTE: Negar contacted me by Private Message for help with this. She provided a link to a compressed archive, 690 MB long, containing the source and data files. Readers, please note that this thread is about troubleshooting input data and array size mismatches with a large Fortran program (IBIS) and that she is using Gfortran, not Intel Fortran.]
Negar, here is some advice for your consideration, before I show you what went wrong.
- If you are involved in modifying a large program (about 900 kB) with complex input data, you will need to learn enough Fortran+OS+IBIS+NetCDF+Debugging skills to do so. There is no way around that; some of us may show you the way, but you will have to do the «lifting and walking». History has it that Ptolemy personally sponsored the great mathematician Euclid. He found Euclid’s seminal work, the Elements, too difficult to study, so he asked if there were an easier way to master it. According to Proclus Euclid famously quipped: «Sire, there is no Royal Road to geometry.»
- When asking for help with a problem, try to reduce the size of the source and data to a manageable size. I find that the attached 1.2 MB Zip file contains all that is needed to reproduce and analyze the problem.
- It is rarely enough to report the last few error messages such as «access violation». Doing so conveys the impression that you say «There is some problem and I don’t know what it is. Please fix it for me.» Such a request can be considered rude or inconsiderate.
I built the program from your sources on Windows 10/Cygwin 64 using Gfortran 10.2 with the command
gfortran -Iinc -fallow-argument-mismatch -ffixed-line-length-0 -g -C src/*.f -lnetcdff -lnetcdf -o gibis
Note the two options that I used for debugging: -g, which puts debug information into the EXE/a.out, and -C, which adds code to check subscripts.
When I ran the resulting program, ibis.exe, the output was:
S:Negar>gibis
****************************************
* IBIS: Integrated BIosphere Simulator *
* Version 2.6b3 *
* March 2002 *
****************************************
length of this simulation (years) : 19
year to begin using anomalies : 9999
model lon, lat resolution (degrees) : 0.02 0.02
model domain (nlon x nlat) : 617 by 534
number of iterations per day : 24
last year run in this sequence : 2019
RD_PARAM: All data read in from parameter files successfully.
ERROR in subroutine readit
number of land points in input/surta.nc
does not match number of land points in compar.h
in surta = 18946 in compar.h = 3
STOP 1
Here is how the access violation occurred: Line 4063 of IO.F contains
garea(nlpoints) = yres * 111400.0 * xres * 111400.0 * cos(xlat)
The array GAREA is declared GAREA(3), yet the data is such that NLPOINTS can reach values in the thousands.
Here is what you have to do: in file COMPAR.H, there is a parameter, NPOI, currently given the value 3. You have to replace that ‘3’ with a value that is large enough. How much? That is something that you will have to work out yourself, using the IBIS documentation + the source and include files, or with the help of an experienced IBIS user. I cannot tell you what to use because I neither use IBIS, nor do I know how to read the voluminous input data files.
Note that the IBIS source code handles this matter of array sizing in an outmoded way. The modern way is to read enough of the input data to ascertain/calculate the required array sizes, and then ALLOCATE those arrays to the exact size required — like buying shoes that fit, rather than the biggest size that any human would ever require.
The part of the IBIS code that did the checking is fine, but the code may well have crashed with an access violation or other error earlier, because the comparison of the array upper bound to the number of points is performed after all the points have been read in. An array violation occurs after only 3 points have been read in, but whether this gets detected depends quite a bit on the compiler and compiler options used.
Содержание
- Error Handling Functions
- Table of Contents
- User Contributed Notes 9 notes
- debug_backtrace
- Description
- Parameters
- Return Values
- Examples
- See Also
- User Contributed Notes 36 notes
Error Handling Functions
Table of Contents
User Contributed Notes 9 notes
I keep seeing qualification lists for error types/error-nums as arrays; In user notes and in the manual itself. For example, in this manual entry’s example, when trying to seperate behavior for the variable trace in the error report:
// set of errors for which a var trace will be saved
$user_errors = array( E_USER_ERROR , E_USER_WARNING , E_USER_NOTICE );
if ( in_array ( $errno , $user_errors )) <
//. whatever
>
//. ?>
I was under the impression that PHP error code values where bitwise flag values. Wouldn’t bitwise masking be better? So I propose a slightly better way:
//.
$user_errors = E_USER_ERROR | E_USER_WARNING | E_USER_NOTICE ;
if ( $errno & $user_errors ) <
//. whatever
>
//. ?>
Or for those of you who don’t like the idea of using an integer as the condition in an if statement:
if (( $errno & $user_errors ) > 0 ) <
//. whatever
>
?>
I think that’s much more efficient than using _yet another_ array() constuct and an in_array().
If I am wrong, and the E_* constants aren’t supposed to be used in this fashion (ie, the constans aren’t guaranteed to be bitwise, which would be odd since that’s how they’re setup in the php.ini file), then delete me. I just don’t see why one should be using arrays when bitwise comparisons will work, considering the bitwise method should be MUCH more efficient.
Although the root user writes to the files ‘error_log’ and ‘access_log’, the Apache user has to own the file referenced by ‘error_log = filename’ or no log entries will be written.
; From php.ini
; Log errors to specified file.
error_log = /usr/local/apache/logs/php.errors
[root@www logs]$ ls -l /usr/local/apache/logs/php.errors
-rw-r—r— 1 nobody root 27K Jan 27 16:58 php.errors
PHP5 only (only tested with php5.0).
If you, for some reason, prefer exceptions over errors and have your custom error handler (set_error_handler) wrap the error into an exception you have to be careful with your script.
Because if you, instead of just calling the exception handler, throws the exception, and having a custom exception handler (set_exception_handler). And an error is being triggered inside that exception handler, you will get a weird error:
«Fatal error: Exception thrown without a stack frame in Unknown on line 0»
This error is not particulary informative, is it? 🙂
This example below will cause this error.
class PHPErrorException extends Exception
<
private $context = null ;
public function __construct
( $code , $message , $file , $line , $context = null )
<
parent :: __construct ( $message , $code );
$this -> file = $file ;
$this -> line = $line ;
$this -> context = $context ;
>
>;
function error_handler ( $code , $message , $file , $line ) <
throw new PHPErrorException ( $code , $message , $file , $line );
>
function exception_handler ( Exception $e )
<
$errors = array(
E_USER_ERROR => «User Error» ,
E_USER_WARNING => «User Warning» ,
E_USER_NOTICE => «User Notice» ,
);
echo $errors [ $e -> getCode ()]. ‘: ‘ . $e -> getMessage (). ‘ in ‘ . $e -> getFile ().
‘ on line ‘ . $e -> getLine (). «n» ;
echo $e -> getTraceAsString ();
>
set_error_handler ( ‘error_handler’ );
set_exception_handler ( ‘exception_handler’ );
// Throw exception with an /unkown/ error code.
throw new Exception ( ‘foo’ , 0 );
?>
There are however, easy fix for this as it’s only cause is sloppy code.
Like one, directly call exception_handler from error_handler instead of throwing an exception. Not only does it remedy this problem, but it’s also faster. Though this will cause a `regular` unhandled exception being printed and if only «designed» error messages are intended, this is not the ultimate solution.
So, what is there to do? Make sure the code in exception_handlers doesn’t cause any errors! In this case a simple isset() would have solved it.
If you are using PHP as an Apache module, your default behavior may be to write PHP error messages to Apache’s error log. This is because the error_log .ini directive may be set equal to «error_log» which is also the name of Apache’s error log. I think this is intentional.
However, you can separate Apache errors from PHP errors if you wish by simply setting a different value for error_log. I write mine in the /var/log folder.
When configuring your error log file in php.ini, you can use an absolute path or a relative path. A relative path will be resolved based on the location of the generating script, and you’ll get a log file in each directory you have scripts in. If you want all your error messages to go to the same file, use an absolute path to the file.
In some application development methodologies, there is the concept of an application root directory, indicated by «/» (even on Windows). However, PHP does not seem to have this concept, and using a «/» as the initial character in a log file path produces weird behavior on Windows.
If you are running on Windows and have set, in php.ini:
You will get some, but not all, error messages. The file will appear at
and contain internally generated error messages, making it appear that error logging is working. However, log messages requested by error_log() do NOT appear here, or anywhere else, making it appear that the code containing them did not get processed.
Apparently on Windows the internally generated errors will interpret «/» as «C:» (or possibly a different drive if you have Windows installed elsewhere — I haven’t tested this). However, the error_log process apparently can’t find «/» — understandably enough — and the message is dropped silently.
It is totally possible to use debug_backtrace() inside an error handling function. Here, take a look:
function errorHandler ( $errno , $errstr , $errfile , $errline , $errcontext )
<
echo ‘Into ‘ . __FUNCTION__ . ‘() at line ‘ . __LINE__ .
«nn—ERRNO—n» . print_r ( $errno , true ).
«nn—ERRSTR—n» . print_r ( $errstr , true ).
«nn—ERRFILE—n» . print_r ( $errfile , true ).
«nn—ERRLINE—n» . print_r ( $errline , true ).
«nn—ERRCONTEXT—n» . print_r ( $errcontext , true ).
«nnBacktrace of errorHandler()n» .
print_r ( debug_backtrace (), true );
>
function a ( )
<
//echo «a()’s backtracen».print_r( debug_backtrace(), true);
asdfasdf ; // oops
>
function b ()
<
//echo «b()’s backtracen».print_r( debug_backtrace(), true);
a ();
>
Into errorhandler() at line 9
—ERRSTR—
Use of undefined constant asdfasdf — assumed ‘asdfasdf’
Backtrace of errorHandler()
Array
(
[0] => Array
(
[function] => errorhandler
[args] => Array
(
[0] => 8
[1] => Use of undefined constant asdfasdf — assumed ‘asdfasdf’
[2] => /home/theotek/test-1.php
[3] => 23
[4] => Array
(
)
[1] => Array
(
[file] => /home/theotek/test-1.php
[line] => 23
[function] => a
)
[2] => Array
(
[file] => /home/theotek/test-1.php
[line] => 30
[function] => a
[args] => Array
(
)
[3] => Array
(
[file] => /home/theotek/test-1.php
[line] => 33
[function] => b
[args] => Array
(
)
So, the first member of the backtrace’s array is not really surprising, except from the missing «file» and «line» members.
The second member of the backtrace seem the be a hook inside the zend engine that is used to trigger the error.
Источник
debug_backtrace
(PHP 4 >= 4.3.0, PHP 5, PHP 7, PHP
debug_backtrace — Generates a backtrace
Description
debug_backtrace() generates a PHP backtrace.
Parameters
This parameter is a bitmask for the following options:
debug_backtrace() options
DEBUG_BACKTRACE_PROVIDE_OBJECT | Whether or not to populate the «object» index. |
DEBUG_BACKTRACE_IGNORE_ARGS | Whether or not to omit the «args» index, and thus all the function/method arguments, to save memory. |
This parameter can be used to limit the number of stack frames returned. By default ( limit = 0 ) it returns all stack frames.
Return Values
Returns an array of associative array s. The possible returned elements are as follows:
Possible returned elements from debug_backtrace()
Name | Type | Description |
---|---|---|
function | string | The current function name. See also __FUNCTION__. |
line | int | The current line number. See also __LINE__. |
file | string | The current file name. See also __FILE__. |
class | string | The current class name. See also __CLASS__ |
object | object | The current object. |
type | string | The current call type. If a method call, «->» is returned. If a static method call, «::» is returned. If a function call, nothing is returned. |
args | array | If inside a function, this lists the functions arguments. If inside an included file, this lists the included file name(s). |
Examples
Example #1 debug_backtrace() example
function a_test ( $str )
<
echo «nHi: $str » ;
var_dump ( debug_backtrace ());
>
a_test ( ‘friend’ );
?>
// filename: /tmp/b.php
include_once ‘/tmp/a.php’ ;
?>
Results similar to the following when executing /tmp/b.php :
See Also
- trigger_error() — Generates a user-level error/warning/notice message
- debug_print_backtrace() — Prints a backtrace
User Contributed Notes 36 notes
Here’s a function I just wrote for getting a nice and comprehensible call trace. It is probably more resource-intensive than some other alternatives but it is short, understandable, and gives nice output (Exception->getTraceAsString()).
function generateCallTrace ()
<
$e = new Exception ();
$trace = explode ( «n» , $e -> getTraceAsString ());
// reverse array to make steps line up chronologically
$trace = array_reverse ( $trace );
array_shift ( $trace ); // remove
array_pop ( $trace ); // remove call to this method
$length = count ( $trace );
$result = array();
for ( $i = 0 ; $i $length ; $i ++)
<
$result [] = ( $i + 1 ) . ‘)’ . substr ( $trace [ $i ], strpos ( $trace [ $i ], ‘ ‘ )); // replace ‘#someNum’ with ‘$i)’, set the right ordering
>
return «t» . implode ( «nt» , $result );
>
?>
Example output:
1) /var/www/test/test.php(15): SomeClass->__construct()
2) /var/www/test/SomeClass.class.php(36): SomeClass->callSomething()
Simple function to get a string in form «filename: [class->][function(): ]»
function get_caller_info () <
$c = » ;
$file = » ;
$func = » ;
$class = » ;
$trace = debug_backtrace ();
if (isset( $trace [ 2 ])) <
$file = $trace [ 1 ][ ‘file’ ];
$func = $trace [ 2 ][ ‘function’ ];
if (( substr ( $func , 0 , 7 ) == ‘include’ ) || ( substr ( $func , 0 , 7 ) == ‘require’ )) <
$func = » ;
>
> else if (isset( $trace [ 1 ])) <
$file = $trace [ 1 ][ ‘file’ ];
$func = » ;
>
if (isset( $trace [ 3 ][ ‘class’ ])) <
$class = $trace [ 3 ][ ‘class’ ];
$func = $trace [ 3 ][ ‘function’ ];
$file = $trace [ 2 ][ ‘file’ ];
> else if (isset( $trace [ 2 ][ ‘class’ ])) <
$class = $trace [ 2 ][ ‘class’ ];
$func = $trace [ 2 ][ ‘function’ ];
$file = $trace [ 1 ][ ‘file’ ];
>
if ( $file != » ) $file = basename ( $file );
$c = $file . «: » ;
$c .= ( $class != » ) ? «:» . $class . «->» : «» ;
$c .= ( $func != » ) ? $func . «(): » : «» ;
return( $c );
>
?>
Usage like:
function debug ( $str ) <
echo get_caller_info () . $str . «
n» ;
>
?>
get_caller_info() will return info about the function /class->method that called debug().
Just a short note on debug_backtrace options for PHP 5.3.6 or newer:
debug_backtrace() — show all options
debug_backtrace(0) — exlude [«object»]
debug_backtrace(1) — same as debug_backtrace()
debug_backtrace(2) — exlude [«object»] AND [«args»]
use this example and try calling debug_backtrace with different options
function F1 ()
<
echo «
» ;
echo «in F1 now» ;
echo «» ;
>
class DebugOptionsTest
<
function F2 ()
<
echo «
» ;
echo «in F2 now» ;
F1 ();
>
echo » calling F1″ ;
F1 ();
$c =new DebugOptionsTest ();
echo » calling F2″ ;
$c -> F2 ( «testValue» );
Howdy guys, just a note really — The [‘args’] data within the resulting array is supplied by reference. I found myself editing the reference unknowingly which in turn shows its ugly head further down the line if you call multiple backtrace.
// LOOP BACKTRACE
$la = 0 ;
$lb = count ( $trace );
while ( $la $lb )<
// DATA FROM BACKTRACE
$trace [ $la ][ ‘file’ ];
$trace [ $la ][ ‘line’ ];
$trace [ $la ][ ‘args’ ];
$trace [ $la ][ ‘function’ ];
// DATA FROM BACKTRACE
// LOOP ARGUMENTS ARRAY
$ba = 0 ;
$bb = count ( $trace [ $la ][ ‘args’ ]);
while ( $ba $bb )<
$trace [ $la ][ ‘args’ ][ $ba ] = «EDITING A REFERENCE/POINTER» ;
$ba ++;
>
unset( $bb );
unset( $ba );
// LOOP ARGUMENTS ARRAY
$la ++;
>
unset( $lb );
unset( $la );
// LOOP BACKTRACE
?>
Be carefull if you are using objects as arguments for function calls!
function myPrint ( $trace ) <
foreach( $trace as $i => $call ) <
/**
* THIS IS NEEDED! If all your objects have a __toString function it’s not needed!
*
* Catchable fatal error: Object of class B could not be converted to string
* Catchable fatal error: Object of class A could not be converted to string
* Catchable fatal error: Object of class B could not be converted to string
*/
if ( is_object ( $call [ ‘object’ ])) < $call [ ‘object’ ] = ‘CONVERTED OBJECT OF CLASS ‘ . get_class ( $call [ ‘object’ ]); >
if ( is_array ( $call [ ‘args’ ])) <
foreach ( $call [ ‘args’ ] AS & $arg ) <
if ( is_object ( $arg )) < $arg = ‘CONVERTED OBJECT OF CLASS ‘ . get_class ( $arg ); >
>
>
$trace_text [ $i ] = «#» . $i . » » . $call [ ‘file’ ]. ‘(‘ . $call [ ‘line’ ]. ‘) ‘ ;
$trace_text [ $i ].= (!empty( $call [ ‘object’ ])? $call [ ‘object’ ]. $call [ ‘type’ ]: » );
$trace_text [ $i ].= $call [ ‘function’ ]. ‘(‘ . implode ( ‘, ‘ , $call [ ‘args’ ]). ‘)’ ;
>
class A <
public function test ( $obj ) <
$obj -> test ();
>
>
class B <
public function test () <
echo myPrint ( debug_backtrace ());
>
>
$A = new A ();
$B = new B ();
Quick and dirty formatted output from debug_backtrace.
foreach($file_paths AS $file_path) <
foreach($file_path AS $key => $var) <
if($key == ‘args’) <
foreach($var AS $key_arg => $var_arg) <
echo $key_arg . ‘: ‘ . $var_arg . ‘
‘;
>
> else <
echo $key . ‘: ‘ . $var . ‘
‘;
>
>
>
I want to point out that debug_backtrace() in new versions of php can detect recursion // circular references .. avoiding memory consumption.
class ParentClass <
public function __construct ()
<
$this -> _child = new ChildClass ( $this );
var_dump ( debug_backtrace ());
>
>
class ChildClass <
public function __construct ( ParentClass $p )
<
$this -> _parent = $p ;
>
>
$test = new ParentClass ();
?>
Output:
array(1) <
[0]=>
array(7) <
[«file»]=>
string(23) «/home/jcm/testdebug.php»
[«line»]=>
int(18)
[«function»]=>
string(11) «__construct»
[«class»]=>
string(11) «ParentClass»
[«object»]=>
object(ParentClass)#1 (1) <
[«_child»]=>
object(ChildClass)#2 (1) <
[«_parent»]=>
*RECURSION*
>
>
[«type»]=>
string(2) «->»
[«args»]=>
array(0) <
>
>
>
Attention in the *RECURSION* hint provided
When using debug_backtrace() to check if you’re being accessed from another caller, please remember to ask debug_backtrace to only go as far as needed in depth and skip taking the entire debug object as return parameter:
if ( count ( debug_backtrace ( FALSE , 1 )) == 0 )
<
// Do something
>
?>
It works a little bit different with resources in different PHP versions.
For example:
function foo($bar)
<
return debug_backtrace();
>
$resource = fopen(__FILE__, ‘r’);
$backtrace = foo($resource);
echo «when resource is opened: » . gettype($backtrace[0][‘args’][0]) . «n»;
fclose($resource);
echo «when resource is closed: » . gettype($backtrace[0][‘args’][0]) . «n»;
With 5.3.10 I got:
when resource is opened: resource
when resource is closed: resource
With 5.5.9:
when resource is opened: resource
when resource is closed: unknown type
Here’s my little updated contribution — it prints colorful output in the way I prefer. Define a helper function isRootIp() that contains an array including your IP; then calls to bt() simply return, so you can sprinkle backtraces in live sites w/o anyone knowing.
function bt ()
<
if( ! isRootIp () )
<
return false ;
>
array_walk ( debug_backtrace (), create_function ( ‘$a,$b’ , ‘print «
«. basename( $a[’file’] ). « <$a[‘line’]> <$a[‘function’]>() — «. dirname( $a[’file’] ). «/»;’ ) );
>
?>
I use this simple but effective function so i can see which method in the child class called the current method (in the parent class).
function get_caller_method ()
<
$traces = debug_backtrace ();
if (isset( $traces [ 2 ]))
<
return $traces [ 2 ][ ‘function’ ];
>
initialize
debug example.php> code-lines: 39-41 time: 2.0002 mem: 19 KB
debug example.php> code-lines: 41-44 time: 0.0000 mem: 19 KB
debug example.php> code-lines: 44-51 time: 0.6343 mem: 9117 KB
debug example.php> code-lines: 51-53 time: 0.1003 mem: 9117 KB
debug example.php> code-lines: 53-55 time: 0.0595 mem: 49 KB
*/
function debug()
<
static $start_time = NULL;
static $start_code_line = 0;
$call_info = array_shift( debug_backtrace() );
$code_line = $call_info[‘line’];
$file = array_pop( explode(‘/’, $call_info[‘file’]));
if( $start_time === NULL )
<
print «debug «.$file.»> initializen»;
$start_time = time() + microtime();
$start_code_line = $code_line;
return 0;
>
printf(«debug %s> code-lines: %d-%d time: %.4f mem: %d KBn», $file, $start_code_line, $code_line, (time() + microtime() — $start_time), ceil( memory_get_usage()/1024));
$start_time = time() + microtime();
$start_code_line = $code_line;
>
Here is a function to cleanly output the debug_backtrace to the error_log
/*
* Send the output from a backtrace to the error_log
* @param string $message Optional message that will be sent the the error_log before the backtrace
*/
function log_trace ( $message = » ) <
$trace = debug_backtrace ();
if ( $message ) <
error_log ( $message );
>
$caller = array_shift ( $trace );
$function_name = $caller [ ‘function’ ];
error_log ( sprintf ( ‘%s: Called from %s:%s’ , $function_name , $caller [ ‘file’ ], $caller [ ‘line’ ]));
foreach ( $trace as $entry_id => $entry ) <
$entry [ ‘file’ ] = $entry [ ‘file’ ] ? : ‘-‘ ;
$entry [ ‘line’ ] = $entry [ ‘line’ ] ? : ‘-‘ ;
if (empty( $entry [ ‘class’ ])) <
error_log ( sprintf ( ‘%s %3s. %s() %s:%s’ , $function_name , $entry_id + 1 , $entry [ ‘function’ ], $entry [ ‘file’ ], $entry [ ‘line’ ]));
> else <
error_log ( sprintf ( ‘%s %3s. %s->%s() %s:%s’ , $function_name , $entry_id + 1 , $entry [ ‘class’ ], $entry [ ‘function’ ], $entry [ ‘file’ ], $entry [ ‘line’ ]));
>
>
>
?>
A usual entry looks like this:
array( 6 ) <
‘file’ =>
string ( 87 ) «DbSelector.php»
‘line’ =>
int ( 171 )
‘function’ =>
string ( 5 ) «error»
‘class’ =>
string ( 42 ) «LoggingService»
‘type’ =>
string ( 2 ) «::»
‘args’ =>
array( 1 ) <
[ 0 ] =>
string ( 27 ) «Connecting to DB: unittests»
>
>
?>
Be warned though that ‘file’ and ‘class’ do not reference the same thing!
‘file’ means which file calls the next step.
‘class’ is the next step being called.
So ‘file’ is the caller, ‘class’ is the callee.
Another variation formatting backtrace.
Parameter $ignore to ignore the extra calls.
/**
* Getting backtrace
*
* @param int $ignore ignore calls
*
* @return string
*/
protected function getBacktrace ( $ignore = 2 )
<
$trace = » ;
foreach ( debug_backtrace () as $k => $v ) <
if ( $k $ignore ) <
continue;
>
$trace .= ‘#’ . ( $k — $ignore ) . ‘ ‘ . $v [ ‘file’ ] . ‘(‘ . $v [ ‘line’ ] . ‘): ‘ . (isset( $v [ ‘class’ ]) ? $v [ ‘class’ ] . ‘->’ : » ) . $v [ ‘function’ ] . ‘(‘ . implode ( ‘, ‘ , $v [ ‘args’ ]) . ‘)’ . «n» ;
>
need no Xdebug or dbg.so on server, return more detailed message:
diyism_trace.php:
( TRACES_MODE , ‘TEXTAREA’ ); //’TEXTAREA’ or ‘FIREPHP’
$GLOBALS [ ‘traces.pre’ ]=array();
function my_array_diff ( $arr1 , $arr2 )
$v )
>
>
return $arr1 ;
>
function my_var_export ( $var , $is_str = false )
< $rtn = preg_replace (array( ‘/Arrays+(/’ , ‘/[(d+)] =>(.*)n/’ , ‘/[([^d].*)] => (.*)n/’ ), array( ‘array (‘ , ‘1 => ’2» . «n» , ‘’1’ => ’2» . «n» ), substr ( print_r ( $var , true ), 0 , — 1 ));
$rtn = strtr ( $rtn , array( «=> ‘array (‘» => ‘=> array (‘ ));
$rtn = strtr ( $rtn , array( «)nn» => «)n» ));
$rtn = strtr ( $rtn , array( «‘n» => «‘,n» , «)n» => «),n» ));
$rtn = preg_replace (array( ‘/n +/e’ ), array( ‘strtr(’’, array(’ ’=>’ ’))’ ), $rtn );
$rtn = strtr ( $rtn , array( » Object’,» => » Object’ ));
if ( $is_str )
>
else
>
>
function tick_handler ()
< $tmp = debug_backtrace ();
$trace = my_array_diff ( $tmp , $GLOBALS [ ‘traces.pre’ ]);
//echo »;echo ‘
‘; //for debug diyism_trace.php
$trace = array_values ( $trace );
$GLOBALS [ ‘traces.pre’ ]= $tmp ;
if ( count ( $trace )> 0 && $trace [ 0 ][ ‘file’ ]. ‘/’ .@ $tmp [ 1 ][ ‘function’ ]!==@ $GLOBALS [ ‘traces’ ][ count ( $GLOBALS [ ‘traces’ ])- 1 ][ ‘key’ ]) //filter empty array and rearrange array_values(), because some lines will trigger two tick events per line, for example: 1.last line is «some code;questmark>» 2.error_reporting(.
= 0 ; — $i )
< $GLOBALS [ ‘traces’ ][]= $tmp_fb = array_merge (array( ‘key’ =>$trace [ $i ][ ‘file’ ]. ‘/’ .@ $tmp [ $i + 1 ][ ‘function’ ]), $trace [ $i ], array( ‘function’ => strtr ( $trace [ $i ][ ‘function’ ], array( ‘tick_handler’ => ‘CONTINUE’ )), ‘in_function’ =>@ $tmp [ $i + 1 ][ ‘function’ ]));
TRACES_MODE === ‘FIREPHP’ ? fb ( trace_output ( $tmp_fb ), ‘diyism_trace:’ .++ $GLOBALS [ ‘diyism_trace_no’ ]): » ;
>
>
>
function trace_output ( $trace )
< $trace [ ‘in_function’ ]= strtr (@ $trace [ ‘in_function’ ], array( ‘require’ =>» , ‘require_once’ => » , ‘include’ => » , ‘include_once’ => » ));
$trace [ ‘args’ ]= $trace [ ‘args’ ]? strtr ( preg_replace (array( ‘/n +/’ ), array( » ), preg_replace (array( ‘/n d+ => /’ ), array( » ), substr ( my_var_export ( $trace [ ‘args’ ], true ), 7 , — 3 ))), array( «r» => ‘r’ , «n» => ‘n’ )): » ;
return $trace [ ‘file’ ].( $trace [ ‘in_function’ ]? ‘/’ . $trace [ ‘in_function’ ]. ‘()’ : » ). ‘/’ . $trace [ ‘line’ ]. ‘: ‘ . $trace [ ‘function’ ]. ‘(‘ . $trace [ ‘args’ ]. ‘)’ ;
>
function traces_output ()
>
register_tick_function ( ‘tick_handler’ );
TRACES_MODE === ‘TEXTAREA’ ? register_shutdown_function ( ‘traces_output’ ): » ;
?>
test.php:
declare( ticks = 1 );
require ‘diyism_trace.php’ ;
Surprisingly, no one has described one of the best uses of this: dumping a variable and showing the location. When debugging, especially a big and unfamiliar system, it’s a pain remembering where I added those var dumps. Also, this way there is a separator between multiple dump calls.
function dump ( $var ) <
$result = var_export ( $var , true );
$loc = whereCalled ();
return «n» ;
>
function whereCalled ( $level = 1 ) <
$trace = debug_backtrace ();
$file = $trace [ $level ][ ‘file’ ];
$line = $trace [ $level ][ ‘line’ ];
$object = $trace [ $level ][ ‘object’ ];
if ( is_object ( $object ))
return «Where called: line $line of $object n(in $file )» ;
>
?>
In addition, calling ‘whereCalled()’ from any function will quickly identify locations that are doing something unexpected (e.g., updating a property at the wrong time). I’m new to PHP, but have used the equivalent in Perl for years.
Further to my previous note, the ‘object’ element of the array can be used to get the parent object. So changing the get_class_static() function to the following will make the code behave as expected:
function get_class_static () <
$bt = debug_backtrace ();
if (isset( $bt [ 1 ][ ‘object’ ]))
return get_class ( $bt [ 1 ][ ‘object’ ]);
else
return $bt [ 1 ][ ‘class’ ];
>
?>
HOWEVER, it still fails when being called statically. Changing the last two lines of my previous example to
:: printClassName ();
bar :: printClassName ();
?>
. still gives the same problematic result in PHP5, but in this case the ‘object’ property is not set, so that technique is unavailable.
I find it useful to know if a function is being called. in Java for instance you usually print a line with the functionname and arguments in the beginning of the function. I wanted to achieve the same thing in php thus i wrote the following class:
class Debug
<
private static $calls ;
public static function log ( $message = null )
<
if(! is_array ( self :: $calls ))
self :: $calls = array();
$call = debug_backtrace ( false );
$call = (isset( $call [ 1 ]))? $call [ 1 ]: $call [ 0 ];
$call [ ‘message’ ] = $message ;
array_push ( self :: $calls , $call );
>
>
?>
include this class before anything else
usage: Debug::log($message); at the beginning of your function.
write yourself a nice printout of the data;
Everybody seems to have their favorite use. I substitute this function for die(). It gives a message
to the user and emails me a PrettyPrint of what went wrong. $info is set by me,
and it does a special check in the database object.
function var_format ( $v ) // pretty-print var_export
<
return ( str_replace (array( «n» , » » , «array» ),
array( «
» , » » , » array» ),
var_export ( $v , true )). «
» );
>
function myDie ( $info )
<
$mysqlerr = strpos ( $info , «ERROR=You have an error in your SQL syntax» );
if( $mysqlerr > 0 ) $info = substr ( $info , 0 , $mysqlerr ). » mySql format error» ;
$out = «
MSG=’ $info ‘
» . var_format ( $_REQUEST ). «
» ;
$bt = debug_backtrace ();
$sp = 0 ;
$trace = «» ;
foreach( $bt as $k => $v )
<
extract ( $v );
$file = substr ( $file , 1 + strrpos ( $file , «/» ));
if( $file == «db.php» )continue; // the db object
$trace .= str_repeat ( » » ,++ $sp ); //spaces(++$sp);
$trace .= «file= $file , line= $line , function= $function
» ;
>
$out .= «
» . backTrace ();
if( substr ( $info , 0 , 4 )== «XXX » ) // special errrors when db is inaccessible
<
$out = str_replace ( «
» , «n» , $out );
$out = str_replace ( » » , » » , $out );
mail ( «me@example.com» , «Database Execution Error for user » . $REMOTE_ADDR , » $out » );
exit( «Database Access Error. Please try again later.» );
>
mail ( «me@example.com» , ‘Error Monitor’ , ‘Execution Error’ , $out );
exit( «DANG! An execution error in the program has been sent to the webmaster.
If you don’t get an email from him soon, please call him.» );
>
?>
This produces an output like this
file=badmode.php, line=5, function=backTrace
file=login.php, line=209, function=require
file=midScreen.php, line=264, function=require
file=masterindex.php, line=161, function=require
file=production2.php, line=121, function=require
file=index.php, line=16, function=require
It should be noted that if an internal php function such as call_user_func in the backtrace, the ‘file’ and ‘line’ entries will not be set.
Most debug tracers will use these entries. You should place a check to see if the key exists in the array before using this function. Otherwise notices will be generated.
foreach ( $arrTrace as $arr )
<
if (!isset ( $arr [ ‘file’ ]))
<
$arr [ ‘file’ ] = ‘[PHP Kernel]’ ;
>
Источник
Debugging the compiler
This chapter contains a few tips to debug the compiler. These tips aim to be
useful no matter what you are working on. Some of the other chapters have
advice about specific parts of the compiler (e.g. the Queries Debugging and
Testing chapter or the LLVM Debugging
chapter).
Configuring the compiler
By default, rustc is built without most debug information. To enable debug info,
set debug = true
in your config.toml.
Setting debug = true
turns on many different debug options (e.g., debug-assertions
,
debug-logging
, etc.) which can be individually tweaked if you want to, but many people
simply set debug = true
.
If you want to use GDB to debug rustc, please set config.toml
with options:
[rust] debug = true debuginfo-level = 2
NOTE:
This will use a lot of disk space
(upwards of 35GB),
and will take a lot more compile time.
Withdebuginfo-level = 1
(the default whendebug = true
),
you will be able to track the execution path,
but will lose the symbol information for debugging.
The default configuration will enable symbol-mangling-version
v0.
This requires at least GDB v10.2,
otherwise you need to disable new symbol-mangling-version in config.toml
.
[rust] new-symbol-mangling = false
See the comments in
config.toml.example
for more info.
You will need to rebuild the compiler after changing any configuration option.
-Z
flags
The compiler has a bunch of -Z
flags. These are unstable flags that are only
enabled on nightly. Many of them are useful for debugging. To get a full listing
of -Z
flags, use -Z help
.
One useful flag is -Z verbose
, which generally enables printing more info that
could be useful for debugging.
Getting a backtrace
When you have an ICE (panic in the compiler), you can set
RUST_BACKTRACE=1
to get the stack trace of the panic!
like in
normal Rust programs. IIRC backtraces don’t work on MinGW,
sorry. If you have trouble or the backtraces are full of unknown
,
you might want to find some way to use Linux, Mac, or MSVC on Windows.
In the default configuration (without debug
set to true
), you don’t have line numbers
enabled, so the backtrace looks like this:
stack backtrace:
0: std::sys::imp::backtrace::tracing::imp::unwind_backtrace
1: std::sys_common::backtrace::_print
2: std::panicking::default_hook::{{closure}}
3: std::panicking::default_hook
4: std::panicking::rust_panic_with_hook
5: std::panicking::begin_panic
(~~~~ LINES REMOVED BY ME FOR BREVITY ~~~~)
32: rustc_typeck::check_crate
33: <std::thread::local::LocalKey<T>>::with
34: <std::thread::local::LocalKey<T>>::with
35: rustc::ty::context::TyCtxt::create_and_enter
36: rustc_driver::driver::compile_input
37: rustc_driver::run_compiler
If you set debug = true
, you will get line numbers for the stack trace.
Then the backtrace will look like this:
stack backtrace:
(~~~~ LINES REMOVED BY ME FOR BREVITY ~~~~)
at /home/user/rust/compiler/rustc_typeck/src/check/cast.rs:110
7: rustc_typeck::check::cast::CastCheck::check
at /home/user/rust/compiler/rustc_typeck/src/check/cast.rs:572
at /home/user/rust/compiler/rustc_typeck/src/check/cast.rs:460
at /home/user/rust/compiler/rustc_typeck/src/check/cast.rs:370
(~~~~ LINES REMOVED BY ME FOR BREVITY ~~~~)
33: rustc_driver::driver::compile_input
at /home/user/rust/compiler/rustc_driver/src/driver.rs:1010
at /home/user/rust/compiler/rustc_driver/src/driver.rs:212
34: rustc_driver::run_compiler
at /home/user/rust/compiler/rustc_driver/src/lib.rs:253
Getting a backtrace for errors
If you want to get a backtrace to the point where the compiler emits an
error message, you can pass the -Z treat-err-as-bug=n
, which will make
the compiler panic on the nth
error on delay_span_bug
. If you leave
off =n
, the compiler will assume 1
for n
and thus panic on the
first error it encounters.
This can also help when debugging delay_span_bug
calls — it will make
the first delay_span_bug
call panic, which will give you a useful backtrace.
For example:
$ rustc +stage1 error.rs
error[E0277]: cannot add `()` to `{integer}`
--> error.rs:2:7
|
2 | 1 + ();
| ^ no implementation for `{integer} + ()`
|
= help: the trait `Add<()>` is not implemented for `{integer}`
error: aborting due to previous error
Now, where does the error above come from?
$ RUST_BACKTRACE=1 rustc +stage1 error.rs -Z treat-err-as-bug
error[E0277]: the trait bound `{integer}: std::ops::Add<()>` is not satisfied
--> error.rs:2:7
|
2 | 1 + ();
| ^ no implementation for `{integer} + ()`
|
= help: the trait `std::ops::Add<()>` is not implemented for `{integer}`
error: internal compiler error: unexpected panic
note: the compiler unexpectedly panicked. this is a bug.
note: we would appreciate a bug report: https://github.com/rust-lang/rust/blob/master/CONTRIBUTING.md#bug-reports
note: rustc 1.24.0-dev running on x86_64-unknown-linux-gnu
note: run with `RUST_BACKTRACE=1` for a backtrace
thread 'rustc' panicked at 'encountered error with `-Z treat_err_as_bug',
/home/user/rust/compiler/rustc_errors/src/lib.rs:411:12
note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose
backtrace.
stack backtrace:
(~~~ IRRELEVANT PART OF BACKTRACE REMOVED BY ME ~~~)
7: rustc::traits::error_reporting::<impl rustc::infer::InferCtxt<'a, 'tcx>>
::report_selection_error
at /home/user/rust/compiler/rustc_middle/src/traits/error_reporting.rs:823
8: rustc::traits::error_reporting::<impl rustc::infer::InferCtxt<'a, 'tcx>>
::report_fulfillment_errors
at /home/user/rust/compiler/rustc_middle/src/traits/error_reporting.rs:160
at /home/user/rust/compiler/rustc_middle/src/traits/error_reporting.rs:112
9: rustc_typeck::check::FnCtxt::select_obligations_where_possible
at /home/user/rust/compiler/rustc_typeck/src/check/mod.rs:2192
(~~~ IRRELEVANT PART OF BACKTRACE REMOVED BY ME ~~~)
36: rustc_driver::run_compiler
at /home/user/rust/compiler/rustc_driver/src/lib.rs:253
Cool, now I have a backtrace for the error!
Getting the the error creation location
-Z track-diagnostics
can help figure out where errors are emitted. It uses #[track_caller]
for this and prints its location alongside the error:
$ RUST_BACKTRACE=1 rustc +stage1 error.rs -Z track-diagnostics
error[E0277]: cannot add `()` to `{integer}`
--> srcerror.rs:2:7
|
2 | 1 + ();
| ^ no implementation for `{integer} + ()`
-Ztrack-diagnostics: created at compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs:638:39
|
= help: the trait `Add<()>` is not implemented for `{integer}`
= help: the following other types implement trait `Add<Rhs>`:
<&'a f32 as Add<f32>>
<&'a f64 as Add<f64>>
<&'a i128 as Add<i128>>
<&'a i16 as Add<i16>>
<&'a i32 as Add<i32>>
<&'a i64 as Add<i64>>
<&'a i8 as Add<i8>>
<&'a isize as Add<isize>>
and 48 others
For more information about this error, try `rustc --explain E0277`.
This is similar but different to -Z treat-err-as-bug
:
- it will print the locations for all errors emitted
- it does not require a compiler built with debug symbols
- you don’t have to read through a big stack trace.
Getting logging output
The compiler uses the tracing
crate for logging.
For details see the guide section on tracing
Formatting Graphviz output (.dot files)
Some compiler options for debugging specific features yield graphviz graphs —
e.g. the #[rustc_mir(borrowck_graphviz_postflow="suffix.dot")]
attribute
dumps various borrow-checker dataflow graphs.
These all produce .dot
files. To view these files, install graphviz (e.g.
apt-get install graphviz
) and then run the following commands:
$ dot -T pdf maybe_init_suffix.dot > maybe_init_suffix.pdf $ firefox maybe_init_suffix.pdf # Or your favorite pdf viewer
Viewing Spanview output (.html files)
In addition to graphviz output, MIR debugging
flags include an option to generate a MIR representation called Spanview
that
uses HTML to highlight code regions in the original source code and display
compiler metadata associated with each region.
-Z dump-mir-spanview
, for example, highlights spans
associated with each MIR Statement
, Terminator
, and/or BasicBlock
.
These .html
files use CSS features to dynamically expand spans obscured by
overlapping spans, and native tooltips (based on the HTML title
attribute) to
reveal the actual MIR elements, as text.
To view these files, simply use a modern browser, or a CSS-capable HTML preview
feature in a modern IDE. (The default HTML preview pane in VS Code is known to
work, for instance.)
Narrowing (Bisecting) Regressions
The cargo-bisect-rustc tool can be used as a quick and easy way to
find exactly which PR caused a change in rustc
behavior. It automatically
downloads rustc
PR artifacts and tests them against a project you provide
until it finds the regression. You can then look at the PR to get more context
on why it was changed. See this tutorial on how to use
it.
Downloading Artifacts from Rust’s CI
The rustup-toolchain-install-master tool by kennytm can be used to
download the artifacts produced by Rust’s CI for a specific SHA1 — this
basically corresponds to the successful landing of some PR — and then sets
them up for your local use. This also works for artifacts produced by @bors try
. This is helpful when you want to examine the resulting build of a PR
without doing the build yourself.
Debugging type layouts
The (permanently) unstable #[rustc_layout]
attribute can be used to dump
the Layout
of the type it is attached to. For example:
#![feature(rustc_attrs)] #[rustc_layout(debug)] type T<'a> = &'a u32;
Will emit the following:
error: layout_of(&'a u32) = Layout {
fields: Primitive,
variants: Single {
index: 0,
},
abi: Scalar(
Scalar {
value: Pointer,
valid_range: 1..=18446744073709551615,
},
),
largest_niche: Some(
Niche {
offset: Size {
raw: 0,
},
scalar: Scalar {
value: Pointer,
valid_range: 1..=18446744073709551615,
},
},
),
align: AbiAndPrefAlign {
abi: Align {
pow2: 3,
},
pref: Align {
pow2: 3,
},
},
size: Size {
raw: 8,
},
}
--> src/lib.rs:4:1
|
4 | type T<'a> = &'a u32;
| ^^^^^^^^^^^^^^^^^^^^^
error: aborting due to previous error
Deriving Error
will generate an Error
implementation, that contains
(depending on the type) a source()
and a backtrace()
method. Please note,
at the time of writing backtrace
is only supported on nightly rust. So you
have to use that to make use of it.
For a struct, these methods always do the same. For an enum
they have separate
behaviour for each of the variants. The variant is first matched and then the
implementation will do the same as it would have done if the variant was a
struct.
Usually when you derive Error
you will also want to derive Display
and
often From
as well.
1.1 When and how does it derive backtrace()
?
- It’s a struct/variant with named fields and one of the fields is
calledbacktrace
. Then it would return that field as thebacktrace
. - It’s a tuple struct/variant and the type of exactly one of the fields is
calledBacktrace
. Then it would return that field as thebacktrace
. - One of the fields is annotated with
#[error(backtrace)]
. Then it would
return that field as thebacktrace
.
1.2 When and how does it derive source()
?
- It’s a struct/variant with named fields and one is the fields is
calledsource
. Then it would return that field as thesource
. - It’s a tuple struct/variant and there’s exactly one field that is not used as
thebacktrace
. So either a tuple struct with one field, or one with two where one
is thebacktrace
. Then it returns this field as thesource
. - One of the fields is annotated with
#[error(backtrace)]
. Then it would
return that field as thebacktrace
.
It’s possible to ignore a field or a whole enum variant completely for this
derive using the #[error(ignore)]
attribute. This will ignore it both for
detecting backtrace
and source
. It’s also possible to mark a field only
ignored for one of these methods by using #[error(not(backtrace))]
or
#[error(not(source))]
.
#![feature(backtrace)] use std::backtrace::Backtrace; #[derive(Default, Debug, Display, Error)] struct Simple; #[derive(Default, Debug, Display, Error)] struct WithSource { source: Simple, } #[derive(Default, Debug, Display, Error)] struct WithExplicitSource { #[error(source)] explicit_source: Simple, } #[derive(Default, Debug, Display, Error)] struct Tuple(Simple); #[derive(Default, Debug, Display, Error)] struct WithoutSource(#[error(not(source))] i32); #[derive(Debug, Display, Error)] #[display(fmt="An error with a backtrace")] struct WithSourceAndBacktrace { source: Simple, backtrace: Backtrace, } #[derive(Debug, Display, Error, From)] enum CompoundError { Simple, WithSource { source: Simple, }, WithExplicitSource { #[error(source)] explicit_source: WithSource, }, Tuple(WithExplicitSource), WithoutSource(#[error(not(source))] Tuple), } fn main() { assert!(Simple.source().is_none()); assert!(Simple.backtrace().is_none()); assert!(WithSource::default().source().is_some()); assert!(WithExplicitSource::default().source().is_some()); assert!(Tuple::default().source().is_some()); assert!(WithoutSource::default().source().is_none()); let with_source_and_backtrace = WithSourceAndBacktrace{ source: Simple, backtrace: Backtrace::capture(), }; assert!(with_source_and_backtrace.source().is_some()); assert!(with_source_and_backtrace.backtrace().is_some()); assert!(CompoundError::Simple.source().is_none()); assert!(CompoundError::from(Simple).source().is_some()); assert!(CompoundError::from(WithSource::default()).source().is_some()); assert!(CompoundError::from(WithExplicitSource::default()).source().is_some()); assert!(CompoundError::from(Tuple::default()).source().is_none()); }
Ian has created a shiny libbacktrace libray which should be used to replace the current implementation in libgfortran/runtime/backtrace.c, which uses unwinder and, if available, addr2line. libbacktrace is installed both as host library (i.e. for backtraces of the compiler when an ICE occurs) and as target library, to be used by "go" and possibly other users (e.g. libgfortran). TODO: a) Enable the building of the target library: --- ./gcc/fortran/config-lang.in.orig 2011-05-10 23:12:01.000000000 +0200 +++ ./gcc/fortran/config-lang.in 2012-09-13 22:06:38.000000000 +0200 @@ -30 +30 @@ compilers="f951$(exeext)" -target_libs=target-libgfortran +target_libs="target-libgfortran target-libbacktrace" b) Add --disable-target-libbacktrace to the toplevel configure to disable libbacktrace; e.g. for our embedded users. (toplevel implies a sync with sourceware; watch out for "go" which also uses the target library, check that "go" is still be working without target libbacktrace.) c) Configure check: Check whether the library is available. (See libgfortran/acinclude.m4's LIBGFOR_CHECK_FLOAT128 for some ideas how one can test this.) d) Configure check 2: Check whether BACKTRACE_SUPPORTED is set to 0 (-> backtrace-supported.h), in that case, it is also pointless to build the support. e) Replace the current version by calls to libbacktrace. Almost latest version of the patch: http://gcc.gnu.org/ml/gcc-patches/2012-09/msg00806.html Or wait a while and browse libbacktrace/ directly. * backtrace-supported.h contains BACKTRACE_USES_MALLOC and BACKTRACE_SUPPORTED * Available functions are listed in backtrace.h [The current version of libbacktrace only handles ELF+DWARF; one could consider keeping the other version for a while. On the other hand, I assume that other formats will soon be supported.]
You need unwind frames present for this to work, i.e. the space (and to some extent optimization-reducing - yes I'm sure) overhead of -funwind-tables. (Only x86_64 has this on, effectively.)
(In reply to comment #1)
> You need unwind frames present for this to work, i.e. the space (and to some
> extent optimization-reducing - yes I'm sure) overhead of -funwind-tables. (Only
> x86_64 has this on, effectively.)
How is this different from the current backtracing implementation in libgfortran?
(That being said, we should probably modify the driver program to always add -funwind-tables, which IIRC isn't done today)
(In reply to comment #2) > (In reply to comment #1) > > You need unwind frames present for this to work, > How is this different from the current backtracing implementation in > libgfortran? Right, it already has that dependence, sorry for the noise.
I have a patch, just need to clean it up a bit and test.
Bummer, I've hit a snag. Otherwise the patch works, but trying to do a symbolic backtrace from a signal handler fails (which was sort of the entire idea of using libbacktrace instead of forking addr2line). Ian, any idea what might go wrong? With the testcase below which is expected to fail due to a div-by-zero: module test contains subroutine c(num, denum, res) integer :: num, denum, res res = num / denum end subroutine c subroutine b(n, d, r) integer :: n, d, r call c(n, d, r) end subroutine b subroutine a(n, d, r) integer :: n, d, r call b(n, d, r) end subroutine a end module test program bt use test integer :: res call a(1, 0, res) print *, res end program bt compiled with "-g" the result is $ ./bt2.g Program received signal SIGFPE: Floating-point exception - erroneous arithmetic operation. Backtrace for this error: Program received signal SIGSEGV: Segmentation fault - invalid memory reference. Backtrace for this error: Segmentation fault (core dumped) backtrace via gdb: (gdb) r Starting program: /home/janne/src/gfortran/my-patches/pr54572-libbacktrace/bt2.g Program received signal SIGFPE, Arithmetic exception. 0x000000000040086b in __test_MOD_c () (gdb) c Continuing. Program received signal SIGFPE: Floating-point exception - erroneous arithmetic operation. Backtrace for this error: Program received signal SIGSEGV, Segmentation fault. 0x00007ffff7bb2a1c in read_uint32 () from /home/janne/src/gfortran/trunk/install/lib64/libgfortran.so.3 (gdb) bt #0 0x00007ffff7bb2a1c in read_uint32 () from /home/janne/src/gfortran/trunk/install/lib64/libgfortran.so.3 #1 0x00007ffff7bb53be in backtrace_dwarf_add () from /home/janne/src/gfortran/trunk/install/lib64/libgfortran.so.3 #2 0x00007ffff7bb72a7 in elf_add () from /home/janne/src/gfortran/trunk/install/lib64/libgfortran.so.3 #3 0x00007ffff7bb7696 in backtrace_initialize () from /home/janne/src/gfortran/trunk/install/lib64/libgfortran.so.3 #4 0x00007ffff7bb630d in fileline_initialize () from /home/janne/src/gfortran/trunk/install/lib64/libgfortran.so.3 #5 0x00007ffff7bb6427 in backtrace_pcinfo () from /home/janne/src/gfortran/trunk/install/lib64/libgfortran.so.3 #6 0x00007ffff7bb6831 in unwind () from /home/janne/src/gfortran/trunk/install/lib64/libgfortran.so.3 #7 0x00007ffff75b9ec9 in _Unwind_Backtrace () from /home/janne/src/gfortran/trunk/install/lib64/libgcc_s.so.1 #8 0x00007ffff7bb6885 in backtrace_full () from /home/janne/src/gfortran/trunk/install/lib64/libgfortran.so.3 #9 0x00007ffff7ad527e in _gfortrani_show_backtrace () at ../../../trunk-git/libgfortran/runtime/backtrace.c:92 #10 0x00007ffff7ad5888 in _gfortrani_backtrace_handler () at ../../../trunk-git/libgfortran/runtime/compile_options.c:129 #11 <signal handler called> #12 0x000000000040086b in __test_MOD_c () #13 0x0000000000400848 in __test_MOD_b () #14 0x000000000040081b in __test_MOD_a () #15 0x0000000000400898 in MAIN__ () #16 0x0000000000400930 in main () #17 0x00007ffff6fd176d in __libc_start_main (main=0x4008fc <main>, argc=1, ubp_av=0x7fffffffd718, init=<optimized out>, fini=<optimized out>, rtld_fini=<optimized out>, stack_end=0x7fffffffd708) at libc-start.c:226 #18 0x0000000000400709 in _start () For comparison, if I compile the testcase without "-g" then it works as expected: $ ./bt2 Program received signal SIGFPE: Floating-point exception - erroneous arithmetic operation. Backtrace for this error: 0x7fcf58e202a0 0x7fcf58e20887 0x7fcf5833149f 0x40086b 0x400847 0x40081a 0x400897 0x40092f 0x7fcf5831c76c 0x400708 Floating point exception (core dumped)
Why are there no line numbers in the backtrace from gdb? You said you compiled with -g. Are you sure that libbacktrace itself was compiled with -g?
The crash within libbacktrace is occurring as it tries to read the debug info. This is presumably a bug in libbacktrace, but I don't know what the problem is without more information. libbacktrace is pretty careful to only read memory that was explicitly read. There is presumably a bug there, but I don't know what it is. I doubt the fact that a signal occurred has anything to do with this. There seems to be something odd about the debug info, as shown both by the fact that libbacktrace crashes trying to read it and that gdb does not display file/line information.
(In reply to comment #7) > Why are there no line numbers in the backtrace from gdb? You said you compiled > with -g. Are you sure that libbacktrace itself was compiled with -g? I meant that I compiled the Fortran testcase with -g; GCC itself, including libbacktrace, was built with default flags which ought to be "-O2 -g", but I didn't specifically check how libbacktrace was built. Now that you mention it, it does indeed seem like libbacktrace doesn't have debug symbols for some reason. (In reply to comment #8) > The crash within libbacktrace is occurring as it tries to read the debug info. > This is presumably a bug in libbacktrace, but I don't know what the problem is > without more information. libbacktrace is pretty careful to only read memory > that was explicitly read. There is presumably a bug there, but I don't know > what it is. > > I doubt the fact that a signal occurred has anything to do with this. There > seems to be something odd about the debug info, as shown both by the fact that > libbacktrace crashes trying to read it and that gdb does not display file/line > information. I forgot to mention, that I'm able to get a symbolic backtrace from outside a signal handler. Though in that case my testcase used external procedures rather than module procedures, so I guess it's possible there's a bug in handling debug info for module procedures. I'll recheck this..
(In reply to comment #6)
> Created attachment 28779 [details]
> Patch to use libbacktrace
I have to apply the following patch on your patch in order to be able to compile it. ("MULTIBUILDTOP" is empty here and the library is not in "/libbacktrace".)
--- libgfortran-backtrace-pr54572.diff.orig 2012-11-27 10:09:13 +0100
+++ libgfortran-backtrace-pr54572.diff 2012-11-27 10:12:05 +0100
@@ -51 +51 @@ index abc23cd..dd325bd 100644
-+ -I$(MULTIBUILDTOP)/../libbacktrace
++ -I$(MULTIBUILDTOP)../libbacktrace
Additionally, I wonder whether one should have:
--- a/Makefile.def
+++ b/Makefile.def
languages = { language=fortran; gcc-check-target=check-fortran;
lib-check-target=check-target-libquadmath;
+ lib-check-target=check-target-libbacktrace;
lib-check-target=check-target-libgfortran; };
languages = { language=java; gcc-check-target=check-java;
And in the same file, I wonder which of the following two is correct:
+dependencies = { module=all-target-libgfortran; on=all-target-libbacktrace; };
or
+dependencies = { module=configure-target-libgfortran; on=all-target-libbacktrace; };
After compiling comment 5 with my changes of comment 10, I get: Backtrace for this error: 0x2b9567c7ca0d _gfortrani_show_backtrace /projects/tob/gcc-git/gcc/libgfortran/runtime/backtrace.c:92 0x2b9567c7d017 _gfortrani_backtrace_handler /projects/tob/gcc-git/gcc/libgfortran/runtime/compile_options.c:129 0x2b95687503ef ??? ???:0 0x40086b __test_MOD_c /dev/shm/foo.f90:5 0x400847 __test_MOD_b /dev/shm/foo.f90:10 0x40081a __test_MOD_a /dev/shm/foo.f90:15 0x400897 bt /dev/shm/foo.f90:22 0x40092f main /dev/shm/foo.f90:20 And before (i.e with addr2line), I got: Backtrace for this error: #0 0x2AC1DC8D7AE7 #1 0x2AC1DC8D80F2 #2 0x2AC1DD3A43EF #3 0x40086B in __test_MOD_c at foo.f90:5 #4 0x400847 in __test_MOD_b at foo.f90:10 #5 0x40081A in __test_MOD_a at foo.f90:15 #6 0x400897 in bt at foo.f90:22
(In reply to comment #9) > (In reply to comment #7) > > Why are there no line numbers in the backtrace from gdb? You said you compiled > > with -g. Are you sure that libbacktrace itself was compiled with -g? > > I meant that I compiled the Fortran testcase with -g; GCC itself, including > libbacktrace, was built with default flags which ought to be "-O2 -g", but I > didn't specifically check how libbacktrace was built. Now that you mention it, > it does indeed seem like libbacktrace doesn't have debug symbols for some > reason. So yes, libbacktrace is compiled with debug information, however, the issue was that gdb 7.4 couldn't handle some DWARF-4 specific stuff which for some reason were generated for the libbacktrace object files (??). I upgraded to GDB 7.5, and now I get the following backtrace: (gdb) r Starting program: /home/janne/src/gfortran/my-patches/pr54572-libbacktrace/bt2.g Program received signal SIGFPE, Arithmetic exception. 0x000000000040086b in test::c (num=1, denum=0, res=32767) at bt2.f90:5 5 res = num / denum (gdb) c Continuing. Program received signal SIGFPE: Floating-point exception - erroneous arithmetic operation. Backtrace for this error: Program received signal SIGSEGV, Segmentation fault. read_uint32 (buf=buf@entry=0x7fffffffc730) at ../../../trunk-git/libbacktrace/dwarf.c:458 458 return (((uint32_t) p[3] << 24) | ((uint32_t) p[2] << 16) (gdb) bt #0 read_uint32 (buf=buf@entry=0x7fffffffc730) at ../../../trunk-git/libbacktrace/dwarf.c:458 #1 0x00007ffff7bb53be in build_address_map (addrs=0x7fffffffc710, data=0x7fffffffcf1c, error_callback=0x7ffff7ad51f0 <error_callback>, is_bigendian=0, dwarf_str_size=360, dwarf_str=0x7ffff7ff71e3 "integer(kind=4)", dwarf_ranges_size=0, dwarf_ranges=0x7ffff7ff6000 <Address 0x7ffff7ff6000 out of bounds>, dwarf_abbrev_size=253, dwarf_abbrev=0x7ffff7ff708f "012101%1623vBv03163316210122012006", dwarf_info_size=484, dwarf_info=0x7ffff7ff6eab <Address 0x7ffff7ff6eab out of bounds>, base_address=<optimized out>, state=<optimized out>) at ../../../trunk-git/libbacktrace/dwarf.c:1299 #2 build_dwarf_data (data=0x7fffffffcf1c, error_callback=0x7ffff7ad51f0 <error_callback>, is_bigendian=0, dwarf_str_size=360, dwarf_str=0x7ffff7ff71e3 "integer(kind=4)", dwarf_ranges_size=0, dwarf_ranges=0x7ffff7ff6000 <Address 0x7ffff7ff6000 out of bounds>, dwarf_abbrev_size=253, dwarf_abbrev=0x7ffff7ff708f "012101%1623vBv03163316210122012006", dwarf_line_size=<optimized out>, dwarf_line=<optimized out>, dwarf_info_size=484, dwarf_info=0x7ffff7ff6eab <Address 0x7ffff7ff6eab out of bounds>, base_address=<optimized out>, state=<optimized out>) at ../../../trunk-git/libbacktrace/dwarf.c:2822 #3 backtrace_dwarf_add (state=state@entry=0x7ffff7ff8000, base_address=base_address@entry=0, dwarf_info=0x7ffff7ff6eab <Address 0x7ffff7ff6eab out of bounds>, dwarf_info_size=484, dwarf_line=0x7ffff7ff718c "S", dwarf_line_size=87, dwarf_abbrev=0x7ffff7ff708f "012101%1623vBv03163316210122012006", dwarf_abbrev_size=253, dwarf_ranges=0x7ffff7ff6000 <Address 0x7ffff7ff6000 out of bounds>, dwarf_ranges_size=0, dwarf_str=0x7ffff7ff71e3 "integer(kind=4)", dwarf_str_size=360, is_bigendian=0, error_callback=error_callback@entry=0x7ffff7ad51f0 <error_callback>, data=data@entry=0x7fffffffcf1c, fileline_fn=fileline_fn@entry=0x7fffffffcb18) at ../../../trunk-git/libbacktrace/dwarf.c:2881 #4 0x00007ffff7bb72a7 in elf_add (state=state@entry=0x7ffff7ff8000, descriptor=<optimized out>, base_address=base_address@entry=0, error_callback=error_callback@entry=0x7ffff7ad51f0 <error_callback>, data=data@entry=0x7fffffffcf1c, fileline_fn=fileline_fn@entry=0x7fffffffcb18, found_sym=found_sym@entry=0x7fffffffcb10, found_dwarf=found_dwarf@entry=0x7fffffffcb14) at ../../../trunk-git/libbacktrace/elf.c:757 #5 0x00007ffff7bb7696 in backtrace_initialize (state=state@entry=0x7ffff7ff8000, descriptor=<optimized out>, error_callback=error_callback@entry=0x7ffff7ad51f0 <error_callback>, data=data@entry=0x7fffffffcf1c, fileline_fn=fileline_fn@entry=0x7fffffffcb98) at ../../../trunk-git/libbacktrace/elf.c:858 #6 0x00007ffff7bb630d in fileline_initialize (state=state@entry=0x7ffff7ff8000, error_callback=error_callback@entry=0x7ffff7ad51f0 <error_callback>, data=data@entry=0x7fffffffcf1c) at ../../../trunk-git/libbacktrace/fileline.c:144 #7 0x00007ffff7bb6427 in backtrace_pcinfo (state=0x7ffff7ff8000, pc=140737348719229, callback=0x7ffff7ad5170 <full_callback>, error_callback=0x7ffff7ad51f0 <error_callback>, data=0x7fffffffcf1c) at ../../../trunk-git/libbacktrace/fileline.c:184 #8 0x00007ffff7bb6831 in unwind (context=<optimized out>, vdata=0x7fffffffced0) at ../../../trunk-git/libbacktrace/backtrace.c:83 #9 0x00007ffff75b9f49 in _Unwind_Backtrace (trace=trace@entry=0x7ffff7bb67e0 <unwind>, trace_argument=trace_argument@entry=0x7fffffffced0) at ../../../trunk-git/libgcc/unwind.inc:295 #10 0x00007ffff7bb6885 in backtrace_full (state=state@entry=0x7ffff7ff8000, skip=skip@entry=0, callback=callback@entry=0x7ffff7ad5170 <full_callback>, error_callback=error_callback@entry=0x7ffff7ad51f0 <error_callback>, data=data@entry=0x7fffffffcf1c) at ../../../trunk-git/libbacktrace/backtrace.c:106 #11 0x00007ffff7ad527e in _gfortrani_show_backtrace (in_signal_handler=in_signal_handler@entry=1) at ../../../trunk-git/libgfortran/runtime/backtrace.c:92 #12 0x00007ffff7ad5888 in _gfortrani_backtrace_handler (signum=8) at ../../../trunk-git/libgfortran/runtime/compile_options.c:129 #13 <signal handler called> #14 0x000000000040086b in test::c (num=1, denum=0, res=32767) at bt2.f90:5 #15 0x0000000000400848 in test::b (n=1, d=0, r=32767) at bt2.f90:10 ---Type <return> to continue, or q <return> to quit--- #16 0x000000000040081b in test::a (n=1, d=0, r=32767) at bt2.f90:15 #17 0x0000000000400898 in bt () at bt2.f90:22 #18 0x0000000000400930 in main (argc=1, argv=0x7fffffffdac1) at bt2.f90:20 #19 0x00007ffff6fd176d in __libc_start_main (main=0x4008fc <main>, argc=1, ubp_av=0x7fffffffd718, init=<optimized out>, fini=<optimized out>, rtld_fini=<optimized out>, stack_end=0x7fffffffd708) at libc-start.c:226 #20 0x0000000000400709 in _start () As an aside, my binutils is also old enough (2.22) to not handle DWARF-4 fully (e.g. addr2line doesn't understand it, objdump -W complains..), but as I understand it libbacktrace has a self-contained dwarf parser so it shouldn't matter, right? > (In reply to comment #8) > > The crash within libbacktrace is occurring as it tries to read the debug info. > > This is presumably a bug in libbacktrace, but I don't know what the problem is > > without more information. libbacktrace is pretty careful to only read memory > > that was explicitly read. There is presumably a bug there, but I don't know > > what it is. > > > > I doubt the fact that a signal occurred has anything to do with this. There > > seems to be something odd about the debug info, as shown both by the fact that > > libbacktrace crashes trying to read it and that gdb does not display file/line > > information. > > I forgot to mention, that I'm able to get a symbolic backtrace from outside a > signal handler. Though in that case my testcase used external procedures rather > than module procedures, so I guess it's possible there's a bug in handling > debug info for module procedures. I'll recheck this.. Another strange thing, if I compile the test example from #c5 with "-g -static", then it works as expected. As a summary, 1) -g => fails with backtrace above 2) -g -static => success, symbolic backtrace 3) Without -g => success, non-symbolic backtrace I'm baffled..
(In reply to comment #10) > (In reply to comment #6) > > Created attachment 28779 [details] > > Patch to use libbacktrace > > I have to apply the following patch on your patch in order to be able to > compile it. ("MULTIBUILDTOP" is empty here and the library is not in > "/libbacktrace".) > > --- libgfortran-backtrace-pr54572.diff.orig 2012-11-27 10:09:13 +0100 > +++ libgfortran-backtrace-pr54572.diff 2012-11-27 10:12:05 +0100 > @@ -51 +51 @@ index abc23cd..dd325bd 100644 > -+ -I$(MULTIBUILDTOP)/../libbacktrace > ++ -I$(MULTIBUILDTOP)../libbacktrace Good point, fixed. Also the previous line had the same issue, fixed that as well. > > > > Additionally, I wonder whether one should have: > > --- a/Makefile.def > +++ b/Makefile.def > languages = { language=fortran; gcc-check-target=check-fortran; > lib-check-target=check-target-libquadmath; > + lib-check-target=check-target-libbacktrace; > lib-check-target=check-target-libgfortran; }; > languages = { language=java; gcc-check-target=check-java; > > > > > And in the same file, I wonder which of the following two is correct: > > +dependencies = { module=all-target-libgfortran; on=all-target-libbacktrace; }; > > or > > +dependencies = { module=configure-target-libgfortran; > on=all-target-libbacktrace; }; I modeled this after how the go frontend does it. The idea, AFAICS, is that libbacktrace is always built as a hard dependency on libgfortran, however, if libbacktrace doesn't support the target, BACKTRACE_SUPPORTED is set to 0 and a dummy implementation is provided. That is, we can always unconditionally rely on libbacktrace being present. This is different from e.g. libquadmath which may or may not be available on the target, and can be explicitly enabled/disabled at configure time etc.
Thanks for the additional info. #1 0x00007ffff7bb53be in build_address_map (addrs=0x7fffffffc710, data=0x7fffffffcf1c, error_callback=0x7ffff7ad51f0 <error_callback>, is_bigendian=0, dwarf_str_size=360, dwarf_str=0x7ffff7ff71e3 "integer(kind=4)", dwarf_ranges_size=0, dwarf_ranges=0x7ffff7ff6000 <Address 0x7ffff7ff6000 out of bounds>, dwarf_abbrev_size=253, dwarf_abbrev=0x7ffff7ff708f "012101%1623vBv03163316210122012006", dwarf_info_size=484, dwarf_info=0x7ffff7ff6eab <Address 0x7ffff7ff6eab out of bounds>, base_address=<optimized out>, state=<optimized out>) at ../../../trunk-git/libbacktrace/dwarf.c:1299 That is weird because it is showing the parameters in reverse order. Is that what gdb normally does on your system? It doesn't seem to do it for other functions. Here gdb says that the value of dwarf_info is out of bounds. That is not good. That is most likely the immediate cause of the problem. (dwarf_ranges is also out of bounds, but that likely doesn't matter as dwarf_ranges_size is zero.) It looks like it had trouble getting the debug info for the executable file itself. Can you add the output of readelf -S on the executable?
(In reply to comment #14) > Thanks for the additional info. > > #1 0x00007ffff7bb53be in build_address_map (addrs=0x7fffffffc710, > data=0x7fffffffcf1c, > error_callback=0x7ffff7ad51f0 <error_callback>, is_bigendian=0, > dwarf_str_size=360, > dwarf_str=0x7ffff7ff71e3 "integer(kind=4)", dwarf_ranges_size=0, > dwarf_ranges=0x7ffff7ff6000 <Address 0x7ffff7ff6000 out of bounds>, > dwarf_abbrev_size=253, > dwarf_abbrev=0x7ffff7ff708f > "012101%1623vBv03163316210122012006", > dwarf_info_size=484, dwarf_info=0x7ffff7ff6eab <Address 0x7ffff7ff6eab out > of bounds>, > base_address=<optimized out>, state=<optimized out>) at > ../../../trunk-git/libbacktrace/dwarf.c:1299 > > That is weird because it is showing the parameters in reverse order. Is that > what gdb normally does on your system? It doesn't seem to do it for other > functions. No, I've never seen it before. Then again, before yesterday I had never used GDB 7.5, only older versions. > Here gdb says that the value of dwarf_info is out of bounds. That is not good. > That is most likely the immediate cause of the problem. (dwarf_ranges is also > out of bounds, but that likely doesn't matter as dwarf_ranges_size is zero.) > > It looks like it had trouble getting the debug info for the executable file > itself. Can you add the output of readelf -S on the executable? $ readelf -S bt2.g There are 35 section headers, starting at offset 0x1668: Section Headers: [Nr] Name Type Address Offset Size EntSize Flags Link Info Align [ 0] NULL 0000000000000000 00000000 0000000000000000 0000000000000000 0 0 0 [ 1] .interp PROGBITS 0000000000400200 00000200 000000000000001c 0000000000000000 A 0 0 1 [ 2] .note.ABI-tag NOTE 000000000040021c 0000021c 0000000000000020 0000000000000000 A 0 0 4 [ 3] .hash HASH 0000000000400240 00000240 0000000000000040 0000000000000004 A 4 0 8 [ 4] .dynsym DYNSYM 0000000000400280 00000280 0000000000000108 0000000000000018 A 5 1 8 [ 5] .dynstr STRTAB 0000000000400388 00000388 00000000000001c8 0000000000000000 A 0 0 1 [ 6] .gnu.version VERSYM 0000000000400550 00000550 0000000000000016 0000000000000002 A 4 0 2 [ 7] .gnu.version_r VERNEED 0000000000400568 00000568 0000000000000050 0000000000000000 A 5 2 8 [ 8] .rela.dyn RELA 00000000004005b8 000005b8 0000000000000018 0000000000000018 A 4 0 8 [ 9] .rela.plt RELA 00000000004005d0 000005d0 0000000000000090 0000000000000018 A 4 11 8 [10] .init PROGBITS 0000000000400660 00000660 000000000000000e 0000000000000000 AX 0 0 4 [11] .plt PROGBITS 0000000000400670 00000670 0000000000000070 0000000000000010 AX 0 0 16 [12] .text PROGBITS 00000000004006e0 000006e0 00000000000002f4 0000000000000000 AX 0 0 16 [13] .fini PROGBITS 00000000004009d4 000009d4 0000000000000009 0000000000000000 AX 0 0 4 [14] .rodata PROGBITS 00000000004009e0 000009e0 000000000000003c 0000000000000000 A 0 0 16 [15] .eh_frame_hdr PROGBITS 0000000000400a1c 00000a1c 000000000000004c 0000000000000000 A 0 0 4 [16] .eh_frame PROGBITS 0000000000400a68 00000a68 0000000000000124 0000000000000000 A 0 0 8 [17] .init_array INIT_ARRAY 0000000000600b90 00000b90 0000000000000008 0000000000000000 WA 0 0 8 [18] .fini_array FINI_ARRAY 0000000000600b98 00000b98 0000000000000008 0000000000000000 WA 0 0 8 [19] .jcr PROGBITS 0000000000600ba0 00000ba0 0000000000000008 0000000000000000 WA 0 0 8 [20] .dynamic DYNAMIC 0000000000600ba8 00000ba8 0000000000000220 0000000000000010 WA 5 0 8 [21] .got PROGBITS 0000000000600dc8 00000dc8 0000000000000008 0000000000000008 WA 0 0 8 [22] .got.plt PROGBITS 0000000000600dd0 00000dd0 0000000000000048 0000000000000008 WA 0 0 8 [23] .data PROGBITS 0000000000600e18 00000e18 0000000000000010 0000000000000000 WA 0 0 8 [24] .bss NOBITS 0000000000600e28 00000e28 0000000000000008 0000000000000000 WA 0 0 4 [25] .comment PROGBITS 0000000000000000 00000e28 0000000000000053 0000000000000001 MS 0 0 1 [26] .debug_aranges PROGBITS 0000000000000000 00000e7b 0000000000000030 0000000000000000 0 0 1 [27] .debug_info PROGBITS 0000000000000000 00000eab 00000000000001e4 0000000000000000 0 0 1 [28] .debug_abbrev PROGBITS 0000000000000000 0000108f 00000000000000fd 0000000000000000 0 0 1 [29] .debug_line PROGBITS 0000000000000000 0000118c 0000000000000057 0000000000000000 0 0 1 [30] .debug_str PROGBITS 0000000000000000 000011e3 0000000000000168 0000000000000001 MS 0 0 1 [31] .debug_loc PROGBITS 0000000000000000 0000134b 00000000000001e0 0000000000000000 0 0 1 [32] .shstrtab STRTAB 0000000000000000 0000152b 000000000000013c 0000000000000000 0 0 1 [33] .symtab SYMTAB 0000000000000000 00001f28 0000000000000768 0000000000000018 34 52 8 [34] .strtab STRTAB 0000000000000000 00002690 000000000000032d 0000000000000000 0 0 1 Key to Flags: W (write), A (alloc), X (execute), M (merge), S (strings), l (large) I (info), L (link order), G (group), T (TLS), E (exclude), x (unknown) O (extra OS processing required) o (OS specific), p (processor specific) Like I mentioned previously, my binutils is version 2.22 which apparently doesn't have complete support for DWARF-4. I can certainly try upgrading, if you think that would help; I don't really know what to look for in the above output, sorry.
Author: fxcoudert Date: Sun Aug 23 21:50:30 2015 New Revision: 227106 URL: https://gcc.gnu.org/viewcvs?rev=227106&root=gcc&view=rev Log: PR libfortran/54572 * Makefile.def: Make libgfortran depend on libbacktrace. * Makefile.in: Regenerate. * config-lang.in: Add libbacktrace to target_libs. * Makefile.am (libgfortran_la_LDFLAGS): Link in libbacktrace. (AM_CPPFLAGS): Add libbacktrace directories to include paths. * Makefile.in: Regenerate. * aclocal.m4: Regenerate. * config.h.in: Regenerate. * configure: Regenerate. * configure.ac: Remove checks for strtok_r, wait, execve, pipe, and dup2. Remove call to GCC_CHECK_UNWIND_GETIPINFO. * libgfortran.h (full_exe_path, find_addr2line, backtrace): Remove prototypes. (show_backtrace): Add prototype. * runtime/backtrace.c: Rework file entirely. * runtime/compile_options.c (backtrace_handler): Rename backtrace to show_backtrace. (maybe_find_addr2line): Remove function. (set_options): Remove call to maybe_find_addr2line. * runtime/error.c (sys_abort): Rename backtrace to show_backtrace. * runtime/main.c (store_exe_path): Empty function body. (full_exe_path, gfstrtok_r, find_addr2line): Remove functions. (cleanup): Don't free removed variables. * runtime/minimal.c (full_exe_path): Remove function. (set_args): Don't set exe_path. * gfortran.dg/backtrace_1.f90: New test. Added: trunk/gcc/testsuite/gfortran.dg/backtrace_1.f90 Modified: trunk/ChangeLog trunk/Makefile.def trunk/Makefile.in trunk/gcc/fortran/ChangeLog trunk/gcc/fortran/config-lang.in trunk/gcc/testsuite/ChangeLog trunk/libgfortran/ChangeLog trunk/libgfortran/Makefile.am trunk/libgfortran/Makefile.in trunk/libgfortran/aclocal.m4 trunk/libgfortran/config.h.in trunk/libgfortran/configure trunk/libgfortran/configure.ac trunk/libgfortran/libgfortran.h trunk/libgfortran/runtime/backtrace.c trunk/libgfortran/runtime/compile_options.c trunk/libgfortran/runtime/error.c trunk/libgfortran/runtime/main.c trunk/libgfortran/runtime/minimal.c
Fixed on trunk. |
-
#1
Hello,
I am running simulations in WRF3.9.1 on 8 processors using ERA5 data and my simulations keep crashing.
The calculations end with:
=========================================================
BAD TERMINATION OF ONE OF YOUR APPLICATION PROCESSES
EXIT CODE:139
CLEANING UP REMAINING PROCESSES
YOU CAN IGNORE THE BELOW CLEANUP MESSAGES
=========================================================
YOUR APPLICATION TERMINATED WITH THE EXIT STRING: Segmentation fault (signal 11)
This typically refers to a problem with your application.
Please see the FAQ page for debugging suggestions.
I have checked the rsl.error.0000 (the biggest of all eight) and in the end there was just:
Program received signal SIGSEV: Segmentation fault — invalid memory reference.
Backtrace for this error:
#0 0x7fc35998c2da in ???
#1 0x7fc35998b503 in ???
#2 0x7fc359008f1f in ???
#3 0x56082a24d0f5 in ???
#4 0x56082a26be67 in ???
#5 0x56082a28ea4b in ???
#6 0x56082a29ddc4 in ???
#7 0x560829e56128 in ???
#8 0x560829f0d2e5 in ???
#9 0x560829a81519 in ???
#10 0x56082997e5e0 in ???
#11 0x560828da4cb8 in ???
#12 0x560828da52ad in ???
#13 0x560828da52ad in ???
#14 0x560828d3dba9 in ???
#15 0x560828d3d4fe in ???
#16 0x7fc358febb96 in ???
#17 0x560828d3d539 in ???
#18 0xffffffffffffffff in ???
I am enclosing the namelist.input, namelist.wps and rsl.error.0000 files.
Also, based on previous discussions with segmentation errors, I have tried:
1) first reducing time step, later setting it to adaptive so that it does not run extremely long.
Even without adaptive time step the backtrace error was similar.
2) I did type ulimit -s unlimited.
3) I modified epssm as well as cfl options.
4) Finally I also set smooth_cg_topo=.true., still no help.
5) I shortened (actually moved forward the beginning of) the study period by two days, it crashes anyway.
I should also note that I have changed the negative moisture values in SM028100 (that were created by metgrid.exe) to positive, but the simulation ran neither with nor without them.
I really do not know what else I can try and any help will be appreciated.
Best regards,
Klara
-
namelist (1).input
6.6 KB
· Views: 60
-
namelist (1).wps
1.5 KB
· Views: 48
-
rsl.error0000.txt
532 KB
· Views: 56