Introduce attribute::signed_constant

This introduces a new method, attribute::signed_constant.  This should
be used wherever DWARF specifies a signed integer constant, or where
this is implied by the context.  It properly handles sign-extension
for DW_FORM_data*.

To my surprise, there doesn't seem to be a pre-existing sign-extension
function.  I've added one to common-utils.h alongside the align
functions.

Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=32680
This commit is contained in:
Tom Tromey
2025-02-24 12:26:36 -07:00
parent 5f90d44355
commit 3d0e5b9992
3 changed files with 49 additions and 0 deletions

View File

@@ -186,6 +186,36 @@ attribute::unsigned_constant () const
/* See attribute.h. */ /* See attribute.h. */
std::optional<LONGEST>
attribute::signed_constant () const
{
if (form_is_strictly_signed ())
return u.snd;
switch (form)
{
case DW_FORM_data8:
case DW_FORM_udata:
/* Not sure if DW_FORM_udata should be handled or not. Anyway
for DW_FORM_data8, there's no need to sign-extend. */
return u.snd;
case DW_FORM_data1:
return sign_extend (u.unsnd, 8);
case DW_FORM_data2:
return sign_extend (u.unsnd, 16);
case DW_FORM_data4:
return sign_extend (u.unsnd, 32);
}
/* For DW_FORM_data16 see attribute::form_is_constant. */
complaint (_("Attribute value is not a constant (%s)"),
dwarf_form_name (form));
return {};
}
/* See attribute.h. */
bool bool
attribute::form_is_unsigned () const attribute::form_is_unsigned () const
{ {

View File

@@ -114,6 +114,15 @@ struct attribute
returned. */ returned. */
std::optional<ULONGEST> unsigned_constant () const; std::optional<ULONGEST> unsigned_constant () const;
/* Return a signed constant value. This only handles constant forms
(i.e., form_is_constant -- and not the extended list of
"unsigned" forms) and assumes a signed value is desired. This
function will sign-extend DW_FORM_data* values.
If non-constant form is used, then complaint is issued and an
empty value is returned. */
std::optional<LONGEST> signed_constant () const;
/* Return non-zero if ATTR's value falls in the 'constant' class, or /* Return non-zero if ATTR's value falls in the 'constant' class, or
zero otherwise. When this function returns true, you can apply zero otherwise. When this function returns true, you can apply
the constant_value method to it. the constant_value method to it.

View File

@@ -196,6 +196,16 @@ in_inclusive_range (T value, T low, T high)
extern ULONGEST align_up (ULONGEST v, int n); extern ULONGEST align_up (ULONGEST v, int n);
extern ULONGEST align_down (ULONGEST v, int n); extern ULONGEST align_down (ULONGEST v, int n);
/* Sign-extend the value V, using N as the number of valid bits. That
is, bit N-1 is the sign bit. The higher-order bits (those outside
0..N-1) must be zero. */
static inline ULONGEST
sign_extend (ULONGEST v, int n)
{
ULONGEST mask = (ULONGEST) 1 << (n - 1);
return (v ^ mask) - mask;
}
/* Convert hex digit A to a number, or throw an exception. */ /* Convert hex digit A to a number, or throw an exception. */
extern int fromhex (int a); extern int fromhex (int a);