Skip to content

Commit 56a3e22

Browse files
committed
[llvm-objcopy] Add change-section-lma *+/-offset
llvm-objcopy did not support change-section-lma argument. This patch adds support for a use case of change-section-lma, that is shifting load address of all sections by the same offset. This seems to be the only practical use case of change-section-lma, found in other software.
1 parent 346f16d commit 56a3e22

File tree

7 files changed

+154
-0
lines changed

7 files changed

+154
-0
lines changed

llvm/docs/CommandGuide/llvm-objcopy.rst

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -528,6 +528,10 @@ them.
528528

529529
Mark all defined global symbols as weak in the output.
530530

531+
.. option:: --change-section-lma \*{+-}<offset>
532+
533+
Currently only supports changing LMA for all sections by the same offset.
534+
531535
MACH-O-SPECIFIC OPTIONS
532536
-----------------------
533537

llvm/include/llvm/ObjCopy/CommonConfig.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -245,6 +245,9 @@ struct CommonConfig {
245245
// Symbol info specified by --add-symbol option.
246246
SmallVector<NewSymbolInfo, 0> SymbolsToAdd;
247247

248+
// Integer options
249+
int64_t ChangeSectionLMAValAll = 0;
250+
248251
// Boolean options
249252
bool DeterministicArchives = true;
250253
bool ExtractDWO = false;

llvm/lib/ObjCopy/ELF/ELFObjcopy.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -670,6 +670,13 @@ static Error handleArgs(const CommonConfig &Config, const ELFConfig &ELFConfig,
670670
}
671671
}
672672

673+
if (Config.ChangeSectionLMAValAll != 0) {
674+
for (auto &Seg : Obj.segments()) {
675+
if (Seg.FileSize > 0)
676+
Seg.PAddr += Config.ChangeSectionLMAValAll;
677+
}
678+
}
679+
673680
if (Config.OnlyKeepDebug)
674681
for (auto &Sec : Obj.sections())
675682
if (Sec.Flags & SHF_ALLOC && Sec.Type != SHT_NOTE)
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
# RUN: yaml2obj %s -o %t
2+
# RUN: llvm-objcopy --change-section-lma *+0x20 %t %t2
3+
# RUN: llvm-readelf -l %t2 | FileCheck %s --check-prefix=CHECK-PLUS
4+
# RUN: llvm-objcopy --change-section-lma *-0x10 %t2 %t3
5+
# RUN: llvm-readelf -l %t3 | FileCheck %s --check-prefix=CHECK-MINUS
6+
# RUN: not llvm-objcopy --change-section-lma .text3=0x5000 %t 2>&1 | FileCheck %s --check-prefix=ERR
7+
8+
!ELF
9+
FileHeader:
10+
Class: ELFCLASS64
11+
Data: ELFDATA2LSB
12+
Type: ET_EXEC
13+
Machine: EM_AARCH64
14+
Sections:
15+
- Name: .text1
16+
Type: SHT_PROGBITS
17+
Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
18+
Address: 0x1000
19+
AddressAlign: 0x1000
20+
Content: "DEADBEEF"
21+
Size: 0x1000
22+
- Name: .text2
23+
Type: SHT_PROGBITS
24+
Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
25+
Address: 0x2000
26+
AddressAlign: 0x1000
27+
Content: "32323232"
28+
Size: 0x1000
29+
- Name: .text3
30+
Type: SHT_PROGBITS
31+
Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
32+
Address: 0x3000
33+
AddressAlign: 0x1000
34+
Content: "c3c3c3c3"
35+
Size: 0x1000
36+
ProgramHeaders:
37+
- Type: PT_LOAD
38+
Flags: [ PF_R ]
39+
VAddr: 0x1000
40+
FirstSec: .text1
41+
LastSec: .text2
42+
# CHECK-PLUS: Type Offset VirtAddr PhysAddr FileSiz MemSiz
43+
# CHECK-PLUS: LOAD 0x001000 0x0000000000001000 0x0000000000001020 0x002000 0x002000
44+
# CHECK-MINUS: LOAD 0x001000 0x0000000000001000 0x0000000000001010 0x002000 0x002000
45+
- Type: PT_LOAD
46+
Flags: [ PF_R ]
47+
VAddr: 0x7000
48+
FirstSec: .text3
49+
LastSec: .text3
50+
# CHECK-PLUS: LOAD 0x003000 0x0000000000007000 0x0000000000007020 0x001000 0x001000
51+
# CHECK-MINUS: LOAD 0x003000 0x0000000000007000 0x0000000000007010 0x001000 0x001000
52+
# ERR: error: bad format for --change-section-lma: it is required that all sections are either incremented, or decremented at the same time; use *+val, or *-val
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
# RUN: yaml2obj %s -o %t
2+
# RUN: llvm-objcopy --change-section-lma *+0x20 %t %t2
3+
# RUN: llvm-readelf -l %t2 | FileCheck %s --check-prefix=CHECK-PLUS
4+
# RUN: llvm-objcopy --change-section-lma *-0x10 %t2 %t3
5+
# RUN: llvm-readelf -l %t3 | FileCheck %s --check-prefix=CHECK-MINUS
6+
# RUN: not llvm-objcopy --change-section-lma .text3=0x5000 %t 2>&1 | FileCheck %s --check-prefix=ERR
7+
8+
!ELF
9+
FileHeader:
10+
Class: ELFCLASS64
11+
Data: ELFDATA2LSB
12+
Type: ET_EXEC
13+
Machine: EM_AARCH64
14+
Sections:
15+
- Name: .text1
16+
Type: SHT_PROGBITS
17+
Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
18+
Address: 0x1000
19+
AddressAlign: 0x1000
20+
Content: "DEADBEEF"
21+
Size: 0x1000
22+
- Name: .text2
23+
Type: SHT_PROGBITS
24+
Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
25+
Address: 0x2000
26+
AddressAlign: 0x1000
27+
Content: "32323232"
28+
Size: 0x1000
29+
- Name: .text3
30+
Type: SHT_PROGBITS
31+
Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
32+
Address: 0x3000
33+
AddressAlign: 0x1000
34+
Content: "c3c3c3c3"
35+
Size: 0x1000
36+
ProgramHeaders:
37+
- Type: PT_LOAD
38+
Flags: [ PF_R ]
39+
VAddr: 0x1000
40+
FirstSec: .text1
41+
LastSec: .text3
42+
# CHECK-PLUS: Type Offset VirtAddr PhysAddr FileSiz MemSiz
43+
# CHECK-PLUS: LOAD 0x001000 0x0000000000001000 0x0000000000001020 0x003000 0x003000
44+
# CHECK-MINUS: LOAD 0x001000 0x0000000000001000 0x0000000000001010 0x003000 0x003000
45+
# ERR: error: bad format for --change-section-lma: it is required that all sections are either incremented, or decremented at the same time; use *+val, or *-val

