1 /* Copyright (C) 2002, 2005 Red Hat, Inc.
2 This file is part of elfutils.
3 Written by Ulrich Drepper <drepper@redhat.com>, 2002.
4
5 This file is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 3 of the License, or
8 (at your option) any later version.
9
10 elfutils is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>. */
17
18 #ifdef HAVE_CONFIG_H
19 # include <config.h>
20 #endif
21
22 #include <fcntl.h>
23 #include ELFUTILS_HEADER(asm)
24 #include ELFUTILS_HEADER(ebl)
25 #include <libelf.h>
26 #include <stdio.h>
27 #include <string.h>
28 #include <unistd.h>
29
30
31 static const char fname[] = "asm-tst3-out.o";
32
33
34 static const char *scnnames[5] =
35 {
36 [0] = "",
37 [1] = ".data",
38 [2] = ".strtab",
39 [3] = ".symtab",
40 [4] = ".shstrtab"
41 };
42
43
44 static unsigned int scntypes[5] =
45 {
46 [0] = SHT_NULL,
47 [1] = SHT_PROGBITS,
48 [2] = SHT_STRTAB,
49 [3] = SHT_SYMTAB,
50 [4] = SHT_STRTAB
51 };
52
53
54 int
main(void)55 main (void)
56 {
57 AsmCtx_t *ctx;
58 AsmScn_t *scn1;
59 AsmScn_t *scn2;
60 int result = 0;
61 int fd;
62 Elf *elf;
63 GElf_Ehdr ehdr_mem;
64 GElf_Ehdr *ehdr;
65 size_t cnt;
66
67 elf_version (EV_CURRENT);
68
69 Ebl *ebl = ebl_openbackend_machine (EM_386);
70 if (ebl == NULL)
71 {
72 puts ("cannot open backend library");
73 return 1;
74 }
75
76 ctx = asm_begin (fname, ebl, false);
77 if (ctx == NULL)
78 {
79 printf ("cannot create assembler context: %s\n", asm_errmsg (-1));
80 return 1;
81 }
82
83 /* Create two sections. */
84 scn1 = asm_newscn (ctx, ".data", SHT_PROGBITS, SHF_ALLOC | SHF_WRITE);
85 scn2 = asm_newsubscn (scn1, 1);
86 if (scn1 == NULL || scn2 == NULL)
87 {
88 printf ("cannot create section in output file: %s\n", asm_errmsg (-1));
89 asm_abort (ctx);
90 return 1;
91 }
92
93 /* Special alignment for the .text section. */
94 if (asm_align (scn1, 16) != 0)
95 {
96 printf ("cannot align .text section: %s\n", asm_errmsg (-1));
97 result = 1;
98 }
99
100 /* Add a few strings with names. */
101 if (asm_newsym (scn1, "one", 4, STT_OBJECT, STB_GLOBAL) == NULL)
102 {
103 printf ("cannot create first name: %s\n", asm_errmsg (-1));
104 result = 1;
105 }
106 if (asm_addstrz (scn1, "one", 4) != 0)
107 {
108 printf ("cannot insert first string: %s\n", asm_errmsg (-1));
109 result = 1;
110 }
111 if (asm_newsym (scn2, "three", 6, STT_OBJECT, STB_WEAK) == NULL)
112 {
113 printf ("cannot create second name: %s\n", asm_errmsg (-1));
114 result = 1;
115 }
116 if (asm_addstrz (scn2, "three", 0) != 0)
117 {
118 printf ("cannot insert second string: %s\n", asm_errmsg (-1));
119 result = 1;
120 }
121 if (asm_newsym (scn1, "two", 4, STT_OBJECT, STB_LOCAL) == NULL)
122 {
123 printf ("cannot create third name: %s\n", asm_errmsg (-1));
124 result = 1;
125 }
126 if (asm_addstrz (scn1, "two", 4) != 0)
127 {
128 printf ("cannot insert third string: %s\n", asm_errmsg (-1));
129 result = 1;
130 }
131
132 /* Create the output file. */
133 if (asm_end (ctx) != 0)
134 {
135 printf ("cannot create output file: %s\n", asm_errmsg (-1));
136 asm_abort (ctx);
137 return 1;
138 }
139
140 /* Check the file. */
141 fd = open (fname, O_RDONLY);
142 if (fd == -1)
143 {
144 printf ("cannot open generated file: %m\n");
145 result = 1;
146 goto out;
147 }
148
149 elf = elf_begin (fd, ELF_C_READ, NULL);
150 if (elf == NULL)
151 {
152 printf ("cannot create ELF descriptor: %s\n", elf_errmsg (-1));
153 result = 1;
154 goto out_close;
155 }
156 if (elf_kind (elf) != ELF_K_ELF)
157 {
158 puts ("not a valid ELF file");
159 result = 1;
160 goto out_close2;
161 }
162
163 ehdr = gelf_getehdr (elf, &ehdr_mem);
164 if (ehdr == NULL)
165 {
166 printf ("cannot get ELF header: %s\n", elf_errmsg (-1));
167 result = 1;
168 goto out_close2;
169 }
170
171 for (cnt = 1; cnt < 5; ++cnt)
172 {
173 Elf_Scn *scn;
174 GElf_Shdr shdr_mem;
175 GElf_Shdr *shdr;
176
177 scn = elf_getscn (elf, cnt);
178 if (scn == NULL)
179 {
180 printf ("cannot get section %zd: %s\n", cnt, elf_errmsg (-1));
181 result = 1;
182 continue;
183 }
184
185 shdr = gelf_getshdr (scn, &shdr_mem);
186 if (shdr == NULL)
187 {
188 printf ("cannot get section header for section %zd: %s\n",
189 cnt, elf_errmsg (-1));
190 result = 1;
191 continue;
192 }
193
194 if (strcmp (elf_strptr (elf, ehdr->e_shstrndx, shdr->sh_name),
195 scnnames[cnt]) != 0)
196 {
197 printf ("section %zd's name differs: %s vs %s\n", cnt,
198 elf_strptr (elf, ehdr->e_shstrndx, shdr->sh_name),
199 scnnames[cnt]);
200 result = 1;
201 }
202
203 if (shdr->sh_type != scntypes[cnt])
204 {
205 printf ("section %zd's type differs\n", cnt);
206 result = 1;
207 }
208
209 if ((cnt == 1 && shdr->sh_flags != (SHF_ALLOC | SHF_WRITE))
210 || (cnt != 1 && shdr->sh_flags != 0))
211 {
212 printf ("section %zd's flags differs\n", cnt);
213 result = 1;
214 }
215
216 if (shdr->sh_addr != 0)
217 {
218 printf ("section %zd's address differs\n", cnt);
219 result = 1;
220 }
221
222 if (cnt == 3)
223 {
224 Elf_Data *data;
225
226 if (shdr->sh_link != 2)
227 {
228 puts ("symbol table has incorrect link");
229 result = 1;
230 }
231
232 data = elf_getdata (scn, NULL);
233 if (data == NULL)
234 {
235 puts ("cannot get data of symbol table");
236 result = 1;
237 }
238 else
239 {
240 size_t inner;
241
242 for (inner = 1;
243 inner < (shdr->sh_size
244 / gelf_fsize (elf, ELF_T_SYM, 1, EV_CURRENT));
245 ++inner)
246 {
247 GElf_Sym sym_mem;
248 GElf_Sym *sym;
249
250 sym = gelf_getsym (data, inner, &sym_mem);
251 if (sym == NULL)
252 {
253 printf ("cannot get symbol %zu: %s\n",
254 inner, elf_errmsg (-1));
255 result = 1;
256 }
257 else
258 {
259 /* The order of the third and fourth entry depends
260 on how the hash table is organized. */
261 static const char *names[4] =
262 {
263 [0] = "",
264 [1] = "two",
265 [2] = "one",
266 [3] = "three"
267 };
268 static const int info[4] =
269 {
270 [0] = GELF_ST_INFO (STB_LOCAL, STT_NOTYPE),
271 [1] = GELF_ST_INFO (STB_LOCAL, STT_OBJECT),
272 [2] = GELF_ST_INFO (STB_GLOBAL, STT_OBJECT),
273 [3] = GELF_ST_INFO (STB_WEAK, STT_OBJECT)
274 };
275 static const unsigned value[4] =
276 {
277 [0] = 0,
278 [1] = 4,
279 [2] = 0,
280 [3] = 8
281 };
282
283 if (strcmp (names[inner],
284 elf_strptr (elf, shdr->sh_link,
285 sym->st_name)) != 0)
286 {
287 printf ("symbol %zu has different name\n", inner);
288 result = 1;
289 }
290
291 if (sym->st_value != value[inner])
292 {
293 printf ("symbol %zu has wrong value\n", inner);
294 result = 1;
295 }
296
297 if (sym->st_other != 0)
298 {
299 printf ("symbol %zu has wrong other info\n", inner);
300 result = 1;
301 }
302
303 if (sym->st_shndx != 1)
304 {
305 printf ("symbol %zu has wrong section reference\n",
306 inner);
307 result = 1;
308 }
309
310 if (sym->st_info != info[inner])
311 {
312 printf ("symbol %zu has wrong type or binding\n",
313 inner);
314 result = 1;
315 }
316
317 if ((inner != 3 && sym->st_size != 4)
318 || (inner == 3 && sym->st_size != 6))
319 {
320 printf ("symbol %zu has wrong size\n", inner);
321 result = 1;
322 }
323 }
324 }
325 }
326 }
327 }
328
329 out_close2:
330 elf_end (elf);
331 out_close:
332 close (fd);
333 out:
334 /* We don't need the file anymore. */
335 unlink (fname);
336
337 ebl_closebackend (ebl);
338
339 return result;
340 }
341