Загрузка данных
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:]
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"])
if is_elf_to_elf_adjust:
sys.exit(0)
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_hex_or_bin_generation and os.path.exists(elf_path):
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
# Step 1: Find the actual end of pure monolithic code sections (0x80000000...)
code_end_vma = 0x80000000
if os.path.exists(readelf_bin):
res = subprocess.run([readelf_bin, "-SW", elf_path], capture_output=True, text=True)
if res.returncode == 0:
section_regex = re.compile(r'^\s*\[\s*\d+\]\s+([\.\w\-_]+)\s+(\w+)\s+([0-9a-fA-F]{8,16})\s+([0-9a-fA-F]{6,8})\s+([0-9a-fA-F]{6,8})')
for line in res.stdout.splitlines():
match = section_regex.match(line)
if match:
sec_name, sec_type, vma_str, _, size_str = match.groups()
vma_val = int(vma_str, 16)
size_val = int(size_str, 16)
# We track the end of traditional continuous code/rodata sections before any RAM data gaps
if 0x80000000 <= vma_val < 0x80300000 and sec_type != "NOBITS" and "area" not in sec_name and "data" not in sec_name:
end_pos = vma_val + size_val
if end_pos > code_end_vma:
code_end_vma = end_pos
# Align the starting point for flash data payload allocation to a 16-byte boundary
flash_data_start_lma = (code_end_vma - 0x20000000 + 15) & ~15
print(f"[LMA Filter] Fixed Dynamic Pack: Code ends around LMA {hex(code_end_vma - 0x20000000)}. Data payload starts at LMA {hex(flash_data_start_lma)}")
# Step 2: Form unique LMA remapping arguments per section
dynamic_offsets = []
if os.path.exists(readelf_bin):
res = subprocess.run([readelf_bin, "-SW", elf_path], capture_output=True, text=True)
if res.returncode == 0:
section_regex = re.compile(r'^\s*\[\s*\d+\]\s+([\.\w\-_]+)\s+(\w+)\s+([0-9a-fA-F]{8,16})')
current_flash_lma = flash_data_start_lma
for line in res.stdout.splitlines():
match = section_regex.match(line)
if match:
sec_name, sec_type, vma_str = match.groups()
if sec_name in [".comment", ".symtab", ".strtab", ".shstrtab"] or sec_name.startswith(".debug"):
continue
vma_val = int(vma_str, 16)
if sec_type == "NOBITS":
continue
# Ignore metadata sections outside of the actual physical hardware memory map range
if vma_val < 0x80000000:
continue
# Classify data vs code based on section naming templates or explicitly high address regions
is_data_section = "area" in sec_name or "data" in sec_name or "state" in sec_name or vma_val >= 0x80400000 or sec_name in [".ramfunc", "nocache"]
if is_data_section:
dynamic_offsets += ["--change-section-lma", f"{sec_name}={hex(current_flash_lma)}"]
size_res = re.search(r'^\s*\[\s*\d+\]\s+' + re.escape(sec_name) + r'\s+\w+\s+[0-9a-fA-F]+\s+[0-9a-fA-F]+\s+([0-9a-fA-F]+)', res.stdout, re.M)
if size_res:
current_flash_lma += (int(size_res.group(1), 16) + 3) & ~3
else:
standard_lma = vma_val - 0x20000000
dynamic_offsets += ["--change-section-lma", f"{sec_name}={hex(standard_lma)}"]
final_cmd = [real_objcopy] + dynamic_offsets + args
subprocess.run(final_cmd, check=True)
# Step 3: Print clean verified summary mapping table
if os.path.exists(readelf_bin):
res = subprocess.run([readelf_bin, "-SW", elf_path], capture_output=True, text=True)
if res.returncode == 0:
print(f"\n[LMA Filter] === VERIFIED DYNAMICALLY PACKED MEMORY MAP FOR FLASH ===")
print(f"{'Section Name':<28} | {'Original VMA':<12} | {'Resulting LMA (Flash)':<22}")
print("-" * 72)
section_regex = re.compile(r'^\s*\[\s*\d+\]\s+([\.\w\-_]+)\s+(\w+)\s+([0-9a-fA-F]{8,16})')
current_flash_lma = flash_data_start_lma
for line in res.stdout.splitlines():
match = section_regex.match(line)
if not match:
continue
sec_name, sec_type, vma_str = match.groups()
if sec_name in [".comment", ".symtab", ".strtab", ".shstrtab"] or sec_name.startswith(".debug"):
continue
vma_val = int(vma_str, 16)
vma_formatted = f"0x{vma_val:08X}"
if sec_type == "NOBITS":
print(f"{sec_name:<28} | {vma_formatted:<12} | {'--------':<22} [RAM-only / Ignored]")
continue
if vma_val < 0x80000000:
print(f"{sec_name:<28} | {vma_formatted:<12} | {'--------':<22} [Toolchain Info / Ignored]")
continue
is_data_section = "area" in sec_name or "data" in sec_name or "state" in sec_name or vma_val >= 0x80400000 or sec_name in [".ramfunc", "nocache"]
if is_data_section:
lma_formatted = f"0x{current_flash_lma:08X}"
size_res = re.search(r'^\s*\[\s*\d+\]\s+' + re.escape(sec_name) + r'\s+\w+\s+[0-9a-fA-F]+\s+[0-9a-fA-F]+\s+([0-9a-fA-F]+)', res.stdout, re.M)
if size_res:
current_flash_lma += (int(size_res.group(1), 16) + 3) & ~3
else:
lma_formatted = f"0x{(vma_val - 0x20000000):08X}"
print(f"{sec_name:<28} | {vma_formatted:<12} | {lma_formatted:<22} -> OK (Flash)")
print("=" * 72 + "\n")
else:
subprocess.run([real_objcopy] + args, check=True)
if __name__ == "__main__":
main()