Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

debug/elf: decoding dwarf section abbrev at offset 0x13: cannot determine class of unknown attribute form #33488

Open
g4w opened this issue Aug 6, 2019 · 6 comments

Comments

@g4w
Copy link

commented Aug 6, 2019

What version of Go are you using (go version)?

$ go version
go version go1.12.7 windows/amd64

Does this issue reproduce with the latest release?

Yes

What operating system and processor architecture are you using (go env)?

go env Output
$ go env
set GOARCH=amd64
set GOBIN=
set GOCACHE=C:\Users\xxx\AppData\Local\go-build
set GOEXE=.exe
set GOFLAGS=
set GOHOSTARCH=amd64
set GOHOSTOS=windows
set GOOS=windows
set GOPATH=c:\xxx\go
set GOPROXY=
set GORACE=
set GOROOT=C:\Go
set GOTMPDIR=
set GOTOOLDIR=C:\Go\pkg\tool\windows_amd64
set GCCGO=gccgo
set CC=gcc
set CXX=g++
set CGO_ENABLED=1
set GOMOD=
set CGO_CFLAGS=-g -O2
set CGO_CPPFLAGS=
set CGO_CXXFLAGS=-g -O2
set CGO_FFLAGS=-g -O2
set CGO_LDFLAGS=-g -O2
set PKG_CONFIG=pkg-config
set GOGCCFLAGS=-m64 -mthreads -fno-caret-diagnostics -Qunused-arguments -fmessage-length=0 -fdebug-prefix-map=C:\Users\xxx\AppData\Local\Temp\go-build858273874=/tmp/go-build -gno-record-gcc-switches

What did you do?

I am trying to parse debug info of an embedded binary (ARM / Cortex) generated by Keil uVision.

What did you expect to see?

Be able to call DWARF() on the file without error.

What did you see instead?

Loading the file _elf, err := elf.Open(os.Args[1]) and calling _elf.DWARF() on it results in following error:
decoding dwarf section abbrev at offset 0x13: cannot determine class of unknown attribute form

This error seems to originated from debug/dwarf/entry.go with (in my case) form being formIndirect.

At somewhat similar issue and change is described here: https://go-review.googlesource.com/c/go/+/14541/2/src/debug/dwarf/entry.go and I can returning ClassUnknown for formIndirect does help get some of the parsing done, but I missing crucial pieces of the dwarf section (i.e. the members of a struct I care for seem to get skipped altogether).

As I am new to all of this I'd be thankful any comments on whether I have a funamental misunderstanding of purpose of the elf package (i.e. "was never meant to worked with embedded binariers") or whether there's something else I could besides deep diving into the issue and creating a pull request.

@ianlancetaylor ianlancetaylor added this to the Go1.14 milestone Aug 6, 2019

@ianlancetaylor

This comment has been minimized.

Copy link
Contributor

commented Aug 6, 2019

At first glance it looks like a bug. I'm not sure parseAbbrev doesn't handle formIndirect.

It would help if you provide a tiny binary that demonstrates the problem, or instructions for how to create one. Thanks.

@g4w

This comment has been minimized.

Copy link
Author

commented Aug 7, 2019

Thanks for the reply.

You can trigger the issue using Keil uVision and the "Blinky project Silicon Labs 'EFM32 Giant Gecko microcontroller using Silicon Labs 'EFM32GG-STK3700 Starter Kit' Board", available for installation from Project > Manage > Pack installer. This not to imply the issue is with this particular vendor, I've reproduced it with other projects, too.

Here's the debug file compiled on my machine: Blinky.zip

With the compiled debug version you can run below go code to get error:

elftest.exe efm\Blinky\Debug\Blinky.axf
decoding dwarf section abbrev at offset 0x13: cannot determine class of unknown attribute form

elftest source:

package main

import (
	"debug/elf"
	"fmt"
	"os"
)

func main() {
	if len(os.Args) < 2 {
		fmt.Println("Usage: elftest elf_file")
		os.Exit(1)
	}

	elffile, _ := elf.Open(os.Args[1])

	_, dwarferror := elffile.DWARF()
	if dwarferror != nil {
		fmt.Println(dwarferror.Error())
	}
}

@thanm thanm self-assigned this Aug 14, 2019

@thanm

This comment has been minimized.

Copy link
Member

commented Aug 14, 2019

I took a look at this as well. As Ian mentioned the problems seem to relate to the handling of DW_FORM_indirect. There is code in that handles it in the main DIE reader but for some reason it is getting rejected in the abbrev code handler. I will send a tentative fix.

FYI, there is some weird DWARF in the binary you posted. Compile units seem to be getting padded with extra null bytes for some reason. Ex:

 <1><2fa>: Abbrev Number: 80 (DW_TAG_typedef)
    <2fb>   DW_AT_name        : uintmax_t
    <305>   DW_AT_type        : DW_FORM_ref2 <0xed>
    <308>   DW_AT_decl_file   : 1
    <309>   DW_AT_decl_line   : 107
    <30a>   DW_AT_decl_column : 33
 <1><30b>: Abbrev Number: 0
 <0><30c>: Abbrev Number: 0
 <-1><30d>: Abbrev Number: 0
 <-2><30e>: Abbrev Number: 0
 <-3><30f>: Abbrev Number: 0
  Compilation Unit @ offset 0x310:

Note the -2, -3 at the end.

@thanm

This comment has been minimized.

Copy link
Member

commented Aug 14, 2019

Writing a regression test for this is proving to be tricky -- neither clang nor gcc seem to emit abbrevs that use DW_FORM_indirect. About all I can think of for a test is to check in the Blinky.axf file, which is about 380k. Let me know if there are any ideas for a smaller/better test.

@gopherbot

This comment has been minimized.

Copy link

commented Aug 14, 2019

Change https://golang.org/cl/190158 mentions this issue: debug/dwarf: better handling for DW_FORM_indirect

@g4w

This comment has been minimized.

Copy link
Author

commented Aug 16, 2019

Thanks for the fix! I am out office until beginning of September and won't be able to test until then (best case). For testing in general I cannot make better suggestion either (yet), but I'll add anything else I might come across here later.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
4 participants
You can’t perform that action at this time.