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(); 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 } | 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 abstract class JELFRelocObject { 50 51 private final BinaryContainer binContainer; 52 53 private final ElfContainer elfContainer; 54 55 private final int segmentSize; 56 57 protected JELFRelocObject(BinaryContainer binContainer, String outputFileName) { 58 this.binContainer = binContainer; 59 this.elfContainer = new ElfContainer(outputFileName); 60 this.segmentSize = binContainer.getCodeSegmentSize(); 61 } 62 63 public static JELFRelocObject newInstance(BinaryContainer binContainer, String outputFileName) { 64 String archStr = System.getProperty("os.arch").toLowerCase(); 65 if (archStr.equals("amd64") || archStr.equals("x86_64")) { 66 return new AMD64JELFRelocObject(binContainer, outputFileName); 67 } else if (archStr.equals("aarch64")) { 68 return new AArch64JELFRelocObject(binContainer, outputFileName); 69 } 70 throw new InternalError("Unsupported platform: " + archStr); 71 } 72 73 private static ElfSection createByteSection(ArrayList<ElfSection> sections, 74 String sectName, 75 byte[] scnData, 76 boolean hasRelocs, 77 int align, 78 int scnFlags, 79 int scnType) { 80 81 ElfSection sect = new ElfSection(sectName, scnData, scnFlags, scnType, 82 hasRelocs, align, 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(); 288 ElfRelocTable elfRelocTable = new ElfRelocTable(sections.size()); 289 /* 290 * For each of the symbols with associated relocation records, create a Elf relocation entry. 291 */ 292 for (Map.Entry<Symbol, List<Relocation>> entry : relocationTable.entrySet()) { 293 List<Relocation> relocs = entry.getValue(); 294 Symbol symbol = entry.getKey(); 295 296 for (Relocation reloc : relocs) { 297 createRelocation(symbol, reloc, elfRelocTable); 298 } 299 } 300 301 for (Map.Entry<Symbol, Relocation> entry : binContainer.getUniqueRelocationTable().entrySet()) { 302 createRelocation(entry.getKey(), entry.getValue(), elfRelocTable); 303 } 304 305 return (elfRelocTable); 306 } 307 308 private static void createElfRelocSections(ArrayList<ElfSection> sections, 309 ElfRelocTable elfRelocTable, 310 int symtabsectidx) { 311 312 // Grab count before we create new sections 313 int count = sections.size(); 314 315 for (int i = 0; i < count; i++) { 316 if (elfRelocTable.getNumRelocs(i) > 0) { 317 ElfSection sect = sections.get(i); 318 String relname = ".rela" + sect.getName(); 319 ElfSection relocSection = createByteSection(sections, relname, 320 elfRelocTable.getRelocData(i), 321 false, 8, 0, Elf64_Shdr.SHT_RELA); 322 relocSection.setLink(symtabsectidx); 323 relocSection.setInfo(sect.getSectionId()); 324 } 325 } 326 } 327 328 abstract void createRelocation(Symbol symbol, Relocation reloc, ElfRelocTable elfRelocTable); 329 330 } |