[llvm] [llvm-size] Add --exclude-pagezero option for Mach-O to exclude __PAGEZERO size. (PR #159574)

Ryan Mansfield via llvm-commits llvm-commits at lists.llvm.org
Fri Sep 26 05:41:04 PDT 2025


https://github.com/rjmansfield updated https://github.com/llvm/llvm-project/pull/159574

>From 91ba62dddeac0f3bc737f7377453f5b580ff1289 Mon Sep 17 00:00:00 2001
From: Ryan Mansfield <ryan_mansfield at apple.com>
Date: Fri, 12 Sep 2025 13:24:46 -0400
Subject: [PATCH 1/4] [llvm-size] Add -z option for Mach-O to exclude
 __PAGEZERO size.

Fixes #86644
---
 llvm/test/tools/llvm-size/macho-pagezero.test | 60 +++++++++++++++++++
 llvm/tools/llvm-size/Opts.td                  |  2 +
 llvm/tools/llvm-size/llvm-size.cpp            | 10 +++-
 3 files changed, 70 insertions(+), 2 deletions(-)
 create mode 100644 llvm/test/tools/llvm-size/macho-pagezero.test

diff --git a/llvm/test/tools/llvm-size/macho-pagezero.test b/llvm/test/tools/llvm-size/macho-pagezero.test
new file mode 100644
index 0000000000000..d53067504c3ad
--- /dev/null
+++ b/llvm/test/tools/llvm-size/macho-pagezero.test
@@ -0,0 +1,60 @@
+# Test the -z option to skip __PAGEZERO segment in Mach-O files
+
+# RUN: yaml2obj %s --docnum=1 -o %t-pagezero.o
+# RUN: llvm-size %t-pagezero.o | \
+# RUN:   FileCheck %s --check-prefix=NORMAL --match-full-lines \
+# RUN:                --strict-whitespace --implicit-check-not={{.}}
+# RUN: llvm-size -z %t-pagezero.o | \
+# RUN:   FileCheck %s --check-prefix=SKIP --match-full-lines \
+# RUN:                --strict-whitespace --implicit-check-not={{.}}
+
+# NORMAL:__TEXT	__DATA	__OBJC	others	dec	hex
+# NORMAL-NEXT:20	100	0	4096	4216	1078	
+
+# SKIP:__TEXT	__DATA	__OBJC	others	dec	hex
+# SKIP-NEXT:20	100	0	0	120	78	
+
+--- !mach-o
+FileHeader:
+  magic:           0xFEEDFACF
+  cputype:         0x100000C
+  cpusubtype:      0x0
+  filetype:        0x2
+  ncmds:           3
+  sizeofcmds:      216
+  flags:           0x2000
+  reserved:        0x0
+LoadCommands:
+  - cmd:             LC_SEGMENT_64
+    cmdsize:         72
+    segname:         __PAGEZERO
+    vmaddr:          0x0
+    vmsize:          4096
+    fileoff:         0
+    filesize:        0
+    maxprot:         0
+    initprot:        0
+    nsects:          0
+    flags:           0
+  - cmd:             LC_SEGMENT_64
+    cmdsize:         72
+    segname:         __TEXT
+    vmaddr:          0x100000000
+    vmsize:          20
+    fileoff:         248
+    filesize:        20
+    maxprot:         7
+    initprot:        5
+    nsects:          0
+    flags:           0
+  - cmd:             LC_SEGMENT_64
+    cmdsize:         72
+    segname:         __DATA
+    vmaddr:          0x100001000
+    vmsize:          100
+    fileoff:         268
+    filesize:        100
+    maxprot:         7
+    initprot:        3
+    nsects:          0
+    flags:           0
diff --git a/llvm/tools/llvm-size/Opts.td b/llvm/tools/llvm-size/Opts.td
index edae43f1abd24..65478730c2801 100644
--- a/llvm/tools/llvm-size/Opts.td
+++ b/llvm/tools/llvm-size/Opts.td
@@ -21,6 +21,8 @@ def grp_mach_o : OptionGroup<"kind">, HelpText<"OPTIONS (Mach-O specific)">;
 def arch_EQ : Joined<["--"], "arch=">, HelpText<"architecture(s) from a Mach-O file to dump">, Group<grp_mach_o>;
 def : Separate<["--", "-"], "arch">, Alias<arch_EQ>;
 def l : F<"l", "When format is darwin, use long format to include addresses and offsets">, Group<grp_mach_o>;
+def z : F<"z", "Do not include __PAGEZERO segment in totals">,
+        Group<grp_mach_o>;
 
 def : F<"A", "Alias for --format">, Alias<format_EQ>, AliasArgs<["sysv"]>;
 def : F<"B", "Alias for --format">, Alias<format_EQ>, AliasArgs<["berkeley"]>;
diff --git a/llvm/tools/llvm-size/llvm-size.cpp b/llvm/tools/llvm-size/llvm-size.cpp
index acc7843ffac8b..805f8ed1e6dcd 100644
--- a/llvm/tools/llvm-size/llvm-size.cpp
+++ b/llvm/tools/llvm-size/llvm-size.cpp
@@ -79,6 +79,7 @@ static bool DarwinLongFormat;
 static RadixTy Radix = RadixTy::decimal;
 static bool TotalSizes;
 static bool HasMachOFiles = false;
+static bool SkipPageZero = false;
 
 static std::vector<std::string> InputFilenames;
 
@@ -307,7 +308,9 @@ static void printDarwinSegmentSizes(MachOObjectFile *MachO) {
         }
       } else {
         StringRef SegmentName = StringRef(Seg.segname);
-        if (SegmentName == "__TEXT")
+        if (SkipPageZero && SegmentName == "__PAGEZERO")
+          ; // Skip __PAGEZERO segment
+        else if (SegmentName == "__TEXT")
           total_text += Seg.vmsize;
         else if (SegmentName == "__DATA")
           total_data += Seg.vmsize;
@@ -333,7 +336,9 @@ static void printDarwinSegmentSizes(MachOObjectFile *MachO) {
         }
       } else {
         StringRef SegmentName = StringRef(Seg.segname);
-        if (SegmentName == "__TEXT")
+        if (SkipPageZero && SegmentName == "__PAGEZERO")
+          ; // Skip __PAGEZERO segment
+        else if (SegmentName == "__TEXT")
           total_text += Seg.vmsize;
         else if (SegmentName == "__DATA")
           total_data += Seg.vmsize;
@@ -914,6 +919,7 @@ int llvm_size_main(int argc, char **argv, const llvm::ToolContext &) {
 
   ELFCommons = Args.hasArg(OPT_common);
   DarwinLongFormat = Args.hasArg(OPT_l);
+  SkipPageZero = Args.hasArg(OPT_z);
   TotalSizes = Args.hasArg(OPT_totals);
   StringRef V = Args.getLastArgValue(OPT_format_EQ, "berkeley");
   if (V == "berkeley")

>From 7e7b187eb04f256bf51bbf4faf7330f7d4e3fff3 Mon Sep 17 00:00:00 2001
From: Ryan Mansfield <ryan_mansfield at apple.com>
Date: Wed, 24 Sep 2025 10:09:02 -0400
Subject: [PATCH 2/4] Update new option to --exclude-pagezero. Address code
 review comments.

---
 llvm/test/tools/llvm-size/macho-pagezero.test | 14 ++++++--------
 llvm/tools/llvm-size/Opts.td                  |  5 +++--
 llvm/tools/llvm-size/llvm-size.cpp            | 16 ++++++----------
 3 files changed, 15 insertions(+), 20 deletions(-)

diff --git a/llvm/test/tools/llvm-size/macho-pagezero.test b/llvm/test/tools/llvm-size/macho-pagezero.test
index d53067504c3ad..9e902c53ec41f 100644
--- a/llvm/test/tools/llvm-size/macho-pagezero.test
+++ b/llvm/test/tools/llvm-size/macho-pagezero.test
@@ -1,18 +1,16 @@
-# Test the -z option to skip __PAGEZERO segment in Mach-O files
+## Test the --exclude-pagezero option to skip __PAGEZERO segment in Mach-O files.
 
 # RUN: yaml2obj %s --docnum=1 -o %t-pagezero.o
 # RUN: llvm-size %t-pagezero.o | \
-# RUN:   FileCheck %s --check-prefix=NORMAL --match-full-lines \
-# RUN:                --strict-whitespace --implicit-check-not={{.}}
-# RUN: llvm-size -z %t-pagezero.o | \
-# RUN:   FileCheck %s --check-prefix=SKIP --match-full-lines \
-# RUN:                --strict-whitespace --implicit-check-not={{.}}
+# RUN:   FileCheck %s --check-prefix=NORMAL --match-full-lines
+# RUN: llvm-size --exclude-pagezero %t-pagezero.o | \
+# RUN:   FileCheck %s --check-prefix=SKIP --match-full-lines
 
 # NORMAL:__TEXT	__DATA	__OBJC	others	dec	hex
-# NORMAL-NEXT:20	100	0	4096	4216	1078	
+# NORMAL-NEXT:20	100	0	4096	4216	1078
 
 # SKIP:__TEXT	__DATA	__OBJC	others	dec	hex
-# SKIP-NEXT:20	100	0	0	120	78	
+# SKIP-NEXT:20	100	0	0	120	78
 
 --- !mach-o
 FileHeader:
diff --git a/llvm/tools/llvm-size/Opts.td b/llvm/tools/llvm-size/Opts.td
index 65478730c2801..88e39f293a505 100644
--- a/llvm/tools/llvm-size/Opts.td
+++ b/llvm/tools/llvm-size/Opts.td
@@ -21,8 +21,9 @@ def grp_mach_o : OptionGroup<"kind">, HelpText<"OPTIONS (Mach-O specific)">;
 def arch_EQ : Joined<["--"], "arch=">, HelpText<"architecture(s) from a Mach-O file to dump">, Group<grp_mach_o>;
 def : Separate<["--", "-"], "arch">, Alias<arch_EQ>;
 def l : F<"l", "When format is darwin, use long format to include addresses and offsets">, Group<grp_mach_o>;
-def z : F<"z", "Do not include __PAGEZERO segment in totals">,
-        Group<grp_mach_o>;
+def exclude_pagezero
+    : FF<"exclude-pagezero", "Do not include __PAGEZERO segment in totals">,
+      Group<grp_mach_o>;
 
 def : F<"A", "Alias for --format">, Alias<format_EQ>, AliasArgs<["sysv"]>;
 def : F<"B", "Alias for --format">, Alias<format_EQ>, AliasArgs<["berkeley"]>;
diff --git a/llvm/tools/llvm-size/llvm-size.cpp b/llvm/tools/llvm-size/llvm-size.cpp
index 805f8ed1e6dcd..ec94db4ff7382 100644
--- a/llvm/tools/llvm-size/llvm-size.cpp
+++ b/llvm/tools/llvm-size/llvm-size.cpp
@@ -79,7 +79,7 @@ static bool DarwinLongFormat;
 static RadixTy Radix = RadixTy::decimal;
 static bool TotalSizes;
 static bool HasMachOFiles = false;
-static bool SkipPageZero = false;
+static bool ExcludePageZero = false;
 
 static std::vector<std::string> InputFilenames;
 
@@ -308,15 +308,13 @@ static void printDarwinSegmentSizes(MachOObjectFile *MachO) {
         }
       } else {
         StringRef SegmentName = StringRef(Seg.segname);
-        if (SkipPageZero && SegmentName == "__PAGEZERO")
-          ; // Skip __PAGEZERO segment
-        else if (SegmentName == "__TEXT")
+        if (SegmentName == "__TEXT")
           total_text += Seg.vmsize;
         else if (SegmentName == "__DATA")
           total_data += Seg.vmsize;
         else if (SegmentName == "__OBJC")
           total_objc += Seg.vmsize;
-        else
+        else if (!ExcludePageZero || SegmentName != "__PAGEZERO")
           total_others += Seg.vmsize;
       }
     } else if (Load.C.cmd == MachO::LC_SEGMENT) {
@@ -336,15 +334,13 @@ static void printDarwinSegmentSizes(MachOObjectFile *MachO) {
         }
       } else {
         StringRef SegmentName = StringRef(Seg.segname);
-        if (SkipPageZero && SegmentName == "__PAGEZERO")
-          ; // Skip __PAGEZERO segment
-        else if (SegmentName == "__TEXT")
+        if (SegmentName == "__TEXT")
           total_text += Seg.vmsize;
         else if (SegmentName == "__DATA")
           total_data += Seg.vmsize;
         else if (SegmentName == "__OBJC")
           total_objc += Seg.vmsize;
-        else
+        else if (!ExcludePageZero || SegmentName != "__PAGEZERO")
           total_others += Seg.vmsize;
       }
     }
