惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Security Archives - TechRepublic
Security Archives - TechRepublic
博客园 - 三生石上(FineUI控件)
云风的 BLOG
云风的 BLOG
C
Check Point Blog
Engineering at Meta
Engineering at Meta
Y
Y Combinator Blog
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
Forbes - Security
Forbes - Security
IT之家
IT之家
L
LINUX DO - 最新话题
N
News and Events Feed by Topic
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
雷峰网
雷峰网
N
News | PayPal Newsroom
The Last Watchdog
The Last Watchdog
V
Visual Studio Blog
月光博客
月光博客
Microsoft Azure Blog
Microsoft Azure Blog
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
Webroot Blog
Webroot Blog
TaoSecurity Blog
TaoSecurity Blog
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
Schneier on Security
Schneier on Security
P
Privacy International News Feed
G
Google Developers Blog
博客园 - 聂微东
博客园 - 叶小钗
M
MIT News - Artificial intelligence
Apple Machine Learning Research
Apple Machine Learning Research
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
WordPress大学
WordPress大学
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
Simon Willison's Weblog
Simon Willison's Weblog
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
宝玉的分享
宝玉的分享
H
Hacker News: Front Page
Martin Fowler
Martin Fowler
L
Lohrmann on Cybersecurity
G
GRAHAM CLULEY
酷 壳 – CoolShell
酷 壳 – CoolShell
罗磊的独立博客
T
The Exploit Database - CXSecurity.com
S
Security @ Cisco Blogs
博客园_首页
AWS News Blog
AWS News Blog
P
Proofpoint News Feed
人人都是产品经理
人人都是产品经理
Help Net Security
Help Net Security
Google DeepMind News
Google DeepMind News
T
Threatpost

ZDDHUB

PixelsMeasure 开发第二年总结 PixelsMeasure 开发一年总结 Swift/SwiftUI 踩坑记 为什么说 GPT 利好程序员 ChatGPT 编程实现 Web 数字水印 Web 数字水印探究 Micro Frontends for Mobile URL 加载系统(URL Loading System) Protocol Buffers GraphQL 从 0 到 1 开发一款 IOS 应用 - Swift MV* 软件设计架构 学习一个新技巧需要多久? 不停机数据库迁移 Rspec 如何 mock update 方法更新自己? Rails 使用 mysql2 出现的段错误 使用 Docker-compose 部署 Rails 应用到生产环境 Cocoa troubleshooting 独孤九剑 Dit (0x05) - 终端篇 Gem-based Jekyll theme 开发小记 Miscellaneous 前端手记 TodoMVC 之 Redux 篇 前端手记 TodoMVC 之 Server 篇 前端手记 TodoMVC 之 React 篇 前端手记 TodoMVC 之 CSS 篇 独孤九剑 Dit (0x04) - 测试篇 独孤九剑 Dit (0x03) - 缓存篇 英语小抄 Make mistakes 大牛俱乐部上线啦 独孤九剑 Dit (0x02) - 数据结构篇 独孤九剑 Dit (0x01) - 总决 独孤九剑 Dit (0x00) - 我为什么要做 Dit 零值强制类型转换的使用 终端颜色输出重定向 Go语法简略 - 正则表达式 Makefile Go语法简略 - Duck框架探索 Go语法简略 - 依赖注入 Go语法简略 - web应用框架 Go语法简略 - 反射 Go语法简略 - 面向对象 Go语法简略 - goroutine Go语法简略 - 方法和接口 Go语法简略 - 基础篇 大牛 轻松科研 未来这几年 为 Android Studio 创建图标 Shell Git Vim 金庸答百问 论拖延症 Flex, A fast scanner generator 有理想的人 从虚拟到现实 常用视频转接口 Recognizer configuration on CentOS 整个世界清静了 《Python源码剖析》读书笔记
LLDB debug Golang
zddhub · 2015-12-20 · via ZDDHUB

除了 GDB,还可以使用 LLDB debug go code

熟练调试工具是程序员的必备技能,lldb 的发展势头,大有取缔 gdb 的趋势,因此需要把 lldb 加入到自己的工具箱里。

LLDB 命令

LLDB 的所有命令都遵从以下格式:

<noun> <verb> [-options [option-value]] [argument [argument...]]

对于常用命令,可设置别名,降低输入负担。(可通过别名设置和 GDB 相同的语法,降低记忆负担)。

常用命令集

go build -gcflags "-N -l" -o test test.go 关闭编译优化
b test.go:10    设置断点,如果项目中存在同名文件,会根据行号对应的内容选择一个,或者两个都选
run             运行到断点处
n               运行到下一行
ni              回到当前运行的代码片段
p varname       打印变量值
frame variable  打印当然 frame 中的所有变量
r               重新运行程序

LLDB 练习

以下通过一个例子程序的调试,了解 LLDB 的基本用法。待调试程序如下:

package main

import (
  "fmt"
  "time"
)

func counting(c chan<- int) {
  for i := 0; i < 10; i++ {
    time.Sleep(1 * time.Second)
    c <- i
  }
  close(c)
}

func main() {
  msg := "Starting main"
  fmt.Println(msg)
  bus := make(chan int)
  msg = "starting a gorountie"
  go counting(bus)
  for count := range bus {
    fmt.Println("count:", count)
  }
}

