[llvm] [llvm-ar][Object] Use K_GNU instead of K_COFF for archives with no symtab. (PR #82898)
Jacek Caban via llvm-commits
llvm-commits at lists.llvm.org
Mon Feb 26 06:10:36 PST 2024
https://github.com/cjacek updated https://github.com/llvm/llvm-project/pull/82898
>From 01b7c455f9fb57c3b22deddea3368d948a267316 Mon Sep 17 00:00:00 2001
From: Jacek Caban <jacek at codeweavers.com>
Date: Sat, 24 Feb 2024 23:34:31 +0100
Subject: [PATCH 1/2] [llvm-ar][Object] Use K_GNU instead of K_COFF for
archives with no symtab.
---
llvm/lib/Object/ArchiveWriter.cpp | 7 +++---
llvm/test/tools/llvm-ar/no-symtab.yaml | 32 ++++++++++++++++++++++++++
2 files changed, 36 insertions(+), 3 deletions(-)
create mode 100644 llvm/test/tools/llvm-ar/no-symtab.yaml
diff --git a/llvm/lib/Object/ArchiveWriter.cpp b/llvm/lib/Object/ArchiveWriter.cpp
index 02f72521c8b544..9af2b6e94a270a 100644
--- a/llvm/lib/Object/ArchiveWriter.cpp
+++ b/llvm/lib/Object/ArchiveWriter.cpp
@@ -966,10 +966,12 @@ static Error writeArchiveToStream(raw_ostream &Out,
SmallString<0> StringTableBuf;
raw_svector_ostream StringTable(StringTableBuf);
SymMap SymMap;
+ bool ShouldWriteSymtab = WriteSymtab != SymtabWritingMode::NoSymtab;
// COFF symbol map uses 16-bit indexes, so we can't use it if there are too
- // many members.
- if (isCOFFArchive(Kind) && NewMembers.size() > 0xfffe)
+ // many members. COFF format also requires symbol table presence, so use
+ // GNU format when NoSymtab is requested.
+ if (isCOFFArchive(Kind) && (NewMembers.size() > 0xfffe || !ShouldWriteSymtab))
Kind = object::Archive::K_GNU;
// In the scenario when LLVMContext is populated SymbolicFile will contain a
@@ -998,7 +1000,6 @@ static Error writeArchiveToStream(raw_ostream &Out,
uint64_t LastMemberHeaderOffset = 0;
uint64_t NumSyms = 0;
uint64_t NumSyms32 = 0; // Store symbol number of 32-bit member files.
- bool ShouldWriteSymtab = WriteSymtab != SymtabWritingMode::NoSymtab;
for (const auto &M : Data) {
// Record the start of the member's offset
diff --git a/llvm/test/tools/llvm-ar/no-symtab.yaml b/llvm/test/tools/llvm-ar/no-symtab.yaml
new file mode 100644
index 00000000000000..7370c9b3235522
--- /dev/null
+++ b/llvm/test/tools/llvm-ar/no-symtab.yaml
@@ -0,0 +1,32 @@
+## Create archives with no symtab in various formats and check that we can read them.
+
+# RUN: yaml2obj %s -o %t.o
+# RUN: rm -f %t.*.a
+
+# RUN: llvm-ar --format=gnu rcS %t.gnu.a %t.o
+# RUN: llvm-ar --format=coff rcS %t.coff.a %t.o
+# RUN: llvm-ar --format=darwin rcS %t.darwin.a %t.o
+# RUN: llvm-ar --format=bsd rcS %t.bsd.a %t.o
+# RUN: llvm-ar --format=bigarchive rcS %t.bigarchive.a %t.o
+
+# RUN: llvm-nm --print-armap %t.gnu.a | FileCheck %s
+# RUN: llvm-nm --print-armap %t.coff.a | FileCheck %s
+# RUN: llvm-nm --print-armap %t.darwin.a | FileCheck %s
+# RUN: llvm-nm --print-armap %t.bsd.a | FileCheck %s
+# RUN: llvm-nm --print-armap %t.bigarchive.a | FileCheck %s
+
+# CHECK-NOT: Archive map
+
+--- !ELF
+FileHeader:
+ Class: ELFCLASS64
+ Data: ELFDATA2LSB
+ Type: ET_REL
+ Machine: EM_X86_64
+Sections:
+ - Name: .text
+ Type: SHT_PROGBITS
+Symbols:
+ - Name: symbol
+ Binding: STB_GLOBAL
+ Section: .text
>From e0d50255da142be7b20a0a67f2adf0c1ada1e387 Mon Sep 17 00:00:00 2001
From: Jacek Caban <jacek at codeweavers.com>
Date: Mon, 26 Feb 2024 15:08:01 +0100
Subject: [PATCH 2/2] Check for COFF files in performWriteOperation if there is
an old archive with no symbol table
---
llvm/test/tools/llvm-ar/coff-symtab.test | 8 +++++++-
llvm/tools/llvm-ar/llvm-ar.cpp | 15 +++++++++++----
2 files changed, 18 insertions(+), 5 deletions(-)
diff --git a/llvm/test/tools/llvm-ar/coff-symtab.test b/llvm/test/tools/llvm-ar/coff-symtab.test
index 50d08fba3b02f6..86f79144416459 100644
--- a/llvm/test/tools/llvm-ar/coff-symtab.test
+++ b/llvm/test/tools/llvm-ar/coff-symtab.test
@@ -1,6 +1,6 @@
Verify that llvm-ar uses COFF archive format by ensuring that archive map is sorted.
-RUN: rm -rf %t.dif && split-file %s %t.dir && cd %t.dir
+RUN: rm -rf %t.dir && split-file %s %t.dir && cd %t.dir
RUN: yaml2obj coff-symtab.yaml -o coff-symtab.obj
RUN: llvm-ar crs out.a coff-symtab.obj
@@ -14,6 +14,12 @@ RUN: yaml2obj elf.yaml -o coff-symtab.o
RUN: llvm-ar crs --format coff out3.a coff-symtab.o
RUN: llvm-nm --print-armap out3.a | FileCheck %s
+Create an empty archive with no symbol map, add a COFF file to it.
+
+RUN: llvm-ar rcS out4.a
+RUN: llvm-ar rs out4.a coff-symtab.obj
+RUN: llvm-nm --print-armap out4.a | FileCheck %s
+
CHECK: Archive map
CHECK-NEXT: a in coff-symtab
CHECK-NEXT: b in coff-symtab
diff --git a/llvm/tools/llvm-ar/llvm-ar.cpp b/llvm/tools/llvm-ar/llvm-ar.cpp
index c58a85c695dacf..5c74bd5589320f 100644
--- a/llvm/tools/llvm-ar/llvm-ar.cpp
+++ b/llvm/tools/llvm-ar/llvm-ar.cpp
@@ -1026,14 +1026,21 @@ static void performWriteOperation(ArchiveOperation Operation,
Kind = object::Archive::K_GNU;
else if (OldArchive) {
Kind = OldArchive->kind();
- if (Kind == object::Archive::K_BSD) {
- auto InferredKind = object::Archive::K_BSD;
+ std::optional<object::Archive::Kind> AltKind;
+ if (Kind == object::Archive::K_BSD)
+ AltKind = object::Archive::K_DARWIN;
+ else if (Kind == object::Archive::K_GNU && !OldArchive->hasSymbolTable())
+ // If there is no symbol table, we can't tell GNU from COFF format
+ // from the old archive type.
+ AltKind = object::Archive::K_COFF;
+ if (AltKind) {
+ auto InferredKind = Kind;
if (NewMembersP && !NewMembersP->empty())
InferredKind = NewMembersP->front().detectKindFromObject();
else if (!NewMembers.empty())
InferredKind = NewMembers.front().detectKindFromObject();
- if (InferredKind == object::Archive::K_DARWIN)
- Kind = object::Archive::K_DARWIN;
+ if (InferredKind == AltKind)
+ Kind = *AltKind;
}
} else if (NewMembersP)
Kind = !NewMembersP->empty() ? NewMembersP->front().detectKindFromObject()
More information about the llvm-commits
mailing list