]> sigrok.org Git - sigrok-util.git/blobdiff - firmware/saleae-logic16/sigrok-fwextract-saleae-logic16
sigrok-fwextract-saleae-logic16: Support vendor SW ver 1.1.18
[sigrok-util.git] / firmware / saleae-logic16 / sigrok-fwextract-saleae-logic16
index 45f98277c879a46d3d02fa1094a9551e64b6ab26..a1213c8674c9e4676f740b1f50ca2e30f1c0ab2c 100755 (executable)
@@ -24,7 +24,7 @@ import parseelf
 
 class searcher:
 
-    def reset(this, offs = 0):
+    def reset(this, offs=0):
         if offs < 0 or offs > this.length:
             raise Exception('Reset past end of section')
         this.address = this.baseaddr + offs
@@ -47,6 +47,15 @@ class searcher:
             raise Exception('Needle not found in haystack')
         this.skip(pos - this.offset)
 
+    def look_for_either(this, needle1, needle2):
+        pos1 = this.data.find(needle1, this.offset)
+        pos2 = this.data.find(needle2, this.offset)
+        if pos1 < 0 and pos2 < 0:
+            raise Exception('Needle not found in haystack')
+        if pos1 < 0 or pos2 < pos1:
+            pos1 = pos2
+        this.skip(pos1 - this.offset)
+
     def __init__(this, data, addr):
         this.data = data
         this.baseaddr = addr
@@ -69,7 +78,7 @@ def search_plt_64(plt, addr):
 
 def find_hex_file_lines_constructor_32(text, hex_file_lines_got, got_plt):
     while True:
-        text.look_for(b'\x8b\xbb')             # mov offs32(%ebx),%edi
+        text.look_for_either(b'\x8b\xbb', b'\x8b\xb3') # mov offs32(%ebx),{%edi,%esi}
         offs = struct.unpack('<i', text.peek(4, 2))[0]
         if got_plt + offs == hex_file_lines_got:
             text.skip(6)
@@ -86,15 +95,18 @@ def find_hex_file_lines_constructor_64(text, hex_file_lines_got):
         text.skip(3)
 
 def parse_hex_file_lines_constructor_32(text, basic_string_plt, got_plt, lines):
+    text.skip(-5)
+    esi = (text.peek(1) == b'\xb3')
+    text.skip(5)
     cnt = len(lines)
     while cnt > 0:
         if text.peek(2) == b'\x8d\x45':                # lea offs8(%ebp),%eax
             text.skip(3)
         elif text.peek(2) == b'\x8d\x85':      # lea offs32(%ebp),%eax
             text.skip(6)
-        if text.peek(1) == b'\xbe':            # mov $imm32,%esi
+        if text.peek(1) == (b'\xbf' if esi else b'\xbe'):      # mov $imm32,%esi
             text.skip(5)
-        elif text.peek(2) == b'\x31\xf6':      # xor %esi,%esi
+        elif text.peek(2) == (b'\x31\xff' if esi else b'\x31\xf6'):    # xor %esi,%esi
             text.skip(2)
         if text.peek(4) == b'\x89\x44\x24\x08':        # mov %eax,0x8(%esp)
             text.skip(4)
@@ -103,21 +115,21 @@ def parse_hex_file_lines_constructor_32(text, basic_string_plt, got_plt, lines):
             text.skip(6)
             straddr += got_plt
         else:
