Intel® C++ Compiler
Community support and assistance for creating C++ code that runs on platforms based on Intel® processors.

popfd compile error on win64

Naveen_Tulabandula
2,982 Views

This is what i am trying to achieve ::
I got eflags value into a context structure "ctx" using GetThreadContext Microsoft API
Now my intention is to set the eflags value in this structure to current thread
This is how i am doing

/*I got to know that we cannot directly modify eflags register,so....
1. I am getting the value in ctx structure to Eax register
2. Pushing the value in Eax register to stack
3. Poping the recently pushed value into eflags register */

    mov eax, dword ptr [ctx+0x044];   // as eflags is 32-bit I am using eax instead of rax
    push eax;
    popfd;

when i try to compile this, i am seeing below compile error

C:\1\stacktracing.c(81): (col. 5) error #13252: Unsupported instruction form in asm instruction push.
C:\1\stacktracing.c(82): (col. 5) error #13250: Opcode POPFD unsupported by architecture in asm instruction popfd.

1. Can't we push 32-bit eax  to a stack in 64-bit machine ....if yes, any alternative?
2. Can't we use popfd in 64-bit machine ?

Thanks & Regards
Naveen

0 Kudos
33 Replies
Marián__VooDooMan__M
New Contributor II
631 Views

oh, and regarding [2.] I forgot to mention that Windows DOES change FS segment register, each thread has its own one, to implement TLS (thread local storage). But as I wrote, Windows can change it, and does change it, and does it before thread is started, and does it via mentioned TSS structure change.

So you can just ignore changing (restoring) segment registers. Then, [2.] crash will disappear.

But I guess you want to implement lightwaeight threads, since you want to hack context by storing a restoring it to/from the structure. If my guess is right, then you should use "Fibers" to implement this (on Windows). I hope "pthreads" has its own implementation of fibers for other OS'es.

Could you please tell us your approach, what do you want to implement by your (above) code? Maybe you are walking the bad path, and maybe there is other approach for you problem you are trying to solve... and maybe much simpler.

0 Kudos
Marián__VooDooMan__M
New Contributor II
631 Views

Naveen Tulabandula wrote:

After call to GetThreadContext, i see the value in ctx structure as 0x100202 or something like that....later i manipuated the structure value as 0x64....and executed the above assembly......I expect 0x64 in eflags....but that is not the case.  I am using "r" command in windbg to see the value of eflags and other registers

when manipulating FLAGS/EFLAGS/RFLAGS you sometimes just can't modify few bits of it, and if you do, you get crash. see http://en.wikipedia.org/wiki/FLAGS_register for layout of bits and then check reference manual for amd64/IA-64 which bits you CAN'T modify. E.g. IOPL 2 bits... if you modify them, then OS will kill the program... and there are few other bits you CAN'T modify.

0 Kudos
Naveen_Tulabandula
631 Views

I am trying to trace the call stack when any AV or something happens. Initially I am using stackwalk64 API to get the call stack but this dbghelp function is not  thread safe......to make it thread safe, I am using synchronization mechanishms like mutex and ....Because of these overheads I feel by stack dumping mechanism is slow.....I want to enhance it....recently i got to know that RtlCaptureStackBackTrace function is available to get stack and it is thread safe.

Above is what i am trying to do.

This is how i am trying to achieve it

My sample application has multiple threads, in each iteration i will suspend one thread,get its context and change its Rip to execute a new function which is having call to  RtlCaptureStackBackTrace function, once i get the stack, i am planning to resume the thread execution at exact same point where it is suspended(using the context which i got earlier).

In above logic, i am suscessful upto getting the stack....after that when trying to resume at the exact point where it is suspended, i am seeing some crashes.......I am restoring context using setThreadcontext....but i was wondering if it is not able to restore all flags properly...hence i am writing my own stack restore using above assembly logic

0 Kudos
Marián__VooDooMan__M
New Contributor II
631 Views

Naveen Tulabandula wrote:

I am trying to trace the call stack when any AV or something happens. Initially I am using stackwalk64 API to get the call stack but this dbghelp function is not  thread safe......to make it thread safe, I am using synchronization mechanishms like mutex and ....Because of these overheads I feel by stack dumping mechanism is slow.....I want to enhance it....recently i got to know that RtlCaptureStackBackTrace function is available to get stack and it is thread safe.

Above is what i am trying to do.

This is how i am trying to achieve it

My sample application has multiple threads, in each iteration i will suspend one thread,get its context and change its Rip to execute a new function which is having call to  RtlCaptureStackBackTrace function, once i get the stack, i am planning to resume the thread execution at exact same point where it is suspended(using the context which i got earlier).

Okay, I don't have time ATM to think more about your problem you are trying to find solution for.

Naveen Tulabandula wrote:

In above logic, i am suscessful upto getting the stack....after that when trying to resume at the exact point where it is suspended, i am seeing some crashes.......I am restoring context using setThreadcontext....but i was wondering if it is not able to restore all flags properly...hence i am writing my own stack restore using above assembly logic

