-
Notifications
You must be signed in to change notification settings - Fork 10.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add adjustVMA option #72870
base: main
Are you sure you want to change the base?
Add adjustVMA option #72870
Conversation
@llvm/pr-subscribers-backend-webassembly @llvm/pr-subscribers-llvm-binary-utilities Author: None (pwprzybyla) ChangesAdd option to adjust section vma Full diff: https://github.com/llvm/llvm-project/pull/72870.diff 4 Files Affected:
diff --git a/llvm/include/llvm/ObjCopy/CommonConfig.h b/llvm/include/llvm/ObjCopy/CommonConfig.h
index e7ce1e6f2c54d75..1dd9dbb29dc372b 100644
--- a/llvm/include/llvm/ObjCopy/CommonConfig.h
+++ b/llvm/include/llvm/ObjCopy/CommonConfig.h
@@ -245,6 +245,11 @@ struct CommonConfig {
StringMap<uint64_t> SetSectionType;
StringMap<StringRef> SymbolsToRename;
+ // Adjust section VMA and LMA
+ int64_t SectionVMA = 0;
+ StringRef SectionName;
+ bool SectionSet = false;
+
// Symbol info specified by --add-symbol option.
std::vector<NewSymbolInfo> SymbolsToAdd;
diff --git a/llvm/lib/ObjCopy/ELF/ELFObjcopy.cpp b/llvm/lib/ObjCopy/ELF/ELFObjcopy.cpp
index 9d02ba051a0a84b..245c11457db6c90 100644
--- a/llvm/lib/ObjCopy/ELF/ELFObjcopy.cpp
+++ b/llvm/lib/ObjCopy/ELF/ELFObjcopy.cpp
@@ -652,7 +652,20 @@ static Error handleArgs(const CommonConfig &Config, const ELFConfig &ELFConfig,
Sec.Align = I->second;
}
}
-
+ if (Config.SectionVMA != 0) {
+ for (SectionBase &Sec : Obj.sections()) {
+ bool AdjustThisSection = false;
+ if (Config.SectionName.empty() ||
+ Config.SectionName.contains(Sec.Name)){
+ AdjustThisSection = true;
+ }
+ if ((Sec.Flags & ELF::SHF_ALLOC) && AdjustThisSection){
+ if (Config.SectionSet)
+ Sec.Addr = 0;
+ Sec.Addr += Config.SectionVMA;
+ }
+ }
+ }
if (Config.OnlyKeepDebug)
for (auto &Sec : Obj.sections())
if (Sec.Flags & SHF_ALLOC && Sec.Type != SHT_NOTE)
diff --git a/llvm/tools/llvm-objcopy/ObjcopyOptions.cpp b/llvm/tools/llvm-objcopy/ObjcopyOptions.cpp
index d33adb0b6a3e478..e2973c9171a408b 100644
--- a/llvm/tools/llvm-objcopy/ObjcopyOptions.cpp
+++ b/llvm/tools/llvm-objcopy/ObjcopyOptions.cpp
@@ -533,6 +533,45 @@ static Error loadNewSectionData(StringRef ArgValue, StringRef OptionName,
return Error::success();
}
+// readChangeSectionVMA reads the command line arguments and sets
+// sectionName and adjustValue of VMA and LMA addresses.
+static Error readChangeSectionVMA(StringRef ArgValue, StringRef OptionName,
+ StringRef& SectionName, int64_t& AdjustValue, bool& setValue) {
+ SectionName = "";
+ AdjustValue = 0;
+ std::pair<StringRef, StringRef> SecPair;
+ if (ArgValue.contains("=")){
+ setValue = true;
+ SecPair = ArgValue.split("=");
+ }
+ else if (ArgValue.contains("+")){
+ setValue = false;
+ SecPair = ArgValue.split("+");
+ }
+ else if (ArgValue.contains("-")){
+ setValue = false;
+ SecPair = ArgValue.split("-");
+ }
+ else{
+ return createStringError(errc::invalid_argument,
+ "bad format for " + OptionName + ": missing '='");
+ }
+ if (SecPair.second.empty())
+ return createStringError(errc::invalid_argument, "bad format for " +
+ OptionName +
+ ": missing offset of VMA");
+ SectionName = SecPair.first;
+ auto ChangeValue = getAsInteger<int64_t>(SecPair.second);
+ if (!ChangeValue)
+ return createStringError(ChangeValue.getError(),
+ "Unable to parse adjustment value");
+ AdjustValue = *ChangeValue;
+ if (ArgValue.contains("-"))
+ AdjustValue *= -1;
+ return Error::success();
+}
+
+
// parseObjcopyOptions returns the config and sets the input arguments. If a
// help flag is set then parseObjcopyOptions will print the help messege and
// exit.
@@ -828,6 +867,11 @@ objcopy::parseObjcopyOptions(ArrayRef<const char *> RawArgsArr,
Config.UpdateSection))
return std::move(Err);
}
+ for (auto *Arg : InputArgs.filtered(OBJCOPY_adjust_section_vma)) {
+ if (Error Err = readChangeSectionVMA(Arg->getValue(), "--adjust-section-vma",
+ Config.SectionName, Config.SectionVMA, Config.SectionSet))
+ return std::move(Err);
+ }
for (auto *Arg : InputArgs.filtered(OBJCOPY_dump_section)) {
StringRef Value(Arg->getValue());
if (Value.split('=').second.empty())
@@ -967,6 +1011,14 @@ objcopy::parseObjcopyOptions(ArrayRef<const char *> RawArgsArr,
ELFConfig.EntryExpr = [Expr, EIncr](uint64_t EAddr) {
return Expr(EAddr) + *EIncr;
};
+ } else if(Arg->getOption().matches(OBJCOPY_adjust_vma)){
+ auto EIncr = getAsInteger<int64_t>(Arg->getValue());
+ if (!EIncr)
+ return createStringError(EIncr.getError(),
+ "bad entry point VMA increment: '%s'",
+ Arg->getValue());
+ Config.SectionName = "";
+ Config.SectionVMA = *EIncr;
}
if (Config.DecompressDebugSections &&
diff --git a/llvm/tools/llvm-objcopy/ObjcopyOpts.td b/llvm/tools/llvm-objcopy/ObjcopyOpts.td
index ea8828637222ac6..c8adb26fb100d32 100644
--- a/llvm/tools/llvm-objcopy/ObjcopyOpts.td
+++ b/llvm/tools/llvm-objcopy/ObjcopyOpts.td
@@ -230,3 +230,14 @@ defm add_symbol
defm update_section
: Eq<"update-section", "Replace the contents of section <name> with contents from a file <file>">,
MetaVarName<"name=file">;
+
+defm adjust_section_vma
+ : Eq<"adjust-section-vma", "Adjust VMA and LMA of section <section> by <value>"
+ ""
+ "">,
+ MetaVarName<".section{=|+|-}value">;
+defm adjust_vma
+ : Eq<"adjust-vma", "Add <incr> to the vma and lma address."
+ ""
+ "">,
+ MetaVarName<"incr">;
|
✅ With the latest revision this PR passed the C/C++ code formatter. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I haven't looked at the implementation yet, as I think there are a couple of high-level things that need addressing:
- This change needs to update the llvm-objcopy docs located at llvm/docs/CommandGuide.
- This change needs tests.
- Should this option apply to platforms other than ELF? There's no need to implement those platforms, but it impacts things like what happens if the option is specified for a non-ELF input.
- Please make sure your new/changed code is reformatted according to clang-format, but not other areas of code, to reduce noise in the patch.
- A quick skim of the behaviour suggests that this only impacts section addresses. This may be correct, but could you confirm whether the option has any impact on program headers with GNU objcopy? In particular, can it result in a section address (sh_addr value) that is outside the program segment it should be in (compare it to the
p_vaddr
andp_memsz
of the segments). - Does GNU objcopy do any sanity checking of the new address? E.g. does it stop you specifying a new address for a section if it would cause its address to overlap with another section?
// Adjust section VMA and LMA | ||
int64_t SectionVMA = 0; | ||
StringRef SectionName; | ||
bool SectionSet = false; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
// Adjust section VMA and LMA | |
int64_t SectionVMA = 0; | |
StringRef SectionName; | |
bool SectionSet = false; | |
// Adjust section VMA and LMA. | |
int64_t SectionVMA = 0; | |
StringRef SectionName; | |
bool SectionSet = false; |
Could you be more precise with these variable names, please, since the SectionName
and SectionSet
variables could be for anything, and the SectionVMA
variable should probably be named more after the corresponding option? Also, leverage std::optional
rather than a boolean property, or even just treat an empty SectionName
as unset, depending on how it's used.
"symbols generated for binary input or added" | ||
" with --add-symbol unless otherwise" | ||
" specified. The default value is 'default'">; | ||
defm new_symbol_visibility |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please avoid reformatting the entire file in the middle of another change. If necessary, create an NFC patch to do the reformatting and base this PR on top of that.
MetaVarName<"name=file">; | ||
|
||
defm adjust_section_vma |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it makes sense to be able to specify this option multiple times? Also, it might make sense to add the --change-addresses/--change-section-address options at the same time (I think they're just aliases from the GNU objcopy docs, but I haven't experimented with them).
"" | ||
"">, | ||
MetaVarName<".section{=|+|-}value">; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please tidy up the formatting (you don't need these empty strings for example).
The GNU docs imply that the --adjust-section-vma
argument takes a section name pattern, not just a section name, but this metavar and option description don't imply this. Please revise accordingly.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Indeed GNU docs use pattern matching here I expect to use full name of section.
Ad 3) parameter handled also in other file formats. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ad 5,6) there are no other checks implemented. No out of bounds checking or overlap checks.
I just tested on my Linux machine, using GNU objcopy and this doesn't appear to be correct. GNU objcopy complains if you try to adjust the VMA of a section in a way that causes problems with the program headers.
I'm also a little confused how just adjusting the VMA of the section achieves anything without changing the program header addresses, because the section address isn't used by the loader. What is the use case for this?
@@ -483,6 +483,12 @@ them. | |||
|
|||
Mark all defined global symbols as weak in the output. | |||
|
|||
.. option:: --adjust-vma <value> | |||
Add ``<value>`` to VMA and LMA address |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add ``<value>`` to VMA and LMA address | |
Add ``<value>`` to VMA and LMA address. |
Address of what?
Add ``<value>`` to VMA and LMA address | ||
|
||
.. option:: --adjust-section-vma <name>{+|-|=}<value> | ||
Adjust section ``<name>`` VMA and LMA address by ``<value>`` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Adjust section ``<name>`` VMA and LMA address by ``<value>`` | |
Adjust section ``<name>`` VMA and LMA address by ``<value>``. |
I think this could do with some elaboration regarding what =
means in this context (presumably it means setting it to the value specified, but that isn't "adjust it by something").
@@ -245,6 +253,9 @@ struct CommonConfig { | |||
StringMap<uint64_t> SetSectionType; | |||
StringMap<StringRef> SymbolsToRename; | |||
|
|||
// Adjust section VMA and LMA |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
// Adjust section VMA and LMA | |
// Adjust section VMA and LMA. |
Comments should use correct punctuation. That being said, this comment doesn't add any value and the member should just be added to the immediately above set of StringMap
members.
@@ -316,6 +316,12 @@ static Error handleArgs(const CommonConfig &Config, | |||
Obj.PeHeader.MinorSubsystemVersion = *COFFConfig.MinorSubsystemVersion; | |||
} | |||
|
|||
if (!Config.AdjustSectionVMA.empty()) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This isn't the correct place to handle unsupported options. Please see ConfigManager.cpp for how to handle options that are not yet implemented for some platforms, but might be in the future.
Add option to adjust section vma
Please respond to these comments. I won't be reviewing further until you do. |
Add option to adjust section vma