func (b *Builder) ExtractSymbolInfo() (error, *symbol.SymbolMap) { syms := symbol.NewSymbolMap() for _, bpkg := range b.PkgMap { err, sm := b.ParseObjectLibrary(bpkg) if err == nil { syms, err = (*syms).Merge(sm) if err != nil { return err, nil } } } return nil, syms }
func (b *Builder) FetchSymbolMap() (error, *symbol.SymbolMap) { loader_sm := symbol.NewSymbolMap() for _, value := range b.PkgMap { err, sm := b.ParseObjectLibrary(value) if err == nil { util.StatusMessage(util.VERBOSITY_VERBOSE, "Size of %s Loader Map %d\n", value.Name(), len(*sm)) loader_sm, err = loader_sm.Merge(sm) if err != nil { return err, nil } } } return nil, loader_sm }
func (b *Builder) buildRomElf(common *symbol.SymbolMap) error { /* check dependencies on the ROM ELF. This is really dependent on * all of the .a files, but since we already depend on the loader * .as to build the initial elf, we only need to check the app .a */ c, err := b.targetBuilder.NewCompiler(b.AppElfPath()) d := toolchain.NewDepTracker(c) if err != nil { return err } archNames := []string{} /* build the set of archive file names */ for _, bpkg := range b.PkgMap { archiveNames, _ := filepath.Glob(b.PkgBinDir(bpkg) + "/*.a") archNames = append(archNames, archiveNames...) } bld, err := d.RomElfBuildRequired(b.AppLinkerElfPath(), b.AppElfPath(), archNames) if err != nil { return err } if !bld { return nil } util.StatusMessage(util.VERBOSITY_DEFAULT, "Generating ROM elf \n") /* the linker needs these symbols kept for the split app * to initialize the loader data and bss */ common.Add(*symbol.NewElfSymbol("__HeapBase")) common.Add(*symbol.NewElfSymbol("__bss_start__")) common.Add(*symbol.NewElfSymbol("__bss_end__")) common.Add(*symbol.NewElfSymbol("__etext")) common.Add(*symbol.NewElfSymbol("__data_start__")) common.Add(*symbol.NewElfSymbol("__data_end__")) /* the split app may need this to access interrupts */ common.Add(*symbol.NewElfSymbol("__vector_tbl_reloc__")) common.Add(*symbol.NewElfSymbol("__isr_vector")) err = b.CopySymbols(common) if err != nil { return err } /* These symbols are needed by the split app so it can zero * bss and copy data from the loader app before it restarts, * but we have to rename them since it has its own copies of * these special linker symbols */ tmp_sm := symbol.NewSymbolMap() tmp_sm.Add(*symbol.NewElfSymbol("__HeapBase")) tmp_sm.Add(*symbol.NewElfSymbol("__bss_start__")) tmp_sm.Add(*symbol.NewElfSymbol("__bss_end__")) tmp_sm.Add(*symbol.NewElfSymbol("__etext")) tmp_sm.Add(*symbol.NewElfSymbol("__data_start__")) tmp_sm.Add(*symbol.NewElfSymbol("__data_end__")) err = c.RenameSymbols(tmp_sm, b.AppLinkerElfPath(), "_loader") if err != nil { return err } return nil }
/* * This function re-links the loader adding symbols from libraries * shared with the app. Returns a list of the common packages shared * by the app and loader */ func (t *TargetBuilder) RelinkLoader() (error, map[string]bool, *symbol.SymbolMap) { /* fetch symbols from the elf and from the libraries themselves */ log.Debugf("Loader packages:") for _, lpkg := range t.LoaderBuilder.sortedLocalPackages() { log.Debugf(" * %s", lpkg.Name()) } log.Debugf("App packages:") for _, lpkg := range t.AppBuilder.sortedLocalPackages() { log.Debugf(" * %s", lpkg.Name()) } err, appLibSym := t.AppBuilder.ExtractSymbolInfo() if err != nil { return err, nil, nil } /* fetch the symbol list from the app temporary elf */ err, appElfSym := t.AppBuilder.ParseObjectElf(t.AppBuilder.AppTempElfPath()) if err != nil { return err, nil, nil } /* extract the library symbols and elf symbols from the loader */ err, loaderLibSym := t.LoaderBuilder.ExtractSymbolInfo() if err != nil { return err, nil, nil } err, loaderElfSym := t.LoaderBuilder.ParseObjectElf( t.LoaderBuilder.AppTempElfPath()) if err != nil { return err, nil, nil } /* create the set of matching and non-matching symbols */ err, smMatch, smNomatch := symbol.IdenticalUnion(appLibSym, loaderLibSym, true, false) /* which packages are shared between the two */ commonPkgs := smMatch.Packages() uncommonPkgs := smNomatch.Packages() /* ensure that the loader and app packages are never shared */ delete(commonPkgs, t.AppBuilder.appPkg.Name()) uncommonPkgs[t.AppBuilder.appPkg.Name()] = true ma := smMatch.FilterPkg(t.AppBuilder.appPkg.Name()) smMatch.RemoveMap(ma) delete(commonPkgs, t.LoaderBuilder.appPkg.Name()) uncommonPkgs[t.LoaderBuilder.appPkg.Name()] = true ml := smMatch.FilterPkg(t.LoaderBuilder.appPkg.Name()) smMatch.RemoveMap(ml) util.StatusMessage(util.VERBOSITY_VERBOSE, "Putting %d symbols from %d packages into loader\n", len(*smMatch), len(commonPkgs)) /* This is worth a special comment. We are building both apps as * stand-alone apps against the normal linker file, so they will both * have a Reset_Handler symbol. We need to ignore this here. When * we build the split app, we use a special linker file which * uses a different entry point */ specialSm := symbol.NewSymbolMap() specialSm.Add(*symbol.NewElfSymbol("Reset_Handler(app)")) specialSm.Add(*symbol.NewElfSymbol("Reset_Handler(loader)")) var badpkgs []string var symbolStr string for v, _ := range uncommonPkgs { if t.AppBuilder.appPkg != nil && t.AppBuilder.appPkg.Name() != v && t.LoaderBuilder.appPkg != nil && t.LoaderBuilder.appPkg.Name() != v { trouble := smNomatch.FilterPkg(v) var found bool for _, sym := range *trouble { if _, ok := specialSm.Find(sym.Name); !ok { if !sym.IsLocal() { found = true } } } if found { symbolStr = (*trouble).String("Non Matching Symbols") badpkgs = append(badpkgs, v) delete(commonPkgs, v) } } } if len(badpkgs) > 0 { errStr := fmt.Sprintf( "Common packages with different implementation\n %s\n", strings.Join(badpkgs, "\n ")) errStr += symbolStr return util.NewNewtError(errStr), nil, nil } /* for each symbol in the elf of the app, if that symbol is in * a common package, keep that symbol in the loader */ preserveElf := symbol.NewSymbolMap() /* go through each symbol in the app */ for _, elfsym := range *appElfSym { name := elfsym.Name if libsym, ok := (*appLibSym)[name]; ok { if _, ok := commonPkgs[libsym.Bpkg]; ok { /* if its not in the loader elf, add it as undefined */ if _, ok := (*loaderElfSym)[name]; !ok { preserveElf.Add(elfsym) } } } } /* re-link loader */ project.ResetDeps(t.LoaderList) util.StatusMessage(util.VERBOSITY_VERBOSE, "Migrating %d unused symbols into Loader\n", len(*preserveElf)) err = t.LoaderBuilder.KeepLink(t.bspPkg.LinkerScripts, preserveElf) if err != nil { return err, nil, nil } return err, commonPkgs, smMatch }
func (b *Builder) ParseObjectLibraryFile(bp *BuildPackage, file string, textDataOnly bool) (error, *symbol.SymbolMap) { c, err := b.targetBuilder.NewCompiler(b.AppElfPath()) ext := filepath.Ext(file) if err != nil { return err, nil } err, out := c.ParseLibrary(file) if err != nil { return err, nil } sm := symbol.NewSymbolMap() buffer := bytes.NewBuffer(out) err, r := getParseRexeg() if err != nil { return err, nil } for { line, err := buffer.ReadString('\n') if err != nil { break } err, si := parseObjectLine(line, r) if err == nil && si != nil { /* assign the library */ if bp != nil { (*si).Bpkg = bp.Name() } else { (*si).Bpkg = "elf" } /* discard undefined */ if (*si).IsSection("*UND*") { continue } /* discard debug symbols */ if (*si).IsDebug() { continue } if (*si).IsFile() { continue } /* if we are looking for text and data only, do a special check */ if textDataOnly { include := (*si).IsSection(".bss") || (*si).IsSection(".text") || (*si).IsSection(".data") || (*si).IsSection("*COM*") || (*si).IsSection(".rodata") if !include { continue } } /* add the symbol to the map */ (*si).Ext = ext sm.Add(*si) util.StatusMessage(util.VERBOSITY_VERBOSE, "Keeping Symbol %s in package %s\n", (*si).Name, (*si).Bpkg) } } return nil, sm }