GP-3262: Mach-O PowerPC relocation framework

This commit is contained in:
Ryan Kurtz
2023-04-03 08:02:51 -04:00
parent e417c4a025
commit 32e5c3de56
8 changed files with 217 additions and 23 deletions

View File

@@ -0,0 +1,93 @@
/* ###
* IP: GHIDRA
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.app.util.bin.format.macho.relocation;
/**
* {@link PowerPC_MachoRelocationHandler} constants
*
* @see <a href="https://opensource.apple.com/source/xnu/xnu-1504.9.37/EXTERNAL_HEADERS/mach-o/ppc/reloc.h.auto.html">mach-o/ppc/reloc.h</a>
*/
public class PowerPC_MachoRelocationConstants {
/**
* Generic relocation as described above
*/
public final static int PPC_RELOC_VANILLA = 0;
/**
* The second relocation entry of a pair
*/
public final static int PPC_RELOC_PAIR = 1;
/**
* 14 bit branch displacement (to a word address)
*/
public final static int PPC_RELOC_BR14 = 2;
/**
* 24 bit branch displacement (to a word address)
*/
public final static int PPC_RELOC_BR24 = 3;
/**
* A {@link #PPC_RELOC_PAIR} follows with the low half
*/
public final static int PPC_RELOC_HI16 = 4;
/**
* A {@link #PPC_RELOC_PAIR} follows with the high half
*/
public final static int PPC_RELOC_LO16 = 5;
/**
* Same as the {@link #PPC_RELOC_HI16} except the low 16 bits and the high 16 bits are added
* together with the low 16 bits sign-extended first. This means if bit 15 of the low 16 bits
* is set the high 16 bits stored in the instruction will be adjusted.
*/
public final static int PPC_RELOC_HA16 = 6;
/**
* Same as the {@link #PPC_RELOC_LO16} except that the low 2 bits are not stored in the
* instruction and are always zero. This is used in double word load/store instructions.
*/
public final static int PPC_RELOC_LO14 = 7;
/**
* A {@link #PPC_RELOC_PAIR} follows with subtract symbol value
*/
public final static int PPC_RELOC_SECTDIFF = 8;
/**
* Pre-bound lazy pointer
*/
public final static int PPC_RELOC_PB_LA_PTR = 9;
/**
* A section difference forms of above.
* A {@link #PPC_RELOC_PAIR} Follows these with subtract symbol value.
*/
public final static int PPC_RELOC_HI16_SECTDIFF = 10;
public final static int PPC_RELOC_LO16_SECTDIFF = 11;
public final static int PPC_RELOC_HA16_SECTDIFF = 12;
public final static int PPC_RELOC_JBSR = 13;
public final static int PPC_RELOC_LO14_SECTDIFF = 14;
/**
* Like {@link #PPC_RELOC_SECTDIFF}, but the symbol referenced was local.
*/
public final static int PPC_RELOC_LOCAL_SECTDIFF = 15;
}

View File

@@ -0,0 +1,89 @@
/* ###
* IP: GHIDRA
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.app.util.bin.format.macho.relocation;
import static ghidra.app.util.bin.format.macho.relocation.PowerPC_MachoRelocationConstants.*;
import ghidra.app.util.bin.format.RelocationException;
import ghidra.app.util.bin.format.macho.*;
import ghidra.program.model.mem.MemoryAccessException;
import ghidra.program.model.reloc.RelocationResult;
/**
* A {@link MachoRelocationHandler} for PowerPC
*
* @see <a href="https://opensource.apple.com/source/xnu/xnu-1504.9.37/EXTERNAL_HEADERS/mach-o/ppc/reloc.h.auto.html">mach-o/ppc/reloc.h</a>
*/
public class PowerPC_MachoRelocationHandler extends MachoRelocationHandler {
@Override
public boolean canRelocate(MachHeader header) {
return header.getCpuType() == CpuTypes.CPU_TYPE_POWERPC;
}
@Override
public boolean isPairedRelocation(RelocationInfo relocation) {
return switch (relocation.getType()) {
case PPC_RELOC_HI16:
case PPC_RELOC_LO16:
case PPC_RELOC_HA16:
case PPC_RELOC_LO14:
case PPC_RELOC_SECTDIFF:
case PPC_RELOC_HI16_SECTDIFF:
case PPC_RELOC_LO16_SECTDIFF:
case PPC_RELOC_HA16_SECTDIFF:
case PPC_RELOC_JBSR:
case PPC_RELOC_LO14_SECTDIFF:
case PPC_RELOC_LOCAL_SECTDIFF: {
yield true;
}
default:
yield false;
};
}
@Override
public RelocationResult relocate(MachoRelocation relocation)
throws MemoryAccessException, RelocationException {
if (!relocation.requiresRelocation()) {
return RelocationResult.SKIPPED;
}
RelocationInfo relocationInfo = relocation.getRelocationInfo();
switch (relocationInfo.getType()) {
case PPC_RELOC_VANILLA: // not seen yet
case PPC_RELOC_PAIR: // not seen yet
case PPC_RELOC_BR14: // not seen yet
case PPC_RELOC_BR24: // not seen yet
case PPC_RELOC_HI16: // not seen yet
case PPC_RELOC_LO16: // not seen yet
case PPC_RELOC_HA16: // not seen yet
case PPC_RELOC_LO14: // not seen yet
case PPC_RELOC_SECTDIFF: // not seen yet
case PPC_RELOC_PB_LA_PTR: // not seen yet
case PPC_RELOC_HI16_SECTDIFF: // not seen yet
case PPC_RELOC_LO16_SECTDIFF: // not seen yet
case PPC_RELOC_HA16_SECTDIFF: // not seen yet
case PPC_RELOC_JBSR: // not seen yet
case PPC_RELOC_LO14_SECTDIFF: // not seen yet
case PPC_RELOC_LOCAL_SECTDIFF: // not seen yet
default:
return RelocationResult.UNSUPPORTED;
}
}
}