Unlike x86, ARM doesn't support a generic thread pointer for TLS data,
so things like
```
reg read tp
...
memory read tp
```
Don't work, and you need to specify tpidr. This works, especially
because that's the name GDB uses. But for ease of use, and at the
request of @aperez I've made it so we can reference it via `tp`.
I personally don't have an aarch machine, and all the arm examples in
`Shell/Register/Core` are freebsd and don't contain tpidr, so I was
unable to add a shell test for this. I added a test to the AARCH
register tests, but without an Aarch machine I'm hoping these work.
This controls whether tag checking is performed for loads and
stores, or stores only.
It requires a specific architecture feature which we detect
with a HWCAP3 and cpuinfo feature.
Live process tests look for this and adjust expectations
accordingly, core file tests are using an updated file with
this feature enabled.
The size of the core file has increased and there's nothing
I can do about that. Could be the presence of new architecure
features or kernel changes since I last generated them.
I can generate a smaller file that has the tag segment,
but that segment does not actually contain tag data. So
that's no use.
In the same way that memory regions may be known from a core file but
not readable, tag segments can also have no content. For example:
```
$ readelf --segments core
<...>
Program Headers:
Type Offset VirtAddr PhysAddr
FileSiz MemSiz Flags Align
<...>
LOAD 0x0000000000002000 0x0000ffff93899000 0x0000000000000000
0x0000000000000000 0x0000000000001000 RW 0x1000
<...>
LOPROC+0x2 0x0000000000008000 0x0000ffff93899000 0x0000000000000000
0x0000000000000000 0x0000000000001000 0x0
```
This happens if you have a restricted coredump filter or size limit.
The area of virtual memory this segment covers is 0x1000, or 4096 bytes
aka one tagged page. It's FileSiz would normally be 0x80. Tags are
packed 2 per byte and granules are 16 bytes. 4096 / 16 / 2 = 128 or
0x80.
But here it has no data, and in theory a corrupt file might have some
data but not all. This triggered an assert in
UnpackTagsFromCoreFileSegment and crashed lldb.
To fix this I have made UnpackTagsFromCoreFileSegment return an expected
and returned an error in this case instead of asserting. This will be
seen by the user, as shown in the added API test.
The architectures provided to skipIf / expectedFail are regular
expressions (v. _match_decorator_property() in decorators.py
so on Darwin systems "arm64" would match the skips for "arm" (32-bit
Linux). Update these to "arm$" to prevent this, and also update
three tests (TestBuiltinFormats.py, TestCrossDSOTailCalls.py,
TestCrossObjectTailCalls.py) that were skipped for arm64 via this
behavior, and need to be skipped or they will fail.
This was moviated by the new TestDynamicValue.py test which has
an expected-fail for arm, but the test was passing on arm64 Darwin
resulting in failure for the CIs.
The features and locked registers hold the same bits, the latter
is a lock for the former. Tested with core files and live processes.
I thought about setting a non-zero lock register in the core file,
however:
* We can be pretty sure it's reading correctly because its between
the 2 other GCS registers in the same core file note.
* I can't make the test case modify lock bits because userspace
can't clear them (without using ptrace) and we don't know what the libc
has locked
(probably all feature bits).
This allows you to read the same registers as you would for a live
process.
As the content of proc/pid/smaps is not included in the core file, we
don't get the "ss" marker that tell us that it is shadow stack. The GCS
region is still in the list though.
When the Guarded Control Stack (GCS) is enabled, returns cause the
processor to validate that the address at the location pointed to by
gcspr_el0 matches the one in the link register.
```
ret (lr=A) << pc
| GCS |
+=====+
| A |
| B | << gcspr_el0
Fault: tried to return to A when you should have returned to B.
```
Therefore when an expression wrapper function tries to return to the
expression return address (usually `_start` if there is a libc), it
would fault.
```
ret (lr=_start) << pc
| GCS |
+============+
| user_func1 |
| user_func2 | << gcspr_el0
Fault: tried to return to _start when you should have returned to user_func2.
```
To fix this we must push that return address to the GCS in
PrepareTrivialCall. This value is then consumed by the final return and
the expression completes as expected.
If for some reason that fails, we will manually restore the value of
gcspr_el0, because it turns out that PrepareTrivialCall
does not restore registers if it fails at all. So for now I am handling
gcspr_el0 specifically, but I have filed
https://github.com/llvm/llvm-project/issues/124269 to address the
general problem.
(the other things PrepareTrivialCall does are exceedingly likely to not
fail, so we have never noticed this)
```
ret (lr=_start) << pc
| GCS |
+============+
| user_func1 |
| user_func2 |
| _start | << gcspr_el0
No fault, we return to _start as normal.
```
The gcspr_el0 register will be restored after expression evaluation so
that the program can continue correctly.
However, due to restrictions in the Linux GCS ABI, we will not restore
the enable bit of gcs_features_enabled. Re-enabling GCS via ptrace is
not supported because it requires memory to be allocated by the kernel.
We could disable GCS if the expression enabled GCS, however this would
use up that state transition that the program might later rely on. And
generally it is cleaner to ignore the enable bit, rather than one state
transition of it.
We will also not restore the GCS entry that was overwritten with the
expression's return address. On the grounds that:
* This entry will never be used by the program. If the program branches,
the entry will be overwritten. If the program returns, gcspr_el0 will
point to the entry before the expression return address and that entry
will instead be validated.
* Any expression that calls functions will overwrite even more entries,
so the user needs to be aware of that anyway if they want to preserve
the contents of the GCS for inspection.
* An expression could leave the program in a state where restoring the
value makes the situation worse. Especially if we ever support this in
bare metal debugging.
I will later document all this on
https://lldb.llvm.org/use/aarch64-linux.html.
Tests have been added for:
* A function call that does not interact with GCS.
* A call that does, and disables it (we do not re-enable it).
* A call that does, and enables it (we do not disable it again).
* Failure to push an entry to the GCS stack.
The Guarded Control Stack extension implements a shadow stack and the
Linux kernel provides access to 3 registers for it via ptrace.
struct user_gcs {
__u64 features_enabled;
__u64 features_locked;
__u64 gcspr_el0;
};
This commit adds support for reading those from a live process.
The first 2 are pseudo registers based on the real control register and
the 3rd is a real register. This is the stack pointer for the guarded
stack.
I have added a "gcs_" prefix to the "features" registers so that they
have a clear name when shown individually. Also this means they will tab
complete from "gcs", and be next to gcspr_el0 in any sorted lists of
registers.
Guarded Control Stack Registers:
gcs_features_enabled = 0x0000000000000000
gcs_features_locked = 0x0000000000000000
gcspr_el0 = 0x0000000000000000
Testing is more of the usual, where possible I'm writing a register then
doing something in the program to confirm the value was actually sent to
ptrace.
.. by changing the signal stop reason format 🤦
The reason this did not work is because the code in
`StopInfo::GetCrashingDereference` was looking for the string "address="
to extract the address of the crash. Macos stop reason strings have the
form
```
EXC_BAD_ACCESS (code=1, address=0xdead)
```
while on linux they look like:
```
signal SIGSEGV: address not mapped to object (fault address: 0xdead)
```
Extracting the address from a string sounds like a bad idea, but I
suppose there's some value in using a consistent format across
platforms, so this patch changes the signal format to use the equals
sign as well. All of the diagnose tests pass except one, which appears
to fail due to something similar #115453 (disassembler reports
unrelocated call targets).
I've left the tests disabled on windows, as the stop reason reporting
code works very differently there, and I suspect it won't work out of
the box. If I'm wrong -- the XFAIL will let us know.
This will be sent by Arm's Guarded Control Stack extension when an
invalid return is executed.
The signal does have an address we could show, but it's the PC at which
the fault occured. The debugger has plenty of ways to show you that
already, so I've left it out.
```
(lldb) c
Process 460 resuming
Process 460 stopped
* thread #1, name = 'test', stop reason = signal SIGSEGV: control protection fault
frame #0: 0x0000000000400784 test`main at main.c:57:1
54 afunc();
55 printf("return from main\n");
56 return 0;
-> 57 }
(lldb) dis
<...>
-> 0x400784 <+100>: ret
```
The new test case generates the signal by corrupting the link register
then attempting to return. This will work whether we manually enable GCS
or the C library does it for us.
(in the former case you could just return from main and it would fault)
This is intended for use with Arm's Guarded Control Stack extension
(GCS). Which reuses some existing shadow stack support in Linux. It
should also work with the x86 equivalent.
A "ss" flag is added to the "VmFlags" line of shadow stack memory
regions in `/proc/<pid>/smaps`. To keep the naming generic I've called
it shadow stack instead of guarded control stack.
Also the wording is "shadow stack: yes" because the shadow stack region
is just where it's stored. It's enabled for the whole process or it
isn't. As opposed to memory tagging which can be enabled per region, so
"memory tagging: enabled" fits better for that.
I've added a test case that is also intended to be the start of a set of
tests for GCS. This should help me avoid duplicating the inline assembly
needed.
Note that no special compiler support is needed for the test. However,
for the intial enabling of GCS (assuming the libc isn't doing it) we do
need to use an inline assembly version of prctl.
This is because as soon as you enable GCS, all returns are checked
against the GCS. If the GCS is empty, the program will fault. In other
words, you can never return from the function that enabled GCS, unless
you push values onto it (which is possible but not needed here).
So you cannot use the libc's prctl wrapper for this reason. You can use
that wrapper for anything else, as we do to check if GCS is enabled.
With this patch, vector registers can be read and written when debugging a live process.
Note: We currently assume that all LoongArch64 processors include the
LSX and LASX extensions.
To add test cases, the following modifications were also made:
lldb/packages/Python/lldbsuite/test/lldbtest.py
lldb/packages/Python/lldbsuite/test/make/Makefile.rules
Reviewed By: DavidSpickett, SixWeining
Pull Request: https://github.com/llvm/llvm-project/pull/120664
This fixes a functionality gap with GDB, where GDB will properly decode
the stop reason and give the address for SIGSEGV. I also added
descriptions to all stop reasons, following the same code path that the
Native Linux Thread uses.
Otherwise known as FEAT_FPMR. This register controls the behaviour of
floating point operations.
https://developer.arm.com/documentation/ddi0601/2024-06/AArch64-Registers/FPMR--Floating-point-Mode-Register
As the current floating point register contexts are fixed size, this has
been placed in a new set. Linux kernel patches have landed already, so
you can cross check with those.
To simplify testing we're not going to do any floating point operations,
just read and write from the program and debugger to make sure each sees
the other's values correctly.
This enables XML output for enums and adds enums for 2 fields on AArch64
Linux:
* mte_ctrl.tcf, which controls how tag faults are delivered.
* fpcr.rmode, which sets the rounding mode for floating point
operations.
The other one we could do is cpsr.btype, but it is not clear what would
be useful here so I'm not including it in this change.
This uses [teyit](https://pypi.org/project/teyit/) to modernize asserts,
as recommended by the [unittest release
notes](https://docs.python.org/3.12/whatsnew/3.12.html#id3).
For example, `assertTrue(a == b)` is replaced with `assertEqual(a, b)`.
This produces better error messages, e.g. `error: unexpectedly found 1
and 2 to be different` instead of `error: False`.
assertRegexpMatches is a deprecated alias for assertRegex and has been
removed in Python 3.12. This wasn't an issue previously because we used
a vendored version of the unittest module. Now that we use the built-in
version this gets updated together with the Python version used to run
the test suite.
This register is a pseudo register but mirrors the architectural
register's contents. See:
https://developer.arm.com/documentation/ddi0616/latest/
For the full details. Example output:
```
(lldb) register read svcr
svcr = 0x0000000000000002
= (ZA = 1, SM = 0)
```
This is a Linux pseudo register provided by the NT_ARM_TAGGED_ADDR_CTRL
register set. It reflects the value passed to prctl
PR_SET_TAGGED_ADDR_CTRL.
https://docs.kernel.org/arch/arm64/memory-tagging-extension.html
The fields are made from the #defines the kernel provides for setting
the value. Its contents are constant so no runtime detection is needed
(once we've decided we have this register in the first place).
The permitted generated tags is technically a bitfield but at this time
we don't have a way to mark a field as preferring hex formatting.
```
(lldb) register read mte_ctrl
mte_ctrl = 0x000000000007fffb
= (TAGS = 65535, TCF_ASYNC = 0, TCF_SYNC = 1, TAGGED_ADDR_ENABLE = 1)
```
(4 bit tags mean 16 possible tags, 16 bit bitfield)
Testing has been added to TestMTECtrlRegister.py, which needed a more
granular way to check for XML support, so I've added hasXMLSupport that
can be used within a test case instead of skipping whole tests if XML
isn't supported.
Same for the core file tests.
The ZT0 register is always 64 bytes in size so it is a lot easier to
handle than ZA which is scalable. In addition, reading an inactive ZT0
via ptrace returns all 0s, unlike ZA which returns no register data.
This means that a corefile from a process where ZA and ZT0 were inactive
still contains an NT_ARM_ZT note and we can simply say that if it's
there, then we should be able to read from it.
Along the way I removed a redundant check on the size of the ZA note. If
that note's size is < the ZA header size, we do not have SME, and
therefore could not have SME2 either.
I have added ZT0 to the existing SME core files tests. This means that
you need an SME2 system to generate them (Arm's FVP at this point). I
think this is a fair tradeoff given that this is all running in
simulation anyway and seperate ZT0 tests would be 99% identical copies
of the ZA only tests.
This register reports the configuration of the AArch64 Linux tagged
address ABI, part of which is the memory tagging (MTE) settings.
It will always be present in core files because even without MTE, there
are parts of the tagged address ABI that can be configured (these parts
use the Top Byte Ignore feature).
I missed adding this when I previously worked on MTE support. Until now
you could read memory tags from a core file but not this register.
This reverts commit 3fa5035823.
m_sve_state was not initialised which (I'm guessing) meant that
it could potentially be a value that matched a real SVE state.
Then we'd be acting as if we're streaming mode, for example,
without ever having the data required to back that up.
By sheer luck this only turn up on x86, AArch64 and ARM were fine.
It is UB regardless.
This adds the ability to read streaming SVE registers,
ZA, SVCR and SVG from core files.
Streaming SVE is in a new note NT_ARM_SSVE but otherwise
has the same format as SVE. So I've done the same as I
did for live processes and reused the existing SVE state
with an extra state for the mode variable.
ZA is in a note NT_ARM_ZA and again the handling matches
live processes. Except that it gets setup only once. A
disabled ZA reads as 0s as usual.
SVCR and SVG are pseudo registers, generated from the notes.
An important detail is that the notes represent what
you would have got if you read from ptrace at the time of
the crash.
This means that for a corefile in non-streaming mode,
there is still an NT_ARM_SSVE note and we check the header
flags to tell if it is active. We cannot just say if you
have the note you're in streaming mode.
The kernel does not provide register values for the inactive
mode and even if it did, they would be undefined, so if we find
streaming state, we ignore the non-streaming state.
Same for ZA, a disabled ZA still has the header in the note.
The tests do not cover all combinations but enough different
vector lengths, modes and ZA states to be confident.
Reviewed By: omjavaid
Differential Revision: https://reviews.llvm.org/D158500
Previously lldb was storing them but not restoring them. Meaning that this function:
```
void expr(uint64_t value) {
__asm__ volatile("msr tpidr_el0, %0" ::"r"(value));
}
```
When run from lldb:
```
(lldb) expression expr()
```
Would leave tpidr as `value` instead of the original value of the register.
A check for this scenario has been added to TestAArch64LinuxTLSRegisters.py,
which covers tpidr and the SME excluisve tpidr2 register when it's present.
Reviewed By: omjavaid
Differential Revision: https://reviews.llvm.org/D156512
This changes the TLS regset to not only be dynamic in that it could
exist or not (though it always does) but also of a dynamic size.
If SME is present then the regset is 16 bytes and contains both tpidr
and tpidr2.
Testing is the same as tpidr. Write from assembly, read from lldb and
vice versa since we have no way to predict what its value should be
by just running a program.
Reviewed By: omjavaid
Differential Revision: https://reviews.llvm.org/D154930
This register is used as the pointer to the current thread
local storage block and is read from NT_ARM_TLS on Linux.
Though tpidr will be present on all AArch64 Linux, I am soon
going to add a second register tpidr2 to this set.
tpidr is only present when SME is implemented, therefore the
NT_ARM_TLS set will change size. This is why I've added this
as a dynamic register set to save changes later.
Reviewed By: omjavaid
Differential Revision: https://reviews.llvm.org/D152516
This is an ongoing series of commits that are reformatting our Python
code. Reformatting is done with `black` (23.1.0).
If you end up having problems merging this commit because you have made
changes to a python file, the best way to handle that is to run `git
checkout --ours <yourfile>` and then reformat it with black.
RFC: https://discourse.llvm.org/t/rfc-document-and-standardize-python-code-style
Differential revision: https://reviews.llvm.org/D151460
Previously we only looked at the si_signo field, so you got:
```
(lldb) bt
* thread #1, name = 'a.out.mte', stop reason = signal SIGSEGV
* frame #0: 0x00000000004007f4
```
This patch adds si_code so we can show:
```
(lldb) bt
* thread #1, name = 'a.out.mte', stop reason = signal SIGSEGV: sync tag check fault
* frame #0: 0x00000000004007f4
```
The order of errno and code was incorrect in ElfLinuxSigInfo::Parse.
It was the order that a "swapped" siginfo arch would use, which for Linux,
is only MIPS. We removed MIPS Linux support some time ago.
See:
fe15c26ee2/include/uapi/asm-generic/siginfo.h (L121)
A test is added using memory tagging faults. Which were the original
motivation for the changes.
Reviewed By: JDevlieghere
Differential Revision: https://reviews.llvm.org/D146045
This is a follow up to https://reviews.llvm.org/D141629
and applies the change it made to all paths through ToAddress
(now DoToAddress).
I have included the test from my previous attempt
https://reviews.llvm.org/D136938.
The initial change only applied fixing to addresses that
would parse as integers, so my test case failed. Since
ToAddress has multiple exit points, I've wrapped it into
a new method DoToAddress.
Now you can call ToAddress, it will call DoToAddress and
no matter what path you take, the address will be fixed.
For the memory tagging commands we actually want the full
address (to work out mismatches). So I added ToRawAddress
for that.
I have tested this on a QEMU AArch64 Linux system with
Memory Tagging, Pointer Authentication and Top Byte Ignore
enabled. By running the new test and all other tests in
API/linux/aarch64.
Some commands have had calls to the ABI plugin removed
as ToAddress now does this for them.
The "memory region" command still needs to use the ABI plugin
to detect the end of memory when there are non-address bits.
Reviewed By: jasonmolenda
Differential Revision: https://reviews.llvm.org/D142715
In API tests, replace use of the `p` alias with the `expression` command.
To avoid conflating tests of the alias with tests of the expression command,
this patch canonicalizes to the use `expression`.
Differential Revision: https://reviews.llvm.org/D141539
This teaches ProcessElfCore to recognise the MTE tag segments.
https://www.kernel.org/doc/html/latest/arm64/memory-tagging-extension.html#core-dump-support
These segments contain all the tags for a matching memory segment
which will have the same size in virtual address terms. In real terms
it's 2 tags per byte so the data in the segment is much smaller.
Since MTE is the only tag type supported I have hardcoded some
things to those values. We could and should support more formats
as they appear but doing so now would leave code untested until that
happens.
A few things to note:
* /proc/pid/smaps is not in the core file, only the details you have
in "maps". Meaning we mark a region tagged only if it has a tag segment.
* A core file supports memory tagging if it has at least 1 memory
tag segment, there is no other flag we can check to tell if memory
tagging was enabled. (unlike a live process that can support memory
tagging even if there are currently no tagged memory regions)
Tests have been added at the commands level for a core file with
mte and without.
There is a lot of overlap between the "memory tag read" tests here and the unit tests for
MemoryTagManagerAArch64MTE::UnpackTagsFromCoreFileSegment, but I think it's
worth keeping to check ProcessElfCore doesn't cause an assert.
Depends on D129487
Reviewed By: omjavaid
Differential Revision: https://reviews.llvm.org/D129489
Eliminate boilerplate of having each test manually assign to `mydir` by calling
`compute_mydir` in lldbtest.py.
Differential Revision: https://reviews.llvm.org/D128077
Add a function to make it easier to debug a test failure caused by an
unexpected state.
Currently, tests are using assertEqual which results in a cryptic error
message: "AssertionError: 5 != 10". Even when a test provides a message
to make it clear why a particular state is expected, you still have to
figure out which of the two was the expected state, and what the other
value corresponds to.
We have a function in lldbutil that helps you convert the state number
into a user readable string. This patch adds a wrapper around
assertEqual specifically for comparing states and reporting better error
messages.
The aforementioned error message now looks like this: "AssertionError:
stopped (5) != exited (10)". If the user provided a message, that
continues to get printed as well.
Differential revision: https://reviews.llvm.org/D127355
This is off by default. If you get a result and that
memory has memory tags, when --show-tags is given you'll
see the tags inline with the memory content.
```
(lldb) memory read mte_buf mte_buf+64 --show-tags
<...>
0xfffff7ff8020: 00 00 00 00 00 00 00 00 0d f0 fe ca 00 00 00 00 ................ (tag: 0x2)
<...>
(lldb) memory find -e 0xcafef00d mte_buf mte_buf+64 --show-tags
data found at location: 0xfffff7ff8028
0xfffff7ff8028: 0d f0 fe ca 00 00 00 00 00 00 00 00 00 00 00 00 ................ (tags: 0x2 0x3)
0xfffff7ff8038: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ (tags: 0x3 0x4)
```
The logic for handling alignments is the same as for memory read
so in the above example because the line starts misaligned to the
granule it covers 2 granules.
Depends on D125089
Reviewed By: omjavaid
Differential Revision: https://reviews.llvm.org/D125090
This reverts commit 3e928c4b9d.
This fixes an issue seen on Windows where we did not properly
get the section names of regions if they overlapped. Windows
has regions like:
[0x00007fff928db000-0x00007fff949a0000) ---
[0x00007fff949a0000-0x00007fff949a1000) r-- PECOFF header
[0x00007fff949a0000-0x00007fff94a3d000) r-x .hexpthk
[0x00007fff949a0000-0x00007fff94a85000) r-- .rdata
[0x00007fff949a0000-0x00007fff94a88000) rw- .data
[0x00007fff949a0000-0x00007fff94a94000) r-- .pdata
[0x00007fff94a94000-0x00007fff95250000) ---
I assumed that you could just resolve the address and get the section
name using the start of the region but here you'd always get
"PECOFF header" because they all have the same start point.
The usual command repeating loop used the end address of the previous
region when requesting the next, or getting the section name.
So I've matched this in the --all scenario.
In the example above, somehow asking for the region at
0x00007fff949a1000 would get you a region that starts at
0x00007fff949a0000 but has a different end point. Using the load
address you get (what I assume is) the correct section name.
This does 2 things:
* Moves it after the short options. Which makes sense given it's
a niche, default off option.
(if 2 files for one option seems a bit much, I am going to reuse
them for "memory find" later)
* Fixes the use of repeated commands. For example:
memory read buf --show-tags
<shows tags>
memory read
<shows tags>
Added tests for the repetition and updated existing help tests.
Reviewed By: omjavaid
Differential Revision: https://reviews.llvm.org/D125089
Previously if you read a code/data mask before there was a valid thread
you would get the top byte mask. This meant the value was "valid" as in,
don't read it again.
When using a corefile we ask for the data mask very early on and this
meant that later once you did have a thread it wouldn't read the
register to get the rest of the mask.
This fixes that and adds a corefile test generated from the same program
as in my previous change on this theme.
Depends on D118794
Reviewed By: omjavaid
Differential Revision: https://reviews.llvm.org/D122411
Non-address bits are not part of the virtual address in a pointer.
So they must be removed before passing to interfaces like ptrace.
Some of them we get way with not removing, like AArch64's top byte.
However this is only because of a hardware feature that ignores them.
This change updates all the Process/Target Read/Write memory methods
to remove non-address bits before using addresses.
Doing it in this way keeps lldb-server simple and also fixes the
memory caching when differently tagged pointers for the same location
are read.
Removing the bits is done at the ReadMemory level not DoReadMemory
because particualrly for process, many subclasses override DoReadMemory.
Tests have been added for read/write at the command and API level,
for process and target. This includes variants like
Read<sometype>FromMemory. Commands are tested to make sure we remove
at the command and API level.
"memory find" is not included because:
* There is no API for it.
* It already has its own address handling tests.
Software breakpoints do use these methods but they are not tested
here because there are bigger issues to fix with those. This will
happen in another change.
Reviewed By: omjavaid
Differential Revision: https://reviews.llvm.org/D118794
This adds an option to the memory region command
to print all regions at once. Like you can do by
starting at address 0 and repeating the command
manually.
memory region [-a] [<address-expression>]
(lldb) memory region --all
[0x0000000000000000-0x0000000000400000) ---
[0x0000000000400000-0x0000000000401000) r-x <...>/a.out PT_LOAD[0]
<...>
[0x0000fffffffdf000-0x0001000000000000) rw- [stack]
[0x0001000000000000-0xffffffffffffffff) ---
The output matches exactly what you'd get from
repeating the command. Including that it shows
unmapped areas between the mapped regions.
(this is why Process GetMemoryRegions is not
used, that skips unmapped areas)
Help text has been updated to show that you can have
an address or --all but not both.
Reviewed By: JDevlieghere
Differential Revision: https://reviews.llvm.org/D111791