Skip to content

Commit

Permalink
[bfd/ChangeLog]
Browse files Browse the repository at this point in the history
2009-03-11  Chris Demetriou  <cgd@google.com>

	* bfd.c (BFD_DETERMINISTIC_OUTPUT): New flag.
	* bfd-in2.h: Regenerate.
	* archive.c (bfd_ar_hdr_from_filesystem): If BFD_DETERMINISTIC_OUTPUT
	flag is set, use 0 for uid, gid, and timestamp, and use 0644 for file
	mode.
	(bsd_write_armap): Likewise.
	(_bfd_archive_bsd_update_armap_timestamp): If BFD_DETERMINISTIC_OUTPUT
	flag is set, do nothing.
	(coff_write_armap): If BFD_DETERMINISTIC_OUTPUT flag is set, use 0
	for timestamp.

[binutils/ChangeLog]
2009-03-11  Chris Demetriou  <cgd@google.com>

	* ar.c (deterministic): New global variable.
	(main): Recognize new 'D' option, which enables 'deterministic mode'.
	(usage): Document new 'D' option.
	(write_archive): Set BFD_DETERMINISTIC_OUTPUT in output archive's
	flags if deterministic mode was requested.
	* doc/binutils.texi (ar): Document deterministic mode ('D' option).

[binutils/testsuite/ChangeLog]
2009-03-11  Chris Demetriou  <cgd@google.com>

	* binutils-all/ar.exp (deterministic_archive): New test.
  • Loading branch information
Chris Demetriou committed Mar 11, 2009
1 parent a07dbd4 commit 36e4dce
Show file tree
Hide file tree
Showing 9 changed files with 144 additions and 5 deletions.
13 changes: 13 additions & 0 deletions bfd/ChangeLog
Original file line number Diff line number Diff line change
@@ -1,3 +1,16 @@
2009-03-11 Chris Demetriou <cgd@google.com>

* bfd.c (BFD_DETERMINISTIC_OUTPUT): New flag.
* bfd-in2.h: Regenerate.
* archive.c (bfd_ar_hdr_from_filesystem): If BFD_DETERMINISTIC_OUTPUT
flag is set, use 0 for uid, gid, and timestamp, and use 0644 for file
mode.
(bsd_write_armap): Likewise.
(_bfd_archive_bsd_update_armap_timestamp): If BFD_DETERMINISTIC_OUTPUT
flag is set, do nothing.
(coff_write_armap): If BFD_DETERMINISTIC_OUTPUT flag is set, use 0
for timestamp.

2009-03-11 Ulrich Weigand <uweigand@de.ibm.com>

* elf32-spu.c (find_function_stack_adjust): Handle sf instruction
Expand Down
44 changes: 39 additions & 5 deletions bfd/archive.c
Original file line number Diff line number Diff line change
Expand Up @@ -1652,6 +1652,16 @@ bfd_ar_hdr_from_filesystem (bfd *abfd, const char *filename, bfd *member)
return NULL;
}

/* If the caller requested that the BFD generate deterministic output,
fake values for modification time, UID, GID, and file mode. */
if ((abfd->flags & BFD_DETERMINISTIC_OUTPUT) != 0)
{
status.st_mtime = 0;
status.st_uid = 0;
status.st_gid = 0;
status.st_mode = 0644;
}

