src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/elf/JELFRelocObject.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/elf

src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/elf/JELFRelocObject.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.elf;
  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.BinaryContainer;
  34 import jdk.tools.jaotc.binformat.ByteContainer;
  35 import jdk.tools.jaotc.binformat.CodeContainer;
  36 import jdk.tools.jaotc.binformat.ReadOnlyDataContainer;
  37 import jdk.tools.jaotc.binformat.Relocation;
  38 import jdk.tools.jaotc.binformat.Relocation.RelocType;
  39 import jdk.tools.jaotc.binformat.Symbol;

  40 import jdk.tools.jaotc.binformat.Symbol.Binding;
  41 import jdk.tools.jaotc.binformat.Symbol.Kind;
  42 import jdk.tools.jaotc.jnilibelf.ELFContainer;
  43 import jdk.tools.jaotc.jnilibelf.ELFSymbol;
  44 import jdk.tools.jaotc.jnilibelf.JNIELFContainer;
  45 import jdk.tools.jaotc.jnilibelf.JNIELFRelocation;
  46 import jdk.tools.jaotc.jnilibelf.JNIELFTargetInfo;
  47 import jdk.tools.jaotc.jnilibelf.JNILibELFAPI.ELF;
  48 import jdk.tools.jaotc.jnilibelf.JNILibELFAPI.LibELF.Elf_Cmd;
  49 import jdk.tools.jaotc.jnilibelf.JNILibELFAPI.LibELF.Elf_Type;
  50 import jdk.tools.jaotc.jnilibelf.Pointer;
  51 
  52 public class JELFRelocObject {
  53 
  54     private final BinaryContainer binContainer;
  55 
  56     private final JNIELFContainer elfContainer;
  57 
  58     private final int segmentSize;
  59 
  60     public JELFRelocObject(BinaryContainer binContainer, String outputFileName, String aotVersion) {
  61         this.binContainer = binContainer;
  62         this.elfContainer = new JNIELFContainer(outputFileName, aotVersion);
  63         this.segmentSize = binContainer.getCodeSegmentSize();
  64     }
  65 
  66     private void createByteSection(ByteContainer c, int scnFlags) {






















  67         byte[] scnData = c.getByteArray();
  68         int scnType = ELF.SHT_PROGBITS;
  69         boolean zeros = !c.hasRelocations();

  70         if (zeros) {
  71             for (byte b : scnData) {
  72                 if (b != 0) {
  73                     zeros = false;
  74                     break;
  75                 }
  76             }
  77             if (zeros) {
  78                 scnType = ELF.SHT_NOBITS;
  79             }
  80         }
  81 
  82         int sectionId = elfContainer.createSection(c.getContainerName(), scnData, Elf_Type.ELF_T_BYTE, segmentSize, scnType, scnFlags, ELF.SHN_UNDEF, 0);
  83         c.setSectionId(sectionId);
  84         // Clear out code section data to allow for GC
  85         c.clear();
  86     }
  87 
  88     private void createCodeSection(CodeContainer c) {
  89         createByteSection(c, ELF.SHF_ALLOC | ELF.SHF_EXECINSTR);
  90     }
  91 
  92     private void createReadOnlySection(ReadOnlyDataContainer c) {
  93         createByteSection(c, ELF.SHF_ALLOC);
  94     }
  95 
  96     private void createReadWriteSection(ByteContainer c) {
  97         createByteSection(c, ELF.SHF_ALLOC | ELF.SHF_WRITE);
  98     }
  99 
 100     /**
 101      * Create an ELF relocatable object using jdk.tools.jaotc.jnilibelf API.
 102      *
 103      * @param relocationTable
 104      * @param symbols
 105      * @throws IOException throws {@code IOException} as a result of file system access failures.
 106      */
 107     public void createELFRelocObject(Map<Symbol, List<Relocation>> relocationTable, Collection<Symbol> symbols) throws IOException {
 108         // Allocate ELF Header
 109         elfContainer.createELFHeader(ELF.ET_REL);





 110 
 111         // Create text section
 112         createCodeSection(binContainer.getCodeContainer());
 113         createReadOnlySection(binContainer.getMetaspaceNamesContainer());
 114         createReadOnlySection(binContainer.getKlassesOffsetsContainer());
 115         createReadOnlySection(binContainer.getMethodsOffsetsContainer());
 116         createReadOnlySection(binContainer.getKlassesDependenciesContainer());
 117         createReadWriteSection(binContainer.getMetaspaceGotContainer());
 118         createReadWriteSection(binContainer.getMetadataGotContainer());
 119         createReadWriteSection(binContainer.getMethodStateContainer());
 120         createReadWriteSection(binContainer.getOopGotContainer());
 121         createReadWriteSection(binContainer.getMethodMetadataContainer());
 122         createReadOnlySection(binContainer.getStubsOffsetsContainer());
 123         createReadOnlySection(binContainer.getHeaderContainer().getContainer());
 124         createReadOnlySection(binContainer.getCodeSegmentsContainer());
 125         createReadOnlySection(binContainer.getConstantDataContainer());
 126         createReadOnlySection(binContainer.getConfigContainer());
 127 
 128         // createExternalLinkage();
 129 
 130         createCodeSection(binContainer.getExtLinkageContainer());
 131         createReadWriteSection(binContainer.getExtLinkageGOTContainer());
 132 
 133         // Get ELF symbol data from BinaryContainer object's symbol tables
 134         createELFSymbolTables(symbols);
 135 
 136         // Create string table section and symbol table sections in
 137         // that order since symtab section needs to set the index of strtab in sh_link field
 138         int strTabSectionIndex = elfContainer.createSection(".strtab", elfContainer.getStrTabContent().getBytes(StandardCharsets.UTF_8), Elf_Type.ELF_T_BYTE, 1, ELF.SHT_STRTAB, 0, ELF.SHN_UNDEF, 0);



















 139 
 140         // Now create .symtab section with the symtab data constructed. On Linux, sh_link of symtab
 141         // contains the index of string table its symbols reference and
 142         // sh_info contains the index of first non-local symbol
 143         int scnInfo = elfContainer.getFirstNonLocalSymbolIndex();
 144         int symTabSectionIndex = elfContainer.createSection(".symtab", getELFSymbolTableData(), Elf_Type.ELF_T_SYM, 8, ELF.SHT_SYMTAB, ELF.SHF_ALLOC, strTabSectionIndex, scnInfo);
 145 
 146         buildRelocations(relocationTable, symTabSectionIndex);
 147 
 148         // Now, finally, after creating all sections, create shstrtab section
 149         elfContainer.createSection(".shstrtab", elfContainer.getShStrTabContent().getBytes(StandardCharsets.UTF_8), Elf_Type.ELF_T_BYTE, 1, ELF.SHT_STRTAB, 0, ELF.SHN_UNDEF, 0);
 150 
 151         // Run elf_update
 152         elfContainer.elfUpdate(Elf_Cmd.ELF_C_NULL);
 153 
 154         // Run elfUpdate again to write it out.
 155         elfContainer.elfUpdate(Elf_Cmd.ELF_C_WRITE);
 156         // Finish ELF processing
 157         elfContainer.elfEnd();







































 158     }
 159 
 160     private void buildRelocations(Map<Symbol, List<Relocation>> relocationTable, final int symTabSectionIndex) {
 161         /*
 162          * Create relocation sections. This needs to be done after symbol table sections were
 163          * created since relocation entries will need indices of sections to which they apply.
 164          */
 165         createELFRelocationTables(relocationTable);
 166         createAllRelocationSections(new SymTabELFContainer(symTabSectionIndex));
 167     }
 168 
 169     /**
 170      * Construct ELF symbol data from BinaryContainer object's symbol tables. Both dynamic ELF
 171      * symbol table and ELF symbol table are created from BinaryContainer's symbol info.
 172      *
 173      * @param symbols
 174      */
 175     private void createELFSymbolTables(Collection<Symbol> symbols) {


 176         // First, create the initial null symbol. This is a local symbol.
 177         elfContainer.createELFSymbolEntry("", 0, 0, ELF.SHN_UNDEF, 0, 0, true);
 178 
 179         // Now create ELF symbol entries for all symbols.
 180         for (Symbol symbol : symbols) {
 181             // Get the index of section this symbol is defined in.
 182             int secHdrIndex = symbol.getSection().getSectionId();
 183             boolean isLocal = (symbol.getBinding() == Binding.LOCAL);
 184             ELFSymbol elfSymbol = elfContainer.createELFSymbolEntry(symbol.getName(), getELFTypeOf(symbol), getELFBindOf(symbol), secHdrIndex, symbol.getSize(), symbol.getOffset(), isLocal);
 185             symbol.setElfSymbol(elfSymbol);
 186         }
 187     }
 188 
 189     /**
 190      * Construct ELF symbol data from BinaryContainer object's symbol tables.
 191      *
 192      * @return a byte array containing the symbol table
 193      */
 194     private byte[] getELFSymbolTableData() {
 195         final int entrySize = JNIELFTargetInfo.sizeOfSymtabEntry();
 196 
 197         // First, add all local symbols.
 198         List<ELFSymbol> localSymbols = elfContainer.getLocalSymbols();
 199         List<ELFSymbol> globalSymbols = elfContainer.getGlobalSymbols();
 200 
 201         int localSymCount = localSymbols.size();
 202         int globalSymCount = globalSymbols.size();
 203         byte[] sectionDataArray = new byte[(localSymCount + globalSymCount) * entrySize];
 204 
 205         for (int i = 0; i < localSymCount; i++) {
 206             ELFSymbol symbol = localSymbols.get(i);
 207             Pointer address = symbol.getAddress();
 208             address.copyBytesTo(sectionDataArray, entrySize, i * entrySize);
 209         }
 210 
 211         // Next, add all global symbols.
 212 
 213         for (int i = 0; i < globalSymCount; i++) {
 214             ELFSymbol symbol = globalSymbols.get(i);
 215             Pointer address = symbol.getAddress();
 216             address.copyBytesTo(sectionDataArray, entrySize, (localSymCount + i) * entrySize);
 217         }
 218 
 219         return sectionDataArray;
 220     }
 221 
 222     private static int getELFTypeOf(Symbol sym) {
 223         Kind kind = sym.getKind();
 224         if (kind == Symbol.Kind.NATIVE_FUNCTION || kind == Symbol.Kind.JAVA_FUNCTION) {
 225             return ELF.STT_FUNC;
 226         } else if (kind == Symbol.Kind.OBJECT) {
 227             return ELF.STT_OBJECT;
 228         }
 229         return ELF.STT_NOTYPE;
 230     }
 231 
 232     private static int getELFBindOf(Symbol sym) {
 233         Binding binding = sym.getBinding();
 234         if (binding == Symbol.Binding.GLOBAL) {
 235             return ELF.STB_GLOBAL;
 236         }
 237         return ELF.STB_LOCAL;
 238     }
 239 
 240     /**
 241      * Construct ELF relocation section data from BinaryContainer object's relocation tables.
 242      *

 243      * @param relocationTable
 244      */
 245     private void createELFRelocationTables(Map<Symbol, List<Relocation>> relocationTable) {



 246         /*
 247          * For each of the symbols with associated relocation records, create an ELF relocation
 248          * entry.
 249          */
 250         for (Map.Entry<Symbol, List<Relocation>> entry : relocationTable.entrySet()) {
 251             List<Relocation> relocs = entry.getValue();
 252             Symbol symbol = entry.getKey();
 253 
 254             for (Relocation reloc : relocs) {
 255                 createRelocation(symbol, reloc);
 256             }
 257         }
 258 
 259         for (Map.Entry<Symbol, Relocation> entry : binContainer.getUniqueRelocationTable().entrySet()) {
 260             createRelocation(entry.getKey(), entry.getValue());
 261         }


 262     }
 263 
 264     private void createRelocation(Symbol symbol, Relocation reloc) {
 265         RelocType relocType = reloc.getType();

 266         int elfRelocType = getELFRelocationType(relocType);





 267 
 268         switch (relocType) {
 269             case FOREIGN_CALL_DIRECT:
 270             case JAVA_CALL_DIRECT:
 271             case STUB_CALL_DIRECT:
 272             case FOREIGN_CALL_INDIRECT_GOT: {
 273                 // Create relocation entry
 274                 int addend = -4; // Size in bytes of the patch location

 275                 // Relocation should be applied at the location after call operand
 276                 int offset = reloc.getOffset() + reloc.getSize() + addend;
 277                 elfContainer.createELFRelocationEntry(reloc.getSection(), offset, elfRelocType, addend, symbol.getElfSymbol());
 278                 break;
 279             }
 280             case FOREIGN_CALL_DIRECT_FAR: {
 281                 // Create relocation entry
 282                 int addend = -8; // Size in bytes of the patch location
 283                 // Relocation should be applied at the location after call operand
 284                 // 10 = 2 (jmp [r]) + 8 (imm64)
 285                 int offset = reloc.getOffset() + reloc.getSize() + addend - 2;
 286                 elfContainer.createELFRelocationEntry(reloc.getSection(), offset, elfRelocType, addend, symbol.getElfSymbol());
 287                 break;
 288             }
 289             case FOREIGN_CALL_INDIRECT:
 290             case JAVA_CALL_INDIRECT:
 291             case STUB_CALL_INDIRECT: {
 292                 // Do nothing.
 293                 break;
 294             }
 295             case EXTERNAL_DATA_REFERENCE_FAR: {
 296                 // Create relocation entry
 297                 int addend = -4; // Size of 32-bit address of the GOT
 298                 /*
 299                  * Relocation should be applied before the test instruction to the move instruction.
 300                  * reloc.getOffset() points to the test instruction after the instruction that loads
 301                  * the address of polling page. So set the offset appropriately.
 302                  */
 303                 int offset = reloc.getOffset() + addend;
 304                 elfContainer.createELFRelocationEntry(reloc.getSection(), offset, elfRelocType, addend, symbol.getElfSymbol());
 305                 break;
 306             }
 307             case METASPACE_GOT_REFERENCE:
 308             case EXTERNAL_PLT_TO_GOT:
 309             case STATIC_STUB_TO_STATIC_METHOD:
 310             case STATIC_STUB_TO_HOTSPOT_LINKAGE_GOT: {
 311                 int addend = -4; // Size of 32-bit address of the GOT
 312                 /*
 313                  * Relocation should be applied before the test instruction to the move instruction.
 314                  * reloc.getOffset() points to the test instruction after the instruction that loads
 315                  * the address of polling page. So set the offset appropriately.

 316                  */
 317                 int offset = reloc.getOffset() + addend;
 318                 elfContainer.createELFRelocationEntry(reloc.getSection(), offset, elfRelocType, addend, symbol.getElfSymbol());
 319                 break;
 320             }
 321             case EXTERNAL_GOT_TO_PLT:
 322             case LOADTIME_ADDRESS: {
 323                 // this is load time relocations
 324                 elfContainer.createELFRelocationEntry(reloc.getSection(), reloc.getOffset(), elfRelocType, 0, symbol.getElfSymbol());
 325                 break;
 326             }
 327             default:
 328                 throw new InternalError("Unhandled relocation type: " + relocType);
 329         }

 330     }
 331 
 332     // TODO: Populate the mapping of RelocType to ELF relocation types
 333     private static int getELFRelocationType(RelocType relocType) {
 334         int elfRelocType = 0; // R_<ARCH>_NONE if #define'd to 0 for all values of ARCH
 335         switch (JNIELFTargetInfo.getELFArch()) {
 336             case ELF.EM_X64_64:
 337                 // Return R_X86_64_* entries based on relocType
 338                 if (relocType == RelocType.FOREIGN_CALL_DIRECT || relocType == RelocType.JAVA_CALL_DIRECT || relocType == RelocType.FOREIGN_CALL_INDIRECT_GOT) {
 339                     elfRelocType = JNIELFRelocation.X86_64.R_X86_64_PLT32;


 340                 } else if (relocType == RelocType.STUB_CALL_DIRECT) {
 341                     elfRelocType = JNIELFRelocation.X86_64.R_X86_64_PC32;
 342                 } else if (relocType == RelocType.FOREIGN_CALL_DIRECT_FAR) {
 343                     elfRelocType = JNIELFRelocation.X86_64.R_X86_64_64;
 344                 } else if (relocType == RelocType.FOREIGN_CALL_INDIRECT || relocType == RelocType.JAVA_CALL_INDIRECT || relocType == RelocType.STUB_CALL_INDIRECT) {
 345                     elfRelocType = JNIELFRelocation.X86_64.R_X86_64_NONE;


 346                 } else if ((relocType == RelocType.EXTERNAL_DATA_REFERENCE_FAR)) {
 347                     elfRelocType = JNIELFRelocation.X86_64.R_X86_64_GOTPCREL;
 348                 } else if (relocType == RelocType.METASPACE_GOT_REFERENCE || relocType == RelocType.EXTERNAL_PLT_TO_GOT || relocType == RelocType.STATIC_STUB_TO_STATIC_METHOD ||


 349                                 relocType == RelocType.STATIC_STUB_TO_HOTSPOT_LINKAGE_GOT) {
 350                     elfRelocType = JNIELFRelocation.X86_64.R_X86_64_PC32;
 351                 } else if (relocType == RelocType.EXTERNAL_GOT_TO_PLT || relocType == RelocType.LOADTIME_ADDRESS) {
 352                     elfRelocType = JNIELFRelocation.X86_64.R_X86_64_64;

 353                 } else {
 354                     assert false : "Unhandled relocation type: " + relocType;
 355                 }
 356                 break;
 357             default:
 358                 System.out.println("Relocation Type mapping: Unhandled architecture");
 359         }
 360         return elfRelocType;
 361     }
 362 
 363     private void createAllRelocationSections(ELFContainer symtab) {
 364         for (Map.Entry<ELFContainer, ArrayList<Pointer>> entry : elfContainer.getRelocTables().entrySet()) {
 365             createRelocationSection(entry.getKey(), entry.getValue(), symtab);
 366         }
 367     }
 368 
 369     private void createRelocationSection(ELFContainer container, ArrayList<Pointer> relocations, ELFContainer symtab) {
 370         String secName = container.getContainerName();
 371         int entrySize = JNIELFTargetInfo.sizeOfRelocEntry();
 372         int numEntries = relocations.size();
 373         byte[] sectionDataBytes = new byte[numEntries * entrySize];
 374 
 375         for (int index = 0; index < relocations.size(); index++) {
 376             Pointer entry = relocations.get(index);
 377             entry.copyBytesTo(sectionDataBytes, entrySize, index * entrySize);
 378         }
 379         String fullSecName;
 380         // If relocDat is non-null create section
 381         if (sectionDataBytes.length > 0) {
 382             int scnType;
 383             Elf_Type dataType;
 384             if (JNIELFTargetInfo.createReloca() == 0) {
 385                 scnType = ELF.SHT_REL;
 386                 dataType = Elf_Type.ELF_T_REL;
 387                 fullSecName = ".rel" + secName;
 388             } else {
 389                 scnType = ELF.SHT_RELA;
 390                 dataType = Elf_Type.ELF_T_RELA;
 391                 fullSecName = ".rela" + secName;
 392             }
 393             // assert compareBytes(relocData.toByteArray(), sectionDataBytes) : "******* Bad array
 394             // copy";
 395             // sh_link holds the index of section header of symbol table associated with this
 396             // relocation table.
 397             // sh_info holds the index of section header to which this relocation table applies
 398             // to.
 399             elfContainer.createSection(fullSecName, sectionDataBytes, dataType, 8, scnType, ELF.SHF_ALLOC, symtab.getSectionId(), container.getSectionId());
 400         }
 401     }
 402 
 403     private static class SymTabELFContainer implements ELFContainer {
 404         private final int symTabSectionIndex;
 405 
 406         public SymTabELFContainer(int symTabSectionIndex) {
 407             this.symTabSectionIndex = symTabSectionIndex;
 408         }
 409 
 410         @Override
 411         public String getContainerName() {
 412             return ".symtab";
 413         }
 414 
 415         @Override
 416         public int getSectionId() {
 417             return symTabSectionIndex;
 418         }
 419     }
 420 }
   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.elf;
  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.elf.Elf;
  46 import jdk.tools.jaotc.binformat.elf.ElfSymbol;
  47 import jdk.tools.jaotc.binformat.elf.ElfTargetInfo;
  48 import jdk.tools.jaotc.binformat.elf.Elf.Elf64_Ehdr;
  49 import jdk.tools.jaotc.binformat.elf.Elf.Elf64_Shdr;
  50 import jdk.tools.jaotc.binformat.elf.Elf.Elf64_Sym;
  51 import jdk.tools.jaotc.binformat.elf.Elf.Elf64_Rel;
  52 import jdk.tools.jaotc.binformat.elf.Elf.Elf64_Rela;
  53 
  54 public class JELFRelocObject {
  55 
  56     private final BinaryContainer binContainer;
  57 
  58     private final ElfContainer elfContainer;
  59 
  60     private final int segmentSize;
  61 
  62     public JELFRelocObject(BinaryContainer binContainer, String outputFileName, String aotVersion) {
  63         this.binContainer = binContainer;
  64         this.elfContainer = new ElfContainer(outputFileName, aotVersion);
  65         this.segmentSize = binContainer.getCodeSegmentSize();
  66     }
  67 
  68     private ElfSection createByteSection(ArrayList<ElfSection>sections,
  69                                          String sectName,
  70                                          byte [] scnData,
  71                                          boolean hasRelocs,
  72                                          int scnFlags,
  73                                          int scnType) {
  74 
  75         ElfSection sect = new ElfSection(sectName,
  76                                          scnData,
  77                                          scnFlags,
  78                                          scnType,
  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<ElfSection>sections,
  88                                    ByteContainer c, int scnFlags) {
  89         ElfSection sect;
  90         boolean hasRelocs = c.hasRelocations();
  91         byte[] scnData = c.getByteArray();
  92 
  93         int scnType = Elf64_Shdr.SHT_PROGBITS;
  94         boolean zeros = hasRelocs;
  95         if (zeros) {
  96             for (byte b : scnData) {
  97                 if (b != 0) {
  98                     zeros = false;
  99                     break;
 100                 }
 101             }
 102             if (zeros) {
 103                 scnType = Elf64_Shdr.SHT_NOBITS;
 104             }
 105         }
 106 
 107         sect = createByteSection(sections, c.getContainerName(),
 108                                  scnData, hasRelocs,
 109                                  scnFlags, scnType);
 110         c.setSectionId(sect.getSectionId());
 111     }
 112 
 113     private void createCodeSection(ArrayList<ElfSection>sections, CodeContainer c) {
 114         createByteSection(sections, c, Elf64_Shdr.SHF_ALLOC | Elf64_Shdr.SHF_EXECINSTR);
 115     }
 116 
 117     private void createReadOnlySection(ArrayList<ElfSection>sections, ReadOnlyDataContainer c) {
 118         createByteSection(sections, c, Elf64_Shdr.SHF_ALLOC);
 119     }
 120 
 121     private void createReadWriteSection(ArrayList<ElfSection>sections, ByteContainer c) {
 122         createByteSection(sections, c, Elf64_Shdr.SHF_ALLOC | Elf64_Shdr.SHF_WRITE);
 123     }
 124 
 125     /**
 126      * Create an ELF relocatable object
 127      *
 128      * @param relocationTable
 129      * @param symbols
 130      * @throws IOException throws {@code IOException} as a result of file system access failures.
 131      */
 132     public void createELFRelocObject(Map<Symbol, List<Relocation>> relocationTable, Collection<Symbol> symbols) throws IOException {
 133         // Allocate ELF Header
 134         ElfHeader eh = new ElfHeader();
 135 
 136         ArrayList<ElfSection> sections = new ArrayList<ElfSection>();
 137 
 138         // Create the null section
 139         createByteSection(sections, null, null, false, 0, 0);
 140 
 141         // Create text section
 142         createCodeSection(sections, binContainer.getCodeContainer());
 143         createReadOnlySection(sections, binContainer.getMetaspaceNamesContainer());
 144         createReadOnlySection(sections, binContainer.getKlassesOffsetsContainer());
 145         createReadOnlySection(sections, binContainer.getMethodsOffsetsContainer());
 146         createReadOnlySection(sections, binContainer.getKlassesDependenciesContainer());
 147         createReadWriteSection(sections, binContainer.getMetaspaceGotContainer());
 148         createReadWriteSection(sections, binContainer.getMetadataGotContainer());
 149         createReadWriteSection(sections, binContainer.getMethodStateContainer());
 150         createReadWriteSection(sections, binContainer.getOopGotContainer());
 151         createReadWriteSection(sections, binContainer.getMethodMetadataContainer());
 152         createReadOnlySection(sections, binContainer.getStubsOffsetsContainer());
 153         createReadOnlySection(sections, binContainer.getHeaderContainer().getContainer());
 154         createReadOnlySection(sections, binContainer.getCodeSegmentsContainer());
 155         createReadOnlySection(sections, binContainer.getConstantDataContainer());
 156         createReadOnlySection(sections, binContainer.getConfigContainer());
 157 
 158         // createExternalLinkage();
 159 
 160         createCodeSection(sections, binContainer.getExtLinkageContainer());
 161         createReadWriteSection(sections, binContainer.getExtLinkageGOTContainer());
 162 
 163         // Get ELF symbol data from BinaryContainer object's symbol tables
 164         ElfSymtab symtab = createELFSymbolTables(sections, symbols);
 165 
 166         // Create string table section and symbol table sections in
 167         // that order since symtab section needs to set the index of
 168         // strtab in sh_link field
 169         ElfSection strTabSection = createByteSection(sections,
 170                                                      ".strtab",
 171                                                      symtab.getStrtabArray(),
 172                                                      false,
 173                                                      0,
 174                                                      Elf64_Shdr.SHT_STRTAB);
 175 
 176         // Now create .symtab section with the symtab data constructed.
 177         // On Linux, sh_link of symtab contains the index of string table
 178         // its symbols reference and sh_info contains the index of first
 179         // non-local symbol
 180         ElfSection symTabSection = createByteSection(sections,
 181                                                     ".symtab",
 182                                                     symtab.getSymtabArray(),
 183                                                     false,
 184                                                     0,
 185                                                     Elf64_Shdr.SHT_SYMTAB);
 186         symTabSection.setLink(strTabSection.getSectionId());
 187         symTabSection.setInfo(symtab.getNumLocalSyms());
 188 
 189         ElfRelocTable elfRelocTable = createElfRelocTable(sections,
 190                                                           relocationTable);



 191 
 192         createElfRelocSections(sections, elfRelocTable, symTabSection.getSectionId());
 193 
 194         // Now, finally, after creating all sections, create shstrtab section
 195         ElfSection shStrTabSection = createByteSection(sections,
 196                                                     ".shstrtab",
 197                                                     null,
 198                                                     false,
 199                                                     0,
 200                                                     Elf64_Shdr.SHT_STRTAB);
 201         eh.setSectionStrNdx(shStrTabSection.getSectionId());
 202 
 203         // Update all section offsets and the Elf header section offset
 204         // Write the Header followed by the contents of each section
 205         // and then the section structures (section table).
 206         int file_offset = Elf64_Ehdr.totalsize;
 207 
 208         // and round it up
 209         file_offset = (file_offset + (sections.get(1).getDataAlign()-1)) &
 210                       ~((sections.get(1).getDataAlign()-1));
 211 
 212         // Calc file offsets for section data skipping null section
 213         for (int i = 1; i < sections.size(); i++) {
 214             ElfSection sect = sections.get(i);
 215             file_offset = (file_offset + (sect.getDataAlign()-1)) &
 216                            ~((sect.getDataAlign()-1));
 217             sect.setOffset(file_offset);
 218             file_offset += sect.getSize();
 219         }
 220 
 221         // Align the section table
 222         file_offset = (file_offset + (ElfSection.getShdrAlign()-1)) &
 223                       ~((ElfSection.getShdrAlign()-1));
 224 
 225         // Update the Elf Header with the offset of the first Elf64_Shdr
 226         // and the number of sections.
 227         eh.setSectionOff(file_offset);
 228         eh.setSectionNum(sections.size());
 229 
 230         // Write out the Header
 231         elfContainer.writeBytes(eh.getArray());
 232 
 233         // Write out each section contents skipping null section
 234         for (int i = 1; i < sections.size(); i++) {
 235             ElfSection sect = sections.get(i);
 236             elfContainer.writeBytes(sect.getDataArray(), sect.getDataAlign());
 237         }
 238 
 239         // Write out the section table
 240         for (int i = 0; i < sections.size(); i++) {
 241             ElfSection sect = sections.get(i);
 242             elfContainer.writeBytes(sect.getArray(), ElfSection.getShdrAlign());
 243         }
 244 
 245         elfContainer.close();






 246     }

 247     /**
 248      * Construct ELF symbol data from BinaryContainer object's symbol tables. Both dynamic ELF
 249      * symbol table and ELF symbol table are created from BinaryContainer's symbol info.
 250      *
 251      * @param symbols
 252      */
 253     private ElfSymtab createELFSymbolTables(ArrayList<ElfSection> sections, Collection<Symbol> symbols) {
 254         ElfSymtab symtab = new ElfSymtab();
 255 
 256         // First, create the initial null symbol. This is a local symbol.
 257         symtab.addSymbolEntry("", (byte)0, (byte)0, Elf64_Shdr.SHN_UNDEF, 0, 0);
 258 
 259         // Now create ELF symbol entries for all symbols.
 260         for (Symbol symbol : symbols) {
 261             // Get the index of section this symbol is defined in.
 262             int secHdrIndex = symbol.getSection().getSectionId();
 263             ElfSymbol elfSymbol = symtab.addSymbolEntry(symbol.getName(), getELFTypeOf(symbol), getELFBindOf(symbol), (byte)secHdrIndex, symbol.getOffset(), symbol.getSize());
 264             symbol.setNativeSymbol((NativeSymbol)elfSymbol);


 265         }
 266         return (symtab);




























 267     }
 268 
 269     private static byte getELFTypeOf(Symbol sym) {



 270         Kind kind = sym.getKind();
 271         if (kind == Symbol.Kind.NATIVE_FUNCTION || kind == Symbol.Kind.JAVA_FUNCTION) {
 272             return Elf64_Sym.STT_FUNC;
 273         } else if (kind == Symbol.Kind.OBJECT) {
 274             return Elf64_Sym.STT_OBJECT;
 275         }
 276         return Elf64_Sym.STT_NOTYPE;
 277     }
 278 
 279     private static byte getELFBindOf(Symbol sym) {
 280         Binding binding = sym.getBinding();
 281         if (binding == Symbol.Binding.GLOBAL) {
 282             return Elf64_Sym.STB_GLOBAL;
 283         }
 284         return Elf64_Sym.STB_LOCAL;
 285     }
 286 
 287     /**
 288      * Construct a Elf relocation table from BinaryContainer object's relocation tables.
 289      *
 290      * @param sections
 291      * @param relocationTable
 292      */
 293     private ElfRelocTable createElfRelocTable(ArrayList<ElfSection> sections,
 294                                               Map<Symbol, List<Relocation>> relocationTable) {
 295 
 296         ElfRelocTable elfRelocTable = new ElfRelocTable(sections.size());
 297         /*
 298          * For each of the symbols with associated relocation records, create a Elf relocation
 299          * entry.
 300          */
 301         for (Map.Entry<Symbol, List<Relocation>> entry : relocationTable.entrySet()) {
 302             List<Relocation> relocs = entry.getValue();
 303             Symbol symbol = entry.getKey();
 304 
 305             for (Relocation reloc : relocs) {
 306                 createRelocation(symbol, reloc, elfRelocTable);
 307             }
 308         }
 309 
 310         for (Map.Entry<Symbol, Relocation> entry : binContainer.getUniqueRelocationTable().entrySet()) {
 311             createRelocation(entry.getKey(), entry.getValue(), elfRelocTable);
 312         }
 313 
 314         return (elfRelocTable);
 315     }
 316 
 317     private void createRelocation(Symbol symbol, Relocation reloc, ElfRelocTable elfRelocTable) {
 318         RelocType relocType = reloc.getType();
 319 
 320         int elfRelocType = getELFRelocationType(relocType);
 321         ElfSymbol sym = (ElfSymbol)symbol.getNativeSymbol();
 322         int symno = sym.getIndex();
 323         int sectindex = reloc.getSection().getSectionId();
 324         int offset = reloc.getOffset();
 325         int addend = 0;
 326 
 327         switch (relocType) {
 328             case FOREIGN_CALL_DIRECT:
 329             case JAVA_CALL_DIRECT:
 330             case STUB_CALL_DIRECT:
 331             case FOREIGN_CALL_INDIRECT_GOT: {
 332                 // Create relocation entry
 333                 // System.out.println("getELFRelocationType: PLT relocation type using X86_64_RELOC_BRANCH");
 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         elfRelocTable.createRelocationEntry(sectindex, offset, symno, elfRelocType, addend);
 387     }
 388 

 389     private static int getELFRelocationType(RelocType relocType) {
 390         int elfRelocType = 0; // R_<ARCH>_NONE if #define'd to 0 for all values of ARCH
 391         switch (ElfTargetInfo.getElfArch()) {
 392             case Elf64_Ehdr.EM_X86_64:
 393                 // Return R_X86_64_* entries based on relocType
 394                 if (relocType == RelocType.FOREIGN_CALL_DIRECT ||
 395                     relocType == RelocType.JAVA_CALL_DIRECT ||
 396                     relocType == RelocType.FOREIGN_CALL_INDIRECT_GOT) {
 397                     elfRelocType = Elf64_Rela.R_X86_64_PLT32;
 398                 } else if (relocType == RelocType.STUB_CALL_DIRECT) {
 399                     elfRelocType = Elf64_Rela.R_X86_64_PC32;
 400                 } else if (relocType == RelocType.FOREIGN_CALL_DIRECT_FAR) {
 401                     elfRelocType = Elf64_Rela.R_X86_64_64;
 402                 } else if (relocType == RelocType.FOREIGN_CALL_INDIRECT ||
 403                            relocType == RelocType.JAVA_CALL_INDIRECT ||
 404                            relocType == RelocType.STUB_CALL_INDIRECT) {
 405                     elfRelocType = Elf64_Rela.R_X86_64_NONE;
 406                 } else if ((relocType == RelocType.EXTERNAL_DATA_REFERENCE_FAR)) {
 407                     elfRelocType = Elf64_Rela.R_X86_64_GOTPCREL;
 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                     elfRelocType = Elf64_Rela.R_X86_64_PC32;
 413                 } else if (relocType == RelocType.EXTERNAL_GOT_TO_PLT ||
 414                            relocType == RelocType.LOADTIME_ADDRESS) {
 415                     elfRelocType = Elf64_Rela.R_X86_64_64;
 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 elfRelocType;
 424     }
 425 
 426     private void createElfRelocSections(ArrayList<ElfSection> sections,
 427                                         ElfRelocTable elfRelocTable,
 428                                         int symtabsectidx) {
 429 
 430         // Grab count before we create new sections
 431         int count = sections.size();
 432 
 433         for (int i = 0; i < count; i++) {
 434             if (elfRelocTable.getNumRelocs(i) > 0) {
 435                 ElfSection sect = sections.get(i);
 436                 String relname = ".rela" + sect.getName();
 437                 ElfSection relocSection = createByteSection(sections,
 438                                                             relname,
 439                                                             elfRelocTable.getRelocData(i),
 440                                                             false,
 441                                                             0,
 442                                                             Elf64_Shdr.SHT_RELA);
 443                 relocSection.setLink(symtabsectidx);
 444                 relocSection.setInfo(sect.getSectionId());


























 445             }









 446         }
 447     }
 448 }
src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/elf/JELFRelocObject.java
Index Unified diffs Context diffs Sdiffs Wdiffs Patch New Old Previous File Next File