`ar` 库覆盖时间戳

发布于 2024-11-25 02:35:57 字数 1424 浏览 3 评论 0原文

.a 存档格式标头需要时间戳。当我重建静态库时,这导致了无数的头痛,主要是因为我无法准确地重现原始二进制文件。

例如(这是在我的 Mac 上,但在 x64 linux 中也会发生同样的事情):

$ cat foo.h
int foo();
$ cat foo.c
#include "foo.h"
int foo() { return 3; }
$ gcc -fno-pic -m64 -arch x86_64 -I/usr/local/include -O3 -c foo.c -o foo.o -fpic
$ ar rcs libfoo.a foo.o
$ md5 libfoo.a
MD5 (libfoo.a) = 0d0e6606185de4e994c47f4a0e54c1c4
$ mv libfoo.a libfoo.a1
$ ar rcs libfoo.a foo.o
$ md5 libfoo.a
MD5 (libfoo.a) = 22a69d42e1325ae8f978c2a18a4886da    

为了向自己证明唯一的区别是时间,我根据 hexdump 进行了比较:

$ diff <(hexdump libfoo.a) <(hexdump libfoo.a1)
2,3c2,3
< 0000010 20 20 20 20 20 20 20 20 31 33 31 31 30 34 33 30
< 0000020 38 36 20 20 35 30 31 20 20 20 32 30 20 20 20 20
---
> 0000010 20 20 20 20 20 20 20 20 31 33 31 31 30 34 32 38
> 0000020 37 31 20 20 35 30 31 20 20 20 32 30 20 20 20 20

如果您使用标头格式进行反向求解,则对应于时间字段。

联机帮助页没有说明是否可以覆盖标头中的时间戳。有什么想法吗?

编辑:是的,可以返回并物理破解文件以使用任意时间戳。是的,可以改变程序的行为。考虑到这种情况的具体情况,并非所有这些本质上都是严格的技术性的,手动更改时间戳的工具是不可接受的,ar 的修改版本也不可接受,也不可以干扰实际系统时间。

编辑:在这种情况下,我必须证明,在构建路径没有任何不可接受的偏差的情况下,可以从源代码生成二进制文件。在某些行业(例如金融),这显然是一种标准做法。使用手动工具来更改时间戳是不可接受的(因为使用了不在原始构建路径中的特殊工具)。手卷版本的 ar 是不可接受的(类似问题)。更改系统时钟的问题在于构建必须完美协调(这是一个长达一小时的构建,包含大量库和二进制文件)。可接受的解决方案包括:

  • AR 或其他程序的标志,可以覆盖库中的时间戳
  • 现有的(年龄 > 1 年)工具,可以执行此操作
  • GCC 的标志,可以在进行链接时覆盖来自 ar 的时间戳

the .a archive format header requires a timestamp. This has led to countless headaches when I rebuild a static library, mainly because I can't exactly reproduce the original binary.

For example (this is on my Mac, but the same thing happens in x64 linux):

$ cat foo.h
int foo();
$ cat foo.c
#include "foo.h"
int foo() { return 3; }
$ gcc -fno-pic -m64 -arch x86_64 -I/usr/local/include -O3 -c foo.c -o foo.o -fpic
$ ar rcs libfoo.a foo.o
$ md5 libfoo.a
MD5 (libfoo.a) = 0d0e6606185de4e994c47f4a0e54c1c4
$ mv libfoo.a libfoo.a1
$ ar rcs libfoo.a foo.o
$ md5 libfoo.a
MD5 (libfoo.a) = 22a69d42e1325ae8f978c2a18a4886da    

To prove to myself that the only difference was time, I took a diff based on hexdump:

$ diff <(hexdump libfoo.a) <(hexdump libfoo.a1)
2,3c2,3
< 0000010 20 20 20 20 20 20 20 20 31 33 31 31 30 34 33 30
< 0000020 38 36 20 20 35 30 31 20 20 20 32 30 20 20 20 20
---
> 0000010 20 20 20 20 20 20 20 20 31 33 31 31 30 34 32 38
> 0000020 37 31 20 20 35 30 31 20 20 20 32 30 20 20 20 20

which, if you backsolve using the header format, corresponds to the time field.

Manpage gives no indication of whether or not it is possible to override the timestamp from the header. Any thoughts?

Edit: yes, it is possible to go back and physically hack the file to use an arbitrary timestamp. yes, it is possible to change the program's behavior. Given the circumstances surrounding the situation, not all of which are strictly technical in nature, a tool to manually change the timestamp is not acceptable, nor is a modified version of ar, nor is messing with the actual system time.

