Thread: weird typeded

  1. #1
    Registered User
    Join Date
    Jun 2009
    Posts
    26

    weird typedef

    Hi all,

    Can anyone please explain to me what the following macro definitions are doing?

    Code:
    #define DECLARE_ARGS(val, low, high)	unsigned long long val
    #define EAX_EDX_VAL(val, low, high)	(val)
    #define EAX_EDX_RET(val, low, high)	"=A" (val)
    They're used in an inline assembly that reads an MSR

    Code:
    static inline unsigned long long native_read_msr(unsigned int msr)
    {
    	DECLARE_ARGS(val, low, high);
    
    	asm volatile("rdmsr" : EAX_EDX_RET(val, low, high) : "c" (msr));
    	return EAX_EDX_VAL(val, low, high);
    }
    Thank you all!
    Last edited by limp; 06-30-2009 at 10:00 AM.

  2. #2
    pwning noobs Zlatko's Avatar
    Join Date
    Jun 2009
    Location
    The Great White North
    Posts
    132
    Well, the low and high values seem to be ignored. (I say seem to, because I'm never sure of anything until I run it through the CPU.)
    Try finding the option to to your compiler to run just the preprocessor. That will replace the macros (they're not typedefs, they're macros) with the real C code. The preprocessor will output to a file usually ending with .i
    Which compiler are you using?

  3. #3
    spurious conceit MK27's Avatar
    Join Date
    Jul 2008
    Location
    segmentation fault
    Posts
    8,300
    I'm not sure this is so good. This bit looks particularly meaningless to me:
    Code:
    {
    	DECLARE_ARGS(val, low, high);
    Even if it did anything, where are val, low, and high coming from inside native_read_msr()?

    And all these will do will do is return val:
    Code:
    #define DECLARE_ARGS(val, low, high)	unsigned long long val
    #define EAX_EDX_VAL(val, low, high)	(val)
    If the first one even compiles, since these are, in fact *NOT* typedefs.

    It looks to me like an "abandoned" segment of code; eg. something that was left in by mistake (presuming that the whole thing actually works?).

    There is a chance some asm guru could set me straight here about something I'm ignorant of, but I'm pretty sure this is just bad code.
    C programming resources:
    GNU C Function and Macro Index -- glibc reference manual
    The C Book -- nice online learner guide
    Current ISO draft standard
    CCAN -- new CPAN like open source library repository
    3 (different) GNU debugger tutorials: #1 -- #2 -- #3
    cpwiki -- our wiki on sourceforge

  4. #4
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Quote Originally Posted by MK27
    This bit looks particularly meaningless to me:
    It means:
    Code:
    unsigned long long val;
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  5. #5
    spurious conceit MK27's Avatar
    Join Date
    Jul 2008
    Location
    segmentation fault
    Posts
    8,300
    Quote Originally Posted by laserlight View Post
    It means:
    Code:
    unsigned long long val;
    Exactly. So:

    Code:
    static inline unsigned long long native_read_msr(unsigned int msr)
    {
               unsigned long long val;
    That is incomplete. Maybe "purposeless" would have been more accurate than "meaningless" but hopefully the point is clear...

    [edit] sorry I'm a little bit mistaken here...
    Last edited by MK27; 06-30-2009 at 08:49 AM.
    C programming resources:
    GNU C Function and Macro Index -- glibc reference manual
    The C Book -- nice online learner guide
    Current ISO draft standard
    CCAN -- new CPAN like open source library repository
    3 (different) GNU debugger tutorials: #1 -- #2 -- #3
    cpwiki -- our wiki on sourceforge

  6. #6
    and the Hat of Guessing tabstop's Avatar
    Join Date
    Nov 2007
    Posts
    14,336
    Quote Originally Posted by MK27 View Post
    Exactly. So:

    Code:
    static inline unsigned long long native_read_msr(unsigned int msr)
    {
               unsigned long long val;
    That is incomplete. Maybe "purposeless" would have been more accurate than "meaningless" but hopefully the point is clear...
    What do you mean incomplete? It's a variable declaration. What exactly were you expecting?

  7. #7
    spurious conceit MK27's Avatar
    Join Date
    Jul 2008
    Location
    segmentation fault
    Posts
    8,300
    Quote Originally Posted by tabstop View Post
    What do you mean incomplete? It's a variable declaration. What exactly were you expecting?
    Whoops! I just decided to ignore the "val" on the end.

    Which makes that code dependent on this line:
    Code:
    asm volatile("rdmsr" : EAX_EDX_RET(val, low, high) : "c" (msr));
    still, a strange, veritably obfuscated way to write IMO.
    Last edited by MK27; 06-30-2009 at 03:02 PM.
    C programming resources:
    GNU C Function and Macro Index -- glibc reference manual
    The C Book -- nice online learner guide
    Current ISO draft standard
    CCAN -- new CPAN like open source library repository
    3 (different) GNU debugger tutorials: #1 -- #2 -- #3
    cpwiki -- our wiki on sourceforge

  8. #8
    Registered User
    Join Date
    Jun 2009
    Posts
    26
    Quote Originally Posted by Zlatko
    Try finding the option to to your compiler to run just the preprocessor. That will replace the macros (they're not typedefs, they're macros) with the real C code.
    Quote Originally Posted by MK27 View Post
    If the first one even compiles, since these are, in fact *NOT* typedefs.
    You're right guys, I was in a bit of rush!

    Quote Originally Posted by Zlatko
    Try finding the option to to your compiler to run just the preprocessor. The preprocessor will output to a file usually ending with .i Which compiler are you using?
    I am using GCC 4.2.4

    Quote Originally Posted by MK27
    Even if it did anything, where are val, low, and high coming from inside native_read_msr()?
    That's why the DECLARE_ARGS(val, low, high) is called. It probably creates these variables and make them all equal to val??


    Actually this is Linux code so it *should* work OK.

    Thanks for the help so far!

  9. #9
    pwning noobs Zlatko's Avatar
    Join Date
    Jun 2009
    Location
    The Great White North
    Posts
    132
    I am using GCC 4.2.4
    gcc -E will send preprocessor output to your console. Be prepared for lots of output if you have header files. I usually redirect it to a new c file so that I can see it in a syntax colouring editor.

    Edit:
    Ohhhh, even better
    gcc -c -save-temps foo.c
    will save preprocessor output to foo.i
    Last edited by Zlatko; 06-30-2009 at 10:34 AM.

  10. #10
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Well, if you had bothered to read the surrounding bits of code, you'd see that there is a #ifdef for CONFIG_X86_64 and #else for the #define's that you posted. Since the type of a 64-bit value is different in x86-64 and x86-32, the code inline assembler will have to deal with this fact, and using these macros allow it to achieve that without writing two complete functions.

    For reference:
    LXR linux/arch/x86/include/asm/msr.h (the quoted function is at line 42).

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  11. #11
    spurious conceit MK27's Avatar
    Join Date
    Jul 2008
    Location
    segmentation fault
    Posts
    8,300
    Quote Originally Posted by MK27 View Post
    Whoops! I just decided to ignore the "val" on the end.
    So I guess there is a sense in which
    Code:
    #define DECLARE_ARGS(val, low, high)	unsigned long long val
    would be useful during development, but either someone forgot to refine this later or they still have big hopes for the future.
    C programming resources:
    GNU C Function and Macro Index -- glibc reference manual
    The C Book -- nice online learner guide
    Current ISO draft standard
    CCAN -- new CPAN like open source library repository
    3 (different) GNU debugger tutorials: #1 -- #2 -- #3
    cpwiki -- our wiki on sourceforge

  12. #12
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    It makes much more sense if you have ALL the relevant defines:
    Code:
    #ifdef CONFIG_X86_64
    #define DECLARE_ARGS(val, low, high)    unsigned low, high
    #define EAX_EDX_VAL(val, low, high)     ((low) | ((u64)(high) << 32))
    #define EAX_EDX_ARGS(val, low, high)    "a" (low), "d" (high)
    #define EAX_EDX_RET(val, low, high)     "=a" (low), "=d" (high)
    #else
    #define DECLARE_ARGS(val, low, high)    unsigned long long val
    #define EAX_EDX_VAL(val, low, high)     (val)
    #define EAX_EDX_ARGS(val, low, high)    "A" (val)
    #define EAX_EDX_RET(val, low, high)     "=A" (val)
    #endif
    Since in x86_64, a long is 64 bits, and returned in ONE register (EAX), we need to make two unsigned (32-bit) values into a single 64-bit value. Meanwhile, in x86_32, each register holds 32 bits, so we need to return a 64-bit value as two registers (eax, edx). It just so happens also that msr's values are returned in eax, edx. The symbol A in inline assembler represents a 64-bit pair of EAX, EDX.

    It is not something missing/extra in there, it's simply that the macros do not use all arguments earch time, instead they are using either val (as a 64-bit two-register integer) or low, high as two 32-bit values that get returned as a single register 64-bit value.

    Which is a longer way of explaining what I said in the previous post. Is it because I posted a link to the source rather than typing it out that it was hard to understand this?

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  13. #13
    spurious conceit MK27's Avatar
    Join Date
    Jul 2008
    Location
    segmentation fault
    Posts
    8,300
    Quote Originally Posted by matsp View Post
    Which is a longer way of explaining what I said in the previous post. Is it because I posted a link to the source rather than typing it out that it was hard to understand this?
    No, I understand now matsp. Thanks!
    C programming resources:
    GNU C Function and Macro Index -- glibc reference manual
    The C Book -- nice online learner guide
    Current ISO draft standard
    CCAN -- new CPAN like open source library repository
    3 (different) GNU debugger tutorials: #1 -- #2 -- #3
    cpwiki -- our wiki on sourceforge

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. weird things with my linked list of queue
    By -EquinoX- in forum C Programming
    Replies: 3
    Last Post: 11-22-2008, 11:23 PM
  2. weird
    By kiz in forum C Programming
    Replies: 8
    Last Post: 09-24-2007, 01:16 AM
  3. Weird Characters With GetDlgItemText
    By execute in forum Windows Programming
    Replies: 4
    Last Post: 05-04-2006, 04:53 PM
  4. weird error
    By gandalf_bar in forum Linux Programming
    Replies: 2
    Last Post: 07-17-2005, 07:32 AM
  5. Getting weird characters in Strings
    By steve8820 in forum C Programming
    Replies: 3
    Last Post: 09-18-2001, 02:49 AM