I understand how static/dynamic libraries are used by the linker/loader.
Shareable libraries tend to be compiled into position-independent code. That means, for example, that transfers of control use PC-relative addressing. This is because they might be mapped into different positions in the address spaces of different client programs.
Shareable libraries should have a clear separation between read-only code+data, and read/write data. This way only a single copy of the read-only parts needs to be loaded into memory for all client processes.
If client program A refers to libraries B and C, while library B also refers to C, then you have to make sure that everything is built with consistent shareability settings. For example, if C is built in shareable and non-shareable versions, and B is built shareable against the shareable version of C, then A must also be built against the shareable versions of both B and C. If it tries to use the nonshareable version of C, this will likely lead to build problems, because of the conflict with the shareable version of C being used by B.
This document by Ulrich Drepper (former maintainer of the GNU libc library) goes into more detail than you would ever want to know about shareable libraries.