Archive

Posts Tagged ‘windows’

Translating Instruction Address to Source Line

February 22nd, 2010

In this article I will describe how to programmatically translate an instruction address from a Win32 executable to a source line. The described approach uses the Microsoft debugger engine dbgeng.dll. Therefore you should have it installed. If you don’t have it, you can download and install the Windows debugger WinDbg which will install dbgeng.dll.

Requirements

To use this approach you will need to have installed windows debugger engine – dbgeng.dll. If you don’t have it, install WinDbg debugger. This will install dbgeng.dll

Approach

Many debuggers support debugging at source code level. The debugger is capable to provide debugging at the source level by translating instruction addresses to lines in source code files. In our approach we use the same mechanisms that debuggers use. This particular solution, to translate an instruction address to a source line, uses functionality provided by the windows debugger engine dbgeng.dll.

In overview, we create a process from the Win32 executable file from which we want to translate instruction addresses. Then we attach the debugger engine to the created process. To create a process and attach the debugger to it we use CreateProcessAndAttach function. When the debugger is attached, we call function GetLineByOffset to do the actual translation. After we finish with the translation task we terminate the process with the function TerminateCurrentProcess. Besides these procedures there are few more things that are necessary to do which I explain in the implementation.

Implementation

First we create objects that implement the following COM interfaces: IDebugControl , IDebugClient, IDebugSymbols. To create these objects we use function DebugCreate.

static IDebugClient5 *dbgClient5 = NULL;
static IDebugSymbols *dbgSymbols = NULL;
static IDebugControl *dbgControl = NULL;
...
DebugCreate(__uuidof(IDebugControl), (void**) & dbgControl);
DebugCreate(__uuidof(IDebugClient), (void **) & dbgClient5);
DebugCreate(__uuidof(IDebugSymbols), (void **) & dbgSymbols);

Before crating the process from the executable we set the debugger engine filters so that the target process breaks into the debugger immediately after it is created. To set the debugger filters we use function SetSpecificFilterParameters.

DEBUG_SPECIFIC_FILTER_PARAMETERS filter[10];
for (int i = 0; i < 10; i++) {
	filter[i].ExecutionOption = DEBUG_FILTER_BREAK;
	filter[i].ContinueOption = DEBUG_FILTER_GO_HANDLED;
	filter[i].TextSize = 0;
	filter[i].CommandSize = 0;
	filter[i].ArgumentSize = 0;
}

dbgControl->SetSpecificFilterParameters(0, 10, filter);

Using function CreateProcessAndAttach we create a windows debug process and attach the debugger to it.

ULONG64 server            = 0;
PSTR    commandLine       = executableName;
ULONG   processId         = 0;
ULONG   attachFlags       = 0; 

dbgClient5->CreateProcessAndAttach(
	server,
	commandLine,
	DEBUG_PROCESS,
	processId,
	attachFlags);

To translate the instruction address to a source line we call function GetLineByOffset.

ULONG64 offset = instrAddress;
ULONG fileNameBufferSize = MAX_FILE_NAME_SIZE;
memset(sourceInfo->fileName, 0, fileNameBufferSize);
sourceInfo->lineNo = 0;
sourceInfo->fileSize = 0;
sourceInfo->displacement = 0;

HRESULT isOk = dbgSymbols->GetLineByOffset(
	offset,
	&sourceInfo->lineNo,
	sourceInfo->fileName,
	fileNameBufferSize,
	&sourceInfo->fileSize,
	&sourceInfo->displacement);

If we want to translate multiple addresses, we have to call function GetLineByOffset multiple times without repeating the earlier operations. After we finish with the translation we detatch the debugger from the process by terminating the process with function TerminateCurrentProcess.

HRESULT isOk = dbgClient5->TerminateCurrentProcess();

Download

The code complete source code is available for download from InstructionToSourceLine.zip. Note that the instruction address provided as input should be a decimal number but not hexadecimal.

C# Version

There is also a C# implementation of this tool that you can download from InstructionToSourceLineCSharp.zip. This C# implementation consists of 2 parts – DbgEngManaged and InstructionToSourceLineCSharp. DbgEngManaged is a managed c++ library wrapper for the debugger engine DbgEng.dll. InstructionToSourceLineCSharp is a C# console application that references DbgEngManaged library. Note that the error handling here is not done properly so don't judge me for it :) The provided code here is something that I have quickly prototyped and decided to share for those who for some reason need to use the debugger engine. It can also serve as an example of using native and managed code together. 

Programming, windows , , , , , , , , , , , , ,

A Short and Comprehensive Tutorial on Windows API

April 15th, 2009

I needed to write a simple native Win32 windows application and after searching around I found very nice tutorial - easy to read and with rich examples. So here is the link "Windows API Tutorial". The tutorial includes examples of how to write native (win32) applications with forms, drawgraphics and threading. The tutorial follows a good practice of encapsulating the Win32 abstractions in C++ classes (something which is alredy done at MFC) and makes things to understand easier.

Programming, windows , , , , ,

dumpbin – reading header files of windows binaries

March 24th, 2009

Using dumpbin /headers you can read the header of windows files and check for example for what architecture and addressing mode the binary is compiled for.

windows , ,

Windows XP – Microphone not Working

January 31st, 2009

Today I had to fix an annoying microphone problem on my brother’s computer. He has Windows XP Professional installed and the microphone was not working – unable to use the microphone in any application. The solution to this problem is very subtle since you have to enable "MIC boost" a very hidden feature. Here is how to do it:

Open the extended Version of Volume Control (down right next to the clock, right click and select properties).

You have to see the following picture:

In Volume Control dialog:

  1. Ensure that Muted is checked for microphone (if not you will be able to hear yourself on the speakers when talking to the microphone)
  2. Then click Advanced for Microphone and select "MIC boost"

Then Close everything and now your microphone should work properly.

Sorry that the first image is in Bulgarian. I will change it as soon as possible.

Computers , , ,

Windows: Time of Last Reboot and Time Since Last Boot

December 22nd, 2008

Today I needed to check the last time when one of our win servers was rebooted and the time it elapsed since its last boot.

So to check:

1. The time of last Reboot, go to Open Event Viewer (Control Panel, Administrative Tools). Look for the last Event Log 1074 with USER32 – this will contain information about the exact date and time of the last reboot.

2. The time since the last boot. A practical way I found is: open command prompt and type “net statistics server”. It will display summary info. The one that you should look for is the 2nd line “Statistics since…” this is the time since your computer is on.

Uncategorized , ,