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