标签: linker-scripts

gcc/ld - 使用glibc.2.6中的__isoc99_sscanf @@ GLIBC_2.7符号创建一个新的libc.so

我有一个应用程序,当我尝试运行它时会出错:

/lib/libc.so.6: version `GLIBC_2.7' not found
Run Code Online (Sandbox Code Playgroud)

但是glibc 2.7需要的唯一符号是

__isoc99_sscanf@@GLIBC_2.7 
Run Code Online (Sandbox Code Playgroud)

我想写一个小的单个函数"library",用这个符号作为__sscanf()的别名

我怎么能用gcc/ld做到这一点?

我的变体不被接受,因为"@@"符号

 int __isoc99_sscanf@@GLIBC_2.7(const char *, const char *, ...) __attribute__((alias("__sscanf")));
Run Code Online (Sandbox Code Playgroud)

第二个是我的变种

#include <stdarg.h>
int __isoc99_sscanf1(const char *a, const char *b, va_list args)
{
   int i;
   va_list ap;
   va_copy(ap,args);
   i=sscanf(a,b,ap);
   va_end(ap);
   return i;
}

   // __asm__(".symver __isoc99_sscanf,__isoc99_sscanf@@GLIBC_2.7");
    __asm__(".symver __isoc99_sscanf1,__isoc99_sscanf@@GLIBC_2.7");
Run Code Online (Sandbox Code Playgroud)

但它以链接器中的"找不到符号__isoc99_sscanf @@ GLIBC_2.7的版本节点"结束.

linker gcc scanf ld linker-scripts

6
推荐指数
1
解决办法
6445
查看次数

在RAM初始化之前使用#defined值

我正在编写ARM CPU的启动代码.没有内部RAM,但是有1GB的DDRAM连接到CPU,在初始化之前无法直接访问.代码存储在闪存中,初始化RAM,然后将自身和数据段复制到RAM并继续执行.我的计划是:

#define REG_BASE_BOOTUP 0xD0000000
#define INTER_REGS_BASE REG_BASE_BOOTUP

#define SDRAM_FTDLL_REG_DEFAULT_LEFT            0x887000

#define DRAM_BASE               0x0
#define SDRAM_FTDLL_CONFIG_LEFT_REG (DRAM_BASE+ 0x1484)
... //a lot of registers

void sdram_init() __attribute__((section(".text_sdram_init")));

void ram_init()
{
  static volatile unsigned int* const sdram_ftdll_config_left_reg = (unsigned int*)(INTER_REGS_BASE + SDRAM_FTDLL_CONFIG_LEFT_REG);
  ... //a lot of registers assignments

  *sdram_ftdll_config_left_reg = SDRAM_FTDLL_REG_DEFAULT_LEFT;
}
Run Code Online (Sandbox Code Playgroud)

目前我的程序工作不正常,因为寄存器值最终被链接到RAM,并且在程序尝试访问它们时,只有闪存可用.

我怎么能改变我的链接器脚本或我的程序,以便这些值在闪存中的地址?有没有办法在文本段中包含这些值?

实际上,当它们在文件范围内声明时,那些定义的值是全局数据还是静态数据?

编辑:

目标文件与以下链接描述文件链接:

MEMORY 
{                                                                                                             
RAM (rw)    : ORIGIN = 0x00001000, LENGTH = 12M-4K                                
ROM (rx)    : ORIGIN = 0x007f1000, LENGTH = 60K
VECTOR (rx) : ORIGIN = …
Run Code Online (Sandbox Code Playgroud)

c arm linker-scripts c-preprocessor

6
推荐指数
1
解决办法
340
查看次数

GCC:如何告诉GCC将'main'函数放在.text段的开头?

我刚刚开始学习一些ARM编程,但我遇到了一个有点恼人的问题.我用来编译源代码的工具链是Sourcery CodeBench Lite 2013.05-23(可以在这里找到:https://sourcery.mentor.com/GNUToolchain/release2449 )

我需要的是告诉GCC或LD或OBJCOPY将'main'函数的编译字节码放在.text段的开头.

有没有办法实现这个目标?(也许通过链接器脚本?)

谢谢

gcc program-entry-point ld linker-scripts objcopy

6
推荐指数
2
解决办法
5469
查看次数

gcc:你能把函数指针放到不同的部分(不是.data)吗?

为了对主机上的嵌入式项目进行单元测试,我开始使用函数指针来在函数的"真实"实现和运行时的模拟之间进行切换.所以,我的函数'foo'在.c文件中看起来像这样:

// the 'real' implementation of the function to be used during runtime
void fooImplementation ( )
{
    /* ... */
}
// the function pointer, initialized to the 'real' implementation
void (*foo) ( ) = fooImplementation;
Run Code Online (Sandbox Code Playgroud)

结果是目标处理器(Blackfin)产生异常,因为函数指针驻留在内部L1数据存储器中,不允许携带代码而只允许数据.

一个有效的解决方案是为每个函数指针分配一个属性,以便将它放入不在L1数据存储器中的不同部分,例如:

void (*foo) ( ) __attribute__ (( section(".ext_mem"))) = fooImplementation;
Run Code Online (Sandbox Code Playgroud)

但是这使得代码有点难以阅读并且容易出错(如果您忘记分配属性,单元测试将运行正常,但代码将在目标上调用函数后立即生成异常).

所以我的问题是,如果有一些方法告诉gcc默认将所有函数指针放到不同的部分.

c embedded gcc pointers linker-scripts

6
推荐指数
1
解决办法
886
查看次数

使用链接描述文件显式设置起始堆栈指针

我想在虚拟内存的末尾创建一个带有特殊部分的程序.所以我想做一个像这样的链接器脚本:

 /* ... */
 .section_x 0xffff0000 : {
     _start_section_x = .;
     . = . + 0xffff;
     _end_section_x = .;
 }
Run Code Online (Sandbox Code Playgroud)

的问题是,GCC/LD/glibc的似乎在该位置处由默认32位应用程序加载堆栈,即使它重叠的已知部分.上面的代码为0,导致异常.有没有办法告诉链接器为堆栈使用另一个VM内存位置?(同样,我想确保堆不会跨越虚拟内存的这一部分......).

linker gcc arm ld linker-scripts

6
推荐指数
1
解决办法
372
查看次数

是否有允许我移动堆栈起始地址的链接器脚本指令?

我正在尝试使用 x86_64 上的链接器脚本更改堆栈的起始位置。我能够使用这个移动我的可执行起始地址:

PROVIDE (__executable_start = SEGMENT_START("text-segment", 0x200000)); . = SEGMENT_START("text-segment", 0x200000) + SIZEOF_HEADERS;
Run Code Online (Sandbox Code Playgroud)

我像这样改变了我的全局变量:

 .data ALIGN(0x10000000)           :
{
*(.data .data.* .gnu.linkonce.d.*)
 SORT(CONSTRUCTORS)
}
Run Code Online (Sandbox Code Playgroud)

我尝试使用以下内容来移动堆栈区域:

. = 0x50000000;
.stack    :
{
 stack_start = .;

  PROVIDE( stack_start = . );
  *(.stack)
      . += 0x2000;
  stack_end = . ;
  PROVIDE( stack_end = . );
}
Run Code Online (Sandbox Code Playgroud)

但这并没有让我去任何地方。

这是我用来测试堆栈位置的测试程序:

 #include <stdio.h>
 #include <stdlib.h>

int global_var = 555;

void test()
{
   int local_test = 666;

   printf("address of global_var: %p\n", &global_var);
   printf("address of local_test: %p\n", &local_test); …
Run Code Online (Sandbox Code Playgroud)

linker executable elf linker-scripts executable-format

5
推荐指数
1
解决办法
1435
查看次数

与另一个启动文件链接

我正在尝试使用STARTUPLD 脚本中的指令将程序与我自己的启动文件链接起来:

...
ENTRY(_start)
STARTUP(my_crt1.o)
...
Run Code Online (Sandbox Code Playgroud)

GCC 驱动程序用于链接程序(不要打扰 libgcc 等库路径):

gcc -T my_script.ld ...
Run Code Online (Sandbox Code Playgroud)

不幸的是,它只适用于为 powerpc 目标编译的 GCC,而 arm 或 i686 目标不支持并且仍然在 collect2 中包含 crt0.o。例如:

arm-eabi-g++ -v -T my_script.ld ...
Run Code Online (Sandbox Code Playgroud)

给我:

collect2 ... /opt/lib/gcc/arm-eabi/4.8.0/../../../../arm-eabi/lib/crt0.o ...
Run Code Online (Sandbox Code Playgroud)

因此:

crt0.S:101: multiple definition of `_start'
Run Code Online (Sandbox Code Playgroud)

