showing CPU register flags

Hi everyone,

I am currently implementing the support for the Intel MPX registers in LLDB. This register set includes 2 registers, BNDSTATUS and BNDCFGU, which store information about the status and configuration of the MPX feature in several fields.
I think that it would be useful for the user to have a nice display of such fields, so that they don't have to extract the information from the raw values of the registers. However, I see that the other registers are just displayed as raw values, without any better ways to explore their contents.

Should I just follow this approach, and also just let the MPX registers be available through their raw values?
Or have there ever been any requests for ways to display the register flags from LLDB?

Thanks,
- Valentina Giusti

Intel Deutschland GmbH
Registered Address: Am Campeon 10-12, 85579 Neubiberg, Germany
Tel: +49 89 99 8853-0, www.intel.de
Managing Directors: Christin Eisenschmid, Christian Lamprechter
Chairperson of the Supervisory Board: Nicole Lau
Registered Office: Munich
Commercial Register: Amtsgericht Muenchen HRB 186928

We've talked about providing a more natural view of registers that are logically made of subfields, as you describe, but I don't think any work has been done on that front.

The ValueObjectRegister has a couple of ways to implement this display. The ValueObjectRegisters can be given a type, and then will display the subfields as though they were of that type. So you could cons up synthetic types for your registers, and use that to display them. The other way would be to use the synthetic child mechanism for ValueObjects in general, would be pretty amenable to this sort of re-presentation. Another slightly tricky bit would be that if you showed a register as having "sub-fields" folks would probably assume they could use these for "register write" as well are "register read". I don't think the synthetic children can be used to change values of the ValueObject that produced them. But if you gave them a synthetic type instead, that might just fall out.

The other concern is that the "register read" command uses a lower level interface (RegisterValues) rather than using ValueObjectRegister's. The RegisterValues really want to be scalars, so they don't provide a natural way to do this. You would probably have to convert "register read" over to use the ValueObject for this project to be worth doing.

Jim

We haven't done anything fancy for registers yet. I see a few ways to do this:

1 - allow register values to specify a CompilerType as the way to display the register. Right now registers always default to use simple built in types:

CompilerType
ValueObjectRegister::GetCompilerTypeImpl ()
{
    if (!m_compiler_type.IsValid())
    {
        ExecutionContext exe_ctx (GetExecutionContextRef());
        Target *target = exe_ctx.GetTargetPtr();
        if (target)
        {
            Module *exe_module = target->GetExecutableModulePointer();
            if (exe_module)
            {
                TypeSystem *type_system = exe_module->GetTypeSystemForLanguage (eLanguageTypeC);
                if (type_system)
                    m_compiler_type = type_system->GetBuiltinTypeForEncodingAndBitSize (m_reg_info.encoding,
                                                                                     m_reg_info.byte_size * 8);
            }
        }
    }
    return m_compiler_type;
}

so we currently take the encoding and byte size and make a built in type for it. We could allow a RegisterContext to manually create types using for a given target.

We might allow RegisterInfo structs to have an extra field that is expression text that defines a register type something like:

const char *my_register_type = "typedef enum EnumType { eValueA, eValueB, eValueC}; struct reg_type { uint8_t a : 7, b:2, c:2; EnumType enum; }"

Then we could use the top level expression parser to parse the expression and extract the "reg_type" as a CompilerType from the source code. Then you could define any type you want for your register. Sean Callanan will be able to help with expression parser details if this sounds like something you would like to do. I can help with the rest of the plumbing.

Greg Clayton

Thanks for your replies!

@Greg, I think I will start by trying your approach and then I will get back to you with some feedback in a couple of days.

Cheers,
- Valentina

> I am currently implementing the support for the Intel MPX registers in LLDB.
This register set includes 2 registers, BNDSTATUS and BNDCFGU, which store
information about the status and configuration of the MPX feature in several
fields.
> I think that it would be useful for the user to have a nice display of such fields,
so that they don't have to extract the information from the raw values of the
registers. However, I see that the other registers are just displayed as raw
values, without any better ways to explore their contents.
>
> Should I just follow this approach, and also just let the MPX registers be
available through their raw values?
> Or have there ever been any requests for ways to display the register flags
from LLDB?

We haven't done anything fancy for registers yet. I see a few ways to do this:

1 - allow register values to specify a CompilerType as the way to display the
register. Right now registers always default to use simple built in types:

CompilerType
ValueObjectRegister::GetCompilerTypeImpl () {
    if (!m_compiler_type.IsValid())
    {
        ExecutionContext exe_ctx (GetExecutionContextRef());
        Target *target = exe_ctx.GetTargetPtr();
        if (target)
        {
            Module *exe_module = target->GetExecutableModulePointer();
            if (exe_module)
            {
                TypeSystem *type_system = exe_module->GetTypeSystemForLanguage
(eLanguageTypeC);
                if (type_system)
                    m_compiler_type = type_system-
>GetBuiltinTypeForEncodingAndBitSize (m_reg_info.encoding,
                                                                                     m_reg_info.byte_size * 8);
            }
        }
    }
    return m_compiler_type;
}

so we currently take the encoding and byte size and make a built in type for it.
We could allow a RegisterContext to manually create types using for a given
target.

We might allow RegisterInfo structs to have an extra field that is expression text
that defines a register type something like:

const char *my_register_type = "typedef enum EnumType { eValueA, eValueB,
eValueC}; struct reg_type { uint8_t a : 7, b:2, c:2; EnumType enum; }"

Then we could use the top level expression parser to parse the expression and
extract the "reg_type" as a CompilerType from the source code. Then you could
define any type you want for your register. Sean Callanan will be able to help
with expression parser details if this sounds like something you would like to do.
I can help with the rest of the plumbing.

Greg Clayton

Intel Deutschland GmbH
Registered Address: Am Campeon 10-12, 85579 Neubiberg, Germany
Tel: +49 89 99 8853-0, www.intel.de
Managing Directors: Christin Eisenschmid, Christian Lamprechter
Chairperson of the Supervisory Board: Nicole Lau
Registered Office: Munich
Commercial Register: Amtsgericht Muenchen HRB 186928