[llvm-dev] [BUG Report] -dead_strip, strips prefix data unconditionally on macOS

Peter Collingbourne via llvm-dev
2017-03-07T02:02:46Z

On Mon, Mar 6, 2017 at 5:54 PM, Moritz Angermann <moritz.angermann at
gmail.com
> wrote:

> Hi Peter,
>
> I’ve just experimented with this a bit:
>
> Say we would end up with the following assembly:
>
>   .section  __TEXT,__text
>   .globl _main
>
>   .long 1
> _main:
>   inc %eax
>   ret
>
>   .globl  _main.dsp
>   .alt_entry      _main.dsp
>

What happens if you try ".alt_entry _main" instead? The alt_entry is
supposed to be bound to the atom appearing *before* it.


> _main.dsp = _main-4
>
>   .subsections_via_symbols
>
> (e.g. we inject the .alt_entry after the fact, pointing to the start of
> the prefix data)
>
> this will yield:
>
> $ clang test.s -dead_strip
> ld: warning: N_ALT_ENTRY bit set on first atom in section __TEXT/__text


> And the prefix data will be stripped again.
>
> E.g. what you end up getting is:
>
> $ otool -vVtdj a.out
> a.out:
> _main:
> 0000000100000fb5        ff c0   incl    %eax
> 0000000100000fb7        c3      retq
>
> instead of what we’d like to get:
>
> otool -vVtdj a.out
> a.out:
> _main.dsp:
> 0000000100000fb1        01 00   addl    %eax, (%rax)
> 0000000100000fb3        00 00   addb    %al, (%rax)
> _main:
> 0000000100000fb5        ff c0   incl    %eax
> 0000000100000fb7        c3      retq
>
> .alt_entry’s are not dead_strip protected, and this makes sense I guess,
> as if the alt_entry is never
> actually called visibly from anywhere, it’s probably not needed. However
> there is the .no_daed_strip

directive. Thus if we graft this slightly different:
>
>   .section  __TEXT,__text
>   .globl _main
>
>   .long 1
> _main:
>   inc %eax
>   ret
>
>   .no_dead_strip  _main.dsp
>   .alt_entry      _main.dsp
> _main.dsp = _main-4
>
>   .subsections_via_symbols
>
> we still get a warning, but it won’t get stripped. At that point however,
> we don’t need the .alt_entry
> anymore (and can drop the warning).
>
> Thus, I’d propose that for functions with prefix_data, a second symbol
> with .no_dead_strip is emitted
> for the prefix data entry point.


I don't think that is sufficient. I believe that the linker is allowed to
move the function away from the prefix data even if the function is not
dead stripped.

Peter


> Cheers,
>  Moritz
>
>
> > On Mar 7, 2017, at 3:35 AM, Peter Collingbourne <peter at
pcc.me.uk> wrote:
> >
> > That is in theory what omitting the .subsections_via_symbols directive
> is supposed to do, but in an experiment I ran a year or two ago I found
> that the Mach-O linker was still dead stripping on symbol boundaries with
> this directive omitted.
> >
> > In any case, a more precise approach has more recently (~a few months
> ago) become possible. There is a relatively new asm directive called
> .altentry that, as I understand it, tells the linker to disregard a given
> symbol as a section boundary (LLVM already uses this for aliases pointing
> into the middle of a global). So what you would do is to use .altentry on
> the function symbol, with an internal symbol appearing before the prefix
> data to ensure that it is not considered part of the body of the previous
> function.
> >
> > Peter
> >
> > On Mon, Mar 6, 2017 at 11:19 AM, James Y Knight via llvm-dev <
> llvm-dev at lists.llvm.org> wrote:
> > AFAIK, this cannot actually work on Apple platforms, because its
object
> file format (Mach-O) doesn't use sections to determine the ranges of
> code/data to keep together, but instead _infers_ boundaries based on the
> range between global symbols in the symbol table.
> >
> > So, the symbol pointing to the beginning of @main *necessarily* makes
> that be a section boundary.
> >
> > I think the best that could be done in LLVM is to not emit the
> ".subsections_via_symbols" asm directive (effectively disabling
dead
> stripping on that object) if any prefix data exists. Currently it emits
> that flag unconditionally for MachO.
> >
> > On Mon, Mar 6, 2017 at 4:40 AM, Moritz Angermann via llvm-dev <
> llvm-dev at lists.llvm.org> wrote:
> > Hi,
> >
> > I just came across a rather annoying behavior with llvm 3.9. Assuming
> the following
> > samle code in test.ll:
> >
> > ; Lets have some global int x = 4
> > @x = global i32 10, align 4
> > ; and two strings "p = %d\n" for the prefix data,
> > ; as well as "x = %d\n" to print the (global) x value.
> > @.str = private unnamed_addr constant [8 x i8] c"x =
%d\0A\00", align 1
> > @.str2 = private unnamed_addr constant [8 x i8] c"p =
%d\0A\00", align 1
> >
> > ; declare printf, we'll use this later for printf style debugging.
> > declare i32 @printf(i8*, ...)
> >
> > ; define a main function.
> > define i32 @main() prefix i32 123 {
> >   ; obtain a i32 pointer to the main function.
> >   ; the prefix data is right before that pointer.
> >   %main = bitcast i32 ()* @main to i32*
> >
> >   ; use the gep, to cmpute the start of the prefix data.
> >   %prefix_ptr = getelementptr inbounds i32, i32* %main, i32 -1
> >   ; and load it.
> >   %prefix_val = load i32, i32* %prefix_ptr
> >
> >   ; print that value.
> >   %ret = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([8 x
> i8], [8 x i8]* @.str2, i32 0, i32 0), i32 %prefix_val)
> >
> >   ; similarly let's do the same with the global x.
> >   %1 = alloca i32, align 4
> >   store i32 0, i32* %1, align 4
> >   %2 = load i32, i32* @x, align 4
> >   %3 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([8 x
i8],
> [8 x i8]* @.str, i32 0, i32 0), i32 %2)
> >   ret i32 0
> > }
> >
> > gives the following result (expected)
> >
> >    $ clang test.ll
> >    $ ./a.out
> >    p = 123
> >    x = 10
> >
> > however, with -dead_strip on macOS, we see the following:
> >
> >    $ clang test.ll -dead_strip
> >    $ ./a.out
> >    p = 0
> >    x = 10
> >
> > Thus I believe we are incorrectly stripping prefix data when linking
> with -dead_strip on macOS.
> >
> > As I do not have a bugzilla account, and hence cannot post this as a
> proper bug report.
> >
> > Cheers,
> >  Moritz
> > _______________________________________________
> > LLVM Developers mailing list
> > llvm-dev at lists.llvm.org
> > http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev
> >
> >
> > _______________________________________________
> > LLVM Developers mailing list
> > llvm-dev at lists.llvm.org
> > http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev
> >
> >
> >
> >
> > --
> > --
> > Peter
>
>


--
--
Peter
-------------- next part --------------
An HTML attachment was scrubbed...
URL:
<http://lists.llvm.org/pipermail/llvm-dev/attachments/20170306/83ac9f46/attachment.html>