symtab.go 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764
  1. // Copyright 2009 The Go Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style
  3. // license that can be found in the LICENSE file.
  4. // Package gosym implements access to the Go symbol
  5. // and line number tables embedded in Go binaries generated
  6. // by the gc compilers.
  7. package gosym
  8. import (
  9. "bytes"
  10. "encoding/binary"
  11. "fmt"
  12. "strconv"
  13. "strings"
  14. )
  15. /*
  16. * Symbols
  17. */
  18. // A Sym represents a single symbol table entry.
  19. type Sym struct {
  20. Value uint64
  21. Type byte
  22. Name string
  23. GoType uint64
  24. // If this symbol is a function symbol, the corresponding Func
  25. Func *Func
  26. }
  27. // Static reports whether this symbol is static (not visible outside its file).
  28. func (s *Sym) Static() bool { return s.Type >= 'a' }
  29. // nameWithoutInst returns s.Name if s.Name has no brackets (does not reference an
  30. // instantiated type, function, or method). If s.Name contains brackets, then it
  31. // returns s.Name with all the contents between (and including) the outermost left
  32. // and right bracket removed. This is useful to ignore any extra slashes or dots
  33. // inside the brackets from the string searches below, where needed.
  34. func (s *Sym) nameWithoutInst() string {
  35. start := strings.Index(s.Name, "[")
  36. if start < 0 {
  37. return s.Name
  38. }
  39. end := strings.LastIndex(s.Name, "]")
  40. if end < 0 {
  41. // Malformed name, should contain closing bracket too.
  42. return s.Name
  43. }
  44. return s.Name[0:start] + s.Name[end+1:]
  45. }
  46. // PackageName returns the package part of the symbol name,
  47. // or the empty string if there is none.
  48. func (s *Sym) PackageName() string {
  49. name := s.nameWithoutInst()
  50. // A prefix of "type." and "go." is a compiler-generated symbol that doesn't belong to any package.
  51. // See variable reservedimports in cmd/compile/internal/gc/subr.go
  52. if strings.HasPrefix(name, "go.") || strings.HasPrefix(name, "type.") {
  53. return ""
  54. }
  55. pathend := strings.LastIndex(name, "/")
  56. if pathend < 0 {
  57. pathend = 0
  58. }
  59. if i := strings.Index(name[pathend:], "."); i != -1 {
  60. return name[:pathend+i]
  61. }
  62. return ""
  63. }
  64. // ReceiverName returns the receiver type name of this symbol,
  65. // or the empty string if there is none. A receiver name is only detected in
  66. // the case that s.Name is fully-specified with a package name.
  67. func (s *Sym) ReceiverName() string {
  68. name := s.nameWithoutInst()
  69. // If we find a slash in name, it should precede any bracketed expression
  70. // that was removed, so pathend will apply correctly to name and s.Name.
  71. pathend := strings.LastIndex(name, "/")
  72. if pathend < 0 {
  73. pathend = 0
  74. }
  75. // Find the first dot after pathend (or from the beginning, if there was
  76. // no slash in name).
  77. l := strings.Index(name[pathend:], ".")
  78. // Find the last dot after pathend (or the beginnng).
  79. r := strings.LastIndex(name[pathend:], ".")
  80. if l == -1 || r == -1 || l == r {
  81. // There is no receiver if we didn't find two distinct dots after pathend.
  82. return ""
  83. }
  84. // Given there is a trailing '.' that is in name, find it now in s.Name.
  85. // pathend+l should apply to s.Name, because it should be the dot in the
  86. // package name.
  87. r = strings.LastIndex(s.Name[pathend:], ".")
  88. return s.Name[pathend+l+1 : pathend+r]
  89. }
  90. // BaseName returns the symbol name without the package or receiver name.
  91. func (s *Sym) BaseName() string {
  92. name := s.nameWithoutInst()
  93. if i := strings.LastIndex(name, "."); i != -1 {
  94. if s.Name != name {
  95. brack := strings.Index(s.Name, "[")
  96. if i > brack {
  97. // BaseName is a method name after the brackets, so
  98. // recalculate for s.Name. Otherwise, i applies
  99. // correctly to s.Name, since it is before the
  100. // brackets.
  101. i = strings.LastIndex(s.Name, ".")
  102. }
  103. }
  104. return s.Name[i+1:]
  105. }
  106. return s.Name
  107. }
  108. // A Func collects information about a single function.
  109. type Func struct {
  110. Entry uint64
  111. *Sym
  112. End uint64
  113. Params []*Sym // nil for Go 1.3 and later binaries
  114. Locals []*Sym // nil for Go 1.3 and later binaries
  115. FrameSize int
  116. LineTable *LineTable
  117. Obj *Obj
  118. }
  119. // An Obj represents a collection of functions in a symbol table.
  120. //
  121. // The exact method of division of a binary into separate Objs is an internal detail
  122. // of the symbol table format.
  123. //
  124. // In early versions of Go each source file became a different Obj.
  125. //
  126. // In Go 1 and Go 1.1, each package produced one Obj for all Go sources
  127. // and one Obj per C source file.
  128. //
  129. // In Go 1.2, there is a single Obj for the entire program.
  130. type Obj struct {
  131. // Funcs is a list of functions in the Obj.
  132. Funcs []Func
  133. // In Go 1.1 and earlier, Paths is a list of symbols corresponding
  134. // to the source file names that produced the Obj.
  135. // In Go 1.2, Paths is nil.
  136. // Use the keys of Table.Files to obtain a list of source files.
  137. Paths []Sym // meta
  138. }
  139. /*
  140. * Symbol tables
  141. */
  142. // Table represents a Go symbol table. It stores all of the
  143. // symbols decoded from the program and provides methods to translate
  144. // between symbols, names, and addresses.
  145. type Table struct {
  146. Syms []Sym // nil for Go 1.3 and later binaries
  147. Funcs []Func
  148. Files map[string]*Obj // for Go 1.2 and later all files map to one Obj
  149. Objs []Obj // for Go 1.2 and later only one Obj in slice
  150. go12line *LineTable // Go 1.2 line number table
  151. }
  152. type sym struct {
  153. value uint64
  154. gotype uint64
  155. typ byte
  156. name []byte
  157. }
  158. var (
  159. littleEndianSymtab = []byte{0xFD, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00}
  160. bigEndianSymtab = []byte{0xFF, 0xFF, 0xFF, 0xFD, 0x00, 0x00, 0x00}
  161. oldLittleEndianSymtab = []byte{0xFE, 0xFF, 0xFF, 0xFF, 0x00, 0x00}
  162. )
  163. func walksymtab(data []byte, fn func(sym) error) error {
  164. if len(data) == 0 { // missing symtab is okay
  165. return nil
  166. }
  167. var order binary.ByteOrder = binary.BigEndian
  168. newTable := false
  169. switch {
  170. case bytes.HasPrefix(data, oldLittleEndianSymtab):
  171. // Same as Go 1.0, but little endian.
  172. // Format was used during interim development between Go 1.0 and Go 1.1.
  173. // Should not be widespread, but easy to support.
  174. data = data[6:]
  175. order = binary.LittleEndian
  176. case bytes.HasPrefix(data, bigEndianSymtab):
  177. newTable = true
  178. case bytes.HasPrefix(data, littleEndianSymtab):
  179. newTable = true
  180. order = binary.LittleEndian
  181. }
  182. var ptrsz int
  183. if newTable {
  184. if len(data) < 8 {
  185. return &DecodingError{len(data), "unexpected EOF", nil}
  186. }
  187. ptrsz = int(data[7])
  188. if ptrsz != 4 && ptrsz != 8 {
  189. return &DecodingError{7, "invalid pointer size", ptrsz}
  190. }
  191. data = data[8:]
  192. }
  193. var s sym
  194. p := data
  195. for len(p) >= 4 {
  196. var typ byte
  197. if newTable {
  198. // Symbol type, value, Go type.
  199. typ = p[0] & 0x3F
  200. wideValue := p[0]&0x40 != 0
  201. goType := p[0]&0x80 != 0
  202. if typ < 26 {
  203. typ += 'A'
  204. } else {
  205. typ += 'a' - 26
  206. }
  207. s.typ = typ
  208. p = p[1:]
  209. if wideValue {
  210. if len(p) < ptrsz {
  211. return &DecodingError{len(data), "unexpected EOF", nil}
  212. }
  213. // fixed-width value
  214. if ptrsz == 8 {
  215. s.value = order.Uint64(p[0:8])
  216. p = p[8:]
  217. } else {
  218. s.value = uint64(order.Uint32(p[0:4]))
  219. p = p[4:]
  220. }
  221. } else {
  222. // varint value
  223. s.value = 0
  224. shift := uint(0)
  225. for len(p) > 0 && p[0]&0x80 != 0 {
  226. s.value |= uint64(p[0]&0x7F) << shift
  227. shift += 7
  228. p = p[1:]
  229. }
  230. if len(p) == 0 {
  231. return &DecodingError{len(data), "unexpected EOF", nil}
  232. }
  233. s.value |= uint64(p[0]) << shift
  234. p = p[1:]
  235. }
  236. if goType {
  237. if len(p) < ptrsz {
  238. return &DecodingError{len(data), "unexpected EOF", nil}
  239. }
  240. // fixed-width go type
  241. if ptrsz == 8 {
  242. s.gotype = order.Uint64(p[0:8])
  243. p = p[8:]
  244. } else {
  245. s.gotype = uint64(order.Uint32(p[0:4]))
  246. p = p[4:]
  247. }
  248. }
  249. } else {
  250. // Value, symbol type.
  251. s.value = uint64(order.Uint32(p[0:4]))
  252. if len(p) < 5 {
  253. return &DecodingError{len(data), "unexpected EOF", nil}
  254. }
  255. typ = p[4]
  256. if typ&0x80 == 0 {
  257. return &DecodingError{len(data) - len(p) + 4, "bad symbol type", typ}
  258. }
  259. typ &^= 0x80
  260. s.typ = typ
  261. p = p[5:]
  262. }
  263. // Name.
  264. var i int
  265. var nnul int
  266. for i = 0; i < len(p); i++ {
  267. if p[i] == 0 {
  268. nnul = 1
  269. break
  270. }
  271. }
  272. switch typ {
  273. case 'z', 'Z':
  274. p = p[i+nnul:]
  275. for i = 0; i+2 <= len(p); i += 2 {
  276. if p[i] == 0 && p[i+1] == 0 {
  277. nnul = 2
  278. break
  279. }
  280. }
  281. }
  282. if len(p) < i+nnul {
  283. return &DecodingError{len(data), "unexpected EOF", nil}
  284. }
  285. s.name = p[0:i]
  286. i += nnul
  287. p = p[i:]
  288. if !newTable {
  289. if len(p) < 4 {
  290. return &DecodingError{len(data), "unexpected EOF", nil}
  291. }
  292. // Go type.
  293. s.gotype = uint64(order.Uint32(p[:4]))
  294. p = p[4:]
  295. }
  296. fn(s)
  297. }
  298. return nil
  299. }
  300. // NewTable decodes the Go symbol table (the ".gosymtab" section in ELF),
  301. // returning an in-memory representation.
  302. // Starting with Go 1.3, the Go symbol table no longer includes symbol data.
  303. func NewTable(symtab []byte, pcln *LineTable) (*Table, error) {
  304. var n int
  305. err := walksymtab(symtab, func(s sym) error {
  306. n++
  307. return nil
  308. })
  309. if err != nil {
  310. return nil, err
  311. }
  312. var t Table
  313. if pcln.isGo12() {
  314. t.go12line = pcln
  315. }
  316. fname := make(map[uint16]string)
  317. t.Syms = make([]Sym, 0, n)
  318. nf := 0
  319. nz := 0
  320. lasttyp := uint8(0)
  321. err = walksymtab(symtab, func(s sym) error {
  322. n := len(t.Syms)
  323. t.Syms = t.Syms[0 : n+1]
  324. ts := &t.Syms[n]
  325. ts.Type = s.typ
  326. ts.Value = s.value
  327. ts.GoType = s.gotype
  328. switch s.typ {
  329. default:
  330. // rewrite name to use . instead of · (c2 b7)
  331. w := 0
  332. b := s.name
  333. for i := 0; i < len(b); i++ {
  334. if b[i] == 0xc2 && i+1 < len(b) && b[i+1] == 0xb7 {
  335. i++
  336. b[i] = '.'
  337. }
  338. b[w] = b[i]
  339. w++
  340. }
  341. ts.Name = string(s.name[0:w])
  342. case 'z', 'Z':
  343. if lasttyp != 'z' && lasttyp != 'Z' {
  344. nz++
  345. }
  346. for i := 0; i < len(s.name); i += 2 {
  347. eltIdx := binary.BigEndian.Uint16(s.name[i : i+2])
  348. elt, ok := fname[eltIdx]
  349. if !ok {
  350. return &DecodingError{-1, "bad filename code", eltIdx}
  351. }
  352. if n := len(ts.Name); n > 0 && ts.Name[n-1] != '/' {
  353. ts.Name += "/"
  354. }
  355. ts.Name += elt
  356. }
  357. }
  358. switch s.typ {
  359. case 'T', 't', 'L', 'l':
  360. nf++
  361. case 'f':
  362. fname[uint16(s.value)] = ts.Name
  363. }
  364. lasttyp = s.typ
  365. return nil
  366. })
  367. if err != nil {
  368. return nil, err
  369. }
  370. t.Funcs = make([]Func, 0, nf)
  371. t.Files = make(map[string]*Obj)
  372. var obj *Obj
  373. if t.go12line != nil {
  374. // Put all functions into one Obj.
  375. t.Objs = make([]Obj, 1)
  376. obj = &t.Objs[0]
  377. t.go12line.go12MapFiles(t.Files, obj)
  378. } else {
  379. t.Objs = make([]Obj, 0, nz)
  380. }
  381. // Count text symbols and attach frame sizes, parameters, and
  382. // locals to them. Also, find object file boundaries.
  383. lastf := 0
  384. for i := 0; i < len(t.Syms); i++ {
  385. sym := &t.Syms[i]
  386. switch sym.Type {
  387. case 'Z', 'z': // path symbol
  388. if t.go12line != nil {
  389. // Go 1.2 binaries have the file information elsewhere. Ignore.
  390. break
  391. }
  392. // Finish the current object
  393. if obj != nil {
  394. obj.Funcs = t.Funcs[lastf:]
  395. }
  396. lastf = len(t.Funcs)
  397. // Start new object
  398. n := len(t.Objs)
  399. t.Objs = t.Objs[0 : n+1]
  400. obj = &t.Objs[n]
  401. // Count & copy path symbols
  402. var end int
  403. for end = i + 1; end < len(t.Syms); end++ {
  404. if c := t.Syms[end].Type; c != 'Z' && c != 'z' {
  405. break
  406. }
  407. }
  408. obj.Paths = t.Syms[i:end]
  409. i = end - 1 // loop will i++
  410. // Record file names
  411. depth := 0
  412. for j := range obj.Paths {
  413. s := &obj.Paths[j]
  414. if s.Name == "" {
  415. depth--
  416. } else {
  417. if depth == 0 {
  418. t.Files[s.Name] = obj
  419. }
  420. depth++
  421. }
  422. }
  423. case 'T', 't', 'L', 'l': // text symbol
  424. if n := len(t.Funcs); n > 0 {
  425. t.Funcs[n-1].End = sym.Value
  426. }
  427. if sym.Name == "runtime.etext" || sym.Name == "etext" {
  428. continue
  429. }
  430. // Count parameter and local (auto) syms
  431. var np, na int
  432. var end int
  433. countloop:
  434. for end = i + 1; end < len(t.Syms); end++ {
  435. switch t.Syms[end].Type {
  436. case 'T', 't', 'L', 'l', 'Z', 'z':
  437. break countloop
  438. case 'p':
  439. np++
  440. case 'a':
  441. na++
  442. }
  443. }
  444. // Fill in the function symbol
  445. n := len(t.Funcs)
  446. t.Funcs = t.Funcs[0 : n+1]
  447. fn := &t.Funcs[n]
  448. sym.Func = fn
  449. fn.Params = make([]*Sym, 0, np)
  450. fn.Locals = make([]*Sym, 0, na)
  451. fn.Sym = sym
  452. fn.Entry = sym.Value
  453. fn.Obj = obj
  454. if t.go12line != nil {
  455. // All functions share the same line table.
  456. // It knows how to narrow down to a specific
  457. // function quickly.
  458. fn.LineTable = t.go12line
  459. } else if pcln != nil {
  460. fn.LineTable = pcln.slice(fn.Entry)
  461. pcln = fn.LineTable
  462. }
  463. for j := i; j < end; j++ {
  464. s := &t.Syms[j]
  465. switch s.Type {
  466. case 'm':
  467. fn.FrameSize = int(s.Value)
  468. case 'p':
  469. n := len(fn.Params)
  470. fn.Params = fn.Params[0 : n+1]
  471. fn.Params[n] = s
  472. case 'a':
  473. n := len(fn.Locals)
  474. fn.Locals = fn.Locals[0 : n+1]
  475. fn.Locals[n] = s
  476. }
  477. }
  478. i = end - 1 // loop will i++
  479. }
  480. }
  481. if t.go12line != nil && nf == 0 {
  482. t.Funcs = t.go12line.go12Funcs()
  483. }
  484. if obj != nil {
  485. obj.Funcs = t.Funcs[lastf:]
  486. }
  487. return &t, nil
  488. }
  489. // PCToFunc returns the function containing the program counter pc,
  490. // or nil if there is no such function.
  491. func (t *Table) PCToFunc(pc uint64) *Func {
  492. funcs := t.Funcs
  493. for len(funcs) > 0 {
  494. m := len(funcs) / 2
  495. fn := &funcs[m]
  496. switch {
  497. case pc < fn.Entry:
  498. funcs = funcs[0:m]
  499. case fn.Entry <= pc && pc < fn.End:
  500. return fn
  501. default:
  502. funcs = funcs[m+1:]
  503. }
  504. }
  505. return nil
  506. }
  507. // PCToLine looks up line number information for a program counter.
  508. // If there is no information, it returns fn == nil.
  509. func (t *Table) PCToLine(pc uint64) (file string, line int, fn *Func) {
  510. if fn = t.PCToFunc(pc); fn == nil {
  511. return
  512. }
  513. if t.go12line != nil {
  514. file = t.go12line.go12PCToFile(pc)
  515. line = t.go12line.go12PCToLine(pc)
  516. } else {
  517. file, line = fn.Obj.lineFromAline(fn.LineTable.PCToLine(pc))
  518. }
  519. return
  520. }
  521. // LineToPC looks up the first program counter on the given line in
  522. // the named file. It returns UnknownPathError or UnknownLineError if
  523. // there is an error looking up this line.
  524. func (t *Table) LineToPC(file string, line int) (pc uint64, fn *Func, err error) {
  525. obj, ok := t.Files[file]
  526. if !ok {
  527. return 0, nil, UnknownFileError(file)
  528. }
  529. if t.go12line != nil {
  530. pc := t.go12line.go12LineToPC(file, line)
  531. if pc == 0 {
  532. return 0, nil, &UnknownLineError{file, line}
  533. }
  534. return pc, t.PCToFunc(pc), nil
  535. }
  536. abs, err := obj.alineFromLine(file, line)
  537. if err != nil {
  538. return
  539. }
  540. for i := range obj.Funcs {
  541. f := &obj.Funcs[i]
  542. pc := f.LineTable.LineToPC(abs, f.End)
  543. if pc != 0 {
  544. return pc, f, nil
  545. }
  546. }
  547. return 0, nil, &UnknownLineError{file, line}
  548. }
  549. // LookupSym returns the text, data, or bss symbol with the given name,
  550. // or nil if no such symbol is found.
  551. func (t *Table) LookupSym(name string) *Sym {
  552. // TODO(austin) Maybe make a map
  553. for i := range t.Syms {
  554. s := &t.Syms[i]
  555. switch s.Type {
  556. case 'T', 't', 'L', 'l', 'D', 'd', 'B', 'b':
  557. if s.Name == name {
  558. return s
  559. }
  560. }
  561. }
  562. return nil
  563. }
  564. // LookupFunc returns the text, data, or bss symbol with the given name,
  565. // or nil if no such symbol is found.
  566. func (t *Table) LookupFunc(name string) *Func {
  567. for i := range t.Funcs {
  568. f := &t.Funcs[i]
  569. if f.Sym.Name == name {
  570. return f
  571. }
  572. }
  573. return nil
  574. }
  575. // SymByAddr returns the text, data, or bss symbol starting at the given address.
  576. func (t *Table) SymByAddr(addr uint64) *Sym {
  577. for i := range t.Syms {
  578. s := &t.Syms[i]
  579. switch s.Type {
  580. case 'T', 't', 'L', 'l', 'D', 'd', 'B', 'b':
  581. if s.Value == addr {
  582. return s
  583. }
  584. }
  585. }
  586. return nil
  587. }
  588. /*
  589. * Object files
  590. */
  591. // This is legacy code for Go 1.1 and earlier, which used the
  592. // Plan 9 format for pc-line tables. This code was never quite
  593. // correct. It's probably very close, and it's usually correct, but
  594. // we never quite found all the corner cases.
  595. //
  596. // Go 1.2 and later use a simpler format, documented at golang.org/s/go12symtab.
  597. func (o *Obj) lineFromAline(aline int) (string, int) {
  598. type stackEnt struct {
  599. path string
  600. start int
  601. offset int
  602. prev *stackEnt
  603. }
  604. noPath := &stackEnt{"", 0, 0, nil}
  605. tos := noPath
  606. pathloop:
  607. for _, s := range o.Paths {
  608. val := int(s.Value)
  609. switch {
  610. case val > aline:
  611. break pathloop
  612. case val == 1:
  613. // Start a new stack
  614. tos = &stackEnt{s.Name, val, 0, noPath}
  615. case s.Name == "":
  616. // Pop
  617. if tos == noPath {
  618. return "<malformed symbol table>", 0
  619. }
  620. tos.prev.offset += val - tos.start
  621. tos = tos.prev
  622. default:
  623. // Push
  624. tos = &stackEnt{s.Name, val, 0, tos}
  625. }
  626. }
  627. if tos == noPath {
  628. return "", 0
  629. }
  630. return tos.path, aline - tos.start - tos.offset + 1
  631. }
  632. func (o *Obj) alineFromLine(path string, line int) (int, error) {
  633. if line < 1 {
  634. return 0, &UnknownLineError{path, line}
  635. }
  636. for i, s := range o.Paths {
  637. // Find this path
  638. if s.Name != path {
  639. continue
  640. }
  641. // Find this line at this stack level
  642. depth := 0
  643. var incstart int
  644. line += int(s.Value)
  645. pathloop:
  646. for _, s := range o.Paths[i:] {
  647. val := int(s.Value)
  648. switch {
  649. case depth == 1 && val >= line:
  650. return line - 1, nil
  651. case s.Name == "":
  652. depth--
  653. if depth == 0 {
  654. break pathloop
  655. } else if depth == 1 {
  656. line += val - incstart
  657. }
  658. default:
  659. if depth == 1 {
  660. incstart = val
  661. }
  662. depth++
  663. }
  664. }
  665. return 0, &UnknownLineError{path, line}
  666. }
  667. return 0, UnknownFileError(path)
  668. }
  669. /*
  670. * Errors
  671. */
  672. // UnknownFileError represents a failure to find the specific file in
  673. // the symbol table.
  674. type UnknownFileError string
  675. func (e UnknownFileError) Error() string { return "unknown file: " + string(e) }
  676. // UnknownLineError represents a failure to map a line to a program
  677. // counter, either because the line is beyond the bounds of the file
  678. // or because there is no code on the given line.
  679. type UnknownLineError struct {
  680. File string
  681. Line int
  682. }
  683. func (e *UnknownLineError) Error() string {
  684. return "no code at " + e.File + ":" + strconv.Itoa(e.Line)
  685. }
  686. // DecodingError represents an error during the decoding of
  687. // the symbol table.
  688. type DecodingError struct {
  689. off int
  690. msg string
  691. val any
  692. }
  693. func (e *DecodingError) Error() string {
  694. msg := e.msg
  695. if e.val != nil {
  696. msg += fmt.Sprintf(" '%v'", e.val)
  697. }
  698. msg += fmt.Sprintf(" at byte %#x", e.off)
  699. return msg
  700. }