link script(链接器ld吃的文件)中使用宏定义的解决方案

问题:工作中遇到一个需求:需要在ld script中使用类似C语言的define等宏定义来做一些判断和替换

实验:

1:理论上*.c中都能用,是否gcc/ld也支持在ld script中直接用宏呢,结果:

arm-linux-ld:xxx.lds:2: ignoring invalid character `#' in expression
arm-linux-ld:xxx.lds:2: syntax error

人说水火无情,看来ld和gcc也不给面子啊。这里用的是交叉编译的ld,x86的也是一样的结论,本是同根生嘛。看来此路不通。

2:*.c中为什么能用define等宏呢,这个是在预编译阶段完成的。我们把gcc的预编译拿来先帮我们处理一次是否就可以了呢?带着疑问我们继续出发

先贴一份原始的ld script 吧:old.lds,里面有些define和注释哦

  1. /*
  2. * comments like C style
  3. * if comments line is less than 2 lines like this, maybe generate some strange result
  4. *
  5. */
  6. #ifdef __ARM__
  7. OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")
  8. OUTPUT_ARCH(arm)
  9. #else
  10. OUTPUT_FORMAT("elf32-littlends", "elf32-littlends", "elf32-littlends")
  11. OUTPUT_ARCH(nds)
  12. #endif
  13. ENTRY(_start)

  14. SECTIONS
  15. {
  16. //C++ comments
  17. . = 0x00000000;

  18. . = ALIGN(__ALIGN__);
  19. .text : /*C style comment*/
  20. {
  21. #if defined(__ARM__)
  22. cpu/arm920t/start.o (.text)
  23. #endif
  24. board/xxx/lowlevel_init.o (.text)
  25. board/xxx/nand_read.o (.text)
  26. *(.text)
  27. }

  28. . = ALIGN(__ALIGN__);
  29. .rodata : { *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.rodata*))) }

  30. . = ALIGN(__ALIGN__);
  31. .data : { *(.data) }

  32. . = ALIGN(__ALIGN__);
  33. __bss_start = .;
  34. .bss (NOLOAD) : { *(.bss) . = ALIGN(__ALIGN__); }
  35. _end = .;
  36. }

我们请gcc出马帮忙只进行预编译吧:(主要是 -E 和 -P的参数,不了解的man gcc 或者 gcc --help)

  1. deeve@debian:~/linux_all/project$ arm-linux-gcc -E -D__ARM__ -D__ALIGN__=4 -P old.lds -o new.lds
  2. arm-none-linux-gnueabi-gcc: old.lds: linker input file unused because linking not done

继续被打,看了gcc还认文件扩展名呀。那我们忽悠忽悠它吧:

  1. deeve@debian:~/linux_all/project$ cp old.lds old.c
  2. deeve@debian:~/linux_all/project$ arm-linux-gcc -E -D__ARM__ -D__ALIGN__=4 -P old.c -o new.lds

哇,居然成功糊弄过去了,赶紧看看new.lds是否是预期的呢:

  1. OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")
  2. OUTPUT_ARCH(arm)
  3. ENTRY(_start)
  4. SECTIONS
  5. {
  6. . = 0x00000000;
  7. . = ALIGN(4);
  8. .text :
  9. {
  10. cpu/arm920t/start.o (.text)
  11. board/xxx/lowlevel_init.o (.text)
  12. board/xxx/nand_read.o (.text)
  13. *(.text)
  14. }
  15. . = ALIGN(4);
  16. .rodata : { *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.rodata*))) }
  17. . = ALIGN(4);
  18. .data : { *(.data) }
  19. . = ALIGN(4);
  20. __bss_start = .;
  21. .bss (NOLOAD) : { *(.bss) . = ALIGN(4); }
  22. _end = .;
  23. }

太cool了,gcc看来还比较好骗嘛,O(∩_∩)O哈哈~

如果客官您觉得改名成*.c感觉不是太好,那您就使用下面的一行命令来搞定它吧:(注意命令中单独的一个"-"的用法哦)

deeve@debian:~/linux_all/project$ cat old.lds | arm-linux-gcc -E -D__ARM__  -D__ALIGN__=4 -P - -o new.lds
deeve@debian:~/linux_all/project$ arm-linux-gcc -E -D__ARM__  -D__ALIGN__=4 -P - <old.lds -o new.lds
deeve@debian:~/linux_all/project$ arm-linux-gcc -E -D__ARM__  -D__ALIGN__=4 -P - <old.lds > new.lds

以上三个命令,随便捞一个吧(一行居然没显示下,将就看看吧)
接下来呢,ld再吃已经处理过的new.lds就可以啦。不用我说,聪明的客官你肯定早知道了。

(0)

相关推荐