llvm.org GIT mirror llvm / e307afa
Revert "[llvm][llvm-objcopy] Added support for outputting to binary in llvm-objcopy" This breaks the build on clang-s390x-linux. This reverts commit r310018. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@310026 91177308-0d34-0410-b5e6-96231b3b80d8 Petr Hosek 2 years ago
6 changed file(s) with 98 addition(s) and 264 deletion(s). Raw diff Collapse all Expand all
+0
-37
test/tools/llvm-objcopy/basic-align-copy.test less more
None # RUN: yaml2obj %s -o %t
1 # RUN: llvm-objcopy -O binary %t %t2
2 # RUN: od -t x2 %t2 | FileCheck %s
3 # RUN: wc -c < %t2 | FileCheck %s --check-prefix=SIZE
4
5 !ELF
6 FileHeader:
7 Class: ELFCLASS64
8 Data: ELFDATA2LSB
9 Type: ET_EXEC
10 Machine: EM_X86_64
11 Sections:
12 - Name: .text
13 Type: SHT_PROGBITS
14 Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
15 AddressAlign: 0x0000000000001000
16 Content: "c3c3c3c3"
17 - Name: .data
18 Type: SHT_PROGBITS
19 Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
20 AddressAlign: 0x0000000000001000
21 Content: "32"
22 ProgramHeaders:
23 - Type: PT_LOAD
24 Flags: [ PF_X, PF_R ]
25 Sections:
26 - Section: .text
27 - Type: PT_LOAD
28 Flags: [ PF_R ]
29 Sections:
30 - Section: .data
31
32 # CHECK: 0000000 c3c3 c3c3 0000 0000 0000 0000 0000 0000
33 # CHECK-NEXT: 0000020 0000 0000 0000 0000 0000 0000 0000 0000
34 # CHECK-NEXT: *
35 # CHECK-NEXT: 0010000 0032
36 # SIZE: 4097
+0
-25
test/tools/llvm-objcopy/basic-binary-copy.test less more
None # RUN: yaml2obj %s -o %t
1 # RUN: llvm-objcopy -O binary %t %t2
2 # RUN: od -t x2 -v %t2 | FileCheck %s
3 # RUN: wc -c < %t2 | FileCheck %s --check-prefix=SIZE
4
5 !ELF
6 FileHeader:
7 Class: ELFCLASS64
8 Data: ELFDATA2LSB
9 Type: ET_EXEC
10 Machine: EM_X86_64
11 Sections:
12 - Name: .text
13 Type: SHT_PROGBITS
14 Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
15 AddressAlign: 0x0000000000001000
16 Content: "c3c3c3c3"
17 ProgramHeaders:
18 - Type: PT_LOAD
19 Flags: [ PF_X, PF_R ]
20 Sections:
21 - Section: .text
22
23 # CHECK: 0000000 c3c3 c3c3
24 # SIZE: 4
1717 type = Tool
1818 name = llvm-objcopy
1919 parent = Tools
20 required_libraries = Object Support MC
20 required_libraries = Object MC
3939 uint64_t OriginalOffset = Offset;
4040 Offset = FirstSec->Offset - (FirstSec->OriginalOffset - OriginalOffset);
4141 }
42 }
43
44 void Segment::writeSegment(FileOutputBuffer &Out) const {
45 uint8_t *Buf = Out.getBufferStart() + Offset;
46 // We want to maintain segments' interstitial data and contents exactly.
47 // This lets us just copy segments directly.
48 std::copy(std::begin(Contents), std::end(Contents), Buf);
4942 }
5043
5144 void SectionBase::finalize() {}
10598 void Object::readProgramHeaders(const ELFFile &ElfFile) {
10699 uint32_t Index = 0;
107100 for (const auto &Phdr : unwrapOrError(ElfFile.program_headers())) {
108 ArrayRef Data{ElfFile.base() + Phdr.p_offset,
109 (size_t)Phdr.p_filesz};
110 Segments.emplace_back(llvm::make_unique(Data));
101 Segments.emplace_back(llvm::make_unique());
111102 Segment &Seg = *Segments.back();
112103 Seg.Type = Phdr.p_type;
113104 Seg.Flags = Phdr.p_flags;
143134 default:
144135 Data = unwrapOrError(ElfFile.getSectionContents(&Shdr));
145136 return llvm::make_unique
(Data);
146 }
137 };
147138 }
148139
149140 template
171162 }
172163 }
173164
165 template size_t Object::totalSize() const {
166 // We already have the section header offset so we can calculate the total
167 // size by just adding up the size of each section header.
168 return SHOffset + Sections.size() * sizeof(Elf_Shdr) + sizeof(Elf_Shdr);
169 }
170
174171 template Object::Object(const ELFObjectFile &Obj) {
175172 const auto &ElfFile = *Obj.getELFFile();
176173 const auto &Ehdr = *ElfFile.getHeader();
189186 dyn_cast(Sections[Ehdr.e_shstrndx - 1].get());
190187 }
191188
192 template
193 void Object::writeHeader(FileOutputBuffer &Out) const {
194 uint8_t *Buf = Out.getBufferStart();
195 Elf_Ehdr &Ehdr = *reinterpret_cast(Buf);
196 std::copy(Ident, Ident + 16, Ehdr.e_ident);
197 Ehdr.e_type = Type;
198 Ehdr.e_machine = Machine;
199 Ehdr.e_version = Version;
200 Ehdr.e_entry = Entry;
201 Ehdr.e_phoff = sizeof(Elf_Ehdr);
202 Ehdr.e_shoff = SHOffset;
203 Ehdr.e_flags = Flags;
204 Ehdr.e_ehsize = sizeof(Elf_Ehdr);
205 Ehdr.e_phentsize = sizeof(Elf_Phdr);
206 Ehdr.e_phnum = Segments.size();
207 Ehdr.e_shentsize = sizeof(Elf_Shdr);
208 Ehdr.e_shnum = Sections.size() + 1;
209 Ehdr.e_shstrndx = SectionNames->Index;
210 }
211
212 template
213 void Object::writeProgramHeaders(FileOutputBuffer &Out) const {
214 for (auto &Phdr : Segments)
215 Phdr->template writeHeader(Out);
216 }
217
218 template
219 void Object::writeSectionHeaders(FileOutputBuffer &Out) const {
220 uint8_t *Buf = Out.getBufferStart() + SHOffset;
221 // This reference serves to write the dummy section header at the begining
222 // of the file.
223 Elf_Shdr &Shdr = *reinterpret_cast(Buf);
224 Shdr.sh_name = 0;
225 Shdr.sh_type = SHT_NULL;
226 Shdr.sh_flags = 0;
227 Shdr.sh_addr = 0;
228 Shdr.sh_offset = 0;
229 Shdr.sh_size = 0;
230 Shdr.sh_link = 0;
231 Shdr.sh_info = 0;
232 Shdr.sh_addralign = 0;
233 Shdr.sh_entsize = 0;
234
235 for (auto &Section : Sections)
236 Section->template writeHeader(Out);
237 }
238
239 template
240 void Object::writeSectionData(FileOutputBuffer &Out) const {
241 for (auto &Section : Sections)
242 Section->writeSection(Out);
243 }
244
245 template void ELFObject::sortSections() {
189 template void Object::sortSections() {
246190 // Put all sections in offset order. Maintain the ordering as closely as
247191 // possible while meeting that demand however.
248192 auto CompareSections = [](const SecPtr &A, const SecPtr &B) {
249193 return A->OriginalOffset < B->OriginalOffset;
250194 };
251 std::stable_sort(std::begin(this->Sections), std::end(this->Sections),
252 CompareSections);
253 }
254
255 template void ELFObject::assignOffsets() {
195 std::stable_sort(std::begin(Sections), std::end(Sections), CompareSections);
196 }
197
198 template void Object::assignOffsets() {
256199 // Decide file offsets and indexes.
257 size_t PhdrSize = this->Segments.size() * sizeof(Elf_Phdr);
200 size_t PhdrSize = Segments.size() * sizeof(Elf_Phdr);
258201 // We can put section data after the ELF header and the program headers.
259202 uint64_t Offset = sizeof(Elf_Ehdr) + PhdrSize;
260203 uint64_t Index = 1;
261 for (auto &Section : this->Sections) {
204 for (auto &Section : Sections) {
262205 // The segment can have a different alignment than the section. In the case
263206 // that there is a parent segment then as long as we satisfy the alignment
264207 // of the segment it should follow that that the section is aligned.
305248 // this needs to be 4-byte aligned and on 64-bit it needs to be 8-byte aligned
306249 // so the size of ELFT::Addr is used to ensure this.
307250 Offset = alignTo(Offset, sizeof(typename ELFT::Addr));
308 this->SHOffset = Offset;
309 }
310
311 template size_t ELFObject::totalSize() const {
312 // We already have the section header offset so we can calculate the total
313 // size by just adding up the size of each section header.
314 return this->SHOffset + this->Sections.size() * sizeof(Elf_Shdr) +
315 sizeof(Elf_Shdr);
316 }
317
318 template void ELFObject::write(FileOutputBuffer &Out) const {
319 this->writeHeader(Out);
320 this->writeProgramHeaders(Out);
321 this->writeSectionData(Out);
322 this->writeSectionHeaders(Out);
323 }
324
325 template void ELFObject::finalize() {
326 for (const auto &Section : this->Sections) {
327 this->SectionNames->addString(Section->Name);
328 }
251 SHOffset = Offset;
252 }
253
254 template void Object::finalize() {
255 for (auto &Section : Sections)
256 SectionNames->addString(Section->Name);
329257
330258 sortSections();
331259 assignOffsets();
332260
333261 // Finalize SectionNames first so that we can assign name indexes.
334 this->SectionNames->finalize();
262 SectionNames->finalize();
335263 // Finally now that all offsets and indexes have been set we can finalize any
336264 // remaining issues.
337 uint64_t Offset = this->SHOffset + sizeof(Elf_Shdr);
338 for (auto &Section : this->Sections) {
265 uint64_t Offset = SHOffset + sizeof(Elf_Shdr);
266 for (auto &Section : Sections) {
339267 Section->HeaderOffset = Offset;
340268 Offset += sizeof(Elf_Shdr);
341 Section->NameIndex = this->SectionNames->findIndex(Section->Name);
269 Section->NameIndex = SectionNames->findIndex(Section->Name);
342270 Section->finalize();
343271 }
344272
345 for (auto &Segment : this->Segments)
273 for (auto &Segment : Segments)
346274 Segment->finalize();
347275 }
348276
349 template size_t BinaryObject::totalSize() const {
350 return TotalSize;
351 }
352
353 template
354 void BinaryObject::write(FileOutputBuffer &Out) const {
355 for (auto &Segment : this->Segments) {
356 if (Segment->Type == llvm::ELF::PT_LOAD) {
357 Segment->writeSegment(Out);
358 }
359 }
360 }
361
362 template void BinaryObject::finalize() {
363 for (auto &Segment : this->Segments)
364 Segment->finalize();
365
366 // Put all segments in offset order.
367 auto CompareSegments = [](const SegPtr &A, const SegPtr &B) {
368 return A->Offset < B->Offset;
369 };
370 std::sort(std::begin(this->Segments), std::end(this->Segments),
371 CompareSegments);
372
373 uint64_t Offset = 0;
374 for (auto &Segment : this->Segments) {
375 if (Segment->Type == llvm::ELF::PT_LOAD) {
376 Offset = alignTo(Offset, Segment->Align);
377 Segment->Offset = Offset;
378 Offset += Segment->FileSize;
379 }
380 }
381 TotalSize = Offset;
277 template
278 void Object::writeHeader(FileOutputBuffer &Out) const {
279 uint8_t *Buf = Out.getBufferStart();
280 Elf_Ehdr &Ehdr = *reinterpret_cast(Buf);
281 std::copy(Ident, Ident + 16, Ehdr.e_ident);
282 Ehdr.e_type = Type;
283 Ehdr.e_machine = Machine;
284 Ehdr.e_version = Version;
285 Ehdr.e_entry = Entry;
286 Ehdr.e_phoff = sizeof(Elf_Ehdr);
287 Ehdr.e_shoff = SHOffset;
288 Ehdr.e_flags = Flags;
289 Ehdr.e_ehsize = sizeof(Elf_Ehdr);
290 Ehdr.e_phentsize = sizeof(Elf_Phdr);
291 Ehdr.e_phnum = Segments.size();
292 Ehdr.e_shentsize = sizeof(Elf_Shdr);
293 Ehdr.e_shnum = Sections.size() + 1;
294 Ehdr.e_shstrndx = SectionNames->Index;
295 }
296
297 template
298 void Object::writeProgramHeaders(FileOutputBuffer &Out) const {
299 for (auto &Phdr : Segments)
300 Phdr->template writeHeader(Out);
301 }
302
303 template
304 void Object::writeSectionHeaders(FileOutputBuffer &Out) const {
305 uint8_t *Buf = Out.getBufferStart() + SHOffset;
306 // This reference serves to write the dummy section header at the begining
307 // of the file.
308 Elf_Shdr &Shdr = *reinterpret_cast(Buf);
309 Shdr.sh_name = 0;
310 Shdr.sh_type = SHT_NULL;
311 Shdr.sh_flags = 0;
312 Shdr.sh_addr = 0;
313 Shdr.sh_offset = 0;
314 Shdr.sh_size = 0;
315 Shdr.sh_link = 0;
316 Shdr.sh_info = 0;
317 Shdr.sh_addralign = 0;
318 Shdr.sh_entsize = 0;
319
320 for (auto &Section : Sections)
321 Section->template writeHeader(Out);
322 }
323
324 template
325 void Object::writeSectionData(FileOutputBuffer &Out) const {
326 for (auto &Section : Sections)
327 Section->writeSection(Out);
328 }
329
330 template void Object::write(FileOutputBuffer &Out) {
331 writeHeader(Out);
332 writeProgramHeaders(Out);
333 writeSectionData(Out);
334 writeSectionHeaders(Out);
382335 }
383336
384337 template class Object;
385338 template class Object;
386339 template class Object;
387340 template class Object;
388
389 template class ELFObject;
390 template class ELFObject;
391 template class ELFObject;
392 template class ELFObject;
393
394 template class BinaryObject;
395 template class BinaryObject;
396 template class BinaryObject;
397 template class BinaryObject;
5757 };
5858
5959 std::set Sections;
60 llvm::ArrayRef Contents;
6160
6261 public:
6362 uint64_t Align;
7069 uint64_t Type;
7170 uint64_t VAddr;
7271
73 Segment(llvm::ArrayRef Data) : Contents(Data) {}
7472 void finalize();
7573 const SectionBase *firstSection() const {
7674 if (!Sections.empty())
7977 }
8078 void addSection(const SectionBase *sec) { Sections.insert(sec); }
8179 template void writeHeader(llvm::FileOutputBuffer &Out) const;
82 void writeSegment(llvm::FileOutputBuffer &Out) const;
8380 };
8481
8582 class Section : public SectionBase {
119116 typedef typename ELFT::Ehdr Elf_Ehdr;
120117 typedef typename ELFT::Phdr Elf_Phdr;
121118
119 StringTableSection *SectionNames;
120 std::vector Sections;
121 std::vector Segments;
122
123 void sortSections();
124 void assignOffsets();
122125 SecPtr makeSection(const llvm::object::ELFFile &ElfFile,
123126 const Elf_Shdr &Shdr);
124127 void readProgramHeaders(const llvm::object::ELFFile &ElfFile);
125128 void readSectionHeaders(const llvm::object::ELFFile &ElfFile);
126
127 protected:
128 StringTableSection *SectionNames;
129 std::vector Sections;
130 std::vector Segments;
131
132129 void writeHeader(llvm::FileOutputBuffer &Out) const;
133130 void writeProgramHeaders(llvm::FileOutputBuffer &Out) const;
134131 void writeSectionData(llvm::FileOutputBuffer &Out) const;
144141 uint32_t Flags;
145142
146143 Object(const llvm::object::ELFObjectFile &Obj);
147 virtual size_t totalSize() const = 0;
148 virtual void finalize() = 0;
149 virtual void write(llvm::FileOutputBuffer &Out) const = 0;
150 virtual ~Object() = default;
144 size_t totalSize() const;
145 void finalize();
146 void write(llvm::FileOutputBuffer &Out);
151147 };
152148
153 template class ELFObject : public Object {
154 private:
155 typedef std::unique_ptr SecPtr;
156 typedef std::unique_ptr SegPtr;
157
158 typedef typename ELFT::Shdr Elf_Shdr;
159 typedef typename ELFT::Ehdr Elf_Ehdr;
160 typedef typename ELFT::Phdr Elf_Phdr;
161
162 void sortSections();
163 void assignOffsets();
164
165 public:
166 ELFObject(const llvm::object::ELFObjectFile &Obj) : Object(Obj) {}
167 void finalize() override;
168 size_t totalSize() const override;
169 void write(llvm::FileOutputBuffer &Out) const override;
170 };
171
172 template class BinaryObject : public Object {
173 private:
174 typedef std::unique_ptr SecPtr;
175 typedef std::unique_ptr SegPtr;
176
177 uint64_t TotalSize;
178
179 public:
180 BinaryObject(const llvm::object::ELFObjectFile &Obj)
181 : Object(Obj) {}
182 void finalize() override;
183 size_t totalSize() const override;
184 void write(llvm::FileOutputBuffer &Out) const override;
185 };
186149 #endif
5252 cl::opt InputFilename(cl::Positional, cl::desc(""));
5353 cl::opt OutputFilename(cl::Positional, cl::desc(""),
5454 cl::init("-"));
55 cl::opt
56 OutputFormat("O", cl::desc("set output format to one of the following:"
57 "\n\tbinary"));
5855
5956 void CopyBinary(const ELFObjectFile &ObjFile) {
6057 std::unique_ptr Buffer;
61 std::unique_ptr> Obj;
62 if (!OutputFormat.empty() && OutputFormat != "binary")
63 error("invalid output format '" + OutputFormat + "'");
64
65 if (!OutputFormat.empty() && OutputFormat == "binary")
66 Obj = llvm::make_unique>(ObjFile);
67 else
68 Obj = llvm::make_unique>(ObjFile);
69 Obj->finalize();
58 Object Obj{ObjFile};
59 Obj.finalize();
7060 ErrorOr> BufferOrErr =
71 FileOutputBuffer::create(OutputFilename, Obj->totalSize(),
61 FileOutputBuffer::create(OutputFilename, Obj.totalSize(),
7262 FileOutputBuffer::F_executable);
7363 if (BufferOrErr.getError())
7464 error("failed to open " + OutputFilename);
7767 std::error_code EC;
7868 if (EC)
7969 report_fatal_error(EC.message());
80 Obj->write(*Buffer);
70 Obj.write(*Buffer);
8171 if (auto EC = Buffer->commit())
8272 reportError(OutputFilename, EC);
8373 }