mirror of
https://github.com/blacktop/ipsw.git
synced 2026-06-07 12:27:36 +00:00
118 lines
2.7 KiB
Go
118 lines
2.7 KiB
Go
package dsc
|
|
|
|
import (
|
|
"sort"
|
|
|
|
"github.com/apex/log"
|
|
|
|
mcmd "github.com/blacktop/ipsw/internal/commands/macho"
|
|
"github.com/blacktop/ipsw/internal/utils"
|
|
"github.com/blacktop/ipsw/pkg/dyld"
|
|
)
|
|
|
|
// Diff compares two DSC files
|
|
func Diff(f1 *dyld.File, f2 *dyld.File, conf *mcmd.DiffConfig) (*mcmd.MachoDiff, error) {
|
|
diff := &mcmd.MachoDiff{
|
|
Updated: make(map[string]string),
|
|
}
|
|
|
|
// Build name->image lookup tables (cheap) so we can diff without
|
|
// materializing DiffInfo for every image at once.
|
|
prev := make(map[string]*dyld.CacheImage, len(f1.Images))
|
|
var prevKeys []string
|
|
for _, img := range f1.Images {
|
|
prev[img.Name] = img
|
|
prevKeys = append(prevKeys, img.Name)
|
|
}
|
|
next := make(map[string]*dyld.CacheImage, len(f2.Images))
|
|
var nextKeys []string
|
|
for _, img := range f2.Images {
|
|
next[img.Name] = img
|
|
nextKeys = append(nextKeys, img.Name)
|
|
}
|
|
|
|
sort.Strings(prevKeys)
|
|
sort.Strings(nextKeys)
|
|
|
|
diff.New = utils.Difference(nextKeys, prevKeys)
|
|
diff.Removed = utils.Difference(prevKeys, nextKeys)
|
|
// Keep output stable for callers
|
|
sort.Strings(diff.New)
|
|
sort.Strings(diff.Removed)
|
|
|
|
for _, name := range nextKeys {
|
|
img1, ok := prev[name]
|
|
if !ok {
|
|
continue
|
|
}
|
|
img2 := next[name]
|
|
|
|
m1, err := img1.GetMacho()
|
|
if err != nil {
|
|
log.Errorf("failed to parse MachO for image %s: %v", img1.Name, err)
|
|
continue
|
|
}
|
|
|
|
m2, err := img2.GetMacho()
|
|
if err != nil {
|
|
log.Errorf("failed to parse MachO for image %s: %v", img2.Name, err)
|
|
if m1 != nil {
|
|
m1.Close()
|
|
}
|
|
continue
|
|
}
|
|
|
|
// Parse local/private symbols for better symbol identity when available
|
|
if err := img1.ParseLocalSymbols(false); err != nil {
|
|
// non-fatal: continue using whatever public symbols we have
|
|
log.Debugf("failed to parse local symbols for image %s: %v", img1.Name, err)
|
|
} else {
|
|
if m1 != nil && m1.Symtab != nil {
|
|
m1.Symtab.Syms = append(m1.Symtab.Syms, img1.GetLocalSymbolsAsMachoSymbols()...)
|
|
}
|
|
}
|
|
if err := img2.ParseLocalSymbols(false); err != nil {
|
|
log.Debugf("failed to parse local symbols for image %s: %v", img2.Name, err)
|
|
} else {
|
|
if m2 != nil && m2.Symtab != nil {
|
|
m2.Symtab.Syms = append(m2.Symtab.Syms, img2.GetLocalSymbolsAsMachoSymbols()...)
|
|
}
|
|
}
|
|
|
|
info1 := mcmd.GenerateDiffInfo(m1, conf)
|
|
info2 := mcmd.GenerateDiffInfo(m2, conf)
|
|
if info2.Equal(*info1) {
|
|
if m1 != nil {
|
|
m1.Close()
|
|
}
|
|
if m2 != nil {
|
|
m2.Close()
|
|
}
|
|
continue
|
|
}
|
|
|
|
out, err := mcmd.FormatUpdatedDiff(info1, info2, conf)
|
|
if err != nil {
|
|
if m1 != nil {
|
|
m1.Close()
|
|
}
|
|
if m2 != nil {
|
|
m2.Close()
|
|
}
|
|
return nil, err
|
|
}
|
|
if out != "" {
|
|
diff.Updated[name] = out
|
|
}
|
|
|
|
if m1 != nil {
|
|
m1.Close()
|
|
}
|
|
if m2 != nil {
|
|
m2.Close()
|
|
}
|
|
}
|
|
|
|
return diff, nil
|
|
}
|