// Copyright (c) 2026 Petr Balvín (https://petrbalvin.org) // SPDX-License-Identifier: BSD-3-Clause package asm import ( "os" "os/exec" "testing" ) // TestReadRuntimeSymbols verifies the GOOBJ reader can extract and find // symbols from the runtime package's compiled archive. func TestReadRuntimeSymbols(t *testing.T) { exp, err := exportPath("runtime") if err != nil { t.Skipf("cannot find runtime export: %v (need Go toolchain)", err) } data, err := os.ReadFile(exp) if err != nil { t.Skipf("cannot read runtime export: %v", err) } gobj, err := extractGOOBJ(data) if err != nil { t.Fatalf("extractGOOBJ: %v", err) } t.Logf("runtime: %d symbols", len(gobj.symbols())) // Verify we can find well-known runtime symbols. for _, tc := range []struct{ pkg, name string }{ {"runtime", "g0"}, {"runtime", "morestack"}, {"runtime", "newstack"}, } { idx := gobj.findSymbol(tc.pkg, tc.name) if idx < 0 { t.Errorf("findSymbol(%q, %q) = -1", tc.pkg, tc.name) } else { t.Logf("findSymbol(%q, %q) = %d", tc.pkg, tc.name, idx) } } } // TestResolveExternalSymbols verifies end-to-end resolution of external // symbol references. func TestResolveExternalSymbols(t *testing.T) { if _, err := exec.LookPath("go"); err != nil { t.Skip("go toolchain not available") } refs := map[string][]string{ "runtime": {"g0"}, } pkgIdx, symIdx, err := resolveExternalGOOBJ(refs) if err != nil { t.Fatalf("resolveExternalGOOBJ: %v", err) } if len(pkgIdx) != 1 || pkgIdx["runtime"] != 1 { // Index 0 is the dummy invalid package in the blkPkgIdx table; // the loader's reader loop starts at 1 (cmd/link/internal/ // loader/loader.go: "PkgIdx 0 is a dummy invalid package"), so // the first real package must carry index 1. t.Errorf("pkgIdx = %v, want runtime→1", pkgIdx) } if _, ok := symIdx["runtime·g0"]; !ok { t.Errorf("symIdx missing runtime·g0, got %v", symIdx) } t.Logf("runtime·g0 → SymIdx=%d", symIdx["runtime·g0"]) }