From a2b1aa12f7d82dfd451e110bff8df16cdf6e2c49 Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Thu, 15 Nov 2007 01:12:55 +0000 Subject: [PATCH] From Craig Silverstein: Add support for --demangle. --- gold/dynobj.cc | 2 +- gold/errors.cc | 2 +- gold/i386.cc | 2 +- gold/object.cc | 21 +++++++++++++++------ gold/options.cc | 12 ++++++++++++ gold/options.h | 14 ++++++++++++++ gold/parameters.cc | 3 ++- gold/parameters.h | 7 +++++++ gold/resolve.cc | 10 +++++----- gold/symtab.cc | 36 ++++++++++++++++++++++++++++++++---- gold/symtab.h | 7 +++++++ gold/x86_64.cc | 5 +++-- 12 files changed, 100 insertions(+), 21 deletions(-) diff --git a/gold/dynobj.cc b/gold/dynobj.cc index a6f3588f48..f479352794 100644 --- a/gold/dynobj.cc +++ b/gold/dynobj.cc @@ -1301,7 +1301,7 @@ Versions::add_def(const Symbol* sym, const char* version, if (parameters->output_is_shared()) { gold_error(_("symbol %s has undefined version %s"), - sym->name(), version); + sym->demangled_name().c_str(), version); return; } diff --git a/gold/errors.cc b/gold/errors.cc index 3aa3ece897..2da1a2569e 100644 --- a/gold/errors.cc +++ b/gold/errors.cc @@ -135,7 +135,7 @@ Errors::undefined_symbol(const Symbol* sym, } fprintf(stderr, _("%s: %s: undefined reference to '%s'\n"), this->program_name_, relinfo->location(relnum, reloffset).c_str(), - sym->name()); + sym->demangled_name().c_str()); } diff --git a/gold/i386.cc b/gold/i386.cc index b4c7e42160..4a6aa7353f 100644 --- a/gold/i386.cc +++ b/gold/i386.cc @@ -1019,7 +1019,7 @@ Target_i386::Scan::unsupported_reloc_global(Sized_relobj<32, false>* object, Symbol* gsym) { gold_error(_("%s: unsupported reloc %u against global symbol %s"), - object->name().c_str(), r_type, gsym->name()); + object->name().c_str(), r_type, gsym->demangled_name().c_str()); } // Scan a relocation for a global symbol. diff --git a/gold/object.cc b/gold/object.cc index 7a4b1fb41e..ecefa8bf39 100644 --- a/gold/object.cc +++ b/gold/object.cc @@ -25,6 +25,7 @@ #include #include #include +#include "demangle.h" #include "libiberty.h" #include "target-select.h" @@ -1032,7 +1033,20 @@ Sized_relobj::get_symbol_location_info( if (sym.get_st_name() > names_size) info->enclosing_symbol_name = "(invalid)"; else - info->enclosing_symbol_name = symbol_names + sym.get_st_name(); + { + info->enclosing_symbol_name = symbol_names + sym.get_st_name(); + if (parameters->demangle()) + { + char* demangled_name = cplus_demangle( + info->enclosing_symbol_name.c_str(), + DMGL_ANSI | DMGL_PARAMS); + if (demangled_name != NULL) + { + info->enclosing_symbol_name.assign(demangled_name); + free(demangled_name); + } + } + } return true; } } @@ -1155,11 +1169,6 @@ Relocate_info::location(size_t, off_t offset) const if (this->object->get_symbol_location_info(this->data_shndx, offset, &info)) { ret += " in function "; - // We could demangle this name before printing, but we don't - // bother because gcc runs linker output through a demangle - // filter itself. The only advantage to demangling here is if - // someone might call ld directly, rather than via gcc. If we - // did want to demangle, cplus_demangle() is in libiberty. ret += info.enclosing_symbol_name; ret += ":"; filename = info.source_file; diff --git a/gold/options.cc b/gold/options.cc index 69f452dd38..20714359e8 100644 --- a/gold/options.cc +++ b/gold/options.cc @@ -22,6 +22,7 @@ #include "gold.h" +#include #include #include #include "filenames.h" @@ -361,6 +362,11 @@ options::Command_line_options::options[] = &Position_dependent_options::set_static_search), GENERAL_NOARG('\0', "Bsymbolic", N_("Bind defined symbols locally"), NULL, ONE_DASH, &General_options::set_symbolic), + GENERAL_NOARG('\0', "demangle", N_("Demangle C++ symbols in log messages"), + NULL, TWO_DASHES, &General_options::set_demangle), + GENERAL_NOARG('\0', "no-demangle", + N_("Do not demangle C++ symbols in log messages"), + NULL, TWO_DASHES, &General_options::clear_demangle), GENERAL_NOARG('\0', "detect-odr-violations", N_("Try to detect violations of the One Definition Rule"), NULL, TWO_DASHES, &General_options::set_detect_odr_violations), @@ -500,6 +506,12 @@ General_options::General_options() thread_count_final_(0), execstack_(EXECSTACK_FROM_INPUT) { + // We initialize demangle_ based on the environment variable + // COLLECT_NO_DEMANGLE. The gcc collect2 program will demangle the + // output of the linker, unless COLLECT_NO_DEMANGLE is set in the + // environment. Acting the same way here lets us provide the same + // interface by default. + this->demangle_ = getenv("COLLECT_NO_DEMANGLE") == NULL; } // The default values for the position dependent options. diff --git a/gold/options.h b/gold/options.h index b5d2328a1a..1a67a7e27a 100644 --- a/gold/options.h +++ b/gold/options.h @@ -159,6 +159,11 @@ class General_options symbolic() const { return this->symbolic_; } + // --demangle: demangle C++ symbols in our log messages. + bool + demangle() const + { return this->demangle_; } + // --detect-odr-violations: Whether to search for One Defn Rule violations. bool detect_odr_violations() const @@ -318,6 +323,14 @@ class General_options set_symbolic() { this->symbolic_ = true; } + void + set_demangle() + { this->demangle_ = true; } + + void + clear_demangle() + { this->demangle_ = false; } + void set_detect_odr_violations() { this->detect_odr_violations_ = true; } @@ -436,6 +449,7 @@ class General_options Strip strip_; bool allow_shlib_undefined_; bool symbolic_; + bool demangle_; bool detect_odr_violations_; bool create_eh_frame_hdr_; Dir_list rpath_; diff --git a/gold/parameters.cc b/gold/parameters.cc index b96221a8b2..aceb61ee73 100644 --- a/gold/parameters.cc +++ b/gold/parameters.cc @@ -34,7 +34,7 @@ Parameters::Parameters(Errors* errors) : errors_(errors), output_file_name_(NULL), output_file_type_(OUTPUT_INVALID), sysroot_(), strip_(STRIP_INVALID), allow_shlib_undefined_(false), - symbolic_(false), detect_odr_violations_(false), + symbolic_(false), demangle_(false), detect_odr_violations_(false), optimization_level_(0), export_dynamic_(false), is_doing_static_link_valid_(false), doing_static_link_(false), is_size_and_endian_valid_(false), size_(0), is_big_endian_(false) @@ -50,6 +50,7 @@ Parameters::set_from_options(const General_options* options) this->sysroot_ = options->sysroot(); this->allow_shlib_undefined_ = options->allow_shlib_undefined(); this->symbolic_ = options->symbolic(); + this->demangle_ = options->demangle(); this->detect_odr_violations_ = options->detect_odr_violations(); this->optimization_level_ = options->optimization_level(); this->export_dynamic_ = options->export_dynamic(); diff --git a/gold/parameters.h b/gold/parameters.h index ee60b10b4a..b760eceb4c 100644 --- a/gold/parameters.h +++ b/gold/parameters.h @@ -129,6 +129,11 @@ class Parameters return this->symbolic_; } + // Whether we should demangle C++ symbols in our log messages. + bool + demangle() const + { return this->demangle_; } + // Whether we should try to detect violations of the One Definition Rule. bool detect_odr_violations() const @@ -236,6 +241,8 @@ class Parameters bool allow_shlib_undefined_; // Whether we are doing a symbolic link. bool symbolic_; + // Whether we should demangle C++ symbols in our log messages. + bool demangle_; // Whether we try to detect One Definition Rule violations. bool detect_odr_violations_; // The optimization level. diff --git a/gold/resolve.cc b/gold/resolve.cc index b3328d564f..6e3d3acce3 100644 --- a/gold/resolve.cc +++ b/gold/resolve.cc @@ -256,11 +256,11 @@ Symbol_table::resolve(Sized_symbol* to, // on C++ symbols. These have (mangled) names starting with _Z. && to->name()[0] == '_' && to->name()[1] == 'Z') { - Symbol_location from_location + Symbol_location fromloc = { object, orig_sym.get_st_shndx(), orig_sym.get_st_value() }; - Symbol_location to_location = { to->object(), to->shndx(), to->value() }; - this->candidate_odr_violations_[to->name()].insert(from_location); - this->candidate_odr_violations_[to->name()].insert(to_location); + Symbol_location toloc = { to->object(), to->shndx(), to->value() }; + this->candidate_odr_violations_[to->name()].insert(fromloc); + this->candidate_odr_violations_[to->name()].insert(toloc); } } @@ -317,7 +317,7 @@ Symbol_table::should_override(const Symbol* to, unsigned int frombits, // FIXME: Do a better job of reporting locations. gold_error(_("%s: multiple definition of %s"), object != NULL ? object->name().c_str() : _("command line"), - to->name()); + to->demangled_name().c_str()); gold_error(_("%s: previous definition here"), (to->source() == Symbol::FROM_OBJECT ? to->object()->name().c_str() diff --git a/gold/symtab.cc b/gold/symtab.cc index caac2a77fb..c918db3293 100644 --- a/gold/symtab.cc +++ b/gold/symtab.cc @@ -26,6 +26,7 @@ #include #include #include +#include "demangle.h" #include "object.h" #include "dwarf_reader.h" @@ -72,6 +73,32 @@ Symbol::init_fields(const char* name, const char* version, this->needs_value_in_got_ = false; } +// Return the demangled version of the symbol's name, but only +// if the --demangle flag was set. + +static std::string +demangle(const char* name) +{ + // cplus_demangle allocates memory for the result it returns, + // and returns NULL if the name is already demangled. + char* demangled_name = cplus_demangle(name, DMGL_ANSI | DMGL_PARAMS); + if (demangled_name == NULL) + return name; + + std::string retval(demangled_name); + free(demangled_name); + return retval; +} + +std::string +Symbol::demangled_name() const +{ + if (parameters->demangle()) + return demangle(name()); + else + return name(); +} + // Initialize the fields in the base class Symbol for SYM in OBJECT. template @@ -1434,7 +1461,7 @@ Symbol_table::sized_finalize(unsigned index, off_t off, Stringpool* pool) && shndx != elfcpp::SHN_ABS) { gold_error(_("%s: unsupported symbol section 0x%x"), - sym->name(), shndx); + sym->demangled_name().c_str(), shndx); shndx = elfcpp::SHN_UNDEF; } @@ -1647,7 +1674,7 @@ Symbol_table::sized_write_globals(const Input_objects* input_objects, && in_shndx != elfcpp::SHN_ABS) { gold_error(_("%s: unsupported symbol section 0x%x"), - sym->name(), in_shndx); + sym->demangled_name().c_str(), in_shndx); shndx = in_shndx; } else @@ -1771,7 +1798,8 @@ Symbol_table::warn_about_undefined_dynobj_symbol( Dynobj* dynobj = static_cast(sym->object()); if (!dynobj->has_unknown_needed_entries()) gold_error(_("%s: undefined reference to '%s'"), - sym->object()->name().c_str(), sym->name()); + sym->object()->name().c_str(), + sym->demangled_name().c_str()); } } @@ -1883,7 +1911,7 @@ Symbol_table::detect_odr_violations(const char* output_file_name) const { gold_warning(_("while linking %s: symbol %s defined in multiple " "places (possible ODR violation):"), - output_file_name, symbol_name); + output_file_name, demangle(symbol_name).c_str()); for (std::set::const_iterator it2 = line_nums.begin(); it2 != line_nums.end(); ++it2) diff --git a/gold/symtab.h b/gold/symtab.h index 8206cbaa33..b6e550463e 100644 --- a/gold/symtab.h +++ b/gold/symtab.h @@ -98,6 +98,13 @@ class Symbol name() const { return this->name_; } + // Return the (ANSI) demangled version of the name, if + // parameters.demangle() is true. Otherwise, return the name. This + // is intended to be used only for logging errors, so it's not + // super-efficient. + std::string + demangled_name() const; + // Return the symbol version. This will return NULL for an // unversioned symbol. const char* diff --git a/gold/x86_64.cc b/gold/x86_64.cc index 5078237385..992b8bf24c 100644 --- a/gold/x86_64.cc +++ b/gold/x86_64.cc @@ -918,7 +918,7 @@ Target_x86_64::Scan::unsupported_reloc_global(Sized_relobj<64, false>* object, Symbol* gsym) { gold_error(_("%s: unsupported reloc %u against global symbol %s"), - object->name().c_str(), r_type, gsym->name()); + object->name().c_str(), r_type, gsym->demangled_name().c_str()); } // Scan a relocation for a global symbol. @@ -1146,7 +1146,8 @@ Target_x86_64::Scan::global(const General_options& options, case elfcpp::R_X86_64_SIZE64: default: gold_error(_("%s: unsupported reloc %u against global symbol %s"), - object->name().c_str(), r_type, gsym->name()); + object->name().c_str(), r_type, + gsym->demangled_name().c_str()); break; } } -- 2.34.1