mirror of
https://github.com/golang/go
synced 2024-11-23 10:20:03 -07:00
Revert "cmd/compile: walk the progs to generate debug_lines"
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>
This commit is contained in:
parent
c33d45a898
commit
5fe3b49a05
@ -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
|
||||
line := 1
|
||||
file := 1
|
||||
|
||||
// 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)
|
||||
// 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
|
||||
}
|
||||
if prologue && !wrotePrologue {
|
||||
dctxt.AddUint8(lines, uint8(dwarf.DW_LNS_set_prologue_end))
|
||||
wrotePrologue = true
|
||||
wrote = true
|
||||
}
|
||||
if stmt != newStmt {
|
||||
dctxt.AddUint8(lines, uint8(dwarf.DW_LNS_negate_stmt))
|
||||
stmt = newStmt
|
||||
wrote = true
|
||||
dwarf.Uleb128put(dctxt, lines, fileNums[pcfile.Value])
|
||||
file = int(pcfile.Value)
|
||||
}
|
||||
|
||||
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
|
||||
// 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))
|
||||
}
|
||||
}
|
||||
|
||||
// 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 !pcstmt.Done && pcstmt.NextPC < thispc {
|
||||
thispc = pcstmt.NextPC
|
||||
}
|
||||
|
||||
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)
|
||||
|
@ -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.
|
||||
|
Loading…
Reference in New Issue
Block a user