2121#include " llvm/Object/ELFTypes.h"
2222#include " llvm/Support/ErrorHandling.h"
2323#include " llvm/Support/raw_ostream.h"
24+ #include " llvm/Support/xxhash.h"
2425
2526#define DEBUG_TYPE " lld-nanomips"
2627using namespace lld ;
@@ -362,19 +363,16 @@ void NanoMipsTransform::changeBytes(InputSection *isec, uint64_t location,
362363 }
363364}
364365
365- void NanoMipsTransform::updateSectionContent (InputSection *isec,
366- uint64_t location, int32_t delta,
367- bool align) {
368-
366+ bool NanoMipsTransform::updateSectionContentInner (InputSection *isec,
367+ uint64_t location,
368+ int32_t delta, bool align) {
369369 // Other than increasing/decreasing byte size of isec, it also
370370 // allocates new section content if delta is 0 and section
371371 // hasn't yet been changed, as those content would be readonly
372- changeBytes (isec, location, delta);
372+ NanoMipsTransform:: changeBytes (isec, location, delta);
373373 if (delta == 0 )
374- return ;
374+ return false ;
375375
376- this ->changed = true ;
377- this ->changedThisIteration = true ;
378376 LLVM_DEBUG (llvm::dbgs () << " Changed size of input section "
379377 << (isec->file ? isec->file ->getName () : " nofile" )
380378 << " (" << isec->name << " ) by " << delta
@@ -395,7 +393,7 @@ void NanoMipsTransform::updateSectionContent(InputSection *isec,
395393 // TODO: Check whether sections without a corresponding file
396394 // may have symbols that should be changed during transformations
397395 if (!isec->file )
398- return ;
396+ return true ;
399397
400398 for (auto &symAnchor : isec->nanoMipsRelaxAux ->anchors ) {
401399 Defined *dSym = symAnchor.d ;
@@ -413,6 +411,19 @@ void NanoMipsTransform::updateSectionContent(InputSection *isec,
413411 }
414412 }
415413 }
414+
415+ return true ;
416+ }
417+
418+ void NanoMipsTransform::updateSectionContent (InputSection *isec,
419+ uint64_t location, int32_t delta,
420+ bool align) {
421+ bool changed = NanoMipsTransform::updateSectionContentInner (isec, location,
422+ delta, align);
423+ if (changed) {
424+ this ->changed = true ;
425+ this ->changedThisIteration = true ;
426+ }
416427}
417428
418429SmallVector<NewInsnToWrite, 3 > NanoMipsTransform::getTransformInsns (
@@ -1140,6 +1151,37 @@ void NanoMipsTransformController<ELFT>::changeState(int pass) {
11401151 LLVM_DEBUG (llvm::dbgs () << " Changed transform state to None\n " ;);
11411152}
11421153
1154+ template <class ELFT >
1155+ void NanoMipsTransformController<ELFT>::scatterNops() const {
1156+ if (!this ->mayRelax ())
1157+ return ;
1158+
1159+ NanoMipsTransformController<ELFT>::initTransformAuxInfo ();
1160+
1161+ for (OutputSection *osec : outputSections) {
1162+ if (!isOutputSecTransformable (osec))
1163+ continue ;
1164+
1165+ SmallVector<InputSection *, 0 > storage;
1166+ for (InputSection *sec : getInputSections (*osec, storage)) {
1167+ if (!NanoMipsTransformController<ELFT>::safeToModify (sec) ||
1168+ !sec->relocs ().size () || !(sec->flags & SHF_EXECINSTR))
1169+ continue ;
1170+
1171+ uint64_t hash = llvm::xxHash64 (sec->name ) + config->scatterNopsSeed ;
1172+ if ((hash % 100 ) >= config->scatterNopsDensity )
1173+ continue ;
1174+
1175+ const uint32_t nop16 = 0x9008 ;
1176+ const uint32_t nop16Size = 2 ;
1177+ NanoMipsTransform::updateSectionContentInner (sec, 0 , 2 , false );
1178+ writeInsn<ELFT::TargetEndianness>(nop16, sec->content (), 0 , nop16Size);
1179+ LLVM_DEBUG (llvm::dbgs () << sec->name
1180+ << " updated with a nop in the beginning!\n " ;);
1181+ }
1182+ }
1183+ }
1184+
11431185// relaxOnce is used for both relaxations and expansions
11441186template <class ELFT >
11451187bool NanoMipsTransformController<ELFT>::relaxOnce(int pass) const {
@@ -1148,18 +1190,18 @@ bool NanoMipsTransformController<ELFT>::relaxOnce(int pass) const {
11481190 LLVM_DEBUG (llvm::dbgs () << " Transformation Pass num: " << pass << " \n " ;);
11491191 bool shouldRunAgain = false ;
11501192 if (this ->mayRelax ()) {
1151- if (pass == 0 ) {
1193+ if (pass == 0 && config-> scatterNopsDensity == 0 ) {
11521194 // Initialization of additional info that are needed for
11531195 // relaxations/expansions
1154- initTransformAuxInfo ();
1196+ NanoMipsTransformController<ELFT>:: initTransformAuxInfo ();
11551197 }
11561198 for (OutputSection *osec : outputSections) {
11571199 if (!isOutputSecTransformable (osec))
11581200 continue ;
11591201
11601202 SmallVector<InputSection *, 0 > storage;
11611203 for (InputSection *sec : getInputSections (*osec, storage)) {
1162- if (!this -> safeToModify (sec))
1204+ if (!NanoMipsTransformController<ELFT>:: safeToModify (sec))
11631205 continue ;
11641206 if (sec->relocs ().size ())
11651207 this ->scanAndTransform (sec);
@@ -1175,8 +1217,8 @@ bool NanoMipsTransformController<ELFT>::relaxOnce(int pass) const {
11751217}
11761218
11771219template <class ELFT >
1178- inline bool lld::elf::NanoMipsTransformController<ELFT>::safeToModify(
1179- InputSection *sec) const {
1220+ inline bool
1221+ lld::elf::NanoMipsTransformController<ELFT>::safeToModify( InputSection *sec) {
11801222 bool modifiable = false ;
11811223 if (auto *obj = sec->getFile <ELF32LE>()) {
11821224 modifiable =
@@ -1186,14 +1228,15 @@ inline bool lld::elf::NanoMipsTransformController<ELFT>::safeToModify(
11861228}
11871229
11881230template <class ELFT >
1189- void NanoMipsTransformController<ELFT>::initTransformAuxInfo() const {
1231+ void NanoMipsTransformController<ELFT>::initTransformAuxInfo() {
11901232 SmallVector<InputSection *, 0 > storage;
11911233 for (OutputSection *osec : outputSections) {
11921234 if (!isOutputSecTransformable (osec))
11931235 continue ;
11941236
11951237 for (InputSection *sec : getInputSections (*osec, storage)) {
1196- if (!this ->safeToModify (sec) || sec->relocs ().size () == 0 )
1238+ if (!NanoMipsTransformController<ELFT>::safeToModify (sec) ||
1239+ sec->relocs ().size () == 0 )
11971240 continue ;
11981241 sec->nanoMipsRelaxAux = make<NanoMipsRelaxAux>();
11991242 sec->nanoMipsRelaxAux ->isAlreadyTransformed = false ;
0 commit comments