Moritz Angermann via llvm-dev
2017-Mar-06 09:40 UTC
[llvm-dev] [BUG Report] -dead_strip, strips prefix data unconditionally on macOS
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
James Y Knight via llvm-dev
2017-Mar-06 19:19 UTC
[llvm-dev] [BUG Report] -dead_strip, strips prefix data unconditionally on macOS
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 >-------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20170306/9bc3748a/attachment.html>
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>
Mehdi Amini via llvm-dev
2017-Mar-06 20:05 UTC
[llvm-dev] [BUG Report] -dead_strip, strips prefix data unconditionally on macOS
> On 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.Even disassembling dead-code stripping, how can you guarantee that the linker won’t change the order in which atoms are laid out? — Mehdi> > 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 > 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/ace68cb4/attachment.html>
Moritz Angermann via llvm-dev
2017-Mar-07 01:42 UTC
[llvm-dev] [BUG Report] -dead_strip, strips prefix data unconditionally on macOS
Hi James, this is the route we just went. We simply post process the generated assembly and strip out the .subsections_via_symbols. Quite ugly, I must say. However we did some post asm mangling already, so this was rather straight forward to implement: https://phabricator.haskell.org/D3287 However the drawback is that on any mach-o platform, you now don’t get the benefit of -dead_code stripping if you use prefix data. And this might for, say iOS, not be such a great deal. Cheers, Moritz> On Mar 7, 2017, at 3:19 AM, James Y Knight <jyknight at google.com> 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 >
Reasonably Related Threads
- [BUG Report] -dead_strip, strips prefix data unconditionally on macOS
- [BUG Report] -dead_strip, strips prefix data unconditionally on macOS
- [BUG Report] -dead_strip, strips prefix data unconditionally on macOS
- [BUG Report] -dead_strip, strips prefix data unconditionally on macOS
- [BUG Report] -dead_strip, strips prefix data unconditionally on macOS