[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:
parent
e6f22596e5
commit
53350d0411
|
@ -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
|
|
@ -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");
|
||||
}
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
|
@ -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, "
|
||||
|
|
Loading…
Reference in New Issue