1// Copyright (c) 2007, Google Inc.
2// All rights reserved.
3//
4// Redistribution and use in source and binary forms, with or without
5// modification, are permitted provided that the following conditions are
6// met:
7//
8//     * Redistributions of source code must retain the above copyright
9// notice, this list of conditions and the following disclaimer.
10//     * Redistributions in binary form must reproduce the above
11// copyright notice, this list of conditions and the following disclaimer
12// in the documentation and/or other materials provided with the
13// distribution.
14//     * Neither the name of Google Inc. nor the names of its
15// contributors may be used to endorse or promote products derived from
16// this software without specific prior written permission.
17//
18// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29
30// Author: Alfred Peng
31
32#ifndef CLIENT_SOLARIS_HANDLER_SOLARIS_LWP_H__
33#define CLIENT_SOLARIS_HANDLER_SOLARIS_LWP_H__
34
35#if defined(sparc) || defined(__sparc)
36#define TARGET_CPU_SPARC 1
37#elif defined(i386) || defined(__i386)
38#define TARGET_CPU_X86 1
39#else
40#error "cannot determine cpu type"
41#endif
42
43#include <signal.h>
44#include <stdint.h>
45#include <sys/user.h>
46#include <ucontext.h>
47
48#ifndef _KERNEL
49#define _KERNEL
50#define MUST_UNDEF_KERNEL
51#endif  // _KERNEL
52#include <sys/procfs.h>
53#ifdef MUST_UNDEF_KERNEL
54#undef _KERNEL
55#undef MUST_UNDEF_KERNEL
56#endif  // MUST_UNDEF_KERNEL
57
58namespace google_breakpad {
59
60// Max module path name length.
61static const int kMaxModuleNameLength = 256;
62
63// Holding infomaton about a module in the process.
64struct ModuleInfo {
65  char name[kMaxModuleNameLength];
66  uintptr_t start_addr;
67  int size;
68};
69
70// A callback to run when getting a lwp in the process.
71// Return true will go on to the next lwp while return false will stop the
72// iteration.
73typedef bool (*LwpCallback)(lwpstatus_t* lsp, void *context);
74
75// A callback to run when a new module is found in the process.
76// Return true will go on to the next module while return false will stop the
77// iteration.
78typedef bool (*ModuleCallback)(const ModuleInfo &module_info, void *context);
79
80// A callback to run when getting a lwpid in the process.
81// Return true will go on to the next lwp while return false will stop the
82// iteration.
83typedef bool (*LwpidCallback)(int lwpid, void *context);
84
85// Holding the callback information.
86template<class CallbackFunc>
87struct CallbackParam {
88  // Callback function address.
89  CallbackFunc call_back;
90  // Callback context;
91  void *context;
92
93  CallbackParam() : call_back(NULL), context(NULL) {
94  }
95
96  CallbackParam(CallbackFunc func, void *func_context) :
97    call_back(func), context(func_context) {
98  }
99};
100
101///////////////////////////////////////////////////////////////////////////////
102
103//
104// SolarisLwp
105//
106// Provides handy support for operation on Solaris lwps.
107// It uses proc file system to get lwp information.
108//
109// TODO(Alfred): Currently it only supports x86. Add SPARC support.
110//
111class SolarisLwp {
112 public:
113  // Create a SolarisLwp instance to list all the lwps in a process.
114  explicit SolarisLwp(int pid);
115  ~SolarisLwp();
116
117  int getpid() const { return this->pid_; }
118
119  // Control all the lwps in the process.
120  // Return the number of suspended/resumed lwps in the process.
121  // Return -1 means failed to control lwps.
122  int ControlAllLwps(bool suspend);
123
124  // Get the count of lwps in the process.
125  // Return -1 means error.
126  int GetLwpCount() const;
127
128  // Iterate the lwps of process.
129  // Whenever there is a lwp found, the callback will be invoked to process
130  // the information.
131  // Return the callback return value or -1 on error.
132  int Lwp_iter_all(int pid, CallbackParam<LwpCallback> *callback_param) const;
133
134  // Get the module count of the current process.
135  int GetModuleCount() const;
136
137  // Get the mapped modules in the address space.
138  // Whenever a module is found, the callback will be invoked to process the
139  // information.
140  // Return how may modules are found.
141  int ListModules(CallbackParam<ModuleCallback> *callback_param) const;
142
143  // Get the bottom of the stack from esp.
144  uintptr_t GetLwpStackBottom(uintptr_t current_esp) const;
145
146  // Finds a signal context on the stack given the ebp of our signal handler.
147  bool FindSigContext(uintptr_t sighandler_ebp, ucontext_t **sig_ctx);
148
149 private:
150  // Check if the address is a valid virtual address.
151  bool IsAddressMapped(uintptr_t address) const;
152
153 private:
154  // The pid of the process we are listing lwps.
155  int pid_;
156};
157
158}  // namespace google_breakpad
159
160#endif  // CLIENT_SOLARIS_HANDLER_SOLARIS_LWP_H__
161