1254721Semaste//===-- source/Host/freebsd/Host.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// C Includes
11254721Semaste#include <stdio.h>
12254721Semaste#include <dlfcn.h>
13254721Semaste#include <execinfo.h>
14254721Semaste#include <sys/types.h>
15254721Semaste#include <sys/user.h>
16254721Semaste#include <sys/utsname.h>
17254721Semaste#include <sys/sysctl.h>
18263363Semaste#include <sys/proc.h>
19254721Semaste
20254721Semaste#include <sys/ptrace.h>
21254721Semaste#include <sys/exec.h>
22254721Semaste#include <machine/elf.h>
23254721Semaste
24254721Semaste// C++ Includes
25254721Semaste// Other libraries and framework includes
26254721Semaste// Project includes
27254721Semaste#include "lldb/Core/Error.h"
28254721Semaste#include "lldb/Host/Endian.h"
29254721Semaste#include "lldb/Host/Host.h"
30263363Semaste#include "lldb/Core/Module.h"
31254721Semaste#include "lldb/Core/DataExtractor.h"
32254721Semaste#include "lldb/Core/StreamFile.h"
33254721Semaste#include "lldb/Core/StreamString.h"
34263363Semaste#include "lldb/Core/Log.h"
35254721Semaste#include "lldb/Target/Process.h"
36263363Semaste#include "lldb/Target/Platform.h"
37254721Semaste
38254721Semaste#include "lldb/Core/DataBufferHeap.h"
39254721Semaste#include "lldb/Core/DataExtractor.h"
40263363Semaste#include "lldb/Utility/CleanUp.h"
41263363Semaste
42254721Semaste#include "llvm/Support/Host.h"
43254721Semaste
44254721Semaste
45254721Semasteextern "C" {
46254721Semaste    extern char **environ;
47254721Semaste}
48254721Semaste
49254721Semasteusing namespace lldb;
50254721Semasteusing namespace lldb_private;
51254721Semaste
52254721Semasteclass FreeBSDThread
53254721Semaste{
54254721Semastepublic:
55254721Semaste    FreeBSDThread(const char *thread_name)
56254721Semaste    {
57254721Semaste        Host::SetThreadName (LLDB_INVALID_PROCESS_ID, LLDB_INVALID_THREAD_ID, thread_name);
58254721Semaste    }
59254721Semaste    static void PThreadDestructor (void *v)
60254721Semaste    {
61254721Semaste        delete (FreeBSDThread*)v;
62254721Semaste    }
63254721Semaste};
64254721Semaste
65254721Semastestatic pthread_once_t g_thread_create_once = PTHREAD_ONCE_INIT;
66254721Semastestatic pthread_key_t g_thread_create_key = 0;
67254721Semaste
68254721Semastestatic void
69254721SemasteInitThreadCreated()
70254721Semaste{
71254721Semaste    ::pthread_key_create (&g_thread_create_key, FreeBSDThread::PThreadDestructor);
72254721Semaste}
73254721Semaste
74254721Semastevoid
75254721SemasteHost::ThreadCreated (const char *thread_name)
76254721Semaste{
77254721Semaste    ::pthread_once (&g_thread_create_once, InitThreadCreated);
78254721Semaste    if (g_thread_create_key)
79254721Semaste    {
80254721Semaste        ::pthread_setspecific (g_thread_create_key, new FreeBSDThread(thread_name));
81254721Semaste    }
82254721Semaste
83254721Semaste    Host::SetShortThreadName (LLDB_INVALID_PROCESS_ID, LLDB_INVALID_THREAD_ID, thread_name, 16);
84254721Semaste}
85254721Semaste
86254721Semastestd::string
87254721SemasteHost::GetThreadName (lldb::pid_t pid, lldb::tid_t tid)
88254721Semaste{
89254721Semaste    std::string thread_name;
90254721Semaste    return thread_name;
91254721Semaste}
92254721Semaste
93254721Semastevoid
94254721SemasteHost::Backtrace (Stream &strm, uint32_t max_frames)
95254721Semaste{
96254721Semaste    char backtrace_path[] = "/tmp/lldb-backtrace-tmp-XXXXXX";
97254721Semaste    int backtrace_fd = ::mkstemp (backtrace_path);
98254721Semaste    if (backtrace_fd != -1)
99254721Semaste    {
100254721Semaste        std::vector<void *> frame_buffer (max_frames, NULL);
101254721Semaste        int count = ::backtrace (&frame_buffer[0], frame_buffer.size());
102254721Semaste        ::backtrace_symbols_fd (&frame_buffer[0], count, backtrace_fd);
103254721Semaste
104254721Semaste        const off_t buffer_size = ::lseek(backtrace_fd, 0, SEEK_CUR);
105254721Semaste
106254721Semaste        if (::lseek(backtrace_fd, 0, SEEK_SET) == 0)
107254721Semaste        {
108254721Semaste            char *buffer = (char *)::malloc (buffer_size);
109254721Semaste            if (buffer)
110254721Semaste            {
111254721Semaste                ssize_t bytes_read = ::read (backtrace_fd, buffer, buffer_size);
112254721Semaste                if (bytes_read > 0)
113254721Semaste                    strm.Write(buffer, bytes_read);
114254721Semaste                ::free (buffer);
115254721Semaste            }
116254721Semaste        }
117254721Semaste        ::close (backtrace_fd);
118254721Semaste        ::unlink (backtrace_path);
119254721Semaste    }
120254721Semaste}
121254721Semaste
122254721Semastesize_t
123254721SemasteHost::GetEnvironment (StringList &env)
124254721Semaste{
125254721Semaste    char *v;
126254721Semaste    char **var = environ;
127263363Semaste    for (; var != NULL && *var != NULL; ++var)
128263363Semaste    {
129254721Semaste        v = strchr(*var, (int)'-');
130254721Semaste        if (v == NULL)
131254721Semaste            continue;
132254721Semaste        env.AppendString(v);
133254721Semaste    }
134254721Semaste    return env.GetSize();
135254721Semaste}
136254721Semaste
137254721Semastebool
138254721SemasteHost::GetOSVersion(uint32_t &major,
139254721Semaste                   uint32_t &minor,
140254721Semaste                   uint32_t &update)
141254721Semaste{
142254721Semaste    struct utsname un;
143254721Semaste
144263363Semaste    ::memset(&un, 0, sizeof(utsname));
145254721Semaste    if (uname(&un) < 0)
146254721Semaste        return false;
147254721Semaste
148263363Semaste    int status = sscanf(un.release, "%u.%u", &major, &minor);
149254721Semaste    return status == 2;
150254721Semaste}
151254721Semaste
152254721Semastebool
153254721SemasteHost::GetOSBuildString (std::string &s)
154254721Semaste{
155254721Semaste    int mib[2] = { CTL_KERN, KERN_OSREV };
156263363Semaste    char osrev_str[12];
157263363Semaste    uint32_t osrev = 0;
158263363Semaste    size_t osrev_len = sizeof(osrev);
159263363Semaste
160263363Semaste    if (::sysctl (mib, 2, &osrev, &osrev_len, NULL, 0) == 0)
161254721Semaste    {
162263363Semaste        ::snprintf(osrev_str, sizeof(osrev_str), "%-8.8u", osrev);
163263363Semaste        s.assign (osrev_str);
164254721Semaste        return true;
165254721Semaste    }
166263363Semaste
167254721Semaste    s.clear();
168254721Semaste    return false;
169254721Semaste}
170254721Semaste
171254721Semastebool
172254721SemasteHost::GetOSKernelDescription (std::string &s)
173254721Semaste{
174263363Semaste    struct utsname un;
175263363Semaste
176263363Semaste    ::memset(&un, 0, sizeof(utsname));
177254721Semaste    s.clear();
178263363Semaste
179263363Semaste    if (uname(&un) < 0)
180254721Semaste    return false;
181263363Semaste
182263363Semaste    s.assign (un.version);
183263363Semaste
184263363Semaste    return true;
185254721Semaste}
186254721Semaste
187254721Semastestatic bool
188254721SemasteGetFreeBSDProcessArgs (const ProcessInstanceInfoMatch *match_info_ptr,
189254721Semaste                      ProcessInstanceInfo &process_info)
190254721Semaste{
191263363Semaste    if (process_info.ProcessIDIsValid())
192263363Semaste    {
193254721Semaste        int mib[4] = { CTL_KERN, KERN_PROC, KERN_PROC_ARGS, (int)process_info.GetProcessID() };
194254721Semaste
195254721Semaste        char arg_data[8192];
196254721Semaste        size_t arg_data_size = sizeof(arg_data);
197254721Semaste        if (::sysctl (mib, 4, arg_data, &arg_data_size , NULL, 0) == 0)
198254721Semaste        {
199254721Semaste            DataExtractor data (arg_data, arg_data_size, lldb::endian::InlHostByteOrder(), sizeof(void *));
200254721Semaste            lldb::offset_t offset = 0;
201254721Semaste            const char *cstr;
202254721Semaste
203254721Semaste            cstr = data.GetCStr (&offset);
204254721Semaste            if (cstr)
205254721Semaste            {
206254721Semaste                process_info.GetExecutableFile().SetFile(cstr, false);
207254721Semaste
208254721Semaste                if (!(match_info_ptr == NULL ||
209254721Semaste                    NameMatches (process_info.GetExecutableFile().GetFilename().GetCString(),
210254721Semaste                                 match_info_ptr->GetNameMatchType(),
211254721Semaste                                 match_info_ptr->GetProcessInfo().GetName())))
212254721Semaste                    return false;
213254721Semaste
214254721Semaste                Args &proc_args = process_info.GetArguments();
215254721Semaste                while (1)
216254721Semaste                {
217254721Semaste                    const uint8_t *p = data.PeekData(offset, 1);
218254721Semaste                    while ((p != NULL) && (*p == '\0') && offset < arg_data_size)
219254721Semaste                    {
220254721Semaste                        ++offset;
221254721Semaste                        p = data.PeekData(offset, 1);
222254721Semaste                    }
223254721Semaste                    if (p == NULL || offset >= arg_data_size)
224254721Semaste                        return true;
225254721Semaste
226254721Semaste                    cstr = data.GetCStr(&offset);
227254721Semaste                    if (cstr)
228254721Semaste                        proc_args.AppendArgument(cstr);
229254721Semaste                    else
230254721Semaste                        return true;
231254721Semaste                }
232254721Semaste            }
233254721Semaste        }
234254721Semaste    }
235254721Semaste    return false;
236254721Semaste}
237254721Semaste
238254721Semastestatic bool
239254721SemasteGetFreeBSDProcessCPUType (ProcessInstanceInfo &process_info)
240254721Semaste{
241263363Semaste    if (process_info.ProcessIDIsValid())
242263363Semaste    {
243254721Semaste        process_info.GetArchitecture() = Host::GetArchitecture (Host::eSystemDefaultArchitecture);
244254721Semaste        return true;
245254721Semaste    }
246254721Semaste    process_info.GetArchitecture().Clear();
247254721Semaste    return false;
248254721Semaste}
249254721Semaste
250254721Semastestatic bool
251254721SemasteGetFreeBSDProcessUserAndGroup(ProcessInstanceInfo &process_info)
252254721Semaste{
253254721Semaste    struct kinfo_proc proc_kinfo;
254254721Semaste    size_t proc_kinfo_size;
255254721Semaste
256254721Semaste    if (process_info.ProcessIDIsValid())
257254721Semaste    {
258254721Semaste        int mib[4] = { CTL_KERN, KERN_PROC, KERN_PROC_PID,
259254721Semaste            (int)process_info.GetProcessID() };
260254721Semaste        proc_kinfo_size = sizeof(struct kinfo_proc);
261254721Semaste
262254721Semaste        if (::sysctl (mib, 4, &proc_kinfo, &proc_kinfo_size, NULL, 0) == 0)
263254721Semaste        {
264254721Semaste            if (proc_kinfo_size > 0)
265254721Semaste            {
266254721Semaste                process_info.SetParentProcessID (proc_kinfo.ki_ppid);
267254721Semaste                process_info.SetUserID (proc_kinfo.ki_ruid);
268254721Semaste                process_info.SetGroupID (proc_kinfo.ki_rgid);
269254721Semaste                process_info.SetEffectiveUserID (proc_kinfo.ki_uid);
270254721Semaste                if (proc_kinfo.ki_ngroups > 0)
271254721Semaste                    process_info.SetEffectiveGroupID (proc_kinfo.ki_groups[0]);
272254721Semaste                else
273254721Semaste                    process_info.SetEffectiveGroupID (UINT32_MAX);
274254721Semaste                return true;
275254721Semaste            }
276254721Semaste        }
277254721Semaste    }
278254721Semaste    process_info.SetParentProcessID (LLDB_INVALID_PROCESS_ID);
279254721Semaste    process_info.SetUserID (UINT32_MAX);
280254721Semaste    process_info.SetGroupID (UINT32_MAX);
281254721Semaste    process_info.SetEffectiveUserID (UINT32_MAX);
282254721Semaste    process_info.SetEffectiveGroupID (UINT32_MAX);
283254721Semaste    return false;
284254721Semaste}
285254721Semaste
286263363Semasteuint32_t
287263363SemasteHost::FindProcesses (const ProcessInstanceInfoMatch &match_info, ProcessInstanceInfoList &process_infos)
288263363Semaste{
289263363Semaste    std::vector<struct kinfo_proc> kinfos;
290263363Semaste
291263363Semaste    int mib[3] = { CTL_KERN, KERN_PROC, KERN_PROC_ALL };
292263363Semaste
293263363Semaste    size_t pid_data_size = 0;
294263363Semaste    if (::sysctl (mib, 3, NULL, &pid_data_size, NULL, 0) != 0)
295263363Semaste        return 0;
296263363Semaste
297263363Semaste    // Add a few extra in case a few more show up
298263363Semaste    const size_t estimated_pid_count = (pid_data_size / sizeof(struct kinfo_proc)) + 10;
299263363Semaste
300263363Semaste    kinfos.resize (estimated_pid_count);
301263363Semaste    pid_data_size = kinfos.size() * sizeof(struct kinfo_proc);
302263363Semaste
303263363Semaste    if (::sysctl (mib, 3, &kinfos[0], &pid_data_size, NULL, 0) != 0)
304263363Semaste        return 0;
305263363Semaste
306263363Semaste    const size_t actual_pid_count = (pid_data_size / sizeof(struct kinfo_proc));
307263363Semaste
308263363Semaste    bool all_users = match_info.GetMatchAllUsers();
309263363Semaste    const lldb::pid_t our_pid = getpid();
310263363Semaste    const uid_t our_uid = getuid();
311263363Semaste    for (int i = 0; i < actual_pid_count; i++)
312263363Semaste    {
313263363Semaste        const struct kinfo_proc &kinfo = kinfos[i];
314263363Semaste        const bool kinfo_user_matches = (all_users ||
315263363Semaste                                         (kinfo.ki_ruid == our_uid) ||
316263363Semaste                                         // Special case, if lldb is being run as root we can attach to anything.
317263363Semaste                                         (our_uid == 0)
318263363Semaste                                         );
319263363Semaste
320263363Semaste        if (kinfo_user_matches == false      || // Make sure the user is acceptable
321263363Semaste            kinfo.ki_pid == our_pid          || // Skip this process
322263363Semaste            kinfo.ki_pid == 0                || // Skip kernel (kernel pid is zero)
323263363Semaste            kinfo.ki_stat == SZOMB    || // Zombies are bad, they like brains...
324263363Semaste            kinfo.ki_flag & P_TRACED  || // Being debugged?
325263363Semaste            kinfo.ki_flag & P_WEXIT)     // Working on exiting
326263363Semaste            continue;
327263363Semaste
328263363Semaste        // Every thread is a process in FreeBSD, but all the threads of a single process
329263363Semaste        // have the same pid. Do not store the process info in the result list if a process
330263363Semaste        // with given identifier is already registered there.
331263363Semaste        bool already_registered = false;
332263363Semaste        for (uint32_t pi = 0;
333263363Semaste             !already_registered &&
334263363Semaste             (const int)kinfo.ki_numthreads > 1 &&
335263363Semaste             pi < (const uint32_t)process_infos.GetSize(); pi++)
336263363Semaste            already_registered = (process_infos.GetProcessIDAtIndex(pi) == (uint32_t)kinfo.ki_pid);
337263363Semaste
338263363Semaste        if (already_registered)
339263363Semaste            continue;
340263363Semaste
341263363Semaste        ProcessInstanceInfo process_info;
342263363Semaste        process_info.SetProcessID (kinfo.ki_pid);
343263363Semaste        process_info.SetParentProcessID (kinfo.ki_ppid);
344263363Semaste        process_info.SetUserID (kinfo.ki_ruid);
345263363Semaste        process_info.SetGroupID (kinfo.ki_rgid);
346263363Semaste        process_info.SetEffectiveUserID (kinfo.ki_svuid);
347263363Semaste        process_info.SetEffectiveGroupID (kinfo.ki_svgid);
348263363Semaste
349263363Semaste        // Make sure our info matches before we go fetch the name and cpu type
350263363Semaste        if (match_info.Matches (process_info) &&
351263363Semaste            GetFreeBSDProcessArgs (&match_info, process_info))
352263363Semaste        {
353263363Semaste            GetFreeBSDProcessCPUType (process_info);
354263363Semaste            if (match_info.Matches (process_info))
355263363Semaste                process_infos.Append (process_info);
356263363Semaste        }
357263363Semaste    }
358263363Semaste
359263363Semaste    return process_infos.GetSize();
360263363Semaste}
361263363Semaste
362254721Semastebool
363254721SemasteHost::GetProcessInfo (lldb::pid_t pid, ProcessInstanceInfo &process_info)
364254721Semaste{
365254721Semaste    process_info.SetProcessID(pid);
366263363Semaste
367263363Semaste    if (GetFreeBSDProcessArgs(NULL, process_info))
368263363Semaste    {
369254721Semaste        // should use libprocstat instead of going right into sysctl?
370254721Semaste        GetFreeBSDProcessCPUType(process_info);
371254721Semaste        GetFreeBSDProcessUserAndGroup(process_info);
372254721Semaste        return true;
373254721Semaste    }
374263363Semaste
375254721Semaste    process_info.Clear();
376254721Semaste    return false;
377254721Semaste}
378254721Semaste
379254721Semastelldb::DataBufferSP
380254721SemasteHost::GetAuxvData(lldb_private::Process *process)
381254721Semaste{
382254721Semaste   int mib[2] = { CTL_KERN, KERN_PS_STRINGS };
383254721Semaste   void *ps_strings_addr, *auxv_addr;
384254721Semaste   size_t ps_strings_size = sizeof(void *);
385254721Semaste   Elf_Auxinfo aux_info[AT_COUNT];
386254721Semaste   struct ps_strings ps_strings;
387254721Semaste   struct ptrace_io_desc pid;
388254721Semaste   DataBufferSP buf_sp;
389254721Semaste   std::unique_ptr<DataBufferHeap> buf_ap(new DataBufferHeap(1024, 0));
390254721Semaste
391254721Semaste   if (::sysctl(mib, 2, &ps_strings_addr, &ps_strings_size, NULL, 0) == 0) {
392254721Semaste           pid.piod_op = PIOD_READ_D;
393254721Semaste           pid.piod_addr = &ps_strings;
394254721Semaste           pid.piod_offs = ps_strings_addr;
395254721Semaste           pid.piod_len = sizeof(ps_strings);
396254721Semaste           if (::ptrace(PT_IO, process->GetID(), (caddr_t)&pid, 0)) {
397254721Semaste                   perror("failed to fetch ps_strings");
398254721Semaste                   buf_ap.release();
399254721Semaste                   goto done;
400254721Semaste           }
401254721Semaste
402254721Semaste           auxv_addr = ps_strings.ps_envstr + ps_strings.ps_nenvstr + 1;
403254721Semaste
404254721Semaste           pid.piod_addr = aux_info;
405254721Semaste           pid.piod_offs = auxv_addr;
406254721Semaste           pid.piod_len = sizeof(aux_info);
407254721Semaste           if (::ptrace(PT_IO, process->GetID(), (caddr_t)&pid, 0)) {
408254721Semaste                   perror("failed to fetch aux_info");
409254721Semaste                   buf_ap.release();
410254721Semaste                   goto done;
411254721Semaste           }
412254721Semaste           memcpy(buf_ap->GetBytes(), aux_info, pid.piod_len);
413254721Semaste           buf_sp.reset(buf_ap.release());
414254721Semaste   } else {
415254721Semaste           perror("sysctl failed on ps_strings");
416254721Semaste   }
417254721Semaste
418254721Semaste   done:
419254721Semaste   return buf_sp;
420254721Semaste}
421