From 63e333184093d8a85bf3b147ebd14dfe6306e826 Mon Sep 17 00:00:00 2001 From: Austin Clements Date: Tue, 1 Dec 2015 22:55:28 -0500 Subject: [PATCH] dwbug/elf: support old-style compressed DWARF GCC and LLVM support zlib-compressing DWARF debug sections (and there's some evidence that this may be happening by default in some circumstances now). Add support for reading compressed DWARF sections. Since ELF relocations apply to the decompressed data, decompression is done before applying relocations. Since relcations are applied by debug/elf, decompression must also be handled there. Note that this is different from compressed ELF sections, which is a more general mechanism used by very recent versions of GCC. Updates #11773. Change-Id: I3f4bf1b04d0802cc1e8fcb7c2a5fcf6c467c5089 Reviewed-on: https://go-review.googlesource.com/17340 Reviewed-by: Ian Lance Taylor Run-TryBot: Austin Clements TryBot-Result: Gobot Gobot Reviewed-by: Russ Cox --- elf/file.go | 29 ++++++++++++++++++--- elf/file_test.go | 28 ++++++++++++++++++++ elf/testdata/zdebug-test-gcc484-x86-64.obj | Bin 0 -> 3216 bytes 3 files changed, 54 insertions(+), 3 deletions(-) create mode 100644 elf/testdata/zdebug-test-gcc484-x86-64.obj diff --git a/elf/file.go b/elf/file.go index 3e766af..a42bde9 100644 --- a/elf/file.go +++ b/elf/file.go @@ -7,6 +7,7 @@ package elf import ( "bytes" + "compress/zlib" "debug/dwarf" "encoding/binary" "errors" @@ -863,6 +864,22 @@ func (f *File) DWARF() (*dwarf.Data, error) { return nil, err } + if len(b) >= 12 && string(b[:4]) == "ZLIB" { + dlen := binary.BigEndian.Uint64(b[4:12]) + dbuf := make([]byte, dlen) + r, err := zlib.NewReader(bytes.NewBuffer(b[12:])) + if err != nil { + return nil, err + } + if _, err := io.ReadFull(r, dbuf); err != nil { + return nil, err + } + if err := r.Close(); err != nil { + return nil, err + } + b = dbuf + } + for _, r := range f.Sections { if r.Type != SHT_RELA && r.Type != SHT_REL { continue @@ -887,17 +904,23 @@ func (f *File) DWARF() (*dwarf.Data, error) { // Don't bother loading others. var dat = map[string][]byte{"abbrev": nil, "info": nil, "str": nil, "line": nil} for i, s := range f.Sections { - if !strings.HasPrefix(s.Name, ".debug_") { + suffix := "" + switch { + case strings.HasPrefix(s.Name, ".debug_"): + suffix = s.Name[7:] + case strings.HasPrefix(s.Name, ".zdebug_"): + suffix = s.Name[8:] + default: continue } - if _, ok := dat[s.Name[7:]]; !ok { + if _, ok := dat[suffix]; !ok { continue } b, err := sectionData(i, s) if err != nil { return nil, err } - dat[s.Name[7:]] = b + dat[suffix] = b } d, err := dwarf.New(dat["abbrev"], nil, nil, dat["info"], dat["line"], nil, nil, dat["str"]) diff --git a/elf/file_test.go b/elf/file_test.go index cd1a457..6864b6d 100644 --- a/elf/file_test.go +++ b/elf/file_test.go @@ -514,6 +514,34 @@ func TestDWARFRelocations(t *testing.T) { } } +func TestCompressedDWARF(t *testing.T) { + // Test file built with GCC 4.8.4 and as 2.24 using: + // gcc -Wa,--compress-debug-sections -g -c -o zdebug-test-gcc484-x86-64.obj hello.c + f, err := Open("testdata/zdebug-test-gcc484-x86-64.obj") + if err != nil { + t.Fatal(err) + } + dwarf, err := f.DWARF() + if err != nil { + t.Fatal(err) + } + reader := dwarf.Reader() + n := 0 + for { + entry, err := reader.Next() + if err != nil { + t.Fatal(err) + } + if entry == nil { + break + } + n++ + } + if n != 18 { + t.Fatalf("want %d DWARF entries, got %d", 18, n) + } +} + func TestNoSectionOverlaps(t *testing.T) { // Ensure 6l outputs sections without overlaps. if runtime.GOOS != "linux" && runtime.GOOS != "freebsd" { diff --git a/elf/testdata/zdebug-test-gcc484-x86-64.obj b/elf/testdata/zdebug-test-gcc484-x86-64.obj new file mode 100644 index 0000000000000000000000000000000000000000..a595a01df45c31a5f266f71103eca7a835242996 GIT binary patch literal 3216 zcmbtWeN0ygjgYPu^dzA;$T{`#d0 z;e*CPUV|3*M`tLiJmm}2>21~X3Bmece=xzOwGdZ*&CGi%aV&rAd}i5^LsO=W> z3Po5S|2fa7Nen}8Oh-&BqHp*DHNC}g6TGgpFeV9Y>0KPkPWo-G9UacnEnd}{PrUj4 z*Bgd}<>mI@x1P!3eaHGfoA>uOTw8pmt@6=1T^EXeWiB=MT)~64`?n3(^*wvW@tt|L zIypTl{+y-n#zN~CM{nj|H(fhCF}1mKWY}Gj@X|jY4(z_-`((_*AL%+iI_79w436pp zCr5P42h!(nUpTwYE%+n8OuLys*|q6M?s#gY2kkPOxAFJaSiMek2c+Mm~WZKo?run?0fx zbB|l*jZ|{m9irf|`#eani5?LN*49=exLvX$S^YM<)!R_pb5_R9U+`z zZqeCbhiC=pXmZ*^QMf1)>Ripub|tO9P9u& z|7*Mv$3o69{3wamk5z(LX6x@z!62j&7EJXr3$1K?A-1UXuaWfcG6{hG!5Ojrdjw-_ zP7I+duwW8p7Ft=~T5Mr4aNb0~j8LR3u)g~+thRrHR`yq(|6Lej_wT_Nn-d}{2?+gF z66@>2Mz#7DQlHKl^luG**!rCqgPe4qSd<9v44@BW7Fub2%6qXzE&d@gP!EJ6Wr4;~ z{wj%Q+)xucki>z;QUB8oDLEH027;t-6h6GZ%XM74A3>bYV4d(!{Ib?5!sIaA@snXN+(NPJT6U(uu6Z zVJGp5{?OkKI6KuW(!V&N4mFESPSoP{w95IYFC3$?ONp{sni<&b(y~l&Hv)lwlqAUu z8Dj|t8+~(_TOh#T`34kBG(W|?GK^9PXXiDG;NY)31%mB?q~d4h~7as+n?7M|5HSNhrt(! Zt~^I7gNe=qn?IYxu{cj~xLcI>%fF{QORN9@ literal 0 HcmV?d00001