Skip to content

[Reproduce] Fix thin archive member reproducer paths - #1741

Open
Rachit Mehta (rachitmeht) wants to merge 1 commit into
qualcomm:mainfrom
rachitmeht:fix/reproduce-thin-archive-members
Open

[Reproduce] Fix thin archive member reproducer paths#1741
Rachit Mehta (rachitmeht) wants to merge 1 commit into
qualcomm:mainfrom
rachitmeht:fix/reproduce-thin-archive-members

Conversation

@rachitmeht

Copy link
Copy Markdown

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

@rachitmeht Rachit Mehta (rachitmeht) changed the title Fix thin archive member reproducer paths [Reproduce] Fix thin archive member reproducer paths Aug 20, 2026
@parth-07

Copy link
Copy Markdown
Contributor

Rachit Mehta (@rachitmeht) Can you please add tests?

@parth-07 Parth (parth-07) left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rachit Mehta (@rachitmeht) With this fix, will the created reproducer work standalone?


std::string OutputTarWriter::getHashAndExtension(const Input *Ipt) const {
uint64_t InputHash = Ipt->getResolvedPathHash();
if (const auto *ArchiveMember = llvm::dyn_cast<ArchiveMemberInput>(Ipt))

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Won't we only call getHashAndExtension on top-level inputs, and thus, it should never be called for archive members?

@rachitmeht
Rachit Mehta (rachitmeht) force-pushed the fix/reproduce-thin-archive-members branch from cc5b631 to 481ff1c Compare August 21, 2026 08:22
@@ -0,0 +1,27 @@
#UNSUPPORTED: windows, reproduce_fail

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is the test unsupported for windows? and we likely do not need reproduce_fail either here.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The windows restriction was there because I used bash -x to replay response.txt, I will change it.

RUN: %clang %clangopts -c %p/Inputs/thin-main.c -o %t.tmpdir/main.o
RUN: cd %t.tmpdir
RUN: %ar cr %aropts --thin libsame.a a/foo.o b/foo.o
RUN: %link --no-threads main.o libsame.a -o same.out --reproduce repro.tar --dump-mapping-file mapping.ini

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you prefix all output files using %t? It makes debugging easier as then we do not need additional efforts in finding the full path of the outputs.

if (const auto *ArchiveMember = llvm::dyn_cast<ArchiveMemberInput>(Ipt))
// Thin archive members share the parent archive's resolved path. Include
// the member identity so members with the same basename cannot collide.
InputHash = llvm::hash_combine(InputHash, ArchiveMember->getMemberName(),

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would using the member name alone not be enough to make the hash different here?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I took reference for this from this lld implementation. ELF/InputFiles.cpp

// ThinLTO assumes that all MemoryBufferRefs given to it have a unique
// name. If two archives define two members with the same name, this
// causes a collision which result in only one of the objects being taken
// into consideration at LTO time (which very likely causes undefined
// symbols later in the link stage). So we append file offset to make
// filename unique.

For a/foo.c and b/foo.c
without offset it will be only "libname.a + foo.c"

@parth-07 Parth (parth-07) Aug 21, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The archive member names should be a/foo.o and b/foo.o instead of just foo.o.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I read gnu ar docs, -q allows duplicate files to get appended. Maybe that's the reason lld implements with child offset for uniqueness.

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 qualcomm#1737
@rachitmeht
Rachit Mehta (rachitmeht) force-pushed the fix/reproduce-thin-archive-members branch from 481ff1c to e7aa304 Compare August 21, 2026 11:36
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

--reproduce mishandles thin archive members with identical basenames

2 participants