<div dir="ltr"><div dir="ltr"><br></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Sat, Feb 19, 2022 at 2:59 AM Rob Landley <<a href="mailto:rob@landley.net">rob@landley.net</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">On 2/17/22 12:05 PM, enh via Toybox wrote:<br>
> On Thu, Feb 17, 2022 at 5:23 AM John wrote:<br>
> > This is a simple patch for seq.c to rename itoa to toybox_itoa, to avoid<br>
> > clashes with functions in the toolchain.<br>
><br>
> > As Piraty mentioned on IIRC there are 2 different implementations of itoa in<br>
> > musl alone, so this should avoid any clashes people have with<br>
> > implementations in their toolchain.<br>
><br>
> the two musl itoa functions are both static, so there's no possibility of a<br>
> clash (otherwise musl itself would have a problem internally!).<br>
> <br>
> what was the actual issue you were seeing?<br>
<br>
I've been waiting for the reply to Elliott's question myself. I'm happy to apply<br>
a fix for an actual bug, but not a purely theoretical "maybe someday" bug.<br>
<br>
But even if it did happen (which seems especially unlikely in musl since Rich is<br>
scrupulous about namespace pollution), in theory a static function declared<br>
earlier in the same compilation unit is going to bind before anything outside<br>
even if some library does have its own version of it. Which means all I'd really<br>
have to worry about is header namespace polution (#including a header with the<br>
conflicting declaration):<br>
<br>
$ cat boing.c<br>
#include <stdio.h><br>
<br>
int exit(char *str)<br>
{<br>
  return printf("string was %s\n", str);<br>
}<br>
<br>
int main(int argc, char *argv[])<br>
{<br>
  int x = exit("potato");<br>
<br>
  printf("and it returned %d\n", x);<br>
<br>
  return 0;<br>
}<br>
$ gcc boing.c<br>
boing.c:3:5: warning: conflicting types for built-in function ‘exit’<br>
[-Wbuiltin-declaration-mismatch]<br>
 int exit(char *str)<br>
     ^~~~<br>
$ ./a.out<br>
string was potato<br>
and it returned 18<br>
<br>
In practice modern compilers are polluting their own namespaces all over the<br>
place, but the option to tell it to stop is "-fno-builtin". and even without<br>
adding that the gcc version works fine.<br>
<br>
Of course the Android NDK version calls my builtin exit() twice and then segfaults:<br>
<br>
$ ./a.out<br>
string was potato<br>
and it returned 18<br>
string was (null)<br>
error: TLS segment alignment in " is not a power of 2: 1<br>
<br>
libc: error: TLS segment alignment in " is not a power of 2: 1<br>
<br>
Aborted<br>
<br>
But I'm guessing that's because bionic's post-main() code that gets returned to<br>
tries to call exit() out of libc and apparently binds to mine if I redefine it.<br>
(Seriously, I break everything. And I point out it wasn't MY code deviating from<br>
expected behavior, it was android's... </blockquote><div><br></div><div>define "expected". this is mostly WAI.</div><div><br></div><div>"WAI" because interposing random libc functions is definitely something we support (for asan etc), but only "mostly" because i'm not sure whether we have a sanitizer that actually needs to interpose exit() or not.</div><div><br></div><div>long ago, we -Bsymbolic'ed everything, but that breaks interposing.</div><div><br></div><div>in practice, i find "connect" is the function that confuses the most people. i've yet to see anyone _want_ to call their own function "exit" :-)</div><div><br></div><div>this might matter more on other systems, but on Android where all apps on user's devices are run by forking from the zygote anyway, you can't be bitten by what i call the "executable always wins" rule of dynamic linking because app_process is your exectuable, and we can just not make that mistake there (and/or deliberately interpose; things like ndk_translation's tricks to run Android arm binaries on glibc x86 systems, say, or ART's trickery with chaining signal handlers).</div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">I want to say crtend.a but they don't<br>
seem to have one? Only .so versions. Eh, it's successfully linking and running<br>
as a static binary (which I still have to do because I haven't installed bionic<br>
on the host) and I'm not running it under strace to try to find out where it's<br>
pulling this stuff from...)<br></blockquote><div><br></div><div>a static binary avoids these kinds of questions.</div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
However, if I make my new exit() static and feed the compiler -fno-builtin, then<br>
the NDK behaves the same way gcc did. (And oddly enough for a _static_ function<br>
clang both works properly and doesn't warn even without -fno-builtin, while gcc<br>
still warns about the static function not matching its expectations. Go figure.)<br>
<br>
Anyway, the point is that even in this contrived case (where I'm fighting<br>
compiler builtins, which itoa() is not likely to become any time soon), the<br>
static function defined before the other function should work fine. Yes even in<br>
the presence of a library that has its own function with the same name I use in<br>
my code.<br>
<br>
This is part of the reason the compiler puts -lc at the end. I had to get that<br>
right back when I had a wrapper to rewrite the gcc command line to start with<br>
--nostdinc --notstdlib and then add everything _back_ to link against uClibc<br>
portability in a compiler that you could extract into an arbitrary directory and<br>
add to the $PATH from there, defeating gcc's horrible "all my resources live at<br>
an absolute path determined at compile time" logic:<br>
<br>
<a href="https://github.com/landley/aboriginal/blob/master/sources/toys/ccwrap.c" rel="noreferrer" target="_blank">https://github.com/landley/aboriginal/blob/master/sources/toys/ccwrap.c</a><br>
<br>
The -lc goes after all the .o files to ensure local references are satisfied<br>
first, but stuff resolved in the same compilation unit should be fine either way.<br>
<br>
Rob<br>
<br>
P.S. I was extremely annoyed as a teenager when I upgraded my turbo c++ version<br>
and suddenly the function throw() in the bbs software I'd written stopped<br>
working because the language committee had decided to make that a keyword. Since<br>
then I maintained the uClibc toolchain using the above wrapper for a decade or<br>
so, maintained my own tinycc fork for 3 years, helped get dynamic linking<br>
working on a new Linux port (qualcomm heaxagon: they had static linking working<br>
already but building x11 with static linking was just painful: yes you CAN stick<br>
debug printfs into uClibc's dynamic loader before it's relocated itself, if by<br>
"printf" you mean a macro that uses a char array on the stack as the buffer it's<br>
passing to an open coded write() system call), learned all SORTS of fun nommu<br>
weirdness about ... These days toybox has a header that #includes all the other<br>
standard headers out of posix and and common bsd ancestry, and then if some<br>
build environment gets weird I hit it with a rock via #ifdefs and #defines in<br>
portability.h. Anything CAN break, at any time. The way to deal with sharp edges<br>
is to find them and file them off.<br>
<br>
P.P.S. "theoretically correct" and "works properly" are two different things,<br>
which sometimes require years of repeatedly explaining at maintainers in<br>
extensive detail:<br>
<br>
<a href="https://lore.kernel.org/qemu-devel/4B73F8CC.6010406@suse.de/t/#md050a8a3df649c375e0ebcd74273f72ff2bf9653" rel="noreferrer" target="_blank">https://lore.kernel.org/qemu-devel/4B73F8CC.6010406@suse.de/t/#md050a8a3df649c375e0ebcd74273f72ff2bf9653</a><br>
</blockquote></div></div>