Bug 252720 - powerpc64 gcc toolchain missing __BYTE_ORDER__ et. al.
Summary: powerpc64 gcc toolchain missing __BYTE_ORDER__ et. al.
Status: New
Alias: None
Product: Base System
Classification: Unclassified
Component: bin (show other bugs)
Version: 12.2-RELEASE
Hardware: powerpc Any
: --- Affects Only Me
Assignee: freebsd-bugs (Nobody)
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2021-01-15 21:50 UTC by Julio Merino,+1 347 694 0576,New York City
Modified: 2021-01-17 05:44 UTC (History)
1 user (show)

See Also:


Attachments
Avoid __BYTE_ORDER__ (1.40 KB, patch)
2021-01-17 05:44 UTC, Julio Merino,+1 347 694 0576,New York City
no flags Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Julio Merino,+1 347 694 0576,New York City freebsd_committer 2021-01-15 21:50:17 UTC
I recently got a PowerMac G5 (powerpc64 big-endian). I was able to install 12.1-RELEASE successfully (the powerpc64 build; there is no powerpc64le duality in 12) on it. I was also able to download the sources for stable/12, do a whole buildworld, and then an installworld. Everything was flawless!

But after the upgrade to 12.2-STABLE from sources, I am unable to buildworld again and other things seem randomly broken (pkg cannot load its database any longer).

buildworld fails like:

===> kerberos5/tools/make-roken (obj,all,install)
objcopy --strip-debug --add-gnu-debuglink=make-roken.debug  make-roken.full make-roken
objcopy: unsupported e_type
*** [make-roken] Error code 1

I dug around a bit and found that libelf seems to have been compiled for a little-endian target: when it checks the e_type of the binary, it gets 0x200 when in reality it should be getting a 0x2.

And indeed, after some more poking, it seems that the gcc toolchain that ships with 12.1-RELEASE thinks it's targeting a little endian machine:

g5:~> cat test.c 
#include <stdio.h>

int main(void) {
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
    printf("little!\n");
#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
    printf("big!\n");
#else
    printf("what?\n");
#endif
}

With the 12.1-RELEASE toolchain:

g5:~> /usr/bin/cc --version
cc (GCC) 4.2.1 20070831 patched [FreeBSD]
Copyright (C) 2007 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

g5:~> /usr/bin/cc test.c && ./a.out
little!

^^^ THIS IS WRONG! ^^^

With the gcc9 compiler installed from pkg:

g5:~> /usr/local/bin/gcc9 --version
gcc9 (FreeBSD Ports Collection) 9.3.0
Copyright (C) 2019 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

g5:~> /usr/local/bin/gcc9 test.c && ./a.out
big!

^^^ THIS IS RIGHT ^^^

After the upgrade to stable/12, the compiler still thinks it's targeting a little-endian machine.

What's interesting, though, is that the binaries that the compiler produces _are_ big-endian -- or else nothing would run. However, the __BYTE_ORDER__ macro is wrong.

Any thoughts on where the problem may be and how to get out of this situation? It looks like I cannot use the base system's compiler to buildworld to upgrade (or for that matter, to build anything).
Comment 1 Julio Merino,+1 347 694 0576,New York City freebsd_committer 2021-01-15 22:16:41 UTC
For some reason I had mistakenly downloaded 12.1-RELEASE instead of 12.2-RELEASE. I have now downloaded the latter and found that the toolchain behaves in the same way... so the problem hasn't been fixed AFAICT.
Comment 2 Ed Maste freebsd_committer 2021-01-16 01:12:51 UTC
If __BYTE_ORDER__ and __ORDER_LITTLE_ENDIAN__ are not defined they will both evaluate to 0 and the result will be true; can you confirm this is not the case you're seeing?
Comment 3 Julio Merino,+1 347 694 0576,New York City freebsd_committer 2021-01-16 20:37:08 UTC
Hah. I came to the same conclusion before seeing your comment. Indeed, the macros are undefined when using the gcc that ships with the base system but they are defined when using gcc9 from ports. (And by looking at the source tree, I understand that they are defined as well when using the clang in the base system.)
Comment 4 Julio Merino,+1 347 694 0576,New York City freebsd_committer 2021-01-17 05:44:35 UTC
Created attachment 221660 [details]
Avoid __BYTE_ORDER__

I scanned the stable/12 source tree and found a bunch of files that query __BYTE_ORDER__. Most seem to have provisions for this macro not being defined, but a couple of them do not. The attached patch seems to have helped generate a new powerpc64 userland that works well.

I do not know if this kind of patch is desired, or if instead sys/endian.h or something like that should be modified to define __BYTE_ORDER__ in terms of other available macros when the former is detected to be missing. It seems to me that this would be slightly more robust.

There is also the question of how this problem slipped through QA into a release.