void vfree(void *mem) { assert(0); }
size_t strncpy_from_user(char *addr, const char *user_name, size_t size)
-{ assert(0); }
+{ assert(0); return 0; }
/* void lock_kernel(void) { assert(0); } */
/* void unlock_kernel(void) { assert(0); } */
/* void __asm__(char *str) { assert(0); } */
extern void *__vmalloc(unsigned long size, int gfp_mask, pgprot_t prot)
-{ assert(0); }
+{ assert(0); return NULL; }
#if 0
void kallsyms_sections(void *infop,
#endif
unsigned long __generic_copy_to_user(void *x, const void *y, unsigned long z)
-{ assert(0); }
+{ assert(0); return -1; }
unsigned long __generic_copy_from_user(void *x, const void *y, unsigned long z)
-{ assert(0); }
+{ assert(0); return -1; }
/* void read_lock(struct lock *lock) { assert(0); } */
/* void read_unlock(struct lock *lock) { assert(0); } */
const char * *sec_name, unsigned long *sec_start, unsigned long *sec_end,
const char * *sym_name, unsigned long *sym_start, unsigned long *sym_end)
{
- static char name[sizeof(((struct nlist *)0)->n_name)+1];
+ static char name[64];
int i;
unsigned long btext, etext;
below= above= NULL;
for (i= 0; i<exe_nlist_n; i++)
{
- if ((exe_nlist[i].n_sclass & N_SECT) != N_TEXT)
+ if (exe_nlist[i].n_type != N_TEXT)
continue;
if (exe_nlist[i].n_value <= off)
{
#if 0
if (below)
{
- printf("found '%.*s' at 0x%x\n", sizeof(below->n_name),
- below->n_name, below->n_value);
+ printf("found '%s' at 0x%x\n", below->n_name, below->n_value);
}
if (above)
{
- printf("found '%.*s' at 0x%x\n", sizeof(above->n_name),
- above->n_name, above->n_value);
+ printf("found '%s' at 0x%x\n", above->n_name, above->n_value);
}
#endif
assert(below && above);
- memcpy(name, below->n_name, sizeof(below->n_name));
- name[sizeof(below->n_name)]= '\0';
+ strncpy(name, below->n_name, sizeof(name)-1);
+ name[sizeof(name)-1]= '\0';
*sym_name= name;
*sym_start= below->n_value | TRAP_BIT;
if (v < 0)
{
fprintf(stderr,
- "text_read_ub: trace T_READB_INS failed on pid %d, addr 0x%x: %s\n",
+ "text_read_ub: trace T_READB_INS failed on pid %d, addr 0x%lx: %s\n",
victim_pid, vaddr, strerror(errno));
exit(1);
}
if (v < 0)
{
fprintf(stderr,
- "text_read_ub: trace T_WRITEB_INS failed on pid %d, addr 0x%x: %s\n",
+ "text_read_ub: trace T_WRITEB_INS failed on pid %d, addr 0x%lx: %s\n",
victim_pid, vaddr, strerror(errno));
exit(1);
}
btext= (unsigned long)-1;
for (i= 0; i<exe_nlist_n; i++)
{
- if ((exe_nlist[i].n_sclass & N_SECT) != N_TEXT)
+ if (exe_nlist[i].n_type != N_TEXT)
continue;
if (exe_nlist[i].n_value < btext)
btext= exe_nlist[i].n_value;
if (btext >= etext)
{
- fprintf(stderr, "Bad btext (0x%x) or etext (0x%x) in %d\n",
+ fprintf(stderr, "Bad btext (0x%lx) or etext (0x%lx) in %s\n",
btext, etext, exe_name);
exit(1);
}
-/*
-read_nlist.c
-
-Read the symbol table of an executable into memory.
-
-Created: Mar 6, 1992 by Philip Homburg
-*/
-
-#include <sys/types.h>
-#include <assert.h>
-#include <a.out.h>
-#include <errno.h>
-#include <fcntl.h>
+/* ELF functions-only symbol table extractor by David van Moolenbroek.
+ * Replaces generic a.out version by Philip Homburg.
+ * Temporary solution until libc's nlist(3) becomes usable.
+ */
#include <stdlib.h>
+#include <stdio.h>
#include <string.h>
#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <libelf.h>
+#include <nlist.h>
-#include "extra.h"
-
-#define USE_OLD_NLIST 1
-
-static u16_t le16 _ARGS(( u16_t *word_p ));
-static u32_t le32 _ARGS(( u32_t *word_p ));
-static u16_t be16 _ARGS(( u16_t *word_p ));
-static u32_t be32 _ARGS(( u32_t *word_p ));
-
-static u16_t le16(word_p)
-u16_t *word_p;
-{
- return (((u8_t *)word_p)[0] << 0) | (((u8_t *)word_p)[1] << 8);
-}
-
-static u16_t be16(word_p)
-u16_t *word_p;
-{
- return (((u8_t *)word_p)[1] << 0) | (((u8_t *)word_p)[0] << 8);
-}
-
-static u32_t le32(dword_p)
-u32_t *dword_p;
+static int get_syms(Elf *elf, Elf_Scn *scn, Elf32_Shdr *shdr,
+ struct nlist **nlistp)
{
- return le16(&((u16_t *)dword_p)[0]) |
- ((u32_t)le16(&((u16_t *)dword_p)[1]) << 16);
-}
+ Elf_Data *data;
+ Elf32_Sym *sym;
+ unsigned long nsyms;
+ struct nlist *nlp;
+ char *name;
+ size_t size;
+ int i;
+
+ if ((data = elf_getdata(scn, NULL)) == NULL) {
+ errno = ENOEXEC;
+ return -1;
+ }
-static u32_t be32(dword_p)
-u32_t *dword_p;
-{
- return be16(&((u16_t *)dword_p)[1]) |
- ((u32_t)be16(&((u16_t *)dword_p)[0]) << 16);
-}
+ nsyms = data->d_size / sizeof(Elf32_Sym);
-#ifndef USE_OLD_NLIST
-struct old_nlist
-{
- char n_name[8];
- long n_value;
- unsigned char n_sclass;
- unsigned char n_numaux;
- unsigned char n_type;
-};
+ size = sizeof(struct nlist) * nsyms;
+ if ((*nlistp = nlp = malloc(size)) == NULL)
+ return -1;
+ memset(nlp, 0, size);
+
+ sym = (Elf32_Sym *) data->d_buf;
+ for (i = 0; i < nsyms; i++, sym++, nlp++) {
+ nlp->n_value = sym->st_value;
+
+ /* The caller only cares about N_TEXT. Properly setting other
+ * types would involve crosschecking with section types.
+ */
+ switch (ELF32_ST_TYPE(sym->st_info)) {
+ case STT_FUNC: nlp->n_type = N_TEXT; break;
+ default: nlp->n_type = N_UNDF; break;
+ }
-/* Low bits of storage class (section). */
-#define O_N_SECT 07 /* section mask */
-#define O_N_UNDF 00 /* undefined */
-#define O_N_ABS 01 /* absolute */
-#define O_N_TEXT 02 /* text */
-#define O_N_DATA 03 /* data */
-#define O_N_BSS 04 /* bss */
-#define O_N_COMM 05 /* (common) */
+ name = elf_strptr(elf, shdr->sh_link, (size_t) sym->st_name);
+ if ((nlp->n_name = strdup(name ? name : "")) == NULL) {
+ free(*nlistp);
+ return -1;
+ }
+ }
-/* High bits of storage class. */
-#define O_N_CLASS 0370 /* storage class mask */
-#define O_C_NULL
-#define O_C_EXT 0020 /* external symbol */
-#define O_C_STAT 0030 /* static */
-#endif
+ return nsyms;
+}
-int read_nlist(filename, nlist_table)
-const char *filename;
-struct nlist **nlist_table;
+int read_nlist(const char *filename, struct nlist **nlist_table)
{
- int r, n_entries, save_err;
- u32_t (*cnv32) _ARGS(( u32_t *addr ));
- u16_t (*cnv16) _ARGS(( u16_t *addr ));
- struct nlist *nlist_p, *nlist_ptr;
- int exec_fd;
- struct exec exec_header;
-#ifndef USE_OLD_NLIST
- struct old_nlist *old_nlist, *old_nlist_p;
- void *old_nlist_end;
-#endif
- char *str_tab, *str_base, *str_null;
- u32_t string_siz;
-
- exec_fd= open(filename, O_RDONLY);
- if (exec_fd == -1) /* No executable present */
- {
+ /* Read in the symbol table of 'filename'. Return the resulting symbols
+ * as an array, with 'nlist_table' set to point to it, and the number
+ * of elements as the return value. The caller has no way to free the
+ * results. Return 0 if the executable contains no symbols. Upon error,
+ * return -1 and set errno to an appropriate value.
+ */
+ Elf *elf;
+ Elf_Scn *scn;
+ Elf32_Shdr *shdr;
+ int res, fd;
+
+ if (elf_version(EV_CURRENT) == EV_NONE) {
+ errno = EINVAL;
return -1;
}
- r= read(exec_fd, (char *)&exec_header, A_MINHDR);
- if (r != A_MINHDR)
- {
- if (r != -1)
- errno= ENOEXEC;
+ if ((fd = open(filename, O_RDONLY)) < 0)
return -1;
- }
- if (BADMAG(exec_header))
- {
- errno= ENOEXEC;
- return -1;
- }
- switch(exec_header.a_cpu & 3)
- {
- case 0: /* little endian */
- cnv32= le32;
- cnv16= le16;
- break;
- case 3: /* big endian */
- cnv32= be32;
- cnv16= be16;
- break;
- default:
- errno= ENOEXEC;
- return -1;
- }
- exec_header.a_version= cnv16((u16_t *)&exec_header.a_version);
- exec_header.a_text= cnv32((u32_t *)&exec_header.a_text);
- exec_header.a_data= cnv32((u32_t *)&exec_header.a_data);
- exec_header.a_bss= cnv32((u32_t *)&exec_header.a_bss);
- exec_header.a_entry= cnv32((u32_t *)&exec_header.a_entry);
- exec_header.a_total= cnv32((u32_t *)&exec_header.a_total);
- exec_header.a_syms= cnv32((u32_t *)&exec_header.a_syms);
- exec_header.a_trsize= cnv32((u32_t *)&exec_header.a_trsize);
- exec_header.a_drsize= cnv32((u32_t *)&exec_header.a_drsize);
- exec_header.a_tbase= cnv32((u32_t *)&exec_header.a_tbase);
- exec_header.a_dbase= cnv32((u32_t *)&exec_header.a_dbase);
- if (!exec_header.a_syms)
- return 0;
-
- if (exec_header.a_flags & A_NSYM)
- {
-#if USE_OLD_NLIST
- errno= EINVAL;
+ elf = elf_begin(fd, ELF_C_READ, NULL);
+ if (elf == NULL) {
+ errno = ENOEXEC;
+ close(fd);
return -1;
-#else
- r= lseek(exec_fd, A_SYMPOS(exec_header)+exec_header.a_syms,
- SEEK_SET);
- if (r == -1)
- {
- return -1;
- }
- r= read(exec_fd, (char *)&string_siz, 4);
- if (r != 4)
- return -1;
- string_siz= cnv32(&string_siz)-4;
- nlist_p= malloc(exec_header.a_syms + string_siz+1);
- if (!nlist_p)
- {
- errno= ENOMEM;
- return -1;
- }
- r= lseek(exec_fd, A_SYMPOS(exec_header)+exec_header.a_syms+4,
- SEEK_SET);
- if (r == -1)
- {
- save_err= errno;
- free(nlist_p);
- errno= save_err;
- return -1;
- }
- r= read(exec_fd, ((char *)nlist_p)+exec_header.a_syms,
- string_siz);
- if (r != string_siz)
- {
- save_err= errno;
- free(nlist_p);
- errno= save_err;
- return -1;
- }
- r= lseek(exec_fd, A_SYMPOS(exec_header), SEEK_SET);
- if (r == -1)
- {
- save_err= errno;
- free(nlist_p);
- errno= save_err;
- return -1;
- }
- r= read(exec_fd, ((char *)nlist_p), exec_header.a_syms);
- if (r != exec_header.a_syms)
- {
- save_err= errno;
- free(nlist_p);
- errno= save_err;
- return -1;
- }
- str_base= ((char *)nlist_p) + exec_header.a_syms -4;
- str_null= (char *)nlist_p + exec_header.a_syms + string_siz;
- *str_null= '\0';
- for (nlist_ptr= nlist_p; (char *)nlist_ptr+1 <= str_base+4;
- nlist_ptr++)
- {
- nlist_ptr->n_desc= le16((u16_t *)&nlist_ptr->n_desc);
- nlist_ptr->n_value= le32(&nlist_ptr->n_value);
- if (nlist_ptr->n_un.n_strx)
- nlist_ptr->n_un.n_name= str_base+
- cnv32((u32_t *)&nlist_ptr->n_un.n_strx);
- else
- nlist_ptr->n_un.n_name= str_null;
- }
- *nlist_table= nlist_p;
- return nlist_ptr-nlist_p;
-#endif
}
- else
- {
- r= lseek(exec_fd, A_SYMPOS(exec_header), SEEK_SET);
- if (r == -1)
- {
- return -1;
- }
-
-#if USE_OLD_NLIST
- n_entries= exec_header.a_syms/sizeof(struct nlist);
- nlist_p= malloc(exec_header.a_syms);
- if (!nlist_p)
- {
- free(nlist_p);
- errno= ENOMEM;
- return -1;
- }
- r= read(exec_fd, (char *)nlist_p, exec_header.a_syms);
- if (r != exec_header.a_syms)
- {
- save_err= errno;
- free(nlist_p);
- errno= save_err;
- return -1;
- }
- *nlist_table= nlist_p;
- return n_entries;
-#else
- n_entries= exec_header.a_syms/sizeof(struct old_nlist)+1;
- nlist_p= NULL;
- old_nlist= NULL;
+ scn = NULL;
+ res = 0;
+ while ((scn = elf_nextscn(elf, scn)) != NULL) {
+ if ((shdr = elf32_getshdr(scn)) == NULL)
+ continue;
- nlist_p= malloc(n_entries * (sizeof(struct nlist)+
- sizeof(old_nlist->n_name)+1));
- old_nlist= malloc(exec_header.a_syms);
- if (!old_nlist || !nlist_p)
- {
- if (nlist_p)
- free(nlist_p);
- if (old_nlist)
- free(old_nlist);
- errno= ENOMEM;
- return -1;
- }
- r= read(exec_fd, (char *)old_nlist, exec_header.a_syms);
- if (r != exec_header.a_syms)
- {
- save_err= errno;
- free(nlist_p);
- free(old_nlist);
- errno= save_err;
- return -1;
- }
+ if (shdr->sh_type != SHT_SYMTAB)
+ continue;
- old_nlist_end= (char *)old_nlist+exec_header.a_syms;
- str_tab= (char *)&nlist_p[n_entries];
- n_entries= 0;
- for (old_nlist_p= old_nlist;
- (void *)(old_nlist_p+1)<=old_nlist_end; old_nlist_p++)
- {
- switch(old_nlist_p->n_sclass & O_N_SECT)
- {
- case O_N_UNDF:
- nlist_p[n_entries].n_type= N_UNDF;
- break;
- case O_N_ABS:
- nlist_p[n_entries].n_type= N_ABS;
- break;
- case O_N_TEXT:
- nlist_p[n_entries].n_type= N_TEXT;
- break;
- case O_N_DATA:
- nlist_p[n_entries].n_type= N_DATA;
- break;
- case O_N_BSS:
- nlist_p[n_entries].n_type= N_BSS;
- break;
- case O_N_COMM:
- nlist_p[n_entries].n_type= N_COMM;
- break;
- default:
- continue;
- }
- switch(old_nlist_p->n_sclass & O_N_CLASS)
- {
- case O_C_EXT:
- nlist_p[n_entries].n_type |= N_EXT;
- case O_C_STAT:
- break;
- default:
- continue;
- }
- nlist_p[n_entries].n_value=
- cnv32((u32_t *)&old_nlist_p->n_value);
- nlist_p[n_entries].n_un.n_name= str_tab;
- memcpy(str_tab, old_nlist_p->n_name,
- sizeof(old_nlist_p->n_name));
- str_tab += sizeof(old_nlist_p->n_name);
- *str_tab++= '\0';
- n_entries++;
- }
- free(old_nlist);
- nlist_p= realloc(nlist_p, str_tab-(char *)nlist_p);
- *nlist_table= nlist_p;
- return n_entries;
-#endif
+ res = get_syms(elf, scn, shdr, nlist_table);
+ break;
}
-}
-/*
- * $PchId: read_nlist.c,v 1.5 1996/04/11 07:47:38 philip Exp $
- */
+ elf_end(elf);
+ close(fd);
+
+ return res;
+}