version 1.9, 2004/10/09 20:17:52 |
version 1.10, 2004/10/09 20:26:57 |
|
|
* THE POSSIBILITY OF SUCH DAMAGE. |
* THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
*/ |
|
|
#if ELF_TARG_CLASS == ELFCLASS32 |
#include <sys/param.h> |
|
#include <sys/mman.h> |
|
#include <unistd.h> |
|
#include <a.out.h> |
|
#include <elf_abi.h> |
|
#include <errno.h> |
|
#include <err.h> |
|
#include <stdio.h> |
|
#include <stdlib.h> |
|
#include <string.h> |
|
#include <ctype.h> |
|
#include "elfuncs.h" |
|
#include "util.h" |
|
|
|
#if ELFSIZE == 32 |
#define swap_addr swap32 |
#define swap_addr swap32 |
#define swap_off swap32 |
#define swap_off swap32 |
#define swap_sword swap32 |
#define swap_sword swap32 |
|
|
#define swap_xword swap32 |
#define swap_xword swap32 |
#define swap_half swap16 |
#define swap_half swap16 |
#define swap_quarter swap16 |
#define swap_quarter swap16 |
#elif ELF_TARG_CLASS == ELFCLASS64 |
#define elf_fix_header elf32_fix_header |
|
#define elf_load_shdrs elf32_load_shdrs |
|
#define elf_fix_shdrs elf32_fix_shdrs |
|
#define elf_fix_phdrs elf32_fix_phdrs |
|
#define elf_fix_sym elf32_fix_sym |
|
#define elf_size elf32_size |
|
#define elf_symload elf32_symload |
|
#define elf2nlist elf32_2nlist |
|
#define elf_shn2type elf32_shn2type |
|
#elif ELFSIZE == 64 |
#define swap_addr swap64 |
#define swap_addr swap64 |
#define swap_off swap64 |
#define swap_off swap64 |
#ifdef __alpha__ |
#ifdef __alpha__ |
|
|
#define swap_xword swap64 |
#define swap_xword swap64 |
#define swap_half swap64 |
#define swap_half swap64 |
#define swap_quarter swap16 |
#define swap_quarter swap16 |
|
#define elf_fix_header elf64_fix_header |
|
#define elf_load_shdrs elf64_load_shdrs |
|
#define elf_fix_shdrs elf64_fix_shdrs |
|
#define elf_fix_phdrs elf64_fix_phdrs |
|
#define elf_fix_sym elf64_fix_sym |
|
#define elf_size elf64_size |
|
#define elf_symload elf64_symload |
|
#define elf2nlist elf64_2nlist |
|
#define elf_shn2type elf64_shn2type |
#else |
#else |
#error "Unsupported ELF class" |
#error "Unsupported ELF class" |
#endif |
#endif |
|
|
return (1); |
return (1); |
} |
} |
|
|
|
Elf_Shdr * |
|
elf_load_shdrs(const char *name, FILE *fp, off_t foff, Elf_Ehdr *head) |
|
{ |
|
Elf_Shdr *shdr; |
|
|
|
elf_fix_header(head); |
|
|
|
if ((shdr = malloc(head->e_shentsize * head->e_shnum)) == NULL) { |
|
warn("%s: malloc shdr", name); |
|
return (NULL); |
|
} |
|
|
|
if (fseeko(fp, foff + head->e_shoff, SEEK_SET)) { |
|
warn("%s: fseeko", name); |
|
free(shdr); |
|
return (NULL); |
|
} |
|
|
|
if (fread(shdr, head->e_shentsize, head->e_shnum, fp) != head->e_shnum) { |
|
warnx("%s: premature EOF", name); |
|
free(shdr); |
|
return (NULL); |
|
} |
|
|
|
elf_fix_shdrs(head, shdr); |
|
return (shdr); |
|
} |
|
|
int |
int |
elf_fix_shdrs(Elf_Ehdr *eh, Elf_Shdr *shdr) |
elf_fix_shdrs(Elf_Ehdr *eh, Elf_Shdr *shdr) |
{ |
{ |
|
|
np->n_type |= N_EXT; |
np->n_type |= N_EXT; |
if (np->n_other) |
if (np->n_other) |
np->n_other = toupper(np->n_other); |
np->n_other = toupper(np->n_other); |
|
} |
|
|
|
return (0); |
|
} |
|
|
|
int |
|
elf_size(Elf_Ehdr *head, Elf_Shdr *shdr, |
|
u_long *ptext, u_long *pdata, u_long *pbss) |
|
{ |
|
int i; |
|
|
|
*ptext = *pdata = *pbss = 0; |
|
|
|
for (i = 0; i < head->e_shnum; i++) { |
|
if (!(shdr[i].sh_flags & SHF_ALLOC)) |
|
; |
|
else if (shdr[i].sh_flags & SHF_EXECINSTR || |
|
!(shdr[i].sh_flags & SHF_WRITE)) |
|
*ptext += shdr[i].sh_size; |
|
else if (shdr[i].sh_type == SHT_NOBITS) |
|
*pbss += shdr[i].sh_size; |
|
else |
|
*pdata += shdr[i].sh_size; |
|
} |
|
|
|
return (0); |
|
} |
|
|
|
int |
|
elf_symload(const char *name, FILE *fp, off_t foff, Elf_Ehdr *eh, |
|
Elf_Shdr *shdr, struct nlist **pnames, struct nlist ***psnames, |
|
size_t *pstabsize, int *pnrawnames) |
|
{ |
|
long symsize, shstrsize; |
|
struct nlist *np; |
|
Elf_Sym sbuf; |
|
char *shstr; |
|
int i; |
|
|
|
shstrsize = shdr[eh->e_shstrndx].sh_size; |
|
if ((shstr = malloc(shstrsize)) == NULL) { |
|
warn("%s: malloc shsrt", name); |
|
return (1); |
|
} |
|
|
|
if (fseeko(fp, foff + shdr[eh->e_shstrndx].sh_offset, SEEK_SET)) { |
|
warn("%s: fseeko", name); |
|
free(shstr); |
|
return (1); |
|
} |
|
|
|
if (fread(shstr, 1, shstrsize, fp) != shstrsize) { |
|
warnx("%s: premature EOF", name); |
|
free(shstr); |
|
return(1); |
|
} |
|
|
|
stab = NULL; |
|
*pnames = NULL; *psnames = NULL; |
|
for (i = 0; i < eh->e_shnum; i++) { |
|
if (!strcmp(shstr + shdr[i].sh_name, ELF_STRTAB)) { |
|
*pstabsize = shdr[i].sh_size; |
|
if (*pstabsize > SIZE_T_MAX) { |
|
warnx("%s: corrupt file", name); |
|
free(shstr); |
|
return (1); |
|
} |
|
|
|
MMAP(stab, *pstabsize, PROT_READ, MAP_PRIVATE|MAP_FILE, |
|
fileno(fp), foff + shdr[i].sh_offset); |
|
if (stab == MAP_FAILED) { |
|
free(shstr); |
|
return (1); |
|
} |
|
} |
|
} |
|
for (i = 0; i < eh->e_shnum; i++) { |
|
if (!strcmp(shstr + shdr[i].sh_name, ELF_SYMTAB)) { |
|
symsize = shdr[i].sh_size; |
|
if (fseeko(fp, foff + shdr[i].sh_offset, SEEK_SET)) { |
|
warn("%s: fseeko", name); |
|
if (stab) |
|
MUNMAP(stab, *pstabsize); |
|
free(shstr); |
|
return (1); |
|
} |
|
|
|
*pnrawnames = symsize / sizeof(sbuf); |
|
if ((*pnames = calloc(*pnrawnames, sizeof(*np))) == NULL) { |
|
warn("%s: malloc names", name); |
|
if (stab) |
|
MUNMAP(stab, *pstabsize); |
|
free(*pnames); |
|
free(shstr); |
|
return (1); |
|
} |
|
if ((*psnames = malloc(*pnrawnames * sizeof(np))) == NULL) { |
|
warn("%s: malloc snames", name); |
|
if (stab) |
|
MUNMAP(stab, *pstabsize); |
|
free(shstr); |
|
free(*pnames); |
|
free(*psnames); |
|
return (1); |
|
} |
|
|
|
for (np = *pnames; symsize > 0; symsize -= sizeof(sbuf)) { |
|
if (fread(&sbuf, 1, sizeof(sbuf), |
|
fp) != sizeof(sbuf)) { |
|
warn("%s: read symbol", name); |
|
if (stab) |
|
MUNMAP(stab, *pstabsize); |
|
free(shstr); |
|
free(*pnames); |
|
free(*psnames); |
|
return (1); |
|
} |
|
|
|
elf_fix_sym(eh, &sbuf); |
|
|
|
if (!sbuf.st_name) |
|
continue; |
|
|
|
elf2nlist(&sbuf, eh, shdr, shstr, np); |
|
np->n_value = sbuf.st_value; |
|
np->n_un.n_strx = sbuf.st_name; |
|
np++; |
|
} |
|
*pnrawnames = np - *pnames; |
|
} |
|
} |
|
|
|
free(shstr); |
|
if (stab == NULL) { |
|
warnx("%s: no name list", name); |
|
if (*pnames) |
|
free(*pnames); |
|
if (*psnames) |
|
free(*psnames); |
|
return (1); |
} |
} |
|
|
return (0); |
return (0); |