From: Andi Kleen <[email protected]>

[v2: Fix some missing discriminator resets in read_line_pprogram]

Add support for reporting GNU discriminators in the libbacktrace full
callback to make it usable for autofdo style usages. The autofdo
file format needs these two bits of information.

There are currently no in tree users for this, but I have some external
software that makes use of it.

For external users this is currently only available through
a new backtrace_pcinfo_extra function. This works the same
as backtrace_pcinfo, except that the callback has an
extra arguments pointing to backtrace_extra with discriminator
and decl_line.

Internally the new callback type is used always since
old callbacks will just ignore the extra argument. This makes the
assumption that no function call ABI changes from an additional argument

"make check" passes with these changes.

libbacktrace/ChangeLog:

        * backtrace.c (struct backtrace_extra): Use backtrace_full_extra
        callback.
        (struct backtrace_data): Dito.
        (unwind): Use pcinfo_extra or pass empty backtrace_extra.
        (backtrace_full): Cast callback to extra variant.
        * backtrace.h (struct backtrace_extra): New structure.
        (backtrace_pcinfo_extra): New function.
        * dwarf.c (struct line): Add disc field.
        (struct function): Add caller_disc and decl_line.
        (add_line): Pass and handle DISC.
        (read_line_program): Handle discriminator. Reset if needed.
        (read_line_info): Dito.
        (read_referenced_name): Support decl_line.
        (read_referenced_name_from_attr): Dito.
        (read_function_entry): Dito.
        (report_inlined_functions): Handle disc and decl_line.
        (dwarf_lookup_pc): Use full_extra_callback and handle
        disc/decl_line.
        (dwarf_fileline): Pass extra_empty_callback.
        * elf.c (elf_nodebug):  Use extra callback.
        * fileline.c (backtrace_pcinfo_extra): New function.
        (backtrace_syminfo): Pass extra argument.
        (backtrace_syminfo_to_full_callback): Dito.
        * internal.h (struct backtrace_call_full):
        (backtrace_extra_empty): New declaration.
        * macho.c (macho_nodebug): Add extra argument to callback.
        * nounwind.c (backtrace_full): Dito.
        * pecoff.c (coff_nodebug): Dito.
        * unknown.c (unknown_fileline): Dito.
        * xcoff.c (xcoff_nodebug): Dito.
        (xcoff_lookup_pc): Dito.
        (xcoff_fileline): Dito.
---
 libbacktrace/backtrace.c |  14 +++--
 libbacktrace/backtrace.h |  26 ++++++++
 libbacktrace/dwarf.c     | 126 +++++++++++++++++++++++++++++----------
 libbacktrace/elf.c       |   2 +-
 libbacktrace/fileline.c  |  26 +++++++-
 libbacktrace/internal.h  |   8 ++-
 libbacktrace/macho.c     |   2 +-
 libbacktrace/nounwind.c  |   2 +-
 libbacktrace/pecoff.c    |   2 +-
 libbacktrace/unknown.c   |   4 +-
 libbacktrace/xcoff.c     |  10 ++--
 11 files changed, 170 insertions(+), 52 deletions(-)

diff --git a/libbacktrace/backtrace.c b/libbacktrace/backtrace.c
index 3935a3ed9682..c617f0bea814 100644
--- a/libbacktrace/backtrace.c
+++ b/libbacktrace/backtrace.c
@@ -38,6 +38,9 @@ POSSIBILITY OF SUCH DAMAGE.  */
 #include "backtrace.h"
 #include "internal.h"
 
+/* Empty backtrace_extra.  */
+struct backtrace_extra backtrace_extra_empty;
+
 /* The main backtrace_full routine.  */
 
 /* Data passed through _Unwind_Backtrace.  */
@@ -49,7 +52,7 @@ struct backtrace_data
   /* Library state.  */
   struct backtrace_state *state;
   /* Callback routine.  */
-  backtrace_full_callback callback;
+  backtrace_full_extra_callback callback;
   /* Error callback routine.  */
   backtrace_error_callback error_callback;
   /* Data to pass to callback routines.  */
@@ -86,9 +89,10 @@ unwind (struct _Unwind_Context *context, void *vdata)
     --pc;
 
   if (!bdata->can_alloc)
