File indexing completed on 2024-04-14 05:34:45

0001 /*
0002     SPDX-FileCopyrightText: 2018 Ivan Middleton <TODO>
0003     SPDX-FileCopyrightText: 2018 Milian Wolff <mail@milianw.de>
0004 
0005     SPDX-License-Identifier: LGPL-2.1-or-later
0006 */
0007 
0008 /*
0009     By default, the linker uses lazy binding (function calls aren't
0010     resolved until the first time the function is called).
0011 
0012     Relevant sections of the executable for lazy binding:
0013     .plt      (trampoline code)
0014     .got.plt  (function addresses cached here)
0015     .rela.plt (relocation entries associating each function name
0016                 with its storage location in .got.plt)
0017 
0018     But symbols can also be bound right away when the executable or
0019     shared library is started or loaded.
0020 
0021     Relevant sections for immediate binding:
0022     .plt.got  (trampoline code)
0023     .got      (function addresses stored here)
0024     .rela.dyn (relocation entries)
0025 
0026     Immediate binding can be triggered in a couple different ways:
0027 
0028     (1) The linker option "-z now" makes all symbols use immediate
0029         binding. Compile this file as follows to see this in action:
0030 
0031             gcc -Wl,-z,now -o testbind testbind.c
0032 
0033         Why might this linker option be used? See:
0034 
0035     https://wiki.debian.org/Hardening#DEB_BUILD_HARDENING_BINDNOW_.28ld_-z_now.29
0036 
0037         Note that this seems to be platform dependant and is not always reproducible.
0038 
0039     (2) If a particular function has a pointer to it passed around,
0040         then it must be bound immediately. Define TAKE_ADDR, i.e. compile with
0041 
0042             gcc -g -O0 -fuse-ld=bfd -DTAKE_ADDR -o testbind testbind.c
0043 
0044         to see this behavior. Note that ld.gold does not show this behavior.
0045 
0046     The heaptrack_inject function needs to look in both .rela.plt
0047     (DT_JMPREL) and .rela.dyn (DT_RELA) in order to find all
0048     malloc/free function pointers, lazily-bound or no.
0049 
0050     There is also another option which is currently not handled by heaptrack:
0051     When do not rewrite data segments, which would be required to catch accessing
0052     a given symbol through a function pointer (-DUSE_FREEPTR).
0053 
0054     Use the run_linkage_tests.sh bash script to check the behavior in an automated fashion.
0055 */
0056 
0057 #include <stdlib.h>
0058 #include <unistd.h>
0059 
0060 #include <benchutil.h>
0061 
0062 int main()
0063 {
0064     // NOTE: if we'd read the free ptr here, then we would not catch/override the value by heaptrack
0065     int i = 0;
0066 
0067     sleep(1);
0068 
0069     for (i = 0; i < 10; ++i) {
0070         void* foo = malloc(256);
0071         escape(foo);
0072 
0073 #if defined(TAKE_ADDR) || defined(USE_FREEPTR)
0074     // but when we read it here, heaptrack may have rewritten the value properly
0075     void (*freePtr)(void*) = &free;
0076 
0077     escape(freePtr);
0078 #endif
0079 
0080         usleep(200);
0081 #if defined(USE_FREEPTR)
0082         freePtr(foo);
0083 #else
0084         free(foo);
0085 #endif
0086         usleep(200);
0087     }
0088     return 0;
0089 }