summaryrefslogtreecommitdiffstats
path: root/qemu/roms/seabios/scripts/checkstack.py
diff options
context:
space:
mode:
Diffstat (limited to 'qemu/roms/seabios/scripts/checkstack.py')
-rwxr-xr-xqemu/roms/seabios/scripts/checkstack.py221
1 files changed, 0 insertions, 221 deletions
diff --git a/qemu/roms/seabios/scripts/checkstack.py b/qemu/roms/seabios/scripts/checkstack.py
deleted file mode 100755
index 5d9b0bfaf..000000000
--- a/qemu/roms/seabios/scripts/checkstack.py
+++ /dev/null
@@ -1,221 +0,0 @@
-#!/usr/bin/env python
-# Script that tries to find how much stack space each function in an
-# object is using.
-#
-# Copyright (C) 2008-2015 Kevin O'Connor <kevin@koconnor.net>
-#
-# This file may be distributed under the terms of the GNU GPLv3 license.
-
-# Usage:
-# objdump -m i386 -M i8086 -M suffix -d out/rom16.o | scripts/checkstack.py
-
-import sys
-import re
-
-# Functions that change stacks
-STACKHOP = ['stack_hop', 'stack_hop_back']
-# List of functions we can assume are never called.
-#IGNORE = ['panic', '__dprintf']
-IGNORE = ['panic']
-
-OUTPUTDESC = """
-#funcname1[preamble_stack_usage,max_usage_with_callers]:
-# insn_addr:called_function [usage_at_call_point+caller_preamble,total_usage]
-#
-#funcname2[p,m,max_usage_to_yield_point]:
-# insn_addr:called_function [u+c,t,usage_to_yield_point]
-"""
-
-class function:
- def __init__(self, funcaddr, funcname):
- self.funcaddr = funcaddr
- self.funcname = funcname
- self.basic_stack_usage = 0
- self.max_stack_usage = None
- self.yield_usage = -1
- self.max_yield_usage = None
- self.total_calls = 0
- # called_funcs = [(insnaddr, calladdr, stackusage), ...]
- self.called_funcs = []
- self.subfuncs = {}
- # Update function info with a found "yield" point.
- def noteYield(self, stackusage):
- if self.yield_usage < stackusage:
- self.yield_usage = stackusage
- # Update function info with a found "call" point.
- def noteCall(self, insnaddr, calladdr, stackusage):
- if (calladdr, stackusage) in self.subfuncs:
- # Already noted a nearly identical call - ignore this one.
- return
- self.called_funcs.append((insnaddr, calladdr, stackusage))
- self.subfuncs[(calladdr, stackusage)] = 1
-
-# Find out maximum stack usage for a function
-def calcmaxstack(info, funcs):
- if info.max_stack_usage is not None:
- return
- info.max_stack_usage = max_stack_usage = info.basic_stack_usage
- info.max_yield_usage = max_yield_usage = info.yield_usage
- total_calls = 0
- seenbefore = {}
- # Find max of all nested calls.
- for insnaddr, calladdr, usage in info.called_funcs:
- callinfo = funcs.get(calladdr)
- if callinfo is None:
- continue
- calcmaxstack(callinfo, funcs)
- if callinfo.funcname not in seenbefore:
- seenbefore[callinfo.funcname] = 1
- total_calls += callinfo.total_calls + 1
- funcnameroot = callinfo.funcname.split('.')[0]
- if funcnameroot in IGNORE:
- # This called function is ignored - don't contribute it to
- # the max stack.
- continue
- totusage = usage + callinfo.max_stack_usage
- totyieldusage = usage + callinfo.max_yield_usage
- if funcnameroot in STACKHOP:
- # Don't count children of this function
- totusage = totyieldusage = usage
- if totusage > max_stack_usage:
- max_stack_usage = totusage
- if callinfo.max_yield_usage >= 0 and totyieldusage > max_yield_usage:
- max_yield_usage = totyieldusage
- info.max_stack_usage = max_stack_usage
- info.max_yield_usage = max_yield_usage
- info.total_calls = total_calls
-
-# Try to arrange output so that functions that call each other are
-# near each other.
-def orderfuncs(funcaddrs, availfuncs):
- l = [(availfuncs[funcaddr].total_calls
- , availfuncs[funcaddr].funcname, funcaddr)
- for funcaddr in funcaddrs if funcaddr in availfuncs]
- l.sort()
- l.reverse()
- out = []
- while l:
- count, name, funcaddr = l.pop(0)
- info = availfuncs.get(funcaddr)
- if info is None:
- continue
- calladdrs = [calls[1] for calls in info.called_funcs]
- del availfuncs[funcaddr]
- out = out + orderfuncs(calladdrs, availfuncs) + [info]
- return out
-
-hex_s = r'[0-9a-f]+'
-re_func = re.compile(r'^(?P<funcaddr>' + hex_s + r') <(?P<func>.*)>:$')
-re_asm = re.compile(
- r'^[ ]*(?P<insnaddr>' + hex_s
- + r'):\t.*\t(addr32 )?(?P<insn>.+?)[ ]*((?P<calladdr>' + hex_s
- + r') <(?P<ref>.*)>)?$')
-re_usestack = re.compile(
- r'^(push[f]?[lw])|(sub.* [$](?P<num>0x' + hex_s + r'),%esp)$')
-
-def main():
- unknownfunc = function(None, "<unknown>")
- indirectfunc = function(-1, '<indirect>')
- unknownfunc.max_stack_usage = indirectfunc.max_stack_usage = 0
- unknownfunc.max_yield_usage = indirectfunc.max_yield_usage = -1
- funcs = {-1: indirectfunc}
- cur = None
- atstart = 0
- stackusage = 0
-
- # Parse input lines
- for line in sys.stdin.readlines():
- m = re_func.match(line)
- if m is not None:
- # Found function
- funcaddr = int(m.group('funcaddr'), 16)
- funcs[funcaddr] = cur = function(funcaddr, m.group('func'))
- stackusage = 0
- atstart = 1
- continue
- m = re_asm.match(line)
- if m is None:
- #print("other", repr(line))
- continue
- insn = m.group('insn')
-
- im = re_usestack.match(insn)
- if im is not None:
- if insn.startswith('pushl') or insn.startswith('pushfl'):
- stackusage += 4
- continue
- elif insn.startswith('pushw') or insn.startswith('pushfw'):
- stackusage += 2
- continue
- stackusage += int(im.group('num'), 16)
-
- if atstart:
- if '%esp' in insn or insn.startswith('leal'):
- # Still part of initial header
- continue
- cur.basic_stack_usage = stackusage
- atstart = 0
-
- insnaddr = m.group('insnaddr')
- calladdr = m.group('calladdr')
- if calladdr is None:
- if insn.startswith('lcallw'):
- cur.noteCall(insnaddr, -1, stackusage + 4)
- cur.noteYield(stackusage + 4)
- elif insn.startswith('int'):
- cur.noteCall(insnaddr, -1, stackusage + 6)
- cur.noteYield(stackusage + 6)
- elif insn.startswith('sti'):
- cur.noteYield(stackusage)
- else:
- # misc instruction
- continue
- else:
- # Jump or call insn
- calladdr = int(calladdr, 16)
- ref = m.group('ref')
- if '+' in ref:
- # Inter-function jump.
- pass
- elif insn.startswith('j'):
- # Tail call
- cur.noteCall(insnaddr, calladdr, 0)
- elif insn.startswith('calll'):
- cur.noteCall(insnaddr, calladdr, stackusage + 4)
- elif insn.startswith('callw'):
- cur.noteCall(insnaddr, calladdr, stackusage + 2)
- else:
- print("unknown call", ref)
- cur.noteCall(insnaddr, calladdr, stackusage)
- # Reset stack usage to preamble usage
- stackusage = cur.basic_stack_usage
-
- # Calculate maxstackusage
- for info in funcs.values():
- calcmaxstack(info, funcs)
-
- # Sort functions for output
- funcinfos = orderfuncs(funcs.keys(), funcs.copy())
-
- # Show all functions
- print(OUTPUTDESC)
- for info in funcinfos:
- if info.max_stack_usage == 0 and info.max_yield_usage < 0:
- continue
- yieldstr = ""
- if info.max_yield_usage >= 0:
- yieldstr = ",%d" % info.max_yield_usage
- print("\n%s[%d,%d%s]:" % (info.funcname, info.basic_stack_usage
- , info.max_stack_usage, yieldstr))
- for insnaddr, calladdr, stackusage in info.called_funcs:
- callinfo = funcs.get(calladdr, unknownfunc)
- yieldstr = ""
- if callinfo.max_yield_usage >= 0:
- yieldstr = ",%d" % (stackusage + callinfo.max_yield_usage)
- print(" %04s:%-40s [%d+%d,%d%s]" % (
- insnaddr, callinfo.funcname, stackusage
- , callinfo.basic_stack_usage
- , stackusage+callinfo.max_stack_usage, yieldstr))
-
-if __name__ == '__main__':
- main()