mirror of
https://github.com/blacktop/ipsw.git
synced 2026-06-07 12:27:36 +00:00
Refactor string concatenation to use strings.Builder for improved performance in multiple files
570 lines
18 KiB
Go
570 lines
18 KiB
Go
package dyld
|
|
|
|
import (
|
|
"bytes"
|
|
"encoding/binary"
|
|
"fmt"
|
|
"sort"
|
|
"strings"
|
|
|
|
"github.com/blacktop/go-macho/types"
|
|
"github.com/blacktop/ipsw/pkg/table"
|
|
"github.com/dustin/go-humanize"
|
|
)
|
|
|
|
func (dch CacheHeader) String() string {
|
|
var magicBytes []byte = dch.Magic[:]
|
|
|
|
return fmt.Sprintf(
|
|
"Magic = %s\n"+
|
|
"MappingOffset = %08X\n"+
|
|
"MappingCount = %d\n"+
|
|
"ImagesOffset = %08X\n"+
|
|
"ImagesCount = %d\n"+
|
|
"DyldBaseAddress = %08X\n"+
|
|
"CodeSignatureOffset = %08X\n"+
|
|
"CodeSignatureSize = %08X\n"+
|
|
"SlideInfoOffset = %08X\n"+
|
|
"SlideInfoSize = %08X\n"+
|
|
"LocalSymbolsOffset = %08X\n"+
|
|
"LocalSymbolsSize = %08X\n"+
|
|
"UUID = %s\n"+
|
|
"Platform = %s\n"+
|
|
"Format = %d\n",
|
|
bytes.Trim(magicBytes, "\x00"),
|
|
dch.MappingOffset,
|
|
dch.MappingCount,
|
|
dch.ImagesOffsetOld,
|
|
dch.ImagesCountOld,
|
|
dch.DyldBaseAddress,
|
|
dch.CodeSignatureOffset,
|
|
dch.CodeSignatureSize,
|
|
dch.SlideInfoOffsetUnused,
|
|
dch.SlideInfoSizeUnused,
|
|
dch.LocalSymbolsOffset,
|
|
dch.LocalSymbolsSize,
|
|
dch.UUID.String(),
|
|
dch.Platform.String(),
|
|
dch.FormatVersion.Version(),
|
|
)
|
|
}
|
|
|
|
func (m *CacheMapping) String() string {
|
|
return fmt.Sprintf(
|
|
"Name = %s\n"+
|
|
"Address = %#x\n"+
|
|
"Size = %s\n"+
|
|
"FileOffset = %#x\n"+
|
|
"MaxProt = %s\n"+
|
|
"InitProt = %s\n",
|
|
m.Name,
|
|
m.Address,
|
|
humanize.Bytes(m.Size),
|
|
m.FileOffset,
|
|
m.MaxProt.String(),
|
|
m.InitProt.String(),
|
|
)
|
|
}
|
|
|
|
func (c CacheImageInfo) String() string {
|
|
return fmt.Sprintf(
|
|
"Address = %016X\n"+
|
|
"ModTime = %016X\n"+
|
|
"Inode = %d\n"+
|
|
"PathFileOffset = %08X\n",
|
|
c.Address,
|
|
c.ModTime,
|
|
c.Inode,
|
|
c.PathFileOffset,
|
|
)
|
|
}
|
|
|
|
func (dch CacheHeader) Print() {
|
|
fmt.Println("Header")
|
|
fmt.Println("======")
|
|
fmt.Println(dch.String())
|
|
fmt.Printf("Slide Info: %4dKB, file offset: 0x%09X -> 0x%09X\n", dch.SlideInfoSizeUnused/1024, dch.SlideInfoOffsetUnused, dch.SlideInfoOffsetUnused+dch.SlideInfoSizeUnused)
|
|
fmt.Printf("Local Symbols: %3dMB, file offset: 0x%09X -> 0x%09X\n", dch.LocalSymbolsSize/(1024*1024), dch.LocalSymbolsOffset, dch.LocalSymbolsOffset+dch.LocalSymbolsSize)
|
|
fmt.Printf("Accelerate Tab: %3dKB, address: 0x%09X -> 0x%09X\n", dch.AccelerateInfoSizeUnusedOrDyldStartFuncAddr/1024, dch.AccelerateInfoAddrUnusedOrDyldAddr, dch.AccelerateInfoAddrUnusedOrDyldAddr+dch.AccelerateInfoSizeUnusedOrDyldStartFuncAddr)
|
|
fmt.Println()
|
|
}
|
|
|
|
func (l *localSymbolInfo) Print() {
|
|
fmt.Printf("Local symbols nlist array: %3dMB, file offset: 0x%09X -> 0x%09X\n", l.NListByteSize/(1024*1024), l.NListFileOffset, l.NListFileOffset+l.NListByteSize)
|
|
fmt.Printf("Local symbols string pool: %3dMB, file offset: 0x%09X -> 0x%09X\n", l.StringsSize/(1024*1024), l.StringsFileOffset, l.StringsFileOffset+l.StringsSize)
|
|
}
|
|
|
|
func (mappings cacheMappings) String() string {
|
|
tableString := &strings.Builder{}
|
|
|
|
mdata := [][]string{}
|
|
for _, mapping := range mappings {
|
|
mdata = append(mdata, []string{
|
|
mapping.Name,
|
|
mapping.InitProt.String(),
|
|
mapping.MaxProt.String(),
|
|
fmt.Sprintf("%d MB", mapping.Size/(1024*1024)),
|
|
// humanize.Bytes(mapping.Size),
|
|
fmt.Sprintf("%08X -> %08X", mapping.Address, mapping.Address+mapping.Size),
|
|
fmt.Sprintf("%08X -> %08X", mapping.FileOffset, mapping.FileOffset+mapping.Size),
|
|
})
|
|
}
|
|
tbl := table.NewStringBuilderTableWriter(tableString)
|
|
tbl.SetHeader([]string{"Seg", "InitProt", "MaxProt", "Size", "Address", "File Offset"})
|
|
tbl.SetBorders(nil)
|
|
tbl.SetCenterSeparator("|")
|
|
tbl.AppendBulk(mdata)
|
|
tbl.SetAlignment(1) // ALIGN_LEFT
|
|
tbl.Render()
|
|
|
|
return tableString.String()
|
|
}
|
|
|
|
func (mapping CacheMappingWithSlideInfo) String() string {
|
|
tableString := &strings.Builder{}
|
|
|
|
mdata := [][]string{}
|
|
|
|
slideInfoSize := fmt.Sprintf("%#08x -> %#08x", mapping.SlideInfoOffset, mapping.SlideInfoOffset+mapping.SlideInfoSize)
|
|
if mapping.SlideInfoSize == 0 {
|
|
slideInfoSize = fmt.Sprintf("%#08x", mapping.SlideInfoOffset)
|
|
}
|
|
|
|
mdata = append(mdata, []string{
|
|
mapping.Name,
|
|
mapping.InitProt.String(),
|
|
mapping.MaxProt.String(),
|
|
fmt.Sprintf("%#08x (%s)", mapping.Size, humanize.Bytes(mapping.Size)),
|
|
fmt.Sprintf("%#08x", mapping.Address),
|
|
fmt.Sprintf("%#08x", mapping.FileOffset),
|
|
slideInfoSize,
|
|
fmt.Sprintf("%d", mapping.Flags),
|
|
})
|
|
|
|
tbl := table.NewStringBuilderTableWriter(tableString)
|
|
tbl.SetHeader([]string{"Seg", "InitProt", "MaxProt", "Size", "Address", "File Offset", "Slide Info Offset", "Flags"})
|
|
tbl.SetBorders(nil)
|
|
tbl.SetCenterSeparator("|")
|
|
tbl.AppendBulk(mdata)
|
|
tbl.SetAlignment(1)
|
|
tbl.Render()
|
|
|
|
return tableString.String()
|
|
}
|
|
|
|
func (mappings cacheMappingsWithSlideInfo) String(slideVersion uint32, verbose bool) string {
|
|
tableString := &strings.Builder{}
|
|
|
|
mdata := [][]string{}
|
|
for _, mapping := range mappings {
|
|
mappingAddr := fmt.Sprintf("%#08x", mapping.Address)
|
|
mappingOff := fmt.Sprintf("%#08x", mapping.FileOffset)
|
|
mappingInitProt := mapping.InitProt.String()
|
|
mappingMaxProt := mapping.MaxProt.String()
|
|
mappingFlags := mapping.Flags.String()
|
|
if verbose {
|
|
mappingAddr = fmt.Sprintf("%#08x -> %#08x", mapping.Address, mapping.Address+mapping.Size)
|
|
mappingOff = fmt.Sprintf("%#08x -> %#08x", mapping.FileOffset, mapping.FileOffset+mapping.Size)
|
|
mappingInitProt += fmt.Sprintf(" (%d)", mapping.InitProt)
|
|
mappingMaxProt += fmt.Sprintf(" (%d)", mapping.MaxProt)
|
|
mappingFlags += fmt.Sprintf(" (%d)", mapping.Flags)
|
|
}
|
|
var slideInfoSize string
|
|
if mapping.SlideInfoSize > 0 {
|
|
slideInfoSize = fmt.Sprintf("%#08x -> %#08x", mapping.SlideInfoOffset, mapping.SlideInfoOffset+mapping.SlideInfoSize)
|
|
}
|
|
mdata = append(mdata, []string{
|
|
mapping.Name,
|
|
mappingInitProt,
|
|
mappingMaxProt,
|
|
fmt.Sprintf("%#08x (%s)", mapping.Size, humanize.Bytes(mapping.Size)),
|
|
mappingAddr,
|
|
mappingOff,
|
|
slideInfoSize,
|
|
mappingFlags,
|
|
})
|
|
}
|
|
tbl := table.NewStringBuilderTableWriter(tableString)
|
|
tbl.SetHeader([]string{"Seg", "InitProt", "MaxProt", "Size", "Address", "File Offset", fmt.Sprintf("Slide Info (v%d) Offset", slideVersion), "Flags"})
|
|
tbl.SetBorders(nil)
|
|
tbl.SetCenterSeparator("|")
|
|
tbl.AppendBulk(mdata)
|
|
tbl.SetAlignment(1)
|
|
tbl.Render()
|
|
|
|
return tableString.String()
|
|
}
|
|
|
|
func (images cacheImages) Print() {
|
|
fmt.Println("Images")
|
|
fmt.Println("======")
|
|
for idx, image := range images {
|
|
fmt.Printf("%d:\t%08x %s\n", idx+1, image.Info.Address, image.Name)
|
|
}
|
|
}
|
|
|
|
func (f *File) String(verbose bool) string {
|
|
var slideVersion uint32
|
|
|
|
if f.SlideInfo != nil {
|
|
slideVersion = f.SlideInfo.GetVersion()
|
|
}
|
|
|
|
return fmt.Sprintf(
|
|
"Header\n"+
|
|
"======\n"+
|
|
"Magic = \"%s\"\n"+
|
|
"Platform = %s\n"+
|
|
"%s"+ // alt platform
|
|
"%s"+ // os version
|
|
"%s"+ // alt os version
|
|
"%s"+ // format
|
|
"%s"+ // max slide
|
|
"%s"+ // image count
|
|
"%s\n"+ // sub cache info
|
|
"%s"+ // shared region
|
|
"%s"+ // local symbols
|
|
"%s"+ // image text info
|
|
"%s"+ // slideInfo
|
|
"%s"+ // branchPools
|
|
"%s"+ // accelerateInfo
|
|
"%s"+ // patch info
|
|
"%s"+ // progClosures
|
|
"%s"+ // progClosuresTrie
|
|
"%s"+ // prebuiltLoaderSet
|
|
"%s"+ // prebuiltLoaderSet pool
|
|
"%s"+ // dynamic config
|
|
"%s"+ // objcOpts
|
|
"%s"+ // swiftOpts
|
|
"%s"+ // dyld/_dyld_start addrs
|
|
"%s", // mappings
|
|
f.Headers[f.UUID].Magic.String(),
|
|
f.Headers[f.UUID].Platform,
|
|
f.getAltPlatform(f.UUID),
|
|
f.getOSVersion(f.UUID),
|
|
f.getAltOSVersion(f.UUID),
|
|
f.getFormatVersion(f.UUID),
|
|
f.getMaxSlide(f.UUID),
|
|
f.getImageCount(f.UUID),
|
|
f.getSubCacheCount(),
|
|
f.getSharedRegion(f.UUID),
|
|
f.getLocalSymbols(),
|
|
f.getImagesTextInfo(f.UUID),
|
|
f.getSlideInfo(f.UUID, slideVersion),
|
|
f.getBranchPools(f.UUID),
|
|
f.getAccelerateInfo(f.UUID),
|
|
f.getPatchInfo(f.UUID),
|
|
f.getProgClosures(f.UUID),
|
|
f.getProgClosuresTrie(f.UUID),
|
|
f.getPrebuiltLoaderSet(f.UUID),
|
|
f.getPrebuiltLoaderSetPool(f.UUID),
|
|
f.getDynamicConfig(f.UUID),
|
|
f.getObjcOpts(f.UUID),
|
|
f.getSwiftOpts(f.UUID),
|
|
f.getDyldInfo(f.UUID),
|
|
f.getMappings(slideVersion, verbose),
|
|
)
|
|
}
|
|
|
|
func (f *File) getFormatVersion(uuid types.UUID) string {
|
|
var output string
|
|
if f.Headers[uuid].FormatVersion > 0 {
|
|
output = fmt.Sprintf("Format = %s\n", f.Headers[uuid].FormatVersion.String())
|
|
}
|
|
return output
|
|
}
|
|
|
|
func (f *File) getOSVersion(uuid types.UUID) string {
|
|
var output string
|
|
if f.IsDyld4 && f.Headers[uuid].OsVersion > 0 {
|
|
output = fmt.Sprintf("OS Version = %s\n", f.Headers[uuid].OsVersion.String())
|
|
}
|
|
return output
|
|
}
|
|
func (f *File) getAltOSVersion(uuid types.UUID) string {
|
|
var output string
|
|
if f.IsDyld4 && f.Headers[uuid].AltOsVersion > 0 {
|
|
output = fmt.Sprintf("Alt OS Version = %s\n", f.Headers[uuid].AltOsVersion.String())
|
|
}
|
|
return output
|
|
}
|
|
func (f *File) getAltPlatform(uuid types.UUID) string {
|
|
var output string
|
|
if f.IsDyld4 && f.Headers[uuid].AltPlatform > 0 {
|
|
output = fmt.Sprintf("Alt Platform = %s\n", f.Headers[uuid].AltPlatform.String())
|
|
}
|
|
return output
|
|
}
|
|
|
|
func (f *File) getMaxSlide(uuid types.UUID) string {
|
|
var output string
|
|
if f.Headers[uuid].MaxSlide > 0 {
|
|
output = fmt.Sprintf("Max Slide = %s\n", f.Headers[uuid].MaxSlide)
|
|
}
|
|
return output
|
|
}
|
|
|
|
func (f *File) getImageCount(uuid types.UUID) string {
|
|
var output string
|
|
if f.Headers[uuid].ImagesCountOld > 0 {
|
|
output = fmt.Sprintf("Num Images = %d\n", f.Headers[uuid].ImagesCountOld)
|
|
} else {
|
|
output = fmt.Sprintf("Num Images = %d\n", f.Headers[uuid].ImagesCount)
|
|
}
|
|
return output
|
|
}
|
|
|
|
func (f *File) getSubCacheCount() string {
|
|
var output string
|
|
if f.IsDyld4 {
|
|
output = fmt.Sprintf("Num SubCaches = %d\n", f.Headers[f.UUID].SubCacheArrayCount)
|
|
}
|
|
return output
|
|
}
|
|
|
|
func (f *File) getLocalSymbols() string {
|
|
var output string
|
|
if f.LocalSymInfo.NListFileOffset > 0 && f.LocalSymInfo.StringsFileOffset > 0 {
|
|
output = fmt.Sprintf(
|
|
"Local Symbols (nlist array): %3dMB, offset: 0x%09X -> 0x%09X\n"+
|
|
"Local Symbols (string pool): %3dMB, offset: 0x%09X -> 0x%09X\n",
|
|
f.LocalSymInfo.NListByteSize/(1024*1024),
|
|
f.LocalSymInfo.NListFileOffset,
|
|
f.LocalSymInfo.NListFileOffset+f.LocalSymInfo.NListByteSize,
|
|
f.LocalSymInfo.StringsSize/(1024*1024),
|
|
f.LocalSymInfo.StringsFileOffset,
|
|
f.LocalSymInfo.StringsFileOffset+f.LocalSymInfo.StringsSize,
|
|
)
|
|
}
|
|
return output
|
|
}
|
|
|
|
func (f *File) getImagesTextInfo(uuid types.UUID) string {
|
|
var output string
|
|
imagesCount := f.Headers[uuid].ImagesCountOld
|
|
imageHumanSize := int(f.Headers[uuid].ImagesCountOld) * binary.Size(CacheImageInfo{}) / 1024
|
|
imagesOffset := int(f.Headers[uuid].ImagesOffsetOld)
|
|
imagesSize := int(imagesCount) * binary.Size(CacheImageInfo{})
|
|
|
|
if f.Headers[uuid].ImagesOffsetOld == 0 && f.Headers[uuid].ImagesCountOld == 0 {
|
|
imagesCount = f.Headers[uuid].ImagesCount
|
|
imageHumanSize = int(f.Headers[uuid].ImagesCount) * binary.Size(CacheImageInfo{}) / 1024
|
|
imagesOffset = int(f.Headers[uuid].ImagesOffset)
|
|
imagesSize = int(f.Headers[uuid].ImagesCount) * binary.Size(CacheImageInfo{})
|
|
}
|
|
|
|
if imagesCount > 0 || imagesOffset > 0 || imagesSize > 0 {
|
|
output = fmt.Sprintf("ImagesText Info: %3dKB, offset: 0x%09X -> 0x%09X\n", imageHumanSize, imagesOffset, imagesOffset+imagesSize)
|
|
}
|
|
|
|
return output
|
|
}
|
|
|
|
func (f *File) getSlideInfo(uuid types.UUID, slideVersion uint32) string {
|
|
var output string
|
|
if f.Headers[uuid].SlideInfoOffsetUnused > 0 {
|
|
output = fmt.Sprintf("Slide Info (v%d): %4dKB, offset: 0x%09X -> 0x%09X\n",
|
|
slideVersion,
|
|
f.Headers[uuid].SlideInfoSizeUnused/1024,
|
|
f.Headers[uuid].SlideInfoOffsetUnused,
|
|
f.Headers[uuid].SlideInfoOffsetUnused+f.Headers[uuid].SlideInfoSizeUnused)
|
|
}
|
|
return output
|
|
}
|
|
|
|
func (f *File) getBranchPools(uuid types.UUID) string {
|
|
var output string
|
|
if f.Headers[uuid].BranchPoolsOffset > 0 {
|
|
output = fmt.Sprintf("Branch Pool: %3dMB, offset: 0x%09X -> 0x%09X\n",
|
|
binary.Size(f.BranchPools),
|
|
f.Headers[uuid].BranchPoolsOffset,
|
|
int(f.Headers[uuid].BranchPoolsOffset)+binary.Size(f.BranchPools))
|
|
}
|
|
return output
|
|
}
|
|
|
|
func (f *File) getAccelerateInfo(uuid types.UUID) string {
|
|
var output string
|
|
if !f.IsDyld4 {
|
|
if f.Headers[uuid].AccelerateInfoAddrUnusedOrDyldAddr > 0 {
|
|
output = fmt.Sprintf("Accelerate Tab: %3dKB, address: 0x%09X -> 0x%09X\n",
|
|
f.Headers[uuid].AccelerateInfoSizeUnusedOrDyldStartFuncAddr/1024,
|
|
f.Headers[uuid].AccelerateInfoAddrUnusedOrDyldAddr,
|
|
f.Headers[uuid].AccelerateInfoAddrUnusedOrDyldAddr+f.Headers[uuid].AccelerateInfoSizeUnusedOrDyldStartFuncAddr)
|
|
}
|
|
}
|
|
return output
|
|
}
|
|
|
|
func (f *File) getDyldInfo(uuid types.UUID) string {
|
|
var output string
|
|
if f.IsDyld4 {
|
|
output = fmt.Sprintf("\ndyld MachO: address: 0x%09X\n", f.Headers[uuid].AccelerateInfoAddrUnusedOrDyldAddr)
|
|
output += fmt.Sprintf("_dyld_start: address: 0x%09X\n", f.Headers[uuid].AccelerateInfoSizeUnusedOrDyldStartFuncAddr)
|
|
}
|
|
return output
|
|
}
|
|
|
|
func (f *File) getPatchInfo(uuid types.UUID) string {
|
|
var output string
|
|
if f.Headers[uuid].PatchInfoAddr > 0 || f.Headers[uuid].PatchInfoSize > 0 {
|
|
output = fmt.Sprintf("Patch Info: %3dMB, address: 0x%09X -> 0x%09X\n",
|
|
f.Headers[uuid].PatchInfoSize/(1024*1024),
|
|
f.Headers[uuid].PatchInfoAddr, f.Headers[uuid].PatchInfoAddr+f.Headers[uuid].PatchInfoSize)
|
|
}
|
|
return output
|
|
}
|
|
|
|
func (f *File) getProgClosures(uuid types.UUID) string {
|
|
var output string
|
|
if f.Headers[uuid].ProgClosuresAddr > 0 {
|
|
output = fmt.Sprintf("Closures: %3dMB, address: 0x%09X -> 0x%09X\n",
|
|
f.Headers[uuid].ProgClosuresSize/(1024*1024),
|
|
f.Headers[uuid].ProgClosuresAddr,
|
|
f.Headers[uuid].ProgClosuresAddr+f.Headers[uuid].ProgClosuresSize)
|
|
}
|
|
return output
|
|
}
|
|
|
|
func (f *File) getProgClosuresTrie(uuid types.UUID) string {
|
|
var output string
|
|
if f.Headers[uuid].ProgClosuresTrieAddr > 0 {
|
|
output = fmt.Sprintf("Closures Trie: %3dKB, address: 0x%09X -> 0x%09X\n",
|
|
f.Headers[uuid].ProgClosuresTrieSize/1024,
|
|
f.Headers[uuid].ProgClosuresTrieAddr,
|
|
f.Headers[uuid].ProgClosuresTrieAddr+f.Headers[uuid].ProgClosuresTrieSize)
|
|
}
|
|
return output
|
|
}
|
|
|
|
func (f *File) getPrebuiltLoaderSet(uuid types.UUID) string {
|
|
var output string
|
|
if f.IsDyld4 && f.Headers[uuid].DylibsPblSetAddr > 0 {
|
|
output = fmt.Sprintf("Prebuilt Loader Set: %3dMB, address: 0x%09X -> 0x%09X\n",
|
|
(f.Headers[uuid].ProgramsPblSetPoolAddr-f.Headers[uuid].DylibsPblSetAddr)/1024/1024,
|
|
f.Headers[uuid].DylibsPblSetAddr,
|
|
f.Headers[uuid].ProgramsPblSetPoolAddr-f.Headers[uuid].DylibsPblSetAddr)
|
|
}
|
|
return output
|
|
}
|
|
|
|
func (f *File) getPrebuiltLoaderSetPool(uuid types.UUID) string {
|
|
var output string
|
|
if f.IsDyld4 && f.Headers[uuid].ProgramsPblSetPoolAddr > 0 {
|
|
output = fmt.Sprintf("Prebuilt Loader Pool: %3dMB, address: 0x%09X -> 0x%09X\n",
|
|
f.Headers[uuid].ProgramsPblSetPoolSize/(1024*1024),
|
|
f.Headers[uuid].ProgramsPblSetPoolAddr,
|
|
f.Headers[uuid].ProgramsPblSetPoolAddr+f.Headers[uuid].ProgramsPblSetPoolSize)
|
|
}
|
|
return output
|
|
}
|
|
|
|
func (f *File) getObjcOpts(uuid types.UUID) string {
|
|
var output string
|
|
if f.IsDyld4 && f.Headers[uuid].ObjcOptsOffset > 0 {
|
|
output = fmt.Sprintf("ObjC Opts: %3dB, offset: 0x%09X -> 0x%09X\n",
|
|
f.Headers[uuid].ObjcOptsSize,
|
|
f.Headers[uuid].ObjcOptsOffset,
|
|
f.Headers[uuid].ObjcOptsOffset+f.Headers[uuid].ObjcOptsSize)
|
|
}
|
|
return output
|
|
}
|
|
|
|
func (f *File) getSwiftOpts(uuid types.UUID) string {
|
|
var output string
|
|
if f.IsDyld4 && f.Headers[uuid].SwiftOptsOffset > 0 {
|
|
output = fmt.Sprintf("Swift Opts: %3dkB, offset: 0x%09X -> 0x%09X\n",
|
|
f.Headers[uuid].SwiftOptsSize/(1024),
|
|
f.Headers[uuid].SwiftOptsOffset,
|
|
f.Headers[uuid].SwiftOptsOffset+f.Headers[uuid].SwiftOptsSize)
|
|
}
|
|
return output
|
|
}
|
|
|
|
func (f *File) getDynamicConfig(uuid types.UUID) string {
|
|
var output string
|
|
if f.IsDyld4 && f.Headers[uuid].SwiftOptsOffset > 0 {
|
|
output = fmt.Sprintf("Dynamic Config: %3dkB, address: 0x%09X -> 0x%09X\n",
|
|
f.Headers[uuid].DynamicDataMaxSize/(1024),
|
|
f.Headers[uuid].SharedRegionStart+f.Headers[uuid].DynamicDataOffset,
|
|
f.Headers[uuid].SharedRegionStart+f.Headers[uuid].DynamicDataOffset+f.Headers[uuid].DynamicDataMaxSize)
|
|
}
|
|
return output
|
|
}
|
|
|
|
func (f *File) getSharedRegion(uuid types.UUID) string {
|
|
var output string
|
|
if f.Headers[uuid].SharedRegionSize > 0 {
|
|
output = fmt.Sprintf("Shared Region: %3dGB, address: 0x%09X -> 0x%09X\n",
|
|
f.Headers[uuid].SharedRegionSize/(1024*1024*1024),
|
|
f.Headers[uuid].SharedRegionStart,
|
|
f.Headers[uuid].SharedRegionStart+f.Headers[uuid].SharedRegionSize)
|
|
}
|
|
return output
|
|
}
|
|
|
|
func (f *File) getCodeSignature(uuid types.UUID) string {
|
|
var output string
|
|
if f.Headers[uuid].CodeSignatureSize > 0 {
|
|
output = fmt.Sprintf("Code Signature: %3dMB, offset: 0x%09X -> 0x%09X\n",
|
|
f.Headers[uuid].CodeSignatureSize/(1024*1024),
|
|
f.Headers[uuid].CodeSignatureOffset,
|
|
f.Headers[uuid].CodeSignatureOffset+f.Headers[uuid].CodeSignatureSize)
|
|
}
|
|
return output
|
|
}
|
|
|
|
func (f *File) getRosetta(uuid types.UUID) string {
|
|
var output string
|
|
if f.Headers[uuid].RosettaReadOnlySize > 0 {
|
|
output += fmt.Sprintf("Rosetta RO: %s, address: 0x%09X -> 0x%09X\n",
|
|
humanize.Bytes(f.Headers[uuid].RosettaReadOnlySize),
|
|
f.Headers[uuid].RosettaReadOnlyAddr,
|
|
f.Headers[uuid].RosettaReadOnlyAddr+f.Headers[uuid].RosettaReadOnlySize)
|
|
}
|
|
if f.Headers[uuid].RosettaReadWriteSize > 0 {
|
|
output += fmt.Sprintf("Rosetta RW: %s, address: 0x%09X -> 0x%09X\n",
|
|
humanize.Bytes(f.Headers[uuid].RosettaReadWriteSize),
|
|
f.Headers[uuid].RosettaReadWriteAddr,
|
|
f.Headers[uuid].RosettaReadWriteAddr+f.Headers[uuid].RosettaReadWriteSize)
|
|
}
|
|
return output
|
|
}
|
|
|
|
func (f *File) getMappings(slideVersion uint32, verbose bool) string {
|
|
var output strings.Builder
|
|
if f.Headers[f.UUID].SlideInfoOffsetUnused > 0 {
|
|
for uuid, cacheMappings := range f.Mappings {
|
|
output.WriteString(fmt.Sprintf("\n> SubCache %s", uuid))
|
|
output.WriteString(cacheMappings.String())
|
|
}
|
|
} else {
|
|
// sort mappings map by address
|
|
uuids := make([]types.UUID, 0, len(f.MappingsWithSlideInfo))
|
|
for u := range f.MappingsWithSlideInfo {
|
|
uuids = append(uuids, u)
|
|
}
|
|
sort.SliceStable(uuids, func(i, j int) bool {
|
|
return f.MappingsWithSlideInfo[uuids[i]][0].Address < f.MappingsWithSlideInfo[uuids[j]][0].Address
|
|
})
|
|
for _, uuid := range uuids {
|
|
if uuid == f.symUUID {
|
|
output.WriteString(fmt.Sprintf("\n> Cache (.symbols) UUID: %s\n\n", uuid))
|
|
} else {
|
|
ext, err := f.GetSubCacheExtensionFromUUID(uuid)
|
|
if err != nil {
|
|
output.WriteString(fmt.Sprintf("\n> Cache UUID: %s\n\n", uuid))
|
|
} else {
|
|
output.WriteString(fmt.Sprintf("\n> Cache (%s) UUID: %s\n\n", ext, uuid))
|
|
}
|
|
}
|
|
output.WriteString("Mappings\n--------\n\n")
|
|
output.WriteString(f.MappingsWithSlideInfo[uuid].String(slideVersion, verbose))
|
|
output.WriteString(fmt.Sprintln())
|
|
output.WriteString(f.getCodeSignature(uuid))
|
|
output.WriteString(f.getRosetta(uuid))
|
|
}
|
|
}
|
|
return output.String()
|
|
}
|