OSDN Git Service

[llvm-objcopy] Add --set-start, --change-start and --adjust-start
authorEugene Leviant <eleviant@accesssoftek.com>
Tue, 26 Feb 2019 09:24:22 +0000 (09:24 +0000)
committerEugene Leviant <eleviant@accesssoftek.com>
Tue, 26 Feb 2019 09:24:22 +0000 (09:24 +0000)
Differential revision: https://reviews.llvm.org/D58173

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@354854 91177308-0d34-0410-b5e6-96231b3b80d8

test/tools/llvm-objcopy/ELF/change-entry-point.test [new file with mode: 0644]
tools/llvm-objcopy/COFF/COFFObjcopy.cpp
tools/llvm-objcopy/CopyConfig.cpp
tools/llvm-objcopy/CopyConfig.h
tools/llvm-objcopy/ELF/ELFObjcopy.cpp
tools/llvm-objcopy/ObjcopyOpts.td

diff --git a/test/tools/llvm-objcopy/ELF/change-entry-point.test b/test/tools/llvm-objcopy/ELF/change-entry-point.test
new file mode 100644 (file)
index 0000000..8136685
--- /dev/null
@@ -0,0 +1,57 @@
+# RUN: yaml2obj %s -o %t
+
+# Test --set-start.
+# RUN: llvm-objcopy --set-start 0x1000 %t %t2
+# RUN: llvm-readobj --file-headers %t2 | FileCheck %s --check-prefix=SET
+# RUN: llvm-objcopy --set-start 4096 %t %t3
+# RUN: cmp %t2 %t3
+# RUN: llvm-objcopy --set-start 0x100000000 %t %t4
+# RUN: llvm-readobj --file-headers %t4 | FileCheck %s --check-prefix=SET-LARGE
+# RUN: not llvm-objcopy --set-start -123 %t %t5 2>&1 | FileCheck %s --check-prefix=SET-ERR
+
+# Test --change-start.
+# RUN: llvm-objcopy --change-start 0x50 %t %t6
+# RUN: llvm-readobj --file-headers %t6 | FileCheck %s --check-prefix=ADD
+# RUN: llvm-objcopy --change-start 0x100000000 %t %t7
+# RUN: llvm-readobj --file-headers %t7 | FileCheck %s --check-prefix=ADD-LARGE
+# RUN: llvm-objcopy --change-start -4353 %t %t8
+# RUN: llvm-readobj --file-headers %t8 | FileCheck %s --check-prefix=ADD-UNDERFLOW
+# RUN: llvm-objcopy --change-start -0x1101 %t %t9
+# RUN: cmp %t8 %t9
+# RUN: not llvm-objcopy --change-start -xyz %t %t10 2>&1 | FileCheck %s --check-prefix=ADD-ERR
+
+# Test --change-start after --set-start. Result should be 0x1150.
+# RUN: llvm-objcopy --set-start 0x1000 --change-start 0x100 --change-start 0x50 %t %t11
+# RUN: cmp %t6 %t11
+
+# If --set-start is after --change-start then --change-start has no effect.
+# RUN: llvm-objcopy --change-start 0x150 --set-start 0x1000 %t %t12
+# RUN: cmp %t2 %t12
+
+# --adjust-start is an alias for --change-start.
+# RUN: llvm-objcopy --adjust-start -0x1101 %t %t13
+# RUN: cmp %t9 %t13
+
+!ELF
+FileHeader:
+  Class:           ELFCLASS64
+  Data:            ELFDATA2LSB
+  Type:            ET_EXEC
+  Machine:         EM_X86_64
+  Entry:           0x1100
+Sections:
+  - Name:            .text
+    Type:            SHT_PROGBITS
+    Flags:           [ SHF_ALLOC, SHF_EXECINSTR ]
+    Address:         0x1000
+    AddressAlign:    0x0000000000001000
+    Size:            0x200
+
+# SET: Entry: 0x1000
+# ADD: Entry: 0x1150
+# SUB: Entry: 0x1080
+# SET-ERR: error: bad entry point address: '-123'
+# SET-LARGE: Entry: 0x100000000
+# ADD-LARGE: Entry: 0x100001100
+# ADD-ERR: error: bad entry point increment: '-xyz'
+# ADD-UNDERFLOW: Entry: 0xFFFFFFFFFFFFFFFF
index bdc0e4f..92e027f 100644 (file)
@@ -186,7 +186,7 @@ static Error handleArgs(const CopyConfig &Config, Object &Obj) {
       Config.PreserveDates || Config.StripDWO || Config.StripNonAlloc ||
       Config.StripSections || Config.Weaken || Config.DecompressDebugSections ||
       Config.DiscardMode == DiscardType::Locals ||
-      !Config.SymbolsToAdd.empty()) {
+      !Config.SymbolsToAdd.empty() || Config.EntryExpr) {
     return createStringError(llvm::errc::invalid_argument,
                              "Option not supported by llvm-objcopy for COFF");
   }