似乎该STARTUP指令被完全忽略(除非STARTUP指定了该指令,否则 powerpc 目标也使用其默认的 crt0 )并且无法禁用默认的 crt0。

是否有一种可移植的方式来链接另一个启动文件?

我的启动文件的使用libgcc功能(打电话给构建函数和dtors)等等crtbegin.ocrtend.o等需要,所以我想,以避免-nostartfiles其禁用选项crt*.o-我需要禁用crt0.o只。

谢谢

c linker gcc ld linker-scripts

5
推荐指数
2
解决办法
4868
查看次数

链接器脚本:将函数的绝对地址插入到生成的代码中

我有一个与 gcc 链接器相关的问题。

我正在处理嵌入式内容(PIC32),但 PIC32 的编译器和链接器基于 gcc,因此,“常规”gcc 链接器和 PIC32 链接器的主要内容应该是通用的。

为了节省闪存空间(这在微控制器上通常是不够的),我需要在引导加载程序中放置几个​​大函数,应用程序应该只通过指针调用这些函数。

所以,我需要在生成的代码中创建向量表。

我正在尝试获取函数的绝对地址并将其写入生成的代码,但仍然出现错误。

在下面的示例中,我试图获取函数的地址_formatted_write

代码:

.user_addr_table _USER_ADDR_TABLE_ADDR :
{
   KEEP(*(.user_addr_table))
   LONG((ABSOLUTE(_formatted_write))); /* _formatted_write is a name of my function */
} > user_addr_table
Run Code Online (Sandbox Code Playgroud)

