某些平台要求您向链接器提供共享库的外部符号列表.但是,在大多数不需要的unixish系统上:默认情况下,所有非静态符号都可用.
我的理解是,GNU工具链可以选择性地将可见性限制为显式声明的符号.如何使用GNU ld实现这一目标?
该LD手册并不能说明什么KEEP命令一样.以下是来自第三方链接器脚本的功能片段KEEP.什么是KEEP命令做ld?
SECTIONS
{
.text :
{
. = ALIGN(4);
_text = .;
PROVIDE(stext = .);
KEEP(*(.isr_vector))
KEEP(*(.init))
*(.text .text.*)
*(.rodata .rodata.*)
*(.gnu.linkonce.t.*)
*(.glue_7)
*(.glue_7t)
*(.gcc_except_table)
*(.gnu.linkonce.r.*)
. = ALIGN(4);
_etext = .;
_sidata = _etext;
PROVIDE(etext = .);
_fini = . ;
*(.fini)
} >flash
Run Code Online (Sandbox Code Playgroud) 我正在尝试了解更深层次的链接过程和链接器脚本...查看binutils文档我发现了一个简单的链接器脚本实现,我通过添加一些命令进行了改进:
OUTPUT_FORMAT("elf32-i386", "elf32-i386",
"elf32-i386")
OUTPUT_ARCH(i386)
ENTRY(mymain)
SECTIONS
{
. = 0x10000;
.text : { *(.text) }
. = 0x8000000;
.data : { *(.data) }
.bss : { *(.bss) }
}
Run Code Online (Sandbox Code Playgroud)
我的程序是一个非常简单的程序:
void mymain(void)
{
int a;
a++;
}
Run Code Online (Sandbox Code Playgroud)
现在我尝试构建一个可执行文件:
gcc -c main.c
ld -o prog -T my_script.lds main.o
Run Code Online (Sandbox Code Playgroud)
但如果我尝试运行prog它SIGKILL在启动期间收到一个.我知道当编译程序并与命令链接时:
gcc prog.c -o prog
Run Code Online (Sandbox Code Playgroud)
最终的可执行文件是该产品也像其他的目标文件crt1.o,crti.o并crtn.o但对于我的情况?使用此链接描述文件的正确方法是什么?
我已经广泛搜索了如何做到这一点并且未能得出答案.
我的内存布局如下:
Fake Address | Section
0 | text
7 | relocate
15 | bss
23 | stack
Run Code Online (Sandbox Code Playgroud)
在堆栈的末尾我放置堆.它正在成长,堆栈是我正在使用的ARM芯片的完全下降堆栈.
现在,我想要做的是将一个部分(让我们称之为.persist)放入我的ram内存中.我希望它驻留在RAM的最后,我想将其编程到我的链接器脚本中.但是,此.persist部分的大小不是由我定义的,而是由编译器根据它包含的符号计算的.
到目前为止,我还没有想出一个好办法.因为我知道RAM起始地址和SIZE,如果我知道部分大小,那么计算部分需要去的位置是微不足道的.但是,根据GNU链接器文档(第74页),似乎:
SIZEOF(section)如果已分配该节,则返回指定节的大小(以字节为单位).如果在评估此部分时尚未分配该部分,则链接器将报告错误.
所以我无法计算链接器脚本中部分的大小(因为我想在放置它/分配之前计算大小).
有谁知道这样做的好方法?
我正在开展一个大学项目,我正在从头开始为Atmel SAM7S256微控制器编写软件.这比我之前使用的其他MCU更深入,因为这次需要了解链接器脚本和汇编语言.
我一直在仔细审查SAM7S芯片的示例项目,以便完全了解如何从头开始SAM7/ARM项目.一个明显的例子是米罗萨梅克的"建筑裸机ARM系统的GNU"教程发现这里(其中在该问题的代码是从).我也花了很多时间从sourceware.org阅读链接器和汇编程序文档.
我很高兴我在大多数情况下理解以下链接器脚本.只有一件涉及到位置计数器的东西对我来说没有意义.以下是上述教程提供的链接描述文件:
OUTPUT_FORMAT("elf32-littlearm", "elf32-bigarm", "elf32-littlearm")
OUTPUT_ARCH(arm)
ENTRY(_vectors)
MEMORY { /* memory map of AT91SAM7S64 */
ROM (rx) : ORIGIN = 0x00100000, LENGTH = 64k
RAM (rwx) : ORIGIN = 0x00200000, LENGTH = 16k
}
/* The sizes of the stacks used by the application. NOTE: you need to adjust */
C_STACK_SIZE = 512;
IRQ_STACK_SIZE = 0;
FIQ_STACK_SIZE = 0;
SVC_STACK_SIZE = 0;
ABT_STACK_SIZE = 0;
UND_STACK_SIZE = 0;
/* The size of the heap used by …Run Code Online (Sandbox Code Playgroud) 我正在尝试在编写内核时调试我所拥有的链接器问题.
问题是我有一个SCAN_CODE_MAPPING我无法使用的变量- 它似乎是空的或者其他东西.我可以通过改变链接程序的方式来解决这个问题,但我不知道为什么.
当我查看使用的生成的二进制文件时objdump,变量的数据肯定存在,所以只有一些东西在引用时被破坏了.
以下是两个链接器脚本和符号表中两个文件之间不同的部分的要点.
令我困惑的是,两个符号表都具有相同的符号,它们的长度都相同,并且它们似乎包含正确的数据.我能看到的唯一区别是它们的顺序不一样.
到目前为止我已经尝试过了
SCAN_CODE_MAPPING内存位置以确保它具有我期望的数据并且没有被清零.data.rel.ro.local确保它有数据的地址一个可能的线索就是这个警告:
warning: uninitialized space declared in non-BSS section `.text': zeroing
我在破碎和正确的情况下得到了.
我接下来应该尝试什么?
ALIGN关键字在链接描述文件中的作用是什么?我阅读了很多关于链接器脚本的教程,但是我无法理解ALIGN真正做了什么.任何人都可以简单解释一下.谢谢!
Q1 ELF中程序头和节头之间有什么区别
Q1.1段和段之间有什么区别?
我相信pheaders只指向部分.
Q2.什么是文件头和程序头之间的差异
根据gnu ld链接器脚本,使用Id:GNU链接器:
PHDRS
{
name type [ FILEHDR ] [ PHDRS ] [ AT ( address ) ]
[ FLAGS ( flags ) ] ;
}
Run Code Online (Sandbox Code Playgroud)
您可以在程序标题类型后面使用FILEHDR和PHDRS关键字来进一步描述该段的内容.FILEHDR关键字表示该段应包含ELF文件头.PHDRS关键字表示该段应包含ELF程序头本身
This is a bit confusing
Run Code Online (Sandbox Code Playgroud) 我从http://newlib.sourcearchive.com/documentation/1.18.0/init_8c-source.html查看了__libc_init_array的源代码.
但我不太明白这个功能是做什么的.
我知道这些符号
/* These magic symbols are provided by the linker. */
extern void (*__preinit_array_start []) (void) __attribute__((weak));
extern void (*__preinit_array_end []) (void) __attribute__((weak));
extern void (*__init_array_start []) (void) __attribute__((weak));
extern void (*__init_array_end []) (void) __attribute__((weak));
extern void (*__fini_array_start []) (void) __attribute__((weak));
extern void (*__fini_array_end []) (void) __attribute__((weak));
Run Code Online (Sandbox Code Playgroud)
在链接描述文件中定义.
链接器脚本的一部分可能如下所示:
.preinit_array :
{
PROVIDE_HIDDEN (__preinit_array_start = .);
KEEP (*(.preinit_array*))
PROVIDE_HIDDEN (__preinit_array_end = .);
} >FLASH
.init_array :
{
PROVIDE_HIDDEN (__init_array_start = .);
KEEP (*(SORT(.init_array.*)))
KEEP (*(.init_array*))
PROVIDE_HIDDEN …Run Code Online (Sandbox Code Playgroud) 我正在使用STMicroelectronics的STM32F746NG微控制器.该器件基于ARM Cortex-M7架构.我花了很多时间来理解示例项目中的linkerscript.我想出了基础知识,但我仍然无法掌握它的大部分内容.请帮我理解这些部分.
linkerscript开头如下:
/* Entry Point */
ENTRY(Reset_Handler) /* The function named 'Reset_Handler' is defined */
/* in the 'startup.s' assembly file. */
/* Highest address of the user mode stack */
/* Remember: the stack points downwards */
_estack = 0x20050000; /* End of RAM */
/* Generate a link error if heap and stack don't fit into RAM */
_Min_Heap_Size = 0x200; /* Required amount of heap */
_Min_Stack_Size = 0x400; /* Required amount of stack */ …Run Code Online (Sandbox Code Playgroud)