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

cmd/link: testDWARF in c-archive mode fails on Linux (but not Darwin) #31363

Closed
eliasnaur opened this issue Apr 9, 2019 · 4 comments
Closed
Labels
FrozenDueToAge NeedsInvestigation Someone must examine and confirm this is a valid issue and not a duplicate of an existing one. OS-Linux Testing An issue that has been verified to require only test changes, not just a test failure.
Milestone

Comments

@eliasnaur
Copy link
Contributor

From the discussion in https://go-review.googlesource.com/c/go/+/170377:

$ git diff
diff --git a/src/cmd/link/dwarf_test.go b/src/cmd/link/dwarf_test.go
index ecc96019be..ffdad6ce10 100644
--- a/src/cmd/link/dwarf_test.go
+++ b/src/cmd/link/dwarf_test.go
@@ -148,6 +148,7 @@ func testDWARF(t *testing.T, buildmode string, expectDWARF bool, env ...string)
 
 func TestDWARF(t *testing.T) {
        testDWARF(t, "", true)
+       testDWARF(t, "c-archive", true)
 }
 
 func TestDWARFiOS(t *testing.T) {
$ ./make.bash 
Building Go cmd/dist using /home/elias/dev/go-1.7.
Building Go toolchain1 using /home/elias/dev/go-1.7.
Building Go bootstrap cmd/go (go_bootstrap) using Go toolchain1.
Building Go toolchain2 using go_bootstrap and Go toolchain1.
Building Go toolchain3 using go_bootstrap and Go toolchain2.
Building packages and commands for linux/amd64.
---
Installed Go for linux/amd64 in /home/elias/dev/go-tip
Installed commands in /home/elias/dev/go-tip/bin
$ go test cmd/link
--- FAIL: TestDWARF (0.09s)
    --- FAIL: TestDWARF/testprog#01 (3.02s)
        dwarf_test.go:130: ErrUnknownPC
    --- FAIL: TestDWARF/testprogcgo#01 (4.01s)
        dwarf_test.go:130: ErrUnknownPC
FAIL
FAIL	cmd/link	4.248s

On the other hand, testDWARF successfully runs on Darwin as demonstrated by CL 170377. It also successfully runs in the related testDWARFiOS test.

@eliasnaur eliasnaur changed the title cmd/link: testDWARF is c-archive mode fails on Linux (but not Darwin) cmd/link: testDWARF in c-archive mode fails on Linux (but not Darwin) Apr 9, 2019
@bcmills bcmills added OS-Linux Testing An issue that has been verified to require only test changes, not just a test failure. NeedsInvestigation Someone must examine and confirm this is a valid issue and not a duplicate of an existing one. labels Apr 10, 2019
@bcmills bcmills added this to the Go1.13 milestone Apr 10, 2019
@andybons andybons modified the milestones: Go1.13, Go1.14 Jul 8, 2019
@thanm
Copy link
Contributor

thanm commented Sep 16, 2019

I spent a little while looking at this problem.

From what I can tell the issue is that our current debug/dwarf reader doesn't support operating on relocatable objects. What this means is that when it goes to read in the contents of things like the .debug_ranges section, it will see a pre-relocation version of the LO/HI PC values, as opposed to the final cooked/relocated value. This is not really so much a bug as it is an implementation shortcoming. The reason that the test works on Darwin is that we are (apparently) emitting fewer relocations.

Some more detail:

I hacked the dwarf.Reader.SeekPC method to print out the contents of the ranges it sees as it tries to locate the compile unit containing the address of interest. When I do this on Linux I see

examining range [0x0,0xdb9]
examining range [0x0,0x5e]
examining range [0x0,0x8a7]
examining range [0x0,0x5980a]
examining range [0x0,0x165]
...

This makes sense, since the .debug_ranges section is in an unrelocated state:

/tmp/go-link-TestDWARF501471370$ objdump -r go.o |  \
  fgrep 'RELOCATION RECORDS' | fgrep .debug
RELOCATION RECORDS FOR [.debug_line]:
RELOCATION RECORDS FOR [.debug_frame]:
RELOCATION RECORDS FOR [.debug_pubnames]:
RELOCATION RECORDS FOR [.debug_pubtypes]:
RELOCATION RECORDS FOR [.debug_info]:
RELOCATION RECORDS FOR [.debug_loc]:
RELOCATION RECORDS FOR [.debug_ranges]:

If I do the same thing on Darwin, here's what I see for relocations:

go-link-TestDWARF386711118 thanm$ gobjdump -r go.o | \
  fgrep 'RELOCATION RECORDS' | fgrep .debug
RELOCATION RECORDS FOR [.debug_line]:
RELOCATION RECORDS FOR [.debug_frame]:
RELOCATION RECORDS FOR [.debug_info]:

Note the lack of .debug_ranges relocations. I think the reason for the discrepancy is https://go-review.googlesource.com/c/go/+/171158, also understandable.

As for what to do about this, I'm unsure at this point (need to consult with other folks).

If the goal of the test is just to verify DWARF generation, then I think perhaps the thing to do would be to do an actual link with the result of the -buildmode=c-archive object, so that the relocations are resolved.

@thanm
Copy link
Contributor

thanm commented Sep 16, 2019

Well now, I stand corrected (having talked this over with Austin). Turns out that debug/elf actually does apply relocations when reading section data to feed into the DWARF reader. So it looks as though the problem may be elsewhere. I will take another look...

@thanm
Copy link
Contributor

thanm commented Sep 16, 2019

I think the culprit is here?

		if SymType(sym.Info&0xf) != STT_SECTION {
			// We don't handle non-section relocations for now.
			continue
		}

Here's the compilation unit DIE as reported by objdump:

 <0><97235>: Abbrev Number: 1 (DW_TAG_compile_unit)
    <97236>   DW_AT_name        : main
    <9723b>   DW_AT_language    : 22	(Go)
    <9723c>   DW_AT_stmt_list   : 0x33790
    <97240>   DW_AT_low_pc      : 0xb80c0
    <97248>   DW_AT_ranges      : 0x490
    <9724c>   DW_AT_comp_dir    : .
    <9724e>   DW_AT_producer    : Go cmd/compile devel +49e7c7672d Mon Sep 16 11:56:15 2019 +0000; -shared
    <97297>   Unknown AT value: 2905: main

The relocations for that section of the .debug_info look like:

000000097230  00020000000a R_X86_64_32       0000000000000000 .debug_abbrev + 0
00000009723c  00030000000a R_X86_64_32       0000000000000000 .debug_line + 33790
000000097240  0fcf00000001 R_X86_64_64       00000000000b80c0 type..eq.[2]interface  + 0
000000097248  00060000000a R_X86_64_32       0000000000000000 .debug_ranges + 490

Note the third relocation -- the symbol this relocation targets is not a section, so that would explain how things are going wrong. So the problem is not that there are no relocations being applied, it's that not quite enough of them are being applied. This doesn't really explain why the test works on Darwin, however (maybe MachO relocations work differently?).

@gopherbot
Copy link

Change https://golang.org/cl/195679 mentions this issue: debug/elf: apply more relocations when reading DWARF data sections

@golang golang locked and limited conversation to collaborators Sep 16, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
FrozenDueToAge NeedsInvestigation Someone must examine and confirm this is a valid issue and not a duplicate of an existing one. OS-Linux Testing An issue that has been verified to require only test changes, not just a test failure.
Projects
None yet
Development

No branches or pull requests

5 participants