开发者

`ar` library override timestamp

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


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.


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


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).


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


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

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