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:
parent
fe76210da6
commit
3fb870c80b
@ -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")) {
|
||||
|
@ -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;
|
||||
|
@ -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.
|
||||
|
||||
|
2
main.cc
2
main.cc
@ -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
39
mold.h
@ -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;
|
||||
|
@ -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> *); \
|
||||
|
21
passes.cc
21
passes.cc
@ -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);
|
||||
}
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user