Peter Collingbourne via llvm-dev
2017-Mar-06 19:35 UTC
[llvm-dev] [BUG Report] -dead_strip, strips prefix data unconditionally on macOS
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 -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20170306/5d6ede48/attachment.html>
Moritz Angermann via llvm-dev
2017-Mar-07 01:54 UTC
[llvm-dev] [BUG Report] -dead_strip, strips prefix data unconditionally on macOS
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 _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. 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 Collingbourne via llvm-dev
2017-Mar-07 02:02 UTC
[llvm-dev] [BUG Report] -dead_strip, strips prefix data unconditionally on macOS
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_stripdirective. 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>
James Y Knight via llvm-dev
2017-Mar-07 03:56 UTC
[llvm-dev] [BUG Report] -dead_strip, strips prefix data unconditionally on macOS
Oh, that's great that it's possible to implement properly, now. Does it actually work for It'd be cool if LLVM hooked up its generic section handling support to this feature now, so that the only global symbols that *didn't* get marked as .alt_entry were those at the beginning of what llvm would consider sections. Then apple platforms could behave sanely, like all other platforms do, only with -f{function,data}-sections defaulted to on instead of off. (That is, if you specify -fno-function-sections -fno-data-sections, it could mark nearly *everything* as .alt_entry -- except the first symbol in the object file) On Mon, Mar 6, 2017 at 2:35 PM, 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 >-------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20170306/1101bcac/attachment.html>
James Y Knight via llvm-dev
2017-Mar-07 03:59 UTC
[llvm-dev] [BUG Report] -dead_strip, strips prefix data unconditionally on macOS
On Mar 6, 2017 10:56 PM, "James Y Knight" <jyknight at google.com> wrote: Oh, that's great that it's possible to implement properly, now. Does it actually work for (Oops forgot to finish the sentence) ... symbols in data sections, as well as text? It'd be cool if LLVM hooked up its generic section handling support to this feature now, so that the only global symbols that *didn't* get marked as .alt_entry were those at the beginning of what llvm would consider sections. Then apple platforms could behave sanely, like all other platforms do, only with -f{function,data}-sections defaulted to on instead of off. (That is, if you specify -fno-function-sections -fno-data-sections, it could mark nearly *everything* as .alt_entry -- except the first symbol in the object file) On Mon, Mar 6, 2017 at 2:35 PM, 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 >-------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20170306/3425dfad/attachment.html>
Mehdi Amini via llvm-dev
2017-Mar-07 06:12 UTC
[llvm-dev] [BUG Report] -dead_strip, strips prefix data unconditionally on macOS
> On Mar 6, 2017, at 7:56 PM, James Y Knight via llvm-dev <llvm-dev at lists.llvm.org> wrote: > > Oh, that's great that it's possible to implement properly, now. Does it actually work for > > It'd be cool if LLVM hooked up its generic section handling support to this feature now, so that the only global symbols that *didn't* get marked as .alt_entry were those at the beginning of what llvm would consider sections. > > Then apple platforms could behave sanely, like all other platforms do, only with -f{function,data}-sections defaulted to on instead of off.What is the advantage of not using -f{function,data}-sections? (i.e. what isn’t sane about it?) I’m asking because I was told the only reason not to use it all the time on ELF is that it makes intermediate object files larger. Thanks, — Mehdi> > (That is, if you specify -fno-function-sections -fno-data-sections, it could mark nearly *everything* as .alt_entry -- except the first symbol in the object file) > > > On Mon, Mar 6, 2017 at 2:35 PM, Peter Collingbourne <peter at pcc.me.uk <mailto: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 <mailto: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 <mailto: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 <mailto:llvm-dev at lists.llvm.org> > http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev <http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev> > > > _______________________________________________ > LLVM Developers mailing list > llvm-dev at lists.llvm.org <mailto:llvm-dev at lists.llvm.org> > http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev <http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev> > > > > > -- > -- > Peter > > _______________________________________________ > LLVM Developers mailing list > llvm-dev at lists.llvm.org > http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev-------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20170306/f7847b21/attachment.html>
Sean Silva via llvm-dev
2017-Mar-09 03:14 UTC
[llvm-dev] [BUG Report] -dead_strip, strips prefix data unconditionally on macOS
When I was at PlayStation, I remember that we had a proprietary linker with the subsections-via-symbols behavior. To avoid private patches in the LLVM backend due to this, Rafael came up with a design (and I think did quite a bit of refactoring upstream to enable it, though I think it applied only to ELF) where subsections-via-symbols could be implemented in terms of -ffunctions-sections/-fdata-sections. IIRC, essentially the model was that everything was done the same as in -ffunction-sections/-fdata-sections but at the very end only a single section header was emitted (and things were inherently laid out in such a way that this was a valid thing to do). In otherwords, the subsections-via-symbols behavior was clearly implemented as basically an optimization to eliminate the need for large numbers of sections (when the linker could be assumed to do subsections-via-symbols), but otherwise didn't affect the rest of the implementation. -- Sean Silva On Mon, Mar 6, 2017 at 7:56 PM, James Y Knight via llvm-dev < llvm-dev at lists.llvm.org> wrote:> Oh, that's great that it's possible to implement properly, now. Does it > actually work for > > It'd be cool if LLVM hooked up its generic section handling support to > this feature now, so that the only global symbols that *didn't* get marked > as .alt_entry were those at the beginning of what llvm would consider > sections. > > Then apple platforms could behave sanely, like all other platforms do, > only with -f{function,data}-sections defaulted to on instead of off. > > (That is, if you specify -fno-function-sections -fno-data-sections, it > could mark nearly *everything* as .alt_entry -- except the first symbol in > the object file) > > > On Mon, Mar 6, 2017 at 2:35 PM, 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 >> > > > _______________________________________________ > LLVM Developers mailing list > llvm-dev at lists.llvm.org > http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev > >-------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20170308/9d5f124f/attachment.html>