3 # This file is open source software, licensed to you under the terms
4 # of the Apache License, Version 2.0 (the "License"). See the NOTICE file
5 # distributed with this work for additional information regarding copyright
6 # ownership. You may not use this file except in compliance with the License.
8 # You may obtain a copy of the License at
10 # http://www.apache.org/licenses/LICENSE-2.0
12 # Unless required by applicable law or agreed to in writing,
13 # software distributed under the License is distributed on an
14 # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 # KIND, either express or implied. See the License for the
16 # specific language governing permissions and limitations
19 # Copyright (C) 2017 ScyllaDB
28 from addr2line
import BacktraceResolver
30 class StdinBacktraceIterator(object):
32 Read stdin char-by-char and stop when when user pressed Ctrl+D or the
33 Enter twice. Altough reading char-by-char is slow this won't be a
34 problem here as backtraces shouldn't be huge.
42 char
= sys
.stdin
.read(1)
48 lines
.append(''.join(line
))
54 if char
== '' or linefeeds
> 1:
60 description
='Massage and pass addresses to the real addr2line for symbol lookup.'
62 There are three operational modes:
63 1) If -f is specified input will be read from FILE
64 2) If -f is omitted and there are ADDRESS args they will be read as input
65 3) If -f is omitted and there are no ADDRESS args input will be read from stdin
68 cmdline_parser
= argparse
.ArgumentParser(
69 description
=description
,
71 formatter_class
=argparse
.RawDescriptionHelpFormatter
,
74 cmdline_parser
.add_argument(
81 help='The executable where the addresses originate from')
83 cmdline_parser
.add_argument(
90 help='The file containing the addresses')
92 cmdline_parser
.add_argument(
98 help='Non-backtrace lines to print before resolved backtraces for context.'
99 ' Set to 0 to print only resolved backtraces.'
100 ' Set to -1 to print all non-backtrace lines. Default is 1.')
102 cmdline_parser
.add_argument(
107 help='Only resolve backtraces whose non-backtrace lines match the regular-expression.'
108 ' The amount of non-backtrace lines considered can be set with --before.'
109 ' By default no matching is performed.')
111 cmdline_parser
.add_argument(
116 help='Make resolved backtraces verbose, prepend to each line the module'
117 ' it originates from, as well as the address being resolved')
119 cmdline_parser
.add_argument(
126 cmdline_parser
.add_argument(
131 help='Addresses to parse')
133 args
= cmdline_parser
.parse_args()
137 ('---', {'type': BacktraceResolver
.BacktraceParser
.Type
.SEPARATOR
}),
139 ('0x12f34', {'type': BacktraceResolver
.BacktraceParser
.Type
.ADDRESS
, 'prefix': None, 'addresses': [{'path': None, 'addr': '0x12f34'}]}),
140 ('0xa1234 0xb4567', {'type': BacktraceResolver
.BacktraceParser
.Type
.ADDRESS
, 'prefix': None, 'addresses': [{'path': None, 'addr': '0xa1234'},{'path': None, 'addr': '0xb4567'}]}),
141 (' 0xa1234 /my/path+0xb4567', {'type': BacktraceResolver
.BacktraceParser
.Type
.ADDRESS
, 'prefix': None, 'addresses': [{'path': None, 'addr': '0xa1234'},{'path': '/my/path', 'addr': '0xb4567'}]}),
142 ('/my/path+0x12f34', {'type': BacktraceResolver
.BacktraceParser
.Type
.ADDRESS
, 'prefix': None, 'addresses': [{'path': '/my/path', 'addr': '0x12f34'}]}),
143 (' /my/path+0x12f34', {'type': BacktraceResolver
.BacktraceParser
.Type
.ADDRESS
, 'prefix': None, 'addresses': [{'path': '/my/path', 'addr': '0x12f34'}]}),
145 ('Some prefix 0x12f34', None),
146 ('Some prefix /my/path+0x12f34', None),
148 ('Reactor stalled on shard 1. Backtrace: 0x12f34',
149 {'type': BacktraceResolver
.BacktraceParser
.Type
.ADDRESS
, 'prefix': 'Reactor stalled on shard 1. Backtrace:',
150 'addresses': [{'path': None, 'addr': '0x12f34'}]}),
151 ('Reactor stalled on shard 1. Backtrace: 0xa1234 0xb5678',
152 {'type': BacktraceResolver
.BacktraceParser
.Type
.ADDRESS
, 'prefix': 'Reactor stalled on shard 1. Backtrace:',
153 'addresses': [{'path': None, 'addr': '0xa1234'}, {'path': None, 'addr': '0xb5678'}]}),
154 ('Reactor stalled on shard 1. Backtrace: /my/path+0xabcd',
155 {'type': BacktraceResolver
.BacktraceParser
.Type
.ADDRESS
, 'prefix': 'Reactor stalled on shard 1. Backtrace:',
156 'addresses': [{'path': '/my/path', 'addr': '0xabcd'}]}),
158 ('Expected partition_end(), but got end of stream, at 0xa1234 0xb5678 /my/path+0xabcd',
159 {'type': BacktraceResolver
.BacktraceParser
.Type
.ADDRESS
, 'prefix': 'Expected partition_end(), but got end of stream, at',
160 'addresses': [{'path': None, 'addr': '0xa1234'}, {'path': None, 'addr': '0xb5678'}, {'path': '/my/path', 'addr': '0xabcd'}]}),
162 ('==16118==ERROR: AddressSanitizer: heap-use-after-free on address 0x60700019c710 at pc 0x000014d24643 bp 0x7ffc51f72220 sp 0x7ffc51f72218', None),
163 ('READ of size 8 at 0x60700019c710 thread T0', None),
164 ('#0 0x14d24642 (/jenkins/workspace/scylla-enterprise/dtest-debug/scylla/.ccm/scylla-repository/1a5173bd45d01697d98ba2a7645f5d86afb2d0be/scylla/libexec/scylla+0x14d24642)',
165 {'type': BacktraceResolver
.BacktraceParser
.Type
.ADDRESS
, 'prefix': None,
166 'addresses': [{'path': '/jenkins/workspace/scylla-enterprise/dtest-debug/scylla/.ccm/scylla-repository/1a5173bd45d01697d98ba2a7645f5d86afb2d0be/scylla/libexec/scylla', 'addr': '0x14d24642'}]}),
168 ('Apr 28 11:42:58 ip-172-31-2-154.ec2.internal scylla[10612]: Reactor stalled for 260 ms on shard 20.', None),
169 ('Apr 28 11:42:58 ip-172-31-2-154.ec2.internal scylla[10612]: Backtrace:', None),
170 ('Apr 28 11:42:58 ip-172-31-2-154.ec2.internal scylla[10612]: 0x0000000003163dc2',
171 {'type': BacktraceResolver
.BacktraceParser
.Type
.ADDRESS
, 'prefix': 'Apr 28 11:42:58 ip-172-31-2-154.ec2.internal scylla[10612]:',
172 'addresses': [{'path': None, 'addr': '0x0000000003163dc2'}]}),
174 ('seastar::internal::backtraced<std::runtime_error> (throw_with_backtrace_exception_logging Backtrace: 0x42bc95 /lib64/libc.so.6+0x281e1 0x412cfd)',
175 {'type': BacktraceResolver
.BacktraceParser
.Type
.ADDRESS
, 'prefix': 'seastar::internal::backtraced<std::runtime_error> (throw_with_backtrace_exception_logging Backtrace:',
176 'addresses': [{'path': None, 'addr': '0x42bc95'}, {'path': '/lib64/libc.so.6', 'addr': '0x281e1'}, {'path': None, 'addr': '0x412cfd'}]}),
177 ('seastar::nested_exception: seastar::internal::backtraced<std::runtime_error> (inner Backtrace: 0x42bc95 /lib64/libc.so.6+0x281e1 0x412cfd) (while cleaning up after unknown_obj)',
178 {'type': BacktraceResolver
.BacktraceParser
.Type
.ADDRESS
, 'prefix': 'seastar::nested_exception: seastar::internal::backtraced<std::runtime_error> (inner Backtrace:',
179 'addresses': [{'path': None, 'addr': '0x42bc95'}, {'path': '/lib64/libc.so.6', 'addr': '0x281e1'}, {'path': None, 'addr': '0x412cfd'}]}),
180 ('seastar::nested_exception: seastar::internal::backtraced<std::runtime_error> (inner Backtrace: 0x42bc95 /lib64/libc.so.6+0x281e1 0x412cfd) '
181 '(while cleaning up after seastar::internal::backtraced<std::runtime_error> (outer Backtrace: 0x1234 /lib64/libc.so.6+0x5678 0xabcd))',
182 {'type': BacktraceResolver
.BacktraceParser
.Type
.ADDRESS
,
183 'prefix': 'seastar::nested_exception: seastar::internal::backtraced<std::runtime_error> (inner Backtrace: 0x42bc95 /lib64/libc.so.6+0x281e1 0x412cfd)'
184 ' (while cleaning up after seastar::internal::backtraced<std::runtime_error> (outer Backtrace:',
185 'addresses': [{'path': None, 'addr': '0x1234'}, {'path': '/lib64/libc.so.6', 'addr': '0x5678'}, {'path': None, 'addr': '0xabcd'}]}),
187 parser
= BacktraceResolver
.BacktraceParser()
188 for line
, expected
in data
:
190 assert res
== expected
, f
"{line}:\nExpected {expected}\nBut got {res}"
193 if args
.addresses
and args
.file:
194 print("Cannot use both -f and ADDRESS")
195 cmdline_parser
.print_help()
199 lines
= open(args
.file, 'r')
201 lines
= args
.addresses
203 if sys
.stdin
.isatty():
204 lines
= StdinBacktraceIterator()
208 with
BacktraceResolver(executable
=args
.executable
, before_lines
=args
.before
, context_re
=args
.match
, verbose
=args
.verbose
) as resolve
:
209 p
= re
.compile(r
'\W+')