aboutsummaryrefslogtreecommitdiff
path: root/llvm/test/tools/llvm-objcopy/ELF/update-section.test
blob: 79cfe0e719418f0d8b5729efbcb9b9f4fed83d19 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
# REQUIRES: x86-registered-target

# RUN: yaml2obj %s -o %t

# RUN: echo -n 11112222 > %t.same
# RUN: echo -n 00000000 > %t.zeros
# RUN: echo -n 11 > %t.short
# RUN: echo -n 11113333 > %t.updated
# RUN: echo -n 111122223 > %t.larger

## Update the segment section with a regular chunk of data the same size as the section.
# RUN: llvm-objcopy --update-section=.in_segment=%t.same %t %t.same.o
# RUN: llvm-readobj --section-headers --section-data --program-headers %t.same.o | \
# RUN:   FileCheck %s --check-prefix=NORMAL

## Show that if we overwrite a given section (.in_segment) with new data, then rewrite it
## back (from the second `--update-section`), then it should be the exact same as the
## original file.
# RUN: llvm-objcopy %t %t.copy.o
# RUN: llvm-objcopy --update-section=.in_segment=%t.same --update-section=.in_segment=%t.zeros %t %t.original.o
# RUN: cmp %t.copy.o %t.original.o

## Update segment section with a smaller chunk of data. This will also update the
## section size to the length of the new data written. This does not affect the offset
## of any subsequent sections in the same segment as this.
# RUN: llvm-objcopy --update-section=.in_segment=%t.short %t %t.short.o
# RUN: llvm-readobj --section-headers --section-data --program-headers %t.short.o | \
# RUN:   FileCheck %s --check-prefix=SHORT

## Ensure the data that was in a shortened section within a segment is still retained.
## For cases where there are gaps in segments not covered by sections, the existing
## contents are preserved.
# RUN: od -t x1 -j 0x78 -N 16 %t.short.o | FileCheck %s --check-prefix=PRESERVED

## Add a new section via --add-section, then update it.
# RUN: llvm-objcopy --add-section=.added=%t.zeros --update-section=.added=%t.updated \
# RUN:   %t %t.updated.o
# RUN: llvm-readobj --section-headers --section-data --program-headers %t.updated.o | \
# RUN:   FileCheck %s --check-prefix=ADD-UPDATE

## Adding should always be first regardless of flag order.
# RUN: llvm-objcopy --update-section=.added=%t.updated --add-section=.added=%t.updated \
# RUN:   %t %t.updated.o
# RUN: llvm-readobj --section-headers --section-data --program-headers %t.updated.o | \
# RUN:   FileCheck %s --check-prefix=ADD-UPDATE

## We can't update sections which don't exist.
# RUN: not llvm-objcopy --update-section=.nosection=%t.same %t %t-err1 2>&1 | \
# RUN:   FileCheck %s --check-prefix=ERR-NO-SECTION

## We can't update certain types of sections.
# RUN: not llvm-objcopy --update-section=.nobits_type=%t.same %t %t-err2 2>&1 | \
# RUN:   FileCheck %s --check-prefix=ERR-NOBITS-TYPE
# RUN: not llvm-objcopy --update-section=.null_type=%t.same %t %t-err2 2>&1 | \
# RUN:   FileCheck %s --check-prefix=ERR-NULL-TYPE

## Fail on trying to insert data larger than the existing section.
# RUN: not llvm-objcopy --update-section=.in_segment=%t.larger %t %t-err3 2>&1 | \
# RUN:   FileCheck %s --check-prefix=ERR-LARGER

## But we can insert larger data if the section is NOT part of a segment.
# RUN: llvm-objcopy --update-section=.not_in_segment=%t.larger %t %t.larger.o
# RUN: llvm-readobj --section-headers --section-data --program-headers %t.larger.o | \
# RUN:   FileCheck %s --check-prefix=LONG

## We should still fail on inserting larger data, even if it is superceded by a
## valid --update-section flag.
# RUN: not llvm-objcopy --update-section=.in_segment=%t.larger --update-section=.in_segment=%t.same %t %t-err3 2>&1 | \
# RUN:   FileCheck %s --check-prefix=ERR-LARGER

## Test option parsing failures.
# RUN: not llvm-objcopy --update-section %t %t.out 2>&1 | FileCheck %s --check-prefix=MISSING-EQ
# RUN: not llvm-objcopy --update-section=.in_segment= %t %t.out 2>&1 | FileCheck %s --check-prefix=MISSING-FILE

