[llvm-branch-commits] [llvm] [llvm-objdump] Decode arm64e chained fixups (PR #234001)
Oskar Wirga via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Tue Oct 20 14:50:48 PDT 2026
https://github.com/oskarwirga created https://github.com/llvm/llvm-project/pull/234001
`llvm-objdump --dyld-info` and `llvm-otool -dyld_info` decoded only the
`DYLD_CHAINED_PTR_64` and `DYLD_CHAINED_PTR_64_OFFSET` formats, and stopped
with "unsupported chained fixup pointer_format" on arm64e images.
- Add the `dyld_chained_ptr_arm64e_*` structs of `<mach-o/fixup-chains.h>` to
`BinaryFormat`
- Decode `DYLD_CHAINED_PTR_ARM64E` and
`DYLD_CHAINED_PTR_ARM64E_USERLAND24` fixups in `MachOChainedFixupEntry`: an
8-byte stride, 16- or 24-bit import ordinals, 19-bit signed inline
addends, and rebase targets that are addresses in `DYLD_CHAINED_PTR_ARM64E`
and offsets from the image in `DYLD_CHAINED_PTR_ARM64E_USERLAND24` and in
every authenticated rebase.
- Authenticated rebases and binds expose their
key, diversity and address diversity, which `--dyld-info` prints in the
div, addr and key columns that cctools' `otool` uses for arm64e.
The test builds its images with `yaml2obj` from the `obj2yaml` output of
images that Xcode 27's ld linked from the sources in the test. The
lld-macho arm64e tests later in the stack check their output with this decoder.
Assisted-by: Claude
>From 10bda14e479d19543af34ff43505fa67018475cd Mon Sep 17 00:00:00 2001
From: Oskar Wirga <oskar at wirga.com>
Date: Tue, 6 Oct 2026 15:09:51 -0700
Subject: [PATCH] [llvm-objdump] Decode arm64e chained fixups
llvm-objdump --dyld-info and llvm-otool -dyld_info decoded only the
DYLD_CHAINED_PTR_64 and DYLD_CHAINED_PTR_64_OFFSET formats, and stopped
with "unsupported chained fixup pointer_format" on arm64e images.
Add the dyld_chained_ptr_arm64e_* structs of <mach-o/fixup-chains.h> to
BinaryFormat, and decode DYLD_CHAINED_PTR_ARM64E and
DYLD_CHAINED_PTR_ARM64E_USERLAND24 fixups in MachOChainedFixupEntry: an
8-byte stride, 16- or 24-bit import ordinals, 19-bit signed inline
addends, and rebase targets that are addresses in DYLD_CHAINED_PTR_ARM64E
and offsets from the image in DYLD_CHAINED_PTR_ARM64E_USERLAND24 and in
every authenticated rebase. Authenticated rebases and binds expose their
key, diversity and address diversity, which --dyld-info prints in the
div, addr and key columns that cctools' otool uses for arm64e.
The test builds its images with yaml2obj from the obj2yaml output of
images that ld64 linked from the sources in the test.
Assisted-by: Claude Code
---
llvm/include/llvm/BinaryFormat/MachO.h | 62 ++++
llvm/include/llvm/Object/MachO.h | 17 +
llvm/lib/Object/MachOObjectFile.cpp | 80 ++++-
.../MachO/chained-fixups-arm64e.test | 338 ++++++++++++++++++
llvm/tools/llvm-objdump/MachODump.cpp | 26 +-
5 files changed, 499 insertions(+), 24 deletions(-)
create mode 100644 llvm/test/tools/llvm-objdump/MachO/chained-fixups-arm64e.test
diff --git a/llvm/include/llvm/BinaryFormat/MachO.h b/llvm/include/llvm/BinaryFormat/MachO.h
index ecf9f36fdffcf..ae2a6ac32b4b8 100644
--- a/llvm/include/llvm/BinaryFormat/MachO.h
+++ b/llvm/include/llvm/BinaryFormat/MachO.h
@@ -1194,6 +1194,68 @@ struct dyld_chained_ptr_64_rebase {
uint64_t bind : 1; // set to 0
};
+// DYLD_CHAINED_PTR_ARM64E / DYLD_CHAINED_PTR_ARM64E_USERLAND
+struct dyld_chained_ptr_arm64e_rebase {
+ uint64_t target : 43;
+ uint64_t high8 : 8;
+ uint64_t next : 11; // 4 or 8-byte stride
+ uint64_t bind : 1; // == 0
+ uint64_t auth : 1; // == 0
+};
+
+struct dyld_chained_ptr_arm64e_bind {
+ uint64_t ordinal : 16;
+ uint64_t zero : 16;
+ uint64_t addend : 19; // +/-256K
+ uint64_t next : 11; // 4 or 8-byte stride
+ uint64_t bind : 1; // == 1
+ uint64_t auth : 1; // == 0
+};
+
+struct dyld_chained_ptr_arm64e_auth_bind {
+ uint64_t ordinal : 16;
+ uint64_t zero : 16;
+ uint64_t diversity : 16;
+ uint64_t addrDiv : 1;
+ uint64_t key : 2;
+ uint64_t next : 11; // 4 or 8-byte stride
+ uint64_t bind : 1; // == 1
+ uint64_t auth : 1; // == 1
+};
+
+struct dyld_chained_ptr_arm64e_auth_rebase {
+ uint64_t target : 32; // runtimeOffset
+ uint64_t diversity : 16;
+ uint64_t addrDiv : 1;
+ uint64_t key : 2;
+ uint64_t next : 11; // 4 or 8-byte stride
+ uint64_t bind : 1; // == 0
+ uint64_t auth : 1; // == 1
+};
+
+// DYLD_CHAINED_PTR_ARM64E_USERLAND24: 24-bit ordinal (vs 16) for more imports.
+// Rebase formats are shared with DYLD_CHAINED_PTR_ARM64E.
+struct dyld_chained_ptr_arm64e_bind24 {
+ uint64_t ordinal : 24;
+ uint64_t zero : 8;
+ uint64_t addend : 19; // +/-256K
+ uint64_t next : 11; // 8-byte stride
+ uint64_t bind : 1; // == 1
+ uint64_t auth : 1; // == 0
+};
+
+// DYLD_CHAINED_PTR_ARM64E_USERLAND24
+struct dyld_chained_ptr_arm64e_auth_bind24 {
+ uint64_t ordinal : 24;
+ uint64_t zero : 8;
+ uint64_t diversity : 16;
+ uint64_t addrDiv : 1;
+ uint64_t key : 2;
+ uint64_t next : 11; // 8-byte stride
+ uint64_t bind : 1; // == 1
+ uint64_t auth : 1; // == 1
+};
+
// Byte order swapping functions for MachO structs
inline void swapStruct(fat_header &mh) {
diff --git a/llvm/include/llvm/Object/MachO.h b/llvm/include/llvm/Object/MachO.h
index cafd6ed3fa9f2..6ba9a92ef48b4 100644
--- a/llvm/include/llvm/Object/MachO.h
+++ b/llvm/include/llvm/Object/MachO.h
@@ -389,6 +389,18 @@ class MachOChainedFixupEntry : public MachOAbstractFixupEntry {
bool isBind() const { return Kind == FixupKind::Bind; }
bool isRebase() const { return Kind == FixupKind::Rebase; }
+ /// \return the DYLD_CHAINED_PTR_* format of the segment of this fixup.
+ uint16_t pointerFormat() const { return PointerFormat; }
+
+ /// \return whether this is an arm64e authenticated rebase or bind, which
+ /// dyld signs with key(), diversity() and, if hasAddressDiversity(), the
+ /// address of the fixup.
+ bool isAuthenticated() const { return IsAuthenticated; }
+ /// \return the ptrauth key: 0 = IA, 1 = IB, 2 = DA, 3 = DB.
+ uint8_t key() const { return Key; }
+ uint16_t diversity() const { return Diversity; }
+ bool hasAddressDiversity() const { return HasAddressDiversity; }
+
LLVM_ABI void moveNext();
LLVM_ABI void moveToFirst();
LLVM_ABI void moveToEnd();
@@ -400,6 +412,11 @@ class MachOChainedFixupEntry : public MachOAbstractFixupEntry {
std::vector<ChainedFixupsSegment> Segments;
ArrayRef<uint8_t> SegmentData;
FixupKind Kind;
+ uint16_t PointerFormat = 0;
+ uint16_t Diversity = 0;
+ uint8_t Key = 0;
+ bool IsAuthenticated = false;
+ bool HasAddressDiversity = false;
uint32_t InfoSegIndex = 0; // Index into Segments
uint32_t PageIndex = 0; // Index into Segments[InfoSegIdx].PageStarts
uint32_t PageOffset = 0; // Page offset of the current fixup
diff --git a/llvm/lib/Object/MachOObjectFile.cpp b/llvm/lib/Object/MachOObjectFile.cpp
index 85c4f69d70dde..7fbb8fb706025 100644
--- a/llvm/lib/Object/MachOObjectFile.cpp
+++ b/llvm/lib/Object/MachOObjectFile.cpp
@@ -3502,9 +3502,11 @@ void MachOChainedFixupEntry::moveNext() {
SegmentOffset = SegInfo.Header.page_size * PageIndex + PageOffset;
// FIXME: Handle other pointer formats.
- uint16_t PointerFormat = SegInfo.Header.pointer_format;
+ PointerFormat = SegInfo.Header.pointer_format;
+ bool IsArm64e = PointerFormat == MachO::DYLD_CHAINED_PTR_ARM64E ||
+ PointerFormat == MachO::DYLD_CHAINED_PTR_ARM64E_USERLAND24;
if (PointerFormat != MachO::DYLD_CHAINED_PTR_64 &&
- PointerFormat != MachO::DYLD_CHAINED_PTR_64_OFFSET) {
+ PointerFormat != MachO::DYLD_CHAINED_PTR_64_OFFSET && !IsArm64e) {
*E = createError("segment " + Twine(SegmentIndex) +
" has unsupported chained fixup pointer_format " +
Twine(PointerFormat));
@@ -3517,6 +3519,10 @@ void MachOChainedFixupEntry::moveNext() {
Addend = 0;
PointerValue = 0;
SymbolName = {};
+ IsAuthenticated = false;
+ HasAddressDiversity = false;
+ Key = 0;
+ Diversity = 0;
if (SegmentOffset + sizeof(RawValue) > SegmentData.size()) {
*E = malformedError("fixup in segment " + Twine(SegmentIndex) +
@@ -3538,15 +3544,59 @@ void MachOChainedFixupEntry::moveNext() {
return (RawValue >> Right) & ((1ULL << Count) - 1);
};
- // The `bind` field (most significant bit) of the encoded fixup determines
- // whether it is dyld_chained_ptr_64_bind or dyld_chained_ptr_64_rebase.
- bool IsBind = Field(63, 1);
+ bool IsBind;
+ uint32_t Next;
+ uint32_t ImportOrdinal = 0;
+ int64_t InlineAddend = 0;
+ if (IsArm64e) {
+ // The `auth` and `bind` fields (the two most significant bits) of the
+ // encoded fixup determine which dyld_chained_ptr_arm64e_* struct it is.
+ IsAuthenticated = Field(63, 1);
+ IsBind = Field(62, 1);
+ Next = Field(51, 11);
+ if (IsAuthenticated) {
+ Diversity = Field(32, 16);
+ HasAddressDiversity = Field(48, 1);
+ Key = Field(49, 2);
+ }
+ if (IsBind) {
+ ImportOrdinal = Field(
+ 0,
+ PointerFormat == MachO::DYLD_CHAINED_PTR_ARM64E_USERLAND24 ? 24 : 16);
+ // Authenticated binds have no room for an addend.
+ if (!IsAuthenticated)
+ InlineAddend = SignExtend64<19>(Field(32, 19));
+ } else if (IsAuthenticated) {
+ // The target of an authenticated rebase is an offset from the image.
+ PointerValue = Field(0, 32) + textAddress();
+ } else {
+ // DYLD_CHAINED_PTR_ARM64E rebases hold an address, and
+ // DYLD_CHAINED_PTR_ARM64E_USERLAND24 rebases an offset from the image.
+ uint64_t Target = Field(0, 43);
+ if (PointerFormat == MachO::DYLD_CHAINED_PTR_ARM64E_USERLAND24)
+ Target += textAddress();
+ PointerValue = Target | (Field(43, 8) << 56);
+ }
+ } else {
+ // The `bind` field (most significant bit) of the encoded fixup determines
+ // whether it is dyld_chained_ptr_64_bind or dyld_chained_ptr_64_rebase.
+ IsBind = Field(63, 1);
+ Next = Field(51, 12);
+ if (IsBind) {
+ ImportOrdinal = Field(0, 24);
+ InlineAddend = Field(24, 8);
+ } else {
+ uint64_t Target = Field(0, 36);
+ uint64_t High8 = Field(36, 8);
+
+ PointerValue = Target | (High8 << 56);
+ if (PointerFormat == MachO::DYLD_CHAINED_PTR_64_OFFSET)
+ PointerValue += textAddress();
+ }
+ }
+
Kind = IsBind ? FixupKind::Bind : FixupKind::Rebase;
- uint32_t Next = Field(51, 12);
if (IsBind) {
- uint32_t ImportOrdinal = Field(0, 24);
- uint8_t InlineAddend = Field(24, 8);
-
if (ImportOrdinal >= FixupTargets.size()) {
*E = malformedError("fixup in segment " + Twine(SegmentIndex) +
" at offset " + Twine(SegmentOffset) +
@@ -3561,18 +3611,12 @@ void MachOChainedFixupEntry::moveNext() {
Addend = InlineAddend ? InlineAddend : Target.addend();
Flags = Target.weakImport() ? MachO::BIND_SYMBOL_FLAGS_WEAK_IMPORT : 0;
SymbolName = Target.symbolName();
- } else {
- uint64_t Target = Field(0, 36);
- uint64_t High8 = Field(36, 8);
-
- PointerValue = Target | (High8 << 56);
- if (PointerFormat == MachO::DYLD_CHAINED_PTR_64_OFFSET)
- PointerValue += textAddress();
}
- // The stride is 4 bytes for DYLD_CHAINED_PTR_64(_OFFSET).
+ // The stride is 8 bytes for the arm64e formats and 4 bytes for
+ // DYLD_CHAINED_PTR_64(_OFFSET).
if (Next != 0) {
- PageOffset += 4 * Next;
+ PageOffset += (IsArm64e ? 8 : 4) * Next;
} else {
++PageIndex;
findNextPageWithFixups();
diff --git a/llvm/test/tools/llvm-objdump/MachO/chained-fixups-arm64e.test b/llvm/test/tools/llvm-objdump/MachO/chained-fixups-arm64e.test
new file mode 100644
index 0000000000000..adc3ea454fd3d
--- /dev/null
+++ b/llvm/test/tools/llvm-objdump/MachO/chained-fixups-arm64e.test
@@ -0,0 +1,338 @@
+## Check that llvm-objdump and llvm-otool decode the arm64e chained fixup
+## formats DYLD_CHAINED_PTR_ARM64E and DYLD_CHAINED_PTR_ARM64E_USERLAND24,
+## including the signing schema of authenticated rebases and binds.
+
+# RUN: yaml2obj -DMINOS=0xB0000 -DFORMAT=0x1 -DTARGET_HI=01 %s -o %t.arm64e
+# RUN: yaml2obj -DMINOS=0xD0000 -DFORMAT=0xC -DTARGET_HI=00 %s -o %t.userland24
+
+# RUN: llvm-objdump --macho --chained-fixups %t.arm64e | \
+# RUN: FileCheck --check-prefix=FORMAT1 %s
+# RUN: llvm-objdump --macho --chained-fixups %t.userland24 | \
+# RUN: FileCheck --check-prefix=FORMAT12 %s
+
+# FORMAT1: pointer_format = 1 (DYLD_CHAINED_PTR_ARM64E)
+# FORMAT12: pointer_format = 12 (DYLD_CHAINED_PTR_ARM64E_USERLAND24)
+
+# RUN: llvm-objdump --macho --dyld-info %t.arm64e | \
+# RUN: FileCheck --check-prefixes=CHECK,ARM64E -DNAME=%t.arm64e %s
+# RUN: llvm-otool -dyld_info %t.arm64e | \
+# RUN: FileCheck --check-prefixes=CHECK,ARM64E -DNAME=%t.arm64e %s
+# RUN: llvm-objdump --macho --dyld-info %t.userland24 | \
+# RUN: FileCheck --check-prefixes=CHECK,USERLAND24 -DNAME=%t.userland24 %s
+
+## The two images differ only in the encoding of the unauthenticated rebases:
+## DYLD_CHAINED_PTR_ARM64E stores their target address, and
+## DYLD_CHAINED_PTR_ARM64E_USERLAND24 its offset from the image. The target of
+## an authenticated rebase is an offset from the image in both formats. The
+## decoded values match the output of dyld_info -fixups. cctools-1040's otool
+## prints the same columns, but shows the offset of an authenticated rebase
+## (0x3B4) where llvm-objdump shows its address, as for every other rebase.
+# CHECK: [[NAME]]:
+# CHECK-NEXT: dyld information:
+# CHECK-NEXT: segment section address pointer type div addr key addend dylib symbol/vm address
+# CHECK-NEXT: __DATA __data 0x100001008 0x80080000000003B4 rebase 0x0000 false IA 0x1000003B4
+# CHECK-NEXT: __DATA __data 0x100001010 0x800B1234000003BC rebase 0x1234 true IB 0x1000003BC
+# CHECK-NEXT: __DATA __data 0x100001018 0xC00C002A00000000 bind 0x002A false DA 0x0 libfoo _foo
+# CHECK-NEXT: __DATA __data 0x100001020 0xC00FFFFF00000002 bind 0xFFFF true DB 0x10 libfoo _foo
+# CHECK-NEXT: __DATA __data 0x100001028 0xC008000100000001 bind 0x0001 false IA 0xFFFFFFFFFFFFFFFC libfoo _foo
+# ARM64E-NEXT: __DATA __data 0x100001030 0x00080001000003B4 rebase 0x1000003B4
+# USERLAND24-NEXT: __DATA __data 0x100001030 0x00080000000003B4 rebase 0x1000003B4
+# CHECK-NEXT: __DATA __data 0x100001038 0x4008000800000000 bind 0x8 libfoo _foo
+# ARM64E-NEXT: __DATA __data 0x100001040 0x0000900100001000 rebase 0x1200000100001000
+# USERLAND24-NEXT: __DATA __data 0x100001040 0x0000900000001000 rebase 0x1200000100001000
+# CHECK-NOT: {{.}}
+
+## The YAML below is the obj2yaml output, with LC_UUID zeroed, of an image
+## that Xcode 27's ld (ld-27037.1) linked from the following files. MINOS
+## selects the deployment target that makes the linker choose each format,
+## FORMAT is the pointer_format, and TARGET_HI is bits 32-39 of the two
+## unauthenticated rebases at 0x100001030 and 0x100001040, which hold the
+## 0x100000000 image base only in DYLD_CHAINED_PTR_ARM64E.
+##
+## --- foo.s:
+## .globl _foo
+## _foo:
+## ret
+##
+## --- chained-fixups-arm64e.s:
+## .globl _main
+## .p2align 2
+## _main:
+## ret
+## _local:
+## ret
+##
+## .data
+## .p2align 3
+## _target:
+## .quad 0
+## .quad _local at AUTH(ia,0)
+## .quad (_local + 8)@AUTH(ib,0x1234,addr)
+## .quad _foo at AUTH(da,42)
+## .quad (_foo + 16)@AUTH(db,0xffff,addr)
+## .quad (_foo - 4)@AUTH(ia,1)
+## .quad _local
+## .quad _foo + 8
+## .quad _target + 0x1200000000000000
+##
+## $ clang -target arm64e-apple-macos11.0 -c foo.s
+## $ ld -arch arm64e -platform_version macos 11.0 27.0 -lSystem -dylib \
+## -install_name @executable_path/libfoo.dylib foo.o -o libfoo.dylib
+## $ clang -target arm64e-apple-macos11.0 -c chained-fixups-arm64e.s
+## $ ld -arch arm64e -platform_version macos 11.0 27.0 -lSystem -segalign 0x1000 \
+## chained-fixups-arm64e.o libfoo.dylib -o chained-fixups-arm64e
+## $ ld -arch arm64e -platform_version macos 13.0 27.0 -lSystem -segalign 0x1000 \
+## chained-fixups-arm64e.o libfoo.dylib -o chained-fixups-arm64e-userland24
+## $ obj2yaml chained-fixups-arm64e
+
+--- !mach-o
+FileHeader:
+ magic: 0xFEEDFACF
+ cputype: 0x100000C
+ cpusubtype: 0x81000002
+ filetype: 0x2
+ ncmds: 18
+ sizeofcmds: 872
+ flags: 0x200085
+ reserved: 0x0
+LoadCommands:
+ - cmd: LC_SEGMENT_64
+ cmdsize: 72
+ segname: __PAGEZERO
+ vmaddr: 0
+ vmsize: 4294967296
+ fileoff: 0
+ filesize: 0
+ maxprot: 0
+ initprot: 0
+ nsects: 0
+ flags: 0
+ - cmd: LC_SEGMENT_64
+ cmdsize: 152
+ segname: __TEXT
+ vmaddr: 4294967296
+ vmsize: 4096
+ fileoff: 0
+ filesize: 4096
+ maxprot: 5
+ initprot: 5
+ nsects: 1
+ flags: 0
+ Sections:
+ - sectname: __text
+ segname: __TEXT
+ addr: 0x1000003B0
+ size: 8
+ offset: 0x3B0
+ align: 2
+ reloff: 0x0
+ nreloc: 0
+ flags: 0x80000400
+ reserved1: 0x0
+ reserved2: 0x0
+ reserved3: 0x0
+ content: C0035FD6C0035FD6
+ - cmd: LC_SEGMENT_64
+ cmdsize: 152
+ segname: __DATA
+ vmaddr: 4294971392
+ vmsize: 4096
+ fileoff: 4096
+ filesize: 4096
+ maxprot: 3
+ initprot: 3
+ nsects: 1
+ flags: 0
+ Sections:
+ - sectname: __data
+ segname: __DATA
+ addr: 0x100001000
+ size: 72
+ offset: 0x1000
+ align: 3
+ reloff: 0x0
+ nreloc: 0
+ flags: 0x0
+ reserved1: 0x0
+ reserved2: 0x0
+ reserved3: 0x0
+ content: 0000000000000000B403000000000880BC03000034120B80000000002A000CC002000000FFFF0FC001000000010008C0B4030000[[TARGET_HI]]000800000000000800084000100000[[TARGET_HI]]900000
+ - cmd: LC_SEGMENT_64
+ cmdsize: 72
+ segname: __LINKEDIT
+ vmaddr: 4294975488
+ vmsize: 4096
+ fileoff: 8192
+ filesize: 536
+ maxprot: 1
+ initprot: 1
+ nsects: 0
+ flags: 0
+ - cmd: LC_DYLD_CHAINED_FIXUPS
+ cmdsize: 16
+ dataoff: 8192
+ datasize: 120
+ - cmd: LC_DYLD_EXPORTS_TRIE
+ cmdsize: 16
+ dataoff: 8312
+ datasize: 48
+ - cmd: LC_SYMTAB
+ cmdsize: 24
+ symoff: 8368
+ nsyms: 5
+ stroff: 8448
+ strsize: 48
+ - cmd: LC_DYSYMTAB
+ cmdsize: 80
+ ilocalsym: 0
+ nlocalsym: 2
+ iextdefsym: 2
+ nextdefsym: 2
+ iundefsym: 4
+ nundefsym: 1
+ tocoff: 0
+ ntoc: 0
+ modtaboff: 0
+ nmodtab: 0
+ extrefsymoff: 0
+ nextrefsyms: 0
+ indirectsymoff: 0
+ nindirectsyms: 0
+ extreloff: 0
+ nextrel: 0
+ locreloff: 0
+ nlocrel: 0
+ - cmd: LC_LOAD_DYLINKER
+ cmdsize: 32
+ name: 12
+ Content: '/usr/lib/dyld'
+ ZeroPadBytes: 7
+ - cmd: LC_UUID
+ cmdsize: 24
+ uuid: 00000000-0000-0000-0000-000000000000
+ - cmd: LC_BUILD_VERSION
+ cmdsize: 32
+ platform: 1
+ minos: [[MINOS]]
+ sdk: 1769472
+ ntools: 1
+ Tools:
+ - tool: 3
+ version: 1771897088
+ - cmd: LC_SOURCE_VERSION
+ cmdsize: 16
+ version: 0
+ - cmd: LC_MAIN
+ cmdsize: 24
+ entryoff: 944
+ stacksize: 0
+ - cmd: LC_LOAD_DYLIB
+ cmdsize: 56
+ dylib:
+ name: 24
+ timestamp: 2
+ current_version: 89063424
+ compatibility_version: 65536
+ Content: '/usr/lib/libSystem.B.dylib'
+ ZeroPadBytes: 6
+ - cmd: LC_LOAD_DYLIB
+ cmdsize: 56
+ dylib:
+ name: 24
+ timestamp: 2
+ current_version: 0
+ compatibility_version: 0
+ Content: '@executable_path/libfoo.dylib'
+ ZeroPadBytes: 3
+ - cmd: LC_FUNCTION_STARTS
+ cmdsize: 16
+ dataoff: 8360
+ datasize: 8
+ - cmd: LC_DATA_IN_CODE
+ cmdsize: 16
+ dataoff: 8368
+ datasize: 0
+ - cmd: LC_CODE_SIGNATURE
+ cmdsize: 16
+ dataoff: 8496
+ datasize: 232
+LinkEditData:
+ ExportTrie:
+ TerminalSize: 0
+ NodeOffset: 0
+ Name: ''
+ Flags: 0x0
+ Address: 0x0
+ Other: 0x0
+ ImportName: ''
+ Children:
+ - TerminalSize: 0
+ NodeOffset: 18
+ Name: _
+ Flags: 0x0
+ Address: 0x0
+ Other: 0x0
+ ImportName: ''
+ Children:
+ - TerminalSize: 2
+ NodeOffset: 9
+ Name: _mh_execute_header
+ Flags: 0x0
+ Address: 0x0
+ Other: 0x0
+ ImportName: ''
+ - TerminalSize: 3
+ NodeOffset: 13
+ Name: main
+ Flags: 0x0
+ Address: 0x3B0
+ Other: 0x0
+ ImportName: ''
+ NameList:
+ - n_strx: 33
+ n_type: 0xE
+ n_sect: 1
+ n_desc: 0
+ n_value: 4294968244
+ - n_strx: 40
+ n_type: 0xE
+ n_sect: 2
+ n_desc: 0
+ n_value: 4294971392
+ - n_strx: 2
+ n_type: 0xF
+ n_sect: 1
+ n_desc: 16
+ n_value: 4294967296
+ - n_strx: 22
+ n_type: 0xF
+ n_sect: 1
+ n_desc: 0
+ n_value: 4294968240
+ - n_strx: 28
+ n_type: 0x1
+ n_sect: 0
+ n_desc: 512
+ n_value: 0
+ StringTable:
+ - ' '
+ - __mh_execute_header
+ - _main
+ - _foo
+ - _local
+ - _target
+ FunctionStarts: [ 0x3B0, 0x3B4 ]
+ ChainedFixups: [ 0x0, 0x0, 0x0, 0x0, 0x20, 0x0, 0x0, 0x0, 0x50, 0x0,
+ 0x0, 0x0, 0x68, 0x0, 0x0, 0x0, 0x3, 0x0, 0x0, 0x0,
+ 0x2, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x18, 0x0, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0x0, 0x0, 0x0,
+ 0x0, 0x10, [[FORMAT]], 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x0, 0x8, 0x0,
+ 0x2, 0x2, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2, 0xC,
+ 0x0, 0x0, 0xFC, 0xFF, 0xFF, 0xFF, 0x2, 0x16, 0x0,
+ 0x0, 0x10, 0x0, 0x0, 0x0, 0x0, 0x5F, 0x66, 0x6F, 0x6F,
+ 0x0, 0x5F, 0x66, 0x6F, 0x6F, 0x0, 0x5F, 0x66, 0x6F,
+ 0x6F, 0x0 ]
+...
diff --git a/llvm/tools/llvm-objdump/MachODump.cpp b/llvm/tools/llvm-objdump/MachODump.cpp
index 40b4b52198407..b10471e6e652b 100644
--- a/llvm/tools/llvm-objdump/MachODump.cpp
+++ b/llvm/tools/llvm-objdump/MachODump.cpp
@@ -1366,6 +1366,8 @@ static void PrintDyldInfo(MachOObjectFile *O) {
auto HexLength = [](uint64_t Num) {
return Num ? (size_t)divideCeil(Log2_64(Num), 4) : 1;
};
+ // arm64e images get columns for the signing schema of authenticated fixups.
+ bool HasAuthColumns = false;
for (const object::MachOChainedFixupEntry &Entry : O->fixupTable(Err)) {
SegmentWidth = std::max(SegmentWidth, Entry.segmentName().size());
SectionWidth = std::max(SectionWidth, Entry.sectionName().size());
@@ -1374,6 +1376,9 @@ static void PrintDyldInfo(MachOObjectFile *O) {
AddendWidth = std::max(AddendWidth, HexLength(Entry.addend()) + 2);
DylibWidth = std::max(DylibWidth, Entry.symbolName().size());
}
+ HasAuthColumns |=
+ Entry.pointerFormat() == MachO::DYLD_CHAINED_PTR_ARM64E ||
+ Entry.pointerFormat() == MachO::DYLD_CHAINED_PTR_ARM64E_USERLAND24;
}
// Errors will be handled when printing the table.
if (Err)
@@ -1383,17 +1388,27 @@ static void PrintDyldInfo(MachOObjectFile *O) {
outs() << left_justify("segment", SegmentWidth) << ' '
<< left_justify("section", SectionWidth) << ' '
<< left_justify("address", AddressWidth) << ' '
- << left_justify("pointer", PointerWidth) << " type "
- << left_justify("addend", AddendWidth) << ' '
+ << left_justify("pointer", PointerWidth) << " type ";
+ if (HasAuthColumns)
+ outs() << "div addr key ";
+ outs() << left_justify("addend", AddendWidth) << ' '
<< left_justify("dylib", DylibWidth) << " symbol/vm address\n";
for (const object::MachOChainedFixupEntry &Entry : O->fixupTable(Err)) {
outs() << left_justify(Entry.segmentName(), SegmentWidth) << ' '
<< left_justify(Entry.sectionName(), SectionWidth) << ' ' << "0x"
<< left_justify(utohexstr(Entry.address()), AddressWidth - 2) << ' '
<< format_hex(Entry.rawValue(), PointerWidth, true) << ' ';
+ outs() << (Entry.isBind() ? "bind " : "rebase ");
+ if (HasAuthColumns && Entry.isAuthenticated()) {
+ static const char *const KeyNames[] = {"IA", "IB", "DA", "DB"};
+ outs() << format("0x%04X ", Entry.diversity())
+ << left_justify(Entry.hasAddressDiversity() ? "true" : "false", 5)
+ << ' ' << left_justify(KeyNames[Entry.key()], 3) << ' ';
+ } else if (HasAuthColumns) {
+ outs().indent(17);
+ }
if (Entry.isBind()) {
- outs() << "bind "
- << "0x" << left_justify(utohexstr(Entry.addend()), AddendWidth - 2)
+ outs() << "0x" << left_justify(utohexstr(Entry.addend()), AddendWidth - 2)
<< ' ' << left_justify(ordinalName(O, Entry.ordinal()), DylibWidth)
<< ' ' << Entry.symbolName();
if (Entry.flags() & MachO::BIND_SYMBOL_FLAGS_WEAK_IMPORT)
@@ -1401,8 +1416,7 @@ static void PrintDyldInfo(MachOObjectFile *O) {
outs() << '\n';
} else {
assert(Entry.isRebase());
- outs() << "rebase";
- outs().indent(AddendWidth + DylibWidth + 2);
+ outs().indent(AddendWidth + DylibWidth + 1);
outs() << format("0x%" PRIX64, Entry.pointerValue()) << '\n';
}
}
More information about the llvm-branch-commits
mailing list