Discussion:
[avr-libc-dev] [bug #50811] using -Wl, -u, vfprintf -lprintf_min causes program to grow a lot
anonymous
2017-04-15 23:38:23 UTC
Permalink
URL:
<http://savannah.nongnu.org/bugs/?50811>

Summary: using -Wl,-u,vfprintf -lprintf_min causes program to
grow a lot
Project: AVR C Runtime Library
Submitted by: None
Submitted on: Sat 15 Apr 2017 11:38:22 PM UTC
Category: None
Severity: 3 - Normal
Priority: 5 - Normal
Item Group: None
Status: None
Percent Complete: 0%
Assigned to: None
Originator Email: ***@gmail.com
Open/Closed: Open
Discussion Lock: Any
Release: 2.0.0
Fixed Release: None

_______________________________________________________

Details:


The documentation seems to be saying that using those flags is supposed to
save flash, but without them, a main() that does a single printf("foo\n");
gives me a 330 byte flash, while with them I get a 1330 byte flash.

If I remove the printf() call, I get flash sizes of 1228 or 228 with or
without the above mentioned printf-min flags, respectively.

It looks like somehow the printf-min flag ends up dragging in a bunch extra
code somehow?

The rest of my linker invocation looks like this:

avr-gcc -mmcu=atmega328p -lm -Wl,-gc-sections
-Wl,-Map=program_to_upload.out.map -o program_to_upload.out main.o

I think probably the documentation ought to mention this possibility, assuming
it isn't a bug.




_______________________________________________________

Reply to this item at:

<http://savannah.nongnu.org/bugs/?50811>

_______________________________________________
Message sent via/by Savannah
http://savannah.nongnu.org/
Dave Hylands
2017-04-16 21:11:13 UTC
Permalink
Follow-up Comment #1, bug #50811 (project avr-libc):

Calling printf("foo\n"); will be optimized to puts("foo"); so your test isn't
really valid.

Try omparing a program which uses printf("foo: %d\n", 42); instead.

_______________________________________________________

Reply to this item at:

<http://savannah.nongnu.org/bugs/?50811>

_______________________________________________
Message sent via/by Savannah
http://savannah.nongnu.org/
anonymous
2017-04-17 06:18:07 UTC
Permalink
Follow-up Comment #2, bug #50811 (project avr-libc):

Ok, with printf("foo: %d\n, 42), the program is indeed smaller with by 264
bytes when -Wl,-u,vfprintf -lprintf_min is used than when none of the printf
linker flags are used.

I guess this is a wishlist item really: it would be nice if using printf_min
didn't end up adding 1000 or so bytes to the program size when variadic
vfprintf() invocations don't happen at all.
I suppose given the realities of how the linker works that's unlikely. At
least the issue deserves a mention in the discussion of these options in the
vfprintf() documentation (that they can end up making your program a lot
bigger, rather than smaller).


_______________________________________________________

Reply to this item at:

<http://savannah.nongnu.org/bugs/?50811>

_______________________________________________
Message sent via/by Savannah
http://savannah.nongnu.org/
Dave Hylands
2017-04-17 16:46:36 UTC
Permalink
Follow-up Comment #3, bug #50811 (project avr-libc):

Using _Wl,-u,vfprintf is essentially forcing the symbol vfprintf to be
undefined and added to the program. This is what's causing your code size to
increase when not otherwise using vfprintf.

It isn't clear to me why that option should be required at all. You should
only need to add the -lprintf_min option and that will pull in vprintf, if its
used, and won't pull anything in if it isn't.

_______________________________________________________

Reply to this item at:

<http://savannah.nongnu.org/bugs/?50811>

_______________________________________________
Message sent via/by Savannah
http://savannah.nongnu.org/
anonymous
2017-04-17 18:54:57 UTC
Permalink
Follow-up Comment #4, bug #50811 (project avr-libc):

You're correct, there's no reason when printf isn't being used to use those
linker options. However:

* realistically at least some linker options are at least somewhat black magic
to many users.

* printf() is particularly likely to go from unused to used during debugging,
during which large swings in code size may be extra confusing

For these reasons, I still think adding something to the documentation would
make sense. It could be as simple as one sentence explaining what you just
explained:

"Note that if your program doesn't end up calling vfprintf(), using the
printf_min linker flags will increase code size because it forces the
vfprintf() function to be included even though it isn't used."

_______________________________________________________

Reply to this item at:

<http://savannah.nongnu.org/bugs/?50811>

_______________________________________________
Message sent via/by Savannah
http://savannah.nongnu.org/
Dave Hylands
2017-04-17 19:19:56 UTC
Permalink
Follow-up Comment #5, bug #50811 (project avr-libc):

I guess my point is that this statement (by itself) is false:

"Note that if your program doesn't end up calling vfprintf(), using the
printf_min linker flags will increase code size because it forces the
vfprintf() function to be included even though it isn't used."

It's only when both options are used together that you get that behaviour.

I think using -Wl,-u,vfprintf is incorrect and there is no need to use that
option unless you want to keep unused code in your image.

Personally, I'd find the behaviour of keeping unused code in the image to be
the confusing behaviour, not the fact that my debug builds are considerably
larger than my release builds.

_______________________________________________________

Reply to this item at:

<http://savannah.nongnu.org/bugs/?50811>

_______________________________________________
Message sent via/by Savannah
http://savannah.nongnu.org/
Joerg Wunsch
2017-04-17 20:07:55 UTC
Permalink
Follow-up Comment #6, bug #50811 (project avr-libc):

Well, the fact that the -u vfprintf needs to be forced is
an unfortunate side effect of libprintf_min.a *only* containing
a different definition of vfprintf(), but not e.g. for printf()
or other members of the family.

Thus, if you only add -lprintf_min, this library will be
processed by a time when the linker has not seen any obvious
need to drag the vfprintf symbol in from it, so in effect, it
will be ignored. Later on, when it comes to resolve the
symbols needed by (e.g.) printf, it will suddenly also need
vfprintf, but libprintf_min.a is already done by that time,
so the standard version of vfprintf is used (from libc.a).

We could probably reorganize these libraries to also contain
the other printf family members, but 1) that needs to be done
by someone (who?), and 2) it won't fix the history, so the
documentation has to remain the way it is for at least a
while (a couple of years or more).