!ELF
FileHeader:
  Class:           ELFCLASS64
  Data:            ELFDATA2LSB
  Type:            ET_EXEC
  Machine:         EM_X86_64
Sections:
  - Name:            .in_segment
    Type:            SHT_PROGBITS
    Content:         "3030303030303030"
  - Name:            .unmodified_in_segment
    Type:            SHT_PROGBITS
    Content:         "3130303030303030"
  - Name:            .nobits_type
    Type:            SHT_NOBITS
  - Name:            .not_in_segment
    Type:            SHT_PROGBITS
  - Name:            .null_type
    Type:            SHT_NULL
ProgramHeaders:
  - Type: PT_LOAD
    VAddr: 0x1000
    FirstSec: .in_segment
## The unmodified section is for ensuring that it remains untouched (ie. its
## offset is the same) even when the section before it is shrunk.
    LastSec: .unmodified_in_segment

# NORMAL:      Name: .in_segment
# NORMAL:      Offset:
# NORMAL-SAME:   {{ }}0x78{{$}}
# NORMAL:      Size:
# NORMAL-SAME:   {{ }}8{{$}}
# NORMAL:      SectionData (
# NORMAL-NEXT:   |11112222|
# NORMAL-NEXT: )
# NORMAL:      Name: .unmodified_in_segment
# NORMAL:      Offset:
# NORMAL-SAME:   {{ }}0x80{{$}}
# NORMAL:      Size:
# NORMAL-SAME:   {{ }}8{{$}}
# NORMAL:      SectionData (
# NORMAL-NEXT:   |10000000|
# NORMAL-NEXT: )
# NORMAL:      ProgramHeaders [
# NORMAL-NEXT:   ProgramHeader {
# NORMAL-NEXT:     Type: PT_LOAD (0x1)
# NORMAL:          FileSize:
# NORMAL-SAME:       {{ }}16{{$}}
# NORMAL:          MemSize:
# NORMAL-SAME:       {{ }}16{{$}}
# NORMAL:        }
# NORMAL-NEXT: ]

# SHORT:      Name: .in_segment
# SHORT:      Offset:
# SHORT-SAME:   {{ }}0x78{{$}}
# SHORT:      Size:
# SHORT-SAME:   {{ }}2{{$}}
# SHORT:      SectionData (
# SHORT-NEXT:   |11|
# SHORT-NEXT: )
# SHORT:      Name: .unmodified_in_segment
# SHORT:      Offset:
# SHORT-SAME:   {{ }}0x80{{$}}
# SHORT:      Size:
# SHORT-SAME:   {{ }}8{{$}}
# SHORT:      SectionData (
# SHORT-NEXT:   |10000000|
# SHORT-NEXT: )
# SHORT:      ProgramHeaders [
# SHORT-NEXT:   ProgramHeader {
# SHORT-NEXT:     Type: PT_LOAD (0x1)
# SHORT:          FileSize:
# SHORT-SAME:       {{ }}16{{$}}
# SHORT:          MemSize:
# SHORT-SAME:       {{ }}16{{$}}
# SHORT:        }
# SHORT-NEXT: ]

## The first 8 bytes are the modified section. The last 8 bytes are the
## unmodified section.
# PRESERVED: 31 31 30 30 30 30 30 30 31 30 30 30 30 30 30 30

# LONG:      Name: .not_in_segment
# LONG:      Size:
# LONG-SAME:   {{ }}9{{$}}
# LONG:      SectionData (
# LONG-NEXT:   |111122223|
# LONT-NEXT: )

# ADD-UPDATE:      Name: .added
# ADD-UPDATE:      Size:
# ADD-UPDATE-SAME:   {{ }}8{{$}}
# ADD-UPDATE:      SectionData (
# ADD-UPDATE-NEXT:   |11113333|
# ADD-UPDATE:      )

# ERR-NO-SECTION: error: {{.*}}section '.nosection' not found
# ERR-NOBITS-TYPE: error: {{.*}}section '.nobits_type' cannot be updated because it does not have contents
# ERR-NULL-TYPE: error: {{.*}}section '.null_type' cannot be updated because it does not have contents
# ERR-LARGER: error: {{.*}}cannot fit data of size 9 into section '.in_segment' with size 8 that is part of a segment

# MISSING-EQ: error: bad format for --update-section: missing '='
# MISSING-FILE: error: bad format for --update-section: missing file name