[llvm] r354787 - [llvm-objcopy] Add --add-symbol

Eugene Leviant via llvm-commits llvm-commits at lists.llvm.org
Mon Feb 25 06:12:41 PST 2019


Author: evgeny777
Date: Mon Feb 25 06:12:41 2019
New Revision: 354787

URL: http://llvm.org/viewvc/llvm-project?rev=354787&view=rev
Log:
[llvm-objcopy] Add --add-symbol

Differential revision: https://reviews.llvm.org/D58234

Added:
    llvm/trunk/test/tools/llvm-objcopy/ELF/add-symbol.test
Modified:
    llvm/trunk/tools/llvm-objcopy/COFF/COFFObjcopy.cpp
    llvm/trunk/tools/llvm-objcopy/CopyConfig.cpp
    llvm/trunk/tools/llvm-objcopy/CopyConfig.h
    llvm/trunk/tools/llvm-objcopy/ELF/ELFObjcopy.cpp
    llvm/trunk/tools/llvm-objcopy/ELF/Object.h
    llvm/trunk/tools/llvm-objcopy/ObjcopyOpts.td

Added: llvm/trunk/test/tools/llvm-objcopy/ELF/add-symbol.test
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/llvm-objcopy/ELF/add-symbol.test?rev=354787&view=auto
==============================================================================
--- llvm/trunk/test/tools/llvm-objcopy/ELF/add-symbol.test (added)
+++ llvm/trunk/test/tools/llvm-objcopy/ELF/add-symbol.test Mon Feb 25 06:12:41 2019
@@ -0,0 +1,76 @@
+# RUN: yaml2obj %s -o %t
+# RUN: llvm-objcopy --add-symbol='abs1=1' \ 
+# RUN:              --add-symbol='abs2=2,LoCaL,HiDdEn,FuNcTiOn' \
+# RUN:              --add-symbol='abs3=3,global,default,object' \
+# RUN:              --add-symbol='foo.cpp=0,file' \
+# RUN:              --add-symbol='=.text:0,section' \
+# RUN:              --add-symbol='data=.data:0x100,weak' \
+# RUN:              --add-symbol='ifunc=.text:0,indirect-function' \
+# RUN:              %t %t2
+# RUN: llvm-readelf -s %t2 | FileCheck %s
+
+# Checked ignored options
+# RUN: llvm-objcopy \
+# RUN:   --add-symbol='dummy1=0,indirect,constructor,debug,synthetic' \
+# RUN:   --add-symbol='dummy2=0,before=foo,unique-object,warning' %t %t3
+# RUN: llvm-readelf -s %t3 | FileCheck %s --check-prefix=IGNORED
+
+# Check errors
+# RUN: not llvm-objcopy --add-symbol='test' %t %t4 2>&1 | FileCheck %s --check-prefix=ERR1
+# RUN: not llvm-objcopy --add-symbol='test=:0' %t %t5 2>&1 | FileCheck %s --check-prefix=ERR2
+# RUN: not llvm-objcopy --add-symbol='test=foo:' %t %t6 2>&1 | FileCheck %s --check-prefix=ERR2
+# RUN: not llvm-objcopy --add-symbol='test=0,cool' %t %t7 2>&1 | FileCheck %s --check-prefix=ERR3
+# RUN: not llvm-objcopy --add-symbol='test=xyz' %t %t8 2>&1 | FileCheck %s --check-prefix=ERR4
+
+!ELF
+FileHeader:
+  Class:           ELFCLASS32
+  Data:            ELFDATA2LSB
+  Type:            ET_EXEC
+  Machine:         EM_ARM
+Sections:
+  - Name:            .text
+    Type:            SHT_PROGBITS
+    Flags:           [ SHF_ALLOC, SHF_EXECINSTR ]
+    Address:         0x1000
+    AddressAlign:    0x0000000000001000
+    Size:            64
+  - Name:            .data
+    Type:            SHT_PROGBITS
+    Flags:           [ SHF_ALLOC ]
+    Address:         0x2000
+    AddressAlign:    0x0000000000001000
+    Size:            64
+ProgramHeaders:
+  - Type: PT_LOAD
+    Flags: [ PF_X, PF_R ]
+    VAddr: 0x1000
+    PAddr: 0x1000
+    Align: 0x1000
+    Sections:
+      - Section: .text
+  - Type: PT_LOAD
+    Flags: [ PF_R, PF_W ]
+    VAddr: 0x2000
+    PAddr: 0x2000
+    Align: 0x1000
+    Sections:
+      - Section: .data
+
+# CHECK:      0: 00000000 0 NOTYPE LOCAL DEFAULT UND 
+# CHECK-NEXT: 1: 00000001 0 NOTYPE GLOBAL DEFAULT ABS abs1
+# CHECK-NEXT: 2: 00000002 0 FUNC LOCAL HIDDEN ABS abs2
+# CHECK-NEXT: 3: 00000003 0 OBJECT GLOBAL DEFAULT ABS abs3
+# CHECK-NEXT: 4: 00000000 0 FILE GLOBAL DEFAULT ABS foo.cpp
+# CHECK-NEXT: 5: 00001000 0 SECTION GLOBAL DEFAULT 1 
+# CHECK-NEXT: 6: 00002100 0 NOTYPE WEAK DEFAULT 2 data
+# CHECK-NEXT: 7: 00001000 0 IFUNC GLOBAL DEFAULT 1 ifunc
+
+# IGNORED:       1: 00000000 0 NOTYPE GLOBAL DEFAULT ABS dummy1
+# IGNORED-NEXT:  2: 00000000 0 NOTYPE GLOBAL DEFAULT ABS dummy2
+
+# ERR1: error: bad format for --add-symbol, missing '=' after 'test'
+# ERR2: error: bad format for --add-symbol, missing section name or symbol value
+# ERR3: error: unsupported flag 'cool' for --add-symbol
+# ERR4: error: bad symbol value: 'xyz'
+

