#!/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('.резб'): size = int(source.split()[1]) virt_start = int(virt_addr_str, 16) 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 return sections, bss_blocks, max_addr 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)""" # Формат: \0.text\0.data\0.comment\0.shstrtab\0 # (и .bss если есть) if has_bss: # .text, .data, .bss, .comment, .shstrtab names = ['', '.text', '.data', '.bss', '.comment', '.shstrtab'] else: # .text, .data, .comment, .shstrtab 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) — все поля нулевые (sh_addralign=1 как в эталоне)""" entries = [] # 64 байта нулей для нулевой секции for j in range(64): if 48 <= j <= 55: byte_val = 0x01 if j == 48 else 0x00 else: byte_val = 0x00 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): """Создаёт записи таблицы секций для CSV (с нулевой секцией, .comment и .shstrtab)""" if DEBUG_PRINTS: print("\n[DEBUG] create_section_table_entries") print(f" has_bss = {has_bss}") 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 = [] # Сначала добавляем НУЛЕВУЮ СЕКЦИЮ (индекс 0) 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 в зависимости от наличия BSS if has_bss: idx_text = 1 idx_data = 7 idx_bss = 13 idx_comment = 17 idx_shstrtab = 22 else: idx_text = 1 idx_data = 7 idx_comment = 13 idx_shstrtab = 22 if DEBUG_PRINTS: print(f" Индексы в .shstrtab:") print(f" idx_text = {idx_text}") print(f" idx_data = {idx_data}") if has_bss: print(f" idx_bss = {idx_bss}") print(f" idx_comment = {idx_comment}") print(f" idx_shstrtab = {idx_shstrtab}") # 1. Заголовок для .text (индекс 1) header_text = struct.pack('") sys.exit(1) csv_file = sys.argv[1] print(f"\n📊 Анализ CSV: {csv_file}") sections, bss_blocks, max_addr = analyze_csv(csv_file) has_bss = len(bss_blocks) > 0 print_section_info(sections, has_bss, max_addr) # Вычисляем смещения (как в kvs_8.py) 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) # Порядок размещения (как в kvs_8.py): # 1. .text (0x1000) # 2. .data (0x2000) # 3. .comment (сразу после .data) comment_offset = data_offset + data_size print(f" comment_offset = 0x{comment_offset:x}") # 4. .shstrtab (выравнивание на 8 байт после .comment) 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}") # 5. Таблица секций (выравнивание на 16 байт после .shstrtab) # Количество секций: NULL + .text + .data + .comment + .shstrtab (+ .bss если есть) num_sections = 5 # NULL + .text + .data + .comment + .shstrtab if has_bss: num_sections += 1 # + .bss # Таблица секций размещается после .shstrtab 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}") # ПЕРЕСОЗДАЁМ ПРОГРАММНЫЕ ЗАГОЛОВКИ regenerate_program_headers_in_csv(csv_file, sections, has_bss, text_offset, data_offset) # Генерируем записи таблицы секций entries, num_headers = create_section_table_entries( sections, has_bss, shdr_offset, shstrtab_offset, comment_offset, comment_size, shstrtab_data ) # Генерируем данные для .comment comment_entries = add_comment_data(comment_offset) # Генерируем данные для .shstrtab shstrtab_entries = add_shstrtab_data(shstrtab_offset, shstrtab_data) e_shoff = shdr_offset e_shnum = num_headers e_shentsize = 64 print(f"\n📝 Обновление ELF-заголовка:") print(f" e_shoff = 0x{e_shoff:08x}") print(f" e_shnum = {e_shnum}") print(f" e_shentsize = {e_shentsize}") # Обновляем ELF-заголовок в CSV update_elf_header_in_csv(csv_file, e_shoff, e_shnum, e_shentsize) # Добавляем таблицу секций, .comment и .shstrtab в CSV 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 присутствует → индекс .shstrtab = 21") else: print(f" BSS отсутствует → индекс .shstrtab = 21") if __name__ == "__main__": main()