BOOL loadDllCallback(DEBUG_EVENT& oDebugEvent, cThreadContext& oThreadContext, cProcessInformation& oProcessInformation) {
/*  if (oThreadContext.bThreadIs64Bit && !oProcessInformation.bIs64Bit) {
    LOG(_tprintf(_T("logHeapAllocation: LoadLibrary: Call by x64 code in x86 process %u, thread %u ignored.\r\n"), oDebugEvent.dwProcessId, oDebugEvent.dwThreadId));
    // 64-bit code running in 32-bit process: this is WoW64 code and not the application, so ignore it.
    return TRUE;
  }*/
  LOG(_tprintf(_T("logHeapAllocation: process %u (%s), thread %u (%s) => process %s.\r\n"), 
    oDebugEvent.dwProcessId, oProcessInformation.bIs64Bit ? _T("x64") : _T("x86"), 
    oDebugEvent.dwThreadId, oThreadContext.bThreadIs64Bit ? _T("x64") : _T("x86"),
    oThreadContext.bProcessIs64Bit ? _T("x64") : _T("x86")
  ));
  std::basic_string<TCHAR>* psDllFilePath = oProcessInformation.getDllFilePath((PBYTE)oDebugEvent.u.LoadDll.lpBaseOfDll);
  if (!psDllFilePath) {
    _tprintf(_T("{\"sEventName\": \"internalError\", \"sErrorMessage\": \"Cannot get module file name for modulke at 0x%IX.\"};\r\n"), oDebugEvent.u.LoadDll.lpBaseOfDll);
    return FALSE;
  }
  std::basic_string<TCHAR> sNtdll = _T("ntdll.dll");
  std::basic_string<TCHAR>::reverse_iterator ritsNtdll = sNtdll.rbegin();
  std::basic_string<TCHAR>::reverse_iterator ritsDllFilePath = psDllFilePath->rbegin();
  while (ritsNtdll != sNtdll.rend() && ritsDllFilePath != psDllFilePath->rend() && _totlower(*ritsDllFilePath) == *ritsNtdll) {
    ritsNtdll++;
    ritsDllFilePath++;
  };
  if (ritsNtdll != sNtdll.rend()) {
    // DLL path does not end in "ntdll.dll"
    return TRUE;
  }
  if (ritsDllFilePath != psDllFilePath->rend() && *ritsDllFilePath != _T('\\')) {
    // DLL path is not "ntdll.dll" and does not end in "\\ntdll.dll"
    return TRUE;
  }
  // This is ntdll.dll.
  PBYTE pfHeapAlloc = getRemoteProcAddress(oProcessInformation, (PBYTE)oDebugEvent.u.LoadDll.lpBaseOfDll, _T("RtlAllocateHeap"));
  if (!pfHeapAlloc) {
    _tprintf(_T("{\"sEventName\": \"internalError\", \"sErrorMessage\": \"Cannot get address of ntdll!HeapAlloc.\"};\r\n"));
    return FALSE;
  }
  if (!setBreakpoint(oDebugEvent.dwProcessId, pfHeapAlloc, &handleRtlAllocateHeapCall)) {
    _tprintf(_T("{\"sEventName\": \"internalError\", \"sErrorMessage\": \"Cannot set breakpoint on ntdll!HeapAlloc: 0x%X\"};\r\n"), GetLastError());
    return FALSE;
  }
  LOG(_tprintf(_T("logHeapAllocation: ntdll!HeapAlloc: Breakpoint at 0x%IX added in process %u.\r\n"), pfHeapAlloc, oDebugEvent.dwProcessId));
  PBYTE pfHeapFree = getRemoteProcAddress(oProcessInformation, (PBYTE)oDebugEvent.u.LoadDll.lpBaseOfDll, _T("RtlFreeHeap"));
  if (!pfHeapFree) {
    _tprintf(_T("{\"sEventName\": \"internalError\", \"sErrorMessage\": \"Cannot get address of ntdll!HeapFree.\"};\r\n"));
    return FALSE;
  }
  if (!setBreakpoint(oDebugEvent.dwProcessId, pfHeapFree, &handleRtlFreeHeapCall)) {
    _tprintf(_T("{\"sEventName\": \"internalError\", \"sErrorMessage\": \"Cannot set breakpoint on ntdll!HeapFree: 0x%X\"};\r\n"), GetLastError());
    return FALSE;
  }
  LOG(_tprintf(_T("logHeapAllocation: ntdll!HeapFree: Breakpoint at 0x%IX added in process %u.\r\n"), pfHeapFree, oDebugEvent.dwProcessId));
  return TRUE;
}
Beispiel #2
0
static void processEvents(LLDBPlugin* plugin, PDReader* reader, PDWriter* writer)
{
    uint32_t event;

    while ((event = PDRead_get_event(reader)))
    {
        //printf("LLDBPlugin: %d Got event %s\n", event, eventTypes[event]);

        switch (event)
        {
            case PDEventType_GetExceptionLocation : setExceptionLocation(plugin, writer); break;
            case PDEventType_GetCallstack : setCallstack(plugin, writer); break;
            case PDEventType_SetExecutable : setExecutable(plugin, reader); break;
            case PDEventType_SelectThread : selectThread(plugin, reader, writer); break;
            case PDEventType_SelectFrame : selectFrame(plugin, reader, writer); break;
            case PDEventType_GetLocals : setLocals(plugin, writer); break;
            case PDEventType_GetThreads : setThreads(plugin, writer); break;
            case PDEventType_GetSourceFiles : setSourceFiles(plugin, writer); break;
            case PDEventType_SetBreakpoint : setBreakpoint(plugin, reader, writer); break;
            case PDEventType_Action : eventAction(plugin, reader); break;
        }
    }

    setTty(plugin, writer);
}
BOOL handleRtlFreeHeapCall(DEBUG_EVENT& oDebugEvent, cThreadContext& oThreadContext, cProcessInformation& oProcessInformation) {
  if (oThreadContext.bThreadIs64Bit && !oProcessInformation.bIs64Bit) {
    LOG(_tprintf(_T("logHeapAllocation: ntdll!HeapFree: Call by x64 code in x86 process %u, thread %u ignored.\r\n"), oDebugEvent.dwProcessId, oDebugEvent.dwThreadId));
    // 64-bit code running in 32-bit process: this is WoW64 code and not the application, so ignore it.
    return TRUE;
  }
  if (gdoActiveHeapFreeCall_by_dwThreadId_by_dwProcessId[oDebugEvent.dwProcessId].count(oDebugEvent.dwThreadId) != 0) {
    LOG(_tprintf(_T("logHeapAllocation: ntdll!HeapFree: Recursive call in process %u, thread %u ignored.\r\n"), oDebugEvent.dwProcessId, oDebugEvent.dwThreadId));
    return TRUE;
  }
  HEAP_FREE_CALL* poActiveHeapFreeCall = new HEAP_FREE_CALL();
  poActiveHeapFreeCall->dwProcessId = oDebugEvent.dwProcessId;
  poActiveHeapFreeCall->dwThreadId = oDebugEvent.dwThreadId;
  PBYTE pStackPointer;
  PBYTE pRetAddress;
#ifdef _WIN64
  if (oThreadContext.bThreadIs64Bit) {
    poActiveHeapFreeCall->hHeapHandle = (PVOID)oThreadContext.x64.Rcx;
    poActiveHeapFreeCall->uFlags = (ULONG)oThreadContext.x64.Rdx;
    poActiveHeapFreeCall->pHeapBase = (PVOID)oThreadContext.x64.R8;
    pStackPointer = (PBYTE)oThreadContext.x64.Rsp;
    if (!oProcessInformation.readBytes(pStackPointer, (PBYTE)&pRetAddress, sizeof(pRetAddress), FALSE)) {
      _tprintf(_T("{\"sEventName\": \"internalError\", \"sErrorMessage\": \"Cannot read ntdll!HeapFree return address from stack.\"};\r\n"));
      delete poActiveHeapFreeCall;
      return FALSE;
    }
  } else
#endif
  {
    pStackPointer = (PBYTE)oThreadContext.x86.Esp;
    DWORD* pdwBuffer = new DWORD[4];
    if (!oProcessInformation.readBytes(pStackPointer, (PBYTE)pdwBuffer, 4 * sizeof(DWORD), FALSE)) {
      _tprintf(_T("{\"sEventName\": \"internalError\", \"sErrorMessage\": \"Cannot read ntdll!HeapFree return address and arguments from stack.\"};\r\n"));
      delete pdwBuffer;
      delete poActiveHeapFreeCall;
      return FALSE;
    }
    pRetAddress = (PBYTE)pdwBuffer[0];
    poActiveHeapFreeCall->hHeapHandle = (HANDLE)pdwBuffer[1];
    poActiveHeapFreeCall->uFlags = (ULONG)pdwBuffer[2];
    poActiveHeapFreeCall->pHeapBase = (PVOID)pdwBuffer[3];
    delete pdwBuffer;
  }
  LOG(_tprintf(_T("logHeapAllocation: ntdll!HeapFree: CALL by 0x%IX in process %u, thread %u: HeapFree(0x%IX, 0x%X, 0x%IX) = ...\r\n"),
      pRetAddress, oDebugEvent.dwProcessId, oDebugEvent.dwThreadId, poActiveHeapFreeCall->hHeapHandle, poActiveHeapFreeCall->uFlags, poActiveHeapFreeCall->pHeapBase));
  
  if (!setBreakpoint(oDebugEvent.dwProcessId, pRetAddress, handleRtlFreeHeapReturn)) {
    _tprintf(_T("{\"sEventName\": \"internalError\", \"sErrorMessage\": \"Cannot set breakpoint on ntdll!HeapFree return address.\"};\r\n"));
    delete poActiveHeapFreeCall;
    return FALSE;
  }
  LOG(_tprintf(_T("logHeapAllocation: ntdll!HeapFree: Breakpoint for caller 0x%IX added in process.\r\n"), pRetAddress, oDebugEvent.dwProcessId));
  gdoActiveHeapFreeCall_by_dwThreadId_by_dwProcessId[oDebugEvent.dwProcessId][oDebugEvent.dwThreadId] = poActiveHeapFreeCall;
  return TRUE;
}
Beispiel #4
0
int CommandLineDebugger::breakpointCmd(const std::vector<std::string>& tokens) {
    cout << "breakpoint " << tokens.size() << endl;
    if(tokens.size() < 2)
        throw std::runtime_error("breakpoint command not enough arguments; Usage: b 100");
    stringstream ss;
    ss << tokens[1];
    unsigned int line = 0;
    ss >> line;
    setBreakpoint(line);
    return 1;
}
/**
 * Do any enabling of events (including setting breakpoints etc)
 * needed to get the events requested by this handler node.
 */