llvm/tools/llvm-objcopy/ObjcopyOptions.cpp

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -552,6 +552,33 @@ static Error loadNewSectionData(StringRef ArgValue, StringRef OptionName,
552552
return Error::success();
553553
}
554554

555+
static Expected<int64_t> parseAdjustSectionLMA(StringRef ArgValue,
556+
StringRef OptionName) {
557+
StringRef StringValue;
558+
if (ArgValue.starts_with("*+")) {
559+
StringValue = ArgValue.slice(2, StringRef::npos);
560+
} else if (ArgValue.starts_with("*-")) {
561+
StringValue = ArgValue.slice(1, StringRef::npos);
562+
} else {
563+
return createStringError(errc::invalid_argument,
564+
"bad format for " + OptionName +
565+
": it is required that all sections "
566+
"are either incremented, or decremented at "
567+
"the same time; use *+val, "
568+
"or *-val");
569+
}
570+
if (StringValue.empty())
571+
return createStringError(errc::invalid_argument,
572+
"bad format for " + OptionName +
573+
": missing offset of LMA");
574+
575+
auto SLMAV = getAsInteger<int64_t>(StringValue);
576+
if (!SLMAV)
577+
return createStringError(SLMAV.getError(),
578+
"Unable to parse adjustment value");
579+
return *SLMAV;
580+
}
581+
555582
// parseObjcopyOptions returns the config and sets the input arguments. If a
556583
// help flag is set then parseObjcopyOptions will print the help messege and
557584
// exit.
@@ -833,6 +860,14 @@ objcopy::parseObjcopyOptions(ArrayRef<const char *> RawArgsArr,
833860
Config.PadTo = *Addr;
834861
}
835862

863+
if (const auto *Arg = InputArgs.getLastArg(OBJCOPY_adjust_section_lma)) {
864+
Expected<int64_t> SLMAV =
865+
parseAdjustSectionLMA(Arg->getValue(), Arg->getSpelling());
866+
if (!SLMAV)
867+
return SLMAV.takeError();
868+
Config.ChangeSectionLMAValAll = *SLMAV;
869+
}
870+
836871
for (auto *Arg : InputArgs.filtered(OBJCOPY_redefine_symbol)) {
837872
if (!StringRef(Arg->getValue()).contains('='))
838873
return createStringError(errc::invalid_argument,

llvm/tools/llvm-objcopy/ObjcopyOpts.td

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -254,6 +254,14 @@ def adjust_start : JoinedOrSeparate<["--"], "adjust-start">,
254254
Alias<change_start>,
255255
HelpText<"Alias for --change-start">;
256256

257+
defm adjust_section_lma
258+
: Eq<"change-section-lma",
259+
"Change LMA of all sections by <val>. LMA is the physical address where the section is "
260+
"loaded in the memory; as opoosed to VMA, which is the virtual address at which the "
261+
"section resides during program execution. Ussually LMA and VMA are the same, but some "
262+
"platforms support these to be different resulting in runtime copying">,
263+
MetaVarName<"*{+|-}val">;
264+
257265
defm add_symbol
258266
: Eq<"add-symbol", "Add new symbol <name> to .symtab. Accepted flags: "
259267
"global, local, weak, default, hidden, protected, file, section, object, "

0 commit comments

Comments
 (0)