support referencing package paths with periods in assembly

The test case is lifted from github.com/bytedance/sonic/internal/native,
which had the following line:

	JMP github·com∕bytedance∕sonic∕internal∕native∕avx2·__quote(SB)

Updates #621.
pull/635/head
Daniel Martí 2 years ago
parent 6ace03322f
commit 417bcf27bb

@ -715,18 +715,21 @@ func replaceAsmNames(buf *bytes.Buffer, remaining []byte) {
// //
// TEXT ·privateAdd(SB),$0-24 // TEXT ·privateAdd(SB),$0-24
// TEXT runtimeinternalsys·Ctz64(SB), NOSPLIT, $0-12 // TEXT runtimeinternalsys·Ctz64(SB), NOSPLIT, $0-12
const middleDot = '·' //
middleDotLen := utf8.RuneLen(middleDot)
// Note that import paths in assembly, like `runtimeinternalsys` above, // Note that import paths in assembly, like `runtimeinternalsys` above,
// use a Unicode slash rather than the ASCII one used by Go and `go list`. // use Unicode periods and slashes rather than the ASCII ones used by `go list`.
// We need to convert to ASCII to find the right package information. // We need to convert to ASCII to find the right package information.
const asmPkgSlash = '' const (
const goPkgSlash = '/' asmPeriod = '·'
goPeriod = '.'
asmSlash = ''
goSlash = '/'
)
asmPeriodLen := utf8.RuneLen(asmPeriod)
for { for {
i := bytes.IndexRune(remaining, middleDot) periodIdx := bytes.IndexRune(remaining, asmPeriod)
if i < 0 { if periodIdx < 0 {
buf.Write(remaining) buf.Write(remaining)
remaining = nil remaining = nil
break break
@ -734,16 +737,37 @@ func replaceAsmNames(buf *bytes.Buffer, remaining []byte) {
// The package name ends at the first rune which cannot be part of a Go // The package name ends at the first rune which cannot be part of a Go
// import path, such as a comma or space. // import path, such as a comma or space.
pkgStart := i pkgStart := periodIdx
for pkgStart >= 0 { for pkgStart >= 0 {
c, size := utf8.DecodeLastRune(remaining[:pkgStart]) c, size := utf8.DecodeLastRune(remaining[:pkgStart])
if !unicode.IsLetter(c) && c != '_' && c != asmPkgSlash && !unicode.IsDigit(c) { if !unicode.IsLetter(c) && c != '_' && c != asmSlash && !unicode.IsDigit(c) {
break break
} }
pkgStart -= size pkgStart -= size
} }
asmPkgPath := string(remaining[pkgStart:i]) // The package name might actually be longer, e.g:
goPkgPath := strings.ReplaceAll(asmPkgPath, string(asmPkgSlash), string(goPkgSlash)) //
// JMP testwith·many·dotsmainimported·PublicAdd(SB)
//
// We have `testwith` so far; grab `·many·dotsmainimported` as well.
pkgEnd := periodIdx
lastAsmPeriod := -1
for i := pkgEnd + asmPeriodLen; i <= len(remaining); {
c, size := utf8.DecodeRune(remaining[i:])
if c == asmPeriod {
lastAsmPeriod = i
} else if !unicode.IsLetter(c) && c != '_' && c != asmSlash && !unicode.IsDigit(c) {
if lastAsmPeriod > 0 {
pkgEnd = lastAsmPeriod
}
break
}
i += size
}
asmPkgPath := string(remaining[pkgStart:pkgEnd])
goPkgPath := asmPkgPath
goPkgPath = strings.ReplaceAll(goPkgPath, string(asmPeriod), string(goPeriod))
goPkgPath = strings.ReplaceAll(goPkgPath, string(asmSlash), string(goSlash))
// Write the bytes before our unqualified `·foo` or qualified `pkg·foo`. // Write the bytes before our unqualified `·foo` or qualified `pkg·foo`.
buf.Write(remaining[:pkgStart]) buf.Write(remaining[:pkgStart])
@ -771,8 +795,8 @@ func replaceAsmNames(buf *bytes.Buffer, remaining []byte) {
} }
// Write the middle dot and advance the remaining slice. // Write the middle dot and advance the remaining slice.
buf.WriteRune(middleDot) buf.WriteRune(asmPeriod)
remaining = remaining[i+middleDotLen:] remaining = remaining[pkgEnd+asmPeriodLen:]
// The declared name ends at the first rune which cannot be part of a Go // The declared name ends at the first rune which cannot be part of a Go
// identifier, such as a comma or space. // identifier, such as a comma or space.

@ -26,14 +26,14 @@ exec ./main
cmp stderr main.stderr cmp stderr main.stderr
binsubstr main$exe 'privateAdd' 'PublicAdd' binsubstr main$exe 'privateAdd' 'PublicAdd'
-- go.mod -- -- go.mod --
module test/main module test/with.many.dots/main
go 1.19 go 1.19
-- main.go -- -- main.go --
package main package main
import ( import (
"test/main/imported" "test/with.many.dots/main/imported"
) )
func privateAdd(x, y int32) int32 func privateAdd(x, y int32) int32
@ -56,17 +56,13 @@ func main() {
println(imported.PublicAdd(3, 4)) println(imported.PublicAdd(3, 4))
} }
-- garble_main_amd64.s -- -- garble_main_amd64.s --
TEXT ·privateAdd(SB),$0-16
MOVL x+0(FP), BX
MOVL y+4(FP), BP
ADDL BP, BX
MOVL BX, ret+8(FP)
RET
#include "garble_define_amd64.h" #include "garble_define_amd64.h"
#include "extra/garble_define2_amd64.h" #include "extra/garble_define2_amd64.h"
TEXT ·privateAdd(SB),$0-16
JMP testwith·many·dotsmainimported·PublicAdd(SB)
TEXT ·modifyGoData(SB),$0-16 TEXT ·modifyGoData(SB),$0-16
addGoDataTo($12) addGoDataTo($12)
ADDL $34, ·goData+8(SB) ADDL $34, ·goData+8(SB)

Loading…
Cancel
Save