I am using arm-none-eabi-gcc (V6.3), and CPU core is ARM COrtexM0. In my linker file, I make 2 sections for text and rodata. The .text section is for all the C code text and rodata, except for the tools_static.a, which is a very large static library I want to place it in other area of the flash. The .tool_sec section is for tools_static.a only(including text and rodata of this static library).
Everything works fine until I add a new function in the tools_static.a.
This new function, although links to the tools_static.a, I want to place it in the .text. So I define the new function with .newaddfunc section flag, and put the .newaddfunc in .text.
Here is what my linker file looks like:
SECTIONS
{
.tool_sec : /* for the tools_static.a*/
{
.=ALIGN(4);
KEEP(*tools_static.a: *(.text*))
KEEP(*tools_static.a: *(.rodata* .srodata*))
} > FLASH_TOOL_AREA AT>FLASH_TOOL_AREA
.text :
{
.=ALIGN(4);
*(.text)
*(.text.*)
*(.newaddfunc) /* for the new added function in tools_static.a*/
*(.rodata)
*(.rodata.*)
} > FLASH AT>FLASH
..... // other sections
}
After compilation, I check the objdump file. The new function is placed in the text section as I want, and the size of text is increased exactly the size of new function. But the size of tool_sec is changed unexpected (increasd 0x18). size of tool_sec should remain the same because the new function is placed in the text section.
I check the symbols and size of each symbol of the tool_sec, trying to find the reason why the size of tool_sec is increased. But to my surprise, the size of all tool_sec symbols are the same. But there is one function (let's call it FUNCTION_A) whose start address is increased by 0x18. And before FUNCTION_A, there is a readonly array (let's call it ARRAY_B) with 0x1c size. While the address gap of the ARRAY_B and FUNCTION_A is much larger than 0x1c. It seems some junk assemble code. I don't know which function these junk code belongs and don't know why it become larger.
I compare the objdump before/after I add the new function to the tools_static.a. Here is what the objdump file looks like:
====================================
before I add the new function
0x210615d0 ARRAY_B (size 0x1c)
.....// ARRAY_B content
..... //unknown code whithout symbol name
....
0x21061824 FUNCTION_A
=====================================
after I add the new function
0x210615d0 ARRAY_B (size 0x1c)
.... // ARRAY_B content
.... // unknown code whithout symbol name
....
0x2106183c FUNCTION_A (the starting address increased 0x18)
Could someone kindly give me a suggestion on this issue?
The problem is related to functions placed in special sections with constant and static data in it, as specified here:
If a function has been placed in a special section via attributes, we may want to put its static data and string constants in a special section too
So the problem is related to the fact that the .newaddfunc section contains only the .text section of the function, and not the static data.
Here I've tried to emulate your problem specifications:
new_function.c
__attribute__((section(".newaddfunc")))
void new_function(void) {
for (int i = 0; i < 100; i++)
{
}
static const uint8_t new_array1[16] = {0};
static const uint8_t new_array2[20] = {0};
}
if I check using:
arm-none-eabi-objdump -x new_function.o
Sections:
Idx Name Size VMA LMA File off Algn
0 .text 00000000 00000000 00000000 00000034 2**0
CONTENTS, ALLOC, LOAD, READONLY, CODE
1 .data 00000000 00000000 00000000 00000034 2**0
CONTENTS, ALLOC, LOAD, DATA
2 .bss 00000000 00000000 00000000 00000034 2**0
ALLOC
3 .newaddfunc 00000044 00000000 00000000 00000034 2**2
CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE
4 .rodata 00000024 00000000 00000000 00000078 2**2
CONTENTS, ALLOC, LOAD, READONLY, DATA
5 .comment 00000045 00000000 00000000 0000009c 2**0
CONTENTS, READONLY
6 .ARM.attributes 0000002a 00000000 00000000 000000e1 2**0
CONTENTS, READONLY
here you can see that the .text section size is 0, because all the .text section is moved into .newaddfunc (but only that).
arm-none-eabi-objdump -d --section=.newaddfunc new_function.o
new_function.o: file format elf32-littlearm
Disassembly of section .newaddfunc:
00000000 <new_function>:
0: e52db004 push {fp} @ (str fp, [sp, #-4]!)
4: e28db000 add fp, sp, #0
8: e24dd00c sub sp, sp, #12
c: e3a03000 mov r3, #0
10: e50b3008 str r3, [fp, #-8]
14: ea000002 b 24 <new_function+0x24>
18: e51b3008 ldr r3, [fp, #-8]
1c: e2833001 add r3, r3, #1
20: e50b3008 str r3, [fp, #-8]
24: e51b3008 ldr r3, [fp, #-8]
28: e3530063 cmp r3, #99 @ 0x63
2c: dafffff9 ble 18 <new_function+0x18>
30: e1a00000 nop @ (mov r0, r0)
34: e1a00000 nop @ (mov r0, r0)
38: e28bd000 add sp, fp, #0
3c: e49db004 pop {fp} @ (ldr fp, [sp], #4)
40: e12fff1e bx lr
instead in the symbol table of .rodata:
arm-none-eabi-objdump -x --section=.rodata new_function.o
SYMBOL TABLE:
00000000 l d .rodata 00000000 .rodata
00000000 l O .rodata 00000014 new_array2.1
00000014 l O .rodata 00000010 new_array1.0
here, the .rodata contains the read-only arrays of the new_function() method.
So when you link it with the library the .rodata arrays of new_function() are going to be put together with all the other .rodata sections and so it will also be in .tool_sec, because of:
KEEP(*libtools_static.a: (.rodata* .srodata*))
here you can see that right now the read-only arrays of new_function() are inside .tool_sec
arm-none-eabi-objdump -d --section=.tool_sec main.elf
main.elf: file format elf32-littlearm
Disassembly of section .tool_sec:
20000000 <FUNCTION_A>:
20000000: e52db004 push {fp} @ (str fp, [sp, #-4]!)
20000004: e28db000 add fp, sp, #0
20000008: e24dd014 sub sp, sp, #20
2000000c: e51b2008 ldr r2, [fp, #-8]
20000010: e51b300c ldr r3, [fp, #-12]
20000014: e0823003 add r3, r2, r3
20000018: e50b3010 str r3, [fp, #-16]
2000001c: e1a00000 nop @ (mov r0, r0)
20000020: e28bd000 add sp, fp, #0
20000024: e49db004 pop {fp} @ (ldr fp, [sp], #4)
20000028: e12fff1e bx lr
2000002c <ARRAY_B>:
...
20000048 <new_array2.1>:
...
2000005c <new_array1.0>:
...
One way to avoid it is to mark the read-only array as a new section (not .newaddfunc because is a .text section and will give you errors), in this way:
__attribute__((section(".newaddfunc")))
void new_function(void) {
for (int i = 0; i < 100; i++)
{
}
__attribute__((section(".newaddfunc_rodata")))
static const uint8_t new_array1[16] = {0};
__attribute__((section(".newaddfunc_rodata")))
static const uint8_t new_array2[20] = {0};
}
here now you can see:
Sections:
Idx Name Size VMA LMA File off Algn
0 .text 00000000 00000000 00000000 00000034 2**0
CONTENTS, ALLOC, LOAD, READONLY, CODE
1 .data 00000000 00000000 00000000 00000034 2**0
CONTENTS, ALLOC, LOAD, DATA
2 .bss 00000000 00000000 00000000 00000034 2**0
ALLOC
3 .newaddfunc 00000044 00000000 00000000 00000034 2**2
CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE
4 .newaddfunc_rodata 00000024 00000000 00000000 00000078 2**2
CONTENTS, ALLOC, LOAD, READONLY, DATA
5 .comment 00000045 00000000 00000000 0000009c 2**0
CONTENTS, READONLY
6 .ARM.attributes 0000002a 00000000 00000000 000000e1 2**0
CONTENTS, READONLY
No more .rodata section, because all the read-only arrays are moved into .newaddfunc_rodata.
and if i check the .toolsec:
arm-none-eabi-objdump -d --section=.tool_sec main.elf
main.elf: file format elf32-littlearm
Disassembly of section .tool_sec:
20000000 <FUNCTION_A>:
20000000: e52db004 push {fp} @ (str fp, [sp, #-4]!)
20000004: e28db000 add fp, sp, #0
20000008: e24dd014 sub sp, sp, #20
2000000c: e51b2008 ldr r2, [fp, #-8]
20000010: e51b300c ldr r3, [fp, #-12]
20000014: e0823003 add r3, r2, r3
20000018: e50b3010 str r3, [fp, #-16]
2000001c: e1a00000 nop @ (mov r0, r0)
20000020: e28bd000 add sp, fp, #0
20000024: e49db004 pop {fp} @ (ldr fp, [sp], #4)
20000028: e12fff1e bx lr
2000002c <ARRAY_B>:
...
So in this way you have no more read-only arrays in .tool_sec.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With