title: Hook and Replace Export Function in the Loaded ELF ( .so shared library )
body: <p>I'm writing some C code to hook some function of .so ELF (shared-library) loaded into memory.</p>
  
  <p>My C code should be able to re-direct an export function of another .so library that was loaded into the app/program's memory. </p>
  
  <p>Here's a bit of elaboration:</p>
  
  <p><img src="https://i.stack.imgur.com/egjkM.png" alt="enter image description here"></p>
  
  <p>Android app will have multiple .so files loaded. My C code has to look through export function that belongs to another shared .so library (called target.so in this case)</p>
  
  <p>This is not a regular dlsym approach because I don't just want address of a function but I want to replace it with my own fuction; in that: when another library makes the call to its own function then instead my hook_func gets called, and then from my hook_func I should call the original_func. </p>
  
  <p>For import functions this can work. But for export functions I'm not sure how to do it.
  Import functions have the entries in the symbol table that have corresponding entry in relocation table that eventually gives the address of entry in global offset table (GOT).
  But for the export functions, the symbol's st_value element itself has address of the procedure and not GOT address (correct me if I'm wrong).</p>
  
  <p>How do I perform the hooking for the <strong>export</strong> function?</p>
  
  <p>Theoretically speaking, I should get the memory location of the <code>st_value</code> element of dynamic symbol table entry ( <code>Elf32_Sym</code> ) of export function. If I get that location then I should be able to replace the value in that location with my hook_func's address. However, I'm not able to write into this location so far. I have to assume the dynamic symbol table's memory is read-only. If that is true then what is the workaround in that case?</p>
  
  <p>Thanks a lot for reading and helping me out. </p>
  
  <p><strong>Update:</strong> LD_PRELOAD can only replace the original functions with my own, but then I'm not sure if there any way to call the originals. 
  In my case for example:</p>
  
  <p>App initializes the audio engine by calling <code>Audio_System_Create</code> and passes a reference of <code>AUDIO_SYSTEM</code> object to <code>Audio_System_Create(AUDIO_SYSTEM **);</code>
  AUDIO API allocates this struct/object and function returns.
  Now if only I could access that <code>AUDIO_SYSTEM</code> object, I would easily attach a callback to this object and start receiving audio data. 
  Hence, my ultimate goal is to get the reference to <code>AUIOD_SYSTEM</code> object; and in my understanding, I can only get that if I intercept the call where that object is first getting allocated through <code>Audio_System_Create(AUIOD_SYSTEM **)</code>.
  Currently there is no straight way to grab the output audio at android. (all examples talk about recording audio that comes from microphone only)</p>
  
  <p><strong>Update2:</strong>
  As advised by Basile in his answer, I made use of dladdr() but strangely enough it gives me the same address as I pass to it.</p>
  
  <pre><code>void *pFunc=procedure_addr;  //procedure address calculated from the st_value of symbol from symbol table in ELF file (not from loaded file)
  
          int  nRet;
  
              // Lookup the name of the function given the function pointer
              if ((nRet = dladdr(pFunc, &amp;DlInfo)) != 0)
              {
                  LOGE("Symbol Name is: %s", DlInfo.dli_sname);
                  if(DlInfo.dli_saddr==NULL)
                      LOGE("Symbol Address is: NULL");
                  else
                      LOGE("Symbol Address is: 0x%x", DlInfo.dli_saddr);
              }
              else
                  LOGE("dladdr failed");
  </code></pre>
  
  <p>Here's the result I get:</p>
  
  <p>entry_addr           =0x75a28cfc</p>
  
  <p>entry_addr_through_dlysm           =0x75a28cfc</p>
  
  <p>Symbol Name is: AUDIO_System_Create</p>
  
  <p>Symbol Address is: 0x75a28cfc</p>
  
  <p>Here address obtained through dlysm or calculated through ELF file is the address of procedure; while I need the location where this address itself is; so that I can replace this address with my <code>hook_func</code> address. <code>dladdr()</code> didn't do what I thought it will do.</p>