Build fixes for Windows
[dyninst.git] / dyninstAPI / src / pdwinnt.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
31 #include "common/src/std_namesp.h"
32 #include <iomanip>
33 #include <string>
34 #include "common/src/headers.h"
35 #include "dyninstAPI/src/os.h"
36 #include "dyninstAPI/src/addressSpace.h"
37 #include "binaryEdit.h"
38 #include "common/src/stats.h"
39 #include "common/src/Types.h"
40 #include "dyninstAPI/src/debug.h"
41 #include "dyninstAPI/src/instPoint.h"
42 #include "common/src/ntHeaders.h"
43 #include "dyninstAPI/src/mapped_object.h"
44 #include "dyninstAPI/src/emit-x86.h"
45 #include "common/src/arch.h"
46 #include "dyninstAPI/src/inst-x86.h"
47 #include "dyninstAPI/src/registerSpace.h"
48 #include "image.h"
49 #include "MemoryEmulator/memEmulator.h"
50 #include <boost/tuple/tuple.hpp>
51
52 #include "dyninstAPI/src/ast.h"
53
54 #include "dyninstAPI/src/function.h"
55 #include "dynProcess.h"
56
57 /* XXX This is only needed for emulating signals. */
58 #include "BPatch_thread.h"
59 #include "BPatch_process.h"
60 #include "nt_signal_emul.h"
61 #include "dyninstAPI/src/PCEventMuxer.h"
62
63 // prototypes of functions used in this file
64
65 void InitSymbolHandler( HANDLE hPCProcess );
66 void ReleaseSymbolHandler( HANDLE hPCProcess );
67 extern bool isValidAddress(AddressSpace *proc, Address where);
68
69 void printSysError(unsigned errNo) {
70     char buf[1000];
71     bool result = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, errNo, 
72                   MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
73                   buf, 1000, NULL);
74     if (!result) {
75         fprintf(stderr, "Couldn't print error message\n");
76         printSysError(GetLastError());
77     }
78     fprintf(stderr, "*** System error [%d]: %s\n", errNo, buf);
79     fflush(stderr);
80 }
81
82
83 // check if a file handle is for kernel32.dll
84 static bool kludge_isKernel32Dll(HANDLE fileHandle, std::string &kernel32Name) {
85     static DWORD IndxHigh, IndxLow;
86     static bool firstTime = true;
87     BY_HANDLE_FILE_INFORMATION info;
88     static std::string kernel32Name_;
89
90     if (firstTime) {
91        HANDLE kernel32H;
92        firstTime = false;
93        char sysRootDir[MAX_PATH+1];
94        if (GetSystemDirectory(sysRootDir, MAX_PATH) == 0)
95           assert(0);
96        kernel32Name_ = std::string(sysRootDir) + "\\kernel32.dll";
97        kernel32H = CreateFile(kernel32Name_.c_str(), GENERIC_READ, 
98                               FILE_SHARE_READ, NULL, OPEN_EXISTING, NULL, NULL);
99        assert(kernel32H);
100        if (!GetFileInformationByHandle(kernel32H, &info)) {
101           printSysError(GetLastError());
102           assert(0);
103        }
104        IndxHigh = info.nFileIndexHigh;
105        IndxLow = info.nFileIndexLow;
106        CloseHandle(kernel32H);
107     }
108
109     if (!GetFileInformationByHandle(fileHandle, &info))
110        return false;
111
112     if (info.nFileIndexHigh==IndxHigh && info.nFileIndexLow==IndxLow) {
113       kernel32Name = kernel32Name_;
114       return true;
115     }
116     return false;
117 }
118
119 // osTraceMe is not needed in Windows NT
120 void OS::osTraceMe(void) {}
121
122 bool PCProcess::dumpImage(std::string outFile)
123 {
124   fprintf(stderr, "%s[%d]:  Sorry, dumpImage() not implemented for windows yet\n", FILE__, __LINE__);
125   fprintf(stderr, "\t cannot create '%s' as requested\n", outFile.c_str());
126   return false;
127 }
128
129
130 static void hasIndex(PCProcess *, unsigned, void *data, void *result) 
131 {
132     *((int *) data) = (int) result;
133 }
134
135
136
137
138 bool CALLBACK printMods(PCSTR name, DWORD64 addr, PVOID unused) {
139     fprintf(stderr, " %s @ %llx\n", name, addr);
140     return true;
141 }
142
143
144 // already setup on this FD.
145 // disconnect from controlling terminal 
146 void OS::osDisconnect(void) {
147 }
148
149 bool PCProcess::getMemoryAccessRights(Address addr, PCMemPerm& rights) {
150     if(!pcProc_->getMemoryAccessRights(addr, rights)) {
151             mal_printf("ERROR: failed to get access rights for page %lx, %s[%d]\n",
152                    addr, FILE__, __LINE__);
153         return false;
154     }
155
156     return true;
157 }
158
159 void PCProcess::changeMemoryProtections(Address addr, size_t size,
160                                         PCMemPerm rights, bool setShadow) {
161     PCMemPerm oldRights;
162     unsigned pageSize = getMemoryPageSize();
163
164         Address pageBase = addr - (addr % pageSize);
165         size += (addr % pageSize);
166
167         // Temporary: set on a page-by-page basis to work around problems
168         // with memory deallocation
169         for (Address idx = pageBase, idx_e = pageBase + size;
170          idx < idx_e; idx += pageSize) {
171         mal_printf("setting rights to %s for [%lx %lx)\n",
172                    rights.getPermName().c_str(), idx , idx + pageSize);
173         if (!pcProc_->setMemoryAccessRights(idx, pageSize,
174                                             rights, oldRights)) {
175                         mal_printf("ERROR: failed to set access rights "
176                        "for page %lx, %s[%d]\n", addr, FILE__, __LINE__);
177                 } else if (isMemoryEmulated() && setShadow) {
178                         Address shadowAddr = 0;
179                         PCMemPerm shadowRights;
180                         bool valid = false;
181                         boost::tie(valid, shadowAddr) = getMemEm()->translate(idx);
182                         if (!valid) {
183                                 mal_printf("WARNING: set access rights on page %lx that has "
184                                            "no shadow %s[%d]\n",addr,FILE__,__LINE__);
185                         } else {
186                 if(!pcProc_->setMemoryAccessRights(shadowAddr, pageSize,
187                                                    rights, shadowRights)) {
188                     mal_printf("ERROR: failed to set access rights "
189                                "for page %lx, %s[%d]\n",
190                                 shadowAddr, FILE__, __LINE__);
191                 }
192
193                                 if (shadowRights != oldRights) {
194                                         mal_printf("WARNING: shadow page[%lx] rights %s did not "
195                                "match orig-page [%lx] rights %s\n",
196                                shadowAddr, shadowRights.getPermName().c_str(),
197                                addr, oldRights.getPermName().c_str());
198                                 }
199                         }
200                 }
201         }
202 }
203
204 bool PCProcess::setMemoryAccessRights(Address start, size_t size,
205                                       PCMemPerm rights) {
206     // if (PAGE_EXECUTE_READWRITE == rights || PAGE_READWRITE == rights) {
207     if (rights.isRWX() || rights.isRW() ) {
208         mapped_object *obj = findObject(start);
209         int page_size = getMemoryPageSize();
210         for (Address cur = start; cur < (start + size); cur += page_size) {
211             obj->removeProtectedPage(start -(start % page_size));
212         }
213     }
214     stopProcess();
215     changeMemoryProtections(start, size, rights, true);
216         return true;
217 }
218
219
220 void InitSymbolHandler( HANDLE hPCProcess )
221 {
222 }
223
224 void
225 ReleaseSymbolHandler( HANDLE hPCProcess )
226 {
227     if( !SymCleanup( hPCProcess ) )
228     {
229         // TODO how to report error?
230         fprintf( stderr, "failed to release symbol handler: %x\n",
231             GetLastError() );
232     }
233
234     CloseHandle(hPCProcess);
235 }
236
237
238 /*
239  * stripAtSuffix
240  *
241  * Strips off of a string any suffix that consists of an @ sign followed by
242  * decimal digits.
243  *
244  * str  The string to strip the suffix from.  The string is altered in place.
245  */
246 static void stripAtSuffix(char *str)
247 {
248     // many symbols have a name like foo@4, we must remove the @4
249     // just searching for an @ is not enough,
250     // as it may occur on other positions. We search for the last one
251     // and check that it is followed only by digits.
252     char *p = strrchr(str, '@');
253     if (p) {
254       char *q = p+1;
255       strtoul(p+1, &q, 10);
256       if (q > p+1 && *q == '\0') {
257         *p = '\0';
258       }
259     }
260 }
261
262 char *cplus_demangle(char *c, int, bool includeTypes) { 
263     char buf[1000];
264     if (c[0]=='_') {
265        // VC++ 5.0 seems to decorate C symbols differently to C++ symbols
266        // and the UnDecorateSymbolName() function provided by imagehlp.lib
267        // doesn't manage (or want) to undecorate them, so it has to be done
268        // manually, removing a leading underscore from functions & variables
269        // and the trailing "$stuff" from variables (actually "$Sstuff")
270        unsigned i;
271        for (i=1; i<sizeof(buf) && c[i]!='$' && c[i]!='\0'; i++)
272            buf[i-1]=c[i];
273        buf[i-1]='\0';
274        stripAtSuffix(buf);
275        if (buf[0] == '\0') return 0; // avoid null names which seem to annoy Paradyn
276        return P_strdup(buf);
277     } else {
278        if (includeTypes) {
279           if (UnDecorateSymbolName(c, buf, 1000, UNDNAME_COMPLETE| UNDNAME_NO_ACCESS_SPECIFIERS|UNDNAME_NO_MEMBER_TYPE|UNDNAME_NO_MS_KEYWORDS)) {
280             //   printf("Undecorate with types: %s = %s\n", c, buf);
281             stripAtSuffix(buf);
282             return P_strdup(buf);
283           }
284        }  else if (UnDecorateSymbolName(c, buf, 1000, UNDNAME_NAME_ONLY)) {
285          //     else if (UnDecorateSymbolName(c, buf, 1000, UNDNAME_COMPLETE|UNDNAME_32_BIT_DECODE)) {
286          //     printf("Undecorate: %s = %s\n", c, buf);
287          stripAtSuffix(buf);          
288          return P_strdup(buf);
289        }
290     }
291     return 0;
292 }
293
294 bool OS::osKill(int pid) {
295     bool res;
296     HANDLE h = OpenProcess(PROCESS_ALL_ACCESS, false, pid);
297     if (h == NULL) {
298         return false;
299     }
300     res = TerminateProcess(h,0);
301     CloseHandle(h);
302     return res;
303 }
304
305
306
307 bool getLWPIDs(pdvector <unsigned> &LWPids)
308 {
309   assert (0 && "Not implemented");
310   return false;
311 }
312
313
314 bool AddressSpace::getDyninstRTLibName() {
315     // Set the name of the dyninst RT lib
316     if (dyninstRT_name.length() == 0) {
317         // Get env variable
318         if (getenv("DYNINSTAPI_RT_LIB") != NULL) {
319             dyninstRT_name = getenv("DYNINSTAPI_RT_LIB");
320         }
321         else {
322             std::string msg = std::string("Environment variable ") +
323                std::string("DYNINSTAPI_RT_LIB") +
324                std::string(" has not been defined");
325             showErrorCallback(101, msg);
326             return false;
327         }
328     }
329     //Canonicalize name
330     char *sptr = P_strdup(dyninstRT_name.c_str());
331     for (unsigned i=0; i<strlen(sptr); i++)
332        if (sptr[i] == '/') sptr[i] = '\\';
333     dyninstRT_name = sptr;
334     free(sptr);
335            
336     if (_access(dyninstRT_name.c_str(), 04)) {
337         std::string msg = std::string("Runtime library ") + dyninstRT_name +
338                        std::string(" does not exist or cannot be accessed!");
339         showErrorCallback(101, msg);
340         return false;
341     }
342
343     return true;
344 }
345
346 void loadNativeDemangler() 
347 {
348     // ensure we load line number information when we load
349     // modules, and give us mangled names
350     DWORD dwOpts = SymGetOptions();
351     dwOpts &= ~(SYMOPT_UNDNAME);
352     dwOpts |= SYMOPT_LOAD_LINES;
353     dwOpts &= ~(SYMOPT_DEFERRED_LOADS);
354     SymSetOptions(dwOpts);
355 }
356
357
358 void dyninst_yield()
359 {
360     SwitchToThread();
361 }
362
363 void OS::make_tempfile(char *name) {
364 }
365
366 bool OS::execute_file(char *file) {
367    STARTUPINFO s;
368    PROCESS_INFORMATION proc;
369    BOOL result;
370
371    ZeroMemory(&s, sizeof(s));
372    ZeroMemory(&proc, sizeof(proc));
373    s.cb = sizeof(s);
374
375    result = CreateProcess(NULL, file, NULL, NULL, FALSE, 0, NULL, NULL, 
376                           &s, &proc);
377    if (!result) {
378       fprintf(stderr, "Couldn't create %s - Error %d\n", file, GetLastError());
379       return false;
380    }
381
382    WaitForSingleObject(proc.hProcess, INFINITE);
383    CloseHandle(proc.hProcess);
384    CloseHandle(proc.hThread);
385    return true;
386 }
387
388 void OS::unlink(char *file) {
389    DeleteFile(file);
390 }
391
392 #if !defined(TF_BIT)
393 #define TF_BIT 0x100
394 #endif
395
396 #if defined (cap_dynamic_heap)
397 void PCProcess::inferiorMallocConstraints(Address near, Address &lo, Address &hi,
398                                         inferiorHeapType /* type */ ) 
399 {
400 }
401 #endif
402
403 /**
404  stdcall:
405    * C Naming - Name prefixed by a '_', followed by the name, then an '@',
406      followed by number of bytes in arguments.  
407      i.e. foo(int a, double b) = _foo@12
408    * C++ Naming - __stdcall
409    * Args - Arguments are passed on the stack.
410    * Cleanup - Callee cleans up the stack before returning
411  cdecl:
412    * C Naming - Name prefixed by a '_'
413    * C++ Naming - __cdecl in demangled name
414    * Args - Arguments are passed on the stack.
415    * Cleanup - Caller cleans up the stack after the return
416  fastcall:
417    * C Naming - Name prefixed by a '@', followed by the func name, then 
418      another '@', followed by the number of bytes in the arguments.  i.e.
419      foo(double a, int b, int c, int d) = @foo@20
420    * C++ Naming - __fastcall in the mangled name
421    * Args - First two arguments that are less than DWORD size are passed in ECX & EDX
422    * Cleanup - Callee cleans up the stack before returning
423  thiscall:
424    * C Naming - NA
425    * C++ Naming - __thiscall in the demangled name
426    * 'this' parameter is passed in ECX, others are passed in the stack
427    * Cleanup Callee cleans up the stack before returning
428  **/
429 callType func_instance::getCallingConvention() {
430         //std::cerr << "symtab name (c++): " << symTabName() << std::endl;
431     //const char *name = symTabName().c_str();
432     const int buffer_size = 1024;
433     char buffer[buffer_size];
434     int pos;
435
436     if (callingConv != unknown_call)
437         return callingConv;
438
439     if (symTabName().empty()) {
440                 assert(0);
441         //Umm...
442         return unknown_call;
443     }
444     switch(symTabName()[0]) {
445         case '?':
446             //C++ Encoded symbol. Everything is stored in the C++ name 
447             // mangling scheme
448             UnDecorateSymbolName(symTabName().c_str(), buffer, buffer_size, 
449                 UNDNAME_NO_ARGUMENTS | UNDNAME_NO_FUNCTION_RETURNS);
450                         printf("undecorated name: %s\n", buffer);
451             if (strstr(buffer, "__thiscall")) {
452                 callingConv = thiscall_call;
453                 return callingConv;
454             }
455             if (strstr(buffer, "__fastcall")) {
456                 callingConv = fastcall_call;
457                 return callingConv;
458             }
459             if (strstr(buffer, "__stdcall")) {
460                 callingConv = stdcall_call;
461                 return callingConv;
462             }
463             if (strstr(buffer, "__cdecl")) {
464                 callingConv = cdecl_call;
465                 return callingConv;
466             }
467             break;
468         case '_':
469           //Check for stdcall or cdecl
470           pos = symTabName().find('@');
471           if (pos != std::string::npos) {
472             callingConv = stdcall_call;
473             return callingConv;
474           }
475           else {
476             callingConv = cdecl_call;
477             return callingConv;
478           }
479           break;
480         case '@':
481           //Should be a fast call
482           pos = symTabName().find('@');
483           if (pos != std::string::npos) {
484              callingConv = fastcall_call;
485              return callingConv;
486           }
487           break;
488     }
489
490     //We have no idea what this call is.  We probably got an undecorated
491     // name.  If the function doesn't clean up it's own stack (doesn't 
492     // have a ret #) instruction, then it must be a cdecl call, as that's
493     // the only type that doesn't clean its own stack.
494     //If the function is part of a class, then it's most likely a thiscall,
495     // although that could be incorrect for a static function.  
496     //Otherwise let's guess that it's a stdcall.
497     if (!ifunc()->cleansOwnStack()) {
498         callingConv = cdecl_call;
499     }
500     else if (symTabName().find("::") != std::string::npos) {
501         callingConv = thiscall_call;
502     }
503     else {
504         callingConv = stdcall_call;
505     }
506     return callingConv;
507 }
508
509 static void emitNeededCallSaves(codeGen &gen, Register reg, pdvector<Register> &extra_saves);
510 static void emitNeededCallRestores(codeGen &gen, pdvector<Register> &saves);
511
512 int EmitterIA32::emitCallParams(codeGen &gen, 
513                               const pdvector<AstNodePtr> &operands,
514                               func_instance *target, 
515                               pdvector<Register> &extra_saves, 
516                               bool noCost)
517 {
518     callType call_conven = target->getCallingConvention();
519     int estimatedFrameSize = 0;
520     pdvector <Register> srcs;
521     Register ecx_target = REG_NULL, edx_target = REG_NULL;
522     Address unused = ADDR_NULL;
523     const int num_operands = operands.size();
524
525     switch (call_conven) {
526         case unknown_call:
527         case cdecl_call:
528         case stdcall_call:
529           //Push all registers onto stack
530           for (unsigned u = 0; u < operands.size(); u++) {
531               Register src = REG_NULL;
532               Address unused = ADDR_NULL;
533               if (!operands[u]->generateCode_phase2( gen, false, unused, src)) assert(0);
534               assert(src != REG_NULL);
535               srcs.push_back(src);
536           }
537           break;
538     case thiscall_call:
539         //Allocate the ecx register for the 'this' parameter
540         if (num_operands) {
541             //result = gen.rs()->allocateSpecificRegister(gen, REGNUM_ECX, false);
542             //if (!result) {
543             //    emitNeededCallSaves(gen, REGNUM_ECX, extra_saves);
544             //}
545             if (!operands[0]->generateCode_phase2(gen, 
546                                                   noCost, 
547                                                   unused, ecx_target)) assert(0);
548         }
549         srcs.push_back(Null_Register);
550         //Push other registers onto the stack
551         for (unsigned u = 1; u < operands.size(); u++) {
552               Register src = REG_NULL;
553               Address unused = ADDR_NULL;
554               if (!operands[u]->generateCode_phase2( gen, false, unused, src)) assert(0);
555               assert(src != REG_NULL);
556               srcs.push_back(src);
557         }     
558         break;
559     case fastcall_call:
560         if (num_operands) {
561             //Allocate the ecx register for the first parameter
562             //ecx_target = gen.rs()->allocateSpecificRegister(gen, REGNUM_ECX, false);
563             //if (!ecx_target) {
564             //    emitNeededCallSaves(gen, REGNUM_ECX, extra_saves);
565             //}
566         }
567         if (num_operands > 1) {
568             //Allocate the edx register for the second parameter
569             //edx_target = gen.rs()->allocateSpecificRegister(gen, REGNUM_EDX, false);
570             //if (!edx_target) {
571             //    emitNeededCallSaves(gen, REGNUM_EDX, extra_saves);
572             //}
573         }
574         if (num_operands) {
575             if (!operands[0]->generateCode_phase2(gen, 
576                                                   noCost, 
577                                                   unused, ecx_target)) assert(0);
578         }
579         if (num_operands > 1) {
580             if (!operands[1]->generateCode_phase2(gen, 
581                                                   noCost, unused, edx_target)) assert(0);
582         }
583         srcs.push_back(Null_Register);
584         srcs.push_back(Null_Register);
585
586         //Push other registers onto the stack
587         for (unsigned u = 2; u < operands.size(); u++) {
588               Register src = REG_NULL;
589               Address unused = ADDR_NULL;
590               if (!operands[u]->generateCode_phase2( gen, false, unused, src)) assert(0);
591               assert(src != REG_NULL);
592               srcs.push_back(src);
593         }
594         break;
595     default:
596         fprintf(stderr, "Internal error.  Unknown calling convention\n");
597         assert(0);
598     }
599
600     // push arguments in reverse order, last argument first
601     // must use int instead of unsigned to avoid nasty underflow problem:
602     for (int i=srcs.size() - 1; i >= 0; i--) {
603        if (srcs[i] == Null_Register) continue;
604            RealRegister r = gen.rs()->loadVirtual(srcs[i], gen);
605            ::emitPush(r, gen);
606        estimatedFrameSize += 4;
607        if (operands[i]->decRefCount())
608           gen.rs()->freeRegister(srcs[i]);
609     }
610
611     if (ecx_target != REG_NULL) {
612         //Store the parameter in ecx
613                 gen.rs()->loadVirtualToSpecific(ecx_target, RealRegister(REGNUM_ECX), gen);
614     }
615
616     if (edx_target != REG_NULL) {
617                 gen.rs()->loadVirtualToSpecific(edx_target, RealRegister(REGNUM_EDX), gen);
618     }
619     return estimatedFrameSize;
620 }
621
622 bool EmitterIA32::emitCallCleanup(codeGen &gen, func_instance *target, 
623                      int frame_size, pdvector<Register> &extra_saves)
624 {
625     callType call_conv = target->getCallingConvention();
626     if ((call_conv == unknown_call || call_conv == cdecl_call) && frame_size)
627     {
628         //Caller clean-up
629         emitOpRegImm(0, RealRegister(REGNUM_ESP), frame_size, gen); // add esp, frame_size        
630     }
631  gen.rs()->incStack(-1 * frame_size);
632
633     //Restore extra registers we may have saved when storing parameters in
634     // specific registers
635     //emitNeededCallRestores(gen, extra_saves);
636     return 0;
637 }
638
639 static void emitNeededCallSaves(codeGen &gen, Register regi, 
640                            pdvector<Register> &extra_saves)
641 {
642     extra_saves.push_back(regi);
643     switch (regi) {
644         case REGNUM_EAX:
645             emitSimpleInsn(PUSHEAX, gen);
646             break;
647         case REGNUM_EBX:
648             emitSimpleInsn(PUSHEBX, gen);
649             break;
650         case REGNUM_ECX:
651             emitSimpleInsn(PUSHECX, gen);
652             break;
653         case REGNUM_EDX:
654             emitSimpleInsn(PUSHEDX, gen);
655             break;
656         case REGNUM_EDI:
657             emitSimpleInsn(PUSHEDI, gen);
658             break;
659     }
660 }
661
662 static void emitNeededCallRestores(codeGen &gen, pdvector<Register> &saves)
663 {
664     for (unsigned i=0; i<saves.size(); i++) {
665       switch (saves[i]) {
666           case REGNUM_EAX:
667               emitSimpleInsn(POP_EAX, gen);
668               break;
669           case REGNUM_EBX:
670               emitSimpleInsn(POP_EBX, gen);
671               break;
672           case REGNUM_ECX:
673               emitSimpleInsn(POP_ECX, gen);
674               break;
675           case REGNUM_EDX:
676               emitSimpleInsn(POP_EDX, gen);
677               break;
678           case REGNUM_EDI:
679               emitSimpleInsn(POP_EDI, gen);
680               break;
681       }
682     }
683     saves.clear();
684 }
685
686 mapped_object* PCProcess::createObjectNoFile(Address addr)
687 {
688     Address closestObjEnd = 0;
689     for (unsigned i = 0; i < mapped_objects.size(); i++) {
690         if (addr >= mapped_objects[i]->codeAbs() &&
691             addr < (mapped_objects[i]->codeAbs() +
692                     mapped_objects[i]->imageSize())) {
693             fprintf(stderr,"createObjectNoFile called for addr %lx, "
694                     "matching existing mapped_object %s %s[%d]\n", addr,
695                     mapped_objects[i]->fullName().c_str(), FILE__,__LINE__);
696             return mapped_objects[i];
697         }
698         if (addr >= (mapped_objects[i]->codeAbs() + 
699                      mapped_objects[i]->imageSize()) &&  
700             closestObjEnd < (mapped_objects[i]->codeAbs() + 
701                              mapped_objects[i]->imageSize())) {
702             closestObjEnd = mapped_objects[i]->codeAbs() + 
703                             mapped_objects[i]->imageSize();
704         }
705     }
706
707     Address testRead = 0;
708
709     // WindowsAPI VirtualQueryEx rounds down to pages size,
710     // so we need to round up first.
711     Address ObjOffset = closestObjEnd % getMemoryPageSize();
712     if (ObjOffset) {
713         closestObjEnd = closestObjEnd - ObjOffset + getMemoryPageSize();
714     }
715     if (readDataSpace((void*)addr, getAddressWidth(), &testRead, false)) {
716                 // create a module for the region enclosing this address
717         ProcControlAPI::Process::MemoryRegion memRegion;
718         if (!pcProc_->findAllocatedRegionAround(addr, memRegion)) {
719             mal_printf("ERROR: failed to find allocated region for page %lx, %s[%d]\n",
720                        addr, FILE__, __LINE__);
721                         assert(0);
722             return NULL;
723         }
724
725         mal_printf("[%lx %lx] is valid region containing %lx and corresponding "
726                    "to no object, closest is object ending at %lx %s[%d]\n", 
727                    memRegion.first, memRegion.second, addr, closestObjEnd, FILE__,__LINE__);
728
729         // The size of the region returned by VirtualQueryEx is from BaseAddress
730         // to the end, NOT from meminfo.AllocationBase, which is what we want.
731         // BaseAddress is the start address of the page of the address parameter
732         // that is sent to VirtualQueryEx as a parameter
733         Address regionSize = memRegion.second - memRegion.first;
734
735         // read region into this PCProcess
736         void* rawRegion = malloc(regionSize);
737                 if (!readDataSpace((void *)memRegion.first, regionSize, rawRegion, true)) {
738             mal_printf("Error: failed to read memory region [%lx, %lx]\n",
739                        memRegion.first, memRegion.second);
740                         printSysError(GetLastError());
741                         assert(0);
742             return NULL;
743                 }
744
745                 // set up file descriptor
746         char regname[64];
747         snprintf(regname, 63, "mmap_buffer_%lx_%lx", memRegion.first, memRegion.second);
748         fileDescriptor desc(string(regname),
749                             memRegion.first, /*  code  */
750                             memRegion.first, /*  data  */
751                             regionSize,       /* length */
752                             rawRegion,        /* rawPtr */
753                             true);            /* shared */
754         mapped_object *obj = mapped_object::createMappedObject
755             (desc, this, getHybridMode(), false);
756         if (obj != NULL) {
757             obj->setMemoryImg();
758             //mapped_objects.push_back(obj);
759                 addMappedObject(obj);
760
761             obj->parse_img()->getOrCreateModule(
762                 obj->parse_img()->getObject()->getDefaultModule());
763             return obj;
764         } else {
765             fprintf(stderr,"Failed to create object (that was not backed by a file) at %lx\n", memRegion.first);
766             return NULL;
767         }
768
769     }
770
771     return NULL;
772 }
773
774 bool OS::executableExists(const std::string &file) {
775    struct stat file_stat;
776    int stat_result;
777
778    stat_result = stat(file.c_str(), &file_stat);
779    if (stat_result == -1)
780        stat_result = stat((file + std::string(".exe")).c_str(), &file_stat);
781    return (stat_result != -1);
782 }
783
784 bool PCProcess::hasPassedMain() 
785 {
786    return true;
787 }
788
789
790 bool PCProcess::startDebugger()
791 {
792    return false;
793 }
794
795 // Temporary remote debugger interface.
796 // I assume these will be removed when procControlAPI is complete.
797 bool OS_isConnected(void)
798 {
799     return true;  // We're always connected to the child on this platform.
800 }
801
802 bool OS_connect(BPatch_remoteHost &remote)
803 {
804     return true;  // We're always connected to the child on this platform.
805 }
806
807 bool OS_getPidList(BPatch_remoteHost &remote,
808                    BPatch_Vector<unsigned int> &tlist)
809 {
810     return false;  // Not implemented.
811 }
812
813 bool OS_getPidInfo(BPatch_remoteHost &remote,
814                    unsigned int pid, std::string &pidStr)
815 {
816     return false;  // Not implemented.
817 }
818
819 bool OS_disconnect(BPatch_remoteHost &remote)
820 {
821     return true;
822 }
823
824 bool PCProcess::dumpCore(std::string coreFile)
825 {
826         assert(0);
827         return false;
828 }
829
830 bool PCProcess::hideDebugger()
831 {
832         Dyninst::ProcControlAPI::Thread::const_ptr threadPtr_ = pcProc_->threads().getInitialThread();
833         if (!threadPtr_)
834                 return false;
835         Address tibPtr = threadPtr_->getThreadInfoBlockAddr();
836     if (!tibPtr) {
837         return false;
838     }
839
840     // read in address of PEB
841     unsigned int pebPtr;
842     if (!readDataSpace((void*)(tibPtr+48), getAddressWidth(), (void*)&pebPtr, false)) {
843         fprintf(stderr, "%s[%d] Failed to read address of Process Environment "
844                 "Block at 0x%x, which is TIB + 0x30\n", FILE__,__LINE__,tibPtr+48);
845         return false;
846     }
847
848     // patch up the processBeingDebugged flag in the PEB
849     unsigned char flag;
850     if (!readDataSpace((void*)(pebPtr+2), 1, (void*)&flag, true)) 
851         return false;
852     if (flag) {
853         flag = 0;
854         if (!writeDataSpace((void*)(pebPtr+2), 1, (void*)&flag)) 
855             return false;
856     }
857
858     //while we're at it, clear the NtGlobalFlag
859     if (!readDataSpace((void*)(pebPtr+0x68), 1, (void*)&flag, true)) 
860         return false;
861     if (flag) {
862         flag = flag & 0x8f;
863         if (!writeDataSpace((void*)(pebPtr+0x68), 1, (void*)&flag)) 
864             return false;
865     }
866
867     // clear the heap flags in the PEB
868     unsigned int heapBase;
869     unsigned int flagWord;
870     if (!readDataSpace((void*)(pebPtr+0x18), 4, (void*)&heapBase, true)) 
871         return false;
872
873     // clear the flags in the heap itself
874     if (!readDataSpace((void*)(heapBase+0x0c), 4, (void*)&flagWord, true)) 
875         return false;
876     flagWord = flagWord & (~0x50000062);
877     if (!writeDataSpace((void*)(heapBase+0x0c), 4, (void*)&flagWord)) 
878         return false;
879     if (!readDataSpace((void*)(heapBase+0x10), 4, (void*)&flagWord, true)) 
880         return false;
881     flagWord = flagWord & (~0x40000060);
882     if (!writeDataSpace((void*)(heapBase+0x10), 4, (void*)&flagWord)) 
883         return false;
884
885     return true;
886 }
887
888 unsigned long PCProcess::setAOutLoadAddress(fileDescriptor &desc)
889 {
890         assert(0);
891         return 0;
892 }
893
894 bool PCEventMuxer::useCallback(Dyninst::ProcControlAPI::EventType et)
895 {
896     // This switch statement can be derived from the EventTypes and Events
897     // table in the ProcControlAPI manual -- it states what Events are
898     // available on each platform
899     
900     switch(et.code()) {
901         case Dyninst::ProcControlAPI::EventType::Exit:
902             switch(et.time()) {
903                 case Dyninst::ProcControlAPI::EventType::Pre:
904                   return true;
905                 default:
906                     break;
907             }
908             break;
909                 case Dyninst::ProcControlAPI::EventType::LWPDestroy:
910             switch(et.time()) {
911                 case Dyninst::ProcControlAPI::EventType::Pre:
912                   return true;
913                 default:
914                     break;
915             }
916             break;
917     }
918
919     return false;
920 }
921
922 bool PCEventMuxer::useBreakpoint(Dyninst::ProcControlAPI::EventType et)
923 {
924 //  if(et.code() == Dyninst::ProcControlAPI::EventType::Exit &&
925 //     et.time() == Dyninst::ProcControlAPI::EventType::Pre)
926 //    return true;
927   
928   return false;
929 }
930
931 bool PCEventHandler::isKillSignal(int signal)
932 {
933         // Kill on Windows does not generate a signal
934         return false;
935 }
936 bool PCEventHandler::isCrashSignal(int signal)
937 {
938         switch(signal)
939         {
940         case EXCEPTION_ACCESS_VIOLATION:
941         case EXCEPTION_ARRAY_BOUNDS_EXCEEDED:
942         case EXCEPTION_DATATYPE_MISALIGNMENT:
943         case EXCEPTION_FLT_DIVIDE_BY_ZERO:
944         case EXCEPTION_FLT_INVALID_OPERATION:
945         case EXCEPTION_ILLEGAL_INSTRUCTION:
946         case EXCEPTION_IN_PAGE_ERROR:
947         case EXCEPTION_INT_DIVIDE_BY_ZERO:
948         case EXCEPTION_NONCONTINUABLE_EXCEPTION:
949         case EXCEPTION_PRIV_INSTRUCTION:
950         case EXCEPTION_STACK_OVERFLOW:
951                 return true;
952         }
953         return false;
954 }
955 bool PCEventHandler::shouldStopForSignal(int signal)
956 {
957         switch(signal)
958         {
959                 case EXCEPTION_BREAKPOINT:
960                         return true;
961         }
962         return false;
963 }
964 bool PCEventHandler::isValidRTSignal(int signal, PCEventHandler::RTBreakpointVal breakpointVal,
965                                                                          Dyninst::Address arg1, int status)
966 {
967         if(signal == EXCEPTION_BREAKPOINT)
968         {
969         if( breakpointVal == NormalRTBreakpoint ) {
970             if( (status != DSE_forkExit) || (arg1 != 0) ) return true;
971
972             proccontrol_printf("%s[%d]: child received signal %d\n",
973                     FILE__, __LINE__, EXCEPTION_BREAKPOINT);
974         } else if( breakpointVal == SoftRTBreakpoint ) {
975             if( status == DSE_forkExit ) {
976                 if( arg1 == 0 ) return true;
977
978                 proccontrol_printf("%s[%d]: parent process received SIGSTOP\n",
979                         FILE__, __LINE__);
980             }else{
981                 proccontrol_printf("%s[%d]: SIGSTOP wasn't due to fork exit\n",
982                         FILE__, __LINE__);
983             }
984         } else {
985             proccontrol_printf("%s[%d]: mismatch in signal for breakpoint type\n",
986                     FILE__, __LINE__);
987         }
988         } else {
989         proccontrol_printf("%s[%d]: signal wasn't sent by RT library\n",
990                 FILE__, __LINE__);
991     }
992
993         return false;
994 }
995
996 bool AddressSpace::usesDataLoadAddress() const
997 {
998         return false;
999 }
1000 bool PCProcess::setEnvPreload(std::vector<std::string> &envp, std::string fileName)
1001 {
1002         // We don't LD_PRELOAD on Windows
1003         return true;
1004 }
1005
1006 void PCProcess::redirectFds(int stdin_fd, int stdout_fd, int stderr_fd, std::map<int,int> &result)
1007 {
1008         // Not implemented on existing dyninst-on-windows, just skip
1009         return;
1010 }
1011 std::string PCProcess::createExecPath(const std::string &file, const std::string &dir)
1012 {
1013         return dir + file;
1014 }
1015
1016 bool PCProcess::multithread_capable(bool ignoreIfMtNotSet)
1017 {
1018         return true;
1019 }
1020
1021 bool PCProcess::copyDanglingMemory(PCProcess *parent)
1022 {
1023         assert(0);
1024         return false;
1025 }
1026
1027 bool PCProcess::instrumentMTFuncs()
1028 {
1029         // This is not needed on Windows, as we get thread events directly.
1030         return true;
1031 }
1032
1033 bool PCProcess::getExecFileDescriptor(std::string filename, bool waitForTrap, fileDescriptor &desc)
1034 {
1035         Address mainFileBase = 0;
1036         Dyninst::ProcControlAPI::ExecFileInfo* efi = pcProc_->getExecutableInfo();
1037
1038         desc = fileDescriptor(filename, efi->fileBase, efi->fileBase, false);
1039         desc.setHandles(efi->processHandle, efi->fileHandle);
1040
1041         delete efi;
1042         return true;
1043 }
1044
1045 bool PCProcess::skipHeap(const heapDescriptor &heap)
1046 {
1047         return false;
1048 }
1049
1050
1051 inferiorHeapType PCProcess::getDynamicHeapType() const
1052 {
1053         return anyHeap;
1054 }
1055
1056
1057 void OS::get_sigaction_names(std::vector<std::string> &names)
1058 {
1059         //names.push_back("signal");
1060 }
1061
1062 bool PCProcess::getDyninstRTLibName()
1063 {
1064     startup_printf("Begin getDyninstRTLibName\n");
1065     bool use_abi_rt = false;
1066 #if defined(arch_64bit)
1067     use_abi_rt = (getAddressWidth() == 4);
1068 #endif
1069
1070     std::vector<std::string> rt_paths;
1071     std::string rt_base = "dyninstAPI_RT";
1072     if(use_abi_rt) rt_base += "_m32";
1073     rt_base += ".dll";
1074     if(!BinaryEdit::getResolvedLibraryPath(rt_base, rt_paths) || rt_paths.empty())
1075     {
1076         startup_printf("%s[%d]: Could not find %s in search path\n", FILE__, __LINE__, rt_base.c_str());
1077         return false;
1078     }
1079     for(auto i = rt_paths.begin();
1080         i != rt_paths.end();
1081         ++i)
1082     {
1083         startup_printf("%s[%d]: Candidate RTLib is %s\n", FILE__, __LINE__, i->c_str());
1084     }
1085     dyninstRT_name = rt_paths[0];
1086     return true;
1087 }