@@ -919,7 +915,7 @@ int llvm_size_main(int argc, char **argv, const llvm::ToolContext &) {
 
   ELFCommons = Args.hasArg(OPT_common);
   DarwinLongFormat = Args.hasArg(OPT_l);
-  SkipPageZero = Args.hasArg(OPT_z);
+  ExcludePageZero = Args.hasArg(OPT_exclude_pagezero);
   TotalSizes = Args.hasArg(OPT_totals);
   StringRef V = Args.getLastArgValue(OPT_format_EQ, "berkeley");
   if (V == "berkeley")

>From ed93efb0f93609ebe09455ecf741b16ff4aef8be Mon Sep 17 00:00:00 2001
From: Ryan Mansfield <ryan_mansfield at apple.com>
Date: Thu, 25 Sep 2025 11:06:35 -0400
Subject: [PATCH 3/4] Add entry in the command guide for --exclude-pagezero
 option. Add test for 32 bit  __PAGEZERO segment.

---
 llvm/docs/CommandGuide/llvm-size.rst          |  7 +++
 llvm/test/tools/llvm-size/macho-pagezero.test | 56 +++++++++++++++++++
 2 files changed, 63 insertions(+)

diff --git a/llvm/docs/CommandGuide/llvm-size.rst b/llvm/docs/CommandGuide/llvm-size.rst
index f244769545b31..01d7357e76b86 100644
--- a/llvm/docs/CommandGuide/llvm-size.rst
+++ b/llvm/docs/CommandGuide/llvm-size.rst
@@ -41,6 +41,13 @@ OPTIONS
  as a separate section entry for ``sysv`` output. If not specified, these
  symbols are ignored.
 
+.. option:: --exclude-pagezero
+
+ Do not include the ``__PAGEZERO`` segment when calculating size information
+ for Mach-O files. ``__PAGEZERO`` segment is a virtual memory region used
+ for memory protection that does not contribute to actual size, and excluding
+ can provide a better representation of actual size.
+
 .. option:: -d
 
  Equivalent to :option:`--radix` with a value of ``10``.
diff --git a/llvm/test/tools/llvm-size/macho-pagezero.test b/llvm/test/tools/llvm-size/macho-pagezero.test
index 9e902c53ec41f..e14096782b8ee 100644
--- a/llvm/test/tools/llvm-size/macho-pagezero.test
+++ b/llvm/test/tools/llvm-size/macho-pagezero.test
@@ -6,12 +6,24 @@
 # RUN: llvm-size --exclude-pagezero %t-pagezero.o | \
 # RUN:   FileCheck %s --check-prefix=SKIP --match-full-lines
 
+# RUN: yaml2obj %s --docnum=2 -o %t-pagezero32.o
+# RUN: llvm-size %t-pagezero32.o | \
+# RUN:   FileCheck %s --check-prefix=NORMAL32 --match-full-lines
+# RUN: llvm-size --exclude-pagezero %t-pagezero32.o | \
+# RUN:   FileCheck %s --check-prefix=SKIP32 --match-full-lines
+
 # NORMAL:__TEXT	__DATA	__OBJC	others	dec	hex
 # NORMAL-NEXT:20	100	0	4096	4216	1078
 
 # SKIP:__TEXT	__DATA	__OBJC	others	dec	hex
 # SKIP-NEXT:20	100	0	0	120	78
 
+# NORMAL32:__TEXT	__DATA	__OBJC	others	dec	hex
+# NORMAL32-NEXT:20	100	0	4096	4216	1078
+
+# SKIP32:__TEXT	__DATA	__OBJC	others	dec	hex
+# SKIP32-NEXT:20	100	0	0	120	78
+
 --- !mach-o
 FileHeader:
   magic:           0xFEEDFACF
@@ -56,3 +68,47 @@ LoadCommands:
     initprot:        3
     nsects:          0
     flags:           0
+
+--- !mach-o
+FileHeader:
+  magic:           0xFEEDFACE
+  cputype:         0x7
+  cpusubtype:      0x3
+  filetype:        0x2
+  ncmds:           3
+  sizeofcmds:      168
+  flags:           0x2000
+LoadCommands:
+  - cmd:             LC_SEGMENT
+    cmdsize:         56
+    segname:         __PAGEZERO
+    vmaddr:          0x0
+    vmsize:          4096
+    fileoff:         0
+    filesize:        0
+    maxprot:         0
+    initprot:        0
+    nsects:          0
+    flags:           0
+  - cmd:             LC_SEGMENT
+    cmdsize:         56
+    segname:         __TEXT
+    vmaddr:          0x1000
+    vmsize:          20
+    fileoff:         196
+    filesize:        20
+    maxprot:         7
+    initprot:        5
+    nsects:          0
+    flags:           0
+  - cmd:             LC_SEGMENT
+    cmdsize:         56
+    segname:         __DATA
+    vmaddr:          0x2000
+    vmsize:          100
+    fileoff:         216
+    filesize:        100
+    maxprot:         7
+    initprot:        3
+    nsects:          0
+    flags:           0

>From 711273cb870124391ff251703f37fb63c80f826c Mon Sep 17 00:00:00 2001
From: Ryan Mansfield <ryan_mansfield at apple.com>
Date: Fri, 26 Sep 2025 08:33:33 -0400
Subject: [PATCH 4/4] Use same check values for 32bit test.

---
 llvm/docs/CommandGuide/llvm-size.rst          |  2 +-
 llvm/test/tools/llvm-size/macho-pagezero.test | 10 ++--------
 2 files changed, 3 insertions(+), 9 deletions(-)

diff --git a/llvm/docs/CommandGuide/llvm-size.rst b/llvm/docs/CommandGuide/llvm-size.rst
index 01d7357e76b86..12e7c58c5776d 100644
--- a/llvm/docs/CommandGuide/llvm-size.rst
+++ b/llvm/docs/CommandGuide/llvm-size.rst
@@ -44,7 +44,7 @@ OPTIONS
 .. option:: --exclude-pagezero
 
  Do not include the ``__PAGEZERO`` segment when calculating size information
- for Mach-O files. ``__PAGEZERO`` segment is a virtual memory region used
+ for Mach-O files. The ``__PAGEZERO`` segment is a virtual memory region used
  for memory protection that does not contribute to actual size, and excluding
  can provide a better representation of actual size.
 
diff --git a/llvm/test/tools/llvm-size/macho-pagezero.test b/llvm/test/tools/llvm-size/macho-pagezero.test
index e14096782b8ee..db69fd0c9daeb 100644
--- a/llvm/test/tools/llvm-size/macho-pagezero.test
+++ b/llvm/test/tools/llvm-size/macho-pagezero.test
@@ -8,9 +8,9 @@
 
 # RUN: yaml2obj %s --docnum=2 -o %t-pagezero32.o
 # RUN: llvm-size %t-pagezero32.o | \
-# RUN:   FileCheck %s --check-prefix=NORMAL32 --match-full-lines
+# RUN:   FileCheck %s --check-prefix=NORMAL --match-full-lines
 # RUN: llvm-size --exclude-pagezero %t-pagezero32.o | \
-# RUN:   FileCheck %s --check-prefix=SKIP32 --match-full-lines
+# RUN:   FileCheck %s --check-prefix=SKIP --match-full-lines
 
 # NORMAL:__TEXT	__DATA	__OBJC	others	dec	hex
 # NORMAL-NEXT:20	100	0	4096	4216	1078
@@ -18,12 +18,6 @@
 # SKIP:__TEXT	__DATA	__OBJC	others	dec	hex
 # SKIP-NEXT:20	100	0	0	120	78
 
-# NORMAL32:__TEXT	__DATA	__OBJC	others	dec	hex
-# NORMAL32-NEXT:20	100	0	4096	4216	1078
-
-# SKIP32:__TEXT	__DATA	__OBJC	others	dec	hex
-# SKIP32-NEXT:20	100	0	0	120	78
-
 --- !mach-o
 FileHeader:
   magic:           0xFEEDFACF



More information about the llvm-commits mailing list