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 <inttypes.h>
32#include ELFUTILS_HEADER(asm)
33#include <libelf.h>
34#include <stdio.h>
35#include <string.h>
36#include <unistd.h>
37
38
39static const char fname[] = "asm-tst9-out.o";
40
41
42static int32_t input[] =
43  {
44    0, 1, 129, 510, 2000, 33000, 0x7ffffff, 0x7fffffff
45  };
46#define ninput (sizeof (input) / sizeof (input[0]))
47
48
49static const GElf_Ehdr expected_ehdr =
50  {
51    .e_ident = { [EI_MAG0] = ELFMAG0,
52		 [EI_MAG1] = ELFMAG1,
53		 [EI_MAG2] = ELFMAG2,
54		 [EI_MAG3] = ELFMAG3,
55		 [EI_CLASS] = ELFCLASS32,
56		 [EI_DATA] = ELFDATA2LSB,
57		 [EI_VERSION] = EV_CURRENT },
58    .e_type = ET_REL,
59    .e_machine = EM_386,
60    .e_version = EV_CURRENT,
61    .e_shoff = 180,
62    .e_ehsize = sizeof (Elf32_Ehdr),
63    .e_shentsize = sizeof (Elf32_Shdr),
64    .e_shnum = 3,
65    .e_shstrndx = 2
66  };
67
68
69static const char *scnnames[3] =
70  {
71    [0] = "",
72    [1] = ".data",
73    [2] = ".shstrtab"
74  };
75
76
77static const char expecteddata[] =
78  {
79    0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0xff, 0xff, 0xff, 0xff, 0x0f, 0x7f,
80    0x81, 0x01, 0x81, 0x01, 0xff, 0xfe, 0xff, 0xff, 0x0f, 0xff, 0x7e, 0xfe,
81    0x03, 0xfe, 0x03, 0x82, 0xfc, 0xff, 0xff, 0x0f, 0x82, 0x7c, 0xd0, 0x0f,
82    0xd0, 0x0f, 0xb0, 0xf0, 0xff, 0xff, 0x0f, 0xb0, 0x70, 0xe8, 0x81, 0x02,
83    0xe8, 0x81, 0x02, 0x98, 0xfe, 0xfd, 0xff, 0x0f, 0x98, 0xfe, 0x7d, 0xff,
84    0xff, 0xff, 0x3f, 0xff, 0xff, 0xff, 0x3f, 0x81, 0x80, 0x80, 0xc0, 0x0f,
85    0x81, 0x80, 0x80, 0x40, 0xff, 0xff, 0xff, 0xff, 0x07, 0xff, 0xff, 0xff,
86    0xff, 0x07, 0x81, 0x80, 0x80, 0x80, 0x08, 0x81, 0x80, 0x80, 0x80, 0x78
87  };
88
89
90int
91main (void)
92{
93  AsmCtx_t *ctx;
94  AsmScn_t *scn;
95  int result = 0;
96  int fd;
97  Elf *elf;
98  GElf_Ehdr ehdr_mem;
99  GElf_Ehdr *ehdr;
100  size_t cnt;
101
102  elf_version (EV_CURRENT);
103
104  Ebl *ebl = ebl_openbackend_machine (EM_386);
105  if (ebl == NULL)
106    {
107      puts ("cannot open backend library");
108      return 1;
109    }
110
111  ctx = asm_begin (fname, ebl, false);
112  if (ctx == NULL)
113    {
114      printf ("cannot create assembler context: %s\n", asm_errmsg (-1));
115      return 1;
116    }
117
118  /* Create two sections.  */
119  scn = asm_newscn (ctx, ".data", SHT_PROGBITS, SHF_ALLOC | SHF_WRITE);
120  if (scn == NULL)
121    {
122      printf ("cannot create section in output file: %s\n", asm_errmsg (-1));
123      asm_abort (ctx);
124      return 1;
125    }
126
127  /* Special alignment for the .text section.  */
128  if (asm_align (scn, 16) != 0)
129    {
130      printf ("cannot align .text section: %s\n", asm_errmsg (-1));
131      result = 1;
132    }
133
134  /* Add a few ULEB128 and SLEB128 numbers.  */
135  for (cnt = 0; cnt < ninput; ++cnt)
136    {
137      if (asm_adduleb128 (scn, input[cnt]) != 0)
138	{
139	  printf ("cannot insert uleb %" PRIu32 ": %s\n",
140		  (uint32_t) input[cnt], asm_errmsg (-1));
141	  result = 1;
142	}
143
144      if (asm_addsleb128 (scn, input[cnt]) != 0)
145	{
146	  printf ("cannot insert sleb %" PRId32 ": %s\n",
147		  input[cnt], asm_errmsg (-1));
148	  result = 1;
149	}
150
151      if (asm_adduleb128 (scn, -input[cnt]) != 0)
152	{
153	  printf ("cannot insert uleb %" PRIu32 ": %s\n",
154		  (uint32_t) -input[cnt], asm_errmsg (-1));
155	  result = 1;
156	}
157
158      if (asm_addsleb128 (scn, -input[cnt]) != 0)
159	{
160	  printf ("cannot insert sleb %" PRId32 ": %s\n",
161		  -input[cnt], asm_errmsg (-1));
162	  result = 1;
163	}
164    }
165
166  /* Create the output file.  */
167  if (asm_end (ctx) != 0)
168    {
169      printf ("cannot create output file: %s\n", asm_errmsg (-1));
170      asm_abort (ctx);
171      return 1;
172    }
173
174  /* Check the file.  */
175  fd = open (fname, O_RDONLY);
176  if (fd == -1)
177    {
178      printf ("cannot open generated file: %m\n");
179      result = 1;
180      goto out;
181    }
182
183  elf = elf_begin (fd, ELF_C_READ, NULL);
184  if (elf == NULL)
185    {
186      printf ("cannot create ELF descriptor: %s\n", elf_errmsg (-1));
187      result = 1;
188      goto out_close;
189    }
190  if (elf_kind (elf) != ELF_K_ELF)
191    {
192      puts ("not a valid ELF file");
193      result = 1;
194      goto out_close2;
195    }
196
197  ehdr = gelf_getehdr (elf, &ehdr_mem);
198  if (ehdr == NULL)
199    {
200      printf ("cannot get ELF header: %s\n", elf_errmsg (-1));
201      result = 1;
202      goto out_close2;
203    }
204
205  if (memcmp (ehdr, &expected_ehdr, sizeof (GElf_Ehdr)) != 0)
206    {
207      puts ("ELF header does not match");
208      result = 1;
209      goto out_close2;
210    }
211
212  for (cnt = 1; cnt < 3; ++cnt)
213    {
214      Elf_Scn *scn;
215      GElf_Shdr shdr_mem;
216      GElf_Shdr *shdr;
217
218      scn = elf_getscn (elf, cnt);
219      if (scn == NULL)
220	{
221	  printf ("cannot get section %Zd: %s\n", cnt, elf_errmsg (-1));
222	  result = 1;
223	  continue;
224	}
225
226      shdr = gelf_getshdr (scn, &shdr_mem);
227      if (shdr == NULL)
228	{
229	  printf ("cannot get section header for section %Zd: %s\n",
230		  cnt, elf_errmsg (-1));
231	  result = 1;
232	  continue;
233	}
234
235      if (strcmp (elf_strptr (elf, ehdr->e_shstrndx, shdr->sh_name),
236		  scnnames[cnt]) != 0)
237	{
238	  printf ("section %Zd's name differs: %s vs %s\n", cnt,
239		  elf_strptr (elf, ehdr->e_shstrndx, shdr->sh_name),
240		  scnnames[cnt]);
241	  result = 1;
242	}
243
244      if (shdr->sh_type != (cnt == 2 ? SHT_STRTAB : SHT_PROGBITS))
245	{
246	  printf ("section %Zd's type differs\n", cnt);
247	  result = 1;
248	}
249
250      if ((cnt == 1 && shdr->sh_flags != (SHF_ALLOC | SHF_WRITE))
251	  || (cnt == 2 && shdr->sh_flags != 0))
252	{
253	  printf ("section %Zd's flags differs\n", cnt);
254	  result = 1;
255	}
256
257      if (shdr->sh_addr != 0)
258	{
259	  printf ("section %Zd's address differs\n", cnt);
260	  result = 1;
261	}
262
263      if ((cnt == 1 && shdr->sh_offset != ((sizeof (Elf32_Ehdr) + 15) & ~15))
264	  || (cnt == 2
265	      && shdr->sh_offset != (((sizeof (Elf32_Ehdr) + 15) & ~15)
266				     + sizeof (expecteddata))))
267	{
268	  printf ("section %Zd's offset differs\n", cnt);
269	  result = 1;
270	}
271
272      if ((cnt == 1 && shdr->sh_size != sizeof (expecteddata))
273	  || (cnt == 2 && shdr->sh_size != 17))
274	{
275	  printf ("section %Zd's size differs\n", cnt);
276	  result = 1;
277	}
278
279      if (shdr->sh_link != 0)
280	{
281	  printf ("section %Zd's link differs\n", cnt);
282	  result = 1;
283	}
284
285      if (shdr->sh_info != 0)
286	{
287	  printf ("section %Zd's info differs\n", cnt);
288	  result = 1;
289	}
290
291      if ((cnt == 1 && shdr->sh_addralign != 16)
292	  || (cnt != 1 && shdr->sh_addralign != 1))
293	{
294	  printf ("section %Zd's addralign differs\n", cnt);
295	  result = 1;
296	}
297
298      if (shdr->sh_entsize != 0)
299	{
300	  printf ("section %Zd's entsize differs\n", cnt);
301	  result = 1;
302	}
303
304      if (cnt == 1)
305	{
306	  Elf_Data *data = elf_getdata (scn, NULL);
307
308	  if (data == NULL)
309	    {
310	      printf ("cannot get data of section %Zd\n", cnt);
311	      result = 1;
312	    }
313	  else
314	    {
315	      if (data->d_size != sizeof (expecteddata))
316		{
317		  printf ("data block size of section %Zd wrong: got %Zd, "
318			  "expected 96\n", cnt, data->d_size);
319		  result = 1;
320		}
321
322	      if (memcmp (data->d_buf, expecteddata, sizeof (expecteddata))
323		  != 0)
324		{
325		  printf ("data block content of section %Zd wrong\n", cnt);
326		  result = 1;
327		}
328	    }
329	}
330    }
331
332 out_close2:
333  elf_end (elf);
334 out_close:
335  close (fd);
336 out:
337  /* We don't need the file anymore.  */
338  unlink (fname);
339
340  ebl_closebackend (ebl);
341
342  return result;
343}
344