1 //===-- PlatformLinux.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 "PlatformLinux.h"
11 
12 // C Includes
13 #include <stdio.h>
14 #include <sys/utsname.h>
15 
16 // C++ Includes
17 // Other libraries and framework includes
18 // Project includes
19 #include "lldb/Core/Error.h"
20 #include "lldb/Core/Module.h"
21 #include "lldb/Core/ModuleList.h"
22 #include "lldb/Core/PluginManager.h"
23 #include "lldb/Core/StreamString.h"
24 #include "lldb/Host/FileSpec.h"
25 #include "lldb/Host/Host.h"
26 #include "lldb/Target/Target.h"
27 #include "lldb/Target/Process.h"
28 
29 using namespace lldb;
30 using namespace lldb_private;
31 
32 Platform *
33 PlatformLinux::CreateInstance ()
34 {
35     return new PlatformLinux();
36 }
37 
38 const char *
39 PlatformLinux::GetPluginNameStatic()
40 {
41     return "plugin.platform.linux";
42 }
43 
44 const char *
45 PlatformLinux::GetPluginDescriptionStatic()
46 {
47     return "Default platform plugin for Linux";
48 }
49 
50 void
51 PlatformLinux::Initialize ()
52 {
53     static bool g_initialized = false;
54 
55     if (!g_initialized)
56     {
57         PlatformSP default_platform_sp (CreateInstance());
58         Platform::SetDefaultPlatform (default_platform_sp);
59         PluginManager::RegisterPlugin(GetPluginNameStatic(),
60                                       GetPluginDescriptionStatic(),
61                                       CreateInstance);
62         g_initialized = true;
63     }
64 }
65 
66 void
67 PlatformLinux::Terminate ()
68 {
69 }
70 
71 
72 Error
73 PlatformLinux::ResolveExecutable (const FileSpec &exe_file,
74                                   const ArchSpec &exe_arch,
75                                   lldb::ModuleSP &exe_module_sp)
76 {
77     Error error;
78     // Nothing special to do here, just use the actual file and architecture
79 
80     FileSpec resolved_exe_file (exe_file);
81 
82     // If we have "ls" as the exe_file, resolve the executable loation based on
83     // the current path variables
84     if (!resolved_exe_file.Exists())
85         resolved_exe_file.ResolveExecutableLocation ();
86 
87     // Resolve any executable within a bundle on MacOSX
88     Host::ResolveExecutableInBundle (resolved_exe_file);
89 
90     if (resolved_exe_file.Exists())
91     {
92         if (exe_arch.IsValid())
93         {
94             error = ModuleList::GetSharedModule (resolved_exe_file,
95                                                  exe_arch,
96                                                  NULL,
97                                                  NULL,
98                                                  0,
99                                                  exe_module_sp,
100                                                  NULL,
101                                                  NULL);
102 
103             if (exe_module_sp->GetObjectFile() == NULL)
104             {
105                 exe_module_sp.reset();
106                 error.SetErrorStringWithFormat ("'%s%s%s' doesn't contain the architecture %s",
107                                                 exe_file.GetDirectory().AsCString(""),
108                                                 exe_file.GetDirectory() ? "/" : "",
109                                                 exe_file.GetFilename().AsCString(""),
110                                                 exe_arch.GetArchitectureName());
111             }
112         }
113         else
114         {
115             // No valid architecture was specified, ask the platform for
116             // the architectures that we should be using (in the correct order)
117             // and see if we can find a match that way
118             StreamString arch_names;
119             ArchSpec platform_arch;
120             for (uint32_t idx = 0; GetSupportedArchitectureAtIndex (idx, platform_arch); ++idx)
121             {
122                 error = ModuleList::GetSharedModule (resolved_exe_file,
123                                                      platform_arch,
124                                                      NULL,
125                                                      NULL,
126                                                      0,
127                                                      exe_module_sp,
128                                                      NULL,
129                                                      NULL);
130                 // Did we find an executable using one of the
131                 if (error.Success())
132                 {
133                     if (exe_module_sp && exe_module_sp->GetObjectFile())
134                         break;
135                     else
136                         error.SetErrorToGenericError();
137                 }
138 
139                 if (idx > 0)
140                     arch_names.PutCString (", ");
141                 arch_names.PutCString (platform_arch.GetArchitectureName());
142             }
143 
144             if (error.Fail() || !exe_module_sp)
145             {
146                 error.SetErrorStringWithFormat ("'%s%s%s' doesn't contain any '%s' platform architectures: %s",
147                                                 exe_file.GetDirectory().AsCString(""),
148                                                 exe_file.GetDirectory() ? "/" : "",
149                                                 exe_file.GetFilename().AsCString(""),
150                                                 GetShortPluginName(),
151                                                 arch_names.GetString().c_str());
152             }
153         }
154     }
155     else
156     {
157         error.SetErrorStringWithFormat ("'%s%s%s' does not exist",
158                                         exe_file.GetDirectory().AsCString(""),
159                                         exe_file.GetDirectory() ? "/" : "",
160                                         exe_file.GetFilename().AsCString(""));
161     }
162 
163     return error;
164 }
165 
166 Error
167 PlatformLinux::GetFile (const FileSpec &platform_file,
168                         const UUID *uuid, FileSpec &local_file)
169 {
170     // Default to the local case
171     local_file = platform_file;
172     return Error();
173 }
174 
175 
176 //------------------------------------------------------------------
177 /// Default Constructor
178 //------------------------------------------------------------------
179 PlatformLinux::PlatformLinux () :
180     Platform(true)
181 {
182 }
183 
184 //------------------------------------------------------------------
185 /// Destructor.
186 ///
187 /// The destructor is virtual since this class is designed to be
188 /// inherited from by the plug-in instance.
189 //------------------------------------------------------------------
190 PlatformLinux::~PlatformLinux()
191 {
192 }
193 
194 bool
195 PlatformLinux::GetProcessInfo (lldb::pid_t pid, ProcessInstanceInfo &process_info)
196 {
197     return Host::GetProcessInfo (pid, process_info);
198 }
199 
200 bool
201 PlatformLinux::GetSupportedArchitectureAtIndex (uint32_t idx, ArchSpec &arch)
202 {
203     if (idx == 0)
204     {
205         arch = Host::GetArchitecture (Host::eSystemDefaultArchitecture);
206         return arch.IsValid();
207     }
208     return false;
209 }
210 
211 void
212 PlatformLinux::GetStatus (Stream &strm)
213 {
214     struct utsname un;
215 
216     if (uname(&un)) {
217         strm << "Linux";
218         return;
219     }
220 
221     strm << un.sysname << ' ' << un.release << ' ' << un.version << '\n';
222 }
223 
224 size_t
225 PlatformLinux::GetSoftwareBreakpointTrapOpcode (Target &target,
226                                                 BreakpointSite *bp_site)
227 {
228     static const uint8_t g_i386_opcode[] = { 0xCC };
229 
230     ArchSpec arch = target.GetArchitecture();
231     const uint8_t *opcode = NULL;
232     size_t opcode_size = 0;
233 
234     switch (arch.GetCore())
235     {
236     default:
237         assert(false && "CPU type not supported!");
238         break;
239 
240     case ArchSpec::eCore_x86_32_i386:
241     case ArchSpec::eCore_x86_64_x86_64:
242         opcode = g_i386_opcode;
243         opcode_size = sizeof(g_i386_opcode);
244         break;
245     }
246 
247     bp_site->SetTrapOpcode(opcode, opcode_size);
248     return opcode_size;
249 }
250 
251 lldb::ProcessSP
252 PlatformLinux::Attach(lldb::pid_t pid,
253                       Debugger &debugger,
254                       Target *target,
255                       Listener &listener,
256                       Error &error)
257 {
258     ProcessSP processSP;
259     assert(!"Not implemented yet!");
260     return processSP;
261 }
262