go cmd/objdump: 函数文件名不正确

tf7tbtn2  于 2个月前  发布在  Go
关注(0)|答案(9)|浏览(22)

请注意,cmplx.Inf被列为位于$GOROOT/src/math/bits.go中。看起来cmd/objdump可能假设函数中的第一个指令位于函数内。在没有前导码的函数中,至少这个假设是错误的。
另外,为什么那里有内联标记?
cc @randall77,因为这是inlmarks的意外后果
cc @dr2chase,用于所有与位置相关的事情

smdncfj3

smdncfj31#

https://golang.org/cl/182758提到了这个问题:cmd: Correctly report the source file of an assembly

9lowa7mx

9lowa7mx2#

感谢Josh的所有帮助。

kmynzznz

kmynzznz3#

在genssa之前,我们有:

v8 (+21) = InlMark <void> [1] v1
v19 (+17) = InlMark <void> [2] v1
v14 (22) = MOVSDconst <float64> [+Inf] : X0

在genssa之后,我们有:

v8 00006 (?) NOP
v19 00007 (+17) XCHGL	AX, AX
v14 00008 (+21) MOVSD	$(+Inf.0), X0

是的,内联标记移除有些奇怪,可能需要修复。不知何故,它没有移除两个标记,而是将一个合并成一个实际的指令(v8->v14),也许这迫使它保留另一个标记(v19)?
我并不惊讶的主要错误。除了第一个指令之外,没有其他地方可以获取位置信息。也许还有返回指令(如果有的话)?

1aaf6o9v

1aaf6o9v4#

另一个寻找位置信息的地方,至少在amd64上,是任何尾随(填充)INT $3指令。但是将启发式更改为首先查找RET,然后查看第一个指令(如果没有RET),似乎是个好开始。

lawou6xi

lawou6xi5#

你好,我是Joshua,对于这个程序还有很多不懂的地方。

在第186行的Print方法中:

  1. 创建了一个额外的tabWriter示例来处理输出的第一行~第202行。
  2. 移除了调用打印第一行的代码,因为它将在函数的后面被处理~第214行。
  3. 添加了两个额外的变量来存储指令中的最后一个指令以及与之关联的文件~第226行。
  4. 在传递给Decode方法的回调函数中,设置了作为项目3声明的变量~第233行。
  5. 在调用Decode之后,我添加了一些逻辑来检查最后一个指令的值,如果它是“RET”,则使用与之关联的文件,否则默认为第一个指令,然后刷新输出的头部和主体~第260行。

由于传递给Decode的回调函数中调用了Fprintf,所以我使用了额外的一个tabWriter示例。封闭的Print方法依赖于io.Writer接口,因此更改比我想要深入讨论的要复杂得多。请告诉我上面的解释是否合理,或者我应该采取什么方向来修复这个问题。

mnowg1ta

mnowg1ta6#

感谢您关注这个问题!
如果简单地调用两次Decode,首先只是为了找到RET(如果有的话),然后第二次进行所有打印,性能会受到影响吗?(顺便说一下,函数中的任何RET都可以工作。它不一定是最终指令,而且通常不会是。)

brgchamk

brgchamk7#

这是一个更好的建议。它减少了更改的行数,并保留了输出的顺序以匹配代码中的逻辑顺序。感谢指出RET代码可能在指令中的任何位置,我过于关注示例,没有考虑到这一点。
一个警告是,我不确定如何短路调用Decode,因为函数正在执行一个回调,这可能会阻止添加goto标签,因为作用域?
执行时间是线性的,所以我不认为解码符号两次会增加太多开销,除非有我不知道的低级事件发生。我会添加一些性能分析代码,并对算法进行一些性能测试,因为这将是一个很好的学习经验。

v9tzhpje

v9tzhpje8#

听起来不错。如果需要帮助,请告诉我。

关于短路问题,我认为你需要添加对它的显式支持,例如让Decode函数的arg返回一个布尔值,表示是否停止解码。你可以先不加这个功能,作为第二步再加上,因为这是一个优化。

lsmd5eda

lsmd5eda9#

今天早上,我熟悉了pprof。当调用函数两次以获取返回代码时,会出现2倍的减速。添加短路逻辑并在运行时重新运行分析。这将减少额外开销的一半,这可能接近平均情况。我有一台快速的笔记本电脑,但结果可以在几秒钟内测量到,这足以证明包含短路逻辑是合理的,因为它已经写下来了。我将提交这些更改,并将其留给代码审查。

相关问题