Skip to content

Commit e7aa304

Browse files
committed
Fix thin archive member reproducer paths
Include the thin archive member name and child offset in the generated input identity. This prevents members with identical basenames from colliding in --reproduce archives and preserves both files during replay. Resolves #1737
1 parent c7cda1a commit e7aa304

5 files changed

Lines changed: 41 additions & 1 deletion

File tree

lib/Support/OutputTarWriter.cpp

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,10 +74,17 @@ void OutputTarWriter::addInputFile(const InputFile *File, bool IsLTOObject) {
7474
}
7575

7676
std::string OutputTarWriter::getHashAndExtension(const Input *Ipt) const {
77+
uint64_t InputHash = Ipt->getResolvedPathHash();
78+
if (const auto *ArchiveMember = llvm::dyn_cast<ArchiveMemberInput>(Ipt))
79+
// Thin archive members share the parent archive's resolved path. Include
80+
// the member identity so members with the same basename cannot collide.
81+
InputHash = llvm::hash_combine(InputHash, ArchiveMember->getMemberName(),
82+
ArchiveMember->getChildOffset());
83+
7784
// Returns filename passed to the linker along with the file hash.
7885
return std::string(
7986
llvm::sys::path::filename(Ipt->getInputFile()->getMappedPath())) +
80-
"." + std::to_string(Ipt->getResolvedPathHash());
87+
"." + std::to_string(InputHash);
8188
}
8289

8390
/// Create mapping.ini file of input filepath to its sha2 hash + file extension
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
int only_a(void) { return 1; }
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
int only_b(void) { return 2; }
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
extern int only_a(void);
2+
extern int only_b(void);
3+
4+
int main(void) { return only_a() + only_b(); }
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
#---ReproduceThinArchiveSameBasename.test----------------- Executable -----------------#
2+
3+
#BEGIN_COMMENT
4+
# Checks that --reproduce preserves thin-archive members with the same basename.
5+
#END_COMMENT
6+
#START_TEST
7+
RUN: %rm -rf %t.tmpdir
8+
RUN: %mkdir %t.tmpdir
9+
RUN: %mkdir %t.tmpdir/a
10+
RUN: %mkdir %t.tmpdir/b
11+
RUN: %clang %clangopts -c %p/Inputs/a/foo.c -o %t.tmpdir/a/foo.o
12+
RUN: %clang %clangopts -c %p/Inputs/b/foo.c -o %t.tmpdir/b/foo.o
13+
RUN: %clang %clangopts -c %p/Inputs/thin-main.c -o %t.tmpdir/main.o
14+
RUN: cd %t.tmpdir
15+
RUN: %ar cr %aropts --thin %t.tmpdir/libsame.a a/foo.o b/foo.o
16+
RUN: %link --no-threads %t.tmpdir/main.o %t.tmpdir/libsame.a -o %t.same.out \
17+
RUN: --reproduce %t.repro.tar --dump-mapping-file %t.mapping.ini
18+
RUN: %filecheck %s < %t.mapping.ini
19+
RUN: %mkdir %t.replay
20+
RUN: %tar %gnutaropts -xf %t.repro.tar -C %t.replay --strip-components=1
21+
RUN: cd %t.replay
22+
RUN: %python -c "import shlex, subprocess; args = shlex.split(open('response.txt').read())[1:]; args[args.index('-o') + 1] = r'%t.same.replay.out'; subprocess.check_call(shlex.split(r'%link') + args)"
23+
RUN: %diff %t.same.out %t.same.replay.out
24+
#END_TEST
25+
26+
CHECK-DAG: Object/foo.o.{{[0-9]+}}
27+
CHECK-DAG: Object/foo.o.{{[0-9]+}}

0 commit comments

Comments
 (0)