2017-08-01 02:33:58 +02:00
|
|
|
//===- Object.h -------------------------------------------------*- C++ -*-===//
|
|
|
|
//
|
2019-01-19 09:50:56 +01:00
|
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
2017-08-01 02:33:58 +02:00
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2017-11-01 22:16:06 +01:00
|
|
|
#ifndef LLVM_TOOLS_OBJCOPY_OBJECT_H
|
|
|
|
#define LLVM_TOOLS_OBJCOPY_OBJECT_H
|
2017-08-01 02:33:58 +02:00
|
|
|
|
2018-10-16 07:40:18 +02:00
|
|
|
#include "Buffer.h"
|
2018-10-12 00:33:50 +02:00
|
|
|
#include "CopyConfig.h"
|
2017-11-01 22:16:06 +01:00
|
|
|
#include "llvm/ADT/ArrayRef.h"
|
|
|
|
#include "llvm/ADT/StringRef.h"
|
|
|
|
#include "llvm/ADT/Twine.h"
|
|
|
|
#include "llvm/BinaryFormat/ELF.h"
|
2017-08-01 02:33:58 +02:00
|
|
|
#include "llvm/MC/StringTableBuilder.h"
|
|
|
|
#include "llvm/Object/ELFObjectFile.h"
|
2018-01-25 23:46:17 +01:00
|
|
|
#include "llvm/Support/FileOutputBuffer.h"
|
2017-11-01 22:16:06 +01:00
|
|
|
#include <cstddef>
|
|
|
|
#include <cstdint>
|
|
|
|
#include <functional>
|
2017-08-01 02:33:58 +02:00
|
|
|
#include <memory>
|
|
|
|
#include <set>
|
2017-11-01 22:16:06 +01:00
|
|
|
#include <vector>
|
2017-08-01 02:33:58 +02:00
|
|
|
|
2017-11-01 22:16:06 +01:00
|
|
|
namespace llvm {
|
2018-09-07 10:10:22 +02:00
|
|
|
enum class DebugCompressionType;
|
2018-07-18 02:10:51 +02:00
|
|
|
namespace objcopy {
|
2018-10-25 00:49:06 +02:00
|
|
|
namespace elf {
|
2017-11-01 22:16:06 +01:00
|
|
|
|
2017-09-25 22:37:28 +02:00
|
|
|
class SectionBase;
|
2018-01-25 23:46:17 +01:00
|
|
|
class Section;
|
|
|
|
class OwnedDataSection;
|
|
|
|
class StringTableSection;
|
|
|
|
class SymbolTableSection;
|
|
|
|
class RelocationSection;
|
|
|
|
class DynamicRelocationSection;
|
|
|
|
class GnuDebugLinkSection;
|
2018-03-21 20:53:44 +01:00
|
|
|
class GroupSection;
|
2018-07-16 21:48:52 +02:00
|
|
|
class SectionIndexSection;
|
2018-09-07 10:10:22 +02:00
|
|
|
class CompressedSection;
|
2018-10-01 12:29:41 +02:00
|
|
|
class DecompressedSection;
|
2017-11-01 22:16:06 +01:00
|
|
|
class Segment;
|
2018-01-25 23:46:17 +01:00
|
|
|
class Object;
|
2018-05-09 23:36:54 +02:00
|
|
|
struct Symbol;
|
2017-09-25 22:37:28 +02:00
|
|
|
|
|
|
|
class SectionTableRef {
|
2018-01-25 23:46:17 +01:00
|
|
|
MutableArrayRef<std::unique_ptr<SectionBase>> Sections;
|
2017-09-25 22:37:28 +02:00
|
|
|
|
|
|
|
public:
|
2018-01-25 23:46:17 +01:00
|
|
|
using iterator = pointee_iterator<std::unique_ptr<SectionBase> *>;
|
|
|
|
|
2018-03-21 20:53:44 +01:00
|
|
|
explicit SectionTableRef(MutableArrayRef<std::unique_ptr<SectionBase>> Secs)
|
2017-09-25 22:37:28 +02:00
|
|
|
: Sections(Secs) {}
|
|
|
|
SectionTableRef(const SectionTableRef &) = default;
|
|
|
|
|
2018-01-25 23:46:17 +01:00
|
|
|
iterator begin() { return iterator(Sections.data()); }
|
|
|
|
iterator end() { return iterator(Sections.data() + Sections.size()); }
|
[llvm-objcopy] Replace the size() helper with SectionTableRef::size
Summary:
BTW, STLExtras.h provides llvm::size() which is similar to std::size()
for random access iterators. However, if we prefer qualified
llvm::size(), the member function .size() will be more convenient.
Reviewers: jhenderson, jakehehrlich, rupprecht, grimar, alexshap, espindola
Reviewed By: grimar
Subscribers: emaste, arichardson, jdoerfert, llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D60028
llvm-svn: 357347
2019-03-30 15:08:59 +01:00
|
|
|
size_t size() const { return Sections.size(); }
|
2018-01-25 23:46:17 +01:00
|
|
|
|
2018-07-16 21:48:52 +02:00
|
|
|
SectionBase *getSection(uint32_t Index, Twine ErrMsg);
|
2017-09-25 22:37:28 +02:00
|
|
|
|
|
|
|
template <class T>
|
2018-07-16 21:48:52 +02:00
|
|
|
T *getSectionOfType(uint32_t Index, Twine IndexErrMsg, Twine TypeErrMsg);
|
2017-09-25 22:37:28 +02:00
|
|
|
};
|
2017-08-01 02:33:58 +02:00
|
|
|
|
2018-01-25 23:46:17 +01:00
|
|
|
enum ElfType { ELFT_ELF32LE, ELFT_ELF64LE, ELFT_ELF32BE, ELFT_ELF64BE };
|
|
|
|
|
|
|
|
class SectionVisitor {
|
|
|
|
public:
|
[llvm-objcopy][ELF] Implement a mutable section visitor that updates size-related fields (Size, EntrySize, Align) before layout.
Summary:
Fix EntrySize, Size, and Align before doing layout calculation.
As a side cleanup, this removes a dependence on sizeof(Elf_Sym) within BinaryReader, so we can untemplatize that.
This unblocks a cleaner implementation of handling the -O<format> flag. See D53667 for a previous attempt. Actual implementation of the -O<format> flag will come in an upcoming commit, this is largely a NFC (although not _totally_ one, because alignment on binary input was actually wrong before).
Reviewers: jakehehrlich, jhenderson, alexshap, espindola
Reviewed By: jhenderson
Subscribers: emaste, arichardson, llvm-commits
Differential Revision: https://reviews.llvm.org/D56211
llvm-svn: 350336
2019-01-03 18:45:30 +01:00
|
|
|
virtual ~SectionVisitor() = default;
|
2018-01-25 23:46:17 +01:00
|
|
|
|
|
|
|
virtual void visit(const Section &Sec) = 0;
|
|
|
|
virtual void visit(const OwnedDataSection &Sec) = 0;
|
|
|
|
virtual void visit(const StringTableSection &Sec) = 0;
|
|
|
|
virtual void visit(const SymbolTableSection &Sec) = 0;
|
|
|
|
virtual void visit(const RelocationSection &Sec) = 0;
|
|
|
|
virtual void visit(const DynamicRelocationSection &Sec) = 0;
|
|
|
|
virtual void visit(const GnuDebugLinkSection &Sec) = 0;
|
2018-03-21 20:53:44 +01:00
|
|
|
virtual void visit(const GroupSection &Sec) = 0;
|
2018-07-16 21:48:52 +02:00
|
|
|
virtual void visit(const SectionIndexSection &Sec) = 0;
|
2018-09-07 10:10:22 +02:00
|
|
|
virtual void visit(const CompressedSection &Sec) = 0;
|
2018-10-01 12:29:41 +02:00
|
|
|
virtual void visit(const DecompressedSection &Sec) = 0;
|
2018-01-25 23:46:17 +01:00
|
|
|
};
|
|
|
|
|
[llvm-objcopy][ELF] Implement a mutable section visitor that updates size-related fields (Size, EntrySize, Align) before layout.
Summary:
Fix EntrySize, Size, and Align before doing layout calculation.
As a side cleanup, this removes a dependence on sizeof(Elf_Sym) within BinaryReader, so we can untemplatize that.
This unblocks a cleaner implementation of handling the -O<format> flag. See D53667 for a previous attempt. Actual implementation of the -O<format> flag will come in an upcoming commit, this is largely a NFC (although not _totally_ one, because alignment on binary input was actually wrong before).
Reviewers: jakehehrlich, jhenderson, alexshap, espindola
Reviewed By: jhenderson
Subscribers: emaste, arichardson, llvm-commits
Differential Revision: https://reviews.llvm.org/D56211
llvm-svn: 350336
2019-01-03 18:45:30 +01:00
|
|
|
class MutableSectionVisitor {
|
|
|
|
public:
|
|
|
|
virtual ~MutableSectionVisitor() = default;
|
|
|
|
|
|
|
|
virtual void visit(Section &Sec) = 0;
|
|
|
|
virtual void visit(OwnedDataSection &Sec) = 0;
|
|
|
|
virtual void visit(StringTableSection &Sec) = 0;
|
|
|
|
virtual void visit(SymbolTableSection &Sec) = 0;
|
|
|
|
virtual void visit(RelocationSection &Sec) = 0;
|
|
|
|
virtual void visit(DynamicRelocationSection &Sec) = 0;
|
|
|
|
virtual void visit(GnuDebugLinkSection &Sec) = 0;
|
|
|
|
virtual void visit(GroupSection &Sec) = 0;
|
|
|
|
virtual void visit(SectionIndexSection &Sec) = 0;
|
|
|
|
virtual void visit(CompressedSection &Sec) = 0;
|
|
|
|
virtual void visit(DecompressedSection &Sec) = 0;
|
|
|
|
};
|
|
|
|
|
2018-01-25 23:46:17 +01:00
|
|
|
class SectionWriter : public SectionVisitor {
|
|
|
|
protected:
|
2018-07-06 19:51:03 +02:00
|
|
|
Buffer &Out;
|
2018-01-25 23:46:17 +01:00
|
|
|
|
|
|
|
public:
|
2019-03-15 11:20:51 +01:00
|
|
|
virtual ~SectionWriter() = default;
|
2018-01-25 23:46:17 +01:00
|
|
|
|
|
|
|
void visit(const Section &Sec) override;
|
|
|
|
void visit(const OwnedDataSection &Sec) override;
|
|
|
|
void visit(const StringTableSection &Sec) override;
|
|
|
|
void visit(const DynamicRelocationSection &Sec) override;
|
|
|
|
virtual void visit(const SymbolTableSection &Sec) override = 0;
|
|
|
|
virtual void visit(const RelocationSection &Sec) override = 0;
|
|
|
|
virtual void visit(const GnuDebugLinkSection &Sec) override = 0;
|
2018-03-21 20:53:44 +01:00
|
|
|
virtual void visit(const GroupSection &Sec) override = 0;
|
2018-07-16 21:48:52 +02:00
|
|
|
virtual void visit(const SectionIndexSection &Sec) override = 0;
|
2018-09-07 10:10:22 +02:00
|
|
|
virtual void visit(const CompressedSection &Sec) override = 0;
|
2018-10-01 12:29:41 +02:00
|
|
|
virtual void visit(const DecompressedSection &Sec) override = 0;
|
2018-01-25 23:46:17 +01:00
|
|
|
|
2018-07-06 19:51:03 +02:00
|
|
|
explicit SectionWriter(Buffer &Buf) : Out(Buf) {}
|
2018-01-25 23:46:17 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
template <class ELFT> class ELFSectionWriter : public SectionWriter {
|
|
|
|
private:
|
|
|
|
using Elf_Word = typename ELFT::Word;
|
|
|
|
using Elf_Rel = typename ELFT::Rel;
|
|
|
|
using Elf_Rela = typename ELFT::Rela;
|
2018-08-10 18:25:58 +02:00
|
|
|
using Elf_Sym = typename ELFT::Sym;
|
2018-01-25 23:46:17 +01:00
|
|
|
|
|
|
|
public:
|
|
|
|
virtual ~ELFSectionWriter() {}
|
|
|
|
void visit(const SymbolTableSection &Sec) override;
|
|
|
|
void visit(const RelocationSection &Sec) override;
|
|
|
|
void visit(const GnuDebugLinkSection &Sec) override;
|
2018-03-21 20:53:44 +01:00
|
|
|
void visit(const GroupSection &Sec) override;
|
2018-07-16 21:48:52 +02:00
|
|
|
void visit(const SectionIndexSection &Sec) override;
|
2018-09-07 10:10:22 +02:00
|
|
|
void visit(const CompressedSection &Sec) override;
|
2018-10-01 12:29:41 +02:00
|
|
|
void visit(const DecompressedSection &Sec) override;
|
2018-01-25 23:46:17 +01:00
|
|
|
|
2018-07-06 19:51:03 +02:00
|
|
|
explicit ELFSectionWriter(Buffer &Buf) : SectionWriter(Buf) {}
|
2018-01-25 23:46:17 +01:00
|
|
|
};
|
|
|
|
|
[llvm-objcopy][ELF] Implement a mutable section visitor that updates size-related fields (Size, EntrySize, Align) before layout.
Summary:
Fix EntrySize, Size, and Align before doing layout calculation.
As a side cleanup, this removes a dependence on sizeof(Elf_Sym) within BinaryReader, so we can untemplatize that.
This unblocks a cleaner implementation of handling the -O<format> flag. See D53667 for a previous attempt. Actual implementation of the -O<format> flag will come in an upcoming commit, this is largely a NFC (although not _totally_ one, because alignment on binary input was actually wrong before).
Reviewers: jakehehrlich, jhenderson, alexshap, espindola
Reviewed By: jhenderson
Subscribers: emaste, arichardson, llvm-commits
Differential Revision: https://reviews.llvm.org/D56211
llvm-svn: 350336
2019-01-03 18:45:30 +01:00
|
|
|
template <class ELFT> class ELFSectionSizer : public MutableSectionVisitor {
|
|
|
|
private:
|
|
|
|
using Elf_Rel = typename ELFT::Rel;
|
|
|
|
using Elf_Rela = typename ELFT::Rela;
|
|
|
|
using Elf_Sym = typename ELFT::Sym;
|
2019-01-03 20:09:00 +01:00
|
|
|
using Elf_Word = typename ELFT::Word;
|
|
|
|
using Elf_Xword = typename ELFT::Xword;
|
[llvm-objcopy][ELF] Implement a mutable section visitor that updates size-related fields (Size, EntrySize, Align) before layout.
Summary:
Fix EntrySize, Size, and Align before doing layout calculation.
As a side cleanup, this removes a dependence on sizeof(Elf_Sym) within BinaryReader, so we can untemplatize that.
This unblocks a cleaner implementation of handling the -O<format> flag. See D53667 for a previous attempt. Actual implementation of the -O<format> flag will come in an upcoming commit, this is largely a NFC (although not _totally_ one, because alignment on binary input was actually wrong before).
Reviewers: jakehehrlich, jhenderson, alexshap, espindola
Reviewed By: jhenderson
Subscribers: emaste, arichardson, llvm-commits
Differential Revision: https://reviews.llvm.org/D56211
llvm-svn: 350336
2019-01-03 18:45:30 +01:00
|
|
|
|
|
|
|
public:
|
|
|
|
void visit(Section &Sec) override;
|
|
|
|
void visit(OwnedDataSection &Sec) override;
|
|
|
|
void visit(StringTableSection &Sec) override;
|
|
|
|
void visit(DynamicRelocationSection &Sec) override;
|
|
|
|
void visit(SymbolTableSection &Sec) override;
|
|
|
|
void visit(RelocationSection &Sec) override;
|
|
|
|
void visit(GnuDebugLinkSection &Sec) override;
|
|
|
|
void visit(GroupSection &Sec) override;
|
|
|
|
void visit(SectionIndexSection &Sec) override;
|
|
|
|
void visit(CompressedSection &Sec) override;
|
|
|
|
void visit(DecompressedSection &Sec) override;
|
|
|
|
};
|
|
|
|
|
2018-01-25 23:46:17 +01:00
|
|
|
#define MAKE_SEC_WRITER_FRIEND \
|
|
|
|
friend class SectionWriter; \
|
[llvm-objcopy][ELF] Implement a mutable section visitor that updates size-related fields (Size, EntrySize, Align) before layout.
Summary:
Fix EntrySize, Size, and Align before doing layout calculation.
As a side cleanup, this removes a dependence on sizeof(Elf_Sym) within BinaryReader, so we can untemplatize that.
This unblocks a cleaner implementation of handling the -O<format> flag. See D53667 for a previous attempt. Actual implementation of the -O<format> flag will come in an upcoming commit, this is largely a NFC (although not _totally_ one, because alignment on binary input was actually wrong before).
Reviewers: jakehehrlich, jhenderson, alexshap, espindola
Reviewed By: jhenderson
Subscribers: emaste, arichardson, llvm-commits
Differential Revision: https://reviews.llvm.org/D56211
llvm-svn: 350336
2019-01-03 18:45:30 +01:00
|
|
|
template <class ELFT> friend class ELFSectionWriter; \
|
|
|
|
template <class ELFT> friend class ELFSectionSizer;
|
2018-01-25 23:46:17 +01:00
|
|
|
|
|
|
|
class BinarySectionWriter : public SectionWriter {
|
|
|
|
public:
|
|
|
|
virtual ~BinarySectionWriter() {}
|
|
|
|
|
|
|
|
void visit(const SymbolTableSection &Sec) override;
|
|
|
|
void visit(const RelocationSection &Sec) override;
|
|
|
|
void visit(const GnuDebugLinkSection &Sec) override;
|
2018-03-21 20:53:44 +01:00
|
|
|
void visit(const GroupSection &Sec) override;
|
2018-07-16 21:48:52 +02:00
|
|
|
void visit(const SectionIndexSection &Sec) override;
|
2018-09-07 10:10:22 +02:00
|
|
|
void visit(const CompressedSection &Sec) override;
|
2018-10-01 12:29:41 +02:00
|
|
|
void visit(const DecompressedSection &Sec) override;
|
2018-03-21 20:53:44 +01:00
|
|
|
|
2018-07-06 19:51:03 +02:00
|
|
|
explicit BinarySectionWriter(Buffer &Buf) : SectionWriter(Buf) {}
|
|
|
|
};
|
|
|
|
|
2018-01-25 23:46:17 +01:00
|
|
|
class Writer {
|
|
|
|
protected:
|
|
|
|
Object &Obj;
|
2018-07-06 19:51:03 +02:00
|
|
|
Buffer &Buf;
|
2018-01-25 23:46:17 +01:00
|
|
|
|
|
|
|
public:
|
|
|
|
virtual ~Writer();
|
[llvm-objcopy] Return Error from Buffer::allocate(), [ELF]Writer::finalize(), and [ELF]Writer::commit()
Summary:
This patch changes a few methods to return Error instead of manually calling error/reportError to abort. This will make it easier to extract into a library.
Note that error() takes just a string (this patch also adds an overload that takes an Error), while reportError() takes string + [error/code]. To help unify things, use FileError to associate a given filename with an error. Note that this takes some special care (for now), e.g. calling reportError(FileName, <something that could be FileError>) will duplicate the filename. The goal is to eventually remove reportError() and have every error associated with a file to be a FileError, and just one error handling block at the tool level.
This change was suggested in D56806. I took it a little further than suggested, but completely fixing llvm-objcopy will take a couple more patches. If this approach looks good, I'll commit this and apply similar patche(s) for the rest.
This change is NFC in terms of non-error related code, although the error message changes in one context.
Reviewers: alexshap, jhenderson, jakehehrlich, mstorsjo, espindola
Reviewed By: alexshap, jhenderson
Subscribers: llvm-commits, emaste, arichardson
Differential Revision: https://reviews.llvm.org/D56930
llvm-svn: 351896
2019-01-23 00:49:16 +01:00
|
|
|
virtual Error finalize() = 0;
|
|
|
|
virtual Error write() = 0;
|
2018-01-25 23:46:17 +01:00
|
|
|
|
2018-07-06 19:51:03 +02:00
|
|
|
Writer(Object &O, Buffer &B) : Obj(O), Buf(B) {}
|
2018-01-25 23:46:17 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
template <class ELFT> class ELFWriter : public Writer {
|
|
|
|
private:
|
2018-08-10 18:25:58 +02:00
|
|
|
using Elf_Addr = typename ELFT::Addr;
|
2018-01-25 23:46:17 +01:00
|
|
|
using Elf_Shdr = typename ELFT::Shdr;
|
|
|
|
using Elf_Phdr = typename ELFT::Phdr;
|
|
|
|
using Elf_Ehdr = typename ELFT::Ehdr;
|
|
|
|
|
[llvm-objcopy] Add support for -I binary -B <arch>.
Summary:
The -I (--input-target) and -B (--binary-architecture) flags exist but are currently silently ignored. This adds support for -I binary for architectures i386, x86-64 (and alias i386:x86-64), arm, aarch64, sparc, and ppc (powerpc:common64). This is largely based on D41687.
This is done by implementing an additional subclass of Reader, BinaryReader, which works by interpreting the input file as contents for .data field, sets up a synthetic header, and adds additional sections/symbols (e.g. _binary__tmp_data_txt_start).
Reviewers: jakehehrlich, alexshap, jhenderson, javed.absar
Reviewed By: jhenderson
Subscribers: jyknight, nemanjai, kbarton, fedor.sergeev, jrtc27, kristof.beyls, paulsemel, llvm-commits
Differential Revision: https://reviews.llvm.org/D50343
llvm-svn: 340070
2018-08-17 20:51:11 +02:00
|
|
|
void initEhdrSegment();
|
|
|
|
|
2018-01-25 23:46:17 +01:00
|
|
|
void writeEhdr();
|
|
|
|
void writePhdr(const Segment &Seg);
|
|
|
|
void writeShdr(const SectionBase &Sec);
|
|
|
|
|
|
|
|
void writePhdrs();
|
|
|
|
void writeShdrs();
|
|
|
|
void writeSectionData();
|
2019-03-25 17:36:26 +01:00
|
|
|
void writeSegmentData();
|
2018-01-25 23:46:17 +01:00
|
|
|
|
|
|
|
void assignOffsets();
|
|
|
|
|
|
|
|
std::unique_ptr<ELFSectionWriter<ELFT>> SecWriter;
|
|
|
|
|
|
|
|
size_t totalSize() const;
|
|
|
|
|
|
|
|
public:
|
|
|
|
virtual ~ELFWriter() {}
|
2019-04-02 16:11:13 +02:00
|
|
|
bool WriteSectionHeaders;
|
2018-01-25 23:46:17 +01:00
|
|
|
|
[llvm-objcopy] Return Error from Buffer::allocate(), [ELF]Writer::finalize(), and [ELF]Writer::commit()
Summary:
This patch changes a few methods to return Error instead of manually calling error/reportError to abort. This will make it easier to extract into a library.
Note that error() takes just a string (this patch also adds an overload that takes an Error), while reportError() takes string + [error/code]. To help unify things, use FileError to associate a given filename with an error. Note that this takes some special care (for now), e.g. calling reportError(FileName, <something that could be FileError>) will duplicate the filename. The goal is to eventually remove reportError() and have every error associated with a file to be a FileError, and just one error handling block at the tool level.
This change was suggested in D56806. I took it a little further than suggested, but completely fixing llvm-objcopy will take a couple more patches. If this approach looks good, I'll commit this and apply similar patche(s) for the rest.
This change is NFC in terms of non-error related code, although the error message changes in one context.
Reviewers: alexshap, jhenderson, jakehehrlich, mstorsjo, espindola
Reviewed By: alexshap, jhenderson
Subscribers: llvm-commits, emaste, arichardson
Differential Revision: https://reviews.llvm.org/D56930
llvm-svn: 351896
2019-01-23 00:49:16 +01:00
|
|
|
Error finalize() override;
|
|
|
|
Error write() override;
|
2019-04-02 16:11:13 +02:00
|
|
|
ELFWriter(Object &Obj, Buffer &Buf, bool WSH);
|
2018-01-25 23:46:17 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
class BinaryWriter : public Writer {
|
|
|
|
private:
|
|
|
|
std::unique_ptr<BinarySectionWriter> SecWriter;
|
|
|
|
|
|
|
|
uint64_t TotalSize;
|
|
|
|
|
|
|
|
public:
|
|
|
|
~BinaryWriter() {}
|
[llvm-objcopy] Return Error from Buffer::allocate(), [ELF]Writer::finalize(), and [ELF]Writer::commit()
Summary:
This patch changes a few methods to return Error instead of manually calling error/reportError to abort. This will make it easier to extract into a library.
Note that error() takes just a string (this patch also adds an overload that takes an Error), while reportError() takes string + [error/code]. To help unify things, use FileError to associate a given filename with an error. Note that this takes some special care (for now), e.g. calling reportError(FileName, <something that could be FileError>) will duplicate the filename. The goal is to eventually remove reportError() and have every error associated with a file to be a FileError, and just one error handling block at the tool level.
This change was suggested in D56806. I took it a little further than suggested, but completely fixing llvm-objcopy will take a couple more patches. If this approach looks good, I'll commit this and apply similar patche(s) for the rest.
This change is NFC in terms of non-error related code, although the error message changes in one context.
Reviewers: alexshap, jhenderson, jakehehrlich, mstorsjo, espindola
Reviewed By: alexshap, jhenderson
Subscribers: llvm-commits, emaste, arichardson
Differential Revision: https://reviews.llvm.org/D56930
llvm-svn: 351896
2019-01-23 00:49:16 +01:00
|
|
|
Error finalize() override;
|
|
|
|
Error write() override;
|
2018-07-06 19:51:03 +02:00
|
|
|
BinaryWriter(Object &Obj, Buffer &Buf) : Writer(Obj, Buf) {}
|
2018-01-25 23:46:17 +01:00
|
|
|
};
|
|
|
|
|
2017-08-01 02:33:58 +02:00
|
|
|
class SectionBase {
|
|
|
|
public:
|
2018-09-07 10:10:22 +02:00
|
|
|
std::string Name;
|
2017-08-01 02:33:58 +02:00
|
|
|
Segment *ParentSegment = nullptr;
|
|
|
|
uint64_t HeaderOffset;
|
2018-07-16 21:48:52 +02:00
|
|
|
uint64_t OriginalOffset = std::numeric_limits<uint64_t>::max();
|
2017-08-01 02:33:58 +02:00
|
|
|
uint32_t Index;
|
2018-07-16 21:48:52 +02:00
|
|
|
bool HasSymbol = false;
|
2017-08-01 02:33:58 +02:00
|
|
|
|
|
|
|
uint64_t Addr = 0;
|
|
|
|
uint64_t Align = 1;
|
|
|
|
uint32_t EntrySize = 0;
|
|
|
|
uint64_t Flags = 0;
|
|
|
|
uint64_t Info = 0;
|
2017-11-01 22:16:06 +01:00
|
|
|
uint64_t Link = ELF::SHN_UNDEF;
|
2017-08-01 02:33:58 +02:00
|
|
|
uint64_t NameIndex = 0;
|
|
|
|
uint64_t Offset = 0;
|
|
|
|
uint64_t Size = 0;
|
2017-11-01 22:16:06 +01:00
|
|
|
uint64_t Type = ELF::SHT_NULL;
|
2018-08-09 19:05:21 +02:00
|
|
|
ArrayRef<uint8_t> OriginalData;
|
2017-11-01 22:16:06 +01:00
|
|
|
|
2018-09-07 10:10:22 +02:00
|
|
|
SectionBase() = default;
|
|
|
|
SectionBase(const SectionBase &) = default;
|
|
|
|
|
2017-11-01 22:16:06 +01:00
|
|
|
virtual ~SectionBase() = default;
|
2017-08-01 02:33:58 +02:00
|
|
|
|
2017-09-25 22:37:28 +02:00
|
|
|
virtual void initialize(SectionTableRef SecTable);
|
2017-08-01 02:33:58 +02:00
|
|
|
virtual void finalize();
|
[llvm-objcopy] Make removeSectionReferences batched
Summary:
Removing a large number of sections from a file with a lot of symbols can have abysmal (i.e. O(n^2)) performance, e.g. when running `--only-section` to extract one section out of a large file.
This comes from iterating over all symbols in the symbol table each time we remove a section, to remove references to the section we just removed.
Instead, do just one pass of symbol removal by passing a hash set of all the sections we'd like to remove references to.
This fixes a regression when running llvm-objcopy -j <one section> on an object file with many sections and symbols -- on my machine, running `objcopy -j .keep_me huge-input.o /tmp/foo.o` takes .3s with GNU objcopy, 1.3s with an updated llvm-objcopy, and 7+ minutes with llvm-objcopy prior to this patch.
Reviewers: MaskRay, jhenderson, jakehehrlich, alexshap, espindola
Reviewed By: MaskRay, jhenderson
Subscribers: echristo, emaste, arichardson, mgrang, jdoerfert, llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D58296
llvm-svn: 354597
2019-02-21 17:45:42 +01:00
|
|
|
// Remove references to these sections. The list of sections must be sorted.
|
|
|
|
virtual Error
|
2019-04-18 11:13:30 +02:00
|
|
|
removeSectionReferences(bool AllowBrokenLinks,
|
|
|
|
function_ref<bool(const SectionBase *)> ToRemove);
|
2019-02-01 16:20:36 +01:00
|
|
|
virtual Error removeSymbols(function_ref<bool(const Symbol &)> ToRemove);
|
2018-01-25 23:46:17 +01:00
|
|
|
virtual void accept(SectionVisitor &Visitor) const = 0;
|
[llvm-objcopy][ELF] Implement a mutable section visitor that updates size-related fields (Size, EntrySize, Align) before layout.
Summary:
Fix EntrySize, Size, and Align before doing layout calculation.
As a side cleanup, this removes a dependence on sizeof(Elf_Sym) within BinaryReader, so we can untemplatize that.
This unblocks a cleaner implementation of handling the -O<format> flag. See D53667 for a previous attempt. Actual implementation of the -O<format> flag will come in an upcoming commit, this is largely a NFC (although not _totally_ one, because alignment on binary input was actually wrong before).
Reviewers: jakehehrlich, jhenderson, alexshap, espindola
Reviewed By: jhenderson
Subscribers: emaste, arichardson, llvm-commits
Differential Revision: https://reviews.llvm.org/D56211
llvm-svn: 350336
2019-01-03 18:45:30 +01:00
|
|
|
virtual void accept(MutableSectionVisitor &Visitor) = 0;
|
2018-05-25 13:01:25 +02:00
|
|
|
virtual void markSymbols();
|
2019-03-11 12:01:24 +01:00
|
|
|
virtual void
|
|
|
|
replaceSectionReferences(const DenseMap<SectionBase *, SectionBase *> &);
|
2017-08-01 02:33:58 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
class Segment {
|
|
|
|
private:
|
|
|
|
struct SectionCompare {
|
|
|
|
bool operator()(const SectionBase *Lhs, const SectionBase *Rhs) const {
|
|
|
|
// Some sections might have the same address if one of them is empty. To
|
|
|
|
// fix this we can use the lexicographic ordering on ->Addr and the
|
|
|
|
// address of the actully stored section.
|
|
|
|
if (Lhs->OriginalOffset == Rhs->OriginalOffset)
|
|
|
|
return Lhs < Rhs;
|
|
|
|
return Lhs->OriginalOffset < Rhs->OriginalOffset;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
std::set<const SectionBase *, SectionCompare> Sections;
|
|
|
|
|
|
|
|
public:
|
2018-12-12 23:46:37 +01:00
|
|
|
uint32_t Type;
|
2017-08-01 02:33:58 +02:00
|
|
|
uint32_t Flags;
|
|
|
|
uint64_t Offset;
|
|
|
|
uint64_t VAddr;
|
2018-12-12 23:46:37 +01:00
|
|
|
uint64_t PAddr;
|
|
|
|
uint64_t FileSize;
|
|
|
|
uint64_t MemSize;
|
|
|
|
uint64_t Align;
|
2017-08-01 02:33:58 +02:00
|
|
|
|
2018-12-12 23:46:37 +01:00
|
|
|
uint32_t Index;
|
2017-08-26 03:32:20 +02:00
|
|
|
uint64_t OriginalOffset;
|
2017-09-19 23:37:35 +02:00
|
|
|
Segment *ParentSegment = nullptr;
|
2019-03-25 17:36:26 +01:00
|
|
|
ArrayRef<uint8_t> Contents;
|
|
|
|
|
|
|
|
explicit Segment(ArrayRef<uint8_t> Data) : Contents(Data) {}
|
|
|
|
Segment() {}
|
2017-11-01 22:16:06 +01:00
|
|
|
|
2017-08-01 02:33:58 +02:00
|
|
|
const SectionBase *firstSection() const {
|
|
|
|
if (!Sections.empty())
|
|
|
|
return *Sections.begin();
|
|
|
|
return nullptr;
|
|
|
|
}
|
2017-11-01 22:16:06 +01:00
|
|
|
|
2017-10-10 20:47:09 +02:00
|
|
|
void removeSection(const SectionBase *Sec) { Sections.erase(Sec); }
|
|
|
|
void addSection(const SectionBase *Sec) { Sections.insert(Sec); }
|
2019-03-25 17:36:26 +01:00
|
|
|
|
|
|
|
ArrayRef<uint8_t> getContents() const { return Contents; }
|
2017-08-01 02:33:58 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
class Section : public SectionBase {
|
2018-01-25 23:46:17 +01:00
|
|
|
MAKE_SEC_WRITER_FRIEND
|
|
|
|
|
2017-11-01 22:16:06 +01:00
|
|
|
ArrayRef<uint8_t> Contents;
|
2018-04-20 22:46:04 +02:00
|
|
|
SectionBase *LinkSection = nullptr;
|
2017-08-01 02:33:58 +02:00
|
|
|
|
|
|
|
public:
|
2018-03-21 20:53:44 +01:00
|
|
|
explicit Section(ArrayRef<uint8_t> Data) : Contents(Data) {}
|
2017-11-01 22:16:06 +01:00
|
|
|
|
2018-01-25 23:46:17 +01:00
|
|
|
void accept(SectionVisitor &Visitor) const override;
|
[llvm-objcopy][ELF] Implement a mutable section visitor that updates size-related fields (Size, EntrySize, Align) before layout.
Summary:
Fix EntrySize, Size, and Align before doing layout calculation.
As a side cleanup, this removes a dependence on sizeof(Elf_Sym) within BinaryReader, so we can untemplatize that.
This unblocks a cleaner implementation of handling the -O<format> flag. See D53667 for a previous attempt. Actual implementation of the -O<format> flag will come in an upcoming commit, this is largely a NFC (although not _totally_ one, because alignment on binary input was actually wrong before).
Reviewers: jakehehrlich, jhenderson, alexshap, espindola
Reviewed By: jhenderson
Subscribers: emaste, arichardson, llvm-commits
Differential Revision: https://reviews.llvm.org/D56211
llvm-svn: 350336
2019-01-03 18:45:30 +01:00
|
|
|
void accept(MutableSectionVisitor &Visitor) override;
|
2019-04-18 11:13:30 +02:00
|
|
|
Error removeSectionReferences(bool AllowBrokenLinks,
|
[llvm-objcopy] Make removeSectionReferences batched
Summary:
Removing a large number of sections from a file with a lot of symbols can have abysmal (i.e. O(n^2)) performance, e.g. when running `--only-section` to extract one section out of a large file.
This comes from iterating over all symbols in the symbol table each time we remove a section, to remove references to the section we just removed.
Instead, do just one pass of symbol removal by passing a hash set of all the sections we'd like to remove references to.
This fixes a regression when running llvm-objcopy -j <one section> on an object file with many sections and symbols -- on my machine, running `objcopy -j .keep_me huge-input.o /tmp/foo.o` takes .3s with GNU objcopy, 1.3s with an updated llvm-objcopy, and 7+ minutes with llvm-objcopy prior to this patch.
Reviewers: MaskRay, jhenderson, jakehehrlich, alexshap, espindola
Reviewed By: MaskRay, jhenderson
Subscribers: echristo, emaste, arichardson, mgrang, jdoerfert, llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D58296
llvm-svn: 354597
2019-02-21 17:45:42 +01:00
|
|
|
function_ref<bool(const SectionBase *)> ToRemove) override;
|
2018-04-20 22:46:04 +02:00
|
|
|
void initialize(SectionTableRef SecTable) override;
|
|
|
|
void finalize() override;
|
2017-08-01 02:33:58 +02:00
|
|
|
};
|
|
|
|
|
2017-12-19 01:47:30 +01:00
|
|
|
class OwnedDataSection : public SectionBase {
|
2018-01-25 23:46:17 +01:00
|
|
|
MAKE_SEC_WRITER_FRIEND
|
|
|
|
|
2017-12-19 01:47:30 +01:00
|
|
|
std::vector<uint8_t> Data;
|
|
|
|
|
|
|
|
public:
|
|
|
|
OwnedDataSection(StringRef SecName, ArrayRef<uint8_t> Data)
|
|
|
|
: Data(std::begin(Data), std::end(Data)) {
|
2018-09-07 10:10:22 +02:00
|
|
|
Name = SecName.str();
|
2017-12-19 01:47:30 +01:00
|
|
|
Type = ELF::SHT_PROGBITS;
|
|
|
|
Size = Data.size();
|
2018-01-25 23:46:17 +01:00
|
|
|
OriginalOffset = std::numeric_limits<uint64_t>::max();
|
2017-12-19 01:47:30 +01:00
|
|
|
}
|
2018-01-25 23:46:17 +01:00
|
|
|
|
|
|
|
void accept(SectionVisitor &Sec) const override;
|
[llvm-objcopy][ELF] Implement a mutable section visitor that updates size-related fields (Size, EntrySize, Align) before layout.
Summary:
Fix EntrySize, Size, and Align before doing layout calculation.
As a side cleanup, this removes a dependence on sizeof(Elf_Sym) within BinaryReader, so we can untemplatize that.
This unblocks a cleaner implementation of handling the -O<format> flag. See D53667 for a previous attempt. Actual implementation of the -O<format> flag will come in an upcoming commit, this is largely a NFC (although not _totally_ one, because alignment on binary input was actually wrong before).
Reviewers: jakehehrlich, jhenderson, alexshap, espindola
Reviewed By: jhenderson
Subscribers: emaste, arichardson, llvm-commits
Differential Revision: https://reviews.llvm.org/D56211
llvm-svn: 350336
2019-01-03 18:45:30 +01:00
|
|
|
void accept(MutableSectionVisitor &Visitor) override;
|
2017-12-19 01:47:30 +01:00
|
|
|
};
|
|
|
|
|
2018-09-07 10:10:22 +02:00
|
|
|
class CompressedSection : public SectionBase {
|
|
|
|
MAKE_SEC_WRITER_FRIEND
|
|
|
|
|
|
|
|
DebugCompressionType CompressionType;
|
|
|
|
uint64_t DecompressedSize;
|
|
|
|
uint64_t DecompressedAlign;
|
|
|
|
SmallVector<char, 128> CompressedData;
|
|
|
|
|
|
|
|
public:
|
|
|
|
CompressedSection(const SectionBase &Sec,
|
|
|
|
DebugCompressionType CompressionType);
|
2018-10-01 12:29:41 +02:00
|
|
|
CompressedSection(ArrayRef<uint8_t> CompressedData, uint64_t DecompressedSize,
|
|
|
|
uint64_t DecompressedAlign);
|
|
|
|
|
|
|
|
uint64_t getDecompressedSize() const { return DecompressedSize; }
|
|
|
|
uint64_t getDecompressedAlign() const { return DecompressedAlign; }
|
|
|
|
|
|
|
|
void accept(SectionVisitor &Visitor) const override;
|
[llvm-objcopy][ELF] Implement a mutable section visitor that updates size-related fields (Size, EntrySize, Align) before layout.
Summary:
Fix EntrySize, Size, and Align before doing layout calculation.
As a side cleanup, this removes a dependence on sizeof(Elf_Sym) within BinaryReader, so we can untemplatize that.
This unblocks a cleaner implementation of handling the -O<format> flag. See D53667 for a previous attempt. Actual implementation of the -O<format> flag will come in an upcoming commit, this is largely a NFC (although not _totally_ one, because alignment on binary input was actually wrong before).
Reviewers: jakehehrlich, jhenderson, alexshap, espindola
Reviewed By: jhenderson
Subscribers: emaste, arichardson, llvm-commits
Differential Revision: https://reviews.llvm.org/D56211
llvm-svn: 350336
2019-01-03 18:45:30 +01:00
|
|
|
void accept(MutableSectionVisitor &Visitor) override;
|
2018-10-01 12:29:41 +02:00
|
|
|
|
|
|
|
static bool classof(const SectionBase *S) {
|
|
|
|
return (S->Flags & ELF::SHF_COMPRESSED) ||
|
|
|
|
(StringRef(S->Name).startswith(".zdebug"));
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
class DecompressedSection : public SectionBase {
|
|
|
|
MAKE_SEC_WRITER_FRIEND
|
|
|
|
|
|
|
|
public:
|
|
|
|
explicit DecompressedSection(const CompressedSection &Sec)
|
|
|
|
: SectionBase(Sec) {
|
|
|
|
Size = Sec.getDecompressedSize();
|
|
|
|
Align = Sec.getDecompressedAlign();
|
|
|
|
Flags = (Flags & ~ELF::SHF_COMPRESSED);
|
|
|
|
if (StringRef(Name).startswith(".zdebug"))
|
|
|
|
Name = "." + Name.substr(2);
|
|
|
|
}
|
|
|
|
|
2018-09-07 10:10:22 +02:00
|
|
|
void accept(SectionVisitor &Visitor) const override;
|
[llvm-objcopy][ELF] Implement a mutable section visitor that updates size-related fields (Size, EntrySize, Align) before layout.
Summary:
Fix EntrySize, Size, and Align before doing layout calculation.
As a side cleanup, this removes a dependence on sizeof(Elf_Sym) within BinaryReader, so we can untemplatize that.
This unblocks a cleaner implementation of handling the -O<format> flag. See D53667 for a previous attempt. Actual implementation of the -O<format> flag will come in an upcoming commit, this is largely a NFC (although not _totally_ one, because alignment on binary input was actually wrong before).
Reviewers: jakehehrlich, jhenderson, alexshap, espindola
Reviewed By: jhenderson
Subscribers: emaste, arichardson, llvm-commits
Differential Revision: https://reviews.llvm.org/D56211
llvm-svn: 350336
2019-01-03 18:45:30 +01:00
|
|
|
void accept(MutableSectionVisitor &Visitor) override;
|
2018-09-07 10:10:22 +02:00
|
|
|
};
|
|
|
|
|
2017-10-10 23:28:22 +02:00
|
|
|
// There are two types of string tables that can exist, dynamic and not dynamic.
|
|
|
|
// In the dynamic case the string table is allocated. Changing a dynamic string
|
|
|
|
// table would mean altering virtual addresses and thus the memory image. So
|
|
|
|
// dynamic string tables should not have an interface to modify them or
|
|
|
|
// reconstruct them. This type lets us reconstruct a string table. To avoid
|
|
|
|
// this class being used for dynamic string tables (which has happened) the
|
|
|
|
// classof method checks that the particular instance is not allocated. This
|
|
|
|
// then agrees with the makeSection method used to construct most sections.
|
2017-08-01 02:33:58 +02:00
|
|
|
class StringTableSection : public SectionBase {
|
2018-01-25 23:46:17 +01:00
|
|
|
MAKE_SEC_WRITER_FRIEND
|
|
|
|
|
2017-11-01 22:16:06 +01:00
|
|
|
StringTableBuilder StrTabBuilder;
|
2017-08-01 02:33:58 +02:00
|
|
|
|
|
|
|
public:
|
2017-11-01 22:16:06 +01:00
|
|
|
StringTableSection() : StrTabBuilder(StringTableBuilder::ELF) {
|
|
|
|
Type = ELF::SHT_STRTAB;
|
2017-08-01 02:33:58 +02:00
|
|
|
}
|
|
|
|
|
2017-11-01 22:16:06 +01:00
|
|
|
void addString(StringRef Name);
|
|
|
|
uint32_t findIndex(StringRef Name) const;
|
2019-03-18 15:27:41 +01:00
|
|
|
void prepareForLayout();
|
2018-01-25 23:46:17 +01:00
|
|
|
void accept(SectionVisitor &Visitor) const override;
|
[llvm-objcopy][ELF] Implement a mutable section visitor that updates size-related fields (Size, EntrySize, Align) before layout.
Summary:
Fix EntrySize, Size, and Align before doing layout calculation.
As a side cleanup, this removes a dependence on sizeof(Elf_Sym) within BinaryReader, so we can untemplatize that.
This unblocks a cleaner implementation of handling the -O<format> flag. See D53667 for a previous attempt. Actual implementation of the -O<format> flag will come in an upcoming commit, this is largely a NFC (although not _totally_ one, because alignment on binary input was actually wrong before).
Reviewers: jakehehrlich, jhenderson, alexshap, espindola
Reviewed By: jhenderson
Subscribers: emaste, arichardson, llvm-commits
Differential Revision: https://reviews.llvm.org/D56211
llvm-svn: 350336
2019-01-03 18:45:30 +01:00
|
|
|
void accept(MutableSectionVisitor &Visitor) override;
|
2017-11-01 22:16:06 +01:00
|
|
|
|
2017-08-01 02:33:58 +02:00
|
|
|
static bool classof(const SectionBase *S) {
|
2017-11-01 22:16:06 +01:00
|
|
|
if (S->Flags & ELF::SHF_ALLOC)
|
2017-10-10 23:28:22 +02:00
|
|
|
return false;
|
2017-11-01 22:16:06 +01:00
|
|
|
return S->Type == ELF::SHT_STRTAB;
|
2017-08-01 02:33:58 +02:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2017-09-08 01:02:50 +02:00
|
|
|
// Symbols have a st_shndx field that normally stores an index but occasionally
|
|
|
|
// stores a different special value. This enum keeps track of what the st_shndx
|
|
|
|
// field means. Most of the values are just copies of the special SHN_* values.
|
|
|
|
// SYMBOL_SIMPLE_INDEX means that the st_shndx is just an index of a section.
|
|
|
|
enum SymbolShndxType {
|
|
|
|
SYMBOL_SIMPLE_INDEX = 0,
|
2017-11-01 22:16:06 +01:00
|
|
|
SYMBOL_ABS = ELF::SHN_ABS,
|
|
|
|
SYMBOL_COMMON = ELF::SHN_COMMON,
|
|
|
|
SYMBOL_HEXAGON_SCOMMON = ELF::SHN_HEXAGON_SCOMMON,
|
|
|
|
SYMBOL_HEXAGON_SCOMMON_2 = ELF::SHN_HEXAGON_SCOMMON_2,
|
|
|
|
SYMBOL_HEXAGON_SCOMMON_4 = ELF::SHN_HEXAGON_SCOMMON_4,
|
|
|
|
SYMBOL_HEXAGON_SCOMMON_8 = ELF::SHN_HEXAGON_SCOMMON_8,
|
2018-07-16 21:48:52 +02:00
|
|
|
SYMBOL_XINDEX = ELF::SHN_XINDEX,
|
2017-09-08 01:02:50 +02:00
|
|
|
};
|
|
|
|
|
2017-08-29 04:12:03 +02:00
|
|
|
struct Symbol {
|
|
|
|
uint8_t Binding;
|
2017-09-27 02:44:00 +02:00
|
|
|
SectionBase *DefinedIn = nullptr;
|
2017-09-08 01:02:50 +02:00
|
|
|
SymbolShndxType ShndxType;
|
2017-08-29 04:12:03 +02:00
|
|
|
uint32_t Index;
|
2018-08-09 19:49:04 +02:00
|
|
|
std::string Name;
|
2017-08-29 04:12:03 +02:00
|
|
|
uint32_t NameIndex;
|
|
|
|
uint64_t Size;
|
|
|
|
uint8_t Type;
|
|
|
|
uint64_t Value;
|
2018-01-03 00:01:24 +01:00
|
|
|
uint8_t Visibility;
|
2018-05-25 13:01:25 +02:00
|
|
|
bool Referenced = false;
|
2017-09-08 01:02:50 +02:00
|
|
|
|
|
|
|
uint16_t getShndx() const;
|
[llvm-objcopy] Don't apply --localize flags to common symbols
Summary:
--localize-symbol and --localize-hidden will currently localize common symbols. GNU objcopy will not localize these symbols even when explicitly requested, which seems reasonable; common symbols should always be global so they can be merged during linking.
See PR39461
Reviewers: jakehehrlich, jhenderson, alexshap, MaskRay, espindola
Reviewed By: jakehehrlich, jhenderson, alexshap, MaskRay
Subscribers: emaste, arichardson, alexshap, MaskRay, llvm-commits
Differential Revision: https://reviews.llvm.org/D53782
llvm-svn: 345856
2018-11-01 18:26:36 +01:00
|
|
|
bool isCommon() const;
|
2017-08-29 04:12:03 +02:00
|
|
|
};
|
|
|
|
|
2018-07-16 21:48:52 +02:00
|
|
|
class SectionIndexSection : public SectionBase {
|
|
|
|
MAKE_SEC_WRITER_FRIEND
|
|
|
|
|
|
|
|
private:
|
|
|
|
std::vector<uint32_t> Indexes;
|
|
|
|
SymbolTableSection *Symbols = nullptr;
|
|
|
|
|
|
|
|
public:
|
|
|
|
virtual ~SectionIndexSection() {}
|
|
|
|
void addIndex(uint32_t Index) {
|
2019-04-12 13:59:30 +02:00
|
|
|
assert(Size > 0);
|
|
|
|
Indexes.push_back(Index);
|
2018-07-16 21:48:52 +02:00
|
|
|
}
|
2019-04-12 13:59:30 +02:00
|
|
|
|
|
|
|
void reserve(size_t NumSymbols) {
|
|
|
|
Indexes.reserve(NumSymbols);
|
|
|
|
Size = NumSymbols * 4;
|
|
|
|
}
|
2018-07-16 21:48:52 +02:00
|
|
|
void setSymTab(SymbolTableSection *SymTab) { Symbols = SymTab; }
|
|
|
|
void initialize(SectionTableRef SecTable) override;
|
|
|
|
void finalize() override;
|
|
|
|
void accept(SectionVisitor &Visitor) const override;
|
[llvm-objcopy][ELF] Implement a mutable section visitor that updates size-related fields (Size, EntrySize, Align) before layout.
Summary:
Fix EntrySize, Size, and Align before doing layout calculation.
As a side cleanup, this removes a dependence on sizeof(Elf_Sym) within BinaryReader, so we can untemplatize that.
This unblocks a cleaner implementation of handling the -O<format> flag. See D53667 for a previous attempt. Actual implementation of the -O<format> flag will come in an upcoming commit, this is largely a NFC (although not _totally_ one, because alignment on binary input was actually wrong before).
Reviewers: jakehehrlich, jhenderson, alexshap, espindola
Reviewed By: jhenderson
Subscribers: emaste, arichardson, llvm-commits
Differential Revision: https://reviews.llvm.org/D56211
llvm-svn: 350336
2019-01-03 18:45:30 +01:00
|
|
|
void accept(MutableSectionVisitor &Visitor) override;
|
2018-07-16 21:48:52 +02:00
|
|
|
|
|
|
|
SectionIndexSection() {
|
|
|
|
Name = ".symtab_shndx";
|
|
|
|
Align = 4;
|
|
|
|
EntrySize = 4;
|
|
|
|
Type = ELF::SHT_SYMTAB_SHNDX;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2017-08-29 04:12:03 +02:00
|
|
|
class SymbolTableSection : public SectionBase {
|
2018-01-25 23:46:17 +01:00
|
|
|
MAKE_SEC_WRITER_FRIEND
|
|
|
|
|
2018-02-24 01:41:01 +01:00
|
|
|
void setStrTab(StringTableSection *StrTab) { SymbolNames = StrTab; }
|
2018-03-21 20:53:44 +01:00
|
|
|
void assignIndices();
|
2018-02-24 01:41:01 +01:00
|
|
|
|
2017-08-29 04:12:03 +02:00
|
|
|
protected:
|
|
|
|
std::vector<std::unique_ptr<Symbol>> Symbols;
|
2017-09-27 02:44:00 +02:00
|
|
|
StringTableSection *SymbolNames = nullptr;
|
2018-07-16 21:48:52 +02:00
|
|
|
SectionIndexSection *SectionIndexTable = nullptr;
|
2017-08-29 04:12:03 +02:00
|
|
|
|
2017-11-01 22:16:06 +01:00
|
|
|
using SymPtr = std::unique_ptr<Symbol>;
|
2017-10-10 20:47:09 +02:00
|
|
|
|
2017-08-29 04:12:03 +02:00
|
|
|
public:
|
[llvm-objcopy] Add support for -I binary -B <arch>.
Summary:
The -I (--input-target) and -B (--binary-architecture) flags exist but are currently silently ignored. This adds support for -I binary for architectures i386, x86-64 (and alias i386:x86-64), arm, aarch64, sparc, and ppc (powerpc:common64). This is largely based on D41687.
This is done by implementing an additional subclass of Reader, BinaryReader, which works by interpreting the input file as contents for .data field, sets up a synthetic header, and adds additional sections/symbols (e.g. _binary__tmp_data_txt_start).
Reviewers: jakehehrlich, alexshap, jhenderson, javed.absar
Reviewed By: jhenderson
Subscribers: jyknight, nemanjai, kbarton, fedor.sergeev, jrtc27, kristof.beyls, paulsemel, llvm-commits
Differential Revision: https://reviews.llvm.org/D50343
llvm-svn: 340070
2018-08-17 20:51:11 +02:00
|
|
|
SymbolTableSection() { Type = ELF::SHT_SYMTAB; }
|
|
|
|
|
|
|
|
void addSymbol(Twine Name, uint8_t Bind, uint8_t Type, SectionBase *DefinedIn,
|
|
|
|
uint64_t Value, uint8_t Visibility, uint16_t Shndx,
|
2019-05-08 09:31:05 +02:00
|
|
|
uint64_t SymbolSize);
|
2018-07-16 21:48:52 +02:00
|
|
|
void prepareForLayout();
|
2018-06-01 18:19:46 +02:00
|
|
|
// An 'empty' symbol table still contains a null symbol.
|
|
|
|
bool empty() const { return Symbols.size() == 1; }
|
2018-07-16 21:48:52 +02:00
|
|
|
void setShndxTable(SectionIndexSection *ShndxTable) {
|
|
|
|
SectionIndexTable = ShndxTable;
|
|
|
|
}
|
|
|
|
const SectionIndexSection *getShndxTable() const { return SectionIndexTable; }
|
2019-04-12 13:59:30 +02:00
|
|
|
void fillShndxTable();
|
2017-11-30 21:14:53 +01:00
|
|
|
const SectionBase *getStrTab() const { return SymbolNames; }
|
2017-08-29 04:12:03 +02:00
|
|
|
const Symbol *getSymbolByIndex(uint32_t Index) const;
|
2018-05-25 13:01:25 +02:00
|
|
|
Symbol *getSymbolByIndex(uint32_t Index);
|
2018-04-26 20:28:17 +02:00
|
|
|
void updateSymbols(function_ref<void(Symbol &)> Callable);
|
|
|
|
|
2019-04-18 11:13:30 +02:00
|
|
|
Error removeSectionReferences(bool AllowBrokenLinks,
|
[llvm-objcopy] Make removeSectionReferences batched
Summary:
Removing a large number of sections from a file with a lot of symbols can have abysmal (i.e. O(n^2)) performance, e.g. when running `--only-section` to extract one section out of a large file.
This comes from iterating over all symbols in the symbol table each time we remove a section, to remove references to the section we just removed.
Instead, do just one pass of symbol removal by passing a hash set of all the sections we'd like to remove references to.
This fixes a regression when running llvm-objcopy -j <one section> on an object file with many sections and symbols -- on my machine, running `objcopy -j .keep_me huge-input.o /tmp/foo.o` takes .3s with GNU objcopy, 1.3s with an updated llvm-objcopy, and 7+ minutes with llvm-objcopy prior to this patch.
Reviewers: MaskRay, jhenderson, jakehehrlich, alexshap, espindola
Reviewed By: MaskRay, jhenderson
Subscribers: echristo, emaste, arichardson, mgrang, jdoerfert, llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D58296
llvm-svn: 354597
2019-02-21 17:45:42 +01:00
|
|
|
function_ref<bool(const SectionBase *)> ToRemove) override;
|
2017-09-25 22:37:28 +02:00
|
|
|
void initialize(SectionTableRef SecTable) override;
|
2017-08-29 04:12:03 +02:00
|
|
|
void finalize() override;
|
2018-01-25 23:46:17 +01:00
|
|
|
void accept(SectionVisitor &Visitor) const override;
|
[llvm-objcopy][ELF] Implement a mutable section visitor that updates size-related fields (Size, EntrySize, Align) before layout.
Summary:
Fix EntrySize, Size, and Align before doing layout calculation.
As a side cleanup, this removes a dependence on sizeof(Elf_Sym) within BinaryReader, so we can untemplatize that.
This unblocks a cleaner implementation of handling the -O<format> flag. See D53667 for a previous attempt. Actual implementation of the -O<format> flag will come in an upcoming commit, this is largely a NFC (although not _totally_ one, because alignment on binary input was actually wrong before).
Reviewers: jakehehrlich, jhenderson, alexshap, espindola
Reviewed By: jhenderson
Subscribers: emaste, arichardson, llvm-commits
Differential Revision: https://reviews.llvm.org/D56211
llvm-svn: 350336
2019-01-03 18:45:30 +01:00
|
|
|
void accept(MutableSectionVisitor &Visitor) override;
|
2019-02-01 16:20:36 +01:00
|
|
|
Error removeSymbols(function_ref<bool(const Symbol &)> ToRemove) override;
|
2019-03-20 14:57:47 +01:00
|
|
|
void replaceSectionReferences(
|
|
|
|
const DenseMap<SectionBase *, SectionBase *> &FromTo) override;
|
2017-11-01 22:16:06 +01:00
|
|
|
|
2017-08-29 04:12:03 +02:00
|
|
|
static bool classof(const SectionBase *S) {
|
2017-11-01 22:16:06 +01:00
|
|
|
return S->Type == ELF::SHT_SYMTAB;
|
2017-08-29 04:12:03 +02:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2017-09-07 01:41:02 +02:00
|
|
|
struct Relocation {
|
2018-05-25 13:01:25 +02:00
|
|
|
Symbol *RelocSymbol = nullptr;
|
2017-09-07 01:41:02 +02:00
|
|
|
uint64_t Offset;
|
|
|
|
uint64_t Addend;
|
|
|
|
uint32_t Type;
|
|
|
|
};
|
|
|
|
|
2017-10-10 20:47:09 +02:00
|
|
|
// All relocation sections denote relocations to apply to another section.
|
|
|
|
// However, some relocation sections use a dynamic symbol table and others use
|
|
|
|
// a regular symbol table. Because the types of the two symbol tables differ in
|
|
|
|
// our system (because they should behave differently) we can't uniformly
|
|
|
|
// represent all relocations with the same base class if we expose an interface
|
|
|
|
// that mentions the symbol table type. So we split the two base types into two
|
|
|
|
// different classes, one which handles the section the relocation is applied to
|
|
|
|
// and another which handles the symbol table type. The symbol table type is
|
|
|
|
// taken as a type parameter to the class (see RelocSectionWithSymtabBase).
|
|
|
|
class RelocationSectionBase : public SectionBase {
|
|
|
|
protected:
|
|
|
|
SectionBase *SecToApplyRel = nullptr;
|
|
|
|
|
|
|
|
public:
|
|
|
|
const SectionBase *getSection() const { return SecToApplyRel; }
|
|
|
|
void setSection(SectionBase *Sec) { SecToApplyRel = Sec; }
|
|
|
|
|
|
|
|
static bool classof(const SectionBase *S) {
|
2017-11-01 22:16:06 +01:00
|
|
|
return S->Type == ELF::SHT_REL || S->Type == ELF::SHT_RELA;
|
2017-10-10 20:47:09 +02:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
// Takes the symbol table type to use as a parameter so that we can deduplicate
|
|
|
|
// that code between the two symbol table types.
|
|
|
|
template <class SymTabType>
|
|
|
|
class RelocSectionWithSymtabBase : public RelocationSectionBase {
|
2018-02-24 01:41:01 +01:00
|
|
|
void setSymTab(SymTabType *SymTab) { Symbols = SymTab; }
|
2017-10-10 20:47:09 +02:00
|
|
|
|
|
|
|
protected:
|
2017-11-01 22:16:06 +01:00
|
|
|
RelocSectionWithSymtabBase() = default;
|
2017-09-26 20:02:25 +02:00
|
|
|
|
2019-02-27 12:18:27 +01:00
|
|
|
SymTabType *Symbols = nullptr;
|
|
|
|
|
2017-09-26 20:02:25 +02:00
|
|
|
public:
|
|
|
|
void initialize(SectionTableRef SecTable) override;
|
|
|
|
void finalize() override;
|
|
|
|
};
|
|
|
|
|
2017-10-10 20:47:09 +02:00
|
|
|
class RelocationSection
|
|
|
|
: public RelocSectionWithSymtabBase<SymbolTableSection> {
|
2018-01-25 23:46:17 +01:00
|
|
|
MAKE_SEC_WRITER_FRIEND
|
2018-01-25 22:03:38 +01:00
|
|
|
|
2017-09-07 01:41:02 +02:00
|
|
|
std::vector<Relocation> Relocations;
|
|
|
|
|
|
|
|
public:
|
|
|
|
void addRelocation(Relocation Rel) { Relocations.push_back(Rel); }
|
2018-01-25 23:46:17 +01:00
|
|
|
void accept(SectionVisitor &Visitor) const override;
|
[llvm-objcopy][ELF] Implement a mutable section visitor that updates size-related fields (Size, EntrySize, Align) before layout.
Summary:
Fix EntrySize, Size, and Align before doing layout calculation.
As a side cleanup, this removes a dependence on sizeof(Elf_Sym) within BinaryReader, so we can untemplatize that.
This unblocks a cleaner implementation of handling the -O<format> flag. See D53667 for a previous attempt. Actual implementation of the -O<format> flag will come in an upcoming commit, this is largely a NFC (although not _totally_ one, because alignment on binary input was actually wrong before).
Reviewers: jakehehrlich, jhenderson, alexshap, espindola
Reviewed By: jhenderson
Subscribers: emaste, arichardson, llvm-commits
Differential Revision: https://reviews.llvm.org/D56211
llvm-svn: 350336
2019-01-03 18:45:30 +01:00
|
|
|
void accept(MutableSectionVisitor &Visitor) override;
|
2019-04-18 11:13:30 +02:00
|
|
|
Error removeSectionReferences(bool AllowBrokenLinks,
|
2019-02-27 12:18:27 +01:00
|
|
|
function_ref<bool(const SectionBase *)> ToRemove) override;
|
2019-02-01 16:20:36 +01:00
|
|
|
Error removeSymbols(function_ref<bool(const Symbol &)> ToRemove) override;
|
2018-05-25 13:01:25 +02:00
|
|
|
void markSymbols() override;
|
2019-03-11 12:01:24 +01:00
|
|
|
void replaceSectionReferences(
|
|
|
|
const DenseMap<SectionBase *, SectionBase *> &FromTo) override;
|
2017-09-26 20:02:25 +02:00
|
|
|
|
2017-09-07 01:41:02 +02:00
|
|
|
static bool classof(const SectionBase *S) {
|
2017-11-01 22:16:06 +01:00
|
|
|
if (S->Flags & ELF::SHF_ALLOC)
|
2017-09-26 20:02:25 +02:00
|
|
|
return false;
|
2017-11-01 22:16:06 +01:00
|
|
|
return S->Type == ELF::SHT_REL || S->Type == ELF::SHT_RELA;
|
2017-09-07 01:41:02 +02:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2018-03-21 20:53:44 +01:00
|
|
|
// TODO: The way stripping and groups interact is complicated
|
|
|
|
// and still needs to be worked on.
|
|
|
|
|
|
|
|
class GroupSection : public SectionBase {
|
|
|
|
MAKE_SEC_WRITER_FRIEND
|
|
|
|
const SymbolTableSection *SymTab = nullptr;
|
2018-05-25 13:01:25 +02:00
|
|
|
Symbol *Sym = nullptr;
|
2018-03-21 20:53:44 +01:00
|
|
|
ELF::Elf32_Word FlagWord;
|
|
|
|
SmallVector<SectionBase *, 3> GroupMembers;
|
2018-03-20 19:20:42 +01:00
|
|
|
|
|
|
|
public:
|
2018-03-21 20:53:44 +01:00
|
|
|
// TODO: Contents is present in several classes of the hierarchy.
|
|
|
|
// This needs to be refactored to avoid duplication.
|
|
|
|
ArrayRef<uint8_t> Contents;
|
|
|
|
|
|
|
|
explicit GroupSection(ArrayRef<uint8_t> Data) : Contents(Data) {}
|
|
|
|
|
|
|
|
void setSymTab(const SymbolTableSection *SymTabSec) { SymTab = SymTabSec; }
|
2018-05-25 13:01:25 +02:00
|
|
|
void setSymbol(Symbol *S) { Sym = S; }
|
2018-03-21 20:53:44 +01:00
|
|
|
void setFlagWord(ELF::Elf32_Word W) { FlagWord = W; }
|
|
|
|
void addMember(SectionBase *Sec) { GroupMembers.push_back(Sec); }
|
2018-03-20 20:46:00 +01:00
|
|
|
|
2018-03-21 20:53:44 +01:00
|
|
|
void accept(SectionVisitor &) const override;
|
[llvm-objcopy][ELF] Implement a mutable section visitor that updates size-related fields (Size, EntrySize, Align) before layout.
Summary:
Fix EntrySize, Size, and Align before doing layout calculation.
As a side cleanup, this removes a dependence on sizeof(Elf_Sym) within BinaryReader, so we can untemplatize that.
This unblocks a cleaner implementation of handling the -O<format> flag. See D53667 for a previous attempt. Actual implementation of the -O<format> flag will come in an upcoming commit, this is largely a NFC (although not _totally_ one, because alignment on binary input was actually wrong before).
Reviewers: jakehehrlich, jhenderson, alexshap, espindola
Reviewed By: jhenderson
Subscribers: emaste, arichardson, llvm-commits
Differential Revision: https://reviews.llvm.org/D56211
llvm-svn: 350336
2019-01-03 18:45:30 +01:00
|
|
|
void accept(MutableSectionVisitor &Visitor) override;
|
2018-03-21 20:53:44 +01:00
|
|
|
void finalize() override;
|
2019-02-01 16:20:36 +01:00
|
|
|
Error removeSymbols(function_ref<bool(const Symbol &)> ToRemove) override;
|
2018-05-25 13:01:25 +02:00
|
|
|
void markSymbols() override;
|
2019-03-24 15:41:45 +01:00
|
|
|
void replaceSectionReferences(
|
|
|
|
const DenseMap<SectionBase *, SectionBase *> &FromTo) override;
|
2018-03-21 20:53:44 +01:00
|
|
|
|
|
|
|
static bool classof(const SectionBase *S) {
|
|
|
|
return S->Type == ELF::SHT_GROUP;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2018-04-20 22:46:04 +02:00
|
|
|
class DynamicSymbolTableSection : public Section {
|
2017-09-20 19:11:58 +02:00
|
|
|
public:
|
2018-04-20 22:46:04 +02:00
|
|
|
explicit DynamicSymbolTableSection(ArrayRef<uint8_t> Data) : Section(Data) {}
|
2017-11-01 22:16:06 +01:00
|
|
|
|
2017-09-20 19:11:58 +02:00
|
|
|
static bool classof(const SectionBase *S) {
|
2017-11-01 22:16:06 +01:00
|
|
|
return S->Type == ELF::SHT_DYNSYM;
|
2017-09-20 19:11:58 +02:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2018-04-20 22:46:04 +02:00
|
|
|
class DynamicSection : public Section {
|
2017-09-20 19:11:58 +02:00
|
|
|
public:
|
2018-04-20 22:46:04 +02:00
|
|
|
explicit DynamicSection(ArrayRef<uint8_t> Data) : Section(Data) {}
|
2017-11-01 22:16:06 +01:00
|
|
|
|
2017-09-20 19:11:58 +02:00
|
|
|
static bool classof(const SectionBase *S) {
|
2017-11-01 22:16:06 +01:00
|
|
|
return S->Type == ELF::SHT_DYNAMIC;
|
2017-09-20 19:11:58 +02:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2017-09-26 20:02:25 +02:00
|
|
|
class DynamicRelocationSection
|
2017-10-10 20:47:09 +02:00
|
|
|
: public RelocSectionWithSymtabBase<DynamicSymbolTableSection> {
|
2018-01-25 23:46:17 +01:00
|
|
|
MAKE_SEC_WRITER_FRIEND
|
|
|
|
|
2017-09-26 20:02:25 +02:00
|
|
|
private:
|
2017-11-01 22:16:06 +01:00
|
|
|
ArrayRef<uint8_t> Contents;
|
2017-09-26 20:02:25 +02:00
|
|
|
|
|
|
|
public:
|
2018-03-21 20:53:44 +01:00
|
|
|
explicit DynamicRelocationSection(ArrayRef<uint8_t> Data) : Contents(Data) {}
|
2019-04-30 13:02:09 +02:00
|
|
|
|
|
|
|
void accept(SectionVisitor &) const override;
|
|
|
|
void accept(MutableSectionVisitor &Visitor) override;
|
|
|
|
Error removeSectionReferences(
|
|
|
|
bool AllowBrokenLinks,
|
|
|
|
function_ref<bool(const SectionBase *)> ToRemove) override;
|
|
|
|
|
|
|
|
static bool classof(const SectionBase *S) {
|
|
|
|
if (!(S->Flags & ELF::SHF_ALLOC))
|
2017-09-26 20:02:25 +02:00
|
|
|
return false;
|
2017-11-01 22:16:06 +01:00
|
|
|
return S->Type == ELF::SHT_REL || S->Type == ELF::SHT_RELA;
|
2017-09-26 20:02:25 +02:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2018-01-25 23:46:17 +01:00
|
|
|
class GnuDebugLinkSection : public SectionBase {
|
|
|
|
MAKE_SEC_WRITER_FRIEND
|
|
|
|
|
2018-01-25 23:15:14 +01:00
|
|
|
private:
|
|
|
|
StringRef FileName;
|
|
|
|
uint32_t CRC32;
|
|
|
|
|
2019-05-14 12:59:04 +02:00
|
|
|
void init(StringRef File);
|
2018-01-25 23:15:14 +01:00
|
|
|
|
|
|
|
public:
|
|
|
|
// If we add this section from an external source we can use this ctor.
|
2019-05-14 12:59:04 +02:00
|
|
|
explicit GnuDebugLinkSection(StringRef File, uint32_t PrecomputedCRC);
|
2018-01-25 23:46:17 +01:00
|
|
|
void accept(SectionVisitor &Visitor) const override;
|
[llvm-objcopy][ELF] Implement a mutable section visitor that updates size-related fields (Size, EntrySize, Align) before layout.
Summary:
Fix EntrySize, Size, and Align before doing layout calculation.
As a side cleanup, this removes a dependence on sizeof(Elf_Sym) within BinaryReader, so we can untemplatize that.
This unblocks a cleaner implementation of handling the -O<format> flag. See D53667 for a previous attempt. Actual implementation of the -O<format> flag will come in an upcoming commit, this is largely a NFC (although not _totally_ one, because alignment on binary input was actually wrong before).
Reviewers: jakehehrlich, jhenderson, alexshap, espindola
Reviewed By: jhenderson
Subscribers: emaste, arichardson, llvm-commits
Differential Revision: https://reviews.llvm.org/D56211
llvm-svn: 350336
2019-01-03 18:45:30 +01:00
|
|
|
void accept(MutableSectionVisitor &Visitor) override;
|
2018-01-25 23:15:14 +01:00
|
|
|
};
|
|
|
|
|
2018-01-25 23:46:17 +01:00
|
|
|
class Reader {
|
|
|
|
public:
|
|
|
|
virtual ~Reader();
|
|
|
|
virtual std::unique_ptr<Object> create() const = 0;
|
|
|
|
};
|
|
|
|
|
|
|
|
using object::Binary;
|
|
|
|
using object::ELFFile;
|
|
|
|
using object::ELFObjectFile;
|
2018-03-21 20:53:44 +01:00
|
|
|
using object::OwningBinary;
|
2018-01-25 22:03:38 +01:00
|
|
|
|
[llvm-objcopy][ELF] Implement a mutable section visitor that updates size-related fields (Size, EntrySize, Align) before layout.
Summary:
Fix EntrySize, Size, and Align before doing layout calculation.
As a side cleanup, this removes a dependence on sizeof(Elf_Sym) within BinaryReader, so we can untemplatize that.
This unblocks a cleaner implementation of handling the -O<format> flag. See D53667 for a previous attempt. Actual implementation of the -O<format> flag will come in an upcoming commit, this is largely a NFC (although not _totally_ one, because alignment on binary input was actually wrong before).
Reviewers: jakehehrlich, jhenderson, alexshap, espindola
Reviewed By: jhenderson
Subscribers: emaste, arichardson, llvm-commits
Differential Revision: https://reviews.llvm.org/D56211
llvm-svn: 350336
2019-01-03 18:45:30 +01:00
|
|
|
class BinaryELFBuilder {
|
[llvm-objcopy] Add support for -I binary -B <arch>.
Summary:
The -I (--input-target) and -B (--binary-architecture) flags exist but are currently silently ignored. This adds support for -I binary for architectures i386, x86-64 (and alias i386:x86-64), arm, aarch64, sparc, and ppc (powerpc:common64). This is largely based on D41687.
This is done by implementing an additional subclass of Reader, BinaryReader, which works by interpreting the input file as contents for .data field, sets up a synthetic header, and adds additional sections/symbols (e.g. _binary__tmp_data_txt_start).
Reviewers: jakehehrlich, alexshap, jhenderson, javed.absar
Reviewed By: jhenderson
Subscribers: jyknight, nemanjai, kbarton, fedor.sergeev, jrtc27, kristof.beyls, paulsemel, llvm-commits
Differential Revision: https://reviews.llvm.org/D50343
llvm-svn: 340070
2018-08-17 20:51:11 +02:00
|
|
|
uint16_t EMachine;
|
|
|
|
MemoryBuffer *MemBuf;
|
|
|
|
std::unique_ptr<Object> Obj;
|
|
|
|
|
|
|
|
void initFileHeader();
|
|
|
|
void initHeaderSegment();
|
|
|
|
StringTableSection *addStrTab();
|
|
|
|
SymbolTableSection *addSymTab(StringTableSection *StrTab);
|
|
|
|
void addData(SymbolTableSection *SymTab);
|
|
|
|
void initSections();
|
|
|
|
|
|
|
|
public:
|
|
|
|
BinaryELFBuilder(uint16_t EM, MemoryBuffer *MB)
|
|
|
|
: EMachine(EM), MemBuf(MB), Obj(llvm::make_unique<Object>()) {}
|
|
|
|
|
|
|
|
std::unique_ptr<Object> build();
|
|
|
|
};
|
|
|
|
|
2018-01-25 23:46:17 +01:00
|
|
|
template <class ELFT> class ELFBuilder {
|
|
|
|
private:
|
2018-02-15 00:31:33 +01:00
|
|
|
using Elf_Addr = typename ELFT::Addr;
|
2017-11-01 22:16:06 +01:00
|
|
|
using Elf_Shdr = typename ELFT::Shdr;
|
2018-07-16 21:48:52 +02:00
|
|
|
using Elf_Word = typename ELFT::Word;
|
2017-08-01 02:33:58 +02:00
|
|
|
|
2018-01-25 23:46:17 +01:00
|
|
|
const ELFFile<ELFT> &ElfFile;
|
|
|
|
Object &Obj;
|
2017-08-04 23:09:26 +02:00
|
|
|
|
2018-02-15 00:31:33 +01:00
|
|
|
void setParentSegment(Segment &Child);
|
2018-01-25 23:46:17 +01:00
|
|
|
void readProgramHeaders();
|
2018-03-21 20:53:44 +01:00
|
|
|
void initGroupSection(GroupSection *GroupSec);
|
2018-01-25 23:46:17 +01:00
|
|
|
void initSymbolTable(SymbolTableSection *SymTab);
|
|
|
|
void readSectionHeaders();
|
|
|
|
SectionBase &makeSection(const Elf_Shdr &Shdr);
|
2017-11-01 22:16:06 +01:00
|
|
|
|
2018-01-25 22:03:38 +01:00
|
|
|
public:
|
2018-01-25 23:46:17 +01:00
|
|
|
ELFBuilder(const ELFObjectFile<ELFT> &ElfObj, Object &Obj)
|
|
|
|
: ElfFile(*ElfObj.getELFFile()), Obj(Obj) {}
|
2017-08-04 23:09:26 +02:00
|
|
|
|
2018-01-25 23:46:17 +01:00
|
|
|
void build();
|
2017-08-01 02:33:58 +02:00
|
|
|
};
|
|
|
|
|
[llvm-objcopy] Add support for -I binary -B <arch>.
Summary:
The -I (--input-target) and -B (--binary-architecture) flags exist but are currently silently ignored. This adds support for -I binary for architectures i386, x86-64 (and alias i386:x86-64), arm, aarch64, sparc, and ppc (powerpc:common64). This is largely based on D41687.
This is done by implementing an additional subclass of Reader, BinaryReader, which works by interpreting the input file as contents for .data field, sets up a synthetic header, and adds additional sections/symbols (e.g. _binary__tmp_data_txt_start).
Reviewers: jakehehrlich, alexshap, jhenderson, javed.absar
Reviewed By: jhenderson
Subscribers: jyknight, nemanjai, kbarton, fedor.sergeev, jrtc27, kristof.beyls, paulsemel, llvm-commits
Differential Revision: https://reviews.llvm.org/D50343
llvm-svn: 340070
2018-08-17 20:51:11 +02:00
|
|
|
class BinaryReader : public Reader {
|
|
|
|
const MachineInfo &MInfo;
|
|
|
|
MemoryBuffer *MemBuf;
|
|
|
|
|
|
|
|
public:
|
|
|
|
BinaryReader(const MachineInfo &MI, MemoryBuffer *MB)
|
|
|
|
: MInfo(MI), MemBuf(MB) {}
|
|
|
|
std::unique_ptr<Object> create() const override;
|
|
|
|
};
|
|
|
|
|
2018-01-25 23:46:17 +01:00
|
|
|
class ELFReader : public Reader {
|
2018-07-06 19:51:03 +02:00
|
|
|
Binary *Bin;
|
2017-11-01 22:16:06 +01:00
|
|
|
|
2018-01-25 22:03:38 +01:00
|
|
|
public:
|
2018-01-25 23:46:17 +01:00
|
|
|
std::unique_ptr<Object> create() const override;
|
2018-08-13 23:30:27 +02:00
|
|
|
explicit ELFReader(Binary *B) : Bin(B) {}
|
2018-01-25 22:03:38 +01:00
|
|
|
};
|
2018-01-25 21:24:17 +01:00
|
|
|
|
2018-01-25 23:46:17 +01:00
|
|
|
class Object {
|
2018-01-25 22:03:38 +01:00
|
|
|
private:
|
|
|
|
using SecPtr = std::unique_ptr<SectionBase>;
|
|
|
|
using SegPtr = std::unique_ptr<Segment>;
|
2018-01-25 21:24:17 +01:00
|
|
|
|
2018-01-25 23:46:17 +01:00
|
|
|
std::vector<SecPtr> Sections;
|
|
|
|
std::vector<SegPtr> Segments;
|
2019-03-25 17:36:26 +01:00
|
|
|
std::vector<SecPtr> RemovedSections;
|
2018-01-25 21:24:17 +01:00
|
|
|
|
2018-01-25 22:03:38 +01:00
|
|
|
public:
|
2018-01-25 23:46:17 +01:00
|
|
|
template <class T>
|
|
|
|
using Range = iterator_range<
|
|
|
|
pointee_iterator<typename std::vector<std::unique_ptr<T>>::iterator>>;
|
2018-01-25 21:24:17 +01:00
|
|
|
|
2018-01-25 23:46:17 +01:00
|
|
|
template <class T>
|
|
|
|
using ConstRange = iterator_range<pointee_iterator<
|
|
|
|
typename std::vector<std::unique_ptr<T>>::const_iterator>>;
|
|
|
|
|
2018-02-15 00:31:33 +01:00
|
|
|
// It is often the case that the ELF header and the program header table are
|
|
|
|
// not present in any segment. This could be a problem during file layout,
|
|
|
|
// because other segments may get assigned an offset where either of the
|
|
|
|
// two should reside, which will effectively corrupt the resulting binary.
|
|
|
|
// Other than that we use these segments to track program header offsets
|
|
|
|
// when they may not follow the ELF header.
|
|
|
|
Segment ElfHdrSegment;
|
|
|
|
Segment ProgramHdrSegment;
|
|
|
|
|
2018-12-20 11:51:42 +01:00
|
|
|
uint8_t OSABI;
|
|
|
|
uint8_t ABIVersion;
|
2018-01-25 23:46:17 +01:00
|
|
|
uint64_t Entry;
|
|
|
|
uint64_t SHOffset;
|
|
|
|
uint32_t Type;
|
|
|
|
uint32_t Machine;
|
|
|
|
uint32_t Version;
|
|
|
|
uint32_t Flags;
|
|
|
|
|
2019-04-02 16:11:13 +02:00
|
|
|
bool HadShdrs = true;
|
2018-01-25 23:46:17 +01:00
|
|
|
StringTableSection *SectionNames = nullptr;
|
|
|
|
SymbolTableSection *SymbolTable = nullptr;
|
2018-07-16 21:48:52 +02:00
|
|
|
SectionIndexSection *SectionIndexTable = nullptr;
|
2018-01-25 23:46:17 +01:00
|
|
|
|
|
|
|
void sortSections();
|
|
|
|
SectionTableRef sections() { return SectionTableRef(Sections); }
|
|
|
|
ConstRange<SectionBase> sections() const {
|
|
|
|
return make_pointee_range(Sections);
|
|
|
|
}
|
2019-02-25 15:12:41 +01:00
|
|
|
SectionBase *findSection(StringRef Name) {
|
|
|
|
auto SecIt =
|
|
|
|
find_if(Sections, [&](const SecPtr &Sec) { return Sec->Name == Name; });
|
|
|
|
return SecIt == Sections.end() ? nullptr : SecIt->get();
|
|
|
|
}
|
2019-03-25 17:36:26 +01:00
|
|
|
SectionTableRef removedSections() { return SectionTableRef(RemovedSections); }
|
|
|
|
|
2018-01-25 23:46:17 +01:00
|
|
|
Range<Segment> segments() { return make_pointee_range(Segments); }
|
|
|
|
ConstRange<Segment> segments() const { return make_pointee_range(Segments); }
|
|
|
|
|
2019-04-18 11:13:30 +02:00
|
|
|
Error removeSections(bool AllowBrokenLinks,
|
|
|
|
std::function<bool(const SectionBase &)> ToRemove);
|
2019-02-01 16:20:36 +01:00
|
|
|
Error removeSymbols(function_ref<bool(const Symbol &)> ToRemove);
|
2018-01-25 23:46:17 +01:00
|
|
|
template <class T, class... Ts> T &addSection(Ts &&... Args) {
|
|
|
|
auto Sec = llvm::make_unique<T>(std::forward<Ts>(Args)...);
|
|
|
|
auto Ptr = Sec.get();
|
|
|
|
Sections.emplace_back(std::move(Sec));
|
[llvm-objcopy] Add support for -I binary -B <arch>.
Summary:
The -I (--input-target) and -B (--binary-architecture) flags exist but are currently silently ignored. This adds support for -I binary for architectures i386, x86-64 (and alias i386:x86-64), arm, aarch64, sparc, and ppc (powerpc:common64). This is largely based on D41687.
This is done by implementing an additional subclass of Reader, BinaryReader, which works by interpreting the input file as contents for .data field, sets up a synthetic header, and adds additional sections/symbols (e.g. _binary__tmp_data_txt_start).
Reviewers: jakehehrlich, alexshap, jhenderson, javed.absar
Reviewed By: jhenderson
Subscribers: jyknight, nemanjai, kbarton, fedor.sergeev, jrtc27, kristof.beyls, paulsemel, llvm-commits
Differential Revision: https://reviews.llvm.org/D50343
llvm-svn: 340070
2018-08-17 20:51:11 +02:00
|
|
|
Ptr->Index = Sections.size();
|
2018-01-25 23:46:17 +01:00
|
|
|
return *Ptr;
|
|
|
|
}
|
2019-03-25 17:36:26 +01:00
|
|
|
Segment &addSegment(ArrayRef<uint8_t> Data) {
|
|
|
|
Segments.emplace_back(llvm::make_unique<Segment>(Data));
|
2018-01-25 23:46:17 +01:00
|
|
|
return *Segments.back();
|
|
|
|
}
|
2017-08-04 23:09:26 +02:00
|
|
|
};
|
2018-10-25 00:49:06 +02:00
|
|
|
|
|
|
|
} // end namespace elf
|
2018-07-18 02:10:51 +02:00
|
|
|
} // end namespace objcopy
|
2017-11-01 22:16:06 +01:00
|
|
|
} // end namespace llvm
|
|
|
|
|
|
|
|
#endif // LLVM_TOOLS_OBJCOPY_OBJECT_H
|