Skip to content

lld hexagon ELF - 4kb aligned virtual addresses? #157597

@androm3da

Description

@androm3da

lld exhibits different behavior regarding the virtual address selection and one of the loaders appears to have an expectation/requirement that the virtual addresses be 4kb-aligned (min page size). This represents different behavior from eld.

  echo 'int main(){}' > test.c
  clang --target=hexagon-unknown-linux-musl -c test.c -o test.o

  ld.lld test.o -o test_lld
  readelf -l test_lld | grep -A1 "LOAD.*R E"
  LLD Output:
    LOAD           0x000000 0x00010210 0x00010210 0x000123 0x000123 R E 0x10000
                                  ↑ NOT 4KB aligned

  ld.eld test.o -o test_eld
  readelf -l test_eld | grep -A1 "LOAD.*R E"
  ELD Output:
    LOAD           0x000000 0x00010000 0x00010000 0x000123 0x000123 R E 0x10000
                                  ↑ 4KB aligned

@MaskRay I can fix this with a patch like the one below. Do you think that'd be an acceptable approach?

diff --git a/lld/ELF/Target.h b/lld/ELF/Target.h
index e121fa1183e9..72e4e6815c05 100644
--- a/lld/ELF/Target.h
+++ b/lld/ELF/Target.h
@@ -122,6 +122,8 @@ public:
   unsigned defaultCommonPageSize = 4096;
   unsigned defaultMaxPageSize = 4096;
 
+  std::optional<unsigned> minLoadSegmentAlignment;
+
   uint64_t getImageBase() const;
 
   // True if _GLOBAL_OFFSET_TABLE_ is relative to .got.plt, false if .got.
diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp
index 4fa80397cbfa..ee8d4314d82a 100644
--- a/lld/ELF/Writer.cpp
+++ b/lld/ELF/Writer.cpp
@@ -2592,6 +2592,19 @@ template <class ELFT> void Writer<ELFT>::fixSectionAlignments() {
         };
       else
         cmd->addrExpr = [&ctx] {
+          // If the target specifies a minimum LOAD segment alignment, enforce
+          // true page alignment to ensure LOAD segments are aligned to the
+          // required boundaries in virtual memory, not just in the p_align
+          // field. Other architectures preserve sub-page offsets to avoid file
+          // padding.
+          if (ctx.target->minLoadSegmentAlignment.has_value()) {
+            // Enforce minimum alignment, even if user specifies smaller page
+            // size
+            uint64_t minAlign = std::max(
+                ctx.arg.maxPageSize,
+                static_cast<uint64_t>(*ctx.target->minLoadSegmentAlignment));
+            return alignToPowerOf2(ctx.script->getDot(), minAlign);
+          }
           return alignToPowerOf2(ctx.script->getDot(), ctx.arg.maxPageSize) +
                  ctx.script->getDot() % ctx.arg.maxPageSize;
         };

Metadata

Metadata

Assignees

Labels

backend:Hexagonclang:driver'clang' and 'clang++' user-facing binaries. Not 'clang-cl'

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions