опять кууууча всего:
базово доделаны терминалки до более менее итогового состояния
This commit is contained in:
@@ -1,12 +1,14 @@
|
||||
# pyinstaller --onefile --distpath ./parse_xml --workpath ./build --specpath ./build parse_xml/Src/parse_xml.py
|
||||
# python -m nuitka --standalone --onefile --output-dir=./build parse_xml/Src/parse_xml.py
|
||||
# pyinstaller --onefile --distpath ./parse_xml --workpath ./parse_xml/build --specpath ./build parse_xml/Src/parse_xml.py
|
||||
# python -m nuitka --standalone --onefile --output-dir=./parse_xml parse_xml/Src/parse_xml.py
|
||||
import xml.etree.ElementTree as ET
|
||||
import xml.dom.minidom
|
||||
import sys
|
||||
import os
|
||||
|
||||
|
||||
|
||||
if len(sys.argv) < 3:
|
||||
print("Usage: python simplify_dwarf.py <input.xml> <info.txt> [output.xml]")
|
||||
print("Usage: python parse_xml.exe <input.xml> <info.txt> [output.xml]")
|
||||
sys.exit(1)
|
||||
|
||||
input_path = sys.argv[1]
|
||||
@@ -159,75 +161,6 @@ def parse_offset(offset_text):
|
||||
|
||||
|
||||
|
||||
def get_array_dimensions(array_die):
|
||||
"""
|
||||
Собрать размеры всех измерений массива.
|
||||
Возвращает список размеров [dim0, dim1, ...] во внешне-внутреннем порядке.
|
||||
"""
|
||||
dims = []
|
||||
|
||||
# Ищем DW_TAG_subrange_type — для каждого измерения
|
||||
for child in array_die.findall("die"):
|
||||
if child.findtext("tag") != "DW_TAG_subrange_type":
|
||||
continue
|
||||
|
||||
dim_size = None
|
||||
|
||||
# Попытка получить upper_bound
|
||||
ub_attr = get_attr(child, "DW_AT_upper_bound")
|
||||
if ub_attr is not None:
|
||||
val = ub_attr.find("value/const")
|
||||
if val is not None:
|
||||
try:
|
||||
# В DWARF верхняя граница включительно, значит размер = upper_bound + 1
|
||||
dim_size = int(val.text, 0) + 1
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
# Если не получилось — попытаться из count
|
||||
if dim_size is None:
|
||||
ct_attr = get_attr(child, "DW_AT_count")
|
||||
if ct_attr is not None:
|
||||
val = ct_attr.find("value/const")
|
||||
if val is not None:
|
||||
try:
|
||||
dim_size = int(val.text, 0)
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
# Если ничего не найдено — ставим 0
|
||||
if dim_size is None:
|
||||
dim_size = 0
|
||||
|
||||
dims.append(dim_size)
|
||||
|
||||
# Если subrange не нашли (например, в случае typedef), попробуем через размер типа
|
||||
if not dims:
|
||||
arr_size = get_die_size(array_die)
|
||||
elem_size = None
|
||||
element_type_ref = get_attr(array_die, "DW_AT_type")
|
||||
if element_type_ref is not None and element_type_ref.find("ref") is not None:
|
||||
element_type_id = element_type_ref.find("ref").attrib.get("idref")
|
||||
elem_die = resolve_type_die(element_type_id)
|
||||
if elem_die is not None:
|
||||
elem_size = get_die_size(elem_die)
|
||||
|
||||
if arr_size is not None and elem_size:
|
||||
dims.append(arr_size // elem_size)
|
||||
else:
|
||||
dims.append(0)
|
||||
|
||||
# Рекурсия — если элементный тип массива тоже массив, добавляем размеры вложенного
|
||||
element_type_ref = get_attr(array_die, "DW_AT_type")
|
||||
if element_type_ref is not None and element_type_ref.find("ref") is not None:
|
||||
element_type_id = element_type_ref.find("ref").attrib.get("idref")
|
||||
element_type_die = resolve_type_die(element_type_id)
|
||||
if element_type_die is not None and element_type_die.findtext("tag") == "DW_TAG_array_type":
|
||||
dims.extend(get_array_dimensions(element_type_die))
|
||||
|
||||
return dims
|
||||
|
||||
|
||||
def get_base_type_die(array_die):
|
||||
"""Спускаемся по цепочке DW_AT_type, пока не дойдем до не-массива (базового типа)."""
|
||||
current_die = array_die
|
||||
@@ -244,11 +177,98 @@ def get_base_type_die(array_die):
|
||||
return next_die
|
||||
return current_die
|
||||
|
||||
def get_array_dimensions(array_die):
|
||||
dims = []
|
||||
# Итерируем по всем DIE с тегом DW_TAG_subrange_type, потомки текущего массива
|
||||
for child in array_die.findall("die"):
|
||||
if child.findtext("tag") != "DW_TAG_subrange_type":
|
||||
continue
|
||||
|
||||
dim_size = None
|
||||
ub_attr = get_attr(child, "DW_AT_upper_bound")
|
||||
if ub_attr is not None:
|
||||
# Попробуем разные варианты получить значение upper_bound
|
||||
# 1) value/const
|
||||
val_const = ub_attr.find("const")
|
||||
if val_const is not None:
|
||||
try:
|
||||
dim_size = int(val_const.text, 0) + 1
|
||||
#print(f"[DEBUG] Found DW_AT_upper_bound const: {val_const.text}, size={dim_size}")
|
||||
except Exception as e:
|
||||
a=1#print(f"[WARN] Error parsing upper_bound const: {e}")
|
||||
else:
|
||||
# 2) value/block (DW_OP_constu / DW_OP_plus_uconst, etc.)
|
||||
val_block = ub_attr.find("block")
|
||||
if val_block is not None:
|
||||
block_text = val_block.text
|
||||
# Можно попытаться парсить DWARF expr (например DW_OP_plus_uconst 7)
|
||||
if block_text and "DW_OP_plus_uconst" in block_text:
|
||||
try:
|
||||
parts = block_text.split()
|
||||
val = int(parts[-1], 0)
|
||||
dim_size = val + 1
|
||||
#print(f"[DEBUG] Parsed upper_bound block: {val} + 1 = {dim_size}")
|
||||
except Exception as e:
|
||||
a=1#print(f"[WARN] Error parsing upper_bound block: {e}")
|
||||
else:
|
||||
a=1#print(f"[WARN] Unexpected DW_AT_upper_bound block content: {block_text}")
|
||||
else:
|
||||
a=1#print(f"[WARN] DW_AT_upper_bound has no const or block value")
|
||||
|
||||
if dim_size is None:
|
||||
# fallback по DW_AT_count — редко встречается
|
||||
ct_attr = get_attr(child, "DW_AT_count")
|
||||
if ct_attr is not None:
|
||||
val_const = ct_attr.find("value/const")
|
||||
if val_const is not None:
|
||||
try:
|
||||
dim_size = int(val_const.text, 0)
|
||||
#print(f"[DEBUG] Found DW_AT_count: {dim_size}")
|
||||
except Exception as e:
|
||||
a=1#print(f"[WARN] Error parsing DW_AT_count const: {e}")
|
||||
|
||||
if dim_size is None:
|
||||
print("[DEBUG] No dimension size found for this subrange, defaulting to 0")
|
||||
dim_size = 0
|
||||
|
||||
dims.append(dim_size)
|
||||
|
||||
# Если не нашли измерений — пытаемся вычислить размер массива по общему размеру
|
||||
if not dims:
|
||||
arr_size = get_die_size(array_die)
|
||||
elem_size = None
|
||||
element_type_ref = get_attr(array_die, "DW_AT_type")
|
||||
if element_type_ref is not None and element_type_ref.find("ref") is not None:
|
||||
element_type_id = element_type_ref.find("ref").attrib.get("idref")
|
||||
elem_die = resolve_type_die(element_type_id)
|
||||
if elem_die is not None:
|
||||
elem_size = get_die_size(elem_die)
|
||||
#print(f"[DEBUG] Fallback: arr_size={arr_size}, elem_size={elem_size}")
|
||||
|
||||
if arr_size is not None and elem_size:
|
||||
dim_calc = arr_size // elem_size
|
||||
dims.append(dim_calc)
|
||||
#print(f"[DEBUG] Calculated dimension size from total size: {dim_calc}")
|
||||
else:
|
||||
dims.append(0)
|
||||
print("[DEBUG] Could not calculate dimension size, set 0")
|
||||
|
||||
# Рекурсивно обрабатываем вложенные массивы
|
||||
element_type_ref = get_attr(array_die, "DW_AT_type")
|
||||
if element_type_ref is not None and element_type_ref.find("ref") is not None:
|
||||
element_type_id = element_type_ref.find("ref").attrib.get("idref")
|
||||
element_type_die = resolve_type_die(element_type_id)
|
||||
if element_type_die is not None and element_type_die.findtext("tag") == "DW_TAG_array_type":
|
||||
dims.extend(get_array_dimensions(element_type_die))
|
||||
|
||||
#print(f"[DEBUG] Array dimensions: {dims}")
|
||||
return dims
|
||||
|
||||
|
||||
|
||||
def handle_array_type(member_elem, resolved_type, offset=0):
|
||||
dims = get_array_dimensions(resolved_type)
|
||||
|
||||
# Определяем базовый тип (не массив)
|
||||
base_die = get_base_type_die(resolved_type)
|
||||
base_name = "unknown"
|
||||
base_size = None
|
||||
@@ -259,10 +279,10 @@ def handle_array_type(member_elem, resolved_type, offset=0):
|
||||
base_size = get_die_size(base_die)
|
||||
else:
|
||||
base_name = get_type_name(base_die.attrib.get("id", ""))
|
||||
#print(f"[DEBUG] Base type name: {base_name}, base size: {base_size}")
|
||||
|
||||
member_elem.set("type", base_name + "[]" * len(dims))
|
||||
|
||||
# Вычисляем общий размер массива — произведение размеров * размер базового элемента
|
||||
if base_size is None:
|
||||
base_size = 0
|
||||
|
||||
@@ -270,31 +290,34 @@ def handle_array_type(member_elem, resolved_type, offset=0):
|
||||
for d in dims:
|
||||
if d == 0:
|
||||
total_elements = 0
|
||||
print(f"[WARN] Dimension size is zero, setting total elements to 0")
|
||||
break
|
||||
total_elements *= d
|
||||
|
||||
total_size = total_elements * base_size if base_size is not None else 0
|
||||
if total_size:
|
||||
member_elem.set("size", str(total_size))
|
||||
member_elem.set("size", str(base_size if base_size is not None else 1))
|
||||
else:
|
||||
# fallback: если не удалось, можно попробовать get_die_size
|
||||
arr_size = get_die_size(resolved_type)
|
||||
if arr_size:
|
||||
member_elem.set("size", str(arr_size))
|
||||
#print(f"[DEBUG] Used fallback size from resolved_type: {arr_size}")
|
||||
else:
|
||||
print(f"[WARN] Could not determine total size for array")
|
||||
|
||||
# Записываем размеры измерений size1, size2 ...
|
||||
for i, dim in enumerate(dims, 1):
|
||||
member_elem.set(f"size{i}", str(dim))
|
||||
#print(f"[DEBUG] Setting size{i} = {dim}")
|
||||
|
||||
member_elem.set("kind", "array")
|
||||
|
||||
# Если элемент базового типа — структура, разворачиваем её поля
|
||||
if base_die is not None and base_die.findtext("tag") == "DW_TAG_structure_type":
|
||||
add_members_recursive(member_elem, base_die, offset)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
def add_members_recursive(parent_elem, struct_die, base_offset=0):
|
||||
is_union = struct_die.findtext("tag") == "DW_TAG_union_type"
|
||||
size = get_die_size(struct_die)
|
||||
@@ -330,6 +353,20 @@ def add_members_recursive(parent_elem, struct_die, base_offset=0):
|
||||
elif tag in ("DW_TAG_structure_type", "DW_TAG_union_type"):
|
||||
member_elem.set("type", type_name)
|
||||
add_members_recursive(member_elem, resolved_type, offset)
|
||||
elif tag == "DW_TAG_pointer_type":
|
||||
# Проверяем тип, на который указывает указатель
|
||||
pointee_ref = get_attr(resolved_type, "DW_AT_type")
|
||||
if pointee_ref is not None and pointee_ref.find("ref") is not None:
|
||||
pointee_id = pointee_ref.find("ref").attrib.get("idref")
|
||||
pointee_die = resolve_type_die(pointee_id)
|
||||
if pointee_die is not None:
|
||||
pointee_tag = pointee_die.findtext("tag")
|
||||
if pointee_tag in ("DW_TAG_structure_type", "DW_TAG_union_type"):
|
||||
# Добавляем подэлементы для структуры, на которую указывает указатель
|
||||
pointer_elem = ET.SubElement(member_elem, "pointee", type=get_type_name(pointee_id))
|
||||
add_members_recursive(pointer_elem, pointee_die, 0)
|
||||
|
||||
|
||||
|
||||
output_root = ET.Element("variables")
|
||||
for die in root.iter("die"):
|
||||
|
||||
Binary file not shown.
Reference in New Issue
Block a user