As I have said, do not modify flags, just restore them as they have been saved and use for it 64-bit version of flags, that is RFLAGS register (though it is the same as EFLAGS, but as per reference documentation, you SHOULD NOT modify upper bits (documentation is saying "these bits are reserved -> do NOT change them". if you change reserved bit, you either get 1. crash: non-zero or non-one bits are not physically present in CPU; 2: you change (possibly) undocumented flag and later behaviour is unpredictable...; 3. CPU will ignore your binary 1 bits, and store them as though they were zeroes. maybe these bits are all zeroes, but to retain future compatibility, maybe next version of CPU will use some bit of RFLAGS(64-bit version) previously as "reserved - do not modify". I was in like the (reserved) are all zeroes. but some of them could default to 1! PAY attention to undocumented bits, and restore them (via POPFQ) to be exactly as they were via PUSHFQ/context save. NB: there are few reserved bits in EFLAGS (16 and 32 bit version) as well!!! NB!!!


---

regarding "dbghelp" DLL thread (non-)safety... you always have a chance to add mutex or cirtical section in front of making debug core crash mini dump into your function to make sure there is no re-entrancy.

Please paste some (maybe pseudo-)code how you do crash (mini) dump. I am using dbghelp for minidump creation at crash for 5 years and I have never had seen threading problem with it, even though my projects are extremely (yea, like 200 threads simultaneously) threaded.

Good luck, and I am able to write you advices regarding "dbghelp" and it's API. Just append a new post to this topic (I don't want to make our private contact, since in opposite case I believe many other users will not profit from our mistakes and fixes of this thing. So I prefer this forum, rather than private e-mail conversation.).

0 Kudos
Marián__VooDooMan__M
New Contributor II
631 Views

foot note: I have fixed som ambigious things in my last post via EDIT. PLS hit refresh in your browser.

0 Kudos
SergeyKostrov
Valued Contributor II
631 Views
I did additional verification and here is a summary of different tests for different formats of PUSH-POP instructions with a 64-bit Intel C++ compiler version 13.1.0.149 Build 20130118 ( Update 2 ): // 32-bit - OK // 64-bit - OK _asm { pushf popf } // 32-bit - OK // 64-bit - Error: Opcode PUSHFD unsupported by architecture in asm instruction... // 64-bit - Error: Opcode POPFD unsupported by architecture in asm instruction... _asm { pushfd popfd } // 32-bit - Error: Unknown opcode PUSHFQ in asm instruction // 32-bit - Error: Unknown opcode POPFQ in asm instruction // 64-bit - OK _asm { pushfq popfq } // 32-bit - OK // 64-bit - Error: Operand size mismatches its default size in asm instruction... _asm { push ax pop ax } // 32-bit - OK // 64-bit - Error: Unsupported instruction form in asm instruction... _asm { push eax pop eax } // 32-bit - Error: label "rax" was referenced but not defined // 64-bit - OK _asm { push rax pop rax }
0 Kudos
Naveen_Tulabandula
631 Views

Hi Sergy

Thanks for verifying this....I think you verified for compilation error.....but did you check the functionality

#include <stdio.h>
main()
{
printf("start\n");
__asm
{
mov rax,20;
push rax;
popfq;
}
printf("Done\n");
}

Keep a break point on "start" and observe eflags value

keep a break point on "Done" and observe eflags value

By the time execution comes to "Done", I expect 0x14 i.e; 20 in eflags...which is not the case
 

Change 20 to 21 and observe the values again

0 Kudos
SergeyKostrov
Valued Contributor II
631 Views
>>...did you check the functionality... No. Is there something wrong?
0 Kudos
Bernard
Valued Contributor I
631 Views

>>>(ccc.1464): Illegal instruction - code c000001d (!!! second chance !!!)
stacktracing!PrintStackTrc+0x2e7:
00000001`3fd4132d 668e0dc47c0000  mov     cs,word ptr [stacktracing!ctx+0x38 (00000001`3fd48ff8)] ds:00000001`3fd48ff8=0033>>>

Why are you trying to write to cs register?Your cpu has trigerred gp error.Those selectors are set by operating system and keeping constant during the constant context switching.The only way for user mode to to modify cs register is to use call and iret instructions.

0 Kudos
jimdempseyatthecove
Honored Contributor III
631 Views

It is unfortunate that MS Windows does not permit setting a segment register to reference a base address within a linear address of the VM of the process. (TLS is implemented this way). This would be handy even at the expense of an O/S call to modify the descriptor table. An app could request n descriptors for manipulation and specify the base VM address for each descriptor. Then subsequently have a fast path set of ?S: to any of the setup descriptors (GP fault of app when outside range). This is a topic for MS forum.

Jim Dempsey

0 Kudos
Bernard
Valued Contributor I
631 Views

>>>it will use its own mechanisms to do it, via modifying TSS (task state segment).>>>

IIRC Linux uses software task switching(it does not use saved current task context in TSS).

0 Kudos
SergeyKostrov
Valued Contributor II
631 Views
Naveen, As far as I understood you have some run-time problem and this is already Not a problem with Intel C++ compiler. So, at that stage you need to be as specific as possible and I think a request to Intel Premier support could / needs to be done.
0 Kudos
SergeyKostrov
Valued Contributor II
631 Views
Did you take into account that bits 1, 3, 5, 15, and 22 through 31 of EFLAGS register are reserved? "...Software should not use or depend on the states of any of these bits..." Intel(R) 64 and IA-32 Architectures Software Developer's Manual Volume 1: Basic Architecture Order Number: 253665-044US August 2012 ... CHAPTER 3 ... 3.4.3 EFLAGS Register ( Page 68 ) ... 3.4.3.4 RFLAGS Register in 64-Bit Mode ( Page 71 ) ...
0 Kudos
Reply