From 91ba62dddeac0f3bc737f7377453f5b580ff1289 Mon Sep 17 00:00:00 2001 From: Ryan Mansfield 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; def : Separate<["--", "-"], "arch">, Alias; def l : F<"l", "When format is darwin, use long format to include addresses and offsets">, Group; +def z : F<"z", "Do not include __PAGEZERO segment in totals">, + Group; def : F<"A", "Alias for --format">, Alias, AliasArgs<["sysv"]>; def : F<"B", "Alias for --format">, Alias, 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 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 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; def : Separate<["--", "-"], "arch">, Alias; def l : F<"l", "When format is darwin, use long format to include addresses and offsets">, Group; -def z : F<"z", "Do not include __PAGEZERO segment in totals">, - Group; +def exclude_pagezero + : FF<"exclude-pagezero", "Do not include __PAGEZERO segment in totals">, + Group; def : F<"A", "Alias for --format">, Alias, AliasArgs<["sysv"]>; def : F<"B", "Alias for --format">, Alias, 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 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 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 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