aboutsummaryrefslogtreecommitdiff
path: root/llvm/tools/llvm-objcopy/ObjcopyOptions.cpp
diff options
context:
space:
mode:
authorEleanor Bonnici <eleanor.bonnici@arm.com>2024-07-30 10:57:57 +0100
committerGitHub <noreply@github.com>2024-07-30 10:57:57 +0100
commit2b2f4ae0fbe366ebaa8811bed567a6ff76bbe3b1 (patch)
tree3c3ffd78b82432a329cd1846d69a101a456a3048 /llvm/tools/llvm-objcopy/ObjcopyOptions.cpp
parentca8a4111f796fe8533e0af95557875b15becff06 (diff)
downloadllvm-2b2f4ae0fbe366ebaa8811bed567a6ff76bbe3b1.zip
llvm-2b2f4ae0fbe366ebaa8811bed567a6ff76bbe3b1.tar.gz
llvm-2b2f4ae0fbe366ebaa8811bed567a6ff76bbe3b1.tar.bz2
[llvm-objcopy] Add --change-section-address (#98664)
--change-section address and its alias --adjust-section-vma allows modification of section addresses in a relocatable file. This used to be used, for example, in Fiasco microkernel. On a relocatable file this option behaves the same as GNU objcopy, apart from the fact that it does not issue any warnings, for example, when an argument is not used. GNU objcopy does not produce an error when passed an executable file but the usecase for this is not clear, and the behaviour is inconsistent. The idea of GNU objcopy --change-section-address is that the option should change both LMA and VMA in an executable file. Since this patch does not implement executable file support, only VMA is changed.
Diffstat (limited to 'llvm/tools/llvm-objcopy/ObjcopyOptions.cpp')
-rw-r--r--llvm/tools/llvm-objcopy/ObjcopyOptions.cpp71
1 files changed, 71 insertions, 0 deletions
diff --git a/llvm/tools/llvm-objcopy/ObjcopyOptions.cpp b/llvm/tools/llvm-objcopy/ObjcopyOptions.cpp
index a54feb7..d82ecc8 100644
--- a/llvm/tools/llvm-objcopy/ObjcopyOptions.cpp
+++ b/llvm/tools/llvm-objcopy/ObjcopyOptions.cpp
@@ -584,6 +584,68 @@ static Expected<int64_t> parseChangeSectionLMA(StringRef ArgValue,
return *LMAValue;
}
+static Expected<SectionPatternAddressUpdate>
+parseChangeSectionAddr(StringRef ArgValue, StringRef OptionName,
+ MatchStyle SectionMatchStyle,
+ function_ref<Error(Error)> ErrorCallback) {
+ SectionPatternAddressUpdate PatternUpdate;
+
+ size_t LastSymbolIndex = ArgValue.find_last_of("+-=");
+ if (LastSymbolIndex == StringRef::npos)
+ return createStringError(errc::invalid_argument,
+ "bad format for " + OptionName +
+ ": argument value " + ArgValue +
+ " is invalid. See --help");
+ char UpdateSymbol = ArgValue[LastSymbolIndex];
+
+ StringRef SectionPattern = ArgValue.slice(0, LastSymbolIndex);
+ if (SectionPattern.empty())
+ return createStringError(
+ errc::invalid_argument,
+ "bad format for " + OptionName +
+ ": missing section pattern to apply address change to");
+ if (Error E = PatternUpdate.SectionPattern.addMatcher(NameOrPattern::create(
+ SectionPattern, SectionMatchStyle, ErrorCallback)))
+ return std::move(E);
+
+ StringRef Value = ArgValue.slice(LastSymbolIndex + 1, StringRef::npos);
+ if (Value.empty()) {
+ switch (UpdateSymbol) {
+ case '+':
+ case '-':
+ return createStringError(errc::invalid_argument,
+ "bad format for " + OptionName +
+ ": missing value of offset after '" +
+ std::string({UpdateSymbol}) + "'");
+
+ case '=':
+ return createStringError(errc::invalid_argument,
+ "bad format for " + OptionName +
+ ": missing address value after '='");
+ }
+ }
+ auto AddrValue = getAsInteger<uint64_t>(Value);
+ if (!AddrValue)
+ return createStringError(AddrValue.getError(),
+ "bad format for " + OptionName + ": value after " +
+ std::string({UpdateSymbol}) + " is " + Value +
+ " when it should be a 64-bit integer");
+
+ switch (UpdateSymbol) {
+ case '+':
+ PatternUpdate.Update.Kind = AdjustKind::Add;
+ break;
+ case '-':
+ PatternUpdate.Update.Kind = AdjustKind::Subtract;
+ break;
+ case '=':
+ PatternUpdate.Update.Kind = AdjustKind::Set;
+ }
+
+ PatternUpdate.Update.Value = *AddrValue;
+ return PatternUpdate;
+}
+
// parseObjcopyOptions returns the config and sets the input arguments. If a
// help flag is set then parseObjcopyOptions will print the help messege and
// exit.
@@ -874,6 +936,15 @@ objcopy::parseObjcopyOptions(ArrayRef<const char *> RawArgsArr,
Config.ChangeSectionLMAValAll = *LMAValue;
}
+ for (auto *Arg : InputArgs.filtered(OBJCOPY_change_section_address)) {
+ Expected<SectionPatternAddressUpdate> AddressUpdate =
+ parseChangeSectionAddr(Arg->getValue(), Arg->getSpelling(),
+ SectionMatchStyle, ErrorCallback);
+ if (!AddressUpdate)
+ return AddressUpdate.takeError();
+ Config.ChangeSectionAddress.push_back(*AddressUpdate);
+ }
+
for (auto *Arg : InputArgs.filtered(OBJCOPY_redefine_symbol)) {
if (!StringRef(Arg->getValue()).contains('='))
return createStringError(errc::invalid_argument,