1 /* stab-elf.c
2  *
3  * $Id$
4  *
5  * Copyright 1990, 1991, 1992, 1993, 1994, 1995, Oliver Laumann, Berlin
6  * Copyright 2002, 2003 Sam Hocevar <sam@hocevar.net>, Paris
7  *
8  * This software was derived from Elk 1.2, which was Copyright 1987, 1988,
9  * 1989, Nixdorf Computer AG and TELES GmbH, Berlin (Elk 1.2 has been written
10  * by Oliver Laumann for TELES Telematic Services, Berlin, in a joint project
11  * between TELES and Nixdorf Microprocessor Engineering, Berlin).
12  *
13  * Oliver Laumann, TELES GmbH, Nixdorf Computer AG and Sam Hocevar, as co-
14  * owners or individual owners of copyright in this software, grant to any
15  * person or company a worldwide, royalty free, license to
16  *
17  *    i) copy this software,
18  *   ii) prepare derivative works based on this software,
19  *  iii) distribute copies of this software or derivative works,
20  *   iv) perform this software, or
21  *    v) display this software,
22  *
23  * provided that this notice is not removed and that neither Oliver Laumann
24  * nor Teles nor Nixdorf are deemed to have made any representations as to
25  * the suitability of this software for any purpose nor are held responsible
26  * for any defects of this software.
27  *
28  * THERE IS ABSOLUTELY NO WARRANTY FOR THIS SOFTWARE.
29  */
30 
31 #include "config.h"
32 
33 #include <sys/types.h>
34 #include <sys/stat.h>
35 #include <fcntl.h>
36 #include <libelf.h>
37 #include <unistd.h>
38 #include <string.h>
39 
40 #include "kernel.h"
41 
42 extern void Free_Symbols (SYMTAB *);
43 
44 SYMTAB *
Snarf_Symbols(int lf)45 Snarf_Symbols (int lf)
46 {
47     SYMTAB      *tab = NULL;
48     register SYM *sp, **nextp;
49     Elf         *elf_ptr;
50     Elf_Scn     *elf_scn_ptr = NULL, *symtab_scn_ptr = NULL;
51     Elf_Data    *elf_data_ptr = NULL;
52     Elf32_Ehdr  *elf_ehdr_ptr = NULL;
53     Elf32_Shdr  *elf_shdr_ptr = NULL,
54                 *symtab_ptr = NULL;
55     size_t      elf_str_index = 0, shstrndx;
56     char        *section_name;
57 
58     if (elf_version (EV_CURRENT) == EV_NONE)
59       Primitive_Error ("a.out file Elf version out of date");
60     if ((elf_ptr = elf_begin (lf, ELF_C_READ, (Elf *)NULL)) == NULL)
61       Primitive_Error ("can't elf_begin() a.out file");
62 
63     /*
64      * get the elf header, so we'll know where to look for the section
65      * names.
66      */
67     if ((elf_ehdr_ptr = elf32_getehdr (elf_ptr)) == NULL) {
68         Primitive_Error ("no elf header in a.out file");
69     }
70     shstrndx = elf_ehdr_ptr->e_shstrndx;
71     /* look for the symbol and string tables */
72     while ((elf_scn_ptr = elf_nextscn (elf_ptr, elf_scn_ptr))) {
73         if ((elf_shdr_ptr = elf32_getshdr (elf_scn_ptr)) == NULL)
74           Primitive_Error ("can't get section header in a.out file");
75         if (elf_shdr_ptr->sh_type == SHT_STRTAB) {
76             /*
77              * save the index to the string table for later use by
78              * elf_strptr().
79              */
80             section_name = elf_strptr (elf_ptr, shstrndx,
81                                       (size_t)elf_shdr_ptr->sh_name);
82             if (strcmp (section_name, ".strtab") == 0 ||
83                     strcmp (section_name, ".dynstr") == 0) {
84                 elf_str_index = elf_ndxscn (elf_scn_ptr);
85             }
86         }
87         else if (elf_shdr_ptr->sh_type == SHT_SYMTAB ||
88                  elf_shdr_ptr->sh_type == SHT_DYNSYM) {
89             symtab_ptr = elf_shdr_ptr;
90             symtab_scn_ptr = elf_scn_ptr;
91         }
92     }
93     if (!symtab_ptr)
94       Primitive_Error ("no symbol table in a.out file");
95     if (!elf_str_index)
96       Primitive_Error ("no string table in a.out file");
97     /*
98      * we've located the symbol table -- go through it and save the names
99      * of the interesting symbols.
100      */
101     while ((elf_data_ptr = elf_getdata (symtab_scn_ptr, elf_data_ptr))) {
102         char *name = NULL;
103         unsigned int symbol_count;
104         Elf32_Sym *symbol_ptr = elf_data_ptr->d_buf;
105         Elf32_Sym *current_symbol;
106 
107         tab = (SYMTAB *)Safe_Malloc (sizeof (SYMTAB));
108         tab->first = 0;
109         tab->strings = 0;
110         nextp = &tab->first;
111         for (symbol_count = 1;
112              /* < was <= in the version I received from the author, but
113               * the last entry is always undefined:
114               */
115              symbol_count < symtab_ptr->sh_size / symtab_ptr->sh_entsize;
116              symbol_count++) {
117             current_symbol = symbol_ptr + symbol_count;
118             if (ELF32_ST_TYPE(current_symbol->st_info) != STT_FUNC ||
119                 ELF32_ST_BIND(current_symbol->st_info) != STB_GLOBAL) {
120                 continue;
121             }
122             if ((name = elf_strptr (elf_ptr, elf_str_index,
123                                    (size_t)current_symbol->st_name)) == NULL) {
124                 Free_Symbols (tab);
125                 (void)close (lf);
126                 Primitive_Error (elf_errmsg (elf_errno ()));
127             }
128             sp = (SYM *)Safe_Malloc (sizeof (SYM));
129             sp->name = Safe_Malloc (strlen (name) + 1);
130             strcpy (sp->name, name);
131             sp->value = current_symbol->st_value;
132             *nextp = sp;
133             nextp = &sp->next;
134             *nextp = 0;
135         }
136     }
137     return tab;
138 }
139 
140 SYMTAB *
Open_File_And_Snarf_Symbols(name)141 Open_File_And_Snarf_Symbols (name)
142      char *name;
143 {
144     int         f;
145     SYMTAB      *tab;
146 
147     if ((f = open (name, O_RDONLY)) == -1)
148         Primitive_Error ("can't open a.out file");
149     tab = Snarf_Symbols (f);
150     (void)close (f);
151     return tab;
152 }
153 
154