Skip to content

Commit

Permalink
[Object] Provide operator< for ELFSymbolRef (#89861)
Browse files Browse the repository at this point in the history
Normally, operator< accepting DataRefImpl is used when comparing
SymbolRef/ELFSymbolRef. However, it uses std::memcmp which interprets
DataRefImpl union as char string so that the result depends on host
endianness.
For ELFSymbolRef a specialized operator< can be used instead to produce
consistent ordering regardless of endianness by comparing the symbol
table index and symbol index fields separately.
  • Loading branch information
aaupov committed Apr 29, 2024
1 parent 1e174a7 commit df6d2fa
Show file tree
Hide file tree
Showing 2 changed files with 51 additions and 0 deletions.
8 changes: 8 additions & 0 deletions llvm/include/llvm/Object/ELFObjectFile.h
Original file line number Diff line number Diff line change
Expand Up @@ -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.a;
}

class elf_symbol_iterator : public symbol_iterator {
public:
elf_symbol_iterator(const basic_symbol_iterator &B)
Expand Down
43 changes: 43 additions & 0 deletions llvm/unittests/Object/ELFObjectFileTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1504,3 +1504,46 @@ 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;

const uint32_t ValLow = 0x00000001;
const uint32_t ValHigh = 0x00000100;

auto MakeSymbol = [&Obj](size_t SymtabIndex, size_t SymbolIndex) {
DataRefImpl Data;
Data.d.a = SymtabIndex;
Data.d.b = SymbolIndex;
SymbolRef Sym(Data, &Obj);
return ELFSymbolRef(Sym);
};

ELFSymbolRef ELFSymLowLow = MakeSymbol(ValLow, ValLow);
ELFSymbolRef ELFSymLowHigh = MakeSymbol(ValLow, ValHigh);
ELFSymbolRef ELFSymHighLow = MakeSymbol(ValHigh, ValLow);
ELFSymbolRef ELFSymHighHigh = MakeSymbol(ValHigh, ValHigh);

EXPECT_TRUE(ELFSymLowLow < ELFSymLowHigh);
EXPECT_FALSE(ELFSymLowHigh < ELFSymLowLow);
EXPECT_FALSE(ELFSymLowLow < ELFSymLowLow);

EXPECT_TRUE(ELFSymLowLow < ELFSymHighHigh);
EXPECT_TRUE(ELFSymLowHigh < ELFSymHighLow);
EXPECT_TRUE(ELFSymLowLow < ELFSymHighLow);

EXPECT_FALSE(ELFSymHighLow < ELFSymLowHigh);
EXPECT_FALSE(ELFSymHighHigh < ELFSymLowLow);
EXPECT_FALSE(ELFSymHighLow < ELFSymLowLow);
}

0 comments on commit df6d2fa

Please sign in to comment.