libcsdbg  1.28
C++ exception (and generic) stack trace debug library
process.cpp
Go to the documentation of this file.
1 #include "../include/process.hpp"
2 #include "../include/util.hpp"
3 
10 namespace csdbg {
11 
22 {
23  util::lock();
24  symbol *sym = NULL;
25  try {
26  sym = new symbol(addr, nm);
27  m_symcache->add(sym);
28  }
29 
30  catch (std::exception &x) {
31  delete sym;
32  util::dbg_error("in process::%s(): %s", __FUNCTION__, x.what());
33  }
34 
35  util::unlock();
36  return *this;
37 }
38 
39 
48 {
49  util::lock();
50 
51  /*
52  * Search the cache starting from the last entry (the latest added) to exploit
53  * locality of reference
54  */
55  for (i32 i = m_symcache->size() - 1; likely(i >= 0); i--) {
56  symbol *sym = m_symcache->at(i);
57  if ( unlikely(sym->addr() == addr) ) {
58  util::unlock();
59  return sym;
60  }
61  }
62 
63  util::unlock();
64  return NULL;
65 }
66 
67 
74 try:
75 m_pid(getpid()),
76 m_threads(NULL),
77 m_modules(NULL),
78 m_symcache(NULL)
79 {
83 }
84 
85 catch (...) {
86  delete m_threads;
87  delete m_modules;
88  m_threads = NULL;
89  m_modules = NULL;
90 }
91 
92 
101 try:
102 m_pid(src.m_pid),
103 m_threads(NULL),
104 m_modules(NULL),
105 m_symcache(NULL)
106 {
107  util::lock();
108  m_threads = src.m_threads->clone();
109  m_modules = src.m_modules->clone();
110  m_symcache = src.m_symcache->clone();
111  util::unlock();
112 }
113 
114 catch (...) {
115  delete m_threads;
116  delete m_modules;
117  m_threads = NULL;
118  m_modules = NULL;
119  util::unlock();
120 }
121 
122 
127 {
128  util::lock();
129  delete m_threads;
130  delete m_modules;
131  delete m_symcache;
132 
133  m_threads = NULL;
134  m_modules = NULL;
135  m_symcache = NULL;
136  util::unlock();
137 }
138 
139 
147 inline process* process::clone() const
148 {
149  return new process(*this);
150 }
151 
152 
158 inline pid_t process::pid() const
159 {
160  return m_pid;
161 }
162 
163 
174 {
175  if ( unlikely(this == &rval) )
176  return *this;
177 
178  util::lock();
179  try {
180  m_pid = rval.m_pid;
181  *m_threads = *rval.m_threads;
182  *m_modules = *rval.m_modules;
183  *m_symcache = *rval.m_symcache;
184 
185  util::unlock();
186  return *this;
187  }
188 
189  catch (...) {
190  util::unlock();
191  throw;
192  }
193 }
194 
195 
202 {
203  u32 cnt = 0;
204  for (i32 i = m_modules->size() - 1; likely(i >= 0); i--)
205  cnt += m_modules->at(i)->size();
206 
207  return cnt;
208 }
209 
210 
217 {
218  return this->m_modules->size();
219 }
220 
221 
237 {
238  util::lock();
239  symtab *tbl = NULL;
240  try {
241  tbl = new symtab(path, base);
242  m_modules->add(tbl);
243  util::unlock();
244  return *this;
245  }
246 
247  catch (...) {
248  delete tbl;
249  util::unlock();
250  throw;
251  }
252 }
253 
254 
267 {
268  const symbol *sym = cache_lookup(addr);
269  if ( likely(sym != NULL) )
270  return sym->name();
271 
272  for (u32 i = 0, sz = m_modules->size(); likely(i < sz); i++) {
273  const i8 *retval = m_modules->at(i)->lookup(addr);
274 
275  if ( unlikely(retval != NULL) ) {
276  cache_add(addr, retval);
277  return retval;
278  }
279  }
280 
281  /* The address was not resolved */
282  cache_add(addr, NULL);
283  return NULL;
284 }
285 
286 
300 const i8* process::ilookup(mem_addr_t addr, mem_addr_t &base) const
301 {
302  for (u32 i = 0, sz = m_modules->size(); likely(i < sz); i++) {
303  const symtab *tbl = m_modules->at(i);
304 
305  if ( unlikely(tbl->exists(addr)) ) {
306  base = tbl->base();
307  return tbl->path();
308  }
309  }
310 
311  base = 0;
312  return NULL;
313 }
314 
315 
322 {
323  return m_threads->size();
324 }
325 
326 
340 {
341  util::lock();
342  for (u32 i = 0, sz = m_threads->size(); likely(i < sz); i++) {
343  thread *thr = m_threads->at(i);
344 
345  if ( unlikely(thr->is_current()) ) {
346  util::unlock();
347  return thr;
348  }
349  }
350 
351  thread *retval = NULL;
352  try {
353  retval = new thread;
354  m_threads->add(retval);
355  util::unlock();
356  return retval;
357  }
358 
359  catch (...) {
360  delete retval;
361  util::unlock();
362  throw;
363  }
364 }
365 
366 
376 thread* process::get_thread(pthread_t id) const
377 {
378  util::lock();
379  for (u32 i = 0, sz = m_threads->size(); likely(i < sz); i++) {
380  thread *thr = m_threads->at(i);
381 
382  if ( unlikely(thr->is_current()) ) {
383  util::unlock();
384  return thr;
385  }
386  }
387 
388  util::unlock();
389  return NULL;
390 }
391 
392 
402 thread* process::get_thread(const i8 *nm) const
403 {
404  __D_ASSERT(nm != NULL);
405  if ( unlikely(nm == NULL) )
406  return NULL;
407 
408  util::lock();
409  for (u32 i = 0, sz = m_threads->size(); likely(i < sz); i++) {
410  thread *thr = m_threads->at(i);
411 
412  if ( unlikely(strcmp(thr->name(), nm) == 0) ) {
413  util::unlock();
414  return thr;
415  }
416  }
417 
418  util::unlock();
419  return NULL;
420 }
421 
422 
433 {
434  try {
435  util::lock();
436  thread *retval = m_threads->at(i);
437  util::unlock();
438  return retval;
439  }
440 
441  catch (...) {
442  util::unlock();
443  throw;
444  }
445 }
446 
447 
464 {
465  util::lock();
466  for (u32 i = 0, sz = m_threads->size(); likely(i < sz); i++) {
467  thread *thr = m_threads->at(i);
468 
469  if ( unlikely(thr->is_current()) ) {
470  m_threads->remove(i);
471  util::unlock();
472  break;
473  }
474  }
475 
476  util::unlock();
477  return *this;
478 }
479 
480 }
481 
virtual process & operator=(const process &)
Assignment operator.
Definition: process.cpp:173
virtual bool exists(mem_addr_t) const
Probe if a symbol exists.
Definition: symtab.cpp:301
virtual ~process()
Object destructor.
Definition: process.cpp:126
virtual u32 thread_count() const
Get the active thread count.
Definition: process.cpp:321
virtual process & cleanup_thread(pthread_t)
Cleanup libcsdbg-related thread resources upon thread cancellation.
Definition: process.cpp:463
chain< thread > * m_threads
Instrumented thread list.
Definition: process.hpp:37
This class represents a program/library function symbol.
Definition: symbol.hpp:17
virtual const i8 * lookup(mem_addr_t)
Lookup an address to resolve a symbol.
Definition: process.cpp:266
chain< symtab > * m_modules
Symbol table list.
Definition: process.hpp:39
virtual pid_t pid() const
Get the process ID.
Definition: process.cpp:158
Lightweight, templated, doubly-linked list (using XOR linking)
Definition: chain.hpp:33
char i8
8-bit signed integer
Definition: config.hpp:72
virtual process & cache_add(mem_addr_t, const i8 *)
Add a symbol to the lookup cache.
Definition: process.cpp:21
virtual bool is_current() const
Check if this is the currently executing thread.
Definition: thread.cpp:185
virtual thread * get_thread(pthread_t) const
Get a thread by ID.
Definition: process.cpp:376
#define likely(expr)
Offer a hint (positive) to the pipeline branch predictor.
Definition: config.hpp:344
This class represents a program/library symbol table (symtab section)
Definition: symtab.hpp:27
virtual u32 symbol_count() const
Get the number of symbols.
Definition: process.cpp:201
static void lock()
Lock the global access mutex.
Definition: util.cpp:397
This class represents a thread of execution in the instrumented process.
Definition: thread.hpp:27
static void unlock()
Unlock the global access mutex.
Definition: util.cpp:406
static void dbg_error(const i8 *,...)
Print an error debug message on the standard error stream.
Definition: util.cpp:726
chain< symbol > * m_symcache
Lookup cache.
Definition: process.hpp:41
This class represents a process, its entire namespace and thread group.
Definition: process.hpp:29
virtual mem_addr_t addr() const
Get the symbol address.
Definition: symbol.cpp:79
virtual process * clone() const
Object virtual copy constructor.
Definition: process.cpp:147
process()
Object default constructor.
Definition: process.cpp:73
virtual process & add_module(const i8 *, mem_addr_t)
Add a symbol table to the namespace. The symbol table is loaded from a non stripped objective code fi...
Definition: process.cpp:236
virtual const i8 * name() const
Get the symbol name.
Definition: symbol.cpp:90
unsigned int u32
32-bit unsigned integer
Definition: config.hpp:102
int i32
32-bit signed integer
Definition: config.hpp:82
virtual const i8 * ilookup(mem_addr_t, mem_addr_t &) const
Inverse lookup. Find the module (executable or DSO library) that defines a symbol and return its path...
Definition: process.cpp:300
virtual const i8 * path() const
Get the objective code file path.
Definition: symtab.cpp:213
virtual const i8 * name() const
Get the thread name.
Definition: thread.cpp:98
virtual const symbol * cache_lookup(mem_addr_t) const
Perform a cache lookup.
Definition: process.cpp:47
unsigned long long mem_addr_t
64-bit memory address
Definition: config.hpp:120
virtual thread * current_thread()
Get the currently executing thread.
Definition: process.cpp:339
virtual u32 module_count() const
Get the number of modules.
Definition: process.cpp:216
pid_t m_pid
Process ID.
Definition: process.hpp:35
#define unlikely(expr)
Offer a hint (negative) to the pipeline branch predictor.
Definition: config.hpp:349
virtual mem_addr_t base() const
Get the load base address.
Definition: symtab.cpp:224
#define __D_ASSERT(x)
Assertion macro.
Definition: config.hpp:268