From fffb1b4af77dc9c1863d01731167a16f6006ea56 Mon Sep 17 00:00:00 2001 From: Manuel Blatt Date: Tue, 21 May 2024 17:55:29 +0200 Subject: [PATCH] add type names to struct defs and detect complex strings --- decompiler/backend/cexpressiongenerator.py | 42 ++++++++++++++++++++++ decompiler/backend/variabledeclarations.py | 12 +++++-- 2 files changed, 52 insertions(+), 2 deletions(-) diff --git a/decompiler/backend/cexpressiongenerator.py b/decompiler/backend/cexpressiongenerator.py index 77cfbe77e..5496f69d4 100644 --- a/decompiler/backend/cexpressiongenerator.py +++ b/decompiler/backend/cexpressiongenerator.py @@ -15,6 +15,7 @@ ) from decompiler.structures.pseudo import instructions as instructions from decompiler.structures.pseudo import operations as operations +from decompiler.structures.pseudo.complextypes import Struct from decompiler.structures.pseudo.operations import MemberAccess from decompiler.structures.visitors.interfaces import DataflowObjectVisitorInterface from decompiler.util.integer_util import normalize_int @@ -22,6 +23,42 @@ MAX_GLOBAL_INIT_LENGTH = 128 +def get_complex_string_struct_address_offset(vartype) -> str | None: + if not isinstance(vartype, Struct): + return None + if len(vartype.members) != 2: + return None + address_offset = None + length_offset = None + for offset, member in vartype.members.items(): + match member.type: + case Pointer(type=Integer(size=8)): + address_offset = offset + case Integer(): + length_offset = offset + case _: + return None + if address_offset is None or length_offset is None: + return None + return address_offset + + +INLINE_COMPLEX_STRINGS = False +DETECT_COMPLEX_STRINGS = True + + +def is_complex_string_struct(vartype) -> bool: + if not DETECT_COMPLEX_STRINGS: + return False + return get_complex_string_struct_address_offset(vartype) is not None + + +def get_data_of_complex_string_struct(variable) -> str: + address_offset = get_complex_string_struct_address_offset(variable.type) + address = variable.initial_value.value[address_offset] + return address + + def inline_global_variable(var) -> bool: if not var.is_constant: return False @@ -29,6 +66,9 @@ def inline_global_variable(var) -> bool: case ArrayType(): if var.type.type in [Integer.char(), CustomType.wchar16(), CustomType.wchar32()]: return True + case Struct(): + if INLINE_COMPLEX_STRINGS and is_complex_string_struct(var.type): + return True case _: return False return False @@ -212,6 +252,8 @@ def visit_variable(self, expr: expressions.Variable) -> str: def visit_global_variable(self, expr: expressions.GlobalVariable): """Inline a global variable if its initial value is constant and not of void type""" if inline_global_variable(expr): + if is_complex_string_struct(expr.type): + return self.visit(get_data_of_complex_string_struct(expr)) return self.visit(expr.initial_value) return expr.name diff --git a/decompiler/backend/variabledeclarations.py b/decompiler/backend/variabledeclarations.py index 7b2d8926b..efd08a37d 100644 --- a/decompiler/backend/variabledeclarations.py +++ b/decompiler/backend/variabledeclarations.py @@ -3,7 +3,12 @@ from collections import defaultdict from typing import Iterable, Iterator, List -from decompiler.backend.cexpressiongenerator import CExpressionGenerator, inline_global_variable +from decompiler.backend.cexpressiongenerator import ( + CExpressionGenerator, + get_data_of_complex_string_struct, + inline_global_variable, + is_complex_string_struct, +) from decompiler.structures.ast.syntaxtree import AbstractSyntaxTree from decompiler.structures.pseudo import GlobalVariable, Integer, Variable from decompiler.structures.pseudo.complextypes import Struct @@ -69,7 +74,10 @@ def _generate_definitions(global_variables: set[GlobalVariable]) -> Iterator[str br, bl = "{", "}" yield f"{base}{variable.type.type} {variable.name}[{hex(variable.type.elements)}] = {br}{CExpressionGenerator().visit(variable.initial_value)}{bl};" case Struct(): - string = f"struct {variable.name}" + "{\n" + if is_complex_string_struct(variable.type): + yield base + f"struct {variable.type.name} {variable.name} = {CExpressionGenerator().visit(get_data_of_complex_string_struct(variable))};" + continue + string = f"struct {variable.type.name} {variable.name}" + "{\n" for m_type, m_value in zip(variable.type.members.values(), variable.initial_value.value.values()): value = CExpressionGenerator().visit(m_value) string += f"\t.{m_type.name} = {value};\n"