aboutsummaryrefslogtreecommitdiff
path: root/gcc/go/gofrontend/names.cc
diff options
context:
space:
mode:
authorIan Lance Taylor <ian@gcc.gnu.org>2018-10-25 22:18:08 +0000
committerIan Lance Taylor <ian@gcc.gnu.org>2018-10-25 22:18:08 +0000
commit34489eb2af3bbb7be101bc838615cf4a4dc6828d (patch)
tree0dbda78980d4553fdaeee92ca666d72a2ab95213 /gcc/go/gofrontend/names.cc
parentfc756f9f460d5f0ec73a72128645fdb39fec77a0 (diff)
downloadgcc-34489eb2af3bbb7be101bc838615cf4a4dc6828d.zip
gcc-34489eb2af3bbb7be101bc838615cf4a4dc6828d.tar.gz
gcc-34489eb2af3bbb7be101bc838615cf4a4dc6828d.tar.bz2
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
Diffstat (limited to 'gcc/go/gofrontend/names.cc')
-rw-r--r--gcc/go/gofrontend/names.cc53
1 files changed, 29 insertions, 24 deletions
diff --git a/gcc/go/gofrontend/names.cc b/gcc/go/gofrontend/names.cc
index 2e36a1d..d9ae5910 100644
--- a/gcc/go/gofrontend/names.cc
+++ b/gcc/go/gofrontend/names.cc
@@ -33,7 +33,7 @@
// variable, is simply "PKGPATH.NAME". Note that NAME is not the
// packed form used for the "hidden" name internally in the compiler;
// 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,
// NAME may not begin with a digit. NAME may require further encoding
// for non-ASCII characters as described below, but until that
@@ -188,12 +188,17 @@
// encoding unambiguous, we introduce it with two consecutive dots.
// 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
-// instead of \u and \U. Since before this encoding names can never
-// contain consecutive dots followed by 'u' or 'U', and after this
-// encoding "..u" and "..U" are followed by a known number of
+// instead of \u and \U. The compiler also produces identifiers that
+// are qualified by package path, which means that there may also be ASCII
+// 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.
//
// Demangling these names is straightforward:
+// - replace ..zXX with an ASCII character
// - replace ..uXXXX with a unicode character
// - replace ..UXXXXXXXX with a unicode character
// - 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,
if (rtype != NULL)
ret = rtype->deref()->mangled_name(this);
else if (package == NULL)
- ret = this->pkgpath_symbol();
+ ret = this->pkgpath();
else
- ret = package->pkgpath_symbol();
+ ret = package->pkgpath();
ret.push_back('.');
// Check for special names that will break if we use
// Gogo::unpack_hidden_name.
@@ -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
// 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.append(Gogo::unpack_hidden_name(mname));
ret.append("..stub");
@@ -302,9 +307,9 @@ Gogo::global_var_asm_name(const std::string& go_name, const Package* package)
{
std::string ret;
if (package == NULL)
- ret = this->pkgpath_symbol();
+ ret = this->pkgpath();
else
- ret = package->pkgpath_symbol();
+ ret = package->pkgpath();
ret.append(1, '.');
ret.append(Gogo::unpack_hidden_name(go_name));
return go_encode_id(ret);
@@ -341,7 +346,7 @@ Gogo::thunk_name()
char thunk_name[50];
snprintf(thunk_name, sizeof thunk_name, "..thunk%d", thunk_count);
++thunk_count;
- std::string ret = this->pkgpath_symbol();
+ std::string ret = this->pkgpath();
return ret + thunk_name;
}
@@ -370,7 +375,7 @@ Gogo::init_function_name()
char buf[30];
snprintf(buf, sizeof buf, "..init%d", init_count);
++init_count;
- std::string ret = this->pkgpath_symbol();
+ std::string ret = this->pkgpath();
return ret + buf;
}
@@ -726,7 +731,7 @@ Struct_type::do_mangled_name(Gogo* gogo, std::string* ret) const
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(' ');
}
@@ -827,7 +832,7 @@ Interface_type::do_mangled_name(Gogo* gogo, std::string* ret) const
if (!p->name().empty())
{
- ret->append(Gogo::mangle_possibly_hidden_name(p->name()));
+ Gogo::append_possibly_hidden_name(ret, p->name());
ret->push_back(' ');
}
@@ -854,9 +859,9 @@ Forward_declaration_type::do_mangled_name(Gogo* gogo, std::string* ret) const
{
const Named_object* no = this->named_object();
if (no->package() == NULL)
- ret->append(gogo->pkgpath_symbol());
+ ret->append(gogo->pkgpath());
else
- ret->append(no->package()->pkgpath_symbol());
+ ret->append(no->package()->pkgpath());
ret->push_back('.');
ret->append(Gogo::unpack_hidden_name(no->name()));
}
@@ -894,18 +899,18 @@ Named_type::append_mangled_type_name(Gogo* gogo, bool use_alias,
if (rcvr != NULL)
ret->append(rcvr->type()->deref()->mangled_name(gogo));
else if (this->in_function_->package() == NULL)
- ret->append(gogo->pkgpath_symbol());
+ ret->append(gogo->pkgpath());
else
- ret->append(this->in_function_->package()->pkgpath_symbol());
+ ret->append(this->in_function_->package()->pkgpath());
ret->push_back('.');
ret->append(Gogo::unpack_hidden_name(this->in_function_->name()));
}
else
{
if (no->package() == NULL)
- ret->append(gogo->pkgpath_symbol());
+ ret->append(gogo->pkgpath());
else
- ret->append(no->package()->pkgpath_symbol());
+ ret->append(no->package()->pkgpath());
}
ret->push_back('.');
}
@@ -951,22 +956,22 @@ Gogo::type_descriptor_name(Type* type, Named_type* nt)
if (rcvr != NULL)
ret.append(rcvr->type()->deref()->mangled_name(this));
else if (in_function->package() == NULL)
- ret.append(this->pkgpath_symbol());
+ ret.append(this->pkgpath());
else
- ret.append(in_function->package()->pkgpath_symbol());
+ ret.append(in_function->package()->pkgpath());
ret.push_back('.');
ret.append(Gogo::unpack_hidden_name(in_function->name()));
ret.push_back('.');
}
if (no->package() == NULL)
- ret.append(this->pkgpath_symbol());
+ ret.append(this->pkgpath());
else
- ret.append(no->package()->pkgpath_symbol());
+ ret.append(no->package()->pkgpath());
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)
{