How to tell when app will run in 64-bit mode?

  • Is there a way to determine when an 'obese-binary' application will
    launch in 64-bit mode?  I'm aware of Apple's
    CheckExecutableArchitecture sample code

        http://developer.apple.com/samplecode/CheckExecutableArchitecture/

    but that only distinguishes between Intel and PPC.  My attempts to
    extend the code to check the cputype flag for x86_64 have been
    unsuccessful, so I'm wondering if someone's aware of a better way
    (please?)

      - Jon

    --
    ________________________________________________________________________
            Jon Gotow                    <gotow...>
        St. Clair Software              http://www.stclairsoft.com/
        Fax (540)552-5898              ftp://ftp.stclairsoft.com/
  • #ifdef __LP64__
    bool in_64bit = true;
    #else
    bool in_64bit = false;
    #endif

    More importantly, if you have code that differs between 32bit and 64bit,
    it is better to conditionally compile than it is to check during
    runtime.  Remember that an 'obese-binary' is basically 4 copies of your
    program.

    -benski

    Jon Gotow wrote:
    > Is there a way to determine when an 'obese-binary' application will
    > launch in 64-bit mode?  I'm aware of Apple's CheckExecutableArchitecture
    > sample code
    >
    > http://developer.apple.com/samplecode/CheckExecutableArchitecture/
    >
    > but that only distinguishes between Intel and PPC.  My attempts to
    > extend the code to check the cputype flag for x86_64 have been
    > unsuccessful, so I'm wondering if someone's aware of a better way (please?)
    >
    > - Jon
    >
  • Woops, sorry I misunderstood your question, ignore me :)  You are
    looking for a way to tell if some arbitrary binary other than yours is
    going to run in 64bit mode.

    Ben Allison wrote:
    > #ifdef __LP64__
    > bool in_64bit = true;
    > #else
    > bool in_64bit = false;
    > #endif
    >
    > More importantly, if you have code that differs between 32bit and 64bit,
    > it is better to conditionally compile than it is to check during
    > runtime.  Remember that an 'obese-binary' is basically 4 copies of your
    > program.
    >
    > -benski
    >
    > Jon Gotow wrote:
    >> Is there a way to determine when an 'obese-binary' application will
    >> launch in 64-bit mode?  I'm aware of Apple's
    >> CheckExecutableArchitecture sample code
    >>
    >> http://developer.apple.com/samplecode/CheckExecutableArchitecture/
    >>
    >> but that only distinguishes between Intel and PPC.  My attempts to
    >> extend the code to check the cputype flag for x86_64 have been
    >> unsuccessful, so I'm wondering if someone's aware of a better way
    >> (please?)
    >>
    >> - Jon
    >>
    >
    > _______________________________________________
    > MacOSX-dev mailing list
    > <MacOSX-dev...>
    > http://www.omnigroup.com/mailman/listinfo/macosx-dev
  • You can use the cpusubtype member of the fat_arch struct in the Mach-O
    header to determine the CPU type for a particular section.    man arch
    enumerates the CPU types; in particular, you would look for
    CPU_SUBTYPE_POWERPC64_ALL and CPU_SUBTYPE_X86_64_ALL.

    Jon Gotow wrote:
    > Is there a way to determine when an 'obese-binary' application will
    > launch in 64-bit mode?  I'm aware of Apple's CheckExecutableArchitecture
    > sample code
    >
    > http://developer.apple.com/samplecode/CheckExecutableArchitecture/
    >
    > but that only distinguishes between Intel and PPC.  My attempts to
    > extend the code to check the cputype flag for x86_64 have been
    > unsuccessful, so I'm wondering if someone's aware of a better way (please?)
    >
    > - Jon
    >
  • At 12:01 PM -0500 2/6/08, Ben Allison wrote:
    > #ifdef __LP64__
    > bool in_64bit = true;
    > #else
    > bool in_64bit = false;
    > #endif

    Sorry - I should have been clearer.  I know how to make my own obese
    binaries and check to see whether _I'm_ in 64-bit mode (I've been
    doing that for a while).  The issue is that I want to look at another
    running application - or the application bundle on disk - and
    determine whether it will run in 64-bit mode or not.

    And to further clarify, I know how to look at the bundle on disk and
    determine which executable architectures exist in the obese binary,
    so I know whether an app is _capable_ of running 64-bit.  The
    question is whether it will on the machine I'm currently running on.

    The crux of the matter is really that NXGetLocalArchInfo() returns a
    cputype of CPU_TYPE_X86 on both Core Duo and Core 2 Duo machines.
    Shouldn't it return CPU_TYPE_X86_64 on Core 2 Duo?  Is this a bug?
    Is there another way to determine this?  Dang - I just realized I
    haven't even tried calling Gestalt() for this - though that'd be an
    odd mix of API's...

      - Jon

    --
    ________________________________________________________________________
            Jon Gotow                    <gotow...>
        St. Clair Software              http://www.stclairsoft.com/
        Fax (540)552-5898              ftp://ftp.stclairsoft.com/
  • At 12:12 PM -0500 2/6/08, Ben Allison wrote:
    > You can use the cpusubtype member of the fat_arch struct in the
    > Mach-O header to determine the CPU type for a particular section.
    > man arch enumerates the CPU types; in particular, you would look for
    > CPU_SUBTYPE_POWERPC64_ALL and CPU_SUBTYPE_X86_64_ALL.

    Heh - I was busy answering your last post.  NXGetLocalArchInfo()
    gives me a cputype of CPU_TYPE_X86 and a cputsubtype of
    CPU_SUBTYPE_486 on both my Core Duo and Core 2 Duo machines, so that
    doesn't appear to be any help.

    How does the loader determine which binary to run?  It doesn't appear
    to be using NXFindBestFatArch() with the results of
    NXGetLocalArchInfo(), because when I do that, it always gives me the
    32-bit section.

      - Jon

    --
    ________________________________________________________________________
            Jon Gotow                    <gotow...>
        St. Clair Software              http://www.stclairsoft.com/
        Fax (540)552-5898              ftp://ftp.stclairsoft.com/
  • Jon -

    Sorry about the confusion earlier.

    The docs for arch(1) suggest a rather convoluted methodology for
    determining which one to choose, including alteration via environment
    variables and plist files in known locations.

    That still doesn't help the fact that NXGetLocalArchInfo() is saying
    that you have a 486.

    You could at least make an educated guess that if you wrote a fat,
    universal binary, that another fat, universal binary will load with the
    same architecture as the one you're currently running on.

    If you intend to use this from some scripting environment or a plugin to
    another application that you don't have control over, you could write a
    simple commandline app which just returns a value representing CPU type
    (using #ifdef __ppc64__ kind of stuff).

    Jon Gotow wrote:
    > At 12:12 PM -0500 2/6/08, Ben Allison wrote:
    >> You can use the cpusubtype member of the fat_arch struct in the Mach-O
    >> header to determine the CPU type for a particular section. man arch
    >> enumerates the CPU types; in particular, you would look for
    >> CPU_SUBTYPE_POWERPC64_ALL and CPU_SUBTYPE_X86_64_ALL.
    >
    > Heh - I was busy answering your last post.  NXGetLocalArchInfo() gives
    > me a cputype of CPU_TYPE_X86 and a cputsubtype of CPU_SUBTYPE_486 on
    > both my Core Duo and Core 2 Duo machines, so that doesn't appear to be
    > any help.
    >
    > How does the loader determine which binary to run?  It doesn't appear to
    > be using NXFindBestFatArch() with the results of NXGetLocalArchInfo(),
    > because when I do that, it always gives me the 32-bit section.
    >
    > - Jon
    >
  • At 12:40 PM -0500 2/6/08, Ben Allison wrote:
    > The docs for arch(1) suggest a rather convoluted methodology for
    > determining which one to choose, including alteration via
    > environment variables and plist files in known locations.
    >
    > That still doesn't help the fact that NXGetLocalArchInfo() is saying
    > that you have a 486.
    >
    > You could at least make an educated guess that if you wrote a fat,
    > universal binary, that another fat, universal binary will load with
    > the same architecture as the one you're currently running on.

    Yeah - it looks like that's the approach I need to take.  Create a
    simple obese universal binary that will load in whatever mode dyld
    deigns to be 'best' with its convoluted logic - then I'll know which
    section of other apps it'll choose when they run.

    Ick.

    Thanks a bunch for the help!

      - Jon

    --
    ________________________________________________________________________
            Jon Gotow                    <gotow...>
        St. Clair Software              http://www.stclairsoft.com/
        Fax (540)552-5898              ftp://ftp.stclairsoft.com/
  • At 12:20 PM -0500 2/6/08, Jon Gotow wrote:
    > The crux of the matter is really that NXGetLocalArchInfo() returns a
    > cputype of CPU_TYPE_X86 on both Core Duo and Core 2 Duo machines.
    > Shouldn't it return CPU_TYPE_X86_64 on Core 2 Duo?

    As is often the case, discussing the problem with you smart folks
    here (thanks Ben :-) led me to reassess what I was doing.  Given that
    NXGetLocalArchInfo() wasn't giving me what I thought it should, I
    looked for a different way to do the same thing.

    Digging through some darwin code, I found the "sysctl.proc_cputype"
    sysctl token.  THAT gives the right results.  On my Core 2 Duo, when
    I check a running process, I now get a cpu type of:

    cpu_type = (CPU_TYPE_X86 | CPU_ARCH_ABI64)

    if the process is running in 64 bit mode.

    - Jon

    For those that can benefit from it, here's the code, which uses the
    sysctlbyname_with_pid() function in Apple's Universal Binary
    Programming Guidelines:

    cpu_type_t GetProcessArchitecture(pid_t pid)
    {
        cpu_type_t cputype;
        size_t cpusz = sizeof(cputype);

        // Default values
    #if __i386__
        cputype = CPU_TYPE_X86;
    #else
        cputype = CPU_TYPE_POWERPC;
    #endif

        if (sysctlbyname_with_pid("sysctl.proc_cputype", pid,
                                  &cputype, &cpusz, NULL, 0) == -1)
        {
            fprintf(stderr, "proc_cputype: sysctlbyname_with_pid failed:"
                    "%s\n", strerror(errno));
        }
        return cputype;
    }
    --
    ________________________________________________________________________
            Jon Gotow                    <gotow...>
        St. Clair Software              http://www.stclairsoft.com/
        Fax (540)552-5898              ftp://ftp.stclairsoft.com/
  • At 12:01 PM -0500 2/6/08, Ben Allison wrote:
    > #ifdef __LP64__
    > bool in_64bit = true;
    > #else
    > bool in_64bit = false;
    > #endif
    >
    > More importantly, if you have code that differs between 32bit and
    > 64bit, it is better to conditionally compile than it is to check
    > during runtime.  Remember that an 'obese-binary' is basically 4
    > copies of your program.

    Yes, of course - that was going to be my approach by writing a little
    obese helper app - different code would run depending on which
    architecture and ABI got loaded.  But if you want to do something
    different to someone else's app depending on whether it's 64 bit or
    not, you have to go poke at it :-)

      - Jon

    --
    ________________________________________________________________________
            Jon Gotow                    <gotow...>
        St. Clair Software              http://www.stclairsoft.com/
        Fax (540)552-5898              ftp://ftp.stclairsoft.com/
  • On Feb 6, 2008, at 11:41 AM, Jon Gotow wrote:

    > Digging through some darwin code, I found the "sysctl.proc_cputype"
    > sysctl token.  THAT gives the right results.  On my Core 2 Duo, when
    > I check a running process, I now get a cpu type of:
    >
    > cpu_type = (CPU_TYPE_X86 | CPU_ARCH_ABI64)
    >
    > if the process is running in 64 bit mode.

    I believe there is also a "hw.cpu64bit_capable" sysctl if you want to
    determine specifically what the hardware can do.

    Douglas Davidson
  • Am 06.02.2008 um 21:26 schrieb Jon Gotow:

    > But if you want to do something different to someone else's app
    > depending on whether it's 64 bit or not, you have to go poke at it :-)

    Would the "file" tool help you?

    file /path/to/binary | grep x86

    or similar.

    Markus

    - - - - - - - - - - - - - - - - - - -
    Dipl. Ing. Markus Hitter
    http://www.jump-ing.de/
  • On 06.02.2008, at 22:04, Markus Hitter wrote:
    > Am 06.02.2008 um 21:26 schrieb Jon Gotow:
    >> But if you want to do something different to someone else's app
    >> depending on whether it's 64 bit or not, you have to go poke at
    >> it :-)
    >
    > Would the "file" tool help you?
    > file /path/to/binary | grep x86
    > or similar.

    How would that help? It just contains the architectures included in
    the FAT, but not in which architecture the binary will get executed/
    loaded by the system?

    Helge
    --
    http://www.helgehess.eu/
  • At 1:39 AM +0100 2/7/08, Helge Hess wrote:
    >> Would the "file" tool help you?
    >> file /path/to/binary | grep x86
    >> or similar.
    >
    >
    > How would that help? It just contains the architectures included in
    > the FAT, but not in which architecture the binary will get
    > executed/loaded by the system?

    Correct.  And trying to predict what the system will or should do
    with it, even if you do know the processor type, isn't a particularly
    great approach either.  That's why using sysctl turned out to be the
    best approach in my case.

      - Jon

    --
    ________________________________________________________________________
            Jon Gotow                    <gotow...>
        St. Clair Software              http://www.stclairsoft.com/
        Fax (540)552-5898              ftp://ftp.stclairsoft.com/