Problem with coupling shared object symbol visibility with protection

Paulo Pinto via Digitalmars-d digitalmars-d at puremagic.com
Wed Jan 21 04:36:55 PST 2015


On Tuesday, 20 January 2015 at 12:23:32 UTC, Benjamin Thaut wrote:
> I'm currently working on Windows DLL support which has stronger 
> rules than linux shared objects for which symbols actually get 
> exported from a shared library. But as we want to replicate the 
> same behaviour on linux using symbol visibility (e.g. gcc 4 
> -fVisibility=hidden) this issue also applies to linux once 
> implemented.
>
> Currently export means two things:
> - the symbol is publicy accessible (same as public)
> - the symbol will be accisble across shared library boundaries
>
>
> This has the following issue:
>
> export void templateFunc(T)()
> {
>   someHelperFunc();
> }
>
> private void someHelperFunc()
> {
>
> }
>
> And you don't even have to go into phobos to hit this problem. 
> It is already in druntime see core.time.FracSec._enforceValid
>
> This works with the current linux shared objects because they 
> simply export all symbols. But once only symbols with export 
> get exported this breaks.
>
> The problem here is that you don't want to make 
> someHelperFunc() export because that would mean users could 
> call it directly, but you want it to be available for cross 
> shared library calls. The cross shared library call happens if 
> a template is instanced from a different shared library / 
> executable than the module it was originally located in.
>
> There are two solutions for this.
>
> 1) Given that export is transitive (that means if a struct or 
> class is declared export every member that is _not_ private 
> will be accessible across shared library boundaries. This 
> behaviour is required to make the export protection level work 
> on windows)
>
> You can now do the following:
>
> export struct SomeStruct
> {
>   static public void templateFunc(T)()
>   {
>     someHelperFunc();
>   }
>
>   static package void someHelperFunc()
>   {
>
>   }
> }
>
> Because of the transitivity someHelperFunc will be exported but 
> still not be callable by the user directly. This can be used to 
> fix the issue in core.time but may not be so well suited if you 
> want the template to be on module level instead of nesting it 
> into a struct.
>
> 2) Make export an attribute. If export is no longer an 
> protection level but instead an attribute this issue can easily 
> be solved by doing.
>
> export public void templateFunc(T)()
> {
>   someHelperFunc();
> }
>
> export private void someHelperFunc()
> {
>
> }
>
> But this would require grammar changes. Which are generally 
> avoided if possible.
>
> There would be a third option, which I rather avoid. Doing a 
> "pramga(forceExport)" or something like that.
>
> My implementation, which I ran into this issue with, currently 
> usses approach 1. What do you think how this sould be solved?
>
> Walter: What was the general idea behind export when you 
> designed it, and how can it be used to solve this problem?
>
> Kind Regards
> Benjamin Thaut

Just as heads up in case D ever comes to Aix, I don't know how it 
looks like nowadays, but Aix back in 2000 used to be have similar 
behavior to Windows.

The .def files in Windows were .exp (I think) files on Aix.

--
Paulo


More information about the Digitalmars-d mailing list