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"
|
2019-05-29 13:37:16 +02:00
|
|
|
#include "llvm/Support/Errc.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; \
|
2019-05-29 13:37:16 +02:00
|
|
|
friend class IHexSectionWriterBase; \
|
|
|
|
friend class IHexSectionWriter; \
|
[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) {}
|
|
|
|
};
|
|
|
|
|
2019-05-29 13:37:16 +02:00
|
|
|
using IHexLineData = SmallVector<char, 64>;
|
|
|
|
|
|
|
|
struct IHexRecord {
|
|
|
|
// Memory address of the record.
|
|
|
|
uint16_t Addr;
|
|
|
|
// Record type (see below).
|
|
|
|
uint16_t Type;
|
|
|
|
// Record data in hexadecimal form.
|
|
|
|
StringRef HexData;
|
|
|
|
|
|
|
|
// Helper method to get file length of the record
|
|
|
|
// including newline character
|
|
|
|
static size_t getLength(size_t DataSize) {
|
|
|
|
// :LLAAAATT[DD...DD]CC'
|
|
|
|
return DataSize * 2 + 11;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Gets length of line in a file (getLength + CRLF).
|
|
|
|
static size_t getLineLength(size_t DataSize) {
|
|
|
|
return getLength(DataSize) + 2;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Given type, address and data returns line which can
|
|
|
|
// be written to output file.
|
|
|
|
static IHexLineData getLine(uint8_t Type, uint16_t Addr,
|
|
|
|
ArrayRef<uint8_t> Data);
|
|
|
|
|
2019-06-13 11:56:14 +02:00
|
|
|
// Parses the line and returns record if possible.
|
|
|
|
// Line should be trimmed from whitespace characters.
|
|
|
|
static Expected<IHexRecord> parse(StringRef Line);
|
|
|
|
|
2019-05-29 13:37:16 +02:00
|
|
|
// Calculates checksum of stringified record representation
|
|
|
|
// S must NOT contain leading ':' and trailing whitespace
|
|
|
|
// characters
|
|
|
|
static uint8_t getChecksum(StringRef S);
|
|
|
|
|
|
|
|
enum Type {
|
|
|
|
// Contains data and a 16-bit starting address for the data.
|
|
|
|
// The byte count specifies number of data bytes in the record.
|
|
|
|
Data = 0,
|
|
|
|
// Must occur exactly once per file in the last line of the file.
|
|
|
|
// The data field is empty (thus byte count is 00) and the address
|
|
|
|
// field is typically 0000.
|
|
|
|
EndOfFile = 1,
|
|
|
|
// The data field contains a 16-bit segment base address (thus byte
|
|
|
|
// count is always 02) compatible with 80x86 real mode addressing.
|
|
|
|
// The address field (typically 0000) is ignored. The segment address
|
|
|
|
// from the most recent 02 record is multiplied by 16 and added to each
|
|
|
|
// subsequent data record address to form the physical starting address
|
|
|
|
// for the data. This allows addressing up to one megabyte of address
|
|
|
|
// space.
|
|
|
|
SegmentAddr = 2,
|
|
|
|
// or 80x86 processors, specifies the initial content of the CS:IP
|
|
|
|
// registers. The address field is 0000, the byte count is always 04,
|
|
|
|
// the first two data bytes are the CS value, the latter two are the
|
|
|
|
// IP value.
|
|
|
|
StartAddr80x86 = 3,
|
|
|
|
// Allows for 32 bit addressing (up to 4GiB). The record's address field
|
|
|
|
// is ignored (typically 0000) and its byte count is always 02. The two
|
|
|
|
// data bytes (big endian) specify the upper 16 bits of the 32 bit
|
|
|
|
// absolute address for all subsequent type 00 records
|
|
|
|
ExtendedAddr = 4,
|
|
|
|
// The address field is 0000 (not used) and the byte count is always 04.
|
|
|
|
// The four data bytes represent a 32-bit address value. In the case of
|
|
|
|
// 80386 and higher CPUs, this address is loaded into the EIP register.
|
|
|
|
StartAddr = 5,
|
|
|
|
// We have no other valid types
|
|
|
|
InvalidType = 6
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
// Base class for IHexSectionWriter. This class implements writing algorithm,
|
|
|
|
// but doesn't actually write records. It is used for output buffer size
|
|
|
|
// calculation in IHexWriter::finalize.
|
|
|
|
class IHexSectionWriterBase : public BinarySectionWriter {
|
|
|
|
// 20-bit segment address
|
|
|
|
uint32_t SegmentAddr = 0;
|
|
|
|
// Extended linear address
|
|
|
|
uint32_t BaseAddr = 0;
|
|
|
|
|
|
|
|
// Write segment address corresponding to 'Addr'
|
|
|
|
uint64_t writeSegmentAddr(uint64_t Addr);
|
|
|
|
// Write extended linear (base) address corresponding to 'Addr'
|
|
|
|
uint64_t writeBaseAddr(uint64_t Addr);
|
|
|
|
|
|
|
|
protected:
|
|
|
|
// Offset in the output buffer
|
|
|
|
uint64_t Offset = 0;
|
|
|
|
|
|
|
|
void writeSection(const SectionBase *Sec, ArrayRef<uint8_t> Data);
|
|
|
|
virtual void writeData(uint8_t Type, uint16_t Addr, ArrayRef<uint8_t> Data);
|
|
|
|
|
|
|
|
public:
|
|
|
|
explicit IHexSectionWriterBase(Buffer &Buf) : BinarySectionWriter(Buf) {}
|
|
|
|
|
|
|
|
uint64_t getBufferOffset() const { return Offset; }
|
|
|
|
void visit(const Section &Sec) final;
|
|
|
|
void visit(const OwnedDataSection &Sec) final;
|
|
|
|
void visit(const StringTableSection &Sec) override;
|
|
|
|
void visit(const DynamicRelocationSection &Sec) final;
|
|
|
|
using BinarySectionWriter::visit;
|
|
|
|
};
|
|
|
|
|
|
|
|
// Real IHEX section writer
|
|
|
|
class IHexSectionWriter : public IHexSectionWriterBase {
|
|
|
|
public:
|
|
|
|
IHexSectionWriter(Buffer &Buf) : IHexSectionWriterBase(Buf) {}
|
|
|
|
|
|
|
|
void writeData(uint8_t Type, uint16_t Addr, ArrayRef<uint8_t> Data) override;
|
|
|
|
void visit(const StringTableSection &Sec) override;
|
|
|
|
};
|
|
|
|
|
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
|
|
|
};
|
|
|
|
|
2019-05-29 13:37:16 +02:00
|
|
|
class IHexWriter : public Writer {
|
|
|
|
struct SectionCompare {
|
|
|
|
bool operator()(const SectionBase *Lhs, const SectionBase *Rhs) const;
|
|
|
|
};
|
|
|
|
|
|
|
|
std::set<const SectionBase *, SectionCompare> Sections;
|
|
|
|
size_t TotalSize;
|
|
|
|
|
|
|
|
Error checkSection(const SectionBase &Sec);
|
|
|
|
uint64_t writeEntryPointRecord(uint8_t *Buf);
|
|
|
|
uint64_t writeEndOfFileRecord(uint8_t *Buf);
|
|
|
|
|
|
|
|
public:
|
|
|
|
~IHexWriter() {}
|
|
|
|
Error finalize() override;
|
|
|
|
Error write() override;
|
|
|
|
IHexWriter(Object &Obj, Buffer &Buf) : Writer(Obj, Buf) {}
|
|
|
|
};
|
|
|
|
|
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
|
|
|
|
2019-05-29 13:37:16 +02:00
|
|
|
OwnedDataSection(const Twine &SecName, uint64_t SecAddr, uint64_t SecFlags,
|
|
|
|
uint64_t SecOff) {
|
|
|
|
Name = SecName.str();
|
|
|
|
Type = ELF::SHT_PROGBITS;
|
|
|
|
Addr = SecAddr;
|
|
|
|
Flags = SecFlags;
|
|
|
|
OriginalOffset = SecOff;
|
|
|
|
}
|
|
|
|
|
|
|
|
void appendHexData(StringRef HexData);
|
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,
|
2019-06-26 21:16:35 +02:00
|
|
|
SYMBOL_LOPROC = ELF::SHN_LOPROC,
|
AMDGPU/MC: Add .amdgpu_lds directive
Summary:
The directive defines a symbol as an group/local memory (LDS) symbol.
LDS symbols behave similar to common symbols for the purposes of ELF,
using the processor-specific SHN_AMDGPU_LDS as section index.
It is the linker and/or runtime loader's job to "instantiate" LDS symbols
and resolve relocations that reference them.
It is not possible to initialize LDS memory (not even zero-initialize
as for .bss).
We want to be able to link together objects -- starting with relocatable
objects, but possible expanding to shared objects in the future -- that
access LDS memory in a flexible way.
LDS memory is in an address space that is entirely separate from the
address space that contains the program image (code and normal data),
so having program segments for it doesn't really make sense.
Furthermore, we want to be able to compile multiple kernels in a
compilation unit which have disjoint use of LDS memory. In that case,
we may want to place LDS symbols differently for different kernels
to save memory (LDS memory is very limited and physically private to
each kernel invocation), so we can't simply place LDS symbols in a
.lds section.
Hence this solution where LDS symbols always stay undefined.
Change-Id: I08cbc37a7c0c32f53f7b6123aa0afc91dbc1748f
Reviewers: arsenm, rampitec, t-tye, b-sumner, jsjodin
Subscribers: kzhuravl, jvesely, wdng, yaxunl, dstuttard, tpr, rupprecht, llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D61493
llvm-svn: 364296
2019-06-25 13:51:35 +02:00
|
|
|
SYMBOL_AMDGPU_LDS = ELF::SHN_AMDGPU_LDS,
|
2017-11-01 22:16:06 +01:00
|
|
|
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,
|
2019-06-26 21:16:35 +02:00
|
|
|
SYMBOL_HIPROC = ELF::SHN_HIPROC,
|
|
|
|
SYMBOL_LOOS = ELF::SHN_LOOS,
|
|
|
|
SYMBOL_HIOS = ELF::SHN_HIOS,
|
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-06-13 11:56:14 +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
|
|
|
|
2019-06-13 11:56:14 +02:00
|
|
|
class BasicELFBuilder {
|
|
|
|
protected:
|
[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;
|
|
|
|
std::unique_ptr<Object> Obj;
|
|
|
|
|
|
|
|
void initFileHeader();
|
|
|
|
void initHeaderSegment();
|
|
|
|
StringTableSection *addStrTab();
|
|
|
|
SymbolTableSection *addSymTab(StringTableSection *StrTab);
|
|
|
|
void initSections();
|
|
|
|
|
2019-06-13 11:56:14 +02:00
|
|
|
public:
|
|
|
|
BasicELFBuilder(uint16_t EM)
|
2019-08-15 17:54:37 +02:00
|
|
|
: EMachine(EM), Obj(std::make_unique<Object>()) {}
|
2019-06-13 11:56:14 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
class BinaryELFBuilder : public BasicELFBuilder {
|
|
|
|
MemoryBuffer *MemBuf;
|
2019-08-30 12:17:16 +02:00
|
|
|
uint8_t NewSymbolVisibility;
|
2019-06-13 11:56:14 +02:00
|
|
|
void addData(SymbolTableSection *SymTab);
|
|
|
|
|
[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
|
|
|
public:
|
2019-08-30 12:17:16 +02:00
|
|
|
BinaryELFBuilder(uint16_t EM, MemoryBuffer *MB, uint8_t NewSymbolVisibility)
|
|
|
|
: BasicELFBuilder(EM), MemBuf(MB),
|
|
|
|
NewSymbolVisibility(NewSymbolVisibility) {}
|
2019-06-13 11:56:14 +02:00
|
|
|
|
|
|
|
std::unique_ptr<Object> build();
|
|
|
|
};
|
|
|
|
|
|
|
|
class IHexELFBuilder : public BasicELFBuilder {
|
|
|
|
const std::vector<IHexRecord> &Records;
|
|
|
|
|
|
|
|
void addDataSections();
|
|
|
|
|
|
|
|
public:
|
|
|
|
IHexELFBuilder(const std::vector<IHexRecord> &Records)
|
|
|
|
: BasicELFBuilder(ELF::EM_386), Records(Records) {}
|
[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
|
|
|
|
|
|
|
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;
|
2019-06-07 20:57:32 +02:00
|
|
|
size_t EhdrOffset = 0;
|
2019-06-07 19:57:48 +02:00
|
|
|
Optional<StringRef> ExtractPartition;
|
2017-08-04 23:09:26 +02:00
|
|
|
|
2018-02-15 00:31:33 +01:00
|
|
|
void setParentSegment(Segment &Child);
|
2019-06-07 19:57:48 +02:00
|
|
|
void readProgramHeaders(const ELFFile<ELFT> &HeadersFile);
|
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();
|
2019-06-07 19:57:48 +02:00
|
|
|
void readSections();
|
|
|
|
void findEhdrOffset();
|
2018-01-25 23:46:17 +01:00
|
|
|
SectionBase &makeSection(const Elf_Shdr &Shdr);
|
2017-11-01 22:16:06 +01:00
|
|
|
|
2018-01-25 22:03:38 +01:00
|
|
|
public:
|
2019-06-07 19:57:48 +02:00
|
|
|
ELFBuilder(const ELFObjectFile<ELFT> &ElfObj, Object &Obj,
|
|
|
|
Optional<StringRef> ExtractPartition)
|
|
|
|
: ElfFile(*ElfObj.getELFFile()), Obj(Obj),
|
|
|
|
ExtractPartition(ExtractPartition) {}
|
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;
|
2019-08-30 12:17:16 +02:00
|
|
|
uint8_t NewSymbolVisibility;
|
[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
|
|
|
|
|
|
|
public:
|
2019-08-30 12:17:16 +02:00
|
|
|
BinaryReader(const MachineInfo &MI, MemoryBuffer *MB,
|
|
|
|
const uint8_t NewSymbolVisibility)
|
|
|
|
: MInfo(MI), MemBuf(MB), NewSymbolVisibility(NewSymbolVisibility) {}
|
[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
|
|
|
std::unique_ptr<Object> create() const override;
|
|
|
|
};
|
|
|
|
|
2019-06-13 11:56:14 +02:00
|
|
|
class IHexReader : public Reader {
|
|
|
|
MemoryBuffer *MemBuf;
|
|
|
|
|
|
|
|
Expected<std::vector<IHexRecord>> parse() const;
|
|
|
|
Error parseError(size_t LineNo, Error E) const {
|
|
|
|
return LineNo == -1U
|
|
|
|
? createFileError(MemBuf->getBufferIdentifier(), std::move(E))
|
|
|
|
: createFileError(MemBuf->getBufferIdentifier(), LineNo,
|
|
|
|
std::move(E));
|
|
|
|
}
|
|
|
|
template <typename... Ts>
|
|
|
|
Error parseError(size_t LineNo, char const *Fmt, const Ts &... Vals) const {
|
|
|
|
Error E = createStringError(errc::invalid_argument, Fmt, Vals...);
|
|
|
|
return parseError(LineNo, std::move(E));
|
|
|
|
}
|
|
|
|
|
|
|
|
public:
|
|
|
|
IHexReader(MemoryBuffer *MB) : 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;
|
2019-06-07 19:57:48 +02:00
|
|
|
Optional<StringRef> ExtractPartition;
|
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;
|
2019-06-07 19:57:48 +02:00
|
|
|
explicit ELFReader(Binary *B, Optional<StringRef> ExtractPartition)
|
|
|
|
: Bin(B), ExtractPartition(ExtractPartition) {}
|
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;
|
2019-07-23 10:03:30 +02:00
|
|
|
bool MustBeRelocatable = false;
|
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) {
|
2019-08-15 17:54:37 +02:00
|
|
|
auto Sec = std::make_unique<T>(std::forward<Ts>(Args)...);
|
2018-01-25 23:46:17 +01:00
|
|
|
auto Ptr = Sec.get();
|
2019-07-23 10:03:30 +02:00
|
|
|
MustBeRelocatable |= isa<RelocationSection>(*Ptr);
|
2018-01-25 23:46:17 +01:00
|
|
|
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) {
|
2019-08-15 17:54:37 +02:00
|
|
|
Segments.emplace_back(std::make_unique<Segment>(Data));
|
2018-01-25 23:46:17 +01:00
|
|
|
return *Segments.back();
|
|
|
|
}
|
2019-07-23 10:03:30 +02:00
|
|
|
bool isRelocatable() const {
|
|
|
|
return (Type != ELF::ET_DYN && Type != ELF::ET_EXEC) || MustBeRelocatable;
|
|
|
|
}
|
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
|