Macos 如何将函数名强制转换为地址并在LLDB中添加偏移量?

Macos 如何将函数名强制转换为地址并在LLDB中添加偏移量?,macos,debugging,lldb,Macos,Debugging,Lldb,比如说,我在Mach-O可执行文件中有两个相邻的函数subfunc()和main(),我想反汇编subfunc()到main()+0x10的所有指令。 我知道我可以使用`(void(*)()subfunc`)将函数强制转换为地址—难道没有更简单的方法吗 我的尝试如下,但我收到以下错误消息: dis-s`(void(*)()子功能`-e`(void(*)()main+0x10` 错误:错误:指向函数类型“void()”的指针上的算术运算 如何修复此问题?这似乎是正确的语法: dis --star

比如说,我在Mach-O可执行文件中有两个相邻的函数
subfunc()
main()
,我想反汇编
subfunc()
main()+0x10的所有指令。

我知道我可以使用
`(void(*)()subfunc`
)将函数强制转换为地址—难道没有更简单的方法吗

我的尝试如下,但我收到以下错误消息:

dis-s`(void(*)()子功能`-e`(void(*)()main+0x10`
错误:错误:指向函数类型“void()”的指针上的算术运算


如何修复此问题?

这似乎是正确的语法:

dis --start-address `(void(*)())main` --end-address `(void(*)())main`+0x10
此语法与您尝试的变体之间的一个非常小的区别是,
+0x10
偏移量在反勾号字符之外,即偏移量在结束反勾号之后

FWIW该变体似乎也能正常工作:

dis --start-address `(void(*)())main` --end-address 0x10+`(void(*)())main`

发现过程:

  • 我不熟悉您在原始问题中描述的“backtick”+函数类型转换,因此这是一个非常有用的起点

    在我的例子中,我试图在共享库中的函数偏移量处设置断点,在搜索到您的问题之前,我已经做了这么多:

    breakpoint set --shlib libexample.dylib --address `((void*)some_function)+81`
    
    error: error: function 'some_function' with unknown type must be given a function type
    error: 1 errors parsing expression
    
    dis --start-address `(void(*)())some_function` --end-address `(void(*)())some_function`+81
    
  • 函数强制转换提示的使用符合错误消息中所述的“函数类型”要求,因此我下一步能够:

    print (void(*)())some_function
    
    (void (*)()) $38 = 0x00000001230094d0 (libexample.dylib`some_function)
    
  • 然后,我尝试了backtick变量,该变量似乎有效,但我希望该值以十六进制显示:

    print `(void(*)())some_function`
    (long) $2 = 4882207952
    
  • 但是,当我尝试将
    -f hex
    格式选项与打印一起使用时,我遇到了一个错误:

    print -f hex `(void(*)())some_function`
    
    error: use of undeclared identifier 'f'
    error: 1 errors parsing expression
    
  • 最后我注意到,
    'print'是
    帮助打印
    输出底部“expression--”的缩写,我意识到这意味着它(显然是?)无法将替代显示格式与
    print
    一起使用,因为它被转换为
    表达式--f hex…
    ,这是无效的语法

  • 最终,我找到了命令名、显示格式和“-”的必要位置和组合,以使其按需要显示:

    expression -f hex -- `(void(*)())some_function`
    
    (long) $7 = 0x00000001230094d0
    
  • 没有什么特别的原因(我记得),就是在这一点上,我试着把偏移量放在背刻度之外,结果成功了

    expression -f hex -- `(void(*)())some_function`+81
    
    (long) $12 = 0x0000000123009521
    
  • 当我尝试使用断点时,它仍然有效:

    breakpoint set --shlib libexample.dylib --address `(void(*)())some_function`+81
    
    Breakpoint 6: where = libexample.dylib`some_function + 81, address = 0x0000000123009521
    
  • 然后,我验证了它是否与原始问题中的
    dis
    命令一起工作:

    breakpoint set --shlib libexample.dylib --address `((void*)some_function)+81`
    
    error: error: function 'some_function' with unknown type must be given a function type
    error: 1 errors parsing expression
    
    dis --start-address `(void(*)())some_function` --end-address `(void(*)())some_function`+81
    
  • 并确认裸函数名不够:

    dis --start-address some_function --end-address `(void(*)())some_function`+81
    
    error: address expression "some_function" evaluation failed
    
  • 我还再次确认,回勾之间的偏移不起作用:

  • 正是在这一点上,我意识到我能够解析错误消息(据推测这是故意的):

    根本问题是“指针上的算术”

  • 进一步的研究表明,它“在函数类型指针上未定义”,并且可以作为gcc扩展提供:

  • 这让我们回到@JasonMolenda和@JimIngham的评论,以及函数指针算术解析是如何特例的

    在我看来,您收到的“错误:函数类型指针上的算术…”消息充其量是糟糕的UX,充其量是一个bug-
    lldb
    本身基本上以这种方式显示地址引用:

    0x1230094f9:  jle    0x123009cc2               ; some_function + 2034
    
    我对
    libexample.dylib`some_function+81
    被显示但AFAICT没有被解析也有类似的感觉

  • 总之,此表格适用于:

    `(void(*)())some_function`+0x10
    
    现在我只需要弄清楚为什么一些函数没有做我认为应该做的事情……:)


如果您有调试信息,因此lldb知道这些是函数,那么有一种特殊情况,您不使用反勾号,它做了正确的事情--
dis-s subfunc-e main+16
--但是我刚刚检查过,当lldb现在不知道这些是函数符号时,它看起来不起作用。显然,没有任何有效的C表达式可用于向函数名添加偏移量,因此lldb中有一些额外的技巧来允许使用这个(通常有用的)地址表达式。我不记得为什么它与一个参数一起工作,这个参数使用的是地址表达式,而不是反勾号eval r.n.@JasonMolenda-谢谢。地址表达式和反勾号求值不是一回事吗?你能给我指一下这些东西的文档吗?main+5不是一个有效的C表达式,但是它是一种非常方便的指定地址的方法。我们添加了“地址表达式”,而不是修改表达式解析器以接受这种形式(我们希望表达式解析器与源语言保持一致)。他们首先尝试将其参数作为表达式进行计算,如果计算失败,他们将解析形式为“symbolname+-offset”的简单表达式“help address expression”应该记录在文档中,但帮助字符串有点简洁…@JimIngham,在任何地方都没有关于地址表达式或backqoute表达式的详细文档吗?如果
+-
工作,为什么
main+5
不工作?
main
不是一个符号吗?