#!/usr/bin/env python3 # -*- coding: utf-8 -*- """ Пятый проход КВС — генерация и добавление таблицы секций в CSV Сканирует CSV, собирает информацию о секциях, обновляет ELF-заголовок ПЕРЕСОЗДАЁТ ПРОГРАММНЫЕ ЗАГОЛОВКИ на основе реальных размеров секций и добавляет таблицу секций в конец файла ДОБАВЛЕНА НУЛЕВАЯ СЕКЦИЯ (индекс 0) ДОБАВЛЕНА СЕКЦИЯ .comment со строкой "Сборщик КВС" РАЗМЕЩЕНИЕ СЕКЦИЙ КАК В kvs_8.py ПРАВИЛЬНЫЕ ИНДЕКСЫ В .shstrtab (с учётом наличия .bss) """ import sys import csv import struct PAGE_SIZE = 0x1000 ELF_BASE_VADDR = 0x400000 DEBUG_PRINTS = True def align_up(value, alignment): """Выравнивание вверх""" return ((value + alignment - 1) // alignment) * alignment def analyze_csv(csv_file): """Анализирует CSV и собирает информацию о секциях""" sections = { '.text': {'start': None, 'end': None, 'size': 0, 'virt_start': None, 'virt_end': None}, '.data': {'start': None, 'end': None, 'size': 0, 'virt_start': None, 'virt_end': None}, } bss_blocks = [] max_addr = 0 with open(csv_file, 'r', encoding='utf-8') as f: reader = csv.DictReader(f, delimiter=';') for row in reader: seg = row['сегмент'] addr_str = row['адрес'] virt_addr_str = row['виртуальный_адрес'] label = row['приводящая_метка'] source = row['исходная_команда'] if not seg: continue # Обновляем максимальный файловый адрес (только числовые адреса) if addr_str and addr_str != 'BSS' and addr_str != '': try: addr = int(addr_str, 16) if addr > max_addr: max_addr = addr except: pass # BSS секция (одна запись на блок) if seg == '.bss': if source and source.startswith('.резб'): # Формат: ".резб 1048576" parts = source.split() if len(parts) >= 2: size = int(parts[1]) virt_start = int(virt_addr_str, 16) if virt_addr_str else 0 bss_blocks.append({ 'virt_start': virt_start, 'size': size, 'label': label, 'source': source }) continue # Обычные секции if addr_str == 'BSS' or addr_str == '': continue try: addr = int(addr_str, 16) virt_addr = int(virt_addr_str, 16) except: continue if seg == '.text': if sections['.text']['start'] is None: sections['.text']['start'] = addr sections['.text']['virt_start'] = virt_addr sections['.text']['end'] = addr sections['.text']['virt_end'] = virt_addr sections['.text']['size'] += 1 elif seg == '.data': if sections['.data']['start'] is None: sections['.data']['start'] = addr sections['.data']['virt_start'] = virt_addr sections['.data']['end'] = addr sections['.data']['virt_end'] = virt_addr sections['.data']['size'] += 1 # Пересчёт размеров секций из адресов if sections['.text']['start'] and sections['.text']['end']: sections['.text']['size'] = sections['.text']['end'] - sections['.text']['start'] + 1 if sections['.data']['start'] and sections['.data']['end']: sections['.data']['size'] = sections['.data']['end'] - sections['.data']['start'] + 1 # Вычисляем общий размер BSS и начальный виртуальный адрес bss_total_size = sum(block['size'] for block in bss_blocks) bss_start_vaddr = min((block['virt_start'] for block in bss_blocks), default=0) return sections, bss_blocks, max_addr, bss_total_size, bss_start_vaddr def generate_comment_data(): """Генерирует данные для секции .comment (UTF-8 строка 'Сборщик КВС' с нуль-терминатором)""" comment_str = 'Сборщик КВС' return comment_str.encode('utf-8') + b'\x00' def generate_shstrtab_binary(has_bss): """Генерирует бинарную таблицу имён секций (как в kvs_8.py)""" if has_bss: names = ['', '.text', '.data', '.bss', '.comment', '.shstrtab'] else: names = ['', '.text', '.data', '.comment', '.shstrtab'] result = b'' for name in names: result += name.encode('ascii') + b'\x00' return result def create_null_section_entry(shdr_offset): """Создаёт нулевую секцию (индекс 0) — все поля нулевые""" entries = [] for j in range(64): byte_val = 0x01 if j == 48 else 0x00 # sh_addralign = 1 entries.append({ 'сегмент': '.shdr', 'адрес': f"0x{shdr_offset + j:08x}", 'виртуальный_адрес': '0x00000000', 'байт': f"0x{byte_val:02x}", 'приводящая_метка': 'NULL' if j == 0 else '', 'уводящий_адрес': '', 'исходная_команда': '.shdr NULL' if j == 0 else '', 'команда_со_значениями': '', 'рассчитанный_уводящий_адрес': '', 'рассчитанный_байт': f"0x{byte_val:02x}" }) return entries def create_section_table_entries(sections, has_bss, shdr_offset, shstrtab_offset, comment_offset, comment_size, shstrtab_data, bss_start_vaddr, bss_total_size): """Создаёт записи таблицы секций для CSV (с нулевой секцией, .comment и .shstrtab)""" if DEBUG_PRINTS: print("\n[DEBUG] create_section_table_entries") print(f" has_bss = {has_bss}") print(f" bss_start_vaddr = 0x{bss_start_vaddr:x}") print(f" bss_total_size = {bss_total_size}") print(f" shdr_offset = 0x{shdr_offset:x}") print(f" shstrtab_offset = 0x{shstrtab_offset:x}") print(f" comment_offset = 0x{comment_offset:x}") print(f" comment_size = {comment_size}") entries = [] # Нулевая секция null_entries = create_null_section_entry(shdr_offset) entries.extend(null_entries) if DEBUG_PRINTS: print(f" Нулевая секция: {len(null_entries)} байт по адресу 0x{shdr_offset:x}") next_offset = shdr_offset + 64 if DEBUG_PRINTS: print(f" next_offset = 0x{next_offset:x}") # Индексы в .shstrtab if has_bss: idx_text = 1 idx_data = 7 idx_bss = 13 idx_comment = 18 idx_shstrtab = 27 # это харкод, если поменяю название сборщика - придется менять else: idx_text = 1 idx_data = 7 idx_comment = 13 idx_shstrtab = 22 if DEBUG_PRINTS: print(f" Индексы в .shstrtab: text={idx_text}, data={idx_data}, bss={idx_bss if has_bss else 'N/A'}, comment={idx_comment}, shstrtab={idx_shstrtab}") # 1. .text header_text = struct.pack(' 0: # SHT_NOBITS = 8, SHF_WRITE|SHF_ALLOC = 3 header_bss = struct.pack('") sys.exit(1) csv_file = sys.argv[1] print(f"\n📊 Анализ CSV: {csv_file}") sections, bss_blocks, max_addr, bss_total_size, bss_start_vaddr = analyze_csv(csv_file) has_bss = bss_total_size > 0 print_section_info(sections, has_bss, max_addr, bss_total_size, bss_start_vaddr) text_offset = sections['.text']['start'] data_offset = sections['.data']['start'] text_size = sections['.text']['size'] data_size = sections['.data']['size'] comment_data = generate_comment_data() comment_size = len(comment_data) comment_offset = data_offset + data_size print(f" comment_offset = 0x{comment_offset:x}") shstrtab_data = generate_shstrtab_binary(has_bss) shstrtab_size = len(shstrtab_data) shstrtab_offset = align_up(comment_offset + comment_size, 8) print(f" shstrtab_offset = 0x{shstrtab_offset:x}") print(f" shstrtab_size = {shstrtab_size}") num_sections = 5 if has_bss: num_sections += 1 shdr_offset = align_up(shstrtab_offset + shstrtab_size, 16) print(f" shdr_offset = 0x{shdr_offset:x}") print(f"\n📍 Размещение секций (как в kvs_8.py):") print(f" .data: 0x{data_offset:08x}") print(f" .comment: 0x{comment_offset:08x} (размер {comment_size} байт)") print(f" .shstrtab: 0x{shstrtab_offset:08x} (размер {shstrtab_size} байт)") print(f" Таблица секций: 0x{shdr_offset:08x}") print(f" Количество секций: {num_sections}") print(f" Наличие BSS: {has_bss}") # === НОВЫЙ КОД: обновляем max_addr === max_addr = max(max_addr, comment_offset + comment_size - 1) max_addr = max(max_addr, shstrtab_offset + shstrtab_size - 1) max_addr = max(max_addr, shdr_offset + (num_sections * 64) - 1) print(f"\n📍 Обновлённый максимальный файловый адрес: 0x{max_addr:08x}") # === КОНЕЦ НОВОГО КОДА === # Обновляем программные заголовки с учётом BSS regenerate_program_headers_in_csv(csv_file, sections, bss_total_size, text_offset, data_offset) # Создаём записи таблицы секций entries, num_headers = create_section_table_entries( sections, has_bss, shdr_offset, shstrtab_offset, comment_offset, comment_size, shstrtab_data, bss_start_vaddr, bss_total_size ) comment_entries = add_comment_data(comment_offset) shstrtab_entries = add_shstrtab_data(shstrtab_offset, shstrtab_data) e_shoff = shdr_offset e_shnum = num_headers e_shentsize = 64 e_shstrndx = num_headers - 1 print(f"\n📝 Обновление ELF-заголовка:") print(f" e_shoff = 0x{e_shoff:08x}") print(f" e_shnum = {e_shnum}") print(f" e_shentsize = {e_shentsize}") print(f" e_shstrndx = {e_shstrndx}") update_elf_header_in_csv(csv_file, e_shoff, e_shnum, e_shentsize, e_shstrndx) merge_csv_with_section_table(csv_file, entries, comment_entries, shstrtab_entries) print(f"\n💾 Таблица секций добавлена в {csv_file}") print(f" Добавлено {len(entries)} записей заголовков") print(f" Добавлено {len(comment_entries)} записей .comment") print(f" Добавлено {len(shstrtab_entries)} записей .shstrtab") print(f"\n✅ Готово! Размещение секций как в kvs_8.py:") print(f" .comment сразу после .data") print(f" .shstrtab выровнен на 8 байт") print(f" Таблица секций выровнена на 16 байт") if has_bss: print(f" BSS присутствует, размер {bss_total_size} байт, адрес 0x{bss_start_vaddr:x}") if __name__ == "__main__": main()