feat(asm): emit linkable ELF and Mach-O objects with external symbols
Assisted-by: Qwen 3.8 Max Preview
This commit is contained in:
+40
-9
@@ -28,7 +28,7 @@ import (
|
||||
|
||||
// version is the release version, stamped at build time via
|
||||
// -ldflags "-X main.version=…" (defaulting to the current release).
|
||||
var version = "0.10.0"
|
||||
var version = "0.11.0"
|
||||
|
||||
func main() {
|
||||
if len(os.Args) < 2 {
|
||||
@@ -93,6 +93,7 @@ Examples:
|
||||
gasm fmt reformat every .s below the current directory
|
||||
gasm lint go-flac/*.s run static checks over the kernels
|
||||
gasm asm -o k.bin kern_amd64.s
|
||||
gasm asm --format elf -o k.o kern_amd64.s
|
||||
`, version)
|
||||
}
|
||||
|
||||
@@ -339,17 +340,24 @@ hover, document symbols, diagnostics and semantic-token highlighting.
|
||||
}
|
||||
|
||||
func cmdAsm(args []string) int {
|
||||
fs := newCommand("asm", "gasm asm [-o out.bin] <file>", `
|
||||
fs := newCommand("asm", "gasm asm [--format raw|elf|macho] [-o out] <file>", `
|
||||
Assemble FILE (amd64) without the Go toolchain: every TEXT function is
|
||||
encoded to machine code — scalar, VEX/AVX2 and EVEX/AVX-512 instructions,
|
||||
FP/SP frame mapping, local labels and file-local static symbols (GLOBL/DATA)
|
||||
resolved RIP-relative — and printed as a hex dump. With -o the concatenated
|
||||
image (functions followed by the data section) is written to a file instead.
|
||||
resolved RIP-relative — and printed as a hex dump.
|
||||
|
||||
With -o the output is written to a file instead. The --format flag selects
|
||||
what is written: raw (the default) concatenates the functions and the data
|
||||
section into one self-consistent image; elf and macho emit a relocatable
|
||||
object (.text/.data sections, a symbol table and one PC32 relocation per
|
||||
static-symbol reference) that links with the system toolchain — references
|
||||
to symbols no GLOBL in the file defines become undefined external symbols.
|
||||
`)
|
||||
out := fs.String("o", "", "write the concatenated machine code to this file")
|
||||
out := fs.String("o", "", "write the output to this file")
|
||||
format := fs.String("format", "raw", "output format: raw (concatenated image), elf or macho (relocatable object)")
|
||||
fs.Parse(args)
|
||||
if fs.NArg() != 1 {
|
||||
fmt.Fprintln(os.Stderr, "usage: gasm asm [-o out.bin] <file>")
|
||||
fmt.Fprintln(os.Stderr, "usage: gasm asm [--format raw|elf|macho] [-o out] <file>")
|
||||
return 2
|
||||
}
|
||||
path := fs.Arg(0)
|
||||
@@ -420,12 +428,35 @@ image (functions followed by the data section) is written to a file instead.
|
||||
}
|
||||
}
|
||||
if *out != "" {
|
||||
all := img.Bytes()
|
||||
if err := os.WriteFile(*out, all, 0o644); err != nil {
|
||||
var obj []byte
|
||||
var err error
|
||||
var kind string
|
||||
switch *format {
|
||||
case "raw":
|
||||
if len(img.Externals) > 0 {
|
||||
fmt.Fprintf(os.Stderr, "gasm asm: external symbol %q needs an object file (use --format elf or --format macho)\n", img.Externals[0])
|
||||
return 1
|
||||
}
|
||||
obj, kind = img.Bytes(), "raw image"
|
||||
case "elf":
|
||||
obj, err = img.ELFObject()
|
||||
kind = "ELF object"
|
||||
case "macho":
|
||||
obj, err = img.MachOObject()
|
||||
kind = "Mach-O object"
|
||||
default:
|
||||
fmt.Fprintf(os.Stderr, "gasm asm: unknown format %q (want raw, elf or macho)\n", *format)
|
||||
return 2
|
||||
}
|
||||
if err != nil {
|
||||
fmt.Fprintln(os.Stderr, "gasm asm:", err)
|
||||
return 1
|
||||
}
|
||||
fmt.Printf("wrote %d bytes to %s\n", len(all), *out)
|
||||
if err := os.WriteFile(*out, obj, 0o644); err != nil {
|
||||
fmt.Fprintln(os.Stderr, "gasm asm:", err)
|
||||
return 1
|
||||
}
|
||||
fmt.Printf("wrote %d bytes to %s (%s)\n", len(obj), *out, kind)
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user