This libbacktrace patch passes -1 to the error callback function for
unknown DWARF versions.  This makes users of libbacktrace treat DWARF
versions that libbacktrace does not support as though no debug
information were available.  This fixes PR 98818.  Bootstrapped and
ran libbacktrace tests on x86_64-pc-linux-gnu.  Committed to mainline.

Ian

* dwarf.c (dwarf_buf_error): Add errnum parameter.  Change all
callers.
* backtrace.h: Update backtrace_error_callback comment.
df003d1e0bf2d0a8e2ed45a323d4e974b15dc95f
diff --git a/libbacktrace/backtrace.h b/libbacktrace/backtrace.h
index 2814763f417..caaa66d3686 100644
--- a/libbacktrace/backtrace.h
+++ b/libbacktrace/backtrace.h
@@ -71,13 +71,14 @@ struct backtrace_state;
    invalid after this function returns.
 
    As a special case, the ERRNUM argument will be passed as -1 if no
-   debug info can be found for the executable, but the function
-   requires debug info (e.g., backtrace_full, backtrace_pcinfo).  The
-   MSG in this case will be something along the lines of "no debug
-   info".  Similarly, ERRNUM will be passed as -1 if there is no
-   symbol table, but the function requires a symbol table (e.g.,
-   backtrace_syminfo).  This may be used as a signal that some other
-   approach should be tried.  */
+   debug info can be found for the executable, or if the debug info
+   exists but has an unsupported version, but the function requires
+   debug info (e.g., backtrace_full, backtrace_pcinfo).  The MSG in
+   this case will be something along the lines of "no debug info".
+   Similarly, ERRNUM will be passed as -1 if there is no symbol table,
+   but the function requires a symbol table (e.g., backtrace_syminfo).
+   This may be used as a signal that some other approach should be
+   tried.  */
 
 typedef void (*backtrace_error_callback) (void *data, const char *msg,
                                          int errnum);
diff --git a/libbacktrace/dwarf.c b/libbacktrace/dwarf.c
index 9097df6cc76..546b4b26a32 100644
--- a/libbacktrace/dwarf.c
+++ b/libbacktrace/dwarf.c
@@ -410,13 +410,13 @@ struct dwarf_data
 /* Report an error for a DWARF buffer.  */
 
 static void
