-
Notifications
You must be signed in to change notification settings - Fork 479
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
-fno-plt
disturbs tracing the libc call and default Rust build flag use it.
#1777
Comments
Some low-level libraries like libc are not allowed to trace because they caused troubles before. Please see |
Now I understand the reason the internal call stack in For example, I wrote these code and test: // libtest.c
void* malloc_wrappar (int size) {
return malloc(size);
}
// main.c
int main() {
malloc_wrappar(1024);
} $ gcc libtest.c -fPIC -shared -o libtest.so
$ gcc main.c libtest.so -o main
$ uftrace -P . -l ./main
# DURATION TID FUNCTION
[1763009] | main() {
[1763009] | malloc_wrappar() {
0.511 us [1763009] | malloc();
2.174 us [1763009] | } /* malloc_wrappar */
2.756 us [1763009] | } /* main */ Rust also wraps the libc as a core library, and I'm not sure about the internal structure, but I guess they use almost the same as the above example, but they are not able to trace. I wonder if it is about the |
When I compile the Rust and C code, it's not about the plt hooking or something else, but the real problem here is Here is the assembly code: Rust: 00000000000072a0 <_ZN13rust_libctest4main17h764c5f32c8353ea0E>:
72a0: 55 push %rbp
72a1: 48 89 e5 mov %rsp,%rbp
72a4: 48 83 ec 70 sub $0x70,%rsp
72a8: e8 83 d5 ff ff callq 4830 <mcount@plt>
72ad: 48 8b 05 d4 2b 25 00 mov 0x252bd4(%rip),%rax # 259e88 <getpid@GLIBC_2.2.5>
72b4: ff d0 callq *%rax
72b6: 89 45 dc mov %eax,-0x24(%rbp)
72b9: 48 8d 4d dc lea -0x24(%rbp),%rcx C: 000000000000077a <main>:
77a: 55 push %rbp
77b: 48 89 e5 mov %rsp,%rbp
77e: ff 15 64 08 20 00 callq *0x200864(%rip) # 200fe8 <mcount@GLIBC_2.2.5>
784: b8 00 00 00 00 mov $0x0,%eax
789: e8 42 fe ff ff callq 5d0 <getpid@plt> You can see If we test a simple C code as below: #include <stdlib.h>
#include <unistd.h>
int main() {
int (*getpid_ptr)() = getpid;
getpid_ptr();
} Then uftrace also not be able to trace the EDIT: 0000000000400600 <main>:
400600: 55 push %rbp
400601: 48 89 e5 mov %rsp,%rbp
400604: 48 83 ec 10 sub $0x10,%rsp
400608: e8 93 fe ff ff callq 4004a0 <mcount@plt>
40060d: ff 15 d5 09 20 00 callq *0x2009d5(%rip) # 600fe8 <getpid@GLIBC_2.2.5> And the |
We can trace if we enable the plt on Rust, by
We may need documentation about the build flags to make it easy to trace the Rust project. EDIT: |
--nest-libcall
(-l
)-fno-plt
disturbs tracing the libc call and default Rust build flag use it.
Hi @ChoKyuWon, thanks for digging into the problem. I also found that I can confirm that
|
@namhyung might have a better idea on this problem |
After shallow trial, I found that even diff --git a/libmcount/plthook.c b/libmcount/plthook.c
index 53dd7a4d..6bbc4b5c 100644
--- a/libmcount/plthook.c
+++ b/libmcount/plthook.c
@@ -204,7 +204,8 @@ static int find_got(struct uftrace_elf_data *elf, struct uftrace_elf_iter *iter,
pltgot_addr = (unsigned long)iter->dyn.d_un.d_val + offset;
break;
case DT_JMPREL:
- plt_found = true;
+ if(strncmp("__monstartup", elf_get_name(elf, iter, iter->sym.st_name), sizeof("__monstartup")))
+ plt_found = true;
break;
default:
break;
@@ -212,6 +213,7 @@ static int find_got(struct uftrace_elf_data *elf, struct uftrace_elf_iter *iter,
}
if (!plt_found) {
+ fprintf(stderr, "plt_not_found!\n");
pd = mcount_arch_hook_no_plt(elf, modname, offset);
if (pd == NULL)
pr_dbg2("no PLTGOT found.. ignoring...\n");
However, when I applied this fix and tried to run the |
Yeah I also noticed it didn't work well at some point but never had a chance to take a deeper look. I think compilers changed the pattern how they generate function calls without PLT. |
Issue namhyung#1777 reported that no-plt binary is handled as plt-enable binary because some functions are still left in plt section. The patch fixes this bug by comparing the name of self with a list of known functions. However, current `mcount_arch_hook_no_plt` make segfault on x86 now, so I comment it out and print the debug message if the binary was built with `-fno-plt` option. Signed-off-by: ChoKyuWon <[email protected]>
In
Maybe the problem is that the |
Issue namhyung#1777 reported that no-plt binary is handled as plt-enable binary because some functions are still left in plt section. The patch fixes this bug by comparing the name of self with a list of known functions. Signed-off-by: ChoKyuWon <[email protected]>
Issue reported that no-plt binary is handled as plt-enable binary because some functions are still left in plt section. The patch fixes this bug by comparing the name of self with a list of known functions. Fixes: namhyung#1777 Signed-off-by: ChoKyuWon <[email protected]>
I want to track the allocation(
malloc
) in Rust, so I use the simple code as follows:And trace it with the following command:
I use the
-Zbuild-std
option because the allocation layout(e.g.,exchange_malloc
,__rdl_alloc
) is also not traced with this option.As far as I know,
__rdl_alloc
calls themalloc
eventually, but the trace misses it in my environment.Additionally, I use the following code to test the direct libc call:
I ran it with uftrace and
--nest-libcall
, but the uftrace never found thegetpid
call.I attach the LLVM IR and asm of getpid example code to help the debug:
ASM:
Are there some missing flags I need to use to track the core libraries, such as libc or libstd in Rust?
The text was updated successfully, but these errors were encountered: