|
6 | 6 | //
|
7 | 7 | //===----------------------------------------------------------------------===//
|
8 | 8 |
|
| 9 | +#include "InputFiles.h" |
9 | 10 | #include "Symbols.h"
|
10 | 11 | #include "SyntheticSections.h"
|
11 | 12 | #include "Target.h"
|
@@ -942,6 +943,117 @@ int64_t ARM::getImplicitAddend(const uint8_t *buf, RelType type) const {
|
942 | 943 | }
|
943 | 944 | }
|
944 | 945 |
|
| 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 | + |
945 | 1057 | TargetInfo *elf::getARMTargetInfo() {
|
946 | 1058 | static ARM target;
|
947 | 1059 | return ⌖
|
|
0 commit comments