From: Victor Michel Date: Sun, 30 Aug 2020 20:43:39 +0000 (+0000) Subject: debug/elf: support relocations relative to sections with non-zero addresses X-Git-Tag: go1.16beta1~1155 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=e01a226fadcac721e26c12921ca54388c7244d03;p=gostls13.git debug/elf: support relocations relative to sections with non-zero addresses commit 72ec930fa70c20ce69b21bf32a7916c04c2e9c2f added basic support for relocations, but assumed that the symbol value would be 0, likely because .debug_info always has address == 0 in the ELF section headers. CL 195679 added further support for relocations, but explicitly encoded the original assumption that section addresses would be 0. This change removes that assumption: all relocations will now be properly computed based on the target symbol value even when that symbol is a section with a non-zero address. Typically, sections that are part of a LOAD program segment have non-zero addresses. For example, .debug_ranges relocations could be relative to .text, which usually has an address > 0. Fixes #40879 Change-Id: Ib0a616bb8b05d6c96d179b03ca33a10946fc5d59 GitHub-Last-Rev: 4200de732641995f3a4958a13a5c78f65b7eae50 GitHub-Pull-Request: golang/go#41038 Reviewed-on: https://go-review.googlesource.com/c/go/+/250559 Run-TryBot: Ian Lance Taylor TryBot-Result: Gobot Gobot Reviewed-by: Ian Lance Taylor --- diff --git a/src/debug/elf/file.go b/src/debug/elf/file.go index 1e863ef78e..cd5bf8fab0 100644 --- a/src/debug/elf/file.go +++ b/src/debug/elf/file.go @@ -628,23 +628,14 @@ func (f *File) applyRelocations(dst []byte, rels []byte) error { } } -// relocSymbolTargetOK decides whether we should try to apply a +// canApplyRelocation reports whether we should try to apply a // relocation to a DWARF data section, given a pointer to the symbol -// targeted by the relocation. Most relocations in DWARF data tend to -// be section-relative, but some target non-section symbols (for -// example, low_PC attrs on subprogram or compilation unit DIEs that -// target function symbols), and we need to include these as well. -// Return value is a pair (X,Y) where X is a boolean indicating -// whether the relocation is needed, and Y is the symbol value in the -// case of a non-section relocation that needs to be applied. -func relocSymbolTargetOK(sym *Symbol) (bool, uint64) { - if ST_TYPE(sym.Info) == STT_SECTION { - return true, 0 - } - if sym.Section != SHN_UNDEF && sym.Section < SHN_LORESERVE { - return true, sym.Value - } - return false, 0 +// targeted by the relocation. +// Most relocations in DWARF data tend to be section-relative, but +// some target non-section symbols (for example, low_PC attrs on +// subprogram or compilation unit DIEs that target function symbols). +func canApplyRelocation(sym *Symbol) bool { + return sym.Section != SHN_UNDEF && sym.Section < SHN_LORESERVE } func (f *File) applyRelocationsAMD64(dst []byte, rels []byte) error { @@ -670,8 +661,7 @@ func (f *File) applyRelocationsAMD64(dst []byte, rels []byte) error { continue } sym := &symbols[symNo-1] - needed, val := relocSymbolTargetOK(sym) - if !needed { + if !canApplyRelocation(sym) { continue } @@ -684,13 +674,13 @@ func (f *File) applyRelocationsAMD64(dst []byte, rels []byte) error { if rela.Off+8 >= uint64(len(dst)) || rela.Addend < 0 { continue } - val64 := val + uint64(rela.Addend) + val64 := sym.Value + uint64(rela.Addend) f.ByteOrder.PutUint64(dst[rela.Off:rela.Off+8], val64) case R_X86_64_32: if rela.Off+4 >= uint64(len(dst)) || rela.Addend < 0 { continue } - val32 := uint32(val) + uint32(rela.Addend) + val32 := uint32(sym.Value) + uint32(rela.Addend) f.ByteOrder.PutUint32(dst[rela.Off:rela.Off+4], val32) } } @@ -796,8 +786,7 @@ func (f *File) applyRelocationsARM64(dst []byte, rels []byte) error { continue } sym := &symbols[symNo-1] - needed, val := relocSymbolTargetOK(sym) - if !needed { + if !canApplyRelocation(sym) { continue } @@ -810,13 +799,13 @@ func (f *File) applyRelocationsARM64(dst []byte, rels []byte) error { if rela.Off+8 >= uint64(len(dst)) || rela.Addend < 0 { continue } - val64 := uint64(val) + uint64(rela.Addend) + val64 := sym.Value + uint64(rela.Addend) f.ByteOrder.PutUint64(dst[rela.Off:rela.Off+8], val64) case R_AARCH64_ABS32: if rela.Off+4 >= uint64(len(dst)) || rela.Addend < 0 { continue } - val32 := uint32(val) + uint32(rela.Addend) + val32 := uint32(sym.Value) + uint32(rela.Addend) f.ByteOrder.PutUint32(dst[rela.Off:rela.Off+4], val32) } } @@ -847,8 +836,7 @@ func (f *File) applyRelocationsPPC(dst []byte, rels []byte) error { continue } sym := &symbols[symNo-1] - needed, val := relocSymbolTargetOK(sym) - if !needed { + if !canApplyRelocation(sym) { continue } @@ -857,7 +845,7 @@ func (f *File) applyRelocationsPPC(dst []byte, rels []byte) error { if rela.Off+4 >= uint32(len(dst)) || rela.Addend < 0 { continue } - val32 := uint32(val) + uint32(rela.Addend) + val32 := uint32(sym.Value) + uint32(rela.Addend) f.ByteOrder.PutUint32(dst[rela.Off:rela.Off+4], val32) } } @@ -888,8 +876,7 @@ func (f *File) applyRelocationsPPC64(dst []byte, rels []byte) error { continue } sym := &symbols[symNo-1] - needed, val := relocSymbolTargetOK(sym) - if !needed { + if !canApplyRelocation(sym) { continue } @@ -898,13 +885,13 @@ func (f *File) applyRelocationsPPC64(dst []byte, rels []byte) error { if rela.Off+8 >= uint64(len(dst)) || rela.Addend < 0 { continue } - val64 := val + uint64(rela.Addend) + val64 := sym.Value + uint64(rela.Addend) f.ByteOrder.PutUint64(dst[rela.Off:rela.Off+8], val64) case R_PPC64_ADDR32: if rela.Off+4 >= uint64(len(dst)) || rela.Addend < 0 { continue } - val32 := uint32(val) + uint32(rela.Addend) + val32 := uint32(sym.Value) + uint32(rela.Addend) f.ByteOrder.PutUint32(dst[rela.Off:rela.Off+4], val32) } } @@ -980,8 +967,7 @@ func (f *File) applyRelocationsMIPS64(dst []byte, rels []byte) error { continue } sym := &symbols[symNo-1] - needed, val := relocSymbolTargetOK(sym) - if !needed { + if !canApplyRelocation(sym) { continue } @@ -990,13 +976,13 @@ func (f *File) applyRelocationsMIPS64(dst []byte, rels []byte) error { if rela.Off+8 >= uint64(len(dst)) || rela.Addend < 0 { continue } - val64 := val + uint64(rela.Addend) + val64 := sym.Value + uint64(rela.Addend) f.ByteOrder.PutUint64(dst[rela.Off:rela.Off+8], val64) case R_MIPS_32: if rela.Off+4 >= uint64(len(dst)) || rela.Addend < 0 { continue } - val32 := uint32(val) + uint32(rela.Addend) + val32 := uint32(sym.Value) + uint32(rela.Addend) f.ByteOrder.PutUint32(dst[rela.Off:rela.Off+4], val32) } } @@ -1027,8 +1013,7 @@ func (f *File) applyRelocationsRISCV64(dst []byte, rels []byte) error { continue } sym := &symbols[symNo-1] - needed, val := relocSymbolTargetOK(sym) - if !needed { + if !canApplyRelocation(sym) { continue } @@ -1037,13 +1022,13 @@ func (f *File) applyRelocationsRISCV64(dst []byte, rels []byte) error { if rela.Off+8 >= uint64(len(dst)) || rela.Addend < 0 { continue } - val64 := val + uint64(rela.Addend) + val64 := sym.Value + uint64(rela.Addend) f.ByteOrder.PutUint64(dst[rela.Off:rela.Off+8], val64) case R_RISCV_32: if rela.Off+4 >= uint64(len(dst)) || rela.Addend < 0 { continue } - val32 := uint32(val) + uint32(rela.Addend) + val32 := uint32(sym.Value) + uint32(rela.Addend) f.ByteOrder.PutUint32(dst[rela.Off:rela.Off+4], val32) } } @@ -1074,8 +1059,7 @@ func (f *File) applyRelocationss390x(dst []byte, rels []byte) error { continue } sym := &symbols[symNo-1] - needed, val := relocSymbolTargetOK(sym) - if !needed { + if !canApplyRelocation(sym) { continue } @@ -1084,13 +1068,13 @@ func (f *File) applyRelocationss390x(dst []byte, rels []byte) error { if rela.Off+8 >= uint64(len(dst)) || rela.Addend < 0 { continue } - val64 := val + uint64(rela.Addend) + val64 := sym.Value + uint64(rela.Addend) f.ByteOrder.PutUint64(dst[rela.Off:rela.Off+8], val64) case R_390_32: if rela.Off+4 >= uint64(len(dst)) || rela.Addend < 0 { continue } - val32 := uint32(val) + uint32(rela.Addend) + val32 := uint32(sym.Value) + uint32(rela.Addend) f.ByteOrder.PutUint32(dst[rela.Off:rela.Off+4], val32) } } @@ -1121,8 +1105,7 @@ func (f *File) applyRelocationsSPARC64(dst []byte, rels []byte) error { continue } sym := &symbols[symNo-1] - needed, val := relocSymbolTargetOK(sym) - if !needed { + if !canApplyRelocation(sym) { continue } @@ -1131,13 +1114,13 @@ func (f *File) applyRelocationsSPARC64(dst []byte, rels []byte) error { if rela.Off+8 >= uint64(len(dst)) || rela.Addend < 0 { continue } - val64 := val + uint64(rela.Addend) + val64 := sym.Value + uint64(rela.Addend) f.ByteOrder.PutUint64(dst[rela.Off:rela.Off+8], val64) case R_SPARC_32, R_SPARC_UA32: if rela.Off+4 >= uint64(len(dst)) || rela.Addend < 0 { continue } - val32 := uint32(val) + uint32(rela.Addend) + val32 := uint32(sym.Value) + uint32(rela.Addend) f.ByteOrder.PutUint32(dst[rela.Off:rela.Off+4], val32) } } diff --git a/src/debug/elf/file_test.go b/src/debug/elf/file_test.go index 4da580da5a..24948e696a 100644 --- a/src/debug/elf/file_test.go +++ b/src/debug/elf/file_test.go @@ -293,6 +293,7 @@ func decompress(gz string) (io.ReaderAt, error) { type relocationTestEntry struct { entryNumber int entry *dwarf.Entry + pcRanges [][2]uint64 } type relocationTest struct { @@ -319,6 +320,7 @@ var relocationTests = []relocationTest{ {Attr: dwarf.AttrStmtList, Val: int64(0), Class: dwarf.ClassLinePtr}, }, }, + pcRanges: [][2]uint64{{0x0, 0x6}}, }, }, }, @@ -340,6 +342,7 @@ var relocationTests = []relocationTest{ {Attr: dwarf.AttrStmtList, Val: int64(0), Class: dwarf.ClassLinePtr}, }, }, + pcRanges: [][2]uint64{{0x0, 0x5}}, }, }, }, @@ -361,6 +364,7 @@ var relocationTests = []relocationTest{ {Attr: dwarf.AttrStmtList, Val: int64(0), Class: dwarf.ClassLinePtr}, }, }, + pcRanges: [][2]uint64{{0x0, 0x6}}, }, }, }, @@ -382,6 +386,7 @@ var relocationTests = []relocationTest{ {Attr: dwarf.AttrStmtList, Val: int64(0), Class: dwarf.ClassLinePtr}, }, }, + pcRanges: [][2]uint64{{0x0, 0x24}}, }, }, }, @@ -403,6 +408,7 @@ var relocationTests = []relocationTest{ {Attr: dwarf.AttrStmtList, Val: int64(0), Class: dwarf.ClassLinePtr}, }, }, + pcRanges: [][2]uint64{{0x0, 0x28}}, }, }, }, @@ -421,9 +427,10 @@ var relocationTests = []relocationTest{ {Attr: dwarf.AttrStmtList, Val: int64(0x0), Class: dwarf.ClassLinePtr}, {Attr: dwarf.AttrCompDir, Val: "/tmp", Class: dwarf.ClassString}, {Attr: dwarf.AttrLowpc, Val: uint64(0x0), Class: dwarf.ClassAddress}, - {Attr: dwarf.AttrHighpc, Val: int64(48), Class: dwarf.ClassConstant}, + {Attr: dwarf.AttrHighpc, Val: int64(0x30), Class: dwarf.ClassConstant}, }, }, + pcRanges: [][2]uint64{{0x0, 0x30}}, }, }, }, @@ -445,6 +452,7 @@ var relocationTests = []relocationTest{ {Attr: dwarf.AttrStmtList, Val: int64(0), Class: dwarf.ClassLinePtr}, }, }, + pcRanges: [][2]uint64{{0x0, 0x44}}, }, }, }, @@ -466,6 +474,7 @@ var relocationTests = []relocationTest{ {Attr: dwarf.AttrStmtList, Val: int64(0), Class: dwarf.ClassLinePtr}, }, }, + pcRanges: [][2]uint64{{0x0, 0x24}}, }, }, }, @@ -483,10 +492,11 @@ var relocationTests = []relocationTest{ {Attr: dwarf.AttrName, Val: "hello.c", Class: dwarf.ClassString}, {Attr: dwarf.AttrCompDir, Val: "/tmp", Class: dwarf.ClassString}, {Attr: dwarf.AttrLowpc, Val: uint64(0x0), Class: dwarf.ClassAddress}, - {Attr: dwarf.AttrHighpc, Val: int64(100), Class: dwarf.ClassConstant}, + {Attr: dwarf.AttrHighpc, Val: int64(0x64), Class: dwarf.ClassConstant}, {Attr: dwarf.AttrStmtList, Val: int64(0), Class: dwarf.ClassLinePtr}, }, }, + pcRanges: [][2]uint64{{0x0, 0x64}}, }, }, }, @@ -504,10 +514,11 @@ var relocationTests = []relocationTest{ {Attr: dwarf.AttrName, Val: "hello.c", Class: dwarf.ClassString}, {Attr: dwarf.AttrCompDir, Val: "/tmp", Class: dwarf.ClassString}, {Attr: dwarf.AttrLowpc, Val: uint64(0x0), Class: dwarf.ClassAddress}, - {Attr: dwarf.AttrHighpc, Val: int64(58), Class: dwarf.ClassConstant}, + {Attr: dwarf.AttrHighpc, Val: int64(0x3a), Class: dwarf.ClassConstant}, {Attr: dwarf.AttrStmtList, Val: int64(0), Class: dwarf.ClassLinePtr}, }, }, + pcRanges: [][2]uint64{{0x0, 0x3a}}, }, }, }, @@ -529,6 +540,7 @@ var relocationTests = []relocationTest{ {Attr: dwarf.AttrStmtList, Val: int64(0), Class: dwarf.ClassLinePtr}, }, }, + pcRanges: [][2]uint64{{0x0, 0x2c}}, }, }, }, @@ -550,6 +562,7 @@ var relocationTests = []relocationTest{ {Attr: dwarf.AttrStmtList, Val: int64(0), Class: dwarf.ClassLinePtr}, }, }, + pcRanges: [][2]uint64{{0x0, 0x58}}, }, }, }, @@ -571,6 +584,7 @@ var relocationTests = []relocationTest{ {Attr: dwarf.AttrStmtList, Val: int64(0), Class: dwarf.ClassLinePtr}, }, }, + pcRanges: [][2]uint64{{0x0, 0x5c}}, }, }, }, @@ -588,10 +602,11 @@ var relocationTests = []relocationTest{ {Attr: dwarf.AttrName, Val: "hello.c", Class: dwarf.ClassString}, {Attr: dwarf.AttrCompDir, Val: "/tmp", Class: dwarf.ClassString}, {Attr: dwarf.AttrLowpc, Val: uint64(0x0), Class: dwarf.ClassAddress}, - {Attr: dwarf.AttrHighpc, Val: int64(100), Class: dwarf.ClassConstant}, + {Attr: dwarf.AttrHighpc, Val: int64(0x64), Class: dwarf.ClassConstant}, {Attr: dwarf.AttrStmtList, Val: int64(0), Class: dwarf.ClassLinePtr}, }, }, + pcRanges: [][2]uint64{{0x0, 0x64}}, }, }, }, @@ -613,6 +628,7 @@ var relocationTests = []relocationTest{ {Attr: dwarf.AttrStmtList, Val: int64(0), Class: dwarf.ClassLinePtr}, }, }, + pcRanges: [][2]uint64{{0x0, 0x2c}}, }, }, }, @@ -670,6 +686,56 @@ var relocationTests = []relocationTest{ }, }, }, + { + "testdata/go-relocation-test-gcc930-ranges-no-rela-x86-64", + []relocationTestEntry{ + { + entry: &dwarf.Entry{ + Offset: 0xb, + Tag: dwarf.TagCompileUnit, + Children: true, + Field: []dwarf.Field{ + {Attr: dwarf.AttrProducer, Val: "GNU C17 9.3.0 -mtune=generic -march=x86-64 -g -fno-asynchronous-unwind-tables", Class: dwarf.ClassString}, + {Attr: dwarf.AttrLanguage, Val: int64(12), Class: dwarf.ClassConstant}, + {Attr: dwarf.AttrName, Val: "multiple-code-sections.c", Class: dwarf.ClassString}, + {Attr: dwarf.AttrCompDir, Val: "/tmp", Class: dwarf.ClassString}, + {Attr: dwarf.AttrRanges, Val: int64(0), Class: dwarf.ClassRangeListPtr}, + {Attr: dwarf.AttrLowpc, Val: uint64(0), Class: dwarf.ClassAddress}, + {Attr: dwarf.AttrStmtList, Val: int64(0), Class: dwarf.ClassLinePtr}, + }, + }, + pcRanges: [][2]uint64{ + {0x765, 0x777}, + {0x7e1, 0x7ec}, + }, + }, + }, + }, + { + "testdata/go-relocation-test-gcc930-ranges-with-rela-x86-64", + []relocationTestEntry{ + { + entry: &dwarf.Entry{ + Offset: 0xb, + Tag: dwarf.TagCompileUnit, + Children: true, + Field: []dwarf.Field{ + {Attr: dwarf.AttrProducer, Val: "GNU C17 9.3.0 -mtune=generic -march=x86-64 -g -fno-asynchronous-unwind-tables", Class: dwarf.ClassString}, + {Attr: dwarf.AttrLanguage, Val: int64(12), Class: dwarf.ClassConstant}, + {Attr: dwarf.AttrName, Val: "multiple-code-sections.c", Class: dwarf.ClassString}, + {Attr: dwarf.AttrCompDir, Val: "/tmp", Class: dwarf.ClassString}, + {Attr: dwarf.AttrRanges, Val: int64(0), Class: dwarf.ClassRangeListPtr}, + {Attr: dwarf.AttrLowpc, Val: uint64(0), Class: dwarf.ClassAddress}, + {Attr: dwarf.AttrStmtList, Val: int64(0), Class: dwarf.ClassLinePtr}, + }, + }, + pcRanges: [][2]uint64{ + {0x765, 0x777}, + {0x7e1, 0x7ec}, + }, + }, + }, + }, } func TestDWARFRelocations(t *testing.T) { @@ -705,6 +771,13 @@ func TestDWARFRelocations(t *testing.T) { if !reflect.DeepEqual(testEntry.entry, entry) { t.Errorf("entry %d mismatch: got:%#v want:%#v", testEntry.entryNumber, entry, testEntry.entry) } + pcRanges, err := dwarf.Ranges(entry) + if err != nil { + t.Fatal(err) + } + if !reflect.DeepEqual(testEntry.pcRanges, pcRanges) { + t.Errorf("entry %d: PC range mismatch: got:%#v want:%#v", testEntry.entryNumber, pcRanges, testEntry.pcRanges) + } } }) } diff --git a/src/debug/elf/testdata/go-relocation-test-gcc930-ranges-no-rela-x86-64 b/src/debug/elf/testdata/go-relocation-test-gcc930-ranges-no-rela-x86-64 new file mode 100644 index 0000000000..c013f3e081 Binary files /dev/null and b/src/debug/elf/testdata/go-relocation-test-gcc930-ranges-no-rela-x86-64 differ diff --git a/src/debug/elf/testdata/go-relocation-test-gcc930-ranges-with-rela-x86-64 b/src/debug/elf/testdata/go-relocation-test-gcc930-ranges-with-rela-x86-64 new file mode 100644 index 0000000000..51e03aa7b0 Binary files /dev/null and b/src/debug/elf/testdata/go-relocation-test-gcc930-ranges-with-rela-x86-64 differ diff --git a/src/debug/elf/testdata/multiple-code-sections.c b/src/debug/elf/testdata/multiple-code-sections.c new file mode 100644 index 0000000000..03b9d53ab9 --- /dev/null +++ b/src/debug/elf/testdata/multiple-code-sections.c @@ -0,0 +1,28 @@ +// Copyright 2020 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Build with: +// gcc -g multiple-code-sections.c -Wl,--emit-relocs -Wl,--discard-none -Wl,-zmax-page-size=1 -fno-asynchronous-unwind-tables -o go-relocation-test-gcc930-ranges-with-rela-x86-64 +// gcc -g multiple-code-sections.c -Wl,-zmax-page-size=1 -fno-asynchronous-unwind-tables -o go-relocation-test-gcc930-ranges-no-rela-x86-64 +// Strip with: +// strip --only-keep-debug \ +// --remove-section=.eh_frame \ +// --remove-section=.eh_frame_hdr \ +// --remove-section=.shstrtab \ +// --remove-section=.strtab \ +// --remove-section=.symtab \ +// --remove-section=.note.gnu.build-id \ +// --remove-section=.note.ABI-tag \ +// --remove-section=.dynamic \ +// --remove-section=.gnu.hash \ +// --remove-section=.interp \ +// --remove-section=.rodata +__attribute__((section(".separate_section"))) // To get GCC to emit a DW_AT_ranges attribute for the CU. +int func(void) { + return 0; +} + +int main(int argc, char *argv[]) { + return 0; +}