// Demangle updates the function names in a profile with demangled C++ // names, simplified according to demanglerMode. If force is set, // overwrite any names that appear already demangled. func Demangle(prof *profile.Profile, force bool, demanglerMode string) { if force { // Remove the current demangled names to force demangling for _, f := range prof.Function { if f.Name != "" && f.SystemName != "" { f.Name = f.SystemName } } } var options []demangle.Option switch demanglerMode { case "": // demangled, simplified: no parameters, no templates, no return type options = []demangle.Option{demangle.NoParams, demangle.NoTemplateParams} case "templates": // demangled, simplified: no parameters, no return type options = []demangle.Option{demangle.NoParams} case "full": options = []demangle.Option{demangle.NoClones} case "none": // no demangling return } // Copy the options because they may be updated by the call. o := make([]demangle.Option, len(options)) for _, fn := range prof.Function { if fn.Name != "" && fn.SystemName != fn.Name { continue // Already demangled. } copy(o, options) if demangled := demangle.Filter(fn.SystemName, o...); demangled != fn.SystemName { fn.Name = demangled continue } // Could not demangle. Apply heuristics in case the name is // already demangled. name := fn.SystemName if looksLikeDemangledCPlusPlus(name) { if demanglerMode == "" || demanglerMode == "templates" { name = removeMatching(name, '(', ')') } if demanglerMode == "" { name = removeMatching(name, '<', '>') } } fn.Name = name } }
// Demangle a string just as the GNU c++filt program does. func doDemangle(out *bufio.Writer, name string) { skip := 0 if name[0] == '.' || name[0] == '$' { skip++ } if *stripUnderscore && name[skip] == '_' { skip++ } result := demangle.Filter(name[skip:], options()...) if result == name[skip:] { out.WriteString(name) } else { if name[0] == '.' { out.WriteByte('.') } out.WriteString(result) } }