amt = sizeof (struct ar_hdr) + sizeof (struct areltdata);
ared = bfd_zalloc (abfd, amt);
if (ared == NULL)
Expand Down Expand Up @@ -2220,20 +2230,39 @@ bsd_write_armap (bfd *arch,
unsigned int count;
struct ar_hdr hdr;
struct stat statbuf;
long uid, gid;

firstreal = mapsize + elength + sizeof (struct ar_hdr) + SARMAG;

stat (arch->filename, &statbuf);
if ((arch->flags & BFD_DETERMINISTIC_OUTPUT) == 0)
{
/* Remember the timestamp, to keep it holy. But fudge it a little. */
bfd_ardata (arch)->armap_timestamp = (statbuf.st_mtime
+ ARMAP_TIME_OFFSET);
uid = getuid();
gid = getgid();
}
else
{
/* If deterministic, we use 0 as the timestamp in the map.
Some linkers may require that the archive filesystem modification
time is less than (or near to) the archive map timestamp. Those
linkers should not be used with deterministic mode. (GNU ld and
Gold do not have this restriction.) */
bfd_ardata (arch)->armap_timestamp = 0;
uid = 0;
gid = 0;
}

memset (&hdr, ' ', sizeof (struct ar_hdr));
memcpy (hdr.ar_name, RANLIBMAG, strlen (RANLIBMAG));
/* Remember the timestamp, to keep it holy. But fudge it a little. */
bfd_ardata (arch)->armap_timestamp = statbuf.st_mtime + ARMAP_TIME_OFFSET;
bfd_ardata (arch)->armap_datepos = (SARMAG
+ offsetof (struct ar_hdr, ar_date[0]));
_bfd_ar_spacepad (hdr.ar_date, sizeof (hdr.ar_date), "%ld",
bfd_ardata (arch)->armap_timestamp);
_bfd_ar_spacepad (hdr.ar_uid, sizeof (hdr.ar_uid), "%ld", getuid ());
_bfd_ar_spacepad (hdr.ar_gid, sizeof (hdr.ar_gid), "%ld", getgid ());
_bfd_ar_spacepad (hdr.ar_uid, sizeof (hdr.ar_uid), "%ld", uid);
_bfd_ar_spacepad (hdr.ar_gid, sizeof (hdr.ar_gid), "%ld", gid);
_bfd_ar_spacepad (hdr.ar_size, sizeof (hdr.ar_size), "%-10ld", mapsize);
memcpy (hdr.ar_fmag, ARFMAG, 2);
if (bfd_bwrite (&hdr, sizeof (struct ar_hdr), arch)
Expand Down Expand Up @@ -2301,6 +2330,10 @@ _bfd_archive_bsd_update_armap_timestamp (bfd *arch)
struct stat archstat;
struct ar_hdr hdr;

/* If creating deterministic archives, just leave the timestamp as-is. */
if ((arch->flags & BFD_DETERMINISTIC_OUTPUT) != 0)
return TRUE;

/* Flush writes, get last-write timestamp from file, and compare it
to the timestamp IN the file. */
bfd_flush (arch);
Expand Down Expand Up @@ -2385,7 +2418,8 @@ coff_write_armap (bfd *arch,
_bfd_ar_spacepad (hdr.ar_size, sizeof (hdr.ar_size), "%-10ld",
mapsize);
_bfd_ar_spacepad (hdr.ar_date, sizeof (hdr.ar_date), "%ld",
time (NULL));
((arch->flags & BFD_DETERMINISTIC_OUTPUT) == 0
? time (NULL) : 0));
/* This, at least, is what Intel coff sets the values to. */
_bfd_ar_spacepad (hdr.ar_uid, sizeof (hdr.ar_uid), "%ld", 0);
_bfd_ar_spacepad (hdr.ar_gid, sizeof (hdr.ar_gid), "%ld", 0);
Expand Down
5 changes: 5 additions & 0 deletions bfd/bfd-in2.h
Original file line number Diff line number Diff line change
Expand Up @@ -4769,6 +4769,11 @@ struct bfd
to any input file. */
#define BFD_LINKER_CREATED 0x2000

/* This may be set before writing out a BFD to request that it
be written using values for UIDs, GIDs, timestamps, etc. that
will be consistent from run to run. */
#define BFD_DETERMINISTIC_OUTPUT 0x4000

/* Currently my_archive is tested before adding origin to
anything. I believe that this can become always an add of
origin, with origin set to 0 for non archive files. */
Expand Down
5 changes: 5 additions & 0 deletions bfd/bfd.c
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,11 @@ CODE_FRAGMENT
. to any input file. *}
.#define BFD_LINKER_CREATED 0x2000
.
. {* This may be set before writing out a BFD to request that it
. be written using values for UIDs, GIDs, timestamps, etc. that
. will be consistent from run to run. *}
.#define BFD_DETERMINISTIC_OUTPUT 0x4000
.
. {* Currently my_archive is tested before adding origin to
. anything. I believe that this can become always an add of
. origin, with origin set to 0 for non archive files. *}
Expand Down
9 changes: 9 additions & 0 deletions binutils/ChangeLog
Original file line number Diff line number Diff line change
@@ -1,3 +1,12 @@
2009-03-11 Chris Demetriou <cgd@google.com>

* ar.c (deterministic): New global variable.
(main): Recognize new 'D' option, which enables 'deterministic mode'.
(usage): Document new 'D' option.
(write_archive): Set BFD_DETERMINISTIC_OUTPUT in output archive's
flags if deterministic mode was requested.
* doc/binutils.texi (ar): Document deterministic mode ('D' option).

2009-03-09 H.J. Lu <hongjiu.lu@intel.com>

PR binutils/9933
Expand Down
15 changes: 15 additions & 0 deletions binutils/ar.c
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,11 @@ int newer_only = 0;
if any of the members are object files. */
int write_armap = 0;

/* Operate in deterministic mode: write zero for timestamps, uids,
and gids for archive members and the archive symbol table, and write
consistent file modes. */
int deterministic = 0;

/* Nonzero means it's the name of an existing member; position new or moved
files with respect to this one. */
char *posname = NULL;
Expand Down Expand Up @@ -240,6 +245,7 @@ usage (int help)
fprintf (s, _(" command specific modifiers:\n"));
fprintf (s, _(" [a] - put file(s) after [member-name]\n"));
fprintf (s, _(" [b] - put file(s) before [member-name] (same as [i])\n"));
fprintf (s, _(" [D] - use zero for timestamps and uids/gids\n"));
fprintf (s, _(" [N] - use instance [count] of name\n"));
fprintf (s, _(" [f] - truncate inserted file names\n"));
fprintf (s, _(" [P] - use full path names when matching\n"));
Expand Down Expand Up @@ -572,6 +578,9 @@ main (int argc, char **argv)
case 'T':
make_thin_archive = TRUE;
break;
case 'D':
deterministic = TRUE;
break;
default:
/* xgettext:c-format */
non_fatal (_("illegal option -- %c"), c);
Expand Down Expand Up @@ -622,6 +631,9 @@ main (int argc, char **argv)
if (newer_only && operation != replace)
fatal (_("`u' is only meaningful with the `r' option."));

if (newer_only && deterministic)
fatal (_("`u' is not meaningful with the `D' option."));

if (postype != pos_default)
posname = argv[arg_index++];

Expand Down Expand Up @@ -972,6 +984,9 @@ write_archive (bfd *iarch)
obfd->flags |= BFD_TRADITIONAL_FORMAT;
}

