Skip to content

Commit ddd6385

Browse files
committed
feat(natsock): patch Netty's native epoll transport library by symbol
1 parent 763d4db commit ddd6385

3 files changed

Lines changed: 47 additions & 2 deletions

File tree

‎ddprof-lib/src/main/cpp/libraryPatcher.h‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,8 @@ typedef struct _socketPatchedLibrary {
4040
enum SocketPatchTarget : u8 {
4141
SOCKET_PATCH_NONE = 0,
4242
SOCKET_PATCH_STANDARD_JDK_NETWORK,
43-
SOCKET_PATCH_IBM_JCL_BRIDGE
43+
SOCKET_PATCH_IBM_JCL_BRIDGE,
44+
SOCKET_PATCH_NETTY_NATIVE_EPOLL
4445
};
4546

4647
const int SOCKET_BASE_TABLE_SIZE = MAX_NATIVE_LIBS * 2;

‎ddprof-lib/src/main/cpp/libraryPatcher_linux.cpp‎

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,21 @@ static const char* library_basename(const char* path) {
5252

5353
static SocketPatchTarget socket_patch_target_for_library(
5454
CodeCache* lib, const char* name, bool in_jdk_directory) {
55-
if (lib == nullptr || name == nullptr || !in_jdk_directory) {
55+
if (lib == nullptr || name == nullptr) {
56+
return SOCKET_PATCH_NONE;
57+
}
58+
59+
// Netty's native epoll transport ships its own .so outside the JDK's lib
60+
// directory, so it is checked ahead of the in_jdk_directory gate below.
61+
// Detection is by exported symbol rather than basename because the .so
62+
// filename is relocated under shading (e.g. grpc-netty-shaded), while the
63+
// JNI_OnLoad_/JNI_OnUnload_ suffix is not.
64+
if (lib->findSymbol("JNI_OnLoad_netty_transport_native_epoll") != nullptr &&
65+
lib->findSymbol("JNI_OnUnload_netty_transport_native_epoll") != nullptr) {
66+
return SOCKET_PATCH_NETTY_NATIVE_EPOLL;
67+
}
68+
69+
if (!in_jdk_directory) {
5670
return SOCKET_PATCH_NONE;
5771
}
5872

‎ddprof-lib/src/test/cpp/nativeSocketInterposer_ut.cpp‎

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1103,6 +1103,36 @@ TEST(LibraryPatcherSocketStateTest,
11031103
}
11041104
}
11051105

1106+
TEST(LibraryPatcherSocketStateTest, AdmitsNettyNativeEpollBySymbolOutsideJdkDirectory) {
1107+
CodeCache netty("libnetty_transport_native_epoll_x86_64.so");
1108+
CodeCache netty_shaded("libio_grpc_netty_shaded_netty_transport_native_epoll_x86_64.so");
1109+
CodeCache netty_partial("libnetty_transport_native_epoll_x86_64.so");
1110+
1111+
char marker_addresses[2] = {};
1112+
netty.add(&marker_addresses[0], 1, "JNI_OnLoad_netty_transport_native_epoll");
1113+
netty.add(&marker_addresses[1], 1, "JNI_OnUnload_netty_transport_native_epoll");
1114+
netty_shaded.add(&marker_addresses[0], 1, "JNI_OnLoad_netty_transport_native_epoll");
1115+
netty_shaded.add(&marker_addresses[1], 1, "JNI_OnUnload_netty_transport_native_epoll");
1116+
netty_partial.add(&marker_addresses[0], 1, "JNI_OnLoad_netty_transport_native_epoll");
1117+
1118+
// Admitted even though it is not located in the JDK's own lib directory,
1119+
// and regardless of the .so's basename (shading relocates the filename).
1120+
EXPECT_EQ(SOCKET_PATCH_NETTY_NATIVE_EPOLL,
1121+
LibraryPatcher::socket_patch_target_for_test(
1122+
&netty, "libnetty_transport_native_epoll_x86_64.so", false));
1123+
EXPECT_EQ(SOCKET_PATCH_NETTY_NATIVE_EPOLL,
1124+
LibraryPatcher::socket_patch_target_for_test(
1125+
&netty_shaded,
1126+
"libio_grpc_netty_shaded_netty_transport_native_epoll_x86_64.so",
1127+
false));
1128+
1129+
// Requires both symbols, mirroring the IBM JCL bridge's all-or-nothing check.
1130+
EXPECT_EQ(SOCKET_PATCH_NONE,
1131+
LibraryPatcher::socket_patch_target_for_test(
1132+
&netty_partial,
1133+
"libnetty_transport_native_epoll_x86_64.so", false));
1134+
}
1135+
11061136
TEST_F(LibraryPatcherImportTest, PatchesAndRestoresEveryImportLocation) {
11071137
initializeImports(3);
11081138
void* originals[3] = {imports[0], imports[1], imports[2]};

0 commit comments

Comments
 (0)