Skip to content

Commit 14f33c6

Browse files
authored
[llvm-objcopy][mach-o] Fix section finding logic for object files (llvm#127604)
Fix section finding logic for object files. As by product, make --update-section functional when the input is an object file. This PR fixes llvm#127495
1 parent 78bac7f commit 14f33c6

File tree

5 files changed

+72
-1
lines changed

5 files changed

+72
-1
lines changed

llvm/docs/ReleaseNotes.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,8 @@ Changes to the Debug Info
146146
Changes to the LLVM tools
147147
---------------------------------
148148

149+
* llvm-objcopy now supports the `--update-section` flag for intermediate Mach-O object files.
150+
149151
Changes to LLDB
150152
---------------------------------
151153

llvm/lib/ObjCopy/MachO/MachOObjcopy.cpp

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -360,6 +360,24 @@ static Error addSection(const NewSectionInfo &NewSection, Object &Obj) {
360360
static Expected<Section &> findSection(StringRef SecName, Object &O) {
361361
StringRef SegName;
362362
std::tie(SegName, SecName) = SecName.split(",");
363+
// For compactness, intermediate object files (MH_OBJECT) contain
364+
// only one segment in which all sections are placed.
365+
// The static linker places each section in the named segment when building
366+
// the final product (any file that is not of type MH_OBJECT).
367+
//
368+
// Source:
369+
// https://math-atlas.sourceforge.net/devel/assembly/MachORuntime.pdf
370+
// page 57
371+
if (O.Header.FileType == MachO::HeaderFileType::MH_OBJECT) {
372+
for (const auto& LC : O.LoadCommands)
373+
for (const auto& Sec : LC.Sections)
374+
if (Sec->Segname == SegName && Sec->Sectname == SecName)
375+
return *Sec;
376+
377+
StringRef ErrMsg = "could not find section with name '%s' in '%s' segment";
378+
return createStringError(errc::invalid_argument, ErrMsg.str().c_str(),
379+
SecName.str().c_str(), SegName.str().c_str());
380+
}
363381
auto FoundSeg =
364382
llvm::find_if(O.LoadCommands, [SegName](const LoadCommand &LC) {
365383
return LC.getSegmentName() == SegName;
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
.section __TEXT,__text
2+
.space 64
3+
.section __DATA,__storage
4+
.space 128
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
# REQUIRES: aarch64-registered-target
2+
3+
# RUN: llvm-mc -assemble -triple=arm64-apple-macos11 -filetype=obj %p/Inputs/macho_sections.s -o %t.o
4+
# RUN: llvm-otool -l %t.o | FileCheck %s --check-prefix=ORIG
5+
6+
7+
# RUN: llvm-objcopy %t.o --update-section __DATA,__storage=%p/Inputs/macho_sections.s %t.new.o
8+
# RUN: llvm-otool -l %t.new.o | FileCheck %s --check-prefix=UPDATED
9+
10+
# ORIG: cmd LC_SEGMENT_64
11+
# ORIG-NEXT: cmdsize 232
12+
# ORIG-NEXT: segname
13+
# ORIG-NEXT: vmaddr 0x0000000000000000
14+
# ORIG-NEXT: vmsize 0x00000000000000c0
15+
# ORIG-NEXT: fileoff 392
16+
# ORIG-NEXT: filesize 192
17+
# ORIG-NEXT: maxprot 0x00000007
18+
# ORIG-NEXT: initprot 0x00000007
19+
# ORIG-NEXT: nsects 2
20+
# ORIG-NEXT: flags 0x0
21+
22+
# ORIG: Section
23+
# ORIG: sectname __storage
24+
# ORIG-NEXT: segname __DATA
25+
# ORIG-NEXT: addr 0x0000000000000040
26+
# ORIG-NEXT: size 0x0000000000000080
27+
28+
29+
### Make sure the file size and segment size have changed
30+
# UPDATED: cmd LC_SEGMENT_64
31+
# UPDATED-NEXT: cmdsize 232
32+
# UPDATED-NEXT: segname
33+
# UPDATED-NEXT: vmaddr 0x0000000000000000
34+
# UPDATED-NEXT: vmsize 0x0000000000000090
35+
# UPDATED-NEXT: fileoff 392
36+
# UPDATED-NEXT: filesize 144
37+
# UPDATED-NEXT: maxprot 0x00000007
38+
# UPDATED-NEXT: initprot 0x00000007
39+
# UPDATED-NEXT: nsects 2
40+
# UPDATED-NEXT: flags 0x0
41+
42+
# UPDATED: Section
43+
# UPDATED: sectname __storage
44+
# UPDATED-NEXT: segname __DATA
45+
# UPDATED-NEXT: addr 0x0000000000000040
46+
# UPDATED-NEXT: size 0x0000000000000050
47+

llvm/test/tools/llvm-objcopy/MachO/update-section.test

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
# RUN: not llvm-objcopy --update-section __TEXT,__text=%t.noexist %t /dev/null
1717

1818
# RUN: not llvm-objcopy --update-section __NOEXIST,__text=%t.diff %t /dev/null 2>&1 | FileCheck %s --check-prefix=NO-SEGMENT
19-
# NO-SEGMENT: error: {{.*}}could not find segment with name '__NOEXIST'
19+
# NO-SEGMENT: error: {{.*}}could not find section with name '__text' in '__NOEXIST' segment
2020

2121
# RUN: not llvm-objcopy --update-section __TEXT,__noexist=%t.diff %t /dev/null 2>&1 | FileCheck %s --check-prefix=NO-SECTION
2222
# NO-SECTION: error: {{.*}}could not find section with name '__noexist'

0 commit comments

Comments
 (0)