From e815a52ea3ece2d2546ef15888197e0c059e8ac4 Mon Sep 17 00:00:00 2001
From: Eugene Tarassov
Date: Wed, 22 Aug 2018 10:19:45 -0700
Subject: TCF Agent: added support for compressed ELF sections
---
agent/msvc/agent-vc2015.vcxproj | 2 +
agent/msvc/agent-vc2015.vcxproj.filters | 6 +
agent/tcf/framework/compression.c | 325 +++++++++++++++++++++
agent/tcf/framework/compression.h | 28 ++
agent/tcf/services/dwarfio.c | 15 +-
agent/tcf/services/tcf_elf.c | 148 +++++++++-
agent/tcf/services/tcf_elf.h | 8 +-
server/msvc/server-vc2015.vcxproj | 2 +
server/msvc/server-vc2015.vcxproj.filters | 6 +
tests/test-dwarf/msvc/test-dwarf-vc2015.vcxproj | 2 +
.../msvc/test-dwarf-vc2015.vcxproj.filters | 6 +
11 files changed, 527 insertions(+), 21 deletions(-)
create mode 100644 agent/tcf/framework/compression.c
create mode 100644 agent/tcf/framework/compression.h
diff --git a/agent/msvc/agent-vc2015.vcxproj b/agent/msvc/agent-vc2015.vcxproj
index 1f3db109..a03041c4 100644
--- a/agent/msvc/agent-vc2015.vcxproj
+++ b/agent/msvc/agent-vc2015.vcxproj
@@ -308,6 +308,7 @@
+
@@ -376,6 +377,7 @@
+
diff --git a/agent/msvc/agent-vc2015.vcxproj.filters b/agent/msvc/agent-vc2015.vcxproj.filters
index 152d9257..3d6df3d6 100644
--- a/agent/msvc/agent-vc2015.vcxproj.filters
+++ b/agent/msvc/agent-vc2015.vcxproj.filters
@@ -402,6 +402,9 @@
http
+
+ framework
+
@@ -861,5 +864,8 @@
framework
+
+ framework
+
\ No newline at end of file
diff --git a/agent/tcf/framework/compression.c b/agent/tcf/framework/compression.c
new file mode 100644
index 00000000..34fa1931
--- /dev/null
+++ b/agent/tcf/framework/compression.c
@@ -0,0 +1,325 @@
+/*******************************************************************************
+* Copyright (c) 2018 Xilinx, Inc. and others.
+* All rights reserved. This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License v1.0
+* and Eclipse Distribution License v1.0 which accompany this distribution.
+* The Eclipse Public License is available at
+* http://www.eclipse.org/legal/epl-v10.html
+* and the Eclipse Distribution License is available at
+* http://www.eclipse.org/org/documents/edl-v10.php.
+* You may elect to redistribute this code under either of these licenses.
+*
+* Contributors:
+* Xilinx - initial API and implementation
+*******************************************************************************/
+
+/*
+ * Implements RFC 1951: http://www.ietf.org/rfc/rfc1951.txt
+ *
+ * RFC 1951 defines a lossless compressed data format that
+ * compresses data using a combination of the LZ77 algorithm and Huffman coding.
+ *
+ * Only decompressor is implemented.
+ */
+
+#include
+
+#include
+#include
+#include
+#include
+
+#define FAST_LOOKUP_BITS 8
+#define MAX_SYMBOLS_CNT 288
+
+typedef struct HuffmanSymbol {
+ uint16_t code;
+ uint8_t size;
+ uint8_t tree;
+} HuffmanSymbol;
+
+typedef struct HuffmanTable {
+ unsigned syms_cnt;
+ uint8_t code_size[MAX_SYMBOLS_CNT];
+ HuffmanSymbol lookup[1 << FAST_LOOKUP_BITS];
+ HuffmanSymbol tree[MAX_SYMBOLS_CNT * 2];
+} HuffmanTable;
+
+static HuffmanTable tables[3];
+
+static uint8_t * inp_buf = NULL;
+static size_t inp_size = 0;
+static unsigned inp_pos = 0;
+static uint32_t inp_bit_buf = 0;
+static unsigned inp_bit_cnt = 0;
+static uint8_t * out_buf = NULL;
+static size_t out_size = 0;
+static unsigned out_pos = 0;
+
+static unsigned get_bits(unsigned bit_cnt) {
+ unsigned v = 0;
+ if (bit_cnt > 0) {
+ assert(bit_cnt <= 32);
+ while (inp_bit_cnt < bit_cnt) {
+ if (inp_pos >= inp_size) exception(ERR_BUFFER_OVERFLOW);
+ inp_bit_buf |= (uint32_t)inp_buf[inp_pos++] << inp_bit_cnt;
+ inp_bit_cnt += 8;
+ }
+ v = inp_bit_buf & ((1u << bit_cnt) - 1);
+ inp_bit_buf >>= bit_cnt;
+ inp_bit_cnt -= bit_cnt;
+ }
+ return v;
+}
+
+static unsigned decode_huffman_symbol(HuffmanTable * t) {
+ HuffmanSymbol v;
+
+ while (inp_bit_cnt < 15) {
+ if (inp_pos >= inp_size) exception(ERR_BUFFER_OVERFLOW);
+ inp_bit_buf |= (uint32_t)inp_buf[inp_pos++] << inp_bit_cnt;
+ inp_bit_cnt += 8;
+ }
+
+ v = t->lookup[inp_bit_buf & ((1 << FAST_LOOKUP_BITS) - 1)];
+ if (v.tree) {
+ unsigned b = FAST_LOOKUP_BITS;
+ do {
+ assert(b <= 14);
+ assert(v.code <= MAX_SYMBOLS_CNT * 2 - 2);
+ v = t->tree[v.code + ((inp_bit_buf >> b++) & 1)];
+ }
+ while (v.tree);
+ assert(v.size == b);
+ }
+ assert(v.size <= 15);
+ if (v.size == 0) exception(ERR_OTHER);
+ inp_bit_buf >>= v.size;
+ inp_bit_cnt -= v.size;
+ return v.code;
+}
+
+static void decode_tables(unsigned type) {
+ memset(tables, 0, sizeof(tables));
+ if (type == 1) {
+ unsigned t;
+ for (t = 0; t < 2; t++) {
+ unsigned i = 0;
+ uint8_t * p = tables[t].code_size;
+ switch (t) {
+ case 0:
+ for (; i <= 143; i++) *p++ = 8;
+ for (; i <= 255; i++) *p++ = 9;
+ for (; i <= 279; i++) *p++ = 7;
+ for (; i <= 287; i++) *p++ = 8;
+ tables[t].syms_cnt = MAX_SYMBOLS_CNT;
+ break;
+ case 1:
+ for (; i <= 31; i++) *p++ = 5;
+ tables[t].syms_cnt = 32;
+ break;
+ }
+ }
+ }
+ else {
+ unsigned i;
+ static const uint8_t zigzag[19] = {
+ 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15
+ };
+ tables[0].syms_cnt = get_bits(5) + 257;
+ tables[1].syms_cnt = get_bits(5) + 1;
+ tables[2].syms_cnt = get_bits(4) + 4;
+ for (i = 0; i < tables[2].syms_cnt; i++) {
+ tables[2].code_size[zigzag[i]] = (uint8_t)get_bits(3);
+ }
+ tables[2].syms_cnt = 19;
+ }
+ for (;;) {
+ unsigned i;
+ unsigned sym;
+ unsigned syms_used = 0;
+ unsigned syms_total = 0;
+ unsigned syms_next[17];
+ unsigned syms_per_size[16];
+ HuffmanSymbol hs, hs_next;
+
+ memset(syms_next, 0, sizeof(syms_next));
+ memset(syms_per_size, 0, sizeof(syms_per_size));
+ for (i = 0; i < tables[type].syms_cnt; i++) syms_per_size[tables[type].code_size[i]]++;
+ for (i = 1; i <= 15; i++) {
+ syms_used += syms_per_size[i];
+ syms_total = (syms_total + syms_per_size[i]) << 1;
+ syms_next[i + 1] = syms_total;
+ }
+ if (syms_total != 0x10000 && syms_used > 1) exception(ERR_OTHER);
+
+ hs_next.tree = 1;
+ hs_next.code = 0;
+ hs_next.size = 0;
+ for (sym = 0; sym < tables[type].syms_cnt; sym++) {
+ unsigned code_size = tables[type].code_size[sym];
+ unsigned rev_code = 0;
+ unsigned cur_code = 0;
+ if (code_size == 0) continue;
+ assert(code_size <= 15);
+ cur_code = syms_next[code_size]++;
+ for (i = 0; i < code_size; i++) {
+ rev_code <<= 1;
+ rev_code = rev_code | (cur_code & 1);
+ cur_code >>= 1;
+ }
+ if (code_size <= FAST_LOOKUP_BITS) {
+ hs.tree = 0;
+ hs.code = (uint16_t)sym;
+ hs.size = (uint8_t)code_size;
+ while (rev_code < (1 << FAST_LOOKUP_BITS)) {
+ tables[type].lookup[rev_code] = hs;
+ rev_code += 1 << code_size;
+ }
+ continue;
+ }
+ hs = tables[type].lookup[rev_code & ((1 << FAST_LOOKUP_BITS) - 1)];
+ assert(hs.size == 0);
+ if (hs.tree == 0) {
+ hs = tables[type].lookup[rev_code & ((1 << FAST_LOOKUP_BITS) - 1)] = hs_next;
+ hs_next.code += 2;
+ }
+ rev_code >>= FAST_LOOKUP_BITS;
+ for (i = code_size; i > FAST_LOOKUP_BITS + 1; i--) {
+ hs.code += rev_code & 1;
+ if (tables[type].tree[hs.code].tree) {
+ hs = tables[type].tree[hs.code];
+ }
+ else {
+ hs = tables[type].tree[hs.code] = hs_next;
+ hs_next.code += 2;
+ }
+ rev_code >>= 1;
+ }
+ assert(hs_next.code <= MAX_SYMBOLS_CNT * 2);
+ hs.code += rev_code & 1;
+ tables[type].tree[hs.code].code = (uint16_t)sym;
+ tables[type].tree[hs.code].size = (uint8_t)code_size;
+ }
+
+ if (type == 2) {
+ uint8_t len_codes[MAX_SYMBOLS_CNT + 32 + 137];
+ i = 0;
+ while (i < tables[0].syms_cnt + tables[1].syms_cnt) {
+ unsigned s = 0;
+ unsigned d = decode_huffman_symbol(tables + 2);
+ if (d < 16) {
+ len_codes[i++] = (uint8_t)d;
+ continue;
+ }
+ if (d == 16 && i == 0) exception(ERR_OTHER);
+ switch (d - 16) {
+ case 0: s = get_bits(2) + 3; break;
+ case 1: s = get_bits(3) + 3; break;
+ case 2: s = get_bits(7) + 11; break;
+ }
+ if (s == 0) exception(ERR_OTHER);
+ memset(len_codes + i, d == 16 ? len_codes[i - 1] : 0, s);
+ i += s;
+ }
+ if (tables[0].syms_cnt + tables[1].syms_cnt != i) exception(ERR_OTHER);
+ memcpy(tables[0].code_size, len_codes, tables[0].syms_cnt);
+ memcpy(tables[1].code_size, len_codes + tables[0].syms_cnt, tables[1].syms_cnt);
+ }
+ if (type == 0) break;
+ type--;
+ }
+}
+
+static void decode_data_block() {
+ static const unsigned length_base[31] = {
+ 3, 4, 5, 6, 7, 8, 9, 10,
+ 11, 13, 15, 17, 19, 23, 27, 31,
+ 35, 43, 51, 59, 67, 83, 99, 115,
+ 131, 163, 195, 227, 258, 0, 0
+ };
+ static const unsigned length_extra[31] = {
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 1, 1, 1, 1, 2, 2, 2, 2,
+ 3, 3, 3, 3, 4, 4, 4, 4,
+ 5, 5, 5, 5, 0, 0, 0
+ };
+ static const unsigned dist_base[32] = {
+ 1, 2, 3, 4, 5, 7, 9, 13,
+ 17, 25, 33, 49, 65, 97, 129, 193,
+ 257, 385, 513, 769, 1025, 1537, 2049, 3073,
+ 4097, 6145, 8193, 12289, 16385, 24577, 0, 0
+ };
+ static const unsigned dist_extra[32] = {
+ 0, 0, 0, 0, 1, 1, 2, 2,
+ 3, 3, 4, 4, 5, 5, 6, 6,
+ 7, 7, 8, 8, 9, 9, 10, 10,
+ 11, 11, 12, 12, 13, 13, 0, 0
+ };
+ for (;;) {
+ unsigned sym = decode_huffman_symbol(tables);
+ if (sym < 256) {
+ if (out_pos >= out_size) exception(ERR_OTHER);
+ out_buf[out_pos++] = (uint8_t)sym;
+ }
+ else if (sym == 256) {
+ return;
+ }
+ else {
+ unsigned len = length_base[sym - 257] + get_bits(length_extra[sym - 257]);
+ unsigned sym_ofs = decode_huffman_symbol(tables + 1);
+ unsigned ofs = dist_base[sym_ofs] + get_bits(dist_extra[sym_ofs]);
+
+ if (ofs > out_pos) exception(ERR_OTHER);
+ if (out_pos + len > out_size) exception(ERR_OTHER);
+
+ while (len > 0) {
+ out_buf[out_pos] = out_buf[out_pos - ofs];
+ out_pos++;
+ len--;
+ }
+ }
+ }
+}
+
+unsigned decompress(void * src_buf, size_t src_size, void * dst_buf, size_t dst_size) {
+ inp_buf = (uint8_t *)src_buf;
+ inp_size = src_size;
+ inp_pos = 0;
+ inp_bit_buf = 0;
+ inp_bit_cnt = 0;
+ out_buf = (uint8_t *)dst_buf;
+ out_size = dst_size;
+ out_pos = 0;
+ for (;;) {
+ unsigned final = get_bits(1);
+ unsigned type = get_bits(2);
+ if (type == 0) {
+ unsigned len = 0, nlen = 0;
+ inp_pos -= inp_bit_cnt >> 3;
+ inp_bit_cnt = 0;
+ if (inp_pos + 4 > inp_size) exception(ERR_OTHER);
+ len |= inp_buf[inp_pos++];
+ len |= (unsigned)inp_buf[inp_pos++] << 8;
+ nlen |= inp_buf[inp_pos++];
+ nlen |= (unsigned)inp_buf[inp_pos++] << 8;
+ if ((len ^ nlen) != 0xffff) exception(ERR_OTHER);
+ if (inp_pos + len > inp_size) exception(ERR_OTHER);
+ if (out_pos + len > out_size) exception(ERR_OTHER);
+ memcpy(out_buf + out_pos, inp_buf + inp_pos, len);
+ inp_pos += len;
+ out_pos += len;
+ }
+ else if (type == 3) {
+ exception(ERR_OTHER);
+ }
+ else {
+ decode_tables(type);
+ decode_data_block();
+ }
+ if (final) break;
+ }
+ inp_pos -= inp_bit_cnt >> 3;
+ inp_bit_cnt = 0;
+ return inp_pos;
+}
diff --git a/agent/tcf/framework/compression.h b/agent/tcf/framework/compression.h
new file mode 100644
index 00000000..ffc1abf4
--- /dev/null
+++ b/agent/tcf/framework/compression.h
@@ -0,0 +1,28 @@
+/*******************************************************************************
+* Copyright (c) 2018 Xilinx, Inc. and others.
+* All rights reserved. This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License v1.0
+* and Eclipse Distribution License v1.0 which accompany this distribution.
+* The Eclipse Public License is available at
+* http://www.eclipse.org/legal/epl-v10.html
+* and the Eclipse Distribution License is available at
+* http://www.eclipse.org/org/documents/edl-v10.php.
+* You may elect to redistribute this code under either of these licenses.
+*
+* Contributors:
+* Xilinx - initial API and implementation
+*******************************************************************************/
+
+/*
+ * Implements RFC 1951: http://www.ietf.org/rfc/rfc1951.txt
+ * Only decompressor is implemented.
+ */
+
+#ifndef D_compression
+#define D_compression
+
+#include
+
+extern unsigned decompress(void * src_buf, size_t src_size, void * dst_buf, size_t dst_size);
+
+#endif /* D_compression */
diff --git a/agent/tcf/services/dwarfio.c b/agent/tcf/services/dwarfio.c
index 461a929f..96011acf 100644
--- a/agent/tcf/services/dwarfio.c
+++ b/agent/tcf/services/dwarfio.c
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2006, 2017 Wind River Systems, Inc. and others.
+ * Copyright (c) 2006-2018 Wind River Systems, Inc. and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* and Eclipse Distribution License v1.0 which accompany this distribution.
@@ -339,11 +339,12 @@ static U1_T * dio_LoadStringTable(ELF_File * File, U8_T * StringTableAddr, U4_T
str_exception(ERR_INV_DWARF, "Section .debug_str not found");
}
- Cache->mStringTableAddr = Section->addr;
- Cache->mStringTableSize = (size_t)Section->size;
if (elf_load(Section) < 0) {
str_exception(errno, "Cannot read .debug_str section");
}
+
+ Cache->mStringTableAddr = Section->addr;
+ Cache->mStringTableSize = (size_t)Section->size;
Cache->mStringTable = (U1_T *)Section->data;
}
@@ -660,7 +661,6 @@ void dio_ReadUnit(DIO_UnitDescriptor * Unit, DIO_EntryCallBack CallBack) {
#define dio_AbbrevTableHash(Offset) (((unsigned)(Offset)) / 16 % ABBREV_TABLE_SIZE)
void dio_LoadAbbrevTable(ELF_File * File) {
- U4_T ID;
U8_T TableOffset = 0;
ELF_Section * Section = NULL;
static U2_T * AttrBuf = NULL;
@@ -669,16 +669,17 @@ void dio_LoadAbbrevTable(ELF_File * File) {
static U4_T AbbrevBufSize = 0;
U4_T AbbrevBufPos = 0;
DIO_Cache * Cache = dio_GetCache(File);
+ unsigned i;
if (Cache->mAbbrevTable != NULL) return;
Cache->mAbbrevTable = (DIO_AbbrevSet **)loc_alloc_zero(sizeof(DIO_AbbrevSet *) * ABBREV_TABLE_SIZE);
- for (ID = 1; ID < File->section_cnt; ID++) {
- if (strcmp(File->sections[ID].name, ".debug_abbrev") == 0) {
+ for (i = 1; i < File->section_cnt; i++) {
+ if (strcmp(File->sections[i].name, ".debug_abbrev") == 0) {
if (Section != NULL) {
str_exception(ERR_INV_DWARF, "More then one .debug_abbrev section in a file");
}
- Section = File->sections + ID;
+ Section = File->sections + i;
}
}
if (Section == NULL) return;
diff --git a/agent/tcf/services/tcf_elf.c b/agent/tcf/services/tcf_elf.c
index 93690604..c1ffeb0e 100644
--- a/agent/tcf/services/tcf_elf.c
+++ b/agent/tcf/services/tcf_elf.c
@@ -31,6 +31,7 @@
#include
#include
#include
+#include
#include
#include
#include
@@ -58,10 +59,18 @@
#define MAX_FILE_AGE 60
#define MAX_FILE_CNT 100
+#ifndef SHF_COMPRESSED
+#define SHF_COMPRESSED 0x00000800
+#endif
+#ifndef ELFCOMPRESS_ZLIB
+#define ELFCOMPRESS_ZLIB 1
+#endif
#ifndef ARCH_SHF_SMALL
#define ARCH_SHF_SMALL 0
#endif
+#define SHDR_BUF_SIZE 64
+
typedef struct FileINode {
struct FileINode * next;
char * name;
@@ -704,18 +713,28 @@ static ELF_File * create_elf_cache(const char * file_name) {
if (error == 0 && hdr.e_shoff == 0) {
error = set_errno(ERR_INV_FORMAT, "Invalid section header table's file offset");
}
- if (error == 0 && lseek(file->fd, hdr.e_shoff, SEEK_SET) == (off_t)-1) error = errno;
if (error == 0) {
unsigned cnt = 0;
+ uint8_t * shdr_buf = (uint8_t *)tmp_alloc(hdr.e_shentsize * SHDR_BUF_SIZE);
file->sections = (ELF_Section *)loc_alloc_zero(sizeof(ELF_Section) * hdr.e_shnum);
file->section_cnt = hdr.e_shnum;
while (error == 0 && cnt < hdr.e_shnum) {
- Elf32_Shdr shdr;
- memset(&shdr, 0, sizeof(shdr));
- if (error == 0 && sizeof(shdr) < hdr.e_shentsize) error = ERR_INV_FORMAT;
- if (error == 0 && read_fully(file->fd, (char *)&shdr, hdr.e_shentsize) < 0) error = errno;
+ if (cnt % SHDR_BUF_SIZE == 0) {
+ unsigned n = hdr.e_shnum - cnt;
+ if (n > SHDR_BUF_SIZE) n = SHDR_BUF_SIZE;
+ if (error == 0 && lseek(file->fd, hdr.e_shoff + cnt * hdr.e_shentsize, SEEK_SET) == (off_t)-1) error = errno;
+ if (error == 0 && read_fully(file->fd, shdr_buf, hdr.e_shentsize * n) < 0) error = errno;
+ }
if (error == 0) {
+ Elf32_Shdr shdr;
ELF_Section * sec = file->sections + cnt;
+ if (hdr.e_shentsize < sizeof(shdr)) {
+ memcpy(&shdr, shdr_buf + cnt % SHDR_BUF_SIZE * hdr.e_shentsize, hdr.e_shentsize);
+ memset((uint8_t *)&shdr + hdr.e_shentsize, 0, sizeof(shdr) - hdr.e_shentsize);
+ }
+ else {
+ memcpy(&shdr, shdr_buf + cnt % SHDR_BUF_SIZE * hdr.e_shentsize, sizeof(shdr));
+ }
if (file->byte_swap) {
SWAP(shdr.sh_name);
SWAP(shdr.sh_type);
@@ -740,6 +759,33 @@ static ELF_File * create_elf_cache(const char * file_name) {
sec->link = shdr.sh_link;
sec->info = shdr.sh_info;
sec->entsize = shdr.sh_entsize;
+ if (sec->flags & SHF_COMPRESSED) {
+ struct {
+ uint32_t type;
+ uint32_t size;
+ uint32_t alignment;
+ } buf;
+ if (sec->size < sizeof(buf)) {
+ error = set_errno(ERR_INV_FORMAT, "Invalid compressed section header");
+ break;
+ }
+ sec->compressed_size = sec->size - sizeof(buf);
+ sec->compressed_offset = sec->offset + sizeof(buf);
+ sec->size = 0;
+ if (lseek(file->fd, sec->offset, SEEK_SET) == (off_t)-1 ||
+ read_fully(file->fd, &buf, sizeof(buf)) < 0) {
+ error = set_errno(errno, "Cannot read symbol file");
+ break;
+ }
+ if (file->byte_swap) {
+ SWAP(buf.type);
+ SWAP(buf.size);
+ SWAP(buf.alignment);
+ }
+ sec->compressed_type = buf.type;
+ sec->size = buf.size;
+ sec->alignment = buf.alignment;
+ }
if (sec->type == SHT_SYMTAB || sec->type == SHT_DYNSYM) {
sec->sym_count = (unsigned)(sec->size / sizeof(Elf32_Sym));
}
@@ -820,18 +866,28 @@ static ELF_File * create_elf_cache(const char * file_name) {
if (error == 0 && hdr.e_shoff == 0) {
error = set_errno(ERR_INV_FORMAT, "Invalid section header table's file offset");
}
- if (error == 0 && lseek(file->fd, hdr.e_shoff, SEEK_SET) == (off_t)-1) error = errno;
if (error == 0) {
unsigned cnt = 0;
+ uint8_t * shdr_buf = (uint8_t *)tmp_alloc(hdr.e_shentsize * SHDR_BUF_SIZE);
file->sections = (ELF_Section *)loc_alloc_zero(sizeof(ELF_Section) * hdr.e_shnum);
file->section_cnt = hdr.e_shnum;
while (error == 0 && cnt < hdr.e_shnum) {
- Elf64_Shdr shdr;
- memset(&shdr, 0, sizeof(shdr));
- if (error == 0 && sizeof(shdr) < hdr.e_shentsize) error = ERR_INV_FORMAT;
- if (error == 0 && read_fully(file->fd, (char *)&shdr, hdr.e_shentsize) < 0) error = errno;
+ if (cnt % SHDR_BUF_SIZE == 0) {
+ unsigned n = hdr.e_shnum - cnt;
+ if (n > SHDR_BUF_SIZE) n = SHDR_BUF_SIZE;
+ if (error == 0 && lseek(file->fd, hdr.e_shoff + cnt * hdr.e_shentsize, SEEK_SET) == (off_t)-1) error = errno;
+ if (error == 0 && read_fully(file->fd, shdr_buf, hdr.e_shentsize * n) < 0) error = errno;
+ }
if (error == 0) {
+ Elf64_Shdr shdr;
ELF_Section * sec = file->sections + cnt;
+ if (hdr.e_shentsize < sizeof(shdr)) {
+ memcpy(&shdr, shdr_buf + cnt % SHDR_BUF_SIZE * hdr.e_shentsize, hdr.e_shentsize);
+ memset((uint8_t *)&shdr + hdr.e_shentsize, 0, sizeof(shdr) - hdr.e_shentsize);
+ }
+ else {
+ memcpy(&shdr, shdr_buf + cnt % SHDR_BUF_SIZE * hdr.e_shentsize, sizeof(shdr));
+ }
if (file->byte_swap) {
SWAP(shdr.sh_name);
SWAP(shdr.sh_type);
@@ -856,6 +912,34 @@ static ELF_File * create_elf_cache(const char * file_name) {
sec->link = shdr.sh_link;
sec->info = shdr.sh_info;
sec->entsize = (U4_T)shdr.sh_entsize;
+ if (sec->flags & SHF_COMPRESSED) {
+ struct {
+ uint32_t type;
+ uint32_t reserved;
+ uint64_t size;
+ uint64_t alignment;
+ } buf;
+ if (sec->size < sizeof(buf)) {
+ error = set_errno(ERR_INV_FORMAT, "Invalid compressed section header");
+ break;
+ }
+ sec->compressed_size = sec->size - sizeof(buf);
+ sec->compressed_offset = sec->offset + sizeof(buf);
+ sec->size = 0;
+ if (lseek(file->fd, sec->offset, SEEK_SET) == (off_t)-1 ||
+ read_fully(file->fd, &buf, sizeof(buf)) < 0) {
+ error = set_errno(errno, "Cannot read symbol file");
+ break;
+ }
+ if (file->byte_swap) {
+ SWAP(buf.type);
+ SWAP(buf.size);
+ SWAP(buf.alignment);
+ }
+ sec->compressed_type = buf.type;
+ sec->size = buf.size;
+ sec->alignment = (U4_T)buf.alignment;
+ }
if (sec->type == SHT_SYMTAB || sec->type == SHT_DYNSYM) {
sec->sym_count = (unsigned)(sec->size / sizeof(Elf64_Sym));
}
@@ -993,7 +1077,7 @@ int elf_load(ELF_Section * s) {
#if USE_MMAP
#if defined(_WIN32) || defined(__CYGWIN__)
- if (s->size >= 0x100000) {
+ if (s->size >= 0x100000 && (s->flags & SHF_COMPRESSED) == 0) {
ELF_File * file = s->file;
if (file->mmap_handle == NULL) {
file->mmap_handle = CreateFileMapping(
@@ -1023,7 +1107,7 @@ int elf_load(ELF_Section * s) {
}
}
#else
- if (s->size >= 0x100000) {
+ if (s->size >= 0x100000 && (s->flags & SHF_COMPRESSED) == 0) {
long page = sysconf(_SC_PAGE_SIZE);
off_t offs = (off_t)s->offset;
offs -= offs % page;
@@ -1048,6 +1132,46 @@ int elf_load(ELF_Section * s) {
set_error_report_errno(file->error);
return -1;
}
+ if (s->flags & SHF_COMPRESSED) {
+ if (s->compressed_type == ELFCOMPRESS_ZLIB && s->compressed_size > 6) {
+ uint8_t * buf = (uint8_t *)loc_alloc((size_t)s->compressed_size);
+ if (lseek(file->fd, s->compressed_offset, SEEK_SET) == (off_t)-1 ||
+ read_fully(file->fd, buf, (size_t)s->compressed_size) < 0) {
+ int error = errno;
+ loc_free(buf);
+ set_errno(error, "Cannot read symbol file");
+ return -1;
+ }
+ else {
+ unsigned pos = 0;
+ unsigned cmf = buf[pos++];
+ unsigned flg = buf[pos++];
+ if ((cmf & 0xf) != 0x08) {
+ loc_free(buf);
+ set_errno(ERR_INV_DWARF, "Unsupported compression type");
+ return -1;
+ }
+ if ((cmf * 256 + flg) % 31 == 0 && (flg & 0x20) == 0) {
+ Trap trap;
+ s->data = loc_alloc_zero((size_t)s->size);
+ if (set_trap(&trap)) {
+ pos += decompress(buf + pos, (size_t)(s->compressed_size - pos), s->data, (size_t)s->size);
+ if (pos + 4 <= s->compressed_size) {
+ /* TODO: checksum verification */
+ clear_trap(&trap);
+ loc_free(buf);
+ return 0;
+ }
+ }
+ loc_free(s->data);
+ s->data = NULL;
+ }
+ }
+ loc_free(buf);
+ }
+ set_errno(ERR_INV_DWARF, "Corrupted compressed section");
+ return -1;
+ }
s->data = loc_alloc((size_t)s->size);
if (lseek(file->fd, s->offset, SEEK_SET) == (off_t)-1 ||
read_fully(file->fd, s->data, (size_t)s->size) < 0) {
diff --git a/agent/tcf/services/tcf_elf.h b/agent/tcf/services/tcf_elf.h
index 25fa3374..62876f46 100644
--- a/agent/tcf/services/tcf_elf.h
+++ b/agent/tcf/services/tcf_elf.h
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2007, 2015 Wind River Systems, Inc. and others.
+ * Copyright (c) 2007-2018 Wind River Systems, Inc. and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* and Eclipse Distribution License v1.0 which accompany this distribution.
@@ -126,7 +126,6 @@
#define STT_HIPROC 15
#define STT_ARM_TFUNC STT_LOPROC
-
#define PT_NULL 0
#define PT_LOAD 1
#define PT_DYNAMIC 2
@@ -506,6 +505,11 @@ struct ELF_Section {
U4_T info;
U4_T entsize;
+ /* Compression info */
+ U4_T compressed_type;
+ U8_T compressed_size;
+ U8_T compressed_offset;
+
void * mmap_addr;
size_t mmap_size;
diff --git a/server/msvc/server-vc2015.vcxproj b/server/msvc/server-vc2015.vcxproj
index 559aa8cf..2ea0fc75 100644
--- a/server/msvc/server-vc2015.vcxproj
+++ b/server/msvc/server-vc2015.vcxproj
@@ -187,6 +187,7 @@
+
@@ -252,6 +253,7 @@
+
diff --git a/server/msvc/server-vc2015.vcxproj.filters b/server/msvc/server-vc2015.vcxproj.filters
index 14dc345f..6b051f93 100644
--- a/server/msvc/server-vc2015.vcxproj.filters
+++ b/server/msvc/server-vc2015.vcxproj.filters
@@ -204,6 +204,9 @@
framework
+
+ framework
+
@@ -438,5 +441,8 @@
framework
+
+ framework
+
\ No newline at end of file
diff --git a/tests/test-dwarf/msvc/test-dwarf-vc2015.vcxproj b/tests/test-dwarf/msvc/test-dwarf-vc2015.vcxproj
index 319fef0f..5597f5fe 100644
--- a/tests/test-dwarf/msvc/test-dwarf-vc2015.vcxproj
+++ b/tests/test-dwarf/msvc/test-dwarf-vc2015.vcxproj
@@ -173,6 +173,7 @@
+
@@ -248,6 +249,7 @@
+
diff --git a/tests/test-dwarf/msvc/test-dwarf-vc2015.vcxproj.filters b/tests/test-dwarf/msvc/test-dwarf-vc2015.vcxproj.filters
index aebaebda..e58d7aa9 100644
--- a/tests/test-dwarf/msvc/test-dwarf-vc2015.vcxproj.filters
+++ b/tests/test-dwarf/msvc/test-dwarf-vc2015.vcxproj.filters
@@ -237,6 +237,9 @@
framework
+
+ framework
+
@@ -459,5 +462,8 @@
framework
+
+ framework
+
\ No newline at end of file
--
cgit v1.2.3