blob: c173a25dfe2e5551d1ab26c32628729786067971 [file] [log] [blame]
Stephen Wilson3e2a18f2011-03-23 01:58:26 +00001//===-- source/Host/linux/Host.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#include <stdio.h>
12#include <sys/utsname.h>
Johnny Chen30213ff2012-01-05 19:17:38 +000013#include <sys/types.h>
14#include <sys/stat.h>
15#include <fcntl.h>
16
Stephen Wilson3e2a18f2011-03-23 01:58:26 +000017
18// C++ Includes
19// Other libraries and framework includes
20// Project includes
Johnny Chenc18a5382011-05-19 23:07:19 +000021#include "lldb/Core/Error.h"
Johnny Chen30213ff2012-01-05 19:17:38 +000022#include "lldb/Target/Process.h"
23
Stephen Wilson3e2a18f2011-03-23 01:58:26 +000024#include "lldb/Host/Host.h"
Johnny Chen30213ff2012-01-05 19:17:38 +000025#include "lldb/Core/DataBufferHeap.h"
26#include "lldb/Core/DataExtractor.h"
Stephen Wilson3e2a18f2011-03-23 01:58:26 +000027
28using namespace lldb;
29using namespace lldb_private;
30
Andrew Kaylorbf9b4c12013-05-07 22:46:38 +000031namespace
Stephen Wilson3e2a18f2011-03-23 01:58:26 +000032{
Johnny Chenc18a5382011-05-19 23:07:19 +000033
Johnny Chen30213ff2012-01-05 19:17:38 +000034lldb::DataBufferSP
Andrew Kaylorbf9b4c12013-05-07 22:46:38 +000035ReadProcPseudoFile(lldb::pid_t pid, const char *name)
Johnny Chen30213ff2012-01-05 19:17:38 +000036{
37 static const size_t path_size = 128;
38 static char path[path_size];
39 lldb::DataBufferSP buf_sp;
40
41 int fd;
42
43 // Ideally, we would simply create a FileSpec and call ReadFileContents.
44 // However, files in procfs have zero size (since they are, in general,
45 // dynamically generated by the kernel) which is incompatible with the
46 // current ReadFileContents implementation. Therefore we simply stream the
47 // data into a DataBuffer ourselves.
Andrew Kaylorbf9b4c12013-05-07 22:46:38 +000048 if (snprintf(path, path_size, "/proc/%" PRIu64 "/%s", pid, name) < 0)
Johnny Chen30213ff2012-01-05 19:17:38 +000049 return buf_sp;
50
51 if ((fd = open(path, O_RDONLY, 0)) < 0)
52 return buf_sp;
53
54 size_t bytes_read = 0;
Greg Clayton7b0992d2013-04-18 22:45:39 +000055 std::unique_ptr<DataBufferHeap> buf_ap(new DataBufferHeap(1024, 0));
Johnny Chen30213ff2012-01-05 19:17:38 +000056 for (;;)
57 {
58 size_t avail = buf_ap->GetByteSize() - bytes_read;
59 ssize_t status = read(fd, buf_ap->GetBytes() + bytes_read, avail);
60
61 if (status < 0)
62 break;
63
64 bytes_read += status;
65
66 if (status == 0)
67 {
68 buf_ap->SetByteSize(bytes_read);
69 buf_sp.reset(buf_ap.release());
70 break;
71 }
72
73 if (avail - status == 0)
74 buf_ap->SetByteSize(2 * buf_ap->GetByteSize());
75 }
76
77 return buf_sp;
78}
Andrew Kaylorbf9b4c12013-05-07 22:46:38 +000079
80} // anonymous namespace
81
82bool
83Host::GetOSVersion(uint32_t &major,
84 uint32_t &minor,
85 uint32_t &update)
86{
87 struct utsname un;
88 int status;
89
90 if (uname(&un))
91 return false;
92
93 status = sscanf(un.release, "%u.%u.%u", &major, &minor, &update);
94 return status == 3;
95}
96
97Error
98Host::LaunchProcess (ProcessLaunchInfo &launch_info)
99{
100 Error error;
101 assert(!"Not implemented yet!!!");
102 return error;
103}
104
105lldb::DataBufferSP
106Host::GetAuxvData(lldb_private::Process *process)
107{
108 return ReadProcPseudoFile(process->GetID(), "auxv");
109}
110
111
112bool
113Host::GetProcessInfo (lldb::pid_t pid, ProcessInstanceInfo &process_info)
114{
115 process_info.Clear();
116 process_info.SetProcessID(pid);
117
118 // Architecture is intentionally omitted because that's better resolved
119 // in other places (see ProcessPOSIX::DoAttachWithID().
120
121 // Use special code here because proc/[pid]/exe is a symbolic link.
122 char link_path[PATH_MAX];
123 char exe_path[PATH_MAX] = "";
124 if (snprintf(link_path, PATH_MAX, "/proc/%" PRIu64 "/exe", pid) > 0)
125 {
126 ssize_t len = readlink(link_path, exe_path, sizeof(exe_path) - 1);
127 if (len > 0)
128 exe_path[len] = 0;
129
130 static const ssize_t deleted_len = strlen(" (deleted)");
131 if (len > deleted_len &&
132 !strcmp(exe_path + len - deleted_len, " (deleted)"))
133 {
134 exe_path[len - deleted_len] = 0;
135 }
136 }
137 process_info.GetExecutableFile().SetFile(exe_path, false);
138
139 lldb::DataBufferSP buf_sp;
140
141 // Get the process environment.
142 buf_sp = ReadProcPseudoFile(pid, "environ");
143 Args &info_env = process_info.GetEnvironmentEntries();
144 char *next_var = (char *)buf_sp->GetBytes();
145 char *end_buf = next_var + buf_sp->GetByteSize();
146 while (next_var < end_buf && 0 != *next_var)
147 {
148 info_env.AppendArgument(next_var);
149 next_var += strlen(next_var) + 1;
150 }
151
152 // Get the commond line used to start the process.
153 buf_sp = ReadProcPseudoFile(pid, "cmdline");
154
155 // Grab Arg0 first.
156 char *cmd = (char *)buf_sp->GetBytes();
157 process_info.SetArg0(cmd);
158
159 // Now process any remaining arguments.
160 Args &info_args = process_info.GetArguments();
161 char *next_arg = cmd + strlen(cmd) + 1;
162 end_buf = cmd + buf_sp->GetByteSize();
163 while (next_arg < end_buf && 0 != *next_arg)
164 {
165 info_args.AppendArgument(next_arg);
166 next_arg += strlen(next_arg) + 1;
167 }
168
169 // FIXME: Parse /proc/<pid>/status to get uid, gid, euid, egid and parent_pid
170
171 return true;
172}