Edit: In this circumstance, I have to prove that, without any unacceptable deviation from the build path, the binaries can be produced from source. In some industries (e.g. finance) this is apparently a standard practice. A handrolled tool to change the timestamps is unacceptable (because a special tool, which was not in the original build path, was used). A handrolled version of ar is unacceptable (similar problem). The problem with changing system clock is that the build would have to be perfectly coordinated (it is an hour-long build with a lot of libraries and binaries). Acceptable solutions include:

  • flags to AR or other programs that could override the timestamp in the library
  • an existing (age > 1 year) tool to do this
  • flags to GCC that could override the timestamp coming from ar when doing the linking

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

风柔一江水 2024-12-02 02:35:57

在 ar 中使用“确定性模式”。请参阅手册中 ar 的选项“D”。

me@mybox:~$ rm libfoo.a; touch foo.o; ar rcsD libfoo.a foo.o; md5sum libfoo.a
3ecae045133ff919d1e42f6050ef56be  libfoo.a
me@mybox:~$ rm libfoo.a; touch foo.o; ar rcsD libfoo.a foo.o; md5sum libfoo.a
3ecae045133ff919d1e42f6050ef56be  libfoo.a

如果您之后使用 ranlib,请确保您使用 ranlib -D;否则ranlib会将时间戳放回去。

Use "deterministic mode" in ar. See option "D" for ar in manual.

me@mybox:~$ rm libfoo.a; touch foo.o; ar rcsD libfoo.a foo.o; md5sum libfoo.a
3ecae045133ff919d1e42f6050ef56be  libfoo.a
me@mybox:~$ rm libfoo.a; touch foo.o; ar rcsD libfoo.a foo.o; md5sum libfoo.a
3ecae045133ff919d1e42f6050ef56be  libfoo.a

If you use ranlib afterwards, make sure you're using ranlib -D; otherwise ranlib will put the timestamp back.

感性不性感 2024-12-02 02:35:57

使用 dd 可以让你覆盖你想要的文件部分:

dd if=libfoo.a1 of=libfoo.a skip=30 seek=30 count=4 bs=1 conv=notrunc

当然,这意味着你需要在其他地方使用时间戳(你可以有一个非常基本的 C 程序,它获取当前时间并以小端或大端输出然后使用 dd 你可以覆盖库文件)。使用 dd,我可以覆盖 .a 文件并且不会得到 diff 结果

using dd will let you overwrite the part of the file you want:

dd if=libfoo.a1 of=libfoo.a skip=30 seek=30 count=4 bs=1 conv=notrunc

of course this means that you'll need your timestamp somewhere else (you can have a very basic c program that takes the current time and outputs it in little endian or big endian and then with dd you can overwrite the library file). using dd, i can overwrite the .a file and get no diff results

萌︼了一个春 2024-12-02 02:35:57

如果二进制文件的其余部分始终完全相同,那么您可以在 .a 文件中找到时间戳并用固定值(如全零)覆盖它。

If the rest of the binary is always exactly the same, then you could locate the timestamp in the .a file and override it with a fixed value (like all zeroes).

长发绾君心 2024-12-02 02:35:57

我在 GitHub 中编写了一个 python 脚本,用于重置没有 -D 选项的旧版本 ar 的时间戳。

我已经在Python 3.8.10和Python 2.6.6中进行了测试。

https://gist.github.com/Supermanuu/ccdbe0c5d15d41dd1df75ad288e2a30a

清除时间戳的使用示例:

./manageStaticLibTimestamp.py cw *.a

用法:

Usage: ./manageStaticLibTimestamp.py [pcw] <static library paths ...>
 p - print timestamps
 c - clear timestamps
 w - write timestamps

I wrote a python script in my GitHub to reset timestamps for older versions of ar that didn't have -D option.

I have tested in Python 3.8.10 and Python 2.6.6.

https://gist.github.com/Supermanuu/ccdbe0c5d15d41dd1df75ad288e2a30a

Use example for clearing timestamps:

./manageStaticLibTimestamp.py cw *.a

Usage:

Usage: ./manageStaticLibTimestamp.py [pcw] <static library paths ...>
 p - print timestamps
 c - clear timestamps
 w - write timestamps
迷路的信 2024-12-02 02:35:57

默认答案是“ar工具做不到”

The default answer is "It can't be done by the ar tool"

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文