[llvm] Add adjustVMA option (PR #72870)

via llvm-commits llvm-commits at lists.llvm.org
Thu Dec 14 01:03:23 PST 2023


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

>From 12d0412fc7dbcf5484555a8843a821655d72df46 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       |   6 +
 llvm/include/llvm/ObjCopy/CommonConfig.h      |  11 ++
 llvm/lib/ObjCopy/COFF/COFFObjcopy.cpp         |   6 +
 llvm/lib/ObjCopy/ELF/ELFObjcopy.cpp           |  29 ++++
 llvm/lib/ObjCopy/MachO/MachOObjcopy.cpp       |   6 +
 llvm/lib/ObjCopy/wasm/WasmObjcopy.cpp         |   6 +
 .../llvm-objcopy/ELF/adjust-section-vma.test  | 130 +++++++++++++++++
 .../tools/llvm-objcopy/ELF/adjust-vma.test    | 131 ++++++++++++++++++
 llvm/tools/llvm-objcopy/ObjcopyOptions.cpp    |  66 ++++++++-
 llvm/tools/llvm-objcopy/ObjcopyOpts.td        |   8 ++
 10 files changed, 395 insertions(+), 4 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..348cfdf8b3ab57 100644
--- a/llvm/docs/CommandGuide/llvm-objcopy.rst
+++ b/llvm/docs/CommandGuide/llvm-objcopy.rst
@@ -483,6 +483,12 @@ them.
 
  Mark all defined global symbols as weak in the output.
 
+.. option:: --adjust-vma <value>
+  Add ``<value>`` to VMA and LMA address
+
+.. option:: --adjust-section-vma <name>{+|-|=}<value>
+  Adjust section ``<name>`` VMA and LMA address by ``<value>``
+
 MACH-O-SPECIFIC OPTIONS
 -----------------------
 
diff --git a/llvm/include/llvm/ObjCopy/CommonConfig.h b/llvm/include/llvm/ObjCopy/CommonConfig.h
index e7ce1e6f2c54d7..28f9abe22a515f 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)
@@ -245,6 +253,9 @@ struct CommonConfig {
   StringMap<uint64_t> SetSectionType;
   StringMap<StringRef> SymbolsToRename;
 
+  // Adjust section VMA and LMA
+  StringMap<SectionVMAUpdate> AdjustSectionVMA;
+
   // Symbol info specified by --add-symbol option.
   std::vector<NewSymbolInfo> SymbolsToAdd;
 
diff --git a/llvm/lib/ObjCopy/COFF/COFFObjcopy.cpp b/llvm/lib/ObjCopy/COFF/COFFObjcopy.cpp
index 622726be8ce5a3..36e07d26760756 100644
--- a/llvm/lib/ObjCopy/COFF/COFFObjcopy.cpp
+++ b/llvm/lib/ObjCopy/COFF/COFFObjcopy.cpp
@@ -316,6 +316,12 @@ static Error handleArgs(const CommonConfig &Config,
       Obj.PeHeader.MinorSubsystemVersion = *COFFConfig.MinorSubsystemVersion;
   }
 
+  if (!Config.AdjustSectionVMA.empty()) {
+    return createStringError(
+        errc::invalid_argument,
+        "Adjustment of VMA and LMA addresses not supported!");
+  }
+
   return Error::success();
 }
 
diff --git a/llvm/lib/ObjCopy/ELF/ELFObjcopy.cpp b/llvm/lib/ObjCopy/ELF/ELFObjcopy.cpp
index 9d02ba051a0a84..b8939cda0580fb 100644
--- a/llvm/lib/ObjCopy/ELF/ELFObjcopy.cpp
+++ b/llvm/lib/ObjCopy/ELF/ELFObjcopy.cpp
@@ -653,6 +653,35 @@ 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 (((Sec.Flags & ELF::SHF_ALLOC) || (Sec.Flags & ELF::SHT_RELA)) &&
+        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/lib/ObjCopy/MachO/MachOObjcopy.cpp b/llvm/lib/ObjCopy/MachO/MachOObjcopy.cpp
index 91500c2d9dd47d..9d0dab2680412f 100644
--- a/llvm/lib/ObjCopy/MachO/MachOObjcopy.cpp
+++ b/llvm/lib/ObjCopy/MachO/MachOObjcopy.cpp
@@ -442,6 +442,12 @@ static Error handleArgs(const CommonConfig &Config,
   if (Error E = processLoadCommands(MachOConfig, Obj))
     return E;
 
+  if (!Config.AdjustSectionVMA.empty()) {
+    return createStringError(
+        errc::invalid_argument,
+        "Adjustment of VMA and LMA addresses not supported!");
+  }
+
   return Error::success();
 }
 
diff --git a/llvm/lib/ObjCopy/wasm/WasmObjcopy.cpp b/llvm/lib/ObjCopy/wasm/WasmObjcopy.cpp
index e5af59f93280a4..de8a7fdc7afcac 100644
--- a/llvm/lib/ObjCopy/wasm/WasmObjcopy.cpp
+++ b/llvm/lib/ObjCopy/wasm/WasmObjcopy.cpp
@@ -138,6 +138,12 @@ static Error handleArgs(const CommonConfig &Config, Object &Obj) {
     Obj.addSectionWithOwnedContents(Sec, std::move(BufferCopy));
   }
 
+  if (!Config.AdjustSectionVMA.empty()) {
+    return createStringError(
+        errc::invalid_argument,
+        "Adjustment of VMA and LMA addresses not supported!");
+  }
+
   return Error::success();
 }
 
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..639addc11c65fa
--- /dev/null
+++ b/llvm/test/tools/llvm-objcopy/ELF/adjust-vma.test
@@ -0,0 +1,131 @@
+# RUN: yaml2obj %s -o %t
+# RUN: llvm-objdump --all-headers -D -z %t | FileCheck %s --check-prefixes=COMMON,NOADJUST
+# RUN: llvm-objcopy --adjust-vma 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 0000000000123000 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.
+
+# 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)
+
+# 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/tools/llvm-objcopy/ObjcopyOptions.cpp b/llvm/tools/llvm-objcopy/ObjcopyOptions.cpp
index 57129025394437..0bfce9c8fea542 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,20 @@ 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");
     }
 
   if (Config.DecompressDebugSections &&
@@ -1250,8 +1308,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