Commit 34489eb2 by Ian Lance Taylor

compiler: improve name mangling for packpaths

    
    The current implementation of Gogo::pkgpath_for_symbol was written in
    a way that allowed two distinct package paths to map to the same
    symbol, which could cause collisions at link- time or compile-time.
    
    Switch to a better mangling scheme to insure that we get a unique
    packagepath symbol for each package. In the new scheme instead of having
    separate mangling schemes for identifiers and package paths, the
    main identifier mangler ("go_encode_id") now handles mangling of
    both packagepath characters and identifier characters.
    
    The new mangling scheme is more intrusive: "foo/bar.Baz" is mangled as
    "foo..z2fbar.Baz" instead of "foo_bar.Baz". To mitigate this, this
    patch also adds a demangling capability so that function names
    returned from runtime.CallersFrames are converted back to their
    original unmangled form.
    
    Changing the pkgpath_for_symbol scheme requires updating a number of
    //go:linkname directives and C "__asm__" directives to match the new
    scheme, as well as updating the 'gotest' driver (which makes
    assumptions about the correct mapping from pkgpath symbol to package
    name).
    
    Fixes golang/go#27534.
    
    Reviewed-on: https://go-review.googlesource.com/c/135455

From-SVN: r265510
parent fc756f9f
771668f7137e560b2ef32c8799e5f8b4c4ee14a9 407a59831ea4fbfe03f0887c40497b73939e7c44
The first line of this file holds the git revision number of the last The first line of this file holds the git revision number of the last
merge done from the gofrontend repository. merge done from the gofrontend repository.
// go-encode-id.cc -- Go identifier encoding hooks // go-encode-id.cc -- Go identifier and packagepath encoding/decoding hooks
// Copyright 2016 The Go Authors. All rights reserved. // Copyright 2016 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style // Use of this source code is governed by a BSD-style
...@@ -82,10 +82,10 @@ fetch_utf8_char(const char* p, unsigned int* pc) ...@@ -82,10 +82,10 @@ fetch_utf8_char(const char* p, unsigned int* pc)
return len; return len;
} }
// Encode an identifier using ASCII characters. The encoding is // Encode an identifier using assembler-friendly characters. The encoding is
// described in detail near the end of the long comment at the start // described in detail near the end of the long comment at the start of
// of names.cc. Short version: translate all non-ASCII-alphanumeric // names.cc. Short version: translate all non-ASCII-alphanumeric characters into
// characters into ..uXXXX or ..UXXXXXXXX. // ..uXXXX or ..UXXXXXXXX, translate ASCII non-alphanumerics into ".zXX".
std::string std::string
go_encode_id(const std::string &id) go_encode_id(const std::string &id)
...@@ -97,7 +97,8 @@ go_encode_id(const std::string &id) ...@@ -97,7 +97,8 @@ go_encode_id(const std::string &id)
} }
// The encoding is only unambiguous if the input string does not // The encoding is only unambiguous if the input string does not
// contain ..u or ..U. // contain ..z, ..u or ..U.
go_assert(id.find("..z") == std::string::npos);
go_assert(id.find("..u") == std::string::npos); go_assert(id.find("..u") == std::string::npos);
go_assert(id.find("..U") == std::string::npos); go_assert(id.find("..U") == std::string::npos);
...@@ -116,17 +117,16 @@ go_encode_id(const std::string &id) ...@@ -116,17 +117,16 @@ go_encode_id(const std::string &id)
{ {
unsigned int c; unsigned int c;
size_t len = fetch_utf8_char(p, &c); size_t len = fetch_utf8_char(p, &c);
if (len == 1) if (len == 1 && !char_needs_encoding(c))
{ {
// At this point we should only be seeing alphanumerics or
// underscore or dot.
go_assert(!char_needs_encoding(c));
ret += c; ret += c;
} }
else else
{ {
char buf[16]; char buf[16];
if (c < 0x10000) if (len == 1)
snprintf(buf, sizeof buf, "..z%02x", c);
else if (c < 0x10000)
snprintf(buf, sizeof buf, "..u%04x", c); snprintf(buf, sizeof buf, "..u%04x", c);
else else
snprintf(buf, sizeof buf, "..U%08x", c); snprintf(buf, sizeof buf, "..U%08x", c);
...@@ -143,6 +143,77 @@ go_encode_id(const std::string &id) ...@@ -143,6 +143,77 @@ go_encode_id(const std::string &id)
return ret; return ret;
} }
// Convert a hex digit string to a unicode codepoint. No checking
// to insure that the hex digit is meaningful.
static unsigned
hex_digits_to_unicode_codepoint(const char *digits, unsigned ndig)
{
unsigned result = 0;
for (unsigned i = 0; i < ndig; ++i) {
result <<= 4;
result |= Lex::hex_val(digits[i]);
}
return result;
}
// Decode/demangle a mangled string produced by go_encode_id(). Returns
// empty string if demangling process fails in some way. At the moment
// this routine is unused; there is an equivalent routine in the runtime
// used for demangling symbols appearing in stack traces.
std::string
go_decode_id(const std::string &encoded)
{
std::string ret;
const char* p = encoded.c_str();
const char* pend = p + encoded.length();
const Location loc = Linemap::predeclared_location();
// Special case for initial "_", in case it was introduced
// as a way to prevent encoded symbol starting with ".".
if (*p == '_' && (strncmp(p+1, "..u", 3) == 0 || strncmp(p+1, "..U", 3) == 0))
p++;
while (p < pend)
{
if (strncmp(p, "..z", 3) == 0)
{
const char* digits = p+3;
if (strlen(digits) < 2)
return "";
unsigned rune = hex_digits_to_unicode_codepoint(digits, 2);
Lex::append_char(rune, true, &ret, loc);
p += 5;
}
else if (strncmp(p, "..u", 3) == 0)
{
const char* digits = p+3;
if (strlen(digits) < 4)
return "";
unsigned rune = hex_digits_to_unicode_codepoint(digits, 4);
Lex::append_char(rune, true, &ret, loc);
p += 7;
}
else if (strncmp(p, "..U", 3) == 0)
{
const char* digits = p+3;
if (strlen(digits) < 8)
return "";
unsigned rune = hex_digits_to_unicode_codepoint(digits, 8);
Lex::append_char(rune, true, &ret, loc);
p += 11;
}
else
{
ret += *p;
p += 1;
}
}
return ret;
}
std::string std::string
go_selectively_encode_id(const std::string &id) go_selectively_encode_id(const std::string &id)
{ {
......
...@@ -20,6 +20,11 @@ go_id_needs_encoding(const std::string& str); ...@@ -20,6 +20,11 @@ go_id_needs_encoding(const std::string& str);
extern std::string extern std::string
go_encode_id(const std::string &id); go_encode_id(const std::string &id);
// Decodes an encoded ID, returning the original string handed off to
// go_encode_id().
extern std::string
go_decode_id(const std::string &id);
// Returns the empty string if the specified name needs encoding, // Returns the empty string if the specified name needs encoding,
// otherwise invokes go_encode_id on the name and returns the result. // otherwise invokes go_encode_id on the name and returns the result.
extern std::string extern std::string
......
...@@ -256,26 +256,11 @@ Gogo::Gogo(Backend* backend, Linemap* linemap, int, int pointer_size) ...@@ -256,26 +256,11 @@ Gogo::Gogo(Backend* backend, Linemap* linemap, int, int pointer_size)
this->globals_->add_function_declaration("delete", NULL, delete_type, loc); this->globals_->add_function_declaration("delete", NULL, delete_type, loc);
} }
// Convert a pkgpath into a string suitable for a symbol. Note that
// this transformation is convenient but imperfect. A -fgo-pkgpath
// option of a/b_c will conflict with a -fgo-pkgpath option of a_b/c,
// possibly leading to link time errors.
std::string std::string
Gogo::pkgpath_for_symbol(const std::string& pkgpath) Gogo::pkgpath_for_symbol(const std::string& pkgpath)
{ {
std::string s = pkgpath; go_assert(!pkgpath.empty());
for (size_t i = 0; i < s.length(); ++i) return go_encode_id(pkgpath);
{
char c = s[i];
if ((c >= 'a' && c <= 'z')
|| (c >= 'A' && c <= 'Z')
|| (c >= '0' && c <= '9'))
;
else
s[i] = '_';
}
return s;
} }
// Get the package path to use for type reflection data. This should // Get the package path to use for type reflection data. This should
...@@ -319,6 +304,32 @@ Gogo::set_prefix(const std::string& arg) ...@@ -319,6 +304,32 @@ Gogo::set_prefix(const std::string& arg)
this->prefix_from_option_ = true; this->prefix_from_option_ = true;
} }
// Given a name which may or may not have been hidden, append the
// appropriate version of the name to the result string. Take care
// to avoid creating a sequence that will be rejected by go_encode_id
// (avoid ..u, ..U, ..z).
void
Gogo::append_possibly_hidden_name(std::string *result, const std::string& name)
{
// FIXME: This adds in pkgpath twice for hidden symbols, which is
// less than ideal.
if (!Gogo::is_hidden_name(name))
(*result) += name;
else
{
std::string n = ".";
std::string pkgpath = Gogo::hidden_name_pkgpath(name);
char lastR = result->at(result->length() - 1);
char firstP = pkgpath.at(0);
if (lastR == '.' && (firstP == 'u' || firstP == 'U' || firstP == 'z'))
n = "_.";
n.append(pkgpath);
n.append(1, '.');
n.append(Gogo::unpack_hidden_name(name));
(*result) += n;
}
}
// Munge name for use in an error message. // Munge name for use in an error message.
std::string std::string
......
...@@ -199,26 +199,10 @@ class Gogo ...@@ -199,26 +199,10 @@ class Gogo
return name.substr(1, name.rfind('.') - 1); return name.substr(1, name.rfind('.') - 1);
} }
// Given a name which may or may not have been hidden, return the // Given a name which may or may not have been hidden, append the
// name to use within a mangled symbol name. // appropriate version of the name to the result string.
static std::string static void
mangle_possibly_hidden_name(const std::string& name) append_possibly_hidden_name(std::string *result, const std::string& name);
{
// FIXME: This adds in pkgpath twice for hidden symbols, which is
// less than ideal.
std::string n;
if (!Gogo::is_hidden_name(name))
n = name;
else
{
n = ".";
std::string pkgpath = Gogo::hidden_name_pkgpath(name);
n.append(Gogo::pkgpath_for_symbol(pkgpath));
n.append(1, '.');
n.append(Gogo::unpack_hidden_name(name));
}
return n;
}
// Given a name which may or may not have been hidden, return the // Given a name which may or may not have been hidden, return the
// name to use in an error message. // name to use in an error message.
......
...@@ -440,6 +440,10 @@ class Lex ...@@ -440,6 +440,10 @@ class Lex
static bool static bool
is_unicode_space(unsigned int c); is_unicode_space(unsigned int c);
// Convert the specified hex char into an unsigned integer value.
static unsigned
hex_val(char c);
private: private:
ssize_t ssize_t
get_line(); get_line();
...@@ -462,9 +466,6 @@ class Lex ...@@ -462,9 +466,6 @@ class Lex
octal_value(char c) octal_value(char c)
{ return c - '0'; } { return c - '0'; }
static unsigned
hex_val(char c);
Token Token
make_invalid_token() make_invalid_token()
{ return Token::make_invalid_token(this->location()); } { return Token::make_invalid_token(this->location()); }
......
...@@ -33,7 +33,7 @@ ...@@ -33,7 +33,7 @@
// variable, is simply "PKGPATH.NAME". Note that NAME is not the // variable, is simply "PKGPATH.NAME". Note that NAME is not the
// packed form used for the "hidden" name internally in the compiler; // packed form used for the "hidden" name internally in the compiler;
// it is the name that appears in the source code. PKGPATH is the // it is the name that appears in the source code. PKGPATH is the
// -fgo-pkgpath option as adjusted by Gogo::pkgpath_for_symbol. Note // -fgo-pkgpath option as adjusted by Gogo::pkgpath_for_symbol. Note
// that PKGPATH can not contain a dot and neither can NAME. Also, // that PKGPATH can not contain a dot and neither can NAME. Also,
// NAME may not begin with a digit. NAME may require further encoding // NAME may not begin with a digit. NAME may require further encoding
// for non-ASCII characters as described below, but until that // for non-ASCII characters as described below, but until that
...@@ -188,12 +188,17 @@ ...@@ -188,12 +188,17 @@
// encoding unambiguous, we introduce it with two consecutive dots. // encoding unambiguous, we introduce it with two consecutive dots.
// This is followed by the letter u and four hex digits or the letter // This is followed by the letter u and four hex digits or the letter
// U and eight digits, just as in the language only using ..u and ..U // U and eight digits, just as in the language only using ..u and ..U
// instead of \u and \U. Since before this encoding names can never // instead of \u and \U. The compiler also produces identifiers that
// contain consecutive dots followed by 'u' or 'U', and after this // are qualified by package path, which means that there may also be ASCII
// encoding "..u" and "..U" are followed by a known number of // characters that are not assembler-friendly (ex: '=', '/'). The encoding
// scheme translates such characters into the "..zNN" where NN is the
// hex value for the character. Since before this encoding names can never
// contain consecutive dots followed by 'z', 'u' or 'U', and after this
// encoding "..z", "..u" and "..U" are followed by a known number of
// characters, this is unambiguous. // characters, this is unambiguous.
// //
// Demangling these names is straightforward: // Demangling these names is straightforward:
// - replace ..zXX with an ASCII character
// - replace ..uXXXX with a unicode character // - replace ..uXXXX with a unicode character
// - replace ..UXXXXXXXX with a unicode character // - replace ..UXXXXXXXX with a unicode character
// - replace .D, where D is a digit, with the character from the above // - replace .D, where D is a digit, with the character from the above
...@@ -215,9 +220,9 @@ Gogo::function_asm_name(const std::string& go_name, const Package* package, ...@@ -215,9 +220,9 @@ Gogo::function_asm_name(const std::string& go_name, const Package* package,
if (rtype != NULL) if (rtype != NULL)
ret = rtype->deref()->mangled_name(this); ret = rtype->deref()->mangled_name(this);
else if (package == NULL) else if (package == NULL)
ret = this->pkgpath_symbol(); ret = this->pkgpath();
else else
ret = package->pkgpath_symbol(); ret = package->pkgpath();
ret.push_back('.'); ret.push_back('.');
// Check for special names that will break if we use // Check for special names that will break if we use
// Gogo::unpack_hidden_name. // Gogo::unpack_hidden_name.
...@@ -268,7 +273,7 @@ Gogo::stub_method_name(const Package* package, const std::string& mname) ...@@ -268,7 +273,7 @@ Gogo::stub_method_name(const Package* package, const std::string& mname)
// We are creating a stub method for an unexported method of an // We are creating a stub method for an unexported method of an
// imported embedded type. We need to disambiguate the method name. // imported embedded type. We need to disambiguate the method name.
std::string ret = this->pkgpath_symbol_for_package(mpkgpath); std::string ret = mpkgpath;
ret.push_back('.'); ret.push_back('.');
ret.append(Gogo::unpack_hidden_name(mname)); ret.append(Gogo::unpack_hidden_name(mname));
ret.append("..stub"); ret.append("..stub");
...@@ -302,9 +307,9 @@ Gogo::global_var_asm_name(const std::string& go_name, const Package* package) ...@@ -302,9 +307,9 @@ Gogo::global_var_asm_name(const std::string& go_name, const Package* package)
{ {
std::string ret; std::string ret;
if (package == NULL) if (package == NULL)
ret = this->pkgpath_symbol(); ret = this->pkgpath();
else else
ret = package->pkgpath_symbol(); ret = package->pkgpath();
ret.append(1, '.'); ret.append(1, '.');
ret.append(Gogo::unpack_hidden_name(go_name)); ret.append(Gogo::unpack_hidden_name(go_name));
return go_encode_id(ret); return go_encode_id(ret);
...@@ -341,7 +346,7 @@ Gogo::thunk_name() ...@@ -341,7 +346,7 @@ Gogo::thunk_name()
char thunk_name[50]; char thunk_name[50];
snprintf(thunk_name, sizeof thunk_name, "..thunk%d", thunk_count); snprintf(thunk_name, sizeof thunk_name, "..thunk%d", thunk_count);
++thunk_count; ++thunk_count;
std::string ret = this->pkgpath_symbol(); std::string ret = this->pkgpath();
return ret + thunk_name; return ret + thunk_name;
} }
...@@ -370,7 +375,7 @@ Gogo::init_function_name() ...@@ -370,7 +375,7 @@ Gogo::init_function_name()
char buf[30]; char buf[30];
snprintf(buf, sizeof buf, "..init%d", init_count); snprintf(buf, sizeof buf, "..init%d", init_count);
++init_count; ++init_count;
std::string ret = this->pkgpath_symbol(); std::string ret = this->pkgpath();
return ret + buf; return ret + buf;
} }
...@@ -726,7 +731,7 @@ Struct_type::do_mangled_name(Gogo* gogo, std::string* ret) const ...@@ -726,7 +731,7 @@ Struct_type::do_mangled_name(Gogo* gogo, std::string* ret) const
if (!p->is_anonymous()) if (!p->is_anonymous())
{ {
ret->append(Gogo::mangle_possibly_hidden_name(p->field_name())); Gogo::append_possibly_hidden_name(ret, p->field_name());
ret->push_back(' '); ret->push_back(' ');
} }
...@@ -827,7 +832,7 @@ Interface_type::do_mangled_name(Gogo* gogo, std::string* ret) const ...@@ -827,7 +832,7 @@ Interface_type::do_mangled_name(Gogo* gogo, std::string* ret) const
if (!p->name().empty()) if (!p->name().empty())
{ {
ret->append(Gogo::mangle_possibly_hidden_name(p->name())); Gogo::append_possibly_hidden_name(ret, p->name());
ret->push_back(' '); ret->push_back(' ');
} }
...@@ -854,9 +859,9 @@ Forward_declaration_type::do_mangled_name(Gogo* gogo, std::string* ret) const ...@@ -854,9 +859,9 @@ Forward_declaration_type::do_mangled_name(Gogo* gogo, std::string* ret) const
{ {
const Named_object* no = this->named_object(); const Named_object* no = this->named_object();
if (no->package() == NULL) if (no->package() == NULL)
ret->append(gogo->pkgpath_symbol()); ret->append(gogo->pkgpath());
else else
ret->append(no->package()->pkgpath_symbol()); ret->append(no->package()->pkgpath());
ret->push_back('.'); ret->push_back('.');
ret->append(Gogo::unpack_hidden_name(no->name())); ret->append(Gogo::unpack_hidden_name(no->name()));
} }
...@@ -894,18 +899,18 @@ Named_type::append_mangled_type_name(Gogo* gogo, bool use_alias, ...@@ -894,18 +899,18 @@ Named_type::append_mangled_type_name(Gogo* gogo, bool use_alias,
if (rcvr != NULL) if (rcvr != NULL)
ret->append(rcvr->type()->deref()->mangled_name(gogo)); ret->append(rcvr->type()->deref()->mangled_name(gogo));
else if (this->in_function_->package() == NULL) else if (this->in_function_->package() == NULL)
ret->append(gogo->pkgpath_symbol()); ret->append(gogo->pkgpath());
else else
ret->append(this->in_function_->package()->pkgpath_symbol()); ret->append(this->in_function_->package()->pkgpath());
ret->push_back('.'); ret->push_back('.');
ret->append(Gogo::unpack_hidden_name(this->in_function_->name())); ret->append(Gogo::unpack_hidden_name(this->in_function_->name()));
} }
else else
{ {
if (no->package() == NULL) if (no->package() == NULL)
ret->append(gogo->pkgpath_symbol()); ret->append(gogo->pkgpath());
else else
ret->append(no->package()->pkgpath_symbol()); ret->append(no->package()->pkgpath());
} }
ret->push_back('.'); ret->push_back('.');
} }
...@@ -951,22 +956,22 @@ Gogo::type_descriptor_name(Type* type, Named_type* nt) ...@@ -951,22 +956,22 @@ Gogo::type_descriptor_name(Type* type, Named_type* nt)
if (rcvr != NULL) if (rcvr != NULL)
ret.append(rcvr->type()->deref()->mangled_name(this)); ret.append(rcvr->type()->deref()->mangled_name(this));
else if (in_function->package() == NULL) else if (in_function->package() == NULL)
ret.append(this->pkgpath_symbol()); ret.append(this->pkgpath());
else else
ret.append(in_function->package()->pkgpath_symbol()); ret.append(in_function->package()->pkgpath());
ret.push_back('.'); ret.push_back('.');
ret.append(Gogo::unpack_hidden_name(in_function->name())); ret.append(Gogo::unpack_hidden_name(in_function->name()));
ret.push_back('.'); ret.push_back('.');
} }
if (no->package() == NULL) if (no->package() == NULL)
ret.append(this->pkgpath_symbol()); ret.append(this->pkgpath());
else else
ret.append(no->package()->pkgpath_symbol()); ret.append(no->package()->pkgpath());
ret.push_back('.'); ret.push_back('.');
} }
ret.append(Gogo::mangle_possibly_hidden_name(no->name())); Gogo::append_possibly_hidden_name(&ret, no->name());
if (in_function != NULL && index > 0) if (in_function != NULL && index > 0)
{ {
......
...@@ -229,6 +229,8 @@ var exportHeader = flag.String("exportheader", "", "where to write export header ...@@ -229,6 +229,8 @@ var exportHeader = flag.String("exportheader", "", "where to write export header
var gccgo = flag.Bool("gccgo", false, "generate files for use with gccgo") var gccgo = flag.Bool("gccgo", false, "generate files for use with gccgo")
var gccgoprefix = flag.String("gccgoprefix", "", "-fgo-prefix option used with gccgo") var gccgoprefix = flag.String("gccgoprefix", "", "-fgo-prefix option used with gccgo")
var gccgopkgpath = flag.String("gccgopkgpath", "", "-fgo-pkgpath option used with gccgo") var gccgopkgpath = flag.String("gccgopkgpath", "", "-fgo-pkgpath option used with gccgo")
var gccgoMangleCheckDone bool
var gccgoNewmanglingInEffect bool
var importRuntimeCgo = flag.Bool("import_runtime_cgo", true, "import runtime/cgo in generated code") var importRuntimeCgo = flag.Bool("import_runtime_cgo", true, "import runtime/cgo in generated code")
var importSyscall = flag.Bool("import_syscall", true, "import syscall in generated code") var importSyscall = flag.Bool("import_syscall", true, "import syscall in generated code")
var goarch, goos string var goarch, goos string
......
...@@ -15,7 +15,9 @@ import ( ...@@ -15,7 +15,9 @@ import (
"go/printer" "go/printer"
"go/token" "go/token"
"io" "io"
"io/ioutil"
"os" "os"
"os/exec"
"path/filepath" "path/filepath"
"regexp" "regexp"
"sort" "sort"
...@@ -1191,12 +1193,91 @@ func (p *Package) writeExportHeader(fgcch io.Writer) { ...@@ -1191,12 +1193,91 @@ func (p *Package) writeExportHeader(fgcch io.Writer) {
fmt.Fprintf(fgcch, "%s\n", p.gccExportHeaderProlog()) fmt.Fprintf(fgcch, "%s\n", p.gccExportHeaderProlog())
} }
// Return the package prefix when using gccgo. // gccgoUsesNewMangling returns whether gccgo uses the new collision-free
func (p *Package) gccgoSymbolPrefix() string { // packagepath mangling scheme (see determineGccgoManglingScheme for more
if !*gccgo { // info).
return "" func gccgoUsesNewMangling() bool {
if !gccgoMangleCheckDone {
gccgoNewmanglingInEffect = determineGccgoManglingScheme()
gccgoMangleCheckDone = true
}
return gccgoNewmanglingInEffect
}
const mangleCheckCode = `
package läufer
func Run(x int) int {
return 1
}
`
// determineGccgoManglingScheme performs a runtime test to see which
// flavor of packagepath mangling gccgo is using. Older versions of
// gccgo use a simple mangling scheme where there can be collisions
// between packages whose paths are different but mangle to the same
// string. More recent versions of gccgo use a new mangler that avoids
// these collisions. Return value is whether gccgo uses the new mangling.
func determineGccgoManglingScheme() bool {
// Emit a small Go file for gccgo to compile.
filepat := "*_gccgo_manglecheck.go"
var f *os.File
var err error
if f, err = ioutil.TempFile(*objDir, filepat); err != nil {
fatalf("%v", err)
}
gofilename := f.Name()
defer os.Remove(gofilename)
if err = ioutil.WriteFile(gofilename, []byte(mangleCheckCode), 0666); err != nil {
fatalf("%v", err)
}
// Compile with gccgo, capturing generated assembly.
gccgocmd := os.Getenv("GCCGO")
if gccgocmd == "" {
gpath, gerr := exec.LookPath("gccgo")
if gerr != nil {
fatalf("unable to locate gccgo: %v", gerr)
}
gccgocmd = gpath
}
cmd := exec.Command(gccgocmd, "-S", "-o", "-", gofilename)
buf, cerr := cmd.CombinedOutput()
if cerr != nil {
fatalf("%s", err)
}
// New mangling: expect go.l..u00e4ufer.Run
// Old mangling: expect go.l__ufer.Run
return regexp.MustCompile(`go\.l\.\.u00e4ufer\.Run`).Match(buf)
}
// gccgoPkgpathToSymbolNew converts a package path to a gccgo-style
// package symbol.
func gccgoPkgpathToSymbolNew(ppath string) string {
bsl := []byte{}
changed := false
for _, c := range []byte(ppath) {
switch {
case 'A' <= c && c <= 'Z', 'a' <= c && c <= 'z',
'0' <= c && c <= '9', '_' == c:
bsl = append(bsl, c)
default:
changed = true
encbytes := []byte(fmt.Sprintf("..z%02x", c))
bsl = append(bsl, encbytes...)
}
}
if !changed {
return ppath
} }
return string(bsl)
}
// gccgoPkgpathToSymbolOld converts a package path to a gccgo-style
// package symbol using the older mangling scheme.
func gccgoPkgpathToSymbolOld(ppath string) string {
clean := func(r rune) rune { clean := func(r rune) rune {
switch { switch {
case 'A' <= r && r <= 'Z', 'a' <= r && r <= 'z', case 'A' <= r && r <= 'Z', 'a' <= r && r <= 'z',
...@@ -1205,14 +1286,32 @@ func (p *Package) gccgoSymbolPrefix() string { ...@@ -1205,14 +1286,32 @@ func (p *Package) gccgoSymbolPrefix() string {
} }
return '_' return '_'
} }
return strings.Map(clean, ppath)
}
// gccgoPkgpathToSymbol converts a package path to a mangled packagepath
// symbol.
func gccgoPkgpathToSymbol(ppath string) string {
if gccgoUsesNewMangling() {
return gccgoPkgpathToSymbolNew(ppath)
} else {
return gccgoPkgpathToSymbolOld(ppath)
}
}
// Return the package prefix when using gccgo.
func (p *Package) gccgoSymbolPrefix() string {
if !*gccgo {
return ""
}
if *gccgopkgpath != "" { if *gccgopkgpath != "" {
return strings.Map(clean, *gccgopkgpath) return gccgoPkgpathToSymbol(*gccgopkgpath)
} }
if *gccgoprefix == "" && p.PackageName == "main" { if *gccgoprefix == "" && p.PackageName == "main" {
return "main" return "main"
} }
prefix := strings.Map(clean, *gccgoprefix) prefix := gccgoPkgpathToSymbol(*gccgoprefix)
if prefix == "" { if prefix == "" {
prefix = "go" prefix = "go"
} }
......
...@@ -38,7 +38,7 @@ static const void *goMemmem(const void *in, size_t inl, const void *s, size_t sl ...@@ -38,7 +38,7 @@ static const void *goMemmem(const void *in, size_t inl, const void *s, size_t sl
#endif #endif
intgo Compare(struct __go_open_array, struct __go_open_array) intgo Compare(struct __go_open_array, struct __go_open_array)
__asm__(GOSYM_PREFIX "internal_bytealg.Compare") __asm__(GOSYM_PREFIX "internal..z2fbytealg.Compare")
__attribute__((no_split_stack)); __attribute__((no_split_stack));
intgo Compare(struct __go_open_array a, struct __go_open_array b) intgo Compare(struct __go_open_array a, struct __go_open_array b)
...@@ -67,7 +67,7 @@ intgo Compare(struct __go_open_array a, struct __go_open_array b) ...@@ -67,7 +67,7 @@ intgo Compare(struct __go_open_array a, struct __go_open_array b)
} }
_Bool Equal(struct __go_open_array, struct __go_open_array) _Bool Equal(struct __go_open_array, struct __go_open_array)
__asm__(GOSYM_PREFIX "internal_bytealg.Equal") __asm__(GOSYM_PREFIX "internal..z2fbytealg.Equal")
__attribute__((no_split_stack)); __attribute__((no_split_stack));
_Bool Equal(struct __go_open_array a, struct __go_open_array b) _Bool Equal(struct __go_open_array a, struct __go_open_array b)
...@@ -82,7 +82,7 @@ _Bool Equal(struct __go_open_array a, struct __go_open_array b) ...@@ -82,7 +82,7 @@ _Bool Equal(struct __go_open_array a, struct __go_open_array b)
} }
intgo IndexByte(struct __go_open_array, byte) intgo IndexByte(struct __go_open_array, byte)
__asm__(GOSYM_PREFIX "internal_bytealg.IndexByte") __asm__(GOSYM_PREFIX "internal..z2fbytealg.IndexByte")
__attribute__((no_split_stack)); __attribute__((no_split_stack));
intgo IndexByte(struct __go_open_array b, byte c) intgo IndexByte(struct __go_open_array b, byte c)
...@@ -98,7 +98,7 @@ intgo IndexByte(struct __go_open_array b, byte c) ...@@ -98,7 +98,7 @@ intgo IndexByte(struct __go_open_array b, byte c)
intgo IndexByteString(String, byte) intgo IndexByteString(String, byte)
__asm__(GOSYM_PREFIX "internal_bytealg.IndexByteString") __asm__(GOSYM_PREFIX "internal..z2fbytealg.IndexByteString")
__attribute__((no_split_stack)); __attribute__((no_split_stack));
intgo IndexByteString(String s, byte c) intgo IndexByteString(String s, byte c)
...@@ -113,7 +113,7 @@ intgo IndexByteString(String s, byte c) ...@@ -113,7 +113,7 @@ intgo IndexByteString(String s, byte c)
} }
intgo Index(struct __go_open_array, struct __go_open_array) intgo Index(struct __go_open_array, struct __go_open_array)
__asm__(GOSYM_PREFIX "internal_bytealg.Index") __asm__(GOSYM_PREFIX "internal..z2fbytealg.Index")
__attribute__((no_split_stack)); __attribute__((no_split_stack));
intgo Index(struct __go_open_array a, struct __go_open_array b) intgo Index(struct __go_open_array a, struct __go_open_array b)
...@@ -128,7 +128,7 @@ intgo Index(struct __go_open_array a, struct __go_open_array b) ...@@ -128,7 +128,7 @@ intgo Index(struct __go_open_array a, struct __go_open_array b)
} }
intgo IndexString(String, String) intgo IndexString(String, String)
__asm__(GOSYM_PREFIX "internal_bytealg.IndexString") __asm__(GOSYM_PREFIX "internal..z2fbytealg.IndexString")
__attribute__((no_split_stack)); __attribute__((no_split_stack));
intgo IndexString(String a, String b) intgo IndexString(String a, String b)
......
...@@ -21,7 +21,7 @@ struct cpuid_ret { ...@@ -21,7 +21,7 @@ struct cpuid_ret {
}; };
struct cpuid_ret cpuid(uint32_t, uint32_t) struct cpuid_ret cpuid(uint32_t, uint32_t)
__asm__(GOSYM_PREFIX "internal_cpu.cpuid") __asm__(GOSYM_PREFIX "internal..z2fcpu.cpuid")
__attribute__((no_split_stack)); __attribute__((no_split_stack));
struct cpuid_ret cpuid(uint32_t eaxArg, uint32_t ecxArg) { struct cpuid_ret cpuid(uint32_t eaxArg, uint32_t ecxArg) {
...@@ -45,7 +45,7 @@ struct xgetbv_ret { ...@@ -45,7 +45,7 @@ struct xgetbv_ret {
}; };
struct xgetbv_ret xgetbv(void) struct xgetbv_ret xgetbv(void)
__asm__(GOSYM_PREFIX "internal_cpu.xgetbv") __asm__(GOSYM_PREFIX "internal..z2fcpu.xgetbv")
__attribute__((no_split_stack)); __attribute__((no_split_stack));
#pragma GCC push_options #pragma GCC push_options
......
...@@ -52,10 +52,10 @@ func casp(ptr *unsafe.Pointer, old, new unsafe.Pointer) bool { ...@@ -52,10 +52,10 @@ func casp(ptr *unsafe.Pointer, old, new unsafe.Pointer) bool {
// We cannot just call the runtime routines, because the race detector expects // We cannot just call the runtime routines, because the race detector expects
// to be able to intercept the sync/atomic forms but not the runtime forms. // to be able to intercept the sync/atomic forms but not the runtime forms.
//go:linkname sync_atomic_StoreUintptr sync_atomic.StoreUintptr //go:linkname sync_atomic_StoreUintptr sync..z2fatomic.StoreUintptr
func sync_atomic_StoreUintptr(ptr *uintptr, new uintptr) func sync_atomic_StoreUintptr(ptr *uintptr, new uintptr)
//go:linkname sync_atomic_StorePointer sync_atomic.StorePointer //go:linkname sync_atomic_StorePointer sync..z2fatomic.StorePointer
//go:nosplit //go:nosplit
func sync_atomic_StorePointer(ptr *unsafe.Pointer, new unsafe.Pointer) { func sync_atomic_StorePointer(ptr *unsafe.Pointer, new unsafe.Pointer) {
if writeBarrier.enabled { if writeBarrier.enabled {
...@@ -64,10 +64,10 @@ func sync_atomic_StorePointer(ptr *unsafe.Pointer, new unsafe.Pointer) { ...@@ -64,10 +64,10 @@ func sync_atomic_StorePointer(ptr *unsafe.Pointer, new unsafe.Pointer) {
sync_atomic_StoreUintptr((*uintptr)(unsafe.Pointer(ptr)), uintptr(new)) sync_atomic_StoreUintptr((*uintptr)(unsafe.Pointer(ptr)), uintptr(new))
} }
//go:linkname sync_atomic_SwapUintptr sync_atomic.SwapUintptr //go:linkname sync_atomic_SwapUintptr sync..z2fatomic.SwapUintptr
func sync_atomic_SwapUintptr(ptr *uintptr, new uintptr) uintptr func sync_atomic_SwapUintptr(ptr *uintptr, new uintptr) uintptr
//go:linkname sync_atomic_SwapPointer sync_atomic.SwapPointer //go:linkname sync_atomic_SwapPointer sync..z2fatomic.SwapPointer
//go:nosplit //go:nosplit
func sync_atomic_SwapPointer(ptr *unsafe.Pointer, new unsafe.Pointer) unsafe.Pointer { func sync_atomic_SwapPointer(ptr *unsafe.Pointer, new unsafe.Pointer) unsafe.Pointer {
if writeBarrier.enabled { if writeBarrier.enabled {
...@@ -77,10 +77,10 @@ func sync_atomic_SwapPointer(ptr *unsafe.Pointer, new unsafe.Pointer) unsafe.Poi ...@@ -77,10 +77,10 @@ func sync_atomic_SwapPointer(ptr *unsafe.Pointer, new unsafe.Pointer) unsafe.Poi
return old return old
} }
//go:linkname sync_atomic_CompareAndSwapUintptr sync_atomic.CompareAndSwapUintptr //go:linkname sync_atomic_CompareAndSwapUintptr sync..z2fatomic.CompareAndSwapUintptr
func sync_atomic_CompareAndSwapUintptr(ptr *uintptr, old, new uintptr) bool func sync_atomic_CompareAndSwapUintptr(ptr *uintptr, old, new uintptr) bool
//go:linkname sync_atomic_CompareAndSwapPointer sync_atomic.CompareAndSwapPointer //go:linkname sync_atomic_CompareAndSwapPointer sync..z2fatomic.CompareAndSwapPointer
//go:nosplit //go:nosplit
func sync_atomic_CompareAndSwapPointer(ptr *unsafe.Pointer, old, new unsafe.Pointer) bool { func sync_atomic_CompareAndSwapPointer(ptr *unsafe.Pointer, old, new unsafe.Pointer) bool {
if writeBarrier.enabled { if writeBarrier.enabled {
......
...@@ -186,7 +186,7 @@ func CPUProfile() []byte { ...@@ -186,7 +186,7 @@ func CPUProfile() []byte {
panic("CPUProfile no longer available") panic("CPUProfile no longer available")
} }
//go:linkname runtime_pprof_runtime_cyclesPerSecond runtime_pprof.runtime_cyclesPerSecond //go:linkname runtime_pprof_runtime_cyclesPerSecond runtime..z2fpprof.runtime_cyclesPerSecond
func runtime_pprof_runtime_cyclesPerSecond() int64 { func runtime_pprof_runtime_cyclesPerSecond() int64 {
return tickspersecond() return tickspersecond()
} }
...@@ -197,7 +197,7 @@ func runtime_pprof_runtime_cyclesPerSecond() int64 { ...@@ -197,7 +197,7 @@ func runtime_pprof_runtime_cyclesPerSecond() int64 {
// on has been returned, readProfile returns eof=true. // on has been returned, readProfile returns eof=true.
// The caller must save the returned data and tags before calling readProfile again. // The caller must save the returned data and tags before calling readProfile again.
// //
//go:linkname runtime_pprof_readProfile runtime_pprof.readProfile //go:linkname runtime_pprof_readProfile runtime..z2fpprof.readProfile
func runtime_pprof_readProfile() ([]uint64, []unsafe.Pointer, bool) { func runtime_pprof_readProfile() ([]uint64, []unsafe.Pointer, bool) {
lock(&cpuprof.lock) lock(&cpuprof.lock)
log := cpuprof.log log := cpuprof.log
......
...@@ -51,10 +51,10 @@ func TestStack(t *testing.T) { ...@@ -51,10 +51,10 @@ func TestStack(t *testing.T) {
n++ n++
} }
n++ n++
frame("stack.go", "runtime_debug.Stack") frame("stack.go", "debug.Stack")
frame("stack_test.go", "ptrmethod") frame("stack_test.go", "ptrmethod")
frame("stack_test.go", "method") frame("stack_test.go", "method")
frame("stack_test.go", "runtime_debug_test.TestStack") frame("stack_test.go", "test.TestStack")
frame("testing.go", "") frame("testing.go", "")
} }
......
...@@ -16,7 +16,7 @@ import ( ...@@ -16,7 +16,7 @@ import (
"unsafe" "unsafe"
) )
//go:linkname runtime_debug_WriteHeapDump runtime_debug.WriteHeapDump //go:linkname runtime_debug_WriteHeapDump runtime..z2fdebug.WriteHeapDump
func runtime_debug_WriteHeapDump(fd uintptr) { func runtime_debug_WriteHeapDump(fd uintptr) {
stopTheWorld("write heap dump") stopTheWorld("write heap dump")
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
#include "runtime.h" #include "runtime.h"
uint32_t Load (uint32_t *ptr) uint32_t Load (uint32_t *ptr)
__asm__ (GOSYM_PREFIX "runtime_internal_atomic.Load") __asm__ (GOSYM_PREFIX "runtime..z2finternal..z2fatomic.Load")
__attribute__ ((no_split_stack)); __attribute__ ((no_split_stack));
uint32_t uint32_t
...@@ -17,7 +17,7 @@ Load (uint32_t *ptr) ...@@ -17,7 +17,7 @@ Load (uint32_t *ptr)
} }
void *Loadp (void *ptr) void *Loadp (void *ptr)
__asm__ (GOSYM_PREFIX "runtime_internal_atomic.Loadp") __asm__ (GOSYM_PREFIX "runtime..z2finternal..z2fatomic.Loadp")
__attribute__ ((no_split_stack)); __attribute__ ((no_split_stack));
void * void *
...@@ -27,7 +27,7 @@ Loadp (void *ptr) ...@@ -27,7 +27,7 @@ Loadp (void *ptr)
} }
uint64_t Load64 (uint64_t *ptr) uint64_t Load64 (uint64_t *ptr)
__asm__ (GOSYM_PREFIX "runtime_internal_atomic.Load64") __asm__ (GOSYM_PREFIX "runtime..z2finternal..z2fatomic.Load64")
__attribute__ ((no_split_stack)); __attribute__ ((no_split_stack));
uint64_t uint64_t
...@@ -39,7 +39,7 @@ Load64 (uint64_t *ptr) ...@@ -39,7 +39,7 @@ Load64 (uint64_t *ptr)
} }
uintptr_t Loaduintptr (uintptr_t *ptr) uintptr_t Loaduintptr (uintptr_t *ptr)
__asm__ (GOSYM_PREFIX "runtime_internal_atomic.Loaduintptr") __asm__ (GOSYM_PREFIX "runtime..z2finternal..z2fatomic.Loaduintptr")
__attribute__ ((no_split_stack)); __attribute__ ((no_split_stack));
uintptr_t uintptr_t
...@@ -49,7 +49,7 @@ Loaduintptr (uintptr_t *ptr) ...@@ -49,7 +49,7 @@ Loaduintptr (uintptr_t *ptr)
} }
uintgo Loaduint (uintgo *ptr) uintgo Loaduint (uintgo *ptr)
__asm__ (GOSYM_PREFIX "runtime_internal_atomic.Loaduint") __asm__ (GOSYM_PREFIX "runtime..z2finternal..z2fatomic.Loaduint")
__attribute__ ((no_split_stack)); __attribute__ ((no_split_stack));
uintgo uintgo
...@@ -59,7 +59,7 @@ Loaduint (uintgo *ptr) ...@@ -59,7 +59,7 @@ Loaduint (uintgo *ptr)
} }
int64_t Loadint64 (int64_t *ptr) int64_t Loadint64 (int64_t *ptr)
__asm__ (GOSYM_PREFIX "runtime_internal_atomic.Loadint64") __asm__ (GOSYM_PREFIX "runtime..z2finternal..z2fatomic.Loadint64")
__attribute__ ((no_split_stack)); __attribute__ ((no_split_stack));
int64_t int64_t
...@@ -71,7 +71,7 @@ Loadint64 (int64_t *ptr) ...@@ -71,7 +71,7 @@ Loadint64 (int64_t *ptr)
} }
uint32_t Xadd (uint32_t *ptr, int32_t delta) uint32_t Xadd (uint32_t *ptr, int32_t delta)
__asm__ (GOSYM_PREFIX "runtime_internal_atomic.Xadd") __asm__ (GOSYM_PREFIX "runtime..z2finternal..z2fatomic.Xadd")
__attribute__ ((no_split_stack)); __attribute__ ((no_split_stack));
uint32_t uint32_t
...@@ -81,7 +81,7 @@ Xadd (uint32_t *ptr, int32_t delta) ...@@ -81,7 +81,7 @@ Xadd (uint32_t *ptr, int32_t delta)
} }
uint64_t Xadd64 (uint64_t *ptr, int64_t delta) uint64_t Xadd64 (uint64_t *ptr, int64_t delta)
__asm__ (GOSYM_PREFIX "runtime_internal_atomic.Xadd64") __asm__ (GOSYM_PREFIX "runtime..z2finternal..z2fatomic.Xadd64")
__attribute__ ((no_split_stack)); __attribute__ ((no_split_stack));
uint64_t uint64_t
...@@ -93,7 +93,7 @@ Xadd64 (uint64_t *ptr, int64_t delta) ...@@ -93,7 +93,7 @@ Xadd64 (uint64_t *ptr, int64_t delta)
} }
uintptr_t Xadduintptr (uintptr_t *ptr, uintptr_t delta) uintptr_t Xadduintptr (uintptr_t *ptr, uintptr_t delta)
__asm__ (GOSYM_PREFIX "runtime_internal_atomic.Xadduintptr") __asm__ (GOSYM_PREFIX "runtime..z2finternal..z2fatomic.Xadduintptr")
__attribute__ ((no_split_stack)); __attribute__ ((no_split_stack));
uintptr_t uintptr_t
...@@ -103,7 +103,7 @@ Xadduintptr (uintptr_t *ptr, uintptr_t delta) ...@@ -103,7 +103,7 @@ Xadduintptr (uintptr_t *ptr, uintptr_t delta)
} }
int64_t Xaddint64 (int64_t *ptr, int64_t delta) int64_t Xaddint64 (int64_t *ptr, int64_t delta)
__asm__ (GOSYM_PREFIX "runtime_internal_atomic.Xaddint64") __asm__ (GOSYM_PREFIX "runtime..z2finternal..z2fatomic.Xaddint64")
__attribute__ ((no_split_stack)); __attribute__ ((no_split_stack));
int64_t int64_t
...@@ -115,7 +115,7 @@ Xaddint64 (int64_t *ptr, int64_t delta) ...@@ -115,7 +115,7 @@ Xaddint64 (int64_t *ptr, int64_t delta)
} }
uint32_t Xchg (uint32_t *ptr, uint32_t new) uint32_t Xchg (uint32_t *ptr, uint32_t new)
__asm__ (GOSYM_PREFIX "runtime_internal_atomic.Xchg") __asm__ (GOSYM_PREFIX "runtime..z2finternal..z2fatomic.Xchg")
__attribute__ ((no_split_stack)); __attribute__ ((no_split_stack));
uint32_t uint32_t
...@@ -125,7 +125,7 @@ Xchg (uint32_t *ptr, uint32_t new) ...@@ -125,7 +125,7 @@ Xchg (uint32_t *ptr, uint32_t new)
} }
uint64_t Xchg64 (uint64_t *ptr, uint64_t new) uint64_t Xchg64 (uint64_t *ptr, uint64_t new)
__asm__ (GOSYM_PREFIX "runtime_internal_atomic.Xchg64") __asm__ (GOSYM_PREFIX "runtime..z2finternal..z2fatomic.Xchg64")
__attribute__ ((no_split_stack)); __attribute__ ((no_split_stack));
uint64_t uint64_t
...@@ -137,7 +137,7 @@ Xchg64 (uint64_t *ptr, uint64_t new) ...@@ -137,7 +137,7 @@ Xchg64 (uint64_t *ptr, uint64_t new)
} }
uintptr_t Xchguintptr (uintptr_t *ptr, uintptr_t new) uintptr_t Xchguintptr (uintptr_t *ptr, uintptr_t new)
__asm__ (GOSYM_PREFIX "runtime_internal_atomic.Xchguintptr") __asm__ (GOSYM_PREFIX "runtime..z2finternal..z2fatomic.Xchguintptr")
__attribute__ ((no_split_stack)); __attribute__ ((no_split_stack));
uintptr_t uintptr_t
...@@ -147,7 +147,7 @@ Xchguintptr (uintptr_t *ptr, uintptr_t new) ...@@ -147,7 +147,7 @@ Xchguintptr (uintptr_t *ptr, uintptr_t new)
} }
void And8 (uint8_t *ptr, uint8_t val) void And8 (uint8_t *ptr, uint8_t val)
__asm__ (GOSYM_PREFIX "runtime_internal_atomic.And8") __asm__ (GOSYM_PREFIX "runtime..z2finternal..z2fatomic.And8")
__attribute__ ((no_split_stack)); __attribute__ ((no_split_stack));
void void
...@@ -157,7 +157,7 @@ And8 (uint8_t *ptr, uint8_t val) ...@@ -157,7 +157,7 @@ And8 (uint8_t *ptr, uint8_t val)
} }
void Or8 (uint8_t *ptr, uint8_t val) void Or8 (uint8_t *ptr, uint8_t val)
__asm__ (GOSYM_PREFIX "runtime_internal_atomic.Or8") __asm__ (GOSYM_PREFIX "runtime..z2finternal..z2fatomic.Or8")
__attribute__ ((no_split_stack)); __attribute__ ((no_split_stack));
void void
...@@ -167,7 +167,7 @@ Or8 (uint8_t *ptr, uint8_t val) ...@@ -167,7 +167,7 @@ Or8 (uint8_t *ptr, uint8_t val)
} }
_Bool Cas (uint32_t *ptr, uint32_t old, uint32_t new) _Bool Cas (uint32_t *ptr, uint32_t old, uint32_t new)
__asm__ (GOSYM_PREFIX "runtime_internal_atomic.Cas") __asm__ (GOSYM_PREFIX "runtime..z2finternal..z2fatomic.Cas")
__attribute__ ((no_split_stack)); __attribute__ ((no_split_stack));
_Bool _Bool
...@@ -177,7 +177,7 @@ Cas (uint32_t *ptr, uint32_t old, uint32_t new) ...@@ -177,7 +177,7 @@ Cas (uint32_t *ptr, uint32_t old, uint32_t new)
} }
_Bool Cas64 (uint64_t *ptr, uint64_t old, uint64_t new) _Bool Cas64 (uint64_t *ptr, uint64_t old, uint64_t new)
__asm__ (GOSYM_PREFIX "runtime_internal_atomic.Cas64") __asm__ (GOSYM_PREFIX "runtime..z2finternal..z2fatomic.Cas64")
__attribute__ ((no_split_stack)); __attribute__ ((no_split_stack));
_Bool _Bool
...@@ -189,7 +189,7 @@ Cas64 (uint64_t *ptr, uint64_t old, uint64_t new) ...@@ -189,7 +189,7 @@ Cas64 (uint64_t *ptr, uint64_t old, uint64_t new)
} }
_Bool Casp1 (void **ptr, void *old, void *new) _Bool Casp1 (void **ptr, void *old, void *new)
__asm__ (GOSYM_PREFIX "runtime_internal_atomic.Casp1") __asm__ (GOSYM_PREFIX "runtime..z2finternal..z2fatomic.Casp1")
__attribute__ ((no_split_stack)); __attribute__ ((no_split_stack));
_Bool _Bool
...@@ -199,7 +199,7 @@ Casp1 (void **ptr, void *old, void *new) ...@@ -199,7 +199,7 @@ Casp1 (void **ptr, void *old, void *new)
} }
_Bool Casuintptr (uintptr_t *ptr, uintptr_t old, uintptr_t new) _Bool Casuintptr (uintptr_t *ptr, uintptr_t old, uintptr_t new)
__asm__ (GOSYM_PREFIX "runtime_internal_atomic.Casuintptr") __asm__ (GOSYM_PREFIX "runtime..z2finternal..z2fatomic.Casuintptr")
__attribute__ ((no_split_stack)); __attribute__ ((no_split_stack));
_Bool _Bool
...@@ -209,7 +209,7 @@ Casuintptr (uintptr_t *ptr, uintptr_t old, uintptr_t new) ...@@ -209,7 +209,7 @@ Casuintptr (uintptr_t *ptr, uintptr_t old, uintptr_t new)
} }
void Store (uint32_t *ptr, uint32_t val) void Store (uint32_t *ptr, uint32_t val)
__asm__ (GOSYM_PREFIX "runtime_internal_atomic.Store") __asm__ (GOSYM_PREFIX "runtime..z2finternal..z2fatomic.Store")
__attribute__ ((no_split_stack)); __attribute__ ((no_split_stack));
void void
...@@ -219,7 +219,7 @@ Store (uint32_t *ptr, uint32_t val) ...@@ -219,7 +219,7 @@ Store (uint32_t *ptr, uint32_t val)
} }
void Store64 (uint64_t *ptr, uint64_t val) void Store64 (uint64_t *ptr, uint64_t val)
__asm__ (GOSYM_PREFIX "runtime_internal_atomic.Store64") __asm__ (GOSYM_PREFIX "runtime..z2finternal..z2fatomic.Store64")
__attribute__ ((no_split_stack)); __attribute__ ((no_split_stack));
void void
...@@ -231,7 +231,7 @@ Store64 (uint64_t *ptr, uint64_t val) ...@@ -231,7 +231,7 @@ Store64 (uint64_t *ptr, uint64_t val)
} }
void Storeuintptr (uintptr_t *ptr, uintptr_t val) void Storeuintptr (uintptr_t *ptr, uintptr_t val)
__asm__ (GOSYM_PREFIX "runtime_internal_atomic.Storeuintptr") __asm__ (GOSYM_PREFIX "runtime..z2finternal..z2fatomic.Storeuintptr")
__attribute__ ((no_split_stack)); __attribute__ ((no_split_stack));
void void
...@@ -241,7 +241,7 @@ Storeuintptr (uintptr_t *ptr, uintptr_t val) ...@@ -241,7 +241,7 @@ Storeuintptr (uintptr_t *ptr, uintptr_t val)
} }
void StorepNoWB (void *ptr, void *val) void StorepNoWB (void *ptr, void *val)
__asm__ (GOSYM_PREFIX "runtime_internal_atomic.StorepNoWB") __asm__ (GOSYM_PREFIX "runtime..z2finternal..z2fatomic.StorepNoWB")
__attribute__ ((no_split_stack)); __attribute__ ((no_split_stack));
void void
......
...@@ -219,7 +219,7 @@ func gcenable() { ...@@ -219,7 +219,7 @@ func gcenable() {
memstats.enablegc = true // now that runtime is initialized, GC is okay memstats.enablegc = true // now that runtime is initialized, GC is okay
} }
//go:linkname setGCPercent runtime_debug.setGCPercent //go:linkname setGCPercent runtime..z2fdebug.setGCPercent
func setGCPercent(in int32) (out int32) { func setGCPercent(in int32) (out int32) {
lock(&mheap_.lock) lock(&mheap_.lock)
out = gcpercent out = gcpercent
......
...@@ -1165,7 +1165,7 @@ func (h *mheap) scavenge(k int32, now, limit uint64) { ...@@ -1165,7 +1165,7 @@ func (h *mheap) scavenge(k int32, now, limit uint64) {
} }
} }
//go:linkname runtime_debug_freeOSMemory runtime_debug.freeOSMemory //go:linkname runtime_debug_freeOSMemory runtime..z2fdebug.freeOSMemory
func runtime_debug_freeOSMemory() { func runtime_debug_freeOSMemory() {
GC() GC()
systemstack(func() { mheap_.scavenge(-1, ^uint64(0), 0) }) systemstack(func() { mheap_.scavenge(-1, ^uint64(0), 0) })
......
...@@ -477,7 +477,7 @@ func readmemstats_m(stats *MemStats) { ...@@ -477,7 +477,7 @@ func readmemstats_m(stats *MemStats) {
stats.StackSys += stats.StackInuse stats.StackSys += stats.StackInuse
} }
//go:linkname readGCStats runtime_debug.readGCStats //go:linkname readGCStats runtime..z2fdebug.readGCStats
func readGCStats(pauses *[]uint64) { func readGCStats(pauses *[]uint64) {
systemstack(func() { systemstack(func() {
readGCStats_m(pauses) readGCStats_m(pauses)
......
...@@ -8,12 +8,12 @@ import ( ...@@ -8,12 +8,12 @@ import (
_ "unsafe" _ "unsafe"
) )
//go:linkname runtime_ignoreHangup internal_poll.runtime_ignoreHangup //go:linkname runtime_ignoreHangup internal..z2fpoll.runtime_ignoreHangup
func runtime_ignoreHangup() { func runtime_ignoreHangup() {
getg().m.ignoreHangup = true getg().m.ignoreHangup = true
} }
//go:linkname runtime_unignoreHangup internal_poll.runtime_unignoreHangup //go:linkname runtime_unignoreHangup internal..z2fpoll.runtime_unignoreHangup
func runtime_unignoreHangup(sig string) { func runtime_unignoreHangup(sig string) {
getg().m.ignoreHangup = false getg().m.ignoreHangup = false
} }
......
...@@ -85,7 +85,7 @@ var ( ...@@ -85,7 +85,7 @@ var (
netpollWaiters uint32 netpollWaiters uint32
) )
//go:linkname poll_runtime_pollServerInit internal_poll.runtime_pollServerInit //go:linkname poll_runtime_pollServerInit internal..z2fpoll.runtime_pollServerInit
func poll_runtime_pollServerInit() { func poll_runtime_pollServerInit() {
netpollinit() netpollinit()
atomic.Store(&netpollInited, 1) atomic.Store(&netpollInited, 1)
...@@ -95,7 +95,7 @@ func netpollinited() bool { ...@@ -95,7 +95,7 @@ func netpollinited() bool {
return atomic.Load(&netpollInited) != 0 return atomic.Load(&netpollInited) != 0
} }
//go:linkname poll_runtime_pollServerDescriptor internal_poll.runtime_pollServerDescriptor //go:linkname poll_runtime_pollServerDescriptor internal..z2fpoll.runtime_pollServerDescriptor
// poll_runtime_pollServerDescriptor returns the descriptor being used, // poll_runtime_pollServerDescriptor returns the descriptor being used,
// or ^uintptr(0) if the system does not use a poll descriptor. // or ^uintptr(0) if the system does not use a poll descriptor.
...@@ -103,7 +103,7 @@ func poll_runtime_pollServerDescriptor() uintptr { ...@@ -103,7 +103,7 @@ func poll_runtime_pollServerDescriptor() uintptr {
return netpolldescriptor() return netpolldescriptor()
} }
//go:linkname poll_runtime_pollOpen internal_poll.runtime_pollOpen //go:linkname poll_runtime_pollOpen internal..z2fpoll.runtime_pollOpen
func poll_runtime_pollOpen(fd uintptr) (*pollDesc, int) { func poll_runtime_pollOpen(fd uintptr) (*pollDesc, int) {
pd := pollcache.alloc() pd := pollcache.alloc()
lock(&pd.lock) lock(&pd.lock)
...@@ -127,7 +127,7 @@ func poll_runtime_pollOpen(fd uintptr) (*pollDesc, int) { ...@@ -127,7 +127,7 @@ func poll_runtime_pollOpen(fd uintptr) (*pollDesc, int) {
return pd, int(errno) return pd, int(errno)
} }
//go:linkname poll_runtime_pollClose internal_poll.runtime_pollClose //go:linkname poll_runtime_pollClose internal..z2fpoll.runtime_pollClose
func poll_runtime_pollClose(pd *pollDesc) { func poll_runtime_pollClose(pd *pollDesc) {
if !pd.closing { if !pd.closing {
throw("runtime: close polldesc w/o unblock") throw("runtime: close polldesc w/o unblock")
...@@ -149,7 +149,7 @@ func (c *pollCache) free(pd *pollDesc) { ...@@ -149,7 +149,7 @@ func (c *pollCache) free(pd *pollDesc) {
unlock(&c.lock) unlock(&c.lock)
} }
//go:linkname poll_runtime_pollReset internal_poll.runtime_pollReset //go:linkname poll_runtime_pollReset internal..z2fpoll.runtime_pollReset
func poll_runtime_pollReset(pd *pollDesc, mode int) int { func poll_runtime_pollReset(pd *pollDesc, mode int) int {
err := netpollcheckerr(pd, int32(mode)) err := netpollcheckerr(pd, int32(mode))
if err != 0 { if err != 0 {
...@@ -163,7 +163,7 @@ func poll_runtime_pollReset(pd *pollDesc, mode int) int { ...@@ -163,7 +163,7 @@ func poll_runtime_pollReset(pd *pollDesc, mode int) int {
return 0 return 0
} }
//go:linkname poll_runtime_pollWait internal_poll.runtime_pollWait //go:linkname poll_runtime_pollWait internal..z2fpoll.runtime_pollWait
func poll_runtime_pollWait(pd *pollDesc, mode int) int { func poll_runtime_pollWait(pd *pollDesc, mode int) int {
err := netpollcheckerr(pd, int32(mode)) err := netpollcheckerr(pd, int32(mode))
if err != 0 { if err != 0 {
...@@ -185,7 +185,7 @@ func poll_runtime_pollWait(pd *pollDesc, mode int) int { ...@@ -185,7 +185,7 @@ func poll_runtime_pollWait(pd *pollDesc, mode int) int {
return 0 return 0
} }
//go:linkname poll_runtime_pollWaitCanceled internal_poll.runtime_pollWaitCanceled //go:linkname poll_runtime_pollWaitCanceled internal..z2fpoll.runtime_pollWaitCanceled
func poll_runtime_pollWaitCanceled(pd *pollDesc, mode int) { func poll_runtime_pollWaitCanceled(pd *pollDesc, mode int) {
// This function is used only on windows after a failed attempt to cancel // This function is used only on windows after a failed attempt to cancel
// a pending async IO operation. Wait for ioready, ignore closing or timeouts. // a pending async IO operation. Wait for ioready, ignore closing or timeouts.
...@@ -193,7 +193,7 @@ func poll_runtime_pollWaitCanceled(pd *pollDesc, mode int) { ...@@ -193,7 +193,7 @@ func poll_runtime_pollWaitCanceled(pd *pollDesc, mode int) {
} }
} }
//go:linkname poll_runtime_pollSetDeadline internal_poll.runtime_pollSetDeadline //go:linkname poll_runtime_pollSetDeadline internal..z2fpoll.runtime_pollSetDeadline
func poll_runtime_pollSetDeadline(pd *pollDesc, d int64, mode int) { func poll_runtime_pollSetDeadline(pd *pollDesc, d int64, mode int) {
lock(&pd.lock) lock(&pd.lock)
if pd.closing { if pd.closing {
...@@ -263,7 +263,7 @@ func poll_runtime_pollSetDeadline(pd *pollDesc, d int64, mode int) { ...@@ -263,7 +263,7 @@ func poll_runtime_pollSetDeadline(pd *pollDesc, d int64, mode int) {
} }
} }
//go:linkname poll_runtime_pollUnblock internal_poll.runtime_pollUnblock //go:linkname poll_runtime_pollUnblock internal..z2fpoll.runtime_pollUnblock
func poll_runtime_pollUnblock(pd *pollDesc) { func poll_runtime_pollUnblock(pd *pollDesc) {
lock(&pd.lock) lock(&pd.lock)
if pd.closing { if pd.closing {
......
...@@ -87,19 +87,19 @@ func TestMemoryProfiler(t *testing.T) { ...@@ -87,19 +87,19 @@ func TestMemoryProfiler(t *testing.T) {
fmt.Sprintf(`%v: %v \[%v: %v\] @ 0x[0-9,a-f x]+ fmt.Sprintf(`%v: %v \[%v: %v\] @ 0x[0-9,a-f x]+
# 0x[0-9,a-f]+ pprof\.allocatePersistent1K\+0x[0-9,a-f]+ .*/mprof_test\.go:40 # 0x[0-9,a-f]+ pprof\.allocatePersistent1K\+0x[0-9,a-f]+ .*/mprof_test\.go:40
# 0x[0-9,a-f]+ runtime_pprof\.TestMemoryProfiler\+0x[0-9,a-f]+ .*/mprof_test\.go:74 # 0x[0-9,a-f]+ runtime/pprof\.TestMemoryProfiler\+0x[0-9,a-f]+ .*/mprof_test\.go:74
`, 32*memoryProfilerRun, 1024*memoryProfilerRun, 32*memoryProfilerRun, 1024*memoryProfilerRun), `, 32*memoryProfilerRun, 1024*memoryProfilerRun, 32*memoryProfilerRun, 1024*memoryProfilerRun),
fmt.Sprintf(`0: 0 \[%v: %v\] @ 0x[0-9,a-f x]+ fmt.Sprintf(`0: 0 \[%v: %v\] @ 0x[0-9,a-f x]+
# 0x[0-9,a-f]+ pprof\.allocateTransient1M\+0x[0-9,a-f]+ .*/mprof_test.go:21 # 0x[0-9,a-f]+ pprof\.allocateTransient1M\+0x[0-9,a-f]+ .*/mprof_test.go:21
# 0x[0-9,a-f]+ runtime_pprof\.TestMemoryProfiler\+0x[0-9,a-f]+ .*/mprof_test.go:72 # 0x[0-9,a-f]+ runtime/pprof\.TestMemoryProfiler\+0x[0-9,a-f]+ .*/mprof_test.go:72
`, (1<<10)*memoryProfilerRun, (1<<20)*memoryProfilerRun), `, (1<<10)*memoryProfilerRun, (1<<20)*memoryProfilerRun),
// This should start with "0: 0" but gccgo's imprecise // This should start with "0: 0" but gccgo's imprecise
// GC means that sometimes the value is not collected. // GC means that sometimes the value is not collected.
fmt.Sprintf(`(0|%v): (0|%v) \[%v: %v\] @ 0x[0-9,a-f x]+ fmt.Sprintf(`(0|%v): (0|%v) \[%v: %v\] @ 0x[0-9,a-f x]+
# 0x[0-9,a-f]+ pprof\.allocateTransient2M\+0x[0-9,a-f]+ .*/mprof_test.go:27 # 0x[0-9,a-f]+ pprof\.allocateTransient2M\+0x[0-9,a-f]+ .*/mprof_test.go:27
# 0x[0-9,a-f]+ runtime_pprof\.TestMemoryProfiler\+0x[0-9,a-f]+ .*/mprof_test.go:73 # 0x[0-9,a-f]+ runtime/pprof\.TestMemoryProfiler\+0x[0-9,a-f]+ .*/mprof_test.go:73
`, memoryProfilerRun, (2<<20)*memoryProfilerRun, memoryProfilerRun, (2<<20)*memoryProfilerRun), `, memoryProfilerRun, (2<<20)*memoryProfilerRun, memoryProfilerRun, (2<<20)*memoryProfilerRun),
// This should start with "0: 0" but gccgo's imprecise // This should start with "0: 0" but gccgo's imprecise
......
...@@ -4670,7 +4670,7 @@ func runqsteal(_p_, p2 *p, stealRunNextG bool) *g { ...@@ -4670,7 +4670,7 @@ func runqsteal(_p_, p2 *p, stealRunNextG bool) *g {
return gp return gp
} }
//go:linkname setMaxThreads runtime_debug.setMaxThreads //go:linkname setMaxThreads runtime..z2fdebug.setMaxThreads
func setMaxThreads(in int) (out int) { func setMaxThreads(in int) (out int) {
lock(&sched.lock) lock(&sched.lock)
out = int(sched.maxmcount) out = int(sched.maxmcount)
...@@ -4716,13 +4716,13 @@ func sync_runtime_procUnpin() { ...@@ -4716,13 +4716,13 @@ func sync_runtime_procUnpin() {
procUnpin() procUnpin()
} }
//go:linkname sync_atomic_runtime_procPin sync_atomic.runtime_procPin //go:linkname sync_atomic_runtime_procPin sync..z2fatomic.runtime_procPin
//go:nosplit //go:nosplit
func sync_atomic_runtime_procPin() int { func sync_atomic_runtime_procPin() int {
return procPin() return procPin()
} }
//go:linkname sync_atomic_runtime_procUnpin sync_atomic.runtime_procUnpin //go:linkname sync_atomic_runtime_procUnpin sync..z2fatomic.runtime_procUnpin
//go:nosplit //go:nosplit
func sync_atomic_runtime_procUnpin() { func sync_atomic_runtime_procUnpin() {
procUnpin() procUnpin()
......
...@@ -8,7 +8,7 @@ import "unsafe" ...@@ -8,7 +8,7 @@ import "unsafe"
var labelSync uintptr var labelSync uintptr
//go:linkname runtime_setProfLabel runtime_pprof.runtime_setProfLabel //go:linkname runtime_setProfLabel runtime..z2fpprof.runtime_setProfLabel
func runtime_setProfLabel(labels unsafe.Pointer) { func runtime_setProfLabel(labels unsafe.Pointer) {
// Introduce race edge for read-back via profile. // Introduce race edge for read-back via profile.
// This would more properly use &getg().labels as the sync address, // This would more properly use &getg().labels as the sync address,
...@@ -34,7 +34,7 @@ func runtime_setProfLabel(labels unsafe.Pointer) { ...@@ -34,7 +34,7 @@ func runtime_setProfLabel(labels unsafe.Pointer) {
getg().labels = labels getg().labels = labels
} }
//go:linkname runtime_getProfLabel runtime_pprof.runtime_getProfLabel //go:linkname runtime_getProfLabel runtime..z2fpprof.runtime_getProfLabel
func runtime_getProfLabel() unsafe.Pointer { func runtime_getProfLabel() unsafe.Pointer {
return getg().labels return getg().labels
} }
...@@ -11,14 +11,14 @@ import _ "unsafe" // for go:linkname ...@@ -11,14 +11,14 @@ import _ "unsafe" // for go:linkname
// maxstacksize. // maxstacksize.
var maxstacksize uintptr = 1 << 20 // enough until runtime.main sets it for real var maxstacksize uintptr = 1 << 20 // enough until runtime.main sets it for real
//go:linkname setMaxStack runtime_debug.setMaxStack //go:linkname setMaxStack runtime..z2fdebug.setMaxStack
func setMaxStack(in int) (out int) { func setMaxStack(in int) (out int) {
out = int(maxstacksize) out = int(maxstacksize)
maxstacksize = uintptr(in) maxstacksize = uintptr(in)
return out return out
} }
//go:linkname setPanicOnFault runtime_debug.setPanicOnFault //go:linkname setPanicOnFault runtime..z2fdebug.setPanicOnFault
func setPanicOnFault(new bool) (old bool) { func setPanicOnFault(new bool) (old bool) {
_g_ := getg() _g_ := getg()
old = _g_.paniconfault old = _g_.paniconfault
......
...@@ -413,7 +413,7 @@ func parsedebugvars() { ...@@ -413,7 +413,7 @@ func parsedebugvars() {
traceback_env = traceback_cache traceback_env = traceback_cache
} }
//go:linkname setTraceback runtime_debug.SetTraceback //go:linkname setTraceback runtime..z2fdebug.SetTraceback
func setTraceback(level string) { func setTraceback(level string) {
var t uint32 var t uint32
switch level { switch level {
......
...@@ -56,7 +56,7 @@ func sync_runtime_Semacquire(addr *uint32) { ...@@ -56,7 +56,7 @@ func sync_runtime_Semacquire(addr *uint32) {
semacquire1(addr, false, semaBlockProfile) semacquire1(addr, false, semaBlockProfile)
} }
//go:linkname poll_runtime_Semacquire internal_poll.runtime_Semacquire //go:linkname poll_runtime_Semacquire internal..z2fpoll.runtime_Semacquire
func poll_runtime_Semacquire(addr *uint32) { func poll_runtime_Semacquire(addr *uint32) {
semacquire1(addr, false, semaBlockProfile) semacquire1(addr, false, semaBlockProfile)
} }
...@@ -71,7 +71,7 @@ func sync_runtime_SemacquireMutex(addr *uint32, lifo bool) { ...@@ -71,7 +71,7 @@ func sync_runtime_SemacquireMutex(addr *uint32, lifo bool) {
semacquire1(addr, lifo, semaBlockProfile|semaMutexProfile) semacquire1(addr, lifo, semaBlockProfile|semaMutexProfile)
} }
//go:linkname poll_runtime_Semrelease internal_poll.runtime_Semrelease //go:linkname poll_runtime_Semrelease internal..z2fpoll.runtime_Semrelease
func poll_runtime_Semrelease(addr *uint32) { func poll_runtime_Semrelease(addr *uint32) {
semrelease(addr) semrelease(addr)
} }
......
...@@ -117,7 +117,7 @@ Send: ...@@ -117,7 +117,7 @@ Send:
// Called to receive the next queued signal. // Called to receive the next queued signal.
// Must only be called from a single goroutine at a time. // Must only be called from a single goroutine at a time.
//go:linkname signal_recv os_signal.signal_recv //go:linkname signal_recv os..z2fsignal.signal_recv
func signal_recv() uint32 { func signal_recv() uint32 {
for { for {
// Serve any signals from local copy. // Serve any signals from local copy.
...@@ -161,7 +161,7 @@ func signal_recv() uint32 { ...@@ -161,7 +161,7 @@ func signal_recv() uint32 {
// the signal(s) in question, and here we are just waiting to make sure // the signal(s) in question, and here we are just waiting to make sure
// that all the signals have been delivered to the user channels // that all the signals have been delivered to the user channels
// by the os/signal package. // by the os/signal package.
//go:linkname signalWaitUntilIdle os_signal.signalWaitUntilIdle //go:linkname signalWaitUntilIdle os..z2fsignal.signalWaitUntilIdle
func signalWaitUntilIdle() { func signalWaitUntilIdle() {
// Although the signals we care about have been removed from // Although the signals we care about have been removed from
// sig.wanted, it is possible that another thread has received // sig.wanted, it is possible that another thread has received
...@@ -181,7 +181,7 @@ func signalWaitUntilIdle() { ...@@ -181,7 +181,7 @@ func signalWaitUntilIdle() {
} }
// Must only be called from a single goroutine at a time. // Must only be called from a single goroutine at a time.
//go:linkname signal_enable os_signal.signal_enable //go:linkname signal_enable os..z2fsignal.signal_enable
func signal_enable(s uint32) { func signal_enable(s uint32) {
if !sig.inuse { if !sig.inuse {
// The first call to signal_enable is for us // The first call to signal_enable is for us
...@@ -208,7 +208,7 @@ func signal_enable(s uint32) { ...@@ -208,7 +208,7 @@ func signal_enable(s uint32) {
} }
// Must only be called from a single goroutine at a time. // Must only be called from a single goroutine at a time.
//go:linkname signal_disable os_signal.signal_disable //go:linkname signal_disable os..z2fsignal.signal_disable
func signal_disable(s uint32) { func signal_disable(s uint32) {
if s >= uint32(len(sig.wanted)*32) { if s >= uint32(len(sig.wanted)*32) {
return return
...@@ -221,7 +221,7 @@ func signal_disable(s uint32) { ...@@ -221,7 +221,7 @@ func signal_disable(s uint32) {
} }
// Must only be called from a single goroutine at a time. // Must only be called from a single goroutine at a time.
//go:linkname signal_ignore os_signal.signal_ignore //go:linkname signal_ignore os..z2fsignal.signal_ignore
func signal_ignore(s uint32) { func signal_ignore(s uint32) {
if s >= uint32(len(sig.wanted)*32) { if s >= uint32(len(sig.wanted)*32) {
return return
...@@ -248,7 +248,7 @@ func sigInitIgnored(s uint32) { ...@@ -248,7 +248,7 @@ func sigInitIgnored(s uint32) {
} }
// Checked by signal handlers. // Checked by signal handlers.
//go:linkname signal_ignored os_signal.signal_ignored //go:linkname signal_ignored os..z2fsignal.signal_ignored
func signal_ignored(s uint32) bool { func signal_ignored(s uint32) bool {
i := atomic.Load(&sig.ignored[s/32]) i := atomic.Load(&sig.ignored[s/32])
return i&(1<<(s&31)) != 0 return i&(1<<(s&31)) != 0
......
...@@ -83,6 +83,11 @@ func (ci *Frames) Next() (frame Frame, more bool) { ...@@ -83,6 +83,11 @@ func (ci *Frames) Next() (frame Frame, more bool) {
if function == "" && file == "" { if function == "" && file == "" {
return Frame{}, more return Frame{}, more
} }
// Demangle function name if needed.
function = demangleSymbol(function)
// Create entry.
entry := funcentry(pc - 1) entry := funcentry(pc - 1)
f := &Func{name: function, entry: entry} f := &Func{name: function, entry: entry}
...@@ -182,6 +187,75 @@ func (f *Func) FileLine(pc uintptr) (file string, line int) { ...@@ -182,6 +187,75 @@ func (f *Func) FileLine(pc uintptr) (file string, line int) {
return file, line return file, line
} }
func hexval(b byte) uint {
if b >= '0' && b <= '9' {
return uint(b - '0')
}
if b >= 'a' && b <= 'f' {
return uint(b-'a') + 10
}
return 0
}
func hexDigitsToRune(digits []byte, ndig int) rune {
result := uint(0)
for i := 0; i < ndig; i++ {
result <<= uint(4)
result |= hexval(digits[i])
}
return rune(result)
}
// Perform an in-place decoding on the input byte slice. This looks
// for "..z<hex 2 >", "..u<hex x 4>" and "..U<hex x 8>" and overwrites
// with the encoded bytes corresponding to the unicode in question.
// Return value is the number of bytes taken by the result.
func decodeIdentifier(bsl []byte) int {
j := 0
for i := 0; i < len(bsl); i++ {
b := bsl[i]
if i+1 < len(bsl) && bsl[i] == '.' && bsl[i+1] == '.' {
if i+4 < len(bsl) && bsl[i+2] == 'z' {
digits := bsl[i+3:]
r := hexDigitsToRune(digits, 2)
nc := encoderune(bsl[j:], r)
j += nc
i += 4
continue
} else if i+6 < len(bsl) && bsl[i+2] == 'u' {
digits := bsl[i+3:]
r := hexDigitsToRune(digits, 4)
nc := encoderune(bsl[j:], r)
j += nc
i += 6
continue
} else if i+10 < len(bsl) && bsl[i+2] == 'U' {
digits := bsl[i+3:]
r := hexDigitsToRune(digits, 8)
nc := encoderune(bsl[j:], r)
j += nc
i += 10
continue
}
}
bsl[j] = b
j += 1
}
return j
}
// Demangle a function symbol. Applies the reverse of go_encode_id()
// as used in the compiler.
func demangleSymbol(s string) string {
bsl := []byte(s)
nchars := decodeIdentifier(bsl)
bsl = bsl[:nchars]
return string(bsl)
}
// implemented in go-caller.c // implemented in go-caller.c
func funcfileline(uintptr, int32) (string, string, int) func funcfileline(uintptr, int32) (string, string, int)
func funcentry(uintptr) uintptr func funcentry(uintptr) uintptr
...@@ -441,7 +441,7 @@ func badTimer() { ...@@ -441,7 +441,7 @@ func badTimer() {
// Entry points for net, time to call nanotime. // Entry points for net, time to call nanotime.
//go:linkname poll_runtimeNano internal_poll.runtimeNano //go:linkname poll_runtimeNano internal..z2fpoll.runtimeNano
func poll_runtimeNano() int64 { func poll_runtimeNano() int64 {
return nanotime() return nanotime()
} }
......
...@@ -1143,7 +1143,7 @@ func traceNextGC() { ...@@ -1143,7 +1143,7 @@ func traceNextGC() {
// To access runtime functions from runtime/trace. // To access runtime functions from runtime/trace.
// See runtime/trace/annotation.go // See runtime/trace/annotation.go
//go:linkname trace_userTaskCreate runtime_trace.userTaskCreate //go:linkname trace_userTaskCreate runtime..z2ftrace.userTaskCreate
func trace_userTaskCreate(id, parentID uint64, taskType string) { func trace_userTaskCreate(id, parentID uint64, taskType string) {
if !trace.enabled { if !trace.enabled {
return return
...@@ -1161,12 +1161,12 @@ func trace_userTaskCreate(id, parentID uint64, taskType string) { ...@@ -1161,12 +1161,12 @@ func trace_userTaskCreate(id, parentID uint64, taskType string) {
traceReleaseBuffer(pid) traceReleaseBuffer(pid)
} }
//go:linkname trace_userTaskEnd runtime_trace.userTaskEnd //go:linkname trace_userTaskEnd runtime..z2ftrace.userTaskEnd
func trace_userTaskEnd(id uint64) { func trace_userTaskEnd(id uint64) {
traceEvent(traceEvUserTaskEnd, 2, id) traceEvent(traceEvUserTaskEnd, 2, id)
} }
//go:linkname trace_userRegion runtime_trace.userRegion //go:linkname trace_userRegion runtime..z2ftrace.userRegion
func trace_userRegion(id, mode uint64, name string) { func trace_userRegion(id, mode uint64, name string) {
if !trace.enabled { if !trace.enabled {
return return
...@@ -1183,7 +1183,7 @@ func trace_userRegion(id, mode uint64, name string) { ...@@ -1183,7 +1183,7 @@ func trace_userRegion(id, mode uint64, name string) {
traceReleaseBuffer(pid) traceReleaseBuffer(pid)
} }
//go:linkname trace_userLog runtime_trace.userLog //go:linkname trace_userLog runtime..z2ftrace.userLog
func trace_userLog(id uint64, category, message string) { func trace_userLog(id uint64, category, message string) {
if !trace.enabled { if !trace.enabled {
return return
......
...@@ -110,9 +110,14 @@ func showframe(name string, gp *g) bool { ...@@ -110,9 +110,14 @@ func showframe(name string, gp *g) bool {
} }
// isExportedRuntime reports whether name is an exported runtime function. // isExportedRuntime reports whether name is an exported runtime function.
// It is only for runtime functions, so ASCII A-Z is fine. // It is only for runtime functions, so ASCII A-Z is fine. Here also check
// for mangled functions from runtime/<...>, which will be prefixed with
// "runtime..z2f".
func isExportedRuntime(name string) bool { func isExportedRuntime(name string) bool {
const n = len("runtime.") const n = len("runtime.")
if hasprefix(name, "runtime..z2f") {
return true
}
return len(name) > n && name[:n] == "runtime." && 'A' <= name[n] && name[n] <= 'Z' return len(name) > n && name[:n] == "runtime." && 'A' <= name[n] && name[n] <= 'Z'
} }
......
...@@ -9,7 +9,7 @@ ...@@ -9,7 +9,7 @@
#include "runtime.h" #include "runtime.h"
int32_t SwapInt32 (int32_t *, int32_t) int32_t SwapInt32 (int32_t *, int32_t)
__asm__ (GOSYM_PREFIX "sync_atomic.SwapInt32") __asm__ (GOSYM_PREFIX "sync..z2fatomic.SwapInt32")
__attribute__ ((no_split_stack)); __attribute__ ((no_split_stack));
int32_t int32_t
...@@ -19,7 +19,7 @@ SwapInt32 (int32_t *addr, int32_t new) ...@@ -19,7 +19,7 @@ SwapInt32 (int32_t *addr, int32_t new)
} }
int64_t SwapInt64 (int64_t *, int64_t) int64_t SwapInt64 (int64_t *, int64_t)
__asm__ (GOSYM_PREFIX "sync_atomic.SwapInt64") __asm__ (GOSYM_PREFIX "sync..z2fatomic.SwapInt64")
__attribute__ ((no_split_stack)); __attribute__ ((no_split_stack));
int64_t int64_t
...@@ -31,7 +31,7 @@ SwapInt64 (int64_t *addr, int64_t new) ...@@ -31,7 +31,7 @@ SwapInt64 (int64_t *addr, int64_t new)
} }
uint32_t SwapUint32 (uint32_t *, uint32_t) uint32_t SwapUint32 (uint32_t *, uint32_t)
__asm__ (GOSYM_PREFIX "sync_atomic.SwapUint32") __asm__ (GOSYM_PREFIX "sync..z2fatomic.SwapUint32")
__attribute__ ((no_split_stack)); __attribute__ ((no_split_stack));
uint32_t uint32_t
...@@ -41,7 +41,7 @@ SwapUint32 (uint32_t *addr, uint32_t new) ...@@ -41,7 +41,7 @@ SwapUint32 (uint32_t *addr, uint32_t new)
} }
uint64_t SwapUint64 (uint64_t *, uint64_t) uint64_t SwapUint64 (uint64_t *, uint64_t)
__asm__ (GOSYM_PREFIX "sync_atomic.SwapUint64") __asm__ (GOSYM_PREFIX "sync..z2fatomic.SwapUint64")
__attribute__ ((no_split_stack)); __attribute__ ((no_split_stack));
uint64_t uint64_t
...@@ -53,7 +53,7 @@ SwapUint64 (uint64_t *addr, uint64_t new) ...@@ -53,7 +53,7 @@ SwapUint64 (uint64_t *addr, uint64_t new)
} }
uintptr_t SwapUintptr (uintptr_t *, uintptr_t) uintptr_t SwapUintptr (uintptr_t *, uintptr_t)
__asm__ (GOSYM_PREFIX "sync_atomic.SwapUintptr") __asm__ (GOSYM_PREFIX "sync..z2fatomic.SwapUintptr")
__attribute__ ((no_split_stack)); __attribute__ ((no_split_stack));
uintptr_t uintptr_t
...@@ -63,7 +63,7 @@ SwapUintptr (uintptr_t *addr, uintptr_t new) ...@@ -63,7 +63,7 @@ SwapUintptr (uintptr_t *addr, uintptr_t new)
} }
_Bool CompareAndSwapInt32 (int32_t *, int32_t, int32_t) _Bool CompareAndSwapInt32 (int32_t *, int32_t, int32_t)
__asm__ (GOSYM_PREFIX "sync_atomic.CompareAndSwapInt32") __asm__ (GOSYM_PREFIX "sync..z2fatomic.CompareAndSwapInt32")
__attribute__ ((no_split_stack)); __attribute__ ((no_split_stack));
_Bool _Bool
...@@ -73,7 +73,7 @@ CompareAndSwapInt32 (int32_t *val, int32_t old, int32_t new) ...@@ -73,7 +73,7 @@ CompareAndSwapInt32 (int32_t *val, int32_t old, int32_t new)
} }
_Bool CompareAndSwapInt64 (int64_t *, int64_t, int64_t) _Bool CompareAndSwapInt64 (int64_t *, int64_t, int64_t)
__asm__ (GOSYM_PREFIX "sync_atomic.CompareAndSwapInt64") __asm__ (GOSYM_PREFIX "sync..z2fatomic.CompareAndSwapInt64")
__attribute__ ((no_split_stack)); __attribute__ ((no_split_stack));
_Bool _Bool
...@@ -85,7 +85,7 @@ CompareAndSwapInt64 (int64_t *val, int64_t old, int64_t new) ...@@ -85,7 +85,7 @@ CompareAndSwapInt64 (int64_t *val, int64_t old, int64_t new)
} }
_Bool CompareAndSwapUint32 (uint32_t *, uint32_t, uint32_t) _Bool CompareAndSwapUint32 (uint32_t *, uint32_t, uint32_t)
__asm__ (GOSYM_PREFIX "sync_atomic.CompareAndSwapUint32") __asm__ (GOSYM_PREFIX "sync..z2fatomic.CompareAndSwapUint32")
__attribute__ ((no_split_stack)); __attribute__ ((no_split_stack));
_Bool _Bool
...@@ -95,7 +95,7 @@ CompareAndSwapUint32 (uint32_t *val, uint32_t old, uint32_t new) ...@@ -95,7 +95,7 @@ CompareAndSwapUint32 (uint32_t *val, uint32_t old, uint32_t new)
} }
_Bool CompareAndSwapUint64 (uint64_t *, uint64_t, uint64_t) _Bool CompareAndSwapUint64 (uint64_t *, uint64_t, uint64_t)
__asm__ (GOSYM_PREFIX "sync_atomic.CompareAndSwapUint64") __asm__ (GOSYM_PREFIX "sync..z2fatomic.CompareAndSwapUint64")
__attribute__ ((no_split_stack)); __attribute__ ((no_split_stack));
_Bool _Bool
...@@ -107,7 +107,7 @@ CompareAndSwapUint64 (uint64_t *val, uint64_t old, uint64_t new) ...@@ -107,7 +107,7 @@ CompareAndSwapUint64 (uint64_t *val, uint64_t old, uint64_t new)
} }
_Bool CompareAndSwapUintptr (uintptr_t *, uintptr_t, uintptr_t) _Bool CompareAndSwapUintptr (uintptr_t *, uintptr_t, uintptr_t)
__asm__ (GOSYM_PREFIX "sync_atomic.CompareAndSwapUintptr") __asm__ (GOSYM_PREFIX "sync..z2fatomic.CompareAndSwapUintptr")
__attribute__ ((no_split_stack)); __attribute__ ((no_split_stack));
_Bool _Bool
...@@ -117,7 +117,7 @@ CompareAndSwapUintptr (uintptr_t *val, uintptr_t old, uintptr_t new) ...@@ -117,7 +117,7 @@ CompareAndSwapUintptr (uintptr_t *val, uintptr_t old, uintptr_t new)
} }
int32_t AddInt32 (int32_t *, int32_t) int32_t AddInt32 (int32_t *, int32_t)
__asm__ (GOSYM_PREFIX "sync_atomic.AddInt32") __asm__ (GOSYM_PREFIX "sync..z2fatomic.AddInt32")
__attribute__ ((no_split_stack)); __attribute__ ((no_split_stack));
int32_t int32_t
...@@ -127,7 +127,7 @@ AddInt32 (int32_t *val, int32_t delta) ...@@ -127,7 +127,7 @@ AddInt32 (int32_t *val, int32_t delta)
} }
uint32_t AddUint32 (uint32_t *, uint32_t) uint32_t AddUint32 (uint32_t *, uint32_t)
__asm__ (GOSYM_PREFIX "sync_atomic.AddUint32") __asm__ (GOSYM_PREFIX "sync..z2fatomic.AddUint32")
__attribute__ ((no_split_stack)); __attribute__ ((no_split_stack));
uint32_t uint32_t
...@@ -137,7 +137,7 @@ AddUint32 (uint32_t *val, uint32_t delta) ...@@ -137,7 +137,7 @@ AddUint32 (uint32_t *val, uint32_t delta)
} }
int64_t AddInt64 (int64_t *, int64_t) int64_t AddInt64 (int64_t *, int64_t)
__asm__ (GOSYM_PREFIX "sync_atomic.AddInt64") __asm__ (GOSYM_PREFIX "sync..z2fatomic.AddInt64")
__attribute__ ((no_split_stack)); __attribute__ ((no_split_stack));
int64_t int64_t
...@@ -149,7 +149,7 @@ AddInt64 (int64_t *val, int64_t delta) ...@@ -149,7 +149,7 @@ AddInt64 (int64_t *val, int64_t delta)
} }
uint64_t AddUint64 (uint64_t *, uint64_t) uint64_t AddUint64 (uint64_t *, uint64_t)
__asm__ (GOSYM_PREFIX "sync_atomic.AddUint64") __asm__ (GOSYM_PREFIX "sync..z2fatomic.AddUint64")
__attribute__ ((no_split_stack)); __attribute__ ((no_split_stack));
uint64_t uint64_t
...@@ -161,7 +161,7 @@ AddUint64 (uint64_t *val, uint64_t delta) ...@@ -161,7 +161,7 @@ AddUint64 (uint64_t *val, uint64_t delta)
} }
uintptr_t AddUintptr (uintptr_t *, uintptr_t) uintptr_t AddUintptr (uintptr_t *, uintptr_t)
__asm__ (GOSYM_PREFIX "sync_atomic.AddUintptr") __asm__ (GOSYM_PREFIX "sync..z2fatomic.AddUintptr")
__attribute__ ((no_split_stack)); __attribute__ ((no_split_stack));
uintptr_t uintptr_t
...@@ -171,7 +171,7 @@ AddUintptr (uintptr_t *val, uintptr_t delta) ...@@ -171,7 +171,7 @@ AddUintptr (uintptr_t *val, uintptr_t delta)
} }
int32_t LoadInt32 (int32_t *addr) int32_t LoadInt32 (int32_t *addr)
__asm__ (GOSYM_PREFIX "sync_atomic.LoadInt32") __asm__ (GOSYM_PREFIX "sync..z2fatomic.LoadInt32")
__attribute__ ((no_split_stack)); __attribute__ ((no_split_stack));
int32_t int32_t
...@@ -186,7 +186,7 @@ LoadInt32 (int32_t *addr) ...@@ -186,7 +186,7 @@ LoadInt32 (int32_t *addr)
} }
int64_t LoadInt64 (int64_t *addr) int64_t LoadInt64 (int64_t *addr)
__asm__ (GOSYM_PREFIX "sync_atomic.LoadInt64") __asm__ (GOSYM_PREFIX "sync..z2fatomic.LoadInt64")
__attribute__ ((no_split_stack)); __attribute__ ((no_split_stack));
int64_t int64_t
...@@ -203,7 +203,7 @@ LoadInt64 (int64_t *addr) ...@@ -203,7 +203,7 @@ LoadInt64 (int64_t *addr)
} }
uint32_t LoadUint32 (uint32_t *addr) uint32_t LoadUint32 (uint32_t *addr)
__asm__ (GOSYM_PREFIX "sync_atomic.LoadUint32") __asm__ (GOSYM_PREFIX "sync..z2fatomic.LoadUint32")
__attribute__ ((no_split_stack)); __attribute__ ((no_split_stack));
uint32_t uint32_t
...@@ -218,7 +218,7 @@ LoadUint32 (uint32_t *addr) ...@@ -218,7 +218,7 @@ LoadUint32 (uint32_t *addr)
} }
uint64_t LoadUint64 (uint64_t *addr) uint64_t LoadUint64 (uint64_t *addr)
__asm__ (GOSYM_PREFIX "sync_atomic.LoadUint64") __asm__ (GOSYM_PREFIX "sync..z2fatomic.LoadUint64")
__attribute__ ((no_split_stack)); __attribute__ ((no_split_stack));
uint64_t uint64_t
...@@ -235,7 +235,7 @@ LoadUint64 (uint64_t *addr) ...@@ -235,7 +235,7 @@ LoadUint64 (uint64_t *addr)
} }
uintptr_t LoadUintptr (uintptr_t *addr) uintptr_t LoadUintptr (uintptr_t *addr)
__asm__ (GOSYM_PREFIX "sync_atomic.LoadUintptr") __asm__ (GOSYM_PREFIX "sync..z2fatomic.LoadUintptr")
__attribute__ ((no_split_stack)); __attribute__ ((no_split_stack));
uintptr_t uintptr_t
...@@ -250,7 +250,7 @@ LoadUintptr (uintptr_t *addr) ...@@ -250,7 +250,7 @@ LoadUintptr (uintptr_t *addr)
} }
void *LoadPointer (void **addr) void *LoadPointer (void **addr)
__asm__ (GOSYM_PREFIX "sync_atomic.LoadPointer") __asm__ (GOSYM_PREFIX "sync..z2fatomic.LoadPointer")
__attribute__ ((no_split_stack)); __attribute__ ((no_split_stack));
void * void *
...@@ -265,7 +265,7 @@ LoadPointer (void **addr) ...@@ -265,7 +265,7 @@ LoadPointer (void **addr)
} }
void StoreInt32 (int32_t *addr, int32_t val) void StoreInt32 (int32_t *addr, int32_t val)
__asm__ (GOSYM_PREFIX "sync_atomic.StoreInt32") __asm__ (GOSYM_PREFIX "sync..z2fatomic.StoreInt32")
__attribute__ ((no_split_stack)); __attribute__ ((no_split_stack));
void void
...@@ -279,7 +279,7 @@ StoreInt32 (int32_t *addr, int32_t val) ...@@ -279,7 +279,7 @@ StoreInt32 (int32_t *addr, int32_t val)
} }
void StoreInt64 (int64_t *addr, int64_t val) void StoreInt64 (int64_t *addr, int64_t val)
__asm__ (GOSYM_PREFIX "sync_atomic.StoreInt64") __asm__ (GOSYM_PREFIX "sync..z2fatomic.StoreInt64")
__attribute__ ((no_split_stack)); __attribute__ ((no_split_stack));
void void
...@@ -295,7 +295,7 @@ StoreInt64 (int64_t *addr, int64_t val) ...@@ -295,7 +295,7 @@ StoreInt64 (int64_t *addr, int64_t val)
} }
void StoreUint32 (uint32_t *addr, uint32_t val) void StoreUint32 (uint32_t *addr, uint32_t val)
__asm__ (GOSYM_PREFIX "sync_atomic.StoreUint32") __asm__ (GOSYM_PREFIX "sync..z2fatomic.StoreUint32")
__attribute__ ((no_split_stack)); __attribute__ ((no_split_stack));
void void
...@@ -309,7 +309,7 @@ StoreUint32 (uint32_t *addr, uint32_t val) ...@@ -309,7 +309,7 @@ StoreUint32 (uint32_t *addr, uint32_t val)
} }
void StoreUint64 (uint64_t *addr, uint64_t val) void StoreUint64 (uint64_t *addr, uint64_t val)
__asm__ (GOSYM_PREFIX "sync_atomic.StoreUint64") __asm__ (GOSYM_PREFIX "sync..z2fatomic.StoreUint64")
__attribute__ ((no_split_stack)); __attribute__ ((no_split_stack));
void void
...@@ -325,7 +325,7 @@ StoreUint64 (uint64_t *addr, uint64_t val) ...@@ -325,7 +325,7 @@ StoreUint64 (uint64_t *addr, uint64_t val)
} }
void StoreUintptr (uintptr_t *addr, uintptr_t val) void StoreUintptr (uintptr_t *addr, uintptr_t val)
__asm__ (GOSYM_PREFIX "sync_atomic.StoreUintptr") __asm__ (GOSYM_PREFIX "sync..z2fatomic.StoreUintptr")
__attribute__ ((no_split_stack)); __attribute__ ((no_split_stack));
void void
......
...@@ -504,6 +504,35 @@ localname() { ...@@ -504,6 +504,35 @@ localname() {
echo $1 | sed 's/^main\./__main__./' echo $1 | sed 's/^main\./__main__./'
} }
# Takes a list of tests derived from 'nm' output (whose symbols are mangled)
# and emits a demangled list of tests, using only the terminal package.
# Example:
#
# Original symbol: foo/bar/leaf.Mumble
# Mangled symbol: foo..z2fbar..z2fleaf.Mumble
# Returned: leaf.Mumble
#
symtogo() {
local s=""
local result=""
local ndots=""
for tp in $*
do
s=$(echo $tp | sed -e 's/\.\.z2f/%/g' | sed -e 's/.*%//')
# screen out methods (X.Y.Z)
ndots=$(echo $s | sed -e 's/\./ /g' | wc -w)
if [ $ndots -ne 2 ]; then
continue
fi
if [ -z "${result}" ]; then
result="${s}"
else
result="${result} ${s}"
fi
done
echo "$result" | sed -e 's/ /\n/g'
}
{ {
text="T" text="T"
...@@ -514,26 +543,27 @@ localname() { ...@@ -514,26 +543,27 @@ localname() {
text="[TD]" text="[TD]"
fi fi
symtogo='sed -e s/_test\([^A-Za-z0-9]\)/XXXtest\1/ -e s/.*_\([^_]*\.\)/\1/ -e s/XXXtest/_test/'
# test functions are named TestFoo # test functions are named TestFoo
# the grep -v eliminates methods and other special names # the grep -v eliminates methods and other special names
# that have multiple dots. # that have multiple dots.
pattern='Test([^a-z].*)?' pattern='Test([^a-z].*)?'
# The -p option tells GNU nm not to sort. # The -p option tells GNU nm not to sort.
# The -v option tells Solaris nm to sort by value. # The -v option tells Solaris nm to sort by value.
tests=$($NM -p -v _gotest_.o $xofile | egrep " $text .*\."$pattern'$' | grep -v '[^ ]\..*\.' | fgrep -v ' __go_' | sed 's/.* //' | $symtogo) testsyms=$($NM -p -v _gotest_.o $xofile | egrep " $text .*\."$pattern'$' | fgrep -v ' __go_' | egrep -v '\.\.\w+$' | sed 's/.* //')
tests=$(symtogo "$testsyms")
if [ "x$tests" = x ]; then if [ "x$tests" = x ]; then
echo 'gotest: warning: no tests matching '$pattern in _gotest_.o $xofile 1>&2 echo 'gotest: warning: no tests matching '$pattern in _gotest_.o $xofile 1>&2
exit 2 exit 2
fi fi
# benchmarks are named BenchmarkFoo. # benchmarks are named BenchmarkFoo.
pattern='Benchmark([^a-z].*)?' pattern='Benchmark([^a-z].*)?'
benchmarks=$($NM -p -v _gotest_.o $xofile | egrep " $text .*\."$pattern'$' | grep -v '[^ ]\..*\.' | fgrep -v ' __go_' | sed 's/.* //' | $symtogo) benchmarksyms=$($NM -p -v _gotest_.o $xofile | egrep " $text .*\."$pattern'$' | fgrep -v ' __go_' | egrep -v '\.\.\w+$' | sed 's/.* //')
benchmarks=$(symtogo "$benchmarksyms")
# examples are named ExampleFoo # examples are named ExampleFoo
pattern='Example([^a-z].*)?' pattern='Example([^a-z].*)?'
examples=$($NM -p -v _gotest_.o $xofile | egrep " $text .*\."$pattern'$' | grep -v '[^ ]\..*\.' | fgrep -v ' __go_' | sed 's/.* //' | $symtogo) examplesyms=$($NM -p -v _gotest_.o $xofile | egrep " $text .*\."$pattern'$' | fgrep -v ' __go_' | egrep -v '\.\.\w+$' | sed 's/.* //')
examples=$(symtogo "$examplesyms")
# package spec # package spec
echo 'package main' echo 'package main'
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment