File indexing completed on 2025-01-19 08:22:20
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 }