链接器返回错误:“ unresolvable symbol '_formatted_write' referenced in expression”。

我注意到如果我写了一些垃圾而不是_formatted_write,那么它会返回错误“ undefined symbol .....”,因此,_formatted_write链接器知道。

这让我觉得我应该执行一些额外的步骤以使其“可解决”。但仍然不知道如何做到这一点。

c gcc ld linker-scripts

5
推荐指数
1
解决办法
2332
查看次数

为什么 Cortex-M4 在链接器脚本中包含 ARM 到 Thumb 粘合

我们正在为 STM32 芯片上的 ARM Cortex M4 编写一些代码。

我的理解是 Cortex-M4 有一些 32 位指令,但这些不是 32 位 ARM 指令,它们只是一些特殊指令。我认为粘合剂是为了在 ARM 和拇指指令集之间转换。那么为什么链接描述文件需要胶水呢?

.text :
{
. = ALIGN(4);
*(.text)           /* .text sections (code) */
*(.text*)          /* .text* sections (code) */
*(.glue_7)         /* glue arm to thumb code */
*(.glue_7t)        /* glue thumb to arm code */
Run Code Online (Sandbox Code Playgroud)

由于处理器仅支持拇指指令,我可以删除glue_7和吗?glue_7t这样做会释放任何闪存吗?

arm linker-scripts thumb cortex-m

5
推荐指数
1
解决办法
948
查看次数

数组和结构体可以以不同的方式初始化吗?

我的问题可能看起来很奇怪,事实上,这是上下文:

我目前面临一个奇怪的问题,同时切换 -在我正在从事的项目上- 从pullinino到CV32的核心(也发生了一些其他变化,例如关于crt0,如一些数据RAM重置)。

这是一个(真实的)示例,说明了一个相当简单的 main 所发生的情况(我无法对startup/crt0 文件进行编辑:我在帖子后面部分给出了它)。

#include <string.h>
#include <inttypes.h>
#include <stdio.h>

typedef struct
{
    uintptr_t addr;
    uint32_t foo;  
} some_struct_t;

static uint32_t text_in_data[8] = {0x11111111, 0x22222222, 0x33333333, 0x44444444, 0x55555555, 0x66666666, 0x77777777, 0x88888888};
uint32_t text_in_data2[8] = {0x11111111, 0x22222222, 0x33333333, 0x44444444, 0x55555555, 0x66666666, 0x77777777, 0x88888888};

some_struct_t text_in = {(uintptr_t)text_in_data, 8};
static some_struct_t text_in2 = {(uintptr_t)text_in_data, 8};

int main(void)
{
    some_struct_t text_in3 = {(uintptr_t)text_in_data, 8};
    static some_struct_t text_in4 = {(uintptr_t)text_in_data, 8};
    static some_struct_t text_in5 = {(uintptr_t)text_in_data2, …
Run Code Online (Sandbox Code Playgroud)

c embedded storage linker-scripts riscv

5
推荐指数
0
解决办法
323
查看次数