Hi, I am looking for any proper working documentation on thumb mode Optimisation on arm architecture
I tried few ways, but there is no size reduction in generated binary file
for certain cross-compiled bare metal architectures, there's different target triples for a32 and t32 codegens, such as armv4t/thumbv4t or armv5te/thumbv5te, but I don't think armv7-linux has a corresponding counter part.
There are a lot of functions in the project, this approach would make it difficult to apply on per function basis, is there any other method to build project for entire project
File: target/arm-unknown-linux-gnueabi/debug/libfoobar.rlib(foobar-7b0841136d790d74.11n7uttcboidvawvgdtli2idt.rcgu.o)
Symbol table '.symtab' contains 21 entries:
Num: Value Size Type Bind Vis Ndx Name
0: 00000000 0 NOTYPE LOCAL DEFAULT UND
1: 00000000 0 FILE LOCAL DEFAULT ABS 11n7uttcboidvawv[...]
2: 00000000 0 SECTION LOCAL DEFAULT 3 .text._ZN6foobar[...]
3: 00000000 0 NOTYPE LOCAL DEFAULT 3 $t
4: 00000028 0 NOTYPE LOCAL DEFAULT 3 $d
5: 00000000 16 OBJECT LOCAL DEFAULT 12 .L__unnamed_1
6: 00000000 0 SECTION LOCAL DEFAULT 7 .text._ZN6foobar[...]
7: 00000000 0 NOTYPE LOCAL DEFAULT 7 $a
8: 0000004c 0 NOTYPE LOCAL DEFAULT 7 $d
9: 00000000 16 OBJECT LOCAL DEFAULT 14 .L__unnamed_2
10: 00000000 0 SECTION LOCAL DEFAULT 11 .rodata..L__unnamed_3
11: 00000000 0 SECTION LOCAL DEFAULT 16 .debug_abbrev
12: 00000000 0 SECTION LOCAL DEFAULT 17 .debug_info
13: 00000000 0 SECTION LOCAL DEFAULT 21 .debug_ranges
14: 00000000 0 SECTION LOCAL DEFAULT 23 .debug_str
15: 00000000 0 SECTION LOCAL DEFAULT 27 .debug_frame
16: 00000000 0 SECTION LOCAL DEFAULT 29 .debug_line
17: 00000001 44 FUNC GLOBAL DEFAULT 3 _ZN6foobar3foo17[...]
18: 00000000 0 NOTYPE GLOBAL DEFAULT UND _ZN4core9panicki[...]
19: 00000000 0 NOTYPE GLOBAL DEFAULT UND __aeabi_unwind_c[...]
20: 00000000 80 FUNC GLOBAL DEFAULT 7 _ZN6foobar3bar17[...]
the thing to look at is the special symbol $t (#3 in this example) and/or the lsb of some symbols' address (note the value of #17 is 00000001 in this example).
if you see a lot of $t mappings and the function symbols have odd addresses, they you already have them compiled in thumb-mode.
some explanation:
per the arm elf spec, the special mapping symbol $a, $t, and $d point to arm-mode code, thumb-mode code, and data, respectively. these symbols are called "mapping symbols" if you want to lookup the terminology. (there are another kind of special symbols called "tagging symbols", but they are not present in this example)
for relocatable ELF files, the lsb of the address of a thumb-mode function is set to 1, or in other words, the address appears as an odd number, while arm-mode functions have even addresses. the linker uses this bit of information to do relocation calculation.
my example is a static library, the symbols are not resolved by the linker, so the values are all zero placeholders (apart from the lsb for thumb-mode functions)
I tried out with a sample app, where I have changed. .cargo/config with the target
armv7-unknown-linux-gnueabi
linker="arm-linux-gnueabi-gcc"
rustflags= [-C, target-feature=+thumb-mode]
After doing readelf on binary file
It gave a couple of $t symbols as you mentioned, apart from that, there were also $t.1, $t.2, ..... $t.n(n being some number)
Are these also thumb mode Optimised
One more query before and after this change, the size of binary file remained same, I checked with du -sh target/armv7-unknown-linux-gnueabi/debug/BINARY
Even with size <above_path >
Before it was
Text: 575882
Data: 12396
Bss: 172
Dec: 588450
After it was
Text: 485438
Data: 12396
Bss:172
Dec:498006
yes, these are all mapping symbols for thumb-mode code, see the ARM ELF spec for details.
you are checking a unstripped ELF file of a debug build, where most space of the file is taken up by debug information. changing code gen to thumb-mode only reduces the code size, which is insignificant in unstripped ELF file built in debug mode.
I would say a 15% code size reduction is not too bad, considering it is a debug build and no optimization is done.
if your end goal is to reduce the size of the executable file, changing to thumb-mode code gen can help, but it's not the most important step you should take. setting the proper optimization flags and stripping the debug information is much more important.
for example, try to add the following settings to your release profile and build in release mode, you'll see significant file size reduction.
if you are still unsatisfied with the "typical" opt-level of "s", you can try "z", which is supposed to reduce the size even more (in theory, at least).
if it's still "too large", you'll have to use some "unconventional" tricks to reduce the size even more (but in practice, these "extreme" steps should be completely unnecessary for most use cases). see:
if you stripped the binary, the symbols are definitely gone. but even if you didn't strip, I think the answer is still no, but I'm not sure. but again, I think whether a function is thumb-mode or not shouldn't matter very much. when it comes to optimization, always measure, never guess.
these mapping symbols are meant to be used by the linker and have local scope. so they should be present in the object files and/or library files, but have no use in the final executable file produced by the linker. if you want check them, you should look in the object files or libaries files, not the executable binary.
but the mapping symbols are not necessary anyway. if the symbols are not stripped, you can simply check the LSB of the address of functions. remember, symbols of thumb-mode functions have LSB set to "1", or, the address appears as odd numbers.
if the symbols are stripped, then I don't know how to check for thumb-mode easily. maybe try a disassembler?