2026-08-21 00:14:02 +02:00
|
|
|
// Copyright (c) 2026 Petr Balvín <opensource@petrbalvin.org> (https://petrbalvin.org)
|
|
|
|
|
// SPDX-License-Identifier: BSD-3-Clause
|
|
|
|
|
|
|
|
|
|
package asm
|
|
|
|
|
|
|
|
|
|
// dwarfELFSections holds the laid-out DWARF sections ready for inclusion
|
|
|
|
|
// in an ELF file.
|
|
|
|
|
type dwarfELFSections struct {
|
|
|
|
|
abbrevOff, abbrevSize int
|
|
|
|
|
infoOff, infoSize int
|
|
|
|
|
lineOff, lineSize int
|
|
|
|
|
lineStrOff, lineStrSize int
|
2026-08-21 01:06:21 +02:00
|
|
|
frameOff, frameSize int
|
2026-08-21 00:14:02 +02:00
|
|
|
// Relocations for .debug_info address references.
|
|
|
|
|
infoRelocs []elfDwarfReloc
|
|
|
|
|
// Relocations for .debug_line address references.
|
|
|
|
|
lineRelocs []elfDwarfReloc
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
type elfDwarfReloc struct {
|
|
|
|
|
off uint64
|
|
|
|
|
sym int // symbol index in .symtab
|
|
|
|
|
addend int64
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// appendDWARFSections generates and appends DWARF5 debug sections to the ELF
|
|
|
|
|
// output. It returns the section offsets/sizes and relocations for the caller
|
|
|
|
|
// to emit section headers and relocation records.
|
|
|
|
|
//
|
|
|
|
|
// symIdx maps function names to their .symtab indices (needed for relocations
|
|
|
|
|
// against .text symbols). The map uses objectName format (pkg.name); the
|
|
|
|
|
// DWARF code uses bare function names, so we build a reverse lookup.
|
|
|
|
|
func appendDWARFSections(out *[]byte, img *Image, srcFile string, symIdx map[string]int, align func(int)) *dwarfELFSections {
|
|
|
|
|
// Build a lookup from bare function name to symbol index.
|
|
|
|
|
nameToIdx := make(map[string]int, len(symIdx))
|
|
|
|
|
for name, idx := range symIdx {
|
|
|
|
|
// Strip package prefix: "pkg.name" → "name".
|
|
|
|
|
if i := len(name) - 1; i >= 0 {
|
|
|
|
|
for j := len(name) - 1; j >= 0; j-- {
|
|
|
|
|
if name[j] == '.' {
|
|
|
|
|
nameToIdx[name[j+1:]] = idx
|
|
|
|
|
break
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
nameToIdx[name] = idx
|
|
|
|
|
}
|
|
|
|
|
ds := emitDWARF(img, srcFile)
|
|
|
|
|
if ds == nil || len(ds.debugAbbrev) == 0 {
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
result := &dwarfELFSections{}
|
|
|
|
|
|
|
|
|
|
// .debug_abbrev
|
|
|
|
|
align(1)
|
|
|
|
|
result.abbrevOff = len(*out)
|
|
|
|
|
result.abbrevSize = len(ds.debugAbbrev)
|
|
|
|
|
*out = append(*out, ds.debugAbbrev...)
|
|
|
|
|
|
|
|
|
|
// .debug_line_str
|
|
|
|
|
align(1)
|
|
|
|
|
result.lineStrOff = len(*out)
|
|
|
|
|
result.lineStrSize = len(ds.debugLineStr)
|
|
|
|
|
*out = append(*out, ds.debugLineStr...)
|
|
|
|
|
|
|
|
|
|
// .debug_line
|
|
|
|
|
align(1)
|
|
|
|
|
result.lineOff = len(*out)
|
|
|
|
|
result.lineSize = len(ds.debugLine)
|
|
|
|
|
lineBase := len(*out)
|
|
|
|
|
*out = append(*out, ds.debugLine...)
|
|
|
|
|
|
|
|
|
|
// Patch .debug_line relocations: replace placeholder addresses with
|
|
|
|
|
// actual .text offsets via symbol lookup.
|
|
|
|
|
for _, dr := range ds.lineRelocs {
|
|
|
|
|
if idx, ok := nameToIdx[dr.name]; ok {
|
|
|
|
|
result.lineRelocs = append(result.lineRelocs, elfDwarfReloc{
|
|
|
|
|
off: uint64(lineBase) + dr.off,
|
|
|
|
|
sym: idx,
|
|
|
|
|
addend: dr.addend,
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// .debug_info
|
|
|
|
|
align(1)
|
|
|
|
|
result.infoOff = len(*out)
|
|
|
|
|
result.infoSize = len(ds.debugInfo)
|
|
|
|
|
infoBase := len(*out)
|
|
|
|
|
*out = append(*out, ds.debugInfo...)
|
|
|
|
|
|
2026-08-21 01:06:21 +02:00
|
|
|
// .debug_frame
|
|
|
|
|
if len(ds.debugFrame) > 0 {
|
|
|
|
|
align(1)
|
|
|
|
|
result.frameOff = len(*out)
|
|
|
|
|
result.frameSize = len(ds.debugFrame)
|
|
|
|
|
*out = append(*out, ds.debugFrame...)
|
|
|
|
|
}
|
|
|
|
|
|
2026-08-21 00:14:02 +02:00
|
|
|
// Patch .debug_info relocations.
|
|
|
|
|
for _, dr := range ds.infoRelocs {
|
|
|
|
|
if idx, ok := nameToIdx[dr.name]; ok {
|
|
|
|
|
result.infoRelocs = append(result.infoRelocs, elfDwarfReloc{
|
|
|
|
|
off: uint64(infoBase) + dr.off,
|
|
|
|
|
sym: idx,
|
|
|
|
|
addend: dr.addend,
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return result
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// dwarfSectionNames returns the DWARF section names for the string table.
|
|
|
|
|
var dwarfSectionNames = []string{
|
|
|
|
|
".debug_abbrev", ".debug_info", ".debug_line", ".debug_line_str",
|
2026-08-21 01:06:21 +02:00
|
|
|
".debug_frame", ".rela.debug_info", ".rela.debug_line",
|
2026-08-21 00:14:02 +02:00
|
|
|
}
|