From dfce764476b6be22907d555097b7346cfa16f0ca Mon Sep 17 00:00:00 2001 From: Colin Cross Date: Wed, 28 Feb 2018 13:05:39 -0800 Subject: [PATCH] Fix finding next symbol when multiple symbols have the same address Some exe files have a .data symbol at the same address as the soong_build_number symbol. If the .data symbol is after soong_build_number in the symbol list, symbol_inject would think the end address was the same as the start address, and use uint32(-1) as the size. Use sort.Search to find the first symbol whose section number is the same as the target symbol, but whose address is higher than the target symbol. Test: manual Change-Id: I51d6e53c6b906222ba68c5cf93be944843e23550 --- cmd/symbol_inject/macho.go | 52 ++++++++++++++++------------------- cmd/symbol_inject/pe.go | 56 +++++++++++++++++++------------------- 2 files changed, 52 insertions(+), 56 deletions(-) diff --git a/cmd/symbol_inject/macho.go b/cmd/symbol_inject/macho.go index 4a3ecc741..478e6de8f 100644 --- a/cmd/symbol_inject/macho.go +++ b/cmd/symbol_inject/macho.go @@ -38,37 +38,33 @@ func findMachoSymbol(r io.ReaderAt, symbolName string) (uint64, uint64, error) { return symbols[i].Value < symbols[j].Value }) - for i, symbol := range symbols { - if symbol.Sect == 0 { - continue - } - if symbol.Name == symbolName { - var nextSymbol *macho.Symbol - if i+1 < len(symbols) { - nextSymbol = &symbols[i+1] + for _, symbol := range symbols { + if symbol.Name == symbolName && symbol.Sect != 0 { + // Find the next symbol in the same section with a higher address + n := sort.Search(len(symbols), func(i int) bool { + return symbols[i].Sect == symbol.Sect && + symbols[i].Value > symbol.Value + }) + + section := machoFile.Sections[symbol.Sect-1] + + var end uint64 + if n < len(symbols) { + end = symbols[n].Value + } else { + end = section.Addr + section.Size } - return calculateMachoSymbolOffset(machoFile, symbol, nextSymbol) + + if end <= symbol.Value && end > symbol.Value+4096 { + return maxUint64, maxUint64, fmt.Errorf("symbol end address does not seem valid, %x:%x", symbol.Value, end) + } + + size := end - symbol.Value - 1 + offset := uint64(section.Offset) + (symbol.Value - section.Addr) + + return offset, size, nil } } return maxUint64, maxUint64, fmt.Errorf("symbol not found") } - -func calculateMachoSymbolOffset(file *macho.File, symbol macho.Symbol, nextSymbol *macho.Symbol) (uint64, uint64, error) { - section := file.Sections[symbol.Sect-1] - - var end uint64 - if nextSymbol != nil && nextSymbol.Sect != symbol.Sect { - nextSymbol = nil - } - if nextSymbol != nil { - end = nextSymbol.Value - } else { - end = section.Addr + section.Size - } - - size := end - symbol.Value - 1 - offset := uint64(section.Offset) + (symbol.Value - section.Addr) - - return offset, size, nil -} diff --git a/cmd/symbol_inject/pe.go b/cmd/symbol_inject/pe.go index dad530d4d..82fdff8cf 100644 --- a/cmd/symbol_inject/pe.go +++ b/cmd/symbol_inject/pe.go @@ -32,41 +32,41 @@ func findPESymbol(r io.ReaderAt, symbolName string) (uint64, uint64, error) { symbolName = "_" + symbolName } - sort.Slice(peFile.Symbols, func(i, j int) bool { - if peFile.Symbols[i].SectionNumber != peFile.Symbols[j].SectionNumber { - return peFile.Symbols[i].SectionNumber < peFile.Symbols[j].SectionNumber + symbols := peFile.Symbols + sort.Slice(symbols, func(i, j int) bool { + if symbols[i].SectionNumber != symbols[j].SectionNumber { + return symbols[i].SectionNumber < symbols[j].SectionNumber } - return peFile.Symbols[i].Value < peFile.Symbols[j].Value + return symbols[i].Value < symbols[j].Value }) - for i, symbol := range peFile.Symbols { + for _, symbol := range symbols { if symbol.Name == symbolName { - var nextSymbol *pe.Symbol - if i+1 < len(peFile.Symbols) { - nextSymbol = peFile.Symbols[i+1] + // Find the next symbol (n the same section with a higher address + n := sort.Search(len(symbols), func(i int) bool { + return symbols[i].SectionNumber == symbol.SectionNumber && + symbols[i].Value > symbol.Value + }) + + section := peFile.Sections[symbol.SectionNumber-1] + + var end uint32 + if n < len(symbols) { + end = symbols[n].Value + } else { + end = section.Size } - return calculatePESymbolOffset(peFile, symbol, nextSymbol) + + if end <= symbol.Value && end > symbol.Value+4096 { + return maxUint64, maxUint64, fmt.Errorf("symbol end address does not seem valid, %x:%x", symbol.Value, end) + } + + size := end - symbol.Value - 1 + offset := section.Offset + symbol.Value + + return uint64(offset), uint64(size), nil } } return maxUint64, maxUint64, fmt.Errorf("symbol not found") } - -func calculatePESymbolOffset(file *pe.File, symbol *pe.Symbol, nextSymbol *pe.Symbol) (uint64, uint64, error) { - section := file.Sections[symbol.SectionNumber-1] - - var end uint32 - if nextSymbol != nil && nextSymbol.SectionNumber != symbol.SectionNumber { - nextSymbol = nil - } - if nextSymbol != nil { - end = nextSymbol.Value - } else { - end = section.Size - } - - size := end - symbol.Value - 1 - offset := section.Offset + symbol.Value - - return uint64(offset), uint64(size), nil -}