Skip to content

Commit

Permalink
Add support for using versionned symbols
Browse files Browse the repository at this point in the history
This is a follow-up to jnr/jffi#66 and use the
new API to make it possible to access versioned symbols in a shared
library.
  • Loading branch information
smortex committed Apr 10, 2019
1 parent 8a2650a commit b2d5b2c
Show file tree
Hide file tree
Showing 8 changed files with 143 additions and 5 deletions.
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();
}
19 changes: 17 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,25 @@ 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);
System.out.println(searchName + " " + searchVersion);
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
70 changes: 70 additions & 0 deletions src/test/java/jnr/ffi/VersionTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
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;

@BeforeClass
public static void setUpClass() throws Exception {
testlib = TstUtil.loadTestLib(TestLib.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);
}
}

0 comments on commit b2d5b2c

Please sign in to comment.