[llvm] Add adjustVMA option (PR #72870)

via llvm-commits llvm-commits at lists.llvm.org
Mon Nov 20 06:10:40 PST 2023


https://github.com/pwprzybyla updated https://github.com/llvm/llvm-project/pull/72870

>From 306d9ea7b709dcb3ae046e456763da0cd3d9cc8e Mon Sep 17 00:00:00 2001
From: Piotr Przybyla <piotr.przybyla at arm.com>
Date: Mon, 20 Nov 2023 13:50:21 +0000
Subject: [PATCH] Add adjustVMA option

Add option to adjust section vma
---
 llvm/include/llvm/ObjCopy/CommonConfig.h   |  5 ++
 llvm/lib/ObjCopy/ELF/ELFObjcopy.cpp        | 14 ++++-
 llvm/tools/llvm-objcopy/ObjcopyOptions.cpp | 58 ++++++++++++++++--
 llvm/tools/llvm-objcopy/ObjcopyOpts.td     | 68 +++++++++++++---------
 4 files changed, 114 insertions(+), 31 deletions(-)

diff --git a/llvm/include/llvm/ObjCopy/CommonConfig.h b/llvm/include/llvm/ObjCopy/CommonConfig.h
index e7ce1e6f2c54d75..1dd9dbb29dc372b 100644
--- a/llvm/include/llvm/ObjCopy/CommonConfig.h
+++ b/llvm/include/llvm/ObjCopy/CommonConfig.h
@@ -245,6 +245,11 @@ struct CommonConfig {
   StringMap<uint64_t> SetSectionType;
   StringMap<StringRef> SymbolsToRename;
 
+  // Adjust section VMA and LMA
+  int64_t SectionVMA = 0;
+  StringRef SectionName;
+  bool SectionSet = false;
+
   // Symbol info specified by --add-symbol option.
   std::vector<NewSymbolInfo> SymbolsToAdd;
 
diff --git a/llvm/lib/ObjCopy/ELF/ELFObjcopy.cpp b/llvm/lib/ObjCopy/ELF/ELFObjcopy.cpp
index 9d02ba051a0a84b..ac84ec21a3f400e 100644
--- a/llvm/lib/ObjCopy/ELF/ELFObjcopy.cpp
+++ b/llvm/lib/ObjCopy/ELF/ELFObjcopy.cpp
@@ -652,7 +652,19 @@ static Error handleArgs(const CommonConfig &Config, const ELFConfig &ELFConfig,
         Sec.Align = I->second;
     }
   }
-
+  if (Config.SectionVMA != 0) {
+    for (SectionBase &Sec : Obj.sections()) {
+      bool AdjustThisSection = false;
+      if (Config.SectionName.empty() || Config.SectionName.contains(Sec.Name)) {
+        AdjustThisSection = true;
+      }
+      if ((Sec.Flags & ELF::SHF_ALLOC) && AdjustThisSection) {
+        if (Config.SectionSet)
+          Sec.Addr = 0;
+        Sec.Addr += Config.SectionVMA;
+      }
+    }
+  }
   if (Config.OnlyKeepDebug)
     for (auto &Sec : Obj.sections())
       if (Sec.Flags & SHF_ALLOC && Sec.Type != SHT_NOTE)
diff --git a/llvm/tools/llvm-objcopy/ObjcopyOptions.cpp b/llvm/tools/llvm-objcopy/ObjcopyOptions.cpp
index d33adb0b6a3e478..c88450a833fb7b6 100644
--- a/llvm/tools/llvm-objcopy/ObjcopyOptions.cpp
+++ b/llvm/tools/llvm-objcopy/ObjcopyOptions.cpp
@@ -533,6 +533,42 @@ static Error loadNewSectionData(StringRef ArgValue, StringRef OptionName,
   return Error::success();
 }
 
+// readChangeSectionVMA reads the command line arguments and sets
+// sectionName and adjustValue of VMA and LMA addresses.
+static Error readChangeSectionVMA(StringRef ArgValue, StringRef OptionName,
+                                  StringRef &SectionName, int64_t &AdjustValue,
+                                  bool &setValue) {
+  SectionName = "";
+  AdjustValue = 0;
+  std::pair<StringRef, StringRef> SecPair;
+  if (ArgValue.contains("=")) {
+    setValue = true;
+    SecPair = ArgValue.split("=");
+  } else if (ArgValue.contains("+")) {
+    setValue = false;
+    SecPair = ArgValue.split("+");
+  } else if (ArgValue.contains("-")) {
+    setValue = false;
+    SecPair = ArgValue.split("-");
+  } else {
+    return createStringError(errc::invalid_argument,
+                             "bad format for " + OptionName + ": missing '='");
+  }
+  if (SecPair.second.empty())
+    return createStringError(errc::invalid_argument,
+                             "bad format for " + OptionName +
+                                 ": missing offset of VMA");
+  SectionName = SecPair.first;
+  auto ChangeValue = getAsInteger<int64_t>(SecPair.second);
+  if (!ChangeValue)
+    return createStringError(ChangeValue.getError(),
+                             "Unable to parse adjustment value");
+  AdjustValue = *ChangeValue;
+  if (ArgValue.contains("-"))
+    AdjustValue *= -1;
+  return Error::success();
+}
+
 // parseObjcopyOptions returns the config and sets the input arguments. If a
 // help flag is set then parseObjcopyOptions will print the help messege and
 // exit.
@@ -606,8 +642,8 @@ objcopy::parseObjcopyOptions(ArrayRef<const char *> RawArgsArr,
   MatchStyle SectionMatchStyle = InputArgs.hasArg(OBJCOPY_regex)
                                      ? MatchStyle::Regex
                                      : MatchStyle::Wildcard;
-  MatchStyle SymbolMatchStyle
-      = InputArgs.hasArg(OBJCOPY_regex)    ? MatchStyle::Regex
+  MatchStyle SymbolMatchStyle =
+      InputArgs.hasArg(OBJCOPY_regex)      ? MatchStyle::Regex
       : InputArgs.hasArg(OBJCOPY_wildcard) ? MatchStyle::Wildcard
                                            : MatchStyle::Literal;
   StringRef InputFormat, OutputFormat;
@@ -828,6 +864,12 @@ objcopy::parseObjcopyOptions(ArrayRef<const char *> RawArgsArr,
                                        Config.UpdateSection))
       return std::move(Err);
   }
