Skip to content

Commit 156f542

Browse files
committed
Improve symbolication of stacktraces on Linux.
* Finds lldb site-package relative to swift executable * Caches lldb target for better performance * Assumes stdin as the log source
1 parent c5342a5 commit 156f542

File tree

1 file changed

+36
-8
lines changed

1 file changed

+36
-8
lines changed

utils/symbolicate-linux-fatal

Lines changed: 36 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,17 @@ import argparse
2828
import os
2929
import subprocess
3030

31-
import lldb
31+
try:
32+
import lldb
33+
except ImportError:
34+
from distutils import spawn
35+
swift_exec = spawn.find_executable('swift')
36+
if swift_exec is not None:
37+
site_packages = os.path.join(os.path.dirname(swift_exec),
38+
'../lib/python2.7/site-packages/')
39+
import sys
40+
sys.path.append(site_packages)
41+
import lldb
3242

3343

3444
def process_ldd(lddoutput):
@@ -38,7 +48,7 @@ def process_ldd(lddoutput):
3848
if len(ldd_tokens) >= 2:
3949
lib = ldd_tokens[-2]
4050
dyn_libs[ldd_tokens[0]] = lib
41-
real_name = os.path.basename(os.path.realpath(lib))
51+
real_name = os.path.basename(os.path.realpath(lib))
4252
dyn_libs[real_name] = lib
4353
return dyn_libs
4454

@@ -57,8 +67,18 @@ def create_lldb_target(binary, memmap):
5767
lldb_target.SetModuleLoadAddress(module, memmap[dynlib_path])
5868
return lldb_target
5969

70+
def add_lldb_target_modules(lldb_target, memmap):
71+
for dynlib_path in memmap:
72+
module = lldb_target.AddModule(
73+
dynlib_path, lldb.LLDB_ARCH_DEFAULT, None, None)
74+
lldb_target.SetModuleLoadAddress(module, memmap[dynlib_path])
75+
76+
lldb_target = None
77+
known_memmap = {}
6078

6179
def process_stack(binary, dyn_libs, stack):
80+
global lldb_target
81+
global known_memmap
6282
if len(stack) == 0:
6383
return
6484
memmap = {}
@@ -77,21 +97,29 @@ def process_stack(binary, dyn_libs, stack):
7797
framePC = int(stack_tokens[2], 16)
7898
symbol_offset = int(stack_tokens[-1], 10)
7999
dynlib_baseaddr = framePC - symbol_offset
80-
if dynlib_path in memmap:
81-
if memmap[dynlib_path] != dynlib_baseaddr:
100+
if dynlib_path in memmap or dynlib_path in known_memmap:
101+
if dynlib_path in memmap:
102+
existing_baseaddr = memmap[dynlib_path]
103+
else:
104+
existing_baseaddr = known_memmap[dynlib_path]
105+
if existing_baseaddr != dynlib_baseaddr:
82106
error_msg = "Mismatched base address for: {0:s}, " \
83107
"had: {1:x}, now got {2:x}"
84108
error_msg = error_msg.format(
85-
dynlib_path, memmap[dynlib_path], dynlib_baseaddr)
109+
dynlib_path, existing_baseaddr, dynlib_baseaddr)
86110
raise Exception(error_msg)
87111
else:
112+
known_memmap[dynlib_path] = dynlib_baseaddr
88113
memmap[dynlib_path] = dynlib_baseaddr
89114
else:
90115
framePC = int(stack_tokens[2], 16) + int(stack_tokens[-1], 10)
91116
full_stack.append(
92117
{"line": line, "framePC": framePC, "dynlib_fname": dynlib_fname})
93118

94-
lldb_target = create_lldb_target(binary, memmap)
119+
if lldb_target == None:
120+
lldb_target = create_lldb_target(binary, memmap)
121+
else:
122+
add_lldb_target_modules(lldb_target, memmap)
95123
frame_idx = 0
96124
for frame in full_stack:
97125
use_orig_line = True
@@ -130,8 +158,8 @@ def main():
130158
parser.add_argument(
131159
"binary", help="Executable which produced the log file")
132160
parser.add_argument(
133-
"log", type=argparse.FileType("rU"),
134-
help="Log file containing the stack trace to symbolicate")
161+
"log", nargs='?', type=argparse.FileType("rU"), default="-",
162+
help="Log file containing the stack trace to symbolicate. Defaults to stdin.")
135163
args = parser.parse_args()
136164

137165
binary = args.binary

0 commit comments

Comments
 (0)