Chinaunix首页 | 论坛 | 博客
  • 博客访问: 579853
  • 博文数量: 169
  • 博客积分: 2656
  • 博客等级: 少校
  • 技术积分: 1685
  • 用 户 组: 普通用户
  • 注册时间: 2009-07-30 13:03
文章分类

全部博文(169)

文章存档

2011年(1)

2010年(135)

2009年(33)

我的朋友

分类: 嵌入式

2010-05-20 23:20:26

链接错误:
dld: Symbol optarg is out of address range
dld:   - Symbol is addressed using Small Data Area relative addressing
dld:   - Area name is SDA, SDA2 or SD0
dld:   - Area base is _SDA_BASE_ 0x001a22c0
dld:   - Either the area has overflowed
dld:     or the symbol is not defined in the area
dld:     or the area sections are not placed in a same GROUP
dld:   - Symbol is defined in section .data in file partialImage.o
dld:   - Symbol section is allocated at address 0x0018ce20
dld:   - Symbol is referenced from file partialImage.o, at address 0x000f9424
dld:   - Symbol is referenced from section .text, section is allocated at 0x00010000
dld:   - Symbol is defined at address 0x00192014
dld:   - Symbol is referenced with offset 0x00000000
dld: error: Can't relocate
 
Linker: Out of Range Error
Introduction
This application notes tries to outline the circumstances under which you will come across this error from the linker. This error results when linking some modules that are compiled with -Xsmall-data=0 and -Xsmall-const=0 and some that are compiled with these values set to a non-zero value. Another probable case would be placing too many variables in small-data area. The wrong usage of #pragmas can also lead to this problem.
Small Data Area and Small Const Area
The Small Data Area is a part of memory in which resides variables which can be accessed with a single instruction. This is done by reserving a register as a base register and accessing a variable off of this register. There are two Small Data Areas (SDA) which are of interest here. The constant SDA, also called as SDA2, denoting .sdata2 section. Most of the time the constants reside in the ROM area after .text section. The normal SDA, from hereon referred to as SDA, denotes .sdata and .sbss sections. The section .sdata is followed by the .sbss section in memory.
The following base registers are used for the addressing modes:
PowerPC
Mode                   Register
absolute              r0
code-relative        r2 for data references, PC for branches
data-relative        r13
68k and ColdFire
Mode                  Register
code-relative        PC
data-relative        a5
The base registers point to the middle of their respective sections.
The startup file crt0.s for PPC has instructions to initialize these base registers. For example:
        addis           r13,r0,_SDA_BASE_@ha
        addi             r13,r13,_SDA_BASE_@l
        addis           r2,r0,_SDA2_BASE_@ha
        addi             r2,r2,_SDA2_BASE_@l
The sumbols _SDA2_BASE and _SDA_BASE are generated by the linker. The values are calculated using the formula
_SDA2_BASE = ADDR(.sdata2) + 0x7ff0;
_SDA_BASE = ADDR(.sdata) + 0x7ff0;
Making these registers point to 32k from the start of these sections enable us to use positive and negative offsets from these registers. This gives us a range of -32k to +32k from this address with an effective size of 64k. Actually, this area is not exactly 32k (0x8000), but 16 bytes less (0x7fff0). The 16 bytes are rquired for implementing loop unrolling optimization.
The limit is 64k because there are only 16 bits to encode the address when using relative addressing under PPC.
Examples Illustrating "Out of Range" Error
This section presents a collection of examples which would give this error and outlines ways to avoid it. All examples are discussed assuming the target to be one of the PowerPC processors.
Example 1
#pragma section SDATA RX address=0x120000
#pragma use_section SDATA i_arr, c_arr;

int i_arr[10]={1,0};
char c_arr[6];

main() {
        char c;
        i_arr[1]=20;
        c=c_arr[6];
}

~/c > dcc ex1.c   
dld: Symbol i_arr is out of range in ex1.o at 0x00100040:
dld:   - Either the Small Data Area (SDA) has overflowed or
dld:     the symbol is not defined in the SDA or
dld:     the SDA sections are not placed in a common GROUP
dld:   - Symbol is defined in section .abs.00120000 in file ex1.o
dld:   - Symbol is addressed using SDA relative addressing
The problem here is that the variable is addressed using relative data addressing and the code which refers to it from main, as shown in the assembly file,
        stw             r12,(i_arr+4)@sdarx(r0)
        lbz             r11,(c_arr+6)@sdarx(r0)
can not be encoded with the address at where this variable resides. The area .abs.00120000 where these variables reside, falls out of the range. This is because the base registers r2 and r13 point to .sdata2 and .sdata respectively by default. Simply put, you need to have only one SDA or SDA2.
This means that we can not use SDA relative addressing when using absolute sections which fall out of the range. There is an easy way to avoid this. All you need to do is to change the way these variables are accessed using a different addressing mode as part of #pragma.
#pragma section SDATA RX far-data address=0x120000
#pragma use_section SDATA i_arr, c_arr;

int i_arr[10]={1,0};
char c_arr[6];

main() {
        char c;
        i_arr[1]=20;
        c=c_arr[6];
}
In the above we use far-data addressing mode and everything links correctly.
Example 2
/* sda.c */
char string[]= "Hello World";
const int sconst1= 50;
const char sconst2='a';

/* sda1.c */
extern char string [];
extern const int sconst1;
extern const char sconst2;

main() {
        int i;
        char c;
        i=sconst1;
        c=sconst2;
}


~/c > dcc sda1.o sda.o
dld: Symbol sconst1 is out of range in sda1.o at 0x0010003c:
dld:   - Either the Small Data Area (SDA) has overflowed or
dld:     the symbol is not defined in the SDA or
dld:     the SDA sections are not placed in a common GROUP
dld:   - Symbol is defined in section .text in file sda.o
dld:   - Symbol is addressed using SDA relative addressing
In the above example, the out of range error occurs because the module sda.c was compiled with options Xsmall-const=0 and Xsmall-data=0. If these options are used, the compiler will not use .sdata2 and .sdata sections. But in the next module, the compiler assumes that these externs are in .sdata2 and .sdata and refers to these varaibles through r2 and r13. Since the linker does not find these variables within the 32k and 32k range, so it issues the out-of-range error.
NOTES:
If you are using the Xsmall-const=0 or Xsmall-data=0 options, make sure you use them for all modules. However, this is NOT a recommended practice because of code bloat and performance degradation.
In versions prior to 4.3, the linker required the .sdata2 and .sdata sections to be in different GROUPs in the linker command file.
Conclusion
The two most common circumstances that generate the out of range error are:
1.        Compiling the modules where the variables are declared with options which cause them to NOT reside in the .sdata or .sdata2 sections and then accessing them from another module using base registers.
2.        Having more than one data area which is of type SDA or SDA2. This requires switching the base registers to point to these two distinctive areas depending on the context. This is difficult to control.
 
本错误的原因在于optarg的重复定义。diab编译器如此报错。
阅读(3026) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~