diff options
author | Ian Lance Taylor <ian@gcc.gnu.org> | 2018-10-25 22:18:08 +0000 |
---|---|---|
committer | Ian Lance Taylor <ian@gcc.gnu.org> | 2018-10-25 22:18:08 +0000 |
commit | 34489eb2af3bbb7be101bc838615cf4a4dc6828d (patch) | |
tree | 0dbda78980d4553fdaeee92ca666d72a2ab95213 /gcc/go/gofrontend/gogo.cc | |
parent | fc756f9f460d5f0ec73a72128645fdb39fec77a0 (diff) | |
download | gcc-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/gogo.cc')
-rw-r--r-- | gcc/go/gofrontend/gogo.cc | 45 |
1 files changed, 28 insertions, 17 deletions
diff --git a/gcc/go/gofrontend/gogo.cc b/gcc/go/gofrontend/gogo.cc index 2472245..70af627 100644 --- a/gcc/go/gofrontend/gogo.cc +++ b/gcc/go/gofrontend/gogo.cc @@ -256,26 +256,11 @@ Gogo::Gogo(Backend* backend, Linemap* linemap, int, int pointer_size) 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 Gogo::pkgpath_for_symbol(const std::string& pkgpath) { - std::string s = pkgpath; - for (size_t i = 0; i < s.length(); ++i) - { - char c = s[i]; - if ((c >= 'a' && c <= 'z') - || (c >= 'A' && c <= 'Z') - || (c >= '0' && c <= '9')) - ; - else - s[i] = '_'; - } - return s; + go_assert(!pkgpath.empty()); + return go_encode_id(pkgpath); } // Get the package path to use for type reflection data. This should @@ -319,6 +304,32 @@ Gogo::set_prefix(const std::string& arg) 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. std::string |