CompilerCrash via llvm-dev
2019-Aug-31 07:22 UTC
[llvm-dev] Usage of the jumptable attribute
Hello everyone, I'm new to LLVM (which is a really great project by the way) and I hope this is the right place for my question. In the LLVM Language Reference Manual I found the "jumptable" function attribute, which seems to be exactly what I need for my project (where I want to add one level of indirection to every function call), but I have trouble figuring out, how to use it correctly. I wrote my own transformation pass (using LLVM 8.0.1) to add this attribute as well as unnamed_addr (I'm aware that this might break some programs, but jumptable requires it) to every function definition: // includes ... using namespace llvm; namespace { struct MyPass : public ModulePass { static char ID; MyPass() : ModulePass(ID) {} bool runOnModule(Module &M) override { for (Function &F : M.getFunctionList()) { if (!F.isDeclaration()) { F.setUnnamedAddr(GlobalValue::UnnamedAddr::Global); F.addFnAttr(Attribute::JumpTable); } } return true; } }; } char MyPass::ID = 0; static RegisterPass<MyPass> X("mypass", "My Pass"); And I wrote a program test.c: #include <stdio.h> void foo() { puts("Hello World"); } int main() { foo(); } I compiled it to test.ll and ran it through opt: clang -O0 -emit-llvm -S -o test.ll test.c build/bin/opt -load build/lib/LLVMMyPass.so -mypass -S -o test.out.ll test.ll The output (test.out.ll) was identical to test.ll except for the 3 occurrences of jumptable and the last 2 occurrences of unnamed_addr: ; ModuleID = 'test.ll' source_filename = "test.c" target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" target triple = "x86_64-unknown-linux-gnu" @.str = private unnamed_addr constant [12 x i8] c"Hello World\00", align 1 ; Function Attrs: jumptable noinline nounwind optnone uwtable define dso_local void @foo() unnamed_addr #0 { %1 = call i32 @puts(i8* getelementptr inbounds ([12 x i8], [12 x i8]* @.str, i32 0, i32 0)) ret void } declare dso_local i32 @puts(i8*) #1 ; Function Attrs: jumptable noinline nounwind optnone uwtable define dso_local i32 @main() unnamed_addr #0 { call void @foo() ret i32 0 } attributes #0 = { jumptable noinline nounwind optnone uwtable "no-jump-tables"="false" ; ... many more attributes ... } attributes #1 = { ; ... many more attributes ... } !llvm.module.flags = !{!0} !llvm.ident = !{!1} !0 = !{i32 1, !"wchar_size", i32 4} !1 = !{!"clang version 8.0.0 (tags/RELEASE_800/final)"} Finally, I executed: build/bin/llc -o test.out.s test.out.ll clang -o test.out.native test.out.s objdump --disassemble-all test.out.native I hoped to see some kind of jump table being used for the call to foo (maybe even the plt mechanism the dynamic library calls use), but it is just a "normal" jump to foo's address: 0000000000400500 <foo>: 400500: 55 push %rbp 400501: 48 89 e5 mov %rsp,%rbp 400504: 48 bf c0 05 40 00 00 movabs $0x4005c0,%rdi 40050b: 00 00 00 40050e: e8 cd fe ff ff callq 4003e0 <puts at plt> 400513: 5d pop %rbp 400514: c3 retq 400515: 66 2e 0f 1f 84 00 00 nopw %cs:0x0(%rax,%rax,1) 40051c: 00 00 00 40051f: 90 nop 0000000000400520 <main>: 400520: 55 push %rbp 400521: 48 89 e5 mov %rsp,%rbp 400524: e8 d7 ff ff ff callq 400500 <foo> 400529: 31 c0 xor %eax,%eax 40052b: 5d pop %rbp 40052c: c3 retq 40052d: 0f 1f 00 nopl (%rax) So, what am I doing wrong? The documentation indicates that the jump table is created at code-generation time. So I guess my pass works fine and I just need to get the code generator to process the jumptable attribute somehow? I found the createJumpInstrTablesPass in include/CodeGen/Passes.h, but it seems like it's never used. Thanks in advance Daniel
Krzysztof Parzyszek via llvm-dev
2019-Sep-04 13:08 UTC
[llvm-dev] Usage of the jumptable attribute
Hi Daniel, This attribute doesn't do anything anymore. It was added a while back to implement control flow integrity, but that work was eventually removed. I believe it's still there for backwards compatibility (i.e. to read old bitcode). -- Krzysztof Parzyszek kparzysz at quicinc.com AI tools development> -----Original Message----- > From: llvm-dev <llvm-dev-bounces at lists.llvm.org> On Behalf Of CompilerCrash > via llvm-dev > Sent: Saturday, August 31, 2019 2:22 AM > To: llvm-dev at lists.llvm.org > Subject: [EXT] [llvm-dev] Usage of the jumptable attribute > > Hello everyone, > > I'm new to LLVM (which is a really great project by the way) and I hope this > is the right place for my question. > > In the LLVM Language Reference Manual I found the "jumptable" function > attribute, which seems to be exactly what I need for my project (where I want > to add one level of indirection to every function call), but I have trouble > figuring out, how to use it correctly. > > I wrote my own transformation pass (using LLVM 8.0.1) to add this attribute > as well as unnamed_addr (I'm aware that this might break some programs, but > jumptable requires it) to every function definition: > > // includes ... > > using namespace llvm; > > namespace { > struct MyPass : public ModulePass { > static char ID; > MyPass() : ModulePass(ID) {} > > bool runOnModule(Module &M) override { > for (Function &F : M.getFunctionList()) { > if (!F.isDeclaration()) { > F.setUnnamedAddr(GlobalValue::UnnamedAddr::Global); > F.addFnAttr(Attribute::JumpTable); > } > } > return true; > } > }; > } > > char MyPass::ID = 0; > static RegisterPass<MyPass> X("mypass", "My Pass"); > > And I wrote a program test.c: > > #include <stdio.h> > > void foo() { > puts("Hello World"); > } > > int main() { > foo(); > } > > I compiled it to test.ll and ran it through opt: > > clang -O0 -emit-llvm -S -o test.ll test.c > build/bin/opt -load build/lib/LLVMMyPass.so -mypass -S -o test.out.ll > test.ll > > The output (test.out.ll) was identical to test.ll except for the 3 > occurrences of jumptable and the last 2 occurrences of unnamed_addr: > > ; ModuleID = 'test.ll' > source_filename = "test.c" > target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" > target triple = "x86_64-unknown-linux-gnu" > > @.str = private unnamed_addr constant [12 x i8] c"Hello World\00", align > 1 > > ; Function Attrs: jumptable noinline nounwind optnone uwtable > define dso_local void @foo() unnamed_addr #0 { > %1 = call i32 @puts(i8* getelementptr inbounds ([12 x i8], [12 x > i8]* @.str, i32 0, i32 0)) > ret void > } > > declare dso_local i32 @puts(i8*) #1 > > ; Function Attrs: jumptable noinline nounwind optnone uwtable > define dso_local i32 @main() unnamed_addr #0 { > call void @foo() > ret i32 0 > } > > attributes #0 = { jumptable noinline nounwind optnone uwtable "no-jump- > tables"="false" > ; ... many more attributes ... > } > attributes #1 = { > ; ... many more attributes ... > } > > !llvm.module.flags = !{!0} > !llvm.ident = !{!1} > > !0 = !{i32 1, !"wchar_size", i32 4} > !1 = !{!"clang version 8.0.0 (tags/RELEASE_800/final)"} > > Finally, I executed: > > build/bin/llc -o test.out.s test.out.ll > clang -o test.out.native test.out.s > objdump --disassemble-all test.out.native > > I hoped to see some kind of jump table being used for the call to foo (maybe > even the plt mechanism the dynamic library calls use), but it is just a > "normal" jump to foo's address: > > 0000000000400500 <foo>: > 400500: 55 push %rbp > 400501: 48 89 e5 mov %rsp,%rbp > 400504: 48 bf c0 05 40 00 00 movabs $0x4005c0,%rdi > 40050b: 00 00 00 > 40050e: e8 cd fe ff ff callq 4003e0 <puts at plt> > 400513: 5d pop %rbp > 400514: c3 retq > 400515: 66 2e 0f 1f 84 00 00 nopw %cs:0x0(%rax,%rax,1) > 40051c: 00 00 00 > 40051f: 90 nop > > 0000000000400520 <main>: > 400520: 55 push %rbp > 400521: 48 89 e5 mov %rsp,%rbp > 400524: e8 d7 ff ff ff callq 400500 <foo> > 400529: 31 c0 xor %eax,%eax > 40052b: 5d pop %rbp > 40052c: c3 retq > 40052d: 0f 1f 00 nopl (%rax) > > So, what am I doing wrong? The documentation indicates that the jump table is > created at code-generation time. So I guess my pass works fine and I just > need to get the code generator to process the jumptable attribute somehow? I > found the createJumpInstrTablesPass in include/CodeGen/Passes.h, but it seems > like it's never used. > > Thanks in advance > > Daniel > _______________________________________________ > LLVM Developers mailing list > llvm-dev at lists.llvm.org > https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev
> -----Original Message----- > From: llvm-dev [mailto:llvm-dev-bounces at lists.llvm.org] On Behalf Of > Krzysztof Parzyszek via llvm-dev > Sent: Wednesday, September 04, 2019 9:08 AM > To: CompilerCrash; llvm-dev at lists.llvm.org > Subject: Re: [llvm-dev] Usage of the jumptable attribute > > Hi Daniel, > This attribute doesn't do anything anymore. It was added a while back to > implement control flow integrity, but that work was eventually removed. I > believe it's still there for backwards compatibility (i.e. to read old > bitcode).In that case, shouldn't you update the LangRef to say so? --paulr> > -- > Krzysztof Parzyszek kparzysz at quicinc.com AI tools development > > > -----Original Message----- > > From: llvm-dev <llvm-dev-bounces at lists.llvm.org> On Behalf Of > CompilerCrash > > via llvm-dev > > Sent: Saturday, August 31, 2019 2:22 AM > > To: llvm-dev at lists.llvm.org > > Subject: [EXT] [llvm-dev] Usage of the jumptable attribute > > > > Hello everyone, > > > > I'm new to LLVM (which is a really great project by the way) and I hope > this > > is the right place for my question. > > > > In the LLVM Language Reference Manual I found the "jumptable" function > > attribute, which seems to be exactly what I need for my project (where I > want > > to add one level of indirection to every function call), but I have > trouble > > figuring out, how to use it correctly. > > > > I wrote my own transformation pass (using LLVM 8.0.1) to add this > attribute > > as well as unnamed_addr (I'm aware that this might break some programs, > but > > jumptable requires it) to every function definition: > > > > // includes ... > > > > using namespace llvm; > > > > namespace { > > struct MyPass : public ModulePass { > > static char ID; > > MyPass() : ModulePass(ID) {} > > > > bool runOnModule(Module &M) override { > > for (Function &F : M.getFunctionList()) { > > if (!F.isDeclaration()) { > > F.setUnnamedAddr(GlobalValue::UnnamedAddr::Global); > > F.addFnAttr(Attribute::JumpTable); > > } > > } > > return true; > > } > > }; > > } > > > > char MyPass::ID = 0; > > static RegisterPass<MyPass> X("mypass", "My Pass"); > > > > And I wrote a program test.c: > > > > #include <stdio.h> > > > > void foo() { > > puts("Hello World"); > > } > > > > int main() { > > foo(); > > } > > > > I compiled it to test.ll and ran it through opt: > > > > clang -O0 -emit-llvm -S -o test.ll test.c > > build/bin/opt -load build/lib/LLVMMyPass.so -mypass -S -o > test.out.ll > > test.ll > > > > The output (test.out.ll) was identical to test.ll except for the 3 > > occurrences of jumptable and the last 2 occurrences of unnamed_addr: > > > > ; ModuleID = 'test.ll' > > source_filename = "test.c" > > target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" > > target triple = "x86_64-unknown-linux-gnu" > > > > @.str = private unnamed_addr constant [12 x i8] c"Hello World\00", > align > > 1 > > > > ; Function Attrs: jumptable noinline nounwind optnone uwtable > > define dso_local void @foo() unnamed_addr #0 { > > %1 = call i32 @puts(i8* getelementptr inbounds ([12 x i8], [12 x > > i8]* @.str, i32 0, i32 0)) > > ret void > > } > > > > declare dso_local i32 @puts(i8*) #1 > > > > ; Function Attrs: jumptable noinline nounwind optnone uwtable > > define dso_local i32 @main() unnamed_addr #0 { > > call void @foo() > > ret i32 0 > > } > > > > attributes #0 = { jumptable noinline nounwind optnone uwtable "no- > jump- > > tables"="false" > > ; ... many more attributes ... > > } > > attributes #1 = { > > ; ... many more attributes ... > > } > > > > !llvm.module.flags = !{!0} > > !llvm.ident = !{!1} > > > > !0 = !{i32 1, !"wchar_size", i32 4} > > !1 = !{!"clang version 8.0.0 (tags/RELEASE_800/final)"} > > > > Finally, I executed: > > > > build/bin/llc -o test.out.s test.out.ll > > clang -o test.out.native test.out.s > > objdump --disassemble-all test.out.native > > > > I hoped to see some kind of jump table being used for the call to foo > (maybe > > even the plt mechanism the dynamic library calls use), but it is just a > > "normal" jump to foo's address: > > > > 0000000000400500 <foo>: > > 400500: 55 push %rbp > > 400501: 48 89 e5 mov %rsp,%rbp > > 400504: 48 bf c0 05 40 00 00 movabs $0x4005c0,%rdi > > 40050b: 00 00 00 > > 40050e: e8 cd fe ff ff callq 4003e0 <puts at plt> > > 400513: 5d pop %rbp > > 400514: c3 retq > > 400515: 66 2e 0f 1f 84 00 00 nopw %cs:0x0(%rax,%rax,1) > > 40051c: 00 00 00 > > 40051f: 90 nop > > > > 0000000000400520 <main>: > > 400520: 55 push %rbp > > 400521: 48 89 e5 mov %rsp,%rbp > > 400524: e8 d7 ff ff ff callq 400500 <foo> > > 400529: 31 c0 xor %eax,%eax > > 40052b: 5d pop %rbp > > 40052c: c3 retq > > 40052d: 0f 1f 00 nopl (%rax) > > > > So, what am I doing wrong? The documentation indicates that the jump > table is > > created at code-generation time. So I guess my pass works fine and I > just > > need to get the code generator to process the jumptable attribute > somehow? I > > found the createJumpInstrTablesPass in include/CodeGen/Passes.h, but it > seems > > like it's never used. > > > > Thanks in advance > > > > Daniel > > _______________________________________________ > > LLVM Developers mailing list > > llvm-dev at lists.llvm.org > > https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev > _______________________________________________ > LLVM Developers mailing list > llvm-dev at lists.llvm.org > https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev
CompilerCrash via llvm-dev
2019-Sep-04 17:09 UTC
[llvm-dev] Usage of the jumptable attribute
Hi Krzysztof, thank you for your reply. That explains a lot. I wonder if it is possible to let llvm create plt entries for user-written functions as if they were dynamic library functions. Does anyone know? Best Daniel Am 04.09.2019 um 15:08 schrieb Krzysztof Parzyszek:> Hi Daniel, > This attribute doesn't do anything anymore. It was added a while back to implement control flow integrity, but that work was eventually removed. I believe it's still there for backwards compatibility (i.e. to read old bitcode). > > -- > Krzysztof Parzyszek kparzysz at quicinc.com AI tools development > >> -----Original Message----- >> From: llvm-dev <llvm-dev-bounces at lists.llvm.org> On Behalf Of CompilerCrash >> via llvm-dev >> Sent: Saturday, August 31, 2019 2:22 AM >> To: llvm-dev at lists.llvm.org >> Subject: [EXT] [llvm-dev] Usage of the jumptable attribute >> >> Hello everyone, >> >> I'm new to LLVM (which is a really great project by the way) and I hope this >> is the right place for my question. >> >> In the LLVM Language Reference Manual I found the "jumptable" function >> attribute, which seems to be exactly what I need for my project (where I want >> to add one level of indirection to every function call), but I have trouble >> figuring out, how to use it correctly. >> >> I wrote my own transformation pass (using LLVM 8.0.1) to add this attribute >> as well as unnamed_addr (I'm aware that this might break some programs, but >> jumptable requires it) to every function definition: >> >> // includes ... >> >> using namespace llvm; >> >> namespace { >> struct MyPass : public ModulePass { >> static char ID; >> MyPass() : ModulePass(ID) {} >> >> bool runOnModule(Module &M) override { >> for (Function &F : M.getFunctionList()) { >> if (!F.isDeclaration()) { >> F.setUnnamedAddr(GlobalValue::UnnamedAddr::Global); >> F.addFnAttr(Attribute::JumpTable); >> } >> } >> return true; >> } >> }; >> } >> >> char MyPass::ID = 0; >> static RegisterPass<MyPass> X("mypass", "My Pass"); >> >> And I wrote a program test.c: >> >> #include <stdio.h> >> >> void foo() { >> puts("Hello World"); >> } >> >> int main() { >> foo(); >> } >> >> I compiled it to test.ll and ran it through opt: >> >> clang -O0 -emit-llvm -S -o test.ll test.c >> build/bin/opt -load build/lib/LLVMMyPass.so -mypass -S -o test.out.ll >> test.ll >> >> The output (test.out.ll) was identical to test.ll except for the 3 >> occurrences of jumptable and the last 2 occurrences of unnamed_addr: >> >> ; ModuleID = 'test.ll' >> source_filename = "test.c" >> target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" >> target triple = "x86_64-unknown-linux-gnu" >> >> @.str = private unnamed_addr constant [12 x i8] c"Hello World\00", align >> 1 >> >> ; Function Attrs: jumptable noinline nounwind optnone uwtable >> define dso_local void @foo() unnamed_addr #0 { >> %1 = call i32 @puts(i8* getelementptr inbounds ([12 x i8], [12 x >> i8]* @.str, i32 0, i32 0)) >> ret void >> } >> >> declare dso_local i32 @puts(i8*) #1 >> >> ; Function Attrs: jumptable noinline nounwind optnone uwtable >> define dso_local i32 @main() unnamed_addr #0 { >> call void @foo() >> ret i32 0 >> } >> >> attributes #0 = { jumptable noinline nounwind optnone uwtable "no-jump- >> tables"="false" >> ; ... many more attributes ... >> } >> attributes #1 = { >> ; ... many more attributes ... >> } >> >> !llvm.module.flags = !{!0} >> !llvm.ident = !{!1} >> >> !0 = !{i32 1, !"wchar_size", i32 4} >> !1 = !{!"clang version 8.0.0 (tags/RELEASE_800/final)"} >> >> Finally, I executed: >> >> build/bin/llc -o test.out.s test.out.ll >> clang -o test.out.native test.out.s >> objdump --disassemble-all test.out.native >> >> I hoped to see some kind of jump table being used for the call to foo (maybe >> even the plt mechanism the dynamic library calls use), but it is just a >> "normal" jump to foo's address: >> >> 0000000000400500 <foo>: >> 400500: 55 push %rbp >> 400501: 48 89 e5 mov %rsp,%rbp >> 400504: 48 bf c0 05 40 00 00 movabs $0x4005c0,%rdi >> 40050b: 00 00 00 >> 40050e: e8 cd fe ff ff callq 4003e0 <puts at plt> >> 400513: 5d pop %rbp >> 400514: c3 retq >> 400515: 66 2e 0f 1f 84 00 00 nopw %cs:0x0(%rax,%rax,1) >> 40051c: 00 00 00 >> 40051f: 90 nop >> >> 0000000000400520 <main>: >> 400520: 55 push %rbp >> 400521: 48 89 e5 mov %rsp,%rbp >> 400524: e8 d7 ff ff ff callq 400500 <foo> >> 400529: 31 c0 xor %eax,%eax >> 40052b: 5d pop %rbp >> 40052c: c3 retq >> 40052d: 0f 1f 00 nopl (%rax) >> >> So, what am I doing wrong? The documentation indicates that the jump table is >> created at code-generation time. So I guess my pass works fine and I just >> need to get the code generator to process the jumptable attribute somehow? I >> found the createJumpInstrTablesPass in include/CodeGen/Passes.h, but it seems >> like it's never used. >> >> Thanks in advance >> >> Daniel >> _______________________________________________ >> LLVM Developers mailing list >> llvm-dev at lists.llvm.org >> https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev