162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
262306a36Sopenharmony_ci#include "symbol/kallsyms.h"
362306a36Sopenharmony_ci#include "api/io.h"
462306a36Sopenharmony_ci#include <stdio.h>
562306a36Sopenharmony_ci#include <sys/stat.h>
662306a36Sopenharmony_ci#include <fcntl.h>
762306a36Sopenharmony_ci
862306a36Sopenharmony_ciu8 kallsyms2elf_type(char type)
962306a36Sopenharmony_ci{
1062306a36Sopenharmony_ci	type = tolower(type);
1162306a36Sopenharmony_ci	return (type == 't' || type == 'w') ? STT_FUNC : STT_OBJECT;
1262306a36Sopenharmony_ci}
1362306a36Sopenharmony_ci
1462306a36Sopenharmony_cibool kallsyms__is_function(char symbol_type)
1562306a36Sopenharmony_ci{
1662306a36Sopenharmony_ci	symbol_type = toupper(symbol_type);
1762306a36Sopenharmony_ci	return symbol_type == 'T' || symbol_type == 'W';
1862306a36Sopenharmony_ci}
1962306a36Sopenharmony_ci
2062306a36Sopenharmony_cistatic void read_to_eol(struct io *io)
2162306a36Sopenharmony_ci{
2262306a36Sopenharmony_ci	int ch;
2362306a36Sopenharmony_ci
2462306a36Sopenharmony_ci	for (;;) {
2562306a36Sopenharmony_ci		ch = io__get_char(io);
2662306a36Sopenharmony_ci		if (ch < 0 || ch == '\n')
2762306a36Sopenharmony_ci			return;
2862306a36Sopenharmony_ci	}
2962306a36Sopenharmony_ci}
3062306a36Sopenharmony_ci
3162306a36Sopenharmony_ciint kallsyms__parse(const char *filename, void *arg,
3262306a36Sopenharmony_ci		    int (*process_symbol)(void *arg, const char *name,
3362306a36Sopenharmony_ci					  char type, u64 start))
3462306a36Sopenharmony_ci{
3562306a36Sopenharmony_ci	struct io io;
3662306a36Sopenharmony_ci	char bf[BUFSIZ];
3762306a36Sopenharmony_ci	int err;
3862306a36Sopenharmony_ci
3962306a36Sopenharmony_ci	io.fd = open(filename, O_RDONLY, 0);
4062306a36Sopenharmony_ci
4162306a36Sopenharmony_ci	if (io.fd < 0)
4262306a36Sopenharmony_ci		return -1;
4362306a36Sopenharmony_ci
4462306a36Sopenharmony_ci	io__init(&io, io.fd, bf, sizeof(bf));
4562306a36Sopenharmony_ci
4662306a36Sopenharmony_ci	err = 0;
4762306a36Sopenharmony_ci	while (!io.eof) {
4862306a36Sopenharmony_ci		__u64 start;
4962306a36Sopenharmony_ci		int ch;
5062306a36Sopenharmony_ci		size_t i;
5162306a36Sopenharmony_ci		char symbol_type;
5262306a36Sopenharmony_ci		char symbol_name[KSYM_NAME_LEN + 1];
5362306a36Sopenharmony_ci
5462306a36Sopenharmony_ci		if (io__get_hex(&io, &start) != ' ') {
5562306a36Sopenharmony_ci			read_to_eol(&io);
5662306a36Sopenharmony_ci			continue;
5762306a36Sopenharmony_ci		}
5862306a36Sopenharmony_ci		symbol_type = io__get_char(&io);
5962306a36Sopenharmony_ci		if (io__get_char(&io) != ' ') {
6062306a36Sopenharmony_ci			read_to_eol(&io);
6162306a36Sopenharmony_ci			continue;
6262306a36Sopenharmony_ci		}
6362306a36Sopenharmony_ci		for (i = 0; i < sizeof(symbol_name); i++) {
6462306a36Sopenharmony_ci			ch = io__get_char(&io);
6562306a36Sopenharmony_ci			if (ch < 0 || ch == '\n')
6662306a36Sopenharmony_ci				break;
6762306a36Sopenharmony_ci			symbol_name[i]  = ch;
6862306a36Sopenharmony_ci		}
6962306a36Sopenharmony_ci		symbol_name[i]  = '\0';
7062306a36Sopenharmony_ci
7162306a36Sopenharmony_ci		err = process_symbol(arg, symbol_name, symbol_type, start);
7262306a36Sopenharmony_ci		if (err)
7362306a36Sopenharmony_ci			break;
7462306a36Sopenharmony_ci	}
7562306a36Sopenharmony_ci
7662306a36Sopenharmony_ci	close(io.fd);
7762306a36Sopenharmony_ci	return err;
7862306a36Sopenharmony_ci}
79