Why is symbol name `memcmp` special to `zig build-lib` and how to make it not special?

I am using zig from zig-linux-x86_64-0.12.0-dev.1856+94c63f31f.tar.xz.

I create asd.zig file:

extern var lemcmp: isize;
export fn asd() callconv(.C) isize {
	return lemcmp;
}
I build libasd.so shared library:
$ zig build-lib -dynamic -O ReleaseFast asd.zig
I check libasd.so file size:
$ du --bytes libasd.so
7624    libasd.so
I edit asd.zig file:
extern var memcmp: isize;
export fn asd() callconv(.C) isize {
	return memcmp;
}
I build libasd.so shared library again:
$ zig build-lib -dynamic -O ReleaseFast asd.zig
I check libasd.so file size:
$ du --bytes libasd.so
854216  libasd.so
I get surprised that libasd.so became approximately 112 times bigger:
$ echo $((854216 / 7624))
112
2 Likes

Because lemcmp does not exist (unlike memcmp) and therefore was not included in the .so , thus making the .so smaller?

I will refer to old libasd.so (small) as lemcmp/libasd.so and new (big) libasd.so as memcmp/libasd.so.

Neither lemcmp/libasd.so or memcmp/libasd.so depend on libc.so.6 (there is no (NEEDED)):
$ readelf -d lemcmp/libasd.so
Dynamic section at offset 0x320 contains 13 entries:
  Tag        Type                         Name/Value
 0x000000000000000e (SONAME)             Library soname: [libasd.so]
 0x000000000000001e (FLAGS)              BIND_NOW
 0x000000006ffffffb (FLAGS_1)            Flags: NOW
 0x0000000000000007 (RELA)               0x2a0
 0x0000000000000008 (RELASZ)             24 (bytes)
 0x0000000000000009 (RELAENT)            24 (bytes)
 0x0000000000000006 (SYMTAB)             0x200
 0x000000000000000b (SYMENT)             24 (bytes)
 0x0000000000000005 (STRTAB)             0x288
 0x000000000000000a (STRSZ)              22 (bytes)
 0x000000006ffffef5 (GNU_HASH)           0x248
 0x0000000000000004 (HASH)               0x268
 0x0000000000000000 (NULL)               0x0
$ readelf -d memcmp/libasd.so
Dynamic section at offset 0x25c50 contains 17 entries:
  Tag        Type                         Name/Value
 0x000000000000000e (SONAME)             Library soname: [libasd.so]
 0x000000000000001e (FLAGS)              BIND_NOW
 0x000000006ffffffb (FLAGS_1)            Flags: NOW
 0x0000000000000007 (RELA)               0x5760
 0x0000000000000008 (RELASZ)             24 (bytes)
 0x0000000000000009 (RELAENT)            24 (bytes)
 0x0000000000000017 (JMPREL)             0x5778
 0x0000000000000002 (PLTRELSZ)           1488 (bytes)
 0x0000000000000003 (PLTGOT)             0x27d68
 0x0000000000000014 (PLTREL)             RELA
 0x0000000000000006 (SYMTAB)             0x238
 0x000000000000000b (SYMENT)             24 (bytes)
 0x0000000000000005 (STRTAB)             0x44b8
 0x000000000000000a (STRSZ)              4773 (bytes)
 0x000000006ffffef5 (GNU_HASH)           0x2ab8
 0x0000000000000004 (HASH)               0x3730
 0x0000000000000000 (NULL)               0x0
