feat(asm): add RISC-V ELF relocatable object emission and SB relocation
support
This commit is contained in:
+47
-3
@@ -85,12 +85,24 @@ func (fl *FuncLayout) LineAt(offset int) int {
|
||||
// measured from After, the address just past the instruction. An External
|
||||
// relocation names a symbol no GLOBL in the file defines; the object-file
|
||||
// emitters carry it into the output's relocation table.
|
||||
// RelocKind discriminates the type of relocation needed.
|
||||
type RelocKind int
|
||||
|
||||
const (
|
||||
RelPCRel32 RelocKind = iota // 32-bit PC-relative (amd64)
|
||||
RelPCRelHI20 // R_RISCV_PCREL_HI20 (AUIPC)
|
||||
RelPCRelLO12 // R_RISCV_PCREL_LO12_I (ADDI, LD)
|
||||
RelPCRelLO12S // R_RISCV_PCREL_LO12_S (SD)
|
||||
RelPCRelAbs // 32-bit absolute (R_RISCV_32)
|
||||
)
|
||||
|
||||
type Reloc struct {
|
||||
Off int
|
||||
After int
|
||||
Name string
|
||||
Addend int64
|
||||
External bool
|
||||
Kind RelocKind
|
||||
}
|
||||
|
||||
// DataSymbol describes one GLOBL symbol laid out in the data section.
|
||||
@@ -220,16 +232,23 @@ func AssembleFile(f *ast.File) (*Image, error) {
|
||||
return img, nil
|
||||
}
|
||||
|
||||
// AssembleFileRISCV assembles every TEXT function of a parsed RISC-V file.
|
||||
// It produces an Image with the function bodies laid out in source order.
|
||||
// AssembleFileRISCV assembles every TEXT function of a parsed RISC-V file
|
||||
// and lays out its static symbols (GLOBL/DATA) in a data section behind the
|
||||
// code. SB references in the code are encoded as AUIPC pairs with zero
|
||||
// immediates; the object-file emitters record relocations for the linker.
|
||||
func AssembleFileRISCV(f *ast.File) (*Image, error) {
|
||||
dataSyms, err := collectData(f)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
img := &Image{Symbols: map[string]int{}}
|
||||
for _, d := range f.Decls {
|
||||
t, ok := d.(*ast.Text)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
code, labels, err := assembleRISCV(t)
|
||||
code, labels, relocs, err := assembleRISCV(t)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%s: %w", t.Name.Name, err)
|
||||
}
|
||||
@@ -243,6 +262,7 @@ func AssembleFileRISCV(f *ast.File) (*Image, error) {
|
||||
Args: argsSize(t),
|
||||
Line: t.Pos().Line,
|
||||
Labels: labels,
|
||||
Relocs: relocs,
|
||||
}
|
||||
for _, f := range t.Flags {
|
||||
switch f {
|
||||
@@ -255,6 +275,28 @@ func AssembleFileRISCV(f *ast.File) (*Image, error) {
|
||||
img.Funcs = append(img.Funcs, fl)
|
||||
img.Code = append(img.Code, code...)
|
||||
}
|
||||
|
||||
// Lay out the data section behind the code, 16-aligned.
|
||||
dataStart := len(img.Code)
|
||||
for _, d := range dataSyms {
|
||||
pos := dataStart + len(img.Data)
|
||||
for pos%16 != 0 {
|
||||
img.Data = append(img.Data, 0)
|
||||
pos++
|
||||
}
|
||||
img.Symbols[d.name] = pos
|
||||
img.Data = append(img.Data, d.buf...)
|
||||
img.DataSyms = append(img.DataSyms, DataSymbol{
|
||||
Name: d.name,
|
||||
Pkg: d.pkg,
|
||||
Offset: pos,
|
||||
Size: d.size,
|
||||
Static: d.static,
|
||||
Rodata: d.rodata,
|
||||
Dupok: d.dupok,
|
||||
})
|
||||
}
|
||||
|
||||
return img, nil
|
||||
}
|
||||
|
||||
@@ -263,6 +305,7 @@ type dataSym struct {
|
||||
name string
|
||||
pkg string
|
||||
buf []byte
|
||||
size int
|
||||
static bool
|
||||
rodata bool
|
||||
dupok bool
|
||||
@@ -292,6 +335,7 @@ func collectData(f *ast.File) ([]dataSym, error) {
|
||||
name: name,
|
||||
pkg: dd.Name.Pkg,
|
||||
buf: make([]byte, size),
|
||||
size: size,
|
||||
static: dd.Name.Static,
|
||||
}
|
||||
for _, f := range dd.Flags {
|
||||
|
||||
Reference in New Issue
Block a user