readFrame parses the addr2line output for a single address. It returns a populated plugin.Frame and whether it has reached the end of the data.
()
| 123 | // returns a populated plugin.Frame and whether it has reached the end of the |
| 124 | // data. |
| 125 | func (d *addr2Liner) readFrame() (plugin.Frame, bool) { |
| 126 | funcname, err := d.rw.readLine() |
| 127 | if err != nil { |
| 128 | return plugin.Frame{}, true |
| 129 | } |
| 130 | if strings.HasPrefix(funcname, "0x") { |
| 131 | // If addr2line returns a hex address we can assume it is the |
| 132 | // sentinel. Read and ignore next two lines of output from |
| 133 | // addr2line |
| 134 | d.rw.readLine() |
| 135 | d.rw.readLine() |
| 136 | return plugin.Frame{}, true |
| 137 | } |
| 138 | |
| 139 | fileline, err := d.rw.readLine() |
| 140 | if err != nil { |
| 141 | return plugin.Frame{}, true |
| 142 | } |
| 143 | |
| 144 | linenumber := 0 |
| 145 | |
| 146 | if funcname == "??" { |
| 147 | funcname = "" |
| 148 | } |
| 149 | |
| 150 | if fileline == "??:0" { |
| 151 | fileline = "" |
| 152 | } else { |
| 153 | if i := strings.LastIndex(fileline, ":"); i >= 0 { |
| 154 | // Remove discriminator, if present |
| 155 | if disc := strings.Index(fileline, " (discriminator"); disc > 0 { |
| 156 | fileline = fileline[:disc] |
| 157 | } |
| 158 | // If we cannot parse a number after the last ":", keep it as |
| 159 | // part of the filename. |
| 160 | if line, err := strconv.Atoi(fileline[i+1:]); err == nil { |
| 161 | linenumber = line |
| 162 | fileline = fileline[:i] |
| 163 | } |
| 164 | } |
| 165 | } |
| 166 | |
| 167 | return plugin.Frame{ |
| 168 | Func: funcname, |
| 169 | File: fileline, |
| 170 | Line: linenumber}, false |
| 171 | } |
| 172 | |
| 173 | func (d *addr2Liner) rawAddrInfo(addr uint64) ([]plugin.Frame, error) { |
| 174 | d.mu.Lock() |