, so compiler doesn't know whether memcmp exists.
$ readelf -d /usr/lib/libbz2.so.1.0 (that does depend on libc.so.6)
Dynamic section at offset 0x11e40 contains 28 entries:
  Tag        Type                         Name/Value
 0x00000001 (NEEDED)                     Shared library: [libc.so.6]
 0x0000000e (SONAME)                     Library soname: [libbz2.so.1]
 0x0000000c (INIT)                       0x1000
 0x0000000d (FINI)                       0xee54
 0x00000019 (INIT_ARRAY)                 0x12df8
 0x0000001b (INIT_ARRAYSZ)               4 (bytes)
 0x0000001a (FINI_ARRAY)                 0x12dfc
 0x0000001c (FINI_ARRAYSZ)               4 (bytes)
 0x00000004 (HASH)                       0x1c0
 0x6ffffef5 (GNU_HASH)                   0x324
 0x00000005 (STRTAB)                     0x718
 0x00000006 (SYMTAB)                     0x3f8
 0x0000000a (STRSZ)                      723 (bytes)
 0x0000000b (SYMENT)                     16 (bytes)
 0x00000003 (PLTGOT)                     0x12f40
 0x00000002 (PLTRELSZ)                   256 (bytes)
 0x00000014 (PLTREL)                     REL
 0x00000017 (JMPREL)                     0xb90
 0x00000011 (REL)                        0xac0
 0x00000012 (RELSZ)                      208 (bytes)
 0x00000013 (RELENT)                     8 (bytes)
 0x0000001e (FLAGS)                      BIND_NOW
 0x6ffffffb (FLAGS_1)                    Flags: NOW
 0x6ffffffe (VERNEED)                    0xa50
 0x6fffffff (VERNEEDNUM)                 1
 0x6ffffff0 (VERSYM)                     0x9ec
 0x6ffffffa (RELCOUNT)                   19
 0x00000000 (NULL)                       0x0

