objutils/ieee695.py
#!/usr/bin/env python
# -*- coding: utf-8 -*-
__version__ = "0.1.0"
__copyright__ = """
objutils - Object file library for Python.
(C) 2010-2020 by Christoph Schueler <github.com/Christoph2,
cpu12.gems@googlemail.com>
All Rights Reserved
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
"""
from datetime import datetime
from functools import reduce
import os
from objutils.logger import Logger
"""
$00-$7F Simple number in the range 0 to 127, or 7-bit ASCII string with length 0 to 127.
$80-$84 Number larger than 127 or negative. 0 to 4 bytes follow. $80 is used as a place
holder and means the value was not provided.
$85-$88 Unsigned numbers between 2ˆˆ32 and (2ˆˆ64)-1, or negative. Not supported in all installations.
$89-$8F Unused.
$90-$9F Reserved functions and operators.
$A0-$BF Function values (arithmetic and logical).
$C0-$DA Variable letters (null, A-Z).
$DB-$DD Unused.
$DE-$DF Extension length. If DE, the next byte is the length of an 8-bit string between 0 and 255
bytes long. If DF, the next two bytes in high- order/low-order format are the length of
an 8-bit string between 0 and 65535 bytes long.
$E0-$FA Record headers.
$FB Define Context.
$FC-$FF Unused.
Table 2-1. Initial Bytes of IEEE Elements
"""
SMALL_NUMBER = 0x7F
SHORT_STRING = 0x7F
COMMAND_CODE = 0xE0
"""
ASP = 0xD0 # Current Section PC.
ASS = 0xD3 # Section Size.
ASR = 0xD2 # Variable Values.
ASW = 0xD7 # Variable Values.
ASA = 0xC1 # Physical Region Size.
ASB = 0xC2 # Physical Region Base Address.
ASP = 0xC6 # Mau Size.
ASG = 0xC7 # Execution Starting Address.
ASI = 0xC9 # Variable Values.
ASL = 0xCC # Section Base Address.
ASM = 0xCD # M-Value.
ASN = 0xCE
"""
F1 = 0xF1
E2 = 0xE2
##
## Header Part.
##
MB = 0xE0 # Module Beginning.
AD = 0xEC # Address Descriptor.
ASW0 = 0x00 # Assign Pointer to AD Extension Part.
ASW1 = 0x01 # Assign Pointer to Environment Part.
ASW2 = 0x02 # Assign Pointer to Section Part.
ASW3 = 0x03 # Assign Pointer to External Part.
ASW4 = 0x04 # Assign Pointer to Debug Part.
ASW5 = 0x05 # Assign Pointer to Data Part.
ASW6 = 0x06 # Assign Pointer to Trailer Part.
ASW7 = 0x07 # Assign Pointer to Module End.
ASWAssignment = {
ASW0: "AD Extension",
ASW1: "Environment",
ASW2: "Section",
ASW3: "External",
ASW4: "Debug",
ASW5: "Data",
ASW6: "Trailer",
ASW7: "Module End",
}
##
## AD Extension Part (ASW0).
##
NN = 0xF0 # Variable Attributes
ATN = 0xCE # Variable Attributes - F1
ASN = 0xCE # Variable Values - E2
##
## Environment Part (ASW1).
##
## Same as ASW0
"""
NN = 0xF0 # Variable Attributes
ATN = 0xF1CE # Variable Attributes
ASN = 0xE2CE # Variable Values
"""
##
## Section Definition Part (ASW2).
##
ST = 0xE6 # Section Type.
SA = 0xE7 # Section Alignment.
ASS = 0xD3 # Section Size. - E2
ASL = 0xCC # Section Base Address. - E2
ASR = 0xD2 # Variable Values. - E2
NC = 0xFB # Define Context.
ASA = 0xC1 # Physical Region Size. - E2
ASB = 0xC2 # Physical Region Base Address. - E2
ASP = 0xC6 # Mau Size. - E2
ASF = 0xC6 # Mau Size. - E2
ASM = 0xCD # M-Value. - E2
##
## External Part (ASW3).
##
NI = 0xE8 # Public (External) Symbol.
ATI = 0xC9 # Variable Attribute. - F1
ASI = 0xC9 # Variable Values. - E2
NX = 0xE9 # External Reference Name.
ATX = 0xD8 # External Reference Relocation Information. - F1
WX = 0xF4 # Weak External Reference.
##
## Debug Information Definition Part (ASW4).
##
BB = 0xF8 # Declare Block Beginning.
NN = 0xF0 # Declare Type Name, file name, line numbers, function name, variable names, etc.
TY = 0xF2 # Define Type Characteristics.
ASN = 0xCE # Variable Values. - E2
ASR = 0xD2 # Variable Values. - E2
BE = 0xF9 # Declare Block End.
##
## Data Part (ASW5).
##
SB = 0xE5 # Current Section.
ASP = 0xD0 # Current Section PC. - E2
LD = 0xED # Load Constant MAUs.
IR = 0xE3 # Initialize Relocation Base.
RE = 0xF7 # Repeat Data.
ASW = 0xD7 # Variable Values. - E2
LR = 0xE4 # Load With Relocation.
LT = 0xFA # Load With Translation.
##
## Trailer Part (ASW6).
##
ASG = 0xC7 # Execution Starting Address. - E2
##
## Module End (ASW7).
##
ME = 0xE1 # Module End.
##Checksum Records - 0xEE, 0xEF
##
## Blocktypes.
##
BB1 = 1 # Type definitions local to a module.
BB2 = 2 # Type definitions global to all modules.
BB3 = 3 # A module. A non-separable unit of code, usually the result
# of a single compilation, i.e. a Modula-2 module or an Ada package.
BB4 = 4 # A global subprogram.
BB5 = 5 # A source file line number block.
BB6 = 6 # A local (static) subprogram.
BB10 = 10 # An assembler debugging information block.
BB11 = 11 # The module portion of a section.
BB20 = 20 # Library - contains a list of global symbols used in a module.
##
## Object Format Types.
##
ObjectFormatTypes = {
1: "Absolute (not relinkable)",
2: "Relocatable",
3: "Loadable",
4: "Library",
}
CaseSensitivity = {1: "case insensitiv", 2: "case sensitiv"}
MemoryModel = {
0: "tiny", # Code and data are in the same single 64K segment/page.
1: "small", # Code and data each have a single 64K segment/page.
2: "medium", # Data has a single 64K segment/page, while code has multiple 64K segments/pages.
3: "compact", # Data has multiple 64K segments/pages, while code has a single 64K segment/page.
4: "large", # Both data and code have multiple 64K segments/pages.
5: "big", # Code has multiple 64K segments/pages, while there is a common "near" data area with
# far data areas available; normaly data and stack are together
6: "huge", # All large arrays and structures are in their own section so that
# addressing involves computations (you can have arrays and structures bigger than 64K)
}
FunctionsAndOperators = {
0xA0: "@F",
0xB0: "@AND",
0xA1: "@T",
0xB1: "@OR",
0xA2: "@ABS",
0xB2: "@XOR",
0xA3: "@NEG",
0xB3: "@EXT",
0xA4: "@NOT",
0xB4: "@INS",
0xA5: "+",
0xB5: "@ERR",
0xA6: "-",
0xB6: "@IF",
0xA7: "/",
0xB7: "@ELSE",
0xA8: "*",
0xB8: "@END",
0xA9: "@MAX",
0xB9: "@ESCAPE",
0xAA: "@MIN",
0xBA: "[",
0xAB: "@MOD",
0xBB: "]",
0xAC: "<",
0xBC: "{",
0xAD: ">",
0xBD: "}",
0xAE: "=",
0xBE: "(",
0xAF: "!=",
0xBF: ")",
}
ESCAPEFunctionEncodings = {
0: "reserved",
1: "@ISDEF",
2: "@TRANS",
3: "@SPLIT",
4: "@INBLOCK",
5: "@CALL_OPT",
}
class InvalidFormatError(Exception):
pass
class Info(object):
pass
class DebugInformation(object):
def __init__(self):
self.children = []
def add(self, child):
self.children.append(child)
class Section(object):
def __init__(self, sectionType, sectionName, parentSectionIndex):
self.sectionType = sectionType
self.sectionName = sectionName
self.parentSectionIndex = parentSectionIndex
self.regionSize = []
self.physicalAddress = []
self.sectionOffset = []
self.mauSize = 0
self.mValue = None
self.segments = {}
class Reader(object):
def __init__(self, inFile):
if not hasattr(inFile, "read"):
raise TypeError("Need a file-like object.")
self.logger = Logger("IEEE695")
self.inFile = inFile
self.info = Info()
self.info.ASWs = {}
self.fpos = 0
self.blockType = []
self.finished = False
self.symbols = {}
self.externalSymbols = {}
self.sections = {}
self.nnRecords = {}
self.contexts = {}
diRoot = DebugInformation()
diRoot.parent = None
diRoot.name = "ROOT"
self.debugInformation = [diRoot]
self.diParents = [diRoot]
self.currentSection = None
self.currentSectionIndex = None
####
self._nb = 0
self.dbCollection = bytearray()
while not self.finished:
cc = self.readByte(self.fpos)
if cc == MB:
self.onModuleBegin()
elif cc == AD:
self.onAD()
elif cc == E2:
self.onE2()
elif cc == NX:
self.onNX()
elif cc == WX:
self.onWX()
elif cc == NN:
self.onNN()
elif cc == F1:
self.onF1()
elif cc == ST:
self.onST()
elif cc == NC:
self.onNC()
elif cc == SA:
self.onSA()
elif cc == NI:
self.onNI()
elif cc == BB:
self.onBB()
elif cc == BE:
self.onBE()
elif cc == TY:
self.onTY()
elif cc == SB:
self.onSB()
elif cc == LD:
self.onLD()
elif cc == ME:
self.onME()
else:
raise NotImplementedError("0x{0:02X}".format(cc))
def setCurrentSectionIndex(self, index):
self.currentSectionIndex = index
def checkSectionIndex(self, index):
if self.currentSectionIndex is None:
print("No current Section Index.")
elif self.currentSectionIndex != index:
print
print("Invalid Section Index.")
def readByte(self, offset):
"Read 8bit quantity"
self.inFile.seek(offset, os.SEEK_SET)
result = ord(self.inFile.read(1))
self.fpos = self.inFile.tell()
return result
def readWord(self, offset):
"Read 16bit quantity"
self.inFile.seek(offset, os.SEEK_SET)
h = ord(self.inFile.read(1))
l = ord(self.inFile.read(1))
self.fpos = self.inFile.tell()
return h << 8 | l
def readNumber(self, offset):
"Read number of abitrary length"
self.inFile.seek(offset, os.SEEK_SET)
typecode = self.readByte(offset)
if typecode <= SMALL_NUMBER:
# length: [0..127]
result = typecode
elif 0x80 <= typecode <= 0x88:
# length (in bytes) [0..8]
length = typecode & ~0x80
data = self.inFile.read(length)
self.fpos = self.inFile.tell()
result = reduce(lambda x, y: (x * 256) + ord(y), data, 0)
return result
def readString(self, offset):
typecode = self.readByte(offset)
if typecode <= SHORT_STRING:
# length: [0..127]
length = typecode
elif typecode == 0xDE:
# length: [0..255]
length = self.readByte(offset + 1)
elif typecode == 0xDF:
# length: [0..65535]
length = self.readWord(offset + 1)
else:
raise TypeError("Invalid typecode [{0:02x}].".format(typecode))
result = self.inFile.read(length)
self.fpos = self.inFile.tell()
return result
def readCharacter(self, offset):
result = chr(self.readByte(offset) - 0x80)
if ord(result) > ord("Z"):
result = None
return result
def checkOptional(self, offset, isString=False):
"Read and maybe putback"
cc = self.readByte(offset)
if cc >= COMMAND_CODE:
self.inFile.seek(offset, os.SEEK_SET) # Put back.
self.fpos = offset
return None
if isString == True:
self.inFile.seek(offset, os.SEEK_SET) # Put back.
self.fpos = offset
return self.readString(offset)
else:
if 0xC0 <= cc <= 0xDA:
result = chr(cc - 0x80)
if ord(result) > ord("Z"):
result = None
else:
return self.readNumber(offset)
def symbolByName(self, name):
pass
def symbolByIndex(self, index):
pass
################################
################################
################################
def onModuleBegin(self):
"{$E0}{Id1}{Id2}"
self.info.processor = self.readString(self.fpos)
self.info.module = self.readString(self.fpos)
self.logger.debug(
"PROCESSOR: '{0!s}' MODULE: '{1!s}'.".format(
self.info.processor, self.info.module
)
)
def onAD(self):
"$EC}{n1}{n2}[a]"
self.info.numberOfBits = self.readNumber(self.fpos)
self.info.numberOfMAUs = self.readNumber(self.fpos)
self.info.adressWidth = self.info.numberOfBits * self.info.numberOfMAUs
self.info.byteOrder = self.checkOptional(self.fpos)
def onE2(self):
"{$E2}{$D7}{0x}{n}"
"""
ASR = 0xD2 # Variable Values.
"""
discr = self.readByte(self.fpos)
if discr == ASW:
addr = self.readByte(self.fpos)
byteOffset = self.readNumber(self.fpos)
self.info.ASWs[addr] = (ASWAssignment[addr], byteOffset)
elif discr == ASS:
sectionIndex = self.readNumber(self.fpos)
self.checkSectionIndex(sectionIndex)
self.sections[sectionIndex].sectionSize = self.readNumber(self.fpos)
self.logger.debug(
"Section-Size: 0x{0:04x}".format(
self.sections[sectionIndex].sectionSize
)
)
elif discr == ASA:
sectionIndex = self.readNumber(self.fpos)
self.checkSectionIndex(sectionIndex)
self.sections[sectionIndex].regionSize.append(self.readNumber(self.fpos))
elif discr == ASB:
sectionIndex = self.readNumber(self.fpos)
self.checkSectionIndex(sectionIndex)
self.sections[sectionIndex].physicalAddress.append(
self.readNumber(self.fpos)
)
elif discr == ASR:
sectionIndex = self.readNumber(self.fpos)
self.checkSectionIndex(sectionIndex)
self.sections[sectionIndex].sectionOffset.append(self.readNumber(self.fpos))
elif discr == ASF:
sectionIndex = self.readNumber(self.fpos)
self.checkSectionIndex(sectionIndex)
self.sections[sectionIndex].mauSize = self.readNumber(self.fpos)
self.logger.debug(
"MAU-Size: 0x{0:04x}".format(self.sections[sectionIndex].mauSize)
)
elif discr == ASL:
sectionIndex = self.readNumber(self.fpos)
self.checkSectionIndex(sectionIndex)
self.sections[sectionIndex].sectionBaseAddr = self.readNumber(self.fpos)
self.logger.debug(
"Section-BaseAddr: 0x{0:04x}".format(
self.sections[sectionIndex].sectionBaseAddr
)
)
elif discr == ASM:
sectionIndex = self.readNumber(self.fpos)
self.checkSectionIndex(sectionIndex)
self.sections[sectionIndex].mValue = self.readNumber(self.fpos)
elif discr == ASI:
# There may be more than one ASI/ATI record pair for a single
# name since constants defined in SETs and #defines my be redefined repeatedly.
symbolIndex = self.readNumber(self.fpos)
expr = self.readNumber(self.fpos)
self.symbols[symbolIndex].expr = expr
elif discr == ASN:
symbolNameIndex = self.readNumber(self.fpos)
symbolTypeIndex = self.readNumber(self.fpos)
elif discr == ASP:
sectionIndex = self.readNumber(self.fpos) # ? check sec-Index!!?
newValue = self.readNumber(self.fpos)
elif discr == ASG:
delim = self.readByte(self.fpos)
if delim != 0xBE:
pass # todo: FormatError!!!
executionStartingAddr = self.readNumber(self.fpos)
self.logger.debug(
"STARTING-ADDRESS: 0x{0:04X}".format(executionStartingAddr)
)
delim = self.readByte(self.fpos)
if delim != 0xBF:
pass # todo: FormatError!!!
self.info.executionStartingAddr = executionStartingAddr
else:
raise NotImplementedError(hex(discr))
def onNN(self):
"{$F0}{n1}{Id}"
symbolType = self.readNumber(self.fpos)
symbolName = self.readString(self.fpos)
self.nnRecords[symbolType] = Info()
self.nnRecords[symbolType].name = symbolName
self.nnRecords[symbolType].atn = {}
# self.logger.debug("Symbol-Type: 0x%02x Name: '%s'" % (symbolType, symbolName))
def onNX(self):
"{$E9}{n1}{Id}"
externalReferenceIndex = self.readNumber(self.fpos)
symbolName = self.readString(self.fpos)
self.externalSymbols[externalReferenceIndex] = Info()
self.externalSymbols[externalReferenceIndex].symbolName = symbolName
def onWX(self):
"{$F4}{n1}{n2}{n3}"
externalReferenceIndex = self.readNumber(self.fpos)
defaultSize = self.readNumber(self.fpos)
defaultValue = self.readNumber(self.fpos)
self.externalSymbols[externalReferenceIndex].defaultSize = defaultSize
self.externalSymbols[externalReferenceIndex].defaultValue = defaultValue
def onF1(self):
"""
ATI = 0xF1C9 # Variable Attribute.
ATX = 0xF1D8 # External Reference Relocation Information.
ATN = 0xF1CE # Variable Attributes.
"""
discr = self.readByte(self.fpos)
if discr == ATI:
numberOfElements = 0
symbolNameIndex = self.readNumber(self.fpos)
symbolTypeIndex = self.readNumber(self.fpos)
attrDef = self.readNumber(self.fpos)
if attrDef == 8:
pass
elif attrDef == 16:
symbolClass = self.readNumber(self.fpos)
publicLocalIndicator = self.checkOptional(self.fpos)
numericValue = self.checkOptional(self.fpos)
stringValue = self.checkOptional(self.fpos)
self.symbols[symbolNameIndex].symbolClass = symbolClass
self.symbols[
symbolNameIndex
].publicLocalIndicator = publicLocalIndicator
self.symbols[symbolNameIndex].numericValue = numericValue
self.symbols[symbolNameIndex].stringValue = stringValue
elif attrDef == 19:
pass
else:
pass # todo: FormatError!!!
## n4 =self.readNumber(self.fpos) # If n2 is non-zero, number of elements in the symbol type specified in n2
if symbolTypeIndex != 0:
numberOfElements = self.readNumber(self.fpos)
self.symbols[symbolNameIndex].symbolTypeIndex = symbolTypeIndex
self.symbols[symbolNameIndex].numberOfElements = numberOfElements
self.symbols[symbolNameIndex].attrDef = attrDef
elif discr == ATX:
externalReferenceIndex = self.readNumber(self.fpos)
typeIndex = self.readNumber(self.fpos)
sectionIndex = self.readNumber(self.fpos)
shortExternalFlag = self.readNumber(self.fpos)
self.externalSymbols[externalReferenceIndex].typeIndex = typeIndex
self.externalSymbols[externalReferenceIndex].sectionIndex = sectionIndex
self.externalSymbols[
externalReferenceIndex
].shortExternalFlag = shortExternalFlag
elif discr == ATN: # todo: onATN
symbolNameIndex = self.readNumber(self.fpos)
symbolTypeIndex = self.readNumber(self.fpos)
attrDef = self.readNumber(self.fpos)
if attrDef == 1:
stackOffset = self.readNumber(self.fpos)
elif attrDef == 2:
registerIndex = self.readNumber(self.fpos)
elif attrDef == 3:
pass
# elif attrDef == 4:
# pass
elif attrDef == 7:
lineNumber = self.readNumber(self.fpos)
columnNumber = self.readNumber(self.fpos)
res1 = self.checkOptional(self.fpos)
res2 = self.checkOptional(self.fpos)
elif attrDef == 8:
pass
elif attrDef == 9:
absoluteProgramCounterOffset = self.readNumber(self.fpos)
##if symbolNameIndex == 0:
## registerResourceIndex = self.readByte(self.fpos)
elif attrDef == 10:
registerIndex = self.readNumber(self.fpos)
frameOffset = self.readNumber(self.fpos)
# elif attrDef == 11:
# pass
elif attrDef == 19:
numberOfElements = self.readNumber(self.fpos)
localGlobal = self.checkOptional(self.fpos)
elif attrDef == 37:
self.info.objectFormatVersionNumber = self.readNumber(self.fpos)
self.info.objectFormatRevisionLevel = self.readNumber(self.fpos)
elif attrDef == 38:
self.info.objectFormatType = ObjectFormatTypes[
self.readNumber(self.fpos)
]
elif attrDef == 39:
self.info.symbolCaseSensitivity = CaseSensitivity[
self.readNumber(self.fpos)
]
elif attrDef == 40:
self.info.memoryModel = MemoryModel[self.readNumber(self.fpos)]
elif attrDef == 50:
year = self.readNumber(self.fpos)
month = self.readNumber(self.fpos)
day = self.readNumber(self.fpos)
hour = self.readNumber(self.fpos)
minute = self.readNumber(self.fpos)
second = self.readNumber(self.fpos)
self.info.creationDate = datetime(
year, month, day, hour, minute, second
)
elif attrDef == 51:
self.info.commandLine = self.readString(self.fpos)
elif attrDef == 52:
self.info.executionStatus = self.readNumber(self.fpos)
elif attrDef == 53:
self.info.hostEnvironment = self.readNumber(self.fpos)
elif attrDef == 54:
tool = self.readNumber(self.fpos)
version = self.readNumber(self.fpos)
revision = self.readNumber(self.fpos)
revisionLevel = self.checkOptional(
self.fpos
) # single IEEE-695 letter in the range $C1-$DA
elif attrDef == 55:
self.info.comments = self.readString(self.fpos)
elif attrDef == 64:
typeIdent = self.readNumber(self.fpos)
addATN = self.readNumber(self.fpos)
elif attrDef == 65:
miscString = self.readString(self.fpos)
else:
raise NotImplementedError("Invalid ATN-Attr: 0x{0:02x}".format(attrDef))
# todo: FormatError
else:
raise NotImplementedError(hex(discr))
# todo: FormatError
def onST(self):
"${E6}{n1}{l}[Id][n2][n3][n4]"
sectionIndex = self.readByte(self.fpos)
self.setCurrentSectionIndex(sectionIndex)
f = self.readCharacter(self.fpos)
if f == "A":
s, t = self.readCharacter(self.fpos), self.readCharacter(self.fpos)
sectionType = f + s + t
elif f == "B":
pass
elif f == "C":
pass
elif f == "E":
pass # todo: 'EA' / 'EZ' !!!
elif f == "M":
pass
elif f == "T":
pass
# todo: 'ZC' / 'ZM'.
else:
raise NotImplementedError("SEG-TYPE: {0!s}".format(f))
sectionName = self.readString(self.fpos)
parentSectionIndex = self.checkOptional(self.fpos)
if f == "T":
brotherSectionIndex = self.readNumber(self.fpos)
if f in ("B", "T"):
contextIndex = self.readNumber(self.fpos)
self.sections[sectionIndex] = Section(
sectionType, sectionName, parentSectionIndex
)
self.logger.debug("SECTION [{0!s}:{1!s}]".format(sectionType, sectionName))
# SA, ASA, ASB, ASF, ASL, ASM, ASR, and ASS records must appear after the ST record they refer to.
"""
ASP absolute code
ASR absolute ROM data
ASD absolute data
CP code
CR ROM data
CD data
EAP common absolute code
EAR common absolute ROM data
EAD common absolute data
ZCP short code
ZCR short ROM data
ZCD short data
"""
def onNC(self):
"{$FB}{n1}{Id}"
contextIndex = self.readNumber(self.fpos)
contextName = self.readString(self.fpos)
self.contexts[contextIndex] = contextName
def onSA(self):
"{$E7}{n1}[n2][n3]"
sectionIndex = self.readByte(self.fpos)
self.checkSectionIndex(sectionIndex)
boundaryAlignmentDivisor = self.checkOptional(self.fpos)
self.sections[sectionIndex].boundaryAlignment = 2**boundaryAlignmentDivisor
self.sections[sectionIndex].pageSize = self.checkOptional(self.fpos)
def onNI(self):
"{$E8}{n}{Id}"
nameIndex = self.readNumber(self.fpos) # must be > 31, 0 - 31 reserved.
symbolName = self.readString(self.fpos)
info = Info()
info.nameIndex = nameIndex
info.symbolName = symbolName
self.symbols[nameIndex] = info
self.logger.debug("SYMBOL: {0!s}".format(symbolName)) # followed by ASI.
def onBB(self):
blockType = self.readByte(self.fpos)
blockSize = self.readNumber(self.fpos)
info = DebugInformation()
info.parent = self.diParents[-1]
info.blockType = blockType
info.blockSize = blockSize
if blockSize == 0:
pass
if blockType == BB1:
self.blockType.append(1)
module_name = self.readString(self.fpos)
info.module_name = module_name
info.name = "BB1"
self.logger.debug("MODULE-NAME: {0!s}".format(module_name))
elif blockType == BB2:
self.blockType.append(2)
zeroLengthName = self.readString(self.fpos)
info.zeroLengthName = zeroLengthName
info.name = "BB2"
elif blockType == BB3:
self.blockType.append(3)
module_name = self.readString(self.fpos)
info.module_name = module_name
info.name = "BB3"
elif blockType == BB4:
self.blockType.append(4)
functionName = self.readString(self.fpos)
stackSpaceRequired = self.readNumber(self.fpos)
typeIndexOfReturnValue = self.readNumber(self.fpos)
offsetExpr = self.readNumber(self.fpos)
info.functionName = functionName
info.stackSpaceRequired = stackSpaceRequired
info.typeIndexOfReturnValue = typeIndexOfReturnValue
info.offsetExpr = offsetExpr
info.name = "BB4"
elif blockType == BB5:
self.blockType.append(5)
sourceFilename = self.readString(self.fpos)
year = self.checkOptional(self.fpos) # todo: factor-out (namedtuple)!!!
month = self.checkOptional(self.fpos)
day = self.checkOptional(self.fpos)
hour = self.checkOptional(self.fpos)
minute = self.checkOptional(self.fpos)
second = self.checkOptional(self.fpos)
info.sourceFilename = sourceFilename
info.year = year
info.month = month
info.day = day
info.hour = hour
info.minute = minute
info.second = second
info.name = "BB5"
elif blockType == BB6:
self.blockType.append(6)
functionName = self.readString(self.fpos)
stackRequired = self.readNumber(self.fpos)
typeIndexForReturnValue = self.readNumber(self.fpos)
offsetExpr = self.readNumber(self.fpos)
info.functionName = functionName
info.stackRequired = stackRequired
info.typeIndexForReturnValue = typeIndexForReturnValue
info.offsetExpr = offsetExpr
info.name = "BB6"
elif blockType == BB10:
self.blockType.append(10)
module_name = self.readString(self.fpos)
objFileName = self.readString(self.fpos)
toolType = self.readNumber(self.fpos)
versionRevision = self.checkOptional(self.fpos, isString=True)
year = self.checkOptional(self.fpos)
month = self.checkOptional(self.fpos)
day = self.checkOptional(self.fpos)
hour = self.checkOptional(self.fpos)
minute = self.checkOptional(self.fpos)
second = self.checkOptional(self.fpos)
info.module_name = module_name
info.objFileName = objFileName
info.toolType = toolType
info.versionRevision = versionRevision
info.year = year
info.month = month
info.day = day
info.hour = hour
info.minute = minute
info.second = second
info.name = "BB10"
elif blockType == BB11:
self.blockType.append(11)
zeroLengthName = self.readString(self.fpos)
sectionType = self.readNumber(self.fpos)
sectionIndex = self.readNumber(self.fpos)
offsetExpr = self.readNumber(self.fpos)
dummy = self.readByte(self.fpos) # $90 - Comma operator!!!
sectionMapping = self.readNumber(self.fpos)
info.zeroLengthName = zeroLengthName
info.sectionType = sectionType
info.sectionIndex = sectionIndex
info.offsetExpr = offsetExpr
info.dummy = dummy
info.sectionMapping = sectionMapping
info.name = "BB11"
elif blockType == BB20:
self.blockType.append(20)
raise NotImplementedError("BB20")
parent = self.diParents[-1]
parent.add(info)
self.diParents.append(info)
# self.logger.debug(" " * len(self.diParents), "BB{0:d}".format(blockType))
def onBE(self):
blockType = self.blockType.pop()
self.diParents.pop()
if blockType in (4, 6):
functionEndAddr = self.readNumber(self.fpos)
elif blockType == 11:
moduleSectionSize = self.checkOptional(self.fpos)
def onTY(self):
""""""
typeIndex = self.readNumber(self.fpos)
if self.readByte(self.fpos) != 0xCE:
pass # todo: raise FormatError!!
localNameIndex = self.readNumber(self.fpos)
values = []
while True:
value = self.checkOptional(self.fpos)
if value is None:
break
else:
values.append(value)
def onSB(self):
"{$E5}{n1}"
sectionIndex = self.readNumber(self.fpos)
sec = self.sections[sectionIndex]
self.logger.debug(
"Data for section: '{0!s}'. {1:d} bytes of data to follow.".format(
sec.sectionName, sec.sectionSize
)
)
def onLD(self):
"{$ED}{n1}{...}"
numberOfMAUs = self.readNumber(self.fpos)
data = self.inFile.read((numberOfMAUs * self.info.numberOfBits) / 8)
self.logger.debug("reading {0:d} bytes".format(len(data)))
# SB ASP LD
self._nb += len(data)
self.dbCollection.extend(data)
self.fpos = self.inFile.tell()
def onME(self):
"Module End Record Type"
self.finished = True
self.logger.debug("{0:d} Data-Bytes.".format(self._nb))
## $C0-$DA Variable letters (null, A-Z).
## Information-Variables: s. 3
"""
Number Format:
--------------
• If the value is between 0-127 decimal, the number is $0-$7F.
• If the value is greater than 127 decimal, then the number must be defined by 1 byte of count with the high
order bit set ($80) followed by the indicated number of bytes of numeric data with the most significant byte
first. The range for the count is usually 0-4 (i.e. $80-$84) and can be 0-8 on some installations. This form is
also valid for numbers in the range 0-127.
Example: $7FFF is encoded as {$82}{$7F}{$FF} (3 bytes). 0 can be encoded as {$00} or {$81}{$00}, 2ˆˆ32
can be encoded as {$85}{01}{00}{00}{00}{00}, etc.
• Omitted optional fields in records may be represented by a byte count of zero.
Example: {$80}
Negative numbers have these characteristics:
• Numbers use $80-$88.
• All readers must handle $80-$84.
• Some processors can use $85 through $88 (see the appendix for your processor).
• Numbers are construed as unsigned except where indicated as signed.
• Signed numbers use signed complement notation; negative numbers must set highest bit of largest
representable number (e.g., {$84}{$FF}{$FF}{$FF}{$FF} is -1 for 32-bit and smaller processors).
"""