import os
import gdb
from array import array
'''
Pouziti v arm-none-eabi-gdb:
source stack.py
stack_usage
'''
tmp_filename = 'stack.tmp'
# Vraci hodnoty symbolu definovanych v linker scriptu
def get_sym (sym):
res = gdb.execute ('p/x &' + sym, to_string=True);
res = res.strip ()
res = res.split ('=')
if len(res) < 2: return 0
value = int (res[1], 16);
return value
# Jen pro uplnost, neni celkem potreba
def data_usage ():
DataBegin = get_sym ('_sdata')
DataEnd = get_sym ('_edata')
DataLen = DataEnd - DataBegin
BssBegin = get_sym ('_sbss')
BssEnd = get_sym ('_ebss')
BssLen = BssEnd - BssBegin
gdb.write ('Data Total: \x1B[34;1m0x%08X \x1B[33;1m(%6d)\x1B[0m bytes\n' % (DataLen, DataLen))
gdb.write ('Bss Total: \x1B[34;1m0x%08X \x1B[33;1m(%6d)\x1B[0m bytes\n' % (BssLen, BssLen))
'''
# Spocte pocet pouzitych slov ve stacku (ze souboru zjisti posledni DEADBEEF)
def parse_file (name, size):
info = os.stat (name)
if size != info.st_size: return 0
file = open (name, 'r')
data = array('I')
size = size / 4 # size from bytes to words
data.fromfile (file, size);
file.close()
count = 0
for word in data:
if word != 0xdeadbeef: break
count += 1
return size - count # in words
# Vypsat data do souboru je nekdy lepsi - muzeme je podrobne zkoumat
def method_file (adr_from, adr_to):
command = 'dump memory %s 0x%08X 0x%08X' % (tmp_filename, adr_from, adr_to)
print command
gdb.execute (command)
return parse_file (tmp_filename, adr_to - adr_from) * 4
'''
def value_at (addr):
res = gdb.execute ('x/x 0x%08X' % (addr), to_string=True);
res = res.strip ()
res = res.split (':')
if len(res) < 2: return 0
value = int (res[1], 16);
return value
# Hledame nejvetsi prvek souvisle mnoziny slov DEADBEEF
def bisection (a, b):
if (b - a) <= 4 : return b
c = int(a + b) >> 1
c = c & ~0x3
if value_at (c) == 0xdeadbeef:
return bisection(c, b)
else:
return bisection(a, c)
# Pro vetsi RAM je lepe pouzit (rekurzivni) bisekci, DEADBEEF je vzdy ve spodni casti
def method_bisect (adr_from, adr_to):
adr_end = bisection (adr_from, adr_to)
return adr_to - adr_end
def stack_usage ():
data_usage() # mozno zakomentovat, pokud ukazuje blbosti
StackTop = get_sym ('_estack')
StackBottom = get_sym ('_ebss')
if StackTop == 0: return
if StackBottom == 0: return
StackTotal = StackTop - StackBottom
gdb.write ('StackTotal: \x1B[34;1m0x%08X \x1B[33;1m(%6d)\x1B[0m bytes\n' % (StackTotal, StackTotal))
StackUsed = method_bisect (StackBottom, StackTop)
gdb.write ('Stack Used: \x1B[34;1m0x%08X \x1B[33;1m(%6d)\x1B[0m bytes\n' % (StackUsed, StackUsed))
class StackUsageCommand (gdb.Command):
"Stack Usage, method DEADBEEF"
def __init__ (self):
super (StackUsageCommand, self).__init__ ("stack_usage",
gdb.COMMAND_SUPPORT,
gdb.COMPLETE_NONE, True)
def invoke (self, arg, from_tty):
stack_usage ()
StackUsageCommand()