From df003d1e0bf2d0a8e2ed45a323d4e974b15dc95f Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Tue, 2 Mar 2021 13:45:56 -0800 Subject: [PATCH] libbacktrace: pass -1 to error callback for unrecognized DWARF PR libbacktrace/98818 * dwarf.c (dwarf_buf_error): Add errnum parameter. Change all callers. * backtrace.h: Update backtrace_error_callback comment. --- libbacktrace/backtrace.h | 15 ++++++----- libbacktrace/dwarf.c | 58 ++++++++++++++++++++++++---------------- 2 files changed, 43 insertions(+), 30 deletions(-) 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 =