[llvm] Add adjustVMA option (PR #72870)

via llvm-commits llvm-commits at lists.llvm.org
Wed Feb 14 04:40:01 PST 2024


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

>From 8b4fbe07ebbe14e0f7e5a242dcaf53c1965338f0 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/docs/CommandGuide/llvm-objcopy.rst       |   7 +
 llvm/include/llvm/ObjCopy/CommonConfig.h      |   9 ++
 llvm/lib/ObjCopy/ConfigManager.cpp            |  11 +-
 llvm/lib/ObjCopy/ELF/ELFObjcopy.cpp           |  28 ++++
 .../llvm-objcopy/ELF/adjust-section-vma.test  | 130 ++++++++++++++++
 .../tools/llvm-objcopy/ELF/adjust-vma.test    | 146 ++++++++++++++++++
 llvm/tools/llvm-objcopy/ObjcopyOptions.cpp    |  71 ++++++++-
 llvm/tools/llvm-objcopy/ObjcopyOpts.td        |   8 +
 8 files changed, 402 insertions(+), 8 deletions(-)
 create mode 100644 llvm/test/tools/llvm-objcopy/ELF/adjust-section-vma.test
 create mode 100644 llvm/test/tools/llvm-objcopy/ELF/adjust-vma.test

diff --git a/llvm/docs/CommandGuide/llvm-objcopy.rst b/llvm/docs/CommandGuide/llvm-objcopy.rst
index 0233a4f7b2f045..4a6b97443c23c2 100644
--- a/llvm/docs/CommandGuide/llvm-objcopy.rst
+++ b/llvm/docs/CommandGuide/llvm-objcopy.rst
@@ -483,6 +483,13 @@ them.
 
  Mark all defined global symbols as weak in the output.
 
+.. option:: --adjust-vma <value>
+  Add ``<value>`` to start address and VMA and LMA addresses of sections.
+
+.. option:: --adjust-section-vma <name>{+|-|=}<value>
+  Adjust section ``<name>`` VMA and LMA address by ``<value>``.
+  Address can be either increased (+), decreased (-) or set (=) to  ``<value>``.
+
 MACH-O-SPECIFIC OPTIONS
 -----------------------
 
diff --git a/llvm/include/llvm/ObjCopy/CommonConfig.h b/llvm/include/llvm/ObjCopy/CommonConfig.h
index e7ce1e6f2c54d7..0dcfee805170ac 100644
--- a/llvm/include/llvm/ObjCopy/CommonConfig.h
+++ b/llvm/include/llvm/ObjCopy/CommonConfig.h
@@ -84,6 +84,14 @@ struct SectionFlagsUpdate {
   SectionFlag NewFlags;
 };
 
+enum class SectionUpdateType { Increase, Decrease, Set };
+
+struct SectionVMAUpdate {
+  int64_t UpdateValue;
+  StringRef UpdateSection;
+  SectionUpdateType UpdateAs;
+};
+
 enum class DiscardType {
   None,   // Default
   All,    // --discard-all (-x)
@@ -244,6 +252,7 @@ struct CommonConfig {
   StringMap<SectionFlagsUpdate> SetSectionFlags;
   StringMap<uint64_t> SetSectionType;
   StringMap<StringRef> SymbolsToRename;
+  StringMap<SectionVMAUpdate> AdjustSectionVMA;
 
   // Symbol info specified by --add-symbol option.
   std::vector<NewSymbolInfo> SymbolsToAdd;
diff --git a/llvm/lib/ObjCopy/ConfigManager.cpp b/llvm/lib/ObjCopy/ConfigManager.cpp
index bccb2903e62aeb..7e29bf2872290b 100644
--- a/llvm/lib/ObjCopy/ConfigManager.cpp
+++ b/llvm/lib/ObjCopy/ConfigManager.cpp
@@ -23,7 +23,8 @@ Expected<const COFFConfig &> ConfigManager::getCOFFConfig() const {
       Common.ExtractDWO || Common.PreserveDates || Common.StripDWO ||
       Common.StripNonAlloc || Common.StripSections || Common.Weaken ||
       Common.DecompressDebugSections ||
-      Common.DiscardMode == DiscardType::Locals || !Common.SymbolsToAdd.empty())
+      Common.DiscardMode == DiscardType::Locals ||
+      !Common.SymbolsToAdd.empty() || !Common.AdjustSectionVMA.empty())
     return createStringError(llvm::errc::invalid_argument,
                              "option is not supported for COFF");
 
@@ -42,7 +43,8 @@ Expected<const MachOConfig &> ConfigManager::getMachOConfig() const {
       Common.PreserveDates || Common.StripAllGNU || Common.StripDWO ||
       Common.StripNonAlloc || Common.StripSections ||
       Common.DecompressDebugSections || Common.StripUnneeded ||
-      Common.DiscardMode == DiscardType::Locals || !Common.SymbolsToAdd.empty())
+      Common.DiscardMode == DiscardType::Locals ||
+      !Common.SymbolsToAdd.empty() || !Common.AdjustSectionVMA.empty())
     return createStringError(llvm::errc::invalid_argument,
                              "option is not supported for MachO");
 
@@ -60,7 +62,7 @@ Expected<const WasmConfig &> ConfigManager::getWasmConfig() const {
       !Common.SymbolsToWeaken.empty() || !Common.SymbolsToKeepGlobal.empty() ||
       !Common.SectionsToRename.empty() || !Common.SetSectionAlignment.empty() ||
       !Common.SetSectionFlags.empty() || !Common.SetSectionType.empty() ||
-      !Common.SymbolsToRename.empty())
+      !Common.SymbolsToRename.empty() || !Common.AdjustSectionVMA.empty())
     return createStringError(llvm::errc::invalid_argument,
                              "only flags for section dumping, removal, and "
                              "addition are supported");