-    bdata->ret = bdata->callback (bdata->data, pc, NULL, 0, NULL);
+    bdata->ret = bdata->callback (bdata->data, pc, NULL, 0, NULL,
+                                 &backtrace_extra_empty);
   else
-    bdata->ret = backtrace_pcinfo (bdata->state, pc, bdata->callback,
+    bdata->ret = backtrace_pcinfo_extra (bdata->state, pc, bdata->callback,
                                   bdata->error_callback, bdata->data);
   if (bdata->ret != 0)
     return _URC_END_OF_STACK;
@@ -108,7 +112,9 @@ backtrace_full (struct backtrace_state *state, int skip,
 
   bdata.skip = skip + 1;
   bdata.state = state;
-  bdata.callback = callback;
+  /* Assume backtrace_full_callback and backtrace_full_extra_callback
+     are ABI compatible.  */
+  bdata.callback = (backtrace_full_extra_callback)(void *)callback;
   bdata.error_callback = error_callback;
   bdata.data = data;
   bdata.ret = 0;
diff --git a/libbacktrace/backtrace.h b/libbacktrace/backtrace.h
index fd0c659decc6..0976122c27e1 100644
--- a/libbacktrace/backtrace.h
+++ b/libbacktrace/backtrace.h
@@ -105,6 +105,17 @@ extern struct backtrace_state *backtrace_create_state (
     const char *filename, int threaded,
     backtrace_error_callback error_callback, void *data);
 
+/* Structure with additional useful data passed to callbacks.
+   The pointer to the structure is only valid during the duration of
+   the callback.  */
+struct backtrace_extra
+{
+  /* The discriminator.  */
+  int disc;
+  /* The line number of the function declaration or 0.  */
+  int decl_line;
+};
+
 /* The type of the callback argument to the backtrace_full function.
    DATA is the argument passed to backtrace_full.  PC is the program
    counter.  FILENAME is the name of the file containing PC, or NULL
@@ -114,6 +125,13 @@ extern struct backtrace_state *backtrace_create_state (
    continuing tracing.  The FILENAME and FUNCTION buffers may become
    invalid after this function returns.  */
 
+/* This version of the callback also passes a pointer to backtrace_extra as
+   last argument. It should be used with backtrace_pcinfo_extra.  */
+typedef int (*backtrace_full_extra_callback) (void *data, uintptr_t pc,
+                                       const char *filename, int lineno,
+                                       const char *function,
+                                       struct backtrace_extra *extra);
+
 typedef int (*backtrace_full_callback) (void *data, uintptr_t pc,
                                        const char *filename, int lineno,
                                        const char *function);
@@ -173,6 +191,14 @@ extern int backtrace_pcinfo (struct backtrace_state 
*state, uintptr_t pc,
                             backtrace_error_callback error_callback,
                             void *data);
 
+/* Similar to backtrace_pcinfo, but the full callback also gets backtrace_extra
+   passed as last argument.  */
+
+extern int backtrace_pcinfo_extra (struct backtrace_state *state, uintptr_t pc,
+                            backtrace_full_extra_callback callback,
+                            backtrace_error_callback error_callback,
+                            void *data);
+
 /* The type of the callback argument to backtrace_syminfo.  DATA and
    PC are the arguments passed to backtrace_syminfo.  SYMNAME is the
    name of the symbol for the corresponding code.  SYMVAL is the
diff --git a/libbacktrace/dwarf.c b/libbacktrace/dwarf.c
index ecf32f7688b2..e080cc2adcca 100644
--- a/libbacktrace/dwarf.c
+++ b/libbacktrace/dwarf.c
@@ -234,6 +234,8 @@ struct line
   const char *filename;
   /* Line number.  */
   int lineno;
+  /* Discriminator.  */
+  int disc;
   /* Index of the object in the original array read from the DWARF
      section, before it has been sorted.  The index makes it possible
      to use Quicksort and maintain stability.  */
@@ -263,6 +265,10 @@ struct function
   /* If this is an inlined function, the line number of the call
      site.  */
   int caller_lineno;
+  /* Dito for the discriminator.  */
+  int caller_disc;
+  /* Dito for the line of the declaration.  */
+  int decl_line;
   /* Map PC ranges to inlined functions.  */
   struct function_addrs *function_addrs;
   size_t function_addrs_count;
@@ -2484,18 +2490,17 @@ build_address_map (struct backtrace_state *state,
 
 static int
 add_line (struct backtrace_state *state, struct dwarf_data *ddata,
-         uintptr_t pc, const char *filename, int lineno,
+         uintptr_t pc, const char *filename, int lineno, int disc,
          backtrace_error_callback error_callback, void *data,
          struct line_vector *vec)
 {
   struct line *ln;
 
-  /* If we are adding the same mapping, ignore it.  This can happen
-     when using discriminators.  */
   if (vec->count > 0)
     {
       ln = (struct line *) vec->vec.base + (vec->count - 1);
-      if (pc == ln->pc && filename == ln->filename && lineno == ln->lineno)
+      if (pc == ln->pc && filename == ln->filename && lineno == ln->lineno
+         && ln->disc == disc)
        return 1;
     }
 
@@ -2511,6 +2516,7 @@ add_line (struct backtrace_state *state, struct 
dwarf_data *ddata,
 
   ln->filename = filename;
   ln->lineno = lineno;
+  ln->disc = disc;
   ln->idx = vec->count;
 
   ++vec->count;
@@ -2929,6 +2935,7 @@ read_line_program (struct backtrace_state *state, struct 
dwarf_data *ddata,
   const char *reset_filename;
   const char *filename;
   int lineno;
+  int disc = 0;
 
   address = 0;
   op_index = 0;
@@ -2954,8 +2961,9 @@ read_line_program (struct backtrace_state *state, struct 
dwarf_data *ddata,
                      / hdr->max_ops_per_insn);
          op_index = (op_index + advance) % hdr->max_ops_per_insn;
          lineno += hdr->line_base + (int) (op % hdr->line_range);
-         add_line (state, ddata, address, filename, lineno,
+         add_line (state, ddata, address, filename, lineno, disc,
                    line_buf->error_callback, line_buf->data, vec);
+         disc = 0;
        }
       else if (op == DW_LNS_extended_op)
        {
@@ -2973,6 +2981,7 @@ read_line_program (struct backtrace_state *state, struct 
dwarf_data *ddata,
              op_index = 0;
              filename = reset_filename;
              lineno = 1;
+             disc = 0;
              break;
            case DW_LNE_set_address:
              address = read_address (line_buf, hdr->addrsize);
@@ -3028,8 +3037,7 @@ read_line_program (struct backtrace_state *state, struct 
dwarf_data *ddata,
              }
              break;
            case DW_LNE_set_discriminator:
-             /* We don't care about discriminators.  */
-             read_uleb128 (line_buf);
+             disc = read_uleb128 (line_buf);
              break;
            default:
              if (!advance (line_buf, len - 1))
@@ -3042,8 +3050,9 @@ read_line_program (struct backtrace_state *state, struct 
dwarf_data *ddata,
          switch (op)
            {
            case DW_LNS_copy:
-             add_line (state, ddata, address, filename, lineno,
+             add_line (state, ddata, address, filename, lineno, disc,
                        line_buf->error_callback, line_buf->data, vec);
+             disc = 0;
              break;
            case DW_LNS_advance_pc:
              {
@@ -3183,6 +3192,7 @@ read_line_info (struct backtrace_state *state, struct 
dwarf_data *ddata,
   ln->pc = (uintptr_t) -1;
   ln->filename = NULL;
   ln->lineno = 0;
+  ln->disc = 0;
   ln->idx = 0;
 
   if (!backtrace_vector_release (state, &vec.vec, error_callback, data))
@@ -3206,15 +3216,17 @@ read_line_info (struct backtrace_state *state, struct 
dwarf_data *ddata,
 
 static const char *read_referenced_name (struct dwarf_data *, struct unit *,
                                         uint64_t, backtrace_error_callback,
-                                        void *);
+                                        void *, int *);
 
-/* Read the name of a function from a DIE referenced by ATTR with VAL.  */
+/* Read the name of a function from a DIE referenced by ATTR with VAL.
+   If DECL_LINE is not NULL, and the referenced DIE has a
+   DW_AT_decl_line attribute, store its value in *DECL_LINE.  */
 
 static const char *
 read_referenced_name_from_attr (struct dwarf_data *ddata, struct unit *u,
                                struct attr *attr, struct attr_val *val,
                                backtrace_error_callback error_callback,
-                               void *data)
+                               void *data, int *decl_line)
 {
   switch (attr->name)
     {
@@ -3237,12 +3249,14 @@ read_referenced_name_from_attr (struct dwarf_data 
*ddata, struct unit *u,
        return NULL;
 
       uint64_t offset = val->u.uint - unit->low_offset;
-      return read_referenced_name (ddata, unit, offset, error_callback, data);
+      return read_referenced_name (ddata, unit, offset, error_callback, data,
+                                  decl_line);
     }
 
   if (val->encoding == ATTR_VAL_UINT
       || val->encoding == ATTR_VAL_REF_UNIT)
-    return read_referenced_name (ddata, u, val->u.uint, error_callback, data);
+    return read_referenced_name (ddata, u, val->u.uint, error_callback, data,
+                                decl_line);
 
   if (val->encoding == ATTR_VAL_REF_ALT_INFO)
     {
@@ -3254,7 +3268,7 @@ read_referenced_name_from_attr (struct dwarf_data *ddata, 
struct unit *u,
 
       uint64_t offset = val->u.uint - alt_unit->low_offset;
       return read_referenced_name (ddata->altlink, alt_unit, offset,
-                                  error_callback, data);
+                                  error_callback, data, decl_line);
     }
 
   return NULL;
@@ -3267,7 +3281,7 @@ read_referenced_name_from_attr (struct dwarf_data *ddata, 
struct unit *u,
 static const char *
 read_referenced_name (struct dwarf_data *ddata, struct unit *u,
                      uint64_t offset, backtrace_error_callback error_callback,
-                     void *data)
+                     void *data, int *decl_line)
 {
   struct dwarf_buf unit_buf;
   uint64_t code;
@@ -3359,12 +3373,18 @@ read_referenced_name (struct dwarf_data *ddata, struct 
unit *u,
            const char *name;
 
            name = read_referenced_name_from_attr (ddata, u, &abbrev->attrs[i],
-                                                  &val, error_callback, data);
+                                                  &val, error_callback, data,
+                                                  decl_line);
            if (name != NULL)
              ret = name;
          }
          break;
 
+       case DW_AT_decl_line:
+         if (decl_line != NULL && val.encoding == ATTR_VAL_UINT)
+           *decl_line = val.u.uint;
+         break;
+
        default:
          break;
        }
@@ -3517,6 +3537,16 @@ read_function_entry (struct backtrace_state *state, 
struct dwarf_data *ddata,
                    function->caller_lineno = val.u.uint;
                  break;
 
+               case DW_AT_GNU_discriminator:
+                 if (val.encoding == ATTR_VAL_UINT)
+                   function->caller_disc = val.u.uint;
+                 break;
+
+               case DW_AT_decl_line:
+                 if (val.encoding == ATTR_VAL_UINT)
+                   function->decl_line = val.u.uint;
+                 break;
+
                case DW_AT_abstract_origin:
                case DW_AT_specification:
                  /* Second name preference: override DW_AT_name, don't override
@@ -3529,7 +3559,8 @@ read_function_entry (struct backtrace_state *state, 
struct dwarf_data *ddata,
                    name
                      = read_referenced_name_from_attr (ddata, u,
                                                        &abbrev->attrs[i], &val,
-                                                       error_callback, data);
+                                                       error_callback, data,
+                                                       &function->decl_line);
                    if (name != NULL)
                      function->name = name;
                  }
@@ -3752,17 +3783,20 @@ read_function_info (struct backtrace_state *state, 
struct dwarf_data *ddata,
 }
 
 /* See if PC is inlined in FUNCTION.  If it is, print out the inlined
-   information, and update FILENAME and LINENO for the caller.
+   information, and update FILENAME and LINENO and DISC and DECL_LINE
+   for the caller.
    Returns whatever CALLBACK returns, or 0 to keep going.  */
 
 static int
 report_inlined_functions (uintptr_t pc, struct function *function,
-                         backtrace_full_callback callback, void *data,
-                         const char **filename, int *lineno)
+                         backtrace_full_extra_callback callback, void *data,
+                         const char **filename, int *lineno,
+                         int *disc, int *decl_line)
 {
   struct function_addrs *p;
   struct function_addrs *match;
   struct function *inlined;
+  struct backtrace_extra extra;
   int ret;
 
   if (function->function_addrs_count == 0)
@@ -3811,12 +3845,16 @@ report_inlined_functions (uintptr_t pc, struct function 
*function,
 
   /* Report any calls inlined into this one.  */
   ret = report_inlined_functions (pc, inlined, callback, data,
-                                 filename, lineno);
+                                 filename, lineno, disc, decl_line);
   if (ret != 0)
     return ret;
 
   /* Report this inlined call.  */
-  ret = callback (data, pc, *filename, *lineno, inlined->name);
+  extra.disc = *disc;
+  /* Report the declaration line of the inlined function itself, not the
+     value threaded in from the caller.  */
+  extra.decl_line = inlined->decl_line;
+  ret = callback (data, pc, *filename, *lineno, inlined->name, &extra);
   if (ret != 0)
     return ret;
 
@@ -3824,6 +3862,7 @@ report_inlined_functions (uintptr_t pc, struct function 
*function,
      it the appropriate filename and line number.  */
   *filename = inlined->caller_filename;
   *lineno = inlined->caller_lineno;
+  *disc = inlined->caller_disc;
 
   return 0;
 }
@@ -3835,7 +3874,7 @@ report_inlined_functions (uintptr_t pc, struct function 
*function,
 
 static int
 dwarf_lookup_pc (struct backtrace_state *state, struct dwarf_data *ddata,
-                uintptr_t pc, backtrace_full_callback callback,
+                uintptr_t pc, backtrace_full_extra_callback callback,
                 backtrace_error_callback error_callback, void *data,
                 int *found)
 {
@@ -3850,7 +3889,10 @@ dwarf_lookup_pc (struct backtrace_state *state, struct 
dwarf_data *ddata,
   struct function *function;
   const char *filename;
   int lineno;
+  int disc = 0;
+  int decl_line = 0;
   int ret;
+  struct backtrace_extra extra;
 
   *found = 1;
 
@@ -3991,7 +4033,7 @@ dwarf_lookup_pc (struct backtrace_state *state, struct 
dwarf_data *ddata,
       if (new_data)
        return dwarf_lookup_pc (state, ddata, pc, callback, error_callback,
                                data, found);
-      return callback (data, pc, NULL, 0, NULL);
+      return callback (data, pc, NULL, 0, NULL, &backtrace_extra_empty);
     }
 
   /* Search for PC within this unit.  */
@@ -4038,13 +4080,18 @@ dwarf_lookup_pc (struct backtrace_state *state, struct 
dwarf_data *ddata,
          entry->u->abs_filename = filename;
        }
 
-      return callback (data, pc, entry->u->abs_filename, 0, NULL);
+      return callback (data, pc, entry->u->abs_filename, 0, NULL,
+                      &backtrace_extra_empty);
     }
 
   /* Search for function name within this unit.  */
 
   if (entry->u->function_addrs_count == 0)
-    return callback (data, pc, ln->filename, ln->lineno, NULL);
+    {
+      extra.decl_line = 0;
+      extra.disc = ln->disc;
+      return callback (data, pc, ln->filename, ln->lineno, NULL, &extra);
+    }
 
   p = ((struct function_addrs *)
        bsearch (&pc, entry->u->function_addrs,
@@ -4052,7 +4099,11 @@ dwarf_lookup_pc (struct backtrace_state *state, struct 
dwarf_data *ddata,
                sizeof (struct function_addrs),
                function_addrs_search));
   if (p == NULL)
-    return callback (data, pc, ln->filename, ln->lineno, NULL);
+    {
+      extra.decl_line = 0;
+      extra.disc = ln->disc;
+      return callback (data, pc, ln->filename, ln->lineno, NULL, &extra);
+    }
 
   /* Here pc >= p->low && pc < (p + 1)->low.  The function_addrs are
      sorted by low, so if pc > p->low we are at the end of a range of
@@ -4076,19 +4127,30 @@ dwarf_lookup_pc (struct backtrace_state *state, struct 
dwarf_data *ddata,
       --p;
     }
   if (fmatch == NULL)
-    return callback (data, pc, ln->filename, ln->lineno, NULL);
+    {
+      extra.decl_line = 0;
+      extra.disc = ln->disc;
+      return callback (data, pc, ln->filename, ln->lineno, NULL, &extra);
+    }
 
   function = fmatch->function;
 
   filename = ln->filename;
   lineno = ln->lineno;
+  disc = ln->disc;
 
   ret = report_inlined_functions (pc, function, callback, data,
-                                 &filename, &lineno);
+                                 &filename, &lineno, &disc, &decl_line);
   if (ret != 0)
     return ret;
 
-  return callback (data, pc, filename, lineno, function->name);
+  extra.disc = disc;
+  /* For the outermost (non-inlined) function report its own declaration
+     line.  The DECL_LINE variable updated by report_inlined_functions
+     carries the declaration line of the innermost inlined callee, which
+     is not what we want for the containing function.  */
+  extra.decl_line = function->decl_line;
+  return callback (data, pc, filename, lineno, function->name, &extra);
 }
 
 
@@ -4097,7 +4159,7 @@ dwarf_lookup_pc (struct backtrace_state *state, struct 
dwarf_data *ddata,
 
 static int
 dwarf_fileline (struct backtrace_state *state, uintptr_t pc,
-               backtrace_full_callback callback,
+               backtrace_full_extra_callback callback,
                backtrace_error_callback error_callback, void *data)
 {
   struct dwarf_data *ddata;
@@ -4138,7 +4200,7 @@ dwarf_fileline (struct backtrace_state *state, uintptr_t 
pc,
 
   /* FIXME: See if any libraries have been dlopen'ed.  */
 
-  return callback (data, pc, NULL, 0, NULL);
+  return callback (data, pc, NULL, 0, NULL, &backtrace_extra_empty);
 }
 
 /* Initialize our data structures from the DWARF debug info for a
diff --git a/libbacktrace/elf.c b/libbacktrace/elf.c
index 46607f6fb8d0..a75b065e62a8 100644
--- a/libbacktrace/elf.c
+++ b/libbacktrace/elf.c
@@ -570,7 +570,7 @@ elf_nosyms (struct backtrace_state *state ATTRIBUTE_UNUSED,
 
 static int
 elf_nodebug (struct backtrace_state *state, uintptr_t pc,
-            backtrace_full_callback callback,
+            backtrace_full_extra_callback callback,
             backtrace_error_callback error_callback, void *data)
 {
   if (state->syminfo_fn != NULL && state->syminfo_fn != elf_nosyms)
diff --git a/libbacktrace/fileline.c b/libbacktrace/fileline.c
index 82535e3f6cfb..52133ba4f771 100644
--- a/libbacktrace/fileline.c
+++ b/libbacktrace/fileline.c
@@ -393,9 +393,31 @@ backtrace_pcinfo (struct backtrace_state *state, uintptr_t 
pc,
   if (state->fileline_initialization_failed)
     return 0;
 
+  /* Just cast the callback because the addition of an argument at the end
+     is ABI compatible.  */
+  return state->fileline_fn (state, pc,
+                            (backtrace_full_extra_callback)(void 
(*)(void))callback,
+                            error_callback, data);
+}
+
+/* Given a PC, find the file name, line number, and function name.
+   This version has a full callback that passes the backtrace_extra.  */
+
+int
+backtrace_pcinfo_extra (struct backtrace_state *state, uintptr_t pc,
+                 backtrace_full_extra_callback callback,
+                 backtrace_error_callback error_callback, void *data)
+{
+  if (!fileline_initialize (state, error_callback, data))
+    return 0;
+
+  if (state->fileline_initialization_failed)
+    return 0;
+
   return state->fileline_fn (state, pc, callback, error_callback, data);
 }
 
+
 /* Given a PC, find the symbol for it, and its value.  */
 
 int
@@ -414,7 +436,7 @@ backtrace_syminfo (struct backtrace_state *state, uintptr_t 
pc,
 }
 
 /* A backtrace_syminfo_callback that can call into a
-   backtrace_full_callback, used when we have a symbol table but no
+   backtrace_full_extra_callback, used when we have a symbol table but no
    debug info.  */
 
 void
@@ -425,7 +447,7 @@ backtrace_syminfo_to_full_callback (void *data, uintptr_t 
pc,
 {
   struct backtrace_call_full *bdata = (struct backtrace_call_full *) data;
 
-  bdata->ret = bdata->full_callback (bdata->full_data, pc, NULL, 0, symname);
+  bdata->ret = bdata->full_callback (bdata->full_data, pc, NULL, 0, symname, 
0);
 }
 
 /* An error callback that corresponds to
diff --git a/libbacktrace/internal.h b/libbacktrace/internal.h
index 09a2147fdef1..290f54303168 100644
--- a/libbacktrace/internal.h
+++ b/libbacktrace/internal.h
@@ -125,7 +125,7 @@ extern void backtrace_atomic_store_int (int *, int);
    is like backtrace_pcinfo.  */
 
 typedef int (*fileline) (struct backtrace_state *state, uintptr_t pc,
-                        backtrace_full_callback callback,
+                        backtrace_full_extra_callback callback,
                         backtrace_error_callback error_callback, void *data);
 
 /* The type of the function that collects symbol information.  This is
@@ -377,14 +377,14 @@ extern int backtrace_dwarf_add (struct backtrace_state 
*state,
 
 struct backtrace_call_full
 {
-  backtrace_full_callback full_callback;
+  backtrace_full_extra_callback full_callback;
   backtrace_error_callback full_error_callback;
   void *full_data;
   int ret;
 };
 
 /* A backtrace_syminfo_callback that can call into a
-   backtrace_full_callback, used when we have a symbol table but no
+   backtrace_full_extra_callback, used when we have a symbol table but no
    debug info.  */
 
 extern void backtrace_syminfo_to_full_callback (void *data, uintptr_t pc,
@@ -424,5 +424,7 @@ extern int backtrace_uncompress_lzma (struct 
backtrace_state *,
                                      backtrace_error_callback, void *data,
                                      unsigned char **uncompressed,
                                      size_t *uncompressed_size);
+/* An empty backtrace_extra.  */
+extern struct backtrace_extra backtrace_extra_empty;
 
 #endif
diff --git a/libbacktrace/macho.c b/libbacktrace/macho.c
index 5eab4a6c7f85..1da93c610478 100644
--- a/libbacktrace/macho.c
+++ b/libbacktrace/macho.c
@@ -324,7 +324,7 @@ static int macho_add (struct backtrace_state *, const char 
*, int, off_t,
 static int
 macho_nodebug (struct backtrace_state *state ATTRIBUTE_UNUSED,
               uintptr_t pc ATTRIBUTE_UNUSED,
-              backtrace_full_callback callback ATTRIBUTE_UNUSED,
+              backtrace_full_extra_callback callback ATTRIBUTE_UNUSED,
               backtrace_error_callback error_callback, void *data)
 {
   error_callback (data, "no debug info in Mach-O executable (make sure to 
compile with -g; may need to run dsymutil)", -1);
diff --git a/libbacktrace/nounwind.c b/libbacktrace/nounwind.c
index 29c44f8c2c44..b047ccc6b1e2 100644
--- a/libbacktrace/nounwind.c
+++ b/libbacktrace/nounwind.c
@@ -44,7 +44,7 @@ POSSIBILITY OF SUCH DAMAGE.  */
 int
 backtrace_full (struct backtrace_state *state ATTRIBUTE_UNUSED,
                int skip ATTRIBUTE_UNUSED,
-               backtrace_full_callback callback ATTRIBUTE_UNUSED,
+               backtrace_full_extra_callback callback ATTRIBUTE_UNUSED,
                backtrace_error_callback error_callback, void *data)
 {
   error_callback (data,
diff --git a/libbacktrace/pecoff.c b/libbacktrace/pecoff.c
index f2b1aa5023ab..ea8e9a1a2a15 100644
--- a/libbacktrace/pecoff.c
+++ b/libbacktrace/pecoff.c
@@ -237,7 +237,7 @@ struct coff_syminfo_data
 static int
 coff_nodebug (struct backtrace_state *state ATTRIBUTE_UNUSED,
              uintptr_t pc ATTRIBUTE_UNUSED,
-             backtrace_full_callback callback ATTRIBUTE_UNUSED,
+             backtrace_full_extra_callback callback ATTRIBUTE_UNUSED,
              backtrace_error_callback error_callback, void *data)
 {
   error_callback (data, "no debug info in PE/COFF executable (make sure to 
compile with -g)", -1);
diff --git a/libbacktrace/unknown.c b/libbacktrace/unknown.c
index 4834ec92c182..b7c548a4cf95 100644
--- a/libbacktrace/unknown.c
+++ b/libbacktrace/unknown.c
@@ -41,12 +41,12 @@ POSSIBILITY OF SUCH DAMAGE.  */
 
 static int
 unknown_fileline (struct backtrace_state *state ATTRIBUTE_UNUSED,
-                 uintptr_t pc, backtrace_full_callback callback,
+                 uintptr_t pc, backtrace_full_extra_callback callback,
                  backtrace_error_callback error_callback ATTRIBUTE_UNUSED,
                  void *data)
 
 {
-  return callback (data, pc, NULL, 0, NULL);
+  return callback (data, pc, NULL, 0, NULL, &backtrace_extra_empty);
 }
 
 /* Initialize the backtrace data when we don't know how to read the
diff --git a/libbacktrace/xcoff.c b/libbacktrace/xcoff.c
index 874642ab3548..255313cf12da 100644
--- a/libbacktrace/xcoff.c
+++ b/libbacktrace/xcoff.c
@@ -405,7 +405,7 @@ struct dwsect_info
 static int
 xcoff_nodebug (struct backtrace_state *state ATTRIBUTE_UNUSED,
               uintptr_t pc ATTRIBUTE_UNUSED,
-              backtrace_full_callback callback ATTRIBUTE_UNUSED,
+              backtrace_full_extra_callback callback ATTRIBUTE_UNUSED,
               backtrace_error_callback error_callback, void *data)
 {
   error_callback (data, "no debug info in XCOFF executable", -1);
@@ -725,7 +725,7 @@ xcoff_incl_search (const void *vkey, const void *ventry)
 static int
 xcoff_lookup_pc (struct backtrace_state *state ATTRIBUTE_UNUSED,
                 struct xcoff_fileline_data *fdata, uintptr_t pc,
-                backtrace_full_callback callback,
+                backtrace_full_extra_callback callback,
                 backtrace_error_callback error_callback ATTRIBUTE_UNUSED,
                 void *data, int *found)
 {
@@ -805,7 +805,7 @@ xcoff_lookup_pc (struct backtrace_state *state 
ATTRIBUTE_UNUSED,
   /* AIX prepends a '.' to function entry points, remove it.  */
   if (function != NULL && *function == '.')
     ++function;
-  return callback (data, pc, filename, lnno, function);
+  return callback (data, pc, filename, lnno, function, 0);
 }
 
 /* Return the file/line information for a PC using the XCOFF lineno
@@ -813,7 +813,7 @@ xcoff_lookup_pc (struct backtrace_state *state 
ATTRIBUTE_UNUSED,
 
 static int
 xcoff_fileline (struct backtrace_state *state, uintptr_t pc,
-               backtrace_full_callback callback,
+               backtrace_full_extra_callback callback,
                backtrace_error_callback error_callback, void *data)
 
 {
@@ -855,7 +855,7 @@ xcoff_fileline (struct backtrace_state *state, uintptr_t pc,
 
   /* FIXME: See if any libraries have been dlopen'ed.  */
 
-  return callback (data, pc, NULL, 0, NULL);
+  return callback (data, pc, NULL, 0, NULL, &backtrace_extra_empty);
 }
 
 /* Initialize the function vector info for xcoff_fileline.  */
-- 
2.54.0

Reply via email to