1
1
mirror of https://github.com/rui314/mold.git synced 2024-11-10 19:26:38 +03:00

Add --compress-debug-info=zlib-gnu

This commit is contained in:
Rui Ueyama 2021-06-03 22:22:29 +09:00
parent fe76210da6
commit 3fb870c80b
8 changed files with 95 additions and 28 deletions

View File

@ -53,7 +53,7 @@ Options:
--no-build-id
--chroot DIR Set a given path to root directory
--color-diagnostics Ignored
--compress-debug-sections [none,zlib,zlib-gabi]
--compress-debug-sections [none,zlib,zlib-gabi,zlib-gnu]
Compress .debug_* sections
--demangle Demangle C++ symbols in log messages (default)
--no-demangle
@ -541,9 +541,11 @@ void parse_nonpositional_args(Context<E> &ctx,
ctx.arg.warn_common = false;
} else if (read_arg(ctx, args, arg, "compress-debug-sections")) {
if (arg == "zlib" || arg == "zlib-gabi")
ctx.arg.compress_debug_sections = true;
ctx.arg.compress_debug_sections = COMPRESS_GABI;
else if (arg == "zlib-gnu")
ctx.arg.compress_debug_sections = COMPRESS_GNU;
else if (arg == "none")
ctx.arg.compress_debug_sections = false;
ctx.arg.compress_debug_sections = COMPRESS_NONE;
else
Fatal(ctx) << "invalid --compress-debug-sections argument: " << arg;
} else if (read_arg(ctx, args, arg, "wrap")) {

View File

@ -61,7 +61,7 @@ static std::vector<u8> do_compress(std::string_view input) {
return buf;
}
Compress::Compress(std::string_view input) {
Compressor::Compressor(std::string_view input) {
std::vector<std::string_view> inputs = split(input);
std::vector<u64> adlers(inputs.size());
shards.resize(inputs.size());
@ -78,14 +78,14 @@ Compress::Compress(std::string_view input) {
checksum = adler32_combine(checksum, adlers[i], inputs[i].size());
}
i64 Compress::size() const {
i64 Compressor::size() const {
i64 size = 2; // +2 for header
for (const std::vector<u8> &shard : shards)
size += shard.size();
return size + 6; // +6 for trailer and checksum
}
void Compress::write_to(u8 *buf) {
void Compressor::write_to(u8 *buf) {
// Write a zlib-format header
buf[0] = 0x78;
buf[1] = 0x9c;

View File

@ -375,7 +375,7 @@ before setting it to build-id. \fBuuid\fR sets a random 128 bits UUID.
.IP "\fB\-\-chroot\fR=\fIdir\fR"
Set \fIdir\fR to root directory.
.IP "\fB\-\-compress\-debug\-sections\fR=[\fInone\fR,\fIzlib\fR,\fIzlib\-gabi\fR]"
.IP "\fB\-\-compress\-debug\-sections\fR=[\fInone\fR,\fIzlib\fR,\fIzlib\-gabi\fR,\fIzlib\-gnu\fR]"
Compress DWARF debug info (\fB.debug_*\fR sections) using the zlib
compression algorithm.

View File

@ -572,7 +572,7 @@ int do_main(int argc, char **argv) {
// If --compress-debug-sections is given, compress .debug_* sections
// using zlib.
if (ctx.arg.compress_debug_sections) {
if (ctx.arg.compress_debug_sections != COMPRESS_NONE) {
compress_debug_sections(ctx);
filesize = set_osec_offsets(ctx);
}

39
mold.h
View File

@ -53,7 +53,7 @@ template <typename E> class Symbol;
template <typename E> struct Context;
template <typename E> struct FdeRecord;
template <typename E> struct CieRecord;
class Compress;
class Compressor;
class TarFile;
template <typename E> void cleanup();
@ -807,14 +807,26 @@ public:
};
template <typename E>
class CompressedSection : public OutputChunk<E> {
class GabiCompressedSection : public OutputChunk<E> {
public:
CompressedSection(Context<E> &ctx, OutputChunk<E> &chunk);
GabiCompressedSection(Context<E> &ctx, OutputChunk<E> &chunk);
void copy_buf(Context<E> &ctx) override;
private:
ElfChdr<E> chdr = {};
std::unique_ptr<Compress> contents;
std::unique_ptr<Compressor> contents;
};
template <typename E>
class GnuCompressedSection : public OutputChunk<E> {
public:
GnuCompressedSection(Context<E> &ctx, OutputChunk<E> &chunk);
void copy_buf(Context<E> &ctx) override;
private:
static constexpr i64 HEADER_SIZE = 12;
i64 original_size = 0;
std::unique_ptr<Compressor> contents;
};
template <typename E>
@ -1251,9 +1263,9 @@ void parse_nonpositional_args(Context<E> &ctx,
// compress.cc
//
class Compress {
class Compressor {
public:
Compress(std::string_view input);
Compressor(std::string_view input);
void write_to(u8 *buf);
i64 size() const;
@ -1329,6 +1341,8 @@ struct BuildId {
i64 hash_size = 0;
};
typedef enum { COMPRESS_NONE, COMPRESS_GABI, COMPRESS_GNU } CompressKind;
struct VersionPattern {
std::string_view pattern;
i16 ver_idx;
@ -1372,10 +1386,10 @@ struct Context {
// Command-line arguments
struct {
BuildId build_id;
CompressKind compress_debug_sections = COMPRESS_NONE;
bool Bsymbolic = false;
bool Bsymbolic_functions = false;
bool allow_multiple_definition = false;
bool compress_debug_sections = false;
bool demangle = true;
bool discard_all = false;
bool discard_locals = false;
@ -2168,6 +2182,17 @@ inline u64 read64be(u8 *buf) {
((u64)buf[6] << 8) | (u64)buf[7];
}
inline void write64be(u8 *buf, u64 val) {
buf[0] = val >> 56;
buf[1] = val >> 48;
buf[2] = val >> 40;
buf[3] = val >> 32;
buf[4] = val >> 24;
buf[5] = val >> 16;
buf[6] = val >> 8;
buf[7] = val;
}
inline void write32be(u8 *buf, u32 val) {
buf[0] = val >> 24;
buf[1] = val >> 16;

View File

@ -1633,7 +1633,8 @@ void NotePropertySection<E>::copy_buf(Context<E> &ctx) {
}
template <typename E>
CompressedSection<E>::CompressedSection(Context<E> &ctx, OutputChunk<E> &chunk)
GabiCompressedSection<E>::GabiCompressedSection(Context<E> &ctx,
OutputChunk<E> &chunk)
: OutputChunk<E>(this->SYNTHETIC) {
assert(chunk.name.starts_with(".debug"));
this->name = chunk.name;
@ -1645,7 +1646,7 @@ CompressedSection<E>::CompressedSection(Context<E> &ctx, OutputChunk<E> &chunk)
chdr.ch_size = chunk.shdr.sh_size;
chdr.ch_addralign = chunk.shdr.sh_addralign;
contents.reset(new Compress({(char *)buf.get(), chunk.shdr.sh_size}));
contents.reset(new Compressor({(char *)buf.get(), chunk.shdr.sh_size}));
this->shdr = chunk.shdr;
this->shdr.sh_flags |= SHF_COMPRESSED;
@ -1655,12 +1656,38 @@ CompressedSection<E>::CompressedSection(Context<E> &ctx, OutputChunk<E> &chunk)
}
template <typename E>
void CompressedSection<E>::copy_buf(Context<E> &ctx) {
void GabiCompressedSection<E>::copy_buf(Context<E> &ctx) {
u8 *base = ctx.buf + this->shdr.sh_offset;
memcpy(base, &chdr, sizeof(chdr));
contents->write_to(base + sizeof(chdr));
}
template <typename E>
GnuCompressedSection<E>::GnuCompressedSection(Context<E> &ctx,
OutputChunk<E> &chunk)
: OutputChunk<E>(this->SYNTHETIC) {
assert(chunk.name.starts_with(".debug"));
this->name = save_string(ctx, ".zdebug" + std::string(chunk.name.substr(6)));
std::unique_ptr<u8[]> buf(new u8[chunk.shdr.sh_size]);
chunk.write_to(ctx, buf.get());
contents.reset(new Compressor({(char *)buf.get(), chunk.shdr.sh_size}));
this->shdr = chunk.shdr;
this->shdr.sh_size = HEADER_SIZE + contents->size();
this->shndx = chunk.shndx;
this->original_size = chunk.shdr.sh_size;
}
template <typename E>
void GnuCompressedSection<E>::copy_buf(Context<E> &ctx) {
u8 *base = ctx.buf + this->shdr.sh_offset;
memcpy(base, "ZLIB", 4);
write64be(base + 4, this->original_size);
contents->write_to(base + 12);
}
template <typename E>
void ReproSection<E>::update_shdr(Context<E> &ctx) {
if (tar)
@ -1715,7 +1742,8 @@ void ReproSection<E>::copy_buf(Context<E> &ctx) {
template class VerdefSection<E>; \
template class BuildIdSection<E>; \
template class NotePropertySection<E>; \
template class CompressedSection<E>; \
template class GabiCompressedSection<E>; \
template class GnuCompressedSection<E>; \
template class ReproSection<E>; \
template i64 BuildId::size(Context<E> &) const; \
template bool is_relro(Context<E> &, OutputChunk<E> *); \

View File

@ -802,15 +802,22 @@ void compress_debug_sections(Context<E> &ctx) {
tbb::parallel_for((i64)0, (i64)ctx.chunks.size(), [&](i64 i) {
OutputChunk<E> &chunk = *ctx.chunks[i];
if (!(chunk.shdr.sh_flags & SHF_ALLOC) &&
chunk.shdr.sh_size > 0 &&
chunk.name.starts_with(".debug")) {
CompressedSection<E> *comp = new CompressedSection<E>(ctx, chunk);
ctx.output_chunks.push_back(std::unique_ptr<OutputChunk<E>>(comp));
ctx.chunks[i] = comp;
}
if ((chunk.shdr.sh_flags & SHF_ALLOC) || chunk.shdr.sh_size == 0 ||
!chunk.name.starts_with(".debug"))
return;
OutputChunk<E> *comp = nullptr;
if (ctx.arg.compress_debug_sections == COMPRESS_GABI)
comp = new GabiCompressedSection<E>(ctx, chunk);
else if (ctx.arg.compress_debug_sections == COMPRESS_GNU)
comp = new GnuCompressedSection<E>(ctx, chunk);
assert(comp);
ctx.output_chunks.push_back(std::unique_ptr<OutputChunk<E>>(comp));
ctx.chunks[i] = comp;
});
ctx.shstrtab->update_shdr(ctx);
ctx.ehdr->update_shdr(ctx);
ctx.shdr->update_shdr(ctx);
}

View File

@ -16,7 +16,12 @@ EOF
clang -fuse-ld=`pwd`/../mold -o $t/exe $t/a.o -Wl,--compress-debug-sections=zlib
dwarfdump $t/exe > $t/log
grep -q '.debug_info SHF_COMPRESSED' $t/log
grep -q '.debug_str SHF_COMPRESSED' $t/log
fgrep -q '.debug_info SHF_COMPRESSED' $t/log
fgrep -q '.debug_str SHF_COMPRESSED' $t/log
clang -fuse-ld=`pwd`/../mold -o $t/exe $t/a.o -Wl,--compress-debug-sections=zlib-gnu
dwarfdump $t/exe > $t/log
fgrep -q .zdebug_info $t/log
fgrep -q .zdebug_str $t/log
echo OK