编译源码,使用 -gcflags "-N -l" 参数关闭编译器代码优化。

$ go build -gcflags "-N -l" -o test test.go

通过 lldb 命令启动调试:

可通过 run (r) 运行整个程序,如下所示,和我们在终端运行命令结果一致。

(lldb) run
Process 3242 launched: '/Users/zdd/Projects/Go/src/github.com/zddhub/test/test' (x86_64)
Starting main
count: 0
count: 1
count: 2
count: 3
count: 4
count: 5
count: 6
count: 7
count: 8
count: 9
Process 3242 exited with status = 0 (0x00000000)
(lldb)

断点命令

(lldb) breakpoint set --file test.go --line 17
(lldb) b test.go:17 #简写

为程序设置断点并查看断点,

(lldb) b test.go:10
Breakpoint 1: where = test`main.counting + 43 at test.go:10, address = 0x000000000000206b
(lldb) b test.go:23
Breakpoint 2: where = test`main.main + 514 at test.go:23, address = 0x00000000000022f2
(lldb) br list
Current breakpoints:
1: file = 'test.go', line = 10, locations = 1
  1.1: where = test`main.counting + 43 at test.go:10, address = test[0x000000000000206b], unresolved, hit count = 0

2: file = 'test.go', line = 23, locations = 1
  2.1: where = test`main.main + 514 at test.go:23, address = test[0x00000000000022f2], unresolved, hit count = 0

运行一次到第一个断点

(lldb) run
Process 3302 launched: '/Users/zdd/Projects/Go/src/github.com/zddhub/test/test' (x86_64)
Starting main
Process 3302 stopped
* thread #1: tid = 0x11ca78, 0x000000000000206b test`main.counting(c=0x000000c820070000) + 43 at test.go:10, stop reason = breakpoint 1.1
    frame #0: 0x000000000000206b test`main.counting(c=0x000000c820070000) + 43 at test.go:10
   7
   8    func counting(c chan<- int) {
   9      for i := 0; i < 10; i++ {
-> 10       time.Sleep(1 * time.Second)
   11       c <- i
   12     }
   13     close(c)
(lldb)

之后,通过 cn 继续运行程序。

查看变量的值:

* thread #10, stop reason = breakpoint 3.1
    frame #0: 0x0000000001093939 xx`main.counting(c=0x000000c420076060) at xx.go:10
   7
   8    func counting(c chan<- int) {
   9      for i := 0; i < 10; i++ {
-> 10       time.Sleep(1 * time.Second)
   11       c <- i
   12     }
   13     close(c)
(lldb) p i
(int) i = 0
(lldb) p c
(chan<- int) c = 0x000000c420076060

查看当前 frame 中的所有变量

(lldb) frame variable
(chan<- int) c = 0x000000c420076060
(int) i = 0
([]*runtime.g) runtime.allgs = (len 5, cap 8) {
  [0] = 0x000000c420000180
  [1] = 0x000000c420000600
  [2] = 0x000000c420000a80
  [3] = 0x000000c420000f00
  [4] = 0x000000c420001080
}

命令 ni 回到当前断点所在的代码片段

(lldb) ni
Process 35396 stopped
* thread #10, stop reason = instruction step over
    frame #0: 0x0000000001093941 xx`main.counting(c=0x000000c420076060) at xx.go:10
   7
   8    func counting(c chan<- int) {
   9      for i := 0; i < 10; i++ {
-> 10       time.Sleep(1 * time.Second)
   11       c <- i
   12     }
   13     close(c)

watch 变量的值:

(lldb) watch set var i
Watchpoint created: Watchpoint 1: addr = 0xc820026798 size = 8 state = enabled type = w
    watchpoint spec = 'i'
    new value: 0
(lldb) c
Process 3302 resuming

Watchpoint 1 hit:
old value: 0
new value: 1
Process 3302 stopped
* thread #1: tid = 0x11ca78, 0x00000000000020be test`main.counting(c=0x000000c820070000) + 126 at test.go:9, stop reason = watchpoint 1
    frame #0: 0x00000000000020be test`main.counting(c=0x000000c820070000) + 126 at test.go:9
   6    )
   7
   8    func counting(c chan<- int) {
-> 9      for i := 0; i < 10; i++ {
   10       time.Sleep(1 * time.Second)
   11       c <- i
   12     }
(lldb)

列举所有观测变量:

(lldb) watch list -v
Number of supported hardware watchpoints: 4
Current watchpoints:
Watchpoint 1: addr = 0xc820026798 size = 8 state = enabled type = w
    watchpoint spec = 'i'
    old value: 0
    new value: 1
    hw_index = 0  hit_count = 1     ignore_count = 0
Watchpoint 2: addr = 0xc8200267b8 size = 8 state = enabled type = w
    watchpoint spec = 'c'
    new value: 0x000000c820070000
    hw_index = -1  hit_count = 0     ignore_count = 0
(lldb)
(lldb) fr v
(long) i = 2
(chan<- int) c = 0x000000c820070000

如果你喜欢这篇文章,欢迎赞赏作者以示鼓励