Re: LTO and global variables used to create a memory area

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Unfortunately it didn't help in my case. I noticed another hint when I
looked at the final binaries using readelf. It seems when I compile with
LTO the section to segment mapping is off.

Instead of putting `heap_mem_area_not_ret` in `.bss`, it is put in its own
segment. So the variable is there, just not where the rest of the program
expects it to be. Could it be that I have to change something in the linker
script to make it work with LTO?

```
 Section to Segment mapping:
  Segment Sections...
   00     .ARM.exidx
   01     ER_IROM1
   02     ER_IROM2
   03     ER_IROM3 .ARM.exidx .copy.table .zero.table .data .bss ER_NZI
   04     RET_DATA RET_HEAP
   05     RET_DATA_UNINIT_TRNG_STATE
   06
```

```
 Section to Segment mapping:
  Segment Sections...
   00     .ARM.exidx
   01     ER_IROM1
   02     ER_IROM2
   03     ER_IROM3 .ARM.exidx .copy.table .zero.table .data heap_db_area
heap_env_area heap_mem_area_not_ret heap_msg_area trng_state .bss
   04     RET_DATA
   05
```
- Niklas


On Fri, 27 Sept 2024 at 16:19, Richard Earnshaw (lists) <
Richard.Earnshaw@xxxxxxx> wrote:

> On 27/09/2024 14:32, Niklas Dusenlund wrote:
> > Hi!
> >
> > I'm compiling for a cortex-m0 with a very small memory, so I would like
> to
> > use LTO to minimize my program size.
> >
> > I compile all the source files of an SDK to object files. Then I create
> an
> > archive with gcc-ar. Finally I link everything together with gcc.
> > Everything except this global variable works as expected both with and
> > without LTO. I fail to understand why the variable is removed when I
> enable
> > LTO.
> >
> > As you can see in the output maps below, the size in the correct version
> is
> > 0x80c, whereas it is 0 in the bad output.
> >
> > When I look at the object files and archives with gcc-nm they look the
> same
> > with and without -flto.
> >
> > I guess this is a "hack" to define the size of a heap. But if there is
> > another way to achieve the same result I'm all open for it. This memory
> > area is referenced by code that is burned into a ROM at manufacturing
> time.
> > So it is used, but of course GCC doesn't see that.
> >
> > The variable is defined like this:
> >
> > ```
> > uint32_t rwip_heap_non_ret[RWIP_CALC_HEAP_LEN(RWIP_HEAP_NON_RET_SIZE_JT)]
> >  __attribute__((section("heap_mem_area_not_ret")));
>
> When the LTO pass is run, any variable not explicitly referenced in your
> source code will be discarded (LTO doesn't look at the linker script), so
> you need to tell the compiler not to discard it (this doesn't generally
> happen without LTO because the compiler is unable to tell if a variable
> will be referenced by another component in your program, but with LTO we
> can see ALL the code).
>
> So try
> uint32_t rwip_heap_non_ret[RWIP_CALC_HEAP_LEN(RWIP_HEAP_NON_RET_SIZE_JT)]
>  __attribute__((used,section("heap_mem_area_not_ret")));
>
> The extra 'used' attribute tells the compiler that this value is used,
> even if it can't tell where that happens.
>
> A simple testcase demonstrates this:
>
> int __attribute__((used)) x;
> int y;
> int main() { return 0;}
>
> If I build this without LTO (gcc test.c -O3 -o test.exe) I get definitions
> of x and y in my executable, but if I enable LTO (gcc -flto test.c -O3 -o
> test.lto.exe) I only get a definition of x.
>
> nm test.exe
> ...
>
> 0000000000004018 B x
> 0000000000004014 B y
>
> nm test.lto.exe
> ...
> 0000000000004014 B x
>
> R.
>
> > ```
> >
> > It is referenced like this in the linker script:
> > ```
> >     ER_NZI (NOLOAD) :
> >     {
> >         . = ALIGN(4);
> >         __heap_mem_area_not_ret_start__ = .;
> >         *jump_table.o(heap_mem_area_not_ret)    /* not retained HEAP */
> >         __heap_mem_area_not_ret_end__ = .;
> >     } > LR_IROM3
> > ```
> >
> >
> > From the memory map it looks like this when it is correct:
> >
> > ```
> > ER_NZI          0x07fc754c      0x80c
> >                 0x07fc754c                        . = ALIGN (0x4)
> >                 0x07fc754c
> >  __heap_mem_area_not_ret_start__ = .
> >  *jump_table.o(heap_mem_area_not_ret)
> >  heap_mem_area_not_ret
> >                 0x07fc754c      0x80c
> >
> /var/folders/9n/c7ggvkrn03ld13___37y6lcw0000gn/T/rustcqiFzCU/libda14531_sdk.a(2077e224400bc0d4-jump_table.o)
> >                 0x07fc754c                rwip_heap_non_ret
> >                 0x07fc7d58
> >  __heap_mem_area_not_ret_end__ = .
> > ```
> >
> > and this when it is incorrect:
> >
> > ```
> > ER_NZI          0x07fc800c        0x0
> >                 0x07fc800c                        . = ALIGN (0x4)
> >                 0x07fc800c
> >  __heap_mem_area_not_ret_start__ = .
> >  *jump_table.o(heap_mem_area_not_ret)
> >                 0x07fc800c
> >  __heap_mem_area_not_ret_end__ = .
> > ```
> >
> > Ouput of gcc-nm:
> >
> > ```
> > 00000000 D rwip_heap_db_ret
> > 00000000 D rwip_heap_env_ret
> > 00000000 D rwip_heap_msg_ret
> > 00000000 D rwip_heap_non_ret
> > ```
> >
> > - Niklas
>
>



[Index of Archives]     [Linux C Programming]     [Linux Kernel]     [eCos]     [Fedora Development]     [Fedora Announce]     [Autoconf]     [The DWARVES Debugging Tools]     [Yosemite Campsites]     [Yosemite News]     [Linux GCC]

  Powered by Linux