Skip to content

6l: PE32+ output for Windows amd64 (-H 10), printing via kernel32#8

Open
rafael2knokia wants to merge 1 commit into
aryx:masterfrom
rafael2knokia:windows-amd64
Open

6l: PE32+ output for Windows amd64 (-H 10), printing via kernel32#8
rafael2knokia wants to merge 1 commit into
aryx:masterfrom
rafael2knokia:windows-amd64

Conversation

@rafael2knokia

@rafael2knokia rafael2knokia commented Jul 9, 2026

Copy link
Copy Markdown

Summary

  • Teach 6l -H 10 to emit PE32+ (64-bit) Windows executables that actually do I/O.
  • The .idata import table imports GetStdHandle, WriteFile and ExitProcess from kernel32.dll, and the linker defines an __imp_<name> symbol at each import's IAT slot so a program can call through the thunk (MOVQ __imp_WriteFile(SB), AX; CALL AX).
  • tests/s/mini/hello_windows_amd64.s prints Hello, World! and exits 0.

Details

  • IMAGE_OPTIONAL_HEADER64 added; asmbpe() emits Magic 0x20b, subsystem/OS 6.0, LARGE_ADDRESS_AWARE, fills oh64 from oh. IAT entries are 8 bytes wide under pe64.
  • peimports() runs from dope() (moved before reloc()) to lay out .idata and define the __imp_* symbols so references resolve to the right IAT slots.
  • add_import_table() writes at the section's PointerToRawData (not EOF), fixing a "file truncated" load error when .data is non-empty.
  • dope() skips zero-size .data/.bss so sections don't collide on VirtualAddress.

This PR is now independent of #7 (386 smoke test); both branch from master.

Test plan

  • 6l -s -H 10 builds a PE32+ executable (console) x86-64.
  • Runs under wine: prints Hello, World!, exits 0.
  • 8l/5l still compile the shared pe.c; mk all in tests/s/mini passes.

Wire the PE writer into 6l so it can produce 64-bit Windows executables
that actually do I/O, the amd64 counterpart to the 386 support on 8l.

src/cmd/ld/pe.{c,h}: add the PE32+ path.
- New IMAGE_OPTIONAL_HEADER64 (ImageBase and the stack/heap sizes widen
  to 8 bytes, BaseOfData dropped; written verbatim like the 32-bit
  header). peinit() already set pe64 for thechar=='6'; asmbpe() now
  emits Magic 0x20b, MajorSubsystem/OS 6.0 (64-bit Windows predates
  4.0), LARGE_ADDRESS_AWARE, and fills oh64 from oh.
- The import table now imports GetStdHandle, WriteFile and ExitProcess
  from kernel32. peimports() (run from dope(), before reloc()) lays out
  the .idata section and defines an __imp_<name> linker symbol at each
  import's IAT slot, so a program can call through the thunk with
  "MOVQ __imp_WriteFile(SB), AX; CALL AX". IAT entries and the null
  terminator are 8 bytes wide under pe64.
- add_import_table() now only writes the bytes (layout done earlier),
  and writes them at the section's PointerToRawData rather than the
  current EOF (with non-empty .data the file position is not
  page-aligned, which left the image "truncated").
- dope() skips zero-size .data/.bss: an empty section does not advance
  the virtual-address cursor, so the next section would collide on
  VirtualAddress and the loader rejects the image.

src/cmd/6l: compile pe.c (symlink + mkfile), add "-H 10" / goos=windows
handling in obj.c (peinit + case 10, defaulting INITTEXT=PEBASE+0x1000
like 8l), call dope() before reloc() so the __imp_* symbols resolve, and
dispatch asmbpe() from asmb(). 6l has no PE symbol-table path yet, so
obj.c forces -s for -H 10.

tests/s/mini: hello_windows_amd64.s prints "Hello, World!" via
GetStdHandle + WriteFile + ExitProcess (Win64 ABI: args in CX/DX/R8/R9,
32-byte shadow space, 16-byte aligned stack), built with 6l -H 10.

Verified on Linux with wine: `6l -s -H 10` produces a
"PE32+ executable (console) x86-64" (Magic 0x20b, ImageBase 0x400000)
that prints "Hello, World!" and exits 0.
@rafael2knokia rafael2knokia changed the title 6l: PE32+ output for Windows amd64 (-H 10) 6l: PE32+ output for Windows amd64 (-H 10), printing via kernel32 Jul 10, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant