Skip to content

Commit d5d8b1c

Browse files
committed
[llvm-objcopy] Fix handling of MIPS64 little endian files
MIPS64 little endian target has a "special" encoding of `r_info` relocation record field. Instead of one 64-bit little endian number, it is a little endian 32-bit number followed by a 32-bit big endian number. For correct reading and writing such fields we must provide information about target machine into the corresponding routine. This patch does this for the `llvm-objcopy` tool and fix handling of MIPS64 little endian files. The bug was reported in the issue #52647. Differential Revision: https://reviews.llvm.org/D115635
1 parent bd05376 commit d5d8b1c

File tree

3 files changed

+65
-16
lines changed

3 files changed

+65
-16
lines changed
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
# mips64el has a special encoding of the r_info relocation field.
2+
# Test that we support both endianness.
3+
4+
# RUN: yaml2obj %s -DENDIANNESS=ELFDATA2LSB -o %t1-le
5+
# RUN: llvm-objcopy %t1-le %t2-le
6+
# RUN: llvm-readobj --relocations %t2-le | FileCheck %s
7+
8+
# RUN: yaml2obj %s -DENDIANNESS=ELFDATA2MSB -o %t1-be
9+
# RUN: llvm-objcopy %t1-be %t2-be
10+
# RUN: llvm-readobj --relocations %t2-be | FileCheck %s
11+
12+
!ELF
13+
FileHeader:
14+
Class: ELFCLASS64
15+
Data: [[ENDIANNESS]]
16+
Type: ET_REL
17+
Machine: EM_MIPS
18+
Sections:
19+
- Name: .text
20+
Type: SHT_PROGBITS
21+
- Name: .rela.text
22+
Type: SHT_RELA
23+
Relocations:
24+
- Offset: 8
25+
Symbol: foo
26+
Type: R_MIPS_JALR
27+
Symbols:
28+
- Name: foo
29+
Type: STT_FUNC
30+
Section: .text
31+
32+
# CHECK: Relocations [
33+
# CHECK-NEXT: Section (2) .rela.text {
34+
# CHECK-NEXT: 0x8 R_MIPS_JALR/R_MIPS_NONE/R_MIPS_NONE foo 0x0
35+
# CHECK-NEXT: }
36+
# CHECK-NEXT: ]

llvm/tools/llvm-objcopy/ELF/Object.cpp

Lines changed: 23 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -978,12 +978,12 @@ static void setAddend(Elf_Rel_Impl<ELFT, true> &Rela, uint64_t Addend) {
978978
}
979979

980980
template <class RelRange, class T>
981-
static void writeRel(const RelRange &Relocations, T *Buf) {
981+
static void writeRel(const RelRange &Relocations, T *Buf, bool IsMips64EL) {
982982
for (const auto &Reloc : Relocations) {
983983
Buf->r_offset = Reloc.Offset;
984984
setAddend(*Buf, Reloc.Addend);
985985
Buf->setSymbolAndType(Reloc.RelocSymbol ? Reloc.RelocSymbol->Index : 0,
986-
Reloc.Type, false);
986+
Reloc.Type, IsMips64EL);
987987
++Buf;
988988
}
989989
}
@@ -992,9 +992,11 @@ template <class ELFT>
992992
Error ELFSectionWriter<ELFT>::visit(const RelocationSection &Sec) {
993993
uint8_t *Buf = reinterpret_cast<uint8_t *>(Out.getBufferStart()) + Sec.Offset;
994994
if (Sec.Type == SHT_REL)
995-
writeRel(Sec.Relocations, reinterpret_cast<Elf_Rel *>(Buf));
995+
writeRel(Sec.Relocations, reinterpret_cast<Elf_Rel *>(Buf),
996+
Sec.getObject().IsMips64EL);
996997
else
997-
writeRel(Sec.Relocations, reinterpret_cast<Elf_Rela *>(Buf));
998+
writeRel(Sec.Relocations, reinterpret_cast<Elf_Rela *>(Buf),
999+
Sec.getObject().IsMips64EL);
9981000
return Error::success();
9991001
}
10001002

@@ -1398,6 +1400,14 @@ Expected<std::unique_ptr<Object>> IHexELFBuilder::build() {
13981400
return std::move(Obj);
13991401
}
14001402

