Skip to content
Merged
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
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@
import com.oracle.svm.hosted.ProgressReporterJsonHelper.ResourceUsageKey;
import com.oracle.svm.hosted.c.codegen.CCompilerInvoker;
import com.oracle.svm.hosted.image.AbstractImage.NativeImageKind;
import com.oracle.svm.hosted.image.NativeImageDebugInfoStripFeature;
import com.oracle.svm.hosted.reflect.ReflectionHostedSupport;
import com.oracle.svm.hosted.util.CPUType;
import com.oracle.svm.hosted.util.DiagnosticUtils;
Expand Down Expand Up @@ -352,8 +353,8 @@ private void printExperimentalOptions(ImageClassLoader classLoader) {
/* Only check builder arguments, ignore options that were set as part of others. */
continue;
}
String origins = "";
String migrationMessage = OptionUtils.getAnnotationsByType(descriptor, OptionMigrationMessage.class).stream().map(a -> a.value()).collect(Collectors.joining(". "));
String origins;
String migrationMessage = OptionUtils.getAnnotationsByType(descriptor, OptionMigrationMessage.class).stream().map(OptionMigrationMessage::value).collect(Collectors.joining(". "));
String alternatives = "";

if (optionValue instanceof AccumulatingLocatableMultiOptionValue<?> lmov) {
Expand Down Expand Up @@ -410,7 +411,7 @@ private void printEnvironmentVariableOptions() {
if (envVarValue != null && !envVarValue.isEmpty()) {
l().printLineSeparator();
l().yellowBold().a(" ").doclink("Picked up " + SubstrateOptions.NATIVE_IMAGE_OPTIONS_ENV_VAR, "#glossary-picked-up-ni-options").reset().a(":").println();
for (String arg : JDKArgsUtils.parseArgsFromEnvVar(envVarValue, SubstrateOptions.NATIVE_IMAGE_OPTIONS_ENV_VAR, msg -> UserError.abort(msg))) {
for (String arg : JDKArgsUtils.parseArgsFromEnvVar(envVarValue, SubstrateOptions.NATIVE_IMAGE_OPTIONS_ENV_VAR, UserError::abort)) {
l().a(" - '%s'", arg).println();
}
}
Expand Down Expand Up @@ -597,6 +598,7 @@ public void printCreationEnd(int imageFileSize, int heapObjectCount, long imageH
recordJsonMetric(ImageDetailKey.IMAGE_HEAP_RESOURCE_COUNT, numResources);
l().a(format, ByteFormattingUtil.bytesToHuman(imageHeapSize), Utils.toPercentage(imageHeapSize, imageFileSize))
.doclink("image heap", "#glossary-image-heap").a(":%,9d objects and %,d resources", heapObjectCount, numResources).println();
long otherBytes = imageFileSize - codeAreaSize - imageHeapSize;
if (debugInfoSize > 0) {
recordJsonMetric(ImageDetailKey.DEBUG_INFO_SIZE, debugInfoSize); // Optional metric
DirectPrinter l = l().a(format, ByteFormattingUtil.bytesToHuman(debugInfoSize), Utils.toPercentage(debugInfoSize, imageFileSize))
Expand All @@ -606,8 +608,12 @@ public void printCreationEnd(int imageFileSize, int heapObjectCount, long imageH
l.a(" generated in %.1fs", Utils.millisToSeconds(debugInfoTimer.getTotalTime()));
}
l.println();
if (!ImageSingletons.lookup(NativeImageDebugInfoStripFeature.class).hasStrippedSuccessfully()) {
// Only subtract if debug info is embedded in file (not stripped).
otherBytes -= debugInfoSize;
}
}
long otherBytes = imageFileSize - codeAreaSize - imageHeapSize - debugInfoSize;
assert otherBytes >= 0 : "Other bytes should never be negative: " + otherBytes;
recordJsonMetric(ImageDetailKey.IMAGE_HEAP_SIZE, imageHeapSize);
recordJsonMetric(ImageDetailKey.TOTAL_SIZE, imageFileSize);
recordJsonMetric(ImageDetailKey.CODE_AREA_SIZE, codeAreaSize);
Expand Down Expand Up @@ -785,9 +791,7 @@ private void createAdditionalArtifacts(String imageName, NativeImageGenerator ge

private void createAdditionalArtifactsOnSuccess(BuildArtifacts artifacts, NativeImageGenerator generator, OptionValues parsedHostedOptions) {
Optional<Path> buildOutputJSONFile = SubstrateOptions.BuildOutputJSONFile.getValue(parsedHostedOptions).lastValue();
if (buildOutputJSONFile.isPresent()) {
artifacts.add(ArtifactType.BUILD_INFO, reportBuildOutput(buildOutputJSONFile.get()));
}
buildOutputJSONFile.ifPresent(path -> artifacts.add(ArtifactType.BUILD_INFO, reportBuildOutput(path)));
if (generator.getBigbang() != null && ImageBuildStatistics.Options.CollectImageBuildStatistics.getValue(parsedHostedOptions)) {
artifacts.add(ArtifactType.BUILD_INFO, reportImageBuildStatistics());
}
Expand Down Expand Up @@ -945,10 +949,7 @@ private static String truncateClassOrPackageName(String classOrPackageName) {
}
}

private static class GCStats {
private final long totalCount;
private final long totalTimeMillis;

private record GCStats(long totalCount, long totalTimeMillis) {
private static GCStats getCurrent() {
long totalCount = 0;
long totalTime = 0;
Expand All @@ -964,11 +965,6 @@ private static GCStats getCurrent() {
}
return new GCStats(totalCount, totalTime);
}

GCStats(long totalCount, long totalTimeMillis) {
this.totalCount = totalCount;
this.totalTimeMillis = totalTimeMillis;
}
}

public abstract static class ReporterClosable implements AutoCloseable {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -177,11 +177,12 @@ protected final void write(DebugContext context, Path outputFile) {
throw shouldNotReachHere(ex);
}
debugInfoSize = 0;
String debugIdentifier = OS.getCurrent() == OS.DARWIN ? "__debug" : ".debug";
for (Element e : objectFile.getElements()) {
String name = e.getName();
if (name.contains(debugIdentifier) && !name.startsWith(".rela")) {
debugInfoSize += e.getMemSize(objectFile.getDecisionsByElement());
if (!OS.DARWIN.isCurrent()) { // debug info not available on Darwin
for (Element e : objectFile.getElements()) {
String name = e.getName();
if (name.contains(".debug") && !name.startsWith(".rela")) {
debugInfoSize += e.getMemSize(objectFile.getDecisionsByElement());
}
}
}
if (NativeImageOptions.PrintImageElementSizes.getValue()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,29 +30,27 @@
import org.graalvm.nativeimage.Platform;
import org.graalvm.nativeimage.impl.InternalPlatform;

import com.oracle.graal.pointsto.util.GraalAccess;
import com.oracle.objectfile.ObjectFile;
import com.oracle.svm.core.BuildArtifacts;
import com.oracle.svm.core.BuildArtifacts.ArtifactType;
import com.oracle.svm.core.SubstrateOptions;
import com.oracle.svm.core.feature.AutomaticallyRegisteredFeature;
import com.oracle.svm.core.feature.InternalFeature;
import com.oracle.svm.core.option.HostedOptionValues;
import com.oracle.svm.core.util.InterruptImageBuilding;
import com.oracle.svm.core.util.UserError;
import com.oracle.svm.core.util.VMError;
import com.oracle.svm.hosted.FeatureImpl.AfterImageWriteAccessImpl;
import com.oracle.svm.hosted.c.util.FileUtils;
import com.oracle.svm.util.LogUtils;

import jdk.graal.compiler.core.common.SuppressFBWarnings;
import jdk.graal.compiler.debug.DebugContext;
import jdk.graal.compiler.debug.DebugContext.Builder;
import jdk.graal.compiler.debug.Indent;
import jdk.graal.compiler.printer.GraalDebugHandlersFactory;

@AutomaticallyRegisteredFeature
public class NativeImageDebugInfoStripFeature implements InternalFeature {

private Boolean hasStrippedSuccessfully = null;

@Override
public boolean isInConfiguration(IsInConfigurationAccess access) {
return SubstrateOptions.StripDebugInfo.getValue();
Expand All @@ -62,14 +60,14 @@ public boolean isInConfiguration(IsInConfigurationAccess access) {
@Override
public void afterImageWrite(AfterImageWriteAccess access) {
AfterImageWriteAccessImpl accessImpl = (AfterImageWriteAccessImpl) access;
DebugContext debugContext = new Builder(HostedOptionValues.singleton(), new GraalDebugHandlersFactory(GraalAccess.getOriginalSnippetReflection())).build();
try (Indent indent = debugContext.logAndIndent("Stripping debuginfo")) {
try (Indent indent = accessImpl.getDebugContext().logAndIndent("Stripping debuginfo")) {
switch (ObjectFile.getNativeFormat()) {
case ELF:
stripLinux(accessImpl);
hasStrippedSuccessfully = stripLinux(accessImpl);
break;
case PECOFF:
// debug info is always "stripped" to a pdb file
// debug info is always "stripped" to a pdb file by linker
hasStrippedSuccessfully = true;
break;
case MACH_O:
// Not supported. See warning in SubstrateOptions.validateStripDebugInfo
Expand All @@ -80,14 +78,21 @@ public void afterImageWrite(AfterImageWriteAccess access) {
}
}

public boolean hasStrippedSuccessfully() {
if (hasStrippedSuccessfully == null) {
throw VMError.shouldNotReachHere("hasStrippedSuccessfully not available yet");
}
return hasStrippedSuccessfully;
}

@SuppressFBWarnings(value = "", justification = "FB reports null pointer dereferencing although it is not possible in this case.")
private static void stripLinux(AfterImageWriteAccessImpl accessImpl) {
private static boolean stripLinux(AfterImageWriteAccessImpl accessImpl) {
String objcopyExe = "objcopy";
String debugExtension = ".debug";
Path imagePath = accessImpl.getImagePath();
if (imagePath == null) {
assert !Platform.includedIn(InternalPlatform.NATIVE_ONLY.class);
return;
return false;
}

Path imageName = imagePath.getFileName();
Expand All @@ -102,6 +107,7 @@ private static void stripLinux(AfterImageWriteAccessImpl accessImpl) {

if (!objcopyAvailable) {
LogUtils.warning("%s not available. The debuginfo will remain embedded in the executable.", objcopyExe);
return false;
} else {
try {
Path outputDirectory = imagePath.getParent();
Expand All @@ -121,6 +127,7 @@ private static void stripLinux(AfterImageWriteAccessImpl accessImpl) {
/* Strip debug info only. */
FileUtils.executeCommand(objcopyExe, "--strip-debug", imageFilePath);
}
return true;
} catch (IOException e) {
throw UserError.abort("Generation of separate debuginfo file failed", e);
} catch (InterruptedException e) {
Expand Down
Loading