diff --git a/common.py b/common.py index 8934b6f..236fb1d 100644 --- a/common.py +++ b/common.py @@ -15,6 +15,7 @@ MAGIC_112 = 0xFFFFFFFB # Magic Number from version 1.12 MAGIC_116 = 0xFFFFFFFA # Magic Number from version 1.16 MAGIC_118 = 0xFFFFFFF0 # Magic Number from version 1.18 +MAGIC_120 = 0xFFFFFFF1 # Magic Number from version 1.20 if finfo.is_64bit(): diff --git a/moduledata.py b/moduledata.py index 9da7c37..efcea77 100644 --- a/moduledata.py +++ b/moduledata.py @@ -61,7 +61,7 @@ def test_firstmoduledata(possible_addr, magic_number): return True else: common._debug(f"Not firstmoduledata addr: @ {possible_addr:#x}") - elif magic_number == common.MAGIC_118: + elif magic_number == common.MAGIC_118 or magic_number == common.MAGIC_120: funcnametab_off = read_mem(mod_data.pcheader_addr + 8 + 3*ADDR_SZ, read_only=True) filetab_off = read_mem(mod_data.pcheader_addr + 8 + 5*ADDR_SZ, read_only=True) pctab_off = read_mem(mod_data.pcheader_addr + 8 + 6*ADDR_SZ, read_only=True) @@ -112,9 +112,9 @@ def find_first_moduledata_addr_by_brute(magic_number): curr_seg = ida_segment.getnseg(idx) if curr_seg.type == 3: # Pure Data segment curr_addr = curr_seg.start_ea - #common._info(f"Search seg [{curr_seg.name}], start: {curr_seg.start_ea:#x}, end: {curr_seg.end_ea:#x}, type: {curr_seg.type}") + common._info(f"Search seg [{curr_seg.name}], start: {curr_seg.start_ea:#x}, end: {curr_seg.end_ea:#x}, type: {curr_seg.type}") while curr_addr <= curr_seg.end_ea: - #common._debug(f"Test firstmoduledata @ {curr_addr:#x} for magic_number {magic_number:#x}") + common._debug(f"Test firstmoduledata @ {curr_addr:#x} for magic_number {magic_number:#x}") if idc.get_wide_dword(read_mem(curr_addr, read_only=True)) & 0xFFFFFFFF == magic_number: # possible firstmoduledata if test_firstmoduledata(curr_addr, magic_number): break @@ -140,7 +140,7 @@ def find_first_moduledata_addr(): break else: # is stripped, find firstmodule data by bruteforce searching common._debug("Binary file is stripped") - magic_numbers = [common.MAGIC_116, common.MAGIC_112, common.MAGIC_118] + magic_numbers = [common.MAGIC_116, common.MAGIC_112, common.MAGIC_118, common.MAGIC_120] # firstmoduledata is often contained in segment [.noptrdata] mdata_seg_addr = get_mdata_seg_addr() common._info("Finding firstmoduledata object...") @@ -164,7 +164,7 @@ def find_first_moduledata_addr(): first_moduledata_addr = curr_addr break - if first_moduledata_addr == idc.BADADDR and mdata_seg_addr == 0: + if first_moduledata_addr == idc.BADADDR:# and mdata_seg_addr == 0: common._info("Now find firstmoduledata object by bruteforcing...") for tmp_magic_number in magic_numbers: common._info(f"Finding firstmoduledata with magic number {tmp_magic_number:#x} by bruteforcing...") @@ -269,6 +269,51 @@ class ModuleData(): next *moduledata } + type moduledata struct { // Go version 1.20+ + pcHeader *pcHeader + funcnametab []byte + cutab []uint32 + filetab []byte + pctab []byte + pclntable []byte + ftab []functab + findfunctab uintptr + minpc, maxpc uintptr + + text, etext uintptr + noptrdata, enoptrdata uintptr + data, edata uintptr + bss, ebss uintptr + noptrbss, enoptrbss uintptr + covctrs, ecovctrs uintptr // Starts from 1.20 + end, gcdata, gcbss uintptr + types, etypes uintptr + rodata uintptr // Starts from 1.18 + gofunc uintptr // go.func.* // Starts from 1.18 + + textsectmap []textsect + typelinks []int32 // offsets from types + itablinks []*itab + + ptab []ptabEntry + + pluginpath string + pkghashes []modulehash + + modulename string + modulehashes []modulehash + + hasmain uint8 // 1 if module contains the main function, 0 otherwise + + gcdatamask, gcbssmask bitvector + + typemap map[typeOff]*_type // offset to *_rtype in previous module + + bad bool // module failed to load and should be ignored + + next *moduledata + } + type pcHeader struct { // Go version 1.16+ magic uint32 // 0xFFFFFFFA pad1, pad2 uint8 // 0, 0 @@ -442,11 +487,13 @@ def parse(self, is_test=False): pluginpath_addr = read_mem(self.start_addr + 39*ADDR_SZ, read_only=is_test) pluginpath_len = read_mem(self.start_addr + 40*ADDR_SZ, read_only=is_test) - self.pluginpath = "" if (pluginpath_len==0x0 or pluginpath_addr ==0x0) else idc.get_bytes(pluginpath_addr, pluginpath_len).decode() + self.pluginpath = "" if (pluginpath_len==0x0 or pluginpath_addr ==0x0) else \ + idc.get_bytes(pluginpath_addr, pluginpath_len).decode() modulename_addr = read_mem(self.start_addr+44*ADDR_SZ, read_only=is_test) modulename_len = read_mem(self.start_addr+45*ADDR_SZ, read_only=is_test) - self.modulename ="" if modulename_addr == 0x0 or modulename_len == 0 else idc.get_bytes(modulename_addr, modulename_len).decode() + self.modulename ="" if modulename_addr == 0x0 or modulename_len == 0 else \ + idc.get_bytes(modulename_addr, modulename_len).decode() self.hasmain = idc.get_wide_byte(self.start_addr + 49*ADDR_SZ) self.next = read_mem(self.start_addr + 54*ADDR_SZ+1, read_only=is_test) @@ -502,9 +549,10 @@ def parse(self, is_test=False): idc.create_strlit(modulename_addr, modulename_addr+modulename_len) idaapi.auto_wait() + idc.create_strlit(pluginpath_addr, pluginpath_addr+pluginpath_len) idaapi.auto_wait() - else: # Go 1.16+ + elif self.magic_number == common.MAGIC_116 or self.magic_number == common.MAGIC_118: self.noptrdata_addr = read_mem(self.start_addr + 24*ADDR_SZ, read_only=is_test) self.enoptrdata_addr = read_mem(self.start_addr + 25*ADDR_SZ, read_only=is_test) self.data_addr = read_mem(self.start_addr + 26*ADDR_SZ, read_only=is_test) @@ -535,11 +583,13 @@ def parse(self, is_test=False): pluginpath_addr = read_mem(self.start_addr+49*ADDR_SZ, read_only=is_test) pluginpath_len = read_mem(self.start_addr+50*ADDR_SZ, read_only=is_test) - self.pluginpath = "" if (pluginpath_len==0x0 or pluginpath_addr ==0x0) else idc.get_bytes(pluginpath_addr, pluginpath_len).decode() + self.pluginpath = "" if (pluginpath_len==0x0 or pluginpath_addr ==0x0) else \ + idc.get_bytes(pluginpath_addr, pluginpath_len).decode() modulename_addr = read_mem(self.start_addr+54*ADDR_SZ, read_only=is_test) modulename_len = read_mem(self.start_addr+55*ADDR_SZ, read_only=is_test) - self.modulename = "" if modulename_addr ==0x0 or modulename_len ==0 else idc.get_bytes(modulename_addr, modulename_len).decode() + self.modulename = "" if modulename_addr ==0x0 or modulename_len ==0 else \ + idc.get_bytes(modulename_addr, modulename_len).decode() self.hasmain = idc.get_wide_byte(self.start_addr+59*ADDR_SZ) self.next = read_mem(self.start_addr+64*ADDR_SZ+1, read_only=is_test) @@ -562,11 +612,13 @@ def parse(self, is_test=False): pluginpath_addr = read_mem(self.start_addr + 51*ADDR_SZ, read_only=is_test) pluginpath_len = read_mem(self.start_addr + 52*ADDR_SZ, read_only=is_test) - self.pluginpath = "" if (pluginpath_len == 0x0 or pluginpath_addr == 0x0) else idc.get_bytes(pluginpath_addr, pluginpath_len).decode() + self.pluginpath = "" if (pluginpath_len == 0x0 or pluginpath_addr == 0x0) else \ + idc.get_bytes(pluginpath_addr, pluginpath_len).decode() modulename_addr = read_mem(self.start_addr + 56*ADDR_SZ, read_only=is_test) modulename_len = read_mem(self.start_addr + 57*ADDR_SZ, read_only=is_test) - self.modulename ="" if modulename_addr == 0x0 or modulename_len == 0x0 else idc.get_bytes(modulename_addr, modulename_len).decode() + self.modulename ="" if modulename_addr == 0x0 or modulename_len == 0x0 else \ + idc.get_bytes(modulename_addr, modulename_len).decode() self.hasmain = idc.get_wide_byte(self.start_addr + 61*ADDR_SZ) self.next = read_mem(self.start_addr + 66*ADDR_SZ+1, read_only=is_test) @@ -654,5 +706,118 @@ def parse(self, is_test=False): idc.create_strlit(modulename_addr, modulename_addr+modulename_len) idaapi.auto_wait() + + idc.create_strlit(pluginpath_addr, pluginpath_addr+pluginpath_len) + idaapi.auto_wait() + else: # MAGIC_120 + self.noptrdata_addr = read_mem(self.start_addr + 24*ADDR_SZ, read_only=is_test) + self.enoptrdata_addr = read_mem(self.start_addr + 25*ADDR_SZ, read_only=is_test) + self.data_addr = read_mem(self.start_addr + 26*ADDR_SZ, read_only=is_test) + self.edata_addr = read_mem(self.start_addr + 27*ADDR_SZ, read_only=is_test) + self.bss_addr = read_mem(self.start_addr + 28*ADDR_SZ, read_only=is_test) + self.ebss_addr = read_mem(self.start_addr + 29*ADDR_SZ, read_only=is_test) + self.noptrbss_addr = read_mem(self.start_addr + 30*ADDR_SZ, read_only=is_test) + self.enoptrbss_addr = read_mem(self.start_addr + 31*ADDR_SZ, read_only=is_test) + self.covctrs_addr = read_mem(self.start_addr + 32*ADDR_SZ, read_only=is_test) + self.ecovctrs_addr = read_mem(self.start_addr + 33*ADDR_SZ, read_only=is_test) + self.end_addr = read_mem(self.start_addr + 34*ADDR_SZ, read_only=is_test) + self.gcdata_addr = read_mem(self.start_addr + 35*ADDR_SZ, read_only=is_test) + self.gcbss_addr = read_mem(self.start_addr + 36*ADDR_SZ, read_only=is_test) + self.types_addr = read_mem(self.start_addr + 37*ADDR_SZ, read_only=is_test) + self.etypes_addr = read_mem(self.start_addr + 38*ADDR_SZ, read_only=is_test) + self.rodata_addr = read_mem(self.start_addr + 39*ADDR_SZ, read_only=is_test) + self.gofunc_addr = read_mem(self.start_addr + 40*ADDR_SZ, read_only=is_test) + self.textsecmap_addr = read_mem(self.start_addr + 41*ADDR_SZ, read_only=is_test) + self.textsecmap_len = read_mem(self.start_addr + 42*ADDR_SZ, read_only=is_test) + self.textsecmap_cap = read_mem(self.start_addr + 43*ADDR_SZ, read_only=is_test) + self.typelink_addr = read_mem(self.start_addr + 44*ADDR_SZ, read_only=is_test) + self.type_cnt = read_mem(self.start_addr + 45*ADDR_SZ, read_only=is_test) + self.type_cap = read_mem(self.start_addr + 46*ADDR_SZ, read_only=is_test) + self.itablink_addr = read_mem(self.start_addr + 47*ADDR_SZ, read_only=is_test) + self.itab_cnt = read_mem(self.start_addr + 48*ADDR_SZ, read_only=is_test) + self.itab_cap = read_mem(self.start_addr + 49*ADDR_SZ, read_only=is_test) + self.ptab_addr = read_mem(self.start_addr + 50*ADDR_SZ, read_only=is_test) + self.ptab_sz = read_mem(self.start_addr + 51*ADDR_SZ, read_only=is_test) + self.ptab_cap = read_mem(self.start_addr + 52*ADDR_SZ, read_only=is_test) + + pluginpath_addr = read_mem(self.start_addr + 53*ADDR_SZ, read_only=is_test) + pluginpath_len = read_mem(self.start_addr + 54*ADDR_SZ, read_only=is_test) + self.pluginpath = "" if (pluginpath_len == 0x0 or pluginpath_addr == 0x0) else \ + idc.get_bytes(pluginpath_addr, pluginpath_len).decode() + + modulename_addr = read_mem(self.start_addr + 58*ADDR_SZ, read_only=is_test) + modulename_len = read_mem(self.start_addr + 59*ADDR_SZ, read_only=is_test) + self.modulename ="" if modulename_addr == 0x0 or modulename_len == 0x0 else \ + idc.get_bytes(modulename_addr, modulename_len).decode() + + self.hasmain = idc.get_wide_byte(self.start_addr + 63*ADDR_SZ) + self.next = read_mem(self.start_addr + 69*ADDR_SZ+1, read_only=is_test) + + # Set comment for each field + idc.set_cmt(self.start_addr, "pcHeader", 0) + idc.set_cmt(self.start_addr + ADDR_SZ, "funcnametab addr", 0) + idc.set_cmt(self.start_addr + 2*ADDR_SZ, "funcnametab size", 0) + idc.set_cmt(self.start_addr + 3*ADDR_SZ, "funcnametab capacity", 0) + idc.set_cmt(self.start_addr + 4*ADDR_SZ, "cutab addr", 0) + idc.set_cmt(self.start_addr + 5*ADDR_SZ, "cutab count", 0) + idc.set_cmt(self.start_addr + 6*ADDR_SZ, "cutab capacity", 0) + idc.set_cmt(self.start_addr + 7*ADDR_SZ, "source files table addr",0) + idc.set_cmt(self.start_addr + 8*ADDR_SZ, "source files count",0) + idc.set_cmt(self.start_addr + 9*ADDR_SZ, "source files table capacity",0) + idc.set_cmt(self.start_addr + 10*ADDR_SZ, "pc table addr", 0) + idc.set_cmt(self.start_addr + 11*ADDR_SZ, "pc table size", 0) + idc.set_cmt(self.start_addr + 12*ADDR_SZ, "pc table capacity", 0) + idc.set_cmt(self.start_addr + 13*ADDR_SZ, "pclntbl addr",0) + idc.set_cmt(self.start_addr + 14*ADDR_SZ, "pclntbl size",0) + idc.set_cmt(self.start_addr + 15*ADDR_SZ, "pclntbl capacity",0) + idc.set_cmt(self.start_addr + 16*ADDR_SZ, "funcs table addr",0) + idc.set_cmt(self.start_addr + 17*ADDR_SZ, "funcs count",0) + idc.set_cmt(self.start_addr + 18*ADDR_SZ, "funcs table capacity",0) + idc.set_cmt(self.start_addr + 19*ADDR_SZ, "findfunctable addr",0) + idc.set_cmt(self.start_addr + 20*ADDR_SZ, "min pc",0) + idc.set_cmt(self.start_addr + 21*ADDR_SZ, "max pc",0) + idc.set_cmt(self.start_addr + 22*ADDR_SZ, "text start addr",0) + idc.set_cmt(self.start_addr + 23*ADDR_SZ, "text end addr",0) + idc.set_cmt(self.start_addr + 24*ADDR_SZ, "noptrdata start addr",0) + idc.set_cmt(self.start_addr + 25*ADDR_SZ, "noptrdata end addr",0) + idc.set_cmt(self.start_addr + 26*ADDR_SZ, "data section start addr",0) + idc.set_cmt(self.start_addr + 27*ADDR_SZ, "data section end addr",0) + idc.set_cmt(self.start_addr + 28*ADDR_SZ, "bss start addr",0) + idc.set_cmt(self.start_addr + 29*ADDR_SZ, "bss end addr",0) + idc.set_cmt(self.start_addr + 30*ADDR_SZ, "noptrbss start addr",0) + idc.set_cmt(self.start_addr + 31*ADDR_SZ, "noptrbss end addr",0) + idc.set_cmt(self.start_addr + 32*ADDR_SZ, "code coverage counters start addr",0) + idc.set_cmt(self.start_addr + 33*ADDR_SZ, "code coverage counters end addr",0) + idc.set_cmt(self.start_addr + 34*ADDR_SZ, "end addr of whole image",0) + idc.set_cmt(self.start_addr + 35*ADDR_SZ, "gcdata addr",0) + idc.set_cmt(self.start_addr + 36*ADDR_SZ, "gcbss addr",0) + idc.set_cmt(self.start_addr + 37*ADDR_SZ, "types start addr",0) + idc.set_cmt(self.start_addr + 38*ADDR_SZ, "types end addr",0) + idc.set_cmt(self.start_addr + 39*ADDR_SZ, "rodata addr",0) + idc.set_cmt(self.start_addr + 40*ADDR_SZ, "go func pointer addr",0) + idc.set_cmt(self.start_addr + 41*ADDR_SZ, "text section map addr",0) + idc.set_cmt(self.start_addr + 42*ADDR_SZ, "text section map length",0) + idc.set_cmt(self.start_addr + 43*ADDR_SZ, "text section map capacity",0) + idc.set_cmt(self.start_addr + 44*ADDR_SZ, "typelink addr",0) + idc.set_cmt(self.start_addr + 45*ADDR_SZ, "types count",0) + idc.set_cmt(self.start_addr + 46*ADDR_SZ, "types table capacity",0) + idc.set_cmt(self.start_addr + 47*ADDR_SZ, "itabslink addr",0) + idc.set_cmt(self.start_addr + 48*ADDR_SZ, "itabs count",0) + idc.set_cmt(self.start_addr + 49*ADDR_SZ, "itabs caapacity",0) + idc.set_cmt(self.start_addr + 50*ADDR_SZ, "ptab addr",0) + idc.set_cmt(self.start_addr + 51*ADDR_SZ, "ptab count",0) + idc.set_cmt(self.start_addr + 52*ADDR_SZ, "ptab capacity",0) + idc.set_cmt(self.start_addr + 53*ADDR_SZ, "plugin path addr",0) + idc.set_cmt(self.start_addr + 54*ADDR_SZ, "plugin path length",0) + idc.set_cmt(self.start_addr + 55*ADDR_SZ, "module name addr",0) + idc.set_cmt(self.start_addr + 56*ADDR_SZ, "module name length",0) + idc.set_cmt(self.start_addr + 63*ADDR_SZ, "hasmain flag",0) + idc.set_cmt(self.start_addr + 69*ADDR_SZ+1, "next moduledata addr",0) + + idaapi.auto_wait() + + idc.create_strlit(modulename_addr, modulename_addr+modulename_len) + idaapi.auto_wait() + idc.create_strlit(pluginpath_addr, pluginpath_addr+pluginpath_len) - idaapi.auto_wait() \ No newline at end of file + idaapi.auto_wait() diff --git a/pclntbl.py b/pclntbl.py index 3e7747d..5b352c1 100644 --- a/pclntbl.py +++ b/pclntbl.py @@ -122,7 +122,8 @@ def parse_hdr(self): ''' if self.magic_number == common.MAGIC_112 \ or self.magic_number == common.MAGIC_116 \ - or self.magic_number == common.MAGIC_118: + or self.magic_number == common.MAGIC_118 \ + or self.magic_number == common.MAGIC_120: common._info(f"Magic Number: {self.magic_number:#x}") else: common._error("Invalid pclntbl header magic number!") @@ -194,7 +195,7 @@ def parse_hdr(self): idc.set_cmt(self.start_addr + 8 + 6*self.ptr_sz, f"func table offset, real addr: {self.func_tbl_addr:#x}", 0) idc.set_name(self.func_tbl_addr, "pc0", flags=idaapi.SN_FORCE) idaapi.auto_wait() - elif self.magic_number == common.MAGIC_118: + elif self.magic_number == common.MAGIC_118 or self.magic_number == common.MAGIC_120: self.srcfile_num = common.read_mem(self.start_addr + 8 + self.ptr_sz, forced_addr_sz=self.ptr_sz) idc.set_cmt(self.start_addr + 8 + self.ptr_sz, "srcfile count number", 0) common._info(f"Total srcfile number: {self.srcfile_num:#x}") @@ -289,8 +290,10 @@ def parse_funcs_118(self): refer: https://go.dev/src/runtime/symtab.go - moduledata.pclntbl_addr == moduledata.ftab_addr == pcheader.pclntbl_addr == (pcheader.start_addr + pclntbl_off) + moduledata.pclntbl_addr == moduledata.ftab_addr == pcheader.pclntbl_addr == \ + (pcheader.start_addr + pclntbl_off) moduledata.ftab: []functab + type functab struct { entryoff uint32 // relative to runtime.text funcoff uint32 // relative to pclntbl_addr @@ -401,7 +404,7 @@ def parse(self): self.parse_funcs_112() elif self.magic_number == common.MAGIC_116: self.parse_funcs_116() - elif self.magic_number == common.MAGIC_118: + elif self.magic_number == common.MAGIC_118 or self.magic_number == common.MAGIC_120: self.parse_funcs_118() idaapi.auto_wait() @@ -410,7 +413,7 @@ def parse(self): if self.magic_number == common.MAGIC_112: self.parse_srcfile_112() - elif self.magic_number == common.MAGIC_116 or self.magic_number == common.MAGIC_118: + elif self.magic_number == common.MAGIC_116 or self.magic_number == common.MAGIC_118 or self.magic_number == common.MAGIC_120: self.parse_srcfile_latest() @@ -473,6 +476,47 @@ class FuncStruct(): nfuncdata uint8 // must be last, must end on a uint32-aligned boundary } + type _func struct { // Go 1.20 + entryOff uint32 // start pc, as offset from moduledata.text/pcHeader.textStart + nameOff int32 // function name, as index into moduledata.funcnametab. + + args int32 // in/out args size + deferreturn uint32 // offset of start of a deferreturn call instruction from entry, if any. + + pcsp uint32 + pcfile uint32 + pcln uint32 + npcdata uint32 + cuOffset uint32 // runtime.cutab offset of this function's CU + startLine int32 // line number of start of function (func keyword/TEXT directive) + funcID funcID // set for certain special runtime functions + flag funcFlag + _ [1]byte // pad + nfuncdata uint8 // must be last, must end on a uint32-aligned boundary + + // The end of the struct is followed immediately by two variable-length + // arrays that reference the pcdata and funcdata locations for this + // function. + + // pcdata contains the offset into moduledata.pctab for the start of + // that index's table. e.g., + // &moduledata.pctab[_func.pcdata[_PCDATA_UnsafePoint]] is the start of + // the unsafe point table. + // + // An offset of 0 indicates that there is no table. + // + // pcdata [npcdata]uint32 + + // funcdata contains the offset past moduledata.gofunc which contains a + // pointer to that index's funcdata. e.g., + // *(moduledata.gofunc + _func.funcdata[_FUNCDATA_ArgsPointerMaps]) is + // the argument pointer map. + // + // An offset of ^uint32(0) indicates that there is no entry. + // + // funcdata [nfuncdata]uint32 + } + // A FuncID identifies particular functions that need to be treated // specially by the runtime. // Note that in some situations involving plugins, there may be multiple @@ -543,6 +587,7 @@ def __init__(self, addr, pclntbl): self.nfuncdata = 0 self.npcdata = 0 self.deferreturn = 0 + self.startline = 0 self.func_id = -1 self.func_flag = -1 self.func_type = "normal" #Default type @@ -558,7 +603,7 @@ def parse(self, is_test=False): name_addr = common.read_mem(self.addr + self.pclntbl.ptr_sz, forced_addr_sz=4, read_only=is_test) \ + self.pclntbl.funcnametab_addr - elif self.pclntbl.magic_number == common.MAGIC_118: + elif self.pclntbl.magic_number == common.MAGIC_118 or self.pclntbl.magic_number == common.MAGIC_120: func_entry_off = common.read_mem(self.addr, forced_addr_sz=4, read_only=is_test) func_addr = self.pclntbl.text_sect_addr + func_entry_off @@ -638,7 +683,26 @@ def parse(self, is_test=False): try: self.func_type = FUNC_TYPES[self.func_id] except Exception as e: - common._debug(f"Invalid funcID. Curr func entry: {real_func_addr.start_ea:#x}, func st addr: {self.addr:#x}, func id: {self.func_id:#x}") + common._debug(f"Invalid funcID. Curr func entry: {real_func_addr.start_ea:#x}, \ + func st addr: {self.addr:#x}, func id: {self.func_id:#x}") + elif self.pclntbl.magic_number == common.MAGIC_120: + self.args = common.read_mem(self.addr + 2*4, forced_addr_sz=4, read_only=is_test) + self.deferreturn = common.read_mem(self.addr + 3*4, forced_addr_sz=4, read_only=is_test) + self.pcsp = common.read_mem(self.addr + 4*4, forced_addr_sz=4, read_only=is_test) + self.pcfile = common.read_mem(self.addr + 5*4, forced_addr_sz=4, read_only=is_test) + self.pcln = common.read_mem(self.addr + 6*4, forced_addr_sz=4, read_only=is_test) + self.npcdata = common.read_mem(self.addr + 7*4, forced_addr_sz=4, read_only=is_test) + self.cuOffset = common.read_mem(self.addr + 8*4, forced_addr_sz=4, read_only=is_test) + self.startline = common.read_mem(self.addr + 9*4, forced_addr_sz=4, read_only=is_test) + self.func_id = idc.get_wide_byte(self.addr + 10*4) & 0xFF + self.func_flag = idc.get_wide_byte(self.addr + 10*4 + 1) & 0xFF + self.nfuncdata = idc.get_wide_byte(self.addr + 10*4 + 3) & 0xFF + + try: + self.func_type = FUNC_TYPES[self.func_id] + except Exception as e: + common._debug(f"Invalid funcID. Curr func entry: {real_func_addr.start_ea:#x}, \ + func st addr: {self.addr:#x}, func id: {self.func_id:#x}") if is_test: return @@ -661,16 +725,28 @@ def parse(self, is_test=False): idc.set_cmt(self.addr + self.pclntbl.ptr_sz + 8*4, f"func_type: {self.func_type}", 0) idc.set_cmt(self.addr + self.pclntbl.ptr_sz + 8*4 + 3, "nfuncdata", 0) elif self.pclntbl.magic_number == common.MAGIC_118: - idc.set_cmt(self.addr + self.pclntbl.ptr_sz + 4, "args", 0) - idc.set_cmt(self.addr + self.pclntbl.ptr_sz + 2*4, "deferreturn", 0) - idc.set_cmt(self.addr + self.pclntbl.ptr_sz + 3*4, "pcsp", 0) - idc.set_cmt(self.addr + self.pclntbl.ptr_sz + 4*4, "pcfile", 0) - idc.set_cmt(self.addr + self.pclntbl.ptr_sz + 5*4, "pcln", 0) - idc.set_cmt(self.addr + self.pclntbl.ptr_sz + 6*4, "npcdata", 0) - idc.set_cmt(self.addr + self.pclntbl.ptr_sz + 7*4, "cuOffset", 0) - idc.set_cmt(self.addr + self.pclntbl.ptr_sz + 8*4, f"func_type: {self.func_type}", 0) - idc.set_cmt(self.addr + self.pclntbl.ptr_sz + 8*4 + 1, "func_flag", 0) - idc.set_cmt(self.addr + self.pclntbl.ptr_sz + 8*4 + 3, "nfuncdata", 0) + idc.set_cmt(self.addr + 2*4, "args", 0) + idc.set_cmt(self.addr + 3*4, "deferreturn", 0) + idc.set_cmt(self.addr + 4*4, "pcsp", 0) + idc.set_cmt(self.addr + 5*4, "pcfile", 0) + idc.set_cmt(self.addr + 6*4, "pcln", 0) + idc.set_cmt(self.addr + 7*4, "npcdata", 0) + idc.set_cmt(self.addr + 8*4, "cuOffset", 0) + idc.set_cmt(self.addr + 9*4, f"func_type: {self.func_type}", 0) + idc.set_cmt(self.addr + 9*4 + 1, "func_flag", 0) + idc.set_cmt(self.addr + 9*4 + 3, "nfuncdata", 0) + elif self.pclntbl.magic_number == common.MAGIC_120: + idc.set_cmt(self.addr + 2*4, "args", 0) + idc.set_cmt(self.addr + 3*4, "deferreturn", 0) + idc.set_cmt(self.addr + 4*4, "pcsp", 0) + idc.set_cmt(self.addr + 5*4, "pcfile", 0) + idc.set_cmt(self.addr + 6*4, "pcln", 0) + idc.set_cmt(self.addr + 7*4, "npcdata", 0) + idc.set_cmt(self.addr + 8*4, "cuOffset", 0) + idc.set_cmt(self.addr + 9*4, "startline", 0) + idc.set_cmt(self.addr + 10*4, f"func_type: {self.func_type}", 0) + idc.set_cmt(self.addr + 10*4 + 1, "func_flag", 0) + idc.set_cmt(self.addr + 10*4 + 3, "nfuncdata", 0) idaapi.auto_wait()