在 Linux 下进行“二进制二分查找”(bibisect)

From The Document Foundation Wiki
< QA‎ | Bibisect‎ | Linux
Jump to: navigation, search

此页面描述了在 GN/Linux 操作系统下使用我们提供的 Bibisect 仓库进行“二进制二分查找” 的详细指导。如果您想了解 bibisect 的基础知识及简单原理,或者想要在其他操作系统上进行 bibisect, 请首先阅读 Bibisect 二进制二分查找

简介

我们的 bibisect 仓库起初是在 buntu 64位机器上编译生成的。一般情况下,这些仓库都可以在其它最新的现代化64位 GNU/Linux 发行版上运行(比如,Fedora, SuSE, Debian, 等等),尽管可能需要安装额外的软件包。

如果您是在跨平台进行测试,那么一个好的办法是使用虚拟机运行目标操作系统,然后进行 bibisect 测试。请参考下面的#VM 虚拟机部分。

选择一个 Bibisect 仓库(repository)

从下方的 #版本 表格中可以看出,bibisect 仓库有好多个,涵盖不同的源代码 commit 范围。如果您在 LibreOffice 4.4.4 中发现了一个 bug,您可能需要下载 50max 仓库,因为它涵盖了 "从 4.4 分支点到 5.0 分支点之间的范围"

另外,通过测试您很有可能会发现在 LO 4.4.4 中发现的这个 bug 早在 4.4 分支点之前就已经存在了。此时,您就需要下载其他更老的 bibisect 仓库。我们将 bibisect 仓库拆分成多个,一方面是能提升 bibisect 时的操作速度,另一方面是避免下载过多不相关的范围。

有了 bibisect 仓库,但是不知道从哪个 bug 下手?您可以从这个清单中找到需要进行 bibisect 的 bug 报告。

环境搭建

下载 bibisect 仓库之前,请确保您已安装了必要的软件。对于所有平台,您都需要安装:

  • git

下表列出了对于不同的操作系统以及不同的 bubisect 仓库,您需要额外安装的软件包:

发行版 43all 43only 50max lo-linux-dbgutil-daily-till51,lo-linux-dbgutil-daily-till52
Ubuntu 13.10 (Saucy) 对于老于 3.5 的版本,需要安装 libjpeg62 (sudo apt-get install libjpeg62) 应该是开箱即用。
Ubuntu 12.04 LTS (Precise) have to install libjpeg62 for included versions older than 3.5 应该是开箱即用。
openSUSE 12.1 no  ?
Fedora 需要从源代码编译 libjpeg8,然后 LD_PRELOAD 它(对于老于3.5的版本) yum install libcurl, export LD_PRELOAD=/usr/lib64/libcurl.so.4 dnf install harfbuzz, export LD_PRELOAD=/usr/lib64/libharfbuzz.so.0
debian sid 需要安装 librtmp0 及其依赖的包。可从 debian wheezy 软件仓库获得。

下载 Bibisect 仓库

由于我们是分布式的、基于社区的项目,因此 bibisect 仓库分布于多个服务器上。尽管下载每个仓库的方式可能有细微的差异,但是大部分 bibisect 仓库都可以使用常规的下载方式从网上下载,或者直接通过 git clone 下载。下载链接可从下方的 版本列表 中找到。

从 Web 服务器上下载

50max 仓库为例,首先下载该仓库对应的 .tar.xz 文件,然后通过如下 linux 的解压缩命令将该 git 仓库解压:

tar -xf bibisect-50max.tar.xz

校验

To verify one of our repos, you'll need the gpg-key of the person/organization who produced it.

For example, to verify the 43all repo, you'll need the gpg-key from https://launchpad.net/~bjoern-michaelsen and will want to check the signature as follows:

gpg --keyserver keyserver.ubuntu.com --recv-keys XXXXXXXX # replace XXXXXXXX with the OpenPGP keys from web page
gpg --verify bibisect-43all.tar.xz.sig

