/* * UnresolvedSymbol.java - This file is part of the Jakstab project. * Copyright 2007-2015 Johannes Kinder <jk@jakstab.org> * * 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. * * 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, see <http://www.gnu.org/licenses/>. */ package org.jakstab.loader; import org.jakstab.asm.AbsoluteAddress; import org.jakstab.util.Logger; public class UnresolvedSymbol { private static final Logger logger = Logger.getLogger(UnresolvedSymbol.class); private final ExecutableImage module; private final String fromLibrary; private final String name; private final int fp; public enum AddressingType { ABSOLUTE, PC_RELATIVE } private final AddressingType addressingType; public UnresolvedSymbol(ExecutableImage module, String fromLibrary, String name, int filepointer, AddressingType addressingType) { this.fromLibrary = fromLibrary; this.module = module; this.name = name; this.fp = filepointer; this.addressingType = addressingType; } public UnresolvedSymbol(ExecutableImage module, String name, int filepointer, AddressingType addressingType) { this(module, null, name, filepointer, addressingType); } public void resolve(AbsoluteAddress virtualAddress) { byte[] data = module.getByteArray(); long address = Integer.MIN_VALUE; if (addressingType == AddressingType.ABSOLUTE) { address = virtualAddress.getValue(); } else if (addressingType == AddressingType.PC_RELATIVE) { // offset = absolute address - PC value (PC holds address of _next_ instruction, which is 4 bytes (address size) from file pointer) address = virtualAddress.getValue() - module.getVirtualAddress(fp + 4).getValue(); } logger.debug("Patching bytes at VA " + module.getVirtualAddress(fp) + ", offset 0x" + Integer.toHexString(fp) + " in byte array, " + "which were " + Integer.toHexString(data[fp]) + " " + Integer.toHexString(data[fp+1]) + " " + Integer.toHexString(data[fp+2]) + " " + Integer.toHexString(data[fp+3])); data[fp] = (byte)( address & 0xFFL); data[fp + 1] = (byte)((address >> 8) & 0xFFL); data[fp + 2] = (byte)((address >> 16) & 0xFFL); data[fp + 3] = (byte)((address >> 24) & 0xFFL); } public String getName() { return name; } public String getFromLibrary() { return fromLibrary; } @Override public String toString() { return name + "(0x" + Long.toHexString(fp) + ")"; } public ExecutableImage getModule() { return module; } }