]> Cypherpunks repositories - gostls13.git/commitdiff
Revert "cmd/compile: walk the progs to generate debug_lines"
authorBryan C. Mills <bcmills@google.com>
Thu, 3 Oct 2019 18:07:53 +0000 (18:07 +0000)
committerBryan C. Mills <bcmills@google.com>
Thu, 3 Oct 2019 18:18:14 +0000 (18:18 +0000)
This reverts CL 196661.

Reason for revert: broke TestGdb* tests on mips64le, ppc64le, and s390x builders.

Change-Id: I3b5c97c840819a0d407b943f7cf7e2d97f06042d
Reviewed-on: https://go-review.googlesource.com/c/go/+/198697
Run-TryBot: Bryan C. Mills <bcmills@google.com>
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>

src/cmd/internal/obj/dwarf.go
src/cmd/internal/obj/pcln.go

index 5efafe11b86cb2d9206e09c25733b4863e750949..d8f3de3b692c3daf0b44289287f5eac4cfee31d0 100644 (file)
@@ -8,7 +8,6 @@ package obj
 
 import (
        "cmd/internal/dwarf"
-       "cmd/internal/src"
        "fmt"
 )
 
@@ -32,51 +31,95 @@ const (
 func (ctxt *Link) generateDebugLinesSymbol(s, lines *LSym) {
        dctxt := dwCtxt{ctxt}
 
+       // The Pcfile table is used to generate the debug_lines section, and the file
+       // indices for that data could differ from the files we write out for the
+       // debug_lines section. Here we generate a LUT between those two indices.
+       fileNums := make(map[int32]int64)
+       for i, filename := range s.Func.Pcln.File {
+               if symbolIndex := ctxt.PosTable.FileIndex(filename); symbolIndex >= 0 {
+                       fileNums[int32(i)] = int64(symbolIndex) + 1
+               } else {
+                       panic(fmt.Sprintf("First time we've seen filename: %q", filename))
+               }
+       }
+
        // Set up the debug_lines state machine.
        // NB: This state machine is reset to this state when we've finished
        // generating the line table. See below.
        // TODO: Once delve can support multiple DW_LNS_end_statements, we don't have
        // to do this.
-       stmt := true
-       line := int64(1)
+       is_stmt := uint8(1)
        pc := s.Func.Text.Pc
-       name := ""
-       prologue, wrotePrologue := false, false
-
-       // Walk the progs, generating the DWARF table.
-       for p := s.Func.Text; p != nil; p = p.Link {
-               prologue = prologue || (p.Pos.Xlogue() == src.PosPrologueEnd)
-               // If we're not at a real instruction, keep looping!
-               if p.Pos.Line() == 0 || (p.Link != nil && p.Link.Pc == pc) {
-                       continue
-               }
-               newStmt := p.Pos.IsStmt() != src.PosNotStmt
-               newName, newLine := linkgetlineFromPos(ctxt, p.Pos)
+       line := 1
+       file := 1
+
+       // The linker will insert the DW_LNE_set_address once determined; therefore,
+       // it's omitted here.
 
-               // Output debug info.
-               wrote := false
-               if name != newName {
-                       newFile := ctxt.PosTable.FileIndex(newName) + 1 // 1 indexing for the table.
+       // Generate the actual line information.
+       // We use the pcline and pcfile to generate this section, and it's suboptimal.
+       // Likely better would be to generate this dirrectly from the progs and not
+       // parse those tables.
+       // TODO: Generate from the progs if it's faster.
+       pcfile := NewPCIter(uint32(ctxt.Arch.Arch.MinLC))
+       pcline := NewPCIter(uint32(ctxt.Arch.Arch.MinLC))
+       pcstmt := NewPCIter(uint32(ctxt.Arch.Arch.MinLC))
+       pcfile.Init(s.Func.Pcln.Pcfile.P)
+       pcline.Init(s.Func.Pcln.Pcline.P)
+       var pctostmtData Pcdata
+       funcpctab(ctxt, &pctostmtData, s, "pctostmt", pctostmt, nil)
+       pcstmt.Init(pctostmtData.P)
+       var thispc uint32
+
+       for !pcfile.Done && !pcline.Done {
+               // Only changed if it advanced
+               if int32(file) != pcfile.Value {
                        dctxt.AddUint8(lines, dwarf.DW_LNS_set_file)
-                       dwarf.Uleb128put(dctxt, lines, int64(newFile))
-                       name = newName
-                       wrote = true
+                       dwarf.Uleb128put(dctxt, lines, fileNums[pcfile.Value])
+                       file = int(pcfile.Value)
+               }
+
+               // Only changed if it advanced
+               if is_stmt != uint8(pcstmt.Value) {
+                       new_stmt := uint8(pcstmt.Value)
+                       switch new_stmt &^ 1 {
+                       case PrologueEnd:
+                               dctxt.AddUint8(lines, uint8(dwarf.DW_LNS_set_prologue_end))
+                       case EpilogueBegin:
+                               // TODO if there is a use for this, add it.
+                               // Don't forget to increase OPCODE_BASE by 1 and add entry for standard_opcode_lengths[11]
+                               panic("unsupported EpilogueBegin")
+                       }
+                       new_stmt &= 1
+                       if is_stmt != new_stmt {
+                               is_stmt = new_stmt
+                               dctxt.AddUint8(lines, uint8(dwarf.DW_LNS_negate_stmt))
+                       }
                }
-               if prologue && !wrotePrologue {
-                       dctxt.AddUint8(lines, uint8(dwarf.DW_LNS_set_prologue_end))
-                       wrotePrologue = true
-                       wrote = true
+
+               // putpcldelta makes a row in the DWARF matrix, always, even if line is unchanged.
+               putpclcdelta(ctxt, dctxt, lines, uint64(s.Func.Text.Pc+int64(thispc)-pc), int64(pcline.Value)-int64(line))
+
+               pc = s.Func.Text.Pc + int64(thispc)
+               line = int(pcline.Value)
+
+               // Take the minimum step forward for the three iterators
+               thispc = pcfile.NextPC
+               if pcline.NextPC < thispc {
+                       thispc = pcline.NextPC
                }
-               if stmt != newStmt {
-                       dctxt.AddUint8(lines, uint8(dwarf.DW_LNS_negate_stmt))
-                       stmt = newStmt
-                       wrote = true
+               if !pcstmt.Done && pcstmt.NextPC < thispc {
+                       thispc = pcstmt.NextPC
                }
 
-               if line != int64(newLine) || wrote {
-                       pcdelta := (p.Pc - pc) / int64(ctxt.Arch.MinLC)
-                       putpclcdelta(ctxt, dctxt, lines, uint64(pcdelta), int64(newLine)-line)
-                       line, pc = int64(newLine), p.Pc
+               if pcfile.NextPC == thispc {
+                       pcfile.Next()
+               }
+               if !pcstmt.Done && pcstmt.NextPC == thispc {
+                       pcstmt.Next()
+               }
+               if pcline.NextPC == thispc {
+                       pcline.Next()
                }
        }
 
@@ -86,16 +129,16 @@ func (ctxt *Link) generateDebugLinesSymbol(s, lines *LSym) {
        //   file = 1
        //   line = 1
        //   column = 0
-       //   stmt = set in header, we assume true
+       //   is_stmt = set in header, we assume true
        //   basic_block = false
        // Careful readers of the DWARF specification will note that we don't reset
        // the address of the state machine -- but this will happen at the beginning
-       // of the NEXT block of opcodes.
+       // of the NEXT block of opcodes. (See the SetAddress call above.)
        dctxt.AddUint8(lines, dwarf.DW_LNS_set_file)
        dwarf.Uleb128put(dctxt, lines, 1)
        dctxt.AddUint8(lines, dwarf.DW_LNS_advance_line)
        dwarf.Sleb128put(dctxt, lines, int64(1-line))
-       if !stmt {
+       if is_stmt != 1 {
                dctxt.AddUint8(lines, dwarf.DW_LNS_negate_stmt)
        }
        dctxt.AddUint8(lines, dwarf.DW_LNS_copy)
index c47897a263ff8e4b634fb556d7973a8e821062ca..ca1eda8d1ecfbeb5cf6de7e90a396173b3652398 100644 (file)
@@ -5,6 +5,7 @@
 package obj
 
 import (
+       "cmd/internal/src"
        "encoding/binary"
        "log"
 )
@@ -248,6 +249,34 @@ func pctospadj(ctxt *Link, sym *LSym, oldval int32, p *Prog, phase int32, arg in
        return oldval + p.Spadj
 }
 
+// pctostmt returns either,
+// if phase==0, then whether the current instruction is a step-target (Dwarf is_stmt)
+//     bit-or'd with whether the current statement is a prologue end or epilogue begin
+// else (phase == 1), zero.
+//
+func pctostmt(ctxt *Link, sym *LSym, oldval int32, p *Prog, phase int32, arg interface{}) int32 {
+       if phase == 1 {
+               return 0 // Ignored; also different from initial value of -1, if that ever matters.
+       }
+       s := p.Pos.IsStmt()
+       l := p.Pos.Xlogue()
+
+       var is_stmt int32
+
+       // PrologueEnd, at least, is passed to the next instruction
+       switch l {
+       case src.PosPrologueEnd:
+               is_stmt = PrologueEnd
+       case src.PosEpilogueBegin:
+               is_stmt = EpilogueBegin
+       }
+
+       if s != src.PosNotStmt {
+               is_stmt |= 1 // either PosDefaultStmt from asm, or PosIsStmt from go
+       }
+       return is_stmt
+}
+
 // pctopcdata computes the pcdata value in effect at p.
 // A PCDATA instruction sets the value in effect at future
 // non-PCDATA instructions.