Marco Peereboom
2012-Mar-20 22:12 UTC
[LLVMdev] Runtime linker issue wtih X11R6 on i386 with -O3 optimization
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
Seemingly Similar Threads
- [LLVMdev] [lldb-dev] How is variable info retrieved in debugging for executables generated by llvm backend?
- [LLVMdev] [lldb-dev] How is variable info retrieved in debugging for executables generated by llvm backend?
- Debug info scope of explicit casting type does not seem correct
- Debug info scope of explicit casting type does not seem correct
- Debug info scope of explicit casting type does not seem correct