compiler: encode user visible names if necessary

Avoid putting weird characters into the user visible name.
It breaks stabs in particular, and may also cause debugger problems.
Instead, encode those names, and use a "g." prefix to tell the debugger.

Also dereference the type for the name of a recover thunk, to avoid a
pointless '*' that gets encoded.

Reviewed-on: https://go-review.googlesource.com/c/gofrontend/+/277232
This commit is contained in:
Ian Lance Taylor 2020-12-10 21:07:27 -08:00
parent e36ce56e81
commit ab264f4b39
5 changed files with 144 additions and 59 deletions

View File

@ -1,4 +1,4 @@
0d0b423739b2fee9788cb6cb8af9ced29375e545
3e8f49a2137a87fdaba51c3002ddbe41ab18ed46
The first line of this file holds the git revision number of the last
merge done from the gofrontend repository.

View File

@ -67,7 +67,7 @@ class Backend_name
public:
Backend_name()
: prefix_(NULL), components_(), count_(0), suffix_(),
is_asm_name_(false)
is_asm_name_(false), is_non_identifier_(false)
{}
// Set the prefix. Prefixes are always constant strings.
@ -120,6 +120,18 @@ class Backend_name
this->is_asm_name_ = true;
}
// Whether some component includes some characters that can't appear
// in an identifier.
bool
is_non_identifier() const
{ return this->is_non_identifier_; }
// Record that some component includes some character that can't
// appear in an identifier.
void
set_is_non_identifier()
{ this->is_non_identifier_ = true; }
// Get the user visible name.
std::string
name() const;
@ -150,6 +162,9 @@ class Backend_name
std::string suffix_;
// True if components_[0] is an assembler name specified by the user.
bool is_asm_name_;
// True if some component includes some character that can't
// normally appear in an identifier.
bool is_non_identifier_;
};
// An initialization function for an imported package. This is a

View File

