/* dwarf.c -- display DWARF contents of a BFD binary file
- Copyright (C) 2005-2022 Free Software Foundation, Inc.
+ Copyright (C) 2005-2023 Free Software Foundation, Inc.
This file is part of GNU Binutils.
value & ~(~(uint64_t) 0 << num_bytes * 4 << num_bytes * 4));
}
+static const char *
+null_name (const char *p)
+{
+ if (p == NULL)
+ p = _("unknown");
+ return p;
+}
+
/* Read in a LEB128 encoded value starting at address DATA.
If SIGN is true, return a signed LEB128 value.
If LENGTH_RETURN is not NULL, return in it the number of bytes read.
return -1;
}
+ if (section->size < 4)
+ {
+ warn (_("Section %s is too small to contain an value indexed from another section!\n"),
+ section->name);
+ return -1;
+ }
+
uint32_t pointer_size, bias;
if (byte_get (section->start, 4) == 0xffffffff)
list->first_abbrev = NULL;
list->last_abbrev = NULL;
list->raw = start;
+ list->next = NULL;
while (start < end)
{
the caller. */
if (start == end || entry == 0)
{
- list->next = NULL;
list->start_of_next_abbrevs = start != end ? start : NULL;
return list;
}
READ_ULEB (tag, start, end);
if (start == end)
- {
- free (list);
- return NULL;
- }
+ return free_abbrev_list (list);
children = *start++;
/* Report the missing single zero which ends the section. */
error (_("%s section not zero terminated\n"), section->name);
- free (list);
- return NULL;
+ return free_abbrev_list (list);
}
/* Return a sequence of abbrevs in SECTION starting at ABBREV_BASE
break;
default:
- warn (_("Unrecognized form: %#lx\n"), form);
+ warn (_("Unrecognized form: %#lx"), form);
/* What to do? Consume a byte maybe? */
++data;
break;
"(%#" PRIx64 " and %#" PRIx64 ")"),
debug_info_p->cu_offset,
debug_info_p->loclists_base, uvalue);
+ svalue = uvalue;
+ if (svalue < 0)
+ {
+ warn (_("CU @ %#" PRIx64 " has has a negative loclists_base "
+ "value of %#" PRIx64 " - treating as zero"),
+ debug_info_p->cu_offset, svalue);
+ uvalue = 0;
+ }
debug_info_p->loclists_base = uvalue;
break;
+
case DW_AT_rnglists_base:
if (debug_info_p->rnglists_base)
warn (_("CU @ %#" PRIx64 " has multiple rnglists_base values "
"(%#" PRIx64 " and %#" PRIx64 ")"),
debug_info_p->cu_offset,
debug_info_p->rnglists_base, uvalue);
+ svalue = uvalue;
+ if (svalue < 0)
+ {
+ warn (_("CU @ %#" PRIx64 " has has a negative rnglists_base "
+ "value of %#" PRIx64 " - treating as zero"),
+ debug_info_p->cu_offset, svalue);
+ uvalue = 0;
+ }
debug_info_p->rnglists_base = uvalue;
break;
+
case DW_AT_str_offsets_base:
if (debug_info_p->str_offsets_base)
warn (_("CU @ %#" PRIx64 " has multiple str_offsets_base values "
"%#" PRIx64 " and %#" PRIx64 ")"),
debug_info_p->cu_offset,
debug_info_p->str_offsets_base, uvalue);
+ svalue = uvalue;
+ if (svalue < 0)
+ {
+ warn (_("CU @ %#" PRIx64 " has has a negative stroffsets_base "
+ "value of %#" PRIx64 " - treating as zero"),
+ debug_info_p->cu_offset, svalue);
+ uvalue = 0;
+ }
debug_info_p->str_offsets_base = uvalue;
break;
const char *name = get_DW_UT_name (compunit.cu_unit_type);
printf (_(" Unit Type: %s (%x)\n"),
- name ? name : "???",
+ null_name (name),
compunit.cu_unit_type);
}
printf (_(" Abbrev Offset: %#" PRIx64 "\n"),
typedef struct
{
- unsigned char *name;
+ char *name;
unsigned int directory_index;
unsigned int modification_date;
unsigned int length;
int i;
File_Entry *file_table = NULL;
unsigned int n_files = 0;
- unsigned char **directory_table = NULL;
- uint64_t n_directories = 0;
+ char **directory_table = NULL;
+ unsigned int n_directories = 0;
if (startswith (section->name, ".debug_line.")
/* Note: the following does not apply to .debug_line.dwo sections.
if (linfo.li_version >= 5)
{
- unsigned char *format_start, format_count, *format;
- uint64_t formati, entryi;
+ unsigned char *format_start, *format;
+ unsigned int format_count, formati, entryi;
load_debug_section_with_follow (line_str, fileptr);
if (n_directories == 0)
directory_table = NULL;
else
- directory_table = (unsigned char **)
- xmalloc (n_directories * sizeof (unsigned char *));
+ directory_table = (char **)
+ xcalloc (n_directories, sizeof (unsigned char *));
for (entryi = 0; entryi < n_directories; entryi++)
{
- unsigned char **pathp = &directory_table[entryi];
+ char **pathp = &directory_table[entryi];
format = format_start;
for (formati = 0; formati < format_count; formati++)
switch (form)
{
case DW_FORM_string:
- *pathp = data;
+ *pathp = (char *) data;
break;
case DW_FORM_line_strp:
SAFE_BYTE_GET (uvalue, data, linfo.li_offset_size,
end);
/* Remove const by the cast. */
- *pathp = (unsigned char *)
+ *pathp = (char *)
fetch_indirect_line_string (uvalue);
break;
}
if (n_files == 0)
file_table = NULL;
else
- file_table = (File_Entry *) xcalloc (1, n_files
- * sizeof (File_Entry));
+ file_table = (File_Entry *) xcalloc (n_files,
+ sizeof (File_Entry));
for (entryi = 0; entryi < n_files; entryi++)
{
switch (form)
{
case DW_FORM_string:
- file->name = data;
+ file->name = (char *) data;
break;
case DW_FORM_line_strp:
SAFE_BYTE_GET (uvalue, data, linfo.li_offset_size,
end);
/* Remove const by the cast. */
- file->name = (unsigned char *)
+ file->name = (char *)
fetch_indirect_line_string (uvalue);
break;
}
{
if (*data != 0)
{
- unsigned char *ptr_directory_table = data;
+ char *ptr_directory_table = (char *) data;
while (data < end && *data != 0)
{
}
/* Go through the directory table again to save the directories. */
- directory_table = (unsigned char **)
+ directory_table = (char **)
xmalloc (n_directories * sizeof (unsigned char *));
i = 0;
while (*ptr_directory_table != 0)
{
directory_table[i] = ptr_directory_table;
- ptr_directory_table
- += strlen ((char *) ptr_directory_table) + 1;
+ ptr_directory_table += strlen (ptr_directory_table) + 1;
i++;
}
}
i = 0;
while (*ptr_file_name_table != 0)
{
- file_table[i].name = ptr_file_name_table;
+ file_table[i].name = (char *) ptr_file_name_table;
ptr_file_name_table
+= strlen ((char *) ptr_file_name_table) + 1;
if (file_table == NULL)
printf (_("CU: No directory table\n"));
else if (directory_table == NULL)
- printf (_("CU: %s:\n"), file_table[0].name);
+ printf (_("CU: %s:\n"), null_name (file_table[0].name));
else
{
unsigned int ix = file_table[0].directory_index;
const char *directory;
- if (ix == 0)
+ if (ix == 0 && linfo.li_version < 5)
directory = ".";
/* PR 20439 */
else if (n_directories == 0)
directory = _("<unknown>");
- else if (ix > n_directories)
+ else
{
- warn (_("directory index %u > number of directories %" PRIu64 "\n"),
- ix, n_directories);
- directory = _("<corrupt>");
+ if (linfo.li_version < 5)
+ --ix;
+ if (ix >= n_directories)
+ {
+ warn (_("directory index %u "
+ ">= number of directories %u\n"),
+ ix, n_directories);
+ directory = _("<corrupt>");
+ }
+ else
+ directory = directory_table[ix];
}
- else if (linfo.li_version >= 5)
- directory = (char *) directory_table[ix];
- else
- directory = (char *) directory_table[ix - 1];
-
if (do_wide)
- printf (_("CU: %s/%s:\n"), directory, file_table[0].name);
+ printf (_("CU: %s/%s:\n"),
+ null_name (directory),
+ null_name (file_table[0].name));
else
- printf ("%s:\n", file_table[0].name);
+ printf ("%s:\n", null_name (file_table[0].name));
}
if (n_files > 0)
- printf (_("File name Line number Starting address View Stmt\n"));
+ {
+ if (do_wide)
+ printf (_("File name Line number Starting address View Stmt\n"));
+ else
+ printf (_("File name Line number Starting address View Stmt\n"));
+ }
else
printf (_("CU: Empty file name table\n"));
saved_linfo = linfo;
++state_machine_regs.last_file_entry;
/* Source file name. */
- file_table[n_files].name = op_code_data;
+ file_table[n_files].name = (char *) op_code_data;
op_code_data += strlen ((char *) op_code_data) + 1;
/* Directory index. */
READ_ULEB (file_table[n_files].directory_index,
READ_ULEB (uladv, data, end);
state_machine_regs.file = uladv;
- {
- unsigned file = state_machine_regs.file;
- unsigned dir;
-
- if (linfo.li_version < 5)
- --file;
+ unsigned file = state_machine_regs.file;
+ if (linfo.li_version < 5)
+ --file;
- if (file_table == NULL || n_files == 0)
- printf (_("\n [Use file table entry %d]\n"), file);
- /* PR 20439 */
- else if (file >= n_files)
- {
- warn (_("file index %u > number of files %u\n"), file, n_files);
- printf (_("\n <over large file table index %u>"), file);
- }
- else if ((dir = file_table[file].directory_index) == 0)
- /* If directory index is 0, that means current directory. */
- printf ("\n./%s:[++]\n", file_table[file].name);
- else if (directory_table == NULL || n_directories == 0)
- printf (_("\n [Use file %s in directory table entry %d]\n"),
- file_table[file].name, dir);
- /* PR 20439 */
- else if (dir > n_directories)
- {
- warn (_("directory index %u > number of directories %" PRIu64 "\n"),
- dir, n_directories);
- printf (_("\n <over large directory table entry %u>\n"), dir);
- }
- else if (linfo.li_version >= 5)
- printf ("\n%s/%s:\n",
- /* The directory index starts counting at 0. */
- directory_table[dir], file_table[file].name);
- else
- printf ("\n%s/%s:\n",
- /* The directory index starts counting at 1. */
- directory_table[dir - 1], file_table[file].name);
- }
+ if (file_table == NULL || n_files == 0)
+ printf (_("\n [Use file table entry %d]\n"), file);
+ /* PR 20439 */
+ else if (file >= n_files)
+ {
+ warn (_("file index %u >= number of files %u\n"),
+ file, n_files);
+ printf (_("\n <over large file table index %u>"), file);
+ }
+ else
+ {
+ unsigned dir = file_table[file].directory_index;
+ if (dir == 0 && linfo.li_version < 5)
+ /* If directory index is 0, that means compilation
+ current directory. bfd/dwarf2.c shows
+ DW_AT_comp_dir here but in keeping with the
+ readelf practice of minimal interpretation of
+ file data, we show "./". */
+ printf ("\n./%s:[++]\n",
+ null_name (file_table[file].name));
+ else if (directory_table == NULL || n_directories == 0)
+ printf (_("\n [Use file %s "
+ "in directory table entry %d]\n"),
+ null_name (file_table[file].name), dir);
+ else
+ {
+ if (linfo.li_version < 5)
+ --dir;
+ /* PR 20439 */
+ if (dir >= n_directories)
+ {
+ warn (_("directory index %u "
+ ">= number of directories %u\n"),
+ dir, n_directories);
+ printf (_("\n <over large directory table entry "
+ "%u>\n"), dir);
+ }
+ else
+ printf ("\n%s/%s:\n",
+ null_name (directory_table[dir]),
+ null_name (file_table[file].name));
+ }
+ }
break;
case DW_LNS_set_column:
|| (xop == DW_LNS_copy))
{
const unsigned int MAX_FILENAME_LENGTH = 35;
- char *fileName;
+ char *fileName = NULL;
char *newFileName = NULL;
size_t fileNameLength;
/* PR 20439 */
if (indx >= n_files)
{
- warn (_("corrupt file index %u encountered\n"), indx);
+ warn (_("file index %u >= number of files %u\n"),
+ indx, n_files);
fileName = _("<corrupt>");
}
else
fileName = (char *) file_table[indx].name;
}
- else
+ if (!fileName)
fileName = _("<unknown>");
fileNameLength = strlen (fileName);
if (linfo.li_max_ops_per_insn == 1)
{
if (xop == -DW_LNE_end_sequence)
- printf ("%-35s %11s %#18" PRIx64,
+ printf ("%-31s %11s %#18" PRIx64,
newFileName, "-",
state_machine_regs.address);
else
- printf ("%-35s %11d %#18" PRIx64,
+ printf ("%-31s %11d %#18" PRIx64,
newFileName, state_machine_regs.line,
state_machine_regs.address);
}
else
{
if (xop == -DW_LNE_end_sequence)
- printf ("%-35s %11s %#18" PRIx64 "[%d]",
+ printf ("%-31s %11s %#18" PRIx64 "[%d]",
newFileName, "-",
state_machine_regs.address,
state_machine_regs.op_index);
else
- printf ("%-35s %11d %#18" PRIx64 "[%d]",
+ printf ("%-31s %11d %#18" PRIx64 "[%d]",
newFileName, state_machine_regs.line,
state_machine_regs.address,
state_machine_regs.op_index);
const char *suffix = strrchr (section->name, '.');
bool is_dwo = false;
int is_loclists = strstr (section->name, "debug_loclists") != NULL;
- uint64_t expected_start = 0;
+ uint64_t header_size = 0;
if (suffix && strcmp (suffix, ".dwo") == 0)
is_dwo = true;
if (offset_entry_count != 0)
return display_offset_entry_loclists (section);
- expected_start = hdrptr - section_begin;
+ header_size = hdrptr - section_begin;
}
if (load_debug_info (file) == 0)
error (_("No location lists in .debug_info section!\n"));
if (debug_information [first].num_loc_offsets > 0
- && debug_information [first].loc_offsets [0] != expected_start
- && debug_information [first].loc_views [0] != expected_start)
+ && debug_information [first].loc_offsets [0] != header_size
+ && debug_information [first].loc_views [0] != header_size)
warn (_("Location lists in %s section start at %#" PRIx64
" rather than %#" PRIx64 "\n"),
section->name, debug_information [first].loc_offsets [0],
- expected_start);
+ header_size);
if (!locs_sorted)
array = (unsigned int *) xcmalloc (num_loc_list, sizeof (unsigned int));
printf (_(" Offset Begin End Expression\n"));
- seen_first_offset = 0;
for (i = first; i < num_debug_info_entries; i++)
{
- uint64_t offset, voffset;
+ uint64_t offset = 0, voffset = 0;
uint64_t base_address;
unsigned int k;
int has_frame_base;
sizeof (*array), loc_offsets_compar);
}
+ /* .debug_loclists has a per-unit header.
+ Update start if we are detecting it. */
+ if (debug_information [i].dwarf_version == 5)
+ {
+ j = locs_sorted ? 0 : array [0];
+
+ if (debug_information [i].num_loc_offsets)
+ offset = debug_information [i].loc_offsets [j];
+
+ if (debug_information [i].num_loc_views)
+ voffset = debug_information [i].loc_views [j];
+
+ /* Assume that the size of the header is constant across CUs. */
+ if (((start - section_begin) + header_size == offset)
+ || ((start -section_begin) + header_size == voffset))
+ start += header_size;
+ }
+
int adjacent_view_loclists = 1;
for (k = 0; k < debug_information [i].num_loc_offsets; k++)
{
start = vstart;
}
- if (!seen_first_offset || !adjacent_view_loclists)
- seen_first_offset = 1;
- else
+ if (start < next)
{
- if (start < next)
+ if (vnext && vnext < next)
warn (_("There is a hole [%#tx - %#" PRIx64 "]"
" in %s section.\n"),
- start - section_begin, offset, section->name);
- else if (start > next)
- warn (_("There is an overlap [%#tx - %#" PRIx64 "]"
+ start - section_begin, voffset, section->name);
+ else
+ warn (_("There is a hole [%#tx - %#" PRIx64 "]"
" in %s section.\n"),
start - section_begin, offset, section->name);
}
+ else if (start > next)
+ warn (_("There is an overlap [%#tx - %#" PRIx64 "]"
+ " in %s section.\n"),
+ start - section_begin, offset, section->name);
start = next;
vstart = vnext;
SAFE_BYTE_GET_AND_INC (length, curr_header, 4, entry);
if (length == 0xffffffff)
SAFE_BYTE_GET_AND_INC (length, curr_header, 8, entry);
+ if (length > (size_t) (section->start + section->size - curr_header)
+ || length < (size_t) (entry - curr_header))
+ {
+ warn (_("Corrupt %s section: unit_length field of %#" PRIx64
+ " is invalid\n"), section->name, length);
+ return 0;
+ }
end = curr_header + length;
-
SAFE_BYTE_GET_AND_INC (version, curr_header, 2, entry);
if (version != 5)
warn (_("Corrupt %s section: expecting version number 5 in header but found %d instead\n"),
}
else
end = section->start + debug_addr_info [i + 1]->addr_base;
+
header = end;
idx = 0;
- while (entry < end)
+
+ if (address_size < 1 || address_size > sizeof (uint64_t))
+ {
+ warn (_("Corrupt %s section: address size (%x) is wrong"),
+ section->name, address_size);
+ return 0;
+ }
+
+ while ((size_t) (end - entry) >= address_size)
{
uint64_t base = byte_get (entry, address_size);
printf (_("\t%d:\t"), idx);
}
introduce (section, false);
-
+
if (is_rnglists)
return display_debug_rnglists (section);
}
next = section_begin + offset + debug_info_p->rnglists_base;
-
+
/* If multiple DWARF entities reference the same range then we will
have multiple entries in the `range_entries' list for the same
offset. Thanks to the sort above these will all be consecutive in
unsigned int ncols;
/* DW_CFA_{undefined,same_value,offset,register,unreferenced} */
short int *col_type;
- int *col_offset;
+ int64_t *col_offset;
char *augmentation;
unsigned int code_factor;
int data_factor;
return -1;
}
- fc->col_type = (short int *) xcrealloc (fc->col_type, fc->ncols,
- sizeof (short int));
- fc->col_offset = (int *) xcrealloc (fc->col_offset, fc->ncols, sizeof (int));
+ fc->col_type = xcrealloc (fc->col_type, fc->ncols,
+ sizeof (*fc->col_type));
+ fc->col_offset = xcrealloc (fc->col_offset, fc->ncols,
+ sizeof (*fc->col_offset));
/* PR 17512: file:002-10025-0.005. */
if (fc->col_type == NULL || fc->col_offset == NULL)
{
strcpy (tmp, "s");
break;
case DW_CFA_offset:
- sprintf (tmp, "c%+d", fc->col_offset[r]);
+ sprintf (tmp, "c%+" PRId64, fc->col_offset[r]);
break;
case DW_CFA_val_offset:
- sprintf (tmp, "v%+d", fc->col_offset[r]);
+ sprintf (tmp, "v%+" PRId64, fc->col_offset[r]);
break;
case DW_CFA_register:
sprintf (tmp, "%s", regname (fc->col_offset[r], 0));
fc = (Frame_Chunk *) xmalloc (sizeof (Frame_Chunk));
memset (fc, 0, sizeof (Frame_Chunk));
- fc->col_type = (short int *) xmalloc (sizeof (short int));
- fc->col_offset = (int *) xmalloc (sizeof (int));
+ fc->col_type = xmalloc (sizeof (*fc->col_type));
+ fc->col_offset = xmalloc (sizeof (*fc->col_offset));
version = *start++;
if (!cie)
{
fc->ncols = 0;
- fc->col_type = (short int *) xmalloc (sizeof (short int));
- fc->col_offset = (int *) xmalloc (sizeof (int));
+ fc->col_type = xmalloc (sizeof (*fc->col_type));
+ fc->col_offset = xmalloc (sizeof (*fc->col_offset));
if (frame_need_space (fc, max_regs > 0 ? max_regs - 1 : 0) < 0)
{
warn (_("Invalid max register\n"));
else
{
fc->ncols = cie->ncols;
- fc->col_type = (short int *) xcmalloc (fc->ncols, sizeof (short int));
- fc->col_offset = (int *) xcmalloc (fc->ncols, sizeof (int));
- memcpy (fc->col_type, cie->col_type, fc->ncols * sizeof (short int));
- memcpy (fc->col_offset, cie->col_offset, fc->ncols * sizeof (int));
+ fc->col_type = xcmalloc (fc->ncols, sizeof (*fc->col_type));
+ fc->col_offset = xcmalloc (fc->ncols, sizeof (*fc->col_offset));
+ memcpy (fc->col_type, cie->col_type,
+ fc->ncols * sizeof (*fc->col_type));
+ memcpy (fc->col_offset, cie->col_offset,
+ fc->ncols * sizeof (*fc->col_offset));
fc->augmentation = cie->augmentation;
fc->ptr_size = cie->ptr_size;
eh_addr_size = cie->ptr_size;
while (start < block_end)
{
unsigned op, opa;
- unsigned long ul, roffs;
/* Note: It is tempting to use an unsigned long for 'reg' but there
are various functions, notably frame_space_needed() that assume that
reg is an unsigned int. */
unsigned int reg;
- int64_t l;
+ int64_t sofs;
uint64_t ofs;
- uint64_t vma;
const char *reg_prefix = "";
op = *start++;
switch (op)
{
case DW_CFA_advance_loc:
+ opa *= fc->code_factor;
if (do_debug_frames_interp)
frame_display_row (fc, &need_col_headers, &max_regs);
else
{
- printf (" DW_CFA_advance_loc: %d to ",
- opa * fc->code_factor);
- print_hex_ns (fc->pc_begin + opa * fc->code_factor,
- fc->ptr_size);
+ printf (" DW_CFA_advance_loc: %d to ", opa);
+ print_hex_ns (fc->pc_begin + opa, fc->ptr_size);
printf ("\n");
}
- fc->pc_begin += opa * fc->code_factor;
+ fc->pc_begin += opa;
break;
case DW_CFA_offset:
- READ_ULEB (roffs, start, block_end);
+ READ_ULEB (ofs, start, block_end);
+ ofs *= fc->data_factor;
if (opa >= fc->ncols)
reg_prefix = bad_reg;
if (! do_debug_frames_interp || *reg_prefix != '\0')
- printf (" DW_CFA_offset: %s%s at cfa%+ld\n",
- reg_prefix, regname (opa, 0),
- roffs * fc->data_factor);
+ printf (" DW_CFA_offset: %s%s at cfa%+" PRId64 "\n",
+ reg_prefix, regname (opa, 0), ofs);
if (*reg_prefix == '\0')
{
fc->col_type[opa] = DW_CFA_offset;
- fc->col_offset[opa] = roffs * fc->data_factor;
+ fc->col_offset[opa] = ofs;
}
break;
break;
case DW_CFA_set_loc:
- vma = get_encoded_value (&start, fc->fde_encoding, section,
+ ofs = get_encoded_value (&start, fc->fde_encoding, section,
block_end);
if (do_debug_frames_interp)
frame_display_row (fc, &need_col_headers, &max_regs);
else
{
printf (" DW_CFA_set_loc: ");
- print_hex_ns (vma, fc->ptr_size);
+ print_hex_ns (ofs, fc->ptr_size);
printf ("\n");
}
- fc->pc_begin = vma;
+ fc->pc_begin = ofs;
break;
case DW_CFA_advance_loc1:
SAFE_BYTE_GET_AND_INC (ofs, start, 1, block_end);
+ ofs *= fc->code_factor;
if (do_debug_frames_interp)
frame_display_row (fc, &need_col_headers, &max_regs);
else
{
- printf (" DW_CFA_advance_loc1: %" PRId64 " to ",
- ofs * fc->code_factor);
- print_hex_ns (fc->pc_begin + ofs * fc->code_factor,
- fc->ptr_size);
+ printf (" DW_CFA_advance_loc1: %" PRId64 " to ", ofs);
+ print_hex_ns (fc->pc_begin + ofs, fc->ptr_size);
printf ("\n");
}
- fc->pc_begin += ofs * fc->code_factor;
+ fc->pc_begin += ofs;
break;
case DW_CFA_advance_loc2:
SAFE_BYTE_GET_AND_INC (ofs, start, 2, block_end);
+ ofs *= fc->code_factor;
if (do_debug_frames_interp)
frame_display_row (fc, &need_col_headers, &max_regs);
else
{
- printf (" DW_CFA_advance_loc2: %" PRId64 " to ",
- ofs * fc->code_factor);
- print_hex_ns (fc->pc_begin + ofs * fc->code_factor,
- fc->ptr_size);
+ printf (" DW_CFA_advance_loc2: %" PRId64 " to ", ofs);
+ print_hex_ns (fc->pc_begin + ofs, fc->ptr_size);
printf ("\n");
}
- fc->pc_begin += ofs * fc->code_factor;
+ fc->pc_begin += ofs;
break;
case DW_CFA_advance_loc4:
SAFE_BYTE_GET_AND_INC (ofs, start, 4, block_end);
+ ofs *= fc->code_factor;
if (do_debug_frames_interp)
frame_display_row (fc, &need_col_headers, &max_regs);
else
{
- printf (" DW_CFA_advance_loc4: %" PRId64 " to ",
- ofs * fc->code_factor);
- print_hex_ns (fc->pc_begin + ofs * fc->code_factor,
- fc->ptr_size);
+ printf (" DW_CFA_advance_loc4: %" PRId64 " to ", ofs);
+ print_hex_ns (fc->pc_begin + ofs, fc->ptr_size);
printf ("\n");
}
- fc->pc_begin += ofs * fc->code_factor;
+ fc->pc_begin += ofs;
break;
case DW_CFA_offset_extended:
READ_ULEB (reg, start, block_end);
- READ_ULEB (roffs, start, block_end);
+ READ_ULEB (ofs, start, block_end);
+ ofs *= fc->data_factor;
if (reg >= fc->ncols)
reg_prefix = bad_reg;
if (! do_debug_frames_interp || *reg_prefix != '\0')
- printf (" DW_CFA_offset_extended: %s%s at cfa%+ld\n",
- reg_prefix, regname (reg, 0),
- roffs * fc->data_factor);
+ printf (" DW_CFA_offset_extended: %s%s at cfa%+" PRId64 "\n",
+ reg_prefix, regname (reg, 0), ofs);
if (*reg_prefix == '\0')
{
fc->col_type[reg] = DW_CFA_offset;
- fc->col_offset[reg] = roffs * fc->data_factor;
+ fc->col_offset[reg] = ofs;
}
break;
case DW_CFA_val_offset:
READ_ULEB (reg, start, block_end);
- READ_ULEB (roffs, start, block_end);
+ READ_ULEB (ofs, start, block_end);
+ ofs *= fc->data_factor;
if (reg >= fc->ncols)
reg_prefix = bad_reg;
if (! do_debug_frames_interp || *reg_prefix != '\0')
- printf (" DW_CFA_val_offset: %s%s is cfa%+ld\n",
- reg_prefix, regname (reg, 0),
- roffs * fc->data_factor);
+ printf (" DW_CFA_val_offset: %s%s is cfa%+" PRId64 "\n",
+ reg_prefix, regname (reg, 0), ofs);
if (*reg_prefix == '\0')
{
fc->col_type[reg] = DW_CFA_val_offset;
- fc->col_offset[reg] = roffs * fc->data_factor;
+ fc->col_offset[reg] = ofs;
}
break;
case DW_CFA_register:
READ_ULEB (reg, start, block_end);
- READ_ULEB (roffs, start, block_end);
+ READ_ULEB (ofs, start, block_end);
if (reg >= fc->ncols)
reg_prefix = bad_reg;
if (! do_debug_frames_interp || *reg_prefix != '\0')
{
printf (" DW_CFA_register: %s%s in ",
reg_prefix, regname (reg, 0));
- puts (regname (roffs, 0));
+ puts (regname (ofs, 0));
}
if (*reg_prefix == '\0')
{
fc->col_type[reg] = DW_CFA_register;
- fc->col_offset[reg] = roffs;
+ fc->col_offset[reg] = ofs;
}
break;
rs->ra = fc->ra;
rs->cfa_exp = fc->cfa_exp;
rs->ncols = fc->ncols;
- rs->col_type = (short int *) xcmalloc (rs->ncols,
- sizeof (* rs->col_type));
- rs->col_offset = (int *) xcmalloc (rs->ncols, sizeof (* rs->col_offset));
- memcpy (rs->col_type, fc->col_type, rs->ncols * sizeof (* fc->col_type));
- memcpy (rs->col_offset, fc->col_offset, rs->ncols * sizeof (* fc->col_offset));
+ rs->col_type = xcmalloc (rs->ncols, sizeof (*rs->col_type));
+ rs->col_offset = xcmalloc (rs->ncols, sizeof (*rs->col_offset));
+ memcpy (rs->col_type, fc->col_type,
+ rs->ncols * sizeof (*fc->col_type));
+ memcpy (rs->col_offset, fc->col_offset,
+ rs->ncols * sizeof (*fc->col_offset));
rs->next = remembered_state;
remembered_state = rs;
break;
fc->ncols = 0;
break;
}
- memcpy (fc->col_type, rs->col_type, rs->ncols * sizeof (* rs->col_type));
+ memcpy (fc->col_type, rs->col_type,
+ rs->ncols * sizeof (*rs->col_type));
memcpy (fc->col_offset, rs->col_offset,
- rs->ncols * sizeof (* rs->col_offset));
+ rs->ncols * sizeof (*rs->col_offset));
free (rs->col_type);
free (rs->col_offset);
free (rs);
break;
case DW_CFA_def_cfa_expression:
- READ_ULEB (ul, start, block_end);
- if (ul > (size_t) (block_end - start))
+ READ_ULEB (ofs, start, block_end);
+ if (ofs > (size_t) (block_end - start))
{
- printf (_(" DW_CFA_def_cfa_expression: <corrupt len %lu>\n"), ul);
+ printf (_(" %s: <corrupt len %" PRIu64 ">\n"),
+ "DW_CFA_def_cfa_expression", ofs);
break;
}
if (! do_debug_frames_interp)
{
printf (" DW_CFA_def_cfa_expression (");
decode_location_expression (start, eh_addr_size, 0, -1,
- ul, 0, section);
+ ofs, 0, section);
printf (")\n");
}
fc->cfa_exp = 1;
- start += ul;
+ start += ofs;
break;
case DW_CFA_expression:
READ_ULEB (reg, start, block_end);
- READ_ULEB (ul, start, block_end);
+ READ_ULEB (ofs, start, block_end);
if (reg >= fc->ncols)
reg_prefix = bad_reg;
/* PR 17512: file: 069-133014-0.006. */
/* PR 17512: file: 98c02eb4. */
- if (ul > (size_t) (block_end - start))
+ if (ofs > (size_t) (block_end - start))
{
- printf (_(" DW_CFA_expression: <corrupt len %lu>\n"), ul);
+ printf (_(" %s: <corrupt len %" PRIu64 ">\n"),
+ "DW_CFA_expression", ofs);
break;
}
if (! do_debug_frames_interp || *reg_prefix != '\0')
printf (" DW_CFA_expression: %s%s (",
reg_prefix, regname (reg, 0));
decode_location_expression (start, eh_addr_size, 0, -1,
- ul, 0, section);
+ ofs, 0, section);
printf (")\n");
}
if (*reg_prefix == '\0')
fc->col_type[reg] = DW_CFA_expression;
- start += ul;
+ start += ofs;
break;
case DW_CFA_val_expression:
READ_ULEB (reg, start, block_end);
- READ_ULEB (ul, start, block_end);
+ READ_ULEB (ofs, start, block_end);
if (reg >= fc->ncols)
reg_prefix = bad_reg;
- if (ul > (size_t) (block_end - start))
+ if (ofs > (size_t) (block_end - start))
{
- printf (" DW_CFA_val_expression: <corrupt len %lu>\n", ul);
+ printf (" %s: <corrupt len %" PRIu64 ">\n",
+ "DW_CFA_val_expression", ofs);
break;
}
if (! do_debug_frames_interp || *reg_prefix != '\0')
printf (" DW_CFA_val_expression: %s%s (",
reg_prefix, regname (reg, 0));
decode_location_expression (start, eh_addr_size, 0, -1,
- ul, 0, section);
+ ofs, 0, section);
printf (")\n");
}
if (*reg_prefix == '\0')
fc->col_type[reg] = DW_CFA_val_expression;
- start += ul;
+ start += ofs;
break;
case DW_CFA_offset_extended_sf:
READ_ULEB (reg, start, block_end);
- READ_SLEB (l, start, block_end);
+ READ_SLEB (sofs, start, block_end);
+ /* data_factor multiplicaton done here as unsigned to
+ avoid integer overflow warnings from asan on fuzzed
+ objects. */
+ ofs = sofs;
+ ofs *= fc->data_factor;
if (reg >= fc->ncols)
reg_prefix = bad_reg;
if (! do_debug_frames_interp || *reg_prefix != '\0')
printf (" DW_CFA_offset_extended_sf: %s%s at cfa%+" PRId64 "\n",
- reg_prefix, regname (reg, 0),
- l * fc->data_factor);
+ reg_prefix, regname (reg, 0), ofs);
if (*reg_prefix == '\0')
{
fc->col_type[reg] = DW_CFA_offset;
- fc->col_offset[reg] = l * fc->data_factor;
+ fc->col_offset[reg] = ofs;
}
break;
case DW_CFA_val_offset_sf:
READ_ULEB (reg, start, block_end);
- READ_SLEB (l, start, block_end);
+ READ_SLEB (sofs, start, block_end);
+ ofs = sofs;
+ ofs *= fc->data_factor;
if (reg >= fc->ncols)
reg_prefix = bad_reg;
if (! do_debug_frames_interp || *reg_prefix != '\0')
printf (" DW_CFA_val_offset_sf: %s%s is cfa%+" PRId64 "\n",
- reg_prefix, regname (reg, 0),
- l * fc->data_factor);
+ reg_prefix, regname (reg, 0), ofs);
if (*reg_prefix == '\0')
{
fc->col_type[reg] = DW_CFA_val_offset;
- fc->col_offset[reg] = l * fc->data_factor;
+ fc->col_offset[reg] = ofs;
}
break;
case DW_CFA_def_cfa_sf:
READ_ULEB (fc->cfa_reg, start, block_end);
- READ_SLEB (l, start, block_end);
- l *= fc->data_factor;
- fc->cfa_offset = l;
+ READ_SLEB (sofs, start, block_end);
+ ofs = sofs;
+ ofs *= fc->data_factor;
+ fc->cfa_offset = ofs;
fc->cfa_exp = 0;
if (! do_debug_frames_interp)
printf (" DW_CFA_def_cfa_sf: %s ofs %" PRId64 "\n",
- regname (fc->cfa_reg, 0), l);
+ regname (fc->cfa_reg, 0), ofs);
break;
case DW_CFA_def_cfa_offset_sf:
- READ_SLEB (l, start, block_end);
- l *= fc->data_factor;
- fc->cfa_offset = l;
+ READ_SLEB (sofs, start, block_end);
+ ofs = sofs;
+ ofs *= fc->data_factor;
+ fc->cfa_offset = ofs;
if (! do_debug_frames_interp)
- printf (" DW_CFA_def_cfa_offset_sf: %" PRId64 "\n", l);
+ printf (" DW_CFA_def_cfa_offset_sf: %" PRId64 "\n", ofs);
break;
case DW_CFA_MIPS_advance_loc8:
SAFE_BYTE_GET_AND_INC (ofs, start, 8, block_end);
+ ofs *= fc->code_factor;
if (do_debug_frames_interp)
frame_display_row (fc, &need_col_headers, &max_regs);
else
{
- printf (" DW_CFA_MIPS_advance_loc8: %" PRId64 " to ",
- ofs * fc->code_factor);
- print_hex_ns (fc->pc_begin + ofs * fc->code_factor,
- fc->ptr_size);
+ printf (" DW_CFA_MIPS_advance_loc8: %" PRId64 " to ", ofs);
+ print_hex_ns (fc->pc_begin + ofs, fc->ptr_size);
printf ("\n");
}
- fc->pc_begin += ofs * fc->code_factor;
+ fc->pc_begin += ofs;
break;
case DW_CFA_GNU_window_save:
break;
case DW_CFA_GNU_args_size:
- READ_ULEB (ul, start, block_end);
+ READ_ULEB (ofs, start, block_end);
if (! do_debug_frames_interp)
- printf (" DW_CFA_GNU_args_size: %ld\n", ul);
+ printf (" DW_CFA_GNU_args_size: %" PRIu64 "\n", ofs);
break;
case DW_CFA_GNU_negative_offset_extended:
READ_ULEB (reg, start, block_end);
- READ_SLEB (l, start, block_end);
- l = - l;
+ READ_SLEB (sofs, start, block_end);
+ ofs = sofs;
+ ofs = -ofs * fc->data_factor;
if (reg >= fc->ncols)
reg_prefix = bad_reg;
if (! do_debug_frames_interp || *reg_prefix != '\0')
printf (" DW_CFA_GNU_negative_offset_extended: %s%s "
"at cfa%+" PRId64 "\n",
- reg_prefix, regname (reg, 0),
- l * fc->data_factor);
+ reg_prefix, regname (reg, 0), ofs);
if (*reg_prefix == '\0')
{
fc->col_type[reg] = DW_CFA_offset;
- fc->col_offset[reg] = l * fc->data_factor;
+ fc->col_offset[reg] = ofs;
}
break;
{
uint64_t low = byte_get_little_endian (address_table + i * 20, 8);
uint64_t high = byte_get_little_endian (address_table + i * 20 + 8, 8);
- uint32_t cu_index = byte_get_little_endian (address_table + i + 20 + 16, 4);
+ uint32_t cu_index = byte_get_little_endian (address_table + i * 20 + 16, 4);
print_hex (low, 8);
print_hex (high, 8);
static void
add_shndx_to_cu_tu_entry (unsigned int shndx)
{
- if (shndx_pool_used >= shndx_pool_size)
- {
- error (_("Internal error: out of space in the shndx pool.\n"));
- return;
- }
shndx_pool [shndx_pool_used++] = shndx;
}
static void
end_cu_tu_entry (void)
{
- if (shndx_pool_used >= shndx_pool_size)
- {
- error (_("Internal error: out of space in the shndx pool.\n"));
- return;
- }
shndx_pool [shndx_pool_used++] = 0;
}
if (version == 1)
{
+ unsigned char *shndx_list;
+ unsigned int shndx;
+
if (!do_display)
- prealloc_cu_tu_list ((limit - ppool) / 4);
- for (i = 0; i < nslots; i++)
{
- unsigned char *shndx_list;
- unsigned int shndx;
-
- SAFE_BYTE_GET (signature, phash, 8, limit);
- if (signature != 0)
+ prealloc_cu_tu_list ((limit - ppool) / 4);
+ for (shndx_list = ppool + 4; shndx_list <= limit - 4; shndx_list += 4)
{
- SAFE_BYTE_GET (j, pindex, 4, limit);
- shndx_list = ppool + j * 4;
- /* PR 17531: file: 705e010d. */
- if (shndx_list < ppool)
- {
- warn (_("Section index pool located before start of section\n"));
- return 0;
- }
+ shndx = byte_get (shndx_list, 4);
+ add_shndx_to_cu_tu_entry (shndx);
+ }
+ end_cu_tu_entry ();
+ }
+ else
+ for (i = 0; i < nslots; i++)
+ {
+ SAFE_BYTE_GET (signature, phash, 8, limit);
+ if (signature != 0)
+ {
+ SAFE_BYTE_GET (j, pindex, 4, limit);
+ shndx_list = ppool + j * 4;
+ /* PR 17531: file: 705e010d. */
+ if (shndx_list < ppool)
+ {
+ warn (_("Section index pool located before start of section\n"));
+ return 0;
+ }
- if (do_display)
printf (_(" [%3d] Signature: %#" PRIx64 " Sections: "),
i, signature);
- for (;;)
- {
- if (shndx_list >= limit)
- {
- warn (_("Section %s too small for shndx pool\n"),
- section->name);
- return 0;
- }
- SAFE_BYTE_GET (shndx, shndx_list, 4, limit);
- if (shndx == 0)
- break;
- if (do_display)
+ for (;;)
+ {
+ if (shndx_list >= limit)
+ {
+ warn (_("Section %s too small for shndx pool\n"),
+ section->name);
+ return 0;
+ }
+ SAFE_BYTE_GET (shndx, shndx_list, 4, limit);
+ if (shndx == 0)
+ break;
printf (" %d", shndx);
- else
- add_shndx_to_cu_tu_entry (shndx);
- shndx_list += 4;
- }
- if (do_display)
+ shndx_list += 4;
+ }
printf ("\n");
- else
- end_cu_tu_entry ();
- }
- phash += 8;
- pindex += 4;
- }
+ }
+ phash += 8;
+ pindex += 4;
+ }
}
else if (version == 2)
{
if (nused == -1u
|| _mul_overflow ((size_t) ncols, 4, &temp)
|| _mul_overflow ((size_t) nused + 1, temp, &total)
+ || total > (size_t) (limit - ppool)
+ /* PR 30227: ncols could be 0. */
+ || _mul_overflow ((size_t) nused + 1, 4, &total)
|| total > (size_t) (limit - ppool))
{
warn (_("Section %s too small for offset and size tables\n"),
Note: does *not* initialise the allocated memory to zero. */
void *
-cmalloc (size_t nmemb, size_t size)
+cmalloc (uint64_t nmemb, size_t size)
{
/* Check for overflow. */
if (nmemb >= ~(size_t) 0 / size)
Note: does *not* initialise the allocated memory to zero. */
void *
-xcmalloc (size_t nmemb, size_t size)
+xcmalloc (uint64_t nmemb, size_t size)
{
/* Check for overflow. */
if (nmemb >= ~(size_t) 0 / size)
{
fprintf (stderr,
- _("Attempt to allocate an array with an excessive number of elements: %#zx\n"),
+ _("Attempt to allocate an array with an excessive number of elements: %#" PRIx64 "\n"),
nmemb);
xexit (1);
}
Note: does *not* initialise any new memory to zero. */
void *
-xcrealloc (void *ptr, size_t nmemb, size_t size)
+xcrealloc (void *ptr, uint64_t nmemb, size_t size)
{
/* Check for overflow. */
if (nmemb >= ~(size_t) 0 / size)
{
- error (_("Attempt to re-allocate an array with an excessive number of elements: %#zx\n"),
+ error (_("Attempt to re-allocate an array with an excessive number of elements: %#" PRIx64 "\n"),
nmemb);
xexit (1);
}
/* Like xcalloc, but verifies that the first parameter is not too large. */
void *
-xcalloc2 (size_t nmemb, size_t size)
+xcalloc2 (uint64_t nmemb, size_t size)
{
/* Check for overflow. */
if (nmemb >= ~(size_t) 0 / size)
{
- error (_("Attempt to allocate a zero'ed array with an excessive number of elements: %#zx\n"),
+ error (_("Attempt to allocate a zero'ed array with an excessive number of elements: %#" PRIx64 "\n"),
nmemb);
xexit (1);
}