[llvm-objcopy] Add --set-start, --change-start and --adjust-start

Differential revision: https://reviews.llvm.org/D58173

llvm-svn: 354854
This commit is contained in:
Eugene Leviant 2019-02-26 09:24:22 +00:00
parent e6f22596e5
commit 53350d0411
6 changed files with 105 additions and 1 deletions

View File

@ -0,0 +1,57 @@
# RUN: yaml2obj %s -o %t
# Test --set-start.
# RUN: llvm-objcopy --set-start 0x1000 %t %t2
# RUN: llvm-readobj --file-headers %t2 | FileCheck %s --check-prefix=SET
# RUN: llvm-objcopy --set-start 4096 %t %t3
# RUN: cmp %t2 %t3
# RUN: llvm-objcopy --set-start 0x100000000 %t %t4
# RUN: llvm-readobj --file-headers %t4 | FileCheck %s --check-prefix=SET-LARGE
# RUN: not llvm-objcopy --set-start -123 %t %t5 2>&1 | FileCheck %s --check-prefix=SET-ERR
# Test --change-start.
# RUN: llvm-objcopy --change-start 0x50 %t %t6
# RUN: llvm-readobj --file-headers %t6 | FileCheck %s --check-prefix=ADD
# RUN: llvm-objcopy --change-start 0x100000000 %t %t7
# RUN: llvm-readobj --file-headers %t7 | FileCheck %s --check-prefix=ADD-LARGE
# RUN: llvm-objcopy --change-start -4353 %t %t8
# RUN: llvm-readobj --file-headers %t8 | FileCheck %s --check-prefix=ADD-UNDERFLOW
# RUN: llvm-objcopy --change-start -0x1101 %t %t9
# RUN: cmp %t8 %t9
# RUN: not llvm-objcopy --change-start -xyz %t %t10 2>&1 | FileCheck %s --check-prefix=ADD-ERR
# Test --change-start after --set-start. Result should be 0x1150.
# RUN: llvm-objcopy --set-start 0x1000 --change-start 0x100 --change-start 0x50 %t %t11
# RUN: cmp %t6 %t11
# If --set-start is after --change-start then --change-start has no effect.
# RUN: llvm-objcopy --change-start 0x150 --set-start 0x1000 %t %t12
# RUN: cmp %t2 %t12
# --adjust-start is an alias for --change-start.
# RUN: llvm-objcopy --adjust-start -0x1101 %t %t13
# RUN: cmp %t9 %t13
!ELF
FileHeader:
Class: ELFCLASS64
Data: ELFDATA2LSB
Type: ET_EXEC
Machine: EM_X86_64
Entry: 0x1100
Sections:
- Name: .text
Type: SHT_PROGBITS
Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
Address: 0x1000
AddressAlign: 0x0000000000001000
Size: 0x200
# SET: Entry: 0x1000
# ADD: Entry: 0x1150
# SUB: Entry: 0x1080
# SET-ERR: error: bad entry point address: '-123'
# SET-LARGE: Entry: 0x100000000
# ADD-LARGE: Entry: 0x100001100
# ADD-ERR: error: bad entry point increment: '-xyz'
# ADD-UNDERFLOW: Entry: 0xFFFFFFFFFFFFFFFF

View File

@ -186,7 +186,7 @@ static Error handleArgs(const CopyConfig &Config, Object &Obj) {
Config.PreserveDates || Config.StripDWO || Config.StripNonAlloc ||
Config.StripSections || Config.Weaken || Config.DecompressDebugSections ||
Config.DiscardMode == DiscardType::Locals ||
!Config.SymbolsToAdd.empty()) {
!Config.SymbolsToAdd.empty() || Config.EntryExpr) {
return createStringError(llvm::errc::invalid_argument,
"Option not supported by llvm-objcopy for COFF");
}

View File

@ -371,6 +371,14 @@ static Error addSymbolsToRenameFromFile(StringMap<StringRef> &SymbolsToRename,
}
return Error::success();
}
template <class T> static ErrorOr<T> getAsInteger(StringRef Val) {
T Result;
if (Val.getAsInteger(0, Result))
return errc::invalid_argument;
return Result;
}
// ParseObjcopyOptions returns the config and sets the input arguments. If a
// help flag is set then ParseObjcopyOptions will print the help messege and
// exit.
@ -617,6 +625,27 @@ Expected<DriverConfig> parseObjcopyOptions(ArrayRef<const char *> ArgsArr) {
Config.PreserveDates = InputArgs.hasArg(OBJCOPY_preserve_dates);
for (auto Arg : InputArgs)
if (Arg->getOption().matches(OBJCOPY_set_start)) {
auto EAddr = getAsInteger<uint64_t>(Arg->getValue());
if (!EAddr)
return createStringError(
EAddr.getError(), "bad entry point address: '%s'", Arg->getValue());
Config.EntryExpr = [EAddr](uint64_t) { return *EAddr; };
} else if (Arg->getOption().matches(OBJCOPY_change_start)) {
auto EIncr = getAsInteger<int64_t>(Arg->getValue());
if (!EIncr)
return createStringError(EIncr.getError(),
"bad entry point increment: '%s'",
Arg->getValue());
auto Expr = Config.EntryExpr ? std::move(Config.EntryExpr)
: [](uint64_t A) { return A; };
Config.EntryExpr = [Expr, EIncr](uint64_t EAddr) {
return Expr(EAddr) + *EIncr;
};
}
if (Config.DecompressDebugSections &&
Config.CompressionType != DebugCompressionType::None) {
return createStringError(

View File

@ -113,6 +113,12 @@ struct CopyConfig {
StringMap<SectionFlagsUpdate> SetSectionFlags;
StringMap<StringRef> SymbolsToRename;
// ELF entry point address expression. The input parameter is an entry point
// address in the input ELF file. The entry address in the output file is
// calculated with EntryExpr(input_address), when either --set-start or
// --change-start is used.
std::function<uint64_t(uint64_t)> EntryExpr;
// Boolean options
bool DeterministicArchives = true;
bool ExtractDWO = false;

View File

@ -574,6 +574,8 @@ static Error handleArgs(const CopyConfig &Config, Object &Obj,
Sec ? SYMBOL_SIMPLE_INDEX : SHN_ABS, 0);
}
if (Config.EntryExpr)
Obj.Entry = Config.EntryExpr(Obj.Entry);
return Error::success();
}

View File

@ -238,6 +238,16 @@ def regex
: Flag<["-", "--"], "regex">,
HelpText<"Permit regular expressions in name comparison">;
defm set_start : Eq<"set-start", "Set the start address to <addr>. Overrides "
"any previous --change-start or --adjust-start values.">,
MetaVarName<"addr">;
defm change_start : Eq<"change-start", "Add <incr> to the start address. Can be "
"specified multiple times, all values will be applied "
"cumulatively.">,
MetaVarName<"incr">;
def adjust_start : JoinedOrSeparate<["-", "--"], "adjust-start">,
Alias<change_start>;
defm add_symbol
: Eq<"add-symbol", "Add new symbol <name> to .symtab. Accepted flags: "
"global, local, weak, default, hidden, file, section, object, "