Index: ELF/Config.h
===================================================================
--- ELF/Config.h
+++ ELF/Config.h
@@ -54,6 +54,7 @@
bool AsNeeded = false;
bool Bsymbolic;
bool BsymbolicFunctions;
+ bool BuildId;
bool Demangle = true;
bool DiscardAll;
bool DiscardLocals;
Index: ELF/Driver.cpp
===================================================================
--- ELF/Driver.cpp
+++ ELF/Driver.cpp
@@ -223,6 +223,7 @@
Config->AllowMultipleDefinition = Args.hasArg(OPT_allow_multiple_definition);
Config->Bsymbolic = Args.hasArg(OPT_Bsymbolic);
Config->BsymbolicFunctions = Args.hasArg(OPT_Bsymbolic_functions);
+ Config->BuildId = Args.hasArg(OPT_build_id);
Config->Demangle = !Args.hasArg(OPT_no_demangle);
Config->DiscardAll = Args.hasArg(OPT_discard_all);
Config->DiscardLocals = Args.hasArg(OPT_discard_locals);
Index: ELF/Options.td
===================================================================
--- ELF/Options.td
+++ ELF/Options.td
@@ -12,6 +12,8 @@
def Bstatic: Flag<["-"], "Bstatic">,
HelpText<"Do not link against shared libraries">;
+def build_id : Flag<["--"], "build-id">;
+
def L : JoinedOrSeparate<["-"], "L">, MetaVarName<"
">,
HelpText<"Directory to search for libraries">;
@@ -170,7 +172,6 @@
def start_group_paren: Flag<["-"], "(">;
// Options listed below are silently ignored for now for compatibility.
-def build_id : Flag<["--"], "build-id">;
def fatal_warnings : Flag<["--"], "fatal-warnings">;
def no_add_needed : Flag<["--"], "no-add-needed">;
def no_fatal_warnings : Flag<["--"], "no-fatal-warnings">;
Index: ELF/OutputSections.h
===================================================================
--- ELF/OutputSections.h
+++ ELF/OutputSections.h
@@ -14,6 +14,7 @@
#include "llvm/MC/StringTableBuilder.h"
#include "llvm/Object/ELF.h"
+#include "llvm/Support/MD5.h"
#include "Config.h"
@@ -529,12 +530,26 @@
std::vector FdeList;
};
+template
+class BuildIdSection final : public OutputSectionBase {
+public:
+ BuildIdSection();
+ void writeTo(uint8_t *Buf) override;
+ void update(ArrayRef Buf);
+ void writeBuildId();
+
+private:
+ llvm::MD5 Hash;
+ uint8_t *Md5Buf;
+};
+
// All output sections that are hadnled by the linker specially are
// globally accessible. Writer initializes them, so don't use them
// until Writer is initialized.
template struct Out {
typedef typename llvm::object::ELFFile::uintX_t uintX_t;
typedef typename llvm::object::ELFFile::Elf_Phdr Elf_Phdr;
+ static BuildIdSection *BuildId;
static DynamicSection *Dynamic;
static EhFrameHeader *EhFrameHdr;
static GnuHashTableSection *GnuHashTab;
@@ -559,6 +574,7 @@
static OutputSectionBase *ProgramHeaders;
};
+template BuildIdSection *Out::BuildId;
template DynamicSection *Out::Dynamic;
template EhFrameHeader *Out::EhFrameHdr;
template GnuHashTableSection *Out::GnuHashTab;
Index: ELF/OutputSections.cpp
===================================================================
--- ELF/OutputSections.cpp
+++ ELF/OutputSections.cpp
@@ -1566,6 +1566,32 @@
}
template
+BuildIdSection::BuildIdSection()
+ : OutputSectionBase(".note.gnu.build-id", SHT_NOTE, 0) {
+ // 16 bytes for the note section header and 16 bytes for MD5.
+ this->Header.sh_size = 32;
+}
+
+template void BuildIdSection::writeTo(uint8_t *Buf) {
+ const endianness E = ELFT::TargetEndianness;
+ write32(Buf, 4); // Name size
+ write32(Buf + 4, 16); // Content size
+ write32(Buf + 8, 3); // Type (NT_GNU_BUILD_ID = 3)
+ memcpy(Buf + 12, "GNU", 4); // Name string
+ Md5Buf = Buf + 16;
+}
+
+template void BuildIdSection::update(ArrayRef Buf) {
+ Hash.update(Buf);
+}
+
+template void BuildIdSection::writeBuildId() {
+ MD5::MD5Result Res;
+ Hash.final(Res);
+ memcpy(Md5Buf, Res, 16);
+}
+
+template
MipsReginfoOutputSection::MipsReginfoOutputSection()
: OutputSectionBase(".reginfo", SHT_MIPS_REGINFO, SHF_ALLOC) {
this->Header.sh_addralign = 4;
@@ -1669,6 +1695,11 @@
template class SymbolTableSection;
template class SymbolTableSection;
+template class BuildIdSection;
+template class BuildIdSection;
+template class BuildIdSection;
+template class BuildIdSection;
+
template uint32_t getLocalRelTarget(const ObjectFile &,
const ELFFile::Elf_Rel &,
uint32_t);
Index: ELF/Writer.cpp
===================================================================
--- ELF/Writer.cpp
+++ ELF/Writer.cpp
@@ -75,6 +75,7 @@
bool openFile();
void writeHeader();
void writeSections();
+ void writeBuildId();
bool isDiscarded(InputSectionBase *IS) const;
StringRef getOutputSectionName(InputSectionBase *S) const;
bool needsInterpSection() const {
@@ -143,6 +144,7 @@
ProgramHeaders.updateAlign(sizeof(uintX_t));
// Instantiate optional output sections if they are needed.
+ std::unique_ptr> BuildId;
std::unique_ptr> GnuHashTab;
std::unique_ptr> GotPlt;
std::unique_ptr> HashTab;
@@ -151,6 +153,8 @@
std::unique_ptr> SymTabSec;
std::unique_ptr> MipsRldMap;
+ if (Config->BuildId)
+ BuildId.reset(new BuildIdSection);
if (Config->GnuHash)
GnuHashTab.reset(new GnuHashTableSection);
if (Config->SysvHash)
@@ -175,6 +179,7 @@
MipsRldMap->updateAlign(sizeof(uintX_t));
}
+ Out::BuildId = BuildId.get();
Out::DynStrTab = &DynStrTab;
Out::DynSymTab = &DynSymTab;
Out::Dynamic = &Dynamic;
@@ -221,6 +226,7 @@
writeSections();
if (HasError)
return;
+ writeBuildId();
check(Buffer->commit());
}
@@ -1126,6 +1132,7 @@
// This order is not the same as the final output order
// because we sort the sections using their attributes below.
+ Add(Out::BuildId);
Add(Out::SymTab);
Add(Out::ShStrTab);
Add(Out::StrTab);
@@ -1547,6 +1554,29 @@
Sec->writeTo(Buf + Sec->getFileOff());
}
+template void Writer::writeBuildId() {
+ BuildIdSection *S = Out::BuildId;
+ if (!S)
+ return;
+
+ // Compute the md5sum of all sections except .debug_* sections.
+ // We skip debug sections because they tend to be very large
+ // and their contents are very likely to be the same as long as
+ // other sections are the same.
+ uint8_t *Start = Buffer->getBufferStart();
+ uint8_t *Last = Start;
+ for (OutputSectionBase *Sec : OutputSections) {
+ uint8_t *End = Start + Sec->getFileOff();
+ if (!Sec->getName().startswith(".debug_"))
+ S->update({Last, End});
+ Last = End;
+ }
+ S->update({Last, Start + FileSize});
+
+ // Fill the MD5 field in the .note.gnu.build-id section.
+ S->writeBuildId();
+}
+
template void elf::writeResult(SymbolTable *Symtab);
template void elf::writeResult(SymbolTable *Symtab);
template void elf::writeResult(SymbolTable *Symtab);