From 30683645c247aa47146d97ecf19b6de2436deb32 Mon Sep 17 00:00:00 2001 From: Rui Ueyama Date: Thu, 24 Feb 2022 11:04:28 +0900 Subject: [PATCH] [ELF] Do not corrupt compressed debug sections on i386 Previously, if an input debug section is compressed, mold produced corrupted output debug section on i386. Fixes https://github.com/rui314/mold/issues/361 --- elf/input-sections.cc | 18 +++++++++++++- test/elf/compressed-debug-info-i386.sh | 33 ++++++++++++++++++++++++++ test/elf/compressed-debug-info.sh | 4 ++-- 3 files changed, 52 insertions(+), 3 deletions(-) create mode 100755 test/elf/compressed-debug-info-i386.sh diff --git a/elf/input-sections.cc b/elf/input-sections.cc index b7c5f243c7..c4574942a3 100644 --- a/elf/input-sections.cc +++ b/elf/input-sections.cc @@ -39,16 +39,31 @@ InputSection::InputSection(Context &ctx, ObjectFile &file, if (section_idx < file.elf_sections.size()) contents = {(char *)file.mf->data + shdr().sh_offset, shdr().sh_size}; + bool compressed; + if (name.starts_with(".zdebug")) { sh_size = *(ubig64 *)&contents[4]; p2align = to_p2align(shdr().sh_addralign); + compressed = true; } else if (shdr().sh_flags & SHF_COMPRESSED) { ElfChdr &chdr = *(ElfChdr *)&contents[0]; sh_size = chdr.ch_size; p2align = to_p2align(chdr.ch_addralign); + compressed = true; } else { sh_size = shdr().sh_size; p2align = to_p2align(shdr().sh_addralign); + compressed = false; + } + + // Uncompress early if the relocation is REL-type so that we can read + // addends from section contents. If RELA-type, we don't need to do this + // because addends are in relocations. + if (compressed && E::is_rel) { + u8 *buf = new u8[sh_size]; + uncompress(ctx, buf); + contents = {(char *)buf, sh_size}; + ctx.string_pool.emplace_back(buf); } output_section = @@ -57,7 +72,8 @@ InputSection::InputSection(Context &ctx, ObjectFile &file, template bool InputSection::is_compressed() { - return name().starts_with(".zdebug") || (shdr().sh_flags & SHF_COMPRESSED); + return !E::is_rel && + (name().starts_with(".zdebug") || (shdr().sh_flags & SHF_COMPRESSED)); } template diff --git a/test/elf/compressed-debug-info-i386.sh b/test/elf/compressed-debug-info-i386.sh new file mode 100755 index 0000000000..20dd0af8fc --- /dev/null +++ b/test/elf/compressed-debug-info-i386.sh @@ -0,0 +1,33 @@ +#!/bin/bash +export LANG= +set -e +CC="${CC:-cc}" +CXX="${CXX:-c++}" +testname=$(basename "$0" .sh) +echo -n "Testing $testname ... " +cd "$(dirname "$0")"/../.. +mold="$(pwd)/mold" +t=out/test/elf/$testname +mkdir -p $t + +[ "$(uname -m)" = x86_64 ] || { echo skipped; exit; } + +which dwarfdump >& /dev/null || { echo skipped; exit; } + +cat < /dev/null +readelf --sections $t/exe | fgrep -q .debug_info + +echo ' OK' diff --git a/test/elf/compressed-debug-info.sh b/test/elf/compressed-debug-info.sh index ee16b64dd9..7d0d5da518 100755 --- a/test/elf/compressed-debug-info.sh +++ b/test/elf/compressed-debug-info.sh @@ -12,13 +12,13 @@ mkdir -p $t which dwarfdump >& /dev/null || { echo skipped; exit; } -cat <