|
From: Wuweijia <wuw...@hu...> - 2019-04-23 12:37:58
|
Hi
On the Android OS, there is a question about the linker program with vaglrind memcheck;
The 1st experiment, the libc module do call the dlopen function to load some shared object, before the linker call the pre_init functions ( before transfer the cpu control to the main ), and then the valgrind can not trace malloc leak;
The second experiment, the libc module do not call the dlopen function to load some shared object, before the linker call the pre_init functions ( before transfer the cpu control to the main ), and then the valgrind can trace malloc leak;
I want to know why , and how to make valgrind can trace memory leak, while the libc module call the dlopen function to load some so, before the linker call the pre-init functions.
If you want to add some args to trace, Please email me.
Valgrind version 3.14.
BR Owen
|
|
From: John R. <jr...@bi...> - 2019-04-23 14:14:35
|
> On the Android OS, there is a question about the linker program with vaglrind memcheck; > > The 1^st experiment, the libc module *do*call the dlopen function to load some shared object, before the linker call the pre_init functions ( before transfer the cpu control to the main ), and then the valgrind *can not*trace malloc leak; > > The second experiment, the libc module *do not*call the dlopen function to load some shared object, before the linker call the pre_init functions ( before transfer the cpu control to the main ), and then the valgrind *can* trace malloc leak; > > I want to know why , and how to make valgrind can trace memory leak, while the libc module call the dlopen function to load some so, before the linker call the pre-init functions. > > If you want to add some args to trace, Please email me. > > Valgrind version 3.14. Thank you for stating the version of Valgrind. It is hard to follow and understand the descriptions of the first and second experiments. Please construct two test cases of specific literal source code with recipes for compile and linking, corresponding to the first and second experiments. Those two cases should be runnable under valgrind, and should illustrate the difference between them. |
|
From: John R. <jr...@bi...> - 2019-04-23 15:19:09
|
>> On the Android OS, there is a question about the linker program with vaglrind memcheck.
Which version of Android?
>>
>> The 1^st experiment, the libc module *do*call the dlopen function to load some shared object, before the linker call the pre_init functions ( before transfer the cpu control to the main ), and then the valgrind *can not*trace malloc leak;
>>
>> The second experiment, the libc module *do not*call the dlopen function to load some shared object, before the linker call the pre_init functions ( before transfer the cpu control to the main ), and then the valgrind *can* trace malloc leak;
>>
>> I want to know why , and how to make valgrind can trace memory leak, while the libc module call the dlopen function to load some so, before the linker call the pre-init functions.
According to
https://docs.oracle.com/cd/E19683-01/816-1386/6m7qcobks/index.html
the order of execution is:
1. linker resolves and fetches all DT_NEEDED modules (shared libraries),
and performs all relocations for the entire process image
2. linker calls DT_PREINIT_ARRAY functions of the main program, in order
(only a main program may have DT_PREINIT_ARRAY; a shared library MUST NOT)
3. in dependency order (topological bottom-up) of all loaded modules (main program
and shared libraries): linker calls DT_INIT and then DT_INIT_ARRAY (in order)
for the module
4. linker transfers control to the ElfXX_Ehdr.e_entry address of the main program
It is undefined what happens if a DT_PREINIT_ARRAY, DT_INIT_ARRAY, or DT_INIT function
calls dlopen, particularly if the newly-loaded module depends on any other modules,
whether or not those modules have been loaded already. (The dependent module
might not be initialized yet.)
|
|
From: Wuweijia <wuw...@hu...> - 2019-04-24 02:56:40
|
Is there any ways to make valgrind to support init_array to dlopen shared object;
I think linker can make the right jump to the malloc function without valgirind, so the source is right;
I want some ways to trace the valgirnd why redir module to malloc is failue;
-----邮件原件-----
发件人: John Reiser [mailto:jr...@bi...]
发送时间: 2019年4月23日 23:19
收件人: val...@li...
主题: Re: [Valgrind-users] Some question about linker dlopen with valgrind
>> On the Android OS, there is a question about the linker program with vaglrind memcheck.
Which version of Android?
>>
>> The 1^st experiment, the libc module *do*call the dlopen
>> function to load some shared object, before the linker call the
>> pre_init functions ( before transfer the cpu control to the main ),
>> and then the valgrind *can not*trace malloc leak;
>>
>> The second experiment, the libc module *do not*call the
>> dlopen function to load some shared object, before the linker call
>> the pre_init functions ( before transfer the cpu control to the main
>> ), and then the valgrind *can* trace malloc leak;
>>
>> I want to know why , and how to make valgrind can trace memory leak, while the libc module call the dlopen function to load some so, before the linker call the pre-init functions.
According to
https://docs.oracle.com/cd/E19683-01/816-1386/6m7qcobks/index.html
the order of execution is:
1. linker resolves and fetches all DT_NEEDED modules (shared libraries),
and performs all relocations for the entire process image
2. linker calls DT_PREINIT_ARRAY functions of the main program, in order
(only a main program may have DT_PREINIT_ARRAY; a shared library MUST NOT)
3. in dependency order (topological bottom-up) of all loaded modules (main program
and shared libraries): linker calls DT_INIT and then DT_INIT_ARRAY (in order)
for the module
4. linker transfers control to the ElfXX_Ehdr.e_entry address of the main program
It is undefined what happens if a DT_PREINIT_ARRAY, DT_INIT_ARRAY, or DT_INIT function calls dlopen, particularly if the newly-loaded module depends on any other modules, whether or not those modules have been loaded already. (The dependent module might not be initialized yet.)
_______________________________________________
Valgrind-users mailing list
Val...@li...
https://lists.sourceforge.net/lists/listinfo/valgrind-users
|
|
From: Wuweijia <wuw...@hu...> - 2019-04-24 01:28:12
|
Android Q
The libc source as below:
__attribute__((constructor(1))) static void __libc_preinit() {
// The linker has initialized its copy of the global stack_chk_guard, and filled in the main
// thread's TLS slot with that value. Initialize the local global stack guard with its value.
__stack_chk_guard = reinterpret_cast<uintptr_t>(__get_tls()[TLS_SLOT_STACK_GUARD]);
__libc_preinit_impl();
}
__attribute__((noinline))
static void __libc_preinit_impl() {
// Register libc.so's copy of the TLS generation variable so the linker can
// update it when it loads or unloads a shared object.
TlsModules& tls_modules = __libc_shared_globals()->tls_modules;
tls_modules.generation_libc_so = &__libc_tls_generation_copy;
__libc_tls_generation_copy = tls_modules.generation;
__libc_init_globals();
__libc_init_common();
// Hooks for various libraries to let them know that we're starting up.
TestInitImpl();
}
static void TestInitImpl() {
printf("%s enter\n", __func__);
void * handle = dlopen("liblog.so", RTLD_NOW ); -----------This is most important call, If call dlopen success, and then malloc trace is not available now; If Not success, the malloc trace is okay;
printf("handle:%p\n", handle);
}
The test main as below:
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
int main(int argc, char ** argv) {
char * p = (char *)malloc(2048);
p[2049] = 5;
printf("p=%p p[2049]=%d malloc=%p \n", p, p[2049], malloc);
(void) argc;
(void) argv;
return 0;
}
The valgrind output as below:
localhost:/system/bin # ./valgrind --undef-value-errors=no --trace-malloc=yes ./test64
MallocInitImpl enter
handle:0xcf2625b55fe1209
==7131== Memcheck, a memory error detector
==7131== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==7131== Using Valgrind-3.14.0 and LibVEX; rerun with -h for copyright info
==7131== Command: ./test64
==7131==
linker: Warning: "/system_Q_EA3/lib64/valgrind/vgpreload_core-arm64-linux.so" has unsupported flags DT_FLAGS_1=0x421 (ignoring unsupported flags)
WARNING: linker: Warning: "/system_Q_EA3/lib64/valgrind/vgpreload_core-arm64-linux.so" has unsupported flags DT_FLAGS_1=0x421 (ignoring unsupported flags)
linker: Warning: "/system_Q_EA3/lib64/valgrind/vgpreload_memcheck-arm64-linux.so" has unsupported flags DT_FLAGS_1=0x421 (ignoring unsupported flags)
WARNING: linker: Warning: "/system_Q_EA3/lib64/valgrind/vgpreload_memcheck-arm64-linux.so" has unsupported flags DT_FLAGS_1=0x421 (ignoring unsupported flags)
--7131-- malloc(48) = 0x60AA040
--7131-- malloc(1024) = 0x60AA0B0-----------------------------before call dlopen in libc module , these text show me malloc trace is okay.
MallocInitImpl enter
--7131-- free(0x0)
handle:0x25bc73725878d53 -----------------------after print these text (it mean dlopen success in libc) , malloc trace is failure;
p=0x6813000 p[2049]=5 malloc=0x5d0f32c----------------------these text mean main alloc some memory ;
==7131==
==7131== HEAP SUMMARY:
==7131== in use at exit: 1,072 bytes in 2 blocks
==7131== total heap usage: 2 allocs, 0 frees, 1,072 bytes allocated
==7131==
==7131== LEAK SUMMARY:
==7131== definitely lost: 0 bytes in 0 blocks
==7131== indirectly lost: 0 bytes in 0 blocks
==7131== possibly lost: 0 bytes in 0 blocks
==7131== still reachable: 1,072 bytes in 2 blocks
==7131== suppressed: 0 bytes in 0 blocks
==7131== Rerun with --leak-check=full to see details of leaked memory
==7131==
==7131== For counts of detected and suppressed errors, rerun with: -v
==7131== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
-----邮件原件-----
发件人: John Reiser [mailto:jr...@bi...]
发送时间: 2019年4月23日 23:19
收件人: val...@li...
主题: Re: [Valgrind-users] Some question about linker dlopen with valgrind
>> On the Android OS, there is a question about the linker program with vaglrind memcheck.
Which version of Android?
>>
>> The 1^st experiment, the libc module *do*call the dlopen
>> function to load some shared object, before the linker call the
>> pre_init functions ( before transfer the cpu control to the main ),
>> and then the valgrind *can not*trace malloc leak;
>>
>> The second experiment, the libc module *do not*call the
>> dlopen function to load some shared object, before the linker call
>> the pre_init functions ( before transfer the cpu control to the main
>> ), and then the valgrind *can* trace malloc leak;
>>
>> I want to know why , and how to make valgrind can trace memory leak, while the libc module call the dlopen function to load some so, before the linker call the pre-init functions.
According to
https://docs.oracle.com/cd/E19683-01/816-1386/6m7qcobks/index.html
the order of execution is:
1. linker resolves and fetches all DT_NEEDED modules (shared libraries),
and performs all relocations for the entire process image
2. linker calls DT_PREINIT_ARRAY functions of the main program, in order
(only a main program may have DT_PREINIT_ARRAY; a shared library MUST NOT)
3. in dependency order (topological bottom-up) of all loaded modules (main program
and shared libraries): linker calls DT_INIT and then DT_INIT_ARRAY (in order)
for the module
4. linker transfers control to the ElfXX_Ehdr.e_entry address of the main program
It is undefined what happens if a DT_PREINIT_ARRAY, DT_INIT_ARRAY, or DT_INIT function calls dlopen, particularly if the newly-loaded module depends on any other modules, whether or not those modules have been loaded already. (The dependent module might not be initialized yet.)
_______________________________________________
Valgrind-users mailing list
Val...@li...
https://lists.sourceforge.net/lists/listinfo/valgrind-users
|
|
From: John R. <jr...@bi...> - 2019-04-29 03:34:24
|
On 4/24/2019 0128 UTC, Wuweijia wrote:
> Android Q
>
> The libc source as below:
The purpose of a test case is to reproduce the problem. What you wrote fails badly.
It does not compile, under ANY compiler: functions are used before they are declared.
It does not have the necessary #include statements.
It is not written in C language. 'reinterpret_cast' is C++.
It is not standard C++. __has_builtin() (from Android #include) is only in the 'clang' dialect.
It uses symbols that start with underscore ('_') without understanding what it is doing.
They're written with a leading underscore to warn you that you should not touch them.
You should have said:
git clone https://android.googlesource.com/platform/bionic/
git clone https://android.googlesource.com/platform/system/core
===== test-libc.cpp
#include <dlfcn.h>
#include <stdio.h>
#include <stdint.h>
#include <private/bionic_ssp.h>
#include <private/__get_tls.h>
#include <private/bionic_asm_tls.h>
#include <private/bionic_globals.h>
#include <bionic/libc_init_common.h>
static void TestInitImpl() {
printf("%s enter\n", __func__);
//-----------This is most important call, If call dlopen success, and then malloc trace is not available now; If Not success, the malloc trace is okay;
void * handle = dlopen("liblog.so", RTLD_NOW );
printf("handle:%p\n", handle);
}
__attribute__((noinline))
static void __libc_preinit_impl() {
// Register libc.so's copy of the TLS generation variable so the linker can
// update it when it loads or unloads a shared object.
TlsModules& tls_modules = __libc_shared_globals()->tls_modules;
tls_modules.generation_libc_so = &__libc_tls_generation_copy;
__libc_tls_generation_copy = tls_modules.generation;
__libc_init_globals();
__libc_init_common();
// Hooks for various libraries to let them know that we're starting up.
TestInitImpl();
}
__attribute__((constructor(1))) static void __libc_preinit() {
// The linker has initialized its copy of the global stack_chk_guard, and filled in the main
// thread's TLS slot with that value. Initialize the local global stack guard with its value.
__stack_chk_guard = reinterpret_cast<uintptr_t>(__get_tls()[TLS_SLOT_STACK_GUARD]);
__libc_preinit_impl();
}
=====
export ADIR=$PWD # after "git clone" above
# -I list: Android source is crap.
test-libc.so: test-libc.cpp
clang++ -shared -fPIC -g -nostdinc \
-I$(ADIR)/bionic/libc/include \
-I$(ADIR)/bionic/libc \
-I$(ADIR)/bionic/libc/async_safe/include \
-I$(ADIR)/core/liblog/include \
-I/usr/lib/gcc/x86_64-redhat-linux/8/include \
-I/usr/include \
$< -o $@
=====
> void * handle = dlopen("liblog.so", RTLD_NOW ); -----------This is most important call, If call dlopen success, and then malloc trace is not available now; If Not success, the malloc trace is okay;
So calling dlopen() while still in the initialization phase of the run-time linker,
causes trouble for valgrind. Get the source, apply a debugger, and find out why.
Calling dlopen() from a DT_INIT, DT_INIT_ARRAY, or DT_PREINIT_ARRAY function
is a design error: the run-time linker makes NO guarantees about what happens.
|