parse LC_DYLD_FIXUPS_CHAINS
This commit is contained in:
parent
b73650258b
commit
7592cfd2dd
@ -1,10 +1,12 @@
|
|||||||
package macho
|
package macho
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bufio"
|
|
||||||
"bytes"
|
"bytes"
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"unsafe"
|
||||||
|
// "bufio"
|
||||||
|
"io"
|
||||||
|
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
|
|
||||||
@ -12,6 +14,9 @@ import (
|
|||||||
. "ios-wrapper/pkg/leb128"
|
. "ios-wrapper/pkg/leb128"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
//#include "fixups.h"
|
||||||
|
import "C"
|
||||||
|
|
||||||
type ImportSymbol struct {
|
type ImportSymbol struct {
|
||||||
name string
|
name string
|
||||||
typ string
|
typ string
|
||||||
@ -58,6 +63,15 @@ func (mc *MachoContext) CollectBindSymbols() []*ImportSymbol {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (mc *MachoContext) findSegmentIndexAt(address uint64) int {
|
||||||
|
for i, segment := range mc.Segments() {
|
||||||
|
if segment.Fileoff() <= address && segment.Fileoff() + segment.Filesize() > address {
|
||||||
|
return i
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
|
||||||
// New convention using LC_DYLD_CHAINED_FIXUPS
|
// New convention using LC_DYLD_CHAINED_FIXUPS
|
||||||
func (mc *MachoContext) CollectBindSymbolsModern() []*ImportSymbol {
|
func (mc *MachoContext) CollectBindSymbolsModern() []*ImportSymbol {
|
||||||
var buf []byte
|
var buf []byte
|
||||||
@ -70,30 +84,83 @@ func (mc *MachoContext) CollectBindSymbolsModern() []*ImportSymbol {
|
|||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
r := bytes.NewReader(buf)
|
// all pointers used are based from this **buf**
|
||||||
rr := bufio.NewReader(r)
|
// until buf is freed, all pointers are valid
|
||||||
|
// remember to copy before moving out
|
||||||
|
header := (*C.uchar)(unsafe.Pointer(&buf[0]))
|
||||||
|
imports_table := C.GetImportsTable(header);
|
||||||
|
|
||||||
var fixups_version int32
|
// for i := 0; i < int(imports_table.size); i++ {
|
||||||
var starts_offset int32
|
// s := C.GetImportsAt(&imports_table, C.int(i))
|
||||||
var imports_offset int32
|
// name := C.GoString(s.name)
|
||||||
var symbols_offset int32
|
// symbol.dylib := string(mc.dylibs[int(s.lib_ordinal)-1].name[:])
|
||||||
var imports_count int32
|
// symbol_table = append(symbol_table, symbol)
|
||||||
var imports_format int32
|
// fmt.Printf("id=%d lib=%s name=%s\n", i, dylib, name)
|
||||||
var symbols_format int32
|
// }
|
||||||
binary.Read(rr, mc.byteorder, &fixups_version)
|
|
||||||
binary.Read(rr, mc.byteorder, &starts_offset)
|
|
||||||
binary.Read(rr, mc.byteorder, &imports_offset)
|
|
||||||
binary.Read(rr, mc.byteorder, &symbols_offset)
|
|
||||||
binary.Read(rr, mc.byteorder, &imports_count)
|
|
||||||
binary.Read(rr, mc.byteorder, &imports_format)
|
|
||||||
binary.Read(rr, mc.byteorder, &symbols_format)
|
|
||||||
fmt.Printf(
|
|
||||||
"HMMGE %x %x\n",
|
|
||||||
imports_offset,
|
|
||||||
imports_count,
|
|
||||||
)
|
|
||||||
|
|
||||||
return []*ImportSymbol{}
|
var syms []*ImportSymbol
|
||||||
|
var sym ImportSymbol
|
||||||
|
|
||||||
|
segment_i := 0
|
||||||
|
for {
|
||||||
|
var fix C.struct_SegmentFix
|
||||||
|
fix_ptr := (*C.struct_SegmentFix)(unsafe.Pointer(&fix))
|
||||||
|
status := int(C.GetSegmentFixAt(header, C.uint(segment_i), fix_ptr))
|
||||||
|
segment_i += 1
|
||||||
|
if status == 2 {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if status == 3 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
// fmt.Printf("segment=%x format=%x page_count=%d\n", fix.segment, fix.format, fix.page_count)
|
||||||
|
// fmt.Printf("pages=%x\n", fix.pages)
|
||||||
|
pages := ([]C.ushort)(unsafe.Slice(fix.pages, fix.page_count))
|
||||||
|
for page_i := 0; page_i < int(fix.page_count); page_i++ {
|
||||||
|
// fmt.Printf(" page offset=%x\n", pages[page_i])
|
||||||
|
|
||||||
|
address := int64(fix.segment) + int64(pages[page_i])
|
||||||
|
mc.file.Seek(address, io.SeekStart)
|
||||||
|
|
||||||
|
code := make([]byte, 8)
|
||||||
|
|
||||||
|
for {
|
||||||
|
mc.file.Read(code)
|
||||||
|
v := binary.LittleEndian.Uint64(code)
|
||||||
|
|
||||||
|
var bind C.int
|
||||||
|
var ret1 C.ulonglong
|
||||||
|
var ret2 C.ulonglong
|
||||||
|
next := C.ParseFixValue(C.int(fix.format), C.ulonglong(v),
|
||||||
|
&bind, &ret1, &ret2)
|
||||||
|
|
||||||
|
if bind == 1 {
|
||||||
|
s := C.GetImportsAt(&imports_table, C.int(ret1))
|
||||||
|
name := C.GoString(s.name)
|
||||||
|
dylib := string(mc.dylibs[int(s.lib_ordinal)-1].name[:])
|
||||||
|
|
||||||
|
// fmt.Printf("%x bind=%d (%s)%s\n", address, bind, dylib, name)
|
||||||
|
|
||||||
|
sym.address = uint64(address)
|
||||||
|
sym.name = name
|
||||||
|
sym.dylib = dylib
|
||||||
|
sym.typ = "lazy"
|
||||||
|
|
||||||
|
sym.segment = uint32(mc.findSegmentIndexAt(uint64(address)))
|
||||||
|
sym.file_address = uint64(address)
|
||||||
|
new_sym := sym
|
||||||
|
syms = append(syms, &new_sym)
|
||||||
|
}
|
||||||
|
|
||||||
|
address += 8
|
||||||
|
if int(next) == 0 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mc.file.Seek(0, io.SeekStart)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return syms
|
||||||
}
|
}
|
||||||
|
|
||||||
// Old convention using LC_DYLD_INFO_ONLY section and bytecode runner
|
// Old convention using LC_DYLD_INFO_ONLY section and bytecode runner
|
||||||
|
125
macho-go/pkg/ios/macho/fixups.c
Normal file
125
macho-go/pkg/ios/macho/fixups.c
Normal file
@ -0,0 +1,125 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include "fixups.h"
|
||||||
|
#include "fixups_type.h"
|
||||||
|
|
||||||
|
struct ImportTable GetImportsTable(uint8_t* header_ptr) {
|
||||||
|
struct dyld_chained_fixups_header* header = (struct dyld_chained_fixups_header*)header_ptr;
|
||||||
|
|
||||||
|
char* symbols_table = (char*)(header_ptr + header->symbols_offset);
|
||||||
|
struct dyld_chained_import* imports_table = (struct dyld_chained_import*)(header_ptr + header->imports_offset);
|
||||||
|
|
||||||
|
struct ImportTable table = {
|
||||||
|
(uint64_t)symbols_table,
|
||||||
|
(uint64_t)imports_table,
|
||||||
|
header->imports_count,
|
||||||
|
};
|
||||||
|
return table;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ImportSymbol GetImportsAt(struct ImportTable* table, int i) {
|
||||||
|
struct dyld_chained_import* imports_table = (struct dyld_chained_import*)table->imports_table;
|
||||||
|
struct dyld_chained_import import = imports_table[i];
|
||||||
|
char* name = (char*)table->symbols_table + import.name_offset;
|
||||||
|
struct ImportSymbol symbol = {
|
||||||
|
import.lib_ordinal,
|
||||||
|
name,
|
||||||
|
};
|
||||||
|
// printf("imports[%d]: (%d)%s\n", i, import.lib_ordinal, name);
|
||||||
|
return symbol;
|
||||||
|
}
|
||||||
|
|
||||||
|
int GetSegmentFixAt(uint8_t* buffer, uint32_t i, struct SegmentFix* fix) {
|
||||||
|
struct dyld_chained_fixups_header* header = (struct dyld_chained_fixups_header*)buffer;
|
||||||
|
struct dyld_chained_starts_in_image* segment = (struct dyld_chained_starts_in_image*)(buffer + header->starts_offset);
|
||||||
|
|
||||||
|
if (fix == 0) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if (i >= segment->seg_count) {
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
// printf("segment %d\n", i);
|
||||||
|
uint32_t offset = segment->seg_info_offset[i];
|
||||||
|
if (offset == 0) {
|
||||||
|
return 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct dyld_chained_starts_in_segment* chain_header = (struct dyld_chained_starts_in_segment*)((char*)segment + offset);
|
||||||
|
|
||||||
|
// printf("segment_offset=0x%llx\n", chain_header->segment_offset);
|
||||||
|
// printf("page count=0x%x\n", chain_header->page_count);
|
||||||
|
fix->segment = (uint64_t)(chain_header->segment_offset);
|
||||||
|
fix->format = chain_header->pointer_format;
|
||||||
|
fix->page_count = chain_header->page_count;
|
||||||
|
fix->pages = chain_header->page_start;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline int isBind(uint64_t value) {
|
||||||
|
struct dyld_chained_ptr_64_bind* b = (struct dyld_chained_ptr_64_bind*)&value;
|
||||||
|
return b->bind;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ParseFixValue(int format, uint64_t value, int* bind, uint64_t* ret1, uint64_t* ret2) {
|
||||||
|
switch (format) {
|
||||||
|
case DYLD_CHAINED_PTR_64:
|
||||||
|
case DYLD_CHAINED_PTR_64_OFFSET: {
|
||||||
|
if (isBind(value)) {
|
||||||
|
struct dyld_chained_ptr_64_bind* b = (struct dyld_chained_ptr_64_bind*)&value;
|
||||||
|
// printf("is bind\n");
|
||||||
|
// printf(" ordinal=%d", b->ordinal);
|
||||||
|
// printf(" addend=0x%x", b->addend);
|
||||||
|
// printf(" next=0x%x\n", b->next);
|
||||||
|
*ret1 = b->ordinal;
|
||||||
|
*ret2 = b->addend;
|
||||||
|
*bind = 1;
|
||||||
|
return b->next;
|
||||||
|
} else {
|
||||||
|
struct dyld_chained_ptr_64_rebase* b = (struct dyld_chained_ptr_64_rebase*)&value;
|
||||||
|
// printf("is rebase\n");
|
||||||
|
// printf(" target=0x%llx", b->target);
|
||||||
|
// printf(" high8=0x%x", b->high8);
|
||||||
|
// printf(" next=0x%x\n", b->next);
|
||||||
|
*ret1 = b->target;
|
||||||
|
*ret2 = b->high8;
|
||||||
|
*bind = 0;
|
||||||
|
return b->next;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ParseFixUps(uint8_t* buffer) {
|
||||||
|
struct dyld_chained_fixups_header* header = (struct dyld_chained_fixups_header*)buffer;
|
||||||
|
printf("starts=0x%x\n", header->starts_offset);
|
||||||
|
printf("imports start=0x%x\n", header->imports_offset);
|
||||||
|
printf("symbols start=0x%x\n", header->symbols_offset);
|
||||||
|
printf("imports count=0x%x\n", header->imports_count);
|
||||||
|
printf("imports format=0x%x\n", header->imports_format);
|
||||||
|
printf("symbols format=0x%x\n", header->symbols_format);
|
||||||
|
|
||||||
|
char* symbols_table = (char*)(buffer + header->symbols_offset);
|
||||||
|
struct dyld_chained_import* imports_table = (struct dyld_chained_import*)(buffer + header->imports_offset);
|
||||||
|
for (int i = 0; i < header->imports_count; i++) {
|
||||||
|
struct dyld_chained_import import = imports_table[i];
|
||||||
|
char* name = symbols_table + import.name_offset;
|
||||||
|
printf("(%d)%s\n", import.lib_ordinal, name);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct dyld_chained_starts_in_image* segment = (struct dyld_chained_starts_in_image*)(buffer + header->starts_offset);
|
||||||
|
|
||||||
|
for (int i = 0; i < segment->seg_count; i++) {
|
||||||
|
printf("segment %d\n", i);
|
||||||
|
uint32_t offset = segment->seg_info_offset[i];
|
||||||
|
if (offset == 0) continue;
|
||||||
|
struct dyld_chained_starts_in_segment* chain_header = (struct dyld_chained_starts_in_segment*)((char*)segment + offset);
|
||||||
|
|
||||||
|
printf("segment_offset=0x%llx\n", chain_header->segment_offset);
|
||||||
|
printf("page count=0x%x\n", chain_header->page_count);
|
||||||
|
}
|
||||||
|
}
|
33
macho-go/pkg/ios/macho/fixups.h
Normal file
33
macho-go/pkg/ios/macho/fixups.h
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
#ifndef _FIXUPS_
|
||||||
|
#define _FIXUPS_
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
// char* symbols_table
|
||||||
|
// struct dyld_chained_import* imports_table
|
||||||
|
//
|
||||||
|
// some conflicting with cgo if using void*
|
||||||
|
// so use uint64_t as abstraction
|
||||||
|
struct ImportTable {
|
||||||
|
uint64_t symbols_table;
|
||||||
|
uint64_t imports_table;
|
||||||
|
uint32_t size;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ImportSymbol {
|
||||||
|
int lib_ordinal;
|
||||||
|
char* name;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct SegmentFix {
|
||||||
|
uint64_t segment;
|
||||||
|
uint32_t format;
|
||||||
|
uint32_t page_count;
|
||||||
|
uint16_t* pages;
|
||||||
|
};
|
||||||
|
|
||||||
|
void ParseFixUps(uint8_t* raw);
|
||||||
|
struct ImportTable GetImportsTable(uint8_t* header_ptr);
|
||||||
|
struct ImportSymbol GetImportsAt(struct ImportTable* table, int i);
|
||||||
|
int GetSegmentFixAt(uint8_t* buffer, uint32_t i, struct SegmentFix* fix);
|
||||||
|
int ParseFixValue(int format, uint64_t value, int* bind, uint64_t* ret1, uint64_t* ret2);
|
||||||
|
#endif
|
256
macho-go/pkg/ios/macho/fixups_type.h
Normal file
256
macho-go/pkg/ios/macho/fixups_type.h
Normal file
@ -0,0 +1,256 @@
|
|||||||
|
/* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*-
|
||||||
|
*
|
||||||
|
* Copyright (c) 2018 Apple Inc. All rights reserved.
|
||||||
|
*
|
||||||
|
* @APPLE_LICENSE_HEADER_START@
|
||||||
|
*
|
||||||
|
* This file contains Original Code and/or Modifications of Original Code
|
||||||
|
* as defined in and that are subject to the Apple Public Source License
|
||||||
|
* Version 2.0 (the 'License'). You may not use this file except in
|
||||||
|
* compliance with the License. Please obtain a copy of the License at
|
||||||
|
* http://www.opensource.apple.com/apsl/ and read it before using this
|
||||||
|
* file.
|
||||||
|
*
|
||||||
|
* The Original Code and all software distributed under the License are
|
||||||
|
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
|
||||||
|
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
|
||||||
|
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
|
||||||
|
* Please see the License for the specific language governing rights and
|
||||||
|
* limitations under the License.
|
||||||
|
*
|
||||||
|
* @APPLE_LICENSE_HEADER_END@
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __MACH_O_FIXUP_CHAINS__
|
||||||
|
#define __MACH_O_FIXUP_CHAINS__ 5
|
||||||
|
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
|
||||||
|
//#define LC_DYLD_EXPORTS_TRIE 0x80000033 // used with linkedit_data_command
|
||||||
|
//#define LC_DYLD_CHAINED_FIXUPS 0x80000034 // used with linkedit_data_command, payload is dyld_chained_fixups_header
|
||||||
|
|
||||||
|
|
||||||
|
// header of the LC_DYLD_CHAINED_FIXUPS payload
|
||||||
|
struct dyld_chained_fixups_header
|
||||||
|
{
|
||||||
|
uint32_t fixups_version; // 0
|
||||||
|
uint32_t starts_offset; // offset of dyld_chained_starts_in_image in chain_data
|
||||||
|
uint32_t imports_offset; // offset of imports table in chain_data
|
||||||
|
uint32_t symbols_offset; // offset of symbol strings in chain_data
|
||||||
|
uint32_t imports_count; // number of imported symbol names
|
||||||
|
uint32_t imports_format; // DYLD_CHAINED_IMPORT*
|
||||||
|
uint32_t symbols_format; // 0 => uncompressed, 1 => zlib compressed
|
||||||
|
};
|
||||||
|
|
||||||
|
// This struct is embedded in LC_DYLD_CHAINED_FIXUPS payload
|
||||||
|
struct dyld_chained_starts_in_image
|
||||||
|
{
|
||||||
|
uint32_t seg_count;
|
||||||
|
uint32_t seg_info_offset[1]; // each entry is offset into this struct for that segment
|
||||||
|
// followed by pool of dyld_chain_starts_in_segment data
|
||||||
|
};
|
||||||
|
|
||||||
|
// This struct is embedded in dyld_chain_starts_in_image
|
||||||
|
// and passed down to the kernel for page-in linking
|
||||||
|
struct dyld_chained_starts_in_segment
|
||||||
|
{
|
||||||
|
uint32_t size; // size of this (amount kernel needs to copy)
|
||||||
|
uint16_t page_size; // 0x1000 or 0x4000
|
||||||
|
uint16_t pointer_format; // DYLD_CHAINED_PTR_*
|
||||||
|
uint64_t segment_offset; // offset in memory to start of segment
|
||||||
|
uint32_t max_valid_pointer; // for 32-bit OS, any value beyond this is not a pointer
|
||||||
|
uint16_t page_count; // how many pages are in array
|
||||||
|
uint16_t page_start[1]; // each entry is offset in each page of first element in chain
|
||||||
|
// or DYLD_CHAINED_PTR_START_NONE if no fixups on page
|
||||||
|
// uint16_t chain_starts[1]; // some 32-bit formats may require multiple starts per page.
|
||||||
|
// for those, if high bit is set in page_starts[], then it
|
||||||
|
// is index into chain_starts[] which is a list of starts
|
||||||
|
// the last of which has the high bit set
|
||||||
|
};
|
||||||
|
|
||||||
|
enum {
|
||||||
|
DYLD_CHAINED_PTR_START_NONE = 0xFFFF, // used in page_start[] to denote a page with no fixups
|
||||||
|
DYLD_CHAINED_PTR_START_MULTI = 0x8000, // used in page_start[] to denote a page which has multiple starts
|
||||||
|
DYLD_CHAINED_PTR_START_LAST = 0x8000, // used in chain_starts[] to denote last start in list for page
|
||||||
|
};
|
||||||
|
|
||||||
|
// This struct is embedded in __TEXT,__chain_starts section in firmware
|
||||||
|
struct dyld_chained_starts_offsets
|
||||||
|
{
|
||||||
|
uint32_t pointer_format; // DYLD_CHAINED_PTR_32_FIRMWARE
|
||||||
|
uint32_t starts_count; // number of starts in array
|
||||||
|
uint32_t chain_starts[1]; // array chain start offsets
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// values for dyld_chained_starts_in_segment.pointer_format
|
||||||
|
enum {
|
||||||
|
DYLD_CHAINED_PTR_ARM64E = 1, // stride 8, unauth target is vmaddr
|
||||||
|
DYLD_CHAINED_PTR_64 = 2, // target is vmaddr
|
||||||
|
DYLD_CHAINED_PTR_32 = 3,
|
||||||
|
DYLD_CHAINED_PTR_32_CACHE = 4,
|
||||||
|
DYLD_CHAINED_PTR_32_FIRMWARE = 5,
|
||||||
|
DYLD_CHAINED_PTR_64_OFFSET = 6, // target is vm offset
|
||||||
|
DYLD_CHAINED_PTR_ARM64E_OFFSET = 7, // old name
|
||||||
|
DYLD_CHAINED_PTR_ARM64E_KERNEL = 7, // stride 4, unauth target is vm offset
|
||||||
|
DYLD_CHAINED_PTR_64_KERNEL_CACHE = 8,
|
||||||
|
DYLD_CHAINED_PTR_ARM64E_USERLAND = 9, // stride 8, unauth target is vm offset
|
||||||
|
DYLD_CHAINED_PTR_ARM64E_FIRMWARE = 10, // stride 4, unauth target is vmaddr
|
||||||
|
DYLD_CHAINED_PTR_X86_64_KERNEL_CACHE = 11, // stride 1, x86_64 kernel caches
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// DYLD_CHAINED_PTR_ARM64E
|
||||||
|
struct dyld_chained_ptr_arm64e_rebase
|
||||||
|
{
|
||||||
|
uint64_t target : 43,
|
||||||
|
high8 : 8,
|
||||||
|
next : 11, // 4 or 8-byte stide
|
||||||
|
bind : 1, // == 0
|
||||||
|
auth : 1; // == 0
|
||||||
|
};
|
||||||
|
|
||||||
|
// DYLD_CHAINED_PTR_ARM64E
|
||||||
|
struct dyld_chained_ptr_arm64e_bind
|
||||||
|
{
|
||||||
|
uint64_t ordinal : 16,
|
||||||
|
zero : 16,
|
||||||
|
addend : 19, // +/-256K
|
||||||
|
next : 11, // 4 or 8-byte stide
|
||||||
|
bind : 1, // == 1
|
||||||
|
auth : 1; // == 0
|
||||||
|
};
|
||||||
|
|
||||||
|
// DYLD_CHAINED_PTR_ARM64E
|
||||||
|
struct dyld_chained_ptr_arm64e_auth_rebase
|
||||||
|
{
|
||||||
|
uint64_t target : 32, // runtimeOffset
|
||||||
|
diversity : 16,
|
||||||
|
addrDiv : 1,
|
||||||
|
key : 2,
|
||||||
|
next : 11, // 4 or 8-byte stide
|
||||||
|
bind : 1, // == 0
|
||||||
|
auth : 1; // == 1
|
||||||
|
};
|
||||||
|
|
||||||
|
// DYLD_CHAINED_PTR_ARM64E
|
||||||
|
struct dyld_chained_ptr_arm64e_auth_bind
|
||||||
|
{
|
||||||
|
uint64_t ordinal : 16,
|
||||||
|
zero : 16,
|
||||||
|
diversity : 16,
|
||||||
|
addrDiv : 1,
|
||||||
|
key : 2,
|
||||||
|
next : 11, // 4 or 8-byte stide
|
||||||
|
bind : 1, // == 1
|
||||||
|
auth : 1; // == 1
|
||||||
|
};
|
||||||
|
|
||||||
|
// DYLD_CHAINED_PTR_64/DYLD_CHAINED_PTR_64_OFFSET
|
||||||
|
struct dyld_chained_ptr_64_rebase
|
||||||
|
{
|
||||||
|
uint64_t target : 36, // 64GB max image size (DYLD_CHAINED_PTR_64 => vmAddr, DYLD_CHAINED_PTR_64_OFFSET => runtimeOffset)
|
||||||
|
high8 : 8, // top 8 bits set to this (DYLD_CHAINED_PTR_64 => after slide added, DYLD_CHAINED_PTR_64_OFFSET => before slide added)
|
||||||
|
reserved : 7, // all zeros
|
||||||
|
next : 12, // 4-byte stride
|
||||||
|
bind : 1; // == 0
|
||||||
|
};
|
||||||
|
|
||||||
|
// DYLD_CHAINED_PTR_64
|
||||||
|
struct dyld_chained_ptr_64_bind
|
||||||
|
{
|
||||||
|
uint64_t ordinal : 24,
|
||||||
|
addend : 8, // 0 thru 255
|
||||||
|
reserved : 19, // all zeros
|
||||||
|
next : 12, // 4-byte stride
|
||||||
|
bind : 1; // == 1
|
||||||
|
};
|
||||||
|
|
||||||
|
// DYLD_CHAINED_PTR_64_KERNEL_CACHE, DYLD_CHAINED_PTR_X86_64_KERNEL_CACHE
|
||||||
|
struct dyld_chained_ptr_64_kernel_cache_rebase
|
||||||
|
{
|
||||||
|
uint64_t target : 30, // basePointers[cacheLevel] + target
|
||||||
|
cacheLevel : 2, // what level of cache to bind to (indexes a mach_header array)
|
||||||
|
diversity : 16,
|
||||||
|
addrDiv : 1,
|
||||||
|
key : 2,
|
||||||
|
next : 12, // 1 or 4-byte stide
|
||||||
|
isAuth : 1; // 0 -> not authenticated. 1 -> authenticated
|
||||||
|
};
|
||||||
|
|
||||||
|
// DYLD_CHAINED_PTR_32
|
||||||
|
// Note: for DYLD_CHAINED_PTR_32 some non-pointer values are co-opted into the chain
|
||||||
|
// as out of range rebases. If an entry in the chain is > max_valid_pointer, then it
|
||||||
|
// is not a pointer. To restore the value, subtract off the bias, which is
|
||||||
|
// (64MB+max_valid_pointer)/2.
|
||||||
|
struct dyld_chained_ptr_32_rebase
|
||||||
|
{
|
||||||
|
uint32_t target : 26, // vmaddr, 64MB max image size
|
||||||
|
next : 5, // 4-byte stride
|
||||||
|
bind : 1; // == 0
|
||||||
|
};
|
||||||
|
|
||||||
|
// DYLD_CHAINED_PTR_32
|
||||||
|
struct dyld_chained_ptr_32_bind
|
||||||
|
{
|
||||||
|
uint32_t ordinal : 20,
|
||||||
|
addend : 6, // 0 thru 63
|
||||||
|
next : 5, // 4-byte stride
|
||||||
|
bind : 1; // == 1
|
||||||
|
};
|
||||||
|
|
||||||
|
// DYLD_CHAINED_PTR_32_CACHE
|
||||||
|
struct dyld_chained_ptr_32_cache_rebase
|
||||||
|
{
|
||||||
|
uint32_t target : 30, // 1GB max dyld cache TEXT and DATA
|
||||||
|
next : 2; // 4-byte stride
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// DYLD_CHAINED_PTR_32_FIRMWARE
|
||||||
|
struct dyld_chained_ptr_32_firmware_rebase
|
||||||
|
{
|
||||||
|
uint32_t target : 26, // 64MB max firmware TEXT and DATA
|
||||||
|
next : 6; // 4-byte stride
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// values for dyld_chained_fixups_header.imports_format
|
||||||
|
enum {
|
||||||
|
DYLD_CHAINED_IMPORT = 1,
|
||||||
|
DYLD_CHAINED_IMPORT_ADDEND = 2,
|
||||||
|
DYLD_CHAINED_IMPORT_ADDEND64 = 3,
|
||||||
|
};
|
||||||
|
|
||||||
|
// DYLD_CHAINED_IMPORT
|
||||||
|
struct dyld_chained_import
|
||||||
|
{
|
||||||
|
uint32_t lib_ordinal : 8,
|
||||||
|
weak_import : 1,
|
||||||
|
name_offset : 23;
|
||||||
|
};
|
||||||
|
|
||||||
|
// DYLD_CHAINED_IMPORT_ADDEND
|
||||||
|
struct dyld_chained_import_addend
|
||||||
|
{
|
||||||
|
uint32_t lib_ordinal : 8,
|
||||||
|
weak_import : 1,
|
||||||
|
name_offset : 23;
|
||||||
|
int32_t addend;
|
||||||
|
};
|
||||||
|
|
||||||
|
// DYLD_CHAINED_IMPORT_ADDEND64
|
||||||
|
struct dyld_chained_import_addend64
|
||||||
|
{
|
||||||
|
uint64_t lib_ordinal : 16,
|
||||||
|
weak_import : 1,
|
||||||
|
reserved : 15,
|
||||||
|
name_offset : 32;
|
||||||
|
uint64_t addend;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // __MACH_O_FIXUP_CHAINS__
|
Loading…
Reference in New Issue
Block a user