diff --git a/_fixtures/zdebug_line_dwarf4 b/_fixtures/zdebug_line_dwarf4 new file mode 100644 index 0000000000000000000000000000000000000000..7e9a016d27201c9b77d7eadd7c18f6df83a1126d Binary files /dev/null and b/_fixtures/zdebug_line_dwarf4 differ diff --git a/pkg/dwarf/line/line_parser.go b/pkg/dwarf/line/line_parser.go index d076199373e2ac81b0fcafdb53d8173c857505ef..71dac59fde9c875581b179c95e1bf5da45db5c07 100644 --- a/pkg/dwarf/line/line_parser.go +++ b/pkg/dwarf/line/line_parser.go @@ -14,6 +14,7 @@ type DebugLinePrologue struct { Version uint16 Length uint32 MinInstrLength uint8 + MaxOpPerInstr uint8 InitialIsStmt uint8 LineBase int8 LineRange uint8 @@ -41,7 +42,7 @@ type DebugLineInfo struct { // if normalizeBackslash is true all backslashes (\) will be converted into forward slashes (/) normalizeBackslash bool - ptrSize int + ptrSize int } type FileEntry struct { @@ -102,6 +103,11 @@ func parseDebugLinePrologue(dbl *DebugLineInfo, buf *bytes.Buffer) { p.Version = binary.LittleEndian.Uint16(buf.Next(2)) p.Length = binary.LittleEndian.Uint32(buf.Next(4)) p.MinInstrLength = uint8(buf.Next(1)[0]) + if p.Version == 4 { + p.MaxOpPerInstr = uint8(buf.Next(1)[0]) + } else { + p.MaxOpPerInstr = 1 + } p.InitialIsStmt = uint8(buf.Next(1)[0]) p.LineBase = int8(buf.Next(1)[0]) p.LineRange = uint8(buf.Next(1)[0]) diff --git a/pkg/dwarf/line/line_parser_test.go b/pkg/dwarf/line/line_parser_test.go index ac3c2405b7e7e5e8cabd0d160dcb6a5dca2795bf..d2e3ba5bea9c510c3a714ac27e4c94c1b69c008a 100644 --- a/pkg/dwarf/line/line_parser_test.go +++ b/pkg/dwarf/line/line_parser_test.go @@ -1,6 +1,7 @@ package line import ( + "compress/zlib" "debug/elf" "debug/macho" "debug/pe" @@ -342,3 +343,38 @@ func TestDebugLineC(t *testing.T) { } } } + +func TestDebugLineDwarf4(t *testing.T) { + p, err := filepath.Abs("../../../_fixtures/zdebug_line_dwarf4") + if err != nil { + t.Fatal("Could not find test data", p, err) + } + fh, err := os.Open(p) + if err != nil { + t.Fatal("Could not open test data", err) + } + defer fh.Close() + fh.Seek(12, 0) // skip "ZLIB" magic signature and length + r, err := zlib.NewReader(fh) + if err != nil { + t.Fatal("Could not open test data (zlib)", err) + } + data, err := ioutil.ReadAll(r) + if err != nil { + t.Fatal("Could not read test data", err) + } + + debugLines := ParseAll(data, nil, 0, true, 8) + + for _, dbl := range debugLines { + if dbl.Prologue.Version == 4 { + if dbl.Prologue.LineBase != -5 { + t.Errorf("Wrong LineBase %d\n", dbl.Prologue.LineBase) + } + if dbl.Prologue.LineRange != 14 { + t.Errorf("Wrong LineRange %d\n", dbl.Prologue.LineRange) + } + } + } + +} diff --git a/pkg/dwarf/line/state_machine.go b/pkg/dwarf/line/state_machine.go index b92f88495dbcf5f5b815287536987e0a11c3170a..c307a106c9e70f57be8455825bd568eb62729663 100644 --- a/pkg/dwarf/line/state_machine.go +++ b/pkg/dwarf/line/state_machine.go @@ -77,9 +77,10 @@ const ( // Extended opcodes const ( - DW_LINE_end_sequence = 1 - DW_LINE_set_address = 2 - DW_LINE_define_file = 3 + DW_LINE_end_sequence = 1 + DW_LINE_set_address = 2 + DW_LINE_define_file = 3 + DW_LINE_set_discriminator = 4 ) var standardopcodes = map[byte]opcodefn{ @@ -98,9 +99,10 @@ var standardopcodes = map[byte]opcodefn{ } var extendedopcodes = map[byte]opcodefn{ - DW_LINE_end_sequence: endsequence, - DW_LINE_set_address: setaddress, - DW_LINE_define_file: definefile, + DW_LINE_end_sequence: endsequence, + DW_LINE_set_address: setaddress, + DW_LINE_define_file: definefile, + DW_LINE_set_discriminator: setdiscriminator, } func newStateMachine(dbl *DebugLineInfo, instructions []byte, ptrSize int) *StateMachine { @@ -548,6 +550,10 @@ func setaddress(sm *StateMachine, buf *bytes.Buffer) { sm.address = addr + sm.dbl.staticBase } +func setdiscriminator(sm *StateMachine, buf *bytes.Buffer) { + _, _ = util.DecodeULEB128(buf) +} + func definefile(sm *StateMachine, buf *bytes.Buffer) { entry := readFileEntry(sm.dbl, sm.buf, false) sm.definedFiles = append(sm.definedFiles, entry)