Update copyright to LGPL on all files
[dyninst.git] / dyninstAPI / src / pdwinntDL.C
1 /*
2  * Copyright (c) 1996-2009 Barton P. Miller
3  * 
4  * We provide the Paradyn Parallel Performance Tools (below
5  * described as "Paradyn") on an AS IS basis, and do not warrant its
6  * validity or performance.  We reserve the right to update, modify,
7  * or discontinue this software at any time.  We shall have no
8  * obligation to supply such updates or modifications or any other
9  * form of support to you.
10  * 
11  * By your use of Paradyn, you understand and agree that we (or any
12  * other person or entity with proprietary rights in Paradyn) are
13  * under no obligation to provide either maintenance services,
14  * update services, notices of latent defects, or correction of
15  * defects for Paradyn.
16  * 
17  * This library is free software; you can redistribute it and/or
18  * modify it under the terms of the GNU Lesser General Public
19  * License as published by the Free Software Foundation; either
20  * version 2.1 of the License, or (at your option) any later version.
21  * 
22  * This library is distributed in the hope that it will be useful,
23  * but WITHOUT ANY WARRANTY; without even the implied warranty of
24  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
25  * Lesser General Public License for more details.
26  * 
27  * You should have received a copy of the GNU Lesser General Public
28  * License along with this library; if not, write to the Free Software
29  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
30  */
31
32 #include "dynamiclinking.h"
33 #include "process.h"
34 #include "signalhandler.h"
35 #include "dyn_lwp.h"
36 #include "mapped_object.h"
37 #include <windows.h>
38 #include <string>
39
40 // Since Windows handles library loads for us, there is nothing to do here
41 // Write in stubs to make the platform-indep code happy
42
43 extern std::string GetLoadedDllImageName( process* p, const DEBUG_EVENT& ev );
44 extern void printSysError(unsigned errNo);
45
46 sharedLibHook::sharedLibHook(process *p, sharedLibHookType t, Address b) 
47         : proc_(p), type_(t), breakAddr_(b), loadinst_(NULL) {}
48
49 sharedLibHook::~sharedLibHook() {}
50
51 bool dynamic_linking::initialize() {
52    dynlinked = true;
53    return true;
54 }
55
56
57 bool dynamic_linking::installTracing()
58 {
59     return true;
60 }
61
62 bool dynamic_linking::decodeIfDueToSharedObjectMapping(EventRecord &, unsigned int &)
63 {
64     // This can be called by a platform indep. layer that wants
65     // to get the list of new libraries loaded. 
66     return false;
67 }
68 bool dynamic_linking::getChangedObjects(EventRecord &, pdvector<mapped_object *> &)
69 {
70     // This can be called by a platform indep. layer that wants
71     // to get the list of new libraries loaded. 
72     return true;
73 }
74 bool dynamic_linking::handleIfDueToSharedObjectMapping(EventRecord &ev, 
75                                  pdvector<mapped_object*> &changed_objects,
76                                  pdvector<bool> &is_new_object)
77 {
78    if (!ev.lwp)
79        //Return early if we're in the call from loadDyninstLib.
80        // Windows can handle this without the special case call.
81        return true;
82
83    process *proc = ev.proc;
84    handleT procHandle = ev.lwp->getProcessHandle();
85
86    if (ev.type == evtLoadLibrary) {
87      std::string imageName = GetLoadedDllImageName( proc, ev.info );
88
89          parsing_printf("%s[%d]: load dll %s: hFile=%x, base=%x, debugOff=%x, debugSz=%d lpname=%x, %d\n",
90          __FILE__, __LINE__,
91          imageName.c_str(),
92          ev.info.u.LoadDll.hFile, ev.info.u.LoadDll.lpBaseOfDll,
93          ev.info.u.LoadDll.dwDebugInfoFileOffset,
94          ev.info.u.LoadDll.nDebugInfoSize,
95          imageName.c_str(),
96          ev.info.u.LoadDll.fUnicode,
97          GetFileSize(ev.info.u.LoadDll.hFile,NULL));
98      startup_printf("Loaded dll: %s\n", imageName.c_str());
99
100          if (!imageName.length())
101                  return true;
102      DWORD64 iresult = SymLoadModule64(procHandle, ev.info.u.LoadDll.hFile, 
103                                  (PSTR) imageName.c_str(), NULL,
104                                  (DWORD64) ev.info.u.LoadDll.lpBaseOfDll, 0);
105      if (!iresult) {
106        printSysError(GetLastError());
107            fprintf(stderr, "[%s:%u] - Couldn't SymLoadModule64\n", FILE__, __LINE__);
108            return true;
109      }
110
111      fileDescriptor desc(imageName.c_str(), 
112                          (Address)ev.info.u.LoadDll.lpBaseOfDll,
113                          (HANDLE)procHandle,
114                          ev.info.u.LoadDll.hFile, true, 
115                          (Address)ev.info.u.LoadDll.lpBaseOfDll);   
116      // discover structure of new DLL, and incorporate into our
117      // list of known DLLs
118      mapped_object *newobj = mapped_object::createMappedObject(desc, proc);
119      if (!newobj) {
120          fprintf(stderr, "[%s:%u] - Couldn't parse loaded module %s\n", 
121                  FILE__,__LINE__, imageName.c_str());
122          return true;
123      }
124      changed_objects.push_back(newobj);
125      is_new_object.push_back(true);
126      ev.what = SHAREDOBJECT_ADDED;
127          return true;
128    }
129    /**
130     * Handle the library unload case.
131         **/
132     Address base = (Address) ev.info.u.UnloadDll.lpBaseOfDll;
133     bool result = SymUnloadModule64(procHandle, base);
134         if (!result) {
135        printSysError(GetLastError());
136            fprintf(stderr, "[%s:%u] - Couldn't SymUnloadModule64\n", FILE__, __LINE__);
137         }
138         
139         mapped_object *oldobj = NULL;
140         const pdvector<mapped_object *> &objs = proc->mappedObjects();
141         for (unsigned i=0; i<objs.size(); i++) {
142             if (objs[i]->codeBase() == base) {
143                 oldobj = objs[i];
144                 break;
145             }
146         }
147         if (!oldobj) 
148             return true;
149     changed_objects.push_back(oldobj);
150     is_new_object.push_back(false);
151     ev.what = SHAREDOBJECT_REMOVED;
152     return true;
153 }
154
155 bool dynamic_linking::processLinkMaps(pdvector<fileDescriptor> &) {
156     // Empty list so nothing happens
157
158     return true;
159 }