If your crash log have dump maps, user stacks, and you have symbols too,
You can try to get a backtrace via below python scripts.
[2-11624.8825] PC, LR MEMINFO
[2-11624.8825] --------------------------------------------------------------------------------------
[2-11624.8825] PC:46cbfc92, LR:46cbfc59
[2-11624.8825] --------------------------------------------------------------------------------------
[2-11624.8825] PC meminfo (0x46cc005d to 0x46cc0092)
[2-11624.8825] 0040:
[2-11624.8825] 0060: be07e9cd 801cf8d0 f04fb085 f1010901 ea4f061b e0015707 d03142b4 f85446a3
[2-11624.8825] 0080: f0055b04 2b010303 ea4fd1f6 f8d85a15 ea4f3a14
[2-11624.8825] --------------------------------------------------------------------------------------
[2-11624.8825] LR meminfo (0x46cbf459 to 0x46cc0059)
[2-11624.8825] f440: 0205ea02
[2-11624.8825] f460: bf0442a2 f8832201 d009202c f84269da 6a191020 f1016a9a ea020101 621a0201
[2-11624.8825] f480: e9ddb002 b0024500 bf004770 8000f3af 4506e96d 5413ea4f e9cd460d ea4f8e04
......
[2-11624.8831] * dump maps on pid (2548 - efl_webprocess)
[2-11624.8831] -----------------------------------------------------------
[2-11624.8831] 00010000-00011000 r-xp 00000000 b3:12 55716 /usr/lib/chromium-efl/efl_webprocess
[2-11624.8831] 00020000-00021000 r--p 00000000 b3:12 55716 /usr/lib/chromium-efl/efl_webprocess
[2-11624.8831] 00021000-00022000 rw-p 00000000 00:00 0
[2-11624.8831] 00031000-00036000 rw-p 00001000 b3:12 55716 /usr/lib/chromium-efl/efl_webprocess
[2-11624.8831] 00036000-0007c000 rw-p 00000000 00:00 0 [heap]
[2-11624.8831] 0007c000-008ae000 rw-p 00000000 00:00 0 [heap]
[2-11624.8917] -----------------------------------------------------------
[2-11624.8917] * dump user stack
[2-11624.8917] -----------------------------------------------------------
[2-11624.8917] pid(2548) stack vma (0xbe729000 ~ 0xbe74c000)
[2-11624.8917] User Stack: (0xbe749e20 to 0xbe745f10)
[2-11624.8917] -----------------------------------------------------------
Save below python scripts as btfs(chmod a+x btfs)
Usage: btfs [option] symbols serial
backtrace from serial log
The options are :
-d use debug symbols
Examples :
btfs symbols dump_systemstate_20161220110158.log
btfs -d symbols dump_systemstate_20161220110158.log
All related libs and bins that have debug info should placed in symbols folder like:
symbols$ ls
lib usr
#!/usr/bin/env python
#Author errong.leng@gmail.com
import commands
import argparse
import glob
import os
import shlex
import subprocess
import sys
import time
import re
STATE_NONE = 0
STATE_PC = 1
STATE_LR = 2
STATE_DUMP_MAPS = 3
STATE_DUMP_MAPS_BEGIN = 4
STATE_DUMP_MAPS_END = 5
STATE_USERSTACK = 6
STATE_USERSTACK_BEGIN = 7
STATE_USERSTACK_END = 8
def hexstr2int(s):
r = 0
i = 0
if (len(s) >= 2 and s[0] == '0' and (s[1] == 'x' or s[1] == 'X')):
i = 2
while i < len(s):
if (s[i] == '\0' or s[i] == '\n' or s[i] == '\r'):
break
if (s[i] >= 'a'):
r = ord(s[i]) - ord('a') + 10 + r*16;
elif (s[i] >= 'A'):
r = ord(s[i]) - ord('A') + 10 + r*16;
else:
r = ord(s[i]) - ord('0') + r*16;
i = i + 1
return r
def ishexstr(s):
i = 0
while i < len(s):
if (s[i] == '\0' or s[i] == '\n' or s[i] == '\r'):
break
if ((s[i] >= '0' and s[i] <= '9') or
(s[i] >= 'a' and s[i] <= 'f') or
(s[i] >= 'A' and s[i] <= 'F') or
s[i] == 'x' or
s[i] == 'X'):
i = i + 1
else:
return 0
return 1
class AdressSeg:
def __init__(self, begin, end):
self.begin = begin
self.end = end
def begin(self):
return self.begin
def end(self):
return self.end
class AdressSegList:
def __init__(self):
self.adlist = []
self.begin = -1
def append(self, begin, end):
self.adlist.append(AdressSeg(begin, end))
if (self.begin == -1):
self.begin = begin
self.end = end
def libbegin(self):
return self.begin
def libend(self):
return self.end
class Meminfo:
def __init__(self, adressseg):
self.addressseg = adressseg
self.mem_list = []
def begin(self):
return self.addressseg.begin
def end(self):
return self.end
class AdressSegList:
def __init__(self):
self.adlist = []
self.begin = -1
def append(self, begin, end):
self.adlist.append(AdressSeg(begin, end))
if (self.begin == -1):
self.begin = begin
self.end = end
def libbegin(self):
return self.begin
def libend(self):
return self.end
class Meminfo:
def __init__(self, adressseg):
self.addressseg = adressseg
self.mem_list = []
def begin(self):
return self.addressseg.begin
def end(self):
return self.addressseg.end
def append_memory(self, memory):
self.mem_list.append(memory)
class MapInfo:
def __init__(self, address_seg, exe_lib_path):
self.address_seg = address_seg;
self.exe_lib_path = exe_lib_path
class MapList:
def __init__(self):
self.exe_libs = {}
self.filecheck = {}
self.btcount = 0
def append_map(self, begin, end, libpath):
if (self.exe_libs.has_key(libpath)):
self.exe_libs[libpath].append(begin, end)
else:
adlist = AdressSegList()
adlist.append(begin, end)
self.exe_libs[libpath] = adlist
def map_mem_info(self, meminfo, symbol_path, debug):
j = 0
while j < len(meminfo.mem_list):
memory = meminfo.mem_list[j]
j = j + 1
self.map_memory(memory, symbol_path, debug)
def map_memory_pc(self, memory, symbol_path, debug):
ret = self.map_memory(memory, symbol_path, debug)
if (ret == 0):
print "#%-2d %s in ?? " % (self.btcount, memory)
self.btcount = self.btcount + 1
def map_memory(self, memory, symbol_path, debug):
if (not ishexstr(memory)):
return 0
pc = hexstr2int(memory) - 1
libs = self.exe_libs.keys()
i = 0
while i < len(libs):
libpath = libs[i]
i = i + 1
real_libpath = symbol_path + libpath
debug_libpath = symbol_path + "/usr/lib/debug" + libpath + ".debug"
if (not (os.path.exists(real_libpath))):
del self.exe_libs[libpath]
continue
if (not self.filecheck.has_key(libpath)):
command_line = "file " + real_libpath
(status, output) = commands.getstatusoutput(command_line)
if (status != 0):
del self.exe_libs[libpath]
continue
if (not (re.search(r'ELF 32-bit LSB shared object', output) or
re.search(r'ELF 32-bit LSB executable', output))):
del self.exe_libs[libpath]
continue
self.filecheck[libpath] = 1
adlist = self.exe_libs[libpath]
libbegin = hexstr2int(adlist.libbegin())
libend = hexstr2int(adlist.libend())
if (pc < libbegin or pc > libend):
continue
address = pc - libbegin
hexaddress = hex(address)
option = " -afC "
real_debug = 0
if debug == 1:
if (os.path.exists(debug_libpath)):
real_debug = 1
real_libpath = debug_libpath
option = " -afiC "
command_line = "addr2line -e " + real_libpath + option + hexaddress
(status, output) = commands.getstatusoutput(command_line)
if (status == 0):
funcs = output.split('\n')
if (re.search(r'\$d', funcs[1], re.I) or
re.search(r'\$t', funcs[1], re.I)):
return 1
if real_debug == 1:
print "#%-2d %s in %s" % (self.btcount, hex(pc), funcs[len(funcs)-2])
print " at " + funcs[len(funcs)-1]
else:
print "#%-2d %s in %s" % (self.btcount, hex(pc), funcs[1])
print " at " + libpath
self.btcount = self.btcount + 1
return 1
return 0
class CoreDumpInfo:
def __init__(self, io_state, debug):
self.io_state = io_state
self.debug = debug
self.maps = MapList()
def set_state(self, io_state):
self.io_state = io_state
def set_name(self, name):
self.name = name
def set_pc(self, pc):
self.pc = pc
def set_lr(self, lr):
self.lr = lr
def set_usr_stack_meminfo(self, meminfo):
self.urs_meminfo = meminfo
def mem_end(self):
return self.urs_meminfo.end()
def mem_begin(self):
return self.urs_meminfo.begin()
def set_mem_end(self):
self.io_state = STATE_USERSTACK_END
def append_memory(self, memory):
self.urs_meminfo.append_memory(memory)
def append_map(self, begin, end, libpath):
i = len(libpath) - 1
while i >= 0:
if (libpath[i] == '\0' or
libpath[i] == '\n' or
libpath[i] == ' ' or
libpath[i] == '\r'):
i = i - 1
else:
break
path = libpath[:i+1]
self.maps.append_map(begin, end, path)
def backtrace(self, symbol_path):
print "bt full for " + self.name
self.maps.map_memory_pc(self.pc, symbol_path, self.debug)
self.maps.map_memory(self.lr, symbol_path, self.debug)
self.maps.map_mem_info(self.urs_meminfo, symbol_path, self.debug)
def DoReadPC(line, core_dump_info):
pcobj = re.search(r'PC is at (.*)', line)
if (pcobj):
core_dump_info.set_state(STATE_PC)
core_dump_info.set_pc(pcobj.group(1))
def DoReadLR(line, core_dump_info):
lrobj = re.search(r'LR is at (.*)', line)
if (lrobj):
core_dump_info.set_state(STATE_LR)
core_dump_info.set_lr(lrobj.group(1))
def DoReadUserStackList(line, core_dump_info):
if (re.search(r'----------------------------', line)):
core_dump_info.set_mem_end()
return
mfobj = re.search(r' ([A-Fa-f0-9]{4}): (.*)', line)
if (not mfobj):
return
memory_begin = mfobj.group(1)
mems = mfobj.group(2).split(' ')
end = core_dump_info.mem_end()
b4 = core_dump_info.mem_begin()[0:4]
e4 = end[0:4]
if ((hexstr2int(b4 + memory_begin) + 32) >= hexstr2int(end) or
(hexstr2int(e4 + memory_begin) + 32) >= hexstr2int(end)):
core_dump_info.set_mem_end(flag)
i = 0
while i < len(mems):
memory = mems[i][:8]
i = i+1
if (re.search(r'[A-Fa-f0-9]{8}', memory)):
core_dump_info.append_memory(memory)
def DoReadDumpMaps(line, core_dump_info):
dmobj = re.search(r'dump maps on pid \((.*)\)', line)
if (dmobj):
core_dump_info.set_name(dmobj.group(1))
core_dump_info.set_state(STATE_DUMP_MAPS)
def DoReadMaps(line, core_dump_info):
if (re.search(r'task stack info', line)):
core_dump_info.set_state(STATE_DUMP_MAPS_END)
return
mapobj = re.search(r'([A-Fa-z0-9]{8})-([A-Fa-z0-9]{8}).*(\/usr\/.*)', line)
if (not mapobj):
return
core_dump_info.append_map(mapobj.group(1), mapobj.group(2), mapobj.group(3))
def DoReadUserStack(line, core_dump_info):
usobj = re.search(r'User Stack: \((.*) to (.*)\)', line)
if (usobj):
core_dump_info.set_state(STATE_USERSTACK_BEGIN)
core_dump_info.set_usr_stack_meminfo(Meminfo(AdressSeg(usobj.group(1), usobj.group(2))))
def read_line(line, core_dump_info):
io_state = core_dump_info.io_state
if (io_state < STATE_PC):
DoReadPC(line, core_dump_info)
elif (io_state < STATE_LR):
DoReadLR(line, core_dump_info)
elif (io_state < STATE_DUMP_MAPS):
DoReadDumpMaps(line, core_dump_info)
elif (io_state == STATE_DUMP_MAPS):
core_dump_info.io_state = STATE_DUMP_MAPS_BEGIN
elif (io_state < STATE_DUMP_MAPS_END):
DoReadMaps(line, core_dump_info)
elif (io_state < STATE_USERSTACK):
DoReadUserStack(line, core_dump_info)
elif (io_state < STATE_USERSTACK_END):
DoReadUserStackList(line, core_dump_info)
def print_help():
print "Usage: btfs [option] symbols serial"
print " backtrace from serial log "
print " The options are : "
print " -d use debug symbols"
print " Examples : "
print " btfs symbols dump_systemstate_20161220110158.log"
print " btfs -d symbols dump_systemstate_20161220110158.log"
def gen_coredump(logfile, symbols, use_debug, begin_line, line_count):
lastline = int(line_count) - int(begin_line) + 6
core_dump = "/tmp/coredump_" + str(time.time())
command_line = "tail -n " + str(lastline) + " " + logfile + " > " + core_dump
os.system(command_line)
core_dump_info = CoreDumpInfo(STATE_NONE, use_debug)
for line in open(core_dump):
if (core_dump_info.io_state == STATE_USERSTACK_END):
break;
read_line(line, core_dump_info)
if (core_dump_info.io_state >= STATE_USERSTACK):
core_dump_info.backtrace(symbols)
elif (core_dump_info.io_state >= STATE_DUMP_MAPS):
print "User Stack not found"
elif (core_dump_info.io_state >= STATE_LR):
print "dump maps not found"
elif (core_dump_info.io_state >= STATE_PC):
print "LR is at not found"
elif (core_dump_info.io_state >= STATE_NONE):
print "PC is at not found"
command_line = "rm -f " + core_dump
os.system(command_line)
def isdigital(s):
l = len(s)
i = 0
while (i < l and s[i] != '\0' and s[i] != '\n' and s[i] != '\r'):
if (s[i] >= '0' and s[i] <= '9'):
i = i + 1
continue
else:
return 0
return 1
def main_function():
if (len(sys.argv) < 3 or len(sys.argv) > 4):
print_help()
return
i = 1
use_debug = 0
if len(sys.argv) >= 4:
if (len(sys.argv[1]) < 2 or sys.argv[1][0] != '-' or sys.argv[1][1] != 'd'):
print_help()
return
use_debug = 1
symbol_path = sys.argv[len(sys.argv)-2]
if (not os.path.exists(symbol_path)):
symbol_path = os.path.abspath(os.curdir) + "/" + symbol_path
if (not os.path.exists(symbol_path)):
print symbol_path + " is not existed\n"
return
log_file = sys.argv[len(sys.argv)-1]
if (not os.path.exists(log_file)):
log_file = os.path.abspath(os.curdir) + "/" + log_file
if (not os.path.exists(log_file)):
print log_file + " is not existed\n"
return
command_line = "wc -l "+log_file+"|awk '{print $1}'"
(status, line_count) = commands.getstatusoutput(command_line)
if status:
print command_line + " return " + status
return
print "log file total line count : %s" % line_count
command_line = "cat " + log_file + "|grep -an 'PC is at'" + "|awk 'BEGIN{FS=\":\"} {print $1}'"
(status, core_dump_begin_line) = commands.getstatusoutput(command_line)
if status:
print command_line + " return " + status
return
print "line number of which include 'PC is at' : \n%s" % core_dump_begin_line
begin_lines = core_dump_begin_line.split('\n')
if (len(begin_lines) <= 0):
if (isdigital(begin_lines)):
gen_coredump(log_file, symbol_path, use_debug, core_dump_begin_line, line_count)
else:
print "%d coredump founded" % len(begin_lines)
index = 0
for begin_line in begin_lines:
index = index + 1
if (isdigital(begin_line)):
gen_coredump(log_file, symbol_path, use_debug, begin_line, line_count)
if (index < len(begin_lines)):
print "\n"
print "\n"
if __name__ == '__main__':
main_function()
Subscribe to:
Post Comments (Atom)
fixed: embedded-redis: Unable to run on macOS Sonoma
Issue you might see below error while trying to run embedded-redis for your testing on your macOS after you upgrade to Sonoma. java.la...
-
F:\webrowser>react-native run-android Scanning folders for symlinks in F:\webrowser\node_modules (73ms) Starting JS server... Buildin...
-
Refer: https://github.com/bazelbuild/bazel/wiki/Building-with-a-custom-toolchain https://www.tensorflow.org/tutorials/image_recognition
-
Solution react-native bundle --platform android --dev false --entry-file index.js --bundle-output android/app/src/main/assets/index.android...
No comments:
Post a Comment