ProcessFreeBSD.cpp revision 296417
1254721Semaste//===-- ProcessFreeBSD.cpp ----------------------------------------*- C++ -*-===//
2254721Semaste//
3254721Semaste//                     The LLVM Compiler Infrastructure
4254721Semaste//
5254721Semaste// This file is distributed under the University of Illinois Open Source
6254721Semaste// License. See LICENSE.TXT for details.
7254721Semaste//
8254721Semaste//===----------------------------------------------------------------------===//
9254721Semaste
10254721Semaste// C Includes
11254721Semaste#include <errno.h>
12254721Semaste
13254721Semaste// C++ Includes
14288943Sdim#include <mutex>
15288943Sdim
16254721Semaste// Other libraries and framework includes
17254721Semaste#include "lldb/Core/PluginManager.h"
18254721Semaste#include "lldb/Core/State.h"
19254721Semaste#include "lldb/Host/Host.h"
20254721Semaste#include "lldb/Symbol/ObjectFile.h"
21254721Semaste#include "lldb/Target/DynamicLoader.h"
22254721Semaste#include "lldb/Target/Target.h"
23254721Semaste
24254721Semaste#include "ProcessFreeBSD.h"
25254721Semaste#include "ProcessPOSIXLog.h"
26254721Semaste#include "Plugins/Process/Utility/InferiorCallPOSIX.h"
27276479Sdim#include "Plugins/Process/Utility/FreeBSDSignals.h"
28254721Semaste#include "ProcessMonitor.h"
29258892Semaste#include "FreeBSDThread.h"
30254721Semaste
31296417Sdim// Other libraries and framework includes
32296417Sdim#include "lldb/Breakpoint/BreakpointLocation.h"
33296417Sdim#include "lldb/Breakpoint/Watchpoint.h"
34296417Sdim#include "lldb/Core/Module.h"
35296417Sdim#include "lldb/Core/ModuleSpec.h"
36296417Sdim#include "lldb/Core/PluginManager.h"
37296417Sdim#include "lldb/Core/State.h"
38296417Sdim#include "lldb/Host/FileSpec.h"
39296417Sdim#include "lldb/Host/Host.h"
40296417Sdim#include "lldb/Symbol/ObjectFile.h"
41296417Sdim#include "lldb/Target/DynamicLoader.h"
42296417Sdim#include "lldb/Target/Platform.h"
43296417Sdim#include "lldb/Target/Target.h"
44296417Sdim
45296417Sdim#include "lldb/Host/posix/Fcntl.h"
46296417Sdim
47296417Sdim
48254721Semasteusing namespace lldb;
49254721Semasteusing namespace lldb_private;
50254721Semaste
51276479Sdimnamespace
52276479Sdim{
53276479Sdim    UnixSignalsSP&
54276479Sdim    GetFreeBSDSignals ()
55276479Sdim    {
56276479Sdim        static UnixSignalsSP s_freebsd_signals_sp (new FreeBSDSignals ());
57276479Sdim        return s_freebsd_signals_sp;
58276479Sdim    }
59276479Sdim}
60276479Sdim
61254721Semaste//------------------------------------------------------------------------------
62254721Semaste// Static functions.
63254721Semaste
64254721Semastelldb::ProcessSP
65296417SdimProcessFreeBSD::CreateInstance(lldb::TargetSP target_sp,
66254721Semaste                               Listener &listener,
67254721Semaste                               const FileSpec *crash_file_path)
68254721Semaste{
69254721Semaste    lldb::ProcessSP process_sp;
70254721Semaste    if (crash_file_path == NULL)
71296417Sdim        process_sp.reset(new ProcessFreeBSD (target_sp, listener, GetFreeBSDSignals()));
72254721Semaste    return process_sp;
73254721Semaste}
74254721Semaste
75254721Semastevoid
76254721SemasteProcessFreeBSD::Initialize()
77254721Semaste{
78288943Sdim    static std::once_flag g_once_flag;
79254721Semaste
80288943Sdim    std::call_once(g_once_flag, []() {
81254721Semaste        PluginManager::RegisterPlugin(GetPluginNameStatic(),
82254721Semaste                                      GetPluginDescriptionStatic(),
83254721Semaste                                      CreateInstance);
84288943Sdim        ProcessPOSIXLog::Initialize(GetPluginNameStatic());
85288943Sdim    });
86254721Semaste}
87254721Semaste
88254721Semastelldb_private::ConstString
89254721SemasteProcessFreeBSD::GetPluginNameStatic()
90254721Semaste{
91254721Semaste    static ConstString g_name("freebsd");
92254721Semaste    return g_name;
93254721Semaste}
94254721Semaste
95254721Semasteconst char *
96254721SemasteProcessFreeBSD::GetPluginDescriptionStatic()
97254721Semaste{
98254721Semaste    return "Process plugin for FreeBSD";
99254721Semaste}
100254721Semaste
101254721Semaste//------------------------------------------------------------------------------
102254721Semaste// ProcessInterface protocol.
103254721Semaste
104254721Semastelldb_private::ConstString
105254721SemasteProcessFreeBSD::GetPluginName()
106254721Semaste{
107254721Semaste    return GetPluginNameStatic();
108254721Semaste}
109254721Semaste
110254721Semasteuint32_t
111254721SemasteProcessFreeBSD::GetPluginVersion()
112254721Semaste{
113254721Semaste    return 1;
114254721Semaste}
115254721Semaste
116254721Semastevoid
117254721SemasteProcessFreeBSD::Terminate()
118254721Semaste{
119254721Semaste}
120254721Semaste
121258054SemasteError
122258054SemasteProcessFreeBSD::DoDetach(bool keep_stopped)
123258054Semaste{
124258054Semaste    Error error;
125258054Semaste    if (keep_stopped)
126258054Semaste    {
127258054Semaste        error.SetErrorString("Detaching with keep_stopped true is not currently supported on FreeBSD.");
128258054Semaste        return error;
129258054Semaste    }
130258054Semaste
131258054Semaste    error = m_monitor->Detach(GetID());
132258054Semaste
133258054Semaste    if (error.Success())
134258054Semaste        SetPrivateState(eStateDetached);
135258054Semaste
136258054Semaste    return error;
137258054Semaste}
138258054Semaste
139258892SemasteError
140258892SemasteProcessFreeBSD::DoResume()
141258892Semaste{
142258892Semaste    Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_PROCESS));
143258892Semaste
144258892Semaste    SetPrivateState(eStateRunning);
145258892Semaste
146258892Semaste    Mutex::Locker lock(m_thread_list.GetMutex());
147258892Semaste    bool do_step = false;
148258892Semaste
149258892Semaste    for (tid_collection::const_iterator t_pos = m_run_tids.begin(), t_end = m_run_tids.end(); t_pos != t_end; ++t_pos)
150258892Semaste    {
151258892Semaste        m_monitor->ThreadSuspend(*t_pos, false);
152258892Semaste    }
153258892Semaste    for (tid_collection::const_iterator t_pos = m_step_tids.begin(), t_end = m_step_tids.end(); t_pos != t_end; ++t_pos)
154258892Semaste    {
155258892Semaste        m_monitor->ThreadSuspend(*t_pos, false);
156258892Semaste        do_step = true;
157258892Semaste    }
158258892Semaste    for (tid_collection::const_iterator t_pos = m_suspend_tids.begin(), t_end = m_suspend_tids.end(); t_pos != t_end; ++t_pos)
159258892Semaste    {
160258892Semaste        m_monitor->ThreadSuspend(*t_pos, true);
161258892Semaste        // XXX Cannot PT_CONTINUE properly with suspended threads.
162258892Semaste        do_step = true;
163258892Semaste    }
164258892Semaste
165258892Semaste    if (log)
166276479Sdim        log->Printf("process %" PRIu64 " resuming (%s)", GetID(), do_step ? "step" : "continue");
167258892Semaste    if (do_step)
168276479Sdim        m_monitor->SingleStep(GetID(), m_resume_signo);
169258892Semaste    else
170276479Sdim        m_monitor->Resume(GetID(), m_resume_signo);
171258892Semaste
172258892Semaste    return Error();
173258892Semaste}
174258892Semaste
175254721Semastebool
176254721SemasteProcessFreeBSD::UpdateThreadList(ThreadList &old_thread_list, ThreadList &new_thread_list)
177254721Semaste{
178258892Semaste    Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_PROCESS));
179258892Semaste    if (log)
180258892Semaste        log->Printf("ProcessFreeBSD::%s (pid = %" PRIu64 ")", __FUNCTION__, GetID());
181258054Semaste
182258892Semaste    std::vector<lldb::pid_t> tds;
183258892Semaste    if (!GetMonitor().GetCurrentThreadIDs(tds))
184258892Semaste    {
185258892Semaste        return false;
186258054Semaste    }
187258054Semaste
188258892Semaste    ThreadList old_thread_list_copy(old_thread_list);
189258892Semaste    for (size_t i = 0; i < tds.size(); ++i)
190258892Semaste    {
191258892Semaste        tid_t tid = tds[i];
192258892Semaste        ThreadSP thread_sp (old_thread_list_copy.RemoveThreadByID(tid, false));
193258892Semaste        if (!thread_sp)
194258892Semaste        {
195258892Semaste            thread_sp.reset(new FreeBSDThread(*this, tid));
196258892Semaste            if (log)
197258892Semaste                log->Printf("ProcessFreeBSD::%s new tid = %" PRIu64, __FUNCTION__, tid);
198258892Semaste        }
199258892Semaste        else
200258892Semaste        {
201258892Semaste            if (log)
202258892Semaste                log->Printf("ProcessFreeBSD::%s existing tid = %" PRIu64, __FUNCTION__, tid);
203258892Semaste        }
204258892Semaste        new_thread_list.AddThread(thread_sp);
205258892Semaste    }
206258892Semaste    for (size_t i = 0; i < old_thread_list_copy.GetSize(false); ++i)
207258892Semaste    {
208258892Semaste        ThreadSP old_thread_sp(old_thread_list_copy.GetThreadAtIndex(i, false));
209258892Semaste        if (old_thread_sp)
210258892Semaste        {
211258892Semaste            if (log)
212258892Semaste                log->Printf("ProcessFreeBSD::%s remove tid", __FUNCTION__);
213258892Semaste        }
214258892Semaste    }
215258054Semaste
216258892Semaste    return true;
217258892Semaste}
218258054Semaste
219258892SemasteError
220258892SemasteProcessFreeBSD::WillResume()
221258892Semaste{
222276479Sdim    m_resume_signo = 0;
223258892Semaste    m_suspend_tids.clear();
224258892Semaste    m_run_tids.clear();
225258892Semaste    m_step_tids.clear();
226296417Sdim    return Process::WillResume();
227254721Semaste}
228258892Semaste
229258892Semastevoid
230258892SemasteProcessFreeBSD::SendMessage(const ProcessMessage &message)
231258892Semaste{
232258892Semaste    Mutex::Locker lock(m_message_mutex);
233258892Semaste
234258892Semaste    switch (message.GetKind())
235258892Semaste    {
236258892Semaste    case ProcessMessage::eInvalidMessage:
237258892Semaste        return;
238258892Semaste
239258892Semaste    case ProcessMessage::eAttachMessage:
240258892Semaste        SetPrivateState(eStateStopped);
241258892Semaste        return;
242258892Semaste
243258892Semaste    case ProcessMessage::eLimboMessage:
244258892Semaste    case ProcessMessage::eExitMessage:
245280031Sdim        SetExitStatus(message.GetExitStatus(), NULL);
246258892Semaste        break;
247258892Semaste
248258892Semaste    case ProcessMessage::eSignalMessage:
249258892Semaste    case ProcessMessage::eSignalDeliveredMessage:
250258892Semaste    case ProcessMessage::eBreakpointMessage:
251258892Semaste    case ProcessMessage::eTraceMessage:
252258892Semaste    case ProcessMessage::eWatchpointMessage:
253258892Semaste    case ProcessMessage::eCrashMessage:
254258892Semaste        SetPrivateState(eStateStopped);
255258892Semaste        break;
256258892Semaste
257258892Semaste    case ProcessMessage::eNewThreadMessage:
258296417Sdim        llvm_unreachable("eNewThreadMessage unexpected on FreeBSD");
259258892Semaste        break;
260258892Semaste
261258892Semaste    case ProcessMessage::eExecMessage:
262258892Semaste        SetPrivateState(eStateStopped);
263258892Semaste        break;
264258892Semaste    }
265258892Semaste
266258892Semaste    m_message_queue.push(message);
267258892Semaste}
268296417Sdim
269296417Sdim//------------------------------------------------------------------------------
270296417Sdim// Constructors and destructors.
271296417Sdim
272296417SdimProcessFreeBSD::ProcessFreeBSD(lldb::TargetSP target_sp, Listener &listener, UnixSignalsSP &unix_signals_sp)
273296417Sdim    : Process(target_sp, listener, unix_signals_sp),
274296417Sdim      m_byte_order(endian::InlHostByteOrder()),
275296417Sdim      m_monitor(NULL),
276296417Sdim      m_module(NULL),
277296417Sdim      m_message_mutex (Mutex::eMutexTypeRecursive),
278296417Sdim      m_exit_now(false),
279296417Sdim      m_seen_initial_stop(),
280296417Sdim      m_resume_signo(0)
281296417Sdim{
282296417Sdim    // FIXME: Putting this code in the ctor and saving the byte order in a
283296417Sdim    // member variable is a hack to avoid const qual issues in GetByteOrder.
284296417Sdim    lldb::ModuleSP module = GetTarget().GetExecutableModule();
285296417Sdim    if (module && module->GetObjectFile())
286296417Sdim        m_byte_order = module->GetObjectFile()->GetByteOrder();
287296417Sdim}
288296417Sdim
289296417SdimProcessFreeBSD::~ProcessFreeBSD()
290296417Sdim{
291296417Sdim    delete m_monitor;
292296417Sdim}
293296417Sdim
294296417Sdim//------------------------------------------------------------------------------
295296417Sdim// Process protocol.
296296417Sdimvoid
297296417SdimProcessFreeBSD::Finalize()
298296417Sdim{
299296417Sdim  Process::Finalize();
300296417Sdim
301296417Sdim  if (m_monitor)
302296417Sdim    m_monitor->StopMonitor();
303296417Sdim}
304296417Sdim
305296417Sdimbool
306296417SdimProcessFreeBSD::CanDebug(lldb::TargetSP target_sp, bool plugin_specified_by_name)
307296417Sdim{
308296417Sdim    // For now we are just making sure the file exists for a given module
309296417Sdim    ModuleSP exe_module_sp(target_sp->GetExecutableModule());
310296417Sdim    if (exe_module_sp.get())
311296417Sdim        return exe_module_sp->GetFileSpec().Exists();
312296417Sdim    // If there is no executable module, we return true since we might be preparing to attach.
313296417Sdim    return true;
314296417Sdim}
315296417Sdim
316296417SdimError
317296417SdimProcessFreeBSD::DoAttachToProcessWithID (lldb::pid_t pid,  const ProcessAttachInfo &attach_info)
318296417Sdim{
319296417Sdim    Error error;
320296417Sdim    assert(m_monitor == NULL);
321296417Sdim
322296417Sdim    Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_PROCESS));
323296417Sdim    if (log && log->GetMask().Test(POSIX_LOG_VERBOSE))
324296417Sdim        log->Printf ("ProcessFreeBSD::%s(pid = %" PRIi64 ")", __FUNCTION__, GetID());
325296417Sdim
326296417Sdim    m_monitor = new ProcessMonitor(this, pid, error);
327296417Sdim
328296417Sdim    if (!error.Success())
329296417Sdim        return error;
330296417Sdim
331296417Sdim    PlatformSP platform_sp (GetTarget().GetPlatform ());
332296417Sdim    assert (platform_sp.get());
333296417Sdim    if (!platform_sp)
334296417Sdim        return error;  // FIXME: Detatch?
335296417Sdim
336296417Sdim    // Find out what we can about this process
337296417Sdim    ProcessInstanceInfo process_info;
338296417Sdim    platform_sp->GetProcessInfo (pid, process_info);
339296417Sdim
340296417Sdim    // Resolve the executable module
341296417Sdim    ModuleSP exe_module_sp;
342296417Sdim    FileSpecList executable_search_paths (Target::GetDefaultExecutableSearchPaths());
343296417Sdim    ModuleSpec exe_module_spec(process_info.GetExecutableFile(), GetTarget().GetArchitecture());
344296417Sdim    error = platform_sp->ResolveExecutable(exe_module_spec,
345296417Sdim                                           exe_module_sp,
346296417Sdim                                           executable_search_paths.GetSize() ? &executable_search_paths : NULL);
347296417Sdim    if (!error.Success())
348296417Sdim        return error;
349296417Sdim
350296417Sdim    // Fix the target architecture if necessary
351296417Sdim    const ArchSpec &module_arch = exe_module_sp->GetArchitecture();
352296417Sdim    if (module_arch.IsValid() && !GetTarget().GetArchitecture().IsExactMatch(module_arch))
353296417Sdim        GetTarget().SetArchitecture(module_arch);
354296417Sdim
355296417Sdim    // Initialize the target module list
356296417Sdim    GetTarget().SetExecutableModule (exe_module_sp, true);
357296417Sdim
358296417Sdim    SetSTDIOFileDescriptor(m_monitor->GetTerminalFD());
359296417Sdim
360296417Sdim    SetID(pid);
361296417Sdim
362296417Sdim    return error;
363296417Sdim}
364296417Sdim
365296417SdimError
366296417SdimProcessFreeBSD::WillLaunch(Module* module)
367296417Sdim{
368296417Sdim    Error error;
369296417Sdim    return error;
370296417Sdim}
371296417Sdim
372296417SdimFileSpec
373296417SdimProcessFreeBSD::GetFileSpec(const lldb_private::FileAction *file_action,
374296417Sdim                          const FileSpec &default_file_spec,
375296417Sdim                          const FileSpec &dbg_pts_file_spec)
376296417Sdim{
377296417Sdim    FileSpec file_spec{};
378296417Sdim
379296417Sdim    if (file_action && file_action->GetAction() == FileAction::eFileActionOpen)
380296417Sdim    {
381296417Sdim        file_spec = file_action->GetFileSpec();
382296417Sdim        // By default the stdio paths passed in will be pseudo-terminal
383296417Sdim        // (/dev/pts). If so, convert to using a different default path
384296417Sdim        // instead to redirect I/O to the debugger console. This should
385296417Sdim        // also handle user overrides to /dev/null or a different file.
386296417Sdim        if (!file_spec || file_spec == dbg_pts_file_spec)
387296417Sdim            file_spec = default_file_spec;
388296417Sdim    }
389296417Sdim    return file_spec;
390296417Sdim}
391296417Sdim
392296417SdimError
393296417SdimProcessFreeBSD::DoLaunch (Module *module,
394296417Sdim                        ProcessLaunchInfo &launch_info)
395296417Sdim{
396296417Sdim    Error error;
397296417Sdim    assert(m_monitor == NULL);
398296417Sdim
399296417Sdim    FileSpec working_dir = launch_info.GetWorkingDirectory();
400296417Sdim    if (working_dir &&
401296417Sdim            (!working_dir.ResolvePath() ||
402296417Sdim             working_dir.GetFileType() != FileSpec::eFileTypeDirectory))
403296417Sdim    {
404296417Sdim        error.SetErrorStringWithFormat("No such file or directory: %s",
405296417Sdim                working_dir.GetCString());
406296417Sdim        return error;
407296417Sdim    }
408296417Sdim
409296417Sdim    SetPrivateState(eStateLaunching);
410296417Sdim
411296417Sdim    const lldb_private::FileAction *file_action;
412296417Sdim
413296417Sdim    // Default of empty will mean to use existing open file descriptors
414296417Sdim    FileSpec stdin_file_spec{};
415296417Sdim    FileSpec stdout_file_spec{};
416296417Sdim    FileSpec stderr_file_spec{};
417296417Sdim
418296417Sdim    const FileSpec dbg_pts_file_spec{launch_info.GetPTY().GetSlaveName(NULL,0), false};
419296417Sdim
420296417Sdim    file_action = launch_info.GetFileActionForFD (STDIN_FILENO);
421296417Sdim    stdin_file_spec = GetFileSpec(file_action, stdin_file_spec, dbg_pts_file_spec);
422296417Sdim
423296417Sdim    file_action = launch_info.GetFileActionForFD (STDOUT_FILENO);
424296417Sdim    stdout_file_spec = GetFileSpec(file_action, stdout_file_spec, dbg_pts_file_spec);
425296417Sdim
426296417Sdim    file_action = launch_info.GetFileActionForFD (STDERR_FILENO);
427296417Sdim    stderr_file_spec = GetFileSpec(file_action, stderr_file_spec, dbg_pts_file_spec);
428296417Sdim
429296417Sdim    m_monitor = new ProcessMonitor(this,
430296417Sdim                                   module,
431296417Sdim                                   launch_info.GetArguments().GetConstArgumentVector(),
432296417Sdim                                   launch_info.GetEnvironmentEntries().GetConstArgumentVector(),
433296417Sdim                                   stdin_file_spec,
434296417Sdim                                   stdout_file_spec,
435296417Sdim                                   stderr_file_spec,
436296417Sdim                                   working_dir,
437296417Sdim                                   launch_info,
438296417Sdim                                   error);
439296417Sdim
440296417Sdim    m_module = module;
441296417Sdim
442296417Sdim    if (!error.Success())
443296417Sdim        return error;
444296417Sdim
445296417Sdim    int terminal = m_monitor->GetTerminalFD();
446296417Sdim    if (terminal >= 0) {
447296417Sdim        // The reader thread will close the file descriptor when done, so we pass it a copy.
448296417Sdim#ifdef F_DUPFD_CLOEXEC
449296417Sdim        int stdio = fcntl(terminal, F_DUPFD_CLOEXEC, 0);
450296417Sdim        if (stdio == -1) {
451296417Sdim            error.SetErrorToErrno();
452296417Sdim            return error;
453296417Sdim        }
454296417Sdim#else
455296417Sdim        // Special case when F_DUPFD_CLOEXEC does not exist (Debian kFreeBSD)
456296417Sdim        int stdio = fcntl(terminal, F_DUPFD, 0);
457296417Sdim        if (stdio == -1) {
458296417Sdim            error.SetErrorToErrno();
459296417Sdim            return error;
460296417Sdim        }
461296417Sdim        stdio = fcntl(terminal, F_SETFD, FD_CLOEXEC);
462296417Sdim        if (stdio == -1) {
463296417Sdim            error.SetErrorToErrno();
464296417Sdim            return error;
465296417Sdim        }
466296417Sdim#endif
467296417Sdim        SetSTDIOFileDescriptor(stdio);
468296417Sdim    }
469296417Sdim
470296417Sdim    SetID(m_monitor->GetPID());
471296417Sdim    return error;
472296417Sdim}
473296417Sdim
474296417Sdimvoid
475296417SdimProcessFreeBSD::DidLaunch()
476296417Sdim{
477296417Sdim}
478296417Sdim
479296417Sdimaddr_t
480296417SdimProcessFreeBSD::GetImageInfoAddress()
481296417Sdim{
482296417Sdim    Target *target = &GetTarget();
483296417Sdim    ObjectFile *obj_file = target->GetExecutableModule()->GetObjectFile();
484296417Sdim    Address addr = obj_file->GetImageInfoAddress(target);
485296417Sdim
486296417Sdim    if (addr.IsValid())
487296417Sdim        return addr.GetLoadAddress(target);
488296417Sdim    return LLDB_INVALID_ADDRESS;
489296417Sdim}
490296417Sdim
491296417SdimError
492296417SdimProcessFreeBSD::DoHalt(bool &caused_stop)
493296417Sdim{
494296417Sdim    Error error;
495296417Sdim
496296417Sdim    if (IsStopped())
497296417Sdim    {
498296417Sdim        caused_stop = false;
499296417Sdim    }
500296417Sdim    else if (kill(GetID(), SIGSTOP))
501296417Sdim    {
502296417Sdim        caused_stop = false;
503296417Sdim        error.SetErrorToErrno();
504296417Sdim    }
505296417Sdim    else
506296417Sdim    {
507296417Sdim        caused_stop = true;
508296417Sdim    }
509296417Sdim    return error;
510296417Sdim}
511296417Sdim
512296417SdimError
513296417SdimProcessFreeBSD::DoSignal(int signal)
514296417Sdim{
515296417Sdim    Error error;
516296417Sdim
517296417Sdim    if (kill(GetID(), signal))
518296417Sdim        error.SetErrorToErrno();
519296417Sdim
520296417Sdim    return error;
521296417Sdim}
522296417Sdim
523296417SdimError
524296417SdimProcessFreeBSD::DoDestroy()
525296417Sdim{
526296417Sdim    Error error;
527296417Sdim
528296417Sdim    if (!HasExited())
529296417Sdim    {
530296417Sdim        assert(m_monitor);
531296417Sdim        m_exit_now = true;
532296417Sdim        if (GetID() == LLDB_INVALID_PROCESS_ID)
533296417Sdim        {
534296417Sdim            error.SetErrorString("invalid process id");
535296417Sdim            return error;
536296417Sdim        }
537296417Sdim        if (!m_monitor->Kill())
538296417Sdim        {
539296417Sdim            error.SetErrorToErrno();
540296417Sdim            return error;
541296417Sdim        }
542296417Sdim
543296417Sdim        SetPrivateState(eStateExited);
544296417Sdim    }
545296417Sdim
546296417Sdim    return error;
547296417Sdim}
548296417Sdim
549296417Sdimvoid
550296417SdimProcessFreeBSD::DoDidExec()
551296417Sdim{
552296417Sdim    Target *target = &GetTarget();
553296417Sdim    if (target)
554296417Sdim    {
555296417Sdim        PlatformSP platform_sp (target->GetPlatform());
556296417Sdim        assert (platform_sp.get());
557296417Sdim        if (platform_sp)
558296417Sdim        {
559296417Sdim            ProcessInstanceInfo process_info;
560296417Sdim            platform_sp->GetProcessInfo(GetID(), process_info);
561296417Sdim            ModuleSP exe_module_sp;
562296417Sdim            ModuleSpec exe_module_spec(process_info.GetExecutableFile(), target->GetArchitecture());
563296417Sdim            FileSpecList executable_search_paths (Target::GetDefaultExecutableSearchPaths());
564296417Sdim            Error error = platform_sp->ResolveExecutable(exe_module_spec,
565296417Sdim                                                         exe_module_sp,
566296417Sdim                                                         executable_search_paths.GetSize() ? &executable_search_paths : NULL);
567296417Sdim            if (!error.Success())
568296417Sdim                return;
569296417Sdim            target->SetExecutableModule(exe_module_sp, true);
570296417Sdim        }
571296417Sdim    }
572296417Sdim}
573296417Sdim
574296417Sdimbool
575296417SdimProcessFreeBSD::AddThreadForInitialStopIfNeeded(lldb::tid_t stop_tid)
576296417Sdim{
577296417Sdim    bool added_to_set = false;
578296417Sdim    ThreadStopSet::iterator it = m_seen_initial_stop.find(stop_tid);
579296417Sdim    if (it == m_seen_initial_stop.end())
580296417Sdim    {
581296417Sdim        m_seen_initial_stop.insert(stop_tid);
582296417Sdim        added_to_set = true;
583296417Sdim    }
584296417Sdim    return added_to_set;
585296417Sdim}
586296417Sdim
587296417Sdimbool
588296417SdimProcessFreeBSD::WaitingForInitialStop(lldb::tid_t stop_tid)
589296417Sdim{
590296417Sdim    return (m_seen_initial_stop.find(stop_tid) == m_seen_initial_stop.end());
591296417Sdim}
592296417Sdim
593296417SdimFreeBSDThread *
594296417SdimProcessFreeBSD::CreateNewFreeBSDThread(lldb_private::Process &process, lldb::tid_t tid)
595296417Sdim{
596296417Sdim    return new FreeBSDThread(process, tid);
597296417Sdim}
598296417Sdim
599296417Sdimvoid
600296417SdimProcessFreeBSD::RefreshStateAfterStop()
601296417Sdim{
602296417Sdim    Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_PROCESS));
603296417Sdim    if (log && log->GetMask().Test(POSIX_LOG_VERBOSE))
604296417Sdim        log->Printf ("ProcessFreeBSD::%s(), message_queue size = %d", __FUNCTION__, (int)m_message_queue.size());
605296417Sdim
606296417Sdim    Mutex::Locker lock(m_message_mutex);
607296417Sdim
608296417Sdim    // This method used to only handle one message.  Changing it to loop allows
609296417Sdim    // it to handle the case where we hit a breakpoint while handling a different
610296417Sdim    // breakpoint.
611296417Sdim    while (!m_message_queue.empty())
612296417Sdim    {
613296417Sdim        ProcessMessage &message = m_message_queue.front();
614296417Sdim
615296417Sdim        // Resolve the thread this message corresponds to and pass it along.
616296417Sdim        lldb::tid_t tid = message.GetTID();
617296417Sdim        if (log)
618296417Sdim            log->Printf ("ProcessFreeBSD::%s(), message_queue size = %d, pid = %" PRIi64, __FUNCTION__, (int)m_message_queue.size(), tid);
619296417Sdim
620296417Sdim        m_thread_list.RefreshStateAfterStop();
621296417Sdim
622296417Sdim        FreeBSDThread *thread = static_cast<FreeBSDThread*>(
623296417Sdim            GetThreadList().FindThreadByID(tid, false).get());
624296417Sdim        if (thread)
625296417Sdim            thread->Notify(message);
626296417Sdim
627296417Sdim        if (message.GetKind() == ProcessMessage::eExitMessage)
628296417Sdim        {
629296417Sdim            // FIXME: We should tell the user about this, but the limbo message is probably better for that.
630296417Sdim            if (log)
631296417Sdim                log->Printf ("ProcessFreeBSD::%s() removing thread, tid = %" PRIi64, __FUNCTION__, tid);
632296417Sdim
633296417Sdim            Mutex::Locker lock(m_thread_list.GetMutex());
634296417Sdim
635296417Sdim            ThreadSP thread_sp = m_thread_list.RemoveThreadByID(tid, false);
636296417Sdim            thread_sp.reset();
637296417Sdim            m_seen_initial_stop.erase(tid);
638296417Sdim        }
639296417Sdim
640296417Sdim        m_message_queue.pop();
641296417Sdim    }
642296417Sdim}
643296417Sdim
644296417Sdimbool
645296417SdimProcessFreeBSD::IsAlive()
646296417Sdim{
647296417Sdim    StateType state = GetPrivateState();
648296417Sdim    return state != eStateDetached
649296417Sdim        && state != eStateExited
650296417Sdim        && state != eStateInvalid
651296417Sdim        && state != eStateUnloaded;
652296417Sdim}
653296417Sdim
654296417Sdimsize_t
655296417SdimProcessFreeBSD::DoReadMemory(addr_t vm_addr,
656296417Sdim                           void *buf, size_t size, Error &error)
657296417Sdim{
658296417Sdim    assert(m_monitor);
659296417Sdim    return m_monitor->ReadMemory(vm_addr, buf, size, error);
660296417Sdim}
661296417Sdim
662296417Sdimsize_t
663296417SdimProcessFreeBSD::DoWriteMemory(addr_t vm_addr, const void *buf, size_t size,
664296417Sdim                            Error &error)
665296417Sdim{
666296417Sdim    assert(m_monitor);
667296417Sdim    return m_monitor->WriteMemory(vm_addr, buf, size, error);
668296417Sdim}
669296417Sdim
670296417Sdimaddr_t
671296417SdimProcessFreeBSD::DoAllocateMemory(size_t size, uint32_t permissions,
672296417Sdim                               Error &error)
673296417Sdim{
674296417Sdim    addr_t allocated_addr = LLDB_INVALID_ADDRESS;
675296417Sdim
676296417Sdim    unsigned prot = 0;
677296417Sdim    if (permissions & lldb::ePermissionsReadable)
678296417Sdim        prot |= eMmapProtRead;
679296417Sdim    if (permissions & lldb::ePermissionsWritable)
680296417Sdim        prot |= eMmapProtWrite;
681296417Sdim    if (permissions & lldb::ePermissionsExecutable)
682296417Sdim        prot |= eMmapProtExec;
683296417Sdim
684296417Sdim    if (InferiorCallMmap(this, allocated_addr, 0, size, prot,
685296417Sdim                         eMmapFlagsAnon | eMmapFlagsPrivate, -1, 0)) {
686296417Sdim        m_addr_to_mmap_size[allocated_addr] = size;
687296417Sdim        error.Clear();
688296417Sdim    } else {
689296417Sdim        allocated_addr = LLDB_INVALID_ADDRESS;
690296417Sdim        error.SetErrorStringWithFormat("unable to allocate %zu bytes of memory with permissions %s", size, GetPermissionsAsCString (permissions));
691296417Sdim    }
692296417Sdim
693296417Sdim    return allocated_addr;
694296417Sdim}
695296417Sdim
696296417SdimError
697296417SdimProcessFreeBSD::DoDeallocateMemory(lldb::addr_t addr)
698296417Sdim{
699296417Sdim    Error error;
700296417Sdim    MMapMap::iterator pos = m_addr_to_mmap_size.find(addr);
701296417Sdim    if (pos != m_addr_to_mmap_size.end() &&
702296417Sdim        InferiorCallMunmap(this, addr, pos->second))
703296417Sdim        m_addr_to_mmap_size.erase (pos);
704296417Sdim    else
705296417Sdim        error.SetErrorStringWithFormat("unable to deallocate memory at 0x%" PRIx64, addr);
706296417Sdim
707296417Sdim    return error;
708296417Sdim}
709296417Sdim
710296417Sdimsize_t
711296417SdimProcessFreeBSD::GetSoftwareBreakpointTrapOpcode(BreakpointSite* bp_site)
712296417Sdim{
713296417Sdim    static const uint8_t g_aarch64_opcode[] = { 0x00, 0x00, 0x20, 0xD4 };
714296417Sdim    static const uint8_t g_i386_opcode[] = { 0xCC };
715296417Sdim
716296417Sdim    ArchSpec arch = GetTarget().GetArchitecture();
717296417Sdim    const uint8_t *opcode = NULL;
718296417Sdim    size_t opcode_size = 0;
719296417Sdim
720296417Sdim    switch (arch.GetMachine())
721296417Sdim    {
722296417Sdim    default:
723296417Sdim        assert(false && "CPU type not supported!");
724296417Sdim        break;
725296417Sdim
726296417Sdim    case llvm::Triple::arm:
727296417Sdim        {
728296417Sdim            // The ARM reference recommends the use of 0xe7fddefe and 0xdefe
729296417Sdim            // but the linux kernel does otherwise.
730296417Sdim            static const uint8_t g_arm_breakpoint_opcode[] = { 0xf0, 0x01, 0xf0, 0xe7 };
731296417Sdim            static const uint8_t g_thumb_breakpoint_opcode[] = { 0x01, 0xde };
732296417Sdim
733296417Sdim            lldb::BreakpointLocationSP bp_loc_sp (bp_site->GetOwnerAtIndex (0));
734296417Sdim            AddressClass addr_class = eAddressClassUnknown;
735296417Sdim
736296417Sdim            if (bp_loc_sp)
737296417Sdim                addr_class = bp_loc_sp->GetAddress ().GetAddressClass ();
738296417Sdim
739296417Sdim            if (addr_class == eAddressClassCodeAlternateISA
740296417Sdim                || (addr_class == eAddressClassUnknown
741296417Sdim                    && bp_loc_sp->GetAddress().GetOffset() & 1))
742296417Sdim            {
743296417Sdim                opcode = g_thumb_breakpoint_opcode;
744296417Sdim                opcode_size = sizeof(g_thumb_breakpoint_opcode);
745296417Sdim            }
746296417Sdim            else
747296417Sdim            {
748296417Sdim                opcode = g_arm_breakpoint_opcode;
749296417Sdim                opcode_size = sizeof(g_arm_breakpoint_opcode);
750296417Sdim            }
751296417Sdim        }
752296417Sdim        break;
753296417Sdim    case llvm::Triple::aarch64:
754296417Sdim        opcode = g_aarch64_opcode;
755296417Sdim        opcode_size = sizeof(g_aarch64_opcode);
756296417Sdim        break;
757296417Sdim
758296417Sdim    case llvm::Triple::x86:
759296417Sdim    case llvm::Triple::x86_64:
760296417Sdim        opcode = g_i386_opcode;
761296417Sdim        opcode_size = sizeof(g_i386_opcode);
762296417Sdim        break;
763296417Sdim    }
764296417Sdim
765296417Sdim    bp_site->SetTrapOpcode(opcode, opcode_size);
766296417Sdim    return opcode_size;
767296417Sdim}
768296417Sdim
769296417SdimError
770296417SdimProcessFreeBSD::EnableBreakpointSite(BreakpointSite *bp_site)
771296417Sdim{
772296417Sdim    return EnableSoftwareBreakpoint(bp_site);
773296417Sdim}
774296417Sdim
775296417SdimError
776296417SdimProcessFreeBSD::DisableBreakpointSite(BreakpointSite *bp_site)
777296417Sdim{
778296417Sdim    return DisableSoftwareBreakpoint(bp_site);
779296417Sdim}
780296417Sdim
781296417SdimError
782296417SdimProcessFreeBSD::EnableWatchpoint(Watchpoint *wp, bool notify)
783296417Sdim{
784296417Sdim    Error error;
785296417Sdim    if (wp)
786296417Sdim    {
787296417Sdim        user_id_t watchID = wp->GetID();
788296417Sdim        addr_t addr = wp->GetLoadAddress();
789296417Sdim        Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_WATCHPOINTS));
790296417Sdim        if (log)
791296417Sdim            log->Printf ("ProcessFreeBSD::EnableWatchpoint(watchID = %" PRIu64 ")",
792296417Sdim                         watchID);
793296417Sdim        if (wp->IsEnabled())
794296417Sdim        {
795296417Sdim            if (log)
796296417Sdim                log->Printf("ProcessFreeBSD::EnableWatchpoint(watchID = %" PRIu64
797296417Sdim                            ") addr = 0x%8.8" PRIx64 ": watchpoint already enabled.",
798296417Sdim                            watchID, (uint64_t)addr);
799296417Sdim            return error;
800296417Sdim        }
801296417Sdim
802296417Sdim        // Try to find a vacant watchpoint slot in the inferiors' main thread
803296417Sdim        uint32_t wp_hw_index = LLDB_INVALID_INDEX32;
804296417Sdim        Mutex::Locker lock(m_thread_list.GetMutex());
805296417Sdim        FreeBSDThread *thread = static_cast<FreeBSDThread*>(
806296417Sdim                               m_thread_list.GetThreadAtIndex(0, false).get());
807296417Sdim
808296417Sdim        if (thread)
809296417Sdim            wp_hw_index = thread->FindVacantWatchpointIndex();
810296417Sdim
811296417Sdim        if (wp_hw_index == LLDB_INVALID_INDEX32)
812296417Sdim        {
813296417Sdim            error.SetErrorString("Setting hardware watchpoint failed.");
814296417Sdim        }
815296417Sdim        else
816296417Sdim        {
817296417Sdim            wp->SetHardwareIndex(wp_hw_index);
818296417Sdim            bool wp_enabled = true;
819296417Sdim            uint32_t thread_count = m_thread_list.GetSize(false);
820296417Sdim            for (uint32_t i = 0; i < thread_count; ++i)
821296417Sdim            {
822296417Sdim                thread = static_cast<FreeBSDThread*>(
823296417Sdim                         m_thread_list.GetThreadAtIndex(i, false).get());
824296417Sdim                if (thread)
825296417Sdim                    wp_enabled &= thread->EnableHardwareWatchpoint(wp);
826296417Sdim                else
827296417Sdim                    wp_enabled = false;
828296417Sdim            }
829296417Sdim            if (wp_enabled)
830296417Sdim            {
831296417Sdim                wp->SetEnabled(true, notify);
832296417Sdim                return error;
833296417Sdim            }
834296417Sdim            else
835296417Sdim            {
836296417Sdim                // Watchpoint enabling failed on at least one
837296417Sdim                // of the threads so roll back all of them
838296417Sdim                DisableWatchpoint(wp, false);
839296417Sdim                error.SetErrorString("Setting hardware watchpoint failed");
840296417Sdim            }
841296417Sdim        }
842296417Sdim    }
843296417Sdim    else
844296417Sdim        error.SetErrorString("Watchpoint argument was NULL.");
845296417Sdim    return error;
846296417Sdim}
847296417Sdim
848296417SdimError
849296417SdimProcessFreeBSD::DisableWatchpoint(Watchpoint *wp, bool notify)
850296417Sdim{
851296417Sdim    Error error;
852296417Sdim    if (wp)
853296417Sdim    {
854296417Sdim        user_id_t watchID = wp->GetID();
855296417Sdim        addr_t addr = wp->GetLoadAddress();
856296417Sdim        Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_WATCHPOINTS));
857296417Sdim        if (log)
858296417Sdim            log->Printf("ProcessFreeBSD::DisableWatchpoint(watchID = %" PRIu64 ")",
859296417Sdim                        watchID);
860296417Sdim        if (!wp->IsEnabled())
861296417Sdim        {
862296417Sdim            if (log)
863296417Sdim                log->Printf("ProcessFreeBSD::DisableWatchpoint(watchID = %" PRIu64
864296417Sdim                            ") addr = 0x%8.8" PRIx64 ": watchpoint already disabled.",
865296417Sdim                            watchID, (uint64_t)addr);
866296417Sdim            // This is needed (for now) to keep watchpoints disabled correctly
867296417Sdim            wp->SetEnabled(false, notify);
868296417Sdim            return error;
869296417Sdim        }
870296417Sdim
871296417Sdim        if (wp->IsHardware())
872296417Sdim        {
873296417Sdim            bool wp_disabled = true;
874296417Sdim            Mutex::Locker lock(m_thread_list.GetMutex());
875296417Sdim            uint32_t thread_count = m_thread_list.GetSize(false);
876296417Sdim            for (uint32_t i = 0; i < thread_count; ++i)
877296417Sdim            {
878296417Sdim                FreeBSDThread *thread = static_cast<FreeBSDThread*>(
879296417Sdim                                      m_thread_list.GetThreadAtIndex(i, false).get());
880296417Sdim                if (thread)
881296417Sdim                    wp_disabled &= thread->DisableHardwareWatchpoint(wp);
882296417Sdim                else
883296417Sdim                    wp_disabled = false;
884296417Sdim            }
885296417Sdim            if (wp_disabled)
886296417Sdim            {
887296417Sdim                wp->SetHardwareIndex(LLDB_INVALID_INDEX32);
888296417Sdim                wp->SetEnabled(false, notify);
889296417Sdim                return error;
890296417Sdim            }
891296417Sdim            else
892296417Sdim                error.SetErrorString("Disabling hardware watchpoint failed");
893296417Sdim        }
894296417Sdim    }
895296417Sdim    else
896296417Sdim        error.SetErrorString("Watchpoint argument was NULL.");
897296417Sdim    return error;
898296417Sdim}
899296417Sdim
900296417SdimError
901296417SdimProcessFreeBSD::GetWatchpointSupportInfo(uint32_t &num)
902296417Sdim{
903296417Sdim    Error error;
904296417Sdim    Mutex::Locker lock(m_thread_list.GetMutex());
905296417Sdim    FreeBSDThread *thread = static_cast<FreeBSDThread*>(
906296417Sdim                          m_thread_list.GetThreadAtIndex(0, false).get());
907296417Sdim    if (thread)
908296417Sdim        num = thread->NumSupportedHardwareWatchpoints();
909296417Sdim    else
910296417Sdim        error.SetErrorString("Process does not exist.");
911296417Sdim    return error;
912296417Sdim}
913296417Sdim
914296417SdimError
915296417SdimProcessFreeBSD::GetWatchpointSupportInfo(uint32_t &num, bool &after)
916296417Sdim{
917296417Sdim    Error error = GetWatchpointSupportInfo(num);
918296417Sdim    // Watchpoints trigger and halt the inferior after
919296417Sdim    // the corresponding instruction has been executed.
920296417Sdim    after = true;
921296417Sdim    return error;
922296417Sdim}
923296417Sdim
924296417Sdimuint32_t
925296417SdimProcessFreeBSD::UpdateThreadListIfNeeded()
926296417Sdim{
927296417Sdim    Mutex::Locker lock(m_thread_list.GetMutex());
928296417Sdim    // Do not allow recursive updates.
929296417Sdim    return m_thread_list.GetSize(false);
930296417Sdim}
931296417Sdim
932296417Sdim#if 0
933296417Sdimbool
934296417SdimProcessFreeBSD::UpdateThreadList(ThreadList &old_thread_list, ThreadList &new_thread_list)
935296417Sdim{
936296417Sdim    Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_THREAD));
937296417Sdim    if (log && log->GetMask().Test(POSIX_LOG_VERBOSE))
938296417Sdim        log->Printf ("ProcessFreeBSD::%s() (pid = %" PRIi64 ")", __FUNCTION__, GetID());
939296417Sdim
940296417Sdim    bool has_updated = false;
941296417Sdim    // Update the process thread list with this new thread.
942296417Sdim    // FIXME: We should be using tid, not pid.
943296417Sdim    assert(m_monitor);
944296417Sdim    ThreadSP thread_sp (old_thread_list.FindThreadByID (GetID(), false));
945296417Sdim    if (!thread_sp) {
946296417Sdim        thread_sp.reset(CreateNewFreeBSDThread(*this, GetID()));
947296417Sdim        has_updated = true;
948296417Sdim    }
949296417Sdim
950296417Sdim    if (log && log->GetMask().Test(POSIX_LOG_VERBOSE))
951296417Sdim        log->Printf ("ProcessFreeBSD::%s() updated pid = %" PRIi64, __FUNCTION__, GetID());
952296417Sdim    new_thread_list.AddThread(thread_sp);
953296417Sdim
954296417Sdim    return has_updated; // the list has been updated
955296417Sdim}
956296417Sdim#endif
957296417Sdim
958296417SdimByteOrder
959296417SdimProcessFreeBSD::GetByteOrder() const
960296417Sdim{
961296417Sdim    // FIXME: We should be able to extract this value directly.  See comment in
962296417Sdim    // ProcessFreeBSD().
963296417Sdim    return m_byte_order;
964296417Sdim}
965296417Sdim
966296417Sdimsize_t
967296417SdimProcessFreeBSD::PutSTDIN(const char *buf, size_t len, Error &error)
968296417Sdim{
969296417Sdim    ssize_t status;
970296417Sdim    if ((status = write(m_monitor->GetTerminalFD(), buf, len)) < 0)
971296417Sdim    {
972296417Sdim        error.SetErrorToErrno();
973296417Sdim        return 0;
974296417Sdim    }
975296417Sdim    return status;
976296417Sdim}
977296417Sdim
978296417Sdim//------------------------------------------------------------------------------
979296417Sdim// Utility functions.
980296417Sdim
981296417Sdimbool
982296417SdimProcessFreeBSD::HasExited()
983296417Sdim{
984296417Sdim    switch (GetPrivateState())
985296417Sdim    {
986296417Sdim    default:
987296417Sdim        break;
988296417Sdim
989296417Sdim    case eStateDetached:
990296417Sdim    case eStateExited:
991296417Sdim        return true;
992296417Sdim    }
993296417Sdim
994296417Sdim    return false;
995296417Sdim}
996296417Sdim
997296417Sdimbool
998296417SdimProcessFreeBSD::IsStopped()
999296417Sdim{
1000296417Sdim    switch (GetPrivateState())
1001296417Sdim    {
1002296417Sdim    default:
1003296417Sdim        break;
1004296417Sdim
1005296417Sdim    case eStateStopped:
1006296417Sdim    case eStateCrashed:
1007296417Sdim    case eStateSuspended:
1008296417Sdim        return true;
1009296417Sdim    }
1010296417Sdim
1011296417Sdim    return false;
1012296417Sdim}
1013296417Sdim
1014296417Sdimbool
1015296417SdimProcessFreeBSD::IsAThreadRunning()
1016296417Sdim{
1017296417Sdim    bool is_running = false;
1018296417Sdim    Mutex::Locker lock(m_thread_list.GetMutex());
1019296417Sdim    uint32_t thread_count = m_thread_list.GetSize(false);
1020296417Sdim    for (uint32_t i = 0; i < thread_count; ++i)
1021296417Sdim    {
1022296417Sdim        FreeBSDThread *thread = static_cast<FreeBSDThread*>(
1023296417Sdim            m_thread_list.GetThreadAtIndex(i, false).get());
1024296417Sdim        StateType thread_state = thread->GetState();
1025296417Sdim        if (thread_state == eStateRunning || thread_state == eStateStepping)
1026296417Sdim        {
1027296417Sdim            is_running = true;
1028296417Sdim            break;
1029296417Sdim        }
1030296417Sdim    }
1031296417Sdim    return is_running;
1032296417Sdim}
1033296417Sdim
1034296417Sdimconst DataBufferSP
1035296417SdimProcessFreeBSD::GetAuxvData ()
1036296417Sdim{
1037296417Sdim    // If we're the local platform, we can ask the host for auxv data.
1038296417Sdim    PlatformSP platform_sp = GetTarget().GetPlatform ();
1039296417Sdim    if (platform_sp && platform_sp->IsHost ())
1040296417Sdim        return lldb_private::Host::GetAuxvData(this);
1041296417Sdim
1042296417Sdim    // Somewhat unexpected - the process is not running locally or we don't have a platform.
1043296417Sdim    assert (false && "no platform or not the host - how did we get here with ProcessFreeBSD?");
1044296417Sdim    return DataBufferSP ();
1045296417Sdim}
1046