Commit df855da6 authored by Than McIntosh's avatar Than McIntosh

debug/elf: apply more relocations when reading DWARF data sections

The elf reader's method for reading in DWARF section data has support
for applying selected relocations when the debug/dwarf readers are
being used on relocatable objects. This patch extends the set of
relocations applied slightly. In particlar, prior to this for some
architectures we were only applying relocations whose target symbol
was a section symbol; now we also include some relocations that target
other symbols. This is needed to get meaningful values for compilation
unit DIE low_pc attributes, which typically target a specific function
symbol in text.

Fixes #31363.

Change-Id: I34b02e7904cd7f2dea74197f73fa648141d15212
Reviewed-on: https://go-review.googlesource.com/c/go/+/195679Reviewed-by: default avatarIan Lance Taylor <iant@golang.org>
parent 7d16e44d
...@@ -167,7 +167,7 @@ func testDWARF(t *testing.T, buildmode string, expectDWARF bool, env ...string) ...@@ -167,7 +167,7 @@ func testDWARF(t *testing.T, buildmode string, expectDWARF bool, env ...string)
func TestDWARF(t *testing.T) { func TestDWARF(t *testing.T) {
testDWARF(t, "", true) testDWARF(t, "", true)
if runtime.GOOS == "darwin" && !testing.Short() { if !testing.Short() {
t.Run("c-archive", func(t *testing.T) { t.Run("c-archive", func(t *testing.T) {
testDWARF(t, "c-archive", true) testDWARF(t, "c-archive", true)
}) })
......
...@@ -628,6 +628,25 @@ func (f *File) applyRelocations(dst []byte, rels []byte) error { ...@@ -628,6 +628,25 @@ func (f *File) applyRelocations(dst []byte, rels []byte) error {
} }
} }
// relocSymbolTargetOK decides 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
}
func (f *File) applyRelocationsAMD64(dst []byte, rels []byte) error { func (f *File) applyRelocationsAMD64(dst []byte, rels []byte) error {
// 24 is the size of Rela64. // 24 is the size of Rela64.
if len(rels)%24 != 0 { if len(rels)%24 != 0 {
...@@ -651,26 +670,28 @@ func (f *File) applyRelocationsAMD64(dst []byte, rels []byte) error { ...@@ -651,26 +670,28 @@ func (f *File) applyRelocationsAMD64(dst []byte, rels []byte) error {
continue continue
} }
sym := &symbols[symNo-1] sym := &symbols[symNo-1]
if SymType(sym.Info&0xf) != STT_SECTION { needed, val := relocSymbolTargetOK(sym)
// We don't handle non-section relocations for now. if !needed {
continue continue
} }
// There are relocations, so this must be a normal // There are relocations, so this must be a normal
// object file, and we only look at section symbols, // object file. The code below handles only basic relocations
// so we assume that the symbol value is 0. // of the form S + A (symbol plus addend).
switch t { switch t {
case R_X86_64_64: case R_X86_64_64:
if rela.Off+8 >= uint64(len(dst)) || rela.Addend < 0 { if rela.Off+8 >= uint64(len(dst)) || rela.Addend < 0 {
continue continue
} }
f.ByteOrder.PutUint64(dst[rela.Off:rela.Off+8], uint64(rela.Addend)) val64 := val + uint64(rela.Addend)
f.ByteOrder.PutUint64(dst[rela.Off:rela.Off+8], val64)
case R_X86_64_32: case R_X86_64_32:
if rela.Off+4 >= uint64(len(dst)) || rela.Addend < 0 { if rela.Off+4 >= uint64(len(dst)) || rela.Addend < 0 {
continue continue
} }
f.ByteOrder.PutUint32(dst[rela.Off:rela.Off+4], uint32(rela.Addend)) val32 := uint32(val) + uint32(rela.Addend)
f.ByteOrder.PutUint32(dst[rela.Off:rela.Off+4], val32)
} }
} }
...@@ -775,26 +796,28 @@ func (f *File) applyRelocationsARM64(dst []byte, rels []byte) error { ...@@ -775,26 +796,28 @@ func (f *File) applyRelocationsARM64(dst []byte, rels []byte) error {
continue continue
} }
sym := &symbols[symNo-1] sym := &symbols[symNo-1]
if SymType(sym.Info&0xf) != STT_SECTION { needed, val := relocSymbolTargetOK(sym)
// We don't handle non-section relocations for now. if !needed {
continue continue
} }
// There are relocations, so this must be a normal // There are relocations, so this must be a normal
// object file, and we only look at section symbols, // object file. The code below handles only basic relocations
// so we assume that the symbol value is 0. // of the form S + A (symbol plus addend).
switch t { switch t {
case R_AARCH64_ABS64: case R_AARCH64_ABS64:
if rela.Off+8 >= uint64(len(dst)) || rela.Addend < 0 { if rela.Off+8 >= uint64(len(dst)) || rela.Addend < 0 {
continue continue
} }
f.ByteOrder.PutUint64(dst[rela.Off:rela.Off+8], uint64(rela.Addend)) val64 := uint64(val) + uint64(rela.Addend)
f.ByteOrder.PutUint64(dst[rela.Off:rela.Off+8], val64)
case R_AARCH64_ABS32: case R_AARCH64_ABS32:
if rela.Off+4 >= uint64(len(dst)) || rela.Addend < 0 { if rela.Off+4 >= uint64(len(dst)) || rela.Addend < 0 {
continue continue
} }
f.ByteOrder.PutUint32(dst[rela.Off:rela.Off+4], uint32(rela.Addend)) val32 := uint32(val) + uint32(rela.Addend)
f.ByteOrder.PutUint32(dst[rela.Off:rela.Off+4], val32)
} }
} }
...@@ -824,8 +847,8 @@ func (f *File) applyRelocationsPPC(dst []byte, rels []byte) error { ...@@ -824,8 +847,8 @@ func (f *File) applyRelocationsPPC(dst []byte, rels []byte) error {
continue continue
} }
sym := &symbols[symNo-1] sym := &symbols[symNo-1]
if SymType(sym.Info&0xf) != STT_SECTION { needed, val := relocSymbolTargetOK(sym)
// We don't handle non-section relocations for now. if !needed {
continue continue
} }
...@@ -834,7 +857,8 @@ func (f *File) applyRelocationsPPC(dst []byte, rels []byte) error { ...@@ -834,7 +857,8 @@ func (f *File) applyRelocationsPPC(dst []byte, rels []byte) error {
if rela.Off+4 >= uint32(len(dst)) || rela.Addend < 0 { if rela.Off+4 >= uint32(len(dst)) || rela.Addend < 0 {
continue continue
} }
f.ByteOrder.PutUint32(dst[rela.Off:rela.Off+4], uint32(rela.Addend)) val32 := uint32(val) + uint32(rela.Addend)
f.ByteOrder.PutUint32(dst[rela.Off:rela.Off+4], val32)
} }
} }
...@@ -864,8 +888,8 @@ func (f *File) applyRelocationsPPC64(dst []byte, rels []byte) error { ...@@ -864,8 +888,8 @@ func (f *File) applyRelocationsPPC64(dst []byte, rels []byte) error {
continue continue
} }
sym := &symbols[symNo-1] sym := &symbols[symNo-1]
if SymType(sym.Info&0xf) != STT_SECTION { needed, val := relocSymbolTargetOK(sym)
// We don't handle non-section relocations for now. if !needed {
continue continue
} }
...@@ -874,12 +898,14 @@ func (f *File) applyRelocationsPPC64(dst []byte, rels []byte) error { ...@@ -874,12 +898,14 @@ func (f *File) applyRelocationsPPC64(dst []byte, rels []byte) error {
if rela.Off+8 >= uint64(len(dst)) || rela.Addend < 0 { if rela.Off+8 >= uint64(len(dst)) || rela.Addend < 0 {
continue continue
} }
f.ByteOrder.PutUint64(dst[rela.Off:rela.Off+8], uint64(rela.Addend)) val64 := val + uint64(rela.Addend)
f.ByteOrder.PutUint64(dst[rela.Off:rela.Off+8], val64)
case R_PPC64_ADDR32: case R_PPC64_ADDR32:
if rela.Off+4 >= uint64(len(dst)) || rela.Addend < 0 { if rela.Off+4 >= uint64(len(dst)) || rela.Addend < 0 {
continue continue
} }
f.ByteOrder.PutUint32(dst[rela.Off:rela.Off+4], uint32(rela.Addend)) val32 := uint32(val) + uint32(rela.Addend)
f.ByteOrder.PutUint32(dst[rela.Off:rela.Off+4], val32)
} }
} }
...@@ -954,8 +980,8 @@ func (f *File) applyRelocationsMIPS64(dst []byte, rels []byte) error { ...@@ -954,8 +980,8 @@ func (f *File) applyRelocationsMIPS64(dst []byte, rels []byte) error {
continue continue
} }
sym := &symbols[symNo-1] sym := &symbols[symNo-1]
if SymType(sym.Info&0xf) != STT_SECTION { needed, val := relocSymbolTargetOK(sym)
// We don't handle non-section relocations for now. if !needed {
continue continue
} }
...@@ -964,12 +990,14 @@ func (f *File) applyRelocationsMIPS64(dst []byte, rels []byte) error { ...@@ -964,12 +990,14 @@ func (f *File) applyRelocationsMIPS64(dst []byte, rels []byte) error {
if rela.Off+8 >= uint64(len(dst)) || rela.Addend < 0 { if rela.Off+8 >= uint64(len(dst)) || rela.Addend < 0 {
continue continue
} }
f.ByteOrder.PutUint64(dst[rela.Off:rela.Off+8], uint64(rela.Addend)) val64 := val + uint64(rela.Addend)
f.ByteOrder.PutUint64(dst[rela.Off:rela.Off+8], val64)
case R_MIPS_32: case R_MIPS_32:
if rela.Off+4 >= uint64(len(dst)) || rela.Addend < 0 { if rela.Off+4 >= uint64(len(dst)) || rela.Addend < 0 {
continue continue
} }
f.ByteOrder.PutUint32(dst[rela.Off:rela.Off+4], uint32(rela.Addend)) val32 := uint32(val) + uint32(rela.Addend)
f.ByteOrder.PutUint32(dst[rela.Off:rela.Off+4], val32)
} }
} }
...@@ -999,10 +1027,8 @@ func (f *File) applyRelocationsRISCV64(dst []byte, rels []byte) error { ...@@ -999,10 +1027,8 @@ func (f *File) applyRelocationsRISCV64(dst []byte, rels []byte) error {
continue continue
} }
sym := &symbols[symNo-1] sym := &symbols[symNo-1]
switch SymType(sym.Info & 0xf) { needed, val := relocSymbolTargetOK(sym)
case STT_SECTION, STT_NOTYPE: if !needed {
break
default:
continue continue
} }
...@@ -1011,14 +1037,14 @@ func (f *File) applyRelocationsRISCV64(dst []byte, rels []byte) error { ...@@ -1011,14 +1037,14 @@ func (f *File) applyRelocationsRISCV64(dst []byte, rels []byte) error {
if rela.Off+8 >= uint64(len(dst)) || rela.Addend < 0 { if rela.Off+8 >= uint64(len(dst)) || rela.Addend < 0 {
continue continue
} }
val := sym.Value + uint64(rela.Addend) val64 := val + uint64(rela.Addend)
f.ByteOrder.PutUint64(dst[rela.Off:rela.Off+8], val) f.ByteOrder.PutUint64(dst[rela.Off:rela.Off+8], val64)
case R_RISCV_32: case R_RISCV_32:
if rela.Off+4 >= uint64(len(dst)) || rela.Addend < 0 { if rela.Off+4 >= uint64(len(dst)) || rela.Addend < 0 {
continue continue
} }
val := uint32(sym.Value) + uint32(rela.Addend) val32 := uint32(val) + uint32(rela.Addend)
f.ByteOrder.PutUint32(dst[rela.Off:rela.Off+4], val) f.ByteOrder.PutUint32(dst[rela.Off:rela.Off+4], val32)
} }
} }
...@@ -1048,10 +1074,8 @@ func (f *File) applyRelocationss390x(dst []byte, rels []byte) error { ...@@ -1048,10 +1074,8 @@ func (f *File) applyRelocationss390x(dst []byte, rels []byte) error {
continue continue
} }
sym := &symbols[symNo-1] sym := &symbols[symNo-1]
switch SymType(sym.Info & 0xf) { needed, val := relocSymbolTargetOK(sym)
case STT_SECTION, STT_NOTYPE: if !needed {
break
default:
continue continue
} }
...@@ -1060,14 +1084,14 @@ func (f *File) applyRelocationss390x(dst []byte, rels []byte) error { ...@@ -1060,14 +1084,14 @@ func (f *File) applyRelocationss390x(dst []byte, rels []byte) error {
if rela.Off+8 >= uint64(len(dst)) || rela.Addend < 0 { if rela.Off+8 >= uint64(len(dst)) || rela.Addend < 0 {
continue continue
} }
val := sym.Value + uint64(rela.Addend) val64 := val + uint64(rela.Addend)
f.ByteOrder.PutUint64(dst[rela.Off:rela.Off+8], val) f.ByteOrder.PutUint64(dst[rela.Off:rela.Off+8], val64)
case R_390_32: case R_390_32:
if rela.Off+4 >= uint64(len(dst)) || rela.Addend < 0 { if rela.Off+4 >= uint64(len(dst)) || rela.Addend < 0 {
continue continue
} }
val := uint32(sym.Value) + uint32(rela.Addend) val32 := uint32(val) + uint32(rela.Addend)
f.ByteOrder.PutUint32(dst[rela.Off:rela.Off+4], val) f.ByteOrder.PutUint32(dst[rela.Off:rela.Off+4], val32)
} }
} }
...@@ -1097,8 +1121,8 @@ func (f *File) applyRelocationsSPARC64(dst []byte, rels []byte) error { ...@@ -1097,8 +1121,8 @@ func (f *File) applyRelocationsSPARC64(dst []byte, rels []byte) error {
continue continue
} }
sym := &symbols[symNo-1] sym := &symbols[symNo-1]
if SymType(sym.Info&0xf) != STT_SECTION { needed, val := relocSymbolTargetOK(sym)
// We don't handle non-section relocations for now. if !needed {
continue continue
} }
...@@ -1107,12 +1131,14 @@ func (f *File) applyRelocationsSPARC64(dst []byte, rels []byte) error { ...@@ -1107,12 +1131,14 @@ func (f *File) applyRelocationsSPARC64(dst []byte, rels []byte) error {
if rela.Off+8 >= uint64(len(dst)) || rela.Addend < 0 { if rela.Off+8 >= uint64(len(dst)) || rela.Addend < 0 {
continue continue
} }
f.ByteOrder.PutUint64(dst[rela.Off:rela.Off+8], uint64(rela.Addend)) val64 := val + uint64(rela.Addend)
f.ByteOrder.PutUint64(dst[rela.Off:rela.Off+8], val64)
case R_SPARC_32, R_SPARC_UA32: case R_SPARC_32, R_SPARC_UA32:
if rela.Off+4 >= uint64(len(dst)) || rela.Addend < 0 { if rela.Off+4 >= uint64(len(dst)) || rela.Addend < 0 {
continue continue
} }
f.ByteOrder.PutUint32(dst[rela.Off:rela.Off+4], uint32(rela.Addend)) val32 := uint32(val) + uint32(rela.Addend)
f.ByteOrder.PutUint32(dst[rela.Off:rela.Off+4], val32)
} }
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment