Skip to content

Commit 8177510

Browse files
committed
When exploiting ar-chives make a .a file for each soruce subfolder
This is required because gcc-ar checks if an object file is already in the archive by looking ONLY at the filename WITHOUT the path, so it may happens that, for example, an object file named "subdir/spi.o", already inside the archive, may be overwritten by an object file in "anotherdir/spi.o" only because they are both named spi.o and even if they are compiled on different directories.
1 parent 9e038ea commit 8177510

File tree

1 file changed

+25
-10
lines changed

1 file changed

+25
-10
lines changed

Diff for: legacy/builder/phases/linker.go

+25-10
Original file line numberDiff line numberDiff line change
@@ -59,23 +59,38 @@ func (s *Linker) Run(ctx *types.Context) error {
5959
func link(ctx *types.Context, objectFiles paths.PathList, coreDotARelPath *paths.Path, coreArchiveFilePath *paths.Path, buildProperties *properties.Map) error {
6060
objectFileList := strings.Join(utils.Map(objectFiles.AsStrings(), wrapWithDoubleQuotes), " ")
6161

62-
// If command line length is too big (> 30000 chars), try to collect the object files into an archive
63-
// and use that archive to complete the build.
62+
// If command line length is too big (> 30000 chars), try to collect the object files into archives
63+
// and use that archives to complete the build.
6464
if len(objectFileList) > 30000 {
65-
objectFilesArchive := ctx.BuildPath.Join("object_files.a")
66-
// Recreate the archive at every build
67-
_ = objectFilesArchive.Remove()
65+
66+
// We must create an object file for each visited directory: this is required becuase gcc-ar checks
67+
// if an object file is already in the archive by looking ONLY at the filename WITHOUT the path, so
68+
// it may happen that a subdir/spi.o inside the archive may be overwritten by a anotherdir/spi.o
69+
// because thery are both named spi.o.
70+
6871
properties := buildProperties.Clone()
69-
properties.Set("archive_file", objectFilesArchive.Base())
70-
properties.SetPath("archive_file_path", objectFilesArchive)
71-
for _, objFile := range objectFiles {
72-
properties.SetPath("object_file", objFile)
72+
archives := map[string]bool{}
73+
for _, object := range objectFiles {
74+
archive := object.Parent().Join("objs.a")
75+
if !archives[archive.String()] {
76+
archives[archive.String()] = true
77+
// Cleanup old archives
78+
_ = archive.Remove()
79+
}
80+
properties.Set("archive_file", archive.Base())
81+
properties.SetPath("archive_file_path", archive)
82+
properties.SetPath("object_file", object)
7383
_, _, err := builder_utils.ExecRecipe(ctx, properties, constants.RECIPE_AR_PATTERN, false, utils.ShowIfVerbose /* stdout */, utils.Show /* stderr */)
7484
if err != nil {
7585
return err
7686
}
7787
}
78-
objectFileList = "-Wl,--whole-archive " + wrapWithDoubleQuotes(objectFilesArchive.String()) + " -Wl,--no-whole-archive"
88+
89+
objectFileList = ""
90+
for archive := range archives {
91+
objectFileList += " " + wrapWithDoubleQuotes(archive)
92+
}
93+
objectFileList = "-Wl,--whole-archive" + objectFileList + " -Wl,--no-whole-archive"
7994
}
8095

8196
properties := buildProperties.Clone()

0 commit comments

Comments
 (0)