Support --build-id=0x<hexstring>.

If you specify the option in the form of --build-id=0x<hexstring>,
that hexstring is set as a build ID. We observed that the feature
is actually in use in some builds, so we want this feature.

llvm-svn: 269495
This commit is contained in:
Rui Ueyama 2016-05-13 21:55:56 +00:00
parent abbc2ac231
commit 9194db78fb
8 changed files with 57 additions and 5 deletions

View File

@ -30,7 +30,7 @@ enum ELFKind {
ELF64BEKind
};
enum class BuildIdKind { None, Fnv1, Md5, Sha1 };
enum class BuildIdKind { None, Fnv1, Md5, Sha1, Hexstring };
// This struct contains the global configuration for the linker.
// Most fields are direct mapping from the command line options
@ -53,6 +53,7 @@ struct Configuration {
std::vector<llvm::StringRef> SearchPaths;
std::vector<llvm::StringRef> Undefined;
std::vector<llvm::StringRef> VersionScriptGlobals;
std::vector<uint8_t> BuildIdVector;
bool AllowMultipleDefinition;
bool AsNeeded = false;
bool Bsymbolic;

View File

@ -386,14 +386,18 @@ void LinkerDriver::readConfigs(opt::InputArgList &Args) {
Config->BuildId = BuildIdKind::Fnv1;
if (auto *Arg = Args.getLastArg(OPT_build_id_eq)) {
StringRef S = Arg->getValue();
if (S == "md5")
if (S == "md5") {
Config->BuildId = BuildIdKind::Md5;
else if (S == "sha1")
} else if (S == "sha1") {
Config->BuildId = BuildIdKind::Sha1;
else if (S == "none")
} else if (S == "none") {
Config->BuildId = BuildIdKind::None;
else
} else if (S.startswith("0x")) {
Config->BuildId = BuildIdKind::Hexstring;
Config->BuildIdVector = parseHexstring(S.substr(2));
} else {
error("unknown --build-id style: " + S);
}
}
for (auto *Arg : Args.filtered(OPT_undefined))

View File

@ -72,6 +72,7 @@ enum {
void printHelp(const char *Argv0);
void printVersion();
std::vector<uint8_t> parseHexstring(StringRef S);
void createResponseFile(const llvm::opt::InputArgList &Args);
void maybeCopyInputFile(StringRef Path, StringRef Buffer);

View File

@ -88,6 +88,22 @@ void elf::printVersion() {
outs() << "\n";
}
// Converts a hex string (e.g. "0x123456") to a vector.
std::vector<uint8_t> elf::parseHexstring(StringRef S) {
if (S.find_first_not_of("0123456789abcdefABCDEF") != StringRef::npos ||
S.size() % 2) {
error("malformed hexstring: " + S);
return {};
}
std::vector<uint8_t> V;
for (; !S.empty(); S = S.substr(2)) {
int I;
S.substr(0, 2).getAsInteger(16, I);
V.push_back(I);
}
return V;
}
// Makes a given pathname an absolute path first, and then remove
// beginning /. For example, "../foo.o" is converted to "home/john/foo.o",
// assuming that the current directory is "/home/john/bar".

View File

@ -1686,6 +1686,16 @@ void BuildIdSha1<ELFT>::writeBuildId(ArrayRef<ArrayRef<uint8_t>> Bufs) {
memcpy(this->HashBuf, Hash.final().data(), 20);
}
template <class ELFT>
BuildIdHexstring<ELFT>::BuildIdHexstring()
: BuildIdSection<ELFT>(Config->BuildIdVector.size()) {}
template <class ELFT>
void BuildIdHexstring<ELFT>::writeBuildId(ArrayRef<ArrayRef<uint8_t>> Bufs) {
memcpy(this->HashBuf, Config->BuildIdVector.data(),
Config->BuildIdVector.size());
}
template <class ELFT>
MipsReginfoOutputSection<ELFT>::MipsReginfoOutputSection()
: OutputSectionBase<ELFT>(".reginfo", SHT_MIPS_REGINFO, SHF_ALLOC) {
@ -1852,5 +1862,10 @@ template class BuildIdSha1<ELF32LE>;
template class BuildIdSha1<ELF32BE>;
template class BuildIdSha1<ELF64LE>;
template class BuildIdSha1<ELF64BE>;
template class BuildIdHexstring<ELF32LE>;
template class BuildIdHexstring<ELF32BE>;
template class BuildIdHexstring<ELF64LE>;
template class BuildIdHexstring<ELF64BE>;
}
}

View File

@ -581,6 +581,13 @@ public:
void writeBuildId(ArrayRef<ArrayRef<uint8_t>> Bufs) override;
};
template <class ELFT>
class BuildIdHexstring final : public BuildIdSection<ELFT> {
public:
BuildIdHexstring();
void writeBuildId(ArrayRef<ArrayRef<uint8_t>> Bufs) override;
};
// 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.

View File

@ -163,6 +163,8 @@ template <class ELFT> void elf::writeResult(SymbolTable<ELFT> *Symtab) {
BuildId.reset(new BuildIdMd5<ELFT>);
else if (Config->BuildId == BuildIdKind::Sha1)
BuildId.reset(new BuildIdSha1<ELFT>);
else if (Config->BuildId == BuildIdKind::Hexstring)
BuildId.reset(new BuildIdHexstring<ELFT>);
if (Config->GnuHash)
GnuHashTab.reset(new GnuHashTableSection<ELFT>);

View File

@ -7,6 +7,8 @@
# RUN: llvm-objdump -s %t2 | FileCheck -check-prefix=MD5 %s
# RUN: ld.lld --build-id=sha1 %t -o %t2
# RUN: llvm-objdump -s %t2 | FileCheck -check-prefix=SHA1 %s
# RUN: ld.lld --build-id=0x12345678 %t -o %t2
# RUN: llvm-objdump -s %t2 | FileCheck -check-prefix=HEX %s
# RUN: ld.lld %t -o %t2
# RUN: llvm-objdump -s %t2 | FileCheck -check-prefix=NONE %s
# RUN: ld.lld --build-id=md5 --build-id=none %t -o %t2
@ -29,4 +31,8 @@ _start:
# SHA1: Contents of section .note.gnu.build-id:
# SHA1-NEXT: 04000000 14000000 03000000 474e5500 ............GNU.
# HEX: Contents of section .note.gnu.build-id:
# HEX-NEXT: 04000000 04000000 03000000 474e5500 ............GNU.
# HEX-NEXT: 12345678
# NONE-NOT: Contents of section .note.gnu.build-id: