Skip to content

Commit 41a8469

Browse files
committed
fixed 'enum' corner case in type resolution
1 parent 223298c commit 41a8469

File tree

1 file changed

+28
-9
lines changed

1 file changed

+28
-9
lines changed

prd_multidecomp_ida.py

Lines changed: 28 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -803,9 +803,10 @@ def resolve_type_order(self, structDump,output):
803803
rtypefh.close()
804804
return structDump,recovered_types,needs_stdio
805805

806-
def update_params_for_forward_decls(self,line,forward_decls):
806+
def update_params_for_typeclass(self,line,forward_decls,enum_decls):
807807
isfnptr,fnrettype,fnptrname,fnptrparams,fnptr_no_params=is_function_ptr(line)
808808
fwddecls_used=list()
809+
enumdecls_used=list()
809810
if isfnptr:
810811
params_=[fnptrparams.strip()]
811812
if ',' in fnptrparams:
@@ -815,17 +816,25 @@ def update_params_for_forward_decls(self,line,forward_decls):
815816
p=p.strip()
816817
xt=get_basetype_info(p)
817818
xlu=forward_decls.get(xt,None)
819+
xlu_enum=enum_decls.get(xt,None)
818820
if xlu is not None:
819821
if xt not in fwddecls_used:
820822
fwddecls_used.append(xt)
821823
if not p.startswith('const '):
822824
params_[i]=f"struct {p}"
823825
else:
824826
params_[i]=f"const struct {p[len('const '):]}"
827+
elif xlu_enum is not None:
828+
if xt not in enumdecls_used:
829+
enumdecls_used.append(xt)
830+
if not p.startswith('const '):
831+
params_[i]=f"enum {p}"
832+
else:
833+
params_[i]=f"const enum {p[len('const '):]}"
825834
new_params=",".join(params_)
826-
return True,new_params,fnptr_no_params,fwddecls_used
835+
return True,new_params,fnptr_no_params,fwddecls_used,enumdecls_used
827836

828-
return False,None,None,fwddecls_used
837+
return False,None,None,fwddecls_used,enumdecls_used
829838

830839
def typedef_resolution(self,structDump):
831840
type_lines=structDump.splitlines()
@@ -1068,7 +1077,7 @@ def typedef_resolution(self,structDump):
10681077
# should be on correct prefix
10691078
if(not ref_line.startswith("typedef "+valid_prefix)):
10701079
ref_line=re.sub(r"\btypedef\b",f"typedef {valid_prefix}",ref_line)
1071-
dprint(f"ALIAS UPDATE: Updating line to {ref_line}")
1080+
dprint(f"ALIAS UPDATE: Updating line to '{ref_line}'")
10721081

10731082
type_to_dependencies[als]['line']=ref_line
10741083

@@ -1142,7 +1151,7 @@ def typedef_resolution(self,structDump):
11421151
# this loop allows to preprocess the types and their requirements to:
11431152
# 1) get rid of extraction issues or "..." i.e., weird type results
11441153
# 2) identify missing type definitions to prevent accumulating errors
1145-
# 3) transform type definition lines to use the 'struct' or 'union' keyword as appropriate
1154+
# 3) transform type definition lines to use the 'enum', 'struct', or 'union' keywords as appropriate
11461155
# which allows for forward declaration use in the case of circular references in type definitions
11471156
# => i.e., when another struct or a function pointer has a field that's a struct/union
11481157
# without 'struct|union' keyword, prepend it to the field
@@ -1152,6 +1161,7 @@ def typedef_resolution(self,structDump):
11521161
reqs=type_to_dependencies[i]['reqs']
11531162

11541163
fdecls=[d in fwd_decl_types for d in reqs]
1164+
enumdecls=[d in enum_types for d in reqs]
11551165
not_defined=[]
11561166
for idx,d in enumerate(copy.copy(reqs)):
11571167
# Reason #1
@@ -1165,7 +1175,7 @@ def typedef_resolution(self,structDump):
11651175
print(f"RUH-ROH, we have at least one undefined type => {not_defined} for '{i}'");
11661176
missing_type_defs.extend(not_defined)
11671177
missing_type_defs.append(i)
1168-
if any(fdecls):
1178+
if any(fdecls) or any(enumdecls):
11691179
if i in collective_types:
11701180
# Reason #3a - function pointers
11711181
mtch=re.match(r"^\s*(typedef)\s+((struct|union)(\s+__attribute__\(\(.*\)\))?)\s+(\S+)\s*(\{\s*(.*)\s*\}\s*)(\S+)\s*;\s*$",line)
@@ -1178,13 +1188,20 @@ def typedef_resolution(self,structDump):
11781188
reqs_=set()
11791189
x_fields=fields.split(';')
11801190
for idx,xf in enumerate(x_fields):
1181-
changeit,newparams,fn_noparams,used_fwddecls=self.update_params_for_forward_decls(xf,forward_decls)
1191+
_ret=self.update_params_for_typeclass(xf,forward_decls,enum_decls)
1192+
changeit,newparams,fn_noparams,used_fwddecls,used_enumdecls=_ret
11821193
if changeit:
11831194
line=f"{fn_noparams}({newparams});"
11841195
x_fields[idx]=line
11851196
else:
11861197
xt=get_basetype_info(xf)
1187-
if xt in fwd_decl_types:
1198+
if xt in enum_types:
1199+
print(f"Found 'enum' type: {xt}")
1200+
if x_fields[idx].startswith('const '):
1201+
x_fields[idx]=f"const enum {x_fields[idx][len('const '):]}"
1202+
else:
1203+
x_fields[idx]=f"enum {x_fields[idx]}"
1204+
elif xt in fwd_decl_types:
11881205
if type_to_dependencies.get(xt,None) is not None:
11891206
ttype=type_to_dependencies[xt]['storage']
11901207
tname=type_to_dependencies[xt]['defname']
@@ -1201,7 +1218,8 @@ def typedef_resolution(self,structDump):
12011218
elif i in fnptr_types:
12021219
# Reason #3b - function pointers
12031220
mtch=re.match(r"^\s*(typedef)\s+((\w+(\s+\w+)*)\s+(\(\s*\*\s*(\w+)\))\s*(\((.*)\)))\s*;\s*$",line);
1204-
changeit,newparams,fn_noparams,used_fwddecls=self.update_params_for_forward_decls(mtch.group(2),forward_decls)
1221+
_ret=self.update_params_for_typeclass(mtch.group(2),forward_decls,enum_decls)
1222+
changeit,newparams,fn_noparams,used_fwddecls,used_enumdecls=_ret
12051223
if changeit:
12061224
line=f"{mtch.group(1)} {fn_noparams}({newparams});"
12071225
type_to_dependencies[i]['line']=line
@@ -1210,6 +1228,7 @@ def typedef_resolution(self,structDump):
12101228
line=type_to_dependencies[i]['line']
12111229
if i in list(fwd_decl_types) and forward_decls.get(i,None) is None:
12121230
dprint(f"INVESTIGATE THIS: {i} in fwd_decl_types, but not in forward_decls.keys()")
1231+
# 'struct' or 'union'
12131232
if forward_decls.get(i,None) is not None:
12141233
ref_line=forward_decls[i]['line'].strip()
12151234
for prefix in ['struct ','union ']:

0 commit comments

Comments
 (0)