diff --git a/src/cmd/link/internal/ld/objfile.go b/src/cmd/link/internal/ld/objfile.go index b04244f3cc9..11cdf91d749 100644 --- a/src/cmd/link/internal/ld/objfile.go +++ b/src/cmd/link/internal/ld/objfile.go @@ -165,7 +165,7 @@ func readsym(ctxt *Link, f *obj.Biobuf, pkg string, pn string) { log.Fatalf("readsym out of sync") } t := rdint(f) - name := expandpkg(rdstring(f), pkg) + name := rdsymName(f, pkg) v := rdint(f) if v != 0 && v != 1 { log.Fatalf("invalid symbol version %d", v) @@ -424,11 +424,17 @@ func rduint8(f *obj.Biobuf) uint8 { return uint8(n) } +// rdBuf is used by rdstring and rdsymName as scratch for reading strings. +var rdBuf []byte +var emptyPkg = []byte(`"".`) + func rdstring(f *obj.Biobuf) string { - n := rdint64(f) - p := make([]byte, n) - obj.Bread(f, p) - return string(p) + n := rdint(f) + if len(rdBuf) < n { + rdBuf = make([]byte, n) + } + obj.Bread(f, rdBuf[:n]) + return string(rdBuf[:n]) } var ( @@ -452,25 +458,48 @@ func rddata(f *obj.Biobuf) []byte { return p } -var symbuf []byte - -func rdsym(ctxt *Link, f *obj.Biobuf, pkg string) *LSym { +// rdsymName reads a symbol name, replacing all "". with pkg. +func rdsymName(f *obj.Biobuf, pkg string) string { n := rdint(f) if n == 0 { rdint64(f) - return nil + return "" } - if len(symbuf) < n { - symbuf = make([]byte, n) + if len(rdBuf) < n { + rdBuf = make([]byte, n, 2*n) + } + origName := rdBuf[:n] + obj.Bread(f, origName) + adjName := rdBuf[n:n] + for { + i := bytes.Index(origName, emptyPkg) + if i == -1 { + adjName = append(adjName, origName...) + break + } + adjName = append(adjName, origName[:i]...) + adjName = append(adjName, pkg...) + adjName = append(adjName, '.') + origName = origName[i+len(emptyPkg):] + } + name := string(adjName) + if len(adjName) > len(rdBuf) { + rdBuf = adjName // save the larger buffer for reuse + } + return name +} + +func rdsym(ctxt *Link, f *obj.Biobuf, pkg string) *LSym { + name := rdsymName(f, pkg) + if name == "" { + return nil } - obj.Bread(f, symbuf[:n]) - p := string(symbuf[:n]) v := rdint(f) if v != 0 { v = ctxt.Version } - s := Linklookup(ctxt, expandpkg(p, pkg), v) + s := Linklookup(ctxt, name, v) if v == 0 && s.Name[0] == '$' && s.Type == 0 { if strings.HasPrefix(s.Name, "$f32.") {