Skip to content

Instantly share code, notes, and snippets.

@ynsta
Last active June 8, 2023 15:33
Show Gist options
  • Star 7 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save ynsta/7df418cb27b908391f86 to your computer and use it in GitHub Desktop.
Save ynsta/7df418cb27b908391f86 to your computer and use it in GitHub Desktop.
Statistic profiling on stm32f4 with openocd by dwt_pcsr sampling
#!/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
@droneshire
Copy link

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!

@maruncz
Copy link

maruncz commented Jun 23, 2020

Hi nice code, but can you explain what does output mean?

@lijon
Copy link

lijon commented Jun 2, 2023

@lijon
Copy link

lijon commented Jun 8, 2023

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