# SPDX-License-Identifier: MPL-2.0 import os import sys import subprocess class VirtualRegion: def __init__(self,start,size): self.start=start self.size=size def compute_end(self): self.end=self.start+self.size args=sys.argv if len(args)!=2: print("[VMLC] Error: not enough arguments") exit(-1) hfile=args[1] if not os.path.exists(hfile): print("[VMLC] Error: provided .h file doesn't exist") exit(-1) hfile=os.path.abspath(hfile) print("[VMLC] Provided file: "+hfile) incomplete_region_va=[] incomplete_region_size_bytes=[] region_name=[] fileslines=open(hfile,"r").readlines() macros=[] for i in range(len(fileslines)): if fileslines[i].startswith("#define"): macros.append(fileslines[i]) for i in range(len(macros)): macroname=str(str(macros[i]).strip(" ").split(" ")[1]) if macroname.endswith("_VA"): if not macroname in incomplete_region_va: incomplete_region_va.append(macroname) else: print("[VMLC] Error: found duplicate macro: "+macroname) exit(-1) elif macroname.endswith("_SIZE_BYTES"): if not macroname in incomplete_region_size_bytes: incomplete_region_size_bytes.append(macroname) else: print("[VMLC] Error: found duplicate macro: "+macroname) exit(-1) for i in range(len(incomplete_region_va)): macronamesize=str(incomplete_region_va[i]).removesuffix("_VA")+"_SIZE_BYTES" if not macronamesize in incomplete_region_size_bytes: print("[VMLC] Error: for region \""+str(incomplete_region_va[i]).removesuffix("_VA")+"\", corresponding size wasn't found.") exit(-1) for i in range(len(incomplete_region_size_bytes)): macronameva=str(incomplete_region_size_bytes[i]).removesuffix("_SIZE_BYTES")+"_VA" if not macronameva in incomplete_region_va: print("[VMLC] Warning: for region \""+str(incomplete_region_size_bytes[i]).removesuffix("_SIZE_BYTES")+"\", corresponding VA wasn't found. Skipping") print("[VMLC] Found "+str(len(incomplete_region_va))+" valid virtual regions: ",end="") for i in range(len(incomplete_region_va)): if i!=len(incomplete_region_va)-1: print(incomplete_region_va[i].removesuffix("_VA")+", ",end="") else: print(incomplete_region_va[i].removesuffix("_VA")) region_name.append(incomplete_region_va[i].removesuffix("_VA")) os.chdir(os.path.dirname(__file__)) try: os.remove("cfile.c") except FileNotFoundError: pass tmpcfile=open("cfile.c","w") tmpcfile.write("#include \n#include \n#include \n#include \""+hfile+"\"\n") tmpcfile.write("int main() {\n char buf[256];\n FILE *f=fopen(\"reg.txt\",\"w\");\n") tmpcfile.write(" if (!f) return -1;\n") for i in range(len(region_name)): tmpcfile.write(" snprintf(buf,256,\"%\" PRIu64 \" %\" PRIu64 \"\\n\",(uint64_t)"+region_name[i]+"_VA,(uint64_t)"+region_name[i]+"_SIZE_BYTES);\n") tmpcfile.write(" fwrite(buf,1,strlen(buf),f);\n") tmpcfile.write(" fclose(f);\n return 0;\n}") tmpcfile.close() try: os.remove("cfile") os.remove("reg.txt") except FileNotFoundError: pass r=subprocess.run(["gcc","cfile.c","-o","cfile"]) if r.returncode!=0: print("[VMLC] Error: can't compile generated cfile.c") exit(-1) r=subprocess.run(["./cfile"]) if r.returncode!=0: print("[VMLC] Error: can't run compiled cfile") exit(-1) if not os.path.exists("reg.txt"): print("[VMLC] Error: reg.txt doesn't exist") exit(-1) reglist={} regstart=[] with open("reg.txt") as f: for line in f: va,size=line.strip().split() vr=VirtualRegion(int(va),int(size)) vr.compute_end() reglist[int(va)]=vr if not vr.start in regstart: regstart.append(vr.start) else: print("[VMLC] Error: found two regions starting at the same VA: "+str(vr.start)+" / 0x"+str(hex(vr.start))) exit(-1) print("[VMLC] Obtained region decimal VA and size.") regstart.sort() regboundaries=[] for i in range(len(regstart)): regboundaries.append(reglist[regstart[i]].start) regboundaries.append(reglist[regstart[i]].end) print("[VMLC] Checking for overlaps...") for i in range(1,len(regboundaries)-1,2): if regboundaries[i]>regboundaries[i+1]: print("[VMLC] Error: found overlap between region ending at "+str(regboundaries[i])+" / 0x"+str(hex(regboundaries[i]))+" and region starting at "+str(regboundaries[i+1])+" / 0x"+str(hex(regboundaries[i+1]))) exit(-1) print("[VMLC] No overlaps found.") try: os.remove("reg.txt") os.remove("cfile.c") os.remove("cfile") except FileNotFoundError: pass