static jvmtiError
enableEvents(HandlerNode *node)
{
    jvmtiError error = JVMTI_ERROR_NONE;

    switch (NODE_EI(node)) {
        /* The stepping code directly enables/disables stepping as
         * necessary
         */
        case EI_SINGLE_STEP:
        /* Internal thread event handlers are always present
         * (hardwired in the event hook), so we don't change the
         * notification mode here.
         */
        case EI_THREAD_START:
        case EI_THREAD_END:
        case EI_VM_INIT:
        case EI_VM_DEATH:
        case EI_CLASS_PREPARE:
        case EI_GC_FINISH:
            return error;

        case EI_FIELD_ACCESS:
        case EI_FIELD_MODIFICATION:
            error = setWatchpoint(node);
            break;

        case EI_BREAKPOINT:
            error = setBreakpoint(node);
            break;

        default:
            break;
    }

    /* Don't globally enable if the above failed */
    if (error == JVMTI_ERROR_NONE) {
        jthread thread = requestThread(node);

        /* If this is the first request of it's kind on this
         * thread (or all threads (thread == NULL)) then enable
         * these events on this thread.
         */
        if (!eventHandlerRestricted_iterator(
                NODE_EI(node), matchThread, thread)) {
            error = threadControl_setEventMode(JVMTI_ENABLE,
                                               NODE_EI(node), thread);
        }
    }
    return error;
}
Beispiel #6
0
void rntSetBp(int address)
{
	char buff[56];

	switch(setBreakpoint(address))
	{
	case ERR_OutOfMemory:
		consoleOut("CRITICAL: PseudoAsm out of memory!\n");
		break;
	case ERR_None:
		sprintf(buff, "Breakpoint set at address %d\n", address);
		consoleOut(buff);
		break;
	default:
		//assert(0);
		consoleOut("Unknown error\n");
		break;
	}
}
Beispiel #7
0
static void processEvents(DbgEngPlugin* plugin, PDReader* reader, PDWriter* writer) {
    printf("DbgEngPlugin: processEvents\n");

    PDEventType event;

    while ((event = (PDEventType)PDRead_get_event(reader))) {
        printf("DbgEngPlugin: %d Got event %s\n", (int)event, eventTypes[event]);

        switch (event) {
            case PDEventType_getExceptionLocation:
                setExceptionLocation(plugin, writer); break;
            case PDEventType_getCallstack:
                setCallstack(plugin, writer); break;
            case PDEventType_setExecutable:
                setExecutable(plugin, reader); break;
            case PDEventType_getLocals:
                setLocals(plugin, writer); break;
            case PDEventType_setBreakpoint:
                setBreakpoint(plugin, reader, writer); break;
            case PDEventType_action:
                eventAction(plugin, reader); break;
        }
    }
}
void remoteGdbMainLoop(Core *core, int enableFbWindow)
{
	int listenSocket;
	struct sockaddr_in address;
	socklen_t addressLength;
	int got;
	char request[256];
	uint32_t i;
	bool noAckMode = false;
	int optval;
	char response[256];
	uint32_t currentThread = 0;
	
	gCore = core;
	gLastSignals = calloc(sizeof(int), getTotalThreads(core));
	for (i = 0; i < getTotalThreads(core); i++)
		gLastSignals[i] = 0;

	listenSocket = socket(PF_INET, SOCK_STREAM, 0);
	if (listenSocket < 0)
	{
		perror("error setting up debug socket (socket)");
		return;
	}

	optval = 1;
	if (setsockopt(listenSocket, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval)) < 0)
	{
		perror("error setting up debug socket (setsockopt)");
		return;
	}
	
	address.sin_family = AF_INET;
	address.sin_port = htons(8000);
	address.sin_addr.s_addr = htonl(INADDR_ANY);
	if (bind(listenSocket, (struct sockaddr*) &address, sizeof(address)) < 0)
	{	
		perror("error setting up debug socket (bind)");
		return;
	}

	if (listen(listenSocket, 1) < 0)
	{
		perror("error setting up debug socket (listen)");
		return;
	}
	
	while (true)
	{
		// Wait for a new client socket
		while (true)
		{
			addressLength = sizeof(address);
			gClientSocket = accept(listenSocket, (struct sockaddr*) &address,
				&addressLength);
			if (gClientSocket >= 0)
				break;
		}
		
		noAckMode = false;

		// Process commands
		while (true)
		{
			got = readPacket(request, sizeof(request));
			if (got < 0) 
				break;
			
			if (!noAckMode)
			{
				if (write(gClientSocket, "+", 1) != 1)
				{
					perror("Error writing to debug socket");
					exit(1);
				}
			}

			switch (request[0])
			{
				// Set arguments
				case 'A':
					// We don't support setting program arguments, so just silently ignore.
					sendResponsePacket("OK");
					break;

				// Continue
				case 'c':
				case 'C':
					runUntilInterrupt(core, ALL_THREADS, enableFbWindow);
					gLastSignals[currentThread] = TRAP_SIGNAL;
					sendFormattedResponse("S%02x", gLastSignals[currentThread]);
					break;

				// Pick thread
				case 'H':
					if (request[1] == 'g' || request[1] == 'c')
					{
						// XXX hack: the request type controls which operations this
						// applies for.
						currentThread = (uint32_t)(request[2] - '1');
						sendResponsePacket("OK");
					}
					else
						sendResponsePacket("");

					break;
					
				// Kill 
				case 'k':
					return;

				// Read/write memory
				case 'm':
				case 'M':
				{
					char *lenPtr;
					char *dataPtr;
					unsigned int start;
					unsigned int length;
					unsigned int offset;
					
					start = (uint32_t) strtoul(request + 1, &lenPtr, 16);
					length = (uint32_t) strtoul(lenPtr + 1, &dataPtr, 16);
					if (request[0] == 'm')
					{
						// Read memory
						for (offset = 0; offset < length; offset++)
							sprintf(response + offset * 2, "%02x", readMemoryByte(core, start + offset));
					
						sendResponsePacket(response);
					}
					else
					{
						// Write memory
						dataPtr += 1;	// Skip colon
						for (offset = 0; offset < length; offset++)
							writeMemoryByte(core, start + offset, decodeHexByte(dataPtr + offset * 2));

						sendResponsePacket("OK");
					}
					
					break;
				}

				// Read register
				case 'p':
				case 'g':
				{
					uint32_t regId = (uint32_t) strtoul(request + 1, NULL, 16);
					uint32_t value;
					if (regId < 32)
					{
						value = getScalarRegister(core, currentThread, regId);
						sendFormattedResponse("%08x", endianSwap32(value));
					}
					else if (regId < 64)
					{
						uint32_t lane;
						
						for (lane = 0; lane < NUM_VECTOR_LANES; lane++)
						{
							value = getVectorRegister(core, currentThread, regId, lane);
							sprintf(response + lane * 8, "%08x", endianSwap32(value));
						}

						sendResponsePacket(response);
					}
					else
						sendResponsePacket("");
				
					break;
				}
				
				// XXX need to implement write register
									
				// Query
				case 'q':
					if (strcmp(request + 1, "LaunchSuccess") == 0)
						sendResponsePacket("OK");
					else if (strcmp(request + 1, "HostInfo") == 0)
						sendResponsePacket("triple:nyuzi;endian:little;ptrsize:4");
					else if (strcmp(request + 1, "ProcessInfo") == 0)
						sendResponsePacket("pid:1");
					else if (strcmp(request + 1, "fThreadInfo") == 0)
						sendResponsePacket("m1,2,3,4");	// XXX need to query number of threads
					else if (strcmp(request + 1, "sThreadInfo") == 0)
						sendResponsePacket("l");
					else if (memcmp(request + 1, "ThreadStopInfo", 14) == 0)
						sprintf(response, "S%02x", gLastSignals[currentThread]);
					else if (memcmp(request + 1, "RegisterInfo", 12) == 0)
					{
						uint32_t regId = (uint32_t) strtoul(request + 13, NULL, 16);
						if (regId < 32)
						{
							sprintf(response, "name:s%d;bitsize:32;encoding:uint;format:hex;set:General Purpose Scalar Registers;gcc:%d;dwarf:%d;",
								regId, regId, regId);
								
							if (regId >= 28)
								sprintf(response + strlen(response), "generic:%s;", kGenericRegs[regId - 28]);
						}
						else if (regId < 64)
						{
							sprintf(response, "name:v%d;bitsize:512;encoding:uint;format:vector-uint32;set:General Purpose Vector Registers;gcc:%d;dwarf:%d;",
								regId - 32, regId, regId);
						}
						else
							strcpy(response, "");
						
						sendResponsePacket(response);
					}
					else if (strcmp(request + 1, "C") == 0)
						sendFormattedResponse("QC%02x", currentThread + 1);
					else
						sendResponsePacket("");	// Not supported
					
					break;

				// Set Value
				case 'Q':
					if (strcmp(request + 1, "StartNoAckMode") == 0)
					{
						noAckMode = true;
						sendResponsePacket("OK");
					}
					else
						sendResponsePacket("");	// Not supported
					
					break;
					
				// Single step
				case 's':
				case 'S':
					singleStep(core, currentThread);
					gLastSignals[currentThread] = TRAP_SIGNAL;
					sendFormattedResponse("S%02x", gLastSignals[currentThread]);
					break;
					
				// Multi-character command
				case 'v':
					if (strcmp(request, "vCont?") == 0)
						sendResponsePacket("vCont;C;c;S;s");
					else if (memcmp(request, "vCont;", 6) == 0)
					{
						// XXX hack.  There are two things lldb requests.  One is
						// to step one thread while resuming the others.  In this case,
						// I cheat and only step the one.  The other is just to continue,
						// which I perform in the else clause.
						const char *sreq = strchr(request, 's');
						if (sreq != NULL)
						{
							// s:0001
							currentThread = (uint32_t) strtoul(sreq + 2, NULL, 16) - 1;
							singleStep(core, currentThread);
							gLastSignals[currentThread] = TRAP_SIGNAL;
							sendFormattedResponse("S%02x", gLastSignals[currentThread]);
						}
						else
						{
							runUntilInterrupt(core, ALL_THREADS, enableFbWindow);
							gLastSignals[currentThread] = TRAP_SIGNAL;
							sendFormattedResponse("S%02x", gLastSignals[currentThread]);
						}
					}
					else
						sendResponsePacket("");
					
					break;
					
				// Clear breakpoint
				case 'z':
					if (clearBreakpoint(core, (uint32_t) strtoul(request + 3, NULL, 16)) < 0)
						sendResponsePacket(""); // Error
					else
						sendResponsePacket("OK");

					break;
					
				// Set breakpoint
				case 'Z':
					if (setBreakpoint(core, (uint32_t) strtoul(request + 3, NULL, 16)) < 0)
						sendResponsePacket(""); // Error
					else
						sendResponsePacket("OK");

					break;
					
				// Get last signal
				case '?':
					sprintf(response, "S%02x", gLastSignals[currentThread]);
					sendResponsePacket(response);
					break;
					
				// Unknown, return error
				default:
					sendResponsePacket("");
			}
		}

		close(gClientSocket);
	}
}
Beispiel #9
0
bool dlgDirectDbg::activateDebugger( )
{
	// Unset the completed flag (if it exists)
	if (m_codeWindow)
		m_codeWindow->m_targetComplete = false;

	// Copy the parameter values from the grid into m_targetInfo
	int i = 0;

	for( int count = 0; count < m_targetInfo->getArgCount(); ++count )
	{
		wsArgInfo &arg = (*m_targetInfo)[count];

		// Populate the ArgInfo object's IN or INOUT variables only, OUT
		// variables will be assigned NULL later on.

		if(arg.getMode() != wxT("o"))
		{
			arg.setValue( grdParams->GetCellValue(i, COL_VALUE));
			i++;
		}
	}

	// Write the target OID and argument values to our settings file
	// so that we can default them next time around
	saveSettings();

	// Now set a breakpoint at the target (note: the call to setBreakpoint()
	// will hang until the  server sends us a response)

	try
	{
		// Debug the initialiser. We can only do so once, so unset, and disable
		// the option after setting the breakpoint
		if( chkPkgInit->GetValue())
			setBreakpoint( m_targetInfo->getPkgOid(), m_targetInfo->getPkgInitOid());

		chkPkgInit->SetValue(false);
		chkPkgInit->Disable();

		setBreakpoint( m_targetInfo->getPkgOid(), m_targetInfo->getOid());
	}
	catch( const std::runtime_error &error )
	{
		wxMessageBox( wxString( error.what(), wxConvUTF8 ), _( "Cannot create breakpoint" ), wxOK | wxICON_ERROR );
		return( false );
	}

	// And invoke the target (note: the call to invokeTarget() will *NOT*
	// wait for a result set from the server - instead, OnResultReady() will
	// be called when the result set is ready)

	try
	{
		invokeTarget();
	}
	catch( const std::runtime_error &error )
	{
		wxMessageBox( wxString( error.what(), wxConvUTF8 ), _( "Cannot invoke target" ), wxOK | wxICON_ERROR );
		return( false );
	}

	return( true );
}
Beispiel #10
0
int main(int argc, char *argv[])
{
  //int ret;
  int c;
  unsigned short i=0, ac;
  unsigned short rom_adr, startAdr=i8086_BEGINADR;  /* Mem-Viewer Startadresse  */
  char str[6];
  char cfgStr[i8086_CFG_MAX_VALUE_LEN];
  unsigned short adr;
  codeView cv;                             /* Code-Viewer Data */

  if (argc<2)
  {
                    printf("i8086emu "VERSION_NUMBER);
                    printf("\nUsage: %s [OPTIONS] FILENAME\n", argv[0]);
                    printf("\nOptions:");
                    printf("\n -c\t\t\tCodeViewer deaktivieren");
                    printf("\n -o XXXXh\t\tStartadresse");
                    printf("\n -r XXXXh\t\tStartadresse ROM-File");
                    printf("\n -d file\t\tDUMP-File");
                    printf("\n --version\t\tshow version information");
                    printf("\n --help\t\t\tthis help information");
                    printf("\n");

    exit(1);
  }
  
  
  signal(SIGTERM, resetAll);
  signal(SIGINT, resetAll);
  signal(SIGQUIT, resetAll);
  signal(SIGSEGV, resetAll);
  
  i8086clearLog(); /* Log-File leeren. */
  i8086init(); /* Prozessor initialisieren. */
  oldPortHandler = i8086SetMsgFunc(i8086_SIG_PORT_OUT, portSignalHandler);

  /* Config-File laden */
  if (i8086ReadStrConfig(cfgStr, CONFIG_FILE, "ROMFILE")!=0)
  {
    rom_adr = i8086ReadHexConfig(CONFIG_FILE, "ROMSTARTADR", 0xc000);
    LoadRomFile(cfgStr, rom_adr);
  }
  else /* Wenn ROM -> kein Core-Dump */
    if (i8086ReadStrConfig(cfgStr, CONFIG_FILE, "COREDUMP")!=0)
      LoadCoreDumpFile(cfgStr);
  startAdr = i8086ReadHexConfig(CONFIG_FILE, "PROGSTARTADR", 0x0100);
    
  for (ac=1; ac<argc; ac++) /* Programmargumente auswerten und speichern */
  {
    char *str;
    
    if(strcmp(argv[ac],"--version")==0)
    {
                    printf("i8086emu "VERSION_NUMBER"\n"
                    "Copyright (C) 2004 JMH, RD, FB, CST\n"
                    "i8086emu comes with NO WARRANTY,\n"
                    "to the extent permitted by law.\n"
                    "You may redistribute copies of i8086emu\n"
                    "under the terms of the GNU General Public License.\n");
                    exit(1);
    }
    if(strcmp(argv[ac],"--help")==0)
    {
                    printf("i8086emu "VERSION_NUMBER);
                    printf("\nUsage: %s [OPTIONS] FILENAME\n", argv[0]);
                    printf("\nOptions:");
                    printf("\n -c\t\t\tCodeViewer deaktivieren");
                    printf("\n -o XXXXh\t\tStartadresse");
                    printf("\n -r XXXXh\t\tStartadresse ROM-File");
                    printf("\n -d file\t\tDUMP-File");
                    printf("\n --version\t\tshow version information");
                    printf("\n --help\t\t\tthis help information");
                    printf("\n");

    exit(1);
    }          
    if (strcmp(argv[ac], "-c")==0)          /* CodeViewer deaktivieren */
      args |= HIDE_CODE_VIEWER;
    if ((str=strstr(argv[ac], "-o"))!=NULL) /* Startadresse des Programmes setzen */
    {
      str = strtok(str, "-o");
      if (str!=NULL)
        startAdr = strtoul(str, NULL, 16);
    }
    if ((str=strstr(argv[ac], "-r"))!=NULL) /* ROM laden */
    {
      //int adr;
      if (argc<ac+2)
      {
        printf("\n -r XXXXh file -> Startadresse ROM-File");
        exit(1);
      }
      rom_adr = strtoul(argv[ac+1], NULL, 16);
      LoadRomFile(argv[ac+2], rom_adr);
    }
    if ((str=strstr(argv[ac], "-d"))!=NULL) /* Core-Dump laden */
    {
      if (argc<ac+1)
      {
        printf("\n -d file -> DUMP-File");
        exit(1);
      }       
      LoadCoreDumpFile(argv[ac+1]);
    }
  }

  if (i8086loadBinFile(core, argv[argc-1], startAdr)!=i8086_SUC_FILELOAD)
  {
    i8086error(argv[argc-1], i8086_ERR_STR_FILENF);    
  }
  if (args & LOAD_ROM) /* ROM verarbeiten */
    startAdr = rom_adr;
  core->pc = startAdr;
    
  initscr();
  clear();
  refresh();
  createWin();

  printReg();
  printFlags();
  printLeds(0);
  printSwitches();
  printDisplay();
  printMem(startAdr);
  cv.startAdr = 0;//i8086_BEGINADR;
  cv.endAdr = 0;

  printCode(core, commands, &cv);
  //i8086PushMsg(1, 1);

  noecho();     /* getch echo aus */
  curs_set(0);  /* Cursor ausschalten */

  keypad(stdscr,1);
  //while (/*c=='g' ||*/ (c=getch/*ar*/())!='q')

  //sendepuffer ist leer
  //core->ports.x[0xD2]=3;

  while ((c==ERR && i%50000!=0) || (c=getch/*ar*/())!='q') //automode nur aller 50000 takte abbrechbar, reicht aber aus, sonst wars zu langsam
  {
    i++;
    if (c==KEY_F(9))
      nodelay(stdscr,TRUE);
    else if (c=='n')
      nodelay(stdscr,FALSE);
    else if (c==KEY_F(8))
    {
    	adr=i8086GetSegRegister_fast(core,i8086_REG_CS, 1)+core->pc;
    	stepover=adr+commands[core->mem[adr]]->size;
	if (commands[core->mem[adr]]->hasMod!=0)
		stepover+=getAdditionalCmdLength(core, core->mem[adr], core->mem[adr+1]);
    	nodelay(stdscr,TRUE);
    }

    if (c==ERR||c=='n') /* next Opcode */
      if (i8086execCommand(core, commands)==i8086_ERR_ILGOPCODE)
      {
        sprintf(str, "%hd", core->mem[core->pc + i8086GetSegRegister_fast(core, i8086_REG_CS, 1)]);
        i8086error(i8086_ERR_STR_ILGOPCODE, str);
        //resetAll(0);
      }

    if (i8086GetSegRegister_fast(core,i8086_REG_CS, 1)+core->pc==breakpoint || i8086GetSegRegister_fast(core,i8086_REG_CS, 1)+core->pc==stepover)
    {
    	i=0;
    	nodelay(stdscr,FALSE);
	    c=0;
    }

    if (c=='r') /* set Registervalue */
      setReg();
    else if (c==KEY_F(1)) /* Print Help */
      printHelp();
    else if (c==KEY_F(2)) //Breakpoint setzen
      {
      	setBreakpoint();
	c=0;
      }
    else if (c=='m') /* Anfangsadresse von Speicherviewer setzen */
      startAdr=readMem();
    else if (c=='w') /* Wert von Speicherzelle setzen */
      setMem();
    else if (c==KEY_F(3)) /* CoreDump */
      coreDump();
    else if ((c>='0')&&(c<='7')) /* Schalter An/Aus */
    {
      unsigned char dual[] = {1,2,4,8,16,32,64,128};
      core->ports.x[0] = core->ports.x[0] ^ dual[atoi((char*)&c)];
    }
    else if (c==KEY_F(12))	//Reset Taste
    {
    	i=0;
    	core->pc=0x0c000;
	i8086SetSegRegister(core,i8086_REG_CS,0xc00);
	i8086SetRegister(core,i8086_REG_AX,1,0);
	//i8086SetRegister(core,i8086_REG_BX,1,0);
	//i8086SetRegister(core,i8086_REG_CX,1,0);
	//i8086SetRegister(core,i8086_REG_DX,1,0);
	//nodelay(stdscr,TRUE);
    }

    handleKeyboard(core,c);

    if (c!=ERR)
    {
      printReg();
      printFlags();
      printSwitches();
      printDisplay();
      printMem(startAdr);
      printCode(core, commands, &cv);
    //printLeds();
    }
  }

  resetAll(0);

  return EXIT_SUCCESS;
}
Beispiel #11
0
void remoteGdbMainLoop(Core *core, int enableFbWindow)
{
	int listenSocket;
	struct sockaddr_in address;
	socklen_t addressLength;
	int got;
	char request[256];
	int i;
	int noAckMode = 0;
	int optval;
	char response[256];
	int currentThread = 0;
	
	gCore = core;
	gLastSignal = calloc(sizeof(int), getTotalThreads(core));
	for (i = 0; i < getTotalThreads(core); i++)
		gLastSignal[i] = 0;

	listenSocket = socket(PF_INET, SOCK_STREAM, 0);
	if (listenSocket < 0)
	{
		perror("socket");
		return;
	}

	optval = 1;
	setsockopt(listenSocket, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof optval);
	
	address.sin_family = AF_INET;
	address.sin_port = htons(8000);
	address.sin_addr.s_addr = htonl(INADDR_ANY);
	if (bind(listenSocket, (struct sockaddr*) &address, sizeof(address)) < 0)
	{	
		perror("bind");
		return;
	}

	if (listen(listenSocket, 4) < 0)
	{
		perror("bind");
		return;
	}
	
	while (1)
	{
		// Wait for a new client socket
		while (1)
		{
			addressLength = sizeof(address);
			gClientSocket = accept(listenSocket, (struct sockaddr*) &address,
				&addressLength);
			if (gClientSocket >= 0)
				break;
		}
		
#if DUMP_MESSAGES
		printf("Got connection from debugger\n");
#endif
		noAckMode = 0;

		// Process commands
		while (1)
		{
			got = readPacket(request, sizeof(request));
			if (got < 0) 
				break;
			
			if (!noAckMode)
				write(gClientSocket, "+", 1);

#if DUMP_MESSAGES
			printf("<< %s\n", request);
#endif

			switch (request[0])
			{
				// Set arguments
				case 'A':
					sendResponsePacket("OK");	// Yeah, whatever
					break;

				// continue
				case 'c':
				case 'C':
					runUntilInterrupt(core, -1, enableFbWindow);
					gLastSignal[currentThread] = TRAP_SIGNAL;
					sendFormattedResponse("S%02x", gLastSignal[currentThread]);
					break;

				// Pick thread
				case 'H':
					if (request[1] == 'g' || request[1] == 'c')
					{
						// XXX hack: the request type controls which operations this
						// applies for.
						currentThread = request[2] - '1';
						sendResponsePacket("OK");
					}
					else
					{
#if DUMP_MESSAGES
						printf("Unhandled command %s\n", request);
#endif
						sendResponsePacket("");
					}

					break;
					
				// Kill 
				case 'k':
#if DUMP_MESSAGES
					printf("Exit requested\n");
#endif
					exit(1);
					break;

				// Read/write memory
				case 'm':
				case 'M':
				{
					char *lenPtr;
					unsigned int start;
					unsigned int length;
					unsigned int offset;
					
					start = strtoul(request + 1, &lenPtr, 16);
					length = strtoul(lenPtr + 1, NULL, 16);
					if (request[0] == 'm')
					{
						// Read memory
						for (offset = 0; offset < length; offset++)
							sprintf(response + offset * 2, "%02x", readMemoryByte(core, start + offset));
					
						sendResponsePacket(response);
					}
					else
					{
						// XXX write memory
					}
					
					break;
				}

				// read register
				case 'p':
				case 'g':
				{
					int regId = strtoul(request + 1, NULL, 16);
					int value;
					if (regId < 32)
					{
						value = getScalarRegister(core, currentThread, regId);
						sendFormattedResponse("%08x", endianSwap32(value));
					}
					else if (regId < 64)
					{
						int lane;
						
						for (lane = 0; lane < 16; lane++)
						{
							value = getVectorRegister(core, currentThread, regId, lane);
							sprintf(response + lane * 8, "%08x", endianSwap32(value));
						}

						sendResponsePacket(response);
					}
					else
						sendResponsePacket("");
				
					break;
				}
									
				// Query
				case 'q':
					if (strcmp(request + 1, "LaunchSuccess") == 0)
						sendResponsePacket("OK");
					else if (strcmp(request + 1, "HostInfo") == 0)
						sendResponsePacket("triple:nyuzi;endian:little;ptrsize:4");
					else if (strcmp(request + 1, "ProcessInfo") == 0)
						sendResponsePacket("pid:1");
					else if (strcmp(request + 1, "fThreadInfo") == 0)
						sendResponsePacket("m1,2,3,4");
					else if (strcmp(request + 1, "sThreadInfo") == 0)
						sendResponsePacket("l");
					else if (memcmp(request + 1, "ThreadStopInfo", 14) == 0)
						sprintf(response, "S%02x", gLastSignal[currentThread]);
					else if (memcmp(request + 1, "RegisterInfo", 12) == 0)
					{
						int regId = strtoul(request + 13, NULL, 16);
						if (regId < 32)
						{
							sprintf(response, "name:s%d;bitsize:32;encoding:uint;format:hex;set:General Purpose Scalar Registers;gcc:%d;dwarf:%d;",
								regId, regId, regId);
								
							if (regId >= 28)
								sprintf(response + strlen(response), "generic:%s;", kGenericRegs[regId - 28]);
						}
						else if (regId < 64)
						{
							sprintf(response, "name:v%d;bitsize:512;encoding:uint;format:vector-uint32;set:General Purpose Vector Registers;gcc:%d;dwarf:%d;",
								regId - 32, regId, regId);
						}
						else
							strcpy(response, "");
						
						sendResponsePacket(response);
					}
					else if (strcmp(request + 1, "C") == 0)
						sendFormattedResponse("QC%02x", currentThread + 1);
					else
						sendResponsePacket("");	// Not supported
					
					break;

				// Set Value
				case 'Q':
					if (strcmp(request + 1, "StartNoAckMode") == 0)
					{
						noAckMode = 1;
						sendResponsePacket("OK");
					}
					else
						sendResponsePacket("");	// Not supported
					
					break;
					
				// Step
				case 's':
				case 'S':
					singleStep(core, currentThread);
					gLastSignal[currentThread] = TRAP_SIGNAL;
					sendFormattedResponse("S%02x", gLastSignal[currentThread]);
					break;
					
				// Multi-character command
				case 'v':
					if (strcmp(request, "vCont?") == 0)
						sendResponsePacket("vCont;C;c;S;s");
					else if (memcmp(request, "vCont;", 6) == 0)
					{
						// XXX hack.  There are two things lldb requests.  One is
						// to step one thread while resuming the others.  In this case,
						// I cheat and only step the one.  The other is just to continue,
						// which I perform in the else clause.
						const char *sreq = strchr(request, 's');
						if (sreq != NULL)
						{
							// s:0001
							currentThread = strtoul(sreq + 2, NULL, 16) - 1;
							singleStep(core, currentThread);
							gLastSignal[currentThread] = TRAP_SIGNAL;
							sendFormattedResponse("S%02x", gLastSignal[currentThread]);
						}
						else
						{
							runUntilInterrupt(core, -1, enableFbWindow);
							gLastSignal[currentThread] = TRAP_SIGNAL;
							sendFormattedResponse("S%02x", gLastSignal[currentThread]);
						}
					}
					else
						sendResponsePacket("");
					
					break;
					
				// Clear breakpoint
				case 'z':
					clearBreakpoint(core, strtoul(request + 3, NULL, 16));
					sendResponsePacket("OK");
					break;
					
				// Set breakpoint
				case 'Z':
					setBreakpoint(core, strtoul(request + 3, NULL, 16));
					sendResponsePacket("OK");
					break;
					
				// Get last signal
				case '?':
					sprintf(response, "S%02x", gLastSignal[currentThread]);
					sendResponsePacket(response);
					break;
					
				// Unknown
				default:
					sendResponsePacket("");
			}
		}
		
#if DUMP_MESSAGES
		printf("Disconnected from debugger\n");
#endif
		close(gClientSocket);
	}
}
static void processEvents(PluginData* data, PDReader* reader, PDWriter* writer)
{
    uint32_t event;

    while ((event = PDRead_getEvent(reader)))
    {
        switch (event)
        {
            //case PDEventType_getExceptionLocation : setExceptionLocation(plugin, writer); break;
            //case PDEventType_getCallstack : setCallstack(plugin, writer); break;

            case PDEventType_getRegisters:
            {
               	sendCommand(data, "registers\n");
                break;
            }

            case PDEventType_getCallstack:
            {
            	if (shouldSendCommand(data))
                	sendCommand(data, "bt\n");

                break;
            }

            case PDEventType_getDisassembly:
            {
            	if (shouldSendCommand(data))
                    getDisassembly(data, reader);

                break;
            }

            case PDEventType_getMemory:
            {
            	if (shouldSendCommand(data))
                    getMemory(data, reader, writer);
                break;
            }

            case PDEventType_menuEvent:
            {
                onMenu(data, reader);
                break;
            }

			case PDEventType_setBreakpoint:
			{
				setBreakpoint(data, reader, writer);

				// if we add a breakpoint to VICE it will always stop but if we are already running when
				// adding the breakpoint we just force VICE to run again

				if (data->state == PDDebugState_running)
                	sendCommand(data, "ret\n");

				break;
			}

			case PDEventType_deleteBreakpoint:
			{
				delBreakpoint(data, reader, writer);
				break;
			}
        }
    }
}