While the complaint this bug is focussing on is not
completely invalid, I think it's practically a non-issue:
except for the degraded testcase, nobody would want to drag
in the full power (and bloat) of printf() & co. if all he
wants to do is printing some constant strings without using
any of the formatting functionality. As soon as a real
printf functionality is needed, as seen, there is indeed a
minimal saving of space by libprintf_min.a.

_______________________________________________________

Reply to this item at:

<http://savannah.nongnu.org/bugs/?50811>

_______________________________________________
Message sent via/by Savannah
http://savannah.nongnu.org/
anonymous
2017-04-17 21:04:22 UTC
Permalink
Follow-up Comment #7, bug #50811 (project avr-libc):

If that's the case, why provide an optimized version of printf() for constant
strings at all? I guess maybe it happens inevitably due to compiler
machinations.

Anyway, at least one person (me) hit this issue and it took me some time to
find the culprit. I set LDFLAGS for the printf_min long ago with the idea of
generally keeping program size low, and this turns out to be a very poor
general policy. The current docs don't give any indication of this, while
they do describe smaller savings related to vfprintf choice in the presence of
printf(). That's inconsistent and somewhat misleading.


_______________________________________________________

Reply to this item at:

<http://savannah.nongnu.org/bugs/?50811>

_______________________________________________
Message sent via/by Savannah
http://savannah.nongnu.org/
Joerg Wunsch
2017-04-18 06:02:58 UTC
Permalink
Post by anonymous
I guess maybe it happens inevitably due to compiler
machinations.
Exactly, it's a compiler thing we cannot influence.

_______________________________________________________

Reply to this item at:

<http://savannah.nongnu.org/bugs/?50811>

_______________________________________________
Message sent via/by Savannah
http://savannah.nongnu.org/
Georg-Johann Lay
2017-05-09 20:55:01 UTC
Permalink
Follow-up Comment #9, bug #50811 (project avr-libc):

Re. the "compiler thing" mentioned above:

avr-gcc might replace a call to printf by a call to puts provided the
arguments of printf allows to do so. You can avoid this optimization by means
of -fno-builtin-printf which takes away any knowledge (except prototype
information) about printf from the compiler. This will result in a call to
printf (which you are using anyway), saving the call to fputs.

_______________________________________________________

Reply to this item at:

<http://savannah.nongnu.org/bugs/?50811>

_______________________________________________
Message sent via/by Savannah
http://savannah.nongnu.org/

Loading...