xref: /third_party/elfutils/tests/asm-tst3.c (revision da0c48c4)
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
31static const char fname[] = "asm-tst3-out.o";
32
33
34static const char *scnnames[5] =
35  {
36    [0] = "",
37    [1] = ".data",
38    [2] = ".strtab",
39    [3] = ".symtab",
40    [4] = ".shstrtab"
41  };
42
43
44static 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
54int
55main (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