• Compile-time alternative to LD_PRELOAD

    From Frederick Gotham@21:1/5 to All on Mon Jul 19 05:46:03 2021
    I have a special audio driver that needs additional clean-up when the ALSA (Advanced Linux Sound Architecture) function, 'snd_pcm_close', is called.

    This additional clean-up can't take place inside the C code for the audio driver, and so it must happen inside the ALSA library 'libasound.so' whenever a process calls 'snd_pcm_close'. To make things a little more complicated, 'libasound.so' is a pre-
    compiled binary for which I don't have the source code (a 3rd party has already made alterations to 'alsa-lib' and they won't give me the source code).

    I could create a small shared library file with just one function 'snd_pcm_close', and then when I start any program that uses ALSA, I can use LD_PRELOAD as follows:

    LD_PRELOAD=my_small_library.so some_program_that_uses_sound

    This would be fine if I only had one or two programs that use sound, and if this rarely changed.

    I'm looking for a solution though that will work with *any* program that links with 'libasound.so'. So here's what I did:

    Step 1) Rename the original library
    mv libasound.so libAsound.so
    Step 2) Change the 'soname' inside the original library
    sed -i 's/libasound.so/libAsound.so/g' libAsound.so
    Step 3) Write my own small library containing one function 'snd_pcm_close'
    (see the source code for this library at the end of this post)
    Step 4) Build my own small library to link with the original renamed library:
    gcc -o libasound.so.2.0.0 my_small_library.c -ldl -L./ -l:libAsound.so.2.0.0 -Wl,-soname,libasound.so.2

    So then when any process (for example 'baresip') links with 'libasound.so', here's what will happen:

    a) baresip links with our small library libasound.so
    b) libasound.so links with the original library named libAsound.so
    c) So now both shared libraries, libasound.so and libAsound.so, have been loaded into the address space of baresip
    d) Since libasound.so was loaded before libAsound.so, the function 'snd_pcm_open' is taken from my small library
    e) All other functions such as 'snd_pcm_open' and 'snd_pcm_writei' are of course missing from our small library, but the Linux operating system automatically finds these functions in any other library that's linked in, and hence finds them in libAsound.so

    I have tested this out and it works. What surprises me though is that I can't find a similar implementation to this on the internet -- I mean surely somebody has done this before? If anyone can suggest a better way of doing this, I'm all ears.

    Source code for my small shared library:

    #include <dlfcn.h> /* dlopen, dlsym, dlclose */

    static void Patch_Code(void); /* Defined lower down in this file */

    int snd_pcm_close(void *arg)
    {
    int retval = -1; /* ALSA manual says "Zero on success, or a negative value on error" */

    void *const dlhandle = dlopen("libAsound.so", RTLD_NOW|RTLD_LOCAL); /* Load original lib */

    if ( dlhandle )
    {
    int (*const snd_pcm_close_PROPER)(void*) = dlsym(dlhandle, "snd_pcm_close");

    if ( snd_pcm_close_PROPER ) retval = snd_pcm_close_PROPER(arg); /* Call original func */

    dlclose(dlhandle);
    }

    Patch_Code(); /* <--------------- Our patch is invoked here */

    return retval;
    }

    static void Patch_Code(void)
    {
    /* We put our patch in here */
    }

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Lew Pitcher@21:1/5 to Frederick Gotham on Mon Jul 19 15:10:12 2021
    On Mon, 19 Jul 2021 05:46:03 -0700, Frederick Gotham wrote:

    I have a special audio driver that needs additional clean-up when the ALSA (Advanced Linux Sound Architecture) function, 'snd_pcm_close', is called.

    This additional clean-up can't take place inside the C code for the audio driver, and so it must happen inside the ALSA library 'libasound.so' whenever a process calls 'snd_pcm_close'. To make things a little more complicated, 'libasound.so' is a pre-compiled binary for which I don't have the source code (a 3rd party has already made alterations to 'alsa-lib' and they won't give me the source code).

    I could create a small shared library file with just one function 'snd_pcm_close', and then when I start any program that uses ALSA, I can use LD_PRELOAD as follows:

    LD_PRELOAD=my_small_library.so some_program_that_uses_sound

    This would be fine if I only had one or two programs that use sound, and if this rarely changed.

    I'm looking for a solution though that will work with *any* program that links with 'libasound.so'. So here's what I did:
    [snip]

    ISTM that you have overlooked the advantages of LD_PRELOAD and minimized
    the disadvantages of your proposed solution.

    For your solution to work, you need to rename the original libasound library. Each time your distribution or software supplier updates libasound, you have
    to remember to preserve your stand-in libasound.so and rename the distributor supplied libasound.so to the name you chose to work with. This seems dangerous to me, as it presumes that you will remember to do this each time you update the official libasound.so.

    OTOH, /proper/ use of LD_PRELOAD would permit you to install a library that will intercept and interceed in any snd_pcm_close() calls from running processes, without requiring manual intervention with each libasound module refresh.

    The key would be to add the path to your intercept library into the /etc/ld.so.preload file (see ld.so(8) for details) to ensure that all processes have your intercept library loaded ahead of, and instead of, the libasound library.

    Alternatively, you /could/ alter the various login-related scripts to set the LD_PRELOAD environment variable appropriately, but this seems chancier, in that you need to change /all/ the login environment setup scripts, both commandline and
    GUI.


    --
    Lew Pitcher
    "In Skills, We Trust"

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Nicolas George@21:1/5 to All on Mon Jul 19 15:04:36 2021
    Frederick Gotham , dans le message <927ce9c7-5a89-405f-9286-8a75ecbc8f14n@googlegroups.com>, a écrit :
    (a 3rd party has already made alterations to 'alsa-lib' and they won't
    give me the source code).

    libasound is LGPL: if they distribute a binary without the source code, they are infringing. You can threaten them.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)