[llvm-objcopy] Add --prefix-alloc-sections
authorJames Henderson <jh7370@my.bristol.ac.uk>
Wed, 8 May 2019 09:49:35 +0000 (09:49 +0000)
committerJames Henderson <jh7370@my.bristol.ac.uk>
Wed, 8 May 2019 09:49:35 +0000 (09:49 +0000)
This patch adds support for --prefix-alloc-sections, which adds a prefix
to every allocated section names.

It adds a prefix after renaming section names by --rename-section as GNU
objcopy does.

Fixes PR41266: https://bugs.llvm.org/show_bug.cgi?id=41266

Differential Revision: https://reviews.llvm.org/D60042

Patch by Seiya Nuta.

llvm-svn: 360233

llvm/test/tools/llvm-objcopy/ELF/prefix-alloc-sections-dynrelocsec.test [new file with mode: 0644]
llvm/test/tools/llvm-objcopy/ELF/prefix-alloc-sections.test [new file with mode: 0644]
llvm/test/tools/llvm-objcopy/ELF/rename-section-and-prefix-alloc-sections.test [new file with mode: 0644]
llvm/tools/llvm-objcopy/COFF/COFFObjcopy.cpp
llvm/tools/llvm-objcopy/CopyConfig.cpp
llvm/tools/llvm-objcopy/CopyConfig.h
llvm/tools/llvm-objcopy/ELF/ELFObjcopy.cpp
llvm/tools/llvm-objcopy/ObjcopyOpts.td

