Print this page
11210 libm should be cstyle(1ONBLD) clean
*** 20,29 ****
--- 20,30 ----
*/
/*
* Copyright 2011 Nexenta Systems, Inc. All rights reserved.
*/
+
/*
* Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
*** 35,61 ****
#include <procfs.h>
#include <string.h>
#include <sys/stat.h>
#if defined(__sparcv9) || defined(__amd64)
-
#define Elf_Ehdr Elf64_Ehdr
#define Elf_Phdr Elf64_Phdr
#define Elf_Shdr Elf64_Shdr
#define Elf_Sym Elf64_Sym
#define ELF_ST_BIND ELF64_ST_BIND
#define ELF_ST_TYPE ELF64_ST_TYPE
-
#else
-
#define Elf_Ehdr Elf32_Ehdr
#define Elf_Phdr Elf32_Phdr
#define Elf_Shdr Elf32_Shdr
#define Elf_Sym Elf32_Sym
#define ELF_ST_BIND ELF32_ST_BIND
#define ELF_ST_TYPE ELF32_ST_TYPE
-
#endif /* __sparcv9 */
/* semi-permanent data established by __fex_sym_init */
static prmap_t *pm = NULL; /* prmap_t array */
static int npm = 0; /* number of entries in pm */
--- 36,58 ----
*** 79,110 ****
int i;
/* clear out the previous prmap_t list */
if (pm != NULL)
free(pm);
pm = lpm = NULL;
npm = 0;
/* get the current prmap_t list */
if (stat("/proc/self/map", &statbuf) < 0 || statbuf.st_size <= 0 ||
! (pm = (prmap_t*)malloc(statbuf.st_size)) == NULL)
return;
! if ((i = open("/proc/self/map", O_RDONLY)) < 0)
! {
free(pm);
pm = NULL;
return;
}
n = read(i, pm, statbuf.st_size);
close(i);
! if (n != statbuf.st_size)
! {
free(pm);
pm = NULL;
}
- else
- npm = (int) (n / sizeof(prmap_t));
}
/* read ELF program headers and symbols; return -1 on error, 0 otherwise */
static int
__fex_read_syms(int fd)
--- 76,109 ----
int i;
/* clear out the previous prmap_t list */
if (pm != NULL)
free(pm);
+
pm = lpm = NULL;
npm = 0;
/* get the current prmap_t list */
if (stat("/proc/self/map", &statbuf) < 0 || statbuf.st_size <= 0 ||
! (pm = (prmap_t *)malloc(statbuf.st_size)) == NULL)
return;
!
! if ((i = open("/proc/self/map", O_RDONLY)) < 0) {
free(pm);
pm = NULL;
return;
}
+
n = read(i, pm, statbuf.st_size);
close(i);
!
! if (n != statbuf.st_size) {
free(pm);
pm = NULL;
+ } else {
+ npm = (int)(n / sizeof (prmap_t));
}
}
/* read ELF program headers and symbols; return -1 on error, 0 otherwise */
static int
__fex_read_syms(int fd)
*** 112,306 ****
Elf_Ehdr h;
Elf_Shdr *sh;
int i, size;
/* read the ELF header */
! if (read(fd, &h, sizeof(h)) != sizeof(h))
! return -1;
! if (h.e_ident[EI_MAG0] != ELFMAG0 ||
! h.e_ident[EI_MAG1] != ELFMAG1 ||
! h.e_ident[EI_MAG2] != ELFMAG2 ||
! h.e_ident[EI_MAG3] != ELFMAG3 ||
! h.e_phentsize != sizeof(Elf_Phdr) ||
! h.e_shentsize != sizeof(Elf_Shdr))
! return -1;
/* get space for the program headers */
size = h.e_phnum * h.e_phentsize;
! if (size > phsize)
! {
if (ph)
free(ph);
phsize = nph = 0;
! if ((ph = (Elf_Phdr*)malloc(size)) == NULL)
! return -1;
phsize = size;
}
/* read the program headers */
! if (lseek(fd, h.e_phoff, SEEK_SET) != h.e_phoff ||
! read(fd, ph, size) != (ssize_t)size)
! {
nph = 0;
! return -1;
}
nph = h.e_phnum;
/* read the section headers */
size = h.e_shnum * h.e_shentsize;
! if ((sh = (Elf_Shdr*)malloc(size)) == NULL)
! return -1;
! if (lseek(fd, h.e_shoff, SEEK_SET) != h.e_shoff ||
! read(fd, sh, size) != (ssize_t)size)
! {
free(sh);
! return -1;
}
/* find the symtab section header */
! for (i = 0; i < h.e_shnum; i++)
! {
if (sh[i].sh_type == SHT_SYMTAB)
break; /* assume there is only one */
}
! if (i == h.e_shnum || sh[i].sh_size == 0 ||
! sh[i].sh_entsize != sizeof(Elf_Sym) ||
! sh[i].sh_link < 1 || sh[i].sh_link >= h.e_shnum ||
! sh[sh[i].sh_link].sh_type != SHT_STRTAB ||
! sh[sh[i].sh_link].sh_size == 0)
! {
free(sh);
! return -1;
}
/* get space for the symbol and string tables */
! size = (int) (sh[i].sh_size + sh[sh[i].sh_link].sh_size);
! if (size > stbufsize)
! {
if (stbuf)
free(stbuf);
stbufsize = nsyms = 0;
! if ((stbuf = (char*)malloc(size)) == NULL)
! {
free(sh);
! return -1;
}
stbufsize = size;
}
/* read the symbol and string tables */
if (lseek(fd, sh[i].sh_offset, SEEK_SET) != sh[i].sh_offset ||
read(fd, stbuf, sh[i].sh_size) != sh[i].sh_size ||
lseek(fd, sh[sh[i].sh_link].sh_offset, SEEK_SET) !=
sh[sh[i].sh_link].sh_offset ||
read(fd, stbuf + sh[i].sh_size, sh[sh[i].sh_link].sh_size) !=
! sh[sh[i].sh_link].sh_size)
! {
free(sh);
return (-1);
}
! nsyms = (int) (sh[i].sh_size / sh[i].sh_entsize);
! stoffset = (int) sh[i].sh_size;
free(sh);
return (0);
}
! /* find the symbol corresponding to the given text address;
! return NULL on error, symbol address otherwise */
char *
__fex_sym(char *a, char **name)
{
Elf_Sym *s;
unsigned long fo, va, value;
int fd, i, j, nm;
! char fname[PRMAPSZ+20];
/* see if the last prmap_t found contains the indicated address */
! if (lpm)
! {
! if (a >= (char*)lpm->pr_vaddr && a < (char*)lpm->pr_vaddr +
lpm->pr_size)
goto cont;
}
/* look for a prmap_t that contains the indicated address */
! for (i = 0; i < npm; i++)
! {
! if (a >= (char*)pm[i].pr_vaddr && a < (char*)pm[i].pr_vaddr +
pm[i].pr_size)
break;
}
if (i == npm)
! return NULL;
/* get an open file descriptor for the mapped object */
if (pm[i].pr_mapname[0] == '\0')
! return NULL;
strcpy(fname, "/proc/self/object/");
strncat(fname, pm[i].pr_mapname, PRMAPSZ);
fd = open(fname, O_RDONLY);
if (fd < 0)
! return NULL;
/* read the program headers and symbols */
lpm = NULL;
j = __fex_read_syms(fd);
close(fd);
if (j < 0)
! return NULL;
lpm = &pm[i];
cont:
/* compute the file offset corresponding to the mapped address */
! fo = (a - (char*)lpm->pr_vaddr) + lpm->pr_offset;
/* find the program header containing the file offset */
! for (i = 0; i < nph; i++)
! {
! if (ph[i].p_type == PT_LOAD && fo >= ph[i].p_offset &&
! fo < ph[i].p_offset + ph[i].p_filesz)
break;
}
if (i == nph)
! return NULL;
/* compute the virtual address corresponding to the file offset */
va = (fo - ph[i].p_offset) + ph[i].p_vaddr;
! /* find the symbol in this segment with the highest value
! less than or equal to the virtual address */
! s = (Elf_Sym*)stbuf;
value = nm = 0;
! for (j = 0; j < nsyms; j++)
! {
if (s[j].st_name == 0 || s[j].st_shndx == SHN_UNDEF ||
! (ELF_ST_BIND(s[j].st_info) != STB_LOCAL &&
! ELF_ST_BIND(s[j].st_info) != STB_GLOBAL &&
! ELF_ST_BIND(s[j].st_info) != STB_WEAK) ||
! (ELF_ST_TYPE(s[j].st_info) != STT_NOTYPE &&
! ELF_ST_TYPE(s[j].st_info) != STT_OBJECT &&
! ELF_ST_TYPE(s[j].st_info) != STT_FUNC))
! {
continue;
- }
! if (s[j].st_value < ph[i].p_vaddr || s[j].st_value >= ph[i].p_vaddr
! + ph[i].p_memsz)
! {
continue;
- }
if (s[j].st_value < value || s[j].st_value > va)
continue;
value = s[j].st_value;
nm = s[j].st_name;
}
if (nm == 0)
! return NULL;
/* pass back the name and return the mapped address of the symbol */
*name = stbuf + stoffset + nm;
fo = (value - ph[i].p_vaddr) + ph[i].p_offset;
! return (char*)lpm->pr_vaddr + (fo - lpm->pr_offset);
}
--- 111,311 ----
Elf_Ehdr h;
Elf_Shdr *sh;
int i, size;
/* read the ELF header */
! if (read(fd, &h, sizeof (h)) != sizeof (h))
! return (-1);
!
! if (h.e_ident[EI_MAG0] != ELFMAG0 || h.e_ident[EI_MAG1] != ELFMAG1 ||
! h.e_ident[EI_MAG2] != ELFMAG2 || h.e_ident[EI_MAG3] != ELFMAG3 ||
! h.e_phentsize != sizeof (Elf_Phdr) || h.e_shentsize !=
! sizeof (Elf_Shdr))
! return (-1);
/* get space for the program headers */
size = h.e_phnum * h.e_phentsize;
!
! if (size > phsize) {
if (ph)
free(ph);
+
phsize = nph = 0;
!
! if ((ph = (Elf_Phdr *)malloc(size)) == NULL)
! return (-1);
!
phsize = size;
}
/* read the program headers */
! if (lseek(fd, h.e_phoff, SEEK_SET) != h.e_phoff || read(fd, ph, size) !=
! (ssize_t)size) {
nph = 0;
! return (-1);
}
+
nph = h.e_phnum;
/* read the section headers */
size = h.e_shnum * h.e_shentsize;
!
! if ((sh = (Elf_Shdr *)malloc(size)) == NULL)
! return (-1);
!
! if (lseek(fd, h.e_shoff, SEEK_SET) != h.e_shoff || read(fd, sh, size) !=
! (ssize_t)size) {
free(sh);
! return (-1);
}
/* find the symtab section header */
! for (i = 0; i < h.e_shnum; i++) {
if (sh[i].sh_type == SHT_SYMTAB)
break; /* assume there is only one */
}
!
! if (i == h.e_shnum || sh[i].sh_size == 0 || sh[i].sh_entsize !=
! sizeof (Elf_Sym) || sh[i].sh_link < 1 || sh[i].sh_link >=
! h.e_shnum || sh[sh[i].sh_link].sh_type != SHT_STRTAB ||
! sh[sh[i].sh_link].sh_size == 0) {
free(sh);
! return (-1);
}
/* get space for the symbol and string tables */
! size = (int)(sh[i].sh_size + sh[sh[i].sh_link].sh_size);
!
! if (size > stbufsize) {
if (stbuf)
free(stbuf);
+
stbufsize = nsyms = 0;
!
! if ((stbuf = (char *)malloc(size)) == NULL) {
free(sh);
! return (-1);
}
+
stbufsize = size;
}
/* read the symbol and string tables */
if (lseek(fd, sh[i].sh_offset, SEEK_SET) != sh[i].sh_offset ||
read(fd, stbuf, sh[i].sh_size) != sh[i].sh_size ||
lseek(fd, sh[sh[i].sh_link].sh_offset, SEEK_SET) !=
sh[sh[i].sh_link].sh_offset ||
read(fd, stbuf + sh[i].sh_size, sh[sh[i].sh_link].sh_size) !=
! sh[sh[i].sh_link].sh_size) {
free(sh);
return (-1);
}
!
! nsyms = (int)(sh[i].sh_size / sh[i].sh_entsize);
! stoffset = (int)sh[i].sh_size;
free(sh);
return (0);
}
! /*
! * find the symbol corresponding to the given text address;
! * return NULL on error, symbol address otherwise
! */
char *
__fex_sym(char *a, char **name)
{
Elf_Sym *s;
unsigned long fo, va, value;
int fd, i, j, nm;
! char fname[PRMAPSZ + 20];
/* see if the last prmap_t found contains the indicated address */
! if (lpm) {
! if (a >= (char *)lpm->pr_vaddr && a < (char *)lpm->pr_vaddr +
lpm->pr_size)
goto cont;
}
/* look for a prmap_t that contains the indicated address */
! for (i = 0; i < npm; i++) {
! if (a >= (char *)pm[i].pr_vaddr && a < (char *)pm[i].pr_vaddr +
pm[i].pr_size)
break;
}
+
if (i == npm)
! return (NULL);
/* get an open file descriptor for the mapped object */
if (pm[i].pr_mapname[0] == '\0')
! return (NULL);
!
strcpy(fname, "/proc/self/object/");
strncat(fname, pm[i].pr_mapname, PRMAPSZ);
fd = open(fname, O_RDONLY);
+
if (fd < 0)
! return (NULL);
/* read the program headers and symbols */
lpm = NULL;
j = __fex_read_syms(fd);
close(fd);
+
if (j < 0)
! return (NULL);
!
lpm = &pm[i];
cont:
/* compute the file offset corresponding to the mapped address */
! fo = (a - (char *)lpm->pr_vaddr) + lpm->pr_offset;
/* find the program header containing the file offset */
! for (i = 0; i < nph; i++) {
! if (ph[i].p_type == PT_LOAD && fo >= ph[i].p_offset && fo <
! ph[i].p_offset + ph[i].p_filesz)
break;
}
+
if (i == nph)
! return (NULL);
/* compute the virtual address corresponding to the file offset */
va = (fo - ph[i].p_offset) + ph[i].p_vaddr;
! /*
! * find the symbol in this segment with the highest value
! * less than or equal to the virtual address
! */
! s = (Elf_Sym *)stbuf;
value = nm = 0;
!
! for (j = 0; j < nsyms; j++) {
if (s[j].st_name == 0 || s[j].st_shndx == SHN_UNDEF ||
! (ELF_ST_BIND(s[j].st_info) != STB_LOCAL && ELF_ST_BIND(
! s[j].st_info) != STB_GLOBAL && ELF_ST_BIND(s[j].st_info) !=
! STB_WEAK) || (ELF_ST_TYPE(s[j].st_info) != STT_NOTYPE &&
! ELF_ST_TYPE(s[j].st_info) != STT_OBJECT && ELF_ST_TYPE(
! s[j].st_info) != STT_FUNC))
continue;
! if (s[j].st_value < ph[i].p_vaddr || s[j].st_value >=
! ph[i].p_vaddr + ph[i].p_memsz)
continue;
if (s[j].st_value < value || s[j].st_value > va)
continue;
value = s[j].st_value;
nm = s[j].st_name;
}
+
if (nm == 0)
! return (NULL);
/* pass back the name and return the mapped address of the symbol */
*name = stbuf + stoffset + nm;
fo = (value - ph[i].p_vaddr) + ph[i].p_offset;
! return ((char *)lpm->pr_vaddr + (fo - lpm->pr_offset));
}