[PATCH] debugedit: Add -p, --preserve-dates
Mark Wielaard
mark@klomp.org
Sun Jun 22 22:33:38 GMT 2025
When --preserve-dates is given to debugedit it will take the original
st_atim and st_mtim and put them back using utimensat after processing
the file (and setting back the original st_mode).
Use it in find-debuginfo when processing ar archive entries so
timestamps in new archives are the same when put back.
* tools/debugedit.c (preserve_dates): New bool.
(optionsTable): Add preserve-dates.
(optionsChars): Add p.
(helpText): Add -p|--preserve-dates.
(main): Handle 'p'. Use utimensat if preserve_dates true.
* scripts/find-debuginfo.in (do_ar_file): Use debugedit -p.
* tests/debugedit.at: Add new debugedit preserve timestamps test.
* tests/find-debuginfo.at: Select the modes, date and entry names
in the ar and compare them after find-debuginfo processing.
https://sourceware.org/bugzilla/show_bug.cgi?id=33096
---
scripts/find-debuginfo.in | 4 ++--
tests/debugedit.at | 20 +++++++++++++++++++-
tests/find-debuginfo.at | 8 +++++---
tools/debugedit.c | 25 ++++++++++++++++++++++---
4 files changed, 48 insertions(+), 9 deletions(-)
diff --git a/scripts/find-debuginfo.in b/scripts/find-debuginfo.in
index 1a4f2a0b64d3..144fd09bfee5 100755
--- a/scripts/find-debuginfo.in
+++ b/scripts/find-debuginfo.in
@@ -543,12 +543,12 @@ do_ar_file()
if [ $? -ne 0 ]; then
res=1
fi
- # preserve timestamp from original file, though debugedit may lose it, PR33096
+ # preserve timestamp from original file and invoke debugedit with -p
touch -d "$date" "$tmpdir/$member_dn$member_bn"
if file "$tmpdir/$member_dn$member_bn" |
grep -qE 'ELF.*, not stripped'; then
- debugedit -b "$debug_base_name" -d "$debug_dest_name" \
+ debugedit -p -b "$debug_base_name" -d "$debug_dest_name" \
-l "$SOURCEFILE" "$tmpdir/$member_dn$member_bn"
if [ $? -ne 0 ]; then
res=1
diff --git a/tests/debugedit.at b/tests/debugedit.at
index 21b67a6e4ef7..042da913af6a 100644
--- a/tests/debugedit.at
+++ b/tests/debugedit.at
@@ -1,6 +1,6 @@
# debugedit.at: Tests for the debugedit tool
#
-# Copyright (C) 2019, 2024 Mark J. Wielaard <mark@klomp.org>
+# Copyright (C) 2019, 2024, 2025 Mark J. Wielaard <mark@klomp.org>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@@ -920,3 +920,21 @@ AT_CHECK([[expr "$bid3" : '[0-9a-f]*']], [0], [ignore])
AT_CHECK([[test "$bid3" != "$bid2a"]])
AT_CLEANUP
+
+# Preserving time stamps
+AT_SETUP([debugedit preserve timestamps])
+AT_KEYWORDS([debugedit] [timestamp])
+
+# compile a test program and record the timestamps
+echo "int main () { }" > main.c
+$CC $CFLAGS -g -o main main.c
+AT_CHECK([[stat -c "%x %y" main]], [0], [stdout], [])
+mv stdout expout
+
+# process it with debugedit, using -p
+AT_CHECK([[debugedit -p -b $(pwd) -d /foo/bar/baz ./main]])
+
+# check timestamps were preserved
+AT_CHECK([[stat -c "%x %y" main]], [0], [expout], [])
+
+AT_CLEANUP
diff --git a/tests/find-debuginfo.at b/tests/find-debuginfo.at
index 5552ce17fe58..1deb7edc6a60 100644
--- a/tests/find-debuginfo.at
+++ b/tests/find-debuginfo.at
@@ -61,6 +61,8 @@ $AR qP subdir_build/dupes.a subdir_zo?b/dupe.o subdir_club/dupe.o # with P, thes
# list old .a contents
AT_CHECK([$AR tPv subdir_build/dupes.a],[0],[stdout],[ignore])
AT_CHECK([test `wc -l < stdout` -eq 4],[0],[ignore],[ignore])
+# Select just the modes, date and entry names (see check after debugedit below)
+awk '{print $1, $4, $5, $6, $7, $8, $9}' < stdout > expout
# expect original source tree refs
AT_CHECK([$READELF --debug-dump=line subdir_build/dupes.a | grep `pwd`], [0], [stdout], [ignore])
@@ -69,9 +71,9 @@ AT_CHECK([$READELF --debug-dump=line subdir_build/dupes.a | grep `pwd`], [0], [s
AT_CHECK([[env RPM_BUILD_DIR=${PWD} RPM_BUILD_ROOT=${PWD} RPM_PACKAGE_NAME=pkg RPM_PACKAGE_VERSION=ver RPM_PACKAGE_RELEASE=rel RPM_ARCH=arch \
bash -x `type -p find-debuginfo` -S sourcefiles.list -v ${PWD}/subdir_build]], [0], [stdout], [ignore])
-# list new .a contents; ar tPv contains timestamps / subdirs, so not a good fit for AT_DATA() here
-AT_CHECK([$AR tPv subdir_build/dupes.a],[0],[stdout],[ignore])
-AT_CHECK([test `wc -l < stdout` -eq 4],[0],[ignore],[ignore])
+# list new .a contents; expout generated from original (see above)
+# Only check modes, timestamp and archive entry names
+AT_CHECK([$AR tPv subdir_build/dupes.a | awk '{print $1, $4, $5, $6, $7, $8, $9}'],[0],[expout],[ignore])
# expect non-empty source file list
AT_CHECK([grep . ${PWD}/subdir_build/sourcefiles.list | tr '\0' '\n'], [0], [stdout], [ignore])
diff --git a/tools/debugedit.c b/tools/debugedit.c
index fcf8f7d6564b..03daae10ed7c 100644
--- a/tools/debugedit.c
+++ b/tools/debugedit.c
@@ -1,5 +1,5 @@
/* Copyright (C) 2001-2003, 2005, 2007, 2009-2011, 2016, 2017 Red Hat, Inc.
- Copyright (C) 2022, 2023, 2024 Mark J. Wielaard <mark@klomp.org>
+ Copyright (C) 2022, 2023, 2024, 2025 Mark J. Wielaard <mark@klomp.org>
Written by Alexander Larsson <alexl@redhat.com>, 2002
Based on code by Jakub Jelinek <jakub@redhat.com>, 2001.
String/Line table rewriting by Mark Wielaard <mjw@redhat.com>, 2017.
@@ -96,6 +96,7 @@ char *list_file = NULL;
int list_file_fd = -1;
int do_build_id = 0;
int no_recompute_build_id = 0;
+bool preserve_dates = false;
char *build_id_seed = NULL;
int show_version = 0;
@@ -3399,13 +3400,14 @@ static struct option optionsTable[] =
{ "build-id", no_argument, 0, 'i' },
{ "build-id-seed", required_argument, 0, 's' },
{ "no-recompute-build-id", no_argument, 0, 'n' },
+ { "preserve-dates", no_argument, 0, 'p' },
{ "version", no_argument, 0, 'V' },
{ "help", no_argument, 0, '?' },
{ "usage", no_argument, 0, 'u' },
{ NULL, 0, 0, 0 }
};
-static const char *optionsChars = "b:d:l:is:nV?u";
+static const char *optionsChars = "b:d:l:is:npV?u";
static const char *helpText =
"Usage: %s [OPTION...] FILE\n"
@@ -3419,6 +3421,7 @@ static const char *helpText =
" this string as hash seed\n"
" -n, --no-recompute-build-id do not recompute build ID note even\n"
" when -i or -s are given\n"
+ " -p, --preserve-dates Preserve modified/access timestamps\n"
"\n"
"Help options:\n"
" -?, --help Show this help message\n"
@@ -3429,7 +3432,9 @@ static const char *usageText =
"Usage: %s [-in?] [-b|--base-dir STRING] [-d|--dest-dir STRING]\n"
" [-l|--list-file STRING] [-i|--build-id] \n"
" [-s|--build-id-seed STRING]\n"
- " [-n|--no-recompute-build-id] [-?|--help] [-u|--usage]\n"
+ " [-n|--no-recompute-build-id]\n"
+ " [-p|--preserve-dates]\n"
+ " [-?|--help] [-u|--usage]\n"
" [-V|--version] FILE\n";
static void
@@ -3720,6 +3725,10 @@ main (int argc, char *argv[])
no_recompute_build_id = 1;
break;
+ case 'p':
+ preserve_dates = true;
+ break;
+
case 'V':
show_version = 1;
break;
@@ -4046,6 +4055,16 @@ main (int argc, char *argv[])
if (chmod (file, stat_buf.st_mode) != 0)
error (0, errno, "Failed to chmod input file '%s' to restore old access rights", file);
+ /* Preserve timestamps. */
+ if (preserve_dates)
+ {
+ struct timespec tv[2];
+ tv[0] = stat_buf.st_atim;
+ tv[1] = stat_buf.st_mtim;
+ if (utimensat (AT_FDCWD, file, tv, 0) != 0)
+ error (0, errno, "Failed to preserve timestamps on '%s'", file);
+ }
+
free ((char *) dso->filename);
destroy_strings (&dso->debug_str);
destroy_strings (&dso->debug_line_str);
--
2.49.0
More information about the Debugedit
mailing list