Projects STRLCPY GoReSym Commits 18266f54
🤬
  • ■ ■ ■ ■ ■ ■
    main.go
    skipped 167 lines
    168 168   }
    169 169   }
    170 170   
    171  - tab, tabva, err := file.PCLineTable(versionOverride)
     171 + tabs, err := file.PCLineTable(versionOverride)
    172 172   if err != nil {
    173 173   return ExtractMetadata{}, fmt.Errorf("failed to read pclntab: %w", err)
    174 174   }
    175 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)
     176 + if len(tabs) == 0 {
     177 + return ExtractMetadata{}, fmt.Errorf("No pclntab candidates found")
    179 178   }
    180 179   
    181  - if len(versionOverride) > 0 {
    182  - extractMetadata.Version = versionOverride
    183  - }
     180 + var moduleData *objfile.ModuleData = nil
     181 + var finalTab *objfile.PclntabCandidate = &tabs[0]
     182 + for _, tab := range tabs {
     183 + if len(versionOverride) > 0 {
     184 + extractMetadata.Version = versionOverride
     185 + }
    184 186   
    185  - // numeric only, go1.17 -> 1.17
    186  - goVersionIdx := strings.Index(extractMetadata.Version, "go")
    187  - if goVersionIdx != -1 {
    188  - // "devel go1.18-2d1d548 Tue Dec 21 03:55:43 2021 +0000"
    189  - extractMetadata.Version = strings.Split(extractMetadata.Version[goVersionIdx+2:]+" ", " ")[0]
     187 + // numeric only, go1.17 -> 1.17
     188 + goVersionIdx := strings.Index(extractMetadata.Version, "go")
     189 + if goVersionIdx != -1 {
     190 + // "devel go1.18-2d1d548 Tue Dec 21 03:55:43 2021 +0000"
     191 + extractMetadata.Version = strings.Split(extractMetadata.Version[goVersionIdx+2:]+" ", " ")[0]
    190 192   
    191  - // go1.18-2d1d548
    192  - extractMetadata.Version = strings.Split(extractMetadata.Version+"-", "-")[0]
    193  - }
     193 + // go1.18-2d1d548
     194 + extractMetadata.Version = strings.Split(extractMetadata.Version+"-", "-")[0]
     195 + }
    194 196   
    195  - extractMetadata.TabMeta.CpuQuantum = tab.Go12line.Quantum
     197 + extractMetadata.TabMeta.CpuQuantum = tab.ParsedPclntab.Go12line.Quantum
    196 198   
    197  - // quantum is the minimal unit for a program counter (1 on x86, 4 on most other systems).
    198  - // 386: 1, amd64: 1, arm: 4, arm64: 4, mips: 4, mips/64/64le/64be: 4, ppc64/64le: 4, riscv64: 4, s390x: 2, wasm: 1
    199  - extractMetadata.TabMeta.CpuQuantumStr = "x86/x64/wasm"
    200  - if extractMetadata.TabMeta.CpuQuantum == 2 {
    201  - extractMetadata.TabMeta.CpuQuantumStr = "s390x"
    202  - } else if extractMetadata.TabMeta.CpuQuantum == 4 {
    203  - extractMetadata.TabMeta.CpuQuantumStr = "arm/mips/ppc/riscv"
    204  - }
     199 + // quantum is the minimal unit for a program counter (1 on x86, 4 on most other systems).
     200 + // 386: 1, amd64: 1, arm: 4, arm64: 4, mips: 4, mips/64/64le/64be: 4, ppc64/64le: 4, riscv64: 4, s390x: 2, wasm: 1
     201 + extractMetadata.TabMeta.CpuQuantumStr = "x86/x64/wasm"
     202 + if extractMetadata.TabMeta.CpuQuantum == 2 {
     203 + extractMetadata.TabMeta.CpuQuantumStr = "s390x"
     204 + } else if extractMetadata.TabMeta.CpuQuantum == 4 {
     205 + extractMetadata.TabMeta.CpuQuantumStr = "arm/mips/ppc/riscv"
     206 + }
    205 207   
    206  - extractMetadata.TabMeta.VA = tabva
    207  - extractMetadata.TabMeta.Version = tab.Go12line.Version.String()
    208  - extractMetadata.TabMeta.Endianess = tab.Go12line.Binary.String()
    209  - extractMetadata.TabMeta.PointerSize = tab.Go12line.Ptrsize
     208 + extractMetadata.TabMeta.VA = tab.PclntabVA
     209 + extractMetadata.TabMeta.Version = tab.ParsedPclntab.Go12line.Version.String()
     210 + extractMetadata.TabMeta.Endianess = tab.ParsedPclntab.Go12line.Binary.String()
     211 + extractMetadata.TabMeta.PointerSize = tab.ParsedPclntab.Go12line.Ptrsize
    210 212   
    211  - // this can be a little tricky to locate and parse properly across all go versions
    212  - _, moduleData, err := file.ModuleDataTable(tabva, extractMetadata.Version, extractMetadata.TabMeta.Version, extractMetadata.TabMeta.PointerSize == 8, extractMetadata.TabMeta.Endianess == "LittleEndian")
    213  - if err == nil {
     213 + // this can be a little tricky to locate and parse properly across all go versions
     214 + // since moduledata holds a pointer to the pclntab, we can (hopefully) find the right candidate by using it to find the moduledata.
     215 + // if that location works, then we must have given it the correct pclntab VA. At least in theory...
     216 + _, tmpModData, err := file.ModuleDataTable(tab.PclntabVA, extractMetadata.Version, extractMetadata.TabMeta.Version, extractMetadata.TabMeta.PointerSize == 8, extractMetadata.TabMeta.Endianess == "LittleEndian")
     217 + if err == nil && tmpModData != nil {
     218 + finalTab = &tab
     219 + moduleData = tmpModData
     220 + }
     221 + }
     222 + 
     223 + if moduleData != nil {
    214 224   extractMetadata.ModuleMeta = *moduleData
    215 225   if printTypes && manualTypeAddress == 0 {
    216 226   types, err := file.ParseTypeLinks(extractMetadata.Version, moduleData, extractMetadata.TabMeta.PointerSize == 8, extractMetadata.TabMeta.Endianess == "LittleEndian")
    skipped 14 lines
    231 241   }
    232 242   
    233 243   if printFilePaths {
    234  - for k := range tab.Files {
     244 + for k := range finalTab.ParsedPclntab.Files {
    235 245   extractMetadata.Files = append(extractMetadata.Files, k)
    236 246   }
    237 247   }
    238 248   
    239  - for _, elem := range tab.Funcs {
     249 + for _, elem := range finalTab.ParsedPclntab.Funcs {
    240 250   if isStdPackage(elem.PackageName()) {
    241 251   if printStdPkgs {
    242 252   extractMetadata.StdFunctions = append(extractMetadata.StdFunctions, FuncMetadata{
    skipped 155 lines
  • ■ ■ ■ ■ ■ ■
    objfile/disasm.go
    skipped 48 lines
    49 49   return nil, err
    50 50   }
    51 51   
    52  - pcln, _, err := e.PCLineTable("")
     52 + pclns, err := e.PCLineTable("")
    53 53   if err != nil {
    54 54   return nil, err
    55 55   }
    skipped 23 lines
    79 79   syms = keep
    80 80   d := &Disasm{
    81 81   syms: syms,
    82  - pcln: pcln,
     82 + pcln: pclns[0].ParsedPclntab,
    83 83   text: textBytes,
    84 84   textStart: textStart,
    85 85   textEnd: textStart + uint64(len(textBytes)),
    skipped 328 lines
  • ■ ■ ■ ■ ■ ■
    objfile/elf.go
    skipped 115 lines
    116 116   pclntab = data[pclntab_idx:]
    117 117   
    118 118   var candidate PclntabCandidate
    119  - candidate.pclntab = pclntab
    120  - candidate.pclntabVA = uint64(sec.Addr) + uint64(pclntab_idx)
     119 + candidate.Pclntab = pclntab
     120 + 
     121 + candidate.SecStart = uint64(sec.Addr)
     122 + candidate.PclntabVA = candidate.SecStart + uint64(pclntab_idx)
    121 123   
    122 124   candidates = append(candidates, candidate)
    123 125   // we must scan all signature for all sections. DO NOT BREAK
    skipped 4 lines
    128 130   pclntab_idx := bytes.Index(data, pclntab)
    129 131   if pclntab_idx != -1 && pclntab_idx < int(sec.Size) {
    130 132   var candidate PclntabCandidate
    131  - candidate.pclntab = pclntab
    132  - candidate.pclntabVA = uint64(sec.Addr) + uint64(pclntab_idx)
     133 + candidate.Pclntab = pclntab
     134 + candidate.SecStart = uint64(sec.Addr)
     135 + candidate.PclntabVA = candidate.SecStart + uint64(pclntab_idx)
    133 136   
    134 137   candidates = append(candidates, candidate)
    135 138   break ExitScan
    skipped 18 lines
    154 157   
    155 158   if err == nil {
    156 159   for _, c := range candidates {
    157  - c.symtab = symtab
     160 + c.Symtab = symtab
    158 161   }
    159 162   }
    160 163   
    skipped 155 lines
  • ■ ■ ■ ■ ■ ■
    objfile/macho.go
    skipped 133 lines
    134 134   pclntab = data[pclntab_idx:]
    135 135   
    136 136   var candidate PclntabCandidate
    137  - candidate.pclntab = pclntab
    138  - candidate.pclntabVA = uint64(sec.Addr) + uint64(pclntab_idx)
     137 + candidate.Pclntab = pclntab
     138 + 
     139 + candidate.SecStart = uint64(sec.Addr)
     140 + candidate.PclntabVA = candidate.SecStart + uint64(pclntab_idx)
    139 141   
    140 142   candidates = append(candidates, candidate)
    141 143   // we must scan all signature for all sections. DO NOT BREAK
    skipped 4 lines
    146 148   pclntab_idx := bytes.Index(data, pclntab)
    147 149   if pclntab_idx != -1 {
    148 150   var candidate PclntabCandidate
    149  - candidate.pclntab = pclntab
    150  - candidate.pclntabVA = uint64(sec.Addr) + uint64(pclntab_idx)
     151 + candidate.Pclntab = pclntab
     152 + 
     153 + candidate.SecStart = uint64(sec.Addr)
     154 + candidate.PclntabVA = candidate.SecStart + uint64(pclntab_idx)
    151 155   
    152 156   candidates = append(candidates, candidate)
    153 157   
    skipped 19 lines
    173 177   
    174 178   if err == nil {
    175 179   for _, c := range candidates {
    176  - c.symtab = symtab
     180 + c.Symtab = symtab
    177 181   }
    178 182   }
    179 183   
    skipped 136 lines
  • ■ ■ ■ ■ ■ ■
    objfile/objfile.go
    skipped 22 lines
    23 23  )
    24 24   
    25 25  type PclntabCandidate struct {
    26  - pclntabVA uint64
    27  - pclntab []byte
    28  - symtab []byte // optional
     26 + SecStart uint64
     27 + PclntabVA uint64
     28 + Pclntab []byte
     29 + Symtab []byte // optional
     30 + ParsedPclntab *gosym.Table
    29 31  }
    30 32   
    31 33  type rawFile interface {
    skipped 79 lines
    111 113  }
    112 114   
    113 115  // previously : func (f *File) PCLineTable() (Liner, error) {
    114  -func (f *File) PCLineTable(versionOverride string) (*gosym.Table, uint64, error) {
     116 +func (f *File) PCLineTable(versionOverride string) ([]PclntabCandidate, error) {
    115 117   return f.entries[0].PCLineTable(versionOverride)
    116 118  }
    117 119   
    skipped 70 lines
    188 190  }
    189 191   
    190 192  // previously: func (e *Entry) PCLineTable() (Liner, error)
    191  -func (e *Entry) PCLineTable(versionOverride string) (*gosym.Table, uint64, error) {
     193 +func (e *Entry) PCLineTable(versionOverride string) ([]PclntabCandidate, error) {
    192 194   // If the raw file implements Liner directly, use that.
    193 195   // Currently, only Go intermediate objects and archives (goobj) use this path.
    194 196   
    195  - // PATCH: DISABLED, We want to gopclntab table 95% of the time
     197 + // FEYE PATCH: DISABLED, We want to gopclntab table 95% of the time
    196 198   // if pcln, ok := e.raw.(Liner); ok {
    197 199   // return pcln, nil
    198 200   // }
    skipped 3 lines
    202 204   // https://github.com/golang/go/issues/42954
    203 205   candidates, err := e.raw.pcln()
    204 206   if err != nil {
    205  - return nil, 0, err
     207 + return nil, err
    206 208   }
    207 209   
    208  - // try to resolve via symbol
    209  - textStart := uint64(0)
    210  - syms, err := e.raw.symbols()
    211  - if err == nil {
    212  - for _, s := range syms {
    213  - if s.Name == "runtime.text" {
    214  - textStart = s.Addr
    215  - break
    216  - }
     210 + var finalCandidates []PclntabCandidate
     211 + var atLeastOneGood bool = false
     212 + for _, candidate := range candidates {
     213 + parsedTable, err := gosym.NewTable(candidate.Symtab, gosym.NewLineTable(candidate.Pclntab, candidate.SecStart), versionOverride)
     214 + if err != nil || parsedTable.Go12line == nil {
     215 + continue
    217 216   }
    218  - }
    219 217   
    220  - // that may have failed, use section base directly
    221  - if textStart == 0 {
    222  - secBase, _, err := e.Text()
    223  - if err == nil {
    224  - textStart = secBase
    225  - }
     218 + // the first good one happens to be correct more often than the last
     219 + candidate.ParsedPclntab = parsedTable
     220 + finalCandidates = append(finalCandidates, candidate)
     221 + atLeastOneGood = true
    226 222   }
    227 223   
    228  - for _, candidate := range candidates {
    229  - table, err := gosym.NewTable(candidate.symtab, gosym.NewLineTable(candidate.pclntab, textStart), versionOverride)
    230  - if err != nil || table.Go12line == nil {
    231  - continue
    232  - }
    233  - 
    234  - return table, candidate.pclntabVA, nil
     224 + if atLeastOneGood {
     225 + return finalCandidates, nil
    235 226   }
    236 227   
    237  - return nil, 0, fmt.Errorf("failed to locate pclntab")
     228 + return finalCandidates, fmt.Errorf("failed to locate pclntab")
    238 229  }
    239 230   
    240 231  func (e *Entry) ModuleDataTable(pclntabVA uint64, runtimeVersion string, version string, is64bit bool, littleendian bool) (secStart uint64, moduleData *ModuleData, err error) {
    skipped 1317 lines
  • ■ ■ ■ ■ ■ ■
    objfile/pe.go
    skipped 164 lines
    165 165   []byte("\xFF\xFF\xFF\xFB\x00\x00"), []byte("\xFF\xFF\xFF\xFA\x00\x00"), []byte("\xFF\xFF\xFF\xF0\x00\x00")}
    166 166   matches := findAllOccurrences(data, pclntab_sigs)
    167 167   for _, pclntab_idx := range matches {
    168  - if pclntab_idx != -1 && pclntab_idx < int(sec.Size) {
     168 + if pclntab_idx != -1 {
    169 169   pclntab = data[pclntab_idx:]
    170 170   
    171 171   var candidate PclntabCandidate
    172  - candidate.pclntab = pclntab
    173  - candidate.pclntabVA = imageBase + uint64(sec.VirtualAddress) + uint64(pclntab_idx)
     172 + candidate.Pclntab = pclntab
     173 + 
     174 + candidate.SecStart = imageBase + uint64(sec.VirtualAddress)
     175 + candidate.PclntabVA = candidate.SecStart + uint64(pclntab_idx)
    174 176   
    175 177   candidates = append(candidates, candidate)
    176 178   // we must scan all signature for all sections. DO NOT BREAK
    skipped 2 lines
    179 181   } else {
    180 182   // 3) if we found it earlier, figure out which section base to return (might be wrong for packed things)
    181 183   pclntab_idx := bytes.Index(data, pclntab)
    182  - if pclntab_idx != -1 && pclntab_idx < int(sec.Size) {
     184 + if pclntab_idx != -1 {
    183 185   var candidate PclntabCandidate
    184  - candidate.pclntab = pclntab
    185  - candidate.pclntabVA = imageBase + uint64(sec.VirtualAddress) + uint64(pclntab_idx)
     186 + candidate.Pclntab = pclntab
     187 + 
     188 + candidate.SecStart = imageBase + uint64(sec.VirtualAddress)
     189 + candidate.PclntabVA = candidate.SecStart + uint64(pclntab_idx)
    186 190   
    187 191   candidates = append(candidates, candidate)
    188 192   break ExitScan
    skipped 18 lines
    207 211   
    208 212   if err == nil {
    209 213   for _, c := range candidates {
    210  - c.symtab = symtab
     214 + c.Symtab = symtab
    211 215   }
    212 216   }
    213 217   
    skipped 201 lines
Please wait...
Page is in error, reload to recover