Modified: llvm/trunk/tools/llvm-objcopy/COFF/COFFObjcopy.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-objcopy/COFF/COFFObjcopy.cpp?rev=354787&r1=354786&r2=354787&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-objcopy/COFF/COFFObjcopy.cpp (original)
+++ llvm/trunk/tools/llvm-objcopy/COFF/COFFObjcopy.cpp Mon Feb 25 06:12:41 2019
@@ -185,7 +185,8 @@ static Error handleArgs(const CopyConfig
       Config.ExtractDWO || Config.KeepFileSymbols || Config.LocalizeHidden ||
       Config.PreserveDates || Config.StripDWO || Config.StripNonAlloc ||
       Config.StripSections || Config.Weaken || Config.DecompressDebugSections ||
-      Config.DiscardMode == DiscardType::Locals) {
+      Config.DiscardMode == DiscardType::Locals ||
+      !Config.SymbolsToAdd.empty()) {
     return createStringError(llvm::errc::invalid_argument,
                              "Option not supported by llvm-objcopy for COFF");
   }

Modified: llvm/trunk/tools/llvm-objcopy/CopyConfig.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-objcopy/CopyConfig.cpp?rev=354787&r1=354786&r2=354787&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-objcopy/CopyConfig.cpp (original)
+++ llvm/trunk/tools/llvm-objcopy/CopyConfig.cpp Mon Feb 25 06:12:41 2019
@@ -13,7 +13,6 @@
 #include "llvm/ADT/Optional.h"
 #include "llvm/ADT/SmallVector.h"
 #include "llvm/ADT/StringRef.h"
-#include "llvm/Object/ELFTypes.h"
 #include "llvm/Option/Arg.h"
 #include "llvm/Option/ArgList.h"
 #include "llvm/Support/CommandLine.h"
@@ -206,6 +205,76 @@ parseSetSectionFlagValue(StringRef FlagV
   return SFU;
 }
 
