views:

788

answers:

11

Hi all,

I have an application for which I do not have the code, and a dll for which I do have the code. I need to be able to debug into the dll, but lacking the source for the exe, how do I do this?

The dll code is mfc c++; I believe that the main app is the same thing as well.

I've tried doing a 'set target application' deal, where I set the application that the dll will be called from, and the application crashes a horrible, horrible death when called that way. I don't know if the fault lies with this dll or with the executable for that behavior, and it's just one of the myriad things I'd like to solve.

I'm thinking that there should be some call to allow the dll to spin indefinitely until a debugger is attached to the process, at which point I should be able to debug the dll by attaching to the process. Does that make sense? Is there a better way to do this?

+2  A: 

There is a registry setting called ImageFileExecutionOptions that can be set up to launch a debugger whenever your DLL is loaded. I used to use it to debug ISAPI extensions. Here is a link to a decent blog entry about it.

D.Shawley
So, I tried to do this, and it didn't quite work. I set the debugger as the executable, and then started up the executable in the project of my dll. Then I set a breakpoint, but again, the breakpoint is not reached. If set the dll to be the target of the key, then the debugger just isn't started. I can give you more details, because this does look like a promising solution, but it's just not working now.
mmr
I think that you have to set a breakpoint then resume execution. Basically, the debugger is launched using a hook into the NTLDR so it is launched before *any* code is executed. For ISAPI extensions I would add a breakpoint in my HttpExtensionProc and let it run. Then it would stop whenever IIS invoked by extension. I can't seem to find the web-page that explained how to do this via Google. Look around for hints on debugging ISAPI extensions. Good luck!
D.Shawley
I doubt that NTLDR (which loads the NT kernel) has anything to do with Image File Execution Options. :)
bk1e
@bk1e: I'll see if I can dig up some references for this. IIRC, The BreakOnDllLoad option is implemented in the same area of the kernel as the trap into DllMain after the DLL is pulled into memory. NTLDR is what is actually executing DllMain - google for the infamous NTLDR locking problems associated with doing anything interesting in DllMain and you should be able to find a description of it.
D.Shawley
+2  A: 

If the application is linked against a non-debug DLL and does not have debug symbols itself, this isn't really likely to be fruitful. You might want to look here for information on using windows symbol packages to help you if you're curious about what's going in inside windows DLL's, but by and large, an application which does not have debug info and which you can't compile isn't debuggable in any meaningful way.

Jherico
Unfortunately, it's looking like you're right. Ah well, guess I'll have to go back to fprintf's in the code to figure out what the hell is going on.
mmr
+1  A: 

With a DLL project, you should be able to tell Visual Studio to start debugging and it will ask you for an executable name. Enter your exe there. I've done this a lot for when I've worked on DLL code that was called from another process. Works for straight DLLs as well as COM components.

It might also help to set some breakpoints in your code ahead of time if you have an idea of where the problem might be.

Update: Since that does not work for you, the only other thing I can think of would be to attach to the running exe, but that could be problematic if your code gets loaded before you have a chance to get in there.

crashmstr
As I said in the problem description, the executable breaks if it's run this way.
mmr
Ah, I did not catch your wording on that. Too bad, since this works for me almost all of the time.
crashmstr
+4  A: 

I used to use the DebugBreak function for this. You could have it called conditionally based on the presence of a particular file, perhaps.

#ifdef DEBUG
if (... file exists...) {
    DebugBreak();
}
#endif

This will halt application execution until you attach a debugger or terminate the app.

Matt Kane
Hmm, seems not what he is looking for: the documentation says that "If the process is not being debugged, the function uses the search logic of a standard exception handler. In most cases, this causes the calling process to terminate because of an unhandled breakpoint exception."
beef2k
That can be the Just in time (JIT) debugger - if you have one configured. Run WinDbg with -I or VS Tools>Options>Debugging>Just-In-Time.
Aardvark
A: 

Here's a simple solution: add a Sleep(10000); in DllMain (or some other startup code) and then use Tools / Attach to Process to attach your debugger while the code is sleeping.

RichieHindle
+1  A: 
__asm int {3};

in your DLL main. Then attach a debugger to the process? If this kills the process, then it probably has it's own int3 trap and is quitting. Are you trying to debug a copy protected game or anything like that? As they tend to do that kind of tricksy behaviour.

Pod
No, it's an actual business app, but I just don't have the source for the main app. There's a lot of stupid politics as to why this situation exists, but it's nothing as tricksy as reverse engineering a game.
mmr
This is actually the exact same thing that DebugBreak() does.
Matt Kane
True, but DebugBreak is WinAPI only. ie, it's not cross platform. Then again, int 3 isn't cross architecture :)I usually roll my own around int 3.
Pod
A: 

I'm thinking that there should be some call to allow the dll to spin indefinitely until a debugger is attached to the process, at which point I should be able to debug the dll by attaching to the process. Does that make sense? Is there a better way to do this?

Why not do it the way you are describing it? Just start the application that you want to debug. Attach the debugger to it, either through Visual Studio or simply by right clicking on the application in the task manager and selecting Debug. Once the debugger is attached, set a break point with F9 at suitable location in your dll code.

Magnus Skog
+1  A: 

Wait until a debugger is present:

while(!IsDebuggerPresent())
{
  Sleep(0);  // yield
}

MSDN Documentation: IsDebuggerPresent().

beef2k
+1  A: 

Ensure that the application is indeed using the DLL that you built, in debug mode, with symbols. You can verify this by using a program such as Process Explorer (in this application, enable the lower pane in the View menu and select DLLs).

Then, in Visual Studio's Debug menu, select "Attach to Process", and select the application that uses your DLL. Your debug breakpoints should become filled in, if and when your DLL is loaded.

swongu
A: 

I've tried doing a 'set target application' deal, where I set the application that the dll will be called from, and the application crashes a horrible, horrible death when called that way. I don't know if the fault lies with this dll or with the executable for that behavior, and it's just one of the myriad things I'd like to solve.

Starting a process inside the debugger causes Windows to enable the NT debug heap. It sounds like the application or DLL has heap corruption or relies on the value of uninitialized heap memory.

You can disable the NT debug heap by setting the environment variable _NO_DEBUG_HEAP to 1 (on XP and later). This may make it possible to get the application to not die a horrible death when started from the debugger.

Starting the application outside the debugger will also result in the NT debug heap being disabled, and attaching a debugger later will not enable it.

bk1e
+1  A: 

I recently had to use one of the methods listed here: http://blogs.msdn.com/greggm/archive/2004/07/08/177418.aspx

Does that help?

Pod