Linker is adding extra crap (Unreferenced library code)

support for the ARM toolchain
Dwedit
Posts: 43
Joined: Sun Jan 06, 2008 4:06 am

Linker is adding extra crap (Unreferenced library code)

Post by Dwedit » Fri Sep 30, 2011 8:33 am

I'm having problems with unnecessary code getting linked into my project. I can't figure out where these symbols are coming from:

abort
_Unwind_decode_target2
__aeabi_unwind_cpp_pr0
restore_core_regs
__gnu_unwind_execute
__libc_init_array

After I disassemble my .elf file with objdump, I can't find any jumps, calls, or references to any of these symbols. I also tried disassembling all the .o files from my source code, and saw no references to them there either.

Of these symbols, "abort" is particularly bad, because linking in "abort" brings malloc into a program that does not use it. Linking in malloc eats up some IWRAM, and it's enough to make me run out.

When I was investigating some of the symbols, I noticed that "abort" is called by some of the multiplcation and division code in libgcc (why?!), but I could not find any calls to abort anywhere in my disassembled code.

I managed to exclude any "linker junk" by making a bunch of blank functions:

Code: Select all

void abort(){}
void __libc_init_array(){}
void _Unwind_VRS_Get(){}
void _Unwind_VRS_Set(){}
void __aeabi_unwind_cpp_pr2(){}
void __aeabi_unwind_cpp_pr1(){}
void __aeabi_unwind_cpp_pr0(){}
void _Unwind_VRS_Pop(){}
void _Unwind_GetCFA(){}
void __gnu_Unwind_RaiseException(){}
void __gnu_Unwind_ForcedUnwind(){}
void __gnu_Unwind_Resume(){}
void __gnu_Unwind_Resume_or_Rethrow(){}
void _Unwind_Complete(){}
void _Unwind_DeleteException(){}
void __gnu_Unwind_Backtrace(){}
void __restore_core_regs(){}
void restore_core_regs(){}
void __gnu_Unwind_Restore_VFP(){}
void __gnu_Unwind_Save_VFP(){}
void __gnu_Unwind_Restore_VFP_D(){}
void __gnu_Unwind_Save_VFP_D(){}
void __gnu_Unwind_Restore_VFP_D_16_to_31(){}
void __gnu_Unwind_Save_VFP_D_16_to_31(){}
void __gnu_Unwind_Restore_WMMXD(){}
void __gnu_Unwind_Save_WMMXD(){}
void __gnu_Unwind_Restore_WMMXC(){}
void __gnu_Unwind_Save_WMMXC(){}
void ___Unwind_RaiseException(){}
void _Unwind_RaiseException(){}
void _Unwind_Resume(){}
void ___Unwind_Resume(){}
void _Unwind_Resume_or_Rethrow(){}
void ___Unwind_Resume_or_Rethrow(){}
void _Unwind_ForcedUnwind(){}
void ___Unwind_ForcedUnwind(){}
void ___Unwind_Backtrace(){}
void _Unwind_Backtrace(){}
When I include these blank functions, I get no extraneous library functions thrown in during linking.
After including these blank functions, I checked the disassembly of my code, and saw absolutely no references or calls to any of these functions.

What is going on here? Why are unreferenced functions getting linked in and bloating up the program?

WinterMute
Site Admin
Posts: 1906
Joined: Tue Aug 09, 2005 3:21 am
Location: UK
Contact:

Re: Linker is adding extra crap (Unreferenced library code)

Post by WinterMute » Sat Oct 01, 2011 1:22 pm

None of your questions are going to be answered until you learn to phrase them with a lot more respect. I have yet to see a post from you that isn't really quite offensive.
Help keep devkitPro toolchains free, Donate today

Personal Blog

Dwedit
Posts: 43
Joined: Sun Jan 06, 2008 4:06 am

Re: Linker is adding extra unreferenced library code

Post by Dwedit » Sat Oct 01, 2011 10:14 pm

I'm sorry, it's just that these posts usually come immediately after I've been trying for about 4 hours to frantically figure out what's going on, and I'm really frustrated at the time I'm posting them.

I just really don't understand how code that isn't referenced anywhere ends up in the program. What steps would I need to do to see what code is attempting to import the library code in question? It is very mysterious, since there are no references to this stuff anywhere in the disassemblies. Right now, the only method I have to "fight" against this problem is to make dummy functions.

User avatar
vuurrobin
Posts: 219
Joined: Fri Jul 11, 2008 8:49 pm
Location: The Netherlands
Contact:

Re: Linker is adding extra crap (Unreferenced library code)

Post by vuurrobin » Sun Oct 02, 2011 12:39 am

my knowledge of gcc is limited, but AFAIK if your program uses 1 part of an object file, it includes the entire object file, causing the linker to include unused functions.

