dlsym: undefined symbol, Android N
<p>I would like to read value from the Android runtime shared library in my application.
Since Android 5, when the new runtime was introduced and <code>libart.so</code> has first appeared, I am doing it successfully with this code:</p>

<pre><code> std::unique_ptr&lt;void, int(*)(void*)&gt; handle { 
     dlopen("libart.so", RTLD_NOW | RTLD_GLOBAL),
     &amp;dlclose
 };

constexpr char THREAD_KEY_NAME[] = "_ZN3art6Thread17pthread_key_self_E";
key_ = static_cast&lt;pthread_key_t *&gt;(dlsym(handle.get(), THREAD_KEY_NAME));

LOG("Current thread: ", key_);
</code></pre>

<p>I'm testing this code on Android N simulator, and it fails! <code>dlsym</code> returns: </p>

<pre><code>undefined symbol: _ZN3art6Thread17pthread_key_self_E
</code></pre>

<p>I think "OK, there is no symbol now", so I pull the libart.so from simulator and see:</p>

<pre><code>% ./i686-linux-android-nm ~/Desktop/libart.so | grep pthread_key
00736ea0 B _ZN3art6Thread17pthread_key_self_E
</code></pre>

<p>hmm...</p>

<pre><code>% ./i686-linux-android-objdump -T ~/Desktop/libart.so | grep pthread_key
00736ea0 g    DO .bss   00000004  Base        .protected _ZN3art6Thread17pthread_key_self_E
</code></pre>

<p>hmm..</p>

<pre><code>  % ./i686-linux-android-readelf -a ~/Desktop/libart.so | grep pthread_key_self
  %
</code></pre>

<p>OK, empty there :(</p>

<p>So, while I'm not fully expert in these things, i have some questions:</p>

<ol>
<li>Why is <code>readelf</code> output is empty? There is some flags i forgot?</li>
<li>What does <code>.protected</code> means in objdump output? I have read some things about it but don't really understand. May be you can get good explanation?</li>
<li>Why <code>dlsym</code> returns error on new versions of Android? What the difference?</li>
</ol>

<p>BTW, I dumped <code>/proc/self/maps</code> file for my application on both Android versions and <code>grep libart.so</code> gives me:</p>

<ul>
<li><p>Android L (which works fine):</p>

<pre><code>b40f3000-b45f3000 r-xp 00000000 1f:00 777        /system/lib/libart.so
b45f3000-b45fb000 r--p 004ff000 1f:00 777        /system/lib/libart.so
b45fb000-b45fc000 rw-p 00507000 1f:00 777        /system/lib/libart.so
</code></pre></li>
<li><p>Android N (does not work):</p>

<pre><code>aaef1000-aaef2000 r-xp 00000000 fd:00 729        /system/fake-libs/libart.so
aaef2000-aaef3000 r--p 00000000 fd:00 729        /system/fake-libs/libart.so
aaef3000-aaef4000 rw-p 00001000 fd:00 729        /system/fake-libs/libart.so


abc53000-ac373000 r-xp 00000000 fd:00 1034       /system/lib/libart.so
ac374000-ac37c000 r--p 00720000 fd:00 1034       /system/lib/libart.so
ac37c000-ac37e000 rw-p 00728000 fd:00 1034       /system/lib/libart.so
</code></pre></li>
</ul>

<p>Thanks for any information!</p>

<p><strong>upd</strong>: I see there is two libart.so on Android N, and /system/fake-libs/libart.so is empty. I suppose there is a problem, but dlopen("/system/lib/libart.so", ...) does not works :(</p>