<div dir="ltr"><div dir="ltr"><br></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Mon, Aug 10, 2020 at 3:41 AM David Spickett via lldb-dev <<a href="mailto:lldb-dev@lists.llvm.org">lldb-dev@lists.llvm.org</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">Hi all,<br>
<br>
What follows is my proposal for supporting AArch64's memory tagging<br>
extension in LLDB. I think the link in the first paragraph is a good<br>
introduction if you haven't come across memory tagging before.<br>
<br>
I've also put the document in a Google Doc if that's easier for you to<br>
read: <a href="https://docs.google.com/document/d/13oRtTujCrWOS_2RSciYoaBPNPgxIvTF2qyOfhhUTj1U/edit?usp=sharing" rel="noreferrer" target="_blank">https://docs.google.com/document/d/13oRtTujCrWOS_2RSciYoaBPNPgxIvTF2qyOfhhUTj1U/edit?usp=sharing</a><br>
(please keep comments to this list though)<br>
<br>
Any and all comments welcome. Particularly I would like opinions on<br>
the naming of the commands, as this extension is AArch64 specific but<br>
the concept of memory tagging itself is not.<br>
(I've added some people on Cc who might have particular interest)<br>
<br>
Thanks,<br>
David Spickett.<br>
<br>
<begin doc><br>
<br>
# RFC: AArch64 Linux Memory Tagging Support for LLDB<br>
<br>
## What is memory tagging?<br>
<br>
Memory tagging is an extension added in the Armv8.5-a architecture for AArch64.<br>
It allows tagging pointers and storing those tags so that hardware can validate<br>
that a pointer matches the memory address it is trying to access. These paired<br>
tags are stored in the upper bits of the pointer (the “logical” tag) and in<br>
special memory in hardware (the “allocation” tag). Each tag is 4 bits in size.<br>
<br>
<a href="https://community.arm.com/developer/ip-products/processors/b/processors-ip-blog/posts/enhancing-memory-safety" rel="noreferrer" target="_blank">https://community.arm.com/developer/ip-products/processors/b/processors-ip-blog/posts/enhancing-memory-safety</a><br>
<br>
## Definitions<br>
<br>
* memtag - This is the clang name for the extension as in<br>
“-march=armv8.5-a+memtag”<br>
* mte - An alternative name for mmtag, also the llvm backend name for<br>
the extension.<br>
  This document may use memtag/memory tagging/MTE at times, they mean<br>
the same thing.<br>
* logical tag - The tag stored inside a pointer variable (accessible<br>
via normal shift and mask)<br>
* allocation tag - The tag stored in tag memory (which the hardware provides)<br>
  for a particular tag granule<br>
* tag granule - The amount of memory that a single tag applies to,<br>
which is 16 bytes.<br>
<br>
## Existing Tool Support<br>
<br>
* GCC/Clang can generate MTE instructions<br>
* Clang has an option to memory tag the stack (discussed later)<br>
* QEMU support has been merged<br>
* Linux Kernel patches are in progress<br>
  (git://<a href="http://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux" rel="noreferrer" target="_blank">git.kernel.org/pub/scm/linux/kernel/git/arm64/linux</a><br>
“devel/mte-v5” branch)<br>
* GDB support is in review and this design takes a lot of direction from that<br>
  (<a href="https://sourceware.org/git/?p=binutils-gdb.git;a=shortlog;h=refs/heads/users/luisgpm/aarch64-mte-v2" rel="noreferrer" target="_blank">https://sourceware.org/git/?p=binutils-gdb.git;a=shortlog;h=refs/heads/users/luisgpm/aarch64-mte-v2</a>)<br>
  (originally proposed<br>
<a href="https://sourceware.org/pipermail/gdb-patches/2019-August/159881.html" rel="noreferrer" target="_blank">https://sourceware.org/pipermail/gdb-patches/2019-August/159881.html</a>)<br>
<br>
## New lldb features<br>
<br>
Assuming your software is acting correctly, memory tagging can “just work”<br>
without debugger support. This assumes the compiler/toolchain/user are<br>
always correct.<br>
<br>
For when that isn’t the case we want to be able to:<br>
* Read/write the logical tags in a pointer<br>
* Read/write the allocation tags assigned to a given area of memory<br>
* Test whether the logical tag in a pointer matches the allocation tag of the<br>
  memory it refers to<br>
* Read/write memory even when tags are mismatched<br>
<br>
The most obvious use case for this is working through issues where bugs in the<br>
toolchain don’t generate correct code. On the other hand there’s a good case for<br>
deliberately messing with pointers in your code to prove that such protection<br>
actually works.<br>
<br>
Note: potential extensions to scripting such as tags as attributes of values and<br>
such are not being proposed here. Of course the new commands will be<br>
added in the<br>
standard ways so you can use those.<br>
<br>
## New Commands<br>
<br>
### Command Availability<br>
<br>
Note: commands will be listed in tab completion and help regardless of<br>
these checks<br>
<br>
* The remote server must support memory tagging packets. lldb will send/check<br>
  for the “memory-tagging” feature in the qSupported packet. (this<br>
name aligns with gdb)<br>
* The process must have MTE available. We check HWCAP2_MTE for this.<br>
* The process must have enabled tagged addressing using prctl<br>
  (see “New Registers” for details)<br>
* The address given must be in a range that has MTE enabled, since you can mmap<br>
  with or without MTE. (this information is in /proc/.../smaps)<br>
<br>
#### Interaction With Clang’s Stack Tagging<br>
<br>
We’re relying on the kernel to tell us if MTE is enabled, so stack tagging will<br>
not be visible to the debugger this way.<br>
(<a href="https://github.com/google/sanitizers/wiki/Stack-instrumentation-with-ARM-Memory-Tagging-Extension-(MTE)" rel="noreferrer" target="_blank">https://github.com/google/sanitizers/wiki/Stack-instrumentation-with-ARM-Memory-Tagging-Extension-(MTE)</a>)<br>
<br>
E.g. {int x; use(&x); } where x is void x(int* ptr);<br>
“ptr” will have a memory tag but the kernel won’t know this.<br>
<br>
To work around this a setting will be added to tell lldb to assume that MTE is<br>
enabled, so that you can at least see the logical tags of a pointer.<br>
(see “New Settings”)<br>
<br>
### General Properties/Errors<br>
<br>
* <address expression> must resolve to some value that can be handled as an<br>
  address by lldb. (though it need not be a pointer specifically)<br>
* Tags will be printed in hexadecimal to reflect the fact that they are a 4 bit<br>
  field. (and since tags are randomly generated, ordering is unlikely<br>
to be a concern)<br>
* Packed tags will be 1 tag per byte (matches what ptrace expects)<br>
* Addresses will be rounded down to the nearest granule (not always by lldb<br>
  itself but what the user sees will look like this)<br>
* Ranges are rounded up to a whole number of granules<br>
* It is an error to use a command on an address that does not have MTE enabled.<br>
  (with the exception of “mtag check”)<br>
<br>
### Commands<br>
<br>
#### Avoiding Architecture Specific Naming<br>
<br>
One problem you might see with the commands below is that they use l/a for<br>
logical/allocation tags. These names are specific to MTE, for instance SPARC’s<br>
ADI talks about “versions” instead. This limits the reuse of these<br>
commands in the future.<br>
(<a href="https://sourceware.org/gdb/current/onlinedocs/gdb/Sparc64.html#ADI-Support" rel="noreferrer" target="_blank">https://sourceware.org/gdb/current/onlinedocs/gdb/Sparc64.html#ADI-Support</a>)<br>
<br>
Instead we could first put them under “memory”, then merge the a/l tag commands<br>
into “memory showtag” and “memory settag” (check -> checktag,<br>
getconfig -> tagconfig).<br>
Which avoids the arch specific names, though the output will still be.<br>
<br>
(lldb) memory showtag <addr> <length in bytes><br>
<addr>: logical 0x1 allocation: 0x1 0x2 0x3 ...<br>
(lldb) memory settag <addr> <logical tag> <length in bytes> <allocation tags...><br>
<br>
Length and allocation tags would be optional. We could assume that if<br>
we only get<br>
the logical tag arg, we should set both kinds of tag. This accommodates future<br>
systems where there is only one type of tag, or you can only set them<br>
all at once.<br>
<br>
Whatever way you do it, there’s some kind of Arch dependent behaviour.<br>
<br>
Another option would be to call them the “pointer tag” and the “memory tag”.<br>
(which lends itself to being “memory tag/ptag” not “mtag mtag/ptag”<br>
which is just confusing)<br>
<br>
(lldb) memory showptrtag <addr><br>
(lldb) memory showtag <addr> <length><br>
(lldb) memory checktag <addr><br>
<br>
This makes the most sense to me and avoids having variable numbers of arguments<br>
to commands.<br>
<br>
#### mtag showltag <address expression><br>
<br>
Show the logical tag contained in the address given.<br>
<br>
(lldb) mtag showltag a_ptr<br>
0xF<br>
<br>
Error conditions:<br>
* As described above<br>
<br>
#### mtag setltag <address expression> <tag value expression><br>
<br>
Set the logical tag of the variable that <address expression> resolves to, to<br>
the value <tag value expression> resolves to.<br>
<br>
(lldb) mtag setltag a_ptr 0xE<br>
<br>
Error conditions:<br>
* Address variable is not writable, e.g ptr+10 we can set a new tag but have<br>
  nowhere to write it back to.<br>
* Tag value is out of 0x0 to 0xF range. (this limit is specific to AArch64)<br>
<br>
#### mtag showatag <address expression> <optional length><br>
<br>
Show the allocation tag(s) associated with the granule of memory that<br>
<address expression> points to. (this is reading target memory so the work will<br>
be done in lldb-server)<br>
<br>
<length> will default to 1 granule, otherwise you can provide a value in bytes<br>
which will be rounded up to a whole number of granules. E.g 28 bytes becomes 32<br>
bytes which is two granules so two tags.<br>
(note that length of 0 also becomes 1 granule)<br>
<br>
(lldb) mtag showatag a_ptr<br>
[0xfffff7ffa000, 0xfffff7ffa010) : 0xE<br>
0xE<br>
(lldb) mtag showatag a_ptr 28<br>
[0xfffff7ffa000, 0xfffff7ffa010) : 0xE<br>
[0xfffff7ffa010, 0xfffff7ffa020) : 0xF<br>
<br>
Error conditions:<br>
* General failure to read tag memory on the target (a ptrace failure)<br>
* Failure to read tags because MTE is not enabled<br>
* Given <length> is less than zero<br>
<br>
#### mtag setatag <address expression> <length> <tags...><br>
<br>
Set the allocation tags of the memory in range <address expression> to<br>
<address expression> + <length> (where length is rounded up to a whole number of<br>
granules, meaning length <16 = 1 granule) to the tags in <tags>.<br>
<br>
Where <tags…> is one or more tag arguments either in hex or decimal. Once these<br>
are validated they will be each packed with 1 byte per tag in the data<br>
sent to lldb-server.<br>
<br>
Note: this is a break from the current gdb design that has the user type the raw<br>
bytes. For example:<br>
(gdb) mtag setatag a_ptr 32 040F<br>
<br>
This does make the command more flexible as validation is done server side but<br>
we’re doing some validation client side for logical tags anyway. The<br>
question is,<br>
is this added convenience enough to break with gdb?<br>
(though if we go with the alternate “memory …” naming scheme proposed<br>
above, we might as well)<br>
<br>
In the example below we’re giving granule 1 at a_ptr a tag of 0x4 and granule 2<br>
at a_ptr+16 a tag of 0xF. The second example sets the tag of the<br>
granule at a_ptr to 0x5.<br>
<br>
(lldb) mtag setatag a_ptr 32 0x4 15<br>
(lldb) mtag setatag a_ptr 1 5<br>
<br>
In the case that the number of tags given is not enough to cover the<br>
memory range,<br>
lldb-server will keep repeating the set until it does. Meaning a set of 2 tags<br>
would be repeated once to cover 4 granules. A set of 3 tags would be<br>
written once<br>
with the first tag used again for the 4th granule.<br>
<br>
Error conditions:<br>
* Length is not a valid number or is less than 0<br>
* One or more tags are out of the valid range of 0-0xF<br>
<br>
#### mtag check <address expression><br>
<br>
Check that the logical tag in <address expression> matches the allocation tag<br>
set for the granule it points to.<br>
<br>
(lldb) mtag check a_ptr<br>
Failed: logical tag 0x1 does not match allocation tag 0x2<br>
(lldb) mtag check non_mte_ptr<br>
Memory tagging is not enabled for address non_mte_ptr<br>
(lldb) mtag check another_ptr<br>
Passed: logical tag 0x1 matches allocation tag 0x1<br>
<br>
Showing tags for a passed check seems redundant but I think it’s good to have as<br>
a shortcut. That way you can use “mtag check” instead of “mtag showltag” then<br>
“mtag showatag” if you want both tags.<br>
<br>
Error conditions:<br>
* Standard handling<br>
<br>
#### mtag getconfig<br>
<br>
This command will read the TAGGED_ADDR_CTRL register (see “New Register”) and<br>
pretty print its values. It's nice to have but certainly isn’t as good as being<br>
able to pretty print a register in general. (which I don’t think is<br>
possible right now)<br>
<br>
(lldb) mtag getconfig<br>
Tagged addressing: Enabled<br>
Fault Mode: Synchronous<br>
Included Tags: 0b1111000011110000<br>
(lldb) mtag getconfig<br>
Target process is not MTE enabled.<br>
<br>
Formatting up for debate of course, the point is you don’t have to shift things<br>
in your head just to sanity check the debugee’s usage.<br>
<br>
Note: no “set” for this at this time as I think that’s going to be a<br>
much rarer occurrence.<br>
<br>
## Modified Commands<br>
<br>
### memory region<br>
<br>
Will use the extra information from the qMemoryRegionInfo packet to show the<br>
VmFlags where possible. For example:<br>
<br>
(lldb) memory region addr<br>
[0x00007ffff7ed2000-0x00007ffff7fd2000) rw- /dev/zero (deleted)<br>
flags:  rd ex mr mw me dw sd mt<br>
<br>
### memory read<br>
<br>
Will not check that logical and allocation tags match, allowing reads<br>
regardless.<br>
Since most of the time checking is not the user’s intent when doing a read and<br>
even if it is, there’s “mtag check” for that.<br>
<br>
It will show allocation tags for memory that is MTE enabled. This is<br>
on by default<br>
on the basis that some subset of memory will be MTE so if you’re working with it<br>
then tags are probably relevant. (new setting added to control this)<br>
<br>
In the ideal scenario this looks like:<br>
(lldb) memory read the_page<br>
<Allocation tag 0x1 for range [0xfffff7ffa000, 0xfffff7ffa010)><br>
0xfffff7ffa000: 66 66 00 00 00 00 00 00 00 00 00 00 00 00 00 00<br>
ff..............<br>
<Allocation tag 0x1 for range [0xfffff7ffa010, 0xfffff7ffa020)><br>
0xfffff7ffa010: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00<br>
................<br>
<br>
Obviously there’s a lot of formatting freedom with the read command so<br>
this won’t<br>
always be as neat. It could be better to put the tags in the lines like:<br>
0xfffff7ffa000 (tag 0x1): 66 66 00 00 00 00 00 00 00 00 00 00 00 00 00<br>
00  ff..............<br>
<br>
Then if the lines are <16 bytes each you can repeat the tag in the next line.<br>
Or for >16 bytes do “(tag 0x1, 0x2)”. This needs some experimentation, it could<br>
get very confusing if we’re showing the same tag next to two ranges and it looks<br>
like two separate tags. For example here we’re showing the same tag twice:<br>
<br>
0xfffff7ffa000 (tag 0x1): 66 66 00 00 00 00 00 00 ff......<br>
0xfffff7ffa008 (tag 0x1): 00 00 00 00 00 00 00 00 ........<br>
<br>
### memory write<br>
<br>
Will allow writes where the tags are mismatched.<br>
<br>
It will print warnings for granules where the tags do not match. Even<br>
if we assume<br>
we’re writing a lot of data, if the program is MTE enabled then most of the time<br>
tags will match. So it’ll only be noise in rare situations. A setting will be<br>
added to disable them if needed.<br>
<br>
lldb will read ahead for the tags. So for a write of 64 bytes we read 4 tags,<br>
do the write then warn about any granules that didn’t match.<br>
<br>
(lldb) memory write the_page 99<br>
(lldb) memory write mismtached_ptr 99<br>
Warning: Logical Tag 0x1 did not match Allocation tag 0x2 for range<br>
[0xfffff7ffb000, 0xfffff7ffb010)<br>
(lldb) memory write mismatched_ptr <17 bytes of data><br>
Warning: Logical Tag 0x1 did not match Allocation tag 0x2 for range<br>
[0xfffff7ffb000, 0xfffff7ffb010)<br>
Warning: Logical Tag 0x1 did not match Allocation tag 0x2 for range<br>
[0xfffff7ffb010, 0xfffff7ffb020)<br>
<br>
Hopefully “Warning” is enough to indicate that the write was still<br>
done despite the mismatch.<br>
<br>
## New Settings<br>
<br>
Like the commands these settings will be present/visible in help even when MTE<br>
is not available. The category name will be “memory-tagging”.<br>
<br>
* assume-tagging-enabled - When handling logical tags in pointers assume that<br>
  the memory they point to is MTE enabled. This allows you to debug/test things<br>
  such as Clang’s stack tagging that are not handled by the kernel.<br>
(default False)<br>
* warn-on-write-tag-mismatch - Print warnings for each mismatching granule when<br>
  writing with “memory write”. (default True)<br>
* show-tags-in-read - Show tags in “memory read” output. (default True)<br>
<br>
## New Registers<br>
<br>
MTE adds 1 new register to the ptrace interface, which is the TAGGED_ADDR_CTRL<br>
register. User programs use this same register via prctl to enable MTE.<br>
<br>
It contains:<br>
* A 16 bit include mask for tag generation. So with 0xFFFF you only get tags of<br>
  0, with 0xFFFE you would get tags of 0 or 1, etc.<br>
  (the hardware register GCR_EL1 actually has the opposite, an exclude mask)<br>
* 1 bit to say whether tagged addresses are enabled at all<br>
* 1 bit to set the fault mode for mismatched tags. This can be none<br>
(ignore failures),<br>
  asynchronous or synchronous.<br>
<br>
So assuming we’re ok with pseudo registers like this being available via<br>
“register read/write” it’ll be added to those. Probably under a “MTE Registers:”<br>
or perhaps “Control Registers:” category.<br>
(the latter could include future config regs such as pointer auth settings).<br>
<br>
I say assuming because the current set are all what you’d call<br>
hardware registers.<br>
(though SVE might change this I’m not sure)<br>
<br>
In “New Commands” I’ve also sketched out a command to read and pretty print the<br>
register. Since I think most of the value will come from double<br>
checking that you<br>
passed the right flags to prctl, rather than modifying it on the fly.<br>
(which could be done manually with “register write” if you really wanted to)<br>
<br>
## SIGSEGV Handling<br>
<br>
MTE faults raise a SIGSEV with a specific si_code for synchronous or<br>
asynchronous.<br>
The former includes the address where the fault happened. So this will fit into<br>
the existing handlers quite easily.<br>
<br>
(lldb) run<br>
<...><br>
Process 19648 stopped<br>
* thread #1, name = 'main', stop reason = signal SIGSEGV: Asynchronous<br>
tag check fault<br>
(lldb) run<br>
<...><br>
Process 19648 stopped<br>
* thread #1, name = 'main', stop reason = signal SIGSEGV: Synchronous<br>
tag check fault (fault address: 0x100000000, allocation tag: 0x1)<br>
<br>
Showing the allocation tag here is a nice to have, making an extra call for this<br>
one fault might be awkward. You’d want to look at the logical tag for<br>
the pointer<br>
that caused the fault, so “mtag check <ptr>” gives you both regardless.<br>
<br>
Note that the fault address does not include the logical tag used to access it.<br>
I think we could show the logical tag assuming lldb knows what the destination<br>
register of the faulting instruction is. I haven’t done the research here so I’m<br>
not proposing that we should do it for this round of support.<br></blockquote><div><br></div><div>Note that the address tag is guaranteed to be present for tag check faults in the system register FAR_EL1, but the tag is currently stripped by the kernel before being stored in siginfo.si_addr. I am working on a <a href="https://www.spinics.net/lists/arm-kernel/msg816034.html">kernel patch</a> which will make this information available via siginfo, and once the tag becomes available from the kernel you shouldn't need to decode the instruction.</div><div><br></div><div>Peter</div><div><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
## Corefiles<br>
<br>
The format of corefiles for MTE is currently undecided so there is nothing to<br>
mention here yet. Obviously we want to use the new commands to work with them<br>
once they’re available. Discussion on that design will start shortly.<br>
<br>
## Remote Protocol Changes<br>
<br>
Note: some of lldb-server’s interpretation of packed tags is also<br>
described in the “mtag setatag” section above.<br>
<br>
### Extending qMemoryRegion<br>
<br>
qMemoryRegion currently gives us the start/size/permissions and name<br>
of a mapping.<br>
For MTE we need to view the VmFlags line of the /proc/.../smaps file.<br>
This contains<br>
the “mt” flag, showing MTE was enabled for that memory.<br>
<br>
Example entry:<br>
00400000-004f4000 r-xp 00000000 fc:00 6431901<br>
  /bin/bash<br>
Size:                976 kB<br>
<...><br>
VmFlags: rd ex mr mw me dw sd<br>
<br>
To do this we will add an optional “flags” tuple to the response packet.<br>
<br>
flags:<flags>;<br>
Contain the flags shown on the VmFlags line, encoded as ASCII text just like the<br>
“name” field is. (spaces remain as the delimiter)<br>
<br>
This tuple will be optional because Linux kernels before 3.10 do not<br>
have this file.<br>
(also “flags” not “vmflags” to not be Linux specific)<br>
<br>
### qSupported feature<br>
<br>
The name will be “memory-tagging” to align with the GDB implementation. If this<br>
feature is supported by the server it means it understands the new<br>
packets and the target supports MTE.<br>
<br>
### qMemTags (new)<br>
<br>
Used to read memory tags from the target. (lldb-server will use<br>
PTRACE_PEEKMTETAGS to do so)<br>
<br>
(the “addr,length” format is derived from the existing m/M packets for<br>
read/write memory)<br>
qMemTags:addr,length:type<br>
<br>
* addr - big endian hex address of the start of the range to read from.<br>
  (the ptrace interface will take care of rounding this down to the<br>
nearest granule)<br>
* length - big endian hex number of bytes of memory to read tags from.<br>
  This will be interpreted by the server to decide how many tags to return.<br>
* type - a signed int indicating the type of tags being sent. This will just be<br>
  one value at this time, meaning MTE, but leaves room for future<br>
multi tag type systems.<br>
<br>
Note: The length is interpreted by the server so the packet spec<br>
doesn’t tell you<br>
how you should do that. For AArch64 MTE lldb-server will be rounding up to the<br>
nearest granule then returning 1 tag per. So 24 bytes becomes 32,<br>
meaning 2 tags.<br>
<br>
The reply is either:<br>
* “mXX...” - (literal ‘m’) where XX is the hex encoded bytes of the tags read.<br>
  (one tag per byte)<br>
* “E nn” - An error code if one occurred. This will only be ‘01’ for<br>
the time being.<br>
  (it may prove useful to pass the ptrace error numbers through here<br>
but it’s not<br>
  needed for the current implementation)<br>
* Empty reply - meaning the server doesn’t support this packet<br>
  (in case the client didn’t pre-check this)<br>
<br>
Note: The ‘m’ to start the tag data is present to support potential multi part<br>
replies, where the last part would have ‘l’ instead.<br>
<br>
Example exchange, reading the tags for the next 24 bytes of memory:<br>
$qMemTags:CAFEFOOD,18:1#<checksum><br>
$m0E0F#<checksum><br>
<br>
### QMemTags (new)<br>
<br>
Write memory tags to the target. (lldb-server will use<br>
PTRACE_POKEMTETAGS to do this)<br>
<br>
QMemTags:address,length:type:tags<br>
<br>
* address - big endian hex address of the start of the range to write to.<br>
  (which the ptrace interface will align for us)<br>
* length - big endian hex length in bytes of the range to be written<br>
to (see note)<br>
* type - signed int indicating the tag type. For now there will only<br>
be one value,<br>
  which means MTE.<br>
* tags - hex encoded bytes of the tags to be written (one tag per<br>
byte/per 2 hex chars)<br>
<br>
Note: The length does not have to match the number of tags given. If it is more<br>
than the given tags can cover, the tags are taken as a pattern to apply.<br>
Examples: (remember 1 tag covers 1 granule/16 bytes)<br>
<br>
Write 0 tags to 16 bytes -> Error, must have at least one tag to use<br>
Write 1 tag to 0 bytes -> round up to next granule making 16, so write<br>
tag to 1st granule<br>
Write 1 tag to 16 bytes -> writes 1st tag to 1st granule<br>
Write 1 tag to 32 bytes -> writes 1st tag to the 1st and 2nd granule<br>
Write 2 tags to 16 bytes -> writes the 1st tag to the 1st granule, 2nd<br>
tag is unused<br>
<br>
In this way you can do bulk operations like clear all tags or stripe<br>
them throughout some range.<br>
<br>
Example packet, writing the tags for the next 24 bytes of memory.<br>
Setting granule<br>
1 to 0xE and the next to 0xF:<br>
$QMemTags:CAFEFOOD,18:1:0E0F#<checksum><br>
<br>
## Toolchain Requirements<br>
<br>
We’re just using ptrace interfaces for this, we do not need tools capable of<br>
assembling MTE instructions to be able to build. So there’ll be another header<br>
in source/Plugins/Process/Linux/ containing the ptrace defines.<br>
<br>
For some of the testing we will need an MTE toolchain to compile the<br>
test programs,<br>
same for corefiles.<br>
<br>
## Testing<br>
<br>
As much as possible will be done without needing an MTE system. Tests that need<br>
an actual memory tagging enabled system will be tested using QEMU system mode<br>
emulation. A document will be added to lldb’s documentation describing<br>
how to run<br>
the tests. (or added to the SVE testing docs)<br>
<br>
## Interaction with Pointer Authentication<br>
<br>
Armv8.3-a Pointer Authentication (PAC) also uses the upper bits of a pointer to<br>
store metadata. PAC and MTE can be enabled in the same system and will share<br>
those bits.<br>
(ARM ARMv8 “Supported PAC field and relation to the use of address tagging”)<br>
<br>
The position of the MTE tag does not change when PAC is enabled, so commands<br>
do not need to check this first.<br>
<br>
I think given the difference between the two schemes they should have<br>
separate commands.<br>
(MTE being a bitfield, PAC involving keys stored elsewhere)<br>
Generic features like reporting mismatched tags/keys when reading memory could<br>
apply to both so settings regarding that could be named generically.<br>
<br>
<end doc><br>
_______________________________________________<br>
lldb-dev mailing list<br>
<a href="mailto:lldb-dev@lists.llvm.org" target="_blank">lldb-dev@lists.llvm.org</a><br>
<a href="https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-dev" rel="noreferrer" target="_blank">https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-dev</a><br>
</blockquote></div><br clear="all"><div><br></div>-- <br><div dir="ltr" class="gmail_signature"><div dir="ltr">-- <div>Peter</div></div></div></div>