[LLVMdev] Runtime linker issue wtih X11R6 on i386 with -O3 optimization
Marco Peereboom
marco at peereboom.us
Tue Mar 20 15:12:21 PDT 2012
I was told that my writeup lacked an example and details so I reproduced
the code that X uses and I was able to boil down the issue to a couple
of lines of code. Sorry again for the length of this email.
Code was compiled on OpenBSD with clang 3.0-release.
========================================================================
With -O0 which works as X expects:
========================================================================
$ make clean
rm -f a.o b.o liba.so libb.so app
$ make CFLAGS=-O0
clang -O0 -fpic -c a.c
clang -shared -o liba.so a.o
clang -O0 -fpic -c b.c
clang -shared -o libb.so b.o
clang -O0 -fpic app.c -o app
$ ./app
opening a
opening b
clang and X sitting in a tree :)
The relevant bits of objdump -R
$ objdump -R liba.so | grep ex_func
2000210c R_386_JUMP_SLOT ex_func
Looking at the asm here shows us that ex_func is always looked up in the
PLT.
$ grep ex_func a.s
calll ex_func at PLT
calll ex_func at PLT
========================================================================
With -O3 that doesn't work like X expects:
========================================================================
$ make clean
rm -f a.o b.o liba.so libb.so app
$ make CFLAGS=-O3
clang -O3 -fpic -c a.c
clang -shared -o liba.so a.o
clang -O3 -fpic -c b.c
clang -shared -o libb.so b.o
clang -O3 -fpic app.c -o app
$ ./app
opening a
./app:./liba.so: undefined symbol 'ex_func'
app: dlopen a Cannot load specified object
The relevant bits of objdump -R
$ objdump -R liba.so | grep ex_func
2000211c R_386_GLOB_DAT ex_func
20002108 R_386_JUMP_SLOT ex_func
Now in the asm here we can see that in the TAILCALL case the ex_func is
looked up in GOT.
$ grep ex_func a.s
calll ex_func at PLT
movl ex_func at GOT(%esi), %eax
...
jmpl *%eax # TAILCALL
I am aware that this might turn a bit religous however I think that
always looking up the function pointer in PLT would eliminate this
issue. I don't see a benefit of using the GOT in this particular case.
The asm of both cases is reproduced at the end of this email.
Code tarball: http://www.peereboom.us/clang_issue.tgz
Code plaintext:
=== Makefile ===
all: app
liba.so: a.c
clang ${CFLAGS} -fpic -c a.c
clang -shared -o liba.so a.o
libb.so: b.c
clang ${CFLAGS} -fpic -c b.c
clang -shared -o libb.so b.o
app: liba.so libb.so
clang ${CFLAGS} -fpic app.c -o app
clean:
rm -f a.o b.o liba.so libb.so app
=== a.c ===
#include <stdio.h>
#include <stdlib.h>
#include "shared.h"
int something = 1;
int something_else = 1;
int something_different = 1;
void
moo(int x)
{
printf("made it to moo %d\n", x);
}
void
meh(int x)
{
printf("made it to meh %d\n", x);
}
void
foo(int x, int y, int z)
{
if (something) {
if (something_else) {
if (something_different) {
ex_func(x, y, z);
meh(y);
}
moo(x);
}
return;
}
ex_func(x, y, z);
}
=== app.c ===
#include <stdio.h>
#include <stdlib.h>
#include <err.h>
#include <dlfcn.h>
int
main(int argc, char *argv[])
{
void *a, *b;
printf("opening a\n");
if ((a = dlopen("./liba.so", RTLD_LAZY)) == NULL)
errx(1, "dlopen a %s", dlerror());
printf("opening b\n");
if ((b = dlopen("./libb.so", RTLD_LAZY)) == NULL)
errx(1, "dlopen b %s", dlerror());
printf("clang and X sitting in a tree :)\n");
dlclose(a);
dlclose(b);
return (0);
}
=== b.c ===
#include <stdio.h>
#include <stdlib.h>
#include "shared.h"
void
ex_func(int x, int y, int z)
{
printf("yep, i am an external function %d %d %d\n", x, y, z);
}
=== shared.h ===
void ex_func(int, int, int);
========================================================================
Asm -O0
========================================================================
.file "a.c"
.file 1 "/home/marco/clang_issue/a.c"
.section .debug_info,"", at progbits
.Lsection_info:
.section .debug_abbrev,"", at progbits
.Lsection_abbrev:
.section .debug_aranges,"", at progbits
.section .debug_macinfo,"", at progbits
.section .debug_line,"", at progbits
.Lsection_line:
.section .debug_loc,"", at progbits
.section .debug_pubnames,"", at progbits
.section .debug_pubtypes,"", at progbits
.section .debug_str,"", at progbits
.Lsection_str:
.section .debug_ranges,"", at progbits
.Ldebug_range:
.section .debug_loc,"", at progbits
.Lsection_debug_loc:
.text
.Ltext_begin:
.data
.text
.globl moo
.align 16, 0x90
.type moo, at function
moo: # @moo
.Ltmp3:
.cfi_startproc
.Lfunc_begin0:
.loc 1 12 0 # a.c:12:0
# BB#0:
pushl %ebp
.Ltmp4:
.cfi_def_cfa_offset 8
.Ltmp5:
.cfi_offset %ebp, -8
movl %esp, %ebp
.Ltmp6:
.cfi_def_cfa_register %ebp
pushl %ebx
subl $20, %esp
.Ltmp7:
.cfi_offset %ebx, -12
calll .L0$pb
.L0$pb:
popl %eax
.Ltmp8:
addl $_GLOBAL_OFFSET_TABLE_+(.Ltmp8-.L0$pb), %eax
movl 8(%ebp), %ecx
leal .L.str at GOTOFF(%eax), %edx
movl %ecx, -8(%ebp)
.loc 1 13 2 prologue_end # a.c:13:2
.Ltmp9:
movl -8(%ebp), %ecx
movl %edx, (%esp)
movl %ecx, 4(%esp)
movl %eax, %ebx
calll printf at PLT
.loc 1 14 1 # a.c:14:1
movl %eax, -12(%ebp) # 4-byte Spill
addl $20, %esp
popl %ebx
popl %ebp
ret
.Ltmp10:
.Ltmp11:
.size moo, .Ltmp11-moo
.Lfunc_end0:
.Ltmp12:
.cfi_endproc
.Leh_func_end0:
.globl meh
.align 16, 0x90
.type meh, at function
meh: # @meh
.Ltmp16:
.cfi_startproc
.Lfunc_begin1:
.loc 1 18 0 # a.c:18:0
# BB#0:
pushl %ebp
.Ltmp17:
.cfi_def_cfa_offset 8
.Ltmp18:
.cfi_offset %ebp, -8
movl %esp, %ebp
.Ltmp19:
.cfi_def_cfa_register %ebp
pushl %ebx
subl $20, %esp
.Ltmp20:
.cfi_offset %ebx, -12
calll .L1$pb
.L1$pb:
popl %eax
.Ltmp21:
addl $_GLOBAL_OFFSET_TABLE_+(.Ltmp21-.L1$pb), %eax
movl 8(%ebp), %ecx
leal .L.str1 at GOTOFF(%eax), %edx
movl %ecx, -8(%ebp)
.loc 1 19 2 prologue_end # a.c:19:2
.Ltmp22:
movl -8(%ebp), %ecx
movl %edx, (%esp)
movl %ecx, 4(%esp)
movl %eax, %ebx
calll printf at PLT
.loc 1 20 1 # a.c:20:1
movl %eax, -12(%ebp) # 4-byte Spill
addl $20, %esp
popl %ebx
popl %ebp
ret
.Ltmp23:
.Ltmp24:
.size meh, .Ltmp24-meh
.Lfunc_end1:
.Ltmp25:
.cfi_endproc
.Leh_func_end1:
.globl foo
.align 16, 0x90
.type foo, at function
foo: # @foo
.Ltmp29:
.cfi_startproc
.Lfunc_begin2:
.loc 1 24 0 # a.c:24:0
# BB#0:
pushl %ebp
.Ltmp30:
.cfi_def_cfa_offset 8
.Ltmp31:
.cfi_offset %ebp, -8
movl %esp, %ebp
.Ltmp32:
.cfi_def_cfa_register %ebp
pushl %ebx
pushl %edi
pushl %esi
subl $28, %esp
.Ltmp33:
.cfi_offset %esi, -20
.Ltmp34:
.cfi_offset %edi, -16
.Ltmp35:
.cfi_offset %ebx, -12
calll .L2$pb
.L2$pb:
popl %eax
.Ltmp36:
addl $_GLOBAL_OFFSET_TABLE_+(.Ltmp36-.L2$pb), %eax
movl 16(%ebp), %ecx
movl 12(%ebp), %edx
movl 8(%ebp), %esi
movl something at GOT(%eax), %edi
movl %esi, -16(%ebp)
movl %edx, -20(%ebp)
movl %ecx, -24(%ebp)
.loc 1 25 2 prologue_end # a.c:25:2
.Ltmp37:
cmpl $0, (%edi)
movl %eax, -28(%ebp) # 4-byte Spill
je .LBB2_6
# BB#1:
movl -28(%ebp), %eax # 4-byte Reload
movl something_else at GOT(%eax), %ecx
.loc 1 26 3 # a.c:26:3
.Ltmp38:
cmpl $0, (%ecx)
je .LBB2_5
# BB#2:
movl -28(%ebp), %eax # 4-byte Reload
movl something_different at GOT(%eax), %ecx
.loc 1 27 4 # a.c:27:4
.Ltmp39:
cmpl $0, (%ecx)
je .LBB2_4
# BB#3:
.loc 1 28 5 # a.c:28:5
.Ltmp40:
movl -16(%ebp), %eax
movl -20(%ebp), %ecx
movl -24(%ebp), %edx
movl %eax, (%esp)
movl %ecx, 4(%esp)
movl %edx, 8(%esp)
movl -28(%ebp), %ebx # 4-byte Reload
calll ex_func at PLT
.loc 1 29 5 # a.c:29:5
movl -20(%ebp), %eax
movl %eax, (%esp)
movl -28(%ebp), %ebx # 4-byte Reload
calll meh at PLT
.Ltmp41:
.LBB2_4:
.loc 1 31 4 # a.c:31:4
movl -16(%ebp), %eax
movl %eax, (%esp)
movl -28(%ebp), %ebx # 4-byte Reload
calll moo at PLT
.Ltmp42:
.LBB2_5:
.loc 1 33 3 # a.c:33:3
jmp .LBB2_7
.Ltmp43:
.LBB2_6:
.loc 1 35 2 # a.c:35:2
movl -16(%ebp), %eax
movl -20(%ebp), %ecx
movl -24(%ebp), %edx
movl %eax, (%esp)
movl %ecx, 4(%esp)
movl %edx, 8(%esp)
movl -28(%ebp), %ebx # 4-byte Reload
calll ex_func at PLT
.LBB2_7:
.loc 1 36 1 # a.c:36:1
addl $28, %esp
popl %esi
popl %edi
popl %ebx
popl %ebp
ret
.Ltmp44:
.Ltmp45:
.size foo, .Ltmp45-foo
.Lfunc_end2:
.Ltmp46:
.cfi_endproc
.Leh_func_end2:
.type something, at object # @something
.data
.globl something
.align 4
something:
.long 1 # 0x1
.size something, 4
.type something_else, at object # @something_else
.globl something_else
.align 4
something_else:
.long 1 # 0x1
.size something_else, 4
.type something_different, at object # @something_different
.globl something_different
.align 4
something_different:
.long 1 # 0x1
.size something_different, 4
.type .L.str, at object # @.str
.section .rodata.str1.1,"aMS", at progbits,1
.L.str:
.asciz "made it to moo %d\n"
.size .L.str, 19
.type .L.str1, at object # @.str1
.L.str1:
.asciz "made it to meh %d\n"
.size .L.str1, 19
.cfi_sections .debug_frame
.text
.Ltext_end:
.data
.Ldata_end:
.text
.Lsection_end1:
.section .debug_info,"", at progbits
.Linfo_begin1:
.long 311 # Length of Compilation Unit Info
.short 2 # DWARF version number
.long .Labbrev_begin # Offset Into Abbrev. Section
.byte 4 # Address Size (in bytes)
.byte 1 # Abbrev [1] 0xb:0x130 DW_TAG_compile_unit
.ascii "clang version 3.0 (tags/RELEASE_30/final)" # DW_AT_producer
.byte 0
.short 12 # DW_AT_language
.ascii "a.c" # DW_AT_name
.byte 0
.long 0 # DW_AT_entry_pc
.long .Lsection_line # DW_AT_stmt_list
.ascii "/home/marco/clang_issue" # DW_AT_comp_dir
.byte 0
.byte 2 # Abbrev [2] 0x5c:0x7 DW_TAG_base_type
.ascii "int" # DW_AT_name
.byte 0
.byte 5 # DW_AT_encoding
.byte 4 # DW_AT_byte_size
.byte 3 # Abbrev [3] 0x63:0x18 DW_TAG_variable
.ascii "something" # DW_AT_name
.byte 0
.long 92 # DW_AT_type
.byte 1 # DW_AT_external
.byte 1 # DW_AT_decl_file
.byte 6 # DW_AT_decl_line
.byte 5 # DW_AT_location
.byte 3
.long something
.byte 3 # Abbrev [3] 0x7b:0x1d DW_TAG_variable
.ascii "something_else" # DW_AT_name
.byte 0
.long 92 # DW_AT_type
.byte 1 # DW_AT_external
.byte 1 # DW_AT_decl_file
.byte 7 # DW_AT_decl_line
.byte 5 # DW_AT_location
.byte 3
.long something_else
.byte 3 # Abbrev [3] 0x98:0x22 DW_TAG_variable
.ascii "something_different" # DW_AT_name
.byte 0
.long 92 # DW_AT_type
.byte 1 # DW_AT_external
.byte 1 # DW_AT_decl_file
.byte 8 # DW_AT_decl_line
.byte 5 # DW_AT_location
.byte 3
.long something_different
.byte 4 # Abbrev [4] 0xba:0x24 DW_TAG_subprogram
.long 222 # DW_AT_sibling
.ascii "moo" # DW_AT_name
.byte 0
.byte 1 # DW_AT_decl_file
.byte 12 # DW_AT_decl_line
.byte 1 # DW_AT_prototyped
.byte 1 # DW_AT_external
.long .Lfunc_begin0 # DW_AT_low_pc
.long .Lfunc_end0 # DW_AT_high_pc
.byte 1 # DW_AT_frame_base
.byte 85
.byte 5 # Abbrev [5] 0xd1:0xc DW_TAG_formal_parameter
.byte 120 # DW_AT_name
.byte 0
.byte 1 # DW_AT_decl_file
.byte 11 # DW_AT_decl_line
.long 92 # DW_AT_type
.byte 2 # DW_AT_location
.byte 145
.byte 120
.byte 0 # End Of Children Mark
.byte 4 # Abbrev [4] 0xde:0x24 DW_TAG_subprogram
.long 258 # DW_AT_sibling
.ascii "meh" # DW_AT_name
.byte 0
.byte 1 # DW_AT_decl_file
.byte 18 # DW_AT_decl_line
.byte 1 # DW_AT_prototyped
.byte 1 # DW_AT_external
.long .Lfunc_begin1 # DW_AT_low_pc
.long .Lfunc_end1 # DW_AT_high_pc
.byte 1 # DW_AT_frame_base
.byte 85
.byte 5 # Abbrev [5] 0xf5:0xc DW_TAG_formal_parameter
.byte 120 # DW_AT_name
.byte 0
.byte 1 # DW_AT_decl_file
.byte 17 # DW_AT_decl_line
.long 92 # DW_AT_type
.byte 2 # DW_AT_location
.byte 145
.byte 120
.byte 0 # End Of Children Mark
.byte 6 # Abbrev [6] 0x102:0x38 DW_TAG_subprogram
.ascii "foo" # DW_AT_name
.byte 0
.byte 1 # DW_AT_decl_file
.byte 24 # DW_AT_decl_line
.byte 1 # DW_AT_prototyped
.byte 1 # DW_AT_external
.long .Lfunc_begin2 # DW_AT_low_pc
.long .Lfunc_end2 # DW_AT_high_pc
.byte 1 # DW_AT_frame_base
.byte 85
.byte 5 # Abbrev [5] 0x115:0xc DW_TAG_formal_parameter
.byte 120 # DW_AT_name
.byte 0
.byte 1 # DW_AT_decl_file
.byte 23 # DW_AT_decl_line
.long 92 # DW_AT_type
.byte 2 # DW_AT_location
.byte 145
.byte 112
.byte 5 # Abbrev [5] 0x121:0xc DW_TAG_formal_parameter
.byte 121 # DW_AT_name
.byte 0
.byte 1 # DW_AT_decl_file
.byte 23 # DW_AT_decl_line
.long 92 # DW_AT_type
.byte 2 # DW_AT_location
.byte 145
.byte 108
.byte 5 # Abbrev [5] 0x12d:0xc DW_TAG_formal_parameter
.byte 122 # DW_AT_name
.byte 0
.byte 1 # DW_AT_decl_file
.byte 23 # DW_AT_decl_line
.long 92 # DW_AT_type
.byte 2 # DW_AT_location
.byte 145
.byte 104
.byte 0 # End Of Children Mark
.byte 0 # End Of Children Mark
.Linfo_end1:
.section .debug_abbrev,"", at progbits
.Labbrev_begin:
.byte 1 # Abbreviation Code
.byte 17 # DW_TAG_compile_unit
.byte 1 # DW_CHILDREN_yes
.byte 37 # DW_AT_producer
.byte 8 # DW_FORM_string
.byte 19 # DW_AT_language
.byte 5 # DW_FORM_data2
.byte 3 # DW_AT_name
.byte 8 # DW_FORM_string
.byte 82 # DW_AT_entry_pc
.byte 1 # DW_FORM_addr
.byte 16 # DW_AT_stmt_list
.byte 6 # DW_FORM_data4
.byte 27 # DW_AT_comp_dir
.byte 8 # DW_FORM_string
.byte 0 # EOM(1)
.byte 0 # EOM(2)
.byte 2 # Abbreviation Code
.byte 36 # DW_TAG_base_type
.byte 0 # DW_CHILDREN_no
.byte 3 # DW_AT_name
.byte 8 # DW_FORM_string
.byte 62 # DW_AT_encoding
.byte 11 # DW_FORM_data1
.byte 11 # DW_AT_byte_size
.byte 11 # DW_FORM_data1
.byte 0 # EOM(1)
.byte 0 # EOM(2)
.byte 3 # Abbreviation Code
.byte 52 # DW_TAG_variable
.byte 0 # DW_CHILDREN_no
.byte 3 # DW_AT_name
.byte 8 # DW_FORM_string
.byte 73 # DW_AT_type
.byte 19 # DW_FORM_ref4
.byte 63 # DW_AT_external
.byte 12 # DW_FORM_flag
.byte 58 # DW_AT_decl_file
.byte 11 # DW_FORM_data1
.byte 59 # DW_AT_decl_line
.byte 11 # DW_FORM_data1
.byte 2 # DW_AT_location
.byte 10 # DW_FORM_block1
.byte 0 # EOM(1)
.byte 0 # EOM(2)
.byte 4 # Abbreviation Code
.byte 46 # DW_TAG_subprogram
.byte 1 # DW_CHILDREN_yes
.byte 1 # DW_AT_sibling
.byte 19 # DW_FORM_ref4
.byte 3 # DW_AT_name
.byte 8 # DW_FORM_string
.byte 58 # DW_AT_decl_file
.byte 11 # DW_FORM_data1
.byte 59 # DW_AT_decl_line
.byte 11 # DW_FORM_data1
.byte 39 # DW_AT_prototyped
.byte 12 # DW_FORM_flag
.byte 63 # DW_AT_external
.byte 12 # DW_FORM_flag
.byte 17 # DW_AT_low_pc
.byte 1 # DW_FORM_addr
.byte 18 # DW_AT_high_pc
.byte 1 # DW_FORM_addr
.byte 64 # DW_AT_frame_base
.byte 10 # DW_FORM_block1
.byte 0 # EOM(1)
.byte 0 # EOM(2)
.byte 5 # Abbreviation Code
.byte 5 # DW_TAG_formal_parameter
.byte 0 # DW_CHILDREN_no
.byte 3 # DW_AT_name
.byte 8 # DW_FORM_string
.byte 58 # DW_AT_decl_file
.byte 11 # DW_FORM_data1
.byte 59 # DW_AT_decl_line
.byte 11 # DW_FORM_data1
.byte 73 # DW_AT_type
.byte 19 # DW_FORM_ref4
.byte 2 # DW_AT_location
.byte 10 # DW_FORM_block1
.byte 0 # EOM(1)
.byte 0 # EOM(2)
.byte 6 # Abbreviation Code
.byte 46 # DW_TAG_subprogram
.byte 1 # DW_CHILDREN_yes
.byte 3 # DW_AT_name
.byte 8 # DW_FORM_string
.byte 58 # DW_AT_decl_file
.byte 11 # DW_FORM_data1
.byte 59 # DW_AT_decl_line
.byte 11 # DW_FORM_data1
.byte 39 # DW_AT_prototyped
.byte 12 # DW_FORM_flag
.byte 63 # DW_AT_external
.byte 12 # DW_FORM_flag
.byte 17 # DW_AT_low_pc
.byte 1 # DW_FORM_addr
.byte 18 # DW_AT_high_pc
.byte 1 # DW_FORM_addr
.byte 64 # DW_AT_frame_base
.byte 10 # DW_FORM_block1
.byte 0 # EOM(1)
.byte 0 # EOM(2)
.byte 0 # EOM(3)
.Labbrev_end:
.section .debug_pubnames,"", at progbits
.Lset0 = .Lpubnames_end1-.Lpubnames_begin1 # Length of Public Names Info
.long .Lset0
.Lpubnames_begin1:
.short 2 # DWARF Version
.long .Linfo_begin1 # Offset of Compilation Unit Info
.Lset1 = .Linfo_end1-.Linfo_begin1 # Compilation Unit Length
.long .Lset1
.long 152 # DIE offset
.asciz "something_different" # External Name
.long 258 # DIE offset
.asciz "foo" # External Name
.long 123 # DIE offset
.asciz "something_else" # External Name
.long 222 # DIE offset
.asciz "meh" # External Name
.long 186 # DIE offset
.asciz "moo" # External Name
.long 99 # DIE offset
.asciz "something" # External Name
.long 0 # End Mark
.Lpubnames_end1:
.section .debug_pubtypes,"", at progbits
.Lset2 = .Lpubtypes_end1-.Lpubtypes_begin1 # Length of Public Types Info
.long .Lset2
.Lpubtypes_begin1:
.short 2 # DWARF Version
.long .Linfo_begin1 # Offset of Compilation Unit Info
.Lset3 = .Linfo_end1-.Linfo_begin1 # Compilation Unit Length
.long .Lset3
.long 0 # End Mark
.Lpubtypes_end1:
.section .debug_aranges,"", at progbits
.section .debug_ranges,"", at progbits
.section .debug_macinfo,"", at progbits
.section ".note.GNU-stack","", at progbits
========================================================================
Asm -O3
========================================================================
.file "a.c"
.file 1 "/home/marco/clang_issue/a.c"
.section .debug_info,"", at progbits
.Lsection_info:
.section .debug_abbrev,"", at progbits
.Lsection_abbrev:
.section .debug_aranges,"", at progbits
.section .debug_macinfo,"", at progbits
.section .debug_line,"", at progbits
.Lsection_line:
.section .debug_loc,"", at progbits
.section .debug_pubnames,"", at progbits
.section .debug_pubtypes,"", at progbits
.section .debug_str,"", at progbits
.Lsection_str:
.section .debug_ranges,"", at progbits
.Ldebug_range:
.section .debug_loc,"", at progbits
.Lsection_debug_loc:
.text
.Ltext_begin:
.data
.text
.globl moo
.align 16, 0x90
.type moo, at function
moo: # @moo
.Ltmp3:
.cfi_startproc
.Lfunc_begin0:
.loc 1 12 0 # a.c:12:0
# BB#0:
pushl %ebp
.Ltmp4:
.cfi_def_cfa_offset 8
.Ltmp5:
.cfi_offset %ebp, -8
movl %esp, %ebp
.Ltmp6:
.cfi_def_cfa_register %ebp
pushl %ebx
subl $12, %esp
.Ltmp7:
.cfi_offset %ebx, -12
calll .L0$pb
.L0$pb:
popl %ebx
.Ltmp8:
addl $_GLOBAL_OFFSET_TABLE_+(.Ltmp8-.L0$pb), %ebx
#DEBUG_VALUE: moo:x <- ESP+4294967295
movl 8(%ebp), %eax
.loc 1 13 2 prologue_end # a.c:13:2
.Ltmp9:
movl %eax, 4(%esp)
leal .L.str at GOTOFF(%ebx), %eax
movl %eax, (%esp)
calll printf at PLT
.loc 1 14 1 # a.c:14:1
addl $12, %esp
popl %ebx
popl %ebp
ret
.Ltmp10:
.Ltmp11:
.size moo, .Ltmp11-moo
.Lfunc_end0:
.Ltmp12:
.cfi_endproc
.Leh_func_end0:
.globl meh
.align 16, 0x90
.type meh, at function
meh: # @meh
.Ltmp16:
.cfi_startproc
.Lfunc_begin1:
.loc 1 18 0 # a.c:18:0
# BB#0:
pushl %ebp
.Ltmp17:
.cfi_def_cfa_offset 8
.Ltmp18:
.cfi_offset %ebp, -8
movl %esp, %ebp
.Ltmp19:
.cfi_def_cfa_register %ebp
pushl %ebx
subl $12, %esp
.Ltmp20:
.cfi_offset %ebx, -12
calll .L1$pb
.L1$pb:
popl %ebx
.Ltmp21:
addl $_GLOBAL_OFFSET_TABLE_+(.Ltmp21-.L1$pb), %ebx
#DEBUG_VALUE: meh:x <- ESP+4294967295
movl 8(%ebp), %eax
.loc 1 19 2 prologue_end # a.c:19:2
.Ltmp22:
movl %eax, 4(%esp)
leal .L.str1 at GOTOFF(%ebx), %eax
movl %eax, (%esp)
calll printf at PLT
.loc 1 20 1 # a.c:20:1
addl $12, %esp
popl %ebx
popl %ebp
ret
.Ltmp23:
.Ltmp24:
.size meh, .Ltmp24-meh
.Lfunc_end1:
.Ltmp25:
.cfi_endproc
.Leh_func_end1:
.globl foo
.align 16, 0x90
.type foo, at function
foo: # @foo
.Ltmp29:
.cfi_startproc
.Lfunc_begin2:
.loc 1 24 0 # a.c:24:0
# BB#0:
pushl %ebp
.Ltmp30:
.cfi_def_cfa_offset 8
.Ltmp31:
.cfi_offset %ebp, -8
movl %esp, %ebp
.Ltmp32:
.cfi_def_cfa_register %ebp
pushl %ebx
pushl %edi
pushl %esi
subl $12, %esp
.Ltmp33:
.cfi_offset %esi, -20
.Ltmp34:
.cfi_offset %edi, -16
.Ltmp35:
.cfi_offset %ebx, -12
calll .L2$pb
.L2$pb:
popl %esi
.Ltmp36:
addl $_GLOBAL_OFFSET_TABLE_+(.Ltmp36-.L2$pb), %esi
.loc 1 25 2 prologue_end # a.c:25:2
.Ltmp37:
movl something at GOT(%esi), %eax
cmpl $0, (%eax)
je .LBB2_6
# BB#1:
.loc 1 26 3 # a.c:26:3
.Ltmp38:
movl something_else at GOT(%esi), %eax
cmpl $0, (%eax)
je .LBB2_5
# BB#2:
movl 8(%ebp), %ecx
#DEBUG_VALUE: foo:x <- ECX+0
.loc 1 27 4 # a.c:27:4
.Ltmp39:
movl something_different at GOT(%esi), %eax
cmpl $0, (%eax)
je .LBB2_4
# BB#3:
#DEBUG_VALUE: foo:x <- ECX+0
movl 16(%ebp), %eax
#DEBUG_VALUE: foo:z <- EAX+0
movl 12(%ebp), %edi
#DEBUG_VALUE: foo:y <- EDI+0
.loc 1 28 5 # a.c:28:5
.Ltmp40:
movl %eax, 8(%esp)
.Ltmp41:
#DEBUG_VALUE: meh:x <- EDI+0
movl %edi, 4(%esp)
movl %ecx, (%esp)
movl %esi, %ebx
.Ltmp42:
#DEBUG_VALUE: foo:x <- undef
calll ex_func at PLT
.Ltmp43:
.loc 1 19 2 # a.c:19:2
movl %edi, 4(%esp)
leal .L.str1 at GOTOFF(%esi), %eax
movl %eax, (%esp)
movl %esi, %ebx
calll printf at PLT
movl 8(%ebp), %ecx
.Ltmp44:
#DEBUG_VALUE: foo:x <- ECX+0
.LBB2_4:
#DEBUG_VALUE: foo:x <- ECX+0
#DEBUG_VALUE: moo:x <- ECX+0
.loc 1 13 2 # a.c:13:2
movl %ecx, 4(%esp)
leal .L.str at GOTOFF(%esi), %eax
movl %eax, (%esp)
movl %esi, %ebx
calll printf at PLT
.Ltmp45:
.LBB2_5:
.loc 1 36 1 # a.c:36:1
addl $12, %esp
popl %esi
popl %edi
popl %ebx
popl %ebp
ret
.LBB2_6:
.loc 1 35 2 # a.c:35:2
movl ex_func at GOT(%esi), %eax
addl $12, %esp
popl %esi
popl %edi
popl %ebx
popl %ebp
jmpl *%eax # TAILCALL
.Ltmp46:
.Ltmp47:
.size foo, .Ltmp47-foo
.Lfunc_end2:
.Ltmp48:
.cfi_endproc
.Leh_func_end2:
.type something, at object # @something
.data
.globl something
.align 4
something:
.long 1 # 0x1
.size something, 4
.type something_else, at object # @something_else
.globl something_else
.align 4
something_else:
.long 1 # 0x1
.size something_else, 4
.type something_different, at object # @something_different
.globl something_different
.align 4
something_different:
.long 1 # 0x1
.size something_different, 4
.type .L.str, at object # @.str
.section .rodata.str1.1,"aMS", at progbits,1
.L.str:
.asciz "made it to moo %d\n"
.size .L.str, 19
.type .L.str1, at object # @.str1
.L.str1:
.asciz "made it to meh %d\n"
.size .L.str1, 19
.cfi_sections .debug_frame
.text
.Ltext_end:
.data
.Ldata_end:
.text
.Lsection_end1:
.section .debug_info,"", at progbits
.Linfo_begin1:
.long 417 # Length of Compilation Unit Info
.short 2 # DWARF version number
.long .Labbrev_begin # Offset Into Abbrev. Section
.byte 4 # Address Size (in bytes)
.byte 1 # Abbrev [1] 0xb:0x19a DW_TAG_compile_unit
.ascii "clang version 3.0 (tags/RELEASE_30/final)" # DW_AT_producer
.byte 0
.short 12 # DW_AT_language
.ascii "a.c" # DW_AT_name
.byte 0
.long 0 # DW_AT_entry_pc
.long .Lsection_line # DW_AT_stmt_list
.ascii "/home/marco/clang_issue" # DW_AT_comp_dir
.byte 0
.byte 1 # DW_AT_APPLE_optimized
.byte 2 # Abbrev [2] 0x5d:0x7 DW_TAG_base_type
.ascii "int" # DW_AT_name
.byte 0
.byte 5 # DW_AT_encoding
.byte 4 # DW_AT_byte_size
.byte 3 # Abbrev [3] 0x64:0x18 DW_TAG_variable
.ascii "something" # DW_AT_name
.byte 0
.long 93 # DW_AT_type
.byte 1 # DW_AT_external
.byte 1 # DW_AT_decl_file
.byte 6 # DW_AT_decl_line
.byte 5 # DW_AT_location
.byte 3
.long something
.byte 3 # Abbrev [3] 0x7c:0x1d DW_TAG_variable
.ascii "something_else" # DW_AT_name
.byte 0
.long 93 # DW_AT_type
.byte 1 # DW_AT_external
.byte 1 # DW_AT_decl_file
.byte 7 # DW_AT_decl_line
.byte 5 # DW_AT_location
.byte 3
.long something_else
.byte 3 # Abbrev [3] 0x99:0x22 DW_TAG_variable
.ascii "something_different" # DW_AT_name
.byte 0
.long 93 # DW_AT_type
.byte 1 # DW_AT_external
.byte 1 # DW_AT_decl_file
.byte 8 # DW_AT_decl_line
.byte 5 # DW_AT_location
.byte 3
.long something_different
.byte 4 # Abbrev [4] 0xbb:0x24 DW_TAG_subprogram
.long 223 # DW_AT_sibling
.ascii "moo" # DW_AT_name
.byte 0
.byte 1 # DW_AT_decl_file
.byte 12 # DW_AT_decl_line
.byte 1 # DW_AT_prototyped
.byte 1 # DW_AT_external
.long .Lfunc_begin0 # DW_AT_low_pc
.long .Lfunc_end0 # DW_AT_high_pc
.byte 1 # DW_AT_frame_base
.byte 85
.byte 1 # DW_AT_inline
.byte 5 # Abbrev [5] 0xd3:0xb DW_TAG_formal_parameter
.byte 120 # DW_AT_name
.byte 0
.byte 1 # DW_AT_decl_file
.byte 11 # DW_AT_decl_line
.long 93 # DW_AT_type
.byte 1 # DW_AT_location
.byte 84
.byte 0 # End Of Children Mark
.byte 4 # Abbrev [4] 0xdf:0x24 DW_TAG_subprogram
.long 259 # DW_AT_sibling
.ascii "meh" # DW_AT_name
.byte 0
.byte 1 # DW_AT_decl_file
.byte 18 # DW_AT_decl_line
.byte 1 # DW_AT_prototyped
.byte 1 # DW_AT_external
.long .Lfunc_begin1 # DW_AT_low_pc
.long .Lfunc_end1 # DW_AT_high_pc
.byte 1 # DW_AT_frame_base
.byte 85
.byte 1 # DW_AT_inline
.byte 5 # Abbrev [5] 0xf7:0xb DW_TAG_formal_parameter
.byte 120 # DW_AT_name
.byte 0
.byte 1 # DW_AT_decl_file
.byte 17 # DW_AT_decl_line
.long 93 # DW_AT_type
.byte 1 # DW_AT_location
.byte 84
.byte 0 # End Of Children Mark
.byte 6 # Abbrev [6] 0x103:0xa1 DW_TAG_subprogram
.ascii "foo" # DW_AT_name
.byte 0
.byte 1 # DW_AT_decl_file
.byte 24 # DW_AT_decl_line
.byte 1 # DW_AT_prototyped
.byte 1 # DW_AT_external
.long .Lfunc_begin2 # DW_AT_low_pc
.long .Lfunc_end2 # DW_AT_high_pc
.byte 1 # DW_AT_frame_base
.byte 85
.byte 7 # Abbrev [7] 0x116:0xd DW_TAG_formal_parameter
.byte 120 # DW_AT_name
.byte 0
.byte 1 # DW_AT_decl_file
.byte 23 # DW_AT_decl_line
.long 93 # DW_AT_type
.Lset0 = .Ldebug_loc0-.Lsection_debug_loc # DW_AT_location
.long .Lset0
.byte 7 # Abbrev [7] 0x123:0xd DW_TAG_formal_parameter
.byte 121 # DW_AT_name
.byte 0
.byte 1 # DW_AT_decl_file
.byte 23 # DW_AT_decl_line
.long 93 # DW_AT_type
.Lset1 = .Ldebug_loc6-.Lsection_debug_loc # DW_AT_location
.long .Lset1
.byte 7 # Abbrev [7] 0x130:0xd DW_TAG_formal_parameter
.byte 122 # DW_AT_name
.byte 0
.byte 1 # DW_AT_decl_file
.byte 23 # DW_AT_decl_line
.long 93 # DW_AT_type
.Lset2 = .Ldebug_loc4-.Lsection_debug_loc # DW_AT_location
.long .Lset2
.byte 8 # Abbrev [8] 0x13d:0x66 DW_TAG_lexical_block
.long .Ltmp37 # DW_AT_low_pc
.long .Ltmp46 # DW_AT_high_pc
.byte 8 # Abbrev [8] 0x146:0x5c DW_TAG_lexical_block
.long .Ltmp38 # DW_AT_low_pc
.long .Ltmp45 # DW_AT_high_pc
.byte 8 # Abbrev [8] 0x14f:0x52 DW_TAG_lexical_block
.long .Ltmp39 # DW_AT_low_pc
.long .Ltmp45 # DW_AT_high_pc
.byte 9 # Abbrev [9] 0x158:0x2b DW_TAG_lexical_block
.long 387 # DW_AT_sibling
.long .Ltmp40 # DW_AT_low_pc
.long .Ltmp44 # DW_AT_high_pc
.byte 10 # Abbrev [10] 0x165:0x1d DW_TAG_inlined_subroutine
.long 223 # DW_AT_abstract_origin
.long .Ltmp43 # DW_AT_low_pc
.long .Ltmp44 # DW_AT_high_pc
.byte 1 # DW_AT_call_file
.byte 29 # DW_AT_call_line
.byte 7 # Abbrev [7] 0x174:0xd DW_TAG_formal_parameter
.byte 120 # DW_AT_name
.byte 0
.byte 1 # DW_AT_decl_file
.byte 17 # DW_AT_decl_line
.long 93 # DW_AT_type
.Lset3 = .Ldebug_loc8-.Lsection_debug_loc # DW_AT_location
.long .Lset3
.byte 0 # End Of Children Mark
.byte 0 # End Of Children Mark
.byte 10 # Abbrev [10] 0x183:0x1d DW_TAG_inlined_subroutine
.long 187 # DW_AT_abstract_origin
.long .Ltmp44 # DW_AT_low_pc
.long .Ltmp45 # DW_AT_high_pc
.byte 1 # DW_AT_call_file
.byte 31 # DW_AT_call_line
.byte 7 # Abbrev [7] 0x192:0xd DW_TAG_formal_parameter
.byte 120 # DW_AT_name
.byte 0
.byte 1 # DW_AT_decl_file
.byte 11 # DW_AT_decl_line
.long 93 # DW_AT_type
.Lset4 = .Ldebug_loc10-.Lsection_debug_loc # DW_AT_location
.long .Lset4
.byte 0 # End Of Children Mark
.byte 0 # End Of Children Mark
.byte 0 # End Of Children Mark
.byte 0 # End Of Children Mark
.byte 0 # End Of Children Mark
.byte 0 # End Of Children Mark
.Linfo_end1:
.section .debug_abbrev,"", at progbits
.Labbrev_begin:
.byte 1 # Abbreviation Code
.byte 17 # DW_TAG_compile_unit
.byte 1 # DW_CHILDREN_yes
.byte 37 # DW_AT_producer
.byte 8 # DW_FORM_string
.byte 19 # DW_AT_language
.byte 5 # DW_FORM_data2
.byte 3 # DW_AT_name
.byte 8 # DW_FORM_string
.byte 82 # DW_AT_entry_pc
.byte 1 # DW_FORM_addr
.byte 16 # DW_AT_stmt_list
.byte 6 # DW_FORM_data4
.byte 27 # DW_AT_comp_dir
.byte 8 # DW_FORM_string
.ascii "\341\177" # DW_AT_APPLE_optimized
.byte 12 # DW_FORM_flag
.byte 0 # EOM(1)
.byte 0 # EOM(2)
.byte 2 # Abbreviation Code
.byte 36 # DW_TAG_base_type
.byte 0 # DW_CHILDREN_no
.byte 3 # DW_AT_name
.byte 8 # DW_FORM_string
.byte 62 # DW_AT_encoding
.byte 11 # DW_FORM_data1
.byte 11 # DW_AT_byte_size
.byte 11 # DW_FORM_data1
.byte 0 # EOM(1)
.byte 0 # EOM(2)
.byte 3 # Abbreviation Code
.byte 52 # DW_TAG_variable
.byte 0 # DW_CHILDREN_no
.byte 3 # DW_AT_name
.byte 8 # DW_FORM_string
.byte 73 # DW_AT_type
.byte 19 # DW_FORM_ref4
.byte 63 # DW_AT_external
.byte 12 # DW_FORM_flag
.byte 58 # DW_AT_decl_file
.byte 11 # DW_FORM_data1
.byte 59 # DW_AT_decl_line
.byte 11 # DW_FORM_data1
.byte 2 # DW_AT_location
.byte 10 # DW_FORM_block1
.byte 0 # EOM(1)
.byte 0 # EOM(2)
.byte 4 # Abbreviation Code
.byte 46 # DW_TAG_subprogram
.byte 1 # DW_CHILDREN_yes
.byte 1 # DW_AT_sibling
.byte 19 # DW_FORM_ref4
.byte 3 # DW_AT_name
.byte 8 # DW_FORM_string
.byte 58 # DW_AT_decl_file
.byte 11 # DW_FORM_data1
.byte 59 # DW_AT_decl_line
.byte 11 # DW_FORM_data1
.byte 39 # DW_AT_prototyped
.byte 12 # DW_FORM_flag
.byte 63 # DW_AT_external
.byte 12 # DW_FORM_flag
.byte 17 # DW_AT_low_pc
.byte 1 # DW_FORM_addr
.byte 18 # DW_AT_high_pc
.byte 1 # DW_FORM_addr
.byte 64 # DW_AT_frame_base
.byte 10 # DW_FORM_block1
.byte 32 # DW_AT_inline
.byte 11 # DW_FORM_data1
.byte 0 # EOM(1)
.byte 0 # EOM(2)
.byte 5 # Abbreviation Code
.byte 5 # DW_TAG_formal_parameter
.byte 0 # DW_CHILDREN_no
.byte 3 # DW_AT_name
.byte 8 # DW_FORM_string
.byte 58 # DW_AT_decl_file
.byte 11 # DW_FORM_data1
.byte 59 # DW_AT_decl_line
.byte 11 # DW_FORM_data1
.byte 73 # DW_AT_type
.byte 19 # DW_FORM_ref4
.byte 2 # DW_AT_location
.byte 10 # DW_FORM_block1
.byte 0 # EOM(1)
.byte 0 # EOM(2)
.byte 6 # Abbreviation Code
.byte 46 # DW_TAG_subprogram
.byte 1 # DW_CHILDREN_yes
.byte 3 # DW_AT_name
.byte 8 # DW_FORM_string
.byte 58 # DW_AT_decl_file
.byte 11 # DW_FORM_data1
.byte 59 # DW_AT_decl_line
.byte 11 # DW_FORM_data1
.byte 39 # DW_AT_prototyped
.byte 12 # DW_FORM_flag
.byte 63 # DW_AT_external
.byte 12 # DW_FORM_flag
.byte 17 # DW_AT_low_pc
.byte 1 # DW_FORM_addr
.byte 18 # DW_AT_high_pc
.byte 1 # DW_FORM_addr
.byte 64 # DW_AT_frame_base
.byte 10 # DW_FORM_block1
.byte 0 # EOM(1)
.byte 0 # EOM(2)
.byte 7 # Abbreviation Code
.byte 5 # DW_TAG_formal_parameter
.byte 0 # DW_CHILDREN_no
.byte 3 # DW_AT_name
.byte 8 # DW_FORM_string
.byte 58 # DW_AT_decl_file
.byte 11 # DW_FORM_data1
.byte 59 # DW_AT_decl_line
.byte 11 # DW_FORM_data1
.byte 73 # DW_AT_type
.byte 19 # DW_FORM_ref4
.byte 2 # DW_AT_location
.byte 6 # DW_FORM_data4
.byte 0 # EOM(1)
.byte 0 # EOM(2)
.byte 8 # Abbreviation Code
.byte 11 # DW_TAG_lexical_block
.byte 1 # DW_CHILDREN_yes
.byte 17 # DW_AT_low_pc
.byte 1 # DW_FORM_addr
.byte 18 # DW_AT_high_pc
.byte 1 # DW_FORM_addr
.byte 0 # EOM(1)
.byte 0 # EOM(2)
.byte 9 # Abbreviation Code
.byte 11 # DW_TAG_lexical_block
.byte 1 # DW_CHILDREN_yes
.byte 1 # DW_AT_sibling
.byte 19 # DW_FORM_ref4
.byte 17 # DW_AT_low_pc
.byte 1 # DW_FORM_addr
.byte 18 # DW_AT_high_pc
.byte 1 # DW_FORM_addr
.byte 0 # EOM(1)
.byte 0 # EOM(2)
.byte 10 # Abbreviation Code
.byte 29 # DW_TAG_inlined_subroutine
.byte 1 # DW_CHILDREN_yes
.byte 49 # DW_AT_abstract_origin
.byte 19 # DW_FORM_ref4
.byte 17 # DW_AT_low_pc
.byte 1 # DW_FORM_addr
.byte 18 # DW_AT_high_pc
.byte 1 # DW_FORM_addr
.byte 88 # DW_AT_call_file
.byte 11 # DW_FORM_data1
.byte 89 # DW_AT_call_line
.byte 11 # DW_FORM_data1
.byte 0 # EOM(1)
.byte 0 # EOM(2)
.byte 0 # EOM(3)
.Labbrev_end:
.section .debug_pubnames,"", at progbits
.Lset5 = .Lpubnames_end1-.Lpubnames_begin1 # Length of Public Names Info
.long .Lset5
.Lpubnames_begin1:
.short 2 # DWARF Version
.long .Linfo_begin1 # Offset of Compilation Unit Info
.Lset6 = .Linfo_end1-.Linfo_begin1 # Compilation Unit Length
.long .Lset6
.long 153 # DIE offset
.asciz "something_different" # External Name
.long 259 # DIE offset
.asciz "foo" # External Name
.long 124 # DIE offset
.asciz "something_else" # External Name
.long 223 # DIE offset
.asciz "meh" # External Name
.long 187 # DIE offset
.asciz "moo" # External Name
.long 100 # DIE offset
.asciz "something" # External Name
.long 0 # End Mark
.Lpubnames_end1:
.section .debug_pubtypes,"", at progbits
.Lset7 = .Lpubtypes_end1-.Lpubtypes_begin1 # Length of Public Types Info
.long .Lset7
.Lpubtypes_begin1:
.short 2 # DWARF Version
.long .Linfo_begin1 # Offset of Compilation Unit Info
.Lset8 = .Linfo_end1-.Linfo_begin1 # Compilation Unit Length
.long .Lset8
.long 0 # End Mark
.Lpubtypes_end1:
.section .debug_loc,"", at progbits
.Ldebug_loc0:
.long .Lfunc_begin2
.long .Ltmp42
.Lset9 = .Ltmp50-.Ltmp49 # Loc expr size
.short .Lset9
.Ltmp49:
.byte 81 # DW_OP_reg1
.Ltmp50:
.long .Ltmp44
.long .Ltmp45
.Lset10 = .Ltmp52-.Ltmp51 # Loc expr size
.short .Lset10
.Ltmp51:
.byte 81 # DW_OP_reg1
.Ltmp52:
.long 0
.long 0
.Ldebug_loc4:
.long .Lfunc_begin2
.long .Ltmp43
.Lset11 = .Ltmp54-.Ltmp53 # Loc expr size
.short .Lset11
.Ltmp53:
.byte 80 # DW_OP_reg0
.Ltmp54:
.long 0
.long 0
.Ldebug_loc6:
.long .Lfunc_begin2
.long .Ltmp44
.Lset12 = .Ltmp56-.Ltmp55 # Loc expr size
.short .Lset12
.Ltmp55:
.byte 87 # DW_OP_reg7
.Ltmp56:
.long 0
.long 0
.Ldebug_loc8:
.long .Ltmp41
.long .Ltmp44
.Lset13 = .Ltmp58-.Ltmp57 # Loc expr size
.short .Lset13
.Ltmp57:
.byte 87 # DW_OP_reg7
.Ltmp58:
.long 0
.long 0
.Ldebug_loc10:
.long .Ltmp44
.long .Ltmp45
.Lset14 = .Ltmp60-.Ltmp59 # Loc expr size
.short .Lset14
.Ltmp59:
.byte 81 # DW_OP_reg1
.Ltmp60:
.long 0
.long 0
.Ldebug_loc12:
.section .debug_aranges,"", at progbits
.section .debug_ranges,"", at progbits
.section .debug_macinfo,"", at progbits
.section ".note.GNU-stack","", at progbits
More information about the llvm-dev
mailing list