使用 git clone 的方式下载

举个例子,dbgutil daily bibisect 可从 TDF 的服务器上获得。您可以像克隆任何其他的 git 仓库一样来克隆它:

git clone git://dev-downloads.libreoffice.org/lo-linux-dbgutil-daily.git

需要注意的是,原始的仓库可能有好几个 GB 大小,因此您需要有很好而且可靠的互联网连接。由于 git clone 自身不支断点续传,所以如果由于网络问题而下载中断,您将不得不重新开始克隆。:-(

首次克隆之后,后续如果该仓库有更新,那么可以通过 git pull 来获取,此时的下载量将会很小,这取决于 Tinderbox 添加新的编译包的频率,以及您多久进行一次 git pull.

开始 bibisect”

找到一个需要进行“倒退“测试的 bug, 以及重现该 bug 的明确步骤,并且有了下载好并已解压缩的 bibisect 仓库,现在您就可以随时进行 bibisect 操作了。

从现在开始, latest 指向您所用的 bibisect 仓库中最新的版本,oldest 指向该仓库中最老的版本。很多仓库都已经标记好了 latest/oldest 对应的tag标记,如果没有这些tag,那么您可以使用对应的 hash 值来表示最新和最老的版本。hash 值可以使用如下的 git 命令获得,这两个命令所显示的第一个 hash值,分别对应的是最新的和最老的版本:

git log # 第一条记录对应该仓库涵盖的最新的版本。可按下 End 键转到最后一页,找到最老的版本。
git log --reverse # 反转顺序,第一条记录对应该仓库涵盖的最新的版本

(提示:在 git log 界面中,按下 q 键可退出 log 显示)

然后,打开命令行终端,切换到相应的 git bibisect 仓库所在的目录,检出 latest 提交,然后运行 soffice:

cd <仓库所在的目录路径>
git checkout latest
./opt/program/soffice

在 bibisect-linux-64-5.3, bibisect-linux-64-5.4 以及其他比较新的仓库中,您需要使用以下命令:

git checkout origin/master
./instdir/program/soffice

如果 bug 在当前检出的版本中不存在,那么请在 bug 里添加如下评论:"Regression does not appear in latest version of <您使用的 bibisect 仓库名称>, 比如 bibisect-43all.tar.xz and must be younger",并在 Keywords 字段添加标签 bibisected 以及 bibisectedNewer。至此,您已经完成了 bibisect! 如果还有其它更新的 bibisect 仓库可用,那么您可以下载它,并在这个更老新的仓库中继续 bibisect 这个 bug.

如果 bug 在 latest 版本中存在,那么接下来我们检出 oldest 版本,看看 bug 在该仓库所包含的最早版本中是否存在:

git checkout oldest
./opt/program/soffice

在 bibisect-linux-64-5.3, bibisect-linux-64-5.4 以及其他比较新的仓库中,您需要使用以下命令:

git checkout oldest
./instdir/program/soffice

如果此时 bug 已经存在,说明这个 bug 不是在您所用的这个仓库所涵盖的范围中产生的,而是一个更老的 bug,需要在更老的 bibisect 仓库中进行测试。因此:

首先,在 bug 中添加一则评论,写明 "Regression does appear in oldest version of <您所用的 bibisect 仓库名称> and must be older"

如果您用的是 43all 仓库,那么:

  1. 在 Keywords 字段添加 preBibisect 关键词,然后
  2. 将 bug 的 Version 字段修改为 3.5beta0(这个是您能设置的最老版本)。

如果 bug 在 oldest 版本中不存在(但是在 latest 版本中存在),这表明 bug 是在您正在使用的这个仓库所涵盖的某个范围内产生的,此时您需要进行下一步,以缩小范围(这时候您应该很开心,离成功不远了!)。接下来,我们需要借助 git 的一个强大的工具进行非常高效率的 二分查找(binary search):

git bisect start latest oldest

在 bibisect-linux-64-5.3, bibisect-linux-64-5.4 以及其他比较新的仓库中,您需要使用以下命令:

git bisect start origin/master oldest

然后重复以下命令:

./opt/program/soffice
git bisect good # 如果 bug *不能* 在这个版本重现
git bisect bad  # 如果 bug *能* 在这个版本重现

在 bibisect-linux-64-5.3, bibisect-linux-64-5.4 以及其他比较新的仓库中,您需要使用以下命令:

./instdir/program/soffice
git bisect good # 如果 bug *不能* 在这个版本重现
git bisect bad  # 如果 bug *能* 在这个版本重现

提示:很多时候,检查的某个 LibreOffice 版本可能根本无法正常启动。这可能是由于:虽然 bibisect 仓库最大程度上确保仅包含能正常启动的版本,但是所包含进来的某些版本可能实际上根本无法运行。在这种情况下,您可能需要 跳过 这个不能运行的版本:

git bisect skip # 如果您在该版本中根本无法测试这个 bug,比如这个版本无法启动,或者其他原因

经过几次重复,git 将会显示如下的输出信息:

    9625329ea5a7e3e8475cd21c07726beec20573bd is the first bad commit
    commit 9625329ea5a7e3e8475cd21c07726beec20573bd
    Author: Bjoern Michaelsen <bjoern.michaelsen@canonical.com>
    Date:   Thu Dec 8 12:29:59 2011 +0100

        source-hash-2d19e9bb07ccff3134f855812dddfda5c07b1fe4
       
        commit 2d19e9bb07ccff3134f855812dddfda5c07b1fe4
        Author:     Jan Holesovsky <kendy@suse.cz>
        AuthorDate: Wed Nov 16 14:17:03 2011 +0100
        Commit:     Jan Holesovsky <kendy@suse.cz>
        CommitDate: Wed Nov 16 14:21:33 2011 +0100
       
            Kill one usage of chrel.sed to fix build.

我们需要将这条重要的输出信息添加到 bug 报告的评论里。这条信息里,最重要的部分是 source-hash-2d19e9bb07ccff3134f855812dddfda5c07b1fe4 这一行,它代表了“第一个坏版本”对应的源代码的 hash 值。但是,请在 bug 报告中包含完整的信息。

如果您能同时将 git log 也添加到 bug 的评论里(与上面的输出信息放到一起添加),对开发者可能会更有帮助:

git bisect log

下面是一个 git log 的输出示例(选择这些文字,右键单击,然后复制。按下 q 键退出):

   git bisect start 'latest' 'oldest'
   # good: [2faf4bc12ab490370d2196dedbc8091f9b09d0a5] source-hash-418a35f4861e863feb39eec73f4a39a87fbcb1f3
   git bisect good 2faf4bc12ab490370d2196dedbc8091f9b09d0a5
   # bad: [b6fca7e58854bc617c5fc9a75d1c1720b0d7e1a4] source-hash-ce60138d339a5eb2a174a5d27063249acf2cac42
   git bisect bad b6fca7e58854bc617c5fc9a75d1c1720b0d7e1a4
   # good: [0a28a62d53e996cf66d86e9bfb63ddc6ade75b7e] source-hash-71cbcb62028295a98ceee60cb4c4ee425bafcd2e
   git bisect good 0a28a62d53e996cf66d86e9bfb63ddc6ade75b7e
   # bad: [9625329ea5a7e3e8475cd21c07726beec20573bd] source-hash-2d19e9bb07ccff3134f855812dddfda5c07b1fe4
   git bisect bad 9625329ea5a7e3e8475cd21c07726beec20573bd
   # good: [89d91bb6074026dc0894bcdc6aaf8f6124102da7] source-hash-fb754a0df859e30255c25af8fa19bfaa75f257e7
   git bisect good 89d91bb6074026dc0894bcdc6aaf8f6124102da7

至此,您已经完整完成了这个 bug 的 bibisect. 您需要添加 bibisected 关键词到 bug 的 Keywords 字段,这样别人就能知道这个 bug 已经 bibisect 过了,并且不会再显示在需要 bibisect 的 bug 清单里。

通过 bibisect 找到修复了某个 bug 的 commit(逆向 bibisect)

要找到修复了某个问题的 commit,您可以使用以下方法:

git bisect start --term-new=fixed --term-old=unfixed
git bisect fixed master
git bisect unfixed <some-old-sha> # 您可以使用 "git log --reverse" 来找到 bibisect 包中的第一个版本。

测试时,请根据情况使用

git bisect fixed

或者

git bisect unfixed

Linux 备注

bibisect 仓库中的 git tag 标记

在 43all 仓库中,有诸如 last35onmaster, last36onmaster 这样的 git 标记 (tag), 这些标记对应的是该版本在 master 分支上被分离的时点(分支点)的提交。如果有一个 bug 是在 4.0 和 4.1 之间产生的,那么您可以进行如下查找:

git bisect start last41onmaster last40onmaster

这个命令限定了 git 仅在 last35onmasterlast36onmaster 之间进行二分查找。需要注意,某个版本的分支点会比这个版本首个正式发布的时间点要早很多(正式发布的版本在分支点之后至少要经历多次的 alpha 和 beta 阶段)。这意味着,某个 bug 在某个版本的分支点是好的,但是 bug 很可能在这个版本分支点之后的阶段产生。但是这种 bug 仍然可以在 master 分支上被 bibisect 查找出来(在两个主版本分支点之间的范围内),这是因为几乎所有的源代码提交都会首先在 master 分支上体现。所有,对于这样的情况您需要有些耐心,并保持头脑清醒。

针对 daily dbgutil 仓库的特殊考虑

El每个版本中都有 build-info.txt 文件,这个文件的第一行包含了这个编译版本对应的源代码希哈值(source-hash)。请将第一个好的版本以及第一个坏的版本分别对应的 source hash 与 bibisect 结果一起包含在 bug 报告的评论里,这些信息很有用。

使用 max 仓库系列

请务必阅读这些仓库中的 README 文件,该文件中指出在首次运行前需要执行以下 git 命令:

git reset --hard latest

这些 "max" 仓库 (43max, 44max, 50max) 中,对于每一个 master 分支上的源代码提交 (commit) 都对应有一个编译的二进制提交,但有如下的例外情况:

  • 忽略仅影响除64位体系结构之外的架构的 commit;
  • 损坏的编译会与后续成功的编译合并为一个 commit.

如果某个损坏的编译被跳过,则这条提交的消息中会包含如下的说明:

   (Bibisect: This commit covers source commit(s) ...... which failed to build)

在这种情况下,特定的源代码无法范围无法准确定位,需要进行进一步的调查分析。

在所有其他情况下(指没有已跳过的已损坏的编译),则 bibisect 所得到的结论与在源代码层面进行 git bisect 是一致的(这是因为这种仓库里一个源代码对应一个编译)。此时,您完全可以在 bug 报告的 Keywords 字段同时加入 bisectedbibisected 两个关键词。

Youtube 视频教程

一部简短的视频教程 (Youtube,墙外),由 Florian Reisinger 提供。

  • (非常抱歉,这部视频的音频质量不太好)。

VM 虚拟机

考虑到 bibisect 仓库的庞大体积,以及在 Windows 或者 macOS 主机下测试 GNU/Linux 系统上的 bug 的需要,使用虚拟机是个好主意。

环境建议:

  • 虚拟机软件:VirtualBox
  • Guest 系统:Ubuntu 14.04 x86_64 (桌面版)
  • (虚拟) 磁盘空间:至少 40GB (有些 bibisect 仓库每个可能有 10GB 大小)

简要指南 - 仅 Linux 下

  1. 下载仓库(有好几个G大小,不要担心,您只需要下载一次)- 见 #版本
  2. 将下载得到的仓库解压缩的磁盘上的某个位置。
  3. 打开命令行终端,并确保 git 及 libjpeg62 已安装。在 Ubuntu 系统上,可通过
    sudo apt-get install git libjpeg62
    
    安装。
  4. 进入到解压缩得到的仓库的位置:
    cd [下载后解压缩得到的仓库位置]
    
  5. 开始”二进制二分查找“。
    git bisect start latest oldest
    
    注意此处的"latest"和"oldest"是bibisect仓库中git tag的名称,但是在某些仓库中可能并没有标记这些名称的tag,此时您需要通过 git log 定位最新和最老的 commit。另请注意,此处用的是"bisect", 而不是"bibisect",因为bibisect根本不是git中的一个指令,git中只有bisect. 其本质是,基于 LibreOffice 的源代码先进行编译,然后将编译得到的二进制程序做成了一个git仓库,在该git仓库中进行bisect,与git本身的bisect类似,不同支出在于您不用在二分查找时先编译再运行。
  6. 在当前的 revision 处运行 LibreOffice:
    ./opt/program/soffice
    
  7. 尝试在当前 revision 上重现 bug.
    1. 如果不能重现该 bug, 则标记为:
      git bisect good
      
    2. 如果能重现该 bug,则标记为:
      git bisect bad
      
  8. 重复第6和第7步,直到您得到类似这样的信息:
    5a52acff89c733acbd4be6896748c76a010cb507 is the first bad commit
    
  9. 得到您bibisect操作的日志信息,并将其复制粘贴到 bug 报告中:
    git bisect log
    

版本

下表中包含了从 3.5beta0 到 当前 master 分支范围内的各个 bibisect 仓库。


构建于 版本 维护者 自动构建? 源代码 Commit 开始自 源代码 Commit 结束于 源代码 Commits 数量 二进制构建(编译)数 下载链接 下载大小 此范围内已经 Bibisect 过的 bug 数量 备注
Ubuntu 12.04 x64
43all
Bjoern Michaelsen No core commit d6cde02d core commit c15927f2 60733 755 builds Canonical: repo signature 12Gb 542+[1] 这个仓库替换了过时的 42all 仓库,包含了 3.5 到 4.3 之间的范围。
43only
Bjoern Michaelsen No core commit 22029c7e core commit c15927f2 13951 220 builds Canonical: repo signature 3.6GB 仅包含 4.2 到 4.3 之间的范围。[2]
Ubuntu 14.04 x64
44
Robinson Tryon No core commit dea4a3b9 core commit 2b5b04e1 11075 394 builds tdf download 3.7G

(3.2G download)

从 4.3 分支点到 4.4 beta1 tag 标记
Ubuntu 14.04 x64
41max
MJFrancis Static core commit efca6f15 core commit 863d38fb 9971 8969 builds tdf download 5.5G 从 4.0 分支点到 4.1 分支点。见:#使用 max 仓库系列
Ubuntu 14.04 x64
42max
MJFrancis Static core commit a2c9d4f8 core commit 22ea573b 12145 11048 builds tdf download 8.2G 从 4.1 分支点到 4.2 分支点。#使用 max 仓库系列
Ubuntu 14.04 x64
43max
MJFrancis Static core commit c15927f2 core commit 3f94c9e9 11091 ? 9644 builds ? tdf download 7.4G 从 4.2 分支点到 4.3 分支点。见:#使用 max 仓库系列
Ubuntu 14.04 x64
44max
MJFrancis Static core commit c15927f2 core commit 3f94c9e9 11091 9644 builds tdf download 7.4G 从 4.3 分支点到 4.4 分支点。见:#使用 max 仓库系列
Ubuntu 14.04 x64
50max
MJFrancis Static core commit 57d6b92b core commit 0db96caf 10009 8174 builds tdf download 6.8G 从 4.4 分支点到 5.0 分支点。见:#使用 max 仓库系列
Linux 64bit
bibisect-linux-64-5.2
Xisco Fauli Yes core commit 3ca42d8d core commit 6238f71d 8897 builds TDF: repo libreoffice-5-1-branch-point 到 libreoffice-5-2-branch-point,然后是 libreoffice-5-2 分支
Linux 64bit
bibisect-linux-64-5.3
Norbert Thiebaud Yes core commit 5b168b3f core commit e5ebc3d7 7490 builds TDF: repo libreoffice-5-2-branch-point 到 libreoffice-5-3-branch-point,然后是 libreoffice-5-3 分支
Linux 64bit
bibisect-linux-64-5.4
Xisco Fauli Yes core commit 4136757b core commit 328f3e7e 8869 builds TDF: repo libreoffice-5-3-branch-point 到 libreoffice-5-4-branch-point,然后是 libreoffice-5-4 分支
Linux 64bit
bibisect-linux-64-6.0
Xisco Fauli Yes core commit 487d0388 TDF: repo libreoffice-5-4-branch-point 到 libreoffice-6-0-branch-point,然后是 libreoffice-6-0
Linux 64bit
bibisect-linux-64-6.1
Xisco Fauli Yes core commit 6eeac353 TDF: repo libreoffice-6-0-branch-point 到 最新的 master 分支。
Linux x86_64 dbgutil
dbgutil
Miklos Vajna Yes TDF: repo 最新的 libreoffice-x-y 分支点到最新的 master。
Releases(包含了所有曾经已发布的版本)
releases
Xisco Fauli No (useful to add to it?) 172 个已发布版本 tdf download 6.0G OOo 3.3.0, LO 3.3.0 - LO5.2.3.3- libreoffice-5.3.0.0.alpha1 之间的所有已发布过的版本

较老的 dbgutil daily 仓库

  1. another 250+ bugs reference bibisect, but do not have the bug tagged. Possibly just forgotten to tag
  2. 它替换了两个更小的部分编译仓库:4.2 分支点到 4.2 alpha14.2 alpha1 到 4.3 分支点 -- 这两个仓库将会很快被移除。

解决 'librtmp.so.0: cannot open shared object file' 错误

I experienced this problem with bibisect-50max repository

1. 检查 librtmp 是否已安装

locate librtmp

/usr/lib/x86_64-linux-gnu/librtmp.so.1 
/usr/share/doc/librtmp1 
/usr/share/doc/librtmp1/changelog.Debian.gz 
/usr/share/doc/librtmp1/copyright 
/var/lib/dpkg/info/librtmp1:amd64.list 
/var/lib/dpkg/info/librtmp1:amd64.md5sums 
/var/lib/dpkg/info/librtmp1:amd64.postinst 
/var/lib/dpkg/info/librtmp1:amd64.postrm 
/var/lib/dpkg/info/librtmp1:amd64.shlibs 
/var/lib/dpkg/info/librtmp1:amd64.symbols

2. 创建符号链接

sudo ln -s /usr/lib/x86_64-linux-gnu/librtmp.so.1 /usr/lib/x86_64-linux-gnu/librtmp.so.0

解决 'libboost_filesystem-mt.so.1.53.0: cannot open shared object file' 错误

这个问题会在 bibisect-linux-64-5.3 仓库中发生,是由于在这个仓库中从 core commit 72e6f08c 开始将 liborcus-0.11.so.0 链接到了这个动态库中。

1. 安装您的发行版的 libboost_filesystem

2. 创建符号链接

sudo ln -s /usr/lib/x86_64-linux-gnu/libboost_filesystem.so /usr/lib/x86_64-linux-gnu/libboost_filesystem-mt.so.1.53.0