import argparse
import re
import struct
def parse_line(line):
match = re.match(r'^\[([0-9A-Fa-f]{8})\]: ((?:[0-9A-Fa-f]{8} ){7}[0-9A-Fa-f]{8})$', line.strip())
if not match:
return None
address_str, data_str = match.groups()
address = int(address_str, 16)
words = [int(w, 16) for w in data_str.strip().split()]
return address, words
def main():
parser = argparse.ArgumentParser(description='Convert hex dump format to raw binary for Ghidra.')
parser.add_argument('-i', '--input', required=True, help='Input .hex-style file')
parser.add_argument('-o', '--output', required=True, help='Output binary file')
parser.add_argument('--base', type=lambda x: int(x, 16), default=None,
help='Optional: base address override (hex, e.g. 0x08000000)')
args = parser.parse_args()
memory = {}
min_address = None
max_address = None
with open(args.input, 'r') as infile:
for line in infile:
parsed = parse_line(line)
if parsed is None:
continue
address, words = parsed
for i, word in enumerate(words):
addr = address + i * 4
memory[addr] = word
if min_address is None or addr < min_address:
min_address = addr
if max_address is None or addr > max_address:
max_address = addr
if args.base:
min_address = args.base
with open(args.output, 'wb') as outfile:
addr = min_address
while addr <= max_address:
word = memory.get(addr, 0)
outfile.write(struct.pack('<I', word)) # little-endian
addr += 4
if __name__ == '__main__':
main()