Bug 25529 - mono can't pinvoke into symbols with __attribute__(("hidden"))
Summary: mono can't pinvoke into symbols with __attribute__(("hidden"))
Status: RESOLVED ANSWERED
Alias: None
Product: iOS
Classification: Xamarin
Component: General ()
Version: XI 8.6.0
Hardware: Macintosh Mac OS
: Normal normal
Target Milestone: Untriaged
Assignee: Bugzilla
URL:
Depends on:
Blocks:
 
Reported: 2014-12-19 09:20 UTC by Mikalai
Modified: 2014-12-22 08:33 UTC (History)
4 users (show)

Tags:
Is this bug a regression?: ---
Last known good build:


Attachments
sample project (8.02 KB, application/zip)
2014-12-19 09:20 UTC, Mikalai
Details


Notice (2018-05-24): bugzilla.xamarin.com is now in read-only mode.

Please join us on Visual Studio Developer Community and in the Xamarin and Mono organizations on GitHub to continue tracking issues. Bugzilla will remain available for reference in read-only mode. We will continue to work on open Bugzilla bugs, copy them to the new locations as needed for follow-up, and add the new items under Related Links.

Our sincere thanks to everyone who has contributed on this bug tracker over the years. Thanks also for your understanding as we make these adjustments and improvements for the future.


Please create a new report on Developer Community or GitHub with your current version information, steps to reproduce, and relevant error messages or log files if you are hitting an issue that looks similar to this resolved bug and you do not yet see a matching new report.

Related Links:
Status:
RESOLVED ANSWERED

Description Mikalai 2014-12-19 09:20:10 UTC
Created attachment 9142 [details]
sample project

Runtime throws EntryPointNotFound() when pinvoking symbol marked as __private_external__.
Comment 1 Udham Singh 2014-12-19 10:03:20 UTC
I have checked this issue with sample project attached in bug description and got exception "System.EntryPointNotFoundException" on running the app.

Screencast : http://www.screencast.com/t/jRVWHjN2uwb

Application Output : https://gist.github.com/Udham1/b0ce4bbee2e8043fe24a

Environment Info : 

=== Xamarin Studio ===

Version 5.5.4 (build 15)
Installation UUID: ce927b2a-2c07-44c5-b186-09cfdafba6dc
Runtime:
	Mono 3.12.0 ((detached/a813491)
	GTK+ 2.24.23 (Raleigh theme)

	Package version: 312000068

=== Apple Developer Tools ===

Xcode 6.1.1 (6611)
Build 6A2008a

=== Xamarin.iOS ===

Version: 8.4.0.47 (Enterprise Edition)
Hash: 7244769
Branch: 
Build date: 2014-12-11 14:54:30-0500

=== Build Information ===

Release ID: 505040015
Git revision: f93940a35458a18052f1a25e106e62ca970d9c40
Build date: 2014-11-19 15:32:41-05
Xamarin addins: dc23cbd91a3a0e1d326328e1229e86c942a49ec8

=== Operating System ===

Mac OS X 10.9.4
Darwin Xamarin76s-Mac-mini.local 13.3.0 Darwin Kernel Version 13.3.0
    Tue Jun  3 21:27:35 PDT 2014
    root:xnu-2422.110.17~1/RELEASE_X86_64 x86_64
Comment 2 Sebastien Pouliot 2014-12-19 10:18:14 UTC
That's by design. In .NET the [DllImport] attribute does not work on non-exported functions.

In the case of iOS (static libs) then once the native linker has created the final executable then `test` because a local symbol.

$ nm ./bin/iPhoneSimulator/Debug/pinvoke.app/pinvoke | grep _test
...
00270320 t _test
00270300 T _test2

However this is still the same mono/.net logic that will execute to find/call pinvoked methods.

IOW if the symbol is hidden then mono won't be able (at runtime) to resolve it's address. Without the address it's not possible to call it and that will result in the EntryPointNotFoundException.
Comment 3 Mikalai 2014-12-20 02:09:55 UTC
How about failing at link time then? or maybe an option to force export this symbol?

nm lists this symbol as global, and ld happily links them (look at main.c in attached sample).

$nm -g libtest.a

libtest.a(i386.o) (for architecture i386):
00000020 T _test
00000000 T _test2

libtest.a(armv7.o) (for architecture armv7):
00000010 T _test
00000000 T _test2
Comment 4 Mikalai 2014-12-20 02:16:24 UTC
Right now we need to write an wrapper for such static library that just forward calls like 

int test_w(int a, int b)
{
    _test(a, b);
}

or just remove that bit from symbol definitions by patching .a file.

Both options aren't very friendly
Comment 5 Sebastien Pouliot 2014-12-20 10:56:52 UTC
If the question is "how you can use those hidden symbols?" then the simplest thing to do is the "re-export" them, like [1].

You can ask the native linker to create aliases for a symbols. That alias will not be hidden and you'll be able tu use it. E,g, add this option to your "Additional mtouch arguments" of your project's options.

>    -gcc_flags="-Xlinker -alias -Xlinker _test -Xlinker _test3"

and then use "test3" in the [DllImport] of your application. That has the advantage of not modifying the .a file and the alias is specific to your project configuration.


Notes:

* that the native linker (ld) is an Apple provided tool (that we cannot change);

* there's generally a reason why the symbols are hidden (but the original developer). Automatically exposing them is not good idea;


[1] http://stackoverflow.com/a/10641759/220643
Comment 6 Rolf Bjarne Kvinge [MSFT] 2014-12-22 08:33:33 UTC
An alternative is to pass this as an additional mtouch argument:

   --dlsym:false

That will resolve all the DllImport symbols at link time instead of at build time. This is a global setting, and may not work, because (unfortunately) it's quite common to have DllImports that point to functions that don't exist in iOS (which would cause link errors as well).

nm will also show the 'private' part if you pass the -m flag:

> nm -mg /Users/rolf/Downloads/pinvoke/pinvoke/libtest.a 

/Users/rolf/Downloads/pinvoke/pinvoke/libtest.a(i386.o) (for architecture i386):
00000020 (__TEXT,__text) private external _test
00000000 (__TEXT,__text) external _test2

/Users/rolf/Downloads/pinvoke/pinvoke/libtest.a(armv7.o) (for architecture armv7):
00000010 (__TEXT,__text) private external [Thumb] _test
00000000 (__TEXT,__text) external [Thumb] _test2