Skip to content

Commit 91d1168

Browse files
committed
Fix SUBALIGN linker script feature
This commit fixes the SUBALIGN linker script feature. SUBALIGN feature is used to modify the alignment of all input sections present in an output section. Until now, we were only changing the alignment of the first fragment of each rule of the output sections with SUBALIGN specified. This commit fixes the SUBALIGN behavior. SUBALIGN affects the alignment of the first fragment as is seen by the linker when traversing the output sections for the input sections that may contain more than 1 fragment such as .eh_frame, PLT / GOT sections, and .comment section. Resolves #343 Signed-off-by: Parth Arora <partaror@qti.qualcomm.com>
1 parent 4ffc848 commit 91d1168

16 files changed

Lines changed: 249 additions & 24 deletions

File tree

include/eld/Diagnostics/DiagLDScript.inc

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,8 @@ DIAG(error_cannot_specify_lma_and_memory_region, DiagnosticEngine::Error,
122122
"cannot specify AT and LMA memory region for output section : %0 defined in script %1")
123123
DIAG(warn_non_power_of_2_value_to_align_builtin, DiagnosticEngine::Warning,
124124
"%0: non-power-of-2 value 0x%1 passed to ALIGN builtin function")
125+
DIAG(warn_subalign_less_than_section_alignment, DiagnosticEngine::Warning,
126+
"SUBALIGN(0x%0) is less than the section alignment (0x%1) for section '%2'")
125127
DIAG(error_non_power_of_2_value_to_align_output_section, DiagnosticEngine::Error,
126128
"%0: non-power-of-2 value 0x%1 passed to ALIGN in '%2' output section description, value must "
127129
"be 0 or a power of 2")

