Projects STRLCPY GoReSym Commits db9fbb33
🤬
  • Allow version override to affect pclntab parsing. Support go1.19 and go1.20

  • Loading...
  • Stephen Eckels committed 2 years ago
    db9fbb33
    1 parent 78e960f3
  • ■ ■ ■ ■ ■
    debug/gosym/pclntab.go
    skipped 14 lines
    15 15   "encoding/binary"
    16 16   "fmt"
    17 17   "sort"
     18 + "strings"
    18 19   "sync"
    19 20  )
    20 21   
    skipped 6 lines
    27 28   ver12
    28 29   ver116
    29 30   ver118
     31 + ver120
    30 32  )
    31 33   
    32 34  func (v version) String() string {
    skipped 8 lines
    41 43   return "1.16"
    42 44   case ver118:
    43 45   return "1.18"
     46 + case ver120:
     47 + return "1.20"
    44 48   default:
    45 49   return fmt.Sprintf("ERROR Unknown ID number %d", int(v))
    46 50   }
    skipped 94 lines
    141 145  //
    142 146  // Deprecated: Use Table's PCToLine method instead.
    143 147  func (t *LineTable) PCToLine(pc uint64) int {
    144  - if t.isGo12() {
     148 + if t.isGo12("") {
    145 149   return t.go12PCToLine(pc)
    146 150   }
    147 151   _, _, line := t.parse(pc, -1)
    skipped 5 lines
    153 157  //
    154 158  // Deprecated: Use Table's LineToPC method instead.
    155 159  func (t *LineTable) LineToPC(line int, maxpc uint64) uint64 {
    156  - if t.isGo12() {
     160 + if t.isGo12("") {
    157 161   return 0
    158 162   }
    159 163   _, pc, line1 := t.parse(maxpc, line)
    skipped 24 lines
    184 188  // are expected to have that recovery logic.
    185 189   
    186 190  // isGo12 reports whether this is a Go 1.2 (or later) symbol table.
    187  -func (t *LineTable) isGo12() bool {
    188  - t.parsePclnTab()
     191 +func (t *LineTable) isGo12(versionOverride string) bool {
     192 + t.parsePclnTab(versionOverride)
    189 193   return t.Version >= ver12
    190 194  }
    191 195   
    skipped 1 lines
    193 197   go12magic = 0xfffffffb
    194 198   go116magic = 0xfffffffa
    195 199   go118magic = 0xfffffff0
     200 + go120magic = 0xfffffff1
    196 201  )
    197 202   
    198 203  // uintptr returns the pointer-sized value encoded at b.
    skipped 6 lines
    205 210  }
    206 211   
    207 212  // parsePclnTab parses the pclntab, setting the version.
    208  -func (t *LineTable) parsePclnTab() {
     213 +func (t *LineTable) parsePclnTab(versionOverride string) {
    209 214   t.mu.Lock()
    210 215   defer t.mu.Unlock()
    211 216   if t.Version != verUnknown {
    skipped 37 lines
    249 254   t.Binary, possibleVersion = binary.LittleEndian, ver118
    250 255   case beMagic == go118magic:
    251 256   t.Binary, possibleVersion = binary.BigEndian, ver118
     257 + case leMagic == go120magic:
     258 + t.Binary, possibleVersion = binary.LittleEndian, ver120
     259 + case beMagic == go120magic:
     260 + t.Binary, possibleVersion = binary.BigEndian, ver120
    252 261   default:
    253 262   return
    254 263   }
    255 264   t.Version = possibleVersion
    256 265   
     266 + if len(versionOverride) > 0 {
     267 + if strings.Contains(versionOverride, "1.20") {
     268 + t.Version = ver120
     269 + } else if strings.Contains(versionOverride, "1.19") {
     270 + t.Version = ver118
     271 + } else if strings.Contains(versionOverride, "1.18") {
     272 + t.Version = ver118
     273 + } else if strings.Contains(versionOverride, "1.17") {
     274 + t.Version = ver116
     275 + } else if strings.Contains(versionOverride, "1.16") {
     276 + t.Version = ver116
     277 + } else if strings.Contains(versionOverride, "1.15") {
     278 + t.Version = ver12
     279 + } else if strings.Contains(versionOverride, "1.14") {
     280 + t.Version = ver12
     281 + } else if strings.Contains(versionOverride, "1.13") {
     282 + t.Version = ver12
     283 + } else if strings.Contains(versionOverride, "1.12") {
     284 + t.Version = ver12
     285 + } else if strings.Contains(versionOverride, "1.11") {
     286 + t.Version = ver11
     287 + } else {
     288 + t.Version = ver11
     289 + }
     290 + }
     291 + 
    257 292   // quantum and ptrSize are the same between 1.2, 1.16, and 1.18
    258 293   t.Quantum = uint32(t.Data[6])
    259 294   t.Ptrsize = uint32(t.Data[7])
    skipped 5 lines
    265 300   return t.Data[offset(word):]
    266 301   }
    267 302   
    268  - switch possibleVersion {
    269  - case ver118:
     303 + switch t.Version {
     304 + case ver118, ver120:
    270 305   t.nfunctab = uint32(offset(0))
    271 306   t.nfiletab = uint32(offset(1))
    272 307   t.textStart = t.PC // use the start PC instead of reading from the table, which may be unrelocated
    skipped 53 lines
    326 361   f.LineTable = t
    327 362   f.FrameSize = int(info.deferreturn())
    328 363   syms[i] = Sym{
    329  - Value: f.Entry,
    330  - Type: 'T',
    331  - Name: t.funcName(info.nameoff()),
    332  - GoType: 0,
    333  - Func: f,
     364 + Value: f.Entry,
     365 + Type: 'T',
     366 + Name: t.funcName(info.nameoff()),
     367 + GoType: 0,
     368 + Func: f,
     369 + GoVersion: t.Version,
    334 370   }
    335 371   f.Sym = &syms[i]
    336 372   }
    skipped 210 lines
    547 583   fileStartPC := filePC
    548 584   for t.step(&fp, &filePC, &fileVal, filePC == entry) {
    549 585   fileIndex := fileVal
    550  - if t.Version == ver116 || t.Version == ver118 {
     586 + if t.Version == ver116 || t.Version == ver118 || t.Version == ver120 {
    551 587   fileIndex = int32(t.Binary.Uint32(cutab[fileVal*4:]))
    552 588   }
    553 589   if fileIndex == filenum && fileStartPC < filePC {
    skipped 92 lines
    646 682   entry := f.entryPC()
    647 683   filetab := f.pcfile()
    648 684   linetab := f.pcln()
    649  - if t.Version == ver116 || t.Version == ver118 {
     685 + if t.Version == ver116 || t.Version == ver118 || t.Version == ver120 {
    650 686   cutab = t.cutab[f.cuOffset()*4:]
    651 687   }
    652 688   pc := t.findFileLine(entry, filetab, linetab, int32(filenum), int32(line), cutab)
    skipped 53 lines
  • ■ ■ ■ ■ ■ ■
    debug/gosym/symtab.go
    skipped 27 lines
    28 28   Name string
    29 29   GoType uint64
    30 30   // If this symbol is a function symbol, the corresponding Func
    31  - Func *Func
     31 + Func *Func
     32 + GoVersion version
    32 33  }
    33 34   
    34 35  // Static reports whether this symbol is static (not visible outside its file).
    skipped 22 lines
    57 58  func (s *Sym) PackageName() string {
    58 59   name := s.nameWithoutInst()
    59 60   
    60  - // A prefix of "type." and "go." is a compiler-generated symbol that doesn't belong to any package.
    61  - // See variable reservedimports in cmd/compile/internal/gc/subr.go
    62  - if strings.HasPrefix(name, "go.") || strings.HasPrefix(name, "type.") {
     61 + // Since go1.20, a prefix of "type:" and "go:" is a compiler-generated symbol,
     62 + // they do not belong to any package.
     63 + //
     64 + // See cmd/compile/internal/base/link.go:ReservedImports variable.
     65 + if s.GoVersion >= ver120 && (strings.HasPrefix(name, "go:") || strings.HasPrefix(name, "type:")) {
     66 + return ""
     67 + }
     68 + 
     69 + // For go1.18 and below, the prefix are "type." and "go." instead.
     70 + if s.GoVersion <= ver118 && (strings.HasPrefix(name, "go.") || strings.HasPrefix(name, "type.")) {
    63 71   return ""
    64 72   }
    65 73   
    skipped 260 lines
    326 334  // NewTable decodes the Go symbol table (the ".gosymtab" section in ELF),
    327 335  // returning an in-memory representation.
    328 336  // Starting with Go 1.3, the Go symbol table no longer includes symbol data.
    329  -func NewTable(symtab []byte, pcln *LineTable) (*Table, error) {
     337 +func NewTable(symtab []byte, pcln *LineTable, versionOverride string) (*Table, error) {
    330 338   var n int
    331 339   err := walksymtab(symtab, func(s sym) error {
    332 340   n++
    skipped 4 lines
    337 345   }
    338 346   
    339 347   var t Table
    340  - if pcln.isGo12() {
     348 + if pcln.isGo12(versionOverride) {
    341 349   t.Go12line = pcln
    342 350   }
    343 351   fname := make(map[uint16]string)
    skipped 8 lines
    352 360   ts.Type = s.typ
    353 361   ts.Value = s.value
    354 362   ts.GoType = s.gotype
     363 + ts.GoVersion = pcln.Version
    355 364   switch s.typ {
    356 365   default:
    357 366   // rewrite name to use . instead of · (c2 b7)
    skipped 410 lines
  • ■ ■ ■ ■ ■ ■
    main.go
    skipped 167 lines
    168 168   }
    169 169   }
    170 170   
     171 + tab, tabva, err := file.PCLineTable(versionOverride)
     172 + if err != nil {
     173 + return ExtractMetadata{}, fmt.Errorf("failed to read pclntab: %w", err)
     174 + }
     175 + 
     176 + if tab.Go12line == nil {
     177 + log.Fatalf("pclntab read, but is nil")
     178 + return ExtractMetadata{}, fmt.Errorf("read pclntab, but parsing failed. The file may not be fully unpacked or corrupted: %w", err)
     179 + }
     180 + 
    171 181   if len(versionOverride) > 0 {
    172 182   extractMetadata.Version = versionOverride
    173 183   }
    skipped 6 lines
    180 190   
    181 191   // go1.18-2d1d548
    182 192   extractMetadata.Version = strings.Split(extractMetadata.Version+"-", "-")[0]
    183  - }
    184  - 
    185  - tab, tabva, err := file.PCLineTable()
    186  - if err != nil {
    187  - return ExtractMetadata{}, fmt.Errorf("failed to read pclntab: %w", err)
    188  - }
    189  - 
    190  - if tab.Go12line == nil {
    191  - log.Fatalf("pclntab read, but is nil")
    192  - return ExtractMetadata{}, fmt.Errorf("read pclntab, but parsing failed. The file may not be fully unpacked or corrupted: %w", err)
    193 193   }
    194 194   
    195 195   extractMetadata.TabMeta.CpuQuantum = tab.Go12line.Quantum
    skipped 202 lines
  • ■ ■ ■ ■
    objfile/disasm.go
    skipped 48 lines
    49 49   return nil, err
    50 50   }
    51 51   
    52  - pcln, _, err := e.PCLineTable()
     52 + pcln, _, err := e.PCLineTable("")
    53 53   if err != nil {
    54 54   return nil, err
    55 55   }
    skipped 358 lines
  • ■ ■ ■ ■ ■ ■
    objfile/objfile.go
    skipped 110 lines
    111 111  }
    112 112   
    113 113  // previously : func (f *File) PCLineTable() (Liner, error) {
    114  -func (f *File) PCLineTable() (*gosym.Table, uint64, error) {
    115  - return f.entries[0].PCLineTable()
     114 +func (f *File) PCLineTable(versionOverride string) (*gosym.Table, uint64, error) {
     115 + return f.entries[0].PCLineTable(versionOverride)
    116 116  }
    117 117   
    118 118  func (f *File) ModuleDataTable(pclntabVA uint64, runtimeVersion string, version string, is64bit bool, littleendian bool) (secStart uint64, moduleData *ModuleData, err error) {
    skipped 69 lines
    188 188  }
    189 189   
    190 190  // previously: func (e *Entry) PCLineTable() (Liner, error)
    191  -func (e *Entry) PCLineTable() (*gosym.Table, uint64, error) {
     191 +func (e *Entry) PCLineTable(versionOverride string) (*gosym.Table, uint64, error) {
    192 192   // If the raw file implements Liner directly, use that.
    193 193   // Currently, only Go intermediate objects and archives (goobj) use this path.
    194 194   
    skipped 31 lines
    226 226   }
    227 227   
    228 228   for _, candidate := range candidates {
    229  - table, err := gosym.NewTable(candidate.symtab, gosym.NewLineTable(candidate.pclntab, textStart))
     229 + table, err := gosym.NewTable(candidate.symtab, gosym.NewLineTable(candidate.pclntab, textStart), versionOverride)
    230 230   if err != nil || table.Go12line == nil {
    231 231   continue
    232 232   }
    skipped 1325 lines
  • ■ ■ ■ ■
    run_test.sh | 100644 /~icons-ver-BEF942F0F42935333EFA072090F4E956.svg#arrow3 100755
    1 1  #!/bin/bash
    2 2  trap "exit" INT
    3 3  sudo rm -rf $(pwd)/test
    4  -versions=("1.17" "1.16" "1.15" "1.14" "1.13" "1.12" "1.11" "1.10" "1.9" "1.8" "1.7" "1.6" "1.5")
     4 +versions=("1.19" "1.18" "1.17" "1.16" "1.15" "1.14" "1.13" "1.12" "1.11" "1.10" "1.9" "1.8" "1.7" "1.6" "1.5")
    5 5  for v in "${versions[@]}"
    6 6  do
    7 7   GO_TAG=$v
    skipped 27 lines
Please wait...
Page is in error, reload to recover