xref: /llvm-project/llvm/test/tools/llvm-objcopy/ELF/update-section.test (revision beae6bfa14ac991b405d2928027fb0e31e777a09)
1# REQUIRES: x86-registered-target
2
3# RUN: yaml2obj %s -o %t
4
5# RUN: echo -n 11112222 > %t.same
6# RUN: echo -n 00000000 > %t.zeros
7# RUN: echo -n 11 > %t.short
8# RUN: echo -n 11113333 > %t.updated
9# RUN: echo -n 111122223 > %t.larger
10
11## Update the segment section with a regular chunk of data the same size as the section.
12# RUN: llvm-objcopy --update-section=.in_segment=%t.same %t %t.same.o
13# RUN: llvm-readobj --section-headers --section-data --program-headers %t.same.o | \
14# RUN:   FileCheck %s --check-prefix=NORMAL
15
16## Show that if we overwrite a given section (.in_segment) with new data, then rewrite it
17## back (from the second `--update-section`), then it should be the exact same as the
18## original file.
19# RUN: llvm-objcopy %t %t.copy.o
20# RUN: llvm-objcopy --update-section=.in_segment=%t.same --update-section=.in_segment=%t.zeros %t %t.original.o
21# RUN: cmp %t.copy.o %t.original.o
22
23## Update segment section with a smaller chunk of data. This will also update the
24## section size to the length of the new data written. This does not affect the offset
25## of any subsequent sections in the same segment as this.
26# RUN: llvm-objcopy --update-section=.in_segment=%t.short %t %t.short.o
27# RUN: llvm-readobj --section-headers --section-data --program-headers %t.short.o | \
28# RUN:   FileCheck %s --check-prefix=SHORT
29
30## Ensure the data that was in a shortened section within a segment is still retained.
31## For cases where there are gaps in segments not covered by sections, the existing
32## contents are preserved.
33# RUN: od -t x1 -j 0x78 -N 16 %t.short.o | FileCheck %s --check-prefix=PRESERVED
34
35## Add a new section via --add-section, then update it.
36# RUN: llvm-objcopy --add-section=.added=%t.zeros --update-section=.added=%t.updated \
37# RUN:   %t %t.updated.o
38# RUN: llvm-readobj --section-headers --section-data --program-headers %t.updated.o | \
39# RUN:   FileCheck %s --check-prefix=ADD-UPDATE
40
41## Adding should always be first regardless of flag order.
42# RUN: llvm-objcopy --update-section=.added=%t.updated --add-section=.added=%t.updated \
43# RUN:   %t %t.updated.o
44# RUN: llvm-readobj --section-headers --section-data --program-headers %t.updated.o | \
45# RUN:   FileCheck %s --check-prefix=ADD-UPDATE
46
47## We can't update sections which don't exist.
48# RUN: not llvm-objcopy --update-section=.nosection=%t.same %t %t-err1 2>&1 | \
49# RUN:   FileCheck %s --check-prefix=ERR-NO-SECTION
50
51## We can't update certain types of sections.
52# RUN: not llvm-objcopy --update-section=.nobits_type=%t.same %t %t-err2 2>&1 | \
53# RUN:   FileCheck %s --check-prefix=ERR-NOBITS-TYPE
54# RUN: not llvm-objcopy --update-section=.null_type=%t.same %t %t-err2 2>&1 | \
55# RUN:   FileCheck %s --check-prefix=ERR-NULL-TYPE
56
57## Fail on trying to insert data larger than the existing section.
58# RUN: not llvm-objcopy --update-section=.in_segment=%t.larger %t %t-err3 2>&1 | \
59# RUN:   FileCheck %s --check-prefix=ERR-LARGER
60
61## But we can insert larger data if the section is NOT part of a segment.
62# RUN: llvm-objcopy --update-section=.not_in_segment=%t.larger %t %t.larger.o
63# RUN: llvm-readobj --section-headers --section-data --program-headers %t.larger.o | \
64# RUN:   FileCheck %s --check-prefix=LONG
65
66## We should still fail on inserting larger data, even if it is superceded by a
67## valid --update-section flag.
68# RUN: not llvm-objcopy --update-section=.in_segment=%t.larger --update-section=.in_segment=%t.same %t %t-err3 2>&1 | \
69# RUN:   FileCheck %s --check-prefix=ERR-LARGER
70
71## Test option parsing failures.
72# RUN: not llvm-objcopy --update-section %t %t.out 2>&1 | FileCheck %s --check-prefix=MISSING-EQ
73# RUN: not llvm-objcopy --update-section=.in_segment= %t %t.out 2>&1 | FileCheck %s --check-prefix=MISSING-FILE
74
75!ELF
76FileHeader:
77  Class:           ELFCLASS64
78  Data:            ELFDATA2LSB
79  Type:            ET_EXEC
80  Machine:         EM_X86_64
81Sections:
82  - Name:            .in_segment
83    Type:            SHT_PROGBITS
84    Content:         "3030303030303030"
85  - Name:            .unmodified_in_segment
86    Type:            SHT_PROGBITS
87    Content:         "3130303030303030"
88  - Name:            .nobits_type
89    Type:            SHT_NOBITS
90  - Name:            .not_in_segment
91    Type:            SHT_PROGBITS
92  - Name:            .null_type
93    Type:            SHT_NULL
94ProgramHeaders:
95  - Type: PT_LOAD
96    VAddr: 0x1000
97    FirstSec: .in_segment
98## The unmodified section is for ensuring that it remains untouched (ie. its
99## offset is the same) even when the section before it is shrunk.
100    LastSec: .unmodified_in_segment
101
102# NORMAL:      Name: .in_segment
103# NORMAL:      Offset:
104# NORMAL-SAME:   {{ }}0x78{{$}}
105# NORMAL:      Size:
106# NORMAL-SAME:   {{ }}8{{$}}
107# NORMAL:      SectionData (
108# NORMAL-NEXT:   |11112222|
109# NORMAL-NEXT: )
110# NORMAL:      Name: .unmodified_in_segment
111# NORMAL:      Offset:
112# NORMAL-SAME:   {{ }}0x80{{$}}
113# NORMAL:      Size:
114# NORMAL-SAME:   {{ }}8{{$}}
115# NORMAL:      SectionData (
116# NORMAL-NEXT:   |10000000|
117# NORMAL-NEXT: )
118# NORMAL:      ProgramHeaders [
119# NORMAL-NEXT:   ProgramHeader {
120# NORMAL-NEXT:     Type: PT_LOAD (0x1)
121# NORMAL:          FileSize:
122# NORMAL-SAME:       {{ }}16{{$}}
123# NORMAL:          MemSize:
124# NORMAL-SAME:       {{ }}16{{$}}
125# NORMAL:        }
126# NORMAL-NEXT: ]
127
128# SHORT:      Name: .in_segment
129# SHORT:      Offset:
130# SHORT-SAME:   {{ }}0x78{{$}}
131# SHORT:      Size:
132# SHORT-SAME:   {{ }}2{{$}}
133# SHORT:      SectionData (
134# SHORT-NEXT:   |11|
135# SHORT-NEXT: )
136# SHORT:      Name: .unmodified_in_segment
137# SHORT:      Offset:
138# SHORT-SAME:   {{ }}0x80{{$}}
139# SHORT:      Size:
140# SHORT-SAME:   {{ }}8{{$}}
141# SHORT:      SectionData (
142# SHORT-NEXT:   |10000000|
143# SHORT-NEXT: )
144# SHORT:      ProgramHeaders [
145# SHORT-NEXT:   ProgramHeader {
146# SHORT-NEXT:     Type: PT_LOAD (0x1)
147# SHORT:          FileSize:
148# SHORT-SAME:       {{ }}16{{$}}
149# SHORT:          MemSize:
150# SHORT-SAME:       {{ }}16{{$}}
151# SHORT:        }
152# SHORT-NEXT: ]
153
154## The first 8 bytes are the modified section. The last 8 bytes are the
155## unmodified section.
156# PRESERVED: 31 31 30 30 30 30 30 30 31 30 30 30 30 30 30 30
157
158# LONG:      Name: .not_in_segment
159# LONG:      Size:
160# LONG-SAME:   {{ }}9{{$}}
161# LONG:      SectionData (
162# LONG-NEXT:   |111122223|
163# LONT-NEXT: )
164
165# ADD-UPDATE:      Name: .added
166# ADD-UPDATE:      Size:
167# ADD-UPDATE-SAME:   {{ }}8{{$}}
168# ADD-UPDATE:      SectionData (
169# ADD-UPDATE-NEXT:   |11113333|
170# ADD-UPDATE:      )
171
172# ERR-NO-SECTION: error: {{.*}}section '.nosection' not found
173# ERR-NOBITS-TYPE: error: {{.*}}section '.nobits_type' cannot be updated because it does not have contents
174# ERR-NULL-TYPE: error: {{.*}}section '.null_type' cannot be updated because it does not have contents
175# ERR-LARGER: error: {{.*}}cannot fit data of size 9 into section '.in_segment' with size 8 that is part of a segment
176
177# MISSING-EQ: error: bad format for --update-section: missing '='
178# MISSING-FILE: error: bad format for --update-section: missing file name
179