compiler: account for alignment with -size=full

Этот коммит содержится в:
Ayke van Laethem 2023-03-06 01:54:12 +01:00 коммит произвёл Ron Evans
родитель 0463d34887
коммит 3701e6eac1

Просмотреть файл

@ -75,6 +75,7 @@ func (ps *packageSize) RAM() uint64 {
type addressLine struct { type addressLine struct {
Address uint64 Address uint64
Length uint64 // length of this chunk Length uint64 // length of this chunk
Align uint64 // (maximum) alignment of this line
File string // file path as stored in DWARF File string // file path as stored in DWARF
IsVariable bool // true if this is a variable (or constant), false if it is code IsVariable bool // true if this is a variable (or constant), false if it is code
} }
@ -86,6 +87,7 @@ type memorySection struct {
Type memoryType Type memoryType
Address uint64 Address uint64
Size uint64 Size uint64
Align uint64
} }
type memoryType int type memoryType int
@ -123,7 +125,7 @@ var (
// readProgramSizeFromDWARF reads the source location for each line of code and // readProgramSizeFromDWARF reads the source location for each line of code and
// each variable in the program, as far as this is stored in the DWARF debug // each variable in the program, as far as this is stored in the DWARF debug
// information. // information.
func readProgramSizeFromDWARF(data *dwarf.Data, codeOffset uint64, skipTombstone bool) ([]addressLine, error) { func readProgramSizeFromDWARF(data *dwarf.Data, codeOffset, codeAlignment uint64, skipTombstone bool) ([]addressLine, error) {
r := data.Reader() r := data.Reader()
var lines []*dwarf.LineFile var lines []*dwarf.LineFile
var addresses []addressLine var addresses []addressLine
@ -195,6 +197,7 @@ func readProgramSizeFromDWARF(data *dwarf.Data, codeOffset uint64, skipTombstone
line := addressLine{ line := addressLine{
Address: prevLineEntry.Address + codeOffset, Address: prevLineEntry.Address + codeOffset,
Length: lineEntry.Address - prevLineEntry.Address, Length: lineEntry.Address - prevLineEntry.Address,
Align: codeAlignment,
File: prevLineEntry.File.Name, File: prevLineEntry.File.Name,
} }
if line.Length != 0 { if line.Length != 0 {
@ -232,9 +235,16 @@ func readProgramSizeFromDWARF(data *dwarf.Data, codeOffset uint64, skipTombstone
return nil, err return nil, err
} }
// Read alignment, if it's stored as part of the debug information.
var alignment uint64
if attr := e.AttrField(dwarf.AttrAlignment); attr != nil {
alignment = uint64(attr.Val.(int64))
}
addresses = append(addresses, addressLine{ addresses = append(addresses, addressLine{
Address: addr, Address: addr,
Length: uint64(typ.Size()), Length: uint64(typ.Size()),
Align: alignment,
File: lines[file.Val.(int64)].Name, File: lines[file.Val.(int64)].Name,
IsVariable: true, IsVariable: true,
}) })
@ -312,7 +322,7 @@ func readMachOSymbolAddresses(path string) (map[string]int, []addressLine, error
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
lines, err := readProgramSizeFromDWARF(dwarf, 0, false) lines, err := readProgramSizeFromDWARF(dwarf, 0, 0, false)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
@ -369,10 +379,15 @@ func loadProgramSize(path string, packagePathMap map[string]string) (*programSiz
// Load the binary file, which could be in a number of file formats. // Load the binary file, which could be in a number of file formats.
var sections []memorySection var sections []memorySection
if file, err := elf.NewFile(f); err == nil { if file, err := elf.NewFile(f); err == nil {
var codeAlignment uint64
switch file.Machine {
case elf.EM_ARM:
codeAlignment = 4 // usually 2, but can be 4
}
// Read DWARF information. The error is intentionally ignored. // Read DWARF information. The error is intentionally ignored.
data, _ := file.DWARF() data, _ := file.DWARF()
if data != nil { if data != nil {
addresses, err = readProgramSizeFromDWARF(data, 0, true) addresses, err = readProgramSizeFromDWARF(data, 0, codeAlignment, true)
if err != nil { if err != nil {
// However, _do_ report an error here. Something must have gone // However, _do_ report an error here. Something must have gone
// wrong while trying to parse DWARF data. // wrong while trying to parse DWARF data.
@ -430,6 +445,7 @@ func loadProgramSize(path string, packagePathMap map[string]string) (*programSiz
sections = append(sections, memorySection{ sections = append(sections, memorySection{
Address: section.Addr, Address: section.Addr,
Size: section.Size, Size: section.Size,
Align: section.Addralign,
Type: memoryStack, Type: memoryStack,
}) })
} else { } else {
@ -437,6 +453,7 @@ func loadProgramSize(path string, packagePathMap map[string]string) (*programSiz
sections = append(sections, memorySection{ sections = append(sections, memorySection{
Address: section.Addr, Address: section.Addr,
Size: section.Size, Size: section.Size,
Align: section.Addralign,
Type: memoryBSS, Type: memoryBSS,
}) })
} }
@ -445,6 +462,7 @@ func loadProgramSize(path string, packagePathMap map[string]string) (*programSiz
sections = append(sections, memorySection{ sections = append(sections, memorySection{
Address: section.Addr, Address: section.Addr,
Size: section.Size, Size: section.Size,
Align: section.Addralign,
Type: memoryCode, Type: memoryCode,
}) })
} else if section.Type == elf.SHT_PROGBITS && section.Flags&elf.SHF_WRITE != 0 { } else if section.Type == elf.SHT_PROGBITS && section.Flags&elf.SHF_WRITE != 0 {
@ -452,6 +470,7 @@ func loadProgramSize(path string, packagePathMap map[string]string) (*programSiz
sections = append(sections, memorySection{ sections = append(sections, memorySection{
Address: section.Addr, Address: section.Addr,
Size: section.Size, Size: section.Size,
Align: section.Addralign,
Type: memoryData, Type: memoryData,
}) })
} else if section.Type == elf.SHT_PROGBITS { } else if section.Type == elf.SHT_PROGBITS {
@ -459,6 +478,7 @@ func loadProgramSize(path string, packagePathMap map[string]string) (*programSiz
sections = append(sections, memorySection{ sections = append(sections, memorySection{
Address: section.Addr, Address: section.Addr,
Size: section.Size, Size: section.Size,
Align: section.Addralign,
Type: memoryROData, Type: memoryROData,
}) })
} }
@ -485,6 +505,7 @@ func loadProgramSize(path string, packagePathMap map[string]string) (*programSiz
sections = append(sections, memorySection{ sections = append(sections, memorySection{
Address: section.Addr, Address: section.Addr,
Size: uint64(section.Size), Size: uint64(section.Size),
Align: uint64(section.Align),
Type: memoryCode, Type: memoryCode,
}) })
} else if sectionType == 1 { // S_ZEROFILL } else if sectionType == 1 { // S_ZEROFILL
@ -492,6 +513,7 @@ func loadProgramSize(path string, packagePathMap map[string]string) (*programSiz
sections = append(sections, memorySection{ sections = append(sections, memorySection{
Address: section.Addr, Address: section.Addr,
Size: uint64(section.Size), Size: uint64(section.Size),
Align: uint64(section.Align),
Type: memoryBSS, Type: memoryBSS,
}) })
} else if segment.Maxprot&0b011 == 0b001 { // --r (read-only data) } else if segment.Maxprot&0b011 == 0b001 { // --r (read-only data)
@ -499,6 +521,7 @@ func loadProgramSize(path string, packagePathMap map[string]string) (*programSiz
sections = append(sections, memorySection{ sections = append(sections, memorySection{
Address: section.Addr, Address: section.Addr,
Size: uint64(section.Size), Size: uint64(section.Size),
Align: uint64(section.Align),
Type: memoryROData, Type: memoryROData,
}) })
} else { } else {
@ -506,6 +529,7 @@ func loadProgramSize(path string, packagePathMap map[string]string) (*programSiz
sections = append(sections, memorySection{ sections = append(sections, memorySection{
Address: section.Addr, Address: section.Addr,
Size: uint64(section.Size), Size: uint64(section.Size),
Align: uint64(section.Align),
Type: memoryData, Type: memoryData,
}) })
} }
@ -589,7 +613,7 @@ func loadProgramSize(path string, packagePathMap map[string]string) (*programSiz
// Read DWARF information. The error is intentionally ignored. // Read DWARF information. The error is intentionally ignored.
data, _ := file.DWARF() data, _ := file.DWARF()
if data != nil { if data != nil {
addresses, err = readProgramSizeFromDWARF(data, 0, true) addresses, err = readProgramSizeFromDWARF(data, 0, 0, true)
if err != nil { if err != nil {
// However, _do_ report an error here. Something must have gone // However, _do_ report an error here. Something must have gone
// wrong while trying to parse DWARF data. // wrong while trying to parse DWARF data.
@ -661,7 +685,7 @@ func loadProgramSize(path string, packagePathMap map[string]string) (*programSiz
// Read DWARF information. The error is intentionally ignored. // Read DWARF information. The error is intentionally ignored.
data, _ := file.DWARF() data, _ := file.DWARF()
if data != nil { if data != nil {
addresses, err = readProgramSizeFromDWARF(data, codeOffset, true) addresses, err = readProgramSizeFromDWARF(data, codeOffset, 0, true)
if err != nil { if err != nil {
// However, _do_ report an error here. Something must have gone // However, _do_ report an error here. Something must have gone
// wrong while trying to parse DWARF data. // wrong while trying to parse DWARF data.
@ -821,10 +845,18 @@ func readSection(section memorySection, addresses []addressLine, addSize func(st
if addr < line.Address { if addr < line.Address {
// There is a gap: there is a space between the current and the // There is a gap: there is a space between the current and the
// previous line entry. // previous line entry.
addSize("(unknown)", line.Address-addr, false) // Check whether this is caused by alignment requirements.
if sizesDebug { addrAligned := (addr + line.Align - 1) &^ (line.Align - 1)
fmt.Printf("%08x..%08x %5d: unknown (gap)\n", addr, line.Address, line.Address-addr) if line.Align > 1 && addrAligned >= line.Address {
// It is, assume that's what causes the gap.
addSize("(padding)", line.Address-addr, true)
} else {
addSize("(unknown)", line.Address-addr, false)
if sizesDebug {
fmt.Printf("%08x..%08x %5d: unknown (gap), alignment=%d\n", addr, line.Address, line.Address-addr, line.Align)
}
} }
addr = line.Address
} }
if addr > line.Address+line.Length { if addr > line.Address+line.Length {
// The current line is already covered by a previous line entry. // The current line is already covered by a previous line entry.
@ -846,9 +878,16 @@ func readSection(section memorySection, addresses []addressLine, addSize func(st
} }
if addr < sectionEnd { if addr < sectionEnd {
// There is a gap at the end of the section. // There is a gap at the end of the section.
addSize("(unknown)", sectionEnd-addr, false) addrAligned := (addr + section.Align - 1) &^ (section.Align - 1)
if sizesDebug { if section.Align > 1 && addrAligned >= sectionEnd {
fmt.Printf("%08x..%08x %5d: unknown (end)\n", addr, sectionEnd, sectionEnd-addr) // The gap is caused by the section alignment.
// For example, if a .rodata section ends with a non-aligned string.
addSize("(padding)", sectionEnd-addr, true)
} else {
addSize("(unknown)", sectionEnd-addr, false)
if sizesDebug {
fmt.Printf("%08x..%08x %5d: unknown (end), alignment=%d\n", addr, sectionEnd, sectionEnd-addr, section.Align)
}
} }
} }
} }