asm-tst1.c revision cc6695e2684ce93cdf8bd2da63d55d2cf49ff076
1/* Copyright (C) 2002, 2005 Red Hat, Inc.
2   This file is part of Red Hat elfutils.
3   Written by Ulrich Drepper <drepper@redhat.com>, 2002.
4
5   Red Hat elfutils is free software; you can redistribute it and/or modify
6   it under the terms of the GNU General Public License as published by the
7   Free Software Foundation; version 2 of the License.
8
9   Red Hat elfutils is distributed in the hope that it will be useful, but
10   WITHOUT ANY WARRANTY; without even the implied warranty of
11   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12   General Public License for more details.
13
14   You should have received a copy of the GNU General Public License along
15   with Red Hat elfutils; if not, write to the Free Software Foundation,
16   Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA.
17
18   Red Hat elfutils is an included package of the Open Invention Network.
19   An included package of the Open Invention Network is a package for which
20   Open Invention Network licensees cross-license their patents.  No patent
21   license is granted, either expressly or impliedly, by designation as an
22   included package.  Should you wish to participate in the Open Invention
23   Network licensing program, please visit www.openinventionnetwork.com
24   <http://www.openinventionnetwork.com>.  */
25
26#ifdef HAVE_CONFIG_H
27# include <config.h>
28#endif
29
30#include <fcntl.h>
31#include ELFUTILS_HEADER(asm)
32#include <libelf.h>
33#include <stdio.h>
34#include <string.h>
35#include <unistd.h>
36
37
38static const char fname[] = "asm-tst1-out.o";
39
40
41static const GElf_Ehdr expected_ehdr =
42  {
43    .e_ident = { [EI_MAG0] = ELFMAG0,
44		 [EI_MAG1] = ELFMAG1,
45		 [EI_MAG2] = ELFMAG2,
46		 [EI_MAG3] = ELFMAG3,
47		 [EI_CLASS] = ELFCLASS32,
48		 [EI_DATA] = ELFDATA2LSB,
49		 [EI_VERSION] = EV_CURRENT },
50    .e_type = ET_REL,
51    .e_machine = EM_386,
52    .e_version = EV_CURRENT,
53    .e_shoff = 88,
54    .e_ehsize = sizeof (Elf32_Ehdr),
55    .e_shentsize = sizeof (Elf32_Shdr),
56    .e_shnum = 4,
57    .e_shstrndx = 3
58  };
59
60
61static const char *scnnames[4] =
62  {
63    [0] = "",
64    [1] = ".text",
65    [2] = ".data",
66    [3] = ".shstrtab"
67  };
68
69
70int
71main (void)
72{
73  AsmCtx_t *ctx;
74  AsmScn_t *scn1;
75  AsmScn_t *scn2;
76  int fd;
77  Elf *elf;
78  GElf_Ehdr ehdr_mem;
79  GElf_Ehdr *ehdr;
80  int result = 0;
81  size_t cnt;
82
83  elf_version (EV_CURRENT);
84
85  Ebl *ebl = ebl_openbackend_machine (EM_386);
86  if (ebl == NULL)
87    {
88      puts ("cannot open backend library");
89      return 1;
90    }
91
92  ctx = asm_begin (fname, ebl, false);
93  if (ctx == NULL)
94    {
95      printf ("cannot create assembler context: %s\n", asm_errmsg (-1));
96      return 1;
97    }
98
99  /* Create two sections.  */
100  scn1 = asm_newscn (ctx, ".text", SHT_PROGBITS, SHF_ALLOC | SHF_EXECINSTR);
101  scn2 = asm_newscn (ctx, ".data", SHT_PROGBITS, SHF_ALLOC | SHF_WRITE);
102  if (scn1 == NULL || scn2 == NULL)
103    {
104      printf ("cannot create section in output file: %s\n", asm_errmsg (-1));
105      asm_abort (ctx);
106      return 1;
107    }
108
109  /* Special alignment for the .text section.  */
110  if (asm_align (scn1, 32) != 0)
111    {
112      printf ("cannot align .text section: %s\n", asm_errmsg (-1));
113      result = 1;
114    }
115
116  /* Create the output file.  */
117  if (asm_end (ctx) != 0)
118    {
119      printf ("cannot create output file: %s\n", asm_errmsg (-1));
120      asm_abort (ctx);
121      return 1;
122    }
123
124  /* Check the file.  */
125  fd = open (fname, O_RDONLY);
126  if (fd == -1)
127    {
128      printf ("cannot open generated file: %m\n");
129      result = 1;
130      goto out;
131    }
132
133  elf = elf_begin (fd, ELF_C_READ, NULL);
134  if (elf == NULL)
135    {
136      printf ("cannot create ELF descriptor: %s\n", elf_errmsg (-1));
137      result = 1;
138      goto out_close;
139    }
140  if (elf_kind (elf) != ELF_K_ELF)
141    {
142      puts ("not a valid ELF file");
143      result = 1;
144      goto out_close2;
145    }
146
147  ehdr = gelf_getehdr (elf, &ehdr_mem);
148  if (ehdr == NULL)
149    {
150      printf ("cannot get ELF header: %s\n", elf_errmsg (-1));
151      result = 1;
152      goto out_close2;
153    }
154
155  if (memcmp (ehdr, &expected_ehdr, sizeof (GElf_Ehdr)) != 0)
156    {
157      puts ("ELF header does not match");
158      result = 1;
159      goto out_close2;
160    }
161
162  for (cnt = 1; cnt < 4; ++cnt)
163    {
164      Elf_Scn *scn;
165      GElf_Shdr shdr_mem;
166      GElf_Shdr *shdr;
167
168      scn = elf_getscn (elf, cnt);
169      if (scn == NULL)
170	{
171	  printf ("cannot get section %Zd: %s\n", cnt, elf_errmsg (-1));
172	  result = 1;
173	  continue;
174	}
175
176      shdr = gelf_getshdr (scn, &shdr_mem);
177      if (shdr == NULL)
178	{
179	  printf ("cannot get section header for section %Zd: %s\n",
180		  cnt, elf_errmsg (-1));
181	  result = 1;
182	  continue;
183	}
184
185      if (strcmp (elf_strptr (elf, ehdr->e_shstrndx, shdr->sh_name),
186		  scnnames[cnt]) != 0)
187	{
188	  printf ("section %Zd's name differs: %s vs %s\n", cnt,
189		  elf_strptr (elf, ehdr->e_shstrndx, shdr->sh_name),
190		  scnnames[cnt]);
191	  result = 1;
192	}
193
194      if (shdr->sh_type != (cnt == 3 ? SHT_STRTAB : SHT_PROGBITS))
195	{
196	  printf ("section %Zd's type differs\n", cnt);
197	  result = 1;
198	}
199
200      if ((cnt == 1 && shdr->sh_flags != (SHF_ALLOC | SHF_EXECINSTR))
201	  || (cnt == 2 && shdr->sh_flags != (SHF_ALLOC | SHF_WRITE))
202	  || (cnt == 3 && shdr->sh_flags != 0))
203	{
204	  printf ("section %Zd's flags differs\n", cnt);
205	  result = 1;
206	}
207
208      if (shdr->sh_addr != 0)
209	{
210	  printf ("section %Zd's address differs\n", cnt);
211	  result = 1;
212	}
213
214      if (shdr->sh_offset != ((sizeof (Elf32_Ehdr) + 31) & ~31))
215	{
216	  printf ("section %Zd's offset differs\n", cnt);
217	  result = 1;
218	}
219
220      if ((cnt != 3 && shdr->sh_size != 0)
221	  || (cnt == 3 && shdr->sh_size != 23))
222	{
223	  printf ("section %Zd's size differs\n", cnt);
224	  result = 1;
225	}
226
227      if (shdr->sh_link != 0)
228	{
229	  printf ("section %Zd's link differs\n", cnt);
230	  result = 1;
231	}
232
233      if (shdr->sh_info != 0)
234	{
235	  printf ("section %Zd's info differs\n", cnt);
236	  result = 1;
237	}
238
239      if ((cnt == 1 && shdr->sh_addralign != 32)
240	  || (cnt != 1 && shdr->sh_addralign != 1))
241	{
242	  printf ("section %Zd's addralign differs\n", cnt);
243	  result = 1;
244	}
245
246      if (shdr->sh_entsize != 0)
247	{
248	  printf ("section %Zd's entsize differs\n", cnt);
249	  result = 1;
250	}
251    }
252
253 out_close2:
254  elf_end (elf);
255 out_close:
256  close (fd);
257 out:
258  /* We don't need the file anymore.  */
259  unlink (fname);
260
261  ebl_closebackend (ebl);
262
263  return result;
264}
265