PlatformDarwin.cpp revision 9ce953807eb814a93b449dc243de4f7bf32c3115
1//===-- PlatformDarwin.cpp --------------------------------------*- C++ -*-===//
2//
3//                     The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10#include "PlatformDarwin.h"
11
12// C Includes
13// C++ Includes
14// Other libraries and framework includes
15// Project includes
16#include "lldb/Breakpoint/BreakpointLocation.h"
17#include "lldb/Core/Debugger.h"
18#include "lldb/Core/Error.h"
19#include "lldb/Host/Host.h"
20#include "lldb/Target/Target.h"
21
22using namespace lldb;
23using namespace lldb_private;
24
25
26//------------------------------------------------------------------
27/// Default Constructor
28//------------------------------------------------------------------
29PlatformDarwin::PlatformDarwin (bool is_host) :
30    Platform(is_host),  // This is the local host platform
31    m_remote_platform_sp ()
32{
33}
34
35//------------------------------------------------------------------
36/// Destructor.
37///
38/// The destructor is virtual since this class is designed to be
39/// inherited from by the plug-in instance.
40//------------------------------------------------------------------
41PlatformDarwin::~PlatformDarwin()
42{
43}
44
45
46Error
47PlatformDarwin::ResolveExecutable (const FileSpec &exe_file,
48                                   const ArchSpec &exe_arch,
49                                   lldb::ModuleSP &exe_module_sp,
50                                   const FileSpecList *module_search_paths_ptr)
51{
52    Error error;
53    // Nothing special to do here, just use the actual file and architecture
54
55    char exe_path[PATH_MAX];
56    FileSpec resolved_exe_file (exe_file);
57
58    if (IsHost())
59    {
60        // If we have "ls" as the exe_file, resolve the executable loation based on
61        // the current path variables
62        if (!resolved_exe_file.Exists())
63        {
64            exe_file.GetPath (exe_path, sizeof(exe_path));
65            resolved_exe_file.SetFile(exe_path, true);
66        }
67
68        if (!resolved_exe_file.Exists())
69            resolved_exe_file.ResolveExecutableLocation ();
70
71        // Resolve any executable within a bundle on MacOSX
72        Host::ResolveExecutableInBundle (resolved_exe_file);
73
74        if (resolved_exe_file.Exists())
75            error.Clear();
76        else
77        {
78            exe_file.GetPath (exe_path, sizeof(exe_path));
79            error.SetErrorStringWithFormat ("unable to find executable for '%s'", exe_path);
80        }
81    }
82    else
83    {
84        if (m_remote_platform_sp)
85        {
86            error = m_remote_platform_sp->ResolveExecutable (exe_file,
87                                                             exe_arch,
88                                                             exe_module_sp,
89                                                             module_search_paths_ptr);
90        }
91        else
92        {
93            // We may connect to a process and use the provided executable (Don't use local $PATH).
94
95            // Resolve any executable within a bundle on MacOSX
96            Host::ResolveExecutableInBundle (resolved_exe_file);
97
98            if (resolved_exe_file.Exists())
99                error.Clear();
100            else
101                error.SetErrorStringWithFormat("the platform is not currently connected, and '%s' doesn't exist in the system root.", resolved_exe_file.GetFilename().AsCString(""));
102        }
103    }
104
105
106    if (error.Success())
107    {
108        if (exe_arch.IsValid())
109        {
110            error = ModuleList::GetSharedModule (resolved_exe_file,
111                                                 exe_arch,
112                                                 NULL,
113                                                 NULL,
114                                                 0,
115                                                 exe_module_sp,
116                                                 module_search_paths_ptr,
117                                                 NULL,
118                                                 NULL);
119
120            if (exe_module_sp->GetObjectFile() == NULL)
121            {
122                exe_module_sp.reset();
123                error.SetErrorStringWithFormat ("'%s%s%s' doesn't contain the architecture %s",
124                                                exe_file.GetDirectory().AsCString(""),
125                                                exe_file.GetDirectory() ? "/" : "",
126                                                exe_file.GetFilename().AsCString(""),
127                                                exe_arch.GetArchitectureName());
128            }
129        }
130        else
131        {
132            // No valid architecture was specified, ask the platform for
133            // the architectures that we should be using (in the correct order)
134            // and see if we can find a match that way
135            StreamString arch_names;
136            ArchSpec platform_arch;
137            for (uint32_t idx = 0; GetSupportedArchitectureAtIndex (idx, platform_arch); ++idx)
138            {
139                error = ModuleList::GetSharedModule (resolved_exe_file,
140                                                     platform_arch,
141                                                     NULL,
142                                                     NULL,
143                                                     0,
144                                                     exe_module_sp,
145                                                     module_search_paths_ptr,
146                                                     NULL,
147                                                     NULL);
148                // Did we find an executable using one of the
149                if (error.Success())
150                {
151                    if (exe_module_sp && exe_module_sp->GetObjectFile())
152                        break;
153                    else
154                        error.SetErrorToGenericError();
155                }
156
157                if (idx > 0)
158                    arch_names.PutCString (", ");
159                arch_names.PutCString (platform_arch.GetArchitectureName());
160            }
161
162            if (error.Fail() || !exe_module_sp)
163            {
164                error.SetErrorStringWithFormat ("'%s%s%s' doesn't contain any '%s' platform architectures: %s",
165                                                exe_file.GetDirectory().AsCString(""),
166                                                exe_file.GetDirectory() ? "/" : "",
167                                                exe_file.GetFilename().AsCString(""),
168                                                GetShortPluginName(),
169                                                arch_names.GetString().c_str());
170            }
171        }
172    }
173
174    return error;
175}
176
177
178
179Error
180PlatformDarwin::GetSharedModule (const FileSpec &platform_file,
181                                 const ArchSpec &arch,
182                                 const UUID *uuid_ptr,
183                                 const ConstString *object_name_ptr,
184                                 off_t object_offset,
185                                 ModuleSP &module_sp,
186                                 const FileSpecList *module_search_paths_ptr,
187                                 ModuleSP *old_module_sp_ptr,
188                                 bool *did_create_ptr)
189{
190    Error error;
191    module_sp.reset();
192
193    if (IsRemote())
194    {
195        // If we have a remote platform always, let it try and locate
196        // the shared module first.
197        if (m_remote_platform_sp)
198        {
199            error = m_remote_platform_sp->GetSharedModule (platform_file,
200                                                           arch,
201                                                           uuid_ptr,
202                                                           object_name_ptr,
203                                                           object_offset,
204                                                           module_sp,
205                                                           module_search_paths_ptr,
206                                                           old_module_sp_ptr,
207                                                           did_create_ptr);
208        }
209    }
210
211    if (!module_sp)
212    {
213        // Fall back to the local platform and find the file locally
214        error = Platform::GetSharedModule (platform_file,
215                                           arch,
216                                           uuid_ptr,
217                                           object_name_ptr,
218                                           object_offset,
219                                           module_sp,
220                                           module_search_paths_ptr,
221                                           old_module_sp_ptr,
222                                           did_create_ptr);
223
224        if (!module_sp && module_search_paths_ptr && platform_file)
225        {
226            // We can try to pull off part of the file path up to the bundle
227            // directory level and try any module search paths...
228            FileSpec bundle_directory;
229            if (Host::GetBundleDirectory (platform_file, bundle_directory))
230            {
231                char platform_path[PATH_MAX];
232                char bundle_dir[PATH_MAX];
233                platform_file.GetPath (platform_path, sizeof(platform_path));
234                const size_t bundle_directory_len = bundle_directory.GetPath (bundle_dir, sizeof(bundle_dir));
235                char new_path[PATH_MAX];
236                size_t num_module_search_paths = module_search_paths_ptr->GetSize();
237                for (size_t i=0; i<num_module_search_paths; ++i)
238                {
239                    const size_t search_path_len = module_search_paths_ptr->GetFileSpecAtIndex(i).GetPath(new_path, sizeof(new_path));
240                    if (search_path_len < sizeof(new_path))
241                    {
242                        snprintf (new_path + search_path_len, sizeof(new_path) - search_path_len, "/%s", platform_path + bundle_directory_len);
243                        FileSpec new_file_spec (new_path, false);
244                        if (new_file_spec.Exists())
245                        {
246                            Error new_error (Platform::GetSharedModule (new_file_spec,
247                                                                        arch,
248                                                                        uuid_ptr,
249                                                                        object_name_ptr,
250                                                                        object_offset,
251                                                                        module_sp,
252                                                                        NULL,
253                                                                        old_module_sp_ptr,
254                                                                        did_create_ptr));
255
256                            if (module_sp)
257                            {
258                                module_sp->SetPlatformFileSpec(new_file_spec);
259                                return new_error;
260                            }
261                        }
262                    }
263                }
264            }
265        }
266    }
267    if (module_sp)
268        module_sp->SetPlatformFileSpec(platform_file);
269    return error;
270}
271
272size_t
273PlatformDarwin::GetSoftwareBreakpointTrapOpcode (Target &target, BreakpointSite *bp_site)
274{
275    const uint8_t *trap_opcode = NULL;
276    uint32_t trap_opcode_size = 0;
277    bool bp_is_thumb = false;
278
279    llvm::Triple::ArchType machine = target.GetArchitecture().GetMachine();
280    switch (machine)
281    {
282    case llvm::Triple::x86:
283    case llvm::Triple::x86_64:
284        {
285            static const uint8_t g_i386_breakpoint_opcode[] = { 0xCC };
286            trap_opcode = g_i386_breakpoint_opcode;
287            trap_opcode_size = sizeof(g_i386_breakpoint_opcode);
288        }
289        break;
290
291    case llvm::Triple::thumb:
292        bp_is_thumb = true; // Fall through...
293    case llvm::Triple::arm:
294        {
295            static const uint8_t g_arm_breakpoint_opcode[] = { 0xFE, 0xDE, 0xFF, 0xE7 };
296            static const uint8_t g_thumb_breakpooint_opcode[] = { 0xFE, 0xDE };
297
298            // Auto detect arm/thumb if it wasn't explicitly specified
299            if (!bp_is_thumb)
300            {
301                lldb::BreakpointLocationSP bp_loc_sp (bp_site->GetOwnerAtIndex (0));
302                if (bp_loc_sp)
303                    bp_is_thumb = bp_loc_sp->GetAddress().GetAddressClass () == eAddressClassCodeAlternateISA;
304            }
305            if (bp_is_thumb)
306            {
307                trap_opcode = g_thumb_breakpooint_opcode;
308                trap_opcode_size = sizeof(g_thumb_breakpooint_opcode);
309                break;
310            }
311            trap_opcode = g_arm_breakpoint_opcode;
312            trap_opcode_size = sizeof(g_arm_breakpoint_opcode);
313        }
314        break;
315
316    case llvm::Triple::ppc:
317    case llvm::Triple::ppc64:
318        {
319            static const uint8_t g_ppc_breakpoint_opcode[] = { 0x7F, 0xC0, 0x00, 0x08 };
320            trap_opcode = g_ppc_breakpoint_opcode;
321            trap_opcode_size = sizeof(g_ppc_breakpoint_opcode);
322        }
323        break;
324
325    default:
326        assert(!"Unhandled architecture in PlatformDarwin::GetSoftwareBreakpointTrapOpcode()");
327        break;
328    }
329
330    if (trap_opcode && trap_opcode_size)
331    {
332        if (bp_site->SetTrapOpcode(trap_opcode, trap_opcode_size))
333            return trap_opcode_size;
334    }
335    return 0;
336
337}
338
339bool
340PlatformDarwin::GetRemoteOSVersion ()
341{
342    if (m_remote_platform_sp)
343        return m_remote_platform_sp->GetOSVersion (m_major_os_version,
344                                                   m_minor_os_version,
345                                                   m_update_os_version);
346    return false;
347}
348
349bool
350PlatformDarwin::GetRemoteOSBuildString (std::string &s)
351{
352    if (m_remote_platform_sp)
353        return m_remote_platform_sp->GetRemoteOSBuildString (s);
354    s.clear();
355    return false;
356}
357
358bool
359PlatformDarwin::GetRemoteOSKernelDescription (std::string &s)
360{
361    if (m_remote_platform_sp)
362        return m_remote_platform_sp->GetRemoteOSKernelDescription (s);
363    s.clear();
364    return false;
365}
366
367// Remote Platform subclasses need to override this function
368ArchSpec
369PlatformDarwin::GetRemoteSystemArchitecture ()
370{
371    if (m_remote_platform_sp)
372        return m_remote_platform_sp->GetRemoteSystemArchitecture ();
373    return ArchSpec();
374}
375
376
377const char *
378PlatformDarwin::GetHostname ()
379{
380    if (IsHost())
381        return Platform::GetHostname();
382
383    if (m_remote_platform_sp)
384        return m_remote_platform_sp->GetHostname ();
385    return NULL;
386}
387
388bool
389PlatformDarwin::IsConnected () const
390{
391    if (IsHost())
392        return true;
393    else if (m_remote_platform_sp)
394        return m_remote_platform_sp->IsConnected();
395    return false;
396}
397
398Error
399PlatformDarwin::ConnectRemote (Args& args)
400{
401    Error error;
402    if (IsHost())
403    {
404        error.SetErrorStringWithFormat ("can't connect to the host platform '%s', always connected", GetShortPluginName());
405    }
406    else
407    {
408        if (!m_remote_platform_sp)
409            m_remote_platform_sp = Platform::Create ("remote-gdb-server", error);
410
411        if (m_remote_platform_sp)
412        {
413            if (error.Success())
414            {
415                if (m_remote_platform_sp)
416                {
417                    error = m_remote_platform_sp->ConnectRemote (args);
418                }
419                else
420                {
421                    error.SetErrorString ("\"platform connect\" takes a single argument: <connect-url>");
422                }
423            }
424        }
425        else
426            error.SetErrorString ("failed to create a 'remote-gdb-server' platform");
427
428        if (error.Fail())
429            m_remote_platform_sp.reset();
430    }
431
432    return error;
433}
434
435Error
436PlatformDarwin::DisconnectRemote ()
437{
438    Error error;
439
440    if (IsHost())
441    {
442        error.SetErrorStringWithFormat ("can't disconnect from the host platform '%s', always connected", GetShortPluginName());
443    }
444    else
445    {
446        if (m_remote_platform_sp)
447            error = m_remote_platform_sp->DisconnectRemote ();
448        else
449            error.SetErrorString ("the platform is not currently connected");
450    }
451    return error;
452}
453
454
455bool
456PlatformDarwin::GetProcessInfo (lldb::pid_t pid, ProcessInstanceInfo &process_info)
457{
458    bool sucess = false;
459    if (IsHost())
460    {
461        sucess = Platform::GetProcessInfo (pid, process_info);
462    }
463    else
464    {
465        if (m_remote_platform_sp)
466            sucess = m_remote_platform_sp->GetProcessInfo (pid, process_info);
467    }
468    return sucess;
469}
470
471
472
473uint32_t
474PlatformDarwin::FindProcesses (const ProcessInstanceInfoMatch &match_info,
475                               ProcessInstanceInfoList &process_infos)
476{
477    uint32_t match_count = 0;
478    if (IsHost())
479    {
480        // Let the base class figure out the host details
481        match_count = Platform::FindProcesses (match_info, process_infos);
482    }
483    else
484    {
485        // If we are remote, we can only return results if we are connected
486        if (m_remote_platform_sp)
487            match_count = m_remote_platform_sp->FindProcesses (match_info, process_infos);
488    }
489    return match_count;
490}
491
492Error
493PlatformDarwin::LaunchProcess (ProcessLaunchInfo &launch_info)
494{
495    Error error;
496
497    if (IsHost())
498    {
499        if (launch_info.GetFlags().Test (eLaunchFlagLaunchInShell))
500        {
501            const bool is_localhost = true;
502            if (!launch_info.ConvertArgumentsForLaunchingInShell (error, is_localhost))
503                return error;
504        }
505        error = Platform::LaunchProcess (launch_info);
506    }
507    else
508    {
509        if (m_remote_platform_sp)
510            error = m_remote_platform_sp->LaunchProcess (launch_info);
511        else
512            error.SetErrorString ("the platform is not currently connected");
513    }
514    return error;
515}
516
517lldb::ProcessSP
518PlatformDarwin::Attach (ProcessAttachInfo &attach_info,
519                        Debugger &debugger,
520                        Target *target,
521                        Listener &listener,
522                        Error &error)
523{
524    lldb::ProcessSP process_sp;
525
526    if (IsHost())
527    {
528        if (target == NULL)
529        {
530            TargetSP new_target_sp;
531            FileSpec emptyFileSpec;
532
533            error = debugger.GetTargetList().CreateTarget (debugger,
534                                                           emptyFileSpec,
535                                                           NULL,
536                                                           false,
537                                                           NULL,
538                                                           new_target_sp);
539            target = new_target_sp.get();
540        }
541        else
542            error.Clear();
543
544        if (target && error.Success())
545        {
546            debugger.GetTargetList().SetSelectedTarget(target);
547
548            process_sp = target->CreateProcess (listener, attach_info.GetProcessPluginName(), NULL);
549
550            if (process_sp)
551                error = process_sp->Attach (attach_info);
552        }
553    }
554    else
555    {
556        if (m_remote_platform_sp)
557            process_sp = m_remote_platform_sp->Attach (attach_info, debugger, target, listener, error);
558        else
559            error.SetErrorString ("the platform is not currently connected");
560    }
561    return process_sp;
562}
563
564const char *
565PlatformDarwin::GetUserName (uint32_t uid)
566{
567    // Check the cache in Platform in case we have already looked this uid up
568    const char *user_name = Platform::GetUserName(uid);
569    if (user_name)
570        return user_name;
571
572    if (IsRemote() && m_remote_platform_sp)
573        return m_remote_platform_sp->GetUserName(uid);
574    return NULL;
575}
576
577const char *
578PlatformDarwin::GetGroupName (uint32_t gid)
579{
580    const char *group_name = Platform::GetGroupName(gid);
581    if (group_name)
582        return group_name;
583
584    if (IsRemote() && m_remote_platform_sp)
585        return m_remote_platform_sp->GetGroupName(gid);
586    return NULL;
587}
588
589bool
590PlatformDarwin::ModuleIsExcludedForNonModuleSpecificSearches (lldb_private::Target &target, const lldb::ModuleSP &module_sp)
591{
592    ObjectFile *obj_file = module_sp->GetObjectFile();
593    if (!obj_file)
594        return false;
595
596    ObjectFile::Type obj_type = obj_file->GetType();
597    if (obj_type == ObjectFile::eTypeDynamicLinker)
598        return true;
599    else
600        return false;
601}
602
603
604// The architecture selection rules for arm processors
605// These cpu subtypes have distinct names (e.g. armv7f) but armv7 binaries run fine on an armv7f processor.
606
607bool
608PlatformDarwin::ARMGetSupportedArchitectureAtIndex (uint32_t idx, ArchSpec &arch)
609{
610    ArchSpec system_arch (GetSystemArchitecture());
611    const ArchSpec::Core system_core = system_arch.GetCore();
612    switch (system_core)
613    {
614    default:
615        switch (idx)
616        {
617        case 0: arch.SetTriple ("armv7-apple-darwin", NULL);  return true;
618        case 1: arch.SetTriple ("armv7f-apple-darwin", NULL); return true;
619        case 2: arch.SetTriple ("armv7k-apple-darwin", NULL); return true;
620        case 3: arch.SetTriple ("armv7s-apple-darwin", NULL); return true;
621        case 4: arch.SetTriple ("armv6-apple-darwin", NULL);  return true;
622        case 5: arch.SetTriple ("armv5-apple-darwin", NULL);  return true;
623        case 6: arch.SetTriple ("armv4-apple-darwin", NULL);  return true;
624        case 7: arch.SetTriple ("arm-apple-darwin", NULL);    return true;
625        default: break;
626        }
627        break;
628
629    case ArchSpec::eCore_arm_armv7f:
630        switch (idx)
631        {
632        case 0: arch.SetTriple ("armv7f-apple-darwin", NULL); return true;
633        case 1: arch.SetTriple ("armv7-apple-darwin", NULL);  return true;
634        case 2: arch.SetTriple ("armv6-apple-darwin", NULL);  return true;
635        case 3: arch.SetTriple ("armv5-apple-darwin", NULL);  return true;
636        case 4: arch.SetTriple ("armv4-apple-darwin", NULL);  return true;
637        case 5: arch.SetTriple ("arm-apple-darwin", NULL);    return true;
638        default: break;
639        }
640        break;
641
642    case ArchSpec::eCore_arm_armv7k:
643        switch (idx)
644        {
645        case 0: arch.SetTriple ("armv7k-apple-darwin", NULL); return true;
646        case 1: arch.SetTriple ("armv7-apple-darwin", NULL);  return true;
647        case 2: arch.SetTriple ("armv6-apple-darwin", NULL);  return true;
648        case 3: arch.SetTriple ("armv5-apple-darwin", NULL);  return true;
649        case 4: arch.SetTriple ("armv4-apple-darwin", NULL);  return true;
650        case 5: arch.SetTriple ("arm-apple-darwin", NULL);    return true;
651        default: break;
652        }
653        break;
654
655    case ArchSpec::eCore_arm_armv7s:
656        switch (idx)
657        {
658        case 0: arch.SetTriple ("armv7s-apple-darwin", NULL); return true;
659        case 1: arch.SetTriple ("armv7-apple-darwin", NULL);  return true;
660        case 2: arch.SetTriple ("armv6-apple-darwin", NULL);  return true;
661        case 3: arch.SetTriple ("armv5-apple-darwin", NULL);  return true;
662        case 4: arch.SetTriple ("armv4-apple-darwin", NULL);  return true;
663        case 5: arch.SetTriple ("arm-apple-darwin", NULL);    return true;
664        default: break;
665        }
666        break;
667
668    case ArchSpec::eCore_arm_armv7:
669        switch (idx)
670        {
671        case 0: arch.SetTriple ("armv7-apple-darwin", NULL);  return true;
672        case 1: arch.SetTriple ("armv6-apple-darwin", NULL);  return true;
673        case 2: arch.SetTriple ("armv5-apple-darwin", NULL);  return true;
674        case 3: arch.SetTriple ("armv4-apple-darwin", NULL);  return true;
675        case 4: arch.SetTriple ("arm-apple-darwin", NULL);    return true;
676        default: break;
677        }
678        break;
679
680    case ArchSpec::eCore_arm_armv6:
681        switch (idx)
682        {
683        case 0: arch.SetTriple ("armv6-apple-darwin", NULL);  return true;
684        case 1: arch.SetTriple ("armv5-apple-darwin", NULL);  return true;
685        case 2: arch.SetTriple ("armv4-apple-darwin", NULL);  return true;
686        case 3: arch.SetTriple ("arm-apple-darwin", NULL);    return true;
687        default: break;
688        }
689        break;
690
691    case ArchSpec::eCore_arm_armv5:
692        switch (idx)
693        {
694        case 0: arch.SetTriple ("armv5-apple-darwin", NULL);  return true;
695        case 1: arch.SetTriple ("armv4-apple-darwin", NULL);  return true;
696        case 2: arch.SetTriple ("arm-apple-darwin", NULL);    return true;
697        default: break;
698        }
699        break;
700
701    case ArchSpec::eCore_arm_armv4:
702        switch (idx)
703        {
704        case 0: arch.SetTriple ("armv4-apple-darwin", NULL);  return true;
705        case 1: arch.SetTriple ("arm-apple-darwin", NULL);    return true;
706        default: break;
707        }
708        break;
709    }
710    arch.Clear();
711    return false;
712}
713