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

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

 



I think I solved it, I updated the linker script to the below (see new
include of "ltrans.o"). I think I might have run into the same issue that
these folks over at qualcomm has[1]. The linker script references a file,
but after LTO, the filename is gone or changed to "ltrans.o". I cannot find
anything about if this is expected behavior or not with GCC.

[1]: https://groups.google.com/g/llvm-dev/c/jNUFfRGOMUs

```
    ER_NZI (NOLOAD) :
    {
        . = ALIGN(4);
        __heap_mem_area_not_ret_start__ = .;
        *jump_table.o(heap_mem_area_not_ret)    /* not retained HEAP */
*ltrans.o(heap_mem_area_not_ret)
        __heap_mem_area_not_ret_end__ = .;
    } > LR_IROM3
```
- Niklas


On Fri, 27 Sept 2024 at 22:14, Niklas Dusenlund <niklas@xxxxxxxxxxxx> wrote:

> 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