diff options
Diffstat (limited to 'qemu/roms/seabios/scripts')
-rwxr-xr-x | qemu/roms/seabios/scripts/buildversion.py | 134 | ||||
-rwxr-xr-x | qemu/roms/seabios/scripts/buildversion.sh | 31 | ||||
-rwxr-xr-x | qemu/roms/seabios/scripts/checkrom.py | 2 | ||||
-rwxr-xr-x | qemu/roms/seabios/scripts/checkstack.py | 270 | ||||
-rw-r--r-- | qemu/roms/seabios/scripts/kconfig/lxdialog/util.c | 2 | ||||
-rwxr-xr-x | qemu/roms/seabios/scripts/layoutrom.py | 8 |
6 files changed, 276 insertions, 171 deletions
diff --git a/qemu/roms/seabios/scripts/buildversion.py b/qemu/roms/seabios/scripts/buildversion.py new file mode 100755 index 000000000..46928984e --- /dev/null +++ b/qemu/roms/seabios/scripts/buildversion.py @@ -0,0 +1,134 @@ +#!/usr/bin/env python +# Generate version information for a program +# +# Copyright (C) 2015 Kevin O'Connor <kevin@koconnor.net> +# +# This file may be distributed under the terms of the GNU GPLv3 license. +import sys, os, subprocess, shlex, time, socket, optparse, logging, traceback + +VERSION_FORMAT = """ +/* DO NOT EDIT! This is an autogenerated file. See scripts/buildversion.py. */ +#define BUILD_VERSION "%s" +#define BUILD_TOOLS "%s" +""" + +# Run program and return the specified output +def check_output(prog): + logging.debug("Running %s" % (repr(prog),)) + try: + process = subprocess.Popen(shlex.split(prog), stdout=subprocess.PIPE) + output = process.communicate()[0] + retcode = process.poll() + except OSError: + logging.debug("Exception on run: %s" % (traceback.format_exc(),)) + return "" + logging.debug("Got (code=%s): %s" % (retcode, repr(output))) + if retcode: + return "" + try: + return output.decode() + except UnicodeError: + logging.debug("Exception on decode: %s" % (traceback.format_exc(),)) + return "" + +# Obtain version info from "git" program +def git_version(): + if not os.path.exists('.git'): + logging.debug("No '.git' file/directory found") + return "" + ver = check_output("git describe --tags --long --dirty").strip() + logging.debug("Got git version: %s" % (repr(ver),)) + return ver + +# Look for version in a ".version" file. Official release tarballs +# have this file (see scripts/tarball.sh). +def file_version(): + if not os.path.isfile('.version'): + logging.debug("No '.version' file found") + return "" + try: + f = open('.version', 'r') + ver = f.readline().strip() + f.close() + except OSError: + logging.debug("Exception on read: %s" % (traceback.format_exc(),)) + return "" + logging.debug("Got .version: %s" % (repr(ver),)) + return ver + +# Generate an output file with the version information +def write_version(outfile, version, toolstr): + logging.debug("Write file %s and %s" % (repr(version), repr(toolstr))) + sys.stdout.write("Version: %s\n" % (version,)) + f = open(outfile, 'w') + f.write(VERSION_FORMAT % (version, toolstr)) + f.close() + +# Run "tool --version" for each specified tool and extract versions +def tool_versions(tools): + tools = [t.strip() for t in tools.split(';')] + versions = ['', ''] + success = 0 + for tool in tools: + # Extract first line from "tool --version" output + verstr = check_output("%s --version" % (tool,)).split('\n')[0] + # Check if this tool looks like a binutils program + isbinutils = 0 + if verstr.startswith('GNU '): + isbinutils = 1 + verstr = verstr[4:] + # Extract version information and exclude program name + if ' ' not in verstr: + continue + prog, ver = verstr.split(' ', 1) + if not prog or not ver: + continue + # Check for any version conflicts + if versions[isbinutils] and versions[isbinutils] != ver: + logging.debug("Mixed version %s vs %s" % ( + repr(versions[isbinutils]), repr(ver))) + versions[isbinutils] = "mixed" + continue + versions[isbinutils] = ver + success += 1 + cleanbuild = versions[0] and versions[1] and success == len(tools) + return cleanbuild, "gcc: %s binutils: %s" % (versions[0], versions[1]) + +def main(): + usage = "%prog [options] <outputheader.h>" + opts = optparse.OptionParser(usage) + opts.add_option("-e", "--extra", dest="extra", default="", + help="extra version string to append to version") + opts.add_option("-t", "--tools", dest="tools", default="", + help="list of build programs to extract version from") + opts.add_option("-v", action="store_true", dest="verbose", + help="enable debug messages") + + options, args = opts.parse_args() + if len(args) != 1: + opts.error("Incorrect arguments") + outfile = args[0] + if options.verbose: + logging.basicConfig(level=logging.DEBUG) + + cleanbuild, toolstr = tool_versions(options.tools) + + ver = git_version() + cleanbuild = cleanbuild and 'dirty' not in ver + if not ver: + ver = file_version() + # We expect the "extra version" to contain information on the + # distributor and distribution package version (if + # applicable). It is a "clean" build if this is a build from + # an official release tarball and the above info is present. + cleanbuild = cleanbuild and ver and options.extra != "" + if not ver: + ver = "?" + if not cleanbuild: + btime = time.strftime("%Y%m%d_%H%M%S") + hostname = socket.gethostname() + ver = "%s-%s-%s" % (ver, btime, hostname) + write_version(outfile, ver + options.extra, toolstr) + +if __name__ == '__main__': + main() diff --git a/qemu/roms/seabios/scripts/buildversion.sh b/qemu/roms/seabios/scripts/buildversion.sh deleted file mode 100755 index 516aff5b2..000000000 --- a/qemu/roms/seabios/scripts/buildversion.sh +++ /dev/null @@ -1,31 +0,0 @@ -#!/bin/sh -# Script to generate a C file with version information. -OUTFILE="$1" -VAR16MODE="$2" - -# Extract version info -if [ -z "$BUILD_VERSION" ]; then - if [ -d .git -o -f .git ]; then - VERSION="`git describe --tags --long --dirty`" - elif [ -f .version ]; then - VERSION="`cat .version`" - else - VERSION="?" - fi - VERSION="${VERSION}-`date +"%Y%m%d_%H%M%S"`-`hostname`" -else - VERSION="$BUILD_VERSION" -fi -echo "Version: ${VERSION}" - -# Build header file -if [ "$VAR16MODE" = "VAR16" ]; then - cat > ${OUTFILE} <<EOF -#include "types.h" -char VERSION[] VAR16 = "${VERSION}"; -EOF -else - cat > ${OUTFILE} <<EOF -char VERSION[] = "${VERSION}"; -EOF -fi diff --git a/qemu/roms/seabios/scripts/checkrom.py b/qemu/roms/seabios/scripts/checkrom.py index 377277db5..aced5e2cf 100755 --- a/qemu/roms/seabios/scripts/checkrom.py +++ b/qemu/roms/seabios/scripts/checkrom.py @@ -39,7 +39,7 @@ def main(): finalsize = 256*1024 if datasize > finalsize: print("Error! ROM doesn't fit (%d > %d)" % (datasize, finalsize)) - print(" You have to either increate the size (CONFIG_ROM_SIZE)") + print(" You have to either increase the size (CONFIG_ROM_SIZE)") print(" or turn off some features (such as hardware support not") print(" needed) to make it fit. Trying a more recent gcc version") print(" might work too.") diff --git a/qemu/roms/seabios/scripts/checkstack.py b/qemu/roms/seabios/scripts/checkstack.py index b49b6c8cc..5d9b0bfaf 100755 --- a/qemu/roms/seabios/scripts/checkstack.py +++ b/qemu/roms/seabios/scripts/checkstack.py @@ -2,7 +2,7 @@ # Script that tries to find how much stack space each function in an # object is using. # -# Copyright (C) 2008 Kevin O'Connor <kevin@koconnor.net> +# Copyright (C) 2008-2015 Kevin O'Connor <kevin@koconnor.net> # # This file may be distributed under the terms of the GNU GPLv3 license. @@ -26,85 +26,84 @@ OUTPUTDESC = """ # 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(funcs, funcaddr): - info = funcs[funcaddr] - # Find max of all nested calls. - maxusage = info[1] - maxyieldusage = doesyield = 0 - if info[3] is not None: - maxyieldusage = info[3] - doesyield = 1 - info[2] = maxusage - info[4] = info[3] +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 = {} - totcalls = 0 - for insnaddr, calladdr, usage in info[6]: + # Find max of all nested calls. + for insnaddr, calladdr, usage in info.called_funcs: callinfo = funcs.get(calladdr) if callinfo is None: continue - if callinfo[2] is None: - calcmaxstack(funcs, calladdr) - if callinfo[0] not in seenbefore: - seenbefore[callinfo[0]] = 1 - totcalls += 1 + callinfo[5] - funcnameroot = callinfo[0].split('.')[0] + 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: - if usage > maxusage: - maxusage = usage - if callinfo[4] is not None: - doesyield = 1 - if usage > maxyieldusage: - maxyieldusage = usage - continue - totusage = usage + callinfo[2] - if totusage > maxusage: - maxusage = totusage - if callinfo[4] is not None: - doesyield = 1 - totyieldusage = usage + callinfo[4] - if totyieldusage > maxyieldusage: - maxyieldusage = totyieldusage - info[2] = maxusage - if doesyield: - info[4] = maxyieldusage - info[5] = totcalls + # 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][5], availfuncs[funcaddr][0], funcaddr) + 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) - if funcaddr not in availfuncs: + info = availfuncs.get(funcaddr) + if info is None: continue - calladdrs = [calls[1] for calls in availfuncs[funcaddr][6]] + calladdrs = [calls[1] for calls in info.called_funcs] del availfuncs[funcaddr] - out = out + orderfuncs(calladdrs, availfuncs) + [funcaddr] + out = out + orderfuncs(calladdrs, availfuncs) + [info] return out -# Update function info with a found "yield" point. -def noteYield(info, stackusage): - prevyield = info[3] - if prevyield is None or prevyield < stackusage: - info[3] = stackusage - -# Update function info with a found "call" point. -def noteCall(info, subfuncs, insnaddr, calladdr, stackusage): - if (calladdr, stackusage) in subfuncs: - # Already noted a nearly identical call - ignore this one. - return - info[6].append((insnaddr, calladdr, stackusage)) - subfuncs[(calladdr, stackusage)] = 1 - hex_s = r'[0-9a-f]+' re_func = re.compile(r'^(?P<funcaddr>' + hex_s + r') <(?P<func>.*)>:$') re_asm = re.compile( @@ -114,11 +113,12 @@ re_asm = re.compile( re_usestack = re.compile( r'^(push[f]?[lw])|(sub.* [$](?P<num>0x' + hex_s + r'),%esp)$') -def calc(): - # funcs[funcaddr] = [funcname, basicstackusage, maxstackusage - # , yieldusage, maxyieldusage, totalcalls - # , [(insnaddr, calladdr, stackusage), ...]] - funcs = {-1: ['<indirect>', 0, 0, None, None, 0, []]} +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 @@ -129,99 +129,93 @@ def calc(): if m is not None: # Found function funcaddr = int(m.group('funcaddr'), 16) - funcs[funcaddr] = cur = [m.group('func'), 0, None, None, None, 0, []] + funcs[funcaddr] = cur = function(funcaddr, m.group('func')) stackusage = 0 atstart = 1 - subfuncs = {} continue m = re_asm.match(line) - if m is not None: - 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[1] = stackusage - atstart = 0 - - insnaddr = m.group('insnaddr') - calladdr = m.group('calladdr') - if calladdr is None: - if insn.startswith('lcallw'): - noteCall(cur, subfuncs, insnaddr, -1, stackusage + 4) - noteYield(cur, stackusage + 4) - elif insn.startswith('int'): - noteCall(cur, subfuncs, insnaddr, -1, stackusage + 6) - noteYield(cur, stackusage + 6) - elif insn.startswith('sti'): - noteYield(cur, stackusage) - else: - # misc instruction - continue + 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: - # 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 - noteCall(cur, subfuncs, insnaddr, calladdr, 0) - elif insn.startswith('calll'): - noteCall(cur, subfuncs, insnaddr, calladdr, stackusage + 4) - elif insn.startswith('callw'): - noteCall(cur, subfuncs, insnaddr, calladdr, stackusage + 2) - else: - print("unknown call", ref) - noteCall(cur, subfuncs, insnaddr, calladdr, stackusage) - # Reset stack usage to preamble usage - stackusage = cur[1] - - #print("other", repr(line)) + print("unknown call", ref) + cur.noteCall(insnaddr, calladdr, stackusage) + # Reset stack usage to preamble usage + stackusage = cur.basic_stack_usage # Calculate maxstackusage - for funcaddr, info in funcs.items(): - if info[2] is not None: - continue - calcmaxstack(funcs, funcaddr) + for info in funcs.values(): + calcmaxstack(info, funcs) # Sort functions for output - funcaddrs = orderfuncs(funcs.keys(), funcs.copy()) + funcinfos = orderfuncs(funcs.keys(), funcs.copy()) # Show all functions print(OUTPUTDESC) - for funcaddr in funcaddrs: - name, basicusage, maxusage, yieldusage, maxyieldusage, count, calls = \ - funcs[funcaddr] - if maxusage == 0 and maxyieldusage is None: + for info in funcinfos: + if info.max_stack_usage == 0 and info.max_yield_usage < 0: continue yieldstr = "" - if maxyieldusage is not None: - yieldstr = ",%d" % maxyieldusage - print("\n%s[%d,%d%s]:" % (name, basicusage, maxusage, yieldstr)) - for insnaddr, calladdr, stackusage in calls: - callinfo = funcs.get(calladdr, ("<unknown>", 0, 0, 0, None)) + 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[4] is not None: - yieldstr = ",%d" % (stackusage + callinfo[4]) + if callinfo.max_yield_usage >= 0: + yieldstr = ",%d" % (stackusage + callinfo.max_yield_usage) print(" %04s:%-40s [%d+%d,%d%s]" % ( - insnaddr, callinfo[0], stackusage, callinfo[1] - , stackusage+callinfo[2], yieldstr)) - -def main(): - calc() + insnaddr, callinfo.funcname, stackusage + , callinfo.basic_stack_usage + , stackusage+callinfo.max_stack_usage, yieldstr)) if __name__ == '__main__': main() diff --git a/qemu/roms/seabios/scripts/kconfig/lxdialog/util.c b/qemu/roms/seabios/scripts/kconfig/lxdialog/util.c index f7abdeb92..2a0d182e8 100644 --- a/qemu/roms/seabios/scripts/kconfig/lxdialog/util.c +++ b/qemu/roms/seabios/scripts/kconfig/lxdialog/util.c @@ -376,7 +376,7 @@ void print_title(WINDOW *dialog, const char *title, int width) /* * Print a string of text in a window, automatically wrap around to the * next line if the string is too long to fit on one line. Newline - * characters '\n' are propperly processed. We start on a new line + * characters '\n' are properly processed. We start on a new line * if there is no room for at least 4 nonblanks following a double-space. */ void print_autowrap(WINDOW * win, const char *prompt, int width, int y, int x) diff --git a/qemu/roms/seabios/scripts/layoutrom.py b/qemu/roms/seabios/scripts/layoutrom.py index dd770fe49..b976fb056 100755 --- a/qemu/roms/seabios/scripts/layoutrom.py +++ b/qemu/roms/seabios/scripts/layoutrom.py @@ -161,6 +161,7 @@ def getSectionsPrefix(sections, prefix): # The sections (and associated information) to be placed in output rom class LayoutInfo: sections = None + config = None genreloc = None sec32init_start = sec32init_end = sec32init_align = None sec32low_start = sec32low_end = None @@ -172,6 +173,7 @@ class LayoutInfo: # Determine final memory addresses for sections def doLayout(sections, config, genreloc): li = LayoutInfo() + li.config = config li.sections = sections li.genreloc = genreloc # Determine 16bit positions @@ -399,6 +401,10 @@ def writeLinkerScripts(li, out16, out32seg, out32flat): filesections32flat = getSectionsFileid(li.sections, '32flat') out = outXRefs([], exportsyms=li.varlowsyms , forcedelta=li.final_sec32low_start-li.sec32low_start) + multiboot_header = "" + if li.config.get('CONFIG_MULTIBOOT'): + multiboot_header = "LONG(0x1BADB002) LONG(0) LONG(-0x1BADB002)" + sec32all_start -= 3 * 4 out += outXRefs(filesections32flat, exportsyms=[li.entrysym]) + """ _reloc_min_align = 0x%x ; zonefseg_start = 0x%x ; @@ -415,6 +421,7 @@ def writeLinkerScripts(li, out16, out32seg, out32flat): .text code32flat_start : { %s %s +%s code32flat_end = ABSOLUTE(.) ; } :text """ % (li.sec32init_align, @@ -428,6 +435,7 @@ def writeLinkerScripts(li, out16, out32seg, out32flat): li.sec32init_start, li.sec32init_end, sec32all_start, + multiboot_header, relocstr, outRelSections(li.sections, 'code32flat_start')) out = COMMONHEADER + out + COMMONTRAILER + """ |