src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/BinaryContainer.java
Index Unified diffs Context diffs Sdiffs Wdiffs Patch New Old Previous File Next File hotspot Sdiff src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat

src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/BinaryContainer.java

Print this page


   1 /*
   2  * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  */
  23 
  24 package jdk.tools.jaotc.binformat;
  25 
  26 import static org.graalvm.compiler.hotspot.meta.HotSpotAOTProfilingPlugin.Options.TieredAOT;
  27 
  28 import java.io.ByteArrayOutputStream;
  29 import java.io.DataOutputStream;
  30 import java.io.IOException;
  31 import java.util.ArrayList;
  32 import java.util.HashMap;
  33 import java.util.List;
  34 import java.util.Map;
  35 
  36 import jdk.tools.jaotc.binformat.Symbol.Binding;
  37 import jdk.tools.jaotc.binformat.Symbol.Kind;
  38 import jdk.tools.jaotc.binformat.elf.JELFRelocObject;


  39 import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig;
  40 
  41 /**
  42  * A format-agnostic container class that holds various components of a binary.
  43  *
  44  * <p>
  45  * This class holds information necessary to create platform-specific binary containers such as
  46  * ELFContainer for Linux and Solaris operating systems or yet-to be created MachOContainer for Mac
  47  * OS or PEContainer for MS Windows operating systems.
  48  *
  49  * <p>
  50  * Method APIs provided by this class are used to construct and populate platform-independent
  51  * contents of a binary as the first step to create a binary representation of code generated by a
  52  * compiler backend such as Graal.
  53  *
  54  * <p>
  55  * Methods to record and access code section contents, symbols and relocations are provided.
  56  */
  57 public class BinaryContainer implements SymbolTable {
  58 
  59     private final int codeSegmentSize;
  60 
  61     private final int codeEntryAlignment;
  62 
  63     /**
  64      * Container holding code bits and any other related information.
  65      */
  66     private final CodeContainer codeContainer;


 246         //@formatter:on
 247     };
 248 
 249     static {
 250         for (String[] entry : map) {
 251             functionNamesToAOTSymbols.put(entry[0], entry[1]);
 252         }
 253     }
 254 
 255     /**
 256      * Allocates a {@code BinaryContainer} object whose content will be generated in a file with the
 257      * prefix {@code prefix}. It also initializes internal code container, symbol table and
 258      * relocation tables.
 259      */
 260     public BinaryContainer(GraalHotSpotVMConfig config, String jvmVersion) {
 261         this.codeSegmentSize = config.codeSegmentSize;
 262         this.codeEntryAlignment = config.codeEntryAlignment;
 263 
 264         // read only, code
 265         codeContainer = new CodeContainer(".text", this);
 266         extLinkageContainer = new CodeContainer(".hotspot.linkage.plt", this);
 267 
 268         // read only, info
 269         configContainer = new ReadOnlyDataContainer(".config", this);
 270         metaspaceNamesContainer = new ReadOnlyDataContainer(".metaspace.names", this);
 271         methodsOffsetsContainer = new ReadOnlyDataContainer(".methods.offsets", this);
 272         klassesOffsetsContainer = new ReadOnlyDataContainer(".klasses.offsets", this);
 273         klassesDependenciesContainer = new ReadOnlyDataContainer(".klasses.dependencies", this);
 274 
 275         headerContainer = new HeaderContainer(jvmVersion, new ReadOnlyDataContainer(".header", this));
 276         stubsOffsetsContainer = new ReadOnlyDataContainer(".stubs.offsets", this);
 277         codeSegmentsContainer = new ReadOnlyDataContainer(".code.segments", this);
 278         constantDataContainer = new ReadOnlyDataContainer(".method.constdata", this);
 279 
 280         // needs relocation patching at load time by the loader
 281         methodMetadataContainer = new ReadOnlyDataContainer(".method.metadata", this);
 282 
 283         // writable sections
 284         metaspaceGotContainer = new ByteContainer(".metaspace.got", this);
 285         metadataGotContainer = new ByteContainer(".metadata.got", this);
 286         methodStateContainer = new ByteContainer(".method.state", this);
 287         oopGotContainer = new ByteContainer(".oop.got", this);
 288         extLinkageGOTContainer = new ByteContainer(".hotspot.linkage.got", this);
 289 
 290         addGlobalSymbols();
 291 
 292         recordConfiguration(config);
 293     }
 294 
 295     private void recordConfiguration(GraalHotSpotVMConfig config) {
 296         // @formatter:off
 297         boolean[] booleanFlags = { config.cAssertions, // Debug VM
 298                                    config.useCompressedOops,
 299                                    config.useCompressedClassPointers,
 300                                    config.compactFields,
 301                                    config.useG1GC,
 302                                    config.useCMSGC,
 303                                    config.useTLAB,
 304                                    config.useBiasedLocking,
 305                                    TieredAOT.getValue(),
 306                                    config.enableContended,
 307                                    config.restrictContended,
 308         };


 473         Symbol gotSymbol = extLinkageGOTContainer.createGotSymbol(s);
 474         extLinkageGOTContainer.createSymbol(gotSymbol.getOffset(), Kind.OBJECT, Binding.GLOBAL, 8, name);
 475     }
 476 
 477     /**
 478      * Create a platform-specific binary file representing the content of the
 479      * {@code BinaryContainer} object.
 480      *
 481      * This method is called after creating and performing any necessary changes to the contents of
 482      * code stream, symbol tables and relocation tables is completely finalized
 483      *
 484      * @param outputFileName name of output file
 485      *
 486      * @throws IOException in case of file creation failure
 487      */
 488     public void createBinary(String outputFileName, String aotVersion) throws IOException {
 489         String osName = System.getProperty("os.name");
 490         switch (osName) {
 491             case "Linux":
 492             case "SunOS":
 493                 JELFRelocObject elfso = new JELFRelocObject(this, outputFileName, aotVersion);
 494                 elfso.createELFRelocObject(relocationTable, symbolTable.values());




 495                 break;
 496             default:






 497                 throw new InternalError("Unsupported platform: " + osName);
 498         }
 499     }
 500 
 501     /**
 502      * Add symbol to the symbol table. If the existing symbol is undefined and the specified symbol
 503      * is not undefined, replace the existing symbol information with that specified.
 504      *
 505      * @param symInfo symbol information to be added
 506      */
 507     public void addSymbol(Symbol symInfo) {
 508         if (symInfo.getName().startsWith("got.") && !(symInfo instanceof GotSymbol)) {
 509             throw new InternalError("adding got. without being GotSymbol");
 510         }
 511         if (symbolTable.containsKey(symInfo.getName())) {
 512             throw new InternalError("Symbol: " + symInfo.getName() + " already exists in SymbolTable");
 513         } else {
 514             // System.out.println("# Symbol [" + name + "] [" + symInfo.getValue() + "] [" +
 515             // symInfo.getSection().getContainerName() + "] [" + symInfo.getSize() + "]");
 516             symbolTable.put(symInfo.getName(), symInfo);


 718         String gotInitName = "got.init." + metaspaceName;
 719         GotSymbol slot1Symbol = metaspaceGotContainer.createGotSymbol(gotInitName);
 720         GotSymbol slot2Symbol = metaspaceGotContainer.createGotSymbol(gotName);
 721 
 722         slot1Symbol.getIndex(); // check alignment and ignore result
 723         // Get the index (offset/8) to the got in the .metaspace.got section
 724         return slot2Symbol.getIndex();
 725     }
 726 
 727     public int addMethodsCount(int count, ReadOnlyDataContainer container) {
 728         return appendInt(count, container);
 729     }
 730 
 731     private static int appendInt(int count, ReadOnlyDataContainer container) {
 732         int offset = container.getByteStreamSize();
 733         container.appendInt(count);
 734         return offset;
 735     }
 736 
 737     /**
 738      * Add constant data as follows. - Adding the data to the method.constdata section
 739      *
 740      * @param data
 741      * @param alignment
 742      * @return the offset in the method.constdata of the data
 743      */
 744     public int addConstantData(byte[] data, int alignment) {
 745         // Get the current length of the metaspaceNameContainer
 746         int constantDataOffset = alignUp(constantDataContainer, alignment);
 747         constantDataContainer.appendBytes(data, 0, data.length);
 748         alignUp(constantDataContainer, alignment); // Post alignment
 749         return constantDataOffset;
 750     }
 751 
 752     public int alignUp(ByteContainer container, int alignment) {
 753         if (Integer.bitCount(alignment) != 1) {
 754             throw new IllegalArgumentException("Must be a power of 2");
 755         }
 756         int offset = container.getByteStreamSize();
 757         int aligned = (offset + (alignment - 1)) & -alignment;
 758         if (aligned < offset || (aligned & (alignment - 1)) != 0) {
 759             throw new RuntimeException("Error aligning: " + offset + " -> " + aligned);
 760         }
 761         if (aligned != offset) {
 762             int nullArraySz = aligned - offset;


   1 /*
   2  * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  */
  23 
  24 package jdk.tools.jaotc.binformat;
  25 
  26 import static org.graalvm.compiler.hotspot.meta.HotSpotAOTProfilingPlugin.Options.TieredAOT;
  27 
  28 import java.io.ByteArrayOutputStream;
  29 import java.io.DataOutputStream;
  30 import java.io.IOException;
  31 import java.util.ArrayList;
  32 import java.util.HashMap;
  33 import java.util.List;
  34 import java.util.Map;
  35 
  36 import jdk.tools.jaotc.binformat.Symbol.Binding;
  37 import jdk.tools.jaotc.binformat.Symbol.Kind;
  38 import jdk.tools.jaotc.binformat.elf.JELFRelocObject;
  39 import jdk.tools.jaotc.binformat.macho.JMachORelocObject;
  40 import jdk.tools.jaotc.binformat.pecoff.JPECoffRelocObject;
  41 import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig;
  42 
  43 /**
  44  * A format-agnostic container class that holds various components of a binary.
  45  *
  46  * <p>
  47  * This class holds information necessary to create platform-specific binary containers such as
  48  * ELFContainer for Linux and Solaris operating systems or MachOContainer for Mac
  49  * OS or PEContainer for MS Windows operating systems.
  50  *
  51  * <p>
  52  * Method APIs provided by this class are used to construct and populate platform-independent
  53  * contents of a binary as the first step to create a binary representation of code generated by a
  54  * compiler backend such as Graal.
  55  *
  56  * <p>
  57  * Methods to record and access code section contents, symbols and relocations are provided.
  58  */
  59 public class BinaryContainer implements SymbolTable {
  60 
  61     private final int codeSegmentSize;
  62 
  63     private final int codeEntryAlignment;
  64 
  65     /**
  66      * Container holding code bits and any other related information.
  67      */
  68     private final CodeContainer codeContainer;


 248         //@formatter:on
 249     };
 250 
 251     static {
 252         for (String[] entry : map) {
 253             functionNamesToAOTSymbols.put(entry[0], entry[1]);
 254         }
 255     }
 256 
 257     /**
 258      * Allocates a {@code BinaryContainer} object whose content will be generated in a file with the
 259      * prefix {@code prefix}. It also initializes internal code container, symbol table and
 260      * relocation tables.
 261      */
 262     public BinaryContainer(GraalHotSpotVMConfig config, String jvmVersion) {
 263         this.codeSegmentSize = config.codeSegmentSize;
 264         this.codeEntryAlignment = config.codeEntryAlignment;
 265 
 266         // read only, code
 267         codeContainer = new CodeContainer(".text", this);
 268         extLinkageContainer = new CodeContainer(".hs.plt.linkage", this);
 269 
 270         // read only, info
 271         configContainer = new ReadOnlyDataContainer(".config", this);
 272         metaspaceNamesContainer = new ReadOnlyDataContainer(".meta.names", this);
 273         methodsOffsetsContainer = new ReadOnlyDataContainer(".methods.offsets", this);
 274         klassesOffsetsContainer = new ReadOnlyDataContainer(".kls.offsets", this);
 275         klassesDependenciesContainer = new ReadOnlyDataContainer(".kls.dependencies", this);
 276 
 277         headerContainer = new HeaderContainer(jvmVersion, new ReadOnlyDataContainer(".header", this));
 278         stubsOffsetsContainer = new ReadOnlyDataContainer(".stubs.offsets", this);
 279         codeSegmentsContainer = new ReadOnlyDataContainer(".code.segments", this);
 280         constantDataContainer = new ReadOnlyDataContainer(".meth.constdata", this);
 281 
 282         // needs relocation patching at load time by the loader
 283         methodMetadataContainer = new ReadOnlyDataContainer(".meth.metadata", this);
 284 
 285         // writable sections
 286         metaspaceGotContainer = new ByteContainer(".meta.got", this);
 287         metadataGotContainer = new ByteContainer(".metadata.got", this);
 288         methodStateContainer = new ByteContainer(".meth.state", this);
 289         oopGotContainer = new ByteContainer(".oop.got", this);
 290         extLinkageGOTContainer = new ByteContainer(".hs.got.linkage", this);
 291 
 292         addGlobalSymbols();
 293 
 294         recordConfiguration(config);
 295     }
 296 
 297     private void recordConfiguration(GraalHotSpotVMConfig config) {
 298         // @formatter:off
 299         boolean[] booleanFlags = { config.cAssertions, // Debug VM
 300                                    config.useCompressedOops,
 301                                    config.useCompressedClassPointers,
 302                                    config.compactFields,
 303                                    config.useG1GC,
 304                                    config.useCMSGC,
 305                                    config.useTLAB,
 306                                    config.useBiasedLocking,
 307                                    TieredAOT.getValue(),
 308                                    config.enableContended,
 309                                    config.restrictContended,
 310         };


 475         Symbol gotSymbol = extLinkageGOTContainer.createGotSymbol(s);
 476         extLinkageGOTContainer.createSymbol(gotSymbol.getOffset(), Kind.OBJECT, Binding.GLOBAL, 8, name);
 477     }
 478 
 479     /**
 480      * Create a platform-specific binary file representing the content of the
 481      * {@code BinaryContainer} object.
 482      *
 483      * This method is called after creating and performing any necessary changes to the contents of
 484      * code stream, symbol tables and relocation tables is completely finalized
 485      *
 486      * @param outputFileName name of output file
 487      *
 488      * @throws IOException in case of file creation failure
 489      */
 490     public void createBinary(String outputFileName, String aotVersion) throws IOException {
 491         String osName = System.getProperty("os.name");
 492         switch (osName) {
 493             case "Linux":
 494             case "SunOS":
 495                 JELFRelocObject elfobj = new JELFRelocObject(this, outputFileName, aotVersion);
 496                 elfobj.createELFRelocObject(relocationTable, symbolTable.values());
 497                 break;
 498             case "Mac OS X":
 499                 JMachORelocObject machobj = new JMachORelocObject(this, outputFileName);
 500                 machobj.createMachORelocObject(relocationTable, symbolTable.values());
 501                 break;
 502             default:
 503                 if (osName.startsWith("Windows")) {
 504                     JPECoffRelocObject pecoffobj = new JPECoffRelocObject(this, outputFileName, aotVersion);
 505                     pecoffobj.createPECoffRelocObject(relocationTable, symbolTable.values());
 506                     break;
 507                 }
 508                 else
 509                     throw new InternalError("Unsupported platform: " + osName);
 510         }
 511     }
 512 
 513     /**
 514      * Add symbol to the symbol table. If the existing symbol is undefined and the specified symbol
 515      * is not undefined, replace the existing symbol information with that specified.
 516      *
 517      * @param symInfo symbol information to be added
 518      */
 519     public void addSymbol(Symbol symInfo) {
 520         if (symInfo.getName().startsWith("got.") && !(symInfo instanceof GotSymbol)) {
 521             throw new InternalError("adding got. without being GotSymbol");
 522         }
 523         if (symbolTable.containsKey(symInfo.getName())) {
 524             throw new InternalError("Symbol: " + symInfo.getName() + " already exists in SymbolTable");
 525         } else {
 526             // System.out.println("# Symbol [" + name + "] [" + symInfo.getValue() + "] [" +
 527             // symInfo.getSection().getContainerName() + "] [" + symInfo.getSize() + "]");
 528             symbolTable.put(symInfo.getName(), symInfo);


 730         String gotInitName = "got.init." + metaspaceName;
 731         GotSymbol slot1Symbol = metaspaceGotContainer.createGotSymbol(gotInitName);
 732         GotSymbol slot2Symbol = metaspaceGotContainer.createGotSymbol(gotName);
 733 
 734         slot1Symbol.getIndex(); // check alignment and ignore result
 735         // Get the index (offset/8) to the got in the .metaspace.got section
 736         return slot2Symbol.getIndex();
 737     }
 738 
 739     public int addMethodsCount(int count, ReadOnlyDataContainer container) {
 740         return appendInt(count, container);
 741     }
 742 
 743     private static int appendInt(int count, ReadOnlyDataContainer container) {
 744         int offset = container.getByteStreamSize();
 745         container.appendInt(count);
 746         return offset;
 747     }
 748 
 749     /**
 750      * Add constant data as follows. - Adding the data to the meth.constdata section
 751      *
 752      * @param data
 753      * @param alignment
 754      * @return the offset in the meth.constdata of the data
 755      */
 756     public int addConstantData(byte[] data, int alignment) {
 757         // Get the current length of the metaspaceNameContainer
 758         int constantDataOffset = alignUp(constantDataContainer, alignment);
 759         constantDataContainer.appendBytes(data, 0, data.length);
 760         alignUp(constantDataContainer, alignment); // Post alignment
 761         return constantDataOffset;
 762     }
 763 
 764     public int alignUp(ByteContainer container, int alignment) {
 765         if (Integer.bitCount(alignment) != 1) {
 766             throw new IllegalArgumentException("Must be a power of 2");
 767         }
 768         int offset = container.getByteStreamSize();
 769         int aligned = (offset + (alignment - 1)) & -alignment;
 770         if (aligned < offset || (aligned & (alignment - 1)) != 0) {
 771             throw new RuntimeException("Error aligning: " + offset + " -> " + aligned);
 772         }
 773         if (aligned != offset) {
 774             int nullArraySz = aligned - offset;


src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/BinaryContainer.java
Index Unified diffs Context diffs Sdiffs Wdiffs Patch New Old Previous File Next File