Beispiel #1
0
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
}
Beispiel #2
0
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
}
Beispiel #3
0
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
}