in newt/builder/targetbuild.go [626:746]
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 _, rpkg := range t.LoaderBuilder.SortedRpkgs() {
log.Debugf(" * %s", rpkg.Lpkg.Name())
}
log.Debugf("App packages:")
for _, rpkg := range t.AppBuilder.SortedRpkgs() {
log.Debugf(" * %s", rpkg.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.AppTentativeElfPath())
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.AppTentativeElfPath())
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.rpkg.Lpkg.Name())
uncommonPkgs[t.AppBuilder.appPkg.rpkg.Lpkg.Name()] = true
ma := smMatch.FilterPkg(t.AppBuilder.appPkg.rpkg.Lpkg.Name())
smMatch.RemoveMap(ma)
delete(commonPkgs, t.LoaderBuilder.appPkg.rpkg.Lpkg.Name())
uncommonPkgs[t.LoaderBuilder.appPkg.rpkg.Lpkg.Name()] = true
ml := smMatch.FilterPkg(t.LoaderBuilder.appPkg.rpkg.Lpkg.Name())
smMatch.RemoveMap(ml)
util.StatusMessage(util.VERBOSITY_VERBOSE,
"Putting %d symbols from %d packages into loader\n",
len(*smMatch), len(commonPkgs))
var badpkgs []string
var symbolStr string
for v, _ := range uncommonPkgs {
if t.AppBuilder.appPkg != nil &&
t.AppBuilder.appPkg.rpkg.Lpkg.Name() != v &&
t.LoaderBuilder.appPkg != nil &&
t.LoaderBuilder.appPkg.rpkg.Lpkg.Name() != v {
trouble := smNomatch.FilterPkg(v)
var found bool
for _, sym := range *trouble {
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,
t.extraADirs())
if err != nil {
return err, nil, nil
}
return err, commonPkgs, smMatch
}