mirror of
https://github.com/rui314/mold.git
synced 2024-12-24 17:01:50 +03:00
Add -build-id=HEXVALUE
This commit is contained in:
parent
5f492fea70
commit
5ae09ee9d3
@ -140,7 +140,32 @@ static i64 parse_hex(std::string opt, std::string_view value) {
|
||||
static i64 parse_number(std::string opt, std::string_view value) {
|
||||
if (value.find_first_not_of("0123456789") != std::string_view::npos)
|
||||
Fatal() << "option -" << opt << ": not a number";
|
||||
return std::stol(std::string(value));
|
||||
return std::stol(std::string(value), nullptr, 16);
|
||||
}
|
||||
|
||||
static std::vector<u8> parse_hex_build_id(std::string_view arg) {
|
||||
assert(arg.starts_with("0x") || arg.starts_with("0X"));
|
||||
|
||||
if (arg.size() % 2)
|
||||
Fatal() << "invalid build-id: " << arg;
|
||||
if (arg.substr(2).find_first_not_of("0123456789abcdefABCDEF") != arg.npos)
|
||||
Fatal() << "invalid build-id: " << arg;
|
||||
|
||||
arg = arg.substr(2);
|
||||
|
||||
auto fn = [](char c) {
|
||||
if ('0' <= c && c <= '9')
|
||||
return c - '0';
|
||||
if ('a' <= c && c <= 'f')
|
||||
return c - 'a' + 10;
|
||||
assert('A' <= c && c <= 'F');
|
||||
return c - 'A' + 10;
|
||||
};
|
||||
|
||||
std::vector<u8> vec(arg.size() / 2);
|
||||
for (i64 i = 0; i < vec.size(); i++)
|
||||
vec[i] = (fn(arg[i * 2]) << 4) | fn(arg[i * 2 + 1]);
|
||||
return vec;
|
||||
}
|
||||
|
||||
static std::vector<std::string_view>
|
||||
@ -294,28 +319,30 @@ void parse_nonpositional_args(std::span<std::string_view> args,
|
||||
} else if (read_arg(args, arg, "version-script")) {
|
||||
parse_version_script(std::string(arg));
|
||||
} else if (read_flag(args, "build-id")) {
|
||||
config.build_id = BuildIdKind::HASH;
|
||||
config.build_id_size = 20;
|
||||
config.build_id.kind = BuildId::HASH;
|
||||
config.build_id.hash_size = 20;
|
||||
} else if (read_arg(args, arg, "build-id")) {
|
||||
if (arg == "none") {
|
||||
config.build_id = BuildIdKind::NONE;
|
||||
config.build_id.kind = BuildId::NONE;
|
||||
} else if (arg == "uuid") {
|
||||
config.build_id = BuildIdKind::UUID;
|
||||
config.build_id_size = 16;
|
||||
config.build_id.kind = BuildId::UUID;
|
||||
} else if (arg == "md5") {
|
||||
config.build_id = BuildIdKind::HASH;
|
||||
config.build_id_size = 16;
|
||||
config.build_id.kind = BuildId::HASH;
|
||||
config.build_id.hash_size = 16;
|
||||
} else if (arg == "sha1") {
|
||||
config.build_id = BuildIdKind::HASH;
|
||||
config.build_id_size = 20;
|
||||
config.build_id.kind = BuildId::HASH;
|
||||
config.build_id.hash_size = 20;
|
||||
} else if (arg == "sha256") {
|
||||
config.build_id = BuildIdKind::HASH;
|
||||
config.build_id_size = 32;
|
||||
config.build_id.kind = BuildId::HASH;
|
||||
config.build_id.hash_size = 32;
|
||||
} else if (arg.starts_with("0x") || arg.starts_with("0X")) {
|
||||
config.build_id.kind = BuildId::HEX;
|
||||
config.build_id.value = parse_hex_build_id(arg);
|
||||
} else {
|
||||
Fatal() << "invalid --build-id argument: " << arg;
|
||||
}
|
||||
} else if (read_flag(args, "no-build-id")) {
|
||||
config.build_id = BuildIdKind::NONE;
|
||||
config.build_id.kind = BuildId::NONE;
|
||||
} else if (read_arg(args, arg, "exclude-libs")) {
|
||||
config.exclude_libs = split(arg, ",");
|
||||
} else if (read_flag(args, "preload")) {
|
||||
|
14
main.cc
14
main.cc
@ -12,6 +12,18 @@
|
||||
static tbb::task_group parser_tg;
|
||||
static bool preloading;
|
||||
|
||||
i64 BuildId::size() const {
|
||||
switch (kind) {
|
||||
case HEX:
|
||||
return value.size();
|
||||
case HASH:
|
||||
return hash_size;
|
||||
case UUID:
|
||||
return 16;
|
||||
}
|
||||
unreachable();
|
||||
}
|
||||
|
||||
static bool is_text_file(MemoryMappedFile *mb) {
|
||||
return mb->size() >= 4 &&
|
||||
isprint(mb->data()[0]) &&
|
||||
@ -926,7 +938,7 @@ int main(int argc, char **argv) {
|
||||
out::copyrel = new CopyrelSection(".bss");
|
||||
out::copyrel_relro = new CopyrelSection(".bss.rel.ro");
|
||||
|
||||
if (config.build_id != BuildIdKind::NONE)
|
||||
if (config.build_id.kind != BuildId::NONE)
|
||||
out::buildid = new BuildIdSection;
|
||||
if (config.eh_frame_hdr)
|
||||
out::eh_frame_hdr = new EhFrameHdrSection;
|
||||
|
12
mold.h
12
mold.h
@ -49,10 +49,16 @@ class OutputSection;
|
||||
class SharedFile;
|
||||
class Symbol;
|
||||
|
||||
enum class BuildIdKind : u8 { NONE, HASH, UUID };
|
||||
struct BuildId {
|
||||
i64 size() const;
|
||||
|
||||
enum { NONE, HEX, HASH, UUID } kind = NONE;
|
||||
std::vector<u8> value;
|
||||
i64 hash_size = 0;
|
||||
};
|
||||
|
||||
struct Config {
|
||||
BuildIdKind build_id = BuildIdKind::NONE;
|
||||
BuildId build_id;
|
||||
bool Bsymbolic = false;
|
||||
bool Bsymbolic_functions = false;
|
||||
bool allow_multiple_definition = false;
|
||||
@ -84,7 +90,6 @@ struct Config {
|
||||
i16 default_version = VER_NDX_GLOBAL;
|
||||
std::vector<std::string_view> version_definitions;
|
||||
std::vector<std::pair<std::string_view, i16>> version_patterns;
|
||||
i64 build_id_size = 0;
|
||||
i64 filler = -1;
|
||||
i64 thread_count = -1;
|
||||
std::string dynamic_linker = "/lib64/ld-linux-x86-64.so.2";
|
||||
@ -99,6 +104,7 @@ struct Config {
|
||||
std::vector<std::string_view> library_paths;
|
||||
std::vector<std::string_view> trace_symbol;
|
||||
std::vector<std::string_view> undefined;
|
||||
std::vector<u8> build_id_value;
|
||||
u64 image_base = 0x200000;
|
||||
};
|
||||
|
||||
|
@ -1055,16 +1055,16 @@ void VerdefSection::copy_buf() {
|
||||
}
|
||||
|
||||
void BuildIdSection::update_shdr() {
|
||||
shdr.sh_size = HEADER_SIZE + config.build_id_size;
|
||||
shdr.sh_size = HEADER_SIZE + config.build_id.size();
|
||||
}
|
||||
|
||||
void BuildIdSection::copy_buf() {
|
||||
u32 *base = (u32 *)(out::buf + shdr.sh_offset);
|
||||
memset(base, 0, shdr.sh_size);
|
||||
base[0] = 4; // Name size
|
||||
base[1] = config.build_id_size; // Hash size
|
||||
base[2] = NT_GNU_BUILD_ID; // Type
|
||||
memcpy(base + 3, "GNU", 4); // Name string
|
||||
base[0] = 4; // Name size
|
||||
base[1] = config.build_id.size(); // Hash size
|
||||
base[2] = NT_GNU_BUILD_ID; // Type
|
||||
memcpy(base + 3, "GNU", 4); // Name string
|
||||
}
|
||||
|
||||
static void compute_sha256(u8 *buf, i64 size, u8 *digest) {
|
||||
@ -1082,19 +1082,29 @@ static void compute_sha256(u8 *buf, i64 size, u8 *digest) {
|
||||
}
|
||||
|
||||
void BuildIdSection::write_buildid(i64 filesize) {
|
||||
if (config.build_id == BuildIdKind::UUID) {
|
||||
switch (config.build_id.kind) {
|
||||
case BuildId::HEX:
|
||||
write_vector(out::buf + shdr.sh_offset + HEADER_SIZE,
|
||||
config.build_id.value);
|
||||
return;
|
||||
case BuildId::HASH: {
|
||||
// Modern x86 processors have purpose-built instructions to accelerate
|
||||
// SHA256 computation, and SHA256 outperforms MD5 on such computers.
|
||||
// So, we always compute SHA256 and truncate it if smaller digest was
|
||||
// requested.
|
||||
u8 digest[SHA256_SIZE];
|
||||
assert(config.build_id.size() <= SHA256_SIZE);
|
||||
compute_sha256(out::buf, filesize, digest);
|
||||
memcpy(out::buf + shdr.sh_offset + HEADER_SIZE, digest,
|
||||
config.build_id.size());
|
||||
return;
|
||||
}
|
||||
case BuildId::UUID:
|
||||
if (!RAND_bytes(out::buf + shdr.sh_offset + HEADER_SIZE,
|
||||
config.build_id_size))
|
||||
config.build_id.size()))
|
||||
Fatal() << "RAND_bytes failed";
|
||||
return;
|
||||
}
|
||||
|
||||
// Modern x86 processors have purpose-built instructions to accelerate
|
||||
// SHA256 computation, and SHA256 outperforms MD5 on such computers.
|
||||
// So, we always compute SHA256 and truncate it if smaller digest was
|
||||
// requested.
|
||||
u8 digest[SHA256_SIZE];
|
||||
assert(config.build_id_size <= SHA256_SIZE);
|
||||
compute_sha256(out::buf, filesize, digest);
|
||||
memcpy(out::buf + shdr.sh_offset + HEADER_SIZE, digest, config.build_id_size);
|
||||
unreachable();
|
||||
}
|
||||
|
@ -22,4 +22,7 @@ readelf -n $t/exe | grep -q 'GNU.*0x00000014.*NT_GNU_BUILD_ID'
|
||||
clang -o $t/exe $t/a.c -fuse-ld=`pwd`/../mold -Wl,-build-id=sha256
|
||||
readelf -n $t/exe | grep -q 'GNU.*0x00000020.*NT_GNU_BUILD_ID'
|
||||
|
||||
clang -o $t/exe $t/a.c -fuse-ld=`pwd`/../mold -Wl,-build-id=0xdeadbeef
|
||||
readelf -n $t/exe | grep -q 'Build ID: deadbeef'
|
||||
|
||||
echo OK
|
||||
|
Loading…
Reference in New Issue
Block a user