# udis86 - scripts/ud_optable.py (optable.xml parser) # # Copyright (c) 2009 Vivek Thampi # All rights reserved. # # Redistribution and use in source and binary forms, with or without modification, # are permitted provided that the following conditions are met: # # * Redistributions of source code must retain the above copyright notice, # this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright notice, # this list of conditions and the following disclaimer in the documentation # and/or other materials provided with the distribution. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR # ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON # ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. import os import sys from xml.dom import minidom class UdOptableXmlParser: def parseDef( self, node ): ven = '' pfx = [] opc = [] opr = [] for def_node in node.childNodes: if not def_node.localName: continue if def_node.localName == 'pfx': pfx = def_node.firstChild.data.split(); elif def_node.localName == 'opc': opc = def_node.firstChild.data.split(); elif def_node.localName == 'opr': opr = def_node.firstChild.data.split(); elif def_node.localName == 'mode': pfx.extend( def_node.firstChild.data.split() ); elif def_node.localName == 'syn': pfx.extend( def_node.firstChild.data.split() ); elif def_node.localName == 'vendor': ven = ( def_node.firstChild.data ); else: print("warning: invalid node - %s" % def_node.localName) continue return ( pfx, opc, opr, ven ) def parse( self, xml, fn ): xmlDoc = minidom.parse( xml ) self.TlNode = xmlDoc.firstChild while self.TlNode and self.TlNode.localName != "x86optable": self.TlNode = self.TlNode.nextSibling for insnNode in self.TlNode.childNodes: if not insnNode.localName: continue if insnNode.localName != "instruction": print("warning: invalid insn node - %s" % insnNode.localName) continue mnemonic = insnNode.getElementsByTagName( 'mnemonic' )[ 0 ].firstChild.data vendor = '' for node in insnNode.childNodes: if node.localName == 'vendor': vendor = node.firstChild.data elif node.localName == 'def': ( prefixes, opcodes, operands, local_vendor ) = \ self.parseDef( node ) if ( len( local_vendor ) ): vendor = local_vendor # callback fn( prefixes, mnemonic, opcodes, operands, vendor ) def printFn( pfx, mnm, opc, opr, ven ): print('def: '), if len( pfx ): print(' '.join( pfx )), print("%s %s %s %s" % \ ( mnm, ' '.join( opc ), ' '.join( opr ), ven )) def parse( xml, callback ): parser = UdOptableXmlParser() parser.parse( xml, callback ) def main(): parser = UdOptableXmlParser() parser.parse( sys.argv[ 1 ], printFn ) if __name__ == "__main__": main()