-dwarf_buf_error (struct dwarf_buf *buf, const char *msg)
+dwarf_buf_error (struct dwarf_buf *buf, const char *msg, int errnum)
 {
   char b[200];
 
   snprintf (b, sizeof b, "%s in %s at %d",
            msg, buf->name, (int) (buf->buf - buf->start));
-  buf->error_callback (buf->data, b, 0);
+  buf->error_callback (buf->data, b, errnum);
 }
 
 /* Require at least COUNT bytes in BUF.  Return 1 if all is well, 0 on
@@ -430,7 +430,7 @@ require (struct dwarf_buf *buf, size_t count)
 
   if (!buf->reported_underflow)
     {
-      dwarf_buf_error (buf, "DWARF underflow");
+      dwarf_buf_error (buf, "DWARF underflow", 0);
       buf->reported_underflow = 1;
     }
 
@@ -592,7 +592,7 @@ read_address (struct dwarf_buf *buf, int addrsize)
     case 8:
       return read_uint64 (buf);
     default:
-      dwarf_buf_error (buf, "unrecognized address size");
+      dwarf_buf_error (buf, "unrecognized address size", 0);
       return 0;
     }
 }
@@ -643,7 +643,7 @@ read_uleb128 (struct dwarf_buf *buf)
        ret |= ((uint64_t) (b & 0x7f)) << shift;
       else if (!overflow)
        {
-         dwarf_buf_error (buf, "LEB128 overflows uint64_t");
+         dwarf_buf_error (buf, "LEB128 overflows uint64_t", 0);
          overflow = 1;
        }
       shift += 7;
@@ -678,7 +678,7 @@ read_sleb128 (struct dwarf_buf *buf)
        val |= ((uint64_t) (b & 0x7f)) << shift;
       else if (!overflow)
        {
-         dwarf_buf_error (buf, "signed LEB128 overflows uint64_t");
+         dwarf_buf_error (buf, "signed LEB128 overflows uint64_t", 0);
          overflow = 1;
        }
       shift += 7;
@@ -818,7 +818,7 @@ read_attribute (enum dwarf_form form, uint64_t implicit_val,
        offset = read_offset (buf, is_dwarf64);
        if (offset >= dwarf_sections->size[DEBUG_STR])
          {
-           dwarf_buf_error (buf, "DW_FORM_strp out of range");
+           dwarf_buf_error (buf, "DW_FORM_strp out of range", 0);
            return 0;
          }
        val->encoding = ATTR_VAL_STRING;
@@ -833,7 +833,7 @@ read_attribute (enum dwarf_form form, uint64_t implicit_val,
        offset = read_offset (buf, is_dwarf64);
        if (offset >= dwarf_sections->size[DEBUG_LINE_STR])
          {
-           dwarf_buf_error (buf, "DW_FORM_line_strp out of range");
+           dwarf_buf_error (buf, "DW_FORM_line_strp out of range", 0);
            return 0;
          }
        val->encoding = ATTR_VAL_STRING;
@@ -880,7 +880,8 @@ read_attribute (enum dwarf_form form, uint64_t implicit_val,
        if (form == DW_FORM_implicit_const)
          {
            dwarf_buf_error (buf,
-                            "DW_FORM_indirect to DW_FORM_implicit_const");
+                            "DW_FORM_indirect to DW_FORM_implicit_const",
+                            0);
            return 0;
          }
        return read_attribute ((enum dwarf_form) form, 0, buf, is_dwarf64,
@@ -1013,7 +1014,7 @@ read_attribute (enum dwarf_form form, uint64_t 
implicit_val,
          }
        if (offset >= altlink->dwarf_sections.size[DEBUG_STR])
          {
-           dwarf_buf_error (buf, "DW_FORM_strp_sup out of range");
+           dwarf_buf_error (buf, "DW_FORM_strp_sup out of range", 0);
            return 0;
          }
        val->encoding = ATTR_VAL_STRING;
@@ -1022,7 +1023,7 @@ read_attribute (enum dwarf_form form, uint64_t 
implicit_val,
        return 1;
       }
     default:
-      dwarf_buf_error (buf, "unrecognized DWARF form");
+      dwarf_buf_error (buf, "unrecognized DWARF form", -1);
       return 0;
     }
 }
@@ -1071,7 +1072,9 @@ resolve_string (const struct dwarf_sections 
*dwarf_sections, int is_dwarf64,
        offset = read_offset (&offset_buf, is_dwarf64);
        if (offset >= dwarf_sections->size[DEBUG_STR])
          {
-           dwarf_buf_error (&offset_buf, "DW_FORM_strx offset out of range");
+           dwarf_buf_error (&offset_buf,
+                            "DW_FORM_strx offset out of range",
+                            0);
            return 0;
          }
        *string = (const char *) dwarf_sections->data[DEBUG_STR] + offset;
@@ -1879,7 +1882,7 @@ add_ranges_from_rnglists (
          break;
 
        default:
-         dwarf_buf_error (&rnglists_buf, "unrecognized DW_RLE value");
+         dwarf_buf_error (&rnglists_buf, "unrecognized DW_RLE value", -1);
          return 0;
        }
     }
@@ -2146,7 +2149,7 @@ build_address_map (struct backtrace_state *state, 
uintptr_t base_address,
       version = read_uint16 (&unit_buf);
       if (version < 2 || version > 5)
        {
-         dwarf_buf_error (&unit_buf, "unrecognized DWARF version");
+         dwarf_buf_error (&unit_buf, "unrecognized DWARF version", -1);
          goto fail;
        }
 
@@ -2425,7 +2428,8 @@ read_v2_paths (struct backtrace_state *state, struct unit 
*u,
            {
              dwarf_buf_error (hdr_buf,
                               ("invalid directory index in "
-                               "line number program header"));
+                               "line number program header"),
+                              0);
              return 0;
            }
          dir_len = strlen (dir);
@@ -2494,7 +2498,8 @@ read_lnct (struct backtrace_state *state, struct 
dwarf_data *ddata,
                {
                  dwarf_buf_error (hdr_buf,
                                   ("invalid directory index in "
-                                   "line number program header"));
+                                   "line number program header"),
+                                  0);
                  return 0;
                }
              dir = hdr->dirs[val.u.uint];
@@ -2509,7 +2514,8 @@ read_lnct (struct backtrace_state *state, struct 
dwarf_data *ddata,
   if (path == NULL)
     {
       dwarf_buf_error (hdr_buf,
-                      "missing file name in line number program header");
+                      "missing file name in line number program header",
+                      0);
       return 0;
     }
 
@@ -2636,7 +2642,7 @@ read_line_header (struct backtrace_state *state, struct 
dwarf_data *ddata,
   hdr->version = read_uint16 (line_buf);
   if (hdr->version < 2 || hdr->version > 5)
     {
-      dwarf_buf_error (line_buf, "unsupported line number version");
+      dwarf_buf_error (line_buf, "unsupported line number version", -1);
       return 0;
     }
 
@@ -2650,7 +2656,8 @@ read_line_header (struct backtrace_state *state, struct 
dwarf_data *ddata,
       if (read_byte (line_buf) != 0)
        {
          dwarf_buf_error (line_buf,
-                          "non-zero segment_selector_size not supported");
+                          "non-zero segment_selector_size not supported",
+                          -1);
          return 0;
        }
     }
@@ -2791,7 +2798,8 @@ read_line_program (struct backtrace_state *state, struct 
dwarf_data *ddata,
                      {
                        dwarf_buf_error (line_buf,
                                         ("invalid directory index "
-                                         "in line number program"));
+                                         "in line number program"),
+                                        0);
                        return 0;
                      }
                    dir_len = strlen (dir);
@@ -2857,7 +2865,8 @@ read_line_program (struct backtrace_state *state, struct 
dwarf_data *ddata,
                      {
                        dwarf_buf_error (line_buf,
                                         ("invalid file number in "
-                                         "line number program"));
+                                         "line number program"),
+                                        0);
                        return 0;
                      }
                    filename = hdr->filenames[fileno];
@@ -3092,7 +3101,9 @@ read_referenced_name (struct dwarf_data *ddata, struct 
unit *u,
   code = read_uleb128 (&unit_buf);
   if (code == 0)
     {
-      dwarf_buf_error (&unit_buf, "invalid abstract origin or specification");
+      dwarf_buf_error (&unit_buf,
+                      "invalid abstract origin or specification",
+                      0);
       return NULL;
     }
 
@@ -3295,7 +3306,8 @@ read_function_entry (struct backtrace_state *state, 
struct dwarf_data *ddata,
                            {
                              dwarf_buf_error (unit_buf,
                                               ("invalid file number in "
-                                               "DW_AT_call_file attribute"));
+                                               "DW_AT_call_file attribute"),
+                                              0);
                              return 0;
                            }
                          function->caller_filename =

Reply via email to