@@ -86,7 +88,8 @@ Expected<const XCOFFConfig &> ConfigManager::getXCOFFConfig() const {
       Common.ExtractMainPartition || Common.OnlyKeepDebug ||
       Common.PreserveDates || Common.StripAllGNU || Common.StripDWO ||
       Common.StripDebug || Common.StripNonAlloc || Common.StripSections ||
-      Common.Weaken || Common.StripUnneeded || Common.DecompressDebugSections) {
+      Common.Weaken || Common.StripUnneeded || Common.DecompressDebugSections ||
+      !Common.AdjustSectionVMA.empty()) {
     return createStringError(
         llvm::errc::invalid_argument,
         "no flags are supported yet, only basic copying is allowed");
diff --git a/llvm/lib/ObjCopy/ELF/ELFObjcopy.cpp b/llvm/lib/ObjCopy/ELF/ELFObjcopy.cpp
index 9d02ba051a0a84..4fd5b42209a7d6 100644
--- a/llvm/lib/ObjCopy/ELF/ELFObjcopy.cpp
+++ b/llvm/lib/ObjCopy/ELF/ELFObjcopy.cpp
@@ -653,6 +653,34 @@ static Error handleArgs(const CommonConfig &Config, const ELFConfig &ELFConfig,
     }
   }
 
+  // Handle VMA adjustment
+  for (SectionBase &Sec : Obj.sections()) {
+    SectionVMAUpdate SectionUpdate;
+    bool AdjustThisSection = false;
+    if (auto It = Config.AdjustSectionVMA.find(Sec.Name);
+        It != Config.AdjustSectionVMA.end()) {
+      AdjustThisSection = true;
+      SectionUpdate = It->second;
+    } else if (auto It = Config.AdjustSectionVMA.find("*");
+               It != Config.AdjustSectionVMA.end()) {
+      AdjustThisSection = true;
+      SectionUpdate = It->second;
+    }
+    if (AdjustThisSection) {
+      switch (SectionUpdate.UpdateAs) {
+      case SectionUpdateType::Increase:
+        Sec.Addr += SectionUpdate.UpdateValue;
+        break;
+      case SectionUpdateType::Decrease:
+        Sec.Addr -= SectionUpdate.UpdateValue;
+        break;
+      case SectionUpdateType::Set:
+        Sec.Addr = SectionUpdate.UpdateValue;
+        break;
+      }
+    }
+  }
+
   if (Config.OnlyKeepDebug)
     for (auto &Sec : Obj.sections())
       if (Sec.Flags & SHF_ALLOC && Sec.Type != SHT_NOTE)
