mirror of
https://github.com/openjdk/jdk.git
synced 2026-08-03 06:35:31 +00:00
8387324: jlink --strip-debug should filter external debug symbols
Reviewed-by: sgehwolf, dbalek, clanger
This commit is contained in:
parent
94e1b11e7d
commit
e04f4dd46f
@ -1,4 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2019, 2026, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2019, Red Hat, Inc.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
@ -27,12 +28,13 @@ package jdk.tools.jlink.internal.plugins;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import jdk.tools.jlink.internal.Platform;
|
||||
import jdk.tools.jlink.internal.PluginRepository;
|
||||
import jdk.tools.jlink.internal.ResourcePoolManager;
|
||||
import jdk.tools.jlink.internal.ResourcePoolManager.ResourcePoolImpl;
|
||||
import jdk.tools.jlink.plugin.Plugin;
|
||||
import jdk.tools.jlink.plugin.ResourcePool;
|
||||
import jdk.tools.jlink.plugin.ResourcePoolBuilder;
|
||||
import jdk.tools.jlink.plugin.ResourcePoolModule;
|
||||
|
||||
/**
|
||||
* Combined debug stripping plugin: Java debug attributes and native debug
|
||||
@ -43,6 +45,7 @@ public final class DefaultStripDebugPlugin extends AbstractPlugin {
|
||||
|
||||
private static final String STRIP_NATIVE_DEBUG_PLUGIN = "strip-native-debug-symbols";
|
||||
private static final String EXCLUDE_DEBUGINFO = "exclude-debuginfo-files";
|
||||
private static final String EXCLUDE_FILES_PLUGIN = "exclude-files";
|
||||
|
||||
private final Plugin javaStripPlugin;
|
||||
private final NativePluginFactory stripNativePluginFactory;
|
||||
@ -68,26 +71,46 @@ public final class DefaultStripDebugPlugin extends AbstractPlugin {
|
||||
@Override
|
||||
public ResourcePool transform(ResourcePool in, ResourcePoolBuilder out) {
|
||||
Plugin stripNativePlugin = stripNativePluginFactory.create();
|
||||
if (stripNativePlugin != null) {
|
||||
Map<String, String> stripNativeConfig = Map.of(
|
||||
STRIP_NATIVE_DEBUG_PLUGIN, EXCLUDE_DEBUGINFO);
|
||||
stripNativePlugin.configure(stripNativeConfig);
|
||||
|
||||
if (!isJavaStripPluginEnabled) {
|
||||
return stripNativePlugin.transform(in, out);
|
||||
}
|
||||
String pattern = debugFilePattern(in);
|
||||
ExcludeFilesPlugin excludeFilesPlugin = new ExcludeFilesPlugin();
|
||||
excludeFilesPlugin.configure(Map.of(EXCLUDE_FILES_PLUGIN, pattern));
|
||||
|
||||
ResourcePoolManager outRes =
|
||||
new ResourcePoolManager(in.byteOrder(),
|
||||
((ResourcePoolImpl)in).getStringTable());
|
||||
ResourcePool strippedJava = javaStripPlugin.transform(in,
|
||||
outRes.resourcePoolBuilder());
|
||||
return stripNativePlugin.transform(strippedJava, out);
|
||||
} else if (isJavaStripPluginEnabled) {
|
||||
return javaStripPlugin.transform(in, out);
|
||||
} else {
|
||||
return in;
|
||||
ResourcePool result = in;
|
||||
if (isJavaStripPluginEnabled) {
|
||||
result = pipe(result, javaStripPlugin);
|
||||
}
|
||||
if (stripNativePlugin != null) {
|
||||
stripNativePlugin.configure(Map.of(STRIP_NATIVE_DEBUG_PLUGIN, EXCLUDE_DEBUGINFO));
|
||||
result = pipe(result, stripNativePlugin);
|
||||
}
|
||||
return excludeFilesPlugin.transform(result, out);
|
||||
}
|
||||
|
||||
// Returns the glob pattern for debug files matching the target platform.
|
||||
// Mirrors the per-OS exclusion logic in make/CreateJmods.gmk.
|
||||
private static String debugFilePattern(ResourcePool in) {
|
||||
Platform platform;
|
||||
try {
|
||||
String tp = in.moduleView()
|
||||
.findModule("java.base")
|
||||
.map(ResourcePoolModule::targetPlatform)
|
||||
.orElse(null);
|
||||
platform = tp != null ? Platform.parsePlatform(tp) : Platform.runtime();
|
||||
} catch (IllegalArgumentException e) {
|
||||
platform = Platform.runtime();
|
||||
}
|
||||
return switch (platform.os()) {
|
||||
case WINDOWS -> "**.pdb,**.map,**.diz";
|
||||
case MACOS -> "**.dSYM/**,**.diz";
|
||||
default -> "**.debuginfo,**.diz"; // Linux, AIX
|
||||
};
|
||||
}
|
||||
|
||||
private ResourcePool pipe(ResourcePool pool, Plugin plugin) {
|
||||
ResourcePoolManager mgr = new ResourcePoolManager(
|
||||
pool.byteOrder(), ((ResourcePoolManager.ResourcePoolImpl)pool).getStringTable());
|
||||
return plugin.transform(pool, mgr.resourcePoolBuilder());
|
||||
}
|
||||
|
||||
public interface NativePluginFactory {
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2019, 2026, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2019, Red Hat, Inc.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
@ -23,6 +24,7 @@
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import jdk.tools.jlink.internal.Platform;
|
||||
import jdk.tools.jlink.internal.ResourcePoolManager;
|
||||
import jdk.tools.jlink.internal.plugins.DefaultStripDebugPlugin;
|
||||
import jdk.tools.jlink.internal.plugins.DefaultStripDebugPlugin.NativePluginFactory;
|
||||
@ -51,12 +53,23 @@ public class DefaultStripDebugPluginTest {
|
||||
DefaultStripDebugPlugin plugin = new DefaultStripDebugPlugin(javaPlugin,
|
||||
nativeFactory);
|
||||
ResourcePoolManager inManager = new ResourcePoolManager();
|
||||
inManager.add(ResourcePoolEntry.create(MockStripPlugin.DEBUGINFO_PATH,
|
||||
ResourcePoolEntry.Type.NATIVE_LIB, new byte[]{0, 1, 2, 3}));
|
||||
inManager.add(ResourcePoolEntry.create(MockStripPlugin.DIZ_PATH,
|
||||
ResourcePoolEntry.Type.NATIVE_LIB, new byte[]{0, 1, 2, 3}));
|
||||
ResourcePoolManager outManager = new ResourcePoolManager();
|
||||
ResourcePool pool = plugin.transform(inManager.resourcePool(),
|
||||
inManager.resourcePoolBuilder());
|
||||
outManager.resourcePoolBuilder());
|
||||
if (!pool.findEntry(MockStripPlugin.JAVA_PATH).isPresent() ||
|
||||
!pool.findEntry(MockStripPlugin.NATIVE_PATH).isPresent()) {
|
||||
throw new AssertionError("Expected both native and java to get called");
|
||||
}
|
||||
if (pool.findEntry(MockStripPlugin.DEBUGINFO_PATH).isPresent()) {
|
||||
throw new AssertionError(".debuginfo file should have been excluded");
|
||||
}
|
||||
if (pool.findEntry(MockStripPlugin.DIZ_PATH).isPresent()) {
|
||||
throw new AssertionError(".diz file should have been excluded");
|
||||
}
|
||||
}
|
||||
|
||||
public void testNoNativeStripPluginPresent() {
|
||||
@ -66,11 +79,22 @@ public class DefaultStripDebugPluginTest {
|
||||
DefaultStripDebugPlugin plugin = new DefaultStripDebugPlugin(javaPlugin,
|
||||
nativeFactory);
|
||||
ResourcePoolManager inManager = new ResourcePoolManager();
|
||||
inManager.add(ResourcePoolEntry.create(MockStripPlugin.DEBUGINFO_PATH,
|
||||
ResourcePoolEntry.Type.NATIVE_LIB, new byte[]{0, 1, 2, 3}));
|
||||
inManager.add(ResourcePoolEntry.create(MockStripPlugin.DIZ_PATH,
|
||||
ResourcePoolEntry.Type.NATIVE_LIB, new byte[]{0, 1, 2, 3}));
|
||||
ResourcePoolManager outManager = new ResourcePoolManager();
|
||||
ResourcePool pool = plugin.transform(inManager.resourcePool(),
|
||||
inManager.resourcePoolBuilder());
|
||||
outManager.resourcePoolBuilder());
|
||||
if (!pool.findEntry(MockStripPlugin.JAVA_PATH).isPresent()) {
|
||||
throw new AssertionError("Expected java strip plugin to get called");
|
||||
}
|
||||
if (pool.findEntry(MockStripPlugin.DEBUGINFO_PATH).isPresent()) {
|
||||
throw new AssertionError(".debuginfo file should have been excluded");
|
||||
}
|
||||
if (pool.findEntry(MockStripPlugin.DIZ_PATH).isPresent()) {
|
||||
throw new AssertionError(".diz file should have been excluded");
|
||||
}
|
||||
}
|
||||
|
||||
// Disable embedded strip Java plugin, with native plugin present.
|
||||
@ -84,12 +108,23 @@ public class DefaultStripDebugPluginTest {
|
||||
plugin.enableJavaStripPlugin(false);
|
||||
|
||||
ResourcePoolManager inManager = new ResourcePoolManager();
|
||||
inManager.add(ResourcePoolEntry.create(MockStripPlugin.DEBUGINFO_PATH,
|
||||
ResourcePoolEntry.Type.NATIVE_LIB, new byte[]{0, 1, 2, 3}));
|
||||
inManager.add(ResourcePoolEntry.create(MockStripPlugin.DIZ_PATH,
|
||||
ResourcePoolEntry.Type.NATIVE_LIB, new byte[]{0, 1, 2, 3}));
|
||||
ResourcePoolManager outManager = new ResourcePoolManager();
|
||||
ResourcePool pool = plugin.transform(inManager.resourcePool(),
|
||||
inManager.resourcePoolBuilder());
|
||||
outManager.resourcePoolBuilder());
|
||||
if (pool.findEntry(MockStripPlugin.JAVA_PATH).isPresent() ||
|
||||
!pool.findEntry(MockStripPlugin.NATIVE_PATH).isPresent()) {
|
||||
throw new AssertionError("Expected only native to get called");
|
||||
}
|
||||
if (pool.findEntry(MockStripPlugin.DEBUGINFO_PATH).isPresent()) {
|
||||
throw new AssertionError(".debuginfo file should have been excluded");
|
||||
}
|
||||
if (pool.findEntry(MockStripPlugin.DIZ_PATH).isPresent()) {
|
||||
throw new AssertionError(".diz file should have been excluded");
|
||||
}
|
||||
}
|
||||
|
||||
// Disable embedded strip Java plugin, and without native plugin present.
|
||||
@ -101,12 +136,23 @@ public class DefaultStripDebugPluginTest {
|
||||
nativeFactory);
|
||||
plugin.enableJavaStripPlugin(false);
|
||||
ResourcePoolManager inManager = new ResourcePoolManager();
|
||||
inManager.add(ResourcePoolEntry.create(MockStripPlugin.DEBUGINFO_PATH,
|
||||
ResourcePoolEntry.Type.NATIVE_LIB, new byte[]{0, 1, 2, 3}));
|
||||
inManager.add(ResourcePoolEntry.create(MockStripPlugin.DIZ_PATH,
|
||||
ResourcePoolEntry.Type.NATIVE_LIB, new byte[]{0, 1, 2, 3}));
|
||||
ResourcePoolManager outManager = new ResourcePoolManager();
|
||||
ResourcePool pool = plugin.transform(inManager.resourcePool(),
|
||||
inManager.resourcePoolBuilder());
|
||||
outManager.resourcePoolBuilder());
|
||||
if (pool.findEntry(MockStripPlugin.JAVA_PATH).isPresent() ||
|
||||
pool.findEntry(MockStripPlugin.NATIVE_PATH).isPresent()) {
|
||||
throw new AssertionError("Expected both native and java not called");
|
||||
}
|
||||
if (pool.findEntry(MockStripPlugin.DEBUGINFO_PATH).isPresent()) {
|
||||
throw new AssertionError(".debuginfo file should have been excluded");
|
||||
}
|
||||
if (pool.findEntry(MockStripPlugin.DIZ_PATH).isPresent()) {
|
||||
throw new AssertionError(".diz file should have been excluded");
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
@ -121,10 +167,25 @@ public class DefaultStripDebugPluginTest {
|
||||
|
||||
private static final String NATIVE_PATH = "/foo/lib/test.so.debug";
|
||||
private static final String JAVA_PATH = "/foo/TestClass.class";
|
||||
// Platform-appropriate debug file paths, matching the patterns chosen by
|
||||
// DefaultStripDebugPlugin.debugFilePattern() for the runtime platform.
|
||||
static final String DEBUGINFO_PATH = platformDebugPath();
|
||||
static final String DIZ_PATH = "/foo/lib/libfoo.diz";
|
||||
private static final String STRIP_NATIVE_NAME = "strip-native-debug-symbols";
|
||||
private static final String OMIT_ARG = "exclude-debuginfo-files";
|
||||
private final boolean isNative;
|
||||
|
||||
private static String platformDebugPath() {
|
||||
String platform = Platform.runtime().toString();
|
||||
if (platform.startsWith("windows")) {
|
||||
return "/foo/bin/libfoo.pdb";
|
||||
} else if (platform.startsWith("macos")) {
|
||||
return "/foo/lib/libfoo.dylib.dSYM/Contents/Resources/DWARF/libfoo.dylib";
|
||||
} else {
|
||||
return "/foo/lib/libfoo.so.debuginfo";
|
||||
}
|
||||
}
|
||||
|
||||
MockStripPlugin(boolean isNative) {
|
||||
this.isNative = isNative;
|
||||
}
|
||||
@ -153,8 +214,7 @@ public class DefaultStripDebugPluginTest {
|
||||
resPath = NATIVE_PATH;
|
||||
type = Type.NATIVE_LIB;
|
||||
}
|
||||
ResourcePoolEntry entry = createMockEntry(resPath, type);
|
||||
out.add(entry);
|
||||
out.add(createMockEntry(resPath, type));
|
||||
return out.build();
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user