+  for (auto *Arg : InputArgs.filtered(OBJCOPY_adjust_section_vma)) {
+    if (Error Err = readChangeSectionVMA(
+            Arg->getValue(), "--adjust-section-vma", Config.SectionName,
+            Config.SectionVMA, Config.SectionSet))
+      return std::move(Err);
+  }
   for (auto *Arg : InputArgs.filtered(OBJCOPY_dump_section)) {
     StringRef Value(Arg->getValue());
     if (Value.split('=').second.empty())
@@ -967,6 +1009,14 @@ objcopy::parseObjcopyOptions(ArrayRef<const char *> RawArgsArr,
       ELFConfig.EntryExpr = [Expr, EIncr](uint64_t EAddr) {
         return Expr(EAddr) + *EIncr;
       };
+    } else if (Arg->getOption().matches(OBJCOPY_adjust_vma)) {
+      auto EIncr = getAsInteger<int64_t>(Arg->getValue());
+      if (!EIncr)
+        return createStringError(EIncr.getError(),
+                                 "bad entry point VMA increment: '%s'",
+                                 Arg->getValue());
+      Config.SectionName = "";
+      Config.SectionVMA = *EIncr;
     }
 
   if (Config.DecompressDebugSections &&
@@ -1251,8 +1301,8 @@ objcopy::parseStripOptions(ArrayRef<const char *> RawArgsArr,
                              "--regex and --wildcard are incompatible");
   MatchStyle SectionMatchStyle =
       InputArgs.hasArg(STRIP_regex) ? MatchStyle::Regex : MatchStyle::Wildcard;
-  MatchStyle SymbolMatchStyle
-      = InputArgs.hasArg(STRIP_regex)    ? MatchStyle::Regex
+  MatchStyle SymbolMatchStyle =
+      InputArgs.hasArg(STRIP_regex)      ? MatchStyle::Regex
       : InputArgs.hasArg(STRIP_wildcard) ? MatchStyle::Wildcard
                                          : MatchStyle::Literal;
   ELFConfig.AllowBrokenLinks = InputArgs.hasArg(STRIP_allow_broken_links);
diff --git a/llvm/tools/llvm-objcopy/ObjcopyOpts.td b/llvm/tools/llvm-objcopy/ObjcopyOpts.td
index ea8828637222ac6..a5c94ab90bba7a4 100644
--- a/llvm/tools/llvm-objcopy/ObjcopyOpts.td
+++ b/llvm/tools/llvm-objcopy/ObjcopyOpts.td
@@ -24,17 +24,20 @@ def O : JoinedOrSeparate<["-"], "O">,
         Alias<output_target>,
         HelpText<"Alias for --output-target">;
 
-defm new_symbol_visibility : Eq<"new-symbol-visibility", "Visibility of "
-                                "symbols generated for binary input or added"
-                                " with --add-symbol unless otherwise"
-                                " specified. The default value is 'default'">;
+defm new_symbol_visibility
+    : Eq<"new-symbol-visibility", "Visibility of "
+                                  "symbols generated for binary input or added"
+                                  " with --add-symbol unless otherwise"
+                                  " specified. The default value is 'default'">;
 
 def compress_debug_sections
     : Joined<["--"], "compress-debug-sections=">,
       MetaVarName<"format">,
-      HelpText<"Compress DWARF debug sections using specified format. Supported "
-               "formats: zlib, zstd. Select zlib if <format> is omitted">;
-def : Flag<["--"], "compress-debug-sections">, Alias<compress_debug_sections>,
+      HelpText<
+          "Compress DWARF debug sections using specified format. Supported "
+          "formats: zlib, zstd. Select zlib if <format> is omitted">;
+def : Flag<["--"], "compress-debug-sections">,
+      Alias<compress_debug_sections>,
       AliasArgs<["zlib"]>;
 def decompress_debug_sections : Flag<["--"], "decompress-debug-sections">,
                                 HelpText<"Decompress DWARF debug sections">;
@@ -64,7 +67,7 @@ defm redefine_symbols
          "contains two symbols per line separated with whitespace and may "
          "contain comments beginning with '#'. Leading and trailing "
          "whitespace is stripped from each line. May be repeated to read "
-         "symbols from many files">,         
+         "symbols from many files">,
       MetaVarName<"filename">;
 
 defm only_section : Eq<"only-section", "Remove all but <section>">,
@@ -93,9 +96,7 @@ defm set_section_type
          "Set the type of section <section> to the integer <type>">,
       MetaVarName<"section=type">;
 
-def S : Flag<["-"], "S">,
-        Alias<strip_all>,
-        HelpText<"Alias for --strip-all">;
+def S : Flag<["-"], "S">, Alias<strip_all>, HelpText<"Alias for --strip-all">;
 def strip_dwo : Flag<["--"], "strip-dwo">,
                 HelpText<"Remove all DWARF .dwo sections from file">;
 def strip_non_alloc
@@ -111,10 +112,8 @@ defm strip_unneeded_symbols
          "if they are not needed by relocations">,
       MetaVarName<"filename">;
 
-defm subsystem
-    : Eq<"subsystem",
-         "Set PE subsystem and version">,
-      MetaVarName<"name[:version]">;
+defm subsystem : Eq<"subsystem", "Set PE subsystem and version">,
+                 MetaVarName<"name[:version]">;
 
 def extract_dwo
     : Flag<["--"], "extract-dwo">,
@@ -205,28 +204,45 @@ defm prefix_symbols
       MetaVarName<"prefix">;
 
 defm prefix_alloc_sections
-    : Eq<"prefix-alloc-sections", "Add <prefix> to the start of every allocated section name">,
+    : Eq<"prefix-alloc-sections",
+         "Add <prefix> to the start of every allocated section name">,
       MetaVarName<"prefix">;
 
-defm set_start : Eq<"set-start", "Set the start address to <addr>. Overrides "
-                    "any previous --change-start or --adjust-start values">,
-                 MetaVarName<"addr">;
-defm change_start : Eq<"change-start", "Add <incr> to the start address. Can be "                        
-                       "specified multiple times, all values will be applied "
-                       "cumulatively">,
-                    MetaVarName<"incr">;
+defm set_start
+    : Eq<"set-start", "Set the start address to <addr>. Overrides "
+                      "any previous --change-start or --adjust-start values">,
+      MetaVarName<"addr">;
+defm change_start
+    : Eq<"change-start", "Add <incr> to the start address. Can be "
+                         "specified multiple times, all values will be applied "
+                         "cumulatively">,
+      MetaVarName<"incr">;
 def adjust_start : JoinedOrSeparate<["--"], "adjust-start">,
                    Alias<change_start>,
                    HelpText<"Alias for --change-start">;
 
 defm add_symbol
-    : Eq<"add-symbol", "Add new symbol <name> to .symtab. Accepted flags: "
-         "global, local, weak, default, hidden, protected, file, section, object, "
+    : Eq<"add-symbol",
+         "Add new symbol <name> to .symtab. Accepted flags: "
+         "global, local, weak, default, hidden, protected, file, section, "
+         "object, "
          "function, indirect-function. Accepted but ignored for "
          "compatibility: debug, constructor, warning, indirect, synthetic, "
          "unique-object, before">,
       MetaVarName<"name=[section:]value[,flags]">;
 
 defm update_section
-    : Eq<"update-section", "Replace the contents of section <name> with contents from a file <file>">,
+    : Eq<"update-section", "Replace the contents of section <name> with "
+                           "contents from a file <file>">,
       MetaVarName<"name=file">;
+
+defm adjust_section_vma
+    : Eq<"adjust-section-vma",
+         "Adjust VMA and LMA of section <section> by <value>"
+         ""
+         "">,
+      MetaVarName<".section{=|+|-}value">;
+defm adjust_vma : Eq<"adjust-vma", "Add <incr> to the vma and lma address."
+                                   ""
+                                   "">,
+                  MetaVarName<"incr">;



More information about the llvm-commits mailing list