/*
 * Copyright (c) 2018, 2018, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

package com.oracle.objectfile.pecoff;

import com.oracle.objectfile.ObjectFile.RelocationKind;
import com.oracle.objectfile.ObjectFile.RelocationMethod;
import com.oracle.objectfile.pecoff.PECoffRelocationTable.PECoffRelocationMethod;
import com.oracle.objectfile.pecoff.PECoff.IMAGE_FILE_HEADER;
import com.oracle.objectfile.pecoff.PECoff.IMAGE_RELOCATION;

PECoff machine type (incomplete). Each machine type also defines its set of relocation types.
/** * PECoff machine type (incomplete). Each machine type also defines its set of relocation types. */
public enum PECoffMachine/* implements Integral */ { NONE { @Override Class<? extends Enum<? extends RelocationMethod>> relocationTypes() { return PECoffDummyRelocation.class; } }, X86_64 { @Override Class<? extends Enum<? extends RelocationMethod>> relocationTypes() { return PECoffX86_64Relocation.class; } }; abstract Class<? extends Enum<? extends RelocationMethod>> relocationTypes(); public static PECoffRelocationMethod getRelocation(PECoffMachine m, RelocationKind k) { switch (m) { case X86_64: switch (k) { case DIRECT_8: return PECoffX86_64Relocation.ADDR64; case DIRECT_4: return PECoffX86_64Relocation.ADDR32; case PC_RELATIVE_4: return PECoffX86_64Relocation.REL32; case SECTION_2: return PECoffX86_64Relocation.SECTION; case SECREL_4: return PECoffX86_64Relocation.SECREL; case UNKNOWN: default: throw new IllegalArgumentException("cannot map unknown relocation kind to an PECoff x86-64 relocation type"); } default: case NONE: return PECoffDummyRelocation.R_NONE; } } public static PECoffMachine from(int m) { switch (m) { case IMAGE_FILE_HEADER.IMAGE_FILE_MACHINE_UNKNOWN: return NONE; case IMAGE_FILE_HEADER.IMAGE_FILE_MACHINE_AMD64: return X86_64; default: throw new IllegalStateException("unknown PECoff machine type"); } } public short toShort() { if (this == NONE) { return (short) IMAGE_FILE_HEADER.IMAGE_FILE_MACHINE_UNKNOWN; } else if (this == X86_64) { return (short) IMAGE_FILE_HEADER.IMAGE_FILE_MACHINE_AMD64; } else { throw new IllegalStateException("should not reach here"); } } public static PECoffMachine getSystemNativeValue() { String archStr = System.getProperty("os.arch").toLowerCase(); if (archStr.equals("amd64") || archStr.equals("x86_64")) { return X86_64; } throw new IllegalStateException("unknown PECoff machine type"); } } enum PECoffDummyRelocation implements PECoffRelocationMethod { R_NONE; @Override public boolean canUseExplicitAddend() { return true; } @Override public boolean canUseImplicitAddend() { return true; } @Override public long toLong() { return ordinal(); } }
@formatter:off IMAGE_REL_AMD64_ABSOLUTE 0x0000 // Reference is absolute, no relocation is necessary IMAGE_REL_AMD64_ADDR64 0x0001 // 64-bit address (VA). IMAGE_REL_AMD64_ADDR32 0x0002 // 32-bit address (VA). IMAGE_REL_AMD64_ADDR32NB 0x0003 // 32-bit address w/o image base (RVA). IMAGE_REL_AMD64_REL32 0x0004 // 32-bit relative address from byte following reloc IMAGE_REL_AMD64_REL32_1 0x0005 // 32-bit relative address from byte distance 1 from reloc IMAGE_REL_AMD64_REL32_2 0x0006 // 32-bit relative address from byte distance 2 from reloc IMAGE_REL_AMD64_REL32_3 0x0007 // 32-bit relative address from byte distance 3 from reloc IMAGE_REL_AMD64_REL32_4 0x0008 // 32-bit relative address from byte distance 4 from reloc IMAGE_REL_AMD64_REL32_5 0x0009 // 32-bit relative address from byte distance 5 from reloc IMAGE_REL_AMD64_SECTION 0x000A // Section index IMAGE_REL_AMD64_SECREL 0x000B // 32 bit offset from base of section containing target IMAGE_REL_AMD64_SECREL7 0x000C // 7 bit unsigned offset from base of section containing target IMAGE_REL_AMD64_TOKEN 0x000D // 32 bit metadata token IMAGE_REL_AMD64_SREL32 0x000E // 32 bit signed span-dependent value emitted into object IMAGE_REL_AMD64_PAIR 0x000F IMAGE_REL_AMD64_SSPAN32 0x0010 // 32 bit signed span-dependent value applied at link time
@formatter:on
/** * @formatter:off * * IMAGE_REL_AMD64_ABSOLUTE 0x0000 // Reference is absolute, no relocation is necessary * IMAGE_REL_AMD64_ADDR64 0x0001 // 64-bit address (VA). * IMAGE_REL_AMD64_ADDR32 0x0002 // 32-bit address (VA). * IMAGE_REL_AMD64_ADDR32NB 0x0003 // 32-bit address w/o image base (RVA). * IMAGE_REL_AMD64_REL32 0x0004 // 32-bit relative address from byte following reloc * IMAGE_REL_AMD64_REL32_1 0x0005 // 32-bit relative address from byte distance 1 from reloc * IMAGE_REL_AMD64_REL32_2 0x0006 // 32-bit relative address from byte distance 2 from reloc * IMAGE_REL_AMD64_REL32_3 0x0007 // 32-bit relative address from byte distance 3 from reloc * IMAGE_REL_AMD64_REL32_4 0x0008 // 32-bit relative address from byte distance 4 from reloc * IMAGE_REL_AMD64_REL32_5 0x0009 // 32-bit relative address from byte distance 5 from reloc * IMAGE_REL_AMD64_SECTION 0x000A // Section index * IMAGE_REL_AMD64_SECREL 0x000B // 32 bit offset from base of section containing target * IMAGE_REL_AMD64_SECREL7 0x000C // 7 bit unsigned offset from base of section containing target * IMAGE_REL_AMD64_TOKEN 0x000D // 32 bit metadata token * IMAGE_REL_AMD64_SREL32 0x000E // 32 bit signed span-dependent value emitted into object * IMAGE_REL_AMD64_PAIR 0x000F IMAGE_REL_AMD64_SSPAN32 0x0010 // 32 bit signed span-dependent value applied at link time * * @formatter:on */
enum PECoffX86_64Relocation implements PECoffRelocationMethod { ADDR64 { @Override public long toLong() { return IMAGE_RELOCATION.IMAGE_REL_AMD64_ADDR64; } }, ADDR32 { @Override public long toLong() { return IMAGE_RELOCATION.IMAGE_REL_AMD64_ADDR32; } }, SECREL { @Override public long toLong() { return IMAGE_RELOCATION.IMAGE_REL_AMD64_SECREL; } }, SECTION { @Override public long toLong() { return IMAGE_RELOCATION.IMAGE_REL_AMD64_SECTION; } }, REL32 { @Override public long toLong() { return IMAGE_RELOCATION.IMAGE_REL_AMD64_REL32; } }; /* * x86-64 relocs always use explicit addends. */ @Override public boolean canUseExplicitAddend() { return true; } @Override public boolean canUseImplicitAddend() { return false; } }