While trying to get work done, I was confronted by several disturbing messages printed on the console of a 64-bit Windows 7 system:
[0x7FEEFEFAAA0] ANOMALY: meaningless REX prefix used [0x7FEEFEE48C0] ANOMALY: meaningless REX prefix used [0x7FEEFEE54B0] ANOMALY: meaningless REX prefix used
This was disturbing because I pretty quickly established that the application I was running was not printing those messages. The expression “meaningless REX prefix” does actually convey comprehensible meaning to me, but I still don’t want to see it printed by some shadowy force, especially not without any clue as to why it might be printed.
A quick trip to a search engine only established the all-too familiar fact: there are lots of clueless people on the Internet. That includes people writing knowledge base articles. All in all, there are many avenues to ask the same question and get no useful answer.
There are all sorts of theories. It’s Windows 10. It’s anti-virus software. It’s Raptr. The winner is probably “my guess is that some non-Microsoft component (driver, software, utility) is installed and has “extended” the command processing environment with a REXX interpreter”. The old saying “better to remain silent and be thought a fool than to speak and to remove all doubt” certainly comes to mind.
Since I was not running Windows 10 or AVG, I could immediately dismiss some of those theories (and no, I didn’t take the REXX theory seriously for one second). But that didn’t help me much. So, where is that blasted message coming from?
What I could do was reproducibly provoke the “ANOMALY” message. Looking at the referenced addresses in WinDbg, it quickly turned out that they had a lot in common. Those were three entry points in opengl32.dll, namely wglSwapBuffers, wglSwapLayerBuffers, and wglMakeCurrent. It was also clear that they were all patched to jump inside ltc_game64-119906.dll. Which lives in the C:\PROGRA~2\RAPTRI~1\Raptr directory, also known as C:\Program Files (x86)\Raptr Inc\Raptr. And that’s something which comes with AMD’s Radeon drivers (the system has a Radeon R9 380 card in it).
So, let’s try our luck and see if the message might be coming from the Raptr DLL. Why yes, it does! And even better, next to it there’s an interesting looking string: ..\mhook\disasm\disasm.c – that looks like a source file name.
Now we’re just a quick search from the current source code and a related issue ticket. Bingo.
What Have We Learned?
Random libraries using
printf() to write to the console (stdout) are a terrible, terrible idea. In fact it’s a monumentally stupid idea. That’s not a problem with the mhook library per se, it’s the fault of whoever used it in a product and configured it that way (like Raptr and others).
It’s not just that incomprehensible (to most users) messages with no context are annoying, they are actively harmful. The “meaningless” message is known to have broken version string parsing for Java and node.js, and almost certainly caused problems elsewhere.
It’s fairly easy to see how this screw-up happened, at least in the Raptr case. Raptr is meant for games and generally graphical applications… where the messages won’t be visible. But console applications can initialize OpenGL too, and if they do—poof, unexpected junk on the console, interfering with expected output.
Just don’t do that, okay? It’s really not cool.
How To Find the Culprit
I used a debugger to track down the origin of the message because that’s what I had at hand. That’s probably not what most users want to do.
It may be possible to find the culprit using tracing tools like Process Monitor, but that has not been tried.
The unexpected “ANOMALY: meaningless REX prefix used” message and several similar “ANOMALY” messages come from the open-source mhook library, which is a generic library used for API hooking; the message is specific to 64-bit systems. Several products use the mhook library, including but not limited to Raptr aka Gaming Evolved (shipped with AMD Radeon and possibly other graphics drivers) and some versions of the AVG anti-virus software.
The message may only cause cosmetic issues, but can also interfere with the operation of various command-line tools. To eliminate the message, it is likely necessary to update or uninstall the software producing it, but establishing the precise origin of the message may unfortunately not be trivial.
Reminds me of when I ran some DirectX capabilites check tool inside VirtualBox, and got a spew of OpenGL error messages from vbox’s display driver 🙂
Thanks for investigating and good find. I have seen this message as well when running Java applications (displayed in the Java console) so I suppose it is because Java initializes OpenGL in certain circumstances. And yes, I have an AMD R9 390 card. But still I am wondering: Is there truly a “bug” somewhere in the stack that is causing this message about meaningless REX prefix? I suppose disasm.c is trying to disassemble some code and is not liking what it sees. Maybe it is a case of it encountering a REX prefix on an instruction where it doesn’t make sense. Likely the CPU will just ignore it, so it isn’t a real issue in itself. But could still represent an issue somewhere (maybe an instruction was generated that was different from the intended, where the intended would have required a REX prefix). And at least it is wasteful to generate redundant REX prefixes. Of course it could also be a bug in disasm.c 🙂
I have not seen anything indicating that the message signifies a real error. The only problem is the message itself.
So far I haven’t tracked down what precisely triggers it. Very likely it’s a redundant but harmless prefix.
At least in the Raptr case I suspect more or less anything initializing OpenGL will provoke the message. Again, in most cases those are GUI applications where the message won’t be visible.
Would you, please, remove IP filter for east Europe to be able to access you web site.
Yes, once I figure out a better spam blocking alternative. Unfortunately it won’t be for at least another week because I’m traveling now.
The Windows amd64 ABI requires that the first opcode of a function be at least 2 bytes in length. (I think this is so the function can be hotpatched.) Many times the first instruction is “push ” but the instruction has a 1-byte encoding! To comply with the ABI, a rex prefix is added to the instruction, making it 2 bytes — “rex push rbp” or “rex push rbx” or whatever. The compiler does this for you, but if you are writing a function in assembler, you need to remember the rule.
Could you please point to some official reference? I could not quickly find anything…
The problem here is probably not so much someone forgetting to add the prefix as someone else (the mhook library) not knowing that it’s required and flagging it as suspicious. But this would certainly explain why the meaningless prefix is there in the first place.
Sure Michal – on docs.microsoft.com I haven’t found a very detailed copy of the AMD64 ABI. There are documentation pages but I feel like they don’t go into enough depth (it’s not like reading a spec).
But if you look at the documentation for /HOTPATCH on the Visual C++ compiler, you’ll see that when the switch is provided, the compiler ensures the first instruction of each function is at least two bytes. And it states that this option is always on for x64 targets. https://docs.microsoft.com/en-us/cpp/build/reference/hotpatch-create-hotpatchable-image?view=vs-2017
The next thing I can point you to is that someone has pushed a copy of the Windows 10 (original version, build 10240) SDK onto GitHub, so I can link to it. Take a look at the rex_push_reg macro defined in macamd64.inc. https://github.com/tpn/winsdk-10/blob/master/Include/10.0.10240.0/shared/macamd64.inc
There are other gems in that file as well. A rex prefix must be used on the final jmp when it appears as a tail call terminating the epilogue of a function – the unwinder needs to see this. This is also called out in https://docs.microsoft.com/en-us/windows/desktop/api/winnt/nf-winnt-rtlvirtualunwind — the Remarks section.
So while maybe forgetting the rex prefix on the first instruction of the function isn’t a terrible sin (maybe this only breaks hotpatching?), forgetting it on a tail call jmp is I think, truly a calling convention break.
Thanks for that. So “calling standard dictates that functions must not begin with a single byte instruction”, but who knows where that standard is. I looked at the calling convention documentation on MSDN, but as you say, it’s not terribly detailed.
Interesting stuff for sure. The usual problem with Windows, ETOOMUCHBLACKMAGIC.