@ -186,6 +186,20 @@
// struct tag, the brace or backslash will be backslash quoted, before
// underscore encoding.
//
// Many of these names will be visible in the debugger. The debugger
// will be given these names before applying any underscore encoding.
// These user names do not have to be unique--they are only used by
// the debugger, not the linker--so this is OK. However, there is an
// exception: if the name would otherwise include characters that
// can't normally appear in an identifier, then the user name will
// also be underscore encoded. This avoids problems with
// communicating the debug info to the assembler and with handling the
// debug info in the debugger. A Go-aware debugger will need to know
// whether to apply underscore decoding to a name before showing it to
// the user. We indicate this by adding a prefix of "g.", and
// assuming that cases of a package path of "g" are unusual. This
// prefix will only appear in the user name, not the assembler name.
//
// The underscore encoding is, naturally, an underscore followed by
// other characters. As there are various characters that commonly
// appear in type literals and in package paths, we have a set of
@ -512,7 +526,7 @@ Gogo::recover_thunk_name(const std::string& name, const Type* rtype)
if (rtype != NULL)
{
Backend_name bname;
rtype->backend_name(this, &bname);
rtype->deref()->backend_name(this, &bname);
ret = bname.name();
ret.append(1, '.');
}
@ -634,37 +648,45 @@ Type::backend_name(Gogo* gogo, Backend_name* bname) const
}
std::string name;
bool is_non_identifier = false;
// The do_symbol_name virtual function will set RET to the mangled
// name before encoding.
this->do_mangled_name(gogo, &name);
this->do_mangled_name(gogo, &name, &is_non_identifier);
bname->add(name);
if (is_non_identifier)
bname->set_is_non_identifier();
}
// The mangled name is implemented as a method on each instance of
// Type.
void
Error_type::do_mangled_name(Gogo*, std::string* ret) const
Error_type::do_mangled_name(Gogo*, std::string* ret,
bool* is_non_identifier) const
{
ret->append("{error}");
*is_non_identifier = true;
}
void
Void_type::do_mangled_name(Gogo*, std::string* ret) const
Void_type::do_mangled_name(Gogo*, std::string* ret,
bool* is_non_identifier) const
{
ret->append("{void}");
*is_non_identifier = true;
}
void
Boolean_type::do_mangled_name(Gogo*, std::string* ret) const
Boolean_type::do_mangled_name(Gogo*, std::string* ret, bool*) const
{
ret->append("bool");
}
void
Integer_type::do_mangled_name(Gogo*, std::string* ret) const
Integer_type::do_mangled_name(Gogo*, std::string* ret,
bool* is_non_identifier) const
{
char buf[100];
snprintf(buf, sizeof buf, "%s%si%d",
@ -672,43 +694,53 @@ Integer_type::do_mangled_name(Gogo*, std::string* ret) const
this->is_unsigned_ ? "u" : "",
this->bits_);
ret->append(buf);
if (this->is_abstract_)
*is_non_identifier = true;
}
void
Float_type::do_mangled_name(Gogo*, std::string* ret) const
Float_type::do_mangled_name(Gogo*, std::string* ret,
bool* is_non_identifier) const
{
char buf[100];
snprintf(buf, sizeof buf, "%sfloat%d",
this->is_abstract_ ? "{abstract}" : "",
this->bits_);
ret->append(buf);
if (this->is_abstract_)
*is_non_identifier = true;
}
void
Complex_type::do_mangled_name(Gogo*, std::string* ret) const
Complex_type::do_mangled_name(Gogo*, std::string* ret,
bool* is_non_identifier) const
{
char buf[100];
snprintf(buf, sizeof buf, "%sc%d",
this->is_abstract_ ? "{abstract}" : "",
this->bits_);
ret->append(buf);
if (this->is_abstract_)
*is_non_identifier = true;
}
void
String_type::do_mangled_name(Gogo*, std::string* ret) const
String_type::do_mangled_name(Gogo*, std::string* ret, bool*) const
{
ret->append("string");
}
void
Function_type::do_mangled_name(Gogo* gogo, std::string* ret) const
Function_type::do_mangled_name(Gogo* gogo, std::string* ret,
bool* is_non_identifier) const
{
ret->append("func");
if (this->receiver_ != NULL)
{
ret->push_back('(');
this->append_mangled_name(this->receiver_->type(), gogo, ret);
this->append_mangled_name(this->receiver_->type(), gogo, ret,
is_non_identifier);
ret->append(")");
}
@ -727,7 +759,8 @@ Function_type::do_mangled_name(Gogo* gogo, std::string* ret) const
ret->push_back(',');
if (this->is_varargs_ && p + 1 == params->end())
ret->append("...");
this->append_mangled_name(p->type(), gogo, ret);
this->append_mangled_name(p->type(), gogo, ret,
is_non_identifier);
}
}
ret->push_back(')');
@ -745,27 +778,34 @@ Function_type::do_mangled_name(Gogo* gogo, std::string* ret) const
first = false;
else
ret->append(",");
this->append_mangled_name(p->type(), gogo, ret);
this->append_mangled_name(p->type(), gogo, ret, is_non_identifier);
}
}
ret->push_back(')');
*is_non_identifier = true;
}
void
Pointer_type::do_mangled_name(Gogo* gogo, std::string* ret) const
Pointer_type::do_mangled_name(Gogo* gogo, std::string* ret,
bool* is_non_identifier) const
{
ret->push_back('*');
this->append_mangled_name(this->to_type_, gogo, ret);
this->append_mangled_name(this->to_type_, gogo, ret, is_non_identifier);
*is_non_identifier = true;
}
void
Nil_type::do_mangled_name(Gogo*, std::string* ret) const
Nil_type::do_mangled_name(Gogo*, std::string* ret,
bool* is_non_identifier) const
{
ret->append("{nil}");
*is_non_identifier = true;
}
void
Struct_type::do_mangled_name(Gogo* gogo, std::string* ret) const
Struct_type::do_mangled_name(Gogo* gogo, std::string* ret,
bool* is_non_identifier) const
{
ret->append("struct{");
@ -796,9 +836,10 @@ Struct_type::do_mangled_name(Gogo* gogo, std::string* ret) const
if (p->is_anonymous()
&& p->type()->named_type() != NULL
&& p->type()->named_type()->is_alias())
p->type()->named_type()->append_symbol_type_name(gogo, true, ret);
p->type()->named_type()->append_symbol_type_name(gogo, true, ret,
is_non_identifier);
else
this->append_mangled_name(p->type(), gogo, ret);
this->append_mangled_name(p->type(), gogo, ret, is_non_identifier);
if (p->has_tag())
{
@ -813,10 +854,13 @@ Struct_type::do_mangled_name(Gogo* gogo, std::string* ret) const
}
ret->push_back('}');
*is_non_identifier = true;
}
void
Array_type::do_mangled_name(Gogo* gogo, std::string* ret) const
Array_type::do_mangled_name(Gogo* gogo, std::string* ret,
bool* is_non_identifier) const
{
ret->push_back('[');
if (this->length_ != NULL)
@ -841,20 +885,24 @@ Array_type::do_mangled_name(Gogo* gogo, std::string* ret) const
ret->append("x");
}
ret->push_back(']');
this->append_mangled_name(this->element_type_, gogo, ret);
this->append_mangled_name(this->element_type_, gogo, ret, is_non_identifier);
*is_non_identifier = true;
}
void
Map_type::do_mangled_name(Gogo* gogo, std::string* ret) const
Map_type::do_mangled_name(Gogo* gogo, std::string* ret,
bool* is_non_identifier) const
{
ret->append("map[");
this->append_mangled_name(this->key_type_, gogo, ret);
this->append_mangled_name(this->key_type_, gogo, ret, is_non_identifier);
ret->push_back(']');
this->append_mangled_name(this->val_type_, gogo, ret);
this->append_mangled_name(this->val_type_, gogo, ret, is_non_identifier);
*is_non_identifier = true;
}
void
Channel_type::do_mangled_name(Gogo* gogo, std::string* ret) const
Channel_type::do_mangled_name(Gogo* gogo, std::string* ret,
bool* is_non_identifier) const
{
if (!this->may_send_)
ret->append("<-");
@ -862,11 +910,13 @@ Channel_type::do_mangled_name(Gogo* gogo, std::string* ret) const
if (!this->may_receive_)
ret->append("<-");
ret->push_back(' ');
this->append_mangled_name(this->element_type_, gogo, ret);
this->append_mangled_name(this->element_type_, gogo, ret, is_non_identifier);
*is_non_identifier = true;
}
void
Interface_type::do_mangled_name(Gogo* gogo, std::string* ret) const
Interface_type::do_mangled_name(Gogo* gogo, std::string* ret,
bool* is_non_identifier) const
{
go_assert(this->methods_are_finalized_);
@ -892,25 +942,29 @@ Interface_type::do_mangled_name(Gogo* gogo, std::string* ret) const
ret->push_back(' ');
}
this->append_mangled_name(p->type(), gogo, ret);
this->append_mangled_name(p->type(), gogo, ret, is_non_identifier);
}
this->seen_ = false;
}
ret->push_back('}');
*is_non_identifier = true;
}
void
Named_type::do_mangled_name(Gogo* gogo, std::string* ret) const
Named_type::do_mangled_name(Gogo* gogo, std::string* ret,
bool* is_non_identifier) const
{
this->append_symbol_type_name(gogo, false, ret);
this->append_symbol_type_name(gogo, false, ret, is_non_identifier);
}
void
Forward_declaration_type::do_mangled_name(Gogo* gogo, std::string* ret) const
Forward_declaration_type::do_mangled_name(Gogo* gogo, std::string* ret,
bool *is_non_identifier) const
{
if (this->is_defined())
this->append_mangled_name(this->real_type(), gogo, ret);
this->append_mangled_name(this->real_type(), gogo, ret, is_non_identifier);
else
{
const Named_object* no = this->named_object();
@ -929,7 +983,8 @@ Forward_declaration_type::do_mangled_name(Gogo* gogo, std::string* ret) const
void
Named_type::append_symbol_type_name(Gogo* gogo, bool use_alias,
std::string* ret) const
std::string* ret,
bool* is_non_identifier) const
{
if (this->is_error_)
return;
@ -938,7 +993,7 @@ Named_type::append_symbol_type_name(Gogo* gogo, bool use_alias,
if (this->seen_alias_)
return;
this->seen_alias_ = true;
this->append_mangled_name(this->type_, gogo, ret);
this->append_mangled_name(this->type_, gogo, ret, is_non_identifier);
this->seen_alias_ = false;
return;
}
@ -957,6 +1012,8 @@ Named_type::append_symbol_type_name(Gogo* gogo, bool use_alias,
Backend_name bname;
rcvr->type()->deref()->backend_name(gogo, &bname);
ret->append(bname.name());
if (bname.is_non_identifier())
*is_non_identifier = true;
}
else if (this->in_function_->package() == NULL)
ret->append(gogo->pkgpath());
@ -1160,6 +1217,15 @@ Backend_name::name() const
{
if (this->is_asm_name_)
return this->components_[0];
// If there is some character in the name that can't appear in an
// identifier, use the assembler name as the user name. This avoids
// possible problems in the assembler or debugger. The usual
// demangling scheme will still work. We use a prefix of "g." to
// tell the debugger about this.
if (this->is_non_identifier_)
return "g." + this->asm_name();
std::string ret;
if (this->prefix_ != NULL)
ret.append(this->prefix_);
@ -1203,6 +1269,8 @@ Backend_name::optional_asm_name() const
{
if (this->is_asm_name_)
return "";
if (this->is_non_identifier_)
return this->asm_name();
for (int i = 0; i < this->count_; i++)
if (go_id_needs_encoding(this->components_[i]))
return this->asm_name();

View File

@ -4602,7 +4602,7 @@ class Sink_type : public Type
{ go_unreachable(); }
void
do_mangled_name(Gogo*, std::string*) const
do_mangled_name(Gogo*, std::string*, bool*) const
{ go_unreachable(); }
};
@ -5712,7 +5712,7 @@ class Call_multiple_result_type : public Type
{ go_assert(saw_errors()); }
void
do_mangled_name(Gogo*, std::string*) const
do_mangled_name(Gogo*, std::string*, bool*) const
{ go_assert(saw_errors()); }
private:

View File

@ -1140,7 +1140,7 @@ class Type
do_reflection(Gogo*, std::string*) const = 0;
virtual void
do_mangled_name(Gogo*, std::string*) const = 0;
do_mangled_name(Gogo*, std::string*, bool*) const = 0;
virtual void
do_export(Export*) const;
@ -1202,8 +1202,9 @@ class Type
// For the benefit of child class mangling.
void
append_mangled_name(const Type* type, Gogo* gogo, std::string* ret) const
{ type->do_mangled_name(gogo, ret); }
append_mangled_name(const Type* type, Gogo* gogo, std::string* ret,
bool *is_non_identifier) const
{ type->do_mangled_name(gogo, ret, is_non_identifier); }
// Return the backend representation for the underlying type of a
// named type.
@ -1664,7 +1665,7 @@ class Error_type : public Type
do_reflection(Gogo*, std::string*) const;
void
do_mangled_name(Gogo*, std::string* ret) const;
do_mangled_name(Gogo*, std::string*, bool*) const;
};
// The void type.
@ -1693,7 +1694,7 @@ class Void_type : public Type
{ }
void
do_mangled_name(Gogo*, std::string* ret) const;
do_mangled_name(Gogo*, std::string*, bool*) const;
};
// The boolean type.
@ -1722,7 +1723,7 @@ class Boolean_type : public Type
{ ret->append("bool"); }
void
do_mangled_name(Gogo*, std::string* ret) const;
do_mangled_name(Gogo*, std::string*, bool*) const;
};
// The type of an integer.
@ -1808,7 +1809,7 @@ protected:
do_reflection(Gogo*, std::string*) const;
void
do_mangled_name(Gogo*, std::string*) const;
do_mangled_name(Gogo*, std::string*, bool*) const;
private:
Integer_type(bool is_abstract, bool is_unsigned, int bits,
@ -1894,7 +1895,7 @@ class Float_type : public Type
do_reflection(Gogo*, std::string*) const;
void
do_mangled_name(Gogo*, std::string*) const;
do_mangled_name(Gogo*, std::string*, bool*) const;
private:
Float_type(bool is_abstract, int bits, int runtime_type_kind)
@ -1972,7 +1973,7 @@ class Complex_type : public Type
do_reflection(Gogo*, std::string*) const;
void
do_mangled_name(Gogo*, std::string*) const;
do_mangled_name(Gogo*, std::string*, bool*) const;
private:
Complex_type(bool is_abstract, int bits, int runtime_type_kind)
@ -2026,7 +2027,7 @@ class String_type : public Type
do_reflection(Gogo*, std::string*) const;
void
do_mangled_name(Gogo*, std::string* ret) const;
do_mangled_name(Gogo*, std::string*, bool*) const;
private:
// The named string type.
@ -2186,7 +2187,7 @@ class Function_type : public Type
do_reflection(Gogo*, std::string*) const;
void
do_mangled_name(Gogo*, std::string*) const;
do_mangled_name(Gogo*, std::string*, bool*) const;
void
do_export(Export*) const;
@ -2315,7 +2316,7 @@ class Pointer_type : public Type
do_reflection(Gogo*, std::string*) const;
void
do_mangled_name(Gogo*, std::string*) const;
do_mangled_name(Gogo*, std::string*, bool*) const;
void
do_export(Export*) const;
@ -2353,7 +2354,7 @@ class Nil_type : public Type
{ go_unreachable(); }
void
do_mangled_name(Gogo*, std::string* ret) const;
do_mangled_name(Gogo*, std::string*, bool*) const;
};
// The type of a field in a struct.
@ -2687,7 +2688,7 @@ class Struct_type : public Type
do_reflection(Gogo*, std::string*) const;
void
do_mangled_name(Gogo*, std::string*) const;
do_mangled_name(Gogo*, std::string*, bool*) const;
void
do_export(Export*) const;
@ -2870,7 +2871,7 @@ class Array_type : public Type
do_reflection(Gogo*, std::string*) const;
void
do_mangled_name(Gogo*, std::string*) const;
do_mangled_name(Gogo*, std::string*, bool*) const;
void
do_export(Export*) const;
@ -3008,7 +3009,7 @@ class Map_type : public Type
do_reflection(Gogo*, std::string*) const;
void
do_mangled_name(Gogo*, std::string*) const;
do_mangled_name(Gogo*, std::string*, bool*) const;
void
do_export(Export*) const;
@ -3122,7 +3123,7 @@ class Channel_type : public Type
do_reflection(Gogo*, std::string*) const;
void
do_mangled_name(Gogo*, std::string*) const;
do_mangled_name(Gogo*, std::string*, bool*) const;
void
do_export(Export*) const;
@ -3298,7 +3299,7 @@ class Interface_type : public Type
do_reflection(Gogo*, std::string*) const;
void
do_mangled_name(Gogo*, std::string*) const;
do_mangled_name(Gogo*, std::string*, bool*) const;
void
do_export(Export*) const;
@ -3572,7 +3573,8 @@ class Named_type : public Type
// Append the symbol type name as for Type::append_mangled_name,
// but if USE_ALIAS use the alias name rather than the alias target.
void
append_symbol_type_name(Gogo*, bool use_alias, std::string*) const;
append_symbol_type_name(Gogo*, bool use_alias, std::string*,
bool* is_non_identifier) const;
// Import a named type.
static void
@ -3619,7 +3621,7 @@ class Named_type : public Type
do_reflection(Gogo*, std::string*) const;
void
do_mangled_name(Gogo*, std::string* ret) const;
do_mangled_name(Gogo*, std::string*, bool*) const;
void
do_export(Export*) const;
@ -3783,7 +3785,7 @@ class Forward_declaration_type : public Type
do_reflection(Gogo*, std::string*) const;
void
do_mangled_name(Gogo*, std::string* ret) const;
do_mangled_name(Gogo*, std::string*, bool*) const;
void
do_export(Export*) const;