[llvm] r227044 - [ELFYAML] Support mips64 relocation record format in yaml2obj/obj2yaml
Simon Atanasyan
simon at atanasyan.com
Sun Jan 25 05:29:25 PST 2015
Author: atanasyan
Date: Sun Jan 25 07:29:25 2015
New Revision: 227044
URL: http://llvm.org/viewvc/llvm-project?rev=227044&view=rev
Log:
[ELFYAML] Support mips64 relocation record format in yaml2obj/obj2yaml
MIPS64 ELF file has a very specific relocation record format. Each
record might specify up to three relocation operations. So the `r_info`
field in fact consists of three relocation type sub-fields and optional
code of "special" symbols.
http://techpubs.sgi.com/library/manuals/4000/007-4658-001/pdf/007-4658-001.pdf
page 40
The patch implements support of the MIPS64 relocation record format in
yaml2obj/obj2yaml tools by introducing new optional Relocation fields:
Type2, Type3, and SpecSym. These fields are recognized only if the
object/YAML file relates to the MIPS64 target.
Differential Revision: http://reviews.llvm.org/D7136
Added:
llvm/trunk/test/Object/Mips/elf-mips64-rel.yaml
Modified:
llvm/trunk/include/llvm/Object/ELFTypes.h
llvm/trunk/include/llvm/Object/ELFYAML.h
llvm/trunk/include/llvm/Support/ELF.h
llvm/trunk/lib/Object/ELFYAML.cpp
llvm/trunk/tools/yaml2obj/yaml2elf.cpp
Modified: llvm/trunk/include/llvm/Object/ELFTypes.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Object/ELFTypes.h?rev=227044&r1=227043&r2=227044&view=diff
==============================================================================
--- llvm/trunk/include/llvm/Object/ELFTypes.h (original)
+++ llvm/trunk/include/llvm/Object/ELFTypes.h Sun Jan 25 07:29:25 2015
@@ -302,7 +302,10 @@ struct Elf_Rel_Base<ELFType<TargetEndian
assert(!isMips64EL);
return r_info;
}
- void setRInfo(uint32_t R) { r_info = R; }
+ void setRInfo(uint32_t R, bool IsMips64EL) {
+ assert(!IsMips64EL);
+ r_info = R;
+ }
};
template <endianness TargetEndianness, std::size_t MaxAlign>
@@ -321,9 +324,12 @@ struct Elf_Rel_Base<ELFType<TargetEndian
return (t << 32) | ((t >> 8) & 0xff000000) | ((t >> 24) & 0x00ff0000) |
((t >> 40) & 0x0000ff00) | ((t >> 56) & 0x000000ff);
}
- void setRInfo(uint64_t R) {
- // FIXME: Add mips64el support.
- r_info = R;
+ void setRInfo(uint64_t R, bool IsMips64EL) {
+ if (IsMips64EL)
+ r_info = (R >> 32) | ((R & 0xff000000) << 8) | ((R & 0x00ff0000) << 24) |
+ ((R & 0x0000ff00) << 40) | ((R & 0x000000ff) << 56);
+ else
+ r_info = R;
}
};
@@ -338,7 +344,10 @@ struct Elf_Rel_Base<ELFType<TargetEndian
assert(!isMips64EL);
return r_info;
}
- void setRInfo(uint32_t R) { r_info = R; }
+ void setRInfo(uint32_t R, bool IsMips64EL) {
+ assert(!IsMips64EL);
+ r_info = R;
+ }
};
template <endianness TargetEndianness, std::size_t MaxAlign>
@@ -358,9 +367,12 @@ struct Elf_Rel_Base<ELFType<TargetEndian
return (t << 32) | ((t >> 8) & 0xff000000) | ((t >> 24) & 0x00ff0000) |
((t >> 40) & 0x0000ff00) | ((t >> 56) & 0x000000ff);
}
- void setRInfo(uint64_t R) {
- // FIXME: Add mips64el support.
- r_info = R;
+ void setRInfo(uint64_t R, bool IsMips64EL) {
+ if (IsMips64EL)
+ r_info = (R >> 32) | ((R & 0xff000000) << 8) | ((R & 0x00ff0000) << 24) |
+ ((R & 0x0000ff00) << 40) | ((R & 0x000000ff) << 56);
+ else
+ r_info = R;
}
};
@@ -380,10 +392,14 @@ struct Elf_Rel_Impl<ELFType<TargetEndian
uint32_t getType(bool isMips64EL) const {
return (uint32_t)(this->getRInfo(isMips64EL) & 0xffffffffL);
}
- void setSymbol(uint32_t s) { setSymbolAndType(s, getType()); }
- void setType(uint32_t t) { setSymbolAndType(getSymbol(), t); }
- void setSymbolAndType(uint32_t s, uint32_t t) {
- this->setRInfo(((uint64_t)s << 32) + (t & 0xffffffffL));
+ void setSymbol(uint32_t s, bool IsMips64EL) {
+ setSymbolAndType(s, getType(), IsMips64EL);
+ }
+ void setType(uint32_t t, bool IsMips64EL) {
+ setSymbolAndType(getSymbol(), t, IsMips64EL);
+ }
+ void setSymbolAndType(uint32_t s, uint32_t t, bool IsMips64EL) {
+ this->setRInfo(((uint64_t)s << 32) + (t & 0xffffffffL), IsMips64EL);
}
};
@@ -401,10 +417,14 @@ struct Elf_Rel_Impl<ELFType<TargetEndian
unsigned char getType(bool isMips64EL) const {
return (unsigned char)(this->getRInfo(isMips64EL) & 0x0ff);
}
- void setSymbol(uint32_t s) { setSymbolAndType(s, getType()); }
- void setType(unsigned char t) { setSymbolAndType(getSymbol(), t); }
- void setSymbolAndType(uint32_t s, unsigned char t) {
- this->setRInfo((s << 8) + t);
+ void setSymbol(uint32_t s, bool IsMips64EL) {
+ setSymbolAndType(s, getType(), IsMips64EL);
+ }
+ void setType(unsigned char t, bool IsMips64EL) {
+ setSymbolAndType(getSymbol(), t, IsMips64EL);
+ }
+ void setSymbolAndType(uint32_t s, unsigned char t, bool IsMips64EL) {
+ this->setRInfo((s << 8) + t, IsMips64EL);
}
};
Modified: llvm/trunk/include/llvm/Object/ELFYAML.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Object/ELFYAML.h?rev=227044&r1=227043&r2=227044&view=diff
==============================================================================
--- llvm/trunk/include/llvm/Object/ELFYAML.h (original)
+++ llvm/trunk/include/llvm/Object/ELFYAML.h Sun Jan 25 07:29:25 2015
@@ -41,6 +41,7 @@ LLVM_YAML_STRONG_TYPEDEF(uint8_t, ELF_EL
LLVM_YAML_STRONG_TYPEDEF(uint64_t, ELF_EF)
LLVM_YAML_STRONG_TYPEDEF(uint32_t, ELF_SHT)
LLVM_YAML_STRONG_TYPEDEF(uint32_t, ELF_REL)
+LLVM_YAML_STRONG_TYPEDEF(uint8_t, ELF_RSS)
// Just use 64, since it can hold 32-bit values too.
LLVM_YAML_STRONG_TYPEDEF(uint64_t, ELF_SHF)
LLVM_YAML_STRONG_TYPEDEF(uint8_t, ELF_STT)
@@ -186,6 +187,11 @@ struct ScalarEnumerationTraits<ELFYAML::
};
template <>
+struct ScalarEnumerationTraits<ELFYAML::ELF_RSS> {
+ static void enumeration(IO &IO, ELFYAML::ELF_RSS &Value);
+};
+
+template <>
struct MappingTraits<ELFYAML::FileHeader> {
static void mapping(IO &IO, ELFYAML::FileHeader &FileHdr);
};
Modified: llvm/trunk/include/llvm/Support/ELF.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Support/ELF.h?rev=227044&r1=227043&r2=227044&view=diff
==============================================================================
--- llvm/trunk/include/llvm/Support/ELF.h (original)
+++ llvm/trunk/include/llvm/Support/ELF.h Sun Jan 25 07:29:25 2015
@@ -796,6 +796,14 @@ enum {
STN_UNDEF = 0
};
+// Special relocation symbols used in the MIPS64 ELF relocation entries
+enum {
+ RSS_UNDEF = 0, // None
+ RSS_GP = 1, // Value of gp
+ RSS_GP0 = 2, // Value of gp used to create object being relocated
+ RSS_LOC = 3 // Address of location being relocated
+};
+
// Relocation entry, without explicit addend.
struct Elf32_Rel {
Elf32_Addr r_offset; // Location (file byte offset, or program virtual addr)
Modified: llvm/trunk/lib/Object/ELFYAML.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Object/ELFYAML.cpp?rev=227044&r1=227043&r2=227044&view=diff
==============================================================================
--- llvm/trunk/lib/Object/ELFYAML.cpp (original)
+++ llvm/trunk/lib/Object/ELFYAML.cpp Sun Jan 25 07:29:25 2015
@@ -415,6 +415,16 @@ void ScalarBitSetTraits<ELFYAML::ELF_STO
#undef BCaseMask
}
+void ScalarEnumerationTraits<ELFYAML::ELF_RSS>::enumeration(
+ IO &IO, ELFYAML::ELF_RSS &Value) {
+#define ECase(X) IO.enumCase(Value, #X, ELF::X);
+ ECase(RSS_UNDEF)
+ ECase(RSS_GP)
+ ECase(RSS_GP0)
+ ECase(RSS_LOC)
+#undef ECase
+}
+
void ScalarEnumerationTraits<ELFYAML::ELF_REL>::enumeration(
IO &IO, ELFYAML::ELF_REL &Value) {
const auto *Object = static_cast<ELFYAML::Object *>(IO.getContext());
@@ -540,11 +550,48 @@ StringRef MappingTraits<std::unique_ptr<
return "Section size must be greater or equal to the content size";
}
+namespace {
+struct NormalizedMips64RelType {
+ NormalizedMips64RelType(IO &)
+ : Type(ELFYAML::ELF_REL(ELF::R_MIPS_NONE)),
+ Type2(ELFYAML::ELF_REL(ELF::R_MIPS_NONE)),
+ Type3(ELFYAML::ELF_REL(ELF::R_MIPS_NONE)),
+ SpecSym(ELFYAML::ELF_REL(ELF::RSS_UNDEF)) {}
+ NormalizedMips64RelType(IO &, ELFYAML::ELF_REL Original)
+ : Type(Original & 0xFF), Type2(Original >> 8 & 0xFF),
+ Type3(Original >> 16 & 0xFF), SpecSym(Original >> 24 & 0xFF) {}
+
+ ELFYAML::ELF_REL denormalize(IO &) {
+ ELFYAML::ELF_REL Res = Type | Type2 << 8 | Type3 << 16 | SpecSym << 24;
+ return Res;
+ }
+
+ ELFYAML::ELF_REL Type;
+ ELFYAML::ELF_REL Type2;
+ ELFYAML::ELF_REL Type3;
+ ELFYAML::ELF_RSS SpecSym;
+};
+}
+
void MappingTraits<ELFYAML::Relocation>::mapping(IO &IO,
ELFYAML::Relocation &Rel) {
+ const auto *Object = static_cast<ELFYAML::Object *>(IO.getContext());
+ assert(Object && "The IO context is not initialized");
+
IO.mapRequired("Offset", Rel.Offset);
IO.mapRequired("Symbol", Rel.Symbol);
- IO.mapRequired("Type", Rel.Type);
+
+ if (Object->Header.Machine == ELFYAML::ELF_EM(ELF::EM_MIPS) &&
+ Object->Header.Class == ELFYAML::ELF_ELFCLASS(ELF::ELFCLASS64)) {
+ MappingNormalization<NormalizedMips64RelType, ELFYAML::ELF_REL> Key(
+ IO, Rel.Type);
+ IO.mapRequired("Type", Key->Type);
+ IO.mapOptional("Type2", Key->Type2, ELFYAML::ELF_REL(ELF::R_MIPS_NONE));
+ IO.mapOptional("Type3", Key->Type3, ELFYAML::ELF_REL(ELF::R_MIPS_NONE));
+ IO.mapOptional("SpecSym", Key->SpecSym, ELFYAML::ELF_RSS(ELF::RSS_UNDEF));
+ } else
+ IO.mapRequired("Type", Rel.Type);
+
IO.mapOptional("Addend", Rel.Addend);
}
Added: llvm/trunk/test/Object/Mips/elf-mips64-rel.yaml
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Object/Mips/elf-mips64-rel.yaml?rev=227044&view=auto
==============================================================================
--- llvm/trunk/test/Object/Mips/elf-mips64-rel.yaml (added)
+++ llvm/trunk/test/Object/Mips/elf-mips64-rel.yaml Sun Jan 25 07:29:25 2015
@@ -0,0 +1,113 @@
+# RUN: yaml2obj -format=elf %s > %t
+# RUN: llvm-readobj -r %t | FileCheck -check-prefix=OBJ %s
+# RUN: obj2yaml %t | FileCheck -check-prefix=YAML %s
+
+# OBJ: Relocations [
+# OBJ-NEXT: Section (2) .rela.text {
+# OBJ-NEXT: 0x14 R_MIPS_GPREL16/R_MIPS_SUB/R_MIPS_HI16 main 0x4
+# OBJ-NEXT: 0x1C R_MIPS_GPREL16/R_MIPS_SUB/R_MIPS_LO16 main 0x8
+# OBJ-NEXT: 0x20 R_MIPS_GOT_PAGE/R_MIPS_NONE/R_MIPS_NONE .rodata 0x0
+# OBJ-NEXT: 0x24 R_MIPS_GOT_OFST/R_MIPS_NONE/R_MIPS_NONE .rodata 0x0
+# OBJ-NEXT: 0x28 R_MIPS_CALL16/R_MIPS_NONE/R_MIPS_NONE printf 0x0
+# OBJ-NEXT: 0x30 R_MIPS_GPREL16/R_MIPS_LO16/R_MIPS_NONE printf 0x0
+# OBJ-NEXT: }
+# OBJ-NEXT: ]
+
+# YAML: Relocations:
+# YAML-NEXT: - Offset: 0x0000000000000014
+# YAML-NEXT: Symbol: main
+# YAML-NEXT: Type: R_MIPS_GPREL16
+# YAML-NEXT: Type2: R_MIPS_SUB
+# YAML-NEXT: Type3: R_MIPS_HI16
+# YAML-NEXT: Addend: 4
+# YAML-NEXT: - Offset: 0x000000000000001C
+# YAML-NEXT: Symbol: main
+# YAML-NEXT: Type: R_MIPS_GPREL16
+# YAML-NEXT: Type2: R_MIPS_SUB
+# YAML-NEXT: Type3: R_MIPS_LO16
+# YAML-NEXT: Addend: 8
+# YAML-NEXT: - Offset: 0x0000000000000020
+# YAML-NEXT: Symbol: .rodata
+# YAML-NEXT: Type: R_MIPS_GOT_PAGE
+# YAML-NEXT: Addend: 0
+# YAML-NEXT: - Offset: 0x0000000000000024
+# YAML-NEXT: Symbol: .rodata
+# YAML-NEXT: Type: R_MIPS_GOT_OFST
+# YAML-NEXT: Addend: 0
+# YAML-NEXT: - Offset: 0x0000000000000028
+# YAML-NEXT: Symbol: printf
+# YAML-NEXT: Type: R_MIPS_CALL16
+# YAML-NEXT: Addend: 0
+# YAML-NEXT: - Offset: 0x0000000000000030
+# YAML-NEXT: Symbol: printf
+# YAML-NEXT: Type: R_MIPS_GPREL16
+# YAML-NEXT: Type2: R_MIPS_LO16
+# YAML-NEXT: SpecSym: RSS_GP0
+# YAML-NEXT: Addend: 0
+
+---
+FileHeader:
+ Class: ELFCLASS64
+ Data: ELFDATA2LSB
+ Type: ET_REL
+ Machine: EM_MIPS
+ Flags: [ EF_MIPS_PIC, EF_MIPS_CPIC,
+ EF_MIPS_NOREORDER, EF_MIPS_ARCH_64R2 ]
+Sections:
+ - Name: .text
+ Type: SHT_PROGBITS
+ Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
+ AddressAlign: 0x10
+ Size: 0x60
+ - Name: .rela.text
+ Type: SHT_RELA
+ Flags: [ SHF_INFO_LINK ]
+ Info: .text
+ Relocations:
+ - Offset: 0x14
+ Symbol: main
+ Type: R_MIPS_GPREL16
+ Type2: R_MIPS_SUB
+ Type3: R_MIPS_HI16
+ Addend: 4
+ - Offset: 0x1C
+ Symbol: main
+ Type: R_MIPS_GPREL16
+ Type2: R_MIPS_SUB
+ Type3: R_MIPS_LO16
+ Addend: 8
+ - Offset: 0x20
+ Symbol: .rodata
+ Type: R_MIPS_GOT_PAGE
+ - Offset: 0x24
+ Symbol: .rodata
+ Type: R_MIPS_GOT_OFST
+ - Offset: 0x28
+ Symbol: printf
+ Type: R_MIPS_CALL16
+ - Offset: 0x30
+ Symbol: printf
+ Type: R_MIPS_GPREL16
+ Type2: R_MIPS_LO16
+ SpecSym: RSS_GP0
+ - Name: .rodata
+ Type: SHT_PROGBITS
+ Flags: [ SHF_ALLOC ]
+ AddressAlign: 0x10
+ Size: 0x0F
+
+Symbols:
+ Local:
+ - Name: .text
+ Type: STT_SECTION
+ Section: .text
+ - Name: .rodata
+ Type: STT_SECTION
+ Section: .rodata
+ Global:
+ - Name: main
+ Type: STT_FUNC
+ Section: .text
+ Size: 0x58
+ - Name: printf
+...
Modified: llvm/trunk/tools/yaml2obj/yaml2elf.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/yaml2obj/yaml2elf.cpp?rev=227044&r1=227043&r2=227044&view=diff
==============================================================================
--- llvm/trunk/tools/yaml2obj/yaml2elf.cpp (original)
+++ llvm/trunk/tools/yaml2obj/yaml2elf.cpp Sun Jan 25 07:29:25 2015
@@ -321,6 +321,12 @@ ELFState<ELFT>::writeSectionContent(Elf_
SHeader.sh_size = Section.Size;
}
+static bool isMips64EL(const ELFYAML::Object &Doc) {
+ return Doc.Header.Machine == ELFYAML::ELF_EM(llvm::ELF::EM_MIPS) &&
+ Doc.Header.Class == ELFYAML::ELF_ELFCLASS(ELF::ELFCLASS64) &&
+ Doc.Header.Data == ELFYAML::ELF_ELFDATA(ELF::ELFDATA2LSB);
+}
+
template <class ELFT>
bool
ELFState<ELFT>::writeSectionContent(Elf_Shdr &SHeader,
@@ -351,13 +357,13 @@ ELFState<ELFT>::writeSectionContent(Elf_
zero(REntry);
REntry.r_offset = Rel.Offset;
REntry.r_addend = Rel.Addend;
- REntry.setSymbolAndType(SymIdx, Rel.Type);
+ REntry.setSymbolAndType(SymIdx, Rel.Type, isMips64EL(Doc));
OS.write((const char *)&REntry, sizeof(REntry));
} else {
Elf_Rel REntry;
zero(REntry);
REntry.r_offset = Rel.Offset;
- REntry.setSymbolAndType(SymIdx, Rel.Type);
+ REntry.setSymbolAndType(SymIdx, Rel.Type, isMips64EL(Doc));
OS.write((const char *)&REntry, sizeof(REntry));
}
}
More information about the llvm-commits
mailing list