/* * $Id$ * * Copyright (C) 2003-2015 JNode.org * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published * by the Free Software Foundation; either version 2.1 of the License, or * (at your option) any later version. * * This library 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 Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; If not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ package org.jnode.linker; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import org.jnode.util.NumberUtils; public class Reloc { public static final Type R_386_32 = new Type("R_386_32", 1); /* ordinary absolute relocation */ public static final Type R_386_PC32 = new Type("R_386_PC32", 2); /* PC-relative relocation */ public static final Type R_386_GOT32 = new Type("R_386_GOT32", 3); /* an offset into GOT */ public static final Type R_386_PLT32 = new Type("R_386_PLT32", 4); /* a PC-relative offset into PLT */ public static final Type R_386_GOTOFF = new Type("R_386_GOTOFF", 9); /* an offset from GOT base */ public static final Type R_386_GOTPC = new Type("R_386_GOTPC", 10); public static final Type[] i386_RelocNumbers = { R_386_32, R_386_PC32, R_386_GOT32, R_386_PLT32, R_386_GOTOFF, R_386_GOTPC }; public static final Type R_X86_64_NONE = new Type("R_X86_64_NONE", 0); /* No reloc */ public static final Type R_X86_64_64 = new Type("R_X86_64_64", 1); /* Direct 64 bit */ public static final Type R_X86_64_PC32 = new Type("R_X86_64_PC32", 2); /* PC relative 32 bit signed */ public static final Type R_X86_64_GOT32 = new Type("R_X86_64_GOT32", 3); /* 32 bit GOT entry */ public static final Type R_X86_64_PLT32 = new Type("R_X86_64_PLT32", 4); /* 32 bit PLT address */ public static final Type R_X86_64_COPY = new Type("R_X86_64_COPY", 5); /* Copy symbol at runtime */ public static final Type R_X86_64_GLOB_DAT = new Type("R_X86_64_GLOB_DAT", 6); /* Create GOT entry */ public static final Type R_X86_64_JUMP_SLOT = new Type("R_X86_64_JUMP_SLOT", 7); /* Create PLT entry */ public static final Type R_X86_64_RELATIVE = new Type("R_X86_64_RELATIVE", 8); /* Adjust by program base */ public static final Type R_X86_64_GOTPCREL = new Type("R_X86_64_GOTPCREL", 9); /* * 32 bit signed pc relative offset * to GOT */ public static final Type R_X86_64_32 = new Type("R_X86_64_32", 10); /* Direct 32 bit zero extended */ public static final Type R_X86_64_32S = new Type("R_X86_64_32S", 11); /* Direct 32 bit sign extended */ public static final Type R_X86_64_16 = new Type("R_X86_64_16", 12); /* Direct 16 bit zero extended */ public static final Type R_X86_64_PC16 = new Type("R_X86_64_PC16", 13); /* 16 bit sign extended pc relative */ public static final Type R_X86_64_8 = new Type("R_X86_64_8", 14); /* Direct 8 bit sign extended */ public static final Type R_X86_64_PC8 = new Type("R_X86_64_PC8", 15); /* 8 bit sign extended pc relative */ public static final Type R_X86_64_DTPMOD64 = new Type("R_X86_64_DTPMOD64", 16); /* ID of module containing symbol*/ public static final Type R_X86_64_DTPOFF64 = new Type("R_X86_64_DTPOFF64", 17); /* Offset in TLS block */ public static final Type R_X86_64_TPOFF64 = new Type("R_X86_64_TPOFF64", 18); /* Offset in initial TLS block */ public static final Type R_X86_64_TLSGD = new Type("R_X86_64_TLSGD", 19); /* PC relative offset to GD GOT block */ public static final Type R_X86_64_TLSLD = new Type("R_X86_64_TLSLD", 20); /* PC relative offset to LD GOT block */ public static final Type R_X86_64_DTPOFF32 = new Type("R_X86_64_DTPOFF32", 21); /* Offset in TLS block */ public static final Type R_X86_64_GOTTPOFF = new Type("R_X86_64_GOTTPOFF", 22); /* PC relative offset to IE GOT * entry */ public static final Type R_X86_64_TPOFF32 = new Type("R_X86_64_TPOFF32", 23); /* Offset in initial TLS block */ public static final Type[] x86_64_RelocNumbers = { R_X86_64_NONE, /* No reloc */ R_X86_64_64, /* Direct 64 bit */ R_X86_64_PC32, /* PC relative 32 bit signed */ R_X86_64_GOT32, /* 32 bit GOT entry */ R_X86_64_PLT32, /* 32 bit PLT address */ R_X86_64_COPY, /* Copy symbol at runtime */ R_X86_64_GLOB_DAT, /* Create GOT entry */ R_X86_64_JUMP_SLOT, /* Create PLT entry */ R_X86_64_RELATIVE, /* Adjust by program base */ R_X86_64_GOTPCREL, /* 32 bit signed pc relative offset to GOT */ R_X86_64_32, /* Direct 32 bit zero extended */ R_X86_64_32S, /* Direct 32 bit sign extended */ R_X86_64_16, /* Direct 16 bit zero extended */ R_X86_64_PC16, /* 16 bit sign extended pc relative*/ R_X86_64_8, /* Direct 8 bit sign extended */ R_X86_64_PC8, /* 8 bit sign extended pc relative*/ R_X86_64_DTPMOD64, /* ID of module containing symbol */ R_X86_64_DTPOFF64, /* Offset in TLS block */ R_X86_64_TPOFF64, /* Offset in initial TLS block */ R_X86_64_TLSGD, /* PC relative offset to GD GOT block */ R_X86_64_TLSLD, /* PC relative offset to LD GOT block */ R_X86_64_DTPOFF32, /* Offset in TLS block */ R_X86_64_GOTTPOFF, /* PC relative offset to IE GOT entry */ R_X86_64_TPOFF32, /* Offset in initial TLS block */ }; private final long r_address; private int r_symndx; private final int r_type; private final Elf elf; private Symbol symbol; private long r_info; public Reloc(Elf elf, InputStream in) throws IOException { this.elf = elf; this.r_address = LoadUtil.loadAddr(in, elf.e_ident); final long info = LoadUtil.loadXword(in, elf.e_ident); this.r_info = info; if (elf.isClass32()) { this.r_symndx = (int) (info >> 8); this.r_type = (int) (info & 0xFF); } else { this.r_symndx = (int) (info >>> 32); this.r_type = (int) (info & 0xFFFFFFFF); } } private Reloc(Elf elf, Symbol symbol, long address, Type type) { this.elf = elf; this.r_address = address; this.r_type = type.getNr(); this.symbol = symbol; } public static Reloc newAbsInstance(Elf elf, Symbol symbol, long address) { return new Reloc(elf, symbol, address, R_386_32); } public static Reloc newPcRelInstance(Elf elf, Symbol symbol, long address) { return new Reloc(elf, symbol, address, R_386_PC32); } public int store(OutputStream out) throws IOException { if (symbol != null) { r_symndx = elf.getIndexOfSymbol(symbol); } final long info; if (elf.isClass32()) { info = (r_type & 0xFF) | (r_symndx << 8); } else { info = ((long) r_type) | (((long) r_symndx) << 32); } int cnt = 0; cnt += StoreUtil.storeAddr(out, elf.e_ident, r_address); cnt += StoreUtil.storeXword(out, elf.e_ident, info); return cnt; } public long getAddress() { return r_address; } public int getSymbolIndex() { if (symbol != null) { return elf.getIndexOfSymbol(symbol); } else { return r_symndx; } } public int getType() { return r_type; } public Type getRelocType() { final Type[] types = (elf.isClass32() ? i386_RelocNumbers : x86_64_RelocNumbers); final int length = types.length; for (int i = 0; i < length; i++) { if (types[i].getNr() == r_type) { return types[i]; } } return null; } public String getTypeName() { final Type type = getRelocType(); if (type != null) { return type.toString(); } else { return "type-" + r_type; } } public Symbol getSymbol() { if (symbol != null) { return symbol; } else { return elf.getSymbol(r_symndx); } } public boolean hasAddEnd() { return false; } public long getAddEnd() { return 0; } public void print() { System.out.println(" ----- Reloc -----"); System.out.println(" r_address : " + Long.toHexString(r_address)); System.out.println(" r_symbol : " + getSymbol()); System.out.println(" r_type : " + getTypeName()); System.out.println(" r_info : " + NumberUtils.hex(r_info)); if (hasAddEnd()) { System.out.println(" r_addend : " + NumberUtils.hex(getAddEnd())); } } public static final class Type { private final int nr; private final String name; private Type(String name, int nr) { this.name = name; this.nr = nr; } public int getNr() { return nr; } public String toString() { return name; } } }