1 //===- ELFConfig.cpp ------------------------------------------------------===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 #include "CopyConfig.h"
10 #include "llvm/ADT/Optional.h"
11 #include "llvm/ADT/StringSwitch.h"
12 #include "llvm/Support/Errc.h"
13 #include "llvm/Support/Error.h"
19 static Expected
<NewSymbolInfo
> parseNewSymbolInfo(StringRef FlagValue
,
20 uint8_t DefaultVisibility
) {
21 // Parse value given with --add-symbol option and create the
22 // new symbol if possible. The value format for --add-symbol is:
24 // <name>=[<section>:]<value>[,<flags>]
27 // <name> - symbol name, can be empty string
28 // <section> - optional section name. If not given ABS symbol is created
29 // <value> - symbol value, can be decimal or hexadecimal number prefixed
31 // <flags> - optional flags affecting symbol type, binding or visibility:
32 // The following are currently supported:
34 // global, local, weak, default, hidden, file, section, object,
37 // The following flags are ignored and provided for GNU
38 // compatibility only:
40 // warning, debug, constructor, indirect, synthetic,
41 // unique-object, before=<symbol>.
44 std::tie(SI
.SymbolName
, Value
) = FlagValue
.split('=');
46 return createStringError(
47 errc::invalid_argument
,
48 "bad format for --add-symbol, missing '=' after '%s'",
49 SI
.SymbolName
.str().c_str());
51 if (Value
.contains(':')) {
52 std::tie(SI
.SectionName
, Value
) = Value
.split(':');
53 if (SI
.SectionName
.empty() || Value
.empty())
54 return createStringError(
55 errc::invalid_argument
,
56 "bad format for --add-symbol, missing section name or symbol value");
59 SmallVector
<StringRef
, 6> Flags
;
60 Value
.split(Flags
, ',');
61 if (Flags
[0].getAsInteger(0, SI
.Value
))
62 return createStringError(errc::invalid_argument
, "bad symbol value: '%s'",
63 Flags
[0].str().c_str());
65 SI
.Visibility
= DefaultVisibility
;
67 using Functor
= std::function
<void(void)>;
68 SmallVector
<StringRef
, 6> UnsupportedFlags
;
69 for (size_t I
= 1, NumFlags
= Flags
.size(); I
< NumFlags
; ++I
)
71 StringSwitch
<Functor
>(Flags
[I
])
72 .CaseLower("global", [&SI
] { SI
.Bind
= ELF::STB_GLOBAL
; })
73 .CaseLower("local", [&SI
] { SI
.Bind
= ELF::STB_LOCAL
; })
74 .CaseLower("weak", [&SI
] { SI
.Bind
= ELF::STB_WEAK
; })
75 .CaseLower("default", [&SI
] { SI
.Visibility
= ELF::STV_DEFAULT
; })
76 .CaseLower("hidden", [&SI
] { SI
.Visibility
= ELF::STV_HIDDEN
; })
77 .CaseLower("protected",
78 [&SI
] { SI
.Visibility
= ELF::STV_PROTECTED
; })
79 .CaseLower("file", [&SI
] { SI
.Type
= ELF::STT_FILE
; })
80 .CaseLower("section", [&SI
] { SI
.Type
= ELF::STT_SECTION
; })
81 .CaseLower("object", [&SI
] { SI
.Type
= ELF::STT_OBJECT
; })
82 .CaseLower("function", [&SI
] { SI
.Type
= ELF::STT_FUNC
; })
83 .CaseLower("indirect-function",
84 [&SI
] { SI
.Type
= ELF::STT_GNU_IFUNC
; })
85 .CaseLower("debug", [] {})
86 .CaseLower("constructor", [] {})
87 .CaseLower("warning", [] {})
88 .CaseLower("indirect", [] {})
89 .CaseLower("synthetic", [] {})
90 .CaseLower("unique-object", [] {})
91 .StartsWithLower("before", [] {})
92 .Default([&] { UnsupportedFlags
.push_back(Flags
[I
]); }))();
93 if (!UnsupportedFlags
.empty())
94 return createStringError(errc::invalid_argument
,
95 "unsupported flag%s for --add-symbol: '%s'",
96 UnsupportedFlags
.size() > 1 ? "s" : "",
97 join(UnsupportedFlags
, "', '").c_str());
101 Expected
<ELFCopyConfig
> parseConfig(const CopyConfig
&Config
) {
102 ELFCopyConfig ELFConfig
;
103 if (Config
.NewSymbolVisibility
) {
104 const uint8_t Invalid
= 0xff;
105 ELFConfig
.NewSymbolVisibility
=
106 StringSwitch
<uint8_t>(*Config
.NewSymbolVisibility
)
107 .Case("default", ELF::STV_DEFAULT
)
108 .Case("hidden", ELF::STV_HIDDEN
)
109 .Case("internal", ELF::STV_INTERNAL
)
110 .Case("protected", ELF::STV_PROTECTED
)
113 if (ELFConfig
.NewSymbolVisibility
== Invalid
)
114 return createStringError(errc::invalid_argument
,
115 "'%s' is not a valid symbol visibility",
116 Config
.NewSymbolVisibility
->str().c_str());
119 for (StringRef Arg
: Config
.SymbolsToAdd
) {
120 Expected
<elf::NewSymbolInfo
> NSI
= parseNewSymbolInfo(
122 ELFConfig
.NewSymbolVisibility
.getValueOr((uint8_t)ELF::STV_DEFAULT
));
124 return NSI
.takeError();
125 ELFConfig
.SymbolsToAdd
.push_back(*NSI
);
131 } // end namespace elf
132 } // end namespace objcopy
133 } // end namespace llvm