Unloading a shared library from memory - linux

I am trying to modify this shared library (with .so) extension on Linux. I am inserting some printf statement and fprintf statement to debug, and it has no effect. I removed the .so file and realized that the the program still runs fine. Does it mean that the program is loaded into memory?? (But I'm sure only the program I'm testing for uses that .so file though)
How do I get it to unload so I can make sure my program is loading the modified one?

No, shared libraries are not cached in memory. If you have deleted the .so file and your program still runs, then either:
the program is loading an .so of the same name from a different location, or
the program can run without loading the .so
If the .so is supposed to be loaded at program startup, then you can use ldd to find out where your OS thinks the .so actually is.
If the .so is loaded dynamically at runtime, then perhaps strace will be able to help pinpoint what is happening.

You can read /proc/1234/maps to find out the memory map of process 1234. This also shows the dynamically loaded shared objects.
You may use the LD_LIBRARY_PATH environment variable to change the path of shared libraries and ldconfig to upgrade its cache. Look also in /etc/ld.so.conf etc.
Of course, you have to restart the program loading your shared library.

Related

What is the role of program interpreters in executable files?

I was going through disassembly of elf executables and understanding the elf format. In there, I saw lib64/ld-linux-x86-64.so.2 used as program interpreter in the generated executable.
My guess is: I had used printf in the source code, which had to be dynamically linked. When I checked through dynamic section, I was able to find a reference to libc.so.6 shared library (tag:DT_NEEDED). In my system, I found multiple files with that name in different directories:
sourav#ubuntu-VirtualBox:/$ sudo find / -name libc.so.6
/usr/lib/x86_64-linux-gnu/libc.so.6
find: ‘/run/user/1000/doc’: Permission denied
find: ‘/run/user/1000/gvfs’: Permission denied
/snap/snapd/13170/lib/x86_64-linux-gnu/libc.so.6
/snap/snapd/11107/lib/x86_64-linux-gnu/libc.so.6
/snap/core18/1988/lib/i386-linux-gnu/libc.so.6
/snap/core18/1988/lib/x86_64-linux-gnu/libc.so.6
/snap/core18/2128/lib/i386-linux-gnu/libc.so.6
/snap/core18/2128/lib/x86_64-linux-gnu/libc.so.6
So, I guess purpose of program interpreter is to resolve these names to the proper libraries and load them during execution. Is this correct?
It seems, we can also have executables with no program interpreter (which is the case for program interpreter itself). In that case, does system/os itself loads the shared library? If so, how does it resolves the path of library?
Is it possible to generate executable with no program interpreter using gcc? My gcc version is 'gcc version 9.3.0 (Ubuntu 9.3.0-17ubuntu1~20.04)'.
So, I guess purpose of program interpreter is to resolve these names to the proper libraries and load them during execution. Is this correct?
Yes, but that that's a bit minimalistic. Loading dynamic libraries involves locating them, loading or mapping them into memory if necessary, and resolving dynamic symbols within, possibly lazily, for multiple kinds of relocations. It involves recursively loading the libraries' own needed libraries. Also, in a dynamically linked executable, the program interpreter provides the program entry point (from the kernel's perspective), so it is also responsible for setting up and entering the program-specific entry point (for example, main() in a C or C++ program).
It seems, we can also have executables with no program interpreter (which is the case for program interpreter itself). In that case, does system/os itself loads the shared library? If so, how does it resolves the path of library?
You can have ELF executables without a program interpreter, but they are not dynamically linked, at least not in the ELF sense. There are no shared libraries to load, and certainly the system does not load any.
Is it possible to generate executable with no program interpreter using gcc? My gcc version is 'gcc version 9.3.0 (Ubuntu 9.3.0-17ubuntu1~20.04)'.
If you have static versions of all needed libraries available then you should be able to achieve that by including the -static option on the command line when you link the program. It is entirely possible, however, that you do not have the needed static libraries, even if libc is the only library you need.

What is the difference between an executable and a shared library

The properties of ls show it is an executable.
And properties of kmod show it is a shared library.
Im trying to check for executables and hash them in ubuntu 14.04 LTS. Is there any way to differentiate executables from the other types? Thanks in advance
Executable is a Load file which executes directly in system as a program. As per your question, "ls" is a executable which is used to
list the current directory contents. The load for "ls" is placed in "/bin" or you can check using command "which ls". Shared library are the one which do some task that is commonly accessed or used by many executables. These library are loaded into the memory only once and accessed by many programs(executables) at runtime.

Which libraries appear in /proc/$PID/pmaps?

On Linux you can inspect /proc/$PID/pmaps to see the libraries loaded by a particular program, and a program can open /proc/self/pmaps to examine the libraries it itself has loaded.
I know pmaps will only contain dynamic libraries, and obviously the kernel can't predict which libraries we might dlopen at a later point, so I expect those aren't included in /proc/self/maps. But I'm unsure of a few other other scenarios:
Are libraries that have been linked at build time but we haven't called any function in yet included? My understanding is the Linux delays linking symbols until the first time they are used, so I'm not sure if they'll show up.
Does pmaps contain all the libraries used recursively? E.g. if I look at each library in pmaps and run ldd on it, and then run ldd on those, ad nauseum, I shouldn't find any new libraries that weren't in the original pmaps? I tried this on a couple binaries and it appears to be so but maybe I'm getting lucky.
Are libraries that have been linked at build time but we haven't called any function in yet included?
Yes: the runtime loader will mmap every library that your executable directly depends on, before your program starts running.
You can find the list of such libraries by running
readelf -d a.out | grep NEEDED
Does pmaps contain all the libraries used recursively?
Yes: if a library that you directly depend on itself depends on some other library, the runtime loader will mmap the recursive dependencies as well.
My understanding is the Linux delays linking symbols until the first time they are used
That is mosty correct for function symbols, but false for data symbols, which can't be resolved lazily.
Also, whether the symbols are resolved lazily or not depends on LD_BIND_NOW environment variable, and on an equivalent setting in the executable dynamic section, controlled by -znow linker flag.
None of that changes the mmap pciture though; if you have a DT_NEEDED entry for foo.so in your dynamic section, then foo.so will be mmaped (and will show in /proc/self/*map*) independent of lazy or non-lazy resolution.
/proc/$pid/maps is not only going to list libraries that are loaded, but also ALL other mapped memory segments.
Read this thread and the article in there:
Understanding Linux /proc/id/maps

Loading and Unloading shared libraries in Mac OSX

I am sorry if this question has been repeated before in this forum. I am having a problem where, Loading and Unloading of dylibs arent working as expected in Mac(esp the unloading part.).
The question is if I have an executable and if I load a shared library say A.dylib and then use the loaded shared library to load an library say B.dylib. When I try unloading the library B.dylib at a later stage, the there is no error code returned(the return int value is 0 - as I am using a regular dlopen and dlclose functions to load and unload libraries, 0 means unloaded successfully), but when I check to make sure using the activity monitor or lsof the b.dylib is still in the memory.
Now the we are porting this code for windows, linux & mac. Windows and Linux works as expected, but only mac is giving me problems.
I was reading in the mac developer library and found out that: " There are a couple of cases in which a dynamic library will never be unloaded:
1) the main executable links against it, 2) An API that does not supoort unloading (e.g. NSAddImage())
was used to load it or some other dynamic library that depends on it, 3) the dynamic library is in
dyld's shared cache."
In my case I dont fall either of the first 2 cases. I am suspecting on case3.
Here is my question:
1. What can I do to make sure I have case 3?
2. If yes, how to fix it?
3. If not, how to fix it?
4. Why is mac so different?
Any help in this regard is appreciated!
Thanks,
Jan
When you load a shared library into an executable, all of the symbols exported by that library are candidates to resolve symbols required by the executable, causing the library to remain loaded if the DYLD linker binds to an unintended symbol. You can list the symbols in a shared library by using nm, and you can set environment variables to enable debugging output for the dynamic linker (see this man page on dyld). You need to set the DYLD_PRINT_BINDINGS environment variable.
Most likely, you need to limit the exported symbols to a specific subset that is used by the executable, so that only those symbols you intend to use are bound. This can be done by placing the required symbols in a file and passing it to the linker via the -exported_symbols_list option. Without doing so, you can end up binding a symbol in the dyloaded library, and it will not be unloaded since they are required to resolve a symbol in the executable and won't unload when dlclose() is called.

.lib files and decompiling

I have a .exe which is compiled from a combination of .for (fortran), and .c source files.
It does not run on anything later than Win98, due to an error with the graphics server:
“access violation error in User 32.dll at Ox7e4467a9”
Unless there is some other way around the above error (?), I assume I have to recompile the .exe from source using a more modern graphics server. I have all the files to do this bar one .lib file!
Is it possible to pull any info on the missing lib file out of the current .exe I have?
It is possible to dis-assemble the .exe, but I don't think I gain much from this?
You probably can't "cut" the lib file from an executable. Even if you could somehow get the code from it, standard compilers and linker wouldn't know how to link against it, since it won't have the linking information needed (they are not included in the result binary).
However, if your problem is that your program works on Win98, but doesn't run on NT-based systems (XP, Vista, Win7), I think it would be easier to find out, what incompatibility is there that crashes the program. You mentioned that the access violation occurs in user32.dll. Start your program inside a debugger, take a look at which function the crash occurs. Make sure you have your PDB symbols loaded (so you can see names of internal non-public functions). Trace down which Win32 API is called and what are its parameters. Try to figure out, what should be at the memory that cannot be accessed.
Also without any other information, it's impossible to help you with that.
Once integrated into an image file (your exe), a library (your .lib) which is statically bound to an application (which is done by your linker) cannot be separated, differentiated from your own code, and thus, one cannot retrieve the code from a lib by decompiling the exe.

Resources