Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
R
riscv-gcc-1
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
lvzhengyang
riscv-gcc-1
Commits
eec2794c
Commit
eec2794c
authored
May 22, 2011
by
Janne Blomqvist
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
PR 48931 Make backtrace async-signal-safe, reformat output
From-SVN: r174030
parent
15f072f9
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
177 additions
and
172 deletions
+177
-172
libgfortran/ChangeLog
+17
-0
libgfortran/config.h.in
+5
-2
libgfortran/configure
+2
-2
libgfortran/configure.ac
+2
-2
libgfortran/runtime/backtrace.c
+135
-165
libgfortran/runtime/main.c
+16
-1
No files found.
libgfortran/ChangeLog
View file @
eec2794c
2011-05-22 Janne Blomqvist <jb@gcc.gnu.org>
PR libfortran/48931
* configure.ac: Check for backtrace_symbols_fd instead of
backtrace_symbols, check for readlink.
* config.h.in: Regenerated.
* configure: Regenerated.
* runtime/backtrace.c (local_strcasestr): Remove.
(bt_header): New function.
(dump_glibc_backtrace): Remove.
(fd_gets): New function.
(show_backtrace): Rework to use backtrace_symbols_fd and pipes
avoiding functions that are not async-signal-safe, reformat
output.
* runtime/main.c (store_exe_path): Try to check /proc/self/exe
first.
2011-05-20 Janne Blomqvist <jb@gcc.gnu.org>
Uros Bizjak <ubizjak@gmail.com>
...
...
libgfortran/config.h.in
View file @
eec2794c
...
...
@@ -84,8 +84,8 @@
/* Define to 1 if you have the `backtrace' function. */
#undef HAVE_BACKTRACE
/* Define to 1 if you have the `backtrace_symbols' function. */
#undef HAVE_BACKTRACE_SYMBOLS
/* Define to 1 if you have the `backtrace_symbols
_fd
' function. */
#undef HAVE_BACKTRACE_SYMBOLS
_FD
/* Define if powf is broken. */
#undef HAVE_BROKEN_POWF
...
...
@@ -639,6 +639,9 @@
/* Define to 1 if you have the <pwd.h> header file. */
#undef HAVE_PWD_H
/* Define to 1 if you have the `readlink' function. */
#undef HAVE_READLINK
/* libm includes round */
#undef HAVE_ROUND
...
...
libgfortran/configure
View file @
eec2794c
...
...
@@ -16458,7 +16458,7 @@ _ACEOF
fi
done
for
ac_func
in
clock_gettime strftime
for
ac_func
in
clock_gettime strftime
readlink
do
:
as_ac_var
=
`
$as_echo
"ac_cv_func_
$ac_func
"
|
$as_tr_sh
`
ac_fn_c_check_func
"
$LINENO
"
"
$ac_func
"
"
$as_ac_var
"
...
...
@@ -16473,7 +16473,7 @@ done
# Check for glibc backtrace functions
for
ac_func
in
backtrace backtrace_symbols
for
ac_func
in
backtrace backtrace_symbols
_fd
do
:
as_ac_var
=
`
$as_echo
"ac_cv_func_
$ac_func
"
|
$as_tr_sh
`
ac_fn_c_check_func
"
$LINENO
"
"
$ac_func
"
"
$as_ac_var
"
...
...
libgfortran/configure.ac
View file @
eec2794c
...
...
@@ -264,10 +264,10 @@ AC_CHECK_FUNCS(sleep time ttyname signal alarm clock access fork execl)
AC_CHECK_FUNCS(wait setmode execvp pipe dup2 close fdopen strcasestr getrlimit)
AC_CHECK_FUNCS(gettimeofday stat fstat lstat getpwuid vsnprintf dup getcwd)
AC_CHECK_FUNCS(localtime_r gmtime_r strerror_r getpwuid_r ttyname_r)
AC_CHECK_FUNCS(clock_gettime strftime)
AC_CHECK_FUNCS(clock_gettime strftime
readlink
)
# Check for glibc backtrace functions
AC_CHECK_FUNCS(backtrace backtrace_symbols)
AC_CHECK_FUNCS(backtrace backtrace_symbols
_fd
)
# Check libc for getgid, getpid, getuid
AC_CHECK_LIB([c],[getgid],[AC_DEFINE([HAVE_GETGID],[1],[libc includes getgid])])
...
...
libgfortran/runtime/backtrace.c
View file @
eec2794c
...
...
@@ -54,59 +54,57 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
#define CAN_FORK (defined(HAVE_FORK) && defined(HAVE_EXECVP) \
&& defined(HAVE_WAIT))
#define GLIBC_BACKTRACE (defined(HAVE_BACKTRACE) \
&& defined(HAVE_BACKTRACE_SYMBOLS))
&& defined(HAVE_BACKTRACE_SYMBOLS
_FD
))
#define CAN_PIPE (CAN_FORK && defined(HAVE_PIPE) \
&& defined(HAVE_DUP2) && defined(HAVE_FDOPEN) \
&& defined(HAVE_CLOSE))
#if GLIBC_BACKTRACE && CAN_PIPE
static
char
*
local_strcasestr
(
const
char
*
s1
,
const
char
*
s2
)
{
#ifdef HAVE_STRCASESTR
return
strcasestr
(
s1
,
s2
);
#else
/* GDB style #NUM index for each stack frame. */
const
char
*
p
=
s1
;
const
size_t
len
=
strlen
(
s2
);
const
char
u
=
*
s2
,
v
=
isupper
((
int
)
*
s2
)
?
tolower
((
int
)
*
s2
)
:
(
islower
((
int
)
*
s2
)
?
toupper
((
int
)
*
s2
)
:
*
s2
);
while
(
1
)
{
while
(
*
p
!=
u
&&
*
p
!=
v
&&
*
p
)
p
++
;
if
(
*
p
==
0
)
return
NULL
;
if
(
strncasecmp
(
p
,
s2
,
len
)
==
0
)
return
(
char
*
)
p
;
}
#endif
static
void
bt_header
(
int
num
)
{
st_printf
(
" #%d "
,
num
);
}
#endif
#if GLIBC_BACKTRACE
static
void
dump_glibc_backtrace
(
int
depth
,
char
*
str
[])
{
int
i
;
/* fgets()-like function that reads a line from a fd, without
needing to malloc() a buffer, and does not use locks, hence should
be async-signal-safe. */
for
(
i
=
0
;
i
<
depth
;
i
++
)
static
char
*
fd_gets
(
char
*
s
,
int
size
,
int
fd
)
{
for
(
int
i
=
0
;
i
<
size
;
i
++
)
{
estr_write
(
" + "
);
estr_write
(
str
[
i
]);
estr_write
(
"
\n
"
);
char
c
;
ssize_t
nread
=
read
(
fd
,
&
c
,
1
);
if
(
nread
==
1
)
{
s
[
i
]
=
c
;
if
(
c
==
'\n'
)
{
if
(
i
+
1
<
size
)
s
[
i
+
1
]
=
'\0'
;
else
s
[
i
]
=
'\0'
;
break
;
}
}
else
{
s
[
i
]
=
'\0'
;
break
;
}
}
free
(
str
);
return
s
;
}
#endif
/* show_backtrace displays the backtrace, currently obtained by means of
the glibc backtrace* functions. */
void
show_backtrace
(
void
)
{
...
...
@@ -116,63 +114,48 @@ show_backtrace (void)
#define BUFSIZE 1024
void
*
trace
[
DEPTH
];
char
**
str
;
int
depth
;
depth
=
backtrace
(
trace
,
DEPTH
);
if
(
depth
<=
0
)
return
;
str
=
backtrace_symbols
(
trace
,
depth
);
#if CAN_PIPE
#ifndef STDIN_FILENO
#define STDIN_FILENO 0
#endif
#ifndef STDOUT_FILENO
#define STDOUT_FILENO 1
#endif
#ifndef STDERR_FILENO
#define STDERR_FILENO 2
#endif
/* We attempt to extract file and line information from addr2line. */
do
{
/* Local variables. */
int
f
[
2
],
pid
,
line
,
i
;
FILE
*
output
;
char
addr_buf
[
DEPTH
][
GFC_XTOA_BUF_SIZE
],
func
[
BUFSIZE
],
file
[
BUFSIZE
];
char
*
p
,
*
end
;
const
char
*
addr
[
DEPTH
];
/* Write the list of addresses in hexadecimal format. */
for
(
i
=
0
;
i
<
depth
;
i
++
)
addr
[
i
]
=
gfc_xtoa
((
GFC_UINTEGER_LARGEST
)
(
intptr_t
)
trace
[
i
],
addr_buf
[
i
],
sizeof
(
addr_buf
[
i
]));
int
f
[
2
],
pid
,
bt
[
2
],
inp
[
2
];
char
addr_buf
[
GFC_XTOA_BUF_SIZE
],
func
[
BUFSIZE
],
file
[
BUFSIZE
];
char
*
p
;
/* Don't output an error message if something goes wrong, we'll simply
fall back to the pstack and glibc backtraces. */
if
(
pipe
(
f
)
!=
0
)
break
;
if
(
pipe
(
inp
)
!=
0
)
break
;
if
((
pid
=
fork
())
==
-
1
)
break
;
if
(
pid
==
0
)
{
/* Child process. */
#define NUM_FIXEDARGS
5
char
*
arg
[
DEPTH
+
NUM_FIXEDARGS
+
1
];
#define NUM_FIXEDARGS
7
char
*
arg
[
NUM_FIXEDARGS
];
close
(
f
[
0
]);
close
(
STDIN_FILENO
);
close
(
inp
[
1
]);
if
(
dup2
(
inp
[
0
],
STDIN_FILENO
)
==
-
1
)
_exit
(
1
);
close
(
inp
[
0
]);
close
(
STDERR_FILENO
);
if
(
dup2
(
f
[
1
],
STDOUT_FILENO
)
==
-
1
)
_exit
(
0
);
_exit
(
1
);
close
(
f
[
1
]);
arg
[
0
]
=
(
char
*
)
"addr2line"
;
...
...
@@ -180,112 +163,111 @@ show_backtrace (void)
arg
[
2
]
=
full_exe_path
();
arg
[
3
]
=
(
char
*
)
"-f"
;
arg
[
4
]
=
(
char
*
)
"-s"
;
for
(
i
=
0
;
i
<
depth
;
i
++
)
arg
[
NUM_FIXEDARGS
+
i
]
=
(
char
*
)
addr
[
i
];
arg
[
NUM_FIXEDARGS
+
depth
]
=
NULL
;
arg
[
5
]
=
(
char
*
)
"-C"
;
arg
[
6
]
=
NULL
;
execvp
(
arg
[
0
],
arg
);
_exit
(
0
);
_exit
(
1
);
#undef NUM_FIXEDARGS
}
/* Father process. */
close
(
f
[
1
]);
wait
(
NULL
);
output
=
fdopen
(
f
[
0
],
"r"
);
i
=
-
1
;
close
(
inp
[
0
]);
if
(
pipe
(
bt
)
!=
0
)
break
;
backtrace_symbols_fd
(
trace
,
depth
,
bt
[
1
]);
close
(
bt
[
1
]);
if
(
fgets
(
func
,
sizeof
(
func
),
output
))
estr_write
(
"
\n
Backtrace for this error:
\n
"
);
for
(
int
j
=
0
;
j
<
depth
;
j
++
)
{
estr_write
(
"
\n
Backtrace for this error:
\n
"
);
do
const
char
*
addr
=
gfc_xtoa
((
GFC_UINTEGER_LARGEST
)
(
intptr_t
)
trace
[
j
],
addr_buf
,
sizeof
(
addr_buf
));
write
(
inp
[
1
],
addr
,
strlen
(
addr
));
write
(
inp
[
1
],
"
\n
"
,
1
);
if
(
!
fd_gets
(
func
,
sizeof
(
func
),
f
[
0
]))
goto
fallback
;
if
(
!
fd_gets
(
file
,
sizeof
(
file
),
f
[
0
]))
goto
fallback
;
for
(
p
=
func
;
*
p
!=
'\n'
&&
*
p
!=
'\r'
;
p
++
)
;
*
p
=
'\0'
;
/* If we only have the address, use the glibc backtrace. */
if
(
func
[
0
]
==
'?'
&&
func
[
1
]
==
'?'
&&
file
[
0
]
==
'?'
&&
file
[
1
]
==
'?'
)
{
if
(
!
fgets
(
file
,
sizeof
(
file
),
output
))
goto
fallback
;
i
++
;
for
(
p
=
func
;
*
p
!=
'\n'
&&
*
p
!=
'\r'
;
p
++
)
;
*
p
=
'\0'
;
/* Try to recognize the internal libgfortran functions. */
if
(
strncasecmp
(
func
,
"*_gfortran"
,
10
)
==
0
||
strncasecmp
(
func
,
"_gfortran"
,
9
)
==
0
||
strcmp
(
func
,
"main"
)
==
0
||
strcmp
(
func
,
"_start"
)
==
0
||
strcmp
(
func
,
"_gfortrani_backtrace_handler"
)
==
0
)
continue
;
if
(
local_strcasestr
(
str
[
i
],
"libgfortran.so"
)
!=
NULL
||
local_strcasestr
(
str
[
i
],
"libgfortran.dylib"
)
!=
NULL
||
local_strcasestr
(
str
[
i
],
"libgfortran.a"
)
!=
NULL
)
continue
;
/* If we only have the address, use the glibc backtrace. */
if
(
func
[
0
]
==
'?'
&&
func
[
1
]
==
'?'
&&
file
[
0
]
==
'?'
&&
file
[
1
]
==
'?'
)
{
estr_write
(
" + "
);
estr_write
(
str
[
i
]);
estr_write
(
"
\n
"
);
continue
;
}
/* Extract the line number. */
for
(
end
=
NULL
,
p
=
file
;
*
p
;
p
++
)
if
(
*
p
==
':'
)
end
=
p
;
if
(
end
!=
NULL
)
{
*
end
=
'\0'
;
line
=
atoi
(
++
end
);
}
else
line
=
-
1
;
if
(
strcmp
(
func
,
"MAIN__"
)
==
0
)
estr_write
(
" + in the main program
\n
"
);
else
bt_header
(
j
);
while
(
1
)
{
estr_write
(
" + function "
)
;
estr_write
(
func
);
estr_write
(
" (0x"
);
estr_write
(
addr
[
i
])
;
estr_write
(
")
\n
"
);
char
bc
;
ssize_t
nread
=
read
(
bt
[
0
],
&
bc
,
1
);
if
(
nread
!=
1
||
bc
==
'\n'
)
break
;
write
(
STDERR_FILENO
,
&
bc
,
1
);
}
if
(
line
<=
0
&&
strcmp
(
file
,
"??"
)
==
0
)
continue
;
if
(
line
<=
0
)
estr_write
(
"
\n
"
);
continue
;
}
else
{
/* Forward to the next entry in the backtrace. */
while
(
1
)
{
estr_write
(
" from file "
);
estr_write
(
file
);
estr_write
(
"
\n
"
);
char
bc
;
ssize_t
nread
=
read
(
bt
[
0
],
&
bc
,
1
);
if
(
nread
!=
1
||
bc
==
'\n'
)
break
;
}
else
st_printf
(
" at line %d of file %s
\n
"
,
line
,
file
);
}
while
(
fgets
(
func
,
sizeof
(
func
),
output
));
free
(
str
);
return
;
/* _start is a setup routine that calls main(), and main() is
the frontend routine that calls some setup stuff and then
calls MAIN__, so at this point we should stop. */
if
(
strcmp
(
func
,
"_start"
)
==
0
||
strcmp
(
func
,
"main"
)
==
0
)
break
;
bt_header
(
j
);
estr_write
(
full_exe_path
());
estr_write
(
"[0x"
);
estr_write
(
addr
);
estr_write
(
"] in "
);
estr_write
(
func
);
if
(
strncmp
(
file
,
"??"
,
2
)
==
0
)
estr_write
(
"
\n
"
);
else
{
estr_write
(
" at "
);
estr_write
(
file
);
}
}
/* Loop over each hex address. */
close
(
inp
[
1
]);
close
(
bt
[
0
]);
wait
(
NULL
);
return
;
fallback:
estr_write
(
"** Something went wrong while running addr2line. **
\n
"
"** Falling back to a simpler backtrace scheme. **
\n
"
);
}
}
estr_write
(
"** Something went wrong while running addr2line. **
\n
"
"** Falling back to a simpler backtrace scheme. **
\n
"
);
}
while
(
0
);
#undef DEPTH
#undef BUFSIZE
#endif
#endif
#endif
/* CAN_PIPE */
/* Fallback to the glibc backtrace. */
estr_write
(
"
\n
Backtrace for this error:
\n
"
);
backtrace_symbols_fd
(
trace
,
depth
,
STDERR_FILENO
);
return
;
#
if CAN_FORK
&& defined(HAVE_GETPPID)
#
elif defined(CAN_FORK)
&& defined(HAVE_GETPPID)
/* Try to call pstack. */
do
{
...
...
@@ -312,15 +294,9 @@ fallback:
execvp
(
arg
[
0
],
arg
);
#undef NUM_ARGS
/* pstack didn't work, so we fall back to dumping the glibc
backtrace if we can. */
#if GLIBC_BACKTRACE
dump_glibc_backtrace
(
depth
,
str
);
#else
/* pstack didn't work. */
estr_write
(
" unable to produce a backtrace, sorry!
\n
"
);
#endif
_exit
(
0
);
_exit
(
1
);
}
/* Father process. */
...
...
@@ -328,13 +304,7 @@ fallback:
return
;
}
while
(
0
);
#endif
#if GLIBC_BACKTRACE
/* Fallback to the glibc backtrace. */
estr_write
(
"
\n
Backtrace for this error:
\n
"
);
dump_glibc_backtrace
(
depth
,
str
);
return
;
#endif
#else
estr_write
(
"
\n
Backtrace not yet available on this platform, sorry!
\n
"
);
#endif
}
libgfortran/runtime/main.c
View file @
eec2794c
...
...
@@ -92,6 +92,19 @@ store_exe_path (const char * argv0)
if
(
please_free_exe_path_when_done
)
free
((
char
*
)
exe_path
);
/* Reading the /proc/self/exe symlink is Linux-specific(?), but if
it works it gives the correct answer. */
#ifdef HAVE_READLINK
int
len
;
if
((
len
=
readlink
(
"/proc/self/exe"
,
buf
,
sizeof
(
buf
)
-
1
))
!=
-
1
)
{
buf
[
len
]
=
'\0'
;
exe_path
=
strdup
(
buf
);
please_free_exe_path_when_done
=
1
;
return
;
}
#endif
/* On the simulator argv is not set. */
if
(
argv0
==
NULL
||
argv0
[
0
]
==
'/'
)
{
...
...
@@ -107,7 +120,9 @@ store_exe_path (const char * argv0)
cwd
=
""
;
#endif
/* exe_path will be cwd + "/" + argv[0] + "\0" */
/* exe_path will be cwd + "/" + argv[0] + "\0". This will not work
if the executable is not in the cwd, but at this point we're out
of better ideas. */
size_t
pathlen
=
strlen
(
cwd
)
+
1
+
strlen
(
argv0
)
+
1
;
path
=
malloc
(
pathlen
);
snprintf
(
path
,
pathlen
,
"%s%c%s"
,
cwd
,
DIR_SEPARATOR
,
argv0
);
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment