fix(elf): relocation records, DWARF tables and per-architecture frame data
Assisted-by: GLM 5.3
This commit is contained in:
+58
-1
@@ -6,6 +6,7 @@ package asm
|
||||
import (
|
||||
"bytes"
|
||||
"debug/elf"
|
||||
"encoding/binary"
|
||||
"testing"
|
||||
|
||||
"sourcedock.dev/petrbalvin/gasm-devkit/parser"
|
||||
@@ -28,6 +29,7 @@ TEXT ·add(SB), NOSPLIT, $0-24
|
||||
|
||||
TEXT ·getanswer(SB), NOSPLIT, $0-8
|
||||
MOVD answer<>(SB), R4
|
||||
MOVD $answer<>(SB), R5
|
||||
MOVD R4, ret+0(FP)
|
||||
RET
|
||||
|
||||
@@ -102,8 +104,63 @@ DATA answer<>+0(SB)/8, $42
|
||||
// Check that .rela.text exists (getanswer has SB reference).
|
||||
relaText := ef.Section(".rela.text")
|
||||
if relaText == nil {
|
||||
t.Error("missing .rela.text section")
|
||||
t.Fatal("missing .rela.text section")
|
||||
}
|
||||
|
||||
// The SB references of getanswer form two ADRP pairs: the load
|
||||
// (MOVD answer<>(SB), R4) is ADRP+LDR carrying HI21 at the ADRP and
|
||||
// LDST64_ABS_LO12_NC at the LDR word, and the address-of
|
||||
// (MOVD $answer<>(SB), R5) is ADRP+ADD carrying HI21 and
|
||||
// ADD_ABS_LO12_NC. cmd/link's own conversion emits exactly this
|
||||
// sectoff / sectoff+4 pairing; a second HI21 at the ADD or LDR word
|
||||
// corrupts the pair.
|
||||
raw, err := relaText.Data()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if len(raw)%24 != 0 || len(raw)/24 != 4 {
|
||||
t.Fatalf(".rela.text has %d bytes, want four 24-byte entries", len(raw))
|
||||
}
|
||||
wantRela := []struct {
|
||||
typ elf.R_AARCH64
|
||||
off uint64 // relative to the getanswer function start
|
||||
}{
|
||||
{elf.R_AARCH64_ADR_PREL_PG_HI21, 0},
|
||||
{elf.R_AARCH64_LDST64_ABS_LO12_NC, 4},
|
||||
{elf.R_AARCH64_ADR_PREL_PG_HI21, 8},
|
||||
{elf.R_AARCH64_ADD_ABS_LO12_NC, 12},
|
||||
}
|
||||
getanswer := byNameElf(t, ef, "getanswer")
|
||||
for i, w := range wantRela {
|
||||
e := raw[i*24 : (i+1)*24]
|
||||
off := binary.LittleEndian.Uint64(e[0:])
|
||||
info := binary.LittleEndian.Uint64(e[8:])
|
||||
typ := elf.R_AARCH64(info & 0xffffffff)
|
||||
sym := int(info >> 32)
|
||||
if typ != w.typ || off != getanswer.Value+w.off {
|
||||
t.Errorf("reloc %d: type %v off %d, want %v at %d", i, typ, off, w.typ, getanswer.Value+w.off)
|
||||
}
|
||||
if sym != 3 { // NULL, .text, .data, then the first local: answer
|
||||
t.Errorf("reloc %d: symbol index %d, want 3 (answer)", i, sym)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// byNameElf returns the symbol table entry for name from the raw .symtab,
|
||||
// which carries every entry including the null and section symbols in order.
|
||||
func byNameElf(t *testing.T, ef *elf.File, name string) elf.Symbol {
|
||||
t.Helper()
|
||||
syms, err := ef.Symbols()
|
||||
if err != nil {
|
||||
t.Fatalf("symbols: %v", err)
|
||||
}
|
||||
for _, s := range syms {
|
||||
if s.Name == name {
|
||||
return s
|
||||
}
|
||||
}
|
||||
t.Fatalf("symbol %q not found", name)
|
||||
return elf.Symbol{}
|
||||
}
|
||||
|
||||
// TestELFAARCH64ObjectNoRelocations checks the ELF output when there are no
|
||||
|
||||
Reference in New Issue
Block a user