1403+
template <class ELFT>
1404+
ELFBuilder<ELFT>::ELFBuilder(const ELFObjectFile<ELFT> &ElfObj, Object &Obj,
1405+
Optional<StringRef> ExtractPartition)
1406+
: ElfFile(ElfObj.getELFFile()), Obj(Obj),
1407+
ExtractPartition(ExtractPartition) {
1408+
Obj.IsMips64EL = ElfFile.isMips64EL();
1409+
}
1410+
14011411
template <class ELFT> void ELFBuilder<ELFT>::setParentSegment(Segment &Child) {
14021412
for (Segment &Parent : Obj.segments()) {
14031413
// Every segment will overlap with itself but we don't want a segment to
@@ -1639,21 +1649,21 @@ static void getAddend(uint64_t &ToSet, const Elf_Rel_Impl<ELFT, true> &Rela) {
16391649
}
16401650

16411651
template <class T>
1642-
static Error initRelocations(RelocationSection *Relocs,
1643-
SymbolTableSection *SymbolTable, T RelRange) {
1652+
static Error initRelocations(RelocationSection *Relocs, T RelRange) {
16441653
for (const auto &Rel : RelRange) {
16451654
Relocation ToAdd;
16461655
ToAdd.Offset = Rel.r_offset;
16471656
getAddend(ToAdd.Addend, Rel);
1648-
ToAdd.Type = Rel.getType(false);
1657+
ToAdd.Type = Rel.getType(Relocs->getObject().IsMips64EL);
16491658

1650-
if (uint32_t Sym = Rel.getSymbol(false)) {
1651-
if (!SymbolTable)
1659+
if (uint32_t Sym = Rel.getSymbol(Relocs->getObject().IsMips64EL)) {
1660+
if (!Relocs->getObject().SymbolTable)
16521661
return createStringError(
16531662
errc::invalid_argument,
16541663
"'" + Relocs->Name + "': relocation references symbol with index " +
16551664
Twine(Sym) + ", but there is no symbol table");
1656-
Expected<Symbol *> SymByIndex = SymbolTable->getSymbolByIndex(Sym);
1665+
Expected<Symbol *> SymByIndex =
1666+
Relocs->getObject().SymbolTable->getSymbolByIndex(Sym);
16571667
if (!SymByIndex)
16581668
return SymByIndex.takeError();
16591669

@@ -1698,7 +1708,7 @@ Expected<SectionBase &> ELFBuilder<ELFT>::makeSection(const Elf_Shdr &Shdr) {
16981708
else
16991709
return Data.takeError();
17001710
}
1701-
return Obj.addSection<RelocationSection>();
1711+
return Obj.addSection<RelocationSection>(Obj);
17021712
case SHT_STRTAB:
17031713
// If a string table is allocated we don't want to mess with it. That would
17041714
// mean altering the memory image. There are no special link types or
@@ -1879,15 +1889,15 @@ template <class ELFT> Error ELFBuilder<ELFT>::readSections(bool EnsureSymtab) {
18791889
if (!Rels)
18801890
return Rels.takeError();
18811891

1882-
if (Error Err = initRelocations(RelSec, Obj.SymbolTable, *Rels))
1892+
if (Error Err = initRelocations(RelSec, *Rels))
18831893
return Err;
18841894
} else {
18851895
Expected<typename ELFFile<ELFT>::Elf_Rela_Range> Relas =
18861896
ElfFile.relas(*Shdr);
18871897
if (!Relas)
18881898
return Relas.takeError();
18891899

1890-
if (Error Err = initRelocations(RelSec, Obj.SymbolTable, *Relas))
1900+
if (Error Err = initRelocations(RelSec, *Relas))
18911901
return Err;
18921902
}
18931903
} else if (auto GroupSec = dyn_cast<GroupSection>(&Sec)) {

llvm/tools/llvm-objcopy/ELF/Object.h

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -783,8 +783,10 @@ class RelocationSection
783783
MAKE_SEC_WRITER_FRIEND
784784

785785
std::vector<Relocation> Relocations;
786+
const Object &Obj;
786787

787788
public:
789+
RelocationSection(const Object &O) : Obj(O) {}
788790
void addRelocation(Relocation Rel) { Relocations.push_back(Rel); }
789791
Error accept(SectionVisitor &Visitor) const override;
790792
Error accept(MutableSectionVisitor &Visitor) override;
@@ -795,6 +797,7 @@ class RelocationSection
795797
void markSymbols() override;
796798
void replaceSectionReferences(
797799
const DenseMap<SectionBase *, SectionBase *> &FromTo) override;
800+
const Object &getObject() const { return Obj; }
798801

799802
static bool classof(const SectionBase *S) {
800803
if (S->OriginalFlags & ELF::SHF_ALLOC)
@@ -971,9 +974,7 @@ template <class ELFT> class ELFBuilder {
971974

972975
public:
973976
ELFBuilder(const ELFObjectFile<ELFT> &ElfObj, Object &Obj,
974-
Optional<StringRef> ExtractPartition)
975-
: ElfFile(ElfObj.getELFFile()), Obj(Obj),
976-
ExtractPartition(ExtractPartition) {}
977+
Optional<StringRef> ExtractPartition);
977978

978979
Error build(bool EnsureSymtab);
979980
};
@@ -1063,6 +1064,8 @@ class Object {
10631064
SymbolTableSection *SymbolTable = nullptr;
10641065
SectionIndexSection *SectionIndexTable = nullptr;
10651066

1067+
bool IsMips64EL = false;
1068+
10661069
SectionTableRef sections() const { return SectionTableRef(Sections); }
10671070
iterator_range<
10681071
filter_iterator<pointee_iterator<std::vector<SecPtr>::const_iterator>,

0 commit comments

Comments
 (0)