Collected Windows fixes
[dyninst.git] / proccontrol / src / DecoderWindows.C
1 /*
2  * Copyright (c) 1996-2011 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 "DecoderWindows.h"
33 #include "windows_process.h"
34 #include "windows_handler.h"
35 #include "windows_thread.h"
36 #include "ProcPool.h"
37 #include <iostream>
38 #include "boost/scoped_ptr.hpp"
39 #include "irpc.h"
40 #include <psapi.h>
41 #include "procControl/h/Mailbox.h"
42 #include "int_event.h"
43
44 using namespace std;
45
46 DecoderWindows::DecoderWindows()
47 {
48 }
49
50 DecoderWindows::~DecoderWindows()
51 {
52 }
53
54 unsigned DecoderWindows::getPriority() const 
55 {
56    return Decoder::default_priority;
57 }
58
59 Dyninst::Address DecoderWindows::adjustTrapAddr(Dyninst::Address addr, Dyninst::Architecture arch)
60 {
61   if (arch == Dyninst::Arch_x86 || arch == Dyninst::Arch_x86_64) {
62     return addr-1;
63   }
64   return addr;
65 }
66
67 void DecoderWindows::dumpSurroundingMemory( unsigned problemArea, int_process* proc )
68 {
69         fprintf(stderr, "segfault in mutatee at %p\n", problemArea);
70         for(unsigned i = problemArea-16; i < problemArea+16; i++)
71         {
72                 unsigned char tmp = 0;
73
74                 if(proc->plat_readMem(NULL, &tmp, i, 1)) {
75                         fprintf(stderr, "%p: %x\n", i, tmp);
76                 }
77                 else {
78                         fprintf(stderr, "failed to read from %p\n", i);
79                 }
80         }
81 }
82
83
84 EventLibrary::ptr DecoderWindows::decodeLibraryEvent(DEBUG_EVENT details, int_process* p)
85 {
86         windows_process* proc = dynamic_cast<windows_process*>(p);
87         EventLibrary::ptr newEvt = EventLibrary::ptr(new EventLibrary());
88         std::set<Library::ptr> addedLibs, removedLibs;
89         HANDLE hproc = proc->plat_getHandle();
90         
91         if(details.dwDebugEventCode == LOAD_DLL_DEBUG_EVENT)
92         {
93                 void* libnameaddr;
94                 std::string result = "";
95                 bool read = false;
96                 if (details.u.LoadDll.lpImageName) {
97                         read = p->plat_readMem(NULL, &libnameaddr, (Dyninst::Address)(details.u.LoadDll.lpImageName), 4);
98                 }
99                 //cerr << "imageName @ " << hex << details.u.LoadDll.lpImageName << " and read " << read << dec << endl;
100                 if(details.u.LoadDll.lpImageName && // NULL lpImageName = done
101                         read &&
102                         libnameaddr) // NULL libnameaddr = done
103                 {
104                         result = readLibNameFromProc((Address) libnameaddr, details, p);
105                 }
106                 else {
107                         result = HACKreadFromFile(details, p);
108                 }
109                 //cerr << "\t ... " << result << endl;
110                 int_library* lib = new int_library(result,
111                         (Dyninst::Address)(details.u.LoadDll.lpBaseOfDll),
112                         (Dyninst::Address)(details.u.LoadDll.lpBaseOfDll));
113                 addedLibs.insert(lib->getUpPtr());
114
115                 pthrd_printf("Load DLL event, loading %s (at 0x%lx)\n",
116                         lib->getName().c_str(), lib->getAddr());
117                 //fprintf(stderr, "Load DLL event, loading %s (at 0x%lx)\n",
118                 //      lib->getName().c_str(), lib->getAddr());
119
120         }
121         else if(details.dwDebugEventCode == UNLOAD_DLL_DEBUG_EVENT)
122         {
123                 std::set<int_library*>::iterator foundLib;
124                 for(foundLib = proc->memory()->libs.begin();
125                         foundLib != proc->memory()->libs.end();
126                         ++foundLib)
127                 {
128                         if((*foundLib)->getAddr() == (Dyninst::Address)(details.u.UnloadDll.lpBaseOfDll))
129                         {
130                                 pthrd_printf("Unload DLL event, unloading %s (was at 0x%lx)\n",
131                                         (*foundLib)->getName().c_str(), (*foundLib)->getAddr());
132                                 removedLibs.insert((*foundLib)->getUpPtr());
133                                 //proc->memory()->libs.erase(foundLib);
134                                 break;
135                         }
136                 }
137         }
138         newEvt->setLibs(addedLibs, removedLibs);
139         newEvt->setSyncType(Event::sync_process);
140         return newEvt;
141 }
142
143 Event::ptr DecoderWindows::decodeSingleStepEvent(DEBUG_EVENT e, int_process* proc, int_thread* thread)
144 {
145         Event::ptr evt;
146         // This handles user-level breakpoints; if we can't associate this with a thread we know about, it's not
147         // something the user installed (or we're in an inconsistent state). Forward to the mutatee.
148         if(!thread) return evt;
149
150         assert(thread->singleStep());
151         bp_instance *clearingbp = thread->isClearingBreakpoint();
152         if(clearingbp) {
153                 pthrd_printf("Decoded event to breakpoint cleanup\n");
154                 evt = Event::ptr(new EventBreakpointRestore(new int_eventBreakpointRestore(clearingbp)));
155         } else {
156                 evt = Event::ptr(new EventSingleStep());
157         }
158
159         CONTEXT verification;
160         verification.ContextFlags = CONTEXT_FULL;
161         ::GetThreadContext(((windows_thread *)thread)->plat_getHandle(), &verification);
162
163         if (verification.EFlags & TF_BIT) {
164                 pthrd_printf("BUG ENCOUNTERED: OS handled us a thread with TF set, clearing manually\n");
165                 verification.EFlags &= (~TF_BIT);
166                 ::SetThreadContext(((windows_thread *)thread)->plat_getHandle(), &verification);
167         }
168
169         return evt;
170 }
171
172 Event::ptr DecoderWindows::decodeBreakpointEvent(DEBUG_EVENT e, int_process* proc, int_thread* thread)
173 {
174         Event::ptr evt;
175         // This handles user-level breakpoints; if we can't associate this with a thread we know about, it's not
176         // something the user installed (or we're in an inconsistent state). Forward to the mutatee.
177         if(!thread) return evt;
178         Dyninst::Address adjusted_addr = (Dyninst::Address)(e.u.Exception.ExceptionRecord.ExceptionAddress);
179
180         if (rpcMgr()->isRPCTrap(thread, adjusted_addr)) {
181                 pthrd_printf("Decoded event to rpc completion on %d/%d at %lx\n",
182                         proc->getPid(), thread->getLWP(), adjusted_addr);
183                 evt = Event::ptr(new EventRPC(thread->runningRPC()->getWrapperForDecode()));
184                 return evt;
185         }
186
187         sw_breakpoint *ibp = proc->getBreakpoint(adjusted_addr);
188
189         if (ibp) {
190            pthrd_printf("Decoded breakpoint on %d/%d at %lx\n", proc->getPid(), 
191                                         thread->getLWP(), adjusted_addr);
192        EventBreakpoint::ptr event_bp = EventBreakpoint::ptr(new EventBreakpoint(new int_eventBreakpoint(adjusted_addr, ibp, thread)));
193            evt = event_bp;
194            evt->setThread(thread->thread());
195         }
196         return evt;
197
198 }
199
200 #define EXCEPTION_DEBUGGER_IO 0x406D1388
201
202 bool DecoderWindows::decode(ArchEvent *ae, std::vector<Event::ptr> &events)
203 {
204         static Address ntdll_ignore_breakpoint_address = 0;
205
206         assert(ae);
207         ArchEventWindows* winEvt = static_cast<ArchEventWindows*>(ae);
208         assert(winEvt);
209         Event::ptr newEvt = Event::ptr();
210         int_thread *thread = ProcPool()->findThread((Dyninst::LWP)(winEvt->evt.dwThreadId));
211         int_process* proc = ProcPool()->findProcByPid(winEvt->evt.dwProcessId);
212         if(!proc) { return false; }
213         windows_process* windows_proc = dynamic_cast<windows_process*>(proc);
214         if(!windows_proc)
215         {
216                 perr_printf("DecoderWindows::decode() called on nonexistent/deleted process %d/%d\n", 
217                         winEvt->evt.dwProcessId, winEvt->evt.dwThreadId);
218                 return false;
219         }
220         //windows_proc->clearPendingDebugBreak();
221
222         DEBUG_EVENT e = winEvt->evt;
223
224         switch(e.dwDebugEventCode)
225         {
226         case CREATE_PROCESS_DEBUG_EVENT:
227         case CREATE_THREAD_DEBUG_EVENT:
228                 pthrd_printf("decodeProcess/decodeThreadEvent\n");
229                 return decodeCreateThread(e, newEvt, proc, events);
230         case EXCEPTION_DEBUG_EVENT:
231                 pthrd_printf("decodeException\n");
232                 switch(e.u.Exception.ExceptionRecord.ExceptionCode)
233                 {
234                 case EXCEPTION_SINGLE_STEP:
235                         pthrd_printf("Decoding singleStep event on PID %d, TID %d\n", e.dwProcessId, e.dwThreadId);
236                         newEvt = decodeSingleStepEvent(e, proc, thread);
237                         break;
238                         //fprintf(stderr, "Decoded Single-step event at 0x%lx, PID: %d, TID: %d\n", e.u.Exception.ExceptionRecord.ExceptionAddress, e.dwProcessId, e.dwThreadId);
239                 case EXCEPTION_BREAKPOINT:
240                         // Case 1: breakpoint is real breakpoint
241                         pthrd_printf("Caught breakpoint for pid %d, tid %d, PC 0x%lx\n", e.dwProcessId, e.dwThreadId, e.u.Exception.ExceptionRecord.ExceptionAddress);
242                         newEvt = decodeBreakpointEvent(e, proc, thread);
243                         if(newEvt)
244                         {
245                                 pthrd_printf("Decoded Breakpoint event at 0x%lx, PID: %d, TID: %d\n", e.u.Exception.ExceptionRecord.ExceptionAddress, e.dwProcessId, e.dwThreadId);
246                                 //fprintf(stderr, "Decoded Breakpoint event at 0x%lx, PID: %d, TID: %d\n", e.u.Exception.ExceptionRecord.ExceptionAddress, e.dwProcessId, e.dwThreadId);
247                                 break;
248                         }
249                         else
250                         {
251                                 if(proc->getState() != int_process::neonatal &&
252                                         proc->getState() != int_process::neonatal_intermediate)
253                                 {
254                                         bool didSomething = false;
255
256                                    if (windows_proc->pendingDebugBreak())
257                                         {
258                                                 pthrd_printf("Decoded Stop event, PID: %d, TID: %d\n", e.dwProcessId, e.dwThreadId);
259                                                 //newEvt = Event::ptr(new EventStop());
260                                                 windows_proc->setStopThread(e.dwThreadId);
261                                                 return true;
262                                         }
263                                         else
264                                         {
265                                                 pthrd_printf("Decoded unhandled exception (breakpoint) event, PID: %d, TID: %d\n", e.dwProcessId, e.dwThreadId);
266                                                 // Case 3: breakpoint that's not from us, while running. Pass on exception.
267                                                 GeneratorWindows* winGen = static_cast<GeneratorWindows*>(GeneratorWindows::getDefaultGenerator());
268                                                 newEvt = EventSignal::ptr(new EventSignal(e.u.Exception.ExceptionRecord.ExceptionCode));
269                                         }
270                                 }
271                                 else
272                                 {
273                                         // Case 4: breakpoint in ntdll.dll due to startup. This should be skipped and we should bootstrap.
274                                         pthrd_printf("Breakpoint due to startup, ignoring\n");
275                                         newEvt = Event::ptr(new EventBootstrap());
276                                         ntdll_ignore_breakpoint_address = (Address) e.u.Exception.ExceptionRecord.ExceptionAddress;
277                                         if(!thread) {
278                                                 pthrd_printf("DEBUG: Missing thread on startup breakpoint\n");
279                                         }
280                                 }
281                         }
282                         break;
283                 case EXCEPTION_ILLEGAL_INSTRUCTION:
284                         {
285                                 pthrd_printf("SIGILL in mutatee\n");
286                                 GeneratorWindows* winGen = static_cast<GeneratorWindows*>(GeneratorWindows::getDefaultGenerator());
287                                 winGen->markUnhandledException(e.dwProcessId);
288                                 newEvt = EventSignal::ptr(new EventSignal(e.u.Exception.ExceptionRecord.ExceptionCode));
289                                 assert(0);
290                         }
291                         break;
292                 case EXCEPTION_ACCESS_VIOLATION:
293                         {
294                                 pthrd_printf("segfault in mutatee, thread %d/%d\n", e.dwProcessId, e.dwThreadId);
295                                 unsigned problemArea = (unsigned int)(e.u.Exception.ExceptionRecord.ExceptionAddress);
296                                 cerr << "SEGFAULT @ " << hex << problemArea << dec << endl;
297                                 dumpSurroundingMemory(problemArea, proc);
298                                 GeneratorWindows* winGen = static_cast<GeneratorWindows*>(GeneratorWindows::getDefaultGenerator());
299                                 winGen->markUnhandledException(e.dwProcessId);
300                                 newEvt = EventSignal::ptr(new EventSignal(e.u.Exception.ExceptionRecord.ExceptionCode));
301                                 cerr << "Signal is " << e.u.Exception.ExceptionRecord.ExceptionCode << endl;
302                         }
303                         break;
304                         // Thread naming exception. Ignore.
305                 case EXCEPTION_DEBUGGER_IO: {
306                         pthrd_printf("Debugger I/O exception: %lx\n", e.u.Exception.ExceptionRecord.ExceptionInformation[0]);
307                         newEvt = EventNop::ptr(new EventNop());
308                         newEvt->setSyncType(Event::async);
309                         break;
310                 }
311                 default:
312                         {
313                                 pthrd_printf("Decoded unhandled exception event, PID: %d, TID: %d, Exception code = 0x%lx, Exception addr = 0x%lx\n", e.dwProcessId, e.dwThreadId,
314                                         e.u.Exception.ExceptionRecord.ExceptionCode, e.u.Exception.ExceptionRecord.ExceptionAddress);
315                                 GeneratorWindows* winGen = static_cast<GeneratorWindows*>(GeneratorWindows::getDefaultGenerator());
316                                 winGen->markUnhandledException(e.dwProcessId);
317                                 newEvt = EventSignal::ptr(new EventSignal(e.u.Exception.ExceptionRecord.ExceptionCode));
318                         }
319                         break;
320                 }
321                 break;
322         case EXIT_PROCESS_DEBUG_EVENT:
323                 {
324                         pthrd_printf("Decoded ProcessExit event, PID: %d, TID: %d\n", e.dwProcessId, e.dwThreadId);
325                         if(proc->wasForcedTerminated()) {
326                                 newEvt = EventForceTerminate::ptr(new EventForceTerminate(e.u.ExitProcess.dwExitCode));
327                         }
328                         else {
329                                 newEvt = EventExit::ptr(new EventExit(EventType::Post, e.u.ExitProcess.dwExitCode));
330                         }
331                         GeneratorWindows* winGen = static_cast<GeneratorWindows*>(GeneratorWindows::getDefaultGenerator());
332                         winGen->removeProcess(proc);
333                         newEvt->setSyncType(Event::sync_process);
334                         newEvt->setProcess(proc->proc());
335                         // Since we're doing thread exit/proc exit, and this means the thread will go away first,
336                         // we don't set the thread here
337                         if(thread)
338                                 newEvt->setThread(thread->thread());
339                         // We do this here because the generator thread will exit before updateSyncState otherwise
340                         int_threadPool::iterator i = proc->threadPool()->begin();
341                         for (; i != proc->threadPool()->end(); i++) {
342                                 (*i)->getGeneratorState().setState(int_thread::exited);
343                                 (*i)->setExitingInGenerator(true);
344                         }
345 /*                      Event::ptr associatedLWPDestroy = EventLWPDestroy::ptr(new EventLWPDestroy(EventType::Pre));
346                         associatedLWPDestroy->setProcess(proc->proc());
347                         associatedLWPDestroy->setSyncType(Event::sync_process);
348                         if(thread)
349                                 associatedLWPDestroy->setThread(thread->thread());
350                         //associatedLWPDestroy->addSubservientEvent(newEvt);
351                         */
352                         events.push_back(newEvt);
353
354                         return true;
355                 }
356                 break;
357         case EXIT_THREAD_DEBUG_EVENT:
358                 pthrd_printf("Decoded ThreadExit event, PID: %d, TID: %d\n", e.dwProcessId, e.dwThreadId);
359                 if(thread) {
360                         thread->getGeneratorState().setState(int_thread::exited);
361                         thread->setExitingInGenerator(true);
362                         if (e.dwThreadId == windows_proc->getStopThread()) {
363                                 newEvt = EventWinStopThreadDestroy::ptr(new EventWinStopThreadDestroy(EventType::Pre));
364                                 windows_proc->clearStopThread();
365                         }
366                         else {
367                                 newEvt = EventLWPDestroy::ptr(new EventLWPDestroy(EventType::Pre));
368                         }
369                 } else {
370                         // If the thread is NULL, we can't give the user an event with a valid thread object anymore.
371                         // So fail the decode.
372                         return false;
373                 }
374                 break;
375         case LOAD_DLL_DEBUG_EVENT:
376                 pthrd_printf("Decoded LoadDLL event, PID: %d, TID: %d\n", e.dwProcessId, e.dwThreadId);
377                 newEvt = decodeLibraryEvent(e, proc);
378                 break;
379         case UNLOAD_DLL_DEBUG_EVENT:
380                 pthrd_printf("Decoded UnloadDLL event, PID: %d, TID: %d\n", e.dwProcessId, e.dwThreadId);
381                 newEvt = decodeLibraryEvent(e, proc);
382                 break;
383         case OUTPUT_DEBUG_STRING_EVENT:
384                 {
385                         TCHAR buf[1024];
386                         unsigned long bytes_read = 0;
387                         windows_process* winProc = dynamic_cast<windows_process*>(proc);
388                         BOOL result = ::ReadProcessMemory(winProc->plat_getHandle(), e.u.DebugString.lpDebugStringData, buf, 
389                                 e.u.DebugString.nDebugStringLength, &bytes_read);
390                         if(result) {
391                                 pthrd_printf("Decoded DebugString event, string: %s\n", buf);
392                         } else {
393                                 pthrd_printf("Decoded DebugString event, but string was not readable!\n");
394                         }
395
396                         break;
397                 }
398         case RIP_EVENT:
399                 pthrd_printf("Decoded RIP event, PID: %d, TID: %d, error = 0x%lx\n", e.dwProcessId, e.dwThreadId,
400                         e.u.RipInfo.dwError);
401                 newEvt = EventCrash::ptr(new EventCrash(e.u.RipInfo.dwError));
402                 assert(0);
403                 break;
404         default:
405                 assert(!"invalid event type");
406                 return false;
407         }
408         if(newEvt)
409         {
410                 assert(proc);
411                 if(newEvt->getSyncType() == Event::unset)
412                         newEvt->setSyncType(Event::sync_process);
413                 if(thread) {
414                         newEvt->setThread(thread->thread());
415                 }
416                 newEvt->setProcess(proc->proc());
417                 events.push_back(newEvt);
418         }
419         return true;
420 }
421
422 bool DecoderWindows::checkForFullString( DEBUG_EVENT &details, int chunkSize, wchar_t* libName, bool gotString, char* asciiLibName )
423 {
424         if(details.u.LoadDll.fUnicode)
425         {
426                 unsigned int lastCharIndex = chunkSize / sizeof(wchar_t);
427                 libName[lastCharIndex] = L'\0';
428                 wchar_t* first_null = wcschr(libName, L'\0');
429                 gotString = (first_null != &(libName[lastCharIndex]));
430         }
431         else
432         {
433                 asciiLibName[chunkSize] = '0';
434                 char* first_null = strchr(asciiLibName, '\0');
435                 gotString = (first_null != &(asciiLibName[chunkSize]));
436
437         }
438         return gotString;
439 }
440
441 bool DecoderWindows::decodeCreateThread( DEBUG_EVENT &e, Event::ptr &newEvt, int_process* &proc, std::vector<Event::ptr> &events )
442 {
443         pthrd_printf("Decoded CreateThread event, PID: %d, TID: %d\n", e.dwProcessId, e.dwThreadId);
444         proc = ProcPool()->findProcByPid(e.dwProcessId);
445         assert(proc);
446
447         // FIXME once things actually work
448         windows_process* wproc = dynamic_cast<windows_process*>(proc);
449         assert(wproc);
450
451         if(e.dwDebugEventCode == CREATE_PROCESS_DEBUG_EVENT) {
452                 newEvt = WinEventThreadInfo::ptr(new WinEventThreadInfo((Dyninst::LWP)(e.dwThreadId), e.u.CreateProcessInfo.hThread,
453                         e.u.CreateProcessInfo.lpStartAddress, e.u.CreateProcessInfo.lpThreadLocalBase));
454                 newEvt->setThread(proc->threadPool()->initialThread()->thread());
455                 wproc->plat_setHandles(e.u.CreateProcessInfo.hProcess, e.u.CreateProcessInfo.hFile, (Dyninst::Address)e.u.CreateProcessInfo.lpBaseOfImage);
456         } else {
457                 newEvt = WinEventNewThread::ptr(new WinEventNewThread((Dyninst::LWP)(e.dwThreadId), e.u.CreateThread.hThread,
458                         e.u.CreateThread.lpStartAddress, e.u.CreateThread.lpThreadLocalBase));
459         }
460
461
462         newEvt->setProcess(proc->proc());
463         newEvt->setSyncType(Event::sync_process);
464         events.push_back(newEvt);
465         return true;
466 }
467
468
469 std::string DecoderWindows::readLibNameFromProc(Address libnameaddr, DEBUG_EVENT details, int_process *p) {
470         char asciiLibName[(MAX_PATH+1)*sizeof(wchar_t)];
471         wchar_t* libName = (wchar_t*)(asciiLibName);    
472         int lowReadSize = 1;
473         int highReadSize = 128;
474         bool doneReading = false;
475         bool gotString = false;
476         int chunkSize = highReadSize;
477         int changeSize = highReadSize / 2;
478
479         while(!doneReading)
480         {
481                 pthrd_printf("Trying read for libname at 0x%lx, size %d\n", libnameaddr, chunkSize);
482                 // try to read with the current byte count
483                 if(p->plat_readMem(NULL, libName, (Dyninst::Address)libnameaddr, chunkSize))
484                 {
485                         // the read succeeded -
486                         // did we get the full string?
487                         gotString = checkForFullString(details, chunkSize, libName, gotString, asciiLibName);
488                         if(gotString)
489                         {
490                                 doneReading = true;
491                         }
492                         else
493                         {
494                                 // we didn't get the full string,
495                                 // need to try a larger read
496                                 if(chunkSize == highReadSize)
497                                 {
498                                         // we were are the high end of the current range -
499                                         // move to the next range
500                                         lowReadSize = highReadSize + 1;
501                                         highReadSize = highReadSize + 128;
502                                         changeSize = 128; // we will half this before we read again
503                                         if(lowReadSize > (MAX_PATH * sizeof(wchar_t)))
504                                         {
505                                                 // we've tried every range but still failed
506                                                 doneReading = true;
507                                         }
508                                         else
509                                         {
510                                                 chunkSize = highReadSize;
511                                         }
512                                 }
513                                 else
514                                 {
515                                         // we were within the current range -
516                                         // try something higher but still within the range
517                                         chunkSize = chunkSize + changeSize;
518                                 }
519                         }
520                 }
521                 else
522                 {
523                         // the read failed -
524                         // we need to try a smaller read
525                         if(chunkSize > lowReadSize)
526                         {
527                                 unsigned int nextReadSize = chunkSize - changeSize;
528                                 if(nextReadSize == chunkSize)
529                                 {
530                                         // we can't subdivide any further
531                                         doneReading = true;
532                                 }
533                                 else
534                                 {
535                                         chunkSize = nextReadSize;
536                                 }
537                         }
538                         else
539                         {
540                                 // there are no smaller reads to try in this range,
541                                 // and by induction, in any range
542                                 doneReading = true;
543                         }
544                 }
545                 // update the amount that we use to change the read request
546                 changeSize /= 2;
547
548         }
549         if(details.u.LoadDll.fUnicode)
550         {
551                 pthrd_printf("Converting unicode into single-byte characters\n");
552                 // the DLL path is a Unicode string
553                 // we have to convert it to single-byte characters
554                 char* tmp = new char[MAX_PATH];
555                 ::WideCharToMultiByte(CP_ACP, 0, libName, -1, tmp, MAX_PATH, NULL, NULL);
556                 // swap buffers so that asciiLibName points to the single-byte string
557                 // when we're out of this code block
558                 return std::string(tmp);
559         }
560         else
561         {
562                 // the DLL path can be cast correctly
563                 return std::string(asciiLibName);
564         }
565
566
567
568 std::string DecoderWindows::HACKreadFromFile(DEBUG_EVENT details, int_process *p) {
569         std::string ret;
570         // Copied from Dyninst, 20OCT11 - Bernat 
571         // And comment preserved for posterity. Hello, posterity!
572
573         //I'm embarassed to be writing this.  We didn't get a name for the image, 
574     // but we did get a file handle.  According to MSDN, the best way to turn
575     // a file handle into a file name is to map the file into the address space
576     // (using the handle), then ask the OS what file we have mapped at that location.
577     // I'm sad now.
578     
579     void *pmap = NULL;
580     HANDLE fmap = CreateFileMapping(details.u.LoadDll.hFile, NULL, 
581                                     PAGE_READONLY, 0, 1, NULL);
582     if (fmap) {
583         pmap = MapViewOfFile(fmap, FILE_MAP_READ, 0, 0, 1);
584         if (pmap) {   
585             char filename[MAX_PATH+1];
586                         BOOL result = ::GetMappedFileName(GetCurrentProcess(), pmap, filename, MAX_PATH);
587             if (result)
588                 ret = std::string(filename);
589             UnmapViewOfFile(pmap);
590         }
591         CloseHandle(fmap);
592     }
593         return ret;
594 }