Repository: incubator-mynewt-newt Updated Branches: refs/heads/develop 386c08789 -> dce8b5cd0
MYNEWT-651; newt - include package size info in manifest file. Project: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newt/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newt/commit/38d3bc22 Tree: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newt/tree/38d3bc22 Diff: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newt/diff/38d3bc22 Branch: refs/heads/develop Commit: 38d3bc222bcb190fb35861cfe3116a7ab1aee57a Parents: a404a47 Author: Marko Kiiskila <ma...@runtime.io> Authored: Thu Mar 2 12:59:43 2017 -0800 Committer: Marko Kiiskila <ma...@runtime.io> Committed: Thu Mar 2 12:59:43 2017 -0800 ---------------------------------------------------------------------- newt/builder/size.go | 209 +++++++++++++++++++++++++++++++-------- newt/builder/targetbuild.go | 10 ++ newt/image/image.go | 80 ++++++++++++++- 3 files changed, 257 insertions(+), 42 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newt/blob/38d3bc22/newt/builder/size.go ---------------------------------------------------------------------- diff --git a/newt/builder/size.go b/newt/builder/size.go index 5ce2939..70b4dc2 100644 --- a/newt/builder/size.go +++ b/newt/builder/size.go @@ -28,6 +28,7 @@ import ( "strconv" "strings" + "mynewt.apache.org/newt/newt/image" "mynewt.apache.org/newt/util" ) @@ -41,6 +42,8 @@ type MemSection struct { } type MemSectionArray []*MemSection +var globalMemSections map[string]*MemSection + func (array MemSectionArray) Len() int { return len(array) } @@ -71,11 +74,23 @@ func (m *MemSection) PartOf(addr uint64) bool { } /* + * Info about specific symbol size + */ +type SymbolData struct { + Name string + ObjName string /* Which object file it came from */ + Sizes map[string]uint32 /* Sizes indexed by mem section name */ +} + +type SymbolDataArray []*SymbolData + +/* * We accumulate the size of libraries to elements in this. */ type PkgSize struct { Name string - Sizes map[string]uint32 /* Sizes indexed by mem section name */ + Sizes map[string]uint32 /* Sizes indexed by mem section name */ + Syms map[string]*SymbolData /* Symbols indexed by symbol name */ } type PkgSizeArray []*PkgSize @@ -92,33 +107,76 @@ func (array PkgSizeArray) Swap(i, j int) { array[i], array[j] = array[j], array[i] } -func MakePkgSize(name string, memSections map[string]*MemSection) *PkgSize { +func (array SymbolDataArray) Len() int { + return len(array) +} + +func (array SymbolDataArray) Less(i, j int) bool { + return array[i].Name < array[j].Name +} + +func (array SymbolDataArray) Swap(i, j int) { + array[i], array[j] = array[j], array[i] +} + +func MakeSymbolData(name string, objName string) *SymbolData { + sym := &SymbolData{ + Name: name, + ObjName: objName, + } + sym.Sizes = make(map[string]uint32) + for _, sec := range globalMemSections { + sym.Sizes[sec.Name] = 0 + } + return sym +} + +func MakePkgSize(name string) *PkgSize { pkgSize := &PkgSize{ Name: name, } pkgSize.Sizes = make(map[string]uint32) - for secName, _ := range memSections { - pkgSize.Sizes[secName] = 0 + for _, sec := range globalMemSections { + pkgSize.Sizes[sec.Name] = 0 } + pkgSize.Syms = make(map[string]*SymbolData) return pkgSize } +func (ps *PkgSize) addSymSize(symName string, objName string, size uint32, addr uint64) { + for _, section := range globalMemSections { + if section.PartOf(addr) { + name := section.Name + size32 := uint32(size) + if size32 > 0 { + sym := ps.Syms[symName] + if sym == nil { + sym = MakeSymbolData(symName, objName) + ps.Syms[symName] = sym + } + ps.Sizes[name] += size32 + sym.Sizes[name] += size32 + } + break + } + } +} + /* * Go through GCC generated mapfile, and collect info about symbol sizes */ -func ParseMapFileSizes(fileName string) (map[string]*PkgSize, - map[string]*MemSection, error) { +func ParseMapFileSizes(fileName string) (map[string]*PkgSize, error) { var state int = 0 file, err := os.Open(fileName) if err != nil { - return nil, nil, - util.NewNewtError("Mapfile failed: " + err.Error()) + return nil, util.NewNewtError("Mapfile failed: " + err.Error()) } - memSections := make(map[string]*MemSection) - pkgSizes := make(map[string]*PkgSize) + var symName string = "" + globalMemSections = make(map[string]*MemSection) + pkgSizes := make(map[string]*PkgSize) scanner := bufio.NewScanner(file) for scanner.Scan() { switch state { @@ -138,13 +196,13 @@ func ParseMapFileSizes(fileName string) (map[string]*PkgSize, array := strings.Fields(scanner.Text()) offset, err := strconv.ParseUint(array[1], 0, 64) if err != nil { - return nil, nil, util.NewNewtError("Can't parse mem info") + return nil, util.NewNewtError("Can't parse mem info") } size, err := strconv.ParseUint(array[2], 0, 64) if err != nil { - return nil, nil, util.NewNewtError("Can't parse mem info") + return nil, util.NewNewtError("Can't parse mem info") } - memSections[array[0]] = MakeMemSection(array[0], offset, + globalMemSections[array[0]] = MakeMemSection(array[0], offset, size) case 3: if strings.Contains(scanner.Text(), @@ -177,6 +235,7 @@ func ParseMapFileSizes(fileName string) (map[string]*PkgSize, * * ignore these for now */ + symName = array[0] continue case 2: /* @@ -214,6 +273,7 @@ func ParseMapFileSizes(fileName string) (map[string]*PkgSize, addrStr = array[1] sizeStr = array[2] srcFile = array[0] + symName = array[0] } else { addrStr = array[0] sizeStr = array[1] @@ -230,6 +290,7 @@ func ParseMapFileSizes(fileName string) (map[string]*PkgSize, * crud, e.g.: * 0x8 (size before relaxing) */ + symName = array[0] addrStr = array[1] sizeStr = array[2] srcFile = array[3] @@ -248,44 +309,49 @@ func ParseMapFileSizes(fileName string) (map[string]*PkgSize, continue } tmpStrArr := strings.Split(srcFile, "(") - srcLib := filepath.Base(tmpStrArr[0]) - for name, section := range memSections { - if section.PartOf(addr) { - pkgSize := pkgSizes[srcLib] - if pkgSize == nil { - pkgSize = - MakePkgSize(srcLib, memSections) - pkgSizes[srcLib] = pkgSize - } - pkgSize.Sizes[name] += uint32(size) - break + srcLib := tmpStrArr[0] + objName := "" + if srcLib != "*fill*" { + tmpStrArr = strings.Split(tmpStrArr[1], ")") + objName = tmpStrArr[0] + } + tmpStrArr = strings.Split(symName, ".") + if len(tmpStrArr) > 2 { + if tmpStrArr[1] == "rodata" && tmpStrArr[2] == "str1" { + symName = ".rodata.str1" + } else { + symName = tmpStrArr[2] } } + pkgSize := pkgSizes[srcLib] + if pkgSize == nil { + pkgSize = MakePkgSize(srcLib) + pkgSizes[srcLib] = pkgSize + } + pkgSize.addSymSize(symName, objName, uint32(size), addr) + symName = ".unknown" default: } } file.Close() - for name, section := range memSections { + for name, section := range globalMemSections { util.StatusMessage(util.VERBOSITY_VERBOSE, "Mem %s: 0x%x-0x%x\n", name, section.Offset, section.EndOff) } - return pkgSizes, memSections, nil + return pkgSizes, nil } /* * Return a printable string containing size data for the libraries */ -func PrintSizes(libs map[string]*PkgSize, - sectMap map[string]*MemSection) (string, error) { - ret := "" - +func PrintSizes(libs map[string]*PkgSize) error { /* * Order sections by offset, and display lib sizes in that order. */ - memSections := make(MemSectionArray, len(sectMap)) + memSections := make(MemSectionArray, len(globalMemSections)) var i int = 0 - for _, sec := range sectMap { + for _, sec := range globalMemSections { memSections[i] = sec i++ } @@ -303,16 +369,17 @@ func PrintSizes(libs map[string]*PkgSize, sort.Sort(pkgSizes) for _, sec := range memSections { - ret += fmt.Sprintf("%7s ", sec.Name) + fmt.Printf("%7s ", sec.Name) } - ret += "\n" + fmt.Printf("\n") for _, es := range pkgSizes { for i := 0; i < len(memSections); i++ { - ret += fmt.Sprintf("%7d ", es.Sizes[memSections[i].Name]) + fmt.Printf("%7d ", es.Sizes[memSections[i].Name]) } - ret += fmt.Sprintf("%s\n", es.Name) + fmt.Printf("%s\n", filepath.Base(es.Name)) } - return ret, nil + + return nil } func (t *TargetBuilder) Size() error { @@ -336,6 +403,67 @@ func (t *TargetBuilder) Size() error { return err } +func (b *Builder) FindPkgNameByArName(arName string) string { + for rpkg, bpkg := range b.PkgMap { + if (b.ArchivePath(bpkg) == arName) { + return rpkg.Lpkg.FullName() + } + } + return filepath.Base(arName) +} + +func (b *Builder) PkgSizes() (*image.ImageManifestSizeCollector, error) { + if b.appPkg == nil { + return nil, util.NewNewtError("app package not specified for this target") + } + + if b.targetBuilder.bspPkg.Arch == "sim" { + return nil, util.NewNewtError("'newt size' not supported for sim targets") + } + mapFile := b.AppElfPath() + ".map" + + libs, err := ParseMapFileSizes(mapFile) + if err != nil { + return nil, err + } + + /* + * Order libraries by name. + */ + pkgSizes := make(PkgSizeArray, len(libs)) + i := 0 + for _, es := range libs { + pkgSizes[i] = es + i++ + } + sort.Sort(pkgSizes) + + c := image.NewImageManifestSizeCollector() + for _, es := range pkgSizes { + p := c.AddPkg(b.FindPkgNameByArName(es.Name)) + + /* + * Order symbols by name. + */ + symbols := make(SymbolDataArray, len(es.Syms)) + i := 0 + for _, sym := range es.Syms { + symbols[i] = sym + i++ + } + sort.Sort(symbols) + for _, sym := range symbols { + for area, areaSz := range sym.Sizes { + if areaSz != 0 { + p.AddSymbol(sym.ObjName, sym.Name, area, areaSz) + } + } + } + } + + return c, nil +} + func (b *Builder) Size() error { if b.appPkg == nil { return util.NewNewtError("app package not specified for this target") @@ -351,15 +479,14 @@ func (b *Builder) Size() error { } mapFile := b.AppElfPath() + ".map" - pkgSizes, memSections, err := ParseMapFileSizes(mapFile) + pkgSizes, err := ParseMapFileSizes(mapFile) if err != nil { return err } - output, err := PrintSizes(pkgSizes, memSections) + err = PrintSizes(pkgSizes) if err != nil { return err } - fmt.Printf("%s", output) c, err := b.newCompiler(b.appPkg, b.FileBinDir(b.AppElfPath())) if err != nil { @@ -367,7 +494,7 @@ func (b *Builder) Size() error { } fmt.Printf("\nobjsize\n") - output, err = c.PrintSize(b.AppElfPath()) + output, err := c.PrintSize(b.AppElfPath()) if err != nil { return err } http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newt/blob/38d3bc22/newt/builder/targetbuild.go ---------------------------------------------------------------------- diff --git a/newt/builder/targetbuild.go b/newt/builder/targetbuild.go index 2576764..06bbee1 100644 --- a/newt/builder/targetbuild.go +++ b/newt/builder/targetbuild.go @@ -577,6 +577,16 @@ func (t *TargetBuilder) createManifest() error { manifest.TgtVars = append(manifest.TgtVars, tgtSyscfg) } + c, err := t.AppBuilder.PkgSizes() + if err == nil { + manifest.PkgSizes = c.Pkgs + } + if t.LoaderBuilder != nil { + c, err = t.LoaderBuilder.PkgSizes() + if err == nil { + manifest.LoaderPkgSizes = c.Pkgs + } + } file, err := os.Create(t.AppBuilder.ManifestPath()) if err != nil { return util.FmtNewtError("Cannot create manifest file %s: %s", http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newt/blob/38d3bc22/newt/image/image.go ---------------------------------------------------------------------- diff --git a/newt/image/image.go b/newt/image/image.go index c63eb2e..f396d7c 100644 --- a/newt/image/image.go +++ b/newt/image/image.go @@ -117,6 +117,30 @@ const ( /* * Data that's going to go to build manifest file */ +type ImageManifestSizeArea struct { + Name string + Size uint32 +} + +type ImageManifestSizeSym struct { + Name string `json:"name"` + Areas []*ImageManifestSizeArea `json:"areas"` +} + +type ImageManifestSizeFile struct { + Name string `json:"name"` + Syms []*ImageManifestSizeSym `json:"sym"` +} + +type ImageManifestSizePkg struct { + Name string `json:"name"` + Files []*ImageManifestSizeFile `json:"files"` +} + +type ImageManifestSizeCollector struct { + Pkgs []*ImageManifestSizePkg +} + type ImageManifest struct { Name string `json:"name"` Date string `json:"build_time"` @@ -127,9 +151,12 @@ type ImageManifest struct { Loader string `json:"loader"` LoaderHash string `json:"loader_hash"` Pkgs []*ImageManifestPkg `json:"pkgs"` - LoaderPkgs []*ImageManifestPkg `json:"loader_pkgs"` + LoaderPkgs []*ImageManifestPkg `json:"loader_pkgs,omitempty"` TgtVars []string `json:"target"` Repos []ImageManifestRepo `json:"repos"` + + PkgSizes []*ImageManifestSizePkg `json:"pkgsz"` + LoaderPkgSizes []*ImageManifestSizePkg `json:"loader_pkgsz,omitempty"` } type ImageManifestPkg struct { @@ -688,3 +715,54 @@ func (r *RepoManager) AllRepos() []ImageManifestRepo { return repos } + +func NewImageManifestSizeCollector() *ImageManifestSizeCollector { + return &ImageManifestSizeCollector{} +} + +func (c *ImageManifestSizeCollector) AddPkg(pkg string) *ImageManifestSizePkg { + p := &ImageManifestSizePkg { + Name: pkg, + } + c.Pkgs = append(c.Pkgs, p) + + return p +} + +func (c *ImageManifestSizePkg) AddSymbol(file string, sym string, area string, + symSz uint32) { + f := c.addFile(file) + s := f.addSym(sym) + s.addArea(area, symSz) +} + +func (p *ImageManifestSizePkg) addFile(file string) *ImageManifestSizeFile { + for _, f := range p.Files { + if f.Name == file { + return f + } + } + f := &ImageManifestSizeFile { + Name: file, + } + p.Files = append(p.Files, f) + + return f +} + +func (f *ImageManifestSizeFile) addSym(sym string) *ImageManifestSizeSym { + s := &ImageManifestSizeSym { + Name: sym, + } + f.Syms = append(f.Syms, s) + + return s +} + +func (s *ImageManifestSizeSym) addArea(area string, areaSz uint32) { + a := &ImageManifestSizeArea { + Name: area, + Size: areaSz, + } + s.Areas = append(s.Areas, a) +}