diff --git a/llvm/test/tools/llvm-objcopy/ELF/adjust-section-vma.test b/llvm/test/tools/llvm-objcopy/ELF/adjust-section-vma.test
new file mode 100644
index 00000000000000..99eaab46708217
--- /dev/null
+++ b/llvm/test/tools/llvm-objcopy/ELF/adjust-section-vma.test
@@ -0,0 +1,130 @@
+# RUN: yaml2obj %s -o %t
+# RUN: llvm-objdump --all-headers -D -z %t | FileCheck %s --check-prefixes=COMMON,NOADJUST
+# RUN: llvm-objcopy --adjust-section-vma .text+0x123000 %t
+# RUN: llvm-objdump --all-headers -D -z %t | FileCheck %s --check-prefixes=COMMON,ADJUST
+# RUN: llvm-objcopy --adjust-section-vma .text-0x123000 %t
+# RUN: llvm-objdump --all-headers -D -z %t | FileCheck %s --check-prefixes=COMMON,NOADJUST
+# RUN: llvm-objcopy --adjust-section-vma .text=0x123000 %t
+# RUN: llvm-objdump --all-headers -D -z %t | FileCheck %s --check-prefixes=COMMON,ADJUST
+
+# NOADJUST:      Sections:
+# NOADJUST-NEXT: Idx Name           Size     VMA              Type
+# NOADJUST-NEXT:  0                 00000000 0000000000000000
+# NOADJUST-NEXT:  1 .text           00000002 0000000000000000 TEXT
+# NOADJUST-NEXT:  2 .debug_str      00000004 0000000000000000
+# NOADJUST-NEXT:  3 .rela.debug_str 00000018 0000000000000000
+# NOADJUST-NEXT:  4 .data           00000004 0000000000000000 DATA
+# NOADJUST-NEXT:  5 .rela.data      00000018 0000000000000000
+# NOADJUST-NEXT:  6 .symtab         {{.*}}   0000000000000000
+# NOADJUST-NEXT:  7 .strtab         {{.*}}   0000000000000000
+# NOADJUST-NEXT:  8 .shstrtab       0000003c 0000000000000000
+
+# ADJUST:        Sections:
+# ADJUST-NEXT:   Idx Name           Size     VMA              Type
+# ADJUST-NEXT:    0                 00000000 0000000000000000
+# ADJUST-NEXT:    1 .text           00000002 0000000000123000 TEXT
+# ADJUST-NEXT:    2 .debug_str      00000004 0000000000000000
+# ADJUST-NEXT:    3 .rela.debug_str 00000018 0000000000000000
+# ADJUST-NEXT:    4 .data           00000004 0000000000000000 DATA
+# ADJUST-NEXT:    5 .rela.data      00000018 0000000000000000
+# ADJUST-NEXT:    6 .symtab         {{.*}}   0000000000000000
+# ADJUST-NEXT:    7 .strtab         {{.*}}   0000000000000000
+# ADJUST-NEXT:    8 .shstrtab       0000003c 0000000000000000
+
+# NOADJUST:      SYMBOL TABLE:
+# NOADJUST-NEXT:  0000000000000001  l F .text      0000000000000000 func
+# NOADJUST-NEXT:  0000000000000000  l   .text      0000000000000000 sym
+# NOADJUST-NEXT:  0000000000000000  l d .text      0000000000000000 .text
+# NOADJUST-NEXT:  0000000000003333  l   *ABS*      0000000000000000 abs
+# NOADJUST-NEXT:  0000000000000000  l   .debug_str 0000000000000000 debug_str_sym
+
+# ADJUST:        SYMBOL TABLE:
+# ADJUST-NEXT:    0000000000123001  l F .text      0000000000000000 func
+# ADJUST-NEXT:    0000000000123000  l   .text      0000000000000000 sym
+# ADJUST-NEXT:    0000000000123000  l d .text      0000000000000000 .text
+# ADJUST-NEXT:    0000000000003333  l   *ABS*      0000000000000000 abs
+# ADJUST-NEXT:    0000000000000000  l   .debug_str 0000000000000000 debug_str_sym
+
+# NOADJUST:      0000000000000000 <sym>:
+# NOADJUST-NEXT:   0: {{.*}}  nop
+# NOADJUST:      0000000000000001 <func>:
+# NOADJUST-NEXT:   1: {{.*}}  retq
+
+# ADJUST:        0000000000123000 <sym>:
+# ADJUST-NEXT:     123000: {{.*}} nop
+# ADJUST:        0000000000123001 <func>:
+# ADJUST-NEXT:     123001: {{.*}} retq
+
+# COMMON:      0000000000000000 <debug_str_sym>:
+# COMMON-NEXT:   0: {{.*}}  %al, (%rax)
+# COMMON-NEXT:      0000000000000001:  R_X86_64_32  .text
+# COMMON-NEXT:   2: {{.*}}  addb    %al, (%rax)
+
+# COMMON:        0000000000000000    <.rela.debug_str>:
+# COMMON-NEXT:     0: {{.*}}  addl %eax, (%rax)
+## ... There are more lines here. We do not care.
+
+# COMMON:      0000000000000000  <.data>:
+# COMMON-NEXT:  0: {{.*}} addb    %al, (%rax)
+# COMMON-NEXT: 0000000000000000: R_X86_64_32  .text
+# COMMON-NEXT:  2: {{.*}} addb    %al, (%rax)
+
+# COMMON:        0000000000000000   <.rela.data>:
+# COMMON-NEXT:    0: {{.*}} addb %al, (%rax)
+## ... There are more lines here. We do not care.
+
+--- !ELF
+FileHeader:      
+  Class:           ELFCLASS64
+  Data:            ELFDATA2LSB
+  Type:            ET_REL
+  Machine:         EM_X86_64
+Sections:        
+  - Name:            .text
+    Type:            SHT_PROGBITS
+    Flags:           [ SHF_ALLOC, SHF_EXECINSTR ]
+    AddressAlign:    0x0000000000000004
+    Content:         90C3
+  - Name:            .debug_str
+    Type:            SHT_PROGBITS
+    Flags:           [ SHF_MERGE, SHF_STRINGS ]
+    AddressAlign:    0x0000000000000001
+    Content:         '00000000'
+  - Name:            .rela.debug_str
+    Type:            SHT_RELA
+    Link:            .symtab
+    AddressAlign:    0x0000000000000008
+    Info:            .debug_str
+    Relocations:     
+      - Offset:          0x0000000000000001
+        Symbol:          .text
+        Type:            R_X86_64_32
+  - Name:            .data
+    Type:            SHT_PROGBITS
+    Flags:           [ SHF_WRITE, SHF_ALLOC ]
+    AddressAlign:    0x0000000000000001
+    Content:         '00000000'
+  - Name:            .rela.data
+    Type:            SHT_RELA
+    Link:            .symtab
+    AddressAlign:    0x0000000000000008
+    Info:            .data
+    Relocations:     
+      - Offset:      0x0000000000000000
+        Symbol:      .text
+        Type:        R_X86_64_32
+Symbols:
+  - Name:            func
+    Type:            STT_FUNC
+    Section:         .text
+    Value:           0x0000000000000001
+  - Name:            sym
+    Section:         .text
+  - Name:            .text
+    Type:            STT_SECTION
+    Section:         .text
+  - Name:            abs
+    Index:           SHN_ABS
+    Value:           0x3333
+  - Name:            debug_str_sym
+    Section:         .debug_str
diff --git a/llvm/test/tools/llvm-objcopy/ELF/adjust-vma.test b/llvm/test/tools/llvm-objcopy/ELF/adjust-vma.test
new file mode 100644
index 00000000000000..93fa534ff3c94f
--- /dev/null
+++ b/llvm/test/tools/llvm-objcopy/ELF/adjust-vma.test
@@ -0,0 +1,146 @@
+# RUN: yaml2obj %s -o %t
+# RUN: llvm-objdump --all-headers -D -z %t | FileCheck %s --check-prefixes=NOADJUST
+# RUN: llvm-objcopy --adjust-vma 0x123000 %t
+# RUN: llvm-objdump --all-headers -D -z %t | FileCheck %s --check-prefixes=ADJUST
+
+# NOADJUST:      Sections:
+# NOADJUST-NEXT: Idx Name           Size     VMA              Type
+# NOADJUST-NEXT:  0                 00000000 0000000000000000
+# NOADJUST-NEXT:  1 .text           00000002 0000000000000000 TEXT
+# NOADJUST-NEXT:  2 .debug_str      00000004 0000000000000000
+# NOADJUST-NEXT:  3 .rela.debug_str 00000018 0000000000000000
+# NOADJUST-NEXT:  4 .data           00000004 0000000000000000 DATA
+# NOADJUST-NEXT:  5 .rela.data      00000018 0000000000000000
+# NOADJUST-NEXT:  6 .symtab         {{.*}}   0000000000000000
+# NOADJUST-NEXT:  7 .strtab         {{.*}}   0000000000000000
+# NOADJUST-NEXT:  8 .shstrtab       0000003c 0000000000000000
+
+# ADJUST:        Sections:
+# ADJUST-NEXT:   Idx Name           Size     VMA              Type
+# ADJUST-NEXT:    0                 00000000 0000000000000000
+# ADJUST-NEXT:    1 .text           00000002 0000000000123000 TEXT
+# ADJUST-NEXT:    2 .debug_str      00000004 0000000000123000
+# ADJUST-NEXT:    3 .rela.debug_str 00000018 0000000000123000
+# ADJUST-NEXT:    4 .data           00000004 0000000000123000 DATA
+# ADJUST-NEXT:    5 .rela.data      00000018 0000000000123000
+# ADJUST-NEXT:    6 .symtab         {{.*}}   0000000000123000
+# ADJUST-NEXT:    7 .strtab         {{.*}}   0000000000123000
+# ADJUST-NEXT:    8 .shstrtab       0000003c 0000000000123000
+
+# NOADJUST:      SYMBOL TABLE:
+# NOADJUST-NEXT:  0000000000000001  l F .text      0000000000000000 func
+# NOADJUST-NEXT:  0000000000000000  l   .text      0000000000000000 sym
+# NOADJUST-NEXT:  0000000000000000  l d .text      0000000000000000 .text
+# NOADJUST-NEXT:  0000000000003333  l   *ABS*      0000000000000000 abs
+# NOADJUST-NEXT:  0000000000000000  l   .debug_str 0000000000000000 debug_str_sym
+
+# ADJUST:        SYMBOL TABLE:
+# ADJUST-NEXT:    0000000000123001  l F .text      0000000000000000 func
+# ADJUST-NEXT:    0000000000123000  l   .text      0000000000000000 sym
+# ADJUST-NEXT:    0000000000123000  l d .text      0000000000000000 .text
+# ADJUST-NEXT:    0000000000003333  l   *ABS*      0000000000000000 abs
+# ADJUST-NEXT:    0000000000123000  l   .debug_str 0000000000000000 debug_str_sym
+
+# NOADJUST:      0000000000000000 <sym>:
+# NOADJUST-NEXT:   0: {{.*}}  nop
+# NOADJUST:      0000000000000001 <func>:
+# NOADJUST-NEXT:   1: {{.*}}  retq
+
+# ADJUST:        0000000000123000 <sym>:
+# ADJUST-NEXT:     123000: {{.*}} nop
+# ADJUST:        0000000000123001 <func>:
+# ADJUST-NEXT:     123001: {{.*}} retq
+
+# NOADJUST:      0000000000000000 <debug_str_sym>:
+# NOADJUST-NEXT:   0: {{.*}}  %al, (%rax)
+# NOADJUST-NEXT:      0000000000000001:  R_X86_64_32  .text
+# NOADJUST-NEXT:   2: {{.*}}  addb    %al, (%rax)
+
+# ADJUST:      0000000000123000 <debug_str_sym>:
+# ADJUST-NEXT:   123000: {{.*}}  %al, (%rax)
+# ADJUST-NEXT:      0000000000123001:  R_X86_64_32  .text
+# ADJUST-NEXT:   123002: {{.*}}  addb    %al, (%rax)
+
+
+# NOADJUST:        0000000000000000    <.rela.debug_str>:
+# NOADJUST-NEXT:     0: {{.*}}  addl %eax, (%rax)
+## ... There are more lines here. We do not care.
+
+# ADJUST:        0000000000123000    <.rela.debug_str>:
+# ADJUST-NEXT:     123000: {{.*}}  addl %eax, (%rax)
+## ... There are more lines here. We do not care.
+
+
+# NOADJUST:      0000000000000000  <.data>:
+# NOADJUST-NEXT:  0: {{.*}} addb    %al, (%rax)
+# NOADJUST-NEXT: 0000000000000000: R_X86_64_32  .text
+# NOADJUST-NEXT:  2: {{.*}} addb    %al, (%rax)
+
+# ADJUST:        0000000000123000  <.data>:
+# ADJUST-NEXT:    123000: {{.*}}  addb    %al, (%rax)
+# ADJUST-NEXT:   0000000000123000: R_X86_64_32  .text
+# ADJUST-NEXT:    123002: {{.*}}  addb    %al, (%rax)
+
+# NOADJUST:        0000000000000000   <.rela.data>:
+# NOADJUST-NEXT:    0: {{.*}} addb %al, (%rax)
+## ... There are more lines here. We do not care.
+
+# ADJUST:        0000000000123000   <.rela.data>:
+# ADJUST-NEXT:    123000: {{.*}} addb %al, (%rax)
+## ... There are more lines here. We do not care.
+
+--- !ELF
+FileHeader:      
+  Class:           ELFCLASS64
+  Data:            ELFDATA2LSB
+  Type:            ET_REL
+  Machine:         EM_X86_64
+Sections:        
+  - Name:            .text
+    Type:            SHT_PROGBITS
+    Flags:           [ SHF_ALLOC, SHF_EXECINSTR ]
+    AddressAlign:    0x0000000000000004
+    Content:         90C3
+  - Name:            .debug_str
+    Type:            SHT_PROGBITS
+    Flags:           [ SHF_MERGE, SHF_STRINGS ]
+    AddressAlign:    0x0000000000000001
+    Content:         '00000000'
+  - Name:            .rela.debug_str
+    Type:            SHT_RELA
+    Link:            .symtab
+    AddressAlign:    0x0000000000000008
+    Info:            .debug_str
+    Relocations:     
+      - Offset:          0x0000000000000001
+        Symbol:          .text
+        Type:            R_X86_64_32
+  - Name:            .data
+    Type:            SHT_PROGBITS
+    Flags:           [ SHF_WRITE, SHF_ALLOC ]
+    AddressAlign:    0x0000000000000001
+    Content:         '00000000'
+  - Name:            .rela.data
+    Type:            SHT_RELA
+    Link:            .symtab
+    AddressAlign:    0x0000000000000008
+    Info:            .data
+    Relocations:     
+      - Offset:      0x0000000000000000
+        Symbol:      .text
+        Type:        R_X86_64_32
+Symbols:
+  - Name:            func
+    Type:            STT_FUNC
+    Section:         .text
+    Value:           0x0000000000000001
+  - Name:            sym
+    Section:         .text
+  - Name:            .text
+    Type:            STT_SECTION
+    Section:         .text
+  - Name:            abs
+    Index:           SHN_ABS
+    Value:           0x3333
+  - Name:            debug_str_sym
+    Section:         .debug_str
diff --git a/llvm/tools/llvm-objcopy/ObjcopyOptions.cpp b/llvm/tools/llvm-objcopy/ObjcopyOptions.cpp
index 57129025394437..086a366edb949c 100644
--- a/llvm/tools/llvm-objcopy/ObjcopyOptions.cpp
+++ b/llvm/tools/llvm-objcopy/ObjcopyOptions.cpp
@@ -532,6 +532,38 @@ 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 Expected<SectionVMAUpdate> parseAdjustSectionVMA(StringRef ArgValue,
+                                                        StringRef OptionName) {
+  SectionVMAUpdate SectionUpdate;
+  std::pair<StringRef, StringRef> SecPair;
+  if (ArgValue.contains("=")) {
+    SectionUpdate.UpdateAs = SectionUpdateType::Set;
+    SecPair = ArgValue.split("=");
+  } else if (ArgValue.contains("+")) {
+    SectionUpdate.UpdateAs = SectionUpdateType::Increase;
+    SecPair = ArgValue.split("+");
+  } else if (ArgValue.contains("-")) {
+    SectionUpdate.UpdateAs = SectionUpdateType::Decrease;
+    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");
+  SectionUpdate.UpdateSection = SecPair.first;
+  auto ChangeValue = getAsInteger<int64_t>(SecPair.second);
+  if (!ChangeValue)
+    return createStringError(ChangeValue.getError(),
+                             "Unable to parse adjustment value");
+  SectionUpdate.UpdateValue = *ChangeValue;
+  return SectionUpdate;
+}
+
 // parseObjcopyOptions returns the config and sets the input arguments. If a
 // help flag is set then parseObjcopyOptions will print the help messege and
 // exit.
@@ -605,8 +637,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;
@@ -827,6 +859,18 @@ objcopy::parseObjcopyOptions(ArrayRef<const char *> RawArgsArr,
                                        Config.UpdateSection))
       return std::move(Err);
   }
