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
Maybe Matching Threads
- [LLVMdev] Question about jumptable and indirect function call.
- [LLVMdev] Unexpected spilling of vector register during lane extraction on some x86_64 targets
- MachineInstr sizes for ARM jumptables
- RFC: Adding a string table to the bitcode format
- [LLVMdev] [RFC] Simple control-flow integrity