This is an archive of the discontinued LLVM Phabricator instance.

[lldb][AArch64] Refactor memory tag range handling
ClosedPublic

Authored by DavidSpickett on Jul 8 2021, 7:06 AM.

Details

Summary

Previously GetMemoryTagManager checked many things in one:

  • architecture supports memory tagging
  • process supports memory tagging
  • memory range isn't inverted
  • memory range is all tagged

Since writing follow up patches for tag writing (in review
at the moment) it has become clear that this gets unwieldy
once we add the features needed for that.

It also implies that the memory tag manager is tied to the
range you used to request it with but it is not. It's a per
process object.

Instead:

  • GetMemoryTagManager just checks architecture and process.
  • Then the MemoryTagManager can later be asked to check a memory range.

This is better because:

  • We don't imply that range and manager are tied together.
  • A slightly diferent range calculation for tag writing doesn't add more code to Process.
  • Range checking code can now be unit tested.

Diff Detail

Event Timeline

DavidSpickett created this revision.Jul 8 2021, 7:06 AM
DavidSpickett requested review of this revision.Jul 8 2021, 7:06 AM
Herald added a project: Restricted Project. · View Herald TranscriptJul 8 2021, 7:06 AM

This is a response to feedback on https://reviews.llvm.org/D105181 but would be intended to come before any of the changes in that series if it looks good.

I'm yet to refactor the tag writing changes on to this, wanted to get some feedback first. Roughly tag writing would instead of adding GetMemoryTagManagerForGranules to process, it would add MakeTaggedRangeForGranules to the tag manager. Then the memory tag write command calls that instead of relying on GetMemoryTagManager to implement that logic.

Then Process simply has GetMemoryTagManager, ReadMemoryTags and WriteMemoryTags. Instead of growing all these variants of GetMemoryTagManager.

Side note: I actually found a bug when writing the unit tests, so I think that's a big plus to this approach.

Similarly, I have a patch locally that has a "best effort" read where it returns a sparse set of results (for annotating memory reads). For that there would be a MakeTaggedRange<...> that returns a list of ranges that you can then read in a loop.

I think this approach is a lot better given that the process of tagged ranged calculation deserved a separation and may be more explanation too. I guess somewhere in the comments of same function you can explain interaction between memory regions and tagged ranges. It will become a bit more complicated for a reader who have no knowledge about memory tag range and disjoint region.

lldb/include/lldb/Target/MemoryTagManager.h
66

I couldnt understand this point in comment "have an untagged base address"

lldb/source/Commands/CommandObjectMemoryTag.cpp
70

If we also pull out the SupportsMemoryTagging out of GetMemoryTagManager we can directly return a tag manager pointer here.

Also SupportsMemoryTagging may also run once for the life time of a process? We can store this information is a flag or something.

71

should we process pointer validity check before this call?

Update various comments.

It will become a bit more complicated for a reader who have no knowledge about memory tag range and disjoint region.

I've added/updated some of the comments in MakeTaggedRange. Maybe you can highlight any bits that aren't clear and I'll make sure they get comments too.

lldb/include/lldb/Target/MemoryTagManager.h
66

This is noted for 2 reasons:

  • Callers don't need to remove tags before displaying the range (memory tag read).
  • There's potentially 2 different tags, begin/end, so removing them is the easiest way to make (or rather not make) that choice.

You could keep the base tagged the same as addr but the code works out simpler if you don't and all it means is that memory tag read has to remove the tags itself. If it turns out that most callers want it tagged then sure I'll change the behaviour.

lldb/source/Commands/CommandObjectMemoryTag.cpp
70

If we also pull out the SupportsMemoryTagging out of GetMemoryTagManager we can directly return a tag manager pointer here.

Sure, that way GetMemoryTagManager does exactly what it says on the tin. I can just make a utility function in CommandObjectMemoryTag.cpp to reduce the duplication of checking both, when adding the write command.

Will do that in the next update.

Also SupportsMemoryTagging may also run once for the life time of a process? We can store this information is a flag or something.

It already is in that for the GDB remote it'll only send a qSupported the first time it (or any other property) is asked for. So we go through a few function calls but that's it.

71

Covered by eCommandRequiresProcess in the constructor.

DavidSpickett added inline comments.Jul 9 2021, 6:15 AM
lldb/source/Commands/CommandObjectMemoryTag.cpp
70

On second thought I'd rather leave GetMemoryTagManager as it is.

If we split the checks up we'll have the same 2 checks repeated in:

  • memory tag read, memory tag write (same file so you could make a helper function)
  • Process::ReadMemoryTags, Process::WriteMemoryTags (again you could make a helper but...)

That helper would be what GetMemoryTagManager is now. Leaving it as is saves duplicating it.

I thought of simply only checking SupportsMemoryTagging in Process::ReadMemoryTags. Problem with that is that you would never get this error if your remote wasn't able to show you MTE memory region flags. And you'd hope the most obvious checks would come first.

The other reason to split the 2 checks is so GetMemoryTagManager could be called from the API to get a manager even if the remote didn't support MTE. Which seems like a very niche use case, perhaps you've got some very old remote but are somehow running an MTE enabled program on it? Seems unlikely.

If we find a use case later when I work on the API then it'll be easy to switch it around anyway.

Correct // to /// in comment block for ReadMemoryTags.

Is this final version or you are still doing refactoring. Also can you kindly order its child and parent revs in current tag-write patch series.

lldb/source/Commands/CommandObjectMemoryTag.cpp
70

Agreed no strong reason to further split GetMemoryTagManager. API use-case may never be utilized and we can always come back and refactor if need arises.

Is this final version or you are still doing refactoring. Also can you kindly order its child and parent revs in current tag-write patch series.

I'm currently rebasing all the active patches onto this one, I don't expect to change this but I might have to I'll see. Then I'll update it all into one series with the correct relations and you can give a final approval for this.

All the follow ups are now based on this change. I didn't need to make an updates to this particular patch after all.

All the follow ups are now based on this change. I didn't need to make an updates to this particular patch after all.

This looks good but the test fails on arm 32 bit.

lldb/source/Plugins/Process/Utility/MemoryTagManagerAArch64MTE.cpp
114

less than?

This looks good but the test fails on arm 32 bit.

I had a few of those last time, I will build the whole series on 32 bit to check for more.

Rebase and correct printf formatting to fix 32 bit test issues.

Update comment about save/restoring end of range.

DavidSpickett marked an inline comment as done.Jul 15 2021, 8:21 AM
omjavaid accepted this revision.Jul 15 2021, 9:55 PM
This revision is now accepted and ready to land.Jul 15 2021, 9:55 PM
This revision was landed with ongoing or failed builds.Jul 16 2021, 3:02 AM
This revision was automatically updated to reflect the committed changes.