+  for (auto *Arg : InputArgs.filtered(OBJCOPY_adjust_section_vma)) {
+    Expected<SectionVMAUpdate> SVMAU =
+        parseAdjustSectionVMA(Arg->getValue(), "--adjust-section-vma");
+    if (!SVMAU)
+      return SVMAU.takeError();
+    if (!Config.AdjustSectionVMA.try_emplace(SVMAU->UpdateSection, *SVMAU)
+             .second)
+      return createStringError(
+          errc::invalid_argument,
+          "--adjust-section-vma set multiple times for section '%s'",
+          SVMAU->UpdateSection.str().c_str());
+  }
   for (auto *Arg : InputArgs.filtered(OBJCOPY_dump_section)) {
     StringRef Value(Arg->getValue());
     if (Value.split('=').second.empty())
@@ -966,6 +1010,25 @@ 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());
+      SectionVMAUpdate SVMAU;
+      SVMAU.UpdateSection = "*";
+      SVMAU.UpdateValue = *EIncr;
+      SVMAU.UpdateAs = SectionUpdateType::Increase;
+      if (!Config.AdjustSectionVMA.try_emplace(SVMAU.UpdateSection, SVMAU)
+               .second)
+        return createStringError(errc::invalid_argument,
+                                 "--adjust-vma set multiple times");
+      auto Expr = ELFConfig.EntryExpr ? std::move(ELFConfig.EntryExpr)
+                                      : [](uint64_t A) { return A; };
+      ELFConfig.EntryExpr = [Expr, EIncr](uint64_t EAddr) {
+        return Expr(EAddr) + *EIncr;
+      };
     }
 
   if (Config.DecompressDebugSections &&
@@ -1250,8 +1313,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 ea8828637222ac..77d00ac8e7377a 100644
--- a/llvm/tools/llvm-objcopy/ObjcopyOpts.td
+++ b/llvm/tools/llvm-objcopy/ObjcopyOpts.td
@@ -230,3 +230,11 @@ defm add_symbol
 defm update_section
     : 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 <name> by <value>">,
+      MetaVarName<"name{=|+|-}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