This is an archive of the discontinued LLVM Phabricator instance.

This patch implements a command to access and manipulate the Intel(R) MPX Boundary Tables.
ClosedPublic

Authored by valentinagiusti on Jan 24 2017, 4:47 AM.

Details

Summary

The Boundary Table Entries are stored in the application memory and allow
to store boundary info for all the pointers of the program, also those that
otherwise wouldn't fit in the 4 bound registers provided by the HW.

Here is an example of how it works:

  • mpx-table show <pointer> lbound = 0x..., ubound = 0x..., (pointer value = 0x..., metadata = 0x...)
  • mpx-table set <pointer>

Signed-off-by: Valentina Giusti <valentina.giusti@intel.com>

Diff Detail

Repository
rL LLVM

Event Timeline

clayborg requested changes to this revision.Jan 24 2017, 9:41 AM

There are a few places where you are reading memory and then wanting to decode data from it. Right now, you first read memory into a local buffer and then we create an SBData and set the data to the bytes. It would be nice to have the ability to read memory and get an SBData back:

class SBProcess
{
  SBData ReadData(lldb::addr_t addr, size_t size, SBError &error);
};

Since the process can fill in the byte order and address byte size it can return an SBData that is ready to use. If you are interested in adding this in this patch, let me know.

tools/intel-mpx/IntelMPXTablePlugin.cpp
35–36 ↗(On Diff #85569)
std:string ptr_str("&");
ptr_str += cptr;
47 ↗(On Diff #85569)

Remove this and use SBData::GetUnsignedInt32(...) or SBData::GetAddress(...).

52 ↗(On Diff #85569)

Remove this and use SBData::GetUnsignedInt64(...) or SBData::GetAddress(...).

143–150 ↗(On Diff #85569)

No need to do manual byte order stuff here, we can use SBData and you don't need the "if (arch == ...)" since SBData knows the address byte size:

SBError error;
SBData data;
data.SetData(error, bd_entry_v.data(), bd_entry_v.size(), target.GetByteOrder(), target.GetAddressByteSize());
lldb::addr_t bd_entry = data.GetAddress(error, 0);
199–218 ↗(On Diff #85569)

Use SBData and you don't need the "if (arch == ...)" since SBData knows the address byte size:

SBError error;
SBData data;
uint32_t addr_size = target.GetAddressByteSize();
data.SetData(error, bt_entry_v.data(), bt_entry_v.size(), target.GetByteOrder(), addr_size);

lldb::addr_t lbound = data.GetAddress(error, 0 * addr_size);
lldb::addr_t ubound  = data.GetAddress(error, 1 * addr_size);
uint64_t value = data.GetAddress(error, 2 * addr_size);
uint64_t meta = data.GetAddress(error, 3 * addr_size);
313–314 ↗(On Diff #85569)

No need to use SBData here, the SBValue can provide what you need. You use SBValue::GetValueAsUnsigned() and specify the invalid value to return as the argument (zero for nullptr):

bndcfgu = bndcfgu_val.GetValueAsUnsigned(0);
354 ↗(On Diff #85569)

No need for the "frame" variable as it is only used within GetInitInfo. Remove this?

359 ↗(On Diff #85569)

I would either extract the target here before passing to any other functions like this one and only pass the target. There is no need to pass both the debugger and the target since you can do "target.GetDebugger()" anytime you need the debugger from the target. You can also remove the "frame" variable from this since it is only used in GetInitInfo().

This revision now requires changes to proceed.Jan 24 2017, 9:41 AM

Noticed another efficiency thing, see inlined comment.

tools/intel-mpx/IntelMPXTablePlugin.cpp
37 ↗(On Diff #85569)

Actually you may not want to make a string like "&my->expr" as you can probably get away with:

lldb::SBValue ptr_addr = frame.GetValueForVariablePath(cptr).GetLoadAddress();

The SBValue::GetLoadAddress() will return the address of the value itself instead of having to conjure up a SBValue for it.

granata.enrico resigned from this revision.Jan 24 2017, 10:15 AM

I don't work on LLDB anymore. Resigning as reviewer. Best of luck with your patch :-)

valentinagiusti marked 2 inline comments as done.Jan 25 2017, 3:07 AM

Hi Greg, thanks a lot for your review. I have a question about the API that you proposed, please have a look at the inline comments.

tools/intel-mpx/IntelMPXTablePlugin.cpp
143–150 ↗(On Diff #85569)

Hi Greg, thanks for the tip, but the code that you proposed doesn't work for i386 for me. GetAddress() fails with the error "unable to read data".
To me it doesn't look like this API is able to handle different arch byte sizes.
In fact, if I leave the "if (arch ==) check and I use GetUnsignedInt32() instead of GetAddress() it works. Is this a bug of GetAddress()?

valentinagiusti marked 3 inline comments as done.Jan 25 2017, 4:42 AM
valentinagiusti added inline comments.
tools/intel-mpx/IntelMPXTablePlugin.cpp
199–218 ↗(On Diff #85569)

same as above.

313–314 ↗(On Diff #85569)

This also doesn't work, it returns the error: "could not resolve value"., which is why I opted for using SBData when I first wrote this code.

359 ↗(On Diff #85569)

I just wanted to avoid repeating the code to initialize the target and have it only inside GetInitInfo.

valentinagiusti edited edge metadata.

Applied some of the proposed changes.

clayborg added inline comments.Jan 25 2017, 11:25 AM
tools/intel-mpx/IntelMPXTablePlugin.cpp
151 ↗(On Diff #85733)

There is indeed a bug in SBData::SetData():

void SBData::SetData(lldb::SBError &error, const void *buf, size_t size,
                     lldb::ByteOrder endian, uint8_t addr_size) {
  if (!m_opaque_sp.get())
    m_opaque_sp.reset(new DataExtractor(buf, size, endian, addr_size));
  else
    m_opaque_sp->SetData(buf, size, endian);

Note that if "m_opaque_sp" already exists, it doesn't set the address byte size.

I will fix this and check it in, then things should work for you.

219 ↗(On Diff #85733)

I'll fix SBData and this should work

315 ↗(On Diff #85733)

The GetValueAsUnsigned() should work. If you look at an x86_64 program:

(lldb) script
>>> r = lldb.frame.FindRegister('rax')
>>> print r
(unsigned long) rax = 0x0000000100000f10
>>> print r.GetValueAsUnsigned(0)
4294971152
>>> hex(4294971152)
'0x100000f10'

Maybe you defined "bndcfgu" the register in a way that makes this not work? This should work and you should step through the code to see why this fails for "bndcfgu". Let me know what you find.

clayborg added inline comments.Jan 25 2017, 11:30 AM
tools/intel-mpx/IntelMPXTablePlugin.cpp
151 ↗(On Diff #85733)

Actually if you can fix this with your patch that might be faster. llvm.org seems to be unreachable for me right now.

Just change the void SBData::SetData(...) function from:

if (!m_opaque_sp.get())
  m_opaque_sp.reset(new DataExtractor(buf, size, endian, addr_size));
else
  m_opaque_sp->SetData(buf, size, endian);

To:

if (!m_opaque_sp.get())
  m_opaque_sp.reset(new DataExtractor(buf, size, endian, addr_size));
else
{
  m_opaque_sp->SetData(buf, size, endian);
  m_opaque_sp->SetAddressByteSize(addr_size);
}

I fixed SBData with:

Sending        packages/Python/lldbsuite/test/python_api/sbdata/TestSBData.py
Sending        source/API/SBData.cpp
Transmitting file data ..done
Committing transaction...
Committed revision 293102.

Let me know why your GetValueAsUnsigned isn't working on your register by stepping through it.

valentinagiusti marked 2 inline comments as done.Jan 26 2017, 7:16 AM
valentinagiusti added inline comments.
tools/intel-mpx/IntelMPXTablePlugin.cpp
219 ↗(On Diff #85733)

Thanks, now it works :)

315 ↗(On Diff #85733)

You are right, bndcfgu is defined as eEncodingVector, whereas rax is eEncodingUint, and this is the reason why this method doesn't work in my case.

GetValueAsUnsigned() executes the following line (source/API/SBValue.cpp:1059):

return value_sp->GetValueAsUnsigned(fail_value);

which uses the operator overloading (defined in include/lldb/Utility/SharingPtr.h:148):

element_type *operator->() const { return ptr_; }

which in its turn simply cannot work with a vector register... So I don't think that this is a bug, it just that this method is probably not intended for this kind of registers.

Is it ok if I just keep my original code or is there a better way to extract data from a vector register?

valentinagiusti marked an inline comment as done.

used GetAddress() instead of GetUnsignedIntXX()

clayborg accepted this revision.Jan 31 2017, 8:49 AM

If we can add a comment around "bndcfgu" where we use an SBData since it is a vector register and SBValue::GetValueAsUnsigned(...) won't work because it is a vector that would be nice for people to know. Other than that this is good to go!

tools/intel-mpx/IntelMPXTablePlugin.cpp
293–294 ↗(On Diff #85906)

Might be nice to comment that we need to use SBData because this is a vector register.

This revision is now accepted and ready to land.Jan 31 2017, 8:49 AM
This revision was automatically updated to reflect the committed changes.

This change is creating a new library usr/lib/llvm-5.0/bin/liblldb-intel-mpxtable.so on GNU/Linux 64b
That sounds pretty specific, is that really something that we want to do?

Do you have a better proposal?

Like llvm or lldb in general, just integrate it into liblldb?

By the way, liblldb-intel-mpxtable.so-5.0 is incorrect should be liblldb-intel-mpxtable.so.5.0

I am not sure what you mean, this is a pluggable command and as such it has to be a dynamic loadable lib.
As for the wrong install name of the binary, I don't think I can fix it from here, the SOVERSION is set by AddLLVM.cmake.
On which platform did you get this issue?