/* Copyright (c) 2013 Xamarin, Inc and contributors * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the * "Software"), to deal in the Software without restriction, including * without limitation the rights to use, copy, modify, merge, publish, * distribute, sublicense, and/or sell copies of the Software, and to * permit persons to whom the Software is furnished to do so, subject to * the following conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ using System; using System.Collections.Generic; using System.IO; using System.Reflection; using System.Runtime.InteropServices; namespace CppSharp { public static class SymbolResolver { static readonly string[] formats; static readonly Func loadImage; static readonly Func resolveSymbol; static SymbolResolver () { switch (Environment.OSVersion.Platform) { case PlatformID.Unix: case PlatformID.MacOSX: loadImage = dlopen; resolveSymbol = dlsym; formats = new[] { "{0}", "{0}.so", "{0}.dylib", "lib{0}.so", "lib{0}.dylib", "{0}.bundle" }; break; default: loadImage = LoadLibrary; resolveSymbol = GetProcAddress; formats = new[] { "{0}", "{0}.dll" }; break; } } public static IntPtr LoadImage (ref string name) { var pathValues = Environment.GetEnvironmentVariable("PATH"); var paths = new List(pathValues == null ? new string[0] : pathValues.Split(Path.PathSeparator)); paths.Insert(0, Directory.GetCurrentDirectory()); paths.Insert(0, Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location)); foreach (var format in formats) { // Search the Current or specified directory for the library string filename = string.Format(format, name); string attempted = null; foreach (var path in paths) { var fullPath = Path.Combine(path, filename); if (File.Exists(fullPath)) { attempted = fullPath; break; } } if (!File.Exists(attempted)) continue; var ptr = loadImage (attempted); if (ptr == IntPtr.Zero) continue; name = attempted; return ptr; } return IntPtr.Zero; } public static IntPtr ResolveSymbol (string name, string symbol) { var image = LoadImage(ref name); return ResolveSymbol(image, symbol); } public static IntPtr ResolveSymbol (IntPtr image, string symbol) { if (image != IntPtr.Zero) return resolveSymbol (image, symbol); return IntPtr.Zero; } #region POSIX private const int RTLD_LAZY = 0x1; static IntPtr dlopen (string path) { return dlopen (path, RTLD_LAZY); } [DllImport ("dl", CharSet=CharSet.Ansi)] static extern IntPtr dlopen (string path, int flags); [DllImport ("dl", CharSet=CharSet.Ansi)] static extern IntPtr dlsym (IntPtr handle, string symbol); #endregion #region Win32 [DllImport("kernel32", SetLastError=true)] static extern IntPtr LoadLibrary (string lpFileName); [DllImport("kernel32", CharSet=CharSet.Ansi, ExactSpelling=true, SetLastError=true)] static extern IntPtr GetProcAddress (IntPtr hModule, string procName); #endregion } }