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


import sys
import subprocess
import os

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:]
    
    # Identify if this is the destructive ELF-to-ELF LMA adjust step
    is_elf_to_elf_adjust = any("--change-section-lma" in arg for arg in args) and ("zephyr.elf" in args) and not any(fmt in " ".join(args) for fmt in ["ihex", "binary"])

    if is_elf_to_elf_adjust:
        print("[LMA Filter] Skipping destructive LMA adjust on the ELF file itself to prevent header corruption...")
        # We simply skip this command and return 0 (Success) so the '&&' chain doesn't break.
        # This keeps zephyr.elf 100% valid and fully debuggable via GDB!
        sys.exit(0)

    # Identify if this is the HEX or BIN generation step where we actually NEED the LMA adjust
    is_hex_or_bin_generation = any("--output-target=" in arg for arg in args)

    if is_hex_or_bin_generation:
        print("[LMA Filter] Injecting dynamic 0x8 LMA adjust directly into Hex/Bin generation step...")
        
        # Hardcoded offset based on your architecture requirements (0x100000000 - FLASH_BASE + FLEXSPI_BASE)
        offset = "+3758096384"
        
        # Determine the path to readelf binary in the toolchain folder
        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

        # Read the section headers structure using -SW
        res = subprocess.run([readelf_bin, "-SW", "zephyr.elf"], capture_output=True, text=True)
        
        # Parse section headers and build the tailored list of LMA targets starting with 0x8
        lma_args = []
        for line in res.stdout.splitlines():
            parts = line.split()
            if len(parts) < 3 or "Адрес" in line or "Address" in line:
                continue
            
            clean_parts = [p.replace('[', '').replace(']', '') for p in parts]
            vma_addr = ""
            sec_name = ""
            
            for i, part in enumerate(clean_parts):
                if len(part) == 8 and part.startswith('8'):
                    vma_addr = part
                    if i > 0:
                        sec_name = clean_parts[i-1]
                        if sec_name.isdigit() and i > 1:
                            sec_name = clean_parts[i-2]
                    break
            
            if not vma_addr:
                continue

            if sec_name in ["PROGBITS", "NOBITS", "ARM_EXIDX", "SYMTAB", "STRTAB"]:
                sec_name = clean_parts[1] if not clean_parts[0].isdigit() else clean_parts[2]

            # Your core idea: only shift sections in the 0x8 range, excluding NOBITS (bss/noinit)
            if vma_addr.startswith('8') and sec_name and not sec_name.isdigit():
                if "bss" not in sec_name and "noinit" not in sec_name:
                    lma_args.extend(["--change-section-lma", f"{sec_name}{offset}"])

        # Deduplicate the LMA arguments array
        unique_lma = []
        for item in lma_args:
            if item not in unique_lma:
                unique_lma.append(item)

        # Build and run the clean command directly producing the requested .hex or .bin file
        final_cmd = [real_objcopy] + unique_lma + args
        print(f"[LMA Filter] Successfully applied dynamic LMA shift to {len(unique_lma)//2} sections directly to output image.")
        subprocess.run(final_cmd, check=True)
    else:
        # Pass-through for any other auxiliary objcopy tasks
        subprocess.run([real_objcopy] + args, check=True)

if __name__ == "__main__":
    main()