package com.oracle.objectfile.elf;
import com.oracle.objectfile.ObjectFile.RelocationKind;
import com.oracle.objectfile.ObjectFile.RelocationMethod;
import com.oracle.objectfile.elf.ELFRelocationSection.ELFRelocationMethod;
public enum ELFMachine {
NONE {
@Override
Class<? extends Enum<? extends RelocationMethod>> relocationTypes() {
return ELFDummyRelocation.class;
}
},
X86_64 {
@Override
Class<? extends Enum<? extends RelocationMethod>> relocationTypes() {
return ELFX86_64Relocation.class;
}
},
AArch64 {
@Override
Class<? extends Enum<? extends RelocationMethod>> relocationTypes() {
return ELFAArch64Relocation.class;
}
};
abstract Class<? extends Enum<? extends RelocationMethod>> relocationTypes();
public static ELFMachine from(String s) {
switch (s.toLowerCase()) {
case "amd64":
case "x86_64":
return X86_64;
case "arm64":
case "aarch64":
return AArch64;
}
throw new IllegalStateException("unknown CPU type: " + s);
}
public static ELFRelocationMethod getRelocation(ELFMachine m, RelocationKind k) {
switch (m) {
case X86_64:
switch (k) {
case DIRECT_1:
return ELFX86_64Relocation.R_8;
case DIRECT_2:
return ELFX86_64Relocation.R_16;
case DIRECT_4:
return ELFX86_64Relocation.R_32;
case DIRECT_8:
return ELFX86_64Relocation.R_64;
case PC_RELATIVE_1:
return ELFX86_64Relocation.R_PC8;
case PC_RELATIVE_2:
return ELFX86_64Relocation.R_PC16;
case PC_RELATIVE_4:
return ELFX86_64Relocation.R_PC32;
case PC_RELATIVE_8:
return ELFX86_64Relocation.R_PC64;
default:
case UNKNOWN:
throw new IllegalArgumentException("cannot map unknown relocation kind to an ELF x86-64 relocation type");
}
case AArch64:
switch (k) {
case DIRECT_2:
return ELFAArch64Relocation.R_AARCH64_ABS16;
case DIRECT_4:
return ELFAArch64Relocation.R_AARCH64_ABS32;
case DIRECT_8:
return ELFAArch64Relocation.R_AARCH64_ABS64;
case AARCH64_R_MOVW_UABS_G0:
return ELFAArch64Relocation.R_AARCH64_MOVW_UABS_G0;
case AARCH64_R_MOVW_UABS_G0_NC:
return ELFAArch64Relocation.R_AARCH64_MOVW_UABS_G0_NC;
case AARCH64_R_MOVW_UABS_G1:
return ELFAArch64Relocation.R_AARCH64_MOVW_UABS_G1;
case AARCH64_R_MOVW_UABS_G1_NC:
return ELFAArch64Relocation.R_AARCH64_MOVW_UABS_G1_NC;
case AARCH64_R_MOVW_UABS_G2:
return ELFAArch64Relocation.R_AARCH64_MOVW_UABS_G2;
case AARCH64_R_MOVW_UABS_G2_NC:
return ELFAArch64Relocation.R_AARCH64_MOVW_UABS_G2_NC;
case AARCH64_R_MOVW_UABS_G3:
return ELFAArch64Relocation.R_AARCH64_MOVW_UABS_G3;
case AARCH64_R_AARCH64_ADR_PREL_PG_HI21:
return ELFAArch64Relocation.R_AARCH64_ADR_PREL_PG_HI21;
case AARCH64_R_AARCH64_LDST128_ABS_LO12_NC:
return ELFAArch64Relocation.R_AARCH64_LDST128_ABS_LO12_NC;
case AARCH64_R_AARCH64_ADD_ABS_LO12_NC:
return ELFAArch64Relocation.R_AARCH64_ADD_ABS_LO12_NC;
case AARCH64_R_GOT_LD_PREL19:
return ELFAArch64Relocation.R_AARCH64_GOT_LD_PREL19;
case AARCH64_R_LD_PREL_LO19:
return ELFAArch64Relocation.R_AARCH64_LD_PREL_LO19;
case AARCH64_R_AARCH64_LDST64_ABS_LO12_NC:
return ELFAArch64Relocation.R_AARCH64_LDST64_ABS_LO12_NC;
case AARCH64_R_AARCH64_LDST32_ABS_LO12_NC:
return ELFAArch64Relocation.R_AARCH64_LDST32_ABS_LO12_NC;
case AARCH64_R_AARCH64_LDST16_ABS_LO12_NC:
return ELFAArch64Relocation.R_AARCH64_LDST16_ABS_LO12_NC;
case AARCH64_R_AARCH64_LDST8_ABS_LO12_NC:
return ELFAArch64Relocation.R_AARCH64_LDST8_ABS_LO12_NC;
default:
case UNKNOWN:
throw new IllegalArgumentException("cannot map unknown relocation kind to an ELF aarch64 relocation type: " + k);
}
default:
case NONE:
return ELFDummyRelocation.R_NONE;
}
}
public static ELFMachine from(int m) {
switch (m) {
case 0:
return NONE;
case 0x3E:
return X86_64;
case 0xB7:
return AArch64;
default:
throw new IllegalStateException("unknown ELF machine type");
}
}
public short toShort() {
if (this == NONE) {
return 0;
} else if (this == AArch64) {
return 0xB7;
} else if (this == X86_64) {
return 0x3E;
} else {
throw new IllegalStateException("should not reach here");
}
}
public static ELFMachine getSystemNativeValue() {
if (System.getProperty("os.arch").equals("aarch64")) {
return AArch64;
} else {
return X86_64;
}
}
}
enum ELFDummyRelocation implements ELFRelocationMethod {
R_NONE;
@Override
public boolean canUseExplicitAddend() {
return true;
}
@Override
public boolean canUseImplicitAddend() {
return true;
}
@Override
public long toLong() {
return ordinal();
}
}
enum ELFX86_64Relocation implements ELFRelocationMethod {
R_NONE,
R_64,
R_PC32,
R_GOT32,
R_PLT32,
R_COPY,
R_GLOB_DAT,
R_JUMP_SLOT,
R_RELATIVE,
R_GOTPCREL,
R_32,
R_32S,
R_16,
R_PC16,
R_8,
R_PC8,
R_DTPMOD64,
R_DTPOFF64,
R_TPOFF64,
R_TLSGD,
R_TLSLD,
R_DTPOFF32,
R_GOTTPOFF,
R_TPOFF32,
R_PC64,
R_GOTOFF64,
R_GOTPC32,
R_GOT64,
R_GOTPCREL64,
R_GOTPC64,
R_GOTPLT64,
R_PLTOFF64,
R_SIZE32,
R_SIZE64,
R_GOTPC32_TLSDESC,
R_TLSDESC_CALL,
R_TLSDESC,
R_IRELATIVE,
R_RELATIVE64,
R_COUNT;
static {
assert R_COUNT.ordinal() == 39;
}
@Override
public boolean canUseExplicitAddend() {
return true;
}
@Override
public boolean canUseImplicitAddend() {
return false;
}
@Override
public long toLong() {
return ordinal();
}
}
enum ELFAArch64Relocation implements ELFRelocationMethod {
R_AARCH64_NONE(0),
R_AARCH64_ABS64(0x101),
R_AARCH64_ABS32(0x102),
R_AARCH64_ABS16(0x103),
R_AARCH64_PREL64(0x104),
R_AARCH64_PREL32(0x105),
R_AARCH64_PREL16(0x106),
R_AARCH64_MOVW_UABS_G0(0x107),
R_AARCH64_MOVW_UABS_G0_NC(0x108),
R_AARCH64_MOVW_UABS_G1(0x109),
R_AARCH64_MOVW_UABS_G1_NC(0x10a),
R_AARCH64_MOVW_UABS_G2(0x10b),
R_AARCH64_MOVW_UABS_G2_NC(0x10c),
R_AARCH64_MOVW_UABS_G3(0x10d),
R_AARCH64_MOVW_SABS_G0(0x10e),
R_AARCH64_MOVW_SABS_G1(0x10f),
R_AARCH64_MOVW_SABS_G2(0x110),
R_AARCH64_LD_PREL_LO19(0x111),
R_AARCH64_ADR_PREL_LO21(0x112),
R_AARCH64_ADR_PREL_PG_HI21(0x113),
R_AARCH64_ADR_PREL_PG_HI21_NC(0x114),
R_AARCH64_ADD_ABS_LO12_NC(0x115),
R_AARCH64_LDST8_ABS_LO12_NC(0x116),
R_AARCH64_TSTBR14(0x117),
R_AARCH64_CONDBR19(0x118),
R_AARCH64_JUMP26(0x11a),
R_AARCH64_CALL26(0x11b),
R_AARCH64_LDST16_ABS_LO12_NC(0x11c),
R_AARCH64_LDST32_ABS_LO12_NC(0x11d),
R_AARCH64_LDST64_ABS_LO12_NC(0x11e),
R_AARCH64_MOVW_PREL_G0(0x11f),
R_AARCH64_MOVW_PREL_G0_NC(0x120),
R_AARCH64_MOVW_PREL_G1(0x121),
R_AARCH64_MOVW_PREL_G1_NC(0x122),
R_AARCH64_MOVW_PREL_G2(0x123),
R_AARCH64_MOVW_PREL_G2_NC(0x124),
R_AARCH64_MOVW_PREL_G3(0x125),
R_AARCH64_LDST128_ABS_LO12_NC(0x12b),
R_AARCH64_MOVW_GOTOFF_G0(0x12c),
R_AARCH64_MOVW_GOTOFF_G0_NC(0x12d),
R_AARCH64_MOVW_GOTOFF_G1(0x12e),
R_AARCH64_MOVW_GOTOFF_G1_NC(0x12f),
R_AARCH64_MOVW_GOTOFF_G2(0x130),
R_AARCH64_MOVW_GOTOFF_G2_NC(0x131),
R_AARCH64_MOVW_GOTOFF_G3(0x132),
R_AARCH64_GOTREL64(0x133),
R_AARCH64_GOTREL32(0x134),
R_AARCH64_GOT_LD_PREL19(0x135),
R_AARCH64_LD64_GOTOFF_LO15(0x136),
R_AARCH64_ADR_GOT_PAGE(0x137),
R_AARCH64_LD64_GOT_LO12_NC(0x138),
R_AARCH64_LD64_GOTPAGE_LO15(0x139),
R_AARCH64_TLSGD_ADR_PREL21(0x200),
R_AARCH64_TLSGD_ADR_PAGE21(0x201),
R_AARCH64_TLSGD_ADD_LO12_NC(0x202),
R_AARCH64_TLSGD_MOVW_G1(0x203),
R_AARCH64_TLSGD_MOVW_G0_NC(0x204),
R_AARCH64_TLSLD_ADR_PREL21(0x205),
R_AARCH64_TLSLD_ADR_PAGE21(0x206),
R_AARCH64_TLSLD_ADD_LO12_NC(0x207),
R_AARCH64_TLSLD_MOVW_G1(0x208),
R_AARCH64_TLSLD_MOVW_G0_NC(0x209),
R_AARCH64_TLSLD_LD_PREL19(0x20a),
R_AARCH64_TLSLD_MOVW_DTPREL_G2(0x20b),
R_AARCH64_TLSLD_MOVW_DTPREL_G1(0x20c),
R_AARCH64_TLSLD_MOVW_DTPREL_G1_NC(0x20d),
R_AARCH64_TLSLD_MOVW_DTPREL_G0(0x20e),
R_AARCH64_TLSLD_MOVW_DTPREL_G0_NC(0x20f),
R_AARCH64_TLSLD_ADD_DTPREL_HI12(0x210),
R_AARCH64_TLSLD_ADD_DTPREL_LO12(0x211),
R_AARCH64_TLSLD_ADD_DTPREL_LO12_NC(0x212),
R_AARCH64_TLSLD_LDST8_DTPREL_LO12(0x213),
R_AARCH64_TLSLD_LDST8_DTPREL_LO12_NC(0x214),
R_AARCH64_TLSLD_LDST16_DTPREL_LO12(0x215),
R_AARCH64_TLSLD_LDST16_DTPREL_LO12_NC(0x216),
R_AARCH64_TLSLD_LDST32_DTPREL_LO12(0x217),
R_AARCH64_TLSLD_LDST32_DTPREL_LO12_NC(0x218),
R_AARCH64_TLSLD_LDST64_DTPREL_LO12(0x219),
R_AARCH64_TLSLD_LDST64_DTPREL_LO12_NC(0x21a),
R_AARCH64_TLSIE_MOVW_GOTTPREL_G1(0x21b),
R_AARCH64_TLSIE_MOVW_GOTTPREL_G0_NC(0x21c),
R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21(0x21d),
R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC(0x21e),
R_AARCH64_TLSIE_LD_GOTTPREL_PREL19(0x21f),
R_AARCH64_TLSLE_MOVW_TPREL_G2(0x220),
R_AARCH64_TLSLE_MOVW_TPREL_G1(0x221),
R_AARCH64_TLSLE_MOVW_TPREL_G1_NC(0x222),
R_AARCH64_TLSLE_MOVW_TPREL_G0(0x223),
R_AARCH64_TLSLE_MOVW_TPREL_G0_NC(0x224),
R_AARCH64_TLSLE_ADD_TPREL_HI12(0x225),
R_AARCH64_TLSLE_ADD_TPREL_LO12(0x226),
R_AARCH64_TLSLE_ADD_TPREL_LO12_NC(0x227),
R_AARCH64_TLSLE_LDST8_TPREL_LO12(0x228),
R_AARCH64_TLSLE_LDST8_TPREL_LO12_NC(0x229),
R_AARCH64_TLSLE_LDST16_TPREL_LO12(0x22a),
R_AARCH64_TLSLE_LDST16_TPREL_LO12_NC(0x22b),
R_AARCH64_TLSLE_LDST32_TPREL_LO12(0x22c),
R_AARCH64_TLSLE_LDST32_TPREL_LO12_NC(0x22d),
R_AARCH64_TLSLE_LDST64_TPREL_LO12(0x22e),
R_AARCH64_TLSLE_LDST64_TPREL_LO12_NC(0x22f),
R_AARCH64_TLSDESC_LD_PREL19(0x230),
R_AARCH64_TLSDESC_ADR_PREL21(0x231),
R_AARCH64_TLSDESC_ADR_PAGE21(0x232),
R_AARCH64_TLSDESC_LD64_LO12_NC(0x233),
R_AARCH64_TLSDESC_ADD_LO12_NC(0x234),
R_AARCH64_TLSDESC_OFF_G1(0x235),
R_AARCH64_TLSDESC_OFF_G0_NC(0x236),
R_AARCH64_TLSDESC_LDR(0x237),
R_AARCH64_TLSDESC_ADD(0x238),
R_AARCH64_TLSDESC_CALL(0x239),
R_AARCH64_TLSLE_LDST128_TPREL_LO12(0x23a),
R_AARCH64_TLSLE_LDST128_TPREL_LO12_NC(0x23b),
R_AARCH64_TLSLD_LDST128_DTPREL_LO12(0x23c),
R_AARCH64_TLSLD_LDST128_DTPREL_LO12_NC(0x23d),
R_AARCH64_COPY(0x400),
R_AARCH64_GLOB_DAT(0x401),
R_AARCH64_JUMP_SLOT(0x402),
R_AARCH64_RELATIVE(0x403),
R_AARCH64_TLS_DTPREL64(0x404),
R_AARCH64_TLS_DTPMOD64(0x405),
R_AARCH64_TLS_TPREL64(0x406),
R_AARCH64_TLSDESC(0x407),
R_AARCH64_IRELATIVE(0x408);
private final long code;
ELFAArch64Relocation(long code) {
this.code = code;
}
@Override
public boolean canUseImplicitAddend() {
return false;
}
@Override
public boolean canUseExplicitAddend() {
return true;
}
@Override
public long toLong() {
return code;
}
}