📄 sym.c
字号:
/* * Copyright 2005 Sun Microsystems, Inc. All rights reserved. * * The contents of this file are subject to the terms of the * Common Development and Distribution License, Version 1.0 only. * See the file usr/src/LICENSING.NOTICE in this distribution or * http://www.opensolaris.org/license/ for details. */#pragma ident "@(#)sym.c 1.3 99/07/27 SMI"#include <stdio.h>#include <fcntl.h>#include <ctype.h>#include <string.h>#include <signal.h>#include <errno.h>#include <stdlib.h>#include <stdarg.h>#include <unistd.h>#include <limits.h>#include <sys/types.h>#include <sys/stat.h>#include <libelf.h>#include <link.h>#include <elf.h>#include <sys/machelf.h>#include <kstat.h>#include <sys/cpuvar.h>typedef struct syment { uintptr_t addr; char *name; size_t size;} syment_t;static syment_t *symbol_table;static int nsyms, maxsyms;static char maxsymname[64];#ifdef _ELF64#define elf_getshdr elf64_getshdr#else#define elf_getshdr elf32_getshdr#endifstatic voidadd_symbol(char *name, uintptr_t addr, size_t size){ syment_t *sep; if (nsyms >= maxsyms) { maxsyms += 10000; symbol_table = realloc(symbol_table, maxsyms * sizeof (*sep)); if (symbol_table == NULL) { (void) fprintf(stderr, "can't allocate symbol table\n"); exit(3); } } sep = &symbol_table[nsyms++]; sep->name = name; sep->addr = addr; sep->size = size;}static voidremove_symbol(uintptr_t addr){ int i; syment_t *sep = symbol_table; for (i = 0; i < nsyms; i++, sep++) if (sep->addr == addr) sep->addr = 0;}static voidfake_up_certain_popular_kernel_symbols(void){ kstat_ctl_t *kc; kstat_t *ksp; char *name; if ((kc = kstat_open()) == NULL) return; for (ksp = kc->kc_chain; ksp; ksp = ksp->ks_next) { if (strcmp(ksp->ks_module, "cpu_info") == 0) { if ((name = malloc(20)) == NULL) break; /* * For consistency, keep cpu[0] and toss cpu0 * or any other such symbols. */ if (ksp->ks_instance == 0) remove_symbol((uintptr_t)ksp->ks_private); (void) sprintf(name, "cpu[%d]", ksp->ks_instance); add_symbol(name, (uintptr_t)ksp->ks_private, sizeof (struct cpu)); } } (void) kstat_close(kc);}static intsymcmp(const void *p1, const void *p2){ uintptr_t a1 = ((syment_t *)p1)->addr; uintptr_t a2 = ((syment_t *)p2)->addr; if (a1 < a2) return (-1); if (a1 > a2) return (1); return (0);}intsymtab_init(void){ Elf *elf; Elf_Scn *scn = NULL; Sym *symtab, *symp, *lastsym; char *strtab; uint_t cnt; int fd; int i; int strindex = -1; if ((fd = open("/dev/ksyms", O_RDONLY)) == -1) return (-1); (void) elf_version(EV_CURRENT); elf = elf_begin(fd, ELF_C_READ, NULL); for (cnt = 1; (scn = elf_nextscn(elf, scn)) != NULL; cnt++) { Shdr *shdr = elf_getshdr(scn); if (shdr->sh_type == SHT_SYMTAB) { symtab = (Sym *)elf_getdata(scn, NULL)->d_buf; nsyms = shdr->sh_size / shdr->sh_entsize; strindex = shdr->sh_link; } } for (cnt = 1; (scn = elf_nextscn(elf, scn)) != NULL; cnt++) { if (cnt == strindex) strtab = (char *)elf_getdata(scn, NULL)->d_buf; } lastsym = symtab + nsyms; nsyms = 0; for (symp = symtab; symp < lastsym; symp++) if ((uint_t)ELF32_ST_TYPE(symp->st_info) <= STT_FUNC && symp->st_size != 0) add_symbol(symp->st_name + strtab, (uintptr_t)symp->st_value, (size_t)symp->st_size); fake_up_certain_popular_kernel_symbols(); (void) sprintf(maxsymname, "0x%lx", ULONG_MAX); add_symbol(maxsymname, ULONG_MAX, 1); qsort(symbol_table, nsyms, sizeof (syment_t), symcmp); /* * Destroy all duplicate symbols, then sort it again. */ for (i = 0; i < nsyms - 1; i++) if (symbol_table[i].addr == symbol_table[i + 1].addr) symbol_table[i].addr = 0; qsort(symbol_table, nsyms, sizeof (syment_t), symcmp); while (symbol_table[1].addr == 0) { symbol_table++; nsyms--; } symbol_table[0].name = "(usermode)"; symbol_table[0].addr = 0; symbol_table[0].size = 1; return (0);}char *addr_to_sym(uintptr_t addr, uintptr_t *offset, size_t *sizep){ int lo = 0; int hi = nsyms - 1; int mid; syment_t *sep; while (hi - lo > 1) { mid = (lo + hi) / 2; if (addr >= symbol_table[mid].addr) { lo = mid; } else { hi = mid; } } sep = &symbol_table[lo]; *offset = addr - sep->addr; *sizep = sep->size; return (sep->name);}uintptr_tsym_to_addr(char *name){ int i; syment_t *sep = symbol_table; for (i = 0; i < nsyms; i++) { if (strcmp(name, sep->name) == 0) return (sep->addr); sep++; } return (NULL);}size_tsym_size(char *name){ int i; syment_t *sep = symbol_table; for (i = 0; i < nsyms; i++) { if (strcmp(name, sep->name) == 0) return (sep->size); sep++; } return (0);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -