()
| 289 | } |
| 290 | |
| 291 | func (this *ContextEvent) ParseContextStack() (err error) { |
| 292 | this.Stackinfo = "" |
| 293 | if this.rec.ExtraOptions.UnwindStack { |
| 294 | // 读取完整的栈数据和寄存器数据 并解析为 UnwindBuf 结构体 |
| 295 | this.UnwindBuffer = &UnwindBuf{} |
| 296 | err = this.UnwindBuffer.ParseContext(this.buf) |
| 297 | if err != nil { |
| 298 | panic(fmt.Sprintf("UnwindStack ParseContext failed, err:%v", err)) |
| 299 | } |
| 300 | // 立刻获取堆栈信息 对于某些hook点前后可能导致maps发生变化的 堆栈可能不准确 |
| 301 | // 这里后续可以调整为只dlopen一次 拿到要调用函数的handle 不要重复dlopen |
| 302 | content, err := util.ReadMapsByPid(this.Pid) |
| 303 | if err != nil || this.mconf.ManualStack { |
| 304 | if err == nil { |
| 305 | maps_helper.TryManualUpdateMaps(this.Pid, []byte(content)) |
| 306 | } |
| 307 | // 直接读取 maps 失败 那么从 mmap2 事件中获取 |
| 308 | // 根据测试结果 有这样的情况 -> 即 fork 产生的子进程 那么应该查找其父进程 mmap2 事件 |
| 309 | maps_helper.SetLogger(this.logger) |
| 310 | info, err := maps_helper.GetStack(this.Pid, this.UnwindBuffer) |
| 311 | if err != nil { |
| 312 | // this.logger.Printf("Error when opening file:%v", err) |
| 313 | this.logger.Printf("Error when GetStack:%v", err) |
| 314 | } else { |
| 315 | this.Stackinfo = info |
| 316 | } |
| 317 | return nil |
| 318 | } |
| 319 | // 发现一个奇怪的问题 termux 按 tab 会访问两次 /dev/null |
| 320 | // 但是第一次的堆栈很大概率打印不了或者不完整 --mstack 正常 |
| 321 | this.Stackinfo = ParseStack(content, this.GetOpt(), this.UnwindBuffer) |
| 322 | } else if this.rec.ExtraOptions.ShowRegs { |
| 323 | err = this.RegsBuffer.ParseContext(this.buf) |
| 324 | if err != nil { |
| 325 | panic(fmt.Sprintf("UnwindStack ParseContext failed, err:%v", err)) |
| 326 | } |
| 327 | } |
| 328 | return nil |
| 329 | } |
nothing calls this directly
no test coverage detected