X-Git-Url: http://sigrok.org/gitweb/?a=blobdiff_plain;f=firmware%2Fsaleae-logic16%2Fsigrok-fwextract-saleae-logic16;h=45f98277c879a46d3d02fa1094a9551e64b6ab26;hb=1b0c6828974e6c18763600aeb09034d5686f21f1;hp=09b8730651b54a59ab1d52fbf6ac1ba29dd0b88e;hpb=28fca3a8f9e73c86d27f20065e51c69a9118a60e;p=sigrok-util.git diff --git a/firmware/saleae-logic16/sigrok-fwextract-saleae-logic16 b/firmware/saleae-logic16/sigrok-fwextract-saleae-logic16 index 09b8730..45f9827 100755 --- a/firmware/saleae-logic16/sigrok-fwextract-saleae-logic16 +++ b/firmware/saleae-logic16/sigrok-fwextract-saleae-logic16 @@ -19,8 +19,265 @@ ## import sys +import struct import parseelf +class searcher: + + def reset(this, offs = 0): + if offs < 0 or offs > this.length: + raise Exception('Reset past end of section') + this.address = this.baseaddr + offs + this.offset = offs + + def skip(this, cnt): + if this.offset + cnt > this.length: + raise Exception('Skip past end of section') + this.address += cnt + this.offset += cnt + + def peek(this, cnt, offs=0): + if this.offset + offs + cnt > this.length: + raise Exception('Peek past end of section') + return this.data[this.offset + offs : this.offset + offs + cnt] + + def look_for(this, needle): + pos = this.data.find(needle, this.offset) + if pos < 0: + raise Exception('Needle not found in haystack') + this.skip(pos - this.offset) + + def __init__(this, data, addr): + this.data = data + this.baseaddr = addr + this.length = len(data) + this.reset() + +def search_plt_32(plt, addr): + plt.reset() + plt.look_for(struct.pack(' 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 + text.skip(5) + elif text.peek(2) == 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) + if text.peek(2) == b'\x8d\x83': # lea offs32(%ebx),%eax + straddr = struct.unpack(' (len(lines) << 2) or (offs & 3) != 0: + raise Exception('Invalid offset %d' % offs) + index = offs >> 2 + if lines[index] != 0: + raise Exception('Line %d filled multiple times' % index) + if text.peek(3) == b'\x89\x04\x24': # mov %eax,(%esp) + text.skip(3) + if text.peek(1) == b'\xe8': # call offs32 + offs = struct.unpack(' 0: + 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 text.peek(4) == b'\x48\x8d\x54\x24': # lea offs8(%rsp),%rdx + text.skip(5) + elif text.peek(4) == b'\x48\x8d\x94\x24': # lea offs32(%rsp),%rdx + text.skip(8) + if text.peek(3) == b'\x48\x8d\x35': # lea offs32(%rip),%rsi + straddr = struct.unpack(' (len(lines) << 3) or (offs & 7) != 0: + raise Exception('Invalid offset %d' % offs) + index = offs >> 3 + if lines[index] != 0: + raise Exception('Line %d filled multiple times' % index) + if text.peek(1) == b'\xe8': # callq offs32 + offs = struct.unpack('BHB', line[:4]) + (data, checksum) = struct.unpack('>%dsB' % (byte_count), line[4:]) + if rectype == 1 and byte_count == 0: + pass + elif rectype != 0 or byte_count == 0: + raise Exception('Unexpected rectype %d with bytecount %d' % + (rectype, byte_count)) + elif address in chunks: + raise Exception('Multiple ihex lines with address 0x%x' % address) + else: + chunks[address] = data + blob = b'' + for address in sorted(iter(chunks)): + if address < len(blob): + raise Exception('Overlapping ihex chunks') + elif address > len(blob): + blob += b'\x00' * (address - len(blob)) + blob += chunks[address] + return blob + +def extract_fx2_firmware(elf, symname, filename): + blob = elf.load_symbol(elf.dynsym[symname+'Count']) + count = struct.unpack('= hi: + raise Exception('Address 0x%x outside of .rodata section' % addr) + l[i] = elf.get_name(addr - lo, rodata) + blob = ihex_to_binary(l) + f = open(filename, 'wb') + f.write(blob) + f.close() + print("saved %d bytes to %s" % (len(blob), filename)) + def extract_symbol(elf, symname, filename): blob = elf.load_symbol(elf.dynsym[symname]) f = open(filename, 'wb') @@ -47,6 +304,9 @@ if len(sys.argv) != 2: try: filename = sys.argv[1] elf = parseelf.elf(filename) + if elf.ehdr['e_machine'] != 3 and elf.ehdr['e_machine'] != 62: + raise Exception('Unsupported e_machine') + extract_fx2_firmware(elf, 'gLogic16HexFileLines', 'saleae-logic16-fx2.fw') extract_bitstream(elf, '18') extract_bitstream(elf, '33') except Exception as e: