dwtest: sync with main Go repo to pull in DWARF5 support func Copy in the latest version of the support file dwtest.go, so as to incorporate a new support function "SubprogLoAndHighPc" that is useful when dealing with DWARF5. Updates golang/go#26379. Change-Id: Icadcab3e33ea40d308fc0068f87c683d2d5eb1bc Reviewed-on: https://go-review.googlesource.com/c/debug/+/640255 Reviewed-by: Dmitri Shuralyov <dmitshur@google.com> LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com> Reviewed-by: Ian Lance Taylor <iant@google.com>
diff --git a/dwtest/dwtest.go b/dwtest/dwtest.go index de9498d..e48ce43 100644 --- a/dwtest/dwtest.go +++ b/dwtest/dwtest.go
@@ -72,8 +72,8 @@ return nil } -func (e *Examiner) DIEs() []*dwarf.Entry { - return e.dies +func (ex *Examiner) DIEs() []*dwarf.Entry { + return ex.dies } func indent(ilevel int) { @@ -93,7 +93,7 @@ fmt.Printf("0x%x: %v\n", idx, entry.Tag) for _, f := range entry.Field { indent(ilevel) - fmt.Printf("at=%v val=0x%x\n", f.Attr, f.Val) + fmt.Printf("at=%v val=%v\n", f.Attr, f.Val) } if dumpKids { ksl := ex.kids[idx] @@ -198,3 +198,60 @@ } return ret } + +// SubprogLoAndHighPc returns the values of the lo_pc and high_pc +// attrs of the DWARF DIE subprogdie. For DWARF versions 2-3, both of +// these attributes had to be of class address; with DWARF 4 the rules +// were changed, allowing compilers to emit a high PC attr of class +// constant, where the high PC could be computed by starting with the +// low PC address and then adding in the high_pc attr offset (doing +// things this way is more compact/efficient: 1 relocation instead of +// 2). This function accepts both styles of specifying a hi/lo pair, +// returning the values or an error if the attributes are malformed in +// some way. +func SubprogLoAndHighPc(subprogdie *dwarf.Entry) (lo uint64, hi uint64, err error) { + // The low_pc attr for a subprogram DIE has to be of class address. + lofield := subprogdie.AttrField(dwarf.AttrLowpc) + if lofield == nil { + err = fmt.Errorf("subprogram DIE has no low_pc attr") + return + } + if lofield.Class != dwarf.ClassAddress { + err = fmt.Errorf("subprogram DIE low_pc attr is not of class address") + return + } + if lopc, ok := lofield.Val.(uint64); ok { + lo = lopc + } else { + err = fmt.Errorf("subprogram DIE low_pc not convertible to uint64") + return + } + + // For the high_pc value, we'll accept either an address or a constant + // offset from lo pc. + hifield := subprogdie.AttrField(dwarf.AttrHighpc) + if hifield == nil { + err = fmt.Errorf("subprogram DIE has no high_pc attr") + return + } + switch hifield.Class { + case dwarf.ClassAddress: + if hipc, ok := hifield.Val.(uint64); ok { + hi = hipc + } else { + err = fmt.Errorf("subprogram DIE high not convertible to uint64") + return + } + case dwarf.ClassConstant: + if hioff, ok := hifield.Val.(int64); ok { + hi = lo + uint64(hioff) + } else { + err = fmt.Errorf("subprogram DIE high_pc not convertible to uint64") + return + } + default: + err = fmt.Errorf("subprogram DIE high_pc unknown value class %s", + hifield.Class) + } + return +}