diff --git a/srcs/binarytool/run_binarytool.go b/srcs/binarytool/run_binarytool.go index 9939b36..4b758fd 100644 --- a/srcs/binarytool/run_binarytool.go +++ b/srcs/binarytool/run_binarytool.go @@ -35,16 +35,16 @@ func RunBinaryAnalyser(homeDir string) { // Check if a json file is used or if it is via command line manager := new(ukManager.Manager) + manager.MicroLibs = make(map[string]*ukManager.MicroLib) if len(*args.StringArg[listArg]) > 0 { - manager.Unikernels = new(ukManager.Unikernels) - manager.Unikernels.Unikernel = make([]ukManager.Unikernel, len(*args.StringArg[listArg])) + manager.Unikernels = make([]ukManager.Unikernel, len(*args.StringArg[listArg])) mapping := false if *args.BoolArg[mappingArg] { mapping = true } list := strings.Split(*args.StringArg[listArg], ",") for i, arg := range list { - manager.Unikernels.Unikernel[i] = ukManager.Unikernel{ + manager.Unikernels[i] = ukManager.Unikernel{ BuildPath: arg, DisplayMapping: mapping, } @@ -62,9 +62,10 @@ func RunBinaryAnalyser(homeDir string) { var comparison elf64analyser.ComparisonElf comparison.GroupFileSegment = make([]*elf64analyser.ElfFileSegment, 0) - for i, uk := range manager.Unikernels.Unikernel { + for i, _ := range manager.Unikernels { - uk.Analyser = new(elf64analyser.ElfAnalyser) + manager.Unikernels[i].Analyser = new(elf64analyser.ElfAnalyser) + uk := manager.Unikernels[i] if len(uk.BuildPath) > 0 { if uk.BuildPath[len(uk.BuildPath)-1] != os.PathSeparator { uk.BuildPath += u.SEP @@ -91,15 +92,6 @@ func RunBinaryAnalyser(homeDir string) { fmt.Println("=====================================================") } - if uk.ComputeLibsMapping && len(uk.LibsMapping) > 0 { - - if err != nil { - u.PrintErr(err) - } else { - uk.Analyser.ComputeAlignedMapping(uk.ElfFile, uk.LibsMapping) - } - } - if uk.DisplayStatSize { uk.Analyser.DisplayStatSize(uk.ElfFile) } @@ -112,7 +104,9 @@ func RunBinaryAnalyser(homeDir string) { uk.Analyser.FindSectionByAddress(uk.ElfFile, uk.FindSectionByAddress) } - if uk.CompareGroup > 0 { + manager.ComputeAlignment(uk) + + /*if uk.CompareGroup > 0 { foundSection := false section := uk.SectionSplit @@ -153,13 +147,25 @@ func RunBinaryAnalyser(homeDir string) { comparison.GroupFileSegment = append(comparison.GroupFileSegment, &elf64analyser.ElfFileSegment{Filename: uk.ElfFile.Name, NbPages: len(uk.Analyser.ElfPage), Pages: uk.Analyser.ElfPage}) - } else { + } else if len(uk.SectionSplit) > 0 { u.PrintWarning("Section '" + section + "' is not found in the ELF file") } - - } + }*/ } + manager.PerformAlignement() + + /* + if uk.ComputeLibsMapping && len(uk.LibsMapping) > 0 { + + if err != nil { + u.PrintErr(err) + } else { + uk.Analyser.ComputeAlignedMapping(uk.ElfFile, uk.LibsMapping) + } + } + */ + if len(comparison.GroupFileSegment) > 1 { // Perform the comparison diff --git a/srcs/binarytool/ukManager/helpers.go b/srcs/binarytool/ukManager/helpers.go index 5efb815..a507878 100644 --- a/srcs/binarytool/ukManager/helpers.go +++ b/srcs/binarytool/ukManager/helpers.go @@ -13,7 +13,7 @@ import ( "strings" ) -func ReadJsonFile(path string) (*Unikernels, error) { +func ReadJsonFile(path string) ([]Unikernel, error) { jsonFile, err := os.Open(path) if err != nil { return nil, err @@ -25,7 +25,7 @@ func ReadJsonFile(path string) (*Unikernels, error) { return nil, err } - return unikernels, nil + return unikernels.Unikernel, nil } func stringInSlice(name string, plats []string) bool { diff --git a/srcs/binarytool/ukManager/manager.go b/srcs/binarytool/ukManager/manager.go index ff73638..c370ed1 100644 --- a/srcs/binarytool/ukManager/manager.go +++ b/srcs/binarytool/ukManager/manager.go @@ -1,17 +1,144 @@ package ukManager +import ( + "fmt" + "math" + "sort" + "tools/srcs/binarytool/elf64analyser" + u "tools/srcs/common" +) + type Manager struct { - Unikernels *Unikernels - MicroLibs map[string]MicroLibs + Unikernels []Unikernel + MicroLibs map[string]*MicroLib + SortedMicroLibs []*MicroLib //Used for the display } -type MicroLibs struct { - Name string - StartAddr uint64 - Size uint64 - instance int +type MicroLib struct { + name string + startAddr uint64 + size uint64 + instance int + sectionSize SectionMicroLibs } -func checkInstance() { - +type SectionMicroLibs struct { + rodataSize uint64 + dataSize uint64 + BssSize uint64 +} + +func (manager *Manager) ComputeAlignment(unikernel Unikernel) { + + for _, libs := range unikernel.Analyser.ElfLibs { + if val, ok := manager.MicroLibs[libs.Name]; ok { + if manager.MicroLibs[libs.Name].size != libs.Size { + //u.PrintWarning(fmt.Sprintf("Different size between %s (0x%x) (0x%x)", libs.Name, libs.Size, val.size)) + if val.size < libs.Size { + u.PrintWarning(fmt.Sprintf("Bigger size found %s (0x%x) > (0x%x)", libs.Name, libs.Size, val.size)) + manager.MicroLibs[libs.Name].size = libs.Size + } + } + manager.MicroLibs[libs.Name].instance += 1 + } else { + mlib := &MicroLib{ + name: libs.Name, + startAddr: libs.StartAddr, + size: libs.Size, + instance: 1, + } + manager.MicroLibs[libs.Name] = mlib + } + } +} + +func (manager *Manager) sortMicroLibs() { + type kv struct { + key string + instance int + addr uint64 + } + + i := 0 + var kvSlice = make([]kv, len(manager.MicroLibs)) + for k, v := range manager.MicroLibs { + kvSlice[i] = kv{k, v.instance, v.startAddr} + i++ + } + + sort.Slice(kvSlice, func(i, j int) bool { + if kvSlice[i].instance != kvSlice[j].instance { + return kvSlice[i].instance > kvSlice[j].instance + } + return kvSlice[i].addr < kvSlice[j].addr + }) + + manager.SortedMicroLibs = make([]*MicroLib, len(manager.MicroLibs)) + for i, lib := range kvSlice { + manager.SortedMicroLibs[i] = manager.MicroLibs[lib.key] + } +} + +func (manager *Manager) DisplayMicroLibs() { + manager.sortMicroLibs() + for i, lib := range manager.SortedMicroLibs { + + if lib.instance < len(manager.Unikernels) { + fmt.Printf("%d %s: %x - %x - %d\n", i, lib.name, lib.startAddr, lib.size, lib.instance) + } + } +} + +func (manager *Manager) PerformAlignement() { + var startValue uint64 = 0x106000 + //manager.Unikernels[0].Analyser.ElfLibs + + manager.sortMicroLibs() + commonMicroLibs := make([]*MicroLib, 0) + for _, lib := range manager.SortedMicroLibs { + if lib.instance == len(manager.Unikernels) { + lib.startAddr = startValue + commonMicroLibs = append(commonMicroLibs, lib) + //fmt.Printf("%s -> 0x%x (0x%x) - 0x%x\n", lib.name, startValue, startValue, startValue+lib.size) + startValue += lib.size + } else if lib.instance > 1 { + //fmt.Printf("---%s -> 0x%x (0x%x) - 0x%x\n", lib.name, startValue, startValue, startValue+lib.size) + startValue = roundAddr(startValue) + for i, _ := range manager.Unikernels { + if manager.Unikernels[i].alignedLibs == nil { + // Init structure + manager.Unikernels[i].InitAlignment() + } + manager.Unikernels[i].AddAlignedMicroLibs(startValue, lib) + } + startValue += lib.size + //fmt.Printf("%s -> 0x%x (0x%x) - 0x%x\n", lib.name, startValue, roundAddr(startValue), startValue+lib.size) + } else if lib.instance == 1 { + for i, _ := range manager.Unikernels { + manager.Unikernels[i].AddSingleMicroLibs(roundAddr(startValue), lib) + } + //fmt.Printf("%s -> 0x%x (0x%x) - 0x%x\n", lib.name, startValue, roundAddr(startValue), startValue+lib.size) + } + } + + // Find max value through unikernels + for i, _ := range manager.Unikernels { + manager.Unikernels[i].alignedLibs.AllCommonMicroLibs = commonMicroLibs + if startValue < manager.Unikernels[i].alignedLibs.startValueUk { + startValue = manager.Unikernels[i].alignedLibs.startValueUk + } + } + + fmt.Printf("END SECTIONS: 0x%x\n", roundAddr(startValue)) + + /*println(commonMicroLibs.String()) + for _, uk := range manager.Unikernels { + println(uk.microLibsInstance.String()) + }*/ +} + +func roundAddr(value uint64) uint64 { + x := float64(value) + unit := float64(elf64analyser.PageSize) + return uint64(math.Round(x/unit+0.5) * unit) } diff --git a/srcs/binarytool/ukManager/unikernels.go b/srcs/binarytool/ukManager/unikernels.go index 9402d35..d46ceae 100644 --- a/srcs/binarytool/ukManager/unikernels.go +++ b/srcs/binarytool/ukManager/unikernels.go @@ -7,6 +7,7 @@ package ukManager import ( + "fmt" "io/ioutil" "path/filepath" "strings" @@ -49,6 +50,15 @@ type Unikernel struct { ElfFile *elf64core.ELF64File ListObjs []*elf64core.ELF64File Analyser *elf64analyser.ElfAnalyser + + alignedLibs *AlignedLibs +} + +type AlignedLibs struct { + startValueUk uint64 + AllCommonMicroLibs []*MicroLib + OnlyFewMicroLibs []*MicroLib + SingleMicroLibs []*MicroLib } func parseFile(path, name string) (*elf64core.ELF64File, error) { @@ -157,3 +167,39 @@ func (uk *Unikernel) DisplayElfInfo() { } } } + +func (uk *Unikernel) InitAlignment() { + uk.alignedLibs = &AlignedLibs{ + startValueUk: 0, + AllCommonMicroLibs: make([]*MicroLib, 0), //todo update with fixed entry + OnlyFewMicroLibs: make([]*MicroLib, 0), + SingleMicroLibs: make([]*MicroLib, 0), + } +} + +func (uk *Unikernel) AddAlignedMicroLibs(startValue uint64, lib *MicroLib) { + + for _, ukLibs := range uk.Analyser.ElfLibs { + if ukLibs.Name == lib.name { + fmt.Printf("%s -> 0x%x - 0x%x\n", lib.name, startValue, startValue+lib.size) + uk.alignedLibs.OnlyFewMicroLibs = append(uk.alignedLibs.SingleMicroLibs, lib) + break + } + } +} + +func (uk *Unikernel) AddSingleMicroLibs(startValue uint64, lib *MicroLib) { + + for _, ukLibs := range uk.Analyser.ElfLibs { + if ukLibs.Name == lib.name { + + uk.alignedLibs.SingleMicroLibs = append(uk.alignedLibs.SingleMicroLibs, lib) + if uk.alignedLibs.startValueUk == 0 { + uk.alignedLibs.startValueUk = startValue + } + fmt.Printf("%s -> 0x%x - 0x%x\n", lib.name, uk.alignedLibs.startValueUk, uk.alignedLibs.startValueUk+lib.size) + uk.alignedLibs.startValueUk += lib.size + break + } + } +}