mirror of
https://github.com/bminor/binutils-gdb.git
synced 2025-11-16 12:34:43 +00:00
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:
@@ -186,6 +186,36 @@ attribute::unsigned_constant () const
|
||||
|
||||
/* 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
|
||||
attribute::form_is_unsigned () const
|
||||
{
|
||||
|
||||
@@ -114,6 +114,15 @@ struct attribute
|
||||
returned. */
|
||||
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
|
||||
zero otherwise. When this function returns true, you can apply
|
||||
the constant_value method to it.
|
||||
|
||||
@@ -196,6 +196,16 @@ in_inclusive_range (T value, T low, T high)
|
||||
extern ULONGEST align_up (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. */
|
||||
extern int fromhex (int a);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user