diff options
author | Eleanor Bonnici <eleanor.bonnici@arm.com> | 2024-07-30 10:57:57 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-07-30 10:57:57 +0100 |
commit | 2b2f4ae0fbe366ebaa8811bed567a6ff76bbe3b1 (patch) | |
tree | 3c3ffd78b82432a329cd1846d69a101a456a3048 /llvm/tools/llvm-objcopy/ObjcopyOptions.cpp | |
parent | ca8a4111f796fe8533e0af95557875b15becff06 (diff) | |
download | llvm-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.cpp | 71 |
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, |