AVR Freaks Forum Index

Post new topic   Reply to topic
View previous topic Printable version Log in to check your private messages View next topic
Author Message
lacis_alfredo
PostPosted: Oct 22, 2007 - 02:37 AM
Rookie


Joined: Aug 10, 2007
Posts: 35
Location: Brisbane, Australia

Hi,
We cannot find how to get the linker to ignore unused functions.

E.g., if we have two functions in a common library file foobar.c, foo() and bar(), and we only use foo(), bar() still seems to be linked when we look at the link map.

We've looked at 'man ld' but we can't see anything that looks likely.

How can we stop this, please...?

Would turning the common files into a 'library.a' file help? We want to avoid this because every project uses its own definitions, etc.

Alf
 
 View user's profile Send private message Visit poster's website 
Reply with quote Back to top
abcminiuser
PostPosted: Oct 22, 2007 - 03:00 AM
Moderator


Joined: Jan 23, 2004
Posts: 7014
Location: Melbourne, Victoria, Australia

Try using -ffunction-sections, which should result in the unlinked functions being thrown away from the binary.

- Dean Twisted Evil

_________________

 
 View user's profile Send private message Send e-mail Visit poster's website 
Reply with quote Back to top
JulianHigginson
PostPosted: Oct 22, 2007 - 03:04 AM
Hangaround


Joined: Aug 16, 2005
Posts: 301


you can use #defines to describe what your project needs, and then have #ifdef statements to pull out things from your "library" file.

that's what I use. (though more for code configuration in a single project than function removal from different projects.... in my case, I've written different handler functions for different modem/GPS/combinations, and don't want all of the code for all possible devices being compiled into my microcontroller - but it's the same basic idea for what you might want to do, I think)

ie

Code:

#define USE_FOO
#define USE_BAR

.
.
.
#ifdef USE_FOO
int foo();
#endif

#ifdef USE_BAR
int bar();
#endif

.
.
.

#ifdef USE_FOO
int foo()
{
}
#endif

#ifdef USE_BAR
int bar()
{
}
#endif


I have a header file called _setup.h that I put these defines in, and then refer to that in the relevant .h and .c files I want to control.
 
 View user's profile Send private message  
Reply with quote Back to top
dl8dtl
PostPosted: Oct 22, 2007 - 09:15 AM
Raving lunatic


Joined: Dec 20, 2002
Posts: 6697
Location: Dresden, Germany

> E.g., if we have two functions in a common library file foobar.c

That's not how libraries usually work. The usual way of things is
to use a "one file, one function" approach (except for things that
inherently belong together). When using that approach, if you
afterwards create a library xxx.a (using avr-ar) out of the individual
.o files, the linker will only pick those modules that are really
needed.

Individual .o files given on the command-line will however always be
linked.

_________________
Jörg Wunsch