+static NewSymbolInfo parseNewSymbolInfo(StringRef FlagValue) {
+  // Parse value given with --add-symbol option and create the
+  // new symbol if possible. The value format for --add-symbol is:
+  //
+  // <name>=[<section>:]<value>[,<flags>]
+  //
+  // where:
+  // <name> - symbol name, can be empty string
+  // <section> - optional section name. If not given ABS symbol is created
+  // <value> - symbol value, can be decimal or hexadecimal number prefixed
+  //           with 0x.
+  // <flags> - optional flags affecting symbol type, binding or visibility:
+  //           The following are currently supported:
+  //
+  //           global, local, weak, default, hidden, file, section, object,
+  //           indirect-function.
+  //
+  //           The following flags are ignored and provided for GNU
+  //           compatibility only:
+  //
+  //           warning, debug, constructor, indirect, synthetic,
+  //           unique-object, before=<symbol>.
+  NewSymbolInfo SI;
+  StringRef Value;
+  std::tie(SI.SymbolName, Value) = FlagValue.split('=');
+  if (Value.empty())
+    error("bad format for --add-symbol, missing '=' after '" + SI.SymbolName +
+          "'");
+
+  if (Value.contains(':')) {
+    std::tie(SI.SectionName, Value) = Value.split(':');
+    if (SI.SectionName.empty() || Value.empty())
+      error(
+          "bad format for --add-symbol, missing section name or symbol value");
+  }
+
+  SmallVector<StringRef, 6> Flags;
+  Value.split(Flags, ',');
+  if (Flags[0].getAsInteger(0, SI.Value))
+    error("bad symbol value: '" + Flags[0] + "'");
+
+  typedef std::function<void(void)> Functor;
+  size_t NumFlags = Flags.size();
+  for (size_t I = 1; I < NumFlags; ++I)
+    static_cast<Functor>(
+        StringSwitch<Functor>(Flags[I])
+            .CaseLower("global", [&SI] { SI.Bind = ELF::STB_GLOBAL; })
+            .CaseLower("local", [&SI] { SI.Bind = ELF::STB_LOCAL; })
+            .CaseLower("weak", [&SI] { SI.Bind = ELF::STB_WEAK; })
+            .CaseLower("default", [&SI] { SI.Visibility = ELF::STV_DEFAULT; })
+            .CaseLower("hidden", [&SI] { SI.Visibility = ELF::STV_HIDDEN; })
+            .CaseLower("file", [&SI] { SI.Type = ELF::STT_FILE; })
+            .CaseLower("section", [&SI] { SI.Type = ELF::STT_SECTION; })
+            .CaseLower("object", [&SI] { SI.Type = ELF::STT_OBJECT; })
+            .CaseLower("function", [&SI] { SI.Type = ELF::STT_FUNC; })
+            .CaseLower("indirect-function",
+                       [&SI] { SI.Type = ELF::STT_GNU_IFUNC; })
+            .CaseLower("debug", [] {})
+            .CaseLower("constructor", [] {})
+            .CaseLower("warning", [] {})
+            .CaseLower("indirect", [] {})
+            .CaseLower("synthetic", [] {})
+            .CaseLower("unique-object", [] {})
+            .StartsWithLower("before", [] {})
+            .Default([&] {
+              error("unsupported flag '" + Flags[I] + "' for --add-symbol");
+            }))();
+  return SI;
+}
+
 static const StringMap<MachineInfo> ArchMap{
     // Name, {EMachine, 64bit, LittleEndian}
     {"aarch64", {ELF::EM_AARCH64, true, true}},
@@ -539,6 +608,8 @@ Expected<DriverConfig> parseObjcopyOptio
       return std::move(E);
   for (auto Arg : InputArgs.filtered(OBJCOPY_keep_symbol))
     Config.SymbolsToKeep.emplace_back(Arg->getValue(), UseRegex);
+  for (auto Arg : InputArgs.filtered(OBJCOPY_add_symbol))
+    Config.SymbolsToAdd.push_back(parseNewSymbolInfo(Arg->getValue()));
 
   Config.DeterministicArchives = InputArgs.hasFlag(
       OBJCOPY_enable_deterministic_archives,

Modified: llvm/trunk/tools/llvm-objcopy/CopyConfig.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-objcopy/CopyConfig.h?rev=354787&r1=354786&r2=354787&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-objcopy/CopyConfig.h (original)
+++ llvm/trunk/tools/llvm-objcopy/CopyConfig.h Mon Feb 25 06:12:41 2019
@@ -14,6 +14,7 @@
 #include "llvm/ADT/SmallVector.h"
 #include "llvm/ADT/StringMap.h"
 #include "llvm/ADT/StringRef.h"
+#include "llvm/Object/ELFTypes.h"
 #include "llvm/Support/Allocator.h"
 #include "llvm/Support/Error.h"
 #include "llvm/Support/Regex.h"
@@ -61,6 +62,15 @@ public:
   bool operator!=(StringRef S) const { return !operator==(S); }
 };
 
+struct NewSymbolInfo {
+  StringRef SymbolName;
+  StringRef SectionName;
+  uint64_t Value = 0;
+  uint8_t Type = ELF::STT_NOTYPE;
+  uint8_t Bind = ELF::STB_GLOBAL;
+  uint8_t Visibility = ELF::STV_DEFAULT;
+};
+
 // Configuration for copying/stripping a single file.
 struct CopyConfig {
   // Main input/output options
@@ -86,6 +96,7 @@ struct CopyConfig {
   // Repeated options
   std::vector<StringRef> AddSection;
   std::vector<StringRef> DumpSection;
+  std::vector<NewSymbolInfo> SymbolsToAdd;
   std::vector<NameOrRegex> KeepSection;
   std::vector<NameOrRegex> OnlySection;
   std::vector<NameOrRegex> SymbolsToGlobalize;

Modified: llvm/trunk/tools/llvm-objcopy/ELF/ELFObjcopy.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-objcopy/ELF/ELFObjcopy.cpp?rev=354787&r1=354786&r2=354787&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-objcopy/ELF/ELFObjcopy.cpp (original)
+++ llvm/trunk/tools/llvm-objcopy/ELF/ELFObjcopy.cpp Mon Feb 25 06:12:41 2019
@@ -566,6 +566,14 @@ static Error handleArgs(const CopyConfig
   if (!Config.AddGnuDebugLink.empty())
     Obj.addSection<GnuDebugLinkSection>(Config.AddGnuDebugLink);
 
+  for (const NewSymbolInfo &SI : Config.SymbolsToAdd) {
+    SectionBase *Sec = Obj.findSection(SI.SectionName);
+    uint64_t Value = Sec ? Sec->Addr + SI.Value : SI.Value;
+    Obj.SymbolTable->addSymbol(SI.SymbolName, SI.Bind, SI.Type, Sec, Value,
+                               SI.Visibility,
+                               Sec ? SYMBOL_SIMPLE_INDEX : SHN_ABS, 0);
+  }
+
   return Error::success();
 }
 

Modified: llvm/trunk/tools/llvm-objcopy/ELF/Object.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-objcopy/ELF/Object.h?rev=354787&r1=354786&r2=354787&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-objcopy/ELF/Object.h (original)
+++ llvm/trunk/tools/llvm-objcopy/ELF/Object.h Mon Feb 25 06:12:41 2019
@@ -805,6 +805,11 @@ public:
   ConstRange<SectionBase> sections() const {
     return make_pointee_range(Sections);
   }
+  SectionBase *findSection(StringRef Name) {
+    auto SecIt =
+        find_if(Sections, [&](const SecPtr &Sec) { return Sec->Name == Name; });
+    return SecIt == Sections.end() ? nullptr : SecIt->get();
+  }
   Range<Segment> segments() { return make_pointee_range(Segments); }
   ConstRange<Segment> segments() const { return make_pointee_range(Segments); }
 

Modified: llvm/trunk/tools/llvm-objcopy/ObjcopyOpts.td
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-objcopy/ObjcopyOpts.td?rev=354787&r1=354786&r2=354787&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-objcopy/ObjcopyOpts.td (original)
+++ llvm/trunk/tools/llvm-objcopy/ObjcopyOpts.td Mon Feb 25 06:12:41 2019
@@ -237,3 +237,11 @@ defm build_id_link_output
 def regex
     : Flag<["-", "--"], "regex">,
       HelpText<"Permit regular expressions in name comparison">;
+
+defm add_symbol
+    : Eq<"add-symbol", "Add new symbol <name> to .symtab. Accepted flags: "
+         "global, local, weak, default, hidden, file, section, object, "
+         "function, indirect-function. Accepted but ignored for "
+         "compatibility: debug, constructor, warning, indirect, synthetic, "
+         "unique-object, before.">,
+      MetaVarName<"name=[section:]value[,flags]">;




More information about the llvm-commits mailing list