Created
November 14, 2020 09:39
-
-
Save bruce30262/c075e7ea623b8997f98c8137b8216b46 to your computer and use it in GitHub Desktop.
ghidra python script for fixing "Unknown Error" in the decompile window of RISC-V binary ( for RV64I language binary )
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Check out the issue for more detail : https://github.com/NationalSecurityAgency/ghidra/issues/2466 | |
# The script will calculate the value of gp register base on the code in entry(), then apply the value to all the functions | |
# This only work in the `RV64I` language though, since other language like `RV64GC` won't set the gp register in entry() | |
from java.math import BigInteger | |
def newAddress(offset): | |
""" | |
Helper function to get a Ghidra Address type | |
""" | |
return currentProgram.getAddressFactory().getDefaultAddressSpace().getAddress(offset) | |
# get entry() function code unit | |
listing = currentProgram.getListing() | |
entry_func = getGlobalFunctions("entry")[0] # one entry function, just get it from index | |
addrSet = entry_func.getBody() # get the body address range | |
codeUnits = listing.getCodeUnits(addrSet, True) # get code units ( instructions and their addresses...). true means 'forward' | |
gp = None | |
def cal_gp(): | |
""" | |
Calculate the value of gp ( global pointer register ) | |
""" | |
global codeUnits, gp | |
if gp != None: | |
return | |
gp = 0 | |
for codeUnit in codeUnits: | |
# print codeUnit info | |
# from binascii import hexlify | |
# print("0x{} : {:16} {}".format(codeUnit.getAddress(), hexlify(codeUnit.getBytes()), codeUnit.toString())) | |
asm = codeUnit.toString() | |
# gp = (<auipc's imm> << 12) + <pc_of_auipc> + <addi's imm> | |
if "auipc gp" in asm: | |
imm = int(asm.split(",")[-1], 16) | |
gp = (imm << 12) + codeUnit.getAddress().getOffset() # getOffset so it returns a integer | |
elif "addi gp,gp" in asm: | |
imm = int(asm.split(",")[-1], 16) | |
gp += imm | |
return | |
cal_gp() # calculate gp | |
print("gp value: {:#x}".format(gp)) | |
# Get all functions | |
# Modify all the gp register in those functions ( except "entry()" ) | |
gp_reg = currentProgram.getRegister("gp") # get Register type of gp | |
fm = currentProgram.getFunctionManager() | |
funcs = fm.getFunctions(True) # True means 'forward' | |
for func in funcs: | |
if(func.getName() == "entry"): # skip entry() | |
continue | |
print("===================================") | |
print("Function: {} @ 0x{}".format(func.getName(), func.getEntryPoint())) | |
addrSet = func.getBody() | |
addrStart = addrSet.getMinAddress() | |
addrEnd = addrSet.getMaxAddress() | |
print("Address start: 0x{}".format(addrStart)) | |
print("Address end: 0x{}".format(addrEnd)) | |
print("Modify the value of gp register...") | |
currentProgram.programContext.setValue(gp_reg, addrStart, addrEnd, BigInteger.valueOf(gp)) | |
print("OK !") | |
print("===================================") | |
print("All done !") |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment