Skip to content

Commit d5d6d29

Browse files
simpal01jsji
authored andcommitted
Revert "Revert "[lld][Arm] Big Endian - Byte invariant support.""
This reverts commit d885138. Reason: Applied the fix for the Asan buildbot failures.
1 parent 32bb25b commit d5d6d29

File tree

2 files changed

+113
-0
lines changed

2 files changed

+113
-0
lines changed

lld/ELF/Arch/ARM.cpp

Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
//
77
//===----------------------------------------------------------------------===//
88

9+
#include "InputFiles.h"
910
#include "Symbols.h"
1011
#include "SyntheticSections.h"
1112
#include "Target.h"
@@ -942,6 +943,117 @@ int64_t ARM::getImplicitAddend(const uint8_t *buf, RelType type) const {
942943
}
943944
}
944945

946+
static bool isArmMapSymbol(const Symbol *b) {
947+
return b->getName() == "$a" || b->getName().startswith("$a.");
948+
}
949+
950+
static bool isThumbMapSymbol(const Symbol *s) {
951+
return s->getName() == "$t" || s->getName().startswith("$t.");
952+
}
953+
954+
static bool isDataMapSymbol(const Symbol *b) {
955+
return b->getName() == "$d" || b->getName().startswith("$d.");
956+
}
957+
958+
void elf::sortArmMappingSymbols() {
959+
// For each input section make sure the mapping symbols are sorted in
960+
// ascending order.
961+
for (auto &kv : sectionMap) {
962+
SmallVector<const Defined *, 0> &mapSyms = kv.second;
963+
llvm::stable_sort(mapSyms, [](const Defined *a, const Defined *b) {
964+
return a->value < b->value;
965+
});
966+
}
967+
}
968+
969+
void elf::addArmInputSectionMappingSymbols() {
970+
// Collect mapping symbols for every executable input sections.
971+
// The linker generated mapping symbols for all the synthetic
972+
// sections are adding into the sectionmap through the function
973+
// addArmSyntheitcSectionMappingSymbol.
974+
for (ELFFileBase *file : ctx.objectFiles) {
975+
for (Symbol *sym : file->getLocalSymbols()) {
976+
auto *def = dyn_cast<Defined>(sym);
977+
if (!def)
978+
continue;
979+
if (!isArmMapSymbol(def) && !isDataMapSymbol(def) &&
980+
!isThumbMapSymbol(def))
981+
continue;
982+
if (auto *sec = cast_if_present<InputSection>(def->section))
983+
if (sec->flags & SHF_EXECINSTR)
984+
sectionMap[sec].push_back(def);
985+
}
986+
}
987+
}
988+
989+
// Synthetic sections are not backed by an ELF file where we can access the
990+
// symbol table, instead mapping symbols added to synthetic sections are stored
991+
// in the synthetic symbol table. Due to the presence of strip (--strip-all),
992+
// we can not rely on the synthetic symbol table retaining the mapping symbols.
993+
// Instead we record the mapping symbols locally.
994+
void elf::addArmSyntheticSectionMappingSymbol(Defined *sym) {
995+
if (!isArmMapSymbol(sym) && !isDataMapSymbol(sym) && !isThumbMapSymbol(sym))
996+
return;
997+
if (auto *sec = cast_if_present<InputSection>(sym->section))
998+
if (sec->flags & SHF_EXECINSTR)
999+
sectionMap[sec].push_back(sym);
1000+
}
1001+
1002+
static void toLittleEndianInstructions(uint8_t *buf, uint64_t start,
1003+
uint64_t end, uint64_t width) {
1004+
CodeState curState = static_cast<CodeState>(width);
1005+
if (curState == CodeState::Arm)
1006+
for (uint64_t i = start; i < end; i += width)
1007+
write32le(buf + i, read32(buf + i));
1008+
1009+
if (curState == CodeState::Thumb)
1010+
for (uint64_t i = start; i < end; i += width)
1011+
write16le(buf + i, read16(buf + i));
1012+
}
1013+
1014+
// Arm BE8 big endian format requires instructions to be little endian, with
1015+
// the initial contents big-endian. Convert the big-endian instructions to
1016+
// little endian leaving literal data untouched. We use mapping symbols to
1017+
// identify half open intervals of Arm code [$a, non $a) and Thumb code
1018+
// [$t, non $t) and convert these to little endian a word or half word at a
1019+
// time respectively.
1020+
void elf::convertArmInstructionstoBE8(InputSection *sec, uint8_t *buf) {
1021+
if (!sectionMap.contains(sec))
1022+
return;
1023+
1024+
SmallVector<const Defined *, 0> &mapSyms = sectionMap[sec];
1025+
1026+
if (mapSyms.empty())
1027+
return;
1028+
1029+
CodeState curState = CodeState::Data;
1030+
uint64_t start = 0, width = 0, size = sec->getSize();
1031+
for (auto &msym : mapSyms) {
1032+
CodeState newState = CodeState::Data;
1033+
if (isThumbMapSymbol(msym))
1034+
newState = CodeState::Thumb;
1035+
else if (isArmMapSymbol(msym))
1036+
newState = CodeState::Arm;
1037+
1038+
if (newState == curState)
1039+
continue;
1040+
1041+
if (curState != CodeState::Data) {
1042+
width = static_cast<uint64_t>(curState);
1043+
toLittleEndianInstructions(buf, start, msym->value, width);
1044+
}
1045+
start = msym->value;
1046+
curState = newState;
1047+
}
1048+
1049+
// Passed last mapping symbol, may need to reverse
1050+
// up to end of section.
1051+
if (curState != CodeState::Data) {
1052+
width = static_cast<uint64_t>(curState);
1053+
toLittleEndianInstructions(buf, start, size, width);
1054+
}
1055+
}
1056+
9451057
TargetInfo *elf::getARMTargetInfo() {
9461058
static ARM target;
9471059
return &target;

lld/test/ELF/arm-plt-reloc.s

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -253,6 +253,7 @@ _start:
253253
// CHECKLONG-EB-NEXT: ldr lr, [pc, #4]
254254
// CHECKLONG-EB-NEXT: add lr, pc, lr
255255
// CHECKLONG-EB-NEXT: ldr pc, [lr, #8]!
256+
// CHECKLONG-EB: <$d>:
256257
// CHECKLONG-EB-NEXT: 11 10 f0 f0 .word 0x1110f0f0
257258
// CHECKLONG-EB-NEXT: d4 d4 d4 d4 .word 0xd4d4d4d4
258259
// CHECKLONG-EB-NEXT: d4 d4 d4 d4 .word 0xd4d4d4d4

0 commit comments

Comments
 (0)