Bug 29012 - gas: .set should copy st_size only if src's st_size is unset
Summary: gas: .set should copy st_size only if src's st_size is unset
Status: RESOLVED FIXED
Alias: None
Product: binutils
Classification: Unclassified
Component: gas (show other bugs)
Version: unspecified
: P2 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2022-03-31 03:35 UTC by Fangrui Song
Modified: 2022-04-29 23:17 UTC (History)
1 user (show)

See Also:
Host:
Target:
Build:
Last reconfirmed:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Fangrui Song 2022-03-31 03:35:59 UTC
For
```
.size foo1, 1
foo1:
 
.set bar1, foo1
.size bar1, 2
.size bar2, 2
.set bar2, foo1
 
.set bar3, foo2
.size bar3, 2
.size bar4, 2
.set bar4, foo2
 
.size foo2, 1
foo2:
```
 
bar1's size is 2 while bar2, bar3, bar4's is 1. The behavior of bar1 makes sense
(generally directives on the new symbol should win) and is relied upon by glibc
stdio-common/errlist.c:
 
```
        .hidden _sys_errlist_internal
        .globl  _sys_errlist_internal
        .type   _sys_errlist_internal, @object
        .size   _sys_errlist_internal, 1072
_sys_errlist_internal:
 
        .globl __GLIBC_2_1_sys_errlist
        .set __GLIBC_2_1_sys_errlist, _sys_errlist_internal
        .type __GLIBC_2_1_sys_errlist, %object
        .size __GLIBC_2_1_sys_errlist, 125 * (64 / 8)
 
// glibc expects that .size __GLIBC_2_1_sys_errlist, 125 * (64 / 8) wins.
```
 
The behavior of bar2/bar3/bar4 seems brittle. To avoid the reordering of the two
code blocks which will result in the bar3 situation, glibc compiles errlist.c
with gcc -fno-toplevel-reorder (previously -fno-unit-at-a-time).
 
To fix the inconsistency and improve robustness, I think we should make bar2/bar3/bar4 match bar1, removing the directive order sensitivity.

There is a pity that `.size dest, 0` is indistinguishable from the case where
dest is unset, but it should be fine.
Comment 2 Sourceware Commits 2022-04-04 15:45:25 UTC
The master branch has been updated by Fangrui Song <maskray@sourceware.org>:

https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=867b8c308a40e79f90db4051cafc273f00f881fb

commit 867b8c308a40e79f90db4051cafc273f00f881fb
Author: Fangrui Song <i@maskray.me>
Date:   Mon Apr 4 08:43:50 2022 -0700

    gas: copy st_size only if unset
    
    For
    ```
    .size foo1, 1
    foo1:
    
    .set bar1, foo1
    .size bar1, 2
    .size bar2, 2
    .set bar2, foo1
    
    .set bar3, foo2
    .size bar3, 2
    .size bar4, 2
    .set bar4, foo2
    
    .size foo2, 1
    foo2:
    ```
    
    bar1's size is 2 while bar2, bar3, bar4's is 1. The behavior of bar1 makes sense
    (generally directives on the new symbol should win) and is relied upon by glibc
    stdio-common/errlist.c:
    
    ```
            .hidden _sys_errlist_internal
            .globl  _sys_errlist_internal
            .type   _sys_errlist_internal, @object
            .size   _sys_errlist_internal, 1072
    _sys_errlist_internal:
    
            .globl __GLIBC_2_1_sys_errlist
            .set __GLIBC_2_1_sys_errlist, _sys_errlist_internal
            .type __GLIBC_2_1_sys_errlist, %object
            .size __GLIBC_2_1_sys_errlist, 125 * (64 / 8)
    
    // glibc expects that .size __GLIBC_2_1_sys_errlist, 125 * (64 / 8) wins.
    ```
    
    The behavior of bar2/bar3/bar4 seems brittle. To avoid the reordering of the two
    code blocks which will result in the bar3 situation, glibc compiles errlist.c
    with gcc -fno-toplevel-reorder (previously -fno-unit-at-a-time).
    
    To fix the inconsistency and improve robustness, make bar2/bar3/bar4 match bar1,
    removing the directive order sensitivity.
    
    There is a pity that `.size dest, 0` is indistinguishable from the case where
    dest is unset, but the compromise seems fine.
    
        PR gas/29012
        * config/obj-elf.c (elf_copy_symbol_attributes): don't copy if src's size
          has been set.
        * testsuite/gas/elf/elf.exp: New test.
        * testsuite/gas/elf/size.d: New file.
        * testsuite/gas/elf/size.s: Likewise.
Comment 3 Fangrui Song 2022-04-04 15:51:30 UTC
Target milestone: 2.39