Last active
June 8, 2023 15:33
-
-
Save ynsta/7df418cb27b908391f86 to your computer and use it in GitHub Desktop.
Statistic profiling on stm32f4 with openocd by dwt_pcsr sampling
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/python2 | |
# run openocd (0.9.0) with : | |
# $ openocd -f stlink-v2-1.cfg -f stm32f4x.cfg &> /dev/null" | |
# then run | |
# $ python2 sampler.py path_to_myelf_with_symbols | |
import sys | |
import time | |
import telnetlib | |
import subprocess | |
from bisect import bisect_right | |
import operator | |
class OpenOCDCMSampler(object): | |
def __init__(self, host='localhost', port=4444): | |
self.net = telnetlib.Telnet(host, port) | |
self.net.read_very_eager() | |
self.table = [] | |
self.indexes = set() | |
def __del__(self): | |
self.net.write('exit\r\n') | |
self.net.read_until('exit\r\n', 1) | |
self.net.close() | |
def getpc(self): | |
self.net.write('mrw 0xE000101C\r\n') | |
res = self.net.read_until('\r\n\r> ', 1) | |
if res: | |
prefix = res[0:16] | |
num = res[16:-5] | |
res = res[-15:0] | |
if prefix == 'mrw 0xE000101C\r\n': | |
return int(num) | |
return 0 | |
def initSymbols(self, elf, readelf='readelf'): | |
proc = subprocess.Popen([readelf, '-s', elf], stdout=subprocess.PIPE) | |
for line in iter(proc.stdout.readline, ''): | |
field = line.split() | |
try: | |
if field[3] == 'FUNC': | |
addr = int(field[1], 16) | |
func = field[7] | |
size = int(field[2]) | |
if addr not in self.indexes: | |
self.table.append((addr, func, size)) | |
self.indexes.add(addr) | |
except IndexError: | |
pass | |
self.table.sort() | |
self.addrs = [ x for (x, y, z) in self.table ] | |
def func(self, pc): | |
if pc == 0 or pc == 0xFFFFFFFF: | |
return ('', 0) | |
i = bisect_right(self.addrs, pc) | |
if i: | |
addr, symb, size = self.table[i-1] | |
if pc >= addr and pc <= addr + size: | |
return (symb, addr) | |
return ('', 0) | |
if __name__ == '__main__': | |
sampler = OpenOCDCMSampler('localhost', 4444) | |
sampler.initSymbols(sys.argv[1]) | |
total = 0 | |
countmap = { } | |
start = time.time() | |
try: | |
while True: | |
func, addr = sampler.func((sampler.getpc())) | |
if not addr: | |
continue | |
if func in countmap: | |
countmap[func] += 1 | |
total += 1 | |
else: | |
countmap[func] = 1 | |
total += 1 | |
cur = time.time() | |
if cur - start > 1.0: | |
tmp = sorted(countmap.items(), key=operator.itemgetter(1), reverse=True) | |
for k, v in tmp: | |
print '{:05.2f}% {}'.format((v * 100.) / total, k) | |
start = cur | |
print '' | |
except KeyboardInterrupt: | |
pass |
Hi nice code, but can you explain what does output mean?
Nice!
I adapted it for python3: https://gist.github.com/lijon/d87543039aa773995704c881c61c2d1c
Here's an improved version! https://github.com/lijon/cortex-profiler
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Hi ynsta, what is the usage agreement on this code? do you mind if I use it? It is awesome btw, thanks for sharing with the world!