Skip to content

Instantly share code, notes, and snippets.

@bruce30262
Created November 14, 2020 09:39
Show Gist options
  • Save bruce30262/c075e7ea623b8997f98c8137b8216b46 to your computer and use it in GitHub Desktop.
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 )
# 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