| | |
| | |
| | |
| |
|
| | |
| | |
| | package pkgpath |
| |
|
| | import ( |
| | "bytes" |
| | "errors" |
| | "fmt" |
| | "os" |
| | "os/exec" |
| | "strings" |
| | ) |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | func ToSymbolFunc(cmd, tmpdir string) (func(string) string, error) { |
| | |
| | |
| | |
| | |
| | |
| | |
| | const filepat = "*_gccgo_manglechck.go" |
| | f, err := os.CreateTemp(tmpdir, filepat) |
| | if err != nil { |
| | return nil, err |
| | } |
| | gofilename := f.Name() |
| | f.Close() |
| | defer os.Remove(gofilename) |
| |
|
| | if err := os.WriteFile(gofilename, []byte(mangleCheckCode), 0644); err != nil { |
| | return nil, err |
| | } |
| |
|
| | command := exec.Command(cmd, "-S", "-o", "-", gofilename) |
| | buf, err := command.Output() |
| | if err != nil { |
| | return nil, err |
| | } |
| |
|
| | |
| | |
| | |
| | if bytes.Contains(buf, []byte("go_0l_u00e4ufer.Run")) { |
| | return toSymbolV3, nil |
| | } else if bytes.Contains(buf, []byte("go.l..u00e4ufer.Run")) { |
| | return toSymbolV2, nil |
| | } else if bytes.Contains(buf, []byte("go.l__ufer.Run")) { |
| | return toSymbolV1, nil |
| | } else { |
| | return nil, errors.New(cmd + ": unrecognized mangling scheme") |
| | } |
| | } |
| |
|
| | |
| | const mangleCheckCode = ` |
| | package läufer |
| | func Run(x int) int { |
| | return 1 |
| | } |
| | ` |
| |
|
| | |
| | func toSymbolV1(ppath string) string { |
| | clean := func(r rune) rune { |
| | switch { |
| | case 'A' <= r && r <= 'Z', 'a' <= r && r <= 'z', |
| | '0' <= r && r <= '9': |
| | return r |
| | } |
| | return '_' |
| | } |
| | return strings.Map(clean, ppath) |
| | } |
| |
|
| | |
| | func toSymbolV2(ppath string) string { |
| | var bsl strings.Builder |
| | changed := false |
| | for _, c := range ppath { |
| | if ('A' <= c && c <= 'Z') || ('a' <= c && c <= 'z') || ('0' <= c && c <= '9') || c == '_' { |
| | bsl.WriteByte(byte(c)) |
| | continue |
| | } |
| | var enc string |
| | switch { |
| | case c == '.': |
| | enc = ".x2e" |
| | case c < 0x80: |
| | enc = fmt.Sprintf("..z%02x", c) |
| | case c < 0x10000: |
| | enc = fmt.Sprintf("..u%04x", c) |
| | default: |
| | enc = fmt.Sprintf("..U%08x", c) |
| | } |
| | bsl.WriteString(enc) |
| | changed = true |
| | } |
| | if !changed { |
| | return ppath |
| | } |
| | return bsl.String() |
| | } |
| |
|
| | |
| | |
| | var v3UnderscoreCodes = map[byte]byte{ |
| | '_': '_', |
| | '.': '0', |
| | '/': '1', |
| | '*': '2', |
| | ',': '3', |
| | '{': '4', |
| | '}': '5', |
| | '[': '6', |
| | ']': '7', |
| | '(': '8', |
| | ')': '9', |
| | '"': 'a', |
| | ' ': 'b', |
| | ';': 'c', |
| | } |
| |
|
| | |
| | func toSymbolV3(ppath string) string { |
| | var bsl strings.Builder |
| | changed := false |
| | for _, c := range ppath { |
| | if ('A' <= c && c <= 'Z') || ('a' <= c && c <= 'z') || ('0' <= c && c <= '9') { |
| | bsl.WriteByte(byte(c)) |
| | continue |
| | } |
| |
|
| | if c < 0x80 { |
| | if u, ok := v3UnderscoreCodes[byte(c)]; ok { |
| | bsl.WriteByte('_') |
| | bsl.WriteByte(u) |
| | changed = true |
| | continue |
| | } |
| | } |
| |
|
| | var enc string |
| | switch { |
| | case c < 0x80: |
| | enc = fmt.Sprintf("_x%02x", c) |
| | case c < 0x10000: |
| | enc = fmt.Sprintf("_u%04x", c) |
| | default: |
| | enc = fmt.Sprintf("_U%08x", c) |
| | } |
| | bsl.WriteString(enc) |
| | changed = true |
| | } |
| | if !changed { |
| | return ppath |
| | } |
| | return bsl.String() |
| | } |
| |
|