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

src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/elf/JELFRelocObject.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.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 align,
  73                                          int scnFlags,
  74                                          int scnType) {
  75 
  76         ElfSection sect = new ElfSection(sectName,
  77                                          scnData,
  78                                          scnFlags,
  79                                          scnType,
  80                                          hasRelocs,
  81                                          align,
  82                                          sections.size());
  83         // Add this section to our list
  84         sections.add(sect);
  85 
  86         return (sect);
  87     }
  88 
  89     private void createByteSection(ArrayList<ElfSection>sections,
  90                                    ByteContainer c, int scnFlags) {
  91         ElfSection sect;
  92         boolean hasRelocs = c.hasRelocations();
  93         byte[] scnData = c.getByteArray();
  94 
  95         int scnType = Elf64_Shdr.SHT_PROGBITS;
  96         boolean zeros = !hasRelocs;
  97         if (zeros) {
  98             for (byte b : scnData) {
  99                 if (b != 0) {
 100                     zeros = false;
 101                     break;
 102                 }
 103             }
 104             if (zeros) {
 105                 scnType = Elf64_Shdr.SHT_NOBITS;
 106             }
 107         }
 108 
 109         sect = createByteSection(sections, c.getContainerName(),
 110                                  scnData, hasRelocs, segmentSize,
 111                                  scnFlags, scnType);
 112         c.setSectionId(sect.getSectionId());
 113     }
 114 
 115     private void createCodeSection(ArrayList<ElfSection>sections, CodeContainer c) {
 116         createByteSection(sections, c, Elf64_Shdr.SHF_ALLOC | Elf64_Shdr.SHF_EXECINSTR);
 117     }
 118 
 119     private void createReadOnlySection(ArrayList<ElfSection>sections, ReadOnlyDataContainer c) {
 120         createByteSection(sections, c, Elf64_Shdr.SHF_ALLOC);
 121     }
 122 
 123     private void createReadWriteSection(ArrayList<ElfSection>sections, ByteContainer c) {
 124         createByteSection(sections, c, Elf64_Shdr.SHF_ALLOC | Elf64_Shdr.SHF_WRITE);
 125     }
 126 
 127     /**
 128      * Create an ELF relocatable object
 129      *
 130      * @param relocationTable
 131      * @param symbols
 132      * @throws IOException throws {@code IOException} as a result of file system access failures.
 133      */
 134     public void createELFRelocObject(Map<Symbol, List<Relocation>> relocationTable, Collection<Symbol> symbols) throws IOException {
 135         // Allocate ELF Header
 136         ElfHeader eh = new ElfHeader();
 137 
 138         ArrayList<ElfSection> sections = new ArrayList<ElfSection>();
 139 
 140         // Create the null section
 141         createByteSection(sections, null, null, false, 1, 0, 0);
 142 
 143         // Create text section
 144         createCodeSection(sections, binContainer.getCodeContainer());
 145         createReadOnlySection(sections, binContainer.getMetaspaceNamesContainer());
 146         createReadOnlySection(sections, binContainer.getKlassesOffsetsContainer());
 147         createReadOnlySection(sections, binContainer.getMethodsOffsetsContainer());
 148         createReadOnlySection(sections, binContainer.getKlassesDependenciesContainer());
 149         createReadWriteSection(sections, binContainer.getMetaspaceGotContainer());
 150         createReadWriteSection(sections, binContainer.getMetadataGotContainer());
 151         createReadWriteSection(sections, binContainer.getMethodStateContainer());
 152         createReadWriteSection(sections, binContainer.getOopGotContainer());
 153         createReadWriteSection(sections, binContainer.getMethodMetadataContainer());
 154         createReadOnlySection(sections, binContainer.getStubsOffsetsContainer());
 155         createReadOnlySection(sections, binContainer.getHeaderContainer().getContainer());
 156         createReadOnlySection(sections, binContainer.getCodeSegmentsContainer());
 157         createReadOnlySection(sections, binContainer.getConstantDataContainer());
 158         createReadOnlySection(sections, binContainer.getConfigContainer());
 159 
 160         // createExternalLinkage();
 161 
 162         createCodeSection(sections, binContainer.getExtLinkageContainer());

 163         createReadWriteSection(sections, binContainer.getExtLinkageGOTContainer());
 164 
 165         // Get ELF symbol data from BinaryContainer object's symbol tables
 166         ElfSymtab symtab = createELFSymbolTables(sections, symbols);
 167 
 168         // Create string table section and symbol table sections in
 169         // that order since symtab section needs to set the index of
 170         // strtab in sh_link field
 171         ElfSection strTabSection = createByteSection(sections,
 172                                                      ".strtab",
 173                                                      symtab.getStrtabArray(),
 174                                                      false,
 175                                                      1,
 176                                                      0,
 177                                                      Elf64_Shdr.SHT_STRTAB);
 178 
 179         // Now create .symtab section with the symtab data constructed.
 180         // On Linux, sh_link of symtab contains the index of string table
 181         // its symbols reference and sh_info contains the index of first
 182         // non-local symbol
 183         ElfSection symTabSection = createByteSection(sections,
 184                                                     ".symtab",
 185                                                     symtab.getSymtabArray(),
 186                                                     false,
 187                                                     8,
 188                                                     0,
 189                                                     Elf64_Shdr.SHT_SYMTAB);
 190         symTabSection.setLink(strTabSection.getSectionId());
 191         symTabSection.setInfo(symtab.getNumLocalSyms());
 192 
 193         ElfRelocTable elfRelocTable = createElfRelocTable(sections,
 194                                                           relocationTable);
 195 
 196         createElfRelocSections(sections, elfRelocTable, symTabSection.getSectionId());
 197 
 198         // Now, finally, after creating all sections, create shstrtab section
 199         ElfSection shStrTabSection = createByteSection(sections,
 200                                                     ".shstrtab",
 201                                                     null,
 202                                                     false,
 203                                                     1,
 204                                                     0,
 205                                                     Elf64_Shdr.SHT_STRTAB);
 206         eh.setSectionStrNdx(shStrTabSection.getSectionId());
 207 
 208         // Update all section offsets and the Elf header section offset
 209         // Write the Header followed by the contents of each section
 210         // and then the section structures (section table).
 211         int file_offset = Elf64_Ehdr.totalsize;
 212 
 213         // and round it up
 214         file_offset = (file_offset + (sections.get(1).getDataAlign()-1)) &
 215                       ~((sections.get(1).getDataAlign()-1));
 216 
 217         // Calc file offsets for section data skipping null section
 218         for (int i = 1; i < sections.size(); i++) {
 219             ElfSection sect = sections.get(i);
 220             file_offset = (file_offset + (sect.getDataAlign()-1)) &
 221                            ~((sect.getDataAlign()-1));
 222             sect.setOffset(file_offset);
 223             file_offset += sect.getSize();
 224         }
 225 
 226         // Align the section table
 227         file_offset = (file_offset + (ElfSection.getShdrAlign()-1)) &
 228                       ~((ElfSection.getShdrAlign()-1));
 229 
 230         // Update the Elf Header with the offset of the first Elf64_Shdr
 231         // and the number of sections.
 232         eh.setSectionOff(file_offset);
 233         eh.setSectionNum(sections.size());
 234 
 235         // Write out the Header
 236         elfContainer.writeBytes(eh.getArray());
 237 
 238         // Write out each section contents skipping null section
 239         for (int i = 1; i < sections.size(); i++) {
 240             ElfSection sect = sections.get(i);
 241             elfContainer.writeBytes(sect.getDataArray(), sect.getDataAlign());
 242         }
 243 
 244         // Write out the section table
 245         for (int i = 0; i < sections.size(); i++) {
 246             ElfSection sect = sections.get(i);
 247             elfContainer.writeBytes(sect.getArray(), ElfSection.getShdrAlign());
 248         }
 249 
 250         elfContainer.close();
 251     }

 252     /**
 253      * Construct ELF symbol data from BinaryContainer object's symbol tables. Both dynamic ELF
 254      * symbol table and ELF symbol table are created from BinaryContainer's symbol info.
 255      *
 256      * @param symbols
 257      */
 258     private ElfSymtab createELFSymbolTables(ArrayList<ElfSection> sections, Collection<Symbol> symbols) {
 259         ElfSymtab symtab = new ElfSymtab();
 260 
 261         // First, create the initial null symbol. This is a local symbol.
 262         symtab.addSymbolEntry("", (byte)0, (byte)0, Elf64_Shdr.SHN_UNDEF, 0, 0);
 263 
 264         // Now create ELF symbol entries for all symbols.
 265         for (Symbol symbol : symbols) {
 266             // Get the index of section this symbol is defined in.
 267             int secHdrIndex = symbol.getSection().getSectionId();
 268             ElfSymbol elfSymbol = symtab.addSymbolEntry(symbol.getName(), getELFTypeOf(symbol), getELFBindOf(symbol), (byte)secHdrIndex, symbol.getOffset(), symbol.getSize());
 269             symbol.setNativeSymbol((NativeSymbol)elfSymbol);
 270         }
 271         return (symtab);
 272     }
 273 
 274     private static byte getELFTypeOf(Symbol sym) {
 275         Kind kind = sym.getKind();
 276         if (kind == Symbol.Kind.NATIVE_FUNCTION || kind == Symbol.Kind.JAVA_FUNCTION) {
 277             return Elf64_Sym.STT_FUNC;
 278         } else if (kind == Symbol.Kind.OBJECT) {
 279             return Elf64_Sym.STT_OBJECT;
 280         }
 281         return Elf64_Sym.STT_NOTYPE;
 282     }
 283 
 284     private static byte getELFBindOf(Symbol sym) {
 285         Binding binding = sym.getBinding();
 286         if (binding == Symbol.Binding.GLOBAL) {
 287             return Elf64_Sym.STB_GLOBAL;
 288         }
 289         return Elf64_Sym.STB_LOCAL;
 290     }
 291 
 292     /**
 293      * Construct a Elf relocation table from BinaryContainer object's relocation tables.
 294      *
 295      * @param sections
 296      * @param relocationTable
 297      */
 298     private ElfRelocTable createElfRelocTable(ArrayList<ElfSection> sections,
 299                                               Map<Symbol, List<Relocation>> relocationTable) {
 300 
 301         ElfRelocTable elfRelocTable = new ElfRelocTable(sections.size());
 302         /*
 303          * For each of the symbols with associated relocation records, create a Elf relocation
 304          * entry.
 305          */
 306         for (Map.Entry<Symbol, List<Relocation>> entry : relocationTable.entrySet()) {
 307             List<Relocation> relocs = entry.getValue();
 308             Symbol symbol = entry.getKey();
 309 
 310             for (Relocation reloc : relocs) {
 311                 createRelocation(symbol, reloc, elfRelocTable);
 312             }
 313         }
 314 
 315         for (Map.Entry<Symbol, Relocation> entry : binContainer.getUniqueRelocationTable().entrySet()) {
 316             createRelocation(entry.getKey(), entry.getValue(), elfRelocTable);
 317         }
 318 
 319         return (elfRelocTable);
 320     }
 321 
 322     private void createRelocation(Symbol symbol, Relocation reloc, ElfRelocTable elfRelocTable) {
 323         RelocType relocType = reloc.getType();
 324 
 325         int elfRelocType = getELFRelocationType(relocType);
 326         ElfSymbol sym = (ElfSymbol)symbol.getNativeSymbol();
 327         int symno = sym.getIndex();
 328         int sectindex = reloc.getSection().getSectionId();
 329         int offset = reloc.getOffset();
 330         int addend = 0;
 331 
 332         switch (relocType) {
 333             case FOREIGN_CALL_DIRECT:
 334             case JAVA_CALL_DIRECT:
 335             case STUB_CALL_DIRECT:
 336             case FOREIGN_CALL_INDIRECT_GOT: {
 337                 // Create relocation entry
 338                 // System.out.println("getELFRelocationType: PLT relocation type using X86_64_RELOC_BRANCH");
 339                 addend = -4; // Size in bytes of the patch location
 340                 // Relocation should be applied at the location after call operand
 341                 offset = offset + reloc.getSize() + addend;
 342                 break;
 343             }
 344             case FOREIGN_CALL_DIRECT_FAR: {
 345                 // Create relocation entry
 346                 addend = -8; // Size in bytes of the patch location
 347                 // Relocation should be applied at the location after call operand
 348                 // 10 = 2 (jmp [r]) + 8 (imm64)
 349                 offset = offset + reloc.getSize() + addend - 2;
 350                 break;
 351             }
 352             case FOREIGN_CALL_INDIRECT:
 353             case JAVA_CALL_INDIRECT:
 354             case STUB_CALL_INDIRECT: {
 355                 // Do nothing.
 356                 return;
 357             }
 358             case EXTERNAL_DATA_REFERENCE_FAR: {
 359                 // Create relocation entry
 360                 addend = -4; // Size of 32-bit address of the GOT
 361                 /*
 362                  * Relocation should be applied before the test instruction to the move instruction.
 363                  * offset points to the test instruction after the instruction that loads
 364                  * the address of polling page. So set the offset appropriately.
 365                  */
 366                 offset = offset + addend;
 367                 break;
 368             }
 369             case METASPACE_GOT_REFERENCE:
 370             case EXTERNAL_PLT_TO_GOT:
 371             case STATIC_STUB_TO_STATIC_METHOD:
 372             case STATIC_STUB_TO_HOTSPOT_LINKAGE_GOT: {
 373                 addend = -4; // Size of 32-bit address of the GOT
 374                 /*
 375                  * Relocation should be applied before the test instruction to
 376                  * the move instruction. reloc.getOffset() points to the
 377                  * test instruction after the instruction that loads the
 378                  * address of polling page. So set the offset appropriately.
 379                  */
 380                 offset = offset + addend;
 381                 break;
 382             }
 383             case EXTERNAL_GOT_TO_PLT:
 384             case LOADTIME_ADDRESS: {
 385                 // this is load time relocations
 386                 break;
 387             }
 388             default:
 389                 throw new InternalError("Unhandled relocation type: " + relocType);
 390         }
 391         elfRelocTable.createRelocationEntry(sectindex, offset, symno, elfRelocType, addend);
 392     }
 393 
 394     private static int getELFRelocationType(RelocType relocType) {
 395         int elfRelocType = 0; // R_<ARCH>_NONE if #define'd to 0 for all values of ARCH
 396         switch (ElfTargetInfo.getElfArch()) {
 397             case Elf64_Ehdr.EM_X86_64:
 398                 // Return R_X86_64_* entries based on relocType
 399                 if (relocType == RelocType.FOREIGN_CALL_DIRECT ||
 400                     relocType == RelocType.JAVA_CALL_DIRECT ||
 401                     relocType == RelocType.FOREIGN_CALL_INDIRECT_GOT) {
 402                     elfRelocType = Elf64_Rela.R_X86_64_PLT32;
 403                 } else if (relocType == RelocType.STUB_CALL_DIRECT) {
 404                     elfRelocType = Elf64_Rela.R_X86_64_PC32;
 405                 } else if (relocType == RelocType.FOREIGN_CALL_DIRECT_FAR) {
 406                     elfRelocType = Elf64_Rela.R_X86_64_64;
 407                 } else if (relocType == RelocType.FOREIGN_CALL_INDIRECT ||
 408                            relocType == RelocType.JAVA_CALL_INDIRECT ||
 409                            relocType == RelocType.STUB_CALL_INDIRECT) {
 410                     elfRelocType = Elf64_Rela.R_X86_64_NONE;
 411                 } else if ((relocType == RelocType.EXTERNAL_DATA_REFERENCE_FAR)) {
 412                     elfRelocType = Elf64_Rela.R_X86_64_GOTPCREL;
 413                 } else if (relocType == RelocType.METASPACE_GOT_REFERENCE ||
 414                            relocType == RelocType.EXTERNAL_PLT_TO_GOT ||
 415                            relocType == RelocType.STATIC_STUB_TO_STATIC_METHOD ||
 416                            relocType == RelocType.STATIC_STUB_TO_HOTSPOT_LINKAGE_GOT) {
 417                     elfRelocType = Elf64_Rela.R_X86_64_PC32;
 418                 } else if (relocType == RelocType.EXTERNAL_GOT_TO_PLT ||
 419                            relocType == RelocType.LOADTIME_ADDRESS) {
 420                     elfRelocType = Elf64_Rela.R_X86_64_64;
 421                 } else {
 422                     assert false : "Unhandled relocation type: " + relocType;
 423                 }
 424                 break;
 425             default:
 426                 System.out.println("Relocation Type mapping: Unhandled architecture");
 427         }
 428         return elfRelocType;
 429     }
 430 
 431     private void createElfRelocSections(ArrayList<ElfSection> sections,
 432                                         ElfRelocTable elfRelocTable,
 433                                         int symtabsectidx) {
 434 
 435         // Grab count before we create new sections
 436         int count = sections.size();
 437 
 438         for (int i = 0; i < count; i++) {
 439             if (elfRelocTable.getNumRelocs(i) > 0) {
 440                 ElfSection sect = sections.get(i);
 441                 String relname = ".rela" + sect.getName();
 442                 ElfSection relocSection = createByteSection(sections,
 443                                                                     relname,
 444                                                                     elfRelocTable.getRelocData(i),
 445                                                                     false,
 446                                                                     8,
 447                                                                     0,
 448                                                                     Elf64_Shdr.SHT_RELA);
 449                         relocSection.setLink(symtabsectidx);
 450                         relocSection.setInfo(sect.getSectionId());
 451             }
 452         }
 453     }
 454 }


   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.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.elf.ElfSymbol;
  43 import jdk.tools.jaotc.binformat.elf.ElfTargetInfo;
  44 import jdk.tools.jaotc.binformat.elf.Elf.Elf64_Ehdr;
  45 import jdk.tools.jaotc.binformat.elf.Elf.Elf64_Shdr;
  46 import jdk.tools.jaotc.binformat.elf.Elf.Elf64_Sym;

  47 import jdk.tools.jaotc.binformat.elf.Elf.Elf64_Rela;
  48 
  49 public class JELFRelocObject {
  50 
  51     private final BinaryContainer binContainer;
  52 
  53     private final ElfContainer elfContainer;
  54 
  55     private final int segmentSize;
  56 
  57     public JELFRelocObject(BinaryContainer binContainer, String outputFileName) {
  58         this.binContainer = binContainer;
  59         this.elfContainer = new ElfContainer(outputFileName);
  60         this.segmentSize = binContainer.getCodeSegmentSize();
  61     }
  62 
  63     private static ElfSection createByteSection(ArrayList<ElfSection> sections,
  64                                                 String sectName,
  65                                                 byte[] scnData,
  66                                                 boolean hasRelocs,
  67                                                 int align,
  68                                                 int scnFlags,
  69                                                 int scnType) {
  70 
  71         ElfSection sect = new ElfSection(sectName, scnData, scnFlags, scnType,
  72                                          hasRelocs, align, sections.size());





  73         // Add this section to our list
  74         sections.add(sect);
  75 
  76         return (sect);
  77     }
  78 
  79     private void createByteSection(ArrayList<ElfSection> sections,
  80                                    ByteContainer c, int scnFlags) {
  81         ElfSection sect;
  82         boolean hasRelocs = c.hasRelocations();
  83         byte[] scnData = c.getByteArray();
  84 
  85         int scnType = Elf64_Shdr.SHT_PROGBITS;
  86         boolean zeros = !hasRelocs;
  87         if (zeros) {
  88             for (byte b : scnData) {
  89                 if (b != 0) {
  90                     zeros = false;
  91                     break;
  92                 }
  93             }
  94             if (zeros) {
  95                 scnType = Elf64_Shdr.SHT_NOBITS;
  96             }
  97         }
  98 
  99         sect = createByteSection(sections, c.getContainerName(),
 100                                  scnData, hasRelocs, segmentSize,
 101                                  scnFlags, scnType);
 102         c.setSectionId(sect.getSectionId());
 103     }
 104 
 105     private void createCodeSection(ArrayList<ElfSection> sections, CodeContainer c) {
 106         createByteSection(sections, c, Elf64_Shdr.SHF_ALLOC | Elf64_Shdr.SHF_EXECINSTR);
 107     }
 108 
 109     private void createReadOnlySection(ArrayList<ElfSection> sections, ReadOnlyDataContainer c) {
 110         createByteSection(sections, c, Elf64_Shdr.SHF_ALLOC);
 111     }
 112 
 113     private void createReadWriteSection(ArrayList<ElfSection> sections, ByteContainer c) {
 114         createByteSection(sections, c, Elf64_Shdr.SHF_ALLOC | Elf64_Shdr.SHF_WRITE);
 115     }
 116 
 117     /**
 118      * Create an ELF relocatable object
 119      *
 120      * @param relocationTable
 121      * @param symbols
 122      * @throws IOException throws {@code IOException} as a result of file system access failures.
 123      */
 124     public void createELFRelocObject(Map<Symbol, List<Relocation>> relocationTable, Collection<Symbol> symbols) throws IOException {
 125         // Allocate ELF Header
 126         ElfHeader eh = new ElfHeader();
 127 
 128         ArrayList<ElfSection> sections = new ArrayList<>();
 129 
 130         // Create the null section
 131         createByteSection(sections, null, null, false, 1, 0, 0);
 132 
 133         // Create text section
 134         createCodeSection(sections, binContainer.getCodeContainer());
 135         createReadOnlySection(sections, binContainer.getMetaspaceNamesContainer());
 136         createReadOnlySection(sections, binContainer.getKlassesOffsetsContainer());
 137         createReadOnlySection(sections, binContainer.getMethodsOffsetsContainer());
 138         createReadOnlySection(sections, binContainer.getKlassesDependenciesContainer());
 139         createReadOnlySection(sections, binContainer.getMethodMetadataContainer());




 140         createReadOnlySection(sections, binContainer.getStubsOffsetsContainer());
 141         createReadOnlySection(sections, binContainer.getHeaderContainer().getContainer());
 142         createReadOnlySection(sections, binContainer.getCodeSegmentsContainer());
 143         createReadOnlySection(sections, binContainer.getConstantDataContainer());
 144         createReadOnlySection(sections, binContainer.getConfigContainer());
 145         createReadWriteSection(sections, binContainer.getKlassesGotContainer());
 146         createReadWriteSection(sections, binContainer.getCountersGotContainer());
 147         createReadWriteSection(sections, binContainer.getMetadataGotContainer());
 148         createReadWriteSection(sections, binContainer.getOopGotContainer());
 149         createReadWriteSection(sections, binContainer.getMethodStateContainer());
 150         createReadWriteSection(sections, binContainer.getExtLinkageGOTContainer());
 151 
 152         // Get ELF symbol data from BinaryContainer object's symbol tables
 153         ElfSymtab symtab = createELFSymbolTables(symbols);
 154 
 155         // Create string table section and symbol table sections in
 156         // that order since symtab section needs to set the index of
 157         // strtab in sh_link field
 158         ElfSection strTabSection = createByteSection(sections, ".strtab",

 159                                                      symtab.getStrtabArray(),
 160                                                      false, 1, 0,


 161                                                      Elf64_Shdr.SHT_STRTAB);
 162 
 163         // Now create .symtab section with the symtab data constructed.
 164         // On Linux, sh_link of symtab contains the index of string table
 165         // its symbols reference and sh_info contains the index of first
 166         // non-local symbol
 167         ElfSection symTabSection = createByteSection(sections, ".symtab",

 168                                                      symtab.getSymtabArray(),
 169                                                      false, 8, 0,


 170                                                      Elf64_Shdr.SHT_SYMTAB);
 171         symTabSection.setLink(strTabSection.getSectionId());
 172         symTabSection.setInfo(symtab.getNumLocalSyms());
 173 
 174         ElfRelocTable elfRelocTable = createElfRelocTable(sections, relocationTable);

 175 
 176         createElfRelocSections(sections, elfRelocTable, symTabSection.getSectionId());
 177 
 178         // Now, finally, after creating all sections, create shstrtab section
 179         ElfSection shStrTabSection = createByteSection(sections, ".shstrtab",
 180                                                        null, false, 1, 0,




 181                                                        Elf64_Shdr.SHT_STRTAB);
 182         eh.setSectionStrNdx(shStrTabSection.getSectionId());
 183 
 184         // Update all section offsets and the Elf header section offset
 185         // Write the Header followed by the contents of each section
 186         // and then the section structures (section table).
 187         int file_offset = Elf64_Ehdr.totalsize;
 188 
 189         // and round it up
 190         file_offset = (file_offset + (sections.get(1).getDataAlign() - 1)) &
 191                       ~((sections.get(1).getDataAlign() - 1));
 192 
 193         // Calc file offsets for section data skipping null section
 194         for (int i = 1; i < sections.size(); i++) {
 195             ElfSection sect = sections.get(i);
 196             file_offset = (file_offset + (sect.getDataAlign() - 1)) &
 197                           ~((sect.getDataAlign() - 1));
 198             sect.setOffset(file_offset);
 199             file_offset += sect.getSize();
 200         }
 201 
 202         // Align the section table
 203         file_offset = (file_offset + (ElfSection.getShdrAlign() - 1)) &
 204                       ~((ElfSection.getShdrAlign() - 1));
 205 
 206         // Update the Elf Header with the offset of the first Elf64_Shdr
 207         // and the number of sections.
 208         eh.setSectionOff(file_offset);
 209         eh.setSectionNum(sections.size());
 210 
 211         // Write out the Header
 212         elfContainer.writeBytes(eh.getArray());
 213 
 214         // Write out each section contents skipping null section
 215         for (int i = 1; i < sections.size(); i++) {
 216             ElfSection sect = sections.get(i);
 217             elfContainer.writeBytes(sect.getDataArray(), sect.getDataAlign());
 218         }
 219 
 220         // Write out the section table
 221         for (int i = 0; i < sections.size(); i++) {
 222             ElfSection sect = sections.get(i);
 223             elfContainer.writeBytes(sect.getArray(), ElfSection.getShdrAlign());
 224         }
 225 
 226         elfContainer.close();
 227     }
 228 
 229     /**
 230      * Construct ELF symbol data from BinaryContainer object's symbol tables. Both dynamic ELF symbol
 231      * table and ELF symbol table are created from BinaryContainer's symbol info.
 232      *
 233      * @param symbols
 234      */
 235     private static ElfSymtab createELFSymbolTables(Collection<Symbol> symbols) {
 236         ElfSymtab symtab = new ElfSymtab();
 237 
 238         // First, create the initial null symbol. This is a local symbol.
 239         symtab.addSymbolEntry("", (byte) 0, (byte) 0, Elf64_Shdr.SHN_UNDEF, 0, 0);
 240 
 241         // Now create ELF symbol entries for all symbols.
 242         for (Symbol symbol : symbols) {
 243             // Get the index of section this symbol is defined in.
 244             int secHdrIndex = symbol.getSection().getSectionId();
 245             ElfSymbol elfSymbol = symtab.addSymbolEntry(symbol.getName(), getELFTypeOf(symbol), getELFBindOf(symbol), (byte) secHdrIndex, symbol.getOffset(), symbol.getSize());
 246             symbol.setNativeSymbol(elfSymbol);
 247         }
 248         return (symtab);
 249     }
 250 
 251     private static byte getELFTypeOf(Symbol sym) {
 252         Kind kind = sym.getKind();
 253         if (kind == Symbol.Kind.NATIVE_FUNCTION || kind == Symbol.Kind.JAVA_FUNCTION) {
 254             return Elf64_Sym.STT_FUNC;
 255         } else if (kind == Symbol.Kind.OBJECT) {
 256             return Elf64_Sym.STT_OBJECT;
 257         }
 258         return Elf64_Sym.STT_NOTYPE;
 259     }
 260 
 261     private static byte getELFBindOf(Symbol sym) {
 262         Binding binding = sym.getBinding();
 263         if (binding == Symbol.Binding.GLOBAL) {
 264             return Elf64_Sym.STB_GLOBAL;
 265         }
 266         return Elf64_Sym.STB_LOCAL;
 267     }
 268 
 269     /**
 270      * Construct a Elf relocation table from BinaryContainer object's relocation tables.
 271      *
 272      * @param sections
 273      * @param relocationTable
 274      */
 275     private ElfRelocTable createElfRelocTable(ArrayList<ElfSection> sections,
 276                                               Map<Symbol, List<Relocation>> relocationTable) {
 277 
 278         ElfRelocTable elfRelocTable = new ElfRelocTable(sections.size());
 279         /*
 280          * For each of the symbols with associated relocation records, create a Elf relocation entry.

 281          */
 282         for (Map.Entry<Symbol, List<Relocation>> entry : relocationTable.entrySet()) {
 283             List<Relocation> relocs = entry.getValue();
 284             Symbol symbol = entry.getKey();
 285 
 286             for (Relocation reloc : relocs) {
 287                 createRelocation(symbol, reloc, elfRelocTable);
 288             }
 289         }
 290 
 291         for (Map.Entry<Symbol, Relocation> entry : binContainer.getUniqueRelocationTable().entrySet()) {
 292             createRelocation(entry.getKey(), entry.getValue(), elfRelocTable);
 293         }
 294 
 295         return (elfRelocTable);
 296     }
 297 
 298     private static void createRelocation(Symbol symbol, Relocation reloc, ElfRelocTable elfRelocTable) {
 299         RelocType relocType = reloc.getType();
 300 
 301         int elfRelocType = getELFRelocationType(relocType);
 302         ElfSymbol sym = (ElfSymbol) symbol.getNativeSymbol();
 303         int symno = sym.getIndex();
 304         int sectindex = reloc.getSection().getSectionId();
 305         int offset = reloc.getOffset();
 306         int addend = 0;
 307 
 308         switch (relocType) {

 309             case JAVA_CALL_DIRECT:
 310             case STUB_CALL_DIRECT:
 311             case FOREIGN_CALL_INDIRECT_GOT: {
 312                 // Create relocation entry

 313                 addend = -4; // Size in bytes of the patch location
 314                 // Relocation should be applied at the location after call operand
 315                 offset = offset + reloc.getSize() + addend;
 316                 break;
 317             }









 318             case JAVA_CALL_INDIRECT:















 319             case METASPACE_GOT_REFERENCE:
 320             case EXTERNAL_PLT_TO_GOT: {


 321                 addend = -4; // Size of 32-bit address of the GOT
 322                 /*
 323                  * Relocation should be applied before the test instruction to the move instruction.
 324                  * reloc.getOffset() points to the test instruction after the instruction that loads the address of
 325                  * polling page. So set the offset appropriately.

 326                  */
 327                 offset = offset + addend;
 328                 break;
 329             }
 330             case EXTERNAL_GOT_TO_PLT: {

 331                 // this is load time relocations
 332                 break;
 333             }
 334             default:
 335                 throw new InternalError("Unhandled relocation type: " + relocType);
 336         }
 337         elfRelocTable.createRelocationEntry(sectindex, offset, symno, elfRelocType, addend);
 338     }
 339 
 340     private static int getELFRelocationType(RelocType relocType) {
 341         int elfRelocType = 0; // R_<ARCH>_NONE if #define'd to 0 for all values of ARCH
 342         switch (ElfTargetInfo.getElfArch()) {
 343             case Elf64_Ehdr.EM_X86_64:
 344                 // Return R_X86_64_* entries based on relocType
 345                 if (relocType == RelocType.JAVA_CALL_DIRECT ||

 346                     relocType == RelocType.FOREIGN_CALL_INDIRECT_GOT) {
 347                     elfRelocType = Elf64_Rela.R_X86_64_PLT32;
 348                 } else if (relocType == RelocType.STUB_CALL_DIRECT) {
 349                     elfRelocType = Elf64_Rela.R_X86_64_PC32;
 350                 } else if (relocType == RelocType.JAVA_CALL_INDIRECT) {




 351                     elfRelocType = Elf64_Rela.R_X86_64_NONE;


 352                 } else if (relocType == RelocType.METASPACE_GOT_REFERENCE ||
 353                            relocType == RelocType.EXTERNAL_PLT_TO_GOT) {


 354                     elfRelocType = Elf64_Rela.R_X86_64_PC32;
 355                 } else if (relocType == RelocType.EXTERNAL_GOT_TO_PLT) {

 356                     elfRelocType = Elf64_Rela.R_X86_64_64;
 357                 } else {
 358                     assert false : "Unhandled relocation type: " + relocType;
 359                 }
 360                 break;
 361             default:
 362                 System.out.println("Relocation Type mapping: Unhandled architecture");
 363         }
 364         return elfRelocType;
 365     }
 366 
 367     private static void createElfRelocSections(ArrayList<ElfSection> sections,
 368                                                ElfRelocTable elfRelocTable,
 369                                                int symtabsectidx) {
 370 
 371         // Grab count before we create new sections
 372         int count = sections.size();
 373 
 374         for (int i = 0; i < count; i++) {
 375             if (elfRelocTable.getNumRelocs(i) > 0) {
 376                 ElfSection sect = sections.get(i);
 377                 String relname = ".rela" + sect.getName();
 378                 ElfSection relocSection = createByteSection(sections, relname,

 379                                                             elfRelocTable.getRelocData(i),
 380                                                             false, 8, 0, Elf64_Shdr.SHT_RELA);



 381                 relocSection.setLink(symtabsectidx);
 382                 relocSection.setInfo(sect.getSectionId());
 383             }
 384         }
 385     }
 386 }
src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/elf/JELFRelocObject.java
Index Unified diffs Context diffs Sdiffs Frames Patch New Old Previous File Next File