Open honggyukim opened 5 years ago
typedef struct {
Elf32_Sword d_tag;
union {
Elf32_Word d_val;
Elf32_Addr d_ptr;
Elf32_Off d_off;
} d_un;
} Elf32_Dyn;
DT_PLTGOT (d_tag
)
d_ptr
field of this entry gives the address of the first byte in the Procedure Linkage Table (.PLT in the Section called Procedure Linkage Table).DT_JMPREL (d_tag
)
DT_JMPREL
relocation entries is wholly contained within the DT_RELA
referenced table. See the Section called Procedure Linkage Table for more information.http://refspecs.linuxfoundation.org/ELF/zSeries/lzsabi0_zSeries/x2251.html
The symbol refers to the start of the .got section. Two words in the GOT are reserved:
The word at _GLOBAL_OFFSET_TABLE_
[0] is set by the linkage editor to hold the address of the dynamic structure, referenced with the symbol _DYNAMIC
. This allows a program, such as the dynamic linker, to find its own dynamic structure without having yet processed its relocation entries. This is especially important for the dynamic linker, because it must initialize itself without relying on other programs to relocate its memory image.
The word at _GLOBAL_OFFSET_TABLE_
[1] is reserved for future use.
The Global Offset Table resides in the ELF .got section.
https://docs.oracle.com/cd/E19683-01/817-3677/chapter6-42444/index.html
Dynamic Section
If an object file participates in dynamic linking, its program header table will have an element of type PT_DYNAMIC
. This segment contains the .dynamic section. A special symbol, _DYNAMIC
, labels the section, which contains an array of the following structures, defined in sys/link.h:
typedef struct {
Elf32_Sword d_tag;
union {
Elf32_Word d_val;
Elf32_Addr d_ptr;
Elf32_Off d_off;
} d_un;
} Elf32_Dyn;
typedef struct {
Elf64_Xword d_tag;
union {
Elf64_Xword d_val;
Elf64_Addr d_ptr;
} d_un;
} Elf64_Dyn;
For each object with this type, d_tag controls the interpretation of d_un.
d_val
d_ptr
commit 3d4ea6b523df63b58cfb02b9756b692e3663744c Author: Namhyung Kim namhyung@gmail.com AuthorDate: Mon Jan 27 11:11:50 2014 +0900 Commit: Namhyung Kim namhyung@gmail.com CommitDate: Mon Jan 27 11:11:50 2014 +0900
plthook: Trace dynamic (PLT) symbols too
Second entry of the _GLOBAL_OFFSET_TABLE_ is an address of dynamic
symbol resolver in the dynamic linker. Hijack the address to record
mcount information using dynamic symbol table.
To trace every invocation of such functions, it needs to set
LD_BIND_NOT environment variable.
commit 2f2baf2a33971868b74a608d24aded7787efd729 Author: Namhyung Kim namhyung@gmail.com AuthorDate: Tue Feb 18 10:08:22 2014 +0900 Commit: Namhyung Kim namhyung@gmail.com CommitDate: Tue Feb 18 10:17:42 2014 +0900
Access _GLOBAL_OFFSET_TABLE_ through DT_PLTGOT info
Accessing through the .got or .got.plt section can be ambiguous.
commit cae6af79bfb8364d8b802f09d816f78b79dd1943 Author: Namhyung Kim namhyung@gmail.com AuthorDate: Tue Feb 18 21:36:36 2014 +0900 Commit: Namhyung Kim namhyung@gmail.com CommitDate: Wed Feb 19 09:26:49 2014 +0900
Use mprotect() before updating GOT
On some systems (like Ubuntu 10.04) the GOT was protected from
overwriting so that it needs to be mprotected first.
Install SIGSEGV handler to catch such case and do mprotect() and then
restore original protection bits. Note that other systems
(eg. Fedora) needs writable GOT for handle .fini section so we cannot
restore it to read-only blindly.
commit 30cf4178f7bce28fc90f649162ae83d093810028 Author: Namhyung Kim namhyung@gmail.com AuthorDate: Tue Mar 11 13:31:42 2014 +0900 Commit: Namhyung Kim namhyung@gmail.com CommitDate: Tue Mar 11 15:22:14 2014 +0900
Prevent recursion on plthook
There was a recursion like below on some workload:
plthook_entry
-> mcount_entry
-> mcount_prepare
-> xmalloc
-> plthook_entry
Add a per-thread recursion guard variable to protect it.
Note that the __libc_start_main() needs to be skipped since
it's a dynamic symbol that never returns.
mcount_startup
mcount_setup_plthook
setup_{exe|mod}_plthook_data(struct dl_phdr_info *info, ...) -> offset = info->dlpi_addr;
hook_pltgot
find_got(..., offset)
overwrite_pltgot(..., plt_hooker)
plt_hooker
plthook_entry
The info
argument is a structure of the following type:
struct dl_phdr_info {
ElfW(Addr) dlpi_addr; /* Base address of object */
const char *dlpi_name; /* (Null-terminated) name of
object */
const ElfW(Phdr) *dlpi_phdr; /* Pointer to array of
ELF program headers
for this object */
ElfW(Half) dlpi_phnum; /* # of items in dlpi_phdr */
};
(The ElfW() macro definition turns its argument into the name of an ELF data type suitable for the hardware architecture. For example, on a 32-bit platform, ElfW(Addr) yields the data type name Elf32_Addr. Further information on these types can be found in the
The dlpi_addr
field indicates the base address of the shared object (i.e., the difference between the virtual memory address of the shared object and the offset of that object in the file from which it was loaded). The dlpi_name field is a null-terminated string giving the pathname from which the shared object was loaded.
#define SKIP_SYM(func) { #func, &uftrace_ ## func }
const struct plthook_skip_symbol plt_skip_syms[] = {
SKIP_SYM(mcount),
SKIP_SYM(_mcount),
SKIP_SYM(__fentry__),
SKIP_SYM(__gnu_mcount_nc),
SKIP_SYM(__cyg_profile_func_enter),
SKIP_SYM(__cyg_profile_func_exit),
};
size_t plt_skip_nr = ARRAY_SIZE(plt_skip_syms);
#undef SKIP_SYM
#undef ALIAS_DECL
/*
* The `mcount` (and its friends) are part of uftrace itself,
* so no need to use PLT hook for them.
*/
static void restore_plt_functions(struct plthook_data *pd)
{
unsigned i, k;
struct symtab *dsymtab = &pd->dsymtab;
for (i = 0; i < dsymtab->nr_sym; i++) {
bool skipped = false;
unsigned long plthook_addr;
unsigned long resolved_addr;
struct sym *sym = dsymtab->sym_names[i];
for (k = 0; k < plt_skip_nr; k++) {
const struct plthook_skip_symbol *skip_sym;
skip_sym = &plt_skip_syms[k];
if (strcmp(sym->name, skip_sym->name))
continue;
overwrite_pltgot(pd, 3 + i, skip_sym->addr);
pr_dbg2("overwrite [%u] %s: %p\n",
i, skip_sym->name, skip_sym->addr);
skipped = true;
break;
}
if (skipped)
continue;
resolved_addr = pd->pltgot_ptr[3 + i];
plthook_addr = mcount_arch_plthook_addr(pd, i);
if (resolved_addr != plthook_addr) {
/* save already resolved address and hook it */
pd->resolved_addr[i] = resolved_addr;
overwrite_pltgot(pd, 3 + i, (void *)plthook_addr);
pr_dbg2("restore [%u] %s: %p (PLT: %#lx)\n",
i, sym->name, resolved_addr, plthook_addr);
}
}
}
$ nm libmcount/libmcount.so | grep mcount
0000000000025310 T mcount
...
w uftrace___gnu_mcount_nc
0000000000025310 t uftrace_mcount
w uftrace__mcount
$ nm libmcount/libmcount.so | grep cyg
000000000000a030 T __cyg_profile_func_enter
000000000000a230 T __cyg_profile_func_exit
000000000000a030 t uftrace___cyg_profile_func_enter
000000000000a230 t uftrace___cyg_profile_func_exit
The above weak references are used as follows:
/* use weak reference for non-defined (arch-dependent) symbols */
#define ALIAS_DECL(_sym) extern __weak void (*uftrace_##_sym)(void);
ALIAS_DECL(mcount);
ALIAS_DECL(_mcount);
ALIAS_DECL(__fentry__);
ALIAS_DECL(__gnu_mcount_nc);
ALIAS_DECL(__cyg_profile_func_enter);
ALIAS_DECL(__cyg_profile_func_exit);
#define SKIP_SYM(func) { #func, &uftrace_ ## func }
const struct plthook_skip_symbol plt_skip_syms[] = {
SKIP_SYM(mcount),
SKIP_SYM(_mcount),
SKIP_SYM(__fentry__),
SKIP_SYM(__gnu_mcount_nc),
SKIP_SYM(__cyg_profile_func_enter),
SKIP_SYM(__cyg_profile_func_exit),
};
size_t plt_skip_nr = ARRAY_SIZE(plt_skip_syms);
#undef SKIP_SYM
#undef ALIAS_DECL
10│ ENTRY(plt_hooker)
11│ @ we get called with
12│ @ stack[0] contains the return address from this call
13│ @ ip contains &GOT[n+3] (pointer to function)
14│ @ lr points to &GOT[2]
15│
16├───────> push {r0-r3,ip,lr,pc}
17│ add r0, sp, #28
18│ sub r2, ip, lr
19│ sub r2, r2, #4
20│ lsr r1, r2, #2
21│ ldr r2, [lr, #-4]
22│ mov r3, sp
23│ bl plthook_entry
24│
25│ cmp r0, $0
26│ beq 1f
27│
28│ /*
29│ * if we skip the resolver, we also need to pop stack[0]
30│ * which saves the original 'lr'.
31│ */
32│ str r0, [sp, #24]
33│ pop {r0-r3,ip,lr}
34│ add sp, sp, #8
35│ ldr lr, [sp, #-4]
36│ ldr pc, [sp, #-8] /* return */
37│
38│ 1:
39│ ldr r2, .L2
40│ .LPIC0:
41│ add r2, pc, r2
42│ ldr r3, .L2+4
43│ ldr r1, [r2, r3]
44│ ldr r2, [r1]
45│ str r2, [sp, #24]
46│ pop {r0-r3,ip,lr,pc}
47│
48│ .L3:
49│ .align 2
50│ .L2:
51│ .word _GLOBAL_OFFSET_TABLE_-(.LPIC0+8)
52│ .word plthook_resolver_addr(GOT)
53│ END(plt_hooker)
/usr/src/debug/uftrace/0.9.2-r0/git/arch/arm/plthook.S
(gdb) disassemble
Dump of assembler code for function plt_hooker:
=> 0x76fc1368 <+0>: push {r0, r1, r2, r3, r12, lr, pc}
0x76fc136c <+4>: add r0, sp, #28
0x76fc1370 <+8>: sub r2, r12, lr
0x76fc1374 <+12>: sub r2, r2, #4
0x76fc1378 <+16>: lsr r1, r2, #2
0x76fc137c <+20>: ldr r2, [lr, #-4]
0x76fc1380 <+24>: mov r3, sp
0x76fc1384 <+28>: blx 0x76fb3f04 <plthook_entry>
0x76fc1388 <+32>: cmp r0, #0
0x76fc138c <+36>: beq 0x76fc13a4 <plt_hooker+60>
0x76fc1390 <+40>: str r0, [sp, #24]
0x76fc1394 <+44>: pop {r0, r1, r2, r3, r12, lr}
0x76fc1398 <+48>: add sp, sp, #8
0x76fc139c <+52>: ldr lr, [sp, #-4]
0x76fc13a0 <+56>: ldr pc, [sp, #-8]
0x76fc13a4 <+60>: ldr r2, [pc, #20] ; 0x76fc13c0 <plt_hooker+88>
0x76fc13a8 <+64>: add r2, pc, r2
0x76fc13ac <+68>: ldr r3, [pc, #16] ; 0x76fc13c4 <plt_hooker+92>
0x76fc13b0 <+72>: ldr r1, [r2, r3]
0x76fc13b4 <+76>: ldr r2, [r1]
0x76fc13b8 <+80>: str r2, [sp, #24]
0x76fc13bc <+84>: pop {r0, r1, r2, r3, r12, lr, pc}
0x76fc13c0 <+88>: andeq r11, r0, r4, asr #31
0x76fc13c4 <+92>: ; <UNDEFINED> instruction: 0xffffffe0
End of assembler dump.
(gdb) x/x 0x76fc13c0
0x76fc13c0 <plt_hooker+88>: 0x0000bfc4
(gdb) x/x 0x76fc13c4
0x76fc13c4 <plt_hooker+92>: 0xffffffe0
About RELRO
plthook: opening executable image: /usr/lib/libxxx.so
plthook: "libxxx.so" is loaded at 0x729aa000 (id: 0, PLTGOT: 0x76d96000)
plthook: update module id to 0x5524d1c0
plthook: found GOT at 0x76d96000 (file_addr: 0x43ec000, PLT resolver: 0)
plthook: restore GOT[3] to (nil) (__gmon_start__) (PLT: 0x72d26e7c)
plthook: restore GOT[4] to 0x72878c24 (__cxa_finalize) (PLT: 0x72d26e7c)
Disassembly of section .dynamic:
043bcd20 <.dynamic>:
43bcd20: 00000003 andeq r0, r0, r3
43bcd24: 043ec000 ldrteq ip, [lr], #-0 # <= same as PLTGOT and file_addr
43bcd28: 00000002 andeq r0, r0, r2
43bcd2c: 00003fe8 andeq r3, r0, r8, ror #31
43bcd30: 00000017 andeq r0, r0, r7, lsl r0
...
Program Headers:
Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
PHDR 0x000034 0x00000034 0x00000034 0x00160 0x00160 R 0x4
LOAD 0x000000 0x00000000 0x00000000 0x41c9110 0x41c9110 R E 0x1000
LOAD 0x41c9690 0x041ca690 0x041ca690 0x243198 0x410964 RW 0x1000
DYNAMIC 0x43bbd20 0x043bcd20 0x043bcd20 0x001d8 0x001d8 RW 0x4
NOTE 0x000194 0x00000194 0x00000194 0x00024 0x00024 R 0x4
NOTE 0x440c808 0x0440d808 0x0440d808 0x00020 0x00020 RW 0x4
GNU_EH_FRAME 0x41c90fc 0x041c90fc 0x041c90fc 0x00014 0x00014 R 0x4
GNU_STACK 0x000000 0x00000000 0x00000000 0x00000 0x00000 RW 0x10
EXIDX 0x387f670 0x0387f670 0x0387f670 0x19b830 0x19b830 R 0x4
TLS 0x41c9690 0x041ca690 0x041ca690 0x00010 0x00018 R 0x8
GNU_RELRO 0x41c9690 0x041ca690 0x041ca690 0x223970 0x223970 RW 0x8
...
Dynamic section at offset 0x43bbd20 contains 54 entries:
Tag Type Name/Value
0x00000003 (PLTGOT) 0x43ec000
0x00000002 (PLTRELSZ) 16360 (bytes)
0x00000017 (JMPREL) 0x378e88
0x00000014 (PLTREL) REL
0x00000011 (REL) 0x49e50
0x00000012 (RELSZ) 3338296 (bytes)
0x00000013 (RELENT) 8 (bytes)
0x6ffffffa (RELCOUNT) 409350
0x00000006 (SYMTAB) 0x1b8
0x0000000b (SYMENT) 16 (bytes)
0x00000005 (STRTAB) 0xccd8
0x0000000a (STRSZ) 221394 (bytes)
0x00000004 (HASH) 0x42dac
Relocation section '.rel.dyn' at offset 0x49e50 ...
Offset Info Type Sym.Value Sym. Name
...
043bd080 00007c15 R_ARM_GLOB_DAT 00000000 pthread_once@GLIBC_2.4
...
043ec170 00007c16 R_ARM_JUMP_SLOT 00000000 pthread_once@GLIBC_2.4
...
Symbol table '.dynsym' ...
...
124: 00000000 0 FUNC GLOBAL DEFAULT UND pthread_once@GLIBC_2.4 (28)
commit ef7137ff86848e346fe60f9d7be7e1e1f090733a Author: Namhyung Kim namhyung@gmail.com AuthorDate: Wed Aug 30 22:58:15 2017 +0900 Commit: Namhyung Kim namhyung@gmail.com CommitDate: Tue Sep 5 10:23:43 2017 +0900
plthook: Introduce struct plthook_data
This is a preparation to support nested PLT hooking which trace
inter-library calls as well. So each modules' PLT info should be
managed separately using the plthook_data.
Each data is identified by module_id and kept in plthook_modules list.
ommit bd4a1a771f0c158720c1c1edb5d9bc3c6ca39665 Author: Namhyung Kim namhyung@gmail.com AuthorDate: Sun Sep 3 13:05:47 2017 +0900 Commit: Namhyung Kim namhyung@gmail.com CommitDate: Tue Sep 5 10:25:27 2017 +0900
plthook: Restore already resolved PLT entries
It might be possible for dynamic linker to resolve some symbols before
uftrace hooks up the PLTGOT. As we know the original PLT hook address,
restore already resolved address so that we can see them in the output.
commit 4d394157ec87956f090999c14201d398be775ad3 Author: Namhyung Kim namhyung@gmail.com AuthorDate: Thu Sep 7 19:05:25 2017 +0900 Commit: Namhyung Kim namhyung@gmail.com CommitDate: Thu Sep 7 21:24:52 2017 +0900
plthook: Save and use PLT0 address on ARM
In order to handle PLT hooking properly, it needs to know PLT0 address.
But it's not deterministic so that we cannot calculate the address using
the first symbol address. So save it in the pd, and use it.
Signed-off-by: Namhyung Kim <namhyung@gmail.com>
diff --git a/arch/arm/mcount-support.c b/arch/arm/mcount-support.c
--- a/arch/arm/mcount-support.c
+++ b/arch/arm/mcount-support.c
@@ -604,7 +604,4 @@
unsigned long mcount_arch_plthook_addr(struct plthook_data *pd, int idx)
{
- struct sym *sym;
-
- sym = &pd->dsymtab.sym[0];
- return sym->addr - ARCH_PLT0_SIZE;
+ return pd->plt_addr;
}
commit bd4a1a771f0c158720c1c1edb5d9bc3c6ca39665 Author: Namhyung Kim namhyung@gmail.com AuthorDate: Sun Sep 3 13:05:47 2017 +0900 Commit: Namhyung Kim namhyung@gmail.com CommitDate: Tue Sep 5 10:25:27 2017 +0900
plthook: Restore already resolved PLT entries
It might be possible for dynamic linker to resolve some symbols before
uftrace hooks up the PLTGOT. As we know the original PLT hook address,
restore already resolved address so that we can see them in the output.
Signed-off-by: Namhyung Kim <namhyung@gmail.com>
diff --git a/libmcount/plthook.c b/libmcount/plthook.c
--- a/libmcount/plthook.c
+++ b/libmcount/plthook.c
@@ -121,1 +132,9 @@
+ resolved_addr = pd->pltgot_ptr[3 + i];
+ plthook_addr = mcount_arch_plthook_addr(pd, i);
+ if (resolved_addr != plthook_addr) {
+ /* save already resolved address and hook it */
+ pd->resolved_addr[i] = resolved_addr;
+ overwrite_pltgot(pd, 3 + i, (void *)plthook_addr);
+ pr_dbg2("restore [%u] %s: %p\n",
+ i, dsymtab->sym[i].name, resolved_addr);
}
commit 3f20adf8c5fc0744edb0b4f60169d1ee67e9b7fd Author: Namhyung Kim namhyung@gmail.com AuthorDate: Mon Apr 30 14:51:01 2018 +0900 Commit: Namhyung Kim namhyung@gmail.com CommitDate: Mon Apr 30 15:27:17 2018 +0900
plthook: Fix infinite loop in execl() on ARM
In restore_plt_functions(), it tries to get address of some special
functions (which cannot return normally for some reason). It uses
dlsym(RTLD_DEFAULT) but on ARM the function returns an address of PLT
routine so the process will be stuck in an infinite loop.
Introduction to the ELF Format (Part VII): Dynamic Linking / Loading and the .dynamic section
commit b7230be418f3185c6b2b65d65c0719d03b4ceb75 Author: Namhyung Kim namhyung@gmail.com AuthorDate: Mon Oct 15 11:32:46 2018 +0900 Commit: Namhyung Kim namhyung@gmail.com CommitDate: Thu Oct 18 14:16:16 2018 +0900
plthook: Do not call dlsym() in the init routine
It resulted in a crash on some systems. It looks like a bug in glibc
but we need to work around it somehow.
Reported-by: Honggyu Kim <honggyu.kp@gmail.com>
Signed-off-by: Namhyung Kim <namhyung@gmail.com>
diff --git a/libmcount/plthook.c b/libmcount/plthook.c
--- a/libmcount/plthook.c
+++ b/libmcount/plthook.c
@@ -55,13 +55,22 @@
static void resolve_pltgot(struct plthook_data *pd, int idx)
{
if (pd->resolved_addr[idx] == 0) {
- char *name;
- void *addr;
+ unsigned long addr;
+ struct sym *sym;
+
+ sym = &pd->dsymtab.sym[idx];
+ addr = (unsigned long) dlsym(RTLD_DEFAULT, sym->name);
+
+ /* On ARM dlsym(DEFAULT) returns the address of PLT */
+ if (unlikely(pd->base_addr <= addr &&
+ addr < sym->addr + sym->size)) {
+ void *real_addr = dlsym(RTLD_NEXT, sym->name);
- name = pd->dsymtab.sym[idx].name;
- addr = dlsym(RTLD_DEFAULT, name);
+ if (real_addr)
+ addr = (unsigned long)real_addr;
+ }
- pr_dbg2("resolved addr of %s = %p\n", name, addr);
- pd->resolved_addr[idx] = (unsigned long)addr;
+ pr_dbg2("resolved addr of %s = %p\n", sym->name, addr);
+ pd->resolved_addr[idx] = addr;
}
}
commit 8503de419ab1b0e5295d5d5c1737b42ecfa6ddb5 Author: Namhyung Kim namhyung@gmail.com AuthorDate: Wed Nov 15 13:41:10 2017 +0900 Commit: Namhyung Kim namhyung@gmail.com CommitDate: Mon Nov 27 09:45:01 2017 +0900
plthook: Resolve address of pthread_exit()
The PLT hooking relies on exit path to restore original PLT address so
that it still can be called through PLT after dynamic resolver updates
the address. But as pthread_exit() never returns, there's no change to
hook it up again.
Add PLT_FL_RESOLVE to do it at entry time explicitly.
Signed-off-by: Namhyung Kim <namhyung@gmail.com>
diff --git a/libmcount/plthook.c b/libmcount/plthook.c
--- a/libmcount/plthook.c
+++ b/libmcount/plthook.c
@@ -76,0 +76,13 @@
+static void resolve_pltgot(struct plthook_data *pd, int idx)
+{
+ if (pd->resolved_addr[idx] == 0) {
+ char *name;
+ void *addr;
+
+ name = pd->dsymtab.sym[idx].name;
+ addr = dlsym(RTLD_DEFAULT, name);
+
+ pr_dbg2("resolved addr of %s = %p\n", name, addr);
+ pd->resolved_addr[idx] = (unsigned long)addr;
+ }
+}
3d4ea6b plthook: Trace dynamic (PLT) symbols too 04e7dd2 Implement plthook on ARM fc664ce fixup for ARM plthook 2f2baf2 Access _GLOBAL_OFFSETTABLE through DT_PLTGOT info cae6af7 Use mprotect() before updating GOT d532a65 Find dynamic symbols to skip on __monstartup() 30cf417 Prevent recursion on plthook 16a31e2 Add support for library symbols c3c8f72 Save resolved addresses of dynamic symbols 1437299 Speed up PLT hooking on x86_64 d8c6a4f Speed up PLT hooking on ARM 53b370f Handle fork() call in child
fee3062 mcount: Create libmcount directory 37d8201 mcount: Build dynsym idxlist for setjmp/longjmp 9635a1a mcount: Add basic support for setjmp/longjmp b13df20 filter: Add '@plt' filter for PLT functions f6fe591 mcount: Fix PLT record after filtering 124653d mcount: Protect resolved PLT addresses using mutex 244ce79 mcount: Fix PLT recursion with filter * c5c2f79 mcount: Protect recursion from malloc() 80319b9 mcount: Ignore mcount() after it finished 9bf99b3 mcount: Flush rstack on special functions 8479be5 mcount: Pass mcount_regs to plthook_entry also
1a54771 mcount: Split PLT-hooking code into separate file 76899f8 mcount: Introduce struct mcount_thread_data 450becc mcount: Move plthook related data to mcount_thread_data 7e7ac2e mcount: Use map load address to adjust symbol offset 9b57d31 mcount: Pass offset to the PLT hook function 5b79331 mcount: Skip PLT hooking when no PLT reloc entries found b7fdfbc mcount: Fix return value of PLT functions 3912dfa mcount: Cleanup the plthook_exit() * 78db558 mcount: Prevent recursive call in mtd_dtor() * 8eb2330 mcount: Fix recursion during fork() 87a0ee7 mcount: Hook dlopen() to trace functions in the dynamic library * 6e3f577 mcount: Move raw access of mtd under unlikely 582ad22 mcount: Move recursion check out of mcount_should_stop() * 3814d4f mcount: Check recursion in mcount_prepare() eb47108 mcount: Use binary search for special PLT functions ** 9479ec2 mcount: Separate PLTGOT overwrite * 3ec95cf mcount: Do not hook PLT of mcount() * 66ac84a mcount: Fix a bug when longjmp() called twice 263ba58 mcount: Hook dlopen() early * ad5869b mcount: Return saved address from plthook_entry() ** 3e0c35b mcount: Introduce setup_pltgot() * 9392847 mcount: Basic support for bind-now binaries
mcount: Introduce mcount_arch_plthook_addr() * 5f2e7d6 mcount: Introduce mcount_arch_plthook_addr() * 6ef9641 mcount: Eliminate plthook_guard ffbfd59 mcount: Don't restore parent ip in rstacks on longjmp() * 2b2403e symbol: Fix SYMTAB_FL_ADJ_OFFSET usage in plthook 7f94a7e plthook: Skip binary has no PLTGOT address ** ef7137f plthook: Introduce struct plthook_data ** 14c9ac3 plthook: Setup module id for BIND-NOW binaries 50f43df plthook: Pass 'pd' to mcount_arch_plthook_addr()
** 3594de2 plthook: Support nested libcall tracing f1f0b28 plthook: Handle special dynsym index per pd * bd4a1a7 plthook: Restore already resolved PLT entries * 4d39415 plthook: Save and use PLT0 address on ARM 1d10f0c plthook: Set resolver address only once
8d90229 symbol: Load and save all module symbols fc41d32 plthook: Make x86's mcount_arch_plthook_addr() as default ** 8503de4 plthook: Resolve address of pthread_exit() 5c8c4ee plthook: Handle recursion in plthook_entry() c6fde0e plthook: Handle corrupted rstack after vfork() 2cb0901 plthook: Check PT_GNU_RELRO 5604ae5 plthook: Pre-resolve address of special functions 3f20adf plthook: Fix infinite loop in execl() on ARM b7230be plthook: Do not call dlsym() in the init routine 0c18764 plthook: Allow architecture to hook no-PLT libcall 5d81130 plthook: Remove mcount_arch_undo_bindnow() * 961518c Revert "Handle mcount/plthook_return() return 0" * 0ba73d0 mcount: Add ARCH_CAN_RESTORE_PLTHOOK logic