include/eld/Object/ObjectLinker.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -312,6 +312,8 @@ class ObjectLinker {
312312

313313
bool initializeOutputSectionsAndRunPlugin();
314314

315+
void applySubAlign();
316+
315317
// Get Plugin list for Relocation registration callback.
316318
LinkerScript::PluginVectorT getLinkerPluginWithLinkerConfigs();
317319

lib/LayoutMap/TextLayoutPrinter.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,10 @@ void TextLayoutPrinter::printOnlyLayoutSection(GNULDBackend const &Backend,
108108
outputStream().write_hex(Section->size());
109109
outputStream() << "\t# Alignment: 0x";
110110
outputStream().write_hex(Section->getAddrAlign());
111+
if (OS->prolog().hasSubAlign()) {
112+
outputStream() << ", SubAlign: 0x";
113+
outputStream().write_hex(OS->prolog().subAlign().resultOrZero());
114+
}
111115
if (Section->isAlloc())
112116
printSegments(Backend, OS);
113117
outputStream() << "\n";
@@ -277,6 +281,12 @@ void TextLayoutPrinter::printSection(GNULDBackend const &Backend,
277281
outputStream() << ", Alignment: 0x";
278282
outputStream().write_hex(Section->getAddrAlign());
279283

284+
// Print SubAlign if present
285+
if (OS->prolog().hasSubAlign()) {
286+
outputStream() << ", SubAlign: 0x";
287+
outputStream().write_hex(OS->prolog().subAlign().resultOrZero());
288+
}
289+
280290
// Print flags
281291
outputStream() << ", Flags: "
282292
<< ELFSection::getELFPermissionsStr(Section->getFlags());

lib/Object/ObjectLinker.cpp

Lines changed: 41 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@
6161
#include "eld/SymbolResolver/ResolveInfo.h"
6262
#include "eld/Target/ELFFileFormat.h"
6363
#include "eld/Target/GNULDBackend.h"
64+
#include "eld/Target/LDFileFormat.h"
6465
#include "eld/Target/Relocator.h"
6566
#include "llvm/ADT/ScopeExit.h"
6667
#include "llvm/ADT/StringSwitch.h"
@@ -81,6 +82,7 @@
8182
#include <chrono>
8283
#include <mutex>
8384
#include <sstream>
85+
#include <unordered_set>
8486

8587
using namespace llvm;
8688
using namespace eld;
@@ -970,7 +972,7 @@ bool ObjectLinker::sortSections(RuleContainer *I, bool SortRule) {
970972
bool ObjectLinker::createOutputSection(ObjectBuilder &Builder,
971973
OutputSectionEntry *Output,
972974
bool PostLayout) {
973-
uint64_t OutAlign = 0x0, InAlign = 0x0;
975+
uint64_t OutAlign = 0x0;
974976
bool IsPartialLink = (LinkerConfig::Object == ThisConfig.codeGenType());
975977

976978
ELFSection *OutSect = Output->getSection();
@@ -980,15 +982,6 @@ bool ObjectLinker::createOutputSection(ObjectBuilder &Builder,
980982
OutputSectionEntry::iterator In, InBegin, InEnd;
981983
InBegin = Output->begin();
982984
InEnd = Output->end();
983-
bool HasSubAlign = false;
984-
985-
// force input alignment from ldscript if any
986-
if (Output->prolog().hasSubAlign()) {
987-
Output->prolog().subAlign().eval();
988-
Output->prolog().subAlign().commit();
989-
InAlign = Output->prolog().subAlign().result();
990-
HasSubAlign = true;
991-
}
992985

993986
// force output alignment from ldscript if any
994987
if (Output->prolog().hasAlign()) {
@@ -1030,12 +1023,6 @@ bool ObjectLinker::createOutputSection(ObjectBuilder &Builder,
10301023
}
10311024
InSect->setAddrAlign(Alignment);
10321025
}
1033-
if (HasSubAlign && (InSect->getAddrAlign() < InAlign)) {
1034-
if (InSect->getFragmentList().size()) {
1035-
InSect->getFragmentList().front()->setAlignment(InAlign);
1036-
InSect->setAddrAlign(InAlign);
1037-
}
1038-
}
10391026
if (InSect->getFragmentList().size() && !FirstNonEmptyRule)
10401027
FirstNonEmptyRule = *In;
10411028

@@ -1286,6 +1273,9 @@ bool ObjectLinker::mergeSections() {
12861273
{
12871274
eld::RegisterTimer T("Create Output Section", "Merge Sections",
12881275
ThisConfig.options().printTimingStats());
1276+
// Prepass: apply SUBALIGN to first fragments per input section per output
1277+
// section serially to avoid races in parallel output creation.
1278+
applySubAlign();
12891279
std::vector<OutputSectionEntry *> OutSections;
12901280
for (Out = OutBegin; Out != OutEnd; ++Out) {
12911281
OutSections.push_back(*Out);
@@ -1329,6 +1319,41 @@ bool ObjectLinker::initializeOutputSectionsAndRunPlugin() {
13291319
return runOutputSectionIteratorPlugin();
13301320
}
13311321

1322+
void ObjectLinker::applySubAlign() {
1323+
std::unordered_set<ELFSection *> seen;
1324+
1325+
for (auto *O : ThisModule->getScript().sectionMap()) {
1326+
auto &prolog = O->prolog();
1327+
if (!prolog.hasSubAlign())
1328+
continue;
1329+
uint64_t subAlign;
1330+
prolog.subAlign().eval();
1331+
prolog.subAlign().commit();
1332+
subAlign = prolog.subAlign().result();
1333+
1334+
for (RuleContainer *R : *O) {
1335+
ELFSection *inSect = R->getSection();
1336+
for (Fragment *F : inSect->getFragmentList()) {
1337+
ELFSection *owningSect = F->getOwningSection();
1338+
if (owningSect->getKind() == LDFileFormat::Kind::OutputSectData) {
1339+
continue;
1340+
}
1341+
if (owningSect && seen.insert(owningSect).second) {
1342+
// Warn if SUBALIGN is reducing the section alignment
1343+
if (ThisConfig.showLinkerScriptWarnings() && F->alignment() > subAlign) {
1344+
ThisConfig.raise(Diag::warn_subalign_less_than_section_alignment)
1345+
<< utility::toHex(subAlign) << utility::toHex(F->alignment())
1346+
<< owningSect->getLocation(0, ThisConfig.options());
1347+
}
1348+
F->setAlignment(subAlign);
1349+
inSect->setAddrAlign(std::max(
1350+
static_cast<uint64_t>(inSect->getAddrAlign()), subAlign));
1351+
}
1352+
}
1353+
}
1354+
}
1355+
}
1356+
13321357
void ObjectLinker::assignOffset(OutputSectionEntry *Out) {
13331358
int64_t O = 0;
13341359
const ELFSection *OutSection = Out->getSection();
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
int foo() { return 0; }
2-
int bar() { return 0; }
2+
int bar() { return foo(); }
33
int car() { return 0; }
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
__attribute__((aligned((0x4))))
2+
int foo() { return 0; }
3+
4+
__attribute__((aligned((0x4))))
5+
int bar() { return foo(); }
6+
7+
__attribute__((aligned((0x4))))
8+
int car() { return 0; }
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
PHDRS {
2+
A PT_LOAD;
3+
}
4+
5+
SECTIONS {
6+
.a : SUBALIGN(64) {
7+
. = . + 1;
8+
*(.text*)
9+
}:A
10+
.b : SUBALIGN(64) {
11+
. = . + 1;
12+
}:A
13+
/DISCARD/ : { *(.ARM.exidx*) }
14+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
SECTIONS {
2+
.explicit_data : SUBALIGN(64) {
3+
BYTE(0x11)
4+
SHORT(0x2222)
5+
LONG(0x44444444)
6+
QUAD(0x8888888888888888)
7+
*(.text*)
8+
BYTE(0xAA)
9+
QUAD(0xBBBBBBBBBBBBBBBB)
10+
}
11+
/DISCARD/ : { *(.ARM.exidx*) }
12+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
PHDRS {
2+
A PT_LOAD;
3+
}
4+
5+
SECTIONS {
6+
.keep : SUBALIGN(64) {
7+
*(.text.foo)
8+
*(.text.bar)
9+
}:A
10+
/DISCARD/ : SUBALIGN(32) {
11+
*(.text.car)
12+
*(.ARM.exidx*)
13+
}
14+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
SECTIONS {
2+
.nonempty : SUBALIGN(64) {
3+
*(.text.foo)
4+
}
5+
.empty1 : SUBALIGN(32) {
6+
*(.nonexistent1)
7+
}
8+
.empty2 : SUBALIGN(128) {
9+
/* Empty section with just location counter */
10+
. = . + 0;
11+
}
12+
/DISCARD/ : { *(.ARM.exidx*) }
13+
}

0 commit comments

Comments
 (0)