diff --git a/llvm/test/tools/llvm-objcopy/ELF/prefix-alloc-sections-dynrelocsec.test b/llvm/test/tools/llvm-objcopy/ELF/prefix-alloc-sections-dynrelocsec.test
new file mode 100644 (file)
index 0000000..9e267f6
--- /dev/null
@@ -0,0 +1,5 @@
+# RUN: llvm-objcopy --prefix-alloc-sections=.prefix %p/Inputs/dynrel.elf %t
+# RUN: llvm-readobj --sections %t | FileCheck %s
+
+# CHECK: Name: .prefix.rela.plt
+# CHECK: Name: .prefix.plt
diff --git a/llvm/test/tools/llvm-objcopy/ELF/prefix-alloc-sections.test b/llvm/test/tools/llvm-objcopy/ELF/prefix-alloc-sections.test
new file mode 100644 (file)
index 0000000..4cb9df5
--- /dev/null
@@ -0,0 +1,36 @@
+# RUN: yaml2obj %s > %t
+# RUN: llvm-objcopy --prefix-alloc-sections=.prefix %t %t2
+# RUN: llvm-readobj --sections %t2 | FileCheck %s
+
+!ELF
+FileHeader:
+  Class:           ELFCLASS64
+  Data:            ELFDATA2LSB
+  Type:            ET_REL
+  Machine:         EM_X86_64
+Sections:
+  - Name:            .foo
+    Type:            SHT_PROGBITS
+    Flags:           [  ]
+  - Name:            .prefix.already_prefixed
+    Type:            SHT_PROGBITS
+    Flags:           [ SHF_ALLOC ]
+  - Name:            .text
+    Type:            SHT_PROGBITS
+    Flags:           [ SHF_ALLOC ]
+  - Name:            .rel.text
+    Type:            SHT_REL
+    Info:            .text
+  - Name:            .rela.data
+    Type:            SHT_RELA
+    Info:            .data
+  - Name:            .data
+    Type:            SHT_PROGBITS
+    Flags:           [ SHF_ALLOC ]
+
+# CHECK: Name: .foo
+# CHECK: Name: .prefix.prefix.already_prefixed
+# CHECK: Name: .prefix.text
+# CHECK: Name: .rel.prefix.text
+# CHECK: Name: .rela.prefix.data
+# CHECK: Name: .prefix.data
diff --git a/llvm/test/tools/llvm-objcopy/ELF/rename-section-and-prefix-alloc-sections.test b/llvm/test/tools/llvm-objcopy/ELF/rename-section-and-prefix-alloc-sections.test
new file mode 100644 (file)
index 0000000..fd642b6
--- /dev/null
@@ -0,0 +1,32 @@
+# RUN: yaml2obj %s > %t
+# RUN: llvm-objcopy --rename-section=.text=.text2 --rename-section=.data=.data2 --prefix-alloc-sections=.prefix %t %t2
+# RUN: llvm-readobj --sections %t2 | FileCheck %s
+
+# .text/.rel.text and .data/.rela.data are the cases when the relocation section
+# comes after/before its target section respectively. We handle them in different
+# ways to perform both --rename-section and --prefix-alloc-sections in one pass.
+
+!ELF
+FileHeader:
+  Class:           ELFCLASS64
+  Data:            ELFDATA2LSB
+  Type:            ET_REL
+  Machine:         EM_X86_64
+Sections:
+  - Name:            .text
+    Type:            SHT_PROGBITS
+    Flags:           [ SHF_ALLOC ]
+  - Name:            .rel.text
+    Type:            SHT_REL
+    Info:            .text
+  - Name:            .rela.data
+    Type:            SHT_RELA
+    Info:            .data
+  - Name:            .data
+    Type:            SHT_PROGBITS
+    Flags:           [ SHF_ALLOC ]
+
+# CHECK: Name: .prefix.text2
+# CHECK: Name: .rel.prefix.text2
+# CHECK: Name: .rela.prefix.data2
+# CHECK: Name: .prefix.data2
index ace4ebd..1f5509e 100644 (file)
@@ -177,15 +177,15 @@ static Error handleArgs(const CopyConfig &Config, Object &Obj) {
   if (Config.AllowBrokenLinks || !Config.BuildIdLinkDir.empty() ||
       Config.BuildIdLinkInput || Config.BuildIdLinkOutput ||
       !Config.SplitDWO.empty() || !Config.SymbolsPrefix.empty() ||
-      !Config.AddSection.empty() || !Config.DumpSection.empty() ||
-      !Config.KeepSection.empty() || !Config.SymbolsToGlobalize.empty() ||
-      !Config.SymbolsToKeep.empty() || !Config.SymbolsToLocalize.empty() ||
-      !Config.SymbolsToWeaken.empty() || !Config.SymbolsToKeepGlobal.empty() ||
-      !Config.SectionsToRename.empty() || !Config.SetSectionFlags.empty() ||
-      !Config.SymbolsToRename.empty() || Config.ExtractDWO ||
-      Config.KeepFileSymbols || Config.LocalizeHidden || Config.PreserveDates ||
-      Config.StripDWO || Config.StripNonAlloc || Config.StripSections ||
-      Config.Weaken || Config.DecompressDebugSections ||
+      !Config.AllocSectionsPrefix.empty() || !Config.AddSection.empty() ||
+      !Config.DumpSection.empty() || !Config.KeepSection.empty() ||
+      !Config.SymbolsToGlobalize.empty() || !Config.SymbolsToKeep.empty() ||
+      !Config.SymbolsToLocalize.empty() || !Config.SymbolsToWeaken.empty() ||
+      !Config.SymbolsToKeepGlobal.empty() || !Config.SectionsToRename.empty() ||
+      !Config.SetSectionFlags.empty() || !Config.SymbolsToRename.empty() ||
+      Config.ExtractDWO || Config.KeepFileSymbols || Config.LocalizeHidden ||
+      Config.PreserveDates || Config.StripDWO || Config.StripNonAlloc ||
+      Config.StripSections || Config.Weaken || Config.DecompressDebugSections ||
       Config.DiscardMode == DiscardType::Locals ||
       !Config.SymbolsToAdd.empty() || Config.EntryExpr) {
     return createStringError(llvm::errc::invalid_argument,
index 3ea4a95..94c0a5b 100644 (file)
@@ -499,6 +499,8 @@ Expected<DriverConfig> parseObjcopyOptions(ArrayRef<const char *> ArgsArr) {
         InputArgs.getLastArgValue(OBJCOPY_build_id_link_output);
   Config.SplitDWO = InputArgs.getLastArgValue(OBJCOPY_split_dwo);
   Config.SymbolsPrefix = InputArgs.getLastArgValue(OBJCOPY_prefix_symbols);
+  Config.AllocSectionsPrefix =
+      InputArgs.getLastArgValue(OBJCOPY_prefix_alloc_sections);
 
   for (auto Arg : InputArgs.filtered(OBJCOPY_redefine_symbol)) {
     if (!StringRef(Arg->getValue()).contains('='))
index fd548cc..65d1d27 100644 (file)
@@ -120,6 +120,7 @@ struct CopyConfig {
   Optional<StringRef> BuildIdLinkOutput;
   StringRef SplitDWO;
   StringRef SymbolsPrefix;
+  StringRef AllocSectionsPrefix;
   DiscardType DiscardMode = DiscardType::None;
 
   // Repeated options
index 9b21190..bed2414 100644 (file)
@@ -13,6 +13,7 @@
 #include "llvm-objcopy.h"
 
 #include "llvm/ADT/BitmaskEnum.h"
+#include "llvm/ADT/DenseSet.h"
 #include "llvm/ADT/Optional.h"
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/ADT/SmallVector.h"
@@ -580,7 +581,8 @@ static Error handleArgs(const CopyConfig &Config, Object &Obj,
   if (Error E = updateAndRemoveSymbols(Config, Obj))
     return E;
 
-  if (!Config.SectionsToRename.empty()) {
+  if (!Config.SectionsToRename.empty() || !Config.AllocSectionsPrefix.empty()) {
+    DenseSet<SectionBase *> PrefixedSections;
     for (auto &Sec : Obj.sections()) {
       const auto Iter = Config.SectionsToRename.find(Sec.Name);
       if (Iter != Config.SectionsToRename.end()) {
@@ -589,6 +591,60 @@ static Error handleArgs(const CopyConfig &Config, Object &Obj,
         if (SR.NewFlags.hasValue())
           setSectionFlagsAndType(Sec, SR.NewFlags.getValue());
       }
+
+      // Add a prefix to allocated sections and their relocation sections. This
+      // should be done after renaming the section by Config.SectionToRename to
+      // imitate the GNU objcopy behavior.
+      if (!Config.AllocSectionsPrefix.empty()) {
+        if (Sec.Flags & SHF_ALLOC) {
+          Sec.Name = (Config.AllocSectionsPrefix + Sec.Name).str();
+          PrefixedSections.insert(&Sec);
+
+        // Rename relocation sections associated to the allocated sections.
+        // For example, if we rename .text to .prefix.text, we also rename
+        // .rel.text to .rel.prefix.text.
+        //
+        // Dynamic relocation sections (SHT_REL[A] with SHF_ALLOC) are handled
+        // above, e.g., .rela.plt is renamed to .prefix.rela.plt, not
+        // .rela.prefix.plt since GNU objcopy does so.
+        } else if (auto *RelocSec = dyn_cast<RelocationSectionBase>(&Sec)) {
+          auto *TargetSec = RelocSec->getSection();
+          if (TargetSec && (TargetSec->Flags & SHF_ALLOC)) {
+            StringRef prefix;
+            switch (Sec.Type) {
+            case SHT_REL:
+              prefix = ".rel";
+              break;
+            case SHT_RELA:
+              prefix = ".rela";
+              break;
+            default:
+              continue;
+            }
+
+            // If the relocation section comes *after* the target section, we
+            // don't add Config.AllocSectionsPrefix because we've already added
+            // the prefix to TargetSec->Name. Otherwise, if the relocation
+            // section comes *before* the target section, we add the prefix.
+            if (PrefixedSections.count(TargetSec)) {
+              Sec.Name = (prefix + TargetSec->Name).str();
+            } else {
+              const auto Iter = Config.SectionsToRename.find(TargetSec->Name);
+              if (Iter != Config.SectionsToRename.end()) {
+                // Both `--rename-section` and `--prefix-alloc-sections` are
+                // given but the target section is not yet renamed.
+                Sec.Name =
+                    (prefix + Config.AllocSectionsPrefix + Iter->second.NewName)
+                        .str();
+              } else {
+                Sec.Name =
+                    (prefix + Config.AllocSectionsPrefix + TargetSec->Name)
+                        .str();
+              }
+            }
+          }
+        }
+      }
     }
   }
 
index 326a459..33545a5 100644 (file)
@@ -238,6 +238,10 @@ defm prefix_symbols
     : Eq<"prefix-symbols", "Add <prefix> to the start of every symbol name">,
       MetaVarName<"prefix">;
 
+defm prefix_alloc_sections
+    : Eq<"prefix-alloc-sections", "Add <prefix> to the start of every allocated section name">,
+      MetaVarName<"prefix">;
+
 def version : Flag<["--"], "version">,
               HelpText<"Print the version and exit.">;
 def V : Flag<["-"], "V">, Alias<version>;