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)
# Забираем путь к настоящему objcopy, который нам передал CMake
real_objcopy = sys.argv[1]
# Все остальные аргументы — это то, что передал Zephyr для objcopy
args = sys.argv[2:]
# Проверяем, является ли этот вызов деструктивным сдвигом LMA со звездочкой '*'
is_lma_adjust = any("--change-section-lma" in arg for arg in args) and any("*" in arg for arg in args)
if is_lma_adjust:
print("[LMA Filter] Перехват деструктивного сдвига LMA...")
# 1. Извлекаем величину смещения (например, +3758096384 или +-536870912)
offset = ""
for arg in args:
if arg.startswith("*+") or arg.startswith("*-"):
offset = arg[1:] # Отсекаем звездочку
break
# 2. Вычисляем путь к readelf, так как он всегда лежит в одной папке с objcopy
sdk_bin_dir = os.path.dirname(real_objcopy)
readelf_bin = os.path.join(sdk_bin_dir, "arm-zephyr-eabi-readelf")
# На всякий случай: если префикс тулчейна отличается, ищем любой 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
# 3. Парсим структуру zephyr.elf
res = subprocess.run([readelf_bin, "-S", "zephyr.elf"], capture_output=True, text=True)
# 4. Ваша идея: отбираем секции, чей VMA-адрес (3-я колонка) строго начинается на '8'
lma_args = []
for line in res.stdout.splitlines():
parts = line.split()
if len(parts) >= 4 and parts[2].startswith("8"):
sec_name = parts[1].replace("[", "").replace("]", "")
# Секции без данных (NOBITS) во FLASH не копируются
if "bss" not in sec_name and "noinit" not in sec_name:
lma_args.extend(["--change-section-lma", f"{sec_name}{offset}"])
# 5. Вырезаем из исходной команды Zephyr маску '*' и дефолтные исключения, которые мешают
cleaned_args = [arg for arg in args if not (arg.startswith("*+") or arg.startswith("*-") or arg.startswith("!--change-section-lma"))]
cleaned_args = [arg for arg in cleaned_args if not arg.startswith("!.dtcm")]
# 6. Запускаем оригинальный objcopy точечно и безопасно
final_cmd = [real_objcopy] + lma_args + cleaned_args
subprocess.run(final_cmd, check=True)
print("[LMA Filter] Сдвиг LMA успешно применен только к секциям 0x8.")
else:
# Для всех остальных вызовов (генерация ihex, binary, удаление .comment) просто передаем управление
subprocess.run([real_objcopy] + args, check=True)
if __name__ == "__main__":
main()