diff --git a/newt/builder/extcmd.go b/newt/builder/extcmd.go index bcbb54e76..e28de1d42 100644 --- a/newt/builder/extcmd.go +++ b/newt/builder/extcmd.go @@ -184,6 +184,47 @@ func (t *TargetBuilder) execExtCmds(sf stage.StageFunc, userSrcDir string, return nil } +func getLinkTableEntry(name string) string { + indent := " " + + entry := indent + "__" + name + "_start__ = .;\n" + + indent + "KEEP(*(." + name + "))\n" + + indent + "__" + name + "_end__ = .;\n\n" + + return entry +} + +func (t *TargetBuilder) generateLinkTables() { + var s []string + + for _, pkg := range t.res.LpkgRpkgMap { + s = append(s, pkg.Lpkg.LinkTables()...) + } + + if len(s) == 0 { + return + } + + dir := GeneratedBaseDir(t.target.FullName()) + "/link/include" + err := os.MkdirAll(dir, os.ModePerm) + if err != nil { + log.Error("Generate link tables error:\n", err) + return + } + + linkHeader, err := os.Create(dir + "/link_tables.ld.h") + if err != nil { + log.Error("Generate link tables error:\n", err) + return + } + + for _, linkTable := range s { + linkHeader.WriteString(getLinkTableEntry(linkTable)) + } + +} + +//link tables // execPreBuildCmds runs the target's set of pre-build user commands. It is an // error if any command fails (exits with a nonzero status). func (t *TargetBuilder) execPreBuildCmds(workDir string) error { diff --git a/newt/builder/targetbuild.go b/newt/builder/targetbuild.go index dc54b68e4..675d4e017 100644 --- a/newt/builder/targetbuild.go +++ b/newt/builder/targetbuild.go @@ -581,6 +581,8 @@ func (t *TargetBuilder) Build() error { os.RemoveAll(workDir) }() + t.generateLinkTables() + // Execute the set of pre-build user scripts. if err := t.execPreBuildCmds(workDir); err != nil { return err diff --git a/newt/pkg/localpackage.go b/newt/pkg/localpackage.go index 344633be9..44d3208ba 100644 --- a/newt/pkg/localpackage.go +++ b/newt/pkg/localpackage.go @@ -59,6 +59,8 @@ type LocalPackage struct { // General information about the package desc *PackageDesc + linkTables []string + // Extra package-specific settings that don't come from syscfg. For // example, SELFTEST gets set when the newt test command is used. injectedSettings *cfgv.Settings @@ -145,6 +147,10 @@ func (pkg *LocalPackage) Desc() *PackageDesc { return pkg.desc } +func (pkg *LocalPackage) LinkTables() []string { + return pkg.linkTables +} + func (pkg *LocalPackage) SetName(name string) { pkg.name = name } @@ -197,6 +203,15 @@ func (pkg *LocalPackage) readDesc(yc ycfg.YCfg) (*PackageDesc, error) { return pdesc, nil } +func (pkg *LocalPackage) readLinkTables(yc ycfg.YCfg) ([]string, error) { + var err error + + sections, err := yc.GetValStringSlice("pkg.link_tables", nil) + util.OneTimeWarningError(err) + + return sections, nil +} + func (pkg *LocalPackage) sequenceString(key string) string { var buffer bytes.Buffer @@ -361,6 +376,8 @@ func (pkg *LocalPackage) Load() error { return err } + pkg.linkTables, err = pkg.readLinkTables(pkg.PkgY) + // Load syscfg settings. pkg.SyscfgY, err = config.ReadFile(pkg.SyscfgYamlPath()) if err != nil && !util.IsNotExist(err) {