C$$ddtorvec is used by the ADS 1.2 (and earlier) C++ compiler, to reserve zero-initialized space (ZI) for recording the destruction of static objects that are local to functions in C++ code. For example: struct T { T() {} ~T() {} }; void f() { static T t; } The destructor is added to C$$ddtorvec at construction time, i.e., when the function is first executed. Each occurrence of a function-local static object causes a call to "__push_ddtor__FPFv_v", which adds the destructor to the C$$ddtorvec list. The destructors are called when "__cpp_finalise_ddtors" is executed from within "__cpp_finalise", normally at the end of the program. C$$ddtorvec must be placed in RAM, because it is written at run-time. C$$ddtorvec must also be placed on a 4-byte aligned address in memory. Be aware that the C++ initialisation, construction and destruction mechanisms have changed in later toolkit releases. RVCT no longer uses C$$ddtorvec, C$$pi_ctorvec or C$$pi_dtorvec. If you have user code that relies on them, then it is advisable to try and isolate such code to allow for easier transition in the future. Known issue with C$$ddtorvec
There is a known issue with C$$ddtorvec in ADS 1.2 (and ADS 1.1, not ADS 1.0.1). C$$ddtorvec must be placed on a 4-byte aligned address in memory, but the C$$ddtorvec section is not marked as alignment 4. Issues can occur if the address of the C$$ddtorvec area does not have alignment 4 when linking. If the example above is expanded to: ---test.cpp--- struct T { T() {} ~T() {} }; void f() { static T t; } #pragma arm section zidata="A" char y; int main() { f(); return y; } then C$$ddtorvec will be mis-aligned because the global variable 'y' is a one byte ZI object. (The '#pragma arm section zidata="A"' is used in this example to provoke misalignment after any aligned .bss from the C library). Executing: armcpp -c test.cpp armlink -map test.o gives: : Execution Region ER_ZI (Base: 0x000084ac, Size: 0x00000074, Max: 0xffffffff, ABSOLUTE) Base Addr Size Type Attr Idx E Section Name Object 0x000084ac 0x0000000c Zero RW 3 .bss test.o 0x000084b8 0x00000060 Zero RW 19 .bss libspace.o(c_a__un.l) 0x00008518 0x00000001 Zero RW 4 A test.o 0x00008519 0x00000004 Zero RW 5 C$$ddtorvec test.o : The address 0x00008519 is not align 4 which reveals the issue. This code is likely to fail at run-time. Work-arounds
1. Adding an area with alignment 4 that will be placed by the linker just before C$$ddtorvec will work-around the issue. To do this create a new assembler file ensure_ddtorvec_alignment.s: ; a zero-length, 4-byte aligned area, ; named so that it sorts just before C$$ddtorvec
AREA |C$$ddtorvebzzzzz|, DATA, NOINIT, ALIGN=2 EXPORT Ensure_ddtorvec_alignment Ensure_ddtorvec_alignment END To ensure the above assembler is included in the final image, use one of the following methods: a) add the following to any one of your c/c++ source files: // in example, add this to test.cpp #if __ARMCC_VERSION < 200000 #pragma import (Ensure_ddtorvec_alignment) #endif or b) add to the link line: -keep Ensure_ddtorvec_alignment
Executing: armcpp -c test.cpp armasm ensure_ddtorvec_alignment.s armlink -map test.o ensure_ddtorvec_alignment.o gives: : Execution Region ER_ZI (Base: 0x000084ac, Size: 0x00000074, Max: 0xffffffff, ABSOLUTE) Base Addr Size Type Attr Idx E Section Name Object 0x000084ac 0x0000000c Zero RW 3 .bss test.o 0x000084b8 0x00000060 Zero RW 20 .bss libspace.o(c_a__un.l) 0x00008518 0x00000001 Zero RW 4 A test.o 0x00008519 0x00000003 PAD 0x0000851c 0x00000000 Zero RW 8 C$$ddtorvebzzzzz ensure_ddtorvec_alignment.o 0x0000851c 0x00000004 Zero RW 5 C$$ddtorvec test.o : From the above memory map, it can be seen that the C$$ddtorvec is now aligned properly to a 4 byte address. 2. Alternatively, another workaround is to place C$$ddtorvec at the start of a new RAM execution region in a scatterfile, e.g:
LOAD_REGION 0x... { : EXEC_REG_RAM 0x... { * (+RW) ; your RW data } EXEC_REG_RAM1 0x... ; an aligned 4 address { * (C$$ddtorvec, +FIRST) * (+ZI) ; your other ZI data } : } or LOAD_REGION 0x.... { : EXEC_REG_RAM 0x... { * (+RW, +ZI) ; your RW and/or ZI data } EXEC_REG_RAM1 +0 ; execution regions start on 4-byte ; aligned addresses, even if they are +0 { * (C$$ddtorvec) } : } Note that C$$ddtorvec is ZI data, so to comply with the linker's default within-region sorting order (RO then RW then ZI), C$$ddtorvec cannot be placed +FIRST within an execution region containing RO or RW sections.
|