Re: Conditional breakpoint based on caller / module

Tech Tip: Click here to run a free scan for Windows Errors and optimize PC performance




When a function call is made, the caller function copies the following information
onto the stack:
- parameters of the callee function
- return address (which tells the callee where it should return upon completion)

This return address allows you to determine who is calling your function,
since it points inside the module that made the call.

ESP register is a pointer, which in normal circumstances always points
to some area of the stack. When you set the breakpoint at the beginning
of the function (precisely, at the first CPU instruction of your function),
and the breakpoint is hit, ESP will point exactly to the place where
the return address is stored.

Therefore, to get the return address, you should take the value of ESP
and dereference it, as you would do with any other pointer.

If the value of ESP is, say, 0x0012FF20, it means that the return address
of the caller is stored in stack memory at address 0x0012FF20.

In C++ pseudocode, it would look like this:

unsigned long RetAddress = *(unsigned long*)ESP;

Now you should take the value of RetAddress and compare it
with the address ranges of your modules.

I would recommend you to read this article for more information on
stack related things:
http://www.codeproject.com/debug/cdbntsd2.asp

Oleg

"Anubhav" <Anubhav@xxxxxxxxxxxxxxxxxxxxxxxxx> wrote in message
news:568AE745-D7FB-4581-95D9-5C62307CC055@xxxxxxxxxxxxxxxx
I dumped the optional header in the file using PEBrowse and found that the
image size is Optional Header Details for DllLoader.exe to be ImageSize:
98304.

This is exactly the range 00400000 to 00417fff

As per the documenation of PE file format pecoff_v8.doc, the description of
this field is "The size (in bytes) of the image, including all headers, as
the image is loaded in memory. It must be a multiple of SectionAlignment."

I don't think that stack segment is part of the PE file format. Is this
reason why the value of ESP in A.EXE is outside the address range of A.exe.

If this is the case, then we are not passing in proper values to our earlier
conditional expression to break based on ESP.

Please advice. I am confused now if it is really a VC++ 6.0 issue.

"Anubhav" wrote:

Hi Oleg,

While I am in A.exe and just about to call the function in C.DLL, the value
of ESP is 0x0012FF20. If A.exe occupies the address range 00400000 to
00417fff, why does ESP point to an address outside this range.

This question is intruiging me. Please help me understand this. Does the
module address range include it's stack region also, or is it only the code
and data segments?

Regards.

"Oleg Starodumov" wrote:


No. I think it is not working. Here are the details in VC++ 6.0

A.EXE is from 00400000 to 00417fff
B.DLL is from 00320000 to 00364fff
C.DLL is from 10000000 to 10044fff

When C.DLL exported function is called from A.exe the ESP value is 0012FEC4
When C.DLL exported function is called from B.DLL which in turn is called
from A.EXE the ESP value is 0012FE68.

Based on my understanding of your response, my breakpoint condition in C.DLL
exported function is (*(unsigned long*)ESP >= 0x00320000) && (*(unsigned
long*)ESP < 0x00364fff)

Hence the breakpoint does not trigger in both the cases. Please correct if I
am doing something wrong.


Assuming that the breakpoint is set at the first assembly instruction of the function
(as it must be), you should look at the value whose _address_ is stored in ESP register:
"*(unsigned long*)ESP", if you use e.g. Watch window.
This value contains the return address of the caller, which should be within
the boundaries of the caller module.

But as I said in my previous reply, I don't think that it works reliably in VC6
(though definitely works in VS2003 and newer). The expression is correct,
but VC6 debugger seems to be unable to process complex expressions
associated with breakpoints.

A possible workaround for VC6 is to obtain the return address programmatically
and store it in a variable. For example:

#ifdef __cplusplus
extern "C"
#endif
void * _ReturnAddress(void);

#pragma intrinsic (_ReturnAddress)

void TestFunc()
{
void* RetAddr = _ReturnAddress();

printf( "TestFunc...\n" ); <-- Put the breakpoint here
}

The breakpoint expression would be:

(RetAddr >= 0x00320000) && (RetAddr < 0x00364fff)

Oleg







.



Relevant Pages

  • Re: Conditional breakpoint based on caller / module
    ... When a function call is made, the caller function copies the following information ... ESP register is a pointer, which in normal circumstances always points ... to some area of the stack. ... When you set the breakpoint at the beginning ...
    (microsoft.public.vc.debugger)
  • Re: Stack frames
    ... > ESP with the common stack frame models. ... ESP, why not simply move the "MOV esp, ebp" ... You can't rely on "size(locals + align)" to keep the ...
    (alt.lang.asm)
  • Re: further optimizations
    ... mov al B$edx;ok ... The users stack is not affected with this, ... but everything below ESP is never usable anyway... ... It had reprogrammed what you call IDT (interrupt table?) and after ...
    (alt.lang.asm)
  • Re: Newbie question...
    ... and esp, -16 ... mov ebp, esp ... Since the x86 increments esp with "pop", the new stack pointer is aligned ... add eax, 15 ...
    (alt.lang.asm)
  • x86 Stack Confusion
    ... finished with chapter 4 which covered the stack and I've written a few ... The assembler used is NASM and the commands to compile the program are ... Value of EBP: 0xbf9884b0 ... First of all I do not understand the value of esp. ...
    (comp.lang.asm.x86)