Skip to content

Commit 7059b6d

Browse files
committed
[LLD][Xtensa] Improve literal sections placement.
Improve sections sort to place literal section closer to code section which uses literals. Fix l32r relocation check.
1 parent c52fc3c commit 7059b6d

File tree

2 files changed

+60
-5
lines changed

2 files changed

+60
-5
lines changed

lld/ELF/Arch/Xtensa.cpp

+6-4
Original file line numberDiff line numberDiff line change
@@ -127,10 +127,12 @@ void Xtensa::relocate(uint8_t *loc, const Relocation &rel, uint64_t val) const {
127127
// Look at the instruction to determine how to do the relocation.
128128
uint8_t opcode = loc[0] & 0x0f;
129129
if (opcode == 0b0001) { // RI16 format: l32r
130-
uint64_t val = dest - ((p + 3) & (uint64_t)0xfffffffc);
131-
checkInt(loc, static_cast<int64_t>(val) >> 2, 16, rel);
132-
checkAlignment(loc, val, 4, rel);
133-
write16le(loc + 1, static_cast<int64_t>(val) >> 2);
130+
int64_t val = dest - ((p + 3) & (uint64_t)0xfffffffc);
131+
if ((val < -262144 || val > -4))
132+
reportRangeError(loc, rel, Twine(static_cast<int64_t>(val)), -262141,
133+
-4);
134+
checkAlignment(loc, static_cast<uint64_t>(val), 4, rel);
135+
write16le(loc + 1, val >> 2);
134136
} else if (opcode == 0b0101) { // call0, call4, call8, call12 (CALL format)
135137
uint64_t val = dest - ((p + 4) & (uint64_t)0xfffffffc);
136138
checkInt(loc, static_cast<int64_t>(val) >> 2, 18, rel);

lld/ELF/Writer.cpp

+54-1
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
#include "llvm/Support/TimeProfiler.h"
3232
#include "llvm/Support/xxhash.h"
3333
#include <climits>
34+
#include <map>
3435

3536
#define DEBUG_TYPE "lld"
3637

@@ -1368,6 +1369,58 @@ sortISDBySectionOrder(InputSectionDescription *isd,
13681369
isd->sections.push_back(isec);
13691370
}
13701371

1372+
// Sort Xtensa literal sections in OutputSection. For each literal section we try
1373+
// to find by name text(code) section, which uses these literals. The literal
1374+
// section should always be placed before code section.
1375+
// Also we try to place literal section just before code section.
1376+
static void sortSectionXtensa(OutputSection &osec) {
1377+
for (SectionCommand *b : osec.commands) {
1378+
if (auto *isd = dyn_cast<InputSectionDescription>(b)) {
1379+
std::map<std::string, int> orderedNames;
1380+
SmallVector<std::pair<InputSection *, int>, 0> orderedSections;
1381+
int sidx = 0;
1382+
1383+
for (InputSection *isec : isd->sections) {
1384+
if (orderedNames.count(isec->name.str())) {
1385+
orderedSections.push_back({isec, orderedNames[isec->name.str()]});
1386+
continue;
1387+
}
1388+
//Check if current section contains literals
1389+
if (isec->name.contains(".literal")) {
1390+
std::string literalName = isec->name.str();
1391+
std::size_t pos = literalName.find(".literal");
1392+
std::string textName;
1393+
// Reconstructing text(code) section name by literal section name
1394+
if (pos == 0) {
1395+
textName = ".text";
1396+
} else {
1397+
textName = literalName.substr(0, pos);
1398+
}
1399+
textName += literalName.substr(pos + 8, std::string::npos);
1400+
if (orderedNames.count(textName)) {
1401+
int textIdx = orderedNames[textName];
1402+
int literalIdx = textIdx - 1;
1403+
orderedSections.push_back({isec, literalIdx});
1404+
orderedNames[isec->name.str()] = literalIdx;
1405+
} else {
1406+
orderedSections.push_back({isec, sidx});
1407+
orderedNames[isec->name.str()] = sidx;
1408+
}
1409+
} else {
1410+
orderedSections.push_back({isec, sidx});
1411+
orderedNames[isec->name.str()] = sidx;
1412+
}
1413+
sidx += 2;
1414+
}
1415+
1416+
llvm::sort(orderedSections, llvm::less_second());
1417+
isd->sections.clear();
1418+
for (std::pair<InputSection *, int> p : orderedSections)
1419+
isd->sections.push_back(p.first);
1420+
}
1421+
}
1422+
}
1423+
13711424
static void sortSection(OutputSection &osec,
13721425
const DenseMap<const InputSectionBase *, int> &order) {
13731426
StringRef name = osec.name;
@@ -1394,7 +1447,7 @@ static void sortSection(OutputSection &osec,
13941447
sortISDBySectionOrder(isd, order, osec.flags & SHF_EXECINSTR);
13951448

13961449
if (config->emachine == EM_XTENSA) {
1397-
osec.sort([](InputSectionBase *s) { return s->name.contains(".literal") ? 0 : 1; });
1450+
sortSectionXtensa(osec);
13981451
}
13991452

14001453
if (script->hasSectionsCommand)

0 commit comments

Comments
 (0)