diff options
-rw-r--r-- | bfd/version.h | 2 | ||||
-rw-r--r-- | binutils/doc/binutils.texi | 8 | ||||
-rw-r--r-- | binutils/resbin.c | 768 | ||||
-rw-r--r-- | binutils/rescoff.c | 262 | ||||
-rw-r--r-- | binutils/resrc.c | 9 | ||||
-rw-r--r-- | binutils/resres.c | 42 | ||||
-rw-r--r-- | binutils/windres.c | 30 | ||||
-rw-r--r-- | binutils/windres.h | 6 | ||||
-rw-r--r-- | gdb/ada-lang.c | 115 | ||||
-rw-r--r-- | gdb/dwarf2/read.c | 31 | ||||
-rw-r--r-- | gdb/testsuite/gdb.ada/scalar_storage.exp | 28 | ||||
-rw-r--r-- | gdb/testsuite/gdb.arch/aarch64-sve-sigunwind.c | 205 | ||||
-rw-r--r-- | gdb/testsuite/gdb.arch/aarch64-sve-sigunwind.exp | 106 | ||||
-rw-r--r-- | gdb/testsuite/gdb.base/bg-execution-repeat.c | 2 | ||||
-rw-r--r-- | ld/ldmain.c | 2 | ||||
-rw-r--r-- | ld/testsuite/ld-plugin/lto.exp | 20 | ||||
-rw-r--r-- | opcodes/riscv-dis.c | 6 |
17 files changed, 1188 insertions, 454 deletions
diff --git a/bfd/version.h b/bfd/version.h index cd21a82..92e691d 100644 --- a/bfd/version.h +++ b/bfd/version.h @@ -16,7 +16,7 @@ In releases, the date is not included in either version strings or sonames. */ -#define BFD_VERSION_DATE 20250414 +#define BFD_VERSION_DATE 20250416 #define BFD_VERSION @bfd_version@ #define BFD_VERSION_STRING @bfd_version_package@ @bfd_version_string@ #define REPORT_BUGS_TO @report_bugs_to@ diff --git a/binutils/doc/binutils.texi b/binutils/doc/binutils.texi index b291670..c74526e 100644 --- a/binutils/doc/binutils.texi +++ b/binutils/doc/binutils.texi @@ -2701,6 +2701,14 @@ but the result again may not be as you expect. For RISC-V, the following options are supported: @table @code +@item max +Disassemble without checking architecture string. This is a best effort mode, so +for overlapping ISA extensions the first match (possibly incorrect in a given +context) will be used to decode the instruction. It's useful, if the ELF file +doesn't expose ISA string, preventing automatic ISA subset deduction, and the +default fallback ISA string (@code{rv64gc}) doesn't cover all instructions in +the binary. + @item numeric Print numeric register names, rather than ABI names (e.g., print @code{x2} instead of @code{sp}). diff --git a/binutils/resbin.c b/binutils/resbin.c index 388b016..98dd68b 100644 --- a/binutils/resbin.c +++ b/binutils/resbin.c @@ -54,8 +54,8 @@ static rc_res_resource *bin_to_res_group_cursor (windres_bfd *, const bfd_byte * static rc_res_resource *bin_to_res_group_icon (windres_bfd *, const bfd_byte *, rc_uint_type); static rc_res_resource *bin_to_res_version (windres_bfd *, const bfd_byte *, rc_uint_type); static rc_res_resource *bin_to_res_userdata (windres_bfd *, const bfd_byte *, rc_uint_type); -static rc_res_resource *bin_to_res_toolbar (windres_bfd *, const bfd_byte *); -static void get_version_header (windres_bfd *, const bfd_byte *, rc_uint_type, const char *, +static rc_res_resource *bin_to_res_toolbar (windres_bfd *, const bfd_byte *, rc_uint_type); +static bool get_version_header (windres_bfd *, const bfd_byte *, rc_uint_type, const char *, unichar **, rc_uint_type *, rc_uint_type *, rc_uint_type *, rc_uint_type *); @@ -105,7 +105,7 @@ bin_to_res (windres_bfd *wrbfd, rc_res_id type, const bfd_byte *data, case RT_VERSION: return bin_to_res_version (wrbfd, data, length); case RT_TOOLBAR: - return bin_to_res_toolbar (wrbfd, data); + return bin_to_res_toolbar (wrbfd, data, length); } } @@ -116,7 +116,7 @@ bin_to_res (windres_bfd *wrbfd, rc_res_id type, const bfd_byte *data, static void toosmall (const char *msg) { - fatal (_("%s: not enough binary data"), msg); + non_fatal (_("%s: not enough binary data"), msg); } /* Swap in a NULL terminated unicode string. */ @@ -132,13 +132,16 @@ get_unicode (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type length, while (1) { if (length < c * 2 + 2) - toosmall (_("null terminated unicode string")); + { + toosmall (_("null terminated unicode string")); + return NULL; + } if (windres_get_16 (wrbfd, data + c * 2, 2) == 0) break; ++c; } - ret = (unichar *) res_alloc ((c + 1) * sizeof (unichar)); + ret = res_alloc ((c + 1) * sizeof (unichar)); for (i = 0; i < c; i++) ret[i] = windres_get_16 (wrbfd, data + i * 2, 2); @@ -159,13 +162,19 @@ get_resid (windres_bfd *wrbfd, rc_res_id *id, const bfd_byte *data, rc_uint_type first; if (length < 2) - toosmall (_("resource ID")); + { + toosmall (_("resource ID")); + return -1; + } first = windres_get_16 (wrbfd, data, 2); if (first == 0xffff) { if (length < 4) - toosmall (_("resource ID")); + { + toosmall (_("resource ID")); + return -1; + } id->named = 0; id->u.id = windres_get_16 (wrbfd, data + 2, 2); return 4; @@ -174,6 +183,8 @@ get_resid (windres_bfd *wrbfd, rc_res_id *id, const bfd_byte *data, { id->named = 1; id->u.n.name = get_unicode (wrbfd, data, length, &id->u.n.length); + if (id->u.n.name == NULL) + return -1; return id->u.n.length * 2 + 2; } } @@ -187,7 +198,7 @@ bin_to_res_generic (windres_bfd *wrbfd ATTRIBUTE_UNUSED, enum rc_res_type type, { rc_res_resource *r; - r = (rc_res_resource *) res_alloc (sizeof (rc_res_resource)); + r = res_alloc (sizeof (rc_res_resource)); r->type = type; r->u.data.data = data; r->u.data.length = length; @@ -204,15 +215,18 @@ bin_to_res_cursor (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type length rc_res_resource *r; if (length < 4) - toosmall (_("cursor")); + { + toosmall (_("cursor")); + return NULL; + } - c = (rc_cursor *) res_alloc (sizeof (rc_cursor)); + c = res_alloc (sizeof (rc_cursor)); c->xhotspot = windres_get_16 (wrbfd, data, 2); c->yhotspot = windres_get_16 (wrbfd, data + 2, 2); c->length = length - 4; c->data = data + 4; - r = (rc_res_resource *) res_alloc (sizeof *r); + r = res_alloc (sizeof *r); r->type = RES_TYPE_CURSOR; r->u.cursor = c; @@ -228,39 +242,58 @@ bin_to_res_menu (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type length) rc_menu *m; rc_uint_type version, got; - r = (rc_res_resource *) res_alloc (sizeof *r); + r = res_alloc (sizeof *r); r->type = RES_TYPE_MENU; - m = (rc_menu *) res_alloc (sizeof (rc_menu)); + m = res_alloc (sizeof (rc_menu)); r->u.menu = m; if (length < 2) - toosmall (_("menu header")); + { + toosmall (_("menu header")); + return NULL; + } version = windres_get_16 (wrbfd, data, 2); if (version == 0) { if (length < 4) - toosmall (_("menu header")); + { + toosmall (_("menu header")); + return NULL; + } m->help = 0; m->items = bin_to_res_menuitems (wrbfd, data + 4, length - 4, &got); + if (m->items == NULL) + return NULL; } else if (version == 1) { rc_uint_type offset; if (length < 8) - toosmall (_("menuex header")); + { + toosmall (_("menuex header")); + return NULL; + } m->help = windres_get_32 (wrbfd, data + 4, 4); offset = windres_get_16 (wrbfd, data + 2, 2); if (offset + 4 >= length) - toosmall (_("menuex offset")); + { + toosmall (_("menuex offset")); + return NULL; + } m->items = bin_to_res_menuexitems (wrbfd, data + 4 + offset, length - (4 + offset), &got); + if (m->items == NULL) + return NULL; } else - fatal (_("unsupported menu version %d"), (int) version); + { + non_fatal (_("unsupported menu version %d"), (int) version); + return NULL; + } return r; } @@ -268,8 +301,8 @@ bin_to_res_menu (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type length) /* Convert menu items from binary. */ static rc_menuitem * -bin_to_res_menuitems (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type length, - rc_uint_type *got) +bin_to_res_menuitems (windres_bfd *wrbfd, const bfd_byte *data, + rc_uint_type length, rc_uint_type *got) { rc_menuitem *first, **pp; @@ -285,9 +318,12 @@ bin_to_res_menuitems (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type len rc_menuitem *mi; if (length < 4) - toosmall (_("menuitem header")); + { + toosmall (_("menuitem header")); + return NULL; + } - mi = (rc_menuitem *) res_alloc (sizeof *mi); + mi = res_alloc (sizeof *mi); mi->state = 0; mi->help = 0; @@ -300,7 +336,10 @@ bin_to_res_menuitems (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type len stroff = 2; if (length < stroff + 2) - toosmall (_("menuitem header")); + { + toosmall (_("menuitem header")); + return NULL; + } if (windres_get_16 (wrbfd, data + stroff, 2) == 0) { @@ -308,7 +347,11 @@ bin_to_res_menuitems (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type len mi->text = NULL; } else - mi->text = get_unicode (wrbfd, data + stroff, length - stroff, &slen); + { + mi->text = get_unicode (wrbfd, data + stroff, length - stroff, &slen); + if (mi->text == NULL) + return NULL; + } itemlen = stroff + slen * 2 + 2; @@ -322,8 +365,10 @@ bin_to_res_menuitems (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type len rc_uint_type subread; mi->id = 0; - mi->popup = bin_to_res_menuitems (wrbfd, data + itemlen, length - itemlen, - &subread); + mi->popup = bin_to_res_menuitems (wrbfd, data + itemlen, + length - itemlen, &subread); + if (mi->popup == NULL) + return NULL; itemlen += subread; } @@ -345,8 +390,8 @@ bin_to_res_menuitems (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type len /* Convert menuex items from binary. */ static rc_menuitem * -bin_to_res_menuexitems (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type length, - rc_uint_type *got) +bin_to_res_menuexitems (windres_bfd *wrbfd, const bfd_byte *data, + rc_uint_type length, rc_uint_type *got) { rc_menuitem *first, **pp; @@ -362,9 +407,12 @@ bin_to_res_menuexitems (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type l rc_menuitem *mi; if (length < 16) - toosmall (_("menuitem header")); + { + toosmall (_("menuitem header")); + return NULL; + } - mi = (rc_menuitem *) res_alloc (sizeof (rc_menuitem)); + mi = res_alloc (sizeof (rc_menuitem)); mi->type = windres_get_32 (wrbfd, data, 4); mi->state = windres_get_32 (wrbfd, data + 4, 4); mi->id = windres_get_32 (wrbfd, data + 8, 4); @@ -377,7 +425,11 @@ bin_to_res_menuexitems (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type l mi->text = NULL; } else - mi->text = get_unicode (wrbfd, data + 14, length - 14, &slen); + { + mi->text = get_unicode (wrbfd, data + 14, length - 14, &slen); + if (mi->text == NULL) + return NULL; + } itemlen = 14 + slen * 2 + 2; itemlen = (itemlen + 3) &~ 3; @@ -392,12 +444,17 @@ bin_to_res_menuexitems (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type l rc_uint_type subread; if (length < itemlen + 4) - toosmall (_("menuitem")); + { + toosmall (_("menuitem")); + return NULL; + } mi->help = windres_get_32 (wrbfd, data + itemlen, 4); itemlen += 4; mi->popup = bin_to_res_menuexitems (wrbfd, data + itemlen, length - itemlen, &subread); + if (mi->popup == NULL) + return NULL; itemlen += subread; } @@ -424,14 +481,18 @@ bin_to_res_dialog (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type length rc_uint_type signature; rc_dialog *d; rc_uint_type c, sublen, i; + int ilen; rc_uint_type off; rc_dialog_control **pp; rc_res_resource *r; if (length < 18) - toosmall (_("dialog header")); + { + toosmall (_("dialog header")); + return NULL; + } - d = (rc_dialog *) res_alloc (sizeof (rc_dialog)); + d = res_alloc (sizeof (rc_dialog)); signature = windres_get_16 (wrbfd, data + 2, 2); if (signature != 0xffff) @@ -447,9 +508,12 @@ bin_to_res_dialog (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type length version = windres_get_16 (wrbfd, data, 2); if (version != 1) - fatal (_("unexpected DIALOGEX version %d"), version); + { + non_fatal (_("unexpected DIALOGEX version %d"), version); + return NULL; + } - d->ex = (rc_dialog_ex *) res_alloc (sizeof (rc_dialog_ex)); + d->ex = res_alloc (sizeof (rc_dialog_ex)); d->ex->help = windres_get_32 (wrbfd, data + 4, 4); d->exstyle = windres_get_32 (wrbfd, data + 8, 4); d->style = windres_get_32 (wrbfd, data + 12, 4); @@ -457,7 +521,10 @@ bin_to_res_dialog (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type length } if (length < off + 10) - toosmall (_("dialog header")); + { + toosmall (_("dialog header")); + return NULL; + } c = windres_get_16 (wrbfd, data + off, 2); d->x = windres_get_16 (wrbfd, data + off + 2, 2); @@ -467,13 +534,19 @@ bin_to_res_dialog (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type length off += 10; - sublen = get_resid (wrbfd, &d->menu, data + off, length - off); - off += sublen; + ilen = get_resid (wrbfd, &d->menu, data + off, length - off); + if (ilen == -1) + return NULL; + off += ilen; - sublen = get_resid (wrbfd, &d->class, data + off, length - off); - off += sublen; + ilen = get_resid (wrbfd, &d->class, data + off, length - off); + if (ilen == -1) + return NULL; + off += ilen; d->caption = get_unicode (wrbfd, data + off, length - off, &sublen); + if (d->caption == NULL) + return NULL; off += sublen * 2 + 2; if (sublen == 0) d->caption = NULL; @@ -492,7 +565,10 @@ bin_to_res_dialog (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type length else { if (length < off + 2) - toosmall (_("dialog font point size")); + { + toosmall (_("dialog font point size")); + return NULL; + } d->pointsize = windres_get_16 (wrbfd, data + off, 2); off += 2; @@ -500,7 +576,10 @@ bin_to_res_dialog (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type length if (d->ex != NULL) { if (length < off + 4) - toosmall (_("dialogex font information")); + { + toosmall (_("dialogex font information")); + return NULL; + } d->ex->weight = windres_get_16 (wrbfd, data + off, 2); d->ex->italic = windres_get_8 (wrbfd, data + off + 2, 1); d->ex->charset = windres_get_8 (wrbfd, data + off + 3, 1); @@ -508,6 +587,8 @@ bin_to_res_dialog (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type length } d->font = get_unicode (wrbfd, data + off, length - off, &sublen); + if (d->font == NULL) + return NULL; off += sublen * 2 + 2; } @@ -521,12 +602,15 @@ bin_to_res_dialog (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type length off = (off + 3) &~ 3; - dc = (rc_dialog_control *) res_alloc (sizeof (rc_dialog_control)); + dc = res_alloc (sizeof (rc_dialog_control)); if (d->ex == NULL) { if (length < off + 8) - toosmall (_("dialog control")); + { + toosmall (_("dialog control")); + return NULL; + } dc->style = windres_get_32 (wrbfd, data + off, 4); dc->exstyle = windres_get_32 (wrbfd, data + off + 4, 4); @@ -536,7 +620,10 @@ bin_to_res_dialog (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type length else { if (length < off + 12) - toosmall (_("dialogex control")); + { + toosmall (_("dialogex control")); + return NULL; + } dc->help = windres_get_32 (wrbfd, data + off, 4); dc->exstyle = windres_get_32 (wrbfd, data + off + 4, 4); dc->style = windres_get_32 (wrbfd, data + off + 8, 4); @@ -544,7 +631,10 @@ bin_to_res_dialog (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type length } if (length < off + (d->ex != NULL ? 2 : 0) + 10) - toosmall (_("dialog control")); + { + toosmall (_("dialog control")); + return NULL; + } dc->x = windres_get_16 (wrbfd, data + off, 2); dc->y = windres_get_16 (wrbfd, data + off + 2, 2); @@ -558,14 +648,21 @@ bin_to_res_dialog (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type length off += 10 + (d->ex != NULL ? 2 : 0); - sublen = get_resid (wrbfd, &dc->class, data + off, length - off); - off += sublen; + ilen = get_resid (wrbfd, &dc->class, data + off, length - off); + if (ilen == -1) + return NULL; + off += ilen; - sublen = get_resid (wrbfd, &dc->text, data + off, length - off); - off += sublen; + ilen = get_resid (wrbfd, &dc->text, data + off, length - off); + if (ilen == -1) + return NULL; + off += ilen; if (length < off + 2) - toosmall (_("dialog control end")); + { + toosmall (_("dialog control end")); + return NULL; + } datalen = windres_get_16 (wrbfd, data + off, 2); off += 2; @@ -575,10 +672,12 @@ bin_to_res_dialog (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type length else { if (length < off + datalen) - toosmall (_("dialog control data")); + { + toosmall (_("dialog control data")); + return NULL; + } - dc->data = ((rc_rcdata_item *) - res_alloc (sizeof (rc_rcdata_item))); + dc->data = res_alloc (sizeof (rc_rcdata_item)); dc->data->next = NULL; dc->data->type = RCDATA_BUFFER; dc->data->u.buffer.length = datalen; @@ -592,7 +691,7 @@ bin_to_res_dialog (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type length pp = &dc->next; } - r = (rc_res_resource *) res_alloc (sizeof *r); + r = res_alloc (sizeof *r); r->type = RES_TYPE_DIALOG; r->u.dialog = d; @@ -608,14 +707,17 @@ bin_to_res_string (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type length int i; rc_res_resource *r; - st = (rc_stringtable *) res_alloc (sizeof (rc_stringtable)); + st = res_alloc (sizeof (rc_stringtable)); for (i = 0; i < 16; i++) { unsigned int slen; if (length < 2) - toosmall (_("stringtable string length")); + { + toosmall (_("stringtable string length")); + return NULL; + } slen = windres_get_16 (wrbfd, data, 2); st->strings[i].length = slen; @@ -625,9 +727,12 @@ bin_to_res_string (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type length unsigned int j; if (length < 2 + 2 * slen) - toosmall (_("stringtable string")); + { + toosmall (_("stringtable string")); + return NULL; + } - s = (unichar *) res_alloc (slen * sizeof (unichar)); + s = res_alloc (slen * sizeof (unichar)); st->strings[i].string = s; for (j = 0; j < slen; j++) @@ -638,7 +743,7 @@ bin_to_res_string (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type length length -= 2 + 2 * slen; } - r = (rc_res_resource *) res_alloc (sizeof *r); + r = res_alloc (sizeof *r); r->type = RES_TYPE_STRINGTABLE; r->u.stringtable = st; @@ -648,14 +753,18 @@ bin_to_res_string (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type length /* Convert a fontdir resource from binary. */ static rc_res_resource * -bin_to_res_fontdir (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type length) +bin_to_res_fontdir (windres_bfd *wrbfd, const bfd_byte *data, + rc_uint_type length) { rc_uint_type c, i; rc_fontdir *first, **pp; rc_res_resource *r; if (length < 2) - toosmall (_("fontdir header")); + { + toosmall (_("fontdir header")); + return NULL; + } c = windres_get_16 (wrbfd, data, 2); @@ -669,10 +778,13 @@ bin_to_res_fontdir (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type lengt unsigned int off; if (length < 56) - toosmall (_("fontdir")); + { + toosmall (_("fontdir")); + return NULL; + } bfi = (const struct bin_fontdir_item *) data; - fd = (rc_fontdir *) res_alloc (sizeof *fd); + fd = res_alloc (sizeof *fd); fd->index = windres_get_16 (wrbfd, bfi->index, 2); /* To work out the length of the fontdir data, we must get the @@ -686,13 +798,19 @@ bin_to_res_fontdir (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type lengt while (off < length && data[off] != '\0') ++off; if (off >= length) - toosmall (_("fontdir device name")); + { + toosmall (_("fontdir device name")); + return NULL; + } ++off; while (off < length && data[off] != '\0') ++off; if (off >= length) - toosmall (_("fontdir face name")); + { + toosmall (_("fontdir face name")); + return NULL; + } ++off; fd->length = off; @@ -709,7 +827,7 @@ bin_to_res_fontdir (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type lengt length -= off; } - r = (rc_res_resource *) res_alloc (sizeof *r); + r = res_alloc (sizeof *r); r->type = RES_TYPE_FONTDIR; r->u.fontdir = first; @@ -719,7 +837,8 @@ bin_to_res_fontdir (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type lengt /* Convert an accelerators resource from binary. */ static rc_res_resource * -bin_to_res_accelerators (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type length) +bin_to_res_accelerators (windres_bfd *wrbfd, const bfd_byte *data, + rc_uint_type length) { rc_accelerator *first, **pp; rc_res_resource *r; @@ -732,9 +851,12 @@ bin_to_res_accelerators (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type rc_accelerator *a; if (length < 8) - toosmall (_("accelerator")); + { + toosmall (_("accelerator")); + return NULL; + } - a = (rc_accelerator *) res_alloc (sizeof (rc_accelerator)); + a = res_alloc (sizeof (rc_accelerator)); a->flags = windres_get_16 (wrbfd, data, 2); a->key = windres_get_16 (wrbfd, data + 2, 2); @@ -751,7 +873,7 @@ bin_to_res_accelerators (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type length -= 8; } - r = (rc_res_resource *) res_alloc (sizeof (rc_res_resource)); + r = res_alloc (sizeof (rc_res_resource)); r->type = RES_TYPE_ACCELERATOR; r->u.acc = first; @@ -767,14 +889,14 @@ bin_to_res_rcdata (windres_bfd *wrbfd ATTRIBUTE_UNUSED, const bfd_byte *data, rc_rcdata_item *ri; rc_res_resource *r; - ri = (rc_rcdata_item *) res_alloc (sizeof (rc_rcdata_item)); + ri = res_alloc (sizeof (rc_rcdata_item)); ri->next = NULL; ri->type = RCDATA_BUFFER; ri->u.buffer.length = length; ri->u.buffer.data = data; - r = (rc_res_resource *) res_alloc (sizeof *r); + r = res_alloc (sizeof *r); r->type = rctyp; r->u.rcdata = ri; @@ -784,18 +906,25 @@ bin_to_res_rcdata (windres_bfd *wrbfd ATTRIBUTE_UNUSED, const bfd_byte *data, /* Convert a group cursor resource from binary. */ static rc_res_resource * -bin_to_res_group_cursor (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type length) +bin_to_res_group_cursor (windres_bfd *wrbfd, const bfd_byte *data, + rc_uint_type length) { int type, c, i; rc_group_cursor *first, **pp; rc_res_resource *r; if (length < 6) - toosmall (_("group cursor header")); + { + toosmall (_("group cursor header")); + return NULL; + } type = windres_get_16 (wrbfd, data + 2, 2); if (type != 2) - fatal (_("unexpected group cursor type %d"), type); + { + non_fatal (_("unexpected group cursor type %d"), type); + return NULL; + } c = windres_get_16 (wrbfd, data + 4, 2); @@ -810,9 +939,12 @@ bin_to_res_group_cursor (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type rc_group_cursor *gc; if (length < 14) - toosmall (_("group cursor")); + { + toosmall (_("group cursor")); + return NULL; + } - gc = (rc_group_cursor *) res_alloc (sizeof *gc); + gc = res_alloc (sizeof *gc); gc->width = windres_get_16 (wrbfd, data, 2); gc->height = windres_get_16 (wrbfd, data + 2, 2); @@ -829,7 +961,7 @@ bin_to_res_group_cursor (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type length -= 14; } - r = (rc_res_resource *) res_alloc (sizeof (rc_res_resource)); + r = res_alloc (sizeof (rc_res_resource)); r->type = RES_TYPE_GROUP_CURSOR; r->u.group_cursor = first; @@ -839,18 +971,25 @@ bin_to_res_group_cursor (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type /* Convert a group icon resource from binary. */ static rc_res_resource * -bin_to_res_group_icon (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type length) +bin_to_res_group_icon (windres_bfd *wrbfd, const bfd_byte *data, + rc_uint_type length) { int type, c, i; rc_group_icon *first, **pp; rc_res_resource *r; if (length < 6) - toosmall (_("group icon header")); + { + toosmall (_("group icon header")); + return NULL; + } type = windres_get_16 (wrbfd, data + 2, 2); if (type != 1) - fatal (_("unexpected group icon type %d"), type); + { + non_fatal (_("unexpected group icon type %d"), type); + return NULL; + } c = windres_get_16 (wrbfd, data + 4, 2); @@ -865,9 +1004,12 @@ bin_to_res_group_icon (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type le rc_group_icon *gi; if (length < 14) - toosmall (_("group icon")); + { + toosmall (_("group icon")); + return NULL; + } - gi = (rc_group_icon *) res_alloc (sizeof (rc_group_icon)); + gi = res_alloc (sizeof (rc_group_icon)); gi->width = windres_get_8 (wrbfd, data, 1); gi->height = windres_get_8 (wrbfd, data + 1, 1); @@ -885,7 +1027,7 @@ bin_to_res_group_icon (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type le length -= 14; } - r = (rc_res_resource *) res_alloc (sizeof *r); + r = res_alloc (sizeof *r); r->type = RES_TYPE_GROUP_ICON; r->u.group_icon = first; @@ -897,14 +1039,17 @@ bin_to_res_group_icon (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type le sets *LEN to the total length, *VALLEN to the value length, *TYPE to the type, and *OFF to the offset to the children. */ -static void -get_version_header (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type length, - const char *key, unichar **pkey, +static bool +get_version_header (windres_bfd *wrbfd, const bfd_byte *data, + rc_uint_type length, const char *key, unichar **pkey, rc_uint_type *len, rc_uint_type *vallen, rc_uint_type *type, rc_uint_type *off) { if (length < 8) - toosmall (key); + { + toosmall (key); + return false; + } *len = (windres_get_16 (wrbfd, data, 2) + 3) & ~3; *vallen = windres_get_16 (wrbfd, data + 2, 2); @@ -920,6 +1065,8 @@ get_version_header (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type lengt rc_uint_type sublen; *pkey = get_unicode (wrbfd, data, length, &sublen); + if (*pkey == NULL) + return false; *off += (sublen + 1) * sizeof (unichar); } else @@ -927,9 +1074,15 @@ get_version_header (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type lengt while (1) { if (length < 2) - toosmall (key); + { + toosmall (key); + return false; + } if (windres_get_16 (wrbfd, data, 2) != (bfd_byte) *key) - fatal (_("unexpected version string")); + { + non_fatal (_("unexpected version string")); + return false; + } *off += 2; length -= 2; @@ -943,12 +1096,14 @@ get_version_header (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type lengt } *off = (*off + 3) &~ 3; + return true; } /* Convert a version resource from binary. */ static rc_res_resource * -bin_to_res_version (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type length) +bin_to_res_version (windres_bfd *wrbfd, const bfd_byte *data, + rc_uint_type length) { rc_uint_type verlen, vallen, type, off; rc_fixed_versioninfo *fi; @@ -956,18 +1111,26 @@ bin_to_res_version (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type lengt rc_versioninfo *v; rc_res_resource *r; - get_version_header (wrbfd, data, length, "VS_VERSION_INFO", - (unichar **) NULL, &verlen, &vallen, &type, &off); + if (!get_version_header (wrbfd, data, length, "VS_VERSION_INFO", + (unichar **) NULL, &verlen, &vallen, &type, &off)) + return NULL; /* PR 17512: The verlen field does not include padding length. */ if (verlen > length) - fatal (_("version length %lu greater than resource length %lu"), - (unsigned long) verlen, (unsigned long) length); + { + non_fatal (_("version length %lu greater than resource length %lu"), + (unsigned long) verlen, (unsigned long) length); + return NULL; + } if (type != 0) - fatal (_("unexpected version type %d"), (int) type); + { + non_fatal (_("unexpected version type %d"), (int) type); + return NULL; + } - /* PR 27686: Ignore any padding bytes after the end of the version structure. */ + /* PR 27686: Ignore any padding bytes after the end of the version + structure. */ length = verlen; data += off; @@ -980,20 +1143,33 @@ bin_to_res_version (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type lengt unsigned long signature, fiv; if (vallen != 52) - fatal (_("unexpected fixed version information length %ld"), (long) vallen); + { + non_fatal (_("unexpected fixed version information length %ld"), + (long) vallen); + return NULL; + } if (length < 52) - toosmall (_("fixed version info")); + { + toosmall (_("fixed version info")); + return NULL; + } signature = windres_get_32 (wrbfd, data, 4); if (signature != 0xfeef04bd) - fatal (_("unexpected fixed version signature %lu"), signature); + { + non_fatal (_("unexpected fixed version signature %lu"), signature); + return NULL; + } fiv = windres_get_32 (wrbfd, data + 4, 4); if (fiv != 0 && fiv != 0x10000) - fatal (_("unexpected fixed version info version %lu"), fiv); + { + non_fatal (_("unexpected fixed version info version %lu"), fiv); + return NULL; + } - fi = (rc_fixed_versioninfo *) res_alloc (sizeof (rc_fixed_versioninfo)); + fi = res_alloc (sizeof (rc_fixed_versioninfo)); fi->file_version_ms = windres_get_32 (wrbfd, data + 8, 4); fi->file_version_ls = windres_get_32 (wrbfd, data + 12, 4); @@ -1020,9 +1196,12 @@ bin_to_res_version (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type lengt int ch; if (length < 8) - toosmall (_("version var info")); + { + toosmall (_("version var info")); + return NULL; + } - vi = (rc_ver_info *) res_alloc (sizeof (rc_ver_info)); + vi = res_alloc (sizeof (rc_ver_info)); ch = windres_get_16 (wrbfd, data + 6, 2); @@ -1032,12 +1211,17 @@ bin_to_res_version (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type lengt vi->type = VERINFO_STRING; - get_version_header (wrbfd, data, length, "StringFileInfo", - (unichar **) NULL, &verlen, &vallen, &type, - &off); + if (!get_version_header (wrbfd, data, length, "StringFileInfo", + (unichar **) NULL, &verlen, &vallen, &type, + &off)) + return NULL; if (vallen != 0) - fatal (_("unexpected stringfileinfo value length %ld"), (long) vallen); + { + non_fatal (_("unexpected stringfileinfo value length %ld"), + (long) vallen); + return NULL; + } data += off; length -= off; @@ -1054,66 +1238,88 @@ bin_to_res_version (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type lengt rc_ver_stringinfo **ppvs; if (length < 8) - toosmall (_("version stringtable")); + { + toosmall (_("version stringtable")); + return NULL; + } - vst = (rc_ver_stringtable *) res_alloc (sizeof (rc_ver_stringtable)); + vst = res_alloc (sizeof (rc_ver_stringtable)); - get_version_header (wrbfd, data, length, (const char *) NULL, - &vst->language, &stverlen, &vallen, &type, &off); + if (!get_version_header (wrbfd, data, length, (const char *) NULL, + &vst->language, &stverlen, &vallen, + &type, &off)) + return NULL; if (vallen != 0) - fatal (_("unexpected version stringtable value length %ld"), (long) vallen); + { + non_fatal (_("unexpected version stringtable value length %ld"), + (long) vallen); + return NULL; + } data += off; length -= off; verlen -= off; - stverlen -= off; - - vst->strings = NULL; - ppvs = &vst->strings; - - while (stverlen > 0) - { - rc_ver_stringinfo *vs; - rc_uint_type sverlen, vslen, valoff; - - if (length < 8) - toosmall (_("version string")); - - vs = (rc_ver_stringinfo *) res_alloc (sizeof (rc_ver_stringinfo)); - - get_version_header (wrbfd, data, length, (const char *) NULL, - &vs->key, &sverlen, &vallen, &type, &off); - - data += off; - length -= off; - - vs->value = get_unicode (wrbfd, data, length, &vslen); - valoff = vslen * 2 + 2; - valoff = (valoff + 3) & ~3; - - if (off + valoff != sverlen) - fatal (_("unexpected version string length %ld != %ld + %ld"), - (long) sverlen, (long) off, (long) valoff); - - data += valoff; - length -= valoff; - - if (stverlen < sverlen) - fatal (_("unexpected version string length %ld < %ld"), - (long) verlen, (long) sverlen); - stverlen -= sverlen; - verlen -= sverlen; - - vs->next = NULL; - *ppvs = vs; - ppvs = &vs->next; - } - - vst->next = NULL; - *ppvst = vst; - ppvst = &vst->next; + stverlen -= off; + + vst->strings = NULL; + ppvs = &vst->strings; + + while (stverlen > 0) + { + rc_ver_stringinfo *vs; + rc_uint_type sverlen, vslen, valoff; + + if (length < 8) + { + toosmall (_("version string")); + return NULL; + } + + vs = res_alloc (sizeof (rc_ver_stringinfo)); + + if (!get_version_header (wrbfd, data, length, + (const char *) NULL, &vs->key, + &sverlen, &vallen, &type, &off)) + return NULL; + + data += off; + length -= off; + + vs->value = get_unicode (wrbfd, data, length, &vslen); + if (vs->value == NULL) + return NULL; + valoff = vslen * 2 + 2; + valoff = (valoff + 3) & ~3; + + if (off + valoff != sverlen) + { + non_fatal (_("unexpected version string length %ld != %ld + %ld"), + (long) sverlen, (long) off, (long) valoff); + return NULL; + } + + data += valoff; + length -= valoff; + + if (stverlen < sverlen) + { + non_fatal (_("unexpected version string length %ld < %ld"), + (long) verlen, (long) sverlen); + return NULL; + } + stverlen -= sverlen; + verlen -= sverlen; + + vs->next = NULL; + *ppvs = vs; + ppvs = &vs->next; + } + + vst->next = NULL; + *ppvst = vst; + ppvst = &vst->next; } } else if (ch == 'V') @@ -1122,18 +1328,25 @@ bin_to_res_version (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type lengt vi->type = VERINFO_VAR; - get_version_header (wrbfd, data, length, "VarFileInfo", - (unichar **) NULL, &verlen, &vallen, &type, - &off); + if (!get_version_header (wrbfd, data, length, "VarFileInfo", + (unichar **) NULL, &verlen, &vallen, + &type, &off)) + return NULL; if (vallen != 0) - fatal (_("unexpected varfileinfo value length %ld"), (long) vallen); + { + non_fatal (_("unexpected varfileinfo value length %ld"), + (long) vallen); + return NULL; + } data += off; length -= off; - get_version_header (wrbfd, data, length, (const char *) NULL, - &vi->u.var.key, &verlen, &vallen, &type, &off); + if (!get_version_header (wrbfd, data, length, (const char *) NULL, + &vi->u.var.key, &verlen, &vallen, + &type, &off)) + return NULL; data += off; length -= off; @@ -1146,9 +1359,12 @@ bin_to_res_version (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type lengt rc_ver_varinfo *vv; if (length < 4) - toosmall (_("version varfileinfo")); + { + toosmall (_("version varfileinfo")); + return NULL; + } - vv = (rc_ver_varinfo *) res_alloc (sizeof (rc_ver_varinfo)); + vv = res_alloc (sizeof (rc_ver_varinfo)); vv->language = windres_get_16 (wrbfd, data, 2); vv->charset = windres_get_16 (wrbfd, data + 2, 2); @@ -1161,7 +1377,11 @@ bin_to_res_version (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type lengt length -= 4; if (vallen < 4) - fatal (_("unexpected version value length %ld"), (long) vallen); + { + non_fatal (_("unexpected version value length %ld"), + (long) vallen); + return NULL; + } vallen -= 4; } @@ -1171,21 +1391,25 @@ bin_to_res_version (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type lengt if (length == 8) /* Padding - skip. */ break; - fatal (_("nul bytes found in version string")); + non_fatal (_("nul bytes found in version string")); + return NULL; } else - fatal (_("unexpected version string character: %x"), ch); + { + non_fatal (_("unexpected version string character: %x"), ch); + return NULL; + } vi->next = NULL; *pp = vi; pp = &vi->next; } - v = (rc_versioninfo *) res_alloc (sizeof (rc_versioninfo)); + v = res_alloc (sizeof (rc_versioninfo)); v->fixed = fi; v->var = first; - r = (rc_res_resource *) res_alloc (sizeof *r); + r = res_alloc (sizeof *r); r->type = RES_TYPE_VERSIONINFO; r->u.versioninfo = v; @@ -1201,14 +1425,14 @@ bin_to_res_userdata (windres_bfd *wrbfd ATTRIBUTE_UNUSED, const bfd_byte *data, rc_rcdata_item *ri; rc_res_resource *r; - ri = (rc_rcdata_item *) res_alloc (sizeof (rc_rcdata_item)); + ri = res_alloc (sizeof (rc_rcdata_item)); ri->next = NULL; ri->type = RCDATA_BUFFER; ri->u.buffer.length = length; ri->u.buffer.data = data; - r = (rc_res_resource *) res_alloc (sizeof *r); + r = res_alloc (sizeof *r); r->type = RES_TYPE_USERDATA; r->u.rcdata = ri; @@ -1216,38 +1440,51 @@ bin_to_res_userdata (windres_bfd *wrbfd ATTRIBUTE_UNUSED, const bfd_byte *data, } static rc_res_resource * -bin_to_res_toolbar (windres_bfd *wrbfd, const bfd_byte *data) +bin_to_res_toolbar (windres_bfd *wrbfd, const bfd_byte *data, + rc_uint_type length) { rc_toolbar *ri; rc_res_resource *r; rc_uint_type i; - ri = (rc_toolbar *) res_alloc (sizeof (rc_toolbar)); + if (length < 12) + { + toosmall (_("toolbar")); + return NULL; + } + ri = res_alloc (sizeof (rc_toolbar)); ri->button_width = windres_get_32 (wrbfd, data, 4); ri->button_height = windres_get_32 (wrbfd, data + 4, 4); ri->nitems = windres_get_32 (wrbfd, data + 8, 4); ri->items = NULL; data += 12; - for (i=0 ; i < ri->nitems; i++) - { - rc_toolbar_item *it; - it = (rc_toolbar_item *) res_alloc (sizeof (rc_toolbar_item)); - it->id.named = 0; - it->id.u.id = (int) windres_get_32 (wrbfd, data, 4); - it->prev = it->next = NULL; - data += 4; - if(ri->items) { - rc_toolbar_item *ii = ri->items; - while (ii->next != NULL) - ii = ii->next; - it->prev = ii; - ii->next = it; - } - else - ri->items = it; - } - r = (rc_res_resource *) res_alloc (sizeof *r); + length -= 12; + for (i = 0; i < ri->nitems; i++) + { + rc_toolbar_item *it; + it = res_alloc (sizeof (rc_toolbar_item)); + it->id.named = 0; + if (length < 4) + { + toosmall (_("toolbar item")); + return NULL; + } + it->id.u.id = (int) windres_get_32 (wrbfd, data, 4); + it->prev = it->next = NULL; + data += 4; + length -= 4; + if(ri->items) { + rc_toolbar_item *ii = ri->items; + while (ii->next != NULL) + ii = ii->next; + it->prev = ii; + ii->next = it; + } + else + ri->items = it; + } + r = res_alloc (sizeof *r); r->type = RES_TYPE_TOOLBAR; r->u.toolbar = ri; return r; @@ -1286,7 +1523,8 @@ res_to_bin (windres_bfd *wrbfd, rc_uint_type off, const rc_res_resource *res) case RES_TYPE_FONT: case RES_TYPE_ICON: case RES_TYPE_MESSAGETABLE: - return res_to_bin_generic (wrbfd, off, res->u.data.length, res->u.data.data); + return res_to_bin_generic (wrbfd, off, res->u.data.length, + res->u.data.data); case RES_TYPE_ACCELERATOR: return res_to_bin_accelerator (wrbfd, off, res->u.acc); case RES_TYPE_CURSOR: @@ -1337,13 +1575,13 @@ resid_to_bin (windres_bfd *wrbfd, rc_uint_type off, rc_res_id id) rc_uint_type len = (id.u.n.name ? unichar_len (id.u.n.name) : 0); if (wrbfd) { - bfd_byte *d = (bfd_byte *) reswr_alloc ((len + 1) * sizeof (unichar)); + bfd_byte *d = reswr_alloc ((len + 1) * sizeof (unichar)); rc_uint_type i; for (i = 0; i < len; i++) windres_put_16 (wrbfd, d + (i * sizeof (unichar)), id.u.n.name[i]); windres_put_16 (wrbfd, d + (len * sizeof (unichar)), 0); set_windres_bfd_content (wrbfd, d, off, (len + 1) * sizeof (unichar)); - } + } off += (rc_uint_type) ((len + 1) * sizeof (unichar)); } return off; @@ -1364,7 +1602,7 @@ unicode_to_bin (windres_bfd *wrbfd, rc_uint_type off, const unichar *str) { bfd_byte *d; rc_uint_type i; - d = (bfd_byte *) reswr_alloc ( (len + 1) * sizeof (unichar)); + d = reswr_alloc ((len + 1) * sizeof (unichar)); for (i = 0; i < len; i++) windres_put_16 (wrbfd, d + (i * sizeof (unichar)), str[i]); windres_put_16 (wrbfd, d + (len * sizeof (unichar)), 0); @@ -1389,12 +1627,13 @@ res_to_bin_accelerator (windres_bfd *wrbfd, rc_uint_type off, { struct bin_accelerator ba; - windres_put_16 (wrbfd, ba.flags, a->flags | (a->next != NULL ? 0 : ACC_LAST)); + windres_put_16 (wrbfd, ba.flags, + a->flags | (a->next != NULL ? 0 : ACC_LAST)); windres_put_16 (wrbfd, ba.key, a->key); windres_put_16 (wrbfd, ba.id, a->id); windres_put_16 (wrbfd, ba.pad, 0); set_windres_bfd_content (wrbfd, &ba, off, BIN_ACCELERATOR_SIZE); - } + } off += BIN_ACCELERATOR_SIZE; } return off; @@ -1413,7 +1652,8 @@ res_to_bin_cursor (windres_bfd *wrbfd, rc_uint_type off, const rc_cursor *c) windres_put_16 (wrbfd, bc.yhotspot, c->yhotspot); set_windres_bfd_content (wrbfd, &bc, off, BIN_CURSOR_SIZE); if (c->length) - set_windres_bfd_content (wrbfd, c->data, off + BIN_CURSOR_SIZE, c->length); + set_windres_bfd_content (wrbfd, c->data, off + BIN_CURSOR_SIZE, + c->length); } off = (off + BIN_CURSOR_SIZE + (rc_uint_type) c->length); return off; @@ -1443,8 +1683,9 @@ res_to_bin_group_cursor (windres_bfd *wrbfd, rc_uint_type off, windres_put_16 (wrbfd, bgci.bits, gc->bits); windres_put_32 (wrbfd, bgci.bytes, gc->bytes); windres_put_16 (wrbfd, bgci.index, gc->index); - set_windres_bfd_content (wrbfd, &bgci, off, BIN_GROUP_CURSOR_ITEM_SIZE); - } + set_windres_bfd_content (wrbfd, &bgci, off, + BIN_GROUP_CURSOR_ITEM_SIZE); + } off += BIN_GROUP_CURSOR_ITEM_SIZE; } @@ -1477,17 +1718,17 @@ res_to_bin_dialog (windres_bfd *wrbfd, rc_uint_type off, const rc_dialog *dialog if (wrbfd) { - if (! dialogex) - { + if (! dialogex) + { windres_put_32 (wrbfd, bd.style, dialog->style); windres_put_32 (wrbfd, bd.exstyle, dialog->exstyle); windres_put_16 (wrbfd, bd.x, dialog->x); windres_put_16 (wrbfd, bd.y, dialog->y); windres_put_16 (wrbfd, bd.width, dialog->width); windres_put_16 (wrbfd, bd.height, dialog->height); - } - else - { + } + else + { windres_put_16 (wrbfd, bdx.sig1, 1); windres_put_16 (wrbfd, bdx.sig2, 0xffff); windres_put_32 (wrbfd, bdx.help, (dialog->ex ? dialog->ex->help : 0)); @@ -1520,9 +1761,12 @@ res_to_bin_dialog (windres_bfd *wrbfd, rc_uint_type off, const rc_dialog *dialog { struct bin_dialogexfont bdxf; windres_put_16 (wrbfd, bdxf.pointsize, dialog->pointsize); - windres_put_16 (wrbfd, bdxf.weight, (dialog->ex == NULL ? 0 : dialog->ex->weight)); - windres_put_8 (wrbfd, bdxf.italic, (dialog->ex == NULL ? 0 : dialog->ex->italic)); - windres_put_8 (wrbfd, bdxf.charset, (dialog->ex == NULL ? 1 : dialog->ex->charset)); + windres_put_16 (wrbfd, bdxf.weight, + dialog->ex == NULL ? 0 : dialog->ex->weight); + windres_put_8 (wrbfd, bdxf.italic, + dialog->ex == NULL ? 0 : dialog->ex->italic); + windres_put_8 (wrbfd, bdxf.charset, + dialog->ex == NULL ? 1 : dialog->ex->charset); set_windres_bfd_content (wrbfd, &bdxf, off, BIN_DIALOGEXFONT_SIZE); } } @@ -1536,8 +1780,8 @@ res_to_bin_dialog (windres_bfd *wrbfd, rc_uint_type off, const rc_dialog *dialog off += (4 - ((off - off_delta) & 3)) & 3; if (wrbfd) { - if (! dialogex) - { + if (! dialogex) + { struct bin_dialog_control bdc; windres_put_32 (wrbfd, bdc.style, dc->style); @@ -1547,10 +1791,11 @@ res_to_bin_dialog (windres_bfd *wrbfd, rc_uint_type off, const rc_dialog *dialog windres_put_16 (wrbfd, bdc.width, dc->width); windres_put_16 (wrbfd, bdc.height, dc->height); windres_put_16 (wrbfd, bdc.id, dc->id); - set_windres_bfd_content (wrbfd, &bdc, off, BIN_DIALOG_CONTROL_SIZE); - } - else - { + set_windres_bfd_content (wrbfd, &bdc, off, + BIN_DIALOG_CONTROL_SIZE); + } + else + { struct bin_dialogex_control bdc; windres_put_32 (wrbfd, bdc.help, dc->help); @@ -1561,11 +1806,11 @@ res_to_bin_dialog (windres_bfd *wrbfd, rc_uint_type off, const rc_dialog *dialog windres_put_16 (wrbfd, bdc.width, dc->width); windres_put_16 (wrbfd, bdc.height, dc->height); windres_put_32 (wrbfd, bdc.id, dc->id); - set_windres_bfd_content (wrbfd, &bdc, off, BIN_DIALOGEX_CONTROL_SIZE); + set_windres_bfd_content (wrbfd, &bdc, off, + BIN_DIALOGEX_CONTROL_SIZE); } } - off += (dialogex != 0 ? BIN_DIALOGEX_CONTROL_SIZE : BIN_DIALOG_CONTROL_SIZE); - + off += dialogex != 0 ? BIN_DIALOGEX_CONTROL_SIZE : BIN_DIALOG_CONTROL_SIZE; off = resid_to_bin (wrbfd, off, dc->class); off = resid_to_bin (wrbfd, off, dc->text); @@ -1607,7 +1852,8 @@ res_to_bin_dialog (windres_bfd *wrbfd, rc_uint_type off, const rc_dialog *dialog /* Convert a fontdir resource to binary. */ static rc_uint_type -res_to_bin_fontdir (windres_bfd *wrbfd, rc_uint_type off, const rc_fontdir *fontdirs) +res_to_bin_fontdir (windres_bfd *wrbfd, rc_uint_type off, + const rc_fontdir *fontdirs) { rc_uint_type start; int c; @@ -1641,7 +1887,8 @@ res_to_bin_fontdir (windres_bfd *wrbfd, rc_uint_type off, const rc_fontdir *font /* Convert a group icon resource to binary. */ static rc_uint_type -res_to_bin_group_icon (windres_bfd *wrbfd, rc_uint_type off, const rc_group_icon *group_icons) +res_to_bin_group_icon (windres_bfd *wrbfd, rc_uint_type off, + const rc_group_icon *group_icons) { rc_uint_type start; struct bin_group_icon bgi; @@ -1691,21 +1938,21 @@ res_to_bin_menu (windres_bfd *wrbfd, rc_uint_type off, const rc_menu *menu) if (wrbfd) { - if (! menuex) - { + if (! menuex) + { struct bin_menu bm; windres_put_16 (wrbfd, bm.sig1, 0); windres_put_16 (wrbfd, bm.sig2, 0); set_windres_bfd_content (wrbfd, &bm, off, BIN_MENU_SIZE); - } - else - { + } + else + { struct bin_menuex bm; windres_put_16 (wrbfd, bm.sig1, 1); windres_put_16 (wrbfd, bm.sig2, 4); windres_put_32 (wrbfd, bm.help, menu->help); set_windres_bfd_content (wrbfd, &bm, off, BIN_MENUEX_SIZE); - } + } } off += (menuex != 0 ? BIN_MENUEX_SIZE : BIN_MENU_SIZE); if (! menuex) @@ -1722,7 +1969,8 @@ res_to_bin_menu (windres_bfd *wrbfd, rc_uint_type off, const rc_menu *menu) /* Convert menu items to binary. */ static rc_uint_type -res_to_bin_menuitems (windres_bfd *wrbfd, rc_uint_type off, const rc_menuitem *items) +res_to_bin_menuitems (windres_bfd *wrbfd, rc_uint_type off, + const rc_menuitem *items) { const rc_menuitem *mi; @@ -1740,11 +1988,12 @@ res_to_bin_menuitems (windres_bfd *wrbfd, rc_uint_type off, const rc_menuitem *i if (wrbfd) { windres_put_16 (wrbfd, bmi.flags, flags); - if (mi->popup == NULL) + if (mi->popup == NULL) windres_put_16 (wrbfd, bmi.id, mi->id); set_windres_bfd_content (wrbfd, &bmi, off, - mi->popup == NULL ? BIN_MENUITEM_SIZE - : BIN_MENUITEM_POPUP_SIZE); + (mi->popup == NULL + ? BIN_MENUITEM_SIZE + : BIN_MENUITEM_POPUP_SIZE)); } off += (mi->popup == NULL ? BIN_MENUITEM_SIZE : BIN_MENUITEM_POPUP_SIZE); @@ -1761,7 +2010,8 @@ res_to_bin_menuitems (windres_bfd *wrbfd, rc_uint_type off, const rc_menuitem *i /* Convert menuex items to binary. */ static rc_uint_type -res_to_bin_menuexitems (windres_bfd *wrbfd, rc_uint_type off, const rc_menuitem *items) +res_to_bin_menuexitems (windres_bfd *wrbfd, rc_uint_type off, + const rc_menuitem *items) { rc_uint_type off_delta = off; const rc_menuitem *mi; @@ -1814,7 +2064,8 @@ res_to_bin_menuexitems (windres_bfd *wrbfd, rc_uint_type off, const rc_menuitem to binary. */ static rc_uint_type -res_to_bin_rcdata (windres_bfd *wrbfd, rc_uint_type off, const rc_rcdata_item *items) +res_to_bin_rcdata (windres_bfd *wrbfd, rc_uint_type off, + const rc_rcdata_item *items) { const rc_rcdata_item *ri; @@ -1855,22 +2106,23 @@ res_to_bin_rcdata (windres_bfd *wrbfd, rc_uint_type off, const rc_rcdata_item *i break; case RCDATA_STRING: hp = (bfd_byte *) ri->u.string.s; - break; - case RCDATA_WSTRING: - { + break; + case RCDATA_WSTRING: + { rc_uint_type i; - hp = (bfd_byte *) reswr_alloc (len); - for (i = 0; i < ri->u.wstring.length; i++) - windres_put_16 (wrbfd, hp + i * sizeof (unichar), ri->u.wstring.w[i]); - } + hp = reswr_alloc (len); + for (i = 0; i < ri->u.wstring.length; i++) + windres_put_16 (wrbfd, hp + i * sizeof (unichar), + ri->u.wstring.w[i]); + } break; - case RCDATA_BUFFER: + case RCDATA_BUFFER: hp = (bfd_byte *) ri->u.buffer.data; - break; - } + break; + } set_windres_bfd_content (wrbfd, hp, off, len); - } + } off += len; } return off; @@ -1899,13 +2151,13 @@ res_to_bin_stringtable (windres_bfd *wrbfd, rc_uint_type off, bfd_byte *hp; rc_uint_type j; - hp = (bfd_byte *) reswr_alloc (length); + hp = reswr_alloc (length); windres_put_16 (wrbfd, hp, slen); - for (j = 0; j < slen; j++) + for (j = 0; j < slen; j++) windres_put_16 (wrbfd, hp + 2 + j * 2, s[j]); set_windres_bfd_content (wrbfd, hp, off, length); - } + } off += length; } return off; @@ -1926,7 +2178,7 @@ string_to_unicode_bin (windres_bfd *wrbfd, rc_uint_type off, const char *s) rc_uint_type i; bfd_byte *hp; - hp = (bfd_byte *) reswr_alloc ((len + 1) * sizeof (unichar)); + hp = reswr_alloc ((len + 1) * sizeof (unichar)); for (i = 0; i < len; i++) windres_put_16 (wrbfd, hp + i * 2, s[i]); @@ -1953,7 +2205,7 @@ res_to_bin_toolbar (windres_bfd *wrbfd, rc_uint_type off, rc_toolbar *tb) bfd_byte *ids; rc_uint_type i = 0; - ids = (bfd_byte *) reswr_alloc (tb->nitems * 4); + ids = reswr_alloc (tb->nitems * 4); it=tb->items; while(it != NULL) { @@ -1992,7 +2244,7 @@ res_to_bin_versioninfo (windres_bfd *wrbfd, rc_uint_type off, struct bin_fixed_versioninfo bfv; const rc_fixed_versioninfo *fi; - fi = versioninfo->fixed; + fi = versioninfo->fixed; windres_put_32 (wrbfd, bfv.sig1, 0xfeef04bd); windres_put_32 (wrbfd, bfv.sig2, 0x10000); windres_put_32 (wrbfd, bfv.file_version, fi->file_version_ms); @@ -2119,13 +2371,13 @@ res_to_bin_versioninfo (windres_bfd *wrbfd, rc_uint_type off, off += 4; } if (wrbfd) - { + { windres_put_16 (wrbfd, bvvd.size, off - vvd_off); windres_put_16 (wrbfd, bvvd.sig1, off - vvvd_off); windres_put_16 (wrbfd, bvvd.sig2, 0); set_windres_bfd_content (wrbfd, &bvvd, vvd_off, BIN_VER_INFO_SIZE); - } + } break; } @@ -2146,7 +2398,7 @@ res_to_bin_versioninfo (windres_bfd *wrbfd, rc_uint_type off, windres_put_16 (wrbfd, bvi.size, off - start); windres_put_16 (wrbfd, bvi.fixed_size, versioninfo->fixed == NULL ? 0 - : BIN_FIXED_VERSIONINFO_SIZE); + : BIN_FIXED_VERSIONINFO_SIZE); windres_put_16 (wrbfd, bvi.sig2, 0); set_windres_bfd_content (wrbfd, &bvi, start, BIN_VER_INFO_SIZE); } diff --git a/binutils/rescoff.c b/binutils/rescoff.c index f9a1e70..88b5f34 100644 --- a/binutils/rescoff.c +++ b/binutils/rescoff.c @@ -120,27 +120,38 @@ read_coff_rsrc (const char *filename, const char *target) struct coff_file_info flaginfo; if (filename == NULL) - fatal (_("filename required for COFF input")); + { + non_fatal (_("filename required for COFF input")); + return NULL; + } abfd = bfd_openr (filename, target); if (abfd == NULL) - bfd_fatal (filename); + { + bfd_nonfatal (filename); + return NULL; + } if (! bfd_check_format_matches (abfd, bfd_object, &matching)) { bfd_nonfatal (bfd_get_filename (abfd)); if (bfd_get_error () == bfd_error_file_ambiguously_recognized) list_matching_formats (matching); - xexit (1); + free (matching); + return NULL; } if (bfd_get_flavour (abfd) != bfd_target_coff_flavour || !obj_pe (abfd)) - fatal (_("%s: not a PE file"), filename); + { + non_fatal (_("%s: not a PE file"), filename); + return NULL; + } sec = bfd_get_section_by_name (abfd, ".rsrc"); if (sec == NULL) { - fatal (_("%s: no resource section"), filename); + non_fatal (_("%s: no resource section"), filename); + return NULL; } set_windres_bfd (&wrbfd, abfd, sec, WR_KIND_BFD); @@ -150,7 +161,10 @@ read_coff_rsrc (const char *filename, const char *target) but there is no other way to determine if the section size is reasonable. */ if (size > (bfd_size_type) get_file_size (filename)) - fatal (_("%s: .rsrc section is bigger than the file!"), filename); + { + non_fatal (_("%s: .rsrc section is bigger than the file!"), filename); + return NULL; + } data = (bfd_byte *) res_alloc (size); get_windres_bfd_content (&wrbfd, data, 0, size); @@ -178,7 +192,7 @@ read_coff_rsrc (const char *filename, const char *target) static void overrun (const struct coff_file_info *flaginfo, const char *msg) { - fatal (_("%s: %s: address out of bounds"), flaginfo->filename, msg); + non_fatal (_("%s: %s: address out of bounds"), flaginfo->filename, msg); } /* Read a resource directory. */ @@ -199,10 +213,17 @@ read_coff_res_dir (windres_bfd *wrbfd, const bfd_byte *data, Microsoft only defines 3 levels. Corrupt files however might claim to use more. */ if (level > 4) - fatal (_("%s: resources nest too deep"), flaginfo->filename); + { + non_fatal (_("%s: resources nest too deep"), flaginfo->filename); + return NULL; + } - if ((size_t) (flaginfo->data_end - data) < sizeof (struct extern_res_directory)) - overrun (flaginfo, _("directory")); + size_t data_len = flaginfo->data_end - data; + if (data_len < sizeof (struct extern_res_directory)) + { + overrun (flaginfo, _("directory")); + return NULL; + } erd = (const struct extern_res_directory *) data; @@ -229,8 +250,12 @@ read_coff_res_dir (windres_bfd *wrbfd, const bfd_byte *data, const bfd_byte *ers; int length, j; - if ((const bfd_byte *) ere >= flaginfo->data_end) - overrun (flaginfo, _("named directory entry")); + if ((const bfd_byte *) ere > flaginfo->data_end + || flaginfo->data_end - (const bfd_byte *) ere < 8) + { + overrun (flaginfo, _("named directory entry")); + return NULL; + } name = windres_get_32 (wrbfd, ere->name, 4); rva = windres_get_32 (wrbfd, ere->rva, 4); @@ -238,24 +263,32 @@ read_coff_res_dir (windres_bfd *wrbfd, const bfd_byte *data, /* For some reason the high bit in NAME is set. */ name &=~ 0x80000000; - if (name > (rc_uint_type) (flaginfo->data_end - flaginfo->data)) - overrun (flaginfo, _("directory entry name")); + if (name > data_len) + { + overrun (flaginfo, _("directory entry name")); + return NULL; + } ers = flaginfo->data + name; - + if (flaginfo->data_end - ers < 2) + { + overrun (flaginfo, _("resource name")); + return NULL; + } + length = windres_get_16 (wrbfd, ers, 2); + /* PR 17512: file: 05dc4a16. */ + if (length * 2 + 4 > flaginfo->data_end - ers) + { + overrun (flaginfo, _("resource name")); + return NULL; + } re = (rc_res_entry *) res_alloc (sizeof *re); re->next = NULL; re->id.named = 1; - length = windres_get_16 (wrbfd, ers, 2); re->id.u.n.length = length; re->id.u.n.name = (unichar *) res_alloc (length * sizeof (unichar)); for (j = 0; j < length; j++) - { - /* PR 17512: file: 05dc4a16. */ - if (length < 0 || ers >= flaginfo->data_end || ers + j * 2 + 4 >= flaginfo->data_end) - overrun (flaginfo, _("resource name")); - re->id.u.n.name[j] = windres_get_16 (wrbfd, ers + j * 2 + 2, 2); - } + re->id.u.n.name[j] = windres_get_16 (wrbfd, ers + j * 2 + 2, 2); if (level == 0) type = &re->id; @@ -263,18 +296,25 @@ read_coff_res_dir (windres_bfd *wrbfd, const bfd_byte *data, if ((rva & 0x80000000) != 0) { rva &=~ 0x80000000; - if (rva >= (rc_uint_type) (flaginfo->data_end - flaginfo->data)) - overrun (flaginfo, _("named subdirectory")); + if (rva >= data_len) + { + overrun (flaginfo, _("named subdirectory")); + return NULL; + } re->subdir = 1; - re->u.dir = read_coff_res_dir (wrbfd, flaginfo->data + rva, flaginfo, type, - level + 1); + re->u.dir = read_coff_res_dir (wrbfd, flaginfo->data + rva, flaginfo, + type, level + 1); } else { - if (rva >= (rc_uint_type) (flaginfo->data_end - flaginfo->data)) - overrun (flaginfo, _("named resource")); + if (rva >= data_len) + { + overrun (flaginfo, _("named resource")); + return NULL; + } re->subdir = 0; - re->u.res = read_coff_data_entry (wrbfd, flaginfo->data + rva, flaginfo, type); + re->u.res = read_coff_data_entry (wrbfd, flaginfo->data + rva, + flaginfo, type); } *pp = re; @@ -286,8 +326,12 @@ read_coff_res_dir (windres_bfd *wrbfd, const bfd_byte *data, unsigned long name, rva; rc_res_entry *re; - if ((const bfd_byte *) ere >= flaginfo->data_end) - overrun (flaginfo, _("ID directory entry")); + if ((const bfd_byte *) ere > flaginfo->data_end + || flaginfo->data_end - (const bfd_byte *) ere < 8) + { + overrun (flaginfo, _("ID directory entry")); + return NULL; + } name = windres_get_32 (wrbfd, ere->name, 4); rva = windres_get_32 (wrbfd, ere->rva, 4); @@ -303,18 +347,25 @@ read_coff_res_dir (windres_bfd *wrbfd, const bfd_byte *data, if ((rva & 0x80000000) != 0) { rva &=~ 0x80000000; - if (rva >= (rc_uint_type) (flaginfo->data_end - flaginfo->data)) - overrun (flaginfo, _("ID subdirectory")); + if (rva >= data_len) + { + overrun (flaginfo, _("ID subdirectory")); + return NULL; + } re->subdir = 1; - re->u.dir = read_coff_res_dir (wrbfd, flaginfo->data + rva, flaginfo, type, - level + 1); + re->u.dir = read_coff_res_dir (wrbfd, flaginfo->data + rva, flaginfo, + type, level + 1); } else { - if (rva >= (rc_uint_type) (flaginfo->data_end - flaginfo->data)) - overrun (flaginfo, _("ID resource")); + if (rva >= data_len) + { + overrun (flaginfo, _("ID resource")); + return NULL; + } re->subdir = 0; - re->u.res = read_coff_data_entry (wrbfd, flaginfo->data + rva, flaginfo, type); + re->u.res = read_coff_data_entry (wrbfd, flaginfo->data + rva, + flaginfo, type); } *pp = re; @@ -337,10 +388,16 @@ read_coff_data_entry (windres_bfd *wrbfd, const bfd_byte *data, const bfd_byte *resdata; if (type == NULL) - fatal (_("resource type unknown")); + { + non_fatal (_("resource type unknown")); + return NULL; + } if ((size_t) (flaginfo->data_end - data) < sizeof (struct extern_res_data)) - overrun (flaginfo, _("data entry")); + { + overrun (flaginfo, _("data entry")); + return NULL; + } erd = (const struct extern_res_data *) data; @@ -348,18 +405,26 @@ read_coff_data_entry (windres_bfd *wrbfd, const bfd_byte *data, rva = windres_get_32 (wrbfd, erd->rva, 4); if (rva < flaginfo->secaddr || rva - flaginfo->secaddr >= (rc_uint_type) (flaginfo->data_end - flaginfo->data)) - overrun (flaginfo, _("resource data")); + { + overrun (flaginfo, _("resource data")); + return NULL; + } resdata = flaginfo->data + (rva - flaginfo->secaddr); if (size > (rc_uint_type) (flaginfo->data_end - resdata)) - overrun (flaginfo, _("resource data size")); + { + overrun (flaginfo, _("resource data size")); + return NULL; + } r = bin_to_res (wrbfd, *type, resdata, size); - - memset (&r->res_info, 0, sizeof (rc_res_res_info)); - r->coff_info.codepage = windres_get_32 (wrbfd, erd->codepage, 4); - r->coff_info.reserved = windres_get_32 (wrbfd, erd->reserved, 4); + if (r != NULL) + { + memset (&r->res_info, 0, sizeof (rc_res_res_info)); + r->coff_info.codepage = windres_get_32 (wrbfd, erd->codepage, 4); + r->coff_info.reserved = windres_get_32 (wrbfd, erd->reserved, 4); + } return r; } @@ -422,9 +487,9 @@ struct coff_write_info static void coff_bin_sizes (const rc_res_directory *, struct coff_write_info *); static bfd_byte *coff_alloc (struct bindata_build *, rc_uint_type); -static void coff_to_bin +static bool coff_to_bin (const rc_res_directory *, struct coff_write_info *); -static void coff_res_to_bin +static bool coff_res_to_bin (const rc_res_resource *, struct coff_write_info *); /* Write resources to a COFF file. RESOURCES should already be @@ -435,7 +500,7 @@ static void coff_res_to_bin would require doing the basic work of objcopy, just modifying or adding the .rsrc section. */ -void +bool write_coff_file (const char *filename, const char *target, const rc_res_directory *resources) { @@ -448,44 +513,77 @@ write_coff_file (const char *filename, const char *target, unsigned long length, offset; if (filename == NULL) - fatal (_("filename required for COFF output")); + { + non_fatal (_("filename required for COFF output")); + return false; + } abfd = bfd_openw (filename, target); if (abfd == NULL) - bfd_fatal (filename); + { + bfd_nonfatal (filename); + return false; + } if (! bfd_set_format (abfd, bfd_object)) - bfd_fatal ("bfd_set_format"); + { + bfd_nonfatal ("bfd_set_format"); + return false; + } #if defined DLLTOOL_SH if (! bfd_set_arch_mach (abfd, bfd_arch_sh, 0)) - bfd_fatal ("bfd_set_arch_mach(sh)"); + { + bfd_nonfatal ("bfd_set_arch_mach(sh)"); + return false; + } #elif defined DLLTOOL_MIPS if (! bfd_set_arch_mach (abfd, bfd_arch_mips, 0)) - bfd_fatal ("bfd_set_arch_mach(mips)"); + { + bfd_nonfatal ("bfd_set_arch_mach(mips)"); + return false; + } #elif defined DLLTOOL_ARM if (! bfd_set_arch_mach (abfd, bfd_arch_arm, 0)) - bfd_fatal ("bfd_set_arch_mach(arm)"); + { + bfd_nonfatal ("bfd_set_arch_mach(arm)"); + return false; + } #elif defined DLLTOOL_AARCH64 if (! bfd_set_arch_mach (abfd, bfd_arch_aarch64, 0)) - bfd_fatal ("bfd_set_arch_mach(aarch64)"); + { + bfd_nonfatal ("bfd_set_arch_mach(aarch64)"); + return false; + } #else /* FIXME: This is obviously i386 specific. */ if (! bfd_set_arch_mach (abfd, bfd_arch_i386, 0)) - bfd_fatal ("bfd_set_arch_mach(i386)"); + { + bfd_nonfatal ("bfd_set_arch_mach(i386)"); + return false; + } #endif if (! bfd_set_file_flags (abfd, HAS_SYMS | HAS_RELOC)) - bfd_fatal ("bfd_set_file_flags"); + { + bfd_nonfatal ("bfd_set_file_flags"); + return false; + } sec = bfd_make_section_with_flags (abfd, ".rsrc", (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_DATA | SEC_READONLY)); if (sec == NULL) - bfd_fatal ("bfd_make_section"); + { + bfd_nonfatal ("bfd_make_section"); + return false; + } if (! bfd_set_symtab (abfd, &sec->symbol, 1)) - bfd_fatal ("bfd_set_symtab"); + { + bfd_nonfatal ("bfd_set_symtab"); + return false; + } /* Requiring this is probably a bug in BFD. */ sec->output_section = sec; @@ -529,7 +627,8 @@ write_coff_file (const char *filename, const char *target, cwi.dirstrsize = (cwi.dirstrsize + 7) & ~7; /* Actually convert the resources to binary. */ - coff_to_bin (resources, &cwi); + if (!coff_to_bin (resources, &cwi)) + return false; /* Add another few bytes to the directory strings if needed for alignment. */ @@ -554,7 +653,10 @@ write_coff_file (const char *filename, const char *target, + cwi.resources.length); if (!bfd_set_section_size (sec, length)) - bfd_fatal ("bfd_set_section_size"); + { + bfd_nonfatal ("bfd_set_section_size"); + return false; + } bfd_set_reloc (abfd, sec, cwi.relocs, cwi.reloc_count); @@ -562,7 +664,10 @@ write_coff_file (const char *filename, const char *target, for (d = cwi.dirs.d; d != NULL; d = d->next) { if (! bfd_set_section_contents (abfd, sec, d->data, offset, d->length)) - bfd_fatal ("bfd_set_section_contents"); + { + bfd_nonfatal ("bfd_set_section_contents"); + return false; + } offset += d->length; } for (d = cwi.dirstrs.d; d != NULL; d = d->next) @@ -577,17 +682,23 @@ write_coff_file (const char *filename, const char *target, } for (rd = cwi.resources.d; rd != NULL; rd = rd->next) { - res_to_bin (cwi.wrbfd, (rc_uint_type) offset, rd->res); + if (res_to_bin (cwi.wrbfd, (rc_uint_type) offset, rd->res) + == (rc_uint_type) -1) + return false; offset += rd->length; } assert (offset == length); if (! bfd_close (abfd)) - bfd_fatal ("bfd_close"); + { + bfd_nonfatal ("bfd_close"); + return false; + } /* We allocated the relocs array using malloc. */ free (cwi.relocs); + return true; } /* Work out the sizes of the various fixed size resource directory @@ -640,7 +751,7 @@ coff_alloc (struct bindata_build *bb, rc_uint_type size) /* Convert the resource directory RESDIR to binary. */ -static void +static bool coff_to_bin (const rc_res_directory *resdir, struct coff_write_info *cwi) { struct extern_res_directory *erd; @@ -701,21 +812,24 @@ coff_to_bin (const rc_res_directory *resdir, struct coff_write_info *cwi) if (e->subdir) { windres_put_32 (cwi->wrbfd, ere->rva, 0x80000000 | cwi->dirs.length); - coff_to_bin (e->u.dir, cwi); + if (!coff_to_bin (e->u.dir, cwi)) + return false; } else { windres_put_32 (cwi->wrbfd, ere->rva, - cwi->dirsize + cwi->dirstrsize + cwi->dataents.length); + cwi->dirsize + cwi->dirstrsize + cwi->dataents.length); - coff_res_to_bin (e->u.res, cwi); + if (!coff_res_to_bin (e->u.res, cwi)) + return false; } } + return true; } /* Convert the resource RES to binary. */ -static void +static bool coff_res_to_bin (const rc_res_resource *res, struct coff_write_info *cwi) { arelent *r; @@ -735,7 +849,10 @@ coff_res_to_bin (const rc_res_resource *res, struct coff_write_info *cwi) r->addend = 0; r->howto = bfd_reloc_type_lookup (WR_BFD (cwi->wrbfd), BFD_RELOC_RVA); if (r->howto == NULL) - bfd_fatal (_("can't get BFD_RELOC_RVA relocation type")); + { + bfd_nonfatal (_("can't get BFD_RELOC_RVA relocation type")); + return false; + } cwi->relocs = xrealloc (cwi->relocs, (cwi->reloc_count + 2) * sizeof (arelent *)); @@ -755,6 +872,8 @@ coff_res_to_bin (const rc_res_resource *res, struct coff_write_info *cwi) d = (coff_res_data *) reswr_alloc (sizeof (coff_res_data)); d->length = res_to_bin (NULL, (rc_uint_type) 0, res); + if (d->length == (rc_uint_type) -1) + return false; d->res = res; d->next = NULL; @@ -770,4 +889,5 @@ coff_res_to_bin (const rc_res_resource *res, struct coff_write_info *cwi) /* Force the next resource to have 64 bit alignment. */ d->length = (d->length + 7) & ~7; + return true; } diff --git a/binutils/resrc.c b/binutils/resrc.c index d265818..8f9451b 100644 --- a/binutils/resrc.c +++ b/binutils/resrc.c @@ -1938,7 +1938,7 @@ indent (FILE *e, int c) refer to that file, we use the user-data model for that to express it binary without the need to store it somewhere externally. */ -void +bool write_rc_file (const char *filename, const rc_res_directory *res_dir) { FILE *e; @@ -1950,12 +1950,17 @@ write_rc_file (const char *filename, const rc_res_directory *res_dir) { e = fopen (filename, FOPEN_WT); if (e == NULL) - fatal (_("can't open `%s' for output: %s"), filename, strerror (errno)); + { + non_fatal (_("can't open `%s' for output: %s"), + filename, strerror (errno)); + return false; + } } language = (rc_uint_type) ((bfd_signed_vma) -1); write_rc_directory (e, res_dir, (const rc_res_id *) NULL, (const rc_res_id *) NULL, &language, 1); + return true; } /* Write out a directory. E is the file to write to. RD is the diff --git a/binutils/resres.c b/binutils/resres.c index ab5aa66..d96fb14 100644 --- a/binutils/resres.c +++ b/binutils/resres.c @@ -109,14 +109,14 @@ read_res_file (const char *fn) } /* Write resource file */ -void +bool write_res_file (const char *fn,const rc_res_directory *resdir) { asection *sec; rc_uint_type language; bfd *abfd; windres_bfd wrbfd; - unsigned long sec_length = 0,sec_length_wrote; + rc_uint_type sec_length = 0, sec_length_wrote; static const bfd_byte sign[] = {0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, @@ -130,7 +130,10 @@ write_res_file (const char *fn,const rc_res_directory *resdir) (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_DATA)); if (sec == NULL) - bfd_fatal ("bfd_make_section"); + { + bfd_nonfatal ("bfd_make_section"); + return false; + } /* Requiring this is probably a bug in BFD. */ sec->output_section = sec; @@ -142,8 +145,13 @@ write_res_file (const char *fn,const rc_res_directory *resdir) sec_length = write_res_directory ((windres_bfd *) NULL, 0x20UL, resdir, (const rc_res_id *) NULL, (const rc_res_id *) NULL, &language, 1); + if (sec_length == (rc_uint_type) -1) + return false; if (!bfd_set_section_size (sec, (sec_length + 3) & ~3)) - bfd_fatal ("bfd_set_section_size"); + { + bfd_nonfatal ("bfd_set_section_size"); + return false; + } if ((sec_length & 3) != 0) set_windres_bfd_content (&wrbfd, sign, sec_length, 4-(sec_length & 3)); set_windres_bfd_content (&wrbfd, sign, 0, sizeof (sign)); @@ -152,12 +160,16 @@ write_res_file (const char *fn,const rc_res_directory *resdir) (const rc_res_id *) NULL, (const rc_res_id *) NULL, &language, 1); + if (sec_length_wrote == (rc_uint_type) -1) + return false; if (sec_length != sec_length_wrote) - fatal ("res write failed with different sizes (%lu/%lu).", - (unsigned long) sec_length, (unsigned long) sec_length_wrote); + { + non_fatal ("res write failed with different sizes (%lu/%lu).", + (unsigned long) sec_length, (unsigned long) sec_length_wrote); + return false; + } - bfd_close (abfd); - return; + return bfd_close (abfd); } /* Read a resource entry, returns 0 when all resources are read */ @@ -252,8 +264,12 @@ write_res_directory (windres_bfd *wrbfd, rc_uint_type off, const rc_res_director } if (re->subdir) - off = write_res_directory (wrbfd, off, re->u.dir, type, name, language, - level + 1); + { + off = write_res_directory (wrbfd, off, re->u.dir, type, name, language, + level + 1); + if (off == (rc_uint_type) -1) + return off; + } else { if (level == 3) @@ -265,12 +281,16 @@ write_res_directory (windres_bfd *wrbfd, rc_uint_type off, const rc_res_director resource itself records if anything. */ off = write_res_resource (wrbfd, off, type, name, re->u.res, language); + if (off == (rc_uint_type) -1) + return off; } else { fprintf (stderr, "// Resource at unexpected level %d\n", level); off = write_res_resource (wrbfd, off, type, (rc_res_id *) NULL, re->u.res, language); + if (off == (rc_uint_type) -1) + return off; } } } @@ -378,6 +398,8 @@ write_res_bin (windres_bfd *wrbfd, rc_uint_type off, const rc_res_resource *res, rc_uint_type datasize = 0; noff = res_to_bin ((windres_bfd *) NULL, off, res); + if (noff == (rc_uint_type) -1) + return noff; datasize = noff - off; off = write_res_header (wrbfd, off, datasize, type, name, resinfo); diff --git a/binutils/windres.c b/binutils/windres.c index 18062f5..b41353b 100644 --- a/binutils/windres.c +++ b/binutils/windres.c @@ -1056,23 +1056,24 @@ main (int argc, char **argv) /* Write the output file. */ reswr_init (); + bool ok; switch (output_format) { default: abort (); case RES_FORMAT_RC: - write_rc_file (output_filename, resources); + ok = write_rc_file (output_filename, resources); break; case RES_FORMAT_RES: - write_res_file (output_filename, resources); + ok = write_res_file (output_filename, resources); break; case RES_FORMAT_COFF: - write_coff_file (output_filename, target, resources); + ok = write_coff_file (output_filename, target, resources); break; } - xexit (0); - return 0; + xexit (ok ? 0 : 1); + return ok ? 0 : 1; } static void @@ -1094,13 +1095,18 @@ windres_open_as_binary (const char *filename, int rdmode) { bfd *abfd; - abfd = (rdmode ? bfd_openr (filename, "binary") : bfd_openw (filename, "binary")); - if (! abfd) - fatal ("can't open `%s' for %s", filename, (rdmode ? "input" : "output")); - - if (rdmode && ! bfd_check_format (abfd, bfd_object)) - fatal ("can't open `%s' for input.", filename); - + if (rdmode) + { + abfd = bfd_openr (filename, "binary"); + if (abfd == NULL || !bfd_check_format (abfd, bfd_object)) + fatal ("can't open `%s' for input", filename); + } + else + { + abfd = bfd_openw (filename, "binary"); + if (abfd == NULL || !bfd_set_format (abfd, bfd_object)) + fatal ("can't open `%s' for output", filename); + } return abfd; } diff --git a/binutils/windres.h b/binutils/windres.h index 309564e..15c6ad0 100644 --- a/binutils/windres.h +++ b/binutils/windres.h @@ -35,9 +35,9 @@ extern int verbose; extern rc_res_directory *read_rc_file (const char *, const char *, const char *, int, int); extern rc_res_directory *read_res_file (const char *); extern rc_res_directory *read_coff_rsrc (const char *, const char *); -extern void write_rc_file (const char *, const rc_res_directory *); -extern void write_res_file (const char *, const rc_res_directory *); -extern void write_coff_file (const char *, const char *, const rc_res_directory *); +extern bool write_rc_file (const char *, const rc_res_directory *); +extern bool write_res_file (const char *, const rc_res_directory *); +extern bool write_coff_file (const char *, const char *, const rc_res_directory *); extern rc_res_resource *bin_to_res (windres_bfd *, rc_res_id, const bfd_byte *, rc_uint_type); diff --git a/gdb/ada-lang.c b/gdb/ada-lang.c index 9d35440..3f5e707 100644 --- a/gdb/ada-lang.c +++ b/gdb/ada-lang.c @@ -36,7 +36,7 @@ #include "objfiles.h" #include "breakpoint.h" #include "gdbcore.h" -#include "hashtab.h" +#include "gdbsupport/unordered_set.h" #include "gdbsupport/gdb_obstack.h" #include "ada-lang.h" #include "completer.h" @@ -52,6 +52,7 @@ #include "namespace.h" #include "cli/cli-style.h" #include "cli/cli-decode.h" +#include "gdbsupport/string-set.h" #include "value.h" #include "mi/mi-common.h" @@ -349,56 +350,58 @@ struct cache_entry_search { const char *name; domain_search_flags domain; +}; + +/* Hash function for cache entry. */ + +struct cache_entry_hash +{ + using is_transparent = void; + using is_avalanching = void; - hashval_t hash () const + /* This implementation works for both cache_entry and + cache_entry_search. */ + template<typename T> + uint64_t operator() (const T &entry) const noexcept { - /* This must agree with hash_cache_entry, below. */ - return htab_hash_string (name); + return ankerl::unordered_dense::hash<std::string_view> () (entry.name); } }; -/* Hash function for cache_entry. */ +/* Equality function for cache entry. */ -static hashval_t -hash_cache_entry (const void *v) +struct cache_entry_eq { - const cache_entry *entry = (const cache_entry *) v; - return htab_hash_string (entry->name.c_str ()); -} - -/* Equality function for cache_entry. */ + using is_transparent = void; -static int -eq_cache_entry (const void *a, const void *b) -{ - const cache_entry *entrya = (const cache_entry *) a; - const cache_entry_search *entryb = (const cache_entry_search *) b; + /* This implementation works for both cache_entry and + cache_entry_search. */ + template<typename T> + bool operator() (const T &lhs, const cache_entry &rhs) const noexcept + { + return lhs.domain == rhs.domain && lhs.name == rhs.name; + } +}; - return entrya->domain == entryb->domain && entrya->name == entryb->name; -} +using cache_entry_set + = gdb::unordered_set<cache_entry, cache_entry_hash, cache_entry_eq>; /* Key to our per-program-space data. */ -static const registry<program_space>::key<htab, htab_deleter> +static const registry<program_space>::key<cache_entry_set> ada_pspace_data_handle; -/* Return this module's data for the given program space (PSPACE). - If not is found, add a zero'ed one now. - - This function always returns a valid object. */ +/* Return this module's data for the given program space (PSPACE). If + not is found, one is created. This function always returns a valid + object. */ -static htab_t +static cache_entry_set & get_ada_pspace_data (struct program_space *pspace) { - htab_t data = ada_pspace_data_handle.get (pspace); + cache_entry_set *data = ada_pspace_data_handle.get (pspace); if (data == nullptr) - { - data = htab_create_alloc (10, hash_cache_entry, eq_cache_entry, - htab_delete_entry<cache_entry>, - xcalloc, xfree); - ada_pspace_data_handle.set (pspace, data); - } + data = ada_pspace_data_handle.emplace (pspace); - return data; + return *data; } /* Utilities */ @@ -1603,7 +1606,7 @@ ada_decode_tests () storage leak, it should not be significant unless there are massive changes in the set of decoded names in successive versions of a symbol table loaded during a single session. */ -static struct htab *decoded_names_store; +static gdb::string_set decoded_names_store; /* Returns the decoded name of GSYMBOL, as for ada_decode, caching it in the language-specific part of GSYMBOL, if it has not been @@ -1637,13 +1640,7 @@ ada_decode_symbol (const struct general_symbol_info *arg) which case, we put the result on the heap. Since we only decode when needed, we hope this usually does not cause a significant memory leak (FIXME). */ - - char **slot = (char **) htab_find_slot (decoded_names_store, - decoded.c_str (), INSERT); - - if (*slot == NULL) - *slot = xstrdup (decoded.c_str ()); - *resultp = *slot; + *resultp = decoded_names_store.insert (decoded); } } @@ -3950,9 +3947,9 @@ ada_type_match (struct type *ftype, struct type *atype) atype = ada_check_typedef (atype); if (ftype->code () == TYPE_CODE_REF) - ftype = ftype->target_type (); + ftype = ada_check_typedef (ftype->target_type ()); if (atype->code () == TYPE_CODE_REF) - atype = atype->target_type (); + atype = ada_check_typedef (atype->target_type ()); switch (ftype->code ()) { @@ -4695,19 +4692,18 @@ static int lookup_cached_symbol (const char *name, domain_search_flags domain, struct symbol **sym, const struct block **block) { - htab_t tab = get_ada_pspace_data (current_program_space); + cache_entry_set &htab = get_ada_pspace_data (current_program_space); cache_entry_search search; search.name = name; search.domain = domain; - cache_entry *e = (cache_entry *) htab_find_with_hash (tab, &search, - search.hash ()); - if (e == nullptr) + auto iter = htab.find (search); + if (iter == htab.end ()) return 0; if (sym != nullptr) - *sym = e->sym; + *sym = iter->sym; if (block != nullptr) - *block = e->block; + *block = iter->block; return 1; } @@ -4735,21 +4731,8 @@ cache_symbol (const char *name, domain_search_flags domain, return; } - htab_t tab = get_ada_pspace_data (current_program_space); - cache_entry_search search; - search.name = name; - search.domain = domain; - - void **slot = htab_find_slot_with_hash (tab, &search, - search.hash (), INSERT); - - cache_entry *e = new cache_entry; - e->name = name; - e->domain = domain; - e->sym = sym; - e->block = block; - - *slot = e; + cache_entry_set &tab = get_ada_pspace_data (current_program_space); + tab.insert (cache_entry {name, domain, sym, block}); } /* Symbol Lookup */ @@ -14049,10 +14032,6 @@ When enabled, the debugger will stop using the DW_AT_GNAT_descriptive_type\n\ DWARF attribute."), NULL, NULL, &maint_set_ada_cmdlist, &maint_show_ada_cmdlist); - decoded_names_store = htab_create_alloc (256, htab_hash_string, - htab_eq_string, - NULL, xcalloc, xfree); - /* The ada-lang observers. */ gdb::observers::new_objfile.attach (ada_new_objfile_observer, "ada-lang"); gdb::observers::all_objfiles_removed.attach (ada_clear_symbol_cache, diff --git a/gdb/dwarf2/read.c b/gdb/dwarf2/read.c index 6e96afe..794c397 100644 --- a/gdb/dwarf2/read.c +++ b/gdb/dwarf2/read.c @@ -2383,14 +2383,14 @@ read_abbrev_offset (dwarf2_per_objfile *per_objfile, return (sect_offset) read_offset (abfd, info_ptr, offset_size); } -/* A helper for create_debug_types_hash_table. Read types from SECTION +/* A helper for create_dwo_debug_types_hash_table. Read types from SECTION and fill them into DWO_FILE's type unit hash table. It will process only type units, therefore DW_UT_type. */ static void -create_debug_type_hash_table (dwarf2_per_objfile *per_objfile, - dwo_file *dwo_file, dwarf2_section_info *section, - rcuh_kind section_kind) +create_dwo_debug_type_hash_table (dwarf2_per_objfile *per_objfile, + dwo_file *dwo_file, dwarf2_section_info *section, + rcuh_kind section_kind) { struct objfile *objfile = per_objfile->objfile; struct dwarf2_section_info *abbrev_section; @@ -2479,12 +2479,12 @@ create_debug_type_hash_table (dwarf2_per_objfile *per_objfile, Note: This function processes DWO files only, not DWP files. */ static void -create_debug_types_hash_table +create_dwo_debug_types_hash_table (dwarf2_per_objfile *per_objfile, dwo_file *dwo_file, gdb::array_view<dwarf2_section_info> type_sections) { for (dwarf2_section_info §ion : type_sections) - create_debug_type_hash_table (per_objfile, dwo_file, §ion, + create_dwo_debug_type_hash_table (per_objfile, dwo_file, §ion, rcuh_kind::TYPE); } @@ -6308,7 +6308,7 @@ lookup_dwo_file (dwarf2_per_bfd *per_bfd, const char *dwo_name, Note: This function processes DWO files only, not DWP files. */ static void -create_cus_hash_table (dwarf2_cu *cu, dwo_file &dwo_file) +create_dwo_cus_hash_table (dwarf2_cu *cu, dwo_file &dwo_file) { dwarf2_per_objfile *per_objfile = cu->per_objfile; struct objfile *objfile = per_objfile->objfile; @@ -6342,6 +6342,12 @@ create_cus_hash_table (dwarf2_cu *cu, dwo_file &dwo_file) if (reader.is_dummy()) continue; + /* DWARF 5 .debug_info.dwo sections may contain some type units. Skip + everything that is not a compile unit. */ + if (const auto ut = reader.cu ()->header.unit_type; + ut != DW_UT_compile && ut != DW_UT_split_compile) + continue; + std::optional<ULONGEST> signature = lookup_dwo_id (reader.cu (), reader.top_level_die ()); if (!signature.has_value ()) @@ -7630,14 +7636,15 @@ open_and_init_dwo_file (dwarf2_cu *cu, const char *dwo_name, dwarf2_locate_dwo_sections (per_objfile->objfile, dwo_file->dbfd.get (), sec, &dwo_file->sections); - create_cus_hash_table (cu, *dwo_file); + create_dwo_cus_hash_table (cu, *dwo_file); if (cu->header.version < 5) - create_debug_types_hash_table (per_objfile, dwo_file.get (), - dwo_file->sections.types); + create_dwo_debug_types_hash_table (per_objfile, dwo_file.get (), + dwo_file->sections.types); else - create_debug_type_hash_table (per_objfile, dwo_file.get (), - &dwo_file->sections.info, rcuh_kind::COMPILE); + create_dwo_debug_type_hash_table (per_objfile, dwo_file.get (), + &dwo_file->sections.info, + rcuh_kind::COMPILE); dwarf_read_debug_printf ("DWO file found: %s", dwo_name); diff --git a/gdb/testsuite/gdb.ada/scalar_storage.exp b/gdb/testsuite/gdb.ada/scalar_storage.exp index 6b29226..52a85cd 100644 --- a/gdb/testsuite/gdb.ada/scalar_storage.exp +++ b/gdb/testsuite/gdb.ada/scalar_storage.exp @@ -45,10 +45,30 @@ if {![runto "storage.adb:$bp_location"]} { return } -gdb_test "print V_LE" "= \\(value => 126, another_value => 12, color => green\\)" +set re "value => 126, another_value => 12, color => green" # This requires a compiler fix that is in GCC 14. -if { ![gnat_version_compare >= 14] } { - setup_kfail "DW_AT_endianity on enum types" *-*-* +set have_xfail [expr ![gnat_version_compare >= 14]] +set re_color "(red|green|blue|$decimal)" +set re_xfail \ + "value => $decimal, another_value => $decimal, color => $re_color" + +set re_pre [string_to_regexp " = ("] +set re_post [string_to_regexp ")"] +set re $re_pre$re$re_post +set re_xfail $re_pre$re_xfail$re_post + +foreach var { V_LE V_BE } { + gdb_test_multiple "print $var" "" { + -re -wrap $re { + pass $gdb_test_name + } + -re -wrap $re_xfail { + if { $have_xfail } { + xfail $gdb_test_name + } else { + fail $gdb_test_name + } + } + } } -gdb_test "print V_BE" "= \\(value => 126, another_value => 12, color => green\\)" diff --git a/gdb/testsuite/gdb.arch/aarch64-sve-sigunwind.c b/gdb/testsuite/gdb.arch/aarch64-sve-sigunwind.c new file mode 100644 index 0000000..c86beaf --- /dev/null +++ b/gdb/testsuite/gdb.arch/aarch64-sve-sigunwind.c @@ -0,0 +1,205 @@ +/* This testcase is part of GDB, the GNU debugger. + + Copyright 2025 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +/* Exercise unwinding AArch64's SVE registers from a signal frame. */ + +#include <stdio.h> +#include <stdlib.h> +#include <signal.h> +#include <sys/prctl.h> +#include <unistd.h> + +static int second_vl = 0; + +static void +initialize_sve_state_main () +{ + __asm __volatile ("dup z0.b, -1"); + __asm __volatile ("dup z1.b, -1"); + __asm __volatile ("dup z2.b, -1"); + __asm __volatile ("dup z3.b, -1"); + __asm __volatile ("dup z4.b, -1"); + __asm __volatile ("dup z5.b, -1"); + __asm __volatile ("dup z6.b, -1"); + __asm __volatile ("dup z7.b, -1"); + __asm __volatile ("dup z8.b, -1"); + __asm __volatile ("dup z9.b, -1"); + __asm __volatile ("dup z10.b, -1"); + __asm __volatile ("dup z11.b, -1"); + __asm __volatile ("dup z12.b, -1"); + __asm __volatile ("dup z13.b, -1"); + __asm __volatile ("dup z14.b, -1"); + __asm __volatile ("dup z15.b, -1"); + __asm __volatile ("dup z16.b, -1"); + __asm __volatile ("dup z17.b, -1"); + __asm __volatile ("dup z18.b, -1"); + __asm __volatile ("dup z19.b, -1"); + __asm __volatile ("dup z20.b, -1"); + __asm __volatile ("dup z21.b, -1"); + __asm __volatile ("dup z22.b, -1"); + __asm __volatile ("dup z23.b, -1"); + __asm __volatile ("dup z24.b, -1"); + __asm __volatile ("dup z25.b, -1"); + __asm __volatile ("dup z26.b, -1"); + __asm __volatile ("dup z27.b, -1"); + __asm __volatile ("dup z28.b, -1"); + __asm __volatile ("dup z29.b, -1"); + __asm __volatile ("dup z30.b, -1"); + __asm __volatile ("dup z31.b, -1"); + __asm __volatile ("ptrue p0.d"); + __asm __volatile ("ptrue p1.d"); + __asm __volatile ("ptrue p2.d"); + __asm __volatile ("ptrue p3.d"); + __asm __volatile ("ptrue p4.d"); + __asm __volatile ("ptrue p5.d"); + __asm __volatile ("ptrue p6.d"); + __asm __volatile ("ptrue p7.d"); + __asm __volatile ("ptrue p8.d"); + __asm __volatile ("ptrue p9.d"); + __asm __volatile ("ptrue p10.d"); + __asm __volatile ("ptrue p11.d"); + __asm __volatile ("ptrue p12.d"); + __asm __volatile ("ptrue p13.d"); + __asm __volatile ("ptrue p14.d"); + __asm __volatile ("ptrue p15.d"); + __asm __volatile ("setffr"); +} + +static void +initialize_sve_state_sighandler () +{ + __asm __volatile ("dup z0.b, -2"); + __asm __volatile ("dup z1.b, -2"); + __asm __volatile ("dup z2.b, -2"); + __asm __volatile ("dup z3.b, -2"); + __asm __volatile ("dup z4.b, -2"); + __asm __volatile ("dup z5.b, -2"); + __asm __volatile ("dup z6.b, -2"); + __asm __volatile ("dup z7.b, -2"); + __asm __volatile ("dup z8.b, -2"); + __asm __volatile ("dup z9.b, -2"); + __asm __volatile ("dup z10.b, -2"); + __asm __volatile ("dup z11.b, -2"); + __asm __volatile ("dup z12.b, -2"); + __asm __volatile ("dup z13.b, -2"); + __asm __volatile ("dup z14.b, -2"); + __asm __volatile ("dup z15.b, -2"); + __asm __volatile ("dup z16.b, -2"); + __asm __volatile ("dup z17.b, -2"); + __asm __volatile ("dup z18.b, -2"); + __asm __volatile ("dup z19.b, -2"); + __asm __volatile ("dup z20.b, -2"); + __asm __volatile ("dup z21.b, -2"); + __asm __volatile ("dup z22.b, -2"); + __asm __volatile ("dup z23.b, -2"); + __asm __volatile ("dup z24.b, -2"); + __asm __volatile ("dup z25.b, -2"); + __asm __volatile ("dup z26.b, -2"); + __asm __volatile ("dup z27.b, -2"); + __asm __volatile ("dup z28.b, -2"); + __asm __volatile ("dup z29.b, -2"); + __asm __volatile ("dup z30.b, -2"); + __asm __volatile ("dup z31.b, -2"); + __asm __volatile ("pfalse p0.b"); + __asm __volatile ("pfalse p1.b"); + __asm __volatile ("pfalse p2.b"); + __asm __volatile ("pfalse p3.b"); + __asm __volatile ("pfalse p4.b"); + __asm __volatile ("pfalse p5.b"); + __asm __volatile ("pfalse p6.b"); + __asm __volatile ("pfalse p7.b"); + __asm __volatile ("pfalse p8.b"); + __asm __volatile ("pfalse p9.b"); + __asm __volatile ("pfalse p10.b"); + __asm __volatile ("pfalse p11.b"); + __asm __volatile ("pfalse p12.b"); + __asm __volatile ("pfalse p13.b"); + __asm __volatile ("pfalse p14.b"); + __asm __volatile ("pfalse p15.b"); + __asm __volatile ("setffr"); +} + +/* Set new value for the SVE vector length. + Return the value that was set. */ + +static int +set_vl (int vl) +{ + int rc; + + rc = prctl (PR_SVE_SET_VL, vl, 0, 0, 0); + if (rc < 0) + { + perror ("FAILED to PR_SVE_SET_VL"); + exit (EXIT_FAILURE); + } + + return rc & PR_SVE_VL_LEN_MASK; +} + +static void +sighandler (int sig, siginfo_t *info, void *ucontext) +{ + /* Set vector length to the second value. */ + second_vl = set_vl (second_vl); + initialize_sve_state_sighandler (); + printf ("sighandler: second_vl = %d\n", second_vl); /* Break here. */ +} + +int +main (int argc, char *argv[]) +{ + if (argc != 3) + { + fprintf (stderr, "Usage: %s <first vl> <second vl>\n", argv[0]); + return 1; + } + + int first_vl = atoi (argv[1]); + second_vl = atoi (argv[2]); + + if (first_vl == 0 || second_vl == 0) + { + fprintf (stderr, "Invalid vector length.\n"); + return 1; + } + + /* Set vector length to the first value. */ + first_vl = set_vl (first_vl); + + printf ("main: first_vl = %d\n", first_vl); + + unsigned char buf[256]; + + /* Use an SVE register to make the kernel start saving the SVE bank. */ + asm volatile ("mov z0.b, #255\n\t" + "str z0, %0" + : + : "m" (buf) + : "z0", "memory"); + + initialize_sve_state_main (); + + struct sigaction sigact; + sigact.sa_sigaction = sighandler; + sigact.sa_flags = SA_SIGINFO; + sigaction (SIGUSR1, &sigact, NULL); + + kill (getpid (), SIGUSR1); + + return 0; +} diff --git a/gdb/testsuite/gdb.arch/aarch64-sve-sigunwind.exp b/gdb/testsuite/gdb.arch/aarch64-sve-sigunwind.exp new file mode 100644 index 0000000..32340bb --- /dev/null +++ b/gdb/testsuite/gdb.arch/aarch64-sve-sigunwind.exp @@ -0,0 +1,106 @@ +# Copyright 2025 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +# Exercise unwinding AArch64's SVE registers from a signal frame. + +require allow_aarch64_sve_tests +# Remote targets can't communicate vector length changes to GDB via the RSP. +require !gdb_protocol_is_remote + +set first_vl 0 +set second_vl 0 + +# Find two valid VL values to use in the test. +# The minimum supported VL is 16 bytes, maximum is 256 bytes, and VL can change +# in increments of at least 16 bytes. +for {set i 16} {$i <= 256} {incr i 16} { + if {![aarch64_supports_sve_vl $i]} { + continue + } + + if {$first_vl == 0} { + set first_vl $i + } elseif {$second_vl == 0} { + set second_vl $i + break + } +} + +if {$first_vl == 0 || $second_vl == 0} { + untested "test needs to support at least two vector lengths" + return +} + +standard_testfile +if { [prepare_for_testing "failed to prepare" ${testfile} ${srcfile} \ + [list debug additional_flags=-march=armv9-a]] } { + return +} + +# We want SIGUSR1 to be delivered normally. +gdb_test "handle SIGUSR1 nostop" \ + [multi_line {Signal Stop Print Pass to program Description} \ + {SIGUSR1 No Yes Yes User defined signal 1}] \ + "don't stop for SIGUSR1" + +set linespec ${srcfile}:[gdb_get_line_number "Break here."] +gdb_test_no_output "set args $first_vl $second_vl" + +if ![runto ${linespec}] { + return +} + +set first_vg [expr $first_vl/8] +set second_vg [expr $second_vl/8] + +gdb_test "print \$vg" ". = $second_vg" "vg was changed" + +for {set row 0} {$row < 32} {incr row} { + set register_name "\$z${row}\.b\.u" + gdb_test "print sizeof $register_name" " = $second_vl" \ + "size of $register_name in the signal handler" + gdb_test "print $register_name" ". = \\{254 <repeats $second_vl times>\\}" \ + "$register_name contents in signal handler" +} + +for {set row 0} {$row < 16} {incr row} { + set register_name "\$p${row}" + gdb_test "print $register_name" ". = \\{(0, ){[expr $second_vl/8 - 1]}0\\}" \ + "$register_name contents in signal handler" +} +gdb_test "print \$ffr" ". = \\{(255, ){[expr $second_vl/8 - 1]}255\\}" \ + "ffr contents in signal handler" + +gdb_test "frame function main" \ + [multi_line "#$decimal $hex in main \[^\r\n\]+" \ + "$decimal\[ \t\]+kill \\(getpid \\(\\), SIGUSR1\\);"] + +gdb_test "print \$vg" ". = $first_vg" "vg was correctly unwound" + +for {set row 0} {$row < 32} {incr row} { + set register_name "\$z${row}\.b\.u" + gdb_test "print sizeof $register_name" " = $first_vl" \ + "size of $register_name was correctly unwound" + gdb_test "print $register_name" ". = \\{255 <repeats $first_vl times>\\}" \ + "$register_name contents were correctly unwound" +} + +for {set row 0} {$row < 16} {incr row} { + set register_name "\$p${row}" + gdb_test "print $register_name" ". = \\{(1, ){[expr $first_vl/8 - 1]}1\\}" \ + "$register_name contents were correctly unwound" +} +gdb_test "print \$ffr" ". = \\{(255, ){[expr $first_vl/8 - 1]}255\\}" \ + "ffr contents were correctly unwound" diff --git a/gdb/testsuite/gdb.base/bg-execution-repeat.c b/gdb/testsuite/gdb.base/bg-execution-repeat.c index 8e9bae4..3c0cc76 100644 --- a/gdb/testsuite/gdb.base/bg-execution-repeat.c +++ b/gdb/testsuite/gdb.base/bg-execution-repeat.c @@ -37,9 +37,9 @@ main (void) { alarm (60); + do_wait = 1; foo (); - do_wait = 1; wait (); /* do_wait set to 0 externally. */ diff --git a/ld/ldmain.c b/ld/ldmain.c index 91237a4..716272b 100644 --- a/ld/ldmain.c +++ b/ld/ldmain.c @@ -423,8 +423,8 @@ ld_stop_phase (ld_phase phase) if (pd->begin.ru_maxrss < usage.ru_maxrss) pd->use.ru_maxrss += usage.ru_maxrss - pd->begin.ru_maxrss; -#endif } +#endif } static void diff --git a/ld/testsuite/ld-plugin/lto.exp b/ld/testsuite/ld-plugin/lto.exp index 726dd93..3a56fb5 100644 --- a/ld/testsuite/ld-plugin/lto.exp +++ b/ld/testsuite/ld-plugin/lto.exp @@ -1215,24 +1215,24 @@ if { [is_elf_format] && [check_lto_shared_available] } { if { [check_lto_fat_available] } { run_cc_link_tests [list \ [list \ - "Build libpr32846a.a" \ - "$plug_opt" "-O2 -flto $lto_no_fat" \ - {pr32846a.c pr32846b.c} {} "libpr32846a.a" \ + "Build libpr32846a.a" \ + "$plug_opt" "-fPIC -O2 -flto $lto_no_fat" \ + {pr32846a.c pr32846b.c} {} "libpr32846a.a" \ ] \ [list \ "Build libpr32846b.a" \ - "$plug_opt" "-O2 -flto $lto_no_fat" \ + "$plug_opt" "-fPIC -O2 -flto $lto_no_fat" \ {pr32846a.c pr32846b.c pr32846c.c} {} "libpr32846b.a" \ ] \ [list \ - "Build pr32846d.o" \ - "$plug_opt" "-O2 -flto $lto_no_fat" \ - {pr32846d.c} {} \ + "Build pr32846d.o" \ + "$plug_opt" "-fPIC -O2 -flto $lto_no_fat" \ + {pr32846d.c} {} \ ] \ [list \ - "Build pr32846e.o" \ - "$plug_opt" "-O2 -flto $lto_no_fat" \ - {pr32846e.c} {} \ + "Build pr32846e.o" \ + "$plug_opt" "-fPIC -O2 -flto $lto_no_fat" \ + {pr32846e.c} {} \ ] \ [list \ "Build pr32846" \ diff --git a/opcodes/riscv-dis.c b/opcodes/riscv-dis.c index f862ef2..277b8fd 100644 --- a/opcodes/riscv-dis.c +++ b/opcodes/riscv-dis.c @@ -69,7 +69,7 @@ struct riscv_private_data const char (*riscv_fpr_names)[NRC]; /* If set, disassemble as most general instruction. */ bool no_aliases; - /* If set, disassemble without checking architectire string, just like what + /* If set, disassemble without checking architecture string, just like what we did at the beginning. */ bool all_ext; }; @@ -83,6 +83,7 @@ set_default_riscv_dis_options (struct disassemble_info *info) pd->riscv_gpr_names = riscv_gpr_names_abi; pd->riscv_fpr_names = riscv_fpr_names_abi; pd->no_aliases = false; + pd->all_ext = false; } /* Parse RISC-V disassembler option (without arguments). */ @@ -1580,6 +1581,9 @@ static struct riscv_option_arg_t arg; } riscv_options[] = { + { "max", + N_("Disassemble without checking architecture string."), + RISCV_OPTION_ARG_NONE }, { "numeric", N_("Print numeric register names, rather than ABI names."), RISCV_OPTION_ARG_NONE }, |