1254721Semaste//===-- PlatformFreeBSD.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#include "lldb/lldb-python.h"
11254721Semaste
12254721Semaste#include "PlatformFreeBSD.h"
13254721Semaste
14254721Semaste// C Includes
15254721Semaste#include <stdio.h>
16254721Semaste#include <sys/utsname.h>
17254721Semaste
18254721Semaste// C++ Includes
19254721Semaste// Other libraries and framework includes
20254721Semaste// Project includes
21254721Semaste#include "lldb/Core/Error.h"
22254721Semaste#include "lldb/Core/Debugger.h"
23254721Semaste#include "lldb/Core/Module.h"
24254721Semaste#include "lldb/Core/ModuleSpec.h"
25254721Semaste#include "lldb/Core/PluginManager.h"
26254721Semaste#include "lldb/Host/Host.h"
27254721Semaste
28254721Semasteusing namespace lldb;
29254721Semasteusing namespace lldb_private;
30254721Semaste
31254721SemastePlatform *
32254721SemastePlatformFreeBSD::CreateInstance (bool force, const lldb_private::ArchSpec *arch)
33254721Semaste{
34254721Semaste    // The only time we create an instance is when we are creating a remote
35254721Semaste    // freebsd platform
36254721Semaste    const bool is_host = false;
37254721Semaste
38254721Semaste    bool create = force;
39254721Semaste    if (create == false && arch && arch->IsValid())
40254721Semaste    {
41254721Semaste        const llvm::Triple &triple = arch->GetTriple();
42254721Semaste        switch (triple.getVendor())
43254721Semaste        {
44254721Semaste            case llvm::Triple::PC:
45254721Semaste                create = true;
46254721Semaste                break;
47254721Semaste
48254721Semaste#if defined(__FreeBSD__) || defined(__OpenBSD__)
49254721Semaste            // Only accept "unknown" for the vendor if the host is BSD and
50254721Semaste            // it "unknown" wasn't specified (it was just returned becasue it
51254721Semaste            // was NOT specified)
52254721Semaste            case llvm::Triple::UnknownArch:
53254721Semaste                create = !arch->TripleVendorWasSpecified();
54254721Semaste                break;
55254721Semaste#endif
56254721Semaste            default:
57254721Semaste                break;
58254721Semaste        }
59254721Semaste
60254721Semaste        if (create)
61254721Semaste        {
62254721Semaste            switch (triple.getOS())
63254721Semaste            {
64254721Semaste                case llvm::Triple::FreeBSD:
65254721Semaste                case llvm::Triple::KFreeBSD:
66254721Semaste                    break;
67254721Semaste
68254721Semaste#if defined(__FreeBSD__) || defined(__OpenBSD__)
69254721Semaste                // Only accept "unknown" for the OS if the host is BSD and
70254721Semaste                // it "unknown" wasn't specified (it was just returned becasue it
71254721Semaste                // was NOT specified)
72254721Semaste                case llvm::Triple::UnknownOS:
73254721Semaste                    create = arch->TripleOSWasSpecified();
74254721Semaste                    break;
75254721Semaste#endif
76254721Semaste                default:
77254721Semaste                    create = false;
78254721Semaste                    break;
79254721Semaste            }
80254721Semaste        }
81254721Semaste    }
82254721Semaste    if (create)
83254721Semaste        return new PlatformFreeBSD (is_host);
84254721Semaste    return NULL;
85254721Semaste
86254721Semaste}
87254721Semaste
88254721Semastelldb_private::ConstString
89254721SemastePlatformFreeBSD::GetPluginNameStatic (bool is_host)
90254721Semaste{
91254721Semaste    if (is_host)
92254721Semaste    {
93254721Semaste        static ConstString g_host_name(Platform::GetHostPlatformName ());
94254721Semaste        return g_host_name;
95254721Semaste    }
96254721Semaste    else
97254721Semaste    {
98254721Semaste        static ConstString g_remote_name("remote-freebsd");
99254721Semaste        return g_remote_name;
100254721Semaste    }
101254721Semaste}
102254721Semaste
103254721Semasteconst char *
104254721SemastePlatformFreeBSD::GetDescriptionStatic (bool is_host)
105254721Semaste{
106254721Semaste    if (is_host)
107254721Semaste        return "Local FreeBSD user platform plug-in.";
108254721Semaste    else
109254721Semaste        return "Remote FreeBSD user platform plug-in.";
110254721Semaste}
111254721Semaste
112254721Semastestatic uint32_t g_initialize_count = 0;
113254721Semaste
114254721Semastevoid
115254721SemastePlatformFreeBSD::Initialize ()
116254721Semaste{
117254721Semaste    if (g_initialize_count++ == 0)
118254721Semaste    {
119254721Semaste#if defined (__FreeBSD__)
120254721Semaste    	// Force a host flag to true for the default platform object.
121254721Semaste        PlatformSP default_platform_sp (new PlatformFreeBSD(true));
122254721Semaste        default_platform_sp->SetSystemArchitecture (Host::GetArchitecture());
123254721Semaste        Platform::SetDefaultPlatform (default_platform_sp);
124254721Semaste#endif
125254721Semaste        PluginManager::RegisterPlugin(PlatformFreeBSD::GetPluginNameStatic(false),
126254721Semaste                                      PlatformFreeBSD::GetDescriptionStatic(false),
127254721Semaste                                      PlatformFreeBSD::CreateInstance);
128254721Semaste    }
129254721Semaste}
130254721Semaste
131254721Semastevoid
132254721SemastePlatformFreeBSD::Terminate ()
133254721Semaste{
134254721Semaste    if (g_initialize_count > 0 && --g_initialize_count == 0)
135254721Semaste    	PluginManager::UnregisterPlugin (PlatformFreeBSD::CreateInstance);
136254721Semaste}
137254721Semaste
138254721Semaste//------------------------------------------------------------------
139254721Semaste/// Default Constructor
140254721Semaste//------------------------------------------------------------------
141254721SemastePlatformFreeBSD::PlatformFreeBSD (bool is_host) :
142254721SemastePlatform(is_host)
143254721Semaste{
144254721Semaste}
145254721Semaste
146254721Semaste//------------------------------------------------------------------
147254721Semaste/// Destructor.
148254721Semaste///
149254721Semaste/// The destructor is virtual since this class is designed to be
150254721Semaste/// inherited from by the plug-in instance.
151254721Semaste//------------------------------------------------------------------
152254721SemastePlatformFreeBSD::~PlatformFreeBSD()
153254721Semaste{
154254721Semaste}
155254721Semaste
156254721Semaste
157254721SemasteError
158254721SemastePlatformFreeBSD::ResolveExecutable (const FileSpec &exe_file,
159254721Semaste                                    const ArchSpec &exe_arch,
160254721Semaste                                    lldb::ModuleSP &exe_module_sp,
161254721Semaste                                    const FileSpecList *module_search_paths_ptr)
162254721Semaste{
163254721Semaste    Error error;
164254721Semaste    // Nothing special to do here, just use the actual file and architecture
165254721Semaste
166254721Semaste    char exe_path[PATH_MAX];
167254721Semaste    FileSpec resolved_exe_file (exe_file);
168254721Semaste
169254721Semaste    if (IsHost())
170254721Semaste    {
171254721Semaste        // If we have "ls" as the exe_file, resolve the executable location based on
172254721Semaste        // the current path variables
173254721Semaste        if (!resolved_exe_file.Exists())
174254721Semaste        {
175254721Semaste            exe_file.GetPath(exe_path, sizeof(exe_path));
176254721Semaste            resolved_exe_file.SetFile(exe_path, true);
177254721Semaste        }
178254721Semaste
179254721Semaste        if (!resolved_exe_file.Exists())
180254721Semaste            resolved_exe_file.ResolveExecutableLocation ();
181254721Semaste
182254721Semaste        if (resolved_exe_file.Exists())
183254721Semaste            error.Clear();
184254721Semaste        else
185254721Semaste        {
186254721Semaste            exe_file.GetPath(exe_path, sizeof(exe_path));
187254721Semaste            error.SetErrorStringWithFormat("unable to find executable for '%s'", exe_path);
188254721Semaste        }
189254721Semaste    }
190254721Semaste    else
191254721Semaste    {
192254721Semaste        if (m_remote_platform_sp)
193254721Semaste        {
194254721Semaste            error = m_remote_platform_sp->ResolveExecutable (exe_file,
195254721Semaste                                                             exe_arch,
196254721Semaste                                                             exe_module_sp,
197254721Semaste                                                             module_search_paths_ptr);
198254721Semaste        }
199254721Semaste        else
200254721Semaste        {
201254721Semaste            // We may connect to a process and use the provided executable (Don't use local $PATH).
202254721Semaste
203254721Semaste            // Resolve any executable within a bundle on MacOSX
204254721Semaste            Host::ResolveExecutableInBundle (resolved_exe_file);
205254721Semaste
206254721Semaste            if (resolved_exe_file.Exists()) {
207254721Semaste                error.Clear();
208254721Semaste            }
209254721Semaste            else
210254721Semaste            {
211254721Semaste                exe_file.GetPath(exe_path, sizeof(exe_path));
212254721Semaste                error.SetErrorStringWithFormat("the platform is not currently connected, and '%s' doesn't exist in the system root.", exe_path);
213254721Semaste            }
214254721Semaste        }
215254721Semaste    }
216254721Semaste
217254721Semaste
218254721Semaste    if (error.Success())
219254721Semaste    {
220254721Semaste        ModuleSpec module_spec (resolved_exe_file, exe_arch);
221254721Semaste        if (module_spec.GetArchitecture().IsValid())
222254721Semaste        {
223254721Semaste            error = ModuleList::GetSharedModule (module_spec,
224254721Semaste                                                 exe_module_sp,
225254721Semaste                                                 module_search_paths_ptr,
226254721Semaste                                                 NULL,
227254721Semaste                                                 NULL);
228254721Semaste
229254721Semaste            if (!exe_module_sp || exe_module_sp->GetObjectFile() == NULL)
230254721Semaste            {
231254721Semaste                exe_module_sp.reset();
232254721Semaste                error.SetErrorStringWithFormat ("'%s' doesn't contain the architecture %s",
233254721Semaste                                                exe_file.GetPath().c_str(),
234254721Semaste                                                exe_arch.GetArchitectureName());
235254721Semaste            }
236254721Semaste        }
237254721Semaste        else
238254721Semaste        {
239254721Semaste            // No valid architecture was specified, ask the platform for
240254721Semaste            // the architectures that we should be using (in the correct order)
241254721Semaste            // and see if we can find a match that way
242254721Semaste            StreamString arch_names;
243254721Semaste            ArchSpec platform_arch;
244254721Semaste            for (uint32_t idx = 0; GetSupportedArchitectureAtIndex (idx, platform_arch); ++idx)
245254721Semaste            {
246254721Semaste                error = ModuleList::GetSharedModule (module_spec,
247254721Semaste                                                     exe_module_sp,
248254721Semaste                                                     module_search_paths_ptr,
249254721Semaste                                                     NULL,
250254721Semaste                                                     NULL);
251254721Semaste                // Did we find an executable using one of the
252254721Semaste                if (error.Success())
253254721Semaste                {
254254721Semaste                    if (exe_module_sp && exe_module_sp->GetObjectFile())
255254721Semaste                        break;
256254721Semaste                    else
257254721Semaste                        error.SetErrorToGenericError();
258254721Semaste                }
259254721Semaste
260254721Semaste                if (idx > 0)
261254721Semaste                    arch_names.PutCString (", ");
262254721Semaste                arch_names.PutCString (platform_arch.GetArchitectureName());
263254721Semaste            }
264254721Semaste
265254721Semaste            if (error.Fail() || !exe_module_sp)
266254721Semaste            {
267254721Semaste                error.SetErrorStringWithFormat ("'%s' doesn't contain any '%s' platform architectures: %s",
268254721Semaste                                                exe_file.GetPath().c_str(),
269254721Semaste                                                GetPluginName().GetCString(),
270254721Semaste                                                arch_names.GetString().c_str());
271254721Semaste            }
272254721Semaste        }
273254721Semaste    }
274254721Semaste    else
275254721Semaste    {
276254721Semaste        error.SetErrorStringWithFormat ("'%s' does not exist",
277254721Semaste                                        exe_file.GetPath().c_str());
278254721Semaste    }
279254721Semaste
280254721Semaste    return error;
281254721Semaste}
282254721Semaste
283254721Semastesize_t
284254721SemastePlatformFreeBSD::GetSoftwareBreakpointTrapOpcode (Target &target, BreakpointSite *bp_site)
285254721Semaste{
286254721Semaste    ArchSpec arch = target.GetArchitecture();
287254721Semaste    const uint8_t *trap_opcode = NULL;
288254721Semaste    size_t trap_opcode_size = 0;
289254721Semaste
290254721Semaste    switch (arch.GetCore())
291254721Semaste    {
292254721Semaste    default:
293254721Semaste        assert(false && "Unhandled architecture in PlatformFreeBSD::GetSoftwareBreakpointTrapOpcode()");
294254721Semaste        break;
295254721Semaste
296254721Semaste    case ArchSpec::eCore_x86_32_i386:
297254721Semaste    case ArchSpec::eCore_x86_64_x86_64:
298254721Semaste        {
299254721Semaste            static const uint8_t g_i386_opcode[] = { 0xCC };
300254721Semaste            trap_opcode = g_i386_opcode;
301254721Semaste            trap_opcode_size = sizeof(g_i386_opcode);
302254721Semaste        }
303254721Semaste        break;
304254721Semaste    }
305254721Semaste
306254721Semaste    if (bp_site->SetTrapOpcode(trap_opcode, trap_opcode_size))
307254721Semaste        return trap_opcode_size;
308254721Semaste
309254721Semaste    return 0;
310254721Semaste}
311254721Semaste
312254721Semastebool
313254721SemastePlatformFreeBSD::GetRemoteOSVersion ()
314254721Semaste{
315254721Semaste    if (m_remote_platform_sp)
316254721Semaste        return m_remote_platform_sp->GetOSVersion (m_major_os_version,
317254721Semaste                                                   m_minor_os_version,
318254721Semaste                                                   m_update_os_version);
319254721Semaste    return false;
320254721Semaste}
321254721Semaste
322254721Semastebool
323254721SemastePlatformFreeBSD::GetRemoteOSBuildString (std::string &s)
324254721Semaste{
325254721Semaste    if (m_remote_platform_sp)
326254721Semaste        return m_remote_platform_sp->GetRemoteOSBuildString (s);
327254721Semaste    s.clear();
328254721Semaste    return false;
329254721Semaste}
330254721Semaste
331254721Semastebool
332254721SemastePlatformFreeBSD::GetRemoteOSKernelDescription (std::string &s)
333254721Semaste{
334254721Semaste    if (m_remote_platform_sp)
335254721Semaste        return m_remote_platform_sp->GetRemoteOSKernelDescription (s);
336254721Semaste    s.clear();
337254721Semaste    return false;
338254721Semaste}
339254721Semaste
340254721Semaste// Remote Platform subclasses need to override this function
341254721SemasteArchSpec
342254721SemastePlatformFreeBSD::GetRemoteSystemArchitecture ()
343254721Semaste{
344254721Semaste    if (m_remote_platform_sp)
345254721Semaste        return m_remote_platform_sp->GetRemoteSystemArchitecture ();
346254721Semaste    return ArchSpec();
347254721Semaste}
348254721Semaste
349254721Semaste
350254721Semasteconst char *
351254721SemastePlatformFreeBSD::GetHostname ()
352254721Semaste{
353254721Semaste    if (IsHost())
354254721Semaste        return Platform::GetHostname();
355254721Semaste
356254721Semaste    if (m_remote_platform_sp)
357254721Semaste        return m_remote_platform_sp->GetHostname ();
358254721Semaste    return NULL;
359254721Semaste}
360254721Semaste
361254721Semastebool
362254721SemastePlatformFreeBSD::IsConnected () const
363254721Semaste{
364254721Semaste    if (IsHost())
365254721Semaste        return true;
366254721Semaste    else if (m_remote_platform_sp)
367254721Semaste        return m_remote_platform_sp->IsConnected();
368254721Semaste    return false;
369254721Semaste}
370254721Semaste
371254721SemasteError
372254721SemastePlatformFreeBSD::ConnectRemote (Args& args)
373254721Semaste{
374254721Semaste    Error error;
375254721Semaste    if (IsHost())
376254721Semaste    {
377254721Semaste        error.SetErrorStringWithFormat ("can't connect to the host platform '%s', always connected", GetPluginName().GetCString());
378254721Semaste    }
379254721Semaste    else
380254721Semaste    {
381254721Semaste        if (!m_remote_platform_sp)
382254721Semaste            m_remote_platform_sp = Platform::Create ("remote-gdb-server", error);
383254721Semaste
384254721Semaste        if (m_remote_platform_sp)
385254721Semaste        {
386254721Semaste            if (error.Success())
387254721Semaste            {
388254721Semaste                if (m_remote_platform_sp)
389254721Semaste                {
390254721Semaste                    error = m_remote_platform_sp->ConnectRemote (args);
391254721Semaste                }
392254721Semaste                else
393254721Semaste                {
394254721Semaste                    error.SetErrorString ("\"platform connect\" takes a single argument: <connect-url>");
395254721Semaste                }
396254721Semaste            }
397254721Semaste        }
398254721Semaste        else
399254721Semaste            error.SetErrorString ("failed to create a 'remote-gdb-server' platform");
400254721Semaste
401254721Semaste        if (error.Fail())
402254721Semaste            m_remote_platform_sp.reset();
403254721Semaste    }
404254721Semaste
405254721Semaste    return error;
406254721Semaste}
407254721Semaste
408254721SemasteError
409254721SemastePlatformFreeBSD::DisconnectRemote ()
410254721Semaste{
411254721Semaste    Error error;
412254721Semaste
413254721Semaste    if (IsHost())
414254721Semaste    {
415254721Semaste        error.SetErrorStringWithFormat ("can't disconnect from the host platform '%s', always connected", GetPluginName().GetCString());
416254721Semaste    }
417254721Semaste    else
418254721Semaste    {
419254721Semaste        if (m_remote_platform_sp)
420254721Semaste            error = m_remote_platform_sp->DisconnectRemote ();
421254721Semaste        else
422254721Semaste            error.SetErrorString ("the platform is not currently connected");
423254721Semaste    }
424254721Semaste    return error;
425254721Semaste}
426254721Semaste
427254721Semastebool
428254721SemastePlatformFreeBSD::GetProcessInfo (lldb::pid_t pid, ProcessInstanceInfo &process_info)
429254721Semaste{
430254721Semaste    bool success = false;
431254721Semaste    if (IsHost())
432254721Semaste    {
433254721Semaste        success = Platform::GetProcessInfo (pid, process_info);
434254721Semaste    }
435254721Semaste    else if (m_remote_platform_sp)
436254721Semaste    {
437254721Semaste        success = m_remote_platform_sp->GetProcessInfo (pid, process_info);
438254721Semaste    }
439254721Semaste    return success;
440254721Semaste}
441254721Semaste
442254721Semaste
443254721Semaste
444254721Semasteuint32_t
445254721SemastePlatformFreeBSD::FindProcesses (const ProcessInstanceInfoMatch &match_info,
446254721Semaste                               ProcessInstanceInfoList &process_infos)
447254721Semaste{
448254721Semaste    uint32_t match_count = 0;
449254721Semaste    if (IsHost())
450254721Semaste    {
451254721Semaste        // Let the base class figure out the host details
452254721Semaste        match_count = Platform::FindProcesses (match_info, process_infos);
453254721Semaste    }
454254721Semaste    else
455254721Semaste    {
456254721Semaste        // If we are remote, we can only return results if we are connected
457254721Semaste        if (m_remote_platform_sp)
458254721Semaste            match_count = m_remote_platform_sp->FindProcesses (match_info, process_infos);
459254721Semaste    }
460254721Semaste    return match_count;
461254721Semaste}
462254721Semaste
463254721SemasteError
464254721SemastePlatformFreeBSD::LaunchProcess (ProcessLaunchInfo &launch_info)
465254721Semaste{
466254721Semaste    Error error;
467254721Semaste    if (IsHost())
468254721Semaste    {
469254721Semaste        error = Platform::LaunchProcess (launch_info);
470254721Semaste    }
471254721Semaste    else
472254721Semaste    {
473254721Semaste        if (m_remote_platform_sp)
474254721Semaste            error = m_remote_platform_sp->LaunchProcess (launch_info);
475254721Semaste        else
476254721Semaste            error.SetErrorString ("the platform is not currently connected");
477254721Semaste    }
478254721Semaste    return error;
479254721Semaste}
480254721Semaste
481254721Semastelldb::ProcessSP
482254721SemastePlatformFreeBSD::Attach(ProcessAttachInfo &attach_info,
483254721Semaste                        Debugger &debugger,
484254721Semaste                        Target *target,
485254721Semaste                        Listener &listener,
486254721Semaste                        Error &error)
487254721Semaste{
488254721Semaste    lldb::ProcessSP process_sp;
489254721Semaste    if (IsHost())
490254721Semaste    {
491254721Semaste        if (target == NULL)
492254721Semaste        {
493254721Semaste            TargetSP new_target_sp;
494254721Semaste            ArchSpec emptyArchSpec;
495254721Semaste
496254721Semaste            error = debugger.GetTargetList().CreateTarget (debugger,
497254721Semaste                                                           NULL,
498254721Semaste                                                           emptyArchSpec,
499254721Semaste                                                           false,
500254721Semaste                                                           m_remote_platform_sp,
501254721Semaste                                                           new_target_sp);
502254721Semaste            target = new_target_sp.get();
503254721Semaste        }
504254721Semaste        else
505254721Semaste            error.Clear();
506254721Semaste
507254721Semaste        if (target && error.Success())
508254721Semaste        {
509254721Semaste            debugger.GetTargetList().SetSelectedTarget(target);
510254721Semaste            // The freebsd always currently uses the GDB remote debugger plug-in
511254721Semaste            // so even when debugging locally we are debugging remotely!
512254721Semaste            // Just like the darwin plugin.
513254721Semaste            process_sp = target->CreateProcess (listener, "gdb-remote", NULL);
514254721Semaste
515254721Semaste            if (process_sp)
516254721Semaste                error = process_sp->Attach (attach_info);
517254721Semaste        }
518254721Semaste    }
519254721Semaste    else
520254721Semaste    {
521254721Semaste        if (m_remote_platform_sp)
522254721Semaste            process_sp = m_remote_platform_sp->Attach (attach_info, debugger, target, listener, error);
523254721Semaste        else
524254721Semaste            error.SetErrorString ("the platform is not currently connected");
525254721Semaste    }
526254721Semaste    return process_sp;
527254721Semaste}
528254721Semaste
529254721Semasteconst char *
530254721SemastePlatformFreeBSD::GetUserName (uint32_t uid)
531254721Semaste{
532254721Semaste    // Check the cache in Platform in case we have already looked this uid up
533254721Semaste    const char *user_name = Platform::GetUserName(uid);
534254721Semaste    if (user_name)
535254721Semaste        return user_name;
536254721Semaste
537254721Semaste    if (IsRemote() && m_remote_platform_sp)
538254721Semaste        return m_remote_platform_sp->GetUserName(uid);
539254721Semaste    return NULL;
540254721Semaste}
541254721Semaste
542254721Semasteconst char *
543254721SemastePlatformFreeBSD::GetGroupName (uint32_t gid)
544254721Semaste{
545254721Semaste    const char *group_name = Platform::GetGroupName(gid);
546254721Semaste    if (group_name)
547254721Semaste        return group_name;
548254721Semaste
549254721Semaste    if (IsRemote() && m_remote_platform_sp)
550254721Semaste        return m_remote_platform_sp->GetGroupName(gid);
551254721Semaste    return NULL;
552254721Semaste}
553254721Semaste
554254721Semaste
555254721Semaste// From PlatformMacOSX only
556254721SemasteError
557254721SemastePlatformFreeBSD::GetFile (const FileSpec &platform_file,
558254721Semaste                          const UUID *uuid_ptr,
559254721Semaste                          FileSpec &local_file)
560254721Semaste{
561254721Semaste    if (IsRemote())
562254721Semaste    {
563254721Semaste        if (m_remote_platform_sp)
564254721Semaste            return m_remote_platform_sp->GetFile (platform_file, uuid_ptr, local_file);
565254721Semaste    }
566254721Semaste
567254721Semaste    // Default to the local case
568254721Semaste    local_file = platform_file;
569254721Semaste    return Error();
570254721Semaste}
571254721Semaste
572254721SemasteError
573254721SemastePlatformFreeBSD::GetSharedModule (const ModuleSpec &module_spec,
574254721Semaste                                  ModuleSP &module_sp,
575254721Semaste                                  const FileSpecList *module_search_paths_ptr,
576254721Semaste                                  ModuleSP *old_module_sp_ptr,
577254721Semaste                                  bool *did_create_ptr)
578254721Semaste{
579254721Semaste    Error error;
580254721Semaste    module_sp.reset();
581254721Semaste
582254721Semaste    if (IsRemote())
583254721Semaste    {
584254721Semaste        // If we have a remote platform always, let it try and locate
585254721Semaste        // the shared module first.
586254721Semaste        if (m_remote_platform_sp)
587254721Semaste        {
588254721Semaste            error = m_remote_platform_sp->GetSharedModule (module_spec,
589254721Semaste                                                           module_sp,
590254721Semaste                                                           module_search_paths_ptr,
591254721Semaste                                                           old_module_sp_ptr,
592254721Semaste                                                           did_create_ptr);
593254721Semaste        }
594254721Semaste    }
595254721Semaste
596254721Semaste    if (!module_sp)
597254721Semaste    {
598254721Semaste        // Fall back to the local platform and find the file locally
599254721Semaste        error = Platform::GetSharedModule (module_spec,
600254721Semaste                                           module_sp,
601254721Semaste                                           module_search_paths_ptr,
602254721Semaste                                           old_module_sp_ptr,
603254721Semaste                                           did_create_ptr);
604254721Semaste    }
605254721Semaste    if (module_sp)
606254721Semaste        module_sp->SetPlatformFileSpec(module_spec.GetFileSpec());
607254721Semaste    return error;
608254721Semaste}
609254721Semaste
610254721Semaste
611254721Semastebool
612254721SemastePlatformFreeBSD::GetSupportedArchitectureAtIndex (uint32_t idx, ArchSpec &arch)
613254721Semaste{
614254721Semaste    // From macosx;s plugin code. For FreeBSD we may want to support more archs.
615254721Semaste    if (idx == 0)
616254721Semaste    {
617254721Semaste        arch = Host::GetArchitecture (Host::eSystemDefaultArchitecture);
618254721Semaste        return arch.IsValid();
619254721Semaste    }
620254721Semaste    else if (idx == 1)
621254721Semaste    {
622254721Semaste        ArchSpec platform_arch (Host::GetArchitecture (Host::eSystemDefaultArchitecture));
623254721Semaste        ArchSpec platform_arch64 (Host::GetArchitecture (Host::eSystemDefaultArchitecture64));
624254721Semaste        if (platform_arch.IsExactMatch(platform_arch64))
625254721Semaste        {
626254721Semaste            // This freebsd platform supports both 32 and 64 bit. Since we already
627254721Semaste            // returned the 64 bit arch for idx == 0, return the 32 bit arch
628254721Semaste            // for idx == 1
629254721Semaste            arch = Host::GetArchitecture (Host::eSystemDefaultArchitecture32);
630254721Semaste            return arch.IsValid();
631254721Semaste        }
632254721Semaste    }
633254721Semaste    return false;
634254721Semaste}
635254721Semaste
636254721Semastevoid
637254721SemastePlatformFreeBSD::GetStatus (Stream &strm)
638254721Semaste{
639254721Semaste    struct utsname un;
640254721Semaste
641254721Semaste    if (uname(&un)) {
642254721Semaste        strm << "FreeBSD";
643254721Semaste        return;
644254721Semaste    }
645254721Semaste
646254721Semaste    strm << "Host: " << un.sysname << ' ' << un.release << ' ' << un.version << '\n';
647254721Semaste    Platform::GetStatus(strm);
648254721Semaste}
649