xref: /linux/tools/perf/util/symbol-minimal.c (revision 779e24e2c777bffa9a6e3d5e821859e67008c98b)
1393be2e3SNamhyung Kim #include "symbol.h"
2393be2e3SNamhyung Kim 
3b691f643SNamhyung Kim #include <stdio.h>
4b691f643SNamhyung Kim #include <fcntl.h>
5b691f643SNamhyung Kim #include <string.h>
6b691f643SNamhyung Kim #include <byteswap.h>
7b691f643SNamhyung Kim #include <sys/stat.h>
8393be2e3SNamhyung Kim 
9b691f643SNamhyung Kim 
10b691f643SNamhyung Kim static bool check_need_swap(int file_endian)
11393be2e3SNamhyung Kim {
12b691f643SNamhyung Kim 	const int data = 1;
13b691f643SNamhyung Kim 	u8 *check = (u8 *)&data;
14b691f643SNamhyung Kim 	int host_endian;
15b691f643SNamhyung Kim 
16b691f643SNamhyung Kim 	if (check[0] == 1)
17b691f643SNamhyung Kim 		host_endian = ELFDATA2LSB;
18b691f643SNamhyung Kim 	else
19b691f643SNamhyung Kim 		host_endian = ELFDATA2MSB;
20b691f643SNamhyung Kim 
21b691f643SNamhyung Kim 	return host_endian != file_endian;
22393be2e3SNamhyung Kim }
23393be2e3SNamhyung Kim 
24b691f643SNamhyung Kim #define NOTE_ALIGN(sz) (((sz) + 3) & ~3)
25b691f643SNamhyung Kim 
26b691f643SNamhyung Kim #define NT_GNU_BUILD_ID	3
27b691f643SNamhyung Kim 
28b691f643SNamhyung Kim static int read_build_id(void *note_data, size_t note_len, void *bf,
29b691f643SNamhyung Kim 			 size_t size, bool need_swap)
30393be2e3SNamhyung Kim {
31b691f643SNamhyung Kim 	struct {
32b691f643SNamhyung Kim 		u32 n_namesz;
33b691f643SNamhyung Kim 		u32 n_descsz;
34b691f643SNamhyung Kim 		u32 n_type;
35b691f643SNamhyung Kim 	} *nhdr;
36b691f643SNamhyung Kim 	void *ptr;
37b691f643SNamhyung Kim 
38b691f643SNamhyung Kim 	ptr = note_data;
39b691f643SNamhyung Kim 	while (ptr < (note_data + note_len)) {
40b691f643SNamhyung Kim 		const char *name;
41b691f643SNamhyung Kim 		size_t namesz, descsz;
42b691f643SNamhyung Kim 
43b691f643SNamhyung Kim 		nhdr = ptr;
44b691f643SNamhyung Kim 		if (need_swap) {
45b691f643SNamhyung Kim 			nhdr->n_namesz = bswap_32(nhdr->n_namesz);
46b691f643SNamhyung Kim 			nhdr->n_descsz = bswap_32(nhdr->n_descsz);
47b691f643SNamhyung Kim 			nhdr->n_type = bswap_32(nhdr->n_type);
48b691f643SNamhyung Kim 		}
49b691f643SNamhyung Kim 
50b691f643SNamhyung Kim 		namesz = NOTE_ALIGN(nhdr->n_namesz);
51b691f643SNamhyung Kim 		descsz = NOTE_ALIGN(nhdr->n_descsz);
52b691f643SNamhyung Kim 
53b691f643SNamhyung Kim 		ptr += sizeof(*nhdr);
54b691f643SNamhyung Kim 		name = ptr;
55b691f643SNamhyung Kim 		ptr += namesz;
56b691f643SNamhyung Kim 		if (nhdr->n_type == NT_GNU_BUILD_ID &&
57b691f643SNamhyung Kim 		    nhdr->n_namesz == sizeof("GNU")) {
58b691f643SNamhyung Kim 			if (memcmp(name, "GNU", sizeof("GNU")) == 0) {
59b691f643SNamhyung Kim 				size_t sz = min(size, descsz);
60b691f643SNamhyung Kim 				memcpy(bf, ptr, sz);
61b691f643SNamhyung Kim 				memset(bf + sz, 0, size - sz);
62b691f643SNamhyung Kim 				return 0;
63b691f643SNamhyung Kim 			}
64b691f643SNamhyung Kim 		}
65b691f643SNamhyung Kim 		ptr += descsz;
66b691f643SNamhyung Kim 	}
67b691f643SNamhyung Kim 
68393be2e3SNamhyung Kim 	return -1;
69393be2e3SNamhyung Kim }
70393be2e3SNamhyung Kim 
711d037ca1SIrina Tirdea int filename__read_debuglink(const char *filename __maybe_unused,
721d037ca1SIrina Tirdea 			     char *debuglink __maybe_unused,
731d037ca1SIrina Tirdea 			     size_t size __maybe_unused)
74393be2e3SNamhyung Kim {
75393be2e3SNamhyung Kim 	return -1;
76393be2e3SNamhyung Kim }
77393be2e3SNamhyung Kim 
78b691f643SNamhyung Kim /*
79b691f643SNamhyung Kim  * Just try PT_NOTE header otherwise fails
80b691f643SNamhyung Kim  */
81b691f643SNamhyung Kim int filename__read_build_id(const char *filename, void *bf, size_t size)
82b691f643SNamhyung Kim {
83b691f643SNamhyung Kim 	FILE *fp;
84b691f643SNamhyung Kim 	int ret = -1;
85b691f643SNamhyung Kim 	bool need_swap = false;
86b691f643SNamhyung Kim 	u8 e_ident[EI_NIDENT];
87b691f643SNamhyung Kim 	size_t buf_size;
88b691f643SNamhyung Kim 	void *buf;
89b691f643SNamhyung Kim 	int i;
90b691f643SNamhyung Kim 
91b691f643SNamhyung Kim 	fp = fopen(filename, "r");
92b691f643SNamhyung Kim 	if (fp == NULL)
93b691f643SNamhyung Kim 		return -1;
94b691f643SNamhyung Kim 
95b691f643SNamhyung Kim 	if (fread(e_ident, sizeof(e_ident), 1, fp) != 1)
96b691f643SNamhyung Kim 		goto out;
97b691f643SNamhyung Kim 
98b691f643SNamhyung Kim 	if (memcmp(e_ident, ELFMAG, SELFMAG) ||
99b691f643SNamhyung Kim 	    e_ident[EI_VERSION] != EV_CURRENT)
100b691f643SNamhyung Kim 		goto out;
101b691f643SNamhyung Kim 
102b691f643SNamhyung Kim 	need_swap = check_need_swap(e_ident[EI_DATA]);
103b691f643SNamhyung Kim 
104b691f643SNamhyung Kim 	/* for simplicity */
105b691f643SNamhyung Kim 	fseek(fp, 0, SEEK_SET);
106b691f643SNamhyung Kim 
107b691f643SNamhyung Kim 	if (e_ident[EI_CLASS] == ELFCLASS32) {
108b691f643SNamhyung Kim 		Elf32_Ehdr ehdr;
109b691f643SNamhyung Kim 		Elf32_Phdr *phdr;
110b691f643SNamhyung Kim 
111b691f643SNamhyung Kim 		if (fread(&ehdr, sizeof(ehdr), 1, fp) != 1)
112b691f643SNamhyung Kim 			goto out;
113b691f643SNamhyung Kim 
114b691f643SNamhyung Kim 		if (need_swap) {
115b691f643SNamhyung Kim 			ehdr.e_phoff = bswap_32(ehdr.e_phoff);
116b691f643SNamhyung Kim 			ehdr.e_phentsize = bswap_16(ehdr.e_phentsize);
117b691f643SNamhyung Kim 			ehdr.e_phnum = bswap_16(ehdr.e_phnum);
118b691f643SNamhyung Kim 		}
119b691f643SNamhyung Kim 
120b691f643SNamhyung Kim 		buf_size = ehdr.e_phentsize * ehdr.e_phnum;
121b691f643SNamhyung Kim 		buf = malloc(buf_size);
122b691f643SNamhyung Kim 		if (buf == NULL)
123b691f643SNamhyung Kim 			goto out;
124b691f643SNamhyung Kim 
125b691f643SNamhyung Kim 		fseek(fp, ehdr.e_phoff, SEEK_SET);
126b691f643SNamhyung Kim 		if (fread(buf, buf_size, 1, fp) != 1)
127b691f643SNamhyung Kim 			goto out_free;
128b691f643SNamhyung Kim 
129b691f643SNamhyung Kim 		for (i = 0, phdr = buf; i < ehdr.e_phnum; i++, phdr++) {
130b691f643SNamhyung Kim 			void *tmp;
131b691f643SNamhyung Kim 
132b691f643SNamhyung Kim 			if (need_swap) {
133b691f643SNamhyung Kim 				phdr->p_type = bswap_32(phdr->p_type);
134b691f643SNamhyung Kim 				phdr->p_offset = bswap_32(phdr->p_offset);
135b691f643SNamhyung Kim 				phdr->p_filesz = bswap_32(phdr->p_filesz);
136b691f643SNamhyung Kim 			}
137b691f643SNamhyung Kim 
138b691f643SNamhyung Kim 			if (phdr->p_type != PT_NOTE)
139b691f643SNamhyung Kim 				continue;
140b691f643SNamhyung Kim 
141b691f643SNamhyung Kim 			buf_size = phdr->p_filesz;
142b691f643SNamhyung Kim 			tmp = realloc(buf, buf_size);
143b691f643SNamhyung Kim 			if (tmp == NULL)
144b691f643SNamhyung Kim 				goto out_free;
145b691f643SNamhyung Kim 
146b691f643SNamhyung Kim 			buf = tmp;
147b691f643SNamhyung Kim 			fseek(fp, phdr->p_offset, SEEK_SET);
148b691f643SNamhyung Kim 			if (fread(buf, buf_size, 1, fp) != 1)
149b691f643SNamhyung Kim 				goto out_free;
150b691f643SNamhyung Kim 
151b691f643SNamhyung Kim 			ret = read_build_id(buf, buf_size, bf, size, need_swap);
152b691f643SNamhyung Kim 			if (ret == 0)
153b691f643SNamhyung Kim 				ret = size;
154b691f643SNamhyung Kim 			break;
155b691f643SNamhyung Kim 		}
156b691f643SNamhyung Kim 	} else {
157b691f643SNamhyung Kim 		Elf64_Ehdr ehdr;
158b691f643SNamhyung Kim 		Elf64_Phdr *phdr;
159b691f643SNamhyung Kim 
160b691f643SNamhyung Kim 		if (fread(&ehdr, sizeof(ehdr), 1, fp) != 1)
161b691f643SNamhyung Kim 			goto out;
162b691f643SNamhyung Kim 
163b691f643SNamhyung Kim 		if (need_swap) {
164b691f643SNamhyung Kim 			ehdr.e_phoff = bswap_64(ehdr.e_phoff);
165b691f643SNamhyung Kim 			ehdr.e_phentsize = bswap_16(ehdr.e_phentsize);
166b691f643SNamhyung Kim 			ehdr.e_phnum = bswap_16(ehdr.e_phnum);
167b691f643SNamhyung Kim 		}
168b691f643SNamhyung Kim 
169b691f643SNamhyung Kim 		buf_size = ehdr.e_phentsize * ehdr.e_phnum;
170b691f643SNamhyung Kim 		buf = malloc(buf_size);
171b691f643SNamhyung Kim 		if (buf == NULL)
172b691f643SNamhyung Kim 			goto out;
173b691f643SNamhyung Kim 
174b691f643SNamhyung Kim 		fseek(fp, ehdr.e_phoff, SEEK_SET);
175b691f643SNamhyung Kim 		if (fread(buf, buf_size, 1, fp) != 1)
176b691f643SNamhyung Kim 			goto out_free;
177b691f643SNamhyung Kim 
178b691f643SNamhyung Kim 		for (i = 0, phdr = buf; i < ehdr.e_phnum; i++, phdr++) {
179b691f643SNamhyung Kim 			void *tmp;
180b691f643SNamhyung Kim 
181b691f643SNamhyung Kim 			if (need_swap) {
182b691f643SNamhyung Kim 				phdr->p_type = bswap_32(phdr->p_type);
183b691f643SNamhyung Kim 				phdr->p_offset = bswap_64(phdr->p_offset);
184b691f643SNamhyung Kim 				phdr->p_filesz = bswap_64(phdr->p_filesz);
185b691f643SNamhyung Kim 			}
186b691f643SNamhyung Kim 
187b691f643SNamhyung Kim 			if (phdr->p_type != PT_NOTE)
188b691f643SNamhyung Kim 				continue;
189b691f643SNamhyung Kim 
190b691f643SNamhyung Kim 			buf_size = phdr->p_filesz;
191b691f643SNamhyung Kim 			tmp = realloc(buf, buf_size);
192b691f643SNamhyung Kim 			if (tmp == NULL)
193b691f643SNamhyung Kim 				goto out_free;
194b691f643SNamhyung Kim 
195b691f643SNamhyung Kim 			buf = tmp;
196b691f643SNamhyung Kim 			fseek(fp, phdr->p_offset, SEEK_SET);
197b691f643SNamhyung Kim 			if (fread(buf, buf_size, 1, fp) != 1)
198b691f643SNamhyung Kim 				goto out_free;
199b691f643SNamhyung Kim 
200b691f643SNamhyung Kim 			ret = read_build_id(buf, buf_size, bf, size, need_swap);
201b691f643SNamhyung Kim 			if (ret == 0)
202b691f643SNamhyung Kim 				ret = size;
203b691f643SNamhyung Kim 			break;
204b691f643SNamhyung Kim 		}
205b691f643SNamhyung Kim 	}
206b691f643SNamhyung Kim out_free:
207b691f643SNamhyung Kim 	free(buf);
208b691f643SNamhyung Kim out:
209b691f643SNamhyung Kim 	fclose(fp);
210b691f643SNamhyung Kim 	return ret;
211b691f643SNamhyung Kim }
212b691f643SNamhyung Kim 
213b691f643SNamhyung Kim int sysfs__read_build_id(const char *filename, void *build_id, size_t size)
214b691f643SNamhyung Kim {
215b691f643SNamhyung Kim 	int fd;
216b691f643SNamhyung Kim 	int ret = -1;
217b691f643SNamhyung Kim 	struct stat stbuf;
218b691f643SNamhyung Kim 	size_t buf_size;
219b691f643SNamhyung Kim 	void *buf;
220b691f643SNamhyung Kim 
221b691f643SNamhyung Kim 	fd = open(filename, O_RDONLY);
222b691f643SNamhyung Kim 	if (fd < 0)
223b691f643SNamhyung Kim 		return -1;
224b691f643SNamhyung Kim 
225b691f643SNamhyung Kim 	if (fstat(fd, &stbuf) < 0)
226b691f643SNamhyung Kim 		goto out;
227b691f643SNamhyung Kim 
228b691f643SNamhyung Kim 	buf_size = stbuf.st_size;
229b691f643SNamhyung Kim 	buf = malloc(buf_size);
230b691f643SNamhyung Kim 	if (buf == NULL)
231b691f643SNamhyung Kim 		goto out;
232b691f643SNamhyung Kim 
233b691f643SNamhyung Kim 	if (read(fd, buf, buf_size) != (ssize_t) buf_size)
234b691f643SNamhyung Kim 		goto out_free;
235b691f643SNamhyung Kim 
236b691f643SNamhyung Kim 	ret = read_build_id(buf, buf_size, build_id, size, false);
237b691f643SNamhyung Kim out_free:
238b691f643SNamhyung Kim 	free(buf);
239b691f643SNamhyung Kim out:
240b691f643SNamhyung Kim 	close(fd);
241b691f643SNamhyung Kim 	return ret;
242b691f643SNamhyung Kim }
243b691f643SNamhyung Kim 
2441d037ca1SIrina Tirdea int symsrc__init(struct symsrc *ss, struct dso *dso __maybe_unused,
2451d037ca1SIrina Tirdea 		 const char *name,
246b68e2f91SCody P Schafer 	         enum dso_binary_type type)
247b68e2f91SCody P Schafer {
248b68e2f91SCody P Schafer 	int fd = open(name, O_RDONLY);
249b68e2f91SCody P Schafer 	if (fd < 0)
250b68e2f91SCody P Schafer 		return -1;
251b68e2f91SCody P Schafer 
252b68e2f91SCody P Schafer 	ss->name = strdup(name);
253b68e2f91SCody P Schafer 	if (!ss->name)
254b68e2f91SCody P Schafer 		goto out_close;
255b68e2f91SCody P Schafer 
256*779e24e2SAdrian Hunter 	ss->fd = fd;
257b68e2f91SCody P Schafer 	ss->type = type;
258b68e2f91SCody P Schafer 
259b68e2f91SCody P Schafer 	return 0;
260b68e2f91SCody P Schafer out_close:
261b68e2f91SCody P Schafer 	close(fd);
262b68e2f91SCody P Schafer 	return -1;
263b68e2f91SCody P Schafer }
264b68e2f91SCody P Schafer 
2651d037ca1SIrina Tirdea bool symsrc__possibly_runtime(struct symsrc *ss __maybe_unused)
2663aafe5aeSCody P Schafer {
2673aafe5aeSCody P Schafer 	/* Assume all sym sources could be a runtime image. */
2683aafe5aeSCody P Schafer 	return true;
2693aafe5aeSCody P Schafer }
2703aafe5aeSCody P Schafer 
2711d037ca1SIrina Tirdea bool symsrc__has_symtab(struct symsrc *ss __maybe_unused)
272d26cd12bSCody P Schafer {
273d26cd12bSCody P Schafer 	return false;
274d26cd12bSCody P Schafer }
275d26cd12bSCody P Schafer 
276b68e2f91SCody P Schafer void symsrc__destroy(struct symsrc *ss)
277b68e2f91SCody P Schafer {
278b68e2f91SCody P Schafer 	free(ss->name);
279b68e2f91SCody P Schafer 	close(ss->fd);
280b68e2f91SCody P Schafer }
281b68e2f91SCody P Schafer 
2821d037ca1SIrina Tirdea int dso__synthesize_plt_symbols(struct dso *dso __maybe_unused,
2831d037ca1SIrina Tirdea 				struct symsrc *ss __maybe_unused,
2841d037ca1SIrina Tirdea 				struct map *map __maybe_unused,
2851d037ca1SIrina Tirdea 				symbol_filter_t filter __maybe_unused)
286393be2e3SNamhyung Kim {
287393be2e3SNamhyung Kim 	return 0;
288393be2e3SNamhyung Kim }
289393be2e3SNamhyung Kim 
2901d037ca1SIrina Tirdea int dso__load_sym(struct dso *dso, struct map *map __maybe_unused,
2911d037ca1SIrina Tirdea 		  struct symsrc *ss,
2921d037ca1SIrina Tirdea 		  struct symsrc *runtime_ss __maybe_unused,
2931d037ca1SIrina Tirdea 		  symbol_filter_t filter __maybe_unused,
2941d037ca1SIrina Tirdea 		  int kmodule __maybe_unused)
295393be2e3SNamhyung Kim {
296b691f643SNamhyung Kim 	unsigned char *build_id[BUILD_ID_SIZE];
297b691f643SNamhyung Kim 
298b68e2f91SCody P Schafer 	if (filename__read_build_id(ss->name, build_id, BUILD_ID_SIZE) > 0) {
299b691f643SNamhyung Kim 		dso__set_build_id(dso, build_id);
300b691f643SNamhyung Kim 		return 1;
301b691f643SNamhyung Kim 	}
302393be2e3SNamhyung Kim 	return 0;
303393be2e3SNamhyung Kim }
304393be2e3SNamhyung Kim 
3058e0cf965SAdrian Hunter int file__read_maps(int fd __maybe_unused, bool exe __maybe_unused,
3068e0cf965SAdrian Hunter 		    mapfn_t mapfn __maybe_unused, void *data __maybe_unused,
3078e0cf965SAdrian Hunter 		    bool *is_64_bit __maybe_unused)
3088e0cf965SAdrian Hunter {
3098e0cf965SAdrian Hunter 	return -1;
3108e0cf965SAdrian Hunter }
3118e0cf965SAdrian Hunter 
312afba19d9SAdrian Hunter int kcore_extract__create(struct kcore_extract *kce __maybe_unused)
313afba19d9SAdrian Hunter {
314afba19d9SAdrian Hunter 	return -1;
315afba19d9SAdrian Hunter }
316afba19d9SAdrian Hunter 
317afba19d9SAdrian Hunter void kcore_extract__delete(struct kcore_extract *kce __maybe_unused)
318afba19d9SAdrian Hunter {
319afba19d9SAdrian Hunter }
320afba19d9SAdrian Hunter 
321fc1b691dSAdrian Hunter int kcore_copy(const char *from_dir __maybe_unused,
322fc1b691dSAdrian Hunter 	       const char *to_dir __maybe_unused)
323fc1b691dSAdrian Hunter {
324fc1b691dSAdrian Hunter 	return -1;
325fc1b691dSAdrian Hunter }
326fc1b691dSAdrian Hunter 
327393be2e3SNamhyung Kim void symbol__elf_init(void)
328393be2e3SNamhyung Kim {
329393be2e3SNamhyung Kim }
330