Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for using versionned symbols #189

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion libtest/GNUmakefile
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ JFLAGS = -fno-omit-frame-pointer -fno-strict-aliasing
OFLAGS = -O2 $(JFLAGS)
WFLAGS = -W -Wall -Wno-unused -Wno-parentheses
PICFLAGS = -fPIC
SOFLAGS = -shared -Wl,-O1
SOFLAGS = -shared -Wl,-O1 -Wl,--version-script,$(SRC_DIR)/libtest.map
LDFLAGS += $(SOFLAGS)

IFLAGS = -I"$(BUILD_DIR)"
Expand Down
14 changes: 14 additions & 0 deletions libtest/VersionedSymbols.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
int
old_answer(void)
{
return 41;
}

int
new_answer(void)
{
return 42;
}

__asm__(".symver old_answer,answer@VERS_1.0");
__asm__(".symver new_answer,answer@@VERS_1.1");
2 changes: 2 additions & 0 deletions libtest/libtest.map
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
VERS_1.0 {};
VERS_1.1 {};
12 changes: 12 additions & 0 deletions src/main/java/jnr/ffi/annotations/Function.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package jnr.ffi.annotations;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Function {
String value();
}
12 changes: 12 additions & 0 deletions src/main/java/jnr/ffi/annotations/Version.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package jnr.ffi.annotations;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Version {
String value();
}
18 changes: 16 additions & 2 deletions src/main/java/jnr/ffi/provider/jffi/AsmLibraryLoader.java
Original file line number Diff line number Diff line change
Expand Up @@ -152,10 +152,24 @@ private <T> T generateInterfaceImpl(final NativeLibrary library, Class<T> interf
continue;
}

String functionName = functionMapper.mapFunctionName(function.name(), new NativeFunctionMapperContext(library, function.annotations()));
String searchName = function.name();
String searchVersion = null;

for (java.lang.annotation.Annotation a : function.annotations()) {
if (a.annotationType() == jnr.ffi.annotations.Function.class) {
jnr.ffi.annotations.Function ann = (jnr.ffi.annotations.Function) a;
searchName = ann.value();
}
if (a.annotationType() == jnr.ffi.annotations.Version.class) {
jnr.ffi.annotations.Version ann = (jnr.ffi.annotations.Version) a;
searchVersion = ann.value();
}
}

String functionName = functionMapper.mapFunctionName(searchName, new NativeFunctionMapperContext(library, function.annotations()));

try {
long functionAddress = library.findSymbolAddress(functionName);
long functionAddress = library.findSymbolAddress(functionName, searchVersion);

FromNativeContext resultContext = new MethodResultContext(runtime, function.getMethod());
SignatureType signatureType = DefaultSignatureType.create(function.getMethod().getReturnType(), resultContext);
Expand Down
17 changes: 15 additions & 2 deletions src/main/java/jnr/ffi/provider/jffi/NativeLibrary.java
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,17 @@ private String locateLibrary(String libraryName) {
}

long getSymbolAddress(String name) {
return getSymbolAddress(name, null);
}

long getSymbolAddress(String name, String version) {
for (com.kenai.jffi.Library l : getNativeLibraries()) {
long address = l.getSymbolAddress(name);
long address;
if (version != null)
address = l.getSymbolAddressWithVersion(name, version);
else
address = l.getSymbolAddress(name);

if (address != 0) {
return address;
}
Expand All @@ -56,7 +65,11 @@ long getSymbolAddress(String name) {
}

long findSymbolAddress(String name) {
long address = getSymbolAddress(name);
return findSymbolAddress(name, null);
}

long findSymbolAddress(String name, String version) {
long address = getSymbolAddress(name, version);
if (address == 0) {
throw new SymbolNotFoundError(com.kenai.jffi.Library.getLastError());
}
Expand Down
83 changes: 83 additions & 0 deletions src/test/java/jnr/ffi/VersionTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
package jnr.ffi;

import jnr.ffi.annotations.Function;
import jnr.ffi.annotations.Version;

import jnr.ffi.types.*;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;
import static org.junit.Assert.*;


public class VersionTest {
public VersionTest() {
}

public static interface TestLib {
public int answer();
public int old_answer();
public int new_answer();

@Function("answer")
@Version("VERS_1.0")
public int answer_1_0();

@Function("answer")
@Version("VERS_1.1")
public int answer_1_1();
}
static TestLib testlib;

public static interface OldTestLib {
@Version("VERS_1.0")
public int answer();
}
static OldTestLib oldtestlib;

@BeforeClass
public static void setUpClass() throws Exception {
testlib = TstUtil.loadTestLib(TestLib.class);
oldtestlib = TstUtil.loadTestLib(OldTestLib.class);
}

@AfterClass
public static void tearDownClass() throws Exception {
}

@Test
public void testAnswer() {
int res = testlib.answer();
assertEquals(42, res);
}

@Test
public void testOldAnswer() {
int res = testlib.old_answer();
assertEquals(41, res);
}

@Test
public void testNewAnswer() {
int res = testlib.new_answer();
assertEquals(42, res);
}

@Test
public void testAnswer_1_0() {
int res = testlib.answer_1_0();
assertEquals(41, res);
}

@Test
public void testAnswer_1_1() {
int res = testlib.answer_1_1();
assertEquals(42, res);
}

@Test
public void oldTestAnswer() {
int res = oldtestlib.answer();
assertEquals(41, res);
}
}