mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-23 11:13:28 +01:00
temp
llvm-svn: 322132
This commit is contained in:
parent
a45d438e5a
commit
548d9f0152
27
test/tools/llvm-objcopy/add-gnu-debuglink.test
Normal file
27
test/tools/llvm-objcopy/add-gnu-debuglink.test
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
# RUN: yaml2obj %s > %t
|
||||||
|
# RUN: printf 0000 > %t.blob
|
||||||
|
# RUN: llvm-objcopy -add-gnu-debuglink=%t.blob %t %t2
|
||||||
|
# RUN: llvm-readobj -sections -section-data %t2 | FileCheck %s
|
||||||
|
|
||||||
|
!ELF
|
||||||
|
FileHeader:
|
||||||
|
Class: ELFCLASS64
|
||||||
|
Data: ELFDATA2LSB
|
||||||
|
Type: ET_EXEC
|
||||||
|
Machine: EM_X86_64
|
||||||
|
|
||||||
|
# CHECK: Name: .gnu_debuglink
|
||||||
|
# CHECK-NEXT: Type: SHT_PROGBITS (0x1)
|
||||||
|
# CHECK-NEXT: Flags [ (0x0)
|
||||||
|
# CHECK-NEXT: ]
|
||||||
|
# CHECK-NEXT: Address: 0x0
|
||||||
|
# CHECK-NEXT: Offset:
|
||||||
|
# CHECK-NEXT: Size: 32
|
||||||
|
# CHECK-NEXT: Link: 0
|
||||||
|
# CHECK-NEXT: Info: 0
|
||||||
|
# CHECK-NEXT: AddressAlignment: 4
|
||||||
|
# CHECK-NEXT: EntrySize: 0
|
||||||
|
# CHECK-NEXT: SectionData (
|
||||||
|
# CHECK-NEXT: 0000: 6164642D 676E752D 64656275 676C696E |add-gnu-debuglin|
|
||||||
|
# CHECK-NEXT: 0010: 6B2E7465 73742E74 6D700000 72C49B0C |k.test.tmp..r...|
|
||||||
|
# CHECK-NEXT: )
|
@ -18,6 +18,7 @@
|
|||||||
#include "llvm/Object/ELFObjectFile.h"
|
#include "llvm/Object/ELFObjectFile.h"
|
||||||
#include "llvm/Support/ErrorHandling.h"
|
#include "llvm/Support/ErrorHandling.h"
|
||||||
#include "llvm/Support/FileOutputBuffer.h"
|
#include "llvm/Support/FileOutputBuffer.h"
|
||||||
|
#include "llvm/Support/Path.h"
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
@ -343,6 +344,50 @@ void SectionWithStrTab::initialize(SectionTableRef SecTable) {
|
|||||||
|
|
||||||
void SectionWithStrTab::finalize() { this->Link = StrTab->Index; }
|
void SectionWithStrTab::finalize() { this->Link = StrTab->Index; }
|
||||||
|
|
||||||
|
template <class ELFT>
|
||||||
|
void GnuDebugLinkSection<ELFT>::init(StringRef File, StringRef Data) {
|
||||||
|
FileName = sys::path::stem(File);
|
||||||
|
// The format for the .gnu_debuglink starts with the stemmed file name and is
|
||||||
|
// followed by a null terminator and then the CRC32 of the file. The CRC32
|
||||||
|
// should be 4 byte aligned. So we add the FileName size, a 1 for the null
|
||||||
|
// byte, and then finally push the size to alignment and add 4.
|
||||||
|
Size = alignTo(FileName.size() + 1, 4) + 4;
|
||||||
|
// The CRC32 will only be aligned if we align the whole section.
|
||||||
|
Align = 4;
|
||||||
|
Type = ELF::SHT_PROGBITS;
|
||||||
|
Name = ".gnu_debuglink";
|
||||||
|
// For sections not found in segments, OriginalOffset is only used to
|
||||||
|
// establish the order that sections should go in. By using the maximum
|
||||||
|
// possible offset we cause this section to wind up at the end.
|
||||||
|
OriginalOffset = std::numeric_limits<uint64_t>::max();
|
||||||
|
JamCRC crc;
|
||||||
|
crc.update(ArrayRef<char>(Data.data(), Data.size()));
|
||||||
|
// The CRC32 value needs to be complemented because the JamCRC dosn't
|
||||||
|
// finalize the CRC32 value. It also dosn't negate the initial CRC32 value
|
||||||
|
// but it starts by default at 0xFFFFFFFF which is the complement of zero.
|
||||||
|
CRC32 = ~crc.getCRC();
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class ELFT>
|
||||||
|
GnuDebugLinkSection<ELFT>::GnuDebugLinkSection(StringRef File)
|
||||||
|
: FileName(File) {
|
||||||
|
// Read in the file to compute the CRC of it.
|
||||||
|
auto DebugOrErr = MemoryBuffer::getFile(File);
|
||||||
|
if (!DebugOrErr)
|
||||||
|
error("'" + File + "': " + DebugOrErr.getError().message());
|
||||||
|
auto Debug = std::move(*DebugOrErr);
|
||||||
|
init(File, Debug->getBuffer());
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class ELFT>
|
||||||
|
void GnuDebugLinkSection<ELFT>::writeSection(FileOutputBuffer &Out) const {
|
||||||
|
auto Buf = Out.getBufferStart() + Offset;
|
||||||
|
char *File = reinterpret_cast<char *>(Buf);
|
||||||
|
Elf_Word *CRC = reinterpret_cast<Elf_Word *>(Buf + Size - sizeof(Elf_Word));
|
||||||
|
*CRC = CRC32;
|
||||||
|
std::copy(std::begin(FileName), std::end(FileName), File);
|
||||||
|
}
|
||||||
|
|
||||||
// Returns true IFF a section is wholly inside the range of a segment
|
// Returns true IFF a section is wholly inside the range of a segment
|
||||||
static bool sectionWithinSegment(const SectionBase &Section,
|
static bool sectionWithinSegment(const SectionBase &Section,
|
||||||
const Segment &Segment) {
|
const Segment &Segment) {
|
||||||
@ -710,6 +755,10 @@ void Object<ELFT>::addSection(StringRef SecName, ArrayRef<uint8_t> Data) {
|
|||||||
Sections.push_back(std::move(Sec));
|
Sections.push_back(std::move(Sec));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <class ELFT> void Object<ELFT>::addGnuDebugLink(StringRef File) {
|
||||||
|
Sections.emplace_back(llvm::make_unique<GnuDebugLinkSection<ELFT>>(File));
|
||||||
|
}
|
||||||
|
|
||||||
template <class ELFT> void ELFObject<ELFT>::sortSections() {
|
template <class ELFT> void ELFObject<ELFT>::sortSections() {
|
||||||
// Put all sections in offset order. Maintain the ordering as closely as
|
// Put all sections in offset order. Maintain the ordering as closely as
|
||||||
// possible while meeting that demand however.
|
// possible while meeting that demand however.
|
||||||
|
@ -16,6 +16,7 @@
|
|||||||
#include "llvm/BinaryFormat/ELF.h"
|
#include "llvm/BinaryFormat/ELF.h"
|
||||||
#include "llvm/MC/StringTableBuilder.h"
|
#include "llvm/MC/StringTableBuilder.h"
|
||||||
#include "llvm/Object/ELFObjectFile.h"
|
#include "llvm/Object/ELFObjectFile.h"
|
||||||
|
#include "llvm/Support/JamCRC.h"
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
@ -345,6 +346,24 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template <class ELFT> class GnuDebugLinkSection : public SectionBase {
|
||||||
|
private:
|
||||||
|
// Elf_Word is 4-bytes on every format but has the same endianess as the elf
|
||||||
|
// type ELFT. We'll need to write the CRC32 out in the proper endianess so
|
||||||
|
// we'll make sure to use this type.
|
||||||
|
using Elf_Word = typename ELFT::Word;
|
||||||
|
|
||||||
|
StringRef FileName;
|
||||||
|
uint32_t CRC32;
|
||||||
|
|
||||||
|
void init(StringRef File, StringRef Data);
|
||||||
|
|
||||||
|
public:
|
||||||
|
// If we add this section from an external source we can use this ctor.
|
||||||
|
GnuDebugLinkSection(StringRef File);
|
||||||
|
void writeSection(FileOutputBuffer &Out) const override;
|
||||||
|
};
|
||||||
|
|
||||||
template <class ELFT> class Object {
|
template <class ELFT> class Object {
|
||||||
private:
|
private:
|
||||||
using SecPtr = std::unique_ptr<SectionBase>;
|
using SecPtr = std::unique_ptr<SectionBase>;
|
||||||
@ -389,6 +408,7 @@ public:
|
|||||||
const SectionBase *getSectionHeaderStrTab() const { return SectionNames; }
|
const SectionBase *getSectionHeaderStrTab() const { return SectionNames; }
|
||||||
void removeSections(std::function<bool(const SectionBase &)> ToRemove);
|
void removeSections(std::function<bool(const SectionBase &)> ToRemove);
|
||||||
void addSection(StringRef SecName, ArrayRef<uint8_t> Data);
|
void addSection(StringRef SecName, ArrayRef<uint8_t> Data);
|
||||||
|
void addGnuDebugLink(StringRef File);
|
||||||
virtual size_t totalSize() const = 0;
|
virtual size_t totalSize() const = 0;
|
||||||
virtual void finalize() = 0;
|
virtual void finalize() = 0;
|
||||||
virtual void write(FileOutputBuffer &Out) const = 0;
|
virtual void write(FileOutputBuffer &Out) const = 0;
|
||||||
|
@ -121,6 +121,10 @@ static cl::opt<bool> LocalizeHidden(
|
|||||||
"localize-hidden",
|
"localize-hidden",
|
||||||
cl::desc(
|
cl::desc(
|
||||||
"Mark all symbols that have hidden or internal visibility as local"));
|
"Mark all symbols that have hidden or internal visibility as local"));
|
||||||
|
static cl::opt<std::string>
|
||||||
|
AddGnuDebugLink("add-gnu-debuglink",
|
||||||
|
cl::desc("adds a .gnu_debuglink for <debug-file>"),
|
||||||
|
cl::value_desc("debug-file"));
|
||||||
|
|
||||||
using SectionPred = std::function<bool(const SectionBase &Sec)>;
|
using SectionPred = std::function<bool(const SectionBase &Sec)>;
|
||||||
|
|
||||||
@ -318,6 +322,10 @@ template <class ELFT> void CopyBinary(const ELFObjectFile<ELFT> &ObjFile) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!AddGnuDebugLink.empty()) {
|
||||||
|
Obj->addGnuDebugLink(AddGnuDebugLink);
|
||||||
|
}
|
||||||
|
|
||||||
Obj->finalize();
|
Obj->finalize();
|
||||||
WriteObjectFile(*Obj, OutputFilename.getValue());
|
WriteObjectFile(*Obj, OutputFilename.getValue());
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user