@@ -8,6 +8,7 @@ package obj
8
8
9
9
import (
10
10
"cmd/internal/dwarf"
11
+ "cmd/internal/src"
11
12
"fmt"
12
13
)
13
14
@@ -31,95 +32,51 @@ const (
31
32
func (ctxt * Link ) generateDebugLinesSymbol (s , lines * LSym ) {
32
33
dctxt := dwCtxt {ctxt }
33
34
34
- // The Pcfile table is used to generate the debug_lines section, and the file
35
- // indices for that data could differ from the files we write out for the
36
- // debug_lines section. Here we generate a LUT between those two indices.
37
- fileNums := make (map [int32 ]int64 )
38
- for i , filename := range s .Func .Pcln .File {
39
- if symbolIndex := ctxt .PosTable .FileIndex (filename ); symbolIndex >= 0 {
40
- fileNums [int32 (i )] = int64 (symbolIndex ) + 1
41
- } else {
42
- panic (fmt .Sprintf ("First time we've seen filename: %q" , filename ))
43
- }
44
- }
45
-
46
35
// Set up the debug_lines state machine.
47
36
// NB: This state machine is reset to this state when we've finished
48
37
// generating the line table. See below.
49
38
// TODO: Once delve can support multiple DW_LNS_end_statements, we don't have
50
39
// to do this.
51
- is_stmt := uint8 (1 )
40
+ stmt := true
41
+ line := int64 (1 )
52
42
pc := s .Func .Text .Pc
53
- line := 1
54
- file := 1
55
-
56
- // The linker will insert the DW_LNE_set_address once determined; therefore,
57
- // it's omitted here.
58
-
59
- // Generate the actual line information.
60
- // We use the pcline and pcfile to generate this section, and it's suboptimal.
61
- // Likely better would be to generate this dirrectly from the progs and not
62
- // parse those tables.
63
- // TODO: Generate from the progs if it's faster.
64
- pcfile := NewPCIter (uint32 (ctxt .Arch .Arch .MinLC ))
65
- pcline := NewPCIter (uint32 (ctxt .Arch .Arch .MinLC ))
66
- pcstmt := NewPCIter (uint32 (ctxt .Arch .Arch .MinLC ))
67
- pcfile .Init (s .Func .Pcln .Pcfile .P )
68
- pcline .Init (s .Func .Pcln .Pcline .P )
69
- var pctostmtData Pcdata
70
- funcpctab (ctxt , & pctostmtData , s , "pctostmt" , pctostmt , nil )
71
- pcstmt .Init (pctostmtData .P )
72
- var thispc uint32
73
-
74
- for ! pcfile .Done && ! pcline .Done {
75
- // Only changed if it advanced
76
- if int32 (file ) != pcfile .Value {
77
- dctxt .AddUint8 (lines , dwarf .DW_LNS_set_file )
78
- dwarf .Uleb128put (dctxt , lines , fileNums [pcfile .Value ])
79
- file = int (pcfile .Value )
43
+ name := ""
44
+ prologue , wrotePrologue := false , false
45
+
46
+ // Walk the progs, generating the DWARF table.
47
+ for p := s .Func .Text ; p != nil ; p = p .Link {
48
+ prologue = prologue || (p .Pos .Xlogue () == src .PosPrologueEnd )
49
+ // If we're not at a real instruction, keep looping!
50
+ if p .Pos .Line () == 0 || (p .Link != nil && p .Link .Pc == pc ) {
51
+ continue
80
52
}
53
+ newStmt := p .Pos .IsStmt () != src .PosNotStmt
54
+ newName , newLine := linkgetlineFromPos (ctxt , p .Pos )
81
55
82
- // Only changed if it advanced
83
- if is_stmt != uint8 (pcstmt .Value ) {
84
- new_stmt := uint8 (pcstmt .Value )
85
- switch new_stmt &^ 1 {
86
- case PrologueEnd :
87
- dctxt .AddUint8 (lines , uint8 (dwarf .DW_LNS_set_prologue_end ))
88
- case EpilogueBegin :
89
- // TODO if there is a use for this, add it.
90
- // Don't forget to increase OPCODE_BASE by 1 and add entry for standard_opcode_lengths[11]
91
- panic ("unsupported EpilogueBegin" )
92
- }
93
- new_stmt &= 1
94
- if is_stmt != new_stmt {
95
- is_stmt = new_stmt
96
- dctxt .AddUint8 (lines , uint8 (dwarf .DW_LNS_negate_stmt ))
97
- }
56
+ // Output debug info.
57
+ wrote := false
58
+ if name != newName {
59
+ newFile := ctxt .PosTable .FileIndex (newName ) + 1 // 1 indexing for the table.
60
+ dctxt .AddUint8 (lines , dwarf .DW_LNS_set_file )
61
+ dwarf .Uleb128put (dctxt , lines , int64 (newFile ))
62
+ name = newName
63
+ wrote = true
98
64
}
99
-
100
- // putpcldelta makes a row in the DWARF matrix, always, even if line is unchanged.
101
- putpclcdelta (ctxt , dctxt , lines , uint64 (s .Func .Text .Pc + int64 (thispc )- pc ), int64 (pcline .Value )- int64 (line ))
102
-
103
- pc = s .Func .Text .Pc + int64 (thispc )
104
- line = int (pcline .Value )
105
-
106
- // Take the minimum step forward for the three iterators
107
- thispc = pcfile .NextPC
108
- if pcline .NextPC < thispc {
109
- thispc = pcline .NextPC
65
+ if prologue && ! wrotePrologue {
66
+ dctxt .AddUint8 (lines , uint8 (dwarf .DW_LNS_set_prologue_end ))
67
+ wrotePrologue = true
68
+ wrote = true
110
69
}
111
- if ! pcstmt .Done && pcstmt .NextPC < thispc {
112
- thispc = pcstmt .NextPC
70
+ if stmt != newStmt {
71
+ dctxt .AddUint8 (lines , uint8 (dwarf .DW_LNS_negate_stmt ))
72
+ stmt = newStmt
73
+ wrote = true
113
74
}
114
75
115
- if pcfile .NextPC == thispc {
116
- pcfile .Next ()
117
- }
118
- if ! pcstmt .Done && pcstmt .NextPC == thispc {
119
- pcstmt .Next ()
120
- }
121
- if pcline .NextPC == thispc {
122
- pcline .Next ()
76
+ if line != int64 (newLine ) || wrote {
77
+ pcdelta := (p .Pc - pc ) / int64 (ctxt .Arch .MinLC )
78
+ putpclcdelta (ctxt , dctxt , lines , uint64 (pcdelta ), int64 (newLine )- line )
79
+ line , pc = int64 (newLine ), p .Pc
123
80
}
124
81
}
125
82
@@ -129,16 +86,16 @@ func (ctxt *Link) generateDebugLinesSymbol(s, lines *LSym) {
129
86
// file = 1
130
87
// line = 1
131
88
// column = 0
132
- // is_stmt = set in header, we assume true
89
+ // stmt = set in header, we assume true
133
90
// basic_block = false
134
91
// Careful readers of the DWARF specification will note that we don't reset
135
92
// the address of the state machine -- but this will happen at the beginning
136
- // of the NEXT block of opcodes. (See the SetAddress call above.)
93
+ // of the NEXT block of opcodes.
137
94
dctxt .AddUint8 (lines , dwarf .DW_LNS_set_file )
138
95
dwarf .Uleb128put (dctxt , lines , 1 )
139
96
dctxt .AddUint8 (lines , dwarf .DW_LNS_advance_line )
140
97
dwarf .Sleb128put (dctxt , lines , int64 (1 - line ))
141
- if is_stmt != 1 {
98
+ if ! stmt {
142
99
dctxt .AddUint8 (lines , dwarf .DW_LNS_negate_stmt )
143
100
}
144
101
dctxt .AddUint8 (lines , dwarf .DW_LNS_copy )
0 commit comments