[llvm-dev] x86: How to Force 2-byte `jmp` instruction in lowering

Dean Michael Berris via llvm-dev llvm-dev at lists.llvm.org
Wed Jun 22 10:40:54 PDT 2016


Thanks Nirav,

I can confirm that this works when I do the compile with llc, but then when
linking to an executable with clang (patched with
http://reviews.llvm.org/D20352 and compiler-rt patched with
http://reviews.llvm.org/D21612) on Linux, I'm getting something different.
Here's a sample of the transcript, and what I'm seeing:

--->8 clang invocation 8<---
[16-06-23 3:33:42] dberris at dberris: ~/xray/llvm-build% ./bin/clang
-fxray-instrument -x c++ -std=c++11 -o test.bin test.cc -g --verbose
clang version 3.9.0 (http://llvm.org/git/clang.git
3ae26ac8b1c9c5db65f3dc0236139448b8b0520a) (http://llvm.org/git/llvm.git
8fd5dd6aa8a633eeb03b245cd0060479371fc521)
Target: x86_64-unknown-linux-gnu
Thread model: posix
InstalledDir: /usr/local/google/home/dberris/xray/llvm-build/./bin
Found candidate GCC installation: /usr/lib/gcc/x86_64-linux-gnu/4.7
Found candidate GCC installation: /usr/lib/gcc/x86_64-linux-gnu/4.7.3
Found candidate GCC installation: /usr/lib/gcc/x86_64-linux-gnu/4.8
Found candidate GCC installation: /usr/lib/gcc/x86_64-linux-gnu/4.8.4
Found candidate GCC installation: /usr/lib/gcc/x86_64-linux-gnu/4.9
Found candidate GCC installation: /usr/lib/gcc/x86_64-linux-gnu/4.9.3
Selected GCC installation: /usr/lib/gcc/x86_64-linux-gnu/4.8
Candidate multilib: .;@m64
Candidate multilib: 32;@m32
Candidate multilib: x32;@mx32
Selected multilib: .;@m64
 "/usr/local/google/home/dberris/xray/llvm-build/bin/clang-3.9" -cc1
-triple x86_64-unknown-linux-gnu -emit-obj -mrelax-all -disable-free
-main-file-name test.cc -mrelocation-model static -mthread-model posix
-mdisable-fp-elim -fmath-errno -masm-verbose -mconstructor-aliases
-munwind-tables -fuse-init-array -target-cpu x86-64 -v -dwarf-column-info
-debug-info-kind=limited -dwarf-version=4 -debugger-tuning=gdb
-fxray-instrument -resource-dir
/usr/local/google/home/dberris/xray/llvm-build/bin/../lib/clang/3.9.0
-internal-isystem
/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../../include/c++/4.8
-internal-isystem
/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../../include/x86_64-linux-gnu/c++/4.8
-internal-isystem
/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../../include/x86_64-linux-gnu/c++/4.8
-internal-isystem
/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../../include/c++/4.8/backward
-internal-isystem /usr/local/include -internal-isystem
/usr/local/google/home/dberris/xray/llvm-build/bin/../lib/clang/3.9.0/include
-internal-externc-isystem /usr/include/x86_64-linux-gnu
-internal-externc-isystem /include -internal-externc-isystem /usr/include
-std=c++11 -fdeprecated-macro -fdebug-compilation-dir
/usr/local/google/home/dberris/xray/llvm-build -ferror-limit 19
-fmessage-length 272 -fobjc-runtime=gcc -fcxx-exceptions -fexceptions
-fdiagnostics-show-option -fcolor-diagnostics -o /tmp/test-03d46e.o -x c++
test.cc
clang -cc1 version 3.9.0 based upon LLVM 3.9.0svn default target
x86_64-unknown-linux-gnu
ignoring nonexistent directory "/include"
ignoring duplicate directory
"/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../../include/x86_64-linux-gnu/c++/4.8"
#include "..." search starts here:
#include <...> search starts here:
 /usr/lib/gcc/x86_64-linux-gnu/4.8/../../../../include/c++/4.8
 /usr/lib/gcc/x86_64-linux-gnu/4.8/../../../../include/x86_64-linux-gnu/c++/4.8
 /usr/lib/gcc/x86_64-linux-gnu/4.8/../../../../include/c++/4.8/backward
 /usr/local/include
 /usr/local/google/home/dberris/xray/llvm-build/bin/../lib/clang/3.9.0/include
 /usr/include/x86_64-linux-gnu
 /usr/include
End of search list.
 "/usr/bin/ld" -z relro --hash-style=gnu --eh-frame-hdr -m elf_x86_64
-dynamic-linker /lib64/ld-linux-x86-64.so.2 -o test.bin
/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu/crt1.o
/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu/crti.o
/usr/lib/gcc/x86_64-linux-gnu/4.8/crtbegin.o
-L/usr/lib/gcc/x86_64-linux-gnu/4.8
-L/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu
-L/lib/x86_64-linux-gnu -L/lib/../lib64 -L/usr/lib/x86_64-linux-gnu
-L/usr/lib/gcc/x86_64-linux-gnu/4.8/../../..
-L/usr/local/google/home/dberris/xray/llvm-build/bin/../lib -L/lib
-L/usr/lib -whole-archive
/usr/local/google/home/dberris/xray/llvm-build/bin/../lib/clang/3.9.0/lib/linux/libclang_rt.xray-x86_64.a
-no-whole-archive /tmp/test-03d46e.o --no-as-needed -lpthread -lrt -lm
-latomic -ldl -lgcc --as-needed -lgcc_s --no-as-needed -lc -lgcc
--as-needed -lgcc_s --no-as-needed
/usr/lib/gcc/x86_64-linux-gnu/4.8/crtend.o
/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu/crtn.o
--->8 clang invocation 8<---

The test.cc is simply:

--->8 test.cc 8<---
#include <cstdio>
#include <cassert>

[[clang::xray_always_instrument]] void foo() { std::printf("Hello,
XRay!\n"); }

void bar() { std::printf("Not instrumented\n"); }

extern "C" {
extern int __xray_patch();
}

int main(int argc, char* argv[]) {
  printf("main has started.\n");
  bar();
  foo();
  __xray_patch();
  foo();
}
--->8 test.cc 8<---

A snippet of the disassembly (llvm-objdump -disassemble test.bin) looks
like:

--->8 disassembly 8<---
_Z3foov:
  400cb0:       e9 09 00 00 00  jmp     9 <_Z3foov+0xE>
  400cb5:       66 0f 1f 84 00 00 02 00 00      nopw    512(%rax,%rax)
  400cbe:       55      pushq   %rbp
  400cbf:       48 89 e5        movq    %rsp, %rbp
  400cc2:       48 83 ec 10     subq    $16, %rsp
  400cc6:       48 bf c5 0e 40 00 00 00 00 00   movabsq $4198085, %rdi
  400cd0:       b0 00   movb    $0, %al
  400cd2:       e8 a9 f9 ff ff  callq   -1623 <.plt+0x30>
  400cd7:       89 45 fc        movl    %eax, -4(%rbp)
  400cda:       48 83 c4 10     addq    $16, %rsp
  400cde:       5d      popq    %rbp
  400cdf:       c3      retq
  400ce0:       2e 66 0f 1f 84 00 00 02 00 00   nopw    %cs:512(%rax,%rax)
  400cea:       66 0f 1f 44 00 00       nopw    (%rax,%rax)

--->8 disassembly 8<---

Having looked at this a bit, I think you're right that the jumps are being
relaxed, due to the -mrelax-all option being used by clang. The question
becomes whether it's possible to inhibit relaxation for specific
instructions at the LLVM level.

Cheers


On Wed, Jun 22, 2016 at 9:37 AM Nirav Davé <niravd at google.com> wrote:

> Hmm. Odd. I just rebuilt from scratch and it seems to work with
> the test/CodeGen/X86/xray-attribute-instrumentation.ll test case outputing
> straight to obj:
>
>    llc -filetype=obj -o ~/a.o -mtriple=x86_64-apple-macosx <
> test/CodeGen/X86/xray-attribute-instrumentation.ll
>
> What test case are you using?
>
> In any case, the issue appears to be that llvm doesn't realize that the
> target address is resolved and erroneously applies branch relaxation to the
> jump. I don't know why a linker private symbol would make a difference.
>
> -Nirav
>
>
>
> On Wed, Jun 22, 2016 at 12:14 PM, Dean Michael Berris <dberris at google.com>
> wrote:
>
>> On Wed, Jun 22, 2016 at 6:05 AM Nirav Davé <niravd at google.com> wrote:
>>
>>> This appears to work:
>>>
>>> auto Target = OutContext.createLinkerPrivateTempSymbol();
>>>
>>> with
>>>
>>> auto Target = OutContext.createTempSymbol();
>>>
>>> -Nirav
>>>
>>>
>> Thanks Nirav -- I tried this but I'm still getting a "jmpq <address>"
>> with this incantation when I load and disassemble from gdb. I'm seeing a
>> 5-instruction jump, followed by the nops.
>>
>> If I disassemble with llvm-objdump though I see the following:
>>
>> _Z3foov:
>>   400c10:       e9 09 00 00 00  jmp     9 <_Z3foov+0xE>
>>   400c15:       66 0f 1f 84 00 00 02 00 00      nopw    512(%rax,%rax)
>>
>> I'm not sure whether the extra 0's after '0xe9 0x09' are alignment
>> padding (though I was expecing 0x90 to show up if this was an alignment
>> issue).
>>
>> Is there anything else I can try here?
>>
>> Thanks in advance!
>>
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20160622/ebbc6ddd/attachment.html>


More information about the llvm-dev mailing list