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