LLDB mainline
ProcessDebugger.cpp
Go to the documentation of this file.
1//===-- ProcessDebugger.cpp -----------------------------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#include "ProcessDebugger.h"
10
11// Windows includes
13#include <psapi.h>
14
21#include "lldb/Target/Process.h"
22#include "llvm/Support/ConvertUTF.h"
23#include "llvm/Support/Error.h"
24
25#include "DebuggerThread.h"
26#include "ExceptionRecord.h"
27#include "ProcessWindowsLog.h"
28
29using namespace lldb;
30using namespace lldb_private;
31
32static DWORD ConvertLldbToWinApiProtect(uint32_t protect) {
33 // We also can process a read / write permissions here, but if the debugger
34 // will make later a write into the allocated memory, it will fail. To get
35 // around it is possible inside DoWriteMemory to remember memory permissions,
36 // allow write, write and restore permissions, but for now we process only
37 // the executable permission.
38 //
39 // TODO: Process permissions other than executable
40 if (protect & ePermissionsExecutable)
41 return PAGE_EXECUTE_READWRITE;
42
43 return PAGE_READWRITE;
44}
45
46// The Windows page protection bits are NOT independent masks that can be
47// bitwise-ORed together. For example, PAGE_EXECUTE_READ is not (PAGE_EXECUTE
48// | PAGE_READ). To test for an access type, it's necessary to test for any of
49// the bits that provide that access type.
50static bool IsPageReadable(uint32_t protect) {
51 return (protect & PAGE_NOACCESS) == 0;
52}
53
54static bool IsPageWritable(uint32_t protect) {
55 return (protect & (PAGE_EXECUTE_READWRITE | PAGE_EXECUTE_WRITECOPY |
56 PAGE_READWRITE | PAGE_WRITECOPY)) != 0;
57}
58
59static bool IsPageExecutable(uint32_t protect) {
60 return (protect & (PAGE_EXECUTE | PAGE_EXECUTE_READ | PAGE_EXECUTE_READWRITE |
61 PAGE_EXECUTE_WRITECOPY)) != 0;
62}
63
64namespace lldb_private {
65
67
70 return m_session_data->m_debugger->GetProcess().GetProcessId();
72}
73
76 DebuggerThreadSP debugger_thread;
77 {
78 // Acquire the lock only long enough to get the DebuggerThread.
79 // StopDebugging() will trigger a call back into ProcessDebugger which will
80 // also acquire the lock. Thus we have to release the lock before calling
81 // StopDebugging().
82 llvm::sys::ScopedLock lock(m_mutex);
83
84 if (!m_session_data) {
85 LLDB_LOG(log, "there is no active session.");
86 return Status();
87 }
88
89 debugger_thread = m_session_data->m_debugger;
90 }
91
93
94 LLDB_LOG(log, "detaching from process {0}.",
95 debugger_thread->GetProcess().GetNativeProcess().GetSystemHandle());
96 error = debugger_thread->StopDebugging(false);
97
98 // By the time StopDebugging returns, there is no more debugger thread, so
99 // we can be assured that no other thread will race for the session data.
100 m_session_data.reset();
101
102 return error;
103}
104
106 DebugDelegateSP delegate) {
107 // Even though m_session_data is accessed here, it is before a debugger
108 // thread has been kicked off. So there's no race conditions, and it
109 // shouldn't be necessary to acquire the mutex.
110
112 Status result;
113
114 FileSpec working_dir = launch_info.GetWorkingDirectory();
115 namespace fs = llvm::sys::fs;
116 if (working_dir) {
117 FileSystem::Instance().Resolve(working_dir);
118 if (!FileSystem::Instance().IsDirectory(working_dir)) {
120 "No such file or directory: %s", working_dir.GetPath().c_str());
121 return result;
122 }
123 }
124
125 if (!launch_info.GetFlags().Test(eLaunchFlagDebug)) {
126 StreamString stream;
127 stream.Printf("ProcessDebugger unable to launch '%s'. ProcessDebugger can "
128 "only be used for debug launches.",
129 launch_info.GetExecutableFile().GetPath().c_str());
130 std::string message = stream.GetString().str();
131 result = Status::FromErrorString(message.c_str());
132
133 LLDB_LOG(log, "error: {0}", message);
134 return result;
135 }
136
137 bool stop_at_entry = launch_info.GetFlags().Test(eLaunchFlagStopAtEntry);
138 m_session_data.reset(new ProcessWindowsData(stop_at_entry));
139 m_session_data->m_debugger.reset(new DebuggerThread(delegate));
140 DebuggerThreadSP debugger = m_session_data->m_debugger;
141
142 // Kick off the DebugLaunch asynchronously and wait for it to complete.
143 result = debugger->DebugLaunch(launch_info);
144 if (result.Fail()) {
145 LLDB_LOG(log, "failed launching '{0}'. {1}",
146 launch_info.GetExecutableFile().GetPath(), result);
147 return result;
148 }
149
150 HostProcess process;
151 Status error = WaitForDebuggerConnection(debugger, process);
152 if (error.Fail()) {
153 LLDB_LOG(log, "failed launching '{0}'. {1}",
154 launch_info.GetExecutableFile().GetPath(), error);
155 return error;
156 }
157
158 LLDB_LOG(log, "successfully launched '{0}'",
159 launch_info.GetExecutableFile().GetPath());
160
161 // We've hit the initial stop. If eLaunchFlagsStopAtEntry was specified, the
162 // private state should already be set to eStateStopped as a result of
163 // hitting the initial breakpoint. If it was not set, the breakpoint should
164 // have already been resumed from and the private state should already be
165 // eStateRunning.
166 launch_info.SetProcessID(process.GetProcessId());
167
168 return result;
169}
170
172 const ProcessAttachInfo &attach_info,
173 DebugDelegateSP delegate) {
175 m_session_data.reset(
176 new ProcessWindowsData(!attach_info.GetContinueOnceAttached()));
177 DebuggerThreadSP debugger(new DebuggerThread(delegate));
178
179 m_session_data->m_debugger = debugger;
180
181 DWORD process_id = static_cast<DWORD>(pid);
182 Status error = debugger->DebugAttach(process_id, attach_info);
183 if (error.Fail()) {
184 LLDB_LOG(
185 log,
186 "encountered an error occurred initiating the asynchronous attach. {0}",
187 error);
188 return error;
189 }
190
191 HostProcess process;
192 error = WaitForDebuggerConnection(debugger, process);
193 if (error.Fail()) {
194 LLDB_LOG(log,
195 "encountered an error waiting for the debugger to connect. {0}",
196 error);
197 return error;
198 }
199
200 LLDB_LOG(log, "successfully attached to process with pid={0}", process_id);
201
202 // We've hit the initial stop. If eLaunchFlagsStopAtEntry was specified, the
203 // private state should already be set to eStateStopped as a result of
204 // hitting the initial breakpoint. If it was not set, the breakpoint should
205 // have already been resumed from and the private state should already be
206 // eStateRunning.
207
208 return error;
209}
210
213 DebuggerThreadSP debugger_thread;
214 {
215 // Acquire this lock inside an inner scope, only long enough to get the
216 // DebuggerThread. StopDebugging() will trigger a call back into
217 // ProcessDebugger which will acquire the lock again, so we need to not
218 // deadlock.
219 llvm::sys::ScopedLock lock(m_mutex);
220
221 if (!m_session_data) {
222 LLDB_LOG(log, "warning: state = {0}, but there is no active session.",
223 state);
224 return Status();
225 }
226
227 debugger_thread = m_session_data->m_debugger;
228 }
229
230 if (state == eStateExited || state == eStateDetached) {
231 LLDB_LOG(log, "warning: cannot destroy process {0} while state = {1}.",
232 GetDebuggedProcessId(), state);
233 return Status();
234 }
235
236 LLDB_LOG(log, "Shutting down process {0}.",
237 debugger_thread->GetProcess().GetNativeProcess().GetSystemHandle());
238 auto error = debugger_thread->StopDebugging(true);
239
240 // By the time StopDebugging returns, there is no more debugger thread, so
241 // we can be assured that no other thread will race for the session data.
242 m_session_data.reset();
243
244 return error;
245}
246
250 llvm::sys::ScopedLock lock(m_mutex);
251 if (!m_session_data) {
252 caused_stop = false;
253 LLDB_LOG(log, "HaltProcess called with no active session.");
255 "HaltProcess called with no active debugger session.");
256 }
257 caused_stop = ::DebugBreakProcess(m_session_data->m_debugger->GetProcess()
258 .GetNativeProcess()
259 .GetSystemHandle());
260 if (!caused_stop) {
261 error = Status(::GetLastError(), eErrorTypeWin32);
262 LLDB_LOG(log, "DebugBreakProcess failed with error {0}", error);
263 }
264
265 return error;
266}
267
268Status ProcessDebugger::ReadMemory(lldb::addr_t vm_addr, void *buf, size_t size,
269 size_t &bytes_read) {
271 bytes_read = 0;
273 llvm::sys::ScopedLock lock(m_mutex);
274
275 if (!m_session_data) {
277 "cannot read, there is no active debugger connection.");
278 LLDB_LOG(log, "error: {0}", error);
279 return error;
280 }
281
282 LLDB_LOG(log, "attempting to read {0} bytes from address {1:x}", size,
283 vm_addr);
284
285 lldb::process_t handle = m_session_data->m_debugger->GetProcess()
286 .GetNativeProcess()
287 .GetSystemHandle();
288 void *addr = reinterpret_cast<void *>(vm_addr);
289 SIZE_T num_of_bytes_read = 0;
290 if (::ReadProcessMemory(handle, addr, buf, size, &num_of_bytes_read)) {
291 bytes_read = num_of_bytes_read;
292 return Status();
293 }
294 error = Status(GetLastError(), eErrorTypeWin32);
295 MemoryRegionInfo info;
296 if (GetMemoryRegionInfo(vm_addr, info).Fail() ||
297 info.GetMapped() != eLazyBoolYes)
298 return error;
299 size = info.GetRange().GetRangeEnd() - vm_addr;
300 LLDB_LOG(log, "retrying the read with size {0:x}", size);
301 if (::ReadProcessMemory(handle, addr, buf, size, &num_of_bytes_read)) {
302 LLDB_LOG(log, "success: read {0:x} bytes", num_of_bytes_read);
303 bytes_read = num_of_bytes_read;
304 return Status();
305 }
306 error = Status(GetLastError(), eErrorTypeWin32);
307 LLDB_LOG(log, "error: {0}", error);
308 return error;
309}
310
312 size_t size, size_t &bytes_written) {
314 bytes_written = 0;
316 llvm::sys::ScopedLock lock(m_mutex);
317 LLDB_LOG(log, "attempting to write {0} bytes into address {1:x}", size,
318 vm_addr);
319
320 if (!m_session_data) {
322 "cannot write, there is no active debugger connection.");
323 LLDB_LOG(log, "error: {0}", error);
324 return error;
325 }
326
327 HostProcess process = m_session_data->m_debugger->GetProcess();
328 void *addr = reinterpret_cast<void *>(vm_addr);
329 SIZE_T num_of_bytes_written = 0;
331 if (::WriteProcessMemory(handle, addr, buf, size, &num_of_bytes_written)) {
332 FlushInstructionCache(handle, addr, num_of_bytes_written);
333 bytes_written = num_of_bytes_written;
334 } else {
335 error = Status(GetLastError(), eErrorTypeWin32);
336 LLDB_LOG(log, "writing failed with error: {0}", error);
337 }
338 return error;
339}
340
341Status ProcessDebugger::AllocateMemory(size_t size, uint32_t permissions,
342 lldb::addr_t &addr) {
346 llvm::sys::ScopedLock lock(m_mutex);
347 LLDB_LOG(log, "attempting to allocate {0} bytes with permissions {1}", size,
348 permissions);
349
350 if (!m_session_data) {
352 "cannot allocate, there is no active debugger connection");
353 LLDB_LOG(log, "error: {0}", error);
354 return error;
355 }
356
357 HostProcess process = m_session_data->m_debugger->GetProcess();
359 auto protect = ConvertLldbToWinApiProtect(permissions);
360 auto result = ::VirtualAllocEx(handle, nullptr, size, MEM_COMMIT, protect);
361 if (!result) {
362 error = Status(GetLastError(), eErrorTypeWin32);
363 LLDB_LOG(log, "allocating failed with error: {0}", error);
364 } else {
365 addr = reinterpret_cast<addr_t>(result);
366 }
367 return error;
368}
369
371 Status result;
372
374 llvm::sys::ScopedLock lock(m_mutex);
375 LLDB_LOG(log, "attempting to deallocate bytes at address {0}", vm_addr);
376
377 if (!m_session_data) {
379 "cannot deallocate, there is no active debugger connection");
380 LLDB_LOG(log, "error: {0}", result);
381 return result;
382 }
383
384 HostProcess process = m_session_data->m_debugger->GetProcess();
386 if (!::VirtualFreeEx(handle, reinterpret_cast<LPVOID>(vm_addr), 0,
387 MEM_RELEASE)) {
388 result = Status(GetLastError(), eErrorTypeWin32);
389 LLDB_LOG(log, "deallocating failed with error: {0}", result);
390 }
391
392 return result;
393}
394
396 MemoryRegionInfo &info) {
399 llvm::sys::ScopedLock lock(m_mutex);
400 info.Clear();
401
402 if (!m_session_data) {
404 "GetMemoryRegionInfo called with no debugging session.");
405 LLDB_LOG(log, "error: {0}", error);
406 return error;
407 }
408 HostProcess process = m_session_data->m_debugger->GetProcess();
410 if (handle == nullptr || handle == LLDB_INVALID_PROCESS) {
412 "GetMemoryRegionInfo called with an invalid target process.");
413 LLDB_LOG(log, "error: {0}", error);
414 return error;
415 }
416
417 LLDB_LOG(log, "getting info for address {0:x}", vm_addr);
418
419 void *addr = reinterpret_cast<void *>(vm_addr);
420 MEMORY_BASIC_INFORMATION mem_info = {};
421 SIZE_T result = ::VirtualQueryEx(handle, addr, &mem_info, sizeof(mem_info));
422 if (result == 0) {
423 DWORD last_error = ::GetLastError();
424 if (last_error == ERROR_INVALID_PARAMETER) {
425 // ERROR_INVALID_PARAMETER is returned if VirtualQueryEx is called with
426 // an address past the highest accessible address. We should return a
427 // range from the vm_addr to LLDB_INVALID_ADDRESS
428 info.GetRange().SetRangeBase(vm_addr);
434 return error;
435 } else {
436 error = Status(last_error, eErrorTypeWin32);
437 LLDB_LOG(log,
438 "VirtualQueryEx returned error {0} while getting memory "
439 "region info for address {1:x}",
440 error, vm_addr);
441 return error;
442 }
443 }
444
445 // Protect bits are only valid for MEM_COMMIT regions.
446 if (mem_info.State == MEM_COMMIT) {
447 const bool readable = IsPageReadable(mem_info.Protect);
448 const bool executable = IsPageExecutable(mem_info.Protect);
449 const bool writable = IsPageWritable(mem_info.Protect);
450 info.SetReadable(readable ? eLazyBoolYes : eLazyBoolNo);
451 info.SetExecutable(executable ? eLazyBoolYes : eLazyBoolNo);
452 info.SetWritable(writable ? eLazyBoolYes : eLazyBoolNo);
453 } else {
457 }
458
459 // AllocationBase is defined for MEM_COMMIT and MEM_RESERVE but not MEM_FREE.
460 if (mem_info.State != MEM_FREE) {
461 info.GetRange().SetRangeBase(
462 reinterpret_cast<addr_t>(mem_info.BaseAddress));
463 info.GetRange().SetRangeEnd(reinterpret_cast<addr_t>(mem_info.BaseAddress) +
464 mem_info.RegionSize);
466 } else {
467 // In the unmapped case we need to return the distance to the next block of
468 // memory. VirtualQueryEx nearly does that except that it gives the
469 // distance from the start of the page containing vm_addr.
470 SYSTEM_INFO data;
471 ::GetSystemInfo(&data);
472 DWORD page_offset = vm_addr % data.dwPageSize;
473 info.GetRange().SetRangeBase(vm_addr);
474 info.GetRange().SetByteSize(mem_info.RegionSize - page_offset);
476 }
477
479 "Memory region info for address {0}: readable={1}, "
480 "executable={2}, writable={3}",
481 vm_addr, info.GetReadable(), info.GetExecutable(),
482 info.GetWritable());
483 return error;
484}
485
486void ProcessDebugger::OnExitProcess(uint32_t exit_code) {
487 // If the process exits before any initial stop then notify the debugger
488 // of the error otherwise WaitForDebuggerConnection() will be blocked.
489 // An example of this issue is when a process fails to load a dependent DLL.
490 if (m_session_data && !m_session_data->m_initial_stop_received) {
492 "Process prematurely exited with {0:x}", exit_code);
494 }
495}
496
498
501 const ExceptionRecord &record) {
503 llvm::sys::ScopedLock lock(m_mutex);
504 // FIXME: Without this check, occasionally when running the test suite
505 // there is an issue where m_session_data can be null. It's not clear how
506 // this could happen but it only surfaces while running the test suite. In
507 // order to properly diagnose this, we probably need to first figure allow the
508 // test suite to print out full lldb logs, and then add logging to the process
509 // plugin.
510 if (!m_session_data) {
511 LLDB_LOG(log,
512 "Debugger thread reported exception {0:x} at address {1:x}, but "
513 "there is no session.",
514 record.GetExceptionCode(), record.GetExceptionAddress());
516 }
517
519 if ((record.GetExceptionCode() == EXCEPTION_BREAKPOINT ||
520 record.GetExceptionCode() ==
521 0x4000001FL /*WOW64 STATUS_WX86_BREAKPOINT*/) &&
522 !m_session_data->m_initial_stop_received) {
523 // Handle breakpoints at the first chance.
525 LLDB_LOG(
526 log,
527 "Hit loader breakpoint at address {0:x}, setting initial stop event.",
528 record.GetExceptionAddress());
529 m_session_data->m_initial_stop_received = true;
530 ::SetEvent(m_session_data->m_initial_stop_event);
531 }
532 return result;
533}
534
536 // Do nothing by default
537}
538
539void ProcessDebugger::OnExitThread(lldb::tid_t thread_id, uint32_t exit_code) {
540 // Do nothing by default
541}
542
544 lldb::addr_t module_addr) {
545 // Do nothing by default
546}
547
549 // Do nothing by default
550}
551
553 bool is_unicode,
554 uint16_t length_lower_word) {
555 // Do nothing by default
556}
557
558void ProcessDebugger::OnDebuggerError(const Status &error, uint32_t type) {
559 llvm::sys::ScopedLock lock(m_mutex);
561
562 if (!m_session_data) {
563 LLDB_LOG(log,
564 "OnDebuggerError called with no active session: error {0}: {1}",
565 error.GetError(), error);
566 return;
567 }
568
569 if (m_session_data->m_initial_stop_received) {
570 // This happened while debugging. Do we shutdown the debugging session,
571 // try to continue, or do something else?
572 LLDB_LOG(log,
573 "Error {0} occurred during debugging. Unexpected behavior "
574 "may result. {1}",
575 error.GetError(), error);
576 } else {
577 // If we haven't actually launched the process yet, this was an error
578 // launching the process. Set the internal error and signal the initial
579 // stop event so that the DoLaunch method wakes up and returns a failure.
580 m_session_data->m_launch_error = error.Clone();
581 ::SetEvent(m_session_data->m_initial_stop_event);
582 LLDB_LOG(log,
583 "Error {0} occurred launching the process before the initial "
584 "stop. {1}",
585 error.GetError(), error);
586 return;
587 }
588}
589
591 HostProcess &process) {
592 Status result;
594 LLDB_LOG(log, "Waiting for loader breakpoint.");
595
596 // Block this function until we receive the initial stop from the process.
597 if (::WaitForSingleObject(m_session_data->m_initial_stop_event, INFINITE) ==
598 WAIT_OBJECT_0) {
599 LLDB_LOG(log, "hit loader breakpoint, returning.");
600
601 process = debugger->GetProcess();
602 return m_session_data->m_launch_error.Clone();
603 } else
604 return Status(::GetLastError(), eErrorTypeWin32);
605}
606
607} // namespace lldb_private
static llvm::raw_ostream & error(Stream &strm)
static int ReadProcessMemory(uint8_t *buffer, size_t size, const pt_asid *, uint64_t pc, void *context)
Callback used by libipt for reading the process memory.
#define LLDB_LOG(log,...)
The LLDB_LOG* macros defined below are the way to emit log messages.
Definition Log.h:364
#define LLDB_LOG_VERBOSE(log,...)
Definition Log.h:371
static bool IsPageExecutable(uint32_t protect)
static bool IsPageWritable(uint32_t protect)
static bool IsPageReadable(uint32_t protect)
static DWORD ConvertLldbToWinApiProtect(uint32_t protect)
lldb::addr_t GetExceptionAddress() const
A file utility class.
Definition FileSpec.h:57
size_t GetPath(char *path, size_t max_path_length, bool denormalize=true) const
Extract the full path to the file.
Definition FileSpec.cpp:374
static FileSystem & Instance()
void Resolve(llvm::SmallVectorImpl< char > &path, bool force_make_absolute=false)
Resolve path to make it canonical.
bool Test(ValueType bit) const
Test a single flag bit.
Definition Flags.h:96
HostNativeProcessBase & GetNativeProcess()
lldb::pid_t GetProcessId() const
bool GetContinueOnceAttached() const
Definition Process.h:152
Status WriteMemory(lldb::addr_t addr, const void *buf, size_t size, size_t &bytes_written)
Status DestroyProcess(lldb::StateType process_state)
Status LaunchProcess(ProcessLaunchInfo &launch_info, DebugDelegateSP delegate)
Status WaitForDebuggerConnection(DebuggerThreadSP debugger, HostProcess &process)
Status GetMemoryRegionInfo(lldb::addr_t load_addr, MemoryRegionInfo &range_info)
virtual void OnCreateThread(const HostThread &thread)
virtual void OnDebuggerError(const Status &error, uint32_t type)
virtual void OnExitThread(lldb::tid_t thread_id, uint32_t exit_code)
virtual void OnDebuggerConnected(lldb::addr_t image_base)
std::unique_ptr< ProcessWindowsData > m_session_data
Status AllocateMemory(size_t size, uint32_t permissions, lldb::addr_t &addr)
virtual ExceptionResult OnDebugException(bool first_chance, const ExceptionRecord &record)
Status AttachProcess(lldb::pid_t pid, const ProcessAttachInfo &attach_info, DebugDelegateSP delegate)
virtual void OnUnloadDll(lldb::addr_t module_addr)
lldb::pid_t GetDebuggedProcessId() const
virtual void OnDebugString(lldb::addr_t debug_string_addr, bool is_unicode, uint16_t length_lower_word)
Status ReadMemory(lldb::addr_t addr, void *buf, size_t size, size_t &bytes_read)
virtual void OnExitProcess(uint32_t exit_code)
virtual void OnLoadDll(const ModuleSpec &module_spec, lldb::addr_t module_addr)
Status HaltProcess(bool &caused_stop)
Status DeallocateMemory(lldb::addr_t addr)
void SetProcessID(lldb::pid_t pid)
Definition ProcessInfo.h:70
FileSpec & GetExecutableFile()
Definition ProcessInfo.h:43
const FileSpec & GetWorkingDirectory() const
An error handling class.
Definition Status.h:118
static Status FromErrorStringWithFormat(const char *format,...) __attribute__((format(printf
Definition Status.cpp:106
static Status FromErrorString(const char *str)
Definition Status.h:141
bool Fail() const
Test for error condition.
Definition Status.cpp:293
static Status static Status FromErrorStringWithFormatv(const char *format, Args &&...args)
Definition Status.h:151
llvm::StringRef GetString() const
size_t Printf(const char *format,...) __attribute__((format(printf
Output printf formatted output to the stream.
Definition Stream.cpp:134
#define LLDB_INVALID_ADDRESS
#define LLDB_INVALID_PROCESS_ID
#define LLDB_INVALID_PROCESS
Definition lldb-types.h:68
A class that represents a running process on the host machine.
Log * GetLog(Cat mask)
Retrieve the Log object for the channel associated with the given log enum.
Definition Log.h:327
std::shared_ptr< DebuggerThread > DebuggerThreadSP
Definition ForwardDecl.h:36
std::shared_ptr< IDebugDelegate > DebugDelegateSP
Definition ForwardDecl.h:35
StateType
Process and Thread States.
@ eStateDetached
Process has been detached and can't be examined.
@ eStateExited
Process has exited and can't be examined.
@ eErrorTypeWin32
Standard Win32 error codes.
uint64_t pid_t
Definition lldb-types.h:83
uint64_t addr_t
Definition lldb-types.h:80
uint64_t tid_t
Definition lldb-types.h:84
uint64_t process_t
Definition lldb-types.h:57
void SetRangeEnd(BaseType end)
Definition RangeMap.h:80
void SetRangeBase(BaseType b)
Set the start value for the range, and keep the same size.
Definition RangeMap.h:48
BaseType GetRangeEnd() const
Definition RangeMap.h:78
void SetByteSize(SizeType s)
Definition RangeMap.h:89