From owner-freebsd-hackers@freebsd.org Sat Dec 26 12:28:24 2015 Return-Path: Delivered-To: freebsd-hackers@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id 43CA3A51B97 for ; Sat, 26 Dec 2015 12:28:24 +0000 (UTC) (envelope-from kostikbel@gmail.com) Received: from kib.kiev.ua (kib.kiev.ua [IPv6:2001:470:d5e7:1::1]) (using TLSv1 with cipher DHE-RSA-CAMELLIA256-SHA (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id D378B163D for ; Sat, 26 Dec 2015 12:28:23 +0000 (UTC) (envelope-from kostikbel@gmail.com) Received: from tom.home (kostik@localhost [127.0.0.1]) by kib.kiev.ua (8.15.2/8.15.2) with ESMTPS id tBQCSIhO036924 (version=TLSv1 cipher=DHE-RSA-CAMELLIA256-SHA bits=256 verify=NO); Sat, 26 Dec 2015 14:28:18 +0200 (EET) (envelope-from kostikbel@gmail.com) DKIM-Filter: OpenDKIM Filter v2.10.3 kib.kiev.ua tBQCSIhO036924 Received: (from kostik@localhost) by tom.home (8.15.2/8.15.2/Submit) id tBQCSIHN036923; Sat, 26 Dec 2015 14:28:18 +0200 (EET) (envelope-from kostikbel@gmail.com) X-Authentication-Warning: tom.home: kostik set sender to kostikbel@gmail.com using -f Date: Sat, 26 Dec 2015 14:28:18 +0200 From: Konstantin Belousov To: Ivan Radovanovic Cc: freebsd-hackers@freebsd.org Subject: Re: Unexpected behavior of dynamic linker Message-ID: <20151226122818.GI3625@kib.kiev.ua> References: <567E810C.3040809@gmail.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <567E810C.3040809@gmail.com> User-Agent: Mutt/1.5.24 (2015-08-30) X-Spam-Status: No, score=-2.0 required=5.0 tests=ALL_TRUSTED,BAYES_00, DKIM_ADSP_CUSTOM_MED,FREEMAIL_FROM,NML_ADSP_CUSTOM_MED autolearn=no autolearn_force=no version=3.4.1 X-Spam-Checker-Version: SpamAssassin 3.4.1 (2015-04-28) on tom.home X-BeenThere: freebsd-hackers@freebsd.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: Technical Discussions relating to FreeBSD List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 26 Dec 2015 12:28:24 -0000 On Sat, Dec 26, 2015 at 12:59:08PM +0100, Ivan Radovanovic wrote: > Hello, > > While investigating possibility of building some module system on > FreeBSD I stumbled upon unexpected (at least for me) behavior of dynamic > linker. > > I have several (C++) modules organized like this: > > * main program (executable) > * main library (shared object, loaded with RTLD_GLOBAL since it provides > symbols for main program and other modules) > * module 1 (shared object, loaded with RTLD_LOCAL) > > I put all private initializations for library and module in (static) > global object constructors, but I gave to both classes same (original) > name "PrivateClass" (so there is in fact PrivateClass in mainlib.so, and > unrelated PrivateClass in module.so). > > What is happening is that when main program loads main library (via > dlopen(3)) its _init calls correctly mainlib::PrivateClass constructor > which performs initialization, but when main program later loads module > (again via dlopen(3)) its _init doesn't call module::PrivateClass > constructor, but rather mainlib::PrivateClass constructor. I understand > this is happening because symbols with same name exist in both shared > objects and dynamic linker is replacing reference to > module::PrivateClass with reference to mainlib::PrivateClass, but I > would expect symbol to be looked up outside of module only if it doesn't > exist within it (ie, the inner-most definition to be used) - in this > case PrivateClass exists within module? > > Further I am not sure what would be correct solution for this in my case > - C++ has static modifier for objects and functions, but not for classes > to make them unavailable from other modules and solution with same > random namespace name doesn't sound elegant enough :-) > > Any thoughts regarding this (I can also supply source files to test this > behavior)? This is expected behaviour, it is mandated by the ELF standard. ELF tried to emulate the behaviour of the static libraries as much as possible. Think what would happen in your case if both modules where linked statically into the binary. To augment the behaviour, read about linker option -Bsymbolic, compiler option -fhidden, and GNU-specific attribute __visibility__("hidden").