if (deterministic)
obfd->flags |= BFD_DETERMINISTIC_OUTPUT;

if (make_thin_archive || bfd_is_thin_archive (iarch))
bfd_is_thin_archive (obfd) = 1;

Expand Down
9 changes: 9 additions & 0 deletions binutils/doc/binutils.texi
Original file line number Diff line number Diff line change
Expand Up @@ -396,6 +396,15 @@ created if it did not exist, when you request an update. But a warning is
issued unless you specify in advance that you expect to create it, by
using this modifier.

@item D
@cindex deterministic archives
Operate in @emph{deterministic} mode. When adding files and the archive
index use zero for UIDs, GIDs, timestamps, and use consistent file modes
for all files. When this option is used, if @command{ar} is used with
identical options and identical input files, multiple runs will create
identical output files regardless of the input files' owners, groups,
file modes, or modification times.

@item f
Truncate names in the archive. @sc{gnu} @command{ar} will normally permit file
names of any length. This will cause it to create archives which are
Expand Down
4 changes: 4 additions & 0 deletions binutils/testsuite/ChangeLog
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
2009-03-11 Chris Demetriou <cgd@google.com>

* binutils-all/ar.exp (deterministic_archive): New test.

2009-03-09 H.J. Lu <hongjiu.lu@intel.com>

PR binutils/9933
Expand Down
45 changes: 45 additions & 0 deletions binutils/testsuite/binutils-all/ar.exp
Original file line number Diff line number Diff line change
Expand Up @@ -354,10 +354,55 @@ proc argument_parsing { } {
pass $testname
}

# Test building a deterministic archive.

proc deterministic_archive { } {
global AR
global AS
global NM
global srcdir
global subdir

set testname "ar deterministic archive"

if ![binutils_assemble $srcdir/$subdir/bintest.s tmpdir/bintest.o] {
unresolved $testname
return
}

if [is_remote host] {
set archive artest.a
set objfile [remote_download host tmpdir/bintest.o]
remote_file host delete $archive
} else {
set archive tmpdir/artest.a
set objfile tmpdir/bintest.o
}

remote_file build delete tmpdir/artest.a

set got [binutils_run $AR "rcD $archive ${objfile}"]
if ![string match "" $got] {
fail $testname
return
}

set got [binutils_run $AR "tv $archive"]
# This only checks the file mode and uid/gid. We can't easily match
# date because it's printed with the user's timezone.
if ![string match "rw-r--r-- 0/0 *bintest.o*" $got] {
fail $testname
return
}

pass $testname
}

# Run the tests.

long_filenames
symbol_table
thin_archive
thin_archive_with_nested
argument_parsing
deterministic_archive

0 comments on commit 36e4dce

Please sign in to comment.