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

src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/pecoff/JPECoffRelocObject.java

Print this page




   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.pecoff;
  25 
  26 import java.io.IOException;
  27 import java.nio.charset.StandardCharsets;
  28 import java.util.ArrayList;
  29 import java.util.Collection;
  30 import java.util.List;
  31 import java.util.Map;
  32 
  33 import jdk.tools.jaotc.binformat.Container;
  34 import jdk.tools.jaotc.binformat.BinaryContainer;
  35 import jdk.tools.jaotc.binformat.ByteContainer;
  36 import jdk.tools.jaotc.binformat.CodeContainer;
  37 import jdk.tools.jaotc.binformat.ReadOnlyDataContainer;
  38 import jdk.tools.jaotc.binformat.Relocation;
  39 import jdk.tools.jaotc.binformat.Relocation.RelocType;
  40 import jdk.tools.jaotc.binformat.Symbol;
  41 import jdk.tools.jaotc.binformat.NativeSymbol;
  42 import jdk.tools.jaotc.binformat.Symbol.Binding;
  43 import jdk.tools.jaotc.binformat.Symbol.Kind;
  44 
  45 import jdk.tools.jaotc.binformat.pecoff.PECoff;
  46 import jdk.tools.jaotc.binformat.pecoff.PECoffSymbol;
  47 import jdk.tools.jaotc.binformat.pecoff.PECoffTargetInfo;
  48 import jdk.tools.jaotc.binformat.pecoff.PECoff.IMAGE_FILE_HEADER;
  49 import jdk.tools.jaotc.binformat.pecoff.PECoff.IMAGE_SECTION_HEADER;
  50 import jdk.tools.jaotc.binformat.pecoff.PECoff.IMAGE_SYMBOL;
  51 import jdk.tools.jaotc.binformat.pecoff.PECoff.IMAGE_RELOCATION;
  52 
  53 public class JPECoffRelocObject {
  54 
  55     private final BinaryContainer binContainer;
  56 
  57     private final PECoffContainer pecoffContainer;
  58 
  59     private final int segmentSize;
  60 
  61     public JPECoffRelocObject(BinaryContainer binContainer, String outputFileName, String aotVersion) {
  62         this.binContainer = binContainer;
  63         this.pecoffContainer = new PECoffContainer(outputFileName, aotVersion);
  64         this.segmentSize = binContainer.getCodeSegmentSize();
  65         if (segmentSize != 64) {
  66             System.out.println("binContainer alignment size not 64 bytes, update JPECoffRelocObject");
  67         }
  68     }
  69 
  70     private PECoffSection createByteSection(ArrayList<PECoffSection>sections,
  71                                          String sectName,
  72                                          byte [] scnData,
  73                                          boolean hasRelocs,
  74                                          int scnFlags) {
  75 
  76         PECoffSection sect = new PECoffSection(sectName,
  77                                          scnData,
  78                                          scnFlags,
  79                                          hasRelocs,
  80                                          sections.size());
  81         // Add this section to our list
  82         sections.add(sect);
  83 
  84         return (sect);
  85     }
  86 
  87     private void createByteSection(ArrayList<PECoffSection>sections,
  88                                    ByteContainer c, int scnFlags) {
  89         PECoffSection sect;
  90         boolean hasRelocs = c.hasRelocations();
  91         byte[] scnData = c.getByteArray();
  92 
  93         sect = createByteSection(sections, c.getContainerName(),
  94                                  scnData, hasRelocs,
  95                                  scnFlags);
  96 
  97         c.setSectionId(sect.getSectionId());
  98     }
  99 
 100     private void createCodeSection(ArrayList<PECoffSection>sections, CodeContainer c) {
 101         createByteSection(sections, c, IMAGE_SECTION_HEADER.IMAGE_SCN_MEM_READ |
 102                                        IMAGE_SECTION_HEADER.IMAGE_SCN_MEM_EXECUTE |
 103                                        IMAGE_SECTION_HEADER.IMAGE_SCN_ALIGN_64BYTES |
 104                                        IMAGE_SECTION_HEADER.IMAGE_SCN_CNT_CODE);
 105     }
 106 
 107     private void createReadOnlySection(ArrayList<PECoffSection>sections, ReadOnlyDataContainer c) {
 108         createByteSection(sections, c, IMAGE_SECTION_HEADER.IMAGE_SCN_MEM_READ |
 109                                        IMAGE_SECTION_HEADER.IMAGE_SCN_ALIGN_64BYTES |
 110                                        IMAGE_SECTION_HEADER.IMAGE_SCN_CNT_INITIALIZED_DATA);
 111     }
 112 
 113     private void createReadWriteSection(ArrayList<PECoffSection>sections, ByteContainer c) {
 114         int scnFlags = IMAGE_SECTION_HEADER.IMAGE_SCN_MEM_READ |
 115                        IMAGE_SECTION_HEADER.IMAGE_SCN_MEM_WRITE |
 116                        IMAGE_SECTION_HEADER.IMAGE_SCN_ALIGN_64BYTES;
 117 
 118         if (c.getByteArray().length > 0)
 119             scnFlags |= IMAGE_SECTION_HEADER.IMAGE_SCN_CNT_INITIALIZED_DATA;
 120         else
 121             scnFlags |= IMAGE_SECTION_HEADER.IMAGE_SCN_CNT_UNINITIALIZED_DATA;
 122 
 123         createByteSection(sections, c, scnFlags);
 124     }
 125 
 126     /**
 127      * Create an PECoff relocatable object
 128      *
 129      * @param relocationTable
 130      * @param symbols
 131      * @throws IOException throws {@code IOException} as a result of file system access failures.
 132      */
 133     public void createPECoffRelocObject(Map<Symbol, List<Relocation>> relocationTable, Collection<Symbol> symbols) throws IOException {
 134         ArrayList<PECoffSection> sections = new ArrayList<PECoffSection>();
 135 
 136         // Create text section
 137         createCodeSection(sections, binContainer.getCodeContainer());
 138         createReadOnlySection(sections, binContainer.getMetaspaceNamesContainer());
 139         createReadOnlySection(sections, binContainer.getKlassesOffsetsContainer());
 140         createReadOnlySection(sections, binContainer.getMethodsOffsetsContainer());
 141         createReadOnlySection(sections, binContainer.getKlassesDependenciesContainer());
 142         createReadWriteSection(sections, binContainer.getMetaspaceGotContainer());
 143         createReadWriteSection(sections, binContainer.getMetadataGotContainer());
 144         createReadWriteSection(sections, binContainer.getMethodStateContainer());
 145         createReadWriteSection(sections, binContainer.getOopGotContainer());
 146         createReadWriteSection(sections, binContainer.getMethodMetadataContainer());
 147         createReadOnlySection(sections, binContainer.getStubsOffsetsContainer());
 148         createReadOnlySection(sections, binContainer.getHeaderContainer().getContainer());
 149         createReadOnlySection(sections, binContainer.getCodeSegmentsContainer());
 150         createReadOnlySection(sections, binContainer.getConstantDataContainer());
 151         createReadOnlySection(sections, binContainer.getConfigContainer());
 152 
 153         // createExternalLinkage();
 154 
 155         createCodeSection(sections, binContainer.getExtLinkageContainer());

 156         createReadWriteSection(sections, binContainer.getExtLinkageGOTContainer());
 157 
 158         // Allocate PECoff Header
 159         PECoffHeader header = new PECoffHeader();
 160 
 161         // Get PECoff symbol data from BinaryContainer object's symbol tables
 162         PECoffSymtab symtab = createPECoffSymbolTables(sections, symbols);
 163 
 164         // Add Linker Directives Section
 165         createByteSection(sections, ".drectve",
 166                           symtab.getDirectiveArray(), false,
 167                           IMAGE_SECTION_HEADER.IMAGE_SCN_LNK_INFO |
 168                           IMAGE_SECTION_HEADER.IMAGE_SCN_LNK_REMOVE |
 169                           IMAGE_SECTION_HEADER.IMAGE_SCN_ALIGN_1BYTES);
 170 
 171         // Create the Relocation Tables
 172         PECoffRelocTable pecoffRelocs = createPECoffRelocTable(sections, relocationTable);
 173 
 174         // File Output Order
 175         //
 176         //   HEADER           (Need address of Symbol Table + symbol count)
 177         //   SECTIONS         (Need pointer to Section Data, Relocation Table)
 178         //   DIRECTIVES
 179         //   SYMBOL TABLE
 180         //   SYMBOLS
 181         //   SECTION DATA
 182         //   RELOCATION TABLE
 183 
 184         // Calculate Offset for Symbol table
 185         int file_offset = IMAGE_FILE_HEADER.totalsize +
 186                           (IMAGE_SECTION_HEADER.totalsize*sections.size());
 187 
 188         // Update Header fields
 189         header.setSectionCount(sections.size());
 190         header.setSymbolCount(symtab.getSymtabCount());
 191         header.setSymbolOff(file_offset);
 192 
 193         // Calculate file offset for first section
 194         file_offset += ((symtab.getSymtabCount() * IMAGE_SYMBOL.totalsize) +
 195                         symtab.getStrtabSize());
 196         // And round it up
 197         file_offset = (file_offset + (sections.get(0).getDataAlign()-1)) &
 198                       ~((sections.get(0).getDataAlign()-1));
 199 
 200         // Calc file offsets for section data
 201         for (int i = 0; i < sections.size(); i++) {
 202             PECoffSection sect = sections.get(i);
 203             file_offset = (file_offset + (sect.getDataAlign()-1)) &
 204                            ~((sect.getDataAlign()-1));
 205             sect.setOffset(file_offset);
 206             file_offset += sect.getSize();
 207         }
 208 
 209         // Update relocation sizing information in each section
 210         for (int i = 0; i < sections.size(); i++) {
 211             PECoffSection sect = sections.get(i);
 212             if (sect.hasRelocations()) {
 213                 int nreloc = pecoffRelocs.getNumRelocs(i);
 214                 sect.setReloff(file_offset);
 215                 sect.setRelcount(nreloc);
 216                 // extended relocations add an addition entry
 217                 if (nreloc > 0xFFFF) nreloc++;


 218                 file_offset += (nreloc * IMAGE_RELOCATION.totalsize);
 219             }
 220         }
 221 
 222         // Write out the Header
 223         pecoffContainer.writeBytes(header.getArray());
 224 
 225         // Write out the section table
 226         for (int i = 0; i < sections.size(); i++) {
 227             PECoffSection sect = sections.get(i);
 228             pecoffContainer.writeBytes(sect.getArray(), PECoffSection.getShdrAlign());
 229         }
 230 
 231         // Write out the symbol table and string table
 232         pecoffContainer.writeBytes(symtab.getSymtabArray(), 4);
 233         pecoffContainer.writeBytes(symtab.getStrtabArray(), 1);
 234 
 235         // Write out each section contents
 236         for (int i = 0; i < sections.size(); i++) {
 237             PECoffSection sect = sections.get(i);
 238             pecoffContainer.writeBytes(sect.getDataArray(), sect.getDataAlign());
 239         }
 240 
 241         // Write out Relocation Tables
 242         for (int i = 0; i < sections.size(); i++) {
 243             if (pecoffRelocs.getNumRelocs(i) > 0) {
 244                 pecoffContainer.writeBytes(pecoffRelocs.getRelocData(i));
 245             }
 246         }
 247         pecoffContainer.close();
 248     }
 249 
 250     /**
 251      * Construct PECoff symbol data from BinaryContainer object's symbol tables. Both dynamic PECoff
 252      * symbol table and PECoff symbol table are created from BinaryContainer's symbol info.
 253      *
 254      * @param symbols
 255      */
 256     private PECoffSymtab createPECoffSymbolTables(ArrayList<PECoffSection> sections, Collection<Symbol> symbols) {
 257         PECoffSymtab symtab = new PECoffSymtab();
 258 
 259         // First, create the initial null symbol. This is a local symbol.
 260         // symtab.addSymbolEntry("", (byte)0, (byte)0, (byte)0, 0, 0);
 261 
 262         // Now create PECoff symbol entries for all symbols.
 263         for (Symbol symbol : symbols) {
 264             // Get the index of section this symbol is defined in.
 265             int secHdrIndex = symbol.getSection().getSectionId();
 266             PECoffSymbol pecoffSymbol = symtab.addSymbolEntry(symbol.getName(), getPECoffTypeOf(symbol), getPECoffClassOf(symbol), (byte)secHdrIndex, symbol.getOffset(), symbol.getSize());
 267             symbol.setNativeSymbol((NativeSymbol)pecoffSymbol);
 268         }
 269         return (symtab);
 270     }
 271 
 272     private static byte getPECoffTypeOf(Symbol sym) {
 273         Kind kind = sym.getKind();
 274         if (kind == Symbol.Kind.NATIVE_FUNCTION || kind == Symbol.Kind.JAVA_FUNCTION) {
 275             return IMAGE_SYMBOL.IMAGE_SYM_DTYPE_FUNCTION;
 276         }
 277         return IMAGE_SYMBOL.IMAGE_SYM_DTYPE_NONE;
 278     }
 279 
 280     private static byte getPECoffClassOf(Symbol sym) {
 281         Binding binding = sym.getBinding();
 282         if (binding == Symbol.Binding.GLOBAL) {
 283             return IMAGE_SYMBOL.IMAGE_SYM_CLASS_EXTERNAL;
 284         }
 285         return IMAGE_SYMBOL.IMAGE_SYM_CLASS_STATIC;
 286     }
 287 
 288     /**
 289      * Construct a PECoff relocation table from BinaryContainer object's relocation tables.
 290      *
 291      * @param sections
 292      * @param relocationTable
 293      */
 294     private PECoffRelocTable createPECoffRelocTable(ArrayList<PECoffSection> sections,
 295                                               Map<Symbol, List<Relocation>> relocationTable) {
 296 
 297         PECoffRelocTable pecoffRelocTable = new PECoffRelocTable(sections.size());
 298         /*
 299          * For each of the symbols with associated relocation records, create a PECoff relocation
 300          * entry.
 301          */
 302         for (Map.Entry<Symbol, List<Relocation>> entry : relocationTable.entrySet()) {
 303             List<Relocation> relocs = entry.getValue();
 304             Symbol symbol = entry.getKey();
 305 
 306             for (Relocation reloc : relocs) {
 307                 createRelocation(symbol, reloc, pecoffRelocTable);
 308             }
 309         }
 310 
 311         for (Map.Entry<Symbol, Relocation> entry : binContainer.getUniqueRelocationTable().entrySet()) {
 312             createRelocation(entry.getKey(), entry.getValue(), pecoffRelocTable);
 313         }
 314 
 315         return (pecoffRelocTable);
 316     }
 317 
 318     private void createRelocation(Symbol symbol, Relocation reloc, PECoffRelocTable pecoffRelocTable) {
 319         RelocType relocType = reloc.getType();
 320 
 321         int pecoffRelocType = getPECoffRelocationType(relocType);
 322         PECoffSymbol sym = (PECoffSymbol)symbol.getNativeSymbol();
 323         int symno = sym.getIndex();
 324         int sectindex = reloc.getSection().getSectionId();
 325         int offset = reloc.getOffset();
 326         int addend = 0;
 327 
 328         switch (relocType) {
 329             case FOREIGN_CALL_DIRECT:
 330             case JAVA_CALL_DIRECT:
 331             case STUB_CALL_DIRECT:
 332             case FOREIGN_CALL_INDIRECT_GOT: {
 333                 // Create relocation entry
 334                 addend = -4; // Size in bytes of the patch location
 335                 // Relocation should be applied at the location after call operand
 336                 offset = offset + reloc.getSize() + addend;
 337                 break;
 338             }
 339             case FOREIGN_CALL_DIRECT_FAR: {
 340                 // Create relocation entry
 341                 addend = -8; // Size in bytes of the patch location
 342                 // Relocation should be applied at the location after call operand
 343                 // 10 = 2 (jmp [r]) + 8 (imm64)
 344                 offset = offset + reloc.getSize() + addend - 2;
 345                 break;
 346             }
 347             case FOREIGN_CALL_INDIRECT:
 348             case JAVA_CALL_INDIRECT:
 349             case STUB_CALL_INDIRECT: {
 350                 // Do nothing.
 351                 return;
 352             }
 353             case EXTERNAL_DATA_REFERENCE_FAR: {
 354                 // Create relocation entry
 355                 addend = -4; // Size of 32-bit address of the GOT
 356                 /*
 357                  * Relocation should be applied before the test instruction to the move instruction.
 358                  * offset points to the test instruction after the instruction that loads
 359                  * the address of polling page. So set the offset appropriately.
 360                  */
 361                 offset = offset + addend;
 362                 break;
 363             }
 364             case METASPACE_GOT_REFERENCE:
 365             case EXTERNAL_PLT_TO_GOT:
 366             case STATIC_STUB_TO_STATIC_METHOD:
 367             case STATIC_STUB_TO_HOTSPOT_LINKAGE_GOT: {
 368                 addend = -4; // Size of 32-bit address of the GOT
 369                 /*
 370                  * Relocation should be applied before the test instruction to
 371                  * the move instruction. reloc.getOffset() points to the
 372                  * test instruction after the instruction that loads the
 373                  * address of polling page. So set the offset appropriately.
 374                  */
 375                 offset = offset + addend;
 376                 break;
 377             }
 378             case EXTERNAL_GOT_TO_PLT:
 379             case LOADTIME_ADDRESS: {
 380                 // this is load time relocations
 381                 break;
 382             }
 383             default:
 384                 throw new InternalError("Unhandled relocation type: " + relocType);
 385         }
 386         pecoffRelocTable.createRelocationEntry(sectindex, offset, symno, pecoffRelocType);
 387     }
 388 
 389     // Return IMAGE_RELOCATION Type based on relocType
 390     private static int getPECoffRelocationType(RelocType relocType) {
 391         int pecoffRelocType = 0; // R_<ARCH>_NONE if #define'd to 0 for all values of ARCH
 392         switch (PECoffTargetInfo.getPECoffArch()) {
 393             case IMAGE_FILE_HEADER.IMAGE_FILE_MACHINE_AMD64:
 394                 if (relocType == RelocType.FOREIGN_CALL_DIRECT ||
 395                     relocType == RelocType.JAVA_CALL_DIRECT ||
 396                     relocType == RelocType.FOREIGN_CALL_INDIRECT_GOT) {
 397                     pecoffRelocType = IMAGE_RELOCATION.IMAGE_REL_AMD64_REL32;
 398                 } else if (relocType == RelocType.STUB_CALL_DIRECT) {
 399                     pecoffRelocType = IMAGE_RELOCATION.IMAGE_REL_AMD64_REL32;
 400                 } else if (relocType == RelocType.FOREIGN_CALL_DIRECT_FAR) {
 401                     pecoffRelocType = IMAGE_RELOCATION.IMAGE_REL_AMD64_ADDR64;
 402                 } else if (relocType == RelocType.FOREIGN_CALL_INDIRECT ||
 403                            relocType == RelocType.JAVA_CALL_INDIRECT ||
 404                            relocType == RelocType.STUB_CALL_INDIRECT) {
 405                     pecoffRelocType = IMAGE_RELOCATION.IMAGE_REL_AMD64_ABSOLUTE;
 406                 } else if ((relocType == RelocType.EXTERNAL_DATA_REFERENCE_FAR)) {
 407                     pecoffRelocType = IMAGE_RELOCATION.IMAGE_REL_AMD64_REL32;
 408                 } else if (relocType == RelocType.METASPACE_GOT_REFERENCE ||
 409                            relocType == RelocType.EXTERNAL_PLT_TO_GOT ||
 410                            relocType == RelocType.STATIC_STUB_TO_STATIC_METHOD ||
 411                            relocType == RelocType.STATIC_STUB_TO_HOTSPOT_LINKAGE_GOT) {
 412                     pecoffRelocType = IMAGE_RELOCATION.IMAGE_REL_AMD64_REL32;
 413                 } else if (relocType == RelocType.EXTERNAL_GOT_TO_PLT ||
 414                            relocType == RelocType.LOADTIME_ADDRESS) {
 415                     pecoffRelocType = IMAGE_RELOCATION.IMAGE_REL_AMD64_ADDR64;
 416                 } else {
 417                     assert false : "Unhandled relocation type: " + relocType;
 418                 }
 419                 break;
 420             default:
 421                 System.out.println("Relocation Type mapping: Unhandled architecture");
 422         }
 423         return pecoffRelocType;
 424     }
 425 }


   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.pecoff;
  25 
  26 import java.io.IOException;

  27 import java.util.ArrayList;
  28 import java.util.Collection;
  29 import java.util.List;
  30 import java.util.Map;
  31 

  32 import jdk.tools.jaotc.binformat.BinaryContainer;
  33 import jdk.tools.jaotc.binformat.ByteContainer;
  34 import jdk.tools.jaotc.binformat.CodeContainer;
  35 import jdk.tools.jaotc.binformat.ReadOnlyDataContainer;
  36 import jdk.tools.jaotc.binformat.Relocation;
  37 import jdk.tools.jaotc.binformat.Relocation.RelocType;
  38 import jdk.tools.jaotc.binformat.Symbol;

  39 import jdk.tools.jaotc.binformat.Symbol.Binding;
  40 import jdk.tools.jaotc.binformat.Symbol.Kind;
  41 

  42 import jdk.tools.jaotc.binformat.pecoff.PECoffSymbol;
  43 import jdk.tools.jaotc.binformat.pecoff.PECoffTargetInfo;
  44 import jdk.tools.jaotc.binformat.pecoff.PECoff.IMAGE_FILE_HEADER;
  45 import jdk.tools.jaotc.binformat.pecoff.PECoff.IMAGE_SECTION_HEADER;
  46 import jdk.tools.jaotc.binformat.pecoff.PECoff.IMAGE_SYMBOL;
  47 import jdk.tools.jaotc.binformat.pecoff.PECoff.IMAGE_RELOCATION;
  48 
  49 public class JPECoffRelocObject {
  50 
  51     private final BinaryContainer binContainer;
  52 
  53     private final PECoffContainer pecoffContainer;
  54 
  55     private final int sectionAlignment;
  56 
  57     public JPECoffRelocObject(BinaryContainer binContainer, String outputFileName) {
  58         this.binContainer = binContainer;
  59         this.pecoffContainer = new PECoffContainer(outputFileName);
  60         this.sectionAlignment = binContainer.getCodeSegmentSize();



  61     }
  62 
  63     private static PECoffSection createByteSection(ArrayList<PECoffSection> sections, String sectName, byte[] scnData,
  64                     boolean hasRelocs, int scnFlags, int sectAlign) {
  65 
  66         PECoffSection sect = new PECoffSection(sectName, scnData, scnFlags, sectAlign, hasRelocs, sections.size());







  67         // Add this section to our list
  68         sections.add(sect);
  69 
  70         return (sect);
  71     }
  72 
  73     private static void createByteSection(ArrayList<PECoffSection> sections, ByteContainer c, int scnFlags, int sectAlign) {

  74         PECoffSection sect;
  75         boolean hasRelocs = c.hasRelocations();
  76         byte[] scnData = c.getByteArray();
  77 
  78         sect = createByteSection(sections, c.getContainerName(), scnData, hasRelocs, scnFlags, sectAlign);


  79 
  80         c.setSectionId(sect.getSectionId());
  81     }
  82 
  83     private void createCodeSection(ArrayList<PECoffSection> sections, CodeContainer c) {
  84         int scnFlags = IMAGE_SECTION_HEADER.IMAGE_SCN_MEM_READ | IMAGE_SECTION_HEADER.IMAGE_SCN_MEM_EXECUTE | IMAGE_SECTION_HEADER.IMAGE_SCN_CNT_CODE;
  85         createByteSection(sections, c, scnFlags, sectionAlignment);


  86     }
  87 
  88     private void createReadOnlySection(ArrayList<PECoffSection> sections, ReadOnlyDataContainer c) {
  89         int scnFlags = IMAGE_SECTION_HEADER.IMAGE_SCN_MEM_READ | IMAGE_SECTION_HEADER.IMAGE_SCN_CNT_INITIALIZED_DATA;
  90         createByteSection(sections, c, scnFlags, sectionAlignment);

  91     }
  92 
  93     private void createReadWriteSection(ArrayList<PECoffSection> sections, ByteContainer c) {
  94         int scnFlags = IMAGE_SECTION_HEADER.IMAGE_SCN_MEM_READ | IMAGE_SECTION_HEADER.IMAGE_SCN_MEM_WRITE;


  95 
  96         if (c.getByteArray().length > 0) {
  97             scnFlags |= IMAGE_SECTION_HEADER.IMAGE_SCN_CNT_INITIALIZED_DATA;
  98         } else {
  99             scnFlags |= IMAGE_SECTION_HEADER.IMAGE_SCN_CNT_UNINITIALIZED_DATA;
 100         }
 101         createByteSection(sections, c, scnFlags, sectionAlignment);
 102     }
 103 
 104     /**
 105      * Create an PECoff relocatable object
 106      *
 107      * @param relocationTable
 108      * @param symbols
 109      * @throws IOException throws {@code IOException} as a result of file system access failures.
 110      */
 111     public void createPECoffRelocObject(Map<Symbol, List<Relocation>> relocationTable, Collection<Symbol> symbols) throws IOException {
 112         ArrayList<PECoffSection> sections = new ArrayList<>();
 113 
 114         // Create text section
 115         createCodeSection(sections, binContainer.getCodeContainer());
 116         createReadOnlySection(sections, binContainer.getMetaspaceNamesContainer());
 117         createReadOnlySection(sections, binContainer.getKlassesOffsetsContainer());
 118         createReadOnlySection(sections, binContainer.getMethodsOffsetsContainer());
 119         createReadOnlySection(sections, binContainer.getKlassesDependenciesContainer());
 120         createReadOnlySection(sections, binContainer.getMethodMetadataContainer());




 121         createReadOnlySection(sections, binContainer.getStubsOffsetsContainer());
 122         createReadOnlySection(sections, binContainer.getHeaderContainer().getContainer());
 123         createReadOnlySection(sections, binContainer.getCodeSegmentsContainer());
 124         createReadOnlySection(sections, binContainer.getConstantDataContainer());
 125         createReadOnlySection(sections, binContainer.getConfigContainer());
 126         createReadWriteSection(sections, binContainer.getKlassesGotContainer());
 127         createReadWriteSection(sections, binContainer.getCountersGotContainer());
 128         createReadWriteSection(sections, binContainer.getMetadataGotContainer());
 129         createReadWriteSection(sections, binContainer.getMethodStateContainer());
 130         createReadWriteSection(sections, binContainer.getOopGotContainer());
 131         createReadWriteSection(sections, binContainer.getExtLinkageGOTContainer());
 132 
 133         // Allocate PECoff Header
 134         PECoffHeader header = new PECoffHeader();
 135 
 136         // Get PECoff symbol data from BinaryContainer object's symbol tables
 137         PECoffSymtab symtab = createPECoffSymbolTables(symbols);
 138 
 139         // Add Linker Directives Section
 140         int scnFlags = IMAGE_SECTION_HEADER.IMAGE_SCN_LNK_INFO | IMAGE_SECTION_HEADER.IMAGE_SCN_LNK_REMOVE;
 141         createByteSection(sections, ".drectve", symtab.getDirectiveArray(), false, scnFlags, 1 /* 1 byte alignment */);



 142 
 143         // Create the Relocation Tables
 144         PECoffRelocTable pecoffRelocs = createPECoffRelocTable(sections, relocationTable);
 145 
 146         // File Output Order
 147         //
 148         // HEADER (Need address of Symbol Table + symbol count)
 149         // SECTIONS (Need pointer to Section Data, Relocation Table)
 150         // DIRECTIVES
 151         // SYMBOL TABLE
 152         // SYMBOLS
 153         // SECTION DATA
 154         // RELOCATION TABLE
 155 
 156         // Calculate Offset for Symbol table
 157         int file_offset = IMAGE_FILE_HEADER.totalsize +
 158                         (IMAGE_SECTION_HEADER.totalsize * sections.size());
 159 
 160         // Update Header fields
 161         header.setSectionCount(sections.size());
 162         header.setSymbolCount(symtab.getSymtabCount());
 163         header.setSymbolOff(file_offset);
 164 
 165         // Calculate file offset for first section
 166         file_offset += ((symtab.getSymtabCount() * IMAGE_SYMBOL.totalsize) +
 167                         symtab.getStrtabSize());
 168         // And round it up
 169         file_offset = (file_offset + (sections.get(0).getDataAlign() - 1)) &
 170                         ~((sections.get(0).getDataAlign() - 1));
 171 
 172         // Calc file offsets for section data
 173         for (int i = 0; i < sections.size(); i++) {
 174             PECoffSection sect = sections.get(i);
 175             file_offset = (file_offset + (sect.getDataAlign() - 1)) &
 176                             ~((sect.getDataAlign() - 1));
 177             sect.setOffset(file_offset);
 178             file_offset += sect.getSize();
 179         }
 180 
 181         // Update relocation sizing information in each section
 182         for (int i = 0; i < sections.size(); i++) {
 183             PECoffSection sect = sections.get(i);
 184             if (sect.hasRelocations()) {
 185                 int nreloc = pecoffRelocs.getNumRelocs(i);
 186                 sect.setReloff(file_offset);
 187                 sect.setRelcount(nreloc);
 188                 // extended relocations add an addition entry
 189                 if (nreloc > 0xFFFF) {
 190                     nreloc++;
 191                 }
 192                 file_offset += (nreloc * IMAGE_RELOCATION.totalsize);
 193             }
 194         }
 195 
 196         // Write out the Header
 197         pecoffContainer.writeBytes(header.getArray());
 198 
 199         // Write out the section table
 200         for (int i = 0; i < sections.size(); i++) {
 201             PECoffSection sect = sections.get(i);
 202             pecoffContainer.writeBytes(sect.getArray(), PECoffSection.getShdrAlign());
 203         }
 204 
 205         // Write out the symbol table and string table
 206         pecoffContainer.writeBytes(symtab.getSymtabArray(), 4);
 207         pecoffContainer.writeBytes(symtab.getStrtabArray(), 1);
 208 
 209         // Write out each section contents
 210         for (int i = 0; i < sections.size(); i++) {
 211             PECoffSection sect = sections.get(i);
 212             pecoffContainer.writeBytes(sect.getDataArray(), sect.getDataAlign());
 213         }
 214 
 215         // Write out Relocation Tables
 216         for (int i = 0; i < sections.size(); i++) {
 217             if (pecoffRelocs.getNumRelocs(i) > 0) {
 218                 pecoffContainer.writeBytes(pecoffRelocs.getRelocData(i));
 219             }
 220         }
 221         pecoffContainer.close();
 222     }
 223 
 224     /**
 225      * Construct PECoff symbol data from BinaryContainer object's symbol tables. Both dynamic PECoff
 226      * symbol table and PECoff symbol table are created from BinaryContainer's symbol info.
 227      *
 228      * @param symbols
 229      */
 230     private static PECoffSymtab createPECoffSymbolTables(Collection<Symbol> symbols) {
 231         PECoffSymtab symtab = new PECoffSymtab();
 232 
 233         // First, create the initial null symbol. This is a local symbol.
 234         // symtab.addSymbolEntry("", (byte)0, (byte)0, (byte)0, 0, 0);
 235 
 236         // Now create PECoff symbol entries for all symbols.
 237         for (Symbol symbol : symbols) {
 238             // Get the index of section this symbol is defined in.
 239             int secHdrIndex = symbol.getSection().getSectionId();
 240             PECoffSymbol pecoffSymbol = symtab.addSymbolEntry(symbol.getName(), getPECoffTypeOf(symbol), getPECoffClassOf(symbol), (byte) secHdrIndex, symbol.getOffset());
 241             symbol.setNativeSymbol(pecoffSymbol);
 242         }
 243         return (symtab);
 244     }
 245 
 246     private static byte getPECoffTypeOf(Symbol sym) {
 247         Kind kind = sym.getKind();
 248         if (kind == Symbol.Kind.NATIVE_FUNCTION || kind == Symbol.Kind.JAVA_FUNCTION) {
 249             return IMAGE_SYMBOL.IMAGE_SYM_DTYPE_FUNCTION;
 250         }
 251         return IMAGE_SYMBOL.IMAGE_SYM_DTYPE_NONE;
 252     }
 253 
 254     private static byte getPECoffClassOf(Symbol sym) {
 255         Binding binding = sym.getBinding();
 256         if (binding == Symbol.Binding.GLOBAL) {
 257             return IMAGE_SYMBOL.IMAGE_SYM_CLASS_EXTERNAL;
 258         }
 259         return IMAGE_SYMBOL.IMAGE_SYM_CLASS_STATIC;
 260     }
 261 
 262     /**
 263      * Construct a PECoff relocation table from BinaryContainer object's relocation tables.
 264      *
 265      * @param sections
 266      * @param relocationTable
 267      */
 268     private PECoffRelocTable createPECoffRelocTable(ArrayList<PECoffSection> sections, Map<Symbol, List<Relocation>> relocationTable) {

 269 
 270         PECoffRelocTable pecoffRelocTable = new PECoffRelocTable(sections.size());
 271         /*
 272          * For each of the symbols with associated relocation records, create a PECoff relocation entry.

 273          */
 274         for (Map.Entry<Symbol, List<Relocation>> entry : relocationTable.entrySet()) {
 275             List<Relocation> relocs = entry.getValue();
 276             Symbol symbol = entry.getKey();
 277 
 278             for (Relocation reloc : relocs) {
 279                 createRelocation(symbol, reloc, pecoffRelocTable);
 280             }
 281         }
 282 
 283         for (Map.Entry<Symbol, Relocation> entry : binContainer.getUniqueRelocationTable().entrySet()) {
 284             createRelocation(entry.getKey(), entry.getValue(), pecoffRelocTable);
 285         }
 286 
 287         return (pecoffRelocTable);
 288     }
 289 
 290     private static void createRelocation(Symbol symbol, Relocation reloc, PECoffRelocTable pecoffRelocTable) {
 291         RelocType relocType = reloc.getType();
 292 
 293         int pecoffRelocType = getPECoffRelocationType(relocType);
 294         PECoffSymbol sym = (PECoffSymbol) symbol.getNativeSymbol();
 295         int symno = sym.getIndex();
 296         int sectindex = reloc.getSection().getSectionId();
 297         int offset = reloc.getOffset();
 298         int addend = 0;
 299 
 300         switch (relocType) {

 301             case JAVA_CALL_DIRECT:
 302             case STUB_CALL_DIRECT:
 303             case FOREIGN_CALL_INDIRECT_GOT: {
 304                 // Create relocation entry
 305                 addend = -4; // Size in bytes of the patch location
 306                 // Relocation should be applied at the location after call operand
 307                 offset = offset + reloc.getSize() + addend;
 308                 break;
 309             }
 310             case JAVA_CALL_INDIRECT: {










 311                 // Do nothing.
 312                 return;
 313             }











 314             case METASPACE_GOT_REFERENCE:
 315             case EXTERNAL_PLT_TO_GOT: {


 316                 addend = -4; // Size of 32-bit address of the GOT
 317                 /*
 318                  * Relocation should be applied before the test instruction to the move instruction.
 319                  * reloc.getOffset() points to the test instruction after the instruction that loads the address of
 320                  * polling page. So set the offset appropriately.

 321                  */
 322                 offset = offset + addend;
 323                 break;
 324             }
 325             case EXTERNAL_GOT_TO_PLT: {

 326                 // this is load time relocations
 327                 break;
 328             }
 329             default:
 330                 throw new InternalError("Unhandled relocation type: " + relocType);
 331         }
 332         pecoffRelocTable.createRelocationEntry(sectindex, offset, symno, pecoffRelocType);
 333     }
 334 
 335     // Return IMAGE_RELOCATION Type based on relocType
 336     private static int getPECoffRelocationType(RelocType relocType) {
 337         int pecoffRelocType = 0; // R_<ARCH>_NONE if #define'd to 0 for all values of ARCH
 338         switch (PECoffTargetInfo.getPECoffArch()) {
 339             case IMAGE_FILE_HEADER.IMAGE_FILE_MACHINE_AMD64:
 340                 if (relocType == RelocType.JAVA_CALL_DIRECT ||

 341                     relocType == RelocType.FOREIGN_CALL_INDIRECT_GOT) {
 342                     pecoffRelocType = IMAGE_RELOCATION.IMAGE_REL_AMD64_REL32;
 343                 } else if (relocType == RelocType.STUB_CALL_DIRECT) {
 344                     pecoffRelocType = IMAGE_RELOCATION.IMAGE_REL_AMD64_REL32;
 345                 } else if (relocType == RelocType.JAVA_CALL_INDIRECT) {




 346                     pecoffRelocType = IMAGE_RELOCATION.IMAGE_REL_AMD64_ABSOLUTE;


 347                 } else if (relocType == RelocType.METASPACE_GOT_REFERENCE ||
 348                            relocType == RelocType.EXTERNAL_PLT_TO_GOT) {


 349                     pecoffRelocType = IMAGE_RELOCATION.IMAGE_REL_AMD64_REL32;
 350                 } else if (relocType == RelocType.EXTERNAL_GOT_TO_PLT) {

 351                     pecoffRelocType = IMAGE_RELOCATION.IMAGE_REL_AMD64_ADDR64;
 352                 } else {
 353                     assert false : "Unhandled relocation type: " + relocType;
 354                 }
 355                 break;
 356             default:
 357                 System.out.println("Relocation Type mapping: Unhandled architecture");
 358         }
 359         return pecoffRelocType;
 360     }
 361 }
src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/pecoff/JPECoffRelocObject.java
Index Unified diffs Context diffs Sdiffs Frames Patch New Old Previous File Next File