View unanswered posts | View active topics It is currently Tue Nov 21, 2017 2:56 pm



Reply to topic  [ 16 posts ]  Go to page 1, 2  Next
 Linker is adding extra crap (Unreferenced library code) 
Author Message

Joined: Sun Jan 06, 2008 4:06 am
Posts: 40
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:
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?


Fri Sep 30, 2011 8:33 am
Profile
Site Admin

Joined: Tue Aug 09, 2005 3:21 am
Posts: 1209
Location: UK
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

devkitPro IRC support
Personal Blog


Sat Oct 01, 2011 1:22 pm
Profile ICQ WWW

Joined: Sun Jan 06, 2008 4:06 am
Posts: 40
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.


Sat Oct 01, 2011 10:14 pm
Profile
User avatar

Joined: Fri Jul 11, 2008 8:49 pm
Posts: 222
Location: The Netherlands
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 (viewtopic.php?f=14&t=1665), you can remove unused code with "-Wl,--gc-sections":

Quote:
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.

_________________
my blog:
http://vuurrobin.100webcustomers.com/


Sun Oct 02, 2011 12:39 am
Profile WWW

Joined: Sun Jan 06, 2008 4:06 am
Posts: 40
I have now tried that, but it didn't work.

My makefile line now looks like
LDFLAGS = -g $(ARCH) -Wl,-Map,$(notdir [email protected]).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:

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:
_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.


Sun Oct 02, 2011 2:08 am
Profile
Site Admin

Joined: Tue Aug 09, 2005 3:21 am
Posts: 1209
Location: UK
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

devkitPro IRC support
Personal Blog


Mon Oct 03, 2011 2:35 pm
Profile ICQ WWW

Joined: Thu Dec 10, 2009 9:26 am
Posts: 40
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.


Mon Oct 03, 2011 6:40 pm
Profile

Joined: Sun Jan 06, 2008 4:06 am
Posts: 40
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?


Tue Oct 04, 2011 2:04 am
Profile

Joined: Wed Mar 31, 2010 6:05 pm
Posts: 212
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.


Tue Oct 04, 2011 5:22 am
Profile

Joined: Thu Dec 10, 2009 9:26 am
Posts: 40
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.


Tue Oct 04, 2011 9:08 am
Profile
Display posts from previous:  Sort by  
Reply to topic   [ 16 posts ]  Go to page 1, 2  Next

Who is online

Users browsing this forum: No registered users and 1 guest


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
  Powered by phpBB® Forum Software © phpBB Group
Designed by ST Software.
Get devkitPro at SourceForge.net. Fast, secure and Free Open Source software downloads