<commit_before>// Copyright 2009 The Go Authors.  All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package sym

import (
	"fmt";
	"io";
	"log";
	"os";
)

/*
 * Internal ELF representation
 */

// Elf represents a decoded ELF binary.
type Elf struct {
	class int;
	data byteOrder;
	Type ElfType;
	Machine ElfMachine;
	Sections []*Section;
}

// Section represents a single section in an ELF binary.
type Section struct {
	r io.ReadSeeker;
	Name string;
	offset int64;
	Size uint64;
	Addr uint64;
}

/*
 * ELF reader
 */

type FormatError struct {
	off int64;
	msg string;
	val interface{};
}

func (e *FormatError) String() string {
	msg := e.msg;
	if e.val != nil {
		msg += fmt.Sprintf(" '%v' ", e.val);
	}
	msg += fmt.Sprintf("in record at byte %#x", e.off);
	return msg;
}

// NewElf reads and decodes an ELF binary.  The ELF binary is expected
// to start where the reader is currently positioned.
func NewElf(r io.ReadSeeker) (*Elf, os.Error) {
	// Read ELF identifier
	var ident [eiNIdent]uint8;
	off, err := r.Seek(0, 0);
	if err != nil {
		return nil, err;
	}
	start := off;
	n, err := io.ReadFull(r, &ident);
	if err != nil {
		if err == os.EOF {
			err = io.ErrUnexpectedEOF;
		}
		return nil, err;
	}

	// Decode identifier
	if ident[eiMag0] != '\x7f' || ident[eiMag1] != 'E' || ident[eiMag2] != 'L' || ident[eiMag3] != 'F' {
		return nil, &FormatError{off, "bad magic number", string(ident[eiMag0:eiMag3])};
	}
	e := &Elf{};

	switch ident[eiClass] {
	case elfClass32:
		e.class = 32;
	case elfClass64:
		e.class = 64;
	default:
		return nil, &FormatError{off, "unknown ELF class", ident[eiClass]};
	}

	switch ident[eiData] {
	case elfData2LSB:
		e.data = lsb;
	case elfData2MSB:
		e.data = msb;
	default:
		return nil, &FormatError{off, "unknown ELF data encoding", ident[eiData]};
	}

	if ident[eiVersion] != evCurrent {
		return nil, &FormatError{off, "unknown ELF version", ident[eiVersion]};
	}

	// TODO(austin) Do something with ABI?

	// Read ELF file header
	var shoff int64;
	var shentsize, shnum, shstrndx int;

	br := newBinaryReader(r, e.data);
	switch e.class {
	case 32:
		return nil, &FormatError{off, "ELF32 not implemented", nil};
	case 64:
		hdr := &elf64Ehdr{};
		br.ReadAny(hdr);
		if err := br.Error(); err != nil {
			return nil, err;
		}

		if hdr.Type > etCore && hdr.Type < etLoOS {
			return nil, &FormatError{off, "unknown ELF file type", hdr.Type};
		}
		e.Type = ElfType(hdr.Type);
		e.Machine = ElfMachine(hdr.Machine);
		if hdr.Version != evCurrent {
			return nil, &FormatError{off, "unknown second ELF version", hdr.Version};
		}

		shoff = int64(hdr.Shoff);
		shentsize = int(hdr.Shentsize);
		shnum = int(hdr.Shnum);
		shstrndx = int(hdr.Shstrndx);
	}

	// Read section headers
	e.Sections = make([]*Section, shnum);
	secNames := make([]uint32, shnum);
	for i := 0; i < shnum; i++ {
		off, err = r.Seek(start + shoff + int64(i*shentsize), 0);
		if err != nil {
			return nil, err;
		}

		br = newBinaryReader(r, e.data);
		switch e.class {
		case 32:
			panic("not reached");
		case 64:
			shdr := &elf64Shdr{};
			br.ReadAny(shdr);
			if err := br.Error(); err != nil {
				return nil, err;
			}

			s := &Section{
				r: r,
				offset: start + int64(shdr.Off),
				Size: shdr.Size,
				Addr: uint64(shdr.Addr),
			};
			secNames[i] = shdr.Name;
			e.Sections[i] = s;
		}
	}

	// Resolve section names
	off, err = r.Seek(start + e.Sections[shstrndx].offset, 0);
	if err != nil {
		return nil, err;
	}
	blob := make([]byte, e.Sections[shstrndx].Size);
	n, err = io.ReadFull(r, blob);
	strings := make(map[uint32] string);
	strStart := uint32(0);
	for i, c := range blob {
		if c == 0 {
			strings[strStart] = string(blob[strStart:i]);
			strStart = uint32(i+1);
		}
	}

	for i, s := range e.Sections {
		var ok bool;
		s.Name, ok = strings[secNames[i]];
		if !ok {
			return nil, &FormatError{start + shoff + int64(i*shentsize), "bad section name", secNames[i]};
		}
	}

	return e, nil;
}

// Section returns a section with the given name, or nil if no such
// section exists.
func (e *Elf) Section(name string) *Section {
	for _, s := range e.Sections {
		if s.Name == name {
			return s;
		}
	}
	return nil;
}

/*
 * Sections
 */

type subReader struct {
	r io.Reader;
	rem uint64;
}<commit_msg>Decode overlapping section names correctly.<commit_after>// Copyright 2009 The Go Authors.  All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package sym

import (
	"fmt";
	"io";
	"log";
	"os";
)

/*
 * Internal ELF representation
 */

