void operator()

in src/backward.h [2852:2947]


        void operator()(Dwarf_Die die, std::vector<std::string>& ns)
        {
            Dwarf_Error error = DW_DLE_NE;
            Dwarf_Half tag_value;
            Dwarf_Attribute attr_mem;
            Dwarf_Debug dwarf = fobj.dwarf_handle.get();

            dwarf_tag(die, &tag_value, &error);

            switch (tag_value) {
                char* name;
                case DW_TAG_subprogram:
                    if (!trace.source.function.empty())
                        break;
                    if (dwarf_diename(die, &name, &error) == DW_DLV_OK) {
                        trace.source.function = std::string(name);
                        dwarf_dealloc(dwarf, name, DW_DLA_STRING);
                    }
                    else {
                        // We don't have a function name in this DIE.
                        // Check if there is a referenced non-defining
                        // declaration.
                        trace.source.function = get_referenced_die_name(dwarf, die, DW_AT_abstract_origin, true);
                        if (trace.source.function.empty()) {
                            trace.source.function = get_referenced_die_name(dwarf, die, DW_AT_specification, true);
                        }
                    }

                    // Append the function parameters, if available
                    set_function_parameters(trace.source.function, ns, fobj, die);

                    // If the object function name is empty, it's possible that
                    // there is no dynamic symbol table (maybe the executable
                    // was stripped or not built with -rdynamic). See if we have
                    // a DWARF linkage name to use instead. We try both
                    // linkage_name and MIPS_linkage_name because the MIPS tag
                    // was the unofficial one until it was adopted in DWARF4.
                    // Old gcc versions generate MIPS_linkage_name
                    if (trace.object_function.empty()) {
                        details::demangler demangler;

                        if (dwarf_attr(die, DW_AT_linkage_name, &attr_mem, &error) != DW_DLV_OK) {
                            if (dwarf_attr(die, DW_AT_MIPS_linkage_name, &attr_mem, &error) != DW_DLV_OK) {
                                break;
                            }
                        }

                        char* linkage;
                        if (dwarf_formstring(attr_mem, &linkage, &error) == DW_DLV_OK) {
                            trace.object_function = demangler.demangle(linkage);
                            dwarf_dealloc(dwarf, linkage, DW_DLA_STRING);
                        }
                        dwarf_dealloc(dwarf, name, DW_DLA_ATTR);
                    }
                    break;

                case DW_TAG_inlined_subroutine:
                    ResolvedTrace::SourceLoc sloc;

                    if (dwarf_diename(die, &name, &error) == DW_DLV_OK) {
                        sloc.function = std::string(name);
                        dwarf_dealloc(dwarf, name, DW_DLA_STRING);
                    }
                    else {
                        // We don't have a name for this inlined DIE, it could
                        // be that there is an abstract origin instead.
                        // Get the DW_AT_abstract_origin value, which is a
                        // reference to the source DIE and try to get its name
                        sloc.function = get_referenced_die_name(dwarf, die, DW_AT_abstract_origin, true);
                    }

                    set_function_parameters(sloc.function, ns, fobj, die);

                    std::string file = die_call_file(dwarf, die, cu_die);
                    if (!file.empty())
                        sloc.filename = file;

                    Dwarf_Unsigned number = 0;
                    if (dwarf_attr(die, DW_AT_call_line, &attr_mem, &error) == DW_DLV_OK) {
                        if (dwarf_formudata(attr_mem, &number, &error) == DW_DLV_OK) {
                            sloc.line = number;
                        }
                        dwarf_dealloc(dwarf, attr_mem, DW_DLA_ATTR);
                    }

                    if (dwarf_attr(die, DW_AT_call_column, &attr_mem, &error) == DW_DLV_OK) {
                        if (dwarf_formudata(attr_mem, &number, &error) == DW_DLV_OK) {
                            sloc.col = number;
                        }
                        dwarf_dealloc(dwarf, attr_mem, DW_DLA_ATTR);
                    }

                    trace.inliners.push_back(sloc);
                    break;
            };
        }