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@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

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).

From: llvm-dev [mailto:llvm-dev-bounces@lists.llvm.org] On Behalf Of
Krzysztof Parzyszek via llvm-dev
Sent: Wednesday, September 04, 2019 9:08 AM
To: CompilerCrash; llvm-dev@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

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