144 lines
4 KiB
Go
144 lines
4 KiB
Go
package ukManager
|
|
|
|
import (
|
|
"fmt"
|
|
"math"
|
|
"sort"
|
|
"tools/srcs/binarytool/elf64analyser"
|
|
u "tools/srcs/common"
|
|
)
|
|
|
|
type Manager struct {
|
|
Unikernels []Unikernel
|
|
MicroLibs map[string]*MicroLib
|
|
SortedMicroLibs []*MicroLib //Used for the display
|
|
}
|
|
|
|
type MicroLib struct {
|
|
name string
|
|
startAddr uint64
|
|
size uint64
|
|
instance int
|
|
sectionSize SectionMicroLibs
|
|
}
|
|
|
|
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)
|
|
}
|