Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

section of static library is changed with unkown reason

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?

like image 297
charlie-xue Avatar asked Jan 23 '26 13:01

charlie-xue


1 Answers

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.

like image 74
Giackkk Avatar answered Jan 25 '26 05:01

Giackkk



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!