Skip to content

Commit 17d67ed

Browse files
AlexanderYastrebovgopherbot
authored andcommitted
debug/buildinfo: read full data segment to lookup buildinfo magic
Fixes #61644 Change-Id: I7d40c33e65221994bb6865d22dd0994545603ba8 GitHub-Last-Rev: aca92af GitHub-Pull-Request: #61649 Reviewed-on: https://go-review.googlesource.com/c/go/+/514075 Run-TryBot: Ian Lance Taylor <[email protected]> Reviewed-by: David Chase <[email protected]> TryBot-Result: Gopher Robot <[email protected]> Run-TryBot: Ian Lance Taylor <[email protected]> Auto-Submit: Ian Lance Taylor <[email protected]> Reviewed-by: Ian Lance Taylor <[email protected]>
1 parent 1eaeec1 commit 17d67ed

File tree

1 file changed

+26
-23
lines changed

1 file changed

+26
-23
lines changed

src/debug/buildinfo/buildinfo.go

Lines changed: 26 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -89,10 +89,10 @@ type exe interface {
8989
// ReadData reads and returns up to size bytes starting at virtual address addr.
9090
ReadData(addr, size uint64) ([]byte, error)
9191

92-
// DataStart returns the virtual address of the segment or section that
92+
// DataStart returns the virtual address and size of the segment or section that
9393
// should contain build information. This is either a specially named section
9494
// or the first writable non-zero data segment.
95-
DataStart() uint64
95+
DataStart() (uint64, uint64)
9696
}
9797

9898
// readRawBuildInfo extracts the Go toolchain version and module information
@@ -148,13 +148,16 @@ func readRawBuildInfo(r io.ReaderAt) (vers, mod string, err error) {
148148
return "", "", errUnrecognizedFormat
149149
}
150150

151-
// Read the first 64kB of dataAddr to find the build info blob.
151+
// Read segment or section to find the build info blob.
152152
// On some platforms, the blob will be in its own section, and DataStart
153153
// returns the address of that section. On others, it's somewhere in the
154154
// data segment; the linker puts it near the beginning.
155155
// See cmd/link/internal/ld.Link.buildinfo.
156-
dataAddr := x.DataStart()
157-
data, err := x.ReadData(dataAddr, 64*1024)
156+
dataAddr, dataSize := x.DataStart()
157+
if dataSize == 0 {
158+
return "", "", errNotGoExe
159+
}
160+
data, err := x.ReadData(dataAddr, dataSize)
158161
if err != nil {
159162
return "", "", err
160163
}
@@ -234,7 +237,7 @@ func hasPlan9Magic(magic []byte) bool {
234237

235238
func decodeString(data []byte) (s string, rest []byte) {
236239
u, n := binary.Uvarint(data)
237-
if n <= 0 || u >= uint64(len(data)-n) {
240+
if n <= 0 || u > uint64(len(data)-n) {
238241
return "", nil
239242
}
240243
return string(data[n : uint64(n)+u]), data[uint64(n)+u:]
@@ -273,18 +276,18 @@ func (x *elfExe) ReadData(addr, size uint64) ([]byte, error) {
273276
return nil, errUnrecognizedFormat
274277
}
275278

276-
func (x *elfExe) DataStart() uint64 {
279+
func (x *elfExe) DataStart() (uint64, uint64) {
277280
for _, s := range x.f.Sections {
278281
if s.Name == ".go.buildinfo" {
279-
return s.Addr
282+
return s.Addr, s.Size
280283
}
281284
}
282285
for _, p := range x.f.Progs {
283286
if p.Type == elf.PT_LOAD && p.Flags&(elf.PF_X|elf.PF_W) == elf.PF_W {
284-
return p.Vaddr
287+
return p.Vaddr, p.Memsz
285288
}
286289
}
287-
return 0
290+
return 0, 0
288291
}
289292

290293
// peExe is the PE (Windows Portable Executable) implementation of the exe interface.
@@ -316,7 +319,7 @@ func (x *peExe) ReadData(addr, size uint64) ([]byte, error) {
316319
return nil, errUnrecognizedFormat
317320
}
318321

319-
func (x *peExe) DataStart() uint64 {
322+
func (x *peExe) DataStart() (uint64, uint64) {
320323
// Assume data is first writable section.
321324
const (
322325
IMAGE_SCN_CNT_CODE = 0x00000020
@@ -332,10 +335,10 @@ func (x *peExe) DataStart() uint64 {
332335
for _, sect := range x.f.Sections {
333336
if sect.VirtualAddress != 0 && sect.Size != 0 &&
334337
sect.Characteristics&^IMAGE_SCN_ALIGN_32BYTES == IMAGE_SCN_CNT_INITIALIZED_DATA|IMAGE_SCN_MEM_READ|IMAGE_SCN_MEM_WRITE {
335-
return uint64(sect.VirtualAddress) + x.imageBase()
338+
return uint64(sect.VirtualAddress) + x.imageBase(), uint64(sect.VirtualSize)
336339
}
337340
}
338-
return 0
341+
return 0, 0
339342
}
340343

341344
// machoExe is the Mach-O (Apple macOS/iOS) implementation of the exe interface.
@@ -363,22 +366,22 @@ func (x *machoExe) ReadData(addr, size uint64) ([]byte, error) {
363366
return nil, errUnrecognizedFormat
364367
}
365368

366-
func (x *machoExe) DataStart() uint64 {
369+
func (x *machoExe) DataStart() (uint64, uint64) {
367370
// Look for section named "__go_buildinfo".
368371
for _, sec := range x.f.Sections {
369372
if sec.Name == "__go_buildinfo" {
370-
return sec.Addr
373+
return sec.Addr, sec.Size
371374
}
372375
}
373376
// Try the first non-empty writable segment.
374377
const RW = 3
375378
for _, load := range x.f.Loads {
376379
seg, ok := load.(*macho.Segment)
377380
if ok && seg.Addr != 0 && seg.Filesz != 0 && seg.Prot == RW && seg.Maxprot == RW {
378-
return seg.Addr
381+
return seg.Addr, seg.Memsz
379382
}
380383
}
381-
return 0
384+
return 0, 0
382385
}
383386

384387
// xcoffExe is the XCOFF (AIX eXtended COFF) implementation of the exe interface.
@@ -399,23 +402,23 @@ func (x *xcoffExe) ReadData(addr, size uint64) ([]byte, error) {
399402
return nil, errors.New("address not mapped")
400403
}
401404

402-
func (x *xcoffExe) DataStart() uint64 {
405+
func (x *xcoffExe) DataStart() (uint64, uint64) {
403406
if s := x.f.SectionByType(xcoff.STYP_DATA); s != nil {
404-
return s.VirtualAddress
407+
return s.VirtualAddress, s.Size
405408
}
406-
return 0
409+
return 0, 0
407410
}
408411

409412
// plan9objExe is the Plan 9 a.out implementation of the exe interface.
410413
type plan9objExe struct {
411414
f *plan9obj.File
412415
}
413416

414-
func (x *plan9objExe) DataStart() uint64 {
417+
func (x *plan9objExe) DataStart() (uint64, uint64) {
415418
if s := x.f.Section("data"); s != nil {
416-
return uint64(s.Offset)
419+
return uint64(s.Offset), uint64(s.Size)
417420
}
418-
return 0
421+
return 0, 0
419422
}
420423

421424
func (x *plan9objExe) ReadData(addr, size uint64) ([]byte, error) {

0 commit comments

Comments
 (0)