proccontrol: Fix Coverity UNINIT_CTOR errors
[dyninst.git] / proccontrol / src / sysv.C
1 /*
2  * See the dyninst/COPYRIGHT file for copyright information.
3  * 
4  * We provide the Paradyn Tools (below described as "Paradyn")
5  * on an AS IS basis, and do not warrant its validity or performance.
6  * We reserve the right to update, modify, or discontinue this
7  * software at any time.  We shall have no obligation to supply such
8  * updates or modifications or any other form of support to you.
9  * 
10  * By your use of Paradyn, you understand and agree that we (or any
11  * other person or entity with proprietary rights in Paradyn) are
12  * under no obligation to provide either maintenance services,
13  * update services, notices of latent defects, or correction of
14  * defects for Paradyn.
15  * 
16  * This library is free software; you can redistribute it and/or
17  * modify it under the terms of the GNU Lesser General Public
18  * License as published by the Free Software Foundation; either
19  * version 2.1 of the License, or (at your option) any later version.
20  * 
21  * This library is distributed in the hope that it will be useful,
22  * but WITHOUT ANY WARRANTY; without even the implied warranty of
23  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
24  * Lesser General Public License for more details.
25  * 
26  * You should have received a copy of the GNU Lesser General Public
27  * License along with this library; if not, write to the Free Software
28  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
29  */
30 #include "common/h/SymReader.h"
31 #include "common/h/dyntypes.h"
32
33 #include "common/src/Types.h"
34 #if defined(os_linux)
35 #include "common/src/linuxKludges.h"
36 #elif defined(os_freebsd)
37 #include "common/src/freebsdKludges.h"
38 #endif
39
40 #include "proccontrol/h/Handler.h"
41 #include "proccontrol/h/PlatFeatures.h"
42
43 #include "proccontrol/src/sysv.h"
44 #include "proccontrol/src/response.h"
45 #include "proccontrol/src/int_handler.h"
46
47 #include <algorithm>
48 #include <cstring>
49 #include <vector>
50 #include <string>
51 #include <set>
52 #include <iostream>
53
54 using namespace Dyninst;
55 using namespace std;
56
57 int_breakpoint *sysv_process::lib_trap = NULL;
58
59 sysv_process::sysv_process(Dyninst::PID p, string e, vector<string> a, vector<string> envp, map<int,int> f) :
60    int_process(p, e, a, envp, f),
61    int_libraryTracking(p, e, a, envp, f),
62    breakpoint_addr(0),
63    lib_initialized(false),
64    procreader(NULL),
65    aout(NULL),
66    translator_(NULL),
67    translator_state(NotReady)
68 {
69    track_libraries = LibraryTracking::getDefaultTrackLibraries();
70 }
71
72 sysv_process::sysv_process(Dyninst::PID pid_, int_process *p) :
73    int_process(pid_, p),
74    int_libraryTracking(pid_, p)
75 {
76    sysv_process *sp = dynamic_cast<sysv_process *>(p);
77    breakpoint_addr = sp->breakpoint_addr;
78    lib_initialized = sp->lib_initialized;
79    track_libraries = sp->track_libraries;
80    aout = new int_library(sp->aout);
81    procreader = NULL;
82    if (sp->procreader)
83       procreader = new PCProcReader(this);
84    translator_ = NULL;
85    if (sp->translator_) {
86      // Delay create because we can't use a
87      // method in a class that inherits from us
88      translator_state = Ready;
89    }
90    else
91      translator_state = NotReady;
92 }
93
94 sysv_process::~sysv_process()
95 {
96    deleteAddrTranslator();
97    if (procreader) {
98       delete procreader;
99       procreader = NULL;
100    }
101 }
102
103 AddressTranslate *sysv_process::constructTranslator(Dyninst::PID pid_)
104 {
105    Address base;   
106    bool result = plat_getInterpreterBase(base);
107    if (result) {
108       return AddressTranslate::createAddressTranslator(pid_, procreader,
109                                                        getSymReader(),
110                                                        INVALID_HANDLE_VALUE,
111                                                        std::string(""), base);
112    }
113    else {
114       return AddressTranslate::createAddressTranslator(pid_, procreader,
115                                                        getSymReader());
116    }
117 }
118
119 PCProcReader::PCProcReader(sysv_process *proc_) :
120    proc(proc_)
121 {
122 }
123
124 PCProcReader::~PCProcReader()
125 {
126    proc->getMemCache()->clear();
127 }
128
129 bool PCProcReader::start()
130 {
131    return true;
132 }
133
134 bool PCProcReader::done()
135 {
136    return true;
137 }
138
139 bool PCProcReader::ReadMem(Address addr, void *buffer, unsigned size)
140 {
141    memCache *cache = proc->getMemCache();
142
143    if (!proc->translator()) {
144       //Can happen if we read during initialization.  We'll fail to read,
145       // and the addrtranslate layer will handle things properly.
146       return false;
147    }
148
149    proc->translator()->setReadAbort(false);
150    async_ret_t ret = cache->readMemory(buffer, addr, size, memresults);
151    switch (ret) {
152       case aret_success:
153          return true;
154       case aret_async:
155          proc->translator()->setReadAbort(true);
156          return false;
157       case aret_error:
158          return false;
159    }
160    return true;
161 }
162
163 bool PCProcReader::GetReg(MachRegister /*reg*/, MachRegisterVal & /*val*/)
164 {
165    assert(0); //Not needed
166    return true;
167 }
168
169 bool PCProcReader::hasPendingAsync()
170 {
171    return proc->getMemCache()->hasPendingAsync();
172 }
173
174 bool PCProcReader::getNewAsyncs(set<response::ptr> &resps)
175 {
176    for (set<mem_response::ptr>::iterator i = memresults.begin(); i != memresults.end(); i++)
177       resps.insert(*i);
178    memresults.clear();
179    return true;
180 }
181
182 bool sysv_process::initLibraryMechanism()
183 {
184   if (lib_initialized) {
185     if( translator() == NULL ) {
186       createAddrTranslator();
187       if (!translator() && procreader->isAsync()) {
188          pthrd_printf("Waiting for async read to finish initializing\n");
189          return false;
190       }
191       if (!translator()) {
192          perr_printf("Error creating address translator object\n");
193          return false;
194       }
195     }
196
197       return true;
198    }
199    lib_initialized = true;
200
201    pthrd_printf("Initializing library mechanism for process %d\n", getPid());
202
203    if (!procreader)
204       procreader = new PCProcReader(this);
205    assert(procreader);
206
207
208    assert(!translator_);
209    createAddrTranslator();
210
211    if (!translator() && procreader->isAsync()) {
212       pthrd_printf("Waiting for async read to finish initializing\n");
213       return false;
214    }
215    if (!translator()) {
216       perr_printf("Error creating address translator object\n");
217       return false;
218    }
219
220    if (!lib_trap) {
221       lib_trap = new int_breakpoint(Breakpoint::ptr());
222       lib_trap->setProcessStopper(true);
223    }
224
225    breakpoint_addr = translator()->getLibraryTrapAddrSysV();
226    if (track_libraries) {
227       pthrd_printf("Installing library breakpoint at %lx\n", breakpoint_addr);
228       if (breakpoint_addr) {
229          addBreakpoint(breakpoint_addr, lib_trap);
230       }
231    }
232
233    return true;
234 }
235
236 bool sysv_process::refresh_libraries(set<int_library *> &added_libs,
237                                      set<int_library *> &rmd_libs,
238                                      bool &waiting_for_async,
239                                      set<response::ptr> &async_responses)
240 {
241    waiting_for_async = false;
242    pthrd_printf("Refreshing list of loaded libraries\n");
243    
244    bool result = initLibraryMechanism();
245    if (!result && procreader && procreader->hasPendingAsync()) {
246       procreader->getNewAsyncs(async_responses);
247       waiting_for_async = true;
248       pthrd_printf("Waiting for async result to init libraries\n");
249       return false;
250    }
251    if (!result) {
252       pthrd_printf("refresh_libraries failed to init the libraries\n");
253       return false;
254    }
255
256    assert(translator());
257    result = translator()->refresh();
258    if (!result && procreader->hasPendingAsync()) {
259       procreader->getNewAsyncs(async_responses);
260       waiting_for_async = true;
261       pthrd_printf("Waiting for async result to read libraries\n");
262       return false;
263    }
264    if (!result) {
265       pthrd_printf("Failed to refresh library list for %d\n", getPid());
266    }
267    for (set<int_library *>::iterator i = mem->libs.begin(); 
268         i != mem->libs.end(); i++) 
269    {
270       (*i)->setMark(false);
271    }
272    vector<LoadedLib *> ll_libs;
273    translator()->getLibs(ll_libs);
274    for (vector<LoadedLib *>::iterator i = ll_libs.begin(); i != ll_libs.end(); i++)
275    {
276       LoadedLib *ll = *i;
277       int_library *lib = (int_library *) ll->getUpPtr();
278       pthrd_printf("Found library %s at %lx\n", ll->getName().c_str(), 
279                    ll->getCodeLoadAddr());
280       if (!lib) {
281          pthrd_printf("Creating new library object for %s\n", ll->getName().c_str());
282          // Note: we set them all to "I'm a shared library"; the a.out is overridden below.
283
284          lib = new int_library(ll->getName(), true, ll->getCodeLoadAddr(), ll->getDynamicAddr());
285          assert(lib);
286          added_libs.insert(lib);
287          ll->setUpPtr((void *) lib);
288          mem->libs.insert(lib);
289       }
290       lib->setMark(true);
291    }
292
293    set<int_library *>::iterator i = mem->libs.begin();
294    while (i != mem->libs.end()) {
295       int_library *lib = *i;
296       if (lib->isMarked()) {
297          i++;
298          continue;
299       }
300       pthrd_printf("Didn't find old library %s at %lx, unloading\n",
301                    lib->getName().c_str(), lib->getAddr());
302       rmd_libs.insert(lib);
303       mem->libs.erase(i++);
304    }
305
306    if (!aout) {
307       LoadedLib *ll_aout = translator()->getExecutable();
308       aout = (int_library *) (ll_aout ? ll_aout->getUpPtr() : NULL);
309       aout->markAOut();
310    }
311
312    return true;
313 }
314
315 Dyninst::Address sysv_process::getLibBreakpointAddr() const
316 {
317    return breakpoint_addr;
318 }
319
320 bool sysv_process::plat_execed()
321 {
322    pthrd_printf("Rebuilding library trap mechanism after exec on %d\n", getPid());
323    if (aout) {
324       // aout has already been deleted in the forking process
325       aout = NULL;
326    }
327    deleteAddrTranslator();
328    if (procreader) {
329       delete procreader;
330       procreader = NULL;
331    }
332    breakpoint_addr = 0x0;
333    lib_initialized = false;
334
335    for (;;) {
336       set<response::ptr> aresps;
337       async_ret_t result = initializeAddressSpace(aresps);
338       if (result == aret_async) {
339          //Not doing performant async handling, as BG does not have exec.
340          waitForAsyncEvent(aresps);
341       }
342       return (result == aret_success);
343    }
344 }
345
346 bool sysv_process::plat_isStaticBinary()
347 {
348   return (breakpoint_addr == 0);
349 }
350
351 int_library *sysv_process::plat_getExecutable()
352 {
353    return aout;
354 }
355
356 bool sysv_process::addSysVHandlers(HandlerPool *) {
357    //Matt: I deleted the SysV handler that was here, but
358    // am leaving the hook in place if new ones ever come
359    // along.
360    return true;
361 }
362
363 bool sysv_process::plat_getInterpreterBase(Address &)
364 {
365    return false;
366 }
367
368 bool sysv_process::setTrackLibraries(bool b, int_breakpoint* &bp, Address &addr, bool &add_bp)
369 {
370    if (b == track_libraries) {
371       bp = NULL;
372       return true;
373    }
374    track_libraries = b;
375    add_bp = track_libraries;
376    bp = lib_trap;
377    addr = breakpoint_addr;
378    return true;
379 }
380
381 bool sysv_process::isTrackingLibraries()
382 {
383    return track_libraries;
384 }
385
386 AddressTranslate *sysv_process::translator() {
387   switch(translator_state) {
388   case NotReady:
389     return NULL;
390   case Ready:
391     translator_state = Creating;
392     translator_ = constructTranslator(getPid());
393     translator_state = Created;
394     return translator_;
395   case Creating:
396     return NULL;
397   case Created:
398     return translator_;
399   default:
400     return NULL;
401   }
402 }
403
404 void sysv_process::createAddrTranslator() {
405   translator_state = Ready;
406 }
407
408 void sysv_process::deleteAddrTranslator() {
409   translator_state = NotReady;
410   if (translator_) delete translator_;
411   translator_ = NULL;
412 }