|
Is there anything Raymond doesn't know? His blog in one of my favorites.
Steve
|
|
|
|
|
Is it possible that an Instruction Pointer value is NULL and is caught during debugging? What is the implication?
|
|
|
|
|
On What Context your instruction pointer beomes NULL?
-Sarath.
"Great hopes make everything great possible" - Benjamin Franklin
|
|
|
|
|
Is is possible that while debugging memory dumps an IP becomes NULL
|
|
|
|
|
tom groezer wrote: Is it possible that an Instruction Pointer value is NULL and is caught during debugging? What is the implication?
Yes, it's possible. The following C++ code will result in this:
#include "StdAfx.h"
#include <iostream>
#include <windows.h>
void main()
{
typedef void (*PFun_t)();
PFun_t pFun = NULL;
__try
{
(*pFun)();
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
using namespace std;
cout << "Caught!!!" << endl;
}
}
Steve
|
|
|
|
|
How shall it expand to an IP to NULL. he line (*pFun)(); dereferences a NULL pointer which raises an exception. Does it cause an IP to be NULL?
|
|
|
|
|
tom groezer wrote: Does it cause an IP to be NULL?
Yes. Remove the __try and __except and verify this if you like.
Steve
|
|
|
|
|
A function pointer is not a pointer to an object, it's a pointer to the start of the function in memory. So calling through a function pointer sets EIP to the pointer's value. You can't actually dereference a function pointer, since functions aren't objects in C/C++, but the syntax rules allow you to apply * to a function pointer as if it were dereference-able. IOW, both of these are equivalent:
void (*pFunc)() = NULL;
(*pFunc)();
pFunc();
|
|
|
|
|
Michael Dunn wrote: void (*pFunc)() = NULL;
(*pFunc)();
pFunc();
I prefer the first for consistency (as it's required in some other uses of pointers).
Steve
|
|
|
|
|
Hi,
Never. (but depends on the architecture).
if you try this, as steve said,
PFun_t pFun = NULL; <br />
(*pFun)();
this doesnot set the CS:EIP to NULL.
My argument may depend on software and hardware architecture.
(*pFun)(); will maps to "call <function>" instruction.
And "CALL" instruction internally "JMP"s to the function location.
Hardware exception handling mechanism detects this error for bad location,
jmp $BAD_JMP (jumped out of Code segment(general Protection Fault)) and causes sofware interrupts and in x86 interrupt return mechanism, IRET instruction points to old CS:EIP (exception causing location), for all page faults and general Protection Fault(GPF).
Hence you never caught EIP to NULL while debugging, you will see the EIP will contain the value of the next instruction following the exception occured instruction. However you can detect the BAD JUMP(GPF) caused by NULL function pointer using try.. catch.
You may watch the registers while debugin IDE and also refer documents that may search to "Interrupt and Exception Handling on the x86".
I think most harware and software platform uses Exception handling and CS:EIP never caught with NULL values.
Best Regards
Raj
|
|
|
|
|
Rajkumar_R wrote: if you try this, as steve said,
PFun_t pFun = NULL;
(*pFun)();
this doesnot set the CS:EIP to NULL.
Rajkumar_R wrote: Hence you never caught EIP to NULL while debugging
Run this code:
#include "StdAfx.h"
#include <windows.h>
void main()
{
typedef void (*PFun_t)();
PFun_t pFun = NULL;
(*pFun)();
}
The following is what the debugger reports (WinDBG):
(1540.172c): Access violation - code c0000005 (!!! second chance !!!)
eax=cccccccc ebx=7ffd6000 ecx=00000000 edx=00322d08 esi=0012ff30 edi=0012ff80
eip=00000000 esp=0012ff2c ebp=0012ff80 iopl=0 nv up ei pl nz ac pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000216
00000000 ?? ???
EIP is indeed NULL!
Steve
|
|
|
|
|
EAX = 00000000 EBX = 7FFDF000 ECX = 00000000 EDX = 00000000 ESI = 00000000 EDI = 00000000 EIP = 004114DA ESP = 0012FE90 EBP = 0012FF68 EFL = 00000000
This is what I get.
(!!! second chance !!!) how to get this message.
I used VS2005 simple console application contains only the above code(Created from empty project)
|
|
|
|
|
Rajkumar_R wrote: (!!! second chance !!!) how to get this message.
I use WinDBG[^].
Can you show me your code?
Steve
|
|
|
|
|
#include <iostream><br />
#include <windows.h><br />
void main(){ <br />
typedef void (*PFun_t)(); <br />
PFun_t pFun = NULL;
(*pFun)();<br />
}
|
|
|
|
|
Can you show me the machine code. Mine is as follows:
7: void main()
8: {
00401010 push ebp
00401011 mov ebp,esp
00401013 sub esp,44h
00401016 push ebx
00401017 push esi
00401018 push edi
00401019 lea edi,[ebp-44h]
0040101C mov ecx,11h
00401021 mov eax,0CCCCCCCCh
00401026 rep stos dword ptr [edi]
9: typedef void (*PFun_t)();
10: PFun_t pFun = NULL;
00401028 mov dword ptr [ebp-4],0
11:
12:
13: (*pFun)();
0040102F mov esi,esp
00401031 call dword ptr [ebp-4]
00401034 cmp esi,esp
00401036 call __chkesp (00401060)
14: }
0040103B pop edi
0040103C pop esi
0040103D pop ebx
0040103E add esp,44h
00401041 cmp ebp,esp
00401043 call __chkesp (00401060)
00401048 mov esp,ebp
0040104A pop ebp
0040104B ret
The bold line will push the return address onto the stack then set EIP to [ebp-4] (NULL).
EIP can be set to NULL as I showed. I can't tell why you're not getting the same results without looking at the machine code.
Steve
|
|
|
|
|
void main(){ <br />
004114B0 push ebp <br />
004114B1 mov ebp,esp <br />
004114B3 sub esp,0CCh <br />
004114B9 push ebx <br />
004114BA push esi <br />
004114BB push edi <br />
004114BC lea edi,[ebp-0CCh] <br />
004114C2 mov ecx,33h <br />
004114C7 mov eax,0CCCCCCCCh <br />
004114CC rep stos dword ptr es:[edi] <br />
typedef void (*PFun_t)(); <br />
PFun_t pFun = NULL;
004114CE mov dword ptr [pFun],0 <br />
(*pFun)();<br />
004114D5 mov esi,esp <br />
004114D7 call dword ptr [pFun] <br />
004114DA cmp esi,esp <br />
004114DC call @ILT+410(__RTC_CheckEsp) (41119Fh) <br />
}<br />
004114E1 xor eax,eax <br />
004114E3 pop edi <br />
004114E4 pop esi <br />
004114E5 pop ebx <br />
004114E6 add esp,0CCh <br />
004114EC cmp ebp,esp <br />
004114EE call @ILT+410(__RTC_CheckEsp) (41119Fh) <br />
004114F3 mov esp,ebp <br />
004114F5 pop ebp <br />
004114F6 ret
|
|
|
|
|
The code looks basically the same. Perhaps the difference in behaviour in CPU dependant. Clearly however, the behaviour described by the OP is possible on some systems (such as mine and, by the looks of things, his).
Steve
|
|
|
|
|
Hi Steve,
please try this on VS2005 and erase "by the looks of things". In VC6 I get EIP as NULL, hence this bahaviour is not because of CPU dependency. Clearly, depends on platform(sw/hw) that I specified explicitly in my first post.
And I think the behaviour is because of exception handler based on VC8 crt, which changes back the eip to address of exception occured instruction called fixup address. May be you can give better definitions for the behaviour, research a little moments for this.
Best Regards,
Raj
|
|
|
|
|
Rajkumar_R wrote: please try this on VS2005 and erase "by the looks of things". In VC6 I get EIP as NULL, hence this bahaviour is not because of CPU dependency. Clearly, depends on platform(sw/hw) that I specified explicitly in my first post
But I inspected the generated code from both versions and concluded it wasn't due to code generation differences.
Steve
|
|
|
|
|
I think particularly in a OS based environment generated code doesnot going to be dumbly executed in the CPU. Even, the before calling our main() function, there are CRT based code executed.
I meant May be VS2005 exception handler differs.
|
|
|
|
|
I want to use some memory manipulation while debugging and wish to get into a function which is not normally called by the function. how do I do that.
Any good tutorials on memory dumps debugging I have read one on codeproject but it does not suffice.
|
|
|
|
|
I'm sorry. It is difficulty to understand your question for me.
<br />
wish to get into a function which is not normally called by the function. <br />
Do you mean want to execute the function not normally call?
Or you mean to set breakpoint when the function called?
|
|
|
|
|
I want this one
Do you mean want to execute the function not normally call?
|
|
|
|
|
I think you want to inject or execute code to other process.
if so, try read [ this ] article.
|
|
|
|
|
tom groezer wrote: get into a function which is not normally called by the function
Your question seems strange for me...
While debugging, you can try Next statement, Step into, Set Next statement options to control and analyze the program flow and the contextual values.
You can verify the memory locations by entering the adress or dragging the variables (it's adress) in the Memory Window of Visual Studio.
If you want to check the memory leak in your code,, by defining the macro _CRTDBG_MAP_ALLOC. If this one is defined, CRT will note down each memory allocation and de-allocation. And when we call _CrtDumpMemoryLeaks(), it will dump the leaks to Output window of Visual Studio. In release version it will have no effect. ForIt should be done in release version itself.
#define _CRTDBG_MAP_ALLOC
#include <crtdbg.h>
void Foo()
{
int* pnNumbers = new int[100];
// Dump the leak summery.
_CrtDumpMemoryLeaks();
}
-Sarath.
"Great hopes make everything great possible" - Benjamin Franklin
|
|
|
|