810 Commits

Author SHA1 Message Date
Jason Molenda
036279addf
[lldb][debugserver] Return shared cache filepath in jGetSharedCacheInfo (#168474)
Add a "shared_cache_path" key-value to the jGetSharedCacheInfo response,
if we can fetch the shared cache path.

If debugserver and the inferior process are running with the same shared
cache UUID, there is a simple SPI to get debugserver's own shared cache
filepath and we will return that.

On newer OSes, there are SPI we can use to get the inferior process'
shared cache filepath, use that if necessary and the SPI are available.

The response for the jGetSharedCacheInfo packet will now look like


{"shared_cache_base_address":6609256448,"shared_cache_uuid":"B69FF43C-DBFD-3FB1-B4FE-A8FE32EA1062","no_shared_cache":false,"shared_cache_private_cache":false,"shared_cache_path":"/System/Volumes/Preboot/Cryptexes/OS/System/Library/dyld/dyld_shared_cache_arm64e"}

when we have the full information about the shared cache in the
inferior. There are three possible types of responses:

1. inferior has not yet mapped in a shared cache (read: when stopped at
dyld_start and dyld hasn't started executing yet). In this case, no
"shared_cache_path" is listed. ("shared_cache_base_address" will be 0,
"shared_cache_uuid" will be all-zeroes uuid)

2. inferior has a shared cache, but it is different than debugserver's
and we do not have the new SPI to query the shared cache filepath. No
"shared_cache_path" is listed.

3. We were able to find the shared cache filepath, and it is included in
the response, as above.

I'm not using this information in lldb yet, but changes that build on
this will be forthcoming.

rdar://148939795
2025-11-30 21:40:13 -08:00
jimingham
420d56a394
Clean up MachTask.mm's handling of m_exception_thread. (#167994)
This was getting joined in ShutDownExcecptionThread (sic) but not
cleared. So this function was not safe to call twice, since you aren't
supposed to join a thread twice. Sadly, this was called in
MachTask::Clear and MachProcess::Destroy, which are both called when you
tell debugserver to detach.

This didn't seem to cause problems IRL, but the most recent ASAN detects
this as an error and calls ASAN::Die, which was causing all the tests
that ran detach to fail.

I fixed that by moving the clear & test for m_exception_thread to
ShutDownExceptionThread. I also fixed the spelling of that routine. And
that routine was claiming to return a kern_return_t which no one was
checking. It actually returns a kern_return_t if there was a Mach
failure and a Posix error if there was a join failure. Since there's
really nothing you can do but exit if this fails, which is always what
you are in the process of doing when you call this, and since we have
already done all the useful logging in ShutDownExceptionThread, I just
removed the return value.
2025-11-14 10:14:28 -08:00
Jonas Devlieghere
fa83723bbe
[debugserver] Remove unnecessary sleep in MachProcess::AttachForDebug (#166674)
Remove the unnecessary sleep in MachProcess::AttachForDebug. The
preceding comment makes it seem like it's necessary for synchronization,
though I don't believe that's the case (see below), and even if it were,
sleeping is not a reliable way to achieve that.

The reason I don't believe it's necessary is because after we return, we
synchronize with the exception thread on a state change. The latter will
call and update the process state, which is exactly what we synchronize
on. I was able to verify that this is the first time we change the
process state: i.e., `GetState` doesn't return a different value before
and after the sleep.

On top of that, there are 3 more places where we call ptrace attach
(`PosixSpawnChildForPTraceDebugging`, `SBLaunchForDebug`, and
`BoardServiceLaunchForDebug`) where we don't sleep.

rdar://163952037
2025-11-06 14:17:51 -08:00
Jonas Devlieghere
bd9030e762
[debugserver] Move constants into TaskPortForProcessID (NFC) (#166670)
I was looking at the calls to `usleep` in debugserver and noticed that
these default arguments are never overwritten. I converted them to
constants in the function, which makes it easier to reason about.
2025-11-05 16:32:36 -08:00
Jonas Devlieghere
bc55f4f4f2
[debugserver] Fix debugserver build on < macOS 10.15 (#166599)
The VM_MEMORY_SANITIZER constant was added in macOs 10.15 and friends.
Support using the constant on older OSes.

Fixes #156144
2025-11-05 18:32:38 +00:00
Jason Molenda
d478737841 [lldb][debugserver] fix typeo in SME ZA register
chunk enumeartions.  Noticed by David Spickett.
NFC--no machine with a ZA register large enough to use this exists
today.
2025-10-23 14:43:51 -07:00
Felipe de Azevedo Piovezan
9e9d67dc9c [debugserver][NFC] Fix unused variable warning
This variable is only read from.
2025-10-20 13:46:56 -07:00
Felipe de Azevedo Piovezan
5e668fe84f
[debugserver] Implement MultiMemRead packet (#162670)
This commit implements, in debugserver, the packet as discussed in the
RFC [1].

[1]:
https://discourse.llvm.org/t/rfc-a-new-vectorized-memory-read-packet/88441
2025-10-15 08:45:35 -07:00
Felipe de Azevedo Piovezan
25933f62dc
[debugserver][NFC] Make helper functions have internal linkage (#162307)
This also allowed deleting unreachable code.
2025-10-07 14:46:02 -07:00
Felipe de Azevedo Piovezan
7ab7554ef6
[debugserver][NFC] Add helper function for escaping special characters (#162297)
This code was duplicated in multiple places and a subsequent patch will
need to do it again.
2025-10-07 14:45:13 -07:00
Julian Lettner
f4784fd13f
[debugserver] Support for qMemTags packet (#160952)
Support for `qMemTags` packet in debugserver which allows usage of
LLDB's `memory tag read` on Darwin.
2025-10-02 13:57:40 -07:00
Julian Lettner
5665b1bf9d
[lldb][NFC] Fix spelling of function in log message (#161261)
Fix spelling of `GetMemoryRegionInfo` function in
log message and comment and reformat code.
2025-09-30 11:32:49 -07:00
Jason Molenda
ac8e7be5fb
[lldb][debugserver] Max response size for qSpeedTest (#156099)
The qSpeedTest packet is used for experiments to determine the optimal
packet size for a given communication medium, e.g. to transfer 10MB of
memory, is it faster to send a hundred 100KB packets or ten 1MB packets.
It creates a packet of the requested size in a stack allocation, but is
not checking that its buffer is large enough for the requested size.

Change this allocation to be on heap, and impose a maximum size that can
be tested (4MB, for now).

rdar://158630250
2025-09-03 16:31:42 -07:00
Jason Molenda
37cd595c1c
[lldb][debugserver] Upstream to debugserver changes (#155733)
Review of diffs from lldb's internal debugserver and llvm.org main found
two orphaned changes that should be upstreamed.

First is in MachTask::ExceptionThread where we want to confirm that a
mach exception messages is from the correct process before we process
it.

Second is that we want to run the arm64 register context through
thread_convert_thread_state() after thread_get_state, and before
thread_set_state, to re-sign fp/sp/lr/pc appropriately for ptrauth
(arm64e) processes.
2025-08-28 10:06:46 -07:00
Jason Molenda
a2f542b7a5
[lldb][debugserver] update --help to list all the options (#154853)
These are almost all for internal-developer-users only so "look at
debugserver.cpp" wasn't unreasonable, but we rarely add any new options
so a simple list of all recognized options isn't a burden to throw in
the help method.
2025-08-22 00:05:13 -07:00
Jonas Devlieghere
cf6a4bbc42
[lldb] Use std::make_shared where possible (NFC) (#150714)
This is a continuation of 68fd102, which did the same thing but only for
StopInfo. Using make_shared is both safer and more efficient:

- With make_shared, the object and the control block are allocated
  together, which is more efficient.
- With make_shared, the enable_shared_from_this base class is properly
  linked to the control block before the constructor finishes, so
  shared_from_this() will be safe to use (though still not recommended
  during construction).
2025-07-25 15:55:21 -07:00
Kazu Hirata
c9ac1679b5
[lldb] Remove a redundant control flow statement (NFC) (#144284) 2025-06-16 08:59:10 -07:00
Alexander Ziaee
44a7ecd1d7
[doc] Use ISO nomenclature for 1024 byte units (#133148)
Increase specificity by using the correct unit sizes. KBytes is an
abbreviation for kB, 1000 bytes, and the hardware industry as well as
several operating systems have now switched to using 1000 byte kBs.

If this change is acceptable, sometimes GitHub mangles merges to use the
original email of the account. $dayjob asks contributions have my work
email. Thanks!
2025-06-11 13:27:23 +02:00
Pavel Labath
8f352f4d7b [lldb/cmake] Fix debugserver build for 2c4f67794bff4df984b43db453fc0f5241ee72c8 2025-06-04 17:44:21 +02:00
Akash Agrawal
e4ed71818e
[LLDB] [NFC] - Remove duplicate #include headers from the files of lldb dir & few other files (#141478)
A few files of lldb dir & few other files had duplicate headers
included. This patch removes those redundancies.

---------

Co-authored-by: Akash Agrawal <akashag@qti.qualcomm.com>
2025-05-29 23:13:30 -07:00
Chelsea Cassanova
28d732a24e
[lldb][cmake] Set CMAKE_OSX_SYSROOT when building debugserver with CMake 4 (#138020)
CMake 4 no longer sets the `CMAKE_OSX_SYSROOT` variable by default. If
you've updated to CMake 4 on macOS (e.g. with brew) and try building
LLDB with CMake/ninja, this will yield an error when building
debugserver that clang is unable to run since it tries to compile files
that don't exist.

These files are supposed to be generated by the `mig` process. `mig`
needs the `CMAKE_OSX_SYSROOT` variable in order to work and without it,
it silently fails to generate the files that later on need to be
compiled.

This commit sets this SDK path for mig and will fatal error out of config
when building debugserver without having set CMAKE_OSX_SYSROOT.
2025-05-14 10:46:01 -07:00
Pavel Labath
b643a529dc [lldb][debugserver] Add missing include to DNBTimer.h 2025-05-07 11:04:51 +02:00
Jonas Devlieghere
9d77a3fa1a
[debugserver] Remove PThreadMutex (NFC) (#137555)
Now that all uses of PThreadMutex have been migrated to their C++
equivalent, this PR removes PThreadMutex itself.
2025-04-28 11:28:45 -07:00
Jonas Devlieghere
46fd2b94af
[debugserver] Migrate PThreadEvent away from PThreadMutex (NFC) (#137554)
The debugserver code predates modern C++, but with C++11 and later
there's no need to have something like PThreadMutex. This migrates
PThreadEvent away from PThreadMutex in preparation for removing it.
2025-04-28 10:31:59 -07:00
Jonas Devlieghere
9f2bcc7a66
[debugserver] Migrate DNBTimer away from PThreadMutex (NFC) (#137540)
The debugserver code predates modern C++, but with C++11 and later
there's no need to have something like PThreadMutex. This migrates
DNBTimer away from that class in preparation for removing PThreadMutex.
2025-04-28 09:44:14 -07:00
Jonas Devlieghere
41ab76bf0a
Revert "[debugserver] Migrate DNBTimer away from PThreadMutex (NFC) (#137540)"
This reverts commit ae71055e6664caf7f74f2e21fb76513bef22a099.
2025-04-28 08:44:30 -07:00
Michael Buch
ec6b619430 [lldb][DNB] Add missing include
On the buildbots:
```
user/jenkins/workspace/llvm.org/as-lldb-cmake/llvm-project/lldb/tools/debugserver/source/DNBLog.cpp
/Users/ec2-user/jenkins/workspace/llvm.org/as-lldb-cmake/llvm-project/lldb/tools/debugserver/source/DNBLog.cpp:66:15: error: no type named 'recursive_mutex' in namespace 'std'
  static std::recursive_mutex g_LogThreadedMutex;
         ~~~~~^
/Users/ec2-user/jenkins/workspace/llvm.org/as-lldb-cmake/llvm-project/lldb/tools/debugserver/source/DNBLog.cpp:67:8: error: no member named 'lock_guard' in namespace 'std'
  std::lock_guard<std::recursive_mutex> guard(g_LogThreadedMutex);
  ~~~~~^
/Users/ec2-user/jenkins/workspace/llvm.org/as-lldb-cmake/llvm-project/lldb/tools/debugserver/source/DNBLog.cpp:67:24: error: no member named 'recursive_mutex' in namespace 'std'
  std::lock_guard<std::recursive_mutex> guard(g_LogThreadedMutex);
                  ~~~~~^
```
2025-04-28 09:39:45 +01:00
Jonas Devlieghere
89f3dc9074
[debugserver] Migrate MachProcess away from PThreadMutex (NFC) (#137553)
The debugserver code predates modern C++, but with C++11 and later
there's no need to have something like PThreadMutex. This migrates
MachProcess away from PThreadMutex in preparation for removing it.
2025-04-27 17:50:35 -07:00
Jonas Devlieghere
e886ba1d59
[debugserver] Migrate RNBRemote away from PThreadMutex (NFC) (#137547)
The debugserver code predates modern C++, but with C++11 and later
there's no need to have something like PThreadMutex. This migrates
RNBRemote away from PThreadMutex in preparation for removing it.
2025-04-27 15:16:42 -07:00
Adrian Prantl
b15adefeff [lldb] Add missing include 2025-04-27 14:35:40 -07:00
Adrian Prantl
cf035e8abb [lldb] Add missing include 2025-04-27 14:32:13 -07:00
Jonas Devlieghere
33a0a786f2
[debugserver] Migrate MachThread away from PThreadMutex (NFC) (#137543)
The debugserver code predates modern C++, but with C++11 and later
there's no need to have something like PThreadMutex. This migrates
MachThread away from PThreadMutex in preparation for removing it.
2025-04-27 13:25:40 -07:00
Jonas Devlieghere
503ebad14c
[debugserver] Migrate MachThreadList away from PThreadMutex (NFC) (#137542)
The debugserver code predates modern C++, but with C++11 and later
there's no need to have something like PThreadMutex. This migrates
MachThreadList away from that class in preparation for removing
PThreadMutex.
2025-04-27 13:08:26 -07:00
Jonas Devlieghere
0755e024fc
[debugserver] Migrate DNBLog away from PThreadMutex (NFC) (#137541)
The debugserver code predates modern C++, but with C++11 and later
there's no need to have something like PThreadMutex. This migrates
DNBLog away from that class in preparation for removing PThreadMutex.
2025-04-27 13:08:04 -07:00
Jonas Devlieghere
ae71055e66
[debugserver] Migrate DNBTimer away from PThreadMutex (NFC) (#137540)
The debugserver code predates modern C++, but with C++11 and later
there's no need to have something like PThreadMutex. This migrates
DNBTimer away from that class in preparation for removing PThreadMutex.
2025-04-27 13:07:52 -07:00
Jason Molenda
df28c81f5a [lldb][debugserver] Fix an off-by-one error in watchpoint identification (#134314)
debugserver takes the address of a watchpoint exception and calculates
which watchpoint was responsible for it. There was an off-by-one error
in the range calculation which causes two watchpoints on consecutive
ranges to not correctly identify hits to the second watchpoint. The
result is that lldb wouldn't show the second watchpoint as ever being
hit.

Re-landing this test with a modification to only require two
watchpoints in the test, instead of four.  If four watchpoints can
be set, it will test them.

rdar://145107575
2025-04-07 13:50:31 -07:00
Jason Molenda
369c7739d0 Revert "[lldb][debugserver] Fix an off-by-one error in watchpoint identification (#134314)"
This reverts commit 21d912121c9f41385b165a736be787527f5bd7c2.

Failure on the aarch64 ubuntu bot when setting the 4th watchpoint;
may be a hardware limitation on that bot.  I thought creating four
watchpoints would be generally safe, but I don't need to do that
for my test, will re-land without it.
2025-04-07 11:21:58 -07:00
Jason Molenda
21d912121c
[lldb][debugserver] Fix an off-by-one error in watchpoint identification (#134314)
debugserver takes the address of a watchpoint exception and calculates
which watchpoint was responsible for it. There was an off-by-one error
in the range calculation which causes two watchpoints on consecutive
ranges to not correctly identify hits to the second watchpoint. The
result is that lldb wouldn't show the second watchpoint as ever being
hit.

rdar://145107575
2025-04-07 11:11:31 -07:00
Jason Molenda
f1c6612202 [lldb][debugserver] Save and restore the SVE/SME register state (#134184)
debugserver isn't saving and restoring the SVE/SME register state around
inferior function calls.

Making arbitrary function calls while in Streaming SVE mode is generally
a poor idea because a NEON instruction can be hit and crash the
expression execution, which is how I missed this, but they should be
handled correctly if the user knows it is safe to do.

Re-landing this change after fixing an incorrect behavior on systems
without SME support.

rdar://146886210
2025-04-03 15:48:54 -07:00
Jason Molenda
a19c018379 Revert "[lldb][debugserver] Save and restore the SVE/SME register state (#134184)"
This reverts commit 4e40c7c4bd66d98f529a807dbf410dc46444f4ca.

arm64 CI is getting a failure in
lldb-api.tools/lldb-server.TestGdbRemoteRegisterState.py
with this commit, need to investigate and re-land.
2025-04-02 23:01:51 -07:00
Jason Molenda
4e40c7c4bd
[lldb][debugserver] Save and restore the SVE/SME register state (#134184)
debugserver isn't saving and restoring the SVE/SME register state around
inferior function calls.

Making arbitrary function calls while in Streaming SVE mode is generally
a poor idea because a NEON instruction can be hit and crash the
expression execution, which is how I missed this, but they should be
handled correctly if the user knows it is safe to do.

rdar://146886210
2025-04-02 20:37:07 -07:00
Michael Buch
52de49e4b9
[lldb][debugserver][MacOSX] Work around sanitizer misaligned address errors when reading exception data (#132193)
We've been dealing with UBSAN issues around this code for some time now
(see `9c36859b33b386fbfa9599646de1e2ae01158180` and
`1a2122e9e9d1d495fdf337a4a9445b61ca56df6f`). On recent macOS versions, a
UBSAN-enabled debugserver will crash when performing a `memcpy` of the
input `mach_exception_data_t`. The pointer to the beginning of the
exception data may not be aligned on a doubleword boundary, leading to
UBSAN failures such as:
```
$ ./bin/debugserver 0.0.0.0:5555 /Volumes/SSD/llvm-builds/llvm-worktrees/clang-work/build-sanitized-release/tools/lldb/test/Shell/Recognizer/Output/verbose_trap.test.tmp.out
/Volumes/SSD/llvm-builds/llvm-worktrees/clang-work/lldb/tools/debugserver/source/MacOSX/MachException.cpp:35:12: runtime error: store to misaligned address 0x00016ddfa634 for type 'mach_exception_data_type_t *' (aka 'long long *'), which requires 8 byte alignment
0x00016ddfa634: note: pointer points here
  02 00 00 00 03 00 01 00  00 00 00 00 11 00 00 00  00 00 00 00 00 00 00 00  08 00 00 00 00 00 00 00
              ^
SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior /Volumes/SSD/llvm-builds/llvm-worktrees/clang-work/lldb/tools/debugserver/source/MacOSX/MachException.cpp:35:12
```

Work around these failures by pretending the input data is a `char*`
buffer.

Drive-by changes:
* I factored out some duplicated code into a static
`AppendExceptionData` and made the types consistent

---------

Co-authored-by: Jonas Devlieghere <jonas@devlieghere.com>
2025-03-21 11:21:29 +00:00
Jason Molenda
ad5cac3b06
[lldb][debugserver] remove g/G packet handling from debugserver (#132127)
In 2013 we added the QSaveRegisterState and QRestoreRegisterState
packets to checkpoint a thread's register state while executing an
inferior function call, instead of using the g packet to read all
registers into lldb, then the G packet to set them again after the func
call.

Since then, lldb has not sent g/G (except as a bug) - it either asks for
registers individually (p/P) or or asks debugserver to save and restore
the entire register set with these lldb extensions.

Felipe recently had a codepath that fell back to using g/G and found
that it does not work with the modern signed fp/sp/pc/lr registers that
we can get -- it sidesteps around the clearing of the non-addressable
bits that we do when reading/writing them, and results in a crash. (
https://github.com/llvm/llvm-project/pull/132079 )

Instead of fixing that issue, I am removing g/G from debugserver because
it's not needed by lldb, and it will would be easy for future bugs to
creep in to this packet that lldb should not use, but it can
accidentally fall back to and result in subtle bugs.

This does mean that a debugger using debugserver on darwin which doesn't
use QSaveRegisterState/QRestoreRegisterState will need to fall back to
reading & writing each register individually. I'm open to re-evaluating
this decision if this proves to be needed, and supporting these lldb
extensions is onerous.
2025-03-20 13:32:52 -07:00
Jason Molenda
e60e064158
[lldb][debugserver] Interrupt should reset outstanding SIGSTOP (#132128)
This fixes an uncommon bug with debugserver controlling an inferior
process that is hitting an internal breakpoint & continuing when
multiple interrupts are sent by SB API to lldb -- with the result being
that lldb never stops the inferior process, ignoring the interrupt/stops
being sent by the driver layer (Xcode, in this case).

In the reproducing setup (which required a machine with unique timing
characteristics), lldb is sent SBProcess::Stop and then shortly after,
SBProcess::SendAsyncInterrupt. The driver process only sees that the
inferior is publicly running at this point, even though it's hitting an
internal breakpoint (new dylib being loaded), disabling the bp, step
instructioning, re-enabling the breakpoint, then continuing.

The packet sequence lldb sends to debugserver looks like

1. vCont;s   // instruction step
2. ^c        // async interrupt
3. Z....     // re-enable breakpoint
4. c         // resume inferior execution
5. ^c        // async interrupt

When debugserver needs to interrupt a running process
(`MachProcess::Interrupt`), the main thread in debugserver sends a
SIGSTOP posix signal to the inferior process, and notes that it has sent
this signal by setting `m_sent_interrupt_signo`.

When we send the first async interrupt while instruction stepping, the
signal is sent (probably after the inferior has already stopped) but
lldb can only *receive* the mach exception that includes the SIGSTOP
when the process is running. So at the point of step (3), we have a
SIGSTOP outstanding in the kernel, and
`m_sent_interrupt_signo` is set to SIGSTOP.

When we resume the inferior (`c` in step 4), debugserver sees that
`m_sent_interrupt_signo` is still set for an outstanding SIGSTOP, but at
this point we've already stopped so it's an unnecessary stop. It records
that (1) we've got a SIGSTOP still coming that debugserver sent and (2)
we should ignore it by also setting `m_auto_resume_signo` to the same
signal value.

Once we've resumed the process, the mach exception thread
(`MachTask::ExceptionThread`) receives the outstanding mach exception,
adds it to a queue to be processed
(`MachProcess::ExceptionMessageReceived`) and when we've collected all
outstanding mach exceptions, it calls
`MachProcess::ExceptionMessageBundleComplete` top evaluate them.

`MachProcess::ExceptionMessageBundleComplete` halts the process (without
updating the MachProcess `m_state`) while evaluating them. It sees that
this incoming SIGSTOP was meant to be ignored (`m_auto_resume_signo` is
set), so it `MachProcess::PrivateResume`'s the process again.

At the same time `MachTask::ExceptionThread` is receiving and processing
the ME, `MachProcess::Interrupt` is called with another interrupt that
debugserver received. This method checks that we're still eStateRunning
(we are) but then sees that we have an outstanding SIGSTOP already
(`m_sent_interrupt_signo`) and does nothing, assuming that we will stop
shortly from that one. It then returns to call
`RNBRemote::HandlePacket_last_signal` to print the status -- but because
the process is still `eStateRunning`, this does nothing.

So the first ^c (resulting in a pending SIGSTOP) is received and we
resume the process silently. And the second ^c is ignored because we've
got one interrupt already being processed.

The fix was very simple. In `MachProcess::Interrupt` when we detect that
we have a SIGSTOP out in the wild (`m_sent_interrupt_signo`), we need to
clear `m_auto_resume_signo` which is used to indicate that this SIGSTOP
is meant to be ignored, because it was from before our most recent
resume.

MachProcess::Interrupt holds the `m_exception_and_signal_mutex` mutex
already (after Jonas's commit last week), and all of
`MachProcess::ExceptionMessageBundleComplete` holds that same mutex, so
we know we can modify `m_auto_resume_signo` here and it will be handled
correctly when the outstanding mach exception is finally processed.

rdar://145872120
2025-03-20 13:31:46 -07:00
Jonas Devlieghere
998511c8ef
[debugserver] Fix mutex scope in RNBRemote::CommDataReceived (#131077)
The mutex in RNBRemote::CommDataReceived protects m_rx_packets and
should extend to the end of the function to cover the read where we
check if the list is empty.
2025-03-13 15:12:19 -07:00
Jonas Devlieghere
e823449f66
[lldb][debugserver] Synchronize interrupt and resume signals (#131073)
This PR fixes a race condition in debugserver where the main thread
calls MachProcess::Interrupt, setting `m_sent_interrupt_signo` while the
exception monitoring thread is checking the value of the variable.

I was on the fence between introducing a new mutex and reusing the
existing exception mutex. With the notable exception of
MachProcess::Interrupt, all the other places where we were already
locking this mutex before accessing the variable. I renamed the mutex to
make it clear that it's now protecting more than the exception messages.

Jason, while investigating a real issue, had a suspicion there was race
condition related to interrupts and I was able to narrow it down by
building debugserver with TSan.
2025-03-13 13:54:13 -07:00
Jason Molenda
fec6d168bb
[lldb] Upstream a few remaining Triple::XROS patches (#126335)
Recognize the visionOS Triple::OSType::XROS os type. Some of these have
already been landed on main, but I reviewed the downstream sources and
there were a few that still needed to be landed upstream.
2025-02-08 15:50:52 -08:00
Jason Molenda
46e7823007
[lldb][debugserver] Read/write SME registers on arm64 (#119171)
**Note:** The register reading and writing depends on new register
flavor support in thread_get_state/thread_set_state in the kernel, which
will be first available in macOS 15.4.

The Apple M4 line of cores includes the Scalable Matrix Extension (SME)
feature. The M4s do not implement Scalable Vector Extension (SVE),
although the processor is in Streaming SVE Mode when the SME is being
used. The most obvious side effects of being in SSVE Mode are that (on
the M4 cores) NEON instructions cannot be used, and watchpoints may get
false positives, the address comparisons are done at a lowered
granularity.

When SSVE mode is enabled, the kernel will provide the Streaming Vector
Length register, which is a maximum of 64 bytes with the M4. Also
provided are SVCR (with bits indicating if SSVE mode and SME mode are
enabled), TPIDR2, SVL. Then the SVE registers Z0..31 (SVL bytes long),
P0..15 (SVL/8 bytes), the ZA matrix register (SVL*SVL bytes), and the M4
supports SME2, so the ZT0 register (64 bytes).

When SSVE/SME are disabled, none of these registers are provided by the
kernel - reads and writes of them will fail.

Unlike Linux, lldb cannot modify the SVL through a thread_set_state
call, or change the processor state's SSVE/SME status. There is also no
way for a process to request a lowered SVL size today, so the work that
David did to handle VL/SVL changing while stepping through a process is
not an issue on Darwin today. But debugserver should be providing
everything necessary so we can reuse all of David's work on resizing the
register contexts in lldb if it happens in the future. debugbserver
sends svl, svcr, and tpidr2 in the expedited registers when a thread
stops, if SSVE|SME mode are enabled (if the kernel allows it to read the
ARM_SME_STATE register set).

While the maximum SVL is 64 bytes on M4, the AArch64 maximum possible
SVL is 256; this would give us a 64k ZA register. If debugserver sized
all of its register contexts assuming the largest possible SVL, we could
easily use 2MB more memory for the register contexts of all threads in a
process -- and on iOS et al, processes must run within a small memory
allotment and this would push us over that.

Much of the work in debugserver was changing the arm64 register context
from being a static compile-time array of register sets, to being
initialized at runtime if debugserver is running on a machine with SME.
The ZA is only created to the machine's actual maximum SVL. The size of
the 32 SVE Z registers is less significant so I am statically allocating
those to the architecturally largest possible SVL value today.

Also, debugserver includes information about registers that share the
same part of the register file. e.g. S0 and D0 are the lower parts of
the NEON 128-bit V0 register. And when running on an SME machine, v0 is
the lower 128 bits of the SVE Z0 register. So the register maps used
when defining the VFP registers must differ depending on the
capabilities of the cpu at runtime.

I also changed register reading in debugserver, where formerly when
debugserver was asked to read a register, and the thread_get_state read
of that register failed, it would return all zero's. This is necessary
when constructing a `g` packet that gets all registers - because there
is no separation between register bytes, the offsets are fixed. But when
we are asking for a single register (e.g. Z0) when not in SSVE/SME mode,
this should return an error.

This does mean that when you're running on an SME capabable machine, but
not in SME mode, and do `register read -a`, lldb will report that 48 SVE
registers were unavailable and 5 SME registers were unavailable. But
that's only when `-a` is used.

The register reading and writing depends on new register flavor support
in thread_get_state/thread_set_state in the kernel, which is not yet in
a release. The test case I wrote is skipped on current OSes. I pilfered
the SME register setup from some of David's existing SME test files;
there were a few Linux specific details in those tests that they weren't
easy to reuse on Darwin.

rdar://121608074
2024-12-19 09:57:27 -08:00
Jonas Devlieghere
bd3a3959dc
[lldb] Fix deprecated defines in debugserver (XROS -> VISIONOS) (NFC) 2024-11-06 15:16:20 -08:00
Felipe de Azevedo Piovezan
474234a096
[debugserver] Mark ASAN memory regions as "heap" (#113968)
This memory type is currently not handled, but it makes sense to mark it
as a heap allocation in requests asking for memory region info.
2024-10-28 15:02:07 -07:00