1e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng#include "symbol.h"
2e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
3e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng#include <stdio.h>
4e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng#include <fcntl.h>
5e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng#include <string.h>
6e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng#include <byteswap.h>
7e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng#include <sys/stat.h>
8e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
9e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
10e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic bool check_need_swap(int file_endian)
11e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{
12e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	const int data = 1;
13e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	u8 *check = (u8 *)&data;
14e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	int host_endian;
15e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
16e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	if (check[0] == 1)
17e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		host_endian = ELFDATA2LSB;
18e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	else
19e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		host_endian = ELFDATA2MSB;
20e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
21e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	return host_endian != file_endian;
22e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng}
23e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
24e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng#define NOTE_ALIGN(sz) (((sz) + 3) & ~3)
25e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
26e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng#define NT_GNU_BUILD_ID	3
27e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
28e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic int read_build_id(void *note_data, size_t note_len, void *bf,
29e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			 size_t size, bool need_swap)
30e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{
31e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	struct {
32e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		u32 n_namesz;
33e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		u32 n_descsz;
34e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		u32 n_type;
35e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	} *nhdr;
36e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	void *ptr;
37e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
38e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	ptr = note_data;
39e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	while (ptr < (note_data + note_len)) {
40e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		const char *name;
41e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		size_t namesz, descsz;
42e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
43e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		nhdr = ptr;
44e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		if (need_swap) {
45e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			nhdr->n_namesz = bswap_32(nhdr->n_namesz);
46e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			nhdr->n_descsz = bswap_32(nhdr->n_descsz);
47e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			nhdr->n_type = bswap_32(nhdr->n_type);
48e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		}
49e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
50e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		namesz = NOTE_ALIGN(nhdr->n_namesz);
51e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		descsz = NOTE_ALIGN(nhdr->n_descsz);
52e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
53e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		ptr += sizeof(*nhdr);
54e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		name = ptr;
55e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		ptr += namesz;
56e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		if (nhdr->n_type == NT_GNU_BUILD_ID &&
57e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		    nhdr->n_namesz == sizeof("GNU")) {
58e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			if (memcmp(name, "GNU", sizeof("GNU")) == 0) {
59e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng				size_t sz = min(size, descsz);
60e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng				memcpy(bf, ptr, sz);
61e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng				memset(bf + sz, 0, size - sz);
62e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng				return 0;
63e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			}
64e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		}
65e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		ptr += descsz;
66e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	}
67e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
68e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	return -1;
69e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng}
70e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
71e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengint filename__read_debuglink(const char *filename __maybe_unused,
72e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			     char *debuglink __maybe_unused,
73e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			     size_t size __maybe_unused)
74e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{
75e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	return -1;
76e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng}
77e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
78e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng/*
79e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng * Just try PT_NOTE header otherwise fails
80e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng */
81e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengint filename__read_build_id(const char *filename, void *bf, size_t size)
82e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{
83e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	FILE *fp;
84e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	int ret = -1;
85e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	bool need_swap = false;
86e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	u8 e_ident[EI_NIDENT];
87e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	size_t buf_size;
88e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	void *buf;
89e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	int i;
90e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
91e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	fp = fopen(filename, "r");
92e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	if (fp == NULL)
93e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		return -1;
94e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
95e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	if (fread(e_ident, sizeof(e_ident), 1, fp) != 1)
96e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		goto out;
97e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
98e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	if (memcmp(e_ident, ELFMAG, SELFMAG) ||
99e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	    e_ident[EI_VERSION] != EV_CURRENT)
100e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		goto out;
101e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
102e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	need_swap = check_need_swap(e_ident[EI_DATA]);
103e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
104e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	/* for simplicity */
105e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	fseek(fp, 0, SEEK_SET);
106e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
107e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	if (e_ident[EI_CLASS] == ELFCLASS32) {
108e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		Elf32_Ehdr ehdr;
109e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		Elf32_Phdr *phdr;
110e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
111e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		if (fread(&ehdr, sizeof(ehdr), 1, fp) != 1)
112e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			goto out;
113e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
114e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		if (need_swap) {
115e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			ehdr.e_phoff = bswap_32(ehdr.e_phoff);
116e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			ehdr.e_phentsize = bswap_16(ehdr.e_phentsize);
117e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			ehdr.e_phnum = bswap_16(ehdr.e_phnum);
118e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		}
119e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
120e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		buf_size = ehdr.e_phentsize * ehdr.e_phnum;
121e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		buf = malloc(buf_size);
122e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		if (buf == NULL)
123e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			goto out;
124e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
125e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		fseek(fp, ehdr.e_phoff, SEEK_SET);
126e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		if (fread(buf, buf_size, 1, fp) != 1)
127e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			goto out_free;
128e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
129e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		for (i = 0, phdr = buf; i < ehdr.e_phnum; i++, phdr++) {
130e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			void *tmp;
131e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
132e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			if (need_swap) {
133e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng				phdr->p_type = bswap_32(phdr->p_type);
134e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng				phdr->p_offset = bswap_32(phdr->p_offset);
135e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng				phdr->p_filesz = bswap_32(phdr->p_filesz);
136e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			}
137e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
138e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			if (phdr->p_type != PT_NOTE)
139e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng				continue;
140e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
141e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			buf_size = phdr->p_filesz;
142e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			tmp = realloc(buf, buf_size);
143e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			if (tmp == NULL)
144e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng				goto out_free;
145e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
146e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			buf = tmp;
147e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			fseek(fp, phdr->p_offset, SEEK_SET);
148e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			if (fread(buf, buf_size, 1, fp) != 1)
149e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng				goto out_free;
150e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
151e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			ret = read_build_id(buf, buf_size, bf, size, need_swap);
152e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			if (ret == 0)
153e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng				ret = size;
154e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			break;
155e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		}
156e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	} else {
157e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		Elf64_Ehdr ehdr;
158e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		Elf64_Phdr *phdr;
159e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
160e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		if (fread(&ehdr, sizeof(ehdr), 1, fp) != 1)
161e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			goto out;
162e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
163e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		if (need_swap) {
164e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			ehdr.e_phoff = bswap_64(ehdr.e_phoff);
165e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			ehdr.e_phentsize = bswap_16(ehdr.e_phentsize);
166e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			ehdr.e_phnum = bswap_16(ehdr.e_phnum);
167e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		}
168e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
169e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		buf_size = ehdr.e_phentsize * ehdr.e_phnum;
170e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		buf = malloc(buf_size);
171e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		if (buf == NULL)
172e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			goto out;
173e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
174e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		fseek(fp, ehdr.e_phoff, SEEK_SET);
175e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		if (fread(buf, buf_size, 1, fp) != 1)
176e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			goto out_free;
177e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
178e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		for (i = 0, phdr = buf; i < ehdr.e_phnum; i++, phdr++) {
179e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			void *tmp;
180e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
181e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			if (need_swap) {
182e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng				phdr->p_type = bswap_32(phdr->p_type);
183e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng				phdr->p_offset = bswap_64(phdr->p_offset);
184e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng				phdr->p_filesz = bswap_64(phdr->p_filesz);
185e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			}
186e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
187e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			if (phdr->p_type != PT_NOTE)
188e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng				continue;
189e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
190e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			buf_size = phdr->p_filesz;
191e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			tmp = realloc(buf, buf_size);
192e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			if (tmp == NULL)
193e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng				goto out_free;
194e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
195e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			buf = tmp;
196e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			fseek(fp, phdr->p_offset, SEEK_SET);
197e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			if (fread(buf, buf_size, 1, fp) != 1)
198e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng				goto out_free;
199e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
200e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			ret = read_build_id(buf, buf_size, bf, size, need_swap);
201e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			if (ret == 0)
202e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng				ret = size;
203e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			break;
204e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		}
205e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	}
206e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengout_free:
207e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	free(buf);
208e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengout:
209e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	fclose(fp);
210e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	return ret;
211e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng}
212e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
213e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengint sysfs__read_build_id(const char *filename, void *build_id, size_t size)
214e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{
215e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	int fd;
216e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	int ret = -1;
217e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	struct stat stbuf;
218e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	size_t buf_size;
219e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	void *buf;
220e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
221e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	fd = open(filename, O_RDONLY);
222e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	if (fd < 0)
223e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		return -1;
224e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
225e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	if (fstat(fd, &stbuf) < 0)
226e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		goto out;
227e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
228e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	buf_size = stbuf.st_size;
229e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	buf = malloc(buf_size);
230e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	if (buf == NULL)
231e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		goto out;
232e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
233e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	if (read(fd, buf, buf_size) != (ssize_t) buf_size)
234e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		goto out_free;
235e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
236e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	ret = read_build_id(buf, buf_size, build_id, size, false);
237e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengout_free:
238e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	free(buf);
239e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengout:
240e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	close(fd);
241e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	return ret;
242e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng}
243e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
244e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengint symsrc__init(struct symsrc *ss, struct dso *dso __maybe_unused,
245e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		 const char *name,
246e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	         enum dso_binary_type type)
247e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{
248e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	int fd = open(name, O_RDONLY);
249e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	if (fd < 0)
250e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		return -1;
251e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
252e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	ss->name = strdup(name);
253e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	if (!ss->name)
254e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		goto out_close;
255e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
256e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	ss->type = type;
257e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
258e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	return 0;
259e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengout_close:
260e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	close(fd);
261e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	return -1;
262e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng}
263e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
264e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengbool symsrc__possibly_runtime(struct symsrc *ss __maybe_unused)
265e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{
266e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	/* Assume all sym sources could be a runtime image. */
267e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	return true;
268e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng}
269e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
270e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengbool symsrc__has_symtab(struct symsrc *ss __maybe_unused)
271e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{
272e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	return false;
273e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng}
274e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
275e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengvoid symsrc__destroy(struct symsrc *ss)
276e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{
277e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	free(ss->name);
278e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	close(ss->fd);
279e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng}
280e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
281e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengint dso__synthesize_plt_symbols(struct dso *dso __maybe_unused,
282e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng				struct symsrc *ss __maybe_unused,
283e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng				struct map *map __maybe_unused,
284e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng				symbol_filter_t filter __maybe_unused)
285e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{
286e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	return 0;
287e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng}
288e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
289e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengint dso__load_sym(struct dso *dso, struct map *map __maybe_unused,
290e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		  struct symsrc *ss,
291e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		  struct symsrc *runtime_ss __maybe_unused,
292e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		  symbol_filter_t filter __maybe_unused,
293e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		  int kmodule __maybe_unused)
294e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{
295e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	unsigned char *build_id[BUILD_ID_SIZE];
296e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
297e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	if (filename__read_build_id(ss->name, build_id, BUILD_ID_SIZE) > 0) {
298e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		dso__set_build_id(dso, build_id);
299e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		return 1;
300e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	}
301e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	return 0;
302e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng}
303e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
304e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengint file__read_maps(int fd __maybe_unused, bool exe __maybe_unused,
305e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		    mapfn_t mapfn __maybe_unused, void *data __maybe_unused,
306e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		    bool *is_64_bit __maybe_unused)
307e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{
308e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	return -1;
309e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng}
310e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
311e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengvoid symbol__elf_init(void)
312e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{
313e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng}
314