Загрузка данных
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()