according to this post (http://devkitpro.org/viewtopic.php?f=14&t=1665), you can remove unused code with "-Wl,--gc-sections":
link option: add -Wl,--gc-sections => garbage collect unreferenced sections => removes all your unused code, but also compiler generated code & data which is finally unused. It means that even if all of your routines are used, it still saves ROM.

Dwedit
Posts: 43
Joined: Sun Jan 06, 2008 4:06 am

Re: Linker is adding extra crap (Unreferenced library code)

Post by Dwedit » Sun Oct 02, 2011 2:08 am

I have now tried that, but it didn't work.

My makefile line now looks like
LDFLAGS = -g $(ARCH) -Wl,-Map,$(notdir $@).map,--gc-sections


EDIT:
When I look through "libgcc.a", I see this odd symbol table stuff in "bpabi.o".
There are references to "aeabi_unwind_cpp_pr0", but they do not appear in the disassembled code, and seem to only appear in the *UND* section. So why does that symbol get linked in?

Code: Select all


bpabi.o:     file format elf32-littlearm
bpabi.o
architecture: arm, flags 0x00000011:
HAS_RELOC, HAS_SYMS
start address 0x00000000
private flags = 5000000: [Version5 EABI]

Sections:
Idx Name          Size      VMA       LMA       File off  Algn
  0 .text         00000074  00000000  00000000  00000034  2**2
                  CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE
  1 .data         00000000  00000000  00000000  000000a8  2**0
                  CONTENTS, ALLOC, LOAD, DATA
  2 .bss          00000000  00000000  00000000  000000a8  2**0
                  ALLOC
  3 .ARM.extab    00000000  00000000  00000000  000000a8  2**0
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  4 .ARM.exidx    00000010  00000000  00000000  000000a8  2**2
                  CONTENTS, ALLOC, LOAD, RELOC, READONLY, DATA
  5 .comment      00000023  00000000  00000000  000000b8  2**0
                  CONTENTS, READONLY
  6 .ARM.attributes 00000032  00000000  00000000  000000db  2**0
                  CONTENTS, READONLY
SYMBOL TABLE:
00000000 l    d  .text	00000000 .text
00000000 l    d  .data	00000000 .data
00000000 l    d  .bss	00000000 .bss
00000000 l    d  .ARM.extab	00000000 .ARM.extab
00000000 l    d  .ARM.exidx	00000000 .ARM.exidx
00000000 l    d  .comment	00000000 .comment
00000000 l    d  .ARM.attributes	00000000 .ARM.attributes
00000000         *UND*	00000000 __aeabi_lmul
00000000 g     F .text	0000003a __gnu_ldivmod_helper
00000000         *UND*	00000000 __divdi3
00000000         *UND*	00000000 __aeabi_unwind_cpp_pr0
0000003c g     F .text	00000036 __gnu_uldivmod_helper
00000000         *UND*	00000000 __udivdi3


RELOCATION RECORDS FOR [.text]:
OFFSET   TYPE              VALUE 
0000000c R_ARM_THM_CALL    __divdi3
0000001c R_ARM_THM_CALL    __aeabi_lmul
00000048 R_ARM_THM_CALL    __udivdi3
00000054 R_ARM_THM_CALL    __aeabi_lmul


RELOCATION RECORDS FOR [.ARM.exidx]:
OFFSET   TYPE              VALUE 
00000000 R_ARM_PREL31      .text
00000000 R_ARM_NONE        __aeabi_unwind_cpp_pr0
00000008 R_ARM_PREL31      .text


I see a few other *UND* section references as well:

Code: Select all

_divdi3.o.headers.txt(37): 00000000         *UND*	00000000 __aeabi_unwind_cpp_pr1
_divdi3.o.headers.txt(67): 00000000 R_ARM_NONE        __aeabi_unwind_cpp_pr1
_moddi3.o.headers.txt(37): 00000000         *UND*	00000000 __aeabi_unwind_cpp_pr1
_moddi3.o.headers.txt(67): 00000000 R_ARM_NONE        __aeabi_unwind_cpp_pr1
_udiv_w_sdiv.o.headers.txt(34): 00000000         *UND*	00000000 __aeabi_unwind_cpp_pr0
_udiv_w_sdiv.o.headers.txt(40): 00000000 R_ARM_NONE        __aeabi_unwind_cpp_pr0
_udivdi3.o.headers.txt(37): 00000000         *UND*	00000000 __aeabi_unwind_cpp_pr1
_udivdi3.o.headers.txt(67): 00000000 R_ARM_NONE        __aeabi_unwind_cpp_pr1
_udivmoddi4.o.headers.txt(37): 00000000         *UND*	00000000 __aeabi_unwind_cpp_pr1
_udivmoddi4.o.headers.txt(67): 00000000 R_ARM_NONE        __aeabi_unwind_cpp_pr1
_umoddi3.o.headers.txt(37): 00000000         *UND*	00000000 __aeabi_unwind_cpp_pr1
_umoddi3.o.headers.txt(67): 00000000 R_ARM_NONE        __aeabi_unwind_cpp_pr1
bpabi.o.headers.txt(36): 00000000         *UND*	00000000 __aeabi_unwind_cpp_pr0
bpabi.o.headers.txt(52): 00000000 R_ARM_NONE        __aeabi_unwind_cpp_pr0
None of these symbols appears anywhere in the disassembled code.

WinterMute
Site Admin
Posts: 1906
Joined: Tue Aug 09, 2005 3:21 am
Location: UK
Contact:

Re: Linker is adding extra crap (Unreferenced library code)

Post by WinterMute » Mon Oct 03, 2011 2:35 pm

This stuff is part of the aeabi standard for some reason that escapes me - some parts of libgcc are built with exception handling code and pull in some extras that most people don't expect to see in their code. I've actually been looking into this over the last few weeks to see what will break if I do some tweaks to remove the extra dependencies.

devkitARM is intended to be a lot more generic than just a compiler that targets GBA/NDS so I need to be pretty careful about making changes for one particular use case.

Making a bunch of blank functions to avoid pulling in extra library code you don't really need isn't an ideal solution so hopefully I can manage to get rid of this stuff without causing problems elsewhere.
Help keep devkitPro toolchains free, Donate today

Personal Blog

tueidj
Posts: 40
Joined: Thu Dec 10, 2009 9:26 am

Re: Linker is adding extra crap (Unreferenced library code)

Post by tueidj » Mon Oct 03, 2011 6:40 pm

The *divdi3 functions are used for 64-bit division/modulus, they will only get linked in (along with the *divmod_helper functions) if you use a (u)int64 in a divide or mod operation. Probably *lmul serves a similar purpose (long multiplication?) but I'm not positive about that. For this reason it's best to avoid using div/mod/mul on 64-bit types if at all possible. If they're still getting linked in, check the .map file to find out what function is calling them.

Dwedit
Posts: 43
Joined: Sun Jan 06, 2008 4:06 am

Re: Linker is adding extra crap (Unreferenced library code)

Post by Dwedit » Tue Oct 04, 2011 2:04 am

Here, I'm doing a 64-bit unsigned division. This is a call to the function __aeabi_uldivmod.
So it depends on these functions:
__aeabi_uldivmod from _aeabi_uldivmod.o
__aeabi_ldiv0 from _dvmd_tls.o (this appears to be a blank function, the only content is "bx lr", it's probably the division by 0 handler)
__gnu_uldivmod_helper from bpabi.o
> __divdi3 from _divdi3.o
> __aeabi_lmul from _muldi3.o
> __udivdi3 from _udivdi3.o
>> __aeabi_uidiv from _udivsi3.o
>> __aeabi_uidivmod from _udivsi3.o
>> __clzsi2 from _clzsi2.o

So far, so good. No problems here.
Except then it proceeds to bring in "__aeabi_unwind_cpp_pr0", even though none of these functions call that function.
"bpabi.o" contains a reference to that function in the symbol table, but it does not exist anywhere in the code. It is tagged as *UND*.

You can see this yourself, use "arm-eabi-ar -x libgcc.a" to get the *.o files out of the library, and "arm-eabi-objdump -d bpabi.o > bpabi.s" to get a disassembly. No code anywhere calls __aeabi_unwind_cpp_pr0.
But if you do "arm-eabi-objdump -t bpabi.o > bpabi.sym" to get the symbol table, there's an external reference symbol for that function anyway.

"__aeabi_unwind_cpp_pr0" brings in a lot more code, including "abort", which brings in "malloc".

So if the code doesn't use it, why does it make a reference to it?

zeromus
Posts: 212
Joined: Wed Mar 31, 2010 6:05 pm

Re: Linker is adding extra crap (Unreferenced library code)

Post by zeromus » Tue Oct 04, 2011 5:22 am

youll also see sections .ARM.extab and .ARM.exidx in the bpapi.o ; exception handling junk that isnt in dwedit.o. its not too surprising that gcc also emit an extern reference to the exception handling code into that file when it emit the exception handling data..maybe to make sure that the exception handling system got linked in, even if there was no code that raised any exceptions?

I was unable to find my way through the maze of gcc to find out where the exceptions related to divs get raised from, but maybe if someone could find that point then wintermute could add a patch with one weak symbol to raise the exception instead of doing it at the spot of the exception, so that it could be overridden cleanly with one function. Thats the nicest way i can think of to reconcile the two use cases.. but I dont know much about this kind of stuff.

tueidj
Posts: 40
Joined: Thu Dec 10, 2009 9:26 am

Re: Linker is adding extra crap (Unreferenced library code)

Post by tueidj » Tue Oct 04, 2011 9:08 am

I say leave it as is. If I want an exception when I divide by zero then I should get one. If someone else doesn't, they can write their own long division function.

Post Reply

Who is online

Users browsing this forum: Google [Bot] and 1 guest