Backtrace for this error

When I compile my code using gfortran -g -fbacktrace -ffpe-trap=invalid,overflow,underflow File.f90 I get the following error: Program received signal SIGFPE : Floating - Point exception - erroneous

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.

Содержание

  1. Error Handling Functions
  2. Table of Contents
  3. User Contributed Notes 9 notes
  4. debug_backtrace
  5. Description
  6. Parameters
  7. Return Values
  8. Examples
  9. See Also
  10. 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 8)

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.
With debuginfo-level = 1 (the default when debug = 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()?

  1. It’s a struct/variant with named fields and one of the fields is
    called backtrace. Then it would return that field as the backtrace.
  2. It’s a tuple struct/variant and the type of exactly one of the fields is
    called Backtrace. Then it would return that field as the backtrace.
  3. One of the fields is annotated with #[error(backtrace)]. Then it would
    return that field as the backtrace.

1.2 When and how does it derive source()?

  1. It’s a struct/variant with named fields and one is the fields is
    called source. Then it would return that field as the source.
  2. It’s a tuple struct/variant and there’s exactly one field that is not used as
    the backtrace. So either a tuple struct with one field, or one with two where one
    is the backtrace. Then it returns this field as the source.
  3. One of the fields is annotated with #[error(backtrace)]. Then it would
    return that field as the backtrace.

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());
}


Description


Tobias Burnus



2012-09-13 22:25:50 UTC

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.]


Comment 1


Hans-Peter Nilsson



2012-09-15 11:25:35 UTC

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.)


Comment 2


Janne Blomqvist



2012-09-16 08:33:42 UTC

(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)


Comment 3


Hans-Peter Nilsson



2012-09-16 23:16:02 UTC

(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.


Comment 4


Janne Blomqvist



2012-11-25 15:10:07 UTC

I have a patch, just need to clean it up a bit and test.


Comment 5


Janne Blomqvist



2012-11-26 16:43:16 UTC

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)


Comment 7


Ian Lance Taylor



2012-11-26 23:02:46 UTC

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?


Comment 8


Ian Lance Taylor



2012-11-26 23:08:45 UTC

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.


Comment 9


Janne Blomqvist



2012-11-27 08:58:59 UTC

(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..


Comment 10


Tobias Burnus



2012-11-27 09:32:55 UTC

(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; };


Comment 11


Tobias Burnus



2012-11-27 10:05:50 UTC

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


Comment 12


Janne Blomqvist



2012-11-30 21:56:29 UTC

(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..


Comment 13


Janne Blomqvist



2012-11-30 22:03:43 UTC

(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.


Comment 14


Ian Lance Taylor



2012-12-01 06:43:07 UTC

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?


Comment 15


Janne Blomqvist



2012-12-01 19:48:12 UTC

(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.


Comment 17


Francois-Xavier Coudert



2015-08-23 21:51:02 UTC

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


Comment 18


Francois-Xavier Coudert



2015-08-23 21:52:37 UTC

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

Понравилась статья? Поделить с друзьями:
  • Backlight error sony
  • Backing up to debug only private cache как исправить
  • Background disk merge failed to complete general access denied error 0x80070005
  • Backend tech error мтс банк
  • Backend internal error exception during ir lowering