// Elf represents a decoded ELF binary.
type Elf struct {
	class int;
	data byteOrder;
	Type ElfType;
	Machine ElfMachine;
	Sections []*Section;
}

// Section represents a single section in an ELF binary.
type Section struct {
	r io.ReadSeeker;
	Name string;
	offset int64;
	Size uint64;
	Addr uint64;
}

/*
 * ELF reader
 */

type FormatError struct {
	off int64;
	msg string;
	val interface{};
}

func (e *FormatError) String() string {
	msg := e.msg;
	if e.val != nil {
		msg += fmt.Sprintf(" '%v' ", e.val);
	}
	msg += fmt.Sprintf("in record at byte %#x", e.off);
	return msg;
}

// NewElf reads and decodes an ELF binary.  The ELF binary is expected
// to start where the reader is currently positioned.
func NewElf(r io.ReadSeeker) (*Elf, os.Error) {
	// Read ELF identifier
	var ident [eiNIdent]uint8;
	off, err := r.Seek(0, 0);
	if err != nil {
		return nil, err;
	}
	start := off;
	n, err := io.ReadFull(r, &ident);
	if err != nil {
		if err == os.EOF {
			err = io.ErrUnexpectedEOF;
		}
		return nil, err;
	}

	// Decode identifier
	if ident[eiMag0] != '\x7f' || ident[eiMag1] != 'E' || ident[eiMag2] != 'L' || ident[eiMag3] != 'F' {
		return nil, &FormatError{off, "bad magic number", string(ident[eiMag0:eiMag3])};
	}
	e := &Elf{};

	switch ident[eiClass] {
	case elfClass32:
		e.class = 32;
	case elfClass64:
		e.class = 64;
	default:
		return nil, &FormatError{off, "unknown ELF class", ident[eiClass]};
	}

	switch ident[eiData] {
	case elfData2LSB:
		e.data = lsb;
	case elfData2MSB:
		e.data = msb;
	default:
		return nil, &FormatError{off, "unknown ELF data encoding", ident[eiData]};
	}

	if ident[eiVersion] != evCurrent {
		return nil, &FormatError{off, "unknown ELF version", ident[eiVersion]};
	}

	// TODO(austin) Do something with ABI?

	// Read ELF file header
	var shoff int64;
	var shentsize, shnum, shstrndx int;

	br := newBinaryReader(r, e.data);
	switch e.class {
	case 32:
		return nil, &FormatError{off, "ELF32 not implemented", nil};
	case 64:
		hdr := &elf64Ehdr{};
		br.ReadAny(hdr);
		if err := br.Error(); err != nil {
			return nil, err;
		}

		if hdr.Type > etCore && hdr.Type < etLoOS {
			return nil, &FormatError{off, "unknown ELF file type", hdr.Type};
		}
		e.Type = ElfType(hdr.Type);
		e.Machine = ElfMachine(hdr.Machine);
		if hdr.Version != evCurrent {
			return nil, &FormatError{off, "unknown second ELF version", hdr.Version};
		}

		shoff = int64(hdr.Shoff);
		shentsize = int(hdr.Shentsize);
		shnum = int(hdr.Shnum);
		shstrndx = int(hdr.Shstrndx);
	}

	// Read section headers
	e.Sections = make([]*Section, shnum);
	secNames := make([]uint32, shnum);
	for i := 0; i < shnum; i++ {
		off, err = r.Seek(start + shoff + int64(i*shentsize), 0);
		if err != nil {
			return nil, err;
		}

		br = newBinaryReader(r, e.data);
		switch e.class {
		case 32:
			panic("not reached");
		case 64:
			shdr := &elf64Shdr{};
			br.ReadAny(shdr);
			if err := br.Error(); err != nil {
				return nil, err;
			}

			s := &Section{
				r: r,
				offset: start + int64(shdr.Off),
				Size: shdr.Size,
				Addr: uint64(shdr.Addr),
			};
			secNames[i] = shdr.Name;
			e.Sections[i] = s;
		}
	}

	// Resolve section names
	off, err = r.Seek(start + e.Sections[shstrndx].offset, 0);
	if err != nil {
		return nil, err;
	}
	blob := make([]byte, e.Sections[shstrndx].Size);
	n, err = io.ReadFull(r, blob);

	for i, s := range e.Sections {
		var ok bool;
		s.Name, ok = getString(blob, int(secNames[i]));
		if !ok {
			return nil, &FormatError{start + shoff + int64(i*shentsize), "bad section name", secNames[i]};
		}
	}

	return e, nil;
}

// getString extracts a string from an ELF string table.
func getString(section []byte, index int) (string, bool) {
	if index < 0 || index >= len(section) {
		return "", false;
	}

	for end := index; end < len(section); end++ {
		if section[end] == 0 {
			return string(section[index:end]), true;
		}
	}
	return "", false;
}

// Section returns a section with the given name, or nil if no such
// section exists.
func (e *Elf) Section(name string) *Section {
	for _, s := range e.Sections {
		if s.Name == name {
			return s;
		}
	}
	return nil;
}

/*
 * Sections
 */

type subReader struct {
	r io.Reader;
	rem uint64;
}
{'fraction_non_alphanumeric': 0.155039637599094, 'fraction_numerical': 0.015968289920724802, 'mean_word_length': 3.2354916067146284, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 6, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2092887', 'n_tokens_mistral': 3709, 'n_tokens_neox': 3396, 'n_words': 995}