Please don't send me PMs, use email instead.
Please read the `General information...' article before.
 
 View user's profile Send private message Send e-mail Visit poster's website 
Reply with quote Back to top
clawson
PostPosted: Oct 22, 2007 - 11:36 AM
10k+ Postman


Joined: Jul 18, 2005
Posts: 34381
Location: (using avr-gcc in) Finchingfield, Essex, England

What a shame no one bothered to explain this in the user manual ...


... oh, wait a minute, they did:

http://www.nongnu.org/avr-libc/user-manual/library.html

_________________
 
 View user's profile Send private message  
Reply with quote Back to top
EW
PostPosted: Oct 22, 2007 - 04:40 PM
Raving lunatic


Joined: Mar 01, 2001
Posts: 4227
Location: Rocky Mountains

abcminiuser wrote:
Try using -ffunction-sections, which should result in the unlinked functions being thrown away from the binary.

- Dean Twisted Evil


Dean, that's not complete.

One must use -ffunction-sections (compiler switch) AND -Wl,-gc-sections (linker switch) to have the linker "garbage collect" (or remove) unused sections. The -ffunction-sections switch places all functions within their own section. You must use both together to make this work.
 
 View user's profile Send private message Send e-mail Visit poster's website 
Reply with quote Back to top
EW
PostPosted: Oct 22, 2007 - 04:41 PM
Raving lunatic


Joined: Mar 01, 2001
Posts: 4227
Location: Rocky Mountains

clawson wrote:
What a shame no one bothered to explain this in the user manual ...


... oh, wait a minute, they did:

http://www.nongnu.org/avr-libc/user-manual/library.html


Thanks! I wrote that because I got tired of repeating myself when answering the same questions over again.
 
 View user's profile Send private message Send e-mail Visit poster's website 
Reply with quote Back to top
lacis_alfredo
PostPosted: Oct 29, 2007 - 03:48 AM
Rookie


Joined: Aug 10, 2007
Posts: 35
Location: Brisbane, Australia

JulianHigginson:
The #ifdef FLAG (actually better to use #ifndef NOT_FLAG) only works for libraries which we have written: libraries from elsewhere in the company or the Net don't have this, and we don't want to start peppering that code with our own #ifndef's.

EW:
Thanks for the -ffunction-sections AND -Wl,-gc-sections: one project I just tried it on went from 15508 down to 14584 bytes: about 900 bytes of saving.

Definitely a 'keeper'.

Thanks muchly,
(at about 20m elevation)
Best regards,
Alf Lacis


Last edited by lacis_alfredo on Nov 06, 2007 - 02:04 AM; edited 1 time in total
 
 View user's profile Send private message Visit poster's website 
Reply with quote Back to top
lacis_alfredo
PostPosted: Oct 29, 2007 - 04:31 AM
Rookie


Joined: Aug 10, 2007
Posts: 35
Location: Brisbane, Australia

clawson:

clawson wrote:
What a shame no one bothered to explain this in the user manual ...

... oh, wait a minute, they did:

http://www.nongnu.org/avr-libc/user-manual/library.html


Yes, I saw this page already before this post.... it did not provide the answer that EW gave of the compiler and linker options which I've added to the various makefiles:
Code:

CFLAGS += -ffunction-sections
LDFLAGS += -Wl,-gc-sections
However, thanks for your input.

Alf
 
 View user's profile Send private message Visit poster's website 
Reply with quote Back to top
clawson
PostPosted: Oct 29, 2007 - 10:47 AM
10k+ Postman


Joined: Jul 18, 2005
Posts: 34381
Location: (using avr-gcc in) Finchingfield, Essex, England

Yeah but it's the best way to make a library (rather than later trying to remove the stuff that "accidentally" got included). Say, for example, that you later made the lib available to others, will they know (or remember) to use ffunction-section and gc-sections? If you make it a "normal" lib where each function is in a separate .o and is therefore only bound in if called then it works for everyone wiht no special stuff being required (just like libc in fact)

_________________
 
 View user's profile Send private message  
Reply with quote Back to top
david.prentice
PostPosted: Oct 29, 2007 - 01:28 PM
Raving lunatic


Joined: Feb 12, 2005
Posts: 7696
Location: Cratfield, England

dear Alf,

I echo Cliff.

Put all your library source in one directory tree.
Include every function object in your Makefile.
Compile every function as a separate file.
Create a single header file for the library function prototypes and any typedefs. Do not have any internal stuff in this header.

Make all the objects via Make.
Use avr-ar to build the libalfred.a via Make.

If you are posh you can generate the documentation too.

Then release <alfred.h> and libalfred.a with the source to the unsuspecting public.

The public says thankyou. The public needs no special compiler switches.

David.
 
 View user's profile Send private message Send e-mail  
Reply with quote Back to top
lacis_alfredo
PostPosted: Nov 06, 2007 - 02:09 AM
Rookie


Joined: Aug 10, 2007
Posts: 35
Location: Brisbane, Australia

Hi, david.prentice & clawson,

Yes, I hear you... and I've done this where it's practical and useful: at the pointy end of a new company's startup, or a new large standalone project.

The situation with the embedded targets with the company I joined 3 months ago, can be summed up with three ideas: history, money, and customer contentment.
    (1) The company has 12-year-long history of different embedded targets, with hundreds of thousands of devices shipped, across scores of product lines;

    (2) the 'libraries' are really just places in the directory tree to hold collections of code source;

    (3) the sources are full of #ifdef...#endif fences and other build switches that are different for practically every target, and therefore *must* be compiled for each target;

    (4) the targets are different CPUs: i.e., Phillips, Renesas(Hitachi), and a few different ATmegas, and even the board layout may mean that the same external device is on another port or bit; and, you probably guessed, this is catered for by build switches, not configuration code;

    (5) the compilers are varied, e.g., several versions of WIN-AVR-GCC (depending on the project!), Cygwin(for PC tools), Renesas/HEW (others?);

    (6) because of 2 thru 5, and they way the company has grown, the code is highly coupled, and detangling it now would cause problems that we don't need to generate for our historical products;
Considering all this: while I like libraries, I do not think that creating compiled libraries is the 'best' thing to do in this company. (And besides, it's not my call anyway.) Sometimes the 'best' thing to do (I know this may gall) is nothing. "If it ain't broke, don't fix it."

Best Regards, and I thank you for your inputs,
Alf Lacis
 
 View user's profile Send private message Visit poster's website 
Reply with quote Back to top
david.prentice
PostPosted: Nov 06, 2007 - 10:46 AM
Raving lunatic


Joined: Feb 12, 2005
Posts: 7696
Location: Cratfield, England

dear Alf,

I take your point about conditional code. It is not worth the aggravation for complex code. I would leave as a source library that hangs off your project rather than a system library directory.

With simple 64 bit operations this will only be conditional on the AVR model.

So a compiled library IS possible. It just gets a separate incarnation in each "model" tree e.g. avr5 ...

As a source library, the library would be compiled in the project directory. Your project Makefile includes two new dependencies:

Code:
MY_LIB     = alf
MY_LIBOBJS = lib_obj1.o lib_obj2.o ...
lib$(MY_LIB).a: $(MY_LIBS)
           avr-ar rv $@ $?
# or let ar handle the update.
#          avr-ar ruv $@ $(MY_LIBS)

project.elf: lib$(MY_LIB).a $(OBJS)


Just written this off the top of my head, rather than looking at one of my own project Makefiles.

David.
 
 View user's profile Send private message Send e-mail  
Reply with quote Back to top
lacis_alfredo
PostPosted: Nov 20, 2007 - 01:54 AM
Rookie


Joined: Aug 10, 2007
Posts: 35
Location: Brisbane, Australia

Thanks, David,

That's not a bad way of doing it, tho I haven't tried it yet.

Thanks, & Regards,
Alf Lacis
http://au.geocities.com/lacis_alfredo
 
 View user's profile Send private message Visit poster's website 
Reply with quote Back to top
brberie
PostPosted: Nov 20, 2007 - 07:09 PM
Resident


Joined: Sep 12, 2003
Posts: 529
Location: XX century

Quote:
/main.c:1: warning: -ffunction-sections may affect debugging on some targets

Quote:
avr-objcopy -O ihex -R .eeprom -j .text -j .data main.elf main.hex
avr-objcopy -j .eeprom --set-section-flags=.eeprom="alloc,load" \
--change-section-lma .eeprom=0 -O ihex main.elf main.eep
avr-objdump -h -S main.elf > main.lss
avr-nm -n main.elf > main.sym
avr-objcopy --debugging --change-section-address .data-0x800000 --change-section-address .bss-0x800000 --change-section-address .noinit-0x800000 --change-section-address .eeprom-0x810000 -O coff-ext-avr main.elf ./main.cof
avr-objcopy: main.elf: no recognized debugging information

Size after:
AVR Memory Usage
----------------
Device: atmega128

Program: 0 bytes (0.0% Full)
(.text + .data + .bootloader)

Data: 0 bytes (0.0% Full)
(.data + .bss + .noinit)



Is this correct behavior?
 
 View user's profile Send private message  
Reply with quote Back to top
abcminiuser
PostPosted: Nov 20, 2007 - 10:44 PM
Moderator


Joined: Jan 23, 2004
Posts: 7014
Location: Melbourne, Victoria, Australia

I used to get that warning on an old version of AVR-GCC - it seems to be gone with the newer releases. IIRC, it was actually there in error, and was put in as a safety by the mainline GCC code for some targets, to remind the developers to test out the switch.

It all boiled down to the -ffunction-sections putting each function into its own section, which confused some debuggers (which expected all the data to be in the one section) I think.

- Dean Twisted Evil

_________________

 
 View user's profile Send private message Send e-mail Visit poster's website 
Reply with quote Back to top
lacis_alfredo
PostPosted: Aug 10, 2008 - 01:58 PM
Rookie


Joined: Aug 10, 2007
Posts: 35
Location: Brisbane, Australia

Not linking unused functions? Nine Months Later: GCC ARM Toolkit
(Yes, I know this is not strictly AVR, but we're all software engineers. This Forum will be crawled by Google, etc, so they will find the reference to the ARM processor, and may help some of us later: it's all karma, right?)

I'm now doing some code for an Atmel ARM AT91SAM7X256, using a GCC toolkit.

I'm pleased to say that the optimization works the same for the ARM as it did for the ATmega... lots of unused functions have been optimized out of the link map.

You may recall the Makefile flags were:
Code:
CFLAGS += -ffunction-sections
LDFLAGS += -Wl,-gc-sections
With the build tool I'm using, the -f option is passed to the compiler:
Code:
-ffunction-sections
For the linker, the option string is (you don't need the "-Wl," if passing straight to the linker):
Code:
-gc-sections
I hope this will have been useful,
Regards,
Alf Lacis
http://alfredo4570.customer.netspace.net.au
 
 View user's profile Send private message Visit poster's website 
Reply with quote Back to top
EW
PostPosted: Aug 10, 2008 - 05:47 PM
Raving lunatic


Joined: Mar 01, 2001
Posts: 4227
Location: Rocky Mountains

Yes, since GCC is the same, whether for ARM or for AVR, those switches should work.

A small word of caution: It is up to the target back-end, whether or not garbage collection on unused sections is done. So it happens to work on ARM and AVR, but I cannot guarantee that it work on other GCC targets. However, it should work on targets that are well supported, I think.
 
 View user's profile Send private message Send e-mail Visit poster's website 
Reply with quote Back to top
Display posts from previous:     
Jump to:  
All times are GMT + 1 Hour
Post new topic   Reply to topic
View previous topic Printable version Log in to check your private messages View next topic
Powered by PNphpBB2 © 2003-2006 The PNphpBB Group
Credits