}
}
-// 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 {
continue
}
sym := &symbols[symNo-1]
- needed, val := relocSymbolTargetOK(sym)
- if !needed {
+ if !canApplyRelocation(sym) {
continue
}
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)
}
}
continue
}
sym := &symbols[symNo-1]
- needed, val := relocSymbolTargetOK(sym)
- if !needed {
+ if !canApplyRelocation(sym) {
continue
}
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)
}
}
continue
}
sym := &symbols[symNo-1]
- needed, val := relocSymbolTargetOK(sym)
- if !needed {
+ if !canApplyRelocation(sym) {
continue
}
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)
}
}
continue
}
sym := &symbols[symNo-1]
- needed, val := relocSymbolTargetOK(sym)
- if !needed {
+ if !canApplyRelocation(sym) {
continue
}
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)
}
}
continue
}
sym := &symbols[symNo-1]
- needed, val := relocSymbolTargetOK(sym)
- if !needed {
+ if !canApplyRelocation(sym) {
continue
}
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)
}
}
continue
}
sym := &symbols[symNo-1]
- needed, val := relocSymbolTargetOK(sym)
- if !needed {
+ if !canApplyRelocation(sym) {
continue
}
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)
}
}
continue
}
sym := &symbols[symNo-1]
- needed, val := relocSymbolTargetOK(sym)
- if !needed {
+ if !canApplyRelocation(sym) {
continue
}
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)
}
}
continue
}
sym := &symbols[symNo-1]
- needed, val := relocSymbolTargetOK(sym)
- if !needed {
+ if !canApplyRelocation(sym) {
continue
}
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)
}
}
type relocationTestEntry struct {
entryNumber int
entry *dwarf.Entry
+ pcRanges [][2]uint64
}
type relocationTest struct {
{Attr: dwarf.AttrStmtList, Val: int64(0), Class: dwarf.ClassLinePtr},
},
},
+ pcRanges: [][2]uint64{{0x0, 0x6}},
},
},
},
{Attr: dwarf.AttrStmtList, Val: int64(0), Class: dwarf.ClassLinePtr},
},
},
+ pcRanges: [][2]uint64{{0x0, 0x5}},
},
},
},
{Attr: dwarf.AttrStmtList, Val: int64(0), Class: dwarf.ClassLinePtr},
},
},
+ pcRanges: [][2]uint64{{0x0, 0x6}},
},
},
},
{Attr: dwarf.AttrStmtList, Val: int64(0), Class: dwarf.ClassLinePtr},
},
},
+ pcRanges: [][2]uint64{{0x0, 0x24}},
},
},
},
{Attr: dwarf.AttrStmtList, Val: int64(0), Class: dwarf.ClassLinePtr},
},
},
+ pcRanges: [][2]uint64{{0x0, 0x28}},
},
},
},
{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}},
},
},
},
{Attr: dwarf.AttrStmtList, Val: int64(0), Class: dwarf.ClassLinePtr},
},
},
+ pcRanges: [][2]uint64{{0x0, 0x44}},
},
},
},
{Attr: dwarf.AttrStmtList, Val: int64(0), Class: dwarf.ClassLinePtr},
},
},
+ pcRanges: [][2]uint64{{0x0, 0x24}},
},
},
},
{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}},
},
},
},
{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}},
},
},
},
{Attr: dwarf.AttrStmtList, Val: int64(0), Class: dwarf.ClassLinePtr},
},
},
+ pcRanges: [][2]uint64{{0x0, 0x2c}},
},
},
},
{Attr: dwarf.AttrStmtList, Val: int64(0), Class: dwarf.ClassLinePtr},
},
},
+ pcRanges: [][2]uint64{{0x0, 0x58}},
},
},
},
{Attr: dwarf.AttrStmtList, Val: int64(0), Class: dwarf.ClassLinePtr},
},
},
+ pcRanges: [][2]uint64{{0x0, 0x5c}},
},
},
},
{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}},
},
},
},
{Attr: dwarf.AttrStmtList, Val: int64(0), Class: dwarf.ClassLinePtr},
},
},
+ pcRanges: [][2]uint64{{0x0, 0x2c}},
},
},
},
},
},
},
+ {
+ "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) {
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)
+ }
}
})
}