1 //===-- PlatformAndroid.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 // C Includes
11 // C++ Includes
12 // Other libraries and framework includes
13 #include "lldb/Core/Log.h"
14 #include "lldb/Core/PluginManager.h"
15 #include "lldb/Host/HostInfo.h"
16 
17 // Project includes
18 #include "PlatformAndroid.h"
19 #include "PlatformAndroidRemoteGDBServer.h"
20 
21 using namespace lldb;
22 using namespace lldb_private;
23 
24 static uint32_t g_initialize_count = 0;
25 
26 void
27 PlatformAndroid::Initialize ()
28 {
29     PlatformLinux::Initialize ();
30 
31     if (g_initialize_count++ == 0)
32     {
33 #if defined(__ANDROID__)
34         PlatformSP default_platform_sp (new PlatformAndroid(true));
35         default_platform_sp->SetSystemArchitecture(HostInfo::GetArchitecture());
36         Platform::SetHostPlatform (default_platform_sp);
37 #endif
38         PluginManager::RegisterPlugin (PlatformAndroid::GetPluginNameStatic(false),
39                                        PlatformAndroid::GetPluginDescriptionStatic(false),
40                                        PlatformAndroid::CreateInstance);
41     }
42 }
43 
44 void
45 PlatformAndroid::Terminate ()
46 {
47     if (g_initialize_count > 0)
48     {
49         if (--g_initialize_count == 0)
50         {
51             PluginManager::UnregisterPlugin (PlatformAndroid::CreateInstance);
52         }
53     }
54 
55     PlatformLinux::Terminate ();
56 }
57 
58 PlatformSP
59 PlatformAndroid::CreateInstance (bool force, const ArchSpec *arch)
60 {
61     Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_PLATFORM));
62     if (log)
63     {
64         const char *arch_name;
65         if (arch && arch->GetArchitectureName ())
66             arch_name = arch->GetArchitectureName ();
67         else
68             arch_name = "<null>";
69 
70         const char *triple_cstr = arch ? arch->GetTriple ().getTriple ().c_str() : "<null>";
71 
72         log->Printf ("PlatformAndroid::%s(force=%s, arch={%s,%s})", __FUNCTION__, force ? "true" : "false", arch_name, triple_cstr);
73     }
74 
75     bool create = force;
76     if (create == false && arch && arch->IsValid())
77     {
78         const llvm::Triple &triple = arch->GetTriple();
79         switch (triple.getVendor())
80         {
81             case llvm::Triple::PC:
82                 create = true;
83                 break;
84 
85 #if defined(__ANDROID__)
86             // Only accept "unknown" for the vendor if the host is android and
87             // it "unknown" wasn't specified (it was just returned because it
88             // was NOT specified_
89             case llvm::Triple::VendorType::UnknownVendor:
90                 create = !arch->TripleVendorWasSpecified();
91                 break;
92 #endif
93             default:
94                 break;
95         }
96 
97         if (create)
98         {
99             switch (triple.getOS())
100             {
101                 case llvm::Triple::Android:
102                     break;
103 
104 #if defined(__ANDROID__)
105                 // Only accept "unknown" for the OS if the host is android and
106                 // it "unknown" wasn't specified (it was just returned because it
107                 // was NOT specified)
108                 case llvm::Triple::OSType::UnknownOS:
109                     create = !arch->TripleOSWasSpecified();
110                     break;
111 #endif
112                 default:
113                     create = false;
114                     break;
115             }
116         }
117     }
118 
119     if (create)
120     {
121         if (log)
122             log->Printf ("PlatformAndroid::%s() creating remote-android platform", __FUNCTION__);
123         return PlatformSP(new PlatformAndroid(false));
124     }
125 
126     if (log)
127         log->Printf ("PlatformAndroid::%s() aborting creation of remote-android platform", __FUNCTION__);
128 
129     return PlatformSP();
130 }
131 
132 PlatformAndroid::PlatformAndroid (bool is_host) :
133     PlatformLinux(is_host)
134 {
135 }
136 
137 PlatformAndroid::~PlatformAndroid()
138 {
139 }
140 
141 lldb_private::ConstString
142 PlatformAndroid::GetPluginNameStatic (bool is_host)
143 {
144     if (is_host)
145     {
146         static ConstString g_host_name(Platform::GetHostPlatformName ());
147         return g_host_name;
148     }
149     else
150     {
151         static ConstString g_remote_name("remote-android");
152         return g_remote_name;
153     }
154 }
155 
156 const char *
157 PlatformAndroid::GetPluginDescriptionStatic (bool is_host)
158 {
159     if (is_host)
160         return "Local Android user platform plug-in.";
161     else
162         return "Remote Android user platform plug-in.";
163 }
164 
165 lldb_private::ConstString
166 PlatformAndroid::GetPluginName()
167 {
168     return GetPluginNameStatic(IsHost());
169 }
170 
171 Error
172 PlatformAndroid::ConnectRemote (Args& args)
173 {
174     if (IsHost())
175     {
176         return Error ("can't connect to the host platform '%s', always connected", GetPluginName().GetCString());
177     }
178 
179     if (!m_remote_platform_sp)
180         m_remote_platform_sp = PlatformSP(new PlatformAndroidRemoteGDBServer());
181     return PlatformLinux::ConnectRemote (args);
182 }
183