Files
vt1200/tools/as34/extract.py
T
arti 6338095683 tools: add as34/ld34 TMS34010 binutils, ported to 64-bit Linux
Andrew Morton's Unix-hosted assembler/linker for the TMS34010, fetched from the gsptools archive and patched to build on x86-64. The K&R sources silently truncate pointers there: implicit int parameter declarations and fixed-argument printf wrappers. The patch fixes those and the flex 2.6 yy_init mismatch.

hello.as34.g is harness/hello-world/hello.asm in as34 syntax. as34/ld34 reproduce the GSPA-built payload byte-for-byte (82 bytes, md5 db91788991ebba476b55a11127a36475), and the MAME hello.lua run reports the same markers, the same 1024-word VRAM block and a byte-identical frame.

build.sh downloads the upstream tarball at build time (sha256 pinned); the tree is not vendored.
2026-10-22 14:19:14 +03:00

75 lines
2.4 KiB
Python
Executable File

#!/usr/bin/env python3
"""Extract the loadable .text bytes from an as34/ld34 g.out file.
g.out is not COFF. It uses the .go/linkhdr format from binutils/link.h
(LINKMAGIC 0x3abf782e), packed with #pragma pack(2).
IMPORTANT: link.h declares the header fields that hold addresses and sizes
as `long`. On the original 32-bit Unix hosts that is 4 bytes; on x86-64 it
is 8, so the written header is 156 bytes here instead of the historical 80.
as34 and ld34 are both rebuilt with the same compiler, so they agree with
each other and with this parser. A stable on-disk format would need `long`
changed to int32_t in link.h.
Layout as written by this 64-bit build (offsets in bytes):
off field
0 short swapped
2 long magic
10 short flags
12 long time
20 long textstart file position of text
28 long textsize size in BYTES
36 long datastart
44 long datasize
52 long bsssize
60 long relocstart
68 long nrelocs
76 long symtabstart
84 long nsyms
92 long stabstart
100 long nstabs
108 long stringstart
116 long stringSize
124 long textLoadAddress BIT address
132 long dataLoadAddress
140 long bssLoadAddress
148 long entrypoint BIT address
"""
import hashlib
import struct
import sys
LINKMAGIC = 0x3ABF782E
def main(out_path, bin_path):
d = open(out_path, "rb").read()
fields = struct.unpack_from("<hqh" + "q" * 18, d, 0)
(swapped, magic, flags, _time, textstart, textsize,
_datastart, _datasize, _bsssize, _relocstart, _nrelocs,
_symtabstart, _nsyms, _stabstart, _nstabs,
_stringstart, _stringsize,
textload, _dataload, _bssload, entry) = fields
if magic != LINKMAGIC:
sys.exit("extract: bad magic %#010x" % magic)
if swapped:
sys.exit("extract: byte-swapped header not handled")
payload = d[textstart:textstart + textsize]
if len(payload) != textsize:
sys.exit("extract: truncated text (%d of %d bytes)"
% (len(payload), textsize))
open(bin_path, "wb").write(payload)
print("origin=%08X (bits) size=%d bytes entry=%08X file_offset=%#x md5=%s"
% (textload, textsize, entry, textstart,
hashlib.md5(payload).hexdigest()))
if __name__ == "__main__":
if len(sys.argv) != 3:
sys.exit("usage: extract.py hello.out payload.bin")
main(sys.argv[1], sys.argv[2])