summaryrefslogtreecommitdiff
path: root/addr2line.c
diff options
context:
space:
mode:
authornaruse <naruse@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2018-08-13 02:56:06 +0000
committernaruse <naruse@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2018-08-13 02:56:06 +0000
commita20a2b00446d52f86b94e86bc43a1aee3da9f92f (patch)
tree6d8a1faf41787737df83db6dc8468dabb30ab70a /addr2line.c
parent8507904385e86d4ce2c913e11e86ea5b71267fdc (diff)
support compressed debug_line
https://blogs.oracle.com/solaris/elf_section_compression-v2 https://gnu.wildebeest.org/blog/mjw/2016/01/13/elf-libelf-compressed-sections-and-elfutils/ git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@64328 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'addr2line.c')
-rw-r--r--addr2line.c59
1 files changed, 52 insertions, 7 deletions
diff --git a/addr2line.c b/addr2line.c
index fbe64758bc..a5b3e22074 100644
--- a/addr2line.c
+++ b/addr2line.c
@@ -101,7 +101,9 @@ void *alloca();
#define PATH_MAX 4096
#endif
-#ifndef SHF_COMPRESSED /* compatibility with glibc < 2.22 */
+#ifdef SHF_COMPRESSED
+#include <zlib.h>
+#else /* compatibility with glibc < 2.22 */
#define SHF_COMPRESSED 0
#endif
@@ -478,6 +480,41 @@ follow_debuglink(const char *debuglink, int num_traces, void **traces,
fill_lines(num_traces, traces, 0, objp, lines, offset);
}
+static int
+parse_compressed_debug_line(int num_traces, void **traces,
+ char *debug_line, unsigned long size,
+ obj_info_t *obj, line_info_t *lines, int offset)
+{
+ void *uncompressed_debug_line;
+ ElfW(Chdr) *chdr = (ElfW(Chdr) *)debug_line;
+ unsigned long destsize = chdr->ch_size;
+ int ret = 0;
+
+ if (chdr->ch_type != ELFCOMPRESS_ZLIB) {
+ /* unsupported compression type */
+ return -1;
+ }
+
+ uncompressed_debug_line = malloc(destsize);
+ if (!uncompressed_debug_line) return -1;
+ ret = uncompress(uncompressed_debug_line, &destsize,
+ (const Bytef *)debug_line + sizeof(ElfW(Chdr)), size-sizeof(ElfW(Chdr)));
+ if (ret != Z_OK) { /* Z_OK = 0 */
+ goto finish;
+ }
+ ret = parse_debug_line(num_traces, traces,
+ uncompressed_debug_line,
+ destsize,
+ obj, lines, offset);
+ if (ret) {
+ goto finish;
+ }
+
+finish:
+ free(uncompressed_debug_line);
+ return ret ? -1 : 0;
+}
+
/* read file and fill lines */
static uintptr_t
fill_lines(int num_traces, void **traces, int check_debuglink,
@@ -644,12 +681,20 @@ fill_lines(int num_traces, void **traces, int check_debuglink,
goto finish;
}
- if (!compressed_p &&
- parse_debug_line(num_traces, traces,
- file + debug_line_shdr->sh_offset,
- debug_line_shdr->sh_size,
- obj, lines, offset))
- goto fail;
+ if (compressed_p) {
+ int r = parse_compressed_debug_line(num_traces, traces,
+ file + debug_line_shdr->sh_offset,
+ debug_line_shdr->sh_size,
+ obj, lines, offset);
+ if (r) goto fail;
+ }
+ else {
+ int r = parse_debug_line(num_traces, traces,
+ file + debug_line_shdr->sh_offset,
+ debug_line_shdr->sh_size,
+ obj, lines, offset);
+ if (r) goto fail;
+ }
finish:
return dladdr_fbase;
fail: