% cat a.s .globl _start, f0, f1 .weak f2 .protected f1 _start: f0: f1: f2: fl: bx lr .data .long f0(FUNCDESC) .long f1(FUNCDESC) .long f2(FUNCDESC) .long fl(FUNCDESC) % ./bin/as-new --fdpic a.s -o a.o && ./bin/ld-new -m armelf_linux_fdpiceabi a.o -pie -z noexecstack -o a % readelf --dyn-syms a Symbol table '.dynsym' contains 9 entries: Num: Value Size Type Bind Vis Ndx Name 0: 00000000 0 NOTYPE LOCAL DEFAULT UND 1: 000000f4 0 SECTION LOCAL DEFAULT 1 .interp 2: 00000204 0 SECTION LOCAL DEFAULT 6 .text 3: 00000208 0 SECTION LOCAL DEFAULT 7 .rofixup 4: 0000128c 0 SECTION LOCAL DEFAULT 9 .got 5: 000012a0 0 SECTION LOCAL DEFAULT 10 .data 6: 00000204 0 NOTYPE WEAK DEFAULT 6 f2 7: 00000204 0 NOTYPE GLOBAL DEFAULT 6 f0 8: 00000204 0 NOTYPE GLOBAL PROTECTED 6 f1 In a non-FDPIC link when f0/f1/f2 are referenced by absolute relocations, f0/f1/f2 are not exported (https://maskray.me/blog/2020-11-15-explain-gnu-linker-options#export-dynamic describes the symbol export rule).
bfd/elf32-arm.c:16521 if (eh->fdpic_cnts.funcdesc_cnt > 0) { if (htab->root.dynamic_sections_created && h->dynindx == -1 && !h->forced_local) if (! bfd_elf_link_record_dynamic_symbol (info, h)) return false; is too conservative. bfd_elf_link_record_dynamic_symbol records some symbols that do not need to be exported.