index 1e8ca51..3972a56 100644 (file)
@@ -371,6 +371,14 @@ static Error addSymbolsToRenameFromFile(StringMap<StringRef> &SymbolsToRename,
   }
   return Error::success();
 }
+
+template <class T> static ErrorOr<T> getAsInteger(StringRef Val) {
+  T Result;
+  if (Val.getAsInteger(0, Result))
+    return errc::invalid_argument;
+  return Result;
+}
+
 // ParseObjcopyOptions returns the config and sets the input arguments. If a
 // help flag is set then ParseObjcopyOptions will print the help messege and
 // exit.
@@ -617,6 +625,27 @@ Expected<DriverConfig> parseObjcopyOptions(ArrayRef<const char *> ArgsArr) {
 
   Config.PreserveDates = InputArgs.hasArg(OBJCOPY_preserve_dates);
 
+  for (auto Arg : InputArgs)
+    if (Arg->getOption().matches(OBJCOPY_set_start)) {
+      auto EAddr = getAsInteger<uint64_t>(Arg->getValue());
+      if (!EAddr)
+        return createStringError(
+            EAddr.getError(), "bad entry point address: '%s'", Arg->getValue());
+
+      Config.EntryExpr = [EAddr](uint64_t) { return *EAddr; };
+    } else if (Arg->getOption().matches(OBJCOPY_change_start)) {
+      auto EIncr = getAsInteger<int64_t>(Arg->getValue());
+      if (!EIncr)
+        return createStringError(EIncr.getError(),
+                                 "bad entry point increment: '%s'",
+                                 Arg->getValue());
+      auto Expr = Config.EntryExpr ? std::move(Config.EntryExpr)
+                                   : [](uint64_t A) { return A; };
+      Config.EntryExpr = [Expr, EIncr](uint64_t EAddr) {
+        return Expr(EAddr) + *EIncr;
+      };
+    }
+
   if (Config.DecompressDebugSections &&
       Config.CompressionType != DebugCompressionType::None) {
     return createStringError(
index 9713294..c9fb4ec 100644 (file)
@@ -113,6 +113,12 @@ struct CopyConfig {
   StringMap<SectionFlagsUpdate> SetSectionFlags;
   StringMap<StringRef> SymbolsToRename;
 
+  // ELF entry point address expression. The input parameter is an entry point
+  // address in the input ELF file. The entry address in the output file is
+  // calculated with EntryExpr(input_address), when either --set-start or
+  // --change-start is used.
+  std::function<uint64_t(uint64_t)> EntryExpr;
+
   // Boolean options
   bool DeterministicArchives = true;
   bool ExtractDWO = false;
index d2696c1..1742213 100644 (file)
@@ -574,6 +574,8 @@ static Error handleArgs(const CopyConfig &Config, Object &Obj,
                                Sec ? SYMBOL_SIMPLE_INDEX : SHN_ABS, 0);
   }
 
+  if (Config.EntryExpr)
+    Obj.Entry = Config.EntryExpr(Obj.Entry);
   return Error::success();
 }
 
index f679ec2..44fd01c 100644 (file)
@@ -238,6 +238,16 @@ def regex
     : Flag<["-", "--"], "regex">,
       HelpText<"Permit regular expressions in name comparison">;
 
+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>;
+
 defm add_symbol
     : Eq<"add-symbol", "Add new symbol <name> to .symtab. Accepted flags: "
          "global, local, weak, default, hidden, file, section, object, "