First of all, I'm asking this from a technical perspective, not a perspective of the user of library code. One example of a difference is that shared objects contain program headers and ordinary object files don't. What are the other differences?

As to the purpose of my question, I'm trying to figure out what content would need to be removed from a shared object file to have the linker treat it as an ordinary object file and attempt to relocate and static link it into the generated executable file, rather than identifying it as a shared library and generating a DT_NEEDED reference. This in turn is the first step to primitive "conversion" of a shared library to something that can be statically linked (further work to make the relocations satisfiable may be required, however).

Edit
Report