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-tst2-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 = 96,
54    .e_ehsize = sizeof (Elf32_Ehdr),
55    .e_shentsize = sizeof (Elf32_Shdr),
56    .e_shnum = 3,
57    .e_shstrndx = 2
58  };
59
60
61static const char *scnnames[3] =
62  {
63    [0] = "",
64    [1] = ".data",
65    [2] = ".shstrtab"
66  };
67
68
69int
70main (void)
71{
72  AsmCtx_t *ctx;
73  AsmScn_t *scn1;
74  AsmScn_t *scn2;
75  int result = 0;
76  int fd;
77  Elf *elf;
78  GElf_Ehdr ehdr_mem;
79  GElf_Ehdr *ehdr;
80  size_t cnt;
81
82  elf_version (EV_CURRENT);
83
84  Ebl *ebl = ebl_openbackend_machine (EM_386);
85  if (ebl == NULL)
86    {
87      puts ("cannot open backend library");
88      return 1;
89    }
90
91  ctx = asm_begin (fname, ebl, false);
92  if (ctx == NULL)
93    {
94      printf ("cannot create assembler context: %s\n", asm_errmsg (-1));
95      return 1;
96    }
97
98  /* Create two sections.  */
99  scn1 = asm_newscn (ctx, ".data", SHT_PROGBITS, SHF_ALLOC | SHF_WRITE);
100  scn2 = asm_newsubscn (scn1, 1);
101  if (scn1 == NULL || scn2 == NULL)
102    {
103      printf ("cannot create section in output file: %s\n", asm_errmsg (-1));
104      asm_abort (ctx);
105      return 1;
106    }
107
108  /* Special alignment for the .text section.  */
109  if (asm_align (scn1, 16) != 0)
110    {
111      printf ("cannot align .text section: %s\n", asm_errmsg (-1));
112      result = 1;
113    }
114
115  /* Add a few strings.  */
116  if (asm_addstrz (scn1, "one", 4) != 0)
117    {
118      printf ("cannot insert first string: %s\n", asm_errmsg (-1));
119      result = 1;
120    }
121  if (asm_addstrz (scn2, "three", 0) != 0)
122    {
123      printf ("cannot insert second string: %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  if (memcmp (ehdr, &expected_ehdr, sizeof (GElf_Ehdr)) != 0)
172    {
173      puts ("ELF header does not match");
174      result = 1;
175      goto out_close2;
176    }
177
178  for (cnt = 1; cnt < 3; ++cnt)
179    {
180      Elf_Scn *scn;
181      GElf_Shdr shdr_mem;
182      GElf_Shdr *shdr;
183
184      scn = elf_getscn (elf, cnt);
185      if (scn == NULL)
186	{
187	  printf ("cannot get section %Zd: %s\n", cnt, elf_errmsg (-1));
188	  result = 1;
189	  continue;
190	}
191
192      shdr = gelf_getshdr (scn, &shdr_mem);
193      if (shdr == NULL)
194	{
195	  printf ("cannot get section header for section %Zd: %s\n",
196		  cnt, elf_errmsg (-1));
197	  result = 1;
198	  continue;
199	}
200
201      if (strcmp (elf_strptr (elf, ehdr->e_shstrndx, shdr->sh_name),
202		  scnnames[cnt]) != 0)
203	{
204	  printf ("section %Zd's name differs: %s vs %s\n", cnt,
205		  elf_strptr (elf, ehdr->e_shstrndx, shdr->sh_name),
206		  scnnames[cnt]);
207	  result = 1;
208	}
209
210      if (shdr->sh_type != (cnt == 2 ? SHT_STRTAB : SHT_PROGBITS))
211	{
212	  printf ("section %Zd's type differs\n", cnt);
213	  result = 1;
214	}
215
216      if ((cnt == 1 && shdr->sh_flags != (SHF_ALLOC | SHF_WRITE))
217	  || (cnt == 2 && shdr->sh_flags != 0))
218	{
219	  printf ("section %Zd's flags differs\n", cnt);
220	  result = 1;
221	}
222
223      if (shdr->sh_addr != 0)
224	{
225	  printf ("section %Zd's address differs\n", cnt);
226	  result = 1;
227	}
228
229      if ((cnt == 1 && shdr->sh_offset != ((sizeof (Elf32_Ehdr) + 15) & ~15))
230	  || (cnt == 2
231	      && shdr->sh_offset != (((sizeof (Elf32_Ehdr) + 15) & ~15)
232				     + strlen ("one") + 1
233				     + strlen ("two") + 1
234				     + strlen ("three") + 1)))
235	{
236	  printf ("section %Zd's offset differs\n", cnt);
237	  result = 1;
238	}
239
240      if ((cnt == 1 && shdr->sh_size != (strlen ("one") + 1
241					 + strlen ("two") + 1
242					 + strlen ("three") + 1))
243	  || (cnt == 2 && shdr->sh_size != 17))
244	{
245	  printf ("section %Zd's size differs\n", cnt);
246	  result = 1;
247	}
248
249      if (shdr->sh_link != 0)
250	{
251	  printf ("section %Zd's link differs\n", cnt);
252	  result = 1;
253	}
254
255      if (shdr->sh_info != 0)
256	{
257	  printf ("section %Zd's info differs\n", cnt);
258	  result = 1;
259	}
260
261      if ((cnt == 1 && shdr->sh_addralign != 16)
262	  || (cnt != 1 && shdr->sh_addralign != 1))
263	{
264	  printf ("section %Zd's addralign differs\n", cnt);
265	  result = 1;
266	}
267
268      if (shdr->sh_entsize != 0)
269	{
270	  printf ("section %Zd's entsize differs\n", cnt);
271	  result = 1;
272	}
273    }
274
275 out_close2:
276  elf_end (elf);
277 out_close:
278  close (fd);
279 out:
280  /* We don't need the file anymore.  */
281  unlink (fname);
282
283  ebl_closebackend (ebl);
284
285  return result;
286}
287