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