-            raise Exception('Expected lea offs32(%ebx),%eax @ '+
+            raise Exception('Expected lea offs32(%ebx),%eax @ ' +
                             ('0x%x' % text.address))
         if text.peek(4) == b'\x89\x44\x24\x04':        # mov %eax,0x4(%esp)
             text.skip(4)
-        if text.peek(3) == b'\x89\x3c\x24':    # mov %edi,(%esp)
+        if text.peek(3) == (b'\x89\x34\x24' if esi else b'\x89\x3c\x24'):      # mov %edi,(%esp)
             offs = 0
             text.skip(3)
-        elif text.peek(2) == b'\x8d\x47':      # lea offs8(%edi),%eax
+        elif text.peek(2) == (b'\x8d\x46' if esi else b'\x8d\x47'):    # lea offs8(%edi),%eax
             offs = struct.unpack('<b', text.peek(1, 2))[0]
             text.skip(3)
-        elif text.peek(2) == b'\x8d\x87':      # lea offs32(%edi),%eax
+        elif text.peek(2) == (b'\x8d\x86' if esi else b'\x8d\x87'):    # lea offs32(%edi),%eax
             offs = struct.unpack('<i', text.peek(4, 2))[0]
             text.skip(6)
         else:
-            raise Exception('Expected lea offs(%edi),%eax @ '+
+            raise Exception('Expected lea offs(%e'+('s' if esi else 'd')+'i),%eax @ ' +
                             ('0x%x' % text.address))
         if offs < 0 or offs > (len(lines) << 2) or (offs & 3) != 0:
             raise Exception('Invalid offset %d' % offs)
@@ -130,10 +142,10 @@ def parse_hex_file_lines_constructor_32(text, basic_string_plt, got_plt, lines):
             offs = struct.unpack('<i', text.peek(4, 1))[0]
             text.skip(5)
             if text.address + offs != basic_string_plt:
-                raise Exception('Expected call ZNSsC1EPKcRKSaIcE@plt @ '+
+                raise Exception('Expected call ZNSsC1EPKcRKSaIcE@plt @ ' +
                                 ('0x%x' % text.address))
         else:
-            raise Exception('Expected call ZNSsC1EPKcRKSaIcE@plt @ '+
+            raise Exception('Expected call ZNSsC1EPKcRKSaIcE@plt @ ' +
                             ('0x%x' % text.address))
         if straddr == 0:
             raise Exception('NULL pointer stored to index %d' % index)
@@ -156,7 +168,7 @@ def parse_hex_file_lines_constructor_64(text, basic_string_plt, lines):
             text.skip(7)
             straddr += text.address
         else:
-            raise Exception('Expected lea offs(%rip),%rsi @ '+
+            raise Exception('Expected lea offs(%rip),%rsi @ ' +
                             ('0x%x' % text.address))
         if text.peek(3) == b'\x48\x89\xef':    # mov %rbp,%rdi
             offs = 0
@@ -168,8 +180,12 @@ def parse_hex_file_lines_constructor_64(text, basic_string_plt, lines):
             offs = struct.unpack('<i', text.peek(4, 3))[0]
             text.skip(7)
         else:
-            raise Exception('Expected lea offs(%rbp),%rdi @ '+
+            raise Exception('Expected lea offs(%rbp),%rdi @ ' +
                             ('0x%x' % text.address))
+        if text.peek(1) == b'\xbb':            # mov $imm32,%ebx
+            text.skip(5)
+        elif text.peek(2) == b'\x31\xdb':      # xor %ebx,%ebx
+            text.skip(2)
         if offs < 0 or offs > (len(lines) << 3) or (offs & 7) != 0:
             raise Exception('Invalid offset %d' % offs)
         index = offs >> 3
@@ -179,10 +195,10 @@ def parse_hex_file_lines_constructor_64(text, basic_string_plt, lines):
             offs = struct.unpack('<i', text.peek(4, 1))[0]
             text.skip(5)
             if text.address + offs != basic_string_plt:
-                raise Exception('Expected callq ZNSsC1EPKcRKSaIcE@plt @ '+
+                raise Exception('Expected callq ZNSsC1EPKcRKSaIcE@plt @ ' +
                                 ('0x%x' % text.address))
         else:
-            raise Exception('Expected callq ZNSsC1EPKcRKSaIcE@plt @ '+
+            raise Exception('Expected callq ZNSsC1EPKcRKSaIcE@plt @ ' +
                             ('0x%x' % text.address))
         if straddr == 0:
             raise Exception('NULL pointer stored to index %d' % index)
@@ -196,7 +212,7 @@ def find_reloc(elf, symname):
             for reloc in relocs['relocs']:
                 if reloc['r_sym'] == symnum:
                     return reloc
-    raise Exception('Unable to find a relocation against '+symname)
+    raise Exception('Unable to find a relocation against ' + symname)
 
 def ihex_to_binary(lines):
     chunks = {}
@@ -227,10 +243,10 @@ def ihex_to_binary(lines):
     return blob
 
 def extract_fx2_firmware(elf, symname, filename):
-    blob = elf.load_symbol(elf.dynsym[symname+'Count'])
+    blob = elf.load_symbol(elf.dynsym[symname + 'Count'])
     count = struct.unpack('<I', blob)[0]
     got_plt = elf.find_section('.got.plt')['sh_addr']
-    hex_file_lines_got = find_reloc(elf, symname)['r_offset'];
+    hex_file_lines_got = find_reloc(elf, symname)['r_offset']
     basic_string_got = find_reloc(elf, '_ZNSsC1EPKcRKSaIcE')['r_offset']
     pltsec = elf.find_section('.plt')
     plt = searcher(elf.read_section(pltsec), pltsec['sh_addr'])
@@ -251,7 +267,7 @@ def extract_fx2_firmware(elf, symname, filename):
                 find_hex_file_lines_constructor_32(text, hex_file_lines_got,
                                                    got_plt)
         except:
-            raise Exception('Unable to find constructor for '+symname)
+            raise Exception('Unable to find constructor for ' + symname)
         oldoffs = text.offset
         l = [0]*count
         try:
@@ -286,8 +302,8 @@ def extract_symbol(elf, symname, filename):
     print("saved %d bytes to %s" % (len(blob), filename))
 
 def extract_bitstream(elf, lv):
-    extract_symbol(elf, 'gLogic16Lv'+lv+'CompressedBitstream',
-                   'saleae-logic16-fpga-'+lv+'.bitstream')
+    extract_symbol(elf, 'gLogic16Lv' + lv + 'CompressedBitstream',
+                   'saleae-logic16-fpga-' + lv + '.bitstream')
 
 def usage():
     print("sigrok-fwextract-saleae-logic16 <programfile>")
@@ -311,4 +327,3 @@ try:
     extract_bitstream(elf, '33')
 except Exception as e:
     print("Error: %s" % str(e))
-