[Toybox] [landley/toybox] weak symbols hack broke the build (Issue #554)

Rob Landley rob at landley.net
Wed Jul 2 09:26:29 PDT 2025


On 7/2/25 07:22, enh-google wrote:
> enh-google created an issue (landley/toybox#554)
> 
> (was "clang build still broken" on the mailing list, but my mails to the list [and direct to rob] are being bounced.)

Sigh. I submitted _another_ removal request to check.spamhaus.org, and 
also sent a long explanatory message through their contact-center webform.

I should have saved a copy of that message so I can send it to the NEXT 
one. Shipping compiler binaries means malware authors use them, virus 
writers decide that gcc leaking the compiler's build paths into the 
resulting binaries gives them sufficiently unique strings to check for, 
and then it's just:

https://www.akamai.com/blog/security-research/new-rce-botnet-spreads-mirai-via-zero-days

Over and over again...

> bounced mail first:
> 
> On Tue, Jul 1, 2025 at 12:41 PM Rob Landley <[rob at landley.net](mailto:rob at landley.net)> wrote:
>>
>> On 6/30/25 14:46, enh wrote:
>>> sending as a separate thread, so it's obvious that there's new
>>> information here... in particular, note that clang isn't complaining
>>> about _attribute_ ordering, it's complaining that the _definition_ it
>>> already saw doesn't match the redeclaration:
>>
>> It built for me with the android-ndk-r27. I'm confused.
> 
> the ndk is generally behind the current platform clang.

There still isn't a self-contained NDK build I can git pull and run on 
my laptop, is there?

>>> external/toybox/lib/hash.c:309:16: error: attribute declaration must
>>> precede definition [-Werror,-Wignored-attributes]
>>>     309 | __attribute__((__weak__)) void hash_by_name(int fd, char
>>> *name, char *result)
>>>         |                ^
>>
>> Define "precede". The attribute declaration is now the first thing on
>> the line. (That's what commit 17d77a264ab6 changed.)
> 
> note that it explicitly says "declaration" must precede "definition".

It says attribute declaration, not function declaration.

The attribute doesn't go on the prototype. Otherwise you couldn't tell 
WHICH symbol was weak.

>> void blah(int, char *, char *)
>> void blah(int, char *, char *)
>>
>> What differs other than one being weak? I'm not spotting it.
> 
> i think that's exactly the complaint. if you're going to say weak, a
> weak declaration has to come before anything else.

Do you have example syntax I could use? Because I have no idea what the 
compiler wants.

>> Sigh, I can go back to #ifdefs if clang is that buggy,
> 
> tbh, i didn't understand why you made this change in the first place.
> given the two variants, there's always going to be a need to build and
> test both. so is "always building both [and trusting that we throw the
> right one away later]" a big improvement?

I prefer dead code elimination to #ifdefs because with the first I 
regression testing everything each build, and with the second there are 
codepaths I haven't personally tried in who knows how long which may or 
may not still compile.

> ---------------
> 
> but "new shit has come to light". turns out there's at least one version of gcc that can't build this too:
> 
> ```
> % make android_defconfig && make
> ..
> lib/hash.c: At top level:
> lib/hash.c:309:28: error: redefinition of 'hash_by_name'
>    309 | __attribute__((weak)) void hash_by_name(int fd, char *name,
> char *result)
>        |                            ^~~~~~~~~~~~
> lib/hash.c:22:6: note: previous definition of 'hash_by_name' with type
> 'void(int,  char *, char *)'
>     22 | void hash_by_name(int fd, char *name, char *result)
>        |      ^~~~~~~~~~~~
> make: *** [Makefile:18: toybox] Error 1
> % cc --version
> cc (Debian 14.2.0-19+build4) 14.2.0
> Copyright (C) 2024 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.
> ```

So it cares that they're in two different compilation units. It works 
fine as long as they're NOT in the same file. That seems deeply silly, 
and clearly _is_ a regression from what both gcc and clang were both 
doing this time last year. I still think this is a compiler bug (weak 
means there can be more than one, that's literally ALL it means), but 
that doesn't mean I don't have to work around it.

No wonder musl is using:

extern __typeof(old) new __attribute__((__weak__, __alias__(#old)))

(Yelling "toro!" as the problem charges the red cape and zooms past.)

Except I was trying to do that for crypt and hit the "is old prototyped 
or not" problem in the __typeof(). The alias depends on the prototype of 
variant you're switching to existing, you can't #ifdef or 
__has_include() for prototypes. Here I can probably switch to that, but 
crypt is only _sometimes_ in the headers posix says it's in, so I was 
trying to make the other way work.

 > https://godbolt.org/z/qG5jxbaax

Which compiler version is this? I want to be able to reproduce it so I 
can tell if I've fixed it. That site pops up a "privacy policy" and when 
that's dismissed the URL redirects to just gotbolt.org with no info on 
what the query was, and the tabs say "x86-64 gcc (trunk)" which is... 
current gcc git maybe?


More information about the Toybox mailing list