2

What is the purpose of COERCE_FLOAT and COERCE_UNSIGNED_INT macros in the Hex Rays decompiled code below?

double __cdecl sub_401580(float a1)
{
  unsigned int v1; // eax@1
  double v2; // st7@1
  float v4; // [sp+10h] [bp+4h]@1
  float v5; // [sp+10h] [bp+4h]@1

  v1 = LODWORD(a1) & 0x80000000;
  v4 = 1.273239493370056 * a1 - a1 * 0.4052847325801849 * COERCE_FLOAT(LODWORD(a1) & 0x7FFFFFFF);
  v2 = v4;
  v5 = v4 * v4;
  return (float)(v5
               * ((v5 * COERCE_FLOAT(v1 ^ COERCE_UNSIGNED_INT(-0.0032225901))
                 + COERCE_FLOAT(v1 | COERCE_UNSIGNED_INT(0.015124941)))
                * v5
                + COERCE_FLOAT(v1 | COERCE_UNSIGNED_INT(0.20363937)))
               + v2 * 0.7844448685646057);
}
  • What is the question? – tmr232 Dec 25 '15 at 10:19
  • that is the question :P – blabb Dec 25 '15 at 13:58
  • macro doing ? COERCE_FLOAT and COERCE_UNSIGNED_INT – Arun Dec 26 '15 at 7:43
  • please help me to simply the code – Arun Dec 26 '15 at 7:44
6

COERCE_TYPE(x) is the same thing as *(TYPE *)&x. Hex-Rays uses COERCE_... macros when &x is illegal. For example:

COERCE_DOUBLE(__PAIR__(i1,i2))

Is the same as *(double *)&__PAIR__(i1, i2), but since & can not be applied to calls, we end up seeing COERCE.

Its name correctly conveys its meaning.

  • Are You The Ilfak Guilfanov ? Welcome to RESE – blabb Jan 17 at 10:51
1

I'd read this (and probably it is a mistake) as treating binary content of the variable as a variable of another type, something like this:

  • coerce float is *((float*)&var), where var was of the same size as float, supposedly 4 bytes.
  • coerce unsigned int is *((unsigned int*)&var), where var was of the same size as unsigned int.

As far as I remember 32 bit platforms treating unsigned int and float as a values of 4 bytes length.

  • 1
    Thanx for Your Answer, where all these macro defined in ida decompiler, is there any header file – Arun Jan 21 '16 at 14:20
  • I don;t know anything about header file where ii is defined. It is only suggestion. – w s Jan 21 '16 at 16:19
  • I'm with @Arun, I would love to know where these macros are defined so I can go look them up. – bravosierra99 Aug 17 '16 at 18:24
1

coerce_* functions are generally a little more coercive that a simple casting, I would assume their meaning as follows:

   #define VALUE_SIZE (sizeof(int))

struct VALUE_TYPE {
    char contents[VALUE_SIZE];
};

struct VALUE_TYPE COERCE_FLOAT(float arg) {
    struct VALUE_TYPE rv;
    memcpy(&arg, rv.contents, sizeof arg);
    return rv;
}

struct VALUE_TYPE COERCE_INT(int arg) {
    struct VALUE_TYPE rv;
    memcpy(&arg, rv.contents, sizeof arg);
    return rv;
}

struct VALUE_TYPE COERCE_UNSIGNED_INT(unsigned int arg) {
    struct VALUE_TYPE rv;
    memcpy(&arg, rv.contents, sizeof arg);
    return rv;
}

source: https://stackoverflow.com/a/37198532/912236

The reason for their use may relate to how the ABI passes floats vs how it passes integers. There is no difference in Windows 32-bit code (either stdcall or cdecl), but in x64 float's and integers are passed in different registers.

It's possible that those macro may make no difference to compilation of a 32-bit target, and are just there to ensure (or inform the reader/compiler) of the expected type, but that's pure conjecture on my part.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.