[llvm] [Object] Provide operator< for ELFSymbolRef (PR #89861)
Amir Ayupov via llvm-commits
llvm-commits at lists.llvm.org
Wed Apr 24 18:31:23 PDT 2024
https://github.com/aaupov updated https://github.com/llvm/llvm-project/pull/89861
>From b6630e85ff5d4a35cf8d77fad63ba93791ffa806 Mon Sep 17 00:00:00 2001
From: Amir Ayupov <aaupov at fb.com>
Date: Tue, 23 Apr 2024 19:34:12 -0700
Subject: [PATCH 1/3] [Object] Provide operator< for ELFSymbolRef
Normally, operator< accepting DataRefImpl is used when comparing
SymbolRef/ELFSymbolRef. However, it uses std::memcmp which interprets
DataRefImpl union as char string. For ELFSymbolRef it's known that it
uses the struct view of the union, therefore a specialized operator< can
be used instead.
---
llvm/include/llvm/Object/ELFObjectFile.h | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/llvm/include/llvm/Object/ELFObjectFile.h b/llvm/include/llvm/Object/ELFObjectFile.h
index 1d457be93741f2..8ec0e3fe15dc9d 100644
--- a/llvm/include/llvm/Object/ELFObjectFile.h
+++ b/llvm/include/llvm/Object/ELFObjectFile.h
@@ -199,6 +199,14 @@ class ELFSymbolRef : public SymbolRef {
}
};
+inline bool operator<(const ELFSymbolRef &A, const ELFSymbolRef &B) {
+ const DataRefImpl &DRIA = A.getRawDataRefImpl();
+ const DataRefImpl &DRIB = B.getRawDataRefImpl();
+ if (DRIA.d.a == DRIB.d.a)
+ return DRIA.d.b < DRIB.d.b;
+ return DRIA.d.a < DRIB.d.b;
+}
+
class elf_symbol_iterator : public symbol_iterator {
public:
elf_symbol_iterator(const basic_symbol_iterator &B)
>From f7e44cfd100904bfd1ea87312a1576f4f4c1524c Mon Sep 17 00:00:00 2001
From: Amir Ayupov <aaupov at fb.com>
Date: Wed, 24 Apr 2024 11:08:50 -0700
Subject: [PATCH 2/3] Use std::tie instead
---
llvm/include/llvm/Object/ELFObjectFile.h | 7 ++-----
1 file changed, 2 insertions(+), 5 deletions(-)
diff --git a/llvm/include/llvm/Object/ELFObjectFile.h b/llvm/include/llvm/Object/ELFObjectFile.h
index 8ec0e3fe15dc9d..11464f317ccd96 100644
--- a/llvm/include/llvm/Object/ELFObjectFile.h
+++ b/llvm/include/llvm/Object/ELFObjectFile.h
@@ -200,11 +200,8 @@ class ELFSymbolRef : public SymbolRef {
};
inline bool operator<(const ELFSymbolRef &A, const ELFSymbolRef &B) {
- const DataRefImpl &DRIA = A.getRawDataRefImpl();
- const DataRefImpl &DRIB = B.getRawDataRefImpl();
- if (DRIA.d.a == DRIB.d.a)
- return DRIA.d.b < DRIB.d.b;
- return DRIA.d.a < DRIB.d.b;
+ auto make_tie = [](DataRefImpl DRI) { return std::tie(DRI.d.a, DRI.d.b); };
+ return make_tie(A.getRawDataRefImpl()) < make_tie(B.getRawDataRefImpl());
}
class elf_symbol_iterator : public symbol_iterator {
>From 6e6905330cad0562b8a5e95f51b48f919cfffc39 Mon Sep 17 00:00:00 2001
From: Amir Ayupov <aaupov at fb.com>
Date: Wed, 24 Apr 2024 11:39:09 -0700
Subject: [PATCH 3/3] Add ELFObjectFileTest::ELFSymbolRefLess
---
llvm/unittests/Object/ELFObjectFileTest.cpp | 36 +++++++++++++++++++++
1 file changed, 36 insertions(+)
diff --git a/llvm/unittests/Object/ELFObjectFileTest.cpp b/llvm/unittests/Object/ELFObjectFileTest.cpp
index c4d2b4ae8b9acd..a4a0f6d4a7276d 100644
--- a/llvm/unittests/Object/ELFObjectFileTest.cpp
+++ b/llvm/unittests/Object/ELFObjectFileTest.cpp
@@ -1504,3 +1504,39 @@ TEST(ELFObjectFileTest, GetSectionAndRelocations) {
"SHT_RELA section with index 1: failed to get a "
"relocated section: invalid section index: 255");
}
+
+TEST(ELFObjectFileTest, ELFSymbolRefLess) {
+ SmallString<0> Storage;
+ Expected<ELFObjectFile<ELF64LE>> ElfOrErr = toBinary<ELF64LE>(Storage, R"(
+--- !ELF
+FileHeader:
+ Class: ELFCLASS64
+ Data: ELFDATA2LSB
+ Type: ET_DYN
+ Machine: EM_X86_64
+)");
+
+ ASSERT_THAT_EXPECTED(ElfOrErr, Succeeded());
+ const ELFObjectFile<ELF64LE> &Obj = *ElfOrErr;
+
+ llvm::object::DataRefImpl Data1;
+ Data1.d.a = 0x00000000;
+ Data1.d.b = 0x00000001;
+ SymbolRef Symbol1(Data1, &Obj);
+ ELFSymbolRef ELFSymbol1(Symbol1);
+
+ llvm::object::DataRefImpl Data2;
+ Data2.d.a = 0x00000000;
+ Data2.d.b = 0x00000100;
+ SymbolRef Symbol2(Data2, &Obj);
+ ELFSymbolRef ELFSymbol2(Symbol2);
+
+ // SymbolRef operator< uses std::memcmp treating the union as char string.
+ if (llvm::sys::IsLittleEndianHost)
+ EXPECT_FALSE(Symbol1 < Symbol2);
+ else
+ EXPECT_TRUE(Symbol1 < Symbol2);
+
+ // ELFSymbolRef operator< compares struct fields.
+ EXPECT_TRUE(ELFSymbol1 < ELFSymbol2);
+}
More information about the llvm-commits
mailing list