Also when asd.zig is:
extern var strcmp: isize;
export fn asd() callconv(.C) isize {
	return strcmp;
}
$ zig build-lib -dynamic -O ReleaseFast asd.zig
$ du --bytes libasd.so
7624    libasd.so
libasd.so is not big (same file size as lemcmp/libasd.so)
2 Likes
Here are special symbols (from nm -D memcmp/libasd.so):
  • __absvdi2
  • __absvsi2
  • __absvti2
  • __adddf3
  • __addhf3
  • __addodi4
  • __addosi4
  • __addoti4
  • __addsf3
  • __addtf3
  • __addxf3
  • __ashldi3
  • __ashlsi3
  • __ashlti3
  • __ashrdi3
  • __ashrsi3
  • __ashrti3
  • __atomic_compare_exchange
  • __atomic_compare_exchange_1
  • __atomic_compare_exchange_16
  • __atomic_compare_exchange_2
  • __atomic_compare_exchange_4
  • __atomic_compare_exchange_8
  • __atomic_exchange
  • __atomic_exchange_1
  • __atomic_exchange_16
  • __atomic_exchange_2
  • __atomic_exchange_4
  • __atomic_exchange_8
  • __atomic_fetch_add_1
  • __atomic_fetch_add_16
  • __atomic_fetch_add_2
  • __atomic_fetch_add_4
  • __atomic_fetch_add_8
  • __atomic_fetch_and_1
  • __atomic_fetch_and_16
  • __atomic_fetch_and_2
  • __atomic_fetch_and_4
  • __atomic_fetch_and_8
  • __atomic_fetch_nand_1
  • __atomic_fetch_nand_16
  • __atomic_fetch_nand_2
  • __atomic_fetch_nand_4
  • __atomic_fetch_nand_8
  • __atomic_fetch_or_1
  • __atomic_fetch_or_16
  • __atomic_fetch_or_2
  • __atomic_fetch_or_4
  • __atomic_fetch_or_8
  • __atomic_fetch_sub_1
  • __atomic_fetch_sub_16
  • __atomic_fetch_sub_2
  • __atomic_fetch_sub_4
  • __atomic_fetch_sub_8
  • __atomic_fetch_umax_1
  • __atomic_fetch_umax_16
  • __atomic_fetch_umax_2
  • __atomic_fetch_umax_4
  • __atomic_fetch_umax_8
  • __atomic_fetch_umin_1
  • __atomic_fetch_umin_16
  • __atomic_fetch_umin_2
  • __atomic_fetch_umin_4
  • __atomic_fetch_umin_8
  • __atomic_fetch_xor_1
  • __atomic_fetch_xor_16
  • __atomic_fetch_xor_2
  • __atomic_fetch_xor_4
  • __atomic_fetch_xor_8
  • __atomic_load
  • __atomic_load_1
  • __atomic_load_16
  • __atomic_load_2
  • __atomic_load_4
  • __atomic_load_8
  • __atomic_store
  • __atomic_store_1
  • __atomic_store_16
  • __atomic_store_2
  • __atomic_store_4
  • __atomic_store_8
  • __bswapdi2
  • __bswapsi2
  • __bswapti2
  • __ceilh
  • __ceilx
  • __chk_fail
  • __clear_cache
  • __clzdi2
  • __clzsi2
  • __clzti2
  • __cmpdf2
  • __cmpdi2
  • __cmphf2
  • __cmpsf2
  • __cmpsi2
  • __cmptf2
  • __cmpti2
  • __cmpxf2
  • __cosh
  • __cosx
  • __ctzdi2
  • __ctzsi2
  • __ctzti2
  • __divdc3
  • __divdf3
  • __divdi3
  • __divhc3
  • __divhf3
  • __divmoddi4
  • __divmodsi4
  • __divmodti4
  • __divsc3
  • __divsf3
  • __divsi3
  • __divtc3
  • __divtf3
  • __divti3
  • __divxc3
  • __divxf3
  • __eqdf2
  • __eqhf2
  • __eqsf2
  • __eqtf2
  • __eqxf2
  • __exp2h
  • __exp2x
  • __exph
  • __expx
  • __extenddftf2
  • __extenddfxf2
  • __extendhfdf2
  • __extendhfsf2
  • __extendhftf2
  • __extendhfxf2
  • __extendsfdf2
  • __extendsftf2
  • __extendsfxf2
  • __extendxftf2
  • __fabsh
  • __fabsx
  • __ffsdi2
  • __ffssi2
  • __ffsti2
  • __fixdfdi
  • __fixdfsi
  • __fixdfti
  • __fixhfdi
  • __fixhfsi
  • __fixhfti
  • __fixsfdi
  • __fixsfsi
  • __fixsfti
  • __fixtfdi
  • __fixtfsi
  • __fixtfti
  • __fixunsdfdi
  • __fixunsdfsi
  • __fixunsdfti
  • __fixunshfdi
  • __fixunshfsi
  • __fixunshfti
  • __fixunssfdi
  • __fixunssfsi
  • __fixunssfti
  • __fixunstfdi
  • __fixunstfsi
  • __fixunstfti
  • __fixunsxfdi
  • __fixunsxfsi
  • __fixunsxfti
  • __fixxfdi
  • __fixxfsi
  • __fixxfti
  • __floatdidf
  • __floatdihf
  • __floatdisf
  • __floatditf
  • __floatdixf
  • __floatsidf
  • __floatsihf
  • __floatsisf
  • __floatsitf
  • __floatsixf
  • __floattidf
  • __floattihf
  • __floattisf
  • __floattitf
  • __floattixf
  • __floatundidf
  • __floatundihf
  • __floatundisf
  • __floatunditf
  • __floatundixf
  • __floatunsidf
  • __floatunsihf
  • __floatunsisf
  • __floatunsitf
  • __floatunsixf
  • __floatuntidf
  • __floatuntihf
  • __floatuntisf
  • __floatuntitf
  • __floatuntixf
  • __floorh
  • __floorx
  • __fmah
  • __fmax
  • __fmaxh
  • __fmaxx
  • __fminh
  • __fminx
  • __fmodh
  • __fmodx
  • __gedf2
  • __gehf2
  • __gesf2
  • __getf2
  • __gexf2
  • __gtdf2
  • __gthf2
  • __gtsf2
  • __gttf2
  • __gtxf2
  • __ledf2
  • __lehf2
  • __lesf2
  • __letf2
  • __lexf2
  • __log10h
  • __log10x
  • __log2h
  • __log2x
  • __logh
  • __logx
  • __lshrdi3
  • __lshrsi3
  • __lshrti3
  • __ltdf2
  • __lthf2
  • __ltsf2
  • __lttf2
  • __ltxf2
  • __memcpy_chk
  • __memmove_chk
  • __memset
  • __memset_chk
  • __moddi3
  • __modsi3
  • __modti3
  • __muldc3
  • __muldf3
  • __muldi3
  • __mulhc3
  • __mulhf3
  • __mulodi4
  • __mulosi4
  • __muloti4
  • __mulsc3
  • __mulsf3
  • __mulsi3
  • __multc3
  • __multf3
  • __multi3
  • __mulxc3
  • __mulxf3
  • __nedf2
  • __negdf2
  • __negdi2
  • __neghf2
  • __negsf2
  • __negsi2
  • __negtf2
  • __negti2
  • __negvdi2
  • __negvsi2
  • __negvti2
  • __negxf2
  • __nehf2
  • __nesf2
  • __netf2
  • __nexf2
  • __paritydi2
  • __paritysi2
  • __parityti2
  • __popcountdi2
  • __popcountsi2
  • __popcountti2
  • __powidf2
  • __powihf2
  • __powisf2
  • __powitf2
  • __powixf2
  • __roundh
  • __roundx
  • __sincosh
  • __sincosx
  • __sinh
  • __sinx
  • __sqrth
  • __sqrtx
  • __stack_chk_fail
  • __stack_chk_guard
  • __strcat_chk
  • __strcpy_chk
  • __strncat_chk
  • __strncpy_chk
  • __subdf3
  • __subhf3
  • __subodi4
  • __subosi4
  • __suboti4
  • __subsf3
  • __subtf3
  • __subxf3
  • __tanh
  • __tanx
  • __truncdfhf2
  • __truncdfsf2
  • __trunch
  • __truncsfhf2
  • __trunctfdf2
  • __trunctfhf2
  • __trunctfsf2
  • __trunctfxf2
  • __truncx
  • __truncxfdf2
  • __truncxfhf2
  • __truncxfsf2
  • __ucmpdi2
  • __ucmpsi2
  • __ucmpti2
  • __udivdi3
  • __udivei4
  • __udivmoddi4
  • __udivmodsi4
  • __udivmodti4
  • __udivsi3
  • __udivti3
  • __umoddi3
  • __umodei4
  • __umodsi3
  • __umodti3
  • __unorddf2
  • __unordhf2
  • __unordsf2
  • __unordtf2
  • __unordxf2
  • __zig_probe_stack
  • bcmp
  • ceil
  • ceilf
  • ceill
  • ceilq
  • cos
  • cosf
  • cosl
  • cosq
  • exp
  • exp2
  • exp2f
  • exp2l
  • exp2q
  • expf
  • expl
  • expq
  • fabs
  • fabsf
  • fabsl
  • fabsq
  • floor
  • floorf
  • floorl
  • floorq
  • fma
  • fmaf
  • fmal
  • fmaq
  • fmax
  • fmaxf
  • fmaxl
  • fmaxq
  • fmin
  • fminf
  • fminl
  • fminq
  • fmod
  • fmodf
  • fmodl
  • fmodq
  • log
  • log10
  • log10f
  • log10l
  • log10q
  • log2
  • log2f
  • log2l
  • log2q
  • logf
  • logl
  • logq
  • memcmp
  • memcpy
  • memmove
  • memset
  • round
  • roundf
  • roundl
  • roundq
  • sin
  • sincos
  • sincosf
  • sincosl
  • sincosq
  • sinf
  • sinl
  • sinq
  • sqrt
  • sqrtf
  • sqrtl
  • sqrtq
  • tan
  • tanf
  • tanl
  • tanq
  • trunc
  • truncf
  • truncl
  • truncq
You extern one of them, you get them all (in nm -D libasd.so)!
1 Like
zig-linux-x86_64-0.14.0-dev.2050+4adf63aef.tar.xz still has this problem and there are more special symbol names:
  • __bitreversedi2
  • __bitreversesi2
  • __bitreverseti2
  • __gnu_f2h_ieee
  • __gnu_h2f_ieee
1 Like

no answers here, so I made github issue: some symbol names cause bloat · Issue #21848 · ziglang/zig · GitHub

Vexu's comment on github issue:

__bitreversedi2 is a compiler-rt symbol so using it causes compiler-rt to be statically linked into the library. You can prevent that with -fno-compiler-rt but doing so might cause other problems.