Загрузка данных


import sys
import subprocess
import os
import re

def main():
    if len(sys.argv) < 2:
        print("[LMA Filter] Error: No real objcopy path provided.")
        sys.exit(1)

    real_objcopy = sys.argv[1]
    args = sys.argv[2:]
    
    # Ищем абсолютный или относительный путь к zephyr.elf в аргументах
    elf_path = "zephyr.elf"
    for arg in args:
        if arg.endswith("zephyr.elf"):
            elf_path = arg
            break

    # Определяем тип шага
    is_elf_to_elf_adjust = any("--change-section-lma" in arg for arg in args) and ("zephyr.elf" in elf_path) and not any(fmt in " ".join(args) for fmt in ["ihex", "binary"])
    is_hex_or_bin_generation = any("--output-target=" in arg for arg in args) or any(fmt in " ".join(args) for fmt in ["ihex", "binary"])

    # Включаем отладку для ОБОИХ шагов, чтобы сравнить вывод
    if is_elf_to_elf_adjust or is_hex_or_bin_generation:
        step_type = "ELF-to-ELF" if is_elf_to_elf_adjust else "HEX/BIN Generation"
        print(f"\n[LMA Filter DEBUG] === Target Step: {step_type} ===")
        print(f"[LMA Filter DEBUG] Working with ELF file: {elf_path}")
        
        # Динамический поиск readelf
        sdk_bin_dir = os.path.dirname(real_objcopy)
        readelf_bin = os.path.join(sdk_bin_dir, "arm-zephyr-eabi-readelf")
        if not os.path.exists(readelf_bin):
            for file in os.listdir(sdk_bin_dir):
                if file.endswith("readelf"):
                    readelf_bin = os.path.join(sdk_bin_dir, file)
                    break

        if not os.path.exists(readelf_bin):
            print(f"[LMA Filter] Critical Error: readelf not found in {sdk_bin_dir}")
            sys.exit(1)

        # Читаем секции
        res = subprocess.run([readelf_bin, "-SW", elf_path], capture_output=True, text=True)
        if res.returncode != 0:
            print(f"[LMA Filter] Error running readelf: {res.stderr}")
            subprocess.run([real_objcopy] + args, check=True)
            sys.exit(0)

        lma_args = []
        # Регулярка захватывает: [индекс] имя_секции тип_секции адрес_VMA
        section_regex = re.compile(r'^\s*\[\s*\d+\]\s+([\.\w\-_]+)\s+(\w+)\s+([0-9a-fA-F]{8,16})')

        print("[LMA Filter DEBUG] Scanning all sections in 0x80000000 range:")
        for line in res.stdout.splitlines():
            match = section_regex.match(line)
            if not match:
                continue
                
            sec_name, sec_type, vma_addr = match.groups()
            
            # Проверяем диапазон 0x8XXXXXXX
            clean_vma = vma_addr.lstrip('0')
            if not (vma_addr.startswith('8') or (vma_addr.startswith('08') and len(clean_vma) <= 8)):
                continue

            # Логируем абсолютно всё, что попало в диапазон 0x8
            status = "ACCEPTED"
            reason = ""

            if sec_type == "NOBITS" or "bss" in sec_name or "noinit" in sec_name:
                status = "SKIPPED"
                reason = "(RAM/BSS section)"
            elif sec_name in [".comment", ".ARM.attributes", ".debug_info"]:
                status = "SKIPPED"
                reason = "(Debug/Service section)"

            print(f"  -> Found: Name: {sec_name:<20} Type: {sec_type:<10} VMA: 0x{vma_addr} [{status}] {reason}")

            if status == "ACCEPTED":
                offset = "+3758096384"
                lma_args.extend(["--change-section-lma", f"{sec_name}{offset}"])

        unique_lma = []
        for item in lma_args:
            if item not in unique_lma:
                unique_lma.append(item)

        print(f"[LMA Filter DEBUG] Total accepted sections for LMA shift: {len(unique_lma)//2}")
        print("==================================================\n")

        # Возвращаем стандартное поведение пропуска/модификации
        if is_elf_to_elf_adjust:
            print("[LMA Filter] Skipping destructive LMA adjust on the ELF file itself...")
            sys.exit(0)
        else:
            final_cmd = [real_objcopy] + unique_lma + args
            subprocess.run(final_cmd, check=True)
    else:
        # Все остальные фоновые вызовы objcopy
        subprocess.run([real_objcopy] + args, check=True)

if __name__ == "__main__":
    main()