[llvm-branch-commits] [llvm] release/20.x: [llvm-objcopy] Apply encryptable offset to first segment, not section (#130517) (PR #131398)

via llvm-branch-commits llvm-branch-commits at lists.llvm.org
Fri Mar 14 14:45:26 PDT 2025


https://github.com/llvmbot created https://github.com/llvm/llvm-project/pull/131398

Backport 8413f4d837a96458104f63bab72c751b8285a458

Requested by: @nikic

>From cb50aaf8a11b89f2785641fba5ffd4b67f566a32 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Daniel=20Rodr=C3=ADguez=20Troiti=C3=B1o?=
 <drodriguez at users.noreply.github.com>
Date: Fri, 14 Mar 2025 13:43:48 -0700
Subject: [PATCH] [llvm-objcopy] Apply encryptable offset to first segment, not
 section (#130517)

Bug introduced #120995. The LLD code calculates the "size" of the Mach-O
headers, and then uses that size to place the segments, but the `__TEXT`
section stays at `fileoff` zero. When I wrote the code into llvm-objcopy
I calculated the extra space into the initial offset, which moved all
the sections back 1 page.

Besides the modified test checking for the right `fileoff` values of the
sections and the segments, I also manually checked the generated
binaries after `llvm-objcopy` using `dyld_info`, as the bug report
suggested.

Fixes #130472

(cherry picked from commit 8413f4d837a96458104f63bab72c751b8285a458)
---
 llvm/lib/ObjCopy/MachO/MachOLayoutBuilder.cpp       | 13 ++++++++-----
 .../MachO/strip-with-encryption-info.test           | 12 +++++++++---
 2 files changed, 17 insertions(+), 8 deletions(-)

diff --git a/llvm/lib/ObjCopy/MachO/MachOLayoutBuilder.cpp b/llvm/lib/ObjCopy/MachO/MachOLayoutBuilder.cpp
index d4eb6a9b9fc0b..8ecd669e67178 100644
--- a/llvm/lib/ObjCopy/MachO/MachOLayoutBuilder.cpp
+++ b/llvm/lib/ObjCopy/MachO/MachOLayoutBuilder.cpp
@@ -116,11 +116,10 @@ uint64_t MachOLayoutBuilder::layoutSegments() {
   const bool IsObjectFile =
       O.Header.FileType == MachO::HeaderFileType::MH_OBJECT;
   uint64_t Offset = IsObjectFile ? (HeaderSize + O.Header.SizeOfCmds) : 0;
-  if (O.EncryptionInfoCommandIndex) {
-    // If we are emitting an encryptable binary, our load commands must have a
-    // separate (non-encrypted) page to themselves.
-    Offset = alignToPowerOf2(HeaderSize + O.Header.SizeOfCmds, PageSize);
-  }
+  // If we are emitting an encryptable binary, our load commands must have a
+  // separate (non-encrypted) page to themselves.
+  bool RequiresFirstSectionOutsideFirstPage =
+      O.EncryptionInfoCommandIndex.has_value();
   for (LoadCommand &LC : O.LoadCommands) {
     auto &MLC = LC.MachOLoadCommand;
     StringRef Segname;
@@ -174,6 +173,10 @@ uint64_t MachOLayoutBuilder::layoutSegments() {
         if (!Sec->hasValidOffset()) {
           Sec->Offset = 0;
         } else {
+          if (RequiresFirstSectionOutsideFirstPage) {
+            SectOffset = alignToPowerOf2(SectOffset, PageSize);
+            RequiresFirstSectionOutsideFirstPage = false;
+          }
           Sec->Offset = SegOffset + SectOffset;
           Sec->Size = Sec->Content.size();
           SegFileSize = std::max(SegFileSize, SectOffset + Sec->Size);
diff --git a/llvm/test/tools/llvm-objcopy/MachO/strip-with-encryption-info.test b/llvm/test/tools/llvm-objcopy/MachO/strip-with-encryption-info.test
index 19b06b1ec02c8..2b2bd670613de 100644
--- a/llvm/test/tools/llvm-objcopy/MachO/strip-with-encryption-info.test
+++ b/llvm/test/tools/llvm-objcopy/MachO/strip-with-encryption-info.test
@@ -1,13 +1,19 @@
 # RUN: rm -rf %t && mkdir %t
 # RUN: yaml2obj %s -o %t/original
 # RUN: llvm-strip --strip-all %t/original -o %t/stripped
-# RUN: llvm-readobj --macho-segment %t/stripped | FileCheck %s
+# RUN: llvm-readobj --macho-segment --section-headers %t/stripped | FileCheck %s
+
+# CHECK-LABEL: Sections [
+# CHECK:      Index: 0
+# CHECK-NEXT: Name: __text
+# CHECK-NEXT: Segment: __TEXT
+# CHECK:      Offset: 16384
 
 # CHECK-LABEL: Name: __PAGEZERO
-# CHECK:       fileoff: 16384
+# CHECK:       fileoff: 0
 
 # CHECK-LABEL: Name: __TEXT
-# CHECK:       fileoff: 16384
+# CHECK:       fileoff: 0
 
 # The YAML below is the following code
 # int main(int argc, char **argv) { return 0; }



More information about the llvm-branch-commits mailing list