Add support for compressed section headers to dump_syms.

Change-Id: I019cc9ffd66850ec5259f6dfcd9af8ac6c37d2c0
Reviewed-on: https://chromium-review.googlesource.com/c/breakpad/breakpad/+/3938926
Reviewed-by: Manoj Gupta <manojgupta@chromium.org>
Reviewed-by: Joshua Peraza <jperaza@chromium.org>
This commit is contained in:
Konstantin Mandrika
2022-10-26 20:16:26 +00:00
committed by Joshua Peraza
parent 7ea7ded187
commit de086a9859
6 changed files with 134 additions and 6 deletions

View File

@@ -46,8 +46,8 @@
#include <sys/mman.h>
#include <sys/stat.h>
#include <unistd.h>
#include <zlib.h>
#include <iostream>
#include <set>
#include <string>
#include <utility>
@@ -281,6 +281,55 @@ class DumperLineToModule: public DwarfCUToModule::LineToModuleHandler {
google_breakpad::ByteReader* byte_reader_;
};
template<typename ElfClass>
bool IsCompressedHeader(const typename ElfClass::Shdr* section) {
return (section->sh_flags & SHF_COMPRESSED) != 0;
}
template<typename ElfClass>
uint32_t GetCompressionHeader(
typename ElfClass::Chdr& compression_header,
const uint8_t* content, uint64_t size) {
const typename ElfClass::Chdr* header =
reinterpret_cast<const typename ElfClass::Chdr *>(content);
if (size < sizeof (*header)) {
return 0;
}
compression_header = *header;
return sizeof (*header);
}
std::pair<uint8_t *, uint64_t> UncompressSectionContents(
const uint8_t* compressed_buffer, uint64_t compressed_size, uint64_t uncompressed_size) {
z_stream stream;
memset(&stream, 0, sizeof stream);
stream.avail_in = compressed_size;
stream.avail_out = uncompressed_size;
stream.next_in = const_cast<uint8_t *>(compressed_buffer);
google_breakpad::scoped_array<uint8_t> uncompressed_buffer(
new uint8_t[uncompressed_size]);
int status = inflateInit(&stream);
while (stream.avail_in != 0 && status == Z_OK) {
stream.next_out =
uncompressed_buffer.get() + uncompressed_size - stream.avail_out;
if ((status = inflate(&stream, Z_FINISH)) != Z_STREAM_END) {
break;
}
status = inflateReset(&stream);
}
return inflateEnd(&stream) != Z_OK || status != Z_OK || stream.avail_out != 0
? std::make_pair(nullptr, 0)
: std::make_pair(uncompressed_buffer.release(), uncompressed_size);
}
template<typename ElfClass>
bool LoadDwarf(const string& dwarf_filename,
const typename ElfClass::Ehdr* elf_header,
@@ -311,7 +360,31 @@ bool LoadDwarf(const string& dwarf_filename,
section->sh_name;
const uint8_t* contents = GetOffset<ElfClass, uint8_t>(elf_header,
section->sh_offset);
file_context.AddSectionToSectionMap(name, contents, section->sh_size);
uint64_t size = section->sh_size;
if (!IsCompressedHeader<ElfClass>(section)) {
file_context.AddSectionToSectionMap(name, contents, size);
continue;
}
typename ElfClass::Chdr chdr;
uint32_t compression_header_size =
GetCompressionHeader<ElfClass>(chdr, contents, size);
if (compression_header_size == 0 || chdr.ch_size == 0) {
continue;
}
contents += compression_header_size;
size -= compression_header_size;
std::pair<uint8_t *, uint64_t> uncompressed =
UncompressSectionContents(contents, size, chdr.ch_size);
if (uncompressed.first != nullptr && uncompressed.second != 0) {
file_context.AddManagedSectionToSectionMap(name, uncompressed.first, uncompressed.second);
}
}
// .debug_ranges and .debug_rnglists reader

View File

@@ -40,6 +40,39 @@
namespace google_breakpad {
typedef struct {
typedef Elf32_Word Type;
typedef Elf32_Word Size;
typedef Elf32_Addr Addr;
static_assert(sizeof (Type) == 4);
static_assert(sizeof (Size) == 4);
static_assert(sizeof (Addr) == 4);
Type ch_type; // Compression type
Size ch_size; // Uncompressed data size in bytes
Addr ch_addralign; // Uncompressed data alignment
} Elf32_Chdr;
static_assert(sizeof (Elf32_Chdr) == 12);
typedef struct {
typedef Elf64_Word Type;
typedef Elf64_Xword Size;
typedef Elf64_Addr Addr;
static_assert(sizeof (Type) == 4);
static_assert(sizeof (Size) == 8);
static_assert(sizeof (Addr) == 8);
Type ch_type; // Compression type
Type ch_reserved; // Padding
Size ch_size; // Uncompressed data size in bytes
Addr ch_addralign; // Uncompressed data alignment
} Elf64_Chdr;
static_assert(sizeof (Elf64_Chdr) == 24);
// Traits classes so consumers can write templatized code to deal
// with specific ELF bits.
struct ElfClass32 {
@@ -49,6 +82,7 @@ struct ElfClass32 {
typedef Elf32_Nhdr Nhdr;
typedef Elf32_Phdr Phdr;
typedef Elf32_Shdr Shdr;
typedef Elf32_Chdr Chdr;
typedef Elf32_Half Half;
typedef Elf32_Off Off;
typedef Elf32_Sym Sym;
@@ -67,6 +101,7 @@ struct ElfClass64 {
typedef Elf64_Nhdr Nhdr;
typedef Elf64_Phdr Phdr;
typedef Elf64_Shdr Shdr;
typedef Elf64_Chdr Chdr;
typedef Elf64_Half Half;
typedef Elf64_Off Off;
typedef Elf64_Sym Sym;