[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