aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bfd/version.h2
-rw-r--r--binutils/doc/binutils.texi8
-rw-r--r--binutils/resbin.c439
-rw-r--r--binutils/rescoff.c216
-rw-r--r--binutils/resrc.c9
-rw-r--r--binutils/resres.c42
-rw-r--r--binutils/windres.c30
-rw-r--r--binutils/windres.h6
-rw-r--r--gdb/ada-lang.c4
-rw-r--r--gdb/dwarf2/read.c31
-rw-r--r--gdb/testsuite/gdb.ada/scalar_storage.exp28
-rw-r--r--gdb/testsuite/gdb.arch/aarch64-sve-sigunwind.c205
-rw-r--r--gdb/testsuite/gdb.arch/aarch64-sve-sigunwind.exp106
-rw-r--r--ld/ldmain.c2
-rw-r--r--ld/testsuite/ld-plugin/lto.exp20
-rw-r--r--opcodes/riscv-dis.c6
16 files changed, 940 insertions, 214 deletions
diff --git a/bfd/version.h b/bfd/version.h
index cd21a82..532112c 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 20250415
#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..1698e14 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,7 +132,10 @@ 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;
@@ -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;
}
}
@@ -204,7 +215,10 @@ 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->xhotspot = windres_get_16 (wrbfd, data, 2);
@@ -235,32 +249,51 @@ bin_to_res_menu (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type length)
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;
}
@@ -285,7 +318,10 @@ 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->state = 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;
@@ -324,6 +367,8 @@ bin_to_res_menuitems (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type len
mi->id = 0;
mi->popup = bin_to_res_menuitems (wrbfd, data + itemlen, length - itemlen,
&subread);
+ if (mi->popup == NULL)
+ return NULL;
itemlen += subread;
}
@@ -362,7 +407,10 @@ 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->type = windres_get_32 (wrbfd, data, 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,12 +481,16 @@ 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));
@@ -447,7 +508,10 @@ 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->help = windres_get_32 (wrbfd, data + 4, 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;
}
@@ -526,7 +607,10 @@ bin_to_res_dialog (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type length
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,7 +672,10 @@ 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)));
@@ -615,7 +715,10 @@ bin_to_res_string (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type length
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,7 +728,10 @@ 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));
st->strings[i].string = s;
@@ -655,7 +761,10 @@ bin_to_res_fontdir (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type lengt
rc_res_resource *r;
if (length < 2)
- toosmall (_("fontdir header"));
+ {
+ toosmall (_("fontdir header"));
+ return NULL;
+ }
c = windres_get_16 (wrbfd, data, 2);
@@ -669,7 +778,10 @@ 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);
@@ -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;
@@ -732,7 +850,10 @@ 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));
@@ -791,11 +912,17 @@ bin_to_res_group_cursor (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type
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,7 +937,10 @@ 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);
@@ -846,11 +976,17 @@ bin_to_res_group_icon (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type le
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,7 +1001,10 @@ 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));
@@ -897,14 +1036,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
+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 +1062,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 +1071,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,6 +1093,7 @@ 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. */
@@ -956,16 +1107,23 @@ 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. */
length = verlen;
@@ -980,18 +1138,31 @@ 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));
@@ -1020,7 +1191,10 @@ 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));
@@ -1032,12 +1206,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,15 +1233,24 @@ 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));
- 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;
@@ -1079,30 +1267,42 @@ bin_to_res_version (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type lengt
rc_uint_type sverlen, vslen, valoff;
if (length < 8)
- toosmall (_("version string"));
+ {
+ toosmall (_("version string"));
+ return NULL;
+ }
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);
+ 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)
- fatal (_("unexpected version string length %ld != %ld + %ld"),
- (long) sverlen, (long) off, (long) valoff);
+ {
+ non_fatal (_("unexpected version string length %ld != %ld + %ld"),
+ (long) sverlen, (long) off, (long) valoff);
+ return NULL;
+ }
data += valoff;
length -= valoff;
if (stverlen < sverlen)
- fatal (_("unexpected version string length %ld < %ld"),
- (long) verlen, (long) sverlen);
+ {
+ non_fatal (_("unexpected version string length %ld < %ld"),
+ (long) verlen, (long) sverlen);
+ return NULL;
+ }
stverlen -= sverlen;
verlen -= sverlen;
@@ -1122,18 +1322,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,7 +1353,10 @@ 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));
@@ -1161,7 +1371,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,10 +1385,14 @@ 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;
@@ -1216,12 +1434,18 @@ 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;
+ if (length < 12)
+ {
+ toosmall (_("toolbar"));
+ return NULL;
+ }
ri = (rc_toolbar *) res_alloc (sizeof (rc_toolbar));
ri->button_width = windres_get_32 (wrbfd, data, 4);
ri->button_height = windres_get_32 (wrbfd, data + 4, 4);
@@ -1229,14 +1453,18 @@ bin_to_res_toolbar (windres_bfd *wrbfd, const bfd_byte *data)
ri->items = NULL;
data += 12;
- for (i=0 ; i < ri->nitems; i++)
+ length -= 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;
+ if (length < 4)
+ toosmall (_("toolbar item"));
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)
@@ -1740,11 +1968,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);
@@ -1855,22 +2084,22 @@ 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++)
+ 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;
@@ -1902,10 +2131,10 @@ res_to_bin_stringtable (windres_bfd *wrbfd, rc_uint_type off,
hp = (bfd_byte *) 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;
diff --git a/binutils/rescoff.c b/binutils/rescoff.c
index f9a1e70..98e5eb0 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,16 @@ 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"));
+ {
+ overrun (flaginfo, _("directory"));
+ return NULL;
+ }
erd = (const struct extern_res_directory *) data;
@@ -230,7 +250,10 @@ read_coff_res_dir (windres_bfd *wrbfd, const bfd_byte *data,
int length, j;
if ((const bfd_byte *) ere >= flaginfo->data_end)
- overrun (flaginfo, _("named directory entry"));
+ {
+ overrun (flaginfo, _("named directory entry"));
+ return NULL;
+ }
name = windres_get_32 (wrbfd, ere->name, 4);
rva = windres_get_32 (wrbfd, ere->rva, 4);
@@ -239,7 +262,10 @@ read_coff_res_dir (windres_bfd *wrbfd, const bfd_byte *data,
name &=~ 0x80000000;
if (name > (rc_uint_type) (flaginfo->data_end - flaginfo->data))
- overrun (flaginfo, _("directory entry name"));
+ {
+ overrun (flaginfo, _("directory entry name"));
+ return NULL;
+ }
ers = flaginfo->data + name;
@@ -252,8 +278,12 @@ read_coff_res_dir (windres_bfd *wrbfd, const bfd_byte *data,
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"));
+ if (length < 0 || ers >= flaginfo->data_end
+ || ers + j * 2 + 4 >= flaginfo->data_end)
+ {
+ overrun (flaginfo, _("resource name"));
+ return NULL;
+ }
re->id.u.n.name[j] = windres_get_16 (wrbfd, ers + j * 2 + 2, 2);
}
@@ -264,7 +294,10 @@ read_coff_res_dir (windres_bfd *wrbfd, const bfd_byte *data,
{
rva &=~ 0x80000000;
if (rva >= (rc_uint_type) (flaginfo->data_end - flaginfo->data))
- overrun (flaginfo, _("named subdirectory"));
+ {
+ overrun (flaginfo, _("named subdirectory"));
+ return NULL;
+ }
re->subdir = 1;
re->u.dir = read_coff_res_dir (wrbfd, flaginfo->data + rva, flaginfo, type,
level + 1);
@@ -272,7 +305,10 @@ read_coff_res_dir (windres_bfd *wrbfd, const bfd_byte *data,
else
{
if (rva >= (rc_uint_type) (flaginfo->data_end - flaginfo->data))
- overrun (flaginfo, _("named resource"));
+ {
+ overrun (flaginfo, _("named resource"));
+ return NULL;
+ }
re->subdir = 0;
re->u.res = read_coff_data_entry (wrbfd, flaginfo->data + rva, flaginfo, type);
}
@@ -287,7 +323,10 @@ read_coff_res_dir (windres_bfd *wrbfd, const bfd_byte *data,
rc_res_entry *re;
if ((const bfd_byte *) ere >= flaginfo->data_end)
- overrun (flaginfo, _("ID directory entry"));
+ {
+ overrun (flaginfo, _("ID directory entry"));
+ return NULL;
+ }
name = windres_get_32 (wrbfd, ere->name, 4);
rva = windres_get_32 (wrbfd, ere->rva, 4);
@@ -304,7 +343,10 @@ read_coff_res_dir (windres_bfd *wrbfd, const bfd_byte *data,
{
rva &=~ 0x80000000;
if (rva >= (rc_uint_type) (flaginfo->data_end - flaginfo->data))
- overrun (flaginfo, _("ID subdirectory"));
+ {
+ overrun (flaginfo, _("ID subdirectory"));
+ return NULL;
+ }
re->subdir = 1;
re->u.dir = read_coff_res_dir (wrbfd, flaginfo->data + rva, flaginfo, type,
level + 1);
@@ -312,7 +354,10 @@ read_coff_res_dir (windres_bfd *wrbfd, const bfd_byte *data,
else
{
if (rva >= (rc_uint_type) (flaginfo->data_end - flaginfo->data))
- overrun (flaginfo, _("ID resource"));
+ {
+ overrun (flaginfo, _("ID resource"));
+ return NULL;
+ }
re->subdir = 0;
re->u.res = read_coff_data_entry (wrbfd, flaginfo->data + rva, flaginfo, type);
}
@@ -337,10 +382,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 +399,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 +481,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 +494,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 +507,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 +621,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 +647,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 +658,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 +676,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 +745,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 +806,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 +843,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 +866,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 +883,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..38c7974 100644
--- a/gdb/ada-lang.c
+++ b/gdb/ada-lang.c
@@ -3950,9 +3950,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 ())
{
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 &section : type_sections)
- create_debug_type_hash_table (per_objfile, dwo_file, &section,
+ create_dwo_debug_type_hash_table (per_objfile, dwo_file, &section,
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/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 },