mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-05 02:39:44 +02:00
GP-700: Improved support for Mach-O MH_OBJECT files
This commit is contained in:
parent
92b7728cd7
commit
c2f60b15d3
27 changed files with 1542 additions and 653 deletions
|
@ -0,0 +1,82 @@
|
|||
/* ###
|
||||
* 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 ARM_MachoRelocationHandler} constants
|
||||
*
|
||||
* @see <a href="https://opensource.apple.com/source/xnu/xnu-7195.81.3/EXTERNAL_HEADERS/mach-o/arm/reloc.h.auto.html">mach-o/arm/reloc.h</a>
|
||||
*/
|
||||
public class ARM_MachoRelocationConstants {
|
||||
|
||||
/**
|
||||
* Generic relocation as described above
|
||||
*/
|
||||
public final static int ARM_RELOC_VANILLA = 0;
|
||||
|
||||
/**
|
||||
* The second relocation entry of a pair
|
||||
*/
|
||||
public final static int ARM_RELOC_PAIR = 1;
|
||||
|
||||
/**
|
||||
* A PAIR follows with subtract symbol value
|
||||
*/
|
||||
public final static int ARM_RELOC_SECTDIFF = 2;
|
||||
|
||||
/**
|
||||
* Like ARM_RELOC_SECTDIFF, but the symbol referenced was local
|
||||
*/
|
||||
public final static int ARM_RELOC_LOCAL_SECTDIFF = 3;
|
||||
|
||||
/**
|
||||
* Pre-bound lazy pointer
|
||||
*/
|
||||
public final static int ARM_RELOC_PB_LA_PTR = 4;
|
||||
|
||||
/**
|
||||
* 24 bit branch displacement (to a word address)
|
||||
*/
|
||||
public final static int ARM_RELOC_BR24 = 5;
|
||||
|
||||
/**
|
||||
* 22 bit branch displacement (to a half-word address)
|
||||
*/
|
||||
public final static int ARM_THUMB_RELOC_BR22 = 6;
|
||||
|
||||
/**
|
||||
* Obsolete - a thumb 32-bit branch instruction possibly needing page-spanning branch workaround
|
||||
*/
|
||||
public final static int ARM_THUMB_32BIT_BRANCH = 7;
|
||||
|
||||
/**
|
||||
* For these two r_type relocations they always have a pair following them and the r_length bits
|
||||
* are used differently. The encoding of the r_length is as follows:
|
||||
*
|
||||
* low bit of r_length:
|
||||
* 0 - :lower16: for movw instructions
|
||||
* 1 - :upper16: for movt instructions
|
||||
*
|
||||
* high bit of r_length:
|
||||
* 0 - arm instructions
|
||||
* 1 - thumb instructions
|
||||
*
|
||||
* The other half of the relocated expression is in the following pair relocation entry in the
|
||||
* low 16 bits of r_address field.
|
||||
*/
|
||||
public final static int ARM_RELOC_HALF = 8;
|
||||
public final static int ARM_RELOC_HALF_SECTDIFF = 9;
|
||||
}
|
|
@ -0,0 +1,105 @@
|
|||
/* ###
|
||||
* 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.ARM_MachoRelocationConstants.*;
|
||||
|
||||
import ghidra.app.util.bin.format.macho.*;
|
||||
import ghidra.program.model.address.Address;
|
||||
import ghidra.program.model.mem.MemoryAccessException;
|
||||
import ghidra.util.exception.NotFoundException;
|
||||
|
||||
/**
|
||||
* A {@link MachoRelocationHandler} for ARM
|
||||
*
|
||||
* @see <a href="https://opensource.apple.com/source/xnu/xnu-7195.81.3/EXTERNAL_HEADERS/mach-o/arm/reloc.h.auto.html">mach-o/arm/reloc.h</a>
|
||||
*/
|
||||
public class ARM_MachoRelocationHandler extends MachoRelocationHandler {
|
||||
|
||||
@Override
|
||||
public boolean canRelocate(MachHeader header) {
|
||||
return header.getCpuType() == CpuTypes.CPU_TYPE_ARM;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPairedRelocation(RelocationInfo relocation) {
|
||||
return relocation.getType() == ARM_RELOC_SECTDIFF ||
|
||||
relocation.getType() == ARM_RELOC_LOCAL_SECTDIFF ||
|
||||
relocation.getType() == ARM_RELOC_HALF ||
|
||||
relocation.getType() == ARM_RELOC_HALF_SECTDIFF;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void relocate(MachoRelocation relocation)
|
||||
throws MemoryAccessException, NotFoundException {
|
||||
|
||||
if (!relocation.requiresRelocation()) {
|
||||
return;
|
||||
}
|
||||
|
||||
RelocationInfo relocationInfo = relocation.getRelocationInfo();
|
||||
Address targetAddr = relocation.getTargetAddress();
|
||||
long orig = read(relocation);
|
||||
|
||||
switch (relocationInfo.getType()) {
|
||||
case ARM_RELOC_VANILLA:
|
||||
if (!relocationInfo.isPcRelocated()) {
|
||||
write(relocation, targetAddr.getOffset());
|
||||
}
|
||||
else {
|
||||
throw new NotFoundException("Unimplemented relocation");
|
||||
}
|
||||
break;
|
||||
case ARM_THUMB_RELOC_BR22: {
|
||||
// BL and BLX
|
||||
boolean blx = (orig & 0xd000f800) == 0xc000f000;
|
||||
long s = (orig >> 10) & 0x1;
|
||||
long j1 = (orig >> 29) & 0x1;
|
||||
long j2 = (orig >> 27) & 0x1;
|
||||
long i1 = ~(j1 ^ s) & 0x1;
|
||||
long i2 = ~(j2 ^ s) & 0x1;
|
||||
long imm10 = orig & 0x3ff;
|
||||
long imm11 = (orig >> 16) & 0x7ff;
|
||||
long addend = (s << 24) | (i1 << 23) | (i2 << 22) | (imm10 << 12) | (imm11 << 1);
|
||||
addend |= s == 1 ? 0xfe000000 : 0; // sign extend
|
||||
addend &= blx ? ~0x3 : ~0; // 4-byte align BLX
|
||||
long value = targetAddr.getOffset() + addend;
|
||||
s = (value >> 24) & 0x1;
|
||||
i1 = (value >> 23) & 0x1;
|
||||
i2 = (value >> 22) & 0x1;
|
||||
j1 = ~(i1 ^ s) & 0x1;
|
||||
j2 = ~(i2 ^ s) & 0x1;
|
||||
imm10 = (value >> 12) & 0x3ff;
|
||||
imm11 = (value >> 1) & 0x7ff;
|
||||
long instr = orig & (blx ? 0xc000f800 : 0xd000f800);
|
||||
instr |= (j1 << 29) | (j2 << 27) | (imm11 << 16) | (s << 10) | imm10;
|
||||
write(relocation, instr);
|
||||
break;
|
||||
}
|
||||
|
||||
case ARM_RELOC_PAIR: // should never see on its own here
|
||||
case ARM_RELOC_SECTDIFF: // relocation not required (scattered)
|
||||
case ARM_RELOC_LOCAL_SECTDIFF: // relocation not required (scattered)
|
||||
case ARM_RELOC_PB_LA_PTR: // not seen yet
|
||||
case ARM_RELOC_BR24: // not seen yet
|
||||
case ARM_THUMB_32BIT_BRANCH: // not seen yet
|
||||
case ARM_RELOC_HALF: // relocation not required (scattered)
|
||||
case ARM_RELOC_HALF_SECTDIFF: // relocation not required (scattered)
|
||||
default:
|
||||
throw new NotFoundException("Unimplemented relocation");
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue