xref: /aosp_15_r20/build/soong/symbol_inject/elf.go (revision 333d2b3687b3a337dbcca9d65000bca186795e39)
1*333d2b36SAndroid Build Coastguard Worker// Copyright 2018 Google Inc. All rights reserved.
2*333d2b36SAndroid Build Coastguard Worker//
3*333d2b36SAndroid Build Coastguard Worker// Licensed under the Apache License, Version 2.0 (the "License");
4*333d2b36SAndroid Build Coastguard Worker// you may not use this file except in compliance with the License.
5*333d2b36SAndroid Build Coastguard Worker// You may obtain a copy of the License at
6*333d2b36SAndroid Build Coastguard Worker//
7*333d2b36SAndroid Build Coastguard Worker//     http://www.apache.org/licenses/LICENSE-2.0
8*333d2b36SAndroid Build Coastguard Worker//
9*333d2b36SAndroid Build Coastguard Worker// Unless required by applicable law or agreed to in writing, software
10*333d2b36SAndroid Build Coastguard Worker// distributed under the License is distributed on an "AS IS" BASIS,
11*333d2b36SAndroid Build Coastguard Worker// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12*333d2b36SAndroid Build Coastguard Worker// See the License for the specific language governing permissions and
13*333d2b36SAndroid Build Coastguard Worker// limitations under the License.
14*333d2b36SAndroid Build Coastguard Worker
15*333d2b36SAndroid Build Coastguard Workerpackage symbol_inject
16*333d2b36SAndroid Build Coastguard Worker
17*333d2b36SAndroid Build Coastguard Workerimport (
18*333d2b36SAndroid Build Coastguard Worker	"debug/elf"
19*333d2b36SAndroid Build Coastguard Worker	"fmt"
20*333d2b36SAndroid Build Coastguard Worker	"io"
21*333d2b36SAndroid Build Coastguard Worker)
22*333d2b36SAndroid Build Coastguard Worker
23*333d2b36SAndroid Build Coastguard Workertype mockableElfFile interface {
24*333d2b36SAndroid Build Coastguard Worker	Symbols() ([]elf.Symbol, error)
25*333d2b36SAndroid Build Coastguard Worker	Sections() []elf.SectionHeader
26*333d2b36SAndroid Build Coastguard Worker	Type() elf.Type
27*333d2b36SAndroid Build Coastguard Worker}
28*333d2b36SAndroid Build Coastguard Worker
29*333d2b36SAndroid Build Coastguard Workervar _ mockableElfFile = elfFileWrapper{}
30*333d2b36SAndroid Build Coastguard Worker
31*333d2b36SAndroid Build Coastguard Workertype elfFileWrapper struct {
32*333d2b36SAndroid Build Coastguard Worker	*elf.File
33*333d2b36SAndroid Build Coastguard Worker}
34*333d2b36SAndroid Build Coastguard Worker
35*333d2b36SAndroid Build Coastguard Workerfunc (f elfFileWrapper) Sections() []elf.SectionHeader {
36*333d2b36SAndroid Build Coastguard Worker	ret := make([]elf.SectionHeader, len(f.File.Sections))
37*333d2b36SAndroid Build Coastguard Worker	for i, section := range f.File.Sections {
38*333d2b36SAndroid Build Coastguard Worker		ret[i] = section.SectionHeader
39*333d2b36SAndroid Build Coastguard Worker	}
40*333d2b36SAndroid Build Coastguard Worker
41*333d2b36SAndroid Build Coastguard Worker	return ret
42*333d2b36SAndroid Build Coastguard Worker}
43*333d2b36SAndroid Build Coastguard Worker
44*333d2b36SAndroid Build Coastguard Workerfunc (f elfFileWrapper) Type() elf.Type {
45*333d2b36SAndroid Build Coastguard Worker	return f.File.Type
46*333d2b36SAndroid Build Coastguard Worker}
47*333d2b36SAndroid Build Coastguard Worker
48*333d2b36SAndroid Build Coastguard Workertype mockElfFile struct {
49*333d2b36SAndroid Build Coastguard Worker	symbols  []elf.Symbol
50*333d2b36SAndroid Build Coastguard Worker	sections []elf.SectionHeader
51*333d2b36SAndroid Build Coastguard Worker	t        elf.Type
52*333d2b36SAndroid Build Coastguard Worker}
53*333d2b36SAndroid Build Coastguard Worker
54*333d2b36SAndroid Build Coastguard Workerfunc (f mockElfFile) Sections() []elf.SectionHeader  { return f.sections }
55*333d2b36SAndroid Build Coastguard Workerfunc (f mockElfFile) Symbols() ([]elf.Symbol, error) { return f.symbols, nil }
56*333d2b36SAndroid Build Coastguard Workerfunc (f mockElfFile) Type() elf.Type                 { return f.t }
57*333d2b36SAndroid Build Coastguard Worker
58*333d2b36SAndroid Build Coastguard Workerfunc elfSymbolsFromFile(r io.ReaderAt) (*File, error) {
59*333d2b36SAndroid Build Coastguard Worker	elfFile, err := elf.NewFile(r)
60*333d2b36SAndroid Build Coastguard Worker	if err != nil {
61*333d2b36SAndroid Build Coastguard Worker		return nil, cantParseError{err}
62*333d2b36SAndroid Build Coastguard Worker	}
63*333d2b36SAndroid Build Coastguard Worker	return extractElfSymbols(elfFileWrapper{elfFile})
64*333d2b36SAndroid Build Coastguard Worker}
65*333d2b36SAndroid Build Coastguard Worker
66*333d2b36SAndroid Build Coastguard Workerfunc extractElfSymbols(elfFile mockableElfFile) (*File, error) {
67*333d2b36SAndroid Build Coastguard Worker	symbols, err := elfFile.Symbols()
68*333d2b36SAndroid Build Coastguard Worker	if err != nil {
69*333d2b36SAndroid Build Coastguard Worker		return nil, err
70*333d2b36SAndroid Build Coastguard Worker	}
71*333d2b36SAndroid Build Coastguard Worker
72*333d2b36SAndroid Build Coastguard Worker	file := &File{}
73*333d2b36SAndroid Build Coastguard Worker
74*333d2b36SAndroid Build Coastguard Worker	for _, section := range elfFile.Sections() {
75*333d2b36SAndroid Build Coastguard Worker		file.Sections = append(file.Sections, &Section{
76*333d2b36SAndroid Build Coastguard Worker			Name:   section.Name,
77*333d2b36SAndroid Build Coastguard Worker			Addr:   section.Addr,
78*333d2b36SAndroid Build Coastguard Worker			Offset: section.Offset,
79*333d2b36SAndroid Build Coastguard Worker			Size:   section.Size,
80*333d2b36SAndroid Build Coastguard Worker		})
81*333d2b36SAndroid Build Coastguard Worker	}
82*333d2b36SAndroid Build Coastguard Worker
83*333d2b36SAndroid Build Coastguard Worker	_ = elf.Section{}
84*333d2b36SAndroid Build Coastguard Worker
85*333d2b36SAndroid Build Coastguard Worker	for _, symbol := range symbols {
86*333d2b36SAndroid Build Coastguard Worker		if elf.ST_TYPE(symbol.Info) != elf.STT_OBJECT {
87*333d2b36SAndroid Build Coastguard Worker			continue
88*333d2b36SAndroid Build Coastguard Worker		}
89*333d2b36SAndroid Build Coastguard Worker		if symbol.Section == elf.SHN_UNDEF || symbol.Section >= elf.SHN_LORESERVE {
90*333d2b36SAndroid Build Coastguard Worker			continue
91*333d2b36SAndroid Build Coastguard Worker		}
92*333d2b36SAndroid Build Coastguard Worker		if int(symbol.Section) >= len(file.Sections) {
93*333d2b36SAndroid Build Coastguard Worker			return nil, fmt.Errorf("invalid section index %d", symbol.Section)
94*333d2b36SAndroid Build Coastguard Worker		}
95*333d2b36SAndroid Build Coastguard Worker
96*333d2b36SAndroid Build Coastguard Worker		section := file.Sections[symbol.Section]
97*333d2b36SAndroid Build Coastguard Worker
98*333d2b36SAndroid Build Coastguard Worker		var addr uint64
99*333d2b36SAndroid Build Coastguard Worker		switch elfFile.Type() {
100*333d2b36SAndroid Build Coastguard Worker		case elf.ET_REL:
101*333d2b36SAndroid Build Coastguard Worker			// "In relocatable files, st_value holds a section offset for a defined symbol.
102*333d2b36SAndroid Build Coastguard Worker			// That is, st_value is an offset from the beginning of the section that st_shndx identifies."
103*333d2b36SAndroid Build Coastguard Worker			addr = symbol.Value
104*333d2b36SAndroid Build Coastguard Worker		case elf.ET_EXEC, elf.ET_DYN:
105*333d2b36SAndroid Build Coastguard Worker			// "In executable and shared object files, st_value holds a virtual address. To make these
106*333d2b36SAndroid Build Coastguard Worker			// files’ symbols more useful for the dynamic linker, the section offset (file interpretation)
107*333d2b36SAndroid Build Coastguard Worker			// gives way to a virtual address (memory interpretation) for which the section number is
108*333d2b36SAndroid Build Coastguard Worker			// irrelevant."
109*333d2b36SAndroid Build Coastguard Worker			if symbol.Value < section.Addr {
110*333d2b36SAndroid Build Coastguard Worker				return nil, fmt.Errorf("symbol starts before the start of its section")
111*333d2b36SAndroid Build Coastguard Worker			}
112*333d2b36SAndroid Build Coastguard Worker			addr = symbol.Value - section.Addr
113*333d2b36SAndroid Build Coastguard Worker			if addr+symbol.Size > section.Size {
114*333d2b36SAndroid Build Coastguard Worker				return nil, fmt.Errorf("symbol extends past the end of its section")
115*333d2b36SAndroid Build Coastguard Worker			}
116*333d2b36SAndroid Build Coastguard Worker		default:
117*333d2b36SAndroid Build Coastguard Worker			return nil, fmt.Errorf("unsupported elf file type %d", elfFile.Type())
118*333d2b36SAndroid Build Coastguard Worker		}
119*333d2b36SAndroid Build Coastguard Worker
120*333d2b36SAndroid Build Coastguard Worker		file.Symbols = append(file.Symbols, &Symbol{
121*333d2b36SAndroid Build Coastguard Worker			Name:    symbol.Name,
122*333d2b36SAndroid Build Coastguard Worker			Addr:    addr,
123*333d2b36SAndroid Build Coastguard Worker			Size:    symbol.Size,
124*333d2b36SAndroid Build Coastguard Worker			Section: section,
125*333d2b36SAndroid Build Coastguard Worker		})
126*333d2b36SAndroid Build Coastguard Worker	}
127*333d2b36SAndroid Build Coastguard Worker
128*333d2b36SAndroid Build Coastguard Worker	return file, nil
129*333d2b36SAndroid Build Coastguard Worker}
130*333d2b36SAndroid Build Coastguard Worker
131*333d2b36SAndroid Build Coastguard Workerfunc dumpElfSymbols(r io.ReaderAt) error {
132*333d2b36SAndroid Build Coastguard Worker	elfFile, err := elf.NewFile(r)
133*333d2b36SAndroid Build Coastguard Worker	if err != nil {
134*333d2b36SAndroid Build Coastguard Worker		return cantParseError{err}
135*333d2b36SAndroid Build Coastguard Worker	}
136*333d2b36SAndroid Build Coastguard Worker
137*333d2b36SAndroid Build Coastguard Worker	symbols, err := elfFile.Symbols()
138*333d2b36SAndroid Build Coastguard Worker	if err != nil {
139*333d2b36SAndroid Build Coastguard Worker		return err
140*333d2b36SAndroid Build Coastguard Worker	}
141*333d2b36SAndroid Build Coastguard Worker
142*333d2b36SAndroid Build Coastguard Worker	fmt.Println("mockElfFile{")
143*333d2b36SAndroid Build Coastguard Worker	fmt.Printf("\tt: %#v,\n", elfFile.Type)
144*333d2b36SAndroid Build Coastguard Worker
145*333d2b36SAndroid Build Coastguard Worker	fmt.Println("\tsections: []elf.SectionHeader{")
146*333d2b36SAndroid Build Coastguard Worker	for _, section := range elfFile.Sections {
147*333d2b36SAndroid Build Coastguard Worker		fmt.Printf("\t\t%#v,\n", section.SectionHeader)
148*333d2b36SAndroid Build Coastguard Worker	}
149*333d2b36SAndroid Build Coastguard Worker	fmt.Println("\t},")
150*333d2b36SAndroid Build Coastguard Worker
151*333d2b36SAndroid Build Coastguard Worker	fmt.Println("\tsymbols: []elf.Symbol{")
152*333d2b36SAndroid Build Coastguard Worker	for _, symbol := range symbols {
153*333d2b36SAndroid Build Coastguard Worker		fmt.Printf("\t\t%#v,\n", symbol)
154*333d2b36SAndroid Build Coastguard Worker	}
155*333d2b36SAndroid Build Coastguard Worker	fmt.Println("\t},")
156*333d2b36SAndroid Build Coastguard Worker
157*333d2b36SAndroid Build Coastguard Worker	fmt.Println("}")
158*333d2b36SAndroid Build Coastguard Worker
159*333d2b36SAndroid Build Coastguard Worker	return nil
160*333d2b36SAndroid Build Coastguard Worker}
161