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