[llvm] r232333 - [dsymutil] Add support for linking line tables.

Frédéric Riss friss at apple.com
Tue Mar 24 16:22:20 PDT 2015


> On Mar 24, 2015, at 8:35 AM, Aaron Ballman <aaron at aaronballman.com> wrote:
> 
> This appears to have caused a bot to go red:
> 
> http://bb.pgr.jp/builders/msbuild-llvmclang-x64-msc18-DA/builds/73 <http://bb.pgr.jp/builders/msbuild-llvmclang-x64-msc18-DA/builds/73>

I can’t make any sense of the failure. I don’t see why only this bot generates a different line table section. It would be nice to get access to the generated binary to investigate. I’m currently on leave, but I’ll look at that as soon as I get back. In the mean time, I’m disabling the tests on windows hosts in r233130 to get that bot green again.

Fred

> ~Aaron
> 
> On Sun, Mar 15, 2015 at 4:45 PM, Frederic Riss <friss at apple.com> wrote:
>> Author: friss
>> Date: Sun Mar 15 15:45:43 2015
>> New Revision: 232333
>> 
>> URL: http://llvm.org/viewvc/llvm-project?rev=232333&view=rev
>> Log:
>> [dsymutil] Add support for linking line tables.
>> 
>> This code comes with a lot of cruft that is meant to mimic darwin's
>> dsymutil behavior. A much simpler approach (described in the numerous
>> FIXMEs that I put in there) gives the right output for the vast
>> majority of cases. The extra corner cases that are handled differently
>> need to be investigated: they seem to correctly handle debug info that
>> is in the input, but that info looks suspicious in the first place.
>> 
>> Anyway, the current code needs to handle this, but I plan to revisit it
>> as soon as the big round of validation against the classic dsymutil is
>> over.
>> 
>> Modified:
>>    llvm/trunk/test/tools/dsymutil/X86/basic-linking-x86.test
>>    llvm/trunk/test/tools/dsymutil/X86/basic-lto-dw4-linking-x86.test
>>    llvm/trunk/test/tools/dsymutil/X86/basic-lto-linking-x86.test
>>    llvm/trunk/tools/dsymutil/DwarfLinker.cpp
>> 
>> Modified: llvm/trunk/test/tools/dsymutil/X86/basic-linking-x86.test
>> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/dsymutil/X86/basic-linking-x86.test?rev=232333&r1=232332&r2=232333&view=diff
>> ==============================================================================
>> --- llvm/trunk/test/tools/dsymutil/X86/basic-linking-x86.test (original)
>> +++ llvm/trunk/test/tools/dsymutil/X86/basic-linking-x86.test Sun Mar 15 15:45:43 2015
>> @@ -16,10 +16,12 @@ CHECK:  DW_TAG_compile_unit [1] *
>> CHECK:    DW_AT_producer [DW_FORM_strp]     ( .debug_str[0x00000001] = "Apple LLVM version 6.0 (clang-600.0.39) (based on LLVM 3.5svn)")
>> CHECK:    DW_AT_language [DW_FORM_data2]       (DW_LANG_C99)
>> CHECK:    DW_AT_name [DW_FORM_strp] ( .debug_str[0x00000040] = "basic1.c")
>> +CHECK:    DW_AT_stmt_list [DW_FORM_data4]   (0x00000000)
>> CHECK:    DW_AT_comp_dir [DW_FORM_strp]     ( .debug_str[0x00000049] = "/Inputs")
>> CHECK:    DW_AT_low_pc [DW_FORM_addr]       (0x0000000100000ea0)
>> CHECK:    DW_TAG_subprogram [2] *
>> CHECK:    DW_AT_name [DW_FORM_strp]       ( .debug_str[0x00000051] = "main")
>> +CHECK:      DW_AT_decl_file [DW_FORM_data1] ("/Inputs/basic1.c")
>> CHECK:      DW_AT_decl_line [DW_FORM_data1]    (23)
>> CHECK:      DW_AT_prototyped [DW_FORM_flag]    (0x01)
>> CHECK:      DW_AT_type [DW_FORM_ref4]       (cu + 0x0063 => {0x00000063})
>> @@ -30,12 +32,13 @@ CHECK:      DW_AT_high_pc [DW_FORM_addr]
>> CHECK:      DW_AT_frame_base [DW_FORM_block1]  (<0x01> 56 )
>> CHECK:      DW_TAG_formal_parameter [3]
>> CHECK:        DW_AT_name [DW_FORM_strp]     ( .debug_str[0x00000056] = "argc")
>> +CHECK:        DW_AT_decl_file [DW_FORM_data1]       ("/Inputs/basic1.c")
>> CHECK:        DW_AT_decl_line [DW_FORM_data1]  (23)
>> CHECK:        DW_AT_type [DW_FORM_ref4]     (cu + 0x0063 => {0x00000063})
>> CHECK:        DW_AT_location [DW_FORM_block1]  (<0x02> 91 78 )
>> CHECK:      DW_TAG_formal_parameter [3]
>> CHECK:        DW_AT_name [DW_FORM_strp]     ( .debug_str[0x0000005b] = "argv")
>> -CHECK:        DW_AT_decl_file [DW_FORM_data1]  (0x01)
>> +CHECK:        DW_AT_decl_file [DW_FORM_data1]  ("/Inputs/basic1.c")
>> CHECK:        DW_AT_decl_line [DW_FORM_data1]  (23)
>> CHECK:        DW_AT_type [DW_FORM_ref4]     (cu + 0x006a => {0x0000006a})
>> CHECK:        DW_AT_location [DW_FORM_block1]  (<0x02> 91 70 )
>> @@ -61,6 +64,7 @@ CHECK:  Compile Unit:
>> CHECK:  DW_TAG_compile_unit [1] *
>> CHECK:   DW_AT_producer [DW_FORM_strp]     ( .debug_str[0x00000001] = "Apple LLVM version 6.0 (clang-600.0.39) (based on LLVM 3.5svn)")
>> CHECK:   DW_AT_name [DW_FORM_strp] ( .debug_str[0x00000069] = "basic2.c")
>> +CHECK:   DW_AT_stmt_list [DW_FORM_data4]   (0x0000003f)
>> CHECK:   DW_AT_comp_dir [DW_FORM_strp]     ( .debug_str[0x00000049] = "/Inputs")
>> CHECK:   DW_AT_low_pc [DW_FORM_addr]       (0x0000000100000ed0)
>> CHECK:    DW_TAG_base_type [4]
>> @@ -68,14 +72,17 @@ CHECK:      DW_AT_name [DW_FORM_strp]
>> CHECK:    DW_TAG_variable [7]
>> CHECK:      DW_AT_name [DW_FORM_strp]       ( .debug_str[0x00000072] = "private_int")
>> CHECK:      DW_AT_type [DW_FORM_ref4]       (cu + 0x0026 => {0x000000a7})
>> +CHECK:      DW_AT_decl_file [DW_FORM_data1] ("/Inputs/basic2.c")
>> BASIC:      DW_AT_location [DW_FORM_block1] (<0x09> 03 08 10 00 00 01 00 00 00 )
>> ARCHIVE:    DW_AT_location [DW_FORM_block1] (<0x09> 03 04 10 00 00 01 00 00 00 )
>> CHECK:    DW_TAG_variable [7]
>> CHECK:      DW_AT_name [DW_FORM_strp]       ( .debug_str[0x0000007e] = "baz")
>> CHECK:      DW_AT_type [DW_FORM_ref4]       (cu + 0x0026 => {0x000000a7})
>> +CHECK:      DW_AT_decl_file [DW_FORM_data1] ("/Inputs/basic2.c")
>> CHECK:      DW_AT_location [DW_FORM_block1] (<0x09> 03 00 10 00 00 01 00 00 00 )
>> CHECK:    DW_TAG_subprogram [2] *
>> CHECK:      DW_AT_name [DW_FORM_strp]       ( .debug_str[0x00000082] = "foo")
>> +CHECK:      DW_AT_decl_file [DW_FORM_data1] ("/Inputs/basic2.c")
>> CHECK:      DW_AT_type [DW_FORM_ref4]       (cu + 0x0026 => {0x000000a7})
>> CHECK:      DW_AT_low_pc [DW_FORM_addr]     (0x0000000100000ed0)
>> CHECK:      DW_AT_high_pc [DW_FORM_addr]    (0x0000000100000f19)
>> @@ -98,11 +105,13 @@ CHECK:  Compile Unit:
>> CHECK:  DW_TAG_compile_unit [1] *
>> CHECK:    DW_AT_producer [DW_FORM_strp]     ( .debug_str[0x00000001] = "Apple LLVM version 6.0 (clang-600.0.39) (based on LLVM 3.5svn)")
>> CHECK:    DW_AT_name [DW_FORM_strp] ( .debug_str[0x0000008e] = "basic3.c")
>> +CHECK:    DW_AT_stmt_list [DW_FORM_data4]   (0x00000093)
>> CHECK:    DW_AT_comp_dir [DW_FORM_strp]     ( .debug_str[0x00000049] = "/Inputs")
>> CHECK:    DW_AT_low_pc [DW_FORM_addr]       (0x0000000100000f40)
>> CHECK:    DW_TAG_variable [9]
>> CHECK:      DW_AT_name [DW_FORM_strp]       ( .debug_str[0x00000097] = "val")
>> CHECK:      DW_AT_type [DW_FORM_ref4]       (cu + 0x003c => {0x00000162})
>> +CHECK:      DW_AT_decl_file [DW_FORM_data1] ("/Inputs/basic3.c")
>> BASIC:      DW_AT_location [DW_FORM_block1] (<0x09> 03 04 10 00 00 01 00 00 00 )
>> ARCHIVE:    DW_AT_location [DW_FORM_block1] (<0x09> 03 08 10 00 00 01 00 00 00 )
>> CHECK:    DW_TAG_volatile_type [10]
>> @@ -142,3 +151,39 @@ CHECK-NEXT:Address Range Header: length
>> CHECK-NEXT:[0x0000000100000f40 - 0x0000000100000f84)
>> CHECK-NEXT:[0x0000000100000f90 - 0x0000000100000fa9)
>> 
>> +CHECK: .debug_line contents:
>> +CHECK:                Dir  Mod Time   File Len   File Name
>> +CHECK-NEXT:                 ---- ---------- ---------- ---------------------------
>> +CHECK-NEXT: file_names[  1]    0 0x00000000 0x00000000 basic1.c
>> +CHECK: Address            Line   Column File   ISA Discriminator Flags
>> +CHECK-NEXT: ------------------ ------ ------ ------ --- ------------- -------------
>> +CHECK-NEXT: 0x0000000100000ea0     23      0      1   0             0  is_stmt
>> +CHECK-NEXT: 0x0000000100000eb6     24      0      1   0             0  is_stmt prologue_end
>> +CHECK-NEXT: 0x0000000100000ec4     24      0      1   0             0  is_stmt end_sequence
>> +
>> +CHECK:                 Dir  Mod Time   File Len   File Name
>> +CHECK-NEXT:                 ---- ---------- ---------- ---------------------------
>> +CHECK-NEXT: file_names[  1]    0 0x00000000 0x00000000 basic2.c
>> +CHECK: Address            Line   Column File   ISA Discriminator Flags
>> +CHECK-NEXT: ------------------ ------ ------ ------ --- ------------- -------------
>> +CHECK-NEXT: 0x0000000100000ed0     19      0      1   0             0  is_stmt
>> +CHECK-NEXT: 0x0000000100000ee2     20      0      1   0             0  is_stmt prologue_end
>> +CHECK-NEXT: 0x0000000100000f19     20      0      1   0             0  is_stmt end_sequence
>> +CHECK-NEXT: 0x0000000100000f20     14      0      1   0             0  is_stmt
>> +CHECK-NEXT: 0x0000000100000f24     15      0      1   0             0  is_stmt prologue_end
>> +CHECK-NEXT: 0x0000000100000f37     15      0      1   0             0  is_stmt end_sequence
>> +
>> +CHECK:                 Dir  Mod Time   File Len   File Name
>> +CHECK-NEXT:                 ---- ---------- ---------- ---------------------------
>> +CHECK-NEXT: file_names[  1]    0 0x00000000 0x00000000 basic3.c
>> +CHECK: Address            Line   Column File   ISA Discriminator Flags
>> +CHECK-NEXT: ------------------ ------ ------ ------ --- ------------- -------------
>> +CHECK-NEXT: 0x0000000100000f40     16      0      1   0             0  is_stmt
>> +CHECK-NEXT: 0x0000000100000f4b     17      0      1   0             0  is_stmt prologue_end
>> +CHECK-NEXT: 0x0000000100000f58     18      0      1   0             0  is_stmt
>> +CHECK-NEXT: 0x0000000100000f6c     19      0      1   0             0  is_stmt
>> +CHECK-NEXT: 0x0000000100000f7b     20      0      1   0             0  is_stmt
>> +CHECK-NEXT: 0x0000000100000f84     20      0      1   0             0  is_stmt end_sequence
>> +CHECK-NEXT: 0x0000000100000f90     11      0      1   0             0  is_stmt
>> +CHECK-NEXT: 0x0000000100000f9b     12      0      1   0             0  is_stmt prologue_end
>> +CHECK-NEXT: 0x0000000100000fa9     12      0      1   0             0  is_stmt end_sequence
>> \ No newline at end of file
>> 
>> Modified: llvm/trunk/test/tools/dsymutil/X86/basic-lto-dw4-linking-x86.test
>> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/dsymutil/X86/basic-lto-dw4-linking-x86.test?rev=232333&r1=232332&r2=232333&view=diff
>> ==============================================================================
>> --- llvm/trunk/test/tools/dsymutil/X86/basic-lto-dw4-linking-x86.test (original)
>> +++ llvm/trunk/test/tools/dsymutil/X86/basic-lto-dw4-linking-x86.test Sun Mar 15 15:45:43 2015
>> @@ -9,6 +9,7 @@ CHECK:  DW_TAG_compile_unit [1] *
>> CHECK:    DW_AT_producer [DW_FORM_strp]        ( .debug_str[0x00000001] = "clang version 3.7.0 ")
>> CHECK:    DW_AT_language [DW_FORM_data2]       (DW_LANG_C99)
>> CHECK:    DW_AT_name [DW_FORM_strp]    ( .debug_str[0x00000016] = "basic1.c")
>> +CHECK:    DW_AT_stmt_list [DW_FORM_sec_offset]      (0x00000000)
>> CHECK:    DW_AT_comp_dir [DW_FORM_strp]        ( .debug_str[0x0000001f] = "/Inputs")
>> CHECK:    DW_AT_low_pc [DW_FORM_addr]       (0x0000000100000f40)
>> CHECK:    DW_AT_high_pc [DW_FORM_data4]     (0x0000000b)
>> @@ -17,12 +18,14 @@ CHECK:      DW_AT_low_pc [DW_FORM_addr]
>> CHECK:      DW_AT_high_pc [DW_FORM_data4]      (0x0000000b)
>> CHECK:      DW_AT_frame_base [DW_FORM_exprloc] (<0x1> 56 )
>> CHECK:      DW_AT_name [DW_FORM_strp]  ( .debug_str[0x00000027] = "main")
>> +CHECK:      DW_AT_decl_file [DW_FORM_data1] ("/Inputs/basic1.c")
>> CHECK:      DW_AT_prototyped [DW_FORM_flag_present]    (true)
>> CHECK:      DW_AT_type [DW_FORM_ref_addr]   (0x00000000000000a1)
>> CHECK:      DW_AT_external [DW_FORM_flag_present]      (true)
>> CHECK:      DW_TAG_formal_parameter [3]
>> CHECK:        DW_AT_location [DW_FORM_exprloc] (<0x3> 55 93 04 )
>> CHECK:        DW_AT_name [DW_FORM_strp]        ( .debug_str[0x0000002c] = "argc")
>> +CHECK:        DW_AT_decl_file [DW_FORM_data1]       ("/Inputs/basic1.c")
>> CHECK:        DW_AT_type [DW_FORM_ref_addr] (0x00000000000000a1)
>> CHECK:      DW_TAG_formal_parameter [4]
>> CHECK:        DW_AT_location [DW_FORM_exprloc] (<0x1> 54 )
>> @@ -45,6 +48,7 @@ CHECK:  DW_TAG_compile_unit [1] *
>> CHECK:    DW_AT_producer [DW_FORM_strp]        ( .debug_str[0x00000001] = "clang version 3.7.0 ")
>> CHECK:    DW_AT_language [DW_FORM_data2]       (DW_LANG_C99)
>> CHECK:    DW_AT_name [DW_FORM_strp]    ( .debug_str[0x0000003b] = "basic2.c")
>> +CHECK:    DW_AT_stmt_list [DW_FORM_sec_offset]      (0x00000044)
>> CHECK:    DW_AT_low_pc [DW_FORM_addr]       (0x0000000100000f50)
>> CHECK:    DW_AT_high_pc [DW_FORM_data4]     (0x00000037)
>> CHECK:    DW_TAG_base_type [7]
>> @@ -54,6 +58,7 @@ CHECK:      DW_AT_name [DW_FORM_strp] (
>> CHECK:      DW_AT_location [DW_FORM_exprloc]   (<0x9> 03 00 10 00 00 01 00 00 00 )
>> CHECK:    DW_TAG_variable [8]
>> CHECK:      DW_AT_name [DW_FORM_strp]  ( .debug_str[0x0000004c] = "private_int")
>> +CHECK:      DW_AT_decl_file [DW_FORM_data1] ("/Inputs/basic2.c")
>> CHECK:      DW_AT_location [DW_FORM_exprloc]   (<0x9> 03 08 10 00 00 01 00 00 00 )
>> CHECK:    DW_TAG_subprogram [9]
>> CHECK:      DW_AT_name [DW_FORM_strp]  ( .debug_str[0x00000058] = "inc")
>> @@ -64,6 +69,7 @@ CHECK:      DW_AT_low_pc [DW_FORM_addr]
>> CHECK:      DW_AT_high_pc [DW_FORM_data4]      (0x00000037)
>> CHECK:      DW_AT_frame_base [DW_FORM_exprloc] (<0x1> 56 )
>> CHECK:      DW_AT_name [DW_FORM_strp]  ( .debug_str[0x0000005c] = "foo")
>> +CHECK:      DW_AT_decl_file [DW_FORM_data1] ("/Inputs/basic2.c")
>> CHECK:      DW_AT_prototyped [DW_FORM_flag_present]    (true)
>> CHECK:      DW_AT_type [DW_FORM_ref4]  (cu + 0x002a => {0x000000a1})
>> CHECK:      DW_TAG_formal_parameter [11]
>> @@ -82,10 +88,12 @@ CHECK:  Compile Unit: {{.*}} version = 0
>> CHECK:  DW_TAG_compile_unit [1] *
>> CHECK:    DW_AT_producer [DW_FORM_strp]        ( .debug_str[0x00000001] = "clang version 3.7.0 ")
>> CHECK:    DW_AT_name [DW_FORM_strp]    ( .debug_str[0x00000064] = "basic3.c")
>> +CHECK:    DW_AT_stmt_list [DW_FORM_sec_offset]      (0x0000009a)
>> CHECK:    DW_AT_low_pc [DW_FORM_addr]       (0x0000000100000f90)
>> CHECK:    DW_AT_high_pc [DW_FORM_data4]     (0x00000024)
>> CHECK:    DW_TAG_variable [13]
>> CHECK:      DW_AT_name [DW_FORM_strp]  ( .debug_str[0x0000006d] = "val")
>> +CHECK:      DW_AT_decl_file [DW_FORM_data1] ("/Inputs/basic3.c")
>> CHECK:      DW_AT_location [DW_FORM_exprloc]   (<0x9> 03 04 10 00 00 01 00 00 00 )
>> CHECK:    DW_TAG_volatile_type [14]
>> CHECK:    DW_TAG_subprogram [15]
>> @@ -129,3 +137,45 @@ CHECK-NEXT: Address Range Header: length
>> CHECK-NEXT: [0x0000000100000f50 - 0x0000000100000f87)
>> CHECK-NEXT: Address Range Header: length = 0x0000002c, version = 0x0002, cu_offset = 0x0000011b, addr_size = 0x08, seg_size = 0x00
>> CHECK-NEXT: [0x0000000100000f90 - 0x0000000100000fb4)
>> +
>> +CHECK: .debug_line contents:
>> +CHECK:                 Dir  Mod Time   File Len   File Name
>> +CHECK-NEXT:                 ---- ---------- ---------- ---------------------------
>> +CHECK-NEXT: file_names[  1]    0 0x00000000 0x00000000 basic1.c
>> +CHECK: Address            Line   Column File   ISA Discriminator Flags
>> +CHECK-NEXT: ------------------ ------ ------ ------ --- ------------- -------------
>> +CHECK-NEXT: 0x0000000100000f40     26      0      1   0             0  is_stmt
>> +CHECK-NEXT: 0x0000000100000f44     27     10      1   0             0  is_stmt prologue_end
>> +CHECK-NEXT: 0x0000000100000f49     27      3      1   0             0
>> +CHECK-NEXT: 0x0000000100000f4b     27      3      1   0             0  end_sequence
>> +
>> +CHECK:                 Dir  Mod Time   File Len   File Name
>> +CHECK-NEXT:                 ---- ---------- ---------- ---------------------------
>> +CHECK-NEXT: file_names[  1]    0 0x00000000 0x00000000 basic2.c
>> +CHECK: Address            Line   Column File   ISA Discriminator Flags
>> +CHECK-NEXT: ------------------ ------ ------ ------ --- ------------- -------------
>> +CHECK-NEXT: 0x0000000100000f50     19      0      1   0             0  is_stmt
>> +CHECK-NEXT: 0x0000000100000f54     20     18      1   0             0  is_stmt prologue_end
>> +CHECK-NEXT: 0x0000000100000f5a     20     17      1   0             0
>> +CHECK-NEXT: 0x0000000100000f5c     20     10      1   0             0
>> +CHECK-NEXT: 0x0000000100000f61     15     10      1   0             0  is_stmt
>> +CHECK-NEXT: 0x0000000100000f70     20     23      1   0             0  is_stmt
>> +CHECK-NEXT: 0x0000000100000f74     20     36      1   0             0
>> +CHECK-NEXT: 0x0000000100000f83     20     31      1   0             0
>> +CHECK-NEXT: 0x0000000100000f85     20      3      1   0             0
>> +CHECK-NEXT: 0x0000000100000f87     20      3      1   0             0  end_sequence
>> +
>> +CHECK:                 Dir  Mod Time   File Len   File Name
>> +CHECK-NEXT:                 ---- ---------- ---------- ---------------------------
>> +CHECK-NEXT: file_names[  1]    0 0x00000000 0x00000000 basic3.c
>> +CHECK: Address            Line   Column File   ISA Discriminator Flags
>> +CHECK-NEXT: ------------------ ------ ------ ------ --- ------------- -------------
>> +CHECK-NEXT: 0x0000000100000f90     16      0      1   0             0  is_stmt
>> +CHECK-NEXT: 0x0000000100000f94     12     10      1   0             0  is_stmt prologue_end
>> +CHECK-NEXT: 0x0000000100000f9a     17      7      1   0             0  is_stmt
>> +CHECK-NEXT: 0x0000000100000f9f     12     10      1   0             0  is_stmt
>> +CHECK-NEXT: 0x0000000100000fa7     20      1      1   0             0  is_stmt
>> +CHECK-NEXT: 0x0000000100000fa9     19     18      1   0             0  is_stmt
>> +CHECK-NEXT: 0x0000000100000fab     19     10      1   0             0
>> +CHECK-NEXT: 0x0000000100000fb2     20      1      1   0             0  is_stmt
>> +CHECK-NEXT: 0x0000000100000fb4     20      1      1   0             0  is_stmt end_sequence
>> 
>> Modified: llvm/trunk/test/tools/dsymutil/X86/basic-lto-linking-x86.test
>> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/dsymutil/X86/basic-lto-linking-x86.test?rev=232333&r1=232332&r2=232333&view=diff
>> ==============================================================================
>> --- llvm/trunk/test/tools/dsymutil/X86/basic-lto-linking-x86.test (original)
>> +++ llvm/trunk/test/tools/dsymutil/X86/basic-lto-linking-x86.test Sun Mar 15 15:45:43 2015
>> @@ -10,10 +10,12 @@ CHECK:  DW_TAG_compile_unit [1] *
>> CHECK:    DW_AT_producer [DW_FORM_strp]     ( .debug_str[0x00000001] = "Apple LLVM version 6.0 (clang-600.0.39) (based on LLVM 3.5svn)")
>> CHECK:    DW_AT_language [DW_FORM_data2]       (DW_LANG_C99)
>> CHECK:    DW_AT_name [DW_FORM_strp] ( .debug_str[0x00000040] = "basic1.c")
>> +CHECK:    DW_AT_stmt_list [DW_FORM_data4]   (0x00000000)
>> CHECK:    DW_AT_comp_dir [DW_FORM_strp]     ( .debug_str[0x00000049] = "/Inputs")
>> CHECK:    DW_AT_low_pc [DW_FORM_addr]       (0x0000000100000f40)
>> CHECK:    DW_TAG_subprogram [2] *
>> CHECK:      DW_AT_name [DW_FORM_strp]       ( .debug_str[0x00000051] = "main")
>> +CHECK:      DW_AT_decl_file [DW_FORM_data1] ("/Inputs/basic1.c")
>> CHECK:      DW_AT_decl_line [DW_FORM_data1]    (23)
>> CHECK:      DW_AT_prototyped [DW_FORM_flag]    (0x01)
>> CHECK:      DW_AT_type [DW_FORM_ref4]       (cu + 0x0063 => {0x00000063})
>> @@ -52,11 +54,13 @@ CHECK:  Compile Unit:
>> CHECK:  DW_TAG_compile_unit [1] *
>> CHECK:    DW_AT_producer [DW_FORM_strp]     ( .debug_str[0x00000001] = "Apple LLVM version 6.0 (clang-600.0.39) (based on LLVM 3.5svn)")
>> CHECK:    DW_AT_name [DW_FORM_strp] ( .debug_str[0x00000069] = "basic2.c")
>> +CHECK:    DW_AT_stmt_list [DW_FORM_data4]   (0x0000003e)
>> CHECK:    DW_AT_comp_dir [DW_FORM_strp]     ( .debug_str[0x00000049] = "/Inputs")
>> CHECK:   DW_AT_low_pc [DW_FORM_addr]       (0x0000000100000f50)
>> CHECK:    DW_TAG_variable [7]
>> CHECK:      DW_AT_name [DW_FORM_strp]       ( .debug_str[0x00000072] = "private_int")
>> CHECK:      DW_AT_type [DW_FORM_ref_addr]   (0x0000000000000063)
>> +CHECK:      DW_AT_decl_file [DW_FORM_data1] ("/Inputs/basic2.c")
>> CHECK:      DW_AT_location [DW_FORM_block1] (<0x09> 03 08 10 00 00 01 00 00 00 )
>> CHECK:    DW_TAG_variable [7]
>> CHECK:      DW_AT_name [DW_FORM_strp]       ( .debug_str[0x0000007e] = "baz")
>> @@ -89,11 +93,13 @@ CHECK:  Compile Unit:
>> CHECK:  DW_TAG_compile_unit [1] *
>> CHECK:    DW_AT_producer [DW_FORM_strp]     ( .debug_str[0x00000001] = "Apple LLVM version 6.0 (clang-600.0.39) (based on LLVM 3.5svn)")
>> CHECK:    DW_AT_name [DW_FORM_strp] ( .debug_str[0x0000008e] = "basic3.c")
>> +CHECK:    DW_AT_stmt_list [DW_FORM_data4]   (0x0000007e)
>> CHECK:    DW_AT_comp_dir [DW_FORM_strp]     ( .debug_str[0x00000049] = "/Inputs")
>> CHECK:    DW_AT_low_pc [DW_FORM_addr]       (0x0000000100000f90)
>> CHECK:    DW_TAG_variable [12]
>> CHECK:      DW_AT_name [DW_FORM_strp]       ( .debug_str[0x00000097] = "val")
>> CHECK:      DW_AT_type [DW_FORM_ref4]       (cu + 0x003c => {0x00000176})
>> +CHECK:      DW_AT_decl_file [DW_FORM_data1] ("/Inputs/basic3.c")
>> CHECK:      DW_AT_location [DW_FORM_block1] (<0x09> 03 04 10 00 00 01 00 00 00 )
>> CHECK:    DW_TAG_volatile_type [13]
>> CHECK:      DW_AT_type [DW_FORM_ref_addr]   (0x0000000000000063)
>> @@ -142,3 +148,39 @@ CHECK-NEXT: Address Range Header: length
>> CHECK-NEXT: [0x0000000100000f50 - 0x0000000100000f89)
>> CHECK-NEXT: Address Range Header: length = 0x0000002c, version = 0x0002, cu_offset = 0x0000013a, addr_size = 0x08, seg_size = 0x00
>> CHECK-NEXT: [0x0000000100000f90 - 0x0000000100000fb4)
>> +
>> +
>> +CHECK: .debug_line contents
>> +CHECK:                 Dir  Mod Time   File Len   File Name
>> +CHECK-NEXT:                 ---- ---------- ---------- ---------------------------
>> +CHECK-NEXT: file_names[  1]    0 0x00000000 0x00000000 basic1.c
>> +CHECK: Address            Line   Column File   ISA Discriminator Flags
>> +CHECK-NEXT: ------------------ ------ ------ ------ --- ------------- -------------
>> +CHECK-NEXT: 0x0000000100000f40     23      0      1   0             0  is_stmt
>> +CHECK-NEXT: 0x0000000100000f44     24      0      1   0             0  is_stmt prologue_end
>> +CHECK-NEXT: 0x0000000100000f4b     24      0      1   0             0  is_stmt end_sequence
>> +
>> +CHECK:                 Dir  Mod Time   File Len   File Name
>> +CHECK-NEXT:                 ---- ---------- ---------- ---------------------------
>> +CHECK-NEXT: file_names[  1]    0 0x00000000 0x00000000 basic2.c
>> +CHECK: Address            Line   Column File   ISA Discriminator Flags
>> +CHECK-NEXT: ------------------ ------ ------ ------ --- ------------- -------------
>> +CHECK-NEXT: 0x0000000100000f50     19      0      1   0             0  is_stmt
>> +CHECK-NEXT: 0x0000000100000f54     20      0      1   0             0  is_stmt prologue_end
>> +CHECK-NEXT: 0x0000000100000f63     15      0      1   0             0  is_stmt
>> +CHECK-NEXT: 0x0000000100000f72     20      0      1   0             0  is_stmt
>> +CHECK-NEXT: 0x0000000100000f89     20      0      1   0             0  is_stmt end_sequence
>> +
>> +CHECK:                 Dir  Mod Time   File Len   File Name
>> +CHECK-NEXT:                 ---- ---------- ---------- ---------------------------
>> +CHECK-NEXT: file_names[  1]    0 0x00000000 0x00000000 basic3.c
>> +CHECK: Address            Line   Column File   ISA Discriminator Flags
>> +CHECK-NEXT: ------------------ ------ ------ ------ --- ------------- -------------
>> +CHECK-NEXT: 0x0000000100000f90     16      0      1   0             0  is_stmt
>> +CHECK-NEXT: 0x0000000100000f94     12      0      1   0             0  is_stmt prologue_end
>> +CHECK-NEXT: 0x0000000100000f9a     17      0      1   0             0  is_stmt
>> +CHECK-NEXT: 0x0000000100000f9f     12      0      1   0             0  is_stmt
>> +CHECK-NEXT: 0x0000000100000fa7     20      0      1   0             0  is_stmt
>> +CHECK-NEXT: 0x0000000100000fa9     19      0      1   0             0  is_stmt
>> +CHECK-NEXT: 0x0000000100000fb2     20      0      1   0             0  is_stmt
>> +CHECK-NEXT: 0x0000000100000fb4     20      0      1   0             0  is_stmt end_sequence
>> 
>> Modified: llvm/trunk/tools/dsymutil/DwarfLinker.cpp
>> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/dsymutil/DwarfLinker.cpp?rev=232333&r1=232332&r2=232333&view=diff
>> ==============================================================================
>> --- llvm/trunk/tools/dsymutil/DwarfLinker.cpp (original)
>> +++ llvm/trunk/tools/dsymutil/DwarfLinker.cpp Sun Mar 15 15:45:43 2015
>> @@ -22,6 +22,7 @@
>> #include "llvm/MC/MCAsmInfo.h"
>> #include "llvm/MC/MCContext.h"
>> #include "llvm/MC/MCCodeEmitter.h"
>> +#include "llvm/MC/MCDwarf.h"
>> #include "llvm/MC/MCInstrInfo.h"
>> #include "llvm/MC/MCObjectFileInfo.h"
>> #include "llvm/MC/MCRegisterInfo.h"
>> @@ -339,6 +340,7 @@ class DwarfStreamer {
>> 
>>   uint32_t RangesSectionSize;
>>   uint32_t LocSectionSize;
>> +  uint32_t LineSectionSize;
>> 
>> public:
>>   /// \brief Actually create the streamer and the ouptut file.
>> @@ -392,6 +394,14 @@ public:
>>   /// the entries from \p Dwarf and offseting them. Update the
>>   /// location attributes to point to the new entries.
>>   void emitLocationsForUnit(const CompileUnit &Unit, DWARFContext &Dwarf);
>> +
>> +  /// \brief Emit the line table described in \p Rows into the
>> +  /// debug_line section.
>> +  void emitLineTableForUnit(StringRef PrologueBytes, unsigned MinInstLength,
>> +                            std::vector<DWARFDebugLine::Row> &Rows,
>> +                            unsigned AdddressSize);
>> +
>> +  uint32_t getLineSectionSize() const { return LineSectionSize; }
>> };
>> 
>> bool DwarfStreamer::init(Triple TheTriple, StringRef OutputFilename) {
>> @@ -459,6 +469,7 @@ bool DwarfStreamer::init(Triple TheTripl
>> 
>>   RangesSectionSize = 0;
>>   LocSectionSize = 0;
>> +  LineSectionSize = 0;
>> 
>>   return true;
>> }
>> @@ -694,6 +705,151 @@ void DwarfStreamer::emitLocationsForUnit
>>   }
>> }
>> 
>> +void DwarfStreamer::emitLineTableForUnit(StringRef PrologueBytes,
>> +                                         unsigned MinInstLength,
>> +                                         std::vector<DWARFDebugLine::Row> &Rows,
>> +                                         unsigned PointerSize) {
>> +  // Switch to the section where the table will be emitted into.
>> +  MS->SwitchSection(MC->getObjectFileInfo()->getDwarfLineSection());
>> +  MCSymbol *LineStartSym = MC->CreateTempSymbol();
>> +  MCSymbol *LineEndSym = MC->CreateTempSymbol();
>> +
>> +  // The first 4 bytes is the total length of the information for this
>> +  // compilation unit (not including these 4 bytes for the length).
>> +  Asm->EmitLabelDifference(LineEndSym, LineStartSym, 4);
>> +  Asm->OutStreamer.EmitLabel(LineStartSym);
>> +  // Copy Prologue.
>> +  MS->EmitBytes(PrologueBytes);
>> +  LineSectionSize += PrologueBytes.size() + 4;
>> +
>> +  SmallString<16> EncodingBuffer;
>> +  raw_svector_ostream EncodingOS(EncodingBuffer);
>> +
>> +  if (Rows.empty()) {
>> +    // We only have the dummy entry, dsymutil emits an entry with a 0
>> +    // address in that case.
>> +    MCDwarfLineAddr::Encode(*MC, INT64_MAX, 0, EncodingOS);
>> +    MS->EmitBytes(EncodingOS.str());
>> +    LineSectionSize += EncodingBuffer.size();
>> +    EncodingBuffer.resize(0);
>> +    MS->EmitLabel(LineEndSym);
>> +    return;
>> +  }
>> +
>> +  // Line table state machine fields
>> +  unsigned FileNum = 1;
>> +  unsigned LastLine = 1;
>> +  unsigned Column = 0;
>> +  unsigned IsStatement = 1;
>> +  unsigned Isa = 0;
>> +  uint64_t Address = -1ULL;
>> +
>> +  unsigned RowsSinceLastSequence = 0;
>> +
>> +  for (unsigned Idx = 0; Idx < Rows.size(); ++Idx) {
>> +    auto &Row = Rows[Idx];
>> +
>> +    int64_t AddressDelta;
>> +    if (Address == -1ULL) {
>> +      MS->EmitIntValue(dwarf::DW_LNS_extended_op, 1);
>> +      MS->EmitULEB128IntValue(PointerSize + 1);
>> +      MS->EmitIntValue(dwarf::DW_LNE_set_address, 1);
>> +      MS->EmitIntValue(Row.Address, PointerSize);
>> +      LineSectionSize += 2 + PointerSize + getULEB128Size(PointerSize + 1);
>> +      AddressDelta = 0;
>> +    } else {
>> +      AddressDelta = (Row.Address - Address) / MinInstLength;
>> +    }
>> +
>> +    // FIXME: code copied and transfromed from
>> +    // MCDwarf.cpp::EmitDwarfLineTable. We should find a way to share
>> +    // this code, but the current compatibility requirement with
>> +    // classic dsymutil makes it hard. Revisit that once this
>> +    // requirement is dropped.
>> +
>> +    if (FileNum != Row.File) {
>> +      FileNum = Row.File;
>> +      MS->EmitIntValue(dwarf::DW_LNS_set_file, 1);
>> +      MS->EmitULEB128IntValue(FileNum);
>> +      LineSectionSize += 1 + getULEB128Size(FileNum);
>> +    }
>> +    if (Column != Row.Column) {
>> +      Column = Row.Column;
>> +      MS->EmitIntValue(dwarf::DW_LNS_set_column, 1);
>> +      MS->EmitULEB128IntValue(Column);
>> +      LineSectionSize += 1 + getULEB128Size(Column);
>> +    }
>> +
>> +    // FIXME: We should handle the discriminator here, but dsymutil
>> +    // doesn' consider it, thus ignore it for now.
>> +
>> +    if (Isa != Row.Isa) {
>> +      Isa = Row.Isa;
>> +      MS->EmitIntValue(dwarf::DW_LNS_set_isa, 1);
>> +      MS->EmitULEB128IntValue(Isa);
>> +      LineSectionSize += 1 + getULEB128Size(Isa);
>> +    }
>> +    if (IsStatement != Row.IsStmt) {
>> +      IsStatement = Row.IsStmt;
>> +      MS->EmitIntValue(dwarf::DW_LNS_negate_stmt, 1);
>> +      LineSectionSize += 1;
>> +    }
>> +    if (Row.BasicBlock) {
>> +      MS->EmitIntValue(dwarf::DW_LNS_set_basic_block, 1);
>> +      LineSectionSize += 1;
>> +    }
>> +
>> +    if (Row.PrologueEnd) {
>> +      MS->EmitIntValue(dwarf::DW_LNS_set_prologue_end, 1);
>> +      LineSectionSize += 1;
>> +    }
>> +
>> +    if (Row.EpilogueBegin) {
>> +      MS->EmitIntValue(dwarf::DW_LNS_set_epilogue_begin, 1);
>> +      LineSectionSize += 1;
>> +    }
>> +
>> +    int64_t LineDelta = int64_t(Row.Line) - LastLine;
>> +    if (!Row.EndSequence) {
>> +      MCDwarfLineAddr::Encode(*MC, LineDelta, AddressDelta, EncodingOS);
>> +      MS->EmitBytes(EncodingOS.str());
>> +      LineSectionSize += EncodingBuffer.size();
>> +      EncodingBuffer.resize(0);
>> +      Address = Row.Address;
>> +      LastLine = Row.Line;
>> +      RowsSinceLastSequence++;
>> +    } else {
>> +      if (LineDelta) {
>> +        MS->EmitIntValue(dwarf::DW_LNS_advance_line, 1);
>> +        MS->EmitSLEB128IntValue(LineDelta);
>> +        LineSectionSize += 1 + getSLEB128Size(LineDelta);
>> +      }
>> +      if (AddressDelta) {
>> +        MS->EmitIntValue(dwarf::DW_LNS_advance_pc, 1);
>> +        MS->EmitULEB128IntValue(AddressDelta);
>> +        LineSectionSize += 1 + getULEB128Size(AddressDelta);
>> +      }
>> +      MCDwarfLineAddr::Encode(*MC, INT64_MAX, 0, EncodingOS);
>> +      MS->EmitBytes(EncodingOS.str());
>> +      LineSectionSize += EncodingBuffer.size();
>> +      EncodingBuffer.resize(0);
>> +
>> +      Address = -1ULL;
>> +      LastLine = FileNum = IsStatement = 1;
>> +      RowsSinceLastSequence = Column = Isa = 0;
>> +    }
>> +  }
>> +
>> +  if (RowsSinceLastSequence) {
>> +    MCDwarfLineAddr::Encode(*MC, INT64_MAX, 0, EncodingOS);
>> +    MS->EmitBytes(EncodingOS.str());
>> +    LineSectionSize += EncodingBuffer.size();
>> +    EncodingBuffer.resize(0);
>> +  }
>> +
>> +  MS->EmitLabel(LineEndSym);
>> +}
>> +
>> /// \brief The core of the Dwarf linking logic.
>> ///
>> /// The link of the dwarf information from the object files will be
>> @@ -724,7 +880,7 @@ public:
>> 
>> private:
>>   /// \brief Called at the start of a debug object link.
>> -  void startDebugObject(DWARFContext &);
>> +  void startDebugObject(DWARFContext &, DebugMapObject &);
>> 
>>   /// \brief Called at the end of a debug object link.
>>   void endDebugObject();
>> @@ -893,6 +1049,11 @@ private:
>>   /// compile_unit if it had one.
>>   void generateUnitRanges(CompileUnit &Unit) const;
>> 
>> +  /// \brief Extract the line tables fromt he original dwarf, extract
>> +  /// the relevant parts according to the linked function ranges and
>> +  /// emit the result in the debug_line section.
>> +  void patchLineTableForUnit(CompileUnit &Unit, DWARFContext &OrigDwarf);
>> +
>>   /// \brief DIELoc objects that need to be destructed (but not freed!).
>>   std::vector<DIELoc *> DIELocs;
>>   /// \brief DIEBlock objects that need to be destructed (but not freed!).
>> @@ -931,6 +1092,14 @@ private:
>> 
>>   /// \brief The Dwarf string pool
>>   NonRelocatableStringpool StringPool;
>> +
>> +  /// \brief This map is keyed by the entry PC of functions in that
>> +  /// debug object and the associated value is a pair storing the
>> +  /// corresponding end PC and the offset to apply to get the linked
>> +  /// address.
>> +  ///
>> +  /// See startDebugObject() for a more complete description of its use.
>> +  std::map<uint64_t, std::pair<uint64_t, int64_t>> Ranges;
>> };
>> 
>> /// \brief Similar to DWARFUnitSection::getUnitForOffset(), but
>> @@ -1015,14 +1184,36 @@ static bool dieNeedsChildrenToBeMeaningf
>>   llvm_unreachable("Invalid Tag");
>> }
>> 
>> -void DwarfLinker::startDebugObject(DWARFContext &Dwarf) {
>> +void DwarfLinker::startDebugObject(DWARFContext &Dwarf, DebugMapObject &Obj) {
>>   Units.reserve(Dwarf.getNumCompileUnits());
>>   NextValidReloc = 0;
>> +  // Iterate over the debug map entries and put all the ones that are
>> +  // functions (because they have a size) into the Ranges map. This
>> +  // map is very similar to the FunctionRanges that are stored in each
>> +  // unit, with 2 notable differences:
>> +  //  - obviously this one is global, while the other ones are per-unit.
>> +  //  - this one contains not only the functions described in the DIE
>> +  // tree, but also the ones that are only in the debug map.
>> +  // The latter information is required to reproduce dsymutil's logic
>> +  // while linking line tables. The cases where this information
>> +  // matters look like bugs that need to be investigated, but for now
>> +  // we need to reproduce dsymutil's behavior.
>> +  // FIXME: Once we understood exactly if that information is needed,
>> +  // maybe totally remove this (or try to use it to do a real
>> +  // -gline-tables-only on Darwin.
>> +  for (const auto &Entry : Obj.symbols()) {
>> +    const auto &Mapping = Entry.getValue();
>> +    if (Mapping.Size)
>> +      Ranges[Mapping.ObjectAddress] = std::make_pair(
>> +          Mapping.ObjectAddress + Mapping.Size,
>> +          int64_t(Mapping.BinaryAddress) - Mapping.ObjectAddress);
>> +  }
>> }
>> 
>> void DwarfLinker::endDebugObject() {
>>   Units.clear();
>>   ValidRelocs.clear();
>> +  Ranges.clear();
>> 
>>   for (auto *Block : DIEBlocks)
>>     Block->~DIEBlock();
>> @@ -1259,6 +1450,8 @@ unsigned DwarfLinker::shouldKeepSubprogr
>>     HighPc = LowPc + *HighPcValue.getAsUnsignedConstant();
>>   }
>> 
>> +  // Replace the debug map range with a more accurate one.
>> +  Ranges[LowPc] = std::make_pair(HighPc, MyInfo.AddrAdjust);
>>   Unit.addFunctionRange(LowPc, HighPc, MyInfo.AddrAdjust);
>>   return Flags;
>> }
>> @@ -1854,6 +2047,176 @@ void DwarfLinker::generateUnitRanges(Com
>>   Streamer->emitUnitRangesEntries(Unit, Attr != nullptr);
>> }
>> 
>> +/// \brief Insert the new line info sequence \p Seq into the current
>> +/// set of already linked line info \p Rows.
>> +static void insertLineSequence(std::vector<DWARFDebugLine::Row> &Seq,
>> +                               std::vector<DWARFDebugLine::Row> &Rows) {
>> +  if (Seq.empty())
>> +    return;
>> +
>> +  if (!Rows.empty() && Rows.back().Address < Seq.front().Address) {
>> +    Rows.insert(Rows.end(), Seq.begin(), Seq.end());
>> +    Seq.clear();
>> +    return;
>> +  }
>> +
>> +  auto InsertPoint = std::lower_bound(
>> +      Rows.begin(), Rows.end(), Seq.front(),
>> +      [](const DWARFDebugLine::Row &LHS, const DWARFDebugLine::Row &RHS) {
>> +        return LHS.Address < RHS.Address;
>> +      });
>> +
>> +  // FIXME: this only removes the unneeded end_sequence if the
>> +  // sequences have been inserted in order. using a global sort like
>> +  // described in patchLineTableForUnit() and delaying the end_sequene
>> +  // elimination to emitLineTableForUnit() we can get rid of all of them.
>> +  if (InsertPoint != Rows.end() &&
>> +      InsertPoint->Address == Seq.front().Address && InsertPoint->EndSequence) {
>> +    *InsertPoint = Seq.front();
>> +    Rows.insert(InsertPoint + 1, Seq.begin() + 1, Seq.end());
>> +  } else {
>> +    Rows.insert(InsertPoint, Seq.begin(), Seq.end());
>> +  }
>> +
>> +  Seq.clear();
>> +}
>> +
>> +/// \brief Extract the line table for \p Unit from \p OrigDwarf, and
>> +/// recreate a relocated version of these for the address ranges that
>> +/// are present in the binary.
>> +void DwarfLinker::patchLineTableForUnit(CompileUnit &Unit,
>> +                                        DWARFContext &OrigDwarf) {
>> +  const DWARFDebugInfoEntryMinimal *CUDie =
>> +      Unit.getOrigUnit().getCompileUnitDIE();
>> +  uint64_t StmtList = CUDie->getAttributeValueAsSectionOffset(
>> +      &Unit.getOrigUnit(), dwarf::DW_AT_stmt_list, -1ULL);
>> +  if (StmtList == -1ULL)
>> +    return;
>> +
>> +  // Update the cloned DW_AT_stmt_list with the correct debug_line offset.
>> +  if (auto *OutputDIE = Unit.getOutputUnitDIE()) {
>> +    const auto &Abbrev = OutputDIE->getAbbrev().getData();
>> +    auto Stmt = std::find_if(
>> +        Abbrev.begin(), Abbrev.end(), [](const DIEAbbrevData &AbbrevData) {
>> +          return AbbrevData.getAttribute() == dwarf::DW_AT_stmt_list;
>> +        });
>> +    assert(Stmt < Abbrev.end() && "Didn't find DW_AT_stmt_list in cloned DIE!");
>> +    DIEInteger *StmtAttr =
>> +        cast<DIEInteger>(OutputDIE->getValues()[Stmt - Abbrev.begin()]);
>> +    StmtAttr->setValue(Streamer->getLineSectionSize());
>> +  }
>> +
>> +  // Parse the original line info for the unit.
>> +  DWARFDebugLine::LineTable LineTable;
>> +  uint32_t StmtOffset = StmtList;
>> +  StringRef LineData = OrigDwarf.getLineSection().Data;
>> +  DataExtractor LineExtractor(LineData, OrigDwarf.isLittleEndian(),
>> +                              Unit.getOrigUnit().getAddressByteSize());
>> +  LineTable.parse(LineExtractor, &OrigDwarf.getLineSection().Relocs,
>> +                  &StmtOffset);
>> +
>> +  // This vector is the output line table.
>> +  std::vector<DWARFDebugLine::Row> NewRows;
>> +  NewRows.reserve(LineTable.Rows.size());
>> +
>> +  // Current sequence of rows being extracted, before being inserted
>> +  // in NewRows.
>> +  std::vector<DWARFDebugLine::Row> Seq;
>> +  const auto &FunctionRanges = Unit.getFunctionRanges();
>> +  auto InvalidRange = FunctionRanges.end(), CurrRange = InvalidRange;
>> +
>> +  // FIXME: This logic is meant to generate exactly the same output as
>> +  // Darwin's classic dsynutil. There is a nicer way to implement this
>> +  // by simply putting all the relocated line info in NewRows and simply
>> +  // sorting NewRows before passing it to emitLineTableForUnit. This
>> +  // should be correct as sequences for a function should stay
>> +  // together in the sorted output. There are a few corner cases that
>> +  // look suspicious though, and that required to implement the logic
>> +  // this way. Revisit that once initial validation is finished.
>> +
>> +  // Iterate over the object file line info and extract the sequences
>> +  // that correspond to linked functions.
>> +  for (auto &Row : LineTable.Rows) {
>> +    // Check wether we stepped out of the range. The range is
>> +    // half-open, but consider accept the end address of the range if
>> +    // it is marked as end_sequence in the input (because in that
>> +    // case, the relocation offset is accurate and that entry won't
>> +    // serve as the start of another function).
>> +    if (CurrRange == InvalidRange || Row.Address < CurrRange.start() ||
>> +        Row.Address > CurrRange.stop() ||
>> +        (Row.Address == CurrRange.stop() && !Row.EndSequence)) {
>> +      // We just stepped out of a known range. Insert a end_sequence
>> +      // corresponding to the end of the range.
>> +      uint64_t StopAddress = CurrRange != InvalidRange
>> +                                 ? CurrRange.stop() + CurrRange.value()
>> +                                 : -1ULL;
>> +      CurrRange = FunctionRanges.find(Row.Address);
>> +      bool CurrRangeValid =
>> +          CurrRange != InvalidRange && CurrRange.start() <= Row.Address;
>> +      if (!CurrRangeValid) {
>> +        CurrRange = InvalidRange;
>> +        if (StopAddress != -1ULL) {
>> +          // Try harder by looking in the DebugMapObject function
>> +          // ranges map. There are corner cases where this finds a
>> +          // valid entry. It's unclear if this is right or wrong, but
>> +          // for now do as dsymutil.
>> +          // FIXME: Understand exactly what cases this addresses and
>> +          // potentially remove it along with the Ranges map.
>> +          auto Range = Ranges.lower_bound(Row.Address);
>> +          if (Range != Ranges.begin() && Range != Ranges.end())
>> +            --Range;
>> +
>> +          if (Range != Ranges.end() && Range->first <= Row.Address &&
>> +              Range->second.first >= Row.Address) {
>> +            StopAddress = Row.Address + Range->second.second;
>> +          }
>> +        }
>> +      }
>> +      if (StopAddress != -1ULL && !Seq.empty()) {
>> +        // Insert end sequence row with the computed end address, but
>> +        // the same line as the previous one.
>> +        Seq.emplace_back(Seq.back());
>> +        Seq.back().Address = StopAddress;
>> +        Seq.back().EndSequence = 1;
>> +        Seq.back().PrologueEnd = 0;
>> +        Seq.back().BasicBlock = 0;
>> +        Seq.back().EpilogueBegin = 0;
>> +        insertLineSequence(Seq, NewRows);
>> +      }
>> +
>> +      if (!CurrRangeValid)
>> +        continue;
>> +    }
>> +
>> +    // Ignore empty sequences.
>> +    if (Row.EndSequence && Seq.empty())
>> +      continue;
>> +
>> +    // Relocate row address and add it to the current sequence.
>> +    Row.Address += CurrRange.value();
>> +    Seq.emplace_back(Row);
>> +
>> +    if (Row.EndSequence)
>> +      insertLineSequence(Seq, NewRows);
>> +  }
>> +
>> +  // Finished extracting, now emit the line tables.
>> +  uint32_t PrologueEnd = StmtList + 10 + LineTable.Prologue.PrologueLength;
>> +  // FIXME: LLVM hardcodes it's prologue values. We just copy the
>> +  // prologue over and that works because we act as both producer and
>> +  // consumer. It would be nicer to have a real configurable line
>> +  // table emitter.
>> +  if (LineTable.Prologue.Version != 2 ||
>> +      LineTable.Prologue.DefaultIsStmt != DWARF2_LINE_DEFAULT_IS_STMT ||
>> +      LineTable.Prologue.LineBase != -5 || LineTable.Prologue.LineRange != 14 ||
>> +      LineTable.Prologue.OpcodeBase != 13)
>> +    reportWarning("line table paramters mismatch. Cannot emit.");
>> +  else
>> +    Streamer->emitLineTableForUnit(LineData.slice(StmtList + 4, PrologueEnd),
>> +                                   LineTable.Prologue.MinInstLength, NewRows,
>> +                                   Unit.getOrigUnit().getAddressByteSize());
>> +}
>> +
>> bool DwarfLinker::link(const DebugMap &Map) {
>> 
>>   if (Map.begin() == Map.end()) {
>> @@ -1888,7 +2251,7 @@ bool DwarfLinker::link(const DebugMap &M
>> 
>>     // Setup access to the debug info.
>>     DWARFContextInMemory DwarfContext(*ErrOrObj);
>> -    startDebugObject(DwarfContext);
>> +    startDebugObject(DwarfContext, *Obj);
>> 
>>     // In a first phase, just read in the debug info and store the DIE
>>     // parent links that we will use during the next phase.
>> @@ -1927,7 +2290,13 @@ bool DwarfLinker::link(const DebugMap &M
>>                                   11 /* Unit Header size */);
>>         CurrentUnit.setOutputUnitDIE(OutputDIE);
>>         OutputDebugInfoSize = CurrentUnit.computeNextUnitOffset();
>> -        if (!OutputDIE || Options.NoOutput)
>> +        if (Options.NoOutput)
>> +          continue;
>> +        // FIXME: for compatibility with the classic dsymutil, we emit
>> +        // an empty line table for the unit, even if the unit doesn't
>> +        // actually exist in the DIE tree.
>> +        patchLineTableForUnit(CurrentUnit, DwarfContext);
>> +        if (!OutputDIE)
>>           continue;
>>         patchRangesForUnit(CurrentUnit, DwarfContext);
>>         Streamer->emitLocationsForUnit(CurrentUnit, DwarfContext);
>> 
>> 
>> _______________________________________________
>> llvm-commits mailing list
>> llvm-commits at cs.uiuc.edu
>> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20150324/c6f22055/attachment.html>


More information about the llvm-commits mailing list