llvm.org GIT mirror llvm / 5f53af3
Revert "Reland "[llvm][llvm-objcopy] Added support for outputting to binary in llvm-objcopy"" This is failing to compile on 32-bit ARM bots. This reverts commit r309768. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@309771 91177308-0d34-0410-b5e6-96231b3b80d8 Petr Hosek 2 years ago
6 changed file(s) with 98 addition(s) and 263 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, Phdr.p_filesz};
109 Segments.emplace_back(llvm::make_unique(Data));
101 Segments.emplace_back(llvm::make_unique());
110102 Segment &Seg = *Segments.back();
111103 Seg.Type = Phdr.p_type;
112104 Seg.Flags = Phdr.p_flags;
142134 default:
143135 Data = unwrapOrError(ElfFile.getSectionContents(&Shdr));
144136 return llvm::make_unique
(Data);
145 }
137 };
146138 }
147139
148140 template
170162 }
171163 }
172164
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
173171 template Object::Object(const ELFObjectFile &Obj) {
174172 const auto &ElfFile = *Obj.getELFFile();
175173 const auto &Ehdr = *ElfFile.getHeader();
188186 dyn_cast(Sections[Ehdr.e_shstrndx - 1].get());
189187 }
190188
191 template
192 void Object::writeHeader(FileOutputBuffer &Out) const {
193 uint8_t *Buf = Out.getBufferStart();
194 Elf_Ehdr &Ehdr = *reinterpret_cast(Buf);
195 std::copy(Ident, Ident + 16, Ehdr.e_ident);
196 Ehdr.e_type = Type;
197 Ehdr.e_machine = Machine;
198 Ehdr.e_version = Version;
199 Ehdr.e_entry = Entry;
200 Ehdr.e_phoff = sizeof(Elf_Ehdr);
201 Ehdr.e_shoff = SHOffset;
202 Ehdr.e_flags = Flags;
203 Ehdr.e_ehsize = sizeof(Elf_Ehdr);
204 Ehdr.e_phentsize = sizeof(Elf_Phdr);
205 Ehdr.e_phnum = Segments.size();
206 Ehdr.e_shentsize = sizeof(Elf_Shdr);
207 Ehdr.e_shnum = Sections.size() + 1;
208 Ehdr.e_shstrndx = SectionNames->Index;
209 }
210
211 template
212 void Object::writeProgramHeaders(FileOutputBuffer &Out) const {
213 for (auto &Phdr : Segments)
214 Phdr->template writeHeader(Out);
215 }
216
217 template
218 void Object::writeSectionHeaders(FileOutputBuffer &Out) const {
219 uint8_t *Buf = Out.getBufferStart() + SHOffset;
220 // This reference serves to write the dummy section header at the begining
221 // of the file.
222 Elf_Shdr &Shdr = *reinterpret_cast(Buf);
223 Shdr.sh_name = 0;
224 Shdr.sh_type = SHT_NULL;
225 Shdr.sh_flags = 0;
226 Shdr.sh_addr = 0;
227 Shdr.sh_offset = 0;
228 Shdr.sh_size = 0;
229 Shdr.sh_link = 0;
230 Shdr.sh_info = 0;
231 Shdr.sh_addralign = 0;
232 Shdr.sh_entsize = 0;
233
234 for (auto &Section : Sections)
235 Section->template writeHeader(Out);
236 }
237
238 template
239 void Object::writeSectionData(FileOutputBuffer &Out) const {
240 for (auto &Section : Sections)
241 Section->writeSection(Out);
242 }
243
244 template void ELFObject::sortSections() {
189 template void Object::sortSections() {
245190 // Put all sections in offset order. Maintain the ordering as closely as
246191 // possible while meeting that demand however.
247192 auto CompareSections = [](const SecPtr &A, const SecPtr &B) {
248193 return A->OriginalOffset < B->OriginalOffset;
249194 };
250 std::stable_sort(std::begin(this->Sections), std::end(this->Sections),
251 CompareSections);
252 }
253
254 template void ELFObject::assignOffsets() {
195 std::stable_sort(std::begin(Sections), std::end(Sections), CompareSections);
196 }
197
198 template void Object::assignOffsets() {
255199 // Decide file offsets and indexes.
256 size_t PhdrSize = this->Segments.size() * sizeof(Elf_Phdr);
200 size_t PhdrSize = Segments.size() * sizeof(Elf_Phdr);
257201 // We can put section data after the ELF header and the program headers.
258202 uint64_t Offset = sizeof(Elf_Ehdr) + PhdrSize;
259203 uint64_t Index = 1;
260 for (auto &Section : this->Sections) {
204 for (auto &Section : Sections) {
261205 // The segment can have a different alignment than the section. In the case
262206 // that there is a parent segment then as long as we satisfy the alignment
263207 // of the segment it should follow that that the section is aligned.
304248 // this needs to be 4-byte aligned and on 64-bit it needs to be 8-byte aligned
305249 // so the size of ELFT::Addr is used to ensure this.
306250 Offset = alignTo(Offset, sizeof(typename ELFT::Addr));
307 this->SHOffset = Offset;
308 }
309
310 template size_t ELFObject::totalSize() const {
311 // We already have the section header offset so we can calculate the total
312 // size by just adding up the size of each section header.
313 return this->SHOffset + this->Sections.size() * sizeof(Elf_Shdr) +
314 sizeof(Elf_Shdr);
315 }
316
317 template void ELFObject::write(FileOutputBuffer &Out) const {
318 this->writeHeader(Out);
319 this->writeProgramHeaders(Out);
320 this->writeSectionData(Out);
321 this->writeSectionHeaders(Out);
322 }
323
324 template void ELFObject::finalize() {
325 for (const auto &Section : this->Sections) {
326 this->SectionNames->addString(Section->Name);
327 }
251 SHOffset = Offset;
252 }
253
254 template void Object::finalize() {
255 for (auto &Section : Sections)
256 SectionNames->addString(Section->Name);
328257
329258 sortSections();
330259 assignOffsets();
331260
332261 // Finalize SectionNames first so that we can assign name indexes.
333 this->SectionNames->finalize();
262 SectionNames->finalize();
334263 // Finally now that all offsets and indexes have been set we can finalize any
335264 // remaining issues.
336 uint64_t Offset = this->SHOffset + sizeof(Elf_Shdr);
337 for (auto &Section : this->Sections) {
265 uint64_t Offset = SHOffset + sizeof(Elf_Shdr);
266 for (auto &Section : Sections) {
338267 Section->HeaderOffset = Offset;
339268 Offset += sizeof(Elf_Shdr);
340 Section->NameIndex = this->SectionNames->findIndex(Section->Name);
269 Section->NameIndex = SectionNames->findIndex(Section->Name);
341270 Section->finalize();
342271 }
343272
344 for (auto &Segment : this->Segments)
273 for (auto &Segment : Segments)
345274 Segment->finalize();
346275 }
347276
348 template size_t BinaryObject::totalSize() const {
349 return TotalSize;
350 }
351
352 template
353 void BinaryObject::write(FileOutputBuffer &Out) const {
354 for (auto &Segment : this->Segments) {
355 if (Segment->Type == llvm::ELF::PT_LOAD) {
356 Segment->writeSegment(Out);
357 }
358 }
359 }
360
361 template void BinaryObject::finalize() {
362 for (auto &Segment : this->Segments)
363 Segment->finalize();
364
365 // Put all segments in offset order.
366 auto CompareSegments = [](const SegPtr &A, const SegPtr &B) {
367 return A->Offset < B->Offset;
368 };
369 std::sort(std::begin(this->Segments), std::end(this->Segments),
370 CompareSegments);
371
372 uint64_t Offset = 0;
373 for (auto &Segment : this->Segments) {
374 if (Segment->Type == llvm::ELF::PT_LOAD) {
375 Offset = alignTo(Offset, Segment->Align);
376 Segment->Offset = Offset;
377 Offset += Segment->FileSize;
378 }
379 }
380 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);
381335 }
382336
383337 template class Object;
384338 template class Object;
385339 template class Object;
386340 template class Object;
387
388 template class ELFObject;
389 template class ELFObject;
390 template class ELFObject;
391 template class ELFObject;
392
393 template class BinaryObject;
394 template class BinaryObject;
395 template class BinaryObject;
396 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 }